% 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,v 1.41 2005/09/28 04:33:27 dan 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% 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 /nodict 1 dict defnodict /self { //nodict } executeonly putnodict readonly pop /dictbeginpage { % <initialdict> dictbeginpage - //nodict 20 dict .copydict begin { def } forall graphicsbeginpage textbeginpage} bdef/endpage { % - endpage - showpage end} bdef /graphicsbeginpage { initgraphics 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 % <value> <key> 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 % 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./grestore_nopath { % Collect the upath with an identity CTM { matrix setmatrix //false upath } stopped { pop grestore newpath } { % Save the CTM, set identity during the uappend, then set the CTM grestore matrix currentmatrix matrix setmatrix exch newpath uappend setmatrix } ifelse} bdef /q { gsave //nodict begin} bdef% Some PDF files have excess Q operators!/Q { currentdict /self .knownget { exec //nodict eq { end grestore_nopath false } { true } ifelse } { true % formaterror -- not a gsave dict } ifelse { (\n **** File has imbalanced q/Q operators \(too many Q's\) ****\n) pdfformaterror } if} bdef % Save PDF gstate/qstate { % - qstate <qstate> gstate} bdef % Set PDF gstate/setqstate { % <qstate> 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 % ---------------- Color setting ---------------- % /fcput % <color> <colorspace> fcput - { /FillColorSpace gput /FillColor gput } bdef/scput % <color> <colorspace> scput - { /StrokeColorSpace gput /StrokeColor gput } bdef/csput % <colorspace> csput - { csset 2 copy fcput scput } 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% <cspace> -proc- <cspace> <initial-color>/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 //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 % <cspace> csset <color> <cspace> { 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% 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 { % <alpha> <smask> .settransparencyparams - /.inittransparencymask where { pop AlphaIsShape { 1 .setopacityalpha 0 .inittransparencymask exch .setshapealpha 1 } { 1 .setshapealpha 1 .inittransparencymask 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} bdef/.settransparencymask { % <paramdict> <masknum> .settransparencymask - exch dup null eq { pop .inittransparencymask } { 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 % <color...> <colorspace> -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 dup /Matrix knownoget not { matrix } if gsave DefaultQstate setqstate makepattern grestore setcolor } bdefend def/setgcolor % (null | <color...>) <colorspace> 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 % <colorspace> -proc- <colorspace|pdfcspace> /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 } bdefend def/pdfcolorspace { % <colorspace> pdfcolorspace <colorspace|pdfcspace> dup type /arraytype eq { //PCSdict 1 index 0 get .knownget { exec } if } if} bdef/setgcolorspace { % <colorspace> setgcolorspace - dup pdfcolorspace currentcolorspace pdfcolorspace eq { pop } { setcolorspace } ifelse} bdef/fsexec % <fillop|strokeop> 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 { setstrokestate /stroke fsexec } bdef/f { setfillstate /fill fsexec } bdef/f* { setfillstate /eofill fsexec } bdef/n { newpath } bdef % don't allow n to get bound in/s { closepath S } bdef/B { gsave setfillstate fill grestore S } bdef/b { closepath B } bdef/B* { gsave setfillstate eofill grestore S } bdef/b* { closepath B* } bdef % Clipping: /Wdict 4 dict dup begin/S { gsave setstrokestate stroke grestore n } bdef/f { gsave setfillstate fill grestore n } bdef/f* { gsave setfillstate eofill grestore n } bdef/n { end clip newpath } bdefend readonly def/W { //Wdict begin } bdef/W*dict 4 dict dup beginWdict { def } forall/n { end eoclip newpath } bdefend 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 { % 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 <x> <y> 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 ---------------- % /Tf { % <font> <scale> 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 dup 1 eq { pop } { scalefont } ifelse /TextFont gput settextstate} bdef % Read a CFF font./FRD % <resname> <file> FRD - { /FontSetInit /ProcSet findresource begin //true 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 % <font> <changed> .copyfontdict <dict> { 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 { % <font> <Metrics|null> .updatefontmetrics % <font'> <copied> dup //null ne { exch //true .copyfontdict dup /Metrics 4 -1 roll put //true } { pop //falseLines 1–500 of 676. Load more
% 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,v 1.41 2005/09/28 04:33:27 dan 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 % 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 /nodict 1 dict def nodict /self { //nodict } executeonly put nodict readonly pop /dictbeginpage { % <initialdict> dictbeginpage - //nodict 20 dict .copydict begin { def } forall graphicsbeginpage textbeginpage } bdef /endpage { % - endpage - showpage end } bdef /graphicsbeginpage { initgraphics 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 % <value> <key> 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 % 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. /grestore_nopath { % Collect the upath with an identity CTM { matrix setmatrix //false upath } stopped { pop grestore newpath } { % Save the CTM, set identity during the uappend, then set the CTM grestore matrix currentmatrix matrix setmatrix exch newpath uappend setmatrix } ifelse } bdef /q { gsave //nodict begin } bdef % Some PDF files have excess Q operators! /Q { currentdict /self .knownget { exec //nodict eq { end grestore_nopath false } { true } ifelse } { true % formaterror -- not a gsave dict } ifelse { (\n **** File has imbalanced q/Q operators \(too many Q's\) ****\n) pdfformaterror } if } bdef % Save PDF gstate /qstate { % - qstate <qstate> gstate } bdef % Set PDF gstate /setqstate { % <qstate> 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 % ---------------- Color setting ---------------- % /fcput % <color> <colorspace> fcput - { /FillColorSpace gput /FillColor gput } bdef /scput % <color> <colorspace> scput - { /StrokeColorSpace gput /StrokeColor gput } bdef /csput % <colorspace> csput - { csset 2 copy fcput scput } 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 % <cspace> -proc- <cspace> <initial-color> /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 //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 % <cspace> csset <color> <cspace> { 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 % 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 { % <alpha> <smask> .settransparencyparams - /.inittransparencymask where { pop AlphaIsShape { 1 .setopacityalpha 0 .inittransparencymask exch .setshapealpha 1 } { 1 .setshapealpha 1 .inittransparencymask 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 } bdef /.settransparencymask { % <paramdict> <masknum> .settransparencymask - exch dup null eq { pop .inittransparencymask } { 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 % <color...> <colorspace> -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 dup /Matrix knownoget not { matrix } if gsave DefaultQstate setqstate makepattern grestore setcolor } bdef end def /setgcolor % (null | <color...>) <colorspace> 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 % <colorspace> -proc- <colorspace|pdfcspace> /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 { % <colorspace> pdfcolorspace <colorspace|pdfcspace> dup type /arraytype eq { //PCSdict 1 index 0 get .knownget { exec } if } if } bdef /setgcolorspace { % <colorspace> setgcolorspace - dup pdfcolorspace currentcolorspace pdfcolorspace eq { pop } { setcolorspace } ifelse } bdef /fsexec % <fillop|strokeop> 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 { setstrokestate /stroke fsexec } bdef /f { setfillstate /fill fsexec } bdef /f* { setfillstate /eofill fsexec } bdef /n { newpath } bdef % don't allow n to get bound in /s { closepath S } bdef /B { gsave setfillstate fill grestore S } bdef /b { closepath B } bdef /B* { gsave setfillstate eofill grestore S } bdef /b* { closepath B* } bdef % Clipping: /Wdict 4 dict dup begin /S { gsave setstrokestate stroke grestore n } bdef /f { gsave setfillstate fill grestore n } bdef /f* { gsave setfillstate 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 { % 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 <x> <y> 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 ---------------- % /Tf { % <font> <scale> 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 dup 1 eq { pop } { scalefont } ifelse /TextFont gput settextstate } bdef % Read a CFF font. /FRD % <resname> <file> FRD - { /FontSetInit /ProcSet findresource begin //true 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 % <font> <changed> .copyfontdict <dict> { 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 { % <font> <Metrics|null> .updatefontmetrics % <font'> <copied> dup //null ne { exch //true .copyfontdict dup /Metrics 4 -1 roll put //true } { pop //false