home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / share / ghostscript / 8.64 / Resource / Init / pdf_ops.ps < prev    next >
Encoding:
Text File  |  2009-04-17  |  27.7 KB  |  878 lines

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