1
0

ps2ascii.ps 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524
  1. % Copyright (C) 1991, 1995, 1996, 1998, 1999 Aladdin Enterprises. All rights reserved.
  2. %
  3. % This software is provided AS-IS with no warranty, either express or
  4. % implied.
  5. %
  6. % This software is distributed under license and may not be copied,
  7. % modified or distributed except as expressly authorized under the terms
  8. % of the license contained in the file LICENSE in this distribution.
  9. %
  10. % For more information about licensing, please refer to
  11. % http://www.ghostscript.com/licensing/. For information on
  12. % commercial licensing, go to http://www.artifex.com/licensing/ or
  13. % contact Artifex Software, Inc., 101 Lucas Valley Road #110,
  14. % San Rafael, CA 94903, U.S.A., +1(415)492-9861.
  15. % $Id: ps2ascii.ps,v 1.10 2004/06/23 09:04:17 igor Exp $
  16. % Extract the ASCII text from a PostScript file. Nothing is displayed.
  17. % Instead, ASCII information is written to stdout. The idea is similar to
  18. % Glenn Reid's `distillery', only a lot more simple-minded, and less robust.
  19. % If SIMPLE is defined, just the text is written, with a guess at line
  20. % breaks and word spacing. If SIMPLE is not defined, lines are written
  21. % to stdout as follows:
  22. %
  23. % F <height> <width> (<fontname>)
  24. % Indicate the font height and the width of a space.
  25. %
  26. % P
  27. % Indicate the end of the page.
  28. %
  29. % S <x> <y> (<string>) <width>
  30. % Display a string.
  31. %
  32. % <width> and <height> are integer dimensions in units of 1/720".
  33. % <x> and <y> are integer coordinates, in units of 1/720", with the origin
  34. % at the lower left.
  35. % <string> and <fontname> are strings represented with the standard
  36. % PostScript escape conventions.
  37. % If COMPLEX is defined, the following additional types of lines are
  38. % written to stdout.
  39. %
  40. % C <r> <g> <b>
  41. % Indicate the current color.
  42. %
  43. % I <x> <y> <width> <height>
  44. % Note the presence of an image.
  45. %
  46. % R <x> <y> <width> <height>
  47. % Fill a rectangle.
  48. %
  49. % <r>, <g>, and <b> are RGB values expressed as integers between 0 and 1000.
  50. %
  51. % Note that future versions of this program (in COMPLEX mode) may add
  52. % other output elements, so programs parsing the output should be
  53. % prepared to ignore elements that they do not recognize.
  54. % Note that this code will only work in all cases if systemdict is writable
  55. % and if `binding' the definitions of operators defined as procedures
  56. % is deferred. For this reason, it is normally invoked with
  57. % gs -q -dNODISPLAY -dDELAYBIND -dWRITESYSTEMDICT ps2ascii.ps
  58. % Thanks to:
  59. % J Greely <jgreely@cis.ohio-state.edu> for improvements to this code;
  60. % Jerry Whelan <jerryw@abode.ccd.bnl.gov> for motivating other improvements;
  61. % David M. Jones <dmjones@theory.lcs.mit.edu> for improvements noted below.
  62. %% Additional modifications by David M. Jones
  63. %% (dmjones@theory.lcs.mit.edu), December 23, 1997
  64. %%
  65. %% (a) Rewrote forall loop at the end of .show.write. This fixes a
  66. %% stack leakage problem, but the changes are more significant
  67. %% than that.
  68. %%
  69. %% .char.map includes the names of all characters in the
  70. %% StandardEncoding, ISOLatin1Encoding, OT1Encoding and
  71. %% T1Encoding vectors. Thus, if the Encoding vector for the
  72. %% current font contains a name that is not in .char.map, it's
  73. %% redundant to check if the Encoding vector is equal to one of
  74. %% the known vectors. Previous versions of ps2ascii would give
  75. %% up at this point, and substitute an asterisk (*) for the
  76. %% character. I've taken the liberty of instead using the
  77. %% OT1Encoding vector to translate the character, on the grounds
  78. %% that in the cases I'm most interested in, a font without a
  79. %% useful Encoding vector was most likely created by a DVI to PS
  80. %% converter such as dvips or DVILASER (and OT1Encoding is
  81. %% largely compatible with StandardEncoding anyway). [Note that
  82. %% this does not make my earlier changes to support dvips (see
  83. %% fix (a) under my 1996 changes) completely obsolete, since
  84. %% there's additional useful information I can extract in that
  85. %% case.]
  86. %%
  87. %% Overall, this should provide better support for some documents
  88. %% (e.g, DVILASER documents will no longer be translated into a
  89. %% series of *'s) without breaking any other documents any worse
  90. %% than they already were broken.
  91. %%
  92. %% (b) Fixed two bugs in dvips.df-tail: (1) changed "dup 127" to "dup
  93. %% 128" to fix fencepost error, and (2) gave each font it's own
  94. %% FontName rather than having all fonts share the same name.
  95. %%
  96. %% (c) Added one further refinement to the heuristic for detecting
  97. %% paragraph breaks: do not ever start a new paragraph after a
  98. %% line ending in a hyphen.
  99. %%
  100. %% (d) Added a bunch of missing letters from the T1Encoding,
  101. %% OT1Encoding and ISOLatin1Encoding vectors to .letter.chars to
  102. %% improve hyphen-elimination algorithm. This still won't help
  103. %% if there's no useful Encoding vector.
  104. %%
  105. %% NOTE: A better solution to the problem of missing Encoding vectors
  106. %% might be to redefine definefont to check whether the Encoding
  107. %% vector is sensible and, if not, replace it by a default. This
  108. %% would alleviate the need for constant tests in the .show.write
  109. %% loop, as well as automatically solving the problem noted in fix
  110. %% (d) above, and the similar problem with .break.chars. This should
  111. %% be investigated. Also, the hyphen-elimination algorithm really
  112. %% needs to be looked at carefully and rethought.
  113. %%* Modifications to ps2ascii.ps by David M. Jones
  114. %%* (dmjones@theory.lcs.mit.edu), June 25-July 8, 1996
  115. %%* Modifications:
  116. %%*
  117. %%* (a) added code to give better support for dvips files by providing
  118. %%* FontBBox's, FontName's and Encoding vectors for downloaded
  119. %%* bitmap fonts. This is done by using dvips's start-hook to
  120. %%* overwrite the df-tail and D procedures that dvips uses to
  121. %%* define its Type 3 bitmap fonts. Thus, this change should
  122. %%* provide better support for dvips-generated PS files without
  123. %%* affecting the handling of other documents.
  124. %%*
  125. %%* (b) Fixed two bugs that could potentially affect any PS file, not
  126. %%* just those created by dvips: (1) added missing "get" operator
  127. %%* in .show.write and (2) fixed bug that caused a hyphen at the
  128. %%* end of a line to be replaced by a space rather than begin
  129. %%* deleted. Note that the first bug was a source of stack
  130. %%* leakage, causing ps2ascii to run out of operand stack space
  131. %%* occasionally.
  132. %%*
  133. %%* Search for "%%* BF" to find these modifications.
  134. %%*
  135. %%* (c) Improved the heuristic for determining whether a line break
  136. %%* has occurred and whether a line break represents a paragraph
  137. %%* break. Previously, any change in the vertical position caused
  138. %%* a line break; now a line break is only registered if the
  139. %%* change is larger than the height of the current font. This
  140. %%* means that superscripts, subscripts, and such things as
  141. %%* shifted accents generated by TeX won't cause line breaks.
  142. %%* Paragraph-recognition is now done by comparing the indentation
  143. %%* of the new line to the indentation of the previous line and by
  144. %%* comparing the vertical distance between the new line and the
  145. %%* previous line to the vertical distance between the previous
  146. %%* line and its predecessor.
  147. %%*
  148. %%* (d) Added a hook for renaming the files where stdout and stderr
  149. %%* go.
  150. %%*
  151. %%* In general, my additions or changes to the code are described in
  152. %%* comments beginning with "%%*". However, there are numerous other
  153. %%* places where I have either re-formatted code or added comments to
  154. %%* the code while I was trying to understand it. These are usually
  155. %%* not specially marked.
  156. %%*
  157. /QUIET true def
  158. systemdict wcheck { systemdict } { userdict } ifelse begin
  159. /.max where { pop } { /.max { 2 copy lt { exch } if pop } bind def } ifelse
  160. /COMPLEX dup where { pop true } { false } ifelse def
  161. /SIMPLE dup where { pop true } { false } ifelse def
  162. /setglobal where
  163. { pop currentglobal /setglobal load true setglobal }
  164. { { } }
  165. ifelse
  166. % Define a way to store and retrieve integers that survives save/restore.
  167. /.i.string0 (0 ) def
  168. /.i.string .i.string0 length string def
  169. /.iget { cvi } bind def
  170. /.iput { exch //.i.string exch copy cvs pop } bind def
  171. /.inew { //.i.string0 dup length string copy } bind def
  172. % We only want to redefine operators if they are defined already.
  173. /codef { 1 index where { pop def } { pop pop } ifelse } def
  174. % Redefine the end-of-page operators.
  175. /erasepage { } codef
  176. /copypage { SIMPLE { (\014) } { (P\n) } ifelse //print } codef
  177. /showpage { copypage erasepage initgraphics } codef
  178. % Redefine the fill operators to detect rectangles.
  179. /.orderrect % <llx> <lly> <urx> <ury> .orderrect <llx> <lly> <w> <h>
  180. { % Ensure llx <= urx, lly <= ury.
  181. 1 index 4 index lt { 4 2 roll } if
  182. dup 3 index lt { 3 1 roll exch } if
  183. exch 3 index sub exch 2 index sub
  184. } odef
  185. /.fillcomplex
  186. { % Do a first pass to see if the path is all rectangles in
  187. % the output coordinate system. We don't worry about overlapping
  188. % rectangles that might be partially not filled.
  189. % Stack: mark llx0 lly0 urx0 ury0 ... true mark x0 y0 ...
  190. mark true mark
  191. % Add a final moveto so we pick up any trailing unclosed subpath.
  192. 0 0 itransform moveto
  193. { .coord counttomark 2 gt
  194. { counttomark 4 gt { .fillcheckrect } { 4 2 roll pop pop } ifelse }
  195. if
  196. }
  197. { .coord }
  198. { cleartomark not mark exit }
  199. { counttomark -2 roll 2 copy counttomark 2 roll .fillcheckrect }
  200. pathforall cleartomark
  201. { .showcolor counttomark 4 idiv
  202. { counttomark -4 roll .orderrect
  203. (R ) //print .show==4
  204. }
  205. repeat pop
  206. }
  207. { cleartomark
  208. }
  209. ifelse
  210. } odef
  211. /.fillcheckrect
  212. { % Check whether the current subpath is a rectangle.
  213. % If it is, add it to the list of rectangles being accumulated;
  214. % if not exit the .fillcomplex loop.
  215. % The subpath has not been closed.
  216. % Stack: as in .fillcomplex, + newx newy
  217. counttomark 10 eq { 9 index 9 index 4 2 roll } if
  218. counttomark 12 ne { cleartomark not mark exit } if
  219. 12 2 roll
  220. % Check for the two possible forms of rectangles:
  221. % x0 y0 x0 y1 x1 y1 x1 y0 x0 y0
  222. % x0 y0 x1 y0 x1 y1 x0 y1 x0 y0
  223. 9 index 2 index eq 9 index 2 index eq and
  224. 10 index 9 index eq
  225. { % Check for first form.
  226. 7 index 6 index eq and 6 index 5 index eq and 3 index 2 index eq and
  227. }
  228. { % Check for second form.
  229. 9 index 8 index eq and
  230. 8 index 7 index eq and 5 index 4 index eq and 4 index 3 index eq and
  231. }
  232. ifelse not { cleartomark not mark exit } if
  233. % We have a rectangle.
  234. pop pop pop pop 4 2 roll pop pop 8 4 roll
  235. } odef
  236. /eofill { COMPLEX { .fillcomplex } if newpath } codef
  237. /fill { COMPLEX { .fillcomplex } if newpath } codef
  238. /rectfill { gsave newpath .rectappend fill grestore } codef
  239. /ueofill { gsave newpath uappend eofill grestore } codef
  240. /ufill { gsave newpath uappend fill grestore } codef
  241. % Redefine the stroke operators to detect rectangles.
  242. /rectstroke
  243. { gsave newpath
  244. dup type dup /arraytype eq exch /packedarraytype eq or
  245. { dup length 6 eq { exch .rectappend concat } { .rectappend } ifelse }
  246. { .rectappend }
  247. ifelse stroke grestore
  248. } codef
  249. /.strokeline % <fromx> <fromy> <tox> <toy> .strokeline <tox> <toy>
  250. % Note: fromx and fromy are in output coordinates;
  251. % tox and toy are in user coordinates.
  252. { .coord 2 copy 6 2 roll .orderrect
  253. % Add in the line width. Assume square or round caps.
  254. currentlinewidth 2 div dup .dcoord add abs 1 .max 5 1 roll
  255. 4 index add 4 1 roll 4 index add 4 1 roll
  256. 4 index sub 4 1 roll 5 -1 roll sub 4 1 roll
  257. (R ) //print .show==4
  258. } odef
  259. /.strokecomplex
  260. { % Do a first pass to see if the path is all horizontal and vertical
  261. % lines in the output coordinate system.
  262. % Stack: true mark origx origy curx cury
  263. true mark null null null null
  264. { .coord 6 2 roll pop pop pop pop 2 copy }
  265. { .coord 1 index 4 index eq 1 index 4 index eq or
  266. { 4 2 roll pop pop }
  267. { cleartomark not mark exit }
  268. ifelse
  269. }
  270. { cleartomark not mark exit }
  271. { counttomark -2 roll 2 copy counttomark 2 roll
  272. 1 index 4 index eq 1 index 4 index eq or
  273. { pop pop 2 copy }
  274. { cleartomark not mark exit }
  275. ifelse
  276. }
  277. pathforall cleartomark
  278. 0 currentlinewidth .dcoord 0 eq exch 0 eq or and
  279. % Do the second pass to write out the rectangles.
  280. % Stack: origx origy curx cury
  281. { .showcolor null null null null
  282. { 6 2 roll pop pop pop pop 2 copy .coord }
  283. { .strokeline }
  284. { }
  285. { 3 index 3 index .strokeline }
  286. pathforall pop pop pop pop
  287. }
  288. if
  289. } odef
  290. /stroke { COMPLEX { .strokecomplex } if newpath } codef
  291. /ustroke
  292. { gsave newpath
  293. dup length 6 eq { exch uappend concat } { uappend } ifelse
  294. stroke grestore
  295. } codef
  296. % The image operators must read the input and note the dimensions.
  297. % Eventually we should redefine these to detect 1-bit-high all-black images,
  298. % since this is how dvips does underlining (!).
  299. /.noteimagerect % <width> <height> <matrix> .noteimagerect -
  300. { COMPLEX
  301. { gsave setmatrix itransform 0 0 itransform
  302. grestore .coord 4 2 roll .coord .orderrect
  303. (I ) //print .show==4
  304. }
  305. { pop pop pop
  306. }
  307. ifelse
  308. } odef
  309. /colorimage where
  310. { pop /colorimage
  311. { 1 index
  312. { dup 6 add index 1 index 6 add index 2 index 5 add index }
  313. { 6 index 6 index 5 index }
  314. ifelse .noteimagerect gsave nulldevice //colorimage grestore
  315. } codef
  316. } if
  317. /.noteimage % Arguments as for image[mask]
  318. { dup type /dicttype eq
  319. { dup /Width get 1 index /Height get 2 index /ImageMatrix get }
  320. { 4 index 4 index 3 index }
  321. ifelse .noteimagerect
  322. } odef
  323. /image { .noteimage gsave nulldevice //image grestore } codef
  324. /imagemask { .noteimage gsave nulldevice //imagemask grestore } codef
  325. % Output the current color if necessary.
  326. /.color.r .inew def
  327. .color.r -1 .iput % make sure we write the color at the beginning
  328. /.color.g .inew def
  329. /.color.b .inew def
  330. /.showcolor
  331. { COMPLEX
  332. { currentrgbcolor
  333. 1000 mul round cvi
  334. 3 1 roll 1000 mul round cvi
  335. exch 1000 mul round cvi
  336. % Stack: b g r
  337. dup //.color.r .iget eq
  338. 2 index //.color.g .iget eq and
  339. 3 index //.color.b .iget eq and
  340. { pop pop pop
  341. }
  342. { (C ) //print
  343. dup //.color.r exch .iput .show==only
  344. ( ) //print dup //.color.g exch .iput .show==only
  345. ( ) //print dup //.color.b exch .iput .show==only
  346. (\n) //print
  347. }
  348. ifelse
  349. }
  350. if
  351. } bind def
  352. % Redefine `show'.
  353. % Set things up so our output will be in tenths of a point, with origin at
  354. % lower left. This isolates us from the peculiarities of individual devices.
  355. /.show.ident.matrix matrix def
  356. /.show.ident { % - .show.ident <scale> <matrix>
  357. % //.show.ident.matrix defaultmatrix
  358. % % Assume the original transformation is well-behaved.
  359. % 0.1 0 2 index dtransform abs exch abs .max /.show.scale exch def
  360. % 0.1 dup 3 -1 roll scale
  361. gsave initmatrix
  362. % Assume the original transformation is well-behaved...
  363. 0.1 0 dtransform abs exch abs .max
  364. 0.1 dup scale .show.ident.matrix currentmatrix
  365. % ... but undo any rotation into landscape orientation.
  366. dup 0 get 0 eq {
  367. 1 get dup abs div 90 mul rotate
  368. .show.ident.matrix currentmatrix
  369. } if
  370. grestore
  371. } bind def
  372. /.coord { % <x> <y> .coord <x'> <y'>
  373. transform .show.ident exch pop itransform
  374. exch round cvi exch round cvi
  375. } odef
  376. /.dcoord { % <dx> <dy> .coord <dx'> <dy'>
  377. % Transforming distances is trickier, because
  378. % the coordinate system might be rotated.
  379. .show.ident pop 3 1 roll
  380. exch 0 dtransform
  381. dup mul exch dup mul add sqrt
  382. 2 index div round cvi
  383. exch 0 exch dtransform
  384. dup mul exch dup mul add sqrt
  385. 3 -1 roll div round cvi
  386. } odef
  387. % Remember the current X, Y, and height.
  388. /.show.x .inew def
  389. /.show.y .inew def
  390. /.show.height .inew def
  391. % Remember the last character of the previous string; if it was a
  392. % hyphen preceded by a letter, we didn't output the hyphen.
  393. /.show.last (\000) def
  394. % Remember the current font.
  395. /.font.name 130 string def
  396. /.font.name.length .inew def
  397. /.font.height .inew def
  398. /.font.width .inew def
  399. %%* Also remember indentation of current line and previous vertical
  400. %%* skip
  401. /.show.indent .inew def
  402. /.show.dy .inew def
  403. % We have to redirect stdout somehow....
  404. /.show.stdout { (%stdout) (w) file } bind def
  405. % Make sure writing will work even if a program uses =string.
  406. /.show.string =string length string def
  407. /.show.=string =string length string def
  408. /.show==only
  409. { //=string //.show.=string copy pop
  410. dup type /stringtype eq
  411. { dup length //.show.string length le
  412. { dup rcheck { //.show.string copy } if
  413. } if
  414. } if
  415. .show.stdout exch write==only
  416. //.show.=string //=string copy pop
  417. } odef
  418. /.show==4
  419. { 4 -1 roll .show==only ( ) //print
  420. 3 -1 roll .show==only ( ) //print
  421. exch .show==only ( ) //print
  422. .show==only (\n) //print
  423. } odef
  424. /.showwidth % Same as stringwidth, but disable COMPLEX so that
  425. % we don't try to detect rectangles during BuildChar.
  426. { COMPLEX
  427. { /COMPLEX false def stringwidth /COMPLEX true def }
  428. { stringwidth }
  429. ifelse
  430. } odef
  431. /.showfont % <string> .showfont <string>
  432. { gsave
  433. % Try getting the height and width of the font from the FontBBox.
  434. currentfont /FontBBox .knownget not { {0 0 0 0} } if
  435. aload pop % llx lly urx ury
  436. exch 4 -1 roll % lly ury urx llx
  437. sub % lly ury dx
  438. 3 1 roll exch % dx ury lly
  439. sub % dx dy
  440. 2 copy .max 0 ne
  441. { currentfont /FontMatrix get dtransform
  442. }
  443. { pop pop
  444. % Fonts produced by dvips, among other applications, have
  445. % BuildChar procedures that bomb out when given unexpected
  446. % characters, and there is no way to determine whether a given
  447. % character will do this. So for Type 1 fonts, we measure a
  448. % typical character ('X'); for others, we punt.
  449. currentfont /FontType get 1 eq
  450. { (X) .showwidth pop dup 1.3 mul
  451. }
  452. { % No safe way to get the character size. Punt.
  453. 0 0
  454. }
  455. ifelse
  456. }
  457. ifelse .dcoord exch
  458. currentfont /FontName .knownget not { () } if
  459. dup type /stringtype ne { //.show.string cvs } if
  460. grestore
  461. % Stack: height width fontname
  462. SIMPLE
  463. { pop pop //.show.height exch .iput }
  464. { 2 index //.font.height .iget eq
  465. 2 index //.font.width .iget eq and
  466. 1 index //.font.name 0 //.font.name.length .iget getinterval eq and
  467. { pop pop pop
  468. }
  469. { (F ) //print
  470. 3 -1 roll dup //.font.height exch .iput .show==only ( ) //print
  471. exch dup //.font.width exch .iput .show==only ( ) //print
  472. dup length //.font.name.length exch .iput
  473. //.font.name cvs .show==only (\n) //print
  474. }
  475. ifelse
  476. }
  477. ifelse
  478. } odef
  479. % Define the letters -- characters which, if they occur followed by a hyphen
  480. % at the end of a line, cause the hyphen and line break to be ignored.
  481. /.letter.chars 100 dict def
  482. mark
  483. 65 1 90 { dup 32 add } for
  484. counttomark
  485. { StandardEncoding exch get .letter.chars exch dup put }
  486. repeat
  487. pop
  488. %%* Add the rest of the letters from the [O]T1Encoding and
  489. %%* ISOLatin1Encoding vectors
  490. mark
  491. /AE
  492. /Aacute
  493. /Abreve
  494. /Acircumflex
  495. /Adieresis
  496. /Agrave
  497. /Aogonek
  498. /Aring
  499. /Atilde
  500. /Cacute
  501. /Ccaron
  502. /Ccedilla
  503. /Dcaron
  504. /Eacute
  505. /Ecaron
  506. /Ecircumflex
  507. /Edieresis
  508. /Egrave
  509. /Eng
  510. /Eogonek
  511. /Eth
  512. /Gbreve
  513. /Germandbls
  514. /IJ
  515. /Iacute
  516. /Icircumflex
  517. /Idieresis
  518. /Idot
  519. /Igrave
  520. /Lacute
  521. /Lcaron
  522. /Lslash
  523. /Nacute
  524. /Ncaron
  525. /Ntilde
  526. /OE
  527. /Oacute
  528. /Ocircumflex
  529. /Odieresis
  530. /Ograve
  531. /Ohungarumlaut
  532. /Oslash
  533. /Otilde
  534. /Racute
  535. /Rcaron
  536. /Sacute
  537. /Scaron
  538. /Scedilla
  539. /Tcaron
  540. /Tcedilla
  541. /Thorn
  542. /Uacute
  543. /Ucircumflex
  544. /Udieresis
  545. /Ugrave
  546. /Uhungarumlaut
  547. /Uring
  548. /Yacute
  549. /Ydieresis
  550. /Zacute
  551. /Zcaron
  552. /Zdot
  553. /aacute
  554. /abreve
  555. /acircumflex
  556. /adieresis
  557. /ae
  558. /agrave
  559. /aogonek
  560. /aring
  561. /atilde
  562. /cacute
  563. /ccaron
  564. /ccedilla
  565. /dbar
  566. /dcaron
  567. /dotlessi
  568. /dotlessj
  569. /eacute
  570. /ecaron
  571. /ecircumflex
  572. /edieresis
  573. /egrave
  574. /eng
  575. /eogonek
  576. /eth
  577. /exclamdown
  578. /ff
  579. /ffi
  580. /ffl
  581. /fi
  582. /fl
  583. /gbreve
  584. /germandbls
  585. /iacute
  586. /icircumflex
  587. /idieresis
  588. /igrave
  589. /ij
  590. /lacute
  591. /lcaron
  592. /lslash
  593. /nacute
  594. /ncaron
  595. /ntilde
  596. /oacute
  597. /ocircumflex
  598. /odieresis
  599. /oe
  600. /ograve
  601. /ohungarumlaut
  602. /oslash
  603. /otilde
  604. /questiondown
  605. /racute
  606. /rcaron
  607. /sacute
  608. /scaron
  609. /scedilla
  610. /section
  611. /sterling
  612. /tcaron
  613. /tcedilla
  614. /thorn
  615. /uacute
  616. /ucircumflex
  617. /udieresis
  618. /ugrave
  619. /uhungarumlaut
  620. /uring
  621. /yacute
  622. /ydieresis
  623. /zacute
  624. /zcaron
  625. /zdot
  626. counttomark
  627. { .letter.chars exch dup put }
  628. repeat
  629. pop
  630. % Define a set of characters which, if they occur at the start of a line,
  631. % are taken as indicating a paragraph break.
  632. /.break.chars 50 dict def
  633. mark
  634. /bullet /dagger /daggerdbl /periodcentered /section
  635. counttomark
  636. { .break.chars exch dup put }
  637. repeat
  638. pop
  639. % Define character translation to ASCII.
  640. % We have to do this for the entire character set.
  641. /.char.map 500 dict def
  642. /.chars.def { counttomark 2 idiv { .char.map 3 1 roll put } repeat pop } def
  643. % Encode the printable ASCII characters.
  644. mark 32 1 126
  645. { 1 string dup 0 4 -1 roll put
  646. dup 0 get StandardEncoding exch get exch
  647. }
  648. for .chars.def
  649. % Encode accents.
  650. mark
  651. /acute (')
  652. /caron (^)
  653. /cedilla (,)
  654. /circumflex (^)
  655. /dieresis (")
  656. /grave (`)
  657. /ring (*)
  658. /tilde (~)
  659. .chars.def
  660. % Encode the ISO accented characters.
  661. mark 192 1 255
  662. { ISOLatin1Encoding exch get =string cvs
  663. dup 0 1 getinterval 1 index dup length 1 sub 1 exch getinterval
  664. .char.map 2 index known .char.map 2 index known and
  665. { .char.map 3 -1 roll get .char.map 3 -1 roll get concatstrings
  666. .char.map 3 1 roll put
  667. }
  668. { pop pop pop
  669. }
  670. ifelse
  671. }
  672. for .chars.def
  673. % Encode the remaining standard and ISO alphabetic characters.
  674. mark
  675. /AE (AE) /Eth (DH) /OE (OE) /Thorn (Th)
  676. /ae (ae) /eth (dh)
  677. /ffi (ffi) /ffl (ffl) /fi (fi) /fl (fl)
  678. /germandbls (ss) /oe (oe) /thorn (th)
  679. .chars.def
  680. % Encode the other standard and ISO characters.
  681. mark
  682. /brokenbar (|) /bullet (*) /copyright ((C)) /currency (#)
  683. /dagger (#) /daggerdbl (##) /degree (o) /divide (/) /dotaccent (.)
  684. /dotlessi (i)
  685. /ellipsis (...) /emdash (--) /endash (-) /exclamdown (!)
  686. /florin (f) /fraction (/)
  687. /guillemotleft (<<) /guillemotright (>>)
  688. /guilsinglleft (<) /guilsinglright (>) /hungarumlaut ("") /logicalnot (~)
  689. /macron (_) /minus (-) /mu (u) /multiply (*)
  690. /ogonek (,) /onehalf (1/2) /onequarter (1/4) /onesuperior (1)
  691. /ordfeminine (-a) /ordmasculine (-o)
  692. /paragraph (||) /periodcentered (*) /perthousand (o/oo) /plusminus (+-)
  693. /questiondown (?) /quotedblbase (") /quotedblleft (") /quotedblright (")
  694. /quotesinglbase (,) /quotesingle (') /registered ((R))
  695. /section ($) /sterling (#)
  696. /threequarters (3/4) /threesuperior (3) /trademark ((TM)) /twosuperior (2)
  697. /yen (Y)
  698. .chars.def
  699. % Encode a few common Symbol characters.
  700. mark
  701. /asteriskmath (*) /copyrightsans ((C)) /copyrightserif ((C))
  702. /greaterequal (>=) /lessequal (<=) /registersans ((R)) /registerserif ((R))
  703. /trademarksans ((TM)) /trademarkserif ((TM))
  704. .chars.def
  705. %%* Add a few characters from StandardEncoding and ISOLatin1Encoding
  706. %%* that were missing.
  707. mark
  708. /cent (c)
  709. /guilsinglleft (<)
  710. /guilsinglright (>)
  711. /breve (*)
  712. /Lslash (L/)
  713. /lslash (l/)
  714. .chars.def
  715. %%* Define the OT1Encoding and T1Encoding vectors for use with dvips
  716. %%* files. Unfortunately, there's no way of telling what font is
  717. %%* really being used within a dvips document, so we can't provide an
  718. %%* appropriate encoding for each individual font. Instead, we'll
  719. %%* just provide support for the two most popular text encodings, the
  720. %%* OT1 and T1 encodings, and just accept the fact that any font not
  721. %%* using one of those encodings will be rendered as gibberish.
  722. %%*
  723. %%* OT1 is Knuth's 7-bit encoding for the CMR text fonts, while T1
  724. %%* (aka the Cork encoding) is the 8-bit encoding used by the DC
  725. %%* fonts, a preliminary version of the proposed Extended Computer
  726. %%* Modern fonts. Unfortunately, T1 is not a strict extension of OT1;
  727. %%* they differ in positions 8#000 through 8#040, 8#074, 8#076, 8#134,
  728. %%* 8#137, 8#173, 8#174, 8#175 and 8#177, so we can't use the same
  729. %%* vector for both.
  730. %%*
  731. %%* Of course, we also can't reliably tell the difference between an
  732. %%* OT1-encoded font and a T1-encoded font based on the information in
  733. %%* a dvips-created PostScript file. As a best-guess solution, we'll
  734. %%* use the T1 encoding if the font contains any characters in
  735. %%* positions above 8#177 and the OT1 encoding if it doesn't.
  736. /T1Encoding 256 array def
  737. /OT1Encoding 256 array def
  738. %%* T1Encoding shares a lot with StandardEncoding, so let's start
  739. %%* there.
  740. StandardEncoding T1Encoding copy pop
  741. /OT1.encode {
  742. counttomark
  743. 2 idiv
  744. { OT1Encoding 3 1 roll put }
  745. repeat
  746. cleartomark
  747. } def
  748. /T1.encode {
  749. counttomark
  750. 2 idiv
  751. { T1Encoding 3 1 roll put }
  752. repeat
  753. cleartomark
  754. } def
  755. mark
  756. 8#000 /grave
  757. 8#001 /acute
  758. 8#002 /circumflex
  759. 8#003 /tilde
  760. 8#004 /dieresis
  761. 8#005 /hungarumlaut
  762. 8#006 /ring
  763. 8#007 /caron
  764. 8#010 /breve
  765. 8#011 /macron
  766. 8#012 /dotaccent
  767. 8#013 /cedilla
  768. 8#014 /ogonek
  769. 8#015 /quotesinglbase
  770. 8#016 /guilsinglleft
  771. 8#017 /guilsinglright
  772. 8#020 /quotedblleft
  773. 8#021 /quotedblright
  774. 8#022 /quotedblbase
  775. 8#023 /guillemotleft
  776. 8#024 /guillemotright
  777. 8#025 /endash
  778. 8#026 /emdash
  779. 8#027 /cwm
  780. 8#030 /perthousandzero
  781. 8#031 /dotlessi
  782. 8#032 /dotlessj
  783. 8#033 /ff
  784. 8#034 /fi
  785. 8#035 /fl
  786. 8#036 /ffi
  787. 8#037 /ffl
  788. %% 8#040 through 8#176 follow StandardEncoding
  789. 8#177 /hyphen
  790. T1.encode
  791. mark
  792. 8#200 /Abreve
  793. 8#201 /Aogonek
  794. 8#202 /Cacute
  795. 8#203 /Ccaron
  796. 8#204 /Dcaron
  797. 8#205 /Ecaron
  798. 8#206 /Eogonek
  799. 8#207 /Gbreve
  800. 8#210 /Lacute
  801. 8#211 /Lcaron
  802. 8#212 /Lslash
  803. 8#213 /Nacute
  804. 8#214 /Ncaron
  805. 8#215 /Eng
  806. 8#216 /Ohungarumlaut
  807. 8#217 /Racute
  808. 8#220 /Rcaron
  809. 8#221 /Sacute
  810. 8#222 /Scaron
  811. 8#223 /Scedilla
  812. 8#224 /Tcaron
  813. 8#225 /Tcedilla
  814. 8#226 /Uhungarumlaut
  815. 8#227 /Uring
  816. 8#230 /Ydieresis
  817. 8#231 /Zacute
  818. 8#232 /Zcaron
  819. 8#233 /Zdot
  820. 8#234 /IJ
  821. 8#235 /Idot
  822. 8#236 /dbar
  823. 8#237 /section
  824. 8#240 /abreve
  825. 8#241 /aogonek
  826. 8#242 /cacute
  827. 8#243 /ccaron
  828. 8#244 /dcaron
  829. 8#245 /ecaron
  830. 8#246 /eogonek
  831. 8#247 /gbreve
  832. 8#250 /lacute
  833. 8#251 /lcaron
  834. 8#252 /lslash
  835. 8#253 /nacute
  836. 8#254 /ncaron
  837. 8#255 /eng
  838. 8#256 /ohungarumlaut
  839. 8#257 /racute
  840. 8#260 /rcaron
  841. 8#261 /sacute
  842. 8#262 /scaron
  843. 8#263 /scedilla
  844. 8#264 /tcaron
  845. 8#265 /tcedilla
  846. 8#266 /uhungarumlaut
  847. 8#267 /uring
  848. 8#270 /ydieresis
  849. 8#271 /zacute
  850. 8#272 /zcaron
  851. 8#273 /zdot
  852. 8#274 /ij
  853. 8#275 /exclamdown
  854. 8#276 /questiondown
  855. 8#277 /sterling
  856. 8#300 /Agrave
  857. 8#301 /Aacute
  858. 8#302 /Acircumflex
  859. 8#303 /Atilde
  860. 8#304 /Adieresis
  861. 8#305 /Aring
  862. 8#306 /AE
  863. 8#307 /Ccedilla
  864. 8#310 /Egrave
  865. 8#311 /Eacute
  866. 8#312 /Ecircumflex
  867. 8#313 /Edieresis
  868. 8#314 /Igrave
  869. 8#315 /Iacute
  870. 8#316 /Icircumflex
  871. 8#317 /Idieresis
  872. 8#320 /Eth
  873. 8#321 /Ntilde
  874. 8#322 /Ograve
  875. 8#323 /Oacute
  876. 8#324 /Ocircumflex
  877. 8#325 /Otilde
  878. 8#326 /Odieresis
  879. 8#327 /OE
  880. 8#330 /Oslash
  881. 8#331 /Ugrave
  882. 8#332 /Uacute
  883. 8#333 /Ucircumflex
  884. 8#334 /Udieresis
  885. 8#335 /Yacute
  886. 8#336 /Thorn
  887. 8#337 /Germandbls
  888. 8#340 /agrave
  889. 8#341 /aacute
  890. 8#342 /acircumflex
  891. 8#343 /atilde
  892. 8#344 /adieresis
  893. 8#345 /aring
  894. 8#346 /ae
  895. 8#347 /ccedilla
  896. 8#350 /egrave
  897. 8#351 /eacute
  898. 8#352 /ecircumflex
  899. 8#353 /edieresis
  900. 8#354 /igrave
  901. 8#355 /iacute
  902. 8#356 /icircumflex
  903. 8#357 /idieresis
  904. 8#360 /eth
  905. 8#361 /ntilde
  906. 8#362 /ograve
  907. 8#363 /oacute
  908. 8#364 /ocircumflex
  909. 8#365 /otilde
  910. 8#366 /odieresis
  911. 8#367 /oe
  912. 8#370 /oslash
  913. 8#371 /ugrave
  914. 8#372 /uacute
  915. 8#373 /ucircumflex
  916. 8#374 /udieresis
  917. 8#375 /yacute
  918. 8#376 /thorn
  919. 8#377 /germandbls
  920. T1.encode
  921. %%* Now copy OT1Encoding into T1Encoding and make a few changes.
  922. T1Encoding OT1Encoding copy pop
  923. mark
  924. 8#000 /Gamma
  925. 8#001 /Delta
  926. 8#002 /Theta
  927. 8#003 /Lambda
  928. 8#004 /Xi
  929. 8#005 /Pi
  930. 8#006 /Sigma
  931. 8#007 /Upsilon
  932. 8#010 /Phi
  933. 8#011 /Psi
  934. 8#012 /Omega
  935. 8#013 /ff
  936. 8#014 /fi
  937. 8#015 /fl
  938. 8#016 /ffi
  939. 8#017 /ffl
  940. 8#020 /dotlessi
  941. 8#021 /dotlessj
  942. 8#022 /grave
  943. 8#023 /acute
  944. 8#024 /caron
  945. 8#025 /breve
  946. 8#026 /macron
  947. 8#027 /ring
  948. 8#030 /cedilla
  949. 8#031 /germandbls
  950. 8#032 /ae
  951. 8#033 /oe
  952. 8#034 /oslash
  953. 8#035 /AE
  954. 8#036 /OE
  955. 8#037 /Oslash
  956. 8#040 /polishslash
  957. 8#042 /quotedblright
  958. 8#074 /exclamdown
  959. 8#076 /questiondown
  960. 8#134 /quotedblleft
  961. 8#137 /dotaccent
  962. 8#173 /endash
  963. 8#174 /emdash
  964. 8#175 /hungarumlaut
  965. 8#177 /dieresis
  966. OT1.encode
  967. %%* And add a few characters from the OT1Encoding
  968. mark
  969. /Gamma (\\Gamma )
  970. /Delta (\\Delta )
  971. /Theta (\\Theta )
  972. /Lambda (\\Lambda )
  973. /Xi (\\Xi )
  974. /Pi (\\Pi )
  975. /Sigma (\\Sigma )
  976. /Upsilon (\\Upsilon )
  977. /Phi (\\Phi )
  978. /Psi (\\Psi )
  979. /Omega (\\Omega )
  980. /dotlessj (j)
  981. /ff (ff)
  982. /cwm ()
  983. /perthousandzero (0)
  984. /polishslash ()
  985. /Abreve (A*)
  986. /Aogonek (A,)
  987. /Cacute (C')
  988. /Ccaron (C^)
  989. /Dcaron (D^)
  990. /Ecaron (E^)
  991. /Eogonek (E,)
  992. /Gbreve (G*)
  993. /Lacute (L')
  994. /Lcaron (L^)
  995. /Nacute (N')
  996. /Ncaron (N^)
  997. /Eng (NG)
  998. /Ohungarumlaut (O"")
  999. /Racute (R')
  1000. /Rcaron (R^)
  1001. /Sacute (S')
  1002. /Scaron (S^)
  1003. /Scedilla (S,)
  1004. /Tcaron (T^)
  1005. /Tcedilla (T,)
  1006. /Uhungarumlaut (U"")
  1007. /Uring (U*)
  1008. /Ydieresis (Y")
  1009. /Zacute (Z')
  1010. /Zcaron (Z^)
  1011. /Zdot (Z.)
  1012. /IJ (IJ)
  1013. /Idot (I.)
  1014. /dbar (d-)
  1015. /abreve (a*)
  1016. /aogonek (a,)
  1017. /cacute (c')
  1018. /ccaron (c^)
  1019. /dcaron (d^)
  1020. /ecaron (e^)
  1021. /eogonek (e,)
  1022. /gbreve (g*)
  1023. /lacute (l')
  1024. /lcaron (l^)
  1025. /nacute (n')
  1026. /ncaron (n^)
  1027. /eng (ng)
  1028. /ohungarumlaut (o"")
  1029. /racute (r')
  1030. /rcaron (r^)
  1031. /sacute (s')
  1032. /scaron (s^)
  1033. /scedilla (s,)
  1034. /tcaron (t^)
  1035. /tcedilla (t,)
  1036. /uhungarumlaut (u"")
  1037. /uring (u*)
  1038. /zacute (z')
  1039. /zcaron (z^)
  1040. /zdot (z.)
  1041. /ij (ij)
  1042. /Germandbls (SS)
  1043. .chars.def
  1044. %%* We extend the df-tail command to stick in an Encoding vector (see
  1045. %%* above for a discussion of the T1 and OT1 encodings), put in a
  1046. %%* FontName (which will just be dvips's name for the font, i.e., Fa,
  1047. %%* Fb, etc.) and give each font a separate FontBBox instead of
  1048. %%* letting them all share a single one.
  1049. /dvips.df-tail % id numcc maxcc df-tail
  1050. {
  1051. /nn 9 dict N
  1052. nn begin
  1053. %%
  1054. %% Choose an encoding based on the highest position occupied.
  1055. %%
  1056. dup 128 gt { T1Encoding } { OT1Encoding } ifelse
  1057. /Encoding X
  1058. /FontType 3 N
  1059. %%
  1060. %% It's ok for all the fonts to share a FontMatrix, but they
  1061. %% need to have separate FontBBoxes
  1062. %%
  1063. /FontMatrix fntrx N
  1064. /FontBBox [0 0 0 0] N
  1065. string /base X
  1066. array /BitMaps X
  1067. %%
  1068. %% And let's throw in a FontName for good measure
  1069. %%
  1070. dup ( ) cvs
  1071. %%
  1072. %% Make sure each font gets it own private FontName. -- dmj,
  1073. %% 12/23/97
  1074. %%
  1075. dup length string copy
  1076. /FontName X
  1077. /BuildChar {CharBuilder} N
  1078. end
  1079. dup { /foo setfont }
  1080. 2 array copy cvx N
  1081. load
  1082. 0 nn put
  1083. /ctr 0 N
  1084. [
  1085. } def
  1086. %%* This is functionally equivalent to dvips's /D procedure, but it
  1087. %%* also calculates the Font Bounding Box while defining the
  1088. %%* characters.
  1089. /dvips.D % char-data ch D - : define character bitmap in current font
  1090. {
  1091. /cc X % char-data
  1092. dup type /stringtype ne {]} if % char-data
  1093. /ch-xoff where
  1094. { pop }
  1095. { dup /Cd exch def
  1096. /ch-width { Cw } def
  1097. /ch-height { Ch } def
  1098. /ch-xoff { Cx } def
  1099. /ch-yoff { Cy } def
  1100. /ch-dx { Cdx } def
  1101. } ifelse
  1102. /ch-data X
  1103. nn /base get cc ctr put % (adds ctr to cc'th position of BASE)
  1104. nn /BitMaps get
  1105. ctr
  1106. ch-data % BitMaps ctr char-data
  1107. sf 1 ne {
  1108. dup dup length 1 sub dup 2 index S get sf div put
  1109. } if
  1110. put % puts char-data into BitMaps at index ctr
  1111. /ctr ctr 1 add N
  1112. %%
  1113. %% Make sure the Font Bounding Box encloses the Bounding Box of the
  1114. %% current character
  1115. %%
  1116. nn /FontBBox get % BB
  1117. dup % calculate new llx
  1118. dup 0 get
  1119. ch-xoff
  1120. .min
  1121. 0 exch put
  1122. dup % calculate new lly
  1123. dup 1 get
  1124. ch-yoff ch-height sub
  1125. .min
  1126. 1 exch put
  1127. dup % calculate new urx
  1128. dup 2 get
  1129. ch-dx ch-width add
  1130. .max
  1131. 2 exch put
  1132. dup 3 get % calculate new ury
  1133. ch-yoff
  1134. .max
  1135. 3 exch put
  1136. } def
  1137. %%* Define start-hook to replace df-tail and D by our versions.
  1138. %%* Unfortunately, the user can redefine start-hook and thus bypass
  1139. %%* these changes, but I don't see an obvious way around that.
  1140. userdict /start-hook {
  1141. TeXDict /df-tail /dvips.df-tail load bind put
  1142. TeXDict /D /dvips.D load bind put
  1143. } put
  1144. %%* Introduce a symbolic constant for hyphens. (Need to make
  1145. %%* allowance for hyphen being in different place?)
  1146. /.hyphen 45 def
  1147. % Write out a string. If it ends in a letter and a hyphen,
  1148. % don't write the hyphen, and set .show.last to a hyphen;
  1149. % otherwise, set .show.last to the character (or \000 if it was a hyphen).
  1150. /.show.write % <string>
  1151. {
  1152. dup length 1 ge
  1153. { dup dup length 1 sub get % string last_char
  1154. dup .hyphen eq % string last_char hyphen?
  1155. { % string last_char
  1156. 1 index length 1 gt
  1157. { 1 index dup length 2 sub get }
  1158. { //.show.last 0 get }
  1159. ifelse % string last_char prev-char
  1160. currentfont /Encoding get exch get % look up prev-char
  1161. //.letter.chars exch known % is it a letter?
  1162. { % Remove the hyphen % string last_char
  1163. exch % last_char string
  1164. dup length 1 sub % last_char string len-1
  1165. 0 exch getinterval % last_char string-1
  1166. exch % string-1 last_char
  1167. }
  1168. { pop 0 } % string 0
  1169. ifelse
  1170. }
  1171. if
  1172. //.show.last 0 3 -1 roll put % store last_char
  1173. % in .show.last
  1174. % If .show.last ==
  1175. % hyphen, then
  1176. % last char of
  1177. % previous string
  1178. % was a hyphen
  1179. }
  1180. if % string
  1181. currentfont /FontType get 0 ne
  1182. {
  1183. { % begin forall % c
  1184. dup % c c
  1185. currentfont /Encoding get % c c vec
  1186. exch get % c name
  1187. dup //.char.map exch known % c name bool
  1188. { exch pop }
  1189. { pop OT1Encoding exch get }
  1190. ifelse % name
  1191. //.char.map exch get % translation
  1192. .show.stdout exch writestring
  1193. }
  1194. forall
  1195. }
  1196. { (\0) dup 0 get 0 eq
  1197. { 0 1 put
  1198. (%stderr) (w) file dup
  1199. (*** Warning: composite font characters dumped without decoding.\n) writestring
  1200. closefile
  1201. }
  1202. { pop
  1203. }
  1204. ifelse
  1205. .show.stdout exch writestring
  1206. }
  1207. ifelse
  1208. } odef
  1209. /.showstring1 { % string
  1210. currentpoint .coord % string x y
  1211. 3 -1 roll dup .showwidth % x y string dx dy
  1212. 1 index % x y string dx dy dx
  1213. 0 rmoveto % x y string dx dy
  1214. .dcoord pop % x y string width
  1215. SIMPLE
  1216. { % x y string width
  1217. 2 index % x y string width y
  1218. //.show.y .iget % x y string width y old.y
  1219. %%*
  1220. %%* Replaced test "has y changed" by "has y changed by more
  1221. %%* than the current font height" so that subscripts and
  1222. %%* superscripts won't cause line/paragraph breaks
  1223. %%*
  1224. sub abs dup % x y string width dy dy
  1225. //.show.height .iget
  1226. gt
  1227. { % x y string width dy
  1228. %%* Vertical position has changed by more than the font
  1229. %%* height, so we now try to figure out whether we've
  1230. %%* started a new paragraph or merely a new line, using a
  1231. %%* variety of heuristics.
  1232. %%* If any of the following is true, we start a new
  1233. %%* paragraph:
  1234. %%* (a) the current vertical shift is more than 1.1 times
  1235. %%* the previous vertical shift, where 1.1 is an
  1236. %%* arbitrarily chosen factor that could probably be
  1237. %%* refined.
  1238. dup % x y string width dy dy
  1239. //.show.dy .iget 1.1 mul
  1240. gt
  1241. exch
  1242. %%* Save the new vertical shift
  1243. //.show.dy exch .iput
  1244. %%* (b) The vertical shift is more than 1.3 times the
  1245. %%* "size" of the current font. I've removed this
  1246. %%* test since it's not really very useful.
  1247. %%* //.show.dy .iget
  1248. %%* //.show.height .iget 1.4 mul
  1249. %%* gt % x y string width bool
  1250. %%* .show.height .iget 0 gt and % only perform test if font
  1251. %%* % height is nonzero
  1252. %%* or
  1253. %%* (c) the first character of the new line is one of the
  1254. %%* .break.chars
  1255. 2 index length % x y string width newpar? len
  1256. 0 gt % x y string width newpar? len>0?
  1257. {
  1258. 2 index 0 get % x y string width newpar? s
  1259. currentfont /Encoding get
  1260. exch get % x y string width newpar? s_enc
  1261. //.break.chars exch known { pop true } if
  1262. }
  1263. if % x y string width newpar?
  1264. %%* (d) The indentation of the new line is greater than
  1265. %%* the indentation of the previous line.
  1266. 4 index
  1267. //.show.indent .iget
  1268. gt
  1269. or
  1270. %%* HOWEVER, if the line ends in a hyphen, we do NOT begin
  1271. %%* a new paragraph (cf. comment at end of BF2). --dmj,
  1272. %%* 12/23/97
  1273. //.show.last 0 get .hyphen ne
  1274. and
  1275. % newpar?
  1276. { (\n\n) } % Paragraph
  1277. { % Line
  1278. %%*
  1279. %%* BF2: If last character on a line is
  1280. %%* a hyphen, we omit the hyphen and
  1281. %%* run the lines together. Of
  1282. %%* course, this will fail if a word
  1283. %%* with an explicit hyphen (e.g.,
  1284. %%* X-ray) is split across two lines.
  1285. %%* Oh, well. (What should we do
  1286. %%* about a hyphen that ends a
  1287. %%* "paragraph"? Perhaps that should
  1288. %%* inhibit a paragraph break.)
  1289. %%*
  1290. //.show.last 0 get .hyphen eq
  1291. { () }
  1292. { ( ) }
  1293. ifelse % x y string width char
  1294. }
  1295. ifelse
  1296. //print
  1297. //.show.y 3 index .iput % x y string width
  1298. //.show.x 4 index .iput % x y string width
  1299. //.show.indent 4 index .iput
  1300. }
  1301. { % x y string width dy
  1302. % If the word processor split a hyphenated word within
  1303. % the same line, put out the hyphen now.
  1304. pop
  1305. //.show.last 0 get .hyphen eq { (-) //print } if
  1306. }
  1307. ifelse
  1308. %%*
  1309. %%* If have moved more than 1 point to
  1310. %%* the right, interpret it as a
  1311. %%* space? This need to be looked at
  1312. %%* more closely.
  1313. %%*
  1314. 3 index % x y string width x
  1315. //.show.x .iget 10 add gt % x y string width bool
  1316. { ( ) //print }
  1317. if
  1318. % x y string width
  1319. 4 1 roll % width x y string
  1320. .show.write pop % width x
  1321. add //.show.x exch .iput % <empty>
  1322. }
  1323. { (S ) //print .show==4 }
  1324. ifelse
  1325. } odef
  1326. /.showstring
  1327. { dup () eq { pop } { .showstring1 } ifelse
  1328. } bind def
  1329. % Redefine all the string display operators.
  1330. /show {
  1331. .showfont
  1332. .showcolor
  1333. .showstring
  1334. } codef
  1335. % We define all the other operators in terms of .show1.
  1336. /.show1.string ( ) def
  1337. /.show1 { //.show1.string exch 0 exch put //.show1.string .showstring } odef
  1338. /ashow
  1339. { .showfont .showcolor
  1340. { .show1 2 copy rmoveto } forall
  1341. pop pop
  1342. } codef
  1343. /awidthshow
  1344. { .showfont .showcolor
  1345. { dup .show1 4 index eq { 4 index 4 index rmoveto } if
  1346. 2 copy rmoveto
  1347. }
  1348. forall
  1349. pop pop pop pop pop
  1350. } codef
  1351. /widthshow
  1352. { .showfont .showcolor
  1353. //.show1.string 0 4 -1 roll put
  1354. { //.show1.string search not { exit } if
  1355. .showstring .showstring
  1356. 2 index 2 index rmoveto
  1357. } loop
  1358. .showstring pop pop
  1359. } codef
  1360. /kshow
  1361. { .showfont .showcolor
  1362. %**************** Should construct a closure, in case the procedure
  1363. %**************** affects the o-stack.
  1364. { .show1 dup exec } forall pop
  1365. } codef
  1366. % We don't really do the right thing with the Level 2 show operators,
  1367. % but we do something semi-reasonable.
  1368. /xshow { pop show } codef
  1369. /yshow { pop show } codef
  1370. /xyshow { pop show } codef
  1371. /glyphshow
  1372. { currentfont /Encoding .knownget not { {} } if
  1373. 0 1 2 index length 1 sub
  1374. { % Stack: glyph encoding index
  1375. 2 copy get 3 index eq { exch pop exch pop null exit } if
  1376. pop
  1377. }
  1378. for null eq { (X) dup 0 4 -1 roll put show } { pop } ifelse
  1379. } codef
  1380. end
  1381. % Bind the operators we just defined, and all the others if we didn't
  1382. % do it before.
  1383. DELAYBIND { .bindnow } if
  1384. % Make systemdict read-only if it wasn't already.
  1385. systemdict wcheck { systemdict readonly pop } if
  1386. % Restore the current local/global VM mode.
  1387. exec