pdf_ops.ps 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522
  1. % Copyright (C) 1994, 2000 Aladdin Enterprises. All rights reserved.
  2. %
  3. % This file is part of AFPL Ghostscript.
  4. %
  5. % AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author or
  6. % distributor accepts any responsibility for the consequences of using it, or
  7. % for whether it serves any particular purpose or works at all, unless he or
  8. % she says so in writing. Refer to the Aladdin Free Public License (the
  9. % "License") for full details.
  10. %
  11. % Every copy of AFPL Ghostscript must include a copy of the License, normally
  12. % in a plain ASCII text file named PUBLIC. The License grants you the right
  13. % to copy, modify and redistribute AFPL Ghostscript, but only under certain
  14. % conditions described in the License. Among other things, the License
  15. % requires that the copyright notice and this notice be preserved on all
  16. % copies.
  17. % $Id: pdf_ops.ps,v 1.17.2.1 2001/12/22 07:34:23 masata-y Exp $
  18. % Definitions for most of the PDF operators.
  19. .currentglobal true .setglobal
  20. % Define pdfmark. Don't allow it to be bound in.
  21. % Also don't define it in systemdict, because this leads some Adobe code
  22. % to think this interpreter is a distiller.
  23. % (If this interpreter really is a distiller, don't do this.)
  24. systemdict /pdfmark known not
  25. { userdict /pdfmark { cleartomark } bind put } if
  26. userdict /GS_PDF_ProcSet 127 dict dup begin
  27. % ---------------- Abbreviations ---------------- %
  28. /bdef { bind def } bind def
  29. % ---------------- Graphics state stack ---------------- %
  30. % PDF adds a number of parameters to the graphics state.
  31. % We implement this by pushing and popping a dictionary
  32. % each time we do a PDF gsave or grestore.
  33. % The keys in this dictionary are as follows:
  34. % self % identifies the dictionary as one of ours
  35. % ClipRect % (optional)
  36. % Show
  37. % TextSaveMatrix % matrix at time of BT (iff within BT/ET)
  38. % (The following correspond directly to PDF state parameters.)
  39. % AlphaIsShape
  40. % FillConstantAlpha
  41. % FillColor
  42. % FillColorSpace
  43. % FillOverprint
  44. % SoftMask
  45. % StrokeConstantAlpha
  46. % StrokeColor
  47. % StrokeColorSpace
  48. % StrokeOverprint
  49. % TextSpacing
  50. % TextHScaling
  51. % Leading
  52. % TextFont
  53. % TextLineMatrix
  54. % TextMatrix
  55. % TextRise
  56. % TextRenderingMode
  57. % WordSpacing
  58. /nodict 1 dict def
  59. nodict /self { //nodict } executeonly put
  60. nodict readonly pop
  61. /dictbeginpage { % <initialdict> dictbeginpage -
  62. //nodict 20 dict .copydict begin { def } forall
  63. graphicsbeginpage textbeginpage
  64. } bdef
  65. /endpage { % - endpage -
  66. showpage end
  67. } bdef
  68. /graphicsbeginpage {
  69. initgraphics
  70. currentdict /ClipRect .knownget { aload pop rectclip } if
  71. 0 g 0 G false op false OP 0 OPM
  72. 1 ca 1 CA null SMask false AIS /Compatible BM true TK
  73. } bdef
  74. /gput % <value> <key> gput -
  75. { exch currentdict //nodict eq { /self dup load end 5 dict begin def } if
  76. % If we're in a Level 1 system, we need to grow the
  77. % dictionary explicitly.
  78. currentdict length currentdict maxlength ge %eq
  79. { currentdict dup length 3 mul 2 idiv 1 add dict .copydict end begin
  80. }
  81. if def
  82. } bdef
  83. /q {
  84. gsave //nodict begin
  85. } bdef
  86. % Some PDF files have excess Q operators!
  87. /Q {
  88. currentdict /self .knownget { exec //nodict eq { end grestore } if } if
  89. } bdef
  90. % ---------------- Color setting ---------------- %
  91. /fcput % <color> <colorspace> fcput -
  92. { /FillColorSpace gput /FillColor gput
  93. } bdef
  94. /scput % <color> <colorspace> scput -
  95. { /StrokeColorSpace gput /StrokeColor gput
  96. } bdef
  97. /csdevgray [/DeviceGray] readonly def
  98. /csdevrgb [/DeviceRGB] readonly def
  99. /csdevcmyk [/DeviceCMYK] readonly def
  100. /cspattern [/Pattern] readonly def
  101. /nullpattern1 mark
  102. /PatternType 1 /PaintType 1 /TilingType 3 /BBox [0 0 0 0]
  103. /XStep 1 /YStep 1 /PaintProc { }
  104. .dicttomark readonly def
  105. /nullpattern2 nullpattern1 dup length dict copy readonly def
  106. % Each entry in the color space dictionary is a procedure of the form
  107. % <cspace> -proc- <cspace> <initial-color>
  108. /CSdict mark
  109. /DeviceGray { pop //csdevgray 0 } bind
  110. /DeviceRGB { pop //csdevrgb [0 0 0] cvx } bind
  111. /DeviceCMYK { pop //csdevcmyk [0 0 0 1] cvx } bind
  112. /CIEBasedA { 0 } bind
  113. /CIEBasedABC { [0 0 0] cvx } bind
  114. /ICCBased { [ 1 index 1 oget /N get { 0 } repeat ] cvx } bind
  115. /Separation { 1 } bind
  116. /DeviceN { % What is the correct value??
  117. [ 1 index 1 get length { 1 } repeat ] cvx
  118. } bind
  119. /Indexed { 0 } bind
  120. /Pattern {
  121. dup type /nametype eq 1 index length 1 eq or {
  122. pop //cspattern //nullpattern1 matrix makepattern
  123. } {
  124. //nullpattern2 matrix makepattern 1 index 1 get csset
  125. % Stack: patternspace nullpattern basecolor basespace
  126. pop [ 3 1 roll dup type /arraytype eq { aload pop } if
  127. counttomark -1 roll ] cvx
  128. } ifelse
  129. } bind
  130. .dicttomark readonly def
  131. /csset % <cspace> csset <color> <cspace>
  132. { dup dup type /nametype ne { 0 get } if //CSdict exch get exec exch
  133. } bdef
  134. /g { //csdevgray fcput } bdef
  135. /G { //csdevgray scput } bdef
  136. /rg { 3 array astore cvx //csdevrgb fcput } bdef
  137. /RG { 3 array astore cvx //csdevrgb scput } bdef
  138. /k { 4 array astore cvx //csdevcmyk fcput } bdef
  139. /K { 4 array astore cvx //csdevcmyk scput } bdef
  140. /cs { csset fcput } bdef
  141. /CS { csset scput } bdef
  142. /ri { pop } bdef
  143. % We have to break up sc according to the number of operands.
  144. /sc1 { /FillColor gput } bdef
  145. /SC1 { /StrokeColor gput } bdef
  146. % We have to avoid storing into a color array associated with an outer
  147. % gsave level, so we do a kind of "copy on write".
  148. /sc* {
  149. currentdict /FillColor .knownget {
  150. astore pop
  151. } {
  152. /FillColor load length array astore cvx /FillColor gput
  153. } ifelse
  154. } bdef
  155. /SC* {
  156. currentdict /StrokeColor .knownget {
  157. astore pop
  158. } {
  159. /StrokeColor load length array astore cvx /StrokeColor gput
  160. } ifelse
  161. } bdef
  162. % ---------------- Overprint/transparency setting ---------------- %
  163. /op { /FillOverprint gput } bdef
  164. /OP { /StrokeOverprint gput } bdef
  165. /OPM {
  166. /.setoverprintmode where { pop .setoverprintmode } { pop } ifelse
  167. } bdef
  168. /ca { /FillConstantAlpha gput } bdef
  169. /CA { /StrokeConstantAlpha gput } bdef
  170. /SMask { /SoftMask gput } bdef
  171. /AIS { /AlphaIsShape gput } bdef
  172. /BM {
  173. /.setblendmode where {
  174. pop [ exch dup type /nametype ne { aload pop } if /Normal ] {
  175. { .setblendmode } .internalstopped not { exit } if pop
  176. } forall
  177. } {
  178. pop
  179. } ifelse
  180. } bdef
  181. /TK {
  182. /.settextknockout where { pop .settextknockout } { pop } ifelse
  183. } bdef
  184. % ---------------- Color installation ---------------- %
  185. % Establish a given color (and color space) as current.
  186. /.settransparencyparams { % <alpha> <smask> .settransparencyparams -
  187. /.begintransparencymask where {
  188. pop AlphaIsShape {
  189. 1 .setopacityalpha 0 .inittransparencymask exch .setshapealpha 1
  190. } {
  191. 1 .setshapealpha 1 .inittransparencymask exch .setopacityalpha 0
  192. } ifelse
  193. % Set the soft mask by rendering the XObject. Doing this every time
  194. % is obviously very inefficient; we'll improve it later.
  195. .settransparencymask
  196. } {
  197. pop pop
  198. } ifelse
  199. } bdef
  200. /.settransparencymask { % <paramdict> <masknum> .settransparencymask -
  201. exch dup null eq {
  202. pop .inittransparencymask
  203. } {
  204. dup /Draw get exec
  205. } ifelse
  206. } bdef
  207. % (Non-mask) images must execute setfillblend.
  208. /setfillblend {
  209. FillOverprint setoverprint
  210. FillConstantAlpha SoftMask .settransparencyparams
  211. } def
  212. /setfillstate {
  213. FillColor FillColorSpace setgcolor setfillblend
  214. } def
  215. /setstrokestate {
  216. StrokeColor StrokeColorSpace setgcolor StrokeOverprint setoverprint
  217. StrokeConstantAlpha SoftMask .settransparencyparams
  218. } def
  219. /Cdict 15 dict dup begin % <color...> <colorspace> -proc- -
  220. /DeviceGray { pop setgray } bdef
  221. /DeviceRGB { pop setrgbcolor } bdef
  222. /DeviceCMYK { pop setcmykcolor } bdef
  223. /CIEBasedA
  224. { dup currentcolorspace eq { pop } { setcolorspace } ifelse setcolor } bdef
  225. /CIEBasedABC /CIEBasedA load def
  226. /CIEBasedDEF /CIEBasedA load def
  227. /CIEBasedDEFG /CIEBasedA load def
  228. /ICCBased /CIEBasedA load def
  229. /Separation /CIEBasedA load def
  230. /DeviceN /CIEBasedA load def
  231. /Indexed /CIEBasedA load def
  232. /Pattern
  233. { dup currentcolorspace eq { pop } { setcolorspace } ifelse
  234. dup /Matrix .knownget not { matrix } if
  235. gsave DefaultMatrix setmatrix makepattern grestore setcolor
  236. } bdef
  237. end def
  238. /setgcolor % (null | <color...>) <colorspace> setgcolor -
  239. { 1 index null eq
  240. { pop pop }
  241. { dup 0 get //Cdict exch get exec }
  242. ifelse
  243. } bdef
  244. /fsexec % <fillop|strokeop> fsexec -
  245. { % Preserve the current point, if any.
  246. { currentpoint } stopped
  247. { $error /newerror false put cvx exec }
  248. { 3 -1 roll cvx exec moveto }
  249. ifelse
  250. } bdef
  251. % ---------------- Path painting and clipping ---------------- %
  252. /S { setstrokestate /stroke fsexec } bdef
  253. /f { setfillstate /fill fsexec } bdef
  254. /f* { setfillstate /eofill fsexec } bdef
  255. /n { newpath } bdef % don't allow n to get bound in
  256. /s { closepath S } bdef
  257. /B { gsave setfillstate fill grestore S } bdef
  258. /b { closepath B } bdef
  259. /B* { gsave setfillstate eofill grestore S } bdef
  260. /b* { closepath B* } bdef
  261. % Clipping:
  262. /Wdict 4 dict dup begin
  263. /S { gsave setstrokestate stroke grestore n } bdef
  264. /f { gsave setfillstate fill grestore n } bdef
  265. /f* { gsave setfillstate eofill grestore n } bdef
  266. /n { end clip newpath } bdef
  267. end readonly def
  268. /W { //Wdict begin } bdef
  269. /W*dict 4 dict dup begin
  270. Wdict { def } forall
  271. /n { end eoclip newpath } bdef
  272. end readonly def
  273. /W* { //W*dict begin } bdef
  274. % ---------------- Text control ---------------- %
  275. /textbeginpage
  276. { /TextSpacing 0 def % 0 Tc
  277. /TextLeading 0 def % 0 TL
  278. /TextRenderingMode 0 def % 0 Tr
  279. /TextRise 0 def % 0 Ts
  280. /WordSpacing 0 def % 0 Tw
  281. /TextHScaling 1.0 def % 100 Tz
  282. /TextFont null def
  283. /Show { showfirst } def
  284. } bdef
  285. % Contrary to the statement in the PDF manual, BT and ET *can* be nested,
  286. % if the CharProc for a Type 3 font does a BT/ET itself.
  287. % Since we always call the CharProc inside a q/Q, we simply ensure that
  288. % the text state is saved and restored like the rest of the extended
  289. % graphics state.
  290. /settextmatrix {
  291. TextMatrix concat
  292. TextHScaling 1 ne { TextHScaling 1 scale } if
  293. TextRise 0 ne { 0 TextRise translate } if
  294. TextFont dup null eq { pop } { setfont } ifelse
  295. } bdef
  296. /settextstate {
  297. % The text state can be set even outside BT/ET.
  298. currentdict /TextSaveMatrix known {
  299. TextSaveMatrix setmatrix settextmatrix
  300. } if
  301. } bdef
  302. /settextposition {
  303. % Update the TextMatrix translation.
  304. gsave TextSaveMatrix setmatrix
  305. currentpoint TextMatrix 4 2 getinterval astore pop
  306. % We would like to do "grestore currentpoint translate"
  307. % here, but some PDF files set a singular text matrix
  308. % (0 0 0 0 <x> <y> Tm), so we can't do this.
  309. TextTempMatrix identmatrix setmatrix currentpoint
  310. grestore
  311. TextTempMatrix currentmatrix 4 2 getinterval astore pop
  312. TextTempMatrix setmatrix
  313. } bdef
  314. /BT {
  315. currentdict /TextLineMatrix .knownget
  316. { identmatrix pop TextMatrix identmatrix pop }
  317. { matrix /TextLineMatrix gput matrix /TextMatrix gput }
  318. ifelse
  319. { showfirst } /Show gput
  320. currentdict /TextSaveMatrix .knownget not {
  321. matrix dup /TextSaveMatrix gput
  322. } if currentmatrix pop settextmatrix
  323. matrix /TextTempMatrix gput % see settextposition
  324. } bdef
  325. /ET {
  326. TextRenderingMode 4 ge { clip newpath } if
  327. TextSaveMatrix setmatrix
  328. currentdict /TextSaveMatrix undef
  329. } bdef
  330. /Tc { /TextSpacing gput { showfirst } /Show gput } bdef
  331. /TL { /TextLeading gput } bdef
  332. /Tr { /TextRenderingMode gput { showfirst } /Show gput } bdef
  333. /Ts { /TextRise gput settextstate } bdef
  334. /Tw { /WordSpacing gput { showfirst } /Show gput } bdef
  335. /Tz { 100 div /TextHScaling gput settextstate} bdef
  336. % ---------------- Font control ---------------- %
  337. /Tf { % <font> <scale> Tf -
  338. dup 1 eq { pop } { scalefont } ifelse
  339. /TextFont gput settextstate
  340. } bdef
  341. % Read a CFF font.
  342. /FRD % <resname> <file> FRD -
  343. { /FontSetInit /ProcSet findresource begin true ReadData
  344. } bdef
  345. % Copy a font, removing its FID. If changed is true, also remove
  346. % the UniqueID and XUID, if any. If the original dictionary doesn't have
  347. % the keys being removed, don't copy it.
  348. /.copyfontdict % <font> <changed> .copyfontdict <dict>
  349. { 1 index /FID known
  350. 1 index { 2 index /UniqueID known or 2 index /XUID known or } if
  351. { % We add 1 to the length just in case the original
  352. % didn't have a FID.
  353. exch dup length 1 add dict exch
  354. { % Stack: changed newfont key value
  355. 1 index /FID eq 4 index
  356. { 2 index /UniqueID eq or 2 index /XUID eq or }
  357. if not { 3 copy put } if pop pop
  358. }
  359. forall exch
  360. }
  361. if pop
  362. } bdef
  363. % Insert a new Encoding or Metrics into a font if necessary.
  364. % Return a possibly updated font, and a flag to indicate whether
  365. % the font was actually copied.
  366. /.updatefontmetrics { % <font> <Metrics|null> .updatefontmetrics
  367. % <font'> <copied>
  368. dup null ne {
  369. exch true .copyfontdict dup /Metrics 4 -1 roll put true
  370. } {
  371. pop false
  372. } ifelse
  373. } bdef
  374. /.updatefontencoding { % <font> <Encoding|null> .updatefontencoding
  375. % <font'> <copied>
  376. dup null ne { dup 2 index /Encoding get ne } { false } ifelse {
  377. exch false .copyfontdict dup /Encoding 4 -1 roll put true
  378. } {
  379. pop false
  380. } ifelse
  381. } bdef
  382. /.updatefont { % <font> <Encoding|null> <Metrics|null> .updatefont
  383. % <font'> <copied>
  384. 3 -1 roll exch .updatefontmetrics
  385. % Stack: enc|null font' copied
  386. 3 1 roll exch .updatefontencoding 3 -1 roll or
  387. } bdef
  388. % ---------------- Text positioning ---------------- %
  389. /Td {
  390. TextLineMatrix transform TextLineMatrix 4 2 getinterval astore pop
  391. TextLineMatrix TextMatrix copy pop settextstate
  392. } bdef
  393. /TD { dup neg /TextLeading gput Td } bdef
  394. /T* { 0 TextLeading neg Td } bdef
  395. /Tm {
  396. TextLineMatrix astore TextMatrix copy pop settextstate
  397. } bdef
  398. % ---------------- Text painting ---------------- %
  399. /Vexch {
  400. rootfont /WMode .knownget { 1 eq { exch } if } if
  401. } bind def
  402. /textrenderingprocs [ % (0 is handled specially)
  403. % Painting-only modes
  404. { tf } { tS } { tB } { tn }
  405. % Clipping modes
  406. { gsave tf grestore tW }
  407. { gsave tS grestore tW }
  408. { gsave tB grestore tW }
  409. { tW }
  410. ] readonly def
  411. /setshowstate
  412. { WordSpacing 0 eq TextSpacing 0 eq and
  413. { TextRenderingMode 0 eq
  414. { { setfillstate show } }
  415. { { false charpath textrenderingprocs TextRenderingMode get exec } }
  416. ifelse
  417. }
  418. { TextRenderingMode 0 eq
  419. { WordSpacing 0 eq
  420. { { setfillstate TextSpacing 0 Vexch 3 -1 roll ashow } }
  421. { TextSpacing 0 eq
  422. { { setfillstate WordSpacing 0 Vexch 32 4 -1 roll widthshow } }
  423. { { setfillstate WordSpacing 0 Vexch 32
  424. TextSpacing 0 Vexch 6 -1 roll awidthshow } }
  425. ifelse
  426. }
  427. ifelse
  428. }
  429. { { WordSpacing TextSpacing
  430. % Implement the combination of t3 and false charpath.
  431. % Note that we must use cshow for this, because we
  432. % can't parse multi-byte strings any other way.
  433. % Stack: string xword xchar
  434. { pop pop (x) dup 0 3 index put false charpath
  435. % Stack: xword xchar ccode
  436. 3 copy 32 eq { add } { exch pop } ifelse 0 Vexch rmoveto pop
  437. }
  438. 4 -1 roll cshow pop pop
  439. textrenderingprocs TextRenderingMode get exec
  440. }
  441. }
  442. ifelse
  443. }
  444. ifelse /Show gput
  445. } bdef
  446. /showfirst { setshowstate Show } def
  447. /Tj {
  448. 0 0 moveto Show settextposition
  449. } bdef
  450. /' { T* Tj } bdef
  451. /" { exch Tc exch Tw T* Tj } bdef
  452. /TJ {
  453. 0 0 moveto {
  454. dup type /stringtype eq {
  455. Show
  456. } { -1000 div
  457. currentfont /ScaleMatrix .knownget { 0 get mul } if
  458. 0 Vexch rmoveto
  459. } ifelse
  460. } forall settextposition
  461. } bdef
  462. /tf { setfillstate currentpoint fill moveto } bdef
  463. /tn { currentpoint newpath moveto } bdef
  464. % For stroking characters, temporarily restore the graphics CTM so that
  465. % the line width will be transformed properly.
  466. /Tmatrix matrix def
  467. /tS
  468. { setstrokestate
  469. currentpoint //Tmatrix currentmatrix TextSaveMatrix setmatrix stroke
  470. setmatrix moveto
  471. } bdef
  472. /tB { gsave tf grestore tS } bdef
  473. % This does the wrong thing if there have been multiple text operations
  474. % within a single BT/ET pair, but it's a start.
  475. /tW { } bdef
  476. end readonly put % GS_PDF_ProcSet
  477. .setglobal