pdf_ops.ps 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676
  1. % Copyright (C) 1994, 2000 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: pdf_ops.ps,v 1.41 2005/09/28 04:33:27 dan Exp $
  16. % Definitions for most of the PDF operators.
  17. .currentglobal true .setglobal
  18. % Define pdfmark. Don't allow it to be bound in.
  19. % Also don't define it in systemdict, because this leads some Adobe code
  20. % to think this interpreter is a distiller.
  21. % (If this interpreter really is a distiller, don't do this.)
  22. systemdict /pdfmark known not
  23. { userdict /pdfmark { cleartomark } bind put } if
  24. userdict /GS_PDF_ProcSet 127 dict dup begin
  25. % ---------------- Abbreviations ---------------- %
  26. /bdef { bind def } bind def
  27. % ---------------- Graphics state stack ---------------- %
  28. % PDF adds a number of parameters to the graphics state.
  29. % We implement this by pushing and popping a dictionary
  30. % each time we do a PDF gsave or grestore.
  31. % The keys in this dictionary are as follows:
  32. % self % identifies the dictionary as one of ours
  33. % ClipRect % (optional)
  34. % Show
  35. % TextSaveMatrix % matrix at time of BT (iff within BT/ET)
  36. % (The following correspond directly to PDF state parameters.)
  37. % AlphaIsShape
  38. % FillConstantAlpha
  39. % FillColor
  40. % FillColorSpace
  41. % FillOverprint
  42. % SoftMask
  43. % StrokeConstantAlpha
  44. % StrokeColor
  45. % StrokeColorSpace
  46. % StrokeOverprint
  47. % TextSpacing
  48. % TextHScaling
  49. % Leading
  50. % TextFont
  51. % TextLineMatrix
  52. % TextMatrix
  53. % TextRise
  54. % TextRenderingMode
  55. % WordSpacing
  56. /nodict 1 dict def
  57. nodict /self { //nodict } executeonly put
  58. nodict readonly pop
  59. /dictbeginpage { % <initialdict> dictbeginpage -
  60. //nodict 20 dict .copydict begin { def } forall
  61. graphicsbeginpage textbeginpage
  62. } bdef
  63. /endpage { % - endpage -
  64. showpage end
  65. } bdef
  66. /graphicsbeginpage {
  67. initgraphics
  68. currentdict /ClipRect knownoget { aload pop rectclip } if
  69. 0 g 0 G false op false OP 0 OPM
  70. 1 ca 1 CA null SMask false AIS /Compatible BM true TK
  71. } bdef
  72. /gput % <value> <key> gput -
  73. { exch currentdict //nodict eq { /self dup load end 5 dict begin def } if
  74. % If we're in a Level 1 system, we need to grow the
  75. % dictionary explicitly.
  76. currentdict length currentdict maxlength ge %eq
  77. { currentdict dup length 3 mul 2 idiv 1 add dict .copydict end begin
  78. }
  79. if def
  80. } bdef
  81. % Restore graphics state, but do not modify path. Paths are not part
  82. % of the PDF graphics state; see 4.4.1 of PDF reference 3rd ed.
  83. /grestore_nopath {
  84. % Collect the upath with an identity CTM
  85. { matrix setmatrix //false upath } stopped {
  86. pop grestore newpath
  87. } {
  88. % Save the CTM, set identity during the uappend, then set the CTM
  89. grestore matrix currentmatrix matrix setmatrix
  90. exch newpath uappend setmatrix
  91. } ifelse
  92. } bdef
  93. /q {
  94. gsave //nodict begin
  95. } bdef
  96. % Some PDF files have excess Q operators!
  97. /Q {
  98. currentdict /self .knownget {
  99. exec //nodict eq { end grestore_nopath false } { true } ifelse
  100. } {
  101. true % formaterror -- not a gsave dict
  102. } ifelse
  103. { (\n **** File has imbalanced q/Q operators \(too many Q's\) ****\n)
  104. pdfformaterror
  105. } if
  106. } bdef
  107. % Save PDF gstate
  108. /qstate { % - qstate <qstate>
  109. gstate
  110. } bdef
  111. % Set PDF gstate
  112. /setqstate { % <qstate> setqstate -
  113. { matrix setmatrix //false upath } stopped {
  114. pop setgstate newpath
  115. } {
  116. % Save the CTM, set identity during the uappend, then set the CTM
  117. exch setgstate matrix currentmatrix matrix setmatrix
  118. exch newpath uappend setmatrix
  119. } ifelse
  120. } bdef
  121. % ---------------- Color setting ---------------- %
  122. /fcput % <color> <colorspace> fcput -
  123. { /FillColorSpace gput /FillColor gput
  124. } bdef
  125. /scput % <color> <colorspace> scput -
  126. { /StrokeColorSpace gput /StrokeColor gput
  127. } bdef
  128. /csput % <colorspace> csput -
  129. { csset 2 copy fcput scput
  130. } bdef
  131. /csdevgray [/DeviceGray] readonly def
  132. /csdevrgb [/DeviceRGB] readonly def
  133. /csdevcmyk [/DeviceCMYK] readonly def
  134. /cspattern [/Pattern] readonly def
  135. /nullpattern1 mark
  136. /PatternType 1 /PaintType 1 /TilingType 3 /BBox [0 0 0 0]
  137. /XStep 1 /YStep 1 /PaintProc { }
  138. .dicttomark readonly def
  139. /nullpattern2 nullpattern1 dup length dict copy readonly def
  140. % Each entry in the color space dictionary is a procedure of the form
  141. % <cspace> -proc- <cspace> <initial-color>
  142. /CSdict mark
  143. /DeviceGray { pop //csdevgray 0 } bind
  144. /DeviceRGB { pop //csdevrgb [0 0 0] cvx } bind
  145. /DeviceCMYK { pop //csdevcmyk [0 0 0 1] cvx } bind
  146. /CIEBasedA { 0 } bind
  147. /CIEBasedABC { [0 0 0] cvx } bind
  148. /ICCBased { [ 1 index 1 oget /N get { 0 } repeat ] cvx } bind
  149. /Separation { 1 } bind
  150. /DeviceN { % What is the correct value??
  151. [ 1 index 1 get length { 1 } repeat ] cvx
  152. } bind
  153. /Indexed { 0 } bind
  154. /Pattern {
  155. dup type /nametype eq 1 index length 1 eq or {
  156. pop //cspattern //nullpattern1 matrix makepattern
  157. } {
  158. //nullpattern2 matrix makepattern 1 index 1 get csset
  159. % Stack: patternspace nullpattern basecolor basespace
  160. pop [ 3 1 roll dup type /arraytype eq { aload pop } if
  161. counttomark -1 roll ] cvx
  162. } ifelse
  163. } bind
  164. .dicttomark readonly def
  165. /csset % <cspace> csset <color> <cspace>
  166. { dup dup type /nametype ne { 0 get } if //CSdict exch get exec exch
  167. } bdef
  168. /g { //csdevgray fcput } bdef
  169. /G { //csdevgray scput } bdef
  170. /rg { 3 array astore cvx //csdevrgb fcput } bdef
  171. /RG { 3 array astore cvx //csdevrgb scput } bdef
  172. /k { 4 array astore cvx //csdevcmyk fcput } bdef
  173. /K { 4 array astore cvx //csdevcmyk scput } bdef
  174. /cs { csset fcput } bdef
  175. /CS { csset scput } bdef
  176. /ri { pop } bdef
  177. % We have to break up sc according to the number of operands.
  178. /sc1 { /FillColor gput } bdef
  179. /SC1 { /StrokeColor gput } bdef
  180. % We have to avoid storing into a color array associated with an outer
  181. % gsave level, so we do a kind of "copy on write".
  182. /sc* {
  183. currentdict /FillColor .knownget {
  184. astore pop
  185. } {
  186. /FillColor load
  187. % FillColor may contain either a single value or an array.
  188. dup type /arraytype eq { length }{ pop 1 } ifelse
  189. array astore cvx /FillColor gput
  190. } ifelse
  191. } bdef
  192. /SC* {
  193. currentdict /StrokeColor .knownget {
  194. astore pop
  195. } {
  196. /StrokeColor load
  197. % StrokeColor may contain either a single value or an array.
  198. dup type /arraytype eq { length }{ pop 1 } ifelse
  199. array astore cvx /StrokeColor gput
  200. } ifelse
  201. } bdef
  202. % ---------------- Overprint/transparency setting ---------------- %
  203. /op { /FillOverprint gput } bdef
  204. /OP { /StrokeOverprint gput } bdef
  205. /OPM {
  206. /.setoverprintmode where { pop .setoverprintmode } { pop } ifelse
  207. } bdef
  208. /ca { /FillConstantAlpha gput } bdef
  209. /CA { /StrokeConstantAlpha gput } bdef
  210. /SMask { /SoftMask gput } bdef
  211. /AIS { /AlphaIsShape gput } bdef
  212. /BM {
  213. /.setblendmode where {
  214. pop [ exch dup type /nametype ne { aload pop } if /Normal ] {
  215. { .setblendmode } .internalstopped not { exit } if pop
  216. } forall
  217. } {
  218. pop
  219. } ifelse
  220. } bdef
  221. /TK {
  222. /.settextknockout where { pop .settextknockout } { pop } ifelse
  223. } bdef
  224. % ---------------- Color installation ---------------- %
  225. % Establish a given color (and color space) as current.
  226. /.settransparencyparams { % <alpha> <smask> .settransparencyparams -
  227. /.inittransparencymask where {
  228. pop AlphaIsShape {
  229. 1 .setopacityalpha 0 .inittransparencymask exch .setshapealpha 1
  230. } {
  231. 1 .setshapealpha 1 .inittransparencymask exch .setopacityalpha 0
  232. } ifelse
  233. % Set the soft mask by rendering the XObject. Doing this every time
  234. % is obviously very inefficient; we'll improve it later.
  235. .settransparencymask
  236. } {
  237. pop pop
  238. } ifelse
  239. } bdef
  240. /.settransparencymask { % <paramdict> <masknum> .settransparencymask -
  241. exch dup null eq {
  242. pop .inittransparencymask
  243. } {
  244. dup /Draw get exec
  245. } ifelse
  246. } bdef
  247. % (Non-mask) images must execute setfillblend.
  248. /setfillblend {
  249. FillOverprint setoverprint
  250. FillConstantAlpha SoftMask .settransparencyparams
  251. } def
  252. /setfillstate {
  253. FillColor FillColorSpace setgcolor setfillblend
  254. } def
  255. /setstrokestate {
  256. StrokeColor StrokeColorSpace setgcolor StrokeOverprint setoverprint
  257. StrokeConstantAlpha SoftMask .settransparencyparams
  258. } def
  259. /Cdict 15 dict dup begin % <color...> <colorspace> -proc- -
  260. /DeviceGray { pop setgray } bdef
  261. /DeviceRGB { pop setrgbcolor } bdef
  262. /DeviceCMYK { pop setcmykcolor } bdef
  263. /CIEBasedA { setgcolorspace setcolor } bdef
  264. /CIEBasedABC /CIEBasedA load def
  265. /CIEBasedDEF /CIEBasedA load def
  266. /CIEBasedDEFG /CIEBasedA load def
  267. /ICCBased /CIEBasedA load def
  268. /Separation /CIEBasedA load def
  269. /DeviceN /CIEBasedA load def
  270. /Indexed /CIEBasedA load def
  271. /Pattern
  272. { setgcolorspace
  273. % Since multiple patterns may share
  274. % same data stream, we need to ensure
  275. % that the stream is at 0 position.
  276. % Making this consistently with resolveshading,
  277. % which applies ReusableStreamDecode filter
  278. % to the PS stream, which represents the
  279. % PDF stream in dynamics.
  280. dup /Shading knownoget {
  281. dup /ShadingType oget 4 ge {
  282. /DataSource knownoget {
  283. dup type /filetype eq {
  284. 0 setfileposition
  285. } {
  286. pop
  287. } ifelse
  288. } if
  289. } {
  290. pop
  291. } ifelse
  292. } if
  293. dup /Matrix knownoget not { matrix } if
  294. gsave DefaultQstate setqstate makepattern grestore setcolor
  295. } bdef
  296. end def
  297. /setgcolor % (null | <color...>) <colorspace> setgcolor -
  298. { 1 index null eq
  299. { pop pop }
  300. { dup 0 get //Cdict exch get exec }
  301. ifelse
  302. } bdef
  303. % Compare the old and new color spaces in an attempt to avoid expensive
  304. % reloads of CIEBased color spaces.
  305. /PCSdict 15 dict dup begin % <colorspace> -proc- <colorspace|pdfcspace>
  306. /CIEBasedA { dup 1 get /PDFColorSpace .knownget { exch pop } if } bdef
  307. /CIEBasedABC /CIEBasedA load def
  308. /CIEBasedDEF /CIEBasedA load def
  309. /CIEBasedDEFG /CIEBasedA load def
  310. /Indexed {
  311. dup 1 get dup pdfcolorspace 2 copy ne { 3 1 roll } if pop pop
  312. } bdef
  313. end def
  314. /pdfcolorspace { % <colorspace> pdfcolorspace <colorspace|pdfcspace>
  315. dup type /arraytype eq {
  316. //PCSdict 1 index 0 get .knownget { exec } if
  317. } if
  318. } bdef
  319. /setgcolorspace { % <colorspace> setgcolorspace -
  320. dup pdfcolorspace currentcolorspace pdfcolorspace eq {
  321. pop
  322. } {
  323. setcolorspace
  324. } ifelse
  325. } bdef
  326. /fsexec % <fillop|strokeop> fsexec -
  327. { % Preserve the current point, if any.
  328. { currentpoint } stopped
  329. { $error /newerror false put cvx exec }
  330. { 3 -1 roll cvx exec moveto }
  331. ifelse
  332. } bdef
  333. % ---------------- Path painting and clipping ---------------- %
  334. /S { setstrokestate /stroke fsexec } bdef
  335. /f { setfillstate /fill fsexec } bdef
  336. /f* { setfillstate /eofill fsexec } bdef
  337. /n { newpath } bdef % don't allow n to get bound in
  338. /s { closepath S } bdef
  339. /B { gsave setfillstate fill grestore S } bdef
  340. /b { closepath B } bdef
  341. /B* { gsave setfillstate eofill grestore S } bdef
  342. /b* { closepath B* } bdef
  343. % Clipping:
  344. /Wdict 4 dict dup begin
  345. /S { gsave setstrokestate stroke grestore n } bdef
  346. /f { gsave setfillstate fill grestore n } bdef
  347. /f* { gsave setfillstate eofill grestore n } bdef
  348. /n { end clip newpath } bdef
  349. end readonly def
  350. /W { //Wdict begin } bdef
  351. /W*dict 4 dict dup begin
  352. Wdict { def } forall
  353. /n { end eoclip newpath } bdef
  354. end readonly def
  355. /W* { //W*dict begin } bdef
  356. % ---------------- Text control ---------------- %
  357. /textbeginpage
  358. { /TextSpacing 0 def % 0 Tc
  359. /TextLeading 0 def % 0 TL
  360. /TextRenderingMode 0 def % 0 Tr
  361. /TextRise 0 def % 0 Ts
  362. /WordSpacing 0 def % 0 Tw
  363. /TextHScaling 1.0 def % 100 Tz
  364. /TextFont null def
  365. /Show { showfirst } def
  366. } bdef
  367. % Contrary to the statement in the PDF manual, BT and ET *can* be nested,
  368. % if the CharProc for a Type 3 font does a BT/ET itself.
  369. % Since we always call the CharProc inside a q/Q, we simply ensure that
  370. % the text state is saved and restored like the rest of the extended
  371. % graphics state.
  372. /settextmatrix {
  373. TextMatrix concat
  374. TextHScaling 1 ne { TextHScaling 1 scale } if
  375. TextRise 0 ne { 0 TextRise translate } if
  376. TextFont dup null eq { pop } { setfont } ifelse
  377. } bdef
  378. /settextstate {
  379. % The text state can be set even outside BT/ET.
  380. currentdict /TextSaveMatrix known {
  381. TextSaveMatrix setmatrix settextmatrix
  382. } if
  383. } bdef
  384. /settextposition {
  385. % Update the TextMatrix translation.
  386. gsave TextSaveMatrix setmatrix
  387. currentpoint TextRise sub TextMatrix 4 2 getinterval astore pop
  388. % We would like to do "grestore currentpoint translate"
  389. % here, but some PDF files set a singular text matrix
  390. % (0 0 0 0 <x> <y> Tm), so we can't do this.
  391. TextTempMatrix identmatrix setmatrix currentpoint
  392. grestore
  393. TextTempMatrix currentmatrix 4 2 getinterval astore pop
  394. TextTempMatrix setmatrix
  395. } bdef
  396. /BT {
  397. currentdict /TextLineMatrix .knownget
  398. { identmatrix pop TextMatrix identmatrix pop }
  399. { matrix /TextLineMatrix gput matrix /TextMatrix gput }
  400. ifelse
  401. { showfirst } /Show gput
  402. currentdict /TextSaveMatrix .knownget not {
  403. matrix dup /TextSaveMatrix gput
  404. } if currentmatrix pop settextmatrix
  405. matrix /TextTempMatrix gput % see settextposition
  406. } bdef
  407. /ET {
  408. TextRenderingMode 4 ge { clip newpath } if
  409. TextSaveMatrix setmatrix
  410. currentdict /TextSaveMatrix undef
  411. } bdef
  412. /Tc { /TextSpacing gput { showfirst } /Show gput } bdef
  413. /TL { /TextLeading gput } bdef
  414. /Tr { dup .settextrenderingmode /TextRenderingMode gput { showfirst } /Show gput } bdef
  415. /Ts { /TextRise gput settextstate } bdef
  416. /Tw { /WordSpacing gput { showfirst } /Show gput } bdef
  417. /Tz { 100 div /TextHScaling gput settextstate} bdef
  418. % ---------------- Font control ---------------- %
  419. /Tf { % <font> <scale> Tf -
  420. dup 0 eq {
  421. (\n **** Warning: Invalid 0.0 font scale given for Tf ****\n)
  422. pdfformaterror
  423. pop 0.00000001 % handle invalid scale by using a really small value
  424. } if
  425. dup 1 eq { pop } { scalefont } ifelse
  426. /TextFont gput settextstate
  427. } bdef
  428. % Read a CFF font.
  429. /FRD % <resname> <file> FRD -
  430. { /FontSetInit /ProcSet findresource begin //true ReadData
  431. } bdef
  432. % Copy a font, removing its FID. If changed is true, also remove
  433. % the UniqueID and XUID, if any. If the original dictionary doesn't have
  434. % the keys being removed, don't copy it.
  435. /.copyfontdict % <font> <changed> .copyfontdict <dict>
  436. { 1 index /FID known
  437. 1 index { 2 index /UniqueID known or 2 index /XUID known or } if
  438. { % We add 1 to the length just in case the original
  439. % didn't have a FID.
  440. exch dup length 1 add dict exch
  441. { % Stack: changed newfont key value
  442. 1 index /FID eq 4 index
  443. { 2 index /UniqueID eq or 2 index /XUID eq or }
  444. if not { 3 copy put } if pop pop
  445. }
  446. forall exch
  447. }
  448. if pop
  449. } bdef
  450. % Insert a new Encoding or Metrics into a font if necessary.
  451. % Return a possibly updated font, and a flag to indicate whether
  452. % the font was actually copied.
  453. /.updatefontmetrics { % <font> <Metrics|null> .updatefontmetrics
  454. % <font'> <copied>
  455. dup //null ne {
  456. exch //true .copyfontdict dup /Metrics 4 -1 roll put //true
  457. } {
  458. pop //false
  459. } ifelse
  460. } bdef
  461. /.updatefontencoding { % <font> <Encoding|null> .updatefontencoding
  462. % <font'> <copied>
  463. dup //null ne { dup 2 index /Encoding get ne } { //false } ifelse {
  464. exch //false .copyfontdict dup /Encoding 4 -1 roll put //true
  465. } {
  466. pop //false
  467. } ifelse
  468. } bdef
  469. % Duplicate keys in CharString dictionary according to GlyphMap: <</new_glyph /old_glyph>>
  470. % We have to do this because PDF fonts can associate multiple widths with the same glyph
  471. % but Metrics dictionary works by the glyph name.
  472. /.update_charstring { % <font> <GlyphMap> .update_charstring <font'> <copied>
  473. dup //null ne {
  474. exch //true .copyfontdict % map font
  475. dup dup /CharStrings get % map font font cstr
  476. dup length % map font font cstr len
  477. 4 index length add % map font font cstr len+map_len
  478. dict copy dup begin % map font font cstr'
  479. /CharStrings exch put % map font
  480. exch { % font /new /old
  481. currentdict exch .knownget {
  482. def
  483. } {
  484. currentdict /.notdef .knownget {
  485. def
  486. } {
  487. pop
  488. % The font has no .notdef.
  489. % Could not resolve the conflict,
  490. % but either the font is invalid or the glyph name is never used.
  491. } ifelse
  492. } ifelse
  493. } forall
  494. end //true
  495. } {
  496. pop //false
  497. } ifelse
  498. } bdef
  499. /.updatefont { % <font> <Encoding|null> <Metrics|null> <GlyphMap|null>
  500. % .updatefont <font'> <copied>
  501. 4 2 roll % <Metrics|null> <GlyphMap> <font> <Encoding|null>
  502. .updatefontencoding % <Metrics|null> <GlyphMap> <font> bool
  503. 4 1 roll exch % bool <Metrics|null> <font> <GlyphMap>
  504. .update_charstring % bool <Metrics|null> <font> bool
  505. 3 1 roll exch % bool bool <font> <Metrics|null>
  506. .updatefontmetrics % bool bool <font> bool
  507. 4 2 roll or or % <font> is_copied
  508. } bdef
  509. % ---------------- Text positioning ---------------- %
  510. /Td {
  511. TextLineMatrix transform TextLineMatrix 4 2 getinterval astore pop
  512. TextLineMatrix TextMatrix copy pop settextstate
  513. } bdef
  514. /TD { dup neg /TextLeading gput Td } bdef
  515. /T* { 0 TextLeading neg Td } bdef
  516. /Tm {
  517. TextLineMatrix astore TextMatrix copy pop settextstate
  518. } bdef
  519. % ---------------- Text painting ---------------- %
  520. /Vexch {
  521. rootfont /WMode knownoget { 1 eq { exch } if } if
  522. } bind def
  523. /textrenderingprocs [ % (0 is handled specially)
  524. % Painting-only modes
  525. { tf } { tS } { tB } { tn }
  526. % Clipping modes
  527. { gsave tf grestore tW }
  528. { gsave tS grestore tW }
  529. { gsave tB grestore tW }
  530. { tW }
  531. ] readonly def
  532. /setshowstate
  533. { WordSpacing 0 eq TextSpacing 0 eq and
  534. { TextRenderingMode 0 eq {
  535. { setfillstate show }
  536. } {
  537. TextRenderingMode 3 eq {
  538. % Some PDF files execute 'tm' with a singular matrix,
  539. % and then use the text rendering mode 3.
  540. % The graphics library currently cannot handle text
  541. % operations when the CTM is singular.
  542. % Work around this here.
  543. {
  544. matrix currentmatrix dup
  545. dup 0 get 0 eq 1 index 1 get 0 eq and {
  546. dup dup 2 get 0 eq { 0 }{ 1 } ifelse 1 put
  547. } if
  548. dup 2 get 0 eq 1 index 3 get 0 eq and {
  549. dup dup 1 get 0 eq { 3 }{ 2 } ifelse 1 put
  550. } if
  551. setmatrix
  552. 1 index setfillstate show % Tr was set to graphic state.
  553. setmatrix
  554. % now set the currentpoint using the original matrix
  555. false charpath currentpoint newpath moveto
  556. }
  557. } {
  558. { false charpath textrenderingprocs TextRenderingMode get exec }
  559. } ifelse
  560. } ifelse
  561. }
  562. { TextRenderingMode 0 eq TextRenderingMode 3 eq or
  563. % Tr was set to graphic state.
  564. { WordSpacing 0 eq
  565. { { setfillstate TextSpacing 0 Vexch 3 -1 roll ashow } }
  566. { TextSpacing 0 eq
  567. { { setfillstate WordSpacing 0 Vexch 32 4 -1 roll widthshow } }
  568. { { setfillstate WordSpacing 0 Vexch 32
  569. TextSpacing 0 Vexch 6 -1 roll awidthshow } }
  570. ifelse
  571. }
  572. ifelse
  573. }
  574. { { WordSpacing TextSpacing
  575. % Implement the combination of t3 and false charpath.
  576. % Note that we must use cshow for this, because we
  577. % can't parse multi-byte strings any other way.
  578. % Stack: string xword xchar
  579. { pop pop (x) dup 0 3 index put false charpath
  580. % Stack: xword xchar ccode
  581. 3 copy 32 eq { add } { exch pop } ifelse 0 Vexch rmoveto pop
  582. }
  583. 4 -1 roll cshow pop pop
  584. textrenderingprocs TextRenderingMode get exec
  585. }
  586. }
  587. ifelse
  588. }
  589. ifelse /Show gput
  590. } bdef
  591. /showfirst { setshowstate Show } def
  592. /Tj {
  593. 0 0 moveto Show settextposition
  594. } bdef
  595. /' { T* Tj } bdef
  596. /" { exch Tc exch Tw T* Tj } bdef
  597. /TJ {
  598. 0 0 moveto {
  599. dup type /stringtype eq {
  600. Show
  601. } { -1000 div
  602. currentfont /ScaleMatrix .knownget { 0 get mul } if
  603. 0 Vexch rmoveto
  604. } ifelse
  605. } forall settextposition
  606. } bdef
  607. /tf { setfillstate currentpoint fill moveto } bdef
  608. /tn { currentpoint newpath moveto } bdef % Obsolete, never used.
  609. % For stroking characters, temporarily restore the graphics CTM so that
  610. % the line width will be transformed properly.
  611. /Tmatrix matrix def
  612. /tS
  613. { setstrokestate
  614. currentpoint //Tmatrix currentmatrix TextSaveMatrix setmatrix stroke
  615. setmatrix moveto
  616. } bdef
  617. /tB { gsave tf grestore tS } bdef
  618. % This does the wrong thing if there have been multiple text operations
  619. % within a single BT/ET pair, but it's a start.
  620. /tW { } bdef
  621. end readonly put % GS_PDF_ProcSet
  622. .setglobal