星火微课系统客户端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

pdf_ops.ps 29KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974
  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 10687 2010-02-02 07:23:57Z alexcher $
  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. % (The following is cached information derived from other graphics state params)
  57. % FontMatrixNonHV % TextFont.FontMatrix alters horz/vert glyph advance vector direction
  58. /nodict 1 dict def
  59. nodict /self { //nodict } executeonly put % to avoid recursion in dumps
  60. nodict readonly pop
  61. /dictbeginpage { % <initialdict> dictbeginpage -
  62. 20 dict copy dup begin
  63. 1 packedarray cvx executeonly /self exch def
  64. graphicsbeginpage textbeginpage
  65. } bdef
  66. /endpage { % - endpage -
  67. showpage end
  68. } bdef
  69. /graphicsbeginpage {
  70. initgraphics
  71. //true .setaccuratecurves
  72. currentdict /ClipRect knownoget { aload pop rectclip } if
  73. 0 g 0 G false op false OP 0 OPM
  74. 1 ca 1 CA null SMask false AIS /Compatible BM true TK
  75. } bdef
  76. /gput % <value> <key> gput -
  77. { exch currentdict //nodict eq { /self dup load end 5 dict begin def } if
  78. def
  79. } bdef
  80. /q {
  81. gsave //nodict begin
  82. PDFusingtransparency {.pushextendedgstate cvx} if
  83. } bdef
  84. % Some PDF files have excess Q operators!
  85. /Q {
  86. PDFusingtransparency {.popextendedgstate cvx} if
  87. currentdict /self .knownget {
  88. exec //nodict eq {
  89. end
  90. % Restore graphics state, but do not modify path. Paths are not part
  91. % of the PDF graphics state; see 4.4.1 of PDF reference 3rd ed.
  92. % Collecting the path with one ctm and re-playing it with another ctm
  93. % transforms the path exactly as PDF needs.
  94. .getpath grestore newpath { exec } forall
  95. //false
  96. } {
  97. //true
  98. } ifelse
  99. } {
  100. //true % formaterror -- not a gsave dict
  101. } ifelse
  102. { (\n **** File has unbalanced q/Q operators \(too many Q's\) ****\n)
  103. pdfformaterror
  104. } if
  105. } bdef
  106. % Save PDF gstate
  107. /qstate { % - qstate <qstate>
  108. gstate
  109. } bdef
  110. % Set PDF gstate
  111. /setqstate { % <qstate> setqstate -
  112. { matrix setmatrix //false upath } stopped {
  113. pop setgstate newpath
  114. } {
  115. % Save the CTM, set identity during the uappend, then set the CTM
  116. exch setgstate matrix currentmatrix matrix setmatrix
  117. exch newpath uappend setmatrix
  118. } ifelse
  119. } bdef
  120. % Save most of graphic state attributes.
  121. % - get-gs-attrs ...
  122. /get-gs-attrs {
  123. currentsmoothness
  124. currentflat
  125. currentoverprint
  126. currentstrokeadjust
  127. currentdash
  128. currentmiterlimit
  129. currentlinejoin
  130. currentlinecap
  131. currentlinewidth
  132. currentfont
  133. currentcolor
  134. currentcolorspace
  135. { currentpoint } stopped
  136. matrix currentmatrix
  137. } bdef
  138. % Restore most of graphic state attributes.
  139. % ... get-gs-attrs -
  140. /set-gs-attrs {
  141. setmatrix
  142. { newpath } { moveto } ifelse
  143. setcolorspace
  144. setcolor
  145. setfont
  146. setlinewidth
  147. setlinecap
  148. setlinejoin
  149. setmiterlimit
  150. setdash
  151. setstrokeadjust
  152. setoverprint
  153. setflat
  154. setsmoothness
  155. } bdef
  156. % ---------------- Color setting ---------------- %
  157. /fcput % <color> <colorspace> fcput -
  158. { /FillColorSpace gput /FillColor gput
  159. } bdef
  160. /scput % <color> <colorspace> scput -
  161. { /StrokeColorSpace gput /StrokeColor gput
  162. } bdef
  163. /csput % <colorspace> csput -
  164. { csset 2 copy fcput scput
  165. } bdef
  166. /csdevgray [/DeviceGray] readonly def
  167. /csdevrgb [/DeviceRGB] readonly def
  168. /csdevcmyk [/DeviceCMYK] readonly def
  169. /cspattern [/Pattern] readonly def
  170. /nullpatternproc { pop } bdef
  171. /nullpattern mark
  172. /PatternType 1 /PaintType 1 /TilingType 3 /BBox [0 0 1 1]
  173. /XStep 1 /YStep 1 /PaintProc //nullpatternproc
  174. .dicttomark readonly def
  175. % Each entry in the color space dictionary is a procedure of the form
  176. % <cspace> -proc- <cspace> <initial-color>
  177. /CSdict mark
  178. /DeviceGray { pop //csdevgray 0 } bind
  179. /DeviceRGB { pop //csdevrgb [0 0 0] cvx } bind
  180. /DeviceCMYK { pop //csdevcmyk [0 0 0 1] cvx } bind
  181. /CIEBasedA { 0 } bind
  182. /CIEBasedABC { [0 0 0] cvx } bind
  183. /ICCBased { [ 1 index 1 oget /N get { 0 } repeat ] cvx } bind
  184. /Separation { 1 } bind
  185. /DeviceN { % What is the correct value??
  186. [ 1 index 1 get length { 1 } repeat ] cvx
  187. } bind
  188. /Indexed { 0 } bind
  189. /Pattern {
  190. dup type /nametype eq 1 index length 1 eq or {
  191. pop //cspattern //nullpattern matrix makepattern
  192. } {
  193. //nullpattern matrix makepattern 1 index 1 get csset
  194. % Stack: patternspace nullpattern basecolor basespace
  195. pop [ 3 1 roll dup type /arraytype eq { aload pop } if
  196. counttomark -1 roll ] cvx
  197. } ifelse
  198. } bind
  199. .dicttomark readonly def
  200. /csset % <cspace> csset <color> <cspace>
  201. { dup dup type /nametype ne { 0 get } if //CSdict exch get exec exch
  202. } bdef
  203. /g { //csdevgray fcput } bdef
  204. /G { //csdevgray scput } bdef
  205. /rg { 3 array astore cvx //csdevrgb fcput } bdef
  206. /RG { 3 array astore cvx //csdevrgb scput } bdef
  207. /k { 4 array astore cvx //csdevcmyk fcput } bdef
  208. /K { 4 array astore cvx //csdevcmyk scput } bdef
  209. /cs { csset fcput } bdef
  210. /CS { csset scput } bdef
  211. /ri { //.renderingintentdict exch .knownget { .setrenderingintent } if } bdef
  212. % We have to break up sc according to the number of operands.
  213. /sc1 { /FillColor gput } bdef
  214. /SC1 { /StrokeColor gput } bdef
  215. % We have to avoid storing into a color array associated with an outer
  216. % gsave level, so we do a kind of "copy on write".
  217. /sc* {
  218. currentdict /FillColor .knownget {
  219. astore pop
  220. } {
  221. /FillColor load
  222. % FillColor may contain either a single value or an array.
  223. dup type /arraytype eq { length }{ pop 1 } ifelse
  224. array astore cvx /FillColor gput
  225. } ifelse
  226. } bdef
  227. /SC* {
  228. currentdict /StrokeColor .knownget {
  229. astore pop
  230. } {
  231. /StrokeColor load
  232. % StrokeColor may contain either a single value or an array.
  233. dup type /arraytype eq { length }{ pop 1 } ifelse
  234. array astore cvx /StrokeColor gput
  235. } ifelse
  236. } bdef
  237. % ---------------- Overprint/transparency setting ---------------- %
  238. /op { /FillOverprint gput } bdef
  239. /OP { /StrokeOverprint gput } bdef
  240. /OPM {
  241. /.setoverprintmode where { pop .setoverprintmode } { pop } ifelse
  242. } bdef
  243. /ca { /FillConstantAlpha gput } bdef
  244. /CA { /StrokeConstantAlpha gput } bdef
  245. /SMask { /SoftMask gput } bdef
  246. /AIS { /AlphaIsShape gput } bdef
  247. /BM {
  248. /.setblendmode where {
  249. pop [ exch dup type /nametype ne { aload pop } if /Normal ] {
  250. { .setblendmode } .internalstopped not { exit } if pop
  251. } forall
  252. } {
  253. pop
  254. } ifelse
  255. } bdef
  256. /TK {
  257. /.settextknockout where { pop .settextknockout } { pop } ifelse
  258. } bdef
  259. % ---------------- Color installation ---------------- %
  260. % Establish a given color (and color space) as current.
  261. /.settransparencyparams { % <alpha> <smask> .settransparencyparams -
  262. PDFusingtransparency {
  263. /.begintransparencygroup where {
  264. pop AlphaIsShape {
  265. 1 .setopacityalpha exch .setshapealpha 1
  266. } {
  267. 1 .setshapealpha exch .setopacityalpha 0
  268. } ifelse
  269. % Set the soft mask by rendering the XObject. Doing this every time
  270. % is obviously very inefficient; we'll improve it later.
  271. .settransparencymask
  272. } {
  273. pop pop
  274. } ifelse
  275. } {
  276. pop pop
  277. } ifelse
  278. } bdef
  279. /.settransparencymask { % <paramdict> <masknum> .settransparencymask -
  280. exch dup null eq {
  281. PDFusingtransparency {
  282. pop pop
  283. } {
  284. dup /Draw get exec
  285. } ifelse
  286. } {
  287. dup /Draw get exec
  288. } ifelse
  289. } bdef
  290. % (Non-mask) images must execute setfillblend.
  291. /setfillblend {
  292. FillOverprint setoverprint
  293. FillConstantAlpha SoftMask .settransparencyparams
  294. } def
  295. /setfillstate {
  296. FillColor FillColorSpace setgcolor setfillblend
  297. } def
  298. /setstrokestate {
  299. StrokeColor StrokeColorSpace setgcolor StrokeOverprint setoverprint
  300. StrokeConstantAlpha SoftMask .settransparencyparams
  301. } def
  302. /Cdict 15 dict dup begin % <color...> <colorspace> -proc- -
  303. /DeviceGray { pop setgray } bdef
  304. /DeviceRGB { pop setrgbcolor } bdef
  305. /DeviceCMYK { pop setcmykcolor } bdef
  306. /CIEBasedA { setgcolorspace setcolor } bdef
  307. /CIEBasedABC /CIEBasedA load def
  308. /CIEBasedDEF /CIEBasedA load def
  309. /CIEBasedDEFG /CIEBasedA load def
  310. /ICCBased /CIEBasedA load def
  311. /Separation /CIEBasedA load def
  312. /DeviceN /CIEBasedA load def
  313. /Indexed /CIEBasedA load def
  314. /Pattern
  315. { setgcolorspace
  316. % Since multiple patterns may share
  317. % same data stream, we need to ensure
  318. % that the stream is at 0 position.
  319. % Making this consistently with resolveshading,
  320. % which applies ReusableStreamDecode filter
  321. % to the PS stream, which represents the
  322. % PDF stream in dynamics.
  323. dup /Shading knownoget {
  324. dup /ShadingType oget 4 ge {
  325. /DataSource knownoget {
  326. dup type /filetype eq {
  327. 0 setfileposition
  328. } {
  329. pop
  330. } ifelse
  331. } if
  332. } {
  333. pop
  334. } ifelse
  335. } if
  336. % Associate pattern instance with the default qstate for the context.
  337. % A single pattren object can be reused in several contexts.
  338. dup DefaultQstate .knownget {
  339. exch pop
  340. } {
  341. % But don't update read-only initial null pattern.
  342. dup /PaintProc .knownget { //nullpatternproc ne } { //true } ifelse {
  343. dup dup /Matrix knownoget not { { 1 0 0 1 0 0 } } if
  344. gsave DefaultQstate setqstate makepattern grestore
  345. dup 3 1 roll
  346. DefaultQstate exch put
  347. } if
  348. } ifelse
  349. setcolor
  350. } bdef
  351. end def
  352. /setgcolor % (null | <color...>) <colorspace> setgcolor -
  353. { 1 index null eq
  354. { pop pop }
  355. { dup 0 get //Cdict exch get exec }
  356. ifelse
  357. } bdef
  358. % Compare the old and new color spaces in an attempt to avoid expensive
  359. % reloads of CIEBased color spaces.
  360. /PCSdict 15 dict dup begin % <colorspace> -proc- <colorspace|pdfcspace>
  361. /CIEBasedA { dup 1 get /PDFColorSpace .knownget { exch pop } if } bdef
  362. /CIEBasedABC /CIEBasedA load def
  363. /CIEBasedDEF /CIEBasedA load def
  364. /CIEBasedDEFG /CIEBasedA load def
  365. /Indexed {
  366. dup 1 get dup pdfcolorspace 2 copy ne { 3 1 roll } if pop pop
  367. } bdef
  368. end def
  369. /pdfcolorspace { % <colorspace> pdfcolorspace <colorspace|pdfcspace>
  370. dup type /arraytype eq {
  371. //PCSdict 1 index 0 get .knownget { exec } if
  372. } if
  373. } bdef
  374. /setgcolorspace { % <colorspace> setgcolorspace -
  375. dup pdfcolorspace currentcolorspace pdfcolorspace eq {
  376. pop
  377. } {
  378. setcolorspace
  379. } ifelse
  380. } bdef
  381. /fsexec % <fillop|strokeop> fsexec -
  382. {
  383. SoftMask //null ne {
  384. mark /Subtype /Group /Isolated true .dicttomark pathbbox .begintransparencygroup
  385. } if
  386. cvx exec
  387. SoftMask //null ne {
  388. .endtransparencygroup
  389. } if
  390. } bdef
  391. % ---------------- Path painting and clipping ---------------- %
  392. /S {
  393. OFFlevels length 0 eq {
  394. setstrokestate /stroke fsexec
  395. } {
  396. newpath
  397. } ifelse
  398. } bdef
  399. /f {
  400. OFFlevels length 0 eq {
  401. setfillstate /fill fsexec
  402. } {
  403. newpath
  404. } ifelse
  405. } bdef
  406. /f* {
  407. OFFlevels length 0 eq {
  408. setfillstate /eofill fsexec
  409. } {
  410. newpath
  411. } ifelse
  412. } bdef
  413. /n { newpath } bdef % don't allow n to get bound in
  414. /s { closepath S } bdef
  415. /B {
  416. OFFlevels length 0 eq {
  417. gsave setfillstate fill grestore
  418. setstrokestate /stroke fsexec
  419. } {
  420. newpath
  421. } ifelse
  422. } bdef
  423. /b { closepath B } bdef
  424. /B* {
  425. OFFlevels length 0 eq {
  426. gsave setfillstate eofill grestore
  427. setstrokestate /stroke fsexec
  428. } {
  429. newpath
  430. } ifelse
  431. } bdef
  432. /b* { closepath B* } bdef
  433. % Clipping:
  434. /Wdict 4 dict dup begin
  435. /S { OFFlevels length 0 eq { gsave setstrokestate stroke grestore } if n } bdef
  436. /f { OFFlevels length 0 eq { gsave setfillstate fill grestore } if n } bdef
  437. /f* { OFFlevels length 0 eq { gsave setfillstate eofill grestore } if n } bdef
  438. /n { end { currentpoint } stopped not { pop pop clip } if newpath } bdef
  439. end readonly def
  440. /W { //Wdict begin } bdef
  441. /W*dict 4 dict dup begin
  442. Wdict { def } forall
  443. /n { end { currentpoint } stopped not { pop pop eoclip } if newpath } bdef
  444. end readonly def
  445. /W* { //W*dict begin } bdef
  446. % ---------------- Text control ---------------- %
  447. /textbeginpage
  448. { /TextSpacing 0 def % 0 Tc
  449. /TextLeading 0 def % 0 TL
  450. /TextRenderingMode 0 def % 0 Tr
  451. /TextRise 0 def % 0 Ts
  452. /WordSpacing 0 def % 0 Tw
  453. /TextHScaling 1.0 def % 100 Tz
  454. /TextFont null def
  455. /FontMatrixNonHV //false def
  456. /Show { showfirst } def
  457. } bdef
  458. % Contrary to the statement in the PDF manual, BT and ET *can* be nested,
  459. % if the CharProc for a Type 3 font does a BT/ET itself.
  460. % Since we always call the CharProc inside a q/Q, we simply ensure that
  461. % the text state is saved and restored like the rest of the extended
  462. % graphics state.
  463. /settextmatrix {
  464. TextMatrix concat
  465. TextHScaling 1 ne { TextHScaling 1 scale } if
  466. TextRise 0 ne { 0 TextRise translate } if
  467. TextFont dup null eq { pop } { setfont } ifelse
  468. } bdef
  469. /settextstate {
  470. % The text state can be set even outside BT/ET.
  471. currentdict /TextSaveMatrix known {
  472. TextSaveMatrix setmatrix settextmatrix
  473. } if
  474. } bdef
  475. /settextposition {
  476. % Update the TextMatrix translation.
  477. gsave TextSaveMatrix setmatrix
  478. currentpoint TextRise sub TextMatrix 4 2 getinterval astore pop
  479. % We would like to do "grestore currentpoint translate"
  480. % here, but some PDF files set a singular text matrix
  481. % (0 0 0 0 <x> <y> Tm), so we can't do this.
  482. TextTempMatrix identmatrix setmatrix currentpoint
  483. grestore
  484. TextTempMatrix currentmatrix 4 2 getinterval astore pop
  485. TextTempMatrix setmatrix
  486. } bdef
  487. /BT {
  488. currentdict /TextLineMatrix .knownget
  489. { identmatrix pop TextMatrix identmatrix pop }
  490. { matrix /TextLineMatrix gput matrix /TextMatrix gput }
  491. ifelse
  492. { showfirst } /Show gput
  493. currentdict /TextSaveMatrix .knownget not {
  494. matrix dup /TextSaveMatrix gput
  495. } if currentmatrix pop settextmatrix
  496. matrix /TextTempMatrix gput % see settextposition
  497. } bdef
  498. /ET {
  499. TextRenderingMode 4 ge { clip newpath } if
  500. TextSaveMatrix setmatrix
  501. currentdict /TextSaveMatrix undef
  502. } bdef
  503. /Tc { /TextSpacing gput { showfirst } /Show gput } bdef
  504. /TL { /TextLeading gput } bdef
  505. /Tr { dup .settextrenderingmode /TextRenderingMode gput { showfirst } /Show gput } bdef
  506. /Ts { /TextRise gput settextstate } bdef
  507. /Tw { /WordSpacing gput { showfirst } /Show gput } bdef
  508. /Tz { 100 div /TextHScaling gput settextstate} bdef
  509. % ---------------- Font control ---------------- %
  510. % Test if the FontMatrix could transform a horizontal/vertical (depending
  511. % on writing mode) advance vector in glyph space into one with a different
  512. % direction in text space.
  513. % - if FontMatrix = [a b c d tx ty], this condition translates to:
  514. % b != 0 for horizontal writing mode
  515. % c != 0 for vertical writing mode
  516. % - when false, we automatically have wy/x == 0 in text space whenever wy/x == 0
  517. % in glyph space, and can avoid the slow method that is otherwise necessary
  518. % to implement zeroing wy/x cf PDF Ref 5.3.3 "Text space details"
  519. % Worker procedure for testing a single font matrix
  520. /?FontMatrixNonHV { % ?horz <<fontdict>> -- ?horz ?nonhv
  521. /FontMatrix .knownget {
  522. 1 index { 1 } { 2 } ifelse get 0 ne
  523. } {
  524. //false
  525. } ifelse
  526. } bdef
  527. % Worker procedure for recursive checking of font matrices
  528. /?FontMatrixNonHV { % {self} ?horz <<font>> -- {self} ?horz ?nonhv
  529. 2 copy //?FontMatrixNonHV exec { % check the font's own FontMatrix
  530. pop pop //true
  531. } {
  532. % look for descendents/ components
  533. pop % {self} ?horz <<font>>
  534. dup /FontType get
  535. dup 0 eq { % Type 0: look into FDepVector
  536. pop /FDepVector get 2 index % {self} ?horz [fonts..] {testproc}
  537. } {
  538. 9 eq { % Type 9 (CIDFontType 0): check FDArray
  539. /FDArray get //?FontMatrixNonHV
  540. } { % all others: nothing more to check
  541. pop {} {}
  542. } ifelse
  543. } ifelse
  544. %stack: {self} ?horz [fonts..] {testproc}
  545. //false 5 2 roll { % {testproc} false {self} ?horz <<subfont>>
  546. 4 index exec {
  547. 4 -1 roll pop //true 4 1 roll
  548. exit
  549. } if
  550. } forall
  551. %stack: {testproc} ?nonhv {self} ?horz
  552. 4 2 roll exch pop
  553. } ifelse
  554. } bdef
  555. % Main procedure
  556. /?FontMatrixNonHV { % <<rootfont>> -- ?nonhv
  557. //?FontMatrixNonHV exch
  558. % determine WMode
  559. dup /WMode .knownget { 0 eq } { //true } ifelse % {proc} <<rootfont>> ?horz
  560. exch
  561. % call the worker procedure
  562. //?FontMatrixNonHV exec
  563. exch pop exch pop
  564. } bdef
  565. /Tf { % <font> <scale> Tf -
  566. dup 0 eq {
  567. (\n **** Warning: Invalid 0.0 font scale given for Tf ****\n)
  568. pdfformaterror
  569. pop 0.00000001 % handle invalid scale by using a really small value
  570. } if
  571. 1 index type /dicttype ne {
  572. selectfont currentfont
  573. } {
  574. dup 1 eq { pop } { scalefont } ifelse
  575. }
  576. ifelse
  577. dup ?FontMatrixNonHV dup FontMatrixNonHV ne {
  578. /FontMatrixNonHV gput
  579. { showfirst } /Show gput
  580. } {
  581. pop
  582. } ifelse
  583. /TextFont gput settextstate
  584. } bdef
  585. % Copy a font, removing its FID. If changed is true, also remove
  586. % the UniqueID and XUID, if any. If the original dictionary doesn't have
  587. % the keys being removed, don't copy it.
  588. /.copyfontdict % <font> <changed> .copyfontdict <dict>
  589. { 1 index /FID known
  590. 1 index { 2 index /UniqueID known or 2 index /XUID known or } if
  591. { % We add 1 to the length just in case the original
  592. % didn't have a FID.
  593. exch dup length 1 add dict exch
  594. { % Stack: changed newfont key value
  595. 1 index /FID eq 4 index
  596. { 2 index /UniqueID eq or 2 index /XUID eq or }
  597. if not { 3 copy put } if pop pop
  598. }
  599. forall exch
  600. }
  601. if pop
  602. } bdef
  603. % Insert a new Encoding or Metrics into a font if necessary.
  604. % Return a possibly updated font, and a flag to indicate whether
  605. % the font was actually copied.
  606. /.updatefontmetrics { % <font> <Metrics|null> .updatefontmetrics
  607. % <font'> <copied>
  608. dup //null ne {
  609. exch //true .copyfontdict dup /Metrics 4 -1 roll put //true
  610. } {
  611. pop //false
  612. } ifelse
  613. } bdef
  614. /.updatefontencoding { % <font> <Encoding|null> .updatefontencoding
  615. % <font'> <copied>
  616. dup //null ne { dup 2 index /Encoding get ne } { //false } ifelse {
  617. exch //false .copyfontdict dup /Encoding 4 -1 roll put //true
  618. } {
  619. pop //false
  620. } ifelse
  621. } bdef
  622. % Duplicate keys in CharString dictionary according to GlyphMap: <</new_glyph /old_glyph>>
  623. % We have to do this because PDF fonts can associate multiple widths with the same glyph
  624. % but Metrics dictionary works by the glyph name.
  625. /.update_charstring { % <font> <GlyphMap> .update_charstring <font'> <copied>
  626. dup //null ne {
  627. exch //true .copyfontdict % map font
  628. dup dup /CharStrings get % map font font cstr
  629. dup length % map font font cstr len
  630. 4 index length add % map font font cstr len+map_len
  631. dict copy dup begin % map font font cstr'
  632. /CharStrings exch put % map font
  633. exch { % font /new /old
  634. currentdict exch .knownget {
  635. def
  636. } {
  637. currentdict /.notdef .knownget {
  638. def
  639. } {
  640. pop
  641. % The font has no .notdef.
  642. % Could not resolve the conflict,
  643. % but either the font is invalid or the glyph name is never used.
  644. } ifelse
  645. } ifelse
  646. } forall
  647. end //true
  648. } {
  649. pop //false
  650. } ifelse
  651. } bdef
  652. /.updatefont { % <font> <Encoding|null> <Metrics|null> <GlyphMap|null>
  653. % .updatefont <font'> <copied>
  654. 4 2 roll % <Metrics|null> <GlyphMap> <font> <Encoding|null>
  655. .updatefontencoding % <Metrics|null> <GlyphMap> <font> bool
  656. 4 1 roll exch % bool <Metrics|null> <font> <GlyphMap>
  657. .update_charstring % bool <Metrics|null> <font> bool
  658. 3 1 roll exch % bool bool <font> <Metrics|null>
  659. .updatefontmetrics % bool bool <font> bool
  660. 4 2 roll or or % <font> is_copied
  661. } bdef
  662. % ---------------- Text positioning ---------------- %
  663. /Td {
  664. TextLineMatrix transform TextLineMatrix 4 2 getinterval astore pop
  665. TextLineMatrix TextMatrix copy pop settextstate
  666. } bdef
  667. /TD { dup neg /TextLeading gput Td } bdef
  668. /T* { 0 TextLeading neg Td } bdef
  669. /Tm {
  670. TextLineMatrix astore TextMatrix copy pop settextstate
  671. } bdef
  672. % ---------------- Text painting ---------------- %
  673. /Vexch {
  674. rootfont /WMode knownoget { 1 eq { exch } if } if
  675. } bind def
  676. /textrenderingprocs [ % (0 is handled specially)
  677. % Painting-only modes
  678. { tf } { tS } { tB } { tn }
  679. % Clipping modes
  680. { gsave tf grestore tW }
  681. { gsave tS grestore tW }
  682. { gsave tB grestore tW }
  683. { tW }
  684. ] readonly def
  685. /pdfwrite_textrenderingprocs [
  686. { setfillstate show } bind
  687. { setstrokestate
  688. % Need to set the stroke width to a value which gives the correct
  689. % width under pdfwrite. Pdfwrite uses (in text mode) an identity
  690. % CTM, so we need to calculate the stroke width which would result
  691. % if the CTM had been unity.
  692. currentlinewidth dup
  693. matrix defaultmatrix idtransform TextSaveMatrix dtransform
  694. 2 copy eq {
  695. pop
  696. }{
  697. % non-square scaling reduces to Text matrix in pdfwrite , so
  698. % we can ignore it. (wrong answer, but consistent)
  699. pop pop currentlinewidth
  700. }ifelse setlinewidth
  701. show } bind
  702. { gsave 0 .settextrenderingmode
  703. setfillstate dup show currentpoint 3 -1 roll
  704. grestore gsave setstrokestate
  705. false charpath
  706. % We need to make sure the matrix used for the stroke
  707. % and therefore stroke width does not include the
  708. % Text Matrix Tm.
  709. TextSaveMatrix setmatrix
  710. stroke
  711. grestore moveto
  712. } bind
  713. { setfillstate show } bind
  714. { gsave 0 .settextrenderingmode
  715. setfillstate dup show grestore true charpath } bind
  716. { gsave 1 .settextrenderingmode
  717. setstrokestate dup show grestore
  718. true charpath } bind
  719. { gsave 0 .settextrenderingmode
  720. setfillstate dup show grestore gsave dup
  721. setstrokestate false charpath
  722. % We need to make sure the matrix used for the stroke
  723. % and therefore stroke width does not include the
  724. % Text Matrix Tm.
  725. TextSaveMatrix setmatrix
  726. stroke grestore
  727. true charpath } bind
  728. { true charpath } bind
  729. ] readonly def
  730. /setshowstate
  731. { WordSpacing 0 eq TextSpacing 0 eq and FontMatrixNonHV not and
  732. {
  733. currentdevice .devicename /pdfwrite eq
  734. {
  735. pdfwrite_textrenderingprocs TextRenderingMode get
  736. }
  737. {
  738. TextRenderingMode 0 eq {
  739. { setfillstate show }
  740. } {
  741. TextRenderingMode 3 eq {
  742. % Some PDF files execute 'tm' with a singular matrix,
  743. % and then use the text rendering mode 3.
  744. % The graphics library currently cannot handle text
  745. % operations when the CTM is singular.
  746. % Work around this here.
  747. {
  748. matrix currentmatrix dup dup
  749. dup 0 get 0 eq 1 index 1 get 0 eq and {
  750. dup dup 2 get 0 eq { 0 }{ 1 } ifelse 1 put
  751. } if
  752. dup 2 get 0 eq 1 index 3 get 0 eq and {
  753. dup dup 1 get 0 eq { 3 }{ 2 } ifelse 1 put
  754. } if
  755. setmatrix
  756. 2 index setfillstate show % Tr was set to graphic state.
  757. setmatrix
  758. % now set the currentpoint using the original matrix
  759. gsave
  760. setmatrix
  761. false charpath currentpoint newpath
  762. grestore
  763. moveto
  764. }
  765. } {
  766. { false charpath textrenderingprocs TextRenderingMode get exec }
  767. } ifelse
  768. } ifelse
  769. } ifelse
  770. }
  771. { TextRenderingMode 0 eq TextRenderingMode 3 eq or
  772. % Tr was set to graphic state.
  773. { FontMatrixNonHV {
  774. {
  775. setfillstate
  776. [ TextSpacing WordSpacing 3 index
  777. { % str [... weach wword c undef|ythis xthis|undef
  778. exch % will be removed, unless FontMatrix.xx/yy == 0 (FontMatrixNonHV already true)
  779. Vexch pop % str [... weach wword c wthis
  780. 3 index add exch 32 eq {1 index add} if % str [... weach wword w
  781. 3 1 roll % str [... w weach wword
  782. }
  783. % for the "exch" removed or not below, see comment in pdf_font.ps::getfontmetrics
  784. currentfont /FontMatrix get 0 3 Vexch pop get 0 ne {
  785. 1 1 index length 1 sub getinterval cvx
  786. } if
  787. cshow pop pop ]
  788. { xshow } { yshow } Vexch pop exec
  789. }
  790. } {
  791. WordSpacing 0 eq
  792. { { setfillstate TextSpacing 0 Vexch 3 -1 roll ashow } }
  793. { TextSpacing 0 eq
  794. { { setfillstate WordSpacing 0 Vexch 32 4 -1 roll widthshow } }
  795. { { setfillstate WordSpacing 0 Vexch 32
  796. TextSpacing 0 Vexch 6 -1 roll awidthshow } }
  797. ifelse
  798. }
  799. ifelse
  800. } ifelse
  801. }
  802. { { WordSpacing TextSpacing
  803. % Implement the combination of t3 and false charpath.
  804. % Note that we must use cshow for this, because we
  805. % can't parse multi-byte strings any other way.
  806. % Stack: string wword wchar
  807. {
  808. exch % will be removed, unless FontMatrixNonHV && FontMatrix.xx/yy == 0
  809. % Stack: str wword wchar ccode xthis ythis
  810. Vexch pop currentpoint 6 3 roll
  811. % Stack: str wthis xorig yorig wword wchar ccode
  812. (x) dup 0 3 index put //false charpath
  813. 3 copy 32 eq { add } { exch pop } ifelse
  814. % Stack: str wthis xorig yorig wword wchar ccode wextra
  815. 7 -3 roll moveto add
  816. 0 Vexch rmoveto pop
  817. }
  818. % for the "exch" removed or not below, see comment in pdf_font.ps::getfontmetrics
  819. FontMatrixNonHV dup not exch {
  820. currentfont /FontMatrix get 0 3 Vexch pop get 0 ne
  821. } if {
  822. 1 1 index length 1 sub getinterval cvx
  823. } if
  824. 4 -1 roll cshow pop pop
  825. textrenderingprocs TextRenderingMode get exec
  826. }
  827. }
  828. ifelse
  829. }
  830. ifelse /Show gput
  831. } bdef
  832. /showfirst { setshowstate Show } def
  833. /Tj {
  834. { 0 0 moveto Show settextposition }
  835. OFFlevels length 0 eq {
  836. exec
  837. } {
  838. gsave get-gs-attrs nulldevice set-gs-attrs
  839. exec
  840. get-gs-attrs grestore set-gs-attrs
  841. } ifelse
  842. } bdef
  843. /' { T* Tj } bdef
  844. /" { exch Tc exch Tw T* Tj } bdef
  845. /TJ {
  846. { 0 0 moveto {
  847. dup type /stringtype eq {
  848. Show
  849. } { -1000 div
  850. currentfont /ScaleMatrix .knownget { 0 get mul } if
  851. 0 Vexch rmoveto
  852. } ifelse
  853. } forall settextposition
  854. }
  855. OFFlevels length 0 eq {
  856. exec
  857. } {
  858. gsave get-gs-attrs nulldevice set-gs-attrs
  859. exec
  860. get-gs-attrs grestore set-gs-attrs
  861. } ifelse
  862. } bdef
  863. /tf { setfillstate currentpoint fill moveto } bdef
  864. /tn { currentpoint newpath moveto } bdef % Obsolete, never used.
  865. % For stroking characters, temporarily restore the graphics CTM so that
  866. % the line width will be transformed properly.
  867. /Tmatrix matrix def
  868. /tS
  869. { setstrokestate
  870. currentpoint //Tmatrix currentmatrix TextSaveMatrix setmatrix stroke
  871. setmatrix moveto
  872. } bdef
  873. /tB { gsave tf grestore tS } bdef
  874. % This does the wrong thing if there have been multiple text operations
  875. % within a single BT/ET pair, but it's a start.
  876. /tW { } bdef
  877. % Text formatting and painting for the AcroForm field without appearance streams.
  878. /Tform { % <MaxLen> (V) <Ff> <Q> Tform -
  879. clippath pathbbox 4 2 roll pop pop % MaxLen (V) Ff Q dx dy
  880. currentfont /ScaleMatrix .knownget { 3 get } { 1 } ifelse % MaxLen (V) Ff Q dx dy yy
  881. currentfont /FontBBox get dup 1 get neg exch 3 get % MaxLen (V) Ff Q dx dy yy desc asc
  882. dup 0 ne { div } { pop pop 0 } ifelse % MaxLen (V) Ff Q dx dy yy desc/asc
  883. 1 index mul % MaxLen (V) Ff Q dx dy yy desc/asc*yy
  884. 4 index 16#1000 and 0 ne { % multiline
  885. 8 { pop } repeat (Multiline form fields are not yet implemented.) =
  886. } {
  887. 4 index 16#1000000 and 0 ne { % comb
  888. 8 { pop } repeat (Combed form fields are not yet implemented.) =
  889. } { % plain text
  890. 3 1 roll sub add 2 div % MaxLen (V) Ff Q dx (dy-yy+desc)/2
  891. 0 exch moveto % MaxLen (V) Ff Q dx
  892. 1 index 0 ne {
  893. 3 index stringwidth pop % MaxLen (V) Ff Q dx w
  894. sub exch 1 eq { 2 div } { 2 sub } ifelse % MaxLen (V) Ff (dx-w)/2
  895. 0 rmoveto % MaxLen (V) Ff
  896. pop % MaxLen (V)
  897. } {
  898. pop pop pop % MaxLen (V)
  899. 2 0 rmoveto
  900. } ifelse
  901. exch pop Show % -
  902. } ifelse
  903. } ifelse
  904. } bdef
  905. end readonly put % GS_PDF_ProcSet
  906. .setglobal