File manager - Edit - /home/newsbmcs.com/public_html/static/img/logo/Init.tar
Back
gs_btokn.ps 0000644 00000030735 15030647507 0006735 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % Initialization file for binary tokens. % When this is run, systemdict is still writable, % but everything defined here goes into level2dict. % Define whether or not to allow writing dictionaries. % This is a non-standard feature! /WRITEDICTS //false def languagelevel 1 .setlanguagelevel level2dict begin % Initialization for the system name table. mark % 0 /abs /add /aload /anchorsearch /and /arc /arcn /arct /arcto /array /ashow /astore /awidthshow /begin /bind /bitshift /ceiling /charpath /clear /cleartomark % 20 /clip /clippath /closepath /concat /concatmatrix /copy /count /counttomark /currentcmykcolor /currentdash /currentdict /currentfile /currentfont /currentgray /currentgstate /currenthsbcolor /currentlinecap /currentlinejoin /currentlinewidth /currentmatrix % 40 /currentpoint /currentrgbcolor /currentshared /curveto /cvi /cvlit /cvn /cvr /cvrs /cvs /cvx /def /defineusername /dict /div /dtransform /dup /end /eoclip /eofill % 60 /eoviewclip /eq /exch /exec /exit /file /fill /findfont /flattenpath /floor /flush /flushfile /for /forall /ge /get /getinterval /grestore /gsave /gstate % 80 /gt /identmatrix /idiv /idtransform /if /ifelse /image /imagemask /index /ineofill /infill /initviewclip /inueofill /inufill /invertmatrix /itransform /known /le /length /lineto % 100 /load /loop /lt /makefont /matrix /maxlength /mod /moveto /mul /ne /neg /newpath /not /null /or /pathbbox /pathforall /pop /print /printobject % 120 /put /putinterval /rcurveto /read /readhexstring /readline /readstring /rectclip /rectfill /rectstroke /rectviewclip /repeat /restore /rlineto /rmoveto /roll /rotate /round /save /scale % 140 /scalefont /search /selectfont /setbbox /setcachedevice /setcachedevice2 /setcharwidth /setcmykcolor /setdash /setfont /setgray /setgstate /sethsbcolor /setlinecap /setlinejoin /setlinewidth /setmatrix /setrgbcolor /setshared /shareddict % 160 /show /showpage /stop /stopped /store /string /stringwidth /stroke /strokepath /sub /systemdict /token /transform /translate /truncate /type /uappend /ucache /ueofill /ufill % 180 /undef /upath /userdict /ustroke /viewclip /viewclippath /where /widthshow /write /writehexstring /writeobject /writestring /wtranslation /xor /xshow /xyshow /yshow /FontDirectory /SharedFontDirectory /Courier % 200 /Courier-Bold /Courier-BoldOblique /Courier-Oblique /Helvetica /Helvetica-Bold /Helvetica-BoldOblique /Helvetica-Oblique /Symbol /Times-Bold /Times-BoldItalic /Times-Italic /Times-Roman /execuserobject /currentcolor /currentcolorspace /currentglobal /execform /filter /findresource /globaldict % 220 /makepattern /setcolor /setcolorspace /setglobal /setpagedevice /setpattern % pad to 256 counttomark 256 exch sub { 0 } repeat % 256 /= /== /ISOLatin1Encoding /StandardEncoding % 260 ([) cvn (]) cvn /atan /banddevice /bytesavailable /cachestatus /closefile /colorimage /condition /copypage /cos /countdictstack /countexecstack /cshow /currentblackgeneration /currentcacheparams /currentcolorscreen /currentcolortransfer /currentcontext /currentflat % 280 /currenthalftone /currenthalftonephase /currentmiterlimit /currentobjectformat /currentpacking /currentscreen /currentstrokeadjust /currenttransfer /currentundercolorremoval /defaultmatrix /definefont /deletefile /detach /deviceinfo /dictstack /echo /erasepage /errordict /execstack /executeonly % 300 /exp /false /filenameforall /fileposition /fork /framedevice /grestoreall /handleerror /initclip /initgraphics /initmatrix /instroke /inustroke /join /kshow /ln /lock /log /mark /monitor % 320 /noaccess /notify /nulldevice /packedarray /quit /rand /rcheck /readonly /realtime /renamefile /renderbands /resetfile /reversepath /rootfont /rrand /run /scheck /setblackgeneration /setcachelimit /setcacheparams % 340 /setcolorscreen /setcolortransfer /setfileposition /setflat /sethalftone /sethalftonephase /setmiterlimit /setobjectformat /setpacking /setscreen /setstrokeadjust /settransfer /setucacheparams /setundercolorremoval /sin /sqrt /srand /stack /status /statusdict % 360 /true /ucachestatus /undefinefont /usertime /ustrokepath /version /vmreclaim /vmstatus /wait /wcheck /xcheck /yield /defineuserobject /undefineuserobject /UserObjects /cleardictstack % 376 /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O /P /Q /R /S /T /U /V /W /X /Y /Z /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o /p /q /r /s /t /u /v /w /x /y /z % 428 /setvmthreshold (<<) cvn (>>) cvn /currentcolorrendering /currentdevparams /currentoverprint /currentpagedevice /currentsystemparams /currentuserparams /defineresource /findencoding /gcheck % 440 /glyphshow /languagelevel /product /pstack /resourceforall /resourcestatus /revision /serialnumber /setcolorrendering /setdevparams /setoverprint /setsystemparams /setuserparams /startjob /undefineresource /GlobalFontDirectory /ASCII85Decode /ASCII85Encode /ASCIIHexDecode /ASCIIHexEncode % 460 /CCITTFaxDecode /CCITTFaxEncode /DCTDecode /DCTEncode /LZWDecode /LZWEncode /NullEncode /RunLengthDecode /RunLengthEncode /SubFileDecode /CIEBasedA /CIEBasedABC /DeviceCMYK /DeviceGray /DeviceRGB /Indexed /Pattern /Separation /CIEBasedDEF /CIEBasedDEFG % 480 /DeviceN % 481 -- end //.packtomark exec .installsystemnames % Define printobject and writeobject. % These are mostly implemented in PostScript, so that we don't have to % worry about interrupts or callbacks when writing to the output file. % Define procedures for accumulating the space required to represent % an object in binary form. % <#refs> <#chars> <obj> -proc- <#refs'> <#chars'> /cntdict mark /integertype /pop load /realtype 1 index /marktype 1 index /nulltype 1 index /booleantype 1 index /nametype { length add } .bind /stringtype 1 index /arraytype 0 % replaced below /dicttype 0 % replaced below .dicttomark def /.cntobj { dup type //cntdict exch get exec } .bind def cntdict /arraytype { dup length % #refs #chars array len 4 -1 roll add % #chars array #refs+len dup 65536 gt { /writeobject .systemvar /limitcheck signalerror } if 3 1 roll % #refs+len #chars array //.cntobj forall } .bind put % replace arraytype in cntdict cntdict /dicttype { /writeobject .systemvar /typecheck signalerror } bind put /.bosheader { % <top_length> <total_length> <string8> .bosheader % <string4|8> dup 0 currentobjectformat 127 add put % object format => BOS tag 2 index 255 le 2 index 65531 le and { % Use the short header format: tag toplen(1) totlen(2) exch 4 add exch 0 4 getinterval dup 1 5 -1 roll put } { % Use the long header format: tag 0(1) toplen(2) totlen(4) exch 8 add exch 0 0 4 2 roll .bosobject exch pop exch pop % store with byte swapping } ifelse % Stack: shortlen str exch dup -8 bitshift exch 255 and % str hibyte lobyte currentobjectformat 1 and 0 eq { % lsb first exch } if 2 index 3 3 -1 roll put 1 index 2 3 -1 roll put } .bind def /.writeobjects { % <file> <tag> <array> .writeobjects - % Apply the tag early and forget about it. (12345678) dup 1 5 -1 roll % file array (...) (...) 1 tag put exch % file (.t.) array % Calculate the space required for refs and strings. % Reject excessively large graphs or graphs with loops. 0 0 % file (.t.) array #refs #chars 2 index //.cntobj exec % file (.t.) array #refs #chars % Write the header. 1 index 8 mul add % file (.t.) array #refs #refs*8+#chars 2 index length exch (12345678) % file (.t.) array #refs len(array) #refs*8+#chars (...) //.bosheader exec % file (.t.) array #refs (...) 4 index exch writestring % file (.t.) array #refs % Traverse an array tree in width-first order and place all the % arrays that are found on the operand stack. Acyclic graphs are % expanded to trees. The top parameter K indicates the number % of arrays on a given depth level. At the root level, K is equal to 1. mark 2 index 1 % file (.t.) array #refs -mark- array K { dup 0 le { pop exit } if dup { dup index { dup type /arraytype eq { exch 1 add } { pop } ifelse } forall 1 sub } repeat } loop % file (.t.) array #refs -mark- array1 ... arrayN counttomark 5 add -4 roll % -mark- array1 ... arrayN file (.t.) array #refs % Write the content of the root array 8 mul % -mark- array1 ... arrayN file (.t.) array #refs*8 exch dup length 8 mul % -mark- array1 ... arrayN file (.t.) #refs*8 array len(array)*8 3 1 roll % -mark- array1 ... arrayN file (.t.) len(array)*8 #refs*8 array { 3 index % -mark- array1 ... arrayN file (.t.) len(array)*8 #refs*8 obj (.t.) .bosobject % -mark- array1 ... arrayN file (.t.) len(array)*8 #refs*8 (.t.) 4 index exch writestring % -mark- array1 ... arrayN file (.t.) len(array)*8 #refs*8 } forall 3 -1 roll pop % -mark- array1 ... arrayN file len(array)*8 #refs*8 % Write the remaining arrays counttomark 2 sub -1 3 { index { % ... file #refs #str obj (1\000345678) .bosobject % ... file #refs #str (...) 3 index exch writestring % ... file #refs #str } forall } for pop pop % -mark- array1 ... arrayN file % Write strings and names. counttomark 1 sub -1 1 { index { dup type /nametype eq { .namestring } if dup type /stringtype eq { 1 index exch writestring } { pop } ifelse } forall } for cleartomark % Clean up } .bind def /.writeobject { 3 copy exch % We must allocate the array in local VM % to avoid a possible invalidaccess. .currentglobal //false .setglobal exch 1 array astore exch .setglobal //.writeobjects exec pop pop pop } .bind def /printobject { % <obj> <tag> printobject - currentobjectformat 0 eq { /printobject .systemvar /undefined signalerror } if (%stdout) (w) file 2 index 2 index //.writeobject exec pop pop } odef /writeobject { % <file> <obj> <tag> writeobject - currentobjectformat 0 eq { /writeobject .systemvar /undefined signalerror } if 2 .argindex pop % check # of args //.writeobject exec } odef % Implement binary error message output. /.objectprinttest { % <obj> .objectprinttest - % This is a pseudo-operator so it will restore the stack % if it gets an error. mark 0 0 3 .argindex //.cntobj exec cleartomark pop } bind def /.printerror { $error /binary get .languagelevel 2 ge and { currentobjectformat 0 ne { [ /Error $error /errorname get $error /command get % Convert the object with cvs if it isn't printable. dup { //.objectprinttest exec } //.internalstopped exec { pop 100 string cvs } if //false ] 250 printobject } //.printerror % known to be a procedure ifelse } //.printerror % known to be a procedure ifelse } bind def currentdict /cntdict .undef % End of level2dict end .setlanguagelevel % undefine things defined in this file and not referenced elsewhere [ /.objectprinttest /.bosheader /.cntobj /.writeobject /.writeobjects ] dup level2dict .undefinternalnames systemdict .undefinternalnames pdf_ops.ps 0000644 00000224561 15030647507 0006563 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % 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 executeonly put } if systemdict /pdfdict where { pop } { /pdfdict 325 dict put } ifelse userdict /GS_PDF_ProcSet 256 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 { % <initialdict> dictbeginpage - 20 dict copy dup begin 1 packedarray cvx executeonly /self exch def graphicsbeginpage textbeginpage } bind executeonly def /endpage { % - endpage - showpage end } bind executeonly def /graphicsbeginpage { initgraphics //true .setaccuratecurves currentdict /ClipRect knownoget { aload pop rectclip } if % inigraphics sets the gstate colorspace and color correctly % *but* pdfwrite's transparency handling can get upset if we % don't explicitly set color and space here. currentcolor currentcolor currentcolorspace dup .setfillcolorspace .setstrokecolorspace .setfillcolor .setstrokecolor //false op //false OP 0 OPM 1 ca 1 CA //null SMask //false AIS /Compatible BM //true TK } bind executeonly def % We must allow /Show to be set, otherwise a text operation can % end up in infinite recursion with showfirst calling Show, and % Show calling showfirst. /gput_always_allow 1 dict dup begin /Show 0 def end def /gput % <value> <key> gput - { dup //gput_always_allow exch known not currentdict /n known and { pop pop ( **** Error: Ignoring changes to the graphic state after operator 'W'.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror } { exch currentdict //nodict eq { /self dup load end 5 dict begin def } if def } ifelse } bind executeonly def currentdict /gput_always_allow .undef /q { %% Special case, if we get a 'q' while accumulating clip/eoclip then %% we need to make sure we close the current dictionary, and reopen it after %% performing the gsave, so that the redefinition of 'n' in particular is correct currentdict /n known { currentdict %% copy the dicitonary for the accumulation end %% and close it (NB *before* the gsave!) gsave //nodict begin %% execute gsave and start 'nodict' just like normal begin %% reopen the accumulation dictionary. %% when we execute 'n' this will close and we'll go back %% to the regular 'nodict' opened above. This could cause some %% odd interactions with 'Q' for unbalanced files..... } { %% ugly hackery to work around badly broken PDF file in Bug #695897. The file has nested BT/ET %% sections, and delimits them with q/Q. The problem is that our code to deal with nested %% text sections looks in the current dictionary for TextSaveMatrix, and a 'q' makes a brand %% new empty dictionary, so it defeats it. %% I tried copying the TextSaveMatrix from the parent state into this one, but that then causes %% other problems because we end up apllying the TextSaveMatrix when we shouold not. Attempting %% to clear the TextSaveMatrix from all saved states on ET then caused it not to be defined at %% times when we needed it..... %% This is all terribly flaky, but defining a new matrix inside gsaves that tells us that we had %% were already in a text block allows us to detect and cope with the nested BT's and leaving the %% original TextSaveMatrix behind allows the matching ET not to throw an error, as well as coping %% with the various other problems listed above. Its not pretty though. currentdict /TextSaveMatrix known { currentdict /TextSaveMatrix get matrix copy gsave //nodict begin /qTextSaveMatrix gput }{ gsave //nodict begin }ifelse } ifelse PDFusingtransparency { .pushextendedgstate } if } bind executeonly def % Some PDF files have excess Q operators! /Q { //false { currentdict /n known { end pop //true } { exit } ifelse } loop { ( **** Error: Encountered a 'Q' before finishing 'W' mode.\n) pdfformaterror ( Output may be incorrect..\n) pdfformaterror } if currentdict /self .knownget { exec //nodict eq { end PDFusingtransparency { .popextendedgstate } if % 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} stopped { ( **** Error: unable to preserve current path, probable degenerate CTM, output may be incorrect.\n) pdfformaterror grestore newpath }{ grestore newpath { exec } forall } ifelse //false } { //true } ifelse } { //true % formaterror -- not a gsave dict } ifelse { (\n **** Error: File has unbalanced q/Q operators \(too many Q's\)\n Output may be incorrect.\n) //pdfdict /.Qqwarning_issued .knownget { { pop } { currentglobal //pdfdict gcheck .setglobal //pdfdict /.Qqwarning_issued //true .forceput .setglobal pdfformaterror } executeonly ifelse } executeonly { currentglobal //pdfdict gcheck .setglobal //pdfdict /.Qqwarning_issued //true .forceput .setglobal pdfformaterror } executeonly ifelse } executeonly if } bind executeonly odef % Save PDF gstate /qstate { % - qstate <qstate> gstate } bind executeonly def % 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 } bind executeonly def % ---------------- Color setting ---------------- % /nullpatternproc { pop } bind executeonly def /nullpattern mark /PatternType 1 /PaintType 1 /TilingType 3 /BBox [0 0 1 1] /XStep 1 /YStep 1 /PaintProc //nullpatternproc .dicttomark readonly def /PDFsetpattern { % 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 .currentfillconstantalpha .currentstrokeconstantalpha DefaultQstate setqstate .setstrokeconstantalpha .setfillconstantalpha makepattern grestore dup 3 1 roll DefaultQstate exch put } if } ifelse } bind executeonly def /CSdict mark /DeviceGray { 0 } bind executeonly /DeviceRGB { [0 0 0] cvx } bind executeonly /DeviceCMYK { [0 0 0 1] cvx } bind executeonly /CIEBasedA { 0 } bind executeonly /CIEBasedABC { [0 0 0] cvx } bind executeonly /CalGray { 0 } bind executeonly /CalRGB { [0 0 0] cvx } bind executeonly /Lab {[0 0 0] cvx } bind executeonly /ICCBased { [ 1 index 1 oget /N get { 0 } repeat ] cvx } bind executeonly /Separation { 1 } bind executeonly /DeviceN { % What is the correct value?? [ 1 index 1 get length { 1 } repeat ] cvx } bind executeonly /Indexed { 0 } bind executeonly /Pattern { //nullpattern matrix makepattern } bind executeonly .dicttomark readonly def /ri {//.renderingintentdict exch .knownget { .setrenderingintent } if } bind executeonly def /g {/DeviceGray .setfillcolorspace .setfillcolor } bind executeonly def /G {/DeviceGray .setstrokecolorspace .setstrokecolor} bind executeonly def /rg {/DeviceRGB .setfillcolorspace .setfillcolor} bind executeonly def /RG {/DeviceRGB .setstrokecolorspace .setstrokecolor} bind executeonly def /k {/DeviceCMYK .setfillcolorspace .setfillcolor} bind executeonly def /K {/DeviceCMYK .setstrokecolorspace .setstrokecolor} bind executeonly def /cs {dup dup type /nametype ne { 0 get } if dup /ICCBased eq { 1 index 1 get /OrigN .knownget not {1 index 1 get /N get} if mark 4 2 roll //CSdict exch get exec exch .setfillcolorspace exec {.setfillcolor} stopped { cleartomark [//null /DeviceGray //null /DeviceRGB /DeviceCMYK] exch {get} stopped { ( **** Error: Unable to set an ICCBased colour space, and cannot set an alternate from the number of components.\n) print /setcolorspace cvx /undefined signalerror } { dup //null eq { ( **** Error: Unable to set an ICCBased colour space, and cannot set an alternate from the number of components.\n) print /setcolorspace cvx /undefined signalerror }{ ICCProfileNError flush not { ( **** Warning : Error setting an ICCBased colour space, using /N to set an alternate device space.\n) print ( Output may be incorrect.\n) print } if setcolorspace /ICCProfileNError where {/ICCProfileNError //true put} if } ifelse }ifelse }{ cleartomark pop } ifelse } { //CSdict exch get exec exch .setfillcolorspace exec .setfillcolor } ifelse } bind executeonly def /CS {dup dup type /nametype ne { 0 get } if dup /ICCBased eq { 1 index 1 get /OrigN .knownget not {1 index 1 get /N get} if mark 4 2 roll //CSdict exch get exec exch .setstrokecolorspace exec {.setstrokecolor} stopped { cleartomark [//null /DeviceGray //null /DeviceRGB /DeviceCMYK] exch {get} stopped { ( **** Error: Unable to set an ICCBased colour space, and cannot set an alternate from the number of components.\n) print /setcolorspace cvx /undefined signalerror } { dup //null eq { ( **** Error: Unable to set an ICCBased colour space, and cannot set an alternate from the number of components.\n) print /setcolorspace cvx /undefined signalerror }{ ICCProfileNError flush not { ( **** Warning : Error setting an ICCBased colour space, using /N to set an alternate device space.\n) print ( Output may be incorrect.\n) print } if setcolorspace /ICCProfileNError where {/ICCProfileNError //true put} if } ifelse }ifelse }{ cleartomark pop } ifelse } { //CSdict exch get exec exch .setstrokecolorspace exec .setstrokecolor } ifelse } bind executeonly def /sc {.setfillcolor} bind executeonly def /SC {.setstrokecolor} bind executeonly def /sc* {.setfillcolor} bind executeonly def /SC* {.setstrokecolor} bind executeonly def /sc*_and_set { dup type /dicttype eq { dup /Type known { dup /Type get /Pattern eq {PDFsetpattern} if } { dup /PatternType known {PDFsetpattern} if } ifelse } if .setfillcolor } bind executeonly def /SC*_and_set { dup type /dicttype eq { dup /Type known { dup /Type get /Pattern eq {PDFsetpattern} if } { dup /PatternType known {PDFsetpattern} if } ifelse } if .setstrokecolor } bind executeonly def /sc1 {.setfillcolor} bind executeonly def /SC1 {.setstrokecolor} bind executeonly def /sc1_and_set { dup type /dicttype eq { dup /Type known { dup /Type get /Pattern eq {PDFsetpattern} if } { dup /PatternType known {PDFsetpattern} if } ifelse } if .setfillcolor } bind executeonly def /SC1_and_set { dup type /dicttype eq { dup /Type known { dup /Type get /Pattern eq {PDFsetpattern} if } { dup /PatternType known {PDFsetpattern} if } ifelse } if .setstrokecolor } bind executeonly def /csput {dup dup type /nametype ne { 0 get } if //CSdict exch get exec exch 2 copy .setfillcolorspace exec .setfillcolor .setstrokecolorspace exec .setstrokecolor} bind executeonly def /csset {dup dup type /nametype ne { 0 get } if //CSdict exch get exec exch} bind executeonly def % ---------------- Color setting ---------------- % % ---------------- Overprint/transparency setting ---------------- % /op { .setfilloverprint } bind executeonly def % NB pdf_draw:gsparamdict handled /OP with no /op /OP { .setstrokeoverprint } bind executeonly def /OPM { /.setoverprintmode where { pop dup .setoverprintmode .swapcolors .setoverprintmode .swapcolors } { pop } ifelse } bind executeonly def /ca { .setfillconstantalpha } bind executeonly def /CA { .setstrokeconstantalpha } bind executeonly def /SMask { dup type /booleantype eq { .currentSMask type /dicttype eq { .currentSMask /Processed 2 index .forceput } executeonly { .setSMask }ifelse } executeonly { .setSMask }ifelse %% This is some craziness to do with annotations and graphics states %% the original nodict can't be written to, and we haven't (I think) done %% a gsave, so we haven't copied it to /self, if we don't do that here %% then transparent annotations cause an invalid access error. currentdict //nodict eq {/self dup load end 5 dict begin def} if } bind executeonly odef /AIS { .setalphaisshape } bind executeonly def /BM { /.setblendmode where { pop [ exch dup type /nametype ne { aload pop } if /Normal ] { { .setblendmode } //.internalstopped exec not { exit } if pop } forall } { pop } ifelse } bind executeonly def /TK { /.settextknockout where { pop .settextknockout } { pop } ifelse } bind executeonly def /UseBlackPtComp { %% Our implementation of black point compensation uses 0 or 1, not a boolean /.setblackptcomp where {pop //false eq {0}{1}ifelse .setblackptcomp }{ pop } ifelse } bind executeonly def % ---------------- Color installation ---------------- % % Establish a given color (and color space) as current. /.settransparencyparams { % <smask> .settransparencyparams - PDFusingtransparency { .currentalphaisshape { 1 } { 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 } ifelse } bind executeonly def /.settransparencymask { % <paramdict> <masknum> .settransparencymask - exch dup type /dicttype ne { PDFusingtransparency { pop pop } { dup /Draw get exec } ifelse } { dup /Processed .knownget { { pop pop } { dup /Draw get exec }ifelse }{ dup /Draw get exec } ifelse } ifelse } bind executeonly def /setsmaskstate { .currentSMask .settransparencyparams } bind executeonly def /Cdict 15 dict dup begin % <color...> <colorspace> -proc- - /DeviceGray { pop setgray } bind executeonly def /DeviceRGB { pop setrgbcolor } bind executeonly def /DeviceCMYK { pop setcmykcolor } bind executeonly def /CIEBasedA { setgcolorspace setcolor } bind executeonly def /CIEBasedABC /CIEBasedA load def /CIEBasedDEF /CIEBasedA load def /CIEBasedDEFG /CIEBasedA load def /CalRGB /CIEBasedA load def /CalGray /CIEBasedA load def /Lab /CIEBasedA load def %% This section is to deal with the horrible pair of files in Bug #696690 and Bug #696120 %% These files have ICCBased spaces where the value of /N and the number of components %% in the profile differ. In addition the profile in Bug #696690 is invalid. In the %% case of Bug #696690 the /N value is correct, and the profile is wrong, in the case %% of Bug #696120 the /N value is incorrect and the profile is correct. %% We 'suspect' that Acrobat uses the fact that Bug #696120 is a pure image to detect %% that the /N is incorrect, we can't be sure whether it uses the profile or just uses %% the /N to decide on a device space. What we now do is; If the /N and device profile %% number of components don't match, we assume the device profile is correct and patch %% /N to be the same as the profile (see /ICCBased-resolve), but we save the original %% value of /N in /OrigN. In setcolor, if the space is a genuine ICCBased space %% (not a replacement for a device profile) we call set_dev_color which will actually %% exercise the profile. If that fails we return an error. Here we run setcolor in a %% stopped context, and if it fails we check to see if there is a /OrigN (ths occurs %% only if the /N was different to the number of components in the profile). If there %% is a /OrigN then prefer that to the profile, otherwise they agreed, so just use %% /N and select a device space. If we can't select a device space with the correct %% number of components, give up and throw an error. See also /last-ditch-bpc-csp %% in pdf_draw.ps. /ICCBased { dup 1 get dup /OrigN .knownget {exch /N get}{/N get dup} ifelse 3 add mark exch 2 roll setgcolorspace {setcolor} stopped { cleartomark [//null /DeviceGray //null /DeviceRGB /DeviceCMYK] exch {get} stopped { ( **** Error: Unable to set an ICCBased colour space, and cannot set an alternate from the number of components.\n) print /setcolorspace cvx /undefined signalerror } { dup //null eq { ( **** Error: Unable to set an ICCBased colour space, and cannot set an alternate from the number of components.\n) print /setcolorspace cvx /undefined signalerror }{ ICCProfileNError flush not { ( **** Warning : Error setting an ICCBased colour space, using /N to set an alternate device space.\n) print ( Output may be incorrect.\n) print } if setcolorspace /ICCProfileNError //true def } ifelse }ifelse }{ cleartomark pop } ifelse } bind executeonly 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 .currentfillconstantalpha .currentstrokeconstantalpha DefaultQstate setqstate .setstrokeconstantalpha .setfillconstantalpha makepattern grestore dup 3 1 roll DefaultQstate exch put } if } ifelse setcolor } bind executeonly def end def /setgcolor % (null | <color...>) <colorspace> setgcolor - { 1 index //null eq { pop pop } { dup 0 get //Cdict exch get exec } ifelse } bind executeonly def % 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 } bind executeonly def /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 } bind executeonly def end def /pdfcolorspace { % <colorspace> pdfcolorspace <colorspace|pdfcspace> dup type /arraytype eq { //PCSdict 1 index 0 get .knownget { exec } if } if } bind executeonly def /setgcolorspace { % <colorspace> setgcolorspace - dup pdfcolorspace currentcolorspace pdfcolorspace eq { pop } { setcolorspace } ifelse } bind executeonly def /OPsaveDstack 6 dict def % for GroupPushed, saveOP, saveFillAlpha, saveBM //OPsaveDstack begin /GroupPushed //false def /ChangeBM //false def /saveStrokeAlpha 1 def /saveFillAlpha 1 def /saveBM /Normal def /previous 1 dict def % for nested setup_trans levels end /Dpush { .currentglobal //true .setglobal % 'previous' dict must be in global VM //OPsaveDstack 6 dict 1 index { 2 index 3 1 roll put } forall /previous exch put .setglobal } def /Dpop { //OPsaveDstack begin previous { def } forall end } def % colorspaces that require special overprint transparency handling /specialOPcs mark /DeviceGray 0 /DeviceCMYK 1 /DeviceN 2 /Separation 3 .dicttomark def % Take care of pushing a transparency group if we need it for SMask or for Overprint.. % After pushing the group, we save the ca and CA and change them % both to 1. For overprint if the colorspace is acceptable, also change to % CompatibleOverprint if the device needs it. % NB: setup_trans is defined as either setupOPtrans (for devices that can support % overprint, or as setupSMtrans which pushes a group for SMask. % Also see 'teardown_trans' that pops the group and resets the changed values. /setupOPtrans % [ pathbbox ] <fillop|strokeop> setup_trans { % Check OP and BM in case we need to push a group //OPsaveDstack begin //Dpush exec % push the current OPsaveDstack values into 'previous' /SupportsDevn .special_op specialOPcs currentcolorspace 0 get dup /Indexed eq { pop currentcolorspace 1 get % use the base space } if known or { dup /stroke ne { .currentfilloverprint 1 index dup /.fillstroke eq exch /.eofillstroke eq or { .currentstrokeoverprint or } if } { .currentstrokeoverprint } ifelse % Change BM to CompatibleOverprint if this has overprint true dup /ChangeBM exch def .currentblendmode dup /Normal eq exch /Compatible eq or not and } { //false } ifelse .currentSMask //null ne or { % push a group for OP or SMask mark /Subtype /Group /Isolated .currentSMask //null ne .dicttomark 2 index aload pop % pathbbox .begintransparencygroup % After group pushed, set alphas and blendmode /saveStrokeAlpha .currentstrokeconstantalpha def /saveFillAlpha .currentfillconstantalpha def 1 .setfillconstantalpha 1 .setstrokeconstantalpha /GroupPushed //true def } { /GroupPushed //false def } ifelse % we may change to CompatibleOverprint even if we didn't push a group. ChangeBM { /saveBM .currentblendmode def /CompatibleOverprint .setblendmode } if pop % fillop/strokeop pop % pathbbox array end % OPsaveDstack } bind executeonly def % Also see 'teardown_trans' that pops the group and resets the changed values. /setupSMtrans % [ pathbbox ] <fillop|strokeop> setup_trans { //OPsaveDstack begin //Dpush exec % push the current OPsaveDstack values into 'previous' .currentSMask //null ne 1 index /image ne and % only push for SMask if not from image { mark /Subtype /Group /Isolated //true .dicttomark 2 index aload pop % pathbbox .begintransparencygroup % After group pushed, set alphas and blendmode /saveStrokeAlpha .currentstrokeconstantalpha def /saveFillAlpha .currentfillconstantalpha def 1 .setfillconstantalpha 1 .setstrokeconstantalpha /GroupPushed //true def } { /GroupPushed //false def } ifelse end % OPsaveDstack pop % fillop/strokeop pop % pathbbox array } bind executeonly def % If a transparency group was pushed, pop it, and reset the settings. % Used after setup_trans /teardown_trans { //OPsaveDstack begin GroupPushed { % pop the group, then restore the alphas .endtransparencygroup % end the group saveStrokeAlpha .setstrokeconstantalpha saveFillAlpha .setfillconstantalpha } if % Also, if we changed the BM, restore it (AFTER the group was popped) .currentblendmode /CompatibleOverprint eq { % restore the blendmode saveBM .setblendmode } if end % OPsaveDstack //Dpop exec % load previous OPsaveDstack contents } bind executeonly def currentdict dup /Dpush .undef /Dpop .undef % ------------------------------------------------------------ % /fsexec % <fillop|strokeop> fsexec - { PDFusingtransparency { dup /stroke eq 1 index /.fillstroke eq or 1 index /.eofillstroke eq or { % BBox needs to include line width / line join expansion. % strokepath will return empty path (no currentpoint) if nothing is stroked { gsave strokepath pathbbox } stopped grestore { % If we get an error, just emit an empty box 0 0 0 0 } if } { % If we get an error, just emit an empty box { pathbbox } stopped { 0 0 0 0 } if } ifelse % pathbbox valid -- proceed with drawing 4 array astore % pathbbox 1 index setup_trans cvx exec teardown_trans } { cvx exec } ifelse } bind executeonly def % ---------------- Path painting and clipping ---------------- % %% Bug #696017 In order to get the correct position of paths and other objects which %% are illegally present inside a text block, we need to use the saved TextSaveMatrix %% to construct/place them. But we don't want to do lots of lookups on every segment of %% a path (we feel its OK to do lookups for images). So what we do is redefine the %% path contruction operators at the beginning of a text block, and put them back afterwards. %% Here we define the 'normal' and 'inside text' versions of those operators, and routines %% to switch the definitions back and forth. /check_and_set_saved_matrix { currentdict /TextSaveMatrix known { currentdict /TextSaveMatrix get setmatrix } { currentdict /qTextSaveMatrix known { currentdict /qTextSaveMatrix get setmatrix } if } ifelse } bind executeonly def /normal_m { { moveto } stopped { count pdfemptycount sub 2 .min { pop } repeat 0 0 moveto } if } bind executeonly def /inside_text_m { { matrix currentmatrix 3 1 roll check_and_set_saved_matrix moveto setmatrix } stopped { count pdfemptycount sub 2 .min { pop } repeat 0 0 moveto } if } bind executeonly def /normal_l { { lineto } stopped { count pdfemptycount sub 2 .min { pop } repeat } if } bind executeonly def /inside_text_l { { matrix currentmatrix 3 1 roll check_and_set_saved_matrix lineto setmatrix } stopped { count pdfemptycount sub 2 .min { pop } repeat } if } bind executeonly def /normal_c { { curveto } stopped { count pdfemptycount sub 6 .min { pop } repeat } if } bind executeonly def /inside_text_c { { matrix currentmatrix 7 1 roll check_and_set_saved_matrix curveto setmatrix } stopped { count pdfemptycount sub 6 .min { pop } repeat } if } bind executeonly def /normal_v { count pdfemptycount sub 4 ge { { currentpoint 6 2 roll curveto } stopped { count pdfemptycount sub 6 .min { pop } repeat } if } { count pdfemptycount sub { pop } repeat } ifelse } bind executeonly def /inside_text_v { count pdfemptycount sub 4 ge { { matrix currentmatrix 5 1 roll check_and_set_saved_matrix currentpoint 6 2 roll curveto setmatrix } stopped { count pdfemptycount sub 6 .min { pop } repeat } if } { count pdfemptycount sub { pop } repeat } ifelse } bind executeonly def /normal_y { { 2 copy curveto } stopped { count pdfemptycount sub 6 .min { pop } repeat } if } bind executeonly def /inside_text_y { { matrix currentmatrix 5 1 roll check_and_set_saved_matrix 2 copy curveto setmatrix } stopped { count pdfemptycount sub 6 .min { pop } repeat } if } bind executeonly def /normal_re { 4 2 roll moveto exch dup 0 rlineto 0 3 -1 roll rlineto neg 0 rlineto closepath } bind executeonly def /inside_text_re { matrix currentmatrix 5 1 roll check_and_set_saved_matrix 4 2 roll moveto exch dup 0 rlineto 0 3 -1 roll rlineto neg 0 rlineto closepath setmatrix } bind executeonly def /S { OFFlevels length 0 eq { setsmaskstate .swapcolors /stroke fsexec .swapcolors } { newpath } ifelse } bind executeonly def /f { OFFlevels length 0 eq { setsmaskstate /fill fsexec } { newpath } ifelse } bind executeonly def /f* { OFFlevels length 0 eq { setsmaskstate /eofill fsexec } { newpath } ifelse } bind executeonly def /n { newpath } bind executeonly def % don't allow n to get bound in /s { closepath S } bind executeonly def /B { OFFlevels length 0 eq { setsmaskstate /.fillstroke fsexec } { newpath } ifelse } bind executeonly def /b { closepath B } bind executeonly def /B* { OFFlevels length 0 eq { setsmaskstate /.eofillstroke fsexec } { newpath } ifelse } bind executeonly def /b* { closepath B* } bind executeonly def % Clipping: /Wdict 8 dict dup begin /S { OFFlevels length 0 eq { gsave setsmaskstate .swapcolors stroke .swapcolors grestore } if n } bind executeonly def /f { OFFlevels length 0 eq { gsave setsmaskstate fill grestore } if n } bind executeonly def /f* { OFFlevels length 0 eq { gsave setsmaskstate eofill grestore } if n } bind executeonly def /B { OFFlevels length 0 eq { .fillstroke } if n } bind executeonly def /b { closepath B } bind executeonly def /B* { OFFlevels length 0 eq { .eofillstroke } if n } bind executeonly def /b { closepath B* } bind executeonly def /n { end .currentpoint_valid { clip } if newpath } bind executeonly def end readonly def /W { //Wdict begin } bind executeonly def /W*dict 8 dict dup begin Wdict { def } forall /n { end .currentpoint_valid { eoclip } if newpath } bind executeonly def end readonly def /W* { //W*dict begin } bind executeonly def % ---------------- Text control ---------------- % /textbeginpage { 1.0 .settexthscaling /FontMatrixNonHV //false def /Show { showfirst } def /TextFillStateNeeded //true def } bind executeonly def /TestDegenerateCTM { matrix currentmatrix dup 0 get exch dup 3 get exch dup 1 get exch 2 get mul 3 1 roll mul exch sub 0 eq { //true }{ //false } ifelse } bind executeonly def % 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 { matrix currentmatrix matrix .currenttextmatrix concat TestDegenerateCTM { (\n **** Error: Degenerate text matrix detected, ignoring Tm operation\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror setmatrix } { pop } ifelse .currenttexthscaling 1 ne { .currenttexthscaling 1 scale } if .currenttextrise 0 ne { 0 .currenttextrise translate } if } bind executeonly def /settextstate { % The text state can be set even outside BT/ET. currentdict /TextSaveMatrix known { TextSaveMatrix aload pop 5 index 0 ne 3 index 0 ne and 5 index 0 ne 5 index 0 ne and or not { (\n **** Error: Invalid (0 scaling) text matrix for Tm ****\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror % handle invalid scale by using a really small value 2 -6 roll pop pop pop pop 0.00000001 0 0 0.00000001 6 -2 roll }if 6 array astore setmatrix settextmatrix } if currentdict /qTextSaveMatrix known { qTextSaveMatrix aload pop 5 index 0 ne 3 index 0 ne and 5 index 0 ne 5 index 0 ne and or not { (\n **** Error: Invalid (0 scaling) text matrix for Tm ****\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror % handle invalid scale by using a really small value 2 -6 roll pop pop pop pop 0.00000001 0 0 0.00000001 6 -2 roll }if 6 array astore setmatrix settextmatrix } if } bind executeonly def /settextposition { % Update the TextMatrix translation. gsave TextSaveMatrix setmatrix .currentpoint_valid { currentpoint .currenttextrise sub matrix .currenttextmatrix dup 5 4 -1 roll put dup 4 4 -1 roll put .settextmatrix % 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 matrix .currenttextmatrix grestore .settextmatrix TextTempMatrix currentmatrix 4 2 getinterval astore pop TextTempMatrix setmatrix } { ( **** Error: Invalid currentpoint, probable degenerate CTM.\n) pdfformaterror ( Ignroing error, output may be incorrect.\n) pdfformaterror grestore } ifelse } bind executeonly def %% Do not make the procedures here executeonly. The /m procedure is %% tested in /.pdf_paintproc in pdf_draw.ps, we need to be able to %% read the name of the procedure from here in order to determine %% whether we are inside a text block. The procedures themselves %% are already executeonly anyway. /switch_to_text_marking_ops { pdfopdict /m {inside_text_m} bind .forceput pdfopdict /l {inside_text_l} bind .forceput pdfopdict /c {inside_text_c} bind .forceput pdfopdict /v {inside_text_v} bind .forceput pdfopdict /y {inside_text_y} bind .forceput pdfopdict /re {inside_text_re} bind .forceput } bind executeonly odef /switch_to_normal_marking_ops { pdfopdict /m {normal_m} bind .forceput pdfopdict /l {normal_l} bind .forceput pdfopdict /c {normal_c} bind .forceput pdfopdict /v {normal_v} bind .forceput pdfopdict /y {normal_y} bind .forceput pdfopdict /re {normal_re} bind .forceput } bind executeonly odef /BT { % Bug 703996 has a path defined before BT, then stroked afterwards .currentpoint_valid { //false upath } { //null } ifelse /BT_upath gput //false /illegal_BT gput currentdict /TextSaveMatrix known { ( **** Error: illegal nested BT operator detected.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror ET_NO_TXT_KO %% Does not push any compositor actions //true /illegal_BT gput } if %% Bug #695897 see the explanation in /q defined above. currentdict /qTextSaveMatrix known { currentdict /qTextSaveMatrix get /TextSaveMatrix gput ( **** Error: Illegal nested BT operator (inside a gsave) detected.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror ET_NO_TXT_KO %% Does not push any compositor actions //true /illegal_BT gput } if currentdict /n known { currentdict end /.W exch def } if matrix .settextlinematrix matrix .settextmatrix { showfirst } /Show gput currentdict /TextSaveMatrix .knownget not { matrix dup /TextSaveMatrix gput } if currentmatrix pop settextmatrix matrix /TextTempMatrix gput % see settextposition %% Set the special version of the path constructoin operators, so that %% they will work as expected if they are illgeally present in a text block. switch_to_text_marking_ops %% If needed, let the pdf14 device know we are in a BT condition. This %% distinguishes BT from an Annotation /FreeText show command which also %% can come into pdf_text_begin with an opacity not equal to 1. PDFusingtransparency .currenttextknockout and currentdict /illegal_BT get not and { .begintransparencytextgroup } if } bind executeonly def /clip_if_required { .currenttextrenderingmode 4 ge .currentpoint_valid and { .currentfilladjust2 0 dup .setfilladjust2 clip .setfilladjust2} if newpath } bind def /ET_NO_TXT_KO { currentdict /TextSaveMatrix known { //clip_if_required exec TextSaveMatrix setmatrix currentdict /TextSaveMatrix undef % if we were in a W/W* context, grab the dict, undefine temp entry for it, % and push it back on the dict stack currentdict /.W known { .W currentdict /.W undef begin } if } { ( **** Error: Ignoring spurious ET operator.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror } ifelse %% Only switch back to the regular marking operations if we were not %% in a nested text block (inside a gsave). currentdict /qTextSaveMatrix known not { switch_to_normal_marking_ops currentdict /BT_upath get dup //null eq { pop } { newpath uappend } ifelse } if } bind executeonly def currentdict /clip_if_required .undef /ET { //ET_NO_TXT_KO exec % Group push occurred in pdf14_text_begin. PDFusingtransparency .currenttextknockout and { .endtransparencytextgroup } if } bind executeonly def /Tc { {.settextspacing} stopped { (\n **** Error: A ) pdfformaterror $error /errorname get 256 string cvs pdfformaterror ( error occured while setting the Text Character spacing to ) pdfformaterror 256 string cvs pdfformaterror (\n Output may be incorrect.\n) pdfformaterror } if { showfirst } /Show gput } bind executeonly def /TL { .settextleading } bind executeonly def /Tr { .settextrenderingmode { showfirst } /Show gput } bind executeonly def /Ts { .settextrise settextstate } bind executeonly def /Tw { .setwordspacing { showfirst } /Show gput } bind executeonly def /Tz { dup 0 eq { (\n **** Error: Invalid 0.0 horizontal text scaling given for Tz\n) ( Output may be incorrect.\n) pdfformaterror pdfformaterror pop 0.00000001 % handle invalid scale by using a really small value }{ 100 div }ifelse .settexthscaling %/TextHScaling gput settextstate} bind executeonly def % ---------------- 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 <<fontdict>> -- ?horz ?nonhv /FontMatrix .knownget { 1 index { 1 } { 2 } ifelse get 0 ne } { //false } ifelse } bind executeonly def % Worker procedure for recursive checking of font matrices /?FontMatrixNonHV { % {self} ?horz <<font>> -- {self} ?horz ?nonhv 2 copy //?FontMatrixNonHV exec { % check the font's own FontMatrix pop pop //true } { % look for descendents/ components pop % {self} ?horz <<font>> 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 <<subfont>> 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 } bind executeonly def % Main procedure /?FontMatrixNonHV { % <<rootfont>> -- ?nonhv //?FontMatrixNonHV exch % determine WMode dup /WMode .knownget { 0 eq } { //true } ifelse % {proc} <<rootfont>> ?horz exch % call the worker procedure //?FontMatrixNonHV exec exch pop exch pop } bind executeonly def /Tf { % <font> <scale> Tf - dup .setPDFfontsize dup 0 eq { 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 setfont } bind executeonly def % 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 /.OrigUniqueIDXUID .knownget {//false} { 1 index /XUID .knownget { //true 1 index {0 gt and} forall {//false}{pop //true} ifelse } { //true }ifelse } ifelse { 1 index /UniqueID .knownget {[exch]}{//null} ifelse } if 3 1 roll 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 not { 3 copy put } if pop pop } forall exch } if pop 1 index //null eq {exch pop} {dup 3 -1 roll /.OrigUniqueIDXUID exch put} ifelse } bind executeonly def % 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 } ifelse } bind executeonly def /.updatefontencoding { % <font> <Encoding|null> .updatefontencoding % <font'> <copied> dup //null ne { dup 2 index /Encoding get ne } { //false } ifelse { exch //false .copyfontdict dup /Encoding 4 -1 roll put //true } { pop //false } ifelse } bind executeonly def % Duplicate keys in CharString dictionary according to GlyphMap: <</new_glyph /old_glyph>> % 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 { % <font> <GlyphMap> .update_charstring <font'> <copied> 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 } bind executeonly def /.updatefont { % <font> <Encoding|null> <Metrics|null> <GlyphMap|null> % .updatefont <font'> <copied> 4 2 roll % <Metrics|null> <GlyphMap> <font> <Encoding|null> .updatefontencoding % <Metrics|null> <GlyphMap> <font> bool 4 1 roll exch % bool <Metrics|null> <font> <GlyphMap> .update_charstring % bool <Metrics|null> <font> bool 3 1 roll exch % bool bool <font> <Metrics|null> .updatefontmetrics % bool bool <font> bool 4 2 roll or or % <font> is_copied } bind executeonly def % ---------------- Text positioning ---------------- % /Td { %% Bug #695950 - invalid parameter to 'Td' operator %% Technically the parameters to Td are reals and can vary +/- 3.403x10^38 %% However that would be kind of hard to validate, and in any event these %% are somewhat unlikely numbers. We validate against +/- 2^32 instead. If this %% should ever be a problem we'll have to modify this check. %% Testing reveals that Acrobat clamps these out of range values to 0, it doesn't %% simply ignore the error. exch dup dup 4294967295 ge exch 4294967295 neg le or { ( **** Error: invalid argument to Td, Treating argument as 0.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror pop 0 } if exch dup dup 4294967295 ge exch 4294967295 neg le or { ( **** Error: invalid argument to Td, Treating argument as 0.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror pop 0 } if matrix .currenttextlinematrix transform matrix .currenttextlinematrix dup 3 -1 roll 5 exch put dup 3 -1 roll 4 exch put .settextlinematrix matrix .currenttextlinematrix .settextmatrix settextstate } bind executeonly def /TD { dup neg .settextleading Td } bind executeonly def /T* { 0 .currenttextleading neg Td } bind executeonly def /Tm { 5 index 0 ne 3 index 0 ne and 5 index 0 ne 5 index 0 ne and or not { ( **** Error: Invalid (0 scaling) text matrix for Tm ****\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror % handle invalid scale by using a really small value 2 -6 roll pop pop pop pop 0.00000001 0 0 0.00000001 6 -2 roll }if matrix .currenttextlinematrix astore .settextlinematrix matrix .currenttextlinematrix .settextmatrix settextstate } bind executeonly def % ---------------- Text painting ---------------- % /Vexch { rootfont /WMode knownoget { 1 eq { exch } if } if } bind executeonly def /textrenderingprocs [ % (0 is handled specially) % Painting-only modes { tf } executeonly { tS } executeonly { tB } executeonly { tn } % Clipping modes { gsave tf grestore tW } executeonly { gsave tS grestore tW } executeonly { gsave tB grestore tW } executeonly { tW } executeonly ] readonly def /pdfwrite_textrenderingprocs [ % Tr 0 - Fill { setsmaskstate show } bind executeonly % Tr 1 - Stroke { currentlinewidth exch setsmaskstate % 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. calc_text_linewidth setlinewidth show setlinewidth} bind executeonly % Tr 2 - Fill then Stroke { currentlinewidth exch setsmaskstate % 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. calc_text_linewidth setlinewidth setsmaskstate show setlinewidth} bind executeonly % Tr 3 - Neither fill nor stroke { setsmaskstate show } bind executeonly % % pdfwrite emits all text inside a gsave/grestore pair. As % a result we can't preserve any of the 'clip' modes, as the % clip gets undone by the restore. We need to handle the clip % separately. % % Tr 4 - Fill, add to clip { gsave 0 .settextrenderingmode setsmaskstate dup show grestore //true charpath } bind executeonly % Tr 5 - Stroke, add to clip { gsave 1 .settextrenderingmode calc_text_linewidth setlinewidth setsmaskstate dup show grestore //true charpath} bind executeonly % Tr 6 - Fill, stroke, add to clip { gsave 2 .settextrenderingmode calc_text_linewidth setlinewidth setsmaskstate dup show grestore //true charpath} bind executeonly % Tr 7 - Add to clip { //true charpath} bind executeonly ] readonly def % - calc_text_linewidth calculated_width % This calculates the required linewidth for stroke for *pdfwrite*, it must not be % used for rendering. Because pdfwrite writes text scaled into a 72 dpi resolution % we cannot use the current linewidth for it, it will be too large. Instead we must % re-calculate the original linewidth (removing the default CTM) and then apply the % TextSaveMatrix to find the appropriate new linewidth. % We check to see if the x and y scaling are approximately the same, if they are not % then we calculate a linewidth based on a right triangle with the x and y values % of the current linewidth in each direction and then calculate the hypotenuse, which % we then use as an approximation to the required width. % The 'approximation' of 0.01 is just a guess. /calc_text_linewidth { currentlinewidth dup currentdict /qTextSaveMatrix known { matrix defaultmatrix idtransform qTextSaveMatrix dtransform }{ matrix defaultmatrix idtransform TextSaveMatrix dtransform } ifelse abs 2 copy exch abs sub abs 0.01 le { pop }{ % We used to leave the linewidth alone for non-square resolutions, % claiming it reduced to the text matrix in pdfwrite. This is not % true. So handle it the same way we usually do, the hypotenuse of % the unit square transformed through the TextSaveMatrix. dup mul exch dup mul add sqrt 2 div }ifelse } bind executeonly def /setstrokeforTrpreservation { % Check to see if the current device supports Tr /PreserveTrMode /GetDeviceParam .special_op { exch pop }{ //false }ifelse { .currenttextrenderingmode 1 eq .currenttextrenderingmode 2 eq or .currenttextrenderingmode 5 eq .currenttextrenderingmode 6 eq or or { setsmaskstate % 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. NOTE! Only interested in magnitudes, % not signs. calc_text_linewidth setlinewidth } if } if } bind executeonly def % conditionally set fillstate to avoid multiple operations during text operators /settextfillstate { TextFillStateNeeded { setsmaskstate //false /TextFillStateNeeded gput } if } bind executeonly def % If current path is not known to be valid, use the clip path /TextTransSetup { % showarg path_valid TextTransSetup showarg % showarg path_valid false TextTransSetup showarg gsave % NB: if 'show' is used, then we use the clippath, but a smaller bbox is preferred { % path was (probably) valid (CTM may not be invertable) % Since TR mode may include stroking, expand for stroke % If we get an error, just emit an empty box { strokepath pathbbox } stopped { 0 0 0 0 } if } { clippath pathbbox stopped { 0 0 0 0 } if } ifelse grestore 4 array astore //null setup_trans } bind executeonly def /TextTransTeardown { teardown_trans } bind executeonly def /setshowstate { .currentwordspacing 0 eq .currenttextspacing 0 eq and FontMatrixNonHV not and { % Check to see if the current device supports Tr /PreserveTrMode /GetDeviceParam .special_op { exch pop }{ //false }ifelse { pdfwrite_textrenderingprocs .currenttextrenderingmode get } { .currenttextrenderingmode 0 eq currentfont /FontType get 3 eq .currenttextrenderingmode 3 eq not and or { { settextfillstate //false TextTransSetup show TextTransTeardown } } { .currenttextrenderingmode 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 % Previously we tested specifically for a scale factor of 0, % but bug #701875 has a CTM which is minute, but not zero. If % we try to use that at anything except low resolution FreeType % ends up trying to deal with glyph metrics where one dimension is 0 % and it throws an error. So instead of looking for zero, we'll look % for a really tiny CTM. % We also used to patch up the CTM, and still use it, but frankly % this is too much trouble. If the CTM is tiny then the displacement % due to drawing the text will also be tiny. Negligible in fact. % So if its that small then lets just ignore it. dup 0 get abs 0.00001 lt 1 index 1 get 0.00001 abs lt and not { dup 2 get abs 0.00001 lt 1 index 3 get abs 0.00001 lt and not { pop currentpoint % don't worry about transparency for invisible text 2 index settextfillstate show % Tr was set to graphic state. moveto % now set the currentpoint using the original matrix gsave //false charpath currentpoint newpath grestore moveto } { pop pop }ifelse } { pop pop }ifelse } } { { //false charpath textrenderingprocs .currenttextrenderingmode get exec } } ifelse } ifelse } ifelse } { % If we are doing a plain old fill, or no text at all, *or* we are going to % a device supporting text rendering modes, then go through this route. % .currenttextrenderingmode 0 eq .currenttextrenderingmode 3 eq or currentfont /FontType get 3 eq or /PreserveTrMode /GetDeviceParam .special_op { exch pop }{ //false }ifelse % pdfwrite can't handle rendering modes which involve clipping .currenttextrenderingmode 4 lt and or % Tr was set to graphic state. { FontMatrixNonHV { { % preserve current line width around possible stroke setup currentlinewidth exch setstrokeforTrpreservation settextfillstate //false TextTransSetup [ .currenttextspacing .currentwordspacing 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 setlinewidth TextTransTeardown } } { .currentwordspacing 0 eq { { { setstrokeforTrpreservation settextfillstate //false TextTransSetup .currenttextspacing 0 Vexch 3 -1 roll ashow TextTransTeardown } currentlinewidth { setlinewidth } 3 .execn } } { .currenttextspacing 0 eq { { % preserve current line width around possible stroke setup { setstrokeforTrpreservation settextfillstate //false TextTransSetup .currentwordspacing 0 Vexch 32 4 -1 roll .pdfwidthshow TextTransTeardown } currentlinewidth { setlinewidth } 3 .execn } } { { % preserve current line width around possible stroke setup { setstrokeforTrpreservation settextfillstate //false TextTransSetup .currentwordspacing 0 Vexch 32 .currenttextspacing 0 Vexch 6 -1 roll .pdfawidthshow TextTransTeardown } currentlinewidth { setlinewidth } 3 .execn } } ifelse } ifelse } ifelse } { { currentlinewidth exch .currentwordspacing .currenttextspacing % 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 % % for devices which can handle the text rendering mode we don't want % to decompose into paths, we want to do a 'show'. However pdfwrite % can't handle clipping text, so we *do* want to do the clip path % as a 'true charpath'. % /PreserveTrMode /GetDeviceParam .special_op { exch pop }{ //false }ifelse { % NB we must have Tr at least 4 or the test above would have % taken a different path, so we *know* the Tr involves clipping % or we wouldn't be here. Subtract 4 from the Tr and preserve % that mode, then do a charpath so the clip path gets set up % correctly. gsave .currenttextrenderingmode 4 sub .settextrenderingmode setstrokeforTrpreservation setsmaskstate settextfillstate //false TextTransSetup dup show grestore TextTransTeardown } if //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 % % If the device doesn't handle text rendering modes then we now have a suitable % path, so call the correct routine to stroke/fill it (clip is handled when we % get ET). % /PreserveTrMode /GetDeviceParam .special_op { exch pop not }{ //true }ifelse { textrenderingprocs .currenttextrenderingmode get exec } if setlinewidth } } ifelse } ifelse /Show gput } bind executeonly def /showfirst { setshowstate Show } executeonly def /Tj { { //true /TextFillStateNeeded gput 0 0 moveto Show settextposition } OFFlevels length 0 eq { exec } { gsave nulldevice exec grestore } ifelse //true /TextFillStateNeeded gput } bind executeonly def /' { T* Tj } bind executeonly def /" { exch Tc exch Tw T* Tj } bind executeonly def /TJ { { 0 0 moveto { dup type /stringtype eq { Show } { -1000 div currentfont /ScaleMatrix .knownget { 0 get mul } if 0 Vexch rmoveto } ifelse } forall settextposition //true /TextFillStateNeeded gput } OFFlevels length 0 eq { exec } { gsave nulldevice exec grestore } ifelse //true /TextFillStateNeeded gput } bind executeonly def % NB: We don't need clippath when filling or stroking /tf { .currentPDFfontsize 0 eq not { //true /TextFillStateNeeded gput settextfillstate //true TextTransSetup currentpoint fill TextTransTeardown moveto } if } bind executeonly def /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 { currentfont /FontType get 3 eq { settextfillstate //true TextTransSetup currentpoint fill TextTransTeardown moveto } { .currentPDFfontsize 0 eq not { setsmaskstate //true TextTransSetup currentpoint //Tmatrix currentmatrix TextSaveMatrix setmatrix currentdict /qTextSaveMatrix known {qTextSaveMatrix setmatrix} if .swapcolors stroke TextTransTeardown .swapcolors setmatrix moveto } if } ifelse //true /TextFillStateNeeded gput } bind executeonly def % Handle transparency the same as /B operator /tB { % Type 3 fonts don't honour text rendering modes, see note on p401 of the 1.7 PDF Reference currentfont /FontType get 3 eq { settextfillstate //true TextTransSetup currentpoint fill TextTransTeardown moveto } { % Don't try to draw text when the point size is 0 .currentPDFfontsize 0 eq not { setsmaskstate settextfillstate % While text will always have a currentpoint, strokepath seems to mess with it. % we get the currentpoint, then use moveto to restore it. currentpoint % For stroking characters, temporarily restore the graphics CTM so that % the line width will be transformed properly. //Tmatrix currentmatrix TextSaveMatrix setmatrix currentdict /qTextSaveMatrix known {qTextSaveMatrix setmatrix} if B setmatrix moveto } if } ifelse //true /TextFillStateNeeded gput } bind executeonly def % This does the wrong thing if there have been multiple text operations % within a single BT/ET pair, but it's a start. /tW { } bind executeonly def %% split a string containing \r or \n into multiple strings) %% \r\n is also handled. %% (string) .splitstring (string1) (string2) ..... /.splitstring { 0 exch %% start_index string dup length 1 sub %% start_index string (string length - 1) 0 1 3 -1 roll %% start_index string 0 1 (string_length -1) { %% start_index string loop_index dup %% start_index string loop_index loop_index 2 index exch get %% start_index string loop_index character dup 10 eq exch 13 eq or { %% start_index string loop_index dup 3 index %% start_index string loop_index loop_index start_index sub %% start_index string loop_index (loop_index - start_index) dup 0 gt { %% \r\n will give us a 0 length string so ignore it 3 index exch %% start_index string loop_index start_index (loop_index - start_index) 3 index 3 1 roll %% start_index string loop_index string start_index (loop_index - start_index) getinterval %% start_index string loop_index sub_string 4 1 roll %% sub_string start_index string loop_index 1 add 3 -1 roll %% sub_string string loop_index start_index pop exch %% sub_string loop_index string %% loop_index becomes new start_index }{ pop %% start_index string loop_index 1 add 3 1 roll exch %% loop_index string start_index pop %% loop_index string %% loop_index becomes new start index } ifelse }{ pop %% start_index string } ifelse } for %% start_index string dup length 2 index sub dup %% start_index string (length - start_index) (length - start_index) 0 gt { %% we have characters left %% start_index string (length - start_index) 3 -1 roll exch %% string start_index (length - start_index) getinterval %% sub_string } { pop pop pop } ifelse } bind executeonly def % Text formatting and painting for the AcroForm field without appearance streams. /Tform { % <MaxLen> (V) <Ff> <Q> 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 .knownget not { currentfont dup /FontType get 0 eq { /FDepVector get 0 get /FontBBox get} { pop //null % force an error } ifelse }if 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 %% Check if this is declared as a multiine text widget, and if it is %% check that the string has at least 2 characters, so we can split it %% into at least two strings.... %% Bug #687498.pdf has a multiline text widget with an empty string (amongst %% many other problems with this file). 5 index 16#1000 and 0 ne 7 index length 1 gt and{ % multiline %% First lets see how many lines we have, make a copy of the string 6 index mark exch .splitstring % MaxLen (V) Ff Q dx dy yy desc/asc*yy [ () () ... counttomark 1 add 4 add index % MaxLen (V) Ff Q dx dy yy desc/asc*yy [ () () ... count Q dup 0 eq { pop % remove extra copy of Q counttomark dup 2 add 2 add index exch div % MaxLen (V) Ff Q dx dy yy desc/asc*yy [ () () ... line_height counttomark 1 add 1 roll % MaxLen (V) Ff Q dx dy yy desc/asc*yy line_height [ () () ... 2 0 moveto % start at bottom left of rect counttomark 1 1 3 -1 roll { % for every string pop gsave <EFBBBF> anchorsearch { pop } { <FEFF> anchorsearch { pop } if } ifelse Show grestore % pop loop counter, show string (saving current point) counttomark 1 add index 0 exch rmoveto % get line height, move that amount vertically. } for pop pop }{ 1 eq { counttomark dup 2 add 2 add index exch div % MaxLen (V) Ff Q dx dy yy desc/asc*yy [ () () ... line_height counttomark 1 add 1 roll % MaxLen (V) Ff Q dx dy yy desc/asc*yy line_height [ () () ... 2 0 moveto % start at bottom left of rect counttomark 1 1 3 -1 roll { % for every string pop gsave % pop loop counter <EFBBBF> anchorsearch { pop } { <FEFF> anchorsearch { pop } if } ifelse dup stringwidth pop counttomark 5 add index % get rectangle width exch sub 2 div 0 rmoveto % subtract width of string, divide by 2 move that amount Show grestore % show string counttomark 1 add index 0 exch rmoveto % get line height, move that amount vertically. } for pop pop }{ counttomark dup 2 add 2 add index exch div % MaxLen (V) Ff Q dx dy yy desc/asc*yy [ () () ... line_height counttomark 1 add 1 roll % MaxLen (V) Ff Q dx dy yy desc/asc*yy line_height [ () () ... 2 0 moveto % start at bottom left of rect counttomark 1 1 3 -1 roll { % for every string pop gsave % pop loop counter <EFBBBF> anchorsearch { pop } { <FEFF> anchorsearch { pop } if } ifelse dup stringwidth pop counttomark 5 add index % get rectangle width exch sub 2 sub 0 rmoveto % subtract width of string,move that amount Show grestore % show string counttomark 1 add index 0 exch rmoveto % get line height, move that amount vertically. } for pop pop }ifelse }ifelse 8 { pop } repeat } { 5 index 16#1000000 and 0 ne { % comb 6 index type /stringtype eq { 6 index length 0 gt { 6 index length 8 index % length of V and MaxLength gt { (Comb field with /V string which exceeds /MaxLength. Ignoring field.) = 8 {pop} repeat }{ 3 index 8 index div % field Rect width / MaxLength, the offset between 'comb' boxes 7 index <EFBBBF> anchorsearch { pop } { <FEFF> anchorsearch { pop } if } ifelse { currentpoint newpath moveto % new path, preserving currnt point currentpoint % store the current point, this is the origin for the next 'comb' 3 -1 roll 1 string dup 3 -1 roll exch 0 3 -1 roll put % turn the character code into a 1 byte string dup gsave false charpath flattenpath pathbbox grestore % get the bounding box of that character 3 -1 roll sub 3 1 roll exch sub % get its width and height (ch, cw) 8 index 6 index % comb box width and height (bh, bw) 3 -1 roll % ch cw bh bw -> ch bh bw cw sub 2 div % ch bh (bw - cw) / 2 = ch bh dw 3 1 roll % ch bh dw -> dw ch bh exch sub 2 div % dw (bh - ch) /2 = dw dh rmoveto % centers character in box Show exch 2 index add exch moveto % Draw the character } forall % repeat for every character in the original string 9 {pop} repeat % discard the various arguments }ifelse }{ 8 {pop} repeat % discard the parameters }ifelse }{ (Comb field with a non-string /V value is illegal. Ignoring field.) = 8 {pop} repeat } ifelse } { % 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 <EFBBBF> anchorsearch { pop } { <FEFF> anchorsearch { pop } if } ifelse 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 <EFBBBF> anchorsearch { pop } { <FEFF> anchorsearch { pop } if } ifelse Show % - } ifelse } ifelse } bind executeonly def end readonly put % GS_PDF_ProcSet .setglobal gs_sym_e.ps 0000644 00000006040 15030647507 0006724 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % Define the Symbol encoding vector. /currentglobal where { pop currentglobal { setglobal } //true setglobal } { { } } ifelse /SymbolEncoding % \000 StandardEncoding 0 32 getinterval aload pop % /.notdef % \040 /space /exclam /universal /numbersign /existential /percent /ampersand /suchthat /parenleft /parenright /asteriskmath /plus /comma /minus /period /slash /zero /one /two /three /four /five /six /seven /eight /nine /colon /semicolon /less /equal /greater /question % \100 /congruent /Alpha /Beta /Chi /Delta /Epsilon /Phi /Gamma /Eta /Iota /theta1 /Kappa /Lambda /Mu /Nu /Omicron /Pi /Theta /Rho /Sigma /Tau /Upsilon /sigma1 /Omega /Xi /Psi /Zeta /bracketleft /therefore /bracketright /perpendicular /underscore % \140 /radicalex /alpha /beta /chi /delta /epsilon /phi /gamma /eta /iota /phi1 /kappa /lambda /mu /nu /omicron /pi /theta /rho /sigma /tau /upsilon /omega1 /omega /xi /psi /zeta /braceleft /bar /braceright /similar /.notdef % \200 StandardEncoding 0 32 getinterval aload pop % /.notdef % \240 /Euro /Upsilon1 /minute /lessequal /fraction /infinity /florin /club /diamond /heart /spade /arrowboth /arrowleft /arrowup /arrowright /arrowdown /degree /plusminus /second /greaterequal /multiply /proportional /partialdiff /bullet /divide /notequal /equivalence /approxequal /ellipsis /arrowvertex /arrowhorizex /carriagereturn % \300 /aleph /Ifraktur /Rfraktur /weierstrass /circlemultiply /circleplus /emptyset /intersection /union /propersuperset /reflexsuperset /notsubset /propersubset /reflexsubset /element /notelement /angle /gradient /registerserif /copyrightserif /trademarkserif /product /radical /dotmath /logicalnot /logicaland /logicalor /arrowdblboth /arrowdblleft /arrowdblup /arrowdblright /arrowdbldown % \340 /lozenge /angleleft /registersans /copyrightsans /trademarksans /summation /parenlefttp /parenleftex /parenleftbt /bracketlefttp /bracketleftex /bracketleftbt /bracelefttp /braceleftmid /braceleftbt /braceex /.notdef /angleright /integral /integraltp /integralex /integralbt /parenrighttp /parenrightex /parenrightbt /bracketrighttp /bracketrightex /bracketrightbt /bracerighttp /bracerightmid /bracerightbt /.notdef 256 packedarray .defineencoding 2 SymbolEncoding .registerencoding exec gs_pdfwr.ps 0000644 00000076776 15030647507 0006761 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % PDF writer additions to systemdict. % This file should be included iff the pdfwrite "device" is included % in the executable. % ---------------- Predefined configurations ---------------- % % These correspond to the 4 predefined settings in Acrobat Distiller 5, % plus a "default" setting that doesn't downsample images. { /pdfwrite finddevice pop } .internalstopped {pop pop (%END PDFWR) .skipeof} if languagelevel 2 .setlanguagelevel /.a2112 [2 1 1 2] readonly def /.a1111 [1 1 1 1] readonly def /.standardfonts [ /Courier /Courier-Bold /Courier-Oblique /Courier-BoldOblique /Helvetica /Helvetica-Bold /Helvetica-Oblique /Helvetica-BoldOblique /Times-Roman /Times-Bold /Times-Italic /Times-BoldItalic /Symbol /ZapfDingbats ] readonly def % Parameters common to all non-default configurations. % Note that the default configuration overrides a few of these. /.defaultImageDict mark /QFactor 0.9 /Blend 1 /HSamples .a2112 /VSamples .a2112 .dicttomark readonly def /.distillercommon mark /AlwaysEmbed [] /AntiAliasColorImages //false /AntiAliasGrayImages //false /AntiAliasMonoImages //false /ASCII85EncodePages //false /AutoFilterColorImages //true /AutoFilterGrayImages //true /AutoPositionEPSFiles //true /Binding /Left /CalCMYKProfile (None) % (U.S. Web Coated (SWOP) v2) /CalGrayProfile (None) % (Dot Gain 20%) /CalRGBProfile (None) % (sRGB IEC61966-2.1) /ColorImageDepth -1 /ColorImageDict .defaultImageDict /ColorImageDownsampleThreshold 1.5 /ColorImageFilter /DCTEncode /CompressPages //true /ConvertImagesToIndexed //true /DefaultRenderingIntent /Default /DetectBlends //true /DownsampleColorImages //true /DownsampleGrayImages //true /DownsampleMonoImages //true /EmitDSCWarnings //false /EncodeColorImages //true /EncodeGrayImages //true /EncodeMonoImages //true /EndPage -1 /GrayImageDepth -1 /GrayImageDict .defaultImageDict /GrayImageDownsampleThreshold 1.5 /GrayImageFilter /DCTEncode /ImageMemory 524288 /LockDistillerParams //false /MaxSubsetPct 100 /MonoImageDepth -1 /MonoImageDict mark /K -1 .dicttomark readonly /MonoImageDownsampleThreshold 1.5 /MonoImageFilter /CCITTFaxEncode /OffOptimizations 0 /OPM 0 /Optimize //true /ParseDSCComments //true /ParseDSCCommentsForDocInfo //true /PDFXTrimBoxToMediaBoxOffset [0 0 0 0] /PDFXSetBleedBoxToMediaBox //true /PDFXBleedBoxToTrimBoxOffset [0 0 0 0] /PreserveCopyPage //true /PreserveHalftoneInfo //false /sRGBProfile (None) % (sRGB IEC61966-2.1) /StartPage 1 /SubsetFonts //true /TransferFunctionInfo /Preserve /UseFlateCompression //true /UsePrologue //false /PassThroughJPEGImages //true /PassThroughJPXImages //true .dicttomark readonly def /.distillersettings mark /default mark /AutoRotatePages /PageByPage /CannotEmbedFontPolicy /Warning /ColorACSImageDict .defaultImageDict /ColorConversionStrategy /LeaveColorUnchanged % /ColorImageDownsampleType % /ColorImageResolution % /CompatibilityLevel /CreateJobTicket //false /DoThumbnails //false /DownsampleColorImages //false % override /DownsampleGrayImages //false % override /DownsampleMonoImages //false % override /EmbedAllFonts //true /GrayACSImageDict .defaultImageDict % /GrayImageDownsampleType % /GrayImageResolution % /MonoImageDownsampleType % /MonoImageResolution /NeverEmbed .standardfonts /Optimize //false % override /PreserveEPSInfo //true /PreserveOPIComments //true /PreserveOverprintSettings //true /UCRandBGInfo /Preserve .dicttomark readonly /.screenACSImageDict mark /QFactor 0.76 /Blend 1 /ColorTransform 1 /HSamples .a2112 /VSamples .a2112 .dicttomark readonly def /screen mark /AutoRotatePages /PageByPage % /CalGrayProfile (None) /CannotEmbedFontPolicy /Warning /ColorACSImageDict .screenACSImageDict /ColorConversionStrategy /sRGB /ColorImageDownsampleType /Average /ColorImageResolution 72 /CompatibilityLevel 1.5 /CreateJobTicket //false /DoThumbnails //false /EmbedAllFonts //true /GrayACSImageDict .screenACSImageDict /GrayImageDownsampleType /Average /GrayImageResolution 72 /MonoImageDownsampleType /Subsample /MonoImageResolution 300 /NeverEmbed .standardfonts /PreserveEPSInfo //false /PreserveOPIComments //false /PreserveOverprintSettings //false /UCRandBGInfo /Remove .dicttomark readonly /ebook mark /AutoRotatePages /All % /CalGrayProfile (None) /CannotEmbedFontPolicy /Warning /ColorACSImageDict .screenACSImageDict /ColorConversionStrategy /sRGB /ColorImageDownsampleType /Average /ColorImageResolution 150 /CompatibilityLevel 1.5 /CreateJobTicket //false /DoThumbnails //false /EmbedAllFonts //true /GrayACSImageDict .screenACSImageDict /GrayImageDownsampleType /Average /GrayImageResolution 150 /MonoImageDownsampleType /Subsample /MonoImageResolution 300 /NeverEmbed .standardfonts /PreserveEPSInfo //false /PreserveOPIComments //false /PreserveOverprintSettings //false /UCRandBGInfo /Remove .dicttomark readonly /.printerACSImageDict mark /QFactor 0.4 /Blend 1 /ColorTransform 1 /HSamples .a1111 /VSamples .a1111 .dicttomark readonly def /printer mark /AutoRotatePages /None % /CalGrayProfile (None) /CannotEmbedFontPolicy /Warning /ColorACSImageDict .printerACSImageDict /ColorConversionStrategy /UseDeviceIndependentColor /ColorImageDownsampleType /Average /ColorImageResolution 300 /CompatibilityLevel 1.7 /CreateJobTicket //true /DoThumbnails //false /EmbedAllFonts //true /GrayACSImageDict .printerACSImageDict /GrayImageDownsampleType /Average /GrayImageResolution 300 /MonoImageDownsampleType /Subsample /MonoImageResolution 1200 /NeverEmbed [] /PreserveEPSInfo //true /PreserveOPIComments //true /PreserveOverprintSettings //true /UCRandBGInfo /Preserve .dicttomark readonly /.prepressACSImageDict mark /QFactor 0.15 /Blend 1 /ColorTransform 1 /HSamples .a1111 /VSamples .a1111 .dicttomark readonly def /prepress mark /AutoRotatePages /None /CannotEmbedFontPolicy /Error /ColorACSImageDict .prepressACSImageDict /ColorConversionStrategy /LeaveColorUnchanged /ColorImageDownsampleType /Bicubic /ColorImageResolution 300 /CompatibilityLevel 1.7 /CreateJobTicket //true /DoThumbnails //true /EmbedAllFonts //true /GrayACSImageDict .prepressACSImageDict /GrayImageDownsampleType /Bicubic /GrayImageResolution 300 /MonoImageDownsampleType /Subsample /MonoImageResolution 1200 /NeverEmbed [] /PreserveEPSInfo //true /PreserveOPIComments //true /PreserveOverprintSettings //true /UCRandBGInfo /Preserve .dicttomark readonly % Define distiller settings for the ps2write device and for the ps2ps2 script : /PSL2Printer mark /AutoRotatePages /None /CannotEmbedFontPolicy /Error /ColorACSImageDict .prepressACSImageDict /ColorConversionStrategy /LeaveColorUnchanged /ColorImageDownsampleType /Subsample /ColorImageResolution 600 /DownsampleColorImages //false /CompatibilityLevel 1.2 % Always 1.2 with ps2write. % /CreateJobTicket //true % Not sure /DoThumbnails //false /EmbedAllFonts //true /GrayACSImageDict .prepressACSImageDict /GrayImageDownsampleType /Subsample /GrayImageResolution 600 /DownsampleGrayImages //false /MonoImageDownsampleType /Subsample /MonoImageResolution 1200 /DownsampleMonoImages //false /NeverEmbed [] /PreserveEPSInfo //true /PreserveOPIComments //true /PreserveOverprintSettings //true /UCRandBGInfo /Preserve /PreserveHalftoneInfo //true /TransferFunctionInfo /Preserve %% Deprecated in 9.06 %% /MaxViewerMemorySize 8000000 /CompressPages //false /CompressFonts //true /ASCII85EncodePages //true .dicttomark readonly .dicttomark readonly def % ---------------- End of predefined configurations ---------------- % % ---------------- pdfmark and DSC processing ---------------- % /.write_small_positive_real % <file> <real> .write_small_positive_real - { % The argument must be grater than 0 and must be strongly samller than 0.1. % The conversion isn't simple due to the low (24 bits) precision % of the floating point arithmetics in Postscript. % For best result we first use the 1e8 factor since its binary % representation 101111101011110000100000000 well rounds into 14 significant % bits : 101111101011110000000000000 . 1 index (.) writestring { dup 100000000 mul dup 10 mul 1 ge { % Will need not greater than 0.1 due to a rounding below. pop exit } if exch pop 1 index (00000000) writestring } loop % Now it is not smaller than 1e-9, use simple digitizing. { dup 10 mul dup 10 mul 1 ge { pop exit } if exch pop 1 index (0) writestring } loop % Now 0.01 <= n < 0.1, but rounding may give 0.1 . % Convert to integer with 7 digits precision : 100000000 % precision factor 1e8 % f n r dup 10 idiv 3 1 roll mul 0.5 add cvi % f r' N 2 copy le { % The rounding overflows, suppress it. % Note it carries out an additional digit, % that's why we needed <0.1 above. pop pop (1) writestring } { % Didn't cary out, put 0. 2 index (0) writestring exch % f N r % Continue the simple digitizing : { 10 idiv dup % f N r' r' 2 index exch idiv % f N r' d (0123456789) exch 1 getinterval % f N r' (d) 3 index exch writestring % f N r' dup 3 2 roll exch mod % f r' N' dup 0 eq { % Don't write trailing zeros. exit } if exch % f N' r' } loop pop pop pop } ifelse } bind def % Encode values to pass for the /pdfmark or /DSC pseudo-parameter. /.pdf===dict mark /arraytype { dup xcheck { ({) (}) } { ([) (]) } ifelse % Stack: file obj left right 4 1 roll 2 index exch writestring () exch { exch 2 index exch writestring 1 index exch pdf===only ( ) } forall pop exch writestring } bind /packedarraytype 1 index /dicttype { 1 index (<<\n) writestring { 2 index 3 -1 roll pdf===only 1 index ( ) writestring 1 index exch pdf===only dup (\n) writestring } forall (>>) writestring } bind /nametype { % If the name string includes any non-regular characters, % write it with two preceding and one following null character(s). % (Null characters in the name itself are not allowed.) % This non-standard escape convention is required for passing names % that include non-regular characters, because PostScript provides % no way to do this. The pdf_scan_token procedure in the C code of % the pdfwrite driver is currently the only place that recognizes % this convention. % Note that \004 may be self-delimiting in gs, but is not in standard PS. dup .namestring (\000\004\011\012\014\015 %()/<>[]{}) .stringbreak //null ne { dup .namestring (\000) .stringbreak //null ne { 1 index <000000> writestring 1 index exch write===only 1 index exch 0 write 0 write }{ 1 index <0000> writestring 1 index exch write===only 0 write }ifelse } { write===only } ifelse } bind /realtype { % Prevent using floating point format - see Bug 688167. dup dup 0 lt { neg } if 0.01 lt { dup 0 eq { pop (0) writestring } { dup 0 lt { 1 index (-) writestring neg } if .write_small_positive_real } ifelse } { write===only } ifelse } bind .dicttomark readonly def /pdf===only { % <file> <obj> pdf===only - .pdf===dict 1 index type .knownget { exec } { write===only } ifelse } bind def /.pdfcvbuf 30 string def % enough for most arguments userdict /.pdfcvstring () put /.pdfcvs { % <obj> .pdfcvs <string> currentglobal exch //false .setglobal /.pdfcvstring () store % We can't handle long values yet. { pop dup length 0 eq { pop } { /.pdfcvstring .pdfcvstring 3 -1 roll concatstrings store } ifelse //.pdfcvbuf } /NullEncode filter dup 3 -1 roll pdf===only closefile .setglobal .pdfcvstring } bind def % Redefine pdfmark to pass the data to the driver. % We use a pseudo-parameter named /pdfmark whose value is an array: % /key1 (value1) ... (CTM) /type /.pdfputparams { % -mark- <key1> <value1> ... .pdfputparams <result...> currentdevice //null //false counttomark 1 add 3 roll % Don't allow the page device to get cleared.... {.putdeviceparams} .currentpagedevice pop {.setpagedevice} 3 .execn } bind def % Convert relevant operands to strings in an array. /.pdfcvsloop { % -mark- values ... markname start step .pdfcvsloop % [values ... ctm markname] matrix currentmatrix .pdfcvs 4 1 roll counttomark 1 add 2 roll counttomark .localvmarray astore exch pop 3 1 roll % Stack: values start step 2 index length 3 sub { 2 copy 2 copy get .pdfcvs put pop } for } bind def /.pdfcvsall { % -mark- values ... markname .pdfcvsall <<same>> 0 1 .pdfcvsloop } bind def /.pdfcvseven { % -mark- key value ... markname .pdfcvseven <<same>> 1 2 .pdfcvsloop } bind def /.pdfcvsnone { % -mark- values ... markname .pdfcvsnone <<same>> 100000 1 .pdfcvsloop } bind def /.pdfcvsfirst { % -mark- first values ... markname .pdfcvsfirst<<same>> .pdfcvsnone dup 0 2 copy get .pdfcvs put } bind def % The procedures in the following dictionary are called with the entire % pdfmark operand list (including the pdfmark name) on the stack; % they may modify this ad lib. They must call .pdfcvsxxx. /.pdfmarkparams mark % Unpack a dictionary for PUT, and don't convert stream data. /PUT { counttomark 3 eq { 1 index type /dicttype eq { pop { } forall /.PUTDICT .pdfcvsall } { pop dup type /filetype eq { % Read the file into a sequence of strings. % This isn't great, but it's simple. { dup 64000 string readstring not { exch exit } if exch } loop closefile } if /.PUTSTREAM .pdfcvsfirst } ifelse } { .pdfcvsall } ifelse } bind % Unpack the array for PUTINTERVAL. /PUTINTERVAL { pop aload pop /.PUTINTERVAL .pdfcvsall } bind .dicttomark readonly def /.pdfparamerror { % ? ? ? -mark- ... <errname> <opname> .pdfparamerror - counttomark 4 add 2 roll cleartomark pop pop pop .systemvar exch signalerror } bind def /.CountLeafs { 0 exch { oforce dup type /dicttype eq { /Limits knownoget { dup type /arraytype eq { 1 get 2 copy lt { exch pop }{ pop }ifelse }{ (invalid number tree, /Limits not an array\n) print pop pop 0 exit } ifelse }{ (invalid number tree, /Limits not defined in intermediate or leaf node\n) print pop pop 0 exit }ifelse } { (invalid number tree, /Kids entry not a dictionary\n) print pop pop 0 exit } ifelse } forall } bind def /.ExtractLeafs { { oforce dup /Nums knownoget { exch pop dup length 1 sub 0 2 3 -1 roll { %% dict array index dup %% dict array index index 2 index exch get %% dict array index 20 string cvs cvn %% dict array index name exch 1 add %% dict array name index+1 2 index exch oget %% dict array name object 3 index %% dict array name object dict 3 1 roll %% dict array dict name object put %% dict array } for pop %% array }{ /Kids knownoget { .ExtractLeafs } if } ifelse } forall } bind def /.pdfpagelabels { dup type /dicttype eq { dup /Nums knownoget { exch pop mark exch 0 1 2 index length 1 sub { 1 index exch oget exch } for pop counttomark array astore 1 dict dup begin exch /Nums exch def end .pdfcvs mark /pdfpagelabels 3 -1 roll .pdfputparams dup type /booleantype ne { /pdfpagelabels .pdfparamerror } if cleartomark }{ /Kids knownoget { dup .CountLeafs dup 1000 ge { (PageLabel tree too complex, ignoring PageLabels\n) print flush pop pop }{ dict exch .ExtractLeafs mark exch dup length 0 1 3 -1 roll { dup 20 string cvs cvn %% mark dict index name 2 index exch .knownget{ %% mark ... dict index object 3 -1 roll %% mark ... index object dict }{ pop }ifelse } for pop counttomark array astore 1 dict dup begin exch /Nums exch def end .pdfcvs mark /pdfpagelabels 3 -1 roll .pdfputparams dup type /booleantype ne { /pdfpagelabels .pdfparamerror } if cleartomark }ifelse }{ (Invalid number tree in PageLabels, ignoring PageLabels\n) print flush }ifelse }ifelse }{ /pdfpagelabels .pdfparamerror } ifelse } bind def /pdfmark { % -mark- <key> <value> ... <markname> pdfmark - counttomark 0 eq { /pdfmark cvx /stackunderflow signalerror } if dup type /nametype eq not { /pdfmark cvx /typecheck signalerror } if dup /SP eq { % A hack for synchronizing the clipping path. gsave [1 0 0 1 0 0] setmatrix 0 setlinewidth newpath -3 -3 moveto closepath stroke % Paints outside the device bbox. grestore } if dup /PS eq systemdict /PDFX .knownget not { //false } if systemdict /PDFA .knownget not { //false }{0 eq {//false}{//true} ifelse} ifelse or and { % Execute it since PDF/X doesn't allow to embed it. pop { dup mark eq { pop exit } if 1 index /DataSource eq { exch pop cvx exec } { pop pop } ifelse } loop } { counttomark 1 add copy //.pdfmarkparams 1 index .knownget { exec } { .pdfcvsall } ifelse mark /pdfmark 3 -1 roll .pdfputparams dup type /booleantype ne { /pdfmark .pdfparamerror } if cleartomark } ifelse } odef userdict /pdfmark .undef currentdict /.pdfmarkparams .undef % <dict> .hook_DSC_Creator - /.pdf_hook_DSC_Creator { % If the Creator is PScript5.dll, disable the 32 /FontType resource for % handling GlyphNames2Unicode. Since /FontType category can't redefine, % we can do only with redefining the operator 'resourcestatus'. systemdict /.pdf_hooked_DSC_Creator .knownget { {//false}{//true} ifelse } { //true } ifelse { /WantsToUnicode /GetDeviceParam .special_op { exch pop }{ //true }ifelse { /Creator .knownget { (PScript5.dll) search { pop pop systemdict /resourcestatus dup { dup /FontType eq 2 index 32 eq and { pop pop //false } { resourcestatus } ifelse } bind .makeoperator .forceput systemdict /.pdf_hooked_DSC_Creator //true .forceput } executeonly if pop } executeonly if } { pop } ifelse } executeonly { pop } ifelse } .bind executeonly odef % must be bound and hidden for .forceput % Use the DSC processing hook to pass DSC comments to the driver. % We use a pseudo-parameter named DSC whose value is an array: % /key1 (value1) ... /type /.pdfdsc_dict 2 dict def /.pdfdsc { % <file> <DSC string> <dsc dict> [<prev proc>] .pdfdsc - 0 get dup //null ne { 4 copy exch pop exec pop } { pop } ifelse 3 -1 roll pop % Stack: <dsc string> <dsc dict> 20 .localvmdict 1 index { 3 copy put pop pop } forall 3 -1 roll .parse_dsc_comments % <dsc dict> <dict> <type> 1 index //.pdf_hook_DSC_Creator exec dup /NOP ne 2 index length 1 gt or { % Skip unparsed comments PDFWRDEBUG { (**** DSC comment: ) print dup //== exec 1 index === flush } if exch mark 4 1 roll { % mark <key1> <value1> ... <dsc dict> <type> <key> <value> 3 index 2 index known { % Skip the DSC_struct entry pop pop } { .pdfcvs 4 -2 roll } ifelse } forall exch pop counttomark .localvmarray astore mark /DSC 3 -1 roll .pdfputparams dup type /booleantype ne { /DSC .pdfparamerror } { cleartomark } ifelse } { pop pop pop } ifelse } bind def currentdict /.pdf_hook_DSC_Creator undef /.initialize_dsc_parser where { pop 3000 % priority { currentglobal //true setglobal 2 dict dup .initialize_dsc_parser readonly currentuserparams /ProcessDSCComment get 1 array astore % in case the value is executable //.pdfdsc /exec load 4 array astore cvx readonly << /ProcessDSCComment 3 -1 roll >> setuserparams setglobal } bind .schedule_init } if % ---------------- {set,current}distillerparams ---------------- % % Define setdistillerparams / currentdistillerparams. % Distiller parameters are currently treated as device parameters. /.distillerparamkeys mark % General parameters -- all distillers /ASCII85EncodePages { } /AutoRotatePages { } /Binding { } /CompressPages { } /DefaultRenderingIntent { } /DetectBlends { } /DoThumbnails { } /ImageMemory { } /LockDistillerParams { } /LZWEncodePages { } /OPM { } /PreserveHalftoneInfo { } /PreserveOPIComments { } /PreserveOverprintSettings { } /TransferFunctionInfo { } /UCRandBGInfo { } /UseFlateCompression { } % General parameters -- PDF writer % StartPage and EndPage are renamed because EndPage % clashes with a page device parameter. /CoreDistVersion { } /CompatibilityLevel { } % ****** NOTE: StartPage and EndPage are disabled because % ****** EndPage clashes with a page device parameter. % /EndPage { exch pop /PDFEndPage exch } /PDFEndPage { pop pop } % /StartPage { exch pop /PDFStartPage exch } /PDFStartPage { pop pop } /Optimize { } /ParseDSCCommentsForDocInfo { } /ParseDSCComments { } /EmitDSCWarnings { } /CreateJobTicket { } /PreserveEPSInfo { } /AutoPositionEPSFiles { } /PreserveCopyPage { } /UsePrologue { } /OffOptimizations { } % PDF/X parameters /PDFXTrimBoxToMediaBoxOffset { } /PDFXSetBleedBoxToMediaBox { } /PDFXBleedBoxToTrimBoxOffset { } % Color sampled image parameters /ColorACSImageDict { } /AntiAliasColorImages { } /AutoFilterColorImages { } /ColorImageDepth { } /ColorImageDict { } /DownsampleColorImages { } /ColorImageDownsampleThreshold { } /ColorImageDownsampleType { } /ColorImageAutoFilterStrategy { } /EncodeColorImages { } /ColorImageFilter { } /ColorImageResolution { } % Color processing parameters /CalCMYKProfile { } /CalGrayProfile { } /CalRGBProfile { } /sRGBProfile { } /ColorConversionStrategy { } /ConvertCMYKImagesToRGB { } /ConvertImagesToIndexed { } % Grayscale sampled image parameters /GrayACSImageDict { } /AntiAliasGrayImages { } /AutoFilterGrayImages { } /GrayImageDepth { } /GrayImageDict { } /DownsampleGrayImages { } /GrayImageDownsampleThreshold { } /GrayImageDownsampleType { } /GrayImageAutoFilterStrategy { } /EncodeGrayImages { } /GrayImageFilter { } /GrayImageResolution { } % Monochrome sampled image parameters /AntiAliasMonoImages { } /MonoImageDepth { } /MonoImageDict { } /DownsampleMonoImages { } /MonoImageDownsampleThreshold { } /MonoImageDownsampleType { } /EncodeMonoImages { } /MonoImageFilter { } /MonoImageResolution { } % Font embedding parameters /AlwaysEmbed { dup length 0 gt { dup 0 get type /booleantype eq } { //false } ifelse { dup 0 get { dup length 1 sub 1 exch getinterval } { dup length 1 sub 1 exch getinterval exch pop /~AlwaysEmbed exch } ifelse } { exch pop /.AlwaysEmbed exch } ifelse } /NeverEmbed { dup length 0 gt { dup 0 get type /booleantype eq } { //false } ifelse { dup 0 get { dup length 1 sub 1 exch getinterval } { dup length 1 sub 1 exch getinterval exch pop /~NeverEmbed exch } ifelse } { exch pop /.NeverEmbed exch } ifelse } /CannotEmbedFontPolicy { } /EmbedAllFonts { } /MaxSubsetPct { } /SubsetFonts { } /DSCEncodingToUnicode { } /PassThroughJPEGImages { } /PassThroughJPXImages { } /PSDocOptions { } /PSPageOptions { } .dicttomark readonly def /.distillerdevice { % Check to see if the current device is a Distiller % and return it if so. /IsDistiller /GetDeviceParam .special_op { exch pop }{ //false }ifelse { currentdevice } { /pdfwrite finddevice } ifelse } bind def % Some badly designed PostScript files only expect the current/set % distillerparams operators to exist in a distiller. Since we have % this as a runtime option, we enable these operators IFF the % currentdevice is pdfwrite. Also, we mask their existence in % systemdict so that 'where' and 'known' don't show them unless % the currentdevice is pdfwrite. /.setdistillerparams { % <dict> setdistillerparams - .distillerdevice //null //false mark 4 index { //.distillerparamkeys 2 index .knownget { exec } { pop pop } ifelse } forall .putdeviceparamsonly dup type /booleantype ne { /setdistillerparams .pdfparamerror } { pop pop pop } ifelse } odef /.currentdistillerparams { % - currentdistillerparams <dict> .distillerdevice //.distillerparamkeys .getdeviceparams .dicttomark % Patch StartPage and EndPage % ****** NOTE: StartPage and EndPage are disabled because % ****** EndPage clashes with a page device parameter. % begin /StartPage PDFStartPage /EndPage PDFEndPage % currentdict dup /PDFStartPage undef /PDFEndPage undef % def def currentdict end } odef /setdistillerparams { % Check to see if the current device is a Distiller /IsDistiller /GetDeviceParam .special_op { exch pop not }{ //true }ifelse { /setdistillerparams cvx /undefined signalerror } if .setdistillerparams } bind odef /currentdistillerparams { % Check to see if the current device is a Distiller /IsDistiller /GetDeviceParam .special_op { exch pop not }{ //true }ifelse { /currentdistillerparams cvx /undefined signalerror } if .currentdistillerparams } bind odef % Patch 'where' so that the distiller operators are only visible % if the pdfwrite device is the current one. { % Check to see if the current device is a Distiller /IsDistiller /GetDeviceParam .special_op { exch pop }{ //false }ifelse { .where } { .where pop dup //systemdict eq { pop //false } { //true } ifelse } ifelse } bind { /currentdistillerparams /setdistillerparams /pdfmark } { .wheredict exch 2 index put } forall pop % Patch 'known' to hide the systemdict version of distiller operators % unless the currentdevice is pdfwrite. /known { /currentdistillerparams 1 index eq /setdistillerparams 2 index eq or /pdfmark 2 index eq or { systemdict 2 index eq { % only mask the operator in systemdict known % Check to see if the current device is a Distiller /IsDistiller /GetDeviceParam .special_op { exch pop not }{ //true }ifelse { pop //false } if } { known } ifelse } { known } ifelse } .bind odef % Create a table for translation DSC comments into Unicode UTF-16 /.make_DSC_translation_table { % <encoding> .make_DSC_translation_table <array> dup type /stringtype eq { cvn } if dup type /nametype eq { /Encoding findresource } if dup length array exch % [out] [in] 0 1 2 index length 1 sub { % [out] [in] i dup 2 index exch get % [out] [in] i n dup dup //null eq exch /.notdef eq or { pop -1 } { dup //AdobeGlyphList exch .knownget { % [out] [in] i n c dup type dup /arraytype eq exch /packedarraytype eq or { 0 get % fixme: using the 1st char } if exch pop % [out] [in] i c } { % [out] [in] i n (DSCEncoding defines a character that is not in AdobeGlyphList : ) exch .namestring concatstrings = /.make_DSC_translation_table cvx /undefined signalerror } ifelse } ifelse 3 index % [out] [in] i c [out] 3 1 roll put % [out] [in] } for pop % [out] } bind def 1000 % priority { % Note, this may not work if the initial device is not pdfwrite % and may require the use of -dProvideUnicode on the command line. % Check to see if the current device wants ToUnicode info /WantsToUnicode /GetDeviceParam .special_op { exch pop }{ //false }ifelse systemdict /ProvideUnicode .knownget not { //false } if or { currentglobal //true setglobal systemdict /.setupUnicodeDecoder known { /Unicode /Decoding resourcestatus { pop pop /Unicode /Decoding findresource .setupUnicodeDecoder } { QUIET not { (WARNING: /Unicode /Decoding resource is not accessible but it is useful for generating ToUnicode CMap.) = } if } ifelse } if setglobal } if } bind .schedule_init 1010 % priority { % Set a predefined configuration in the distiller device (pdfwrite) /PDFSETTINGS where { pop /PDFSETTINGS load } { % We use the presence of the OPDFRead key as a proxy for a pdfwrite-family device /ForOPDFRead /GetDeviceParam .special_op { % Get rid of the OPDFRead key exch pop % and then check the value to see if its pdfwrite or ps2write { /PSL2Printer } { /default } ifelse } { /default } ifelse } ifelse .distillersettings exch get % Don't override parameters defined on the command line. dup length .distillercommon length add dict begin .distillercommon 2 { { systemdict 2 index known { pop pop } { def } ifelse } forall } repeat % We use the presence of the OPDFRead key as a proxy for a pdfwrite-family device /ForOPDFRead /GetDeviceParam .special_op { % Get rid of the OPDFRead key exch pop % Then check to see if OPDFRead is true or not not { systemdict /PDFX known systemdict /PDFA known or { /DSCEncoding where { /DSCEncoding get .make_DSC_translation_table /DSCEncodingToUnicode exch def } if } if } if } if currentdict end .setdistillerparams .distillerdevice //null //false mark .putdeviceparams dup type /booleantype eq not { cleartomark pop } if pop pop } bind .schedule_init 2000 % priority { % Note, this may not work if the initial device is not pdfwrite % We use the presence of the OPDFRead key as a proxy for a pdfwrite-family device /ForOPDFRead /GetDeviceParam .special_op { % Get rid of the OPDFRead key and value pop pop % Inform the device with initial graphic state. See gdev_pdf_fill_path. newpath fill } if } bind .schedule_init .setlanguagelevel %END PDFWR gs_init.ps 0000644 00000270641 15030647507 0006565 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % Initialization file for the interpreter. % When this is run, systemdict is still writable. % Comment lines of the form % %% Replace <n> <file(s)> % indicate places where the next <n> lines should be replaced by % the contents of <file(s)>, when creating a single merged init file. % % For reasons not clear to me, some cases of %% are being treated as % DSC comments when (and only when) the resource files are disk based % This can kill DSC parsing for pdfwrite at least, so avoid using % double % comments in this file. % The interpreter can call out to PostScript code. All procedures % called in this way, and no other procedures defined in these % initialization files, have names that begin with %, e.g., % (%Type1BuildChar) cvn. % Interpreter library version number % NOTE: the interpreter code requires that the first non-comment token % in this file be an integer, and that it match the compiled-in version! 9550 % Check the interpreter revision. dup revision ne { (gs: Interpreter revision \() print revision 10 string cvs print (\) does not match gs_init.ps revision \() print 10 string cvs print (\).\n) print flush //null 1 .quit } if pop % Acquire userdict, and set its length if necessary. /userdict where { pop userdict maxlength 0 eq } { //true } ifelse systemdict exch { % userdict wasn't already set up by iinit.c. dup /userdict currentdict dup 200 .setmaxlength % userdict .forceput % userdict is local, systemdict is global } executeonly if begin % Init to global memory (possibly not needed, but left in for legacy purposes) //true .setglobal % Define .languagelevel if needed. systemdict /.languagelevel known not { /.languagelevel 1 def } if % Optionally choose a default paper size other than U.S. letter. % The default page size for many devices is set at compile time to % letter, but this can be changed to A4 although this is rarely done. % Some devices such as bbox have a different default page size, % and should not be set to A4 or letter. % When ghostscript is used in countries that use the international % standard page size A4 rather than US letter, the page size of % devices that default to letter or A4 can be changed by setting % DEFAULTPAPERSIZE. % /DEFAULTPAPERSIZE (a4) def % Turn on array packing for the rest of initialization. //true setpacking % Define the old MS-DOS EOF character as a no-op. % This is a hack to get around the absurd habit of MS-DOS editors % of adding an EOF character at the end of the file. <1a> cvn { } def % Acquire the debugging flags. currentdict /DEBUG known /DEBUG exch def % if DEBUG is set, set ALL of the subset debugging flags mark % '[' isn't defined yet /CCFONTDEBUG % Compiled Fonts /CFFDEBUG % CFF Fonts /CMAPDEBUG % CMAP /DOCIEDEBUG % CIE color /EPSDEBUG % EPS handling /FAPIDEBUG % Font API /INITDEBUG % Initialization /PDFDEBUG % PDF Interpreter /PDFWRDEBUG % PDF Writer /SETPDDEBUG % setpagedevice /TTFDEBUG % TTF Fonts /VGIFDEBUG % ViewGIF /VJPGDEBUG % ViewJPEG /RESMPDEBUG % Resource map counttomark array astore exch pop % ']' isn't defined yet { dup currentdict exch known DEBUG or def } forall currentdict /PDFSTEP known /PDFSTEP exch def % if PDFSTEP is on, turn on PDFDEBUG PDFSTEP { /PDFDEBUG //true def } if currentdict /PDFSTOPONERROR known /PDFSTOPONERROR exch def currentdict /PDFSTOPONWARNING known {/PDFSTOPONWARNING //true def /PDFSTOPONERROR //true def}{/PDFSTOPONWARNING //false def} ifelse currentdict /PDFNOCIDFALLBACK known /PDFNOCIDFALLBACK exch def /.bind /bind load def /VMDEBUG INITDEBUG {{print mark systemdict /level2dict known { .currentglobal dup //false .setglobal vmstatus //true .setglobal vmstatus 3 -1 roll pop 6 -2 roll pop .setglobal } { vmstatus 3 -1 roll pop } ifelse usertime 16#fffff and counttomark { ( ) print ( ) cvs print } repeat pop ( ) print systemdict length ( ) cvs print ( ) print countdictstack ( ) cvs print ( <) print count ( ) cvs print (>\n) print flush }} {{pop }} ifelse .bind def % This was a debugging switch removed in 9.22, no other software % should have had any regard for it, and even if testing its value % should have checked its existence first. However pstotext, an % ancient and no longer maintained piece of softare, did check % its value unconditionally. So we retain this key in the dictionary % purely for backward compatibility. /NOBIND //false def currentdict /BATCH known /BATCH exch def currentdict /DELAYBIND known /DELAYBIND exch def currentdict /DOINTERPOLATE .knownget { { -1 } { 1 } ifelse /InterpolateControl exch def } if currentdict /NOINTERPOLATE .knownget { { 0 } { 1 } ifelse /InterpolateControl exch def } if currentdict /ESTACKPRINT known /ESTACKPRINT exch def currentdict /FAKEFONTS known /FAKEFONTS exch def currentdict /FIXEDMEDIA known /FIXEDMEDIA exch def currentdict /FIXEDRESOLUTION known /FIXEDRESOLUTION exch def currentdict /LOCALFONTS known /LOCALFONTS exch def currentdict /JOBSERVER known /JOBSERVER exch def currentdict /NOCACHE known /NOCACHE exch def currentdict /NOCCFONTS known /NOCCFONTS exch def currentdict /NOCIE known /NOCIE exch def currentdict /NOPSICC known /NOPSICC exch def currentdict /NODISPLAY known not /DISPLAYING exch def currentdict /NOFONTMAP known /NOFONTMAP exch def currentdict /NOFONTPATH known /NOFONTPATH exch def currentdict /NOGC known /NOGC exch def currentdict /NOMEDIAATTRS known /NOMEDIAATTRS exch def currentdict /NOOUTERSAVE known /NOOUTERSAVE exch def currentdict /NOPAGEPROMPT known /NOPAGEPROMPT exch def currentdict /NOPAUSE known /NOPAUSE exch def currentdict /NOPLATFONTS known /NOPLATFONTS exch def currentdict /NOPROMPT known /NOPROMPT exch def currentdict /NOTRANSPARENCY known /NOTRANSPARENCY exch def currentdict /DOPS known /DOPS exch def currentdict /NOSUBSTDEVICECOLORS known /NOSUBSTDEVICECOLORS exch def % The default value of ORIENT1 is true, not false. currentdict /ORIENT1 known not { /ORIENT1 //true def } if currentdict /OSTACKPRINT known /OSTACKPRINT exch def currentdict /OUTPUTFILE known % obsolete { /OutputFile /OUTPUTFILE load def currentdict /OUTPUTFILE .undef } if currentdict /QUIET known /QUIET exch def % DELAYSAFER is effectively the same as newer NOSAFER currentdict /DELAYSAFER known { /DELAYSAFER //true def /NOSAFER //true def } if /SAFER currentdict /NOSAFER known { //false } { //true } ifelse def /OLDSAFER currentdict /OLDSAFER known def /SAFERERRORS currentdict /NOSAFERERRORS known { //false } { currentdict /SAFERERRORS known } ifelse def currentdict /ALLOWPSTRANSPARENCY known not { /ALLOWPSTRANSPARENCY //false def } if currentdict /SHORTERRORS known /SHORTERRORS exch def currentdict /TTYPAUSE known /TTYPAUSE exch def currentdict /WRITESYSTEMDICT known /WRITESYSTEMDICT exch def currentdict /RENDERTTNOTDEF known /RENDERTTNOTDEF exch def currentdict /SCANCONVERTERTYPE known { currentdict /SCANCONVERTERTYPE get .setscanconverter } if currentdict /EPSFitPage known { /PSFitPage //true def } if % This is a "convenience" option that sets a combination of EPSFitPage, PDFFitPage and PSFitPage currentdict /FitPage known { /EPSFitPage //true def /PDFFitPage //true def /PSFitPage //true def } if currentdict /SimulateOverprint known { (\n**** -dSimulateOverprint={true|false} is no longer supported. ****\n) print (**** It has been replaced by -dOverprint={enable|disable|simulate} ****\n\n) print % Set the new variable appropriately. /Overprint SimulateOverprint { /enable } { /disable } ifelse def } if % Acquire environment variables. currentdict /DEVICE known not { (GS_DEVICE) getenv { /DEVICE exch def } if } if (START) VMDEBUG % Open the standard files, so they will be open at the outermost save level. (%stdin) (r) file pop (%stdout) (w) file pop (%stderr) (w) file pop /.currentuserparams where { pop mark % The Adobe implementations appear to have very large maximum % stack sizes. This turns out to actually make a difference, % since some badly-behaved files include extremely long procedures, % or construct huge arrays on the operand stack. % We reset the stack sizes now so that we don't have to worry % about overflowing the (rather small) built-in stack sizes % during initialization. /MaxDictStack 500 /MaxExecStack 5000 /MaxOpStack 300000 .dicttomark .setuserparams } if % Define a procedure for skipping over an unneeded section of code. % This avoids allocating space for the skipped procedures. % We can't use readline, because that imposes a line length limit. /.skipeof % <string> .skipeof - { currentfile exch 1 exch .subfiledecode flushfile } .bind def % Define procedures to assist users who don't read the documentation. userdict begin /help { (Enter PostScript commands. '(filename) run' runs a file, 'quit' exits.\n) print flush } .bind def end % Define =string, which is used by some PostScript programs even though % it isn't documented anywhere. % Put it in userdict so that each context can have its own copy. userdict /=string 256 string put % Print the greeting. /printgreeting { mark product (GPL Ghostscript) search { pop pop pop (This software is supplied under the GNU AGPLv3 and comes with NO WARRANTY:\nsee the file COPYING for details.\n) } { pop } ifelse (\n) copyright (\)\n) revisiondate 10 mod revisiondate 10 idiv 10 mod (-) revisiondate 100 idiv 10 mod revisiondate 1000 idiv 10 mod (-) revisiondate 10000 idiv ( \() revision 10 mod (.) revision 1000 mod 10 idiv (.) revision 1000 idiv ( ) product counttomark { (%stdout) (w) file exch 0 .writecvp } repeat pop } .bind def QUIET not { //printgreeting exec flush } if currentdict /printgreeting .undef % Define a special version of def for making operator procedures. /obind { % <name> <proc> obind <name> <oper> 1 index exch .makeoperator } .bind def /odef { % <name> <proc> odef - 1 index exch .makeoperator def } .bind def % Define procedures for accessing variables in systemdict and userdict % regardless of the contents of the dictionary stack. /.systemvar { % <name> .systemvar <value> //systemdict exch get } .bind executeonly odef /.systemexec { .systemvar exec } .bind executeonly odef /.userdict { % - .userdict <dict> /userdict .systemvar } .bind executeonly odef /.uservar { % <name> .uservar <value> .userdict exch get } .bind executeonly odef % If we're delaying binding, remember everything that needs to be bound later. DELAYBIND { SAFER { (\n *** WARNING - you have selected SAFER, indicating you want Ghostscript\n) print ( to execute in a safer environment, but at the same time\n) print ( have selected DELAYBIND. Unless you use this option with\n) print ( care \(and specifically, remember to call .bindnow\) it is\n) print ( possible that malicious code may be able to evade the\n) print ( limited security offered by the SAFER option.\n) print flush } if .currentglobal //false .setglobal systemdict /.delaybind 2000 array .forceput .setglobal userdict /.delaycount 0 put % When we've done the delayed bind, we want to stop saving. % Detect this by the disappearance of .delaybind. /bind { /.delaybind .systemvar dup length 0 ne { .delaycount 2 index put .userdict /.delaycount .delaycount 1 add put } { pop /.bind cvx exec } ifelse } .bind odef } executeonly if .currentglobal //true .setglobal /.undefinternalnameslist 10 dict def .setglobal % Under normal operation .undefinternalnames simply removes % the keys in the array parameter from the dictionary parameter. % Under DELAYBIND operation, we accumulate the names in dictionaries, % stored in .undefinternalnameslist, and then .bindow calls % .applyundefinternalnames once all binds have been applied. % The .undefinternalnameslist dictionary is a little odd in that it % uses the dictionary from which the keys should be undefined as the % 'key' and then the value is a dictionary whose key/value pairs are % both the names to be undefined. % % [array of names] <<dict from which to undef>> .undefinternalnames - /.undefinternalnames { DELAYBIND { .currentglobal //true .setglobal 3 1 roll dup //.undefinternalnameslist exch .knownget not { 128 dict dup 3 1 roll //.undefinternalnameslist 3 1 roll put }{exch pop} ifelse exch { dup 2 index 3 1 roll put } forall pop .setglobal } { exch { 1 index exch .forceundef } executeonly forall pop } executeonly ifelse } .bind executeonly def /.applyundefinternalnames { //.undefinternalnameslist { { pop 1 index exch .forceundef } executeonly forall pop } executeonly forall } .bind executeonly def %**************** BACKWARD COMPATIBILITY **************** /hwsizedict mark /HWSize //null .dicttomark readonly def /copyscanlines { % <device> <y> <string> copyscanlines <substr> 0 3 1 roll 3 index //hwsizedict .getdeviceparams exch pop exch pop aload pop 3 2 roll 0 exch //null exch .getbitsrect exch pop } bind odef currentdict /hwsizedict .undef /getdeviceprops { //null .getdeviceparams } bind odef % NOTE: Note sure why/if this needs to be a separate operator. Consider rolling this % implementation into /putdeviceprops ? /.putdeviceprops { //null //true counttomark 1 add 3 roll .putdeviceparams dup type /booleantype ne { dup mark eq { /unknown /rangecheck } if counttomark 4 add 1 roll cleartomark pop pop pop /.putdeviceprops .systemvar exch signalerror } if } bind executeonly odef /.writecvs { 0 .writecvp } bind odef %**************** DEPRECATED PROCEDURES **************** %**************** DO NOT USE THESE IN NEW CODE **************** % Keeping these because they have been around a long time and we don't want to break old code that's out in the wild /max { .max } bind def % use .max instead /min { .min } bind def % use .min instead %**************** END OF BACKWARD COMPATIBILITY SECTION **************** % Utility for removing all entries from a dictionary /.PurgeDict % <dict> .PurgeDict - { { //true 1 index { pop exch pop //false exit } forall { exit } if 1 index exch undef } loop pop } bind def % Define predefined procedures substituting for operators, % in alphabetical order. userdict /#copies 1 put % Adobe implementations don't accept /[ or /], so we don't either. ([) cvn /mark load def (]) cvn {counttomark array astore exch pop} odef % % - initgraphics - % % Although the internal routine gs_initgraphics resets the color space, % it does not reset the color space we store in the 'interpreter' % graphics state (so that we can hand it back in currentcolorspace). % So we need to do that in the PostScript world. % % /initgraphics { initgraphics systemdict /DeviceGray_array get setcolorspace } .bind executeonly odef /currentmatrix { dup type /arraytype ne { /currentmatrix load /typecheck signalerror } if dup length 6 ne { /currentmatrix load /rangecheck signalerror } if .currentmatrix 6 .argindex astore pop } odef % We have to guard against the BeginPage procedure not popping its operand. % This is really stupid, but the Genoa CET does it. /.beginpage { % - .beginpage - .updatematrices .currentshowpagecount { .currentpagedevice pop dup //null ne { /BeginPage .knownget } { pop //false } ifelse { % Stack: ... pagecount proc count 2 .execn % Stack: ... ..???.. oldcount count 1 add exch sub { pop } repeat } { pop } ifelse } if } .bind executeonly odef % Guard similarly against EndPage not popping its operand. /.endpage { % <reason> .endpage <print_bool> .updatematrices .currentshowpagecount { 1 index .currentpagedevice pop dup //null ne { /EndPage .knownget } { pop //false } ifelse { % Stack: ... reason pagecount reason proc count 2 .execn % Stack: ... ..???.. print oldcount count 2 add exch sub { exch pop } repeat } { pop pop 2 ne } ifelse } { 2 ne } ifelse } .bind executeonly odef % Define .currentnumcopies so it consults the NumCopies device parameter. /.numcopiesdict mark /NumCopies dup .dicttomark readonly def /.currentnumcopies { currentdevice //.numcopiesdict .getdeviceparams dup type /integertype eq { exch pop exch pop } { cleartomark #copies } ifelse } .bind executeonly odef /setcolorscreen where { pop % not in all Level 1 configurations /currentcolorscreen { .currenthalftone { { 60.0 exch 0.0 exch 3 copy 6 copy } % halftone - not possible { 3 copy 6 copy } % screen { } % colorscreen } exch get exec } odef } if /currentscreen { .currenthalftone { { 60.0 exch 0.0 exch } % halftone - not possible { } % screen { 12 3 roll 9 { pop } repeat } % colorscreen } exch get exec } odef /.echo /echo load def userdict /.echo.mode //true put /echo {dup /.echo.mode exch store .echo} odef /.eexec_param_dict mark /eexec //true /seed 55665 .dicttomark readonly def /eexec { % Rebind .currentresourcefile if it is the source for the eexec. dup //.eexec_param_dict //filterdict /eexecDecode get exec cvx exch .currentresourcefile eq //systemdict begin { {exec} .execasresource } { exec } ifelse % Only pop systemdict if it is still the top element, % because this is apparently what Adobe interpreters do. currentdict //systemdict eq { end } if } odef % erasepage mustn't use gsave/grestore, because we call it before % the graphics state stack has been fully initialized. /erasepage { /currentcolor where { pop currentcolor currentcolorspace { setcolorspace setcolor } } { /currentcmykcolor where { pop currentcmykcolor { setcmykcolor } } { currentrgbcolor { setrgbcolor } } ifelse } ifelse currentoverprint //false setoverprint 1 setgray .fillpage setoverprint exec } odef % Define a procedure for clearing the error indication. /.clearerror { $error /newerror //false put $error /errorname //null put $error /errorinfo //null put 0 .setoserrno } bind executeonly def % To satisfy the Genoa FTS, executive must be a procedure, not an operator. % Define the procedure used by .runfile, .runstdin and .runstring % for executing user input. % This is called with a procedure or executable file on the operand stack. /.execute { % <obj> .execute <stopped> stopped $error /newerror get and { /handleerror .systemvar exec flush //true } { //false } ifelse } bind def % Define an execute analogue of runlibfile0. /execute0 { % <obj> execute0 - //.execute exec { /execute0 cvx 1 .quit } if } bind def /executive { { prompt { (%statementedit) (r) .systemvmfile } stopped { pop pop $error /errorname get /undefinedfilename eq { //.clearerror exec exit } if % EOF /handleerror .systemvar exec //null % ioerror?? } if cvx { .runexec } //.execute exec pop } loop } bind def currentdict /.execute .undef /filter { //filterdict 1 .argindex .knownget { exch pop exec } { /filter .systemvar /undefined signalerror } ifelse } odef % Internal uses of stopped that aren't going to do a stop if an error occurs % should use .internalstopped to avoid setting newerror et al. /.internalstopped { //null 1 .stopped //null ne } bind executeonly def % handleerror procedure as mentioned in the "Operators" section of the PLRM Section 8.2 % This invokes the handleerror procedure from errordict (unless we are running under a % JOBSERVER where we want to always use a defined error handler (many error handlers in % 'wild' PostScript files are broken and don't indicate the error in any useful fashion). % % We run the handleerror procedure using .internalstopped so that broken error handlers % won't cause nested errors (Unexpected Error conditions). /handleerror //systemdict /JOBSERVER get{ { /.GShandleerror .systemvar //.internalstopped exec pop } bind % always use .GShandleerror. } { { /errordict .systemvar /handleerror get //.internalstopped exec pop } bind % PLRM standard errorhandling } ifelse def /identmatrix [1.0 0.0 0.0 1.0 0.0 0.0] readonly def /identmatrix { dup type /arraytype ne { /identmatrix load /typecheck signalerror } if dup length 6 ne { /identmatrix load /rangecheck signalerror } if dup 0 //identmatrix putinterval } odef /languagelevel 1 def % gs_lev2.ps may change this /makeimagedevice { //false makewordimagedevice } odef /matrix { 6 array identmatrix } odef /.promptmsg { (GS) print count 0 ne { (<) print count =only } if (>) print flush } bind def /prompt { flush flushpage //systemdict /NOPROMPT get not { //.promptmsg exec} if } bind def currentdict /.promptmsg .undef /pstack { 0 1 count 3 sub { index == } for } bind def /putdeviceprops { .putdeviceprops { erasepage } if } bind executeonly odef /quit { /quit load 0 .quit } odef /run { dup type /filetype ne { (r) .systemvmfile } if % We must close the file when execution terminates, % regardless of the state of the stack, % and then propagate an error, if any. cvx //null {.runexec} .errorexec } odef % Execute a file. % Level 2 uses 2 .stop to clear the e-stack for a successful startjob: % we detect that here, since we need to handle this even if we start out % without job control in effect. % % What we push on the e-stack is the following to be executed in this order: % <lit-file|fileproc> .runexec1 <lit-file|fileproc> .runexec2 /.runexec1 { % <file|fileproc> .runexec1 - dup type /filetype ne { cvx exec } if cvx //null 2 .stopped % If we got back here from a startjob, just keep going. % startjob replaces the null on the o-stack with a procedure % to be executed when we get back here. dup //null ne { exec //true } { pop //false } ifelse } bind executeonly def /.runexec2 { % <continue> <file|fileproc> .runexec2 - exch { .runexec } { dup type /filetype ne { cvx exec } if closefile } ifelse } bind def /.runexec { % <file|fileproc> .runexec - cvlit /.runexec1 cvx 1 index /.runexec2 cvx 4 .execn } bind def % The following is only for compatibility with Adobe interpreters. /setdash { 0 .argindex type dup /integertype eq exch /realtype eq or not { /setdash .systemvar /typecheck signalerror } if //setdash } odef /setdevice { .setdevice { mark { % Reset the halftone since the device may differ currenthalftone dup type /dicttype eq { sethalftone } { pop } ifelse } stopped cleartomark erasepage } if } odef /setlinecap { dup 2 gt { /setlinecap .systemvar /rangecheck signalerror } if .setlinecap } odef /setlinejoin { dup 2 gt { /setlinejoin .systemvar /rangecheck signalerror } if .setlinejoin } odef /setmatrix { dup type /arraytype ne { dup type /packedarraytype ne { /setmatrix load /typecheck signalerror } if } if dup length 6 ne { /setmatrix load /rangecheck signalerror } if dup aload pop .setmatrix pop } odef /.confirmread { //systemdict /TTYPAUSE get { (/dev/tty) (r) file dup read pop pop closefile } { .echo.mode //false echo (%stdin) (r) file dup read { dup (\n) 0 get eq { pop pop } { .unread } ifelse } { pop } ifelse echo } ifelse } bind executeonly def /.confirm { //systemdict /DISPLAYING get //systemdict /NOPAUSE get not //systemdict /TTYPAUSE get or and { % Print a message (unless NOPAGEPROMPT or NOPROMPT is true) % and wait for the user to type something. % If the user just types a newline, flush it. //systemdict /NOPAGEPROMPT get //systemdict /NOPROMPT get or { pop } { print flush } ifelse //.confirmread exec } { pop } ifelse } bind executeonly def % In LanguageLevel 3, copypage erases the page. /copypage { .languagelevel 3 ge dup { 0 } { 1 } ifelse .endpage .doneshowpage { .currentnumcopies 1 index .outputpage (>>copypage, press <return> to continue<<\n) //.confirm exec dup { erasepage } if } if pop systemdict /..page_default_spaces .knownget { //.PurgeDict exec } if .beginpage } .bind executeonly odef /showpage { 0 .endpage .doneshowpage { .currentnumcopies //true .outputpage (>>showpage, press <return> to continue<<\n) //.confirm exec % Uncomment the following line, and use a Memento build to track % blocks that are created and not destroyed between each successive % page. % 2 .vmreclaim .mementolistnewblocks initgraphics currentoverprint //false setoverprint 1 setcolor .fillpage setoverprint 0 setcolor } { initgraphics } ifelse systemdict /..page_default_spaces .knownget { //.PurgeDict exec } if .beginpage } .bind executeonly odef % Code output by Adobe Illustrator relies on the fact that % `stack' is a procedure, not an operator!!! /stack { 0 1 count 3 sub { index = } for } bind def /start { //systemdict /BATCH get { //null 0 .quit } { executive } ifelse } def /store { % Don't alter operands before completing. 1 .argindex where { 2 index 2 index put pop pop } { def } ifelse } odef /.typenames mark .typenames counttomark packedarray exch pop def /type { //.typenames .type } odef currentdict /.typenames .undef % When running in Level 1 mode, this interpreter is supposed to be % compatible with PostScript "version" 54.0 (I think). /version (54.0) readonly def /.wheredict 10 dict def /.where /where load def /where { //.wheredict 1 .argindex .knownget { exec } { .where } ifelse } odef % internaldict is defined in systemdict, but the dictionary is allocated % in local VM. However, the procedure must be global, since it is an % "operator" and must be bind-able into global procedures. /.makeinternaldict { .currentglobal //true .setglobal [ /dup .systemvar 1183615869 /eq .systemvar [ /pop .systemvar //null ] cvx //false .setglobal dup 1 10 dict .forceput % proc is global, dict is local //true .setglobal [ /internaldict /cvx .systemvar /invalidaccess /signalerror cvx ] cvx /ifelse .systemvar ] cvx executeonly exch .setglobal } executeonly def systemdict /internaldict dup .makeinternaldict .makeoperator .forceput % proc is local, systemdict is global currentdict /.makeinternaldict .undef % Define some additional built-in procedures (beyond the ones defined by % the PostScript Language Reference Manual). % Warning: these are not guaranteed to stay the same from one release % to the next! /concatstrings % (str1) (str2) concatstrings (str1str2) { exch dup length 2 index length add string % str2 str1 new dup dup 4 2 roll copy % str2 new new new1 length 4 -1 roll putinterval } bind def /copyarray { dup length array copy } bind def % Copy a dictionary per the Level 2 spec even in Level 1. /.copydict % <fromdict> <todict> .copydict <todict> { dup 3 -1 roll { put dup } forall pop } bind def /findlibfile { .systemvmlibfile { dup .filename pop exch //true } { //false } ifelse } odef /.growdictlength % get size for growing a dictionary { length 3 mul 2 idiv 1 add } bind def /.growdict % grow a dictionary { dup //.growdictlength exec .setmaxlength } bind def /.growput % put, grow the dictionary if needed { 2 index length 3 index maxlength eq { 3 copy pop known not { 2 index //.growdict exec} if } if put } bind def % .localvmarray may be an operator: see zsysvm.c. /.localvmarray where { pop } { /.localvmarray { .currentglobal //false .setglobal exch array exch .setglobal } bind def } ifelse /.localvmdict where { pop } { /.localvmdict { .currentglobal //false .setglobal exch dict exch .setglobal } bind def } ifelse /.packtomark { counttomark packedarray exch pop } bind def /runlibfile { % We don't want to bind 'run' into this procedure, % since run may get redefined. findlibfile { exch pop /run .systemvar exec } { /undefinedfilename signalerror } ifelse } bind def /selectdevice { finddevice setdevice .setdefaultscreen } bind def /signalerror % <object> <errorname> signalerror - { /errordict .systemvar exch get exec } bind def /signaloperror { % <object> <errorname> signaloperror - % Same as signalerror, except that if we are inside a pseudo-operator % or .errorexec, we use its error object, just as errors generated by % real operators do. /errordict .systemvar exch get .finderrorobject { 3 -1 roll pop exch } if exec } bind def % Define the =[only] procedures. Also define =print, % which is used by some PostScript programs even though % it isn't documented anywhere. /write=only { .writecvs } bind def /write= { 1 index exch write=only (\n) writestring } bind def /=only { (%stdout) (w) file exch write=only } bind def /= { =only (\n) print } bind def /=print /=only load def % Temporarily define == as = for the sake of runlibfile0. /== /= load def % The following procedures are documented. /copydevice { % <device> copydevice <newdevice> //false .copydevice2 } odef /finddevice { % <devicename> finddevice <device> /devicedict .systemvar exch get dup 1 get //null eq { % This is the first request for this type of device. % Create a default instance now. % Stack: [proto null] .currentglobal //true .setglobal exch dup dup 0 get copydevice 1 exch put exch .setglobal } if 1 get } bind def /findprotodevice { % <devicename> findprotodevice <protodevice> /devicedict .systemvar exch get 0 get } bind def % Run a resource file. This allows us to distinguish resource objects % from objects coming from input files. userdict /.currentresourcefile //null put /.execasresource { % <file> <proc|runfile> .execasresource - /stopped .systemvar /.currentresourcefile .uservar % Stack: file proc -stopped- currfile .userdict /.currentresourcefile 5 index cvlit put 2 .execn % stopped <file> .userdict /.currentresourcefile 3 -1 roll put { stop } if } bind executeonly def /.runresource { % <file> .runresource - { /run .systemvar exec } .execasresource } bind def % Convenience function (documented extension) /.shellarguments % -> shell_arguments true (or) false { /ARGUMENTS where { /ARGUMENTS get dup type /arraytype eq { aload pop /ARGUMENTS //null store //true } { pop //false } ifelse } { //false } ifelse } bind def % Define the procedure that the C code uses for running files % named on the command line. /.runfile { { runlibfile } execute0 } def % Define the procedure that the C code uses for running piped input. % We don't use the obvious { (%stdin) run }, because we want the file to be % reopened if a startjob does a restore. /.runstdin { { { (%stdin) (r) file cvx } .runexec } execute0 } bind def % Define the procedure that the C code uses for running commands % given on the command line with -c. We turn the string into a file so that % .runexec can do the right thing with a startjob. /.runstring { 0 0 .systemvmstring .systemvmSFD cvx { .runexec } execute0 } bind def % Define the procedure that the C code uses to set up for executing % a string that may be received in pieces. % % Immediate evaluation doesn't work on operators (like .needinput) % so calling .runstringbegin will throw an undefined error if we % undefined .needinput so it cannot be accessed outside the init % code. But, we can store the operator in an array, use immediate % evaluation on the array to get the operator, then undefined the % array (and because they are both of the same name, the operator % get undefined too). % This prevents random Postscript from erroneously calling .needinput % and forcing the interpreter into an invalid state. /.needinput 1 .systemvmarray dup 0 /.needinput load put def /.runstringbegin { 1 .systemvmarray dup 0 //.needinput 0 get put cvx % { .needinput } in systemvm 0 0 .systemvmstring .systemvmSFD cvx .runexec } bind executeonly def % Define a special version of runlibfile that aborts on errors. /runlibfile0 { cvlit dup dup /.currentfilename exch def { findlibfile not { stop } if } stopped { (Can't find \(or open\) initialization file ) print .currentfilename == flush /runlibfile0 cvx 1 .quit } if exch pop cvx { stopped } 0 get 3 -1 roll 2 array astore cvx exec /.currentfilename exch store { (While reading ) print .currentfilename print (:\n) print flush /handleerror .systemvar exec /runlibfile0 1 .quit } if } bind def % Temporarily substitute it for the real runlibfile. /.runlibfile /runlibfile load def /runlibfile //runlibfile0 def currentdict /runlibfile0 .undef % Create the error handling machinery. % Define the standard error handlers. % The interpreter has created the ErrorNames array. /.unstoppederrorhandler % <command> <errorname> .unstoppederrorhandler - { % This is the handler that gets used for recursive errors, % or errors outside the scope of a 'stopped'. 2 copy //systemdict /SHORTERRORS get { (%%[ Error: ) print =only flush (; OffendingCommand: ) print =only ( ]%%) = } { (Unrecoverable error: ) print =only flush ( in ) print = flush count 2 gt { (Operand stack:\n ) print count 1 sub -1 2 { ( ) print index =only flush } for () = flush } if } ifelse -1 0 1 //ErrorNames length 1 sub { dup //ErrorNames exch get 3 index eq { not exch pop exit } { pop } ifelse } for exch pop .quit } bind executeonly def /.errorhandler % <command> <errorname> .errorhandler - { % Detect an internal 'stopped'. 1 .instopped { //null eq { pop pop stop } if } if $error /.inerror get 1 .instopped { pop } { pop //true } ifelse { //.unstoppederrorhandler exec } if % detect error recursion $error /globalmode .currentglobal //false .setglobal put $error /.inerror //true put $error /newerror //true put $error exch /errorname exch put $error exch /command exch put $error /errorinfo known not { $error /errorinfo //null put } if $error /recordstacks get $error /errorname get /VMerror ne and { % Attempt to store the stack contents atomically. count array astore dup $error /ostack 4 -1 roll % Grab the execstack, then remove to two elements that are from % this error handler (not interesting). countexecstack array execstack dup length 2 sub 0 exch getinterval $error /estack 3 -1 roll countdictstack array dictstack $error /dstack 3 -1 roll put put put aload pop } { $error /dstack .undef $error /estack .undef $error /ostack .undef } ifelse $error /position currentfile status { currentfile { fileposition } //.internalstopped exec { pop //null } if } { % If this was a scanner error, the file is no longer current, % but the command holds the file, which may still be open. $error /command get dup type /filetype eq { { fileposition } //.internalstopped exec { pop //null } if } { pop //null } ifelse } ifelse put % During initialization, we don't reset the allocation % mode on errors. $error /globalmode get $error /.nosetlocal get and .setglobal $error /.inerror //false put stop } bind executeonly def currentdict /.unstoppederrorhandler .undef % Define the standard handleerror. We break out the printing procedure % (.printerror) so that it can be extended for binary output % if the Level 2 facilities are present. /.printerror_long % long error printout, % $error is on the dict stack { % Push the (anonymous) stack printing procedure. % <heading> <==flag> <override-name> <stackname> proc { currentdict exch .knownget % stackname defined in $error? { 4 1 roll % stack: <stack> <head> <==flag> <over> /errordict .systemvar exch .knownget % overridename defined? { exch pop exch pop exec % call override with <stack> } { exch print exch % print heading. stack <==flag> <stack> 1 index not { () = } if { 1 index { (\n ) } { ( ) } ifelse print dup type /dicttype eq { (--dict:) print dup rcheck { dup length =only (/) print dup maxlength =only dup wcheck not { ((ro)) print } if } if /gcheck where { pop gcheck { ((G)) } { ((L)) } ifelse print } { pop } ifelse (--) print } { dup type /stringtype eq 2 index or { ==only } { =only } ifelse } ifelse } forall pop } ifelse % overridden } { pop pop pop } ifelse % stack known } (\nOperand stack:) OSTACKPRINT /.printostack /ostack 4 index exec (\nExecution stack:) ESTACKPRINT /.printestack /estack 4 index exec (\nBacktrace:) //true /.printbacktrace /backtrace 4 index exec (\nDictionary stack:) //false /.printdstack /dstack 4 index exec () = pop % printing procedure errorname /VMerror eq { (VM status:) print mark vmstatus counttomark { ( ) print counttomark -1 roll dup =only } repeat cleartomark () = } if .languagelevel 2 ge { (Current allocation mode is ) print globalmode { (global\n) } { (local\n) } ifelse print } if .oserrno dup 0 ne { (Last OS error: ) print errorname /VMerror ne { dup .oserrorstring { = pop } { = } ifelse } { = } ifelse } { pop } ifelse position //null ne { (Current file position is ) print position = } if } bind executeonly def /.printerror { $error begin newerror { /command load errorname //systemdict /SHORTERRORS get { (%%[ Error: ) print =only flush (; OffendingCommand: ) print =only errorinfo dup //null eq { pop } { (;\nErrorInfo:) print dup type /arraytype eq { { ( ) print =only } forall } { ( ) print =only } ifelse } ifelse ( ]%%) = flush } { (Error: ) print ==only flush ( in ) print ==only flush errorinfo dup //null eq { pop } { (\nAdditional information: ) print ==only flush } ifelse //.printerror_long exec } ifelse //.clearerror exec flush } { % newerror is //false, test to see if user has set handleerror to a different % routine, if so execute it, otherwise, just return. This code deals with the % Genoa issue of setting /handleerror, and then calling it, without an error % being set. We were erroring in this case, due to /command load failing. //JOBSERVER { /errordict .systemvar /handleerror get /.GShandleerror .systemvar ne } { //false } ifelse { /errordict .systemvar begin /handleerror load //.internalstopped exec pop end } if } ifelse % newerror end flush } bind executeonly def currentdict /.printerror_long .undef % Define $error. This must be in local VM. .currentglobal //false .setglobal currentdict /$error 40 dict .forceput % $error is local, systemdict is global % newerror, errorname, command, errorinfo, % ostack, estack, dstack, recordstacks, % binary, globalmode, % .inerror, .nosetlocal, position, % plus extra space for badly designed error handers. $error begin /newerror //false def /recordstacks //true def /binary //false def /globalmode .currentglobal def /.inerror //false def /.nosetlocal //true def /position //null def /errorinfo //null def end % Define errordict similarly. It has one entry per error name, % plus handleerror. However, some astonishingly badly written PostScript % files require it to have at least one empty slot. currentdict /errordict ErrorNames length 3 add dict .forceput % errordict is local, systemdict is global .setglobal % back to global VM % gserrordict contains all the default error handling methods, but unlike % errordict it is noaccess after creation (also it is in global VM). % When running 'SAFER', we'll ignore the contents of errordict, which % may have been tampered with by the running job, and always use gserrordict % gserrordict also contains any non-standard errors, for better compatibility % with Adobe. % % NOTE: the name gserrordict is known to the interpreter. /gserrordict ErrorNames length 3 add dict def % Register an error in errordict. We make this a procedure because we only % register the Level 1 errors here: the rest are registered by "feature" % files. However, ErrorNames contains all of the error names regardless of % what features are included, so we have to "know" that VMerror is the last % Level 1 error. /.registererror2 % <dict> <name> .registererror - { .currentglobal //true .setglobal % create procs in global VM 3 1 roll mark 1 index systemdict /.errorhandler get /exec load //.packtomark exec cvx put .setglobal } bind def /.registererror % <name> .registererror - { errordict exch //.registererror2 exec } bind def currentdict /.registererror2 .undef ErrorNames { .registererror} forall errordict begin % The handlers for interrupt and timeout are special; there is no % 'current object', so they push their own name. { /interrupt /timeout } { mark 1 index dup systemdict /.errorhandler get /exec load //.packtomark exec cvx def } forall /handleerror % this key is 'well known' and some PS may redefine it { /.printerror .systemvar exec } bind def end % errordict gserrordict /unknownerror errordict /unknownerror get put errordict /unknownerror .undef /.SAFERERRORLIST ErrorNames def /.setsafererrors { % Put all the requested handlers in gserrordict gserrordict //.SAFERERRORLIST { dup /unknownerror eq {pop} { dup errordict exch get 2 index 3 1 roll put }ifelse }forall noaccess pop //systemdict /.setsafeerrors .forceundef //systemdict /.SAFERERRORLIST .forceundef } bind executeonly odef SAFERERRORS {.setsafererrors} if % Define a stable private copy of handleerror that we will always use under % JOBSERVER mode. /.GShandleerror errordict /handleerror get def % Define the [write]==[only] procedures. /.dict 8 dict dup begin def /.cvp {1 index exch 1 .writecvp} bind def /.p {1 index exch writestring} bind def /.p1 {2 index exch writestring} bind def /.p2 {3 index exch writestring} bind def /.print { dup type .dict exch .knownget { exec } { .cvp } ifelse } bind def /arraytype {dup rcheck {() exch dup xcheck {({) .p2 {exch .p1 1 index exch .print pop ( )} forall (})} {([) .p2 {exch .p1 1 index exch .print pop ( )} forall (])} ifelse exch pop .p} {.cvp} ifelse} bind def /packedarraytype /arraytype load def {//.dict begin .print pop end} bind end /write==only exch def /write== {1 index exch write==only (\n) writestring} bind def /==only { (%stdout) (w) file exch write==only } bind def /== {==only (\n) print} bind def % Define [write]===[only], an extension that prints dictionaries % in readable form and doesn't truncate strings. /.dict /write==only load 0 get dup length 2 add dict .copydict dup begin def /dicttype { dup rcheck { (<< ) .p1 { 2 index 3 -1 roll .print pop ( ) .p1 1 index exch .print pop ( ) .p } forall (>>) .p } { .cvp } ifelse } bind def /stringtype { 1 index exch 2 .writecvp } bind def {//.dict begin .print pop end} bind end /write===only exch def /write=== {1 index exch write===only (\n) writestring} bind def /===only { (%stdout) (w) file exch write===only } bind def /=== { ===only (\n) print } bind def % Create the initialization queue. 1183615869 internaldict dup /.delayed_init_queue 10 dict put /.schedule_init % <priority> <proc> .schedule_init - { 1183615869 internaldict begin .delayed_init_queue 2 index known { end (.delayed_init_queue priority conflict with ) print 1 index = /.schedule_init cvx /configurationerror signalerror } if .delayed_init_queue 3 1 roll .growput end } bind def begin /.execute_scheduled_inits % - .execute_scheduled_inits - { 2 dict begin /.newdelayed_init_queue mark 1183615869 internaldict /.delayed_init_queue get {} forall .dicttomark def { 0 //null .newdelayed_init_queue { % maxp {} p {} 3 index 2 index lt { 4 2 roll } if pop pop } forall exch .newdelayed_init_queue exch undef dup //null eq { pop exit } if exec } loop currentdict /.newdelayed_init_queue undef end } bind def end (END PROCS) VMDEBUG % Define the font directory. currentdict /FontDirectory //false .setglobal 100 dict //true .setglobal .forceput % FontDirectory is local, systemdict is global % Define the encoding dictionary. /EncodingDirectory 16 dict def % enough for Level 2 + PDF standard encodings % Define .findencoding. (This is redefined in Level 2.) /.findencoding { //EncodingDirectory exch get exec } bind def /.defineencoding { //EncodingDirectory 3 1 roll put } bind def % If we've got the composite font extensions, define findencoding. % To satisfy the Genoa FTS, findencoding must be a procedure, not an operator. /rootfont where { pop /findencoding { .findencoding } def } if % Define .registerencoding. % NOTE: This procedure no longer does anything, but it must continue to % exist for the sake of toolbin/encs2c.ps. /.registerencoding { % <index> <array> .registerencoding - pop pop } bind odef % Load StandardEncoding. %% Replace 1 (gs_std_e.ps) (gs_std_e.ps) dup runlibfile VMDEBUG % Load ISOLatin1Encoding. %% Replace 1 (gs_il1_e.ps) (gs_il1_e.ps) dup runlibfile VMDEBUG % Define stubs for the Symbol and Dingbats encodings. % Note that the first element of the procedure must be the file name, % since gs_lev2.ps extracts it to set up the Encoding resource category. /SymbolEncoding { /SymbolEncoding .findencoding } bind def %% Replace 3 (gs_sym_e.ps) EncodingDirectory /SymbolEncoding { (gs_sym_e.ps) //systemdict begin runlibfile SymbolEncoding end } bind put /DingbatsEncoding { /DingbatsEncoding .findencoding } bind def %% Replace 3 (gs_dbt_e.ps) EncodingDirectory /DingbatsEncoding { (gs_dbt_e.ps) //systemdict begin runlibfile DingbatsEncoding end } bind put (END FONTDIR/ENCS) VMDEBUG % Special handling for device parameters. Must follow definition of 'type' % make -dPDFA equivalent to -dPDFA=1 (backwards compatible) currentdict /PDFA known { PDFA type /booleantype eq { /PDFA 1 def } if } if % Construct a dictionary of all available devices. % These are (read-only) device prototypes that can't be % installed or have their parameters changed. For this reason, % the value in the dictionary is actually a 2-element writable array, % to allow us to create a default instance of the prototype on demand. % Loop until the .getdevice gets a rangecheck. errordict /rangecheck 2 copy get errordict /rangecheck { pop stop } put % pop the command 0 { {dup .getdevice exch 1 add} loop} //.internalstopped exec pop 1 add dict /devicedict 1 index def begin % 2nd copy of count is on stack { dup .devicename exch dup wcheck { dup } { //null } ifelse 2 array astore def } repeat end put % errordict /rangecheck .clearerror /devicenames devicedict { pop } forall devicedict length packedarray def % Determine the default device. /defaultdevice //systemdict /DISPLAYING get { //systemdict /DEVICE .knownget { devicedict 1 index known not { (Unknown device: ) print = flush /defaultdevice cvx 1 .quit } if } { .getdefaultdevice .devicename } ifelse } { /nullpage } ifelse /.defaultdevicename 1 index def finddevice % make a copy def devicedict /Default devicedict .defaultdevicename get put (END DEVS) VMDEBUG % Define statusdict, for the benefit of programs % that think they are running on a LaserWriter or similar printer. %% Replace 1 (gs_statd.ps) (gs_statd.ps) runlibfile (END STATD) VMDEBUG % Load the standard font environment. %% Replace 1 (gs_fonts.ps) (gs_fonts.ps) runlibfile (END GS_FONTS) VMDEBUG % Define the default halftone screen and BG/UCR functions now, so that % it will bind in the original definitions of set[color]screen. % We make this a procedure so we can call it again when switching devices. % Use an ordered dither for low-resolution devices. /.setloreshalftone { % <dpi> .setloreshalftone - % The following 'ordered dither' spot function was contributed by % Gregg Townsend. Thanks, Gregg! 16.001 div 0 % not 16: avoids rounding problems { 1 add 7.9999 mul cvi exch 1 add 7.9999 mul cvi 16 mul add < 0E 8E 2E AE 06 86 26 A6 0C 8C 2C AC 04 84 24 A4 CE 4E EE 6E C6 46 E6 66 CC 4C EC 6C C4 44 E4 64 3E BE 1E 9E 36 B6 16 96 3C BC 1C 9C 34 B4 14 94 FE 7E DE 5E F6 76 D6 56 FC 7C DC 5C F4 74 D4 54 01 81 21 A1 09 89 29 A9 03 83 23 A3 0B 8B 2B AB C1 41 E1 61 C9 49 E9 69 C3 43 E3 63 CB 4B EB 6B 31 B1 11 91 39 B9 19 99 33 B3 13 93 3B BB 1B 9B F1 71 D1 51 F9 79 D9 59 F3 73 D3 53 FB 7B DB 5B 0D 8D 2D AD 05 85 25 A5 0F 8F 2F AF 07 87 27 A7 CD 4D ED 6D C5 45 E5 65 CF 4F EF 6F C7 47 E7 67 3D BD 1D 9D 35 B5 15 95 3F BF 1F 9F 37 B7 17 97 FD 7D DD 5D F5 75 D5 55 FF 7F DF 5F F7 77 D7 57 02 82 22 A2 0A 8A 2A AA 00 80 20 A0 08 88 28 A8 C2 42 E2 62 CA 4A EA 6A C0 40 E0 60 C8 48 E8 68 32 B2 12 92 3A BA 1A 9A 30 B0 10 90 38 B8 18 98 F2 72 D2 52 FA 7A DA 5A F0 70 D0 50 F8 78 D8 58 > exch get 256 div } bind % Use correct, per-plane screens for CMYK devices only. //systemdict /setcolorscreen known processcolors 4 eq and { 3 copy 6 copy //setcolorscreen } { //setscreen } ifelse } bind def /.setloresscreen { % <dpi> .setloresscreen - .setloreshalftone 0 array cvx settransfer % Genoa CET won't accept a packed array! /setstrokeadjust where { pop //true setstrokeadjust } if } bind def % Use a 45-degree spot screen for high-resolution devices. % The PS3 CET insists that the screen be an array and not a packedarray (!). currentpacking //false setpacking /.linescreen % The following screen algorithm is used by permission of the author. { ((C) 1989 Berthold K.P. Horn) pop 1 add 180 mul cos 1 0.08 add mul exch 2 add 180 mul cos 1 0.08 sub mul add 2 div } bind readonly def setpacking /.sethireshalftone { % <dpi> .sethireshalftone <doscreen> % According to information published by Hewlett-Packard, % they use a 60 line screen on 300 DPI printers and % an 85 line screen on 600 DPI printers. % However, we use a 106 line screen, which produces smoother- % looking shades but fewer of them (32 vs. 50). % 46 was suggested as a good frequency value for printers % between 200 and 400 DPI, so we use it for lower resolutions. % Imagesetters need even higher frequency screens. //systemdict /DITHERPPI known { //systemdict /DITHERPPI get } { dup cvi 100 idiv 15 .min {//null 46 46 60 60 60 106 106 106 106 133 133 133 133 133 150} exch get } ifelse 1 index 4.01 div .min % at least a 4x4 cell 45 //.linescreen % Determine whether we have lots of process colors. % If so, don't bother with color screening or gamma correction. % Also don't do gamma correction on very high-resolution devices. % (This should depend on dot gain, not resolution, but we don't % currently have a way to determine this.) Ignore missing components % (*Values = 1). currentdevice mark /RedValues 0 /GreenValues 0 /BlueValues 0 /GrayValues 0 .dicttomark .getdeviceparams counttomark 2 idiv 1 sub { exch pop dup 1 le { pop } { exch dup 1 le { pop } { .min } ifelse } ifelse } repeat exch pop exch pop 32 lt 4 index 800 lt and 5 1 roll % Stack: doscreen dpi freq angle proc % Ghostscript currently doesn't use correct, per-plane halftones % unless setcolorscreen has been executed. Since these are % computationally much more expensive than binary halftones, % we check to make sure they are really warranted, i.e., we have % a high-resolution CMYK device (i.e., not a display) with % fewer than 5 bits per plane (i.e., not a true-color device). 4 -1 roll 150 ge { /setcolorscreen where { pop //systemdict /COLORSCREEN known { //systemdict /COLORSCREEN get} { 3 index } ifelse dup //false ne { 4 1 roll 3 copy 6 copy 13 -1 roll % For really high-quality screening on printers, we need to % give each plane its own screen angle. Unfortunately, % this currently has very large space and time costs. //true eq % true => different angles, % 0 => same angles { { 45 90 15 75 } { 3 1 roll exch pop 12 3 roll } forall } if //setcolorscreen } { pop //setscreen % false => single binary screen } ifelse } { //setscreen % setcolorscreen not known } ifelse } { //setscreen % not high resolution } ifelse } bind def /.sethiresscreen { % <dpi> .sethiresscreen .sethireshalftone % pushes true if a screen halftone used % Stack: doscree { % Set the transfer function to lighten up the grays. % Parameter values closer to 1 are better for devices with % less dot spreading; lower values are better with more spreading. % The value 0.8 is a compromise that will probably please no one! % % Because of a bug in FrameMaker, we have to accept operands % outside the valid range of [0..1]. { dup dup 0.0 gt exch 1.0 lt and { 0.8 exp } if } } { % Set the transfer function to the identity. 0 array cvx % Genoa CET won't accept a packed array! } ifelse settransfer /setstrokeadjust where { pop //false setstrokeadjust } if % Increase fill adjustment so that we effectively use Adobe's % any-part-of-pixel rule. 0.5 dup .setfilladjust2 } bind def % Set the default screen and BG/UCR. % We define the proc here, rather than inline in .setdefaultbgucr % for the benefit of gs_cet.ps so jobs that do anything that causes % .setdefaultbgucr to be called will still get the redefined proc % in gs_cet.ps (%.defaultbgrucrproc) cvn { pop 0 } def /.setdefaultbgucr { systemdict /setblackgeneration known { (%.defaultbgrucrproc) cvn load dup setblackgeneration setundercolorremoval } if } bind def /.useloresscreen { % - .useloresscreen <bool> % Compute min(|dpi x|,|dpi y|) as the definition of the resolution. 72 72 matrix defaultmatrix dtransform abs exch abs .min dup 150 lt //systemdict /DITHERPPI known not and } bind def /.gsgetdeviceprop % <device> <propname> gsgetdeviceprop <value> { 2 copy mark exch //null .dicttomark .getdeviceparams dup mark eq % if true, not found { pop dup /undefined signalerror } { 5 1 roll pop pop pop pop } ifelse } bind def % The following implementation uses LL2 extensions, but only in stopped % contexts so that with LL1, the .set??reshalftone will be used. % % - .getdefaulthalftone <halftonedict> true if default found % false /.getdefaulthalftone { % try the device to see if it has a default halftone { currentdevice /HalftoneDefault //.gsgetdeviceprop exec } //.internalstopped exec { pop pop //false } % no device property { dup type /dicttype eq { //true } { pop //false } ifelse } ifelse % stack: <halftonedict> true if default found % false not found dup not { % device did not provide a default, try Resource pop { /Default /Halftone /findresource .systemvar exec } //.internalstopped exec { pop pop //false } { //true } ifelse } if } bind def currentdict /.gsgetdeviceprop .forceundef /.setdefaulthalftone { //.getdefaulthalftone exec { sethalftone } { % default not found //.useloresscreen exec { .setloreshalftone } { .sethireshalftone pop } ifelse } ifelse } bind def /.setdefaultscreen { //.useloresscreen exec { .setloresscreen } { .sethiresscreen } ifelse //.setdefaultbgucr exec } bind def currentdict /.setdefaultbgucr .undef currentdict /.useloresscreen .undef % Rendering intent mapping for setcolorrendering1 and PDF interpreter /.renderingintentdict mark /Perceptual 0 /RelativeColorimetric 1 /Saturation 2 /AbsoluteColorimetric 3 .dicttomark readonly def % Load basic color support %% Replace 1 (gs_cspace.ps) (gs_cspace.ps) runlibfile (END BASIC COLOR) VMDEBUG % Load image support %% Replace 1 (gs_img.ps) (gs_img.ps) runlibfile (END IMAGE) VMDEBUG % Auxiliary procedures for generating file name templates. % Convert a path name into a string suitable for filenameforall % For example: (a\\b*?c) to (a\\\\b\\*\\?c) /.makepathtemplate { % str1 -- str2 dup length dup add string 0 % result string up to twice the size 0 1 4 index length 1 sub { 3 index exch get dup 92 eq { % \ -> \\ 2 index 2 index 92 put exch 1 add exch } if dup 42 eq { % * -> \* 2 index 2 index 92 put exch 1 add exch } if dup 63 eq { % ? -> \? 2 index 2 index 92 put exch 1 add exch } if 2 index 2 index 3 -1 roll put 1 add } for 0 exch getinterval exch pop } bind def % false <dir_list> <template> .generate_dir_list_templates_with_length <t1> ... <tN> % true <dir_list> <template> .generate_dir_list_templates_with_length <t1> <l1> ... <tN> <ln> % % Generates various valid templates combining a directory list with a given template. % With 'true' operand it also returns lengths of directory pathes. % % Example1 (DOS, Windows) : % false [(/gs/lib) (/gs/Resource/) (\gs8.00\Resource)] (*/*) --> % (/gs/lib/*/*) (/gs/Resource/*/*) (\\gs8.00\\Resource/*/*) % % Example2 (OpenVMS) : % false [(gs:[lib]) (gs:[Resource]) (gs800:[Resource)] (*]*) --> % ((gs:[lib.*]*) [gs:[Resource.*]*) ([gs800:[Resource.*]*) % /.generate_dir_list_templates_with_length { % [dl] (templ) % We need to convert paths into templates, % because it can include '\' on DOS. % In same time, the <template> must not convert, % because it is already a template. % Besides that, we cannot combine template using .file_name_combine, % because template syntax breaks the platform path syntax. % To resolve this, we first convert the <template> into % a fake filename, and combine it with path, % obtaining a correct separator. Then we replace % the fake file name with the given template. % % Create the fake file name : dup dup length string copy % b [dl] (templ) (ffn) (*) 0 get (?) 0 get (\\) 0 get (x) 0 get 0 0 % b [dl] (templ) (ffn) * ? \ x i j { 1 index 7 index length ge { exit } if 6 index 2 index get % b [dl] (templ) (ffn) * ? \ x i j c dup 7 index eq % b [dl] (templ) (ffn) * ? \ x i j c bool 1 index 7 index eq or { % *? pop 2 index } if % b [dl] (templ) (ffn) * ? \ x i j C dup 5 index eq { % \ 3 2 roll 1 add 3 1 roll % b [dl] (templ) (ffn) * ? \ x i' j C 2 index 8 index length ge { pop exit } if pop 6 index 2 index get % b [dl] (templ) (ffn) * ? \ x i' j C' } if 7 index 2 index 3 2 roll put % b [dl] (templ) (ffn) * ? \ x i' j 1 add exch 1 add exch % b [dl] (templ) (ffn) * ? \ x i'' j' } loop % b [dl] (templ) (ffn) * ? \ x i j 6 1 roll pop % b [dl] (templ) (ffn) j * ? \ x exch pop exch pop exch pop exch % b [dl] (templ) (ffn) x j { dup 3 index length ge { exit } if 3 copy exch put 1 add } loop pop pop % b [dl] (templ) (ffn) % An internal procedure : { % {} b [dl] (templ) (ffn) (dffn) dup length 2 index length sub % drop "ffn", remaining "ldffn" = length of the "directory" part exch % {} b [dl] (templ) (ffn) ldffn (dffn) //.makepathtemplate exec % {} b [dl] (templ) (ffn) ldffn (Dffn) dup % {} b [dl] (templ) (ffn) ldffn (Dffn) (Dffn) 4 index length dup % {} b [dl] (templ) (ffn) ldffn (Dffn) (Dffn) templL templL 2 index length % {} b [dl] (templ) (ffn) ldffn (Dffn) (Dffn) templL templL DffnL exch sub % {} b [dl] (templ) (ffn) ldffn (Dffn) (Dffn) templL i exch getinterval % {} b [dl] (templ) (ffn) ldffn (Dffn) (suffix) 4 index exch copy pop % {} b [dl] (templ) (ffn) ldffn (dt) 5 index { exch % {} b [dl] (templ) (ffn) (dt) ldffn 7 2 roll % (dt) ldffn {} b [dl] (templ) (ffn) } { exch pop % {} b [dl] (templ) (ffn) (dt) 6 1 roll % (dt) {} b [dl] (templ) (ffn) } ifelse } 5 1 roll % {} b [dl] (templ) (ffn) % Generate templates : dup .file_name_is_absolute { dup % {} b [dl] (templ) (ffn) (ffn) 5 index exec % (t1) {} b [dl] (templ) (ffn) } { 2 index { % ... {} b [dl] (templ) (ffn) (d) 1 index % ... {} b [dl] (templ) (ffn) (d) (ffn) //false .file_name_combine { % ... {} b [dl] (templ) (ffn) (dffn) 5 index exec % ... (t1) ?l1 {} b [dl] (templ) (ffn) } { % ... {} b [dl] (templ) (ffn) (d) (ffn) pop pop % ... {} b [dl] (templ) (ffn) } ifelse } forall } ifelse % (t1) ?l1 (t2) ?l2 ... (tN) ?ln {} b [dl] (templ) (ffn) pop pop pop pop pop % (t1) ?l1 (t2) ?l2 ... (tN) ?ln } .bind executeonly odef currentdict /.makepathtemplate .undef % <dir_list> <template> .generate_dir_list_templates <t1> ... <tN> % % Generates various valid templates combining a directory list with a given template. % It's the 'false' case of the function above. % /.generate_dir_list_templates { //false 3 1 roll //.generate_dir_list_templates_with_length } .bind executeonly odef % Load the initialization files for optional features. %% Replace 4 INITFILES systemdict /INITFILES known { INITFILES { <00> search { exch pop dup runlibfile VMDEBUG }{ dup runlibfile VMDEBUG exit } ifelse } .bind loop } if % If Level 2 (or higher) functionality is implemented, enable it now. /.setlanguagelevel where { pop 2 .setlanguagelevel % If the resource machinery is loaded, fix up some things now. /.fixresources where { pop .fixresources } if } if /ll3dict where { pop 3 .setlanguagelevel } if (END INITFILES) VMDEBUG % Create a null font. This is the initial font. 8 dict dup begin /FontMatrix [ 1 0 0 1 0 0 ] readonly def /FontType 3 def /FontName () def /Encoding StandardEncoding def /FontBBox { 0 0 0 0 } readonly def % executable is bogus, but customary ... /BuildChar { pop pop 0 0 setcharwidth } bind def /PaintType 0 def % shouldn't be needed! end /NullFont exch definefont setfont % Define NullFont as the font. /NullFont currentfont def % Load initial fonts from FONTPATH directories, Fontmap file, % and/or .getccfont as appropriate. .loadinitialfonts currentdict /.loadinitialfonts .undef % Remove NullFont from FontDirectory, so it can't be accessed by mistake. /undefinefont where { pop /NullFont undefinefont } { FontDirectory /NullFont .undef } ifelse (END FONTS) VMDEBUG % Restore the real definition of runlibfile. /runlibfile /.runlibfile load def currentdict /.runlibfile .undef % Bind all the operators defined as procedures. /.bindoperators % binds operators in currentdict { currentdict { dup type /operatortype eq { % This might be a real operator, so bind might cause a typecheck {.bind} //.internalstopped exec pop } if pop pop } forall } def DELAYBIND not { .bindoperators %% if not DELAYBIND, undef this now. Otherwise defer to .bindnow //systemdict /.bindoperators .undef } if % Establish a default environment. defaultdevice % The following line used to skip setting of page size and resolution if % NODISPLAY was selected. We think this was only to save time and memory, % and it is a bad idea because it prevents setting the resolution in this % situation, which pstoedit (among other programs) relies on. %DISPLAYING not { setdevice (%END DISPLAYING) .skipeof } if % If the paper size is not specifed and the device defaults to % letter or A4 paper, select the DEFAULTPAPERSIZE. systemdict /DEFAULTPAPERSIZE known not { % Use .defaultpapersize if it returns a known paper size .defaultpapersize { statusdict /.pagetypeprocs get 1 index known { systemdict exch /DEFAULTPAPERSIZE exch put } { QUIET { pop } { (Unknown .defaultpapersize: ) print ==only (.) = } ifelse } ifelse } if } if systemdict /DEFAULTPAPERSIZE known systemdict /PAPERSIZE known not and systemdict /DEVICEWIDTH known not and systemdict /DEVICEHEIGHT known not and systemdict /DEVICEWIDTHPOINTS known not and systemdict /DEVICEHEIGHTPOINTS known not and { defaultdevice mark /PageSize //null .dicttomark .getdeviceparams .dicttomark /PageSize get dup 0 get 0.5 add cvi 612 eq 1 index 1 get 0.5 add cvi 792 eq and 1 index 0 get 0.5 add cvi 595 eq 2 index 1 get 0.5 add cvi 842 eq and or exch pop { % the default paper size was letter, so replace it with DEFAULTPAPERSIZE /PAPERSIZE DEFAULTPAPERSIZE def } if } if systemdict /DEVICEWIDTH known systemdict /DEVICEHEIGHT known or systemdict /DEVICEWIDTHPOINTS known or systemdict /DEVICEHEIGHTPOINTS known or systemdict /DEVICEXRESOLUTION known or systemdict /DEVICEYRESOLUTION known or systemdict /PAPERSIZE known or not { (%END DEVICE) .skipeof } if % Let DEVICE{WIDTH,HEIGHT}[POINTS] override PAPERSIZE. systemdict /PAPERSIZE known systemdict /DEVICEWIDTH known not and systemdict /DEVICEHEIGHT known not and systemdict /DEVICEWIDTHPOINTS known not and systemdict /DEVICEHEIGHTPOINTS known not and { % Convert the paper size to device dimensions. statusdict /.pagetypeprocs get PAPERSIZE .knownget { dup 0 get /DEVICEWIDTHPOINTS exch def 1 get /DEVICEHEIGHTPOINTS exch def } { (Unknown paper size: ) print PAPERSIZE ==only (.) = } ifelse } if % Adjust the device parameters per the command line. % It is possible to specify resolution, pixel size, and page size; % since any two of these determine the third, conflicts are possible. % We simply pass them to .setdeviceparams and let it sort things out. mark /HWResolution //null /HWSize //null /PageSize //null .dicttomark .getdeviceparams .dicttomark begin mark % Check for resolution. /DEVICEXRESOLUTION where dup { exch pop HWResolution 0 DEVICEXRESOLUTION put } if /DEVICEYRESOLUTION where dup { exch pop HWResolution 1 DEVICEYRESOLUTION put } if or { /HWResolution HWResolution } if % Check for device sizes specified in pixels. /DEVICEWIDTH where dup { exch pop HWSize 0 DEVICEWIDTH put } if /DEVICEHEIGHT where dup { exch pop HWSize 1 DEVICEHEIGHT put } if or { /HWSize HWSize } if % Check for device sizes specified in points. /DEVICEWIDTHPOINTS where dup { exch pop PageSize 0 DEVICEWIDTHPOINTS put } if /DEVICEHEIGHTPOINTS where dup { exch pop PageSize 1 DEVICEHEIGHTPOINTS put } if or { /PageSize PageSize } if % Check whether any parameters were set. dup mark eq { pop defaultdevice } { defaultdevice putdeviceprops } ifelse end %END DEVICE % Set any device properties defined on the command line. % If BufferSpace is defined but not MaxBitmap, set MaxBitmap to BufferSpace. systemdict /BufferSpace known systemdict /MaxBitmap known not and { systemdict /MaxBitmap BufferSpace put } if dup getdeviceprops counttomark 2 idiv { systemdict 2 index known { pop dup load counttomark 2 roll } { pop pop } ifelse } repeat counttomark dup 0 ne { 2 add -1 roll putdeviceprops } { pop pop } ifelse % If the initial device parameters are invalid, the setdevice may fail. % Trap this and produce a reasonable error message. { setdevice } % does an erasepage INITDEBUG { exec //false } { //.internalstopped exec } ifelse { (%stderr) (w) file dup (**** Unable to open the initial device, quitting.\n) writestring flushfile 1 .quit } if % If the media size is fixed, update the current page device dictionary. FIXEDMEDIA dup { pop systemdict /.currentpagedevice known } if dup { pop .currentpagedevice exch pop } if not { (%END MEDIA) .skipeof } if currentpagedevice dup length dict .copydict dup /Policies % Stack: <pagedevice> <pagedevice> /Policies 1 index /InputAttributes 2 copy get dup length dict .copydict % Stack: <pagedevice> <pagedevice> /Policies <pagedevice> % /InputAttributes <inputattrs'> dup 0 2 copy get dup length dict .copydict % Stack: <pagedevice> <pagedevice> /Policies <pagedevice> % /InputAttributes <inputattrs'> <inputattrs'> 0 <attrs0'> dup /PageSize 7 index /PageSize get put % PageSize in 0 put % 0 in InputAttributes put % InputAttributes in pagedevice % Also change the page size policy so we don't get an error. % Stack: <pagedevice> <pagedevice> /Policies 2 copy get dup length dict .copydict % Stack: <pagedevice> <pagedevice> /Policies <policies'> dup /PageSize 7 put % PageSize in Policies put % Policies in pagedevice .setpagedevice %END MEDIA % Set up the interpreter context version of -dUSeCIEColor option % so that .getuseciecolor has the correct value (see gs_setpd.ps) /setpagedevice where { pop systemdict /UseCIEColor known { mark /UseCIEColor UseCIEColor /..StartupGlobal //true .dicttomark setpagedevice } if } if %END DISPLAYING (END DEVICE) VMDEBUG % Establish a default upper limit in the character cache, % namely, enough room for a 18-point character at the resolution % of the default device, or for a character consuming 1% of the % maximum cache size, whichever is larger. mark % Compute limit based on character size. 18 dup dtransform exch abs cvi 31 add 32 idiv 4 mul % X raster exch abs cvi mul % Y % Compute limit based on allocated space. cachestatus pop pop pop pop pop exch pop 0.01 mul cvi .max dup 10 idiv exch setcacheparams % Conditionally disable the character cache. NOCACHE { 0 setcachelimit } if (END CONFIG) VMDEBUG % Initialize graphics. .setdefaultscreen initgraphics % The interpreter relies on there being at least 2 entries % on the graphics stack. Establish the second one now. gsave % Define some control sequences as no-ops. % This is a hack to get around problems % in some common PostScript-generating applications. <04> cvn JOBSERVER { { { clear cleardictstack //false 0 .startnewjob } 2 .stop } bind } { { } } ifelse def <1b> cvn .actonuel % UEL is <esc>%-12345X and acts the same as ^D {systemdict (.forceinterp_exit) cvn known {//true} {//false} ifelse} {//false} ifelse { { currentfile (%-12345X) .peekstring pop (%-12345X) eq { currentfile .forceinterp_exit } if } } { {currentfile (%-12345X) .peekstring pop (%-12345X) eq <04> cvn load if} } ifelse bind def <1b45> cvn { } def % PJL reset prologue (ESC E) <1b451b> cvn <1b> cvn load def % PJL reset epilogue (ESC E + UEL) (\001M) cvn % TBCP initiator { currentfile /TBCPDecode filter cvx exec } bind def /@PJL % H-P job control { % Windows 2000 driver includes PJL into %%BeginFeature block. % Identify this from the pattern on the stack: countdictstack lucas mark % and fail the feature request. count 3 ge { dup mark eq { 2 index countdictstack eq { 1 index /lucas where { /lucas get eq } { pop //false } ifelse { stop } if } if } if } if currentfile //=string readline pop pop } bind def % Install the EPS handler if needed systemdict /EPSBoundingBoxInit known { EPSBoundingBoxInit } if systemdict /EPSBoundingBoxInit .forceundef %% ---------------- SAFER stuff BEGIN -------------------%% % If we want a "safer" system, disable some obvious ways to cause havoc. .currentglobal //true .setglobal /SAFETY 2 dict dup /safe //false put dup /tempfiles 10 dict noaccess put readonly def .setglobal /SAFERUndefinePostScriptOperators { [ % Used by our own test suite files /.setdotlength % Bug687720.ps /.sort /.setdebug /.mementolistnewblocks /getenv /unread ] {systemdict exch .forceundef} forall //systemdict /SAFERUndefinePostScriptOperators .forceundef } .bind executeonly def % must be bound and hidden for .forceundef /tempfilepaths [ (TMPDIR) getenv not { (TEMP) getenv not { (TMP) getenv not { (/temp) (/tmp) } if } if } if ] def /.lockfileaccess { .currentpathcontrolstate { //QUIET not { (\n **** WARNING: .lockfileaccess or .setsafe called ****\n) print ( **** when file access controls are already active ****\n) print flush } if } { [ //tempfilepaths (*) .generate_dir_list_templates /FONTPATH .systemvar (*) .generate_dir_list_templates /level2dict where { pop % Default resources : [ currentsystemparams /GenericResourceDir get] (*) .generate_dir_list_templates } if /LIBPATH .systemvar (*) .generate_dir_list_templates currentuserparams /ICCProfilesDir known { [currentuserparams /ICCProfilesDir get] (*) .generate_dir_list_templates } if ] {/PermitFileReading exch .addcontrolpath} forall [ //tempfilepaths (*) .generate_dir_list_templates ] {/PermitFileWriting exch .addcontrolpath} forall [ //tempfilepaths (*) .generate_dir_list_templates ] {/PermitFileControl exch .addcontrolpath} forall .activatepathcontrol } ifelse } bind def /.locksafe_userparams { SAFETY /safe get not { << /PermitFileReading [ currentuserparams /PermitFileReading get aload pop //tempfilepaths (*) .generate_dir_list_templates /FONTPATH .systemvar (*) .generate_dir_list_templates % Library files : /LIBPATH .systemvar (*) .generate_dir_list_templates % Resource files on OpenVMS requires a separate template (gs:[dir.*]*) % because the (gs:[dir]*) doesn't cover them. /LIBPATH .systemvar (*) .file_name_separator (*) concatstrings concatstrings .generate_dir_list_templates .languagelevel 2 ge { % Default resources : [ currentsystemparams /GenericResourceDir get] (*) .generate_dir_list_templates % Default resources (OpenVMS, see comment above.) : [ currentsystemparams /GenericResourceDir get] (*) .file_name_separator (*) concatstrings concatstrings .generate_dir_list_templates } if currentuserparams /ICCProfilesDir known { [currentuserparams /ICCProfilesDir get] (*) .generate_dir_list_templates } if ] /PermitFileWriting [ currentuserparams /PermitFileWriting get aload pop //tempfilepaths (*) .generate_dir_list_templates ] /PermitFileControl [ currentuserparams /PermitFileControl get aload pop //tempfilepaths (*) .generate_dir_list_templates ] /LockFilePermissions //true >> setuserparams } if } .bind executeonly def currentdict /tempfilepaths undef %% --- These are documented extensions --- /.locksafe { //.locksafe_userparams exec //systemdict /getenv {pop //false} .forceput % setpagedevice has the side effect of clearing the page, but % we will just document that. Using setpagedevice keeps the device % properties and pagedevice .LockSafetyParams in agreement even % after a restore that changes the value to false. currentglobal currentpagedevice gcheck setglobal % use correct VM space << /.LockSafetyParams //true >> setpagedevice setglobal //SAFETY /safe //true .forceput % overrides readonly } .bind executeonly odef /.setsafe { OLDSAFER { SAFETY /safe get not { << /PermitFileReading [ ] /PermitFileWriting [ ] /PermitFileControl [ ] >> setuserparams } if .locksafe } { //.lockfileaccess exec DELAYBIND not { //systemdict /SAFERUndefinePostScriptOperators .knownget {exec} if } if } ifelse } .bind executeonly odef %% --- End documented extensions --- % This is only used during startup. Its required so that % we can detect in setpagdevice that we are in fact in startup % and allocate a *global* instead of local VM. We need it to be % global to satisfy Display PostScript (see start of /setpagdevice % in gs_setpd.ps) % /.locksafeglobal { //.locksafe_userparams exec systemdict /getenv {pop //false} put % setpagedevice has the side effect of clearing the page, but % we will just document that. Using setpagedevice keeps the device % properties and pagedevice .LockSafetyParams in agreement even % after a restore that changes the value to false. currentglobal currentpagedevice gcheck setglobal % use correct VM space << /.LockSafetyParams //true /..StartupGlobal //true >> setpagedevice setglobal //SAFETY /safe //true .forceput % overrides readonly } .bind def % See /.locksafeglobal above. % /.setsafeglobal { OLDSAFER { SAFETY /safe get not { << /PermitFileReading [ ] /PermitFileWriting [ ] /PermitFileControl [ ] >> setuserparams } if //.locksafeglobal exec } { //.lockfileaccess exec DELAYBIND not { //systemdict /SAFERUndefinePostScriptOperators .knownget {exec} if } if } ifelse } .bind executeonly odef % If we are running in SAFER mode, lock things down SAFER { .setsafeglobal } if currentdict /.locksafe_userparams .undef currentdict /.setsafeglobal .undef currentdict /.locksafeglobal .undef %% ---------------- SAFER stuff END -------------------%% /UndefinePostScriptOperators { % This list is of operators which no longer appear to be used, and which we do not believe % to have any real use. For now we will undefine the operstors so they cannot easily be used % but can be easily restored (just delete the name from the list in the array). In future % we may remove the operator and the code implementation entirely. [ /.bitadd /.charboxpath /.cond /.runandhide /.popdevicefilter /.execfile /.filenamesplit /.file_name_parent /.setdefaultmatrix /.updatematrices /.isprocfilter /.unread /.psstringencode /.buildsampledfunction /.isencapfunction /.currentaccuratecurves /.currentcurvejoin /.currentdashadapt /.currentdotlength /.currentlimitclamp /.dotorientation /.setaccuratecurves /.setcurvejoin /.setdashadapt /.setdotorientation /.setlimitclamp /.currentscreenlevels /.dashpath /.pathbbox /.identeq /.identne /.tokenexec /.forgetsave /.pantonecallback % Used by our own test suite files %/.setdotlength % Bug687720.ps ] {systemdict exch .forceundef} forall % This list of operators are used internally by various parts of the Ghostscript startup code. % Since each operator is a potential security vulnerability, and any operator listed here % is not required once the initialisation is complete and functions are bound, we undefine % the ones that aren't needed at runtime. [ /.callinstall /.callbeginpage /.callendpage /.currentstackprotect /.setstackprotect /.errorexec /.finderrorobject /.installsystemnames /.bosobject /.fontbbox /.type1execchar /.type2execchar /.type42execchar /.setweightvector /.getuseciecolor /processcolors /.includecolorspace /.execn /.instopped /.stop /.stopped /.setcolorrendering /.setdevicecolorrendering /.buildcolorrendering1 /.builddevicecolorrendering1 /.TransformPQR_scale_WB0 /.TransformPQR_scale_WB1 /.TransformPQR_scale_WB2 /.currentoverprintmode /.copydevice2 /.devicename /.doneshowpage /.getbitsrect /.getdevice /.getdefaultdevice /.getdeviceparams /.gethardwareparams /makewordimagedevice /.outputpage /.putdeviceparams /.setdevice /.currentshowpagecount /.setpagedevice /.currentpagedevice /.knownundef /.setmaxlength /.rectappend /.initialize_dsc_parser /.parse_dsc_comments /.fillCIDMap /.fillIdentityCIDMap /.buildcmap /.filenamelistseparator /.libfile /.getfilename /.file_name_combine /.file_name_is_absolute /.file_name_separator /.file_name_directory_separator /.file_name_current /.filename /.peekstring /.writecvp /.subfiledecode /.setupUnicodeDecoder /.jbig2makeglobalctx /.registerfont /.parsecff /.getshowoperator /.getnativefonts /.beginform /.endform /.get_form_id /.repeatform /.reusablestream /.rsdparams /.buildfunction /.sethpglpathmode /.currenthpglpathmode /.currenthalftone /.sethalftone5 /.image1 /.imagemask1 /.image3 /.image4 /.getiodevice /.getdevparms /.putdevparams /.bbox_transform /.matchmedia /.matchpagesize /.defaultpapersize /.oserrno /.setoserrno /.oserrorstring /.getCPSImode /.getscanconverter /.setscanconverter /.type1encrypt /.type1decrypt/.languagelevel /.setlanguagelevel /.eqproc /.fillpage /.saslprep /.shfill /.argindex /.bytestring /.namestring /.stringbreak /.stringmatch /.globalvmarray /.globalvmdict /.globalvmpackedarray /.globalvmstring /.localvmarray /.localvmdict /.localvmpackedarray /.localvmstring /.systemvmarray /.systemvmdict /.systemvmpackedarray /.systemvmstring /.systemvmfile /.systemvmlibfile /.systemvmSFD /.settrapparams /.currentsystemparams /.currentuserparams /.getsystemparam /.getuserparam /.setsystemparams /.setuserparams /.checkpassword /.locale_to_utf8 /.currentglobal /.gcheck /.imagepath /.currentoutputdevice /.type /.writecvs /.setSMask /.currentSMask /.needinput /.countexecstack /.execstack /filterdict /.cidfonttypes /.colorrenderingtypes /.formtypes /.halftonetypes /.imagetypes /.imagemasktypes /.patterntypes /.shadingtypes /.wheredict /.renderingintentdict /.currentmatrix /.setmatrix /.setlinecap /.setlinejoin /.sizeimagebox /.systemvmcheck /.forceinterp_exit /.actonuel /.init_otto_font_file /.composefontdict /.type1build /.origdefinefont /.origundefinefont /.origfindfont /.buildnativefontmap /.completefont /.definefakefonts /.fontnameproperties /.growfontdict /.substitutefont /.substitutefontname /.FontDirectory /.charkeys /.makesfnts /.pickcmap /.loadttcidfont /.loadpdfttfont /obind /odef /.packtomark /.putdeviceprops /.growdict /.growdictlength /.userdict /.uservar /.getdefaulthalftone /.registererror /.PurgeDict /.runresource /.numicc_components /.set_outputintent /.internalstopped /.generate_dir_list_templates /.generate_dir_list_templates_with_length /.type11mapcid /.type9mapcid /.clearerror /.beginpage /.endpage /.getpath /.confirm /.confirmread % Used by a free user in the Library of Congress. Apparently this is used to % draw a partial page, which is then filled in by the results of a barcode % scanner and SQL database lookup. Its not clear to us exactly why this needs to be % done as a partial page, but its easiest to restore the operator, and it seems like % its a reasonably safe operator to restore, for the *very* few devices on which % it will have any effect. Currently this uses the 'sync_output' device method % to transfer the partial page, in future we may use a spec_op instead. %/flushpage % Used by our own test suite files %/.fileposition %image-qa.ps % Either our code uses these in ways which mean they can't be undefined, or they are used directly by % test files/utilities, or engineers expressed a desire to keep them visible. % %/currentdevice /.sort /.buildfont0 /.buildfont1 /.buildfont2 /.buildfont3 /.buildfont4 /.buildfont9 /.buildfont10 /.buildfont11 %/.buildfont32 /.buildfont42 /.swapcolors %/currentdevice /.quit /.setuseciecolor /.needinput /.setoverprintmode /.special_op /.dicttomark /.knownget %/.FAPIBuildGlyph /.FAPIBuildChar /.FAPIBuildGlyph9 %/.tempfile /.max /.min /.setglobal %/.setdebug /.mementolistnewblocks /getenv ] {systemdict exch .forceundef} forall % level 2 operators, undefine from both systemdict and level2dict [ /.execform1 /.getdevparams /.setuserparams2 /.startjob /.checkFilePermitparams /.copyparam /.setdevicecolorrendering1 /.buildpattern1 /.findcategory /.execinstall /.findfontop % Couldn't figure out how to do these yet % /.checkparamtype % /.startnewjob ] dup {level2dict exch .forceundef} forall {systemdict exch .forceundef} forall % undef stuff from statusdict [ % /.setpagesize ] {statusdict exch .forceundef} forall //systemdict /UndefinePostScriptOperators .forceundef } .bind executeonly def % must be bound and hidden for .forceundef % If we delayed binding, make it possible to do it later. /.bindnow { currentuserparams /IdiomRecognition .knownget { 1 dict dup /IdiomRecognition //false put setuserparams } if //systemdict begin .bindoperators end % Temporarily disable the typecheck error. errordict /typecheck 2 copy get errordict /typecheck { pop } put % pop the command 0 1 .delaycount 1 sub { .delaybind exch get .bind pop } for //systemdict /.delaybind {} .forceput % reclaim the space //systemdict /.bindnow .forceundef % ditto .applyundefinternalnames put SAFER { //systemdict /SAFERUndefinePostScriptOperators get exec } if //systemdict /UndefinePostScriptOperators get exec //systemdict /.forcecopynew .forceundef % remove temptation //systemdict /.forceput .forceundef % ditto //systemdict /.undef .forceundef % ditto //systemdict /.bindoperators .forceundef //systemdict /.forceundef .forceundef % ditto //systemdict /.undefinternalnames .forceundef //systemdict /.applyundefinternalnames .forceundef //systemdict /.undefinternalnameslist .forceundef currentuserparams /IdiomRecognition known { 1 dict dup /IdiomRecognition 4 -1 roll put setuserparams } if } .bind def % Turn off array packing, since some PostScript code assumes that % procedures are writable. //false setpacking (END INIT) VMDEBUG /.currentuserparams where { pop % Remove real user params from psuserparams. mark .currentuserparams counttomark 2 idiv { pop psuserparams exch undef } repeat pop % Update the copy of the user parameters. mark .currentuserparams counttomark 2 idiv { userparams 3 1 roll .forceput % userparams is read-only } executeonly repeat pop % Turn on idiom recognition, if available. currentuserparams /IdiomRecognition known { /IdiomRecognition //true .definepsuserparam } if psuserparams readonly pop systemdict /.definepsuserparam undef % Save a copy of userparams for use with save/restore % (and, if implemented, context switching). .currentglobal //false .setglobal mark userparams { } forall .dicttomark readonly currentdict exch /userparams exch .forceput % systemdict is read-only .setglobal } executeonly if /.currentsystemparams where { pop % Remove real system params from pssystemparams. mark .currentsystemparams counttomark 2 idiv { pop pssystemparams exch .forceundef } executeonly repeat pop } if % Set up AlignToPixels : /AlignToPixels where { mark /AlignToPixels 2 index /AlignToPixels get .dicttomark setuserparams /AlignToPixels undef } if % Set up GridFitTT : /GridFitTT where { mark /GridFitTT 2 index /GridFitTT get .dicttomark setuserparams /GridFitTT undef } if % Establish local VM as the default. //false /setglobal where { pop setglobal } { .setglobal } ifelse $error /.nosetlocal //false put (END GLOBAL) VMDEBUG % Add the fake fonts to LocalFontDirectory. //.definefakefonts exec % current VM is local % Execute scheduled inits : 1183615869 internaldict /.execute_scheduled_inits get exec currentdict /.schedule_init undef %currentdict /.execute_scheduled_inits undef %currentdict /.delayed_init_queue undef % Make global and local FontDirectory read-only. FontDirectory readonly pop /GlobalFontDirectory where { pop GlobalFontDirectory readonly pop } if % If we are using DELAYBIND we have to defer the undefinition % until .bindnow. DELAYBIND not { //systemdict /UndefinePostScriptOperators get exec } if end % Clean up VM, and enable GC. Use .vmreclaim to force the GC. /vmreclaim where { pop //systemdict /NOGC get not { 2 .vmreclaim 0 vmreclaim } if } if systemdict /.vmreclaim .undef level2dict /.vmreclaim .undef % Do this before systemdict is locked (see below for additional CETMODE setup using gs_cet.ps) systemdict /CETMODE .knownget { { (gs_cet.ps) runlibfile } if } if systemdict /.makeoperator .undef % must be after gs_cet.ps systemdict /.setCPSImode .undef % must be after gs_cet.ps DELAYBIND not { systemdict /.bindnow .undef % We only need this for DELAYBIND systemdict /.forcecopynew .undef % remove temptation systemdict /.forceput .undef % ditto systemdict /.forceundef .undef % ditto systemdict /.undefinternalnames .undef systemdict /.applyundefinternalnames .undef systemdict /.undefinternalnameslist .undef } if % Can't remove this one until the last minute :-) DELAYBIND not { systemdict /.undef .undef } if WRITESYSTEMDICT { SAFER { (\n *** WARNING - you have selected SAFER, indicating you want Ghostscript\n) print ( to execute in a safer environment, but at the same time\n) print ( have selected WRITESYSTEMDICT. Unless you use this option with\n) print ( care and specifically, remember to execute code like:\n) print ( "systemdict readonly pop"\n) print ( it is possible that malicious code may be able to evade the\n) print ( limited security offered by the SAFER option.\n) print flush }if } { systemdict readonly pop } ifelse (END GC) VMDEBUG % The Adobe AGM_Core used by Illustrator 9 has some code that breaks % if the 'product' is not (Adobe PostScript Parser). A bug has been % submitted to Adobe since this also fails with Acrobat Distiller. % As a temporary work around, the following HACK will work for % devices without spot color support. Once Ghostscript can % support DeviceN and spot color separations this will need to % be 'true' in some cases. userdict /AGM_preserve_spots //false put % The interpreter will run the initial procedure (start). gs_cidfm.ps 0000644 00000017605 15030647507 0006703 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % Redefine CIDFont category with cidfmap . languagelevel 2 .setlanguagelevel 4 dict begin /CategoryName /CIDFont def /MapFileName (cidfmap) def /IsMyRecord % <raw_record> -> <raw_record> bool { % Only for client's needs. dup type /stringtype eq exch dup type /nametype eq 3 -1 roll or } bind def /RecordVirtualMethods 3 dict begin /MakeInstance % <Name> <record> MakeInstance <Name> <Instance> <size> { % We know that currentdict is the category. /Substitute get dup type /stringtype eq { (r) file dup cvx exec closefile dup } if FindResource % /Name <<CIDFont>> dup length dict copy % /Name <<CIDFont>> 1 index ResourceStatus pop exch pop % /Name <<CIDFont>> size } bind def /GetFilePath % <scratch> <Name> <record> GetFilePath <filepath> { % We know that currentdict is the category. exch pop /Substitute get dup type /stringtype eq not { exch ResourceFileName } if } bind def /GetSize % <Name> <record> GetSize <size> { % We know that currentdict is the category. dup /Substitute get dup type /stringtype eq { % The simplest solution is to instantiate the resource pop //MakeInstance exec 3 1 roll pop pop } { exch pop ResourceStatus { exch pop exch pop } { /undefinedresource signalerror } ifelse }ifelse } bind def /GetCSI % <record> GetCSI null % <record> GetCSI dict { % We know that currentdict is the category. RESMPDEBUG { (cidfm GetCSI beg ) = } if dup /Substitute get dup type /stringtype eq { pop dup /Name get exch //MakeInstance exec pop exch pop /CIDSystemInfo get } { exch pop % /Name GetCIDSystemInfoFromMap } ifelse RESMPDEBUG { (cidfm GetCSI end ) print dup = } if } bind def /IsActive % <record> IsActive <bool> { pop //true } bind def currentdict end def % This is the default definition of our fallback CIDFont /DefaultCIDFallBack << /Path systemdict /CIDFSubstPath .knownget { (/) concatstrings } { (CIDFSUBSTPATH) getenv { (/) concatstrings } { currentsystemparams /GenericResourceDir get (CIDFSubst/) concatstrings } ifelse } ifelse systemdict /CIDFSubstFont .knownget not { (CIDFSUBSTFONT) getenv not { (DroidSansFallback.ttf) } if } if % If CIDFSubstFont looks like a path/file (rather than just file) % use it without the CIDFSubstPath string dup .file_name_directory_separator rsearch {pop pop pop exch pop} {pop concatstrings} ifelse % The CSI data just has to be valid, the substition machinery will % generally overwrite it with appropriate values for the missing font. /CSI [(Identity) 0] /RecordVirtualMethods //RecordVirtualMethods /FileType /TrueType (CIDFSUBSTFONTID) getenv { /SubfontID exch cvi } if >> def % <dir.../base.extn> .basename <dir> /.splitdirname { (/) rsearch { //true } { (\\) rsearch } ifelse {exch concatstrings exch pop //true}{//false} ifelse } bind def % <file> .addcidfmappath - /.addcidfmpermitpath { .filename { //.splitdirname exec {dup def} if } if } bind def /VerifyMap % <raw_map> VerifyMap - { % This is where we insert the default fallback into the map % checking first to see if there is a user specified alternative dup /CIDFallBack known not{ //DefaultCIDFallBack dup /Path get status { pop pop pop pop /CIDFallBack exch 2 index 3 1 roll put } { pop }ifelse } if % Remove any mappings for which we cannot find the font file dup length dict begin dup { % if we have a name1->name2 mapping, follow the "trail", % so if the name2 mapping is known in the .map dict, retrieve % that map value and loop round until we either reach a map % which references a TTF (i.e. a dictionary record) or we have % a name not known in the .map, in which case we have to resort % to the normal Postscript "resourcestatus". { dup type /nametype eq { dup 3 index exch .knownget { exch pop } { /CIDFont resourcestatus { pop pop pop } { 2 index exch .undef } ifelse exit } ifelse } { dup type /dicttype eq { /Path .knownget { .libfile { dup //.addcidfmpermitpath exec closefile pop} { {(r) file} //.internalstopped exec {pop pop 2 index exch .undef} {dup //.addcidfmpermitpath exec closefile pop} ifelse } ifelse } {2 index exch .undef} ifelse exit } if } ifelse } loop } forall currentdict end {exch pop /PermitFileReading exch .addcontrolpath} forall % Checks for vicious substitution cycles. dup length dict copy % <<map>> dup length dict % <<map>> <<temp>> { % Choose a random record : //true 2 index { % <<map>> <<temp>> true /Name /Subs 3 2 roll pop //false exit % <<map>> <<temp>> /Name /Subs false } forall { exit % <<map>> <<temp>> } if % <<map>> <<temp>> /Name /Subs % Move the substitution chain to <<temp>>, checking for a cycle : 3 index 2 index undef % <<map>> <<temp>> /Name /Subs exch 2 index exch 0 put % <<map>> <<temp>> /Subs { //IsMyRecord exec not { % Not a substitution, the chain terminates. pop exit % <<map>> <<temp>> } if % <<map>> <<temp>> /Subs 1 index 1 index known { (Vicious substitution cycle in map file with the entry ) print =string cvs print ( .) = /VerifyMap cvx /undefinedresource signalerror } if % <<map>> <<temp>> /Subs 1 index 1 index 0 put dup 3 index exch .knownget not { % <<map>> <<temp>> /Subs % No more substitutions, the chain terminates. pop exit % <<map>> <<temp>> } if % <<map>> <<temp>> /Subs /Subs1 exch % <<map>> <<temp>> /Subs1 /Subs 3 index exch undef % <<map>> <<temp>> /Subs1 } loop % Not cycled, now purge the <<temp>> : { % Choose a random record : //true 1 index { % <<map>> <<temp>> true /Name /Subs 3 2 roll pop //false exit % <<map>> <<temp>> /Name /Subs false } forall { exit % <<map>> <<temp>> } if % <<map>> <<temp>> /Name /Subs % Remove it : pop 1 index exch undef % <<map>> <<temp>> } loop } loop pop pop } bind def currentdict /.splitdirname undef currentdict /.addcidfmpermitpath undef /PreprocessRecord % <map> <Name> <raw_record> PreprocessRecord <map> <Name> <record> <bool> { //IsMyRecord exec { 1 dict begin /Substitute exch def dup /Name exch def /RecordVirtualMethods //RecordVirtualMethods def currentdict end //true } { //false } ifelse } bind def currentdict end /MappedCategoryRedefiner /ProcSet findresource /Redefine get exec .setlanguagelevel xlatmap 0000644 00000003347 15030647507 0006153 0 ustar 00 % xlatmap - the map of translation tables for various kinds of fonts. % % It specifies Decoding resources to be used with FAPI-handled fonts. % If a font contains multiple character mapping tables, this gives % priorities for choosing a specific table from the font according to % the order of entries of this map. % This file is intended to be customized by users. Please keep the % obvious format of this file. Strings and names must not be empty % and must not contain null ('\0') characters. % The map contains entries for each kind of font being handled by % any font rendering plugin. The key of an entry is the font type % and the value is array of pairs. % The first element of pair is a string which encodes identifier of % character mapping table. The format of the first element depends % on the font type, and should be recognized by the font rendering % plugins. The second element is name of the Decoding resource. If % that resource is not available, definefont will fail. Note that % currently we supply insufficient decoding resources, as well as % insufficient entries in this map. /TrueType [ % Each entry is pair : % a string PlatformID.SpecificID and a name of Decoding resource. (3.0) /Symbol % Symbol (3.1) /Unicode % Unicode (3.2) /ShiftJIS % Japanese (3.3) /PRC % Simplified Chinese, GB2312 (3.4) /Big5 % Traditional Chinese (3.5) /Wansung % Korean (3.6) /Johab % Korean (3.10) /UCS-4 % UCS-4 % todo : add more entries ] /PostScript [ % Since PostScript fonts were designed especially for PostScript, (*) /Unicode % fixme : other charsets ] /Intellifont [ (*) /FCO_Unicode % fixme : other charsets ] /Microtype [ (*) /FCO_Unicode % FCOfontmap may may overwrite this for a specific font. ] gs_statd.ps 0000644 00000042703 15030647507 0006735 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % This file provides statusdict, serverdict, and assorted LaserWriter % operators, mostly for the benefit of poorly designed PostScript programs % that 'know' they are running on a LaserWriter. systemdict begin % We make statusdict a little larger for Level 2 stuff. % Note that it must be allocated in local VM. .currentglobal //false .setglobal currentdict /statusdict 91 dict .forceput % statusdict is local, sys'dict global % To support the Level 2 job control features, % serverdict must also be in local VM. currentdict /serverdict 10 dict .forceput % serverdict is local, sys'dict global .setglobal end statusdict begin /.setpagesize { 2 copy 2 array astore /PageSize exch mark 3 1 roll .dicttomark { setpagedevice } stopped { pop % the setpagedevice dict /setpagesize $error /errorname get signalerror } { pop pop % success -- pop the arguments } ifelse } bind def % Keep the table of named paper sizes as procedures. Reuse them later % as compatibility operators. /.pagetypeprocs 70 dict begin % Define various paper formats. The Adobe documentation defines only these: % 11x17, a3, a4, a4small, b5, ledger, legal, letter, lettersmall, note. % These procedures are also accessed as data structures during initialization, % so the page dimensions must be the first two elements of the procedure. % Page sizes defined by Adobe documentation % Note: these executable arrays should all begin with two % integers which are the width and height (see gs_setpd.ps). /11x17 {792 1224 //.setpagesize stopped { pop pop /11x17 $error /errorname get signalerror } if } bind def % 11x17 portrait /a3 {842 1191 //.setpagesize stopped { pop pop /a3 $error /errorname get signalerror } if } bind def /a4 {595 842 //.setpagesize stopped { pop pop /a4 $error /errorname get signalerror } if } bind def % a4small should be a4 with an ImagingBBox of [25 25 570 817]. /a4small /a4 load def % b5 see below. /ledger {1224 792 //.setpagesize stopped { pop pop /ledger $error /errorname get signalerror } if } bind def % 11x17 landscape /legal {612 1008 //.setpagesize stopped { pop pop /legal $error /errorname get signalerror } if } bind def /letter {612 792 //.setpagesize stopped { pop pop /letter $error /errorname get signalerror } if } bind def % lettersmall should be letter with an ImagingBBox of [25 25 587 767]. /lettersmall /letter load def % note should be letter (or some other size) with the ImagingBBox % shrunk by 25 units on all 4 sides. /note /letter load def % End of Adobe-defined page sizes % Other page sizes % ISO standard paper sizes /a0 {2384 3370 //.setpagesize stopped { pop pop /a0 $error /errorname get signalerror } if } bind def /a1 {1684 2384 //.setpagesize stopped { pop pop /a1 $error /errorname get signalerror } if } bind def /a2 {1191 1684 //.setpagesize stopped { pop pop /a2 $error /errorname get signalerror } if } bind def % /a3 {842 1191 //.setpagesize stopped { pop pop /a3 $error /errorname get signalerror } if } bind def % defined by Adobe % /a4 {595 842 //.setpagesize stopped { pop pop /a4 $error /errorname get signalerror } if } bind def % defined by Adobe /a5 {420 595 //.setpagesize stopped { pop pop /a5 $error /errorname get signalerror } if } bind def /a6 {297 420 //.setpagesize stopped { pop pop /a6 $error /errorname get signalerror } if } bind def /a7 {210 297 //.setpagesize stopped { pop pop /a7 $error /errorname get signalerror } if } bind def /a8 {148 210 //.setpagesize stopped { pop pop /a8 $error /errorname get signalerror } if } bind def /a9 {105 148 //.setpagesize stopped { pop pop /a9 $error /errorname get signalerror } if } bind def /a10 {73 105 //.setpagesize stopped { pop pop /a10 $error /errorname get signalerror } if } bind def % ISO and JIS B sizes are different.... /isob0 {2835 4008 //.setpagesize stopped { pop pop /isob0 $error /errorname get signalerror } if } bind def /b0 /isob0 load def /isob1 {2004 2835 //.setpagesize stopped { pop pop /isob1 $error /errorname get signalerror } if } bind def /b1 /isob1 load def /isob2 {1417 2004 //.setpagesize stopped { pop pop /isob2 $error /errorname get signalerror } if } bind def /b2 /isob2 load def /isob3 {1001 1417 //.setpagesize stopped { pop pop /isob3 $error /errorname get signalerror } if } bind def /b3 /isob3 load def /isob4 {709 1001 //.setpagesize stopped { pop pop /isob4 $error /errorname get signalerror } if } bind def /b4 /isob4 load def /isob5 {499 709 //.setpagesize stopped { pop pop /isob5 $error /errorname get signalerror } if } bind def /b5 /isob5 load def /isob6 {354 499 //.setpagesize stopped { pop pop /isob6 $error /errorname get signalerror } if } bind def /b6 /isob6 load def /jisb0 {2920 4127 //.setpagesize stopped { pop pop /jisb0 $error /errorname get signalerror } if } bind def /jisb1 {2064 2920 //.setpagesize stopped { pop pop /jisb1 $error /errorname get signalerror } if } bind def /jisb2 {1460 2064 //.setpagesize stopped { pop pop /jisb2 $error /errorname get signalerror } if } bind def /jisb3 {1032 1460 //.setpagesize stopped { pop pop /jisb3 $error /errorname get signalerror } if } bind def /jisb4 {729 1032 //.setpagesize stopped { pop pop /jisb4 $error /errorname get signalerror } if } bind def /jisb5 {516 729 //.setpagesize stopped { pop pop /jisb5 $error /errorname get signalerror } if } bind def /jisb6 {363 516 //.setpagesize stopped { pop pop /jisb6 $error /errorname get signalerror } if } bind def /c0 {2599 3677 //.setpagesize stopped { pop pop /c0 $error /errorname get signalerror } if } bind def /c1 {1837 2599 //.setpagesize stopped { pop pop /c1 $error /errorname get signalerror } if } bind def /c2 {1298 1837 //.setpagesize stopped { pop pop /c2 $error /errorname get signalerror } if } bind def /c3 {918 1298 //.setpagesize stopped { pop pop /c3 $error /errorname get signalerror } if } bind def /c4 {649 918 //.setpagesize stopped { pop pop /c4 $error /errorname get signalerror } if } bind def /c5 {459 649 //.setpagesize stopped { pop pop /c5 $error /errorname get signalerror } if } bind def /c6 {323 459 //.setpagesize stopped { pop pop /c6 $error /errorname get signalerror } if } bind def % U.S. CAD standard paper sizes /archE {2592 3456 //.setpagesize stopped { pop pop /archE $error /errorname get signalerror } if } bind def /archD {1728 2592 //.setpagesize stopped { pop pop /archD $error /errorname get signalerror } if } bind def /archC {1296 1728 //.setpagesize stopped { pop pop /archC $error /errorname get signalerror } if } bind def /archB {864 1296 //.setpagesize stopped { pop pop /archB $error /errorname get signalerror } if } bind def /archA {648 864 //.setpagesize stopped { pop pop /archA $error /errorname get signalerror } if } bind def % Other paper sizes /flsa {612 936 //.setpagesize stopped { pop pop /flsa $error /errorname get signalerror } if } bind def % U.S. foolscap /flse {612 936 //.setpagesize stopped { pop pop /flse $error /errorname get signalerror } if } bind def % European foolscap /halfletter {396 612 //.setpagesize stopped { pop pop /halfletter $error /errorname get signalerror } if } bind def % minimum of a4 and letter (a4 width, letter length) /pa4 {595 792 //.setpagesize stopped { pop pop /pa4 $error /errorname get signalerror } if } bind def % Japanese postcard size, 100mm x 148mm /hagaki {283 420 //.setpagesize stopped { pop pop /hagaki $error /errorname get signalerror } if } bind def % U.S. ANSI/ASME Y14.1 paper sizes /ANSI_A //letter def /ANSI_B //11x17 def /tabloid //11x17 def /ANSI_C {1224 1585 //.setpagesize stopped { pop pop /ANSI_C $error /errorname get signalerror } if } bind def /ANSI_D {1585 2448 //.setpagesize stopped { pop pop /ANSI_D $error /errorname get signalerror } if } bind def /ANSI_E {2448 3168 //.setpagesize stopped { pop pop /ANSI_E $error /errorname get signalerror } if } bind def /ANSI_F {2016 2880 //.setpagesize stopped { pop pop /ANSI_F $error /errorname get signalerror } if } bind def %END SIZES currentdict end userdict begin dup { def } forall end % reuse! readonly def % Define the pagetype values for the known page formats. % This array is now used for deterministic enumeration of .pagetypeprocs /.pagetypenames [ .pagetypeprocs { pop } bind forall ] { .namestring exch .namestring gt } bind .sort readonly def %%%%%% The following items were suggested by a user as useful. % Permanent definitions /ramsize 4194304 def /hardwareiomode 0 def /sethardwareiomode {pop} bind def /softwareiomode 0 def /setsoftwareiomode {pop} bind def /dosysstart //false def /setdosysstart {pop} bind def /allowjobreset //true def /setallowjobreset {pop} bind def /defaultpaperfamily 0 def /setdefaultpaperfamily {pop} bind def /defaultpapertray 0 def /setdefaultpapertray {pop} bind def /defaulttrayswitch //false def /setdefaulttrayswitch {pop} bind def % Tray and format selection /11x17tray {/11x17 .uservar stopped { pop pop /11x17tray $error /errorname get signalerror } if } bind executeonly def /a3tray {/a3 .uservar stopped { pop pop /a3tray $error /errorname get signalerror } if } bind executeonly def /a4tray {/a4 .uservar stopped { pop pop /a4tray $error /errorname get signalerror } if } bind executeonly def /a5tray {/a5 .uservar stopped { pop pop /a5tray $error /errorname get signalerror } if } bind executeonly def /a6tray {/a6 .uservar stopped { pop pop /a6tray $error /errorname get signalerror } if } bind executeonly def /b4tray {/b4 .uservar stopped { pop pop /b4tray $error /errorname get signalerror } if } bind executeonly def /b5tray {/b5 .uservar stopped { pop pop /b5tray $error /errorname get signalerror } if } bind executeonly def /flsatray {/flsa .uservar stopped { pop pop /flsatray $error /errorname get signalerror } if } bind executeonly def /flsetray {/flse .uservar stopped { pop pop /flsetray $error /errorname get signalerror } if } bind executeonly def /halflettertray {/halfletter .uservar stopped { pop pop /halflettertray $error /errorname get signalerror } if } bind executeonly def /ledgertray {/ledger .uservar stopped { pop pop /ledgertray $error /errorname get signalerror } if } bind executeonly def /legaltray {/legal .uservar stopped { pop pop /legaltray $error /errorname get signalerror } if } bind executeonly def /lettertray {/letter .uservar stopped { pop pop /lettertray $error /errorname get signalerror } if } bind executeonly def % Per-job parameters /paperfamily 0 def % 0 is US, 1 is European /papertray 1 def /setpapertray {statusdict exch /papertray exch put} bind def /trayswitch //false def % paperout feeds from another tray % We don't implement the (undocumented by Adobe) papersize 'operator', % because it's very awkward to make it interact properly with all the % different ways of setting the paper size. %/papersize {/letter //true} bind def % <name of paper size>, <short-edge-first-p> /appletalktype (LaserWriter) def %%%%%% The following items are defined in the PostScript Language %%%%%% Reference Manual, First Edition, and subsequent 'compatibility' %%%%%% documentation from Adobe. /checkpassword {statusdict begin .password eq end} bind def /defaulttimeouts {statusdict begin .timeouts aload pop end} bind def /diskonline { //false (%disk*%) { pop not exit } 8192 string /IODevice resourceforall } bind def /diskstatus {10240 2097152 } bind odef % - diskstatus <free> <total> (in 1024 byte pages) %/dostartpage /eescratch {pop 0} bind def /idlefonts {statusdict begin mark .idlefonts aload pop end} bind def /jobname () def %/jobtimeout /manualfeed //false def /manualfeedtimeout 60 def /margins {statusdict begin .topmargin .leftmargin end} bind def /pagecount {4711} bind def /pagestackorder {//false} bind def /pagetype 0 def /prefeed //false def /printererror {pop pop} bind def /printername {statusdict /.printername get exch copy} bind def /processcolors /processcolors load def % defined in systemdict /product product def % product is defined in systemdict /revision revision def % revision is defined in systemdict /sccbatch {pop 9600 0} bind def /sccinteractive {pop 9600 0} bind def /setdefaulttimeouts {statusdict begin .timeouts astore pop end} bind def /setdostartpage {statusdict exch /dostartpage exch put} bind def /setduplexmode {mark /Duplex 3 -1 roll currentdevice putdeviceprops} bind def /seteescratch {pop pop} bind def /setidlefonts {] statusdict exch /.idlefonts exch put} bind def /setjobtimeout {statusdict exch /jobtimeout exch put} bind def /setmargins { statusdict begin /.leftmargin exch def /.topmargin exch def end } bind def % The following compatibility operators are only documented by Adobe in a % supplement to the Red Book. % % - pagemargin <offset> % - pageparams <width> <height> <offset> <orientation> % <width> <height> <orientation> setpage - % <offset> setpagemargin - % <width> <height> <offset> <orientation> setpageparams - % % width and height are in default units (and if orientation is odd, are % exchanged!). offset is the x margin, also in default units. % Unfortunately, because orientation is relative to the device paper feed, % it does not have a consistent meaning in terms of image orientation. % We follow the convention that ORIENT1 determines the orientation value % that means portait: false means 0, true means 1. /pagemargin { 0 } bind def /pageparams { currentdevice 1 dict dup /.MediaSize dup put .getdeviceparams exch pop exch pop aload pop 0 ORIENT1 { 1 } { 0 } ifelse } bind def /setpage { ORIENT1 { 1 } { 0 } ifelse ne {exch} if //.setpagesize exec } bind def /setpagemargin {pop} bind def % can't do better without setpagedevice /setpageparams { exch pop ORIENT1 { 1 } { 0 } ifelse ne {exch} if //.setpagesize exec } bind def /setpagetype { statusdict begin % The Adobe documentation only defines setpagetype % (a Level 1 operator) as accepting the values 0 and 1, % so we do too. dup type /integertype ne { /setpage cvx /typecheck signalerror } { dup 0 ne 1 index 1 ne or { /setpage cvx /rangecheck signalerror } { {/letter /note} 1 index get //systemdict /userdict get exch get cvx exec } ifelse /pagetype exch def } ifelse end } bind def /setpassword {exch checkpassword {statusdict exch /.password exch put //true} {pop //false} ifelse} bind def /setprintername {dup length string copy statusdict exch /.printername exch put} bind def % setresolution is not documented by Adobe, but some applications % use it anyway, without testing whether or not it is present. % % <pixels_per_inch> setresolution - % % sets the resolution of the device. /setresolution { mark /HWResolution [ 4 -1 roll dup ] currentdevice putdeviceprops pop initmatrix erasepage } bind def /setsccbatch {pop pop pop} bind def /setsccinteractive {pop pop pop} bind def /settumble {pop} bind def /waittimeout 300 def %%%%%% End of documented items. /.password 0 def /.timeouts [0 60 30] def //true setdostartpage mark setidlefonts 0 setjobtimeout 0 0 setmargins product setprintername currentdict /.setpagesize .undef end % statusdict %%%%%% The following documented compatibility "operators" are in systemdict, %%%%%% not in statusdict. systemdict begin .currentglobal //true .setglobal /devformat //true def /devforall { % <pattern> <proc> <scratch> devforall - exch { 1 index currentdevparams /Type .knownget { /FileSystem eq } { //false } ifelse { exec } { pop pop } ifelse } /exec load 3 packedarray cvx exch (*) 3 1 roll /IODevice resourceforall } odef /devstatus { % <(%disk*%)> devstatus <searchable> <writable> % <hasNames> <mounted> <removable> <searchOrder> % <freePages> <size> //true % <string> devstatus //false dup length 5 ge { dup 0 5 getinterval (%disk) eq { dup /IODevice resourcestatus { pop pop dup currentdevparams dup /Searchable get exch dup /Writeable get exch dup /HasNames get exch dup /Mounted get exch dup /Removable get exch dup /SearchOrder get exch dup /Free get exch /LogicalSize get 9 -1 roll pop //true } { pop //false } ifelse } { pop //false } ifelse } { pop //false } ifelse } odef .setglobal end % systemdict % The following contents of serverdict are a complete guess, % based on some observed LaserWriter boilerplate. serverdict begin /execjob { } bind def % The Red Book implies that something like the following is % an appropriate definition of exitserver. /exitserver { clear stop } bind def % However, this interacts badly with our standard error handler, % so we override it with the following less appropriate definition. /exitserver { 0 ne { clear cleardictstack } if } bind def /setrealdevice { } bind def end % serverdict gs_dps1.ps 0000644 00000011224 15030647507 0006457 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % Initialization file for most of the Display PostScript functions % that are also included in Level 2. level2dict begin % ------ Virtual memory ------ % /currentshared /.currentglobal load def /scheck {.gcheck} bind odef %****** FOLLOWING IS WRONG ****** /shareddict currentdict /globaldict .knownget not { 20 dict } if def % Global and LocalFontDirectory must remain in systemdict % even if we temporarily exit Level 2 mode. end % level2dict systemdict begin /SharedFontDirectory .FontDirectory .gcheck { .currentglobal //false .setglobal currentdict /LocalFontDirectory .FontDirectory dup maxlength dict copy .forceput % LocalFontDirectory is local, systemdict is global .setglobal .FontDirectory } executeonly { currentdict /LocalFontDirectory .FontDirectory .forceput % LocalFontDirectory is local, systemdict is global 50 dict }executeonly ifelse def end % systemdict level2dict begin % setshared must rebind FontDirectory to the appropriate one of % Local or SharedFontDirectory. /.setglobal % <bool> .setglobal - { dup .setglobal //systemdict /FontDirectory .currentglobal { //SharedFontDirectory } { /LocalFontDirectory .systemvar } % can't embed ref to local VM ifelse .forceput pop % LocalFontDirectory is local, systemdict is global } .bind executeonly odef % Don't just copy (load) the definition of .setglobal: % it gets redefined for LL3. /setshared { /.setglobal .systemvar exec } odef .currentglobal setshared % See below for changes in save and restore. % ------ Fonts ------ % /selectfont % <fontname> <size> selectfont - { { 1 .argindex findfont 1 index dup type /arraytype eq { makefont } { scalefont } ifelse setfont pop pop } stopped { /selectfont .systemvar $error /errorname get signalerror } if } odef % undefinefont has to take local/global VM into account. /undefinefont % <fontname> undefinefont - { //.FontDirectory 1 .argindex .forceundef % FontDirectory is readonly .currentglobal { % Current mode is global; delete from local directory too. //systemdict /LocalFontDirectory .knownget { 1 index .forceundef } executeonly % LocalFontDirectory is readonly if } { % Current mode is local; if there was a shadowed global % definition, copy it into the local directory. //systemdict /SharedFontDirectory .knownget { 1 index .knownget { //.FontDirectory 2 index 3 -1 roll .forceput } % readonly if } if } ifelse pop } odef % If we load a font into global VM within an inner save, the restore % will delete it from FontDirectory but not from SharedFontDirectory. % We have to handle this by making restore copy missing entries from % SharedFontDirectory to FontDirectory. Since this could slow down restore % considerably, we define a new operator .forcecopynew for this purpose. % Furthermore, if FAKEFONTS is in effect, we want global real fonts to % override fake local ones. We handle this by brute force. /restore % <save> restore - { dup //restore /LocalFontDirectory .systemvar FAKEFONTS { mark % We want to delete a fake font from the local directory % iff the global directory now has no definition for it, % or a non-fake definition. 1 index dup { % Stack: lfd mark lfd key ... lfd key value length 1 gt { % This is a real local definition; don't do anything. pop } { % This is a fake local definition, check for global. //SharedFontDirectory 1 index .knownget { % A global definition exists, check for fake. length 1 eq { pop } { 1 index } ifelse } { % No global definition, delete the local one. 1 index } ifelse } ifelse } forall pop counttomark 2 idiv { .forceundef } executeonly repeat pop % readonly } if //SharedFontDirectory exch .forcecopynew pop .currentglobal .setglobal % Rebind FontDirectory according to current VM. pop } .bind odef end % level2dict gs_frsd.ps 0000644 00000007304 15030647507 0006552 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % Implementation of ReusableStreamDecode filter. % This file must be loaded after gs_lev2.ps and gs_res.ps. level2dict begin % ------ ReusableStreamDecode filter ------ % /.reusablestreamdecode { % <source> <dict> .reusablestreamdecode <file> % <source> .reusablestreamdecode <file> % Collect the filter parameters. dup type /dicttype eq { 2 copy } { dup 0 dict } ifelse dup .rsdparams % Construct the filter pipeline. % The very first filter should use the value of CloseSource % from the RSD dictionary; all the others should have % CloseSource = true. % Stack: source dict filters parms 2 index /CloseSource .knownget not { //false } if 5 -1 roll % Stack: dict filters parms CloseSource source 0 1 5 index length 1 sub { 4 index 1 index get % Stack: dict filters parms CloseSource source index filtname 4 index //null eq { 0 dict } { 4 index 2 index get dup //null eq { pop 0 dict} if } ifelse 3 -1 roll pop exch filter exch pop //true exch % set CloseSource for further filters } for % If AsyncRead is true, try to create the filter directly. % Stack: dict filters parms CloseSource source 4 index /AsyncRead .knownget not { //false } if { 1 index { .reusablestream } //.internalstopped exec } { //null //true } ifelse { pop % No luck. Read the entire contents of the stream now. dup type /filetype ne { % Make a stream from a procedure or string data source. 0 () .subfiledecode } if % We must allocate the string in the same VM space as its % source, since the reusable stream must be allocated there. .currentglobal 1 index gcheck .setglobal exch currentpacking //false setpacking exch 2 dict begin /filelen 0 def % scratch dict for filelen and pos (below). % Stack: dict filters parms CloseSource oldglobal oldpacking file [ exch { dup 40000 string readstring /filelen 2 index length filelen add def % accumulate filelen not { exit } if exch } loop exch pop ] { filelen string } stopped { % try allocating a single string pop % couldn't make a string - discard filelen value } { % transfer the array-of-strings to the single string. % stack: ... [() ...] string /pos 0 def exch { 1 index exch pos exch putinterval /pos pos 40000 add def } forall } ifelse % top of stack is either array of strings or one string == stream_data end % done with scratch dict % Stack: dict filters parms CloseSource oldglobal oldpacking stream_data 3 1 roll setpacking setglobal % Stack: dict filters parms CloseSource stream_data 1 index .reusablestream } if % We created the stream successfully: clean up. 4 { exch pop } repeat 1 index type /dicttype eq { exch pop } if exch pop } odef filterdict /ReusableStreamDecode /.reusablestreamdecode load put end % level2dict gs_ll3.ps 0000644 00000046174 15030647507 0006316 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % Initialization file for PostScript LanguageLevel 3 functions. % This file must be loaded after gs_lev2.ps and gs_res.ps. % These definitions go into ll3dict or various ProcSets. % NOTE: the interpreter creates ll3dict. ll3dict begin % We need LanguageLevel 2 or higher in order to have setuserparams and % defineresource. languagelevel dup 2 .max .setlanguagelevel % ------ Idiom recognition ------ % /IdiomRecognition //false .definepsuserparam % Modify `bind' to apply idiom recognition afterwards. /.bindscratch 128 string def % Note that since this definition of `bind' may get bound in, % it has to function properly even at lower language levels, % where IdiomRecognition may not be defined. /.bind_ { % <proc> .bind <proc'> //.bind currentuserparams /IdiomRecognition .knownget not { //false } if { //false /IdiomSet //.findcategory exec .Instances { exch pop % pop the IdiomSet identifying key. Stack /proc /false [-dict- status size] 0 get % get resource instance, a dictionary. Stack : /proc false -dict- { exch pop % pop the instance identifying key % Stack: proc //false [template substitute] dup 1 get exch 0 get % Stack: proc //false substitute template 3 index .eqproc { % Stack: proc //false substitute 3 -1 roll pop exch not % Stack: substitute true } { pop % Stack: proc //false } ifelse } forall dup {exit} if % Stack proc <bool> } forall not % Not matched in global resources currentglobal not and % must not match local resources if currentglobal is true { //false .LocalInstances { exch pop % pop IdiomSet identifying key. Stack /proc /false [-dict- status size] 0 get % get resource instance, a dictionary Stack : /proc false -dict- { exch pop % pop instance identifier key % Stack: proc //false [template substitute] dup 1 get exch 0 get % Stack: proc //false substitute template 3 index .eqproc { % Stack: proc //false substitute 2 index gcheck % Stack: proc //false substitute _global?_ 1 index gcheck not and % Stack: proc //false substitute _global?_ _global?_ { % must not match if candidate in global VM and substitute in local pop % Stack: proc //false } { % Stack: proc //false substitute 3 -1 roll pop exch not % Stack: substitute true }ifelse } { pop % Stack: proc //false } ifelse } forall dup {exit} if } forall pop % Stack: proc/substitute } if end % .findcategory makes the category dictionary the current dict, so we must pop it from dict stack } if } def /.bind /.bind_ load odef % note that .bind_ will get bound currentdict /.bindscratch .undef DELAYBIND not { % We can't just do % /bind /.bind load def % because then /bind load == prints --.bind-- . /bind {//.bind_ exec} odef } if currentdict /.bind_ undef /.readbytestring { % <source> <bytestring> .readbytestring % <bytestring> <filled> % Note that since bytestrings don't implement getinterval, % if filled is false, there is no way to tell how much % was read. //true exch 0 1 2 index length 1 sub { % Stack: source true str index 3 index read not { pop exch not exch exit } if 3 copy put pop pop } for 3 -1 roll pop exch } bind def /.bigstring { % <size> .bigstring <string|bytestring> count 1 lt { /.bigstring cvx /stackunderflow signalerror } if dup type /integertype ne { /.bigstring cvx /typecheck signalerror } if dup 65400 gt { .bytestring } { string } ifelse } bind def % ------ HalftoneTypes 6, 10, 16 and HalftoneMode ------ % % This code depends on an internal HalftoneType 7 with the following keys: % Width, Height, Width2, Height2, TransferFunction: % as for HalftoneType 16. % Thresholds: a string or bytestring holding the thresholds, % (Width x Height + Width2 x Height2) x BitsPerSample / 8 bytes, % as for HalftoneType 16 except that the samples may be either % 8 or 16 bits wide. % BitsPerSample: 8 or 16. % Note that this HalftoneType never appears in halftone dictionaries given % to sethalftone, only as a component in those given to .sethalftone5, % so its numeric value can be chosen ad lib as long as it differs from the % other values that are legal in component dictionaries for .sethalftone5 % (currently only 1 and 3). /.makehalftone7 { % <dict> <dict> <source> <Width> <Height> % (<Width2> <Height2> | null) <BPS> .makehalftone7 % <setdict> <dict5> { .sethalftone5 } 8 dict begin /HalftoneType 7 def /BitsPerSample exch def dup //null eq { pop 0 } { /Height2 1 index def /Width2 2 index def mul } ifelse 3 1 roll /Height 1 index def /Width 2 index def mul add BitsPerSample 8 idiv mul //.bigstring exec % Stack: dict dict source str dup type /stringtype eq { readstring } { //.readbytestring exec} ifelse not { /sethalftone .systemvar /rangecheck signalerror exit } if readonly /Thresholds exch def /TransferFunction .knownget { /TransferFunction exch def } if % If the original Thresholds was a file, replace it with % a new one. dup /Thresholds get type /filetype eq { dup /Thresholds [ Thresholds ] cvx 0 () .subfiledecode put } if mark /HalftoneType 5 /Default currentdict end .dicttomark { .sethalftone5 } } bind def /.sethalftone6 { % <dict> <dict> .sethalftone6 <setdict> <dict5> % { .sethalftone5 } % Keys: Width, Height, Thresholds, T'Function dup /Thresholds get 1 index /Width get 2 index /Height get //null 8 //.makehalftone7 exec } bind def /.sethalftone10 { % <dict> <dict> .sethalftone10 <setdict> <dict5> % { .sethalftone5 } % Keys: Xsquare, Ysquare, Thresholds, T'Function % Note that this is the only one of these three HalftoneTypes % that allows either a file or a string for Thresholds. dup /Thresholds get dup type /stringtype eq { 0 () .subfiledecode } if 1 index /Xsquare get dup 3 index /Ysquare get dup 8 //.makehalftone7 exec } bind def /.sethalftone16 { % <dict> <dict> .sethalftone16 <setdict> <dict5> % { .sethalftone5 } % Keys: Width, Height, Width2, Height2, % Thresholds, T'Function dup /Thresholds get 1 index /Width get 2 index /Height get 3 index /Width2 .knownget { % 2-rectangle case 4 index /Height2 get } { % 1-rectangle case //null } ifelse 16 //.makehalftone7 exec } bind def .halftonetypes begin 6 //.sethalftone6 def 10 //.sethalftone10 def 16 //.sethalftone16 def end % Redefine the halftone-setting operators to honor HalftoneMode. /setcolorscreen { /HalftoneMode getuserparam 0 eq { //setcolorscreen } { 12 { pop } repeat //.getdefaulthalftone exec { //sethalftone } { .setdefaulthalftone } ifelse } ifelse } odef /setscreen { /HalftoneMode getuserparam 0 eq { //setscreen } { pop pop pop //.getdefaulthalftone exec { //sethalftone } { .setdefaulthalftone } ifelse } ifelse } odef /sethalftone { /HalftoneMode getuserparam 0 eq { //sethalftone } { gsave //sethalftone grestore //.getdefaulthalftone exec { //sethalftone } { .setdefaulthalftone } ifelse } ifelse } odef % ------ ImageTypes 3 and 4 (masked images) ------ % % Put the new data source in the requested dictionary. % Copy the updated dictionary because it nay be used elsewhere. % <dict> <data> <name> update_image3 <dict'> /update_image3 { 3 -1 roll dup length dict copy dup % [data] /name <<image>> <<image>> 2 index get % [data] /name <<image>> <<sub-image>> dup length dict copy dup % [data] /name <<image>> <<sub-image>> <<sub-image>> /DataSource 6 -1 roll put % /name <<image>> <<sub-image>> exch dup % /name <<sub-image>> <<image>> <<image>> 4 2 roll % <<image>> <<image>> /name <<sub-image>> put % <<image>> } bind def % Copy mask data source to a reusable stream % <dict> <source> buffer_mask <dict> <file> /buffer_mask { 1 index /MaskDict get dup /Width get 1 index /BitsPerComponent get mul 7 add 8 idiv exch /Height get mul () /SubFileDecode filter /ReusableStreamDecode filter } bind def % Data type vs. mask type decission table. % All procedures have the signature: % <image dict> <data DataSource> <mask DataSource> proc <image dict'> /data_mask_dict mark /stringtype mark % data is a string /stringtype { pop pop } bind /arraytype { % convert data to proc, don't buffer mask pop dup type dup /arraytype eq exch /packedarraytype eq or { [ exch { 1 array astore cvx } forall ] } { 1 array astore cvx } ifelse /DataDict //update_image3 exec } bind /packedarraytype 1 index /filetype { % convert data to file, don't buffer mask pop dup type dup /arraytype eq exch /packedarraytype eq or { [ exch { 1 array astore cvx 0 () /SubFileDecode filter } forall ] } { 1 array astore cvx 0 () /SubFileDecode filter } ifelse /DataDict //update_image3 exec } bind .dicttomark readonly /arraytype mark % data is a proc /stringtype { % convert mask to proc exch pop 1 array astore cvx /MaskDict //update_image3 exec } bind /arraytype { % buffer mask in reusable stream and convert back to proc exch pop //buffer_mask exec 500 string { readstring pop } aload pop 4 packedarray cvx /MaskDict //update_image3 exec } bind /packedarraytype 1 index /filetype 1 index .dicttomark readonly /packedarraytype 1 index /filetype mark % data is a file /stringtype { % convert mask to file exch pop 1 array astore cvx 0 () /SubFileDecode filter /MaskDict //update_image3 exec } bind /arraytype { % buffer the mask and convert to file exch pop //buffer_mask exec /MaskDict //update_image3 exec } bind /packedarraytype 1 index /filetype { //systemdict /userdict get /PDFTopSave known { pop pop % mask is already buffered by PDF interpreter } { exch pop % buffer the mask //buffer_mask exec /MaskDict //update_image3 exec } ifelse } bind .dicttomark readonly .dicttomark readonly def .imagetypes dup 3 { dup /InterleaveType get 3 eq { % .image3 requires data sources of the image and mask to be of the % same type. Work around this restriction here. dup /DataDict get /DataSource get 1 index /MaskDict get /DataSource get % <<>> data mask dup type % <<>> data mask mask_type 2 index 4 index /DataDict get /MultipleDataSources .knownget { { 0 get } if } if type % <<>> data mask mask_type data_type //data_mask_dict exch .knownget { exch .knownget { exec } { pop pop % pass wrong type as is to .image3 } ifelse } { pop pop pop % pass wrong type as is to .image3 } ifelse } if .image3 } bind put dup 4 /.image4 load put % We also detect ImageType 103 here: it isn't worth making a separate file % just for this. /.image3x where { pop dup 103 /.image3x load put } if pop currentdict /data_mask_dict undef currentdict /update_image3 undef currentdict /buffer_mask undef % ------ Functions ------ % % Define the FunctionType resource category. /Generic /Category findresource dup maxlength 3 add dict .copydict begin /InstanceType /integertype def /FunctionType currentdict end /Category defineresource pop {0 2 3} { dup /FunctionType defineresource pop } forall % ------ Smooth shading ------ % % Define the ShadingType resource category. /Generic /Category findresource dup maxlength 3 add dict .copydict begin /InstanceType /integertype def /ShadingType currentdict end /Category defineresource pop systemdict /.shadingtypes mark % not ll3dict 1 /.buildshading1 load 2 /.buildshading2 load 3 /.buildshading3 load 4 /.buildshading4 load 5 /.buildshading5 load 6 /.buildshading6 load 7 /.buildshading7 load .dicttomark put systemdict /.reuseparamdict mark /Intent 2 /AsyncRead //false /CloseSource //true .dicttomark readonly put /.buildshading { % <shadingdict> .buildshading <shading> dup rcheck not { % Adobe seems to access ColorSpace first and CET 12-14c checks this. /$error .systemvar /errorinfo [ /ColorSpace //null ] put /shfill .systemvar /invalidaccess signalerror } if % Unfortunately, we always need to make the DataSource reusable, % because if clipping is involved, even shfill may need to read % the source data multiple times. If it weren't for this, % we would only need to create a reusable stream if the ultimate % source of the data is a procedure (since the library can't % suspend shading to do a procedure callout). dup /DataSource .knownget { dup type /filetype eq { //.reuseparamdict /ReusableStreamDecode filter % Copy the dictionary to replace the DataSource, but make sure the % copy is in the same VM as the original. .currentglobal 2 index gcheck .setglobal % Stack: shdict rsdfile saveglobal 2 index dup length dict copy exch .setglobal dup /DataSource 4 -1 roll put exch pop } { pop } ifelse } if % The .buildshading operators use the current color space % for ColorSpace. dup /ShadingType .knownget not { % error handling for CET 12-14b conformance /$error .systemvar /errorinfo [ /ShadingType //null ] put /shfill .systemvar /undefined signalerror } if dup type /integertype ne { /$error .systemvar /errorinfo [ /ShadingType 4 index ] put /shfill .systemvar /typecheck signalerror } if //.shadingtypes 1 index .knownget not { /$error .systemvar /errorinfo [ /ShadingType 4 index ] put /shfill .systemvar /rangecheck signalerror } if exch pop 1 index /ColorSpace .knownget { { setcolorspace } stopped { /$error .systemvar /errorinfo [ /ColorSpace 4 index ] put /shfill .systemvar /$error .systemvar /errorname get signalerror } if exec } { /$error .systemvar /errorinfo [ /ColorSpace //null ] put /shfill .systemvar /undefined signalerror } ifelse } bind def /.buildshading_and_shfill { //.buildshading exec .shfill } bind def systemdict /.reuseparamdict undef /.buildpattern2 { % <template> <matrix> .buildpattern2 % <template> <pattern> % We want to build the pattern without doing gsave/grestore, % since we want it to load the CIE caches. 1 index /Shading get mark currentcolor currentcolorspace counttomark 4 add -3 roll mark 4 1 roll % Stack: -mark- ..color.. cspace -mark- template matrix shadingdict { //.buildshading exec} stopped { cleartomark setcolorspace setcolor pop stop } if .buildshadingpattern 3 -1 roll pop counttomark 1 add 2 roll setcolorspace setcolor pop } bind def .patterntypes 2 //.buildpattern2 put /shfill { % <shadingdict> shfill - % Currently, .shfill requires that the color space % in the pattern be the current color space. % Disable overprintmode for shfill { dup gsave 0 .setoverprintmode .buildshading_and_shfill } stopped grestore { /$error .systemvar /errorinfo 2 copy known { pop pop } { //null put % CET 12-14c } ifelse stop } if pop } odef % Establish an initial smoothness value that matches Adobe RIPs. 0.02 setsmoothness % ------ DeviceN color space ------ % % gs_res.ps uses these entries in colorspacedict % to populate the ColorSpaceFamily resource, so we need % to add the supported spaces. % systemdict /colorspacedict get begin /CIEBasedDEF [] def /CIEBasedDEFG [] def /DeviceN [] def end % ------ Miscellaneous ------ % % Make the setoverprintmode and currentoverprintmode operators visible (3015) % Because of the requirements of PDF, the .currentoverprintmode and % .setoverprintmode operators have integer parameters. Thus we need to % convert the Postscript bool parameters to integers. % /setoverprintmode % bool setoverprint - { { 1 } { 0 } ifelse % convert bool to integer //.setoverprintmode } odef /currentoverprintmode % - currentoverprintmode bool { //.currentoverprintmode 0 ne % convert integers to bool } odef % Define additional user and system parameters. /HalftoneMode 0 .definepsuserparam /MaxSuperScreen 1016 .definepsuserparam % read-only, so use .forceput pssystemparams /MaxDisplayAndSourceList 160000 .forceput % Define the IdiomSet resource category. { /IdiomSet } { /Generic /Category findresource dup maxlength 3 add dict .copydict begin /InstanceType /dicttype def currentdict end /Category defineresource pop } forall (*) { dup type /nametype eq not { cvn } if /IdiomSet findresource pop } 256 string /IdiomSet resourceforall /languagelevel 3 def % When running in LanguageLevel 3 mode, this interpreter is supposed to be % compatible with Adobe version 3010. /version (3010) readonly def .setlanguagelevel % undefine things defined (or used) in this file and not referenced elsewhere [ /.buildpattern2 /.buildshading /.buildshading1 /.buildshading2 /.buildshading3 /.buildshading4 /.buildshading5 /.buildshading6 /.buildshading7 /.buildshadingpattern /.makehalftone7 /.sethalftone6 /.sethalftone10 /.sethalftone16 /.readbytestring /.bigstring ] dup currentdict .undefinternalnames systemdict .undefinternalnames end % ll3dict gs_icc.ps 0000644 00000006040 15030647507 0006346 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % We need LanguageLevel 2 or higher in order to have setuserparams and % << >> dictionaries languagelevel dup 2 .max .setlanguagelevel % ICCBased color space method dictionaries. % This assumes gs_ciecs2.ps has already been processed. .currentglobal //true .setglobal % gs_res.ps uses these entries in colorspacedict % to populate the ColorSpaceFamily resource, so we need % to add the supported spaces. % systemdict /colorspacedict get begin /ICCBased [] def end NOPSICC { (%END PSICC) .skipeof } if % Now set up ICC profile loading for PostScript %%BeginICCProfile sections. /cs-sig-dict << (XYZ ) 3 (Lab ) 3 (Luv ) 3 (YCbr) 3 (Yxy ) 3 (RGB ) 3 (GRAY) 1 (HSV ) 3 (HLS ) 3 (CMYK) 4 (CMY ) 3 >> readonly def systemdict begin /.ProcessICCcomment { % file comment -- file comment dup (%%BeginICCProfile) anchorsearch { pop pop DEBUG { (.ProcessICCcomment found %%BeginICCProfile) print flush } if % load an ICC profile defined as comments (hex encoded). % Ends with %%End at the start of a line. Read the data into % an array of strings. This string can be used directly as a % source for ReusableStreamDecode filter. % % stack: --file-- (%%BeginICCProfile: ...) 1 index 0 (%%EndICCProfile) /SubFileDecode filter [ { counttomark 1 add index 64000 string readhexstring not { exit } if } loop ] exch closefile % make a seekable -file- out of the string array mark /AsyncRead //true .dicttomark /ReusableStreamDecode filter % stack: --file-- (%%BeginICCProfile: ...) --icc_subfile-- dup 16 setfileposition dup (1234) readstring pop 1 index 0 setfileposition //cs-sig-dict exch .knownget { 3 dict begin /Alternate {0 /DeviceGray 0 /DeviceRGB /DeviceCMYK } 2 index get def /N exch def /DataSource exch def [/ICCBased currentdict] end { setcolorspace } stopped { pop QUIET not { ( *** Unable to load ICC profile from PostScript DSC comments ***) = flush } if } if } { pop } ifelse } { pop % Not interested in this DSC comment } ifelse } bind def currentdict /cs-sig-dict undef % Merge ProcessICCcomment with existing handler /.ProcessICCcomment load /exec load currentuserparams /ProcessDSCComment get dup //null eq {pop {pop pop}} if /exec load 4 array astore cvx readonly << /ProcessDSCComment 3 -1 roll >> setuserparams currentdict /.ProcessICCcomment .undef end % systemdict %END PSICC .setglobal .setlanguagelevel gs_agl.ps 0000644 00000651645 15030647507 0006374 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % $Id: gs_agl.ps 10822 2010-02-27 20:24:13Z alexcher $ % This file was derived from the Adobe Glyph List, version 2.0, dated % September 20, 2002. % See http://partners.adobe.com/asn/developer/typeforum/unicodegn.html % That file does not contain any copyright notice. /AdobeGlyphList mark /A 16#0041 /AE 16#00C6 /AEacute 16#01FC /AEmacron 16#01E2 /AEsmall 16#F7E6 /Aacute 16#00C1 /Aacutesmall 16#F7E1 /Abreve 16#0102 /Abreveacute 16#1EAE /Abrevecyrillic 16#04D0 /Abrevedotbelow 16#1EB6 /Abrevegrave 16#1EB0 /Abrevehookabove 16#1EB2 /Abrevetilde 16#1EB4 /Acaron 16#01CD /Acircle 16#24B6 /Acircumflex 16#00C2 /Acircumflexacute 16#1EA4 /Acircumflexdotbelow 16#1EAC /Acircumflexgrave 16#1EA6 /Acircumflexhookabove 16#1EA8 /Acircumflexsmall 16#F7E2 /Acircumflextilde 16#1EAA /Acute 16#F6C9 /Acutesmall 16#F7B4 /Acyrillic 16#0410 /Adblgrave 16#0200 /Adieresis 16#00C4 /Adieresiscyrillic 16#04D2 /Adieresismacron 16#01DE /Adieresissmall 16#F7E4 /Adotbelow 16#1EA0 /Adotmacron 16#01E0 /Agrave 16#00C0 /Agravesmall 16#F7E0 /Ahookabove 16#1EA2 /Aiecyrillic 16#04D4 /Ainvertedbreve 16#0202 /Alpha 16#0391 /Alphatonos 16#0386 /Amacron 16#0100 /Amonospace 16#FF21 /Aogonek 16#0104 /Aring 16#00C5 /Aringacute 16#01FA /Aringbelow 16#1E00 /Aringsmall 16#F7E5 /Asmall 16#F761 /Atilde 16#00C3 /Atildesmall 16#F7E3 /Aybarmenian 16#0531 /B 16#0042 /Bcircle 16#24B7 /Bdotaccent 16#1E02 /Bdotbelow 16#1E04 /Becyrillic 16#0411 /Benarmenian 16#0532 /Beta 16#0392 /Bhook 16#0181 /Blinebelow 16#1E06 /Bmonospace 16#FF22 /Brevesmall 16#F6F4 /Bsmall 16#F762 /Btopbar 16#0182 /C 16#0043 /Caarmenian 16#053E /Cacute 16#0106 /Caron 16#F6CA /Caronsmall 16#F6F5 /Ccaron 16#010C /Ccedilla 16#00C7 /Ccedillaacute 16#1E08 /Ccedillasmall 16#F7E7 /Ccircle 16#24B8 /Ccircumflex 16#0108 /Cdot 16#010A /Cdotaccent 16#010A /Cedillasmall 16#F7B8 /Chaarmenian 16#0549 /Cheabkhasiancyrillic 16#04BC /Checyrillic 16#0427 /Chedescenderabkhasiancyrillic 16#04BE /Chedescendercyrillic 16#04B6 /Chedieresiscyrillic 16#04F4 /Cheharmenian 16#0543 /Chekhakassiancyrillic 16#04CB /Cheverticalstrokecyrillic 16#04B8 /Chi 16#03A7 /Chook 16#0187 /Circumflexsmall 16#F6F6 /Cmonospace 16#FF23 /Coarmenian 16#0551 /Csmall 16#F763 /D 16#0044 /DZ 16#01F1 /DZcaron 16#01C4 /Daarmenian 16#0534 /Dafrican 16#0189 /Dcaron 16#010E /Dcedilla 16#1E10 /Dcircle 16#24B9 /Dcircumflexbelow 16#1E12 /Dcroat 16#0110 /Ddotaccent 16#1E0A /Ddotbelow 16#1E0C /Decyrillic 16#0414 /Deicoptic 16#03EE /Delta 16#2206 /Deltagreek 16#0394 /Dhook 16#018A /Dieresis 16#F6CB /DieresisAcute 16#F6CC /DieresisGrave 16#F6CD /Dieresissmall 16#F7A8 /Digammagreek 16#03DC /Djecyrillic 16#0402 /Dlinebelow 16#1E0E /Dmonospace 16#FF24 /Dotaccentsmall 16#F6F7 /Dslash 16#0110 /Dsmall 16#F764 /Dtopbar 16#018B /Dz 16#01F2 /Dzcaron 16#01C5 /Dzeabkhasiancyrillic 16#04E0 /Dzecyrillic 16#0405 /Dzhecyrillic 16#040F /E 16#0045 /Eacute 16#00C9 /Eacutesmall 16#F7E9 /Ebreve 16#0114 /Ecaron 16#011A /Ecedillabreve 16#1E1C /Echarmenian 16#0535 /Ecircle 16#24BA /Ecircumflex 16#00CA /Ecircumflexacute 16#1EBE /Ecircumflexbelow 16#1E18 /Ecircumflexdotbelow 16#1EC6 /Ecircumflexgrave 16#1EC0 /Ecircumflexhookabove 16#1EC2 /Ecircumflexsmall 16#F7EA /Ecircumflextilde 16#1EC4 /Ecyrillic 16#0404 /Edblgrave 16#0204 /Edieresis 16#00CB /Edieresissmall 16#F7EB /Edot 16#0116 /Edotaccent 16#0116 /Edotbelow 16#1EB8 /Efcyrillic 16#0424 /Egrave 16#00C8 /Egravesmall 16#F7E8 /Eharmenian 16#0537 /Ehookabove 16#1EBA /Eightroman 16#2167 /Einvertedbreve 16#0206 /Eiotifiedcyrillic 16#0464 /Elcyrillic 16#041B /Elevenroman 16#216A /Emacron 16#0112 /Emacronacute 16#1E16 /Emacrongrave 16#1E14 /Emcyrillic 16#041C /Emonospace 16#FF25 /Encyrillic 16#041D /Endescendercyrillic 16#04A2 /Eng 16#014A /Enghecyrillic 16#04A4 /Enhookcyrillic 16#04C7 /Eogonek 16#0118 /Eopen 16#0190 /Epsilon 16#0395 /Epsilontonos 16#0388 /Ercyrillic 16#0420 /Ereversed 16#018E /Ereversedcyrillic 16#042D /Escyrillic 16#0421 /Esdescendercyrillic 16#04AA /Esh 16#01A9 /Esmall 16#F765 /Eta 16#0397 /Etarmenian 16#0538 /Etatonos 16#0389 /Eth 16#00D0 /Ethsmall 16#F7F0 /Etilde 16#1EBC /Etildebelow 16#1E1A /Euro 16#20AC /Ezh 16#01B7 /Ezhcaron 16#01EE /Ezhreversed 16#01B8 /F 16#0046 /Fcircle 16#24BB /Fdotaccent 16#1E1E /Feharmenian 16#0556 /Feicoptic 16#03E4 /Fhook 16#0191 /Fitacyrillic 16#0472 /Fiveroman 16#2164 /Fmonospace 16#FF26 /Fourroman 16#2163 /Fsmall 16#F766 /G 16#0047 /GBsquare 16#3387 /Gacute 16#01F4 /Gamma 16#0393 /Gammaafrican 16#0194 /Gangiacoptic 16#03EA /Gbreve 16#011E /Gcaron 16#01E6 /Gcedilla 16#0122 /Gcircle 16#24BC /Gcircumflex 16#011C /Gcommaaccent 16#0122 /Gdot 16#0120 /Gdotaccent 16#0120 /Gecyrillic 16#0413 /Ghadarmenian 16#0542 /Ghemiddlehookcyrillic 16#0494 /Ghestrokecyrillic 16#0492 /Gheupturncyrillic 16#0490 /Ghook 16#0193 /Gimarmenian 16#0533 /Gjecyrillic 16#0403 /Gmacron 16#1E20 /Gmonospace 16#FF27 /Grave 16#F6CE /Gravesmall 16#F760 /Gsmall 16#F767 /Gsmallhook 16#029B /Gstroke 16#01E4 /H 16#0048 /H18533 16#25CF /H18543 16#25AA /H18551 16#25AB /H22073 16#25A1 /HPsquare 16#33CB /Haabkhasiancyrillic 16#04A8 /Hadescendercyrillic 16#04B2 /Hardsigncyrillic 16#042A /Hbar 16#0126 /Hbrevebelow 16#1E2A /Hcedilla 16#1E28 /Hcircle 16#24BD /Hcircumflex 16#0124 /Hdieresis 16#1E26 /Hdotaccent 16#1E22 /Hdotbelow 16#1E24 /Hmonospace 16#FF28 /Hoarmenian 16#0540 /Horicoptic 16#03E8 /Hsmall 16#F768 /Hungarumlaut 16#F6CF /Hungarumlautsmall 16#F6F8 /Hzsquare 16#3390 /I 16#0049 /IAcyrillic 16#042F /IJ 16#0132 /IUcyrillic 16#042E /Iacute 16#00CD /Iacutesmall 16#F7ED /Ibreve 16#012C /Icaron 16#01CF /Icircle 16#24BE /Icircumflex 16#00CE /Icircumflexsmall 16#F7EE /Icyrillic 16#0406 /Idblgrave 16#0208 /Idieresis 16#00CF /Idieresisacute 16#1E2E /Idieresiscyrillic 16#04E4 /Idieresissmall 16#F7EF /Idot 16#0130 /Idotaccent 16#0130 /Idotbelow 16#1ECA /Iebrevecyrillic 16#04D6 /Iecyrillic 16#0415 /Ifraktur 16#2111 /Igrave 16#00CC /Igravesmall 16#F7EC /Ihookabove 16#1EC8 /Iicyrillic 16#0418 /Iinvertedbreve 16#020A /Iishortcyrillic 16#0419 /Imacron 16#012A /Imacroncyrillic 16#04E2 /Imonospace 16#FF29 /Iniarmenian 16#053B /Iocyrillic 16#0401 /Iogonek 16#012E /Iota 16#0399 /Iotaafrican 16#0196 /Iotadieresis 16#03AA /Iotatonos 16#038A /Ismall 16#F769 /Istroke 16#0197 /Itilde 16#0128 /Itildebelow 16#1E2C /Izhitsacyrillic 16#0474 /Izhitsadblgravecyrillic 16#0476 /J 16#004A /Jaarmenian 16#0541 /Jcircle 16#24BF /Jcircumflex 16#0134 /Jecyrillic 16#0408 /Jheharmenian 16#054B /Jmonospace 16#FF2A /Jsmall 16#F76A /K 16#004B /KBsquare 16#3385 /KKsquare 16#33CD /Kabashkircyrillic 16#04A0 /Kacute 16#1E30 /Kacyrillic 16#041A /Kadescendercyrillic 16#049A /Kahookcyrillic 16#04C3 /Kappa 16#039A /Kastrokecyrillic 16#049E /Kaverticalstrokecyrillic 16#049C /Kcaron 16#01E8 /Kcedilla 16#0136 /Kcircle 16#24C0 /Kcommaaccent 16#0136 /Kdotbelow 16#1E32 /Keharmenian 16#0554 /Kenarmenian 16#053F /Khacyrillic 16#0425 /Kheicoptic 16#03E6 /Khook 16#0198 /Kjecyrillic 16#040C /Klinebelow 16#1E34 /Kmonospace 16#FF2B /Koppacyrillic 16#0480 /Koppagreek 16#03DE /Ksicyrillic 16#046E /Ksmall 16#F76B /L 16#004C /LJ 16#01C7 /LL 16#F6BF /Lacute 16#0139 /Lambda 16#039B /Lcaron 16#013D /Lcedilla 16#013B /Lcircle 16#24C1 /Lcircumflexbelow 16#1E3C /Lcommaaccent 16#013B /Ldot 16#013F /Ldotaccent 16#013F /Ldotbelow 16#1E36 /Ldotbelowmacron 16#1E38 /Liwnarmenian 16#053C /Lj 16#01C8 /Ljecyrillic 16#0409 /Llinebelow 16#1E3A /Lmonospace 16#FF2C /Lslash 16#0141 /Lslashsmall 16#F6F9 /Lsmall 16#F76C /M 16#004D /MBsquare 16#3386 /Macron 16#F6D0 /Macronsmall 16#F7AF /Macute 16#1E3E /Mcircle 16#24C2 /Mdotaccent 16#1E40 /Mdotbelow 16#1E42 /Menarmenian 16#0544 /Mmonospace 16#FF2D /Msmall 16#F76D /Mturned 16#019C /Mu 16#039C /N 16#004E /NJ 16#01CA /Nacute 16#0143 /Ncaron 16#0147 /Ncedilla 16#0145 /Ncircle 16#24C3 /Ncircumflexbelow 16#1E4A /Ncommaaccent 16#0145 /Ndotaccent 16#1E44 /Ndotbelow 16#1E46 /Nhookleft 16#019D /Nineroman 16#2168 /Nj 16#01CB /Njecyrillic 16#040A /Nlinebelow 16#1E48 /Nmonospace 16#FF2E /Nowarmenian 16#0546 /Nsmall 16#F76E /Ntilde 16#00D1 /Ntildesmall 16#F7F1 /Nu 16#039D /O 16#004F /OE 16#0152 /OEsmall 16#F6FA /Oacute 16#00D3 /Oacutesmall 16#F7F3 /Obarredcyrillic 16#04E8 /Obarreddieresiscyrillic 16#04EA /Obreve 16#014E /Ocaron 16#01D1 /Ocenteredtilde 16#019F /Ocircle 16#24C4 /Ocircumflex 16#00D4 /Ocircumflexacute 16#1ED0 /Ocircumflexdotbelow 16#1ED8 /Ocircumflexgrave 16#1ED2 /Ocircumflexhookabove 16#1ED4 /Ocircumflexsmall 16#F7F4 /Ocircumflextilde 16#1ED6 /Ocyrillic 16#041E /Odblacute 16#0150 /Odblgrave 16#020C /Odieresis 16#00D6 /Odieresiscyrillic 16#04E6 /Odieresissmall 16#F7F6 /Odotbelow 16#1ECC /Ogoneksmall 16#F6FB /Ograve 16#00D2 /Ogravesmall 16#F7F2 /Oharmenian 16#0555 /Ohm 16#2126 /Ohookabove 16#1ECE /Ohorn 16#01A0 /Ohornacute 16#1EDA /Ohorndotbelow 16#1EE2 /Ohorngrave 16#1EDC /Ohornhookabove 16#1EDE /Ohorntilde 16#1EE0 /Ohungarumlaut 16#0150 /Oi 16#01A2 /Oinvertedbreve 16#020E /Omacron 16#014C /Omacronacute 16#1E52 /Omacrongrave 16#1E50 /Omega 16#2126 /Omegacyrillic 16#0460 /Omegagreek 16#03A9 /Omegaroundcyrillic 16#047A /Omegatitlocyrillic 16#047C /Omegatonos 16#038F /Omicron 16#039F /Omicrontonos 16#038C /Omonospace 16#FF2F /Oneroman 16#2160 /Oogonek 16#01EA /Oogonekmacron 16#01EC /Oopen 16#0186 /Oslash 16#00D8 /Oslashacute 16#01FE /Oslashsmall 16#F7F8 /Osmall 16#F76F /Ostrokeacute 16#01FE /Otcyrillic 16#047E /Otilde 16#00D5 /Otildeacute 16#1E4C /Otildedieresis 16#1E4E /Otildesmall 16#F7F5 /P 16#0050 /Pacute 16#1E54 /Pcircle 16#24C5 /Pdotaccent 16#1E56 /Pecyrillic 16#041F /Peharmenian 16#054A /Pemiddlehookcyrillic 16#04A6 /Phi 16#03A6 /Phook 16#01A4 /Pi 16#03A0 /Piwrarmenian 16#0553 /Pmonospace 16#FF30 /Psi 16#03A8 /Psicyrillic 16#0470 /Psmall 16#F770 /Q 16#0051 /Qcircle 16#24C6 /Qmonospace 16#FF31 /Qsmall 16#F771 /R 16#0052 /Raarmenian 16#054C /Racute 16#0154 /Rcaron 16#0158 /Rcedilla 16#0156 /Rcircle 16#24C7 /Rcommaaccent 16#0156 /Rdblgrave 16#0210 /Rdotaccent 16#1E58 /Rdotbelow 16#1E5A /Rdotbelowmacron 16#1E5C /Reharmenian 16#0550 /Rfraktur 16#211C /Rho 16#03A1 /Ringsmall 16#F6FC /Rinvertedbreve 16#0212 /Rlinebelow 16#1E5E /Rmonospace 16#FF32 /Rsmall 16#F772 /Rsmallinverted 16#0281 /Rsmallinvertedsuperior 16#02B6 /S 16#0053 /SF010000 16#250C /SF020000 16#2514 /SF030000 16#2510 /SF040000 16#2518 /SF050000 16#253C /SF060000 16#252C /SF070000 16#2534 /SF080000 16#251C /SF090000 16#2524 /SF100000 16#2500 /SF110000 16#2502 /SF190000 16#2561 /SF200000 16#2562 /SF210000 16#2556 /SF220000 16#2555 /SF230000 16#2563 /SF240000 16#2551 /SF250000 16#2557 /SF260000 16#255D /SF270000 16#255C /SF280000 16#255B /SF360000 16#255E /SF370000 16#255F /SF380000 16#255A /SF390000 16#2554 /SF400000 16#2569 /SF410000 16#2566 /SF420000 16#2560 /SF430000 16#2550 /SF440000 16#256C /SF450000 16#2567 /SF460000 16#2568 /SF470000 16#2564 /SF480000 16#2565 /SF490000 16#2559 /SF500000 16#2558 /SF510000 16#2552 /SF520000 16#2553 /SF530000 16#256B /SF540000 16#256A /Sacute 16#015A /Sacutedotaccent 16#1E64 /Sampigreek 16#03E0 /Scaron 16#0160 /Scarondotaccent 16#1E66 /Scaronsmall 16#F6FD /Scedilla 16#015E /Schwa 16#018F /Schwacyrillic 16#04D8 /Schwadieresiscyrillic 16#04DA /Scircle 16#24C8 /Scircumflex 16#015C /Scommaaccent 16#0218 /Sdotaccent 16#1E60 /Sdotbelow 16#1E62 /Sdotbelowdotaccent 16#1E68 /Seharmenian 16#054D /Sevenroman 16#2166 /Shaarmenian 16#0547 /Shacyrillic 16#0428 /Shchacyrillic 16#0429 /Sheicoptic 16#03E2 /Shhacyrillic 16#04BA /Shimacoptic 16#03EC /Sigma 16#03A3 /Sixroman 16#2165 /Smonospace 16#FF33 /Softsigncyrillic 16#042C /Ssmall 16#F773 /Stigmagreek 16#03DA /T 16#0054 /Tau 16#03A4 /Tbar 16#0166 /Tcaron 16#0164 /Tcedilla 16#0162 /Tcircle 16#24C9 /Tcircumflexbelow 16#1E70 /Tcommaaccent 16#0162 /Tdotaccent 16#1E6A /Tdotbelow 16#1E6C /Tecyrillic 16#0422 /Tedescendercyrillic 16#04AC /Tenroman 16#2169 /Tetsecyrillic 16#04B4 /Theta 16#0398 /Thook 16#01AC /Thorn 16#00DE /Thornsmall 16#F7FE /Threeroman 16#2162 /Tildesmall 16#F6FE /Tiwnarmenian 16#054F /Tlinebelow 16#1E6E /Tmonospace 16#FF34 /Toarmenian 16#0539 /Tonefive 16#01BC /Tonesix 16#0184 /Tonetwo 16#01A7 /Tretroflexhook 16#01AE /Tsecyrillic 16#0426 /Tshecyrillic 16#040B /Tsmall 16#F774 /Twelveroman 16#216B /Tworoman 16#2161 /U 16#0055 /Uacute 16#00DA /Uacutesmall 16#F7FA /Ubreve 16#016C /Ucaron 16#01D3 /Ucircle 16#24CA /Ucircumflex 16#00DB /Ucircumflexbelow 16#1E76 /Ucircumflexsmall 16#F7FB /Ucyrillic 16#0423 /Udblacute 16#0170 /Udblgrave 16#0214 /Udieresis 16#00DC /Udieresisacute 16#01D7 /Udieresisbelow 16#1E72 /Udieresiscaron 16#01D9 /Udieresiscyrillic 16#04F0 /Udieresisgrave 16#01DB /Udieresismacron 16#01D5 /Udieresissmall 16#F7FC /Udotbelow 16#1EE4 /Ugrave 16#00D9 /Ugravesmall 16#F7F9 /Uhookabove 16#1EE6 /Uhorn 16#01AF /Uhornacute 16#1EE8 /Uhorndotbelow 16#1EF0 /Uhorngrave 16#1EEA /Uhornhookabove 16#1EEC /Uhorntilde 16#1EEE /Uhungarumlaut 16#0170 /Uhungarumlautcyrillic 16#04F2 /Uinvertedbreve 16#0216 /Ukcyrillic 16#0478 /Umacron 16#016A /Umacroncyrillic 16#04EE /Umacrondieresis 16#1E7A /Umonospace 16#FF35 /Uogonek 16#0172 /Upsilon 16#03A5 /Upsilon1 16#03D2 /Upsilonacutehooksymbolgreek 16#03D3 /Upsilonafrican 16#01B1 /Upsilondieresis 16#03AB /Upsilondieresishooksymbolgreek 16#03D4 /Upsilonhooksymbol 16#03D2 /Upsilontonos 16#038E /Uring 16#016E /Ushortcyrillic 16#040E /Usmall 16#F775 /Ustraightcyrillic 16#04AE /Ustraightstrokecyrillic 16#04B0 /Utilde 16#0168 /Utildeacute 16#1E78 /Utildebelow 16#1E74 /V 16#0056 /Vcircle 16#24CB /Vdotbelow 16#1E7E /Vecyrillic 16#0412 /Vewarmenian 16#054E /Vhook 16#01B2 /Vmonospace 16#FF36 /Voarmenian 16#0548 /Vsmall 16#F776 /Vtilde 16#1E7C /W 16#0057 /Wacute 16#1E82 /Wcircle 16#24CC /Wcircumflex 16#0174 /Wdieresis 16#1E84 /Wdotaccent 16#1E86 /Wdotbelow 16#1E88 /Wgrave 16#1E80 /Wmonospace 16#FF37 /Wsmall 16#F777 /X 16#0058 /Xcircle 16#24CD /Xdieresis 16#1E8C /Xdotaccent 16#1E8A /Xeharmenian 16#053D /Xi 16#039E /Xmonospace 16#FF38 /Xsmall 16#F778 /Y 16#0059 /Yacute 16#00DD /Yacutesmall 16#F7FD /Yatcyrillic 16#0462 /Ycircle 16#24CE /Ycircumflex 16#0176 /Ydieresis 16#0178 /Ydieresissmall 16#F7FF /Ydotaccent 16#1E8E /Ydotbelow 16#1EF4 /Yericyrillic 16#042B /Yerudieresiscyrillic 16#04F8 /Ygrave 16#1EF2 /Yhook 16#01B3 /Yhookabove 16#1EF6 /Yiarmenian 16#0545 /Yicyrillic 16#0407 /Yiwnarmenian 16#0552 /Ymonospace 16#FF39 /Ysmall 16#F779 /Ytilde 16#1EF8 /Yusbigcyrillic 16#046A /Yusbigiotifiedcyrillic 16#046C /Yuslittlecyrillic 16#0466 /Yuslittleiotifiedcyrillic 16#0468 /Z 16#005A /Zaarmenian 16#0536 /Zacute 16#0179 /Zcaron 16#017D /Zcaronsmall 16#F6FF /Zcircle 16#24CF /Zcircumflex 16#1E90 /Zdot 16#017B /Zdotaccent 16#017B /Zdotbelow 16#1E92 /Zecyrillic 16#0417 /Zedescendercyrillic 16#0498 /Zedieresiscyrillic 16#04DE /Zeta 16#0396 /Zhearmenian 16#053A /Zhebrevecyrillic 16#04C1 /Zhecyrillic 16#0416 /Zhedescendercyrillic 16#0496 /Zhedieresiscyrillic 16#04DC /Zlinebelow 16#1E94 /Zmonospace 16#FF3A /Zsmall 16#F77A /Zstroke 16#01B5 /a 16#0061 /aabengali 16#0986 /aacute 16#00E1 /aadeva 16#0906 /aagujarati 16#0A86 /aagurmukhi 16#0A06 /aamatragurmukhi 16#0A3E /aarusquare 16#3303 /aavowelsignbengali 16#09BE /aavowelsigndeva 16#093E /aavowelsigngujarati 16#0ABE /abbreviationmarkarmenian 16#055F /abbreviationsigndeva 16#0970 /abengali 16#0985 /abopomofo 16#311A /abreve 16#0103 /abreveacute 16#1EAF /abrevecyrillic 16#04D1 /abrevedotbelow 16#1EB7 /abrevegrave 16#1EB1 /abrevehookabove 16#1EB3 /abrevetilde 16#1EB5 /acaron 16#01CE /acircle 16#24D0 /acircumflex 16#00E2 /acircumflexacute 16#1EA5 /acircumflexdotbelow 16#1EAD /acircumflexgrave 16#1EA7 /acircumflexhookabove 16#1EA9 /acircumflextilde 16#1EAB /acute 16#00B4 /acutebelowcmb 16#0317 /acutecmb 16#0301 /acutecomb 16#0301 /acutedeva 16#0954 /acutelowmod 16#02CF /acutetonecmb 16#0341 /acyrillic 16#0430 /adblgrave 16#0201 /addakgurmukhi 16#0A71 /adeva 16#0905 /adieresis 16#00E4 /adieresiscyrillic 16#04D3 /adieresismacron 16#01DF /adotbelow 16#1EA1 /adotmacron 16#01E1 /ae 16#00E6 /aeacute 16#01FD /aekorean 16#3150 /aemacron 16#01E3 /afii00208 16#2015 /afii08941 16#20A4 /afii10017 16#0410 /afii10018 16#0411 /afii10019 16#0412 /afii10020 16#0413 /afii10021 16#0414 /afii10022 16#0415 /afii10023 16#0401 /afii10024 16#0416 /afii10025 16#0417 /afii10026 16#0418 /afii10027 16#0419 /afii10028 16#041A /afii10029 16#041B /afii10030 16#041C /afii10031 16#041D /afii10032 16#041E /afii10033 16#041F /afii10034 16#0420 /afii10035 16#0421 /afii10036 16#0422 /afii10037 16#0423 /afii10038 16#0424 /afii10039 16#0425 /afii10040 16#0426 /afii10041 16#0427 /afii10042 16#0428 /afii10043 16#0429 /afii10044 16#042A /afii10045 16#042B /afii10046 16#042C /afii10047 16#042D /afii10048 16#042E /afii10049 16#042F /afii10050 16#0490 /afii10051 16#0402 /afii10052 16#0403 /afii10053 16#0404 /afii10054 16#0405 /afii10055 16#0406 /afii10056 16#0407 /afii10057 16#0408 /afii10058 16#0409 /afii10059 16#040A /afii10060 16#040B /afii10061 16#040C /afii10062 16#040E /afii10063 16#F6C4 /afii10064 16#F6C5 /afii10065 16#0430 /afii10066 16#0431 /afii10067 16#0432 /afii10068 16#0433 /afii10069 16#0434 /afii10070 16#0435 /afii10071 16#0451 /afii10072 16#0436 /afii10073 16#0437 /afii10074 16#0438 /afii10075 16#0439 /afii10076 16#043A /afii10077 16#043B /afii10078 16#043C /afii10079 16#043D /afii10080 16#043E /afii10081 16#043F /afii10082 16#0440 /afii10083 16#0441 /afii10084 16#0442 /afii10085 16#0443 /afii10086 16#0444 /afii10087 16#0445 /afii10088 16#0446 /afii10089 16#0447 /afii10090 16#0448 /afii10091 16#0449 /afii10092 16#044A /afii10093 16#044B /afii10094 16#044C /afii10095 16#044D /afii10096 16#044E /afii10097 16#044F /afii10098 16#0491 /afii10099 16#0452 /afii10100 16#0453 /afii10101 16#0454 /afii10102 16#0455 /afii10103 16#0456 /afii10104 16#0457 /afii10105 16#0458 /afii10106 16#0459 /afii10107 16#045A /afii10108 16#045B /afii10109 16#045C /afii10110 16#045E /afii10145 16#040F /afii10146 16#0462 /afii10147 16#0472 /afii10148 16#0474 /afii10192 16#F6C6 /afii10193 16#045F /afii10194 16#0463 /afii10195 16#0473 /afii10196 16#0475 /afii10831 16#F6C7 /afii10832 16#F6C8 /afii10846 16#04D9 /afii299 16#200E /afii300 16#200F /afii301 16#200D /afii57381 16#066A /afii57388 16#060C /afii57392 16#0660 /afii57393 16#0661 /afii57394 16#0662 /afii57395 16#0663 /afii57396 16#0664 /afii57397 16#0665 /afii57398 16#0666 /afii57399 16#0667 /afii57400 16#0668 /afii57401 16#0669 /afii57403 16#061B /afii57407 16#061F /afii57409 16#0621 /afii57410 16#0622 /afii57411 16#0623 /afii57412 16#0624 /afii57413 16#0625 /afii57414 16#0626 /afii57415 16#0627 /afii57416 16#0628 /afii57417 16#0629 /afii57418 16#062A /afii57419 16#062B /afii57420 16#062C /afii57421 16#062D /afii57422 16#062E /afii57423 16#062F /afii57424 16#0630 /afii57425 16#0631 /afii57426 16#0632 /afii57427 16#0633 /afii57428 16#0634 /afii57429 16#0635 /afii57430 16#0636 /afii57431 16#0637 /afii57432 16#0638 /afii57433 16#0639 /afii57434 16#063A /afii57440 16#0640 /afii57441 16#0641 /afii57442 16#0642 /afii57443 16#0643 /afii57444 16#0644 /afii57445 16#0645 /afii57446 16#0646 /afii57448 16#0648 /afii57449 16#0649 /afii57450 16#064A /afii57451 16#064B /afii57452 16#064C /afii57453 16#064D /afii57454 16#064E /afii57455 16#064F /afii57456 16#0650 /afii57457 16#0651 /afii57458 16#0652 /afii57470 16#0647 /afii57505 16#06A4 /afii57506 16#067E /afii57507 16#0686 /afii57508 16#0698 /afii57509 16#06AF /afii57511 16#0679 /afii57512 16#0688 /afii57513 16#0691 /afii57514 16#06BA /afii57519 16#06D2 /afii57534 16#06D5 /afii57636 16#20AA /afii57645 16#05BE /afii57658 16#05C3 /afii57664 16#05D0 /afii57665 16#05D1 /afii57666 16#05D2 /afii57667 16#05D3 /afii57668 16#05D4 /afii57669 16#05D5 /afii57670 16#05D6 /afii57671 16#05D7 /afii57672 16#05D8 /afii57673 16#05D9 /afii57674 16#05DA /afii57675 16#05DB /afii57676 16#05DC /afii57677 16#05DD /afii57678 16#05DE /afii57679 16#05DF /afii57680 16#05E0 /afii57681 16#05E1 /afii57682 16#05E2 /afii57683 16#05E3 /afii57684 16#05E4 /afii57685 16#05E5 /afii57686 16#05E6 /afii57687 16#05E7 /afii57688 16#05E8 /afii57689 16#05E9 /afii57690 16#05EA /afii57694 16#FB2A /afii57695 16#FB2B /afii57700 16#FB4B /afii57705 16#FB1F /afii57716 16#05F0 /afii57717 16#05F1 /afii57718 16#05F2 /afii57723 16#FB35 /afii57793 16#05B4 /afii57794 16#05B5 /afii57795 16#05B6 /afii57796 16#05BB /afii57797 16#05B8 /afii57798 16#05B7 /afii57799 16#05B0 /afii57800 16#05B2 /afii57801 16#05B1 /afii57802 16#05B3 /afii57803 16#05C2 /afii57804 16#05C1 /afii57806 16#05B9 /afii57807 16#05BC /afii57839 16#05BD /afii57841 16#05BF /afii57842 16#05C0 /afii57929 16#02BC /afii61248 16#2105 /afii61289 16#2113 /afii61352 16#2116 /afii61573 16#202C /afii61574 16#202D /afii61575 16#202E /afii61664 16#200C /afii63167 16#066D /afii64937 16#02BD /agrave 16#00E0 /agujarati 16#0A85 /agurmukhi 16#0A05 /ahiragana 16#3042 /ahookabove 16#1EA3 /aibengali 16#0990 /aibopomofo 16#311E /aideva 16#0910 /aiecyrillic 16#04D5 /aigujarati 16#0A90 /aigurmukhi 16#0A10 /aimatragurmukhi 16#0A48 /ainarabic 16#0639 /ainfinalarabic 16#FECA /aininitialarabic 16#FECB /ainmedialarabic 16#FECC /ainvertedbreve 16#0203 /aivowelsignbengali 16#09C8 /aivowelsigndeva 16#0948 /aivowelsigngujarati 16#0AC8 /akatakana 16#30A2 /akatakanahalfwidth 16#FF71 /akorean 16#314F /alef 16#05D0 /alefarabic 16#0627 /alefdageshhebrew 16#FB30 /aleffinalarabic 16#FE8E /alefhamzaabovearabic 16#0623 /alefhamzaabovefinalarabic 16#FE84 /alefhamzabelowarabic 16#0625 /alefhamzabelowfinalarabic 16#FE88 /alefhebrew 16#05D0 /aleflamedhebrew 16#FB4F /alefmaddaabovearabic 16#0622 /alefmaddaabovefinalarabic 16#FE82 /alefmaksuraarabic 16#0649 /alefmaksurafinalarabic 16#FEF0 /alefmaksurainitialarabic 16#FEF3 /alefmaksuramedialarabic 16#FEF4 /alefpatahhebrew 16#FB2E /alefqamatshebrew 16#FB2F /aleph 16#2135 /allequal 16#224C /alpha 16#03B1 /alphatonos 16#03AC /amacron 16#0101 /amonospace 16#FF41 /ampersand 16#0026 /ampersandmonospace 16#FF06 /ampersandsmall 16#F726 /amsquare 16#33C2 /anbopomofo 16#3122 /angbopomofo 16#3124 /angkhankhuthai 16#0E5A /angle 16#2220 /anglebracketleft 16#3008 /anglebracketleftvertical 16#FE3F /anglebracketright 16#3009 /anglebracketrightvertical 16#FE40 /angleleft 16#2329 /angleright 16#232A /angstrom 16#212B /anoteleia 16#0387 /anudattadeva 16#0952 /anusvarabengali 16#0982 /anusvaradeva 16#0902 /anusvaragujarati 16#0A82 /aogonek 16#0105 /apaatosquare 16#3300 /aparen 16#249C /apostrophearmenian 16#055A /apostrophemod 16#02BC /apple 16#F8FF /approaches 16#2250 /approxequal 16#2248 /approxequalorimage 16#2252 /approximatelyequal 16#2245 /araeaekorean 16#318E /araeakorean 16#318D /arc 16#2312 /arighthalfring 16#1E9A /aring 16#00E5 /aringacute 16#01FB /aringbelow 16#1E01 /arrowboth 16#2194 /arrowdashdown 16#21E3 /arrowdashleft 16#21E0 /arrowdashright 16#21E2 /arrowdashup 16#21E1 /arrowdblboth 16#21D4 /arrowdbldown 16#21D3 /arrowdblleft 16#21D0 /arrowdblright 16#21D2 /arrowdblup 16#21D1 /arrowdown 16#2193 /arrowdownleft 16#2199 /arrowdownright 16#2198 /arrowdownwhite 16#21E9 /arrowheaddownmod 16#02C5 /arrowheadleftmod 16#02C2 /arrowheadrightmod 16#02C3 /arrowheadupmod 16#02C4 /arrowhorizex 16#F8E7 /arrowleft 16#2190 /arrowleftdbl 16#21D0 /arrowleftdblstroke 16#21CD /arrowleftoverright 16#21C6 /arrowleftwhite 16#21E6 /arrowright 16#2192 /arrowrightdblstroke 16#21CF /arrowrightheavy 16#279E /arrowrightoverleft 16#21C4 /arrowrightwhite 16#21E8 /arrowtableft 16#21E4 /arrowtabright 16#21E5 /arrowup 16#2191 /arrowupdn 16#2195 /arrowupdnbse 16#21A8 /arrowupdownbase 16#21A8 /arrowupleft 16#2196 /arrowupleftofdown 16#21C5 /arrowupright 16#2197 /arrowupwhite 16#21E7 /arrowvertex 16#F8E6 /asciicircum 16#005E /asciicircummonospace 16#FF3E /asciitilde 16#007E /asciitildemonospace 16#FF5E /ascript 16#0251 /ascriptturned 16#0252 /asmallhiragana 16#3041 /asmallkatakana 16#30A1 /asmallkatakanahalfwidth 16#FF67 /asterisk 16#002A /asteriskaltonearabic 16#066D /asteriskarabic 16#066D /asteriskmath 16#2217 /asteriskmonospace 16#FF0A /asterisksmall 16#FE61 /asterism 16#2042 /asuperior 16#F6E9 /asymptoticallyequal 16#2243 /at 16#0040 /atilde 16#00E3 /atmonospace 16#FF20 /atsmall 16#FE6B /aturned 16#0250 /aubengali 16#0994 /aubopomofo 16#3120 /audeva 16#0914 /augujarati 16#0A94 /augurmukhi 16#0A14 /aulengthmarkbengali 16#09D7 /aumatragurmukhi 16#0A4C /auvowelsignbengali 16#09CC /auvowelsigndeva 16#094C /auvowelsigngujarati 16#0ACC /avagrahadeva 16#093D /aybarmenian 16#0561 /ayin 16#05E2 /ayinaltonehebrew 16#FB20 /ayinhebrew 16#05E2 /b 16#0062 /babengali 16#09AC /backslash 16#005C /backslashmonospace 16#FF3C /badeva 16#092C /bagujarati 16#0AAC /bagurmukhi 16#0A2C /bahiragana 16#3070 /bahtthai 16#0E3F /bakatakana 16#30D0 /bar 16#007C /barmonospace 16#FF5C /bbopomofo 16#3105 /bcircle 16#24D1 /bdotaccent 16#1E03 /bdotbelow 16#1E05 /beamedsixteenthnotes 16#266C /because 16#2235 /becyrillic 16#0431 /beharabic 16#0628 /behfinalarabic 16#FE90 /behinitialarabic 16#FE91 /behiragana 16#3079 /behmedialarabic 16#FE92 /behmeeminitialarabic 16#FC9F /behmeemisolatedarabic 16#FC08 /behnoonfinalarabic 16#FC6D /bekatakana 16#30D9 /benarmenian 16#0562 /bet 16#05D1 /beta 16#03B2 /betasymbolgreek 16#03D0 /betdagesh 16#FB31 /betdageshhebrew 16#FB31 /bethebrew 16#05D1 /betrafehebrew 16#FB4C /bhabengali 16#09AD /bhadeva 16#092D /bhagujarati 16#0AAD /bhagurmukhi 16#0A2D /bhook 16#0253 /bihiragana 16#3073 /bikatakana 16#30D3 /bilabialclick 16#0298 /bindigurmukhi 16#0A02 /birusquare 16#3331 /blackcircle 16#25CF /blackdiamond 16#25C6 /blackdownpointingtriangle 16#25BC /blackleftpointingpointer 16#25C4 /blackleftpointingtriangle 16#25C0 /blacklenticularbracketleft 16#3010 /blacklenticularbracketleftvertical 16#FE3B /blacklenticularbracketright 16#3011 /blacklenticularbracketrightvertical 16#FE3C /blacklowerlefttriangle 16#25E3 /blacklowerrighttriangle 16#25E2 /blackrectangle 16#25AC /blackrightpointingpointer 16#25BA /blackrightpointingtriangle 16#25B6 /blacksmallsquare 16#25AA /blacksmilingface 16#263B /blacksquare 16#25A0 /blackstar 16#2605 /blackupperlefttriangle 16#25E4 /blackupperrighttriangle 16#25E5 /blackuppointingsmalltriangle 16#25B4 /blackuppointingtriangle 16#25B2 /blank 16#2423 /blinebelow 16#1E07 /block 16#2588 /bmonospace 16#FF42 /bobaimaithai 16#0E1A /bohiragana 16#307C /bokatakana 16#30DC /bparen 16#249D /bqsquare 16#33C3 /braceex 16#F8F4 /braceleft 16#007B /braceleftbt 16#F8F3 /braceleftmid 16#F8F2 /braceleftmonospace 16#FF5B /braceleftsmall 16#FE5B /bracelefttp 16#F8F1 /braceleftvertical 16#FE37 /braceright 16#007D /bracerightbt 16#F8FE /bracerightmid 16#F8FD /bracerightmonospace 16#FF5D /bracerightsmall 16#FE5C /bracerighttp 16#F8FC /bracerightvertical 16#FE38 /bracketleft 16#005B /bracketleftbt 16#F8F0 /bracketleftex 16#F8EF /bracketleftmonospace 16#FF3B /bracketlefttp 16#F8EE /bracketright 16#005D /bracketrightbt 16#F8FB /bracketrightex 16#F8FA /bracketrightmonospace 16#FF3D /bracketrighttp 16#F8F9 /breve 16#02D8 /brevebelowcmb 16#032E /brevecmb 16#0306 /breveinvertedbelowcmb 16#032F /breveinvertedcmb 16#0311 /breveinverteddoublecmb 16#0361 /bridgebelowcmb 16#032A /bridgeinvertedbelowcmb 16#033A /brokenbar 16#00A6 /bstroke 16#0180 /bsuperior 16#F6EA /btopbar 16#0183 /buhiragana 16#3076 /bukatakana 16#30D6 /bullet 16#2022 /bulletinverse 16#25D8 /bulletoperator 16#2219 /bullseye 16#25CE /c 16#0063 /caarmenian 16#056E /cabengali 16#099A /cacute 16#0107 /cadeva 16#091A /cagujarati 16#0A9A /cagurmukhi 16#0A1A /calsquare 16#3388 /candrabindubengali 16#0981 /candrabinducmb 16#0310 /candrabindudeva 16#0901 /candrabindugujarati 16#0A81 /capslock 16#21EA /careof 16#2105 /caron 16#02C7 /caronbelowcmb 16#032C /caroncmb 16#030C /carriagereturn 16#21B5 /cbopomofo 16#3118 /ccaron 16#010D /ccedilla 16#00E7 /ccedillaacute 16#1E09 /ccircle 16#24D2 /ccircumflex 16#0109 /ccurl 16#0255 /cdot 16#010B /cdotaccent 16#010B /cdsquare 16#33C5 /cedilla 16#00B8 /cedillacmb 16#0327 /cent 16#00A2 /centigrade 16#2103 /centinferior 16#F6DF /centmonospace 16#FFE0 /centoldstyle 16#F7A2 /centsuperior 16#F6E0 /chaarmenian 16#0579 /chabengali 16#099B /chadeva 16#091B /chagujarati 16#0A9B /chagurmukhi 16#0A1B /chbopomofo 16#3114 /cheabkhasiancyrillic 16#04BD /checkmark 16#2713 /checyrillic 16#0447 /chedescenderabkhasiancyrillic 16#04BF /chedescendercyrillic 16#04B7 /chedieresiscyrillic 16#04F5 /cheharmenian 16#0573 /chekhakassiancyrillic 16#04CC /cheverticalstrokecyrillic 16#04B9 /chi 16#03C7 /chieuchacirclekorean 16#3277 /chieuchaparenkorean 16#3217 /chieuchcirclekorean 16#3269 /chieuchkorean 16#314A /chieuchparenkorean 16#3209 /chochangthai 16#0E0A /chochanthai 16#0E08 /chochingthai 16#0E09 /chochoethai 16#0E0C /chook 16#0188 /cieucacirclekorean 16#3276 /cieucaparenkorean 16#3216 /cieuccirclekorean 16#3268 /cieuckorean 16#3148 /cieucparenkorean 16#3208 /cieucuparenkorean 16#321C /circle 16#25CB /circlemultiply 16#2297 /circleot 16#2299 /circleplus 16#2295 /circlepostalmark 16#3036 /circlewithlefthalfblack 16#25D0 /circlewithrighthalfblack 16#25D1 /circumflex 16#02C6 /circumflexbelowcmb 16#032D /circumflexcmb 16#0302 /clear 16#2327 /clickalveolar 16#01C2 /clickdental 16#01C0 /clicklateral 16#01C1 /clickretroflex 16#01C3 /club 16#2663 /clubsuitblack 16#2663 /clubsuitwhite 16#2667 /cmcubedsquare 16#33A4 /cmonospace 16#FF43 /cmsquaredsquare 16#33A0 /coarmenian 16#0581 /colon 16#003A /colonmonetary 16#20A1 /colonmonospace 16#FF1A /colonsign 16#20A1 /colonsmall 16#FE55 /colontriangularhalfmod 16#02D1 /colontriangularmod 16#02D0 /comma 16#002C /commaabovecmb 16#0313 /commaaboverightcmb 16#0315 /commaaccent 16#F6C3 /commaarabic 16#060C /commaarmenian 16#055D /commainferior 16#F6E1 /commamonospace 16#FF0C /commareversedabovecmb 16#0314 /commareversedmod 16#02BD /commasmall 16#FE50 /commasuperior 16#F6E2 /commaturnedabovecmb 16#0312 /commaturnedmod 16#02BB /compass 16#263C /congruent 16#2245 /contourintegral 16#222E /control 16#2303 /controlACK 16#0006 /controlBEL 16#0007 /controlBS 16#0008 /controlCAN 16#0018 /controlCR 16#000D /controlDC1 16#0011 /controlDC2 16#0012 /controlDC3 16#0013 /controlDC4 16#0014 /controlDEL 16#007F /controlDLE 16#0010 /controlEM 16#0019 /controlENQ 16#0005 /controlEOT 16#0004 /controlESC 16#001B /controlETB 16#0017 /controlETX 16#0003 /controlFF 16#000C /controlFS 16#001C /controlGS 16#001D /controlHT 16#0009 /controlLF 16#000A /controlNAK 16#0015 /controlRS 16#001E /controlSI 16#000F /controlSO 16#000E /controlSOT 16#0002 /controlSTX 16#0001 /controlSUB 16#001A /controlSYN 16#0016 /controlUS 16#001F /controlVT 16#000B /copyright 16#00A9 /copyrightsans 16#F8E9 /copyrightserif 16#F6D9 /cornerbracketleft 16#300C /cornerbracketlefthalfwidth 16#FF62 /cornerbracketleftvertical 16#FE41 /cornerbracketright 16#300D /cornerbracketrighthalfwidth 16#FF63 /cornerbracketrightvertical 16#FE42 /corporationsquare 16#337F /cosquare 16#33C7 /coverkgsquare 16#33C6 /cparen 16#249E /cruzeiro 16#20A2 /cstretched 16#0297 /curlyand 16#22CF /curlyor 16#22CE /currency 16#00A4 /cyrBreve 16#F6D1 /cyrFlex 16#F6D2 /cyrbreve 16#F6D4 /cyrflex 16#F6D5 /d 16#0064 /daarmenian 16#0564 /dabengali 16#09A6 /dadarabic 16#0636 /dadeva 16#0926 /dadfinalarabic 16#FEBE /dadinitialarabic 16#FEBF /dadmedialarabic 16#FEC0 /dagesh 16#05BC /dageshhebrew 16#05BC /dagger 16#2020 /daggerdbl 16#2021 /dagujarati 16#0AA6 /dagurmukhi 16#0A26 /dahiragana 16#3060 /dakatakana 16#30C0 /dalarabic 16#062F /dalet 16#05D3 /daletdagesh 16#FB33 /daletdageshhebrew 16#FB33 % /dalethatafpatah 16#05D3 16#05B2 % /dalethatafpatahhebrew 16#05D3 16#05B2 % /dalethatafsegol 16#05D3 16#05B1 % /dalethatafsegolhebrew 16#05D3 16#05B1 /dalethebrew 16#05D3 % /dalethiriq 16#05D3 16#05B4 % /dalethiriqhebrew 16#05D3 16#05B4 % /daletholam 16#05D3 16#05B9 % /daletholamhebrew 16#05D3 16#05B9 % /daletpatah 16#05D3 16#05B7 % /daletpatahhebrew 16#05D3 16#05B7 % /daletqamats 16#05D3 16#05B8 % /daletqamatshebrew 16#05D3 16#05B8 % /daletqubuts 16#05D3 16#05BB % /daletqubutshebrew 16#05D3 16#05BB % /daletsegol 16#05D3 16#05B6 % /daletsegolhebrew 16#05D3 16#05B6 % /daletsheva 16#05D3 16#05B0 % /daletshevahebrew 16#05D3 16#05B0 % /dalettsere 16#05D3 16#05B5 % /dalettserehebrew 16#05D3 16#05B5 /dalfinalarabic 16#FEAA /dammaarabic 16#064F /dammalowarabic 16#064F /dammatanaltonearabic 16#064C /dammatanarabic 16#064C /danda 16#0964 /dargahebrew 16#05A7 /dargalefthebrew 16#05A7 /dasiapneumatacyrilliccmb 16#0485 /dblGrave 16#F6D3 /dblanglebracketleft 16#300A /dblanglebracketleftvertical 16#FE3D /dblanglebracketright 16#300B /dblanglebracketrightvertical 16#FE3E /dblarchinvertedbelowcmb 16#032B /dblarrowleft 16#21D4 /dblarrowright 16#21D2 /dbldanda 16#0965 /dblgrave 16#F6D6 /dblgravecmb 16#030F /dblintegral 16#222C /dbllowline 16#2017 /dbllowlinecmb 16#0333 /dbloverlinecmb 16#033F /dblprimemod 16#02BA /dblverticalbar 16#2016 /dblverticallineabovecmb 16#030E /dbopomofo 16#3109 /dbsquare 16#33C8 /dcaron 16#010F /dcedilla 16#1E11 /dcircle 16#24D3 /dcircumflexbelow 16#1E13 /dcroat 16#0111 /ddabengali 16#09A1 /ddadeva 16#0921 /ddagujarati 16#0AA1 /ddagurmukhi 16#0A21 /ddalarabic 16#0688 /ddalfinalarabic 16#FB89 /dddhadeva 16#095C /ddhabengali 16#09A2 /ddhadeva 16#0922 /ddhagujarati 16#0AA2 /ddhagurmukhi 16#0A22 /ddotaccent 16#1E0B /ddotbelow 16#1E0D /decimalseparatorarabic 16#066B /decimalseparatorpersian 16#066B /decyrillic 16#0434 /degree 16#00B0 /dehihebrew 16#05AD /dehiragana 16#3067 /deicoptic 16#03EF /dekatakana 16#30C7 /deleteleft 16#232B /deleteright 16#2326 /delta 16#03B4 /deltaturned 16#018D /denominatorminusonenumeratorbengali 16#09F8 /dezh 16#02A4 /dhabengali 16#09A7 /dhadeva 16#0927 /dhagujarati 16#0AA7 /dhagurmukhi 16#0A27 /dhook 16#0257 /dialytikatonos 16#0385 /dialytikatonoscmb 16#0344 /diamond 16#2666 /diamondsuitwhite 16#2662 /dieresis 16#00A8 /dieresisacute 16#F6D7 /dieresisbelowcmb 16#0324 /dieresiscmb 16#0308 /dieresisgrave 16#F6D8 /dieresistonos 16#0385 /dihiragana 16#3062 /dikatakana 16#30C2 /dittomark 16#3003 /divide 16#00F7 /divides 16#2223 /divisionslash 16#2215 /djecyrillic 16#0452 /dkshade 16#2593 /dlinebelow 16#1E0F /dlsquare 16#3397 /dmacron 16#0111 /dmonospace 16#FF44 /dnblock 16#2584 /dochadathai 16#0E0E /dodekthai 16#0E14 /dohiragana 16#3069 /dokatakana 16#30C9 /dollar 16#0024 /dollarinferior 16#F6E3 /dollarmonospace 16#FF04 /dollaroldstyle 16#F724 /dollarsmall 16#FE69 /dollarsuperior 16#F6E4 /dong 16#20AB /dorusquare 16#3326 /dotaccent 16#02D9 /dotaccentcmb 16#0307 /dotbelowcmb 16#0323 /dotbelowcomb 16#0323 /dotkatakana 16#30FB /dotlessi 16#0131 /dotlessj 16#F6BE /dotlessjstrokehook 16#0284 /dotmath 16#22C5 /dottedcircle 16#25CC /doubleyodpatah 16#FB1F /doubleyodpatahhebrew 16#FB1F /downtackbelowcmb 16#031E /downtackmod 16#02D5 /dparen 16#249F /dsuperior 16#F6EB /dtail 16#0256 /dtopbar 16#018C /duhiragana 16#3065 /dukatakana 16#30C5 /dz 16#01F3 /dzaltone 16#02A3 /dzcaron 16#01C6 /dzcurl 16#02A5 /dzeabkhasiancyrillic 16#04E1 /dzecyrillic 16#0455 /dzhecyrillic 16#045F /e 16#0065 /eacute 16#00E9 /earth 16#2641 /ebengali 16#098F /ebopomofo 16#311C /ebreve 16#0115 /ecandradeva 16#090D /ecandragujarati 16#0A8D /ecandravowelsigndeva 16#0945 /ecandravowelsigngujarati 16#0AC5 /ecaron 16#011B /ecedillabreve 16#1E1D /echarmenian 16#0565 /echyiwnarmenian 16#0587 /ecircle 16#24D4 /ecircumflex 16#00EA /ecircumflexacute 16#1EBF /ecircumflexbelow 16#1E19 /ecircumflexdotbelow 16#1EC7 /ecircumflexgrave 16#1EC1 /ecircumflexhookabove 16#1EC3 /ecircumflextilde 16#1EC5 /ecyrillic 16#0454 /edblgrave 16#0205 /edeva 16#090F /edieresis 16#00EB /edot 16#0117 /edotaccent 16#0117 /edotbelow 16#1EB9 /eegurmukhi 16#0A0F /eematragurmukhi 16#0A47 /efcyrillic 16#0444 /egrave 16#00E8 /egujarati 16#0A8F /eharmenian 16#0567 /ehbopomofo 16#311D /ehiragana 16#3048 /ehookabove 16#1EBB /eibopomofo 16#311F /eight 16#0038 /eightarabic 16#0668 /eightbengali 16#09EE /eightcircle 16#2467 /eightcircleinversesansserif 16#2791 /eightdeva 16#096E /eighteencircle 16#2471 /eighteenparen 16#2485 /eighteenperiod 16#2499 /eightgujarati 16#0AEE /eightgurmukhi 16#0A6E /eighthackarabic 16#0668 /eighthangzhou 16#3028 /eighthnotebeamed 16#266B /eightideographicparen 16#3227 /eightinferior 16#2088 /eightmonospace 16#FF18 /eightoldstyle 16#F738 /eightparen 16#247B /eightperiod 16#248F /eightpersian 16#06F8 /eightroman 16#2177 /eightsuperior 16#2078 /eightthai 16#0E58 /einvertedbreve 16#0207 /eiotifiedcyrillic 16#0465 /ekatakana 16#30A8 /ekatakanahalfwidth 16#FF74 /ekonkargurmukhi 16#0A74 /ekorean 16#3154 /elcyrillic 16#043B /element 16#2208 /elevencircle 16#246A /elevenparen 16#247E /elevenperiod 16#2492 /elevenroman 16#217A /ellipsis 16#2026 /ellipsisvertical 16#22EE /emacron 16#0113 /emacronacute 16#1E17 /emacrongrave 16#1E15 /emcyrillic 16#043C /emdash 16#2014 /emdashvertical 16#FE31 /emonospace 16#FF45 /emphasismarkarmenian 16#055B /emptyset 16#2205 /enbopomofo 16#3123 /encyrillic 16#043D /endash 16#2013 /endashvertical 16#FE32 /endescendercyrillic 16#04A3 /eng 16#014B /engbopomofo 16#3125 /enghecyrillic 16#04A5 /enhookcyrillic 16#04C8 /enspace 16#2002 /eogonek 16#0119 /eokorean 16#3153 /eopen 16#025B /eopenclosed 16#029A /eopenreversed 16#025C /eopenreversedclosed 16#025E /eopenreversedhook 16#025D /eparen 16#24A0 /epsilon 16#03B5 /epsilontonos 16#03AD /equal 16#003D /equalmonospace 16#FF1D /equalsmall 16#FE66 /equalsuperior 16#207C /equivalence 16#2261 /erbopomofo 16#3126 /ercyrillic 16#0440 /ereversed 16#0258 /ereversedcyrillic 16#044D /escyrillic 16#0441 /esdescendercyrillic 16#04AB /esh 16#0283 /eshcurl 16#0286 /eshortdeva 16#090E /eshortvowelsigndeva 16#0946 /eshreversedloop 16#01AA /eshsquatreversed 16#0285 /esmallhiragana 16#3047 /esmallkatakana 16#30A7 /esmallkatakanahalfwidth 16#FF6A /estimated 16#212E /esuperior 16#F6EC /eta 16#03B7 /etarmenian 16#0568 /etatonos 16#03AE /eth 16#00F0 /etilde 16#1EBD /etildebelow 16#1E1B /etnahtafoukhhebrew 16#0591 /etnahtafoukhlefthebrew 16#0591 /etnahtahebrew 16#0591 /etnahtalefthebrew 16#0591 /eturned 16#01DD /eukorean 16#3161 /euro 16#20AC /evowelsignbengali 16#09C7 /evowelsigndeva 16#0947 /evowelsigngujarati 16#0AC7 /exclam 16#0021 /exclamarmenian 16#055C /exclamdbl 16#203C /exclamdown 16#00A1 /exclamdownsmall 16#F7A1 /exclammonospace 16#FF01 /exclamsmall 16#F721 /existential 16#2203 /ezh 16#0292 /ezhcaron 16#01EF /ezhcurl 16#0293 /ezhreversed 16#01B9 /ezhtail 16#01BA /f 16#0066 /fadeva 16#095E /fagurmukhi 16#0A5E /fahrenheit 16#2109 /fathaarabic 16#064E /fathalowarabic 16#064E /fathatanarabic 16#064B /fbopomofo 16#3108 /fcircle 16#24D5 /fdotaccent 16#1E1F /feharabic 16#0641 /feharmenian 16#0586 /fehfinalarabic 16#FED2 /fehinitialarabic 16#FED3 /fehmedialarabic 16#FED4 /feicoptic 16#03E5 /female 16#2640 /ff 16#FB00 /ffi 16#FB03 /ffl 16#FB04 /fi 16#FB01 /fifteencircle 16#246E /fifteenparen 16#2482 /fifteenperiod 16#2496 /figuredash 16#2012 /filledbox 16#25A0 /filledrect 16#25AC /finalkaf 16#05DA /finalkafdagesh 16#FB3A /finalkafdageshhebrew 16#FB3A /finalkafhebrew 16#05DA % /finalkafqamats 16#05DA 16#05B8 % /finalkafqamatshebrew 16#05DA 16#05B8 % /finalkafsheva 16#05DA 16#05B0 % /finalkafshevahebrew 16#05DA 16#05B0 /finalmem 16#05DD /finalmemhebrew 16#05DD /finalnun 16#05DF /finalnunhebrew 16#05DF /finalpe 16#05E3 /finalpehebrew 16#05E3 /finaltsadi 16#05E5 /finaltsadihebrew 16#05E5 /firsttonechinese 16#02C9 /fisheye 16#25C9 /fitacyrillic 16#0473 /five 16#0035 /fivearabic 16#0665 /fivebengali 16#09EB /fivecircle 16#2464 /fivecircleinversesansserif 16#278E /fivedeva 16#096B /fiveeighths 16#215D /fivegujarati 16#0AEB /fivegurmukhi 16#0A6B /fivehackarabic 16#0665 /fivehangzhou 16#3025 /fiveideographicparen 16#3224 /fiveinferior 16#2085 /fivemonospace 16#FF15 /fiveoldstyle 16#F735 /fiveparen 16#2478 /fiveperiod 16#248C /fivepersian 16#06F5 /fiveroman 16#2174 /fivesuperior 16#2075 /fivethai 16#0E55 /fl 16#FB02 /florin 16#0192 /fmonospace 16#FF46 /fmsquare 16#3399 /fofanthai 16#0E1F /fofathai 16#0E1D /fongmanthai 16#0E4F /forall 16#2200 /four 16#0034 /fourarabic 16#0664 /fourbengali 16#09EA /fourcircle 16#2463 /fourcircleinversesansserif 16#278D /fourdeva 16#096A /fourgujarati 16#0AEA /fourgurmukhi 16#0A6A /fourhackarabic 16#0664 /fourhangzhou 16#3024 /fourideographicparen 16#3223 /fourinferior 16#2084 /fourmonospace 16#FF14 /fournumeratorbengali 16#09F7 /fouroldstyle 16#F734 /fourparen 16#2477 /fourperiod 16#248B /fourpersian 16#06F4 /fourroman 16#2173 /foursuperior 16#2074 /fourteencircle 16#246D /fourteenparen 16#2481 /fourteenperiod 16#2495 /fourthai 16#0E54 /fourthtonechinese 16#02CB /fparen 16#24A1 /fraction 16#2044 /franc 16#20A3 /g 16#0067 /gabengali 16#0997 /gacute 16#01F5 /gadeva 16#0917 /gafarabic 16#06AF /gaffinalarabic 16#FB93 /gafinitialarabic 16#FB94 /gafmedialarabic 16#FB95 /gagujarati 16#0A97 /gagurmukhi 16#0A17 /gahiragana 16#304C /gakatakana 16#30AC /gamma 16#03B3 /gammalatinsmall 16#0263 /gammasuperior 16#02E0 /gangiacoptic 16#03EB /gbopomofo 16#310D /gbreve 16#011F /gcaron 16#01E7 /gcedilla 16#0123 /gcircle 16#24D6 /gcircumflex 16#011D /gcommaaccent 16#0123 /gdot 16#0121 /gdotaccent 16#0121 /gecyrillic 16#0433 /gehiragana 16#3052 /gekatakana 16#30B2 /geometricallyequal 16#2251 /gereshaccenthebrew 16#059C /gereshhebrew 16#05F3 /gereshmuqdamhebrew 16#059D /germandbls 16#00DF /gershayimaccenthebrew 16#059E /gershayimhebrew 16#05F4 /getamark 16#3013 /ghabengali 16#0998 /ghadarmenian 16#0572 /ghadeva 16#0918 /ghagujarati 16#0A98 /ghagurmukhi 16#0A18 /ghainarabic 16#063A /ghainfinalarabic 16#FECE /ghaininitialarabic 16#FECF /ghainmedialarabic 16#FED0 /ghemiddlehookcyrillic 16#0495 /ghestrokecyrillic 16#0493 /gheupturncyrillic 16#0491 /ghhadeva 16#095A /ghhagurmukhi 16#0A5A /ghook 16#0260 /ghzsquare 16#3393 /gihiragana 16#304E /gikatakana 16#30AE /gimarmenian 16#0563 /gimel 16#05D2 /gimeldagesh 16#FB32 /gimeldageshhebrew 16#FB32 /gimelhebrew 16#05D2 /gjecyrillic 16#0453 /glottalinvertedstroke 16#01BE /glottalstop 16#0294 /glottalstopinverted 16#0296 /glottalstopmod 16#02C0 /glottalstopreversed 16#0295 /glottalstopreversedmod 16#02C1 /glottalstopreversedsuperior 16#02E4 /glottalstopstroke 16#02A1 /glottalstopstrokereversed 16#02A2 /gmacron 16#1E21 /gmonospace 16#FF47 /gohiragana 16#3054 /gokatakana 16#30B4 /gparen 16#24A2 /gpasquare 16#33AC /gradient 16#2207 /grave 16#0060 /gravebelowcmb 16#0316 /gravecmb 16#0300 /gravecomb 16#0300 /gravedeva 16#0953 /gravelowmod 16#02CE /gravemonospace 16#FF40 /gravetonecmb 16#0340 /greater 16#003E /greaterequal 16#2265 /greaterequalorless 16#22DB /greatermonospace 16#FF1E /greaterorequivalent 16#2273 /greaterorless 16#2277 /greateroverequal 16#2267 /greatersmall 16#FE65 /gscript 16#0261 /gstroke 16#01E5 /guhiragana 16#3050 /guillemotleft 16#00AB /guillemotright 16#00BB /guilsinglleft 16#2039 /guilsinglright 16#203A /gukatakana 16#30B0 /guramusquare 16#3318 /gysquare 16#33C9 /h 16#0068 /haabkhasiancyrillic 16#04A9 /haaltonearabic 16#06C1 /habengali 16#09B9 /hadescendercyrillic 16#04B3 /hadeva 16#0939 /hagujarati 16#0AB9 /hagurmukhi 16#0A39 /haharabic 16#062D /hahfinalarabic 16#FEA2 /hahinitialarabic 16#FEA3 /hahiragana 16#306F /hahmedialarabic 16#FEA4 /haitusquare 16#332A /hakatakana 16#30CF /hakatakanahalfwidth 16#FF8A /halantgurmukhi 16#0A4D /hamzaarabic 16#0621 % /hamzadammaarabic 16#0621 16#064F % /hamzadammatanarabic 16#0621 16#064C % /hamzafathaarabic 16#0621 16#064E % /hamzafathatanarabic 16#0621 16#064B /hamzalowarabic 16#0621 % /hamzalowkasraarabic 16#0621 16#0650 % /hamzalowkasratanarabic 16#0621 16#064D % /hamzasukunarabic 16#0621 16#0652 /hangulfiller 16#3164 /hardsigncyrillic 16#044A /harpoonleftbarbup 16#21BC /harpoonrightbarbup 16#21C0 /hasquare 16#33CA /hatafpatah 16#05B2 /hatafpatah16 16#05B2 /hatafpatah23 16#05B2 /hatafpatah2f 16#05B2 /hatafpatahhebrew 16#05B2 /hatafpatahnarrowhebrew 16#05B2 /hatafpatahquarterhebrew 16#05B2 /hatafpatahwidehebrew 16#05B2 /hatafqamats 16#05B3 /hatafqamats1b 16#05B3 /hatafqamats28 16#05B3 /hatafqamats34 16#05B3 /hatafqamatshebrew 16#05B3 /hatafqamatsnarrowhebrew 16#05B3 /hatafqamatsquarterhebrew 16#05B3 /hatafqamatswidehebrew 16#05B3 /hatafsegol 16#05B1 /hatafsegol17 16#05B1 /hatafsegol24 16#05B1 /hatafsegol30 16#05B1 /hatafsegolhebrew 16#05B1 /hatafsegolnarrowhebrew 16#05B1 /hatafsegolquarterhebrew 16#05B1 /hatafsegolwidehebrew 16#05B1 /hbar 16#0127 /hbopomofo 16#310F /hbrevebelow 16#1E2B /hcedilla 16#1E29 /hcircle 16#24D7 /hcircumflex 16#0125 /hdieresis 16#1E27 /hdotaccent 16#1E23 /hdotbelow 16#1E25 /he 16#05D4 /heart 16#2665 /heartsuitblack 16#2665 /heartsuitwhite 16#2661 /hedagesh 16#FB34 /hedageshhebrew 16#FB34 /hehaltonearabic 16#06C1 /heharabic 16#0647 /hehebrew 16#05D4 /hehfinalaltonearabic 16#FBA7 /hehfinalalttwoarabic 16#FEEA /hehfinalarabic 16#FEEA /hehhamzaabovefinalarabic 16#FBA5 /hehhamzaaboveisolatedarabic 16#FBA4 /hehinitialaltonearabic 16#FBA8 /hehinitialarabic 16#FEEB /hehiragana 16#3078 /hehmedialaltonearabic 16#FBA9 /hehmedialarabic 16#FEEC /heiseierasquare 16#337B /hekatakana 16#30D8 /hekatakanahalfwidth 16#FF8D /hekutaarusquare 16#3336 /henghook 16#0267 /herutusquare 16#3339 /het 16#05D7 /hethebrew 16#05D7 /hhook 16#0266 /hhooksuperior 16#02B1 /hieuhacirclekorean 16#327B /hieuhaparenkorean 16#321B /hieuhcirclekorean 16#326D /hieuhkorean 16#314E /hieuhparenkorean 16#320D /hihiragana 16#3072 /hikatakana 16#30D2 /hikatakanahalfwidth 16#FF8B /hiriq 16#05B4 /hiriq14 16#05B4 /hiriq21 16#05B4 /hiriq2d 16#05B4 /hiriqhebrew 16#05B4 /hiriqnarrowhebrew 16#05B4 /hiriqquarterhebrew 16#05B4 /hiriqwidehebrew 16#05B4 /hlinebelow 16#1E96 /hmonospace 16#FF48 /hoarmenian 16#0570 /hohipthai 16#0E2B /hohiragana 16#307B /hokatakana 16#30DB /hokatakanahalfwidth 16#FF8E /holam 16#05B9 /holam19 16#05B9 /holam26 16#05B9 /holam32 16#05B9 /holamhebrew 16#05B9 /holamnarrowhebrew 16#05B9 /holamquarterhebrew 16#05B9 /holamwidehebrew 16#05B9 /honokhukthai 16#0E2E /hookabovecomb 16#0309 /hookcmb 16#0309 /hookpalatalizedbelowcmb 16#0321 /hookretroflexbelowcmb 16#0322 /hoonsquare 16#3342 /horicoptic 16#03E9 /horizontalbar 16#2015 /horncmb 16#031B /hotsprings 16#2668 /house 16#2302 /hparen 16#24A3 /hsuperior 16#02B0 /hturned 16#0265 /huhiragana 16#3075 /huiitosquare 16#3333 /hukatakana 16#30D5 /hukatakanahalfwidth 16#FF8C /hungarumlaut 16#02DD /hungarumlautcmb 16#030B /hv 16#0195 /hyphen 16#002D /hypheninferior 16#F6E5 /hyphenmonospace 16#FF0D /hyphensmall 16#FE63 /hyphensuperior 16#F6E6 /hyphentwo 16#2010 /i 16#0069 /iacute 16#00ED /iacyrillic 16#044F /ibengali 16#0987 /ibopomofo 16#3127 /ibreve 16#012D /icaron 16#01D0 /icircle 16#24D8 /icircumflex 16#00EE /icyrillic 16#0456 /idblgrave 16#0209 /ideographearthcircle 16#328F /ideographfirecircle 16#328B /ideographicallianceparen 16#323F /ideographiccallparen 16#323A /ideographiccentrecircle 16#32A5 /ideographicclose 16#3006 /ideographiccomma 16#3001 /ideographiccommaleft 16#FF64 /ideographiccongratulationparen 16#3237 /ideographiccorrectcircle 16#32A3 /ideographicearthparen 16#322F /ideographicenterpriseparen 16#323D /ideographicexcellentcircle 16#329D /ideographicfestivalparen 16#3240 /ideographicfinancialcircle 16#3296 /ideographicfinancialparen 16#3236 /ideographicfireparen 16#322B /ideographichaveparen 16#3232 /ideographichighcircle 16#32A4 /ideographiciterationmark 16#3005 /ideographiclaborcircle 16#3298 /ideographiclaborparen 16#3238 /ideographicleftcircle 16#32A7 /ideographiclowcircle 16#32A6 /ideographicmedicinecircle 16#32A9 /ideographicmetalparen 16#322E /ideographicmoonparen 16#322A /ideographicnameparen 16#3234 /ideographicperiod 16#3002 /ideographicprintcircle 16#329E /ideographicreachparen 16#3243 /ideographicrepresentparen 16#3239 /ideographicresourceparen 16#323E /ideographicrightcircle 16#32A8 /ideographicsecretcircle 16#3299 /ideographicselfparen 16#3242 /ideographicsocietyparen 16#3233 /ideographicspace 16#3000 /ideographicspecialparen 16#3235 /ideographicstockparen 16#3231 /ideographicstudyparen 16#323B /ideographicsunparen 16#3230 /ideographicsuperviseparen 16#323C /ideographicwaterparen 16#322C /ideographicwoodparen 16#322D /ideographiczero 16#3007 /ideographmetalcircle 16#328E /ideographmooncircle 16#328A /ideographnamecircle 16#3294 /ideographsuncircle 16#3290 /ideographwatercircle 16#328C /ideographwoodcircle 16#328D /ideva 16#0907 /idieresis 16#00EF /idieresisacute 16#1E2F /idieresiscyrillic 16#04E5 /idotbelow 16#1ECB /iebrevecyrillic 16#04D7 /iecyrillic 16#0435 /ieungacirclekorean 16#3275 /ieungaparenkorean 16#3215 /ieungcirclekorean 16#3267 /ieungkorean 16#3147 /ieungparenkorean 16#3207 /igrave 16#00EC /igujarati 16#0A87 /igurmukhi 16#0A07 /ihiragana 16#3044 /ihookabove 16#1EC9 /iibengali 16#0988 /iicyrillic 16#0438 /iideva 16#0908 /iigujarati 16#0A88 /iigurmukhi 16#0A08 /iimatragurmukhi 16#0A40 /iinvertedbreve 16#020B /iishortcyrillic 16#0439 /iivowelsignbengali 16#09C0 /iivowelsigndeva 16#0940 /iivowelsigngujarati 16#0AC0 /ij 16#0133 /ikatakana 16#30A4 /ikatakanahalfwidth 16#FF72 /ikorean 16#3163 /ilde 16#02DC /iluyhebrew 16#05AC /imacron 16#012B /imacroncyrillic 16#04E3 /imageorapproximatelyequal 16#2253 /imatragurmukhi 16#0A3F /imonospace 16#FF49 /increment 16#2206 /infinity 16#221E /iniarmenian 16#056B /integral 16#222B /integralbottom 16#2321 /integralbt 16#2321 /integralex 16#F8F5 /integraltop 16#2320 /integraltp 16#2320 /intersection 16#2229 /intisquare 16#3305 /invbullet 16#25D8 /invcircle 16#25D9 /invsmileface 16#263B /iocyrillic 16#0451 /iogonek 16#012F /iota 16#03B9 /iotadieresis 16#03CA /iotadieresistonos 16#0390 /iotalatin 16#0269 /iotatonos 16#03AF /iparen 16#24A4 /irigurmukhi 16#0A72 /ismallhiragana 16#3043 /ismallkatakana 16#30A3 /ismallkatakanahalfwidth 16#FF68 /issharbengali 16#09FA /istroke 16#0268 /isuperior 16#F6ED /iterationhiragana 16#309D /iterationkatakana 16#30FD /itilde 16#0129 /itildebelow 16#1E2D /iubopomofo 16#3129 /iucyrillic 16#044E /ivowelsignbengali 16#09BF /ivowelsigndeva 16#093F /ivowelsigngujarati 16#0ABF /izhitsacyrillic 16#0475 /izhitsadblgravecyrillic 16#0477 /j 16#006A /jaarmenian 16#0571 /jabengali 16#099C /jadeva 16#091C /jagujarati 16#0A9C /jagurmukhi 16#0A1C /jbopomofo 16#3110 /jcaron 16#01F0 /jcircle 16#24D9 /jcircumflex 16#0135 /jcrossedtail 16#029D /jdotlessstroke 16#025F /jecyrillic 16#0458 /jeemarabic 16#062C /jeemfinalarabic 16#FE9E /jeeminitialarabic 16#FE9F /jeemmedialarabic 16#FEA0 /jeharabic 16#0698 /jehfinalarabic 16#FB8B /jhabengali 16#099D /jhadeva 16#091D /jhagujarati 16#0A9D /jhagurmukhi 16#0A1D /jheharmenian 16#057B /jis 16#3004 /jmonospace 16#FF4A /jparen 16#24A5 /jsuperior 16#02B2 /k 16#006B /kabashkircyrillic 16#04A1 /kabengali 16#0995 /kacute 16#1E31 /kacyrillic 16#043A /kadescendercyrillic 16#049B /kadeva 16#0915 /kaf 16#05DB /kafarabic 16#0643 /kafdagesh 16#FB3B /kafdageshhebrew 16#FB3B /kaffinalarabic 16#FEDA /kafhebrew 16#05DB /kafinitialarabic 16#FEDB /kafmedialarabic 16#FEDC /kafrafehebrew 16#FB4D /kagujarati 16#0A95 /kagurmukhi 16#0A15 /kahiragana 16#304B /kahookcyrillic 16#04C4 /kakatakana 16#30AB /kakatakanahalfwidth 16#FF76 /kappa 16#03BA /kappasymbolgreek 16#03F0 /kapyeounmieumkorean 16#3171 /kapyeounphieuphkorean 16#3184 /kapyeounpieupkorean 16#3178 /kapyeounssangpieupkorean 16#3179 /karoriisquare 16#330D /kashidaautoarabic 16#0640 /kashidaautonosidebearingarabic 16#0640 /kasmallkatakana 16#30F5 /kasquare 16#3384 /kasraarabic 16#0650 /kasratanarabic 16#064D /kastrokecyrillic 16#049F /katahiraprolongmarkhalfwidth 16#FF70 /kaverticalstrokecyrillic 16#049D /kbopomofo 16#310E /kcalsquare 16#3389 /kcaron 16#01E9 /kcedilla 16#0137 /kcircle 16#24DA /kcommaaccent 16#0137 /kdotbelow 16#1E33 /keharmenian 16#0584 /kehiragana 16#3051 /kekatakana 16#30B1 /kekatakanahalfwidth 16#FF79 /kenarmenian 16#056F /kesmallkatakana 16#30F6 /kgreenlandic 16#0138 /khabengali 16#0996 /khacyrillic 16#0445 /khadeva 16#0916 /khagujarati 16#0A96 /khagurmukhi 16#0A16 /khaharabic 16#062E /khahfinalarabic 16#FEA6 /khahinitialarabic 16#FEA7 /khahmedialarabic 16#FEA8 /kheicoptic 16#03E7 /khhadeva 16#0959 /khhagurmukhi 16#0A59 /khieukhacirclekorean 16#3278 /khieukhaparenkorean 16#3218 /khieukhcirclekorean 16#326A /khieukhkorean 16#314B /khieukhparenkorean 16#320A /khokhaithai 16#0E02 /khokhonthai 16#0E05 /khokhuatthai 16#0E03 /khokhwaithai 16#0E04 /khomutthai 16#0E5B /khook 16#0199 /khorakhangthai 16#0E06 /khzsquare 16#3391 /kihiragana 16#304D /kikatakana 16#30AD /kikatakanahalfwidth 16#FF77 /kiroguramusquare 16#3315 /kiromeetorusquare 16#3316 /kirosquare 16#3314 /kiyeokacirclekorean 16#326E /kiyeokaparenkorean 16#320E /kiyeokcirclekorean 16#3260 /kiyeokkorean 16#3131 /kiyeokparenkorean 16#3200 /kiyeoksioskorean 16#3133 /kjecyrillic 16#045C /klinebelow 16#1E35 /klsquare 16#3398 /kmcubedsquare 16#33A6 /kmonospace 16#FF4B /kmsquaredsquare 16#33A2 /kohiragana 16#3053 /kohmsquare 16#33C0 /kokaithai 16#0E01 /kokatakana 16#30B3 /kokatakanahalfwidth 16#FF7A /kooposquare 16#331E /koppacyrillic 16#0481 /koreanstandardsymbol 16#327F /koroniscmb 16#0343 /kparen 16#24A6 /kpasquare 16#33AA /ksicyrillic 16#046F /ktsquare 16#33CF /kturned 16#029E /kuhiragana 16#304F /kukatakana 16#30AF /kukatakanahalfwidth 16#FF78 /kvsquare 16#33B8 /kwsquare 16#33BE /l 16#006C /labengali 16#09B2 /lacute 16#013A /ladeva 16#0932 /lagujarati 16#0AB2 /lagurmukhi 16#0A32 /lakkhangyaothai 16#0E45 /lamaleffinalarabic 16#FEFC /lamalefhamzaabovefinalarabic 16#FEF8 /lamalefhamzaaboveisolatedarabic 16#FEF7 /lamalefhamzabelowfinalarabic 16#FEFA /lamalefhamzabelowisolatedarabic 16#FEF9 /lamalefisolatedarabic 16#FEFB /lamalefmaddaabovefinalarabic 16#FEF6 /lamalefmaddaaboveisolatedarabic 16#FEF5 /lamarabic 16#0644 /lambda 16#03BB /lambdastroke 16#019B /lamed 16#05DC /lameddagesh 16#FB3C /lameddageshhebrew 16#FB3C /lamedhebrew 16#05DC % /lamedholam 16#05DC 16#05B9 % /lamedholamdagesh 16#05DC 16#05B9 16#05BC % /lamedholamdageshhebrew 16#05DC 16#05B9 16#05BC % /lamedholamhebrew 16#05DC 16#05B9 /lamfinalarabic 16#FEDE /lamhahinitialarabic 16#FCCA /laminitialarabic 16#FEDF /lamjeeminitialarabic 16#FCC9 /lamkhahinitialarabic 16#FCCB /lamlamhehisolatedarabic 16#FDF2 /lammedialarabic 16#FEE0 /lammeemhahinitialarabic 16#FD88 /lammeeminitialarabic 16#FCCC % /lammeemjeeminitialarabic 16#FEDF 16#FEE4 16#FEA0 % /lammeemkhahinitialarabic 16#FEDF 16#FEE4 16#FEA8 /largecircle 16#25EF /lbar 16#019A /lbelt 16#026C /lbopomofo 16#310C /lcaron 16#013E /lcedilla 16#013C /lcircle 16#24DB /lcircumflexbelow 16#1E3D /lcommaaccent 16#013C /ldot 16#0140 /ldotaccent 16#0140 /ldotbelow 16#1E37 /ldotbelowmacron 16#1E39 /leftangleabovecmb 16#031A /lefttackbelowcmb 16#0318 /less 16#003C /lessequal 16#2264 /lessequalorgreater 16#22DA /lessmonospace 16#FF1C /lessorequivalent 16#2272 /lessorgreater 16#2276 /lessoverequal 16#2266 /lesssmall 16#FE64 /lezh 16#026E /lfblock 16#258C /lhookretroflex 16#026D /lira 16#20A4 /liwnarmenian 16#056C /lj 16#01C9 /ljecyrillic 16#0459 /ll 16#F6C0 /lladeva 16#0933 /llagujarati 16#0AB3 /llinebelow 16#1E3B /llladeva 16#0934 /llvocalicbengali 16#09E1 /llvocalicdeva 16#0961 /llvocalicvowelsignbengali 16#09E3 /llvocalicvowelsigndeva 16#0963 /lmiddletilde 16#026B /lmonospace 16#FF4C /lmsquare 16#33D0 /lochulathai 16#0E2C /logicaland 16#2227 /logicalnot 16#00AC /logicalnotreversed 16#2310 /logicalor 16#2228 /lolingthai 16#0E25 /longs 16#017F /lowlinecenterline 16#FE4E /lowlinecmb 16#0332 /lowlinedashed 16#FE4D /lozenge 16#25CA /lparen 16#24A7 /lslash 16#0142 /lsquare 16#2113 /lsuperior 16#F6EE /ltshade 16#2591 /luthai 16#0E26 /lvocalicbengali 16#098C /lvocalicdeva 16#090C /lvocalicvowelsignbengali 16#09E2 /lvocalicvowelsigndeva 16#0962 /lxsquare 16#33D3 /m 16#006D /mabengali 16#09AE /macron 16#00AF /macronbelowcmb 16#0331 /macroncmb 16#0304 /macronlowmod 16#02CD /macronmonospace 16#FFE3 /macute 16#1E3F /madeva 16#092E /magujarati 16#0AAE /magurmukhi 16#0A2E /mahapakhhebrew 16#05A4 /mahapakhlefthebrew 16#05A4 /mahiragana 16#307E /maichattawalowleftthai 16#F895 /maichattawalowrightthai 16#F894 /maichattawathai 16#0E4B /maichattawaupperleftthai 16#F893 /maieklowleftthai 16#F88C /maieklowrightthai 16#F88B /maiekthai 16#0E48 /maiekupperleftthai 16#F88A /maihanakatleftthai 16#F884 /maihanakatthai 16#0E31 /maitaikhuleftthai 16#F889 /maitaikhuthai 16#0E47 /maitholowleftthai 16#F88F /maitholowrightthai 16#F88E /maithothai 16#0E49 /maithoupperleftthai 16#F88D /maitrilowleftthai 16#F892 /maitrilowrightthai 16#F891 /maitrithai 16#0E4A /maitriupperleftthai 16#F890 /maiyamokthai 16#0E46 /makatakana 16#30DE /makatakanahalfwidth 16#FF8F /male 16#2642 /mansyonsquare 16#3347 /maqafhebrew 16#05BE /mars 16#2642 /masoracirclehebrew 16#05AF /masquare 16#3383 /mbopomofo 16#3107 /mbsquare 16#33D4 /mcircle 16#24DC /mcubedsquare 16#33A5 /mdotaccent 16#1E41 /mdotbelow 16#1E43 /meemarabic 16#0645 /meemfinalarabic 16#FEE2 /meeminitialarabic 16#FEE3 /meemmedialarabic 16#FEE4 /meemmeeminitialarabic 16#FCD1 /meemmeemisolatedarabic 16#FC48 /meetorusquare 16#334D /mehiragana 16#3081 /meizierasquare 16#337E /mekatakana 16#30E1 /mekatakanahalfwidth 16#FF92 /mem 16#05DE /memdagesh 16#FB3E /memdageshhebrew 16#FB3E /memhebrew 16#05DE /menarmenian 16#0574 /merkhahebrew 16#05A5 /merkhakefulahebrew 16#05A6 /merkhakefulalefthebrew 16#05A6 /merkhalefthebrew 16#05A5 /mhook 16#0271 /mhzsquare 16#3392 /middledotkatakanahalfwidth 16#FF65 /middot 16#00B7 /mieumacirclekorean 16#3272 /mieumaparenkorean 16#3212 /mieumcirclekorean 16#3264 /mieumkorean 16#3141 /mieumpansioskorean 16#3170 /mieumparenkorean 16#3204 /mieumpieupkorean 16#316E /mieumsioskorean 16#316F /mihiragana 16#307F /mikatakana 16#30DF /mikatakanahalfwidth 16#FF90 /minus 16#2212 /minusbelowcmb 16#0320 /minuscircle 16#2296 /minusmod 16#02D7 /minusplus 16#2213 /minute 16#2032 /miribaarusquare 16#334A /mirisquare 16#3349 /mlonglegturned 16#0270 /mlsquare 16#3396 /mmcubedsquare 16#33A3 /mmonospace 16#FF4D /mmsquaredsquare 16#339F /mohiragana 16#3082 /mohmsquare 16#33C1 /mokatakana 16#30E2 /mokatakanahalfwidth 16#FF93 /molsquare 16#33D6 /momathai 16#0E21 /moverssquare 16#33A7 /moverssquaredsquare 16#33A8 /mparen 16#24A8 /mpasquare 16#33AB /mssquare 16#33B3 /msuperior 16#F6EF /mturned 16#026F /mu 16#00B5 /mu1 16#00B5 /muasquare 16#3382 /muchgreater 16#226B /muchless 16#226A /mufsquare 16#338C /mugreek 16#03BC /mugsquare 16#338D /muhiragana 16#3080 /mukatakana 16#30E0 /mukatakanahalfwidth 16#FF91 /mulsquare 16#3395 /multiply 16#00D7 /mumsquare 16#339B /munahhebrew 16#05A3 /munahlefthebrew 16#05A3 /musicalnote 16#266A /musicalnotedbl 16#266B /musicflatsign 16#266D /musicsharpsign 16#266F /mussquare 16#33B2 /muvsquare 16#33B6 /muwsquare 16#33BC /mvmegasquare 16#33B9 /mvsquare 16#33B7 /mwmegasquare 16#33BF /mwsquare 16#33BD /n 16#006E /nabengali 16#09A8 /nabla 16#2207 /nacute 16#0144 /nadeva 16#0928 /nagujarati 16#0AA8 /nagurmukhi 16#0A28 /nahiragana 16#306A /nakatakana 16#30CA /nakatakanahalfwidth 16#FF85 /napostrophe 16#0149 /nasquare 16#3381 /nbopomofo 16#310B /nbspace 16#00A0 /ncaron 16#0148 /ncedilla 16#0146 /ncircle 16#24DD /ncircumflexbelow 16#1E4B /ncommaaccent 16#0146 /ndotaccent 16#1E45 /ndotbelow 16#1E47 /nehiragana 16#306D /nekatakana 16#30CD /nekatakanahalfwidth 16#FF88 /newsheqelsign 16#20AA /nfsquare 16#338B /ngabengali 16#0999 /ngadeva 16#0919 /ngagujarati 16#0A99 /ngagurmukhi 16#0A19 /ngonguthai 16#0E07 /nhiragana 16#3093 /nhookleft 16#0272 /nhookretroflex 16#0273 /nieunacirclekorean 16#326F /nieunaparenkorean 16#320F /nieuncieuckorean 16#3135 /nieuncirclekorean 16#3261 /nieunhieuhkorean 16#3136 /nieunkorean 16#3134 /nieunpansioskorean 16#3168 /nieunparenkorean 16#3201 /nieunsioskorean 16#3167 /nieuntikeutkorean 16#3166 /nihiragana 16#306B /nikatakana 16#30CB /nikatakanahalfwidth 16#FF86 /nikhahitleftthai 16#F899 /nikhahitthai 16#0E4D /nine 16#0039 /ninearabic 16#0669 /ninebengali 16#09EF /ninecircle 16#2468 /ninecircleinversesansserif 16#2792 /ninedeva 16#096F /ninegujarati 16#0AEF /ninegurmukhi 16#0A6F /ninehackarabic 16#0669 /ninehangzhou 16#3029 /nineideographicparen 16#3228 /nineinferior 16#2089 /ninemonospace 16#FF19 /nineoldstyle 16#F739 /nineparen 16#247C /nineperiod 16#2490 /ninepersian 16#06F9 /nineroman 16#2178 /ninesuperior 16#2079 /nineteencircle 16#2472 /nineteenparen 16#2486 /nineteenperiod 16#249A /ninethai 16#0E59 /nj 16#01CC /njecyrillic 16#045A /nkatakana 16#30F3 /nkatakanahalfwidth 16#FF9D /nlegrightlong 16#019E /nlinebelow 16#1E49 /nmonospace 16#FF4E /nmsquare 16#339A /nnabengali 16#09A3 /nnadeva 16#0923 /nnagujarati 16#0AA3 /nnagurmukhi 16#0A23 /nnnadeva 16#0929 /nohiragana 16#306E /nokatakana 16#30CE /nokatakanahalfwidth 16#FF89 /nonbreakingspace 16#00A0 /nonenthai 16#0E13 /nonuthai 16#0E19 /noonarabic 16#0646 /noonfinalarabic 16#FEE6 /noonghunnaarabic 16#06BA /noonghunnafinalarabic 16#FB9F % /noonhehinitialarabic 16#FEE7 16#FEEC /nooninitialarabic 16#FEE7 /noonjeeminitialarabic 16#FCD2 /noonjeemisolatedarabic 16#FC4B /noonmedialarabic 16#FEE8 /noonmeeminitialarabic 16#FCD5 /noonmeemisolatedarabic 16#FC4E /noonnoonfinalarabic 16#FC8D /notcontains 16#220C /notelement 16#2209 /notelementof 16#2209 /notequal 16#2260 /notgreater 16#226F /notgreaternorequal 16#2271 /notgreaternorless 16#2279 /notidentical 16#2262 /notless 16#226E /notlessnorequal 16#2270 /notparallel 16#2226 /notprecedes 16#2280 /notsubset 16#2284 /notsucceeds 16#2281 /notsuperset 16#2285 /nowarmenian 16#0576 /nparen 16#24A9 /nssquare 16#33B1 /nsuperior 16#207F /ntilde 16#00F1 /nu 16#03BD /nuhiragana 16#306C /nukatakana 16#30CC /nukatakanahalfwidth 16#FF87 /nuktabengali 16#09BC /nuktadeva 16#093C /nuktagujarati 16#0ABC /nuktagurmukhi 16#0A3C /numbersign 16#0023 /numbersignmonospace 16#FF03 /numbersignsmall 16#FE5F /numeralsigngreek 16#0374 /numeralsignlowergreek 16#0375 /numero 16#2116 /nun 16#05E0 /nundagesh 16#FB40 /nundageshhebrew 16#FB40 /nunhebrew 16#05E0 /nvsquare 16#33B5 /nwsquare 16#33BB /nyabengali 16#099E /nyadeva 16#091E /nyagujarati 16#0A9E /nyagurmukhi 16#0A1E /o 16#006F /oacute 16#00F3 /oangthai 16#0E2D /obarred 16#0275 /obarredcyrillic 16#04E9 /obarreddieresiscyrillic 16#04EB /obengali 16#0993 /obopomofo 16#311B /obreve 16#014F /ocandradeva 16#0911 /ocandragujarati 16#0A91 /ocandravowelsigndeva 16#0949 /ocandravowelsigngujarati 16#0AC9 /ocaron 16#01D2 /ocircle 16#24DE /ocircumflex 16#00F4 /ocircumflexacute 16#1ED1 /ocircumflexdotbelow 16#1ED9 /ocircumflexgrave 16#1ED3 /ocircumflexhookabove 16#1ED5 /ocircumflextilde 16#1ED7 /ocyrillic 16#043E /odblacute 16#0151 /odblgrave 16#020D /odeva 16#0913 /odieresis 16#00F6 /odieresiscyrillic 16#04E7 /odotbelow 16#1ECD /oe 16#0153 /oekorean 16#315A /ogonek 16#02DB /ogonekcmb 16#0328 /ograve 16#00F2 /ogujarati 16#0A93 /oharmenian 16#0585 /ohiragana 16#304A /ohookabove 16#1ECF /ohorn 16#01A1 /ohornacute 16#1EDB /ohorndotbelow 16#1EE3 /ohorngrave 16#1EDD /ohornhookabove 16#1EDF /ohorntilde 16#1EE1 /ohungarumlaut 16#0151 /oi 16#01A3 /oinvertedbreve 16#020F /okatakana 16#30AA /okatakanahalfwidth 16#FF75 /okorean 16#3157 /olehebrew 16#05AB /omacron 16#014D /omacronacute 16#1E53 /omacrongrave 16#1E51 /omdeva 16#0950 /omega 16#03C9 /omega1 16#03D6 /omegacyrillic 16#0461 /omegalatinclosed 16#0277 /omegaroundcyrillic 16#047B /omegatitlocyrillic 16#047D /omegatonos 16#03CE /omgujarati 16#0AD0 /omicron 16#03BF /omicrontonos 16#03CC /omonospace 16#FF4F /one 16#0031 /onearabic 16#0661 /onebengali 16#09E7 /onecircle 16#2460 /onecircleinversesansserif 16#278A /onedeva 16#0967 /onedotenleader 16#2024 /oneeighth 16#215B /onefitted 16#F6DC /onegujarati 16#0AE7 /onegurmukhi 16#0A67 /onehackarabic 16#0661 /onehalf 16#00BD /onehangzhou 16#3021 /oneideographicparen 16#3220 /oneinferior 16#2081 /onemonospace 16#FF11 /onenumeratorbengali 16#09F4 /oneoldstyle 16#F731 /oneparen 16#2474 /oneperiod 16#2488 /onepersian 16#06F1 /onequarter 16#00BC /oneroman 16#2170 /onesuperior 16#00B9 /onethai 16#0E51 /onethird 16#2153 /oogonek 16#01EB /oogonekmacron 16#01ED /oogurmukhi 16#0A13 /oomatragurmukhi 16#0A4B /oopen 16#0254 /oparen 16#24AA /openbullet 16#25E6 /option 16#2325 /ordfeminine 16#00AA /ordmasculine 16#00BA /orthogonal 16#221F /oshortdeva 16#0912 /oshortvowelsigndeva 16#094A /oslash 16#00F8 /oslashacute 16#01FF /osmallhiragana 16#3049 /osmallkatakana 16#30A9 /osmallkatakanahalfwidth 16#FF6B /ostrokeacute 16#01FF /osuperior 16#F6F0 /otcyrillic 16#047F /otilde 16#00F5 /otildeacute 16#1E4D /otildedieresis 16#1E4F /oubopomofo 16#3121 /overline 16#203E /overlinecenterline 16#FE4A /overlinecmb 16#0305 /overlinedashed 16#FE49 /overlinedblwavy 16#FE4C /overlinewavy 16#FE4B /overscore 16#00AF /ovowelsignbengali 16#09CB /ovowelsigndeva 16#094B /ovowelsigngujarati 16#0ACB /p 16#0070 /paampssquare 16#3380 /paasentosquare 16#332B /pabengali 16#09AA /pacute 16#1E55 /padeva 16#092A /pagedown 16#21DF /pageup 16#21DE /pagujarati 16#0AAA /pagurmukhi 16#0A2A /pahiragana 16#3071 /paiyannoithai 16#0E2F /pakatakana 16#30D1 /palatalizationcyrilliccmb 16#0484 /palochkacyrillic 16#04C0 /pansioskorean 16#317F /paragraph 16#00B6 /parallel 16#2225 /parenleft 16#0028 /parenleftaltonearabic 16#FD3E /parenleftbt 16#F8ED /parenleftex 16#F8EC /parenleftinferior 16#208D /parenleftmonospace 16#FF08 /parenleftsmall 16#FE59 /parenleftsuperior 16#207D /parenlefttp 16#F8EB /parenleftvertical 16#FE35 /parenright 16#0029 /parenrightaltonearabic 16#FD3F /parenrightbt 16#F8F8 /parenrightex 16#F8F7 /parenrightinferior 16#208E /parenrightmonospace 16#FF09 /parenrightsmall 16#FE5A /parenrightsuperior 16#207E /parenrighttp 16#F8F6 /parenrightvertical 16#FE36 /partialdiff 16#2202 /paseqhebrew 16#05C0 /pashtahebrew 16#0599 /pasquare 16#33A9 /patah 16#05B7 /patah11 16#05B7 /patah1d 16#05B7 /patah2a 16#05B7 /patahhebrew 16#05B7 /patahnarrowhebrew 16#05B7 /patahquarterhebrew 16#05B7 /patahwidehebrew 16#05B7 /pazerhebrew 16#05A1 /pbopomofo 16#3106 /pcircle 16#24DF /pdotaccent 16#1E57 /pe 16#05E4 /pecyrillic 16#043F /pedagesh 16#FB44 /pedageshhebrew 16#FB44 /peezisquare 16#333B /pefinaldageshhebrew 16#FB43 /peharabic 16#067E /peharmenian 16#057A /pehebrew 16#05E4 /pehfinalarabic 16#FB57 /pehinitialarabic 16#FB58 /pehiragana 16#307A /pehmedialarabic 16#FB59 /pekatakana 16#30DA /pemiddlehookcyrillic 16#04A7 /perafehebrew 16#FB4E /percent 16#0025 /percentarabic 16#066A /percentmonospace 16#FF05 /percentsmall 16#FE6A /period 16#002E /periodarmenian 16#0589 /periodcentered 16#00B7 /periodhalfwidth 16#FF61 /periodinferior 16#F6E7 /periodmonospace 16#FF0E /periodsmall 16#FE52 /periodsuperior 16#F6E8 /perispomenigreekcmb 16#0342 /perpendicular 16#22A5 /perthousand 16#2030 /peseta 16#20A7 /pfsquare 16#338A /phabengali 16#09AB /phadeva 16#092B /phagujarati 16#0AAB /phagurmukhi 16#0A2B /phi 16#03C6 /phi1 16#03D5 /phieuphacirclekorean 16#327A /phieuphaparenkorean 16#321A /phieuphcirclekorean 16#326C /phieuphkorean 16#314D /phieuphparenkorean 16#320C /philatin 16#0278 /phinthuthai 16#0E3A /phisymbolgreek 16#03D5 /phook 16#01A5 /phophanthai 16#0E1E /phophungthai 16#0E1C /phosamphaothai 16#0E20 /pi 16#03C0 /pieupacirclekorean 16#3273 /pieupaparenkorean 16#3213 /pieupcieuckorean 16#3176 /pieupcirclekorean 16#3265 /pieupkiyeokkorean 16#3172 /pieupkorean 16#3142 /pieupparenkorean 16#3205 /pieupsioskiyeokkorean 16#3174 /pieupsioskorean 16#3144 /pieupsiostikeutkorean 16#3175 /pieupthieuthkorean 16#3177 /pieuptikeutkorean 16#3173 /pihiragana 16#3074 /pikatakana 16#30D4 /pisymbolgreek 16#03D6 /piwrarmenian 16#0583 /plus 16#002B /plusbelowcmb 16#031F /pluscircle 16#2295 /plusminus 16#00B1 /plusmod 16#02D6 /plusmonospace 16#FF0B /plussmall 16#FE62 /plussuperior 16#207A /pmonospace 16#FF50 /pmsquare 16#33D8 /pohiragana 16#307D /pointingindexdownwhite 16#261F /pointingindexleftwhite 16#261C /pointingindexrightwhite 16#261E /pointingindexupwhite 16#261D /pokatakana 16#30DD /poplathai 16#0E1B /postalmark 16#3012 /postalmarkface 16#3020 /pparen 16#24AB /precedes 16#227A /prescription 16#211E /primemod 16#02B9 /primereversed 16#2035 /product 16#220F /projective 16#2305 /prolongedkana 16#30FC /propellor 16#2318 /propersubset 16#2282 /propersuperset 16#2283 /proportion 16#2237 /proportional 16#221D /psi 16#03C8 /psicyrillic 16#0471 /psilipneumatacyrilliccmb 16#0486 /pssquare 16#33B0 /puhiragana 16#3077 /pukatakana 16#30D7 /pvsquare 16#33B4 /pwsquare 16#33BA /q 16#0071 /qadeva 16#0958 /qadmahebrew 16#05A8 /qafarabic 16#0642 /qaffinalarabic 16#FED6 /qafinitialarabic 16#FED7 /qafmedialarabic 16#FED8 /qamats 16#05B8 /qamats10 16#05B8 /qamats1a 16#05B8 /qamats1c 16#05B8 /qamats27 16#05B8 /qamats29 16#05B8 /qamats33 16#05B8 /qamatsde 16#05B8 /qamatshebrew 16#05B8 /qamatsnarrowhebrew 16#05B8 /qamatsqatanhebrew 16#05B8 /qamatsqatannarrowhebrew 16#05B8 /qamatsqatanquarterhebrew 16#05B8 /qamatsqatanwidehebrew 16#05B8 /qamatsquarterhebrew 16#05B8 /qamatswidehebrew 16#05B8 /qarneyparahebrew 16#059F /qbopomofo 16#3111 /qcircle 16#24E0 /qhook 16#02A0 /qmonospace 16#FF51 /qof 16#05E7 /qofdagesh 16#FB47 /qofdageshhebrew 16#FB47 % /qofhatafpatah 16#05E7 16#05B2 % /qofhatafpatahhebrew 16#05E7 16#05B2 % /qofhatafsegol 16#05E7 16#05B1 % /qofhatafsegolhebrew 16#05E7 16#05B1 /qofhebrew 16#05E7 % /qofhiriq 16#05E7 16#05B4 % /qofhiriqhebrew 16#05E7 16#05B4 % /qofholam 16#05E7 16#05B9 % /qofholamhebrew 16#05E7 16#05B9 % /qofpatah 16#05E7 16#05B7 % /qofpatahhebrew 16#05E7 16#05B7 % /qofqamats 16#05E7 16#05B8 % /qofqamatshebrew 16#05E7 16#05B8 % /qofqubuts 16#05E7 16#05BB % /qofqubutshebrew 16#05E7 16#05BB % /qofsegol 16#05E7 16#05B6 % /qofsegolhebrew 16#05E7 16#05B6 % /qofsheva 16#05E7 16#05B0 % /qofshevahebrew 16#05E7 16#05B0 % /qoftsere 16#05E7 16#05B5 % /qoftserehebrew 16#05E7 16#05B5 /qparen 16#24AC /quarternote 16#2669 /qubuts 16#05BB /qubuts18 16#05BB /qubuts25 16#05BB /qubuts31 16#05BB /qubutshebrew 16#05BB /qubutsnarrowhebrew 16#05BB /qubutsquarterhebrew 16#05BB /qubutswidehebrew 16#05BB /question 16#003F /questionarabic 16#061F /questionarmenian 16#055E /questiondown 16#00BF /questiondownsmall 16#F7BF /questiongreek 16#037E /questionmonospace 16#FF1F /questionsmall 16#F73F /quotedbl 16#0022 /quotedblbase 16#201E /quotedblleft 16#201C /quotedblmonospace 16#FF02 /quotedblprime 16#301E /quotedblprimereversed 16#301D /quotedblright 16#201D /quoteleft 16#2018 /quoteleftreversed 16#201B /quotereversed 16#201B /quoteright 16#2019 /quoterightn 16#0149 /quotesinglbase 16#201A /quotesingle 16#0027 /quotesinglemonospace 16#FF07 /r 16#0072 /raarmenian 16#057C /rabengali 16#09B0 /racute 16#0155 /radeva 16#0930 /radical 16#221A /radicalex 16#F8E5 /radoverssquare 16#33AE /radoverssquaredsquare 16#33AF /radsquare 16#33AD /rafe 16#05BF /rafehebrew 16#05BF /ragujarati 16#0AB0 /ragurmukhi 16#0A30 /rahiragana 16#3089 /rakatakana 16#30E9 /rakatakanahalfwidth 16#FF97 /ralowerdiagonalbengali 16#09F1 /ramiddlediagonalbengali 16#09F0 /ramshorn 16#0264 /ratio 16#2236 /rbopomofo 16#3116 /rcaron 16#0159 /rcedilla 16#0157 /rcircle 16#24E1 /rcommaaccent 16#0157 /rdblgrave 16#0211 /rdotaccent 16#1E59 /rdotbelow 16#1E5B /rdotbelowmacron 16#1E5D /referencemark 16#203B /reflexsubset 16#2286 /reflexsuperset 16#2287 /registered 16#00AE /registersans 16#F8E8 /registerserif 16#F6DA /reharabic 16#0631 /reharmenian 16#0580 /rehfinalarabic 16#FEAE /rehiragana 16#308C % /rehyehaleflamarabic 16#0631 16#FEF3 16#FE8E 16#0644 /rekatakana 16#30EC /rekatakanahalfwidth 16#FF9A /resh 16#05E8 /reshdageshhebrew 16#FB48 % /reshhatafpatah 16#05E8 16#05B2 % /reshhatafpatahhebrew 16#05E8 16#05B2 % /reshhatafsegol 16#05E8 16#05B1 % /reshhatafsegolhebrew 16#05E8 16#05B1 /reshhebrew 16#05E8 % /reshhiriq 16#05E8 16#05B4 % /reshhiriqhebrew 16#05E8 16#05B4 % /reshholam 16#05E8 16#05B9 % /reshholamhebrew 16#05E8 16#05B9 % /reshpatah 16#05E8 16#05B7 % /reshpatahhebrew 16#05E8 16#05B7 % /reshqamats 16#05E8 16#05B8 % /reshqamatshebrew 16#05E8 16#05B8 % /reshqubuts 16#05E8 16#05BB % /reshqubutshebrew 16#05E8 16#05BB % /reshsegol 16#05E8 16#05B6 % /reshsegolhebrew 16#05E8 16#05B6 % /reshsheva 16#05E8 16#05B0 % /reshshevahebrew 16#05E8 16#05B0 % /reshtsere 16#05E8 16#05B5 % /reshtserehebrew 16#05E8 16#05B5 /reversedtilde 16#223D /reviahebrew 16#0597 /reviamugrashhebrew 16#0597 /revlogicalnot 16#2310 /rfishhook 16#027E /rfishhookreversed 16#027F /rhabengali 16#09DD /rhadeva 16#095D /rho 16#03C1 /rhook 16#027D /rhookturned 16#027B /rhookturnedsuperior 16#02B5 /rhosymbolgreek 16#03F1 /rhotichookmod 16#02DE /rieulacirclekorean 16#3271 /rieulaparenkorean 16#3211 /rieulcirclekorean 16#3263 /rieulhieuhkorean 16#3140 /rieulkiyeokkorean 16#313A /rieulkiyeoksioskorean 16#3169 /rieulkorean 16#3139 /rieulmieumkorean 16#313B /rieulpansioskorean 16#316C /rieulparenkorean 16#3203 /rieulphieuphkorean 16#313F /rieulpieupkorean 16#313C /rieulpieupsioskorean 16#316B /rieulsioskorean 16#313D /rieulthieuthkorean 16#313E /rieultikeutkorean 16#316A /rieulyeorinhieuhkorean 16#316D /rightangle 16#221F /righttackbelowcmb 16#0319 /righttriangle 16#22BF /rihiragana 16#308A /rikatakana 16#30EA /rikatakanahalfwidth 16#FF98 /ring 16#02DA /ringbelowcmb 16#0325 /ringcmb 16#030A /ringhalfleft 16#02BF /ringhalfleftarmenian 16#0559 /ringhalfleftbelowcmb 16#031C /ringhalfleftcentered 16#02D3 /ringhalfright 16#02BE /ringhalfrightbelowcmb 16#0339 /ringhalfrightcentered 16#02D2 /rinvertedbreve 16#0213 /rittorusquare 16#3351 /rlinebelow 16#1E5F /rlongleg 16#027C /rlonglegturned 16#027A /rmonospace 16#FF52 /rohiragana 16#308D /rokatakana 16#30ED /rokatakanahalfwidth 16#FF9B /roruathai 16#0E23 /rparen 16#24AD /rrabengali 16#09DC /rradeva 16#0931 /rragurmukhi 16#0A5C /rreharabic 16#0691 /rrehfinalarabic 16#FB8D /rrvocalicbengali 16#09E0 /rrvocalicdeva 16#0960 /rrvocalicgujarati 16#0AE0 /rrvocalicvowelsignbengali 16#09C4 /rrvocalicvowelsigndeva 16#0944 /rrvocalicvowelsigngujarati 16#0AC4 /rsuperior 16#F6F1 /rtblock 16#2590 /rturned 16#0279 /rturnedsuperior 16#02B4 /ruhiragana 16#308B /rukatakana 16#30EB /rukatakanahalfwidth 16#FF99 /rupeemarkbengali 16#09F2 /rupeesignbengali 16#09F3 /rupiah 16#F6DD /ruthai 16#0E24 /rvocalicbengali 16#098B /rvocalicdeva 16#090B /rvocalicgujarati 16#0A8B /rvocalicvowelsignbengali 16#09C3 /rvocalicvowelsigndeva 16#0943 /rvocalicvowelsigngujarati 16#0AC3 /s 16#0073 /sabengali 16#09B8 /sacute 16#015B /sacutedotaccent 16#1E65 /sadarabic 16#0635 /sadeva 16#0938 /sadfinalarabic 16#FEBA /sadinitialarabic 16#FEBB /sadmedialarabic 16#FEBC /sagujarati 16#0AB8 /sagurmukhi 16#0A38 /sahiragana 16#3055 /sakatakana 16#30B5 /sakatakanahalfwidth 16#FF7B /sallallahoualayhewasallamarabic 16#FDFA /samekh 16#05E1 /samekhdagesh 16#FB41 /samekhdageshhebrew 16#FB41 /samekhhebrew 16#05E1 /saraaathai 16#0E32 /saraaethai 16#0E41 /saraaimaimalaithai 16#0E44 /saraaimaimuanthai 16#0E43 /saraamthai 16#0E33 /saraathai 16#0E30 /saraethai 16#0E40 /saraiileftthai 16#F886 /saraiithai 16#0E35 /saraileftthai 16#F885 /saraithai 16#0E34 /saraothai 16#0E42 /saraueeleftthai 16#F888 /saraueethai 16#0E37 /saraueleftthai 16#F887 /sarauethai 16#0E36 /sarauthai 16#0E38 /sarauuthai 16#0E39 /sbopomofo 16#3119 /scaron 16#0161 /scarondotaccent 16#1E67 /scedilla 16#015F /schwa 16#0259 /schwacyrillic 16#04D9 /schwadieresiscyrillic 16#04DB /schwahook 16#025A /scircle 16#24E2 /scircumflex 16#015D /scommaaccent 16#0219 /sdotaccent 16#1E61 /sdotbelow 16#1E63 /sdotbelowdotaccent 16#1E69 /seagullbelowcmb 16#033C /second 16#2033 /secondtonechinese 16#02CA /section 16#00A7 /seenarabic 16#0633 /seenfinalarabic 16#FEB2 /seeninitialarabic 16#FEB3 /seenmedialarabic 16#FEB4 /segol 16#05B6 /segol13 16#05B6 /segol1f 16#05B6 /segol2c 16#05B6 /segolhebrew 16#05B6 /segolnarrowhebrew 16#05B6 /segolquarterhebrew 16#05B6 /segoltahebrew 16#0592 /segolwidehebrew 16#05B6 /seharmenian 16#057D /sehiragana 16#305B /sekatakana 16#30BB /sekatakanahalfwidth 16#FF7E /semicolon 16#003B /semicolonarabic 16#061B /semicolonmonospace 16#FF1B /semicolonsmall 16#FE54 /semivoicedmarkkana 16#309C /semivoicedmarkkanahalfwidth 16#FF9F /sentisquare 16#3322 /sentosquare 16#3323 /seven 16#0037 /sevenarabic 16#0667 /sevenbengali 16#09ED /sevencircle 16#2466 /sevencircleinversesansserif 16#2790 /sevendeva 16#096D /seveneighths 16#215E /sevengujarati 16#0AED /sevengurmukhi 16#0A6D /sevenhackarabic 16#0667 /sevenhangzhou 16#3027 /sevenideographicparen 16#3226 /seveninferior 16#2087 /sevenmonospace 16#FF17 /sevenoldstyle 16#F737 /sevenparen 16#247A /sevenperiod 16#248E /sevenpersian 16#06F7 /sevenroman 16#2176 /sevensuperior 16#2077 /seventeencircle 16#2470 /seventeenparen 16#2484 /seventeenperiod 16#2498 /seventhai 16#0E57 /sfthyphen 16#00AD /shaarmenian 16#0577 /shabengali 16#09B6 /shacyrillic 16#0448 /shaddaarabic 16#0651 /shaddadammaarabic 16#FC61 /shaddadammatanarabic 16#FC5E /shaddafathaarabic 16#FC60 % /shaddafathatanarabic 16#0651 16#064B /shaddakasraarabic 16#FC62 /shaddakasratanarabic 16#FC5F /shade 16#2592 /shadedark 16#2593 /shadelight 16#2591 /shademedium 16#2592 /shadeva 16#0936 /shagujarati 16#0AB6 /shagurmukhi 16#0A36 /shalshelethebrew 16#0593 /shbopomofo 16#3115 /shchacyrillic 16#0449 /sheenarabic 16#0634 /sheenfinalarabic 16#FEB6 /sheeninitialarabic 16#FEB7 /sheenmedialarabic 16#FEB8 /sheicoptic 16#03E3 /sheqel 16#20AA /sheqelhebrew 16#20AA /sheva 16#05B0 /sheva115 16#05B0 /sheva15 16#05B0 /sheva22 16#05B0 /sheva2e 16#05B0 /shevahebrew 16#05B0 /shevanarrowhebrew 16#05B0 /shevaquarterhebrew 16#05B0 /shevawidehebrew 16#05B0 /shhacyrillic 16#04BB /shimacoptic 16#03ED /shin 16#05E9 /shindagesh 16#FB49 /shindageshhebrew 16#FB49 /shindageshshindot 16#FB2C /shindageshshindothebrew 16#FB2C /shindageshsindot 16#FB2D /shindageshsindothebrew 16#FB2D /shindothebrew 16#05C1 /shinhebrew 16#05E9 /shinshindot 16#FB2A /shinshindothebrew 16#FB2A /shinsindot 16#FB2B /shinsindothebrew 16#FB2B /shook 16#0282 /sigma 16#03C3 /sigma1 16#03C2 /sigmafinal 16#03C2 /sigmalunatesymbolgreek 16#03F2 /sihiragana 16#3057 /sikatakana 16#30B7 /sikatakanahalfwidth 16#FF7C /siluqhebrew 16#05BD /siluqlefthebrew 16#05BD /similar 16#223C /sindothebrew 16#05C2 /siosacirclekorean 16#3274 /siosaparenkorean 16#3214 /sioscieuckorean 16#317E /sioscirclekorean 16#3266 /sioskiyeokkorean 16#317A /sioskorean 16#3145 /siosnieunkorean 16#317B /siosparenkorean 16#3206 /siospieupkorean 16#317D /siostikeutkorean 16#317C /six 16#0036 /sixarabic 16#0666 /sixbengali 16#09EC /sixcircle 16#2465 /sixcircleinversesansserif 16#278F /sixdeva 16#096C /sixgujarati 16#0AEC /sixgurmukhi 16#0A6C /sixhackarabic 16#0666 /sixhangzhou 16#3026 /sixideographicparen 16#3225 /sixinferior 16#2086 /sixmonospace 16#FF16 /sixoldstyle 16#F736 /sixparen 16#2479 /sixperiod 16#248D /sixpersian 16#06F6 /sixroman 16#2175 /sixsuperior 16#2076 /sixteencircle 16#246F /sixteencurrencydenominatorbengali 16#09F9 /sixteenparen 16#2483 /sixteenperiod 16#2497 /sixthai 16#0E56 /slash 16#002F /slashmonospace 16#FF0F /slong 16#017F /slongdotaccent 16#1E9B /smileface 16#263A /smonospace 16#FF53 /sofpasuqhebrew 16#05C3 /softhyphen 16#00AD /softsigncyrillic 16#044C /sohiragana 16#305D /sokatakana 16#30BD /sokatakanahalfwidth 16#FF7F /soliduslongoverlaycmb 16#0338 /solidusshortoverlaycmb 16#0337 /sorusithai 16#0E29 /sosalathai 16#0E28 /sosothai 16#0E0B /sosuathai 16#0E2A /space 16#0020 /spacehackarabic 16#0020 /spade 16#2660 /spadesuitblack 16#2660 /spadesuitwhite 16#2664 /sparen 16#24AE /squarebelowcmb 16#033B /squarecc 16#33C4 /squarecm 16#339D /squarediagonalcrosshatchfill 16#25A9 /squarehorizontalfill 16#25A4 /squarekg 16#338F /squarekm 16#339E /squarekmcapital 16#33CE /squareln 16#33D1 /squarelog 16#33D2 /squaremg 16#338E /squaremil 16#33D5 /squaremm 16#339C /squaremsquared 16#33A1 /squareorthogonalcrosshatchfill 16#25A6 /squareupperlefttolowerrightfill 16#25A7 /squareupperrighttolowerleftfill 16#25A8 /squareverticalfill 16#25A5 /squarewhitewithsmallblack 16#25A3 /srsquare 16#33DB /ssabengali 16#09B7 /ssadeva 16#0937 /ssagujarati 16#0AB7 /ssangcieuckorean 16#3149 /ssanghieuhkorean 16#3185 /ssangieungkorean 16#3180 /ssangkiyeokkorean 16#3132 /ssangnieunkorean 16#3165 /ssangpieupkorean 16#3143 /ssangsioskorean 16#3146 /ssangtikeutkorean 16#3138 /ssuperior 16#F6F2 /sterling 16#00A3 /sterlingmonospace 16#FFE1 /strokelongoverlaycmb 16#0336 /strokeshortoverlaycmb 16#0335 /subset 16#2282 /subsetnotequal 16#228A /subsetorequal 16#2286 /succeeds 16#227B /suchthat 16#220B /suhiragana 16#3059 /sukatakana 16#30B9 /sukatakanahalfwidth 16#FF7D /sukunarabic 16#0652 /summation 16#2211 /sun 16#263C /superset 16#2283 /supersetnotequal 16#228B /supersetorequal 16#2287 /svsquare 16#33DC /syouwaerasquare 16#337C /t 16#0074 /tabengali 16#09A4 /tackdown 16#22A4 /tackleft 16#22A3 /tadeva 16#0924 /tagujarati 16#0AA4 /tagurmukhi 16#0A24 /taharabic 16#0637 /tahfinalarabic 16#FEC2 /tahinitialarabic 16#FEC3 /tahiragana 16#305F /tahmedialarabic 16#FEC4 /taisyouerasquare 16#337D /takatakana 16#30BF /takatakanahalfwidth 16#FF80 /tatweelarabic 16#0640 /tau 16#03C4 /tav 16#05EA /tavdages 16#FB4A /tavdagesh 16#FB4A /tavdageshhebrew 16#FB4A /tavhebrew 16#05EA /tbar 16#0167 /tbopomofo 16#310A /tcaron 16#0165 /tccurl 16#02A8 /tcedilla 16#0163 /tcheharabic 16#0686 /tchehfinalarabic 16#FB7B /tchehinitialarabic 16#FB7C /tchehmedialarabic 16#FB7D % /tchehmeeminitialarabic 16#FB7C 16#FEE4 /tcircle 16#24E3 /tcircumflexbelow 16#1E71 /tcommaaccent 16#0163 /tdieresis 16#1E97 /tdotaccent 16#1E6B /tdotbelow 16#1E6D /tecyrillic 16#0442 /tedescendercyrillic 16#04AD /teharabic 16#062A /tehfinalarabic 16#FE96 /tehhahinitialarabic 16#FCA2 /tehhahisolatedarabic 16#FC0C /tehinitialarabic 16#FE97 /tehiragana 16#3066 /tehjeeminitialarabic 16#FCA1 /tehjeemisolatedarabic 16#FC0B /tehmarbutaarabic 16#0629 /tehmarbutafinalarabic 16#FE94 /tehmedialarabic 16#FE98 /tehmeeminitialarabic 16#FCA4 /tehmeemisolatedarabic 16#FC0E /tehnoonfinalarabic 16#FC73 /tekatakana 16#30C6 /tekatakanahalfwidth 16#FF83 /telephone 16#2121 /telephoneblack 16#260E /telishagedolahebrew 16#05A0 /telishaqetanahebrew 16#05A9 /tencircle 16#2469 /tenideographicparen 16#3229 /tenparen 16#247D /tenperiod 16#2491 /tenroman 16#2179 /tesh 16#02A7 /tet 16#05D8 /tetdagesh 16#FB38 /tetdageshhebrew 16#FB38 /tethebrew 16#05D8 /tetsecyrillic 16#04B5 /tevirhebrew 16#059B /tevirlefthebrew 16#059B /thabengali 16#09A5 /thadeva 16#0925 /thagujarati 16#0AA5 /thagurmukhi 16#0A25 /thalarabic 16#0630 /thalfinalarabic 16#FEAC /thanthakhatlowleftthai 16#F898 /thanthakhatlowrightthai 16#F897 /thanthakhatthai 16#0E4C /thanthakhatupperleftthai 16#F896 /theharabic 16#062B /thehfinalarabic 16#FE9A /thehinitialarabic 16#FE9B /thehmedialarabic 16#FE9C /thereexists 16#2203 /therefore 16#2234 /theta 16#03B8 /theta1 16#03D1 /thetasymbolgreek 16#03D1 /thieuthacirclekorean 16#3279 /thieuthaparenkorean 16#3219 /thieuthcirclekorean 16#326B /thieuthkorean 16#314C /thieuthparenkorean 16#320B /thirteencircle 16#246C /thirteenparen 16#2480 /thirteenperiod 16#2494 /thonangmonthothai 16#0E11 /thook 16#01AD /thophuthaothai 16#0E12 /thorn 16#00FE /thothahanthai 16#0E17 /thothanthai 16#0E10 /thothongthai 16#0E18 /thothungthai 16#0E16 /thousandcyrillic 16#0482 /thousandsseparatorarabic 16#066C /thousandsseparatorpersian 16#066C /three 16#0033 /threearabic 16#0663 /threebengali 16#09E9 /threecircle 16#2462 /threecircleinversesansserif 16#278C /threedeva 16#0969 /threeeighths 16#215C /threegujarati 16#0AE9 /threegurmukhi 16#0A69 /threehackarabic 16#0663 /threehangzhou 16#3023 /threeideographicparen 16#3222 /threeinferior 16#2083 /threemonospace 16#FF13 /threenumeratorbengali 16#09F6 /threeoldstyle 16#F733 /threeparen 16#2476 /threeperiod 16#248A /threepersian 16#06F3 /threequarters 16#00BE /threequartersemdash 16#F6DE /threeroman 16#2172 /threesuperior 16#00B3 /threethai 16#0E53 /thzsquare 16#3394 /tihiragana 16#3061 /tikatakana 16#30C1 /tikatakanahalfwidth 16#FF81 /tikeutacirclekorean 16#3270 /tikeutaparenkorean 16#3210 /tikeutcirclekorean 16#3262 /tikeutkorean 16#3137 /tikeutparenkorean 16#3202 /tilde 16#02DC /tildebelowcmb 16#0330 /tildecmb 16#0303 /tildecomb 16#0303 /tildedoublecmb 16#0360 /tildeoperator 16#223C /tildeoverlaycmb 16#0334 /tildeverticalcmb 16#033E /timescircle 16#2297 /tipehahebrew 16#0596 /tipehalefthebrew 16#0596 /tippigurmukhi 16#0A70 /titlocyrilliccmb 16#0483 /tiwnarmenian 16#057F /tlinebelow 16#1E6F /tmonospace 16#FF54 /toarmenian 16#0569 /tohiragana 16#3068 /tokatakana 16#30C8 /tokatakanahalfwidth 16#FF84 /tonebarextrahighmod 16#02E5 /tonebarextralowmod 16#02E9 /tonebarhighmod 16#02E6 /tonebarlowmod 16#02E8 /tonebarmidmod 16#02E7 /tonefive 16#01BD /tonesix 16#0185 /tonetwo 16#01A8 /tonos 16#0384 /tonsquare 16#3327 /topatakthai 16#0E0F /tortoiseshellbracketleft 16#3014 /tortoiseshellbracketleftsmall 16#FE5D /tortoiseshellbracketleftvertical 16#FE39 /tortoiseshellbracketright 16#3015 /tortoiseshellbracketrightsmall 16#FE5E /tortoiseshellbracketrightvertical 16#FE3A /totaothai 16#0E15 /tpalatalhook 16#01AB /tparen 16#24AF /trademark 16#2122 /trademarksans 16#F8EA /trademarkserif 16#F6DB /tretroflexhook 16#0288 /triagdn 16#25BC /triaglf 16#25C4 /triagrt 16#25BA /triagup 16#25B2 /ts 16#02A6 /tsadi 16#05E6 /tsadidagesh 16#FB46 /tsadidageshhebrew 16#FB46 /tsadihebrew 16#05E6 /tsecyrillic 16#0446 /tsere 16#05B5 /tsere12 16#05B5 /tsere1e 16#05B5 /tsere2b 16#05B5 /tserehebrew 16#05B5 /tserenarrowhebrew 16#05B5 /tserequarterhebrew 16#05B5 /tserewidehebrew 16#05B5 /tshecyrillic 16#045B /tsuperior 16#F6F3 /ttabengali 16#099F /ttadeva 16#091F /ttagujarati 16#0A9F /ttagurmukhi 16#0A1F /tteharabic 16#0679 /ttehfinalarabic 16#FB67 /ttehinitialarabic 16#FB68 /ttehmedialarabic 16#FB69 /tthabengali 16#09A0 /tthadeva 16#0920 /tthagujarati 16#0AA0 /tthagurmukhi 16#0A20 /tturned 16#0287 /tuhiragana 16#3064 /tukatakana 16#30C4 /tukatakanahalfwidth 16#FF82 /tusmallhiragana 16#3063 /tusmallkatakana 16#30C3 /tusmallkatakanahalfwidth 16#FF6F /twelvecircle 16#246B /twelveparen 16#247F /twelveperiod 16#2493 /twelveroman 16#217B /twentycircle 16#2473 /twentyhangzhou 16#5344 /twentyparen 16#2487 /twentyperiod 16#249B /two 16#0032 /twoarabic 16#0662 /twobengali 16#09E8 /twocircle 16#2461 /twocircleinversesansserif 16#278B /twodeva 16#0968 /twodotenleader 16#2025 /twodotleader 16#2025 /twodotleadervertical 16#FE30 /twogujarati 16#0AE8 /twogurmukhi 16#0A68 /twohackarabic 16#0662 /twohangzhou 16#3022 /twoideographicparen 16#3221 /twoinferior 16#2082 /twomonospace 16#FF12 /twonumeratorbengali 16#09F5 /twooldstyle 16#F732 /twoparen 16#2475 /twoperiod 16#2489 /twopersian 16#06F2 /tworoman 16#2171 /twostroke 16#01BB /twosuperior 16#00B2 /twothai 16#0E52 /twothirds 16#2154 /u 16#0075 /uacute 16#00FA /ubar 16#0289 /ubengali 16#0989 /ubopomofo 16#3128 /ubreve 16#016D /ucaron 16#01D4 /ucircle 16#24E4 /ucircumflex 16#00FB /ucircumflexbelow 16#1E77 /ucyrillic 16#0443 /udattadeva 16#0951 /udblacute 16#0171 /udblgrave 16#0215 /udeva 16#0909 /udieresis 16#00FC /udieresisacute 16#01D8 /udieresisbelow 16#1E73 /udieresiscaron 16#01DA /udieresiscyrillic 16#04F1 /udieresisgrave 16#01DC /udieresismacron 16#01D6 /udotbelow 16#1EE5 /ugrave 16#00F9 /ugujarati 16#0A89 /ugurmukhi 16#0A09 /uhiragana 16#3046 /uhookabove 16#1EE7 /uhorn 16#01B0 /uhornacute 16#1EE9 /uhorndotbelow 16#1EF1 /uhorngrave 16#1EEB /uhornhookabove 16#1EED /uhorntilde 16#1EEF /uhungarumlaut 16#0171 /uhungarumlautcyrillic 16#04F3 /uinvertedbreve 16#0217 /ukatakana 16#30A6 /ukatakanahalfwidth 16#FF73 /ukcyrillic 16#0479 /ukorean 16#315C /umacron 16#016B /umacroncyrillic 16#04EF /umacrondieresis 16#1E7B /umatragurmukhi 16#0A41 /umonospace 16#FF55 /underscore 16#005F /underscoredbl 16#2017 /underscoremonospace 16#FF3F /underscorevertical 16#FE33 /underscorewavy 16#FE4F /union 16#222A /universal 16#2200 /uogonek 16#0173 /uparen 16#24B0 /upblock 16#2580 /upperdothebrew 16#05C4 /upsilon 16#03C5 /upsilondieresis 16#03CB /upsilondieresistonos 16#03B0 /upsilonlatin 16#028A /upsilontonos 16#03CD /uptackbelowcmb 16#031D /uptackmod 16#02D4 /uragurmukhi 16#0A73 /uring 16#016F /ushortcyrillic 16#045E /usmallhiragana 16#3045 /usmallkatakana 16#30A5 /usmallkatakanahalfwidth 16#FF69 /ustraightcyrillic 16#04AF /ustraightstrokecyrillic 16#04B1 /utilde 16#0169 /utildeacute 16#1E79 /utildebelow 16#1E75 /uubengali 16#098A /uudeva 16#090A /uugujarati 16#0A8A /uugurmukhi 16#0A0A /uumatragurmukhi 16#0A42 /uuvowelsignbengali 16#09C2 /uuvowelsigndeva 16#0942 /uuvowelsigngujarati 16#0AC2 /uvowelsignbengali 16#09C1 /uvowelsigndeva 16#0941 /uvowelsigngujarati 16#0AC1 /v 16#0076 /vadeva 16#0935 /vagujarati 16#0AB5 /vagurmukhi 16#0A35 /vakatakana 16#30F7 /vav 16#05D5 /vavdagesh 16#FB35 /vavdagesh65 16#FB35 /vavdageshhebrew 16#FB35 /vavhebrew 16#05D5 /vavholam 16#FB4B /vavholamhebrew 16#FB4B /vavvavhebrew 16#05F0 /vavyodhebrew 16#05F1 /vcircle 16#24E5 /vdotbelow 16#1E7F /vecyrillic 16#0432 /veharabic 16#06A4 /vehfinalarabic 16#FB6B /vehinitialarabic 16#FB6C /vehmedialarabic 16#FB6D /vekatakana 16#30F9 /venus 16#2640 /verticalbar 16#007C /verticallineabovecmb 16#030D /verticallinebelowcmb 16#0329 /verticallinelowmod 16#02CC /verticallinemod 16#02C8 /vewarmenian 16#057E /vhook 16#028B /vikatakana 16#30F8 /viramabengali 16#09CD /viramadeva 16#094D /viramagujarati 16#0ACD /visargabengali 16#0983 /visargadeva 16#0903 /visargagujarati 16#0A83 /vmonospace 16#FF56 /voarmenian 16#0578 /voicediterationhiragana 16#309E /voicediterationkatakana 16#30FE /voicedmarkkana 16#309B /voicedmarkkanahalfwidth 16#FF9E /vokatakana 16#30FA /vparen 16#24B1 /vtilde 16#1E7D /vturned 16#028C /vuhiragana 16#3094 /vukatakana 16#30F4 /w 16#0077 /wacute 16#1E83 /waekorean 16#3159 /wahiragana 16#308F /wakatakana 16#30EF /wakatakanahalfwidth 16#FF9C /wakorean 16#3158 /wasmallhiragana 16#308E /wasmallkatakana 16#30EE /wattosquare 16#3357 /wavedash 16#301C /wavyunderscorevertical 16#FE34 /wawarabic 16#0648 /wawfinalarabic 16#FEEE /wawhamzaabovearabic 16#0624 /wawhamzaabovefinalarabic 16#FE86 /wbsquare 16#33DD /wcircle 16#24E6 /wcircumflex 16#0175 /wdieresis 16#1E85 /wdotaccent 16#1E87 /wdotbelow 16#1E89 /wehiragana 16#3091 /weierstrass 16#2118 /wekatakana 16#30F1 /wekorean 16#315E /weokorean 16#315D /wgrave 16#1E81 /whitebullet 16#25E6 /whitecircle 16#25CB /whitecircleinverse 16#25D9 /whitecornerbracketleft 16#300E /whitecornerbracketleftvertical 16#FE43 /whitecornerbracketright 16#300F /whitecornerbracketrightvertical 16#FE44 /whitediamond 16#25C7 /whitediamondcontainingblacksmalldiamond 16#25C8 /whitedownpointingsmalltriangle 16#25BF /whitedownpointingtriangle 16#25BD /whiteleftpointingsmalltriangle 16#25C3 /whiteleftpointingtriangle 16#25C1 /whitelenticularbracketleft 16#3016 /whitelenticularbracketright 16#3017 /whiterightpointingsmalltriangle 16#25B9 /whiterightpointingtriangle 16#25B7 /whitesmallsquare 16#25AB /whitesmilingface 16#263A /whitesquare 16#25A1 /whitestar 16#2606 /whitetelephone 16#260F /whitetortoiseshellbracketleft 16#3018 /whitetortoiseshellbracketright 16#3019 /whiteuppointingsmalltriangle 16#25B5 /whiteuppointingtriangle 16#25B3 /wihiragana 16#3090 /wikatakana 16#30F0 /wikorean 16#315F /wmonospace 16#FF57 /wohiragana 16#3092 /wokatakana 16#30F2 /wokatakanahalfwidth 16#FF66 /won 16#20A9 /wonmonospace 16#FFE6 /wowaenthai 16#0E27 /wparen 16#24B2 /wring 16#1E98 /wsuperior 16#02B7 /wturned 16#028D /wynn 16#01BF /x 16#0078 /xabovecmb 16#033D /xbopomofo 16#3112 /xcircle 16#24E7 /xdieresis 16#1E8D /xdotaccent 16#1E8B /xeharmenian 16#056D /xi 16#03BE /xmonospace 16#FF58 /xparen 16#24B3 /xsuperior 16#02E3 /y 16#0079 /yaadosquare 16#334E /yabengali 16#09AF /yacute 16#00FD /yadeva 16#092F /yaekorean 16#3152 /yagujarati 16#0AAF /yagurmukhi 16#0A2F /yahiragana 16#3084 /yakatakana 16#30E4 /yakatakanahalfwidth 16#FF94 /yakorean 16#3151 /yamakkanthai 16#0E4E /yasmallhiragana 16#3083 /yasmallkatakana 16#30E3 /yasmallkatakanahalfwidth 16#FF6C /yatcyrillic 16#0463 /ycircle 16#24E8 /ycircumflex 16#0177 /ydieresis 16#00FF /ydotaccent 16#1E8F /ydotbelow 16#1EF5 /yeharabic 16#064A /yehbarreearabic 16#06D2 /yehbarreefinalarabic 16#FBAF /yehfinalarabic 16#FEF2 /yehhamzaabovearabic 16#0626 /yehhamzaabovefinalarabic 16#FE8A /yehhamzaaboveinitialarabic 16#FE8B /yehhamzaabovemedialarabic 16#FE8C /yehinitialarabic 16#FEF3 /yehmedialarabic 16#FEF4 /yehmeeminitialarabic 16#FCDD /yehmeemisolatedarabic 16#FC58 /yehnoonfinalarabic 16#FC94 /yehthreedotsbelowarabic 16#06D1 /yekorean 16#3156 /yen 16#00A5 /yenmonospace 16#FFE5 /yeokorean 16#3155 /yeorinhieuhkorean 16#3186 /yerahbenyomohebrew 16#05AA /yerahbenyomolefthebrew 16#05AA /yericyrillic 16#044B /yerudieresiscyrillic 16#04F9 /yesieungkorean 16#3181 /yesieungpansioskorean 16#3183 /yesieungsioskorean 16#3182 /yetivhebrew 16#059A /ygrave 16#1EF3 /yhook 16#01B4 /yhookabove 16#1EF7 /yiarmenian 16#0575 /yicyrillic 16#0457 /yikorean 16#3162 /yinyang 16#262F /yiwnarmenian 16#0582 /ymonospace 16#FF59 /yod 16#05D9 /yoddagesh 16#FB39 /yoddageshhebrew 16#FB39 /yodhebrew 16#05D9 /yodyodhebrew 16#05F2 /yodyodpatahhebrew 16#FB1F /yohiragana 16#3088 /yoikorean 16#3189 /yokatakana 16#30E8 /yokatakanahalfwidth 16#FF96 /yokorean 16#315B /yosmallhiragana 16#3087 /yosmallkatakana 16#30E7 /yosmallkatakanahalfwidth 16#FF6E /yotgreek 16#03F3 /yoyaekorean 16#3188 /yoyakorean 16#3187 /yoyakthai 16#0E22 /yoyingthai 16#0E0D /yparen 16#24B4 /ypogegrammeni 16#037A /ypogegrammenigreekcmb 16#0345 /yr 16#01A6 /yring 16#1E99 /ysuperior 16#02B8 /ytilde 16#1EF9 /yturned 16#028E /yuhiragana 16#3086 /yuikorean 16#318C /yukatakana 16#30E6 /yukatakanahalfwidth 16#FF95 /yukorean 16#3160 /yusbigcyrillic 16#046B /yusbigiotifiedcyrillic 16#046D /yuslittlecyrillic 16#0467 /yuslittleiotifiedcyrillic 16#0469 /yusmallhiragana 16#3085 /yusmallkatakana 16#30E5 /yusmallkatakanahalfwidth 16#FF6D /yuyekorean 16#318B /yuyeokorean 16#318A /yyabengali 16#09DF /yyadeva 16#095F /z 16#007A /zaarmenian 16#0566 /zacute 16#017A /zadeva 16#095B /zagurmukhi 16#0A5B /zaharabic 16#0638 /zahfinalarabic 16#FEC6 /zahinitialarabic 16#FEC7 /zahiragana 16#3056 /zahmedialarabic 16#FEC8 /zainarabic 16#0632 /zainfinalarabic 16#FEB0 /zakatakana 16#30B6 /zaqefgadolhebrew 16#0595 /zaqefqatanhebrew 16#0594 /zarqahebrew 16#0598 /zayin 16#05D6 /zayindagesh 16#FB36 /zayindageshhebrew 16#FB36 /zayinhebrew 16#05D6 /zbopomofo 16#3117 /zcaron 16#017E /zcircle 16#24E9 /zcircumflex 16#1E91 /zcurl 16#0291 /zdot 16#017C /zdotaccent 16#017C /zdotbelow 16#1E93 /zecyrillic 16#0437 /zedescendercyrillic 16#0499 /zedieresiscyrillic 16#04DF /zehiragana 16#305C /zekatakana 16#30BC /zero 16#0030 /zeroarabic 16#0660 /zerobengali 16#09E6 /zerodeva 16#0966 /zerogujarati 16#0AE6 /zerogurmukhi 16#0A66 /zerohackarabic 16#0660 /zeroinferior 16#2080 /zeromonospace 16#FF10 /zerooldstyle 16#F730 /zeropersian 16#06F0 /zerosuperior 16#2070 /zerothai 16#0E50 /zerowidthjoiner 16#FEFF /zerowidthnonjoiner 16#200C /zerowidthspace 16#200B /zeta 16#03B6 /zhbopomofo 16#3113 /zhearmenian 16#056A /zhebrevecyrillic 16#04C2 /zhecyrillic 16#0436 /zhedescendercyrillic 16#0497 /zhedieresiscyrillic 16#04DD /zihiragana 16#3058 /zikatakana 16#30B8 /zinorhebrew 16#05AE /zlinebelow 16#1E95 /zmonospace 16#FF5A /zohiragana 16#305E /zokatakana 16#30BE /zparen 16#24B5 /zretroflexhook 16#0290 /zstroke 16#01B6 /zuhiragana 16#305A /zukatakana 16#30BA .dicttomark readonly def /ReverseAdobeGlyphList mark 16#F769 [/Ismall] 16#263B [/invsmileface /blacksmilingface] 16#FB48 [/reshdageshhebrew] 16#A1A [/cagurmukhi] 16#183 [/btopbar] 16#F8EC [/parenleftex] 16#3055 [/sahiragana] 16#FF27 [/Gmonospace] 16#562 [/benarmenian] 16#FCCB [/lamkhahinitialarabic] 16#2562 [/SF200000] 16#306 [/brevecmb] 16#941 [/uvowelsigndeva] 16#20AA [/sheqelhebrew /sheqel /newsheqelsign /afii57636] 16#AA [/ordfeminine] 16#FE4E [/lowlinecenterline] 16#1E4E [/Otildedieresis] 16#2489 [/twoperiod] 16#AC4 [/rrvocalicvowelsigngujarati] 16#60C [/commaarabic /afii57388] 16#3B0 [/upsilondieresistonos] 16#9EB [/fivebengali] 16#2154 [/twothirds] 16#154 [/Racute] 16#3026 [/sixhangzhou] 16#278F [/sixcircleinversesansserif] 16#FEF8 [/lamalefhamzaabovefinalarabic] 16#1EF8 [/Ytilde] 16#533 [/Gimarmenian] 16#2D7 [/minusmod] 16#912 [/oshortdeva] 16#7B [/braceleft] 16#F7E4 [/Adieresissmall] 16#1E1F [/fdotaccent] 16#45A [/njecyrillic /afii10107] 16#A95 [/kagujarati] 16#1FE [/Ostrokeacute /Oslashacute] 16#30D0 [/bakatakana] 16#5DD [/finalmemhebrew /finalmem /afii57677] 16#9BC [/nuktabengali] 16#125 [/hcircumflex] 16#F88E [/maitholowrightthai] 16#1EC9 [/ihookabove] 16#FC6D [/behnoonfinalarabic] 16#33D6 [/molsquare] 16#2A8 [/tccurl] 16#317A [/sioskiyeokkorean] 16#4C [/L] 16#42B [/Yericyrillic /afii10045] 16#FB94 [/gafinitialarabic] 16#A66 [/zerogurmukhi] 16#21CF [/arrowrightdblstroke] 16#1CF [/Icaron] 16#30A1 [/asmallkatakana] 16#FF73 [/ukatakanahalfwidth] 16#F6DC [/onefitted] 16#E45 [/lakkhangyaothai] 16#5AE [/zinorhebrew] 16#3224 [/fiveideographicparen] 16#F6 [/odieresis] 16#FE9A [/thehfinalarabic] 16#1E9A [/arighthalfring] 16#24D5 [/fcircle] 16#4D5 [/aiecyrillic] 16#33A7 [/moverssquare] 16#279 [/rturned] 16#2279 [/notgreaternorless] 16#314B [/khieukhkorean] 16#1D [/controlGS] 16#201D [/quotedblright] 16#1A0 [/Ohorn] 16#3072 [/hihiragana] 16#FF44 [/dmonospace] 16#E16 [/thothungthai] 16#57F [/tiwnarmenian] 16#323 [/dotbelowcomb /dotbelowcmb] 16#95E [/fadeva] 16#C7 [/Ccedilla] 16#1E6B [/tdotaccent] 16#FE6B [/atsmall] 16#24A6 [/kparen] 16#4A6 [/Pemiddlehookcyrillic] 16#311C [/ebopomofo] 16#629 [/tehmarbutaarabic /afii57417] 16#3CD [/upsilontonos] 16#FB36 [/zayindageshhebrew /zayindagesh] 16#A08 [/iigurmukhi] 16#2171 [/tworoman] 16#171 [/udblacute /uhungarumlaut] 16#3043 [/ismallhiragana] 16#FF15 [/fivemonospace] 16#2550 [/SF430000] 16#550 [/Reharmenian] 16#92F [/yadeva] 16#FE3C [/blacklenticularbracketrightvertical] 16#1E3C [/Lcircumflexbelow] 16#477 [/izhitsadblgravecyrillic] 16#2477 [/fourparen] 16#3349 [/mirisquare] 16#AB2 [/lagujarati] 16#30ED [/rokatakana] 16#39E [/Xi] 16#3270 [/tikeutacirclekorean] 16#142 [/lslash] 16#3014 [/tortoiseshellbracketleft] 16#FEE6 [/noonfinalarabic] 16#1EE6 [/Uhookabove] 16#2C5 [/arrowheaddownmod] 16#22C5 [/dotmath] 16#69 [/i] 16#6A4 [/veharabic /afii57505] 16#1E0D [/ddotbelow] 16#448 [/shacyrillic /afii10090] 16#A83 [/visargagujarati] 16#1EC [/Oogonekmacron] 16#30BE [/zokatakana] 16#FF90 [/mikatakanahalfwidth] 16#F6F9 [/Lslashsmall] 16#25CB [/whitecircle /circle] 16#9AA [/pabengali] 16#2113 [/lsquare /afii61289] 16#113 [/emacron] 16#FEB7 [/sheeninitialarabic] 16#1EB7 [/abrevedotbelow] 16#4F2 [/Uhungarumlautcyrillic] 16#33C4 [/squarecc] 16#2296 [/minuscircle] 16#296 [/glottalstopinverted] 16#3168 [/nieunpansioskorean] 16#203A [/guilsinglright] 16#3A [/colon] 16#419 [/afii10027 /Iishortcyrillic] 16#1BD [/tonefive] 16#308F [/wahiragana] 16#FF61 [/periodhalfwidth] 16#F6CA [/Caron] 16#E33 [/saraamthai] 16#59C [/gereshaccenthebrew] 16#340 [/gravetonecmb] 16#3212 [/mieumaparenkorean] 16#E4 [/adieresis] 16#FE88 [/alefhamzabelowfinalarabic] 16#1E88 [/Wdotbelow] 16#24C3 [/Ncircle] 16#4C3 [/Kahookcyrillic] 16#3395 [/mulsquare] 16#2267 [/greateroverequal] 16#267 [/henghook] 16#3139 [/rieulkorean] 16#200B [/zerowidthspace] 16#B [/controlVT] 16#F774 [/Tsmall] 16#646 [/noonarabic /afii57446] 16#3EA [/Gangiacoptic] 16#A25 [/thagurmukhi] 16#18E [/Ereversed] 16#F8F7 [/parenrightex] 16#3060 [/dahiragana] 16#FF32 [/Rmonospace] 16#E04 [/khokhwaithai] 16#56D [/xeharmenian] 16#311 [/breveinvertedcmb] 16#94C [/auvowelsigndeva] 16#B5 [/mu1 /mu] 16#6F0 [/zeropersian] 16#FE59 [/parenleftsmall] 16#1E59 [/rdotaccent] 16#2494 [/thirteenperiod] 16#494 [/Ghemiddlehookcyrillic] 16#310A [/tbopomofo] 16#3BB [/lambda] 16#328D [/ideographwoodcircle] 16#9F6 [/threenumeratorbengali] 16#15F [/scedilla] 16#FF03 [/numbersignmonospace] 16#53E [/Caarmenian] 16#91D [/jhadeva] 16#2086 [/sixinferior] 16#F7EF [/Idieresissmall] 16#6C1 [/haaltonearabic /hehaltonearabic] 16#1E2A [/Hbrevebelow] 16#2465 [/sixcircle] 16#465 [/eiotifiedcyrillic] 16#AA0 [/tthagujarati] 16#2209 [/notelementof /notelement] 16#209 [/idblgrave] 16#30DB [/hokatakana] 16#5E8 [/resh /reshhebrew /afii57688] 16#38C [/Omicrontonos] 16#9C7 [/evowelsignbengali] 16#130 [/Idotaccent /Idot] 16#F899 [/nikhahitleftthai] 16#3002 [/ideographicperiod] 16#FED4 [/fehmedialarabic] 16#1ED4 [/Ocircumflexhookabove] 16#3185 [/ssanghieuhkorean] 16#57 [/W] 16#436 [/zhecyrillic /afii10072] 16#FB9F [/noonghunnafinalarabic] 16#A71 [/addakgurmukhi] 16#1DA [/udieresiscaron] 16#30AC [/gakatakana] 16#FF7E [/sekatakanahalfwidth] 16#F6E7 [/periodinferior] 16#E50 [/zerothai] 16#25B9 [/whiterightpointingsmalltriangle] 16#5B9 [/holamwidehebrew /holamquarterhebrew /holamnarrowhebrew /holamhebrew /holam32 /holam26 /holam19 /holam /afii57806] 16#322F [/ideographicearthparen] 16#998 [/ghabengali] 16#101 [/amacron] 16#1EA5 [/acircumflexacute] 16#24E0 [/qcircle] 16#4E0 [/Dzeabkhasiancyrillic] 16#33B2 [/mussquare] 16#284 [/dotlessjstrokehook] 16#2284 [/notsubset] 16#3156 [/yekorean] 16#28 [/parenleft] 16#663 [/threehackarabic /threearabic /afii57395] 16#2663 [/clubsuitblack /club] 16#407 [/afii10056 /Yicyrillic] 16#A42 [/uumatragurmukhi] 16#1AB [/tpalatalhook] 16#307D [/pohiragana] 16#FF4F [/omonospace] 16#E21 [/momathai] 16#32E [/brevebelowcmb] 16#3200 [/kiyeokparenkorean] 16#969 [/threedeva] 16#D2 [/Ograve] 16#1E76 [/Ucircumflexbelow] 16#4B1 [/ustraightstrokecyrillic] 16#24B1 [/vparen] 16#3383 [/masquare] 16#AEC [/sixgujarati] 16#255 [/ccurl] 16#3127 [/ibopomofo] 16#F762 [/Bsmall] 16#634 [/sheenarabic /afii57428] 16#FB41 [/samekhdageshhebrew /samekhdagesh] 16#A13 [/oogurmukhi] 16#17C [/zdotaccent /zdot] 16#F8E5 [/radicalex] 16#304E [/gihiragana] 16#FF20 [/atmonospace] 16#55B [/emphasismarkarmenian] 16#255B [/SF280000] 16#20A3 [/franc] 16#A3 [/sterling] 16#1E47 [/ndotbelow] 16#482 [/thousandcyrillic] 16#2482 [/fifteenparen] 16#2226 [/notparallel] 16#30F8 [/vikatakana] 16#F733 [/threeoldstyle] 16#2605 [/blackstar] 16#3A9 [/Omegagreek] 16#327B [/hieuhacirclekorean] 16#14D [/omacron] 16#1EF1 [/uhorndotbelow] 16#252C [/SF060000] 16#2D0 [/colontriangularmod] 16#90B [/rvocalicdeva] 16#2074 [/foursuperior] 16#74 [/t] 16#6AF [/gafarabic /afii57509] 16#1E18 [/Ecircumflexbelow] 16#453 [/gjecyrillic /afii10100] 16#30C9 [/dokatakana] 16#FF9B [/rokatakanahalfwidth] 16#5D6 [/zayinhebrew /zayin /afii57670] 16#FD3F [/parenrightaltonearabic] 16#37A [/ypogegrammeni] 16#211E [/prescription] 16#F887 [/saraueleftthai] 16#11E [/Gbreve] 16#FEC2 [/tahfinalarabic] 16#1EC2 [/Ecircumflexhookabove] 16#33CF [/ktsquare] 16#2A1 [/glottalstopstroke] 16#3173 [/pieuptikeutkorean] 16#45 [/E] 16#424 [/afii10038 /Efcyrillic] 16#FB8D [/rrehfinalarabic] 16#1C8 [/Lj] 16#FF6C [/yasmallkatakanahalfwidth] 16#F6D5 [/cyrflex] 16#25A7 [/squareupperlefttolowerrightfill] 16#5A7 [/dargalefthebrew /dargahebrew] 16#986 [/aabengali] 16#EF [/idieresis] 16#1E93 [/zdotbelow] 16#24CE [/Ycircle] 16#33A0 [/cmsquaredsquare] 16#272 [/nhookleft] 16#2272 [/lessorequivalent] 16#3144 [/pieupsioskorean] 16#16 [/controlSYN] 16#2016 [/dblverticalbar] 16#651 [/shaddaarabic /afii57457] 16#A30 [/ragurmukhi] 16#199 [/khook] 16#2199 [/arrowdownleft] 16#306B [/nihiragana] 16#FF3D [/bracketrightmonospace] 16#E0F [/topatakthai] 16#578 [/voarmenian] 16#31C [/ringhalfleftbelowcmb] 16#C0 [/Agrave] 16#FE64 [/lesssmall] 16#1E64 [/Sacutedotaccent] 16#49F [/kastrokecyrillic] 16#249F [/dparen] 16#FC08 [/behmeemisolatedarabic] 16#2243 [/asymptoticallyequal] 16#3115 [/shbopomofo] 16#622 [/afii57410 /alefmaddaabovearabic] 16#3C6 [/phi] 16#FB2F [/alefqamatshebrew] 16#3298 [/ideographiclaborcircle] 16#16A [/Umacron] 16#216A [/Elevenroman] 16#FF0E [/periodmonospace] 16#549 [/Chaarmenian] 16#928 [/nadeva] 16#F7FA [/Uacutesmall] 16#FE35 [/parenleftvertical] 16#1E35 [/klinebelow] 16#2470 [/seventeencircle] 16#470 [/Psicyrillic] 16#3342 [/hoonsquare] 16#AAB [/phagujarati] 16#214 [/Udblgrave] 16#30E6 [/yukatakana] 16#F721 [/exclamsmall] 16#5F3 [/gereshhebrew] 16#397 [/Eta] 16#FB00 [/ff] 16#3269 [/chieuchcirclekorean] 16#13B [/Lcommaaccent /Lcedilla] 16#300D [/cornerbracketright] 16#1EDF [/ohornhookabove] 16#FEDF [/laminitialarabic] 16#2BE [/ringhalfright] 16#62 [/b] 16#1E06 [/Blinebelow] 16#441 [/escyrillic /afii10083] 16#1E5 [/gstroke] 16#21E5 [/arrowtabright] 16#30B7 [/sikatakana] 16#FF89 [/nokatakanahalfwidth] 16#F6F2 [/ssuperior] 16#E5B [/khomutthai] 16#5C4 [/upperdothebrew] 16#25C4 [/triaglf /blackleftpointingpointer] 16#323A [/ideographiccallparen] 16#9A3 [/nnabengali] 16#10C [/Ccaron] 16#FEB0 [/zainfinalarabic] 16#1EB0 [/Abrevegrave] 16#4EB [/obarreddieresiscyrillic] 16#33BD [/mwsquare] 16#3161 [/eukorean] 16#2033 [/second] 16#33 [/three] 16#412 [/afii10019 /Vecyrillic] 16#FB7B [/tchehfinalarabic] 16#A4D [/halantgurmukhi] 16#1B6 [/zstroke] 16#3088 [/yohiragana] 16#FF5A [/zmonospace] 16#F6C3 [/commaaccent] 16#E2C [/lochulathai] 16#595 [/zaqefgadolhebrew] 16#339 [/ringhalfrightbelowcmb] 16#320B [/thieuthparenkorean] 16#DD [/Yacute] 16#1E81 [/wgrave] 16#24BC [/Gcircle] 16#4BC [/Cheabkhasiancyrillic] 16#338E [/squaremg] 16#260 [/ghook] 16#2260 [/notequal] 16#3132 [/ssangkiyeokkorean] 16#4 [/controlEOT] 16#F76D [/Msmall] 16#3E3 [/sheicoptic] 16#FB4C [/betrafehebrew] 16#A1E [/nyagurmukhi] 16#187 [/Chook] 16#F8F0 [/bracketleftbt] 16#3059 [/suhiragana] 16#FF2B [/Kmonospace] 16#566 [/zaarmenian] 16#2566 [/SF410000] 16#30A [/ringcmb] 16#945 [/ecandravowelsigndeva] 16#AE [/registered] 16#FE52 [/periodsmall] 16#1E52 [/Omacronacute] 16#248D [/sixperiod] 16#AC8 [/aivowelsigngujarati] 16#3B4 [/delta] 16#9EF [/ninebengali] 16#158 [/Rcaron] 16#FEFC [/lamaleffinalarabic] 16#537 [/Eharmenian] 16#22DB [/greaterequalorless] 16#2DB [/ogonek] 16#916 [/khadeva] 16#207F [/nsuperior] 16#7F [/controlDEL] 16#F7E8 [/Egravesmall] 16#6BA [/noonghunnaarabic /afii57514] 16#1E23 [/hdotaccent] 16#45E [/ushortcyrillic /afii10110] 16#A99 [/ngagujarati] 16#202 [/Ainvertedbreve] 16#2202 [/partialdiff] 16#30D4 [/pikatakana] 16#5E1 [/samekhhebrew /samekh /afii57681] 16#385 [/dialytikatonos /dieresistonos] 16#9C0 [/iivowelsignbengali] 16#129 [/itilde] 16#F892 [/maitrilowleftthai] 16#1ECD [/odotbelow] 16#317E [/sioscieuckorean] 16#50 [/P] 16#42F [/afii10049 /IAcyrillic] 16#A6A [/fourgurmukhi] 16#1D3 [/Ucaron] 16#21D3 [/arrowdbldown] 16#30A5 [/usmallkatakana] 16#FF77 [/kikatakanahalfwidth] 16#F6E0 [/centsuperior] 16#E49 [/maithothai] 16#25B2 [/triagup /blackuppointingtriangle] 16#5B2 [/hatafpatahquarterhebrew /hatafpatahnarrowhebrew /hatafpatahhebrew /hatafpatah2f /hatafpatah23 /hatafpatah16 /hatafpatah /hatafpatahwidehebrew /afii57800] 16#3228 [/nineideographicparen] 16#FA [/uacute] 16#FE9E [/jeemfinalarabic] 16#4D9 [/schwacyrillic /afii10846] 16#24D9 [/jcircle] 16#33AB [/mpasquare] 16#27D [/rhook] 16#314F [/akorean] 16#2021 [/daggerdbl] 16#21 [/exclam] 16#FB69 [/ttehmedialarabic] 16#1A4 [/Phook] 16#3076 [/buhiragana] 16#FF48 [/hmonospace] 16#E1A [/bobaimaithai] 16#583 [/piwrarmenian] 16#327 [/cedillacmb] 16#2327 [/clear] 16#962 [/lvocalicvowelsigndeva] 16#CB [/Edieresis] 16#1E6F [/tlinebelow] 16#24AA [/oparen] 16#4AA [/Esdescendercyrillic] 16#337C [/syouwaerasquare] 16#3120 [/aubopomofo] 16#62D [/haharabic /afii57421] 16#3D1 [/thetasymbolgreek /theta1] 16#FB3A [/finalkafdageshhebrew /finalkafdagesh] 16#32A3 [/ideographiccorrectcircle] 16#175 [/wcircumflex] 16#2175 [/sixroman] 16#3047 [/esmallhiragana] 16#FF19 [/ninemonospace] 16#554 [/Keharmenian] 16#2554 [/SF390000] 16#933 [/lladeva] 16#FE40 [/anglebracketrightvertical] 16#1E40 [/Mdotaccent] 16#47B [/omegaroundcyrillic] 16#247B [/eightparen] 16#334D [/meetorusquare] 16#AB6 [/shagujarati] 16#221F [/rightangle /orthogonal] 16#30F1 [/wekatakana] 16#3274 [/siosacirclekorean] 16#9DD [/rhabengali] 16#146 [/ncommaaccent /ncedilla] 16#3018 [/whitetortoiseshellbracketleft] 16#FEEA [/hehfinalarabic /hehfinalalttwoarabic] 16#1EEA [/Uhorngrave] 16#2C9 [/firsttonechinese] 16#6D [/m] 16#1E11 [/dcedilla] 16#44C [/softsigncyrillic /afii10094] 16#331E [/kooposquare] 16#A87 [/igujarati] 16#1F0 [/jcaron] 16#30C2 [/dikatakana] 16#FF94 [/yakatakanahalfwidth] 16#F6FD [/Scaronsmall] 16#25CF [/blackcircle /H18533] 16#9AE [/mabengali] 16#117 [/edotaccent /edot] 16#FEBB [/sadinitialarabic] 16#1EBB [/ehookabove] 16#FC5F [/shaddakasratanarabic] 16#33C8 [/dbsquare] 16#29A [/eopenclosed] 16#316C [/rieulpansioskorean] 16#203E [/overline] 16#3E [/greater] 16#679 [/tteharabic /afii57511] 16#41D [/afii10031 /Encyrillic] 16#1C1 [/clicklateral] 16#3093 [/nhiragana] 16#FF65 [/middledotkatakanahalfwidth] 16#F6CE [/Grave] 16#E37 [/saraueethai] 16#5A0 [/telishagedolahebrew] 16#25A0 [/blacksquare /filledbox] 16#344 [/dialytikatonoscmb] 16#3216 [/cieucaparenkorean] 16#E8 [/egrave] 16#FE8C [/yehhamzaabovemedialarabic] 16#1E8C [/Xdieresis] 16#24C7 [/Rcircle] 16#4C7 [/Enhookcyrillic] 16#3399 [/fmsquare] 16#226B [/muchgreater] 16#26B [/lmiddletilde] 16#313D [/rieulsioskorean] 16#F [/controlSI] 16#200F [/afii300] 16#F778 [/Xsmall] 16#64A [/yeharabic /afii57450] 16#3EE [/Deicoptic] 16#FB57 [/pehfinalarabic] 16#192 [/florin] 16#F8FB [/bracketrightbt] 16#3064 [/tuhiragana] 16#2192 [/arrowright] 16#FF36 [/Vmonospace] 16#E08 [/chochanthai] 16#571 [/jaarmenian] 16#315 [/commaaboverightcmb] 16#950 [/omdeva] 16#B9 [/onesuperior] 16#6F4 [/fourpersian] 16#FE5D [/tortoiseshellbracketleftsmall] 16#1E5D [/rdotbelowmacron] 16#2498 [/seventeenperiod] 16#498 [/Zedescendercyrillic] 16#223C [/tildeoperator /similar] 16#310E [/kbopomofo] 16#FFE0 [/centmonospace] 16#61B [/semicolonarabic /afii57403] 16#3BF [/omicron] 16#9FA [/issharbengali] 16#163 [/tcedilla /tcommaaccent] 16#2163 [/Fourroman] 16#279E [/arrowrightheavy] 16#FF07 [/quotesinglemonospace] 16#542 [/Ghadarmenian] 16#2E6 [/tonebarhighmod] 16#921 [/ddadeva] 16#F7F3 [/Oacutesmall] 16#1E2E [/Idieresisacute] 16#469 [/yuslittleiotifiedcyrillic] 16#2469 [/tencircle] 16#333B [/peezisquare] 16#AA4 [/tagujarati] 16#20D [/odblgrave] 16#30DF [/mikatakana] 16#390 [/iotadieresistonos] 16#3262 [/tikeutcirclekorean] 16#9CB [/ovowelsignbengali] 16#134 [/Jcircumflex] 16#3006 [/ideographicclose] 16#FED8 [/qafmedialarabic] 16#1ED8 [/Ocircumflexdotbelow] 16#2B7 [/wsuperior] 16#3189 [/yoikorean] 16#5B [/bracketleft] 16#43A [/kacyrillic /afii10076] 16#21DE [/pageup] 16#1DE [/Adieresismacron] 16#30B0 [/gukatakana] 16#FF82 [/tukatakanahalfwidth] 16#F6EB [/dsuperior] 16#E54 [/fourthai] 16#25BD [/whitedownpointingtriangle] 16#5BD [/siluqlefthebrew /siluqhebrew /afii57839] 16#361 [/breveinverteddoublecmb] 16#3233 [/ideographicsocietyparen] 16#99C [/jabengali] 16#2105 [/careof /afii61248] 16#105 [/aogonek] 16#1EA9 [/acircumflexhookabove] 16#24E4 [/ucircle] 16#4E4 [/Idieresiscyrillic] 16#33B6 [/muvsquare] 16#288 [/tretroflexhook] 16#315A [/oekorean] 16#202C [/afii61573] 16#2C [/comma] 16#667 [/sevenhackarabic /sevenarabic /afii57399] 16#2667 [/clubsuitwhite] 16#40B [/afii10060 /Tshecyrillic] 16#1AF [/Uhorn] 16#3081 [/mehiragana] 16#FF53 [/smonospace] 16#E25 [/lolingthai] 16#332 [/lowlinecmb] 16#3204 [/mieumparenkorean] 16#96D [/sevendeva] 16#D6 [/Odieresis] 16#1E7A [/Umacrondieresis] 16#24B5 [/zparen] 16#4B5 [/tetsecyrillic] 16#3387 [/GBsquare] 16#259 [/schwa] 16#F766 [/Fsmall] 16#638 [/zaharabic /afii57432] 16#3DC [/Digammagreek] 16#A17 [/gagurmukhi] 16#180 [/bstroke] 16#F8E9 [/copyrightsans] 16#3052 [/gehiragana] 16#FF24 [/Dmonospace] 16#55F [/abbreviationmarkarmenian] 16#255F [/SF370000] 16#303 [/tildecomb /tildecmb] 16#2303 [/control] 16#93E [/aavowelsigndeva] 16#20A7 [/peseta] 16#A7 [/section] 16#FE4B [/overlinewavy] 16#1E4B [/ncircumflexbelow] 16#486 [/psilipneumatacyrilliccmb] 16#2486 [/nineteenparen] 16#AC1 [/uvowelsigngujarati] 16#222A [/union] 16#30FC [/prolongedkana] 16#F737 [/sevenoldstyle] 16#3AD [/epsilontonos] 16#327F [/koreanstandardsymbol] 16#9E8 [/twobengali] 16#151 [/odblacute /ohungarumlaut] 16#3023 [/threehangzhou] 16#278C [/threecircleinversesansserif] 16#1EF5 [/ydotbelow] 16#FEF5 [/lamalefmaddaaboveisolatedarabic] 16#2D4 [/uptackmod] 16#90F [/edeva] 16#2078 [/eightsuperior] 16#F7E1 [/Aacutesmall] 16#78 [/x] 16#1E1C [/Ecedillabreve] 16#457 [/yicyrillic /afii10104] 16#1FB [/aringacute] 16#30CD [/nekatakana] 16#FF9F [/semivoicedmarkkanahalfwidth] 16#5DA [/finalkafhebrew /finalkaf /afii57674] 16#37E [/questiongreek] 16#9B9 [/habengali] 16#2122 [/trademark] 16#F88B [/maieklowrightthai] 16#122 [/Gcommaaccent /Gcedilla] 16#FEC6 [/zahfinalarabic] 16#1EC6 [/Ecircumflexdotbelow] 16#33D3 [/lxsquare] 16#2A5 [/dzcurl] 16#22A5 [/perpendicular] 16#3177 [/pieupthieuthkorean] 16#49 [/I] 16#428 [/afii10042 /Shacyrillic] 16#1CC [/nj] 16#309E [/voicediterationhiragana] 16#FF70 [/katahiraprolongmarkhalfwidth] 16#F6D9 [/copyrightserif] 16#E42 [/saraothai] 16#25AB [/whitesmallsquare /H18551] 16#5AB [/olehebrew] 16#3221 [/twoideographicparen] 16#98A [/uubengali] 16#F3 [/oacute] 16#FE97 [/tehinitialarabic] 16#1E97 [/tdieresis] 16#24D2 [/ccircle] 16#4D2 [/Adieresiscyrillic] 16#33A4 [/cmcubedsquare] 16#2276 [/lessorgreater] 16#3148 [/cieuckorean] 16#1A [/controlSUB] 16#201A [/quotesinglbase] 16#19D [/Nhookleft] 16#306F [/hahiragana] 16#FF41 [/amonospace] 16#E13 [/nonenthai] 16#57C [/raarmenian] 16#320 [/minusbelowcmb] 16#2320 [/integraltop /integraltp] 16#95B [/zadeva] 16#C4 [/Adieresis] 16#1E68 [/Sdotbelowdotaccent] 16#24A3 [/hparen] 16#FC0C [/tehhahisolatedarabic] 16#4A3 [/endescendercyrillic] 16#3119 [/sbopomofo] 16#626 [/yehhamzaabovearabic /afii57414] 16#3CA [/iotadieresis] 16#FB33 [/daletdageshhebrew /daletdagesh] 16#A05 [/agurmukhi] 16#16E [/Uring] 16#FF12 [/twomonospace] 16#54D [/Seharmenian] 16#92C [/badeva] 16#F7FE [/Thornsmall] 16#FE39 [/tortoiseshellbracketleftvertical] 16#1E39 [/ldotbelowmacron] 16#2474 [/oneparen] 16#474 [/afii10148 /Izhitsacyrillic] 16#AAF [/yagujarati] 16#218 [/Scommaaccent] 16#30EA [/rikatakana] 16#39B [/Lambda] 16#FB04 [/ffl] 16#326D [/hieuhcirclekorean] 16#13F [/Ldotaccent /Ldot] 16#3011 [/blacklenticularbracketright] 16#1EE3 [/ohorndotbelow] 16#FEE3 [/meeminitialarabic] 16#2C2 [/arrowheadleftmod] 16#66 [/f] 16#1E0A [/Ddotaccent] 16#445 [/khacyrillic /afii10087] 16#1E9 [/kcaron] 16#21E9 [/arrowdownwhite] 16#30BB [/sekatakana] 16#FF8D [/hekatakanahalfwidth] 16#F6F6 [/Circumflexsmall] 16#25C8 [/whitediamondcontainingblacksmalldiamond] 16#323E [/ideographicresourceparen] 16#9A7 [/dhabengali] 16#110 [/Dslash /Dcroat] 16#FEB4 [/seenmedialarabic] 16#1EB4 [/Abrevetilde] 16#4EF [/umacroncyrillic] 16#FC58 [/yehmeemisolatedarabic] 16#33C1 [/mohmsquare] 16#293 [/ezhcurl] 16#3165 [/ssangnieunkorean] 16#37 [/seven] 16#416 [/Zhecyrillic /afii10024] 16#1BA [/ezhtail] 16#308C [/rehiragana] 16#FF5E [/asciitildemonospace] 16#F6C7 [/afii10831] 16#E30 [/saraathai] 16#599 [/pashtahebrew] 16#33D [/xabovecmb] 16#320F [/nieunaparenkorean] 16#E1 [/aacute] 16#1E85 [/wdieresis] 16#4C0 [/palochkacyrillic] 16#24C0 [/Kcircle] 16#3392 [/mhzsquare] 16#264 [/ramshorn] 16#2264 [/lessequal] 16#3136 [/nieunhieuhkorean] 16#8 [/controlBS] 16#F771 [/Qsmall] 16#643 [/kafarabic /afii57443] 16#3E7 [/kheicoptic] 16#A22 [/ddhagurmukhi] 16#18B [/Dtopbar] 16#F8F4 [/braceex] 16#305D [/sohiragana] 16#FF2F [/Omonospace] 16#E01 [/kokaithai] 16#56A [/zhearmenian] 16#256A [/SF540000] 16#30E [/dblverticallineabovecmb] 16#949 [/ocandravowelsigndeva] 16#B2 [/twosuperior] 16#1E56 [/Pdotaccent] 16#2491 [/tenperiod] 16#491 [/gheupturncyrillic /afii10098] 16#ACC [/auvowelsigngujarati] 16#2235 [/because] 16#3107 [/mbopomofo] 16#3B8 [/theta] 16#328A [/ideographmooncircle] 16#9F3 [/rupeesignbengali] 16#215C [/threeeighths] 16#15C [/Scircumflex] 16#53B [/Iniarmenian] 16#FCA4 [/tehmeeminitialarabic] 16#91A [/cadeva] 16#2083 [/threeinferior] 16#F7EC [/Igravesmall] 16#1E27 [/hdieresis] 16#2462 [/threecircle] 16#462 [/afii10146 /Yatcyrillic] 16#A9D [/jhagujarati] 16#2206 [/increment /Delta] 16#206 [/Einvertedbreve] 16#30D8 [/hekatakana] 16#5E5 [/finaltsadihebrew /finaltsadi /afii57685] 16#25E5 [/blackupperrighttriangle] 16#389 [/Etatonos] 16#9C4 [/rrvocalicvowelsignbengali] 16#12D [/ibreve] 16#F896 [/thanthakhatupperleftthai] 16#1ED1 [/ocircumflexacute] 16#250C [/SF010000] 16#2B0 [/hsuperior] 16#3182 [/yesieungsioskorean] 16#54 [/T] 16#433 [/gecyrillic /afii10068] 16#3305 [/intisquare] 16#A6E [/eightgurmukhi] 16#1D7 [/Udieresisacute] 16#30A9 [/osmallkatakana] 16#FF7B [/sakatakanahalfwidth] 16#F6E4 [/dollarsuperior] 16#E4D [/nikhahitthai] 16#5B6 [/segolwidehebrew /segolquarterhebrew /segolnarrowhebrew /segolhebrew /segol2c /segol1f /segol13 /segol /afii57795] 16#25B6 [/blackrightpointingtriangle] 16#322C [/ideographicwaterparen] 16#995 [/kabengali] 16#FE [/thorn] 16#FEA2 [/hahfinalarabic] 16#1EA2 [/Ahookabove] 16#4DD [/zhedieresiscyrillic] 16#24DD [/ncircle] 16#33AF [/radoverssquaredsquare] 16#2281 [/notsucceeds] 16#281 [/Rsmallinverted] 16#3153 [/eokorean] 16#2025 [/twodotleader /twodotenleader] 16#25 [/percent] 16#660 [/zerohackarabic /zeroarabic /afii57392] 16#2660 [/spadesuitblack /spade] 16#404 [/afii10053 /Ecyrillic] 16#FB6D [/vehmedialarabic] 16#A3F [/imatragurmukhi] 16#1A8 [/tonetwo] 16#21A8 [/arrowupdownbase /arrowupdnbse] 16#307A [/pehiragana] 16#FF4C [/lmonospace] 16#E1E [/phophanthai] 16#587 [/echyiwnarmenian] 16#32B [/dblarchinvertedbelowcmb] 16#232B [/deleteleft] 16#966 [/zerodeva] 16#CF [/Idieresis] 16#1E73 [/udieresisbelow] 16#24AE [/sparen] 16#4AE [/Ustraightcyrillic] 16#3380 [/paampssquare] 16#AE9 [/threegujarati] 16#252 [/ascriptturned] 16#2252 [/approxequalorimage] 16#3124 [/angbopomofo] 16#631 [/reharabic /afii57425] 16#3D5 [/phisymbolgreek /phi1] 16#FB3E [/memdageshhebrew /memdagesh] 16#32A7 [/ideographicleftcircle] 16#A10 [/aigurmukhi] 16#2179 [/tenroman] 16#179 [/Zacute] 16#304B [/kahiragana] 16#FF1D [/equalmonospace] 16#2558 [/SF500000] 16#937 [/ssadeva] 16#A0 [/nonbreakingspace /nbspace] 16#FE44 [/whitecornerbracketrightvertical] 16#1E44 [/Ndotaccent] 16#247F [/twelveparen] 16#47F [/otcyrillic] 16#3351 [/rittorusquare] 16#2223 [/divides] 16#30F5 [/kasmallkatakana] 16#F730 [/zerooldstyle] 16#3A6 [/Phi] 16#3278 [/khieukhacirclekorean] 16#9E1 [/llvocalicbengali] 16#14A [/Eng] 16#301C [/wavedash] 16#FEEE [/wawfinalarabic] 16#1EEE [/Uhorntilde] 16#2CD [/macronlowmod] 16#908 [/iideva] 16#71 [/q] 16#1E15 [/emacrongrave] 16#3322 [/sentisquare] 16#A8B [/rvocalicgujarati] 16#1F4 [/Gacute] 16#30C6 [/tekatakana] 16#FF98 [/rikatakanahalfwidth] 16#5D3 [/dalethebrew /dalet /afii57667] 16#9B2 [/labengali] 16#11B [/ecaron] 16#F884 [/maihanakatleftthai] 16#1EBF [/ecircumflexacute] 16#FEBF [/dadinitialarabic] 16#29E [/kturned] 16#3170 [/mieumpansioskorean] 16#2042 [/asterism] 16#42 [/B] 16#421 [/afii10035 /Escyrillic] 16#A5C [/rragurmukhi] 16#21C5 [/arrowupleftofdown] 16#1C5 [/Dzcaron] 16#FF69 [/usmallkatakanahalfwidth] 16#F6D2 [/cyrFlex] 16#25A4 [/squarehorizontalfill] 16#5A4 [/mahapakhlefthebrew /mahapakhhebrew] 16#321A [/phieuphaparenkorean] 16#983 [/visargabengali] 16#EC [/igrave] 16#FE90 [/behfinalarabic] 16#1E90 [/Zcircumflex] 16#24CB [/Vcircle] 16#4CB [/Chekhakassiancyrillic] 16#339D [/squarecm] 16#26F [/mturned] 16#226F [/notgreater] 16#3141 [/mieumkorean] 16#13 [/controlDC3] 16#2013 [/endash] 16#64E [/fathalowarabic /fathaarabic /afii57454] 16#3F2 [/sigmalunatesymbolgreek] 16#A2D [/bhagurmukhi] 16#2196 [/arrowupleft] 16#F8FF [/apple] 16#3068 [/tohiragana] 16#196 [/Iotaafrican] 16#FF3A [/Zmonospace] 16#E0C [/chochoethai] 16#575 [/yiarmenian] 16#319 [/righttackbelowcmb] 16#954 [/acutedeva] 16#BD [/onehalf] 16#6F8 [/eightpersian] 16#1E61 [/sdotaccent] 16#FE61 [/asterisksmall] 16#249C [/aparen] 16#49C [/Kaverticalstrokecyrillic] 16#3112 [/xbopomofo] 16#261F [/pointingindexdownwhite] 16#61F [/questionarabic /afii57407] 16#FD88 [/lammeemhahinitialarabic] 16#3C3 [/sigma] 16#FB2C [/shindageshshindothebrew /shindageshshindot] 16#167 [/tbar] 16#2167 [/Eightroman] 16#FF0B [/plusmonospace] 16#546 [/Nowarmenian] 16#925 [/thadeva] 16#208E [/parenrightinferior] 16#FE32 [/endashvertical] 16#1E32 [/Kdotbelow] 16#46D [/yusbigiotifiedcyrillic] 16#246D [/fourteencircle] 16#AA8 [/nagujarati] 16#211 [/rdblgrave] 16#2211 [/summation] 16#30E3 [/yasmallkatakana] 16#5F0 [/vavvavhebrew /afii57716] 16#394 [/Deltagreek] 16#3266 [/sioscirclekorean] 16#138 [/kgreenlandic] 16#300A [/dblanglebracketleft] 16#FEDC [/kafmedialarabic] 16#1EDC [/Ohorngrave] 16#2BB [/commaturnedmod] 16#318D [/araeakorean] 16#5F [/underscore] 16#1E03 [/bdotaccent] 16#43E [/ocyrillic /afii10080] 16#FBA7 [/hehfinalaltonearabic] 16#21E2 [/arrowdashright] 16#1E2 [/AEmacron] 16#30B4 [/gokatakana] 16#FF86 [/nikatakanahalfwidth] 16#F6EF [/msuperior] 16#E58 [/eightthai] 16#25C1 [/whiteleftpointingtriangle] 16#5C1 [/shindothebrew /afii57804] 16#3237 [/ideographiccongratulationparen] 16#9A0 [/tthabengali] 16#2109 [/fahrenheit] 16#109 [/ccircumflex] 16#1EAD [/acircumflexdotbelow] 16#24E8 [/ycircle] 16#4E8 [/Obarredcyrillic] 16#33BA [/pwsquare] 16#28C [/vturned] 16#315E [/wekorean] 16#2030 [/perthousand] 16#30 [/zero] 16#266B [/musicalnotedbl /eighthnotebeamed] 16#66B [/decimalseparatorpersian /decimalseparatorarabic] 16#40F [/afii10145 /Dzhecyrillic] 16#1B3 [/Yhook] 16#3085 [/yusmallhiragana] 16#FF57 [/wmonospace] 16#F6C0 [/ll] 16#E29 [/sorusithai] 16#2592 [/shademedium /shade] 16#592 [/segoltahebrew] 16#336 [/strokelongoverlaycmb] 16#3208 [/cieucparenkorean] 16#DA [/Uacute] 16#1E7E [/Vdotbelow] 16#4B9 [/cheverticalstrokecyrillic] 16#24B9 [/Dcircle] 16#338B [/nfsquare] 16#25D [/eopenreversedhook] 16#1 [/controlSTX] 16#F76A [/Jsmall] 16#263C [/sun /compass] 16#3E0 [/Sampigreek] 16#FB49 [/shindageshhebrew /shindagesh] 16#A1B [/chagurmukhi] 16#184 [/Tonesix] 16#F8ED [/parenleftbt] 16#3056 [/zahiragana] 16#FF28 [/Hmonospace] 16#563 [/gimarmenian] 16#FCCC [/lammeeminitialarabic] 16#2563 [/SF230000] 16#307 [/dotaccentcmb] 16#942 [/uuvowelsigndeva] 16#20AB [/dong] 16#AB [/guillemotleft] 16#FE4F [/underscorewavy] 16#1E4F [/otildedieresis] 16#248A [/threeperiod] 16#AC5 [/ecandravowelsigngujarati] 16#222E [/contourintegral] 16#3B1 [/alpha] 16#9EC [/sixbengali] 16#155 [/racute] 16#3027 [/sevenhangzhou] 16#2790 [/sevencircleinversesansserif] 16#1EF9 [/ytilde] 16#FEF9 [/lamalefhamzabelowisolatedarabic] 16#2534 [/SF070000] 16#534 [/Daarmenian] 16#2D8 [/breve] 16#913 [/odeva] 16#7C [/verticalbar /bar] 16#207C [/equalsuperior] 16#F7E5 [/Aringsmall] 16#1E20 [/Gmacron] 16#45B [/tshecyrillic /afii10108] 16#A96 [/khagujarati] 16#1FF [/ostrokeacute /oslashacute] 16#30D1 [/pakatakana] 16#5DE [/memhebrew /mem /afii57678] 16#2126 [/Ohm /Omega] 16#F88F [/maitholowleftthai] 16#126 [/Hbar] 16#FECA [/ainfinalarabic] 16#1ECA [/Idotbelow] 16#317B [/siosnieunkorean] 16#4D [/M] 16#688 [/ddalarabic /afii57512] 16#42C [/afii10046 /Softsigncyrillic] 16#FB95 [/gafmedialarabic] 16#A67 [/onegurmukhi] 16#1D0 [/icaron] 16#21D0 [/arrowleftdbl /arrowdblleft] 16#30A2 [/akatakana] 16#FF74 [/ekatakanahalfwidth] 16#F6DD [/rupiah] 16#E46 [/maiyamokthai] 16#5AF [/masoracirclehebrew] 16#3225 [/sixideographicparen] 16#F7 [/divide] 16#FE9B [/thehinitialarabic] 16#1E9B [/slongdotaccent] 16#24D6 [/gcircle] 16#4D6 [/Iebrevecyrillic] 16#33A8 [/moverssquaredsquare] 16#227A [/precedes] 16#27A [/rlonglegturned] 16#314C [/thieuthkorean] 16#1E [/controlRS] 16#201E [/quotedblbase] 16#A38 [/sagurmukhi] 16#1A1 [/ohorn] 16#3073 [/bihiragana] 16#FF45 [/emonospace] 16#E17 [/thothahanthai] 16#2580 [/upblock] 16#580 [/reharmenian] 16#324 [/dieresisbelowcmb] 16#95F [/yyadeva] 16#C8 [/Egrave] 16#1E6C [/Tdotbelow] 16#4A7 [/pemiddlehookcyrillic] 16#24A7 [/lparen] 16#311D [/ehbopomofo] 16#62A [/teharabic /afii57418] 16#3CE [/omegatonos] 16#A09 [/ugurmukhi] 16#2172 [/threeroman] 16#172 [/Uogonek] 16#3044 [/ihiragana] 16#FF16 [/sixmonospace] 16#2551 [/SF240000] 16#551 [/Coarmenian] 16#930 [/radeva] 16#1E3D [/lcircumflexbelow] 16#FE3D [/dblanglebracketleftvertical] 16#2478 [/fiveparen] 16#478 [/Ukcyrillic] 16#334A [/miribaarusquare] 16#AB3 [/llagujarati] 16#30EE [/wasmallkatakana] 16#39F [/Omicron] 16#3271 [/rieulacirclekorean] 16#143 [/Nacute] 16#3015 [/tortoiseshellbracketright] 16#1EE7 [/uhookabove] 16#FEE7 [/nooninitialarabic] 16#2C6 [/circumflex] 16#901 [/candrabindudeva] 16#6A [/j] 16#1E0E [/Dlinebelow] 16#449 [/shchacyrillic /afii10091] 16#1ED [/oogonekmacron] 16#30BF [/takatakana] 16#FF91 [/mukatakanahalfwidth] 16#F6FA [/OEsmall] 16#25CC [/dottedcircle] 16#3242 [/ideographicselfparen] 16#9AB [/phabengali] 16#114 [/Ebreve] 16#FEB8 [/sheenmedialarabic] 16#1EB8 [/Edotbelow] 16#4F3 [/uhungarumlautcyrillic] 16#33C5 [/cdsquare] 16#2297 [/timescircle /circlemultiply] 16#297 [/cstretched] 16#3169 [/rieulkiyeoksioskorean] 16#203B [/referencemark] 16#3B [/semicolon] 16#41A [/afii10028 /Kacyrillic] 16#1BE [/glottalinvertedstroke] 16#3090 [/wihiragana] 16#FF62 [/cornerbracketlefthalfwidth] 16#F6CB [/Dieresis] 16#E34 [/saraithai] 16#59D [/gereshmuqdamhebrew] 16#341 [/acutetonecmb] 16#3213 [/pieupaparenkorean] 16#E5 [/aring] 16#1E89 [/wdotbelow] 16#4C4 [/kahookcyrillic] 16#24C4 [/Ocircle] 16#3396 [/mlsquare] 16#268 [/istroke] 16#313A [/rieulkiyeokkorean] 16#200C [/zerowidthnonjoiner /afii61664] 16#C [/controlFF] 16#F775 [/Usmall] 16#647 [/heharabic /afii57470] 16#3EB [/gangiacoptic] 16#A26 [/dagurmukhi] 16#18F [/Schwa] 16#F8F8 [/parenrightbt] 16#3061 [/tihiragana] 16#FF33 [/Smonospace] 16#E05 [/khokhonthai] 16#56E [/caarmenian] 16#312 [/commaturnedabovecmb] 16#2312 [/arc] 16#94D [/viramadeva] 16#B6 [/paragraph] 16#6F1 [/onepersian] 16#FE5A [/parenrightsmall] 16#1E5A [/Rdotbelow] 16#495 [/ghemiddlehookcyrillic] 16#2495 [/fourteenperiod] 16#AD0 [/omgujarati] 16#310B [/nbopomofo] 16#3BC [/mugreek] 16#328E [/ideographmetalcircle] 16#9F7 [/fournumeratorbengali] 16#2160 [/Oneroman] 16#160 [/Scaron] 16#FF04 [/dollarmonospace] 16#53F [/Kenarmenian] 16#2E3 [/xsuperior] 16#91E [/nyadeva] 16#2087 [/seveninferior] 16#F7F0 [/Ethsmall] 16#1E2B [/hbrevebelow] 16#2466 [/sevencircle] 16#466 [/Yuslittlecyrillic] 16#AA1 [/ddagujarati] 16#20A [/Iinvertedbreve] 16#30DC [/bokatakana] 16#5E9 [/shinhebrew /shin /afii57689] 16#9C8 [/aivowelsignbengali] 16#131 [/dotlessi] 16#3003 [/dittomark] 16#1ED5 [/ocircumflexhookabove] 16#2510 [/SF030000] 16#2B4 [/rturnedsuperior] 16#3186 [/yeorinhieuhkorean] 16#58 [/X] 16#437 [/zecyrillic /afii10073] 16#A72 [/irigurmukhi] 16#1DB [/Udieresisgrave] 16#30AD [/kikatakana] 16#FF7F [/sokatakanahalfwidth] 16#F6E8 [/periodsuperior] 16#E51 [/onethai] 16#25BA [/triagrt /blackrightpointingpointer] 16#3230 [/ideographicsunparen] 16#999 [/ngabengali] 16#102 [/Abreve] 16#FEA6 [/khahfinalarabic] 16#1EA6 [/Acircumflexgrave] 16#24E1 [/rcircle] 16#4E1 [/dzeabkhasiancyrillic] 16#33B3 [/mssquare] 16#2285 [/notsuperset] 16#285 [/eshsquatreversed] 16#3157 [/okorean] 16#29 [/parenright] 16#2664 [/spadesuitwhite] 16#664 [/fourhackarabic /fourarabic /afii57396] 16#408 [/afii10057 /Jecyrillic] 16#1AC [/Thook] 16#307E [/mahiragana] 16#FF50 [/pmonospace] 16#E22 [/yoyakthai] 16#32F [/breveinvertedbelowcmb] 16#3201 [/nieunparenkorean] 16#96A [/fourdeva] 16#D3 [/Oacute] 16#1E77 [/ucircumflexbelow] 16#24B2 [/wparen] 16#4B2 [/Hadescendercyrillic] 16#3384 [/kasquare] 16#AED [/sevengujarati] 16#256 [/dtail] 16#3128 [/ubopomofo] 16#F763 [/Csmall] 16#635 [/sadarabic /afii57429] 16#A14 [/augurmukhi] 16#17D [/Zcaron] 16#F8E6 [/arrowvertex] 16#304F [/kuhiragana] 16#FF21 [/Amonospace] 16#55C [/exclamarmenian] 16#255C [/SF270000] 16#300 [/gravecomb /gravecmb] 16#20A4 [/lira /afii08941] 16#A4 [/currency] 16#1E48 [/Nlinebelow] 16#483 [/titlocyrilliccmb] 16#2483 [/sixteenparen] 16#ABE [/aavowelsigngujarati] 16#2227 [/logicaland] 16#30F9 [/vekatakana] 16#F734 [/fouroldstyle] 16#2606 [/whitestar] 16#3AA [/Iotadieresis] 16#14E [/Obreve] 16#3020 [/postalmarkface] 16#FEF2 [/yehfinalarabic] 16#1EF2 [/Ygrave] 16#2D1 [/colontriangularhalfmod] 16#90C [/lvocalicdeva] 16#2075 [/fivesuperior] 16#75 [/u] 16#1E19 [/ecircumflexbelow] 16#454 [/ecyrillic /afii10101] 16#3326 [/dorusquare] 16#A8F [/egujarati] 16#30CA [/nakatakana] 16#FF9C [/wakatakanahalfwidth] 16#5D7 [/hethebrew /het /afii57671] 16#9B6 [/shabengali] 16#11F [/gbreve] 16#F888 [/saraueeleftthai] 16#FEC3 [/tahinitialarabic] 16#1EC3 [/ecircumflexhookabove] 16#33D0 [/lmsquare] 16#2A2 [/glottalstopstrokereversed] 16#3174 [/pieupsioskiyeokkorean] 16#46 [/F] 16#F7AF [/Macronsmall] 16#425 [/afii10039 /Khacyrillic] 16#1C9 [/lj] 16#309B [/voicedmarkkana] 16#FF6D [/yusmallkatakanahalfwidth] 16#F6D6 [/dblgrave] 16#E3F [/bahtthai] 16#25A8 [/squareupperrighttolowerleftfill] 16#5A8 [/qadmahebrew] 16#987 [/ibengali] 16#F0 [/eth] 16#FE94 [/tehmarbutafinalarabic] 16#1E94 [/Zlinebelow] 16#24CF [/Zcircle] 16#33A1 [/squaremsquared] 16#273 [/nhookretroflex] 16#2273 [/greaterorequivalent] 16#3145 [/sioskorean] 16#2017 [/underscoredbl /dbllowline] 16#17 [/controlETB] 16#652 [/sukunarabic /afii57458] 16#19A [/lbar] 16#306C [/nuhiragana] 16#FF3E [/asciicircummonospace] 16#E10 [/thothanthai] 16#579 [/chaarmenian] 16#31D [/uptackbelowcmb] 16#958 [/qadeva] 16#C1 [/Aacute] 16#1E65 [/sacutedotaccent] 16#FE65 [/greatersmall] 16#24A0 [/eparen] 16#4A0 [/Kabashkircyrillic] 16#3116 [/rbopomofo] 16#623 [/afii57411 /alefhamzaabovearabic] 16#3C7 [/chi] 16#FB30 [/alefdageshhebrew] 16#3299 [/ideographicsecretcircle] 16#A02 [/bindigurmukhi] 16#16B [/umacron] 16#216B [/Twelveroman] 16#FF0F [/slashmonospace] 16#54A [/Peharmenian] 16#22EE [/ellipsisvertical] 16#929 [/nnnadeva] 16#F7FB [/Ucircumflexsmall] 16#FE36 [/parenrightvertical] 16#1E36 [/Ldotbelow] 16#471 [/psicyrillic] 16#2471 [/eighteencircle] 16#AAC [/bagujarati] 16#215 [/udblgrave] 16#2215 [/divisionslash] 16#30E7 [/yosmallkatakana] 16#5F4 [/gershayimhebrew] 16#398 [/Theta] 16#FB01 [/fi] 16#326A [/khieukhcirclekorean] 16#13C [/lcommaaccent /lcedilla] 16#300E [/whitecornerbracketleft] 16#FEE0 [/lammedialarabic] 16#1EE0 [/Ohorntilde] 16#2BF [/ringhalfleft] 16#22BF [/righttriangle] 16#63 [/c] 16#1E07 [/blinebelow] 16#442 [/tecyrillic /afii10084] 16#3314 [/kirosquare] 16#21E6 [/arrowleftwhite] 16#1E6 [/Gcaron] 16#30B8 [/zikatakana] 16#FF8A [/hakatakanahalfwidth] 16#F6F3 [/tsuperior] 16#323B [/ideographicstudyparen] 16#9A4 [/tabengali] 16#10D [/ccaron] 16#1EB1 [/abrevegrave] 16#33BE [/kwsquare] 16#290 [/zretroflexhook] 16#3162 [/yikorean] 16#34 [/four] 16#266F [/musicsharpsign] 16#413 [/afii10020 /Gecyrillic] 16#FB7C [/tchehinitialarabic] 16#1B7 [/Ezh] 16#3089 [/rahiragana] 16#FF5B [/braceleftmonospace] 16#F6C4 [/afii10063] 16#E2D [/oangthai] 16#596 [/tipehalefthebrew /tipehahebrew] 16#33A [/bridgeinvertedbelowcmb] 16#320C [/phieuphparenkorean] 16#DE [/Thorn] 16#FE82 [/alefmaddaabovefinalarabic] 16#1E82 [/Wacute] 16#4BD [/cheabkhasiancyrillic] 16#24BD [/Hcircle] 16#338F [/squarekg] 16#261 [/gscript] 16#2261 [/equivalence] 16#3133 [/kiyeoksioskorean] 16#5 [/controlENQ] 16#F76E [/Nsmall] 16#640 [/tatweelarabic /kashidaautonosidebearingarabic /kashidaautoarabic /afii57440] 16#2640 [/venus /female] 16#3E4 [/Feicoptic] 16#FB4D [/kafrafehebrew] 16#A1F [/ttagurmukhi] 16#188 [/chook] 16#F8F1 [/bracelefttp] 16#305A [/zuhiragana] 16#FF2C [/Lmonospace] 16#567 [/eharmenian] 16#2567 [/SF450000] 16#30B [/hungarumlautcmb] 16#946 [/eshortvowelsigndeva] 16#AF [/overscore /macron] 16#1E53 [/omacronacute] 16#248E [/sevenperiod] 16#AC9 [/ocandravowelsigngujarati] 16#F73F [/questionsmall] 16#3B5 [/epsilon] 16#9F0 [/ramiddlediagonalbengali] 16#159 [/rcaron] 16#538 [/Etarmenian] 16#FCA1 [/tehjeeminitialarabic] 16#2DC [/ilde /tilde] 16#917 [/gadeva] 16#2080 [/zeroinferior] 16#F7E9 [/Eacutesmall] 16#1E24 [/Hdotbelow] 16#45F [/dzhecyrillic /afii10193] 16#3331 [/birusquare] 16#A9A [/cagujarati] 16#2203 [/thereexists /existential] 16#203 [/ainvertedbreve] 16#30D5 [/hukatakana] 16#25E2 [/blacklowerrighttriangle] 16#5E2 [/ayin /afii57682 /ayinhebrew] 16#386 [/Alphatonos] 16#9C1 [/uvowelsignbengali] 16#12A [/Imacron] 16#F893 [/maichattawaupperleftthai] 16#FECE [/ghainfinalarabic] 16#1ECE [/Ohookabove] 16#33DB [/srsquare] 16#317F [/pansioskorean] 16#51 [/Q] 16#430 [/acyrillic /afii10065] 16#A6B [/fivegurmukhi] 16#1D4 [/ucaron] 16#21D4 [/dblarrowleft /arrowdblboth] 16#30A6 [/ukatakana] 16#FF78 [/kukatakanahalfwidth] 16#F6E1 [/commainferior] 16#E4A [/maitrithai] 16#25B3 [/whiteuppointingtriangle] 16#5B3 [/hatafqamatswidehebrew /hatafqamatsquarterhebrew /hatafqamatsnarrowhebrew /hatafqamatshebrew /hatafqamats34 /hatafqamats28 /hatafqamats1b /hatafqamats /afii57802] 16#3229 [/tenideographicparen] 16#FB [/ucircumflex] 16#FE9F [/jeeminitialarabic] 16#24DA [/kcircle] 16#4DA [/Schwadieresiscyrillic] 16#33AC [/gpasquare] 16#27E [/rfishhook] 16#3150 [/aekorean] 16#22 [/quotedbl] 16#2022 [/bullet] 16#401 [/afii10023 /Iocyrillic] 16#A3C [/nuktagurmukhi] 16#1A5 [/phook] 16#3077 [/puhiragana] 16#FF49 [/imonospace] 16#E1B [/poplathai] 16#584 [/keharmenian] 16#2584 [/dnblock] 16#328 [/ogonekcmb] 16#963 [/llvocalicvowelsigndeva] 16#CC [/Igrave] 16#1E70 [/Tcircumflexbelow] 16#24AB [/pparen] 16#4AB [/esdescendercyrillic] 16#337D [/taisyouerasquare] 16#AE6 [/zerogujarati] 16#3121 [/oubopomofo] 16#62E [/khaharabic /afii57422] 16#3D2 [/Upsilonhooksymbol /Upsilon1] 16#FB3B [/kafdageshhebrew /kafdagesh] 16#32A4 [/ideographichighcircle] 16#2176 [/sevenroman] 16#176 [/Ycircumflex] 16#3048 [/ehiragana] 16#FF1A [/colonmonospace] 16#555 [/Oharmenian] 16#2555 [/SF220000] 16#934 [/llladeva] 16#1E41 [/mdotaccent] 16#FE41 [/cornerbracketleftvertical] 16#247C [/nineparen] 16#47C [/Omegatitlocyrillic] 16#334E [/yaadosquare] 16#AB7 [/ssagujarati] 16#2220 [/angle] 16#30F2 [/wokatakana] 16#3A3 [/Sigma] 16#3275 [/ieungacirclekorean] 16#147 [/Ncaron] 16#3019 [/whitetortoiseshellbracketright] 16#1EEB [/uhorngrave] 16#FEEB [/hehinitialarabic] 16#2CA [/secondtonechinese] 16#905 [/adeva] 16#6E [/n] 16#1E12 [/Dcircumflexbelow] 16#44D [/ereversedcyrillic /afii10095] 16#A88 [/iigujarati] 16#1F1 [/DZ] 16#30C3 [/tusmallkatakana] 16#FF95 [/yukatakanahalfwidth] 16#F6FE [/Tildesmall] 16#25D0 [/circlewithlefthalfblack] 16#5D0 [/alefhebrew /afii57664 /alef] 16#374 [/numeralsigngreek] 16#9AF [/yabengali] 16#118 [/Eogonek] 16#2118 [/weierstrass] 16#FEBC [/sadmedialarabic] 16#1EBC [/Etilde] 16#FC60 [/shaddafathaarabic] 16#33C9 [/gysquare] 16#29B [/Gsmallhook] 16#316D [/rieulyeorinhieuhkorean] 16#3F [/question] 16#F7A8 [/Dieresissmall] 16#41E [/afii10032 /Ocyrillic] 16#A59 [/khhagurmukhi] 16#1C2 [/clickalveolar] 16#3094 [/vuhiragana] 16#FF66 [/wokatakanahalfwidth] 16#F6CF [/Hungarumlaut] 16#E38 [/sarauthai] 16#25A1 [/whitesquare /H22073] 16#5A1 [/pazerhebrew] 16#345 [/ypogegrammenigreekcmb] 16#3217 [/chieuchaparenkorean] 16#E9 [/eacute] 16#1E8D [/xdieresis] 16#4C8 [/enhookcyrillic] 16#24C8 [/Scircle] 16#339A [/nmsquare] 16#26C [/lbelt] 16#313E [/rieulthieuthkorean] 16#2010 [/hyphentwo] 16#10 [/controlDLE] 16#F779 [/Ysmall] 16#64B [/fathatanarabic /afii57451] 16#3EF [/deicoptic] 16#FB58 [/pehinitialarabic] 16#A2A [/pagurmukhi] 16#193 [/Ghook] 16#F8FC [/bracerighttp] 16#3065 [/duhiragana] 16#2193 [/arrowdown] 16#FF37 [/Wmonospace] 16#E09 [/chochingthai] 16#572 [/ghadarmenian] 16#316 [/gravebelowcmb] 16#951 [/udattadeva] 16#BA [/ordmasculine] 16#6F5 [/fivepersian] 16#FE5E [/tortoiseshellbracketrightsmall] 16#1E5E [/Rlinebelow] 16#499 [/zedescendercyrillic] 16#2499 [/eighteenperiod] 16#223D [/reversedtilde] 16#310F [/hbopomofo] 16#FFE1 [/sterlingmonospace] 16#261C [/pointingindexleftwhite] 16#3C0 [/pi] 16#2164 [/Fiveroman] 16#164 [/Tcaron] 16#3036 [/circlepostalmark] 16#FF08 [/parenleftmonospace] 16#543 [/Cheharmenian] 16#2E7 [/tonebarmidmod] 16#922 [/ddhadeva] 16#F7F4 [/Ocircumflexsmall] 16#1E2F [/idieresisacute] 16#246A [/elevencircle] 16#46A [/Yusbigcyrillic] 16#AA5 [/thagujarati] 16#20E [/Oinvertedbreve] 16#30E0 [/mukatakana] 16#391 [/Alpha] 16#3263 [/rieulcirclekorean] 16#9CC [/auvowelsignbengali] 16#135 [/jcircumflex] 16#2135 [/aleph] 16#3007 [/ideographiczero] 16#1ED9 [/ocircumflexdotbelow] 16#2514 [/SF020000] 16#2B8 [/ysuperior] 16#318A [/yuyeokorean] 16#5C [/backslash] 16#1E00 [/Aringbelow] 16#43B [/elcyrillic /afii10077] 16#FBA4 [/hehhamzaaboveisolatedarabic] 16#330D [/karoriisquare] 16#21DF [/pagedown] 16#1DF [/adieresismacron] 16#30B1 [/kekatakana] 16#FF83 [/tekatakanahalfwidth] 16#F6EC [/esuperior] 16#E55 [/fivethai] 16#5BE [/maqafhebrew /afii57645] 16#3234 [/ideographicnameparen] 16#99D [/jhabengali] 16#106 [/Cacute] 16#FEAA [/dalfinalarabic] 16#1EAA [/Acircumflextilde] 16#24E5 [/vcircle] 16#FC4E [/noonmeemisolatedarabic] 16#33B7 [/mvsquare] 16#4E5 [/idieresiscyrillic] 16#289 [/ubar] 16#315B [/yokorean] 16#202D [/afii61574] 16#2D [/hyphen] 16#2668 [/hotsprings] 16#668 [/eightarabic /eighthackarabic /afii57400] 16#40C [/afii10061 /Kjecyrillic] 16#A47 [/eematragurmukhi] 16#1B0 [/uhorn] 16#3082 [/mohiragana] 16#FF54 [/tmonospace] 16#E26 [/luthai] 16#333 [/dbllowlinecmb] 16#3205 [/pieupparenkorean] 16#96E [/eightdeva] 16#D7 [/multiply] 16#1E7B [/umacrondieresis] 16#24B6 [/Acircle] 16#4B6 [/Chedescendercyrillic] 16#3388 [/calsquare] 16#25A [/schwahook] 16#F767 [/Gsmall] 16#639 [/afii57433 /ainarabic] 16#FB46 [/tsadidageshhebrew /tsadidagesh] 16#A18 [/ghagurmukhi] 16#181 [/Bhook] 16#F8EA [/trademarksans] 16#3053 [/kohiragana] 16#FF25 [/Emonospace] 16#2560 [/SF420000] 16#FCC9 [/lamjeeminitialarabic] 16#304 [/macroncmb] 16#93F [/ivowelsigndeva] 16#A8 [/dieresis] 16#FE4C [/overlinedblwavy] 16#1E4C [/Otildeacute] 16#2487 [/twentyparen] 16#AC2 [/uuvowelsigngujarati] 16#222B [/integral] 16#30FD [/iterationkatakana] 16#F738 [/eightoldstyle] 16#3AE [/etatonos] 16#9E9 [/threebengali] 16#152 [/OE] 16#3024 [/fourhangzhou] 16#278D [/fourcircleinversesansserif] 16#FEF6 [/lamalefmaddaabovefinalarabic] 16#1EF6 [/Yhookabove] 16#531 [/Aybarmenian] 16#2D5 [/downtackmod] 16#910 [/aideva] 16#2079 [/ninesuperior] 16#F7E2 [/Acircumflexsmall] 16#79 [/y] 16#1E1D [/ecedillabreve] 16#458 [/jecyrillic /afii10105] 16#332A [/haitusquare] 16#A93 [/ogujarati] 16#1FC [/AEacute] 16#30CE [/nokatakana] 16#5DB [/kafhebrew /kaf /afii57675] 16#123 [/gcommaaccent /gcedilla] 16#F88C [/maieklowleftthai] 16#FEC7 [/zahinitialarabic] 16#1EC7 [/ecircumflexdotbelow] 16#2502 [/SF110000] 16#33D4 [/mbsquare] 16#2A6 [/ts] 16#3178 [/kapyeounpieupkorean] 16#4A [/J] 16#429 [/afii10043 /Shchacyrillic] 16#21CD [/arrowleftdblstroke] 16#1CD [/Acaron] 16#FF71 [/akatakanahalfwidth] 16#F6DA [/registerserif] 16#E43 [/saraaimaimuanthai] 16#5AC [/iluyhebrew] 16#25AC [/filledrect /blackrectangle] 16#3222 [/threeideographicparen] 16#98B [/rvocalicbengali] 16#F4 [/ocircumflex] 16#FE98 [/tehmedialarabic] 16#1E98 [/wring] 16#24D3 [/dcircle] 16#4D3 [/adieresiscyrillic] 16#33A5 [/mcubedsquare] 16#277 [/omegalatinclosed] 16#2277 [/greaterorless] 16#3149 [/ssangcieuckorean] 16#201B [/quotereversed /quoteleftreversed] 16#1B [/controlESC] 16#A35 [/vagurmukhi] 16#19E [/nlegrightlong] 16#3070 [/bahiragana] 16#FF42 [/bmonospace] 16#E14 [/dodekthai] 16#57D [/seharmenian] 16#321 [/hookpalatalizedbelowcmb] 16#2321 [/integralbottom /integralbt] 16#95C [/dddhadeva] 16#C5 [/Aring] 16#1E69 [/sdotbelowdotaccent] 16#FE69 [/dollarsmall] 16#24A4 [/iparen] 16#4A4 [/Enghecyrillic] 16#2248 [/approxequal] 16#311A [/abopomofo] 16#627 [/afii57415 /alefarabic] 16#3CB [/upsilondieresis] 16#FB34 [/hedageshhebrew /hedagesh] 16#329D [/ideographicexcellentcircle] 16#A06 [/aagurmukhi] 16#16F [/uring] 16#3041 [/asmallhiragana] 16#FF13 [/threemonospace] 16#54E [/Vewarmenian] 16#92D [/bhadeva] 16#F7FF [/Ydieresissmall] 16#6D1 [/yehthreedotsbelowarabic] 16#FE3A [/tortoiseshellbracketrightvertical] 16#1E3A [/Llinebelow] 16#2475 [/twoparen] 16#475 [/izhitsacyrillic /afii10196] 16#3347 [/mansyonsquare] 16#AB0 [/ragujarati] 16#219 [/scommaaccent] 16#2219 [/bulletoperator] 16#30EB [/rukatakana] 16#F726 [/ampersandsmall] 16#39C [/Mu] 16#326E [/kiyeokacirclekorean] 16#9D7 [/aulengthmarkbengali] 16#140 [/ldotaccent /ldot] 16#3012 [/postalmark] 16#FEE4 [/meemmedialarabic] 16#1EE4 [/Udotbelow] 16#2C3 [/arrowheadrightmod] 16#67 [/g] 16#1E0B [/ddotaccent] 16#446 [/tsecyrillic /afii10088] 16#FBAF [/yehbarreefinalarabic] 16#3318 [/guramusquare] 16#A81 [/candrabindugujarati] 16#21EA [/capslock] 16#1EA [/Oogonek] 16#30BC [/zekatakana] 16#FF8E [/hokatakanahalfwidth] 16#F6F7 [/Dotaccentsmall] 16#25C9 [/fisheye] 16#323F [/ideographicallianceparen] 16#9A8 [/nabengali] 16#111 [/dmacron /dcroat] 16#2111 [/Ifraktur] 16#1EB5 [/abrevetilde] 16#4F0 [/Udieresiscyrillic] 16#33C2 [/amsquare] 16#294 [/glottalstop] 16#3166 [/nieuntikeutkorean] 16#38 [/eight] 16#F7A1 [/exclamdownsmall] 16#417 [/Zecyrillic /afii10025] 16#1BB [/twostroke] 16#308D [/rohiragana] 16#F6C8 [/afii10832] 16#E31 [/maihanakatthai] 16#59A [/yetivhebrew] 16#33E [/tildeverticalcmb] 16#3210 [/tikeutaparenkorean] 16#E2 [/acircumflex] 16#FE86 [/wawhamzaabovefinalarabic] 16#1E86 [/Wdotaccent] 16#4C1 [/Zhebrevecyrillic] 16#24C1 [/Lcircle] 16#3393 [/ghzsquare] 16#265 [/hturned] 16#2265 [/greaterequal] 16#3137 [/tikeutkorean] 16#9 [/controlHT] 16#F772 [/Rsmall] 16#644 [/lamarabic /afii57444] 16#3E8 [/Horicoptic] 16#A23 [/nnagurmukhi] 16#18C [/dtopbar] 16#F8F5 [/integralex] 16#305E [/zohiragana] 16#FF30 [/Pmonospace] 16#E02 [/khokhaithai] 16#56B [/iniarmenian] 16#256B [/SF530000] 16#30F [/dblgravecmb] 16#94A [/oshortvowelsigndeva] 16#B3 [/threesuperior] 16#1E57 [/pdotaccent] 16#2492 [/elevenperiod] 16#492 [/Ghestrokecyrillic] 16#ACD [/viramagujarati] 16#2236 [/ratio] 16#3108 [/fbopomofo] 16#3B9 [/iota] 16#328B [/ideographfirecircle] 16#9F4 [/onenumeratorbengali] 16#15D [/scircumflex] 16#215D [/fiveeighths] 16#FF01 [/exclammonospace] 16#53C [/Liwnarmenian] 16#253C [/SF050000] 16#2E0 [/gammasuperior] 16#91B [/chadeva] 16#2084 [/fourinferior] 16#F7ED [/Iacutesmall] 16#1E28 [/Hcedilla] 16#463 [/yatcyrillic /afii10194] 16#2463 [/fourcircle] 16#A9E [/nyagujarati] 16#2207 [/nabla /gradient] 16#207 [/einvertedbreve] 16#30D9 [/bekatakana] 16#5E6 [/tsadihebrew /tsadi /afii57686] 16#25E6 [/whitebullet /openbullet] 16#38A [/Iotatonos] 16#12E [/Iogonek] 16#212E [/estimated] 16#F897 [/thanthakhatlowrightthai] 16#3000 [/ideographicspace] 16#FED2 [/fehfinalarabic] 16#1ED2 [/Ocircumflexgrave] 16#2B1 [/hhooksuperior] 16#3183 [/yesieungpansioskorean] 16#55 [/U] 16#434 [/decyrillic /afii10069] 16#A6F [/ninegurmukhi] 16#1D8 [/udieresisacute] 16#30AA [/okatakana] 16#FF7C [/sikatakanahalfwidth] 16#F6E5 [/hypheninferior] 16#E4E [/yamakkanthai] 16#25B7 [/whiterightpointingtriangle] 16#5B7 [/patahwidehebrew /patahquarterhebrew /patahnarrowhebrew /patahhebrew /patah2a /patah1d /patah11 /patah /afii57798] 16#322D [/ideographicwoodparen] 16#996 [/khabengali] 16#FF [/ydieresis] 16#FEA3 [/hahinitialarabic] 16#1EA3 [/ahookabove] 16#24DE [/ocircle] 16#4DE [/Zedieresiscyrillic] 16#33B0 [/pssquare] 16#2282 [/subset /propersubset] 16#282 [/shook] 16#3154 [/ekorean] 16#26 [/ampersand] 16#2026 [/ellipsis] 16#661 [/onehackarabic /onearabic /afii57393] 16#2661 [/heartsuitwhite] 16#405 [/afii10054 /Dzecyrillic] 16#A40 [/iimatragurmukhi] 16#1A9 [/Esh] 16#307B [/hohiragana] 16#FF4D [/mmonospace] 16#E1F [/fofanthai] 16#2588 [/block] 16#32C [/caronbelowcmb] 16#967 [/onedeva] 16#D0 [/Eth] 16#1E74 [/Utildebelow] 16#4AF [/ustraightcyrillic] 16#24AF [/tparen] 16#3381 [/nasquare] 16#AEA [/fourgujarati] 16#2253 [/imageorapproximatelyequal] 16#253 [/bhook] 16#3125 [/engbopomofo] 16#F760 [/Gravesmall] 16#632 [/zainarabic /afii57426] 16#3D6 [/pisymbolgreek /omega1] 16#32A8 [/ideographicrightcircle] 16#17A [/zacute] 16#217A [/elevenroman] 16#304C [/gahiragana] 16#FF1E [/greatermonospace] 16#559 [/ringhalfleftarmenian] 16#2559 [/SF490000] 16#938 [/sadeva] 16#20A1 [/colonmonetary /colonsign] 16#A1 [/exclamdown] 16#1E45 [/ndotaccent] 16#2480 [/thirteenparen] 16#480 [/Koppacyrillic] 16#30F6 [/kesmallkatakana] 16#F731 [/oneoldstyle] 16#3A7 [/Chi] 16#3279 [/thieuthacirclekorean] 16#9E2 [/lvocalicvowelsignbengali] 16#14B [/eng] 16#301D [/quotedblprimereversed] 16#1EEF [/uhorntilde] 16#2CE [/gravelowmod] 16#22CE [/curlyor] 16#909 [/udeva] 16#72 [/r] 16#1E16 [/Emacronacute] 16#451 [/iocyrillic /afii10071] 16#3323 [/sentosquare] 16#1F5 [/gacute] 16#30C7 [/dekatakana] 16#FF99 [/rukatakanahalfwidth] 16#5D4 [/hehebrew /he /afii57668] 16#11C [/Gcircumflex] 16#F885 [/saraileftthai] 16#211C [/Rfraktur] 16#FEC0 [/dadmedialarabic] 16#1EC0 [/Ecircumflexgrave] 16#33CD [/KKsquare] 16#3171 [/kapyeounmieumkorean] 16#43 [/C] 16#67E [/peharabic /afii57506] 16#422 [/afii10036 /Tecyrillic] 16#FB8B [/jehfinalarabic] 16#1C6 [/dzcaron] 16#21C6 [/arrowleftoverright] 16#FF6A [/esmallkatakanahalfwidth] 16#F6D3 [/dblGrave] 16#25A5 [/squareverticalfill] 16#5A5 [/merkhalefthebrew /merkhahebrew] 16#321B [/hieuhaparenkorean] 16#ED [/iacute] 16#1E91 [/zcircumflex] 16#FE91 [/behinitialarabic] 16#4CC [/chekhakassiancyrillic] 16#24CC [/Wcircle] 16#339E [/squarekm] 16#270 [/mlonglegturned] 16#2270 [/notlessnorequal] 16#3142 [/pieupkorean] 16#14 [/controlDC4] 16#2014 [/emdash] 16#64F [/dammalowarabic /dammaarabic /afii57455] 16#3F3 [/yotgreek] 16#A2E [/magurmukhi] 16#2197 [/arrowupright] 16#197 [/Istroke] 16#3069 [/dohiragana] 16#FF3B [/bracketleftmonospace] 16#E0D [/yoyingthai] 16#576 [/nowarmenian] 16#31A [/leftangleabovecmb] 16#BE [/threequarters] 16#6F9 [/ninepersian] 16#FE62 [/plussmall] 16#1E62 [/Sdotbelow] 16#49D [/kaverticalstrokecyrillic] 16#249D [/bparen] 16#3113 [/zhbopomofo] 16#FFE5 [/yenmonospace] 16#3C4 [/tau] 16#FB2D [/shindageshsindothebrew /shindageshsindot] 16#3296 [/ideographicfinancialcircle] 16#168 [/Utilde] 16#2168 [/Nineroman] 16#FF0C [/commamonospace] 16#547 [/Shaarmenian] 16#926 [/dadeva] 16#F7F8 [/Oslashsmall] 16#FE33 [/underscorevertical] 16#1E33 [/kdotbelow] 16#246E [/fifteencircle] 16#46E [/Ksicyrillic] 16#212 [/Rinvertedbreve] 16#2212 [/minus] 16#30E4 [/yakatakana] 16#5F1 [/vavyodhebrew /afii57717] 16#395 [/Epsilon] 16#3267 [/ieungcirclekorean] 16#139 [/Lacute] 16#300B [/dblanglebracketright] 16#1EDD [/ohorngrave] 16#2518 [/SF040000] 16#2BC [/apostrophemod /afii57929] 16#318E [/araeaekorean] 16#60 [/grave] 16#1E04 [/Bdotbelow] 16#43F [/pecyrillic /afii10081] 16#FBA8 [/hehinitialaltonearabic] 16#1E3 [/aemacron] 16#21E3 [/arrowdashdown] 16#30B5 [/sakatakana] 16#FF87 [/nukatakanahalfwidth] 16#F6F0 [/osuperior] 16#E59 [/ninethai] 16#5C2 [/sindothebrew /afii57803] 16#3238 [/ideographiclaborparen] 16#9A1 [/ddabengali] 16#10A [/Cdotaccent /Cdot] 16#FEAE [/rehfinalarabic] 16#1EAE [/Abreveacute] 16#24E9 [/zcircle] 16#4E9 [/obarredcyrillic] 16#33BB [/nwsquare] 16#28D [/wturned] 16#315F [/wikorean] 16#31 [/one] 16#66C [/thousandsseparatorpersian /thousandsseparatorarabic] 16#266C [/beamedsixteenthnotes] 16#410 [/afii10017 /Acyrillic] 16#A4B [/oomatragurmukhi] 16#1B4 [/yhook] 16#3086 [/yuhiragana] 16#FF58 [/xmonospace] 16#E2A [/sosuathai] 16#2593 [/shadedark /dkshade] 16#593 [/shalshelethebrew] 16#337 [/solidusshortoverlaycmb] 16#3209 [/chieuchparenkorean] 16#DB [/Ucircumflex] 16#1E7F [/vdotbelow] 16#4BA [/Shhacyrillic] 16#24BA [/Ecircle] 16#338C [/mufsquare] 16#25E [/eopenreversedclosed] 16#2002 [/enspace] 16#2 [/controlSOT] 16#F76B [/Ksmall] 16#FB4A [/tavdageshhebrew /tavdagesh /tavdages] 16#A1C [/jagurmukhi] 16#185 [/tonesix] 16#F8EE [/bracketlefttp] 16#3057 [/sihiragana] 16#FF29 [/Imonospace] 16#564 [/daarmenian] 16#2564 [/SF470000] 16#308 [/dieresiscmb] 16#943 [/rvocalicvowelsigndeva] 16#20AC [/euro /Euro] 16#AC [/logicalnot] 16#FE50 [/commasmall] 16#1E50 [/Omacrongrave] 16#248B [/fourperiod] 16#260E [/telephoneblack] 16#3B2 [/beta] 16#9ED [/sevenbengali] 16#156 [/Rcommaaccent /Rcedilla] 16#3028 [/eighthangzhou] 16#2791 [/eightcircleinversesansserif] 16#FEFA [/lamalefhamzabelowfinalarabic] 16#535 [/Echarmenian] 16#2D9 [/dotaccent] 16#914 [/audeva] 16#207D [/parenleftsuperior] 16#F7E6 [/AEsmall] 16#7D [/braceright] 16#1E21 [/gmacron] 16#45C [/kjecyrillic /afii10109] 16#A97 [/gagujarati] 16#200 [/Adblgrave] 16#2200 [/universal /forall] 16#30D2 [/hikatakana] 16#5DF [/finalnunhebrew /finalnun /afii57679] 16#9BE [/aavowelsignbengali] 16#127 [/hbar] 16#F890 [/maitriupperleftthai] 16#1ECB [/idotbelow] 16#FECB [/aininitialarabic] 16#33D8 [/pmsquare] 16#317C [/siostikeutkorean] 16#4E [/N] 16#FDF2 [/lamlamhehisolatedarabic] 16#42D [/afii10047 /Ereversedcyrillic] 16#A68 [/twogurmukhi] 16#1D1 [/Ocaron] 16#21D1 [/arrowdblup] 16#30A3 [/ismallkatakana] 16#FF75 [/okatakanahalfwidth] 16#F6DE [/threequartersemdash] 16#E47 [/maitaikhuthai] 16#5B0 [/shevawidehebrew /shevaquarterhebrew /shevanarrowhebrew /shevahebrew /sheva2e /sheva22 /sheva15 /sheva115 /sheva /afii57799] 16#3226 [/sevenideographicparen] 16#98F [/ebengali] 16#F8 [/oslash] 16#FE9C [/thehmedialarabic] 16#24D7 [/hcircle] 16#4D7 [/iebrevecyrillic] 16#33A9 [/pasquare] 16#227B [/succeeds] 16#27B [/rhookturned] 16#314D [/phieuphkorean] 16#1F [/controlUS] 16#FB67 [/ttehfinalarabic] 16#A39 [/hagurmukhi] 16#1A2 [/Oi] 16#3074 [/pihiragana] 16#FF46 [/fmonospace] 16#E18 [/thothongthai] 16#581 [/coarmenian] 16#325 [/ringbelowcmb] 16#2325 [/option] 16#960 [/rrvocalicdeva] 16#C9 [/Eacute] 16#1E6D [/tdotbelow] 16#24A8 [/mparen] 16#4A8 [/Haabkhasiancyrillic] 16#224C [/allequal] 16#311E [/aibopomofo] 16#62B [/theharabic /afii57419] 16#FB38 [/tetdageshhebrew /tetdagesh] 16#A0A [/uugurmukhi] 16#173 [/uogonek] 16#2173 [/fourroman] 16#3045 [/usmallhiragana] 16#FF17 [/sevenmonospace] 16#552 [/Yiwnarmenian] 16#2552 [/SF510000] 16#931 [/rradeva] 16#6D5 [/afii57534] 16#FE3E [/dblanglebracketrightvertical] 16#1E3E [/Macute] 16#479 [/ukcyrillic] 16#2479 [/sixparen] 16#221D [/proportional] 16#30EF [/wakatakana] 16#3A0 [/Pi] 16#3272 [/mieumacirclekorean] 16#144 [/nacute] 16#3016 [/whitelenticularbracketleft] 16#FEE8 [/noonmedialarabic] 16#1EE8 [/Uhornacute] 16#2C7 [/caron] 16#902 [/anusvaradeva] 16#6B [/k] 16#1E0F [/dlinebelow] 16#44A [/hardsigncyrillic /afii10092] 16#A85 [/agujarati] 16#1EE [/Ezhcaron] 16#30C0 [/dakatakana] 16#FF92 [/mekatakanahalfwidth] 16#F6FB [/Ogoneksmall] 16#3243 [/ideographicreachparen] 16#9AC [/babengali] 16#115 [/ebreve] 16#1EB9 [/edotbelow] 16#4F4 [/Chedieresiscyrillic] 16#33C6 [/coverkgsquare] 16#298 [/bilabialclick] 16#316A [/rieultikeutkorean] 16#203C [/exclamdbl] 16#3C [/less] 16#41B [/afii10029 /Elcyrillic] 16#1BF [/wynn] 16#3091 [/wehiragana] 16#FF63 [/cornerbracketrighthalfwidth] 16#F6CC [/DieresisAcute] 16#E35 [/saraiithai] 16#59E [/gershayimaccenthebrew] 16#342 [/perispomenigreekcmb] 16#3214 [/siosaparenkorean] 16#E6 [/ae] 16#FE8A [/yehhamzaabovefinalarabic] 16#1E8A [/Xdotaccent] 16#24C5 [/Pcircle] 16#3397 [/dlsquare] 16#269 [/iotalatin] 16#313B [/rieulmieumkorean] 16#D [/controlCR] 16#200D [/afii301] 16#F776 [/Vsmall] 16#648 [/wawarabic /afii57448] 16#3EC [/Shimacoptic] 16#A27 [/dhagurmukhi] 16#190 [/Eopen] 16#F8F9 [/bracketrighttp] 16#3062 [/dihiragana] 16#2190 [/arrowleft] 16#FF34 [/Tmonospace] 16#E06 [/khorakhangthai] 16#56F [/kenarmenian] 16#313 [/commaabovecmb] 16#B7 [/middot /periodcentered] 16#6F2 [/twopersian] 16#1E5B [/rdotbelow] 16#FE5B [/braceleftsmall] 16#2496 [/fifteenperiod] 16#496 [/Zhedescendercyrillic] 16#310C [/lbopomofo] 16#3BD [/nu] 16#328F [/ideographearthcircle] 16#9F8 [/denominatorminusonenumeratorbengali] 16#161 [/scaron] 16#2161 [/Tworoman] 16#FF05 [/percentmonospace] 16#540 [/Hoarmenian] 16#2E4 [/glottalstopreversedsuperior] 16#91F [/ttadeva] 16#2088 [/eightinferior] 16#F7F1 [/Ntildesmall] 16#1E2C [/Itildebelow] 16#467 [/yuslittlecyrillic] 16#2467 [/eightcircle] 16#3339 [/herutusquare] 16#AA2 [/ddhagujarati] 16#20B [/iinvertedbreve] 16#220B [/suchthat] 16#30DD [/pokatakana] 16#5EA [/tavhebrew /tav /afii57690] 16#38E [/Upsilontonos] 16#3260 [/kiyeokcirclekorean] 16#132 [/IJ] 16#3004 [/jis] 16#FED6 [/qaffinalarabic] 16#1ED6 [/Ocircumflextilde] 16#2B5 [/rhookturnedsuperior] 16#3187 [/yoyakorean] 16#59 [/Y] 16#438 [/iicyrillic /afii10074] 16#A73 [/uragurmukhi] 16#1DC [/udieresisgrave] 16#30AE [/gikatakana] 16#FF80 [/takatakanahalfwidth] 16#F6E9 [/asuperior] 16#E52 [/twothai] 16#5BB [/qubutswidehebrew /qubutsquarterhebrew /qubutsnarrowhebrew /qubutshebrew /qubuts31 /qubuts25 /qubuts18 /qubuts /afii57796] 16#3231 [/ideographicstockparen] 16#99A [/cabengali] 16#2103 [/centigrade] 16#103 [/abreve] 16#FEA7 [/khahinitialarabic] 16#1EA7 [/acircumflexgrave] 16#24E2 [/scircle] 16#FC4B [/noonjeemisolatedarabic] 16#33B4 [/pvsquare] 16#4E2 [/Imacroncyrillic] 16#2286 [/subsetorequal /reflexsubset] 16#286 [/eshcurl] 16#3158 [/wakorean] 16#2A [/asterisk] 16#665 [/fivehackarabic /fivearabic /afii57397] 16#2665 [/heartsuitblack /heart] 16#409 [/afii10058 /Ljecyrillic] 16#1AD [/thook] 16#307F [/mihiragana] 16#FF51 [/qmonospace] 16#E23 [/roruathai] 16#258C [/lfblock] 16#330 [/tildebelowcmb] 16#3202 [/tikeutparenkorean] 16#96B [/fivedeva] 16#D4 [/Ocircumflex] 16#1E78 [/Utildeacute] 16#24B3 [/xparen] 16#4B3 [/hadescendercyrillic] 16#3385 [/KBsquare] 16#AEE [/eightgujarati] 16#257 [/dhook] 16#3129 [/iubopomofo] 16#F764 [/Dsmall] 16#636 [/dadarabic /afii57430] 16#3DA [/Stigmagreek] 16#FB43 [/pefinaldageshhebrew] 16#A15 [/kagurmukhi] 16#17E [/zcaron] 16#F8E7 [/arrowhorizex] 16#3050 [/guhiragana] 16#FF22 [/Bmonospace] 16#55D [/commaarmenian] 16#255D [/SF260000] 16#301 [/acutecomb /acutecmb] 16#93C [/nuktadeva] 16#A5 [/yen] 16#FE49 [/overlinedashed] 16#1E49 [/nlinebelow] 16#2484 [/seventeenparen] 16#484 [/palatalizationcyrilliccmb] 16#ABF [/ivowelsigngujarati] 16#2228 [/logicalor] 16#30FA [/vokatakana] 16#F735 [/fiveoldstyle] 16#3AB [/Upsilondieresis] 16#9E6 [/zerobengali] 16#14F [/obreve] 16#3021 [/onehangzhou] 16#278A [/onecircleinversesansserif] 16#FEF3 [/yehinitialarabic /alefmaksurainitialarabic] 16#1EF3 [/ygrave] 16#2D2 [/ringhalfrightcentered] 16#90D [/ecandradeva] 16#2076 [/sixsuperior] 16#76 [/v] 16#1E1A [/Etildebelow] 16#455 [/dzecyrillic /afii10102] 16#3327 [/tonsquare] 16#A90 [/aigujarati] 16#30CB [/nikatakana] 16#FF9D [/nkatakanahalfwidth] 16#5D8 [/tethebrew /tet /afii57672] 16#25D8 [/invbullet /bulletinverse] 16#9B7 [/ssabengali] 16#120 [/Gdotaccent /Gdot] 16#F889 [/maitaikhuleftthai] 16#FEC4 [/tahmedialarabic] 16#1EC4 [/Ecircumflextilde] 16#33D1 [/squareln] 16#22A3 [/tackleft] 16#2A3 [/dzaltone] 16#3175 [/pieupsiostikeutkorean] 16#47 [/G] 16#426 [/afii10040 /Tsecyrillic] 16#1CA [/NJ] 16#309C [/semivoicedmarkkana] 16#FF6E [/yosmallkatakanahalfwidth] 16#F6D7 [/dieresisacute] 16#E40 [/saraethai] 16#25A9 [/squarediagonalcrosshatchfill] 16#5A9 [/telishaqetanahebrew] 16#988 [/iibengali] 16#F1 [/ntilde] 16#1E95 [/zlinebelow] 16#24D0 [/acircle] 16#4D0 [/Abrevecyrillic] 16#33A2 [/kmsquaredsquare] 16#3146 [/ssangsioskorean] 16#18 [/controlCAN] 16#2018 [/quoteleft] 16#A32 [/lagurmukhi] 16#19B [/lambdastroke] 16#306D [/nehiragana] 16#FF3F [/underscoremonospace] 16#E11 [/thonangmonthothai] 16#57A [/peharmenian] 16#31E [/downtackbelowcmb] 16#959 [/khhadeva] 16#C2 [/Acircumflex] 16#FE66 [/equalsmall] 16#1E66 [/Scarondotaccent] 16#24A1 [/fparen] 16#4A1 [/kabashkircyrillic] 16#2245 [/approximatelyequal /congruent] 16#3117 [/zbopomofo] 16#624 [/wawhamzaabovearabic /afii57412] 16#3C8 [/psi] 16#FB31 [/betdageshhebrew /betdagesh] 16#16C [/Ubreve] 16#FF10 [/zeromonospace] 16#54B [/Jheharmenian] 16#92A [/padeva] 16#F7FC [/Udieresissmall] 16#1E37 [/ldotbelow] 16#FE37 [/braceleftvertical] 16#2472 [/nineteencircle] 16#472 [/afii10147 /Fitacyrillic] 16#5344 [/twentyhangzhou] 16#AAD [/bhagujarati] 16#216 [/Uinvertedbreve] 16#30E8 [/yokatakana] 16#399 [/Iota] 16#FB02 [/fl] 16#326B [/thieuthcirclekorean] 16#13D [/Lcaron] 16#300F [/whitecornerbracketright] 16#1EE1 [/ohorntilde] 16#251C [/SF080000] 16#2C0 [/glottalstopmod] 16#64 [/d] 16#1E08 [/Ccedillaacute] 16#443 [/ucyrillic /afii10085] 16#3315 [/kiroguramusquare] 16#1E7 [/gcaron] 16#21E7 [/arrowupwhite] 16#30B9 [/sukatakana] 16#FF8B [/hikatakanahalfwidth] 16#F6F4 [/Brevesmall] 16#25C6 [/blackdiamond] 16#323C [/ideographicsuperviseparen] 16#9A5 [/thabengali] 16#10E [/Dcaron] 16#FEB2 [/seenfinalarabic] 16#1EB2 [/Abrevehookabove] 16#33BF [/mwmegasquare] 16#291 [/zcurl] 16#3163 [/ikorean] 16#2035 [/primereversed] 16#35 [/five] 16#414 [/afii10021 /Decyrillic] 16#FB7D [/tchehmedialarabic] 16#1B8 [/Ezhreversed] 16#308A [/rihiragana] 16#FF5C [/barmonospace] 16#F6C5 [/afii10064] 16#E2E [/honokhukthai] 16#597 [/reviamugrashhebrew /reviahebrew] 16#33B [/squarebelowcmb] 16#320D [/hieuhparenkorean] 16#DF [/germandbls] 16#1E83 [/wacute] 16#24BE [/Icircle] 16#4BE [/Chedescenderabkhasiancyrillic] 16#3390 [/Hzsquare] 16#2262 [/notidentical] 16#3134 [/nieunkorean] 16#6 [/controlACK] 16#F76F [/Osmall] 16#641 [/feharabic /afii57441] 16#2641 [/earth] 16#3E5 [/feicoptic] 16#FB4E [/perafehebrew] 16#A20 [/tthagurmukhi] 16#189 [/Dafrican] 16#F8F2 [/braceleftmid] 16#305B [/sehiragana] 16#FF2D [/Mmonospace] 16#568 [/etarmenian] 16#FCD1 [/meemmeeminitialarabic] 16#2568 [/SF460000] 16#30C [/caroncmb] 16#947 [/evowelsigndeva] 16#B0 [/degree] 16#FE54 [/semicolonsmall] 16#1E54 [/Pacute] 16#248F [/eightperiod] 16#3105 [/bbopomofo] 16#3B6 [/zeta] 16#FB1F [/yodyodpatahhebrew /doubleyodpatahhebrew /doubleyodpatah /afii57705] 16#9F1 [/ralowerdiagonalbengali] 16#15A [/Sacute] 16#539 [/Toarmenian] 16#FCA2 [/tehhahinitialarabic] 16#2DD [/hungarumlaut] 16#918 [/ghadeva] 16#2081 [/oneinferior] 16#F7EA [/Ecircumflexsmall] 16#1E25 [/hdotbelow] 16#2460 [/onecircle] 16#460 [/Omegacyrillic] 16#A9B [/chagujarati] 16#204 [/Edblgrave] 16#30D6 [/bukatakana] 16#5E3 [/finalpehebrew /finalpe /afii57683] 16#25E3 [/blacklowerlefttriangle] 16#387 [/anoteleia] 16#9C2 [/uuvowelsignbengali] 16#12B [/imacron] 16#F894 [/maichattawalowrightthai] 16#212B [/angstrom] 16#1ECF [/ohookabove] 16#FECF [/ghaininitialarabic] 16#FC73 [/tehnoonfinalarabic] 16#33DC [/svsquare] 16#3180 [/ssangieungkorean] 16#52 [/R] 16#431 [/becyrillic /afii10066] 16#3303 [/aarusquare] 16#A6C [/sixgurmukhi] 16#1D5 [/Udieresismacron] 16#30A7 [/esmallkatakana] 16#FF79 [/kekatakanahalfwidth] 16#F6E2 [/commasuperior] 16#E4B [/maichattawathai] 16#5B4 [/hiriq2d /hiriq21 /hiriq14 /hiriq /hiriqwidehebrew /hiriqquarterhebrew /hiriqnarrowhebrew /hiriqhebrew /afii57793] 16#25B4 [/blackuppointingsmalltriangle] 16#322A [/ideographicmoonparen] 16#993 [/obengali] 16#FC [/udieresis] 16#FEA0 [/jeemmedialarabic] 16#1EA0 [/Adotbelow] 16#4DB [/schwadieresiscyrillic] 16#24DB [/lcircle] 16#33AD [/radsquare] 16#27F [/rfishhookreversed] 16#3151 [/yakorean] 16#23 [/numbersign] 16#402 [/afii10051 /Djecyrillic] 16#FB6B [/vehfinalarabic] 16#1A6 [/yr] 16#3078 [/hehiragana] 16#FF4A [/jmonospace] 16#E1C [/phophungthai] 16#585 [/oharmenian] 16#329 [/verticallinebelowcmb] 16#2329 [/angleleft] 16#964 [/danda] 16#CD [/Iacute] 16#1E71 [/tcircumflexbelow] 16#24AC [/qparen] 16#4AC [/Tedescendercyrillic] 16#337E [/meizierasquare] 16#AE7 [/onegujarati] 16#250 [/aturned] 16#2250 [/approaches] 16#3122 [/anbopomofo] 16#262F [/yinyang] 16#62F [/dalarabic /afii57423] 16#3D3 [/Upsilonacutehooksymbolgreek] 16#FB3C [/lameddageshhebrew /lameddagesh] 16#32A5 [/ideographiccentrecircle] 16#177 [/ycircumflex] 16#2177 [/eightroman] 16#3049 [/osmallhiragana] 16#FF1B [/semicolonmonospace] 16#556 [/Feharmenian] 16#2556 [/SF210000] 16#935 [/vadeva] 16#FE42 [/cornerbracketrightvertical] 16#1E42 [/Mdotbelow] 16#247D [/tenparen] 16#47D [/omegatitlocyrillic] 16#AB8 [/sagujarati] 16#30F3 [/nkatakana] 16#3A4 [/Tau] 16#3276 [/cieucacirclekorean] 16#9DF [/yyabengali] 16#148 [/ncaron] 16#FEEC [/hehmedialarabic] 16#1EEC [/Uhornhookabove] 16#2CB [/fourthtonechinese] 16#906 [/aadeva] 16#6F [/o] 16#1E13 [/dcircumflexbelow] 16#44E [/iucyrillic /afii10096] 16#A89 [/ugujarati] 16#1F2 [/Dz] 16#30C4 [/tukatakana] 16#FF96 [/yokatakanahalfwidth] 16#F6FF [/Zcaronsmall] 16#25D1 [/circlewithrighthalfblack] 16#5D1 [/bethebrew /afii57665 /bet] 16#375 [/numeralsignlowergreek] 16#9B0 [/rabengali] 16#119 [/eogonek] 16#1EBD [/etilde] 16#4F8 [/Yerudieresiscyrillic] 16#FC61 [/shaddadammaarabic] 16#33CA [/hasquare] 16#316E [/mieumpieupkorean] 16#40 [/at] 16#41F [/afii10033 /Pecyrillic] 16#A5A [/ghhagurmukhi] 16#1C3 [/clickretroflex] 16#FF67 [/asmallkatakanahalfwidth] 16#F6D0 [/Macron] 16#E39 [/sarauuthai] 16#3218 [/khieukhaparenkorean] 16#981 [/candrabindubengali] 16#EA [/ecircumflex] 16#1E8E [/Ydotaccent] 16#FE8E [/aleffinalarabic] 16#24C9 [/Tcircle] 16#339B [/mumsquare] 16#26D [/lhookretroflex] 16#313F [/rieulphieuphkorean] 16#11 [/controlDC1] 16#F77A [/Zsmall] 16#64C [/dammatanarabic /dammatanaltonearabic /afii57452] 16#3F0 [/kappasymbolgreek] 16#FB59 [/pehmedialarabic] 16#A2B [/phagurmukhi] 16#194 [/Gammaafrican] 16#F8FD [/bracerightmid] 16#3066 [/tehiragana] 16#2194 [/arrowboth] 16#FF38 [/Xmonospace] 16#E0A [/chochangthai] 16#573 [/cheharmenian] 16#317 [/acutebelowcmb] 16#952 [/anudattadeva] 16#BB [/guillemotright] 16#6F6 [/sixpersian] 16#1E5F [/rlinebelow] 16#FE5F [/numbersignsmall] 16#249A [/nineteenperiod] 16#49A [/Kadescendercyrillic] 16#3110 [/jbopomofo] 16#261D [/pointingindexupwhite] 16#3C1 [/rho] 16#FB2A [/shinshindothebrew /shinshindot /afii57694] 16#165 [/tcaron] 16#2165 [/Sixroman] 16#FF09 [/parenrightmonospace] 16#544 [/Menarmenian] 16#2E8 [/tonebarlowmod] 16#923 [/nnadeva] 16#F7F5 [/Otildesmall] 16#FE30 [/twodotleadervertical] 16#1E30 [/Kacute] 16#46B [/yusbigcyrillic] 16#246B [/twelvecircle] 16#AA6 [/dagujarati] 16#20F [/oinvertedbreve] 16#220F [/product] 16#30E1 [/mekatakana] 16#392 [/Beta] 16#3264 [/mieumcirclekorean] 16#9CD [/viramabengali] 16#136 [/Kcommaaccent /Kcedilla] 16#3008 [/anglebracketleft] 16#FEDA [/kaffinalarabic] 16#1EDA [/Ohornacute] 16#2B9 [/primemod] 16#318B [/yuyekorean] 16#5D [/bracketright] 16#698 [/jeharabic /afii57508] 16#1E01 [/aringbelow] 16#43C [/emcyrillic /afii10078] 16#FBA5 [/hehhamzaabovefinalarabic] 16#21E0 [/arrowdashleft] 16#1E0 [/Adotmacron] 16#30B2 [/gekatakana] 16#FF84 [/tokatakanahalfwidth] 16#F6ED [/isuperior] 16#E56 [/sixthai] 16#25BF [/whitedownpointingsmalltriangle] 16#5BF [/rafehebrew /rafe /afii57841] 16#3235 [/ideographicspecialparen] 16#99E [/nyabengali] 16#107 [/cacute] 16#1EAB [/acircumflextilde] 16#24E6 [/wcircle] 16#4E6 [/Odieresiscyrillic] 16#33B8 [/kvsquare] 16#28A [/upsilonlatin] 16#228A [/subsetnotequal] 16#315C [/ukorean] 16#202E [/afii61575] 16#2E [/period] 16#2669 [/quarternote] 16#669 [/ninearabic /ninehackarabic /afii57401] 16#A48 [/aimatragurmukhi] 16#1B1 [/Upsilonafrican] 16#3083 [/yasmallhiragana] 16#FF55 [/umonospace] 16#F6BE [/dotlessj] 16#E27 [/wowaenthai] 16#2590 [/rtblock] 16#334 [/tildeoverlaycmb] 16#3206 [/siosparenkorean] 16#96F [/ninedeva] 16#D8 [/Oslash] 16#2713 [/checkmark] 16#1E7C [/Vtilde] 16#4B7 [/chedescendercyrillic] 16#24B7 [/Bcircle] 16#3389 [/kcalsquare] 16#25B [/eopen] 16#F768 [/Hsmall] 16#263A [/whitesmilingface /smileface] 16#63A [/ghainarabic /afii57434] 16#3DE [/Koppagreek] 16#FB47 [/qofdageshhebrew /qofdagesh] 16#A19 [/ngagurmukhi] 16#182 [/Btopbar] 16#F8EB [/parenlefttp] 16#3054 [/gohiragana] 16#FF26 [/Fmonospace] 16#561 [/aybarmenian] 16#FCCA [/lamhahinitialarabic] 16#2561 [/SF190000] 16#2305 [/projective] 16#305 [/overlinecmb] 16#940 [/iivowelsigndeva] 16#20A9 [/won] 16#A9 [/copyright] 16#FE4D [/lowlinedashed] 16#1E4D [/otildeacute] 16#2488 [/oneperiod] 16#AC3 [/rvocalicvowelsigngujarati] 16#222C [/dblintegral] 16#30FE [/voicediterationkatakana] 16#F739 [/nineoldstyle] 16#3AF [/iotatonos] 16#9EA [/fourbengali] 16#2153 [/onethird] 16#153 [/oe] 16#3025 [/fivehangzhou] 16#278E [/fivecircleinversesansserif] 16#1EF7 [/yhookabove] 16#FEF7 [/lamalefhamzaaboveisolatedarabic] 16#532 [/Benarmenian] 16#2D6 [/plusmod] 16#911 [/ocandradeva] 16#207A [/plussuperior] 16#F7E3 [/Atildesmall] 16#7A [/z] 16#1E1E [/Fdotaccent] 16#459 [/ljecyrillic /afii10106] 16#332B [/paasentosquare] 16#A94 [/augujarati] 16#1FD [/aeacute] 16#30CF [/hakatakana] 16#5DC [/lamedhebrew /lamed /afii57676] 16#124 [/Hcircumflex] 16#F88D [/maithoupperleftthai] 16#FEC8 [/zahmedialarabic] 16#1EC8 [/Ihookabove] 16#33D5 [/squaremil] 16#2A7 [/tesh] 16#3179 [/kapyeounssangpieupkorean] 16#4B [/K] 16#F7B4 [/Acutesmall] 16#686 [/tcheharabic /afii57507] 16#42A [/afii10044 /Hardsigncyrillic] 16#FB93 [/gaffinalarabic] 16#1CE [/acaron] 16#FF72 [/ikatakanahalfwidth] 16#F6DB [/trademarkserif] 16#E44 [/saraaimaimalaithai] 16#5AD [/dehihebrew] 16#3223 [/fourideographicparen] 16#98C [/lvocalicbengali] 16#F5 [/otilde] 16#1E99 [/yring] 16#24D4 [/ecircle] 16#4D4 [/Aiecyrillic] 16#33A6 [/kmcubedsquare] 16#278 [/philatin] 16#314A [/chieuchkorean] 16#1C [/controlFS] 16#201C [/quotedblleft] 16#A36 [/shagurmukhi] 16#19F [/Ocenteredtilde] 16#3071 [/pahiragana] 16#FF43 [/cmonospace] 16#E15 [/totaothai] 16#57E [/vewarmenian] 16#322 [/hookretroflexbelowcmb] 16#95D [/rhadeva] 16#C6 [/AE] 16#FE6A [/percentsmall] 16#1E6A [/Tdotaccent] 16#24A5 [/jparen] 16#FC0E [/tehmeemisolatedarabic] 16#4A5 [/enghecyrillic] 16#AE0 [/rrvocalicgujarati] 16#311B [/obopomofo] 16#628 [/afii57416 /beharabic] 16#3CC [/omicrontonos] 16#FB35 [/vavdageshhebrew /vavdagesh65 /vavdagesh /afii57723] 16#329E [/ideographicprintcircle] 16#A07 [/igurmukhi] 16#2170 [/oneroman] 16#170 [/Uhungarumlaut /Udblacute] 16#3042 [/ahiragana] 16#FF14 [/fourmonospace] 16#54F [/Tiwnarmenian] 16#92E [/madeva] 16#6D2 [/yehbarreearabic /afii57519] 16#1E3B [/llinebelow] 16#FE3B [/blacklenticularbracketleftvertical] 16#2476 [/threeparen] 16#476 [/Izhitsadblgravecyrillic] 16#221A [/radical] 16#30EC [/rekatakana] 16#39D [/Nu] 16#326F [/nieunacirclekorean] 16#141 [/Lslash] 16#3013 [/getamark] 16#1EE5 [/udotbelow] 16#2C4 [/arrowheadupmod] 16#68 [/h] 16#1E0C [/Ddotbelow] 16#447 [/checyrillic /afii10089] 16#A82 [/anusvaragujarati] 16#1EB [/oogonek] 16#30BD [/sokatakana] 16#FF8F [/makatakanahalfwidth] 16#F6F8 [/Hungarumlautsmall] 16#25CA [/lozenge] 16#3240 [/ideographicfestivalparen] 16#112 [/Emacron] 16#FEB6 [/sheenfinalarabic] 16#1EB6 [/Abrevedotbelow] 16#4F1 [/udieresiscyrillic] 16#33C3 [/bqsquare] 16#2295 [/pluscircle /circleplus] 16#295 [/glottalstopreversed] 16#3167 [/nieunsioskorean] 16#2039 [/guilsinglleft] 16#F7A2 [/centoldstyle] 16#39 [/nine] 16#418 [/afii10026 /Iicyrillic] 16#21BC [/harpoonleftbarbup] 16#1BC [/Tonefive] 16#308E [/wasmallhiragana] 16#F6C9 [/Acute] 16#E32 [/saraaathai] 16#59B [/tevirlefthebrew /tevirhebrew] 16#33F [/dbloverlinecmb] 16#3211 [/rieulaparenkorean] 16#E3 [/atilde] 16#1E87 [/wdotaccent] 16#4C2 [/zhebrevecyrillic] 16#24C2 [/Mcircle] 16#3394 [/thzsquare] 16#2266 [/lessoverequal] 16#266 [/hhook] 16#3138 [/ssangtikeutkorean] 16#A [/controlLF] 16#F773 [/Ssmall] 16#645 [/meemarabic /afii57445] 16#3E9 [/horicoptic] 16#A24 [/tagurmukhi] 16#18D [/deltaturned] 16#F8F6 [/parenrighttp] 16#305F [/tahiragana] 16#FF31 [/Qmonospace] 16#E03 [/khokhuatthai] 16#56C [/liwnarmenian] 16#FCD5 [/noonmeeminitialarabic] 16#256C [/SF440000] 16#2310 [/revlogicalnot /logicalnotreversed] 16#310 [/candrabinducmb] 16#94B [/ovowelsigndeva] 16#B4 [/acute] 16#1E58 [/Rdotaccent] 16#2493 [/twelveperiod] 16#493 [/ghestrokecyrillic] 16#2237 [/proportion] 16#3109 [/dbopomofo] 16#3BA [/kappa] 16#328C [/ideographwatercircle] 16#9F5 [/twonumeratorbengali] 16#215E [/seveneighths] 16#15E [/Scedilla] 16#FF02 [/quotedblmonospace] 16#53D [/Xeharmenian] 16#91C [/jadeva] 16#2085 [/fiveinferior] 16#F7EE [/Icircumflexsmall] 16#1E29 [/hcedilla] 16#2464 [/fivecircle] 16#464 [/Eiotifiedcyrillic] 16#3336 [/hekutaarusquare] 16#A9F [/ttagujarati] 16#208 [/Idblgrave] 16#2208 [/element] 16#30DA [/pekatakana] 16#5E7 [/qofhebrew /qof /afii57687] 16#12F [/iogonek] 16#F898 [/thanthakhatlowleftthai] 16#3001 [/ideographiccomma] 16#1ED3 [/ocircumflexgrave] 16#FED3 [/fehinitialarabic] 16#2B2 [/jsuperior] 16#3184 [/kapyeounphieuphkorean] 16#56 [/V] 16#F7BF [/questiondownsmall] 16#691 [/rreharabic /afii57513] 16#FDFA [/sallallahoualayhewasallamarabic] 16#435 [/iecyrillic /afii10070] 16#A70 [/tippigurmukhi] 16#1D9 [/Udieresiscaron] 16#30AB [/kakatakana] 16#FF7D [/sukatakanahalfwidth] 16#F6E6 [/hyphensuperior] 16#E4F [/fongmanthai] 16#5B8 [/qamatswidehebrew /qamatsquarterhebrew /qamatsqatanwidehebrew /qamatsqatanquarterhebrew /qamatsqatannarrowhebrew /qamatsqatanhebrew /qamatsnarrowhebrew /qamatshebrew /qamatsde /qamats33 /qamats29 /qamats27 /qamats1c /qamats1a /qamats10 /qamats /afii57797] 16#322E [/ideographicmetalparen] 16#997 [/gabengali] 16#100 [/Amacron] 16#FEA4 [/hahmedialarabic] 16#1EA4 [/Acircumflexacute] 16#4DF [/zedieresiscyrillic] 16#24DF [/pcircle] 16#33B1 [/nssquare] 16#FC48 [/meemmeemisolatedarabic] 16#2283 [/superset /propersuperset] 16#283 [/esh] 16#3155 [/yeokorean] 16#27 [/quotesingle] 16#662 [/twoarabic /twohackarabic /afii57394] 16#2662 [/diamondsuitwhite] 16#406 [/afii10055 /Icyrillic] 16#A41 [/umatragurmukhi] 16#1AA [/eshreversedloop] 16#307C [/bohiragana] 16#FF4E [/nmonospace] 16#E20 [/phosamphaothai] 16#589 [/periodarmenian] 16#32D [/circumflexbelowcmb] 16#968 [/twodeva] 16#D1 [/Ntilde] 16#1E75 [/utildebelow] 16#24B0 [/uparen] 16#4B0 [/Ustraightstrokecyrillic] 16#3382 [/muasquare] 16#AEB [/fivegujarati] 16#254 [/oopen] 16#3126 [/erbopomofo] 16#F761 [/Asmall] 16#633 [/seenarabic /afii57427] 16#FB40 [/nundageshhebrew /nundagesh] 16#32A9 [/ideographicmedicinecircle] 16#217B [/twelveroman] 16#17B [/Zdotaccent /Zdot] 16#304D [/kihiragana] 16#FF1F [/questionmonospace] 16#55A [/apostrophearmenian] 16#255A [/SF380000] 16#939 [/hadeva] 16#20A2 [/cruzeiro] 16#A2 [/cent] 16#1E46 [/Ndotbelow] 16#481 [/koppacyrillic] 16#2481 [/fourteenparen] 16#ABC [/nuktagujarati] 16#2225 [/parallel] 16#30F7 [/vakatakana] 16#F732 [/twooldstyle] 16#3A8 [/Psi] 16#327A [/phieuphacirclekorean] 16#9E3 [/llvocalicvowelsignbengali] 16#14C [/Omacron] 16#301E [/quotedblprime] 16#FEF0 [/alefmaksurafinalarabic] 16#1EF0 [/Uhorndotbelow] 16#FC94 [/yehnoonfinalarabic] 16#22CF [/curlyand] 16#2CF [/acutelowmod] 16#90A [/uudeva] 16#73 [/s] 16#1E17 [/emacronacute] 16#452 [/djecyrillic /afii10099] 16#A8D [/ecandragujarati] 16#30C8 [/tokatakana] 16#FF9A [/rekatakanahalfwidth] 16#5D5 [/vavhebrew /vav /afii57669] 16#FD3E [/parenleftaltonearabic] 16#11D [/gcircumflex] 16#F886 [/saraiileftthai] 16#1EC1 [/ecircumflexgrave] 16#33CE [/squarekmcapital] 16#2A0 [/qhook] 16#3172 [/pieupkiyeokkorean] 16#2044 [/fraction] 16#44 [/D] 16#2423 [/blank] 16#423 [/afii10037 /Ucyrillic] 16#A5E [/fagurmukhi] 16#1C7 [/LJ] 16#FF6B [/osmallkatakanahalfwidth] 16#F6D4 [/cyrbreve] 16#25A6 [/squareorthogonalcrosshatchfill] 16#5A6 [/merkhakefulalefthebrew /merkhakefulahebrew] 16#321C [/cieucuparenkorean] 16#985 [/abengali] 16#EE [/icircumflex] 16#1E92 [/Zdotbelow] 16#FE92 [/behmedialarabic] 16#24CD [/Xcircle] 16#339F [/mmsquaredsquare] 16#271 [/mhook] 16#2271 [/notgreaternorequal] 16#3143 [/ssangpieupkorean] 16#2015 [/horizontalbar /afii00208] 16#15 [/controlNAK] 16#650 [/kasraarabic /afii57456] 16#A2F [/yagurmukhi] 16#2198 [/arrowdownright] 16#198 [/Khook] 16#306A [/nahiragana] 16#FF3C [/backslashmonospace] 16#E0E [/dochadathai] 16#577 [/shaarmenian] 16#31B [/horncmb] 16#BF [/questiondown] 16#1E63 [/sdotbelow] 16#FE63 [/hyphensmall] 16#249E [/cparen] 16#49E [/Kastrokecyrillic] 16#3114 [/chbopomofo] 16#FFE6 [/wonmonospace] 16#621 [/hamzalowarabic /hamzaarabic /afii57409] 16#3C5 [/upsilon] 16#FB2E [/alefpatahhebrew] 16#169 [/utilde] 16#2169 [/Tenroman] 16#FF0D [/hyphenmonospace] 16#548 [/Voarmenian] 16#927 [/dhadeva] 16#F7F9 [/Ugravesmall] 16#FE34 [/wavyunderscorevertical] 16#1E34 [/Klinebelow] 16#246F [/sixteencircle] 16#46F [/ksicyrillic] 16#AAA [/pagujarati] 16#213 [/rinvertedbreve] 16#2213 [/minusplus] 16#30E5 [/yusmallkatakana] 16#5F2 [/yodyodhebrew /afii57718] 16#396 [/Zeta] 16#3268 [/cieuccirclekorean] 16#13A [/lacute] 16#300C [/cornerbracketleft] 16#FEDE [/lamfinalarabic] 16#1EDE [/Ohornhookabove] 16#2BD [/commareversedmod /afii64937] 16#61 [/a] 16#1E05 [/bdotbelow] 16#440 [/ercyrillic /afii10082] 16#FBA9 [/hehmedialaltonearabic] 16#21E4 [/arrowtableft] 16#1E4 [/Gstroke] 16#30B6 [/zakatakana] 16#FF88 [/nekatakanahalfwidth] 16#F6F1 [/rsuperior] 16#E5A [/angkhankhuthai] 16#25C3 [/whiteleftpointingsmalltriangle] 16#5C3 [/sofpasuqhebrew /afii57658] 16#3239 [/ideographicrepresentparen] 16#9A2 [/ddhabengali] 16#10B [/cdotaccent /cdot] 16#1EAF [/abreveacute] 16#4EA [/Obarreddieresiscyrillic] 16#33BC [/muwsquare] 16#28E [/yturned] 16#3160 [/yukorean] 16#2032 [/minute] 16#32 [/two] 16#266D [/musicflatsign] 16#66D [/asteriskaltonearabic /asteriskarabic /afii63167] 16#411 [/afii10018 /Becyrillic] 16#A4C [/aumatragurmukhi] 16#1B5 [/Zstroke] 16#21B5 [/carriagereturn] 16#3087 [/yosmallhiragana] 16#FF59 [/ymonospace] 16#E2B [/hohipthai] 16#594 [/zaqefqatanhebrew] 16#338 [/soliduslongoverlaycmb] 16#320A [/khieukhparenkorean] 16#DC [/Udieresis] 16#1E80 [/Wgrave] 16#4BB [/shhacyrillic] 16#24BB [/Fcircle] 16#338D [/mugsquare] 16#25F [/jdotlessstroke] 16#3131 [/kiyeokkorean] 16#3 [/controlETX] 16#F76C [/Lsmall] 16#3E2 [/Sheicoptic] 16#FB4B [/vavholamhebrew /vavholam /afii57700] 16#A1D [/jhagurmukhi] 16#186 [/Oopen] 16#F8EF [/bracketleftex] 16#3058 [/zihiragana] 16#FF2A [/Jmonospace] 16#565 [/echarmenian] 16#2565 [/SF480000] 16#309 [/hookcmb /hookabovecomb] 16#944 [/rrvocalicvowelsigndeva] 16#AD [/softhyphen /sfthyphen] 16#1E51 [/omacrongrave] 16#248C [/fiveperiod] 16#AC7 [/evowelsigngujarati] 16#260F [/whitetelephone] 16#3B3 [/gamma] 16#9EE [/eightbengali] 16#157 [/rcommaaccent /rcedilla] 16#3029 [/ninehangzhou] 16#2792 [/ninecircleinversesansserif] 16#FEFB [/lamalefisolatedarabic] 16#536 [/Zaarmenian] 16#FC9F [/behmeeminitialarabic] 16#22DA [/lessequalorgreater] 16#2DA [/ring] 16#915 [/kadeva] 16#207E [/parenrightsuperior] 16#F7E7 [/Ccedillasmall] 16#7E [/asciitilde] 16#1E22 [/Hdotaccent] 16#A98 [/ghagujarati] 16#201 [/adblgrave] 16#30D3 [/bikatakana] 16#5E0 [/nunhebrew /nun /afii57680] 16#384 [/tonos] 16#9BF [/ivowelsignbengali] 16#128 [/Itilde] 16#F891 [/maitrilowrightthai] 16#FECC [/ainmedialarabic] 16#1ECC [/Odotbelow] 16#317D [/siospieupkorean] 16#4F [/O] 16#F7B8 [/Cedillasmall] 16#42E [/afii10048 /IUcyrillic] 16#3300 [/apaatosquare] 16#A69 [/threegurmukhi] 16#1D2 [/ocaron] 16#21D2 [/dblarrowright /arrowdblright] 16#30A4 [/ikatakana] 16#FF76 [/kakatakanahalfwidth] 16#F6DF [/centinferior] 16#E48 [/maiekthai] 16#5B1 [/hatafsegolwidehebrew /hatafsegolquarterhebrew /hatafsegolnarrowhebrew /hatafsegolhebrew /hatafsegol30 /hatafsegol24 /hatafsegol17 /hatafsegol /afii57801] 16#3227 [/eightideographicparen] 16#990 [/aibengali] 16#F9 [/ugrave] 16#24D8 [/icircle] 16#4D8 [/Schwacyrillic] 16#33AA [/kpasquare] 16#27C [/rlongleg] 16#314E [/hieuhkorean] 16#20 [/spacehackarabic /space] 16#2020 [/dagger] 16#FB68 [/ttehinitialarabic] 16#1A3 [/oi] 16#3075 [/huhiragana] 16#FF47 [/gmonospace] 16#E19 [/nonuthai] 16#582 [/yiwnarmenian] 16#2326 [/deleteright] 16#961 [/llvocalicdeva] 16#CA [/Ecircumflex] 16#1E6E [/Tlinebelow] 16#24A9 [/nparen] 16#4A9 [/haabkhasiancyrillic] 16#337B [/heiseierasquare] 16#311F [/eibopomofo] 16#62C [/jeemarabic /afii57420] 16#3D0 [/betasymbolgreek] 16#FB39 [/yoddageshhebrew /yoddagesh] 16#2174 [/fiveroman] 16#174 [/Wcircumflex] 16#3046 [/uhiragana] 16#FF18 [/eightmonospace] 16#553 [/Piwrarmenian] 16#2553 [/SF520000] 16#932 [/ladeva] 16#1E3F [/macute] 16#FE3F [/anglebracketleftvertical] 16#247A [/sevenparen] 16#47A [/Omegaroundcyrillic] 16#AB5 [/vagujarati] 16#221E [/infinity] 16#30F0 [/wikatakana] 16#3A1 [/Rho] 16#3273 [/pieupacirclekorean] 16#9DC [/rrabengali] 16#145 [/Ncommaaccent /Ncedilla] 16#3017 [/whitelenticularbracketright] 16#1EE9 [/uhornacute] 16#2524 [/SF090000] 16#FC8D [/noonnoonfinalarabic] 16#2C8 [/verticallinemod] 16#903 [/visargadeva] 16#6C [/l] 16#1E10 [/Dcedilla] 16#44B [/yericyrillic /afii10093] 16#A86 [/aagujarati] 16#1EF [/ezhcaron] 16#30C1 [/tikatakana] 16#FF93 [/mokatakanahalfwidth] 16#F6FC [/Ringsmall] 16#25CE [/bullseye] 16#9AD [/bhabengali] 16#2116 [/numero /afii61352] 16#116 [/Edotaccent /Edot] 16#FEBA [/sadfinalarabic] 16#1EBA [/Ehookabove] 16#4F5 [/chedieresiscyrillic] 16#FC5E [/shaddadammatanarabic] 16#33C7 [/cosquare] 16#2299 [/circleot] 16#316B [/rieulpieupsioskorean] 16#3D [/equal] 16#41C [/afii10030 /Emcyrillic] 16#21C0 [/harpoonrightbarbup] 16#1C0 [/clickdental] 16#3092 [/wohiragana] 16#FF64 [/ideographiccommaleft] 16#F6CD [/DieresisGrave] 16#E36 [/sarauethai] 16#59F [/qarneyparahebrew] 16#343 [/koroniscmb] 16#3215 [/ieungaparenkorean] 16#E7 [/ccedilla] 16#FE8B [/yehhamzaaboveinitialarabic] 16#1E8B [/xdotaccent] 16#24C6 [/Qcircle] 16#3398 [/klsquare] 16#226A [/muchless] 16#313C [/rieulpieupkorean] 16#E [/controlSO] 16#200E [/afii299] 16#F777 [/Wsmall] 16#649 [/alefmaksuraarabic /afii57449] 16#3ED [/shimacoptic] 16#A28 [/nagurmukhi] 16#191 [/Fhook] 16#F8FA [/bracketrightex] 16#3063 [/tusmallhiragana] 16#2191 [/arrowup] 16#FF35 [/Umonospace] 16#E07 [/ngonguthai] 16#570 [/hoarmenian] 16#314 [/commareversedabovecmb] 16#B8 [/cedilla] 16#6F3 [/threepersian] 16#FE5C [/bracerightsmall] 16#1E5C [/Rdotbelowmacron] 16#2497 [/sixteenperiod] 16#497 [/zhedescendercyrillic] 16#310D [/gbopomofo] 16#3BE [/xi] 16#3290 [/ideographsuncircle] 16#9F9 [/sixteencurrencydenominatorbengali] 16#162 [/Tcommaaccent /Tcedilla] 16#2162 [/Threeroman] 16#FF06 [/ampersandmonospace] 16#541 [/Jaarmenian] 16#2E5 [/tonebarextrahighmod] 16#920 [/tthadeva] 16#2089 [/nineinferior] 16#F7F2 [/Ogravesmall] 16#1E2D [/itildebelow] 16#2468 [/ninecircle] 16#468 [/Yuslittleiotifiedcyrillic] 16#AA3 [/nnagujarati] 16#220C [/notcontains] 16#20C [/Odblgrave] 16#30DE [/makatakana] 16#38F [/Omegatonos] 16#3261 [/nieuncirclekorean] 16#133 [/ij] 16#3005 [/ideographiciterationmark] 16#FED7 [/qafinitialarabic] 16#1ED7 [/ocircumflextilde] 16#2B6 [/Rsmallinvertedsuperior] 16#3188 [/yoyaekorean] 16#5A [/Z] 16#439 [/iishortcyrillic /afii10075] 16#A74 [/ekonkargurmukhi] 16#1DD [/eturned] 16#30AF [/kukatakana] 16#FF81 [/tikatakanahalfwidth] 16#F6EA [/bsuperior] 16#E53 [/threethai] 16#25BC [/triagdn /blackdownpointingtriangle] 16#5BC [/dageshhebrew /dagesh /afii57807] 16#360 [/tildedoublecmb] 16#3232 [/ideographichaveparen] 16#99B [/chabengali] 16#104 [/Aogonek] 16#FEA8 [/khahmedialarabic] 16#1EA8 [/Acircumflexhookabove] 16#24E3 [/tcircle] 16#4E3 [/imacroncyrillic] 16#33B5 [/nvsquare] 16#287 [/tturned] 16#2287 [/supersetorequal /reflexsuperset] 16#3159 [/waekorean] 16#2B [/plus] 16#666 [/sixhackarabic /sixarabic /afii57398] 16#2666 [/diamond] 16#40A [/afii10059 /Njecyrillic] 16#1AE [/Tretroflexhook] 16#3080 [/muhiragana] 16#FF52 [/rmonospace] 16#E24 [/ruthai] 16#331 [/macronbelowcmb] 16#3203 [/rieulparenkorean] 16#96C [/sixdeva] 16#D5 [/Otilde] 16#1E79 [/utildeacute] 16#24B4 [/yparen] 16#4B4 [/Tetsecyrillic] 16#3386 [/MBsquare] 16#AEF [/ninegujarati] 16#258 [/ereversed] 16#F765 [/Esmall] 16#637 [/taharabic /afii57431] 16#FB44 [/pedageshhebrew /pedagesh] 16#A16 [/khagurmukhi] 16#17F [/slong /longs] 16#F8E8 [/registersans] 16#3051 [/kehiragana] 16#FF23 [/Cmonospace] 16#55E [/questionarmenian] 16#255E [/SF360000] 16#2302 [/house] 16#302 [/circumflexcmb] 16#93D [/avagrahadeva] 16#A6 [/brokenbar] 16#FE4A [/overlinecenterline] 16#1E4A [/Ncircumflexbelow] 16#485 [/dasiapneumatacyrilliccmb] 16#2485 [/eighteenparen] 16#3357 [/wattosquare] 16#AC0 [/iivowelsigngujarati] 16#2229 [/intersection] 16#30FB [/dotkatakana] 16#F736 [/sixoldstyle] 16#3AC [/alphatonos] 16#9E7 [/onebengali] 16#150 [/Ohungarumlaut /Odblacute] 16#3022 [/twohangzhou] 16#278B [/twocircleinversesansserif] 16#FEF4 [/yehmedialarabic /alefmaksuramedialarabic] 16#1EF4 [/Ydotbelow] 16#2D3 [/ringhalfleftcentered] 16#90E [/eshortdeva] 16#2077 [/sevensuperior] 16#F7E0 [/Agravesmall] 16#77 [/w] 16#1E1B [/etildebelow] 16#456 [/icyrillic /afii10103] 16#A91 [/ocandragujarati] 16#1FA [/Aringacute] 16#30CC [/nukatakana] 16#FF9E [/voicedmarkkanahalfwidth] 16#5D9 [/yodhebrew /yod /afii57673] 16#25D9 [/whitecircleinverse /invcircle] 16#9B8 [/sabengali] 16#2121 [/telephone] 16#F88A [/maiekupperleftthai] 16#121 [/gdotaccent /gdot] 16#1EC5 [/ecircumflextilde] 16#2500 [/SF100000] 16#33D2 [/squarelog] 16#22A4 [/tackdown] 16#2A4 [/dezh] 16#3176 [/pieupcieuckorean] 16#48 [/H] 16#427 [/afii10041 /Checyrillic] 16#1CB [/Nj] 16#309D [/iterationhiragana] 16#FF6F [/tusmallkatakanahalfwidth] 16#F6D8 [/dieresisgrave] 16#E41 [/saraaethai] 16#5AA [/yerahbenyomolefthebrew /yerahbenyomohebrew] 16#25AA [/blacksmallsquare /H18543] 16#3220 [/oneideographicparen] 16#989 [/ubengali] 16#F2 [/ograve] 16#FE96 [/tehfinalarabic] 16#1E96 [/hlinebelow] 16#4D1 [/abrevecyrillic] 16#24D1 [/bcircle] 16#33A3 [/mmcubedsquare] 16#275 [/obarred] 16#3147 [/ieungkorean] 16#19 [/controlEM] 16#2019 [/quoteright] 16#19C [/Mturned] 16#306E [/nohiragana] 16#FF40 [/gravemonospace] 16#E12 [/thophuthaothai] 16#57B [/jheharmenian] 16#31F [/plusbelowcmb] 16#95A [/ghhadeva] 16#C3 [/Atilde] 16#1E67 [/scarondotaccent] 16#24A2 [/gparen] 16#FC0B [/tehjeemisolatedarabic] 16#4A2 [/Endescendercyrillic] 16#3118 [/cbopomofo] 16#625 [/afii57413 /alefhamzabelowarabic] 16#3C9 [/omega] 16#FB32 [/gimeldagesh /gimeldageshhebrew] 16#16D [/ubreve] 16#FF11 [/onemonospace] 16#54C [/Raarmenian] 16#92B [/phadeva] 16#F7FD [/Yacutesmall] 16#FE38 [/bracerightvertical] 16#1E38 [/Ldotbelowmacron] 16#2473 [/twentycircle] 16#473 [/fitacyrillic /afii10195] 16#AAE [/magujarati] 16#217 [/uinvertedbreve] 16#2217 [/asteriskmath] 16#30E9 [/rakatakana] 16#F724 [/dollaroldstyle] 16#39A [/Kappa] 16#FB03 [/ffi] 16#326C [/phieuphcirclekorean] 16#13E [/lcaron] 16#3010 [/blacklenticularbracketleft] 16#FEE2 [/meemfinalarabic] 16#1EE2 [/Ohorndotbelow] 16#2C1 [/glottalstopreversedmod] 16#65 [/e] 16#1E09 [/ccedillaacute] 16#444 [/efcyrillic /afii10086] 16#3316 [/kiromeetorusquare] 16#21E8 [/arrowrightwhite] 16#1E8 [/Kcaron] 16#30BA [/zukatakana] 16#FF8C [/hukatakanahalfwidth] 16#F6F5 [/Caronsmall] 16#25C7 [/whitediamond] 16#323D [/ideographicenterpriseparen] 16#9A6 [/dabengali] 16#10F [/dcaron] 16#FEB3 [/seeninitialarabic] 16#1EB3 [/abrevehookabove] 16#4EE [/Umacroncyrillic] 16#33C0 [/kohmsquare] 16#292 [/ezh] 16#3164 [/hangulfiller] 16#36 [/six] 16#415 [/afii10022 /Iecyrillic] 16#1B9 [/ezhreversed] 16#308B [/ruhiragana] 16#FF5D [/bracerightmonospace] 16#F6C6 [/afii10192] 16#E2F [/paiyannoithai] 16#598 [/zarqahebrew] 16#33C [/seagullbelowcmb] 16#320E [/kiyeokaparenkorean] 16#E0 [/agrave] 16#FE84 [/alefhamzaabovefinalarabic] 16#1E84 [/Wdieresis] 16#4BF [/chedescenderabkhasiancyrillic] 16#24BF [/Jcircle] 16#3391 [/khzsquare] 16#263 [/gammalatinsmall] 16#3135 [/nieuncieuckorean] 16#7 [/controlBEL] 16#F770 [/Psmall] 16#642 [/qafarabic /afii57442] 16#2642 [/mars /male] 16#3E6 [/Kheicoptic] 16#FB4F [/aleflamedhebrew] 16#A21 [/ddagurmukhi] 16#18A [/Dhook] 16#F8F3 [/braceleftbt] 16#305C [/zehiragana] 16#FF2E [/Nmonospace] 16#569 [/toarmenian] 16#FCD2 [/noonjeeminitialarabic] 16#2569 [/SF400000] 16#30D [/verticallineabovecmb] 16#948 [/aivowelsigndeva] 16#B1 [/plusminus] 16#1E55 [/pacute] 16#FE55 [/colonsmall] 16#2490 [/nineperiod] 16#490 [/afii10050 /Gheupturncyrillic] 16#ACB [/ovowelsigngujarati] 16#2234 [/therefore] 16#3106 [/pbopomofo] 16#3B7 [/eta] 16#FB20 [/ayinaltonehebrew] 16#9F2 [/rupeemarkbengali] 16#15B [/sacute] 16#215B [/oneeighth] 16#FEFF [/zerowidthjoiner] 16#53A [/Zhearmenian] 16#2DE [/rhotichookmod] 16#919 [/ngadeva] 16#2082 [/twoinferior] 16#F7EB [/Edieresissmall] 16#1E26 [/Hdieresis] 16#2461 [/twocircle] 16#461 [/omegacyrillic] 16#3333 [/huiitosquare] 16#A9C [/jagujarati] 16#205 [/edblgrave] 16#2205 [/emptyset] 16#30D7 [/pukatakana] 16#5E4 [/pe /pehebrew /afii57684] 16#25E4 [/blackupperlefttriangle] 16#388 [/Epsilontonos] 16#9C3 [/rvocalicvowelsignbengali] 16#12C [/Ibreve] 16#F895 [/maichattawalowleftthai] 16#FED0 [/ghainmedialarabic] 16#1ED0 [/Ocircumflexacute] 16#33DD [/wbsquare] 16#3181 [/yesieungkorean] 16#53 [/S] 16#432 [/vecyrillic /afii10067] 16#A6D [/sevengurmukhi] 16#1D6 [/udieresismacron] 16#30A8 [/ekatakana] 16#FF7A [/kokatakanahalfwidth] 16#F6E3 [/dollarinferior] 16#E4C [/thanthakhatthai] 16#5B5 [/tsere /tserewidehebrew /tserequarterhebrew /tserenarrowhebrew /tserehebrew /tsere2b /tsere1e /tsere12 /afii57794] 16#25B5 [/whiteuppointingsmalltriangle] 16#322B [/ideographicfireparen] 16#994 [/aubengali] 16#FD [/yacute] 16#1EA1 [/adotbelow] 16#24DC [/mcircle] 16#4DC [/Zhedieresiscyrillic] 16#33AE [/radoverssquare] 16#2280 [/notprecedes] 16#3152 [/yaekorean] 16#2024 [/onedotenleader] 16#24 [/dollar] 16#403 [/afii10052 /Gjecyrillic] 16#FB6C [/vehinitialarabic] 16#A3E [/aamatragurmukhi] 16#1A7 [/Tonetwo] 16#3079 [/behiragana] 16#FF4B [/kmonospace] 16#E1D [/fofathai] 16#586 [/feharmenian] 16#32A [/bridgebelowcmb] 16#232A [/angleright] 16#965 [/dbldanda] 16#CE [/Icircumflex] 16#1E72 [/Udieresisbelow] 16#4AD [/tedescendercyrillic] 16#24AD [/rparen] 16#337F [/corporationsquare] 16#AE8 [/twogujarati] 16#2251 [/geometricallyequal] 16#251 [/ascript] 16#3123 [/enbopomofo] 16#630 [/thalarabic /afii57424] 16#3D4 [/Upsilondieresishooksymbolgreek] 16#32A6 [/ideographiclowcircle] 16#A0F [/eegurmukhi] 16#2178 [/nineroman] 16#178 [/Ydieresis] 16#304A [/ohiragana] 16#FF1C [/lessmonospace] 16#2557 [/SF250000] 16#936 [/shadeva] 16#FE43 [/whitecornerbracketleftvertical] 16#1E43 [/mdotbelow] 16#247E [/elevenparen] 16#47E [/Otcyrillic] 16#AB9 [/hagujarati] 16#30F4 [/vukatakana] 16#3A5 [/Upsilon] 16#3277 [/chieuchacirclekorean] 16#9E0 [/rrvocalicbengali] 16#149 [/quoterightn /napostrophe] 16#1EED [/uhornhookabove] 16#2CC [/verticallinelowmod] 16#907 [/ideva] 16#2070 [/zerosuperior] 16#70 [/p] 16#1E14 [/Emacrongrave] 16#44F [/iacyrillic /afii10097] 16#A8A [/uugujarati] 16#1F3 [/dz] 16#30C5 [/dukatakana] 16#FF97 [/rakatakanahalfwidth] 16#5D2 [/gimel /gimelhebrew /afii57666] 16#11A [/Ecaron] 16#FEBE [/dadfinalarabic] 16#1EBE [/Ecircumflexacute] 16#4F9 [/yerudieresiscyrillic] 16#FC62 [/shaddakasraarabic] 16#33CB [/HPsquare] 16#29D [/jcrossedtail] 16#316F [/mieumsioskorean] 16#41 [/A] 16#420 [/afii10034 /Ercyrillic] 16#FB89 [/ddalfinalarabic] 16#A5B [/zagurmukhi] 16#21C4 [/arrowrightoverleft] 16#1C4 [/DZcaron] 16#FF68 [/ismallkatakanahalfwidth] 16#F6D1 [/cyrBreve] 16#E3A [/phinthuthai] 16#25A3 [/squarewhitewithsmallblack] 16#5A3 [/munahlefthebrew /munahhebrew] 16#3219 [/thieuthaparenkorean] 16#982 [/anusvarabengali] 16#EB [/edieresis] 16#1E8F [/ydotaccent] 16#24CA [/Ucircle] 16#339C [/squaremm] 16#226E [/notless] 16#26E [/lezh] 16#3140 [/rieulhieuhkorean] 16#2012 [/figuredash] 16#12 [/controlDC2] 16#64D [/kasratanarabic /afii57453] 16#3F1 [/rhosymbolgreek] 16#A2C [/bagurmukhi] 16#195 [/hv] 16#2195 [/arrowupdn] 16#3067 [/dehiragana] 16#F8FE [/bracerightbt] 16#FF39 [/Ymonospace] 16#E0B [/sosothai] 16#574 [/menarmenian] 16#FCDD [/yehmeeminitialarabic] 16#2318 [/propellor] 16#318 [/lefttackbelowcmb] 16#953 [/gravedeva] 16#BC [/onequarter] 16#6F7 [/sevenpersian] 16#1E60 [/Sdotaccent] 16#249B [/twentyperiod] 16#49B [/kadescendercyrillic] 16#3111 [/qbopomofo] 16#FFE3 [/macronmonospace] 16#261E [/pointingindexrightwhite] 16#3C2 [/sigmafinal /sigma1] 16#FB2B [/shinsindothebrew /shinsindot /afii57695] 16#3294 [/ideographnamecircle] 16#166 [/Tbar] 16#2166 [/Sevenroman] 16#FF0A [/asteriskmonospace] 16#545 [/Yiarmenian] 16#2E9 [/tonebarextralowmod] 16#924 [/tadeva] 16#208D [/parenleftinferior] 16#F7F6 [/Odieresissmall] 16#1E31 [/kacute] 16#FE31 [/emdashvertical] 16#246C [/thirteencircle] 16#46C [/Yusbigiotifiedcyrillic] 16#AA7 [/dhagujarati] 16#210 [/Rdblgrave] 16#30E2 [/mokatakana] 16#25EF [/largecircle] 16#393 [/Gamma] 16#3265 [/pieupcirclekorean] 16#137 [/kcommaaccent /kcedilla] 16#3009 [/anglebracketright] 16#1EDB [/ohornacute] 16#FEDB [/kafinitialarabic] 16#2BA [/dblprimemod] 16#318C [/yuikorean] 16#5E [/asciicircum] 16#1E02 [/Bdotaccent] 16#43D [/encyrillic /afii10079] 16#1E1 [/adotmacron] 16#21E1 [/arrowdashup] 16#30B3 [/kokatakana] 16#FF85 [/nakatakanahalfwidth] 16#F6EE [/lsuperior] 16#E57 [/seventhai] 16#5C0 [/paseqhebrew /afii57842] 16#25C0 [/blackleftpointingtriangle] 16#3236 [/ideographicfinancialparen] 16#99F [/ttabengali] 16#108 [/Ccircumflex] 16#FEAC [/thalfinalarabic] 16#1EAC [/Acircumflexdotbelow] 16#24E7 [/xcircle] 16#4E7 [/odieresiscyrillic] 16#33B9 [/mvmegasquare] 16#228B [/supersetnotequal] 16#28B [/vhook] 16#315D [/weokorean] 16#2F [/slash] 16#66A [/percentarabic /afii57381] 16#266A [/musicalnote] 16#40E [/afii10062 /Ushortcyrillic] 16#1B2 [/Vhook] 16#3084 [/yahiragana] 16#FF56 [/vmonospace] 16#F6BF [/LL] 16#E28 [/sosalathai] 16#2591 [/shadelight /ltshade] 16#591 [/etnahtalefthebrew /etnahtahebrew /etnahtafoukhlefthebrew /etnahtafoukhhebrew] 16#335 [/strokeshortoverlaycmb] 16#3207 [/ieungparenkorean] 16#970 [/abbreviationsigndeva] 16#D9 [/Ugrave] 16#1E7D [/vtilde] 16#24B8 [/Ccircle] 16#4B8 [/Cheverticalstrokecyrillic] 16#338A [/pfsquare] 16#25C [/eopenreversed] .dicttomark readonly def gs_setpd.ps 0000644 00000113133 15030647507 0006731 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % The current implementation of setpagedevice has the following limitations: % - It doesn't attempt to "interact with the user" for Policy = 2. languagelevel 1 .setlanguagelevel level2dict begin % ---------------- Redefinitions ---------------- % % Define interpreter callouts for handling gstate-saving operators, % to make sure that they create a page device dictionary for use by % the corresponding gstate-restoring operator. % We'd really like to avoid the cost of doing this, but we don't see how. % The names %gsavepagedevice, %savepagedevice, %gstatepagedevice, % %copygstatepagedevice, and %currentgstatepagedevice are known to the % interpreter. (%gsavepagedevice) cvn { currentpagedevice pop gsave } bind def (%savepagedevice) cvn { currentpagedevice pop save } bind def (%gstatepagedevice) cvn { currentpagedevice pop gstate } bind def (%copygstatepagedevice) cvn { currentpagedevice pop copy } bind def (%currentgstatepagedevice) cvn { currentpagedevice pop currentgstate } bind def % Define interpreter callouts for handling gstate-restoring operators % when the current page device needs to be changed. % The names %grestorepagedevice, %grestoreallpagedevice, % %restorepagedevice, %restore1pagedevice, and %setgstatepagedevice % are known to the interpreter. % ---------------- Keys and Attributes ---------------- % % We have to deal specially with entries that the driver may change % on its own. We also have to deal specially with parameters which the device may % change on its own but which we *also* want to transmit to the device. Previously % any parameter which was 'dynamic' would not be sent to the device, making it % impossible to set a parameter, and later have the device change it. Currently % only OutputICCProfile fits this category. % This whole area is broken its completely the wrong way round from the way the spec says it should work. % This dictionary contains the keys we never want to set. /.readonlypdkeys mark /.MediaSize dup % because it changes when PageSize is set /PageCount dup /Colors dup /BitsPerPixel dup /ColorValues dup .dicttomark readonly def % Bonkers, but needed by our ridiculous setpagedevice implementation. There are % some keys (at the moment, RedValues, GreenValues and BlueValues are known) which % only exist in the page device dictionary under some conditions (ProcessColorModel == DeviceRGB) % If we change the conditions, so that these keys are no longer present in the params % returned by the device, sending these keys to the device can trigger a fault. % This is a problem because of our stored dictionary: % % 1) Set up the inital dictioanry by retrieving the params from the device % 2) Change the conditions (ProcessColorModel == DeviceGray) % 3) merge any volatile keys from the device. Note that RedValues etc no longer defined. % 4) Call .installpagdevice, use the stored dicitonary to set the params % 5) The stored RedValues etc, cause an error. % % The stored dictioanry is readonly (we use forceput to wedge new keys into it) so % we can't 'undef' keys from it. (the dictionary is made readonly by the action of zsetpagedevice % '.setpagedevice' in PostScrfipt) % % So the only solution is to have 'write only' keys. These can be written to the device % but are not stored in the saved page device dictionary. This means PostScript programs % can't interrogate and take action on these, but there's no solution to that except to % rewrite this stuff completely so that it actually works properly. /.writeonlykeys mark /RedValues dup % Set by the device when ProcessColorModel changes /GreenValues dup % Set by the device when ProcessColorModel changes /BlueValues dup % Set by the device when ProcessColorModel changes /GrayValues dup % Set by the device when ProcessColorModel changes .dicttomark readonly def % This dictionary contains the keys we always want to read back from the device. /.volatilepdkeys mark /.MediaSize dup % because it changes when PageSize is set /RedValues dup % Set by the device when ProcessColorModel changes /GreenValues dup % Set by the device when ProcessColorModel changes /BlueValues dup % Set by the device when ProcessColorModel changes /GrayValues dup % Set by the device when ProcessColorModel changes /PageCount dup /Colors dup /BitsPerPixel dup /ColorValues dup /OutputICCProfile dup % ColorConversionStrategy can change this .dicttomark readonly def % The implementation of setpagedevice is quite complex. Currently, % everything but the media matching algorithm is implemented here. % By default, we only present the requested changes to the device, % but there are some parameters that require special merging action. % Define those parameters here, with the procedures that do the merging. % The procedures are called as follows: % <merged> <key> <new_value> -proc- <merged> <key> <new_value'> /.mergespecial mark /InputAttributes { dup //null eq { pop //null } { 3 copy pop .knownget { dup //null eq { pop dup length dict } { dup length 2 index length add dict .copydict } ifelse } { dup length dict } ifelse .copydict readonly } ifelse } bind /OutputAttributes 1 index /Policies { 3 copy pop .knownget { dup length 2 index length add dict .copydict } { dup length dict } ifelse copy readonly } bind .dicttomark readonly def % M. Sweet, Easy Software Products: % % Define NOMEDIAATTRS to turn off the default (but unimplementable) media % selection policies for setpagedevice. This is used by CUPS to support % the standard Adobe media attributes. NOMEDIAATTRS { % Define only PageSize for input attribute matching. /.inputattrkeys [ /PageSize ] readonly def % Define no other keys used in media selection. /.inputselectionkeys [ /noInputSelectionsKeys ] readonly def % Define no keys used in output attribute matching. /.outputattrkeys [ /noOutputAttrKeys ] readonly def } { % Define the keys used in input attribute matching. /.inputattrkeys [ /PageSize /MediaColor /MediaWeight /MediaType /InsertSheet /ManualFeed % The following are documented in Adobe's supplement for v2017. /LeadingEdge /MediaClass ] readonly def % Define other keys used in media selection. /.inputselectionkeys [ /MediaPosition /Orientation ] readonly def % Define the keys used in output attribute matching. /.outputattrkeys [ /OutputType ] readonly def } ifelse % Define all the parameters that should always be copied to the merged % dictionary. /.copiedkeys [ /OutputDevice //.mergespecial { pop } forall .inputattrkeys aload pop .inputselectionkeys aload pop .outputattrkeys aload pop ] readonly def % Define the parameters that should not be presented to the device. % The procedures are called as follows: % <merged> <key> <value> -proc- % The procedure leaves all its operands on the stack and returns % true iff the key/value pair should be presented to .putdeviceparams. /.presentspecial mark .readonlypdkeys { pop //false } forall % We must ignore an explicit request for .MediaSize, % because media matching always handles this. /.MediaSize //false /Name //false /OutputDevice //false /PageDeviceName //false /PageOffset //false /PageSize //false % obsolete alias for .MediaSize /InputAttributes //false .inputattrkeys { dup dup /PageSize eq exch /LeadingEdge eq or { pop } { { 2 index /InputAttributes .knownget { //null eq } { //true } ifelse } } ifelse } forall .inputselectionkeys { //false } forall /OutputAttributes //false .outputattrkeys { { 2 index /OutputAttributes .knownget { //null eq } { //true } ifelse } } forall /Install //false /BeginPage //false /EndPage //false /Policies //false % Our extensions: /HWColorMap { % HACK: don't transmit the color map, because % window systems can change the color map on their own % incrementally. Someday we'll have a better % solution for this.... //false } /ViewerPreProcess //false /ImagingBBox //false % This prevents the ImagingBBox value in the setpagedevice % from affecting the device's ImagingBBox parameter, but % does retain a 'shadow' copy at the PostScript level. % This is done for Adobe compatibility since Adobe does % render marks outside the ImagingBBox (and QuarkXpress % relies on it). .dicttomark readonly def % ---------------- End Keys and Attributes ---------------- % % Prepare to present parameters to the device, by spreading them onto the % operand stack and removing any that shouldn't be presented. /.prepareparams % <params> .prepareparams -mark- <key1> <value1> ... { mark exch dup { % Stack: -mark- key1 value1 ... merged key value //.presentspecial 2 index .knownget { exec { 3 -1 roll } { pop pop } ifelse } { 3 -1 roll } ifelse } forall pop } bind def currentdict /.presentspecial .undef % Compute the media size and initial matrix from a merged request (after % media selection). /.computemediasize % <request> .computemediasize % <request> <matrix> <[width height]> { dup /PageSize get % requested page size 1 index /InputAttributes get 2 index (%MediaSource) get get /PageSize get % media size % (may be a range) 2 index /Policies get dup /PageSize .knownget { exch pop } { /PolicyNotFound get } ifelse % PageSize policy, % affects scaling 3 index /Orientation .knownget not { //null } if 4 index /RollFedMedia .knownget not { //false } if matrix .matchpagesize not { % This is a "can't happen" condition! /setpagedevice .systemvar /rangecheck signalerror } if 2 array astore } bind def % Try setting the device parameters from the merged request. /.trysetparams % <merged> <(ignored)> <device> <Policies> % .trysetparams { //true 4 index //.prepareparams exec % Add the computed .MediaSize. % Stack: merged (ignored) device Policies -true- % -mark- key1 value1 ... counttomark 5 add index //.computemediasize exec exch pop exch pop /.MediaSize exch SETPDDEBUG { (Putting.) = pstack flush } if .putdeviceparamsonly SETPDDEBUG { (Result of putting.) = pstack flush } if } bind executeonly odef /.installpagedevice { % Since setpagedevice doesn't create new device objects, % we must (carefully) reinstall the old parameters in % the same device. .currentpagedevice pop //null currentdevice //null { //.trysetparams } //.internalstopped exec { //null } if dup type /booleantype eq { pop pop } { SETPDDEBUG { (Error in .trysetparams!) = pstack flush } if {cleartomark pop pop pop} //.internalstopped exec pop % if resetting the entire device state failed, at least put back the % security related key currentdevice //null //false mark /.LockSafetyParams currentpagedevice /.LockSafetyParams .knownget not {systemdict /SAFER .knownget not {//false} } if .putdeviceparamsonly /.installpagedevice cvx /rangecheck signalerror } ifelse pop pop % A careful reading of the Red Book reveals that an erasepage % should occur, but *not* an initgraphics. erasepage .beginpage } bind executeonly def /.uninstallpagedevice { {2 .endpage { .currentnumcopies //false .outputpage } if} //.internalstopped exec pop nulldevice } bind executeonly def (%grestorepagedevice) cvn { .uninstallpagedevice grestore //.installpagedevice exec } bind def (%grestoreallpagedevice) cvn { .uninstallpagedevice grestore //.installpagedevice exec grestoreall } bind def (%restore1pagedevice) cvn { .uninstallpagedevice grestore //.installpagedevice exec restore } bind def (%restorepagedevice) cvn { .uninstallpagedevice restore //.installpagedevice exec } bind def (%setgstatepagedevice) cvn { .uninstallpagedevice setgstate //.installpagedevice exec } bind def % Redefine .currentpagedevice and .setpagedevice so they convert between % null and a fixed empty directionary. /.nullpagedevice 0 dict readonly def /.currentpagedevice { //.currentpagedevice exch dup //null eq { pop //.nullpagedevice } if exch } bind odef /.setpagedevice { dup //.nullpagedevice eq { pop //null } if //.setpagedevice } bind odef % ---------------- Auxiliary definitions ---------------- % % Define the required attributes of all page devices, and their default values. % We don't include attributes such as .MediaSize, which all devices % are guaranteed to supply on their own. /.defaultpolicies mark % M. Sweet, Easy Software Products % % Due to the fact that it is not possible to properly implement % the selection policies from a Ghostscript driver, we have changed % the default policy to "7" (impose) to avoid numerous problems with % printing within CUPS... % % If NOMEDIAATTRS is false, the set the default depending on whether % PSFitPage is true. Policy 13 does best fit with page scaling up or down % so it is only useful if FIXEDMEDIA is also specified, or if the set of % media in the InputAttributes dictionary is the actual available choices % and does not include any "range" page sizes. /PageSize NOMEDIAATTRS { 7 } { //systemdict /PSFitPage known { 13 } { 0 } ifelse } ifelse /PolicyNotFound 1 /PolicyReport { dup /.LockSafetyParams known { % Only possible error is invalidaccess /setpagedevice .systemvar /invalidaccess signalerror } if pop } bind .dicttomark readonly def % Note that the values of .requiredattrs are executed, not just fetched. /.requiredattrs mark /PageDeviceName //null /PageOffset [0 0] readonly % We populate InputAttributes with all of the known page sizes % followed by a dummy media type that handles pages of any size. % This will create some duplicates, but that only slightly slows % down the media selection (loop is in zmedia2.c). % % Some PostScript creators assume that slot 0 is the default media % size and some can't handle a non-standard 4-element array which % is a 'range' type page size (always put last). % % Real Devices that can only handle specific page sizes will override this. /InputAttributes { mark % First put the device's default page size in slot 0 % This satifies those that have devices built with a4 as the default 0 mark /PageSize /GetDeviceParam .special_op not {/setpagedevice .systemvar /configurationerror signalerror} if .dicttomark % Only populate the other entries if we aren't FIXEDMEDIA FIXEDMEDIA not { statusdict /.pagetypenames get { statusdict /.pagetypeprocs get exch get 0 2 getinterval cvlit counttomark 1 sub 2 idiv exch mark exch /PageSize exch % stack: mark --dict-- --dict-- ... key mark /PageSize [x y] % see note above about pagetype executable array contents. .dicttomark } forall % If NORANGEPAGESIZE is defined, (-dNORANGEPAGESIZE), then don't add % the 'match any' PageSize entry systemdict /NORANGEPAGESIZE known not { % Add one last entry which is the 4 element range array (non-standard) counttomark 2 idiv % PageSize with either dimension 0 will be detected in % match_page_size, so we can allow it here mark /PageSize [0 dup 16#7ffff dup] .dicttomark } if } if % FIXEDMEDIA false .dicttomark } (%MediaSource) 0 /OutputAttributes { mark 0 mark .dicttomark readonly .dicttomark } (%MediaDestination) 0 /Install {{.callinstall}} bind /BeginPage {{.callbeginpage}} bind /EndPage {{.callendpage}} bind /Policies .defaultpolicies /ImagingBBox //null % default value /UseCIEColor /.getuseciecolor load .dicttomark readonly def % Define currentpagedevice so it creates the dictionary on demand if needed, % adding all the required entries defined just above. /.makecurrentpagedevice { % - .makecurrentpagedevice <dict> currentdevice //null .getdeviceparams % Make the dictionary large enough to add defaulted entries. counttomark 2 idiv //.requiredattrs length add dict counttomark 2 idiv { dup 4 2 roll put } repeat exch pop % Add any missing required attributes. % Make a writable and (if possible) local copy of any default % dictionaries, to work around a bug in the output of WordPerfect, % which assumes that these dictionaries are writable and local. .currentglobal exch dup gcheck .setglobal //.requiredattrs { 2 index 2 index known { 1 index /Policies eq { % Merge policies from the device driver with defaults 2 index % <<>> /key value <<>> 3 2 roll get % <<>> value <<policies>> exch { 2 index 2 index known { pop pop } { 2 index 3 1 roll put } ifelse } forall pop } { pop pop } ifelse } { exec 2 index 3 1 roll put } ifelse } forall exch .setglobal % Remove any keys we don't want to be stored, before .setpagedevice % makes the dictionary read only .writeonlykeys {2 index exch undef pop} forall dup .setpagedevice } bind def % Copy a dictionary recursively. /.copytree { % <dict> .copytree <dict'> dup length dict exch { dup type /dicttype eq { .copytree } if 2 index 3 1 roll put } forall } def /currentpagedevice { .currentpagedevice { dup length 0 eq { pop //.makecurrentpagedevice exec } { % If any of the dynamic keys have changed, % we must update the page device dictionary. currentdevice //.volatilepdkeys .getdeviceparams .dicttomark { % Stack: current key value 2 index 2 index .knownget { 1 index ne } { //true } ifelse { 2 index wcheck not { % This is the first entry being updated. % Copy the dictionary to make it writable. 3 -1 roll currentglobal 1 index dup gcheck currentglobal and setglobal length dict exch setglobal .copydict 3 1 roll } if 2 index 3 1 roll put } { pop pop } ifelse } forall % If the device is the distiller device, update distillerparams that % may have been changed by setdistillerparams /IsDistiller /GetDeviceParam .special_op { exch pop }{ //false }ifelse { currentdistillerparams { % Stack: current key value 2 index 2 index .knownget { 1 index ne } { //true } ifelse { 2 index 3 1 roll put } { pop pop } ifelse } forall } if % If the dictionary was global and is now local, copy % any global subsidiary dictionaries to local VM. This % too is to work around the Word Perfect bug (see above). dup gcheck not { dup { dup type /dicttype eq { dup gcheck } { //false } ifelse { % Copy-on-write, see above. 2 index wcheck not { 3 -1 roll dup length dict .copydict 3 1 roll } if //.copytree exec 2 index 3 1 roll put } { pop pop } ifelse } forall } if % We would like to do a .setpagedevice so we don't keep % re-creating the dictionary. Unfortunately, the effect % of this is that if any dynamic key changes (PageCount % in particular), we will do the equivalent of a % setpagedevice at the next restore or grestore. % Therefore, we make the dictionary read-only, but % we don't store it away. I.e., NOT: % dup wcheck { .setpagedevice .currentpagedevice pop } if readonly } ifelse } if } bind odef % Define access to device defaults. /.defaultdeviceparams { finddevice //null .getdeviceparams } bind def % Select media (input or output). The hard work is done in an operator: % <pagedict> <attrdict> <policydict> <keys> .matchmedia <key> true % <pagedict> <attrdict> <policydict> <keys> .matchmedia false % <pagedict> null <policydict> <keys> .matchmedia null true /.selectmedia % <orig> <request> <merged> <failed> <-- retained % <attrdict> <policydict> <attrkeys> <mediakey> % .selectmedia { 5 index 5 -2 roll 4 index .matchmedia % Stack: orig request merged failed attrkeys mediakey % (key true | false) { 4 index 3 1 roll put pop } { % Adobe's implementations have a "big hairy heuristic" % to choose the set of keys to report as having failed the match. % For the moment, we report any keys that are in the request % and don't have the same value as in the original dictionary. 5 index 1 index .knownget { 4 index 3 1 roll put } { 3 index exch .undef } ifelse { % Stack: <orig> <request> <merged> <failed> <attrkey> 3 index 1 index .knownget { 5 index 2 index .knownget { ne } { pop //true } ifelse } { //false } ifelse % Stack: ... <failed> <attrkey> <report> { 2 copy /rangecheck put } if pop } forall } ifelse } bind def % Apply Policies to any unprocessed failed requests. % As we process each request entry, we replace the error name % in the <failed> dictionary with the policy value, % and we replace the key in the <merged> dictionary with its prior value % (or remove it if it had no prior value). % These procedures are called with the following on the stack: % <orig> <merged> <failed> <Policies> <key> <policy> % They are expected to consume the top 2 operands. % NOTE: we currently treat all values other than 0, 1, or 7 (for PageSize) % the same as 0, i.e., we signal an error. /0Policy { % Set errorinfo and signal a configurationerror. NOMEDIAATTRS { % NOMEDIAATTRS means that the default policy is 7... pop 2 index exch 7 put } { pop dup 4 index exch get 2 array astore $error /errorinfo 3 -1 roll put cleartomark /setpagedevice .systemvar /configurationerror signalerror } ifelse } bind executeonly odef % Making this an operator means we can properly hide % the contents - specifically .forceput /1Policy { % Roll back the failed request to its previous status. SETPDDEBUG { (Rolling back.) = pstack flush } if 3 index 2 index 3 -1 roll .forceput 4 index 1 index .knownget { 4 index 3 1 roll .forceput } executeonly { 3 index exch .undef } ifelse } bind executeonly odef /7Policy { % For PageSize only, just impose the request. 1 index /PageSize eq { pop pop 1 index /PageSize 7 put } { .policyprocs 0 get exec } ifelse } bind executeonly odef /.applypolicies % <orig> <merged> <failed> .applypolicies % <orig> <merged'> <failed'> { 1 index /Policies get 1 index { type /integertype eq { pop % already processed }{ 2 copy .knownget not { 1 index /PolicyNotFound get } if % Stack: <orig> <merged> <failed> <Policies> <key> % <policy> dup 1 eq { 1Policy }{ dup 7 eq { 7Policy }{ 0Policy } ifelse } ifelse } ifelse } forall pop } .bind executeonly odef currentdict /0Policy undef currentdict /1Policy undef currentdict /7Policy undef % Put device parameters without resetting currentpagedevice. % (.putdeviceparams clears the current page device.) /.putdeviceparamsonly % <device> <Policies|null> <require_all> -mark- % <key1> <value1> ... .putdeviceparamsonly % On success: <device> <eraseflag> % On failure: <device> <Policies|null> <req_all> -mark- % <key1> <error1> ... { .currentpagedevice { counttomark 4 add 1 roll .putdeviceparams dup type /booleantype eq { 3 } { counttomark 5 add } ifelse -1 roll .setpagedevice } { pop .putdeviceparams } ifelse } bind def /.postinstall { % mark ... <failed> <merged> .postinstall - matrix currentmatrix .setdefaultmatrix % Erase and initialize the page. initgraphics currentoverprint //false setoverprint 1 setcolor .fillpage 0 setcolor setoverprint .beginpage % Clean up, calling PolicyReport if needed. % Stack: mark ... <failed> <merged> SETPDDEBUG { (Finishing.) = pstack flush } if exch dup length 0 ne { 1 index /Policies get /PolicyReport get counttomark 1 add 2 roll cleartomark exec } { cleartomark } ifelse pop } def % ---------------- setpagedevice itself ---------------- % /setpagedevice { % To avoid VM mismatches caused by copying subsidiary % dictionaries to local VM (see WorPerfect bug in % .makecurrentpagedevice) we want to make the dict % returned by currentpagedevice local. However, if we % run with -dSAFER we get a call to setpagedevice from % .setsafe in gs_init.ps during startup. The dict returned % by currentpagdevice is stored to the graphics state by % .setpagedevice below, and returned by currentpagdevice. % The Display PostScript code insists that the savedinitialgstate % not have any pointers to local VM objects, so if we simply % make the dict local then we fail in gs_dps.ps. The only % solution is to make sure the VM mode is global during % startup (to satisfy gs_dps.ps) and local thereafter % (to satisfy the WordPerfect bug). dup /..StartupGlobal known { currentglobal exch //true setglobal dup /..StartupGlobal undef } { % ensure that we are always in local VM mode to avoid % mismatches. This is because we always create child % dictionaries in local VM, regardless of the current VM state, % (see .makecurrentpagdevice) and we can't store local objects % in a global object, so we must ensure teh dictionary returned % from currentpagedevice is in local VM. currentglobal exch //false setglobal } ifelse %% We used to execute endpage after .tsrysetparams, but that actually alters %% the page device dictionary (in particular /PageSize) this is not correct. %% Testing with Adobe Acrobat Distiller shows that EndPage is ececuted if the %% page device dictionary is empty, and indeed even if setpagedevice returns %% an error (caught by stopped), so it seems pretty clear that we should %% run any required EndPage very early in the setpagedevice process. %% Bug 690667. 2 .endpage { 1 //true .outputpage (>>setpagedevice, press <return> to continue<<\n) //.confirm exec } if % We mustn't pop the argument until the very end, % so that the pseudo-operator machinery can restore the stack % if an error occurs. mark 1 index currentpagedevice % Check whether we are changing OutputDevice; % also handle the case where the current device % is not a page device. % Stack: mark <request> <current> SETPDDEBUG { (Checking.) = pstack flush } if dup /OutputDevice .knownget { % Current device is a page device. 2 index /OutputDevice .knownget { % A specific OutputDevice was requested. 2 copy eq { pop pop //null } { exch pop } ifelse } { pop //null } ifelse } { % Current device is not a page device. % Use the default device. 1 index /OutputDevice .knownget not { .defaultdevicename } if } ifelse dup //null eq { pop } { exch pop //.defaultdeviceparams exec % In case of duplicate keys, .dicttomark takes the entry % lower on the stack, so we can just append the defaults here. //.requiredattrs { exec } forall .dicttomark } ifelse % Check whether a viewer wants to intervene. % We must check both the request (which takes precedence) % and the current dictionary. % Stack: mark <request> <orig> exch dup /ViewerPreProcess .knownget { exec } { 1 index /ViewerPreProcess .knownget { exec } if } ifelse exch % Construct a merged request from the actual request plus % any keys that should always be propagated. % Stack: mark <request> <orig> SETPDDEBUG { (Merging.) = pstack flush } if exch 1 index length 1 index length add dict .copiedkeys { % Stack: <orig> <request> <merged> <key> 3 index 1 index .knownget { 3 copy put pop } if pop } forall % Stack: <orig> <request> <merged> dup 2 index { % stack: <orig> <request> <merged> <merged> <rkey> <rvalue> //.mergespecial 2 index .knownget { exec } if put dup } forall pop % Hack: if FIXEDRESOLUTION is true, discard any attempt to % change HWResolution. FIXEDRESOLUTION { dup /HWResolution .undef } if % Hack: if FIXEDMEDIA is true, discard any attempt to change % PageSize or HWSize unless the PageSize Policy 13 (for FitPage). dup /Policies get /PageSize get 13 ne FIXEDMEDIA and { dup /PageSize 4 index /PageSize get put dup /HWSize 4 index /HWSize get put } if % Hack: to work around some files that take a PageSize % from InputAttributes and impose it, discard any attempt % to set PageSize to a 4-element value. % Stack: mark <orig> <request> <merged> dup /PageSize .knownget { length 2 ne { dup /PageSize 4 index /PageSize get put } if } if % Select input and output media. % Stack: mark <orig> <request> <merged> SETPDDEBUG { (Selecting.) = pstack flush } if 0 dict % <failed> 1 index /InputAttributes .knownget { 2 index /Policies get .inputattrkeys (%MediaSource) cvn //.selectmedia exec } if 1 index /OutputAttributes .knownget { 2 index /Policies get .outputattrkeys (%MediaDestination) cvn //.selectmedia exec } if 3 -1 roll 4 1 roll % temporarily swap orig & request .applypolicies 3 -1 roll 4 1 roll % swap back % Construct the new device, and attempt to set its attributes. % Stack: mark <orig> <request> <merged> <failed> SETPDDEBUG { (Constructing.) = pstack flush } if % Non-obvious: we need to check the name of the output device, to tell % whether we're going to have to replace the entire device chain (which % may be only one device, or may be multiple devices. % If we're not replacing the entire change, we have to use the device in % the graphics state, so the configuration of the entire device chain is % correctly set. .currentoutputdevice .devicename 2 index /OutputDevice get eq { currentdevice } { 1 index /OutputDevice get finddevice } ifelse %**************** We should copy the device here, %**************** but since we can't close the old device, %**************** we don't. This is WRONG. %****************copydevice 2 index /Policies get //.trysetparams dup type /booleantype ne { % The request failed. % Stack: ... <orig> <request> <merged> <failed> <device> % <Policies> true mark <name> <errorname> ... SETPDDEBUG { (Recovering.) = pstack flush } if counttomark 4 add index counttomark 2 idiv { dup 4 -2 roll put } repeat pop pop pop % Stack: mark ... <orig> <request> <merged> <failed> <device> % <Policies> 6 2 roll 3 -1 roll 4 1 roll .applypolicies 3 -1 roll 4 1 roll 6 -2 roll //.trysetparams % shouldn't fail! dup type /booleantype ne { 2 { counttomark 1 add 1 roll cleartomark } repeat /setpagedevice .systemvar exch signalerror } if } if % The attempt succeeded. Install the new device. % Stack: mark ... <merged> <failed> <device> <eraseflag> SETPDDEBUG { (Installing.) = pstack flush } if pop % .setdevice clears the current page device! .currentpagedevice pop exch { .setdevice } stopped { cleartomark exch pop /setpagedevice cvx $error /errorname get signalerror } if pop .setpagedevice % Implement UseCIEColor directly if this is a LL3 system. % The color substitution feature is now implemented in % the interpreter, and this is used as an optimization. % % NB: This shoud be the only use of the .setuseciecolor % operator anywhere. % % Set some color space other than /DeviceGray, to insure % that initgraphics will actually perform a setcolorspace % operation (there is an optimization in setcolorspace % that does nothing if the operand and current color % spaces are the same) /.setuseciecolor where { pop 1 index /UseCIEColor .knownget { .setuseciecolor /DeviceRGB setcolorspace } if } if % Merge the request into the current page device, % unless we're changing the OutputDevice. % Stack: mark ... <merged> <failed> exch currentpagedevice dup length 2 index length add dict % Stack: mark ... <failed> <merged> <current> <newdict> 2 index /OutputDevice .knownget { 2 index /OutputDevice .knownget not { //null } if eq } { //true } ifelse { % Same OutputDevice, merge the dictionaries. .copydict } { % Different OutputDevice, discard the old dictionary. exch pop } ifelse .copydict % Initialize the default matrix, taking media matching % into account. //.computemediasize exec pop initmatrix concat dup /PageOffset .knownget { % Translate by the given number of 1/72" units in device X/Y. dup 0 get exch 1 get 2 index /HWResolution get dup 1 get exch 0 get 4 -1 roll mul 72 div 3 1 roll mul 72 div idtransform translate } if % We must install the new page device dictionary % before calling the Install procedure. dup .setpagedevice /HighLevelDevice /GetDeviceParam .special_op { exch pop not }{ //true }ifelse { .setdefaulthalftone % Set the default screen before calling Install. } if dup /Install .knownget { { .execinstall } stopped { pop % Install procedure failed. One element will have been left on the stack. % stack: mark <orig> <request> <failed> <merged> 1 index /Install $error /errorname get put % Put it in the "failed" dict % .applypolicies needs stack: <orig> <merged> <failed> exch 4 2 roll exch 4 2 roll .applypolicies exch 4 2 roll exch 4 2 roll % Now execute the old Install -- failures after this are not handled dup /Install .knownget { { .execinstall } stopped { pop } if } if //.postinstall exec stop } { //.postinstall exec } ifelse } { //.postinstall exec } ifelse setglobal % return to original VM allocation mode } .bind executeonly odef % We break out the code after calling the Install procedure into a % separate procedure, since it is executed even if Install causes an error. % By making .execinstall a separate operator procedure, we get the stacks % mostly restored if it fails, except for one element (the operand). % Thus if it fails, there will be one element left on the op stack. /.execinstall { % <proc> .execinstall - dup % element left on the stack if the exec fails. % Because the interpreter optimizes tail calls, we can't just let % the body of this procedure be 'exec', because that would lose % the stack protection that is the whole reason for having the % procedure in the first place. The 'pop' for the dummy element % on the op stack suffices. exec pop % See above. } odef [ /.computemediasize /.prepareparams /.selectmedia /.trysetparams /.installpagedevice /.postinstall /.defaultdeviceparams /.makecurrentpagedevice /.mergespecial /.requiredattrs /.applypolicies % /.copytree % /.uninstallpagedevice % (called from C code) ] dup currentdict .undefinternalnames systemdict .undefinternalnames end % level2dict .setlanguagelevel gs_fntem.ps 0000644 00000026175 15030647507 0006734 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % A procset for Postscript font emulation % The procedures must not depend on the presence of the % procset dictionary on the dictionary stack. languagelevel 2 .setlanguagelevel %========================= Process xlatmap ==================== mark %% Replace 1 (xlatmap) (xlatmap) .runlibfile .dicttomark dup systemdict exch /.xlatmap_dict exch put % Convert it into a plain text to simplify the processing in C : % *(fontkind\0\0\ *(charmap\0decoding\0) ) \0 () exch { 3 1 roll =string cvs concatstrings (\0\0) concatstrings exch { =string cvs concatstrings (\0) concatstrings } forall } forall (\0) concatstrings systemdict exch /.xlatmap exch put /FontEmulationProcs 10 dict begin %-------------------------------Font-------------------------------- /FontCommon % - font_common - { currentdict /PaintType known not { /PaintType 0 def } if currentdict /Encoding .knownget not { //StandardEncoding } if dup type /nametype eq { /Encoding findresource } if /Encoding exch def } bind def /FontOptions 5 dict begin /make_procs currentdict def /NameKey /FontName def /TypeKey /FontType def 1 { currentdict /FontMatrix known not { /FontMatrix [0.001 0 0 0.001 0 0] def } if currentdict /FontBBox known not { /FontBBox [-128 -128 1024 1024] cvx def } if % zfapi.ps refines it. /Private 0 dict def % if we're using the FAPI/UFST code for Microtype fonts, % then we've already created a "fake" CharStrings, so don't replace it. % See gs_fapi.ps currentdict /CharStrings known not {/CharStrings << /.notdef () >> def} if //FontCommon exec } bind def 42 { /FontMatrix [1 0 0 1 0 0] def /FontBBox [0 0 1 1] def % zfapi.ps refines it. /CharStrings <<>> def /sfnts [<00010000 0000 0000 0000 0000 0000>] def /GlyphDirectory [] def //FontCommon exec } bind def %fixme : more font types. currentdict end def %---------------------------CIDFont--------------------------- /TranslateCSI % <record> TranslateCSI <CSI> { RESMPDEBUG { (fntem TranslateCSI beg ) = } if begin CSI length 2 eq { << /Registry (Adobe) /Ordering CSI aload pop /Supplement exch >> } { << /Registry CSI 0 get /Ordering CSI 1 get /Supplement CSI 2 get >> } ifelse end RESMPDEBUG { (fntem TranslateCSI end ) = } if } bind def /CIDFontCommon { /CIDSystemInfo currentdict //TranslateCSI exec def currentdict /CSI undef /FontBBox [-128 -128 1024 1024] def % zfapi.ps refines it. /CIDCount 1 def % ChooseDecoding will set a reasonable value. } bind def % GFlyph substitution table for narrow, wide, proportional glyphs - % used with TrueTypes. currentpacking //false setpacking /SubstNWP << % Array format : orig_type, beg_CID, end_CID, subst_beg_CID, subst_type % type = (n==narrow, w==wide, p==proportional). /Japan1 { p 1 94 231 n p 17 26 780 w p 34 59 790 w p 66 91 816 w w 842 842 7918 w % fixme: These substitutions require to shift the glyph origin. w 844 844 7919 w w 846 846 7920 w w 848 848 7921 w w 850 850 7922 w w 876 876 7923 w w 908 908 7924 w w 910 910 7925 w w 912 912 7926 w w 914 914 7927 w w 925 925 7928 w w 927 927 7929 w w 929 929 7930 w w 931 931 7931 w w 933 933 7932 w w 959 959 7933 w w 991 991 7934 w w 993 993 7935 w w 995 995 7936 w w 1002 1002 7937 w w 1009 1009 7938 w w 1010 1010 7939 w } cvlit /Japan2 1 index /CNS1 { p 1 94 13648 n p 17 26 333 w p 34 59 365 w p 66 91 391 w } cvlit /GB1 { p 2 94 814 n p 2 94 262 w p 1 1 7716 n } cvlit /Korea1 { p 1 60 8094 n p 62 94 8155 n p 2 59 264 w p 63 94 325 w } cvlit /Identity [] /Unicode [] >> def setpacking /CIDFontOptions 5 dict begin /make_procs currentdict def /NameKey /CIDFontName def /TypeKey /CIDFontType def 0 { //CIDFontCommon exec /FDArray [ 14 dict begin /FontName CIDFontName =string cvs (%) concatstrings cvn def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0 ] def /PaintType 0 def /Private 0 dict def currentdict end ] def /GlyphDirectory [] def /GDBytes 1 def /FDBytes 0 def } bind def 1 { //CIDFontCommon exec /FontMatrix [1 0 0 1 0 0] def /BuildGlyph {} def } bind def 2 { //CIDFontCommon exec /FontMatrix [1 0 0 1 0 0] def /GDBytes 2 def /CIDMap <0000> def /sfnts [<00010000 0000 0000 0000 0000 0000>] def /Encoding [] def /CharStrings << /.notdef 0 >> def } bind def currentdict end def /complete_instance % <font_name> <FontDict> <Options> complete_FAPI_Font <font_name> <FontDict> { begin dup length dict copy begin dup type /nametype ne { cvn } if dup NameKey exch def currentglobal //true setglobal make_procs TypeKey load .knownget { exec } { setglobal /complete_instance cvx /invalidfont signalerror } ifelse setglobal currentdict end end } bind def /GetFilePath % <scratch> <Name> <record> GetFilePath <filepath> { exch pop % (scratch) <record> /Path get % (scratch) (path) exch copy % What we make here it is not a complete PS resource. % Unable to provide full conformity : % the attempt to run this file may fail. } bind def /GetSize % <Name> <record> GetSize <size> { pop pop -1 % Unknown size. % fixme: probably we could provide an estimation size for some fonts. } bind def /RecordVirtualMethodsStub 3 dict begin /GetFilePath //GetFilePath def /GetSize //GetSize def currentdict end def % ---------------------- Decoding helpers ---------------------------- /encodingnames mark StandardEncoding /StandardEncoding ISOLatin1Encoding /ISOLatin1Encoding SymbolEncoding /SymbolEncoding DingbatsEncoding /DingbatsEncoding .dicttomark def /ChooseDecoding % <font> ChooseDecoding <font> { { % A loop for 'exit' context. dup /Decoding .knownget { dup type /nametype eq { 1 index /CIDFontType known { /CIDDecoding } { /Decoding } ifelse findresource 1 index exch /Decoding exch put } { pop } ifelse dup /CIDFontType known { dup dup /Decoding get /CIDCount get /CIDCount exch put } if exit } if dup /CIDFontType known { % This is a hooked CID font, no need for Decoding. exit } if % This works when the renderer can't choose character by name, % and we cannot determine the charset. % Probably this branch is to be removed after UFST problem is fixed. dup /Encoding get % <<font>> encoding dup type /nametype eq { /Decoding findresource 1 index exch /Decoding exch put } { dup //encodingnames exch .knownget { { /Decoding findresource } stopped {pop pop //true}{ exch pop 1 index exch /Decoding exch put //false } ifelse } { //true } ifelse { % unknown encoding, or an encoding for which we don't have a % predefined decoding, convert it to decoding : currentglobal 3 1 roll 2 index gcheck setglobal dup length dict begin /.notdef 0 def 0 1 currentdict length 1 sub { dup 2 index exch get dup dup /.notdef ne exch type /nulltype ne and { exch def } { pop pop } ifelse } for pop currentdict end 3 -1 roll setglobal 1 index exch /Decoding exch put } if } ifelse exit } loop dup /CIDFontType known { dup /SubstNWP .knownget not { dup /CIDSystemInfo get /Ordering get cvn } if dup type /nametype eq { //SubstNWP exch .knownget not { [] } if % <<font>> [SubstNWP] } if 1 index exch /SubstNWP exch put } if } bind def /PrintFontRef % <string|name> <font> PrintFontRef <string|name> <font> { dup /FontName known { (Font ) } { (CIDFont ) } ifelse print 1 index =string cvs print dup /FontName .knownget not { dup /CIDFontName get } if % <string|name> <font> <fontname> dup 3 index ne { ( \( aliased from ) print =string cvs print ( \)) print } { pop } ifelse } bind def /GetFontType % <font> GetFontType int { dup /CIDFontType .knownget { exch pop 9 add } { /FontType get } ifelse } bind def /FindInArray % <array> <elem> .array_find <bool> { //false 3 1 roll exch { % false elem elem_i 1 index eq { % false elem pop //true exch } if } forall pop } bind def /ProvideUnicodeDecoding % <font> ProvideUnicodeDecoding <font> { % If the font is maintained by FAPI, or if it is TT-emulated CID font, % it already has /Decoding. But its value isn't guaranteeed to % be an Unicode decoding. Since we can't determine whether % it is an Unicode decoding, we unconditionally load an appropriate Unicode decoding % and attach it with /GlyphNames2Unicode entry. % % Another interesting case is when the font already has /GlyphNames2Unicode. % The latter to be used instead. Note that /GlyphNames2Unicode % appears only when type 32 fonts are disable (see .pdf_hook_DSC_Creator), % but an automatic disabling is not implemented yet. currentglobal //true setglobal exch dup /FontInfo known not { dup /FontInfo 1 dict put } if { % A loop just for 'exit' context. dup /FontInfo get /GlyphNames2Unicode known { exit } if dup /CIDFontType known { dup mark exch % bool <font> [ <font> dup /CIDSystemInfo get /Ordering get (.Unicode) % bool <font> [ <font> () () concatstrings cvn % bool <font> [ <font> /Name /CIDDecoding { findresource } stopped { % Can't provide a decoding, giving up without creating /GlyphNames2Unicode. cleartomark exit } if % bool <font> [ <font> <D> exch /FontInfo get exch % bool <font> [ <FI> <D> /GlyphNames2Unicode exch .forceput % FontInfo can be read-only. pop % bool <font> exit } executeonly if dup /FontInfo get % bool <font> <FI> /GlyphNames2Unicode /Unicode /Decoding findresource .forceput % FontInfo can be read-only. exit } executeonly loop exch setglobal } .bind executeonly odef % must be bound and hidden for .forceput currentdict end /ProcSet defineresource pop .setlanguagelevel pdf_draw.ps 0000644 00000561742 15030647507 0006724 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % pdf_draw.ps % PDF drawing operations (graphics, text, and images). /.setlanguagelevel where { pop 2 .setlanguagelevel } if .currentglobal //true .setglobal /GS_PDF_ProcSet load begin pdfdict begin % For simplicity, we use a single interpretation dictionary for all % PDF graphics operations, even though this is too liberal. /drawopdict 100 dict def % ================================ Graphics ================================ % % ---------------- Functions ---------------- % % Note that resolvefunction converts a PDF Function to a PostScript Function; % resolve*fnproc converts a PDF function to a PostScript procedure. % We need to process all required and optional parameters to resolve any % use of indirect references. /fnrdict mark 0 { .resolvefn0 } 2 { .resolvefn2 } 3 { .resolvefn3 } 4 { .resolvefn4 } .dicttomark readonly def /.resolvefn0 { dup length 1 add dict .copydict % make room for DataSource % now resolve any indirect references dup /Size 2 copy knownoget { put } { pop pop } ifelse dup /BitsPerSample 2 copy knownoget { put } { pop pop } ifelse dup /Order 2 copy knownoget { put } { pop pop } ifelse dup /Encode 2 copy knownoget { put } { pop pop } ifelse dup /Decode 2 copy knownoget { put } { pop pop } ifelse % Don't lose our place in PDFfile. PDFfile fileposition exch dup //true resolvestream % The stream isn't positionable, so read all the data now. % Stack: filepos fndict stream 1 index /Range get length 2 idiv 2 index /BitsPerSample get mul 2 index /Size get { mul } forall 7 add 8 idiv dup 65535 le { string 1 index exch readstring pop } { 1 index exch () /SubFileDecode filter /ReusableStreamDecode filter } ifelse exch closefile % Stack: filepos fndict data exch dup /DataSource 4 -1 roll put exch PDFfile exch setfileposition } bind executeonly def /.resolvefn2 { dup length dict .copydict dup /C0 2 copy knownoget { put } { pop pop } ifelse dup /C1 2 copy knownoget { put } { pop pop } ifelse dup /N 2 copy knownoget { put } { pop pop } ifelse } bind executeonly def /.resolvefn3 { dup length dict .copydict dup /Bounds 2 copy knownoget { put } { pop pop } ifelse dup /Encode 2 copy knownoget { put } { pop pop } ifelse dup /Functions 2 copy oget mark exch dup { oforce .resolvefn } forall counttomark -1 roll astore exch pop put } bind executeonly def /.resolvefn4 { PDFfile fileposition exch % filepos fndict dup //true resolvestream % filepos fndict stream exch dup length dict copy % filepos stream fndict2 dup /Function undef % filepos stream fndict2 exch dup token not { () /rangecheck signalerror } if exch token { /rangecheck signalerror } if % Use .bind to avoid idiom recognition. .bind 1 index /Function 3 -1 roll put exch PDFfile exch setfileposition } bind executeonly def /.resolvefn { % <fndict> .resolvefn <fndict'> dup length dict .copydict dup /Domain 2 copy knownoget { put } { pop pop } ifelse dup /Range 2 copy knownoget { put } { pop pop } ifelse dup /FunctionType oget //fnrdict exch get exec } bind executeonly def /resolvefunction { % <fndict> resolvefunction <function> .resolvefn PDFDEBUG { //pdfdict /PDFSTEPcount .knownget { 1 le } { //true } ifelse { (%Function: ) print dup === flush } if } if } bind executeonly def /resolvefnproc { % <fndict> resolvefnproc <proc> resolvefunction .buildfunction } bind executeonly def /resolveidfnproc { % <fndict> resolveidfnproc <proc> dup /Identity eq { pop { } } { resolvefnproc } ifelse } bind executeonly def /resolvedefaultfnproc { % <fndict> <default> resolved'fnproc <proc> 1 index /Default eq { exch pop } { pop resolveidfnproc } ifelse } bind executeonly def %% A BBox where width or height (or both) is 0 should still paint one pixel %% See the ISO 32000-2:2017 spec, section 8.7.4.3, p228 'BBox' and 8.7.3.1 /FixPatternBBox { dup aload pop 3 index 2 index sub 0 eq { 3 index 0.000001 add 3 -1 roll pop exch } if 2 index 1 index sub 0 eq { 2 index 0.000001 add exch pop }if 5 -1 roll astore }bind executeonly def % ---------------- Shadings ---------------- % /shrdict mark /Coords { aload 5 1 roll 4 { % Bug 694542 dup type dup /integertype ne exch /realtype ne and { ( **** Error: replacing malformed number ') pdfformaterror pdfstring cvs pdfformaterror (' with 0.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror 0 } if 4 1 roll } repeat 5 -1 roll astore } bind executeonly /BBox { dup dup dup aload pop normrect_elems 5 -1 roll astore FixPatternBBox } bind executeonly /ColorSpace { resolvecolorspace } bind executeonly /Function { dup type /dicttype eq { resolvefunction } { [ exch { oforce resolvefunction } forall ] } ifelse } bind executeonly /Extend { mark exch {oforce} forall ] } bind executeonly .dicttomark readonly def /resolveshading { % <shadingstream> resolveshading <shading> dup /.shading_dict .knownget { exch pop dup /ShadingType get 4 ge { dup /DataSource get 0 setfileposition } if } { dup PDFfile fileposition exch mark exch { oforce //shrdict 2 index .knownget { exec } if } forall .dicttomark dup /ShadingType get 4 ge { dup dup //true resolvestream % Make a reusable stream so that the shading doesn't % reposition PDFfile at unexpected times. /ReusableStreamDecode filter /DataSource exch put } if exch PDFfile exch setfileposition dup 3 1 roll /.shading_dict exch put } ifelse } bind executeonly def /resolvesh { % <shname> resolvesh <shading> % <shname> resolvesh <null> Page /Shading rget { %% Horrible hacky fix, see /DoImage later in ths file for more information %% dup /ColorSpace known { dup /ColorSpace get dup type /arraytype eq { exch dup length dict copy exch dup length array copy /ColorSpace exch 2 index 3 1 roll put } {pop} ifelse } if resolveshading } { //null }ifelse } bind executeonly def % ---------------- Halftones ---------------- % /spotfunctions mark /Round { abs exch abs 2 copy add 1 le { dup mul exch dup mul add 1 exch sub } { 1 sub dup mul exch 1 sub dup mul add 1 sub } ifelse } bind executeonly /Diamond { abs exch abs 2 copy add .75 le { dup mul exch dup mul add 1 exch sub } { 2 copy add 1.23 le { .85 mul add 1 exch sub } { 1 sub dup mul exch 1 sub dup mul add 1 sub } ifelse } ifelse } bind executeonly /Ellipse { abs exch abs 2 copy 3 mul exch 4 mul add 3 sub dup 0 lt { pop dup mul exch .75 div dup mul add 4 div 1 exch sub } { dup 1 gt { pop 1 exch sub dup mul exch 1 exch sub .75 div dup mul add 4 div 1 sub } { .5 exch sub exch pop exch pop } ifelse } ifelse } bind executeonly /EllipseA { dup mul .9 mul exch dup mul add 1 exch sub } bind executeonly /InvertedEllipseA { dup mul .9 mul exch dup mul add 1 sub } bind executeonly /EllipseB { dup 5 mul 8 div mul exch dup mul exch add sqrt 1 exch sub } bind executeonly /EllipseC { dup mul .9 mul exch dup mul add 1 exch sub } bind executeonly /InvertedEllipseC { dup mul .9 mul exch dup mul add 1 sub } bind executeonly /Line { exch pop abs neg } bind executeonly /LineX { pop } bind executeonly /LineY { exch pop } bind executeonly /Square { abs exch abs 2 copy lt { exch } if pop neg } bind executeonly /Cross { abs exch abs 2 copy gt { exch } if pop neg } bind executeonly /Rhomboid { abs exch abs 0.9 mul add 2 div } bind executeonly /DoubleDot { 2 {360 mul sin 2 div exch } repeat add } bind executeonly /InvertedDoubleDot { 2 {360 mul sin 2 div exch } repeat add neg } bind executeonly /SimpleDot { dup mul exch dup mul add 1 exch sub } bind executeonly /InvertedSimpleDot { dup mul exch dup mul add 1 sub } bind executeonly /CosineDot { 180 mul cos exch 180 mul cos add 2 div } bind executeonly /Double { exch 2 div exch 2 { 360 mul sin 2 div exch } repeat add } bind executeonly /InvertedDouble { exch 2 div exch 2 { 360 mul sin 2 div exch } repeat add neg } bind executeonly .dicttomark readonly def /.resolveht1 { mark exch { oforce 1 index /SpotFunction eq { dup type /arraytype eq { %% check all the names in the array in turn, stop when we find %% the first one we recognise. { //spotfunctions exch .knownget { exit } if } forall dup type /nametype eq { %% If we didn't find any that we recognise, then use %% the default halftone's spot function .setdefaulthalftone currenthalftone dup /SpotFunction .knownget { exch pop }{ /GraySpotFunction .knownget not { //spotfunctions /Round get } if }ifelse } if }{ dup type /nametype eq { //spotfunctions exch get } { resolvefnproc } ifelse } ifelse } { 1 index /TransferFunction eq { resolveidfnproc } if } ifelse } forall .dicttomark } bind executeonly def /.resolveht5 { mark exch { oforce dup type /dicttype eq { resolvehalftone } if } forall .dicttomark } bind executeonly def /.resolveht6 { %% resolvestream will reposition PDFfile. If we are in the middle %% of reading a content stream from PDFfile when we execute this, %% then reading the next buffer will read from the wrong place. We %% must save and restore the position of PDFfile. See the definition %% of resolvestream. Bug #695886 PDFfile fileposition exch mark exch { oforce } forall .dicttomark dup dup //false resolvestream /ReusableStreamDecode filter /Thresholds exch put dup /TransferFunction .knownget { resolveidfnproc 1 index exch /TransferFunction exch put } if exch PDFfile exch setfileposition } bind executeonly def /htrdict mark 1 //.resolveht1 5 //.resolveht5 6 //.resolveht6 10 //.resolveht6 16 //.resolveht6 .dicttomark readonly def currentdict /.resolveht1 undef currentdict /.resolveht5 undef currentdict /.resolveht6 undef /resolvehalftone { % <dict> resolvehalftone <halftone> dup /HalftoneType oget dup //htrdict exch .knownget { exch pop exec } { =string cvs ( **** Error: Incorrect halftone type ) exch concatstrings (. Using defailt.\n) concatstrings pdfformaterror ( Output may be incorrect.\n) pdfformaterror gsave .setdefaulthalftone currenthalftone grestore } ifelse } bind executeonly def % ---------------- Graphics state management ---------------- % /cmmatrix matrix def drawopdict begin % Graphics state stack /q { q } executeonly def /Q { Q } executeonly def % Graphics state setting /cm { //cmmatrix astore .getpath exch concat newpath { exec } forall % If inside a BT/ET block, we need to update the TextSaveMatrix currentdict /TextSaveMatrix .knownget { //cmmatrix exch dup concatmatrix pop } if % And if we ha\ve done a gsave inside a text block, we need to update % that matrix instead. currentdict /qTextSaveMatrix .knownget { //cmmatrix exch dup concatmatrix pop } if } bind executeonly def /i { 1 .min setflat } bind executeonly def /J { setlinecap } bind 0 get def /d { setdash } bind 0 get def /j { setlinejoin } bind 0 get def /w { setlinewidth } bind 0 get def /M { 1 .max setmiterlimit } bind executeonly def /gs { gs } executeonly def end % Each entry in this dictionary is % <gsres> <value> -proc- <gsres> /gsbg { /BGDefault load resolvedefaultfnproc setblackgeneration } bind executeonly def /gsucr { /UCRDefault load resolvedefaultfnproc setundercolorremoval } bind executeonly def /gstr { dup type /arraytype eq { { oforce /TRDefault load resolvedefaultfnproc } forall setcolortransfer } { /TRDefault load resolvedefaultfnproc settransfer } ifelse } bind executeonly def /gsparamdict mark /SA { setstrokeadjust } executeonly /OP { 1 index /op known not { dup op } if OP } executeonly % The PDF 1.3 specification says that the name /Default is only % recognized for {BG,UCR,TR}2. However, PDF 1.3 files produced % by Adobe Acrobat Distiller 4.0 for Windows use the name /Default % with the older keys, so we have to implement this. /BG { 1 index /BG2 known { pop } { gsbg } ifelse } executeonly /UCR { 1 index /UCR2 known { pop } { gsucr } ifelse } executeonly /TR { 1 index /TR2 known { pop } { gstr } ifelse } executeonly % Some functions used to implement phases of HT and HTP /sethalftones { % As is so often the case, if we get an error we need to clean up the stack, but we can't % use mark/cleartomark, because the action which caused the error may have left a mark % on the stack. So we need to define our own mark. On an error we'll clean up the stack % until we reach this unique key on the stack /SethalftonesMark exch dup /Default eq { pop .setdefaulthalftone pop } { {resolvehalftone} stopped { (\n **** Error resolving halftone. Ignoring the halftone, output may be incorrect.\n) pdfformaterror % Clean up the stack by checking every entry until we find our unique key {/SethalftonesMark eq {exit} if} loop } { {sethalftone} stopped { (\n **** Error setting halftone. Ignoring the halftone, output may be incorrect.\n) pdfformaterror % Clean up the stack by checking every entry until we find our unique key {/SethalftonesMark eq {exit} if} loop } { pop }ifelse }ifelse } ifelse } bind executeonly def /sethalftonephases { {aload pop -1 2 index 2 index .setscreenphase pop pop} stopped { (\n **** Error setting halftone phase. Ignoring the phase, output may be incorrect.\n) pdfformaterror } if } bind executeonly def /HT { dup sethalftones .swapcolors sethalftones .swapcolors % the transfer function may dependent on the halftone, so make sure % it is set if included in the graphic state (otherwise this is % subject to order of a dictionary forall, which is unpredictable) dup /TR2 .knownget { dup /Default eq { oforce gsparamdict /TR2 get exec } { pop } ifelse } { dup /TR .knownget { /dup /Default eq { oforce gsparamdict /TR get exec } { pop } ifelse } if } ifelse } executeonly /HTP { % HTP may be present even if this isn't a DPS interpreter. dup sethalftonephases .swapcolors sethalftonephases .swapcolors } executeonly % PDF 1.3 % The font is an indirect reference, not a resource name /Font { aload pop exch oforce resourcefont exch Tf } /LW { setlinewidth } executeonly /LC { setlinecap } executeonly /LJ { setlinejoin } executeonly /ML { 1 .max setmiterlimit } executeonly /D { aload pop setdash } executeonly /RI { ri } executeonly /op { op } executeonly /OPM { OPM } executeonly /BG2 { gsbg } executeonly /UCR2 { gsucr } executeonly /TR2 { gstr } executeonly /FL { 1 .min setflat } executeonly /SM { % SM may be present even if this is only a Level 2 interpreter. /setsmoothness where { pop setsmoothness } { pop } ifelse } executeonly % PDF 1.4 % All of these require the "transparency" feature in the interpreter. /ca { ca } executeonly /CA { CA } executeonly /SMask { {gssmask} PDFSTOPONERROR { exec //false } { stopped } ifelse { pop (\n **** Error in SMask during ExtGState. Ignoring the mask, output may be incorrect.\n) pdfformaterror } if } executeonly /AIS { AIS } executeonly /BM { BM } executeonly /TK { TK } executeonly /UseBlackPtComp { UseBlackPtComp } executeonly /HTO { % PDF 2.0, supposed to be 'similar' to halftone phase but using a different % co-ordiate system. Treat the same for now and fix if anyone ever complains. aload pop transform cvi exch cvi exch 2 array astore dup sethalftonephases .swapcolors sethalftonephases .swapcolors } executeonly .dicttomark readonly def /gs { % <gsres> gs - Page /ExtGState rget { % We keep the dictionary on the stack during the forall so that % keys that interact with each other have access to it. dup { oforce exch gsparamdict exch .knownget { exec } { pop } ifelse } forall pop } { //pdfdict /.gs_warning_issued known not { (\n **** Error 'gs' ignored -- ExtGState missing from Resources.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror //pdfdict /.gs_warning_issued //true .forceput PDFSTOPONERROR { /gs cvx /undefined signalerror } if } executeonly if } executeonly ifelse } bind executeonly def % ------ Transparency support ------ % /gssmask { { dup type /dicttype eq { dup /G knownogetdict {pop} { ( **** Error: Ignoring invalid transparency SMask group\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror % replace the invalid SMask object pop /None } ifelse } if dup /None eq 1 index //null eq or PDFusingtransparency not or { pop //null .currentSMask //null ne { % get rid of the current SMask (Bug 695471) //false % colorspace not set << /Subtype /None >> % Special type for this purpose 0 0 0 0 % fake BBox .begintransparencymaskgroup } if exit } if % Preprocess the SMask value into a parameter dictionary for % .begintransparencymaskgroup, with added /BBox and /Draw keys. mark exch % Stack: mark smaskdict dup /S oget /Subtype exch 3 2 roll % Stack: mark ... smaskdict dup /BC knownoget { dup /Background exch 4 2 roll 1 index /G oget /Group knownoget not { ( **** Error: Ignoring a transparency group XObject without /Group attribute.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror cleartomark //null exit } if gsave //nodict begin dup /CS knownoget { exch pop resolvecolorspace dup setgcolorspace csput } { % Group attributes dictionaries are supposed to contain a /CS % entry, but Acrobat apparently also handles a /ColorSpace.... /ColorSpace knownoget { ( **** Error: A transparency group XObject has a /ColorSpace instead of /CS attribute.\n) pdfformaterror resolvecolorspace dup setgcolorspace csput } { ( **** Error: Ignoring a transparency group XObject without /CS attribute.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror cleartomark //null exit }ifelse } ifelse aload pop setcolor [ currentgray ] end grestore /GrayBackground exch 3 2 roll } if dup /TR knownoget { dup /Identity eq { pop } { resolvefnproc /TransferFunction exch 3 2 roll } ifelse } if dup /G oget dup /BBox oget oforce_array 1 index /Matrix knownoget { oforce_array .bbox_transform 4 array astore } if /BBox exch 4 2 roll % Because we don't execute the group form stream until we find % out whether we're actually going to draw through it, we need % to save the current gstate with the other parameters, so % we can subsequently execute it in the correct graphics state. % We need to concatenate the Matrix in this gstate as per the PDF % spec 7.5.4 (p. 552 in the PDF 1.7 Ref) (bug 694455). gsave dup /Matrix knownoget { matrix currentmatrix matrix concatmatrix setmatrix } if /GroupGState gstate currentgstate 6 2 roll grestore /GroupMat matrix currentmatrix 8 2 roll % /GroupExtGState 1 dict % 10 2 roll /.execmaskgroup cvx 2 packedarray cvx /Draw exch 3 2 roll pop .dicttomark exit } loop SMask } bind executeonly def % Functions specific to the Device* colorspaces to force the switch to % the Device* colorspace so that the SMask will not get a CIEBased* colorspace % in the case when UseCIEColor changes the Device* colorspace to something else. % Also see the logic in pdf_main.ps:pdfopen that similarly defines these resources. /forceDefaultCS << { currentcolorspace setcolorspace % this will switch to Device colorspace } bind executeonly /DeviceGray exch /DeviceRGB 1 index /DeviceCMYK 1 index >> def % This procedure is called to actually render the soft mask. /.execmaskgroup { % <masknum> <paramdict> <formdict> .execmaskgroup - % Save our place in PDFfile. Do not use gsave-grestore when creating % a soft mask with .begintransparencygroup because high level devices % need to modify the graphic state by storing the soft mask ID. % Save the ExtGState (//nodict begin) BEFORE changing the colorspace //nodict begin matrix currentmatrix 4 1 roll mark currentcolor counttomark dup 4 add exch roll pop currentcolorspace 4 1 roll .getuseciecolor 4 1 roll .swapcolors mark currentcolor counttomark dup 4 add exch roll pop currentcolorspace 4 1 roll .swapcolors currentuserparams /OverrideICC get 4 1 roll mark /OverrideICC //true .dicttomark setuserparams % We can't simply set the group's gstate here because % we can't use gsave/grestore. So we actually set it % in .execgroup. But the matrix needs set here for % .begintransparencymaskgroup to correctly work. % It might seem we should also set the colorspace % in case the group doesn't have one, *but* empirical % suggests that is not the case - fts_26_2600.pdf and % fts_26_2603.pdf render incorrectly if we set the % colrospace 1 index /GroupMat .knownget { setmatrix } if PDFfile fileposition 4 1 roll % We have to select the group's color space so that the % background color will be interpreted correctly. % [save/restore]DefaultCS make sure that the SMask logic sees % the Device* spaces, not CIEBased* that UseCIEColor may have % established. //false .setuseciecolor % SMask gets processed without UseCIEColor dup /Group oget /CS knownoget { resolvecolorspace dup setgcolorspace csput //true % use currentcolorspace } { % Group attributes dictionaries are supposed to contain a /CS % entry, but Acrobat apparently also handles a /ColorSpace.... dup /Group oget /ColorSpace knownoget { ( **** Error: A transparency group attribute dictionary has a /ColorSpace instead of /CS attribute.\n) pdfformaterror resolvecolorspace dup setgcolorspace csput //true % use currentcolorspace } { % inheriting the colorspace -- make sure Device* spaces are not CIEBased forceDefaultCS currentcolorspace 0 get .knownget { exec } if //false % no defined colorspace } ifelse } ifelse 3 -1 roll dup dup 4 1 roll /BBox get aload pop .begintransparencymaskgroup exch dup /Resources knownoget { oforce } { 2 dict } ifelse 3 -1 roll /GroupGState .knownget { 1 index /GroupGState 3 -1 roll put} if exch //false resolvestream 1 index exch %% Get the current colour space and colour values (as an array), we need to pass these to .execgroup %% as well, so that it can restore them, in case the colour space gets changed by transparency %% graphics state stuff. mark currentcolor counttomark array astore exch pop currentcolorspace 4 2 roll .execgroup % We have to remove these in case the Form XObject is subsequently used as % a form rather than a group - they remain in the paramdict for the SMask % so this will all still work if the SMask is re-evaluated. /GroupGState undef .endtransparencymask PDFfile exch setfileposition mark exch /OverrideICC exch .dicttomark setuserparams .swapcolors setcolorspace setcolor .swapcolors .setuseciecolor setcolorspace setcolor setmatrix end % restore colorspace, color and ExtGState (end) .currentSMask /Processed //true put % special setting to tell us it has been rendered } bind executeonly def % Paint a Form+Group XObject, either for a transparency mask or for a Do. /.execgroup { % [colour values] <colour space> <resdict> <stream> .execgroup - pdfemptycount 3 1 roll /pdfemptycount count 5 sub store gsave //nodict begin % We have to set the gstate correctly for lazy evaluation of a softmask group. % we also must restore the color(space) as setup in .execmaskgroup or paintformgroup. % This stuff must be done here, as .execmaskgroup can't use gsave/grestore to % manipulate the gstates, due to the requirements of .begintransparencymaskgroup. % We also must set the ExtGState values. % It may seem redundant to do the color(space) twice (once here and once in % .execmaskgroup) but we have to set it in .execmaskgroup for the background % color and set it here once in the correct gstate. 1 index /GroupGState .knownget { setgstate } if newpath //null SMask 1 CA 1 ca /Compatible .setblendmode % Execute the body of the Form, similar to DoForm. pdfopdict %% Restore the colour space (passed in on the stack) and current colour %% 6 -2 roll setcolorspace aload pop setcolor .pdfruncontext end grestore % check for extra garbage on the operand stack and clean it up count pdfemptycount sub dup 0 ne { ( **** Error: Transparency Group, Form XObject execution corrupted the stack.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror PDFSTOPONERROR { /.execgroup cvx /rangecheck signalerror } { dup 0 gt { { pop } repeat }{ pop } ifelse } ifelse } { pop } ifelse /pdfemptycount exch store } bind executeonly def /.beginformgroup { % groupdict bbox .beginformgroup - exch mark exch % bbox mark groupdict dup /CS knownoget { resolvecolorspace dup setgcolorspace /CS exch 3 2 roll} if dup /I knownoget { /Isolated exch 3 2 roll } if dup /K knownoget { /Knockout exch 3 2 roll } if pop .dicttomark % Stack: bbox paramdict exch aload pop .begintransparencygroup } bind executeonly def /.beginpagegroup { % groupdict bbox .beginformgroup - currentcolorspace 3 1 roll exch mark exch % bbox mark groupdict dup /CS knownoget { resolvecolorspace dup setgcolorspace /CS exch 3 2 roll} if dup /I knownoget { /Isolated exch 3 2 roll } if dup /K knownoget { /Knockout exch 3 2 roll } if pop .dicttomark % Stack: bbox paramdict exch aload pop .begintransparencypagegroup setcolorspace } bind executeonly def % .paintgroupform implements the Form PaintProc in the case where the % Form XObject dictionary includes a Group key. See .paintform below. /.paintgroupform { % <resdict> <stream> <formdict> .paintgroupform - %% Pass the current color space, and an array with the current color vales %% as arguments to .execgroup mark currentcolor counttomark array astore exch pop currentcolorspace 5 2 roll dup /Group oget dup type /dicttype eq { exch /BBox oget dup type /arraytype eq { % Stack: resdict stream groupdict bbox .beginformgroup .execgroup .endtransparencygroup }{ ( **** Error: Form XObject has a BBox entry with an invalid type.\n) pdfformaterror ( Ignoring transparency Group, output may be incorrect.\n) pdfformaterror pop pop pop pop pop pop } ifelse } { ( **** Error: Form XObject has a Group entry with an invalid type.\n) pdfformaterror ( Ignoring transparency Group, output may be incorrect.\n) pdfformaterror pop pop pop pop pop pop } ifelse } bind executeonly def % Make an ImageType 103 (soft-masked) image. /makesoftmaskimage { % <datasource> <imagemask> <SMask> makesoftmaskimage % <datasource> <imagemask>, updates currentdict = % imagedict % See the ImageType 3 case of makemaskimage below. % SMask is a stream, another Image XObject. % Stack: datasource imagemask(false) smaskstreamdict PDFfile fileposition exch dup /Matte knownoget { /Matte exch def } if dup length dict makeimagedict pop % In order to prevent the two data sources from being % aliased, we need to make at least one a reusable stream. % We pick the mask, since it's smaller (in case we need to % read all its data now). % Stack: datasource imagemask(false) savedpos % maskdict is currentdict /DataSource DataSource mark /Intent 1 /AsyncRead //true .dicttomark {.reusablestreamdecode} stopped {pop} if def PDFfile exch setfileposition currentdict end currentdict end 5 dict begin /ImageType 103 def /DataDict exch def dup /InterleaveType 3 put DataDict /Matte knownoget { /Matte exch def } if .currentalphaisshape { /ShapeMaskDict } { /OpacityMaskDict } ifelse exch def /ColorSpace DataDict /ColorSpace get def } bind executeonly def % ---------------- Color setting ---------------- % /01_1 [0 1] readonly def /01_3 [0 1 0 1 0 1] readonly def /01_4 [0 1 0 1 0 1 0 1] readonly def % The keys here are resolved (PostScript, not PDF) color space names. /csncompdict 9 dict begin /DeviceGray { pop 1 } bind executeonly def /DeviceRGB { pop 3 } bind executeonly def /DeviceCMYK { pop 4 } bind executeonly def /CIEBasedA //DeviceGray def /CIEBasedABC //DeviceRGB def /CalGray //DeviceGray def /CalRGB //DeviceRGB def /Lab //DeviceRGB def /ICCBased { 1 oget /N oget } bind executeonly def /Separation //DeviceGray def /DeviceN { 1 oget length } bind executeonly def /Indexed //DeviceGray def currentdict end readonly def % <colorspace> csncomp <n> /csncomp { dup dup type /arraytype eq { 0 oget } if //csncompdict exch get exec } bind executeonly def currentdict /csncompdict undef /ICCBased-resolve { PDFfile fileposition exch dup dup 1 oget mark exch { oforce } forall .dicttomark dup dup //true resolvestream { /ReusableStreamDecode filter } stopped { pop null % ( **** Error: Failed to read ICC profile for an ICCBased colour space.\n) pdfformaterror % ( Falling back to a colour space determined by the /N value.\n) pdfformaterror }if /DataSource exch put dup /.hash 0 put % placeholder for use by seticc icc_profile_cache key % Check that the number of components (/N) defined in the ICCBased % dictionry matches the actual profile. Bug #696120 dup /N get 1 index %% If we get an error reading the profile, just assume that /N is correct %% If its genuinely faulty we will use an alternate based on /N. {.numicc_components} stopped {pop dup} if dup 3 -1 roll ne { %% /N and the actual number of components don't match. Ensure %% that we have a valid number of components from the ICC %% profile. Certain kinds of profile can't determine the numebr of components %% and in ths case we must not override the /N value. dup 0 gt { ( **** Error: ICCbased space /N value does not match the ICC profile.\n) pdfformaterror ( Using the number of channels from the profile.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror 1 index dup /N get /OrigN exch put 1 index exch /N exch put }{ pop } ifelse } { pop } ifelse 1 exch put exch PDFfile exch setfileposition % Resolve alternate color space dup 1 get % Get colorspace dictionary dup /Alternate .knownget { % Check for alternate color space oforce resolvecolorspace /Alternate exch put % resolve and replace } { pop % remove colorspace dictionary } ifelse } bind executeonly def /csrdict 13 dict begin /DeviceGray { } bind executeonly def /DeviceRGB { } bind executeonly def /DeviceCMYK { } bind executeonly def /CalGray { 1 oget [ exch /CalGray exch ] } bind executeonly def /CalRGB { 1 oget [ exch /CalRGB exch ] } bind executeonly def /Lab { 1 oget [ exch /Lab exch ] } bind executeonly def /CalCMYK { pop /DeviceCMYK % not defined by Adobe } bind executeonly def /ICCBased { dup 1 get type /dicttype ne { % don't resolve more than once ICCBased-resolve } if } bind executeonly def /Separation { aload pop exch oforce resolvecolorspace % Contrary to PDF manuals up to v.1.5, Acrobat Distiller 3.01 % can use /Identity name here instead of a function. exch oforce resolveidfnproc %% Make sure the ink name is not an indirect object.... 3 -1 roll oforce 3 1 roll 4 array astore } bind executeonly def /DeviceN { [ exch aload pop ] % Copy into a new array dup dup 1 oget % Resolve Names array [ exch { oforce } forall ] % resolve each of the names 1 exch put dup dup 2 oget resolvecolorspace 2 exch put dup dup 3 oget resolvefnproc 3 exch put dup length 4 gt { % Check for attributes dict dup dup 4 oget % devn_array devn_array attr_dict dup /Colorants knownoget % Check for Colorants Dict { % Create a new attribute dict with only a Colorants dict entry. % Resolve all of the Colorant dict entries. This is needed % to prevent a conflict if we attempt to resolve the tint % transform functions of the Colorant color spaces multiple % times. exch pop % Remove old attributes dict << exch % Start new attributes dict % Build new Colorants dict with resolved entries << exch { oforce resolvecolorspace } forall >> /Colorants exch >> % Finish new attributes dict } if % devn_array devn_array <<..attributes..>> 1 index 4 oget /Process knownoget { dup /ColorSpace knownoget { 1 index exch resolvecolorspace /ColorSpace exch put } if % devn_array devn_array <<..attributes..>> <<..Process..>> 1 index /Process 3 -1 roll put } if 4 exch put % Put resolved or new attributes dict } if } bind executeonly def /Indexed { aload pop %% Resolve 'hival' in case it is an indirect reference. This is kind of %% dumb, it just makes the file bigger, but it *is* legal. 3 1 roll oforce 3 -1 roll 1 index -1 eq { exch pop 255 exch ( **** Error: Highest color index given as -1. Assuming this actually means 255.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror } if 3 -1 roll oforce resolvecolorspace % Stack: /Indexed hival lookup basespace % If the underlying space is a Lab space, we must scale % the output of the lookup table as part of DecodeABC. dup dup type /arraytype eq { 0 get } if /CIEBasedABC eq { dup 1 get /DecodeLMN known { 1 get dup length dict copy begin /DecodeABC [ 0 2 4 { RangeABC 1 index 1 add get RangeABC 2 index get sub /mul load RangeABC 3 index get /add load DecodeABC 6 -1 roll 2 idiv get [ 6 1 roll aload pop ] cvx } for ] def /RangeABC //01_3 def currentdict end /CIEBasedABC exch 2 array astore } if } if 3 1 roll % Stack: /Indexed csp comp table oforce dup type /stringtype ne { % The color lookup table is a stream. % Get its contents. Don't lose our place in PDFfile. % Stack: /Indexed basespace hival lookup PDFfile fileposition 5 1 roll dup /Filter oknown not { % For Bug691941.pdf and similar lossage dup /Length knownoget not { 0 } if } { 0 } ifelse % Stack: filepos /Indexed basespace hival lookup Length 2 index 1 add % Stack: filepos /Indexed basespace hival lookup Length len 4 index csncomp mul .max string % Stack: filepos /Indexed basespace hival lookup (...) exch //true resolvestream 1 index readstring not { % The string is padded with 0s ( **** Error: Short look-up table in the Indexed color space was padded with 0's.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror } if pop % Stack: filepos /Indexed basespace hival (...) PDFfile 6 -1 roll setfileposition } if 4 array astore % Stack: [filepos /Indexed basespace hival (...)] % Replace the PDFColorSpace with the Indexed space if needed. dup 1 get dup type /arraytype eq { dup length 2 ge { dup 1 get type /dicttype eq { dup 1 get /PDFColorSpace known { dup 1 get /PDFColorSpace 3 index put } if } if } if } if pop } bind executeonly def /I { % Bug 689815 ( **** Error: The name /Indexed cannot be abbreviated to /I in the color space\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror dup 0 /Indexed put //Indexed exec } bind executeonly def /Pattern { dup type /nametype ne { dup length 1 gt { 1 oget resolvecolorspace /Pattern exch 2 array astore } if } if } bind executeonly def currentdict end readonly def /cssubst { % <csname> cssubst <cspace'> true % <csname> cssubst false dup resolvecolorspace dup 1 index ne { exch pop //true } { pop pop //false } ifelse } bind executeonly def /csnames mark /DeviceGray dup /DeviceRGB dup /DeviceCMYK dup /Pattern dup .dicttomark readonly def /csresolve { % <csresourcename> csresolve <cspace> <true> | <false> dup type /nametype ne { (\n **** Error: CS/cs (setcolorspace) operand not a name: ) pdfformaterror dup stderrfile dup 3 -1 roll write==only flushfile ( ****\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror dup type /arraytype eq { % Adobe InDesign + PDF Library has array resolvecolorspace } if //true } { dup Page /ColorSpace rget { exch pop resolvecolorspace //true } { //csnames 1 index known { //true } { ( **** Error: Undefined space resource: /) exch .namestring concatstrings (\n) concatstrings pdfformaterror ( Output may be incorrect.\n) pdfformaterror //false } ifelse } ifelse } ifelse } bind executeonly def /resolvecolorspace { % <cspace> resolvecolorspace <cspace'> dup type /dicttype eq { dup /N known { ( **** ICCBased color space is a bare stream dictionary\n) pdfformatwarning [ /ICCBased 3 -1 roll ] ICCBased-resolve exec //false } { dup /ColorSpace knownoget { ( **** Error: unrecognised color space <</ColorSpace /Device...>>\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror exch pop //true } { //true } ifelse } ifelse } { //true } ifelse { dup dup type /arraytype eq { 0 get } if dup type /packedarraytype eq {exch pop exec dup} if //csrdict exch .knownget { exec dup type /nametype ne { dup length 1 eq { 0 get } if } if } { dup type /nametype eq { csresolve not { /DeviceRGB } if % Arbitrary } { csset exch pop } ifelse } ifelse } if } bind executeonly def /scresolve { % <c0> ... scresolve <multi> % We can't really make sc[n] and SC[N] work, because % the color space information isn't available at % conversion time; so we hack it by assuming that % all the operands on the stack are used, and that % if the top operand is a name, it's a Pattern resource. dup type /nametype eq { Page /Pattern rget { resolvepattern } { //null } ifelse } if dup type /dicttype eq { % Check the PaintType, if any (shading patterns don't % have one). dup /PaintType knownoget { 2 eq } { //false } ifelse } { .pdfcount 1 gt } ifelse } bind executeonly def %% Bug #696017 When we begin a text block, we switch to a special set of marking operations %% for paths, these ops don't use the current CTM, but the 'SavedTextMatrix', in order to %% correctly position marks which are illegally present inside a text block. But, if we are %% executing a PaintProc (eg for a pattern) we *don't* want to do that or the pattern will be wrong. %% So we moved the .pdfpaintproc to .actual_pdfpaintproc, and redefined .pdfpaintproc to test %% the current value of /m. We always switch to the regular marking operations, but if the definition %% of /m at the start of the PaintProc was a special text version, then we switch back to that after we %% finished running the PaintProc. /.actual_pdfpaintproc { % <patdict> <resdict> .pdfpaintproc - PDFDEBUG { //pdfdict /PDFSTEPcount .knownget { 1 le } { //true } ifelse { (%Begin PaintProc) print dup === flush } if } if PDFfile fileposition 3 1 roll q 1 index /PaintType oget 1 eq { % For colored patterns, set default fill and stroke colors. 0 g 0 G } { % For uncolored patterns, we have to unbind the current % color and color space before running the PaintProc. % Not true since moving the ExtGState parameters into the gstate. % //null sc1 //null SC1 } ifelse % Save old values on opstack, set pdfemptycount to new value. pdfemptycount countdictstack mark %% We can't simply 'def' into the dictionary saved by 'q' above, we need to %% call gput to copy it and store inside it. Stupid or what.... /pdfemptycount count 3 sub gput 5 3 roll % % Stack: ... <old emptycount> <dictcount> mark <patdict> <resdict> % | % New empty count points here -----------+ exch //false resolvestream pdfopdict .pdfruncontext cleartomark //false { countdictstack 2 index le { exit } if currentdict /n known not or currentdict /n known currentdict /self known or{ Q }{ (\n **** Error: File has unbalanced q/Q operators \(too many Q's\)\n Output may be incorrect.\n) //pdfdict /.Qqwarning_issued .knownget { { pop } { currentglobal //pdfdict gcheck .setglobal //pdfdict /.Qqwarning_issued //true .forceput .setglobal pdfformaterror } executeonly ifelse } executeonly { currentglobal //pdfdict gcheck .setglobal //pdfdict /.Qqwarning_issued //true .forceput .setglobal pdfformaterror } executeonly ifelse end } executeonly ifelse } executeonly loop { (\n **** Error: File has unbalanced q/Q operators \(too many q's\)\n Output may be incorrect.\n) //pdfdict /.Qqwarning_issued .knownget { { pop } { currentglobal //pdfdict gcheck .setglobal //pdfdict /.Qqwarning_issued //true .forceput .setglobal pdfformaterror } executeonly ifelse } executeonly { currentglobal //pdfdict gcheck .setglobal //pdfdict /.Qqwarning_issued //true .forceput .setglobal pdfformaterror } executeonly ifelse } executeonly if pop % restore pdfemptycount /pdfemptycount exch def Q PDFDEBUG { //pdfdict /PDFSTEPcount .knownget { 1 le } { //true } ifelse { (%End PaintProc) print dup === flush } if } if PDFfile exch setfileposition } bind executeonly odef /.pdfpaintproc { %% Get the /m from pdfopdict (must be present) %% and check its a packedarray pdfopdict /m get dup type /packedarraytype eq { %% The non-text version of /m is executeonly, so if we can't read it, its not a text block. dup rcheck { %% get the initial element of the packedarray %% and check its a name 0 get dup type /nametype eq { %% If the name is inside_text_m then we are in a text block /inside_text_m eq }{ pop //false } ifelse }{ pop //false } ifelse }{ pop //false } ifelse %% rearrange the operands, move the boolean to the back 3 1 roll %% Uncopnditionally use the normal marking ops switch_to_normal_marking_ops .actual_pdfpaintproc %% If we were in a text block, restore the text marking ops. { switch_to_text_marking_ops } if }bind executeonly odef /resolvepattern { % <patternstreamdict> resolvepattern <patterndict> % Don't do the resolvestream now: just capture the data % from the file if necessary. dup length dict copy dup /FilePosition .knownget { 1 index /File get dup fileposition 3 1 roll % Stack: dict savepos pos file dup 3 -1 roll setfileposition dup 3 index /Length knownoget { dup 65535 le { dup 0 eq { pop pop () } { string readstring pop } ifelse } { () /SubFileDecode filter /ReusableStreamDecode filter } ifelse } { 0 (endstream) /SubFileDecode filter /ReusableStreamDecode filter } ifelse % Stack: dict savepos file string 3 1 roll exch setfileposition 1 index /File 3 -1 roll put dup /FilePosition undef } if dup /Shading knownoget { resolveshading 1 index /Shading 3 -1 roll put } if dup /PaintProc [ % Bind the resource dictionary into the PaintProc. 2 index /Resources knownoget { oforce } { 0 dict } ifelse /.pdfpaintproc cvx ] cvx put dup /BBox 2 copy knownoget { normrect FixPatternBBox put } { pop pop } ifelse dup /.pattern_uses_transparency 1 index patternusestransparency put PDFDEBUG { //pdfdict /PDFSTEPcount .knownget { 1 le } { //true } ifelse { (%Pattern: ) print dup === flush } if } if } bind executeonly def /ignore_color_op ( **** Error: Ignoring a color operation in a cached context.\n Output may be incorrect.\n) readonly def drawopdict begin /g { .incachedevice { % Bug 689302 pop //ignore_color_op pdfformaterror } { /DeviceGray cssubst { cs sc1 } { g } ifelse } ifelse } bind executeonly def /rg { .incachedevice { pop pop pop //ignore_color_op pdfformaterror } { /DeviceRGB cssubst { cs sc* } { rg } ifelse } ifelse } bind executeonly def /k { .incachedevice { pop pop pop pop //ignore_color_op pdfformaterror } { k } ifelse } bind executeonly def /cs { .incachedevice { pop //ignore_color_op pdfformaterror } { csresolve { cs } if } ifelse } bind executeonly def /sc { .incachedevice { .pdfcount { pop } repeat //ignore_color_op pdfformaterror } { scresolve 1 index //null eq { pop pop //ignore_color_op pdfformaterror } { { sc*_and_set } { sc1_and_set } ifelse } ifelse } ifelse } bind executeonly def /scn /sc load def /G { .incachedevice { pop //ignore_color_op pdfformaterror } { /DeviceGray cssubst { CS SC1 } { G } ifelse } ifelse } bind executeonly def /RG { .incachedevice { pop pop pop //ignore_color_op pdfformaterror } { /DeviceRGB cssubst { CS SC* } { RG } ifelse } ifelse } bind executeonly def /K { .incachedevice { pop pop pop pop //ignore_color_op pdfformaterror } { K } ifelse } bind executeonly def /CS { .incachedevice { pop //ignore_color_op pdfformaterror } { csresolve { CS } if } ifelse } bind executeonly def /ri { .incachedevice { pop //ignore_color_op pdfformaterror } { ri } ifelse } bind executeonly def /SC { .incachedevice { .pdfcount { pop } repeat //ignore_color_op pdfformaterror } { scresolve 1 index //null eq { pop pop //ignore_color_op pdfformaterror }{ { SC*_and_set } { SC1_and_set } ifelse }ifelse } ifelse } bind executeonly def /SCN /SC load def end currentdict /ignore_color_op undef % ---------------- Paths ---------------- % drawopdict begin % Path construction /m { { moveto } stopped { count pdfemptycount sub 2 .min { pop } repeat 0 0 moveto } if } bind executeonly def /l { { lineto } stopped { count pdfemptycount sub 2 .min { pop } repeat } if } bind executeonly def /c { { curveto } stopped { count pdfemptycount sub 6 .min { pop } repeat } if } bind executeonly def /v { count pdfemptycount sub 4 ge { { currentpoint 6 2 roll curveto } stopped { count pdfemptycount sub 6 .min { pop } repeat } if } { count pdfemptycount sub { pop } repeat } ifelse } bind executeonly def /y { { 2 copy curveto } stopped { count pdfemptycount sub 6 .min { pop } repeat } if } bind executeonly def /re { 4 2 roll moveto exch dup 0 rlineto 0 3 -1 roll rlineto neg 0 rlineto closepath } bind executeonly def /h { closepath } bind 0 get def % Path painting and clipping /n { n } executeonly def /S { S } executeonly def /s { s } executeonly def /f { f } executeonly def /f* { f* } executeonly def /B { B } executeonly def /b { b } executeonly def /B* { B* } executeonly def /b* { b* } executeonly def /W { W } executeonly def /W* { W* } executeonly def /sh_save 1 array def /do_shade { 0 .setoverprintmode { dup /.shading .knownget { exch pop } { .buildshading_and_shfill } ifelse } stopped { pop ( **** Error: Ignoring invalid smooth shading object, output may be incorrect.\n) pdfformaterror } if } bind executeonly def /sh { OFFlevels length 0 eq { setsmaskstate resolvesh //sh_save 0 save put PDFusingtransparency { gsave dup /BBox knownoget { { oforce } forall 4 2 roll moveto exch 0 lineto 0 exch lineto closepath } { clippath } ifelse % If we get an error, just emit an empty box { pathbbox } stopped { 0 0 0 0 } if 4 array astore grestore //null setup_trans //do_shade exec teardown_trans } { //do_shade exec } ifelse //sh_save 0 get restore } { pop } ifelse } bind executeonly def currentdict dup /sh_save undef /sh_group undef end % ---------------- XObjects ---------------- % /xobjectprocs mark % <dict> -proc- - /Image { DoImage } executeonly /Form { DoForm } executeonly /PS { DoPS } executeonly .dicttomark readonly def % Note that the keys in defaultdecodedict are resolved (PostScript, not PDF) % color space names. /defaultdecodedict mark /DeviceGray { pop //01_1 } bind executeonly /DeviceRGB { pop //01_3 } bind executeonly /DeviceCMYK { pop //01_4 } bind executeonly /CIEBasedA { 1 get /RangeA knownoget not { //01_1 } if } bind executeonly /CIEBasedABC { 1 get /RangeABC knownoget not { //01_3 } if } bind executeonly /CalGray { pop //01_1 } bind executeonly /CalRGB { pop //01_3 } bind executeonly /Lab { 1 get /Range knownoget not { [-100 100 -100 100] } {aload pop 0 100 6 2 roll 6 array astore}ifelse } bind executeonly /ICCBased { 1 oget dup /Range knownoget { exch pop }{ /N get [ exch {0 1} repeat ] readonly } ifelse } bind executeonly /Separation { pop //01_1 } bind executeonly /DeviceN { 1 oget length [ exch {0 1} repeat ] readonly } bind executeonly /Indexed { pop [ 0 1 BitsPerComponent bitshift 1 sub ] } bind executeonly .dicttomark readonly def /checkaltimage { % <resdict> checkaltimage <resdict[']> Printed { dup /Alternates knownoget { { dup /DefaultForPrinting knownoget { { /Image oget exch pop exit } { pop } ifelse } { pop } ifelse } forall } if } if } bind executeonly def % <string> <index> getu16 <integer> /getu16 { 2 copy get 8 bitshift 3 1 roll 1 add get add } bind executeonly def % <string> <index> getu32 <integer> /getu32 { 2 copy getu16 16 bitshift 3 1 roll 2 add getu16 add } bind executeonly def /jp2_csp_dict mark 12 { /DeviceCMYK } % CMYK 14 { [ /Lab << /WhitePoint [ 0.9505 1 1.0890 ] readonly >> ] } % LAB, WhitePoint == D65 16 { /sRGBICC /ColorSpace findresource } bind executeonly 17 { /sGrayICC /ColorSpace findresource } bind executeonly 18 3 index % YCC is converted to RGB % 19 % CIEJab not supportec by PDF 1.7 20 { /esRGBICC /ColorSpace findresource } bind executeonly % e-sRGB 21 { /rommRGBICC /ColorSpace findresource} bind executeonly % ROMMRGB 24 { /esRGBICC /ColorSpace findresource } bind executeonly % e-sYCC .dicttomark readonly def % Process jp2 blocks (aka boxes). All procedures have the signature % <file> <length> -> ... <file> <flush_length> /jp2_tag_dict 10 dict begin /jp2h { % descend into a sub-stream, don't return. () /SubFileDecode filter 0 } bind executeonly def /ihdr { 14 sub % file len-14 1 index (1234567890abcd) readstring pop % file len-14 (14) /JPXComponents 1 index 8 getu16 % file len-14 (14) /JPXComponents NC def % file len-14 (14) 10 get %% If the BPC is 255 then each component has variable depth %% we can't handle this, but JasPer is known to produce %% images whcih declare this, but are actually all equal, we cater %% for that in the bpcc box below. dup 16#FF eq not { 16#7F and 1 add dup 12 eq { pop 16 } if /BitsPerComponent exch def % file len-14 } {pop} ifelse } bind executeonly def %% if the ihdr has a BPC of 255 then we get a bpcc box which %% gives the bpc for each component individually. We cannot %% actually deal with differing component depths, but it %% seems JasPer produces images with this box where all the %% component depths are in fact the same. /bpcc { JPXComponents sub 1 index JPXComponents string readstring pop dup 0 get /BitsPerComponent exch def 1 1 JPXComponents 1 sub { 1 index exch get BitsPerComponent eq not { ( **** Error: JPX image colour channels do not all have the same colour depth\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror } if } for pop /BitsPerComponent BitsPerComponent 1 add def } bind executeonly def /colr { currentdict /ColorSpace known not { 3 sub 1 index (123) readstring pop % file len-3 (3) 0 get dup 1 eq { pop 4 sub % file len-7 1 index (1234) readstring pop % file len-16 (4) 0 getu32 % file len-16 enum //jp2_csp_dict exch .knownget { exec /ColorSpace exch def % file len-7 } { ( **** Error: Unknown enumerated color space in JPX stream.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror } ifelse } { dup 2 eq exch 3 eq or { 1 index exch () /SubFileDecode filter /ReusableStreamDecode filter /JPXICC exch def 0 % file 0 } { ( **** Error: Unknown color space method in JPX stream.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror } ifelse } ifelse } if } bind executeonly def % Palette colors are decoded by the library. /pclr { 4 sub 1 index (1234) readstring pop 3 get 16#7F and 1 add /BitsPerComponent exch def } bind executeonly def /cdef { pop dup (12) readstring pop 0 getu16 { dup (123456) readstring pop 2 getu16 dup 3 lt { { /JPXColors /JPXOpacity /JPXPremult } exch get currentdict 1 index .knownget { 1 add } { 1 } ifelse def } { pop } ifelse } repeat 0 } bind executeonly def currentdict end readonly def % Parse jp2 file format to get color space and image depth info. % <file> get_jp2_csp - /get_jp2_csp { { dup (01234567) readstring pop % f (LBoxTBox) dup length 8 lt { pop exit } if dup 4 4 getinterval exch % f (TBox) (LBoxTBox) 0 getu32 % f (TBox) LBox dup 0 eq { pop pop exit % cannot happen } { dup 1 eq { pop 1 index (01234567) readstring pop 4 getu32 % f (TBox) LBox 16 sub } { 8 sub } ifelse } ifelse % f (TBox) LBox-8..16 PDFDEBUG { 2 copy 2 packedarray //== exec % f (TBox) LBox-8..16 } if //jp2_tag_dict 3 -1 roll .knownget { exec } if % f flush dup 0 ne { 1 index exch % f f flush () /SubFileDecode filter flushfile % skip unwanted blocks } { pop } ifelse } loop pop } bind executeonly def currentdict /jp2_tag_dict .undef currentdict /jp2_csp_dict .undef % Add a key-value pair to the last /DecodeParms dictionary % Copy the objects to avoid spoiling shared ones. % <resdict> <key> <value> -> <resdict> /add-to-last-param { 2 index /DecodeParms knownoget { dup type /dicttype ne 1 index type /arrratype ne and 1 index length 1 lt or { pop //false } { //true } ifelse } { //false } ifelse { dup type /arraytype eq { [ exch { oforce } forall dup //null eq { pop 1 dict } if ] dup dup length 1 sub get % <resdict> <key> <value> [] <<>> } { dup length 1 add dict copy dup % <resdict> <key> <value> <<>> <<>> } ifelse 4 2 roll put % <resdict> obj } { % <resdict> <key> <value> mark 3 1 roll .dicttomark % <resdict> obj 1 index /Filter knownoget { dup type /arraytype eq { length array % <resdict> obj [...] dup dup length 1 sub % <resdict> obj [...] [...] len-1 4 -1 roll put % <resdict> [... obj] } { pop } ifelse } if } ifelse 1 index exch /DecodeParms exch put % <resdict> } bind executeonly def % Add a key-value pair to the all the /DecodeParms % dictionaries (i.e. handle the array) % Copy the objects to avoid spoiling shared ones. % <resdict> <patch dict> -> <resdict> /add-to-all-params { 1 index % <resdict> <patch dict> <resdict> /Filter knownoget { % <resdict> <patch dict> </name or [array]> dup type /arraytype eq { length % <resdict> <patch dict> <len> dup 0 gt { 2 index /DecodeParms knownoget { oforce_recursive % resolve indirect references exch pop % <resdict> <patch dict> [array] [ exch { dup type /dicttype eq { mark exch {} forall .dicttomark } { pop 1 dict } ifelse } forall ] % <resdict> <patch dict> [array] } { % <resdict> <patch dict> <len> % create an array of dictionaries [ 0 1 4 -1 roll 1 sub { pop 1 dict } for ] % <resdict> <patch dict> [array] } ifelse dup % <resdict> <patch dict> [array] [array] { % <resdict> <patch dict> [array] [dict] 2 index % <resdict> <patch dict> [array] [dict] <patch dict> { % <resdict> <patch dict> [array] [dict] </key> <value> 2 index % <resdict> <patch dict> [array] [dict] </key> <value> [dict] 3 1 roll put } forall pop } forall % <resdict> <patch dict> [array] exch pop % <resdict> [dict/array] 1 index exch /DecodeParms exch put } { pop pop } ifelse } { % <resdict> <patch dict> </name> pop 1 index /DecodeParms knownoget { oforce_recursive dup type /dicttype eq { mark exch {} forall .dicttomark } { pop 1 dict } ifelse } { 1 dict } ifelse % <resdict> <patch dict> [dict] 1 index % <resdict> <patch dict> [dict] <patch dict> { % <resdict> <patch dict> [dict] </key> <value> 2 index 3 1 roll put } forall exch pop % <resdict> [dict/array] 1 index exch /DecodeParms exch put } ifelse } {pop} ifelse } bind def /last-ditch-bpc-csp { currentdict /BitsPerComponent oknown not { ( **** Error: image has no /BitsPerComponent key; assuming 8 bit.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror /BitsPerComponent 8 def } if currentdict /ColorSpace knownoget not { dup /ColorSpace knownoget not { ( **** Error: image has no /ColorSpace key; assuming /DeviceRGB.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror /DeviceRGB } if } if resolvecolorspace %% This section is to deal with the horrible pair of files in Bug #696690 and Bug #696120 %% These files have ICCBased spaces where the value of /N and the number of components %% in the profile differ. In addition the profile in Bug #696690 is invalid. In the %% case of Bug #696690 the /N value is correct, and the profile is wrong, in the case %% of Bug #696120 the /N value is incorrect and the profile is correct. %% We 'suspect' that Acrobat uses the fact that Bug #696120 is a pure image to detect %% that the /N is incorrect, we can't be sure whether it uses the profile or just uses %% the /N to decide on a device space. What we now do is; If the /N and device profile %% number of components don't match, we assume the device profile is correct and patch %% /N to be the same as the profile (see /ICCBased-resolve), but we save the original %% value of /N in /OrigN. In setcolor, if the space is a genuine ICCBased space %% (not a replacement for a device profile) we call set_dev_color which will actually %% exercise the profile. If that fails we return an error. Here we run setcolor in a %% stopped context, and if it fails we check to see if there is a /OrigN (ths occurs %% only if the /N was different to the number of components in the profile). If there %% is a /OrigN then prefer that to the profile, otherwise they agreed, so just use %% /N and select a device space. If we can't select a device space with the correct %% number of components, give up and throw an error. See also 'Cdict' in pdf_ops.ps. dup type /arraytype eq { dup 0 get /ICCBased eq { gsave dup setcolorspace dup 1 get /N get 1 sub mark exch 0 1 3 -1 roll {pop 0} for {setcolor} stopped grestore { cleartomark 1 get dup /OrigN .knownget {exch pop}{/N get} ifelse [//null /DeviceGray //null /DeviceRGB /DeviceCMYK] exch {get} stopped { ( **** Error: Unable to set an ICCBased colour space, and cannot set an alternate from the number of components.\n) print /setcolorspace cvx /undefined signalerror } { dup //null eq { ( **** Error: Unable to set an ICCBased colour space, and cannot set an alternate from the number of components.\n) print /setcolorspace cvx /undefined signalerror }{ ICCProfileNError not { ( **** Warning : Error setting an ICCBased colour space, using /N to set an alternate device space.\n) print ( Output may be incorrect.\n) print } if } ifelse }ifelse /ICCProfileNError //true def }{cleartomark}ifelse } if } if /ColorSpace exch def } bind executeonly def /get-smask-in-data { % <dict> -> <int> /SMaskInData knownoget { dup dup 1 ne exch 2 ne and { pop 0 } if } { 0 } ifelse } bind executeonly def /makeimagedict { % <resdict> <newdict> makeimagedict <imagemask?> % On return, newdict' is currentdict begin /Width 2 copy oget def /Height 2 copy oget def % Handle missing BitsPerComponent later. /BitsPerComponent 2 copy knownoget { cvi def } { pop } ifelse /Interpolate 2 copy knownoget { def } { pop } ifelse makeimagekeys } bind executeonly def /makeimagekeys { % <resdict> makeimagekeys <imagemask> % newdict is currentdict % Assumes Width, Height, BPC, Interpolate already copied. /ImageType 1 def /ImageMatrix Width 0 0 % Handle 0-height images specially. Height dup 0 eq { pop 1 } if neg 0 1 index neg 6 array astore def %% If the image has a rendering intent, get its numeric equivalent %% from renderingintentdict, and save it in the dictionary we pass %% on to render images. dup /Intent knownoget { //.renderingintentdict exch .knownget { /Intent exch def } if } if dup /ImageMask knownoget dup { and } if { % Image mask % Decode is required for the PostScript image operators. % AI8 writes bogus decode array [0 1 0 0 0 0 0 0] /Decode 2 copy knownoget { 0 2 getinterval } { //01_1 } ifelse def % BitsPerComponent is optional for masks. /BitsPerComponent 2 copy known { pop } { 1 def } ifelse % Even though we're going to read data, % pass false to resolvestream so that % it doesn't try to use Length (which may not be present). % Bug 701083: We add a /ErrsAsEOD key to the DecodeParms here too. <</ErrsAsEOD //true>> //add-to-all-params exec //false resolvestream /DataSource exch def //true } { % Opaque image dup /Filter knownoget { dup type /arraytype eq { dup length dup 0 gt { 1 sub get oforce } { pop } ifelse } if /JPXDecode eq } { //false } ifelse { % /JPXDecode tricks % Previously we only ran the code to extract the Color Space and Bits Per Component % from the JOX stream if the image dict had either BPC or ColorSpace undefined. % However, while this is correct for the ColorSpace, its *not* correct for the BPC. % According to the spec we should ignore any BPC in the image dicitonary and % always use the BPC from the JPX stream. % Now the code in get_jp2_csp always overwrites the ColorSpace (in the image resource dict) % which technically is fine, because the image dictionary entry must be either not present or the % same as the JPX stream. However, this doesn't work, so instead we just save the existing % color space (if any). Then after extracting the color space and BPC from the JPX stream % we put back the saved color space, but only if there was one previously. dup /ColorSpace oknown { dup dup /ColorSpace get /ImageDictColorSpace exch put } if dup /IDFlag known { ( **** Warning: PDF spec bans inline JPX images.\n) pdfformatwarning % Inline stream is not positionable. Cannot get ColorSpace. } { % Drop the last filter (JPXDecode) from the pipeline dup dup length dict copy dup /Filter oget dup type /arraytype eq { dup length 1 gt { dup length 1 sub 0 exch getinterval 1 index exch /Filter exch put dup /DecodeParms knownoget { dup type /arraytype eq { dup length 1 gt { dup length 1 sub 0 exch getinterval 1 index exch /DecodeParms exch put } { pop dup /DecodeParms undef } ifelse } { pop dup /DecodeParms undef } ifelse } if } { pop dup /Filter undef dup /DecodeParms undef } ifelse } { pop dup /Filter undef dup /DecodeParms undef } ifelse //false resolvestream get_jp2_csp currentdict /ColorSpace oknown not { currentdict /JPXICC .knownget { [ /ICCBased mark /DataSource 5 -1 roll /N currentdict /JPXColors .knownget not { currentdict /JPXComponents get } if .dicttomark ] /ColorSpace exch def } if } if { /JPXICC /JPXColors /JPXComponents /JPXOpacity /JPXPremult } { currentdict exch undef } forall } ifelse % If we had a Color Space in the image dictionary before we read the JPX % stream, put it back now. We mujst do this before last-ditch-bpc-csp % because that resolves any indirect references to the color space. dup /ImageDictColorSpace known { dup /ImageDictColorSpace get currentdict /ColorSpace 3 -1 roll put } if //last-ditch-bpc-csp exec dup /ColorSpace oknown { % Propagate known color space to the filter /ColorSpace currentdict /ColorSpace get //add-to-last-param exec } if /Decode 2 copy knownoget not { ColorSpace //defaultdecodedict ColorSpace dup type /arraytype eq { 0 get } if get exec } if def dup get-smask-in-data dup 0 ne { PDFusingtransparency { currentdict dup length dict copy begin {/Mask/SMask/SMaskInData/Name} { currentdict exch undef } forall 2 eq { /Matte [ Decode length 2 idiv { 0 } repeat ] def } if /Decode //01_1 def /ColorSpace /DeviceGray def {/File /FilePosition /Filter /Length /DecodeParms /FFilter /FDecodeParms } { 2 copy knownoget { def } { pop } ifelse } forall currentdict /Alpha //true //add-to-last-param exec pop /SMask currentdict end def } { pop } ifelse } { pop } ifelse } { % not JPX image //last-ditch-bpc-csp exec /Decode 2 copy knownoget not { ColorSpace //defaultdecodedict ColorSpace dup type /arraytype eq { 0 get } if get exec } if def } ifelse % fi JPX tricks % Add a /Height key containing the image height to the DecodeParms % for any Filters we will apply. If there are no DecodeParms for any % filter, create one and add a /Height key. This is to solve the problem % in Bug #695116 where a JPEG image has a bad height, which is later % fixed up using a DNL marker. By placing the image height from the % PDF in the DecodeParms we can use it in the DCTDecode filter to % work around this. % Bug 701083: We add a /ErrsAsEOD key to the DecodeParms here too. << /Height 2 index /Height oget round cvi /ErrsAsEOD //true >> //add-to-all-params exec % Even though we're going to read data, % pass false to resolvestream so that % it doesn't try to use Length (which may not be present). //false resolvestream /DataSource exch def //false } ifelse } bind executeonly def currentdict /add-to-last-param undef currentdict /add-to-all-params undef currentdict /last-ditch-bpc-csp undef /DoImage { %% Bug #696439. This is incredibly icky. When we find indirect obects we resolve them %% and store the resolved object in the containing object. This means that we retain %% the image dicionary here until the end of job. Potentially wasteful. Even worse though %% is the case where the image has a ColorSpace which is not an indirect object, but *is* %% an ICCBased colour space. In ths case we end up resolving the colour space and storing it %% here. Unfortunately, we use a ReusableStreamDecode filter on the ICC profile, which means %% we end up retaining the memory for that too. ICC profiles can be large, and if there are a %% lot of places where they get used, we can exhaust memory. %% Here we check if the ColorSpace is an array object, if it is we *copy* the image dictionary %% and use the copy instead. The copy is (eventually) discarded so we don't retain the ICC profile %% and don't exhaust memory. Note that we have to copy the actual colour space array too, copying %% the dictionary just copies the opriginal array as well. %% 1 dict begin /.ImageDictStackDepth countdictstack def /.ImageOpStackDepth count 2 sub def { dup /ColorSpace known { dup /ColorSpace get dup type /arraytype eq { exch dup length dict copy exch dup length array copy /ColorSpace exch 2 index 3 1 roll put } {pop} ifelse } if checkaltimage dup length 6 add dict % <<image>> <<>> 1 index /SMask knownoget { % <<image>> <<>> <<sm>> dup 3 index ne { % <<image>> <<>> <<sm>> <<sm>> 1 index exch /SMask exch put } { pop ( **** Error: ignoring recursive /SMask attribute.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror } ifelse } if 1 index /Mask knownoget { dup type dup /dicttype eq exch /arraytype eq or { % Bug #703681 1 index exch /Mask exch put } { pop ( **** Error: Ignoring Mask attribute that is not an array or a dictionary.\n) pdfformaterror } ifelse } if makeimagedict doimagesmask } PDFSTOPONERROR {exec false}{stopped} ifelse { (\n **** Error: File encountered ') $error /errorname get dup length string cvs concatstrings (' error while processing an image.\n) concatstrings ( Output may be incorrect.\n) concatstrings pdfformaterror } if count .ImageOpStackDepth sub {pop} repeat countdictstack .ImageDictStackDepth sub {end} repeat end } bind executeonly def /makemaskimage { % <datasource> <imagemask> <Mask> makemaskimage % <datasource> <imagemask>, updates currentdict = % imagedict dup type /arraytype eq { /ImageType 4 def % Check that every element of the Mask is an integer. //false 1 index { type /integertype ne or } forall { oforce_array //false 1 index { type /integertype ne or } forall { (\n **** Error: Some elements of Mask array are not integers.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror [ exch { 0.5 add cvi } forall ] % following AR4, 5, 6 implementation } if } if % Check elements of array are within 0::(2**BitsPerComponent)-1 % This is a PostScript error, but AR tries to fix the Mask. 1 BitsPerComponent bitshift 1 sub //false 2 index { % stack: max_value result_bool value dup 0 lt exch 3 index gt or or } forall exch pop { ( **** Error: Some elements of Mask array are out of range.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror ColorSpace dup type /arraytype eq { 0 oget } if /Indexed eq BitsPerComponent 1 eq and { % AR9 treats Indexed 1 bpc images specially. Bug 692852 see also 697919 and 689717. dup 0 oget dup 0 lt exch 1 BitsPerComponent bitshift ge or { % First component is invalid - AR9 ignores the mask pop //null } { % Second component is invalid; AR9 replaces it with 1. [ exch 0 oget 1 ] } ifelse } { BitsPerComponent 1 eq { dup length 2 gt { % There are too many Mask entries, discard the Mask array pop //null }{ % Bug 701468 and 689717, the latter requires us to set the Mask values % so that the value is calculated from the BPC, the other requires us % to ignore the Mask. The only difference between the two files is the % actual range of the Mask values. This may yet need more work. % Note! Both files are technically invalid.... aload 3 1 roll eq { % There's only one Mask value, but its illegal, substitute with the % calculated maximum. [ exch { 1 BitsPerComponent bitshift 1 sub and } forall ] } { % The Mask values are not the same. This is a 2 colour image, if % we mask off any range then the result will be blank, so ignore the Mask pop //null } ifelse } ifelse } { % We think AR5, AR9 do this for most other cases. Originally Bug 690786, % but that is actually handled in the /Indexed case above. [ exch { 1 BitsPerComponent bitshift 1 sub and } forall ] } ifelse } ifelse } if dup //null ne { /MaskColor exch def } { pop /ImageType 1 def } ifelse } { % Mask is a stream, another Image XObject. % Stack: datasource imagemask(false) maskstreamdict PDFfile fileposition exch dup length dict makeimagedict pop % In order to prevent the two data sources from being % aliased, we need to make at least one a reusable stream. % We pick the mask, since it's smaller (in case we need to % read all its data now). % Stack: datasource imagemask(false) savedpos % maskdict is currentdict /DataSource DataSource mark /Intent 1 /AsyncRead //true .dicttomark {.reusablestreamdecode} stopped {pop} if def PDFfile exch setfileposition currentdict end currentdict end 5 dict begin /ImageType 3 def /InterleaveType 3 def /DataDict exch def /MaskDict exch def /ColorSpace DataDict /ColorSpace get def } ifelse } bind executeonly def /doimagesmask { % <imagemask> doimagesmask - PDFusingtransparency not /PreserveSMask /GetDeviceParam .special_op { exch pop } { //false } ifelse or { % not using transparency OR the device supports SMask (e.g. pdfwrite) doimage } { currentdict /SMask knownoget { % We are doing transparency and SMask is present in the image % stack: <imagemask> <SMask> % Normalize /Matte attribute for .begintransparencymaskimage dup /Matte .knownget { oforce dup //null eq { pop dup /Matte undef } { 1 index /Matte [ 4 -1 roll { oforce } forall ] put } ifelse } if .begintransparencymaskimage PDFfile fileposition exch gsave //nodict begin //null .setSMask 1 CA 1 ca /Compatible .setblendmode DoImage end grestore PDFfile exch setfileposition 0 .endtransparencymask << /Subtype /Group /Isolated //true /.image_with_SMask //true % pdfwrite needs : see gs/src/ztrans.c, gs/src/gdevpdft.c % Code to deal with a Matte in the SMask. We know the image dictionary must have an SMask % entry if we get here, so we don't need to check its existence. Just pull it out and see if % the SMask has a Matte entry. If it does, get the ColorSpace from the parent image and % put a /CS key with that colour space in the Group that we manufacture. Bug #700686 % We also need to actually set the current colour space to be the same as the group % code only picks up the current colour space, not the space from the dictionary. currentdict /SMask get /Matte known {/CS currentdict /ColorSpace get dup pdfopdict /cs get exec } if >> 0 0 1 1 gsave 1 1 moveto 0 0 lineto % If we get an error, just emit an empty box { pathbbox } stopped { 0 0 0 0 } if 4 array astore grestore /image setup_trans .begintransparencygroup .currentstrokeconstantalpha .currentfillconstantalpha 3 -1 roll 1 .setfillconstantalpha 1 .setstrokeconstantalpha doimage .setfillconstantalpha .setstrokeconstantalpha .endtransparencygroup % tell the compositor we're done with the SMask. % Note that any SMask in the ExtGState should be reapplied % by the next call to setfill(stroke)state AND this relies % on our lazy evaulation of SMask groups //false << /Subtype /None >> 0 0 0 0 .begintransparencymaskgroup } { % We don't have an SMask in the image but there might be an SMask in the ExtGState .currentSMask //null ne { % the image doesn't have an SMask, but the ExtGState does, force a group. << /Subtype /Group /Isolated //true >> 0 0 1 1 .begintransparencygroup .currentstrokeconstantalpha .currentfillconstantalpha 3 -1 roll 1 .setfillconstantalpha 1 .setstrokeconstantalpha doimage .setfillconstantalpha .setstrokeconstantalpha .endtransparencygroup } { doimage } ifelse } ifelse } ifelse } bind executeonly def % For development needs we define a special option for running with a new handler % for images with a soft mask. //systemdict /NEW_IMAGE3X .knownget not { //false } if { /doimagesmask { % <imagemask> doimagesmask - doimage } bind executeonly def } if /ValidateDecode { % <<image dict>> -imagemask- ValidateDecode <<image dict>> exch dup /Decode .knownget { dup length % -imagemask- <<image dict>> [Decode] length 4 -1 roll % <<image dict>> [Decode] length -imagemask- { 1 % ImageMask Decode arrays must be [0 1] or [1 0] } { mark currentcolor counttomark % <<image dict>> [Decode] length [ ... component_count dup 2 add 1 roll % <<image dict>> [Decode] length component_count [ .... cleartomark % <<image dict>> [Decode] length component_count } ifelse 2 mul dup % <<image dict>> [Decode] length comp_count*2 comp_count*2 3 1 roll % <<image dict>> [Decode] comp_count*2 length comp_count*2 eq { % <<image dict>> length of Decode matches colour space requirement pop pop % <<image dict>> remove [Decode] and comp_count*2 }{ % <<image dict>> Decode array incorrect dup 2 index length % <<image dict>> [Decode] comp_count*2 comp_count*2 length exch sub 0 gt { % Decode is too long (\n **** Warning: Decode array for an image is too long\n) pdfformatwarning ( Output may be incorrect.\n) pdfformatwarning 0 exch % <<image dict>> [Decode] 0 comp_count*2 getinterval % <<image dict>> [subarray of Decode] 1 index exch /Decode exch % <<image dict>> <<image dict>> /Decode [subarray] put % <<image dict>> }{ % Decode is too short, Acrobat throws errors on this (\n **** ERROR: Decode array for an image is too short\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror pop pop % remove [Decode] and comp_count*2 } ifelse } ifelse } { exch pop }ifelse }bind executeonly def /doimage { % <imagemask> doimage - % imagedict is currentdict, gets popped from dstack %% We must save the colour space, in case it gets changed. I did try doing this %% at a higher level (/Do) but that caused numerous problems with pdfwrite. currentcolorspace exch %% save the current rendering intent .currentrenderintent exch %% Check the image dictionary to see if there is a /Intent currentdict /Intent known { %% and set the current rendering intent to match if so Intent .setrenderingintent } if DataSource exch currentdict /SMask known PDFusingtransparency and { /PreserveSMask /GetDeviceParam .special_op { pop pop currentdict /SMask oget makesoftmaskimage } if } if currentdict /Mask knownoget { makemaskimage } if % Stack: datasource imagemask { currentdict end setsmaskstate //true ValidateDecode { imagemask } } { ColorSpace setgcolorspace currentdict end setsmaskstate //false ValidateDecode { image } } ifelse PDFSTOPONERROR { exec //false } { stopped } ifelse { dup type /dicttype eq { pop } if % Sometimes image fails to restore the stack $error /errorname get dup /ioerror eq { pop (\n **** Error: File has insufficient data for an image.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror } { (\n **** Error: File encountered ') exch 40 string cvs concatstrings (' error while processing an image.\n) concatstrings pdfformaterror ( Output may be incorrect.\n) pdfformaterror } ifelse } if % Close the input stream, unless it is PDFfile or % PDFsource. dup dup PDFfile eq exch PDFsource eq or { pop } { closefile } ifelse %% restore the rendering intent .setrenderingintent %% and restore the colour space. We need to do this in a stopped context because %% if we are rendering a glyph, the cache device will throw an error if we try %% to change colour space (even when the new space is the same as the old space) %% We can't tell if we are rendering a bitmap for a glyph, and its hard to compare %% colour spaces, so just ignore errors for now. {setcolorspace} stopped {pop} if teardown_trans } bind executeonly def /.paintform { % <formdict> <resdict> <stream> .paintform - 1 index /FormResDict gput % For broken forms that inherit resources from the context. 3 -1 roll dup /Group oknown PDFusingtransparency and { .paintgroupform } { pop pdfopdict .pdfruncontext } ifelse } bind executeonly def /IncrementAppearanceNumber { //pdfdict /AppearanceNumber .knownget { 1 add //pdfdict /AppearanceNumber 3 -1 roll .forceput } executeonly { //pdfdict /AppearanceNumber 0 .forceput } executeonly ifelse }bind executeonly odef /MakeAppearanceName { //pdfdict /AppearanceNumber get 10 string cvs dup length 10 add string dup 0 (\{FormName) putinterval dup 3 -1 roll 9 exch putinterval dup dup length 1 sub (\}) putinterval } bind executeonly def /MakeNewAppearanceName { IncrementAppearanceNumber MakeAppearanceName }bind executeonly def /DoAppearance { %% Might need to rethink this. The problem is that if the page has a CropBox, we apply %% that as an initial clip. When we run the form, we don't apply the /Rect from the %% annotation, which means that the form could be out of the clip, which results in %% content going missing. Resetting the clip prevents this. gsave initclip MakeNewAppearanceName .pdfFormName //pdfdict /.PreservePDFForm known {//pdfdict /.PreservePDFForm get} {//false}ifelse exch //pdfdict /.PreservePDFForm //true .forceput DoForm //pdfdict /.PreservePDFForm 3 -1 roll .forceput grestore } bind executeonly odef %% We don't want to do any high level forms stuff if the source %% is PDF because : %% 1) Transparent forms are handled separately and we don't want to ge confused %% 2) PDF forms are too llikely to trip over the limitations in our support %% 3) Its highly unusual to find a PDF file which uses forms sensibly. %% %% So we have a special PDF version of execform which doesn't do high level forms. pdfdict /.PDFexecform { % This is a separate operator so that the stacks will be restored % properly if an error occurs. dup /Matrix get concat dup /BBox get aload pop exch 3 index sub exch 2 index sub rectclip dup /PaintProc get 1 index /Implementation known not { 1 index dup /Implementation //null .forceput readonly pop } executeonly if exec } .bind executeonly put pdfdict /PDFexecform { gsave { //.PDFexecform exec } stopped grestore {stop} if } .bind executeonly put /DoForm { %% save the current value, if its true we will set it to false later, in order %% to prevent us preserving Forms which are used *from* an annotation /Appearance. //pdfdict /.PreservePDFForm known {//pdfdict /.PreservePDFForm get} {//false}ifelse exch %% We may alter the Default* colour spaces, if the Resources %% ColorSpace entry contains one of them. But we don't want that %% to become the new default, we want to revert to any existing %% definition, or the Device space. The Default* spaces are defined %% as ColorSpace resources, so the only way to handle them is to %% save and restore round the definitions 3 dict dup begin /saved_DG /DefaultGray /ColorSpace findresource def /saved_DRGB /DefaultRGB /ColorSpace findresource def /saved_DCMYK /DefaultCMYK /ColorSpace findresource def end exch % Adobe 2nd edition of the PDF 1.3 spec makes /FormType % and /Matrix keys optional. Cope with the missing keys. begin << currentdict /FormType known not { /FormType 1 } if currentdict /Matrix known not { /Matrix { 1 0 0 1 0 0 } cvlit } { 0 1 Matrix length 1 sub { dup Matrix exch get type dup /integertype eq exch /realtype eq or not { (\n **** Error: Invalid element in /Form XObject matrix.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror Matrix exch 0.00 put } { pop } ifelse } for } ifelse currentdict /BBox known not { (\n **** Error: Required entry /BBox not present in Form.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror /BBox [0 1 0 1] } if currentdict end { oforce } forall >> dup [ 2 index /Resources knownoget { oforce } { 0 dict } ifelse %% Ugly hackery for Default* colour spaces in forms %% dup /ColorSpace knownoget { oforce { //false 3 1 roll exch dup /DefaultGray eq { pop exec resolvecolorspace dup csncomp 1 eq { dup type /nametype eq { 1 array astore } if /DefaultGray exch /ColorSpace defineresource pop pop //true }{ pop ( **** Error: ignoring invalid /DefaultGray color space.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror } ifelse }{ dup /DefaultRGB eq { pop exec resolvecolorspace dup csncomp 3 eq { dup type /nametype eq { 1 array astore } if /DefaultRGB exch /ColorSpace defineresource pop pop //true }{ pop ( **** Error: ignoring invalid /DefaultRGB color space in Form Resources.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror } ifelse }{ /DefaultCMYK eq { exec resolvecolorspace dup csncomp 4 eq { dup type /nametype eq { 1 array astore } if /DefaultCMYK exch /ColorSpace defineresource pop pop //true }{ pop ( **** Error: ignoring invalid /DefaultCMYK color space in Form Resources.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror } ifelse }{ pop } ifelse } ifelse }ifelse { % if using color space substitution, "transition" the current color space currentcolorspace dup length 1 eq { % always an array 0 get dup /DeviceGray eq 1 index /DeviceRGB eq or 1 index /DeviceCMYK eq or { /Pattern setcolorspace setcolorspace } { pop } ifelse } { pop } ifelse } if } forall } if 3 index % /Contents for the stream is not per the spec, but Acrobat handles it dup /Contents knownoget { % We want to make it's a dictionary, and represents a stream dup type /dicttype eq { dup /FilePosition known { PDFSTOPONERROR { /DoForm cvx /undefinedresource signalerror } if ( **** Error: Invalid Form definition. Output may be incorrect.\n) pdfformaterror exch pop } {pop} ifelse } { pop } ifelse }if //false /resolvestream cvx /.paintform cvx ] cvx /PaintProc exch put % Adjust pdfemptycount since we have an extra dictionary on the stack pdfemptycount countdictstack 3 -1 roll /pdfemptycount count 4 sub store //pdfdict /.PreservePDFForm known {//pdfdict /.PreservePDFForm get}{//false} ifelse { %% We must *not* preserve any subsidiary forms (curently at least) as PDF %% form preservation doesn't really work. This is used just for Annotation %% Appearances currently, and if they should happen to use a form, we do not %% want to preserve it. //pdfdict /.PreservePDFForm //false .forceput /q cvx /execform cvx 5 -2 roll } executeonly { /q cvx /PDFexecform cvx 5 -2 roll } ifelse 4 .execn % Restore pdfemptycount 0 { countdictstack 2 index le { exit } if currentdict /n known not { 1 add } if countdictstack Q countdictstack eq {end} if } loop 1 gt { ( **** Error: Form stream has unbalanced q/Q operators \(too many q's\)\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror } if pop /pdfemptycount exch store % We've now seen Form XObjects leaving junk on the stack, so we % can't assume that when we finish the form the stack will be restored % nor can we assume that the junk won't include a 'mark' so we an't % simply do a cleartomark. Instead clear the stack until we get back % to a dictionary which contains /saved_DG. We can still get errors; % if the stream removes too many objects from the stack we will end % up with a stackunderflow, but there's nothing we can do about that. dup type /dicttype eq not { //true } { dup /saved_DG known { //false } { //true } ifelse } ifelse { ( **** Error: Form stream left garbage on the stack, attempting to recover.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror { dup type /dicttype eq not { pop } { dup /saved_DG known { exit } { pop } ifelse } ifelse } loop } if %% Put back pre-existing Default* ColorSpace definitions. dup type /dicttype eq { begin saved_DG /DefaultGray exch /ColorSpace defineresource pop saved_DRGB /DefaultRGB exch /ColorSpace defineresource pop saved_DCMYK /DefaultCMYK exch /ColorSpace defineresource pop end } if //pdfdict /.PreservePDFForm 3 -1 roll .forceput } bind executeonly odef /_dops_save 1 array def /DoPS { DOPS { //_dops_save 0 save put //true resolvestream cvx exec //_dops_save 0 get restore } { pop } ifelse } bind executeonly def currentdict /_dops_save undef /ocg_pocs 4 dict begin /AllOn { //true exch { oforce dup type /dicttype eq { /OFF known not and } { pop } ifelse } forall } bind executeonly def /AnyOn { //false exch { oforce dup type /dicttype eq { /OFF known not or } { pop } ifelse } forall } bind executeonly def /AnyOff { //AllOn exec not } bind executeonly def /AllOff { //AnyOn exec not } bind executeonly def currentdict end readonly def % Check whether OCG or OCMD is visible % <dict> oc-is-visible <bool> /ocg-is-visible { dup /Type knownoget { /OCMD eq { dup /OCGs knownoget not { {} } if % OC OCGs dup type /dicttype eq { 1 array astore } if //true 1 index { //null eq and } forall { pop pop //true % all nulls => show } { exch /P knownoget not { /AnyOn } if % OCGs P //ocg_pocs exch get exec % bool } ifelse } { dup /OFF known not % OFF is inserted by process_trailer_attrs { %% /OC is not in the OCProperties /OFF array, so we need to %% test its usage. We may eventually have to add a /ON to the dictionary %% if the OCProperties /ON array defines the /OC, I think that should override % the Usage, but I don't have an example to test. /Usage .knownget { oforce /Printed where { /Printed get } { //false }ifelse { %% We are behaving as a printer, check the Print state /Print .knownget { oforce /PrintState .knownget { oforce /OFF eq { //false }{ //true } ifelse }{ //true } ifelse }{ %% If we don't know, assume its visible //true } ifelse }{ %% We are behaving as a viewer, check the View state /View .knownget { oforce /ViewState .knownget { oforce /OFF eq { //false }{ //true } ifelse }{ //true } ifelse }{ %% If we don't know, assume its visible //true } ifelse } ifelse }{ %% If we don't know, assume its visible //true } ifelse }{ pop //false }ifelse } ifelse } { /OFF known not % OFF is inserted by process_trailer_attrs } ifelse } bind executeonly def drawopdict begin /Do { % /Name %% Bug 695897 This file has nested text blocks and also a Do image inside %% a text block. Here we attempt to detect and recover from this by setting the %% CTM to the matrix we saved before the text block. NB we update the 'TextSaveMatrix' %% or 'qTextSaveMatrix' whenever a 'cm' is issued, even if we are in a text block, so %% these matrices 'ought' to be correct. %% Of course, the file is badly broken, but 'Acrobat can open it....' currentdict /TextSaveMatrix known { gsave ( **** Error: Executing Do inside a text block, attempting to recover\n) pdfformaterror currentdict /TextSaveMatrix get setmatrix ( Output may be incorrect.\n) pdfformaterror } if currentdict /qTextSaveMatrix known { gsave ( **** Error: Executing Do inside a text block, attempting to recover\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror currentdict /qTextSaveMatrix get setmatrix } if setsmaskstate PDFfile fileposition exch % pos /Name % Bug #698226, Acrobat signals an error for recursive XObjects in a PDF file % but continues. This is true even if the XObject is not a simple self-reference % (eg /Fm1 -> /Fm2 -> /Fm3 -> /Fm1). % Normally when dealing with recursion we would put a dictionary on the stack, store the % object numbers encoutnered in it, and check each new object number to see if we've % already seen it. This doesn't work well for XObjects, because the operand stack can be % in any state when we run a Do. So we make a new dictionary in pdfdict to hold the % object numbers. % We also don't usually know the object number of a Form, we just get given its name % so we need a new routine to return the object number. This is because the parent XObject % might reference teh object by one name, while the child references it by another, we % can't permit clashes. % % Start by getting the object number for a Form XObject dup Page /XObject obj_get dup 0 eq not { % Now get the recording dictionary and see if that object number has been seen //pdfdict /Recursive_XObject_D get 1 index known { ( **** Error: Recursive XObject detected, ignoring ") print 1 index 256 string cvs print (", object number ) print 256 string cvs print (\n) print ( Output may be incorrect.\n) pdfformaterror //false }{ % We haven't seen it yet, so record it. //pdfdict /Recursive_XObject_D get 1 index //null put 3 1 roll //true }ifelse } { % I don't think this should be possible, but just in case ( **** Error: Unable to determine object number for ) print exch 256 string cvs print ( so ignoring it) print ( Output may be incorrect.\n) pdfformaterror //false } ifelse % If we could get the object number, and we haven't already seen it, then execute it. { dup Page /XObject rget { exch pop % pos obj OFFlevels length 0 eq { dup /OC knownoget { ocg-is-visible } { //true } ifelse } { //false } ifelse { dup /Subtype oget //xobjectprocs exch get % pos obj {proc} % Don't leave extra objects on the stack while executing % the definition of the form. 3 -1 roll % obj {proc} pos 2 .execn % pos } { pop % pos } ifelse } { % This should cause an error, but Acrobat Reader can % continue, so we do too. ( **** Error: Undefined XObject resource: ) exch =string cvs concatstrings (\n) concatstrings pdfformaterror ( Output may be incorrect.\n) pdfformaterror } ifelse PDFfile exch setfileposition //pdfdict /Recursive_XObject_D get exch undef }{ % Otherwise ignore it and tidy up the stacks pop pop } ifelse } bind executeonly def end currentdict /xobjectprocs .undef currentdict /ocg_pocs .undef % ---------------- In-line images ---------------- % % Undo the abbreviations in an in-line image dictionary. % Note that we must look inside array values. % /I is context-dependent. /unabbrevkeydict mark /BPC /BitsPerComponent /CS /ColorSpace /D /Decode /DP /DecodeParms /F /Filter /H /Height /I /Interpolate /IM /ImageMask /W /Width .dicttomark readonly def /unabbrevvaluedict mark /AHx /ASCIIHexDecode /A85 /ASCII85Decode /CC /CalCMYK /CCF /CCITTFaxDecode /CG /CalGray /CR /CalRGB /DCT /DCTDecode /CMYK /DeviceCMYK /Fl /FlateDecode /G /DeviceGray /RGB /DeviceRGB /I /Indexed /LZW /LZWDecode /RL /RunLengthDecode .dicttomark readonly def /unabbrevtypedict mark /nametype { //unabbrevvaluedict 1 index .knownget { exch pop } if } /arraytype { dup 0 1 2 index length 1 sub { 2 copy get unabbrevvalue put dup } for pop } .dicttomark readonly def /unabbrevvalue { % <obj> unabbrevvalue <obj'> oforce //unabbrevtypedict 1 index type .knownget { exec } if } bind executeonly def /is_space_dict << 0 0 9 9 10 10 12 12 13 13 32 32 >> readonly def drawopdict begin /BI { mark } bind executeonly def /ID { gsave %% Bug 696547, related to Bug 695897 (see /Do above) This file has an inline image inside %% a text block. Here we attempt to detect and recover from this by setting the %% CTM to the matrix we saved before the text block. NB we update the 'TextSaveMatrix' %% or 'qTextSaveMatrix' whenever a 'cm' is issued, even if we are in a text block, so %% these matrices 'ought' to be correct. %% Of course, the file is badly broken, but 'Acrobat can open it....' currentdict /TextSaveMatrix known { ( **** Error: Executing ID inside a text block, attempting to recover\n) pdfformaterror currentdict /TextSaveMatrix get setmatrix ( Output may be incorrect.\n) pdfformaterror } if currentdict /qTextSaveMatrix known { ( **** Error: Executing ID inside a text block, attempting to recover\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror currentdict /qTextSaveMatrix get setmatrix } if counttomark 2 idiv dup 7 add dict begin { exch //unabbrevkeydict 1 index .knownget { exch pop } if exch unabbrevvalue def } repeat pop /IDFlag //true def % flag for stream processing. /File PDFsource def currentdict makeimagekeys OFFlevels length 0 eq { gsave 1 1 moveto 0 0 lineto % If we get an error, just emit an empty box { pathbbox } stopped { 0 0 0 0 } if 4 array astore grestore /image setup_trans doimage } { pop Width currentdict /ImageMask knownoget dup { and } if not { ColorSpace oforce csncomp mul BitsPerComponent mul } if 7 add 8 idiv Height mul DataSource exch () /SubFileDecode filter flushfile end } ifelse % The Adobe documentation says that the data following ID % consists of "lines", and some PDF files (specifically, some files % produced by PCL2PDF from Visual Software) contain garbage bytes % between the last byte of valid data and an EOL. % Some files (PDFOUT v3.8d by GenText) have EI immediately following % the stream. Some have no EOL and garbage bytes. % Sometimes (bug 690300) CCITTDecode filter consumes 'E' in 'EI'. % Therefore, we search for <start>I<sp|end> or <start|sp>EI<sp|end> PDFsource read not { /ID cvx /syntaxerror signalerror } if dup 73 eq { pop 10 69 73 % Seed to: <sp>EI } { 10 10 3 -1 roll % Seed to: <sp><sp><any> } ifelse { PDFsource read not dup { 10 exch } if //is_space_dict 2 index known 3 index 73 eq and 4 index 69 eq and //is_space_dict 6 index known and { pop pop pop pop pop exit } { { pop pop pop /ID cvx /syntaxerror signalerror } { 4 -1 roll pop } ifelse } ifelse } loop grestore } bind executeonly def end currentdict /is_space_dict undef % ================================ Text ================================ % drawopdict begin % Text control /BT { BT } executeonly def /ET { ET } executeonly def /Tc { Tc } executeonly def /TL { TL } executeonly def /Tr { Tr } executeonly def /Ts { Ts } executeonly def /Tw { Tw } executeonly def /Tz { Tz } executeonly def % Text positioning /Td { Td } executeonly def /TD { TD } executeonly def /Tm { Tm } executeonly def /T* { T* } executeonly def % Text painting /Tj { Tj } executeonly def /' { ' } executeonly def /" { " } executeonly def /TJ { TJ } executeonly def /Tform { Tform } executeonly def % Text formatting and painting for AcroForm % without appearance streams. end % ======================= Invalid operators ============================ % drawopdict begin /QBT { Q BT ( **** Error: invalid operator QBT processed as Q BT .\n) pdfformaterror % Bug 690089 ( Output may be incorrect.\n) pdfformaterror } executeonly def /. { 0. ( **** Error: invalid operator . processed as number 0. .\n) pdfformaterror % Bug 690730 ( Output may be incorrect.\n) pdfformaterror } executeonly def end % ============================== Annotations ============================== % % Create links from separate widget annotations to the parent field nodes. % Surprisingly, separate widget annotations don't have a link to the parent % from which they inherit some data. /link_widget_annots { % <<parent>> <<kid>> -> <<parent>> <<kid>> dup /Kids knownoget { { oforce dup type /dicttype eq { link_widget_annots } if pop } forall } if dup /Parent oknown not { 2 copy exch /ParentField exch put } if } bind executeonly def % Get and normalize an annotation's rectangle. /annotrect { % <annot> annotrect <x> <y> <w> <h> /Rect oget oforce_recursive aload pop exch 3 index sub dup 0 lt { dup 5 -1 roll add 4 1 roll neg } if exch 2 index sub dup 0 lt { dup 4 -1 roll add 3 1 roll neg } if } bind executeonly def % Set an annotation color. % If the /C array is empty we don't want to draw the annotation % /annotsetcolor { % <annot> annotsetcolor bool /C knownoget { dup length 4 eq { aload pop setcmykcolor //true }{ dup length 3 eq { aload pop setrgbcolor //true }{ dup length 1 eq { aload pop setgray //true } { dup length 0 eq { pop //false }{ ( **** Error: invalid color specified for annotation /C entry) pdfformaterror //false ( Output may be incorrect.\n) pdfformaterror } ifelse } ifelse } ifelse } ifelse } { 0 setgray //true} ifelse } bind executeonly def % Set an annotation color. % If the /C array is empty we don't want to draw the annotation % /annotsetinteriorcolor { % <annot> annotsetcolor bool /IC knownoget { dup length 4 eq { aload pop setcmykcolor //true }{ dup length 3 eq { aload pop setrgbcolor //true }{ dup length 1 eq { aload pop setgray //true } { dup length 0 eq { pop //false }{ ( **** Error: invalid color specified for annotation /C entry) pdfformaterror //false ( Output may be incorrect.\n) pdfformaterror } ifelse } ifelse } ifelse } ifelse } { //false } ifelse } bind executeonly def % Draw the border. Currently, we ignore requests for beveling, and we % don't round the corners of rectangles. /strokeborder { % <annot> <width> <dash> strokeborder - 1 index 0 ne { % do not draw if border width is 0 gsave % 2 index annotsetcolor % { 0 setdash dup setlinewidth exch dup annotrect 5 -1 roll /RD knownoget { applyRD } if 2 { 4 index sub 4 1 roll } repeat 2 { 4 index 0.5 mul add 4 1 roll } repeat rectstroke pop grestore % } { % pop pop pop % } ifelse } { pop pop pop }ifelse } bind executeonly def % Draw an annotation border. /drawborder { % <annot> drawborder - gsave dup /BS known 1 index /Border known or { dup /BS knownoget { dup type /dicttype ne % <annot> <border> <bad?> } { dup /Border oget dup type /arraytype eq { dup length 3 lt } { //true } ifelse % <annot> [border] <bad?> } ifelse { ( **** Error: Invalid annotation border object, border has not been drawn.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror pop { 0 0 0 } } if dup type /dicttype eq { dup /W knownoget not { 1 } if % Per PDF1.6 Reference table 8.13, /W in the border style dictionary is % expressed in points (an absolute unit), so compensate here for any % scaling of the PostScript user space done due to /UserUnit. % Scaling due to -dPDFFitPage is not undone, to keep the correct border width % compared to the size of the surrounding marks. //systemdict /NoUserUnit .knownget not { //false } if not //systemdict /PDFFitPage known not and % Don't apply USerUnit if we are passing it to the device /PassUserUnit /GetDeviceParam .special_op {exch pop} {//false} ifelse not and { % UserUnit is ignored if -dPDFFitPage Page /UserUnit knownoget { div } if } if {} 2 index /S knownoget { /D eq { 2 index /D knownoget not { {3} } if exch pop } if } if 3 -1 roll pop strokeborder } { dup 2 get exch dup length 3 gt { 3 get } { pop {} } ifelse strokeborder } ifelse } { 1 {} strokeborder } ifelse grestore } bind executeonly def % stroke the path of an annotation border. /strokeborderpath { % <annot> strokeborderpath - gsave dup /BS known 1 index /Border known or { dup /BS knownoget { dup type /dicttype ne % <annot> <border> <bad?> } { dup /Border oget dup type /arraytype eq { dup length 3 lt } { //true } ifelse % <annot> [border] <bad?> } ifelse { ( **** Error: Invalid annotation border object, border has not been drawn.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror pop { 0 0 0 } } if dup type /dicttype eq { dup /W knownoget not { 1 } if % Per PDF1.6 Reference table 8.13, /W in the border style dictionary is % expressed in points (an absolute unit), so compensate here for any % scaling of the PostScript user space done due to /UserUnit. % Scaling due to -dPDFFitPage is not undone, to keep the correct border width % compared to the size of the surrounding marks. //systemdict /NoUserUnit .knownget not { //false } if not //systemdict /PDFFitPage known not and % Don't apply USerUnit if we are passing it to the device /PassUserUnit /GetDeviceParam .special_op {exch pop} {//false} ifelse not and { % UserUnit is ignored if -dPDFFitPage Page /UserUnit knownoget { div } if } if {} 2 index /S knownoget { /D eq { 2 index /D knownoget not { {3} } if exch pop } if } if 3 index /CA knownoget {dup .setstrokeconstantalpha .setfillconstantalpha} if 3 -1 roll pop % 2 index annotsetcolor { 0 setdash setlinewidth stroke % } if } { dup 2 get % If element 3 of the /Border array is 0, then don't draw the border dup 0 ne { exch dup length 3 gt { 3 get } { pop {} } ifelse 3 index /CA knownoget {dup .setstrokeconstantalpha .setfillconstantalpha} if % 2 index annotsetcolor { 0 setdash setlinewidth stroke % } if }{ pop pop } ifelse } ifelse } { dup /CA knownoget {dup .setstrokeconstantalpha .setfillconstantalpha} if 1 {} % 2 index annotsetcolor { 0 setdash setlinewidth stroke % } if } ifelse pop grestore } bind executeonly def /fillborderpath { % <annot> fillborderpath - gsave dup /ca knownoget {dup .setstrokeconstantalpha .setfillconstantalpha} if annotsetinteriorcolor {fill} if grestore }bind executeonly def % % The PDF annotation F (flags) integer is bit encoded. % Bit 1 (LSB) Invisible: 1 --> Do not display if no handler. % Note: We have no handlers but we ignore this bit. % Bit 2 Hidden: 1 --> Do not display. We will not display if this bit is set. % Bit 3 Print: 1 --> Display if printing. We will display if this bit set % (and not hidden) and Printed is true % Bit 4 NoZoom: 1 --> Do not zoom annotation even if image is zoomed. % Bit 5 NoRotate: 1 --> Do not rotate annotation even if image is rotated. % Bit 6 NoView: 0 --> Display if this is a 'viewer'. We will display % if this bit is not set (and not hidden) and Printed is false % Bit 7 Read Only - 1 --> No interaction. We ignore this bit % % AR8 and AR9 print 3D annotations even if Print flag is off. Bug 691486. % /annotvisible { % <annot> annotvisible <visible> dup /Subtype knownoget { /3D eq } { //false } ifelse % 3D annot exch /F knownoget not { 0 } if % Get flag value dup 2 and 0 eq { /Printed load { 4 and 4 eq or % Printed or 3D } { 32 and 0 eq exch pop % not NoView } ifelse } { pop pop //false % Hidden } ifelse } bind executeonly def /set_bc_color << 1 { 0 get oforce setgray } bind executeonly 3 { { oforce } forall setrgbcolor } bind executeonly 4 { { oforce } forall setcmykcolor } bind executeonly >> readonly def % Get an inherited attribute from a node through /Parent and /ParentField % links. The latter is set at start-up to access parents of annotations and % defaults at AcroForm. /fget % <field> <key> fget <value> -true- { % <field> <key> fget -false- { 2 copy knownoget { exch pop exch pop //true exit } { exch dup /Parent knownoget { exch pop exch } { /ParentField knownoget { exch } { pop //false exit } ifelse } ifelse } ifelse } loop } bind executeonly def % <annot> foo <annot> /make_tx_da { dup /AP << /N 10 dict dup cvx begin >> put /Subtype /Form def /BBox [ 0 0 4 index /Rect oget { oforce } forall 3 -1 roll sub abs 3 1 roll sub abs exch ] def /Resources 1 index /DR fget not { 0 dict } if def /File 1 index /V fget not { () } if length 2 index /DA fget not { () } if length add 500 add 65535 .min string dup 3 1 roll def /NullEncode filter % <annot> file dup (BT ) writestring 1 index /DA fget not { 1 index /V fget { <EFBBBF> anchorsearch { pop /Helvetica findfont 12 scalefont setfont } { <FEFF> anchorsearch { pop pop /FallBackFont /Identity-UTF16-H [/CIDFallBack] composefont 12 scalefont setfont } { pop /Helvetica findfont % re-encode the font to PDFDocEncoding dup length dict begin { 1 index /FID ne 2 index /UniqueID ne and { def } { pop pop } ifelse } forall /Encoding /PDFDocEncoding /Encoding findresource def /FontName /Helvetica-PDFDocEncoding def currentdict end /Helvetica-PDFDocEncoding exch definefont 12 scalefont setfont }ifelse }ifelse } if () }if [ exch { token { dup /Tf eq { 2 index 0 eq { /BBox load 3 get 0.75 mul % empirical constant 4 -1 roll pop 3 1 roll } if } if exch } { exit } ifelse } loop ] { 1 index exch write== } forall dup 2 index /MaxLen fget not { 0 } if write= dup 2 index /V fget not { () } if write== dup 2 index /Ff fget not { 0 } if write= dup 2 index /Q fget not { 0 } if write= dup (Tform ET) write= dup .fileposition /Length exch def /File File 0 Length getinterval def closefile % <annot> end } bind executeonly def /can-regenerate-ap { % <annot> -> <bool> //false exch NeedAppearances { dup /FT fget { dup /Tx eq { pop dup /V oknown { pop not 1 } if } { /Ch eq { dup /V oknown { pop not 1 } if } if } ifelse } if } if pop } bind executeonly def /drawwidget { % <scalefactor_x> <scalefactor_y> <annot> drawwidget - %% This code checks to see if we can geenrate an appearance stream for the %% given widget, and if we can it ignores the given Appearance stream, so that %% we generate one instead. This seems wrong to me, if we've been given an %% appearance stream we should use it, no synthesize something else. Several %% files in our regression test suite render 'incorrectly' when compared to %% Acrobat with this removed, clearly Acrobat always ignores appearances. However %% several other files are rendered better when we *don't* ignore the Appearance %% So on balance I'm choosing to honour the appearance. %% % dup /UpdatedAP known not { % dup can-regenerate-ap { % dup /AP undef % } if % } if % Acrobat doesn't draw Widget annotations unles they have both /FT % (which is defined as required) and /T keys present. Annoyingly % these can either be inherited from the Form Definition Field % dictionary (via the AcroForm tree) or present directly in the % annotation, so we need to check the annotation to make sure its % a Widget, then follow any /Parent key up to the root node % extracting and storing any FT or T keys as we go (we only care if % these are present, their value is immaterial). If after all that % both keys are not present, then we don't draw the annotation. dup /Subtype get /Widget eq { dup /FT known 1 index /T known and not { dup { dup /FT knownoget { /FT exch 3 index 3 1 roll put } if dup /T knownoget { /T exch 3 index 3 1 roll put } if /Parent knownoget not { exit } if } loop } if dup /FT known 1 index /T known and { //true } { ( **** Warning: A Widget annotation dictionary lacks either the FT or T key.\n) pdfformaterror ( Acrobat ignores such annotations, annotation will not be rendered.\n) pdfformaterror ( Output may not be as expected.\n) pdfformaterror //false } ifelse } { //true }ifelse { dup /AP knownoget { dup /N known not { ( **** Error: Appearance dictionary (AP) lacks the mandatory normal (N) appearance.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror } if //false [/N /R /D] { % stack: scalex scaley annot appearance false key 2 index exch knownogetdict { exch not exit } if } forall % stack: scalex scaley annot appearance value true % stack: scalex scaley annot appearance false dup { pop exch pop % Acrobat Distiller produces files in which this Form % XObject lacks Type and Subtype keys. This is illegal, % but Acrobat Reader accepts it. The only way we can % tell whether this is a Form or a set of sub-appearances % is by testing for the stream Length or File key. % If the stream lacks Length key, try File key. dup /Length knownoget { type /integertype eq } { //false } ifelse 1 index /File knownoget { type /filetype eq or } if { % If this is a form then simply use it //true } { 1 index /AS knownoget not { % If we do not have AS then use any appearance { exch pop oforce exit } forall //true } { % Stack: annot Ndict AS % Get the specified appearance. If no appearance, then % display nothing - set stack = false. knownoget } ifelse } ifelse } { exch pop % discard useless AP dictionary } ifelse % Stack: scalex scaley annot appearance true % Stack: scalex scaley annot false { dup type /dicttype eq { % Draw appearance % Initialize graphic following "7.4.4 Appearance Streams" q graphicsbeginpage textbeginpage 1 index annotrect pop pop translate 3 index 3 index scale % Apply scale factors dup /BBox knownoget { 1 index /Matrix knownoget not { {1 0 0 1 0 0} } if .bbox_transform pop pop % Compensate for non-zero origin of BBox neg exch neg exch translate } if DoForm Q } { ( **** Error: Annotation's appearance is not a dictionary.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror } ifelse } if } { dup /MK knownoget { % mk dup /BG knownoget { % mk bg dup length % mk bg len //set_bc_color exch .knownget { gsave exec 3 index 3 index scale 1 index annotrect rectfill grestore } { pop } ifelse } if dup /BC knownoget { dup length //set_bc_color exch .knownget { gsave exec 1 setlinewidth 3 index 3 index scale 1 index annotrect rectstroke grestore } { pop } ifelse } if pop } if dup can-regenerate-ap { make_tx_da dup /UpdatedAP //true put 3 copy drawwidget } if } ifelse } if pop pop pop } bind executeonly def currentdict /set_bc_color undef % For annotation object we have to determine the size of the output rectangle % and the size of the BBox for the form XObject. From these we calculate % a scale factors for drawing it. /calc_annot_scale { % <annot> calc_annot_scale <x_scale> <y_scale> dup /Rect knownoget { pop dup annotrect 4 2 roll pop pop % get width height size in user space 2 index /AP knownoget { /N knownogetdict { % <<Annot>> x y <<N>> dup 4 index /AS knownoget { knownoget { exch pop } if } { pop } ifelse dup /Matrix knownoget not { {1 0 0 1 0 0} } if exch /BBox knownoget { % <<>> x y {matrix} [box] exch .bbox_transform % <<>> x y x0 y0 x1 y1 3 -1 roll sub % <<>> x y x0 x1 y1-y0 3 1 roll exch sub % <<>> x y y1-y0 x1-x0 2 copy mul 0 eq { ( **** Error: /BBox has zero width or height, which is not allowed.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror pop pop pop pop 1 1 % zero size -- revert to unity scaling } { 3 1 roll div % <<>> x x1-x0 y/(y1-y0) 3 1 roll div % <<>> y/(y1-y0) x/(x1-x0) exch % <<>> x/(x1-x0) y/(y1-y0) } ifelse } { pop pop pop 1 1 % default to unity scaling } ifelse % if we have /BBox } { pop pop 1 1 } ifelse % if we have /N } { pop pop 1 1 } ifelse % if we have /AP 3 -1 roll pop } { ( **** Error: /Annot dict is missing required /Rect entry.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror pop 1 1 } ifelse } bind executeonly def /applyRD { % x y w h [l t r b] dup 0 get % x y w h [] l 6 -1 roll add 5 1 roll %x+l y w h [] dup 1 get %x+l y w h [] b 5 -1 roll add %x+l w h [] b+y 4 1 roll %x+l y+b w h [] aload pop %x+l y+b w h l t r b exch %x+l y+b w h l t b r 4 -1 roll add %x+l y+b w h t b r+l 3 1 roll add %x+l y+b w h r+l t+b 3 -1 roll exch sub %x+l y+b w r+l h-(t+b) 3 1 roll sub %x+l y+b h-(t+b) w-(r+l) exch } bind executeonly def % Draw an annotation. /drawannottypes 20 dict begin /startannottransparency { PDFusingtransparency { dup /BM known { dup /BM get << exch /BM exch >> } { << >> }ifelse %% We should be able to use the Rect to create the group, but it seems %% Acrobat ignores this, or at least doesn't clip the annotation to it :-( % 1 index /Rect known { % 1 index annotrect exch % llx lly h w % 3 index add exch % x y urx h % 2 index add % }{ clippath pathbbox newpath % } ifelse .begintransparencygroup } if }bind executeonly def /endannottransparency { PDFusingtransparency { .endtransparencygroup } if }bind executeonly def /ValidateAP { dup /AP oknown { dup /AP oget /N oknown not { //false } { //true } ifelse } { //false }ifelse } bind executeonly def % x0 y0 x1 y1 x2 y2 x3 y3 -> x0 y0 x1-x0 y1-y0 x2-x0 y2-y0 /quadpoints2basis { 8 { oforce 8 1 roll } repeat % The text is oriented with respect to the vertex with the smallest % y value (or the leftmost of those, if there are two such vertices) % (x0, y0) and the next vertex in a counterclockwise direction % (x1, y1), regardless of whether these are the first two points in % the QuadPoints array. 2 { 2 index 1 index eq { 3 index 2 index gt { 4 2 roll } if } { 2 index 1 index gt { 4 2 roll } if } ifelse 8 4 roll } repeat 6 index 3 index gt { 8 4 roll } if % ^ % | % * (x2,y2) * (x3,y3) % | % | % *------------*-> % (x0,y0) (x1,y1) pop pop % x0 y0 x1 y1 x2 y2 4 index sub exch % x0 y0 x1 y1 y2-y0 x2 5 index sub exch % x0 y0 x1 y1 x2-x0 y2-y0 4 2 roll 4 index sub exch % x0 y0 x2-x0 y2-y0 y1-y0 x1 5 index sub exch % x0 y0 x2-x0 y2-y0 x1-x0 y1-y0 4 2 roll % x0 y0 x1-x0 y1-y0 x2-x0 y2-y0 } bind executeonly def /Square { //ValidateAP exec { //true } { gsave //startannottransparency exec dup annotsetinteriorcolor { gsave dup /ca knownoget {dup .setstrokeconstantalpha .setfillconstantalpha} if dup annotrect 5 index /RD knownoget { applyRD } if rectfill grestore dup /CA knownoget {dup .setstrokeconstantalpha .setfillconstantalpha} if dup annotsetcolor { drawborder } if //false }{ dup annotrect 5 index /RD knownoget { applyRD } if drawopdict /re get exec dup annotsetcolor { strokeborderpath } if } ifelse //endannottransparency exec grestore //false }ifelse } bind executeonly def %% Width Height drawellipse - /drawellipse { %% Don Lancaster's code for drawing an ellipse 0.55228475 0.00045 sub % improved magic value 3 1 roll % magic width height 2 div exch 2 div % magic y-radius x-radius dup 3 index mul % magic y-radius x-radius x-magic 2 index % magic y-radius x-radius x-magic y-radius 5 -1 roll mul % magic y-radius x-radius x-magic y-magic 2 index neg 0 moveto % xrad neg 0 moveto 2 index neg 1 index 3 index neg 6 index 0 8 index curveto % xrad neg ymag xmag neg yrad 0 yrad curveto 1 index 4 index 4 index 3 index 1 index 0 curveto % xmag yrad xrad ymag xrad 0 curveto 2 index 1 index neg 3 index 6 index neg 0 1 index curveto % xrad ymag neg xmag yrad neg 0 yrad neg curveto % Stack: yrad xrad xmag ymag exch neg 4 1 roll 3 -1 roll neg 3 1 roll exch neg exch neg 1 index 0 curveto % xmag neg yrad neg xrad neg ymag neg 0 curveto }bind executeonly def /Circle { //ValidateAP exec { //true } { gsave //startannottransparency exec dup annotrect 5 index /RD knownoget { applyRD } if 4 2 roll exch 3 index 2 div add exch 2 index 2 div add translate //drawellipse exec dup fillborderpath dup annotsetcolor { strokeborderpath } if //endannottransparency exec grestore //false } ifelse } bind executeonly def /Polygon { //ValidateAP exec { //true } { gsave //startannottransparency exec dup /Vertices knownoget { dup length 2 div 1 sub cvi 0 1 3 -1 roll { 2 mul dup 2 index exch 2 getinterval aload pop 3 -1 roll 0 eq { moveto }{ lineto } ifelse } for pop closepath //true } { ( **** Error: Invalid Vertices for Polygon, annotation has not been drawn.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror //false } ifelse 1 index annotsetinteriorcolor { //true }{ //false }ifelse and { gsave dup /ca knownoget {dup .setstrokeconstantalpha .setfillconstantalpha} if fill grestore dup /CA knownoget {dup .setstrokeconstantalpha .setfillconstantalpha} if dup annotsetcolor { strokeborderpath } if } { dup annotsetcolor { strokeborderpath } if } ifelse //endannottransparency exec //false grestore } ifelse } bind executeonly def /LineEnd_dict 10 dict begin %% Stack contains <annot> %% CTM rotated so line segment is vertical, translated so line endpoint at 0,0 /Square { dup /BS knownoget { /W knownoget { }{ 1 }ifelse }{ 1 }ifelse dup 2.5 mul gsave dup neg 1 index neg exch moveto dup neg 1 index lineto dup 1 index exch lineto dup neg lineto closepath 1 index /CA knownoget {dup .setstrokeconstantalpha .setfillconstantalpha} if 1 index fillborderpath grestore 3 mul dup neg 1 index neg exch moveto dup neg 1 index lineto dup 1 index exch lineto dup neg lineto closepath strokeborderpath } bind executeonly def /Circle { dup /BS knownoget { /W knownoget { }{ 1 }ifelse }{ 1 }ifelse dup gsave 2.5 mul dup 0 moveto 0 0 3 -1 roll 0 360 arc 1 index /CA knownoget {dup .setstrokeconstantalpha .setfillconstantalpha} if 1 index fillborderpath grestore 3 mul dup 0 moveto 0 0 3 -1 roll 0 360 arc strokeborderpath } bind executeonly def /Diamond { dup /BS knownoget { /W knownoget { }{ 1 }ifelse }{ 1 }ifelse dup 2.5 mul gsave dup neg 0 exch moveto dup neg 0 lineto dup 0 exch lineto 0 lineto closepath 1 index /CA knownoget {dup .setstrokeconstantalpha .setfillconstantalpha} if 1 index fillborderpath grestore 3 mul dup neg 0 exch moveto dup neg 0 lineto dup 0 exch lineto 0 lineto closepath strokeborderpath } bind executeonly def /OpenArrow { dup gsave /BS knownoget { /W knownoget { }{ 1 }ifelse }{ 1 }ifelse 0 setlinejoin dup 6 mul neg 1 index 4 mul neg moveto dup 1.2 div neg 0 lineto dup 6 mul neg exch 4 mul lineto strokeborderpath grestore } bind executeonly def /ClosedArrow { dup gsave /BS knownoget { /W knownoget { }{ 1 }ifelse }{ 1 }ifelse dup gsave 0 setlinejoin dup 6 mul neg 1 index 4 mul neg moveto dup 1.2 div neg 0 lineto dup 6 mul neg exch 4 mul lineto closepath 1 index strokeborderpath grestore dup 1.3 mul neg 0 translate dup 2 div sub dup 8.4 mul neg 1 index 5.9 mul neg moveto dup 1.2 div neg 0 lineto dup 8.4 mul neg exch 5.9 mul lineto closepath dup /CA knownoget {dup .setstrokeconstantalpha .setfillconstantalpha} if fillborderpath grestore } bind executeonly def /None {pop} bind executeonly def /Butt { dup /BS knownoget { /W knownoget { }{ 1 }ifelse }{ 1 }ifelse 3 mul dup neg 0 exch moveto 0 exch lineto strokeborderpath } bind executeonly def /ROpenArrow { gsave dup /BS knownoget { /W knownoget { }{ 1 }ifelse }{ 1 }ifelse 180 rotate 0 setlinejoin dup 6 mul neg 1 index 4 mul neg moveto dup 1.2 div neg 0 lineto dup 6 mul neg exch 4 mul lineto strokeborderpath grestore } bind executeonly def /RClosedArrow { gsave dup /BS knownoget { /W knownoget { }{ 1 }ifelse }{ 1 }ifelse 180 rotate dup gsave 0 setlinejoin dup 6 mul neg 1 index 4 mul neg moveto dup 1.2 div neg 0 lineto dup 6 mul neg exch 4 mul lineto closepath 1 index strokeborderpath grestore dup 1.3 mul neg 0 translate dup 2 div sub dup 8.4 mul neg 1 index 5.9 mul neg moveto dup 1.2 div neg 0 lineto dup 8.4 mul neg exch 5.9 mul lineto closepath dup /CA knownoget {dup .setstrokeconstantalpha .setfillconstantalpha} if fillborderpath grestore } bind executeonly def /Slash { gsave dup /BS knownoget { /W knownoget { }{ 1 }ifelse }{ 1 }ifelse 330 rotate 3 mul dup neg 0 exch moveto 0 exch lineto strokeborderpath grestore } bind executeonly def currentdict end readonly def /Line { //ValidateAP exec { //true } { gsave //startannottransparency exec dup annotsetcolor { dup /L knownoget { 1 index /LE knownoget { % <annot> [x1 y1 x2 y2] [LE1 LE2] gsave 1 index aload pop % <annot> [x1 y1 x2 y2] [LE1 LE2] x1 y1 x2 y2 3 -1 roll sub % <annot> [x1 y1 x2 y2] [LE1 LE2] x1 x2 dy 3 1 roll exch sub % <annot> [x1 y1 x2 y2] [LE1 LE2] dy dx 3 index aload pop 4 2 roll pop pop translate 0 0 moveto {atan} stopped {pop pop 0} if % <annot> [x1 y1 x2 y2] [LE1 LE2] rotate dup 1 get % <annot> [x1 y1 x2 y2] [LE1 LE2] LE1 dup //LineEnd_dict exch known not { pop /None } if //LineEnd_dict exch % <annot> [x1 y1 x2 y2] [LE1 LE2] <dict> LE1 get % <annot> [x1 y1 x2 y2] [LE1 LE2] {} 3 index exch % <annot> [x1 y1 x2 y2] [LE1 LE2] <annot> {} exec grestore gsave 1 index aload pop % x1 y1 x2 y2 3 -1 roll sub % x1 x2 dy 3 1 roll exch sub % dy dx 3 index aload pop pop pop translate 0 0 moveto {atan} stopped {pop pop 0} if 180 add rotate 0 get dup //LineEnd_dict exch known not {pop /None} if //LineEnd_dict exch get 3 index exch exec grestore }if aload pop 4 2 roll moveto lineto strokeborderpath }{ ( **** Error: Invalid L array for Line, annotation has not been drawn.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror pop } ifelse } if //endannottransparency exec //false grestore } ifelse } bind executeonly def /PolyLine { //ValidateAP exec { //true } { gsave //startannottransparency exec dup annotsetcolor pop dup /Vertices knownoget { 1 index /LE knownoget { gsave 1 index 0 4 getinterval aload pop 4 2 roll 2 copy translate 4 2 roll 3 -1 roll exch sub % x1 x2 dy 3 1 roll sub % dy dx {atan} stopped {pop pop 0} if rotate dup 0 get dup //LineEnd_dict exch known not {pop /None} if //LineEnd_dict exch get 3 index exch exec grestore gsave 1 index dup length 4 sub 4 getinterval aload pop 2 copy translate 3 -1 roll sub % x1 x2 dy 3 1 roll exch sub % dy dx {atan} stopped {pop pop 0} if rotate 1 get dup //LineEnd_dict exch known not {pop /None} if //LineEnd_dict exch get 3 index exch exec grestore } if dup length 2 div 1 sub cvi 0 1 3 -1 roll { 2 mul dup 2 index exch 2 getinterval aload pop 3 -1 roll 0 eq { moveto }{ lineto } ifelse } for pop //true } { ( **** Error: Invalid Vertices for Polygon, annotation has not been drawn.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror //false } ifelse { strokeborderpath } if //endannottransparency exec //false grestore } ifelse } bind executeonly def /Link { % <annot> -> <false> //startannottransparency exec dup annotsetcolor { dup drawborder dup calc_annot_scale 2 copy mul 0 ne {3 -1 roll drawwidget} { pop pop ( **** Error: ignoring annotation with scale factor of 0\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror }ifelse } if //endannottransparency exec //false } bind executeonly def /Ink { % <annot> -> <annot> <true> % <annot> -> <false> //ValidateAP exec { //true } { //startannottransparency exec 1 setlinewidth 1 setlinecap 1 setlinejoin dup annotsetcolor { dup calc_annot_scale 2 copy mul 0 ne { scale dup /InkList knownoget { { oforce [ exch { oforce } forall ] .pdfinkpath stroke } forall pop } { /Path knownoget { oforce dup length 1 sub 0 1 3 -1 roll { dup 0 eq { 1 index exch get aload pop moveto } { 1 index exch get dup length 2 eq { aload pop lineto }{ aload pop curveto } ifelse }ifelse } for pop dup strokeborderpath } if }ifelse } { pop pop ( **** Error: ignoring annotation with scale factor of 0\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror } ifelse } if //endannottransparency exec //false } ifelse } bind executeonly def /Underline { //ValidateAP exec { //true } { 0 setlinecap dup annotsetcolor { dup calc_annot_scale 2 copy mul 0 ne { scale /QuadPoints knownoget { aload length 8 idiv { //quadpoints2basis exec % Acrobat draws the line at 1/7 of the box width from the bottom % of the box and 1/16 thick of the box width. /Rect is ignored. 2 copy dup mul exch dup mul add sqrt 16 div setlinewidth 7 div 4 index add exch % x0 y0 x1-x0 y1-y0 (y2-y0)/7+y0 x2-x0 7 div 5 index add exch % x0 y0 x1-x0 y1-y0 (x2-x0)/7+x0 (y2-y0)/7+y0 2 copy moveto 2 index add exch 3 index add exch lineto % x0 y0 x1-x0 y1-y0 pop pop pop pop stroke } repeat } if } { pop pop ( **** Error: ignoring annotation with scale factor of 0\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror } ifelse } if //false } ifelse } bind executeonly def /StrikeOut { //ValidateAP exec { //true } { 0 setlinecap dup annotsetcolor { dup calc_annot_scale 2 copy mul 0 ne { scale /QuadPoints knownoget { aload length 8 idiv { //quadpoints2basis exec % Acrobat draws the line at 3/7 of the box width from the bottom % of the box and 1/16 thick of the box width. /Rect is ignored. 2 copy dup mul exch dup mul add sqrt 16 div setlinewidth 0.4285714 mul 4 index add exch % x0 y0 x1-x0 y1-y0 (y2-y0)*3/7+y0 x2-x0 0.4285714 mul 5 index add exch % x0 y0 x1-x0 y1-y0 (x2-x0)*3/7+x0 (y2-y0)*3/7+y0 2 copy moveto 2 index add exch 3 index add exch lineto % x0 y0 x1-x0 y1-y0 pop pop pop pop stroke } repeat } if } { pop pop ( **** Error: ignoring annotation with scale factor of 0\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror } ifelse } if //false } ifelse } bind executeonly def % Connect 2 points with an arc that has max distance from the line % segment to the ark equal 1/4 of the radius. /highlight-arc { % x1 y1 x0 y0 -> - 4 2 roll % x0 y0 x1 y1 dup 3 index add 2 div % x0 y0 x1 y1 (y1+y0)/2 2 index 5 index sub .9375 mul sub % x0 y0 x1 y1 (y1+y0)/2-15/16*dx=yc 4 index 3 index add 2 div % x0 y0 x1 y1 yc (x0+x1)/2 2 index 5 index sub .9375 mul add % x0 y0 x1 y1 yc xc exch % x0 y0 x1 y1 xc yc dup 3 index exch sub % x0 y0 x1 y1 xc yc y1-yc 4 index 3 index sub % x0 y0 x1 y1 xc yc y1-yc x1-xc dup dup mul 2 index dup mul add sqrt %x0 y0 x1 y1 xc yc y1-yc x1-xc r 3 1 roll atan % x0 y0 x1 y1 xc yc r a1 6 index 3 index sub % x0 y0 x1 y1 xc yc r a1 y0-yc 8 index 5 index sub % x0 y0 x1 y1 xc yc r a1 y0-yc x0-xc atan % x0 y0 x1 y1 xc yc r a1 a2 exch arcn % x0 y0 x1 y1 pop pop pop pop } bind executeonly def /emptydict 0 dict readonly def /Highlight { //ValidateAP exec { //true } { 0 setlinecap dup annotsetcolor { /QuadPoints knownoget { aload length 8 idiv { 6 -2 roll 2 copy moveto //highlight-arc exec 2 copy lineto //highlight-arc exec closepath } repeat PDFusingtransparency { //emptydict % If we get an error, just emit an empty box { pathbbox } stopped { 0 0 0 0 } if 2 index add exch 3 index add exch .begintransparencygroup /Multiply .setblendmode fill .endtransparencygroup } { % for -dNOTRANSPARENCY stroke newpath } ifelse } if } if //false } ifelse } bind executeonly def currentdict /emptydict undef currentdict /highlight-arc undef /Squiggly { //ValidateAP exec { //true } { //startannottransparency exec dup annotsetcolor { dup calc_annot_scale 2 copy mul 0 ne { scale /QuadPoints knownoget { aload length 8 idiv { gsave 8 copy moveto lineto 4 2 roll lineto lineto closepath clip newpath //quadpoints2basis exec 6 -2 roll translate % adjust for x0 y0 % x1-x0 y1-y0 x2-x0 y2-y0 1 index 56 div 1 index 56 div translate % zigzag box is 1/56 up 1 index 72 div 1 index 72 div translate % the line in the box is 1/72 up 2 copy dup mul exch dup mul add sqrt % x1-x0 y1-y0 x2-x0 y2-y0 |p2| 4 index dup mul 4 index dup mul add sqrt % x1-x0 y1-y0 x2-x0 y2-y0 |p2| |p1| dup 0 gt 2 index 0 gt and { div % x1-x0 y1-y0 x2-x0 y2-y0 |p2|/|p1|=p12 dup 1 exch div 4 mul 1 add cvi exch 6 2 roll % cnt p12 x1-x0 y1-y0 x2-x0 y2-y0 4 2 roll % cnt p12 x2-x0 y2-y0 x1-x0 y1-y0 4 index mul exch 4 index mul exch % cnt p12 x2-x0 y2-y0 (x1-x0)*p12 (y1-y0)*p12 4 2 roll 0 0 6 array astore concat % cnt p12 1 40 div 1 72 div scale pop % cnt 0 0 moveto 1 setlinecap 1 setlinejoin 1 setlinewidth { 5 10 lineto 10 0 lineto 10 0 translate } repeat stroke } { 6 { pop } repeat } ifelse grestore } repeat } if } { pop pop ( **** Error: ignoring annotation with scale factor of 0\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror } ifelse } if //endannottransparency exec //false } ifelse } bind executeonly def /Text { //ValidateAP exec { //true } { //startannottransparency exec dup calc_annot_scale 2 copy mul 0 ne { scale annotrect 4 2 roll translate exch pop % Draw a page icon 0.5 exch 18.5 sub translate 1 setlinewidth 0.75 setgray 0.5 -1 moveto 10 -1 lineto 15 4 lineto 15 17.5 lineto stroke 0 0 moveto 9 0 lineto 14 5 lineto 14 18 lineto 0 18 lineto closepath gsave .5 setgray fill grestore 0 setgray stroke 3 8 moveto 7.5 8 lineto 3 11 moveto 10 11 lineto 3 14 moveto 10 14 lineto 9 0 moveto 9 5 lineto 14 5 lineto stroke } { pop pop ( **** Error: ignoring annotation with scale factor of 0\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror } ifelse //endannottransparency exec //false } ifelse } bind executeonly def /FreeText { //ValidateAP exec { //true } %% We either have no appearance, or its invalid, make one up. { gsave //startannottransparency exec dup annotrect rectclip dup /CA knownoget { dup .setstrokeconstantalpha .setfillconstantalpha } if dup /ca knownoget { dup .setstrokeconstantalpha .setfillconstantalpha } if dup /C knownoget { dup length 4 eq { aload pop setcmykcolor //true }{ dup length 3 eq { aload pop setrgbcolor //true }{ dup length 1 eq { aload pop setgray //true } { dup length 0 eq { pop //false }{ ( **** Error: invalid color specified for FreeText annotation /C entry) pdfformaterror ( Output may be incorrect.\n) pdfformaterror //false } ifelse } ifelse } ifelse } ifelse }{ //false } ifelse { dup annotrect 5 index /RD knownoget { applyRD } if rectfill } if %% get and process the default appearance string, if we don't have one, use a default /DA_Action_Dict << /Tf { exch dup /Helv eq { pop /Helvetica dup findfont } {dup findfont}ifelse % re-encode the font to PDFDocEncoding dup length dict begin { 1 index /FID ne 2 index /UniqueID ne and { def } { pop pop } ifelse } forall /Encoding /PDFDocEncoding /Encoding findresource def /FontName /Helvetica-PDFDocEncoding def currentdict end definefont exch scalefont setfont } /r {aload pop setrgbcolor} % Can't find this actually defined anywhere, but Acrobat seems to honour it :-( /rg {setrgbcolor} /RG {setrgbcolor} /G {setgray} /g {setgray} /k {setcmykcolor} /K {setcmykcolor} >> def % Set some sane defaults, in case the /DA does not. 0 setgray /Helvetica findfont % re-encode the font to PDFDocEncoding dup length dict begin { 1 index /FID ne 2 index /UniqueID ne and { def } { pop pop } ifelse } forall /Encoding /PDFDocEncoding /Encoding findresource def /FontName /Helvetica-PDFDocEncoding def currentdict end /Helvetica-PDFDocEncoding exch definefont 12 scalefont setfont dup /DA knownoget { length string /tempstr exch def dup /DA get tempstr copy pop gstate mark { { %% This is kind of ugly, we use token to process the string %% and process each token separately. tempstr token { exch /tempstr exch def %% If the token is a name %% dup type /nametype eq { %% Is it a name we want to take actionon dup DA_Action_Dict exch known { DA_Action_Dict exch get exec }{ %% Its not a name we know, is it executable dup xcheck {exec} if } ifelse }{ %% Not a name, just make it executable and execute it cvx exec }ifelse }{ exit }ifelse } loop } stopped {cleartomark setgstate} {cleartomark pop} ifelse } if %% draw the border, if we don't have a border style dictionary, draw a default one. dup /BS knownoget { pop dup drawborder }{ newpath 0 setgray 1 setlinewidth dup annotrect 5 index /RD knownoget { applyRD 4 -1 roll 4 -1 roll 4 -1 roll 4 -1 roll 4 2 roll } { 4 -1 roll 1 add 4 -1 roll 1 add 4 -1 roll 2 sub 4 -1 roll 2 sub 4 2 roll }ifelse moveto currentpoint exch 3 index add exch lineto currentpoint 2 index add lineto exch currentpoint 3 1 roll exch sub exch lineto currentpoint 3 -1 roll sub lineto stroke }ifelse gsave % in case we rotate the contents %% Start the current point at the top left of the annotation Rect %% dup /Rotate knownoget % x y w h - x' w' x' y' { dup 90 eq { pop dup annotrect 5 index /RD knownoget { applyRD } if exch pop 3 -1 roll 2 index moveto 90 rotate 1 index add } { dup 180 eq { pop dup annotrect 5 index /RD knownoget { applyRD } if pop 3 -1 roll 1 index add -1 mul exch 1 index -1 mul 4 -1 roll moveto 180 rotate 1 index add }{ 270 eq { dup annotrect 5 index /RD knownoget { applyRD } if dup 4 -1 roll add 3 -1 roll 3 index add exch moveto 270 rotate exch pop currentpoint pop dup 3 -1 roll add }{ dup annotrect 5 index /RD knownoget { applyRD 3 -1 roll add 2 index exch moveto 1 index add }{ 4 -1 roll 2 add 4 -1 roll 2 add 4 -1 roll 4 sub 4 -1 roll 4 sub 3 -1 roll add 2 index exch moveto 1 index add } ifelse } ifelse } ifelse } ifelse }{ dup annotrect 5 index /RD knownoget { applyRD 3 -1 roll add 2 index exch moveto 1 index add }{ 4 -1 roll 2 add 4 -1 roll 2 add 4 -1 roll 4 sub 4 -1 roll 4 sub 3 -1 roll add 2 index exch moveto 1 index add } ifelse } ifelse %% Get the Contents string, if we don't have one, we're done %% 2 index /Contents knownoget { dup length 0 gt { PDFusingtransparency { .begintransparencytextgroup } if %% Check for UTF16-BE, we probably don't work properly with this yet. %% (If the string is less than 4 bytes its either not UTF16-BE or it is %% but has no actual content) dup length 4 ge { dup 0 get 254 eq 1 index 1 get 255 eq and }{ //false } ifelse { /FallBackFont /Identity-UTF16-H [/CIDFallBack] composefont 12 scalefont setfont dup length 2 div 1 sub 0 1 3 -1 roll { %% llx urx (string) index 1 index exch 2 mul 2 getinterval %% llx urx (string) (substring) dup stringwidth pop currentpoint pop add 3 index gt { currentpoint exch pop 4 index exch 12 sub moveto } if show } for pop } { %% Heuristic to determine the height (ascender to descender) of the text %% for when we move down a line. gsave /..TextHeight (Hy) //false charpath pathbbox exch pop exch sub exch pop def grestore %% and use it immediatley to start the text one line down %% currentpoint ..TextHeight sub moveto %% Now we process each character code in the string. If we find %% a /r/ or /n then we drop a line. If the character would end up %% outside the Annot Rect, then we drop a line before showing it. %% dup length 1 sub 0 1 3 -1 roll { %% llx urx (string) index 1 index exch get %% llx urx (string) int dup 10 eq 1 index 13 eq or { pop currentpoint exch pop 3 index exch ..TextHeight sub moveto } { 1 string dup 0 4 -1 roll put dup %% llx urx (string) (int) (int) stringwidth pop currentpoint pop add 3 index gt { currentpoint exch pop 4 index exch ..TextHeight sub moveto } if show } ifelse } for pop }ifelse PDFusingtransparency { .endtransparencytextgroup } if } { pop } ifelse } if pop pop grestore % in case the contents were rotated dup /CL knownoget { dup length 6 eq { dup aload pop pop pop } { dup length 4 eq { dup aload pop } { pop 0 } ifelse } ifelse 4 2 roll exch 4 -1 roll sub 3 1 roll exch sub atan exch aload pop moveto lineto lineto currentpoint % stroke % 0 1 0 setrgbcolor moveto currentpoint translate 0 0 moveto 360 exch sub rotate currentpoint -5 -8 rlineto moveto 5 -8 rlineto stroke } if //endannottransparency exec //false grestore } ifelse } bind executeonly def /frame { { 255 div } forall setrgbcolor -95 -25 translate 2 190 atan rotate { 6 0 moveto 190 0 190 6 6 arct 190 47 184 47 6 arct 0 47 0 41 6 arct 0 0 6 0 6 arct closepath 10 4 moveto 185 4 185 9 5 arct 185 43 180 43 5 arct 5 43 5 38 5 arct 5 4 9 4 5 arct closepath eofill } gsave 1 -1 translate 0.75 setgray dup exec grestore exec } bind executeonly def % (text) y h -> - /text { PDFusingtransparency { .begintransparencytextgroup } if /Times-Bold findfont % re-encode the font to PDFDocEncoding dup length dict begin { 1 index /FID ne 2 index /UniqueID ne and { def } { pop pop } ifelse } forall /Encoding /PDFDocEncoding /Encoding findresource def /FontName /Times-Bold-PDFDocEncoding def currentdict end /Times-Bold-PDFDocEncoding exch definefont exch scalefont setfont % (text) y gsave 0 0 moveto 1 index //false charpath flattenpath pathbbox pop exch pop sub 2 div grestore 95 add exch moveto gsave 1 -1 rmoveto 0.75 setgray dup show grestore show PDFusingtransparency { .endtransparencytextgroup } if } bind executeonly def /red <ef4023> readonly def /green <3fae49> readonly def /blue <0072bc> readonly def /stamp_dict 14 dict begin /Approved { //green //frame exec (APPROVED) 13 30 //text exec } bind executeonly def /AsIs { //red //frame exec (AS IS) 13 30 //text exec } bind executeonly def /Confidential { //red //frame exec (CONFIDENTIAL) 17 20 //text exec } bind executeonly def /Departmental { //blue //frame exec (DEPARTMENTAL) 17 20 //text exec } bind executeonly def /Draft { //red //frame exec (DRAFT) 13 30 //text exec } bind executeonly def /Experimental { //blue //frame exec (EXPERIMENTAL) 17 20 //text exec } bind executeonly def /Expired { //red //frame exec (EXPIRED) 13 30 //text exec } bind executeonly def /Final { //red //frame exec (FINAL) 13 30 //text exec } bind executeonly def /ForComment { //green //frame exec (FOR COMMENT) 17 20 //text exec } bind executeonly def /ForPublicRelease { //green //frame exec (FOR PUBLIC) 26 18 //text exec (RELEASE) 8.5 18 //text exec } bind executeonly def /NotApproved { //red //frame exec (NOT APPROVED) 17 20 //text exec } bdef /NotForPublicRelease { //red //frame exec (NOT FOR) 26 18 //text exec (PUBLIC RELEASE) 8.5 18 //text exec } bind executeonly def /Sold { //blue //frame exec (SOLD) 13 30 //text exec } bind executeonly def /TopSecret { //red //frame exec (TOP SECRET) 14 26 //text exec } bind executeonly def currentdict end readonly def {/text/frame/red/green/blue} {currentdict exch undef} forall /Stamp { //ValidateAP exec { //true } { //startannottransparency exec dup calc_annot_scale 2 copy mul 0 ne { scale % translate to the center of Rect dup annotrect 4 2 roll % dx dy x0 y0 2 index 2 div add exch 3 index 2 div add exch translate % dx dy 50 div exch 190 div .min dup 0.0 eq {pop 1.0} if dup scale /Name knownoget not { /Draft } if //stamp_dict 1 index known not { exch pop /Draft exch } if //stamp_dict exch get exec } { pop pop ( **** Error: ignoring annotation with scale factor of 0\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror } ifelse //endannottransparency exec //false } ifelse } bind executeonly def /Popup { dup /Open oknown { dup /Open get { //ValidateAP exec { //true } { gsave //startannottransparency exec newpath 0.05 setlinewidth dup /Parent .knownget { oforce } { dup /P .knownget { oforce } { dup } ifelse } ifelse /C .knownget { aload pop }{ 1 1 0 }ifelse setrgbcolor dup /Rect get dup aload pop 2 index sub exch 3 index sub exch 4 copy gsave 1 setgray rectfill grestore gsave 0 setgray rectstroke grestore 1 index /Parent .knownget { oforce }{ 1 index /P .knownget { oforce }{ 1 index } ifelse }ifelse dup /Contents .knownget { gsave PDFusingtransparency { .begintransparencytextgroup } if 0 setgray /Helvetica findfont % re-encode the font to PDFDocEncoding dup length dict begin { 1 index /FID ne 2 index /UniqueID ne and { def } { pop pop } ifelse } forall /Encoding /PDFDocEncoding /Encoding findresource def /FontName /Helvetica-PDFDocEncoding def currentdict end /Helvetica-PDFDocEncoding exch definefont 9 scalefont setfont 2 index aload pop 3 1 roll pop pop 30 sub exch 5 add exch moveto show PDFusingtransparency { .endtransparencytextgroup } if grestore } if exch dup aload pop 3 -1 roll pop exch 2 index sub -15 4 copy rectfill 0 setgray rectstroke exch /T .knownget { gsave PDFusingtransparency { .begintransparencytextgroup } if 0 setgray /Helvetica findfont % re-encode the font to PDFDocEncoding dup length dict begin { 1 index /FID ne 2 index /UniqueID ne and { def } { pop pop } ifelse } forall /Encoding /PDFDocEncoding /Encoding findresource def /FontName /Helvetica-PDFDocEncoding def currentdict end /Helvetica-PDFDocEncoding exch definefont 9 scalefont setfont dup stringwidth pop 2 index aload pop pop exch pop exch sub exch sub 2 div 2 index aload pop 3 1 roll pop pop 11 sub 3 1 roll add exch moveto show PDFusingtransparency { .endtransparencytextgroup } if grestore } if grestore //endannottransparency exec //false } ifelse } { pop //false }ifelse } { pop //false }ifelse } bind executeonly def /Redact { %% Redact annotations are part of a process, a Redact annotation is only present %% until the content is removed, before that the content should be present and %% I beleive we should print it. So take no action for Redact annotations if they %% have no appearance. //ValidateAP exec { //true } { //false } ifelse } bind executeonly def currentdict /startannottransparency undef currentdict /endannottransparency undef currentdict /ValidateAP undef currentdict /quadpoints2basis undef currentdict /drawellipse undef currentdict end readonly def /.PDFDrawAnnotType? { //false exch /ShowAnnotTypes where { /ShowAnnotTypes get { dup /* eq exch 2 index eq or { pop //true exch exit } if } forall pop } {pop pop //true} ifelse } bind executeonly def /.PDFPreserveAnnotType? { //false exch /PreserveAnnotTypes where { /PreserveAnnotTypes get { dup /* eq exch 2 index eq or { pop //true exch exit } if } forall pop } {pop pop //true} ifelse } bind executeonly def /drawannot { % <annot> drawannot - dup annotvisible { gsave dup dup /Subtype knownoget { dup //.PDFDrawAnnotType? exec { //drawannottypes exch .knownget { exec } { //true } ifelse { dup calc_annot_scale 2 copy mul 0 ne { 3 -1 roll drawwidget } { ( **** Error: ignoring annotation with scale factor of 0\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror }ifelse % Draw rejected annots as widgets } if % type known } { pop }ifelse } { pop ( **** Error: Ignoring /Annot dict without required /Subtype entry.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror } ifelse grestore } if pop % annotvisible } bind executeonly def currentdict /drawannottypes undef % Draw an annotation. /loadannot { dup /AP .knownget { % <<Annot dict>> <<Appearance dictionary>> true | false oforce dup { % <<Annot dict>> <<Appearance dict>> /Key <</Key dict>> oforce % <<Annot dict>> <<Appearance dict>> /Key <<resolved /Key dict>> %% %% Check to see if the apperance key has a simple stream or a dictionary of states %% dup /Subtype known % <<Annot dict>> <<Appearance dict>> /Key <<resolved /Key dict>> bool { %% Simple appearance stream DoAppearance % <<Annot dict>> <<Appearance dict>> /Key 2 index % <<Annot dict>> <<Appearance dict>> /Key <<Annot dict>> /AP << % <<Annot dict>> <<Appearance dict>> /Key <<Annot dict>> /AP << 4 -1 roll MakeAppearanceName cvx cvn >> put % <<Annot dict>> <<Appearance dict>> } { %% dictionary of states <<Annot dict>> <<Appearance dict>> /Key <<appearance states dict>> dup % <<Annot dict>> <<Appearance dict>> /Key <<appearance states dict>> <<appearance states dict>> { % <<Annot dict>> <<Appearance dict>> /Key <<appearance states dict>> /StateKey <<State dictionary>> oforce % <<Annot dict>> <<Appearance dict>> /Key <<appearance states dict>> /StateKey <<resolved State dictionary>> DoAppearance % <<Annot dict>> <<Appearance dict>> /Key <<appearance states dict>> /StateKey 1 index exch % <<Annot dict>> <<Appearance dict>> /Key <<appearance states dict>> <<appearance states dict>> /StateKey MakeAppearanceName cvx cvn % <<Annot dict>> <<Appearance dict>> /Key <<appearance states dict>> <<appearance states dict>> /StateKey {} put % <<Annot dict>> <<Appearance dict>> /Key <<appearance states dict>> } forall put % <<Annot dict>> <<Appearance dict>> /Key dup }ifelse } forall pop % <<Annot dict>> } if %% Parent (or /P) references will be incorrect. Remove them %% for now as they are optional. dup /Popup known {dup /Popup undef} if dup /IRT known {dup /IRT undef} if dup /RT known {dup /RT undef} if dup /P known {dup /P undef} if dup /Parent known {dup /Parent undef} if %% Resolve any indirect references. May need further work :-( { %% We know /AP doesn't need processing, we handled that above... 1 index /AP eq not { dup {oforce} stopped not {exch pop} if dup type /dicttype eq{ dup { dup {oforce} stopped not {exch pop} if 2 index 3 1 roll put } forall Removepdfobj# } if dup type /arraytype eq { 0 1 2 index length 1 sub{ dup 2 index exch get dup {oforce} stopped not {exch pop} if 2 index 3 1 roll put } for } if } if } forall } bind executeonly def /ApplyCTMToQuadPoints { %% Nasty hackery here really. We need to undo the HWResolution scaling which %% is done by pdfwrite. Default is 720 dpi, so 0.1. We also need to make %% sure that any translation of the page (because its been rotated for example) %% is also modified by the requisite amount. SO we ned to calculate a matrix %% which does the scaling and concatenate it with the current matrix. %% Do this inside a gsave/grestore pair to avoid side effects! gsave currentpagedevice /HWResolution get aload pop exch 72 exch div exch 72 exch div matrix 3 1 roll 2 index 3 3 -1 roll put 1 index 0 3 -1 roll put matrix currentmatrix exch matrix concatmatrix setmatrix oforce %% QuadPoints are given as 'n' sequences of 8 numbers. mark exch aload counttomark 1 roll counttomark 1 sub 2 div cvi { transform counttomark 1 sub 2 roll } repeat counttomark -1 roll astore exch pop % the mark grestore } bind executeonly def /preserveannottypes 20 dict begin /Circle {mark exch loadannot /ANN pdfmark //false} bind executeonly def /FileAttachment {mark exch loadannot /ANN pdfmark //false} bind executeonly def /FreeText {mark exch loadannot /ANN pdfmark //false} bind executeonly def /Highlight { mark exch dup /QuadPoints .knownget { 1 index /QuadPoints 3 -1 roll ApplyCTMToQuadPoints put } if loadannot /ANN pdfmark //false } bind executeonly def /Ink {mark exch loadannot /ANN pdfmark //false} bind executeonly def /PolyLine {mark exch loadannot /ANN pdfmark //false} bind executeonly def /Line {mark exch loadannot /ANN pdfmark //false} bind executeonly def /Link { /NO_PDFMARK_DESTS where {pop NO_PDFMARK_DESTS not}{//true}ifelse { mark exch dup /BS knownoget { << exch { oforce } forall >> /BS exch 3 -1 roll } if dup /F knownoget { /F exch 3 -1 roll } if dup /C knownoget { /Color exch 3 -1 roll } if dup /Rect knownoget { /Rect exch 3 -1 roll } if dup /Border knownoget { dup type /arraytype eq { dup length 3 lt } { //true } ifelse { pop [ 0 0 0 ] % Following AR5 use invisible border. } if /Border exch 3 -1 roll } if dup /A knownoget { dup /URI known { /A mark 3 2 roll % <<>> /A [ <<action>> { oforce } forall .dicttomark 3 2 roll } { dup /S knownoget { %% Because we process GoTo Destinations into absolute references in the PDF file %% we need to resolve the /D or /Dest. However, we must *not* do this for %% GoToR Destinations because (obviously) those are in a different file and %% we cannot resolve them into absolute references. We don't need to anyway %% because that file must already have a named destination. dup /GoTo eq { pop dup /D knownoget { exch pop exch dup length dict copy dup /Dest 4 -1 roll put } if }{ dup /GoToR eq { pop /A mark % <<..action dict..>> /A [ 3 2 roll % /A [ <<..action dict..>> { oforce } forall .dicttomark 3 2 roll }{ dup /Launch eq { pop /A mark % <<..action dict..>> /A [ 3 2 roll % /A [ <<..action dict..>> { oforce } forall .dicttomark 3 2 roll }{ /Named eq { /N knownoget { namedactions exch .knownget { exec { pop ( **** Warning: Ignoring a named action pointing out of the document page range.\n) pdfformatwarning } { /Page exch 3 -1 roll } ifelse } if } if } if }ifelse } ifelse } ifelse } if } ifelse } if { linkdest } stopped { cleartomark ( **** Warning: Link annotation points out of the document page range.\n) pdfformatwarning } { pop { %% Need to remove any '/.gs.pdfobj# key/value pairs from any dictionaries counttomark array astore dup length 1 sub 0 1 3 -1 roll { dup 2 index exch get Removepdfobj# 2 index 3 1 roll put } for aload pop /LNK pdfmark } stopped {cleartomark} if } ifelse }{pop} ifelse //false } bind executeonly def %% We don't handle movies correctly, so don't try to preserve them %/Movie {mark exch loadannot /ANN pdfmark //false} bind executeonly def /Popup {mark exch loadannot /ANN pdfmark //false} bind executeonly def /Sound {mark exch loadannot /ANN pdfmark //false} bind executeonly def /Square {mark exch loadannot /ANN pdfmark //false} bind executeonly def /Stamp {mark exch loadannot /ANN pdfmark //false} bind executeonly def /StrikeOut { mark exch dup /QuadPoints .knownget { 1 index /QuadPoints 3 -1 roll ApplyCTMToQuadPoints put } if loadannot /ANN pdfmark //false } bind executeonly def /Squiggly { mark exch dup /QuadPoints .knownget { 1 index /QuadPoints 3 -1 roll ApplyCTMToQuadPoints put } if loadannot /ANN pdfmark //false } bind executeonly def /Text {mark exch loadannot /ANN pdfmark //false} bind executeonly def /TrapNet {mark exch loadannot /ANN pdfmark //false} bind executeonly def /Underline { mark exch dup /QuadPoints .knownget { 1 index /QuadPoints 3 -1 roll ApplyCTMToQuadPoints put } if loadannot /ANN pdfmark //false } bind executeonly def %% Widget annotations are only used with AcroForms, and since we don't preserve AcroForms %% we don't want to preserve widget annotations either, because the consumer of the new %% PDF won't know what values they should take. So we draw widget annotations instead. If we %% ever preserve AcroForms then we should alter this to preserve Widgets as well. %% simply chane "drawannot" to "mark exch loadannot /ANN pdfmark" /Widget {mark exch {drawannot} PDFSTOPONERROR {exec}{stopped {(Error: Ignoring invalid annotation, output may be incorrect.\n) pdfformaterror} if} ifelse cleartomark //false} bind executeonly def currentdict end readonly def /preserveannot { % <annot> preserveannot - dup /.gs.pdfobj# known { dup /.gs.pdfobj# undef } if gsave dup dup /Subtype knownoget { dup //.PDFPreserveAnnotType? exec { //preserveannottypes exch .knownget { exec } { //true } ifelse { dup annotvisible { dup calc_annot_scale 2 copy mul 0 ne { 3 -1 roll drawwidget } { ( **** Error: ignoring annotation with scale factor of 0\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror }ifelse % Draw rejected annots as widgets } { pop }ifelse } if } { % Not preserving this type of annotation % discard teh Subtype pop % copy the Annot dictionary and try drawing it instead dup drawannot } ifelse % type known } { pop ( **** Error: Ignoring /Annot dict without required /Subtype entry.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror } ifelse grestore } bind executeonly def currentdict /preserveannottypes undef currentdict /.PDFDrawAnnotType? undef % ============================ AcroForm fields ============================ % % Get an attribure of the 0th annotation of a node /annot_oget { % <annot> /Name annot_oget <value> 1 index /Kids knownoget { 0 oget exch oget exch pop } { oget } ifelse } bind executeonly def % All procedures have the signature: % <acroform> <field> <annot|field> foo <acroform> <field> <annot|field> /draw_terminal_field_dict 4 dict begin /Btn { 1 index /Tf pget not { 0 } if dup 16#20000 and 0 ne { pop % Push button dup /AP known { 1 1 2 index drawwidget } { (Push button without appearance stream is not yet implemented) = } ifelse } { 16#10000 and 0 ne { % Radio button dup /AP known { 1 index /Kids oget { 1 1 3 -1 roll drawwidget } forall } { (Radio button without appearance stream is not yet implemented) = } ifelse } { % Checkbox dup /AP known { dup 1 1 3 -1 roll drawwidget } { (CkeckBox without appearance stream is not yet implemented) = } ifelse } ifelse } ifelse } bind executeonly def /Tx { dup /AP known { dup 1 1 3 -1 roll drawwidget } { %% If we don't have a NeedApperances, treat as true, because Acrobat %% always regenerates Appearances anyway. 2 index /NeedAppearances knownoget not { //true } if { dup /AP << /N 10 dict dup cvx begin >> put /Subtype /Form def /BBox [ 0 0 4 index /Rect oget { oforce } forall 3 -1 roll sub abs 3 1 roll sub abs exch ] def /Resources 3 index /DR pget not { 0 dict } if def /File 1000 string dup 3 1 roll def /Length 1000 def % <acroform> <field> <annot> (string) /NullEncode filter % <acroform> <field> <annot> file dup (BT ) writestring 2 index /DA pget not { () } if [ exch { token { dup /Tf eq { 2 index 0 eq { /BBox load 3 get 0.75 mul % empirical constant 4 -1 roll pop 3 1 roll } if } if exch } { exit } ifelse } loop ] { 1 index exch write== } forall dup 3 index /MaxLen pget not { 0 } if write= dup 3 index /V pget not { 3 index /DV pget not { () } if } if write== dup 3 index /Ff pget not { 0 } if write= dup 3 index /Q pget not { 0 } if write= dup (Tform ET) write= end closefile % <acroform> <field> <annot> dup 1 1 3 -1 roll drawwidget } if } ifelse } bind executeonly def /Ch { dup /AP known 3 index /NeedAppearances knownoget not { //true } if not and { dup 1 1 3 -1 roll drawwidget } { %% If we don't have a NeedApperances, treat as true, because Acrobat %% always regenerates Appearances anyway. 2 index /NeedAppearances knownoget not { //true } if { dup /AP << /N 10 dict dup cvx begin >> put /Subtype /Form def /BBox [ 0 0 4 index /Rect oget { oforce } forall 3 -1 roll sub abs 3 1 roll sub abs exch ] def /Resources 3 index /DR pget not { 0 dict } if def /File 1000 string dup 3 1 roll def /Length 1000 def % <acroform> <field> <annot> (string) /NullEncode filter % <acroform> <field> <annot> file dup (BT ) writestring 2 index /DA pget not { () } if [ exch { token { dup /Tf eq { 2 index 0 eq { /BBox load 3 get 0.75 mul % empirical constant 4 -1 roll pop 3 1 roll } if } if exch } { exit } ifelse } loop ] { 1 index exch write== } forall dup 3 index /MaxLen pget not { 0 } if write= dup 3 index /V pget not { 3 index /DV pget not { () } if } if write== dup 3 index /Ff pget not { 0 } if write= dup 3 index /Q pget not { 0 } if write= dup (Tform ET) write= end closefile % <acroform> <field> <annot> dup 1 1 3 -1 roll drawwidget } if } ifelse } bind executeonly def /Sig { (Sig is not yet implemened ) //== exec } bind executeonly def currentdict end def /draw_terminal_field { % <field> draw_terminal_field - dup /Kids knownoget { 0 oget } { dup } ifelse dup /P knownoget { /Page load eq { //draw_terminal_field_dict 2 index /FT pget not { 0 } if .knownget { exec } if } if } if pop pop } bind executeonly def % We distinguish 4 types of nodes on the form field tree: % - non-terminal field - has a kid that refers to the parent (or anywhere else) % - terminal field with separate widget annotations - has a kid that doesn't have a parent % - terminal field with a merged widget annotation - has no kids % - widget annotation - has /Subtype and /Rect % % The recursive enumeration of the form fields doesn't descend into widget annotations. /draw_form_field { % <field> draw_form_field - dup type /dicttyype eq { % File for Bug692447 has 'null' Fields entries % This matches what pdf_main process_trailer_attrs dup /Kids knownoget { % field [] dup length 0 gt { dup 0 oget /Parent knownoget { % field [] kid pop % mon-terminal field % field [] exch pop % [] { oforce draw_form_field } forall } { pop draw_terminal_field % separate annots % - } ifelse } { ( **** Error: Ignoring empty /Kids array in Form field.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror } ifelse } { draw_terminal_field % merged annotation % - } ifelse } if } bind executeonly def /draw_acro_form { % <form> draw_acro_form - dup /Fields knownoget { { oforce draw_form_field } forall } if pop } bind executeonly def currentdict /draw_terminal_field_dict undef end % pdfdict end % GS_PDF_ProcSet .setglobal gs_pdf_e.ps 0000644 00000003024 15030647507 0006664 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % Define the PDFDoc encoding vector. /currentglobal where { pop currentglobal { setglobal } //true setglobal } { { } } ifelse /PDFDocEncoding ISOLatin1Encoding 0 24 getinterval aload pop /breve /caron /circumflex /dotaccent /hungarumlaut /ogonek /ring /tilde ISOLatin1Encoding 32 7 getinterval aload pop /quotesingle ISOLatin1Encoding 40 5 getinterval aload pop /hyphen ISOLatin1Encoding 46 50 getinterval aload pop /grave ISOLatin1Encoding 97 31 getinterval aload pop % \20x /bullet /dagger /daggerdbl /ellipsis /emdash /endash /florin /fraction /guilsinglleft /guilsinglright /minus /perthousand /quotedblbase /quotedblleft /quotedblright /quoteleft /quoteright /quotesinglbase /trademark /fi /fl /Lslash /OE /Scaron /Ydieresis /Zcaron /dotlessi /lslash /oe /scaron /zcaron /.notdef % \24x /Euro ISOLatin1Encoding 161 12 getinterval aload pop /.notdef ISOLatin1Encoding 174 82 getinterval aload pop 256 packedarray .defineencoding exec pdf_rbld.ps 0000644 00000050000 15030647507 0006666 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % pdf_rbld.ps - Rebuilding of broken PDF files (xref errors) % This module contains routines that are used if we detect an error % while reading the xref tables. These routines will scan the file and % build an xref table by finding the objects. We also need to find the % appropriate trailer dictionary. Note: One procedure is also used % even if we do not need to rebuild a PDF file. % % This module cannot rebuild a PDF file which has had errors created inside % of objects or binary data streams. It often succeeds with files that % have had its end of lines converted between unix and dos versions. % if true --> we have an object with duplicate object and generation numbers. /dup_obj_gen_num //false def % Note: This procedure is also used by non-rebuild code. % Store a line in the xref array (Actually Objects and Generations arrays) % <obj num> (strm num> <obj loc> <gen num> <rebuild> % setxrefentry <obj num> strm num> <obj loc> <gen num> /setxrefentry { 5 1 roll dup 65535 or 65535 ne { ( **** Error: Generation number out of 0..65535 range, assuming 0.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror pop 0 } if % We store generation numbers as value + 1 % We reserve 0 to indicate an free xref entry 1 add % increment generation number % To save space, generations numbers are stored in a string unless we % find a generation number greater than 255. If so then transfer to % an array. dup 255 gt { Generations type /stringtype eq { % Convert Generations to an array. Generations length array dup % Create new array 0 1 2 index length 1 sub { % Copy from old string to new array Generations 1 index get put dup } for pop /Generations exch store % Save new Generations array } if } if % Verify that the new values are for a new object. If the current % entry is null then we have a new entry. Objects 4 index get //null eq { ObjectStream 4 index 4 index cvx put % Save ObjectStream object number Objects 4 index 3 index cvx put % Save object location Generations 4 index 2 index put % Save geenration number } { % Verify that the new entry has at least as high a generaton number % We accept equal entry number because we have found PDF files in % which there are multiple objects with the same object and entry % numbers. The normal xref logic only accepts the first such % entry that it finds. However the 'rebuild PDF' logic can find % both such entries. The correct one is usually the last one. Generations 4 index get 1 index le { %% Check if the object we already found was at the locaton specified %% in the original xref (now stored in Orig_Objects). If so, prefer %% that offset, otherwise prefer the later object. %% NB check first to see that the object number is in the range of the original %% xref. If it isn't, set the 'original' Offset to 0. 3 index Orig_Objects length le {Orig_Objects 4 index get}{0}ifelse Objects 5 index get eq not { ObjectStream 4 index 4 index cvx put % Save ObjectStream object number Objects 4 index 3 index cvx put % Save object location Generations 4 index 2 index put % Save geenration number } if } if % Set error flag if we have equal object and generation numbers Generations 4 index get 1 index eq { /dup_obj_gen_num //true def } if } 8 -1 roll { ifelse } { pop if } ifelse % Run 'else' only when rebuilding. } bind executeonly def % Print the contents of the xref array. This actually consists of three % arrays (Objects, Generations, and ObjectStream). /print_xref % - print_xref - { 0 1 Objects length 1 sub % stack: 0 1 <number of objects - 1> { dup =only % print object number ( ) print dup Generations exch get 1 sub =only % print Generation number ( ) print dup ObjectStream exch get ==only % print ObjectStream object number ( ) print Objects exch get === % print object location } for flush } bind executeonly def % Get token from string and check its type % <string> <type> typed_token <false> % no token or not match % <string> <type> typed_token <obj> <last> <true> % matching token type % Where last is the string remainder /typed_token { exch token_nofail % get token { dup type % stack: type last token type 4 -1 roll eq { % stack: last token bool exch //true % desired object found - set exit status } { pop pop //false % not type - clear stack, set exit status } ifelse } { pop //false % no token - pop type, set exit status } ifelse % check if we got token } bind executeonly def % Allocate space for post_eof_count to be bound into procedures below. /post_eof_count 0 def % We want the location of the trailer dictionary at the start of file. % First we will find the xref. Then we will skip over the xref entries % to the trailer. /search_start_trailer % - search_start_trailer <trailer loc> { % Read the first 300 bytes and check for xref PDFfile 0 setfileposition PDFfile bytesavailable post_eof_count sub % location of end of data 300 .min % block size to read dup string 0 1 4 -1 roll 1 sub { 2 copy PDFfile read pop put pop } for (xref) search { % found 'xref' exch pop exch pop length 4 add PDFfile exch setfileposition PDFfile token pop % get starting entry - or 'trailer' (trailer) ne { % if we do not already have 'trailer' PDFfile token pop % get number of entries % The following check could be more efficient % but broken file..... dup PDFfile fileposition PDFfile 0 setfileposition PDFfile bytesavailable exch PDFfile exch setfileposition % On the basis it requires at least 15 bytes to define an object % in PDF, if the claimed number of objects is more than the number % of bytes in the file, then it is clearly bogus, and we just give up 15 idiv lt { PDFfile token pop pop % this moves us into the middle of the first entry 25 string exch % define working string for readline { PDFfile 1 index readline pop pop } repeat % skip entries pop % pop working string PDFfile token pop pop % get 'trailer' PDFfile fileposition % get file position } { pop 0} ifelse } if } { pop 0 % no xref, should not happen, report it upstrem } ifelse } bind executeonly def %% Searches backwards from a specified point looking for a 'trailer' keyword. %% position search_earlier_trailer position or 0 %% %% Its is just possible that a 'trailer' keyword could straddle a buffer, in which case %% we wouldn't find it. Given that this only executes for broken files anyway I don't %% propose to worry about it at the moment, if anyone ever turns up an example we may %% choose to enhance this routine further. %% /search_earlier_trailer { { % position dup 0 gt { % position bool dup 65535 .min exch % block_size position 1 index sub % block_size position-block_size dup % block_size new_position new_position PDFfile exch setfileposition % block_size new position exch dup % new position block_size block_size dup string 0 1 4 -1 roll 1 sub % {2 copy PDFfile read pop put pop } for % % new_position block size (...string from file....) (trailer) search { pop { search not { exit } if pop } loop % determine where the trailer is in the file % trailer loc = end loc - remaing string length length % new_position block size string length 3 1 roll % string length new_position block size add exch sub % string length - (new_position + block size) } { pop % discard old block size pop 0 } ifelse } { pop 0 exit }ifelse %% We either have a position for a trailer, or 0 if we failed to find one dup 0 eq not { exit }if pop % renove the zero leaving the new start position } loop } bind executeonly def % We want the location of the trailer dictionary at the end of file. % We will read the last block of data and search for the final occurance % of the word 'trailer' /search_end_trailer % - search_end_trailer <trailer loc> { % Position to read block of data from the end of the file. Note: We ignore % anything past the last %%EOF since this is not PDF data. PDFfile 0 setfileposition PDFfile bytesavailable post_eof_count sub % location of end of data dup 65535 .min % block size to read % stack: <file end pos> <block size> % move file position to the start of the block 2 copy sub PDFfile exch setfileposition % read block of data dup string 0 1 4 -1 roll 1 sub { 2 copy PDFfile read pop put pop } for % search for last occurance of 'trailer' (trailer) search { pop { search not { exit } if pop } loop % determine where the trailer is in the file % trailer loc = end loc - remaing string length length sub } { pop pop 0 } ifelse } bind executeonly def % We want to find the trailer dictionary. There is a trailer dictionary % for each xref object list. We only want the trailer dictionary associated % with the first xref object list. In theory this can be anywhere in the % file. However since we are trying to repair a broken file, we cannot simply % follow the xref links. So we are falling back to a simple strategy. We % find the specified location of the first xref list. If its location is in % the first half of the file then we search for the first trailer dictionary % at the start of the file. Otherwise we search for the last trailer at the % end of the file. /search_trailer % - search_trailer - { % Find the 'startxref' and associated position at the end of the file. % Position to read block of data from the end of the file. Note: We % actually end at the end of the last %%EOF since this is the end of the % useful PDF data. (Some files contain trailing garbage.) PDFfile 0 setfileposition PDFfile bytesavailable % size of file post_eof_count sub dup % location of end of last %%EOF dup 4096 .min % block size to read % stack: <useful file size> <useful file size file> <block size> % move file position to the start of the block 2 copy sub PDFfile exch setfileposition % read block of data dup string 0 1 4 -1 roll 1 sub { 2 copy PDFfile read pop put pop } for % search for last occurance of 'startxref' //false % Assume that startxref not present exch (startxref) { search not { exit } if % Exit loop when no more startxref's pop 3 -1 roll pop //true 3 1 roll % Idicate that we have found starxref } loop exch % Exch last string and 'found' flag { % determine where the startxref is in the file % 'startxref' loc = end loc - remaing string length - 9 bytes length sub 9 sub % move the file to this position and read startxref and position % First, read the startxref token, this should not fail. PDFfile exch setfileposition PDFfile token { % Discard the startxref token and read the following token, which should be the offset. pop PDFfile token_no_close { % Now chck its an integer dup type /integertype eq not { pop % startxref not followed by integer. We will search the end of the file for trailer. PDFfilelen } if } { % startxref not followed by any token. We will search the end of the file for trailer. PDFfilelen } ifelse } { % No startxref token ? We will search the end of the file for trailer. PDFfilelen } ifelse } { % startxref not found. We will search the end of the file for trailer. pop pop PDFfilelen } ifelse % compare xref position to 1/2 the length of the file and search for trailer exch 2 div lt { search_start_trailer dup 0 eq { pop search_end_trailer } if } { search_end_trailer dup 0 eq { pop search_start_trailer } if } ifelse dup 0 eq { pop ( **** Error: Trailer dictionary not found.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror }{ % get the trailer dup PDFfile exch setfileposition % set to the specified trailer location /dictlevelcount 0 def PDFfile traileropdict .pdfrun % read trailer info { dup /Root known not { ( **** Warning: This trailer dictionary does not contain a /Root entry\n searching for a prior trailer.\n) pdfformatwarning %% remove trailer dict copy, duplicate file position, then remove the length of 'trailer' so we don't %% find the same one again.... pop dup 7 sub search_earlier_trailer }{exit}ifelse dup 0 eq { pop ( **** Error: Valid trailer not found.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror }{ PDFfile exch setfileposition % set to the specified trailer location /dictlevelcount 0 def PDFfile traileropdict .pdfrun % read trailer info } ifelse } loop /Trailer exch def pop } ifelse } bind executeonly def % This routine will determine if there is stuff after the %%EOF. There is % supposed to be only a line termination. However many real life files % contain some garbage. This routine checks how much. We then ignore this % stuff when we are scanning for objects. /determine_post_eof_count % - determine_post_eof_count <count> { % Position to read block of data from the end of the file. PDFfilelen % size of file dup 4096 .min % file_size block_size dup 3 1 roll sub % block_size file_size-block_size PDFfile exch setfileposition % block_size string PDFfile exch readstring pop % () % search for last occurance of 'startxref', '%%EOF' is often damaged (startxref) search { pop { search not { exit } if pop } loop % how much is left = remaining string length % Now search for %%EO or try to read a number after 'startxref'. (%%EO) search { pop pop } { % Look for a number after startxref { dup token { pop exch pop } if } stopped pop } ifelse length } { % Can't even find startxref, assume it's all objects pop 0 } ifelse } bind executeonly def % This routine will scan a file searaching for object locations to build % an alternate version of the data in the xref tables. % Its purpose is to provide a basis for an xref fixing facility. /search_objects % - search_objects - { % Initialize the Objects, Generations, etc. arrays Objects dup length array copy /Orig_Objects exch def initPDFobjects % reset duplicate object and generation numbers error flag /dup_obj_gen_num //false def % Determine how many bytes are in the file after the final %%EOF /post_eof_count determine_post_eof_count def % Start at the beginning of the file PDFfile 0 setfileposition % Create a working string (and also store its length on stack). We are % using a maximum size string size the logic below wants a recovered object % to fit into our working string. 65535 dup string { % Now loop through the entire file looking for objects PDFfile fileposition % save current file position % When we get near the end of the file, we use a smaller interval of % our working string to prevent reading past the end. (See comments on % EOF testing below.) PDFfile bytesavailable post_eof_count sub 10 sub dup 4 index lt { 2 index 0 3 -1 roll getinterval % near EOF, use interval of string } { pop 1 index % not near end, use full working string } ifelse % Read a line from file. If the line does not fit into our working string, % or any other error, then we will discard it. PDFfile exch { readline } //.internalstopped exec { pop pop //false } if % indicate no string if we stopped { % stack: <length> <working_str> <loc> <string> % Now that we have line, get obj num, ref num, and 'obj'. Verify that each % of these is correct type. dup (obj) search { % preliminary check for obj pop pop pop /integertype typed_token { % get obj number /integertype typed_token { % get ref number /nametype typed_token { % get 'obj' text pop % pop remaining string /obj eq { % verify name is 'obj' % make sure we have room in the arrays. We work in increments % of 20 each time we increase the size. 1 index 20 add 20 idiv 20 mul growPDFobjects % save xref parameters into ObjectStream, Objects and Generations 1 index 0 % rearrange parms for setxrefentry 4 index PDFoffset sub 3 index //true setxrefentry % save parameters pop pop pop pop % clear parameters } if % check if name is 'obj' } if % check if we got 'obj" string pop % remove ref number } if % check if we got ref number pop % remove obj number } if % check if we got object number } { pop pop } ifelse } if % check if got a string from readline pop % remove location % Check if we are approaching the end of the file. We do not want to % read past the end of the file since that closes it. We actually stop % 10-20 bytes early since there cannot be an object that close to the end. % (There is a Trailer dictionary, etc. at the end of the file.) PDFfile bytesavailable post_eof_count sub 20 lt { exit } if } loop % loop through the entire file pop pop % remove working string and its length % Output warning if we have two objects with the same object and generation % numbers. dup_obj_gen_num { ( **** Warning: There are objects with matching object and generation\n) pdfformatwarning ( **** numbers. The output may be incorrect.\n) pdfformatwarning } if currentdict /Orig_Objects undef } bind executeonly def % Print warning message because we found a problem while reading the xref % tables /print_xref_warning { ( **** Error: An error occurred while reading an XREF table.\n) pdfformaterror ( **** The file has been damaged. This may have been caused\n) pdfformaterror ( **** by a problem while converting or transferring the file.\n) pdfformaterror ( **** Ghostscript will attempt to recover the data.\n) pdfformaterror ( **** However, the output may be incorrect.\n) pdfformaterror } bind executeonly def % Attempt to recover the XRef data. This is called if we have a failure % while reading the normal XRef tables. This routine usually works % only for pre PDF1.5 versions of PDF files. /recover_xref_data % - recover_xref_data - { print_xref_warning % Print warning message count pdfemptycount sub { pop } repeat % remove anything left by readxref search_objects % Search for objects } bind executeonly def pdf_main.ps 0000644 00000525363 15030647507 0006712 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % pdf_main.ps % PDF file- and page-level operations. /.setlanguagelevel where { pop 2 .setlanguagelevel } if .currentglobal //true .setglobal pdfdict begin /GS_PDF_ProcSet dup load def % keep in pdfdict to hide it userdict /GS_PDF_ProcSet undef % Patch in an obsolete variable used by some third-party software. /#? //false def % Test whether the current output device handles pdfmark. /.writepdfmarks { % - .writepdfmarks <bool> /PdfmarkCapable /GetDeviceParam .special_op { exch pop }{ //false }ifelse systemdict /DOPDFMARKS known or } bind executeonly def % For simplicity, we use a single interpretation dictionary for all % PDF graphics execution, even though this is too liberal. /pdfopdict mark objopdict { } forall drawopdict { } forall /endstream { exit } bind executeonly (%%EOF) cvn { exit } bind executeonly % for filters /obj { ( **** Error: Content stream is not terminated by 'endstream'.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror } bind executeonly % PDF 1.1 operators /BX { /BXlevel BXlevel 1 add store } bind executeonly /EX { /BXlevel BXlevel 1 sub store } bind executeonly /PS { DOPS { cvx exec } { pop } ifelse } bind executeonly % PS disabled by default, as in pdf_draw.ps DoPS % PDF 1.2 operators /BMC { /BMClevel BMClevel 1 add store pop } bind executeonly /BDC { /BMClevel BMClevel 1 add store exch /OC eq { dup type /nametype eq { PDFfile fileposition exch % pos /Name Page /Properties rget { ocg-is-visible not { OFFlevels BMClevel dup put } if } if PDFfile exch setfileposition } { pop } ifelse } { pop } ifelse } bind executeonly /EMC { OFFlevels BMClevel 2 copy known { 2 copy undef } if 1 sub /BMClevel exch store pop } bind executeonly /MP { pop } bind /DP { pop pop } bind /- { 0 % Bug 690016 ( **** Error: Invalid operator '-' is assumed to be the number 0.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror } bind executeonly /Recursive_XObject_D 1 dict def .dicttomark readonly def % This dictionaty encapsulates all that is needed to generate pagelabel pdfmarks. % % This is provided by Leon Bottou for the benefit of the djvudigital device % which is a device developed and maintained outside of Artifex, and which is % not a contributed device. % % This device does not cope with the method used by pdfwrite to pass the pagelabels % number tree as a 'blob' of data, but requires that the page labels be passed using % a PAGELABEL pdfmark. % % We don't want to do that with pdfwrite because there is no mechanism in pdfmark syntax % to pass a tree, which means we'd have to laboriously disassemble the pdfmarks for the % page labels and rebuild a number tree for it. This would mean pattern matching each % string passed via PAGELABEL to see if it could be defined as a continuation % of the preceding string, uing prefixes. Its much easier for us just to pass the tree. % % Note that this code simply translates the PageLabels Number tree into a number of % individual PAGELABEL pdfmarks, if used for pdfwrite this would result in a number % tree which consists solely of leaf nodes, where each node has a string for its label. % This can be considerably more verbose than the shorthand possible with a Page Label % dictionary. % /pagelabeldict mark % (TEXT) .toLower (text) /.toLower { dup length 1 sub -1 0 { 1 index exch 2 copy get 2#00100000 or put } for } bind executeonly % int .cvAlpha (int in alphabetic base 26) /.cvAlpha { [ exch % construct an array of ASCII values, in reverse { % the remainder stays on the top of stack dup 0 eq { pop exit } if % quit if the value is zero dup 26 mod dup 0 eq { 26 add } if % so that the division is correct dup 64 add 3 1 roll sub 26 idiv % save the ASCII value and iterate } loop ] dup length dup string 3 1 roll dup -1 1 { % put the letters in a string 4 copy sub exch 4 -1 roll 1 sub get put } for pop pop } bind executeonly % int .cvRoman (int in capital Roman numerals) % convert a positive integer to capital Roman numerals % return a decimal string if >= 4000 /.cvRoman { dup 255 string cvs % start with the decimal representation exch 4000 lt { % convert only if Roman numerals can represent this dup length [ [ () (I) (II) (III) (IV) (V) (VI) (VII) (VIII) (IX) ] [ () (X) (XX) (XXX) (XL) (L) (LX) (LXX) (LXXX) (XC) ] [ () (C) (CC) (CCC) (CD) (D) (DC) (DCC) (DCCC) (CM) ] [ () (M) (MM) (MMM) ] ] % Roman equivalents () % append the Roman equivalent of each decimal digit to this string 2 index -1 1 { 2 index 1 index 1 sub get 5 index 5 index 4 -1 roll sub get 48 sub get concatstrings } for 4 1 roll pop pop pop } if } bind executeonly % style printers /PageStyle << /D { 255 string cvs } bind executeonly /R { .cvRoman } executeonly /r { .cvRoman .toLower } executeonly /A { .cvAlpha } executeonly /a { .cvAlpha .toLower } executeonly >> % check whether we want to generate pdfmarks /wantpagelabelmarks { % WantsPageLabels means that pagelabels will be passed % using .pdfpagelabels and not using pdfmarks /WantsPageLabels /GetDeviceParam .special_op {pop pop //false}{//true} ifelse %% This is truly ugly..... %% GSView 5 redefines pdfmark and processes it itself. However if it gets %% a pdfmark it cannot cope with, it simply fails. Its not prepared to cope %% with PAGELABEL pdfmarks, so we don't want to send it to them. There's no %% way for us to fix GSView 5, its long out of any kind of support, but we do %% try not to break it. We happen to know that GSView 5 installs a GSview %% dictionary in userdict, so this test simply ensures we don't emit PAGELABEL %% pdfmarks if that dictioanry is present. userdict /GSview known {pop //false} if } bind executeonly % generate pagelabel pdfmark /dopagelabel { % -- dopagelabel -- << /S //null /P () /O 0 >> begin wantpagelabelmarks { Trailer /Root knownoget { oforce /PageLabels knownoget { oforce Page# 1 sub numogetle { oforce dup /S knownoget not { //false } if /S exch def dup /P knownoget not { 0 string } if /P exch def /St knownoget not { 1 } if exch sub /O exch def } if P Page# 1 sub O add PageStyle S knownoget { exec concatstrings } if mark /Label 3 -1 roll /PAGELABEL pdfmark } if } if } if end } bind executeonly .dicttomark readonly def % ======================== Main program ======================== % end % pdfdict userdict begin /defaultfontname /Times-Roman def % Make sure the registered encodings are loaded, so we don't run the risk % that some of the indices for their names will overflow the packed % representation. (Yes, this is a hack.) SymbolEncoding pop DingbatsEncoding pop % Redefine 'run' so it recognizes PDF files. systemdict begin systemdict /NEWPDF known not {/NEWPDF //false def} if % PostScript interface to the ghostpdf C-based interpreter % % Promised or documented as used by customers % =========================================== % runpdf <file> runpdf - % Called from the modified run operator (which copies stdin to a temp % file if required). Calls runpdfbegin, check for PDF collections. Then % calls process_trailer_attrs, runpdfpagerange, dopdfpages and runpdfend % to process all the required pages. % % runpdfbegin <file> runpdfbegin - % creates /pdfdict in userdict set userparmas (ProcessDSCComment % setobjectformat to 0 /Page# /Page to null DSCPageCount to 0 % /PDFSave /null. % calls pdfopen and then 'begin's the returned dictionary. % Also disables page handler device. % % pdfgetpage <int> pdfgetpage <pagedict> | <null> % int is a number from 1 to N indicating the desired page number from % the PDF file. Returns a dictionary, apparently the /Page dictionary. Probably % we only need the Boxes and Rotate key ? If this fails, returns a null object. % % pdfshowpage_init <int> pdfshowpage_init <dict> % This simply adds 1 to the /DSCPageCount value in the supplied dictioanry % % pdfshowpage_setpage <pagedict> pdfshowpage_setpage <pagedict> % Takes a dictionary as returned from pdfgetpage, extracts various % parameters from it, and sets the media size for the page, taking into % account the boxes, and requested Box, Rotate value and PDFFitPage. % % pdfshowpage_finish <pagedict> pdfshowpage_finish - % Takes a dictionary as returned from pdfgetpage, renders the page content % executes showpage to transfer the rendered content to the device. % % runpdfend - % Uses currentdict as an argument to pdfclose, which closes /PDFfile. Also % executes restore and various cleanup activities. % % Also Used by gsview 5 % ===================== % pdfopen <file> pdfopen <dict> % According to the comments; open a PDF file and read the header, trailer % and cross-reference. Calls pdfopenfile and 'begin's the returned dictionary % calls pdfopencache and then closes the current dictionary. % pdfopenfile appears to create a dictionary containing a load of stuff but % most importantly, sets /PDFfile to the passed-in file. Probably also contains % the Trailer dictionary. % % pdfclose <dict> pdfclose - % The supplied dictionary contains /PDFfile and it executes closefile on that % supplied file. % % Supplied by Ray to customer % ============================ % pdfshowpage <pagedict> pdfshowpage % Takes a dictionary returned from pdfgetpage and calls the pdfshowpage_init % pdfshowpage_setpage, pdfshowpage_finish trio to start the page, set up the % media and render the page. % % dopdfpages <int> <int> dopdfpages - % The integers are the first and last pages to be run from the file. Runs a loop from % the fist integer to the last. NOTE! If the current dictionary contains a PDFPageList % array then we 'get' the entry from the array corresponding to the current loop % index, and use that to determine whether we should draw the page. Otherwise we % simply draw the page. Uses pdfshowpage to actually render the page. % % Additionallly useful ? % ======================= % runpdfpagerange - runpdfpagerange <int> <int> % Processes the PostScript /FirstPage, /LastPage and /PageList parameters to build an array % of page numbers to run (if PageList is present) and a FirstPage and LastPage value. % There seems no point in rewriting this, may as well use it to control page processing. % % Normal operation % ================= % runpdf - runpdfbegin - pdfopen % - process_trailer_attrs % - runpdfpagerange % - dopdfpages - pdfgetpage % - pdfshowpage - pdfshowpage_init % - pdfshowpage_setpage % - pdfshowpage_finish % - runpdfend - pdfclose % /DisablePageHandlerDevice { systemdict /FirstPage known systemdict /LastPage known or systemdict /PageList known or { <</DisablePageHandler //true>> setpagedevice } if } bind def /EnablePageHandlerDevice { systemdict /FirstPage known systemdict /LastPage known or systemdict /PageList known or { <</DisablePageHandler //false>> setpagedevice } if } bind def /newpdf_pdfformaterror { % <string> pdfformaterror - (%stdout) (w) file dup 3 -1 roll writestring flushfile } bind executeonly def % This routine sets up the transparency compositor requirement, and % number of spot channels required (if any) in the device. This needs % to be done before we set the media size, so that the erasepage is % correct. Called with the dictionary returned from .PDFPageInfo /newpdf_device_setup { 2 dict exch % <<page dict>> << >> dup /UsesTransparency get % << >> <<page dict>> bool /PageUsesTransparency exch % << >> <<page dict>> /PageUsesTransparency bool 3 index 3 1 roll % << >> <<page dict>> <<info dict>> << >> /PageUsesTransparency bool put % <</PageUsesTransparency bool>> <<page dict>> /NumSpots get % <</PageUsesTransparency bool>> int /PageSpotColors exch % <</PageUsesTransparency bool>> /PageSpotColors int 2 index 3 1 roll % <</PageUsesTransparency bool>> <<page dict>> /PageSpotColors int put % <</PageUsesTransparency bool /PageSpotColors int >> setpagedevice }bind def % Takes the selected Box as a parameter and scales it to fit the current media. % If the amount of scaling would be reduced by rotating the content, then % rotate the content. % Caters for the box non-zero lower left x and y (ie cropping) /NewPDF_FitPage { dup 2 get 1 index 0 get sub %urx -llx = width 1 index 3 get 2 index 1 get sub %ury - lly = height currentpagedevice /PageSize get aload pop % Stack - box boxwidth boxheight mediawidth mediaheight % Start by deciding if we should rotate the page to better fit the media. 4 copy eq 3 1 roll eq or % square media or square page, no point in rotating { //false } { gt { % landscape media ge { % landscape media, landscape box, no rotation //false } { % landscape media, portrait box, rotate it to landscape //true } ifelse } { % portrait media ge { % portrait media, landscape box, rotate it to portrait //true } { % portrait media, portrait box, no rotation //false } ifelse }ifelse } ifelse % Store values for calculating scale, we do this here because we want to % swap the media width and height (for the scale calculation) if we are % rotating the page 1 index 2 get 2 index 0 get sub % urx -llx = width 2 index 3 get 3 index 1 get sub % ury - lly = height currentpagedevice /PageSize get aload pop % Stack - box rotate boxwidth boxheight mediawidth mediaheight 5 -1 roll % Stack - box boxwidth boxheight mediawidth mediaheight rotate % If we need to rotate, recalculate the box { 90 rotate 0 2 index neg translate % move 0,0 to bottom right of media to account for rotation exch % swap media width/height for scaling calculation }if % Stack - box boxwidth boxheight mediawidth mediaheight % Incorporate up any offset from 0,0 4 index aload pop pop pop neg exch neg exch 2 copy exch translate % Now use the box and media values to calculate the required x/y scale factors 3 -1 roll div % box boxwidth mediawidth (mediaheight / boxheight) 3 1 roll % box (mediaheight / boxheight) boxwidth mediawidth exch % box (mediaheight / boxheight) mediawidth boxwidth div % box (mediaheight / boxheight) (mediawidth / boxwidth) 2 copy % box Yscale Xscale Yscale Xscale gt {exch} if % select smallest scale factor pop % dup scale % and scale page isomorphically pop pop } bind def /newpdf_get_media_box { % <pagedict> get_media_box <box> <bool> dup /MediaBox known { /MediaBox get dup length 4 eq { //true } { pop ( **** Error: Page has an invalid /MediaBox attribute. Using the current page size.\n) newpdf_pdfformaterror ( Output may be incorrect.\n) pdfformaterror [ 0 0 currentpagedevice /PageSize get aload pop ] //false }ifelse } { pop ( **** Error: Page has no /MediaBox attribute. Using the current page size.\n) newpdf_pdfformaterror ( Output may be incorrect.\n) newpdf_pdfformaterror [ 0 0 currentpagedevice /PageSize get aload pop ] //false } ifelse %(newpdf_get_media_box end) == flush } bind executeonly def /newpdf_get_any_box { % <pagedict> get_any_box <box name> <box> %(newpdf_get_any_box start) == flush //systemdict /UseBleedBox .knownget dup { and } if { dup /BleedBox get { /BleedBox exch } if } if //systemdict /UseTrimBox .knownget dup { and } if { dup /TrimBox get { /TrimBox exch } if } if dup type /arraytype ne { //systemdict /UseArtBox .knownget dup { and } if { dup /ArtBox get { /ArtBox exch } if } if } if dup type /arraytype ne { //systemdict /UseCropBox .knownget dup { and } if { dup /CropBox get { /CropBox exch } if } if } if dup type /arraytype ne { /MediaBox exch newpdf_get_media_box pop } { %% Complicated stuff. We need to use the 'Box' we identified (if any), but we %% need to clamp the boundaries of the 'Box' to the MediaBox. This appears to %% be what Acrobat does. The complication arises because the Box values don't %% have to be sensibly positive, its permissible to have the MediaBox set up %% so that it extends down and left instead of up and right. We take care of the %% content when we st up the CTM, but we do need to make sure that we clamp %% the BoundingBox, and that means we need to take direcitonality into account... 6 -1 roll newpdf_get_media_box { % /SomeBox x0 y0 x1 y1 [MediaBox] aload pop % /SomeBox x0 y0 x1 y1 X0 Y0 X1 Y1 %% Start with the width, get the X0 and X1 values of the MediaBox 3 index % /SomeBox x0 y0 x1 y1 X0 Y0 X1 Y1 X0 2 index % /SomeBox x0 y0 x1 y1 X0 Y0 X1 Y1 X0 X1 gt { %% Media extends to left 4 -1 roll % /SomeBox x0 y0 x1 y1 Y0 X1 Y1 X0 8 -1 roll % /SomeBox y0 x1 y1 Y0 X1 Y1 X0 x0 .min % /SomeBox y0 x1 y1 Y0 X1 Y1 mX0 7 1 roll % /SomeBox mX0 y0 x1 y1 Y0 X1 Y1 exch % /SomeBox mX0 y0 x1 y1 Y0 Y1 X1 5 -1 roll % /SomeBox mX0 y0 y1 Y0 Y1 X1 x1 .max % /SomeBox mX0 y0 y1 Y0 Y1 mX1 5 1 roll % /SomeBox mX0 mX1 y0 y1 Y0 Y1 }{ %% Media extends to right 4 -1 roll % /SomeBox x0 y0 x1 y1 Y0 X1 Y1 X0 8 -1 roll % /SomeBox y0 x1 y1 Y0 X1 Y1 X0 x0 .max % /SomeBox y0 x1 y1 Y0 X1 Y1 mX0 7 1 roll % /SomeBox mX0 y0 x1 y1 Y0 X1 Y1 exch % /SomeBox mX0 y0 x1 y1 Y0 Y1 X1 5 -1 roll % /SomeBox mX0 y0 y1 Y0 Y1 X1 x1 .min % /SomeBox mX0 y0 y1 Y0 Y1 mX1 5 1 roll % /SomeBox mX0 mX1 y0 y1 Y0 Y1 } ifelse %% Now deal with the height 2 copy % /SomeBox mX0 mX1 y0 y1 Y0 Y1 Y0 Y1 gt { %% Media extends down exch % /SomeBox mX0 mX1 y0 y1 Y1 Y0 4 -1 roll % /SomeBox mX0 mX1 y1 Y1 Y0 y0 .min % /SomeBox mX0 mX1 y1 Y1 mY0 3 1 roll % /SomeBox mX0 mX1 mY0 y1 Y1 .max % /SomeBox mX0 mX1 mY0 mY1 }{ %% Media extends up exch % /SomeBox mX0 mX1 y0 y1 Y1 Y0 4 -1 roll % /SomeBox mX0 mX1 y1 Y1 Y0 y0 .max % /SomeBox mX0 mX1 y1 Y1 mY0 3 1 roll % /SomeBox mX0 mX1 mY0 y1 Y1 .min % /SomeBox mX0 mX1 mY0 mY1 } ifelse exch % /SomeBox mX0 mX1 mY1 mY0 3 1 roll % /SomeBox mX0 mY0 mX1 mY1 } { pop } ifelse 4 array astore % /SomeBox [mX0 mY0 mX1 mY1] } ifelse } bind executeonly def % This routine is used to set the PostScript /PageSize from the requested Box of the % PDF file. Much of this is copied from the old pdfshowpage_setpage routine which % is used for the PDF interpreter written in PostScript. % % Called with a dictionary containing the PDF page information. % /newpdf_set_pagesize { % Stack: pdfpagedict % Don't understand this at all, removed for now replace if we ever figure out % what it's for. % Only lock in Orientation if we need to for pdfmarks % .writepdfmarks { /Orientation 0 def } if dup dup newpdf_get_any_box % Stack: pdfpagedict pdfpagedict /BoxName [box] //systemdict /PDFFitPage known { NewPDF_FitPage } { 6 dict begin % for setpagedevice % Set the page size. 2 index /UserUnit known { systemdict /NoUserUnit .knownget not {//false} if { 2 index /UserUnit undef % No scaling required, calculate PageSize as the width and height of the box aload 5 1 roll % box llx lly urx ury 2 index sub % box llx lly urx (ury - lly) exch 3 index sub % box llx lly (ury - lly) (urx - llx) exch } { 2 index /UserUnit get % The PageSize needs to be multiplied too exch aload 5 1 roll % UserUnit box llx lly urx ury 2 index sub exch % UserUnit box llx lly (ury - lly) urx 3 index sub % UserUnit box llx lly boxheight boxwidth 5 index mul % UserUnit box llx lly boxheight (Boxwidth*UserUnit) exch 5 index mul % UserUnit box llx lly (Boxwidth*UserUnit) (boxheight*UserUnit) 4 -2 roll 5 index mul exch % UserUnit box (Boxwidth*UserUnit) (boxheight*UserUnit) (lly*UserUnit) llx 5 index mul exch % UserUnit box (Boxwidth*UserUnit) (boxheight*UserUnit) (llx*UserUnit) (lly*UserUnit) 4 2 roll % UserUnit box (llx*UserUnit) (lly*UserUnit) (Boxwidth*UserUnit) (boxheight*UserUnit) 6 -1 roll pop % box (llx*UserUnit) (lly*UserUnit) (Boxwidth*UserUnit) (boxheight*UserUnit) } ifelse } { /PassUserUnit /GetDeviceParam .special_op { exch pop { [ /UserUnit 1 .pdfputparams pop pop } if }if % No scaling required, calculate PageSize as the width and height of the box aload 5 1 roll % box llx lly urx ury 2 index sub % box llx lly urx (ury - lly) exch 3 index sub % box llx lly (ury - lly) (urx - llx) exch } ifelse % handle page rotation here 6 index /Rotate known { % PDF page rotation runs clockwise and must be a multiple of 90, unlike PostScript..... % convert Rotate into a quadrant number 6 index /Rotate get 90 div cvi % Make sure quadrant is 0-3 dup 0 lt { % Negative rotation... Turn it into a positive rotation % Again, limit the quadrant to -0 to -3 dup -4 lt {4 mod} if % Adding 360 degrees results in the same positive rotation 4 add } if dup 3 gt {4 mod} if dup 0 eq { pop 2 array astore /PageSize exch def currentdict end setpagedevice neg exch neg exch translate } { dup 1 eq { pop exch 4 2 roll exch 4 2 roll 2 array astore dup /PageSize exch def currentdict end setpagedevice 270 rotate 1 get add neg exch neg translate } { 2 eq { 2 array astore dup /PageSize exch def currentdict end setpagedevice 180 rotate aload pop 3 -1 roll add neg 3 1 roll add neg exch translate } { exch 4 2 roll exch 4 2 roll 2 array astore dup /PageSize exch def currentdict end setpagedevice 90 rotate 0 get 3 -1 roll add neg exch neg exch translate } ifelse } ifelse } ifelse } { 2 array astore /PageSize exch def currentdict end setpagedevice neg exch neg exch translate }ifelse % scale the co-ordinate system by the UserUnit % We have to do this after setting the PageSize, because % setpagedevice does an implicit initgraphics, resetting the CTM. % //systemdict /NoUserUnit .knownget not { //false } if not { 2 index /UserUnit known { 2 index /UserUnit get dup scale } if } if } ifelse pop % The box % If we are using the MediaBox (and only the MediaBox) then we % want to clip to the CropBox, if there s one present /MediaBox eq { dup /CropBox known { /CropBox get aload pop 2 index sub exch 3 index sub exch rectclip } { pop } ifelse } if pop } bind executeonly def % This routine checks a list of known/implemented command line switches to see if they % have been defined in the PostScript environment. If they have we construct a dictionary % containing the names and their values, and return it. That dictionary can then be % passed to a custom PostScript operator and used to configure the PDF interpreter. % % NB device parameters will already have been sent to the device and used to configure it % so here we should only handle parameters which control the behaviour of the interpreter. % /newpdf_gather_parameters { 10 dict begin /PDFSwitches [ /PDFPassword /PDFDEBUG /PDFSTOPONERROR /PDFSTOPONWARNING /NOTRANSPARENCY /FirstPage /LastPage /NOCIDFALLBACK /NO_PDFMARK_OUTLINES /NO_PDFMARK_DESTS /PDFFitPage /Printed /UseBleedBox /UseCropBox /UseArtBox /UseTrimBox /ShowAcroForm /ShowAnnots /PreserveAnnots /NoUserUnit /RENDERTTNOTDEF /DOPDFMARKS /PDFINFO /SHOWANNOTTYPES /PRESERVEANNOTTYPES] def 0 1 PDFSwitches length 1 sub { PDFSwitches exch get dup where { exch dup 3 1 roll get def } { pop } ifelse } for currentdict /PDFSwitches undef currentdict end } bind executeonly def /newpdf_pagecount { PDFFile //null eq not { PDFFile {.PDFInfo} stopped not { dup /NumPages known { /NumPages get } { pop 0 } ifelse } { pop 0 } ifelse } { 0 } ifelse }bind def /newpdf_runpdfpagerange { /PageList where { pop PageList (even) anchorsearch { pop length 0 gt { /runpdfpagerange cvx /syntaxerror signalerror } if /PDFPageList pdfpagecount 1 add array def 2 2 pdfpagecount { PDFPageList exch 1 put } for QUIET not { (Processing even-numbered pages\n) print (1 through ) print pdfpagecount =only (.) = flush } if } { (odd) anchorsearch { pop length 0 gt { /runpdfpagerange cvx /syntaxerror signalerror } if /PDFPageList pdfpagecount 1 add array def 1 2 pdfpagecount { PDFPageList exch 1 put } for QUIET not { (Processing odd-numbered pages\n) print (1 through ) print pdfpagecount =only (.) = flush } if } { %% validate string contents, check for digit comma or minus dup { dup 44 eq not { dup 45 eq not { dup 48 lt 1 index 57 gt or { /runpdfpagerange cvx /syntaxerror signalerror } if } if } if pop } forall /PDFPageList pdfpagecount 1 add array def { (,) search { %% We now have (post) (,) (pre) exch pop %% get rid of the (,), leave the (post) as the string for the next iteration, deal with the section up to the comma (-) search { %% Now we have (end) (-) (start) exch pop %% get rid of the minus (end) (start) 0 exch {48 sub exch 10 mul add} forall %% Make sure the start of the range is inside the number of available pages dup pdfpagecount le { exch %% deal with a trailing '-' by replacing it with the number of pages in the file dup length 0 eq { pop pdfpagecount }{ 0 exch {48 sub exch 10 mul add} forall } ifelse 1 exch %% start 1 end %% Make sure the end of the range is inside the number of available pages dup pdfpagecount gt {pop pdfpagecount} if {PDFPageList exch 1 put} for } { %% start of range invalid, drop this range. pop pop }ifelse }{ %% no minus signs, must be a simple page number 0 exch {48 sub exch 10 mul add} forall %% ensure its in the valid range of pages dup pdfpagecount le { PDFPageList exch 1 put } { pop } ifelse } ifelse }{ %% no commas separating pages, just the original string (), deal with its as a section, then exit the loop (-) search { %% Now we have (end) (-) (start) exch pop %% get rid of the minus (end) (start) 0 exch {48 sub exch 10 mul add} forall %% Make sure the start of the range is inside the number of available pages dup pdfpagecount le { exch %% deal with a trailing '-' by replacing it with the number of pages in the file dup length 0 eq { pop pdfpagecount }{ 0 exch {48 sub exch 10 mul add} forall } ifelse 1 exch %% start 1 end %% Make sure the end of the range is inside the number of available pages dup pdfpagecount gt {pop pdfpagecount} if {PDFPageList exch 1 put} for } { %% start of range invalid, drop this range. pop pop }ifelse }{ %% no minus signs, must be a simple page number 0 exch {48 sub exch 10 mul add} forall %% ensure its in the valid range of pages dup pdfpagecount le { PDFPageList exch 1 put } { pop } ifelse } ifelse exit %% done all the sections. } ifelse } loop QUIET not { (Processing pages ) print PageList =only (.) = flush } if } ifelse } ifelse 1 pdfpagecount }{ /FirstPage where { pop FirstPage dup pdfpagecount gt { (\nRequested FirstPage is greater than the number of pages in the file: ) print pdfpagecount = flush } if } { 1 } ifelse /LastPage where {pop LastPage pdfpagecount .min } { pdfpagecount } ifelse 1 index 1 index gt { ( No pages will be processed \(FirstPage > LastPage\).) = flush } { QUIET not { (Processing pages ) print 1 index =only ( through ) print dup =only (.) = flush } if } ifelse } ifelse } bind def % <file> runpdf - /newpdf_runpdf { runpdfbegin % <file> runpdfbegin - PDFInfo /Collection known { PDFInfo /Collection get pdfclose dup length 1 sub 0 2 3 -1 roll { 1 index exch get (r) file runpdf } for pop } { process_trailer_attrs % - process_trailer_attrs - runpdfpagerange % - runpdfpagerange <int> <int> dopdfpages % <int> <int> dopdfpages - runpdfend % - runpdfend - } ifelse } bind def /newpdf_runpdfbegin { /pdfdict 10 dict def pdfdict begin % This is for the benefit of pdf2dsc which assumes it will be present /Trailer << >> def /PDFSave save def % Define these in the current dictionary, if anyone uses % systemdict then this will be defeated so we'll add extra % code to the systemdict definitions as well. /pdfpagecount /newpdf_pagecount load def /pdfgetpage /newpdf_pdfgetpage load def /pdfshowpage /newpdf_pdfshowpage load def /pdfshowpage_init /newpdf_pdfshowpage_init load def /pdfshowpage_setpage /newpdf_pdfshowpage_setpage load def /pdfshowpage_finish /newpdf_pdfshowpage_finish load def /pdfopen /newpdf_pdfopen load def /pdfclose /newpdf_pdfclose load def /dopdfpages /newpdf_dopdfpages load def /runpdfend /newpdf_runpdfend load def /runpdfpagerange /newpdf_runpdfpagerange load def /process_trailer_attrs /newpdf_process_trailer_attrs load def % These are also for the benefit of pdf2dsc, which assumes they % are available. /knownoget {2 copy known {get //true}{pop //false}ifelse} bind def /pget {2 copy known {get //true}{pop //false}ifelse}bind def newpdf_gather_parameters {.PDFInit} stopped { /PDFFile //null def /PDFInfo //null def } { /PDFFile exch def pdfopen /PDFInfo exch def pop }ifelse } bind def /newpdf_pdfgetpage { PDFFile exch 1 sub {.PDFPageInfo} stopped { pop pop ( **** Error: Couldn't get page info.\n) newpdf_pdfformaterror ( Output may be incorrect.\n) newpdf_pdfformaterror //null } if } bind def /newpdf_process_trailer_attrs { }bind def /newpdf_pdfshowpage_init { gsave } bind def /newpdf_pdfshowpage_setpage { dup newpdf_device_setup dup newpdf_set_pagesize } bind def /newpdf_pdfshowpage_finish { /Page# get PDFFile exch 1 sub {.PDFDrawPage} stopped { pop pop ( **** Error: Page drawing error occured.\n) newpdf_pdfformaterror ( Output may be incorrect.\n) newpdf_pdfformaterror } if showpage grestore } bind def /newpdf_pdfshowpage { pdfshowpage_init pdfshowpage_setpage pdfshowpage_finish } bind def /newpdf_runpdfend { pdfclose PDFSave restore end % pdfdict } bind def /newpdf_pdfopen { dup PDFFile //null ne { PDFFile {.PDFStream} stopped { pop pop ( **** Error: Couldn't initialise file.\n) newpdf_pdfformaterror ( Output may be incorrect.\n) newpdf_pdfformaterror <</NumPages 0>> } { PDFFile {.PDFInfo} stopped { pop ( **** Error: Couldn't get page information.\n) newpdf_pdfformaterror ( Output may be incorrect.\n) newpdf_pdfformaterror <</NumPages 0>> } if } ifelse } { pop <</NumPages 0>> } ifelse } bind def /newpdf_pdfclose { PDFFile {.PDFClose} stopped { pop } if } bind def % <int> <int> dopdfpages - % First Page and then LastPage /newpdf_dopdfpages { //DisablePageHandlerDevice exec 1 exch { %% If we have a array of pages to render, use it. /PDFPageList where { pop dup PDFPageList exch get 1 eq } {//true} ifelse { QUIET not { (Page ) print dup //== exec flush } if dup pdfgetpage dup //null ne { exch 1 index /Page# 3 -1 roll put pdfshowpage } { PDFSTOPONERROR { /dopdfpages cvx /syntaxerror signalerror } { pop pop ( **** Error: page) newpdf_pdfformaterror ( not found.\n) newpdf_pdfformaterror } ifelse } ifelse }{ pop }ifelse } for //EnablePageHandlerDevice exec } bind def /.runps /run load def /run { dup type /filetype ne { (r) file } if % skip leading whitespace characters (actually anything less than or equal to <sp>) { dup ( ) .peekstring not { //false exit } if dup 0 get 32 le { pop dup read pop pop } { //true exit } ifelse } loop exch pop { % Appletalk PAP sends short strings with %! header expecting a response. % 'gv' swallows the %!PS line, then sends DSC comments beginning with %% % and also waits for a response. The following avoids those hangs. dup 2 string .peekstring pop dup (%!) eq exch (%%) eq or { cvx .runps } { dup 1023 string .peekstring pop % "1024 string" exceeds current %stdin buffer % Valid PDF file cannot be smaller than 400 bytes. (%PDF-) search { 3 1 roll pop pop dup (%!PS) search not { length 0 ne { 1 index exch readstring pop pop (%stderr) (w) file dup ( **** Warning: File has some garbage before %PDF- .\n) writestring flushfile } { pop } ifelse dup (%stdin) (r) file eq { % Copy PDF from stdin to temporary file then run it. //null (w+) /.tempfile .systemvar exec exch 3 1 roll % stack: tempname stdin tempfile 64000 string { % stack: tempname stdin tempfile string 2 index 1 index readstring exch 3 index exch writestring not { exit } if } loop pop exch closefile % stack: tempname tempfile dup 0 setfileposition dup runpdf closefile deletefile } { runpdf } ifelse } { pop pop pop pop cvx .runps % (%!PS) found first } ifelse } { pop cvx .runps % (%PDF-) not found } ifelse } ifelse } { closefile % file was empty } ifelse } bind odef currentdict /runpdfstring .undef /runpdfbegin { % <file> runpdfbegin - /NEWPDF where {/NEWPDF get} {//true} ifelse { newpdf_runpdfbegin } { userdict begin % It turns out that the PDF interpreter uses memory more % effectively if it is run under at least one level of save. % This is counter-intuitive, and we don't understand why it happens, % but the improvement is significant. /PDFTopSave save def << /ProcessDSCComment //null /ProcessComment //null %% Bug #696487, allow dict stack to grow without limit, as these PDF %% files have stupidly deep gsave nesting and we need a dictionary per gsave %% at the moment. %% Remove ths if bug #696511 is ever completed (move ExtGstate parameters into gstate) /MaxDictStack -1 %% Bug #696567, same customer as above. Ths time they have a file with a page whch has %% 447000 ExtGState references (all of which contain no gstate!) Because we allocate %% these on the stack, allow the stack to grow indefinitely in order to accomodate %% such stupid files. Also move these lines from the end of the routine, so that %% the increases are in place before we call odfopen, which will build the %% resources and needs this definition in place. /MaxOpStack -1 >> setuserparams //DisablePageHandlerDevice exec 0 setobjectformat /Page# //null def /Page //null def /DSCPageCount 0 def /PDFSave //null def //pdfdict /GS_PDF_ProcSet get begin //pdfdict begin pdfopen begin /CumulativePageCount currentpagedevice /PageCount get def } ifelse } bind executeonly def /runpdfpagerange { % - runpdfpagerange <firstpage#> <lastpage#> /NEWPDF where {/NEWPDF get} {//true} ifelse { newpdf_runpdfpagerange } { /PortfolioPage where { pop PortfolioPage cvi dup pdfpagecount add % a b+1 /PortfolioPage dup load % a b+1 /P () ( ) 1 index copy pop dup 3 index exch cvs pop % a b+1 /P (b+1) store 1 sub % a b /FirstPage where { pop FirstPage} { 1 } ifelse /LastPage where { pop LastPage} {2000000000} ifelse % a b fp lp 2 index 2 index lt { % b < fp 1e10 } { 3 index 2 index gt { % a > fp 1 } { 1 index 4 index sub 1 add } ifelse } ifelse % a b fp lp f 3 index 2 index lt { % b < bp 3 index 5 index sub 1 add % b-a+1=count } { 4 index 2 index gt { 0 } { 1 index 5 index sub 1 add } ifelse } ifelse % a b fp lp f l 6 2 roll pop pop pop pop QUIET not { 1 index 1 index gt { (Skipping the subfile.) = flush } { (Processing pages ) print 1 index =only ( through ) print dup =only (.) = flush } ifelse } if } { /PageList where { pop PageList (even) anchorsearch { pop length 0 gt { /runpdfpagerange cvx /syntaxerror signalerror } if /PDFPageList pdfpagecount 1 add array def 2 2 pdfpagecount { PDFPageList exch 1 put } for QUIET not { (Processing even-numbered pages\n) print (1 through ) print pdfpagecount =only (.) = flush } if } { (odd) anchorsearch { pop length 0 gt { /runpdfpagerange cvx /syntaxerror signalerror } if /PDFPageList pdfpagecount 1 add array def 1 2 pdfpagecount { PDFPageList exch 1 put } for QUIET not { (Processing odd-numbered pages\n) print (1 through ) print pdfpagecount =only (.) = flush } if } { %% validate string contents, check for digit comma or minus dup { dup 44 eq not { dup 45 eq not { dup 48 lt 1 index 57 gt or { /runpdfpagerange cvx /syntaxerror signalerror } if } if } if pop } forall /PDFPageList pdfpagecount 1 add array def { (,) search { %% We now have (post) (,) (pre) exch pop %% get rid of the (,), leave the (post) as the string for the next iteration, deal with the section up to the comma (-) search { %% Now we have (end) (-) (start) exch pop %% get rid of the minus (end) (start) 0 exch {48 sub exch 10 mul add} forall %% Make sure the start of the range is inside the number of available pages dup pdfpagecount le { exch %% deal with a trailing '-' by replacing it with the number of pages in the file dup length 0 eq { pop pdfpagecount }{ 0 exch {48 sub exch 10 mul add} forall } ifelse 1 exch %% start 1 end %% Make sure the end of the range is inside the number of available pages dup pdfpagecount gt {pop pdfpagecount} if {PDFPageList exch 1 put} for } { %% start of range invalid, drop this range. pop pop }ifelse }{ %% no minus signs, must be a simple page number 0 exch {48 sub exch 10 mul add} forall %% ensure its in the valid range of pages dup pdfpagecount le { PDFPageList exch 1 put } { pop } ifelse } ifelse }{ %% no commas separating pages, just the original string (), deal with its as a section, then exit the loop (-) search { %% Now we have (end) (-) (start) exch pop %% get rid of the minus (end) (start) 0 exch {48 sub exch 10 mul add} forall %% Make sure the start of the range is inside the number of available pages dup pdfpagecount le { exch %% deal with a trailing '-' by replacing it with the number of pages in the file dup length 0 eq { pop pdfpagecount }{ 0 exch {48 sub exch 10 mul add} forall } ifelse 1 exch %% start 1 end %% Make sure the end of the range is inside the number of available pages dup pdfpagecount gt {pop pdfpagecount} if {PDFPageList exch 1 put} for } { %% start of range invalid, drop this range. pop pop }ifelse }{ %% no minus signs, must be a simple page number 0 exch {48 sub exch 10 mul add} forall %% ensure its in the valid range of pages dup pdfpagecount le { PDFPageList exch 1 put } { pop } ifelse } ifelse exit %% done all the sections. } ifelse } loop QUIET not { (Processing pages ) print PageList =only (.) = flush } if } ifelse } ifelse 1 pdfpagecount }{ /FirstPage where { pop FirstPage dup pdfpagecount gt { (\nRequested FirstPage is greater than the number of pages in the file: ) print pdfpagecount = flush } if } { 1 } ifelse /LastPage where {pop LastPage pdfpagecount .min } { pdfpagecount } ifelse 1 index 1 index gt { ( No pages will be processed \(FirstPage > LastPage\).) = flush } { QUIET not { (Processing pages ) print 1 index =only ( through ) print dup =only (.) = flush } if } ifelse } ifelse }ifelse }ifelse } bind executeonly def /dopdfpages { % firstpage# lastpage# dopdfpages - /NEWPDF where {/NEWPDF get} {//true} ifelse { newpdf_dopdfpages } { << /PDFScanRules //true >> setuserparams % set scanning rules for PDF vs. PS << /RenderTTNotdef systemdict /RENDERTTNOTDEF get >> setuserparams % Should we render TT /.notdef 1 exch { %% If we have a array of pages to render, use it. /PDFPageList where { pop dup PDFPageList exch get 1 eq } {//true} ifelse { dup /Page# exch store QUIET not { (Page ) print dup //== exec flush } if pdfgetpage dup //null ne { pdfshowpage } { PDFSTOPONERROR { /dopdfpages cvx /syntaxerror signalerror } { pop ( **** Error: Page #) pdfformaterror Page# 10 string cvs pdfformaterror ( not found.\n) pdfformaterror } ifelse } ifelse }{ pop }ifelse } for % Indicate that the number of spot colors is unknown in case the next page % imaged is a PS file. currentpagedevice /PageSpotColors known { << /PageSpotColors -1 >> setpagedevice } if << /PDFScanRules //null >> setuserparams % restore scanning rules for PS } ifelse } bind executeonly def /runpdfend { /NEWPDF where {/NEWPDF get} {//true} ifelse { newpdf_runpdfend } { RepairedAnError { printrepairederror } { Repaired { printrepaired } if } ifelse currentdict pdfclose end % temporary dict end % pdfdict end % GS_PDF_ProcSet PDFTopSave restore end % userdict 2 vmreclaim % couldn't hurt //EnablePageHandlerDevice exec } ifelse } bind executeonly def currentdict /DisablePageHandlerDevice undef currentdict /EnablePageHandlerDevice undef % Copy stream to an external temporary file and % return the file name as PS name. /copy_embedded_file { //true resolvestream % strm dup 1023 string .peekstring pop % "1024 string" exceeds current %stdin buffer dup length 400 ge { % Valid PDF file cannot be smaller than 400 bytes. (%PDF-) search { pop pop pop //true } { pop //false } ifelse } { pop //false } ifelse { //null (w) /.tempfile % strm (name) null (w) /.tempfile .systemvar exec % strm (name) file 3 -1 roll % (name) file strm 32768 string % (name) file strm (buf) { 3 copy readstring % (name) file strm (buf) file (data) bool 3 1 roll % (name) file strm (buf) bool file (data) writestring % (name) file strm (buf) bool not { exit } if } loop pop closefile % (name) file closefile % (name) cvn % /name } { closefile } ifelse } bind executeonly def % Recursively enumerate /Names entries % <node> pdf_collection_names /temp_file_name ... /pdf_collection_names { dup /Names knownoget { exch pop { oforce dup type /dicttype eq { /EF knownoget { /F knownoget { copy_embedded_file } if } if } { pop } ifelse } forall } { /Kids knownoget { { oforce dup //null ne { pdf_collection_names } { pop } ifelse } forall } if } ifelse } bind executeonly def % Copy selected subfiles to temporary files and return the file names % as a PostScript names to protect them from restore. % Currently, all PDF files in the Portfolio are extracted and returned. % % - pdf_collection_files [ /temp_file_name ... /temp_file_name /pdf_collection_files { mark Trailer /Root knownoget { dup /Collection oknown { /Names knownoget { /EmbeddedFiles knownoget { pdf_collection_names } if } if } { pop } ifelse } if } bind executeonly def /runpdf { % <file> runpdf - /NEWPDF where {/NEWPDF get} {//true} ifelse {newpdf_runpdf} { %% Get the PDF filename (it *must* be a file even if it came from stdin it gets %% copied to a temporary file) and store it in pdfdict. We will use this for %% hashing fonts to detect if fonts with the same name are from different files. %% dup currentglobal exch //true setglobal .getfilename exch setglobal /InputPDFFileName exch //pdfdict 3 1 roll .forceput //runpdfbegin exec //pdf_collection_files exec dup mark eq { pop process_trailer_attrs //runpdfpagerange exec //dopdfpages exec //runpdfend exec } { //runpdfend exec ] (1 ) 10 string copy exch { dup type /filetype eq { //runpdfbegin exec dup /PortfolioPage exch def process_trailer_attrs //runpdfpagerange exec //dopdfpages exec //runpdfend exec closefile } { .namestring dup (r) file //runpdfbegin exec /PortfolioPage 2 index def process_trailer_attrs //runpdfpagerange exec //dopdfpages exec //runpdfend exec deletefile } ifelse } forall pop } ifelse } ifelse } bind executeonly odef currentdict /pdf_collection_files .undef end % systemdict % Redefine the procedure that the C code uses for running piped input. % It is OK to use { (%stdin) run } here, because a startjob cannot occur. /.runstdin { { (%stdin) run } execute0 } bind executeonly def end % userdict pdfdict begin % ======================== File parsing ======================== % % Read the cross-reference and trailer sections. % I believe the definitions here are only used when parsing the trailer % dictionary and cross-reference table. So, following on from bug 697351 % we will validate the operands to /R here, because the trailer and xref % are comparatively small. Note that the bug does not expose a problem % here, but we probably ought to validate the operands. Of course, if % they are invalid, the PDF file is probably unreadable anyway. /traileropdict mark (<<) cvn { /dictlevelcount dictlevelcount 1 add store mark } bind executeonly (>>) cvn { { .dicttomark } stopped { ( **** Warning: File has unbalanced >> in trailer.\n) pdfformatwarning } if /dictlevelcount dictlevelcount 1 sub def dictlevelcount 0 eq { exit } if } bind executeonly ([) cvn { mark } bind executeonly % ditto (]) cvn dup load % /true true % see .pdfexectoken in pdf_base.ps % /false false % ibid. % /null null % ibid. /R { 1 index type /integertype eq 1 index type /integertype eq and { /resolveR cvx 3 packedarray cvx } { ( **** Error: indirect object reference \(R\) encountered with invalid arguments.) pdfformaterror ( Output may be incorrect.\n) pdfformaterror } ifelse } bind executeonly % see Objects below .dicttomark readonly def % After reading entry count: skip whitespace, exit on a digit % (presumably the object offset, otherwise throw /syntaxerror /xref-char-dict << 0 {} % \000 9 1 index % \t 10 1 index % \r 12 1 index % \f 13 1 index % \n 32 1 index % ' ' 48 { exit } bind % '0' 49 1 index % '1' 50 1 index % '2' 51 1 index % '3' 52 1 index % '4' 53 1 index % '5' 54 1 index % '6' 55 1 index % '7' 56 1 index % '8' 57 1 index % '9' 116 { % 't'railer PDFfile 7 string .peekstring not { () } if dup /trailer eq { % Empty xref section pop exit } { ( **** Warning: Invalid string \() exch concatstrings (\) follows xref section header.\n) concatstrings pdfformatwarning /setxrefentry cvx /syntaxerror signalerror } ifelse } bind >> readonly def % Read original version (pre PDF 1.5) of the xref table. % Note: The position is the location of 'xref'. The current PDFfile % position is just after the 'XREF'. /readorigxref % <pos> readorigxref <trailerdict> { pop % We do not need the position. % First we search this (and any Previous) trailers, looking for % the /Size of the xref. We use ths to initialise our storage % of xref and similar objects. This avoids us havign to continually % resize these objescts which is very wasteful, and leads to us % spending much time in memory amanagement. % Bug #696454 PDFfile fileposition /dictlevelcount 0 def /TrailerSizeError //false def /TrailerSize 0 def { % Throw away the 'xref' data up to the trailer dictionary PDFfile 0 (trailer) /SubFileDecode filter flushfile % Now read the trailer dictionary PDFfile traileropdict .pdfrun dup /Size known { % If we have a /Size then use it and exit this loop /Size get /TrailerSize exch def exit }{ dup /Prev known { % We don't have a Size, but we have a Previous, set up to read it. /Prev get PDFfile exch setfileposition }{ % No size and no Prev with a Size. Fall back to resizing the xref as we go. pop (*** Warning: No trailer dictionary with a Size detected, xref processing will be dynamic and slower) pdfformatwarning /TrailerDict 0 def exit } ifelse }ifelse }loop % Initialise the objects with the detected Size. TrailerSize growPDFobjects PDFfile exch setfileposition 0 % Initialize xref table error counter //false % Have we seen at least one section entry in this xref ? Bug #694342 { PDFfile token pop % first object # or trailer dup /trailer eq { %% check to see if we have seen at least an empty section for this xref pop {exit} { %% we have not seen any section entries in an xref, not even an empty section (xref 0 0) %% Bug 694342, treat this as an error and rebuild the xref. /setxrefentry cvx /syntaxerror signalerror } ifelse } { %% remove the boolean telling us if we have a section or not, leaving the first object number exch pop } ifelse PDFfile token pop % entry count % remaining must be whitespace only (otherwise this xref Size was invalid. { PDFfile (0) .peekstring not { pop exit } if 0 get //xref-char-dict exch .knownget { exec } { ( **** Warning: xref subsection header has extra characters.\n) pdfformatwarning /setxrefentry cvx /syntaxerror signalerror } ifelse PDFfile read { pop } { exit } ifelse } loop % This section might be adding new objects: % ensure that Objects and Generations are big enough. % stack: <err count> <first obj> <entry count> 2 copy add TrailerSize gt { TrailerSizeError not { /TrailerSizeError //true def PDFSTOPONERROR not { (**** Warning: Discovered more entries in xref than declared in trailer /Size\n) pdfformatwarning } { /readorigxref cvx /rangecheck signalerror } ifelse } if % We now know that the /Size was wrong. We could read the whole table % resizing on every section, but if there are a lot of sections we % end up spending lots of time in memory management (Bug #696454) so % instead add 64k to the first object number in the section. This will % waste some memory, but is faster in ths case. 1 index 65534 add dup /TrailerSize exch def growPDFobjects } if { % stack: <err count> <obj num> % Read xref line PDFfile 20 string readstring pop % always read 20 chars. token pop % object position exch token pop % generation # exch token pop % n or f exch % stack: <err count> <obj#> <loc> <gen#> <tag> <remainder of line> % check to make sure trailing garbage is just white space //false 1 index { 32 gt or } forall { 6 -1 roll 1 add 6 1 roll % bump error count on garbage dup (\n) search { exch pop exch pop } { (\r) search { exch pop exch pop } if } ifelse length PDFfile fileposition exch sub PDFfile exch setfileposition } if pop % Stack: <err count> <obj#> <loc> <gen#> <tag> dup /n eq { % xref line tag is /n pop % pop dup of line tag 1 index 0 eq { ( **** Warning: considering '0000000000 XXXXX n' as a free entry.\n) pdfformatwarning } { 0 3 1 roll % Set ObjectStream object number = 0 //false setxrefentry % Save xref entry, don't change existing entries 3 -1 roll pop % Remove ObjectStream object onumber } ifelse } { % xref line tag was not /n /f ne % verify that the tag was /f { /setxrefentry cvx /syntaxerror signalerror } { % Bug #703214 has a invalid initial xref table. The table entries are correct % but the subsection begins 1 7 instead of 0 7, which means the initial entry is % declared as object 1 instead of object 0. The file is incrementally updated % many times and every object *except* object 1 is redefined. Object 1 is % therefore defined as free and having an offset of 0. Acrobat can open this % without complaint! Because the PDF header is a comment line it is skipped % so Acrobat must simply be ignoring the free flag. We can't easily detect % this, but we can check for the generation number being the canonical % head of the free list. If it is, and the object number we have is not % zero, then pretend its not free....... dup 65535 eq { 2 index 0 ne { 0 3 1 roll //false setxrefentry 3 -1 roll pop } if }if }ifelse } ifelse pop pop % pop <obj location> and <gen num> % stack: <err count> <obj num> 1 add % increment object number } repeat pop % pop <obj #> //true % We have seen at least one entry in an xref section Bug #694342 } loop 0 ne { ( **** Warning: length of some xref entries is not equal to 20 bytes.\n) pdfformatwarning } if PDFfile traileropdict .pdfrun } bind executeonly def currentdict /xref-char-dict undef % This dicitonary is used to read the xref dictionary. It should work for % reading any dictionary. dictlevelcount must contain 0. /xrefopdict mark (<<) cvn { /dictlevelcount dictlevelcount 1 add def mark } bind executeonly (>>) cvn { .dicttomark /dictlevelcount dictlevelcount 1 sub def dictlevelcount 0 eq { exit} if } bind executeonly ([) cvn { mark } bind executeonly % ditto (]) cvn dup load % /true true % see .pdfexectoken in pdf_base.ps % /false false % ibid. % /null null % ibid. /R { /resolveR cvx 3 packedarray cvx } bind executeonly % see Objects below .dicttomark readonly def % Get a variable length positive integer value from a stream. A value % of zero is returned if the count is zero. /getintn { % <stream> <count> getintn int 0 exch { 256 mul 1 index read pop add } repeat exch pop % Discard stream } bind executeonly def % This array contains handlers for processing the different types of % entries in the XRef stream. % Stack: <Xrefdict> <xref stream> <Index array> <pair loc> <obj num> % <field 2> <field 3> % The handlers leave the stack unchanged. /xref15entryhandlers [ { % XRef entry type 0 - free or f type xref entry % (free ) print % (obj num: ) print 2 index pdfstring cvs print ( ) print % (loc: ) print 1 index pdfstring cvs print ( ) print % (gen: ) print dup === flush } bind executeonly % Do nothing for free xref entries % XRef entry type 1 - normal or n type xref entry { % field 2 = obj loc, field 3 = gen num % (normal ) print % (obj num: ) print 2 index pdfstring cvs print ( ) print % (loc: ) print 1 index pdfstring cvs print ( ) print % (gen: ) print dup === flush 0 3 1 roll % set stream number = 0 //false setxrefentry 3 -1 roll pop % remove stream number } bind executeonly % XRef entry type 2 - compressed object type xref entry { % field 2 = object stream num, field 3 = index into object stream % (Compressed objects: ) print % (obj num: ) print 2 index pdfstring cvs print ( ) print % (field 2: ) print 1 index pdfstring cvs print ( ) print % (field 3: ) print dup === flush 0 //false setxrefentry pop % set generation number = 0 } bind executeonly ] def % Read the PDF 1.5 version of the xref table. % Note: The position is the location of the start of the dictionary object % In PDF 1.5, the XRef dictionary also serves as the trailer dictionary /readpdf15xref % <pos> readpdf15xref <trailerdict> { /Classic-xref //false store PDFfile exch setfileposition % move to start of object % Get object number, revision, and 'obj' and discard //false PDFfile token { type /integertype eq { PDFfile token { type /integertype eq { PDFfile token { /obj eq or } if } if } if } if } if not { /readpdf15xref cvx /syntaxerror signalerror } if % Get the XRef dicitionary /dictlevelcount 0 def PDFfile xrefopdict .pdfrun % Verify that we have an XRef dictionary dup /Type get /XRef ne { /readpdf15xref cvx /syntaxerror signalerror } if % Ensure that we we have room in the objects array, etc. dup /Size get 1 index /Index .knownget { %% if we have a /Index, remember to add the starting index on to the size dup 0 get 3 -1 roll add exch %% Get the staring index and number of entries from the Index array %% add them, and see if the result is larger than the starting index plus %% Size entry (yes they are *supposed* to be consistent.....) %% Bug #696365 dup 0 get exch 1 get add 2 copy gt { pop }{ exch pop } ifelse } if growPDFobjects % Create a stream for the XRef data PDFfile token pop pop % Skip over 'stream' dup stream //false resolvestream % Stack: <XRefdict> <xref stream> % The Index array defines the ranges of object numbers in the % XRef stream. Each value pair is consists of starting object % number and the count of consecutive objects. % Get the Index array, if present 1 index /Index .knownget not { % If no Index array ... [ 0 3 index /Size get ] % Default = [ 0 Size ] } if % Loop through the Index array 0 2 2 index length 1 sub { % Get start and end of object range 2 copy get % Start of the range dup 3 index 3 index 1 add get % Number of entries in range % Loop through the range of object numbers add 1 sub 1 exch { % Form end of range, set increment = 1 % Stack: <Xrefdict> <xref stream> <Index array> <pair loc> <obj num> % Get xref parameters. Note: The number of bytes for each parameter % is defined by the entries in the W array. 4 index /W get aload pop % Get W array values % The first field indicates type of entry. Get first field value. % If the num. of bytes for field 1 is 0 then default field value is 1 3 -1 roll dup 0 eq { pop 1 } { 6 index exch getintn } ifelse % Get the handler for the xref entry type. We will execute the % handler after we get the other two field values. xref15entryhandlers exch get 3 -1 roll 6 index exch getintn % Get second field 3 -1 roll 6 index exch getintn % Get third field 3 -1 roll exec % Execute Xref entry handler pop pop pop % Remove field values and obj num } for % Loop through Xref entries pop % Remove Index array pair loc } for % Loop through Index array entries pop pop % Remove Index array and xref stream } bind executeonly def % Read the cross-reference table. % <pos> is the position either from the startxref statement or the /Prev % entry in the prior trailer dictionary. /readxref % <pos> readxref <trailerdict> { PDFoffset add PDFfile exch % Check that the given location is within the file. dup PDFfilelen gt { ( **** Warning: Specified xref location is beyond end of file.\n) pdfformatwarning /readxref cvx /invalidaccess signalerror } if setfileposition % In some PDF files, this position actually points to % white space before the xref line. Skip over this here. { PDFfile fileposition PDFfile read pop 32 gt { exit } if pop } loop dup % Make copy of the file position (before last char was read). PDFfile exch setfileposition % The PDF specification says that the 'xref' must be on a line % by itself. The code here formerly used readline and linene to % check this. However, Acrobat Reader only requires the line to % begin with 'xref', and there are enough applications producing % non-compliant PDF files that we have to do this too. PDFfile pdfstring 0 4 getinterval readstring pop (xref) eq { readorigxref % 'xref' -> original xref table % if hybrid-reference PDF, also fetch the entries % found in the XRef stream pointed by /XRefStm dup /XRefStm knownoget { %% Bug #695883 the test file has an XRefStm which points beyond the end of the file. %% We check that here and simply fall back to thje classic xref if this error occurs. dup PDFfilelen lt{ PDFSTOPONERROR not { mark exch {readpdf15xref pop} stopped { ( **** Error: This hybrid file's XRefStm does not point to a valid stream.\n Ignoring error, output may be incorrect.\n) pdfformaterror } if cleartomark } { readpdf15xref pop } ifelse } { ( **** Error: This hybrid file's XRefStm points beyond the end of file.\n Ignoring error, output may be incorrect.\n) pdfformaterror pop }ifelse } if } { readpdf15xref } % otherwise assume PDF 1.5 xref stream ifelse } bind executeonly def % Open a PDF file and read the header, trailer, and cross-reference. /pdfopen { % <file> pdfopen <dict> /NEWPDF where {/NEWPDF get} {//true} ifelse { newpdf_pdfopen } { % Color space substitution in PDF is handled somewhat differently % than in PostScript. A given device color space will be substituted % if the corresponding "Default..." entry exists in the Page's % Resource dictionary (which might be inhereted); there is no % UseCIEColor to enable/disable color mapping. % % This behavior is achieved by always setting UseCIEColor to true % in the page device dictionary. If the value of this parameter was % originally false (i.e.: the output device does not perform color % space substitution by default), the instances DefaultGray, % DefaultRGB, and DefaultCMYK of the (local) ColorSpace category % are redefined to be DeviceGray, DeviceRGB, and DeviceCMYK, % respectively. This is not done if UseCIEColor is true by default, % as in that case color substitution is presumably desired even % if the file does not request it. currentpagedevice /UseCIEColor .knownget dup { pop } if not { .currentglobal //false .setglobal /DefaultGray { /DeviceGray } cvlit /ColorSpace defineresource pop /DefaultRGB { /DeviceRGB } cvlit /ColorSpace defineresource pop /DefaultCMYK { /DeviceCMYK } cvlit /ColorSpace defineresource pop .setglobal } if pdfopenfile begin pdfopencache currentdict end } ifelse } bind executeonly def /process_trailer_attrs { % - process_trailer_attrs - writeoutputintents .writepdfmarks { % Copy bookmarks (outline) to the output. Trailer /Root knownoget { /Outlines knownoget { /NO_PDFMARK_OUTLINES where {pop NO_PDFMARK_OUTLINES not}{//true}ifelse { dup /First known { 100 dict exch %% dictionary for detecting circular references /First get dup type /packedarraytype eq { %% << >> {} or << >> dup 0 get dup %% << >> {} object_num object_num 3 index 3 1 roll %% << >> {} << >> object_num object_num put oforce } if dup type /dicttype eq { { dup /Next known { dup /Next get %% << >> <</Next...>> {} or << >> dup type /packedarraytype eq { dup 0 get %% << >> <</Next....>> {} object_num dup 4 index exch known { (\n **** ERROR: Circular reference detected in Outlines,\n) pdfformaterror ( terminating Outline processing.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror %% << >> <</Next....>> {} object_num pop pop dup /Next undef %% << >> <<.....>> writeoutline exit } if %% << >> <</Next....>> {} object_num dup 3 index 3 1 roll put %% << >> <</Next....>> {} oforce } if exch writeoutline %% << >> </Next object> dup type /dicttype eq not {pop exit} if } { writeoutline exit }ifelse } loop pop } {pop pop} ifelse }{ pop }ifelse } { pop }ifelse } if } if count /pdfemptycount exch def Trailer /Info {knownoget} stopped { ( **** Error: Unable to read Info dictionary from Trailer, Info will not be preserved.\n) pdfformaterror count pdfemptycount sub {pop} repeat /emitProducer where {/emitProducer //false put} if } { { % % Bug #700820, if the Info dictionary isn't a dictionary, then don't try to use it.... % dup type /dicttype eq { mark exch { /Author /Creator /Title /Subject /Keywords % /Producer is Ghostscript; /CreationDate is now; /ModDate is also now. } { 2 copy knownoget { 3 -1 roll } { pop } ifelse } forall pop dup mark ne { {/DOCINFO pdfmark} stopped {cleartomark} if } { pop } ifelse }{ pop ( **** Error: The Info dictionary is not a dictionary, Info will not be preserved.\n) pdfformaterror count pdfemptycount sub {pop} repeat /emitProducer where {/emitProducer //false put} if } ifelse } if } ifelse } if % Initialize OC groups Trailer /Root knownoget { /OCProperties knownoget { % By default, OCGs are 'on'; mark only 'off' OCGs. % If, contrary to the spec, BaseState is OFF, mark all OCGs % and unmark ON ones. Bug 691491. dup /OCGs knownoget not { {} } if exch /D knownoget { dup /BaseState knownoget { /OFF eq } { //false } ifelse { ( **** Warning: Default viewing OC config dictionary has /BaseState /OFF\n) pdfformatwarning 1 index { oforce dup type /dicttype eq { /OFF 0 put } { pop } ifelse } forall /ON knownoget { { oforce dup type /dicttype eq { /OFF undef } { pop } ifelse } forall } if } { /OFF knownoget { { oforce dup type /dicttype eq { /OFF 0 put } { pop } ifelse } forall } if } ifelse } if pop } if } if % Enumerate all AcroForm fields and link all separate widgets % to the parent field. Trailer /Root knownoget { /AcroForm knownoget { %% If we don't have a NeedAppearances entry, treat as if true. %% We know Acrobat always regenerates all annotations. dup /NeedAppearances knownoget not { //true } if { /NeedAppearances //true def dup /Fields knownoget { { oforce %% Make sure the entry from the Fields array is a dictionary %% Bug #692447.pdf has an array of nulls. dup type /dicttype eq { link_widget_annots }if pop } forall } if pop } { pop } ifelse } if } if % Use OutputIntent ICC profile systemdict /UsePDFX3Profile .knownget { dup //false eq { pop } { dup //true eq { pop 0 } if dup type /integertype eq { Trailer /Root oget /OutputIntents knownoget { dup length 2 index le % i [] bool 2 index 0 lt or { pop pop (Source file has no OutputIntent with this number.\n) } { exch oget dup type /dicttype ne { pop << >> } if /DestOutputProfile knownoget { [ /ICCBased 3 -1 roll ] ICCBased-resolve 1 get .set_outputintent () } { (This OutputputIntents dictionary has no profile.\n) } ifelse } ifelse } { pop (File has no /OutputIntents attribute\n) } ifelse } { pop (UsePDFX3Profile must be a boolean or an integer.\n) } ifelse dup () eq { pop } { ( **** ) stderrprint stderrprint } ifelse } ifelse } { % If the user told us to use a named OutputIntent systemdict /UseOutputIntent .knownget { cvn Trailer /Root oget /OutputIntents knownoget { { dup /OutputConditionIdentifier get cvn dup /Custom eq { pop dup /Info get cvn }if 2 index eq { %% Found the required OutputIntent /DestOutputProfile knownoget { [ /ICCBased 3 -1 roll ] ICCBased-resolve 1 get .set_outputintent () } if pop exit }{ pop } ifelse } forall pop }{ pop }ifelse } if }ifelse Trailer /Root knownoget { /PageLabels knownoget { %% Currenlty only the pdfwrite device can handle PageLabels %% because we deal with these using putparams, not pdfmarks %% This is because the pdfmark syntax can't handle all the %% possible page label formats in a PDF file! /WantsPageLabels /GetDeviceParam .special_op { pop pop .pdfpagelabels } { pop } ifelse } if } if } bind executeonly def % Verify that each entry in the xref table is pointing at an object with % the correct object number and generation number. /verify_xref % - verify_xref - { PDFfilelen 1 1 Objects length 1 sub % stack: filesize 1 1 <number of objects - 1> { % Check if the object is free (i.e. not used). The values in % Generations is the generation number plus 1. If the value in % Generations is zero then the object is free. % Stack: <filesize> <obj num> Generations 1 index get % Get the genration number 0 ne { % Skip if object number is free ObjectStream 1 index get % Check if object is in objectstream 0 eq { % We only check objects not in an objectstream { % Use stop context since we may get an error if object is invalid dup Objects exch get % Get the object location PDFoffset add dup 3 index ge % Compare object location to file size { pop //true } % Rebuild if location not in file { PDFfile exch setfileposition % Go to the object location //true % Stack: <filesize> <obj num> <true> PDFfile token pop % Read object number from file 2 index eq { % Verify object number PDFfile token pop % Read generation number from file Generations 3 index % Get specified generaton number get 1 sub % Gen numbs are stored with 1 added. eq { % Verify generation number PDFfile token pop /obj eq { % Verify 'obj' text pop //false % We have valid object, do not rebuild } if } if } if } ifelse } //.internalstopped exec { //true } if % If we stop then we need to rebuild % Stack: <filesize> <obj num> <need rebuild flag> { ( **** Warning: File has an invalid xref entry: ) pdfformatwarning pdfstring cvs pdfformatwarning (. Rebuilding xref table.\n) pdfformatwarning search_objects exit } if % If the entry is invalid } { % The object is in an object stream. We currently do not rebuild % objects in an object stream. So If we find one, then abort the % verification of the xref table entries. pop exit % Pop object number and then exit loop } ifelse % If not in an object stream } if % If object entry is not free pop % Remove object number } for pop % Remove the size of the file } bind odef /pdfopencache { % - pdfopencache - % Create and initialize some caches. /PageCount pdfpagecount def /PageNumbers PageCount 65534 .min dict def /PageIndex PageCount 65534 .min array def } bind executeonly def /pdfopenfile { % <file> pdfopenfile <dict> //pdfdict readonly pop % can't do it any earlier than this 32 dict begin /LocalResources 0 dict def /DefaultQstate //null def % establish binding /Printed where { pop } { % Guess whether the output device is a printer. /Printed currentpagedevice /OutputFile known def } ifelse % If the file name has an odd number of '%', it is either a request for % separate pages, or is invalid. In either case some marks can be omitted. currentpagedevice /OutputFile .knownget { //false exch { 37 eq xor } forall { /NO_PDFMARK_OUTLINES //true def /NO_PDFMARK_DESTS //true def } if } if /PSLevel1 where { pop } { /PSLevel1 //false def } ifelse % NB: PDFfile is used outside of the PDF code to determine that a % PDF job is being processed; to not change or hide this key. cvlit /PDFfile exch def /PDFsource PDFfile def /Repaired //false def /emitProducer //true def /RepairedAnError //false def /StreamRunAborted //false def /NeedAppearances //false def /ICCProfileNError //false def currentglobal //true .setglobal globaldict begin /UndefProcList 0 dict def end .setglobal PDFfile dup 0 setfileposition 0 () /SubFileDecode filter % to avoid file closure pdfstring readstring pop (%PDF-) search not {/pdfopen cvx /syntaxerror signalerror} if length /PDFoffset exch def pop % some badly formed PDF's (Visioneer) have something other than EOL % after the version number. If we get an error, shorten the string % and try again. //false exch % error encountered { { cvr } stopped { exch pop //true exch 0 1 index length 1 sub dup 0 eq { pop 0 exit } if % exit if string now empty getinterval % trim character from right end and retry } { exch { ( **** Warning: PDF version number not followed by EOL.\n) pdfformatwarning } if exit } ifelse } loop /Classic-xref //true def /PDFversion exch def % Read the last cross-reference table. count /pdfemptycount exch def /Trailer << >> def % Initialize to an emptry dict. {initPDFobjects findxref readxref} PDFSTOPONERROR not { //.internalstopped exec { recover_xref_data % Read failed. Attempt to recover xref data. search_trailer % Search for the primary trailer //false % search_trailer sets up /Trailer, so don't run the code to do that... } { //true } ifelse } { exec //true } ifelse { /Trailer exch def % Save trailer dict after first xref table % Read any previous cross-reference tables. When we are done, % verify that the entries in the xref tables are valid if NoVerifyXref % is not defined. /PrevArray [] def % Empty array, we use this to detect circular /Prev entries in xref (see below) % For some reqason, leaving this on the stack messes up seom files. Trailer { /Prev knownoget not { % If no previous xref table then ... Classic-xref { /NoVerifyXref where { pop } { verify_xref } ifelse } if exit } if %% This code is used to detect circular references in xref tables. Every time %% we detect a /Prev in the xref, we check the given offset of the /Prev xref %% against a list of all previously encountered /Prev offsets. If we find that %% we have previously seen this one, we raise an error, stop processing the xref %% but carry on with the PDF file (unless PDFSTOPONERROR is true). //false exch PrevArray %% Used to determine if the looop found a circular ref { %% //false offset 'array entry' 1 index eq { exch pop //true exch %% We've seen this offset before, pop the false and replace with true exit %% //true offset } if } forall exch %% [...] offset bool { (\n **** Error: Circular /Prev entry while reading xref.\n Aborting xref read, output may be incorrect.\n) pdfformaterror PDFSTOPONERROR { /readxref cvx /syntaxerror signalerror } if pop exit %% [...] and then exit this loop } if PrevArray dup %% offset [...] [...] length 1 add array %% offset [...] [ ] dup 3 1 roll %% offset [ ] [...] [ ] copy pop %% offset [... ] dup dup length 1 sub %% offset [... ] [... ] index 3 index %% offset [... ] [... ] index offset put /PrevArray exch def { readxref } PDFSTOPONERROR not { //.internalstopped exec { recover_xref_data % Read failed. Attempt to recover xref data. /PrevArray where {/PrevArray undef} if %% remove the array we were using to detect circular references exit % Exit loop since recover gets all obj data. } if % If readxref stopped } { exec } ifelse % The PDF spec. says that each trailer dict should contain the required % entries. However we have seen a PDF file that only has a Prev entry in % the initial trailer dict. Acrobat complains but it accepts these files. % To work with these files, we are copying any entries which we find in % a previous trailer dict which are not present in the initial dict. dup { Trailer 2 index known { pop pop % discard if key already present } { Trailer 3 1 roll put % add key if not present } ifelse } forall } loop % Loop to previous trailer /PrevArray where {/PrevArray undef} if %% remove the array we were using to detect circular references } if /NumObjects Objects length def % To check that obj# < NumObjects % Scan numbers in the range 2147483648..4294967295 in Encrypt dictionary % as unsigned integers for compatibility with Acrobat Reader. Bug 689010. << /PDFScanUnsigned //true >> setuserparams { Trailer /Encrypt knownoget { pop pdf_process_Encrypt % signal error } if } stopped << /PDFScanUnsigned //false >> setuserparams { stop } if % Check for recursion in the page tree. Bug 689954, MOAB-06-01-2007 % Make sure that the operand stack is cleaned up in case there's % an error and we ignore it (bug #700953) /StackMarkVerifyPageTree verify_page_tree /StackMarkVerifyPageTree ClearToKey currentdict end } bind executeonly def %% Executing token on a file will close the file if we reach EOF while %% processing. When repairing broken files (or searching for startxref %% and the xref offset) we do *NOT* want this to happen, because that %% will close PDFfile and we don't have the filename to reopen it. /token_no_close { %% -file- token_no_close <any> true | false dup type /filetype eq { << /EODCount 2 index bytesavailable %% fix data length at underlying bytes /EODString () %% make sure filter passes that many bytes, no EOD /CloseSource //false %% Be sure, tell the filter not to close the source file >> /SubFileDecode filter dup %% -filter- -filter- token { %% -filter- <any> true | false %% token returned a value exch %% <any> filter closefile %% <any> //true %% <any> true }{ %% token didn't find a value closefile %% - //false %% false } ifelse } { token } ifelse } bind executeonly def % Look for the last (startxref) from the current position % of the file. Return the position after (startxref) if found or -1 . /find-startxref { % <file> find_eof <file> <position> -1 { 1 index dup 0 (startxref) /SubFileDecode filter flushfile bytesavailable 9 lt { exit } if pop dup fileposition } loop } bind executeonly def % Search for the last 'startxfer' and read a following token, which % must be a number. Don't pay any attention to %%EOF because it's % often mangled. % There seems to be no limit on the amount of garbage that can be % appended to the PDF file. Current record (60K) belongs to % PDF-Out (v 2.0 - 35). We start the search from the last 1024 % bytes and continue from the beginning of the file. /findxref { % - findxref <xrefpos> PDFfile dup dup dup 0 setfileposition bytesavailable dup /PDFfilelen exch def % Find the last %%EOF string (within 1024 bytes) 1024 sub PDFoffset .max setfileposition find-startxref % file pos|-1 % search the last 1024 bytes dup 0 le { pop dup PDFoffset setfileposition find-startxref % search from the beginnibg dup 0 le { ( **** Error: Cannot find a 'startxref' anywhere in the file.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror /findxref cvx /syntaxerror signalerror } if } if 2 copy setfileposition pop token_no_close not { //null } if dup type /integertype ne { ( **** Error: invalid token after startxref.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror /findxref cvx /syntaxerror signalerror } if } bind executeonly def /stderrfile (%stderr) (w) file def /stdoutfile (%stdout) (w) file def /stderrprint { % <string> stderrprint - //stderrfile dup 3 -1 roll writestring flushfile } bind executeonly def /stdoutprint { % <string> stderrprint - //stdoutfile dup 3 -1 roll writestring flushfile } bind executeonly def /pdfformaterror { % <string> pdfformaterror - stdoutprint /Repaired //true store /RepairedAnError //true store } bind executeonly def /pdfformatwarning { % <string> pdfformaterror - QUIET not {stdoutprint}{pop}ifelse /Repaired //true store PDFSTOPONWARNING {/warning cvx /undefined signalerror} if } bind executeonly def /knownoget_safe { 2 copy knownoget { 3 1 roll pop pop //true } { pop pop //false } ifelse } odef /printProducer { Trailer /Info { knownoget_safe } stopped { pop pop //false } if { /emitProducer where {/emitProducer get}{//true} ifelse { /Producer knownoget not { //null } if }{ pop //null } ifelse } { //null } ifelse dup //null eq { pop } { ( **** The file was produced by: \n **** >>>> ) stderrprint % Handle a Unicode Producer. (\376\377) anchorsearch { pop dup length 2 idiv string 0 1 2 index length 1 sub { % Stack: origstr newstr i 1 index exch 3 index 1 index 2 mul 1 add get put } for exch pop } if stderrprint ( <<<<\n) stderrprint } ifelse } bind executeonly def % The UndefProcList collects noisy warnings. % This gets rid of many multiple warnings from pdf_font.ps /printCollectedWarnings { UndefProcList length 0 gt { (\n **** Embedded font uses undefined procedure\(s\): ) stderrprint UndefProcList { exch .namestring stderrprint ( ) stderrprint =string cvs stderrprint ( times, ) stderrprint } forall (\n) stderrprint } if } bind executeonly def /printrepaired { QUIET not { printCollectedWarnings (\n **** This file had errors that were repaired or ignored.\n) stdoutprint printProducer ( **** Please notify the author of the software that produced this\n) stdoutprint ( **** file that it does not conform to Adobe's published PDF\n) stdoutprint ( **** specification.\n\n) stdoutprint } if } bind executeonly def /printrepairederror { QUIET not { printrepaired ( **** The rendered output from this file may be incorrect.\n) stdoutprint } if } bind executeonly def % Write the outline structure for a file. Uses linkdest (below). % omit links to pages that don't exist. /writeoutline % <outlinedict> writeoutline - { mark 0 2 index /First knownoget { { exch 1 add exch /Next knownoget not { exit } if } loop } if % stack: dict mark count dup 0 eq { pop 1 index } { 2 index /Count knownoget { 0 lt { neg } if } if /Count exch 3 index } ifelse { dup /A knownoget { dup /URI known { /A mark 3 2 roll % <<>> /A [ <<action>> { oforce } forall .dicttomark 3 2 roll } { dup /S knownoget { %% Because we process GoTo Destinations into absolute references in the PDF file %% we need to resolve the /D or /Dest. However, we must *not* do this for %% GoToR Destinations because (obviously) those are in a different file and %% we cannot resolve them into absolute references. We don't need to anyway %% because that file must already have a named destination. dup /GoTo eq { pop dup /D knownoget { exch pop exch dup length dict copy dup /Dest 4 -1 roll put } if }{ dup /GoToR eq { pop /A mark % <<..action dict..>> /A [ 3 2 roll % /A [ <<..action dict..>> { oforce } forall .dicttomark 3 2 roll }{ dup /Launch eq { pop /A mark % <<..action dict..>> /A [ 3 2 roll % /A [ <<..action dict..>> { oforce } forall .dicttomark 3 2 roll }{ /Named eq { /N knownoget { % Assume /S /Named namedactions exch .knownget { exec } if } if } if } ifelse } ifelse } ifelse } if } ifelse } if linkdest } stopped { cleartomark % ignore this link ( **** Warning: Outline has invalid link that was discarded.\n) pdfformatwarning } { /Title knownoget { {/Title exch /OUT pdfmark} stopped {cleartomark} if } { cleartomark ( **** Warning: Outline without /Title attribute was discarded.\n) pdfformatwarning } ifelse } ifelse /First knownoget { { dup writeoutline /Next knownoget not { exit } if } loop } if } bind executeonly def % Close a PDF file. /pdfclose % <dict> pdfclose - { begin PDFfile closefile end } bind executeonly def % ======================== Page accessing ======================== % % Get a (possibly inherited) attribute of a page. /pget % <pagedict> <key> pget <value> -true- % <pagedict> <key> pget -false- { 2 copy knownoget { exch pop exch pop //true } { %% Check to see if there's a Parent 1 index 3 1 roll exch /Parent knownoget { %% If there is a Parent, check to see if this dictionary has a stored object number 3 -1 roll /.gs.pdfobj# .knownget { %% if it does, check the Parent as wwell 1 index /.gs.pdfobj# .knownget { %% Both have object numbers, are they the same (ie its self-referencing) eq { pop pop //false }{ exch pget }ifelse }{ pop exch pget }ifelse } { exch pget }ifelse } % finally see if the key is (misplaced) in the Root Catalog dict { exch pop dup Trailer /Root oget exch knownoget dup { 3 -1 roll ( **** Error: The /) pdfformaterror 50 string cvs pdfformaterror ( key is missing from the Page tree.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror } { exch pop } ifelse } ifelse } ifelse } bind executeonly def /parent_obj_get { % /ResourceName pagedict /ObjType LocalResourceDir /ParentResources .knownget { dup 2 index .knownget { % Found ObjType directory 4 index .knownget { 0 get 5 1 roll pop pop pop pop } { parent_obj_get % not found -- check it's parent. } ifelse } { parent_obj_get % not found -- check it's parent. } ifelse } { pop pop 0 } ifelse } bind executeonly def /obj_get { % /ResourceName pagedict /ObjType obj_get % success: /ResourceName objnumber % fail: /ResourceName /ResourceName 0 LocalResources 1 index knownoget { dup 4 index .knownget { 0 get 5 1 roll pop pop pop pop } { pop pop pop 0 } ifelse } { % Not in LocalResources. Try Page Resources. 1 index /Resources pget { 1 index knownoget { dup 4 index known { 3 index get 0 get 4 1 roll pop pop pop }{ % Not in Page Resources, recursively try ParentResources as a last resort pop % page Resources LocalResources parent_obj_get }ifelse }{ % No Page Resources, recursively try ParentResources as a last resort LocalResources parent_obj_get } ifelse } { % No Page Resources, recursively try ParentResources as a last resort pop pop pop 0 }ifelse }ifelse }bind executeonly def % Get the value of a resource on a given page. /rget { % <resname> <pagedict> <restype> rget <value> -true- % <resname> <pagedict> <restype> rget -false- LocalResources 1 index knownoget { 3 index knownoget } { //false } ifelse { exch pop exch pop exch pop //true } { 1 index /Resources pget { 1 index knownoget { 3 index knownoget } { //false } ifelse } { //false } ifelse { 4 1 roll pop pop pop //true } { countdictstack array dictstack //false 5 1 roll dup length 1 sub -1 4 { % false /Name <<>> /Type [<<gstate>>] i 1 index exch get % false /Name <<>> /Type [] <<gstate>> /FormResDict .knownget { % false /Name <<>> /Type [] <<res>> 2 index knownoget { % false /Name <<>> /Type [] <<type_dict>> 4 index knownoget { % false /Name <<>> /type [] <<res_dict>> ( **** Warning: resource was found only in an external (parent) context.\n) pdfformatwarning //true 7 2 roll % <<res_dict>> true false /Name <<>> /Type [] pop exit } if } if } if } for pop pop pop pop } ifelse } ifelse } bind executeonly def % Get the total number of pages in the document. /pdfpagecount % - pdfpagecount <int> { Trailer /Root knownoget { /Pages knownoget { dup /Count knownoget { dup type /integertype eq { dup 0 le } { //true } ifelse { pop dup /Kids knownoget { pop ( **** Warning: Invalid Page count.\n) pdfformatwarning % find the last page and use that as the Count 1 1 999999999 { dup pdffindpage? exch pop //null eq { exit } { pop } ifelse } for 1 sub % decrement to last page that we were able to find 2 copy /Count exch put } { 0 % return 0 and keep 0 page count. ( **** Warning: PDF document has no pages.\n) pdfformatwarning } ifelse } if exch pop } { dup /Type oget /Page eq { << exch 1 array astore /Kids exch /Count 1 /Type /Pages >> Trailer /Root oget /Pages 3 -1 roll put 1 ( **** Warning: No /Pages node. The document /Root points directly to a page.\n) pdfformatwarning } { ( **** Warning: Page count not found; assuming 1.\n) pdfformatwarning pop 1 } ifelse } ifelse } { 0 }ifelse }{ 0 } ifelse } bind executeonly def % Check for loops in the 'page tree' but accept an acyclic graph. % - verify_page_tree - /verify_page_tree { % Run the verification inside a 'stopped' context. Bug #700953 % has a peculiarly constructed page tree, and a huge number of % pages, which recurses to a depth beyond the level we can cope % with on the exec stack. If we ignore that error then we can { Trailer /Root knownoget { /Pages knownoget { 10 dict begin /Count pdfpagecount def /verify_page_tree_recursive { Count 0 gt { dup 1 def dup /Kids knownoget { { oforce dup //null ne { currentdict 1 index known { ( **** Error: there's a loop in the Pages tree. Giving up.\n) pdfformaterror /verify_page_tree cvx /syntaxerror signalerror } if verify_page_tree_recursive } { pop } ifelse } forall } { /Count Count 1 sub def }ifelse currentdict exch undef } { pop ( **** Error: Too many pages in Page tree.\n) pdfformaterror } ifelse } def verify_page_tree_recursive end } if } if } stopped { %% Specific check for syntax error, in this case assume we found a loop in the Pages tree. %% (see above). Otherwise, just try to process the file anyway. $error /errorname get /syntaxerror eq { /verify_page_tree cvx /syntaxerror signalerror } { ( **** Error: Something went wrong while checking for recursion in the Page tree. Giving up checking.\n This PDF file may not terminate, if there is a loop in the Pages tree.\n) pdfformaterror } ifelse } if } bind executeonly def /pdffindpage? { % <int> pdffindpage? 1 null (page not found) % <int> pdffindpage? 1 noderef (page found) % <int> pdffindpage? 0 null (Error: page not found) Trailer /Root oget /Pages get { % We should be able to tell when we reach a leaf % by finding a Type unequal to /Pages. Unfortunately, % some files distributed by Adobe lack the Type key % in some of the Pages nodes! Instead, we check for Kids. dup oforce /Kids knownoget not { exit } if exch pop //null 0 1 3 index length 1 sub { 2 index exch get dup oforce dup //null eq { PDFSTOPONERROR { /pdffindpage? cvx /syntaxerror signalerror } { ( **** Error: Ignoring a null node in the Page tree.\n) pdfformaterror pop pop } ifelse } { dup /Kids known { /Count oget } { pop 1 } ifelse % Stack: index kids null noderef count dup 5 index ge { pop exch pop exit } if 5 -1 roll exch sub 4 1 roll pop } ifelse } for exch pop % Stack: index null|noderef dup //null eq { pop pop 1 //null exit } if } loop } bind executeonly def % Find the N'th page of the document by iterating through the Pages tree. % The first page is numbered 1. /pdffindpageref { % <int> pdffindpage <objref> dup pdffindpage? % Stack: index countleft noderef dup //null ne { 1 index 1 ne { pop pop /pdffindpage cvx /rangecheck signalerror } if exch pop PageIndex 2 index 1 sub 65533 .min 2 index oforce put PageNumbers 1 index oforce 3 index dup 65534 le { put } { pop pop pop } % don't store more than 65534 pagenumbers ifelse } { exch pop % return the //null } ifelse exch pop % pop the page number, return the object or null } bind executeonly def /pdffindpage { % <int> pdffindpage <pagedict> pdffindpageref oforce } bind executeonly def % Find the N'th page of the document. % The first page is numbered 1. /pdfgetpage % <int> pdfgetpage <pagedict> { PageIndex 1 index 1 sub dup 65533 lt { get } { pop pop //null } ifelse dup //null ne { exch pop oforce } { pop pdffindpage } ifelse } bind executeonly def % Find the page number of a page object (inverse of pdfgetpage). /pdfpagenumber % <pagedict> pdfpagenumber <int> { % We use the simplest and stupidest of all possible algorithms.... PageNumbers 1 index .knownget { exch pop } { 1 1 PageCount 1 add % will give a rangecheck if not found { dup pdfgetpage oforce 2 index eq { exit } if pop } for exch pop } ifelse } bind executeonly def % Arrange the four elements that define a rectangle into a 'normal' order. /normrect_elems % <x1> <y1> <x2> <y2> normrect_elems <llx> <lly> <urx> <ury> { 4 { % Bug 693919 dup type dup /integertype ne exch /realtype ne and { ( **** Error: replacing malformed number ') pdfformaterror pdfstring cvs pdfformaterror (' with 0.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror 0 } if 4 1 roll } repeat exch 4 1 roll % <x2> <x1> <y1> <y2> 2 copy gt { exch } if % <x2> <x1> <lly> <ury> 4 2 roll 2 copy lt { exch } if % <lly> <ury> <urx> <llx> 4 1 roll exch % <llx> <lly> <urx> <ury> } bind executeonly def % Arrange a rectangle into a 'normal' order. I.e the lower left corner % followed by the upper right corner. /normrect % <rect> normrect <rect> { aload pop normrect_elems 4 array astore } bind executeonly def /fix_empty_rect_elems % </Name> <x1> <y1> <x2> <y2> fix_empty_rect_elems <x1> <y1> <x2'> <y2'> { dup 3 index eq { //true } { 1 index 4 index eq } ifelse { pop pop pop pop ( **** Warning: File has an empty ) pdfformaterror pdfstring cvs pdfformaterror (. Using the current page size instead.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror 0 0 currentpagedevice /PageSize get aload pop } { 5 -1 roll pop } ifelse } bind executeonly def /boxrect % <llx> <lly> <urx> <ury> boxrect <x> <y> <w> <h> { exch 3 index sub exch 2 index sub } bind executeonly def /resolvedest { % <name|string|other> resolvedest <other|null> dup type /nametype eq { Trailer /Root oget /Dests knownoget { exch knownoget not { //null } if } { pop //null } ifelse } { dup type /stringtype eq { Trailer /Root oget /Names knownoget { /Dests knownoget { exch nameoget } { pop //null } ifelse } { pop //null } ifelse } if } ifelse } bind executeonly def % Procedures to do the necessary transformations of view destinations % <PDF2PS_matrix> <rot> <view> -- <view'> /viewdestprocs 8 dict dup begin /Fit { exch pop exch pop } bind executeonly def /FitH { aload length 2 lt { 1 array astore 3 1 roll pop pop }{ 0 4 -1 roll 1 and 0 eq { exch } if 4 -1 roll transform exch pop 2 array astore } ifelse } bind executeonly def /FitV { aload length 2 lt { 1 array astore 3 1 roll pop pop }{ 0 4 -1 roll 1 and 0 ne { exch } if 4 -1 roll transform pop 2 array astore } ifelse } bind executeonly def /FitB /Fit load def /FitBH /FitH load def /FitBV /FitV load def /XYZ { dup length dup 4 gt { pop /viewdestprocs cvx /rangecheck signalerror }{ dup 4 eq { pop aload pop } { dup 3 eq { pop aload pop //null } { dup 2 eq { pop aload pop //null //null } { dup 1 eq { pop aload pop //null //null //null } { pop /viewdestprocs cvx /rangecheck signalerror } ifelse } ifelse } ifelse } ifelse } ifelse 3 1 roll 2 copy 7 -1 roll 1 and 0 ne { exch } if 4 2 roll % odd rotation switches x<->y 2 { dup //null eq { pop 0 } if exch } repeat % replace nulls with 0 7 -1 roll transform % transform coordinates 2 { 3 -1 roll //null eq { pop //null } if exch } repeat % put the nulls back 3 -1 roll 4 array astore } bind executeonly def /FitR { exch pop aload pop 2 { 5 index transform 4 2 roll } repeat normrect_elems 5 array astore exch pop } bind executeonly def end readonly def /linkdest { % <link|outline> linkdest % ([/Page <n>] /View <view> | ) <link|outline> dup /NewWindow knownoget { /NewWindow exch 3 -1 roll } if dup /F knownoget { /File exch 3 -1 roll } if dup /Dest knownoget { resolvedest dup type /dicttype eq { /D knownoget not { //null } if } if dup //null eq { pop } { dup 0 oget //false % don't have a page# and transformation matrix (yet) 1 index type /dicttype eq { 1 index /Type knownoget { /Page eq { pop % the "false" flag dup pdf_cached_PDF2PS_matrix exch dup /Rotate pget not { 0 } if cvi 90 idiv exch pdfpagenumber /CumulativePageCount where {pop CumulativePageCount}{0}ifelse add //true % now we have a page# and a transformation matrix } if } if } if % stack: <link|outline> <dest> ( <PDF2PS_matrix> <rot> <page#> true | <page> false ) { /Page exch 6 2 roll % stack: [/Page <page#>] <link|outline> <dest> <PDF2PS_matrix> <rot> 3 -1 roll dup length 1 sub 1 exch getinterval /View 4 1 roll % stack: [/Page <page#>] <link|outline> /View <PDF2PS_matrix> <rot> <view> //viewdestprocs 1 index 0 get get exec 3 -1 roll } { dup type /integertype eq { /CumulativePageCount where {pop CumulativePageCount}{0}ifelse add /Page exch 1 add 4 2 roll } { pop } ifelse dup length 1 sub 1 exch getinterval /View exch 3 -1 roll } ifelse } ifelse } if } bind executeonly def %% Used to recursively check dictionaries for any /.gs.pdfobj# keys %% and remove them if so %% -any- /Removepdfobj# -any- /Removepdfobj# { dup type /dicttype eq { dup /.gs.pdfobj# known { dup /.gs.pdfobj# undef } if dup {Removepdfobj# 2 index 3 1 roll put} forall } if }bind executeonly def % <pagedict> mark ... -proc- <page#> <error> /namedactions 8 dict dup begin /FirstPage { 1 /CumulativePageCount where {pop CumulativePageCount}{0}ifelse add //false } bind executeonly def /LastPage { pdfpagecount /CumulativePageCount where {pop CumulativePageCount}{0}ifelse add //false } bind executeonly def /NextPage { counttomark 2 add index pdfpagenumber 1 add dup pdfpagecount gt exch /CumulativePageCount where {pop CumulativePageCount}{0}ifelse add exch} bind executeonly def /PrevPage { counttomark 2 add index pdfpagenumber 1 sub dup 1 lt exch /CumulativePageCount where {pop CumulativePageCount}{0}ifelse add exch} bind executeonly def end readonly def % <pagedict> <annotdict> -proc- - % **** The following procedure should not be changed to allow clients % **** to directly interface with the constituent procedures. GSview % **** and some Artifex customers rely on the pdfshowpage_init, % **** pdfshowpage_setpage, pdfshowpage_finish so all logic should be % **** implemented in one of those three procedures. /pdfshowpage % <pagedict> pdfshowpage - { dup /Page exch store pdfshowpage_init % <pagedict> pdfshowpage_setpage % <pagedict> pdfshowpage_finish % - } bind executeonly def /pdfpagecontents % <pagedict> pdfpagecontents <contents> { } bind executeonly def /pdfshowpage_init % <pagedict> pdfshowpage_init <pagedict> { /DSCPageCount DSCPageCount 1 add store } bind executeonly def /get_media_box { % <pagedict> get_media_box <box> <bool> /MediaBox pget { oforce_array dup length 4 eq { //true } { pop ( **** Error: Page has an invalid /MediaBox attribute. Using the current page size.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror [ 0 0 currentpagedevice /PageSize get aload pop ] //false }ifelse } { ( **** Error: Page has no /MediaBox attribute. Using the current page size.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror [ 0 0 currentpagedevice /PageSize get aload pop ] //false } ifelse } bind executeonly def /get_any_box { % <pagedict> get_any_box <box name> <box> //systemdict /UseBleedBox .knownget dup { and } if { dup /BleedBox pget { /BleedBox exch } if } if //systemdict /UseTrimBox .knownget dup { and } if { dup /TrimBox pget { /TrimBox exch } if } if dup type /arraytype ne { //systemdict /UseArtBox .knownget dup { and } if { dup /ArtBox pget { /ArtBox exch } if } if } if dup type /arraytype ne { //systemdict /UseCropBox .knownget dup { and } if { dup /CropBox pget { /CropBox exch } if } if } if dup type /arraytype ne { /MediaBox exch get_media_box pop } { oforce_elems % <<pdict>> /SomeBox x0 y0 x1 y1 %% Complicated stuff. We need to use the 'Box' we identified (if any), but we %% need to clamp the boundaries of the 'Box' to the MediaBox. This appears to %% be what Acrobat does. The complication arises because the Box values don't %% have to be sensibly positive, its permissible to have the MediaBox set up %% so that it extends down and left instead of up and right. We take care of the %% content when we st up the CTM, but we do need to make sure that we clamp %% the BoundingBox, and that means we need to take direcitonality into account... 6 -1 roll get_media_box { % /SomeBox x0 y0 x1 y1 [MediaBox] aload pop % /SomeBox x0 y0 x1 y1 X0 Y0 X1 Y1 %% Start with the width, get the X0 and X1 values of the MediaBox 3 index % /SomeBox x0 y0 x1 y1 X0 Y0 X1 Y1 X0 2 index % /SomeBox x0 y0 x1 y1 X0 Y0 X1 Y1 X0 X1 gt { %% Media extends to left 4 -1 roll % /SomeBox x0 y0 x1 y1 Y0 X1 Y1 X0 8 -1 roll % /SomeBox y0 x1 y1 Y0 X1 Y1 X0 x0 .min % /SomeBox y0 x1 y1 Y0 X1 Y1 mX0 7 1 roll % /SomeBox mX0 y0 x1 y1 Y0 X1 Y1 exch % /SomeBox mX0 y0 x1 y1 Y0 Y1 X1 5 -1 roll % /SomeBox mX0 y0 y1 Y0 Y1 X1 x1 .max % /SomeBox mX0 y0 y1 Y0 Y1 mX1 5 1 roll % /SomeBox mX0 mX1 y0 y1 Y0 Y1 }{ %% Media extends to right 4 -1 roll % /SomeBox x0 y0 x1 y1 Y0 X1 Y1 X0 8 -1 roll % /SomeBox y0 x1 y1 Y0 X1 Y1 X0 x0 .max % /SomeBox y0 x1 y1 Y0 X1 Y1 mX0 7 1 roll % /SomeBox mX0 y0 x1 y1 Y0 X1 Y1 exch % /SomeBox mX0 y0 x1 y1 Y0 Y1 X1 5 -1 roll % /SomeBox mX0 y0 y1 Y0 Y1 X1 x1 .min % /SomeBox mX0 y0 y1 Y0 Y1 mX1 5 1 roll % /SomeBox mX0 mX1 y0 y1 Y0 Y1 } ifelse %% Now deal with the height 2 copy % /SomeBox mX0 mX1 y0 y1 Y0 Y1 Y0 Y1 gt { %% Media extends down exch % /SomeBox mX0 mX1 y0 y1 Y1 Y0 4 -1 roll % /SomeBox mX0 mX1 y1 Y1 Y0 y0 .min % /SomeBox mX0 mX1 y1 Y1 mY0 3 1 roll % /SomeBox mX0 mX1 mY0 y1 Y1 .max % /SomeBox mX0 mX1 mY0 mY1 }{ %% Media extends up exch % /SomeBox mX0 mX1 y0 y1 Y1 Y0 4 -1 roll % /SomeBox mX0 mX1 y1 Y1 Y0 y0 .max % /SomeBox mX0 mX1 y1 Y1 mY0 3 1 roll % /SomeBox mX0 mX1 mY0 y1 Y1 .min % /SomeBox mX0 mX1 mY0 mY1 } ifelse exch % /SomeBox mX0 mX1 mY1 mY0 3 1 roll % /SomeBox mX0 mY0 mX1 mY1 } { pop } ifelse 4 array astore % /SomeBox [mX0 mY0 mX1 mY1] } ifelse } bind executeonly def % Compute the matrix that transforms the PDF->PS "default" user space /pdf_PDF2PS_matrix { % <pdfpagedict> -- matrix matrix currentmatrix matrix setmatrix exch % stack: savedCTM <pdfpagedict> dup get_any_box % stack: savedCTM <pdfpagedict> /Trim|Crop|Art|MediaBox <Trim|Crop|Art|Media Box> oforce_elems normrect_elems fix_empty_rect_elems 4 array astore //systemdict /PDFFitPage known { PDFDEBUG { (Fiting PDF to imageable area of the page.) = flush } if currentpagedevice /.HWMargins get aload pop currentpagedevice /PageSize get aload pop % Adjust PageSize and .HWMargins for the page portrait/landscape orientation 2 copy gt % PageSize_is_landscape 7 index aload pop 3 -1 roll sub 3 1 roll exch sub exch 10 index /Rotate pget not { 0 } if cvi 90 idiv 1 and 0 ne { exch } if gt % Box_is_landscape xor % PageSize_is_landscape(or square) xor'ed with Box_is_lanscape suggests rotate 2 index 2 index eq not and { % don't rotate if Page is square 1 index 0 translate 90 rotate % add in a rotation PDFDEBUG { ( Rotating the page for best fit) = flush } if 2 copy ne { % rotate the .HWMargins 2 copy lt { 6 2 roll 4 -1 roll 6 -2 roll } { 6 2 roll 4 1 roll 6 -2 roll } ifelse % rotate the page dimensions exch } if } if 3 -1 roll sub 3 1 roll exch sub exch % stack: savedCTM <pdfpagedict> <Crop|Media Box> Xmin Ymin Xmax Ymax PDFDEBUG { ( Translate up by [ ) print 3 index =print (, ) print 2 index =print ( ]) = flush } if 3 index 3 index translate % move origin up to imageable area 2 index sub exch 3 index sub exch 4 2 roll pop pop % stack: savedCTM <pdfpagedict> [Box] XImageable YImageable 2 index aload pop 2 index sub exch 3 index sub exch 4 2 roll pop pop 5 index /Rotate pget not { 0 } if cvi 90 idiv 1 and 0 ne { exch } if % stack: savedCTM <pdfpagedict> [Box] XImageable YImageable XBox YBox 4 copy 3 -1 roll exch div 3 1 roll div .min % stack: savedCTM <pdfpagedict> [Box] XImageable YImageable XBox YBox scale PDFDEBUG { ( Scale by ) print dup = flush } if 5 -4 roll % stack: savedCTM <pdfpagedict> [Box] scale XImageable YImageable XBox YBox 3 index 2 index 6 index mul sub 2 div 3 index 2 index 7 index mul sub 2 div PDFDEBUG { ( Centering translate by [ ) print 1 index =print (, ) print dup =print ( ]) = flush } if translate pop pop pop pop } { //systemdict /NoUserUnit .knownget not { //false } if { 1 } { 1 index /UserUnit knownoget { /PassUserUnit /GetDeviceParam .special_op { exch pop dup { [ /UserUnit 4 -1 roll .pdfputparams pop pop 1 exch } if }{ //false }ifelse not { PDFDEBUG { (Scaling due to UserUnit by ) print dup = flush } if } if } { /PassUserUnit /GetDeviceParam .special_op { exch pop { [ /UserUnit 1 .pdfputparams pop pop } if 1 }{ 1 } ifelse } ifelse } ifelse } ifelse % stack: savedCTM <pdfpagedict> [Box] scale dup scale % Rotate according to /Rotate aload pop boxrect { { pop pop } { -90 rotate pop neg 0 translate } { 180 rotate neg exch neg exch translate } { 90 rotate neg 0 exch translate pop } } 5 index /Rotate pget not { 0 } if cvi PDFDEBUG { dup 0 ne { (Rotating by ) print dup =print ( degrees.) = flush } if } if 90 idiv 3 and get exec % Now translate to the origin given in the Crop|Media Box exch neg exch neg translate % stack: savedCTM <pdfpagedict> pop matrix currentmatrix exch setmatrix } bind executeonly def % Cache the matrix that transforms the PDF->PS "default" user space % into <pdfpagedict> under the key //PDF2PS_matrix_key, then return it /PDF2PS_matrix_key (PDF->PS matrix) cvn def /pdf_cached_PDF2PS_matrix { % <pdfpagedict> -- <PDF2PS_matrix> dup //PDF2PS_matrix_key .knownget { exch pop } { dup dup pdf_PDF2PS_matrix //PDF2PS_matrix_key exch put //PDF2PS_matrix_key get } ifelse } bind executeonly def currentdict /PDF2PS_matrix_key undef /.pdfshowpage_Install { % <pagedict> [<prevproc>] .pdfshowpage_Install - 0 get exec pdf_cached_PDF2PS_matrix concat } bind executeonly def /pdfshowpage_setpage { % <pagedict> pdfshowpage_setpage <pagedict> 6 dict begin % for setpagedevice % Stack: pdfpagedict % This comment is no longer true, and is maintained here for history only: % % UseCIEColor is always true for PDF; see the comment in runpdf above % % We now test the page to see if it defines any Default* colour spaces and % only set UseCIEColor if it does. This prevents a spurious warning from % pdfwrite about not using UseCIEColor with pdfwrite. % pdfshowpage_detect_cspacesub { /UseCIEColor //true def } if % Only lock in Orientation if we need to for pdfmarks .writepdfmarks { /Orientation 0 def } if currentpagedevice % Stack: pdfpagedict currentpagedevicedict 1 index get_any_box % Stack: pdfpagedict currentpagedevicedict /BoxName [box] oforce_elems normrect_elems fix_empty_rect_elems boxrect 4 2 roll pop pop 3 index /Rotate pget not { 0 } if cvi 90 idiv 1 and 0 ne { exch } if % stack: pdfpagedict currentpagedevicedict boxwidth boxheight //systemdict /PDFFitPage known { % Preserve page size, % but choose portrait/landscape depending on box width:height ratio % (if box width == height, select portrait orientation) gt 1 index /PageSize get aload pop 2 copy gt 4 -1 roll ne { exch } if } { % Set the page size. //systemdict /NoUserUnit .knownget not { //false } if not { 3 index /UserUnit knownoget { /PassUserUnit /GetDeviceParam .special_op { exch pop dup { [ /UserUnit 4 -1 roll .pdfputparams pop pop } if }{ //false }ifelse not { dup 4 -1 roll mul 3 1 roll mul } if } { /PassUserUnit /GetDeviceParam .special_op { exch pop { [ /UserUnit 1 .pdfputparams pop pop } if }if } ifelse } if } ifelse 2 array astore /PageSize exch def % Determine the number of spot colors used on the page. Note: This searches % the pages resources. It may be high if a spot color is in a resource but % is not actually used on the page. currentpagedevice /PageSpotColors known { /PageSpotColors 2 index countspotcolors userdict /PageSpotColors 2 index put def } if % If the user told us to use a named OutputIntent systemdict /UseOutputIntent .knownget { cvn % Check to see if this page has such an OutputIntent 2 index /OutputIntents knownoget { { dup /OutputConditionIdentifier get cvn dup /Custom eq { pop dup /Info get cvn }if 2 index eq { %% Found the required OutputIntent /DestOutputProfile knownoget { [ /ICCBased 3 -1 roll ] ICCBased-resolve 1 get .set_outputintent () } if pop exit }{ pop } ifelse } forall pop }{ pop }ifelse } if % Let the device know if we will be using PDF 1.4 transparency. % The clist logic may need to adjust the size of bands. 1 index pageusestransparency /PageUsesTransparency exch def dup /Install .knownget { % Don't let the Install procedure get more deeply % nested after every page. dup type dup /arraytype eq exch /packedarraytype eq or { dup length 4 eq { dup 2 get /.pdfshowpage_Install load eq { 1 get 0 get % previous procedure } if } if } if } { { } } ifelse 1 array astore 2 index exch /.pdfshowpage_Install load /exec load 4 packedarray cvx % Stack: pagedict currentpagedict installproc /Install exch def % Stack: pagedict currentpagedict % If the Overprint device flag is not /disable, check usage of OP/op /PageUsesOverprint //false def % assume we don't need OP simulation dup /Overprint get /disable ne % If the device suppports SpotColors (DeviceN device) we don't need simulation 1 index /PageSpotColors known not and /HighLevelDevice /GetDeviceParam .special_op { exch pop }{ //false }ifelse not and % Only if not HighLevelDevice { % Overprint is /enable, so the device might need the overprint compositor % if it does not support spot colors, thus check if overprint is used so % overprint simulation can be done with the pdf14 compositor 1 index countspotcolors userdict exch /PageSpotColors exch put % save it in a known place 1 index pageusesoverprint 1 index /ProcessColorModel get /DeviceCMYK eq { PageSpotColors 0 gt % count of colorants NOT including CMYK and } if /PageUsesOverprint exch def % the page needs OP simulation so set device param. } if pop currentdict end setpagedevice } bind executeonly def /.free_page_resources { % - .free_page_resources - Page /Resources pget { /Shading knownoget { { dup type /dicttype eq { dup /.shading_dict known { dup /.shading_dict undef } if } if pop pop } forall } if } if } bind executeonly def /pdfshowpage_finish { % <pagedict> pdfshowpage_finish - save /PDFSave exch store /PDFdictstackcount countdictstack store /PDFexecstackcount count 2 sub store (before exec) VMDEBUG % set up color space substitution (this must be inside the page save) pdfshowpage_setcspacesub .writepdfmarks { % Pagelabel pagelabeldict begin dopagelabel end % Copy the boxes. % Copy the boxes. { /CropBox /BleedBox /TrimBox /ArtBox } { 2 copy pget { % .pdfshowpage_Install transforms the user space do same here with the boxes oforce_elems 2 { Page pdf_cached_PDF2PS_matrix transform 4 2 roll } repeat normrect_elems 4 index 5 1 roll fix_empty_rect_elems 4 array astore mark 3 1 roll {/PAGE pdfmark} stopped {cleartomark} if } { pop } ifelse } forall } if % end .writepdfmarks % Display the actual page contents. 9 dict begin /BXlevel 0 def /BMClevel 0 def /OFFlevels 0 dict def /BGDefault currentblackgeneration def /UCRDefault currentundercolorremoval def %****** DOESN'T HANDLE COLOR TRANSFER YET ****** /TRDefault currenttransfer def matrix currentmatrix 2 dict 2 index /CropBox pget { oforce_elems normrect_elems boxrect 4 array astore 1 index /ClipRect 3 -1 roll put } if dictbeginpage setmatrix /DefaultQstate qstate store count 1 sub /pdfemptycount exch store % If the page uses any transparency features, show it within % a transparency group. The scan was performed during pdfshowpage_setpage % and the result was set in the pagedevice dictionary. Use it rather than % scanning again IF it is present. If the pdfshowpage_setup was not called % (eg GSView 5) then it will not be present, so we must rescan. currentdict /PageUsesTransparency .knownget not {dup pageusestransparency} if dup /PDFusingtransparency exch def { % If the current device isn't CMYK, or if it is a device that supports transparency % we don't need the special handling of Overprint transparency, so disable the checking. 4 dict begin % working directory to simplify currentpagedevice dup /Colors get /devColors exch def % put into our convenience dict dup /HaveTransparency .knownget not { //false } if /devSupportsTrans exch def % put into our convenience dict dup /Overprint get /SimOP exch def % put into our convenience dict SimOP /simulate eq exch /PageUsesOverprint .knownget not { //false } if and % both Overprint==/simulate and PageUsesOverprint { % Determine if the device needs the special pdf14 compositor push devColors 4 eq PageSpotColors 0 gt and % CMYK device, but device has spot colors devColors 4 lt % RGB or Gray device or } { //false % Overprint is not /simulate or PageUseOverprint is false } ifelse % Determine if the device needs SMask for Overprint SimOP /simulate eq { //true % we will need setupOPrtans for Compatible BM } { SimOP /enable eq devColors 4 ge % CMYK device and } ifelse devSupportsTrans not and % If device supports transparency (e.g. pdfwrite) then no setupOPtrans end % pop the convenience dict /setup_trans exch { /setupOPtrans } { /setupSMtrans } ifelse load def % Show the page within a PDF 1.4 device filter. { -1 } { 0 } ifelse .pushpdf14devicefilter { /DefaultQstate qstate store % device has changed -- reset DefaultQstate % If the page has a Group, enclose contents in transparency group. % (Adobe Tech Note 5407, sec 9.2) dup /Group knownoget { 1 index /CropBox pget { /CropBox exch } { 1 index get_media_box pop /MediaBox exch } ifelse oforce_elems normrect_elems fix_empty_rect_elems 4 array astore .beginpagegroup showpagecontents .endtransparencygroup } { showpagecontents } ifelse } stopped { % abort the transparency device .abortpdf14devicefilter /DefaultQstate qstate store % device has changed -- reset DefaultQstate stop } if { } settransfer % identity transfer during popdevice (put_image) .poppdf14devicefilter % NB: reset to DefaultQstate will also restore transfer function /DefaultQstate qstate store % device has changed -- reset DefaultQstate } { /setup_trans { pop pop } def % no-op this if the page doesn't use transparency % NB: original will be restored from PDFsave % The page doesn't use transparency, but if Overprint is /simulate, we may need to % push a pdf14devicefilter to handle the overprint simulation using the pdf14 device. currentpagedevice dup /Overprint get /simulate eq 1 index /PageSpotColors known not and exch /PageUsesOverprint .knownget not { //false } if and { % Show the page within a PDF 1.4 device filter for overprint_simulation. -1 .pushpdf14devicefilter { /DefaultQstate qstate store % device has changed -- reset DefaultQstate showpagecontents } stopped { % abort the transparency device .abortpdf14devicefilter /DefaultQstate qstate store % device has changed -- reset DefaultQstate stop } if { } settransfer % identity transfer during popdevice (put_image) .poppdf14devicefilter % NB: reset to DefaultQstate will also restore transfer function /DefaultQstate qstate store % device has changed -- reset DefaultQstate } { showpagecontents } ifelse } ifelse .free_page_resources % todo: mixing drawing ops outside the device filter could cause % problems, for example with the pnga device. endpage end % scratch dict % Some PDF files don't have matching q/Q (gsave/grestore) so we need % to clean up any left over dicts from the dictstack PDFdictstackcount //false { countdictstack 2 index le { exit } if currentdict /n known not or end } loop { StreamRunAborted not { (\n **** Error: File has unbalanced q/Q operators \(too many q's\)\n Output may be incorrect.\n) //pdfdict /.Qqwarning_issued .knownget { { pop } { currentglobal //pdfdict gcheck .setglobal //pdfdict /.Qqwarning_issued //true .forceput .setglobal pdfformaterror } executeonly ifelse } executeonly { currentglobal //pdfdict gcheck .setglobal //pdfdict /.Qqwarning_issued //true .forceput .setglobal pdfformaterror } executeonly ifelse } executeonly if } executeonly if pop count PDFexecstackcount sub { pop } repeat (after exec) VMDEBUG Repaired % pass Repaired state around the restore RepairedAnError PDFSave restore currentglobal //pdfdict gcheck .setglobal //pdfdict /.Qqwarning_issued //false .forceput .setglobal /RepairedAnError exch def /Repaired exch def } bind executeonly odef % Display the contents of a page (including annotations). /showpagecontents { % <pagedict> showpagecontents - dup % Save the pagedict for the Annotations % We do a 'save' here in order to allow us to restore at the end of the page, before % we run the annotations. There are two reasons for this; firstly so that the graphics state % at the time we run the annotations is the same as when we ran the page, secondly in order % to empty the font cache before we run the annotations. % % Bug #700096 an annotation uses Helvetica but doesn't embed it, however the page *does* % use an embedded Helvetica, which is subset and not prefixed as such. For this file to % render correctly we must not use the font from the page, but must find a replacement. % However the file for Bug #695897 has a page which uses two versions of the same font, % one embedded, one not. In order for *that* file to render correctly we *must* use the % embedded font as a substitute for the missing font. So we divorce the fonts used % for the page from the fonts used for Annotations, this allows both files to work as % expected. % % We also need a countdictstack, so that we can check the dictionaries on the dictioanry % stack after we run the page contents, and 'end' an extra ones before we try to restore % otherwise we might try to restore back to a point before one of those dictionaries existed. % save countdictstack 3 -1 roll count 1 sub /pdfemptycount exch store /Contents knownoget not { 0 array } if dup type /arraytype ne { 1 array astore } if { oforce dup type /dicttype eq { //false resolvestream pdfopdict .pdfrun } { (**** Error: The Page /Contents array contains an element which is not a stream\n This page will not display correctly\n\n) pdfformaterror pop exit }ifelse } forall % check for extra garbage on the ostack and clean it up count pdfemptycount sub dup 0 ne { ( **** Error: File did not complete the page properly and may be damaged.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror { pop } repeat } { pop } ifelse % Top of the stack should ow be the count of dictionaries on the stack at the time % we did a save. If there are more than there were then, end dictionaries until % we get back to the sme number. { countdictstack 1 index le {exit}if end } loop % discard the count of dictionaries pop % and restore the state. This will take us back to a point before any fonts % used on the page were defined, so the annotations won't inherit any of % them. restore % Draw the annotations //systemdict /ShowAnnots .knownget not { //true } if { /Annots knownoget { dup type /arraytype eq { { /AnnotDrawCheck exch % marker to clean up stack on error {oforce} stopped { ( **** Error: Unable to draw an annotation.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror count -1 0 { % make sure we don't go past the top of the stack pop % remove the counter /AnnotDrawCheck eq {exit} if % remove object and check if its the marker, exit if it is } for } { exch pop dup //null ne { .writepdfmarks %% %% We don't want to preserve annotations with ps2write, because we don't convert them %% back into pdfmarks on output. %% /ForOPDFRead /GetDeviceParam .special_op { exch pop }{ //false }ifelse not and //systemdict /PreserveAnnots .knownget not {//true} if and { mark exch {preserveannot} PDFSTOPONERROR {exec}{stopped {(Error: Ignoring invalid annotation, output may be incorrect.\n) pdfformaterror} if} ifelse {cleartomark} stopped pop }{ mark exch {drawannot} PDFSTOPONERROR {exec}{stopped {(Error: Ignoring invalid annotation, output may be incorrect.\n) pdfformaterror} if} ifelse {cleartomark} stopped pop } ifelse } { pop } ifelse } ifelse } forall } { ( **** Error: Annotation array is not an array, ignoring it.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror pop } ifelse } if } if % default AcroForm to true to match Acrobat. //systemdict /ShowAcroForm .knownget { //true eq } { //true } ifelse { Trailer /Root oget /AcroForm knownoget { draw_acro_form } if } if } bind executeonly def /processcolorspace { % - processcolorspace <colorspace> % The following is per the PLRM3. currentdevice 1 dict dup /ProcessColorModel dup put .getdeviceparams exch pop exch pop dup type /nametype ne { cvn } if dup { setcolorspace } //.internalstopped exec { pop /DeviceRGB } if } bind executeonly def % returns true if OP or op is true in an ExtGState /pageusesoverprint { % <pagedict> pageusesoverprint <bool> dup //false exch { 4 dict 1 index resourceusesoverprint { pop not exit } if %% Check the current dictionary and its Parent (if any) to see %% if they both have stored object numbers. If they do then %% check the numbers, don't allow self-references. dup /Parent knownoget not { pop exit } { exch /.gs.pdfobj# .knownget { 1 index /.gs.pdfobj# .knownget { eq { pop exit }if }{ pop }ifelse }if } ifelse } loop % Also check for transparency in the annotation (if not in resources). { pop //true } { annotsuseoverprint } ifelse } bind def % Check if Overprint (OP/op) is specified in an ExtGState dict /extgstateusesoverprint { % <gstate dict> extgstateusesoverprint <bool> //false exch % Assume no overprint dup //null eq { pop % bug 692050 } { { % establish loop context dup /OP knownoget { { pop not exit } if } if dup /op knownoget { { pop not exit } if } if pop exit } loop } ifelse } bind def % Check if overprint is used in a Pattern /patternusesoverprint { % <Pattern dict> patternusesoverprint <bool> //false exch % Assume no overprint { 4 dict 1 index resourceusesoverprint { pop not exit } if dup /ExtGState knownoget { extgstateusesoverprint { pop not exit } if } if pop exit } loop } bind def % Check the Resources of a page or Form. Check for loops in the resource chain. /resourceusesoverprint { % <dict> <dict> resourceusesoverprint <bool> { % Use loop to provide an exitable context. /Resources knownoget not { 0 dict } if 2 copy .knownget { { % Some circular references may be missed because scanning stops % when the 1st overprint is found. ( **** File has circular references in resource dictionaries.\n) pdfformaterror } if pop //false exit } if 2 copy //true put % In the current chain. dup /ExtGState knownoget { //false exch { exch pop oforce extgstateusesoverprint { pop //true exit } if } forall { pop //true exit } if } if dup /Pattern knownoget { //false exch { exch pop oforce patternusesoverprint { pop //true exit } if } forall { pop //true exit } if } if 2 copy //false put % Visited but not in the current chain. pop //false exit } loop exch pop } bind def % Check if the annotations on a page use overprint /annotsuseoverprint { % <page dict> annotsuseoverprint <bool> //false exch % Assume no overprint /Annots knownoget { % Get Annots array dup type /arraytype eq { { oforce dup //null ne { /AP knownoget { % Get appearance dict for the annoation /N knownogetdict { % Get the /N (i.e. normal) appearance stream 4 dict exch resourceusesoverprint { not exit } if } if } if % If AP dict known } { pop } ifelse } forall % For all annots on the page } { ( **** Error: Annotation array is not an array, ignoring it.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror pop } ifelse } if } bind def % ------ Transparency support ------ % % Determine whether a page might invoke any transparency features: % - Non-default BM, ca, CA, or SMask in an ExtGState % - Image XObject with SMask % Note: we deliberately don't check to see whether a Group is defined, % because Adobe Illustrator 10 (and possibly other applications) define % a page-level group whether transparency is actually used or not. % Ignoring the presence of Group is justified because, in the absence % of any other transparency features, they have no effect. % % Transparency is a 1.4 feature however we have seen files that claimed % to be PDF 1.1 with transparency features. Bugs 689288, 691273. /pageusestransparency { % <pagedict> pageusestransparency <bool> NOTRANSPARENCY { pop //false } { dup //false exch { 4 dict 1 index resourceusestransparency { pop not exit } if %% Check the current dictionary and its Parent (if any) to see %% if they both have stored object numbers. If they do then %% check the numbers, don't allow self-references. dup /Parent knownoget not { pop exit } { exch /.gs.pdfobj# .knownget { 1 index /.gs.pdfobj# .knownget { eq { pop exit }if }{ pop }ifelse }if } ifelse } loop % Also check for transparency in the annotation (if not in resources). { pop //true } { annotsusetransparency } ifelse } ifelse } bind executeonly def % Check if transparency is specified in an ExtGState dict /extgstateusestransparency { % <gstate dict> extgstateusestransparency <bool> //false exch % Assume no transparency dup //null eq { pop % bug 692050 } { { % establish loop context dup /BM knownoget { dup /Normal ne exch /Compatible ne and { pop not exit } if } if dup /ca knownoget { 1 ne { pop not exit } if } if dup /CA knownoget { 1 ne { pop not exit } if } if dup /SMask knownoget { /None ne { pop not exit } if } if pop exit } loop } ifelse } bind executeonly def % Check if transparency is used in a Pattern /patternusestransparency { % <Pattern dict> patternusestransparency <bool> dup //null eq NOTRANSPARENCY or { pop //false } { //false exch % Assume no transparency { 4 dict 1 index resourceusestransparency { pop not exit } if dup /ExtGState knownoget { extgstateusestransparency { pop not exit } if } if pop exit } loop } ifelse } bind executeonly def % Check the Resources of a page or Form. Check for loops in the resource chain. /resourceusestransparency { % <dict> <dict> resourceusestransparency <bool> { % Use loop to provide an exitable context. /Resources knownoget not { 0 dict } if 2 copy .knownget { { % Some circular references may be missed because scanning stops % when the 1st transparency is found. ( **** Warning: Found circular references in resource dictionaries while checking for transparency.\n) pdfformatwarning } if pop //false exit } if 2 copy //true put % In the current chain. dup /ExtGState knownoget { //false exch { exch pop oforce extgstateusestransparency { pop //true exit } if } forall { pop //true exit } if } if dup /Pattern knownoget { //false exch { exch pop oforce patternusestransparency { pop //true exit } if } forall { pop //true exit } if } if dup /XObject knownoget { dup type /dicttype eq { //false exch { exch pop oforce dup //null ne { dup type /dicttype eq { dup /Subtype get dup /Image eq { 1 index /SMask oknown { pop pop not exit } if 1 index /SMaskInData knownoget { 0 ne { pop pop not exit } if } if } if /Form eq { dup /Group known {pop pop //true exit}{ 3 index exch resourceusestransparency { not exit } if } ifelse } { pop } ifelse } { pop ( **** Warning: Ignoring non-dictionary /XObject attribute while checking for transparency.\n) pdfformatwarning } ifelse } { pop } ifelse } forall { pop //true exit } if } { ( **** Warning: Ignoring non-dictionary /XObject while checking for transparency.\n) pdfformatwarning pop } ifelse } if dup /Font knownoget { //false exch { exch pop oforce dup type /dicttype eq { dup /Subtype knownoget { /Type3 eq { 3 index exch resourceusestransparency { pop //true exit } if } {pop} ifelse } { pop }ifelse } { % probably a name object pop }ifelse } forall { pop //true exit } if } if 2 copy //false put % Visited but not in the current chain. pop //false exit } loop exch pop } bind executeonly def % Check if the annotations on a page use transparency /annotsusetransparency { % <page dict> annotsusetransparency <bool> //false exch % Assume no transparency /Annots knownoget { % Get Annots array dup type /arraytype eq { { /AnnotTransparencyCheck exch % marker to clean up stack on error {oforce} stopped { ( **** Error: Unable to check an annotation for use of transparency.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror count -1 0 { % make sure we don't go past the top of the stack pop % remove the counter /AnnotTransparencyCheck eq {exit} if % remove object and check if its the marker, exit if it is } for } { exch pop % remove the 'on error' marker dup type /dicttype eq { dup //null ne { dup /Subtype knownoget { /Highlight eq { % Highlight annotation is always implemented pop pop //true exit % as transparency. } if } if dup /AP knownoget { % Get appearance dict for the annoation /N knownogetdict { % Get the /N (i.e. normal) appearance stream 4 dict exch resourceusestransparency { pop pop //true exit } if } if } if % If AP dict known dup /BM knownoget { pop pop pop //true exit } if dup /CA knownoget { 1 le { pop pop //true exit } if } if /ca knownoget { 1 le { pop //true exit } if } if } { pop } ifelse } { ( **** Error: Annotation entry is not a dictionary, ignoring it.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror pop } ifelse } ifelse } forall % For all annots on the page } { ( **** Error: Annotation array is not an array, ignoring it.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror pop } ifelse } if } bind executeonly def % Add a color name to our spot color list. Ignore /All and /None /putspotcolor { % <name> <spotcolordict> putspotcolor - % The 'name' could be a string. If so then convert to a name. exch dup type /stringtype eq { cvn } if dup dup /None eq exch /All eq or { pop pop } { 0 put } ifelse } bind executeonly def % Determine which spot colors are used within a color space Note: This % dict will include all colors used in Separation or DeviceN color spaces. % Thus it may include Cyan, Magenta, Yellow, and Black. % <colorspace> <spotcolordict> colorspacespotcolors - /colorspacespotcolors { % Make sure we have an array, and that it is has enough info exch dup type /arraytype eq { % If we have an Indexed color space then get the base space. dup 0 oget % <<>> [csp] /Type dup /Indexed eq { pop 1 oget % <<>> [base] 2 copy exch colorspacespotcolors } { dup /Pattern eq { 1 index length 1 gt { % only uncolored patterns have colorspace pop 1 oget % <<>> [base] 2 copy exch colorspacespotcolors } { pop } ifelse } { % Stack: <spotcolordict> <colorspace> <colorspacetype> dup /Separation eq exch /DeviceN eq or { dup 1 oget dup type /arraytype eq { { oforce 2 index putspotcolor } forall } { 2 index putspotcolor } ifelse } if } ifelse } ifelse } if pop pop } bind executeonly def % Check the Resources of a page, form, or annotation. Determine which spot % colors are used within the resource Note: The spot color dict will include % all colors used in Separation or DeviceN color spaces. Thus it may include % Cyan, Magenta, Yellow, and Black. We also pass a dict that is used to check % for loops in the resource list. % <spotcolordict> <loopdict> <page/form/annot dict> % resourcespotcolors <spotcolordict> <loopdict> /resourcespotcolors { { % Use loop to provide an exitable context. % Exit if no Resources entry /Resources knownoget not { exit } if % Exit if we have already seen this dict 2 copy known { pop exit } if % Save the Resources dict into our loop checking dict. 2 copy 0 put % Scan resources that might contain a color space. dup /ColorSpace knownoget { { exch pop oforce 3 index colorspacespotcolors } forall } if dup /Pattern knownoget { { exch pop oforce dup /Shading knownoget { exch pop /ColorSpace oget 3 index colorspacespotcolors } { 4 copy exch pop resourcespotcolors pop pop pop } ifelse } forall } if dup /Shading knownoget { { exch pop oforce /ColorSpace { oget } stopped { pop pop ( **** Error: invalid color space in shading, output may be incorrect.\n) pdfformaterror } { 3 index colorspacespotcolors} ifelse } forall } if /XObject knownoget { dup type /dicttype eq { { exch pop oforce dup type /dicttype eq { dup //null ne { dup /Subtype oget dup /Form eq { pop resourcespotcolors } { /Image eq { /ColorSpace knownoget { 2 index colorspacespotcolors } if } { pop } ifelse } ifelse } { pop } ifelse } { pop } ifelse } forall } { pop % Just ignore here, already reported by resourceusestransparency. } ifelse } if exit } loop } bind executeonly def % Determine which spot colors are used within the annotations. Note: This % dict will include all colors used in Separation or DeviceN color spaces. % Thus it may include Cyan, Magenta, Yellow, and Black. % <spotcolordict> <loopdict> <annotsarray> % annotsspotcolors <spotcolordict> <loopdict> /annotsspotcolors { dup type /arraytype eq { { oforce dup //null ne { /AP knownoget { % Get appearance dict for the annoation /N knownogetdict { % Get the /N (i.e. normal) appearance stream resourcespotcolors } if % If normal appearance streamknown } if % If AP dict known } { pop } ifelse } forall } { ( **** Error: Annotation array is not an array, ignoring it.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror pop } ifelse } bind executeonly def % Determine spot colors are used within a page. We are creating a dict to % hold the spot color names as keys. Using a dict avoids having to worry % about duplicate entries. The keys in the dict contain the spot color % names. However the values have no meaning. Note: This dict will include % all colors used in Separation or DeviceN color spaces specified in the % page's resources. Thus it may include Cyan, Magenta, Yellow, and Black. % There is no attempt to verify that these color spaces are actually used % within the object streams for the page. /pagespotcolors { % <pagedict> pagespotcolors <spotcolordict> dup % Create a dict to hold spot color names. 0 dict exch % Create a dict to be used to check for reference loops. 4 dict exch % Check for color spaces in the Resources resourcespotcolors % now check upwards in the object hierarchy in case of inherited resources 2 index { /Parent knownoget { dup /Pages known not { pop exit } if % not a valid Page Tree ancestor dup 4 1 roll resourcespotcolors 3 -1 roll } { exit } ifelse } loop % Also check for color spaces in the annotations. 3 -1 roll /Annots knownoget { annotsspotcolors } if pop % Discard reference loop dict } bind executeonly def % Determine how many (if any) spot colors are used by a page. % Note: This count does not include Cyan, Magenta, Yellow, or Black /countspotcolors { % <pagedict> countspotcolors <count> pagespotcolors % Get dict with all spot colors dup length % spot color dict length % Remove CMYK from the spot color count. [ /Cyan /Magenta /Yellow /Black ] { 2 index exch known { 1 sub } if } forall exch pop % Remove spot color dict } bind executeonly def % ------ ColorSpace substitution support ------ % %% %% <pagedict> pdf_colorspace_detect_cspacesub <boolean> %% /pdf_colorspace_detect_cspacesub { //false exch /Resources knownoget { /ColorSpace knownoget { dup /DefaultGray knownoget { resolvecolorspace csncomp 1 eq { pop pop //true } if } { dup /DefaultRGB knownoget { resolvecolorspace csncomp 3 eq { pop pop //true } if } { /DefaultCMYK knownoget { resolvecolorspace csncomp 4 eq { pop //true } if } if } ifelse } ifelse } if } if } bind executeonly def %% <loopdict> <Objectdict> <calling obj_num> pdfform_detect_cspacesub <boolean> %% /pdf_object_detect_cspacesub { %% use loop operator for an exitable context %% we need this to detect recursion/looping { exch %% <loopdict> <calling obj_num> <Objectdict> dup pdf_colorspace_detect_cspacesub { pop pop //true exit }{ %% <loopdict> <calling obj_num> <Objectdict> /Resources knownoget { %% <loopdict> <calling obj_num> <Resourcesdict> 2 index 1 index known { %% We've already seen this object, ignore it and exit pop pop //false exit }{ 2 index 1 index //null put } ifelse /XObject knownoget { %% <loopdict> <calling obj_num> <XObjectdict> //false exch %% <loopdict> <calling obj_num> <XObjectdict> false %% We have files where the XObject Resource is not a dictionary dup type /dicttype eq { %% <loopdict> <calling obj_num> <XObjectdict> false %% check each Xobject entry in the dictionary, %% forall purs a key/value pair on the stack for us. %% { %% <loopdict> <calling obj_num> <XObjectdict> false key value exch pop %% <loopdict> <calling obj_num> <XObjectdict> false value %% If this is an indirect reference, check if its the smae object %% as the current one. If its not indirect, make the object number 0 %% for comparison purposes. dup type /packedarraytype eq { dup 0 get dup 4 index eq } { 0 //false }ifelse %% <calling obj_num> <XObjectdict> false value <form object or 0 if not indirect> <boolean> not { %% swap object number and value, and dereference value exch oforce %% Apparently we have files where the content of the XObject Resource dictionary is null dup //null ne { %% and files where the indivudal XObjects are not dictionaries dup type /dicttype eq { dup /Subtype get /Form eq { exch 4 index 3 1 roll pdf_object_detect_cspacesub { pop //true exit } if } { pop pop }ifelse }{ pop pop } ifelse }{ pop pop } ifelse }{ pop pop } ifelse } forall }{ pop }ifelse } { %% No forms, so can't be any Default* spaces //false }ifelse } { //false } ifelse } ifelse %% Remove the calling object ID, return our boolean exch pop exit } loop %% remove and discard the loopdict exch pop } bind executeonly def % % <pagedict> pdfshowpage_detect_cspacesub <pagedict> <boolean> % % this is used simply to detect whether the current page has any % Default* color spaces defined. If it does then we want pdfshowpage_setpage % to set UseCIEColor to true so that the Default* space is used. If the % page doesn't use any Default* spaces, then we *don't* want to set % UseCIEColor as that will confuse a warning in pdfwrite about % not using UseCIEColor with pdfwrite. % /pdfshowpage_detect_cspacesub { dup 0 1 dict 3 1 roll pdf_object_detect_cspacesub /HighLevelDevice /GetDeviceParam .special_op { exch pop not exch pop }if } bind executeonly def % % <pagedict> pdfshowpage_setcspacesub <pagedict> % % Set up color space substitution for a page. Invocations of this procedure % must be bracketed by the save/restore operation for the page, to avoid % unintended effects on other pages. % % If any color space substitution is used, and the current color space is a % device dependent color space, make sure the current color space is updated. % There is an optimization in the setcolorspace operator that does % nothing if both the current and operand color spaces are the same. For % PostScript this optimization is disabled if the UseCIEColor page device % parameter is true. This is not the case for PDF, as performance suffers % significantly on some PDF files if color spaces are set repeatedly. Hence, % if color space substitution is to be used, and the current color space % is a device dependent color space, we must make sure to "transition" the % current color space. % /pdfshowpage_setcspacesub { //false /DefaultGray 2 index /ColorSpace //rget exec { resolvecolorspace dup csncomp 1 eq { dup type /nametype eq { 1 array astore } if /DefaultGray exch /ColorSpace defineresource pop pop //true } { pop ( **** Error: ignoring invalid /DefaultGray color space.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror } ifelse } if /DefaultRGB 2 index /ColorSpace //rget exec { resolvecolorspace dup csncomp 3 eq { dup type /nametype eq { 1 array astore } if /DefaultRGB exch /ColorSpace defineresource pop pop //true } { pop ( **** Error: ignoring invalid /DefaultRGB color space.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror } ifelse } if /DefaultCMYK 2 index /ColorSpace //rget exec { resolvecolorspace dup csncomp 4 eq { dup type /nametype eq { 1 array astore } if /DefaultCMYK exch /ColorSpace defineresource pop pop //true } { pop ( **** Error: ignoring invalid /DefaultCMYK color space.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror } ifelse } if { % if using color space substitution, "transition" the current color space currentcolorspace dup length 1 eq { % always an array 0 get dup /DeviceGray eq 1 index /DeviceRGB eq or 1 index /DeviceCMYK eq or { /Pattern setcolorspace setcolorspace } { pop } ifelse } { pop } ifelse } if } bind executeonly def % Write OutputIntents to device if the device handles it /writeoutputintents { currentdevice 1 dict dup /OutputIntent //null put readonly .getdeviceparams mark ne { pop pop % device supports OutputIntent parameter % Make sure we don't have a badly broken PDF file! Trailer /Root knownoget { /OutputIntents knownoget { dup type /arraytype eq { { % process all output profiles present oforce dup length dict .copydict dup /DestOutputProfile knownoget { PDFfile fileposition exch mark exch { oforce } forall .dicttomark //true resolvestream [ { counttomark 1 add index 64000 string readstring not { exit } if } loop ] exch closefile 0 1 index { length add } forall .bytestring 0 3 2 roll { 3 copy putinterval length add } forall pop exch PDFfile exch setfileposition 1 index /DestOutputProfile 3 2 roll put } if % Convert to string array because it's easier for the device [ 1 index /OutputCondition knownoget not { () } if 2 index /OutputConditionIdentifier knownoget not { () } if 3 index /RegistryName knownoget not { () } if 4 index /Info knownoget not { () } if 5 index /DestOutputProfile knownoget not { () } if ] [ /OutputIntent 3 2 roll /.pdfputparams where { pop .pdfputparams } { currentdevice //null //false counttomark 1 add 3 roll .putdeviceparamsonly } ifelse pop pop pop % done with this OutputIntent dictionary } forall } { pop ( **** Error: /OutputIntent is of an incorrect type, ignoring OutputIntent.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror } ifelse } if % OutputIntents known % tell device there are no more OutputIntents [ /OutputIntent [ ] /.pdfputparams where { pop .pdfputparams } { currentdevice //null //false counttomark 1 add 3 roll .putdeviceparamsonly } ifelse pop pop } if } if } bind executeonly def % These functions can be used in error handling. It is not always possible to % use the PostScript sequence 'mark ..... cleartomark' to clean up behind a % sequence of operations, because processing the PDF might leave a mark % object on the stack. There are a number of ways to address that problem; one % is to count the objects on the stack at the time and store that value in a % convenient dictionary, presented here is an alternative. Instead of using a % mark object, we can use a specific name object as if it were a mark object % and use the two routines below to count the number of objects on the stack % up to a specific key, and to clear the stack back to a named key. % % /key CountToKey false | int true % % Counts the operand stack backwards until it encounters % a specific name key on the stack. Returns true and the count % of objects on the stack after that key, or false if the key % was not found on the stack. Consumes the key passed % to CountToKey. Throws a typecheck if the operand is not % a name type. % /CountToKey { dup type /nametype eq { //false 0 1 count 5 sub { dup 3 add index 3 index eq { 3 1 roll pop pop //true exit } {pop} ifelse } for { //true } { pop //false } ifelse } { /CountToKey cvx /typecheck signalerror }ifelse }bind readonly def % % /key ClearToKey - % % Clears the operand stack backwards until it encounters % the name object passed as an operand. If the name object % is not present on the stack then it will clear the entire % stack. Like cleartomark this removes the 'key' from the stack. % /ClearToKey { 0 1 count 4 sub { pop dup 3 1 roll eq {exit} if } for pop }bind readonly def end % pdfdict systemdict /ALLOWPSTRANSPARENCY get { /.setopacityalpha { /.setfillconstantalpha where { pop ( **** WARNING: .setopacityalpha is deprecated (as of 9.53.0) and will be removed in a future release\n) print ( **** See .setfillconstantalpha/.setalphaisshape for the improved solution\n) print flush false .setalphaisshape dup .setfillconstantalpha .setstrokeconstantalpha } { /.setopacityalpha /undefined cvx signalerror } ifelse } bind def /.setshapealpha { /.setfillconstantalpha where { pop ( **** WARNING: .setshapealpha is deprecated (as of 9.53.0) and will be removed in a future release.\n) print ( **** See .setfillconstantalpha/.setalphaisshape for the improved solution\n) print flush true .setalphaisshape dup .setfillconstantalpha .setstrokeconstantalpha } { /.setshapealpha /undefined cvx signalerror } ifelse } bind def } if .setglobal %% This list of operators are used internally by various parts of the Ghostscript PDF interpreter. %% Since each operator is a potential security vulnerability, and any operator listed here %% is not required once the initislisation is complete and functions are bound, we undefine %% the ones that aren't needed at runtime. [ /.pdfawidthshow /.pdfwidthshow /.currentblackptcomp /.setblackptcomp /.setfillcolor /.setfillcolorspace /.setstrokecolor /.setstrokecolorspace /.currentrenderingintent /.setrenderingintent /.currenttextrenderingmode /.settextspacing /.currenttextspacing /.settextleading /.currenttextleading /.settextrise /.currenttextrise /.setwordspacing /.currentwordspacing /.settexthscaling /.currenttexthscaling /.settextlinematrix /.currenttextlinematrix /.currenttextmatrix /.settextmatrix /.pushextendedgstate /.popextendedgstate /.pdfinkpath /.pdfFormName /.settextspacing /.currenttextspacing /.settextleading /.currenttextleading /.settextrise /.currenttextrise /.setwordspacing /.currentwordspacing /.settexthscaling /.currenttexthscaling /.setPDFfontsize /.currentPDFfontsize /.setdistillerparams /.currentpoint_valid % undefining these causes errors/incorrect output %/.settextrenderingmode ] systemdict .undefinternalnames % The following are split out allowing control via ALLOWPSTRANSPARENCY command line param % The examples/transparency_example.ps uses some of these (on the first line). [ /.pushpdf14devicefilter /.poppdf14devicefilter /.setstrokeconstantalpha /.setfillconstantalpha /.endtransparencygroup /.currentblendmode /.currenttextknockout /.begintransparencytextgroup /.endtransparencytextgroup /.begintransparencymaskgroup /.begintransparencymaskimage /.begintransparencypagegroup /.endtransparencymask /.image3x /.abortpdf14devicefilter /.setstrokeconstantalpha /.setfillconstantalpha /.setalphaisshape /.currentalphaisshape % undefining these causes errors/incorrect output %/.setblendmode /.begintransparencygroup /.settextknockout /.setstrokeoverprint /.setfilloverprint %/.currentstrokeoverprint /.currentfilloverprint /.currentfillconstantalpha /.currentstrokeconstantalpha %/.setSMask /.currentSMask ] systemdict dup /ALLOWPSTRANSPARENCY get {pop pop}{.undefinternalnames}ifelse gs_epsf.ps 0000644 00000027623 15030647507 0006557 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % Allow the interpreter to encapsulate EPS files, to recognize MS-DOS % EPSF file headers, and skip to the PostScript section of the file. % Encapsulate EPS files and optionally resize page or rescale image. % To display an EPS file cropped to the bounding box: % gs -dEPSCrop file.eps % To display an EPS file scaled to fit the page: % gs -dEPSFitPage file.eps % To display a file without EPS encapsulation: % gs -dNOEPS file.ps % When starting to process an EPS file, state is 0. % After %%BoundingBox processed, state is 1 if OK or 2 if cropped. % After %%HiResBoundingBox processed, state is 3 if OK or 4 if cropped. % After %%EndComments processed, state is 5. /EPSBoundingBoxState 5 def /EPSBoundingBoxString () def % set if either BoundingBox is seen (even if invalid) /EPSBoundingBoxSetState { //systemdict /EPSBoundingBoxState 3 -1 roll .forceput } .bind executeonly odef % .forceput must be bound and hidden % Parse 4 numbers for a bounding box /EPSBoundingBoxParse { % (llx lly urx ury) -- llx lly urx ury true OR false mark exch token {exch token {exch token {exch token {exch pop} if} if} if} if counttomark 4 eq { 5 -1 roll pop % remove mark //true } { cleartomark //false } ifelse } bind executeonly odef % Crop the page to the BoundingBox /EPSBoundingBoxCrop { % llx lly urx ury -- EPSDEBUG { (gs_epsf.ps: Setting pagesize from EPS bounding box\n) print flush } if exch 3 index sub exch 2 index sub % stack: llx lly urx-llx ury-lly << /PageSize [ 5 -2 roll ] >> setpagedevice neg exch neg exch translate } bind executeonly odef % Rescale, translate and rotate to fit the BoundingBox on the page /EPSBoundingBoxFitPage { % llx lly urx ury -- EPSDEBUG { (gs_epsf.ps: Rescaling EPS to fit page\n) print flush } if clippath pathbbox newpath % ellx elly eurx eury pllx plly purx pury EPSDEBUG { (Page Coordinates: LLX: ) print 3 index =print (, LLY: ) print 2 index =print (, URX: ) print 1 index =print (, URY: ) print dup = flush } if % Convert box corners to coordinates of the center and box sizes 2 { % loop doing the page coordinates, the the EPS bbox coordinates 3 -1 roll exch % ... llx urx lly ury 2 { % loop doing Y then X coordnates 2 copy exch sub % ... llx urx lly ury ury-lly 3 1 roll % ... llx urx ury-lly lly ury add 2 div % ... llx urx ury-lly (lly+ury)/2 4 2 roll % ... ury-lly (lly+ury)/2 llx urx } repeat 8 4 roll } repeat % edx, edy = EPS dimension X and Y, ecx, ecy = EPS Center X and Y. % pdx and pcx, etc, are for the Page values. % edx ecx edy ecy pdx pcx pdy pcy % Move the origin to the center of the printable area. 3 -1 roll exch % edx ecx edy ecy pdx pdy pcx pcy translate % edx ecx edy ecy pdx pdy % Find orientation of the best fit. Square pages or files don't rotate. 2 copy sub % edx ecx edy ecy pdx pdy pdx-pdy EPSDEBUG { (pdx: ) print 2 index =print (, pdy: ) print 1 index =print (, pdx-pdy: ) print dup = flush } if 6 index 5 index sub EPSDEBUG { (edx: ) print 7 index =print (, edy: ) print 5 index =print (, edx-edy: ) print dup = flush } if mul % edx ecx edy ecy pdx pdy (pdx-pdy)*(edx-edy) EPSDEBUG { (product: ) print dup = flush } if 0 lt { 90 rotate exch } if % Scale to fit in the most restricting direction. 4 -1 roll div % edx ecx ecy pdx pdy/edy exch 5 -1 roll div % ecx ecy pdy/edy pdx/edx //.min exec dup scale % ecx ecy % Center the document neg exch neg exch translate } bind executeonly odef /EPSBoundingBoxProcess { % (llx lly urx ury) state -- % The following 'lt' check prioritzies HiResBoundingBox over BoundingBox % even if HiResBoundingBox occurs first in the EPS file. //systemdict /EPSBoundingBoxState get 1 index lt { % save the BBoxString for possible FitPage when EndComments is seen exch dup //systemdict /EPSBoundingBoxString 3 -1 roll .forceput EPSBoundingBoxParse { //systemdict /EPSCrop known { EPSBoundingBoxCrop } { //systemdict /EPSFitPage known not { % Warn if some of the EPS file will be clipped clippath pathbbox newpath { % context for exit 5 -1 roll lt { 6 { pop } repeat //true exit } if 4 -1 roll lt { 4 { pop } repeat //true exit } if 3 -1 roll gt { 2 { pop } repeat //true exit } if exch gt { //true exit } if //false exit } loop QUIET not and /EPSBoundingBoxState .systemvar 1 and 1 eq and { (\n **** Warning: Some of the BoundingBox for the EPS file will be clipped.) = ( Use -dEPSCrop or -dEPSFitPage to avoid clipping.\n) = flush 1 add } if } { pop pop pop pop } ifelse } ifelse EPSBoundingBoxSetState } { % improperly formed BoundingBox string. QUIET not { (\n **** Warning: BoundingBox values are invalid and will be ignored: ') print EPSBoundBoxString print (') = flush } if pop % state } ifelse } { pop pop } ifelse } bind executeonly odef % Perform anchorsearch on the strings in the array until a match is found. /anchorsearchforany { % haystack [needle1 ...] --> post needle true % --> haystack false false 3 1 roll % false haystack [...] { % false haystack needle dup 3 1 roll % false needle haystack needle anchorsearch { % false needle post needle pop % false needle post 3 1 roll % post false needle exch not exch % post true needle exit } { % false needle haystack exch pop % false haystack } ifelse } forall exch % haystack false | post needle true } bind def /ProcessEPSComment { % file comment -- file comment /EPSBoundingBoxState .systemvar 3 lt { dup (%%BoundingBox:) anchorsearch { pop EPSDEBUG { (gs_epsf.ps: found %%BoundingBox\n) print flush } if 1 EPSBoundingBoxProcess } { (%%HiResBoundingBox:) anchorsearch { pop EPSDEBUG { (gs_epsf.ps: found %%HiResBoundingBox\n) print flush } if 3 EPSBoundingBoxProcess } { pop % Not interested in this DSC comment } ifelse } ifelse } if /EPSBoundingBoxState .systemvar 5 lt { dup (%%DocumentCustomColors:) anchorsearch { pop [ exch { { token not { exit } if dup type /stringtype ne { stop } if dup (atend) eq { stop } if exch } loop { counttomark 2 add index dup (123) .peekstring not { stop } if (%%+) eq { dup (123) readstring pop pop 256 string readline pop cvx exec } { pop exit } ifelse } loop } stopped { cleartomark } { counttomark 0 gt { currentpagedevice /MaxSeparations get 4 gt { ] << /SeparationColorNames 3 -1 roll >> setpagedevice } { cleartomark } ifelse } { cleartomark } ifelse } ifelse } { {(%%EndComments) (%%BeginProlog) (%%BeginSetup)} anchorsearchforany { EPSDEBUG { (EPSComment processing finished, encountered: ) print dup = } if pop pop % discard the strings from the anchorsearch % We may have seen BoundingBox or HiResBounfingBox. If so and if EPSFitPage % is set, then we do the transformation here to scale and center the page, % rotating if needed (and AllowFitPageRotation is true -- the default.) //systemdict /EPSFitPage known //systemdict /EPSBoundingBoxState get 0 gt and { EPSBoundingBoxString EPSBoundingBoxParse { EPSBoundingBoxFitPage } if } if % Ignore any following comments 5 EPSBoundingBoxSetState } { pop % Not %%EndComments -- ignore it } ifelse } ifelse } if } bind executeonly def % Install EPS handler for DSC comments, which we do later /EPSBoundingBoxInit { systemdict /NOEPS known not { % Merge ProcessEPSComment with existing handler //ProcessEPSComment /exec load currentuserparams /ProcessDSCComment get dup //null eq {pop {pop pop}} if /exec load 4 array astore cvx readonly << /ProcessDSCComment 3 -1 roll >> setuserparams } if } bind executeonly odef /.runNoEPS /run load def /.runEPS { % file OR string -- .updatematrices /runEPS_save save def /runEPS_dict_count countdictstack def /runEPS_op_count count 2 sub def /runEPS_page_count .currentshowpagecount not {0} if def 0 EPSBoundingBoxSetState //.runNoEPS .currentshowpagecount not {0} if runEPS_page_count sub 0 eq { /showpage load exec } if count runEPS_op_count sub {pop} repeat countdictstack runEPS_dict_count sub {end} repeat runEPS_save restore } bind executeonly odef /run { % file OR string -- dup type /filetype ne { (r) file } if dup (%!PS-Adobe-) .peekstring { (%!PS-Adobe-) eq { dup (%!PS-Adobe-X.X EPSF-X.X) .peekstring { (EPSF) search { pop pop pop EPSDEBUG {(runEPS: Found EPS\n) print flush} if systemdict /NOEPS known { cvx //.runNoEPS } { cvx .runEPS } ifelse } { EPSDEBUG {(runEPS: Normal DSC\n) print flush} if pop cvx //.runNoEPS } ifelse } { EPSDEBUG {(runEPS: Short DSC\n) print flush} if pop cvx //.runNoEPS } ifelse } { EPSDEBUG {(runEPS: Not DSC\n) print flush} if cvx //.runNoEPS } ifelse } { EPSDEBUG {(runEPS: Short non-DSC\n) print flush} if pop cvx //.runNoEPS } ifelse } bind odef % Handle DOS EPS files. /.runnoepsf /run load def /.epsfheader <C5D0D3C6> def /run { dup type /filetype ne { (r) file } if % Check for MS-DOS EPSF file (see Red Book p. 729). dup ( ) .peekstring { .epsfheader eq { dup ( ) readstring exch pop } { //false } ifelse } { pop //false } ifelse % Stack: file true/false { % This block is executed if the file is MS-DOS EPSF. % Build up the little-endian byte offset and length. 2 { 1 0 4 { 2 index read not { pop exit } if % if EOF, let error happen 2 index mul add exch 256 mul exch } repeat exch pop exch } repeat % Stack: offset length file % Use flushfile to skip quickly to the start of the % PostScript section. dup 4 -1 roll 12 sub () /SubFileDecode filter flushfile % Now interpret the PostScript. exch () /SubFileDecode filter cvx run } { //.runnoepsf } ifelse } odef % rebind .runstdin to use redefined run userdict begin /.runstdin { { (%stdin) run } execute0 } bind def end % undefine things defined in this file and not referenced elsewhere [ /.runNoEPS /.runnoepsf /.runEPS /EPSBoundingBoxSetState /EPSBoundingBoxString /EPSBoundingBoxCrop /EPSBoundingBoxFitPage /EPSBoundingBoxParse /EPSBoundingBoxProcess /ProcessEPSComment ] currentdict .undefinternalnames gs_dbt_e.ps 0000644 00000004126 15030647507 0006670 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % Define the Dingbats encoding vector. /currentglobal where { pop currentglobal { setglobal } //true setglobal } { { } } ifelse /DingbatsEncoding % \000 StandardEncoding 0 32 getinterval aload pop % /.notdef % \040 /space /a1 /a2 /a202 /a3 /a4 /a5 /a119 /a118 /a117 /a11 /a12 /a13 /a14 /a15 /a16 /a105 /a17 /a18 /a19 /a20 /a21 /a22 /a23 /a24 /a25 /a26 /a27 /a28 /a6 /a7 /a8 % \100 /a9 /a10 /a29 /a30 /a31 /a32 /a33 /a34 /a35 /a36 /a37 /a38 /a39 /a40 /a41 /a42 /a43 /a44 /a45 /a46 /a47 /a48 /a49 /a50 /a51 /a52 /a53 /a54 /a55 /a56 /a57 /a58 % \140 /a59 /a60 /a61 /a62 /a63 /a64 /a65 /a66 /a67 /a68 /a69 /a70 /a71 /a72 /a73 /a74 /a203 /a75 /a204 /a76 /a77 /a78 /a79 /a81 /a82 /a83 /a84 /a97 /a98 /a99 /a100 /.notdef % \200 StandardEncoding 0 32 getinterval aload pop % /.notdef % \240 /.notdef /a101 /a102 /a103 /a104 /a106 /a107 /a108 /a112 /a111 /a110 /a109 /a120 /a121 /a122 /a123 /a124 /a125 /a126 /a127 /a128 /a129 /a130 /a131 /a132 /a133 /a134 /a135 /a136 /a137 /a138 /a139 % \300 /a140 /a141 /a142 /a143 /a144 /a145 /a146 /a147 /a148 /a149 /a150 /a151 /a152 /a153 /a154 /a155 /a156 /a157 /a158 /a159 /a160 /a161 /a163 /a164 /a196 /a165 /a192 /a166 /a167 /a168 /a169 /a170 % \340 /a171 /a172 /a173 /a162 /a174 /a175 /a176 /a177 /a178 /a179 /a193 /a180 /a199 /a181 /a200 /a182 /.notdef /a201 /a183 /a184 /a197 /a185 /a194 /a198 /a186 /a195 /a187 /a188 /a189 /a190 /a191 /.notdef 256 packedarray .defineencoding 3 DingbatsEncoding .registerencoding exec gs_ttf.ps 0000644 00000202075 15030647507 0006413 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % Support code for direct use of TrueType fonts. % (Not needed for Type 42 fonts.) % Note that if you want to use this file without including the ttfont.dev % option when you built Ghostscript, you will need to load the following % files before this one: % lib/gs_mgl_e.ps % lib/gs_mro_e.ps % lib/gs_wan_e.ps % Thanks to B. Jackowski and GUST (the Polish TeX Users' Group) for % the glyf-splitting code. % ---------------- Font loading machinery ---------------- % % Augment the FONTPATH machinery so it recognizes TrueType fonts. /.scanfontheaders where { /.scanfontheaders [ /.scanfontheaders .systemvar aload pop (\000\001\000\000*) (true*) (wOFF*) ] put } if % ---------------- Automatic Type 42 generation ---------------- % % Load a TrueType font from a file as a Type 42 PostScript font. % The thing that makes this really messy is the handling of encodings. % There are 2 interacting tables that affect the encoding: % 'cmap' provides multiple maps from character codes to glyph indices % 'post' maps glyph indices to glyph names (if present) % What we need to get out of this is: % Encoding mapping character codes to glyph names % (the composition of cmap and post) % CharStrings mapping glyph names to glyph indices % (the inverse of post) % If the post table is missing, we have to take a guess based on the cmap % table. /.loadttfontdict 50 dict dup begin /orgXUID AladdinEnterprisesXUID def /maxstring 32764 def % half the maximum length of a PostScript string, % must be a multiple of 4 (for hmtx / loca / vmtx) /.invert_encoding % <array> invert_encoding <dict> { dup 256 dict exch 0 exch 1 exch length 1 sub { % [] <> i dup 3 index exch get % [] <> i v dup /.notdef ne { exch 2 index 2 index .knownget { dup type /arraytype eq { [ exch aload pop counttomark 2 add -1 roll ] } { exch 2 array astore } ifelse } if 2 index 3 1 roll put } { pop pop } ifelse } for exch pop } .bind def % Make /MacRomanEncodingForTrueType including additional % characters in Mac OS Roman encoding, which is missing % in /MacRomanEncoding. See PDF spec 1.7, p. 431 or % "Inside Macintosh: Text" 1-55, Figure 1-36. % This is useful to exploit the glyphs via Apple Roman % TrueType cmap subtable, but not appropriate for information % interchange. /MacRomanEncodingForTrueType /MacRomanEncoding .findencoding dup length array copy << /notequal 173 /infinity 176 /lessequal 178 /greaterequal 179 /partialdiff 182 /summation 183 /product 184 /pi 185 /integral 186 /Omega 189 /radical 195 /approxequal 197 /Delta 198 /lozenge 215 /Euro 219 /apple 240 >> { TTFDEBUG { (Extend MacRomanEncodingForTrueType for TrueType: ) =only } if % check /.notdef to avoid overwriting 2 index 1 index get dup /.notdef eq { TTFDEBUG { (insert /) =only 2 index =only ( @ ) =only 1 index //== exec } if pop exch 2 index 3 1 roll put } { TTFDEBUG { (cannot insert /) =only 2 index =only ( @ ) =only 1 index =only ( used for ) =only dup //== exec } if pop pop pop } ifelse } forall aload pop 256 packedarray 5 1 index .registerencoding .defineencoding % Define the Macintosh standard mapping from characters to glyph indices. /MacRomanEncoding dup .findencoding def /MacGlyphEncoding dup .findencoding def /MacRomanEncodingForTrueType dup .findencoding def % Invert the MacRomanEncoding. /.romanmacdict MacRomanEncodingForTrueType .invert_encoding def /.latin1isodict ISOLatin1Encoding .invert_encoding def % Define remapping for misnamed glyphs in TrueType 'post' tables. % There are probably a lot more than this! /postremap mark /Eoverdot /Edotaccent /eoverdot /edotaccent .dicttomark readonly def % Array used for fast pre-filling of cmap array /.array1024z [ 1024 { 0 } repeat ] def % ---- Utilities ---- % % Define a serial number for creating unique XUIDs for TrueType fonts. % We used to use the checkSumAdjustment value from the font, but this is % not reliable, since some fonts don't set it correctly. % Note that we must do this in a string to make it immune to save/restore. % handle 64 bit integer objects /xuidstring 16#ffffffff 0 gt { <8000000000000000> } { <80000000> } ifelse def /curxuid { % - curxuid <int> //.getCPSImode //false //.setCPSImode 0 xuidstring { exch 8 bitshift exch add } forall % for tbe benefit of pdfwrite/ps2write we want the resulting XUID contents % to fit into a 32 bit value 16#ffffffff 0 gt { 16#ffffffff idiv } if exch //.setCPSImode } .bind def /nextxuid { % - nextxuid - 3 -1 0 { xuidstring 1 index 2 copy get dup 255 ne { 1 add put pop exit } if pop 0 put pop } for } bind def % <string> <index> getu16 <integer> /getu16 { 2 copy get 8 bitshift 3 1 roll 1 add get add } .bind def % <string> <index> gets16 <integer> /gets16 { getu16 16#8000 xor 16#8000 sub } .bind def % <string> <index> getu32 <integer> /getu32 { 2 copy getu16 16 bitshift 3 1 roll 2 add getu16 add } .bind def % <string> <index> gets32 <integer> /gets32 { 2 copy gets16 16 bitshift 3 1 roll 2 add getu16 add } .bind def % <string|array> <index> getu16 <integer> /getu16a { 2 getinterval_from_stringarray 0 getu16 } .bind def % <string|array> <index> gets16 <integer> /gets16a { 2 getinterval_from_stringarray 0 gets16 } .bind def % <string|array> <index> getu32a <integer> /getu32a { 4 getinterval_from_stringarray 0 getu32 } .bind def % <string|array> <index> gets32a <integer> /gets32a { 4 getinterval_from_stringarray 0 gets32 } .bind def 16#ffffffff 0 gt { % 64-bit sign extension { /gets32 /gets32a} { mark 1 index load aload pop { 16#80000000 xor 16#80000000 sub } aload pop //.packtomark exec cvx def } .bind forall } if % <string> <index> <integer> putu16 - /putu16 { 3 copy -8 bitshift put exch 1 add exch 16#ff and put } .bind def % <string> <index> <integer> putu32 - /putu32 { 3 copy -16 bitshift putu16 exch 2 add exch 16#ffff and putu16 } .bind def % <nametable> <nameid> findname <string> true % <nametable> <nameid> findname false /findname { TTFDEBUG { (findname: ) print dup =only } if [ //false 4 2 roll { 0 1 3 index 2 getu16 1 sub { % Stack: false table id index 12 mul 6 add 2 index exch 12 % Check the table is actually long enough to contain the requested index 1 index add 2 index length gt { /pdfformaterror where { ( **** TrueType font has malformed name table.\n) exch /pdfformaterror get exec PDFSTOPONERROR { /.loadpdfttfont cvx /invalidfont signalerror } if } if pop pop exit } if 12 getinterval dup 6 getu16 2 index eq 1 index 8 getu16 0 ne and { % We found the name we want. exch pop % Stack: false table record dup 10 getu16 2 index 4 getu16 add 1 index 8 getu16 4 -1 roll 3 1 roll 3 copy add 1 index length le { pop getinterval exch % Stack: false string record % Check for 8- vs. 16-bit characters. is2byte { //true } { dup is2byte2 } ifelse { string2to1 } if //true //null 4 -1 roll exit } { pop pop pop pop //false exit } ifelse } if pop } for } stopped { cleartomark //false } { pop pop counttomark 1 add -1 roll pop } ifelse TTFDEBUG { dup { ( = ) print 1 index //== exec } { ( not found) = } ifelse } if } .bind def % <namerecord> is2byte <bool> /is2byte { dup 0 getu16 { { pop //true } % Apple Unicode { pop //false } % Macintosh Script manager { 1 getu16 1 eq } % ISO { 1 getu16 1 eq } % Microsoft { pop //false } % default - *MUST* be last } % check for a valid Platform ID, if we don't get one, assume single byte encoding dup length 1 sub 2 index lt {exch pop dup length 1 sub}{exch} ifelse get exec } .bind def % <string> is2byte2 <bool> /is2byte2 { dup length dup 2 mod 0 ne { pop pop //false } { % s l //true exch % s b l 1 sub 0 exch 2 exch { 2 index exch get 0 ne { pop //false exit } if } for exch pop } ifelse } .bind def % <string2> string2to1 <string> /string2to1 { dup length 2 idiv string dup 0 1 3 index length 1 sub { 3 index 1 index 2 mul 1 add get put dup } for pop exch pop } .bind def % Each procedure in this dictionary is called as follows: % <encodingtable> proc <glyph dictionary> /cmapformats mark 0 { % Apple standard 1-to-1 mapping. 6 256 getinterval_from_stringarray mark 0 3 -1 roll { 1 index 1 add } forall pop .dicttomark } .bind 2 { % Apple 16bit CJK (ShiftJIS etc) % /sHK_sz subHeaderKey_size % 1 * uint16 % /sH_sz subHeader_size % 4 * uint16 % /sH_len subHeader_length % /cmapf2_tblen total table length % /cmapf2_lang language code (not used) % /sHKs subHeaderKeys /sHK_sz 2 def /sH_sz 8 def dup 2 getu16a /cmapf2_tblen exch def dup 4 getu16a /cmapf2_lang exch def dup 6 256 sHK_sz mul getinterval_from_stringarray /sHKs exch def 0 % initialization value for /sH_len 0 1 255 { sHKs exch 2 mul getu16a 1 index % get current max 1 index % get current subHeaderKey lt {exch} if pop } for /sH_len exch def dup 6 256 sHK_sz mul add cmapf2_tblen 1 index sub getinterval_from_stringarray /sH_gIA exch def /cmapf2_glyph_array 0 dict def /.cmapf2_putGID { /cmapf2_ch cmapf2_ch_hi 8 bitshift cmapf2_ch_lo add def firstCode cmapf2_ch_lo le cmapf2_ch_lo firstCode entryCount add lt and { % true: j is inside sH_offset idRangeOffset add % offset to gI cmapf2_ch_lo firstCode sub 2 mul % rel. pos. in range add 6 add % offset in sH_gIA sH_gIA exch getu16a dup 0 gt { % idDelta add cmapf2_glyph_array exch cmapf2_ch exch put } { pop % cmapf2_glyph_array cmapf2_ch 0 put } ifelse } { % false: j is outside % cmapf2_glyph_array cmapf2_ch 0 put } ifelse } def 16#00 1 16#ff { % hi_byte scan /cmapf2_ch_hi exch def sHKs cmapf2_ch_hi sHK_sz mul getu16a /sH_offset exch def sH_gIA sH_offset sH_sz getinterval dup 0 getu16a /firstCode exch def dup 2 getu16a /entryCount exch def dup 4 gets16a /idDelta exch def dup 6 getu16a /idRangeOffset exch def pop sH_offset 0 eq { /cmapf2_ch_lo cmapf2_ch_hi def /cmapf2_ch_hi 0 def .cmapf2_putGID } { 16#00 1 16#ff { % lo_byte scan /cmapf2_ch_lo exch def .cmapf2_putGID } for } ifelse } for pop cmapf2_glyph_array } .bind 4 { % Microsoft/Adobe segmented mapping. /etab exch def /nseg2 etab 6 getu16a def 14 /endc etab 2 index nseg2 getinterval_from_stringarray def % The Apple TrueType documentation omits the 2-byte % 'reserved pad' that follows the endCount vector! 2 add nseg2 add /startc etab 2 index nseg2 getinterval_from_stringarray def nseg2 add /iddelta etab 2 index nseg2 getinterval_from_stringarray def nseg2 add /idroff etab 2 index nseg2 getinterval_from_stringarray def % The following hack allows us to properly handle % idiosyncratic fonts that start at 0xf000: pop /firstcode startc 0 getu16a 16#ff00 and dup 16#f000 ne { pop 0 } if def /putglyph { glyphs code known { glyphs /.cmap_warning_issued known not { (**** Warning: Invalid TTF cmap mapping (overlapping/repeated map)\n) print flush glyphs /.cmap_warning_issued //true put } if pop } {glyphs code 3 -1 roll put}ifelse /code code 1 add def } bind def /glyphs 0 dict def % neg2 is number of segments x 2. A format 4 cmap, with usable % mappings cannot (according to the spec) have only 1 segment, % since format 4 requires a closing segment with start and end % codes being 0xffff. Unfortunately, we have found badly subsetted % TTF fonts which have one segment with valid mappings, and no % closing segment. % In such a case, force the loop to work as though as we have two % segments - this works as we don't rely on the terminating segment % but use the loop counter to spot completion - effrectively, we % ignore the closing segment when it's present, anyway. % % This loop and/or putglyph do not account for out of spec fonts % that have repeated or overlapping ranges in the segments. As we % write the code/gid to a PS dictionary, later encounters with a % given code will overwrite the earlier one(s). As this is outside % of the spec, it's not clear how other consumers handle this % condition, so we'll await a suitable example before making changes. % Two choices are: drop later repeated/overlapping segments entirely, % or only use codes from later, overlapping segments not already set % by the earlier segment. (Inspired by Bug 700968). % Revision: bug 703589 has an (invalid) cmap table with overlapping % (actually repeating) ranges, and requires the *first* range definition % to be used in order to render correctly. So /putglyph now refuses to % overwrite existing keys in the "glyphs" dictionary 0 2 nseg2 dup 4 lt {pop 4}if 3 sub { /i2 exch def /scode startc i2 getu16a def /ecode endc i2 getu16a def % Bug 693538: see above scode 0 eq ecode 0 eq and not { scode ecode 1 add gt { /ecode scode 1 add def } if % Bug 691326. See above. /code scode def /delta iddelta i2 gets16a def TTFDEBUG { (scode=) print scode =only ( ecode=) print ecode =only ( delta=) print delta =only ( droff=) print idroff i2 getu16 = } if idroff i2 getu16a dup 0 eq { pop scode delta add 65535 and 1 ecode delta add 65535 and { putglyph } for } { % The +2 is for the 'reserved pad'. /gloff exch 14 nseg2 3 mul add 2 add i2 add add def 0 1 ecode scode sub { 2 mul gloff add etab exch getu16a dup 0 ne { delta add 65535 and } if putglyph } for } ifelse } if } for % If we've encoutered an invalid table, remove the key before returning glyphs /.cmap_warning_issued undef glyphs /glyphs //null def % for GC } .bind 6 { % Single interval lookup. dup 6 getu16a /firstcode exch def dup 8 getu16a /ng exch def ng dict dup % Stack: tab dict dict % Fill elements firstcode .. firstcode+nvalue-1 with glyph values 0 1 ng 1 sub { dup firstcode add exch 2 mul 10 add 4 index exch getu16a 3 copy put pop pop } for pop exch pop } .bind 12 { % Microsoft/Adobe segmented mapping. /etab exch def /glyphs 0 dict def 0 1 etab 12 getu32a % nGroups 1 sub { /ind exch def /gid etab 12 ind mul 8 add 16 add getu32a def % startGlyphID etab 12 ind mul 16 add getu32a % startCharCode 1 etab 12 ind mul 4 add 16 add getu32a % endCharCode { gid glyphs 3 1 roll put /gid gid 1 add def } for } for glyphs /glyphs //null def % for GC } .bind .dicttomark readonly def % cmapformats % <cmaptab> cmapdict <glyph dictionary> /cmapdict { dup 0 getu16a cmapformats exch .knownget { TTFDEBUG { (cmap: format ) print 1 index 0 getu16a = flush } if exec } { (Can't handle format ) print 0 getu16a = flush mark 0 1 255 { dup } for .dicttomark } ifelse TTFDEBUG { (cmap: length=) print dup length = dup === } if } .bind def /get_from_stringarray % <array|string> <offset> get_from_stringarray <int> { 1 index type /stringtype eq { get } { exch { % o () 2 copy length ge { length sub } { exch get exit } ifelse } forall } ifelse } .bind def /getinterval_from_stringarray % <array|string> <offset> <length> getinterval_from_stringarray <string> { % May allocate a string in VM. 2 index type /stringtype eq { getinterval } { dup 65535 le { string exch 0 % [] s o p 4 3 roll { % s o p Si dup length % s o p Si lSi dup 4 index lt { 3 index exch sub % s o p Si o' exch pop 3 1 roll exch pop % s o' p } { % s o p Si lSi dup 3 1 roll % s o p lSi Si lSi 4 index sub % s o p lSi Si lSi-o 5 index length 4 index sub % s o p lSi Si lSi-o ls-p 2 copy gt { exch } if pop % s o p lSi Si minl dup 3 1 roll % s o p lSi minl Si minl 5 index exch getinterval % s o p lSi minl from 5 index 4 index 3 index % s o p lSi minl from s p minl getinterval % s o p lSi minl from to copy pop % s o p lSi minl exch pop add exch pop 0 exch % s 0 p' dup 3 index length ge { exit } if } ifelse } forall pop pop % s } { [ 4 1 roll { dup 0 eq { pop pop pop exit } if 3 copy dup 65535 ge { pop 65535 } if getinterval_from_stringarray 4 1 roll 3 index length sub exch 3 index length add exch } loop ] } ifelse } ifelse } .bind def /string_array_size % <array|string> string_array_size <int> { dup type /stringtype eq { length } { 0 exch { length add } forall } ifelse } .bind def % Each procedure in this dictionary is called as follows: % posttable <<proc>> glyphencoding /postformats mark 16#00010000 { % 258 standard Macintosh glyphs. pop MacGlyphEncoding } 16#00020000 { % Detailed map, required by Microsoft fonts. dup dup type /arraytype eq { 0 get } if length 36 lt { TTFDEBUG { (post format 2.0 invalid.) = flush } if pop [ ] } { /postglyphs exch def /post_first postglyphs dup type /arraytype eq { 0 get } if def post_first 32 getu16 /numglyphs exch def % Build names array in the order they occur in the 'post' table /postpos numglyphs 2 mul 34 add def /total_length postglyphs //string_array_size exec def % the number of names in a post table is not declared up front % and there are fonts with more names than glyph indices <sigh> % so we have to pre-process and find the highest index used. % We start with a base value of numglyphs as it's most common, % and we can safely have a array that's too large. % Rather than parse out the indices twice, we store them in an % array on the stack, which we then reuse, overwriting entries % as we go later on. numglyphs array numglyphs postglyphs 0 1 numglyphs 1 sub { dup 2 mul 34 add 2 index exch 2 //getinterval_from_stringarray exec dup 0 get 8 bitshift exch 1 get add dup 5 index exch 4 -1 roll exch put 258 sub dup 3 index gt % if we find a reference to an index higher than the value % already on the stack, replace the value on the stack { 3 -1 roll pop 2 1 roll} {pop} ifelse } for pop 1 add array 0 1 2 index length 1 sub { postpos total_length ge { % Fill the rest with .notdef 1 2 index length 1 sub { 1 index exch /.notdef put } for exit } if % No name available, /postnames will be defined as an empty % array and the glyph won't get a name attached. postglyphs postpos //get_from_stringarray exec postglyphs postpos 1 add 2 index 2 copy add total_length gt { TTFDEBUG { (post table ends in the middle of the entry.) print flush } if pop pop pop pop % Fill the rest with .notdef 1 2 index length 1 sub { 1 index exch /.notdef put } for exit } if //getinterval_from_stringarray exec cvn exch postpos add 1 add /postpos exch def 2 index 3 1 roll put } for /postnames exch def % Some TrueType fonts converted by "Windows Type 1 Installer" have % problematic post table including MacGlyphEncoding entries which % should be omitted. Such extra entries in the beginning of glyphName % array make /Encoding broken. If we find populary predefined % ISOLatin1Encoding glyph name in the post table, empty encoding is % returned. Some TrueType fonts for Microsoft Windows redefines % MacGlyphEncoding glyph name out of predefined range). To permit % such fonts, ISOLatin1Encoding is used to find broken post. Bug 689495. /.broken_post //false def tabdict /name .knownget { (Windows Type 1 Installer V1.0) search { pop pop pop .latin1isodict postnames { dup /.notdef ne { 2 copy known { TTFDEBUG { (ignore post table that redefines ISOLatin1Encoding glyph name ) print dup //== exec flush } if /.broken_post //true def pop exit } if } if pop } forall pop } { pop } ifelse } if % Loop through the array of name indices we created above. % This loop replaces name index in the array with the name % it references. 0 1 2 index length 1 sub { dup 2 index exch get dup 258 lt { MacGlyphEncoding exch get } { 258 sub postnames exch get % At least some of Microsoft's TrueType fonts use incorrect % (Adobe-incompatible) names for some glyphs. % Correct for this here. postremap 1 index .knownget { exch pop } if } ifelse 2 index 3 1 roll put } for .broken_post { pop [ postnames aload length 1 roll ] } if } ifelse } .bind 16#00030000 { % No map. pop [ ] } .bind .dicttomark readonly def % postformats /call.readtable { .readtable } .bind def /call.readbigtable { .readbigtable } .bind def % Each procedure in this dictionary is called as follows: % <file> <length> -proc- <string|array_of_strings> % Note that each table must have an even length, because of a strange % Adobe requirement that each sfnts entry have even length. /readtables mark % Ordinary tables (head) //call.readtable (hhea) 1 index (maxp) 1 index (name) 1 index (OS/2) 1 index (post) //call.readbigtable (vhea) //call.readtable % Big tables (cmap) //call.readbigtable (GSUB) //call.readbigtable (glyf) //call.readbigtable (loca) 1 index (hmtx) 1 index (vmtx) 1 index (cvt ) //call.readtable (fpgm) 1 index (prep) 1 index .dicttomark % Normally there would be a 'readonly' here, but the ttf2pf utility wants % to include the 'kern' table as well, so we leave the readtables dictionary % writable. def % readtables /readtables_stripped readtables dup length dict copy dup (loca) { .skiptable } put dup (glyf) { .skiptable } put def % Read a table as a single string. % <file> <length> .skiptable <string> /.skiptable { pop pop () } .bind def % Read a table as a single string. % <file> <length> .readtable <string> /.readtable { dup dup 1 and add string % Stack: f len str dup 0 4 -1 roll getinterval % Stack: f str str1 % Because of the absurd PostScript specification that gives an % error for reading into an empty string, we have to check for % this explicitly here. 3 -1 roll exch dup () ne { readstring } if pop pop } .bind def % Read a big table (one that may exceed 64K). % <file> <length> .readbigtable <string[s]> /.readbigtable { dup 65400 lt { .readtable } { currentuserparams /VMReclaim get -2 vmreclaim [ 4 2 roll { % Stack: mark ... f left dup maxstring le { exit } if 1 index maxstring string readstring pop 3 1 roll maxstring sub } loop .readtable ] exch vmreclaim } ifelse } .bind def end readonly def % .loadttfontdict % <tab> .printtab - /.printtab { dup 0 4 getinterval print ( ) print dup 8 getu32 =only ( ) print 12 getu32 = } bind def % <file> <bool> <SubfontID> .loadttfonttables - % Pushes .loadttfontdict & scratch dict on d-stack. % Defines f, offsets, tables, tabdict, tabs, tthdrlen. % Skips loca and glyf if <bool> is true. /.loadttfonttables { //.loadttfontdict begin 40 dict begin /SubfontID exch def /load_stripped exch def /f exch def /offsets f 12 string readstring pop def /tthdrlen offsets length def load_stripped { readtables_stripped } { readtables } ifelse /readtables_ exch def offsets 0 4 getinterval (ttcf) eq { offsets 8 getu32 /num_fonts exch def SubfontID num_fonts ge { QUIET not { (True Type collection contains insufficient fonts.) = } if /.loadttfonttables cvx /invalidfont signalerror } if f SubfontID 4 mul dup 0 ne { () /SubFileDecode filter flushfile } { pop pop } ifelse f 4 string readstring pop 0 getu32 /ttc_offset exch def f ttc_offset SubfontID 4 mul sub 16 sub dup 0 ne { () /SubFileDecode filter flushfile } { pop pop } ifelse /offsets f 12 string readstring pop def } { SubfontID 0 gt { QUIET not { (SubfontID > 0 with a True Type file which is not a collection.) = } if /.loadttfonttables cvx /invalidfont signalerror } if /ttc_offset 0 def } ifelse % Peek because table counter may be incorrect. /tables f offsets 4 getu16 16 mul string .peekstring pop def /tabdict tables length 16 idiv dict def % tabs = tables we want to keep, sorted by file position. /tabs [ 0 16 tables length 1 sub { tables exch 16 getinterval TTFDEBUG { dup //.printtab exec } if dup 0 4 getinterval readtables_ 1 index known { % put all 0 length tables at 0 to avoid overlap 1 index 12 getu32 0 eq { 1 index 8 0 putu32 } if tabdict exch 2 index put } { pop pop } ifelse } for ] { exch 8 getu32 exch 8 getu32 lt } .sort def % In certain malformed TrueType fonts, tables overlap. % Truncate tables if necessary. 0 1 tabs length 2 sub { dup tabs exch get exch 1 add tabs exch get 1 index 8 getu32 2 index 12 getu32 add 1 index 8 getu32 gt { (**** Warning: ) print 1 index 0 4 getinterval print ( overlaps ) print dup 0 4 getinterval print (, truncating.) = flush dup 8 getu32 2 index 8 getu32 sub 2 index 12 3 -1 roll putu32 } if pop pop } for } .bind executeonly def % <file> <bool> <SubfontID> .loadwofftables - % Pushes .loadttfontdict & scratch dict on d-stack. % Defines f, offsets, tables, tabdict, tabs, tthdrlen. % Skips loca and glyf if <bool> is true. /.loadwofftables { //.loadttfontdict begin 40 dict begin /SubfontID exch def /load_stripped exch def /f exch def % loading WOFFs "stripped" only works for .findfontvalue - we cannot % (currently) use a stripped wOFF font load_stripped { readtables_stripped } { readtables } ifelse /readtables_ exch def /offsets 12 string def /woffhdr f 44 string readstring pop def /tthdrlen woffhdr length def /ttc_offset 0 def woffhdr 0 4 getinterval (wOFF) eq not % allow loading wOFFOTTO fonts "stripped" for .findfontvalue woffhdr 4 4 getinterval (OTTO) eq load_stripped not and or {/.loadwofftables cvx /invalidfont signalerror} { offsets 0 woffhdr 4 4 getinterval putinterval /tables f woffhdr 12 getu16 20 mul string .peekstring pop def offsets 4 tables length 20 idiv putu16 /tabdict tables length 20 idiv dict def /tabs [ 0 20 tables length 1 sub { tables exch 20 getinterval TTFDEBUG { dup //.printtab exec } if dup 0 4 getinterval readtables_ 1 index known { % put all 0 length tables at 0 to avoid overlap 1 index 12 getu32 0 eq { 1 index 8 0 putu32 } if tabdict exch 2 index put } {pop pop} ifelse }for ] { exch 4 getu32 exch 4 getu32 lt } .sort def } ifelse } .bind def /.file_table_pos_names mark /glyf 0 /loca 0 .dicttomark readonly def % - .readttdata - % Read data. Updates offsets, tabs; stores data in tabdict. /.readttdata { /file_table_pos 10 dict def /fpos tthdrlen ttc_offset add def /sfpos offsets length tabs length 16 mul add def offsets 4 tabs length putu16 0 1 tabs length 1 sub { dup tabs exch get dup 0 4 getinterval /tname exch def dup length 20 eq { dup 4 getu32 /tpos exch def dup 8 getu32 /tclen exch def dup 12 getu32 /tlen exch def } { dup 8 getu32 /tpos exch def dup 12 getu32 /tlen exch def /tclen tlen def } ifelse load_stripped //.file_table_pos_names tname known and { pop file_table_pos tname [tpos tlen tclen] put tabdict tname () put pop } { dup length 20 eq { 0 16 getinterval dup 8 sfpos putu32 tabs 3 -2 roll put } {8 sfpos putu32 pop} ifelse % Skip data between the end of the previous table and % the beginning of this one, if any. tpos fpos gt { load_stripped { % 'setfileposition' is faster for skipping a big data. f tpos setfileposition } { f tpos fpos sub () /SubFileDecode filter dup flushfile closefile /fpos tpos def } ifelse } if /ff tlen tclen eq not {f tclen () /SubFileDecode filter /FlateDecode filter} {f tlen () /SubFileDecode filter} ifelse def ff tlen readtables_ tname get exec ff closefile tabdict tname 3 -1 roll put % Round up the table length to an even value. /sfpos sfpos tlen dup 1 and add add def } ifelse /fpos fpos tclen add def } for } .bind def % Find the string in a list of strings that includes a given index. % <strings> <index> .findseg <string> <index'> /.findseg { exch { dup length 2 index gt { exch exit } if length sub } forall } .bind def % - .makesfnts - % Defines checksum, getloca, head, locatable, numloca, post, sfnts, upem % Note that the 'loca' table may be out of order. /.makesfnts { //.readttdata exec /head tabdict /head get def /post tabdict /post .knownget { dup 0 get /post_first_part exch def } { //null } ifelse def load_stripped not { /locatable tabdict /loca get def /numloca locatable dup type /stringtype eq { length } { 0 exch { length add } forall } ifelse % no def yet locatable type /stringtype eq { /.indexloca {} def } { /.indexloca //.findseg def } ifelse head 50 getu16 0 ne { /getloca { 2 bitshift locatable exch .indexloca getu32 } def 4 idiv 1 sub } { /getloca { dup add locatable exch .indexloca getu16 dup add } def 2 idiv 1 sub } ifelse def % numloca } { % We did not load loca, take the number of glyphs from maxp. /numloca tabdict /maxp get 4 getu16 def } ifelse /sfnts [ offsets tabs { concatstrings } forall tabs { 0 4 getinterval tabdict exch get dup type /stringtype ne { aload pop } if } forall ] def } .bind executeonly odef /first_post_string % - first_post_string <string> { post dup type /arraytype eq { 0 get } if } bind def % - .getpost - % Uses post, defines glyphencoding /.getpost { /glyphencoding post //null eq { TTFDEBUG { (post missing) = flush } if [ ] } { postformats first_post_string 0 getu32 .knownget { TTFDEBUG { (post: format ) print first_post_string dup 0 getu16 =only (,) print 2 getu16 = flush } if post exch exec } { TTFDEBUG { (post: unknown format ) print post 0 getu32 = flush } if [ ] } ifelse } ifelse TTFDEBUG { (post=) print dup //== exec } if def } .bind def % - .ttkeys <key> <value> ... /.ttkeys { count /ttkeycount exch def /upem head 18 getu16 def /FontMatrix matrix /FontBBox [ 36 2 42 { head exch gets16 upem div } for ] nextxuid tabdict /name .knownget { % Find the names from the 'name' table. /names exch def /FontName names 6 findname not { names 4 findname not { curxuid 16#ffffffff and 16 32 string cvrs } if } if /fontname 1 index def /FontInfo mark names 0 findname { /Notice exch } if names 1 findname { /FamilyName exch } if names 4 findname { /FullName exch } if names 5 findname { /Version exch } if } { % No name table, fabricate a FontName. /FontName curxuid 16#ffffffff and 16 32 string cvrs /fontname 1 index def /FontInfo mark } ifelse % Stack: ... /FontInfo mark key1 value1 ... post //null ne { /ItalicAngle first_post_string 4 gets32 65536.0 div /isFixedPitch first_post_string 12 getu32 0 ne /UnderlinePosition first_post_string 8 gets16 upem div /UnderlineThickness first_post_string 10 gets16 upem div } if counttomark 0 ne { .dicttomark } { pop pop } ifelse /XUID [orgXUID 42 curxuid] TTFDEBUG { tabs { //.printtab exec } forall [ sfnts { length } forall ] //== exec count ttkeycount sub array astore dup { //== exec } forall aload pop } if /sfnts sfnts } .bind def % ---------------- Standard TrueType font loading ---------------- % % - .pickcmap_with_no_xlatmap - % Defines cmapsub, cmaptab /.pickcmap_with_no_xlatmap { tabdict /cmap get % The Apple cmap format is no help in determining the encoding. % Look for a Microsoft table. If we can't find one, % just use the first table, whatever it is. dup 4 8 getinterval_from_stringarray exch % () [] % the default 0 1 2 index 2 getu16a 1 sub { % () [] i 8 mul 4 add 1 index exch 8 getinterval_from_stringarray % () [] () TTFDEBUG { (cmap: platform ) print dup 0 getu16 =only ( encoding ) print dup 2 getu16 = flush } if dup 0 getu16 3 eq { exch 3 -1 roll pop exit } if pop } for % Stack: subentry table /cmapsub 2 index def % () [] exch 4 getu32 1 index string_array_size 1 index sub getinterval_from_stringarray /cmaptab exch def } .bind def % - .pickcmap_with_xlatmap - % Defines cmapsub, cmaptab /.pickcmap_with_xlatmap { .xlatmap_dict /TrueType known not { (Emulating a CID font with a True Type file, ) print (the file gs/lib/xlatmap must contain /TrueType key.) = /.pickcmap_with_xlatmap cvx /configurationerror signalerror } if //false .xlatmap_dict /TrueType get dup length 2 sub 0 exch 2 exch { % bool [] i 2 copy get % bool [] i () (.) search { % bool [] i post match pre cvi exch pop exch cvi % bool [] i PlatID SpecID } { (gs/lib/xlatmap containg a record with an invalid (PlatformID.SpecificID)) = /.pickcmap_with_xlatmap cvx /configurationerror signalerror } ifelse TTFDEBUG { (Seeking a cmap for platform=) print 1 index =only ( encoding=) print dup = } if tabdict /cmap get % bool [] i PlatID SpecID (cmap) dup /cmaptab exch def % temporary 0 1 2 index 2 getu16a 1 sub { % bool [] i PlatID SpecID (cmap) j 8 mul 4 add 1 index exch 8 getinterval_from_stringarray % bool [] i PlatID SpecID (cmap) (cmapsub) TTFDEBUG { (cmap: platform ) print dup 0 getu16 =only ( encoding ) print dup 2 getu16 = flush } if dup 0 getu16 4 index eq { dup 2 getu16 3 index eq { % bool [] i PlatID SpecID (cmap) (cmapsub) TTFDEBUG { (Choosen a cmap for platform=) print 3 index =only ( encoding=) print 2 index = } if /cmapsub 1 index def dup 4 getu32 % bool [] i PlatID SpecID (cmap) (cmapsub) p cmaptab 1 index getu16a % get cmap format 8 lt { % length for traditional 16bit format 0, 2, 4, 6 cmaptab 1 index 2 add getu16a } { % length for advanced 32bit format 8, 10, 12 cmaptab 1 index 4 add getu32a } ifelse % bool [] i PlatID SpecID (cmap) (cmapsub) p l cmaptab 3 1 roll getinterval_from_stringarray /cmaptab exch def % bool [] i PlatID SpecID (cmap) (cmapsub) 5 index 5 index 1 add get % bool [] i PlatID SpecID (cmap) (cmapsub) /Decoding /Decoding exch def % bool [] i PlatID SpecID (cmap) (cmapsub) 7 -1 roll pop //true 7 1 roll % true [] i PlatID SpecID (cmap) (cmapsub) } if } if pop % true [] i PlatID SpecID (cmap) 5 index { exit } if } for % bool [] i PlatID SpecID (cmap) pop pop pop pop % bool [] 1 index { exit } if } for % bool [] pop % bool not { QUIET not { (True Type font doesn't contain a charset listed in gs/lib/xlatmap.) = } if /.pickcmap_with_xlatmap cvx /invalidfont signalerror } if % } .bind def % - .pickcmap - % Defines cmapsub, cmaptab /.pickcmap { % Currently we use xlatmap only for emulation CIDFontType 2 with % a disk True Type font files, and use load_stripped % to check this regime. We would like to do so % while emulating a Type 42, but first the old code % about handling them to be changed % with adding a handling of a Decoding. % fixme : A correct way to fix this is to implenent % the Type 42 emulation with gs_fntem.ps . % Also note that PDF embedded fonts probably don't need a xlatmap - % see PDF spec, "Encodings for True Type fonts". load_stripped { //.pickcmap_with_xlatmap exec } { //.pickcmap_with_no_xlatmap exec } ifelse } .bind executeonly odef currentdict /.pickcmap_with_xlatmap .undef currentdict /.pickcmap_with_no_xlatmap .undef % <glyph> .nname <_name> /.nname { =string cvs (_) exch concatstrings cvn } bind def % - .charkeys /CharStrings <charstrings> /Encoding <encoding> % Resets glyphencoding /.charkeys { TTFDEBUG { (glyphencoding: length=) print glyphencoding dup length = === flush } if % Hack: if there is no usable post table but the cmap uses % the Microsoft Unicode encoding, use ISOLatin1Encoding. % if 'post' presents, .charkeys computes (with dropping minor details) : % CharStrings = glyphencoding^-1 % Encoding = cmap*glyphencoding % because 'post' maps glyph indices to glyph names. % Otherwise .charkeys must compute (with dropping same details) : % CharStrings = glyphencoding^-1 * cmap % Encoding = glyphencoding % because glyphencoding is stubbed with an encoding, % which maps char codes to glyph names. glyphencoding length 0 eq { /have_post //false def cmapsub 0 4 getinterval <00030001> eq { TTFDEBUG { (No post but have cmap 3.1, so use ISOLatin1Encoding) = } if /glyphencoding ISOLatin1Encoding dup length array copy def } { TTFDEBUG { (No encoding info, use .GS_extended_SymbolEncoding) = } if /glyphencoding /.GS_extended_SymbolEncoding findencoding dup length array copy def } ifelse } { /have_post //true def } ifelse % If necessary, fabricate additional glyphencoding entries % to cover all of loca glyphencoding length numloca lt { /glyphencoding numloca array glyphencoding length dup 1 sub 0 1 3 2 roll { dup glyphencoding exch get 3 index 3 1 roll put } for % /glyphencoding <newarray> <glyphencoding length> 1 numloca 1 sub { 1 index exch dup //.nname exec put } for def } if /cmapa cmaptab cmapdict def % Some badly designed Chinese fonts have a post table % in which all glyphs other than 0 are named .null. % Use CharStrings to keep track of the reverse map from % names to glyphs, and don't let any name be used for % more than one glyph. /CharStrings glyphencoding dup length 1 add dict % +1 for .notdef 0 1 3 index length 1 sub { % Stack: glyphencoding dict index dup 3 index 1 index get have_post not { exch cmapa exch .knownget not { 0 % a stub for a while. Must skip the entry. } if exch } if 3 index 1 index known { % The same name maps to more than one glyph. Change the name. % No special treatment for /.notdef glyph. Bug 689408. pop //.nname exec 3 index 2 index 2 index put 2 index exch 3 -1 roll put } { 3 index exch 3 -1 roll put % unique name pop } ifelse } for exch pop % If there is no .notdef entry, map it to glyph 0. dup /.notdef known not { dup /.notdef 0 put } if TTFDEBUG { (CharStrings:)= dup { exch =string cvs print ( ) print //== exec } forall } if % Provide all known aliases for each glyph cmapsub 0 4 getinterval <00030001> eq % is the cmap table a unicode one? cmapa //ReverseAdobeGlyphList //AdobeGlyphList { % CharStrings(dict) isunicode(boolean) cmap(dict) RAGL(dict) gname(name) codep(integer) exch dup 6 index exch .knownget { % CharStrings(dict) isunicode(boolean) cmap(dict) RAGL(dict) codep(integer) gname(name) gindex(integer) 3 index 3 index .knownget { % CharStrings(dict) isunicode(boolean) cmap(dict) RAGL(dict) codep(integer) gname(name) gindex(integer) gnames(array) { % CharStrings(dict) isunicode(boolean) cmap(dict) RAGL(dict) codep(integer) gname(name) gindex(integer) gname(name) TTFDEBUG { (\n1 setting alias: ) print dup ==only ( to be the same as ) print 2 index //== exec } if 7 index 2 index 3 -1 roll exch put } forall pop pop pop } { pop pop } ifelse } { % CharStrings(dict) isunicode(boolean) cmap(dict) RAGL(dict) gname(name) codep(integer) exch % Only do this for Unicode cmap table 4 index { dup 4 index exch .knownget { % CharStrings(dict) isunicode(boolean) cmap(dict) RAGL(dict) gname(name) codep(integer) gindex(integer) exch pop TTFDEBUG { (\n2 setting alias: ) print 1 index ==only ( to use glyph index: ) print dup //== exec } if 5 index 3 1 roll put //false } { //true }ifelse } { //true } ifelse { % CharStrings(dict) isunicode(boolean) cmap(dict) RAGL(dict) gname(name) codep(integer) 16 4 string cvrs dup length neg 7 add (uni0000) dup 4 -2 roll exch putinterval cvn 3 index 1 index .knownget { % CharStrings(dict) isunicode(boolean) cmap(dict) RAGL(dict) gname(name) codep(integer) gindex(integer) TTFDEBUG { (\3 nsetting alias: ) print 1 index ==only ( to be index: ) print dup //== exec } if exch pop 5 index 3 1 roll put } { pop pop } ifelse } if } ifelse } forall pop pop pop readonly /Encoding [ have_post { 0 1 255 { cmapa exch .knownget not { 0 } if glyphencoding dup length 2 index le { pop pop /.notdef } { exch get } ifelse } for } { glyphencoding dup length 256 gt { 0 256 getinterval } if aload pop counttomark 256 exch sub { /.notdef } repeat } ifelse ] TTFDEBUG { (Encoding: ) print dup === flush } if } .bind odef % ---------------- CIDFontType 2 font loading ---------------- % % Fill a string with sequential CIDs starting from the initial value. % <string> <value> .fill_identity_cmap <string> /.fill_identity_cmap { % () v 1 index length 2 sub % () v n-2 0 2 3 2 roll { % () v 0 2 n-1 3 copy exch % () v i () i v -8 bitshift % () v i () i v>>8 put % () v i 3 copy 1 add % () v i () v i+1 exch 255 and % () v i () i+1 v&255 put % () v i pop 1 add % () v+1 } for pop } .bind def % <CIDSystemInfo dict> <dict> .definettcidfont <font> /.definettcidfont { dup begin /CIDFontName fontname def /CIDFontType 2 def /CIDSystemInfo 4 -1 roll def /CharStrings mark /.notdef 0 .dicttomark def % The cmap isn't of any use even if it is present. % Just construct an identity CIDMap covering all the glyphs. /CIDCount numloca % Wrong if a CIDFontType2 embedded into PDF with a non-Identity CIDToGIDMap. def % processCIDToGIDMap may replace. /CIDMap numloca maxstring le { % Use a single string. numloca 2 mul string 0 //.fill_identity_cmap exec } { % We must use 2 strings. maxstring 2 mul string 0 //.fill_identity_cmap exec numloca maxstring sub 2 mul string maxstring //.fill_identity_cmap exec 2 array astore } ifelse def /GDBytes 2 def end end end dup /CIDFontName get exch /CIDFont defineresource } .bind def % <CIDSystemInfo dict> <file> <Substite name> .loadttcidfont <cidtype2font> /.loadttcidfont { exch //false 0 .loadttfonttables .makesfnts % CIDFontType2 fonts don't have a cmap: they are indexed by CID. mark //.ttkeys exec .dicttomark dup % convert keys to dict and copy dict 3 -1 roll % Bring PDF substitute name to top of stack dup /fontname exch def /FontName exch put % replace any definition of /FontName //.definettcidfont exec } .bind executeonly odef % <file> <SubfontID> .load_tt_font_stripped <font_data> % The font_data includes sfnts, NumGlyphs, TT_cmap, file_table_pos, Decoding. % CIDMap to be created later from TT_cmap. /.load_tt_font_stripped { //true exch .loadttfonttables .makesfnts .pickcmap mark //.ttkeys exec /NumGlyphs numloca /TT_cmap cmaptab cmapdict /file_table_pos file_table_pos /Decoding Decoding .dicttomark end end } .bind executeonly def /.load_woff_for_cid { //false exch //.loadwofftables exec .makesfnts % we have to set load_stripped here so % .pickcmap will follow the right logic % for emulating a CIDFont /load_stripped //true def .pickcmap /load_stripped //false def mark //.ttkeys exec /NumGlyphs numloca /TT_cmap cmaptab cmapdict % /file_table_pos file_table_pos /Decoding Decoding .dicttomark end end } .bind executeonly def % ---------------- PDF TrueType font loading ---------------- % % Strictly speaking, this code should be loaded only if we have a PDF % interpreter, but it's so closely tied to the rest of the code in this % file that we always include it. % <plat+enc> .findcmap <subtable> true % <plat+enc> .findcmap false /.findcmap { //false exch tabdict /cmap get % Some fonts have multiple cmaps with the same platform and % encoding. Use the first one we find. 0 1 2 index 2 getu16a 1 sub { % Stack: false plat+enc cmap index 8 mul 4 add 1 index exch 8 getinterval_from_stringarray dup 0 4 getinterval 3 index eq { 4 getu32 1 index exch 1 index string_array_size 1 index sub getinterval_from_stringarray 4 -1 roll not 4 2 roll exit } if pop } for % Stack: false plat+enc cmap || subtable true plat+enc cmap pop pop } .bind def % Build .symbol_list for .pdfcharkeys . % It is a dictionary containing all SymbolEncoding glyph names % and random names for filling gaps in the character code range. /.symbol_list 256 dict def { =string 0 (x) 0 get put /SymbolEncoding .findencoding 0 1 255 { dup 2 index exch get dup /.notdef eq { pop dup =string 1 3 getinterval cvs length 1 add =string exch 0 exch getinterval cvn } if exch //.symbol_list 3 1 roll put } for pop } .bind exec % Create .GS_extended_SymbolEncoding as inverse of .symbol_list . { /.GS_extended_SymbolEncoding 256 array //.symbol_list { exch 2 index 3 1 roll put } forall .defineencoding } .bind exec /.hexdigits (0123456789ABCDEF) def /.is_hex_digit { % <int> .is_hex_digit <bool> dup 48 ge exch dup 57 le exch dup 65 ge exch 70 le and 3 1 roll and or } .bind def /.popfex { pop //false exit } bind def /.pop3ex { pop pop pop exit } bind def /.addglyph { % <dict> <name> <glyph#> .addglyph - 1 index .namestring % d n g s dup length 7 eq { % Bug688467.ps doesn't work if the uniXXXX mapping is allowed with any cmap. % Allow it with cmap 3.1 only. currentdict /.allow_uniXXXX_glyph_names .knownget not { //false } if } { //false } ifelse % d n g s b { % An undocumented Adobe feature (not sure) : % if the name is uniXXXX, obtain Unicode code from it. % See bug 688946. TTFDEBUG { (Try uniXXXX:) print dup print } if { dup 0 get 117 ne //.popfex if % u dup 1 get 110 ne //.popfex if % n dup 2 get 105 ne //.popfex if % i dup 3 get //.is_hex_digit exec not //.popfex if dup 4 get //.is_hex_digit exec not //.popfex if dup 5 get //.is_hex_digit exec not //.popfex if dup 6 get //.is_hex_digit exec not //.popfex if dup 3 1 getinterval .hexdigits exch search pop length exch pop exch pop 12 bitshift exch dup 4 1 getinterval .hexdigits exch search pop length exch pop exch pop 8 bitshift exch dup 5 1 getinterval .hexdigits exch search pop length exch pop exch pop 4 bitshift exch dup 6 1 getinterval .hexdigits exch search pop length exch pop exch pop exch pop add add add cmapencoding exch .knownget not { 0 } if dup 0 eq //.popfex if TTFDEBUG { ( index=) print dup =string cvs print } if exch pop put //true exit } loop TTFDEBUG { ()= } if } { pop //false } ifelse not { % d n g { cmapencoding exch .knownget not { 0 } if dup 0 eq //.pop3ex if 3 copy pop known //.pop3ex if put exit } loop } if } .bind def % <chartoglyphmap> <subcmap> <AGL> .pdfmapchars /CharStrings <charstrings> /.pdfmapchars { exch cmapdict /cmapencoding exch def % c2g /CharStrings 0 dict % c2g /CS <<>> % Add glyphs of <AGL>*<subcmap> : 3 2 roll { % /CS <<>> v dup type /arraytype eq { % /CS <<>> /name [] { 3 copy //.addglyph exec pop } forall } { 3 copy //.addglyph exec pop } ifelse pop } forall % Add glyphs of 'post' with lower priority : 0 1 glyphencoding length 1 sub { dup glyphencoding exch get exch dup 0 ne { 3 copy pop known not { 3 copy put } if } if pop pop } for % Finally, add glyphs from the prebuilt_encoding with lowest priority % this is a catch-all for poorly matched font/PDF combos 3 2 roll { % /CS <<>> v dup type /arraytype eq { % /CS <<>> /name [] { 3 copy //.addglyph exec pop } forall } { 3 copy //.addglyph exec pop } ifelse pop } forall dup /.notdef 0 put } .bind def % <subtable> .pdfmapsymbolic /Encoding [] /CharStrings <<>> /.pdfmapsymbolic { //true /.render_notdef gput cmapdict dup length 1 add dict begin [ 64 { /.notdef /.notdef /.notdef /.notdef } repeat ] exch { % [] char glyph exch dup 255 gt { 255 and 2 index 1 index get /.notdef ne { pop pop //false } { //true } ifelse } { //true } ifelse { dup (01234567) cvs cvn % glyph char /char 3 1 roll % /char glyph char 3 index exch % /char glyph [] char 3 index put % /char glyph def % - } if } forall /.notdef 0 def /Encoding exch /CharStrings currentdict end } .bind def % If we're using a 1,0 cmap table, we need to store the table for the heuristic % to know whether to image or elide GID 0. See zfapi.c ps_get_glyphname_or_cid(). % For other cmap types, we don't. Since this just pushes key/value pairs onto the % stack for a later dicttomark op, it doesn't matter that different branches can push % different numbers of objects. % % - .pdfcharkeys [/TT_cmap cmapdict] /CharStrings <charstrings> /Encoding <encoding> /.pdfcharkeys { % The following algorithms are per the PDF 1.7 Reference. TTFDEBUG { (.pdfcharkeys beg) = } if % if the flags say symbolic, *and* the font contains a symbol or UCS-2 % cmap table, ignore Encoding if there is one, treat as symbolic. % If the flags say symbolic, and the font doesn't have a symbol cmap % and we have an Encoding, treat it as non-symbolic % if we don't have an Encoding, try the MacRoman cmap table. % Finally, if none of that works, remove the Encoding, and treat it % as non-symbolic. is_symbolic { <00030000> //.findcmap exec { //true } { prebuilt_encoding //null eq { <00030001> //.findcmap exec {//true} {<00010000> //.findcmap exec} ifelse } {//false} ifelse } ifelse { //.pdfmapsymbolic exec /prebuilt_encoding //null def //false } { /prebuilt_encoding //null def //true } ifelse } { //true } ifelse { <00030001> //.findcmap exec { prebuilt_encoding //null ne { TTFDEBUG { (Using cmap 3.1 with prebuilt_encoding for non-symbolic.) = } if //true /.render_notdef gput % The character code in /prebuilt_encoding[] is not guaranteed to be % compatible with the Microsoft UCS2 TrueType cmap subtable. % If the glyphname is known by AdobeGlyphList, the charcode for the glyph % is replaced by UCS2 charcode from AdobeGlyphList. Otherwise it is left % as in /prebuilt_encoding[]. /.pdfmapchars should dredge them. /.allow_uniXXXX_glyph_names //true def AdobeGlyphList prebuilt_encoding .invert_encoding dup { % <<AGL>> <<pbe>> <glyphname> <pbecode> pop % <<AGL>> <<pbe>> <glyphname> TTFDEBUG { (check glypname /) print dup =only flush } if 2 index 1 index .knownget { % <<AGL>> <<pbe>> <glyphname> <AGLcode> 2 index 3 1 roll % <<AGL>> <<pbe>> <<pbe>> <glyphname> <AGLcode> TTFDEBUG { ( redefine codepoint by AdobeGlyphList, ) print dup //== exec flush } if put % <<AGL>> <<pbe>> } { % <<AGL>> <<pbe>> <glyphname> TTFDEBUG { ( unknown glyphname, leave as it is ) = flush } if pop % <<AGL>> <<pbe>> } ifelse } forall exch pop % <<pbe>> TTFDEBUG { dup (<<\n) print { exch ( ) print =only (\t) print //== exec } forall (>>\n) print flush } if exch AdobeGlyphList //.pdfmapchars exec /Encoding prebuilt_encoding } { % Likely this branch is now obsolete. TTFDEBUG { (Using cmap 3.1 for non-symbolic.) = } if 0 dict exch AdobeGlyphList //.pdfmapchars exec /Encoding /WinAnsiEncoding .findencoding % WinAnsiEncoding is just a stub here. % It will be replaced with one from font resource, % because PDF spec requires it. } ifelse } { <00010000> //.findcmap exec { /TT_cmap 1 index cmapdict 3 -1 roll TTFDEBUG { (Using cmap 1.0 for non-symbolic.) = } if prebuilt_encoding //null ne { prebuilt_encoding .invert_encoding exch .romanmacdict //.pdfmapchars exec prebuilt_encoding } { 0 dict exch .romanmacdict //.pdfmapchars exec /MacRomanEncodingForTrueType .findencoding } ifelse /Encoding exch } { % Apply the default algorithm for using the 'post'. .charkeys % But use PDF encoding when available. prebuilt_encoding //null ne { pop prebuilt_encoding } if } ifelse } ifelse } if TTFDEBUG { (.pdfcharkeys end) = } if } .bind executeonly def % <file> <is_symbolic> <Encoding|null> <FontName> .loadpdfttfont <type42font> /.loadpdfttfont { TTFDEBUG { (.loadpdfttfont FontName=) print dup == } if /font_name gput TTFDEBUG { (.loadpdfttfont Encoding=) print dup //== exec } if /prebuilt_encoding gput % for .pdfcharkeys /is_symbolic gput % init key for whether to display the TTF notdef //false /.render_notdef gput //false 0 .loadttfonttables .makesfnts tabdict /cmap known not { ( **** Warning: Embedded TT font lacks required cmap table. Using identity cmap.\n) pdfformaterror % Unknown (i.e. not 0 ) language ID brings in post table. % Fields: cmap_version, number_of_subtables, % plarform_id, encoding_id, offset, % format, subtable_length, language, % 256 bytes of identity mapping. tabdict /cmap < 0000 0001 0001 D00D 0000000c 0000 0106 0000 00 01 02 03 04 05 06 07 08 09 0a 0d 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1d 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2d 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3d 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4d 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 5d 5c 5d 5e 5f 60 61 62 63 64 65 66 67 68 69 6a 6d 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 7d 7c 7d 7e 7f 80 81 82 83 84 85 86 87 88 89 8a 8d 8c 8d 8e 8f 90 91 92 93 94 95 96 97 98 99 9a 9d 9c 9d 9e 9f a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ad ac ad ae af b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bd bc bd be bf c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cd cc cd ce cf d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da dd dc dd de df e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea ed ec ed ee ef f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fd fc fd fe ff > readonly put } if .getpost .pickcmap mark //.pdfcharkeys exec //.ttkeys exec /FontType 42 /PaintType 0 /.render_notdef .render_notdef TTFDEBUG { (numloca=) print numloca = } if .dicttomark dup /FontName font_name put % replace any definition of /FontName end end .completefont } .bind executeonly odef %--------- Define main type42font loading routines, after their dependencies ------------ % <file> .loadttfont <type42font> /.loadttfont { TTFDEBUG { (.loadttfont) = } if //false % if this came from Fontmap, there may be a dictionary on the dict stack % with a SubfontID in it. Validate it *is* a Fontmap record by also % checking for a Path key /SubfontID where { dup /Path known {/SubfontID get} {pop 0} ifelse } {0} ifelse .loadttfonttables .makesfnts .getpost .pickcmap mark % if we're loading to substitute for TTF in a PDF, % load the font the "PDF way" /prebuilt_encoding where {pop //.pdfcharkeys exec} {.charkeys} ifelse //.ttkeys exec /FontType 42 /PaintType 0 TTFDEBUG { (numloca=) print numloca = } if .dicttomark end end dup /FontName get exch definefont } .bind executeonly def % <file> .loadwofffont <type42font> /.loadwofffont { TTFDEBUG { (.loadwofffont) = } if //false 0 //.loadwofftables exec .makesfnts .getpost .pickcmap mark .charkeys //.ttkeys exec /FontType 42 /PaintType 0 TTFDEBUG { (numloca=) print numloca = } if .dicttomark end end dup /FontName get exch definefont } .bind executeonly def % ----- Utilities for loading possible TrueType font ------ % <file> .findttfontname <fname> true % <file> .findttfontname false % Closes the file in either case. /.findttfontname { //true 0 .loadttfonttables tabdict /name .knownget { dup 8 getu32 f exch setfileposition 12 getu32 dup 65535 gt { pop 65535 } if % protect against extremely large name string f exch readstring pop dup 6 findname not { 4 findname % Try FullName } { exch pop //true } ifelse } { //false } ifelse f closefile end end } .bind def /.findwoffname { //true 0 //.loadwofftables exec tabdict /name .knownget { dup /clen exch 8 getu32 def dup /olen exch 12 getu32 def 4 getu32 f exch setfileposition olen dup 65535 gt { pop 65535 } if % protect against extremely large name /fs clen olen ne {f clen () /SubFileDecode filter /FlateDecode filter} {f clen () /SubFileDecode filter} ifelse def string fs exch readstring pop fs closefile dup 6 findname not { 4 findname % Try FullName } { exch pop //true } ifelse } { //false } ifelse f closefile end end } .bind def /tt_tag_dict << <00010000> 0 (true) 0 (typ1) 0 (ttcf) 0 >> readonly def /ttf_otf_tag_dict << <00010000> 0 (true) 0 (typ1) 0 (ttcf) 0 (OTTO) 0>> readonly def % The wOFF tag is immediately followed by the sfnt "flavour" so for simplicity % combine them /woff_tag_dict << (wOFF) 0 <774F464600010000> 0 % (wOFF)<00010000> .concatstrings (wOFFtrue) 0 (wOFFtyp1) 0 >> readonly def % <file> .is_ttf_or_otf <bool> /.is_ttf_or_otf { dup 0 setfileposition (1234) .peekstring { //ttf_otf_tag_dict exch known } { //false } ifelse } .bind def /.is_woff { dup 0 setfileposition (1234) .peekstring { //woff_tag_dict exch known } { //false } ifelse } .bind def % <file> <key> .findfontvalue <value> true % <file> <key> .findfontvalue false % Closes the file in either case. /.findnonttfontvalue /.findfontvalue load def /.findfontvalue { 1 index //.is_woff exec { dup /FontType eq { pop closefile 42 //true } { dup /FontName eq { pop //.findwoffname exec} { pop closefile //false } ifelse } ifelse } { 1 index //.is_ttf_or_otf exec { % If this is a font at all, it's a TrueType font. dup /FontType eq { pop closefile 42 //true } { dup /FontName eq { pop //.findttfontname exec} { pop closefile //false } ifelse } ifelse } { % Not a TrueType font. .findnonttfontvalue } ifelse } ifelse } .bind executeonly def % Load a font file that might be a TrueType font. % <file> .loadfontfile - /.loadnonttfontfile /.loadfontfile load def /.loadfontfile { dup (12345678) .peekstring { //woff_tag_dict exch known } { //false } ifelse { //.loadwofffont exec pop } { dup (1234) .peekstring { //tt_tag_dict exch known } { //false } ifelse { % If this is a font at all, it's a TrueType font. //.loadttfont exec pop } { % Not a TrueType font. .loadnonttfontfile } ifelse } ifelse } .bind def % Undef the local utility funcs [ /.findttfontname /.findwoffname /ttf_otf_tag_dict /tt_tag_dict /woff_tag_dict /.is_ttf_or_otf /.is_woff ] currentdict .undefinternalnames % ----- END .loadfontfile that supports possible TrueType font ------ % Undef these, not needed outside this file [ /.addglyph /.definettcidfont /.fill_identity_cmap /.findseg /.loadttfontdict /.is_hex_digit /.pop3ex /.popfex /.ttkeys /.printtab /.readttdata /.nname /.loadttfont /.loadwofffont /.loadwofftables /.findcmap /.pdfmapsymbolic /.pdfcharkeys /.pdfmapchars ] systemdict .undefinternalnames Fontmap.GS 0000644 00000031201 15030647507 0006407 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % Fontmap - standard font catalog for Ghostscript. % ---------------------------------------------------------------- % This file is a catalog of fonts known to Ghostscript. Any font % that is to be loaded automatically when named must be in this catalog, % except for fonts that Ghostscript finds automatically in directories % named in the GS_FONTPATH environment variable. % Each font has an entry consisting of three items: % % - The name by which the font is known inside Ghostscript % (a Ghostscript name preceded by a `/', or a string enclosed % in parentheses). This is used to find the file from which % a font of a given name should be loaded. % % - Information depending on whether this is a real font or a % font alias: % % - For real fonts, `PFA', `PFB', 'CFF', 'TTF, % 'TTC' (see below) files are usable as fonts for % Ghostscript. % % - For font aliases, the name of the font which should % be used when this one is requested, preceded by a % `/'. See the entry for Charter below for an example. % Note that an alias name cannot be enclosed in parentheses. % % - At least one space or tab, and a terminating semicolon. % % % There are three forms of record: % Substitute a font by name: % /FontName /SubstituteFont ; % Substitute a font with a file: % /FontName (/path/to/font/file) ; % Substitute a font with a font from a Truetype collection: % /FontName << /Path (/path/to/font/file) /SubfontID <ttc-index> >> ; % % Substituting a font with a file can either use the full path form, for example: % /CenturySchL-Ital (/usr/share/fonts/type1/gsfonts/c059033l.pfb) ; % Or rely on the Ghostscript font search path: % /CenturySchL-Ital (c059033l.pfb) ; % % % The dictionary form can be used to substitute a font with an individual font from a Truetype % collection: % /NSimSun << /Path (/home/user/fonts/simsun.ttc) /SubfontID 1>> ; % If the target is not a TTC, the SubfontID entry is ignored. % % NOTE: The font name (the entry in first column) must match the name of the TTC index. As % in the above example, index 0 in simsun.ttc must be /SimSun and index 1 must be /NSimSin. % The following table is executed as a PostScript file. % If you add new entries, be sure to copy the punctuation accurately; % in particular, you must leave at least one space or tab between each % field in the entry. Also, please read fonts.doc for important information % about font names. % PDF interpreter evaluates hexadecimal escapes in PDF font names before % looking up the font. When the resulting name cannot be represented using % PostScript name syntax, the string can be used instead of the name. % Note that .pfa and .pfb fonts are compatible with Adobe Type Manager % and other programs that don't include full PostScript interpreters, % as well as with PostScript interpreters; .gsf fonts are compatible with % PostScript interpreters, but not with ATM or similar programs. % % % Fonts contributed by: % URW++ Design and Development Incorporated % Poppenbuetteler Bogen 29A % D-22399 Hamburg % Germany % tel. +49 (40) 60 60 50 % fax +49 (40) 60 60 51 11 % http://www.urwpp.de % for distribution under the GNU License and Aladdin Free Public License. % See the notice at the head of this Fontmap file for licensing terms. % Each of these fonts is individually covered by the license: % for licensing purposes, they are not "part of" any larger entity. % The following notice applies to these fonts: % % Copyright URW Software, Copyright 1994 by URW. % % Aliases /AvantGarde-BookOblique /URWGothic-BookOblique ; /AvantGarde-Book /URWGothic-Book ; /AvantGarde-DemiOblique /URWGothic-DemiOblique ; /AvantGarde-Demi /URWGothic-Demi ; /Bookman-DemiItalic /URWBookman-DemiItalic ; /Bookman-Demi /URWBookman-Demi ; /Bookman-LightItalic /URWBookman-LightItalic ; /Bookman-Light /URWBookman-Light ; /Courier-Bold /NimbusMonoPS-Bold ; /Courier-BoldOblique /NimbusMonoPS-BoldItalic ; /Courier /NimbusMonoPS-Regular ; /Courier-Oblique /NimbusMonoPS-Italic ; /Helvetica-Bold /NimbusSans-Bold ; /Helvetica-BoldOblique /NimbusSans-BoldItalic ; /Helvetica-Narrow-Bold /NimbusSansNarrow-Bold ; /Helvetica-Narrow-BoldOblique /NimbusSansNarrow-BoldOblique ; /Helvetica-Narrow /NimbusSansNarrow-Regular ; /Helvetica-Narrow-Oblique /NimbusSansNarrow-Oblique ; /Helvetica /NimbusSans-Regular ; /Helvetica-Oblique /NimbusSans-Italic ; /NewCenturySchlbk-Bold /C059-Bold ; /NewCenturySchlbk-BoldItalic /C059-BdIta ; /NewCenturySchlbk-Italic /C059-Italic ; /NewCenturySchlbk-Roman /C059-Roman ; /Palatino-BoldItalic /P052-BoldItalic ; /Palatino-Bold /P052-Bold ; /Palatino-Italic /P052-Italic ; /Palatino-Roman /P052-Roman ; /Symbol /StandardSymbolsPS ; /Times-BoldItalic /NimbusRoman-BoldItalic ; /Times-Bold /NimbusRoman-Bold ; /Times-Italic /NimbusRoman-Italic ; /Times-Roman /NimbusRoman-Regular ; /ZapfChancery-MediumItalic /Z003-MediumItalic ; /ZapfDingbats /D050000L ; % % % Type 1 fonts contributed to the X11R5 distribution. % % The following notice accompanied the Charter fonts. % % (c) Copyright 1989-1992, Bitstream Inc., Cambridge, MA. % % You are hereby granted permission under all Bitstream propriety rights % to use, copy, modify, sublicense, sell, and redistribute the 4 Bitstream % Charter (r) Type 1 outline fonts and the 4 Courier Type 1 outline fonts % for any purpose and without restriction; provided, that this notice is % left intact on all copies of such fonts and that Bitstream's trademark % is acknowledged as shown below on all unmodified copies of the 4 Charter % Type 1 fonts. % % BITSTREAM CHARTER is a registered trademark of Bitstream Inc. /CharterBT-Roman (bchr.pfa) ; /CharterBT-Italic (bchri.pfa) ; /CharterBT-Bold (bchb.pfa) ; /CharterBT-BoldItalic (bchbi.pfa) ; % Aliases /Charter-Roman /CharterBT-Roman ; /Charter-Italic /CharterBT-Italic ; /Charter-Bold /CharterBT-Bold ; /Charter-BoldItalic /CharterBT-BoldItalic ; % The following notice accompanied the Utopia font: % % Permission to use, reproduce, display and distribute the listed % typefaces is hereby granted, provided that the Adobe Copyright notice % appears in all whole and partial copies of the software and that the % following trademark symbol and attribution appear in all unmodified % copies of the software: % % Copyright (c) 1989 Adobe Systems Incorporated % Utopia (R) % Utopia is a registered trademark of Adobe Systems Incorporated % % The Adobe typefaces (Type 1 font program, bitmaps and Adobe Font % Metric files) donated are: % % Utopia Regular % Utopia Italic % Utopia Bold % Utopia Bold Italic /Utopia-Regular (putr.pfa) ; /Utopia-Italic (putri.pfa) ; /Utopia-Bold (putb.pfa) ; /Utopia-BoldItalic (putbi.pfa) ; % % % Fonts contributed by URW GmbH for distribution under the GNU License. % The following notice accompanied these fonts: % % U004006T URW Grotesk 2031 Bold PostScript Type 1 Font Program % U003043T URW Antiqua 2051 Regular Condensed PostScript Type 1 Font Program % % Copyright (c) 1992 URW GmbH, Hamburg, Germany % % This program is free software; you can redistribute it and/or modify % it under the terms of the GNU General Public License as published by % the Free Software Foundation; either version 2 of the License, or % (at your option) later version. % % This program is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; wihtout even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. % See the GNU General Public License for more details. % % You should have received a copy of the GNU General Public License % along with this program; if not, write to the Free Software % Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 U.S.A. % % Address: % URW GmbH % PC Support % Harksheider Strasse 102 % 2000 Hamburg 65 % Germany % Phone: +49 40 60 60 50 (Reception) % Phone: +49 40 60 60 52 30 (PC Support) % Fax : +49 40 60 60 52 52 % /URWAntiquaT-RegularCondensed (u003043t.gsf) ; /URWGroteskT-Bold (u004006t.gsf) ; % % % Calligraphic Kana fonts. These are distributed under the OFL 1.1: % % Copyright (c) 1993, Kevin Hartig (kevin.hartig@gmail.com), % with Reserved Font Name Calligraphic-Hiragana and Calligraphic-Katakana. % This Font Software is licensed under the SIL Open Font License, Version 1.1. % This license is available with an FAQ at: http://scripts.sil.org/OFL % Hiragana and Katakana fonts. The character names are inappropriate, % and the encoding is probably not related to any known standard. /Calligraphic-Hiragana (fhirw.gsf) ; /Calligraphic-Katakana (fkarw.gsf) ; % % % Public-domain fonts. These have no copyright, and are of unknown quality. % Cyrillic fonts. The character names are inappropriate, % and the encoding is probably not related to any known standard. /Shareware-Cyrillic-Regular (fcyr.gsf) ; /Shareware-Cyrillic-Italic (fcyri.gsf) ; % Aliases /Cyrillic /Cyrillic-Regular ; /Cyrillic-Regular /Shareware-Cyrillic-Regular ; /Cyrillic-Italic /Shareware-Cyrillic-Italic ; % % % Fonts converted from Hershey outlines. These are constructed and % maintained manually. These are also in the public domain. % % The suggested UniqueID's and filenames are constructed differently for % these than for the ones above, because of the strange way that the Hershey % fonts were constructed. The scheme for these looks like: % % 42TTXY0 % % TT = typeface, X = ``class'', Y = variation % % The typeface names and numbers are listed in fonts.mak. % % class: % 0 = normal = r % 1 = simplex = s % 2 = complex = c % 3 = triplex = t % 4 = duplex = d % % variation: % 0 = normal (omitted) % 1 = oblique = o % 2 = italic = i % 3 = bold = b % 4 = bold oblique = bo % 5 = bold italic = bi % % Fonts created by Thomas Wolff <wolff@inf.fu-berlin.de>, by adding % accents, accented characters, and various other non-alphabetics % to the original Hershey fonts. These are "freeware", not to be sold. /Hershey-Gothic-English (hrger.pfa) ; % 5066533 /Hershey-Gothic-German (hrgrr.pfa) ; /Hershey-Gothic-Italian (hritr.pfa) ; /Hershey-Plain-Duplex (hrpld.pfa) ; /Hershey-Plain-Duplex-Italic (hrpldi.pfa) ; /Hershey-Plain-Triplex (hrplt.pfa) ; /Hershey-Plain-Triplex-Italic (hrplti.pfa) ; /Hershey-Script-Complex (hrscc.pfa) ; /Hershey-Script-Simplex (hrscs.pfa) ; % 5066541 % Fonts created algorithmically from the above. /Hershey-Gothic-English-Bold (hrgerb.gsf) ; % 5066542 /Hershey-Gothic-English-Oblique (hrgero.gsf) ; /Hershey-Gothic-English-SemiBold (hrgerd.gsf) ; /Hershey-Gothic-German-Bold (hrgrrb.gsf) ; /Hershey-Gothic-German-Oblique (hrgrro.gsf) ; /Hershey-Gothic-Italian-Bold (hritrb.gsf) ; /Hershey-Gothic-Italian-Oblique (hritro.gsf) ; /Hershey-Plain-Duplex-Bold (hrpldb.gsf) ; /Hershey-Plain-Duplex-Bold-Italic (hrpldbi.gsf) ; /Hershey-Plain-Triplex-Bold (hrpltb.gsf) ; /Hershey-Plain-Triplex-Bold-Italic (hrpltbi.gsf) ; /Hershey-Script-Complex-Bold (hrsccb.gsf) ; /Hershey-Script-Complex-Oblique (hrscco.gsf) ; /Hershey-Script-Simplex-Bold (hrscsb.gsf) ; /Hershey-Script-Simplex-Oblique (hrscso.gsf) ; % 5066556 % Fonts consisting only of characters from the original Hershey % distribution. These are Type 3 fonts. /Hershey-Greek-Complex (hrgkc.gsf) ; % 5066557 /Hershey-Greek-Simplex (hrgks.gsf) ; /Hershey-Plain (hrplr.gsf) ; /Hershey-Plain-Simplex (hrpls.gsf) ; % 5066560 % Fonts created algorithmically from the above. /Hershey-Plain-Bold (hrplrb.gsf) ; % 5066561 /Hershey-Plain-Bold-Oblique (hrplrbo.gsf) ; /Hershey-Plain-Oblique (hrplro.gsf) ; /Hershey-Plain-Simplex-Bold (hrplsb.gsf) ; /Hershey-Plain-Simplex-Bold-Oblique (hrplsbo.gsf) ; /Hershey-Plain-Simplex-Oblique (hrplso.gsf) ; % 5066566 % This font, and only this font among the Hershey fonts, uses % the SymbolEncoding. /Hershey-Symbol (hrsyr.gsf) ; % 5066567 /Arial /ArialMT ; /Arial,Bold /Arial-BoldMT ; /Arial,Italic /Arial-ItalicMT ; /Arial,BoldItalic /Arial-BoldItalicMT ; /TimesNewRoman /TimesNewRomanPSMT ; /TimesNewRoman,Bold /TimesNewRomanPS-BoldMT ; /TimesNewRoman,Italic /TimesNewRomanPS-ItalicMT ; /TimesNewRoman,BoldItalic /TimesNewRomanPS-BoldItalicMT ; gs_cidcm.ps 0000644 00000040673 15030647507 0006701 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % Extending Font resource category with CIDFont-CMap fonts. languagelevel 2 .setlanguagelevel currentglobal //true setglobal % In the comments below, 'CSI' is an abbreviation/acronym for CIDSystemInfo. % We pre-scan resource files to retrieve the CSI from them. % First we define a hidden procset .prs_dict containing % necessary variables and procedures. % Then we redefine the old /Font category using this procset. % We maintain internal caches for the CSI values retrieved from % resource files. This supposes that document doesn't uninstall % resource files. To disable caching, set enable_cache to false. % We assume that names starting with '.prs' do not appear in resource files. % If this causes any problem, this prefix should be systematically changed % in this file. ('prs' is an abbreviation for 'prescan'.) 25 dict begin % Define local variables : /.prs_dict currentdict def % self-reference (constant) /.prs_empty 0 dict readonly def /path_buffer 8192 string def /name_buffer 1024 string def /minus (-) 0 get def % character code constant for '-' /period (.) 0 get def % character code constant for '.' /CMap 10 dict def % CSI cache for CMaps /CIDFont 10 dict def % CSI cache for CIDFonts /enable_cache //true def % set false to disable cache % The folloving variables are just placeholders for ones to be set % dynamically : /.prsFile 0 def % file to prescan /.prsResult 0 def % result of prescan /.prsDictCount 0 def % save the dictionary stack depth % Define a dummy CIDInit procset to use while pre-scanning : /DummyCIDInit 15 dict begin /begincmap {} def /usecmap {pop} bind def {stop} bind [ /begincodespacerange /endcodespacerange /beginnotdefchar /endnotdefchar /beginnotdefrange /endnotdefrange /begincidchar /endcidchar /begincidrange /endcidrange /endcmap /usefont /StartData ] { 1 index def } bind forall pop currentdict end def % Define a local 'findresource' for pre-scanning : % (it returns the dummy CIDInit instead of the regular CIDInit ProcSet) /findresource { % <InstName> <CatName> findresource <inst> 2 copy /ProcSet eq exch % /InstName /CatName bool /InstName /CIDInit eq and { pop pop //DummyCIDInit } { //findresource exec } ifelse } bind def % Define procedures for pre-scanning : /StopIfCSIDefined { % - StopIfCSIDefined - % Check if the dictionary stack contains a dictionary containing /CIDSystemInfo. % The search is limited to the top .prsDictCount dictionaries in the stack. % If so, retrieve the CSI, and execute stop to terminate the pre-scanning of the file. % Otherwise, do nothing, so the pre-scanning continues. countdictstack //.prs_dict /.prsDictCount get sub dup { currentdict /CIDSystemInfo .knownget { //.prs_dict exch /.prsResult exch put stop } if currentdict exch end } repeat { begin } repeat } bind def /PrescanFile { % - PrescanFile - { //.prs_dict /.prsFile get token { dup type % token type dup /nametype eq exch /operatortype eq or { dup xcheck { exec //StopIfCSIDefined exec } if } if } { stop } ifelse } loop } bind odef /GetCIDSystemInfoFromFile { % <file> GetCIDSystemInfoFromFile <CSI> % This procedure reads resource files with 'token', % executing the tokens untill /CIDSystemInfo appears to be defined. % Normally the resource file creates a new dictionary on % dictionary stack and defines /CIDSystemInfo in it. % % Returns an empty dictionary if no CIDSystemInfo is found. RESMPDEBUG { (cidcm GetCIDSystemInfoFromFile beg) = } if //.prs_dict begin /.prsFile exch def /.prsResult //.prs_empty def /.prsDictCount countdictstack def RESMPDEBUG { (cidcm GetCIDSystemInfoFromFile will PrescanFile.) = } if { //PrescanFile } stopped pop //.prs_dict /.prsResult get end RESMPDEBUG { (cidcm GetCIDSystemInfoFromFile end) = } if } bind def /GetCIDSystemInfo { % <InstName> <CatName> GetCIDSystemInfo <CSI> % Retrieve CSI, using caches. RESMPDEBUG { (cidcm GetCIDSystemInfo beg) = } if /Category findresource begin % /InstName dup ResourceStatus { pop 2 lt { FindResource /CIDSystemInfo .knownget not { //.prs_empty } if % CSI } { % /InstName currentdict /GetCIDSystemInfoFromMap .knownget { exec } if dup type /nametype eq { RESMPDEBUG { (cidcm GetCIDSystemInfo got a name.) = } if //.prs_dict Category get % /InstName CSIs dup 2 index known //enable_cache and { RESMPDEBUG { (cidcm GetCIDSystemInfo from cache.) = } if exch get % CSI } { RESMPDEBUG { (cidcm GetCIDSystemInfo from file.) = } if exch % CSIs /InstName dup //path_buffer ResourceFileName % CSIs /InstName (path) RESMPDEBUG { (cidcm GetCIDSystemInfo from file ) print dup = } if currentglobal exch //true setglobal % CSIs /InstName g (path) mark exch % CSIs /InstName g [ (path) { (r) file } stopped { cleartomark //.prs_empty } { exch 1 index % CSIs /InstName g file [ file //GetCIDSystemInfoFromFile stopped { cleartomark closefile //.prs_empty } { exch pop exch closefile } ifelse } ifelse % CSIs /InstName g CSI exch setglobal % CSIs /InstName CSI dup 4 1 roll % CSI CSIs /InstName CSI put % CSI RESMPDEBUG { (cidcm GetCIDSystemInfo got from file : <<) print dup { exch //=string cvs print ( ) print //=string cvs print ( ) print } forall (>>) = } if } ifelse } if } ifelse } { pop //.prs_empty } ifelse end RESMPDEBUG { (cidcm GetCIDSystemInfo end) = } if } bind def /IsCompatibleCSI { % <CSI-M> <CSI-F> IsCompatibleCSI <bool> % The CSI in a CIDFont may be an array, a dict, or null. % If it is an array, it must be of 1 element, which is a dict. % In this case the dict is used for testing the compatibility. % Two dicts are compatible iff they contain same /Ordering and /Registry. % Identity CMap is compatible with any CIDFont. exch % CSI-F CSI-M { dup type /arraytype eq { dup length 1 ne { pop pop //false exit } if 0 get } if % CSI-F CSI-M dup type /dicttype ne { pop pop //false exit } if % CSI-F <<CSI-M>> exch % <<CSI-M>> CSI-F dup type /dicttype ne { pop pop //false exit } if % <<CSI-M>> <<CSI-F>> dup /Ordering .knownget { /Identity eq { pop pop //true exit } if } if //true % <<CSI-M>> <<CSI-F>> bEQ [/Registry /Ordering] { 2 index 1 index .knownget not { 1234567 } if % <<CSI-M>> <<CSI-F>> bEQ /key vF exch % <<CSI-M>> <<CSI-F>> bEQ vF /key 4 index exch .knownget not { 7654321 } if % <<CSI-M>> <<CSI-F>> bEQ vF vM eq and % <<CSI-M>> <<CSI-F>> bEQ } forall exch pop exch pop % bEQ exit } loop } bind def /IsWellComposed { % <CIDFontName> <CMapName> IsWellComposed <bool> % Check if the given CIDFont and CMap have compatible CSIs. exch % /CMapName /CIDFontName /CIDFont //GetCIDSystemInfo exec % /CMapName CSI-F dup type /dicttype eq { dup length 0 ne { exch % CSI-F /CMapName /CMap //GetCIDSystemInfo exec % CSI-F CSI-M //IsCompatibleCSI exec % bool } { pop pop //false } ifelse } { pop pop //false } ifelse } bind def /IsComposedFont { % <FontName> IsComposedFont <CIDFontName> <CMapName> true % <FontName> IsComposedFont false % Check if the given font name may be decomposed into CIDFont.CMap, CIDFont-CMap % or into CIDFont--CMap, such that CIDFont and CMap have compatible CSIs. % FontName dup type /stringtype ne { //name_buffer cvs } if % (FontName) { dup length 2 sub -1 1 { % (FontName) i 2 copy get dup //minus eq exch //period eq or { 2 copy 2 copy % (FontName) i (FontName) i (FontName) i 2 copy get //minus eq { 2 copy 1 sub get //minus eq { 1 sub } if } if % (FontName) i (FontName) i (FontName) i0 0 exch getinterval cvn % (FontName) i (FontName) i /CIDFontName 3 1 roll % (FontName) i /CIDFontName (FontName) i 1 add dup % (FontName) i /CIDFontName (FontName) i1 i1 5 index length % (FontName) i /CIDFontName (FontName) i1 i1 l exch sub getinterval cvn % (FontName) i /CIDFontName /CMapName 2 copy //IsWellComposed exec { % (FontName) i /CIDFontName /CMapName 4 2 roll pop pop % /CIDFontName /CMapName stop } if pop pop pop } { pop } ifelse % (FontName) } for pop } stopped } bind def /ComposeName { % <CIDFont> <CMap> <scr> ComposeName <CIDFont-CMap> dup dup 5 2 roll % (scr) (scr) /CIDFont /CMap (scr) 3 2 roll exch cvs length dup % (scr) (scr) /CMap l0 l0 4 -1 roll exch //minus put % (scr) /CMap l0 1 add dup % (scr) /CMap l1 l1 3 index dup length % (scr) /CMap l1 l1 (scr) L 2 index sub % (scr) /CMap l1 l1 (scr) LT 3 2 roll % (scr) /CMap l1 (scr) LT l1 exch getinterval % (scr) /CMap l1 (scrT) 3 2 roll exch cvs length % (scr) l1 l2 add 0 exch getinterval % (CIDFont-CMap) } bind def % Redefine the /Font category with CIDFont-CMap construction : % The following code supposes that the following names are not % defined in the old /Font category dictionary : % /IsComposedFont, /IsWellComposed . /Font /Category findresource dup length dict copy begin /FindResource { % <InstName> FindResource <inst> dup //ResourceStatus exec { pop pop //FindResource exec } { dup //IsComposedFont exec { % /FontName /CIDFontName /CMapName exch [ exch ] composefont % inst } { //FindResource exec } ifelse } ifelse } bind executeonly def /ResourceStatus { % <InstName> ResourceStatus <nStatus> <nSize> true % <InstName> ResourceStatus false dup //ResourceStatus exec { 3 2 roll pop //true % nStatus nSize true } { //IsComposedFont exec { % /CIDFontName /CMapName /CMap resourcestatus { % /CIDFontName nStatusM nSizeM exch pop exch % nSizeM /CIDFontName /CIDFont resourcestatus { % nSizeM nStatusF nSizeF exch pop % nSizeF nSizeM dup 0 ge { exch dup 0 ge { add } { exch pop } ifelse } { pop } ifelse % nSize 2 exch //true % nStatus nSize true } { pop pop pop //false % work around buggy resource file } ifelse } { pop pop pop //false % work around buggy resource file } ifelse } { //false } ifelse } ifelse } bind executeonly def /ResourceForAll { % <template> <proc> <scratch> ResourceForAll - % We suppose that the resourceforall procedure does not % define or install new fonts, CMaps, and/or CIDFonts. % First we create 3 temporary dictionaries to store temporary data % about fonts, CMaps and CIDFonts. % These dictionaries must be created dynamically, to allow for a possible % recursive call to resourceforall from the resourceforall procedure. currentglobal //false setglobal 20 dict 20 dict 20 dict % (templ) proc (scr) g <<CIDFont>> <<CMap>> <<Fonts>> % Store resource identifiers into local dictionaries % A resource instance can have a key that is not a name or a string. In this % case, resourceforall passes the key directly to proc instead of copying it % into the scratch string. This case can arise only for a resource instance % defined in virtual memory by a previous defineresource % Discard non-string keys of CIDFont and CMap because <CIDFontName>-<CMapName> % is only defined for names. { /.DisableResourceOrdering pop % gs_resmp accesses this through execstack - don't remove ! 6 index [ 2 index {exch //null put} aload pop ] cvx bind 6 index //ResourceForAll exec (*) [ 3 index {exch dup type /stringtype eq { cvn dup put } { pop pop } ifelse } aload pop ] cvx bind 6 index /CMap resourceforall (*) [ 4 index {exch dup type /stringtype eq { cvn dup put } { pop pop } ifelse } aload pop ] cvx bind 6 index /CIDFont resourceforall exit } loop % This loop is a pattern for execstack_lookup - don't remove ! 4 -1 roll setglobal % (templ) proc (scr) <<CIDFont>> <<CMap>> <<Fonts>> %% Make the list of fonts in the form (/Name status) : % (templ) proc (scr) <<CIDFont>> <<CMap>> <<Fonts>> dup { pop dup //ResourceStatus exec { pop 2 index % (templ) proc (scr) <<CIDFont>> <<CMap>> <<Fonts>> /Name nStatus <<Font>> 3 1 roll put % (templ) proc (scr) <<CIDFont>> <<CMap>> <<Fonts>> } { pop } ifelse } forall % (templ) proc (scr) <<CIDFont>> <<CMap>> <<Fonts>> %% Add CIDFont-CMap to it (filtering duplicates) : 3 2 roll { 3 index { 3 1 roll % (templ) proc (scr) <<CMap>> <<Font>> /CIDFont /CMap /CIDFont /CMap 6 index //ComposeName exec % (templ) proc (scr) <<CMap>> <<Font>> /CIDFont /CMap (Font) dup 8 index .stringmatch { cvn % (templ) proc (scr) <<CMap>> <<Font>> /CIDFont /CMap /Font dup 4 index exch known { pop pop } { 2 index % (templ) proc (scr) <<CMap>> <<Font>> /CIDFont /CMap /Font /CIDFont 4 2 roll % (templ) proc (scr) <<CMap>> <<Font>> /Font /CIDFont /CIDFont /CMap //IsWellComposed exec { exch 2 index exch 2 put % (templ) proc (scr) <<CMap>> <<Font>> /CIDFont } { exch pop } ifelse } ifelse } { pop pop } ifelse dup % (templ) proc (scr) <<CMap>> <<Font>> /CIDFont /CIDFont } forall pop pop % (templ) proc (scr) <<CMap>> <<Font>> } forall % (templ) proc (scr) <<CMap>> <<Font>> exch pop % (templ) proc (scr) <<Font>> 4 3 roll pop % proc (scr) <<Font>> % Make the enumerator and apply it : /MappedCategoryRedefiner /ProcSet findresource /MakeResourceEnumerator get exec exec } bind executeonly def currentdict end /Font exch /Category defineresource pop end setglobal .setlanguagelevel gs_res.ps 0000644 00000122732 15030647507 0006410 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % Initialization file for Level 2 resource machinery. % When this is run, systemdict is still writable, % but (almost) everything defined here goes into level2dict. level2dict begin (BEGIN RESOURCES) VMDEBUG % We keep track of (global) instances with another entry in the resource % dictionary, an .Instances dictionary. For categories with implicit % instances, the values in .Instances are the same as the keys; % for other categories, the values are [instance status size]. % Note that the dictionary that defines a resource category is stored % in global VM. The PostScript manual says that each category must % manage global and local instances separately. However, objects in % global VM other than systemdict can't reference objects in local VM. % This means that the resource category dictionary, which would otherwise be % the obvious place to keep track of the instances, can't be used to keep % track of local instances. Instead, we define a dictionary in local VM % called localinstancedict, in which the key is the category name and % the value is the analogue of .Instances for local instances. % We don't currently implement automatic resource unloading. % When and if we do, it should be hooked to the garbage collector. % However, Ed Taft of Adobe says their interpreters don't implement this % either, so we aren't going to worry about it for a while. currentglobal //false setglobal systemdict /localinstancedict 5 dict .forceput % localinstancedict is local, systemdict is global //true setglobal /.emptydict 0 dict readonly def setglobal % Resource category dictionaries have the following keys (those marked with % * are optional): % Standard, defined in the Red Book: % Category (name) % *InstanceType (name) % DefineResource % <key> <instance> DefineResource <instance> % UndefineResource % <key> UndefineResource - % FindResource % <key> FindResource <instance> % ResourceStatus % <key> ResourceStatus <status> <size> true % <key> ResourceStatus false % ResourceForAll % <template> <proc> <scratch> ResourceForAll - % *ResourceFileName % <key> <scratch> ResourceFileName <filename> % Additional, specific to our implementation: % .Instances (dictionary) % .LocalInstances % - .LocalInstances <dict> % .GetInstance % <key> .GetInstance <instance> -true- % <key> .GetInstance -false- % .CheckResource % <key> <value> .CheckResource <key> <value> <ok> % (or may give an error if not OK) % .DoLoadResource % <key> .DoLoadResource <key> (may give an error) % .LoadResource % <key> .LoadResource - (may give an error) % .ResourceFile % <key> .ResourceFile <file> -true- % <key> .ResourceFile <key> -false- % .ResourceFileStatus % <key> .ResourceFileStatus 2 <vmusage> -true- % <key> .ResourceFileStatus -false- % All the above procedures expect that the top dictionary on the d-stack % is the resource dictionary. % Define enough of the Category category so we can define other categories. % The dictionary we're about to create will become the Category % category definition dictionary. % .findcategory and .resourceexec are only called from within the % implementation of the resource 'operators', so they don't have to worry % about cleaning up the stack if they fail (the interpreter's stack % protection machinery for pseudo-operators takes care of this). % Note that all places that look up categories must use .findcategory % so that the command in case of error will be correct rather than an % internal invocation of findresource. /.findcategory { % <name> .findcategory - % (pushes the category on the dstack) /Category .findresource begin % note: *not* findresource } bind def % If an error occurs within the logic of a resource operator (after operand % acquisition and checking), the Adobe interpreters report the operator name, % not the operator object, as the command in $error. For this reason, and % this reason only, all resource operators must wrap their logic code in % /<opername> cvx { ...logic... } .errorexec % The Category resource signals /undefined rather than /undefinedresource, % both when referenced implicitly (to look up the category for a general % resource operation) and when it is accessed directly (/Category /xxx % findresource). Because of this, all resource operators must use % .undefinedresource rather than signalling undefinedresource directly. /.undefinedresource { % <command> .undefinedresource - /Category dup load eq { /undefined } { /undefinedresource } ifelse signaloperror } bind def /.resourceexec { % <key> /xxxResource .resourceexec - % (also pops the category from the dstack) load exec end } bind def % .getvminstance treats instances on disk as undefined. /.getvminstance { % <key> .getvminstance <instance> -true- % <key> .getvminstance -false- .GetInstance { dup 1 get 2 ne { //true } { pop //false } ifelse } { //false } ifelse } bind def 20 dict begin % Standard entries /Category /Category def /InstanceType /dicttype def /DefineResource { .CheckResource { dup /Category 3 index cvlit .growput dup [ exch 0 -1 ] exch .Instances 4 2 roll put % Make the Category dictionary read-only. We will have to % use .forceput / .forceput later to replace the dummy, % empty .Instances dictionary with the real one later. readonly }{ /defineresource cvx /typecheck signaloperror } ifelse } bind executeonly odef /FindResource % (redefined below) { .Instances exch get 0 get } bind executeonly def % Additional entries /.Instances 30 dict def .Instances /Category [currentdict 0 -1] put /.LocalInstances 0 dict def /.GetInstance { .Instances exch .knownget } bind def /.CheckResource { dup gcheck currentglobal and { /DefineResource /FindResource /ResourceForAll /ResourceStatus /UndefineResource } { 2 index exch known and } forall not { /defineresource cvx /invalidaccess signaloperror } if //true } bind def .Instances end begin % for the base case of findresource (END CATEGORY) VMDEBUG % Define the resource operators. We use the "stack protection" feature of % odef to make sure the stacks are restored properly on an error. % This requires that the operators not pop anything from the stack until % they have executed their logic successfully. We can't make this % work for resourceforall, because the procedure it executes mustn't see % the operands of resourceforall on the stack, but we can make it work for % the others. % findresource is the only operator that needs to bind //Category. % We define its contents as a separate procedure so that .findcategory % can use it without entering another level of pseudo-operator. /.findresource { % <key> <category> findresource <instance> 2 copy dup /Category eq { pop //Category 0 get begin } { //.findcategory exec } ifelse /FindResource //.resourceexec exec exch pop exch pop } bind end % .Instances of Category def /findresource { % See above re .errorexec. 1 .argindex % also catch stackunderflow dup type /stringtype eq { cvn } if % for CET 23-13-04 3 1 roll exch pop dup type /nametype ne { /findresource .systemvar /typecheck signalerror } if /findresource cvx //.findresource .errorexec } bind executeonly odef /defineresource { % <key> <instance> <category> defineresource <instance> 2 .argindex 2 index 2 index % catch stackunderflow % See above re .errorexec. /defineresource cvx { //.findcategory exec currentdict /InstanceType known { dup type InstanceType ne { dup type /packedarraytype eq InstanceType /arraytype eq and not { /defineresource cvx /typecheck signaloperror } if } if } if /DefineResource //.resourceexec exec 4 1 roll pop pop pop } .errorexec } bind executeonly odef % We must prevent resourceforall from automatically restoring the stacks, % because we don't want the stacks restored if proc causes an error or % executes a 'stop'. On the other hand, resourceforall is defined in the % PLRM as an operator, so it must have type /operatortype. We hack this % by taking advantage of the fact that the interpreter optimizes tail % calls, so stack protection doesn't apply to the very last token of an % operator procedure. /resourceforall1 { % <template> <proc> <scratch> <category> resourceforall1 - dup //.findcategory exec /ResourceForAll load % Stack: <template> <proc> <scratch> <category> proc exch pop % pop the category exec end } .bind executeonly def /resourceforall { % <template> <proc> <scratch> <category> resourceforall1 - //resourceforall1 exec % see above } .bind executeonly odef /resourcestatus { % <key> <category> resourcestatus <status> <size> true % <key> <category> resourcestatus false { 0 .argindex type /nametype ne { % CET 23-26 wants typecheck here, not undefineresource that happens % without the check. /resourcestatus cvx /typecheck signalerror } if 2 copy //.findcategory exec /ResourceStatus //.resourceexec exec { 4 2 roll pop pop //true } { pop pop //false } ifelse } stopped { % Although resourcestatus is an operator, Adobe uses executable name % for error reporting. CET 23-26 /resourcestatus cvx $error /errorname get signalerror } if } .bind executeonly odef /undefineresource { % <key> <category> undefineresource - 0 .argindex type /nametype ne { /undefinedresource cvx /typecheck signaloperror } if 1 .argindex 1 index % catch stackunderflow { //.findcategory exec /UndefineResource //.resourceexec exec pop pop } stopped { % Although undefineresource is an operator, Adobe uses executable name % here but uses operator for the errors above. CET 23-33 /undefineresource cvx $error /errorname get signalerror } if } .bind executeonly odef % Define the system parameters used for the Generic implementation of % ResourceFileName. systemdict begin % - .default_resource_dir <string> /.default_resource_dir { /LIBPATH .systemvar { dup .file_name_current eq { pop } { (Resource) rsearch { exch concatstrings exch pop .file_name_separator concatstrings exit } { pop } ifelse } ifelse } forall } bind def % <path> <name> <string> .resource_dir_name <path> <name> <string> /.resource_dir_name { systemdict 2 index .knownget { exch pop systemdict 1 index undef } { dup () ne { .file_name_directory_separator concatstrings } if 2 index exch //false .file_name_combine not { (Error: .default_resource_dir returned ) print exch print ( that can't combine with ) print = /.default_resource_dir cvx /configurationerror signalerror } if } ifelse } bind def currentdict /pssystemparams known not { /pssystemparams 10 dict readonly def } if pssystemparams begin //.default_resource_dir exec /FontResourceDir (Font) //.resource_dir_name exec readonly currentdict 3 1 roll .forceput % pssys'params is r-o /GenericResourceDir () //.resource_dir_name exec readonly currentdict 3 1 roll .forceput % pssys'params is r-o pop % .default_resource_dir /GenericResourcePathSep .file_name_separator readonly currentdict 3 1 roll .forceput % pssys'params is r-o currentdict (%diskFontResourceDir) cvn (/Resource/Font/) readonly .forceput % pssys'params is r-o currentdict (%diskGenericResourceDir) cvn (/Resource/) readonly .forceput % pssys'params is r-o end end % Check if GenericResourceDir presents in LIBPATH. % The value of GenericResourceDir must end with directory separator. % We use .file_name_combine to check it. % Comments use OpenVMS syntax, because it is the most complicated case. (x) pssystemparams /GenericResourcePathSep get (y) concatstrings concatstrings dup length % (x]y) l1 pssystemparams /GenericResourceDir get dup length exch % (x]y) l1 l2 (dir) 3 index //true .file_name_combine not { exch (File name ) print print ( cant combine with ) print = /GenericResourceDir cvx /configurationerror signaloperror } if dup length % (x]y) l1 l2 (dir.x]y) l 4 2 roll add % (x]y) (dir.x]y) l ll ne { (GenericResourceDir value does not end with directory separator.\n) = /GenericResourceDir cvx /configurationerror signaloperror } if pop pop pssystemparams dup /GenericResourceDir get exch /GenericResourcePathSep get (Init) exch (gs_init.ps) concatstrings concatstrings concatstrings status { pop pop pop pop } { (\n*** Warning: GenericResourceDir doesn't point to a valid resource directory.) = ( the -sGenericResourceDir=... option can be used to set this.\n) = flush } ifelse % Define the generic algorithm for computing resource file names. /.rfnstring 8192 string def /.genericrfn % <key> <scratch> <prefix> .genericrfn <filename> { 3 -1 roll //.rfnstring cvs concatstrings exch copy } bind def % Define the Generic category. /Generic mark % Standard entries % We're still running in Level 1 mode, so dictionaries won't expand. % Leave room for the /Category entry. /Category //null % Implement the body of Generic resourceforall for local, global, and % external cases. 'args' is [template proc scratch resdict]. /.enumerateresource { % <key> [- <proc> <scratch>] .enumerateresource - 1 index type dup /stringtype eq exch /nametype eq or { exch 1 index 2 get cvs exch } if % Use .setstackprotect to prevent the stacks from being restored if % an error occurs during execution of proc. 1 get //false .setstackprotect exec //true .setstackprotect } bind def /.localresourceforall { % <key> <value> <args> .localr'forall - exch pop 2 copy 0 get .stringmatch { //.enumerateresource exec } { pop pop } ifelse } bind def /.globalresourceforall { % <key> <value> <args> .globalr'forall - exch pop 2 copy 0 get .stringmatch { dup 3 get begin .LocalInstances end 2 index known not { //.enumerateresource exec } { pop pop } ifelse } { pop pop } ifelse } bind def /.externalresourceforall { % <filename> <len> <args> .externalr'forall - 3 1 roll 1 index length 1 index sub getinterval exch dup 3 get begin .Instances .LocalInstances end % Stack: key args insts localinsts 3 index known { pop pop pop } { 2 index known { pop pop } { //.enumerateresource exec } ifelse } ifelse } bind def /DefineResource dup { .CheckResource { dup [ exch 0 -1 ] % Stack: key value instance currentglobal { //false setglobal 2 index UndefineResource % remove local def if any //true setglobal .Instances dup //.emptydict eq { pop 3 dict % As noted above, Category dictionaries are read-only, % so we have to use .forceput here. currentdict /.Instances 2 index .forceput % Category dict is read-only } executeonly if } executeonly { .LocalInstances dup //.emptydict eq { pop 3 dict localinstancedict Category 2 index put } if } ifelse % Stack: key value instance instancedict 3 index 2 index .growput % Now make the resource value read-only. 0 2 copy get { readonly } //.internalstopped exec pop dup 4 1 roll put exch pop exch pop } executeonly { /defineresource cvx /typecheck signaloperror } ifelse } .bind executeonly .makeoperator % executeonly to prevent access to .forceput /UndefineResource { { dup 2 index .knownget { dup 1 get 1 ge { dup 0 //null put 1 2 put pop pop } { pop exch .undef } ifelse } { pop pop } ifelse } currentglobal { 2 copy .Instances exch exec } if .LocalInstances exch exec } .bind executeonly % Because of some badly designed code in Adobe's CID font downloader that % makes findresource and resourcestatus deliberately inconsistent with each % other, the default FindResource must not call ResourceStatus if there is % an instance of the desired name already defined in VM. /FindResource { dup //null eq { % CET 13-06 wants /typecheck for "null findencoding" but % .knownget doesn't fail on null /findresource cvx /typecheck signaloperror } if dup //.getvminstance exec { exch pop 0 get } { dup ResourceStatus { pop 1 gt { .DoLoadResource //.getvminstance exec not { /findresource cvx //.undefinedresource exec } if 0 get } { .GetInstance pop 0 get } ifelse } { /findresource cvx //.undefinedresource exec } ifelse } ifelse } .bind executeonly % Because of some badly designed code in Adobe's CID font downloader, the % definition of ResourceStatus for Generic and Font must be the same (!). % We patch around this by using an intermediate .ResourceFileStatus procedure. /ResourceStatus { dup .GetInstance { exch pop dup 1 get exch 2 get //true } { .ResourceFileStatus } ifelse } .bind executeonly /.ResourceFileStatus { .ResourceFile { closefile 2 -1 //true } { pop //false } ifelse } bind executeonly /ResourceForAll { % Construct a new procedure to hold the arguments. % All objects constructed here must be in local VM to avoid % a possible invalidaccess. currentdict 4 .localvmpackedarray % [template proc scratch resdict] % We must pop the resource dictionary off the dict stack % when doing the actual iteration, and restore it afterwards. .currentglobal not { .LocalInstances length 0 ne { % We must do local instances, and do them first. //.localresourceforall {exec} 0 get 3 .localvmpackedarray cvx .LocalInstances exch {forall} 0 get 1 index 0 get currentdict end 3 .execn begin } if } if % Do global instances next. //.globalresourceforall {exec} 0 get 3 .localvmpackedarray cvx .Instances exch cvx {forall} 0 get 1 index 0 get currentdict end 3 .execn begin mark % args [ Category .namestring .file_name_separator concatstrings 2 index 0 get % args [ (c/) (t) 1 index length 3 1 roll % args [ l (c/) (t) concatstrings % args [ l (c/t) [ //true /LIBPATH .systemvar 3 index .generate_dir_list_templates_with_length % args (t) [ l [(pt) Lp ...] % also add on the Resources as specified by the GenericResourceDir //true [ currentsystemparams /GenericResourceDir get] counttomark 1 add index .generate_dir_list_templates_with_length ] exch pop dup length 1 sub 0 exch 2 exch { % args [ l [] i 2 copy get % args [ l [] i (pt) exch 2 index exch 1 add get % args [ l [] (pt) Lp 3 index add exch % args [ l [] Lp (pt) { % args [ l [] Lp (pf) dup length % args [ l [] Lp (pf) Lpf 2 index sub % args [ l [] Lp (pf) Lf 2 index exch % args [ l [] Lp (pf) Lp Lf getinterval cvn dup % args [ l [] Lp /n /n 5 2 roll % args [ /n /n l [] Lp } //.rfnstring filenameforall pop % args [ /n1 /n1 ... /nN /nN l [] } for % args [ /n1 /n1 ... /nN /nN l [] pop pop .dicttomark % An easy way to exclude duplicates. % args <</n/n>> % { { pop } 0 get 2 index 2 get { cvs 0 } aload pop 5 index //.externalresourceforall {exec} 0 get % } 7 .localvmpackedarray cvx 3 2 roll pop % args { forall } 0 get currentdict end 2 .execn begin } .bind executeonly /ResourceFileName { % /in (scr) --> (p/c/n) exch //.rfnstring cvs % (scr) (n) /GenericResourcePathSep getsystemparam exch % (scr) (/) (n) Category .namestring % (scr) (/) (n) (c) 3 1 roll % (scr) (c) (/) (n) concatstrings concatstrings % (scr) (c/n) /GenericResourceDir getsystemparam 1 index % (scr) (c/n) (p/) (c/n) concatstrings % (scr) (c/n) (p/c/n) dup status { pop pop pop pop exch pop % (scr) (p/c/n) } { exch .libfile {//true} { pop dup .libfile {//true} {//false} ifelse } ifelse { dup .filename pop exch closefile exch pop } {pop} ifelse } ifelse exch copy % (p/c/n) } .bind executeonly % Additional entries % Unfortunately, we can't create the real .Instances dictionary now, % because if someone copies the Generic category (which pp. 95-96 of the % 2nd Edition Red Book says is legitimate), they'll wind up sharing % the .Instances. Instead, we have to create .Instances on demand, % just like the entry in localinstancedict. % We also have to prevent anyone from creating instances of Generic itself. /.Instances //.emptydict /.LocalInstances { localinstancedict Category .knownget not { //.emptydict } if } bind /.GetInstance { currentglobal { .Instances exch .knownget } { .LocalInstances 1 index .knownget { exch pop //true } { .Instances exch .knownget } ifelse } ifelse } bind /.CheckResource { //true } bind /.vmused { % - .vmused <usedvalue> % usedvalue = vmstatus in global + vmstatus in local. 0 2 { .currentglobal not .setglobal vmstatus pop exch pop add } repeat } bind executeonly odef /.DoLoadResource { % .LoadResource may push entries on the operand stack. % It is an undocumented feature of Adobe implementations, % which we must match for the sake of some badly written % font downloading code, that such entries are popped % automatically. count 1 index cvlit //.vmused % Stack: key count litkey memused {.LoadResource} 4 1 roll 4 .execn % Stack: ... count key memused //.vmused exch sub 1 index //.getvminstance exec not { pop dup //.undefinedresource exec % didn't load } if dup 1 1 put 2 3 -1 roll put % Stack: ... count key exch count 1 sub exch sub {exch pop} repeat } bind /.LoadResource { dup .ResourceFile { exch pop currentglobal { //.runresource exec } { //true setglobal { //.runresource exec } stopped //false setglobal { stop } if } ifelse } { dup //.undefinedresource exec } ifelse } bind /.ResourceFile { Category //.rfnstring cvs length % key l dup //.rfnstring dup length 2 index sub % key l l (buf) L-l 3 2 roll exch getinterval % key l () .file_name_directory_separator exch copy length add % key l1 dup //.rfnstring dup length 2 index sub % key l1 l1 (buf) L-l 3 2 roll exch getinterval % key l1 () 2 index exch cvs length add % key l2 //.rfnstring exch 0 exch getinterval % key (relative_path) .libfile { exch pop //true } { pop currentdict /ResourceFileName known { mark 1 index //.rfnstring { ResourceFileName } //.internalstopped exec { cleartomark //false } { (r) { file } //.internalstopped exec { cleartomark //false } { exch pop exch pop //true } ifelse } ifelse } { pop //false } ifelse } ifelse } bind .dicttomark /Category defineresource pop % Fill in the rest of the Category category. /Category /Category findresource dup /Generic /Category findresource begin { /FindResource /ResourceForAll /ResourceStatus /.ResourceFileStatus /UndefineResource /ResourceFileName /.ResourceFile /.LoadResource /.DoLoadResource } { dup load put dup } forall pop readonly pop end (END GENERIC) VMDEBUG % Define the fixed categories. mark % Non-Type categories with existing entries. /ColorSpaceFamily { } % These must be deferred, because optional features may add some. /Emulator mark EMULATORS { <00> search { exch pop cvn exch }{ cvn exit } ifelse } .bind loop //.packtomark exec /Filter { } % These must be deferred, because optional features may add some. /IODevice % Loop until the .getiodevice gets a rangecheck. errordict /rangecheck 2 copy get errordict /rangecheck { pop stop } put % pop the command mark 0 { { dup .getiodevice dup //null eq { pop } { exch } ifelse 1 add } loop} //.internalstopped exec pop pop pop //.packtomark exec 4 1 roll put //.clearerror exec % Type categories listed in the Red Book. /ColorRenderingType { } % These must be deferred, because optional features may add some. /FMapType { } % These must be deferred, because optional features may add some. /FontType { } % These must be deferred, because optional features may add some. /FormType { } % These must be deferred, because optional features may add some. /HalftoneType { } % These must be deferred, because optional features may add some. /ImageType { } % Deferred, optional features may add some. /PatternType { } % Deferred, optional features may add some. % Type categories added since the Red Book. /setsmoothness where { pop /ShadingType { } % Deferred, optional features may add some. } if counttomark 2 idiv { mark % Standard entries % We'd like to prohibit defineresource, % but because optional features may add entries, we can't. % We can at least require that the key and value match. /DefineResource { currentglobal not { /defineresource cvx /invalidaccess signaloperror } { 2 copy ne { /defineresource cvx /rangecheck signaloperror } { dup .Instances 4 -2 roll .growput } ifelse } ifelse } bind executeonly /UndefineResource { /undefineresource cvx /invalidaccess signaloperror } bind executeonly /FindResource { .Instances 1 index .knownget { exch pop } { /findresource cvx //.undefinedresource exec } ifelse } bind executeonly /ResourceStatus { .Instances exch known { 0 0 //true } { //false } ifelse } bind executeonly /ResourceForAll /Generic //.findcategory exec /ResourceForAll load end % Additional entries counttomark 2 add -1 roll dup length dict dup begin exch { dup def } forall end % We'd like to make the .Instances readonly here, % but because optional features may add entries, we can't. /.Instances exch /.LocalInstances % used by ResourceForAll 0 dict def .dicttomark /Category defineresource pop } repeat pop (END FIXED) VMDEBUG % Define the other built-in categories. /.definecategory % <name> -mark- <key1> ... <valuen> .definecategory - { counttomark 2 idiv 2 add % .Instances, Category /Generic /Category findresource dup maxlength 3 -1 roll add dict .copydict begin counttomark 2 idiv { def } repeat pop % pop the mark currentdict end /Category defineresource pop } bind def /ColorRendering mark /InstanceType /dicttype .definecategory % ColorSpace is defined below % Encoding is defined below % Font is defined below /Form mark /InstanceType /dicttype .definecategory /Halftone mark /InstanceType /dicttype .definecategory /Pattern mark /InstanceType /dicttype .definecategory /ProcSet mark /InstanceType /dicttype .definecategory % Added since the Red Book: /ControlLanguage mark /InstanceType /dicttype .definecategory /HWOptions mark /InstanceType /dicttype .definecategory /Localization mark /InstanceType /dicttype .definecategory /PDL mark /InstanceType /dicttype .definecategory % CIDFont, CIDMap, and CMap are defined in gs_cidfn.ps % FontSet is defined in gs_cff.ps % IdiomSet is defined in gs_ll3.ps % InkParams and TrapParams are defined in gs_trap.ps (END MISC) VMDEBUG % Define the OutputDevice category. /OutputDevice mark /InstanceType /dicttype /.Instances mark %% devicedict is not created yet so here we employ a technique similar to %% that used to create it, in order to get the device names. We run a loop %% executing .getdevice with incremental numbers until we get an error. %% The devicedict creation only stops on a rangecheck, we stop on any error. %% We need to use .internalstopped, not stopped or we get an invalidacces %% later in this file. Instances of /OutputDevice are dictionaries, and the %% only required key is a /PageSize. The array of 4 numbers are minimum to %% maximum and are matches for the Adobe Acrobat Distiller values. 0 { {dup .getdevice .devicename cvn 1 dict dup /PageSize [1 1 14400 14400] put [exch readonly 0 -1] 3 -1 roll 1 add} loop } //.internalstopped exec pop %% Remove the count, and the duplicate, from the stack pop pop .dicttomark .definecategory % Define the ColorSpace category. /.defaultcsnames mark /DefaultGray 0 /DefaultRGB 1 /DefaultCMYK 2 .dicttomark readonly def % The "hooks" are no-ops here, redefined in LL3. /.definedefaultcs { % <index> <value> .definedefaultcs - pop pop } bind def /.undefinedefaultcs { % <index> .undefinedefaultcs - pop } bind def /ColorSpace mark /InstanceType /arraytype % We keep track of whether there are any local definitions for any of % the Default keys. This information must get saved and restored in % parallel with the local instance dictionary, so it must be stored in % local VM. userdict /.localcsdefaults //false put /DefineResource { 2 copy /Generic /Category findresource /DefineResource get exec exch pop exch //.defaultcsnames exch .knownget { 1 index //.definedefaultcs exec currentglobal not { .userdict /.localcsdefaults //true put } if } if } bind executeonly /UndefineResource { dup /Generic /Category findresource /UndefineResource get exec //.defaultcsnames 1 index .knownget { % Stack: resname index currentglobal { //.undefinedefaultcs exec pop } { % We removed the local definition, but there might be a global one. exch .GetInstance { 0 get //.definedefaultcs exec } { //.undefinedefaultcs exec } ifelse % Recompute .localcsdefaults by scanning. This is rarely needed. .userdict /.localcsdefaults //false //.defaultcsnames { pop .LocalInstances exch known { pop //true exit } if } forall put } ifelse } { pop } ifelse } bind executeonly .definecategory % ColorSpace % Define the Encoding category. /Encoding mark /InstanceType /arraytype % Handle already-registered encodings, including lazily loaded encodings % that aren't loaded yet. /.Instances mark EncodingDirectory { dup length 256 eq { [ exch readonly 0 -1 ] } { pop [//null 2 -1] } ifelse } forall .dicttomark /.ResourceFileDict mark EncodingDirectory { dup length 256 eq { pop pop } { 0 get } ifelse } forall .dicttomark /ResourceFileName { .ResourceFileDict 2 index .knownget { exch copy exch pop } { /Generic /Category findresource /ResourceFileName get exec } ifelse } bind executeonly .definecategory % Encoding % Make placeholders in level2dict for the redefined Encoding operators, % so that they will be swapped properly when we switch language levels. /.findencoding /.findencoding load def /findencoding /findencoding load def /.defineencoding /.defineencoding load def (END ENCODING) VMDEBUG % Define the Font category. /.fontstatusaux { % <fontname> .fontstatusaux <fontname> <found> { % Create a loop context just so we can exit it early. % Check Fontmap. Fontmap 1 index .knownget { //true } { .nativeFontmap 1 index .knownget } ifelse { { dup type /nametype eq { .fontstatus { pop //null exit } if } { dup type /dicttype eq {/Path .knownget pop} if dup type /stringtype eq { findlibfile { closefile pop //null exit } if pop } { % Procedure, assume success. pop //null exit } ifelse } ifelse } forall dup //null eq { pop //true exit } if } if dup / eq { //false exit } if % / throws an error from findlibfile % Convert names to strings; give up on other types. dup type /nametype eq { .namestring } if dup type /stringtype ne { //false exit } if % Check the resource directory. dup //.fonttempstring /FontResourceDir getsystemparam .genericrfn status { pop pop pop pop //true exit } if % Check for a file on the search path with the same name % as the font. findlibfile { closefile //true exit } if % Scan a FONTPATH directory and try again. //.scannextfontdir exec not { //false exit } if } loop } bind def /.fontstatus { % <fontname> .fontstatus <fontname> <found> //.fontstatusaux exec { //true } { .buildnativefontmap { //.fontstatusaux exec } { //false } ifelse } ifelse } bind executeonly def currentdict /.fontstatusaux .undef /Font mark /InstanceType /dicttype /DefineResource { 2 copy //definefont exch pop /Generic /Category findresource /DefineResource get exec } bind executeonly /UndefineResource { dup //undefinefont /Generic /Category findresource /UndefineResource get exec } bind executeonly /FindResource { dup //.getvminstance exec { exch pop 0 get } { dup ResourceStatus { pop 1 gt { .loadfontresource } { .GetInstance pop 0 get } ifelse } { .loadfontresource } ifelse } ifelse } bind executeonly /ResourceForAll { { //.scannextfontdir exec not { exit } if } loop /Generic /Category findresource /ResourceForAll get exec } .bind executeonly /.ResourceFileStatus { .fontstatus { pop 2 -1 //true } { pop //false } ifelse } bind executeonly /.loadfontresource { dup //.vmused exch % Hack: rebind .currentresourcefile so that all calls of % definefont will know these are built-in fonts. currentfile {pop //findfont exec} .execasresource % (findfont is a procedure) exch //.vmused exch sub % stack: name font vmused % findfont has the prerogative of not calling definefont % in certain obscure cases of font substitution. 2 index //.getvminstance exec { dup 1 1 put 2 3 -1 roll put } { pop } ifelse exch pop } bind /.Instances FontDirectory length 2 mul dict .definecategory % Font % Redefine font "operators". /.definefontmap { /Font /Category findresource /.Instances get dup 3 index known { pop } { 2 index % Make sure we create the array in global VM. .currentglobal //true .setglobal [//null 2 -1] exch .setglobal .growput } ifelse //.definefontmap exec } bind def % Make sure the old definitions are still in systemdict so that % they will get bound properly. % NOTE: Mystery code... I can't just delete this, but don't understand why. % Instead we will undef these three operators in gs_init.ps after all the initialization is done. systemdict begin /.origdefinefont /definefont load def /.origundefinefont /undefinefont load def /.origfindfont /findfont load def end /definefont { { /Font defineresource } stopped { /definefont cvx $error /errorname get signalerror } if } bind executeonly odef /undefinefont { /Font undefineresource } bind executeonly odef % The Red Book requires that findfont be a procedure, not an operator, % but it still needs to restore the stacks reliably if it fails. /.findfontop { { /Font findresource } stopped { pop /findfont cvx $error /errorname get signalerror } if } bind executeonly odef /findfont { .findfontop } bind executeonly def % Must be a procedure, not an operator % Remove initialization utilities. currentdict /.definecategory .undef currentdict /.emptydict .undef end % level2dict % Convert deferred resources after we finally switch to Level 2. /.fixresources { % Encoding resources EncodingDirectory { dup length 256 eq { /Encoding defineresource pop } { pop pop } ifelse } forall /.findencoding { { /Encoding findresource } stopped { pop /findencoding cvx $error /errorname get signalerror } if } bind def /findencoding /.findencoding load def % must be a procedure /.defineencoding { /Encoding defineresource pop } bind def % ColorRendering resources and ProcSet systemdict /ColorRendering .knownget { /ColorRendering exch /ProcSet defineresource pop systemdict /ColorRendering undef /DefaultColorRendering currentcolorrendering /ColorRendering defineresource pop } if % ColorSpace resources systemdict /CIEsRGB .knownget { /sRGB exch /ColorSpace defineresource pop systemdict /CIEsRGB undef } if systemdict /CIEsRGBICC .knownget { /sRGBICC exch /ColorSpace defineresource pop systemdict /CIEsRGBICC undef } if systemdict /CIEsGRAYICC .knownget { /sGrayICC exch /ColorSpace defineresource pop systemdict /CIEsGRAYICC undef } if systemdict /CIEesRGBICC .knownget { /esRGBICC exch /ColorSpace defineresource pop systemdict /CIEesRGBICC undef } if systemdict /CIErommRGBICC .knownget { /rommRGBICC exch /ColorSpace defineresource pop systemdict /CIErommRGBICC undef } if % ColorSpaceFamily resources colorspacedict { pop dup /ColorSpaceFamily defineresource pop } forall % Filter resources filterdict { pop dup /Filter defineresource pop } forall % FontType and FMapType resources buildfontdict { pop dup /FontType defineresource pop } forall mark buildfontdict 0 known { 2 3 4 5 6 7 8 } if buildfontdict 9 known { 9 } if counttomark { dup /FMapType defineresource pop } repeat pop % FormType resources .formtypes { pop dup /FormType defineresource pop } forall % HalftoneType resources .halftonetypes { pop dup /HalftoneType defineresource pop } forall % ColorRenderingType resources .colorrenderingtypes {pop dup /ColorRenderingType defineresource pop} forall % ImageType resources .imagetypes { pop dup /ImageType defineresource pop } forall % PatternType resources .patterntypes { pop dup /PatternType defineresource pop } forall % Make the fixed resource categories immutable. /.shadingtypes where { pop .shadingtypes { pop dup /ShadingType defineresource pop } forall } if [ /ColorSpaceFamily /Emulator /Filter /IODevice /ColorRenderingType /FMapType /FontType /FormType /HalftoneType /ImageType /PatternType /.shadingtypes where { pop /ShadingType } if ] { /Category findresource dup /.Instances get readonly pop .LocalInstances readonly pop readonly pop } forall % clean up systemdict /.fixresources undef } bind def %% Replace 1 (gs_resmp.ps) (gs_resmp.ps) dup runlibfile VMDEBUG [ /.default_resource_dir /.resource_dir_name /.fonttempstring /.scannextfontdir % from gs_fonts.ps ] systemdict .undefinternalnames [ /.definedefaultcs /.undefinedefaultcs /.defaultcsnames /.enumerateresource /.externalresourceforall /.getvminstance /.globalresourceforall /.localresourceforall /resourceforall1 /.resourceexec /.undefinedresource /.vmused ] dup level2dict .undefinternalnames systemdict .undefinternalnames FCOfontmap-PCLPS2 0000644 00000005451 15030647507 0007440 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % May add general FAPIfontmap records here like this : /Wingdings-Regular << /Path FCOfontfile2 /FontType 1 /FAPI /UFST /SubfontId 0 /Encoding /Wingdings /Decoding /FCO_Wingdings>> ; % Mapping Postscript fonts to pclp2_xj.fco FCO members : FCOfontfile ReadFCOfontmap: 0 Albertus-Medium 1 Albertus-ExtraBold 2 AntiqueOlive 3 AntiqueOlive-Italic 4 AntiqueOlive-Bold 5 Arial 6 Arial-Italic 7 Arial-Bold 8 Arial-BoldItalic 9 Clarendon-Condensed-Bold 10 Coronet 11 CourierHP 12 CourierHP-Italic 13 CourierHP-Bold 14 CourierHP-BoldItalic 15 Garamond-Antiqua 16 Garamond-Kursiv 17 Garamond-Halbfett 18 Garamond-KursivHalbfett 19 LetterGothic 20 LetterGothic-Italic 21 LetterGothic-Bold 22 Marigold 23 CGOmega 24 CGOmega-Italic 25 CGOmega-Bold 26 CGOmega-BoldItalic 27 SymbolMT SymbolEncoding FCO_Symbol 28 CGTimes 29 CGTimes-Italic 30 CGTimes-Bold 31 CGTimes-BoldItalic 32 TimesNewRoman 33 TimesNewRoman-Italic 34 TimesNewRoman-Bold 35 TimesNewRoman-BoldItalic 36 UniversMedium 37 UniversMedium-Italic 38 Univers-Bold 39 Univers-BoldItalic 40 Univers-Condensed-Medium 41 Univers-Condensed-MediumItalic 42 Univers-Condensed-Bold 43 Univers-Condensed-BoldItalic 44 Courier- 45 Courier-Italic 46 Courier-Bold- 47 Courier-BoldItalic 48 AvantGarde-Book 49 AvantGarde-BookOblique 50 AvantGarde-Demi 51 AvantGarde-DemiOblique 52 Bookman-Light 53 Bookman-LightItalic 54 Bookman-Demi 55 Bookman-DemiItalic 56 Courier 57 Courier-Oblique 58 Courier-Bold 59 Courier-BoldOblique 60 Helvetica 61 Helvetica-Oblique 62 Helvetica-Bold 63 Helvetica-BoldOblique 64 Helvetica-Narrow 65 Helvetica-Narrow-Oblique 66 Helvetica-Narrow-Bold 67 Helvetica-Narrow-BoldOblique 68 NewCenturySchlbk-Roman 69 NewCenturySchlbk-Italic 70 NewCenturySchlbk-Bold 71 NewCenturySchlbk-BoldItalic 72 Palatino-Roman 73 Palatino-Italic 74 Palatino-Bold 75 Palatino-BoldItalic 76 Symbol SymbolEncoding FCO_Symbol 77 Times-Roman 78 Times-Italic 79 Times-Bold 80 Times-BoldItalic 81 ZapfChancery-MediumItalic 82 ZapfDingbats DingbatsEncoding FCO_Dingbats EndFCOfontmap %EOF gs_cet.ps 0000644 00000011544 15030647507 0006370 0 ustar 00 % Set defaults for Ghostscript to match Adobe CPSI behaviour for CET % skip if we've already run this -- based on fake "product" systemdict /product get (PhotoPRINT SE 5.0v2) readonly eq { (%END GS_CET) .skipeof } if % Note: this must be run at save level 0 and when systemdict is writeable currentglobal //true setglobal systemdict dup dup dup /version (3017.102) readonly .forceput % match CPSI 3017.102 /product (PhotoPRINT SE 5.0v2) readonly .forceput % match CPSI 3017.102 /revision 0 put % match CPSI 3017.103 Tek shows revision 5 /serialnumber dup {233640} readonly .makeoperator .forceput % match CPSI 3017.102 Tek shows serialnumber 1401788461 systemdict /.odef { % <name> <proc> odef - 1 index exch //.makeoperator def } .bind .forceput % this will be undefined at the end 300 .sethiresscreen % needed for language switch build since it % processes gs_init.ps BEFORE setting the resolution 0 array 0 setdash % CET 09-08 wants local setdash /UNROLLFORMS //true def (%.defaultbgrucrproc) cvn { } bind def (%.defaultbgrucrproc) cvn load dup setblackgeneration setundercolorremoval 0 array cvx readonly dup dup dup setcolortransfer % CPSI doesn't define "Localization" resource. /Localization /Category undefineresource % Quality Logic test 09-59.ps tries to set each listed /OutputDevice. % This can cause problems with some devices (eg mswinpr2 on Windows) % so for the CET files we define the OutputDevice resource as % being empty. We need to redefine /.definecategory as that definition % gets destroyed at the end of gs_res.ps /OutputDevice /Category undefineresource /.definecategory % <name> -mark- <key1> ... <valuen> .definecategory - { counttomark 2 idiv 2 add % .Instances, Category /Generic /Category findresource dup maxlength 3 -1 roll add dict .copydict begin counttomark 2 idiv { def } repeat pop % pop the mark currentdict end /Category defineresource pop } bind def /OutputDevice mark /InstanceType /dicttype .definecategory % Redefine Font category to return -1 (unknown) VM usage % in all cases to avoid differences between hosts. /Font /Category findresource dup length dict copy dup dup /.loadfontresource get dup length array copy cvx dup 1 0 put dup 7 -1 put /.loadfontresource exch put /Font exch /Category defineresource pop % Some previously compile time options such as USE_ADOBE_CMYK_RGB % and GS_CHAR_FILL are now dynamic. Force CPSI compatibility. //true .setCPSImode % Some QL jobs (/23-12B.PS for example) do: % '(%stdin) (r) file' % expecting that they are being read from stdin. % if that is not the case, they block waiting for input % from stdin. % This hooks the 'file' operator', so if a job tries to % open %stdin, and we're *not* reading the job from stdin % it'll return currentfile instead. /ofile /file load def /file { 1 index (%stdin) eq 2 index (%stdin%) eq or { ofile dup currentfile eq not { pop currentfile }if } { ofile } ifelse } .bind //.odef exec currentdict /ofile undef % One QL job (23-12B.PS) effectively does: % (%stdin) (r) file 0 setfileposition % expecting it to throw an ioerror (stdin not being a positionable % stream. % With the above 'file' hook, when running from a file % rather than stdin, setfileposition will succeed, and we hit % an infinite loop - '0 setfileposition' meaning we restart intepreting % from the beginning of the file. % Hook setfileposition to throw an error attempting to reposition % the current file. /osetfileposition /setfileposition load def /setfileposition { 1 index currentfile eq { /setfileposition cvx /ioerror signalerror } { osetfileposition } ifelse } .bind //.odef exec currentdict /osetfileposition undef setglobal % Remove all but the default page size (the 0 entry in the InputAttributes % dictionary). This is usually 'letter'. << % As we're removing all but the default, make sure we're % using the default. /PageSize currentpagedevice /InputAttributes get 0 get /PageSize get currentpagedevice /InputAttributes get 1 1 2 index length 1 sub { 1 index exch undef } for /InputAttributes exch >> setpagedevice % Patch setsmoothness, currentsmoothness for a better view of shadings : userdict /.smoothness currentsmoothness put /setsmoothness { dup type dup /integertype eq exch /realtype eq or { userdict /.smoothness 3 2 roll cvr put } { /setsmoothness .systemvar /typecheck signalerror } ifelse } bind //.odef exec /currentsmoothness { userdict /.smoothness get } bind //.odef exec % for 09-55.PS, 09-57.PS . % slightly nasty hack to give consistent cluster results /ofnfa systemdict /filenameforall get def /filenameforall { 2 index dup length 1 eq { (*) eq { 3 -1 roll pop ( ) 3 1 roll } if } { pop } ifelse ofnfa } bind def systemdict /.odef .undef % end of slightly nasty hack to give consistent cluster results %END GS_CET gs_img.ps 0000644 00000056676 15030647507 0006410 0 ustar 00 % Copyright (C) 2002-2021 Artifex, Inc. 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., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861. % image, colorimage, and imagemask implementation % % The design of the overprint facility in Ghostscript requires that color % specifications include the color space from which they were expressed, % even after conversion to the device color model. Directly including this % information in color specifications is usually not efficient, and is % difficult to integrate into the existing code structure. The alternative % approach taken is to extend a state mechanism through the device % interface, and make the current color space, or more specifically, % certain information about the current color space, a property of this % state. % % For such a mechanism to work, it is necessary to identify all changes % to the current color space. This is accomplished in the graphic library % by funneling all changes to the current color space through the % gs_setcolorspace procedure. At the PostScript interpreter level, this % result is achieved by forcing color space changes through the % setcolorspace operator. % % Aside from explicit use of setcolorspace, PostScript provides a few % implicit methods of changing the current color space. The setgray, % setrgbcolor, and setcmykcolor operators implicitly set the color space % while explicitly setting the current color. Similarly, the colorimage % operator and the traditional form of the image operator (5 operands) % both temporarily modify the current color space while an image is % being processed. The current file is concerned with the implementation % of these two operators. In addition, the traditional form of the % imagemask operator (5 operands), while it does not affect the current % color space, is closely related to the image operator and thus is % implemented in this file as well. % % In this implementation, all sampled objects are passed through one of % the internal operators .image1, .imagemask1, .image2, % .image3, or .image4, each of which handles a specific ImageType value. % % The procedures in this file are responsible for constructing % image dictionaries from a set of stack entries. This is, in principle, % a trivial exercise. In practice it appears to be far more complex, % primarily due to the need to reconstruct the original state in the % event of an error. This is a particular problem for operators such as % image, which include data source objects that may, directly or % indirectly, be procedures. When these procedures are executed, the % image operator's operands must have been cleared from the operand % stack. Hence, the operand stack cannot be used to store state % information. Similarly, the dictionary stack also cannot be used to % store state information, as the data source procedures may depend on % a particular dictionary being on the top of this stack. % % Adobe's PostScript implementations determine the extent to which the % interpreter state is restored in the event of an error by the point at % which the error is detected. Errors in the image/colorimage/imagemask % operators that are detected before the data source procedures are % executed restore the state in effect before the image was processed. % Those that are detected as part of running the data source procedures % only attempt to restore the state to that in effect at the start of % the operator that failed (or at the conclusion of the data source % procedure, if this procedure failed to push a string). % % The implementation given here follows the Adobe convention. The % mechanism used is as follows: % % 1. Check that the stack has a sufficient number of operands, and % that enough of them have the proper type to allow construction % of the image dictionary. Any errors at this point are handled % in the conventional manner. % % 2. Build the image dictionary, in the process clearing the image/ % colorimage/imagemask operands from the stack. No errors can % occur during this process. % % (Special precautions could be taken during this step to handle % a limitcheck or VMError during the building of the image % dictionary, but this essentially never occurs in practice and, if % it did, is very unlikely to leave a useable state. Hence, we don't % bother with this possibility.) % % 3. The .image operator is executed in a stopped context. If it % returns abnormally, a check is made to see if the uppermost % operand on the stack is a color image dictionary. If so, the % original stack is created anew using this dictionary. (Because % the image operand works via colorimage, some additional special % handling is required in this case.) % % % Create a dictionary of operators for specific image and image mask types. % Each of these will always handle ImageType 1. Additional types are added % as they are supported in specific interpreter levels or versions. % % These dictionaries are in systemdict for historical reasons. % .currentglobal //true .setglobal systemdict begin /.imagetypes 5 dict dup 1 /.image1 load put def /.imagemasktypes 5 dict dup 1 /.imagemask1 load put def % % Some useful local data structures: % % img_csary maps the number of components in an image to the implied % color space. % % img_decary is a prototype Decode array; subintervals of this array % may be used for fewer than 4 color components. % % img_params_ary is a list of the parameters to be built in the image % dictionary for a colorimage invocation. ImageType is given a % fixed value; the other parameters are in stack order (IMG_NComps % is the number of components). % % img_mask_params_ary is the equivalent of img_params_ary for imagemask % invocations. Polarity is a proxy for Decode, and is replaced % by the Decode key in the image dictionary. % % img_mask_check_ary is the set of parameters that must be present in % an image dictionary generated by an imagemask invocation. This % differs from img_mask_params_ary in that Decode replaces Polarity. % /img_csary [ //null /DeviceGray //null /DeviceRGB /DeviceCMYK ] def /img_decary [ 0 1 0 1 0 1 0 1 ] def /img_params_ary [ /ImageType /IMG_NComps /MultipleDataSources /DataSource /ImageMatrix /BitsPerComponent /Height /Width /Decode ] def /img_check_ary //img_params_ary def /img_unbuild_ary //img_params_ary 1 1 index length 2 sub getinterval def /img_mask_params_ary [ /ImageType /DataSource /ImageMatrix /Polarity /Height /Width ] def /img_mask_check_ary [ /ImageType /BitsPerComponent /DataSource /ImageMatrix /Decode /Height /Width ] def /img_mask_unbuild_ary //img_mask_check_ary 2 1 index length 2 sub getinterval def % % <?any?> <array> img_check_keys <?any?> <bool> % % Verify that: % that there are at least two entries on the stack, and % the second (lower) entry is a dictionary, and % that dictionary contains all of the keys in the array % % If any one of these conditions does not hold, pop the array and push % false; otherwise pop the array and push true. This utility is used by % the colorimage and imagematrix procedures to determine if .image left % the image dictionary on the stack after an abnormal return. % /img_check_keys { count 2 ge { 1 index type /dicttype eq { //true exch { 2 index exch known and dup not { exit } if } forall } { pop //false } ifelse } { pop //false } ifelse } .bind def % % Procedures to convert a set of stack entries to a dictionary. There is % a procedure associated with each key, though most keys use the same % procedure. The dictionary to be built is at the top of the dictionary % stack. Stack handling for the procedures is: % % <?val0?> ... <?val(n - 1)?> <key> proc - % % Parameters are handle in inverse-stack order, so inter-parameter % dependencies that on the stack can generally be used here. % /img_params_dict mark /ImageType { 1 def } .bind /IMG_NComps { exch def } .bind % number of components /MultipleDataSources 1 index /Width 1 index /Height 1 index /ImageMatrix 1 index /BitsPerComponent 1 index /DataSource 1 index % Polarity is a proxy for Decode; it never appears in a dictionary /Polarity { pop { { 1 0 } } { { 0 1 } } ifelse /Decode exch cvlit def } .bind % the definition of Decode is based on the number of components /Decode { //img_decary 0 IMG_NComps 2 mul getinterval def } .bind .dicttomark def % % <oper_0> ... <oper_n> <array> img_build_dict <dict> % % Build a dictionary. This will always be done in local VM. The array is % a list of the keys to be associated with operands on the stack, in % inverse stack order (topmost element first). The caller should verify % that the dictionary can be built successfully (except for a possible % VMerror) before calling this routine. % /img_build_dict { % build the dictionary in local VM; all for 2 extra entries .currentglobal //false .setglobal 1 index length 2 add dict exch .setglobal begin % process all keys in the array { //img_params_dict 1 index get exec } forall % if BitsPerComponent is not yet defined, define it to be 1 currentdict /BitsPerComponent known not { /BitsPerComponent 1 def } if currentdict end } .bind def % % <dict> <array> img_unbuild_dict <oper_0> ... <oper_n> % % "Unbuild" a dictionary: spread the contents the dictionary back onto the % stack, in the inverse of the order indicated in the array (inverse is % used as this order is more convenient for img_build_dict, which is % expected to be invoked far more frequently). % /img_unbuild_dict { exch begin dup length 1 sub -1 0 { 1 index exch get load exch } for pop end } .bind def % % Check the image types that can be used as data sources % <any> foo <bool> % /good_image_types mark /filetype { pop //true } .bind /stringtype 1 index /arraytype //xcheck /packedarraytype //xcheck .dicttomark readonly def % % <width> <height> <bits/component> <matrix> <dsrc0> ... % <multi> <ncomp> % img_build_image_dict % <dict> % % Build the dictionary corresponding to a colorimage operand stack. This % routine will check just enough of the stack to verify that the % dictionary can be built, and will generate the appropriate error if this % is not the case. % % At the first level, errors in this procedure are reported as colorimage % errors. The error actually reported will usually be determined by the % pseudo-operator which invokes this routine. % /img_build_image_dict { % Verify that at least 7 operands are available, and that the top two % operands have the expected types count 7 lt { /.colorimage cvx /stackunderflow signalerror } if 2 copy type /integertype ne exch type /booleantype ne or { /.colorimage cvx /typecheck signalerror } if % verify that the number of components is 1, 3, or 4 dup 1 lt 1 index 2 eq or 1 index 4 gt or { /.colorimage cvx /rangecheck signalerror } if % Verify that the required number of operands are present if multiple % data sources are being used. If this test is successful, convert % the data sources to an array (in local VM). 1 index { dup dup count 8 sub gt { % Adobe interpreters appear to test the arguments sequentially % starting from the top of the stack and report the 1st error found. % To satisfy CET test 12-02.PS we emulate this logic. //true exch -1 1 { 2 add index //good_image_types 1 index type .knownget { exec and } { pop pop //false } ifelse } for { /stackunderflow } { /typecheck } ifelse /.colorimage cvx exch signalerror } if % build the DataSource array in local VM dup .currentglobal //false .setglobal exch array exch .setglobal % stack: <w> <h> <bps> <mtx> <d0> ... <multi> <n> <n'> <array> 4 1 roll 3 add 2 roll astore 3 1 roll } if % the image dictionary can be built; do so % stack: <w> <h> <bps> <mtx> <dsrc|dsrc_array> <multi> <n> //img_params_ary //img_build_dict exec } .bind def currentdict /good_image_types .undef % % <?dict?> % img_unbuild_image_dict % <width> <height> <bits/component> <matrix> <dsrc0> ... % <multi> <ncomp> % % If the top entry of the stack is a dictionary that has the keys required % by a colorimage dictionary, unpack that dictionary onto the stack. % Otherwise just leave things as they are. % /img_unbuild_image_dict { //img_check_ary //img_check_keys exec { //img_unbuild_ary //img_unbuild_dict exec 1 index type /booleantype eq { 1 index { 3 -1 roll aload length 2 add -2 roll } if } if } if } .bind def % % <width> <height> <polarity> <matrix> <dsrc> % img_unbuild_imagemask_dict % <dict> % % Build the dictionary corresponding to an imagemask stack. This routine % will verify that the appropriate number of operands are on the stack, % and that polarity is a boolean. This is all that is necessary to build % the dictionary. % /img_build_imagemask_dict { % check for proper number of operands count 5 lt { /imagemask .systemvar /stackunderflow signalerror } if % verify that polarity is a boolean 2 index type /booleantype ne { /imagemask .systemvar /typecheck signalerror } if % the imagemask dictionary can be built; do so //img_mask_params_ary //img_build_dict exec } .bind def % % <?dict?> % img_unbuild_imagemask_dict % <width> <height> <polarity> <matrix> <dsrc> % % If the top entry of the stack is a dictionary that has the keys rquired % by an imagemask dictionary, unpack that dictionary onto the stack. % Otherwise just leave things as they are. % /img_unbuild_imagemask_dict { //img_mask_check_ary //img_check_keys exec { //img_mask_unbuild_ary //img_unbuild_dict exec 3 -1 roll dup type dup /arraytype eq exch /packedarraytype eq or 1 index rcheck and { 0 get 1 eq } if 3 1 roll } if } .bind def % % <width> <height> <bits/component> <matrix> <dsrc_0> ... % <multi> <ncomp> % .colorimage % - % % Convert the image/colorimage operator from their traditional form to % the dictionary form. % % Error handling for these operators is a bit complex, due to the stack % handling required of operators that potentially invoke procedures. % This problem is discussed in the comment above. The facts relevant to % this particular implementation are: % % 1. The .image1 operator is executed in a stopped % context, so that we can undo the gsave context in the event of % an error. % % 2. In the event of an error, the stack is examined to see if the % dictionary passed to .image1 is still present. % If so, this dictionary is "unpacked" onto the stack to re- % create the original stack. % % 3. The use of pseudo-operators in this case may yield incorrect % results for late-detected errors, as the stack depth will be % restored (even though the stack is not). This is, however, no % worse than the prior (level >= 2) code, so it should cause no % new problems. % /.colorimage { % build the image dictionary //img_build_image_dict exec % execute .image1 in a stopped context { gsave % The CET test file 12-02.ps creates colorimages with a width and % height of 0. Ignore these since that is what the CET expects. dup dup /Height get 0 eq exch /Width get 0 eq or { pop } % Ignore colorimage. Pop dict { 0 .setoverprintmode % disable overprint mode for images //img_csary 1 index /IMG_NComps get get setcolorspace .image1 } ifelse } stopped grestore { //img_unbuild_image_dict exec /.colorimage cvx $error /errorname get signalerror } if } .bind def % % <width> <height> <bits/component> <matrix> <dsrc_0> ... % <multi> <ncomp> % colorimage % - % % Build the colorimage pseudo-operator only if setcolorscreen is visible. % systemdict /setcolorscreen .knownget { type /operatortype eq { /colorimage { //.colorimage stopped { /colorimage .systemvar $error /errorname get signalerror } if } .bind systemdict begin odef end } if } if % % width height bits_per_component matrix data_src image - % % <dict> image - % % Some special handling is required for ImageType 2 (Display PostScript % pixmap images) so as to set the appropriate color space as the current % color space. % /image { dup type /dicttype eq .languagelevel 2 ge and { dup /ImageType get dup 2 eq { % verify the ImageType 2 is supported //.imagetypes exch known { % % Set either DevicePixel or DeviceRGB as the current % color space. DevicePixel is used if the image data is % to be copied directly, with only a geometric % transformation (PixelCopy true). The use of DeviceRGB % in the alternate case is not, in general, correct, and % reflects a current implementation limitation. Ideally, % an intermediate color space should be used only if % the source and destination color models vary; otherwise % the native color space corresponding to the color model % should be used. % % The mechanism to determine depth for the DevicePixel % color space when BitsPerPixel is not available is % somewhat of a hack. % gsave 0 .setoverprintmode % disable overprintmode for images dup /PixelCopy .knownget dup { pop } if { [ /DevicePixel currentpagedevice dup /BitsPerPixel .knownget { exch pop } { /GrayValues .knownget not { 2 } % try a guess if ln 2 ln div round cvi } ifelse ] } { /DeviceRGB } ifelse setcolorspace //.imagetypes 2 get stopped grestore { /image .systemvar $error /errorname get signalerror } if } { /image .systemvar /rangecheck signalerror } ifelse } { dup //.imagetypes exch .knownget { exch pop gsave 0 .setoverprintmode % disable overprintmode for images stopped grestore { /image .systemvar $error /errorname get signalerror } if } { /image .systemvar exch type /integertype eq { /rangecheck } { /typecheck } ifelse signalerror } ifelse } ifelse } { //false 1 //.colorimage stopped { /image .systemvar $error /errorname get signalerror } if } ifelse } .bind odef % An auxiliary function for checking whether an imagemask to be interpolated. /.is_low_resolution % <image dict> .is_low_resolution <bool> { % Checking whether image pixel maps to more than 2 device pixels. % The threshold 2 is arbitrary. 1 exch 0 exch 0 exch 1 exch /ImageMatrix get dup 2 { 4 1 roll idtransform dtransform dup mul exch dup mul add sqrt } repeat .max 2 gt % arbitrary } .bind def % % width height polarity matrix datasrc imagemask - % % See the comment preceding the definition of .colorimage for information % as to the handling of error conditions. % /imagemask { dup type /dicttype eq .languagelevel 2 ge and { dup /ImageType get //.imagemasktypes exch .knownget { 1 index //.is_low_resolution exec 2 index /ImageType get 1 eq and 2 index /BitsPerComponent get 1 eq and 2 index /Interpolate .knownget not { //false } if and //filterdict /ImscaleDecode known and %% %% Don't apply ImScaleDecode to interpolate imagemasks if %% the current device is a high level device. %% /HighLevelDevice /GetDeviceParam .special_op { exch pop not }{ //true }ifelse and { % Apply interpolated imagemask scaling filter exch .currentglobal exch dup .gcheck .setglobal dup length dict .copydict dup dup /DataSource get dup type /stringtype eq { 1 array astore cvx % image.* operators read strings repeatesly } if mark /Width 3 index /Width get /Height 5 index /Height get .dicttomark /ImscaleDecode filter /DataSource exch put dup dup /Width get 4 mul /Width exch put dup dup /Height get 4 mul /Height exch put dup dup /ImageMatrix get { 4 0 0 4 0 0 } matrix concatmatrix /ImageMatrix exch put 3 1 roll .setglobal } if exec } { % CET 12-08b.ps wants /typecheck /imagemask .systemvar /typecheck signalerror } ifelse } { //img_build_imagemask_dict exec { .imagemask1 } stopped { //img_unbuild_imagemask_dict exec /imagemask .systemvar $error /errorname get signalerror } if } ifelse } .bind odef % undefine a bunch of local definitions [ /.colorimage /img_params_dict /img_unbuild_dict /img_unbuild_image_dict /img_unbuild_imagemask_dict /img_build_dict /img_build_image_dict /img_build_imagemask_dict /img_check_keys /img_mask_check_ary /img_params_ary /img_mask_unbuild_ary /img_mask_params_ary /img_csary /img_decary /img_check_ary /img_unbuild_ary /.is_low_resolution ] currentdict .undefinternalnames end % systemdict .setglobal % restore VM mode gs_dps2.ps 0000644 00000021103 15030647507 0006455 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % Initialization file for basic Display PostScript functions % that are also included in Level 2. level2dict begin % ------ Errors ------ % % These errors are only defined in Level 2 and DPS. { /configurationerror /undefinedresource /unregistered } { .registererror } forall % ------ Halftones ------ % /.makestackdict { { counttomark -1 roll } forall .dicttomark } bind def /currenthalftone % - currenthalftone <dict> { mark .currenthalftone { { exch pop } % halftone { /HalftoneType 1 % screen { /Frequency /Angle /SpotFunction } //.makestackdict exec readonly } { /HalftoneType 2 % colorscreen { /RedFrequency /RedAngle /RedSpotFunction /GreenFrequency /GreenAngle /GreenSpotFunction /BlueFrequency /BlueAngle /BlueSpotFunction /GrayFrequency /GrayAngle /GraySpotFunction } //.makestackdict exec readonly } } exch get exec } odef currentdict /.makestackdict undef % Define sethalftone so it converts types 1-4 to type 5. /.makehalftoneRGBV { % <dict> <type> <keys> <keysRGBV> 4 -1 roll exch { 1 index exch get exch } forall 15 1 roll 14 -2 roll mark 15 1 roll { /Gray /Blue /Green /Red } { % stack: v0 v1 v2 type keys comp mark 2 index 0 get 8 -1 roll 4 index 1 get 9 -1 roll 6 index 2 get 10 -1 roll % stack: type keys comp mark k0 v0 k1 v1 k2 v2 /HalftoneType 10 index .dicttomark counttomark 2 roll } forall pop pop /Default 1 index .dicttomark exch pop { .sethalftone5 } } bind def % The value of each entry in .halftonetypes is a procedure: % <setdict> <htdict> <<proc>> <setdict'> <htdict'> <sethalftoneproc> % This allows us to use these procedures both for actually implementing % sethalftone and for converting subsidiary dictionaries of HalftoneType 5 % halftones. systemdict begin 15 dict /.halftonetypes 1 index def begin 1 { mark exch /Default exch .dicttomark { .sethalftone5 } } bind def 2 { 1 { /Frequency /Angle /SpotFunction } { /RedFrequency /RedAngle /RedSpotFunction /GreenFrequency /GreenAngle /GreenSpotFunction /BlueFrequency /BlueAngle /BlueSpotFunction /GrayFrequency /GrayAngle /GraySpotFunction } //.makehalftoneRGBV exec } bind def 3 { mark exch /Default exch .dicttomark { .sethalftone5 } } bind def 4 { 3 { /Width /Height /Thresholds } { /RedWidth /RedHeight /RedThresholds /GreenWidth /GreenHeight /GreenThresholds /BlueWidth /BlueHeight /BlueThresholds /GrayWidth /GrayHeight /GrayThresholds } //.makehalftoneRGBV exec } bind def 5 { pop dup length dict copy mark 1 index { % Even HalftoneType 5 dictionaries have entries other than % subsidiary halftone dictionaries. dup type /dicttype ne { 0 } { dup /HalftoneType .knownget not { 0 } if } ifelse dup 5 gt { % Stack: dict mark ... keyN dictN httypeN % Assume that all HalftoneTypes > 5 convert to 5. 1 index 3 1 roll //.halftonetypes exch get exec pop /Default get % Stack: dict mark ... keyN setdict'N htdict'N counttomark 1 add index 3 index 4 -1 roll put } { pop } ifelse } forall .dicttomark { .sethalftone5 } } bind def end end currentdict /.makehalftoneRGBV undef /sethalftone { % <dict> sethalftone - % We must create the new dictionary in the same VM as the % operand; otherwise, invalidaccess errors may occur. .currentglobal 1 .argindex dup gcheck .setglobal dup //.halftonetypes 1 index /HalftoneType get dup type /integertype ne { /sethalftone .systemvar /typecheck signalerror } if .knownget not { /sethalftone .systemvar /rangecheck signalerror } if exec exec .setglobal pop } .bind odef % Redefine setscreen and setcolorscreen to recognize halftone dictionaries, % and to insert the Frequency and Angle into Type 1 halftones, per % Adobe TN 5085. /.fixsethalftonescreen % <freq> <angle> <dict> .fix...screen % <freq> <angle> <dict> <dict'> { dup dup /HalftoneType get 1 eq { dup wcheck not { dup length dict .copydict } if dup /Frequency 5 index put dup /Angle 4 index put languagelevel 3 ge { dup /AccurateScreens dup getuserparam put } if } if } bind def /setscreen % <ignore*2> <dict> setscreen - { dup type /dicttype eq { //.fixsethalftonescreen exec sethalftone pop pop pop } { //setscreen } ifelse } .bind odef /setcolorscreen % <ignore*11> <dict> setcolorscreen - { dup type /dicttype eq { //.fixsethalftonescreen exec sethalftone 12 { pop } repeat } { //setcolorscreen } ifelse } .bind odef currentdict /.fixsethalftonescreen undef % Redefine currentscreen and currentcolorscreen to extract the Frequency % and Angle from Type 1 halftones, per Adobe TN 5085. /.fixcurrenthalftonescreen % <dict> .fix... <freq> <angle> <proc> { dup /HalftoneType get 1 eq { dup /Frequency get 1 index /Angle get } { 60.0 0.0 } % Adobe returns these as reals ifelse 3 2 roll } bind def /currentscreen % - currentscreen 60 0 <dict> { .currenthalftone { { //.fixcurrenthalftonescreen exec }% halftone { } % screen { 12 3 roll 9 { pop } repeat % colorscreen dup type /dicttype eq { //.fixcurrenthalftonescreen exec } if } } exch get exec } odef /currentcolorscreen % - currentcolorscreen (60 0 <dict>)*4 { .currenthalftone { { //.fixcurrenthalftonescreen exec 3 copy 6 copy } % halftone { % screen % The procedure might not be readable.... dup rcheck { dup length array copy cvx } if 3 copy 6 copy } { } % colorscreen } exch get exec } odef currentdict /.fixcurrenthalftonescreen undef % ------ User objects ------ % /.UserObjects { .userdict /UserObjects } bind executeonly odef % In order to get proper error recovery behavior, we need to be careful % not to pop any operands from the stack until we're done. % The code below faithfully duplicates the apparent array-growing % behavior of Adobe interpreters. /defineuserobject { % <index> <value> defineuserobject - 1 index 65535 gt { % .localvmarray throws limitcheck but CET 31-02 wants rangecheck /defineuserobject .systemvar /rangecheck signalerror } if .UserObjects .knownget { length dup 3 .argindex le { % Stack: index value len 2 index eq { 1 index 2 mul } { 1 index 1 add } ifelse .localvmarray .UserObjects get 1 index copy pop .UserObjects 3 -1 roll put } { pop } ifelse } { .UserObjects 3 .argindex 1 add 10 .max .localvmarray put } ifelse .UserObjects get 2 .argindex 2 index put pop pop } .bind odef /execuserobject { % <index> execuserobject - dup type /integertype ne { % Adobe validates the argument before accessing UserObjects - CET 31-03 /execuserobject .systemvar /typecheck signalerror } if .UserObjects get 1 .argindex get exch pop exec } .bind odef /undefineuserobject { % <index> undefineuserobject - dup type /integertype ne { % Adobe validates the argument before accessing UserObjects - CET 31-11 /undefineuserobject .systemvar /typecheck signalerror } if .UserObjects get 1 .argindex //null put pop } .bind odef currentdict /.UserObjects undef % ------ Cache control ------ % % Dummy definitions for cache control operators /ucachestatus { % - ucachestatus -mark- ? ? ? ? <size> mark 0 0 0 0 /MaxUPathItem getuserparam } odef /setucacheparams { % -mark- ... <size> setucacheparams - % Provoke an appropriate error if needed. counttomark 1 lt { () 0 get } if dup 0 or /MaxUPathItem getuserparam .max 1 dict dup /MaxUPathItem 4 -1 roll put setuserparams cleartomark } odef end % level2dict Fontmap 0000644 00000000155 15030647507 0006103 0 ustar 00 %! % See Fontmap.GS for the syntax of real Fontmap files. %% Replace 1 (Fontmap.GS) (Fontmap.GS) .runlibfile gs_cidtt.ps 0000644 00000013327 15030647507 0006725 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % Redefine CIDFont category with an emulation with True Type fonts. languagelevel 2 .setlanguagelevel 15 dict begin % a temporary dictionary for local binding. %------------------Copy the FontEmulationProcs here : ------------------- /FontEmulationProcs /ProcSet findresource { def } forall currentdict /super.complete_instance currentdict /complete_instance get put %-------Auxiliary procedures for building CIDFontType 2 from TT file ----------- /GenerateCIDMap % <font> GenerateCIDMap <font> { begin % Obtain the maximal CID : % This implementation doesn't check whether glyphs really present. Decoding /CIDCount get /CIDCount exch def % Prepare the CIDMap structure : /CIDMap [ CIDCount 22000 le { CIDCount 2 mul string } { 44000 string CIDCount 44000 gt { % need three strings 44000 string % 22000 2 mul string CIDCount 44000 sub 2 mul string } { CIDCount 22000 sub 2 mul string } ifelse } ifelse ] def % Now fill it : Decoding TT_cmap SubstNWP GDBytes CIDMap .fillCIDMap currentdict end } bind def /GenerateIdentityCIDMap % <font> GenerateCIDMap <font> { begin /CIDMap [ 44000 string 44000 string 44000 string] def CIDMap .fillIdentityCIDMap currentdict end } bind def /load_sfnts % <FontDict> load_sfnts <FontDict> { % Read the True Type file from the path /Path, and buld /sfnts, % skipping glyf and loca. dup /Path get % <font> (path) QUIET not { (Loading a TT font from ) print dup print ( to emulate a CID font ) print 1 index /CIDFontName get =only ( ... ) print } if (r) file dup % <font> file file 3 1 roll % file <font> file 1 index /SubfontID .knownget not { 0 } if % file <font> file SubfontID 2 index /FileType .knownget {/WOFF eq} {//false} ifelse % It's not (currently) viable to load WOFF fonts "stripped", so we don't try {.load_woff_for_cid exch copy exch pop} { .load_tt_font_stripped exch copy % file <font> QUIET not { (Done.) = } if dup 3 1 roll % <font> file <font> exch /File exch put % <font> } ifelse dup dup /CIDSystemInfo get /Ordering get (.) % <font> () () 2 index /Decoding get =string cvs % <font> () () () concatstrings concatstrings cvn /Decoding exch put % <font> dup dup /CIDSystemInfo get /Ordering get (-WMode) % <font> <font> () () concatstrings cvn /SubstCID 2 copy resourcestatus { pop pop findresource /subst_CID_on_WMode exch put % <font> } { pop pop pop } ifelse dup /Decoding get /Identity.Unicode eq { //ChooseDecoding exec % <font> //GenerateIdentityCIDMap exec % <font> } { //ChooseDecoding exec % <font> //GenerateCIDMap exec % <font> } ifelse } bind def %-----------TrueType-specific methods for category redefinition : ----------- /RefinePath % <FontDict> RefinePath <FontDict> { dup begin Path .libfile { dup .filename { currentdict exch /Path exch put } if closefile } { (r) { file } //.internalstopped exec { (Can't find the font file ) print = /findfont cvx /undefinedfilename signalerror } { dup .filename { currentdict exch /Path exch put } if closefile } ifelse } ifelse end } bind def /complete_instance % <font_name> <FontDict> <Options> complete_FAPI_Font <font_name> <FontDict> { 1 index /CIDFontType 2 put % Other types are not emulated yet. //super.complete_instance exec //RefinePath exec //load_sfnts exec } bind def /ValidFileTypes << /TrueType 0 /WOFF 0 >> def /IsMyRecord % <raw_record> -> <raw_record> bool { dup type /dicttype eq { dup /FileType .knownget { //ValidFileTypes exch known } { //false } ifelse } { //false } ifelse } bind def currentdict /ValidFileTypes undef /IsActive % <record> IsActive <bool> { pop //true } bind def /CIDFontRecordVirtualMethods //RecordVirtualMethodsStub dup length 3 add dict copy begin /GetCSI //TranslateCSI def /IsActive //IsActive def /MakeInstance % <Name> <record> MakeInstance <Name> <Instance> <size> { currentglobal 3 1 roll //true setglobal //CIDFontOptions //complete_instance exec 2 copy //GetSize exec 4 3 roll setglobal } bind def currentdict end def % Redefine the /CIDFont category : 4 dict begin /CategoryName /CIDFont def /IsMapFileOptional //true def /VerifyMap { pop } bind def /PreprocessRecord % <map> <Name> <raw_record> PreprocessRecord <map> <Name> <record> <bool> { //IsMyRecord exec dup { pop dup /RecordVirtualMethods //CIDFontRecordVirtualMethods put //true } if } bind def currentdict end /MappedCategoryRedefiner /ProcSet findresource /Redefine get exec end % the temporary dictionary for local binding. .setlanguagelevel gs_mro_e.ps 0000644 00000004712 15030647507 0006715 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % $Id: gs_mro_e.ps 8954 2008-08-08 04:22:38Z ray $ % Define the MacRoman encoding vector. /currentglobal where { pop currentglobal { setglobal } //true setglobal } { { } } ifelse /MacRomanEncoding StandardEncoding 0 39 getinterval aload pop /quotesingle StandardEncoding 40 56 getinterval aload pop /grave StandardEncoding 97 31 getinterval aload pop % \20x /Adieresis /Aring /Ccedilla /Eacute /Ntilde /Odieresis /Udieresis /aacute /agrave /acircumflex /adieresis /atilde /aring /ccedilla /eacute /egrave /ecircumflex /edieresis /iacute /igrave /icircumflex /idieresis /ntilde /oacute /ograve /ocircumflex /odieresis /otilde /uacute /ugrave /ucircumflex /udieresis % \24x /dagger /degree /cent /sterling /section /bullet /paragraph /germandbls /registered /copyright /trademark /acute /dieresis /.notdef /AE /Oslash /.notdef /plusminus /.notdef /.notdef /yen /mu /.notdef /.notdef /.notdef /.notdef /.notdef /ordfeminine /ordmasculine /.notdef /ae /oslash % \30x /questiondown /exclamdown /logicalnot /.notdef /florin /.notdef /.notdef /guillemotleft /guillemotright /ellipsis /space /Agrave /Atilde /Otilde /OE /oe /endash /emdash /quotedblleft /quotedblright /quoteleft /quoteright /divide /.notdef % NOTE: Euro should replace currency, but the PDF 1.3 documentation % explicitly says it does not. /ydieresis /Ydieresis /fraction /currency /guilsinglleft /guilsinglright /fi /fl % \34x /daggerdbl /periodcentered /quotesinglbase /quotedblbase /perthousand /Acircumflex /Ecircumflex /Aacute /Edieresis /Egrave /Iacute /Icircumflex /Idieresis /Igrave /Oacute /Ocircumflex /.notdef /Ograve /Uacute /Ucircumflex /Ugrave /dotlessi /circumflex /tilde /macron /breve /dotaccent /ring /cedilla /hungarumlaut /ogonek /caron 256 packedarray 5 1 index .registerencoding .defineencoding exec gs_mex_e.ps 0000644 00000007403 15030647507 0006711 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % Define the MacExpert encoding vector. /currentglobal where { pop currentglobal { setglobal } //true setglobal } { { } } ifelse /MacExpertEncoding % \00x /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef % \04x /space /exclamsmall /Hungarumlautsmall /centoldstyle /dollaroldstyle /dollarsuperior /ampersandsmall /Acutesmall /parenleftsuperior /parenrightsuperior /twodotenleader /onedotenleader /comma /hyphen /period /fraction /zerooldstyle /oneoldstyle /twooldstyle /threeoldstyle /fouroldstyle /fiveoldstyle /sixoldstyle /sevenoldstyle /eightoldstyle /nineoldstyle /colon /semicolon /.notdef /threequartersemdash /.notdef /questionsmall % \10x /.notdef /.notdef /.notdef /.notdef /Ethsmall /.notdef /.notdef /onequarter /onehalf /threequarters /oneeighth /threeeighths /fiveeighths /seveneighths /onethird /twothirds /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /ff /fi /fl /ffi /ffl /parenleftinferior /.notdef /parenrightinferior /Circumflexsmall /hypheninferior % \14x /Gravesmall /Asmall /Bsmall /Csmall /Dsmall /Esmall /Fsmall /Gsmall /Hsmall /Ismall /Jsmall /Ksmall /Lsmall /Msmall /Nsmall /Osmall /Psmall /Qsmall /Rsmall /Ssmall /Tsmall /Usmall /Vsmall /Wsmall /Xsmall /Ysmall /Zsmall /colonmonetary /onefitted /rupiah /Tildesmall /.notdef % \20x /.notdef /asuperior /centsuperior /.notdef /.notdef /.notdef /.notdef /Aacutesmall /Agravesmall /Acircumflexsmall /Adieresissmall /Atildesmall /Aringsmall /Ccedillasmall /Eacutesmall /Egravesmall /Ecircumflexsmall /Edieresissmall /Iacutesmall /Igravesmall /Icircumflexsmall /Idieresissmall /Ntildesmall /Oacutesmall /Ogravesmall /Ocircumflexsmall /Odieresissmall /Otildesmall /Uacutesmall /Ugravesmall /Ucircumflexsmall /Udieresissmall % \24x /.notdef /eightsuperior /fourinferior /threeinferior /sixinferior /eightinferior /seveninferior /Scaronsmall /.notdef /centinferior /twoinferior /.notdef /Dieresissmall /.notdef /Caronsmall /osuperior /fiveinferior /.notdef /commainferior /periodinferior /Yacutesmall /.notdef /dollarinferior /.notdef /.notdef /Thornsmall /.notdef /nineinferior /zeroinferior /Zcaronsmall /AEsmall /Oslashsmall % \30x /questiondownsmall /oneinferior /Lslashsmall /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /Cedillasmall /.notdef /.notdef /.notdef /.notdef /.notdef /OEsmall /figuredash /hyphensuperior /.notdef /.notdef /.notdef /.notdef /exclamdownsmall /.notdef /Ydieresissmall /.notdef /onesuperior /twosuperior /threesuperior /foursuperior /fivesuperior /sixsuperior % \34x /sevensuperior /ninesuperior /zerosuperior /.notdef /esuperior /rsuperior /tsuperior /.notdef /.notdef /isuperior /ssuperior /dsuperior /.notdef /.notdef /.notdef /.notdef /.notdef /lsuperior /Ogoneksmall /Brevesmall /Macronsmall /bsuperior /nsuperior /msuperior /commasuperior /periodsuperior /Dotaccentsmall /Ringsmall /.notdef /.notdef /.notdef /.notdef 256 packedarray 6 1 index .registerencoding .defineencoding exec gs_cmap.ps 0000644 00000044433 15030647507 0006540 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % ProcSet for implementing CMap resources. % When this is run, systemdict is still writable. % NOTE: Rearranged fonts are not implemented yet. [ /CMERGE_DEBUG /USE_CIDCHAR_AS_RANGE ] {dup where {pop pop} { currentdict exch //false def pop } ifelse} forall % ---------------- Public operators ---------------- % /.rewriteTempMapsNotDef { % % Before building .CodeMapData from .TempMaps, % we need to replace dst type codes in the notdef map with the value 3, % which corresponds to CODE_VALUE_NOTDEF, see gxfcmap.h . % CMAPDEBUG { (rewriting TempMapsNotDef\n) print flush } if .TempMaps 2 get dup length 0 gt { 0 get CMAPDEBUG { (...original...\n) print flush } if 1 5 2 index length 1 sub { { 1 index exch get 2 3 put } stopped { CMAPDEBUG { (cannot rewrite\n) print flush } if } { CMAPDEBUG { (rewrite\n) print flush } if } ifelse } for } if pop CMAPDEBUG { (...FINISHED...\n) print } if } bind def /.composefontdict { % <name> <cmap|cmapname> <fonts> composefont <name> <font_dict> 10 dict begin /CMap 2 index dup type /dicttype ne { /CMap findresource } if def /FDepVector 1 index cvlit def % temporarily /Encoding [ 0 1 FDepVector length 1 sub { } for ] def /FontInfo 1 dict def % for .processToUnicode in pdf_font.ps . /FDepVector [ 0 1 FDepVector length 1 sub { % Stack: name cmap[name] fonts /FDepVector [ fonts... i FDepVector 1 index get dup type /dicttype ne { dup /CIDFont resourcestatus { pop pop /CIDFont } { /Font } ifelse findresource } if exch CMap /FontMatrices get dup length 2 index gt { exch get dup //null eq { pop } { makefont } ifelse } { pop pop } ifelse } for ] readonly def /FMapType 9 def /FontMatrix matrix def /FontName 3 index def CMap /WMode .knownget { /WMode exch def } if /FontType 0 def pop pop currentdict end } bind executeonly odef % composefont doesn't appear in CMap files -- it's documented in % the "PostScript Language Reference Manual Supplement". /composefont { % <name> <cmap|cmapname> <fonts> composefont <font> .composefontdict /Font defineresource } bind def % ---------------- CMap operators ---------------- % 40 dict begin % Our internal .CodeMapData structure closely mirrors the structures % defined in gxfcmap.h (q.v.). () indicate a string, [] indicate an array, % ? indicates a Boolean, # indicates an integer, {} for grouping. % [[[(first) (last) ...]+] % code space ranges % [[(prefix) (key_size,?is_range,value_type,value_size) (keys...) % {(values...) | [value ...]} #font_index ]+] % code mappings % ...] % <<same>> % notdef mappings % ] % FontMatrices is the array of matrices defined by begin/endusematrix. % All of the arrays and strings are read-only after they have been built. % % Note that the code in zfcmap.c that constructs the C structures from % the PostScript structures has intimate knowledge of the above format. % ****** NOTE: The code currently only handles "well-behaved" CMaps: % - CID values only (no bfchars), 16-bit % - Entries (both code space and map) must be sorted % - Only the last byte must vary in each map range, except for % the identity mapping % ------ Font-level operators ------ % /begincmap { % - begincmap - /.CodeMapData [[[]] [[]] [[]]] def /FontMatrices [] def /.FontIndex 0 def /.TempMaps [20 dict 50 dict 50 dict] def /CodeMap //null def % for .buildcmap } bind def /endcmap { % - endcmap - //.rewriteTempMapsNotDef exec CMAPDEBUG { 2 (*** undefined charmap ***) 1 (*** defined charmap ***) 0 (*** code space ranges ***) 3 { = .TempMaps exch get 0 1 2 index length 1 sub { dup //== exec (\t) print 1 index exch get //== exec } for pop } repeat } if /.CodeMapData dup load [ exch .TempMaps aload pop begin begin begin { [ exch aload pop 0 1 currentdict length 1 sub { currentdict exch get } for ] end } forall ] .endmap def CMAPDEBUG { (*** Content of .CodeMapData ***) = 0 .CodeMapData { exch dup //== exec 1 add exch (\t) print //== exec } forall pop } if currentdict /.TempMaps undef /FontMatrices FontMatrices .endmap def } bind def /.endmap { % <map> .endmap <map> dup type /arraytype eq { % This might be a shared read-only array inherited via usecmap. % Don't try to update its elements if this is the case. dup wcheck { 0 1 2 index length 1 sub { 2 copy 2 copy get .endmap put pop } for readonly } if } { dup type /stringtype eq { readonly } if } ifelse } bind def /.appendmap { % -mark- <elt> ... <array#> .appendmap - .TempMaps exch get counttomark 1 add 1 roll ] 1 index length exch put } bind def /begincodespacerange { % <count> begincodespacerange - pop mark } bind def /endcodespacerange { % <code_lo> <code_hi> ... endcodespacerange - 0 .appendmap } bind def /usecmap { % <CMap_name> usecmap - /CMap findresource dup % Copy the top level of .CodeMapData /.CodeMapData exch /.CodeMapData get copyarray def /FontMatrices exch /FontMatrices get copyarray def } bind def /usefont { % <fontID> usefont - /.FontIndex exch def } bind def /beginusematrix { % <fontID> beginusematrix - FontMatrices wcheck not FontMatrices length 2 index le or { FontMatrices length 1 index 1 add .max array dup 0 FontMatrices putinterval /FontMatrices exch def } if } bind def /endusematrix { % <matrix> endusematrix - FontMatrices 3 1 roll put } bind def % ------ Rearranged font operators ------ % /beginrearrangedfont { % <font_name> <font*> beginrearrangedfont - 10 dict begin /.FontNames exch def /.FontName exch def begincmap } bind def /endrearrangedfont { % - endrearrangedfont - (REARRANGED FONTS NOT IMPLEMENTED YET.) = flush .FontName .FontNames 0 get findfont end definefont pop } bind def % ------ Character name/code selector operators ------ % /beginbfchar { % <count> beginbfchar - pop mark } bind def /endbfchar { % [ <code> <to_code|charname> ... endbfchar ] [ //true % [<da><ta>] [ true 3 -1 roll % [ true [<da><ta>] { exch { //false % [ <da> false } { % [ <da> <ta> .addbfchar % [ prefix params key value font_index //true } ifelse } forall pop 1 .appendmap } bind def /beginbfrange { % <count> beginbfrange - pop mark } bind def /endbfrange { % <code_lo> <code_hi> <to_code|(charname*)> ... % endbfrange - ] [ 0 % [<da><ta><set>] [ 0 3 -1 roll % [ 0 [<da><ta><set>] { exch % [ <da> 0 { 1 2 { dup type dup /arraytype eq exch /packedarraytype eq or { % Array value, split up. exch pop { % Stack: code to_code|charname 1 index exch .addbfchar % Increment the code. As noted above, we require % that only the last byte vary, but we still must % mask it after incrementing, in case the last % value was 0xff. % Stack: code prefix params key value fontindex 6 -1 roll dup length string copy dup dup length 1 sub 2 copy get 1 add 255 and put } forall pop } { % Single value, handle directly. .addbfrange } ifelse 0 } } exch get exec } forall pop 1 .appendmap } bind def /.addbfchar { % <code> <to_code|charname> .addbfchar % <prefix> <params> <key> <value> <font_index> 1 index exch .addbfrange } bind def /.addbfrange { % <code_lo> <code_hi> <to_code|charname> % .addbfrange <<same as .addbfchar>> 4 string dup 3 3 index type /nametype eq { 2 index 2 1 put % dst = CODE_VALUE_GLYPH, see gxfcmap.h . 4 -1 roll 1 array astore 4 1 roll 4 } { 2 index 2 2 put % dst = CODE_VALUE_CHARS, see gxfcmap.h . 3 index length } ifelse put % Stack: code_lo code_hi value params 3 index 3 index eq { % Single value. 3 -1 roll pop exch () exch } { % Range. dup 0 4 index length put dup 1 1 put 4 2 roll 1 index dup length 1 sub 0 exch getinterval 5 1 roll % prefix % Stack: prefix value params code_lo code_hi concatstrings 3 -1 roll } ifelse .FontIndex } bind def % ------ CID selector operators ------ % /begincidchar { % <count> begincidchar - pop mark } bind def /endcidchar { % <code> <cid> ... endcidchar - 1 .endmapchars } bind def /begincidrange { % <count> begincidrange - pop mark } bind def /endcidrange { % <code_lo> <code_hi> <cid_base> ... endcidrange - 1 .endmapranges } bind def /.endmapchars { % -mark- <code> <cid> ... <map#> .endmapchars - counttomark 1 add 1 roll counttomark 2 idiv { counttomark -2 roll % process in correct order exch % <cid> <code> % Construct prefix, params, key, value, font_index dup length 1 eq { % 1-byte <00 00 00 02> () % <prefix> <param> <null_key> } { % N-byte dup 0 1 getinterval exch % make 1-byte prefix 4 string dup 0 USE_CIDCHAR_AS_RANGE { <00 01 00 02> % skelton for param } { <00 00 00 02> % skelton for param } ifelse putinterval exch % <prefix> <param> <code> dup length % <prefix> <param> <code> N 1 sub % <prefix> <param> <code> N-1 dup % <prefix> <param> <code> N-1 N-1 3 index % <prefix> <param> <code> N-1 N-1 <param> exch % <prefix> <param> <code> N-1 <param> N-1 0 exch % <prefix> <param> <code> N-1 <param> 0 N-1 put % <prefix> <param'> <code> N-1 1 exch % <prefix> <param'> <code> 1 N-1 getinterval % <prefix> <param'> <key> USE_CIDCHAR_AS_RANGE { dup length 2 mul string % <key> <dkey> dup % <key> <dkey> <dkey> 2 index % <key> <dkey> <dkey> <key> 0 exch putinterval % <key> <dkey'> dup % <key> <dkey'> <dkey'> 3 -1 roll % <dkey'> <dkey'> <key> dup length % <dkey'> <dkey'> <key> N-1 exch putinterval % <dkey''> } if } ifelse 4 -1 roll % <prefix> <param'> <key> <cid> .endmapvalue % <prefix> <param'> <key> <hex_cid> <font_idx> % prefix params keys value fontindex counttomark 9 gt { % 2 (or more) ranges (1 range = 5 item) 4 index 10 index eq % compare prefix 4 index 10 index eq and % compare params 1 index 7 index eq and % compare fontindex { CMAPDEBUG { (merge! char\n) print } if pop 4 2 roll pop pop % prefix params keys value fontindex keys2 value2 5 -1 roll 3 -1 roll concatstrings % prefix params value fontindex value2 keys' 4 -1 roll 3 -1 roll concatstrings % prefix params fontindex keys' values' 3 -1 roll } if } if % end of 2 (or more) ranges CMERGE_DEBUG { ( prefix:) print 4 index =only ( param:) print 3 index =only ( key:) print 2 index =only ( hex_cid:) print 1 index =only ( font_idx:) print 0 index //== exec flush } if } repeat counttomark 2 add -1 roll .appendmap } bind def /.endmapranges { % -mark- <code_lo> <code_hi> <cid_base> ... <map#> % .endmapranges - counttomark 1 add 1 roll counttomark 3 idiv { counttomark -3 roll % process in correct order % Construct prefix, params, key_lo, key_hi, value, font_index 3 1 roll % <cid_base> <code_lo> <code_hi> % prefix key % 1-byte code: () . % 1-byte range: () . % N-byte code: . (*) % N-byte range: (*) (*) dup 2 index eq { % <code_lo> == <code_hi> % 0: prefix_len for 1-byte code % 1: prefix_len for N-byte code dup length 1 eq { 0 } { 1 } ifelse } { % <code_lo> != <code_hi> % calculate prefix_len for *-byte range dup length 1 sub % <cid_base> <code_lo> <code_hi> <code_len-1> 0 % initial value for N { % <cid_base> <code_lo> <code_hi> (code_len-1) N dup 2 index ge { exit } if % if (N >= len - 1) exit 3 index 1 index get % N-th byte of code_lo 3 index 2 index get % N-th byte of code_hi eq { 1 add } { exit } ifelse } loop exch pop % discard <code_len-1> } ifelse % cid_base code_lo code_hi prefix_len % Althogh Adobe CPSI with native CID/CMap support accept % multi-dimensional range specification in notdef & cidrange % (and CID is calculated as relative position in multi-dimensional % range), but older CPSI & ATM cannot handle it. % % GS accepts such specification, but it's recommended to keep % from using this feature for notdef & cidrange. % Following is a disabler of this feature. % ------------------------------------------------------------- % counttomark 1 add index % get map# % 0 ne { % if not codespacerange % 1 index length % get code length % 1 index % get prefix length % sub % calculate key length % 1 gt { % if (key_len > 1), % (.endmapranges error) = flush % (multi-dimensional range specification is used out of codespacerange) % = flush % (/) =only % CMapName CMapName length string cvs =only % (: <) =only % 2 index (%stdout) (w) file exch writehexstring % (> <) =only % 1 index (%stdout) (w) file exch writehexstring % (>\n) =only flush % quit % } if % } if % ------------------------------------------------------------- 1 index exch 0 exch getinterval % cid_base code_lo code_hi prefix dup length 3 index length exch sub % cid_base code_lo code_hi prefix range_len dup 255 gt { (too long coderange specification for current GS\n) print /.endmapranges cvx /rangecheck signalerror } if <00 01 00 02> 4 string copy % create initialized param dup 0 4 -1 roll put % put range_len into param % get key_hi 3 -1 roll dup length 3 index length dup 3 1 roll sub getinterval % get key_lo 4 -1 roll dup length 4 index length dup 3 1 roll sub getinterval % make "keys" (concatenated key_lo + key_hi) exch concatstrings % 4 -1 roll .endmapvalue % See if we can merge with the previous value. % The prefix, params, and font index must match. % prefix params keys value fontindex counttomark 9 gt { % 2 (or more) ranges (1 range = 5 item) 4 index 10 index eq % compare prefix 4 index 10 index eq and % compare params 1 index 7 index eq and % compare fontindex { CMAPDEBUG { (merge!\n) print } if pop 4 2 roll pop pop % prefix params keys value fontindex keys2 value2 5 -1 roll 3 -1 roll concatstrings % prefix params value fontindex value2 keys' 4 -1 roll 3 -1 roll concatstrings % prefix params fontindex keys' values' 3 -1 roll } if } if % end of 2 (or more) ranges } repeat counttomark 2 add -1 roll .appendmap } bind def /.endmapvalue { % <cid> .endmapvalue (hi,lo) .FontIndex 2 string dup 0 3 index -8 bitshift put % value dup 1 4 -1 roll 255 and put .FontIndex % font_index } bind def % ------ notdef operators ------ % /beginnotdefchar { % <count> beginnotdefchar - pop mark } bind def /endnotdefchar { % <code> <cid> ... endnotdefchar - 2 .endmapchars } bind def /beginnotdefrange { % <count> beginnotdefrange - pop mark } bind def /endnotdefrange { % <code_lo> <code_hi> <cid> ... endnotdefrange - 2 .endmapranges } bind def % ---------------- Resource category definition ---------------- % currentdict end languagelevel exch 2 .setlanguagelevel /CMap /Generic /Category findresource dup length dict .copydict dup /InstanceType /dicttype put dup /DefineResource { % The AdobePS5 Windows driver emits code that attempts to % create CMaps without the required CMapName entry. % Work around this here. dup /CMapName known not { dup wcheck not { .currentglobal exch dup wcheck .setglobal dup length dict .copydict exch .setglobal } if dup gcheck 2 index gcheck not and { exch .currentglobal exch //true .setglobal dup length string copy exch .setglobal exch } if dup /CMapName 3 index put } if % Adobe PS CET 23-25 and others define an almost empty CMap. Tolerate this. % With the above, we can actually tolerate: /name << >> defineresource dup /CIDSystemInfo known not { dup wcheck not { .currentglobal exch dup wcheck .setglobal dup length dict .copydict exch .setglobal } if dup /CIDSystemInfo [ //null ] put } if dup /CodeMap .knownget { //null eq { .buildcmap } if } if /Generic /Category findresource /DefineResource get exec } bind executeonly put /Category defineresource pop % We might have loaded CID font support already. /CIDInit /ProcSet 2 copy { findresource } //.internalstopped exec % An interior `stopped' might have reset VM allocation to local. //true .setglobal { pop pop 3 -1 roll } { dup length 4 index length add dict .copydict 4 -1 roll exch .copydict } ifelse exch defineresource pop currentdict /.rewriteTempMapsNotDef .undef .setlanguagelevel gs_fonts.ps 0000644 00000136623 15030647507 0006754 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % Font initialization and management code. % Define the default font. /defaultfontname /Courier def % Define the name of the font map file. % Note that the "%%Replace " comment below provides the font map file name % for compiling initialization files into executable. Most likely it should be % consistent with the one specified here. /defaultfontmap (Fontmap) def % we have to set .languagelevel to 2 so the parser will accept the names % '<<' and '>>', then we use a local definition here. .languagelevel 2 .setlanguagelevel /defaultfontmap_content 50 dict 4 dict begin (<<) cvn /mark load def (>>) cvn /.dicttomark load def /; { 2 index 3 1 roll .growput } bind def %% Replace 0 (Fontmap) end def .setlanguagelevel % ------ End of editable parameters ------ % % Define the UniqueIDs and organization XUID assigned to Artifex. % UniqueIDs 5,066,501 - 5,066,580 are assigned as follows: % 01 and 02 for shareware Cyrillic % 33 through 67 for Type 1 versions of the Hershey fonts % UniqueIDs 5,115,501 - 5,115,600 are currently unassigned. /AladdinEnterprisesXUID 107 def % If SUBSTFONT is defined, make it the default font. /SUBSTFONT where { pop /defaultfontname /SUBSTFONT load def } if % Define a reliable way of accessing FontDirectory in systemdict. /.FontDirectory { /FontDirectory .systemvar } .bind executeonly odef % Define a temporary string for local use, since using =string % interferes with some PostScript programs. /.fonttempstring 8192 string def % Split up a search path into individual directories or files. /.pathlist % <path> .pathlist <dir1|file1> ... { { dup length 0 eq { pop exit } if .filenamelistseparator search not { exit } if exch pop exch } loop } bind def % <dir.../base.extn> .basename <dir> /.splitdirname { (/) rsearch { //true } { (\\) rsearch } ifelse {exch concatstrings exch pop //true}{//false} ifelse } bind def % <dict> .addfontmappermitpaths % As fontmap can contain a *lot* of individual entries % we split off the filenames, and add directories to the % allowed paths. % We accumulate the paths in a dictionary, then iterate % the dictionary adding the paths to the PermitReading % list. This leverages the efficiency of dictionaries % handling duplicate keys. /.addfontmappermitpaths { dup length dict begin { exch pop dup type /stringtype eq {//.splitdirname exec {dup def} {pop} ifelse} {pop} ifelse } forall currentdict end {exch pop /PermitFileReading exch .addcontrolpath}forall } bind def defaultfontmap_content length 0 gt {defaultfontmap_content .addfontmappermitpaths} if % Load a font name -> font file name map. userdict /Fontmap .FontDirectory maxlength dict put userdict /.nativeFontmap .FontDirectory maxlength dict put /.loadFontmap { % <file> .loadFontmap - % We would like to simply execute .definefontmap as we read, % but we have to maintain backward compatibility with an older % specification that makes later entries override earlier % ones within the same file. 50 dict exch .readFontmap dup //.addfontmappermitpaths exec { .definefontmap } forall } bind def /.readFontmap { % <dict> <file> .readFontmap <dict> { dup token not { closefile exit } if % stack: dict file fontname % This is a hack to get around the absurd habit of MS-DOS editors % of adding an EOF character at the end of the file. dup (\032) eq { pop closefile exit } if 1 index token not { (Fontmap entry for ) print dup =only ( has no associated file or alias name! Giving up.) = flush {.readFontmap} 0 get 1 .quit } if dup type dup /stringtype eq exch /nametype eq or not { (Fontmap entry for ) print 1 index =only ( has an invalid file or alias name! Giving up.) = flush {.readFontmap} 0 get 1 .quit } if % stack: dict file fontname filename|aliasname dup type /nametype eq { dup (<<) cvn eq { pop mark { counttomark 2 add index token not {//false exit} if dup (>>) cvn eq {pop //true exit} if } loop { .dicttomark }{cleartomark} ifelse } if } if 1 index type /stringtype eq 1 index type /nametype eq and 1 index xcheck and 1 index /run eq 2 index /.runlibfile eq or and { % This is an inclusion entry. pop findlibfile { exch pop } { file } ifelse 2 index exch .readFontmap pop } { % This is a real entry. % Read and pop tokens until a semicolon. { 2 index token not { (Fontmap entry for ) print 1 index =only ( ends prematurely! Giving up.) = flush {//.loadFontmap exec} 0 get 1 .quit } if dup /; eq { pop 3 index 3 1 roll .growput exit } if pop } loop } ifelse } loop } bind def % Add an entry in Fontmap. We redefine this if the Level 2 % resource machinery is loaded. /.definefontmapaux % <bool> <fontname> <file|alias> .definefontmapaux - { % Since Fontmap is global, make sure the values are storable. % If the fontname contains Unicode (first byte == \000) and % this is not an alias definition, define an alias using ASCII % (stripping out the high \000 bytes). Observed with some TT fonts. 1 index 100 string cvs dup length 0 gt { 0 get 0 eq 1 index type /nametype ne and { 1 index 100 string cvs dup length 2 div cvi string //true exch 0 1 2 index length 1 sub { % stack: fontname filename fontnamestring addflag newstring index dup 4 index exch 2 mul get 0 ne { % High byte of pair is not \000 pop pop //false exch exit } if dup 4 index exch 2 mul 1 add get 2 index 3 1 roll put } for exch { DEBUG { (\nAdding alias for: ) print 1 index ==only ( as: ) print dup //== exec flush } if cvn exch cvn .definefontmapaux % recurse with an alias } { pop pop % discard the name } ifelse } if } { pop } ifelse .currentglobal 3 1 roll //true .setglobal dup type /stringtype eq { dup .gcheck not { dup length string copy } if } if 4 -1 roll {.nativeFontmap}{Fontmap} ifelse 3 -1 roll 2 copy .knownget { % Add an element to the end of the existing value, % unless it's the same as the current last element. mark exch aload pop counttomark 4 add -1 roll 2 copy eq { cleartomark pop pop } { ] readonly .growput } ifelse } { % Make a new entry. mark 4 -1 roll ] readonly .growput } ifelse .setglobal } bind def /.definefontmap % <fontname> <file|alias> .definefontmap - { //false 3 1 roll //.definefontmapaux exec } bind def /.definenativefontmap % <fontname> <file|alias> .definenativefontmap - { //true 3 1 roll //.definefontmapaux exec } bind def % Parse a font file just enough to find the FontName or FontType. /.findfontvalue { % <file> <key> .findfontvalue <value> true % <file> <key> .findfontvalue false % Closes the file in either case. exch dup read { 2 copy .unread 16#80 eq { dup (xxxxxx) readstring pop pop % skip .PFB header } if { % Stack: key file % Protect ourselves against syntax errors here. dup { token } stopped { //false exit } if not { //false exit } if % end of file dup /eexec eq { pop //false exit } if % reached eexec section dup /Subrs eq { pop //false exit } if % Subrs without eexec dup /CharStrings eq { pop //false exit } if % CharStrings without eexec dup 3 index eq { xcheck not { dup token exit } if } % found key { pop } ifelse } loop % Stack: key file value true (or) % Stack: key file false dup { 4 } { 3 } ifelse -2 roll closefile pop } { closefile pop //false } ifelse } bind executeonly def /.findfontname { /FontName .findfontvalue } bind def % If there is no FONTPATH, try to get one from the environment. NOFONTPATH { /FONTPATH () def } if /FONTPATH where { pop } { /FONTPATH (GS_FONTPATH) getenv not { () } if def } ifelse % The following are dummy definitions that, if we have a FONTPATH, will % be replaced in the following section. % They are here so immediately evaulation will work, and allow them to % undefined at the bottom of the file. /.scanfontbegin{} bind def /.scanfontdir {} bind def FONTPATH length 0 eq { (%END FONTPATH) .skipeof } if /FONTPATH [ FONTPATH .pathlist ] def FONTPATH { /PermitFileReading exch .addcontrolpath } forall % Scan directories looking for plausible fonts. "Plausible" means that % the file begins with %!PS-AdobeFont or %!FontType1, or with \200\001 % followed by four arbitrary bytes and then either of these strings. % To speed up the search, we skip any file whose name appears in % the Fontmap (with any extension and upper/lower case variation) already, % and any file whose extension definitely indicates it is not a font. % % NOTE: The current implementation of this procedure is somewhat Unix/DOS- % specific. It assumes that '/' and '\' are directory separators, and that % the part of a file name following the last '.' is the extension. % /.lowerstring % <string> .lowerstring <lowerstring> { 0 1 2 index length 1 sub { 2 copy get dup 65 ge exch 90 le and { 2 copy 2 copy get 32 add put } if pop } for } bind def /.splitfilename { % <dir.../base.extn> .basename <base> <extn> % Make the file name read-only to detect aliasing bugs. % We really don't like doing this, but we've had one % such bug already. readonly { (/) search { //true } { (\\) search } ifelse { pop pop } { exit } ifelse } loop dup { (.) search { pop pop } { exit } ifelse } loop 2 copy eq { pop () } { exch dup length 2 index length 1 add sub 0 exch getinterval exch } ifelse } bind def /.scanfontdict 1 dict def % establish a binding /.scanfontbegin { % Construct the table of all file names already in Fontmap. currentglobal //true setglobal //.scanfontdict dup maxlength Fontmap length 2 add .max .setmaxlength Fontmap { exch pop { dup type /stringtype eq { //.splitfilename exec pop //.fonttempstring copy //.lowerstring exec cvn //.scanfontdict exch //true put } { pop } ifelse } forall } forall setglobal } bind def /.scanfontskip mark % Strings are converted to names anyway, so.... /afm //true /bat //true /c //true /cmd //true /com //true /dir //true /dll //true /doc //true /drv //true /exe //true /fon //true /fot //true /h //true /o //true /obj //true /pfm //true /pss //true % Adobe Multiple Master font instances /txt //true .dicttomark def /.scan1fontstring 8192 string def % BeginFont: is not per Adobe documentation, but a few fonts have it. /.scanfontheaders [(%!PS-Adobe*) (%!FontType*) (%%BeginFont:*)] def 0 /.scanfontheaders .systemvar { length .max } forall 6 add % extra for PFB header /.scan1fontfirst exch string def /.scanfontdir % <dirname> .scanfontdir - { currentglobal exch //true setglobal QUIET not { (Scanning ) print dup print ( for fonts...) print flush } if [ 1 index ] (*) .generate_dir_list_templates 0 0 0 4 -1 roll % found scanned files { % stack: <fontcount> <scancount> <filecount> <filename> exch 1 add exch % increment filecount dup //.splitfilename exec //.fonttempstring copy //.lowerstring exec % stack: <fontcount> <scancount> <filecount+1> <filename> % <BASE> <ext> //.scanfontskip exch known exch //.scanfontdict exch known or { pop % stack: <fontcount> <scancount> <filecount+1> } { 3 -1 roll 1 add 3 1 roll % stack: <fontcount> <scancount+1> <filecount+1> <filename> dup (r) { file } //.internalstopped exec { pop pop //null () % stack: <fontcount> <scancount+1> <filecount+1> <filename> % null () } { % On some platforms, the file operator will open directories, % but an error will occur if we try to read from one. % Handle this possibility here. dup //.scan1fontfirst { readstring } //.internalstopped exec { pop pop () } { pop } ifelse % stack: <fontcount> <scancount+1> <filecount+1> % <filename> <file> <header> } ifelse % Check for PFB file header. dup (\200\001????*) .stringmatch { dup length 6 sub 6 exch getinterval } if % Check for font file headers. //false /.scanfontheaders .systemvar { 2 index exch .stringmatch or } forall exch pop { % stack: <fontcount> <scancount+1> <filecount+1> <filename> % <file> dup 0 setfileposition //.findfontname exec { dup .nativeFontmap exch known { pop pop } { exch dup length string copy % copy string exch DEBUG { ( ) print dup =only flush } if 1 index //.definenativefontmap exec //.splitfilename exec pop //true //.scanfontdict 3 1 roll .growput % Increment fontcount. 3 -1 roll 1 add 3 1 roll } ifelse } { pop } ifelse } % .findfontname will have done a closefile in the above case. { dup //null eq { pop } { closefile } ifelse pop } ifelse } ifelse } //.scan1fontstring filenameforall QUIET { pop pop pop } { ( ) print =only ( files, ) print =only ( scanned, ) print =only ( new fonts.) = flush } ifelse pop setglobal } bind executeonly def %END FONTPATH % Try to enumerate native fonts registered with the os % and add them to the fontmap. This relies on a custom % operator which calls platform-specific C code. It % returns an array of arrays, each containing a pair % of strings: what the system thinks is the ps name, % and the access path. /.setnativefontmapbuilt { % set whether we've been run dup type /booleantype eq { systemdict exch /.nativefontmapbuilt exch .forceput } executeonly {pop} ifelse } .bind executeonly odef systemdict /NONATIVEFONTMAP known .setnativefontmapbuilt /.buildnativefontmap { % - .buildnativefontmap <bool> systemdict /.nativefontmapbuilt .knownget not { //false} if {//false} { QUIET not { (Querying operating system for font files...\n) print flush } if .getnativefonts dup { exch { % stack: [ (name) (path) ] % verify the font name ourselves dup 1 get (r) { file } //.internalstopped exec { % skip the entry if we can't open the returned path pop pop pop }{ % we could open the font file mark 2 1 roll {//.findfontname exec} //.internalstopped exec { cleartomark pop } { counttomark 1 add -1 roll pop not { dup 0 get } if % stack: (newname) [ (name) (path) ] % DEBUG { ( found ) print dup print (\n) print flush } if % add entry to the fontmap 1 index exch 0 exch dup type /nametype ne {cvn} if put aload pop //.definenativefontmap exec } ifelse } ifelse } forall } if % record that we've been run //true //.setnativefontmapbuilt } ifelse } bind executeonly odef % Create the dictionary that registers the .buildfont procedure % (called by definefont) for each FontType. /buildfontdict 20 dict def % Register Type 3 fonts, which are always supported, for definefont. buildfontdict 3 /.buildfont3 cvx put % Register Type 0 fonts if they are supported. Strictly speaking, % we should do this in its own file (gs_type0.ps), but since this is % the only thing that would be in that file, it's simpler to put it here. /.buildfont0 where { pop buildfontdict 0 /.buildfont0 cvx put } if % Define definefont. This is a procedure built on a set of operators % that do all the error checking and key insertion. /.growfontdict { % Grow the font dictionary, if necessary, to ensure room for an % added entry, making sure there is at least one slot left for FID. dup maxlength 1 index length sub 2 lt { dup dup wcheck { //.growdict exec} { //.growdictlength exec dict .copydict } ifelse } { dup wcheck not { dup maxlength dict .copydict } if } ifelse } bind def /.completefont { { % Check for disabled platform fonts. NOPLATFONTS { % Make sure we leave room for FID. //.growfontdict exec dup /ExactSize 0 put } { % Hack: if the Encoding looks like it might be the % Symbol or Dingbats encoding, load those now (for the % benefit of platform font matching) just in case % the font didn't actually reference them. % Note that some types of font don't have an Encoding. dup /Encoding .knownget { dup length 65 ge { 64 get dup /congruent eq { SymbolEncoding pop } if /a9 eq { DingbatsEncoding pop } if } { pop } ifelse } if } ifelse dup /OrigFont known not { dup dup /OrigFont exch .growput } if //true exch % If this is a CIDFont, CIDFontType takes precedence % over FontType. dup /CIDFontType known { /.buildcidfont where { pop exch not exch % true => false } if } if exch { dup /FontType get //buildfontdict exch get } { {.buildcidfont} % so it gets bound } ifelse } stopped { $error /command get /invalidfont signalerror } if % Execute the .buildxxxfontx outside the 'stopped', because we don't % want its errors converted to invalidfont. exec { systemdict /ProvideUnicode .knownget not { //false } if { /FontEmulationProcs /ProcSet findresource /ProvideUnicodeDecoding get exec } if readonly % stack: name fontdict } stopped { $error /command get /invalidfont signalerror } if } bind executeonly odef /definefont { dup rcheck not { /definefont cvx /invalidaccess signalerror } if /definefont cvx {.completefont} .errorexec % If the current allocation mode is global, also enter % the font in LocalFontDirectory. .currentglobal { //systemdict /LocalFontDirectory .knownget { 2 index 2 index .forceput } % readonly if } if dup //.FontDirectory 4 -2 roll .forceput % readonly % If the font originated as a resource, register it. currentfile .currentresourcefile eq { dup .registerfont } if readonly } .bind executeonly odef % Define a procedure for defining aliased fonts. % We use this only for explicitly aliased fonts, not substituted fonts: % we think this matches the observed behavior of Adobe interpreters. /.aliasfont % <name> <font> .aliasfont <newFont> { currentglobal 3 1 roll dup gcheck setglobal % <bool> <name> <font> dup length 2 add dict % <bool> <name> <font> <dict> dup 3 -1 roll % <bool> <name> <dict> <dict> <font> { 1 index /FID eq { pop pop } { put dup } ifelse } forall % <bool> <name> <dict> <dict> % Stack: global fontname newfont newfont. % We might be defining a global font whose FontName % is a local string. This is weird, but legal, % and doesn't cause problems anywhere else: % to avoid any possible problems in this case, do a cvn. % We might also be defining (as an alias) a global font % whose FontName is a local non-string, if someone passed a % garbage value to findfont. In this case, just don't % call definefont at all. 2 index dup type /stringtype eq exch gcheck or 1 index gcheck not or { pop % <bool> <name> <dict> 1 index dup type /stringtype eq { cvn } if % <bool> <name> <dict> <name1> % HACK: % We want to know whether we alias a font, % because in this case its FontName to be replaced with the alias. % There is no simple way to know that at this point. % But if the original font has defaultfontname, % we probably substitute it rather than alias. % Using such condition as an approximation to the strong condition. % % Note it works wrongly if Fontmap maps something to defaultfontname like this : % /Courier /NimbusMonL-Regu ; % /Something /Courier ; % The FontName of Something will not be /Something. It will be /Courier . % 1 index /FontName get defaultfontname ne { 2 copy /FontName exch put } if 1 index exch /.Alias exch put % <bool> <name> <dict> dup dup /OrigFont exch .growput % Don't bind in definefont, since Level 2 redefines it. /definefont .systemvar exec } { /findfont cvx {.completefont} //.errorexec exec pop exch pop } ifelse exch setglobal } bind executeonly odef % so findfont will bind it % Define .loadfontfile for loading a font. If we recognize Type 1 and/or % TrueType fonts, gs_type1.ps and/or gs_ttf.ps will redefine this. /.loadfontfile { % According to Ed Taft, Adobe interpreters push userdict % before loading a font, and pop it afterwards. userdict begin cvx exec end } bind def /.setloadingfont { //systemdict /.loadingfont 3 -1 roll .forceput } .bind executeonly odef % .forceput must be bound and hidden /.loadfont { % Some buggy fonts leave extra junk on the stack, % so we have to make a closure that records the stack depth % in a fail-safe way. //true .setloadingfont { /FAPI_hook_disable pop % gs_fapi accesses this with execstack_lookup - don't remove ! {{.loadfontfile} .execasresource} count 1 sub 2 .execn count exch sub { pop } repeat exit } loop % this loop is a pattern for execstack_lookup, don't remove ! //false .setloadingfont } bind def % Find an alternate font to substitute for an unknown one. % We go to some trouble to parse the font name and extract % properties from it. Later entries take priority over earlier. /.substitutefaces [ % Define substitutes for the fonts we define in Fontmap.GS [(Charter) /Times 0] [(Utopia) /Times 0] [(Antiqua) /Times 0] [(Calligraphic) /Helvetica 0] [(Hershey) /Times 0] % Guess at suitable substitutions for random unknown fonts. [(Book) /NewCenturySchlbk 0] [(Grot) /Helvetica 0] [(Roman) /Times 0] [(Chancery) /ZapfChancery-MediumItalic 0] % If the family name appears in the font name, % use a font from that family. [(Arial) /Helvetica 0] [(Avant) /AvantGarde 0] [(Bookman) /Bookman 0] [(Century) /NewCenturySchlbk 0] [(Cour) /Courier 0] [(Frut) /Helvetica 0] [(Garamond) /Palatino 0] [(Geneva) /Helvetica 0] [(Helv) /Helvetica 0] [(NewYork) /Bookman 0] [(Pala) /Palatino 0] [(Schlbk) /NewCenturySchlbk 0] [(Swiss) /Helvetica 0] [(Symbol) /Symbol 0] [(Times) /Times 0] % Substitute for Adobe Multiple Master fonts. [(Minion) /Times 0] [(Myriad) /Helvetica 0] % If the font wants to be monospace, use Courier. [(Monospace) /Courier 0] [(Typewriter) /Courier 0] % Define substitutes for the other Adobe PostScript 3 fonts. % For some of them, the substitution is pretty bad! [(Albertus) /Palatino 0] [(AntiqueOlive) /Helvetica 0] [(Bodoni) /NewCenturySchlbk 0] [(Chicago) /Helvetica 2] [(Clarendon) /Bookman 0] [(Cooper) /NewCenturySchlbk 0] [(Copperplate) /AvantGarde 0] % inappropriate, small-cap font [(Coronet) /ZapfChancery-MediumItalic 0] [(Eurostile) /Helvetica 0] [(Geneva) /Courier 2] % should be fixed-pitch sans demi [(GillSans) /Helvetica 2] [(GillSans-Light) /Helvetica 0] [(Goudy) /Palatino 0] [(Hoefler) /NewCenturySchlbk 0] [(Joanna) /Times 0] [(LetterGothic) /Courier 0] % should be fixed-pitch sans [(LubalinGraph-Book) /Bookman 2] [(LubalinGraph-Demi) /Bookman 0] [(Marigold) /ZapfChancery-MediumItalic 0] [(MonaLisa-Recut) /Palatino 0] % inappropriate [(Monaco) /Courier 2] % should be fixed-pitch sans demi [(Optima) /Helvetica 0] [(Oxford) /ZapfChancery-MediumItalic 0] [(Tekton) /Helvetica 0] [(Univers) /Helvetica 0] ] readonly def /.substituteproperties [ [(It) 1] [(Oblique) 1] [(Black) 2] [(Bd) 2] [(Bold) 2] [(bold) 2] [(Demi) 2] [(Heavy) 2] [(Sb) 2] [(Cn) 4] [(Cond) 4] [(Narrow) 4] [(Pkg) 4] [(Compr) 4] [(Serif) 8] [(Sans) -8] ] readonly def /.fontnamestring { % <fontname> .fontnamestring <string|name> dup type dup /nametype eq { pop .namestring } { /stringtype ne { pop () } if } ifelse } bind def /.fontnameproperties { % <int> <string|name> .fontnameproperties % <int'> //.fontnamestring exec //.substituteproperties { 2 copy 0 get search { pop pop pop dup length 1 sub 1 exch getinterval 3 -1 roll exch { dup 0 ge { or } { neg not and } ifelse } forall exch } { pop pop } ifelse } forall pop } bind def /.substitutefamilies mark /AvantGarde {/AvantGarde-Book /AvantGarde-BookOblique /AvantGarde-Demi /AvantGarde-DemiOblique} /Bookman {/Bookman-Demi /Bookman-DemiItalic /Bookman-Light /Bookman-LightItalic} /Courier {/Courier /Courier-Oblique /Courier-Bold /Courier-BoldOblique} /Helvetica {/Helvetica /Helvetica-Oblique /Helvetica-Bold /Helvetica-BoldOblique /Helvetica-Narrow /Helvetica-Narrow-Oblique /Helvetica-Narrow-Bold /Helvetica-Narrow-BoldOblique} /NewCenturySchlbk {/NewCenturySchlbk-Roman /NewCenturySchlbk-Italic /NewCenturySchlbk-Bold /NewCenturySchlbk-BoldItalic} /Palatino {/Palatino-Roman /Palatino-Italic /Palatino-Bold /Palatino-BoldItalic} /Symbol {/Symbol /Symbol /Symbol /Symbol} /Times {/Times-Roman /Times-Italic /Times-Bold /Times-BoldItalic} /ZapfChancery-MediumItalic {/ZapfChancery-MediumItalic} .dicttomark readonly def /.nametostring { % <name> .nametostring <string> % <other> .nametostring <other> dup type /nametype eq { .namestring } if } bind def /.substitutefontname { % <fontname> <properties> .substitutefontname % <altname|null> % Look for properties and/or a face name in the font name. % If we find any, use Times (serif) or Helvetica (sans) as the % base font; otherwise, use the default font. % Note that the "substituted" font name may be the same as % the requested one; the caller must check this. exch //.fontnamestring exec { defaultfontname /Helvetica-Oblique /Helvetica-Bold /Helvetica-BoldOblique /Helvetica-Narrow /Helvetica-Narrow-Oblique /Helvetica-Narrow-Bold /Helvetica-Narrow-BoldOblique /Times-Roman /Times-Italic /Times-Bold /Times-BoldItalic /Helvetica-Narrow /Helvetica-Narrow-Oblique /Helvetica-Narrow-Bold /Helvetica-Narrow-BoldOblique } 3 1 roll % Stack: facelist properties fontname % Look for a face name. //.substitutefaces { 2 copy 0 get search { pop pop pop % Stack: facelist properties fontname [(pattern) family properties] dup 2 get 4 -1 roll or 3 1 roll 1 get //.substitutefamilies exch get 4 -1 roll pop 3 1 roll } { pop pop } ifelse } forall pop 1 index length mod get exec } bind executeonly odef /.substitutefont { % <fontname> .substitutefont <altname> dup 0 exch //.fontnameproperties exec .substitutefontname % Only accept fonts known in the Fontmap. Fontmap 1 index known not { .nativeFontmap 1 index known not {pop defaultfontname } if } if } bind executeonly odef % If requested, make (and recognize) fake entries in FontDirectory for fonts % present in Fontmap but not actually loaded. Thanks to Ray Johnston for % the idea behind this code. FAKEFONTS not { (%END FAKEFONTS) .skipeof } if % We use the presence or absence of the FontMatrix key to indicate whether % a font is real or fake. We must pop the arguments at the very end, % so that stack protection will be effective. /definefont { % <name> <font> definefont <font> dup /FontMatrix known { //definefont } { 2 copy /FontName get findfont //definefont exch pop exch pop } ifelse } bind odef /scalefont { % <font> <scale> scalefont <font> 1 index /FontMatrix known { //scalefont } { 1 index /FontName get findfont 1 index //scalefont exch pop exch pop } ifelse } bind odef /makefont { % <font> <matrix> makefont <font> 1 index /FontMatrix known { //makefont } { 1 index /FontName get findfont 1 index //makefont exch pop exch pop } ifelse } bind odef /setfont { % <font> setfont - dup /FontMatrix known { //setfont } { dup /FontName get findfont //setfont pop } ifelse } bind odef %END FAKEFONTS % Define findfont so it tries to load a font if it's not found. % The Red Book requires that findfont be a procedure, not an operator, % but it still needs to restore the stacks reliably if it fails, % so we do all the work in an operator. /.findfont { % <fontname> .findfont <font> mark 1 index % <fontname> mark <fontname> //systemdict begin .dofindfont % <fontname> mark <alias> ... <font> % Define any needed aliases. counttomark 1 sub { .aliasfont } repeat end % <fontname> mark <font> exch pop exch pop } bind odef /findfont { .findfont } bind def % Check whether the font name we are about to look for is already on the list % of aliases we're accumulating; if so, cause an error. /.checkalias % -mark- <alias1> ... <name> .checkalias <<same>> { counttomark 1 sub -1 1 { index 1 index eq { pop QUIET not { (Unable to substitute for font.) = flush } if /findfont cvx /invalidfont signalerror } if } for } bind def % Get a (non-fake) font if present in a FontDirectory. /.fontknownget % <fontdir> <fontname> .fontknownget <font> true % <fontdir> <fontname> .fontknownget false { .knownget { FAKEFONTS { dup /FontMatrix known { //true } { pop //false } ifelse } { //true } ifelse } { //false } ifelse } bind def % This is the standard procedure for handling font substitution. % Its location is per an Adobe newsgroup posting. % It is called with the font name on the stack, standing in for findfont. /.stdsubstfont { % mark <alias1> ... <fontname> .stdsubstfont mark <alias1> ... <aliasN> <font> /SUBSTFONT where { pop QUIET not { (Substituting for font ) print dup =only (.) = flush } if % No aliasing. % This mode is incompatible with high level devices. cleartomark mark defaultfontname } { dup .substitutefont 2 copy eq { pop defaultfontname } if //.checkalias exec QUIET not { SHORTERRORS { (%%[) print 1 index =only ( not found, substituting ) print dup =only (]%%) } { (Substituting font ) print dup =only ( for ) print 1 index =only (.) } ifelse = flush } if } ifelse /Font findresource } bind executeonly def % Default font substitution does {pop /Courier} om many implementations. % GS post-process font substitution in .stdsubstfont and uses {} for % backward compatibility $error /SubstituteFont { } put % Scan the next directory on FONTPATH. /.scannextfontdir { % - .scannextfontdir <bool> % If we haven't scanned all the directories in % FONTPATH, scan the next one. //null 0 1 FONTPATH length 1 sub { FONTPATH 1 index get //null ne { exch pop exit } if pop } for dup //null ne { dup 0 eq { //.scanfontbegin exec} if FONTPATH 1 index get //.scanfontdir exec FONTPATH exch //null put //true } { pop //false } ifelse } bind def % Do the work of findfont, including substitution, defaulting, and % scanning of FONTPATH. /.dofindfont { % mark <fontname> .dofindfont % mark <alias> ... <font> .tryfindfont not { % We didn't find the font. If we haven't scanned % all the directories in FONTPATH, scan the next one % now and look for the font again. //.scannextfontdir exec { % Start over with an empty alias list. counttomark 1 sub { pop } repeat % mark <fontname> .dofindfont } { % No more directories to scan. Try building the native % font map entries if we haven't already done so. .buildnativefontmap { % Same stack as at the beginning of .dofindfont. .dofindfont % start over } { % No luck. Make sure we're not already % looking for the default font. QUIET not { (Didn't find this font on the system!\n) print } if dup defaultfontname eq { QUIET not { (Unable to load default font ) print dup =only (! Giving up.) = flush } if /findfont cvx /invalidfont signalerror } if % Substitute for the font. Don't alias. % Same stack as at the beginning of .dofindfont. $error /SubstituteFont get exec % % igorm: I guess the surrounding code assumes that .stdsubstfont % must ADD an alias to allow .checkalias and .findfont to work properly. % Also I guess that a trailing recursion is % used in .dofindfont and through .stdsubstfont % just to represent a simple iteration, % which accumulates the aliases after the mark. //.stdsubstfont exec } ifelse } ifelse } if } bind executeonly def % any user of .putgstringcopy must use bind and executeonly /.putgstringcopy % <dict> <name> <string> .putgstringcopy - { 2 index gcheck currentglobal 2 copy eq { pop pop .forceput } executeonly { 5 1 roll setglobal dup length string copy .forceput setglobal } executeonly ifelse } .bind executeonly odef % must be bound and hidden for .forceput /.loadfontloop { % <fontname> <filename> <libflag> .loadfontloop % <font> true % -or- % <fontname> false % See above regarding the use of 'loop'. { % Is the font name a string? 1 index type /stringtype ne { pop QUIET not { (Can't find font with non-string name: ) print dup =only (.) = flush } if pop //false exit } if % check <libflag> { findlibfile not } { //true } ifelse % if findlibfile didn't work, try just opening the file direcly. { dup (r) { file } stopped { pop pop //true } { //false } ifelse } { //false }ifelse % If just opening the file didn't work, try opening the file name % in the font resource directory { dup //.fonttempstring /FontResourceDir getsystemparam .genericrfn (r) { file } stopped { pop pop //true } { dup .filename { 3 -1 roll pop exch } { pop } ifelse //false } ifelse } { //false }ifelse { QUIET not { (Can't find \(or can't open\) font file ) print dup print (.) = flush } if pop //false exit } if % Stack: fontname fontfilename fontfile QUIET not { (Loading ) print 2 index =only ( font from ) print 1 index print (... ) print flush } if % If LOCALFONTS isn't set, load the font into local or global % VM according to FontType; if LOCALFONTS is set, load the font % into the current VM, which is what Adobe printers (but not % DPS or CPSI) do. LOCALFONTS { //false } { /setglobal where } ifelse { pop /FontType .findfontvalue { 1 eq } { //false } ifelse % .setglobal, like setglobal, aliases FontDirectory to % GlobalFontDirectory if appropriate. However, we mustn't % allow the current version of .setglobal to be bound in, % because it's different depending on language level. .currentglobal exch /.setglobal .systemvar exec % Remove the fake definition, if any. //.FontDirectory 3 index .forceundef % readonly 1 index (r) file .loadfont //.FontDirectory exch /.setglobal .systemvar exec } executeonly { .loadfont //.FontDirectory } ifelse % Stack: fontname fontfilename fontdirectory QUIET not { //systemdict /level2dict known { .currentglobal //false .setglobal vmstatus //true .setglobal vmstatus 3 -1 roll pop 6 -1 roll .setglobal 5 } { vmstatus 3 } ifelse { =only ( ) print } repeat (done.) = flush } if % Check to make sure the font was actually loaded. dup 3 index //.fontknownget exec { dup /PathLoad 4 index //.putgstringcopy 4 1 roll pop pop pop //true exit } executeonly if % Maybe the file had a different FontName. % See if we can get a FontName from the file, and if so, % whether a font by that name exists now. exch dup % Stack: origfontname fontdirectory path path (r) file //.findfontname exec { % Stack: origfontname fontdirectory path filefontname 2 index 1 index //.fontknownget exec { % Yes. Stack: origfontname fontdirectory path filefontname fontdict dup 4 -1 roll /PathLoad exch //.putgstringcopy % Stack: origfontname fontdirectory filefontname fontdict 3 -1 roll pop % Stack: origfontname filefontname fontdict dup /FontName get dup //.FontDirectory exch .forceundef /GlobalFontDirectory .systemvar exch .forceundef dup length dict .copydict dup 3 index /FontName exch put 2 index exch definefont exch QUIET { pop } { (Using ) print =only ( font for ) print 1 index =only (.) = flush } ifelse % Stack: origfontname fontdict exch pop //true exit % Stack: fontdict } executeonly if pop % Stack: origfontname fontdirectory path } executeonly if pop pop % Stack: origfontname % The font definitely did not load correctly. QUIET not { (Loading ) print dup =only ( font failed.) = flush } if //false exit } loop % end of loop } bind executeonly def % must be bound and hidden for .putgstringcopy % Attempt to load a font from a file. /.tryloadfont { % <fontname> .tryloadfont <font> true % <fontname> .tryloadfont false dup //.nametostring exec % Hack: check for the presence of the resource machinery. /.genericrfn where { pop pop dup //.fonttempstring /FontResourceDir getsystemparam .genericrfn {//false //.loadfontloop exec} //.internalstopped exec {//false} if { //true } { dup //.nametostring exec {//true //.loadfontloop exec} //.internalstopped exec {//false} if } ifelse } { {//true //.loadfontloop exec} //.internalstopped exec {//false} if } ifelse } bind def % Try to find a font using only the present contents of Fontmap. /.tryfindfont { % <fontname> .tryfindfont <font> true % <fontname> .tryfindfont false //.FontDirectory 1 index //.fontknownget exec { % Already loaded exch pop //true } { dup Fontmap exch .knownget { //true //true } { % Unknown font name. Look for a file with the % same name as the requested font. dup //.tryloadfont exec { exch pop //true //false } { % if we can't load by name check the native font map .nativeFontmap exch .knownget { //true //true } { //false //false } ifelse } ifelse } ifelse { % Try each element of the Fontmap in turn. pop //false exch % (in case we exhaust the list) % Stack: fontname false fontmaplist { exch pop dup type /nametype eq { % Font alias //.checkalias exec dup .tryfindfont { % We don't want to reuse an embedded font as a substitute % so make sure the font came from disk before using it. dup /Path known 1 index /PathLoad known or { exch pop //true exit } { % if the candidate didn't come from disk, remove it from % FontDirectory and try again. pop dup undefinefont .tryfindfont exit } ifelse } if } { dup dup type dup /arraytype eq exch /packedarraytype eq or exch xcheck and { % Font with a procedural definition exec % The procedure will load the font. % Check to make sure this really happened. //.FontDirectory 1 index .knownget { exch pop //true exit } if } { % Font file name dup type /dicttype eq { begin Path } { 1 dict begin } ifelse //true //.loadfontloop exec end { //true exit } if } ifelse } ifelse //false } forall % Stack: font true -or- fontname false { //true } { % None of the Fontmap entries worked. % Try loading a file with the same name % as the requested font. //.tryloadfont exec } ifelse } if } ifelse } bind executeonly def % Define a procedure to load all known fonts. % This isn't likely to be very useful. /loadallfonts { [Fontmap .nativeFontmap] { { pop findfont pop } forall } forall } bind def % If requested, load all the fonts defined in the Fontmap into FontDirectory % as "fake" fonts i.e., font dicts with only FontName and FontType defined. % (We define FontType only for the sake of some questionable code in the % Apple Printer Utility 2.0 font inquiry code.) % % Note that this procedure only creates fake fonts in the FontDirectory % associated with the current VM. This is because in multi-context systems, % creating the fake fonts in local VM leads to undesirable complications. /.definefakefonts { } { (gs_fonts FAKEFONTS) VMDEBUG [Fontmap .nativeFontmap ] { { pop dup type /stringtype eq { cvn } if //.FontDirectory 1 index known not { 2 dict dup /FontName 3 index put dup /FontType 1 put //.FontDirectory 3 1 roll //.forceput exec % readonly } { pop } ifelse } forall } forall } executeonly % hide .forceput FAKEFONTS { exch } if pop def % don't bind, .current/setglobal get redefined % Install initial fonts from Fontmap. /.loadinitialfonts { NOFONTMAP not { /FONTMAP where { pop [ FONTMAP //.pathlist exec] { dup VMDEBUG findlibfile { exch pop //.loadFontmap exec } { /undefinedfilename signalerror } ifelse } } { LIBPATH { defaultfontmap //false .file_name_combine { dup VMDEBUG (r) { file } //.internalstopped exec { pop pop defaultfontmap_content { .definefontmap } forall } { //.loadFontmap exec } ifelse } { pop pop } ifelse } } ifelse forall } if userdict /defaultfontmap_content .undef //.definefakefonts exec % current VM is global } def % don't bind, .current/setglobal get redefined % Undef these, not needed outside this file [ % /.fonttempstring /.scannextfontdir - are also used in gs_res.ps, so are undefined there % /.scanfontheaders - used in gs_cff.ps, gs_ttf.ps /.loadfontloop /.tryloadfont /.findfont /.pathlist /.loadFontmap /.lowerstring /.splitfilename /.scanfontdict /.scanfontbegin /.scanfontskip /.scan1fontstring /.scan1fontfirst /.scanfontdir /.setnativefontmapbuilt /.aliasfont /.setloadingfont /.substitutefaces /.substituteproperties /.substitutefamilies /.nametostring /.fontnamestring /.checkalias /.fontknownget /.stdsubstfont /.putgstringcopy /.definenativefontmap /.findfontname /.addfontmappermitpaths /.splitdirname ] systemdict .undefinternalnames pdf_base.ps 0000644 00000166617 15030647507 0006703 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % pdf_base.ps % Basic parser for PDF reader. % This handles basic parsing of the file (including the trailer % and cross-reference table), as well as objects, object references, % streams, and name/number trees; it doesn't include any facilities for % making marks on the page. /.setlanguagelevel where { pop 2 .setlanguagelevel } if .currentglobal //true .setglobal pdfdict begin % Define the name interpretation dictionary for reading values. /valueopdict mark (<<) cvn { mark } bind executeonly % don't push an actual mark! (>>) cvn { { .dicttomark } stopped { ( **** Error: File has an unbalanced >> \(close dictionary\).\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror } if } bind executeonly ([) cvn { mark } bind executeonly % ditto (]) cvn dup load % /true true % see .pdfexectoken below % /false false % ibid. % /null null % ibid. /F dup cvx % see Objects section below /R dup cvx % see Objects section below /stream dup cvx % see Streams section below .dicttomark readonly def % ------ Utilities ------ % % Define a scratch string. The PDF language definition says that % no line in a PDF file can exceed 255 characters, but this string % is also used to search for %PDF-, which needs 1024 characters. /pdfstring 1024 string def % Handle the PDF 1.2 #nn escape convention when reading from a file. % This should eventually be done in C. /.pdffixname { % <execname> .pdffixname <execname'> PDFversion 1.2 ge { dup .namestring (#) search { name#escape cvn exch pop } { pop } ifelse } if } bind executeonly def /name#escape % <post> <(#)> <pre> name#escape <string> { exch pop 1 index 2 () /SubFileDecode filter dup (x) readhexstring % Stack: post pre stream char t/f not { % tolerate, but complain about bad syntax pop closefile (#) concatstrings exch ( **** Error: Invalid hex following '#' name escape, using literal '#' in name.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror } { exch closefile concatstrings exch 2 1 index length 2 sub getinterval } ifelse (#) search { name#escape } if concatstrings } bind executeonly def /num-chars-dict mark (0123456789-.) {dup} forall .dicttomark readonly def % Execute a file, interpreting its executable names in a given % dictionary. The name procedures may do whatever they want % to the operand stack. /.pdftokenerror { % <count> <opdict> <errtoken> .pdftokenerror - % if we're called prior to actually drawing the page contents % (i.e. for pageusestransparency) BXlevel may not be defined, yet. /BXlevel where {/BXlevel get 0 le}{//true} ifelse { ( **** Error: Unknown operator: ') pdfformaterror dup =string cvs pdfformaterror (') pdfformaterror % Attempt a retry scan of the element after changing to PDFScanInvNum << /PDFScanInvNum //true >> setuserparams =string cvs token pop exch pop dup type dup /integertype eq exch /realtype eq or { exch pop exch pop (, processed as number, value: ) pdfformaterror dup =string cvs pdfformaterror (\n) pdfformaterror << /PDFScanInvNum //null >> setuserparams % reset to default scanning rules //false % suppress any stack cleanup } { % error was non-recoverable with modified scanning rules, continue. dup type /nametype eq { //true 1 index .namestring { //num-chars-dict exch known and } forall { % perhaps, it's a malformed number. PDFSTOPONERROR {//true}{ pop pop pop 0 //false ( looks like a malformed number, replacing with 0.) pdfformaterror } ifelse } { //true % punt } ifelse } { //true % punt } ifelse (\n) pdfformaterror } ifelse } { //true } ifelse { % clean up the operand stack if this was non-recoverable pop pop count exch sub { pop } repeat % pop all the operands } if ( Output may be incorrect.\n) pdfformaterror } bind executeonly def currentdict /num-chars-dict .undef /.pdfexectoken { % <count> <opdict> <exectoken> .pdfexectoken ? PDFDEBUG { //pdfdict /PDFSTEPcount known not { //pdfdict /PDFSTEPcount 1 .forceput } executeonly if PDFSTEP { //pdfdict /PDFtokencount 2 copy .knownget { 1 add } { 1 } ifelse .forceput PDFSTEPcount 1 gt { //pdfdict /PDFSTEPcount PDFSTEPcount 1 sub .forceput } executeonly { dup ==only ( step # ) print PDFtokencount =only ( ? ) print flush 1 //false .outputpage (%stdin) (r) file 255 string readline { token { exch pop //pdfdict /PDFSTEPcount 3 -1 roll .forceput } executeonly { //pdfdict /PDFSTEPcount 1 .forceput } executeonly ifelse % token } { pop /PDFSTEP //false def % EOF on stdin } ifelse % readline } ifelse % PDFSTEPcount > 1 } executeonly { dup ==only () = flush } ifelse % PDFSTEP } executeonly if % PDFDEBUG 2 copy .knownget { exch pop exch pop exch pop exec } { % Normally, true, false, and null would appear in opdict % and be treated as "operators". However, there is a % special fast case in the PostScript interpreter for names % that are defined in, and only in, systemdict and/or % userdict: putting these three names in the PDF dictionaries % destroys this property for them, slowing down their % interpretation in all PostScript code. Therefore, we % check for them explicitly here instead. dup dup dup /true eq exch /false eq or exch /null eq or { exch pop exch pop //systemdict exch get } { % Hackish fix to detect missing whitespace after "endobj". Yet another % problem that (you guessed it!) Adobe Acrobat ignores silently dup .namestring (endobj) anchorsearch { ( **** Error: Missing whitespace after 'endobj'.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror pop pop pop exch pop /endobj get exec } { %% First, lets try and see if this 'might' be a broken number %% we look for 0-9 as well as '.' ',' and '-' to permit those %% locales in which the separator is a comma, as well as negative %% numbers. We've seena t least one tool replace '0' with '-' *sometimes* //true exch dup length 1 sub 0 1 3 -1 roll { 1 index exch get dup 44 lt { pop exch pop //false exch exit }{ dup 57 gt { pop exch pop //false exch exit }{ dup 47 eq { pop exch pop //false exch exit }{ pop } ifelse } ifelse } ifelse } for pop { %% If it looks like a number, try to deal with it as such PDFSTOPONERROR { dup .pdftokenerror }{ dup {.pdftokenerror} stopped } ifelse { pop %% But if it fails, fall back to converting into a anem. %% This will propagate through and cause different %% fallback code to try and take care ot if. cvlit exch pop exch pop }{ exch pop } ifelse }{ %% Doesn't look like a number, convert it into a name cvlit exch pop exch pop } ifelse } ifelse } ifelse } ifelse } bind executeonly def /PDFScanRules_true << /PDFScanRules //true >> def /PDFScanRules_null << /PDFScanRules //null >> def /.pdfrun { % <file> <opdict> .pdfrun - % Construct a procedure with the stack depth, file and opdict % bound into it. 1 index cvlit % file <<>> file count 2 sub % file <<>> file cnt 3 1 roll mark % file cnt <<>> file [ /PDFScanRules .getuserparam //null eq { //PDFScanRules_true { setuserparams } 0 get % force PDF scanning mode mark 7 4 roll } { mark 5 2 roll % file [ [ cnt <<>> file } ifelse { % Stack: ..operands.. count opdict file { token } stopped { dup type /filetype eq { pop } if pop pop stop } if { dup type /nametype eq { dup xcheck { .pdfexectoken } { .pdffixname exch pop exch pop PDFDEBUG { PDFSTEPcount 1 le { dup ==only ( ) print flush } if } if } ifelse } { exch pop exch pop PDFDEBUG { PDFSTEPcount 1 le { dup ==only ( ) print flush } if } if } ifelse } { pop pop exit } ifelse } aload pop //.packtomark exec cvx % file [ {cnt <<>> file ... } { loop } 0 get 2 packedarray cvx % file [ { {cnt <<>> file ... } loop } PDFSTOPONERROR { {exec //false} } { {stopped} } ifelse aload pop % file [ { {cnt <<>> file ... } loop } stopped /PDFScanRules .getuserparam //null eq { //PDFScanRules_null { setuserparams } 0 get % reset PDF scannig mode if it was off } if /PDFsource PDFsource % file [ { {cnt <<>> file ... } loop } stopped /PDFsource PDFsource { store { /StreamRunAborted //true store ( **** Error reading a content stream. The page may be incomplete.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror } if } aload pop % file [ { {cnt <<>> file ... } loop } stopped /PDFsource PDFsource store {...} if //.packtomark exec cvx % file { { {cnt <<>> file ... } loop } stopped /PDFsource PDFsource store {...} if} /PDFsource 3 -1 roll store % {...} exec } bind executeonly def % Execute a file, like .pdfrun, for a marking context. % This temporarily rebinds LocalResources and DefaultQstate. /.pdfruncontext { % <resdict> <file> <opdict> .pdfruncontext - /.pdfrun load LocalResources DefaultQstate % res file op .pdfrun Loc Qst /LocalResources 7 -1 roll % file op .pdfrun Loc Qst /Loc res dup 4 index ne { % Ensure Loc != res to avoid self-referencing /ParentResources dup /ParentResources 5 index put % save the parent LocalResources } if store % store new LocalResources /DefaultQstate qstate store 3 .execn /DefaultQstate exch store /LocalResources exch store } bind executeonly def % Get the depth of the PDF operand stack. The caller sets pdfemptycount % before calling .pdfrun or .pdfruncontext. It is initially set by % pdf_main, and is also set by any routine which changes the operand % stack depth (currently .pdfpaintproc, although there are other callers % of .pdfrun{context} which have not been checked for opstack depth. /.pdfcount { % - .pdfcount <count> count pdfemptycount sub } bind executeonly def % Read a token, but simply return false (no token read) in the case of an % error. This is messy because 'token' either may or may not pop its operand % if an error occurs, and because the return values are different depending % on whether the source is a file or a string. To avoid closing the file % check for '{' before trying 'token'. /token_nofail_dict mark ( ) { dup ( ) readstring pop pop } bind executeonly (\t) 1 index (\r) 1 index (\n) 1 index (\000) 1 index ({) { //null //true exit } bind executeonly .dicttomark def /token_nofail { % <file|string> token_nofail false % <file> token_nofail <token> true % <string> token_nofail <post> <token> true dup type /filetype eq { { dup ( ) .peekstring not { ({) } if //token_nofail_dict exch .knownget not { //null 1 index { token } //.internalstopped exec exit } if exec } loop { % stack: source null [source] //null ne { pop } if pop //false } { % stack: source null ([post] token true | false) { 3 1 roll pop pop //true } { pop pop //false } ifelse } ifelse } { //null 1 index % stack: source null source { token } //.internalstopped exec { % stack: source null [source] //null ne { pop } if pop //false } { % stack: source null ([post] token true | false) { 4 2 roll pop pop //true } { pop pop //false } ifelse } ifelse } ifelse } bind executeonly def currentdict /token_nofail_dict .undef % ================================ Objects ================================ % % We keep track of PDF objects using the following PostScript variables: % % Generations (string): Generations[N] holds 1+ the current % generation number for object number N. (As far as we can tell, % this is needed only for error checking.) For free objects, % Generations[N] is 0. % % Objects (array): If object N is loaded, Objects[N] is the actual % object; otherwise, Objects[N] is an executable integer giving % the file offset of the object's location in the file. If % ObjectStream[N] is non-zero then Objects[N] contains the index % into the object stream instead of the file offset of the object. % % ObjectStream (array): If object N is in an object stream then % ObjectStream[N] holds the object number of the object stream. % Otherwise ObjectStream[N] contains 0. If ObjectStream[N] % is non-zero then Objects[N] contains the index into the object % stream. % % GlobalObjects (dictionary): If object N has been resolved in % global VM, GlobalObjects[N] is the same as Objects[N] % (except that GlobalObjects itself is stored in global VM, % so the entry will not be deleted at the end of the page). % % IsGlobal (string): IsGlobal[N] = 1 iff object N was resolved in % global VM. This is an accelerator to avoid having to do a % dictionary lookup in GlobalObjects when resolving every object. % Initialize the PDF object tables. /initPDFobjects { % - initPDFobjects - /ObjectStream 0 array def /Objects 0 array def /Generations 0 string def .currentglobal //true .setglobal /GlobalObjects 20 dict def .setglobal /IsGlobal 0 string def } bind executeonly def % Grow the tables to a specified size. /growPDFobjects { % <minsize> growPDFobjects - dup ObjectStream length gt { dup ObjectStream exch array dup 3 1 roll copy pop /ObjectStream exch def } if dup Objects length gt { dup Objects exch array dup 3 1 roll copy pop /Objects exch def } if dup Generations length gt { %% Initiallly Generations is a string, but the xref rebuilding code %% can convert it to an array (/setxrefentry in pdf_rbld.ps). So we %% need to be able to deal with either case. Generations type /stringtype eq { dup Generations exch string dup 3 1 roll copy pop /Generations exch def } { dup Generations exch array dup 3 1 roll copy pop /Generations exch def } ifelse } if dup IsGlobal length gt { dup IsGlobal exch string dup 3 1 roll copy pop /IsGlobal exch def } if pop } bind executeonly def % We represent an unresolved object reference by a procedure of the form % {obj# gen# resolveR}. This is not a possible PDF object, because PDF has % no way to represent procedures. Since PDF in fact has no way to represent % any PostScript object that doesn't evaluate to itself, we can 'force' % a possibly indirect object painlessly with 'exec'. % Note that since we represent streams by executable dictionaries % (see below), we need both an xcheck and a type check to determine % whether an object has been resolved. /resolved? { % <object#> resolved? <value> true % <object#> resolved? false Objects 1 index get dup xcheck { % Check if executable dup type /integertype eq { % Check if an integer % Check whether the object is in GlobalObjects. pop IsGlobal 1 index get 0 eq { % 0 --> Not in GlabalObjects pop //false % The object is not resolved } { % The object is in GlobalObjects % Update Objects from GlobalObjects PDFDEBUG { (%Global=>local: ) print dup //== exec } if GlobalObjects 1 index get dup Objects 4 1 roll put //true } ifelse } { % Else object is executable but not integer exch pop //true % Therefore must be executable dict. (stream) } ifelse } { % Else object is not executable. exch pop //true % Therefore it must have been resolved. } ifelse } bind executeonly def /oforce /exec load def /oget { % <array> <index> oget <object> % <dict> <key> oget <object> % Before release 6.20, this procedure stored the resolved % object back into the referring slot. In order to support % PDF linearization, we no longer do this. get oforce } bind executeonly def /oforce_array { % <array> oforce_array <array> [ exch { oforce } forall ] } bind executeonly def /oforce_elems { % <array> oforce_elems <first> ... <last> { oforce } forall } bind executeonly def %% Safe recursion maintain a dicitonary in which we record all the object numbers %% of objects which we resolve. Whenever it resolves a new one, it checks all the %% existing ones to see if its already present, in which case we assume recursion %% has taken place. Whenever this procedure calls itself it copies the existing %% dictionary, and throws it away afterwards. This means that we won't falsely %% detect recursion if two elements at the same level indirect to the same %% object. /safe_recursive { % <<recursion dict>> <any> oforce_recursive <recursion dict> <any> dup type dup /arraytype eq exch /packedarraytype eq or { dup rcheck { % protect tint transform functions, etc. dup length 3 eq { dup 2 get /resolveR eq { dup 0 get % <recursion dict> {x y resolveR} x dup % <recursion dict> {x y resolveR} x x 3 index exch known { ( **** Error: detected circular reference in object number ) pdfformaterror pdfstring cvs pdfformaterror (\n) pdfformaterror pop //null } { dup 3 index % <recursion dict> {x y resolveR} x x <recursion dict> 3 1 roll put % <recursion dict> {x y resolveR} } ifelse } if } if oforce % but dereference {1 0 R} dup type dup /arraytype eq exch /packedarraytype eq or { [ exch { counttomark 1 add index <<>> copy % create a copy for the recursion exch safe_recursive exch pop % pop the dictionary created for this level } forall ] } { dup type /dicttype eq { << exch 2 index <<>> copy exch { 3 -1 roll exch safe_recursive 3 -1 roll oforce 3 1 roll exch } forall pop>> } if } ifelse } if } { dup type /dicttype eq { << exch 2 index <<>> copy exch { 3 -1 roll exch safe_recursive 3 -1 roll oforce 3 1 roll exch } forall pop>> } if } ifelse } bind executeonly def /oforce_recursive { << >> exch safe_recursive exch pop } bind executeonly def % A null value in a dictionary is equivalent to an omitted key; % we must check for this specially. /knownoget { % <dict> <key> knownoget <value> true % <dict> <key> knownoget false % See oget above regarding this procedure. .knownget { oforce dup //null eq { pop //false } { //true } ifelse } { //false } ifelse } bind executeonly def % See /knownoget above. /oknown { % <dict> <key> oknown <bool> .knownget { oforce //null ne } { //false } ifelse } bind executeonly def /knownogetdict { % <dict> <key> knownogetdict <dict> true % <dict> <key> knownogetdict false //knownoget exec dup { 1 index type /dicttype ne { pop pop //false } if } if } bind executeonly def % PDF 1.1 defines a 'foreign file reference', but not its meaning. % Per the specification, we convert these to nulls. /F { % <file#> <object#> <generation#> F <object> % Some PDF 1.1 files use F as a synonym for f! .pdfcount 3 lt { f } { pop pop pop //null } ifelse } bind executeonly def % Verify the generation number for a specified object % Note: The values in Generations is the generation number plus 1. % If the value in Generations is zero then the object is free. /checkgeneration { % <object#> <generation#> checkgeneration <object#> <OK> Generations 2 index get 1 sub 1 index eq { % If generation # match ... pop //true % Then return true } { % Else not a match ... QUIET not { % Create warning message if not QUIET Generations 2 index get 0 eq { % Check if object is free ... ( **** Warning: reference to free object: ) 2 index =string cvs concatstrings ( ) concatstrings % put obj # exch =string cvs concatstrings ( R\n) concatstrings % put gen # } { ( **** Warning: wrong generation: ) 2 index =string cvs concatstrings ( ) concatstrings % put obj # exch =string cvs concatstrings % put gen # (, xref gen#: ) concatstrings 1 index Generations % put xref gen # exch get 1 sub =string cvs concatstrings (\n) concatstrings } ifelse pdfformatwarning % Output warning message } { % Else QUIET ... pop % Pop generation number } ifelse % We should return false for an incorrect generation number, however % we are simply printing a warning and then returning true. This makes % Ghostscript tolerant of of bad generation numbers. //true } ifelse } bind executeonly def /R { % <object#> <generation#> R <object> %% Parameter validation; this should not be required but we have found files %% (Bug 697351) which are corrupted in ways that mean we see a 'R' in a stream %% even though it is not an indirect object reference. Because a stream %% may reference objetcs which have not been resolved, we cannot simply %% 'undef' teh R operator, the only solution is to have it chekc the %% types of its operands. This is poterntially slow of course, we may %% need to remove this in future if the performance penalty is too great. %% We cannot slow down all files significantly purely to work-around %% files which are invalid. 1 index type /integertype eq 1 index type /integertype eq and { /resolveR cvx 3 packedarray cvx } { ( **** Error: indirect object reference \(R\) encountered with invalid arguments.) pdfformaterror ( Output may be incorrect.\n) pdfformaterror } ifelse } bind executeonly def % If we encounter an object definition while reading sequentially, % we just store it away and keep going. /objopdict mark valueopdict { } forall /endobj dup cvx .dicttomark readonly def /obj { % <object#> <generation#> obj <object> PDFfile objopdict .pdfrun } bind executeonly def /endobj { % <object#> <generation#> <object> endobj <object> %% If we have a stream wioth a broken endstream we can get here without %% an object definition on nthe stack. If we simply pop the 'extraneous' %% data we will break the stream definition and throw an error. So we look %% to see if this appears to be this specific case. 2 index type /marktype eq 2 index type /marktype eq or { { dup type /marktype eq { exit }{ pop }if }loop }{ { 2 index type /integertype ne 2 index type /integertype ne or { count 3 gt { ( **** Error: obj definition followed by multiple tokens, attempting to recover.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror pop } { //null ( **** Error: ignoring obj followed by multiple tokens.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror exit } ifelse } { exit } ifelse } loop 3 1 roll % Read the xref entry if we haven't yet done so. % This is only needed for generation # checking. 1 index resolved? { pop } if checkgeneration { % The only global objects we bother to save are % (resource) dictionaries. 1 index dup gcheck exch type /dicttype eq and { PDFDEBUG { (%Local=>global: ) print dup //== exec } if GlobalObjects 1 index 3 index put IsGlobal 1 index 1 put } if Objects exch 2 index put } { pop pop //null } ifelse }ifelse } bind executeonly def % When resolving an object reference in an object stream, we stop at % the end of file. Note: Objects in an object stream do not have either % a starting 'obj' or and ending 'endobj'. /resolveobjstreamopdict mark valueopdict { } forall (%%EOF) cvn { exit } bind executeonly /endobj { % bug 689795 ( **** Error: Objects in an object stream should not have 'endobj'.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror } bind executeonly .dicttomark readonly def % Note: This version of this function is not currently being used. % Resolve all objects in an object stream /resolveobjectstream { % <object stream #> resolveobjectstream - PDFDEBUG { (%Resolving object stream: ) print } if 0 resolveR % Get the objectstream dict, all objstrms use 0 as the gen # dup /First get % Save location of first object onto the stack 1 index /N get % Save number of objects onto the stack 2 index //false resolvestream % Convert stream dict into a stream /ReusableStreamDecode filter % We need to be able to position stream % Objectstreams begin with list of object numbers and locations % Create two arrays to hold object numbers and stream location 1 index array % Array for holding object number 2 index array % Array for holding stream object location % Get the object numbers and locations. 0 1 5 index 1 sub { % Loop and collect obj # and locations % Stack: objstreamdict First N objectstream [obj#] [loc] index 2 index 1 index % Setup to put obj# into object number array 5 index token pop put % Get stream, then get obj# and put into array 1 index 1 index % Setup to put object loc into location array 5 index token pop put % Get stream, get obj loc and put into array pop % Remove loop index } for % Create a bytestring big enough for reading any object data % Scan for the size of the largest object 0 0 % Init max object size and previous location 2 index { % Loop through all object locations % Stack: ... maxsize prevloc currentloc dup 4 1 roll % Save copy of object location into stack exch sub % Object size = currentloc - prevloc .max % Determine maximum object size exch % Put max size under previous location } forall pop % Remove previous location .bigstring % Create bytestring based upon max obj size % Move to the start of the object data 3 index 6 index % Get objectstream and start of first object setfileposition % Move to the start of the data % Read the data for all objects except the last. We do % not know the size of the last object so we need to treat % it as a special case. 0 1 6 index 2 sub { dup 4 index exch get % Get our current object number % Stack: objstreamdict First N objectstream [obj#] [loc] % bytestring loopindex object# dup resolved? { % If we already have this object pop pop % Remove object and object number 1 add 2 index exch get % Get location of next object 6 index add 6 index exch % Form location of next object and get stream setfileposition % Move to the start of the next object data } { % Else this is a new object ... % We are going to create a string for reading the object 2 index 0 % use our working string % Determine the size of the object 5 index 4 index 1 add get % Get location of the next object 6 index 5 index get % Get location of this object sub % Size of object = next loc - this loc getinterval % Create string for reading object 6 index exch readstring pop % Read object /ReusableStreamDecode filter % Convert string into a stream resolveobjstreamopdict .pdfrun % Get PDF object Objects exch 2 index exch put % Put object into Objects array pop pop % Remove object # and loop index } ifelse } for pop pop % Remove our working string and loc array % Now read the last object in the object stream. Since it % is the last object, we can use the original stream and % terminate when we hit the end of the stream % Stack: objstreamdict First N objectstream [obj#] 2 index 1 sub get % Get our current object number dup resolved? not { % If we do not already have this object exch % Get our object stream resolveobjstreamopdict .pdfrun % Get PDF object Objects exch 2 index exch put % Put object into Objects array } if pop pop pop pop % Clear stack } bind executeonly def /no_debug_dict << /PDFDEBUG //false >> readonly def % Resolve all objects in an object stream /resolveobjectstream { % <object stream #> resolveobjectstream - PDFDEBUG { (%Resolving object stream: ) print } if dup 0 resolveR % Get the objectstream dict, all objstrms use 0 as the gen # dup /Type get /ObjStm ne { % Verify type is object stream ( **** Error: Incorrect Type in object stream dictionary.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror /resolveobjectstream cvx /typecheck signalerror } if dup /N get % Save number of objects onto the stack 1 index //false resolvestream % Convert stream dict into a stream /ReusableStreamDecode filter % We need to be able to position stream % Objectstreams begin with list of object numbers and locations 1 index array % Create array for holding object number % Get the object numbers 0 1 4 index 1 sub { % Loop and collect obj numbers % Stack: strm# objstreamdict N PDFDEBUG objectstream [obj#] loopindex 1 index 1 index % Setup to put obj# into object number array 4 index token pop put % Get stream, then get obj# and put into array 2 index token pop pop pop % Get stream, get obj loc and clear stack } for % Move to the start of the object data 1 index 4 index /First get % Get objectstream and start of first object setfileposition % Move to the start of the data % We disable PDFDEBUG while reading the data stream. We will % print the data later PDFDEBUG { //no_debug_dict begin } if % Read the data for all objects. We check to see if we get % the number of objects that we expect. % Stack: strm# objstreamdict N objectstream [obj#] PDFDEBUG /ResolveObjectStreamMark 3 -1 roll count 4 index add % Determine stack depth with objects 3 1 roll resolveobjstreamopdict .pdfrun % Get PDF objects count /ResolveObjectStreamMark CountToKey not {0} if 1 add index ne { count /ResolveObjectStreamMark CountToKey not {0} if 1 add index gt { ( **** Error: Incorrect object count in object stream (too many objects).\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror } if % Its possible for us to end up here with a valid file. The way we work is to read the % stream and tokenise all the objects, but that assumes there will be delimiters or % whitespace between each object in the stream. We can easily think of cases where % that is not true; eg two consecutive numbers 123 456 would be tokenised as a % single number with the value 123456. % In this case we can use the approach below to read each object individually and % that will define the correct number of objects. After we've collected all the % objects we'll check the number of objects recovered again, and see if there % are still too few. We should probably raise an error in that case, but lets wait % until we see a case. % Having too many objects in an ObjStm is not illegal, dumb but not illegal. We can % recover from this, but its complicated. The extra object could be any of the ones % from the stream, the only way to find out is to process each object individually. % Unfortunately, my attempts to come up with a version of .pdfrun which only tokenised % one object got rapidly bogged down. So a new approach was needed. % % The idea is simple; turn the underlying file into a ReusableStream, then we can % reposition it. Build an array of the object offsets, reposition the file to the % start of each object in turn. For all except the last object, create a sub file % using SubFileDeocde with an empty string, and an EODCount which is the difference % between the offset of this object and the offset of the next. % For the last object we just read from the offset to the end of the stream. % % Then call .pdfrun on that sub file, or the main stream, which will tokenise all the % objects from that point onwards. Then discard all but the first object read. % % The complications arise from the fact that we need to end up with the objects on % the stack, in the right order, preceded by a mark, a count, and an array containing % all the object numbers. % First, discard everything we read up to now; we can reuse the 'mark' which was placed % by the preceding code to do this, as long as we remember to replace that 'mark'. % Handily this will leave the count and the array which contains the object numbers in place. /ResolveObjectStreamMark ClearToKey % Replace the 'mark' consumed by conttomark above, so that we match what the code following this error handling expects. /ResolveObjectStreamMark % copy the ObjStm dictionary and then copy the count of objects expected 4 index 4 index % Copy the ObjStm dictionary, and create a file from it 1 index //false resolvestream % Convert stream dict into a stream /ReusableStreamDecode filter % We need to be able to re-position the stream 1 index array % Create array for holding offsets % Get the object offsets, these are stored at teh start of the stream, interleaved % between the object numbers. We know reading these can't fail, because we've already % done this to create the array of object numbers, above. 0 1 % starting index (0), increment (1) for loop 4 index 1 sub % limit of loop is object count-1 (because we start at 0) { 1 index 1 index % copy array and index 4 index % copy the file object token pop pop % read a token (object number) and discard it 4 index token % read another token (offset) pop put pop % put the offset into the array at the new index } for % We now have an array with all the object offsets in it % So we need to reposition the file to the start of each object and read % from that point. We use the difference between two offsets to setup % a SubFileDecode filter to only read as many bytes as there are % between the objects. Normally this should result in us reading one object, % if there are extra objects then we'll discard the extras. By doing this % we avoid tokenising the same data multiple times. % Set the loop to be from 0 to the number of objects minus 1 (starts from 0), step 1. 2 index 1 sub 0 1 3 -1 roll { dup % copy the loop index 2 index length 2 sub lt % Check if index + 1 exceeds array size (it will on last iteration) { % Not the last iteration dup % copy the loop index 2 index exch get 5 index /First get add % get the object offset, and add the value of First from the dictionary. exch 1 add % add one to the loop index 2 index exch get 5 index /First get add % and get the offset to the start of the next object 1 index sub % copy the first offset and subtract from the second to get the length exch 3 index dup 3 -1 roll setfileposition % copy the file and position it to the offset of the object exch << /EODCount 3 -1 roll /EODString () >> % Set up a dictionary for the filter /SubFileDecode filter % and apply it to limit the number of bytes read. } { % On the last iteration, simly read from the file, we don't need another SubFileDecode. 1 index exch get 4 index /First get add % get the offset, and add the value of First from the dictionary. 2 index dup 3 -1 roll setfileposition % copy the stream, and position it at that point }ifelse mark exch resolveobjstreamopdict .pdfrun % make a mark and then tokenise all the objects from there to the end of stream (or sub file) counttomark 2 sub % Find out how many objects we created (less two, one for the count and one for the first object) 0 1 3 -1 roll {pop pop} for % pop that many objects off the stack 6 1 roll pop % roll the new object to be behind our working objects on the stack and pop the mark } for % pop most of the working objects (array, file, and ObjStrm dictionary) % but leave count of objects. Check that aginst the number of objects % retrieved. If we got too few then issue a warning. pop pop exch pop /ResolveObjectStreamMark CountToKey not {1} if 1 sub lt { ( **** Error: Incorrect object count in object stream (too few objects).\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror } if } if % We have the object data /ResolveObjectStreamMark CountToKey not {0} if array astore exch pop exch pop % Remove mark and count currentdict //no_debug_dict eq { end } if % Restore debug context % Save the objects into Objects 0 1 2 index length 1 sub { % Loop through all objects % Stack: strm# objstreamdict N [obj#] [objects] loopindex dup 3 index exch get % Get our current object number % Stack: strm# objstreamdict N [obj#] [objects] loopindex obj# dup ObjectStream exch get 7 index eq { dup resolved? { % If we already have this object pop pop % Remove object and object number } { % Else if we do not have this object PDFDEBUG { (%Resolving compressed object: [) print dup =only ( 0]) = } if Objects exch 3 index % Put the object into Objects 3 index get PDFDEBUG { dup === flush } if put } ifelse } { pop % Ignore old object; remove object number. } ifelse pop % Remove loop index } for pop pop pop pop pop % Remove strm# objstream, N, (obj#], and [objects] } bind executeonly def currentdict /no_debug_dict undef % When resolving an object reference, we stop at the endobj or endstream. /resolveopdict mark valueopdict { } forall /xref { % Bug 697761 ( **** Error: Encountered 'xref' while expecting 'endobj'.\n) pdfformaterror ( Treating this as a missing 'endobj', output may be incorrect.\n) pdfformaterror endobj exit } bind executeonly /endstream { endobj exit } bind /endobj { endobj exit } bind /endjobj { % Bug 689876. ( **** Error: Operator 'endobj' is misspelled as 'endjobj'.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror endobj exit } bind executeonly /enbobj { % Bug 690397. ( **** Error: Operator 'endobj' is misspelled as 'enbobj'.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror endobj exit } bind executeonly /obj { % OmniForm generates PDF file with endobj missing in some % objects. AR ignores this. So we have to do it too. ( **** Error: Encountered 'obj' while expecting 'endobj'.\n) pdfformaterror ( Treating this as a missing 'endobj', output may be incorrect.\n) pdfformaterror pop pop endobj exit } bind executeonly .dicttomark readonly def /resolveR { % <object#> <generation#> resolveR <object> 1 index 3 1 roll % copy the object for the code after pdf_run_resolve (may store it) PDFDEBUG { PDFSTEPcount 1 le { (%Resolving: ) print 2 copy 2 array astore //== exec } if } if 1 index dup 0 le exch NumObjects ge or { ( **** Error: Considering object with an invalid number ) 2 index 20 string cvs concatstrings ( as null.\n) concatstrings pdfformaterror ( Output may be incorrect.\n) pdfformaterror pop pop //null } { 1 index resolved? { % If object has already been resolved ... exch pop exch pop % then clear stack and return object } { % Else if not resolved ... PDFfile fileposition 3 1 roll % Save current file position 1 index Objects exch get % Get location of object from xref 3 1 roll checkgeneration { % Verify the generation number % Stack: savepos objpos obj# ObjectStream 1 index get dup 0 eq { % Check if obj in not an objstream pop exch PDFoffset add PDFfile exch setfileposition PDFfile token pop 2 copy ne { ( **** Error: Unrecoverable error in xref!\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror /resolveR cvx /rangecheck signalerror } if pop PDFfile token pop PDFfile token pop /obj ne { ( **** Error: Unrecoverable error in xref!\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror /resolveR cvx /rangecheck signalerror } if pdf_run_resolve % PDFfile resolveopdict .pdfrun } { % Else the object is in an ObjectStream % Process an objectstream object. We are going to resolve all % of the objects in sthe stream and place them into the Objects % array. % Stack: savepos objpos obj# objectstream# resolveobjectstream resolved? { % If object has already been resolved ... exch pop % Remove object pos from stack. } { pop pop //null % Pop objpos and obj#, put null for object } ifelse } ifelse } { % Else the generation number is wrong % Don't cache if the generation # is wrong. pop pop //null % Pop objpos and obj#, put null for object } ifelse % ifelse generation number is correct exch PDFfile exch setfileposition % Return to original file position } ifelse } ifelse dup type /dicttype eq % For dictionaries only { dup /Type known % make sure the dictionary has a type { %% We must not add to *all* dictionaries, because some of them are handled by %% executing all the key/value pairs, and adding a integer causes problems %% Since we only use this number for font identification, or checking self-references, %% we only need it for dictionaries with a Type, and these are always handled more carefully. dup 3 -1 roll /.gs.pdfobj# exch put } {exch pop} ifelse } {exch pop} ifelse } bind executeonly def % ================================ Streams ================================ % % We represent a stream by an executable dictionary that contains, % in addition to the contents of the original stream dictionary: % /File - the file or string where the stream contents are stored, % if the stream is not an external one. % /FilePosition - iff File is a file, the position in the file % where the contents start. % /StreamKey - the key used to decrypt this stream, if any. % We do the real work of constructing the data stream only when the % contents are needed. % Construct a stream. The length is not reliable in the face of % different end-of-line conventions, but it's all we've got. % % PDF files are inconsistent about what may fall between the 'stream' keyword % and the actual stream data, and it appears that no one algorithm can % detect this reliably. We used to try to guess whether the file included % extraneous \r and/or \n characters, but we no longer attempt to do so, % especially since the PDF 1.2 specification states flatly that the only % legal terminators following the 'stream' keyword are \n or \r\n, both of % which are properly skipped and discarded by the token operator. % Unfortunately, this doesn't account for other whitespace characters that % may have preceded the EOL, such as spaces or tabs. Thus we back up one % character and scan until we find the \n terminator. /stream { % <dict> stream <modified_dict> dup /F known dup PDFsource PDFfile eq or { not { dup /File PDFfile put % make sure that we are just past the EOL \n character PDFfile dup fileposition 1 sub setfileposition % back up one % Skip spaces till \n or a non-space character is found. //false { PDFfile read pop dup 32 eq { pop //true or } { exit } ifelse } loop dup 13 eq { pop PDFfile read pop } if 10 ne { PDFfile dup fileposition 1 sub setfileposition //true or } if { ( **** Error: stream operator isn't terminated by valid EOL.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror } if dup /FilePosition PDFfile fileposition put PDFDEBUG { PDFSTEPcount 1 le { (%FilePosition: ) print dup /FilePosition get //== exec } if } if } if % Some (bad) PDf files have invalid stream lengths. This causes problems % if we reposition beyond the end of the file. So we compare the given % length to number of bytes left in the file. dup mark exch /Length {knownoget} stopped { % Bug 703372 is a PDF file where the XRef stream dictionary has a Length which is an % indirect object. Clearly we cannot look that up in an xref which we haevn't yet % read! We catch the error from knownoget and do not reposition the steam. After % that the normal recovery code kicks in and we will eventually manage to read % the compressed xref. cleartomark } { { dup type /realtype eq { ( **** Warning: stream length is a real number; converting to integer.\n) pdfformatwarning cvi 2 copy /Length exch put } if dup PDFfile bytesavailable lt { % compare to to bytes left in file PDFfile fileposition % reposition to the end of stream add PDFfile exch setfileposition } { pop % bad stream length - do not reposition. % This will force a length warning below } ifelse } if pop % the mark from the Length dereference guard above. } ifelse } { pop % We're already reading from a stream, which we can't reposition. % Capture the sub-stream contents in a string. dup /Length oget string PDFsource exch readstring not { ( **** Error: Unexpected EOF in stream!\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror /stream cvx /rangecheck signalerror } if 1 index exch /File exch put } ifelse PDFsource token_nofail not { //null } if dup /endobj eq { % Another case that Acrobat Reader handles -- 'endobj' without 'endstream'. ( **** Error: stream missing 'endstream'.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror pop /endstream % fake a valid endstream } if /endstream ne { ( **** Error: stream Length incorrect.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror dup /Length undef % prevent the use of the incorrect length. %% Bug #696560 If we get a stream whose length is incorrect we cannot %% safely *assume* it has an object definition as we can get here when %% reading an XRef stream, and in that case we will not have the object %% and generation numbers on the stack! %% So before we call endobj and exit pdfrun, try and see if ths looks like %% a regular object or not. If it isn't then don't try and ahndle it as %% one, just return the object. count 3 ge { 1 index type /integertype eq 2 index type /integertype eq and { cvx endobj exit % exit from .pdfrun now. } if } if } { PDFsource (??) .peekstring pop (>>) eq { % Bug 690161, sample #1 ( **** Error: Spurious '>>' after 'endstream' ignored.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror PDFsource (12) readstring pop pop } if } ifelse cvx } bind executeonly def /endstream { exit } bind executeonly def % Contrary to the published PDF (1.3) specification, Acrobat Reader % accepts abbreviated filter names everywhere, not just for in-line images, % and some applications (notably htmldoc) rely on this. /unabbrevfilterdict mark /AHx /ASCIIHexDecode /A85 /ASCII85Decode /CCF /CCITTFaxDecode /DCT /DCTDecode /Fl /FlateDecode /LZW /LZWDecode /RL /RunLengthDecode .dicttomark readonly def % Extract and apply filters. /filterparms { % <dict> <DPkey> <Fkey> filterparms % <dict> <parms> <filternames> 2 index exch knownoget { oforce_recursive exch 2 index exch knownoget { dup length 0 eq { pop //false } { //true } ifelse } { //false } ifelse { % Both filters and parameters. oforce_recursive exch dup type /nametype eq { 1 array astore exch dup type /arraytype ne { 1 array astore } if exch } if } { % Filters, but no parameters. //null exch dup type /nametype eq { 1 array astore } if } ifelse } { % No filters: ignore parameters, if any. pop //null { } } ifelse } bind executeonly def /filtername { % <filtername> filtername <filtername'> //unabbrevfilterdict 1 index .knownget { exch pop } if dup /Filter resourcestatus { pop pop } { Repaired exch % this error is not the creator's fault RepairedAnError exch ( **** ERROR: Unable to process ) pdfformaterror 64 string cvs pdfformaterror ( data. Page will be missing data.\n) pdfformaterror /RepairedAnError exch store /Repaired exch store % restore the previous "Repaired" state % provide a filter that returns EOF (no data) /.EOFDecode } ifelse } bind executeonly def /pdf_rules_dict << /PDFRules //true >> readonly def % Add PDF option to ASCII85Decode filter % <source> <name> add_A85_param <source> <dict'> <name> % <source> <dict> <name> add_A85_param <source> <dict'> <name> /add_A85_param { dup /ASCII85Decode eq { 1 index type /dicttype eq { exch dup length 1 add dict copy dup /PDFRules //true put exch } { //pdf_rules_dict exch } ifelse } if } bind executeonly def currentdict /pdf_rules_dict undef /applyfilters { % <parms> <source> <filternames> applyfilters <stream> 2 index //null eq { { filtername add_A85_param filter } } { dup length 3 index length ne %% compare lengths of DecodeParmas and Filter arrays { %% if they aren't the same, ignore the decode params ( **** Error: ignoring stream /DecodeParams array as its length is different to the Filters array.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror 3 -1 roll pop //null 3 1 roll { filtername add_A85_param filter } } { { % Stack: parms source filtername 2 index 0 oget dup type /dicttype ne { pop } { exch filtername dup /JBIG2Decode eq { exch jbig2cachectx exch } if } ifelse add_A85_param filter exch dup length 1 sub 1 exch getinterval exch } } ifelse } ifelse forall exch pop } bind executeonly def % JBIG2 streams have an optional 'globals' stream obj for % sharing redundant data between page images. Here we resolve % that stream reference (if any) and run it through the decoder, % creating a special -jbig2globalctx- postscript object our % JBIG2Decode filter implementation looks for in the parm dict. /jbig2cachectx { % <parmdict> jbig2cachectx <parmdict> dup /JBIG2Globals knownoget { % make global ctx PDFfile fileposition exch % resolvestream is not reentrant mark exch //true resolvestream % stack after: PDFfileposition -file- % Read the data in a loop until EOF to so we can move the strings into a bytestring [ { counttomark 1 add index 60000 string readstring not { exit } if } loop ] exch pop 0 1 index { length add } forall % compute the total length % now copy the data from the array of strings into a bytestring .bytestring exch 0 exch { 3 copy putinterval length add } forall pop % If this fails we don't want to abort totally, there may be more content % in the PDF file that we can render. So just run in a stopped context. {.jbig2makeglobalctx} stopped { cleartomark PDFfile exch setfileposition } { exch pop PDFfile 3 -1 roll setfileposition 1 index exch /.jbig2globalctx exch put } ifelse } if } bind executeonly def % Resolve a stream dictionary to a PostScript stream. % Streams with no filters require special handling: % - Whether we are going to interpret the stream, or If we are just % going to read data from them, we impose a SubFileDecode filter % that reads just the requisite amount of data. % Note that, in general, resolving a stream repositions PDFfile. % Clients must save and restore the position of PDFfile themselves. /resolvestream { % <streamdict> <readdata?> resolvestream <stream> 1 index /F knownoget { % This stream is stored on an external file. (r) file 3 -1 roll /FDecodeParms /FFilter filterparms % Stack: readdata? file dict parms filternames 4 -1 roll exch pdf_decrypt_stream applyfilters } { exch dup /Length knownoget { 0 eq } { //false } ifelse { () 0 () /SubFileDecode filter } { dup /FilePosition .knownget { 1 index /File get exch setfileposition } if % Stack: readdata? dict /DecodeParms /Filter filterparms % Stack: readdata? dict parms filternames 2 index /File .knownget not { ( **** Error: Stream object is missing the stream data.\n) ( Output may be incorrect.\n) pdfformaterror pdfformaterror () } if exch % Stack: readdata? dict parms file/string filternames dup length 0 eq { % All the PDF filters have EOD markers, but in this case % there is no specified filter. exch dup type /filetype eq 5 index or { % Use length for any files or reading data from any source. 3 index /Length knownoget not { 0 } if } { 0 % Otherwise length of 0 for whole string } ifelse 4 index /IDFlag known { pop } { () /SubFileDecode filter } ifelse exch pdf_decrypt_stream % add decryption if needed pop exch pop } { % Stack: readdata? dict parms source filternames exch 3 index /Length knownoget { () /SubFileDecode filter } if exch pdf_decrypt_stream % add decryption if needed applyfilters } ifelse } ifelse } ifelse % Stack: readdata? dict file exch pop exch pop } bind executeonly def % ============================ Name/number trees ============================ % /nameoget { % <nametree> <key> nameoget <obj|null> exch /Names exch .treeget } bind executeonly def /numoget { % <numtree> <key> numoget <obj|null> exch /Nums exch .treeget } bind executeonly def /.treeget { % <key> <leafkey> <tree> .treeget <obj|null> dup /Kids knownoget { exch pop .branchget } { exch oget .leafget } ifelse } bind executeonly def /.branchget { % <key> <leafkey> <kids> .branchget <obj|null> dup length 0 eq { pop pop pop //null } { dup length -1 bitshift 2 copy oget % Stack: key leafkey kids mid kids[mid] dup /Limits oget aload pop % Stack: key leafkey kids mid kids[mid] min max 6 index lt { pop pop 1 add 1 index length 1 index sub getinterval .branchget } { 5 index gt { pop 0 exch getinterval .branchget } { exch pop exch pop .treeget } ifelse } ifelse } ifelse } bind executeonly def /.leafget { % <key> <pairs> .leafget <obj|null> dup length 2 eq { dup 0 get 2 index eq { 1 oget } { pop //null } ifelse exch pop } { dup length -1 bitshift -2 and 2 copy oget % Stack: key pairs mid pairs[mid] 3 index gt { 0 exch } { 1 index length 1 index sub } ifelse getinterval .leafget } ifelse } bind executeonly def % The following variants return tree entry whose key is closest but % less or equal to the given key. /numogetle { % <numtree> <key> numogetle <key obj true|false> exch /Nums exch .treegetle } bind executeonly def /.treegetle { % <key> <leafkey> <tree> .treegetle <key obj true|false> dup /Kids knownoget { exch pop .branchgetle } { exch oget .leafgetle } ifelse } bind executeonly def /.branchgetle { % <key> <leafkey> <kids> .branchgetle <key obj true|false> dup length 0 eq { pop pop pop //false } { dup length -1 bitshift 2 copy oget dup /Limits oget aload pop % Stack: key leafkeyb kids mid kids[mid] min max 6 index ge { 5 index le { exch pop exch pop .treegetle } { pop 0 exch getinterval .branchgetle } ifelse } { pop 2 index length 2 index sub 1 gt { pop 1 index length 1 index sub getinterval .branchgetle } { exch pop exch pop .treegetle } ifelse } ifelse } ifelse } bind executeonly def /.leafgetle { % <key> <pairs> .leafget <obj|null> dup length 2 eq { dup 0 get 2 index le { exch pop aload pop //true } { pop pop //false } ifelse } { dup length -1 bitshift -2 and 2 copy oget % Stack: key pairs mid pairs[mid] 3 index gt { 0 exch } { 1 index length 1 index sub } ifelse getinterval .leafgetle } ifelse } bind executeonly def end % pdfdict .setglobal pdf_sec.ps 0000644 00000066331 15030647507 0006533 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % Copyright (C) 1996-1998 Geoffrey Keating. % Copyright (C) 2001-2008 Artifex Software, Inc. % This file may be freely distributed with or without modifications, % so long as modified versions are marked as such and copyright notices are % not removed. % Implementation of security hooks for PDF reader. % This file contains the procedures that have to take encryption into % account when reading a PDF file. It was originally distributed % separately by Geoffrey Keating as an add-on to version 6 and earlier. % Modified by Alex Cherepanov to work with GS 6.60 and higher. % New versions of GS require explicit checks for /true, /false, and /null % in .decpdfrun. This fix is backward-compatible. % Modified by Raph Levien and Ralph Giles to use the new C % implementations of md5 and arcfour in ghostscript 7.01, and to % be compatible with PDF 1.4 128-bit encryption. % Modified by Ralph Giles for PDF 1.6 AES encryption. % Modified by Michael Constant for PDF 1.7 ExtensionLevel 3 % AES-256 encryption. /.setlanguagelevel where { pop 2 .setlanguagelevel } if .currentglobal //true .setglobal pdfdict begin % Older ghostscript versions do not have .pdftoken, so we use 'token' instead. /.pdftoken where { pop } { /.pdftoken /token load def } ifelse % take a stream and arc4 decrypt it. % <stream> <key> arc4decodefilter <stream> /arc4decodefilter { 1 dict begin /Key exch def currentdict end /ArcfourDecode filter } bind executeonly def % <ciphertext> <key> arc4decode <plaintext> /arc4decode { 1 index length 0 eq { pop } { 1 index length string 3 1 roll arc4decodefilter exch readstring pop } ifelse } bind executeonly def % take a stream and aes decrypt it. % <stream> <key> aesdecodefilter <stream> /aesdecodefilter { 1 dict begin /Key exch def currentdict end /AESDecode filter } bind executeonly def % AES decrypt a string, returning a string. The second argument can % be a dictionary of the form << /Key key /Padding false >>, which % specifies the key and any options for the AESDecode filter, or it % can just be a string (the key). % % <ciphertext> <dict> aesdecode <plaintext> % <ciphertext> <key> aesdecode <plaintext> /aesdecode { 1 index length 0 eq { pop } { 1 index length string 3 1 roll % If our second argument is a dictionary, it's the full set % of decoding options (including the key); pass it directly % to the AESDecode filter. Otherwise, it's just the key, so % call aesdecodefilter to construct the dictionary. dup type /dicttype eq { /AESDecode filter } { aesdecodefilter } ifelse exch readstring pop } ifelse } bind executeonly def /md5 { 16 string dup /MD5Encode filter dup 4 3 roll writestring closefile } bind executeonly def /md5_trunk { md5 0 pdf_key_length getinterval } bind executeonly def /sha256 { 32 string dup /SHA256Encode filter dup 4 3 roll writestring closefile } bind executeonly def % <string> contains_non_ascii <bool> /contains_non_ascii { //false exch { 128 ge { pop //true exit } if } forall } bind executeonly def /pdf_padding_string <28bf4e5e4e758a41 64004e56fffa0108 2e2e00b6d0683e80 2f0ca9fe6453697a> def % Pad a key out to 32 bytes. /pdf_pad_key { % <key> pdf_pad_key <padded key> dup length 32 gt { 0 32 getinterval } if pdf_padding_string 0 32 3 index length sub getinterval concatstrings } bind executeonly def /pdf_xorbytes { % <iter-num> <key> pdf_xorbytes <xored-key> dup length dup string exch 1 sub 0 1 3 2 roll { % <iter-num> <key> <new-key> <byte-num> dup 3 index exch get 4 index xor % <iter-num> <key> <new-key> <byte-num> <byte> 3 copy put pop pop } for 3 1 roll pop pop } bind executeonly def % Get length of encryption key in bytes /pdf_key_length { % pdf_key_length <key_length> Trailer /Encrypt oget dup /V knownoget not { 0 } if 1 eq { pop 5 } % If V == 1 then always use 40 bits { /Length knownoget { -3 bitshift } { 5 } ifelse } ifelse } bind executeonly def % Algorithm 3.2 /pdf_compute_encryption_key { % <password> pdf_compute_encryption_key <key> % Step 1. pdf_pad_key % Step 2, 3. Trailer /Encrypt oget dup /O oget % <padded-key> <encrypt> <O> % Step 4. exch /P oget 4 string exch 2 copy 255 and 0 exch put 2 copy -8 bitshift 255 and 1 exch put 2 copy -16 bitshift 255 and 2 exch put 2 copy -24 bitshift 255 and 3 exch put pop % <padded-key> <O> <P> % Step 5. Trailer /ID knownoget { 0 oget } { () ( **** Error: ID key in the trailer is required for encrypted files.\n) pdfformaterror ( File may not be possible to decrypt.\n) pdfformaterror } ifelse 3 { concatstrings } repeat % We will finish step 5 after possibly including step 6. % The following only executed for /R equal to 3 or more Trailer /Encrypt oget dup /R oget dup 3 ge { % Step 6. If EncryptMetadata is false, pass 0xFFFFFFFF to md5 function % The PDF 1.5 Spec says that EncryptMetadata is an undocumented % feature of PDF 1.4. That implies that this piece of logic should % be executed if R >= 3. However testing with Acrobat 5.0 and 6.0 shows % that this step is not executed if R equal to 3. Thus we have a test for % R being >= 4. 4 ge { /EncryptMetadata knownoget % Get EncryptMetadata (if present) not { //true } if % Default is true not { % If EncryptMetadata is false <ff ff ff ff> concatstrings % Add 0xFFFFFFFF to working string } if } { pop % Remove Encrypt dict } ifelse md5_trunk % Finish step 5 and 6. % Step 7. Executed as part of step 6 % Step 8. (This step is defintely a part of PDF 1.4.) 50 { md5_trunk } repeat } { pop pop md5_trunk % Remove R, Encrypt dict, finish step 5 } ifelse % Step 9 - Done in md5_trunk. } bind executeonly def % Algorithm 3.4 /pdf_gen_user_password_R2 { % <filekey> pdf_gen_user_password_R2 <U> % Step 2. pdf_padding_string exch arc4decode } bind executeonly def % Algorithm 3.5 /pdf_gen_user_password_R3 { % <filekey> pdf_gen_user_password_R3 <U> % Step 2. pdf_padding_string % Step 3. Trailer /ID knownoget { 0 oget } { () ( **** Error: ID key in the trailer is required for encrypted files.\n) pdfformaterror ( File may not be possible to decrypt.\n) pdfformaterror } ifelse concatstrings md5 % Step 4. 1 index arc4decode % Step 5. 1 1 19 { 2 index pdf_xorbytes arc4decode } for exch pop } bind executeonly def /pdf_gen_user_password { % <password> pdf_gen_user_password <filekey> <U> % common Step 1 of Algorithms 3.4 and 3.5. pdf_compute_encryption_key dup Trailer /Encrypt oget /R oget dup 2 eq { pop pdf_gen_user_password_R2 } { dup 3 eq { pop pdf_gen_user_password_R3 } { dup 4 eq { % 4 uses the algorithm as 3 pop pdf_gen_user_password_R3 } { % This procedure is only used if R is between 2 and 4, % so we should never get here. /pdf_gen_user_password cvx /undefined signalerror } ifelse } ifelse } ifelse } bind executeonly def % Algorithm 3.6 % <password> pdf_check_pre_r5_user_password <filekey> true % <password> pdf_check_pre_r5_user_password false /pdf_check_pre_r5_user_password { pdf_gen_user_password Trailer /Encrypt oget /U oget 0 2 index length getinterval eq { //true } { pop //false } ifelse } bind executeonly def % Compute an owner key, ie the result of step 4 of Algorithm 3.3 /pdf_owner_key % <password> pdf_owner_key <owner-key> { % Step 1. pdf_pad_key % Step 2. md5_trunk % 3.3 Step 3. Only executed for /R equal to 3 or more Trailer /Encrypt oget /R oget 3 ge { 50 { md5_trunk } repeat } if % Step 4 - Done in md5_trunk. } bind executeonly def % Algorithm 3.7 % <password> pdf_check_pre_r5_owner_password <filekey> true % <password> pdf_check_pre_r5_owner_password false /pdf_check_pre_r5_owner_password { % Step 1. pdf_owner_key % Step 2. Trailer /Encrypt oget dup /O oget 2 index arc4decode % <encryption-key> <encrypt-dict> <decrypted-O> % Step 3. Only executed for /R equal to 3 or more exch /R oget 3 ge { 1 1 19 { 2 index pdf_xorbytes arc4decode } for } if exch pop % <result-of-step-3> pdf_check_pre_r5_user_password } bind executeonly def % Algorithm 3.2a % <password> pdf_check_r5_password <filekey> true % <password> pdf_check_r5_password false /pdf_check_r5_password { 10 dict begin % temporary dict for local variables % Step 1. % If the .saslprep operator isn't available (because ghostscript % wasn't built with libidn support), just skip this step. ASCII % passwords will still work fine, and even most non-ASCII passwords % will be okay; any non-ASCII passwords that fail will produce a % warning from pdf_process_Encrypt. /.saslprep where { pop .saslprep } if % Step 2. dup length 127 gt { 0 127 getinterval } if /Password exch def % Step 3. /O Trailer /Encrypt oget /O oget def /U Trailer /Encrypt oget /U oget def Password O 32 8 getinterval concatstrings U 0 48 getinterval concatstrings sha256 O 0 32 getinterval eq { % Step 3, second paragraph. Password O 40 8 getinterval concatstrings U 0 48 getinterval concatstrings sha256 16 string Trailer /Encrypt oget /OE oget concatstrings << /Key 4 -1 roll /Padding //false >> aesdecode //true } { % Step 4. Password U 32 8 getinterval concatstrings sha256 U 0 32 getinterval eq { % Step 4, second paragraph. Password U 40 8 getinterval concatstrings sha256 16 string Trailer /Encrypt oget /UE oget concatstrings << /Key 4 -1 roll /Padding //false >> aesdecode //true } { //false } ifelse } ifelse % Step 5. dup { % Adobe says to decrypt the Perms string using "ECB mode with % an initialization vector of zero", which must be a mistake -- % ECB mode doesn't use initialization vectors. It looks like % they meant "ECB mode, or CBC mode with an initialization % vector of zero", since the two are equivalent for a single- % block message. We use the latter. 16 string Trailer /Encrypt oget /Perms oget concatstrings << /Key 4 index /Padding //false >> aesdecode 9 3 getinterval (adb) eq not { ( **** Error: Failed to decrypt Perms string.\n) pdfformaterror ( Cannot decrypt PDF file.\n) pdfformaterror printProducer /pdf_check_r5_password cvx /rangecheck signalerror } if } if end } bind executeonly def % <password> pdf_check_password <filekey> true % <password> pdf_check_password false /pdf_check_password { % If R is 2, 3, or 4, use Algorithms 3.6 and 3.7 to see if this is % a valid user or owner password. Following historical practice, % we treat the password as an arbitrary string of bytes and don't % interpret it in any way. (If the password fails, it would be % nice to try some plausible character set conversions, but this % gets complicated. Even Adobe products don't seem to handle it % consistently.) % % If R is 5, use Algorithm 3.2a. The password should be text, in % either UTF-8 or the current locale's charset. Trailer /Encrypt oget /R oget dup dup 2 ge exch 4 le and { pop dup pdf_check_pre_r5_user_password { exch pop //true } { pdf_check_pre_r5_owner_password } ifelse } { dup 5 eq { pop % First, try the password as UTF-8. dup pdf_check_r5_password { exch pop //true } { % The password didn't work as UTF-8, so maybe it's in the % locale character set instead. If possible, convert it to % UTF-8 and try again. /.locale_to_utf8 where { pop .locale_to_utf8 pdf_check_r5_password } { pop //false } ifelse } ifelse } { dup 6 eq { pop % First, try the password as UTF-8. dup Trailer /Encrypt oget //check_r6_password exec { exch pop //true } { % The password didn't work as UTF-8, so maybe it's in the % locale character set instead. If possible, convert it to % UTF-8 and try again. /.locale_to_utf8 where { pop .locale_to_utf8 Trailer /Encrypt oget //check_r6_password exec } { pop //false } ifelse } ifelse } { ( **** Warning: This file uses an unknown standard security handler revision: ) exch =string cvs concatstrings (\n) concatstrings pdfformatwarning ( Cannot decrypt PDF file.\n) pdfformaterror printProducer /pdf_check_password cvx /undefined signalerror } ifelse } ifelse } ifelse } bind executeonly def systemdict /check_r6_password .forceundef % Process the encryption information in the Trailer. /pdf_process_Encrypt { Trailer /Encrypt oget /Filter oget /Standard eq not { ( **** Warning: This file uses an unknown security handler.\n) pdfformatwarning ( Cannot decrypt PDF file.\n) pdfformaterror printProducer /pdf_process_Encrypt cvx /undefined signalerror } if % Bug 702598: We can have a trailer dictionary with an /Encrypt entry, and if the % Encrypt dictionary is V 4 or greater we can (should ?) have StrF and stmF entries. % % The code below checks for the existence of StmF and StrF entries. Its possible % that both may be /Identity (which means no encryption) in which case we don't need to check % the password, as we won't need to decrypt any streams or strings. Note that the dict may still % have a non-Identity /EFF (embedded files) key, but Ghostscript doesn't process embedded % files so we don't have to worry about that. Trailer /Encrypt oget dup /V get 4 ge { % NB: Entries in the Encrypt dictionary cannot be indirect references dup /StmF .knownget { /Identity eq not } { false % default StmF is Identity }ifelse 1 index /StrF .knownget { /Identity eq not } { false % default StrF is Identity }ifelse or % ...still in the V4 or above checking... % Even if StmF and StrF are Identity, if the StdCF is missing AuthEvent % or it is DocOpen, we require the password. Check for that. 1 index /CF .knownget { oforce dup type /dicttype eq { /StdCF .knownget { oforce dup type /dicttype eq { /AuthEvent .knownget { oforce dup type /nametype eq { /DocOpen eq or }{ ( **** Error: AuthEvent has wrong type.\n) pdfformaterror ( Cannot decrypt PDF file.\n) pdfformaterror /pdf_process_Encrypt cvx /invalidfileaccess signalerror } ifelse } { pop true % no AuthEvent, default is DocOpen, require password } ifelse }{ ( **** Error: StdCF has wrong type.\n) pdfformaterror ( Cannot decrypt PDF file.\n) pdfformaterror /pdf_process_Encrypt cvx /invalidfileaccess signalerror } ifelse } { pop true % no StdCF, require password } ifelse }{ ( **** Error: CF has wrong type.\n) pdfformaterror ( Cannot decrypt PDF file.\n) pdfformaterror /pdf_process_Encrypt cvx /invalidfileaccess signalerror } ifelse } { pop true % no CF, require password } ifelse exch pop % discard Encrypt dict }{ % Not V4 or later pop true % discard Encrypt dict, require password } ifelse % If we were given a PDFPassword, check it anyway, even if the % code above said we didn't need one. This will allow us to process % PDF files with an initial CryptFilter which has StrF=StmF=Identity, % but contains streams which themselves have non-Identity StmF or StrF. /PDFPassword where { pop true } { false } ifelse or { () pdf_check_password { /FileKey exch def } { /PDFPassword where { pop PDFPassword pdf_check_password { /FileKey exch def } { ( **** Error: Password did not work.\n) pdfformaterror ( Cannot decrypt PDF file.\n) pdfformaterror % If ghostscript was built without libidn, it's missing the % .saslprep operator and thus can't do proper Unicode password % normalization. Similarly, if the system provides neither % iconv nor the Windows MultiByteToWideChar function, then we % won't have the .locale_to_utf8 operator to convert passwords % from the locale character set to UTF-8. % % It's not a huge problem if you're missing either or both of % these. ASCII passwords will work fine regardless, and even % Unicode passwords will often be okay. % % However, if .saslprep or .locale_to_utf8 is missing, and the % user enters a non-ASCII password that doesn't work, we give % a warning message. PDFPassword contains_non_ascii { /.saslprep where not { ( **** WARNING: Ghostscript was configured without libidn,\n) ( **** so non-ASCII passwords aren't supported!\n) concatstrings pdfformaterror } { pop /.locale_to_utf8 where not { ( **** WARNING: Ghostscript was configured without iconv,\n) ( **** so non-ASCII passwords aren't supported!\n) concatstrings pdfformaterror } { pop } ifelse } ifelse } if /pdf_process_Encrypt cvx /invalidfileaccess signalerror } ifelse } { ( **** This file requires a password for access.\n) pdfformaterror /pdf_process_Encrypt cvx /invalidfileaccess signalerror } ifelse } ifelse } { ( **** This file has an Encryption dictionary, but both the StmF and StrF entries\n) pdfformatwarning ( **** are /Identity, and AuthEvent allows the document to be opened. It is possible\n) pdfformatwarning ( **** that embedded streams may still use encryption, if the file fails to process\n) pdfformatwarning ( **** you may need to supply a User or Owner password by setting -sPDFPassword=\n) pdfformatwarning } ifelse } bind executeonly def % Calculate the key used to decrypt an object (to pass to .decpdfrun or % put into a stream dictionary). /computeobjkey % <object#> <generation#> computeobjkey <keystring> { Trailer /Encrypt oget /V oget 5 eq { % Encrypt version 5 doesn't use object keys; everything is % encrypted with the file key. pop pop FileKey } { exch FileKey length 5 add string dup 0 FileKey putinterval exch % stack: gen# string obj# 2 copy 255 and FileKey length exch put 2 copy -8 bitshift 255 and FileKey length 1 add exch put 2 copy -16 bitshift 255 and FileKey length 2 add exch put pop exch 2 copy 255 and FileKey length 3 add exch put 2 copy -8 bitshift 255 and FileKey length 4 add exch put pop % this step is for the AES cipher only Trailer /Encrypt oget dup /StmF knownoget { %% Treat StmF of 'Identity' the same as if it is missing. dup /Identity eq { pop pop } { exch /CF knownoget { exch oget /CFM oget /AESV2 eq { (sAlT) concatstrings } if } { pop } ifelse } ifelse } { pop } ifelse md5 0 FileKey length 5 add 2 index length .min getinterval } ifelse } bind executeonly def % As .pdfrun, but decrypt strings with key <key>. /PDFScanRules_true << /PDFScanRules //true >> def /PDFScanRules_null << /PDFScanRules //null >> def /.decpdfrun % <file> <keystring> <opdict> .decpdfrun - { % Construct a procedure with the file, opdict and key bound into it. 2 index cvlit mark /PDFScanRules .getuserparam //null eq { //PDFScanRules_true { setuserparams } 0 get % force PDF scanning mode mark 7 4 roll } { mark 5 2 roll } ifelse { .pdftoken not { (%%EOF) cvn cvx } if dup xcheck { PDFDEBUG { dup //== exec flush } if 3 -1 roll pop 2 copy .knownget { exch pop exch pop exec } { exch pop dup /true eq { pop //true } { dup /false eq { pop //false } { dup /null eq { pop //null } { ( **** Error: Unknown operator: ) exch =string cvs concatstrings (\n) concatstrings pdfformaterror ( Output may be incorrect.\n) pdfformaterror } ifelse } ifelse } ifelse } ifelse } { exch pop PDFDEBUG { dup ==only ( ) print flush } if dup type /stringtype eq { % Check if we have encrypted strings R>=4 allows for % selection of encryption on streams and strings Trailer /Encrypt oget % Get encryption dictionary dup /R oget 4 lt % only >=4 has selectable { % R < 4 --> arc4 strings pop 1 index arc4decode % Decrypt string PDFDEBUG { (%Decrypted: ) print dup //== exec flush } if } { % Else R >= 4 /StrF knownoget % Get StrF (if present) { % If StrF is present ... dup /Identity eq not % Check if StrF != Identity { /StdCF eq { Trailer /Encrypt oget /CF knownoget { /StdCF oget /CFM oget dup /AESV2 eq exch /AESV3 eq or } { //false } ifelse { % Decrypt string 1 index aesdecode } { 1 index arc4decode } ifelse } { 1 index arc4decode } ifelse % If StrF != StdCF PDFDEBUG { (%Decrypted: ) print dup //== exec flush } if } { pop } ifelse % If StrF != identity } if % If StrF is known } ifelse % Ifelse R < 4 } { dup type /nametype eq { .pdffixname } if } ifelse exch pop } ifelse } aload pop //.packtomark exec cvx { loop } 0 get 2 packedarray cvx { stopped } 0 get /PDFScanRules .getuserparam //null eq { //PDFScanRules_null { setuserparams } 0 get % reset PDF scannig mode if it was off } if /PDFsource PDFsource { store { stop } if } aload pop //.packtomark exec cvx /PDFsource 3 -1 roll store exec } bind executeonly def currentdict /PDFScanRules_true undef currentdict /PDFScanRules_null undef % Run the code to resolve an object reference. /pdf_run_resolve { /FileKey where % Check if the file is encrypted { pop % File is encrypted 2 copy computeobjkey dup 4 1 roll PDFfile exch resolveopdict .decpdfrun dup dup dup 5 2 roll % stack: object object key object object { % Use loop to provide an exitable context. xcheck exch type /dicttype eq and % Check if executable dictionary not { % If object is not ... pop pop % ignore object exit % Exit 'loop' context } if % If not possible stream % Starting with PDF 1.4 (R = 3), there are some extra features % which control encryption of streams. The EncryptMetadata entry % in the Encrypt dict controls the encryption of metadata streams. Trailer /Encrypt oget % Get encryption dictionary dup /R oget dup 3 lt % Only PDF 1.4 and higher has options { % R < 3 --> all streams encrypted pop pop /StreamKey exch put % Insert StreamKey in dictionary exit % Exit 'loop' context } if % Check EncryptMeta. stack: object object key Encrypt R exch dup /EncryptMetadata knownoget % Get EncryptMetadata (if present) not { //true } if % If not present default = true not % Check if EncryptMetadata = false { % if false we need to check the stream type 3 index /Type knownoget % Get stream type (if present) not { //null } if % If type not present use fake name /Metadata eq % Check if the type is Metadata { pop pop pop pop % Type == Metadata --> no encryption exit % Exit 'loop' context } if } if % PDF 1.5 encryption (R == 4) has selectable encryption handlers. If % this is not PDF 1.5 encryption (R < 4) then we are done checking and % we need to decrypt the stream. stack: object object key R Encrypt exch 4 lt % Check for less than PDF 1.5 { pop /StreamKey exch put % Insert StreamKey in dictionary exit % Exit 'loop' context } if % Check if the stream encryption handler (StmF) == Identity. PDFDEBUG { Trailer /Encrypt oget /CF knownoget { /StdCF oget /CFM oget (Encrypt StmF is StdCF with CFM ) print = } if } if /StmF knownoget % Get StmF (if present) not { /Identity } if % If StmF not present default = Identity /Identity eq % Check if StmF == Identity { pop pop % Identity --> no encryption exit % Exit 'loop' context } if % If we get here then we need to decrypt the stream. /StreamKey exch put % Insert StreamKey into dictionary exit % Exit 'loop' context, never loop } loop % End of loop exitable context } { % Else file is not encrypted PDFfile resolveopdict .pdfrun } ifelse % Ifelse encrypted } bind executeonly def % Prefix a decryption filter to a stream if needed. % Stack: readdata? dict parms file/string filternames % (both before and after). /pdf_decrypt_stream { 3 index /StreamKey known % Check if the file is encrypted { exch % Stack: readdata? dict parms filternames file/string 3 index /StreamKey get Trailer /Encrypt oget dup /StmF knownoget { % stack: key Encrypt StmF exch /CF knownoget { exch oget /CFM oget % stack: key StmF-CFM dup /AESV2 eq exch /AESV3 eq or } { pop //false } ifelse { aesdecodefilter } % install the requested filter { arc4decodefilter } ifelse } { pop arc4decodefilter } % fallback for no StmF ifelse exch } if } bind executeonly def end % pdfdict systemdict /pdfdict .forceundef % hide pdfdict .setglobal gs_trap.ps 0000644 00000005602 15030647507 0006561 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % PostScript LanguageLevel 3 in-RIP trapping support. ll3dict begin % We need LanguageLevel 2 or higher in order to have setuserparams and % defineresource. languagelevel dup 2 .max .setlanguagelevel % ------ Trapping ------ % % The PostScript-level trapping parameters are maintained in userdict, % and explicitly reinstalled upon restore. /Trapping mark /settrapparams dup { % <paramdict> settrapparams - /.trapparams .uservar dup length dict .copydict dup 2 index { % Stack: paramdict olddict olddict key value 2 index 2 index known { put dup } { pop pop } ifelse } forall pop dup .settrapparams % Let the operator check parameter validity. .userdict /.trapparams 3 -1 roll put pop } bind executeonly .makeoperator /.copyparams { % <obj> .copyparams <obj'> dup type /dicttype eq { dup length dict .copydict dup { .copyparams 3 copy put pop pop } forall } { dup type /arraytype eq { [ exch { .copyparams } forall ] } if } ifelse } odef /currenttrapparams dup { % - currenttrapparams <paramdict> /.trapparams .uservar .copyparams } bind executeonly .makeoperator /settrapzone dup { % - settrapzone - % ****** DUMMY ****** newpath } bind .makeoperator % Define initial (dummy) trapping parameters. % These values are mostly complete guesses. userdict /.trapparams mark /BlackColorLimit 1.0 /BlackDensityLimit 1.0 /BlackWidth 1.0 /ColorantZoneDetails 0 dict /Enabled //true /HalftoneName //null /ImageInternalTrapping //false /ImagemaskTrapping //true /ImageResolution 1 /ImageToObjectTrapping //true /ImageTrapPlacement /Center /SlidingTrapLimit 1.0 /StepLimit 1.0 /TrapColorScaling 0.0 /TrapSetName //null /TrapWidth 1.0 .dicttomark readonly put .dicttomark /ProcSet defineresource pop % Define the InkParams and TrapParams resource categories. { /InkParams /TrapParams } { /Generic /Category findresource dup maxlength 3 add dict .copydict begin /InstanceType /dicttype def currentdict end /Category defineresource pop } forall % Define the TrappingType resource category. /Generic /Category findresource dup maxlength 3 add dict .copydict begin /InstanceType /integertype def /TrappingType currentdict end /Category defineresource pop {1001} { dup /TrappingType defineresource pop } forall .setlanguagelevel end % ll3dict gs_dscp.ps 0000644 00000007542 15030647507 0006551 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % Postscript interface routines to DSC parser /send_orientation { % <orientation> send_orientation - % .parse_dsc_comments returns -1 for an Orientation key with an % unrecognized value. dup 0 ge { << /Orientation 2 index >> setpagedevice } if pop } bind def % This dictionary contains local handlers for DSC comments. % See header in zdscpars.c for more information. % <dsc_dict> handler <dsc_dict> /DSCparseprocs mark /Orientation { dup /Orientation get send_orientation } bind /PageOrientation { dup /PageOrientation .knownget { send_orientation } { dup /Orientation .knownget { send_orientation } if } ifelse } bind /Page { dup /Orientation .knownget { send_orientation } if } bind /NOP { } bind .dicttomark readonly def % This procedure is called whenever a DSC comment is found by the interpreter /do_parse_dsc //false def /parse_dsc { % <file> <DSC string> [<prev proc>] % parse_dsc - % Run any previously installed parser. 0 get dup //null eq { pop } { 3 copy exec pop } ifelse do_parse_dsc { % Check if this parser is enabled currentglobal //true setglobal % Go to global VM, save old state 3 1 roll % Put old VM state under <file> <string> dsc_dict exch % <VM state> <file> <dict> <string> .parse_dsc_comments % <VM state> <file> <dict> <DSC name> 4 -1 roll % Get old VM state from under <file> <dict> <DSC name> setglobal % restore previous VM state //DSCparseprocs exch .knownget { % Check DSC name against local handler list exec % execute any local handler } if } if pop pop % remove file, dict } bind def % Check whether the currently installed parser is the one defined in this file. /.using_parse_dsc { % - .using_parse_dsc <proc> <using?> currentuserparams /ProcessDSCComment get dup //null eq { pop {{//null} //parse_dsc exec} } if dup length 3 eq { dup dup length 1 sub get /parse_dsc load eq } { //false } ifelse } bind def % Establish a binding for dsc_dict. userdict /dsc_dict //null put % - dsc_init - /dsc_init { % Initialize DSC parser currentglobal //true setglobal /dsc_dict 50 dict store % Size must be large enough for all DSC values dsc_dict .initialize_dsc_parser .using_parse_dsc { % Already using this parser. pop } { % Encapsulate the previous parser. We know it is in global VM: % allocate the new one in global VM as well. 1 array astore /parse_dsc load /exec load 3 array astore cvx readonly << /ProcessDSCComment 3 -1 roll >> setuserparams } ifelse setglobal /do_parse_dsc //true def } bind def % Enable the DSC parser defined in this file. % - enable_dsc - /enable_dsc { dsc_init } bind def % Disable the DSC parser defined in this file. % - disable_dsc - /disable_dsc { % There might be another parser installed: if so, restore it. % (If it has encapsulated our parser, we can't.) .using_parse_dsc { % Restore the parser we encapsulated. 0 get 0 get currentglobal //true setglobal exch << /ProcessDSCComment 3 -1 roll >> exch setglobal setuserparams } { pop } ifelse % If we couldn't restore the old parser, at least disable ours. /do_parse_dsc //false def } bind def gs_cff.ps 0000644 00000015471 15030647507 0006356 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % Loader for CFF (compressed) fonts, including OpenType CFFs. % The following are not implemented yet: % Deleted entries in the Name Index % Embedded PostScript % Multiple Master fonts % Chameleon fonts % Synthetic fonts % ---------------- Font loading machinery ---------------- % % Augment the FONTPATH machinery so it recognizes OpenType CFF font sets. /.scanfontheaders where { /.scanfontheaders [ /.scanfontheaders .systemvar aload pop (OTTO*) ] put } if % Load a font file that might be an OpenType CFF font set. % <file> .init_otto_font_file <file> /.init_otto_font_file { /FontSetInit /ProcSet findresource begin 2 dict begin /f exch def /cff //null def card32 pop card16 6 { next pop } repeat dup { % Stack: numtables tablesleft dup 0 eq { pop pop /.loadottofontfile cvx /invalidfont signalerror } if f 4 string readstring pop (CFF ) eq { sub exit } if f 12 string readstring pop pop 1 sub % skip to next table } loop % Stack: tablesread card32 pop card32 card32 % Stack: tablesread start length exch 3 -1 roll 1 add 16 mul 12 add sub f exch subfilefilter flushfile % skip to start f exch subfilefilter end } .bind executeonly odef % <file> .init_otto_font_file <file> /.init_wOFF_otto_font_file { /FontSetInit /ProcSet findresource begin 2 dict begin /f exch def /cff //null def 3 {card32 pop} repeat % (wOFF), (OTTO) and file length card16 30 { next pop } repeat dup { % Stack: numtables tablesleft dup 0 eq { pop pop /.loadottofontfile cvx /invalidfont signalerror } if f 4 string readstring pop (CFF ) eq { sub exit } if f 12 string readstring pop pop 1 sub % skip to next table } loop % Stack: tablesread 4 { card32 } repeat % Stack: tablesread start complen len checksum pop % Stack: tablesread start complen len 4 -2 roll exch % Stack: complen len start tablesread 1 add 20 mul 44 add sub % Stack: complen len offset f exch subfilefilter flushfile % skip to start % Stack: complen len % the table can legally be uncompressed: complen == len 1 index 1 index eq { exch pop f exch subfilefilter} { pop f exch subfilefilter /FlateDecode filter} ifelse end } bind def % <file> .loadfontfile - /.loadnonottofontfile /.loadfontfile load def /.loadfontfile { dup (12345678) .peekstring pop (wOFFOTTO) eq { //.init_wOFF_otto_font_file exec //true //false }{//true} ifelse { dup 4 string .peekstring pop (OTTO) eq { % If this is a font at all, it's an OpenType CFF font set. .init_otto_font_file //true } { //false } ifelse } if { % Use a random FontSet resource name. ****** WRONG ****** realtime rand xor =string cvs exch //false //false ReadData pop } { % Not a TrueType font. .loadnonottofontfile } ifelse } bind executeonly def currentdict /.init_wOFF_otto_font_file .forceundef 20 dict begin % ------ Utilities ------ % /subfilefilter { % <file> <length> subfilefilter <filter> % SubFileDecode interprets a length of 0 as infinite. dup 0 le { pop pop () 0 } if () /SubFileDecode filter } bind def /advance { % <n> advance - f cff eq { pos add /pos exch store } { pop } ifelse } bind def /next { % - next <byte> f read { 1 advance CFFDEBUG { ( ) print dup = } if } { 0 CFFDEBUG { ( Out of range access, assuming 0) = } if /pdfformaterror where { pop ( **** Warning: Out of range access to a CFF table, assuming 0.\n) pdfformaterror } if } ifelse } bind def /next2 { % - next2 <byte1> <byte2> f read { f read { 2 advance CFFDEBUG { ( ) print 1 index =only (,) print dup = } if } { 1 advance CFFDEBUG { ( ) print dup = } if } ifelse } if } bind def /nextstring { % <length> nextstring <string> dup 0 eq { pop () } { string f exch readstring pop dup length advance CFFDEBUG { ( ) print dup //== exec } if } ifelse } bind def /card8 % - card8 <card8> /next load def /card16 { % - card16 <card16> next2 exch 8 bitshift add } bind def /card32 { % - card32 <card32> card16 16 bitshift card16 add } bind def /offsetprocs [ /card8 load /card16 load { card8 16 bitshift card16 add } bind /card32 load ] readonly def /offsetproc { % <offsize> offsetproc <proc> 1 sub //offsetprocs exch get } bind def /offset { % <offsize> offset <offset> offsetproc exec } bind def /sid % - <sid> sid /card16 load def % ------ Main program ------ % % We need to pass the file as a parameter for the sake of the PDF % interpreter. Also for the sake of PDF, a flag forces the font % to be defined as <resname> instead of the name embedded in the data. % This is needed for subsetted fonts; it is valid if the CFF % contains only a single font. % Finally, PDF interpreter may request creation of CIDFont out of an % ordinary CFF font. /StartData { % <resname> <nbytes> StartData - currentfile exch subfilefilter //false //false ReadData pop } bind executeonly def /ReadData { % <resname> <file> <forceresname> <forcecid> ReadData <fontset> % Initialize. 30 dict begin /forcecidfont exch def /forceresname exch def /cff exch def /pos 0 def /resname exch cvlit def /DEBUG CFFDEBUG def % bring the binding closer /StringCache 1 dict def % Private DICT may be reused. forcecidfont [ { cff 1024 string readstring not { exit } if } loop ] .parsecff /fonts exch def resname mark fonts { forceresname { exch pop resname exch } if dup /CIDFontType known { % This is a CIDFont. dup /CIDFontName 3 index put 1 index exch /CIDFont defineresource } { % This is a font. dup /FontName 3 index put dup /FontType 2 put 1 index exch definefont } ifelse } forall .dicttomark end % temporary dict end % FontSetInit ProcSet /FontSet defineresource } bind executeonly def % ---------------- Resource category definition ---------------- % currentdict end readonly languagelevel exch 2 .setlanguagelevel /FontSet /Generic /Category findresource dup length dict .copydict /Category defineresource pop /FontSetInit exch /ProcSet defineresource pop .setlanguagelevel gs_type1.ps 0000644 00000030377 15030647507 0006664 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % Type 1 font support code. % The standard representation for PostScript compatible fonts is described % in the book "Adobe Type 1 Font Format", published by Adobe Systems Inc. /t1_glyph_equivalence mark % Exported for pf2afm.ps /Odblacute /Ohungarumlaut /Udblacute /Uhungarumlaut /odblacute /ohungarumlaut /udblacute /uhungarumlaut .dicttomark def % Define an augmented version of .buildfont1 that inserts UnderlinePosition % and UnderlineThickness entries in FontInfo if they aren't there already, % and FontBBox isn't degenerate. % (This works around the incorrect assumption, made by many word processors, % that these entries are present in the built-in fonts.) % Also add alternative names to some glyphs. /.buildfont1 { .currentglobal 3 1 roll dup .gcheck .setglobal dup .fontbbox { pop pop pop pop dup /FontInfo known not { //.growfontdict exec dup /FontInfo 2 dict put } if dup dup /FontInfo get dup dup /UnderlinePosition known exch /UnderlineThickness known and { pop pop % entries already present } { dup length 2 add dict .copydict dup /UnderlinePosition known not { dup /UnderlinePosition 3 index /FontBBox get 1 get 2 div put % 1/2 the font descent } if dup /UnderlineThickness known not { dup /UnderlineThickness 3 index /FontBBox get dup 3 get exch 1 get sub 20 div put % 1/20 the font height } if 1 index /FontInfo get wcheck not { readonly } if /FontInfo exch put } ifelse } if % We want to skip this process if we've already done it, and % not do it for embedded fonts. dup /.AGLprocessed~GS known not 1 index /PathLoad known and { dup /CharStrings get % Provide all known aliases for each glyph if % substitution is allowed (pf2afm.ps has code % to disables it by modifying t1_glyph_equivalence). t1_glyph_equivalence length 0 ne { % 16 byte scratch string % 16 bytes is arbitrary, but should be large enough to hold any "uniXXXX" style name //ReverseAdobeGlyphList //AdobeGlyphList 3 -1 roll % scratch(string) RAGL(dict) AGL(dict) CharStrings(dict) dup { % scratch(string) RAGL(dict) AGL(dict) CharStrings(dict) gname cstring exch dup % scratch(string) RAGL(dict) AGL(dict) CharStrings(dict) cstring gname gname 4 index exch .knownget { //true} { % scratch(string) RAGL(dict) AGL(dict) CharStrings(dict) cstring gname dup length 16 gt { //false } { % if we couldn't derive the code point from the AGL, we might derive it % from a formatted "uniXXXX" name. dup <00000000000000000000000000000000> cvs dup flush (uni) anchorsearch { % as luck would have it, we can just replace the "uni" with "16#" % to get something we can convert to a number pop pop dup 0 (16#) putinterval {cvi} //.internalstopped exec { pop //false} { % scratch(string) RAGL(dict) AGL(dict) CharStrings(dict) cstring gname cpoint dup 5 index exch known { //true } { pop //false } ifelse } ifelse } { pop pop //false} ifelse } ifelse } ifelse { % scratch(string) RAGL(dict) AGL(dict) CharStrings(dict) cstring gname cpoint % loop through the array of names for this codepoint % if the CharStrings dict doesn't contain an entry for the name % create one. 5 index exch .knownget { % scratch(string) RAGL(dict) AGL(dict) CharStrings(dict) cstring gname aglnames(array) { % scratch(string) RAGL(dict) AGL(dict) CharStrings(dict) cstring gname aglname dup 4 index exch known not { % scratch(string) RAGL(dict) AGL(dict) CharStrings(dict) cstring gname aglname CFFDEBUG { (\nsetting alias: ) print dup ==only ( to be the same as glyph: ) print 1 index //== exec } if 3 index exch 3 index .forceput % scratch(string) RAGL(dict) AGL(dict) CharStrings(dict) cstring gname }executeonly {pop} ifelse } executeonly forall pop pop } executeonly { pop pop pop } ifelse } executeonly { % scratch(string) RAGL(dict) AGL(dict) CharStrings(dict) cstring gname pop pop } ifelse } executeonly forall 3 1 roll pop pop } executeonly if pop dup /.AGLprocessed~GS //true .forceput } executeonly if %% We need to excute the C .buildfont1 in a stopped context so that, if there %% are errors we can put the stack back sanely and exit. Otherwise callers won't %% be able to execute this redefinied .buildfont1 in a stopped context and still %% usefully continue (because the stack will be altered, which it shold not be). %% %% Uncovered working on bug #696306 and fixed as part of that bug. %% {//.buildfont1} stopped 4 3 roll .setglobal {//.buildfont1 $error /errorname get signalerror} if } .bind executeonly def % hide .forceput % container for CloseSource flag (default //true to prevent buildup of file handles) /closesourcedict mark /CloseSource //true .dicttomark readonly def /.loadfont1 { % <file> .loadfont1 <errorflag> { % We would like to use `false /PFBDecode filter', % but this occasionally produces a whitespace character as % the first of an eexec section, so we can't do it. % Also, since the real input file never reaches EOF if we are using % a PFBDecode filter (the filter stops just after reading the last % character), we must explicitly close the real file in this case. % Since the file might leave garbage on the operand stack, % we have to create a procedure to close the file reliably. dup read not { -1 } if 2 copy .unread 16#80 eq { dup //closesourcedict //true /PFBDecode filter cvx exch .currentresourcefile eq { dup /.execasresource .systemvar } { {exec} } ifelse 2 index cvlit /closefile .systemvar 3 .execn } { cvx exec } ifelse } stopped } bind executeonly def % If the diskfont feature isn't included, define a dummy .loadfontdict. /.loadfontdict where { pop } { /.loadfontdict 0 dict readonly def } ifelse /.loadfontfile % <file> .loadfontfile - { mark exch % In order to load fonts reliably, we should push systemdict % here. However, Ed Taft says that Adobe implementations % push userdict and nothing else! % We really would just like systemdict on the stack, % but fonts produced by Fontographer require a writable dictionary. % However, we can't use any of the other well-known dictionaries % (such as userdict), since the whole point of pushing systemdict % is to make sure that nothing important has been redefined. 32 dict begin % We can't just use `run', because we want to check for .PFB files. currentpacking { //false setpacking //.loadfont1 exec //true setpacking } { //.loadfont1 exec } ifelse end { stop } if cleartomark } bind def % undefine stuff that is only used internally, and is immediately bound currentdict /closesourcedict .undef currentdict /.loadfont1 .undef % Note: this procedure is used for both Type 1 and Type 2 fonts. /.type1build { % <font> <code|name> <name> .type1build % <font> <code|name> <name> <charstring> 2 index begin dup CharStrings exch .knownget not { 2 copy eq { exch pop /.notdef exch } if QUIET not { (Substituting .notdef for ) print =string cvs print ( in the font ) print 1 index /FontName get = flush } { pop } ifelse /.notdef CharStrings /.notdef get } if end } bind def % Here are the BuildChar and BuildGlyph implementation for Type 1 fonts. % The names %Type1BuildChar and %Type1BuildGlyph are known to the interpreter. % The real work is done in an operator: % <font> <code|name> <name> <charstring> .type1execchar - (%Type1BuildChar) cvn { % <font> <code> %Type1BuildChar - 1 index /Encoding get 1 index get //.type1build exec .type1execchar } bind executeonly def (%Type1BuildGlyph) cvn { % <font> <name> %Type1BuildGlyph - dup //.type1build exec .type1execchar } bind executeonly def 1183615869 internaldict begin % CCRun is an undocumented procedure provided for Type 4 and Type 0 fonts. % Apparently there are two different argument lists for CCRun. % Handling the one with the extra Private dictionary requires fabricating % a Type 1 font on the fly, since we aren't currently prepared to parse the % dictionary any other way. /CCRun { % <font> <code|name> <charstring> CCRun - % <font> <code|name> <charstring> <Private> CCRun - dup type /dicttype eq { dup 4 index /Private .knownget { ne } { pop //true } ifelse { % The Private dictionary was supplied, and is different % from the Private dictionary of the font. Fabricate a % Type 1 font with this Private dictionary. Most of the % font entries are arbitrary or not needed. .currentglobal //false .setglobal 10 dict exch .setglobal begin /Private exch def /FontType 1 def /FontMatrix 3 index /FontMatrix get def /Encoding 3 index /Encoding .knownget not { StandardEncoding } if def /FontBBox 3 index /FontBBox .knownget not { {0 0 0 0} } if def /PaintType 0 def /CharStrings 1 dict dup /.notdef () put def 3 -1 roll pop () currentdict end .buildfont1 exch pop 3 1 roll } { pop } ifelse } if 1 index dup type /integertype eq { 3 index /Encoding get exch get } if exch .type1execchar } bind def % setweightvector is an undocumented procedure that force writes % weight vector to the font. Do extra checks for safety. /setweightvector { % <font> <vector> setweightvector - dup type dup /arraytype ne exch /packedarraytype ne and 2 index type /dicttype ne or { /setweightvector cvx /typecheck signalerror } if 1 index /FontType known not { /setweightvector cvx /invalidfont signalerror } if dup gcheck 2 index gcheck not and { /setweightvector cvx /invalidaccess signalerror } if 2 copy /WeightVector exch .forceput .setweightvector } .bind executeonly odef end % Register the font types for definefont. buildfontdict 1 /.buildfont1 cvx put buildfontdict 4 /.buildfont4 cvx put % Add Type 2 support if applicable. /.buildfont2 where not { (%END2) .skipeof } if pop (%Type2BuildChar) cvn { % <font> <code> %Type2BuildChar - 1 index /Encoding get 1 index get //.type1build exec .type2execchar } bind executeonly def (%Type2BuildGlyph) cvn { % <font> <name> %Type2BuildGlyph - dup //.type1build exec .type2execchar } bind executeonly def buildfontdict 2 /.buildfont2 cvx put %END2 gs_diskn.ps 0000644 00000015323 15030647507 0006724 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % Initialization file for %disk device modifications % When this is run, systemdict is still writable, systemdict begin % Collect the list of searchable IODevices in SearchOrder % Efficiency here doesn't matter since we run this at the end % of gs_init and convert it to a static array. /.getsearchabledevs { % - .getsearchabledevs [ list_of_strings ] //systemdict /.searchabledevs .knownget not { .currentglobal //true .setglobal mark (*) { dup length string copy dup currentdevparams /Searchable .knownget { not { pop } if } { pop } ifelse } 8192 string /IODevice resourceforall ] % now process the array into correct SearchOrder 0 1 2 { mark exch 2 index { dup currentdevparams /SearchOrder get 2 index eq { exch } { pop } ifelse } forall % devices on the old list pop % make the array and sort it by name ] { lt } bind .sort exch } for % collect all devices with SearchOrder > 2 mark 2 index { dup currentdevparams /SearchOrder get 2 gt { exch } { pop } ifelse } forall ] exch pop % We now have 4 arrays on the stack, SO=0 SO=1 SO=2 SO>2 % make them into a single array mark 5 1 roll ] mark exch { { } forall } forall ] //systemdict /.searchabledevs 2 index .forceput exch .setglobal } executeonly if } .bind executeonly odef % must be bound and hidden for .forceput % Modify .putdevparams to force regeneration of .searchabledevs list /.putdevparams { % We could be smarter and check for %disk* device, but this % doesn't get run enough to justify the complication //.putdevparams //systemdict /.searchabledevs .forceundef } .bind executeonly odef % must be bound and hidden for .forceundef % ------ extend filenameforall to handle wildcards in %dev% part of pattern -------% /filenameforall { count 3 ge { 2 index (%) search { pop pop } { % no device specified, so search them all pop (*%) 3 index concatstrings % we need to suppress the device when we return the string % in order to match Adobe's behaviour with %disk devices. 4 -2 roll % the callers procedure [ { (%) search { pop pop (%) search { pop pop } if } if } /exec load 4 -1 roll % the callers procedure /exec load ] cvx 4 2 roll % put the modified procedure where it belongs } ifelse % extract device portion (up to end of string or next %) (%) search { exch pop } if % stack: opat proc scratch npat device dup (*) search { pop pop pop //true } { pop //false } ifelse 1 index (?) search { pop pop pop //true } { pop //false } ifelse or not { pop pop //filenameforall % device with no wildcard } { (%) concatstrings (%) exch concatstrings .getsearchabledevs % find all matching devices and add the rest of the search string mark exch { dup counttomark 1 add index .stringmatch { counttomark 2 add index concatstrings } { pop } ifelse } forall ] 3 1 roll pop pop 4 -1 roll pop % now we need to invoke filenameforall for each of the strings % in the array. We do this by building a procedure that is like % an unrolled 'forall' loop. We do this to get the parameters % for each filenameforall, since each execution will pop its % parameters, but we can't use the operand stack for storage % since each invocation must have the same operand stack. mark exch { counttomark dup 3 add index exch 2 add index /filenameforall load } forall ] cvx 3 1 roll pop pop exec % run our unrolled loop } ifelse } { //filenameforall % not enough parameters -- just let it fail } ifelse } odef % redefine file to search all devices in order /file { dup 0 get (r) 0 get eq dup { pop //false % success code 2 index 0 get 37 eq { [ () ] } { .getsearchabledevs } ifelse { 3 index concatstrings % prepend the device { 2 index //file } //.internalstopped exec not { 4 1 roll pop pop pop //true exit % exit with success } { pop pop } ifelse } forall } if not { % just let standard file operator handle things //file } if } bind odef % redefine deletefile to search all devices in order /deletefile { //false % success code 1 index 0 get 37 eq { [ () ] } { .getsearchabledevs } ifelse { 2 index concatstrings % prepend the device { //deletefile } //.internalstopped exec exch pop not { pop //true exit % exit with success } if } forall not { $error /errorname get /deletefile .systemvar exch signalerror } if } bind odef % redefine status to search all devices in order /status { dup type /stringtype eq { //false % success code 1 index 0 get 37 eq { [ () ] } { .getsearchabledevs } ifelse { 2 index concatstrings % prepend the device { //status } //.internalstopped exec not { { //true 7 -2 roll pop pop //true exit } % exit with success if } if } forall % If we made it this far, no devices were found to status the file % clean up to return 'false' exch pop } { //status } ifelse } bind odef % Also redefine renamefile to search all devices in order /renamefile { //false % success code 2 index 0 get 37 eq { [ () ] } { .getsearchabledevs } ifelse { dup 4 index concatstrings % prepend the device { (r) //file } //.internalstopped exec not { closefile exch pop //true exit % exit with success } { pop pop } ifelse } forall not { $error /errorname get /renamefile .systemvar exch signalerror } if 3 -1 roll concatstrings exch //renamefile } bind odef % redefine devforall to process devices in numeric order % Spec's for 'devforall' are unclear, but font downloaders may expect this /devforall { % <proc> <scratch> devforall - [ { dup length string copy } 2 index //devforall ] % stack: proc scratch array_of_device_names { lt } .sort % We don't really invoke the procedure with the scratch string % but rather with the strings from our array exch pop exch forall } odef end % systemdict gs_wan_e.ps 0000644 00000003033 15030647507 0006700 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % Define the WinAnsi encoding vector. /currentglobal where { pop currentglobal { setglobal } //true setglobal } { { } } ifelse /WinAnsiEncoding ISOLatin1Encoding 0 39 getinterval aload pop /quotesingle ISOLatin1Encoding 40 5 getinterval aload pop /hyphen ISOLatin1Encoding 46 50 getinterval aload pop /grave ISOLatin1Encoding 97 30 getinterval aload pop /bullet % \20x % NOTE: /Euro, /Zcaron, and /zcaron are new for PDF 1.3. % We may have to take them out for backward compatibility. /Euro /bullet /quotesinglbase /florin /quotedblbase /ellipsis /dagger /daggerdbl /circumflex /perthousand /Scaron /guilsinglleft /OE /bullet /Zcaron /bullet /bullet /quoteleft /quoteright /quotedblleft /quotedblright /bullet /endash /emdash /tilde /trademark /scaron /guilsinglright /oe /bullet /zcaron /Ydieresis ISOLatin1Encoding 160 96 getinterval aload pop 256 packedarray 4 1 index .registerencoding .defineencoding exec gs_typ42.ps 0000644 00000004060 15030647507 0006572 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % Type 42 font support code. % Here are the BuildChar and BuildGlyph implementation for Type 42 fonts. % The names %Type42BuildChar and %Type42BuildGlyph are known to the % interpreter. The real work is done in an operator: % <font> <code|name> <name> <glyphindex> .type42execchar - /.type42build % <font> <code|name> <name> .type42build - { 2 index begin dup CharStrings exch .knownget not { 2 copy eq { exch pop /.notdef exch } if QUIET not { (Substituting .notdef for ) print =string cvs print ( in the font ) print 1 index /FontName get = flush } { pop } ifelse /.notdef CharStrings /.notdef get } if end .type42execchar } bind def (%Type42BuildChar) cvn % <font> <code> %Type42BuildChar - { 1 index /Encoding get 1 index get //.type42build exec } bind executeonly def (%Type42BuildGlyph) cvn % <font> <name> %Type42BuildGlyph - { dup //.type42build exec } bind executeonly def currentdict /.type42build .undef % Register the font type for definefont. buildfontdict 42 { % check for bogus sfnts -- this happens in Genoa FTS 421-01.ps dup /sfnts get 0 get length 14 lt { % smallest valid sfnts is 14 bytes % HACK: Add a BuildGlyph and make this a Type 3 font instead dup /FontType 3 put dup /BuildGlyph { 1 index /CharStrings get exch 2 copy known not { pop /.notdef } if get exec } bind put //.buildfont3 exec } { systemdict /.buildfont42 get exec } ifelse } bind put FAPIcidfmap 0000644 00000002713 15030647507 0006544 0 ustar 00 %! % $Id: FAPIcidfmap 6826 2006-05-31 15:29:52Z leonardo $ % This is a sample map file for FAPI CID fonts. % % The map is a set of records like this : % % /CIDfont_name options_dict ; % % where options_dict is a dictionary with the following entries : % % Key Type Description % Path string Absolute path to font file, or relative path to font file from % the GS_EXTFONTPATH value. % CIDFontType interger PostScript type for this CID font. Only 0 is currently allowed. % Note that this is unrelated to the real type of the font file - % the bridge will perform format conversion. % FAPI name Name of the renderer to be used with the font. Only /UFST is now allowed. % SubfontId integer (optional) Index of the font in font collection, such as FCO or TTC. % It is being ignored if /Path doesn't specify a collection. % Default value is 0. % CSI array Must have strongly 2 elements. % The first element of the array specifies Ordering of CIDSystemInfo. % The second element specifies Supplement of CIDSystemInfo. % % Use regular Postscript syntax. % % Examples : % % /Ryumin-Medium << /Path (msgothic.ttc) /CIDFontType 0 /FAPI /UFST /CSI [(Japan1) 2] >> ; % /HeiseiKakuGo-W5 << /Path (F:/WIN2000/Fonts/BATANG.TTC) /CIDFontType 0 /FAPI /UFST /CSI [(Japan1) 2] >> ; gs_std_e.ps 0000644 00000006107 15030647507 0006712 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % Define the standard encoding vector. /StandardEncoding % \00x /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef % \04x /space /exclam /quotedbl /numbersign /dollar /percent /ampersand /quoteright /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash /zero /one /two /three /four /five /six /seven /eight /nine /colon /semicolon /less /equal /greater /question % \10x /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O /P /Q /R /S /T /U /V /W /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore % \14x /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o /p /q /r /s /t /u /v /w /x /y /z /braceleft /bar /braceright /asciitilde /.notdef % \20x /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef % \24x /.notdef /exclamdown /cent /sterling /fraction /yen /florin /section /currency /quotesingle /quotedblleft /guillemotleft /guilsinglleft /guilsinglright /fi /fl /.notdef /endash /dagger /daggerdbl /periodcentered /.notdef /paragraph /bullet /quotesinglbase /quotedblbase /quotedblright /guillemotright /ellipsis /perthousand /.notdef /questiondown % \30x /.notdef /grave /acute /circumflex /tilde /macron /breve /dotaccent /dieresis /.notdef /ring /cedilla /.notdef /hungarumlaut /ogonek /caron /emdash /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef % \34x /.notdef /AE /.notdef /ordfeminine /.notdef /.notdef /.notdef /.notdef /Lslash /Oslash /OE /ordmasculine /.notdef /.notdef /.notdef /.notdef /.notdef /ae /.notdef /.notdef /.notdef /dotlessi /.notdef /.notdef /lslash /oslash /oe /germandbls /.notdef /.notdef /.notdef /.notdef % Make an array on large systems, a packed array on small ones. 256 vmstatus exch pop exch pop 100000 ge { array astore readonly } { packedarray } ifelse def 0 StandardEncoding .registerencoding /StandardEncoding StandardEncoding .defineencoding gs_mgl_e.ps 0000644 00000004205 15030647507 0006674 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % $Id: gs_mgl_e.ps 8954 2008-08-08 04:22:38Z ray $ % Define the Macintosh standard glyph encoding vector. % This is not an Encoding strictly speaking, but we treat it like one. /currentglobal where { pop currentglobal { setglobal } //true setglobal } { { } } ifelse /MacRomanEncoding .findencoding /MacGlyphEncoding /.notdef /.null /CR % 3 4 index 32 95 getinterval aload pop % 98 99 index 128 45 getinterval aload pop % 143 /notequal /AE /Oslash /infinity /plusminus /lessequal /greaterequal /yen /mu1 /partialdiff /summation /product /pi /integral /ordfeminine /ordmasculine /Ohm /ae /oslash /questiondown /exclamdown /logicalnot /radical /florin /approxequal /increment /guillemotleft /guillemotright /ellipsis /nbspace % 173 174 index 203 12 getinterval aload pop /lozenge % 186 187 index 216 24 getinterval aload pop /applelogo % 211 212 index 241 7 getinterval aload pop /overscore % 219 220 index 249 7 getinterval aload pop % 226 /Lslash /lslash /Scaron /scaron /Zcaron /zcaron /brokenbar /Eth /eth /Yacute /yacute /Thorn /thorn /minus /multiply /onesuperior /twosuperior /threesuperior /onehalf /onequarter /threequarters /franc /Gbreve /gbreve % The TrueType documentation says the next glyph is named % Idot, but the Adobe standard name for this glyph is % Idotaccent. /Idotaccent /Scedilla /scedilla /Cacute /cacute /Ccaron /ccaron /dmacron 260 -1 roll pop % delete MacRomanEncoding 258 packedarray 7 1 index .registerencoding .defineencoding exec gs_fapi.ps 0000644 00000036373 15030647507 0006543 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % Redefine Font and CIDFont categories with FAPI-handeled fonts. systemdict /.FAPIavailable known { //null .FAPIavailable } { //false } ifelse not { (%END FAPI) .skipeof } if languagelevel 2 .setlanguagelevel %==================================================================== % Redefine Font category with FAPIfontmap and CIDFont with FAPIfontmap : 15 dict begin % a temporary dictionary for local binding. /EmbedFontObjectsQuery mark /.EmbedFontObjects 0 .dicttomark def /is_device_compatible_to_FAPI % - is_device_compatible_to_FAPI <bool> { //true % removed a bogus check against EmbedFontObjectsQuery % % Temporary switch to allow override of FAPI and fallback to GS font rendering % to be removed at some date after FT integration is completed and released. % /DisableFAPI where { /DisableFAPI get not and }if % The code above assumes that only the requested parameter is rendered. % The commented-out code below may be useful for general case. % Keeping it for a while. % counttomark 2 idiv { % exch /.EmbedFontObjects eq { % counttomark 1 add 1 roll cleartomark % 0 eq exit % } if % } repeat % dup mark eq { % pop //true % } if } bind def %----------------------------- Process FAPIconfig ----------------------- % The HookDiskFonts and HookEmbeddedFonts take a simple array setting normally. % but if two or more FAPI plugins are built in, they can take a dictionary, % whose contents are the FAPI subtype string of a given plugin as the key, % and an array containing the (sub)set of font types the plugin should handle. % Any repetition of font types is ill advised since the resulting bevhaviour % will depend on the order entries are stored in the dictionary, which is % indeterminate. An attempt to use request a font scaler/renderer which cannot % deal with a given font type will result in the FAPI resorting to it's default % search for a viable plugin. % % As an example, you might want UFST to handle Truetype/Type 42 fonts, and % Freetype to handle others, thus: % /HookDiskFonts << /UFST [11 42] /FreeType [1 2 9] >> % /HookEmbeddedFonts << /UFST [11 42] /FreeType [1 2 9] >> /Config << % If we've got a FAPIConfig, run it now. systemdict /FAPIconfig known { /FAPIconfig .systemvar .runlibfile } if % Now setup defaults for any entries not set above - these defaults are correct % for FAPI/Freeetype currentdict /FontPath known not { /FontPath (/Fonts)} if % A default directory for FAPI-handled font files % path in FAPIfontmap. currentdict /CIDFontPath known not { /CIDFontPath (/CIDFonts)} if % A default directory for FAPI-handled CIDfont % files path in FAPIcidfmap. currentdict /HookDiskFonts known not { /HookDiskFonts [1 2 9 11 42] } if % FontType values for disk PS fonts to be % redirected to FAPI. currentdict /HookEmbeddedFonts known not { /HookEmbeddedFonts [1 2 9 11 42] } if % FontType values for embedded PS fonts to be % redirected to FAPI. /ServerOptions 2 dict >> def systemdict /.FAPIconfig //Config put /UFST .FAPIavailable { systemdict /UFST_SSdir known { /UFSTFONTDIR UFST_SSdir def systemdict /UFST_SSdir undef } { /UFSTROMFONTDIR (%rom%fontdata/) def UFSTROMFONTDIR (mtfonts/pcl45/mt3/plug__xi.fco) concatstrings status { pop pop pop pop /UFSTFONTDIR UFSTROMFONTDIR def } { /UFSTFONTDIR () def } ifelse } ifelse systemdict /UFST_PlugIn known not { systemdict /UFST_PlugIn UFSTFONTDIR (mtfonts/pcl45/mt3/plug__xi.fco) concatstrings put } if systemdict /FCOfontfile known not { systemdict /FCOfontfile UFSTFONTDIR (mtfonts/pclps2/mt3/pclp2_xj.fco) concatstrings put } if systemdict /FCOfontfile2 known not { systemdict /FCOfontfile2 UFSTFONTDIR (mtfonts/pcl45/mt3/wd____xh.fco) concatstrings put } if systemdict /FAPIfontmap known not { systemdict /FAPIfontmap (FCOfontmap-PCLPS2) put } if } if () systemdict /UFST_SSdir .knownget { (UFST_SSdir=) exch concatstrings concatstrings } if systemdict /UFST_PlugIn .knownget { 1 index length 0 ne { exch .filenamelistseparator concatstrings exch } if (UFST_PlugIn=) exch concatstrings concatstrings } if dup length 0 ne { //Config /ServerOptions get exch /UFST exch put } { pop } ifelse %------------------Copy the FontEmulationProcs here : ------------------- /FontEmulationProcs /ProcSet findresource { def } forall currentdict /super.complete_instance currentdict /complete_instance get put %-----------FAPI-specific methods for category redefinition : ----------- /RefinePath % <FontDict> /key RefinePath <FontDict> { exch begin //Config exch get /Path exch Path //false .file_name_combine not { exch (Can't combine paths ) print print ( and ) print = /RefinePath cvx /configurationerror signalerror } if def currentdict end } bind def /complete_instance % <font_name> <FontDict> <Options> complete_FAPI_Font <font_name> <FontDict> { //super.complete_instance exec dup /CIDFontName known { /CIDFontPath } { /FontPath } ifelse //RefinePath exec } bind def /IsMyRecord % <raw_record> -> <raw_record> bool { dup type /dicttype eq { dup /FAPI known } { //false } ifelse } bind def /IsActive % <record> IsActive <bool> { pop //is_device_compatible_to_FAPI exec } bind def /FontRecordVirtualMethods //RecordVirtualMethodsStub dup length 2 add dict copy begin /IsActive //IsActive def /MakeInstance % <Name> <record> MakeInstance <Name> <Instance> <size> { currentglobal 3 1 roll //true setglobal //FontOptions //complete_instance exec 2 copy //GetSize exec 4 3 roll setglobal } bind def currentdict end def /CIDFontRecordVirtualMethods //RecordVirtualMethodsStub dup length 3 add dict copy begin /GetCSI //TranslateCSI def /IsActive //IsActive def /MakeInstance % <Name> <record> MakeInstance <Name> <Instance> <size> { currentglobal 3 1 roll //true setglobal //CIDFontOptions //complete_instance exec 2 copy //GetSize exec 4 3 roll setglobal } bind def currentdict end def /ReadFCOfontmap: % <path> ReadFCOfontmap: name dict ... { /fontfile exch def { currentfile =string readline not { pop exit } if dup length 0 ne { 0 () /SubFileDecode filter dup token not { % A comment line closefile } { dup /EndFCOfontmap cvx eq { pop closefile exit } if exch dup token not { /ReadFCOfontmap: cvx /rangecheck signalerror } if exch dup token not { /StandardEncoding } { dup type /nametype ne { /ReadFCOfontmap: cvx /rangecheck signalerror } if } ifelse findencoding exch dup token not { //null } { dup type /nametype ne { /ReadFCOfontmap: cvx /rangecheck signalerror } if /Decoding findresource } ifelse exch closefile % index name enc dec|null 4 3 roll % name enc dec|null index << /Path fontfile /FontType 1 /FAPI /UFST /SubfontId counttomark 2 add -1 roll /Decoding counttomark 2 add -1 roll dup //null eq { pop pop } if /Encoding counttomark 2 add -1 roll /FontInfo << /UnderlineThickness 50 /Weight (Regular) /version (0.00) /ItalicAngle 0 /UnderlinePosition -100 /FamilyName () /Notice () /FullName () >> % although we pretend this is a Type 1, the FAPI interface currently % needs an identity FontMatrix /FontMatrix [0.001 0.0 0.0 0.001 0.0 0.0] % we need a fake CharStrings dictionary to placate certain jobs % which try to look inside it /CharStrings << /.notdef ( ) StandardEncoding { ( ) } forall >> % FontBBox will get replaced with valid numbers pulled from the rendering engine /FontBBox [-128 -128 1024 1024] cvx >> % dup { exch == = } forall } ifelse } { pop } ifelse } loop currentdict /fontfile undef } bind def %----------------------------------The Redefintion--------------------- /MappedCategoryRedefiner /ProcSet findresource /Redefine get /Redefine exch def % Redefine the /Font category : 4 dict begin /CategoryName /Font def /MapFileName systemdict /FAPIfontmap known {/FAPIfontmap .systemvar} {(FAPIfontmap)} ifelse def /VerifyMap { pop } bind def /PreprocessRecord % <map> <Name> <raw_record> PreprocessRecord <map> <Name> <record> <bool> { //IsMyRecord exec dup { pop dup /RecordVirtualMethods //FontRecordVirtualMethods put //true } if } bind def currentdict end Redefine % Redefine the /CIDFont category : 4 dict begin /CategoryName /CIDFont def /MapFileName systemdict /FAPIcidfmap known {/FAPIcidfmap .systemvar} {(FAPIcidfmap)} ifelse def /VerifyMap { pop } bind def /PreprocessRecord % <map> <Name> <raw_record> PreprocessRecord <map> <Name> <record> <bool> { //IsMyRecord exec dup { pop dup /RecordVirtualMethods //CIDFontRecordVirtualMethods put //true } if } bind def currentdict end Redefine %==================== A hook for buildfont* operators ==================== % The procedure .FAPIhook redirects PS fonts to FAPI on necessity. % This depends on the following conditions : % % 1. If font dictionary has /FAPI entry, it is a font listed in FAPIconfig.FontPath, % and must be build with .FAPIrebuildfont, or a copy of a font, which was % built with .FAPIrebuildfont . % % 2. If the font dictionary has /PathLoad entry, and has no /FAPI entry, % it is an installed PS font, which is described in lib/fontmap or % in GS_FONTPATH. .loadfont inserts /PathLoad entry for this case % (see gs_fonts.ps). % % Installed fonts are being loaded with GS font loader, % the they are passed to FAPI is same way as embedded fonts are. % We do so because UFST cannot read fonts, which don't % follow Type 1/42 file format strongly. % % 3. Executing .loadfont, we place /FAPI_hook_disable in the 0th % element of some procedure on the execution stack - see gs_fonts.ps . % If FAPI_hook finds /FAPI_hook_disable in there, % it knows that it is called for a disk font during % its internal definefont. % % 4. If font dictionary has no /FAPI entry, and has no /Path entry, % and if we are not in .loadfont context, it is an embedded font. % % 5. Two entries to be defined in lib/FAPIconfig to control the hooking of PS fonts : % HookDiskFonts and HookEmbeddedFonts . % They specify arrays of font types (integers) to be redirected with FAPI. % HookDiskFonts controls disk PS fonts (which fall into (2) and (3) ). % HookEmbeddedFonts controls fonts being embedded into documents. % % 7. We apply the operator .passtoFAPI for checking whether FAPI can handle a font. % If so, we insert /FAPI entry into the font dictionary and convert it % with .FAPIrebuildfont . Otherwise the font is handled with the native GS font renderer. /FAPI_hook_debug % <proc> FAPI_hook_debug - FAPIDEBUG { {exec} } { {pop} } ifelse bind def /FAPI_hook_warn % <proc> FAPI_hook_debug - QUIET { {pop} } { {exec} } ifelse bind def /FAPI_is_hook_disabled % - FAPI_is_hook_disabled <bool> { % checks whether execution stack contains packedarray started with /FAPI_hook_disable . /FAPI_hook_disable /MappedCategoryRedefiner /ProcSet findresource /execstack_lookup get exec //null ne } bind def /FAPIhook_aux % <string|name> <font_dict> .FAPIhook <string|name> <font> { % name <<font>> { (\nFAPIhook ) print 1 index = flush } //FAPI_hook_debug exec dup /FAPI known { { //PrintFontRef exec ( is mapped to FAPI=) print dup /FAPI get = flush } //FAPI_hook_debug exec //true .FAPIrebuildfont //ChooseDecoding exec } { dup /PathLoad known dup { { (PathLoad known for the font ) print //PrintFontRef exec (.\n) print flush} //FAPI_hook_debug exec } { pop //FAPI_is_hook_disabled exec dup { pop { (FAPIhook is in .loadfont context for the font ) print //PrintFontRef exec (.\n) print flush } //FAPI_hook_debug exec //true } if } ifelse { /HookDiskFonts } { /HookEmbeddedFonts } ifelse //Config exch get % name <<font>> [types] dup type /dicttype eq { //false exch { 3 index //GetFontType exec //FindInArray exec { 2 index exch /FAPIPlugInReq exch put pop //true exit } { pop } ifelse } forall } { 1 index //GetFontType exec //FindInArray exec % name <<font>> bHook } ifelse { { (Trying to render the font ) print //PrintFontRef exec ( with FAPI...\n) print flush } //FAPI_hook_debug exec .FAPIpassfont { { //PrintFontRef exec ( is being rendered with FAPI=) print dup /FAPI get = flush } //FAPI_hook_debug exec //false .FAPIrebuildfont //ChooseDecoding exec } { { (Can't render ) print //PrintFontRef exec ( with FAPI, will do with native GS renderer.\n) print flush } //FAPI_hook_warn exec } ifelse } { { (The font ) print //PrintFontRef exec ( doesn't need to render with FAPI.\n) print flush } //FAPI_hook_debug exec } ifelse % Remove the plugin request from the font dictionary dup /FAPIPlugInReq undef } ifelse } bind def /FAPIhook % <string|name> <font_dict> .FAPIhook <string|name> <font> { //is_device_compatible_to_FAPI exec { //FAPIhook_aux exec } { { (FAPIhook is disabled for the current device.\n) print flush } //FAPI_hook_debug exec } ifelse } bind def % ------------------ Redefine .buildfont* with FAPI : ----------------------- /.buildfont1 { //.buildfont1 exec //FAPIhook exec } bind % 'odef' is below. /.buildfont2 { //.buildfont2 exec //FAPIhook exec } bind % 'odef' is below. /.buildfont42 { //.buildfont42 exec //FAPIhook exec } bind % 'odef' is below. /.buildfont9 { //.buildfont9 exec //FAPIhook exec } bind % 'odef' is below. /.buildfont10 { //.buildfont10 exec //FAPIhook exec } bind % 'odef' is below. /.buildfont11 { //.buildfont11 exec //FAPIhook exec } bind % 'odef' is below. end % the temporary dictionary for local binding. odef odef odef odef odef odef % Undef these, not needed outside this file [ /.FAPIavailable /.FAPIpassfont /.FAPIrebuildfont ] systemdict .undefinternalnames .setlanguagelevel %END FAPI gs_resmp.ps 0000644 00000053722 15030647507 0006747 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % A procset to redefine a resource category with a resource map. % Public entries : % Redefine - a procedure for redefining a resource category with a map. % Methods for interpreting the resource map to be provided by client % in the argument dictionary. % % Note that the procedure Redefine is idempotential : % consequtive calls to it will not replace the category methods, % but will merge resource maps. If an interleaving redefinition % needs to cancel the idempotentity, it must remove the entry % /.IsRedefinedWithMap from the category dictionary. % MakeResourceEnumerator - this procedure is useful for % redefining any category. It provides a proper order of instances % and proper stacks during resourceforall. % BindWithCurrentdict - a procedure for generating temporary procedures % from templates, binding them with a local dictionary. % execstack_lookup - a procedure for communicating through the execution stack. % It allows for a callee to get an information from an indirect caller. % The procedures are designed for exeution witout putting % the procset instance onto the dictionary stack. languagelevel 2 .setlanguagelevel currentglobal //true setglobal /MappedCategoryRedefiner 10 dict begin % The procset. currentpacking //false setpacking /InstanceEnumeratorPattern % - InstanceEnumeratorPattern ... { % This is a pattern for enumeration procedure to be built dynamically, % applying BindWithCurrentdict with a temporary dictionary. % The following names will be replaced with specific objects % during BindWithCurrentdict : % en_local_dict - a dictionary for storing the local integer variable 'status'. % scr - the scratch string argument of resourceforall; % proc - the procedure argument of resourceforall; % InstancesStatus - a dictionary that maps resource instance names to their status value; % Category - the category to be enumerated. % When this procedure is called from ResourceForAll, the category is the current dictionary. % We remove it from the dictionary stack before performing the enumeration % to provide the <proc> to write to the underlying dictionary, % and put it back after the enumeration is completed. end { 0 1 2 { en_local_dict exch /status exch put InstancesStatus { en_local_dict /status get eq { scr cvs % ... (Font) proc exec % } { pop } ifelse % ... } forall } for % ... } stopped Category begin { stop } if } bind def % An auxiliary proc for BindWithCurrentdict : /.BindAux % <proc> BindAux <proc> { 0 exec } bind def setpacking /BindWithCurrentdict % <proc> BindWithCurrentdict <proc> { % Make a copy of the given procedure, binding in the values of all names % defined in currentdict. % Caution1 : this code cannot handle procedures that were already % bound recursively. % Caution2 : this code don't bind packedarrays. This was done % intentionally for a termination of the procedure tree. dup length array copy dup length 1 sub -1 0 { 2 copy get % {precopy} i {elem} dup dup type /arraytype eq exch xcheck and { % {precopy} i {elem} //.BindAux exec % {precopy} i {elem_copy} 2 index 3 1 roll put % {precopy} } { dup dup type /nametype eq exch xcheck and { % {precopy} i {elem} currentdict exch .knownget { 2 index 3 1 roll put % {precopy} } { pop } ifelse } { pop pop } ifelse } ifelse % {precopy} } for % {copy} cvx } bind def //.BindAux 0 //BindWithCurrentdict put % bind the recursive call in 'Bind'. /MakeResourceEnumerator % <proc> <scr> <InstancesStatus> MakeResourceEnumerator <Enumerator> { % Build the enumeration procedure : % Since the resourceforall procedure may leave values on the operand stack, % we cannot simply store the enumerator's local data on the stack. % We also cannot use a static dictionary to store local variables, % because of possible recursion in the resourceforall procedure. % To work around this, we create a copy of the enumeration procedure and % bind it dynamically with a temporary dictionary, which contains % local variables for the currently executing instance of resourceforall. % Always place the enumerator in local VM, % because its elements may be in local VM. currentglobal 4 1 roll //false setglobal currentdict % Category 6 dict begin % the temporary dictionary /Category exch def /InstancesStatus exch def /scr exch def /proc exch def /en_local_dict currentdict def //InstanceEnumeratorPattern //BindWithCurrentdict exec % Enumerator /status 0 def % variable for the current status to enumerate - do not bind with it ! end exch setglobal } bind def /execstack_lookup % <object> execstack_lookup <object1> % <object> execstack_lookup null { % Checks whether execution stack contains a procedure starting with <object>, % and retrives the 2nd element of the procedure, % or null if the procedure was not found. % % Since 'execstack' actually renders subarrays of procedures, % the pattern for recognition must be like this : % % { <object> <object1> % CallSomething % } loop % % The solution with 'loop' depends on how GS implements cycles, % so it must not appear in documents, which are required to be interpreter independent. % Any other type of cycles are also acceptable. % If no repitition is really needed, just insert 'exit' into its body. % If <object> <object1> are not needed for the caller, insert "pop pop" after them. % If <object1> is really unuseful, the pattern may be simplified : % % { <object> pop % CallSomething % exit % } loop % % It will retrieve 'pop' or 'null'. % % Note that 2 topmost execstack elements are the execstack_lookup procedure and its caller. % We don't check them. currentglobal //false setglobal % <object> bGlobal //false .countexecstack array //false .execstack % <object> bGlobal [execstack] dup //null exch % <object> bGlobal [execstack] null [execstack] length 3 sub -1 0 { % <object> bGlobal [execstack] null i 2 index exch get % <object> bGlobal [execstack] null proc dup type dup /packedarraytype eq exch /arraytype eq or { dup rcheck { dup length 1 gt { % <object> bGlobal [execstack] null proc dup 0 get % <object> bGlobal [execstack] null proc elem0 5 index eq { % <object> bGlobal [execstack] null proc 1 get % <object> bGlobal [execstack] null object1 exch pop exit % <object> bGlobal [execstack] object1 } { pop } ifelse } { pop % <object> bGlobal [execstack] false } ifelse } { pop % <object> bGlobal [execstack] false } ifelse } { pop % <object> bGlobal [execstack] false } ifelse } for % <object> bGlobal [execstack] bResult exch pop exch setglobal exch pop % bResult } bind def currentpacking //false setpacking /MethodsToRedefine 5 dict begin % Procedures in this dictionary really are patterns for new category methods. % The following names will be replaced with specific objects during BindWithCurrentdict : % .map - the map dictionary; % DefineResource, ResourceStatus, ResourceFileName, FindResource, ResourceForAll % - procedures from the original resource category. /FindResource % <Name> FindResource <dict> { RESMPDEBUG { (resmp FindResource beg ) print dup = } if dup ResourceStatus exec { pop 2 lt } { //false } ifelse % bInVirtualMemory { FindResource exec } { dup dup .map exch .knownget { % /Name /Name <<record>> dup dup /RecordVirtualMethods get /IsActive get exec { 1 index //.getvminstance exec { % /Name /Name <<record>> holder 1 get 1 eq } { //true } ifelse % /Name /Name <<record>> bStatusIs1 4 1 roll % bStatusIs1 /Name /Name <<record>> dup /RecordVirtualMethods get /MakeInstance get exec % bStatusIs1 /Name /Name Instance size 5 1 roll % size bStatusIs1 /Name /Name Instance DefineResource exec % size bStatusIs1 /Name Instance % Make ResourceStatus to return correct values for this instance : % Hack: we replace status values in the instance holder : exch //.getvminstance exec pop % size bStatusIs1 Instance holder dup 5 -1 roll 2 exch put % bStatusIs1 Instance holder 3 2 roll { % Instance holder 1 1 put % Instance } { pop } ifelse % Instance } { % /Name /Name <<record>> pop pop FindResource exec } ifelse } { % /Name /Name pop FindResource exec } ifelse } ifelse RESMPDEBUG { (resmp FindResource end) = } if } .bind def /ResourceStatus % <Name> ResourceStatus <status> <size> true % <Name> ResourceStatus false { RESMPDEBUG { (resmp ResourceStatus beg ) print dup //== exec } if dup ResourceStatus exec { % /Name status size 1 index 2 lt { % In VM - return with it. 3 2 roll pop //true } { % Not in VM. exch pop exch % size /Name dup .map exch .knownget { % size /Name <<record>> dup dup /RecordVirtualMethods get /IsActive get exec { 3 2 roll pop % /Name <<record>> dup /RecordVirtualMethods get /GetSize get exec 2 exch //true } { % size /Name <<record>> pop pop 2 exch //true } ifelse } { % size /Name pop 2 exch //true } ifelse } ifelse } { % /Name dup .map exch .knownget { % /Name <<record>> dup dup /RecordVirtualMethods get /IsActive get exec { dup /RecordVirtualMethods get /GetSize get exec 2 exch //true } { % /Name <<record>> pop pop //false } ifelse } { % /Name pop //false } ifelse } ifelse RESMPDEBUG { (resmp ResourceStatus end) = } if } .bind def /ResourceFileName % <Name> <scratch> ResourceFileName <string> { RESMPDEBUG { (resmp ResourceFileName beg ) print 1 index = } if exch % (scratch) /Name .map 1 index .knownget { % (scratch) /Name <<record>> RESMPDEBUG { (resmp ResourceFileName : have a map record.) = } if dup dup /RecordVirtualMethods get /IsActive get exec { RESMPDEBUG { (resmp ResourceFileName : record is active.) = } if dup /RecordVirtualMethods get /GetFilePath get exec % (string) RESMPDEBUG { (resmp ResourceFileName : retrieving ) print dup = } if } { % (scratch) /Name <<record>> RESMPDEBUG { (resmp ResourceFileName : record is NOT active.) = } if pop exch ResourceFileName exec RESMPDEBUG { (resmp ResourceFileName : retrieving ) print dup = } if } ifelse } { RESMPDEBUG { (resmp ResourceFileName : have NO map record.) = } if exch ResourceFileName exec RESMPDEBUG { (resmp ResourceFileName : retrieving ) print dup = } if } ifelse RESMPDEBUG { (resmp ResourceFileName end) = } if } .bind def /ResourceForAll % <template> <proc> <scratch> ResourceForAll - { RESMPDEBUG { (resmp ResourceForAll beg ) print CategoryName =string cvs print ( ) print 2 index = } if % Create InstancesStatus dictionary : 20 dict % IS - Instances Status 4 1 roll % <<IS>> (templ) {proc} (sctarch) % Check if we are under another ResourceForAll : /.DisableResourceOrdering //execstack_lookup exec //null eq 4 1 roll % <<IS>> bOrder (templ) {proc} (sctarch) % Put underlying resources to the InstancesStatus dictionary : currentdict % the category begin % ResourceForAll removes it locally. 2 index { cvn % <<IS>> bOrder (templ) {proc} (sctarch) /Name 4 index { dup ResourceStatus exec {pop 6 index 3 1 roll put} {pop} ifelse } { 5 index exch 2 put % Don't need the ordering, put '2' as a scratch. } ifelse } 2 index ResourceForAll exec % <<IS>> bOrder (templ) {proc} (sctarch) 4 3 roll pop % <<IS>> (templ) {proc} (sctarch) end % Put .map entries to the InstancesStatus dictionary : 4 -1 roll begin % (templ) {proc} (sctarch) .map { % (templ) {proc} (sctarch) /Name record dup dup /RecordVirtualMethods get /IsActive get exec { pop % (templ) {proc} (sctarch) /Name dup currentdict exch known { pop } { dup 2 index cvs % (templ) {proc} (sctarch) /Name (Name) 4 index .stringmatch { % (templ) {proc} (sctarch) /Name 2 def % It is not in VM. } { pop } ifelse } ifelse } { % (templ) {proc} (sctarch) /Name record pop pop } ifelse } forall % (templ) {proc} (sctarch) % prepare stacks for the enumeration : 3 2 roll pop % {proc} (sctarch) currentdict end % {proc} (scratch) <<IS>> % Make the enumerator and apply it : //MakeResourceEnumerator exec exec RESMPDEBUG { (resmp ResourceForAll end)= } if } .bind def /GetCIDSystemInfoFromMap % <Name> GetCIDSystemInfoFromMap <Name> % <Name> GetCIDSystemInfoFromMap <dict> { RESMPDEBUG { (resmp GetCIDSystemInfoFromMap beg ) print dup = } if % This is a special function for communicating with GetCIDSystemInfo in gs_cidcm.ps . dup .map exch .knownget { RESMPDEBUG { (resmp GetCIDSystemInfoFromMap : have a map record.) = } if dup /RecordVirtualMethods get /GetCSI get exec dup //null ne { RESMPDEBUG { (resmp GetCIDSystemInfoFromMap : retrieving a dict.) = } if exch } if pop } if RESMPDEBUG { (resmp GetCIDSystemInfoFromMap end) = } if } bind def currentdict end def setpacking /Redefine % <OptionsDict> Redefine - { % Before calling this proc, the OptionsDict must specify options for % the catregory to be redefined : % CategoryName - a name of category to redefine; % MapFileName - a string for the resource map file name; % VerifyMap - a procedure : % <raw_map> VerifyMap - % - checks the map for consistency % PreprocessRecord - a procedure : % <map> <Name> <raw_record> PreprocessRecord <map> <Name> <record> true % <map> <Name> <raw_record> PreprocessRecord <map> <Name> <raw_record> false % - converts a map record into a dictionary; % It must add RecordVirtualMethods dictionary to the record : % MakeInstance - a procedure : % <Name> <record> MakeInstance <Name> <Instance> <size> % - converts the record to resource instance; % GetFilePath - a procedure for ResourceFileName : % <scratch> <Name> <record> GetFilePath <filepath> % GetSize - a procedure for ResourceStatus : % <Name> <record> GetSize <size> % GetCSI - a procedure for obtaining CIDSystemInfo dictionary from the record : % <record> GetCSI <CSI> % <record> GetCSI null % IsActive - a procedure for skipping records depending on the current device : % <record> IsActive <bool> % Also it is allowed to contain additional entries for client's needs. % The OptionsDict is also used for storing some local variables. % If a category is being redefined several times with this function, % each redefinition must either use an unique map file, % or the map file should be scanned by the last redefinition % (and must be defined in the last one with /MapFileName). % This happens so because we must accumulate all variants of % methods before scanning the map. We would like to delay % the scanning until all redefinitions are done, but it requires % to implement a queue of "refinish" methods and execute it % at very end of the prelude. begin % OptionsDict CategoryName /Category findresource /OldCategory exch def OldCategory /.IsRedefinedWithMap known { % Already redefined with map - don't redefine, but enhance the map. OldCategory /NewCategory exch def } { % Redefine with a new category instance. OldCategory dup length dict dup /.PreprocessRecord 4 dict put copy /NewCategory exch def } ifelse % Provide the 'or' logic for PreprocessRecord, % to allow different record types to be mixed in a single map file. % We do this with building a dictionary of PreprocessRecord procedures, % which come from different calls to Redefine : NewCategory /.PreprocessRecord get dup length % <<pr>> l currentdict /PreprocessRecord get .growput currentdict /MapFileName known { MapFileName .libfile { 1 dict begin /; {} def mark exch cvx exec .dicttomark % <<map>> end dup VerifyMap % <<map>> } { QUIET not { currentdict /IsMapFileOptional .knownget not { //false } if not { (Warning: the map file ) print dup =string cvs print ( was not found.) = } if } if pop 0 dict % <<map>> } ifelse } { currentdict /.map .knownget not { 0 dict % <<map>> } if } ifelse % Preprocess entries : dup NewCategory /.PreprocessRecord get % <<map>> <<map>> <<pr>> 3 1 roll { % <<pr>> <<map>> /Name raw_record //false 3 1 roll % <<pr>> <<map>> false /Name raw_record 4 index { % <<pr>> <<map>> false /Name raw_record i {pr} exch pop % <<pr>> <<map>> false /Name raw_record {pr} exec { % <<pr>> <<map>> false /Name record 3 -1 roll pop //true 3 1 roll % <<pr>> <<map>> true /Name record exit } if % <<pr>> <<map>> false /Name raw_record } forall 3 2 roll { % <<pr>> <<map>> /Name record 2 index 3 1 roll put % <<pr>> <<map>> } { exch % <<pr>> <<map>> raw_record /Name (Incorrect record ) print =string cvs print ( of the map file ) print MapFileName =string cvs print (.) = end % Pops OptionsDict from dstack. pop pop pop % /Redefine cvx /undefinedresource signalerror } ifelse } forall % <<pr>> <<map>> exch pop % <<map>> % Add the map : OldCategory /.IsRedefinedWithMap known { % <<map>> % Just add to the old map : OldCategory /.map get copy pop % } { % <<map>> % Store the map to both the category and OptionsDict : dup NewCategory exch /.map exch put /.map exch def % } ifelse OldCategory /.IsRedefinedWithMap known not { % Copy old methods to OptionsDict : [ /DefineResource /ResourceStatus /ResourceFileName /FindResource /ResourceForAll ] { dup OldCategory exch get def } forall % Build new methods : //MethodsToRedefine { //BindWithCurrentdict exec NewCategory 3 1 roll put } forall CategoryName /CIDFont ne { NewCategory /GetCIDSystemInfoFromMap undef % This is some ugly, sorry. } if % Redefine the category : NewCategory /.IsRedefinedWithMap //true put CategoryName NewCategory /Category defineresource pop } if end % OptionsDict } bind executeonly def currentdict /PutPreprocessRecord .undef currentdict end /ProcSet defineresource pop setglobal .setlanguagelevel pdf_font.ps 0000644 00000300664 15030647507 0006727 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % PDF font operations. % Since PDF font are not unique and can collide with external font resources % or each other, use font dictionaries obtained from PDF directly, never % register them as resources or look them up by name. Use findfont oparator % for non-embedded fonts only. CIDFont resources still use the old logic % described below. % Finding a font by name can't give a proper result when PDF font names aren't unique. % But it is only the way to obtain a font in Postscript after a font file is executed. % Therefore using a FontName (and findfont) is allowed only % immediately after a font file is executed. % In all other cases the font to be found by a pointer through PDF structures. % % This ideal logics can't work for documents, % which define a font resource with an embedded font, % and another font resource with same BaseFont but with no embedded font % (and possibly with no font descriptor). % Our testbase does contain such examples. % In this case we do find font by FontName (with findfont), % since there is no other way to get a reasonable result. /.setlanguagelevel where { pop 2 .setlanguagelevel } if .currentglobal //true .setglobal /GS_PDF_ProcSet load begin % from userdict at this point pdfdict begin % We cache the PostScript font in an additional element of the % font resource dictionary, called PSFont. % ---------------- Encodings ---------------- % /.notdefEncoding 256 { /.notdef } repeat 256 packedarray def % Apply a list of differences to an Encoding. % Note that the differences may cause the array to grow. /updateencoding { % <encoding|null> <differences> updateencoding <enc'> % Calculate the length of the result. % in case the incoming Encoding is null, use .notdefEncoding exch dup //null eq { pop .notdefEncoding } if 0 0 3 index { dup type /nametype ne { exch pop oforce } { pop 1 add } ifelse % Differences list may not be in order, update the largest_index % stack: <Differences> <encoding> <largest_index> <at_index> 2 copy lt { exch pop dup } if % at_index is new largest } forall pop 1 index length .max array dup 0 4 -1 roll putinterval exch 0 exch { % Stack: enc' code element dup type /nametype ne { exch pop oforce } { 3 copy put pop 1 add } ifelse } forall pop } bind executeonly def /good_encoding_names << /MacRomanEncoding 0 /MacExpertEncoding 0 /WinAnsiEncoding 0 >> readonly def /known_symbolic_fonts << /Wingdings2 0 /ZapfDingbats 0 >> readonly def % Get the Encoding for a font. /getencoding % <base-encoding> <font-resource> getencoding <enc> { dup /Encoding knownoget { dup type /nametype eq { % The published PDF specification says the Encoding name % "must be" one of the 3 predefined Encodings, implying % that an error should occur if it isn't. However, Acrobat % Reader simply ignores unknown names, and since there are % some buggy applications that rely on this, we do the same. //good_encoding_names 1 index known { exch /BaseFont knownoget not { 0 } if % Ignore named encodings for known symbolic fonts. See bug 690135. //known_symbolic_fonts exch known { pop } { exch pop findencoding } ifelse } { pop pop } ifelse } { exch pop dup type /arraytype eq { exch pop ( **** Warning: Encoding is an array, not name or dictionary.\n) pdfformatwarning } { dup /BaseEncoding knownoget { %% Originally we ignored the specific invalid name '/' here from Bug #687786, however %% Bug #696942 contains an invalid BaseEncoding '/utf-8', so now we check all BaseEncoding %% against the permitted names, just as we do for Encodings. //good_encoding_names 1 index known{ findencoding 3 -1 roll pop exch }{ ( **** Error: Invalid BaseEncoding name ") print 256 string cvs print (" ignoring BaseEncoding.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror }ifelse } if /Differences knownoget { updateencoding } if } ifelse } ifelse } { pop ( **** Error: Encoding not present.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror } ifelse } bind executeonly def currentdict /good_encoding_names undef currentdict /known_symbolic_fonts undef /checkGlyphNames2Unicode % <dict> checkGlyphNames2Unicode - { PDFDEBUG { dup /FontInfo .knownget { /GlyphNames2Unicode .knownget { (Has GlyphNames2Unicode) = pop % { exch //== exec //== exec} forall } if } if } if pop } bind executeonly def % Define a font using it's FontName as the key. % Adjust a font according to the Encoding and Widths in the font resource. /adjustfont { % <font-resource> <font> adjustfont <font'> getfontencoding 3 copy .processToUnicode getfontmetrics 5 -1 roll pop .updatefont { %% Bug #696306 has a broken type 1 font where the eexec encrypted portion simply ends %% leaving a partial glyph description and, more importantly, the Private dictionary %% on the operand stack. Ths means the font dictonary does not contain a Private %% dictionary which causes .buildfont1 to throw an error. .completefont calls .buildfont1 %% (which is obscured by a definition in gs_type1.ps) so we need to check the reault %% of .completefont. If it fails we must discard the font dictionary and use a fallback. {.completefont} stopped { (\n *** ERROR: The font ) print /FontName get 256 string cvs print ( is damaged and cannot be used. Switching to a\n) pdfformaterror ( last-ditch fallback, text may not render correctly, or at all.\n\n) pdfformaterror /Helvetica findfont }if } if } bind executeonly def % Get the (possibly modified) encoding of a font. /getfontencoding { % <font-resource> <font> getfontencoding % <font-resource> <font> <Encoding|null> % Ignore encoding when TrueType is requested % and loaded from an embedded stream. % All other cases are left unchanged. dup /FontType get 42 eq 1 index /PathLoad known not and 2 index /Subtype get /TrueType eq and { //null } { % Acrobat appears to be always using StandardEcoding as the % default encoding for some non-symbolic fonts (rather than, % as the spec states, the encoding specified by the font). % As this is contrary to spec, and we only have a CFF % example, I've restricted this to fonts with Subtype Type1C % *and* that result in a Type 2 PS font. 1 index /FontDescriptor knownoget { dup % Unfortunately, Acrobat doesn't enforce the meaning of % FontFile[23] so whilst, in theory, Type1C should only % occur in FontFile3, we can't rely on that. dup /FontFile knownoget not { dup /FontFile2 knownoget not { dup /FontFile3 knownoget not {1 dict} if } if } if exch pop /Subtype knownoget {/Type1C eq}{//false} ifelse exch /Flags knownoget {4 and 4 eq not}{//false}ifelse and } {//false} ifelse 1 index /FontType get 2 eq and { 2 index /Encoding knownoget {pop StandardEncoding 2 index getencoding} { //null } ifelse } { 2 index /Encoding known { dup /Encoding knownoget { 2 index getencoding } { //null } ifelse } { //null } ifelse } ifelse } ifelse } bind executeonly def % Returns true if the current glyph is in the Differences array at % the specified index value. This is needed because the Widths % array may map to the same glyph at different positions from the % Encoding. We want to use the Width that was associated with the % one specified in the Encoding::Differences list. /match_in_diff % <Differences> <index> <glyphname> match_in_diff <bool> { //false 4 1 roll 0 4 -1 roll % stack: false index glyphname at_index==0 Differences { exch 1 index type /nametype ne { % stack: false index glyphname Diff_element at_index pop % Diff_element is new at_index } { % stack: false index glyphname Diff_element at_index exch 2 index eq { % stack: false index glyphname at_index dup 3 index eq { //true 5 1 roll % stack: true false index glyphname at_index pop exit } if } if 1 add % at_index++ stack: false index glyphname at_index' } ifelse } forall % stack: true false index glyphname % or : false index glyphname at_index pop pop pop } bind executeonly def /unique_name { % <dict> </root> unique_name </unique> % % Note : this function interacts with pdf_write_encoding in src/gdevpdtw.c % and with copied_drop_extension_glyphs in src\gxfcopy.c % by adding a reserved substring (~GS~). % .namestring % <<>> (root) 0 1 65535 { 5 string cvs % <<>> (root) (0) (~GS~) exch concatstrings 1 index exch % <<>> (root) (root) (~GS~0) concatstrings % <<>> (root) (root~GS~0) dup % <<>> (root) (root~GS~0) (root~GS~0) 3 index exch % <<>> (root) (root~GS~0) <<>> (root~GS~0) known not { exch pop exit % <<>> (root~GS~0) } if pop } for exch pop cvn % /root0 } bind executeonly def % Get the metrics of a font, if specified. /getfontmetrics { % <font-resource> <font> <Encoding|null> getfontmetrics % <font-resource> <font> <Encoding|null> % <Metrics|null> <GlyphMap|null> 2 index /Widths oknown { dup //null eq { pop dup /Encoding get } if 7 dict begin dup length dict /Metrics exch def /Encoding exch def /GlyphMap //null def exch dup /Widths oget /Widths exch def % Stack: font font-res % Note that widths are always based on a 1000-unit % character space, but the FontMatrix may specify % some other scale factor. Compensate for this here, % by scaling the Widths if necessary. 0.001 2 index /FontMatrix get 0 get dup 0 eq { % FontMatrix.xx == 0, so we cannot scale down by xx. % - FontMatrix[0] == 0 implies either FontMatrix[1] <> 0 or % FontMatrix cannot be inverted. In the 1st case we have % FontMatrixNonHV == true and will render text with cshow + xshow. % In the 2nd case, metrics in the PDF Font object cannot be enforced % [by altering metrics in PS glyph space]. % HACK: % - we scale down by FontMatrix[1]; % - given the format of Metrics entries we use, wy = 0 in glyph space; % - as a result, the cshow procedure receives as wy the value we % need for wx (all of this in PS user space). pop 2 index /FontMatrix get 1 get dup 0 eq { pop 1 } if % sorry, no way to enforce PDF metrics by altering the font } if div % Stack: font font-res mscale /FirstChar 2 index /FirstChar knownoget not { ( **** Warning: /FirstChar attribute is missing, assuming 0.\n) pdfformatwarning 0 } if def /LastChar 2 index /LastChar knownoget not { ( **** Warning: /LastChar attribute is missing, assuming 255.\n) pdfformatwarning 255 } if def Encoding length LastChar le { ( **** Warning: Font Encoding array size is smaller than character range.\n) pdfformatwarning } if 1 index /FontDescriptor knownoget { /MissingWidth knownoget not { 0 } if } { 1000 } ifelse /MissingWidth exch def Widths length LastChar FirstChar sub le { ( **** Warning: Font Widths array size is smaller than character range.\n) pdfformatwarning /Widths [Widths aload length LastChar FirstChar sub exch sub MissingWidth exch {dup} repeat] def } if FirstChar 0 Encoding { % Stack: font font-res mscale first-char index charname 1 index FirstChar lt { MissingWidth } { 1 index LastChar gt { MissingWidth } { Widths 2 index FirstChar sub get } ifelse } ifelse oforce % Stack: font font-res mscale first-char index charname width 4 index mul % The following 'loop' is only context for 'exit'. { % Work around a bug in pdfTeX, which can generate Encoding % vectors containing nulls : 1 index //null eq { exit } if Metrics 2 index .knownget { 1 index ne } { //false } ifelse { % Two or more Encoding elements refer same glyph name, % and Widths specify different wihts for it. % Since a Postscript font can't have different % Metrics for same glyph name, % we generate an unique name, and create a new % Charstrings entry with same glyph value. GlyphMap //null eq { /Encoding Encoding dup length array copy def /GlyphMap 4 dict def } if % To prevent too many new names, check whether % we can use one already created for same glyph. //true GlyphMap { % f r s c i n w b n1 n2 4 index eq { % f r s c i n w b n1 dup Metrics exch get % f r s c i n w b n1 w1 3 index eq { % f r s c i n w b n1 4 3 roll pop % f r s c i w b n1 3 1 roll pop % f r s c i n1 w Encoding 3 index 3 index put //false % f r s c i n1 w b exit } { pop } ifelse } { % f r s c i n w b n1 pop } ifelse } forall % f r s c i n w b { % Do create a new name. Metrics 2 index //unique_name exec % f r s c i n w nn Encoding 4 index 2 index put GlyphMap 1 index 5 -1 roll put % f r s c i w nn exch % Stack: font font-res mscale first-char index new_name width } if } if 2 copy Metrics 3 1 roll put exit } loop pop pop 1 add } forall pop pop pop exch Encoding Metrics GlyphMap end } { //null //null } ifelse } bind executeonly def currentdict /unique_name undef currentdict /match_in_diff undef /ToUnicodeCMapReader 4 dict begin /defineresource % <name> <dict> <cat-name> defineresource <dict> { pop dup userdict exch /.lastToUnicode exch put exch pop } bind executeonly def /CIDSystemInfo { ( **** Warning: ToUnicode CMap has invalid syntax near CIDSystemInfo.\n) pdfformatwarning /CIDSystemInfo } bind executeonly def % A work around a bug in Altona.Page_3.2002-09-27.pdf - a slash is missed. /CMapName { ( **** Warning: ToUnicode CMap has no CMapName.\n\ See the comment to revision 6201 in gs/doc/ps2pdf.htm#Problems .\n) pdfformatwarning /CMap1 % arbitrary, PDF defineresource tolerates non-unique names } bind executeonly def % A work around incorrect ToUnicode CMap generated by GS before rev. 6201. % Split large ranges into smaller chunks to stay withing the limits % of various PS% objects and speed up operand stack manipulation, % esp. "counttomatk -3 roll". Bug 691908. /beginbfrange { { pop mark 256 { currentfile token not { /endbfrange exit } if dup /endbfrange eq { exit } if currentfile token not { pop /endbfrange } if currentfile token not { pop pop /endbfrange } if dup ([) eq { pop [ { currentfile token not { exit } if dup (]) eq { pop exit } if } loop ] } if } repeat dup /endbfrange eq { pop endbfrange exit } { endbfrange mark } ifelse } loop } bind executeonly def currentdict end readonly def /string2number % <string> string2number <number> { 0 exch dup 0 exch 1 exch length 1 sub { % n () i 1 index exch get % n () v 3 2 roll 256 mul add exch % v+n*256 () } for pop % N } bind executeonly def /copy&def % <key> <value> <bool> copy&def - { { //true } { currentdict gcheck { dup gcheck not } { //false } ifelse } ifelse { currentglobal currentdict gcheck setglobal exch dup length string copy exch setglobal } if def } bind executeonly def /.convert_ToUnicode-into-g2u % <GlyphNames2Unicode> <Encoding|null> <CMap> .convert_ToUnicode-into-g2u - { CMAPDEBUG { (.convert_ToUnicode-into-g2u beg) = } if 3 2 roll begin /.CodeMapData get % About the data format see gs_cmap.ps, the comment after "CMap operators". 1 get % code maps { CMAPDEBUG { dup //== exec } if dup length 1 sub 0 exch 5 exch { % e [] i 2 copy get % e [] i (prefix) string2number % e [] i prefix 2 index 2 index 1 add get % e [] i prefix (key_size,?is_range,value_type,value_size) dup 0 get 8 mul % e [] i prefix (key_size,?is_range,value_type,value_size) key_size*8 3 2 roll exch bitshift exch % e [] i prefix<<key_size*8 (key_size,?is_range,value_type,value_size) dup 0 get exch 3 get % e [] i offset key_size value_size 4 index 4 index 2 add get % e [] i offset key_size value_size (keys) 5 index 5 index 3 add get % e [] i offset key_size value_size (keys) (values) CMAPDEBUG { ( offset=) print 4 index =string cvs print ( key_size=) print 3 index =string cvs print ( value_size=) print 2 index = ( keys=) print 1 index //== exec ( values=) print dup //== exec } if 1 index length 0 eq { % A single pair. exch pop exch pop exch pop exch % e [] i (values) offset 4 index //null ne { 4 index length 1 index gt { 4 index exch get } if } if % e [] i (values) cid|name exch CMAPDEBUG { ( defined single: ) print 1 index =string cvs print ( ) print dup //== exec } if //false copy&def % e [] i pop % e [] } { % A range. % e [] i offset key_size value_size (keys) (values) dup length string copy % protect the original string from modifications below. 0 4 index 2 mul 3 index length 1 sub { % e [] i offset key_size value_size (keys) (values) j 2 index 1 index 6 index getinterval string2number % e [] i offset key_size value_size (keys) (values) j keyL CMAPDEBUG { ( keyL=) print dup =string cvs print } if 3 index 2 index 7 index add 7 index getinterval string2number % e [] i offset key_size value_size (keys) (values) j keyL keyH CMAPDEBUG { ( keyH=) print dup = } if 3 2 roll 6 index idiv 5 index mul % e [] i offset key_size value_size (keys) (values) keyL keyH J 3 index exch 6 index getinterval % e [] i offset key_size value_size (keys) (values) keyL keyH (valueL) 3 1 roll 1 exch { % e [] i offset key_size value_size (keys) (values) (value) k 9 index //null ne { 9 index exch get % e [] i offset key_size value_size (keys) (values) (value) name } if % e [] i offset key_size value_size (keys) (values) (value) cid|name 1 index % e [] i offset key_size value_size (keys) (values) (value) cid|name (value) CMAPDEBUG { ( defined from range: ) print 1 index =string cvs print ( ) print dup //== exec } if //true copy&def % e [] i offset key_size value_size (keys) (values) (value) %% Calculate the value from the last string dup dup length 1 sub 0 exch 0 1 3 -1 roll { % (string) value index exch 256 mul exch 2 index exch get add } for %% and increment the value for the next string 1 add %% Now convert the value into a string of bytes. 1 index length 1 sub 1 exch 0 1 3 -1 roll { % (string) value divisor index 2 index 2 index idiv 255 and % (string) value divisor index byte exch 4 index length 1 sub exch sub % (string) value divisor byte string_position 5 index % (string) value divisor byte string_position (string) exch 3 -1 roll put % (string) value divisor 256 mul } for pop pop pop } for % e [] i offset key_size value_size (keys) (values) (value) } for pop pop pop pop pop pop pop % e [] } ifelse } for pop % e } forall end pop % CMAPDEBUG { (.convert_ToUnicode-into-g2u end) = } if } bind executeonly def /.DoToUnicode? { /IgnoreToUnicode where {/IgnoreToUnicode get not} {//true} ifelse } bind executeonly def /.processToUnicode % <font-resource> <font-dict> <encoding|null> .processToUnicode - { //.DoToUnicode? exec { currentdict count 1 sub /.stackdepth exch .forceput currentdict countdictstack /.dstackdepth exch .forceput { 1 index /FontType get 0 eq { 1 index /FDepVector get 0 get dup /FontType .knownget not { dup /CIDFontType .knownget { dup 2 eq {pop 11} if } {-1} % just some value that's not a valid font type ifelse }if 11 eq { /Path known} {pop //false} ifelse } {//false} ifelse % Currently pdfwrite is only device which can handle GlyphNames2Unicoide to % generate a ToUnicode CMaps. So don't bother with other devices. /WantsToUnicode /GetDeviceParam .special_op { exch pop }{ //false }ifelse or { PDFDEBUG { (.processToUnicode beg) = } if 2 index /ToUnicode knownoget { dup type /nametype eq { % This is contrary to the specification but it seems that Acrobat at least will accept % a ToUnicode with a value of Identity-H *and* will use that for search, copy/paste. % We can't pass through a name, so the best we can do is build a GlyphNames2Unicode % map matching that which would have been generated by a full 16-bit Identity CMap % % See bug numbers 701003 and 687351 % dup /Identity-H eq 1 index /Identity-V eq or{ pop 1 index /FontInfo .knownget not { currentglobal 2 index dup gcheck setglobal /FontInfo 5 dict dup 5 1 roll .forceput setglobal } executeonly if dup /GlyphNames2Unicode .knownget not { //true % No existing G2U, make one } { dup wcheck { //false % Existing, writeable G2U, don't make new one } { pop //true % Existing read only G2U, make new one } ifelse } ifelse { currentglobal exch dup gcheck setglobal dup /GlyphNames2Unicode 100 dict dup 4 1 roll .forceput 3 2 roll setglobal } if % font-res font-dict encoding|null font-info g2u 0 1 65535{ % g2u index dup dup 256 mod exch 256 idiv % g2u index lo-byte hi-byte 2 string dup 0 4 -1 roll % g2u index lo-byte () () 0 hi-byte put % g2u index lo-byte (x) dup 1 % g2u index lo-byte (x) (x) 1 4 -1 roll put % g2u index (x) (x) 1 lo-byte -> dict index (xx) 2 index % g2u index (xx) dict 3 1 roll % g2u g2u index (xx) put % g2u } for pop % font-res font-dict encoding|null font-info pop % font-res font-dict encoding|null //false % We built a GlyphNames2Unicode table, don't need to process further } executeonly { //true % name is not Identity-V or H, fail by falling through }ifelse } executeonly { //true } ifelse % not a name, try as a dictionary (as specified) % If the ToUnicode isn't a name, or the name isn't Identity-V or -H then follow the specification % If its not a dictionary type throw an error, otherwise decode it and build a GlyphNames2Unicode % { dup type /dicttype eq { dup /File known not } { //true } ifelse { % We undefine wrong /Length and define /File in stream dictionaries. % Bug687351.pdf defines /ToUnicode /Identity-H, what is incorrect. ( **** Warning: Ignoring bad ToUnicode CMap.\n) pdfformatwarning pop } { /PDFScanRules .getuserparam dup //null eq { pop //PDFScanRules_null } { 1 dict dup /PDFScanRules 4 -1 roll put } ifelse //PDFScanRules_true setuserparams PDFfile fileposition 3 -1 roll count 1 sub countdictstack { //false resolvestream % Following Acrobat we ignore everything outside % begincodespacerange .. endcmap. dup 0 (begincodespacerange) /SubFileDecode filter flushfile /CIDInit /ProcSet findresource begin //ToUnicodeCMapReader begin 12 dict begin /CMapType 2 def mark exch % emulate 'begincodespacerange' 0 (endcmap) /SubFileDecode filter cvx /begincmap cvx exch 2 .execn endcmap userdict /.lastToUnicode currentdict put end end end } PDFSTOPONERROR { { exec } 0 get //false 5 -2 roll 5 } { { stopped } 0 get 4 2 roll 4 } ifelse array astore cvx exec countdictstack exch sub 0 .max { end } repeat count exch sub 2 sub 0 .max { exch pop } repeat 3 1 roll % Stach the stop flag. PDFfile exch setfileposition setuserparams { ( **** Warning: Failed to read ToUnicode CMap.\n) pdfformatwarning } { 1 index /FontInfo .knownget not { currentglobal 2 index dup gcheck setglobal /FontInfo 5 dict dup 5 1 roll .forceput setglobal } if dup /GlyphNames2Unicode .knownget not { //true % No existing G2U, make one } { dup wcheck { //false % Existing, writeable G2U, don't make new one } { pop //true % Existing read only G2U, make new one } ifelse } ifelse { currentglobal exch dup gcheck setglobal dup /GlyphNames2Unicode 100 dict dup 4 1 roll .forceput 3 2 roll setglobal } if % font-res font-dict encoding|null font-info g2u exch pop exch % font-res font-dict g2u encoding|null userdict /.lastToUnicode get % font-res font-dict g2u Encoding|null CMap .convert_ToUnicode-into-g2u % font-res font-dict //null % font-res font-dict //null } ifelse } ifelse } if PDFDEBUG { (.processToUnicode end) = } if } executeonly if } executeonly if } executeonly stopped { .dstackdepth 1 countdictstack 1 sub {pop end} for .stackdepth 1 count 3 sub {pop pop} for } if pop pop pop currentdict /.stackdepth .forceundef currentdict /.dstackdepth .forceundef } executeonly {pop pop pop} ifelse } bind executeonly odef currentdict /.DoToUnicode? .forceundef % ---------------- Descriptors ---------------- % % Partial descriptors for the 14 built-in fonts. Note that % from PDF 1.1 to PDF 1.2, the meaning of the Flag 6 in the FontDescriptor % object has undergone a subtle change in its meaning which has serious % consequences for searching with Acrobat: % In PDF 1.1, the flag meant: Font has StandardEncoding % In PDF 1.2, the flag means: Font has (subset of) StandardRomanCharacterSet /standardfontdescriptors mark /Courier mark /Flags 16#23 .dicttomark /Courier-Oblique 1 index /Courier-Bold 1 index /Courier-BoldOblique 1 index /Helvetica mark /Flags 16#20 .dicttomark /Helvetica-Oblique 1 index /Helvetica-Bold 1 index /Helvetica-BoldOblique 1 index /Times-Roman mark /Flags 16#22 .dicttomark /Times-Bold 1 index /Times-Italic mark /Flags 16#62 .dicttomark /Times-BoldItalic 1 index /Symbol mark /Flags 16#4 .dicttomark /ZapfDingbats 1 index .dicttomark readonly def % ---------------- Utilities ---------------- % /.pdforigfontcache_g 20 dict def currentglobal //false setglobal systemdict /.pdforigfontcache_l 20 dict .forceput setglobal % Find an original font, using cache to prevent adjustfont to accumulate changes. /pdffindcachedfont { % <font_name> pdffindcachedfont <font> dup //.pdforigfontcache_g exch .knownget { exch pop } { dup .pdforigfontcache_l exch .knownget { exch pop } { dup findfont dup dup gcheck { //.pdforigfontcache_g } { .pdforigfontcache_l } ifelse % Stack : font_name font font cache 4 2 roll .growput } ifelse } ifelse } bind executeonly def % Add original font to cache to prevent adjustfont to accumulate changes. /pdfaddcachedfont { % <font_name> pdfaddcachedfont <font> dup findfont dup % name font font dup gcheck { //.pdforigfontcache_g } {.pdforigfontcache_l} ifelse 4 2 roll % font d name font put % font } bind executeonly def /.remove_font_name_prefix { % <name> .remove_font_name_prefix <name> dup .namestring (+) search { //true exch { dup 65 lt exch 90 gt or { pop //false exit } if } forall { pop exch pop cvn } { pop pop } ifelse } { pop } ifelse } bind executeonly def % Find a font (except for embedded ones), and adjust its encoding if necessary. /.pdfdfndict mark /defaultfontname /Helvetica .dicttomark readonly def % This code attempts to use the FontName and FontDescriptor to find a % 'better' match for a missing font than the default font. There % are a list of fonts and mappings here (TTfonts) and in gs_font.ps % (.substitutefaces) which we can use to map from a requested font % family name to a substitute family. If that fails we check the % FontDescriptor Flags to attempt a (very slightly) better match. % We use Times-Roman for serif fonts and Helvetica for non-serif. % This all seems pretty poor to me, but its long-standing, so we % won't attempt to meddle with it. /pdfsubstitutefont { % Stack: font-res fontname fontdesc dup /Flags oget dup 16#40 and -6 bitshift % 1, oblique/italic 1 index 16#40000 and -17 bitshift add % 2, bold exch 16#2 and 2 bitshift add % 8, serif % We should look at the fixed flag, too. % Stack: font-res fontname fontdesc properties % Even though /FontName is a required key in FontDescriptor dict % (As of the PDF 1.4 Reference Manual), In the case of missing % /FontName key, we substitue /BaseFont for the value of /FontName. % Yet another case of broken PDF's that Adobe Reader accepts. 1 index dup /FontName known { /FontName oget dup type /nametype ne { ( **** Error: /FontName in FontDescriptor is not a name.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror cvn } if } { ( **** Error: FontDescriptor missing required /FontName key. BaseFont name used.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror pop 2 index % grab the BaseFont from the stack. } ifelse .remove_font_name_prefix exch % Analyzes font name and extract "Bold" and "Narrow" properties % which are not described by the FontDescriptor Flags. % We also allow the font name analysis to override the Flags setting % for Italic/Oblique as this gives us results more consistent with % Acrobat. 0 2 index //.fontnameproperties exec 7 and or % Rebind the default font name to Helvetica so that % fonts with no properties are handled correctly. //.pdfdfndict begin .substitutefontname end % Stack: font-res fontname fontdesc substname|null Fontmap 1 index known {//false} { .buildnativefontmap pop NativeFontmap 1 index known not} ifelse { % No available good substitution, use the standard one. pop 1 index .substitutefont } if dup 3 index ne { QUIET not { (Substituting font ) print dup =only ( for ) print 2 index =only (.) = flush } if % Send a warning to the device, in case its pdfwrite and we are in PDF/A mode % In that case the substituted font may not (probably doesn't) have glyphs which % match the /Widths of the original font, and that will cause a fault with PDF/A % so we need to let the device know. /SubstitutedFont /EventInfo .special_op } if pdffindcachedfont % Stack: font-res fontname fontdesc font % Some non-compliant files are missing FirstChar/LastChar, % despite referencing a non-base14 font 3 index /FirstChar knownoget { 0 % push an initial value for accumating the Widths 0 string % and an empty string to interrogate the font 7 index /Widths knownoget { 0 1 2 index length 1 sub { dup 2 index exch get dup type /packedarraytype eq {exec} if % Handle entries which are indirect references (seriously ? !!) dup 0 gt % We ignore entries of zero in the widths array { exch 5 index add % add FirstChar to the idx to get a char code dup 64 gt 1 index 91 lt and % we only want to consider A~Z and.... 1 index 96 gt 2 index 123 lt and or % ... a~z { exch 5 -1 roll add 4 1 roll % add the width to the accumulator on the stack 1 string dup 0 4 -1 roll put 3 -1 roll concatstrings exch % add the char code to the string } { pop pop } ifelse } { pop pop } ifelse } for pop % get rid of the Widths array 3 -1 roll pop % get rid of the FirstChar value dup length dup 0 gt { 3 -1 roll exch div % calculate an average width from the Widths array gsave 2 index 10 scalefont setfont exch dup length exch stringwidth grestore pop 100 mul exch div div % Only make the font smaller/narrower, not larger/wider dup 1.0 lt { 0 0 2 index 0 0 6 array astore exch //true .copyfontdict dup /FontMatrix get 3 -1 roll matrix concatmatrix exch dup 3 -1 roll /FontMatrix exch put % we don't need to definfont here, we can leave that to .completefont below } { pop } ifelse } { % no suitable Widths entries - carry on and hope for the best...... pop pop pop } ifelse } { % Broken file: no Widths array for non-base14 font - carry on and hope for the best...... ( **** Warning: Widths array missing in FontDescriptor for non-base14 font\n) pdfformatwarning pop pop pop } ifelse } { ( **** Warning: FirstChar value missing in FontDescriptor for non-base14 font\n) pdfformatwarning } ifelse % Stack: font-res fontname fontdesc font % If this is a small-caps font, replace the CharString % entries for a..z. exch /Flags oget 16#20000 and 0 ne { //true .copyfontdict dup /CharStrings 2 copy get dup length dict .copydict % stack: font-res fontname font font /CharStrings CharStringsdict 5 index /FirstChar get 97 .max 6 index /LastChar get 122 .min 1 exch { % Stack: font-res fontname font' font' /CharStrings charstrings code % Note that this only remaps a-z, not accented characters. 6 index /Widths oget 1 index 8 index /FirstChar get sub oget 1 string dup 0 5 -1 roll put % Stack: font-res font' font' /CharStrings charstrings code % width (x) 2 index exch dup cvn exch dup 0 2 copy get 32 sub put 4 -1 roll { % Stack: operand (X) width 0 setcharwidth exch pop currentfont /FontMatrix get matrix invertmatrix concat 0.7 dup scale 0 0 moveto show } /exec cvx 4 packedarray cvx put } for put } if dup /FontName get 2 index ne { //true .copyfontdict 2 copy exch /FontName exch put } if exch pop .completefont } bind executeonly def /pdffindfont { % <font-resource> <fontname> pdffindfont <font> % If the font isn't available, synthesize one based on % its descriptor. dup /Font resourcestatus { pop pop pdffindcachedfont } { 1 index /FontDescriptor knownoget { /SUBSTFONT where not { pdfsubstitutefont } { % User has defined SUBSTFONT, use the defined substitute font, do not % try to be clever pop % the dictionary containing SUBSTFONT pop % the FontDescriptor pdffindcachedfont }ifelse } { % No descriptor available, use the default algorithm. pdffindcachedfont } ifelse } ifelse exch pop } bind executeonly def % ---------------- Type 1 fonts ---------------- % /buildType1 % <Type1-font-resource> buildType1 <font> { dup /BaseFont get pdffindfont } bind executeonly def % Read an embedded Type 1 font. /readfontfilter { % <proc> readfontfilter <filter> 0 () /SubFileDecode filter } bind executeonly def % Adobe Acrobat doesn't skip space characters after eexec /eexec_pdf_param_dict mark .eexec_param_dict {} forall /keep_spaces //true .dicttomark readonly def % When Type 1 font reading procedure is executing, a copy of this dictionary is current. % topFontDict allows us to *attempt* to handle the case where a Type 1 font definition % does not start by creating it's own dictionary (i.e. a number of the keys end up in % the currentdict rather than the font dictionary). % The whole type1 stream can be executed directly. There's no need to process % Length1, 2, 3 keys. /readtype1dict 10 dict dup begin /prev_definefont /definefont load def /definefont { % if a font defines any keys outside it's own dictionary, % this attempts to cope by copying them into the font dictionary [ /FontType % in PLRM order /FontMatrix /FontName /FontInfo /WMode /Encoding /FontBBox /UniqueID /XUID /PaintType /StrokeWidth /Metrics /Metrics2 /CDevProc /CharStrings /Private /WeightVector ] { 2 copy known {pop} { dup where { 1 index get 2 index 3 1 roll put dup /MisplacedKey 0 put } {pop} ifelse } ifelse } forall dup /MisplacedKey known { ( **** Warning: Type 1 font defines some required keys outside the font dictionary.\n) pdfformatwarning } if dup /CharStrings get /.notdef known not { dup /CharStrings get /.notdef <9E35CED7FFD3622F09> put ( **** Warning: Type 1 font has no /.notdef entry in /CharString dictionary.\n) pdfformatwarning } if dup /UniqueID .knownget { dup dup 0 lt exch 16#ffffff gt or { ( **** Warning: Ignoring invalid /UniqueID = ) exch =string cvs concatstrings (\n) concatstrings pdfformatwarning dup /UniqueID undef } { pop } ifelse } if prev_definefont } bind executeonly def /undef_proc_warning { /Repaired //true store % flag that we have warnings UndefProcList exch 2 copy .knownget { 1 add } { 1 } ifelse put } bind executeonly def /missing-type1-procs 6 dict begin /-| { string currentfile exch readstring pop /-| //undef_proc_warning exec } executeonly bdef /RD { string currentfile exch readstring pop /RD //undef_proc_warning exec } executeonly bdef /|- { noaccess def /|- //undef_proc_warning exec } executeonly bdef /ND { noaccess def /ND //undef_proc_warning exec } executeonly bdef /| { noaccess put /| //undef_proc_warning exec } executeonly bdef /NP { noaccess put /NP //undef_proc_warning exec } executeonly bdef currentdict end readonly def /eexec { % Assume the font dictionary is directly below the file on the stack count 0 gt { /topFontDict 2 index cvlit store } if //eexec_pdf_param_dict /eexecDecode filter //missing-type1-procs begin /userdict .systemvar begin //systemdict begin readtype1dictcopy begin cvx stopped currentfile flushfile % Skip the trailer after return from eexec, bug 690701. { currentdict end //missing-type1-procs eq { exit } if } loop { stop } if } bind executeonly def /readonly-op-dict << /stringtype 0 /arraytype 0 /packedarraytype 0 /dicttype 0 >> readonly def /readonly { % bug 689617 dup type //readonly-op-dict exch known not { ( **** Warning: Type 1 font applies operator readonly to an invalid object type.\n) pdfformatwarning } if } bind executeonly def /prev_get /get load def /get { dup /FontName eq { % No warning, probably FontName is defined elsewhere; see definefont above. .knownget not { /Missing } if } { dup /UniqueID eq { % We don't want fonts to check /UniqueID and do 'restore'. pop pop 16#FEDCBA98 % Arbitrary and invalid value } { prev_get } ifelse } ifelse } bind executeonly def /prev_begin /begin load def /begin { dup //systemdict eq { pop 0 dict } if prev_begin } bind executeonly def { /undef_proc_warning /missing-type1-procs /readonly-op-dict } { currentdict exch undef } forall % Bug703454.pdf contains a number of fonts with multiple definitions % of a given glyph name in the CharStrings dict - i.e. two entries % for /a - the first of which is "correct" the second is "wrong". % Normal Postscript behaviour replaces the first value with the second % for the given key/value pair. % To handle this, *only* for Type 1 fonts embedded in PDFs, we % have a special definition of "def" which won't overwrite existing % values in the CharStrings dict. /def { 3 index /CharStrings eq currentdict 3 index known and { pop pop } { systemdict /def get exec } ifelse } bind executeonly def end readonly def currentdict /eexec_pdf_param_dict .undef /readtype1 { % <font-resource> <stream-dict> readtype1 <font|null> PDFfile fileposition 3 1 roll % pos res stream dup /PFB known exch % pos res pfb? stream //true resolvestream % pos res pfb? file exch { //false /PFBDecode filter % pos res file' } if % Some buggy embedded fonts leave extra junk on the stack, % so we have to make a closure that records the stack depth % in a fail-safe way. This code also removes the mark when % the implied cleartomark is not executed, i.e. Length3 == 0. % Also restore dictstack depth. % //systemdict begin //readtype1dict dup length 5 add dict copy begin % pos res file' /file-position 4 -1 roll def % res file' /stack-count count 3 sub def 1 index /BaseFont oget /savedFontName exch def /topFontDict //null def /readtype1dictcopy currentdict def cvx stopped { currentdict /topFontDict known not { end } { exit } ifelse } loop { /topFontDict //null def } if PDFfile file-position setfileposition count stack-count sub { pop } repeat topFontDict end end } bind executeonly def % ---------------- Type 3 fonts ---------------- % /buildType3 { % <Type3-font-resource> buildType3 <font> 8 dict begin /FontType 3 def % If the font does not contain a Resources entry, then we use % the resources from our current context. Page 391 of the PDF % 1.6 spec says that the Resources dict is optional and if not % present then we should use the Resources for the page. % However we have a test file (687989) which uses a Type3 font % inside a form XObject and the desired Resources are in the % XObject dict and not in the Page dict. So we are going to % the parent object to find resources instead of only going to % the page dict when a font does not specify its required % resources. /Resources 1 index /Resources knownoget { oforce } { 0 dict } ifelse def /FontBBox 1 index /FontBBox get cvx def /FontMatrix 1 index /FontMatrix oget def /CharProcs 1 index /CharProcs oget def 1 index /Widths knownoget { /Widths exch def 1 index /FirstChar known 2 index /LastChar known and { /FirstChar 1 index /FirstChar oget def /LastChar 1 index /LastChar oget def } { ( **** Error: Requireed entry FirstChar or LastChar is missing from Font.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror /FirstChar 0 def /LastChar Widths length def }ifelse } if /FontName 1 index /Name knownoget not { /PDFType3Untitled } if def /Encoding .notdefEncoding 2 index getencoding def % We have to define BuildChar rather than BuildGlyph: % there is no PDF equivalent of glyphshow, and we need % the character code to access the Widths. /BuildChar { % Stack: font charcode 1 index begin 4 dict begin /Font 3 -1 roll def /CharCode 1 index def Encoding exch get CharProcs exch knownoget { dup /Length get 0 eq { pop %% Detect a 0 length stream. If this occurs %% then we won't execute d0 or d1, and so won't adjust the %% character width. So, pretend we got a %% null d1, just so that we can adjust using the /Widths %% (Bug 697805) 0 0 0 0 0 0 pdfopdict /d1 get exec }{ { dup //false resolvestream % Stack: filepos streamdict stream % Don't let setgcolor set the color inside the BuildGlyph % procedure, because this causes an /undefined error. q %% This is (currently) needed to make sure that the current dictionary, which is %% 'nodict' because we did a gsave, is writeable. If we don't execute gput %% to make a writeable copy then it is a no access dicitonary and the 'def' %% below will fail. It would be nice to fix the cases of this someday, but %% we use 'nodict'[ to store other PDF state stuff that isn't gstate, and we %% probably always will, so it may well be more trouble than its worth. /Dummy //false gput Font /Resources get % Stack: filepos streamdict stream resdict dup length 0 eq { 3 -1 roll /Resources knownoget { exch pop ( **** Warning: Type 3 font has resource dictionary in glyph stream.\n) pdfformatwarning } if } { 3 -1 roll pop } ifelse exch pdfopdict /BuildCharDictDepth countdictstack def .pdfruncontext countdictstack BuildCharDictDepth sub { //pdfdict /.Qqwarning_issued .knownget {not}{//true} ifelse { (\n **** Warning: Type 3 glyph has unbalanced q/Q operators \(too many q's\)\n Output may be incorrect.\n) pdfformatwarning //pdfdict /.Qqwarning_issued //true .forceput } executeonly if Q } executeonly repeat Q } executeonly PDFfile fileposition 2 .execn % Keep pdfcount valid. PDFfile exch setfileposition } executeonly ifelse } executeonly { % PDF Type 3 fonts don't use .notdef % d1 implementation adjusts the width as needed 0 0 0 0 0 0 pdfopdict /d1 get exec } ifelse end end } executeonly bdef dup currentdict Encoding .processToUnicode currentdict end .completefont exch pop } bind executeonly odef /.adjustcharwidth { % <wx> <wy> .adjustcharwidth <wx'> <wy'> % Enforce the metrics, in glyph space, to the values found in the PDF Font object % - force wy == 0 (assumed, and not stored in the PDF font) % Even though PDF1.3-1.7 specifications state that this must be 0, % Distiller sometimes creates Type3 fonts with non-zero wy. We set % it to 0 since this is apparently what Acrobat Reader 4 and 5 do. % PDF1.2 does not mention this restriction, it only says % "see setcharwidth/ setcachedevice in the PostScript Reference". % - get wx from the Widths array (do nothing if not present) pop 0 /Widths where { begin CharCode FirstChar ge CharCode LastChar le and { exch pop Widths CharCode FirstChar sub get exch } if end } if } bind executeonly def % ---------------- TrueType fonts ---------------- % /TTfonts mark /Arial /Helvetica /Arial,Italic /Helvetica-Oblique /Arial,Bold /Helvetica-Bold /Arial,BoldItalic /Helvetica-BoldOblique /CourierNew /Courier /CourierNew,Bold /Courier-Bold /TimesNewRoman /Times-Roman /TimesNewRoman,Italic /Times-Italic /TimesNewRoman,Bold /Times-Bold /TimesNewRoman,BoldItalic /Times-BoldItalic .dicttomark readonly def /buildTrueType { % <TrueType-font-resource> buildTrueType <font> dup /BaseFont oget dup /font_name gput 1 index /FontDescriptor knownoget { /Flags knownoget { 4 and 0 ne { //true } % symbolic { 1 index /Encoding oknown not} % no encoding => symbolic ifelse } {//false} ifelse } {//false} ifelse /is_symbolic gput 1 index /Encoding oknown { StandardEncoding 3 index getencoding } { //null } ifelse /prebuilt_encoding gput //false /.render_notdef gput % set the default dup /Font resourcestatus dup { exch pop exch pop } if not TTfonts 2 index known and { dup TTfonts exch get QUIET not { (Substituting font ) print dup =only ( for ) print 1 index =only (.) = flush } if exch 3 1 roll pdffindfont //true .copyfontdict 2 copy exch /FontName exch put exch pop .completefont } { pdffindfont } ifelse } bind executeonly def % Read an embedded TrueType font. /readtruetype { % <font-resource> <stream-dict> readtruetype <font> 1 index exch PDFfile fileposition 3 1 roll //true resolvestream readfontfilter % Stack: filepos fontres stream 1 index /CIDSystemInfo oknown { 1 index /CIDSystemInfo get dup type /packedarraytype eq {exec}if dup /Registry known not { ( **** Warning: a CIDFont's CIDSystemInfo is missing the required Registry entry\n) pdfformatwarning dup /Registry (Adobe) put } if dup /Ordering known not { ( **** Warning: a CIDFont's CIDSystemInfo is missing the required Ordering entry\n) pdfformatwarning dup /Ordering (Identity) put } if dup /Supplement known not { ( **** Warning: a CIDFont's CIDSystemInfo is missing the required Supplement entry\n) pdfformatwarning dup /Supplement 0 put } if 3 1 roll 1 index /Subtype knownoget { /CIDFontType2 ne { ( **** Error: Subtype of a TT CID font is not /CIDFontType2\n) pdfformaterror 1 index /Subtype /CIDFontType2 put ( Output may be incorrect.\n) pdfformaterror } if } { ( **** Error: Subtype of a TT CID font is missing.\n) pdfformaterror 1 index /Subtype /CIDFontType2 put ( Output may be incorrect.\n) pdfformaterror } ifelse 1 index /BaseFont get % Use the BaseFont name for the font. Otherwise we % would use the name table, or a manufactured name. .loadttcidfont % Stack: filepos fontres cidfont } { % filepos fontres stream 1 index /FontDescriptor oget /Flags oget dup % only believe the symbolic flag if the non-symbolic flag is not also set! 4 and 0 ne exch 32 and 0 eq and { //true % symbolic } { 1 index /Encoding oknown not % no encoding => symbolic } ifelse 2 index /Encoding oknown { StandardEncoding 3 index getencoding } { //null } ifelse dup 4 index exch % filepos fontres stream is_symbolic Encoding fontres Encoding /prebuilt_encoding exch put % filepos fontres stream is_symbolic Encoding 5 index /BaseFont get % Use the BaseFont name for the font. Otherwise we % would use the name table, or a manufactured name. .loadpdfttfont } ifelse exch pop PDFfile 3 -1 roll setfileposition % Ignore both the Encoding and the Widths. exch pop } bind executeonly def % ---------------- Type 0 fonts ---------------- % % Predefine the known CMaps, but only create them on demand. /knownCMaps mark /Identity-H { /Identity-H 0 makeIdentityCMap } /Identity-V { /Identity-V 1 makeIdentityCMap } .dicttomark def /makeIdentityCMap { % <cmapname> <wmode> .makeIdentityCMap - .currentglobal //true .setglobal 3 1 roll /CIDInit /ProcSet findresource begin 12 dict begin begincmap /WMode exch def /CMapName exch def /CIDSystemInfo 3 dict dup begin /Registry (Adobe) def /Ordering (Identity) def /Supplement 0 def end def %/CMapName (see above) /CMapVersion 1 def /CMapType 1 def %WMode (see above) % The PDF documentation says that these CMaps map CIDs % "1 to 65,536". This is a misprint for 0 to 65,535. 1 begincodespacerange % <0001> <00ff> <0100> <ffff> <0000> <ffff> endcodespacerange 1 begincidrange % <0001> <00ff> 1 <0100> <ffff> 256 <0000> <ffff> 0 endcidrange endcmap CMapName currentdict /CMap defineresource knownCMaps CMapName 2 index put end % CMap end % CIDInit ProcSet exch .setglobal } bind executeonly def /CMap_read_dict 3 dict begin /defineresource % <name> <dict> <cat-name> defineresource <dict> { pop /.last_CMap_def 1 index store exch pop } bind executeonly def /CIDSystemInfo { ( **** Error: CMap has invalid syntax near CIDSystemInfo.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror /CIDSystemInfo } bind executeonly def % A work around a bug in Altona.Page_3.2002-09-27.pdf - a slash is missed. /CMapName { ( **** Error: CMap has no CMapName.\n\ See the comment to revision 6201 in gs/doc/ps2pdf.htm#Problems .\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror /CMap1 % arbitrary, PDF defineresource tolerates non-unique names } bind executeonly def % A work around incorrect ToUnicode CMap generated by GS before rev. 6201. currentdict end readonly def % Read an embedded stream that we *hope* is a PostScript CMap. According % to the spec, ths isn't legal, but 'Acrobat opens it'.... % /read_CMap { dup mark exch 0 (begincodespacerange) /SubFileDecode filter cvx exec cleartomark {currentdict dup /CMapType known not {end}{pop exit} ifelse} loop /CMapType 1 def mark exch % emulate 'begincodespacerange' 0 (endcmap) /SubFileDecode filter cvx /begincmap cvx exch 2 .execn endcmap currentdict end dup /CMapName get exch /CMap defineresource end } bind executeonly def % Read embedded CMap stream. % if the <wmode> parameter is null, it indicates there is no WMode, and we % should not add one. % Following Acrobat we ignore everything outside % begincodespacerange .. endcmap. /read_CMap_stream { % <info> <wmode> <name> <stream> read_CMap <CMap> dup 0 (begincodespacerange) /SubFileDecode filter flushfile //CMap_read_dict begin /CIDInit /ProcSet findresource begin 12 dict begin /o.endmapvalue /.endmapvalue load def /.endmapvalue { dup 65535 gt { ( **** Warning: CMap: CID out of valid range (0-65535).\n) pdfformatwarning pop 65535 } if o.endmapvalue } bind def 4 2 roll dup //null eq { pop } { /WMode exch def } ifelse dup //null eq { pop } { /CIDSystemInfo exch def } ifelse /CMapType 1 def /.last_CMap_def currentdict def % establish binding mark exch % emulate 'begincodespacerange' 0 (endcmap) /SubFileDecode filter cvx /begincmap cvx exch 2 .execn currentdict /o.endmapvalue undef endcmap /.last_CMap_def load { currentdict end //CMap_read_dict eq { exit } if } loop dup /.last_CMap_def undef /CMap defineresource } bind executeonly def currentdict /CMap_read_dict undef /buildType0 { % <Type0-font-resource> buildType0 <font> dup /BaseFont get % FontName 1 index /Encoding oget dup type /nametype eq { dup /CMap resourcestatus { pop pop /CMap findresource } { knownCMaps 1 index .knownget { exch pop exec } { /undefined signalerror } ifelse } ifelse } { %% Bug #696449 Acrobat will read an embedded PostScript %% CMap, whcih according to the spec is not valid, it needs %% to be a PDF CMap stream. Here we check and see if it looks like a CMap %% dictionary. If it is we proceed, if its some other kind of dictionary, %% throw an error, if its neither, treat it as a stream and hope for the best. dup /Type known { dup /Type get /CMap eq { PDFfile fileposition exch dup /CIDSystemInfo knownoget { << exch { oforce } forall >> } { //null } ifelse exch dup /WMode knownoget not {//null} if exch dup /CMapName knownoget not {/null} if exch //true resolvestream read_CMap_stream exch PDFfile exch setfileposition } { PDFSTOPONERROR { /buildType0 cvx /syntaxerror signalerror } if } ifelse }{ PDFfile fileposition exch //true resolvestream read_CMap exch PDFfile exch setfileposition } ifelse } ifelse % CMap [ 3 index /DescendantFonts oget { exec resourcefont } forall ] % subfonts .composefontdict % composefont must insert FontInfo dictionary - see gs_cmap.ps . % Stack: fontres name font 3 copy exch pop //null .processToUnicode exch pop .completefont % Stack: fontres font 1 index /FontMatrix knownoget { dup aload pop //true {0 0 1 0 0 1} {3 -1 roll eq and} forall { 1 index exch makefont exch /FontName get exch exch pop .completefont } { pop } ifelse } if exch pop } bind executeonly def % ---------------- CIDFontType0/2 fonts ---------------- % % Insert metrics into a CIDFont, by saving the PDF W, W2, DW, and DW2 % arrays and using a (currently very inefficient) CDevProc. % For detail, refer "PDF Reference" 2nd ed., p314 "5.6.3 CIDFonts". % It notes default DW is 0, but Acrobat Reader uses 1000 as default. % If DW is 0, currentpoint does not move by default in rendering text % horizontally, the result is unreadable. You can check it by Acrobat. /.pdfDefaultDW 1000 def /.pdfDefaultDW2 [ 880 -1000 ] def /addCIDmetrics { % <CIDFont-resource> <CIDFont> addCIDmetrics <fontdict> dup length 5 add dict .copydict dup /FID undef dup /UniqueID undef dup /XUID undef % Insert the widths into the font. % Stack: pdfresource newfont 1 index /DW knownoget { 1 index /DW 3 -1 roll put } { dup /DW .pdfDefaultDW put } ifelse 1 index /W knownoget { //false 1 index { xcheck or } forall { oforce_array } if dup 2 index /W 3 -1 roll put .pdfMakeInternalW 1 index /.internalW 3 -1 roll put } if 1 index /DW2 knownoget { 1 index /DW2 3 -1 roll put } { dup /DW2 .pdfDefaultDW2 put } ifelse 1 index /W2 knownoget { //false 1 index { xcheck or } forall { oforce_array } if dup 2 index /W2 3 -1 roll put .pdfMakeInternalW2 1 index /.internalW2 3 -1 roll put } if dup /CDevProc 1 index /CIDWProc load /exec load 3 packedarray cvx put exch pop } bind executeonly def /.pdfMakeInternalMTXArray { % <mtx_array> <item_size> .pdfConvertInternalW <mtx_array'> % convert /W or /W2 to internal expression % % mtx_array: original /W or /W2 array % item_size: number of metrics values per CID % % for detail of the metrics list format in PDF, % refer PDF Ref. p.317 "Glyph Metrics in CIDFonts". % % format of single entry in internal expression % % [ % [cid_begin cid_end] % value_is_varied (bool) % [ [values for cid_begin...] % [values for cid_begin + 1] % ... ] % ] % 7 dict begin /itemSize exch def /M exch def % original /W or /W2 /Msize M length def /Mi { M i get } def % W[i] /Mi1 { M i 1 add get } def % W[i + 1] /putMTXEntry << /arraytype { [ [Mi Mi Mi1 length itemSize idiv add 1 sub] //true [ 0 itemSize Mi1 length 1 sub { [ exch 1 1 index itemSize add 1 sub { Mi1 exch get } for ] } for ] ] /i i 2 add def } /integertype { [ [Mi Mi1] //false [[ i 2 add 1 i 1 add itemSize add { M exch get } for ]] ] /i i 2 add itemSize add def } >> def /i 0 def [ { putMTXEntry Mi1 type get exec i Msize ge { exit } if } loop ] end } executeonly def /.pdfMakeInternalW { dup length 0 gt { oforce_recursive 1 .pdfMakeInternalMTXArray } if } executeonly def /.pdfMakeInternalW2 { dup length 0 gt { oforce_recursive 3 .pdfMakeInternalMTXArray } if } executeonly def /.pdfGetMTXByCID { % <internalMTXArray> <cid> % .pdfGetMTXByCID % { <MTXEntry> true | false } % get values for given CID from internal format of /W or /W2 exch { { dup 0 get {} forall % Stack: <cid> <entry> <cid_0> <cid_1> 3 index lt { pop pop //false exit } if 2 index exch sub dup 0 lt { pop pop //false exit } if 1 index 1 get not { pop 0 } if exch 2 get exch get //true exit } loop { exit } if } forall dup type /arraytype eq { exch pop //true } { pop //false } ifelse } executeonly def % Apply the [D]W[2] metrics to a character before displaying. /CIDWProc { % <w0x> <w0y> <llx> <lly> <urx> <ury> % <w1x> <w1y> <vx> <vy> <cid> <font> CIDWproc % <w0x'> ... <vy'> begin % push <font> to currentdict % <w1x> <w1y> <vx> <vy> won't be used and replaced, discard now 5 1 roll pop pop pop pop % get FontMatrix that applies to this CID % (needs to convert [D]W[2] values to glyph space) currentdict /FontMatrix get % if the currentfont is a CIDFontType 0 CIDFont, % we need FDArray font's FontMatrix too FontType 9 eq { currentdict 2 index .type9mapcid % <w0x> <w0y> <llx> <lly> <urx> <ury> <cid> <FontMatrix> (charstring) <FDArray#> exch pop currentdict /FDArray get exch get /FontMatrix get % <w0x> <w0y> <llx> <lly> <urx> <ury> <cid> <FontMatrix> <FontMatrix2> matrix concatmatrix } if % preserve this FontMatrix at bottom of the stack 8 1 roll % Stack: <FontMatrix> <w0x> <w0y> <llx> <lly> <urx> <ury> <cid> { currentdict /DW .knownget not { % no DW .pdfDefaultDW exit % replace <w0x> by defaultDW } if currentdict /.internalW .knownget not { % no W exit % use already-stacked DW } if dup length 0 eq { % W is null array pop % discard unusable W exit % use already-stacked DW } if % W is finite array, try to get W_cid 2 index .pdfGetMTXByCID { % got W, discard DW exch pop {} forall exit } if exit } loop 0 % <w0y'> % Stack: <FontMatrix> <w0x> <w0y> <llx> <lly> <urx> <ury> <cid> <w0x'> <w0y'> 9 -2 roll pop pop % discard <w0x> <w0y> 7 2 roll % put <w0x'> <w0y'> % Stack: <FontMatrix> <w0x'> <w0y'> <llx> <lly> <urx> <ury> <cid> 0 % <w1x'> exch % put <w1x'> % Stack: <FontMatrix> <w0x'> <w0y'> <llx> <lly> <urx> <ury> <w1x'> <cid> { currentdict /DW2 .knownget not { % no DW2, use defaultDW2 .pdfDefaultDW2 exit } if currentdict /.internalW2 .knownget not { % has DW2, no W2 exit % use already-stacked DW2 } if dup length 0 eq { % W2 is null array pop % discard unusable W2 exit % use already-stacked DW2 } if 2 index .pdfGetMTXByCID { % got W2_cid, discard DW2 exch pop exit } if % could not get W2_cid exit } loop exch pop % discard <cid> % Stack: <FontMatrix> <w0x'> <w0y'> <llx> <lly> <urx> <ury> % <w1x'> { [<vy'> <w1y'>] | [<w1y'> <vx'> <vy'>] } dup length 2 eq { % this is DW2 aload pop exch 8 index 2 div % <vx'> = <w0x'> / 2 exch } { % assume W2 aload pop } ifelse % Stack: <FontMatrix> <w0x'> <w0y'> <llx> <lly> <urx> <ury> <w1x'> <w1y'> <vx'> <vy'> % now, convert each metrics valude (1000th of text space) to glyph space 10 -2 roll % Stack: <FontMatrix> <llx> <lly> <urx> <ury> <w1x'> <w1y'> <vx'> <vy'> <w0x'> <w0y'> 3 { 10 index idtransform exch 1000 div exch 1000 div 6 2 roll } repeat 10 2 roll % Stack: <FontMatrix> <w0x'> <w0y'> <llx> <lly> <urx> <ury> <w1x'> <w1y'> <vx'> <vy'> 11 -1 roll pop % Stack: <w0x'> <w0y'> <llx> <lly> <urx> <ury> <w1x'> <w1y'> <vx'> <vy'> end % recover currentdict } bind executeonly def % <string> <match> tailmatch ==> <pre> true % ==> <string> false /tailmatch { 2 copy length 1 index length .min dup 2 index length exch sub exch getinterval 1 index eq { length 1 index length exch sub 0 exch getinterval //true } { pop //false } ifelse } bind executeonly def /makeboldfont { 16 dict begin /strokewidth exch def /basecidfont exch def /FontMatrix [ 1 0 0 1 0 0 ] def /CIDFontName /.boldfont def /CIDFontType 1 def /basefont-H /.basefont-H /Identity-H [ basecidfont ] composefont def /basefont-V /.basefont-V /Identity-V [ basecidfont ] composefont def /CIDSystemInfo dup basecidfont exch get def /FontBBox [ basecidfont /FontBBox get cvx exec 4 2 roll basecidfont /FontMatrix get transform 4 2 roll basecidfont /FontMatrix get transform ] def /tmpstr 2 string def /BuildGlyph { gsave exch begin dup 256 idiv tmpstr exch 0 exch put 256 mod tmpstr exch 1 exch put rootfont /WMode known { rootfont /WMode get 1 eq } { //false } ifelse { basefont-V } { basefont-H } ifelse setfont strokewidth setlinewidth 1 setlinejoin newpath 0 0 moveto tmpstr //false charpath stroke 0 0 moveto tmpstr show currentpoint setcharwidth end grestore } bind def currentdict end dup /CIDFontName get exch /CIDFont defineresource } bind executeonly def % <CIDFont-resource> <CIDFontName> findCIDFont <CIDFont-resource> <font> % CIDFont-resource is not modified. % In various places we do: % "findCIDFont dup /OrigFont .knownget {exch pop} if" % because the CIDFont we find may have been "patched" to apply metrics from % the PDF file (W, W2, etc). We want to avoid applying those metrics more % than once, hence retrieving the original, unpatched CIDFont dictionary, % if it exists. /findCIDFont { { dup /CIDFont resourcestatus { pop pop dup /CIDFont findresource dup /Path known 1 index /ResourcePath known or { exch pop exit } { pop dup /CIDFont undefineresource } ifelse } if .remove_font_name_prefix dup dup length string cvs (,Bold) tailmatch { exch pop % If we're substituting a standard weight font for a % "Light,Bold" font, don't artificially bolden further dup (Light) tailmatch { pop cvn findCIDFont dup /OrigFont .knownget {exch pop} if dup /FontName .knownget { (Light) tailmatch exch pop } { //true } ifelse { 0.03 makeboldfont } if } { pop cvn findCIDFont dup /OrigFont .knownget {exch pop} if 0.03 makeboldfont } ifelse exit } if (,Italic) tailmatch { exch pop cvn findCIDFont dup /OrigFont .knownget {exch pop} if [ 1 0 0.3 1 0 0 ] makefont exit } if (,BoldItalic) tailmatch { exch pop % see above dup (Light) tailmatch { pop cvn findCIDFont dup /OrigFont .knownget {exch pop} if dup /FontName .knownget { (Light) tailmatch exch pop } { //true } ifelse { 0.03 makeboldfont } if } { pop cvn findCIDFont dup /OrigFont .knownget {exch pop} if 0.03 makeboldfont } ifelse [ 1 0 0.3 1 0 0 ] makefont exit } if QUIET not { (Can't find CID font ") print dup =string cvs print (".) = flush } if pop 1 index /CIDSystemInfo oget begin Registry (-) Ordering end concatstrings concatstrings cvn QUIET not { (Attempting to substitute CID font ) print dup ==only ( for ) print 1 index ==only (, see doc/Use.htm#CIDFontSubstitution.) = flush } if exch pop dup /CIDFont resourcestatus { pop pop /CIDFont { findresource } stopped {pop}{exit} ifelse } if QUIET not { (The substitute CID font ") print dup =string cvs print (" is not provided either. ) print } if PDFNOCIDFALLBACK { PDFSTOPONERROR { (Will exit with error.) = flush } { (Will attempt to continue, but content may be missing.) = flush } ifelse exit } if QUIET not { (attempting to use fallback CIDFont.) print (See doc/Use.htm#CIDFontSubstitution.) = flush } if PDFNOCIDFALLBACK not { % This previously worked by loading the substitute font, and using that % as a "template" to create a new CIDFont dictionary with the CIDSystemInfo % dict appropriate for the requested font. % This, however, caused problems with the CIDMap and thus broke pdfwrite. % Hence, we now modify the CIDFont resource .map dictionary on the fly % so it includes an appropriate mapping, so the subsitute font is loaded % from the beginning with the correct ordering and supplement settings. /CIDFont /Category findresource /.map get dup /CIDFallBack .knownget { dup type /dicttype eq { dup /FileType get /TrueType eq { currentglobal 4 1 roll dup gcheck setglobal dup length dict copy dup 6 index /CIDSystemInfo oget dup /Ordering oget exch /Supplement get % we have to copy the string, for VM correctness exch dup length string copy exch 2 array astore /CSI exch put 2 index exch .forceput exch setglobal { % This *should* not execute arbitrary Postscript, so we ought to % be safe running in a stopped context, in knowledge we know how % to clean up afterwards - this would not be safe if CIDFallBack % were a "real" CIDFont. /CIDFont findresource } % if the above fails, try just using the CIDFallBack font directly stopped { pop % First, since it didn't work, remove the entry from the CIDFont category % .map dictionary. currentglobal exch /CIDFont /Category findresource /.map get dup gcheck setglobal exch undef setglobal (Warning: falling back to Identity ordering\n) print flush /CIDFallBack /CIDFont findresource } if exit } executeonly if } if } if pop pop pop /CIDFallBack QUIET not { (The fallback CID font ") print dup =string cvs print (" is not provided. ) print ( Finally attempting to use ArtifexBullet.\n) print flush }if % We'll just use Identity for this, we have only one glyph anyway. /ArtifexBullet /CIDFont resourcestatus { pop pop pop /ArtifexBullet /CIDFont findresource exit } { pop /ArtifexBullet } ifelse QUIET not { (The CID font ") print dup =string cvs print (" is not provided. ) print PDFSTOPONERROR { (Will exit with error.) = flush } { (Will continue, but content may be missing.) = flush } ifelse } if } executeonly if /findresource cvx /undefined signalerror } executeonly loop } bind executeonly odef /buildCIDType0 { % <CIDFontType0-font-resource> buildCIDType0 <font> dup /BaseFont get findCIDFont exch pop } bind executeonly def /buildCIDType2 { % <CIDFontType2-font-resource> buildCIDType2 <font> dup /BaseFont get findCIDFont exch pop } bind executeonly def /processCIDToGIDMap { % <fontres> <cidfont> processCIDToGIDMap <fontres> <cidfont> 1 index /CIDToGIDMap knownoget { PDFfile fileposition 4 1 roll dup /Identity eq { pop } { //true resolvestream % Stack: filepos fontres font mapstream [ { counttomark 1 add index 32768 string readstring not { counttomark 1 eq { exch pop dup length } { ] dup 0 exch { length add } forall } ifelse exit } if } loop 2 idiv % Stack: filepos fontres font mapstream array/string CIDCount dup 0 ne { 3 index exch /CIDCount exch put exch closefile exch dup /CIDMap 4 -1 roll put }{ % If CIDCount is zero, ignore it pop pop closefile }ifelse } ifelse 3 2 roll PDFfile exch setfileposition } if } bind executeonly def % Adjust a CIDFontType0 DW[2] in the font resource. /adjustCIDType0 { % <font-resource> <font> adjustfont <font'> dup /FontType get 1 eq { ( **** Error: Font resource has a wrong /Subtype.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror adjustfont } { addCIDmetrics dup /CIDFontName get exch /CIDFont defineresource } ifelse } bind executeonly def % Adjust a CIDFontType2 DW[2] and CIDToGIDMap in the font resource. /adjustCIDType2 { % <font-resource> <font> adjustfont <font'> dup /FontType get 1 eq { ( **** Error: Font resource has a wrong /Subtype.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror adjustfont } { addCIDmetrics dup /CIDFontType get 2 eq { % OpenType CFF font converts to CIDFontType 0 processCIDToGIDMap % that ignores CIDMap. } if dup /CIDFontName get exch /CIDFont defineresource } ifelse } bind executeonly def % ---------------- Other embedded fonts ---------------- % % Read an embedded compressed font. /readType1C { % <font-resource> <stream-dict> readType1C <font> 1 index exch PDFfile fileposition 3 1 roll dup //true resolvestream dup readfontfilter % Stack: pos resource streamdict stream filter 3 index /FontDescriptor oget /FontName oget 1 index /FontSetInit /ProcSet findresource begin //true //false ReadData %% We need to be careful not to corrupt the stack if something went wrong. %% Previously, if the dict was length 0 (an error occured) we would end up %% unable to recover the stack in the calling procedure. %% Bug #695819. dup length 0 ne { { exch pop exit } forall 7 1 roll }{ /invalidfont signalerror } ifelse closefile closefile pop PDFfile 3 -1 roll setfileposition pop pop } bind executeonly def % Read an embedded CFF CIDFont. /readCIDFontType0C { % <font-resource> <stream-dict> readCIDFontType0C <font> PDFfile fileposition 3 1 roll dup //true resolvestream dup readfontfilter % Stack: pos resource streamdict stream filter 3 index /FontDescriptor oget /FontName oget 1 index /FontSetInit /ProcSet findresource begin //true //true ReadData pop closefile closefile pop PDFfile 3 -1 roll setfileposition % Some broken Adobe software produces PDF files in which % the FontName of the CFF font and the FontName in the % FontDescriptor don't match the BaseFont in the font. % Use the FontName, rather than the BaseFont, here. dup /FontDescriptor oget /FontName oget /CIDFont findresource addCIDmetrics dup /CIDFontName get exch /CIDFont defineresource } bind executeonly def % Read an embedded OpenType font. /readOTTOfont { % <font-resource> <stream-dict> readOTTOfont <font> 1 index exch % res res strdict PDFfile fileposition 3 1 roll % res pos res strdict dup //true resolvestream % res pos res strdict stream dup readfontfilter % res pos res strdict stream filter 3 index /FontDescriptor oget /FontName oget % res pos res strdict stream filter /name 1 index .init_otto_font_file % res pos res strdict stream filter /name filter' //true 6 index /CIDSystemInfo known % res pos res strdict stream filter /name filter' bool bool ReadData % res pos res strdict stream filter fontset { exch pop exit } forall % res pos res strdict stream filter font dup /FontType get 9 eq { % OpenType may contain simple CFF font, which is accesed as a CIDFont by PDF. % The font is converted to Type 9 CIDFont resource, which ignores CIDMap attribute. % The following code just shuffles GlyphDirectory to the same effect. 4 index /CIDToGIDMap knownoget { dup type /dicttype eq { 1 index /GlyphDirectory get exch % res pos res strdict stream filter font dir c2g //true resolvestream % res pos res strdict stream filter font dir c2g_file 256 dict begin 0 2 index 0 get def % copy .notdef 0 1 16#7fffffff { 1 index read not { pop exit } if % res pos res strdict stream filter font dir c2g_file cid hi 256 mul % res pos res strdict stream filter font dir c2g_file cid hi 2 index read not { pop pop exit } if % res pos res strdict stream filter font dir c2g_file cid hi lo add % res pos res strdict stream filter font dir c2g_file cid gid dup 0 ne { dup 4 index length lt { 3 index exch get % res pos res strdict stream filter font dir c2g_file cid charstr def % res pos res strdict stream filter font dir c2g_file } { pop pop } ifelse } { pop pop } ifelse } for closefile pop % res pos res strdict stream filter font dup length dict copy % res pos res strdict stream filter font' dup /GlyphDirectory currentdict put % res pos res strdict stream filter font' end dup /GlyphDirectory get 0 exch { pop .max } forall 1 index exch /CIDCount exch 1 add put } { pop } ifelse } if } if 7 1 roll % font res pos res strdict stream filter closefile closefile pop pop % font res pos PDFfile exch setfileposition % font res pop % font } bind executeonly def % ---------------- Font lookup ---------------- % % Some PDF files mis-identify font type of the embedded font streams or % include raw PFB font streams. Length1, Length2, Length3 may be wrong or % missing. Adobe Acrobat corrects these errors transparently to the user. % % We ignore the font type keys and recognize the font type by the 1st 4 bytes % of the font stream. The PFB stream is recognized by the 1st 2 bytes. /fonttypeprocs mark % <font-resource> -proc- <font> /Type0 //buildType0 /Type1 //buildType1 /MMType1 //buildType1 /Type3 /buildType3 load /TrueType //buildTrueType /CIDFontType0 //buildCIDType0 /CIDFontType2 //buildCIDType2 .dicttomark readonly def /adjustfonttypes mark /Type1 //adjustfont /MMType1 //adjustfont /TrueType //adjustfont /CIDFontType0 //adjustCIDType0 /CIDFontType2 //adjustCIDType2 .dicttomark readonly def % Bind a proc and define n names % /name ... /name {proc} n bndef - /bndef { exch bind executeonly exch { dup 3 1 roll def } repeat pop } bind executeonly def % <res> run-fonttypeproc <font> /run-fonttypeproc { dup /Subtype knownoget not { 0 } if % res /subtype //fonttypeprocs 1 index known not { ( **** Error: Font /Subtype attribute is wrong or missing, /Type1 assumed.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror pop /Type1 2 copy /Subtype exch put } if //fonttypeprocs exch get exec } bind executeonly def % Prototype for all procedures: <res> <desc> <stream> foo <font> /font_tag_dict 13 dict begin % When the font stream is absent or cannot be read we load the font by the name. /no_stream { pop pop run-fonttypeproc } bind executeonly def /bad_stream { ( **** Error: Error reading font stream, attempting to load the font using its name\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror //no_stream exec } bind executeonly def <8001> % PFB { dup /PFB //true put exch pop readtype1 } bind executeonly def (%!PS) (%!Fo) % Type1 { exch pop readtype1 } 2 bndef <01000401> % Type 1C { exch pop 1 index /Subtype knownoget { dup /CIDFontType2 eq{ pop ( **** Error: Subtype of a Type 1 CID font is not /CIDFontType0\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror 1 index /Subtype /CIDFontType0 put readCIDFontType0C } { /CIDFontType0 eq { readCIDFontType0C } { readType1C } ifelse } ifelse } { readType1C } ifelse } bind executeonly def <00010000> (true) (typ1) (ttcf) % TrueType OpenType { exch pop readtruetype } 4 bndef (OTTO) { exch pop readOTTOfont } bind executeonly def currentdict end readonly def currentdict /bndef undef % Used to create a hash for the XUID, ths combines the input PDF file name and the % object number (currently the object number of the FontDescriptor). NB we *must* % use an object number, as otherwise all fonts will have the same % XUID and Ghostscript will think they are the same font. Ths routine must not % be used unless we have an object number which is believed to be uniqe to % a particular font instance. /.CRCHashFilenameAndObject % object_number (filename) CRCHasFilename integer { dup % object_number (filename) (filename) length % object_number (filename) length 0 exch % object_number (filename) hash length 1 sub % object_number (filename) hash length-1 0 1 3 -1 roll % object_number (filename) hash 0 1 length-1 { % object_number (filename) hash index 2 index exch get % object_number (filename) hash char exch % object_number (filename) char hash dup 16#F8000000 and % object_number (filename) char hash top5bits -27 bitshift % object_number (filename) char hash top5>>27 exch 5 bitshift % object_number (filename) char top5>>27 hash<<5 16#7FFFFFFF and xor % object_number (filename) char CRC<hash> xor % object_number (filename) newhash } for exch pop % object_number newhash dup 16#F8000000 and % object_number newhash top5bits -27 bitshift % object_number newhash top5>>27 exch 5 bitshift % object_number top5>>27 newhash<<5 16#7FFFFFFF and xor % object_number CRC<newhash> xor % final hashed value }bind executeonly def % Either patch or create a new XUID based on the existing % XUID or UniqueID and incorporating the PDF object number % so we get an XUID we can use to improve cache efficiency % in multipage documents. /patch_font_XUID % <font dict> <patch> patch_font_XUID <font dict'> { dup //null eq {pop} { //pdfdict /InputPDFFileName .knownget {.CRCHashFilenameAndObject} if exch dup /.OrigUniqueIDXUID .knownget not { dup /XUID .knownget not { dup /UniqueID .knownget {1 array astore}{ [] } ifelse } if } if dup //null eq { pop exch pop } { [ 1000000 3 -1 roll 4 index exch {exch} forall ] exch //true .copyfontdict dup 3 -1 roll /XUID exch put exch pop .completefont } ifelse } ifelse } bind executeonly def /resourcefont % <font-resource> resourcefont <font> { dup /PSFont .knownget dup { pop /FID knownoget dup { pop type /fonttype eq } if } if { /PSFont get } { dup /Subtype get /Type0 eq { % if the font was defined in-line, we won't have a object number dup /.gs.pdfobj# .knownget not { //null } if } { % if the font was defined in-line, we won't have a object number dup /.gs.pdfobj# .knownget not { //null }if dup //null eq not { 1 index /FontDescriptor knownoget { dup /FontFile knownoget not { dup /FontFile2 knownoget not { dup /FontFile3 knownoget not { pop pop //null } {pop pop}ifelse } {pop pop}ifelse }{pop pop}ifelse } { pop //null } ifelse }if } ifelse 3 1 roll % In the event we have a Type 0 dictionary with a spurious % FontDescriptor object, remove it here to prevent confusion % later on. % Bug 691589 dup /Subtype get /Type0 eq 1 index /FontDescriptor known and { dup /FontDescriptor undef }if dup /CIDSystemInfo .knownget { oforce_recursive 1 index exch /CIDSystemInfo exch put } if dup dup /FontDescriptor knownoget { % font-res font-res font-desc % The same font descriptor can be reused in a CID and non-CID contexts. % Store CID and non-CID fonts under different keys. Bug 689301 1 index /Subtype knownoget dup { pop dup /CIDFontType0 eq exch /CIDFontType2 eq or } if { /CIDFontObject } { /FontObject } ifelse % font-res font-res font-desc /key 2 index 1 index .knownget { 4 1 roll pop pop pop % font-res obj } { 4 1 roll % /key font-res font-res font-desc dup /FontFile knownoget not { dup /FontFile2 knownoget not { dup /FontFile3 knownoget not { //null } if } if } if % /key res res desc stream dup //null ne { PDFfile fileposition mark { 2 index //true resolvestream dup 4 string readstring pop exch closefile } stopped { cleartomark /bad_stream } { exch pop } ifelse PDFfile 3 -1 roll setfileposition dup length 4 lt { pop /bad_stream } if } { /no_stream } ifelse % /key res res desc stream tag //font_tag_dict 1 index known not { % % The tag is the first 4 (?) bytes frm the font stream, if we get here then % it didn't match any of the keys in the dictionary. There seems to be % a possibility that a PFB font could be undetected (because its only 2 bytes?) % but the main problem is CFF fonts. These lack a magic number, and the header % can vary in the last 3 of the 4 bytes. We've now found 7 different possible % values for these bytes, adding more seems pointless and isn't future proof. % Instead check the dictionary for its Subtype. % dup 0 2 getinterval <8001> eq { 0 2 getinterval % /key res res desc stream pfb_tag } { 1 index /Subtype known { 1 index /Subtype get dup /Type1C eq 1 index /CIDFontType0C eq or exch /CIDFontType1C eq or { pop <01000401> % discard the data we read and pretend we read the original Type1C tag //false }{ //true }ifelse } { //true % no /Subtype, give up. }ifelse { (12345678>\n) dup /ASCIIHexEncode filter dup 4 -1 roll writestring closefile ( **** Error: unrecognized font file starts with <) exch concatstrings pdfformaterror ( Output may be incorrect.\n) pdfformaterror /no_stream % /key res res desc stream unknown_tag }if } ifelse } if //font_tag_dict exch get % /key res res desc stream {proc} { stopped } 0 get % /key res res desc stream {proc} --stopped-- count % /key res res desc stream {proc} --stopped-- # countdictstack % /key res res desc stream {proc} --stopped-- # ## PDFfile fileposition % /key res res desc stream {proc} --stopped-- # ## ### 5 array astore cvx % /key res res desc stream {{proc} --stopped-- # ## ###} exec 4 -1 roll { PDFSTOPONERROR not { PDFfile exch setfileposition countdictstack exch sub 0 .max { end } repeat count 4 add exch sub 0 .max { pop } repeat //null } { /resourcefont cvx /undefinederror signalerror } ifelse } { PDFfile exch setfileposition countdictstack exch sub 0 .max { end } repeat count 3 sub exch sub 0 .max { pop } repeat } ifelse dup //null eq { PDFSTOPONERROR not { pop ( **** Error: can't process embedded font stream,\n attempting to load the font using its name.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror dup run-fonttypeproc % /key res font } { /resourcefont cvx /undefinederror signalerror } ifelse } if 1 index % /key res font res 4 -1 roll 2 index % res font desc /key font put % Save pointer to the font. } ifelse } { run-fonttypeproc } ifelse % Stack: font-res font 1 index exch 1 index /Subtype get //adjustfonttypes exch .knownget { exec } { exch pop } ifelse 4 -1 roll patch_font_XUID dup 3 1 roll /PSFont exch put } ifelse dup checkGlyphNames2Unicode } bind executeonly def currentdict /font_tag_dict .undef currentdict /fonttypeprocs .undef currentdict /adjustfonttypes .undef drawopdict begin /d0 { currentcolor currentcolorspace .swapcolors setcolorspace setcolor .swapcolors .adjustcharwidth setcharwidth } bind executeonly def /d1 { 2 copy % ... llx lly urx ury | urx ury 0 ne exch 0 ne % ... llx lly urx ury | ury!=0 urx!=0 3 index 6 index eq and % ... llx lly urx ury | ury!=0 (urx!=0 && llx==urx) exch 2 index 5 index eq and or { % ... llx lly urx ury | (urx!=0 && llx==urx) || (ury!=0 && lly==ury) % The bounding box is empty and likely incorrect. Don't cache. pop pop pop pop //d0 exec } { currentcolor currentcolorspace .swapcolors setcolorspace setcolor .swapcolors 6 -2 roll .adjustcharwidth 6 2 roll setcachedevice } ifelse } bind executeonly def /Tf { 1 index Page /Font rget { dup type /dicttype eq { resourcefont exch Tf pop } { PDFSTOPONERROR { /typecheck signalerror } { % Bug 689450 type ( **** Error: Tf refers to a resource key with an invalid value type: ) pdfformaterror .namestring pdfformaterror (. Assuming resource key: ) pdfformaterror 1 index .namestring pdfformaterror ( is a font name.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror Tf } ifelse }ifelse } { PDFSTOPONERROR { pop /undefined signalerror } { % Bug 689037 ( **** Error: Tf refers to an unknown resource name: ) pdfformaterror 1 index .namestring pdfformaterror ( Assuming it's a font name.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror Tf } ifelse } ifelse } bind executeonly def end end % pdfdict end % GS_PDF_ProcSet .setglobal gs_cspace.ps 0000644 00000007733 15030647507 0007060 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % basic colorspace mechanism % % There have been some major changes to the PostScript colour handling. % In particular, the vast majority of the colour space code has been % converted from PostScript to C. This file has been extensively % modified, as has gs_icc.ps. The remaining PostScript files which % previously implemented colour space handling; gs_ciecs2.ps, gs_ciecs3.ps % gs_devcs.ps, gs_devn.ps, gs_devpxl.ps, gs_indxd.ps, gs_patrn.ps and % gs_sepr.ps have been superceded by the C code and removed. % % gs_lev2.ps and gs_ll3.ps have also been modified so that they no longer % attempt to execute these PostScript files. % .currentglobal //true .setglobal systemdict begin % % gs_res.ps, and possibly other files, use this dictionary. Formerly % in cspace_util, moved to systemdict. % 20 dict dup /colorspacedict exch def begin % colorspacedict % % gs_res.ps uses these entries in colorspacedict % to populate the ColorSpaceFamily resource, so we need % to add the supported spaces. % /DeviceGray [] def /DeviceRGB [] def /DeviceCMYK [] def end % colorspacedict % % Global, read-only, unpacked, array-form device color spaces % We need to return an array argument in response to currentcolorspace % even if the argument presented to setcolorspace was a simple device % space name. Not only that, but in order to satisfy some Adobe % applications, it must be the *same* array every time. The only way % to do that is to define an appropriate set initial arrays and always return % one of those. These arrays are defined here. % /DeviceGray_array /DeviceGray 1 array astore readonly def /DeviceRGB_array /DeviceRGB 1 array astore readonly def /DeviceCMYK_array /DeviceCMYK 1 array astore readonly def % % These routines used for the NOSUBSTDEVICECOLORS switch. This prevents % substitution of DeviceGray, DeviceRGB and DeviceCMYK with a Default* % colour space when /UseCIEColors is true. If the job includes a % definition of /DefaltGray, DefaultRGB or DefaultCMYK then it also executes % .includecolorspace to allow the device to record the substitute space. % /..page_default_spaces 3 dict def % % Used internally to retrieve any relevant default colour space. % % <Default space name> ..nosubstdevicetest false % <Default space name> [space] true % % If the boolean is true then the C code must set the additional colour space % and execute .includecolorspace before finally setting a DeviceGray space. % % called from C code, can't undef. Use this to trigger the code: % -sDEVICE=pkmraw -dMaxBitmap=4000m -r72 -dNOSUBSTDEVICECOLORS ./tests/Ghent_V3.0/110_defaultcolourspace_x3.pdf /..nosubstdevicetest { //false mark 3 -1 roll % If we have already recorded this space, don't repeat it. systemdict /..page_default_spaces get 1 index known { cleartomark } { { % Check to see if this space was defined by defineresource, if so then % the job defined it, otherwise its the usual default, so ignore it. dup /ColorSpace resourcestatus { pop 0 eq { % Default* defined by defineresource systemdict /..page_default_spaces get 1 index //true put dup /ColorSpace findresource 4 2 roll pop pop //true }{ cleartomark } ifelse }{ cleartomark } ifelse } stopped {cleartomark}if } ifelse }bind def end % % Set the initial device space % systemdict /DeviceGray_array get setcolorspace .setglobal gs_cidfn.ps 0000644 00000033513 15030647507 0006700 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % ProcSet for implementing CIDFont and CIDMap resources. % When this is run, systemdict is still writable. % ---------------- Defining CIDFont resources ---------------- % % Define a CIDFont resource. This is the defineresource implementation for % the CIDFont resource category. /.checkfonttype { % <cidfont> <fonttype> .checkfonttype <cidfont> <new?> 1 index /FID known { 1 index /FontType get ne { /definefont cvx /invalidfont signalerror } if //false } { 1 index /FontType 3 -1 roll put //true } ifelse } bind def /.cidfonttypes where { pop } { /.cidfonttypes 6 dict def } ifelse .cidfonttypes 30 dict begin % The key in .cidfonttypes is the CIDFontType value; % the value is a procedure that takes a font name and the CIDFont dictionary % and replaces the latter with a real font. % ------ CIDFontType 0 (FontType 9) ------ % % We add the following entries to the CIDFont dictionary, in addition to % the ones documented by Adobe: % SubrCache - dictionary for caching Subr arrays % For CIDFonts where we read the data from disk incrementally: % GlyphData is 0 (arbitrary) % DataSource - a ReusableStreamDecode filter for the data % We also add a FID entry, and possibly a Subrs entry, to each element of % FDArray. dup 0 { 9 //.checkfonttype exec { /CIDInit /ProcSet findresource begin .completefont9 end } if 1 index exch .buildfont9 .currentresourcefile dup type /filetype eq { //.filename {1 index exch /ResourcePath exch put} if }{ pop} ifelse exch pop } put % Don't bind it here, because gs_fapi.ps redefines .buildfont9 % Add entries to a new CIDFontType 0 font per documentation (FontMatrix) % or for .buildfont9 (FDArray.Private.Subrs). /.completefont9 { % <cidfont0> .completefont9 <cidfont0> currentglobal 3 1 roll dup gcheck setglobal dup /FontMatrix known { dup /FDArray get { dup /FontMatrix get 0 get 1000000 ge { /FontMatrix matrix put % Bug 688517 } { pop } ifelse } forall } { dup /FontMatrix [0.001 0 0 0.001 0 0] put dup /FDArray get { currentglobal exch dup gcheck setglobal dup /FontMatrix get {1000 0 0 1000 0 0} matrix concatmatrix /FontMatrix exch put setglobal } forall } ifelse dup /FDArray get { % Read the Subrs if necessary. dup /Private get dup /Subrs known not { dup /SubrCount .knownget { % Stack: font Private SubrCount currentglobal 3 1 roll 1 index gcheck setglobal array 1 index /Subrs 3 -1 roll put % Stack: font global Private 2 index begin begin .loadsubrs end end setglobal } { pop } ifelse readonly pop } { pop pop } ifelse } forall 3 -1 roll setglobal } bind def % Read some Subrs for the current Type 1 subfont. % The subfont's Private dict is currentdict; the CIDFont itself is the % next dictionary on the stack. /.readsubrs { % <Subrs> <start> .readsubrs <Subrs> 1 SubrCount 1 sub { dup SDBytes mul SubrMapOffset add dup SDBytes .readint exch SDBytes add SDBytes .readint 1 index sub string ReadString 2 index 3 1 roll put } for } bind def % Ensure that all the Subrs for the current Type 1 subfont are loaded. % The subfont's Private dict is currentdict; the CIDFont itself is the % next dictionary on the stack. /.loadsubrs { Subrs length 0 ne { SubrCache SubrMapOffset .knownget { % We've already loaded some Subrs at this offset. % Make sure we've got as many as we need. dup length SubrCount lt { % We need to load more. SubrCount array exch 1 index copy length .readsubrs SubrCache SubrMapOffset 2 index put } if } { % We haven't loaded any Subrs at this offset yet. SubrCount array 0 .readsubrs SubrCache SubrMapOffset 2 index put } ifelse Subrs copy pop } if } bind def % ------ CIDFontType 1 (FontType 10) ------ % dup 1 { 10 //.checkfonttype exec pop 1 index exch .buildfont10 .currentresourcefile dup type /filetype eq { //.filename {1 index exch /ResourcePath exch put} if }{ pop} ifelse exch pop } put % Don't bind it here because gs_fapi.ps redefines .buildfont10 % ------ CIDFontType 2 (FontType 11) ------ % dup 2 { 11 //.checkfonttype exec pop 1 index exch .buildfont11 .currentresourcefile dup type /filetype eq { //.filename {1 index exch /ResourcePath exch put} if }{ pop} ifelse exch pop } put % Don't bind it here because gs_fapi.ps redefines .buildfont11 pop % .cidfonttypes % ---------------- Reading CIDFontType 0 files ---------------- % /StartData { % <(Binary)|(Hex)> <datalength> StartData - % (currentdict is CID font dict) % If we're loading a resource file and the data format is % binary, we can just save a pointer to the data and load it % incrementally. mark { % Previous versions of this code made provisions for % reading hex-encoded data incrementally. Since hex data % doesn't seem to be used in practice, we no longer bother. 2 index (Binary) ne { stop } if currentfile .currentresourcefile ne { stop } if % Hack: the pdfwrite driver relies on finalization to write % out fonts. However, the font may be finalized after the % resource file, in which case the resource file will be % closed. So if the current output device is pdfwrite, % don't use incremental loading. /AllowIncrementalCFF /GetDeviceParam .special_op { exch pop {stop}if }if currentfile fileposition } //.internalstopped exec { % File is not positionable, or uses hex data. % Load the data now. cleartomark exch currentfile exch (Hex) eq { /ASCIIHexDecode filter } if exch % Stack: file length dup 65400 le { % readstring with a 0-length string causes a rangecheck, % but a data length of 0 is allowed. string dup () ne { 1 index exch readstring pop } if } { mark 3 1 roll { % Stack: mark str ... file length dup 0 eq { pop exit } if dup 65400 .min dup string 3 index exch readstring pop % Stack: mark str ... file length newstrlen newstr 4 1 roll sub } loop counttomark 1 add 1 roll ] } ifelse /GlyphData exch def dup currentfile eq { pop } { closefile } ifelse } { % File is positionable and binary, just save a pointer. % Stack: (Binary) length -mark- pos /GlyphData 0 def exch pop 3 -1 roll pop exch % Stack: pos length /DataSource currentfile 2 index () .subfiledecode //true .reusablestream def currentfile 3 1 roll add setfileposition } ifelse /SubrCache 10 dict def CIDFontName currentdict /CIDFont defineresource pop end % CID font dict end % resource category dict } bind def % Some Adobe fonts include the line % /Setup /cid_Setup load def % This is apparently included only to prevent proper, conforming PostScript % interpreters (as opposed to ATM or a special Adobe font loader) from % loading the font, since Setup is not referenced anywhere else in the file. /cid_Setup { } def % ------ Generic ------ % % Read a string at a given offset in a "file" (binary file or % GlyphData in RAM). /ReadString { % <pos> <string> ReadString <string> GlyphData 0 eq { % Read from the file. DataSource 3 -1 roll setfileposition DataSource exch readstring pop } { % Read from a string or an array of strings. GlyphData .stringsreadstring } ifelse } bind def /.stringsreadstring % <pos> <string> <strings> .stringsreadstring % <vmstring> { dup type /stringtype eq { 3 1 roll length getinterval } { { % Stack: pos string glyphdata dup 0 get length dup 4 index gt { exit } if 4 -1 roll exch sub 3 1 roll dup length 1 sub 1 exch getinterval } loop % Stack: pos string glyphdata glyphdata[0]length % We know no request can span more than 2 strings. 3 index 3 index length add 1 index le { % Request fits in a single string: just return a substring. pop 0 get 3 1 roll length getinterval } { % Request spans 2 strings. Copy the first part. 1 index 0 get 4 index 3 -1 roll 1 index sub getinterval 2 index copy % Copy the second part. % Stack: pos str glyphdata str1 length exch 1 get 0 3 index length 3 index sub getinterval 2 index 3 1 roll putinterval exch pop } ifelse } ifelse } bind def % Interpret a byte string as a (big-endian) integer. /.cvbsi % <bytes> .cvbsi <int> { 0 exch { exch 8 bitshift add } forall } bind def % Read an integer from binary data. /.readint % <pos> <nbytes> .readint <int> { string ReadString .cvbsi } bind def currentdict end % ---------------- Rendering ---------------- % % ------ CIDFontType 0 ------ % /.readglyphdata { currentfont exch .type9mapcid FDArray exch get exch } bind executeonly def % BuildGlyph procedure for CIDFontType 0. % The name %Type9BuildGlyph is known to the interpreter. /.cid0buildstring 10 string def (%Type9BuildGlyph) cvn { % <cidfont> <cid> %Type9BuildGlyph - .currentglobal 3 1 roll 1 index gcheck .setglobal 1 index begin dup //.readglyphdata exec dup //null eq { % Substitute CID 0. **** WRONG **** pop pop 0 //.readglyphdata exec } if % Stack: cidfont cid subfont charstring dup //null eq { pop pop pop pop } { %**** WRONG **** 4 -1 roll pop 3 1 roll exch dup 4 -1 roll 0 0 moveto 3 index /FontType get 2 eq { .type2execchar } { .type1execchar } ifelse } ifelse %**** WRONG **** end .setglobal } bind executeonly def % ------ CIDFontType 2 ------ % % BuildGlyph procedure for CIDFontType 2. % The name %Type11BuildGlyph is known to the interpreter. (%Type11BuildGlyph) cvn { % <cidfont> <cid> %Type11BuildGlyph - % We must be prepared for out-of-range CIDs. 2 copy { .type11mapcid } //.internalstopped exec { pop /CharStrings get /.notdef get } if % Stack: cidfont cid glyphindex 1 index exch .type42execchar } bind executeonly def % ---------------- Define resources ---------------- % languagelevel exch 2 .setlanguagelevel % Define the CIDInit ProcSet resource. % The ProcSet dictionary is still on the stack. % We might have loaded CMap support already. However, Adobe's % protected font downloader defines a CIDInit ProcSet that will be % loaded from the filesystem later, so we must check specifically % for the ProcSet being defined in VM. /CIDInit /ProcSet 2 copy resourcestatus { pop 0 eq } { //false } ifelse { pop pop findresource dup length 4 index length add dict .copydict 4 -1 roll exch .copydict } { 3 -1 roll } ifelse exch defineresource pop % Define the CIDFont resource category. % We break out .buildcidfont because it appears that at least for % Type 32 (CIDFontType 4) fonts, the font can be registered in the Font % category with only a CIDFontType and no FontType. /.buildcidfont { % <name> <fontdict> .buildcidfont % <name> <cidfont> systemdict /ProvideUnicode .knownget not { //false } if { /FontEmulationProcs /ProcSet findresource /ProvideUnicodeDecoding get exec } if dup /CIDFontType get //.cidfonttypes exch get exec } bind executeonly odef /CIDFont /Generic /Category findresource dup length dict .copydict dup /InstanceType /dicttype put dup /DefineResource { dup /OrigFont known not { dup dup /OrigFont exch .growput % CPSI does it. Adding just for CET 33_all.PS conformity. } if dup /PaintType known not { dup /PaintType 0 .growput % CPSI does it. Adding just for CET 33_all.PS conformity. } if .buildcidfont /Generic /Category findresource /DefineResource get exec } put % CIDFonts may be defined in CFF OpenType files. % Check for this here. /.loadcidfontresource { dup .ResourceFile { {.loadfont} .execasresource } { dup /undefinedresource signalerror } ifelse } bind def dup /.LoadResource { currentglobal { //.loadcidfontresource exec } { //true setglobal {//.loadcidfontresource exec} stopped //false setglobal {stop} if } ifelse } bind put /Category defineresource pop % Add the new FontType resources. 9 1 11 { dup /FontType defineresource pop } for % Add the new FMapType resource. 9 dup /FMapType defineresource pop % Define the CIDMap resource category. % These aren't documented, but it's clear what they are for: % to give names to CIDMaps for CIDFontType 2 fonts. /CIDMap /Generic /Category findresource dup length dict .copydict dup /.CheckResource { % Allow a string, an array of strings, or (as of Adobe release 3011) % a dictionary. dup type dup dup /stringtype eq exch /dicttype eq or { pop //true } { dup /arraytype eq exch /packedarraytype eq or { //true exch { type /stringtype eq and } forall } { //false } ifelse } ifelse } bind put /Category defineresource pop .setlanguagelevel %% Replace 1 (gs_ciddc.ps) (gs_ciddc.ps) runlibfile % Undef these, not needed outside this file [ /.checkfonttype /.loadcidfontresource /.readglyphdata ] systemdict .undefinternalnames FAPIfontmap 0000644 00000002674 15030647507 0006613 0 ustar 00 %! % $Id: FAPIfontmap 6870 2006-06-20 16:31:15Z leonardo $ % This is a sample map file for FAPI fonts. % % The map is a set of records like this : % % /font_name options_dict ; % % where options_dict is a dictionary with the following entries : % % Key Type Description % Path string Absolute path to font file, or relative path to font file from % the GS_EXTFONTPATH value. % FontType interger PostScript type for this font. Only 1 and 42 are currently allowed. % Note that this is unrelated to the real type of the font file - % the bridge will perform format conversion. % FAPI name Name of the renderer to be used with the font. Only /AgfaUFST is now allowed. % SubfontId integer (optional) Index of the font in font collection, such as FCO or TTC. % It is being ignored if /Path doesn't specify a collection. % Default value is 0. % Decoding name (optional) The name of a Decoding resource to be used with the font. % If specified, "xlatmap" doesn't work for this font. % % Use regular Postscript syntax. % % Examples : % % /ArialTT << /Path (arial.ttf) /FontType 1 /FAPI /UFST >> ; % /CourierTT << /Path (F:/WIN2000/Fonts/cour.ttf) /FontType 1 /FAPI /UFST >> ; % /FCO1 << /Path (F:/AFPL/ufst/fontdata/MTFONTS/PCLPS3/MT1/PCLP3__G.FCO) /FontType 42 /FAPI /UFST /SubfontId 10 >> ; % gs_typ32.ps 0000644 00000010720 15030647507 0006571 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % Initialization file for Type 32 fonts. % ------ Type 32 fonts ------ % % We need LanguageLevel 2 or higher in order to have defineresource. languagelevel dup 2 .max .setlanguagelevel /BitmapFontInit mark /.makeglyph32 systemdict /.makeglyph32 get systemdict /.makeglyph32 .undef /addglyph { % ([wx wy llx lly urx ury] | % [w0x w0y llx lly urx ury w1x w1y vx vy]) % <bitmap> <cid> <type32font> addglyph - 1 index dup 2 index .removeglyphs 22 string .makeglyph32 % Stack: metrics bitmap cid font metstr 3 index () ne { % Use G4 encoding to compress the bitmap. % Define a string large enough to hold the metrics, % an uncompressed bitmap (worst case = 5x expansion), % and the 2 RTC codes (3 bytes). dup length 4 index length 5 mul add 10 add 65535 .min string % Stack: metrics bitmap cid font metstr buffer dup 0 3 index putinterval dup 2 index length 1 index length 1 index sub getinterval % Stack: metrics bitmap cid font metstr buffer bitbuf mark /Columns 8 index dup 4 get exch 2 get sub /Rows 10 index dup 5 get exch 3 get sub /K -1 /EndOfBlock //true /BlackIs1 //true .dicttomark /CCITTFaxEncode filter % Stack: metrics bitmap cid font metstr buffer filter dup 6 index writestring closefile % Find the end of the data by scanning backwards for the RTC. % There are 2 RTCs x 12 bits = 3 bytes to remove. { dup dup length 1 sub get 0 ne { exit } if 0 1 index length 1 sub getinterval } loop 0 1 index length 3 sub getinterval exch pop % metstr } if 1 index /CharStrings get 3 index 3 -1 roll put pop pop pop pop } obind /removeall { % <type32font> removeall - 0 65535 2 index removeglyphs pop } obind /.removeglyphs systemdict /.removeglyphs get systemdict /.removeglyphs .undef /removeglyphs { % <cid_min> <cid_max> <type32font> .removeglyphs - 3 copy .removeglyphs dup /CharStrings get dup { % Stack: cidmin cidmax font CharStrings cid bitmap pop dup 5 index ge { dup 4 index le { 2 copy undef } if } if pop } forall pop pop pop pop } obind .dicttomark /ProcSet defineresource pop /.cidfonttypes where { pop } { /.cidfonttypes 6 dict def } ifelse /CIDFontType4 { dup /FontType 32 .forceput dup /CharStrings 20 dict .forceput 1 index exch .buildfont32 exch pop } .bind executeonly odef .cidfonttypes begin 4 /CIDFontType4 load def % CIDFontType 4 = FontType 32 end % .cidfonttypes currentdict /CIDFontType4 .forceundef % Define the BuildGlyph procedure. % Since Type 32 fonts are indexed by CID, there is no BuildChar procedure. % The name %Type32BuildGlyph is known to the interpreter. (%Type32BuildGlyph) cvn { % <font> <cid> %Type32BuildGlyph - 1 index /CharStrings get % Stack: font cid CharStrings dup 2 index .knownget { exch pop } { 0 .knownget not { exch pop % Stack: cid .getshowoperator /invalidfont signalerror } if } ifelse % Stack: font cid cstr dup //.getmetrics32 % use // because of .undef below dup 14 gt { 8 index 8 index 13 3 roll setcachedevice2 } { 4 index 4 index 9 3 roll setcachedevice } ifelse % Stack: font cid cstr w h nmetrics llx lly 6 -1 roll 4 -1 roll 1 index length 1 index sub getinterval % Stack: font cid w h llx lly bitstr dup () eq { pop pop pop } { mark /Columns 6 index /Rows 7 index /K -1 /EndOfBlock //false /BlackIs1 //true .dicttomark /CCITTFaxDecode filter 4 index 4 index //true % Stack: font cid w h llx lly filter w h //true [ 1 0 0 1 11 -2 roll exch neg exch neg ] 5 -1 roll imagemask } ifelse pop pop pop pop } .bind def systemdict /.getmetrics32 .undef buildfontdict 32 /.buildfont32 cvx put 32 dup /FontType defineresource pop .setlanguagelevel FAPIconfig 0000644 00000001457 15030647507 0006412 0 ustar 00 %! % $Id: FAPIconfig 6870 2006-06-20 16:31:15Z leonardo $ % This is configuration file for FAPI client. % % /FontPath (/Fonts) % A default directory for FAPI-handled font files path in FAPIfontmap. % /CIDFontPath (/CIDFonts) % A default directory for FAPI-handled CID font files path in FAPIcidfmap. % /HookDiskFonts [1 2 9 11 42] % FontType values for disk PS fonts to be redirected to FAPI. % /HookEmbeddedFonts [1 2 9 11 42] % FontType values for embedded PS fonts to be redirected to FAPI. % % Values allowed for HookDiskFonts and HookEmbeddedFonts are 1, 2, 9, 11, 42. % "Disk fonts" are fonts being installed to Ghostscript with 'lib/Fontmap' or with GS_FONTPATH, % and CID font resource files. % "Embedded fonts" are fonts and CID fonts being embedded into a document. gs_ciddc.ps 0000644 00000020471 15030647507 0006662 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % Define SubstCID, Decoding and CIDDecoding resource categories and related procsets. languagelevel 2 .setlanguagelevel currentglobal //true setglobal %----------------ParseDecoding procset---------------------------- /ParseDecoding << /Parse % <resource_name> <num_tokens> Parse - { dict begin % /ResName 0 % /ResName nCode { currentfile token not { exit } if % /ResName nCode token dup type /integertype eq { % /ResName nCode exch pop } { 1 index def % /ResName nCode } ifelse } loop % /ResName nCode pop % /ResName currentdict end /Decoding % /ResName <<inst>> /Decoding defineresource pop } bind >> /ProcSet defineresource pop %----------------Decoding category---------------------------- /Generic /Category findresource dup length dict copy dup /InstanceType /dicttype put /Decoding exch /Category defineresource pop %----------------ParseCMap_Inverse procset---------------------------- /ParseCMap_Inverse << /findresource { pop } bind /defineresource { pop pop } bind /dict {} /def { pop pop } bind /dup //null /begin { pop } bind /end {} /currentdict //null /CMapName //null /usecmap { pop } bind /begincmap {} /endcmap {} /begincodespacerange { pop mark } bind /endcodespacerange { cleartomark } bind /beginnotdefrange { pop mark } bind /endnotdefrange { cleartomark } bind /beginbfchar { pop mark } bind /endbfchar { pop mark } bind /beginbfrange { begincidrange } /endbfrange { endcidrange } /begincidchar { beginbfchar } /endcidchar { endbfchar } /begincidrange { pop mark } bind /endcidrange { cleartomark } bind >> % Just keep it on stack for a while. % Now we define another dict for local binding, than merge it with the previous one : dup length 5 add dict begin /.Ranges 40 dict def % Key = CID/256, value = array of 256 integer codes. //.Ranges /CIDCount 0 put /.StringToInt % <string> .StringToInt <integer> { 0 exch { exch 8 bitshift add } forall } bind def /.SetCouple % <I> <b> .SetCouple - { exch % b I dup 256 idiv % b I I0 dup //.Ranges exch known not { dup //.Ranges exch 256 array put } if % b I I0 //.Ranges exch get % b I [Range] exch 256 mod % b [Range] I1 2 copy get % b [Range] I1 e dup //null ne { % We've got char code duplicates for same CID. dup type /integertype eq { 4 3 roll % [Range] I1 e b 2 array astore put % } { dup length 1 add dup dup array dup % b [Range] I1 D l l D' D' 3 2 roll 0 exch getinterval % b [Range] I1 D l D' D'' 4 3 roll exch copy pop % b [Range] I1 l D' dup 3 2 roll 1 sub % b [Range] I1 D' D' l-1 6 5 roll % [Range] I1 D' D' l-1 b put put % } ifelse } { pop 3 2 roll put % } ifelse } bind def /endcidrange { % Writes the inversed CMap to .Ranges counttomark 3 idiv { % (b) (e) I exch .StringToInt % (b) I e 3 2 roll .StringToInt % I e b % Note : this code does't handle multidimentional CID ranges. % fixme : optimize below. dup 3 2 roll exch sub 1 add % I b d { 2 copy //.SetCouple exec % I b 1 add exch 1 add exch } repeat % I b pop % I dup //.Ranges /CIDCount get gt { % I dup //.Ranges exch /CIDCount exch put } if % I pop } repeat pop % mark } bind def /.GetCIDDecoding % - .GetCIDDEcoding <dict> { //.Ranges dup length dict copy //.Ranges //.PurgeDict exec //.Ranges /CIDCount 0 put } bind def currentdict end exch copy % Merge the dicts - see above. /ProcSet defineresource pop %----------------CIDDecoding category---------------------------- % Note that we put all instances in global memory - see FindResource. /Generic /Category findresource dup length dict copy begin /Category /CIDDecoding def /InstanceType /dicttype def /.CMapChooser << % This lists CMaps to inverse and unite for creating a CIDDecoding. % Choose by FAPIcidfmap.Registry concatenated with TrueType encoding ID. % Font renderer must provide the glyph substitution internally. /CNS1.Big5 [ /ETen-B5-H /ETen-B5-V ] /CNS1.Unicode [ /UniCNS-UCS2-H /UniCNS-UCS2-V] /CNS1.UCS-4 [ /UniCNS-UCS2-H /UniCNS-UCS2-V] /GB1.GB2312 [ /GBK-EUC-H /GBK-EUC-V ] /GB1.Unicode [ /UniGB-UCS2-H /UniGB-UCS2-V ] /GB1.UCS-4 [ /UniGB-UCS2-H /UniGB-UCS2-V ] /Japan1.ShiftJIS [ /90ms-RKSJ-H /90ms-RKSJ-V ] /Japan1.Unicode [ /UniJIS-UCS2-H /UniJIS-UCS2-V] /Japan1.UCS-4 [ /UniJIS-UCS2-H /UniJIS-UCS2-V] /Japan2.ShiftJIS [ /90ms-RKSJ-H /90ms-RKSJ-V ] /Japan2.Unicode [ /UniHojo-UCS2-H ] /Japan2.UCS-4 [ /UniHojo-UCS2-H ] /Korea1.Johab [ /KSC-Johab-V /KSC-Johab-H ] /Korea1.Wansung [ /KSCms-UHC-V /KSCms-UHC-H ] /Korea1.Unicode [ /UniKS-UCS2-H /UniKS-UCS2-V ] /Identity.Symbol [ /Identity-H /Identity-V ] /Unicode.Unicode [ /Identity-UTF16-H ] /Identity.Unicode [ /Identity-UTF16-H ] /Identity.UCS-4 [ /Identity-H /Identity-V ] >> def /.MakeInstance % <name> .MakeInstance <inst> { dup % /Name /Name //.CMapChooser exch .knownget not { (Can't build /) print =string cvs print ( /CIDDecoding resource. See gs_ciddc.ps . ) = flush /findresource cvx /undefinedresource signalerror } if % /Name [CMaps] exch pop % [CMaps] /CMap /Category findresource % [CMaps] <CMapCategory> /ParseCMap_Inverse /ProcSet findresource % [CMaps] <CMapCategory> <PCI> 3 2 roll { % <CMapCategory> <PCI> /CMapName 3 2 roll begin % <PCI> /CMapName dup .ResourceFile not { (Can't find CMap ) print =string cvs print ( building a CIDDecoding resource. ) = flush /findresource cvx /undefinedresource signalerror } if currentdict end exch % <PCI> /CMapName <CMapCategory> file 3 index begin cvx exec % <PCI> /CMapName <CMapCategory> end exch pop exch % <CMapCategory> <PCI> } forall exch pop begin % .GetCIDDecoding end } bind executeonly def /FindResource % <name> FindResource <dict> { currentglobal exch % bGlobal /InstName //true setglobal dup //.MakeInstance exec % bGlobal /InstName <Inst> DefineResource % bGlobal <Inst> exch setglobal % <Inst> } bind executeonly def currentdict end /CIDDecoding exch /Category defineresource pop %----------------SubstCID category---------------------------- /Generic /Category findresource dup length dict copy begin /Category /SubstCID def /InstanceType /dicttype def currentdict end /SubstCID exch /Category defineresource pop setglobal .setlanguagelevel gs_il1_e.ps 0000644 00000005242 15030647507 0006604 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % Define the ISO Latin-1 encoding vector. % The first half is the same as the standard encoding, % except for minus instead of hyphen at code 055. /ISOLatin1Encoding StandardEncoding 0 45 getinterval aload pop /minus StandardEncoding 46 82 getinterval aload pop % NOTE: the following are missing in the Adobe documentation, % but appear in the displayed table: % macron at 0225, dieresis at 0230, cedilla at 0233, space at 0240. % This is an error in the Red Book, corrected in Adobe TN 5085. % \20x /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /dotlessi /grave /acute /circumflex /tilde /macron /breve /dotaccent /dieresis /.notdef /ring /cedilla /.notdef /hungarumlaut /ogonek /caron % \24x /space /exclamdown /cent /sterling /currency /yen /brokenbar /section /dieresis /copyright /ordfeminine /guillemotleft /logicalnot /hyphen /registered /macron /degree /plusminus /twosuperior /threesuperior /acute /mu /paragraph /periodcentered /cedilla /onesuperior /ordmasculine /guillemotright /onequarter /onehalf /threequarters /questiondown % \30x /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla /Egrave /Eacute /Ecircumflex /Edieresis /Igrave /Iacute /Icircumflex /Idieresis /Eth /Ntilde /Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply /Oslash /Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn /germandbls % \34x /agrave /aacute /acircumflex /atilde /adieresis /aring /ae /ccedilla /egrave /eacute /ecircumflex /edieresis /igrave /iacute /icircumflex /idieresis /eth /ntilde /ograve /oacute /ocircumflex /otilde /odieresis /divide /oslash /ugrave /uacute /ucircumflex /udieresis /yacute /thorn /ydieresis % Make an array on large systems, a packed array on small ones. 256 vmstatus exch pop exch pop 100000 ge { array astore readonly } { packedarray } ifelse def 1 ISOLatin1Encoding .registerencoding /ISOLatin1Encoding ISOLatin1Encoding .defineencoding gs_lev2.ps 0000644 00000125553 15030647507 0006473 0 ustar 00 % Copyright (C) 2001-2021 Artifex Software, Inc. % 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. % % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. % % Initialization file for Level 2 functions. % When this is run, systemdict is still writable, % but (almost) everything defined here goes into level2dict. level2dict begin % ------ System and user parameters ------ % % User parameters must obey save/restore, and must also be maintained % per-context. We implement the former, and some of the latter, here % with PostScript code. NOTE: our implementation assumes that user % parameters change only as a result of setuserparams -- that there are % no user parameters that are ever changed dynamically by the interpreter % (although the interpreter may adjust the value presented to setuserparams) % % There are two types of user parameters: those which are actually % maintained in the interpreter, and those which exist only at the % PostScript level. We maintain the current state of both types in % a read-only local dictionary named userparams, defined in systemdict. % In a multi-context system, each context has its own copy of this % dictionary. In addition, there is a constant dictionary named % psuserparams where each key is the name of a user parameter that exists % only in PostScript and the value is a procedure to check that the value % is legal: setuserparams uses this for checking the values. % setuserparams updates userparams explicitly, in addition to setting % any user parameters in the interpreter; thus we can use userparams % to reset those parameters after a restore or a context switch. % NOTE: the name userparams is known to the interpreter, and in fact % the interpreter creates the userparams dictionary. % Check parameters that are managed at the PostScript level. /.checkparamtype { % <newvalue> <type> .checkparamtype <bool> exch type eq } .bind def /.checksetparams { % <newdict> <opname> <checkdict> % .checksetparams <newdict> 2 .argindex { % Stack: newdict opname checkdict key newvalue 3 copy 3 1 roll .knownget { exec not { pop pop pop load /typecheck signalerror } if dup type /stringtype eq { dup rcheck not { pop pop pop load /invalidaccess signalerror } if } if } { pop } ifelse pop pop } forall pop pop } .bind def % currentuser/systemparams creates and returns a dictionary in the % current VM. The easiest way to make this work is to copy any composite % PostScript-level parameters to global VM. Currently we have strings % as well as arrays. For arrays, we also need to copy any contents that % are in VM. Also copying string parameters insures the contents won't % be changed. Also be careful to preserve 'executable' state. /.copyparam { % <value> .copyparam <value'> dup type /arraytype eq { .currentglobal //true .setglobal exch dup wcheck exch dup xcheck exch % original attributes dup length array exch dup { % stack: destination_array original_array original_array dup type /arraytype eq { dup 2 index ne { % avoid recursion .copyparam % recurse to handle composite array elements } { % this array self referenced, do it again (yuk!) pop 1 index % get copy of destination array } ifelse } { dup type /stringtype eq { .copyparam } if } ifelse 3 1 roll % keep arrays on top } forall pop astore exch { cvx } if % set executable state exch not { readonly } if % set readonly attribute as original exch .setglobal } if dup type /stringtype eq { dup wcheck exch % save attr for setting readonly .currentglobal //true .setglobal 1 index length string exch .setglobal copy exch not { readonly } if } if } .bind odef % Some user parameters are managed entirely at the PostScript level. % We take care of that here. systemdict begin /psuserparams 48 dict def /getuserparam { % <name> getuserparam <value> /userparams .systemvar 1 .argindex get exch pop } odef % Fill in userparams (created by the interpreter) with current values. mark .currentuserparams counttomark 2 idiv { userparams 3 1 roll put } repeat pop /.definepsuserparam { % <name> <value> .definepsuserparam - psuserparams 3 copy pop type cvlit //.checkparamtype /exec load 3 packedarray cvx put userparams 3 1 roll put } .bind def end /currentuserparams { % - currentuserparams <dict> /userparams .systemvar dup length dict .copydict } odef % We break out setuserparams into a separate procedure so that setvmxxx % can use it without affecting the command in case of an error. /.setuserparams2 { % Check that we will be able to set the PostScript-level % user parameters. /setuserparams /psuserparams .systemvar //.checksetparams exec % Set the C-level user params. If this succeeds, we know that % the password check succeeded. dup .setuserparams % Now set the PostScript-level params. % The interpreter may have adjusted the values of some of the % parameters, so we have to read them back. dup { /userparams .systemvar 2 index known { psuserparams 2 index known not { pop dup .getuserparam } if .copyparam % special protection for the security related parameters [ /PermitFileReading /PermitFileWriting /PermitFileControl ] { 2 index eq { % force all strings to readonly but make sure the % array is in the correct VM space (local/global). currentglobal exch dup gcheck setglobal dup length array exch { readonly exch } forall astore exch setglobal } if } forall % protect top level of parameters that we copied dup type dup /arraytype eq exch /stringtype eq or { readonly } if /userparams .systemvar 3 1 roll .forceput % userparams is read-only } executeonly { pop pop } ifelse } executeonly forall % A context switch might have occurred during the above loop, % causing the interpreter-level parameters to be reset. % Set them again to the new values. From here on, we are safe, % since a context switch will consult userparams. .setuserparams } .bind executeonly odef % must be bound and hidden for .forceput /setuserparams { % <dict> setuserparams - {.setuserparams2} stopped {/setuserparams load $error /errorname get signalerror} if } .bind odef % Initialize user parameters managed here. /JobName () .definepsuserparam % Restore must restore the user parameters. % (Since userparams is in local VM, save takes care of saving them.) /restore { % <save> restore - //restore /userparams .systemvar .setuserparams } .bind odef % The pssystemparams dictionary holds some system parameters that % are managed entirely at the PostScript level. systemdict begin currentdict /pssystemparams known not { /pssystemparams 40 dict readonly def } if /getsystemparam { % <name> getsystemparam <value> //pssystemparams 1 .argindex .knownget { exch pop } { .getsystemparam } ifelse } odef end /currentsystemparams { % - currentsystemparams <dict> mark .currentsystemparams //pssystemparams { } forall .dicttomark } odef /setsystemparams { % <dict> setsystemparams - % Check that we will be able to set the PostScript-level % system parameters. dup pop % check # of args /SAFETY .systemvar /safe get { % SAFER mode disallows some changes [ /GenericResourceDir /FontResourceDir /GenericResourcePathSep ] { 2 copy .knownget { exch //pssystemparams exch .knownget { ne { /setsystemparams cvx /invalidaccess signalerror } if } { pop } ifelse } { pop } ifelse } forall } if /setsystemparams //pssystemparams mark exch { type cvlit //.checkparamtype /exec load 3 packedarray cvx } forall .dicttomark //.checksetparams exec % Set the C-level system params. If this succeeds, we know that % the password check succeeded. dup .setsystemparams % Now set the PostScript-level params. We must copy local strings % into global VM. dup { //pssystemparams 2 index known { % Stack: key newvalue .copyparam % protect top level parameters that we copied dup type dup /arraytype eq exch /stringtype eq or { readonly } if //pssystemparams 3 1 roll .forceput % pssystemparams is read-only } executeonly { pop pop } ifelse } executeonly forall pop } .bind executeonly odef % Initialize the passwords. % NOTE: the names StartJobPassword and SystemParamsPassword are known to % the interpreter, and must be bound to noaccess strings. % The length of these strings must be max_password (iutil2.h) + 1. /StartJobPassword 65 string noaccess def /SystemParamsPassword 65 string noaccess def % Redefine cache parameter setting to interact properly with userparams. /setcachelimit { { mark /MaxFontItem 2 .argindex .dicttomark setuserparams pop } stopped { /setcachelimit .systemvar $error /errorname get signalerror } if } .bind odef /setcacheparams { % The MaxFontCache parameter is a system parameter, which we might % not be able to set. Fortunately, this doesn't matter, because % system parameters don't have to be synchronized between this code % and the VM. counttomark 1 add copy setcacheparams currentcacheparams % mark size lower upper 3 -1 roll pop /MinFontCompress 3 1 roll /MaxFontItem exch .dicttomark { setuserparams cleartomark } stopped { /setcacheparams .systemvar $error /errorname get signalerror } if } .bind odef % Add bogus user and system parameters to satisfy badly written PostScript % programs that incorrectly assume the existence of all the parameters % listed in Appendix C of the Red Book. Note that some of these may become % real parameters later: code near the end of gs_init.ps takes care of % removing any such parameters from ps{user,system}params. % psuserparams /MaxFormItem 100000 .definepsuserparam /MaxPatternItem 20000 .definepsuserparam /MaxScreenItem 48000 .definepsuserparam /MaxUPathItem 0 .definepsuserparam % File Access Permission parameters .currentglobal //true .setglobal /.checkFilePermitparams { type /arraytype eq { currentuserparams /LockFilePermissions get { 5 { pop } repeat /setuserparams cvx /invalidaccess signalerror }{ % in addition to validating the value, ensure the value is read/only dup { readonly exch } forall .currentglobal exch dup gcheck .setglobal length array exch .setglobal astore readonly } ifelse } { 5 { pop } repeat /setuserparams cvx /typecheck signalerror } ifelse //true } .bind def % Initialize the File Permission access control to wide open % These will only be accessed via current/set userparams. % Values are a string containing multiple nul terminated path strings /PermitFileReading dup [ (*) ] .definepsuserparam psuserparams exch /.checkFilePermitparams load put /PermitFileWriting dup [ (*) ] .definepsuserparam psuserparams exch /.checkFilePermitparams load put /PermitFileControl dup [ (*) ] .definepsuserparam psuserparams exch /.checkFilePermitparams load put .setglobal pssystemparams dup /CurDisplayList 0 .forceput dup /CurFormCache 0 .forceput dup /CurInputDevice () .forceput dup /CurOutlineCache 0 .forceput dup /CurOutputDevice () .forceput dup /CurPatternCache 0 .forceput dup /CurUPathCache 0 .forceput dup /CurScreenStorage 0 .forceput dup /CurSourceList 0 .forceput dup /DoPrintErrors //false .forceput dup /JobTimeout 0 .forceput dup /LicenseID (LN-001) .forceput % bogus dup /MaxDisplayList 140000 .forceput dup /MaxFormCache 100000 .forceput dup /MaxImageBuffer 524288 .forceput dup /MaxOutlineCache 65000 .forceput dup /MaxPatternCache 100000 .forceput dup /MaxUPathCache 300000 .forceput dup /MaxScreenStorage 84000 .forceput dup /MaxSourceList 25000 .forceput dup /PrinterName product .forceput dup /RamSize 4194304 .forceput /WaitTimeout 40 .forceput % Define the procedures for handling comment scanning. The names % %ProcessComment and %ProcessDSCComment are known to the interpreter. % These procedures take the file and comment string and file as operands. /.checkprocesscomment { dup //null eq { pop //true } { dup xcheck { type dup /arraytype eq exch /packedarraytype eq or } { pop //false } ifelse } ifelse } .bind def /ProcessComment //null .definepsuserparam psuserparams /ProcessComment {//.checkprocesscomment exec} put (%ProcessComment) cvn { /ProcessComment getuserparam dup //null eq { pop pop pop } { exec } ifelse } bind def /ProcessDSCComment //null .definepsuserparam psuserparams /ProcessDSCComment {//.checkprocesscomment exec} put /.loadingfont //false def (%ProcessDSCComment) cvn { /ProcessDSCComment getuserparam dup //null eq .loadingfont or { pop pop pop } { exec } ifelse } bind def % ------ Miscellaneous ------ % (<<) cvn % - << -mark- /mark load def % (>> is defined primitively.) /languagelevel 2 def % When running in Level 2 mode, this interpreter is supposed to be % compatible with Adobe version 2017. /version (2017) readonly def % If binary tokens are supported by this interpreter, % set an appropriate default binary object format. /setobjectformat where { pop /RealFormat getsystemparam (IEEE) eq { 1 } { 3 } ifelse /ByteOrder getsystemparam { 1 add } if setobjectformat } if % Aldus Freehand versions 2.x check for the presence of the % setcolor operator, and if it is missing, substitute a procedure. % Unfortunately, the procedure takes different parameters from % the operator. As a result, files produced by this application % cause an error if the setcolor operator is actually defined % and 'bind' is ever used. Aldus fixed this bug in Freehand 3.0, % but there are a lot of files created by the older versions % still floating around. Therefore, at Adobe's suggestion, % we implement the following dreadful hack in the 'where' operator: % If the key is /setcolor, and % there is a dictionary named FreeHandDict, and % currentdict is that dictionary, % then "where" consults only that dictionary and not any other % dictionaries on the dictionary stack. .wheredict /setcolor { /FreeHandDict .where { /FreeHandDict get currentdict eq { pop currentdict /setcolor known { currentdict //true } { //false } ifelse } { .where } ifelse } { .where } ifelse } bind put % ------ Virtual memory ------ % /currentglobal % - currentglobal <bool> /currentshared load def /gcheck % <obj> gcheck <bool> /scheck load def /setglobal % <bool> setglobal - /setshared load def % We can make the global dictionaries very small, because they auto-expand. /globaldict currentdict /shareddict .knownget not { 4 dict } if def /GlobalFontDirectory SharedFontDirectory def % VMReclaim and VMThreshold are user parameters. /setvmthreshold { % <int> setvmthreshold - mark /VMThreshold 2 .argindex .dicttomark {.setuserparams2} stopped {pop /setvmthreshold load $error /errorname get signalerror} {pop} ifelse } odef /vmreclaim { % <int> vmreclaim - dup 0 gt { dup 2 le 1 index type /integertype eq and { pop % ignore user requests for vmreclaim % (reclaim will still happen controlled by vmthreshold) } { .vmreclaim } % let internal operator handle error conditions ifelse } { % VMReclaim userparam controls enable/disable GC mark /VMReclaim 2 index .dicttomark {.setuserparams2} stopped {pop /vmreclaim load $error /errorname get signalerror} {pop} ifelse } ifelse } .bind executeonly odef -1 setvmthreshold % ------ IODevices ------ % /.getdevparams where { pop /currentdevparams { % <iodevice> currentdevparams <dict> .getdevparams .dicttomark } odef } if /.putdevparams where { pop /setdevparams { % <iodevice> <dict> setdevparams - dup type /dicttype ne { /setdevparams .systemvar /typecheck signalerror } if mark 1 index { } forall counttomark 2 add index .putdevparams pop pop } odef } if % ------ Job control ------ % serverdict begin % We could protect the job information better, but we aren't attempting % (currently) to protect ourselves against maliciousness. /.jobsave //null def % top-level save object /.jobsavelevel 0 def % save depth of job (0 if .jobsave is null, % 1 otherwise) /.adminjob //true def % status of current unencapsulated job end % serverdict % Because there may be objects on the e-stack created since the job save, % we have to clear the e-stack before doing the end-of-job restore. % We do this by executing a 2 .stop, which is caught by the 2 .stopped % in .runexec; we leave on the o-stack a procedure to execute aftewards. % %**************** The definition of startjob is not complete yet, since % it doesn't reset stdin/stdout. /.startnewjob { % <exit_bool> <password_level> % .startnewjob - serverdict /.jobsave get dup //null eq { pop } { restore } ifelse exch { % Unencapsulated job serverdict /.jobsave //null put serverdict /.jobsavelevel 0 put serverdict /.adminjob 3 -1 roll 1 gt put } { % Encapsulated job pop serverdict /.jobsave save put serverdict /.jobsavelevel 1 put .userdict /quit { stop } .bind put % CET 28-10 requires a procedure } ifelse % Reset the interpreter state. clear cleardictstack initgraphics //false setglobal } bind executeonly def /.startjob { % <exit_bool> <password> <finish_proc> % .startjob <ok_bool> vmstatus pop pop serverdict /.jobsavelevel get eq 2 .argindex .checkpassword 0 gt and { exch .checkpassword exch count 3 roll count 3 sub { pop } repeat cleardictstack % Reset the e-stack back to the 2 .stopped in .runexec, % passing the finish_proc to be executed afterwards. 2 .stop } { % Password check failed pop pop pop //false } ifelse } odef /startjob { % <exit_bool> <password> startjob <ok_bool> % This is a hack. We really need some way to indicate explicitly % to the interpreter that we are under control of a job server. 1 .argindex type /booleantype ne { /startjob .systemvar /typecheck signalerror } if { .startnewjob //true } .startjob } odef systemdict begin /quit { % - quit - //systemdict begin serverdict /.jobsave get //null eq { end //quit } { /quit .systemvar /invalidaccess /signalerror load end exec } ifelse } bind odef end % We would like to define exitserver as a procedure, using the code % that the Red Book says is equivalent to it. However, since startjob % resets the exec stack, we can't do this, because control would never % proceed past the call on startjob if the exitserver is successful. % Instead, we need to construct exitserver out of pieces of startjob. serverdict begin /exitserver { % <password> exitserver - //true exch { .startnewjob } .startjob not { /exitserver cvx /invalidaccess signalerror } if } bind def end % serverdict % ------ Compatibility ------ % % In Level 2 mode, the following replace the definitions that gs_statd.ps % installs in statusdict and serverdict. % Note that statusdict must be allocated in local VM. % We don't bother with many of these yet. % convenience function to make a dictionary from an object and a key /.pair2dict { exch mark 3 1 roll .dicttomark } bind def currentglobal //false setglobal 25 dict exch setglobal begin currentsystemparams % The following do not depend on the presence of setpagedevice. /buildtime 1 index /BuildTime get def % Also define /buildtime in systemdict because Adobe does so and some fonts use it as ID systemdict /buildtime dup load put /byteorder 1 index /ByteOrder get def /checkpassword { .checkpassword 0 gt } bind def dup /DoStartPage known { /dostartpage { /DoStartPage getsystemparam } bind def /setdostartpage { /DoStartPage //.pair2dict exec setsystemparams } bind def } if dup /StartupMode known { /dosysstart { /StartupMode getsystemparam 0 ne } bind def /setdosysstart { { 1 } { 0 } ifelse /StartupMode //.pair2dict exec setsystemparams } bind def } if %****** Setting jobname is supposed to set userparams.JobName, too. /jobname { /JobName getuserparam } bind def /jobtimeout { /JobTimeout getuserparam } bind def /ramsize { /RamSize getsystemparam } bind def /realformat 1 index /RealFormat get def dup /PrinterName known { /setprintername { /PrinterName //.pair2dict exec setsystemparams } bind def } if /printername { currentsystemparams /PrinterName .knownget not { () } if exch copy } bind def currentuserparams /WaitTimeout known { /waittimeout { /WaitTimeout getuserparam } bind def } if % The following do require setpagedevice. /.setpagedevice where { pop } { (%END PAGEDEVICE) .skipeof } ifelse /defaulttimeouts { currentsystemparams dup /JobTimeout .knownget not { 0 } if exch /WaitTimeout .knownget not { 0 } if currentpagedevice /ManualFeedTimeout .knownget not { 0 } if } bind def /margins { currentpagedevice /Margins .knownget { exch } { [0 0] } ifelse } bind def /pagemargin { currentpagedevice /PageOffset .knownget { 0 get } { 0 } ifelse } bind def /pageparams { currentpagedevice dup /Orientation .knownget { 1 and ORIENT1 { 1 xor } if } { 0 } ifelse exch dup /PageSize get aload pop 3 index 0 ne { exch } if 3 2 roll /PageOffset .knownget { 0 get } { 0 } ifelse 4 -1 roll } bind def /setdefaulttimeouts { exch mark /ManualFeedTimeout 3 -1 roll /Policies mark /ManualFeedTimeout 1 .dicttomark .dicttomark setpagedevice /WaitTimeout exch mark /JobTimeout 5 2 roll .dicttomark setsystemparams } bind def /setduplexmode { /Duplex //.pair2dict exec setpagedevice } bind def /setmargins { exch 2 array astore /Margins //.pair2dict exec setpagedevice } bind def /setpagemargin { 0 2 array astore /PageOffset //.pair2dict exec setpagedevice } bind def /setpageparams { mark /PageSize 6 -2 roll 4 index 1 and ORIENT1 { 1 } { 0 } ifelse ne { exch } if 2 array astore /Orientation 5 -1 roll ORIENT1 { 1 xor } if /PageOffset counttomark 2 add -1 roll 0 2 array astore .dicttomark setpagedevice } bind def /setresolution { count 1 lt { /setresolution cvx /stackunderflow signalerror } if dup type dup /integertype eq exch /realtype eq or not { /setresolution cvx /typecheck signalerror } if dup 2 array astore /HWResolution //.pair2dict exec { setpagedevice } stopped { pop /setresolution cvx $error /errorname get signalerror } if } bind def %END PAGEDEVICE % The following are not implemented yet. %manualfeed %manualfeedtimeout %pagecount %pagestackorder %setpagestackorder % -------- ICC manager -------- % % All color management is going % through ICC flow. We need % to have the default device % spaces gray, RGB and CMYK % defined by ICC profiles //systemdict /ICCProfilesDir .knownget { % Set the directory sepcified by the command line option mark exch /ICCProfilesDir exch .dicttomark .setuserparams2 } { % First see if the current value is valid so we don't have to guess mark .currentuserparams .dicttomark /ICCProfilesDir get (default_gray.icc) concatstrings {status} //.internalstopped exec {pop //false} if { pop pop pop pop % current value was OK. Just clean up stack } { % Search for valid (iccprofiles) directory as a sibling to (Resource) % and set it as a default if found. LIBPATH { (Resource) rsearch { exch pop exch pop (iccprofiles) concatstrings .file_name_separator concatstrings dup (default_gray.icc) concatstrings status { pop pop pop pop mark exch /ICCProfilesDir exch .dicttomark .setuserparams2 exit } { pop } ifelse } { pop } ifelse } forall } ifelse % if currentuserparams ICCProfilesDir } ifelse % ICCProfilesDir set in systemdict (command line option) mark % collect dict key value pairs for anything set in systemdict (command line options) [ /DefaultRGBProfile /DefaultGrayProfile /DefaultCMYKProfile /DeviceNProfile /NamedProfile /SourceObjectICC /OverrideICC ] { dup //systemdict exch .knownget not { pop % discard keys not in systemdict } if } forall .dicttomark .setuserparams2 pop % currentsystemparams % Flag the current dictionary so it will be swapped when we % change language levels. (See zmisc2.c for more information.) /statusdict currentdict def currentdict end currentdict exch /statusdict exch .forceput % statusdict is local, systemdict is global % The following compatibility operators are in systemdict. They are % defined here, rather than in gs_init.ps, because they require the % resource machinery. /devforall { % <proc> <scratch> devforall - exch { 1 index currentdevparams /Type .knownget { /FileSystem eq } { //false } ifelse { exec } { pop pop } ifelse } /exec load 3 packedarray cvx exch (*) 3 1 roll /IODevice resourceforall } odef /devstatus { % <(%disk*%)> devstatus <searchable> <writable> % <hasNames> <mounted> <removable> <searchOrder> % <freePages> <size> true % <string> devstatus false dup length 5 ge { dup 0 5 getinterval (%disk) eq { dup /IODevice resourcestatus { pop pop dup currentdevparams dup /Searchable get exch dup /Writeable get exch dup /HasNames get exch dup /Mounted get exch dup /Removable get exch dup /SearchOrder get exch dup /Free get exch /LogicalSize get 9 -1 roll pop //true } { pop //false } ifelse } { pop //false } ifelse } { pop //false } ifelse } odef % ------ Color spaces ------ % % gs_res.ps uses these entries in colorspacedict % to populate the ColorSpaceFamily resource, so we need % to add the supported spaces. % systemdict /colorspacedict get begin /CIEBasedA [] def /CIEBasedABC [] def /DevicePixel [] def /Indexed [] def /Pattern [] def /Separation [] def end % ------ CIE color rendering ------ % % Define findcolorrendering and a default ColorRendering ProcSet. /findcolorrendering { % <intentname> findcolorrendering % <crdname> <found> % Adobe interpreters report /findcolorrendering (literal name), not the % operator itself, if an error occurs in findcolorrendering. /findcolorrendering { /ColorRendering /ProcSet findresource 1 .argindex dup type /nametype eq { .namestring } if (.) concatstrings 1 index /GetPageDeviceName get exec dup type /nametype eq { .namestring } if (.) concatstrings 2 index /GetHalftoneName get exec dup type /nametype eq { .namestring } if concatstrings concatstrings cvn % stack: intentname procset crdname dup /ColorRendering resourcestatus { pop pop exch pop exch pop //true } { pop /GetSubstituteCRD get exec //false } ifelse } .errorexec } odef 5 dict dup begin /GetPageDeviceName { % - GetPageDeviceName <name> currentpagedevice dup /PageDeviceName .knownget { exch pop dup //null eq { pop /none } if } { pop /none } ifelse } bind def /GetHalftoneName { % - GetHalftoneName <name> currenthalftone /HalftoneName .knownget not { /none } if } bind def /GetSubstituteCRD { % <intentname> GetSubstituteCRD <crdname> pop /DefaultColorRendering } bind def end % The resource machinery hasn't been activated, so just save the ProcSet % and let .fixresources finish the installation process. /ColorRendering exch def % Define setcolorrendering. /.colorrenderingtypes 5 dict def /setcolorrendering { % <crd> setcolorrendering - dup /ColorRenderingType get dup type /integertype ne { /setcolorrendering .systemvar /typecheck signalerror } if //.colorrenderingtypes exch .knownget { exec } { /setcolorrendering .systemvar /rangecheck signalerror } ifelse } odef /.setcolorrendering1 where { pop } { (%END CRD) .skipeof } ifelse .colorrenderingtypes 1 { % Adobe ProcSet "Adobe_AGM_Core 2.0 0" places an /Intent key into CRD's dup /Intent .knownget { //.renderingintentdict exch .knownget { .setrenderingintent } if } if dup .buildcolorrendering1 .setcolorrendering1 } .bind put % Note: the value 101 in the next line must be the same as the value of % GX_DEVICE_CRD1_TYPE in gscrdp.h. .colorrenderingtypes 101 { dup .builddevicecolorrendering1 .setdevicecolorrendering1 } .bind put % sRGB output CRD, D65 white point mark /ColorRenderingType 1 /RangePQR [ -0.5 2 -0.5 2 -0.5 2 ] readonly % Bradford Cone Space /MatrixPQR [ 0.8951 -0.7502 0.0389 0.2664 1.7135 -0.0685 -0.1614 0.0367 1.0296] readonly /MatrixLMN [ 3.240449 -0.969265 0.055643 -1.537136 1.876011 -0.204026 -0.498531 0.041556 1.057229 ] readonly % Inverse sRGB gamma transform /EncodeABC [ { dup 0.00304 le { 12.92321 mul } { 1 2.4 div exp 1.055 mul 0.055 sub } ifelse } bind dup dup ] readonly /WhitePoint [ 0.9505 1 1.0890 ] readonly % D65 /BlackPoint [ 0 0 0 ] readonly % VonKries-like transform in Bradford Cone Space /TransformPQR % The implementations have been moved to C for performance. [ { .TransformPQR_scale_WB0 } bind { .TransformPQR_scale_WB1 } bind { .TransformPQR_scale_WB2 } bind ] readonly .dicttomark setcolorrendering %END CRD % Initialize a CIEBased color space for sRGB. /CIEsRGB [ /CIEBasedABC mark /DecodeLMN [ { dup 0.03928 le { 12.92321 div } { 0.055 add 1.055 div 2.4 exp } ifelse } bind dup dup ] readonly /MatrixLMN [ 0.412457 0.212673 0.019334 0.357576 0.715152 0.119192 0.180437 0.072175 0.950301 ] readonly /WhitePoint [0.9505 1.0 1.0890] readonly .dicttomark readonly ] readonly def % Special type to install % sRGB ICC profile color space /CIEsRGBICC [ /ICCBased mark /N 3 /DataSource (srgb) /Alternate [/DeviceRGB] /Name (srgb) .dicttomark ] def % Special type to install % sGray ICC profile color space /CIEsGRAYICC [ /ICCBased mark /N 1 /DataSource (sgray) /Alternate [/DeviceGray] /Name (sgray) .dicttomark ] def % Special type to install % e-sRGB ICC profile color space /CIEesRGBICC [ /ICCBased mark /N 3 /DataSource (esrgb) /Alternate [/DeviceRGB] /Name (esrgb) .dicttomark ] def % Special type to install % rommRGB ICC profile color space /CIErommRGBICC [ /ICCBased mark /N 3 /DataSource (rommrgb) /Alternate [/DeviceRGB] /Name (rommrgb) .dicttomark ] def % ------ Painting ------ % % A straightforward definition of execform that doesn't actually % do any caching. /.execform1 { % This is a separate operator so that the stacks will be restored % properly if an error occurs. %% High level forms need the CTM before the Form Matrix is applied /UNROLLFORMS where {/UNROLLFORMS get}{//false}ifelse not {matrix currentmatrix exch} if dup /Matrix get concat dup /BBox get aload pop exch 3 index sub exch 2 index sub rectclip dup /PaintProc get 1 index /Implementation known not { 1 index dup /Implementation //null .forceput readonly pop } executeonly if /UNROLLFORMS where {/UNROLLFORMS get}{//false}ifelse not %% [CTM] <<Form>> PaintProc .beginform - { %% First,, check to see if we have no /Implementation already defined (see above) 1 index /Implementation get //null eq { %% We don't, so copy the form dictionary 1 index 4 1 roll %% tell devices we're starting a form, run the PaintProc, and then tell the devices we've finished 3 -1 roll 2 index .beginform exec %% This is all horrible code to deal with illegal forms which leave junk on the operand stack %% Starting from 1 (not 0, we don't want to look at the loop count) and going up to the %% number of objects on the stack, check each object to see if its the Form dict (it is %% *supposed* to be the top object after executing the PaintProc). I don't currently check to see if %% the PaintProc ate the dict, but if there are extra objects, remove them and tell %% the user. %% count 1 1 3 -1 roll { dup index dup type /dicttype eq { /Implementation known { 2 sub 0 1 3 -1 roll { QUIET not { (\n WARNING - Form PaintProc left operands on the stack after execution.\n This is technically illegal and these have been removed, \n if output is incorrect run again with -dUNROLLFORMS.\n) = } if pop pop } for exit }if } { pop pop }ifelse } for .endform %% Ask devices if they have cached the form, and what ID to use if so %% returning -1 means 'no ID' .get_form_id dup -1 eq {pop pop} { %% The form is cached with a specific ID. Make a dictionary (which we'll store in the %% Form dictioanry using the /Implementation key). 1 dict dup /FormID 4 -1 roll put 1 index exch /Implementation exch .forceput readonly pop } executeonly ifelse } { %% We have a (non-null) Implementation, get the dictionary and pull the %% FormID key from it, then tell the device to use the stored form with the %% specified key. pop dup /Implementation get /FormID get .repeatform }ifelse } {exec} ifelse } .bind odef % must bind .forceput /.formtypes 5 dict dup 1 /.execform1 load put def /execform { % <form> execform - gsave { dup /FormType get //.formtypes exch get exec } stopped grestore { stop } if } odef /.patterntypes 5 dict dup 1 /.buildpattern1 load put def /makepattern { % <proto_dict> <matrix> makepattern <pattern> dup type /dicttype eq { % "<dict> makepattern" reports /typecheck on Adobe /makepattern .systemvar /typecheck signalerror } if //.patterntypes 2 .argindex /PatternType get .knownget not { /makepattern .systemvar /rangecheck signalerror } if .currentglobal //false .setglobal exch % Stack: proto matrix global buildproc 3 index dup length 1 add dict .copydict % Stack: proto matrix global buildproc newdict 3 index 3 -1 roll exec % Stack: proto matrix global newdict instance % Create an 'Implementation' entry for the pattern dict. The PRLM 3rd says % this about the contents of Implementation: "The type and value of this % entry are implementation-dependent." The CET (page 2 of 18-02f) expects % that this entry be an array and that the second element of the array be a % gstate. We put our pattern instance struct into the first element of the % array. 1 index /Implementation 3 -1 roll .getCPSImode { gstate } { //null } ifelse 2 array astore put % put Implementation into the pattern dict. % Stack: proto matrix global newdict readonly exch .setglobal exch pop exch pop } odef /setpattern { % [<comp1> ...] <pattern> setpattern - { currentcolorspace 0 get /Pattern ne { [ /Pattern currentcolorspace ] setcolorspace } if setcolor } stopped { /setpattern .systemvar $error /errorname get signalerror } if } odef % The following functions emulate the actions of findcmykcustomcolor and % setcustomcolor. These functions are described in Adobe's TN 5044. That % same document also says "The following "operators" are not defined in the % PostScript Language Reference Manual, but should be used as pseudo-operators % in your PostScript language output. Separation applications from Adobe % Systems and other vendors will redefine these convention operators to % separate your documents. Your application should conditionally define % procedures with these special names, as shown later in this document." % % We are providing these functions because we have found files created by % "QuarkXPress: pictwpstops filter 1.0" which produce bad shading dictionaries % if these operators are not defined. % Also we add a findrgbcustomcolor that was discovered in Adobe Illustrator % AI5 (Adobe Illustrator (R) Version 7.0 Full Prolog) ProcSet that allows % us to create Separation colorspace with a /DeviceRGB tint transform. % Conditionally disable the TN 5044 psuedo-ops if NO_TN5044 specified /NO_TN5044 where { pop (%END TN 5044 psuedo-ops) .skipeof } if % TN 5044 does not define the contents of the array. We are simply putting % the values given into an array. This is consistent with what we see when % testing with Adobe Distiller 6.0. % <cyan> <magenta> <yellow> <black> <key> findcmykcustomcolor <array> /findcmykcustomcolor { 5 array astore } bind executeonly def % The following isn't documented by Adobe, but was found in Adobe Illustrator (R) % Version 7.0 Full Prolog /findrgbcustomcolor { 4 array astore } bind executeonly def % Build a tint transform function for use by setcustomcolor. This function % is for a Separation color space which has either a DeviceCMYK base color space % (i.e. 1 input and 4 outputs) or a DeviceRGB colorspace (1 in, 3 out). % The input to buildcustomtinttransform is the array created by findcmykcustomcolor % and the length of the array is used to determine the alternate colorspace. % The resulting function for CMYK is: % { dup cyan mul exch dup magenta mul exch dup yellow mul exch black mul } % Where cyan, magenta, yellow, and black are values from the array. % For RGB, since the resulting function is: % { dup red mul exch dup green mul exch blue mul } /buildcustomtinttransform % <array> buildcustomtinttransform <function> { dup length 5 eq { % CMYK [ /dup load 2 index 0 get /mul load /exch load /dup load 6 index 1 get /mul load /exch load /dup load 10 index 2 get /mul load /exch load 13 index 3 get /mul load ] } { % RGB is assumed [ /dup load 2 index 0 get /mul load /exch load /dup load 6 index 1 get /mul load /exch load 9 index 2 get /mul load ] } ifelse cvx bind exch pop % Make executable and remove the input array } bind executeonly def % Construct the colorspace array to be used by setcolorspace from the array % result of either findcmykcustomcolor or findrgbcustomcolor. /buildcolorspacearray % <array> buildcustomtinttransform <colorspace_array> { % as with buildcustomtinttransform, the length of the array is used to % determine the alternate colorspace dup length 5 eq { % Start building Separation colorspace with CMYK alternate [ /Separation 2 index 4 get % Get separation name from array's key /DeviceCMYK 4 index //buildcustomtinttransform exec % build the tint transform function ] } { [ /Separation 2 index 3 get % Get separation name from array's key /DeviceRGB 4 index //buildcustomtinttransform exec % build the tint transform function ] } ifelse exch pop % remove the input array } bind executeonly def % Set a custom color based upon a tint and array which describes the custom % color. See findcmykcustomcolor. First we create and then set a Separation % colorspace. Then we set the specified color. % Note that older Adobe ProcSets apparently allow for 'null' as the tint % for some reason, so an alternate operational mode is tolerated: % null setcustomcolor - /setcustomcolor % <array> <tint> setcustomcolor - { dup //null eq { pop pop }{ % Check that the tint is a number between 0 and 1 dup type dup /integertype eq exch /realtype eq or not { /setcustomcolor cvx /typecheck signalerror } if % Bug 703869. Apparently Adobe (at least Acrobat Pro) silently clamps values dup 1 le not { pop 1 } if dup 0 ge not { pop 0 } if % The array is supposed to be the result of fundcmykcustomcolor. Our % implementation just pushes all the arguments into the array and that's % what buildcolorspacearray expects. So check that now. % Starting with the first N-1 elemenst which must be numbers where 0 <= x <= 1 1 index 0 1 2 index length 2 sub { 1 index exch get dup type dup /integertype eq exch /realtype eq or not { /setcustomcolor cvx /typecheck signalerror } if dup 1 le not { /setcustomcolor cvx /rangecheck signalerror } if 0 ge not { /setcustomcolor cvx /rangecheck signalerror } if } for % Finally, check the last element of the array, which must be a string. dup length 1 sub get type /stringtype eq not { /setcustomcolor cvx /typecheck signalerror } if exch //buildcolorspacearray exec setcolorspace % Set the Separation color space as current setcolor % Set the tint as the current color } ifelse } bind executeonly def % This proc is supposed to implement a version of overprinting. TN 5044 says % that this proc is not used by any shipping host-based application. We have % only found it being used in a proc set in files by Canvas from Deneba Systems. % Even their proc set does not actually do any overprinting. However their % files crash if this is not defined. Thus we have a copy of this proc but % we are simply checking for inputs being -1 and if so then we set the value % to 0. /setcmykoverprint { 4 { dup -1 eq { pop 0 } if 4 1 roll } repeat setcmykcolor } bind def /separation_all [/Separation /All /DeviceCMYK { dup dup dup } bind ] readonly def % Collect the arguments into the image dictionary % <width> <height> <bits/sample> <matrix> <proc> args2dict <dict> /args2dict { 10 dict begin {1 0} 1 { /ImageType /Decode /DataSource /ImageMatrix /BitsPerComponent /Height /Width } { exch def } forall currentdict end } bind def % Prints (1-gray) on all separations. % <gray> setseparationgray - /setseparationgray { //separation_all setcolorspace 1 exch sub setcolor } bind def % Renders an image whose sample values specify the amount of the custom color. % <width> <height> <bits/sample> <matrix> <proc> <array> customcolorimage - /customcolorimage { gsave //buildcolorspacearray exec setcolorspace //args2dict exec image grestore } bind def % Renders an image on all process and custom color plates. % <width> <height> <bits/sample> <matrix> <proc> /separationimage { gsave //separation_all setcolorspace //args2dict exec image grestore } bind def { /buildcustomtinttransform /buildcolorspacearray /separation_all /args2dict } { currentdict exch undef } forall %END TN 5044 psuedo-ops end % level2dict % undefine things defined in this file and not referenced elsewhere [ /.checkprocesscomment /.pair2dict /.setcolorrendering1 /.checkparamtype /.checksetparams ] dup level2dict .undefinternalnames systemdict .undefinternalnames
| ver. 1.4 |
Github
|
.
| PHP 8.2.28 | Generation time: 0.05 |
proxy
|
phpinfo
|
Settings