% Copyright (C) 1994, 2000 Aladdin Enterprises. All rights reserved. % % This software is provided AS-IS with no warranty, either express or % implied. % % This software is distributed under license and may not be copied, % modified or distributed except as expressly authorized under the terms % of the license contained in the file LICENSE in this distribution. % % For more information about licensing, please refer to % http://www.ghostscript.com/licensing/. For information on % commercial licensing, go to http://www.artifex.com/licensing/ or % contact Artifex Software, Inc., 101 Lucas Valley Road #110, % San Rafael, CA 94903, U.S.A., +1(415)492-9861. % $Id: pdf_ops.ps 10687 2010-02-02 07:23:57Z alexcher $ % Definitions for most of the PDF operators. .currentglobal true .setglobal % Define pdfmark. Don't allow it to be bound in. % Also don't define it in systemdict, because this leads some Adobe code % to think this interpreter is a distiller. % (If this interpreter really is a distiller, don't do this.) systemdict /pdfmark known not { userdict /pdfmark { cleartomark } bind put } if userdict /GS_PDF_ProcSet 127 dict dup begin % ---------------- Abbreviations ---------------- % /bdef { bind def } bind def % ---------------- Graphics state stack ---------------- % % PDF adds a number of parameters to the graphics state. % We implement this by pushing and popping a dictionary % each time we do a PDF gsave or grestore. % The keys in this dictionary are as follows: % self % identifies the dictionary as one of ours % ClipRect % (optional) % Show % TextSaveMatrix % matrix at time of BT (iff within BT/ET) % (The following correspond directly to PDF state parameters.) % AlphaIsShape % FillConstantAlpha % FillColor % FillColorSpace % FillOverprint % SoftMask % StrokeConstantAlpha % StrokeColor % StrokeColorSpace % StrokeOverprint % TextSpacing % TextHScaling % Leading % TextFont % TextLineMatrix % TextMatrix % TextRise % TextRenderingMode % WordSpacing % (The following is cached information derived from other graphics state params) % FontMatrixNonHV % TextFont.FontMatrix alters horz/vert glyph advance vector direction /nodict 1 dict def nodict /self { //nodict } executeonly put % to avoid recursion in dumps nodict readonly pop /dictbeginpage { % dictbeginpage - 20 dict copy dup begin 1 packedarray cvx executeonly /self exch def graphicsbeginpage textbeginpage } bdef /endpage { % - endpage - showpage end } bdef /graphicsbeginpage { initgraphics //true .setaccuratecurves currentdict /ClipRect knownoget { aload pop rectclip } if 0 g 0 G false op false OP 0 OPM 1 ca 1 CA null SMask false AIS /Compatible BM true TK } bdef /gput % gput - { exch currentdict //nodict eq { /self dup load end 5 dict begin def } if def } bdef /q { gsave //nodict begin PDFusingtransparency {.pushextendedgstate cvx} if } bdef % Some PDF files have excess Q operators! /Q { PDFusingtransparency {.popextendedgstate cvx} if currentdict /self .knownget { exec //nodict eq { end % Restore graphics state, but do not modify path. Paths are not part % of the PDF graphics state; see 4.4.1 of PDF reference 3rd ed. % Collecting the path with one ctm and re-playing it with another ctm % transforms the path exactly as PDF needs. .getpath grestore newpath { exec } forall //false } { //true } ifelse } { //true % formaterror -- not a gsave dict } ifelse { (\n **** File has unbalanced q/Q operators \(too many Q's\) ****\n) pdfformaterror } if } bdef % Save PDF gstate /qstate { % - qstate gstate } bdef % Set PDF gstate /setqstate { % setqstate - { matrix setmatrix //false upath } stopped { pop setgstate newpath } { % Save the CTM, set identity during the uappend, then set the CTM exch setgstate matrix currentmatrix matrix setmatrix exch newpath uappend setmatrix } ifelse } bdef % Save most of graphic state attributes. % - get-gs-attrs ... /get-gs-attrs { currentsmoothness currentflat currentoverprint currentstrokeadjust currentdash currentmiterlimit currentlinejoin currentlinecap currentlinewidth currentfont currentcolor currentcolorspace { currentpoint } stopped matrix currentmatrix } bdef % Restore most of graphic state attributes. % ... get-gs-attrs - /set-gs-attrs { setmatrix { newpath } { moveto } ifelse setcolorspace setcolor setfont setlinewidth setlinecap setlinejoin setmiterlimit setdash setstrokeadjust setoverprint setflat setsmoothness } bdef % ---------------- Color setting ---------------- % /fcput % fcput - { /FillColorSpace gput /FillColor gput } bdef /scput % scput - { /StrokeColorSpace gput /StrokeColor gput } bdef /csput % csput - { csset 2 copy fcput scput } bdef /csdevgray [/DeviceGray] readonly def /csdevrgb [/DeviceRGB] readonly def /csdevcmyk [/DeviceCMYK] readonly def /cspattern [/Pattern] readonly def /nullpatternproc { pop } bdef /nullpattern mark /PatternType 1 /PaintType 1 /TilingType 3 /BBox [0 0 1 1] /XStep 1 /YStep 1 /PaintProc //nullpatternproc .dicttomark readonly def % Each entry in the color space dictionary is a procedure of the form % -proc- /CSdict mark /DeviceGray { pop //csdevgray 0 } bind /DeviceRGB { pop //csdevrgb [0 0 0] cvx } bind /DeviceCMYK { pop //csdevcmyk [0 0 0 1] cvx } bind /CIEBasedA { 0 } bind /CIEBasedABC { [0 0 0] cvx } bind /ICCBased { [ 1 index 1 oget /N get { 0 } repeat ] cvx } bind /Separation { 1 } bind /DeviceN { % What is the correct value?? [ 1 index 1 get length { 1 } repeat ] cvx } bind /Indexed { 0 } bind /Pattern { dup type /nametype eq 1 index length 1 eq or { pop //cspattern //nullpattern matrix makepattern } { //nullpattern matrix makepattern 1 index 1 get csset % Stack: patternspace nullpattern basecolor basespace pop [ 3 1 roll dup type /arraytype eq { aload pop } if counttomark -1 roll ] cvx } ifelse } bind .dicttomark readonly def /csset % csset { dup dup type /nametype ne { 0 get } if //CSdict exch get exec exch } bdef /g { //csdevgray fcput } bdef /G { //csdevgray scput } bdef /rg { 3 array astore cvx //csdevrgb fcput } bdef /RG { 3 array astore cvx //csdevrgb scput } bdef /k { 4 array astore cvx //csdevcmyk fcput } bdef /K { 4 array astore cvx //csdevcmyk scput } bdef /cs { csset fcput } bdef /CS { csset scput } bdef /ri { //.renderingintentdict exch .knownget { .setrenderingintent } if } bdef % We have to break up sc according to the number of operands. /sc1 { /FillColor gput } bdef /SC1 { /StrokeColor gput } bdef % We have to avoid storing into a color array associated with an outer % gsave level, so we do a kind of "copy on write". /sc* { currentdict /FillColor .knownget { astore pop } { /FillColor load % FillColor may contain either a single value or an array. dup type /arraytype eq { length }{ pop 1 } ifelse array astore cvx /FillColor gput } ifelse } bdef /SC* { currentdict /StrokeColor .knownget { astore pop } { /StrokeColor load % StrokeColor may contain either a single value or an array. dup type /arraytype eq { length }{ pop 1 } ifelse array astore cvx /StrokeColor gput } ifelse } bdef % ---------------- Overprint/transparency setting ---------------- % /op { /FillOverprint gput } bdef /OP { /StrokeOverprint gput } bdef /OPM { /.setoverprintmode where { pop .setoverprintmode } { pop } ifelse } bdef /ca { /FillConstantAlpha gput } bdef /CA { /StrokeConstantAlpha gput } bdef /SMask { /SoftMask gput } bdef /AIS { /AlphaIsShape gput } bdef /BM { /.setblendmode where { pop [ exch dup type /nametype ne { aload pop } if /Normal ] { { .setblendmode } .internalstopped not { exit } if pop } forall } { pop } ifelse } bdef /TK { /.settextknockout where { pop .settextknockout } { pop } ifelse } bdef % ---------------- Color installation ---------------- % % Establish a given color (and color space) as current. /.settransparencyparams { % .settransparencyparams - PDFusingtransparency { /.begintransparencygroup where { pop AlphaIsShape { 1 .setopacityalpha exch .setshapealpha 1 } { 1 .setshapealpha exch .setopacityalpha 0 } ifelse % Set the soft mask by rendering the XObject. Doing this every time % is obviously very inefficient; we'll improve it later. .settransparencymask } { pop pop } ifelse } { pop pop } ifelse } bdef /.settransparencymask { % .settransparencymask - exch dup null eq { PDFusingtransparency { pop pop } { dup /Draw get exec } ifelse } { dup /Draw get exec } ifelse } bdef % (Non-mask) images must execute setfillblend. /setfillblend { FillOverprint setoverprint FillConstantAlpha SoftMask .settransparencyparams } def /setfillstate { FillColor FillColorSpace setgcolor setfillblend } def /setstrokestate { StrokeColor StrokeColorSpace setgcolor StrokeOverprint setoverprint StrokeConstantAlpha SoftMask .settransparencyparams } def /Cdict 15 dict dup begin % -proc- - /DeviceGray { pop setgray } bdef /DeviceRGB { pop setrgbcolor } bdef /DeviceCMYK { pop setcmykcolor } bdef /CIEBasedA { setgcolorspace setcolor } bdef /CIEBasedABC /CIEBasedA load def /CIEBasedDEF /CIEBasedA load def /CIEBasedDEFG /CIEBasedA load def /ICCBased /CIEBasedA load def /Separation /CIEBasedA load def /DeviceN /CIEBasedA load def /Indexed /CIEBasedA load def /Pattern { setgcolorspace % Since multiple patterns may share % same data stream, we need to ensure % that the stream is at 0 position. % Making this consistently with resolveshading, % which applies ReusableStreamDecode filter % to the PS stream, which represents the % PDF stream in dynamics. dup /Shading knownoget { dup /ShadingType oget 4 ge { /DataSource knownoget { dup type /filetype eq { 0 setfileposition } { pop } ifelse } if } { pop } ifelse } if % Associate pattern instance with the default qstate for the context. % A single pattren object can be reused in several contexts. dup DefaultQstate .knownget { exch pop } { % But don't update read-only initial null pattern. dup /PaintProc .knownget { //nullpatternproc ne } { //true } ifelse { dup dup /Matrix knownoget not { { 1 0 0 1 0 0 } } if gsave DefaultQstate setqstate makepattern grestore dup 3 1 roll DefaultQstate exch put } if } ifelse setcolor } bdef end def /setgcolor % (null | ) setgcolor - { 1 index null eq { pop pop } { dup 0 get //Cdict exch get exec } ifelse } bdef % Compare the old and new color spaces in an attempt to avoid expensive % reloads of CIEBased color spaces. /PCSdict 15 dict dup begin % -proc- /CIEBasedA { dup 1 get /PDFColorSpace .knownget { exch pop } if } bdef /CIEBasedABC /CIEBasedA load def /CIEBasedDEF /CIEBasedA load def /CIEBasedDEFG /CIEBasedA load def /Indexed { dup 1 get dup pdfcolorspace 2 copy ne { 3 1 roll } if pop pop } bdef end def /pdfcolorspace { % pdfcolorspace dup type /arraytype eq { //PCSdict 1 index 0 get .knownget { exec } if } if } bdef /setgcolorspace { % setgcolorspace - dup pdfcolorspace currentcolorspace pdfcolorspace eq { pop } { setcolorspace } ifelse } bdef /fsexec % fsexec - { SoftMask //null ne { mark /Subtype /Group /Isolated true .dicttomark pathbbox .begintransparencygroup } if cvx exec SoftMask //null ne { .endtransparencygroup } if } bdef % ---------------- Path painting and clipping ---------------- % /S { OFFlevels length 0 eq { setstrokestate /stroke fsexec } { newpath } ifelse } bdef /f { OFFlevels length 0 eq { setfillstate /fill fsexec } { newpath } ifelse } bdef /f* { OFFlevels length 0 eq { setfillstate /eofill fsexec } { newpath } ifelse } bdef /n { newpath } bdef % don't allow n to get bound in /s { closepath S } bdef /B { OFFlevels length 0 eq { gsave setfillstate fill grestore setstrokestate /stroke fsexec } { newpath } ifelse } bdef /b { closepath B } bdef /B* { OFFlevels length 0 eq { gsave setfillstate eofill grestore setstrokestate /stroke fsexec } { newpath } ifelse } bdef /b* { closepath B* } bdef % Clipping: /Wdict 4 dict dup begin /S { OFFlevels length 0 eq { gsave setstrokestate stroke grestore } if n } bdef /f { OFFlevels length 0 eq { gsave setfillstate fill grestore } if n } bdef /f* { OFFlevels length 0 eq { gsave setfillstate eofill grestore } if n } bdef /n { end { currentpoint } stopped not { pop pop clip } if newpath } bdef end readonly def /W { //Wdict begin } bdef /W*dict 4 dict dup begin Wdict { def } forall /n { end { currentpoint } stopped not { pop pop eoclip } if newpath } bdef end readonly def /W* { //W*dict begin } bdef % ---------------- Text control ---------------- % /textbeginpage { /TextSpacing 0 def % 0 Tc /TextLeading 0 def % 0 TL /TextRenderingMode 0 def % 0 Tr /TextRise 0 def % 0 Ts /WordSpacing 0 def % 0 Tw /TextHScaling 1.0 def % 100 Tz /TextFont null def /FontMatrixNonHV //false def /Show { showfirst } def } bdef % Contrary to the statement in the PDF manual, BT and ET *can* be nested, % if the CharProc for a Type 3 font does a BT/ET itself. % Since we always call the CharProc inside a q/Q, we simply ensure that % the text state is saved and restored like the rest of the extended % graphics state. /settextmatrix { TextMatrix concat TextHScaling 1 ne { TextHScaling 1 scale } if TextRise 0 ne { 0 TextRise translate } if TextFont dup null eq { pop } { setfont } ifelse } bdef /settextstate { % The text state can be set even outside BT/ET. currentdict /TextSaveMatrix known { TextSaveMatrix setmatrix settextmatrix } if } bdef /settextposition { % Update the TextMatrix translation. gsave TextSaveMatrix setmatrix currentpoint TextRise sub TextMatrix 4 2 getinterval astore pop % We would like to do "grestore currentpoint translate" % here, but some PDF files set a singular text matrix % (0 0 0 0 Tm), so we can't do this. TextTempMatrix identmatrix setmatrix currentpoint grestore TextTempMatrix currentmatrix 4 2 getinterval astore pop TextTempMatrix setmatrix } bdef /BT { currentdict /TextLineMatrix .knownget { identmatrix pop TextMatrix identmatrix pop } { matrix /TextLineMatrix gput matrix /TextMatrix gput } ifelse { showfirst } /Show gput currentdict /TextSaveMatrix .knownget not { matrix dup /TextSaveMatrix gput } if currentmatrix pop settextmatrix matrix /TextTempMatrix gput % see settextposition } bdef /ET { TextRenderingMode 4 ge { clip newpath } if TextSaveMatrix setmatrix currentdict /TextSaveMatrix undef } bdef /Tc { /TextSpacing gput { showfirst } /Show gput } bdef /TL { /TextLeading gput } bdef /Tr { dup .settextrenderingmode /TextRenderingMode gput { showfirst } /Show gput } bdef /Ts { /TextRise gput settextstate } bdef /Tw { /WordSpacing gput { showfirst } /Show gput } bdef /Tz { 100 div /TextHScaling gput settextstate} bdef % ---------------- Font control ---------------- % % Test if the FontMatrix could transform a horizontal/vertical (depending % on writing mode) advance vector in glyph space into one with a different % direction in text space. % - if FontMatrix = [a b c d tx ty], this condition translates to: % b != 0 for horizontal writing mode % c != 0 for vertical writing mode % - when false, we automatically have wy/x == 0 in text space whenever wy/x == 0 % in glyph space, and can avoid the slow method that is otherwise necessary % to implement zeroing wy/x cf PDF Ref 5.3.3 "Text space details" % Worker procedure for testing a single font matrix /?FontMatrixNonHV { % ?horz <> -- ?horz ?nonhv /FontMatrix .knownget { 1 index { 1 } { 2 } ifelse get 0 ne } { //false } ifelse } bdef % Worker procedure for recursive checking of font matrices /?FontMatrixNonHV { % {self} ?horz <> -- {self} ?horz ?nonhv 2 copy //?FontMatrixNonHV exec { % check the font's own FontMatrix pop pop //true } { % look for descendents/ components pop % {self} ?horz <> dup /FontType get dup 0 eq { % Type 0: look into FDepVector pop /FDepVector get 2 index % {self} ?horz [fonts..] {testproc} } { 9 eq { % Type 9 (CIDFontType 0): check FDArray /FDArray get //?FontMatrixNonHV } { % all others: nothing more to check pop {} {} } ifelse } ifelse %stack: {self} ?horz [fonts..] {testproc} //false 5 2 roll { % {testproc} false {self} ?horz <> 4 index exec { 4 -1 roll pop //true 4 1 roll exit } if } forall %stack: {testproc} ?nonhv {self} ?horz 4 2 roll exch pop } ifelse } bdef % Main procedure /?FontMatrixNonHV { % <> -- ?nonhv //?FontMatrixNonHV exch % determine WMode dup /WMode .knownget { 0 eq } { //true } ifelse % {proc} <> ?horz exch % call the worker procedure //?FontMatrixNonHV exec exch pop exch pop } bdef /Tf { % Tf - dup 0 eq { (\n **** Warning: Invalid 0.0 font scale given for Tf ****\n) pdfformaterror pop 0.00000001 % handle invalid scale by using a really small value } if 1 index type /dicttype ne { selectfont currentfont } { dup 1 eq { pop } { scalefont } ifelse } ifelse dup ?FontMatrixNonHV dup FontMatrixNonHV ne { /FontMatrixNonHV gput { showfirst } /Show gput } { pop } ifelse /TextFont gput settextstate } bdef % Copy a font, removing its FID. If changed is true, also remove % the UniqueID and XUID, if any. If the original dictionary doesn't have % the keys being removed, don't copy it. /.copyfontdict % .copyfontdict { 1 index /FID known 1 index { 2 index /UniqueID known or 2 index /XUID known or } if { % We add 1 to the length just in case the original % didn't have a FID. exch dup length 1 add dict exch { % Stack: changed newfont key value 1 index /FID eq 4 index { 2 index /UniqueID eq or 2 index /XUID eq or } if not { 3 copy put } if pop pop } forall exch } if pop } bdef % Insert a new Encoding or Metrics into a font if necessary. % Return a possibly updated font, and a flag to indicate whether % the font was actually copied. /.updatefontmetrics { % .updatefontmetrics % dup //null ne { exch //true .copyfontdict dup /Metrics 4 -1 roll put //true } { pop //false } ifelse } bdef /.updatefontencoding { % .updatefontencoding % dup //null ne { dup 2 index /Encoding get ne } { //false } ifelse { exch //false .copyfontdict dup /Encoding 4 -1 roll put //true } { pop //false } ifelse } bdef % Duplicate keys in CharString dictionary according to GlyphMap: <> % We have to do this because PDF fonts can associate multiple widths with the same glyph % but Metrics dictionary works by the glyph name. /.update_charstring { % .update_charstring dup //null ne { exch //true .copyfontdict % map font dup dup /CharStrings get % map font font cstr dup length % map font font cstr len 4 index length add % map font font cstr len+map_len dict copy dup begin % map font font cstr' /CharStrings exch put % map font exch { % font /new /old currentdict exch .knownget { def } { currentdict /.notdef .knownget { def } { pop % The font has no .notdef. % Could not resolve the conflict, % but either the font is invalid or the glyph name is never used. } ifelse } ifelse } forall end //true } { pop //false } ifelse } bdef /.updatefont { % % .updatefont 4 2 roll % .updatefontencoding % bool 4 1 roll exch % bool .update_charstring % bool bool 3 1 roll exch % bool bool .updatefontmetrics % bool bool bool 4 2 roll or or % is_copied } bdef % ---------------- Text positioning ---------------- % /Td { TextLineMatrix transform TextLineMatrix 4 2 getinterval astore pop TextLineMatrix TextMatrix copy pop settextstate } bdef /TD { dup neg /TextLeading gput Td } bdef /T* { 0 TextLeading neg Td } bdef /Tm { TextLineMatrix astore TextMatrix copy pop settextstate } bdef % ---------------- Text painting ---------------- % /Vexch { rootfont /WMode knownoget { 1 eq { exch } if } if } bind def /textrenderingprocs [ % (0 is handled specially) % Painting-only modes { tf } { tS } { tB } { tn } % Clipping modes { gsave tf grestore tW } { gsave tS grestore tW } { gsave tB grestore tW } { tW } ] readonly def /pdfwrite_textrenderingprocs [ { setfillstate show } bind { setstrokestate % Need to set the stroke width to a value which gives the correct % width under pdfwrite. Pdfwrite uses (in text mode) an identity % CTM, so we need to calculate the stroke width which would result % if the CTM had been unity. currentlinewidth dup matrix defaultmatrix idtransform TextSaveMatrix dtransform 2 copy eq { pop }{ % non-square scaling reduces to Text matrix in pdfwrite , so % we can ignore it. (wrong answer, but consistent) pop pop currentlinewidth }ifelse setlinewidth show } bind { gsave 0 .settextrenderingmode setfillstate dup show currentpoint 3 -1 roll grestore gsave setstrokestate false charpath % We need to make sure the matrix used for the stroke % and therefore stroke width does not include the % Text Matrix Tm. TextSaveMatrix setmatrix stroke grestore moveto } bind { setfillstate show } bind { gsave 0 .settextrenderingmode setfillstate dup show grestore true charpath } bind { gsave 1 .settextrenderingmode setstrokestate dup show grestore true charpath } bind { gsave 0 .settextrenderingmode setfillstate dup show grestore gsave dup setstrokestate false charpath % We need to make sure the matrix used for the stroke % and therefore stroke width does not include the % Text Matrix Tm. TextSaveMatrix setmatrix stroke grestore true charpath } bind { true charpath } bind ] readonly def /setshowstate { WordSpacing 0 eq TextSpacing 0 eq and FontMatrixNonHV not and { currentdevice .devicename /pdfwrite eq { pdfwrite_textrenderingprocs TextRenderingMode get } { TextRenderingMode 0 eq { { setfillstate show } } { TextRenderingMode 3 eq { % Some PDF files execute 'tm' with a singular matrix, % and then use the text rendering mode 3. % The graphics library currently cannot handle text % operations when the CTM is singular. % Work around this here. { matrix currentmatrix dup dup dup 0 get 0 eq 1 index 1 get 0 eq and { dup dup 2 get 0 eq { 0 }{ 1 } ifelse 1 put } if dup 2 get 0 eq 1 index 3 get 0 eq and { dup dup 1 get 0 eq { 3 }{ 2 } ifelse 1 put } if setmatrix 2 index setfillstate show % Tr was set to graphic state. setmatrix % now set the currentpoint using the original matrix gsave setmatrix false charpath currentpoint newpath grestore moveto } } { { false charpath textrenderingprocs TextRenderingMode get exec } } ifelse } ifelse } ifelse } { TextRenderingMode 0 eq TextRenderingMode 3 eq or % Tr was set to graphic state. { FontMatrixNonHV { { setfillstate [ TextSpacing WordSpacing 3 index { % str [... weach wword c undef|ythis xthis|undef exch % will be removed, unless FontMatrix.xx/yy == 0 (FontMatrixNonHV already true) Vexch pop % str [... weach wword c wthis 3 index add exch 32 eq {1 index add} if % str [... weach wword w 3 1 roll % str [... w weach wword } % for the "exch" removed or not below, see comment in pdf_font.ps::getfontmetrics currentfont /FontMatrix get 0 3 Vexch pop get 0 ne { 1 1 index length 1 sub getinterval cvx } if cshow pop pop ] { xshow } { yshow } Vexch pop exec } } { WordSpacing 0 eq { { setfillstate TextSpacing 0 Vexch 3 -1 roll ashow } } { TextSpacing 0 eq { { setfillstate WordSpacing 0 Vexch 32 4 -1 roll widthshow } } { { setfillstate WordSpacing 0 Vexch 32 TextSpacing 0 Vexch 6 -1 roll awidthshow } } ifelse } ifelse } ifelse } { { WordSpacing TextSpacing % Implement the combination of t3 and false charpath. % Note that we must use cshow for this, because we % can't parse multi-byte strings any other way. % Stack: string wword wchar { exch % will be removed, unless FontMatrixNonHV && FontMatrix.xx/yy == 0 % Stack: str wword wchar ccode xthis ythis Vexch pop currentpoint 6 3 roll % Stack: str wthis xorig yorig wword wchar ccode (x) dup 0 3 index put //false charpath 3 copy 32 eq { add } { exch pop } ifelse % Stack: str wthis xorig yorig wword wchar ccode wextra 7 -3 roll moveto add 0 Vexch rmoveto pop } % for the "exch" removed or not below, see comment in pdf_font.ps::getfontmetrics FontMatrixNonHV dup not exch { currentfont /FontMatrix get 0 3 Vexch pop get 0 ne } if { 1 1 index length 1 sub getinterval cvx } if 4 -1 roll cshow pop pop textrenderingprocs TextRenderingMode get exec } } ifelse } ifelse /Show gput } bdef /showfirst { setshowstate Show } def /Tj { { 0 0 moveto Show settextposition } OFFlevels length 0 eq { exec } { gsave get-gs-attrs nulldevice set-gs-attrs exec get-gs-attrs grestore set-gs-attrs } ifelse } bdef /' { T* Tj } bdef /" { exch Tc exch Tw T* Tj } bdef /TJ { { 0 0 moveto { dup type /stringtype eq { Show } { -1000 div currentfont /ScaleMatrix .knownget { 0 get mul } if 0 Vexch rmoveto } ifelse } forall settextposition } OFFlevels length 0 eq { exec } { gsave get-gs-attrs nulldevice set-gs-attrs exec get-gs-attrs grestore set-gs-attrs } ifelse } bdef /tf { setfillstate currentpoint fill moveto } bdef /tn { currentpoint newpath moveto } bdef % Obsolete, never used. % For stroking characters, temporarily restore the graphics CTM so that % the line width will be transformed properly. /Tmatrix matrix def /tS { setstrokestate currentpoint //Tmatrix currentmatrix TextSaveMatrix setmatrix stroke setmatrix moveto } bdef /tB { gsave tf grestore tS } bdef % This does the wrong thing if there have been multiple text operations % within a single BT/ET pair, but it's a start. /tW { } bdef % Text formatting and painting for the AcroForm field without appearance streams. /Tform { % (V) Tform - clippath pathbbox 4 2 roll pop pop % MaxLen (V) Ff Q dx dy currentfont /ScaleMatrix .knownget { 3 get } { 1 } ifelse % MaxLen (V) Ff Q dx dy yy currentfont /FontBBox get dup 1 get neg exch 3 get % MaxLen (V) Ff Q dx dy yy desc asc dup 0 ne { div } { pop pop 0 } ifelse % MaxLen (V) Ff Q dx dy yy desc/asc 1 index mul % MaxLen (V) Ff Q dx dy yy desc/asc*yy 4 index 16#1000 and 0 ne { % multiline 8 { pop } repeat (Multiline form fields are not yet implemented.) = } { 4 index 16#1000000 and 0 ne { % comb 8 { pop } repeat (Combed form fields are not yet implemented.) = } { % plain text 3 1 roll sub add 2 div % MaxLen (V) Ff Q dx (dy-yy+desc)/2 0 exch moveto % MaxLen (V) Ff Q dx 1 index 0 ne { 3 index stringwidth pop % MaxLen (V) Ff Q dx w sub exch 1 eq { 2 div } { 2 sub } ifelse % MaxLen (V) Ff (dx-w)/2 0 rmoveto % MaxLen (V) Ff pop % MaxLen (V) } { pop pop pop % MaxLen (V) 2 0 rmoveto } ifelse exch pop Show % - } ifelse } ifelse } bdef end readonly put % GS_PDF_ProcSet .setglobal