summaryrefslogtreecommitdiff
path: root/Master/tlpkg/tlgs/lib/opdfread.ps
diff options
context:
space:
mode:
Diffstat (limited to 'Master/tlpkg/tlgs/lib/opdfread.ps')
-rw-r--r--Master/tlpkg/tlgs/lib/opdfread.ps4594
1 files changed, 4594 insertions, 0 deletions
diff --git a/Master/tlpkg/tlgs/lib/opdfread.ps b/Master/tlpkg/tlgs/lib/opdfread.ps
new file mode 100644
index 00000000000..f934f085134
--- /dev/null
+++ b/Master/tlpkg/tlgs/lib/opdfread.ps
@@ -0,0 +1,4594 @@
+%!PS-Adobe-2.0
+%
+% Copyright (C) 2002 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.
+%
+% For more information about licensing, please refer to
+% http://www.ghostscript.com/licensing/. For information on
+% commercial licensing, go to http://www.artifex.com/licensing/ or
+% contact Artifex Software, Inc., 101 Lucas Valley Road #110,
+% San Rafael, CA 94903, U.S.A., +1(415)492-9861.
+
+% $Id: opdfread.ps 11951 2010-12-15 08:22:58Z ken $
+% pdfread.ps - A procset for interpreting an ordered PDF 1.3 file.
+
+% This module defines routines for interpreting a PDF file with
+% a Postscript interpreter. To convert a PDF file into Postscript
+% just pre-contcatenate this file. The PDF file must satisfy
+% few constraints :
+%
+% 1. It must contain only Postscript level 2 objects encoded with
+% the PDF 1.3 language. Higher PDF levels must be re-distilled
+% with CompatibilityLevel=1.3 .
+%
+% 2. Objects must be ordered so that any resource be defined before
+% its usage.
+%
+% 3. The PDF file must not include other PDF files.
+% Consequently we have a single instance of the PDF reader.
+% We use this fact to simplify binding of the routines.
+%
+% 4. The PDF root object must always have the object id 1.
+%
+% 5. Generations besides 0 are not allowed.
+%
+% 6. xref must appear after all objects.
+%
+% Assuming the currentfile isn't positionable.
+% As a consequence, the reader fully ignores xref.
+
+% ====================== Error handler =======================
+% A general error handler prints an error to page.
+
+%
+% See if our notification from ps2write is present. If it is
+% then pick it up. Otherwise define it as false. Used to prevent
+% use of setmatrix at start of each page. The DSC-compliant
+% output from ps2write wraps pages in a save/restore, so we don't
+% need the setmatrix, and it breaks use of psnup with the output.
+%
+currentdict /DSC_OPDFREAD known {
+ currentdict /DSC_OPDFREAD get
+}{
+ false
+} ifelse
+
+10 dict begin % A dictionary for local binding
+
+% This switch used to control paeg independent values, like
+% whether to use InitialMatrix in SetupPageView
+%
+/DSC_OPDFREAD exch def
+
+/this currentdict def
+/y 720 def
+/ebuf 200 string def
+
+/prnt {
+ 36 //this /y get moveto //ebuf cvs show
+ //this /y 2 copy get 12 sub put
+} bind def
+
+/newline {
+ 36 //this /y get moveto
+ //this /y 2 copy get 12 sub put
+} bind def
+
+errordict /handleerror
+{ systemdict begin
+ $error begin
+ newerror
+ { (%%[ Error handled by opdfread.ps : ) print errorname //ebuf cvs print (; OffendingCommand: )
+ print /command load //ebuf cvs print ( ]%%) = flush
+ /newerror false store vmstatus pop pop 0 ne
+ { grestoreall
+ } if
+ errorname (VMerror) ne
+ { showpage
+ } if
+ initgraphics
+ 0 720 moveto
+ errorname (VMerror) eq
+ { //this /ehsave known
+ { clear //this /ehsave get restore 2 vmreclaim
+ } if
+ vmstatus exch pop exch pop
+ }
+ /Courier 12 selectfont
+ {
+ (ERROR: ) //prnt exec errorname //prnt exec
+ (OFFENDING COMMAND: ) //prnt exec
+ /command load //prnt exec
+ $error /ostack known {
+ (%%[STACK:) =
+ (STACK:) //prnt exec
+ $error /ostack get aload length {
+ //newline exec
+ dup mark eq {
+ (-mark-) dup = show
+ } {
+ dup type /nametype eq {
+ dup xcheck not {
+ (/) show
+ (/) print
+ } if
+ } if
+ dup = //ebuf cvs show
+ } ifelse
+ } repeat
+ } if
+ } ifelse
+ (%%]%) =
+ //systemdict /showpage get exec
+ quit
+ } if
+ end
+ end
+} bind readonly put
+
+end % A dictionary for local binding
+
+
+50 dict begin
+
+% ===================== Debugging =========================================
+
+/DefaultSwitch % <name> DefaultSwitch -
+{
+ dup where {
+ pop pop
+ } {
+ false def
+ } ifelse
+} bind def
+
+/=string 256 string def
+
+/=only {
+ //=string cvs print
+} bind def
+
+/HexDigits (0123456789ABCDEF) readonly def
+
+/PrintHex % <int> PrintHex -
+{ 8 {
+ dup -28 bitshift //HexDigits exch 1 getinterval //=only exec
+ 4 bitshift
+ } repeat
+ pop
+} bind def
+
+/PDFR_DEBUG DefaultSwitch
+/PDFR_DUMP DefaultSwitch
+/PDFR_STREAM DefaultSwitch
+/TTFDEBUG DefaultSwitch
+/RotatePages DefaultSwitch
+/FitPages DefaultSwitch
+/CenterPages DefaultSwitch
+/SetPageSize DefaultSwitch
+
+/error % mark <object> .... error -
+{ % A stub for a while.
+ counttomark 1 sub -1 0 {
+ index dup type /arraytype eq { == } { =only } ifelse
+ } for
+ () =
+ cleartomark
+ % Assuming ....Undefined is never defined.
+ % Use it to emit an error.
+ ....Undefined
+} bind def
+
+//SetPageSize {
+ //RotatePages //FitPages or //CenterPages or{
+ mark (/RotatePages, /FitPages and CenterPages are not allowed with /SetPageSize) //error exec
+ } if
+}
+{
+ //FitPages //CenterPages and {
+ mark (CenterPages is not allowed with /FitPages) //error exec
+ } if
+}
+ifelse
+
+% ===================== Utilities =========================================
+
+/knownget % <dict> <key> knownget <value> true
+ % <dict> <key> knownget false
+{
+ 2 copy known {
+ get true
+ } {
+ pop pop false
+ } ifelse
+} bind def
+
+/IsUpper % <int> IsUpper <bool>
+{ dup (A) 0 get ge exch (Z) 0 get le and
+} bind def
+
+% Copy (recursive) packedarray|array to to global VM
+% NOTE: a packedarray will be converted to non-packed (too bad)
+/cpa2g { % <packedarray|array> cpa2g <packedarray|array>
+ dup length array % <src> <dest>
+ 0 1 2 index length 1 sub {
+ % <src> <dest> index
+ dup 3 index exch get cp2g
+ % <src> <dest> index <globalelement>
+ 3 copy put pop pop
+ } for
+ exch pop
+} bind def
+
+% Copy (recursive) dict to to global VM
+/cpd2g {
+ dup length dict exch {
+ cp2g 2 index 3 1 roll put
+ } forall
+} bind def
+
+% Copy string to to global VM
+/cps2g { % <string> cps2g <string>
+ dup length string copy
+} bind def
+
+/cp2gprocs
+<< /arraytype //cpa2g /dicttype //cpd2g /packedarraytype //cpa2g /stringtype //cps2g >>
+def
+
+/cp2g { % <any> cp2g <any>
+ % where <any> is array | dict | string | packedarray
+ % NOTE: The object must be readable (not executeonly or noaccess)
+ dup gcheck not {
+ dup //cp2gprocs 1 index type
+ 2 copy known {
+ get currentglobal 3 1 roll true setglobal exec exch setglobal
+ % set the attributes appropriately (we must have 'read' access to get this far)
+ 1 index wcheck not { readonly } if
+ 1 index xcheck { cvx } if
+ exch pop % discard original (local) object
+ } {
+ pop pop % discard type
+ } ifelse
+ } if
+} bind def
+
+% ===================== Work Data =========================================
+
+/BlockBuffer 65535 string def % Make it big to load entire TrueType font
+/PDFReader currentdict def
+/ObjectRegistryMaxLength 50000 def
+/ObjectRegistry 10 dict def
+ObjectRegistry
+begin
+ 0 ObjectRegistryMaxLength dict def
+end
+/CurrentObject null def
+/DoneDocumentStructure false def
+/GraphicState 20 dict begin
+ /InitialTextMatrix matrix def
+ /InitialMatrix matrix currentmatrix def
+currentdict end def
+/TempMatrix matrix def
+/GraphicStateStack 20 array def
+/GraphicStateStackPointer 0 def
+/InitialTextMatrixStack 20 array def
+/InitialTextMatrixStackPointer 0 def
+/PDFColorSpaces 50 dict def
+/InstalledFonts 50 dict def
+/MacRomanEncodingInverse null def
+
+% We need some structures in local VM, put then into the userdict :
+currentglobal false setglobal
+userdict /PDFR_InitialGS gstate put
+userdict /PDFR_Patterns 50 dict put
+userdict /FuncDataReader 10 dict put
+setglobal
+
+% ===================== Constants =========================================
+
+% The ExtGState elements are composite, thus need to be copied to
+% global VM (in case they aren't already global).
+/InitialExtGState 20 dict begin
+ /BG2 currentblackgeneration cp2g def
+ /UCR2 currentundercolorremoval cp2g def
+ /TR2 currentglobal false setglobal [ currentcolortransfer ] exch setglobal cp2g def
+ /HT currenthalftone cp2g def
+currentdict end readonly def
+
+/InitialGraphicState 20 dict begin
+ /FontSize 0 def
+ /CharacterSpacing 0 def
+ /TextLeading 0 def
+ /TextRenderingMode 0 def
+ /WordSpacing 0 def
+currentdict end readonly def
+
+/SimpleColorSpaceNames 15 dict begin
+ /DeviceGray true def
+ /DeviceRGB true def
+ /DeviceCMYK true def
+currentdict end readonly def
+
+/1_24_bitshift_1_sub 1 24 bitshift 1 sub def
+
+/ReadFontProcs 10 dict def % Will be filled below.
+
+/GetObject % <id> GetObject obj true
+ % <id> GetObject false
+{
+ dup ObjectRegistryMaxLength idiv
+ //PDFReader /ObjectRegistry get exch knownget {
+ exch knownget
+ } {
+ pop false
+ }ifelse
+} bind def
+
+/PutObject % <id> <obj> PutObject
+{
+ 1 index ObjectRegistryMaxLength idiv % id obj oregnr
+ //PDFReader /ObjectRegistry get 1 index knownget {
+ % object already defined in Objectregistry
+ % id obj oregnr dict
+ exch pop % id obj dict
+ 3 1 roll put
+ }{
+ % object not already defined in ObjectRegistry
+ % id obj oregnr
+ //PDFReader /ObjectRegistry get dup
+ begin % new Objectregistry entry:
+ 1 index ObjectRegistryMaxLength dict def
+ end
+ exch get % id obj dict
+ 3 1 roll put
+ }ifelse
+} bind def
+
+% ===================== Reading PDF objects ===============================
+
+/Register % <DefaultDaemon> <id> <obj> Register -
+{
+ 1 index GetObject {
+ % d id obj e
+ dup xcheck {
+ 4 3 roll pop % id obj e
+ //PDFR_DEBUG {
+ (Have a daemon for ) print 2 index ==
+ } if
+ %% We've got a definition daamon, execute it:
+ exec
+ } {
+ dup null ne {
+ mark (The object ) 4 index (is already defined : ) 4 index //error exec
+ } {
+ pop % d id obj
+ } ifelse
+ 3 2 roll % id obj d
+ %% Execute the default Daemon
+ exec
+ }ifelse
+ } {
+ % d id obj
+ 3 2 roll % id obj d
+ exec % execute the default deamon
+ }ifelse
+ PutObject
+} bind def
+
+/IsRegistered % <id> GetRegistered <bool>
+{
+ GetObject {
+ null ne
+ } {
+ false
+ }ifelse
+} bind def
+
+/GetRegistered % <id> GetRegistered <obj>
+{
+ dup GetObject not {
+ exch mark exch (Object ) exch ( isn't defined before needed (1).) //error exec
+ } if
+ % id obj
+ dup xcheck {
+ exch mark exch (Object ) exch ( isn't defined before needed (2).) //error exec
+ } {
+ dup null eq {
+ exch mark exch (Object ) exch ( isn't defined before needed (3).) //error exec
+ } if
+ exch pop % e
+ } ifelse
+} bind def
+
+/StandardFontNames <<
+ /Times-Roman true
+ /Helvetica true
+ /Courier true
+ /Symbol true
+ /Times-Bold true
+ /Helvetica-Bold true
+ /Courier-Bold true
+ /ZapfDingbats true
+ /Times-Italic true
+ /Helvetica-Oblique true
+ /Courier-Oblique true
+ /Times-BoldItalic true
+ /Helvetica-BoldOblique true
+ /Courier-BoldOblique true
+>> def
+
+/CleanAllResources % - CleanAllResources -
+{ //PDFR_DEBUG {
+ (CleanAllResources beg) =
+ } if
+ //PDFReader /ObjectRegistry get {
+ dup length 0 exch 1 exch 1 sub { % R i
+ 2 copy get dup xcheck {
+ % Don't clean a daemon.
+ pop pop
+ } {
+ dup null eq {
+ pop pop
+ } {
+ dup type /dicttype eq { /.Global known } { pop false } ifelse {
+ pop
+ } {
+ //PDFR_DEBUG {
+ (Dropping ) print dup =
+ } if
+ 1 index exch /DroppedObject put
+ } ifelse
+ } ifelse
+ } ifelse
+ } for
+ pop
+ }forall % Check each dictionary in the ObjectRegistry
+ FontDirectory length dict begin
+ FontDirectory {
+ pop
+ dup //StandardFontNames exch known not {
+ dup null def
+ } if
+ pop
+ } forall
+ currentdict
+ end {
+ pop
+ //PDFR_DEBUG {
+ (Undefining font ) print dup =
+ } if
+ undefinefont
+ } forall
+ //PDFR_DEBUG {
+ (CleanAllResources end) =
+ } if
+} bind def
+
+/PrintReference % <array> PrintReference <array>
+{
+ //PDFR_DEBUG {
+ ({ ) print
+ dup {
+ =only ( ) print
+ } forall
+ ( }) =
+ } if
+} bind def
+
+/R % <id> <gen> R <daemon>
+{ % Make a reference daemon.
+ 0 ne {
+ exch mark exch (A referred object generation ) exch ( isn't 0.) //error exec
+ } if % id
+ [ % <id> proc <obj>
+ exch //GetRegistered /exec load
+ ] cvx
+ //PrintReference exec
+} bind def
+
+/IsObjRef % <any> IsObjRef <bool>
+{
+ dup type /arraytype eq {
+ dup length 3 eq {
+ dup xcheck exch
+ dup 0 get type /integertype eq 3 2 roll and exch
+ dup 1 get //GetRegistered eq 3 2 roll and exch
+ 2 get /exec load eq and
+ } {
+ pop false
+ } ifelse
+ } {
+ pop false
+ } ifelse
+} bind def
+
+/DoNothing
+{
+} def
+
+/RunTypeDaemon % <id> <obj> RunTypeDaemon <id> <obj>
+{
+ dup type /dicttype eq {
+ dup /Type //knownget exec {
+ //PDFReader /TypeDaemons get exch
+ //knownget exec {
+ exec
+ } if
+ } if
+ } if
+} bind def
+
+/obj % <id> <generation> obj <id>
+{
+ //PDFR_DEBUG {
+ (Defining ) print 1 index =only ( ) print dup =only ( obj) =
+ } if
+ 0 ne {
+ exch mark exch (An object generation ) exch ( isn't 0.) //error exec
+ } if
+} bind def
+
+/endobj % <id> <obj> endobj -
+{
+ //PDFR_DEBUG {
+ (endobj ) =
+ } if
+ dup type /dicttype eq {
+ dup /.endobj_daemon //knownget exec {
+ //PDFR_DEBUG { (.endobj_daemon for ) print 2 index = } if
+ exec
+ } if
+ } if
+ dup type /dicttype eq { dup /ImmediateExec known } { false } ifelse {
+ pop pop
+ } {
+ //PDFR_DEBUG {
+ (Storing ) print 1 index =
+ } if
+ //RunTypeDaemon exec
+ //DoNothing 3 1 roll //Register exec
+ } ifelse
+} bind def
+
+/StoreBlock % <buf> StoreBlock -
+{ % Stores a (encoded) stream data block to the current object.
+ //PDFR_DEBUG {
+ (StoreBlock ) print //PDFReader /BlockCount get =only (, Length = ) print dup length =
+ } if
+ dup length string copy
+ //PDFReader /BlockCount get exch % i s
+ //PDFReader /CurrentObject get 3 1 roll % o i s
+ put %
+ //PDFReader /BlockCount get 1 add
+ //PDFReader exch /BlockCount exch put
+} bind def
+
+/CheckLength % <val> CheckNumber <val>
+{ dup type /integertype ne {
+ mark (Object length isn't an integer.) //error exec
+ } if
+} bind def
+
+/ResolveD % <dict> <key> <check> ResolveD <value>
+{
+ 3 copy pop get % <> key {} e
+ dup //IsObjRef exec {
+ % We've got a reference daemon, execute it :
+ //PDFR_DEBUG {
+ (Resolving ) print //PrintReference exec
+ } if
+ exec % <> key {} val
+ exch exec % <> key val
+ } {
+ exch pop
+ } ifelse
+ dup 4 1 roll % val <> key val
+ put % val
+} bind def
+
+/ResolveA % <array> <index> <check> ResolveA <value>
+{ 2 index 2 index get
+ dup //IsObjRef exec {
+ exec
+ exch exec
+ 3 copy put
+ } {
+ exch pop
+ } ifelse
+ exch pop exch pop
+} bind def
+
+/StoreStream % <id> <obj> StoreStream <id> <obj>
+{ % Stores a (encoded) data stream copy to the current object.
+ dup //PDFReader exch /CurrentObject exch put % id obj
+ //PDFReader /BlockCount 0 put
+ dup /Length //CheckLength //ResolveD exec % id obj l
+ //PDFR_DEBUG {
+ (StoreStream Length = ) print dup =
+ } if
+ currentfile exch () /SubFileDecode filter % id obj file
+ { dup //BlockBuffer readstring { % id obj file buf
+ //StoreBlock exec
+ } {
+ //StoreBlock exec
+ exit
+ } ifelse % id obj file
+ } loop
+ pop % id obj
+ //PDFReader /CurrentObject null put
+ //PDFR_DEBUG {
+ (StoreStream end.) =
+ } if
+} bind def
+
+/MakeStreamDumper % <file> MakeStreamDumper <file>
+{ % Debug purpose only.
+ //PDFR_DEBUG {
+ (MakeStreamDumper beg.) =
+ } if
+ currentglobal exch dup gcheck setglobal
+ [ exch % f
+ 1 dict dup /c 0 put exch % d f
+ 1024 string % d f s
+ { readstring pop % d s
+ (StreamDumper ) print 1 index /c get =string cvs print ( ) print
+ dup length =string cvs print ( <) print dup print (>\n) print
+ dup length % d s l
+ 3 2 roll % s l d
+ dup /c get % s l d c
+ 3 2 roll % s d c l
+ add /c exch put % s
+ } /exec load
+ ]
+ cvx 0 () /SubFileDecode filter
+ exch setglobal
+ //PDFR_DEBUG {
+ (MakeStreamDumper end.) =
+ } if
+} bind def
+
+/ShortFilterNames 15 dict begin
+ /AHx /ASCIIHexDecode def
+ /A85 /ASCII85Decode def
+ /LZW /LZWDecode def
+ /Fl /FlateDecode def
+ /RL /RunLengthDecode def
+ /CCF /CCITTFaxDecode def
+ /DCT /DCTDecode def
+currentdict end readonly def
+
+/AppendFilters % <file> <dict> AppendFilters <file>
+{
+ //PDFR_DEBUG {
+ (AppendFilters beg.) =
+ } if
+ dup 3 1 roll % d f d
+ /Filter //knownget exec { % d f F
+ dup type /nametype eq { % d f /F
+ dup //ShortFilterNames exch //knownget exec {
+ exch pop
+ } if
+ 2 index /DecodeParms //knownget exec { % d f p /F
+ exch
+ } if
+ filter % d f'
+ } { % d f []
+ dup 0 exch 1 exch length 1 sub { % d f [] i
+ 2 copy get % d f [] i /F
+ dup //ShortFilterNames exch //knownget exec {
+ exch pop
+ } if
+ 3 1 roll % d f /F [] i
+ 4 index /DecodeParms //knownget exec { % d f /F [] i DP
+ exch get % d f /F [] dp
+ } { % d f /F [] i
+ pop null % d f /F [] dp
+ } ifelse
+ dup null eq { % d f /F [] dp
+ pop 3 1 roll filter exch % d f' []
+ } { % d f /F [] dp
+ 3 1 roll % d f dp /F []
+ 4 1 roll filter exch % d f' []
+ } ifelse
+ } for
+ pop % d f'
+ } ifelse
+ //PDFR_DEBUG //PDFR_DUMP and {
+ //MakeStreamDumper exec
+ } if
+ } if
+ exch pop
+ //PDFR_DEBUG {
+ (AppendFilters end.) =
+ } if
+} bind def
+
+/ExecuteStream % <id> <obj> ExecuteStream <id> <obj>
+{ % Executes a (encoded) data stream.
+ dup //PDFReader exch /CurrentObject exch put % id obj
+ dup /Length //CheckLength //ResolveD exec % id obj l
+ //PDFR_DEBUG {
+ (ExecuteStream id = ) print 2 index =only ( Length = ) print dup =
+ } if
+ //PDFReader /InitialGraphicState get
+ //PDFReader /GraphicState get copy pop
+ //PDFReader /Operators get begin
+ % currentfile exch () /SubFileDecode filter % id obj file
+ % We would like to use the code above,
+ % but HP LaserJet 1320 continues parsing after the byte count exceeds.
+ pop currentfile 0 (endstream) /SubFileDecode filter % id obj file
+ 1 index //AppendFilters exec
+ cvx mark exch % id obj mark file
+ exec
+ counttomark 0 ne {
+ mark (Data left on ostack after an immediate stream execution.) //error exec
+ } if
+ cleartomark % id obj
+ end % Operators
+ //PDFR_DEBUG {
+ (ExecuteStream end.) =
+ } if
+ //PDFReader /CurrentObject null put
+ dup /IsPage known {
+ dup /Context get /NumCopies //knownget exec {
+ 1 sub {
+ copypage
+ } repeat
+ } if
+ showpage
+ } if
+} bind def
+
+/stream % <id> <obj> stream <id> <obj>
+{
+ //PDFR_DEBUG {
+ 1 index =only ( stream) =
+ } if % id obj
+ % Run the object definition daemon, if exists :
+ 1 index GetObject {
+ % id obj e
+ dup xcheck {
+ exec
+ % Disable the daemon :
+ 1 index null PutObject
+ } {
+ pop
+ } ifelse
+ }if
+ dup /ImmediateExec known {
+ dup /GlobalExec //knownget exec {
+ currentglobal 4 1 roll
+ setglobal
+ //ExecuteStream exec
+ 3 2 roll setglobal
+ } {
+ //ExecuteStream exec
+ } ifelse
+ } {
+ //StoreStream exec
+ } ifelse
+ dup /.CleanResources //knownget exec {
+ /All eq {
+ //CleanAllResources exec
+ } if
+ } if
+} bind def
+
+/HookFont % <id> <obj> <font_descriptor> HookFont <id> <obj>
+{
+ //PDFR_DEBUG {
+ (Loaded the font ) print dup /FontName get =
+ } if
+ {
+ dup /FontFileType get dup /Type1 eq exch /MMType1 eq or { % id obj fd
+ % We assume that the Type 1 font has same name with no prefix
+ % due to pdfwrite specifics.
+ % We use it to find the font after it is defined.
+ % We could redefine 'definefont' for hooking the font,
+ % but we don't think that it could be guaranteedly portable :
+ % a 3d party PS interpreter may set a special context
+ % when running the font file.
+ % Note that this mechanizm does not depend on the
+ % font name uniquity, because the last 'definefont'
+ % is only important.
+ dup /FontName get % id obj fd fn
+ //PDFReader /RemoveFontNamePrefix get exec
+ findfont % id obj fd g f
+ exit
+ } if
+ dup /FontFileType get /TrueType eq { % id obj fd
+ //PDFReader /MakeType42 get exec
+ //PDFR_DEBUG {
+ (Font dict <<) =
+ dup {
+ 1 index /sfnts eq {
+ exch pop
+ (/sfnts [) print
+ {
+ (-string\() print length //=only exec (\)- ) =
+ } forall
+ (]) =
+ } {
+ exch //=only exec ( ) print ==
+ } ifelse
+ } forall
+ (>>) =
+ } if
+ dup /FontName get exch definefont
+ exit
+ } if
+ mark (FontHook has no proc for ) 2 index /FontFileType get //error exec
+ } loop
+ /Font exch put % id obj
+} bind def
+
+/endstream % <id> <obj> endstream <id> <obj>
+{
+} bind def
+
+/xref % - xref -
+{
+ //PDFR_DEBUG {
+ (xref) =
+ //PDFR_DUMP {
+ //PDFReader /ObjectRegistry get ==
+ } if
+ } if
+ end % The procset
+ count 0 ne {
+ mark (Excessive data on estack at the end of the interpretation.) //error exec
+ } if
+ currentfile 1 (%%EOF) /SubFileDecode filter
+ flushfile
+ cleardictstack
+} bind def
+
+% ===================== Restoring the PDF Document Structure ===============
+
+/ResolveDict % <dict> /ResolveDict -
+{ dup { % d key val
+ pop 1 index exch % d cp key
+ //DoNothing //ResolveD exec % d obj
+ pop % d
+ } forall
+ pop %
+} bind def
+
+/SetupPageView % <obj> SetupPageView -
+{
+ //PDFR_DEBUG {
+ (SetupPageView beg) =
+ } if
+//DSC_OPDFREAD not {
+ //GraphicState /InitialMatrix get setmatrix
+} if
+ /MediaBox get aload pop % bx0 by0 bx1 by1
+ 3 index neg 3 index neg translate % Temporary move to origin
+ 3 -1 roll sub 3 1 roll exch sub exch % bw bh
+ userdict /.HWMargins //knownget exec {
+ aload pop
+ } {
+ currentpagedevice /.HWMargins //knownget exec {
+ aload pop
+ } {
+ 0 0 0 0
+ } ifelse
+ } ifelse
+ currentpagedevice /PageSize get aload pop
+ 3 -1 roll sub 3 1 roll exch sub exch % bw bh px0 py0 px1 py1
+ exch 3 index sub exch 3 index sub % bw bh px0 py0 pw ph
+ //SetPageSize {
+ //PDFR_DEBUG {
+ (Setting page size to ) print 1 index //=only exec ( ) print dup =
+ } if
+ pop pop 3 index 3 index 2 copy % bw bh px0 py0 bw bh bw bh
+ currentglobal false setglobal 3 1 roll % bw bh px0 py0 bw bh bool bw bh
+ 2 array astore % bw bh px0 py0 bw bh bool []
+ << exch /PageSize exch >> setpagedevice % bw bh px0 py0 bw bh bool
+ userdict /PDFR_InitialGS gstate put
+ setglobal % bw bh px0 py0 bw bh
+ } if
+ //RotatePages {
+ 2 copy gt 6 index 6 index gt ne {
+ % a rotation is useful except it fits with no rotation.
+ 1 index 5 index le 1 index 5 index le and not
+ } {
+ false
+ } ifelse
+ } {
+ false
+ } ifelse
+ { //CenterPages {
+ //PDFR_DEBUG {
+ (Rotating page, and then centering it) ==
+ } if
+ 90 rotate
+ 0 5 index neg translate
+ 5 index 1 index exch sub 2 div
+ 2 index 6 index sub 2 div neg % bw bh px0 py0 pw ph lm bm
+ translate
+ } {
+ //FitPages {
+ 1 index 5 index div 1 index 7 index div % bw bh px0 py0 pw ph sx sy
+ 2 copy gt {
+ exch
+ } if
+ pop dup scale % bw bh px0 py0 pw ph
+ } if
+ 90 rotate
+ 0 5 index neg translate
+ } ifelse
+ } {
+ //CenterPages {
+ //PDFR_DEBUG {
+ (Ccentering page) ==
+ } if
+ 1 index 6 index sub 2 div
+ 1 index 6 index sub 2 div % bw bh px0 py0 pw ph lm bm
+ translate
+ } {
+ //FitPages {
+ 1 index 6 index div 1 index 6 index div % bw bh px0 py0 pw ph sx sy
+ 2 copy gt {
+ exch
+ } if
+ pop dup scale % bw bh px0 py0 pw ph
+ } if
+ } ifelse
+ } ifelse
+ pop pop % bw bh px0 py0
+ translate % bw bh
+ pop pop %
+ //PDFR_DEBUG {
+ (SetupPageView end) =
+ } if
+} bind def
+
+/PageContentsDaemon % <id> <obj> <node> PageContentsDaemon <id> <obj>
+{ % Note: an excessive operand from a prebond procedure.
+ //PDFR_DEBUG {
+ (Executing PageContentsDaemon for ) print 2 index =
+ } if % id obj node
+ 1 index exch /Context exch put % id obj
+ dup /ImmediateExec true put
+ dup /IsPage true put
+ dup /Context get //SetupPageView exec
+} bind def
+
+/FontFileDaemon % <id> <obj> <font_descriptor> FontFileDaemon <id> <obj>
+{ % Note: an excessive operand from a prebond procedure.
+ //PDFR_DEBUG {
+ (Executing FontFileDaemon for ) print 2 index =
+ } if
+ % We need any font resource that refers this descriptor
+ % to know the font type. Assuming that FontDescriptorDaemon
+ % provided FontFileType.
+ dup /FontFileType get % id obj fd ft
+ 2 index exch % id obj fd obj ft
+ dup //ReadFontProcs exch //knownget exec { % id obj fd obj ft proc
+ exch pop exec % id obj fd
+ } {
+ mark (FontFile reader for ) 2 index ( isn't implemented yet.) //error exec
+ } ifelse
+ //PDFR_DEBUG {
+ (FontFileDaemon end) =
+ } if % id obj fd
+ pop
+} bind def
+
+/FontDescriptorDaemon % <id> <obj> <font_resource> FontDescriptorDaemon <id> <obj>
+{ % Note: an excessive operand from a prebond procedure.
+ //PDFR_DEBUG {
+ (Executing FontDescriptorDaemon for ) print 2 index =
+ } if % id obj fr
+ %HACK BEG assuming an own font for each font descriptor
+ % to provide an access to PDFEncoding
+ % from MakeType42, ComposeCharStrings.
+ 2 copy /FontResource exch put
+ %HACK END
+ /Subtype get 1 index exch /FontFileType exch put
+} bind def
+
+/UnPDFEscape { % <namepdf> UnPDFEscape <nameps>
+ dup dup length string cvs % /namepdf (name)
+ dup (#) search {
+ % name contains PDF-style escapes ("#hh") that need to be removed
+ { % ... (po..st) (#) (pre)
+ pop % ... (po..st) (#)
+ (16#--) 2 index 0 2 getinterval % ... (po..st) (#) (16#--) (po)
+ 1 index 3 2 getinterval copy pop % ... (po..st) (#) (16#po)
+ cvi % ... (po..st) (#) 16#po
+ 0 exch put % ... (po..st); 16#po patched into (#)
+ 0 % ... (po..st) 0
+ 1 index 2 1 index length 2 sub getinterval % ... (po..st) 0 (..st)
+ 3 copy putinterval % ... (..stst) 0 (XXst)
+ length % ... (..stst) 0 LEN_OF_(po..st)-2
+ 3 copy exch put % ... (..st\0t) 0 LEN_OF_(po..st)-2
+ getinterval % ... (..st), stored at begining of old (po..st)
+ (#) search not {
+ pop exit % /namepdf (nameps\0..)
+ } if
+ } loop
+ % we have a '\0' marker (not allowed in PDF names) after all usefull characters
+ (\0) search pop exch pop exch pop
+ cvn
+ exch pop
+ } {
+ pop pop
+ } ifelse
+} bind def
+
+/TypeDaemons << % <id> <obj> proc <id> <obj>
+ /Page
+ { //PDFR_DEBUG {
+ (Recognized a page.) =
+ } if
+ dup /Contents //knownget exec { % id obj c
+ 0 get //DoNothing exch % id obj dn id1
+ [ % <id> <obj> proc <id> <obj>
+ 3 index //PageContentsDaemon /exec load
+ ] cvx % id obj {}
+ //Register exec % id obj
+ } {
+ (fixme: page with no Contents won't be printed.) =
+ } ifelse
+ } bind
+ /FontDescriptor
+ { //PDFR_DEBUG {
+ (Recognized a font descriptor.) =
+ } if
+ dup /FontName //knownget exec {
+ 1 index /FontName 3 -1 roll //UnPDFEscape exec put
+ } if
+ dup dup /FontFile known {/FontFile} {/FontFile2} ifelse
+ //knownget exec { % id obj ff
+ 0 get //DoNothing exch % id obj dn id1
+ [ % <id> <obj> proc <id> <obj>
+ 3 index //FontFileDaemon /exec load
+ ] cvx % id obj {}
+ //Register exec % id obj
+ } {
+ % FontFile3 are not implemented yet.
+ (Font descriptor ) print 1 index =only ( has no FontFile.) =
+ } ifelse
+ } bind
+ /Font
+ { //PDFR_DEBUG {
+ (Recognized a font resource.) =
+ } if
+ dup /BaseFont //knownget exec {
+ //UnPDFEscape exec 2 copy /BaseFont exch put
+ % cache the installed font (if any) before replacing it.
+ //PDFReader /RemoveFontNamePrefix get exec
+ currentglobal exch % A hack against HP LaserJet 1320 bug :
+ % It sets the local allocation mode
+ % when 'resourcestatus' fails.
+ dup /Font resourcestatus {
+ pop pop
+ //PDFReader /GetInstalledFont get exec pop
+ } {
+ pop
+ } ifelse
+ setglobal
+ } if
+ dup /FontDescriptor //knownget exec { % id obj fd
+ 0 get % id obj id1
+ dup //IsRegistered exec { % id obj id1
+ //PDFR_DEBUG {
+ (already registered ) print dup =
+ } if
+ pop
+ } {
+ //DoNothing exch % id obj dn id1
+ [ % <id> <obj> proc <id> <obj>
+ 3 index //FontDescriptorDaemon /exec load
+ ] cvx % id obj {}
+ //Register exec % id obj
+ } ifelse
+ } if
+ } bind
+>> def
+
+/MakeStreamReader % <obj> MakeStreamReader <file>
+{ dup
+ [
+ exch
+ //PDFR_DEBUG {
+ (Stream proc )
+ /print load
+ //PDFR_STREAM {
+ (<)
+ /print load
+ } if
+ } if
+ 1 dict dup /i -1 put
+ /dup load
+ /i
+ /get load
+ 1
+ /add load
+ /dup load
+ 3
+ 1
+ /roll load
+ /i
+ /exch load
+ /put load
+ //knownget
+ /exec load
+ /not load
+ { () }
+ /if load
+ //PDFR_DEBUG {
+ //PDFR_STREAM {
+ /dup load
+ /print load
+ (>)
+ /print load
+ } if
+ ( end of stream proc.\n)
+ /print load
+ } if
+ ] cvx
+ //PDFR_DEBUG {
+ (Stream reader ) print dup ==
+ } if
+ 0 () /SubFileDecode filter
+ exch //AppendFilters exec
+} bind def
+
+/RunDelayedStream % <stream_obj> RunDelayedStream -
+{
+ % Save InitialTextMatrix, as this is local to each content stream
+ //GraphicState /InitialTextMatrix get
+ //InitialTextMatrixStack //PDFReader /InitialTextMatrixStackPointer get
+ 2 copy get null eq {
+ 2 copy currentglobal true setglobal matrix exch setglobal put
+ } if
+ get copy pop
+ //PDFReader /InitialTextMatrixStackPointer 2 copy get 1 add put
+ % Execute the stream
+ //MakeStreamReader exec % file
+ mark exch
+ cvx exec %
+ counttomark 0 ne {
+ mark (Data left on ostack after a delayed stream execution.) //error exec
+ } if
+ cleartomark
+ % Restore InitialTextMatrix
+ //PDFReader /InitialTextMatrixStackPointer 2 copy get 1 sub put
+ //InitialTextMatrixStack //PDFReader /InitialTextMatrixStackPointer get get
+ //GraphicState /InitialTextMatrix get
+ copy pop
+} bind def
+
+% ===================== Font Management ======================
+
+//ReadFontProcs begin
+ /Type1 % <font_descriptor> <FontFile_object> Type1 <font_descriptor>
+ { //PDFR_DEBUG {
+ (ReadFontProcs.Type1) =
+ } if
+ dup /.endobj_daemon [ 4 index //HookFont /exec load ] cvx put
+ dup /ImmediateExec true put
+ /GlobalExec true put
+ } bind def
+ /MMType1 //Type1 def
+ /TrueType % <font_descriptor> <FontFile_object> TrueType <font_descriptor>
+ { //PDFR_DEBUG {
+ (ReadFontProcs.TrueType) =
+ } if
+ dup /.endobj_daemon [ 4 index //HookFont /exec load ] cvx put
+ pop
+ } bind def
+end
+
+% A working dictionary to hold items related to reading a TrueType font
+% and converting into a type 42 font, especially regarding creating the sfnts
+% array of strings, and ensuring strings are split on table boundaries and
+% for the glyf table, on glyph boundaries.
+%
+/.opdloadttfontdict 50 dict def
+.opdloadttfontdict begin
+
+/maxstring 65400 def % less than the maximum length of a PostScript string,
+ % must be a multiple of 4 (for hmtx / loca / vmtx)
+end
+
+% Uses an insertion sort to sort the contents of an array,
+% the sorted array is returned. Takes the array to sort and a
+% comparison procedure. The comparison procedure must take two
+% arguments, and return a boolean. The return value should be
+% false if arguments incorrectly ordered, true if they are
+% already in the correct order.
+%
+% [Array to sort] {comparisaon proc} InsertionSort [Sorted array]
+%
+/.InsertionSort
+{
+ /CompareProc exch def
+ /Array exch def
+ 1 1 Array length 1 sub
+ {
+ /Ix exch def
+ /Value1 Array Ix get def
+
+ /Jx Ix 1 sub def
+ {
+ Jx 0 lt {
+ exit
+ } if
+ /Value2 Array Jx get def
+ Value1 Value2 CompareProc {
+ exit
+ } if
+
+ Array Jx 1 add Value2 put
+ /Jx Jx 1 sub def
+ } loop
+ Array Jx 1 add Value1 put
+ } for
+ Array
+} bind def
+
+%
+% Utility rourtines to insert a TrueType data type
+%
+% <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
+
+%
+% Utility routines to read TrueType table data, returning
+% either a string or an array of strings depending on the
+% table length.
+%
+
+% 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 maxstring 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
+
+% ReadTTF reads the tables and so on from a TreuType font into memory
+% so that they are available for later processing.
+%
+% <filename> ReadTTF -
+%
+/ReadTTF
+{
+ .opdloadttfontdict begin
+ /TTFontFile exch def
+
+ % Table directory:
+ % version - fixed (4 bytes)
+ % numTables - USHORT (2 bytes)
+ % searchRange - USHORT (2 bytes)
+ % entrySelector - USHORT (2 bytes)
+ % Read Table
+ /TableDir TTFontFile 12 string readstring pop def
+
+ % There are numTables table directory entries:
+ % tag - ULONG (4 bytes)
+ % checkSum - ULONG (4 bytes)
+ % offset - ULONG (4 bytes)
+ % length - ULONG (4 bytes)
+ % Read entries
+ /tables TTFontFile TableDir 4 getu16 16 mul string readstring pop def
+
+ % Create dictionary to store directory entries.
+ /tabarray tables length 16 idiv array def
+
+ % Check version for TrueType collection
+ TableDir 0 4 getinterval (ttcf) eq {
+ QUIET not { (Can't handle TrueType font Collections.) = } if
+ /.loadttfonttables cvx /invalidfont signalerror
+ } {
+ % There are ((length of tables string) / 16) Table directory entries
+ % Get and store each in turn
+ 0 16 tables length 1 sub {
+ % Get each directory entry as a 16-byte string
+ dup % index index
+ tables exch 16 getinterval % index (string)
+ exch 16 div cvi exch % index/16 (string)
+ tabarray 3 1 roll put
+ } for
+ } ifelse
+
+ % We need the tables in the order they occur in the file, so sort
+ % by 'offset'.
+ tabarray { exch 8 getu32 exch 8 getu32 gt} .InsertionSort pop
+
+ % Now we read the content of each table in turn. If the table is < 64K
+ % then we store it in a single string. If its more, we store it in an
+ % array of strings. The table contents are stored in 'tabs' in the same
+ % order as they are read from the file, as per the sorted array 'tabarray'.
+ /Read TableDir length tables length add def
+ /tabs [
+ tabarray {
+ % Get offset (from start of file) of next table
+ dup 8 getu32 % () offset
+ % Subtract amount read so far
+ Read sub % () offset-Read
+ dup 0 gt {
+ % Read and discard any extra padding bytes % () offset-Read
+ dup string TTFontFile exch readstring pop pop % () offset-Read
+ % Update bytes read
+ Read add /Read exch def % ()
+ } {
+ pop % ()
+ } ifelse
+ % Find length of this table and add it to bytes read
+ 12 getu32 % () tablelength
+ dup Read add % () tablelength tablelength+Read
+ /Read exch def % () tablelength
+ TTFontFile exch .readbigtable
+ } forall
+ ] def
+ end % .opdloadttfontdict
+} bind def
+
+% GetLocaType finds the head table in tabarray, which gives
+% an index into the 'tabs' array where the data is stored.
+% From that data we extract the loca type (short or long).
+%
+% - GetLocaType -
+%
+/GetLocaType
+{
+ 0 1 tabarray length 1 sub{
+ % control-variable
+ dup tabarray exch get % control-variable ()
+ 0 4 getinterval (head) eq{ % control-variable bool
+ tabs exch get % ()
+ 50 gets16
+ /LocaType exch def
+ exit
+ } {
+ pop % control variable % -
+ } ifelse
+ } for
+} bind def
+
+% GetNumGlyphs finds the maxp table in tabarray, which gives
+% an index into the 'tabs' array where the data is stored.
+% From that data we extract the number of glyphs in the font.
+%
+% - GetNumGlyphs -
+%
+/GetNumGlyphs
+{
+ 0 1 tabarray length 1 sub{
+ % control-variable
+ dup tabarray exch get % control-variable ()
+ 0 4 getinterval (maxp) eq{ % control-variable bool
+ % Get the maxp string
+ % from the tabs array
+ tabs exch get % ()
+ 4 getu16 % int
+ /NumGlyphs exch def
+ exit % int
+ } {
+ pop % control variable % -
+ } ifelse
+ } for
+} bind def
+
+% StringtoLoca takes a string, and an index in to an array
+% where the loca results should be stored from. It reads
+% along the string getting either 2-byte or 4-byte values
+% (depends on loca type) and stores them in the array at
+% successive locations. Leaves the next unused location
+% on the stack at end (easy to process multiple strings).
+%
+% string ArrayIndex StringToLoca ArrayIndex
+%
+/StringToLoca
+{
+ /LocaIndex exch def % ()
+ /StringOffset 0 def % ()
+ {
+ dup length StringOffset gt { % ()
+ dup % ()
+ LocaType 1 eq{
+ StringOffset getu32 % () loca
+ LocaArray LocaIndex 3 -1 roll put % ()
+ /LocaIndex LocaIndex 1 add def % ()
+ /StringOffset StringOffset 4 add % ()
+ def
+ } {
+ dup % () loca
+ StringOffset getu16 % ()
+ LocaArray LocaIndex 3 -1 roll put % ()
+ /LocaIndex LocaIndex 1 add def % ()
+ /StringOffset StringOffset 4 add % ()
+ def
+ } ifelse
+ }{ % ()
+ pop % -
+ LocaIndex % return index
+ exit
+ }ifelse
+ } loop
+} bind def
+
+% GetSortedLoca reads the loca table, and sorts it by offset
+% this is so that we can walk up the array looking for an approporiate
+% place to split strings. The result is stored in LocArray
+%
+% - GetSortedLoca -
+%
+/GetSortedLoca
+{
+ NumGlyphs 1 add array /LocaArray exch def
+
+ % Get the loca table
+ 0 1 tabarray length 1 sub{
+ % control-variable
+ dup tabarray exch get % control-variable ()
+ 0 4 getinterval (loca) eq{ % control-variable bool
+ % Get the loca string
+ % from the tabs array
+ tabs exch get % ()
+ exit
+ } {
+ pop % control variable % -
+ } ifelse
+ } for
+
+ % If its a single string handle the easy way
+ dup type /stringtype eq {
+ 0 StringToLoca pop
+ }{
+ % Otherwise its an array, process each string in the array
+ 0 exch % Starting LocaArray index
+ {
+ exch StringToLoca
+ }forall
+ pop % final LocaArray index
+ }ifelse
+
+ % Now we've read all the locations, sort them so
+ % we can figure out where to break the strings
+ LocaArray {gt} .InsertionSort pop
+} bind def
+
+% Updates internal storage with a new string from the
+% GlyfArray
+% - GetWorkingString -
+/GetWorkingString
+{
+ WorkString 0
+ GlyfArray GlyfStringIndex get
+ putinterval
+ % Update the available bytes
+ /WorkBytes GlyfArray GlyfStringIndex get length def
+ % Set index to get data from next string in array
+ /GlyfStringIndex GlyfStringIndex 1 add def
+} bind def
+
+% Returns a string with the requested number of bytes taken
+% from WorkingString. There must be enough data in WorkingString to
+% satisfy the request
+%
+/GetWorkingBytes
+{
+ /BytesToRead exch def
+ % Get 'BytesToRead' bytes from working store
+ WorkString 0 BytesToRead getinterval
+ dup length string copy
+ % Get remaining bytes from working store
+ WorkString BytesToRead WorkBytes BytesToRead sub getinterval
+ dup length string copy
+ % replace first 'n' bytes of working store with unread bytes
+ WorkString 0 3 -1 roll putinterval
+ % Subtract bytes read from bytes available
+ /WorkBytes WorkBytes BytesToRead sub def
+} bind def
+
+% Read 'int' bytes from GlyfArray strings, return string composed
+% of those bytes
+%
+% int GetGlyfBytes string
+/GetGlyfBytes
+{
+ /ToRead exch def
+
+ % If we have no available data, get soem from the array of
+ % glyf strings
+ WorkBytes 0 eq {
+ GetWorkingString
+ } if
+
+ WorkBytes ToRead ge {
+ ToRead string dup 0
+ ToRead GetWorkingBytes putinterval
+ }{
+ % Create a string sized to hold the target data
+ ToRead string
+ % Get remaining stored bytes, and put at the start
+ % of the string
+ dup
+ % Start of string
+ 0
+ % Get remaining bytes
+ WorkString 0 WorkBytes getinterval
+ % store at start of output string
+ putinterval
+
+ dup
+ % Location in output to store data from next string
+ WorkBytes
+ % amout of data required to read from next string
+ ToRead WorkBytes sub
+ % Get the next string from the array of strings
+ GetWorkingString
+ % Get a string containing the required data, updating
+ % the internal data storage
+ GetWorkingBytes
+ % put the data at the end of the stored data in the
+ % output string
+ putinterval
+ } ifelse
+} bind def
+
+% Given an array of glyf strings, returns an array of strings
+% split on glyf boundaries
+%
+% [] SplitGlyf []
+%
+/SplitGlyf
+{
+ /GlyfArray exch def
+ /DestArray GlyfArray length 2 mul array def
+ /DestArrayIndex 0 def
+
+ /LastLoca 0 def
+ /NextLocaIndex 0 def
+ /LastLocaIndex 0 def
+
+ /GlyfStringIndex 0 def
+ /WorkString maxstring string def
+ /WorkBytes 0 def
+
+ % Find appropriate next loca
+ {
+ % Get location of next glyph
+ LocaArray NextLocaIndex get % int
+ % subtract location of last point to get
+ % the actual bytes between
+ LastLoca sub maxstring gt % int bool
+ {
+ LocaArray LastLocaIndex get LastLoca sub
+ GetGlyfBytes % ()
+ DestArray DestArrayIndex 3 -1 roll put % -
+ /DestArrayIndex DestArrayIndex 1 add def % -
+ LocaArray LastLocaIndex get /LastLoca exch def % -
+ } { % int
+ /LastLocaIndex NextLocaIndex def % -
+ /NextLocaIndex NextLocaIndex 1 add def % -
+ NextLocaIndex NumGlyphs gt % bool
+ {
+ WorkBytes % int
+ GlyfStringIndex GlyfArray length lt { % int bool
+ GlyfArray GlyfStringIndex get length % int
+ add string dup % (d) (d)
+ 0 % (d) (d) 0
+ WorkString 0 WorkBytes getinterval % (d) (d) (s)
+ putinterval % (d)
+ dup % (d) (d)
+ WorkBytes % (d) (d) int
+ GetWorkingString % (d) (d) int
+ WorkString 0 WorkBytes getinterval % (d) (d) int (s)
+ putinterval % (d)
+ } {
+ pop % -
+ WorkString 0 WorkBytes getinterval % ()
+ } ifelse
+ dup length string copy
+ DestArray DestArrayIndex 3 -1 roll put
+ exit
+ } if
+ } ifelse
+ } loop
+ DestArray
+
+} bind def
+
+% ProcessTTData looks at the data stored in the 'tabs' array and does several things:
+% 1) Make sure strings representing tables are multiples of 4 bytes long
+% 2) For arrays representing tables, make sure the total string length is a multiple
+% of 4 bytes long, to ensure the table is a multiple of 4 bytes.
+% 3) Handle the glyf table specislly, each string in this array must be split on the
+% boundary of a glyf. Use the loca table to determine where the split should happen
+% and build a new array of strings split appropriately.
+%
+% - ProcessTTData -
+%
+/ProcessTTData
+{
+ .opdloadttfontdict begin
+ % Make sure all the strings are a multiple of 4 bytes
+ 0 1 tabarray length 1 sub{
+ /ix exch def
+ tabarray ix get
+ 12 getu32 dup maxstring le {
+ % String < 64Kb, still need to check if its a multiple of 4
+ dup 4 mod 0 ne {
+ 4 div cvi 1 add 4 mul string /newstring exch def
+ /oldstring tabs ix get def
+ newstring 0 oldstring putinterval
+ 0 1 newstring length oldstring length sub 1 sub {
+ newstring exch oldstring length add 0 put
+ } for
+ tabs ix newstring put
+ } {
+ % table size is a multiple of 4, don't need to promote it
+ pop
+ } ifelse
+ }{
+ % table size > 64K, so this is an array of strings, not a string
+ % We still need to make sure that the tables end on 4-byte
+ % boundaries.
+ dup 4 mod 0 ne {
+ % First we need to work out how many strings of size maxstring
+ % are present, and how much they contribute to the overall size.
+ dup maxstring idiv maxstring mul sub
+ % Promote final string length to multiple of 4
+ 4 idiv 1 add 4 mul string /newstring exch def
+ % Get array of strings
+ tabs ix get
+ % find size of table and get last string
+ dup length 1 sub dup /iy exch def get /oldstring exch def
+ newstring 0 oldstring putinterval
+ 0 1 newstring length oldstring length sub 1 sub {
+ newstring exch oldstring length add 0 put
+ } for
+ tabs ix get iy newstring put
+ } {
+ % table size is a multiple of 4, don't need to promote it
+ pop
+ } ifelse
+ } ifelse
+ } for
+
+ % Now, if glyf table > 64Kb, then it will be an array of strings
+ % We need to make sure the strings are split on glyph boundaries
+ 0 1 tabarray length 1 sub { % int
+ dup tabarray exch get % int ()
+ dup 12 getu32 maxstring gt { % int () bool
+ 0 4 getinterval dup (glyf) eq{ % int () bool
+ % Need to split the glyf strings on glyph boundaries, hmmm.
+ pop % int
+ % We need to know the number of glyphs (from the maxp table) and the
+ % position of each glyph (from the loca table).
+ GetLocaType % int
+ GetNumGlyphs % int
+ GetSortedLoca % int
+ % Get the array of strings from tabs
+ dup tabs exch get % int
+ SplitGlyf % int []
+ tabs 3 1 roll put % -
+ } { % int ()
+ (Warning, table ) print print ( > 64Kb\n) print
+ pop % -
+ } ifelse
+ }{ % int ()
+ % Table less than 64K, so don't worry
+ pop % directory entry % int
+ pop % 'for' control variable % -
+ } ifelse
+ } for
+ end % .opdloadttfontdict
+} bind def
+
+% Makesfnts uses the accumulated data to create an array of strings
+% containing only the required data.
+%
+% - Makesfnts array
+%
+/Makesfnts
+{
+ .opdloadttfontdict begin
+ % Determine size of sfnts array
+ % length of tabarray + header
+ 0
+ tabs { % int obj
+ dup type /stringtype eq { % int obj bool
+ pop % int
+ 1 add % int
+ }{ % int obj
+ { % int obj
+ type /stringtype eq { % int bool
+ 1 add % int
+ } if
+ } forall
+ } ifelse
+ } forall
+
+ 1 add % add header and table directory
+ % to determine total # strings
+ % Need to recalculate the lengths of the TT
+ % tables, just in case any have changed. If required we
+ % could also resort the tables here, ideally we should do so
+ % and recalculate checksums, but this should never be necessary
+ % for fonts produced by pdfwrite.
+ /TTOffset
+ TableDir length % initial table offset is header length
+ tabarray length 16 mul add % + (NumTables * 16) bytes
+ def
+
+ 0
+ tabarray { % index ()
+ exch dup 1 add % () index index+1
+ 3 1 roll % index+1 () index
+ dup % index+1 () index index
+ tabs exch get % index+1 () index ()/[]
+ dup type /stringtype eq { % index+1 () index ()/[] bool
+ length % index+1 () index int
+ 2 index exch % index+1 () index () int
+ TTOffset
+ dup 3 1 roll add % add the running total of offsets
+ /TTOffset exch def % update running total of offsets
+ 8 exch putu32 % index+1 () index
+ exch tabarray 3 1 roll % index+1 [] index ()
+ put % index+1
+ } { % index+1 () index ()/[]
+ 0 exch % add all string lengths
+ { % starting from 0
+ dup type /stringtype eq {
+ length add %
+ } {
+ pop
+ } ifelse
+ } forall %
+ 2 index exch % index+1 () index () int
+ TTOffset
+ dup 3 1 roll add % add the running total of offsets
+ /TTOffset exch def % update running total of offsets
+ 8 exch putu32 % index+1 () index
+ exch tabarray 3 1 roll % index+1 [] index ()
+ put % index+1
+ } ifelse
+ } forall
+ pop % index+1
+
+ array % []
+ dup 0 % [] [] 0
+ TableDir length
+ tables length add % [] [] 0 header_length
+ string % [] [] 0 ()
+ dup 0 TableDir putinterval % [] [] 0 ()
+ dup 12 tables putinterval % [] [] 0 ()
+ put % []
+ dup % [] []
+ /ix 1 def
+ tabs { % [] [] obj
+ dup type /stringtype eq { % [] [] obj bool
+ ix exch % [] [] int obj
+ put dup % [] []
+ /ix ix 1 add def % [] []
+ }{
+ {
+ dup type /stringtype eq { % [] [] obj bool
+ ix exch put dup % [] []
+ /ix ix 1 add def %
+ } {
+ pop % [] []
+ } ifelse
+ } forall
+ } ifelse
+ } forall
+ pop % []
+ end %.opdloadttfontdict
+} bind def
+
+/MakeType42 % <FontFile_object> <font_descriptor> MakeType42 <FontFile_object> <font_descriptor> <font>
+{
+ //PDFR_DEBUG {
+ (MakeType42 beg) =
+ } if
+ 10 dict begin
+ /FontName 1 index /FontName get def
+ /FontType 42 def
+ /FontMatrix [1 0 0 1 0 0] def
+ /FontBBox 1 index /FontBBox get def % fo fd
+ dup /FontResource get % fo fd fr
+ dup /Encoding known { % fo fd fr
+ //PDFReader /ObtainEncoding get exec % fo fd fr
+ /Encoding get % fo fd e
+ } {
+ pop null
+ } ifelse
+ /PDFEncoding exch def % fo fd
+ /CharStrings 2 index //PDFReader /MakeTTCharStrings get exec def
+ /sfnts 2 index //MakeStreamReader exec
+ ReadTTF
+ ProcessTTData
+ Makesfnts
+ def
+ /Encoding StandardEncoding def % A stub - will be replaced by font resource.
+ /PaintType 0 def
+ currentdict end
+ //PDFR_DEBUG {
+ (MakeType42 end) =
+ } if
+} bind def
+
+/GetInstalledFont % <name> GetInstalledFont <font>
+{
+ dup //InstalledFonts exch knownget { % n f
+ exch pop % f
+ } { % n
+ dup findfont dup 3 1 roll % f n f
+ //InstalledFonts 3 1 roll put % f
+ } ifelse
+} bind def
+
+/RemoveFontNamePrefix % <name> RemoveFontNamePrefix <name>
+{ //=string cvs true
+ 0 1 5 {
+ 2 index exch get //IsUpper exec not {
+ pop false exit
+ } if
+ } for
+ { (+) search {
+ pop pop
+ } if
+ } if
+ cvn
+} bind def
+
+/CheckFont % <key> <val> CheckFont <key> <val>
+{ dup /Type get /Font ne {
+ mark (Resource ) 3 index ( must have /Type/Font .) //error exec
+ } if
+} bind def
+
+/CheckEncoding % <key> <val> CheckEncoding <key> <val>
+{ dup type /nametype ne {
+ dup /Type get /Encoding ne {
+ mark (Resource ) 3 index ( must have /Type/Encoding .) //error exec
+ } if
+ } if
+} bind def
+
+/ObtainEncoding % <font_resource> ObtainEncoding <font_resource>
+{ dup /Encoding known {
+ dup dup /Encoding //CheckEncoding //ResolveD exec % fr fr er|e|n
+ dup type dup /arraytype eq exch /packedarraytype eq or {
+ % Already resolved.
+ pop pop
+ } {
+ dup type /nametype eq {
+ /Encoding findresource % fr fr e
+ } {
+ dup /BaseEncoding //knownget exec not {
+ /StandardEncoding
+ } if
+ /Encoding findresource % fr fr er e
+ exch % fr fr e er
+ /Differences //knownget exec { % fr fr e d
+ exch dup length array copy exch
+ 0 exch % fr fr e 0 d
+ { % fr fr e i v
+ dup type /integertype eq {
+ exch pop
+ } {
+ 3 copy put pop % fr fr e i
+ 1 add
+ } ifelse
+ } forall
+ pop % fr fr e
+ } if % fr fr e
+ } ifelse % fr fr e
+ /Encoding exch put % fr
+ } ifelse
+ } {
+ dup /Encoding /StandardEncoding /Encoding findresource put
+ } ifelse
+} bind def
+
+/ObtainMetrics % <font_resource> ObtainMetrics <font_resource>
+{ dup /Widths //knownget exec { % fr W
+ 1 index /Encoding get % fr W E
+ 256 dict % fr W E M
+ 3 index /Subtype get /TrueType eq {
+ 1000
+ } {
+ 1
+ } ifelse % fr W E M s
+ 4 index /MissingWidth //knownget exec not {
+ 0
+ } if % fr W E M s mw
+ 5 index /FirstChar //knownget exec not {
+ 0
+ } if % fr W E M s mw c0
+ 6 5 roll % fr E M s mw c0 W
+ dup 0 exch 1 exch length 1 sub { % fr E M s mw c0 W i
+ 2 copy get % fr E M s mw c0 W i w
+ exch 3 index add % fr E M s mw c0 W w c
+ 7 index exch get % fr E M s mw c0 W w n
+ dup null ne {
+ 6 index 3 1 roll exch % fr E M s mw c0 W M n w
+ 6 index div
+ 3 copy pop //knownget exec {
+ 0 eq
+ } {
+ true
+ } ifelse
+ { put % fr E M s mw c0 W
+ } {
+ pop pop pop
+ } ifelse
+ } {
+ pop pop
+ } ifelse
+ } for
+ pop pop pop pop exch pop % fr M
+ 1 index exch /Metrics exch put % fr
+ } {
+ dup /MissingWidth //knownget exec { % fr mw
+ 256 dict % fr mw M
+ 2 index /Encoding get { % fr mw M e
+ dup null ne {
+ 3 copy 3 2 roll put % fr mw M e
+ } if
+ pop % fr mw M
+ } forall
+ exch pop % fr M
+ 1 index exch /Metrics exch put % fr
+ } if
+ } ifelse
+} bind def
+
+/NotDef % - NotDef -
+{ % A Type 3 font is on dstack.
+ FontMatrix aload pop pop pop exch pop exch pop % sx sy
+ 1 exch div exch
+ 1 exch div exch % wx wy
+ 1 index 0 setcharwidth
+ 0 setlinewidth
+ 0 0 moveto
+ 2 copy rlineto
+ 1 index 0 rlineto
+ neg exch neg exch rlineto %
+ closepath stroke
+} bind def
+
+/BuildChar % <font> <char_code> BuildChar -
+{ //PDFR_DEBUG {
+ (BuildChar ) print dup //=only exec ( ) print
+ } if
+ exch begin
+ Encoding exch get % n
+ //PDFR_DEBUG {
+ dup =
+ } if
+ dup null eq {
+ pop //NotDef exec %
+ } { % n
+ CharProcs exch //knownget exec { % cp_stream
+ //RunDelayedStream exec
+ } {
+ //NotDef exec
+ } ifelse
+ } ifelse %
+ end % font
+} bind def
+
+/printdict % <dict> printdict -
+{ (<<) =
+ { exch = == } forall
+ (>>) =
+} bind def
+
+/printfont % <dict> printfont -
+{
+ dup {
+ exch dup =
+ dup /Encoding eq {
+ pop =
+ } {
+ dup /FontInfo eq exch /Private eq or {
+ //printdict exec
+ } {
+ ==
+ } ifelse
+ } ifelse
+ } forall
+} bind def
+
+/ScaleMetrics % <Metrics> <scale> ScaleMetrics <Metrics>
+{ 1 index { % M s n v
+ 2 index div % M s n v'
+ 3 index % M s n v' M
+ 3 1 roll put % M s
+ } forall
+ pop
+} bind def
+
+/ResolveAndSetFontAux % <resource_name> <size> ResolveAndSetFont -
+{ exch dup % s rn rn
+ //PDFReader /CurrentObject get /Context get /Resources get
+ /Font //DoNothing //ResolveD exec
+ exch //CheckFont //ResolveD exec % s rn fr
+ dup /Font //knownget exec { % s rn fr f
+ exch pop exch pop
+ } {
+ {
+ dup /Subtype get dup dup /Type1 eq exch /TrueType eq or exch /MMType1 eq or {
+ % s rn fr
+ exch pop % s fr
+ dup /BaseFont get % s fr n
+ //RemoveFontNamePrefix exec % s fr n
+ //PDFR_DEBUG {
+ (Font ) print dup =
+ } if % s fr n
+ 1 index /FontDescriptor known { % s fr n
+ //PDFR_DEBUG {
+ (Font from a font descriptor.) =
+ } if
+ 1 index % s fr n fr
+ /FontDescriptor //DoNothing //ResolveD exec % s fr n fd
+ /Font //knownget exec {
+ exch pop % s fr fd
+ } {
+ //PDFR_DEBUG {
+ (Font descriptor has no Font resolved.) =
+ } if
+ //GetInstalledFont exec % s fr f
+ } ifelse
+ } {
+ //GetInstalledFont exec % s fr f
+ } ifelse
+ exch % s f fr
+ dup /Encoding known not {
+ 1 index /Encoding get 1 index exch /Encoding exch put
+ } if
+ //ObtainEncoding exec
+ //ObtainMetrics exec
+ exch
+ dup length dict copy % s fr f
+ dup 2 index /Encoding get % s fr f f e
+ /Encoding exch put % s fr f
+ 1 index /Metrics //knownget exec { % s fr f M
+ 2 index /Subtype get /TrueType ne {
+ 1 index /FontMatrix get 0 get
+ dup 0 eq {
+ % FontMatrix[0] == 0, so cannot downscale by it
+ % HACK: downscale by FontMatrix[1], and will get the target value of wx as wy
+ pop
+ 1 index /FontMatrix get 1 get
+ dup 0 eq { pop 1 } if % sorry, FontMatrix is singular so cannot enforce the PDF metrics
+ } if
+ 0.001 div
+ //ScaleMetrics exec
+ }{
+ % Check if we got a /sfnts key in the dict
+ % If we did then we are probably OK (TT font from GS)
+ 1 index /sfnts known not {
+ % otherwise we need to check the FontMatrix
+ 1 index /FontMatrix get 0 get
+ dup 0 eq {
+ % FontMatrix[0] == 0, so cannot downscale by it
+ % HACK: downscale by FontMatrix[1], and will get the target value of wx as wy
+ pop
+ 1 index /FontMatrix get 1 get
+ dup 0 eq { pop 1 } if % sorry, FontMatrix is singular so cannot enforce the PDF metrics
+ } if
+ //ScaleMetrics exec
+ } if
+ } ifelse
+ 1 index exch /Metrics exch put % s fr f
+ } if
+ 1 index /BaseFont get % s fr f n
+ exch
+ dup /FID undef
+ dup /UniqueID undef
+ definefont % s fr f
+ dup 3 1 roll % s f fr f
+ /Font exch put % s f
+ exit
+ } if
+ dup /Subtype get /Type3 eq { % s rn fr
+ //ObtainEncoding exec
+ 2 copy exch /FontName exch put
+ dup /CharProcs get //ResolveDict exec
+ dup /FontType 3 put
+ dup /BuildChar //BuildChar put
+ dup dup /Font exch put
+ % Ignore Metrics because pdfwrite duplicates it
+ % from setcharwidth/setcachedevice.
+ dup 3 1 roll % s fr rn fr
+ definefont % s fr f
+ 2 copy ne {
+ % The interpreter copied the font dictionary while 'definefont'
+ % Need to update the font pointer in the resource.
+ 2 copy /Font exch put % s fr f
+ } if
+ exch pop % s f
+ exit
+ } if
+ dup /Subtype get /Type0 eq { % s rn fr
+ } if
+ dup /Subtype get /CIDFontType0 eq { % s rn fr
+ } if
+ dup /Subtype get /CIDFontType2 eq { % s rn fr
+ } if
+ mark (Unknown font type ) 2 index /Subtype get //error exec
+ } loop
+ } ifelse % s f
+ exch scalefont setfont %
+} bind def
+
+/ResolveAndSetFont % <resource_name> <size> ResolveAndSetFont -
+{
+ //ResolveAndSetFontAux exec
+} bind def
+
+%%beg TrueType
+% ================= Auxiliary procedures for True Type cmap Decoder =============
+
+/.knownget
+{ 2 copy known {
+ get true
+ } {
+ pop pop false
+ } ifelse
+} bind def
+
+/.min
+{ 2 copy lt {
+ exch
+ } if
+ pop
+} bind def
+
+/.max
+{ 2 copy gt {
+ exch
+ } if
+ pop
+} bind def
+
+/.dicttomark
+{ >>
+} bind def
+
+% ===================== True Type cmap Decoder =============
+% The following procedures are copied from gs/lib/gs_ttf.ps with no change.
+
+% <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
+
+% Each procedure in this dictionary is called as follows:
+% <encodingtable> proc <glypharray>
+/cmapformats mark
+ 0 { % Apple standard 1-to-1 mapping.
+ 6 256 getinterval { } forall 256 packedarray
+ } 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 getu16 /cmapf2_tblen exch def
+
+ dup 4 getu16 /cmapf2_lang exch def
+
+ dup 6 256 sHK_sz mul getinterval /sHKs exch def
+
+ 0 % initialization value for /sH_len
+ 0 1 255 {
+ sHKs exch
+ 2 mul getu16
+ 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
+ /sH_gIA exch def
+
+ /cmapf2_glyph_array 65535 array 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 getu16
+ 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 getu16
+ /sH_offset exch def
+ sH_gIA sH_offset sH_sz getinterval
+ dup 0 getu16 /firstCode exch def
+ dup 2 getu16 /entryCount exch def
+ dup 4 gets16 /idDelta exch def
+ dup 6 getu16 /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
+ 0 1 cmapf2_glyph_array length 1 sub { % rewrite null -> 0.
+ dup cmapf2_glyph_array exch get
+ null eq { cmapf2_glyph_array exch 0 put } {pop} ifelse
+ } for
+ cmapf2_glyph_array
+ } bind
+ 4 { % Microsoft/Adobe segmented mapping.
+ /etab exch def
+ /nseg2 etab 6 getu16 def
+ 14 /endc etab 2 index nseg2 getinterval 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 def
+ nseg2 add /iddelta etab 2 index nseg2 getinterval def
+ nseg2 add /idroff etab 2 index nseg2 getinterval def
+ % The following hack allows us to properly handle
+ % idiosyncratic fonts that start at 0xf000:
+ pop
+ /firstcode startc 0 getu16 16#ff00 and dup 16#f000 ne { pop 0 } if def
+ /putglyph {
+ glyphs code 3 -1 roll put /code code 1 add def
+ } bind def
+ % Do a first pass to compute the size of the glyphs array.
+ /numcodes 0 def /glyphs 0 0 2 nseg2 3 sub {
+ % Stack: /glyphs numglyphs i2
+ /i2 exch def
+ /scode startc i2 getu16 def
+ /ecode endc i2 getu16 def
+ numcodes scode firstcode sub
+ % Hack for fonts that have only 0x0000 and 0xf000 ranges
+ %dup 16#e000 ge { 255 and } if
+ % the previous line is obstructive to CJK fonts, so it was removed
+ exch sub 0 .max ecode scode sub 1 add add
+ exch 1 index add exch
+ numcodes add /numcodes exch def
+ } for array def
+ % prefill the array with 0's faster than a { 0 putglyph } repeat
+ glyphs length 1024 ge {
+ .array1024z 0 1024 glyphs length 1023 sub { glyphs exch 2 index putinterval } for
+ glyphs dup length 1024 sub 3 -1 roll
+ putinterval
+ } {
+ 0 1 glyphs length 1 sub { glyphs exch 0 put } for
+ } ifelse
+ % Now fill in the array.
+ /numcodes 0 def /code 0 def
+ 0 2 nseg2 3 sub {
+ /i2 exch def
+ /scode startc i2 getu16 def
+ /ecode endc i2 getu16 def
+ numcodes scode firstcode sub
+ % Hack for fonts that have only 0x0000 and 0xf000 ranges
+ %dup 16#e000 ge { 255 and } if
+ % the previous line is obstructive to CJK fonts, so it was removed
+ exch sub 0 .max dup /code exch code exch add def
+ ecode scode sub 1 add add numcodes add /numcodes exch def
+ /delta iddelta i2 gets16 def
+ TTFDEBUG {
+ (scode=) print scode =only
+ ( ecode=) print ecode =only
+ ( delta=) print delta =only
+ ( droff=) print idroff i2 getu16 =
+ } if
+ idroff i2 getu16 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 getu16
+ dup 0 ne { delta add 65535 and } if putglyph
+ } for
+ } ifelse
+ } for glyphs /glyphs null def % for GC
+ } bind
+ 6 { % Single interval lookup.
+ dup 6 getu16 /firstcode exch def dup 8 getu16 /ng exch def
+ firstcode ng add array
+ % Stack: tab array
+ % Fill elements 0 .. firstcode-1 with 0
+ 0 1 firstcode 1 sub { 2 copy 0 put pop } for
+ dup firstcode ng getinterval
+ % Stack: tab array subarray
+ % Fill elements firstcode .. firstcode+nvalue-1 with glyph values
+ 0 1 ng 1 sub {
+ dup 2 mul 10 add 4 index exch getu16 3 copy put pop pop
+ } for pop exch pop
+ } bind
+.dicttomark readonly def % cmapformats
+
+% <cmaptab> cmaparray <glypharray>
+/cmaparray {
+ dup 0 getu16 cmapformats exch .knownget {
+ TTFDEBUG {
+ (cmap: format ) print 1 index 0 getu16 = flush
+ } if exec
+ } {
+ (Can't handle format ) print 0 getu16 = flush
+ 0 1 255 { } for 256 packedarray
+ } ifelse
+ TTFDEBUG {
+ (cmap: length=) print dup length = dup ==
+ } if
+} bind def
+
+% Define remapping for misnamed glyphs in TrueType 'post' tables.
+% There are probably a lot more than this!
+/postremap mark
+ /Cdot /Cdotaccent
+ /Edot /Edotaccent
+ /Eoverdot /Edotaccent
+ /Gdot /Gdotaccent
+ /Ldot /Ldotaccent
+ /Zdot /Zdotaccent
+ /cdot /cdotaccent
+ /edot /edotaccent
+ /eoverdot /edotaccent
+ /gdot /gdotaccent
+ /ldot /ldotaccent
+ /zdot /zdotaccent
+.dicttomark readonly 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
+ } {
+ 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
+ } 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
+ /glyphnames numglyphs 2 mul 34 add def
+ % Build names array in the order they occur in the 'post' table
+ /postpos glyphnames def
+ /total_length postglyphs //string_array_size exec def
+ numglyphs array 0 1 numglyphs 1 sub {
+ postpos total_length ge {
+ % Fill the rest with .notdef
+ 1 numglyphs 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 //getinterval_from_stringarray exec cvn
+ exch postpos add 1 add /postpos exch def
+ 2 index 3 1 roll
+ put
+ } for
+ /postnames exch def
+ numglyphs array 0 1 numglyphs 1 sub {
+ dup 2 mul 34 add postglyphs exch 2 //getinterval_from_stringarray exec
+ dup 0 get 8 bitshift exch 1 get add dup 258 lt {
+ MacGlyphEncoding exch get
+ } {
+ dup 32768 ge {
+ % According to the published TrueType spec, such values are
+ % "reserved for future use", but at least some PDF files
+ % produced by the Adobe PDF library contain entries with a
+ % value of 16#ffff.
+ pop /.notdef
+ } {
+ % Get the name for this glyph
+ 258 sub dup postnames length ge {
+ TTFDEBUG { ( *** warning: glyph index past end of 'post' table) = flush } if
+ pop
+ exit
+ } if
+ 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
+ } ifelse
+ 2 index 3 1 roll put
+ } for
+
+ }
+ ifelse
+ } bind
+ 16#00030000 { % No map.
+ pop [ ]
+ } bind
+.dicttomark readonly def % postformats
+
+/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 def
+} bind def
+
+% ===================== True Type Interpretation =============
+
+/TTParser <<
+ /Pos 0
+ /post null
+>> def
+
+/readu8 % <file> readu8 <int>
+{ read not {
+ mark (Insufficient data in the stream.) //error exec
+ } if
+} bind def
+
+/readu16 % <file> readu16 <int>
+{ dup //readu8 exec 8 bitshift exch //readu8 exec or
+} bind def
+
+/reads16 % <file> reads16 <int>
+{ //readu16 exec 16#8000 xor 16#8000 sub
+} bind def
+
+/readu32 % <file> readu32 <int>
+{ dup //readu16 exec 16 bitshift exch //readu16 exec or
+} bind def
+
+/reads32 % <file> reads32 <int>
+{ dup //reads16 exec 16 bitshift exch //readu16 exec or
+} bind def
+
+/SkipToPosition % <file> <int> SkipToPosition -
+{ dup //TTParser /Pos get % f P P p
+ exch //TTParser exch /Pos exch put % f P p
+ sub % f P-p
+ //PDFR_DEBUG {
+ (Skipping ) print dup //=only exec ( bytes.) =
+ } if
+ dup 0 eq {
+ pop pop
+ } {
+ dup 3 1 roll % P-p f P-p
+ () /SubFileDecode filter % P-p f'
+ exch % f' P-p
+ { 1 index //BlockBuffer readstring pop length
+ dup 0 eq { pop exch pop exit } if
+ sub
+ } loop
+ 0 ne {
+ mark (Insufficient data in the stream for SkipToPosition.) //error exec
+ } if
+ } ifelse
+} bind def
+
+/TagBuffer 4 string def
+
+/ParseTTTableDirectory % <file> ParseTTTableDirectory <dict>
+{ //PDFR_DEBUG {
+ (ParseTTTableDirectory beg) =
+ } if
+ 15 dict begin
+ dup //readu32 exec 16#00010000 ne {
+ mark (Unknown True Type version.) //error exec
+ } if
+ dup //readu16 exec /NumTables exch def
+ dup //readu16 exec /SearchRange exch def
+ dup //readu16 exec /EntrySelector exch def
+ dup //readu16 exec /RangeShift exch def
+ //PDFR_DEBUG {
+ (NumTables = ) print NumTables =
+ } if
+ NumTables {
+ dup //TagBuffer readstring not {
+ mark (Could not read TT tag.) //error exec
+ } if
+ cvn
+ [ 2 index //readu32 exec pop % CheckSum
+ 2 index //readu32 exec % Offset
+ 3 index //readu32 exec % Length
+ ]
+ //PDFR_DEBUG {
+ 2 copy exch //=only exec ( ) print ==
+ } if
+ def
+ } repeat
+ pop % file
+ //TTParser /Pos 12 NumTables 16 mul add put
+ currentdict end
+ //PDFR_DEBUG {
+ (ParseTTTableDirectory end) =
+ } if
+} bind def
+
+/ParseTTcmap % <file> <TableDirectory> ParseTTcmap <dict>
+{ //PDFR_DEBUG {
+ (ParseTTcmap beg) =
+ } if
+ /cmap get aload pop % f o L
+ 3 1 roll % L f o
+ 7 dict begin
+ //PDFR_DEBUG {
+ (Current position = ) print //TTParser /Pos get =
+ (cmap position = ) print dup =
+ } if
+ 1 index exch //SkipToPosition exec % L f
+ //TTParser /Pos get /TablePos exch def
+ dup //readu16 exec pop % version
+ dup //readu16 exec /NumEncodings exch def
+ //PDFR_DEBUG {
+ (NumEncodings = ) print NumEncodings =
+ } if
+ null % L f null
+ NumEncodings {
+ 1 index //readu32 exec % platformID, specificID % L f null id
+ 2 index //readu32 exec % offset % L f null id o
+ 3 array dup 3 2 roll 0 exch put % L f []|null id []
+ 2 index null ne {
+ dup 0 get 3 index 0 get sub % L f []|null id [] l
+ 3 index exch 1 exch put % L f []|null id []
+ } if
+ dup 4 3 roll pop 3 1 roll % L f [] id []
+ def
+ } repeat % L f []
+ dup 0 get % L f [] o
+ 4 3 roll exch sub % f [] L-o
+ 1 exch put % f
+ //PDFR_DEBUG {
+ currentdict {
+ exch dup type /integertype eq {
+ //PrintHex exec ( ) print ==
+ } {
+ pop pop
+ } ifelse
+ } forall
+ } if
+ 4 NumEncodings 8 mul add /HeaderLength exch def
+ //TTParser /Pos //TTParser /Pos get HeaderLength add put
+ 0 % f o
+ NumEncodings {
+ 16#7FFFFFF null % f o om null|[]
+ % Choosing a table with minimal offset greater than 'o' :
+ currentdict {
+ 1 index type /integertype eq { % f o om null|[] id []
+ exch pop dup 0 get % f o om null|[] [] oi
+ dup 5 index gt {
+ dup 4 index lt {
+ 4 1 roll % f o oi om null|[] []
+ exch pop exch pop % f o oi []
+ } {
+ pop pop
+ } ifelse
+ } {
+ pop pop
+ } ifelse % f o oi []
+ } {
+ pop pop
+ } ifelse
+ } forall % f o om' []
+ //PDFR_DEBUG {
+ (Obtaining subtable for ) print dup ==
+ } if
+ 3 2 roll pop % f o' []
+ 3 copy pop % f o' [] f o'
+ TablePos add //SkipToPosition exec % f o' []
+ 3 copy exch pop 1 get % f o' [] l
+ //TTParser /Pos //TTParser /Pos get 3 index add put
+ string % f o' [] f ()
+ readstring not {
+ mark (Can't read a cmap subtable.) //error exec
+ } if % f o' [] ()
+ 2 exch put % f o'
+ } repeat
+ pop pop %
+ currentdict end
+ //PDFR_DEBUG {
+ (ParseTTcmap end) =
+ } if
+} bind def
+
+/GetTTEncoding % <file> <TTcmapHeader> <platformIDspecificID> GetTTEncoding <array>
+{ //PDFR_DEBUG {
+ (GetTTEncoding beg) =
+ } if
+ get % f []
+ exch pop % []
+ 2 get
+ 10 dict begin % For local variables.
+ /TTFDEBUG //PDFR_DEBUG def
+ //cmaparray exec
+ end
+ //PDFR_DEBUG {
+ (GetTTEncoding end) =
+ dup ==
+ } if
+} bind def
+
+/InverseEncoding % <encoding> InverseEncoding <dict>
+{
+ 256 dict begin
+ dup length 1 sub -1 0 { % E i
+ 2 copy get % E i n
+ exch % E n i
+ 1 index currentdict exch //knownget exec { % E n i e
+ dup type /arraytype eq {
+ aload length 1 add array astore % E n e'
+ } {
+ 2 array astore % E n e'
+ } ifelse
+ } if
+ def
+ } for
+ pop
+ currentdict end
+} bind def
+
+/GetMacRomanEncodingInverse
+{ //PDFReader /MacRomanEncodingInverse get
+ dup null eq {
+ pop
+ MacRomanEncoding //InverseEncoding exec
+ dup //PDFReader exch /MacRomanEncodingInverse exch put
+ } if
+} bind def
+
+/PutCharStringSingle % <cmap_array> <glyph_name> <char_code> PutCharStringSingle <cmap_array>
+{
+ dup 3 index length lt { % cmap name code
+ 2 index exch get % cmap name glyphindex
+ dup 0 ne {
+ def % cmap
+ } {
+ pop pop
+ } ifelse
+ } {
+ pop pop % cmap
+ } ifelse
+} bind def
+
+/PutCharString % <cmap_array> <glyph_name> <char_code> PutCharString <cmap_array>
+{ 1 index type /nametype ne {
+ mark (Bad charstring name) //error exec
+ } if
+ dup type /arraytype eq {
+ { % cmap name code
+ 3 copy //PutCharStringSingle exec % cmap name code cmap
+ pop pop % cmap name
+ } forall
+ pop % cmap
+ } {
+ //PutCharStringSingle exec
+ } ifelse
+} bind def
+
+/ComposeCharStrings % <cmaparray> <dict> ComposeCharStrings <dict>
+{
+ //PDFR_DEBUG {
+ (ComposeCharStrings beg) =
+ } if
+ 1 index length 1 add dict begin % cmap d
+ % fixme : the dict length estimation doesn't account 'post'.
+ /.notdef 0 def
+ exch % d cmap
+ //TTParser /post get % d cmap [post]|null
+ dup null ne {
+ exch % d [] cmap
+ 1 index length 1 sub -1 0 { % d [] cmap code
+ dup 3 index exch get exch % d [] cmap name code
+ dup 0 eq 2 index /.notdef eq or { % do not re-encode GID 0, or the
+ % /.notdef glyph name
+ pop pop
+ } {
+ def
+ } ifelse
+ } for
+ } if
+ exch pop exch % cmap d
+ { % cmap name code
+ //PutCharString exec
+ } forall % cmap
+ pop %
+ currentdict end
+ //PDFR_DEBUG {
+ (ComposeCharStrings end) =
+ } if
+} bind def
+
+/ParseTTpost % <file> <TableDirectory> ParseTTpost -
+{ % Defines TTparser.post - an array,
+ % which maps glyph indices to glyph names.
+ //PDFR_DEBUG {
+ (ParseTTpost beg) =
+ } if
+ /post get aload pop % f o L
+ 3 1 roll % L f o
+ //PDFR_DEBUG {
+ (Current position = ) print //TTParser /Pos get =
+ (post position = ) print dup =
+ } if
+ 1 index exch //SkipToPosition exec % L f
+ //TTParser /Pos //TTParser /Pos get 4 index add put
+ exch dup 65535 le {
+ string % f s
+ readstring not {
+ mark (Insufficient data in the stream for ParseTTpost.) //error exec
+ } if % s
+ } {
+ % f s
+ [ 3 1 roll % [ f s
+ dup 16384 div floor cvi % [ f s numblocks
+ exch 1 index 16384 mul % [ f numblocks s bytesinblocks
+ sub exch % [ f remainder numblocks
+ 1 sub 0 1 3 -1 roll % [ f remainder 0 1 numblocks
+ {
+ 1 add index % [ f remainder () ()... f
+ 16384 string readstring not {
+ mark (Insufficient data in the stream for ParseTTpost.) //error exec
+ } if
+ } for
+ % [ f remainder () ()...
+ counttomark -2 roll % [ () ()... f remainder
+ string readstring not{
+ mark (Insufficient data in the stream for ParseTTpost.) //error exec
+ } if
+ ]
+ } ifelse
+ 1 dict begin % A bridge to the code from /gs/lib/gs_ttf.ps .
+ /post exch def
+ //.getpost exec
+ //TTParser /post glyphencoding put
+ //PDFR_DEBUG {
+ (ParseTTpost end) =
+ glyphencoding ==
+ } if
+ end
+} bind def
+
+/MakeTTCharStrings % <FontFile_object> MakeTTCharStrings <CharStrings>
+{ //MakeStreamReader exec % f
+ dup dup //ParseTTTableDirectory exec % f f d
+ % Since the file isn't positionable,
+ % we must pick up either 'post' or 'cmap' first.
+ % Deside which one we do first :
+ //TTParser /post null put
+ dup /post //knownget exec {
+ 0 get
+ 1 index /cmap get 0 get
+ lt {
+ 2 copy //ParseTTpost exec % f f d
+ //ParseTTcmap exec % f ch
+ } {
+ 2 copy //ParseTTcmap exec % f f d ch
+ 3 1 roll % f ch f d
+ //ParseTTpost exec % f ch
+ } ifelse
+ } {
+ //ParseTTcmap exec % f ch
+ } ifelse
+ {
+ dup 16#00030001 known {
+ //PDFR_DEBUG {
+ (Using the TT cmap encoding for Windows Unicode.) =
+ } if
+ 16#00030001 //GetTTEncoding exec
+ AdobeGlyphList //ComposeCharStrings exec
+ exit
+ } if
+ dup 16#00010000 known {
+ //PDFR_DEBUG {
+ (Using the TT cmap encoding for Macintosh Roman.) =
+ } if
+ 16#00010000 //GetTTEncoding exec
+ PDFEncoding dup null eq {
+ pop //GetMacRomanEncodingInverse exec
+ } {
+ //InverseEncoding exec
+ } ifelse
+ //ComposeCharStrings exec
+ exit
+ } if
+ dup 16#00030000 known {
+ //PDFR_DEBUG {
+ (Using the TT cmap encoding 3.0 - not sure why Ghostscript writes it since old versions.) =
+ } if
+ % Same algorithm as for 16#00010000.
+ 16#00030000 //GetTTEncoding exec
+ PDFEncoding dup null eq {
+ pop //GetMacRomanEncodingInverse exec
+ } {
+ //InverseEncoding exec
+ } ifelse
+ //ComposeCharStrings exec
+ exit
+ } if
+ mark (True Type cmap has no useful encodings.) //error exec
+ } loop
+ //PDFR_DEBUG {
+ (CharStrings <<) =
+ dup {
+ exch
+ dup type /nametype eq {
+ //=only exec
+ } {
+ ==
+ } ifelse
+ ( ) print ==
+ } forall
+ (>>) =
+ } if
+} bind def
+
+%%end TrueType
+
+% ===================== Functions ============================
+
+/ScaleVal % <value> <Range> ScaleVal <scaled_value>
+{
+ aload pop % v r0 r1
+ 1 index sub % v r0 r1-r0
+ 3 2 roll mul add
+} bind def
+
+/ScaleArg % <arg> <Domain> ScaleArg <scaled_arg>
+{
+ aload pop % a d0 d1
+ 1 index sub % a d0 d1-d0
+ 3 1 roll % d1-d0 a d0
+ sub exch div % (a-d0)/(d1-d0)
+} bind def
+
+/ScaleArgN % <arg1> ... <argN> <Domain> ScaleArg <scaled_arg1> ... <scaled_argN>
+{
+ dup length 2 sub -2 0 { % a1 ... an [] 2i
+ 2 % a1 ... an [] 2i 2
+ 2 index 3 1 roll getinterval % a1 ... an [] []
+ 3 2 roll % a1 ... [] [] an
+ exch //ScaleArg exec % a1 ... [] an'
+ 1 index length 2 idiv 1 add 1 roll % an' a1 ... []
+ } for % a1' ... an' []
+ pop % a1' ... an'
+} bind def
+
+
+/ComputeFunction_10 % <scaled_arg> <sample_array> ComputeFunction_10 <result>
+{ % Assuming a 1-argument 1-result function type 0.
+ //PDFR_DEBUG {
+ (ComputeFunction_10 beg ) print 1 index //=only exec ( stack=) print count =
+ } if
+ exch % [] x
+ dup 1 eq {
+ pop dup length 1 sub get % y
+ } {
+ 1 index length 1 sub mul % [] x*(l-1)
+ dup dup floor sub % [] x*(l-1) f
+ dup 0 eq {
+ pop cvi get % y
+ } {
+ 3 1 roll floor cvi % f [] i
+ 2 getinterval % f []
+ aload pop % f y0 y1
+ 2 index mul 3 2 roll 1 exch sub 3 2 roll mul add % y1*f+(1-f)*y0
+ } ifelse
+ } ifelse
+ //PDFR_DEBUG {
+ (ComputeFunction_10 end ) print dup //=only exec ( stack=) print count =
+ } if
+} bind def
+
+/ComputeFunction_n0 % <arg1> .... <argn> <sample_array> <n> ComputeFunction_n0 <result>
+{ % Assuming a n-argument 1-result function type 0.
+ //PDFR_DEBUG {
+ (ComputeFunction_n0 beg N=) print dup //=only exec ( stack=) print count =
+ } if
+ dup 0 eq { % v 0
+ pop % v
+ } {
+ dup 2 add -1 roll % a2 .... an [] n a1
+ dup 3 index length 1 sub ge {
+ pop 1 sub % a2 .... an [] n-1
+ exch dup length 1 sub get exch
+ //PDFReader /ComputeFunction_n0 get exec
+ } {
+ dup floor cvi dup % a2 .... an [] n a1 i i
+ 4 index exch get % a2 .... an [] n a1 i [i]
+ 3 index dup % a2 .... an [] n a1 i [i] n n
+ 5 add copy % a2 .... an [] n a1 i [i] n a2 .... an [] n a1 i [i] n
+ 6 2 roll % a2 .... an [] n a1 i [i] n a2 .... an [i] n [] n a1 i
+ pop pop pop pop % a2 .... an [] n a1 i [i] n a2 .... an [i] n
+ 1 sub % a2 .... an [] n a1 i [i] n a2 .... an [i] n-1
+ //PDFReader /ComputeFunction_n0 get exec % a2 .... an [] n a1 i [i] n v0
+ 3 2 roll pop % a2 .... an [] n a1 i n v0
+ exch % a2 .... an [] n a1 i v0 n
+ 4 3 roll exch % a2 .... an [] n i v0 a1 n
+ 4 add 2 roll 1 add % v0 a1 a2 .... an [] n i+1
+ 3 2 roll exch get % v0 a1 a2 .... an n [i+1]
+ exch 1 sub % v0 a1 a2 .... an [i+1] n-1
+ //PDFReader /ComputeFunction_n0 get exec % v0 a1 v1
+ 1 index mul % v0 a1 v1*a1
+ 3 1 roll % v1*a1 v0 a1
+ 1 exch sub mul add % v1*a1+v0*(1-a1)
+ } ifelse
+ } ifelse
+ //PDFR_DEBUG {
+ (ComputeFunction_n0 end ) print dup //=only exec ( stack=) print count =
+ } if
+} bind def
+
+/FunctionToProc_x01 % <function_dict> FunctionToProc_x01 <proc>
+{ % Assuming a n-argument 1-result function type 0.
+ % The stream is already converted to the array /Data.
+ dup /Domain get exch
+ dup /Data get 0 get exch
+ /Size get length
+ [ 4 1 roll
+ //PDFR_DEBUG {
+ { (function beg, stack =) print count //=only exec (\n) print } /exec load
+ 5 2 roll
+ } if
+ dup 1 gt { % a1 ... an Domain Data n
+ { mark exch % a1 ... an Domain Data [ n
+ 3 add 2 roll % Data [ a1 ... an Domain
+ //ScaleArgN exec % Data [ a1 ... an
+ counttomark dup % Data [ a1 ... an n n
+ 3 add -2 roll % a1 ... an n Data [
+ pop exch % a1 ... an Data n
+ //ComputeFunction_n0 exec
+ } /exec load
+ } {
+ pop % a1 Domain Data
+ 3 1 /roll load //ScaleArg /exec load % Data a1s
+ /exch load
+ //ComputeFunction_10 /exec load
+ } ifelse
+ //PDFR_DEBUG {
+ (function end, stack =) /print load /count load //=only /exec load (\n) /print load
+ } if
+ ] cvx
+ //PDFR_DEBUG {
+ (Made a procedure for the 1-result function :) =
+ dup ==
+ } if
+} bind def
+
+/FunctionProcDebugBeg % - FunctionProcDebugBeg -
+{ (FunctionProcDebugBeg ) print count =
+} bind def
+
+/FunctionProcDebugEnd % - FunctionProcDebugEnd -
+{ (FunctionProcDebugEnd ) print count =
+} bind def
+
+/FunctionToProc_x0n % <function_dict> <m> FunctionToProc_x0n <proc>
+{ % Assuming a n-argument m-result function type 0.
+ % The stream is already converted to the array /Data.
+ %
+ % Making the procedure : { Domain //ScaleArg exec ... n copy {} exec n+1 1 roll ... }
+ % except "n copy" for the last chunk.
+ %
+ PDFR_DEBUG {
+ (FunctionToProc_x0n beg m=) print dup =
+ } if
+ 1 index /Size get length exch % f n m
+ dup 7 mul 2 add array % f n m []
+ PDFR_DEBUG {
+ dup 0 //FunctionProcDebugBeg put
+ } {
+ dup 0 //DoNothing put
+ } ifelse
+ dup 1 /exec load put
+ dup 2 5 index /Domain get put
+ 2 index 1 eq {
+ dup 3 //ScaleArg put
+ } {
+ dup 3 //ScaleArgN put
+ } ifelse
+ dup 4 /exec load put
+ 1 index 1 sub 0 exch 1 exch { % f n m [] i
+ dup 7 mul 5 add % f n m [] i i1
+ 1 index 4 index 1 sub ne {
+ dup 3 index exch 6 index put 1 add
+ dup 3 index exch /copy load put 1 add
+ } if
+ [ % f n m [] i i1 [
+ 6 index /Data get 3 index get % f n m [] i i1 [ di
+ 6 index 1 eq {
+ //ComputeFunction_10 /exec load
+ } {
+ 6 index
+ //ComputeFunction_n0 /exec load
+ } ifelse
+ ] cvx % f n m [] i i1 {}
+ 3 index exch 2 index exch put 1 add % f n m [] i i1
+ 2 index 1 index /exec load put 1 add
+ 1 index 4 index 1 sub ne {
+ 2 index 1 index 6 index 1 add put 1 add
+ 2 index 1 index 1 put 1 add
+ 2 index 1 index /roll load put % f n m [] i i1
+ } if
+ pop pop % f n m []
+ } for
+ PDFR_DEBUG {
+ dup dup length 2 sub //FunctionProcDebugEnd put
+ } {
+ dup dup length 2 sub //DoNothing put
+ } ifelse
+ dup dup length 1 sub /exec load put
+ cvx exch pop exch pop exch pop
+ //PDFR_DEBUG {
+ (Made a procedure for the n-argument function :) =
+ dup ==
+ } if
+ PDFR_DEBUG {
+ (FunctionToProc_x0n end) =
+ } if
+} bind def
+
+/MakeTableRec % <func_obj> <n> MakeTableRec <array>
+{
+ 0 % to be bound below
+ exec
+} bind def
+
+/MakeTable % <func_obj> <n> MakeTable <array>
+{ //PDFR_DEBUG {
+ (MakeTable beg ) print count =
+ } if
+ 1 index /Size get exch % f S N
+ 1 sub dup % f S n n
+ 3 1 roll % f n S n
+ get % f n s
+ array % f n []
+ 1 index 0 eq {
+ exch pop exch pop % []
+ } {
+ dup length 1 sub -1 0 { % f n [] i
+ 3 index 3 index //MakeTableRec exec % f n [] i []
+ 2 index 3 1 roll put % f n []
+ } for
+ exch pop exch pop
+ } ifelse
+ //PDFR_DEBUG {
+ (MakeTable end ) print count =
+ } if
+} bind def
+
+//MakeTableRec 0 //MakeTable put
+
+/StoreSample % <value> <table> <dimensions> StoreSample -
+{ % The reader is on the dictionary stack.
+ 1 sub
+ dup 0 eq {
+ pop % v []
+ } {
+ -1 1 { % v T i
+ I exch get get % v T[I[i]]
+ } for % v []
+ } ifelse
+ I 0 get 3 2 roll put
+} bind def
+
+/ReadSample32 % - ReadSample32 <value>
+{
+ 4 {
+ File read not {
+ mark (Insufficient data for function.) //error exec
+ } if
+ } repeat
+ pop % Ignore the last byte because it can't fit into 'real'.
+ 3 1 roll exch
+ 256 mul add 256 mul add
+ //1_24_bitshift_1_sub div
+} bind def
+
+/ReadSample % - ReadSample <value>
+{ % The reader in on the dictionary stack.
+ Buffer BitsLeft BitsPerSample
+ { 2 copy ge {
+ exit
+ } if
+ 3 1 roll
+ 8 add 3 1 roll
+ 256 mul File read not {
+ mark (Insufficient data for function.) //error exec
+ } if
+ add
+ 3 1 roll
+ } loop % b bl pbs
+ sub dup % b bl-bps bl-bps
+ 2 index exch % b bl-bps b bl-bps
+ neg bitshift % b bl-bps v
+ 2 copy exch bitshift % b bl-bps v v<<(bl-bps)
+ 4 3 roll exch sub % bl-bps v b-(v<<(bl-bps))
+ /Buffer exch def % bl-bps v
+ exch /BitsLeft exch def % v
+ Div div % v/(1<<pbs-1)
+} bind def
+
+/ReadSamplesRec % <dimensions> ReadSamplesRec -
+{ 0 % Will be bound below
+ exec
+} bind def
+
+/ReadSamples % <dimensions> ReadSamples -
+{ % The reader in on the dictionary stack.
+ //PDFR_DEBUG {
+ (ReadSamples beg ) print count =
+ } if
+ dup 1 eq {
+ pop
+ 0 1 Size 0 get 1 sub {
+ I exch 0 exch put
+ 0 1 M 1 sub {
+ dup Range exch 2 mul 2 getinterval % m r
+ //PDFR_DEBUG {
+ (Will read a sample ... ) print
+ } if
+ BitsPerSample 32 eq { //ReadSample32 } { //ReadSample } ifelse
+ exec exch //ScaleVal exec % m v
+ //PDFR_DEBUG {
+ (value=) print dup =
+ } if
+ exch Table exch get % v []
+ Size length //StoreSample exec %
+ } for
+ } for
+ } {
+ 1 sub
+ dup Size exch get 0 exch 1 exch 1 sub { % d-1 i
+ I exch 2 index exch put % d-1
+ dup //ReadSamplesRec exec % d-1
+ } for
+ pop
+ } ifelse
+ //PDFR_DEBUG {
+ (ReadSamples end ) print count =
+ } if
+} bind def
+
+//ReadSamplesRec 0 //ReadSamples put
+
+/StreamToArray % <obj> StreamToArray -
+{ //PDFR_DEBUG {
+ (StreamToArray beg ) print count =
+ } if
+ userdict /FuncDataReader get begin % f
+ dup /BitsPerSample get /BitsPerSample exch def
+ dup /Size get length /N exch def
+ dup /Range get length 2 idiv /M exch def
+ 1 BitsPerSample bitshift 1 sub /Div exch def
+ /BitsLeft 0 def
+ /Buffer 0 def
+ dup /Size get /Size exch def % f
+ dup /Range get /Range exch def % f
+ /File 1 index //MakeStreamReader exec def % f
+ /I [ N { 0 } repeat ] def % f
+ M array % f []
+ dup length 1 sub -1 0 { % f [] m
+ 2 index N //MakeTable exec % f [] m T
+ 2 index 3 1 roll put % f []
+ } for
+ /Table exch def % f
+ N //ReadSamples exec % f
+ PDFR_DEBUG {
+ (Table = ) print Table ==
+ } if
+ /Data Table put %
+ end
+ //PDFR_DEBUG {
+ (StreamToArray end ) print count =
+ } if
+} bind def
+
+/FunctionToProc10 % <function_dict> FunctionToProc10 <proc>
+{ % Assuming a 1-argument function type 0.
+ PDFR_DEBUG {
+ (FunctionToProc10 beg, Range = ) print dup /Range get ==
+ } if
+ dup /Order //knownget exec {
+ 1 ne {
+ (Underimplemented function Type 0 Order 3.) =
+ } if
+ } if
+ dup //StreamToArray exec % f
+ dup /Range get length dup 2 eq {
+ pop //FunctionToProc_x01 exec % proc
+ } {
+ 2 idiv //FunctionToProc_x0n exec % proc
+ } ifelse
+ PDFR_DEBUG {
+ (FunctionToProc10 end) =
+ } if
+} bind def
+
+/FunctionToProc12 % <function_dict> FunctionToProc12 <proc>
+{ begin
+ currentdict /C0 //knownget exec { length 1 eq } { true } ifelse {
+ N
+ currentdict /C0 //knownget exec {
+ 0 get
+ } {
+ 0
+ } ifelse
+ currentdict /C1 //knownget exec {
+ 0 get
+ } {
+ 1
+ } ifelse
+ 1 index sub
+ [ 4 1 roll
+ { % x n c0 c1-c0
+ 4 2 roll % c0 c1-c0 x n
+ excp mul add % y
+ } aload pop
+ ] cvx
+ } {
+ [
+ 0 1 C0 length 1 sub {
+ N % [ ... i n
+ C0 2 index get % [ ... i n c0
+ C1 3 index get % [ ... i n c0 c1
+ 4 3 roll pop % [ ... n c0 c1
+ 1 index sub % [ ... n c0 c1-c0
+ [ /dup load % [ ... n c0 c1-c0 [ dup
+ 5 2 roll % [ ... [ dup n c0 c1-c0
+ { % x x n c0 c1-c0
+ 4 2 roll % x c0 c1-c0 x n
+ exp mul add % x y
+ exch % y x
+ } aload pop
+ ] cvx
+ /exec load
+ } for
+ /pop load
+ ] cvx
+ } ifelse
+ end
+ //PDFR_DEBUG {
+ (FunctionType2Proc : ) print dup ==
+ } if
+} bind def
+
+
+/FunctionToProc14 % <function_dict> FunctionToProc14 <proc>
+{ //MakeStreamReader exec cvx exec
+ //PDFR_DEBUG {
+ (FunctionType4Proc : ) print dup ==
+ } if
+} bind def
+
+/FunctionToProc1 % <function_dict> FunctionToProc <proc>
+{ % Assuming a 1-argument function.
+ dup /FunctionType get
+ { dup 0 eq {
+ pop //FunctionToProc10 exec exit
+ } if
+ dup 2 eq {
+ pop //FunctionToProc12 exec exit
+ } if
+ dup 4 eq {
+ pop //FunctionToProc14 exec exit
+ } if
+ mark exch (Function type ) exch ( isn't implemented yet.) //error exec
+ } loop
+} bind def
+
+/FunctionToProc20 % <function_dict> FunctionToProc20 <proc>
+{ % Assuming a 2-argument function type 0.
+ PDFR_DEBUG {
+ (FunctionToProc20, Range = ) print dup /Range get ==
+ } if
+ dup /Order //knownget exec {
+ 1 ne {
+ (Underimplemented function Type 0 Order 3.) =
+ } if
+ } if
+ dup //StreamToArray exec % f
+ dup /Range get length dup 2 eq {
+ pop //FunctionToProc_x01 exec % proc
+ } {
+ 2 idiv //FunctionToProc_x0n exec % proc
+ } ifelse
+} bind def
+
+/FunctionToProc % <function_dict> FunctionToProc <proc>
+{ //PDFR_DEBUG {
+ (FunctionToProc beg ) print count =
+ } if
+ dup type /dicttype eq {
+ dup /Domain get length 2 idiv
+ {
+ dup 1 eq {
+ pop //FunctionToProc1 exec exit
+ } if
+ dup 2 eq {
+ pop //FunctionToProc20 exec exit
+ } if
+ mark (Functions with many arguments aren't implemented yet.) //error exec
+ } loop
+ } {
+ //PDFR_DEBUG {(Not a function dict, assume already a procedure.) print } if
+ } ifelse
+ //PDFR_DEBUG {
+ (FunctionToProc end ) print count =
+ } if
+} bind def
+
+/spotfunctions mark % Copied from pdf_draw.ps
+ /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
+ }
+ /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
+ }
+ /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
+ }
+ /EllipseA { dup mul .9 mul exch dup mul add 1 exch sub }
+ /InvertedEllipseA { dup mul .9 mul exch dup mul add 1 sub }
+ /EllipseB { dup 5 mul 8 div mul exch dup mul exch add sqrt 1 exch sub }
+ /EllipseC { dup mul .9 mul exch dup mul add 1 exch sub }
+ /InvertedEllipseC { dup mul .9 mul exch dup mul add 1 sub }
+ /Line { exch pop abs neg }
+ /LineX { pop }
+ /LineY { exch pop }
+ /Square { abs exch abs 2 copy lt { exch } if pop neg }
+ /Cross { abs exch abs 2 copy gt { exch } if pop neg }
+ /Rhomboid { abs exch abs 0.9 mul add 2 div }
+ /DoubleDot { 2 {360 mul sin 2 div exch } repeat add }
+ /InvertedDoubleDot { 2 {360 mul sin 2 div exch } repeat add neg }
+ /SimpleDot { dup mul exch dup mul add 1 exch sub }
+ /InvertedSimpleDot { dup mul exch dup mul add 1 sub }
+ /CosineDot { 180 mul cos exch 180 mul cos add 2 div }
+ /Double { exch 2 div exch 2 { 360 mul sin 2 div exch } repeat add }
+ /InvertedDouble {
+ exch 2 div exch 2 { 360 mul sin 2 div exch } repeat add neg
+ }
+.dicttomark readonly def
+
+% ===================== Color Spaces and Colors ==============
+
+/CheckColorSpace % <key> <val> CheckColorSpace <key> <val>
+{
+ dup type /arraytype ne {
+ mark (Resource ) 3 index ( must be an array.) //error exec
+ } if
+} bind def
+
+/SubstitutePDFColorSpaceRec % <array> SubstitutePDFColorSpace <array>
+{ 0 % Will be bound below
+ exec
+} bind def
+
+/SubstitutePDFColorSpace % <array> SubstitutePDFColorSpace <array>
+{
+ {
+ dup 0 get /Pattern eq {
+ dup length 1 gt {
+ dup dup 1 //CheckColorSpace //ResolveA exec
+ dup type /nametype ne {
+ //SubstitutePDFColorSpaceRec exec
+ } if
+ 1 exch put
+ } if
+ exit
+ } if
+ dup 0 get /Indexed eq {
+ exit
+ } if
+ dup 0 get /Separation eq {
+ dup dup 2 //CheckColorSpace //ResolveA exec
+ dup type /nametype ne {
+ //SubstitutePDFColorSpaceRec exec
+ } if
+ 2 exch put
+ exit
+ } if
+ dup 0 get /CalGray eq {
+ 1 get % dict
+ dup /Gamma //knownget exec {
+ [ exch /exp load ] cvx
+ 1 index exch /DecodeLMN exch put
+ } if
+ [ exch /CIEBasedA exch ] % []
+ exit
+ } if
+ dup 0 get /CalRGB eq {
+ 1 get % dict
+ dup /Matrix //knownget exec {
+ 1 index exch /MatrixLMN exch put
+ } if
+ dup /Gamma //knownget exec {
+ aload pop
+ [ exch /exp load ] cvx
+ 3 1 roll
+ [ exch /exp load ] cvx
+ 3 1 roll
+ [ exch /exp load ] cvx
+ 3 1 roll
+ 3 array astore
+ 1 index exch /DecodeLMN exch put
+ } if
+ [ exch /CIEBasedABC exch ] % []
+ exit
+ } if
+ dup 0 get /Lab eq {
+ 1 get % dict
+ begin
+ currentdict /Range //knownget exec { aload pop } { -100 100 -100 100 } ifelse
+ 0 100 6 2 roll 6 array astore
+ /RangeABC exch def
+ /DecodeABC [{16 add 116 div} bind {500 div} bind {200 div} bind] def
+ /MatrixABC [1 1 1 1 0 0 0 0 -1] def
+ { dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse }
+ /DecodeLMN [
+ % Store white point implicitly inside procedures.
+ [ 3 index aload pop WhitePoint 0 get /mul load ] cvx
+ [ 4 index aload pop WhitePoint 1 get /mul load ] cvx
+ [ 5 index aload pop WhitePoint 2 get /mul load ] cvx
+ ] def pop
+ //PDFR_DEBUG {
+ (Constructed from Lab <<) =
+ currentdict { exch = == } forall
+ (>>) =
+ } if
+ [ /CIEBasedABC currentdict ] % []
+ end
+ exit
+ pop
+ } if
+ % Check if this is an already substituted space
+ dup 0 get /CIEBasedA eq {exit} if
+ dup 0 get /CIEBasedABC eq {exit} if
+ mark exch (Unimplemented color space ) exch //error exec
+ } loop
+} bind def
+
+//SubstitutePDFColorSpaceRec 0 //SubstitutePDFColorSpace put
+
+/ResolveArrayElement % <array> <index> ResolveArrayElement <array>
+{ 2 copy get
+ dup type dup /arraytype eq exch
+ /packedarraytype eq or { % make sure its a procedure/executable array
+ xcheck {
+ 2 copy get % Get executable array
+ dup 0 get type /integertype eq % ensure first element is an integer
+ 1 index 1 get type dup /arraytype
+ eq exch
+ /packedarraytype eq or % ensure second element is executable array
+ and {
+ exec
+ 2 index 4 1 roll put
+ } {
+ pop pop
+ } ifelse
+ } {
+ pop
+ } ifelse
+ } {
+ pop pop
+ } ifelse
+} bind def
+
+/ResolveColorSpaceArrayRec % <color_space> ResolveColorSpaceArrayRec <color_space>
+{ 0 % Will be bond below.
+ exec
+} bind def
+
+/SetColorSpaceSafe % <color_space> SetColorSpaceSafe -
+{
+ % This works against applying a pattern over a pattern space,
+ % which may happen due to duplication of stroking and non-stroking colors.
+ % gs3.70 fails when setting a pattern space and
+ % the (old) current color space is a pattern space.
+ %
+ % If the new color space is an array and it appears equal to the old one,
+ % do nothing. Otherwise set the new color space.
+ PDFR_DEBUG {
+ (SetColorSpaceSafe beg) =
+ } if
+ currentcolorspace dup type /arraytype eq { % cs cs'
+ 1 index type /arraytype eq {
+ dup length 2 index length eq {
+ false exch % cs b cs'
+ dup length 0 exch 1 exch 1 sub { % cs b cs' i
+ dup % cs b cs' i i
+ 4 index exch get exch % cs b cs' csi i
+ 2 index exch get % cs b cs' csi cs'i
+ ne { % cs b cs'
+ exch pop true exch exit
+ } if
+ } for % cs b cs'
+ pop % cs b
+ {
+ setcolorspace
+ } {
+ pop
+ } ifelse %
+ } {
+ pop setcolorspace
+ } ifelse
+ } {
+ pop setcolorspace
+ } ifelse
+ } { % cs cs'
+ pop setcolorspace
+ } ifelse
+ PDFR_DEBUG {
+ (SetColorSpaceSafe end) =
+ } if
+} bind def
+
+/ResolveColorSpaceArray % <color_space> ResolveColorSpaceArray <color_space>
+{
+ //PDFR_DEBUG {
+ (ResolveColorSpaceArray beg ) print dup ==
+ } if
+ dup 0 get /Indexed eq {
+ 1 //ResolveArrayElement exec
+ dup dup 1 get
+ dup type /arraytype eq {
+ //SubstitutePDFColorSpace exec
+ //ResolveColorSpaceArrayRec exec
+ 1 exch put
+ } {
+ pop pop
+ } ifelse
+ } if
+ dup 0 get /Separation eq {
+ 3 //ResolveArrayElement exec
+ dup 3 get //FunctionToProc exec
+ 2 copy 3 exch put
+ pop
+ } if
+ PDFR_DEBUG {
+ (Construcrted color space :) =
+ dup ==
+ } if
+ //PDFR_DEBUG {
+ (ResolveColorSpaceArray end ) print dup ==
+ } if
+} bind def
+
+//ResolveColorSpaceArrayRec 0 //ResolveColorSpaceArray put
+
+/ResolveColorSpace % <name> ResolveColorSpace <color_space>
+{
+ //PDFR_DEBUG {
+ (ResolveColorSpace beg ) print dup =
+ } if
+ dup //SimpleColorSpaceNames exch known not {
+ dup //PDFColorSpaces exch //knownget exec {
+ exch pop
+ //PDFR_DEBUG {
+ (ResolveColorSpace known ) =
+ } if
+ } {
+ dup % n n
+ //PDFReader /CurrentObject get /Context get /Resources get
+ /ColorSpace //DoNothing //ResolveD exec
+ exch //CheckColorSpace //ResolveD exec % n cs
+ dup type /arraytype eq {
+ //SubstitutePDFColorSpace exec
+ //ResolveColorSpaceArray exec
+ dup //PDFColorSpaces 4 2 roll put % []
+ } if
+ } ifelse
+ } if
+ //PDFR_DEBUG {
+ (ResolveColorSpace end ) print dup ==
+ } if
+} bind def
+
+/CheckPattern % <key> <val> CheckPattern <key> <val>
+{
+ dup /PatternType //knownget exec {
+ dup 1 ne {
+ mark (Resource ) 4 index ( is a shading, which can't be handled at level 2. ) //error exec
+ } if
+ pop
+ } if
+ dup /Type knownget { % /Type is optional for type 1 pattern dictionaries
+ /Pattern ne {
+ mark (Resource ) 4 index ( must have /Type/Pattern .) //error exec
+ } if
+ } if
+} bind def
+
+/PaintProc %
+{ /Context get % pattern_object
+ //RunDelayedStream exec
+} bind def
+
+/ResolvePattern % <name> ResolvePattern <pattern>
+{
+ dup % n n
+ % Since makepattern makes a local dictionary,
+ % we cahche them in userdict, which is in local VM.
+ % Assuming unique resource name through the document
+ userdict /PDFR_Patterns get % n n d
+ exch //knownget exec { % n p
+ exch pop % p
+ } { % n
+ dup % n n
+ //PDFReader /CurrentObject get /Context get /Resources get
+ /Pattern //DoNothing //ResolveD exec
+ exch //CheckPattern //ResolveD exec % n o
+ dup dup /Context exch put
+ dup /Resources //DoNothing //ResolveD exec pop
+ dup /PaintProc //PaintProc put
+ gsave userdict /PDFR_InitialGS get setgstate
+ currentglobal exch false setglobal % gs3_70 compatibility
+ dup /Matrix get
+ makepattern % n p
+ exch setglobal % gs3_70 compatibility
+ grestore
+ dup userdict /PDFR_Patterns get % n p p d
+ 4 2 roll % p d n p
+ put % p
+ } ifelse
+} bind def
+
+/SetColor % Same arguments and result as for scn
+{ //PDFR_DEBUG {
+ (SetColor beg) =
+ } if
+ currentcolorspace dup type /nametype eq {
+ pop setcolor
+ } {
+ 0 get /Pattern eq {
+ //ResolvePattern exec setpattern
+ } {
+ setcolor
+ } ifelse
+ } ifelse
+ //PDFR_DEBUG {
+ (SetColor end) =
+ } if
+} bind def
+
+% ===================== Images ===============================
+
+/ImageKeys 15 dict begin
+ /BPC /BitsPerComponent def
+ /CS /ColorSpace def
+ /D /Decode def
+ /DP /DecodeParms def
+ /F /Filter def
+ /H /Height def
+ /IM /ImageMask def
+ % /Intent is undefined - pdfwrite must take care of.
+ /I /Interpolate def
+ /W /Width def
+currentdict end readonly def
+
+/ImageValues 15 dict begin
+ /G /DeviceGray def
+ /RGB /DeviceRGB def
+ /CMYK /DeviceCMYK def
+ /I /Indexed def
+ /AHx /ASCIIHexDecode def
+ /A85 /ASCII85Decode def
+ /LZW /LZWDecode def
+ /Fl /FlateDecode def
+ /RL /RunLengthDecode def
+ /CCF /CCITTFaxDecode def
+ /DCT /DCTDecode def
+currentdict end readonly def
+
+/GetColorSpaceRange
+{ 2 index /ColorSpace get
+ dup type /arraytype eq {
+ 1 get
+ } if
+ exch //knownget exec {
+ exch pop
+ } if
+} bind def
+
+/DecodeArrays 15 dict begin
+ /DeviceGray { [0 1] } def
+ /DeviceRGB { [0 1 0 1 0 1] } def
+ /DeviceCMYK { [0 1 0 1 0 1 0 1] } def
+ /Indexed {
+ dup /BitsPerComponent get 1 exch bitshift 1 sub [exch 0 exch]
+ } def
+ /Separation { [0 1] } def
+ /CIEBasedA { [0 1] /RangeA //GetColorSpaceRange exec } def
+ /CIEBasedABC { [0 1 0 1 0 1] /RangeABC //GetColorSpaceRange exec } def
+currentdict end readonly def
+
+/Substitute % <key> <dict> Substitute <key>
+{ 1 index //knownget exec {
+ exch pop
+ } if
+} bind def
+
+/DebugImagePrinting % <image_dict> DebugImagePrinting <image_dict>
+{
+ //PDFR_DEBUG {
+ (Image :) =
+ dup { exch //=only exec ( ) print ==
+ } forall
+ } if
+} bind def
+
+/CompleteImage % <dict> CompleteImage <image_dict>
+{
+ dup /ColorSpace known {
+ dup /ColorSpace //CheckColorSpace //ResolveD exec pop
+ } if
+ dup /Decode known not {
+ dup /ColorSpace //knownget exec {
+ dup type /arraytype eq {
+ 0 get
+ } if
+ //DecodeArrays exch get exec
+ } {
+ [0 1]
+ } ifelse
+ 1 index exch /Decode exch put
+ } if
+ dup /ImageMatrix [2 index /Width get 0 0 5 index /Height get neg
+ 0 7 index /Height get] put % Not sure why upside down ?
+ //DebugImagePrinting exec
+} bind def
+
+/CompleteInlineImage % <dict> CompleteInlineImage <image_dict>
+{
+ //PDFR_DEBUG {
+ (CompleteInlineImage beg) =
+ } if
+ dup /ImageType known not {
+ dup /ImageType 1 put
+ } if
+ dup length dict exch { % d key val
+ exch //ImageKeys //Substitute exec
+ dup /Filter eq {
+ exch //ImageValues //Substitute exec exch
+ } if
+ dup /ColorSpace eq {
+ exch
+ dup //ImageValues exch //knownget exec {
+ exch pop
+ } {
+ //ResolveColorSpace exec
+ } ifelse
+ exch
+ } if
+ exch
+ 2 index 3 1 roll put
+ } forall
+ //CompleteImage exec
+ dup /DataSource 2 copy get % d d /n f
+ 2 index //AppendFilters exec put
+ //PDFR_DEBUG {
+ (CompleteInlineImage end) =
+ } if
+} bind def
+
+/CompleteOutlineImage % <dict> CompleteOutlineImage <image_dict>
+{
+ currentglobal exch dup gcheck setglobal
+ //PDFR_DEBUG {
+ (CompleteOutlineImage beg) =
+ } if
+ % todo: ResetStreamReader if DataSource already exists.
+ dup dup //MakeStreamReader exec /DataSource exch put
+ dup /ImageType known not {
+ //CompleteImage exec
+ dup /ImageType 1 put
+ dup /ColorSpace known {
+ dup /ColorSpace //CheckColorSpace //ResolveD exec
+ dup type /arraytype eq {
+ //ResolveColorSpaceArray exec
+ //SubstitutePDFColorSpace exec
+ 1 index exch /ColorSpace exch put
+ } {
+ pop
+ } ifelse
+ } if
+ } if
+ //PDFR_DEBUG {
+ (CompleteOutlineImage end) =
+ } if
+ exch setglobal
+} bind def
+
+/DoImage % <image_dict> DoImage -
+{
+ //PDFR_DEBUG {
+ (DoImage beg) =
+ } if
+ gsave
+ dup /ColorSpace //knownget exec { setcolorspace } if
+ dup /ImageMask //knownget exec not { false } if
+ { imagemask } { image } ifelse
+ grestore
+ //PDFR_DEBUG {
+ (DoImage end) =
+ } if
+} bind def
+
+% ===================== Viewer State ===============
+
+/GSave % - GSave -
+{
+ gsave
+ //PDFReader /GraphicStateStackPointer get
+ dup //GraphicStateStack exch get null eq {
+ dup //GraphicStateStack exch //InitialGraphicState length dict put
+ } if
+ dup //GraphicStateStack exch get
+ //GraphicState exch copy pop
+ 1 add //PDFReader exch /GraphicStateStackPointer exch put
+} bind def
+
+/GRestore % - GRestore -
+{
+ grestore
+ //PDFReader /GraphicStateStackPointer get
+ 1 sub dup
+ //PDFReader exch /GraphicStateStackPointer exch put
+ //GraphicStateStack exch get
+ //GraphicState copy pop
+} bind def
+
+
+% ===================== Interpret Data Streams ===============
+
+/SetFont % <resource_name> <size> SetFont -
+{ dup //GraphicState exch /FontSize exch put
+ //ResolveAndSetFont exec
+ //GraphicState /FontMatrixNonHV currentfont /FontMatrix get 1 get 0 ne put
+} bind def
+
+/ShowText % <string> ShowText -
+{ //GraphicState /TextRenderingMode get 0 eq {
+ //GraphicState /WordSpacing get 0
+ 32
+ //GraphicState /CharacterSpacing get 0
+ 6 5 roll
+ //GraphicState /FontMatrixNonHV get {
+ % Use xshow to force wy in text space to be 0 (PDF1.7 5.3.3 "Text Space Details")
+ %stack: wordspacing_wx wordspacing_wy space_char charspacing_wx charspacing_wy string
+ [ % wwx wwy sp cwx cwy str [
+ 7 -2 roll pop % sp cwx cwy str [ ww
+ 5 -2 roll pop % sp str [ ww cw
+ 5 -1 roll % str [ ww cw sp
+ { % str [ ... ww cw sp c wx wy
+ exch % will be removed, unless FontMatrix.xx == 0 (FontMatrixNonHV already true)
+ pop % str [ ... ww cw sp c w
+ 3 index add % str [ ... ww cw sp c w+cw
+ exch 2 index eq { 3 index add } if % str [ ... ww cw sp w+cw[+ww]
+ 4 1 roll % str [ ... w+cw[+ww] ww cw sp
+ }
+ currentfont /FontMatrix get 0 get 0 ne {
+ 1 1 index length 1 sub getinterval cvx % drop the "exch"
+ } if
+ 5 index % str [ ww cw sp {cshowproc} str
+ cshow % str [ widths... ww cw sp
+ pop pop pop ] % str [widths...]
+ xshow
+ } {
+ awidthshow
+ } ifelse
+ } {
+ //GraphicState /CharacterSpacing get 0 eq
+ //GraphicState /FontMatrixNonHV get not and
+ //GraphicState /WordSpacing get 0 eq and {
+ true charpath
+ } {
+ % Emulate with "{ charpath } cshow".
+ % Not sure how it works with CID fonts.
+ { % c wx wy
+ exch % will be removed, unless FontMatrixNonHV && FontMatrix.xx == 0
+ pop 0 % (PDF1.7 5.3.3 "Text Space Details")
+ currentpoint 5 4 roll % wx wy x y c
+ ( ) dup 0 3 index put true charpath % wx wy x y c
+ 5 1 roll % c wx wy x y
+ moveto rmoveto % c
+ //GraphicState /CharacterSpacing get 0 rmoveto % c
+ 32 eq { %
+ //GraphicState /WordSpacing get 0 rmoveto
+ } if
+ }
+ //GraphicState /FontMatrixNonHV get dup not exch {
+ pop currentfont /FontMatrix get 0 get 0 ne
+ } if {
+ 1 1 index length 1 sub getinterval cvx
+ } if
+ exch cshow
+ } ifelse
+ } ifelse
+} bind def
+
+/ShowTextBeg % - ShowTextBeg -
+{ //GraphicState /TextRenderingMode get 0 ne {
+ currentpoint newpath moveto
+ } if
+} bind def
+
+/ShowTextEnd % - ShowTextEnd -
+{ //GraphicState /TextRenderingMode get
+ { dup 1 eq {
+ stroke exit
+ } if
+ dup 2 eq {
+ gsave fill grestore stroke exit
+ } if
+ dup 3 eq {
+ currentpoint newpath moveto
+ } if
+ dup 4 eq {
+ gsave fill grestore clip exit
+ } if
+ dup 5 eq {
+ gsave stroke grestore clip exit
+ } if
+ dup 6 eq {
+ gsave fill grestore gsave stroke grestore fill exit
+ } if
+ dup 7 eq {
+ clip exit
+ } if
+ exit
+ } loop
+ pop
+} bind def
+
+/ShowTextWithGlyphPositioning % <array> ShowTextWithGlyphPositioning -
+{ //ShowTextBeg exec
+ { dup type /stringtype eq {
+ //ShowText exec
+ } {
+ neg 1000 div //GraphicState /FontSize get mul 0 rmoveto
+ } ifelse
+ } forall
+ //ShowTextEnd exec
+} bind def
+
+/CheckFont % key val CheckFont key val
+{ dup /Type get /ExtGState ne {
+ mark (Resource ) 3 index ( must have /Type/ExtGState.) //error exec
+ } if
+} bind def
+
+/SetTransfer % <operand> SetTransfer -
+{
+ //PDFR_DEBUG { (SetTransfer beg ) print count = } if
+ dup type /arraytype eq 1 index xcheck not and {
+ 0 4 getinterval aload pop
+ setcolortransfer
+ } {
+ settransfer
+ } ifelse
+ //PDFR_DEBUG { (SetTransfer end ) print count = } if
+} bind def
+
+/CheckExtGState % <id> <obj> CheckExtGState <id> <obj>
+{ dup /Type get /ExtGState ne {
+ mark (Resource ) 3 index ( must have /Type/ExtGState.) //error exec
+ } if
+} bind def
+
+/CheckHalftone % <id> <obj> CheckHalftone <id> <obj>
+{ dup /HalftoneType known not {
+ mark (Resource ) 3 index ( must have /HalftoneType.) //error exec
+ } if
+} bind def
+
+/ResolveFunction % <dict> <name> ResolveFunction <dict> <proc>
+{
+ //PDFR_DEBUG { (ResolveFunction beg ) print dup = count = } if
+ 2 copy get //IsObjRef exec {
+ 2 copy //DoNothing //ResolveD exec
+ 3 copy put pop
+ } if
+ 2 copy get dup type /arraytype eq exch xcheck and not {
+ 2 copy get
+ dup type /arraytype eq 1 index xcheck not and {
+ dup length 1 sub -1 0 {
+ 2 copy //DoNothing ResolveA
+ dup /Identity eq {
+ pop 2 copy {} put
+ } {
+ //FunctionToProc exec
+ 3 copy put pop
+ } ifelse
+ pop
+ } for
+ } {
+ dup /Default eq {
+ % Leave it. ExtGState methods will resolve.
+ } {
+ dup /Identity eq {
+ pop {}
+ } { dup type /nametype eq {
+ //spotfunctions exch get
+ } {
+ //FunctionToProc exec
+ } ifelse
+ } ifelse
+ } ifelse
+ } ifelse
+ 3 copy put
+ exch pop
+ } {
+ 1 index exch get
+ } ifelse
+ //PDFR_DEBUG { (ResolveFunction end ) print dup == count = } if
+} bind def
+
+/ResolveFunctionSafe % <dict> <name> ResolveFunctionSafe <dict>
+{ 2 copy known {
+ //ResolveFunction exec
+ } if
+ pop
+} bind def
+
+/CreateHalftoneThresholds % <halftone_dict> CreateHalftoneThresholds <halftone_dict>
+{
+ dup /Thresholds known not {
+ dup /HalftoneType get 10 eq {
+ dup dup //MakeStreamReader exec
+ /Thresholds exch put
+ } if
+ dup /HalftoneType get dup 3 eq exch 6 eq or {
+ dup dup //MakeStreamReader exec
+ //BlockBuffer readstring pop
+ dup length
+ dup 0 eq {
+ mark (Could not read Thresholds) //error exec
+ } if
+ string copy /Thresholds exch put
+ dup /HalftoneType 3 put % replace Type 6 with Type 3.
+ } if
+ } if
+} bind def
+
+
+/SetExtGState % <name> SetExtGState -
+{
+ //PDFReader /CurrentObject get /Context get /Resources get
+ /ExtGState //DoNothing //ResolveD exec
+ exch //CheckExtGState //ResolveD exec % s gs
+ dup /LW //knownget exec {
+ setlinewidth
+ } if
+ dup /LC //knownget exec {
+ setlinecap
+ } if
+ dup /LJ //knownget exec {
+ setlinejoin
+ } if
+ dup /ML //knownget exec {
+ setmeterlimit
+ } if
+ dup /D //knownget exec {
+ setdash
+ } if
+ dup /RI //knownget exec {
+ % Ghostscript never writes it.
+ mark (Unimplemented ExtGState.RI) //error exec
+ } if
+ dup /OP //knownget exec {
+ % pdfwrite must take care of stroking/filling
+ setoverprint
+ } if
+ dup /op //knownget exec {
+ setoverprint
+ } if
+ dup /OPM //knownget exec {
+ % pdfwrite must take care of.
+ mark (Unimplemented ExtGState.OPM) //error exec
+ } if
+ dup /Font //knownget exec {
+ % Ghostscript never writes it.
+ mark (Unimplemented ExtGState.Font) //error exec
+ } if
+ dup /BG known {
+ /BG //ResolveFunction exec
+ setblackgeneration
+ } if
+ dup /BG2 known {
+ /BG2 //ResolveFunction exec
+ dup /Default eq {
+ //InitialExtGState /BG2 get
+ } if
+ setblackgeneration
+ } if
+ dup /UCR known {
+ /UCR //ResolveFunction exec
+ setundercolorremoval
+ } if
+ dup /UCR2 known {
+ /UCR2 //ResolveFunction exec
+ dup /Default eq {
+ //InitialExtGState /UCR2 get
+ } if
+ setundercolorremoval
+ } if
+ dup /TR known {
+ /TR //ResolveFunction exec
+ //SetTransfer exec
+ } if
+ dup /TR2 known {
+ /TR2 //ResolveFunction exec
+ dup /Default eq {
+ pop //InitialExtGState /TR2 get
+ aload pop setcolortransfer
+ } {
+ //SetTransfer exec
+ } ifelse
+ } if
+ dup /HT //knownget exec {
+ dup /Default eq {
+ pop //InitialExtGState /HT get
+ sethalftone
+ } {
+ //PDFR_DEBUG { (Ht beg) = } if
+ pop dup /HT //CheckHalftone //ResolveD exec
+ /SpotFunction //ResolveFunctionSafe exec
+ /TransferFunction //ResolveFunctionSafe exec
+ null exch
+ dup /HalftoneType get dup 5 eq exch dup 4 eq exch 2 eq or or {
+ dup { % null h n v
+ dup //IsObjRef exec {
+ pop
+ 1 index exch //CheckHalftone ResolveD
+ } if
+ dup type /dicttype eq {
+ dup /SpotFunction //ResolveFunctionSafe exec
+ /TransferFunction //ResolveFunctionSafe exec
+ //CreateHalftoneThresholds exec
+ dup /HalftoneType get 5 gt { % null h n v
+ 4 3 roll pop
+ dup 4 1 roll
+ } if
+ } if
+ pop pop
+ } forall
+ } if
+ //CreateHalftoneThresholds exec
+ //PDFR_DEBUG {
+ (HT:)=
+ dup {
+ 1 index /Default eq {
+ (Default <<)=
+ exch pop
+ { exch = == } forall
+ (>>)=
+ } {
+ exch = ==
+ } ifelse
+ } forall
+ (HT end)= flush
+ } if
+ exch dup null ne {
+ (Warning: Ignoring a halftone with a Level 3 component halftone Type ) print dup /HalftoneType get =
+ pop pop
+ } {
+ pop
+ dup /HalftoneType get 5 gt {
+ (Warning: Ignoring a Level 3 halftone Type ) print dup /HalftoneType get =
+ pop
+ } {
+ sethalftone
+ } ifelse
+ } ifelse
+ //PDFR_DEBUG { (HT set)= flush } if
+ } ifelse
+ } if
+ dup /FL //knownget exec {
+ setflattness
+ } if
+ dup /SM //knownget exec {
+ setsmoothness
+ } if
+ dup /SA //knownget exec {
+ setstrokeadjust
+ } if
+ dup /BM //knownget exec {
+ % pdfwrite must take care of.
+ mark (Unimplemented ExtGState.BM) //error exec
+ } if
+ dup /SMask //knownget exec {
+ % pdfwrite must take care of.
+ mark (Unimplemented ExtGState.SMask) //error exec
+ } if
+ dup /CA //knownget exec {
+ % pdfwrite must take care of.
+ mark (Unimplemented ExtGState.CA) //error exec
+ } if
+ dup /ca //knownget exec {
+ % pdfwrite must take care of.
+ mark (Unimplemented ExtGState.ca) //error exec
+ } if
+ dup /AIS //knownget exec {
+ % pdfwrite must take care of.
+ mark (Unimplemented ExtGState.AIS) //error exec
+ } if
+ dup /TK //knownget exec {
+ % pdfwrite must take care of.
+ mark (Unimplemented ExtGState.TK) //error exec
+ } if
+ pop
+} bind def
+
+/CheckXObject % <id> <obj> CheckHalftone <id> <obj>
+{ dup /Subtype get dup /Image ne exch dup /Form ne exch /PS ne and and {
+ mark (Resource ) 3 index ( must have /Subtype /Image or /Form or /PS.) //error exec
+ } if
+} bind def
+
+/DoXObject % <name> DoXObject -
+{
+ //PDFReader /CurrentObject get /Context get /Resources get
+ /XObject //DoNothing //ResolveD exec
+ exch //CheckXObject //ResolveD exec
+ dup /Subtype get
+ dup /Image eq {
+ pop
+ //CompleteOutlineImage exec
+ //DoImage exec
+ } {
+ dup /PS eq {
+ PDFR_DEBUG {
+ (Executing a PS Xobject) =
+ } if
+ pop
+ //RunDelayedStream exec
+ } {
+ dup /Form eq {
+ pop
+ PDFR_DEBUG {
+ (Executing a Form XObject) =
+ } if
+ //PDFReader /CurrentObject get exch
+ dup //PDFReader exch << exch /Context exch >> /CurrentObject exch put
+ dup /Matrix get concat
+ dup /BBox get aload pop exch 3 index sub exch 2 index sub rectclip
+ //RunDelayedStream exec
+ //PDFReader exch /CurrentObject exch put
+ } {
+ mark exch (unimplemented XObject type ) exch //error exec
+ } ifelse
+ } ifelse
+ } ifelse
+} bind def
+
+/Operators 50 dict begin
+ /q { //GSave exec } bind def
+ /Q { //GRestore exec } bind def
+ /cm { //TempMatrix astore concat } bind def
+ /i { 1 .min setflat } bind def
+ /J /setlinecap load def
+ /d /setdash load def
+ /j /setlinejoin load def
+ /w /setlinewidth load def
+ /M /setmiterlimit load def
+ /gs { SetExtGState } bind def
+
+ /g /setgray load def
+ /rg /setrgbcolor load def
+ /k /setcmykcolor load def
+ /cs { //ResolveColorSpace exec //SetColorSpaceSafe exec
+ } bind def
+ /sc /setcolor load def
+ /scn { //SetColor exec } bind def
+ /G /setgray load def
+ /RG /setrgbcolor load def
+ /K /setcmykcolor load def
+ /CS //cs def
+ /ri { SetColorRenderingIntent } bind def
+ /SC /setcolor load def
+ /SCN { //SetColor exec } bind def
+
+ /m /moveto load def
+ /l /lineto load def
+ /c /curveto load def
+ /v { currentpoint 6 2 roll curveto } bind def
+ /y { 2 copy curveto } bind def
+ /re {
+ 4 2 roll moveto exch dup 0 rlineto 0 3 -1 roll rlineto neg 0 rlineto
+ closepath
+ } def
+ /h /closepath load def
+ /n /newpath load def
+ /S /stroke load def
+ /s { closepath stroke } bind def
+ /f /fill load def
+ /f* /eofill load def
+ /B { gsave fill grestore stroke } bind def
+ /b { closepath gsave fill grestore stroke } bind def
+ /B* { gsave eofill grestore stroke } bind def
+ /b* { closepath gsave eofill grestore stroke } bind def
+ /W /clip load def
+ /W* /eoclip load def
+ /sh { % Reserved for ps3write.
+ ResolveShading
+ dup /Background known {
+ gsave
+ dup /ColorSpace get setcolorspace
+ dup /Background get aload pop setcolor
+ pathbbox % x0 y0 x1 y1
+ 2 index sub exch 3 index sub exch
+ rectfill
+ grestore
+ } if
+ shfill
+ } bind def
+
+ /Do { //DoXObject exec } bind def
+
+ /BI { currentglobal false setglobal << } bind def
+ /ID { >>
+ dup /DataSource currentfile
+ % HACK BEG
+ % This hack provides a compatibility to HP LaserJet 1320,
+ % which sometimes closes the underlying stream when EOD
+ % is reached in the ASCII85Decode filter.
+ % This portion is not required by the Postscript language definition.
+ 2 index /F //knownget exec {
+ /A85 eq {
+ 0 (~>) /SubFileDecode filter
+ } if
+ } if
+ % HACK END
+ put
+ //CompleteInlineImage exec
+ exch setglobal
+ //DoImage exec
+ } bind def
+ /EI {} bind def
+
+ /BT { gsave //GraphicState /InitialTextMatrix get currentmatrix pop } bind def
+ /ET { grestore } bind def
+ /Tc { //GraphicState exch /CharacterSpacing exch put } bind def
+ /TL { //GraphicState exch /TextLeading exch put } bind def
+ /Tr { //GraphicState exch /TextRenderingMode exch put } bind def
+ /Ts { % Ghostscript never generates it.
+ mark (Unimplemented SetTextRise) //error exec
+ } bind def
+ /Tw { //GraphicState exch /WordSpacing exch put } bind def
+ /Tz { % Ghostscript never generates it.
+ mark (Unimplemented SetHorizontalTextScaling) //error exec
+ } bind def
+ /Td { translate 0 0 moveto } bind def
+ /TD { dup neg //TL exec //Td exec } bind def
+ /Tm { //GraphicState /InitialTextMatrix get setmatrix
+ //TempMatrix astore concat
+ 0 0 moveto } bind def
+ /T* { 0 //GraphicState /TextLeading get neg //Td exec } bind def
+ /Tj { //ShowTextBeg exec //ShowText exec //ShowTextEnd exec } bind def
+ /' { //T* exec //ShowText exec //ShowTextEnd exec } bind def
+ /" { 3 2 roll //Tw exec exch //Tc exec //' exec} bind def
+ /TJ //ShowTextWithGlyphPositioning def
+ /Tf //SetFont def
+
+ /d0 /setcharwidth load def
+ /d1 /setcachedevice load def
+
+ /BDC { BeginMarkedContentSequenceWithPropertyList } bind def
+ /BMC { BeginMarkedContentSequence } bind def
+ /EMC { EndMarkedContentSequence } bind def
+ /BX { BeginCompatibilitySection } bind def
+ /EX { EndCompatibilitySection } bind def
+ /DP { DefineMarkedContentPointWithPropertyList } bind def
+ /MP { DefineMarkedContentPoint } bind def
+ /PS { cvx exec } bind def
+currentdict end def
+
+//PDFR_STREAM {
+ % Rebind operators with a debug tracing.
+ //Operators length dict begin
+ //Operators { % n p
+ exch dup % p n n
+ [ exch //=only /exec load % p n [ n =only exec
+ ( ) /print load % p n [ n =only exec () print
+ 8 7 roll % n [ n =only exec () print p
+ dup type /arraytype eq {
+ /exec load % n [ n =only exec () print p exec
+ } if
+ ( ) /print load
+ ] cvx % n {}
+ def
+ } forall
+ currentdict end /Operators exch def
+} if
+
+% Functions for handling Ghostscript library files that define encodings.
+
+/.registerencoding
+{ pop pop
+} bind def
+
+/.defineencoding
+{ def
+} bind def
+
+/.findencoding
+{ load
+} bind def
+
+
+% Leaving the procset on the dictionary stack to provide
+% definitions of obj, endobj, stream, endstream, R, xref.
+%%EndPrologue