% Copyright (C) 1994, 2000 Aladdin Enterprises. All rights reserved. % % This file is part of Aladdin Ghostscript. % % Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author % or distributor accepts any responsibility for the consequences of using it, % or for whether it serves any particular purpose or works at all, unless he % or she says so in writing. Refer to the Aladdin Ghostscript Free Public % License (the "License") for full details. % % Every copy of Aladdin Ghostscript must include a copy of the License, % normally in a plain ASCII text file named PUBLIC. The License grants you % the right to copy, modify and redistribute Aladdin Ghostscript, but only % under certain conditions described in the License. Among other things, the % License requires that the copyright notice and this notice be preserved on % all copies. % $Id: pdf_ops.ps,v 1.2 2000/03/10 03:57:03 lpd Exp $ % 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 % Show % TextSaveMatrix % matrix at time of BT % (The following correspond directly to PDF state parameters.) % FillColor % FillColorSpace % StrokeColor % StrokeColorSpace % TextSpacing % TextHScaling % Leading % TextFont % TextLineMatrix % TextMatrix % TextRise % TextRenderingMode % WordSpacing /nodict 1 dict def nodict /self { //nodict } executeonly put nodict readonly pop /beginpage { //nodict 20 dict .copydict begin graphicsbeginpage textbeginpage } bdef /endpage { showpage end } bdef /graphicsbeginpage { initgraphics 0 g 0 G } bdef /gput % gput - { exch currentdict //nodict eq { /self dup load end 5 dict begin def } if % If we're in a Level 1 system, we need to grow the % dictionary explicitly. currentdict length currentdict maxlength ge %eq { currentdict dup length 3 mul 2 idiv 1 add dict .copydict end begin } if def } bdef /q { gsave //nodict begin } bdef % Some PDF files have excess Q operators! /Q { currentdict /self .knownget { exec //nodict eq { end grestore } if } if } bdef % ---------------- Color setting ---------------- % /fcput % fcput - { /FillColorSpace gput /FillColor gput } bdef /scput % scput - { /StrokeColorSpace gput /StrokeColor gput } bdef /csdevgray [/DeviceGray] readonly def /csdevrgb [/DeviceRGB] readonly def /csdevcmyk [/DeviceCMYK] readonly def /cspattern [/Pattern] readonly def /nullpattern1 mark /PatternType 1 /PaintType 1 /TilingType 3 /BBox [0 0 0 0] /XStep 1 /YStep 1 /PaintProc { } .dicttomark readonly def /nullpattern2 nullpattern1 dup length dict copy 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 /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 //nullpattern1 matrix makepattern } { //nullpattern2 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 { pop } bdef % We have to break up sc according to the number of operands. /sc1 { /FillColor gput } bdef /SC1 { /StrokeColor gput } bdef /sc* { /FillColor load astore pop } bdef /SC* { /StrokeColor load astore pop } bdef % ---------------- Color installation ---------------- % % Establish a given color (and color space) as current. /setfillcolor { FillColor FillColorSpace setgcolor } def /setstrokecolor { StrokeColor StrokeColorSpace setgcolor } def /Cdict 15 dict dup begin % -proc- - /DeviceGray { pop setgray } bdef /DeviceRGB { pop setrgbcolor } bdef /DeviceCMYK { pop setcmykcolor } bdef /CIEBasedA { dup currentcolorspace eq { pop } { setcolorspace } ifelse setcolor } bdef /CIEBasedABC /CIEBasedA load def /CIEBasedDEF /CIEBasedA load def /CIEBasedDEFG /CIEBasedA load def /Separation /CIEBasedA load def /DeviceN /CIEBasedA load def /Indexed /CIEBasedA load def /Pattern { dup currentcolorspace eq { pop } { setcolorspace } ifelse dup /Matrix .knownget not { matrix } if makepattern setcolor } bdef end def /setgcolor % (null | ) setgcolor - { 1 index null eq { pop pop } { dup 0 get //Cdict exch get exec } ifelse } bdef /fsexec % fsexec - { % Preserve the current point, if any. { currentpoint } stopped { $error /newerror false put cvx exec } { 3 -1 roll cvx exec moveto } ifelse } bdef % ---------------- Path painting and clipping ---------------- % /S { setstrokecolor /stroke fsexec } bdef /f { setfillcolor /fill fsexec } bdef /f* { setfillcolor /eofill fsexec } bdef /n { newpath } bdef % don't allow n to get bound in /s { closepath S } bdef /B { gsave setfillcolor fill grestore S } bdef /b { closepath B } bdef /B* { gsave setfillcolor eofill grestore S } bdef /b* { closepath B* } bdef % Clipping: /Wdict 4 dict dup begin /S { gsave setstrokecolor stroke grestore n } bdef /f { gsave setfillcolor fill grestore n } bdef /f* { gsave setfillcolor eofill grestore n } bdef /n { end clip newpath } bdef end readonly def /W { //Wdict begin } bdef /W*dict 4 dict dup begin Wdict { def } forall /n { end eoclip 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 /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 { TextSaveMatrix setmatrix settextmatrix } bdef /settextposition { % Update the TextMatrix translation. gsave TextSaveMatrix setmatrix currentpoint TextMatrix 4 2 getinterval astore pop grestore currentpoint translate } 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 } bdef /ET { TextSaveMatrix setmatrix } bdef /Tc { /TextSpacing gput { showfirst } /Show gput } bdef /TL { /TextLeading gput } bdef /Tr { /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 ---------------- % /Tf { % Tf - dup 1 eq { pop } { scalefont } ifelse /TextFont gput settextstate } bdef % Read a CFF font. /FRD % FRD - { /FontSetInit /ProcSet findresource begin ReadData } 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 /.updatefont { % .updatefont % 3 -1 roll exch .updatefontmetrics % Stack: enc|null font' copied 3 1 roll exch .updatefontencoding 3 -1 roll or } 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 ---------------- % /textrenderingprocs [ % (0 is handled specially) { tf } { tS } { tB } { tn } % We don't know what the clipping modes mean.... 4 copy ] readonly def /setshowstate { WordSpacing 0 eq TextSpacing 0 eq and { TextRenderingMode 0 eq { { setfillcolor show } } { { false charpath textrenderingprocs TextRenderingMode get exec } } ifelse } { TextRenderingMode 0 eq { WordSpacing 0 eq { { setfillcolor TextSpacing exch 0 exch ashow } } { TextSpacing 0 eq { { setfillcolor WordSpacing exch 0 exch 32 exch widthshow } } { { setfillcolor WordSpacing exch TextSpacing exch 0 32 4 2 roll 0 exch awidthshow } } 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 xword xchar { pop pop (x) dup 0 3 index put false charpath % Stack: xword xchar ccode 3 copy 32 eq { add } { exch pop } ifelse 0 rmoveto pop } 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 } 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 rmoveto } ifelse } forall settextposition } bdef /tf { setfillcolor currentpoint fill moveto } bdef /tn { currentpoint newpath moveto } bdef % For stroking characters, temporarily restore the graphics CTM so that % the line width will be transformed properly. /Tmatrix matrix def /tS { setstrokecolor currentpoint //Tmatrix currentmatrix TextSaveMatrix setmatrix stroke setmatrix moveto } bdef /tB { gsave tf grestore tS } bdef end readonly put % GS_PDF_ProcSet .setglobal