summaryrefslogtreecommitdiff
path: root/Master/tlpkg/tlgs/Resource/Init/pdf_base.ps
diff options
context:
space:
mode:
authorAkira Kakuto <kakuto@fuk.kindai.ac.jp>2023-09-13 23:30:15 +0000
committerAkira Kakuto <kakuto@fuk.kindai.ac.jp>2023-09-13 23:30:15 +0000
commit9262fc101afe7733e74817d5d3e5917cf0143503 (patch)
treed53e8cfa6d589a695ef5554bfb69f5c0bf6c6b8e /Master/tlpkg/tlgs/Resource/Init/pdf_base.ps
parentc167e0a5bb767292da0aeef68f0bc336fc06ec0f (diff)
tlgs (gs-10.02.0)
git-svn-id: svn://tug.org/texlive/trunk@68272 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/tlpkg/tlgs/Resource/Init/pdf_base.ps')
-rw-r--r--Master/tlpkg/tlgs/Resource/Init/pdf_base.ps1474
1 files changed, 0 insertions, 1474 deletions
diff --git a/Master/tlpkg/tlgs/Resource/Init/pdf_base.ps b/Master/tlpkg/tlgs/Resource/Init/pdf_base.ps
deleted file mode 100644
index 87b9650d8c1..00000000000
--- a/Master/tlpkg/tlgs/Resource/Init/pdf_base.ps
+++ /dev/null
@@ -1,1474 +0,0 @@
-% Copyright (C) 2001-2021 Artifex Software, Inc.
-% All Rights Reserved.
-%
-% This software is provided AS-IS with no warranty, either express or
-% implied.
-%
-% This software is distributed under license and may not be copied,
-% modified or distributed except as expressly authorized under the terms
-% of the license contained in the file LICENSE in this distribution.
-%
-% Refer to licensing information at http://www.artifex.com or contact
-% Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato,
-% CA 94945, U.S.A., +1(415)492-9861, for further information.
-%
-
-% pdf_base.ps
-% Basic parser for PDF reader.
-
-% This handles basic parsing of the file (including the trailer
-% and cross-reference table), as well as objects, object references,
-% streams, and name/number trees; it doesn't include any facilities for
-% making marks on the page.
-
-/.setlanguagelevel where { pop 2 .setlanguagelevel } if
-.currentglobal //true .setglobal
-pdfdict begin
-
-% Define the name interpretation dictionary for reading values.
-/valueopdict mark
- (<<) cvn { mark } bind executeonly % don't push an actual mark!
- (>>) cvn { { .dicttomark } stopped {
- ( **** Error: File has an unbalanced >> \(close dictionary\).\n)
- pdfformaterror
- ( Output may be incorrect.\n) pdfformaterror
- } if
- } bind executeonly
- ([) cvn { mark } bind executeonly % ditto
- (]) cvn dup load
-% /true true % see .pdfexectoken below
-% /false false % ibid.
-% /null null % ibid.
- /F dup cvx % see Objects section below
- /R dup cvx % see Objects section below
- /stream dup cvx % see Streams section below
-.dicttomark readonly def
-
-% ------ Utilities ------ %
-
-% Define a scratch string. The PDF language definition says that
-% no line in a PDF file can exceed 255 characters, but this string
-% is also used to search for %PDF-, which needs 1024 characters.
-/pdfstring 1024 string def
-
-% Handle the PDF 1.2 #nn escape convention when reading from a file.
-% This should eventually be done in C.
-/.pdffixname { % <execname> .pdffixname <execname'>
- PDFversion 1.2 ge {
- dup .namestring (#) search {
- name#escape cvn exch pop
- } {
- pop
- } ifelse
- } if
-} bind executeonly def
-/name#escape % <post> <(#)> <pre> name#escape <string>
-{ exch pop
- 1 index 2 () /SubFileDecode filter dup (x) readhexstring
- % Stack: post pre stream char t/f
- not { % tolerate, but complain about bad syntax
- pop closefile (#) concatstrings exch
- ( **** Error: Invalid hex following '#' name escape, using literal '#' in name.\n)
- pdfformaterror
- ( Output may be incorrect.\n) pdfformaterror
- } {
- exch closefile concatstrings
- exch 2 1 index length 2 sub getinterval
- } ifelse
- (#) search { name#escape } if concatstrings
-} bind executeonly def
-
-/num-chars-dict mark (0123456789-.) {dup} forall .dicttomark readonly def
-
-% Execute a file, interpreting its executable names in a given
-% dictionary. The name procedures may do whatever they want
-% to the operand stack.
-/.pdftokenerror { % <count> <opdict> <errtoken> .pdftokenerror -
- % if we're called prior to actually drawing the page contents
- % (i.e. for pageusestransparency) BXlevel may not be defined, yet.
- /BXlevel where {/BXlevel get 0 le}{//true} ifelse
- {
- ( **** Error: Unknown operator: ') pdfformaterror
- dup =string cvs pdfformaterror
- (') pdfformaterror
- % Attempt a retry scan of the element after changing to PDFScanInvNum
- << /PDFScanInvNum //true >> setuserparams
- =string cvs
- token pop exch pop dup type
- dup /integertype eq exch /realtype eq or {
- exch pop exch pop
- (, processed as number, value: ) pdfformaterror
- dup =string cvs pdfformaterror (\n) pdfformaterror
- << /PDFScanInvNum //null >> setuserparams % reset to default scanning rules
- //false % suppress any stack cleanup
- } {
- % error was non-recoverable with modified scanning rules, continue.
- dup type /nametype eq {
- //true 1 index .namestring {
- //num-chars-dict exch known and
- } forall { % perhaps, it's a malformed number.
- PDFSTOPONERROR {//true}{
- pop pop pop 0 //false
- ( looks like a malformed number, replacing with 0.) pdfformaterror
- } ifelse
- } {
- //true % punt
- } ifelse
- } {
- //true % punt
- } ifelse
- (\n) pdfformaterror
- } ifelse
- } {
- //true
- } ifelse
- { % clean up the operand stack if this was non-recoverable
- pop pop count exch sub { pop } repeat % pop all the operands
- } if
- ( Output may be incorrect.\n) pdfformaterror
-} bind executeonly def
-
-currentdict /num-chars-dict .undef
-
-/.pdfexectoken { % <count> <opdict> <exectoken> .pdfexectoken ?
- PDFDEBUG {
- //pdfdict /PDFSTEPcount known not { //pdfdict /PDFSTEPcount 1 .forceput } executeonly if
- PDFSTEP {
- //pdfdict /PDFtokencount 2 copy .knownget { 1 add } { 1 } ifelse .forceput
- PDFSTEPcount 1 gt {
- //pdfdict /PDFSTEPcount PDFSTEPcount 1 sub .forceput
- } executeonly
- {
- dup ==only
- ( step # ) print PDFtokencount =only
- ( ? ) print flush 1 //false .outputpage
- (%stdin) (r) file 255 string readline {
- token {
- exch pop //pdfdict /PDFSTEPcount 3 -1 roll .forceput
- } executeonly
- {
- //pdfdict /PDFSTEPcount 1 .forceput
- } executeonly ifelse % token
- } {
- pop /PDFSTEP //false def % EOF on stdin
- } ifelse % readline
- } ifelse % PDFSTEPcount > 1
- } executeonly
- {
- dup ==only () = flush
- } ifelse % PDFSTEP
- } executeonly if % PDFDEBUG
- 2 copy .knownget {
- exch pop exch pop exch pop exec
- } {
- % Normally, true, false, and null would appear in opdict
- % and be treated as "operators". However, there is a
- % special fast case in the PostScript interpreter for names
- % that are defined in, and only in, systemdict and/or
- % userdict: putting these three names in the PDF dictionaries
- % destroys this property for them, slowing down their
- % interpretation in all PostScript code. Therefore, we
- % check for them explicitly here instead.
- dup dup dup /true eq exch /false eq or exch /null eq or {
- exch pop exch pop //systemdict exch get
- } {
- % Hackish fix to detect missing whitespace after "endobj". Yet another
- % problem that (you guessed it!) Adobe Acrobat ignores silently
- dup .namestring (endobj) anchorsearch {
- ( **** Error: Missing whitespace after 'endobj'.\n) pdfformaterror
- ( Output may be incorrect.\n) pdfformaterror
- pop pop pop exch pop /endobj get exec
- } {
- %% First, lets try and see if this 'might' be a broken number
- %% we look for 0-9 as well as '.' ',' and '-' to permit those
- %% locales in which the separator is a comma, as well as negative
- %% numbers. We've seena t least one tool replace '0' with '-' *sometimes*
- //true exch
- dup length 1 sub 0 1 3 -1 roll {
- 1 index exch get
- dup 44 lt {
- pop exch pop //false exch exit
- }{
- dup 57 gt {
- pop exch pop //false exch exit
- }{
- dup 47 eq {
- pop exch pop //false exch exit
- }{
- pop
- } ifelse
- } ifelse
- } ifelse
- } for
- pop
- {
- %% If it looks like a number, try to deal with it as such
- PDFSTOPONERROR {
- dup .pdftokenerror
- }{
- dup {.pdftokenerror} stopped
- } ifelse
- { pop
- %% But if it fails, fall back to converting into a anem.
- %% This will propagate through and cause different
- %% fallback code to try and take care ot if.
- cvlit exch pop exch pop
- }{
- exch pop
- } ifelse
- }{
- %% Doesn't look like a number, convert it into a name
- cvlit exch pop exch pop
- } ifelse
- } ifelse
- } ifelse
- } ifelse
-} bind executeonly def
-/PDFScanRules_true << /PDFScanRules //true >> def
-/PDFScanRules_null << /PDFScanRules //null >> def
-/.pdfrun { % <file> <opdict> .pdfrun -
- % Construct a procedure with the stack depth, file and opdict
- % bound into it.
- 1 index cvlit % file <<>> file
- count 2 sub % file <<>> file cnt
- 3 1 roll mark % file cnt <<>> file [
- /PDFScanRules .getuserparam //null eq {
- //PDFScanRules_true { setuserparams } 0 get % force PDF scanning mode
- mark 7 4 roll
- } {
- mark 5 2 roll % file [ [ cnt <<>> file
- } ifelse
- { % Stack: ..operands.. count opdict file
- { token } stopped {
- dup type /filetype eq { pop } if
- pop pop stop
- } if {
- dup type /nametype eq {
- dup xcheck {
- .pdfexectoken
- } {
- .pdffixname
- exch pop exch pop PDFDEBUG {
- PDFSTEPcount 1 le {
- dup ==only ( ) print flush
- } if
- } if
- } ifelse
- } {
- exch pop exch pop PDFDEBUG {
- PDFSTEPcount 1 le {
- dup ==only ( ) print flush
- } if
- } if
- } ifelse
- } {
- pop pop exit
- } ifelse
- }
- aload pop //.packtomark exec cvx % file [ {cnt <<>> file ... }
- { loop } 0 get 2 packedarray cvx % file [ { {cnt <<>> file ... } loop }
- PDFSTOPONERROR { {exec //false} } { {stopped} } ifelse
- aload pop % file [ { {cnt <<>> file ... } loop } stopped
- /PDFScanRules .getuserparam //null eq {
- //PDFScanRules_null { setuserparams } 0 get % reset PDF scannig mode if it was off
- } if
- /PDFsource PDFsource % file [ { {cnt <<>> file ... } loop } stopped /PDFsource PDFsource
- { store {
- /StreamRunAborted //true store
- ( **** Error reading a content stream. The page may be incomplete.\n)
- pdfformaterror
- ( Output may be incorrect.\n) pdfformaterror
- } if
- } aload pop % file [ { {cnt <<>> file ... } loop } stopped /PDFsource PDFsource store {...} if
- //.packtomark exec cvx % file { { {cnt <<>> file ... } loop } stopped /PDFsource PDFsource store {...} if}
- /PDFsource 3 -1 roll store % {...}
- exec
-} bind executeonly def
-
-% Execute a file, like .pdfrun, for a marking context.
-% This temporarily rebinds LocalResources and DefaultQstate.
-/.pdfruncontext { % <resdict> <file> <opdict> .pdfruncontext -
- /.pdfrun load LocalResources DefaultQstate % res file op .pdfrun Loc Qst
- /LocalResources 7 -1 roll % file op .pdfrun Loc Qst /Loc res
- dup 4 index ne { % Ensure Loc != res to avoid self-referencing /ParentResources
- dup /ParentResources 5 index put % save the parent LocalResources
- } if
- store % store new LocalResources
- /DefaultQstate qstate store
- 3 .execn
- /DefaultQstate exch store
- /LocalResources exch store
-} bind executeonly def
-
-% Get the depth of the PDF operand stack. The caller sets pdfemptycount
-% before calling .pdfrun or .pdfruncontext. It is initially set by
-% pdf_main, and is also set by any routine which changes the operand
-% stack depth (currently .pdfpaintproc, although there are other callers
-% of .pdfrun{context} which have not been checked for opstack depth.
-/.pdfcount { % - .pdfcount <count>
- count pdfemptycount sub
-} bind executeonly def
-
-% Read a token, but simply return false (no token read) in the case of an
-% error. This is messy because 'token' either may or may not pop its operand
-% if an error occurs, and because the return values are different depending
-% on whether the source is a file or a string. To avoid closing the file
-% check for '{' before trying 'token'.
-/token_nofail_dict mark
- ( ) { dup ( ) readstring pop pop } bind executeonly
- (\t) 1 index
- (\r) 1 index
- (\n) 1 index
- (\000) 1 index
- ({) { //null //true exit } bind executeonly
-.dicttomark def
-
-/token_nofail { % <file|string> token_nofail false
- % <file> token_nofail <token> true
- % <string> token_nofail <post> <token> true
- dup type /filetype eq {
- { dup ( ) .peekstring not { ({) } if
- //token_nofail_dict exch .knownget not {
- //null 1 index { token } //.internalstopped exec exit
- } if
- exec
- } loop
- { % stack: source null [source]
- //null ne { pop } if pop //false
- } { % stack: source null ([post] token true | false)
- { 3 1 roll pop pop //true }
- { pop pop //false }
- ifelse
- } ifelse
- } {
- //null 1 index % stack: source null source
- { token } //.internalstopped exec { % stack: source null [source]
- //null ne { pop } if pop //false
- } { % stack: source null ([post] token true | false)
- { 4 2 roll pop pop //true }
- { pop pop //false }
- ifelse
- } ifelse
- } ifelse
-} bind executeonly def
-
-currentdict /token_nofail_dict .undef
-
-% ================================ Objects ================================ %
-
-% We keep track of PDF objects using the following PostScript variables:
-%
-% Generations (string): Generations[N] holds 1+ the current
-% generation number for object number N. (As far as we can tell,
-% this is needed only for error checking.) For free objects,
-% Generations[N] is 0.
-%
-% Objects (array): If object N is loaded, Objects[N] is the actual
-% object; otherwise, Objects[N] is an executable integer giving
-% the file offset of the object's location in the file. If
-% ObjectStream[N] is non-zero then Objects[N] contains the index
-% into the object stream instead of the file offset of the object.
-%
-% ObjectStream (array): If object N is in an object stream then
-% ObjectStream[N] holds the object number of the object stream.
-% Otherwise ObjectStream[N] contains 0. If ObjectStream[N]
-% is non-zero then Objects[N] contains the index into the object
-% stream.
-%
-% GlobalObjects (dictionary): If object N has been resolved in
-% global VM, GlobalObjects[N] is the same as Objects[N]
-% (except that GlobalObjects itself is stored in global VM,
-% so the entry will not be deleted at the end of the page).
-%
-% IsGlobal (string): IsGlobal[N] = 1 iff object N was resolved in
-% global VM. This is an accelerator to avoid having to do a
-% dictionary lookup in GlobalObjects when resolving every object.
-
-% Initialize the PDF object tables.
-/initPDFobjects { % - initPDFobjects -
- /ObjectStream 0 array def
- /Objects 0 array def
- /Generations 0 string def
- .currentglobal //true .setglobal
- /GlobalObjects 20 dict def
- .setglobal
- /IsGlobal 0 string def
-} bind executeonly def
-
-% Grow the tables to a specified size.
-/growPDFobjects { % <minsize> growPDFobjects -
- dup ObjectStream length gt {
- dup ObjectStream exch array dup 3 1 roll copy pop /ObjectStream exch def
- } if
- dup Objects length gt {
- dup Objects exch array dup 3 1 roll copy pop /Objects exch def
- } if
- dup Generations length gt {
- %% Initiallly Generations is a string, but the xref rebuilding code
- %% can convert it to an array (/setxrefentry in pdf_rbld.ps). So we
- %% need to be able to deal with either case.
- Generations type /stringtype eq {
- dup Generations exch string dup 3 1 roll copy pop /Generations exch def
- } {
- dup Generations exch array dup 3 1 roll copy pop /Generations exch def
- } ifelse
- } if
- dup IsGlobal length gt {
- dup IsGlobal exch string dup 3 1 roll copy pop /IsGlobal exch def
- } if
- pop
-} bind executeonly def
-
-% We represent an unresolved object reference by a procedure of the form
-% {obj# gen# resolveR}. This is not a possible PDF object, because PDF has
-% no way to represent procedures. Since PDF in fact has no way to represent
-% any PostScript object that doesn't evaluate to itself, we can 'force'
-% a possibly indirect object painlessly with 'exec'.
-% Note that since we represent streams by executable dictionaries
-% (see below), we need both an xcheck and a type check to determine
-% whether an object has been resolved.
-/resolved? { % <object#> resolved? <value> true
- % <object#> resolved? false
- Objects 1 index get dup xcheck { % Check if executable
- dup type /integertype eq { % Check if an integer
- % Check whether the object is in GlobalObjects.
- pop IsGlobal 1 index get 0 eq { % 0 --> Not in GlabalObjects
- pop //false % The object is not resolved
- } { % The object is in GlobalObjects
- % Update Objects from GlobalObjects
- PDFDEBUG { (%Global=>local: ) print dup //== exec } if
- GlobalObjects 1 index get dup Objects 4 1 roll put //true
- } ifelse
- } { % Else object is executable but not integer
- exch pop //true % Therefore must be executable dict. (stream)
- } ifelse
- } { % Else object is not executable.
- exch pop //true % Therefore it must have been resolved.
- } ifelse
-} bind executeonly def
-/oforce /exec load def
-/oget { % <array> <index> oget <object>
- % <dict> <key> oget <object>
- % Before release 6.20, this procedure stored the resolved
- % object back into the referring slot. In order to support
- % PDF linearization, we no longer do this.
- get oforce
-} bind executeonly def
-
-/oforce_array { % <array> oforce_array <array>
- [ exch { oforce } forall ]
-} bind executeonly def
-
-/oforce_elems { % <array> oforce_elems <first> ... <last>
- { oforce } forall
-} bind executeonly def
-
-%% Safe recursion maintain a dicitonary in which we record all the object numbers
-%% of objects which we resolve. Whenever it resolves a new one, it checks all the
-%% existing ones to see if its already present, in which case we assume recursion
-%% has taken place. Whenever this procedure calls itself it copies the existing
-%% dictionary, and throws it away afterwards. This means that we won't falsely
-%% detect recursion if two elements at the same level indirect to the same
-%% object.
-/safe_recursive { % <<recursion dict>> <any> oforce_recursive <recursion dict> <any>
- dup type dup /arraytype eq exch /packedarraytype eq or {
- dup rcheck { % protect tint transform functions, etc.
- dup length 3 eq {
- dup 2 get /resolveR eq {
- dup 0 get % <recursion dict> {x y resolveR} x
- dup % <recursion dict> {x y resolveR} x x
- 3 index exch known {
- ( **** Error: detected circular reference in object number ) pdfformaterror pdfstring cvs pdfformaterror
- (\n) pdfformaterror
- pop //null
- } {
- dup 3 index % <recursion dict> {x y resolveR} x x <recursion dict>
- 3 1 roll put % <recursion dict> {x y resolveR}
- } ifelse
- } if
- } if
- oforce % but dereference {1 0 R}
- dup type dup /arraytype eq exch /packedarraytype eq or {
- [ exch {
- counttomark 1 add index <<>> copy % create a copy for the recursion
- exch safe_recursive exch
- pop % pop the dictionary created for this level
- } forall
- ]
- } {
- dup type /dicttype eq {
- << exch 2 index <<>> copy exch { 3 -1 roll exch safe_recursive 3 -1 roll oforce 3 1 roll exch } forall pop>>
- } if
- } ifelse
- } if
- } {
- dup type /dicttype eq {
- << exch 2 index <<>> copy exch { 3 -1 roll exch safe_recursive 3 -1 roll oforce 3 1 roll exch } forall pop>>
- } if
- } ifelse
-} bind executeonly def
-
-/oforce_recursive {
- << >> exch safe_recursive exch pop
-} bind executeonly def
-
-% A null value in a dictionary is equivalent to an omitted key;
-% we must check for this specially.
-/knownoget { % <dict> <key> knownoget <value> true
- % <dict> <key> knownoget false
- % See oget above regarding this procedure.
- .knownget {
- oforce dup //null eq { pop //false } { //true } ifelse
- } {
- //false
- } ifelse
-} bind executeonly def
-
-% See /knownoget above.
-/oknown { % <dict> <key> oknown <bool>
- .knownget { oforce //null ne } { //false } ifelse
-} bind executeonly def
-
-/knownogetdict { % <dict> <key> knownogetdict <dict> true
- % <dict> <key> knownogetdict false
- //knownoget exec dup {
- 1 index type /dicttype ne { pop pop //false } if
- } if
-} bind executeonly def
-
-% PDF 1.1 defines a 'foreign file reference', but not its meaning.
-% Per the specification, we convert these to nulls.
-/F { % <file#> <object#> <generation#> F <object>
- % Some PDF 1.1 files use F as a synonym for f!
- .pdfcount 3 lt { f } { pop pop pop //null } ifelse
-} bind executeonly def
-
-% Verify the generation number for a specified object
-% Note: The values in Generations is the generation number plus 1.
-% If the value in Generations is zero then the object is free.
-/checkgeneration { % <object#> <generation#> checkgeneration <object#> <OK>
- Generations 2 index get 1 sub 1 index eq { % If generation # match ...
- pop //true % Then return true
- } { % Else not a match ...
- QUIET not { % Create warning message if not QUIET
- Generations 2 index get 0 eq { % Check if object is free ...
- ( **** Warning: reference to free object: )
- 2 index =string cvs concatstrings ( ) concatstrings % put obj #
- exch =string cvs concatstrings ( R\n) concatstrings % put gen #
- } {
- ( **** Warning: wrong generation: )
- 2 index =string cvs concatstrings ( ) concatstrings % put obj #
- exch =string cvs concatstrings % put gen #
- (, xref gen#: ) concatstrings 1 index Generations % put xref gen #
- exch get 1 sub =string cvs concatstrings (\n) concatstrings
- } ifelse
- pdfformatwarning % Output warning message
- } { % Else QUIET ...
- pop % Pop generation number
- } ifelse
- % We should return false for an incorrect generation number, however
- % we are simply printing a warning and then returning true. This makes
- % Ghostscript tolerant of of bad generation numbers.
- //true
- } ifelse
-} bind executeonly def
-/R { % <object#> <generation#> R <object>
- %% Parameter validation; this should not be required but we have found files
- %% (Bug 697351) which are corrupted in ways that mean we see a 'R' in a stream
- %% even though it is not an indirect object reference. Because a stream
- %% may reference objetcs which have not been resolved, we cannot simply
- %% 'undef' teh R operator, the only solution is to have it chekc the
- %% types of its operands. This is poterntially slow of course, we may
- %% need to remove this in future if the performance penalty is too great.
- %% We cannot slow down all files significantly purely to work-around
- %% files which are invalid.
- 1 index type /integertype eq 1 index type /integertype eq and {
- /resolveR cvx 3 packedarray cvx
- } {
- ( **** Error: indirect object reference \(R\) encountered with invalid arguments.) pdfformaterror
- ( Output may be incorrect.\n) pdfformaterror
- } ifelse
-} bind executeonly def
-
-% If we encounter an object definition while reading sequentially,
-% we just store it away and keep going.
-/objopdict mark
- valueopdict { } forall
- /endobj dup cvx
-.dicttomark readonly def
-
-/obj { % <object#> <generation#> obj <object>
- PDFfile objopdict .pdfrun
-} bind executeonly def
-
-/endobj { % <object#> <generation#> <object> endobj <object>
-
- %% If we have a stream wioth a broken endstream we can get here without
- %% an object definition on nthe stack. If we simply pop the 'extraneous'
- %% data we will break the stream definition and throw an error. So we look
- %% to see if this appears to be this specific case.
- 2 index type /marktype eq 2 index type /marktype eq or {
- {
- dup type /marktype eq {
- exit
- }{
- pop
- }if
- }loop
- }{
- {
- 2 index type /integertype ne 2 index type /integertype ne or {
- count 3 gt {
- ( **** Error: obj definition followed by multiple tokens, attempting to recover.\n) pdfformaterror
- ( Output may be incorrect.\n) pdfformaterror
- pop
- } {
- //null
- ( **** Error: ignoring obj followed by multiple tokens.\n) pdfformaterror
- ( Output may be incorrect.\n) pdfformaterror
- exit
- } ifelse
- } {
- exit
- } ifelse
- } loop
-
- 3 1 roll
- % Read the xref entry if we haven't yet done so.
- % This is only needed for generation # checking.
- 1 index resolved? {
- pop
- } if
- checkgeneration {
- % The only global objects we bother to save are
- % (resource) dictionaries.
- 1 index dup gcheck exch type /dicttype eq and {
- PDFDEBUG { (%Local=>global: ) print dup //== exec } if
- GlobalObjects 1 index 3 index put
- IsGlobal 1 index 1 put
- } if
- Objects exch 2 index put
- } {
- pop pop //null
- } ifelse
- }ifelse
-} bind executeonly def
-
-% When resolving an object reference in an object stream, we stop at
-% the end of file. Note: Objects in an object stream do not have either
-% a starting 'obj' or and ending 'endobj'.
-/resolveobjstreamopdict mark
- valueopdict { } forall
- (%%EOF) cvn { exit } bind executeonly
- /endobj { % bug 689795
- ( **** Error: Objects in an object stream should not have 'endobj'.\n)
- pdfformaterror
- ( Output may be incorrect.\n) pdfformaterror
- } bind executeonly
-.dicttomark readonly def
-
-% Note: This version of this function is not currently being used.
-% Resolve all objects in an object stream
-/resolveobjectstream { % <object stream #> resolveobjectstream -
- PDFDEBUG { (%Resolving object stream: ) print } if
- 0 resolveR % Get the objectstream dict, all objstrms use 0 as the gen #
- dup /First get % Save location of first object onto the stack
- 1 index /N get % Save number of objects onto the stack
- 2 index //false resolvestream % Convert stream dict into a stream
- /ReusableStreamDecode filter % We need to be able to position stream
- % Objectstreams begin with list of object numbers and locations
- % Create two arrays to hold object numbers and stream location
- 1 index array % Array for holding object number
- 2 index array % Array for holding stream object location
- % Get the object numbers and locations.
- 0 1 5 index 1 sub { % Loop and collect obj # and locations
- % Stack: objstreamdict First N objectstream [obj#] [loc] index
- 2 index 1 index % Setup to put obj# into object number array
- 5 index token pop put % Get stream, then get obj# and put into array
- 1 index 1 index % Setup to put object loc into location array
- 5 index token pop put % Get stream, get obj loc and put into array
- pop % Remove loop index
- } for
- % Create a bytestring big enough for reading any object data
- % Scan for the size of the largest object
- 0 0 % Init max object size and previous location
- 2 index { % Loop through all object locations
- % Stack: ... maxsize prevloc currentloc
- dup 4 1 roll % Save copy of object location into stack
- exch sub % Object size = currentloc - prevloc
- .max % Determine maximum object size
- exch % Put max size under previous location
- } forall
- pop % Remove previous location
- .bigstring % Create bytestring based upon max obj size
- % Move to the start of the object data
- 3 index 6 index % Get objectstream and start of first object
- setfileposition % Move to the start of the data
- % Read the data for all objects except the last. We do
- % not know the size of the last object so we need to treat
- % it as a special case.
- 0 1 6 index 2 sub {
- dup 4 index exch get % Get our current object number
- % Stack: objstreamdict First N objectstream [obj#] [loc]
- % bytestring loopindex object#
- dup resolved? { % If we already have this object
- pop pop % Remove object and object number
- 1 add 2 index exch get % Get location of next object
- 6 index add 6 index exch % Form location of next object and get stream
- setfileposition % Move to the start of the next object data
- } { % Else this is a new object ...
- % We are going to create a string for reading the object
- 2 index 0 % use our working string
- % Determine the size of the object
- 5 index 4 index 1 add get % Get location of the next object
- 6 index 5 index get % Get location of this object
- sub % Size of object = next loc - this loc
- getinterval % Create string for reading object
- 6 index exch readstring pop % Read object
- /ReusableStreamDecode filter % Convert string into a stream
- resolveobjstreamopdict .pdfrun % Get PDF object
- Objects exch 2 index exch put % Put object into Objects array
- pop pop % Remove object # and loop index
- } ifelse
- } for
- pop pop % Remove our working string and loc array
- % Now read the last object in the object stream. Since it
- % is the last object, we can use the original stream and
- % terminate when we hit the end of the stream
- % Stack: objstreamdict First N objectstream [obj#]
- 2 index 1 sub get % Get our current object number
- dup resolved? not { % If we do not already have this object
- exch % Get our object stream
- resolveobjstreamopdict .pdfrun % Get PDF object
- Objects exch 2 index exch put % Put object into Objects array
- } if
- pop pop pop pop % Clear stack
-} bind executeonly def
-
-/no_debug_dict <<
- /PDFDEBUG //false
->> readonly def
-
-% Resolve all objects in an object stream
-/resolveobjectstream { % <object stream #> resolveobjectstream -
- PDFDEBUG { (%Resolving object stream: ) print } if
- dup 0 resolveR % Get the objectstream dict, all objstrms use 0 as the gen #
- dup /Type get /ObjStm ne { % Verify type is object stream
- ( **** Error: Incorrect Type in object stream dictionary.\n) pdfformaterror
- ( Output may be incorrect.\n) pdfformaterror
- /resolveobjectstream cvx /typecheck signalerror
- } if
- dup /N get % Save number of objects onto the stack
- 1 index //false resolvestream % Convert stream dict into a stream
- /ReusableStreamDecode filter % We need to be able to position stream
- % Objectstreams begin with list of object numbers and locations
- 1 index array % Create array for holding object number
- % Get the object numbers
- 0 1 4 index 1 sub { % Loop and collect obj numbers
- % Stack: strm# objstreamdict N PDFDEBUG objectstream [obj#] loopindex
- 1 index 1 index % Setup to put obj# into object number array
- 4 index token pop put % Get stream, then get obj# and put into array
- 2 index token pop pop pop % Get stream, get obj loc and clear stack
- } for
- % Move to the start of the object data
- 1 index 4 index /First get % Get objectstream and start of first object
- setfileposition % Move to the start of the data
- % We disable PDFDEBUG while reading the data stream. We will
- % print the data later
- PDFDEBUG { //no_debug_dict begin } if
- % Read the data for all objects. We check to see if we get
- % the number of objects that we expect.
- % Stack: strm# objstreamdict N objectstream [obj#] PDFDEBUG
- /ResolveObjectStreamMark 3 -1 roll
- count 4 index add % Determine stack depth with objects
- 3 1 roll
- resolveobjstreamopdict .pdfrun % Get PDF objects
- count /ResolveObjectStreamMark CountToKey not {0} if
- 1 add index
- ne
- {
- count /ResolveObjectStreamMark CountToKey not {0} if
- 1 add index gt {
- ( **** Error: Incorrect object count in object stream (too many objects).\n) pdfformaterror
- ( Output may be incorrect.\n) pdfformaterror
- } if
- % Its possible for us to end up here with a valid file. The way we work is to read the
- % stream and tokenise all the objects, but that assumes there will be delimiters or
- % whitespace between each object in the stream. We can easily think of cases where
- % that is not true; eg two consecutive numbers 123 456 would be tokenised as a
- % single number with the value 123456.
- % In this case we can use the approach below to read each object individually and
- % that will define the correct number of objects. After we've collected all the
- % objects we'll check the number of objects recovered again, and see if there
- % are still too few. We should probably raise an error in that case, but lets wait
- % until we see a case.
-
- % Having too many objects in an ObjStm is not illegal, dumb but not illegal. We can
- % recover from this, but its complicated. The extra object could be any of the ones
- % from the stream, the only way to find out is to process each object individually.
- % Unfortunately, my attempts to come up with a version of .pdfrun which only tokenised
- % one object got rapidly bogged down. So a new approach was needed.
- %
- % The idea is simple; turn the underlying file into a ReusableStream, then we can
- % reposition it. Build an array of the object offsets, reposition the file to the
- % start of each object in turn. For all except the last object, create a sub file
- % using SubFileDeocde with an empty string, and an EODCount which is the difference
- % between the offset of this object and the offset of the next.
- % For the last object we just read from the offset to the end of the stream.
- %
- % Then call .pdfrun on that sub file, or the main stream, which will tokenise all the
- % objects from that point onwards. Then discard all but the first object read.
- %
- % The complications arise from the fact that we need to end up with the objects on
- % the stack, in the right order, preceded by a mark, a count, and an array containing
- % all the object numbers.
-
- % First, discard everything we read up to now; we can reuse the 'mark' which was placed
- % by the preceding code to do this, as long as we remember to replace that 'mark'.
- % Handily this will leave the count and the array which contains the object numbers in place.
- /ResolveObjectStreamMark ClearToKey
-
- % Replace the 'mark' consumed by conttomark above, so that we match what the code following this error handling expects.
- /ResolveObjectStreamMark
-
- % copy the ObjStm dictionary and then copy the count of objects expected
- 4 index 4 index
-
- % Copy the ObjStm dictionary, and create a file from it
- 1 index //false resolvestream % Convert stream dict into a stream
-
- /ReusableStreamDecode filter % We need to be able to re-position the stream
-
- 1 index array % Create array for holding offsets
-
- % Get the object offsets, these are stored at teh start of the stream, interleaved
- % between the object numbers. We know reading these can't fail, because we've already
- % done this to create the array of object numbers, above.
- 0 1 % starting index (0), increment (1) for loop
- 4 index 1 sub % limit of loop is object count-1 (because we start at 0)
- {
- 1 index 1 index % copy array and index
- 4 index % copy the file object
- token pop pop % read a token (object number) and discard it
- 4 index token % read another token (offset)
- pop put pop % put the offset into the array at the new index
- } for
-
- % We now have an array with all the object offsets in it
- % So we need to reposition the file to the start of each object and read
- % from that point. We use the difference between two offsets to setup
- % a SubFileDecode filter to only read as many bytes as there are
- % between the objects. Normally this should result in us reading one object,
- % if there are extra objects then we'll discard the extras. By doing this
- % we avoid tokenising the same data multiple times.
-
- % Set the loop to be from 0 to the number of objects minus 1 (starts from 0), step 1.
- 2 index 1 sub 0 1 3 -1 roll
- {
- dup % copy the loop index
- 2 index length 2 sub lt % Check if index + 1 exceeds array size (it will on last iteration)
-
- { % Not the last iteration
- dup % copy the loop index
- 2 index exch get 5 index /First get add % get the object offset, and add the value of First from the dictionary.
- exch 1 add % add one to the loop index
- 2 index exch get 5 index /First get add % and get the offset to the start of the next object
-
- 1 index sub % copy the first offset and subtract from the second to get the length
- exch
- 3 index dup 3 -1 roll setfileposition % copy the file and position it to the offset of the object
- exch
- << /EODCount 3 -1 roll /EODString () >> % Set up a dictionary for the filter
- /SubFileDecode filter % and apply it to limit the number of bytes read.
- }
- { % On the last iteration, simly read from the file, we don't need another SubFileDecode.
- 1 index exch get 4 index /First get add % get the offset, and add the value of First from the dictionary.
- 2 index dup 3 -1 roll setfileposition % copy the stream, and position it at that point
- }ifelse
-
- mark exch resolveobjstreamopdict .pdfrun % make a mark and then tokenise all the objects from there to the end of stream (or sub file)
- counttomark 2 sub % Find out how many objects we created (less two, one for the count and one for the first object)
- 0 1 3 -1 roll {pop pop} for % pop that many objects off the stack
- 6 1 roll pop % roll the new object to be behind our working objects on the stack and pop the mark
- } for
-
- % pop most of the working objects (array, file, and ObjStrm dictionary)
- % but leave count of objects. Check that aginst the number of objects
- % retrieved. If we got too few then issue a warning.
-
- pop pop exch pop /ResolveObjectStreamMark CountToKey not {1} if
- 1 sub lt {
- ( **** Error: Incorrect object count in object stream (too few objects).\n) pdfformaterror
- ( Output may be incorrect.\n) pdfformaterror
- } if
- } if
-
- % We have the object data
- /ResolveObjectStreamMark CountToKey not {0} if array astore
- exch pop exch pop % Remove mark and count
- currentdict //no_debug_dict eq { end } if % Restore debug context
- % Save the objects into Objects
- 0 1 2 index length 1 sub { % Loop through all objects
- % Stack: strm# objstreamdict N [obj#] [objects] loopindex
- dup 3 index exch get % Get our current object number
- % Stack: strm# objstreamdict N [obj#] [objects] loopindex obj#
- dup ObjectStream exch get 7 index eq {
- dup resolved? { % If we already have this object
- pop pop % Remove object and object number
- } { % Else if we do not have this object
- PDFDEBUG { (%Resolving compressed object: [) print dup =only ( 0]) = } if
- Objects exch 3 index % Put the object into Objects
- 3 index get
- PDFDEBUG { dup === flush } if
- put
- } ifelse
- } {
- pop % Ignore old object; remove object number.
- } ifelse
- pop % Remove loop index
- } for
- pop pop pop pop pop % Remove strm# objstream, N, (obj#], and [objects]
-} bind executeonly def
-
-currentdict /no_debug_dict undef
-
-% When resolving an object reference, we stop at the endobj or endstream.
-/resolveopdict mark
- valueopdict { } forall
- /xref { % Bug 697761
- ( **** Error: Encountered 'xref' while expecting 'endobj'.\n) pdfformaterror
- ( Treating this as a missing 'endobj', output may be incorrect.\n) pdfformaterror
- endobj exit
- } bind executeonly
- /endstream { endobj exit } bind
- /endobj { endobj exit } bind
- /endjobj { % Bug 689876.
- ( **** Error: Operator 'endobj' is misspelled as 'endjobj'.\n) pdfformaterror
- ( Output may be incorrect.\n) pdfformaterror
- endobj exit
- } bind executeonly
- /enbobj { % Bug 690397.
- ( **** Error: Operator 'endobj' is misspelled as 'enbobj'.\n) pdfformaterror
- ( Output may be incorrect.\n) pdfformaterror
- endobj exit
- } bind executeonly
- /obj {
- % OmniForm generates PDF file with endobj missing in some
- % objects. AR ignores this. So we have to do it too.
- ( **** Error: Encountered 'obj' while expecting 'endobj'.\n) pdfformaterror
- ( Treating this as a missing 'endobj', output may be incorrect.\n) pdfformaterror
- pop pop endobj exit
- } bind executeonly
-.dicttomark readonly def
-
-/resolveR { % <object#> <generation#> resolveR <object>
- 1 index 3 1 roll % copy the object for the code after pdf_run_resolve (may store it)
- PDFDEBUG {
- PDFSTEPcount 1 le {
- (%Resolving: ) print 2 copy 2 array astore //== exec
- } if
- } if
- 1 index dup 0 le exch NumObjects ge or {
- ( **** Error: Considering object with an invalid number )
- 2 index 20 string cvs concatstrings
- ( as null.\n) concatstrings pdfformaterror
- ( Output may be incorrect.\n) pdfformaterror
- pop pop //null
- } {
- 1 index resolved? { % If object has already been resolved ...
- exch pop exch pop % then clear stack and return object
- } { % Else if not resolved ...
- PDFfile fileposition 3 1 roll % Save current file position
- 1 index Objects exch get % Get location of object from xref
- 3 1 roll checkgeneration { % Verify the generation number
- % Stack: savepos objpos obj#
- ObjectStream 1 index get dup 0 eq { % Check if obj in not an objstream
- pop exch PDFoffset add PDFfile exch setfileposition
- PDFfile token pop 2 copy ne
- { ( **** Error: Unrecoverable error in xref!\n) pdfformaterror
- ( Output may be incorrect.\n) pdfformaterror
- /resolveR cvx /rangecheck signalerror
- }
- if pop PDFfile token pop
- PDFfile token pop /obj ne
- { ( **** Error: Unrecoverable error in xref!\n) pdfformaterror
- ( Output may be incorrect.\n) pdfformaterror
- /resolveR cvx /rangecheck signalerror
- }
- if
- pdf_run_resolve % PDFfile resolveopdict .pdfrun
- } { % Else the object is in an ObjectStream
- % Process an objectstream object. We are going to resolve all
- % of the objects in sthe stream and place them into the Objects
- % array.
- % Stack: savepos objpos obj# objectstream#
- resolveobjectstream
- resolved? { % If object has already been resolved ...
- exch pop % Remove object pos from stack.
- } {
- pop pop //null % Pop objpos and obj#, put null for object
- } ifelse
- } ifelse
- } { % Else the generation number is wrong
- % Don't cache if the generation # is wrong.
- pop pop //null % Pop objpos and obj#, put null for object
- } ifelse % ifelse generation number is correct
- exch PDFfile exch setfileposition % Return to original file position
- } ifelse
- } ifelse
-
- dup type /dicttype eq % For dictionaries only
- {
- dup /Type known % make sure the dictionary has a type
- {
- %% We must not add to *all* dictionaries, because some of them are handled by
- %% executing all the key/value pairs, and adding a integer causes problems
- %% Since we only use this number for font identification, or checking self-references,
- %% we only need it for dictionaries with a Type, and these are always handled more carefully.
- dup 3 -1 roll /.gs.pdfobj# exch put
- }
- {exch pop}
- ifelse
- }
- {exch pop}
- ifelse
-} bind executeonly def
-
-% ================================ Streams ================================ %
-
-% We represent a stream by an executable dictionary that contains,
-% in addition to the contents of the original stream dictionary:
-% /File - the file or string where the stream contents are stored,
-% if the stream is not an external one.
-% /FilePosition - iff File is a file, the position in the file
-% where the contents start.
-% /StreamKey - the key used to decrypt this stream, if any.
-% We do the real work of constructing the data stream only when the
-% contents are needed.
-
-% Construct a stream. The length is not reliable in the face of
-% different end-of-line conventions, but it's all we've got.
-%
-% PDF files are inconsistent about what may fall between the 'stream' keyword
-% and the actual stream data, and it appears that no one algorithm can
-% detect this reliably. We used to try to guess whether the file included
-% extraneous \r and/or \n characters, but we no longer attempt to do so,
-% especially since the PDF 1.2 specification states flatly that the only
-% legal terminators following the 'stream' keyword are \n or \r\n, both of
-% which are properly skipped and discarded by the token operator.
-% Unfortunately, this doesn't account for other whitespace characters that
-% may have preceded the EOL, such as spaces or tabs. Thus we back up one
-% character and scan until we find the \n terminator.
-/stream { % <dict> stream <modified_dict>
- dup /F known dup PDFsource PDFfile eq or {
- not {
- dup /File PDFfile put
- % make sure that we are just past the EOL \n character
- PDFfile dup fileposition 1 sub setfileposition % back up one
- % Skip spaces till \n or a non-space character is found.
- //false
- {
- PDFfile read pop
- dup 32 eq { pop //true or } { exit } ifelse
- } loop
- dup 13 eq {
- pop
- PDFfile read pop
- } if
- 10 ne {
- PDFfile dup fileposition 1 sub setfileposition
- //true or
- } if {
- ( **** Error: stream operator isn't terminated by valid EOL.\n) pdfformaterror
- ( Output may be incorrect.\n) pdfformaterror
- } if
-
- dup /FilePosition PDFfile fileposition put
- PDFDEBUG {
- PDFSTEPcount 1 le {
- (%FilePosition: ) print dup /FilePosition get //== exec
- } if
- } if
- } if
- % Some (bad) PDf files have invalid stream lengths. This causes problems
- % if we reposition beyond the end of the file. So we compare the given
- % length to number of bytes left in the file.
- dup mark exch /Length {knownoget} stopped {
- % Bug 703372 is a PDF file where the XRef stream dictionary has a Length which is an
- % indirect object. Clearly we cannot look that up in an xref which we haevn't yet
- % read! We catch the error from knownoget and do not reposition the steam. After
- % that the normal recovery code kicks in and we will eventually manage to read
- % the compressed xref.
- cleartomark
- }
- {
- {
- dup type /realtype eq {
- ( **** Warning: stream length is a real number; converting to integer.\n) pdfformatwarning
- cvi 2 copy /Length exch put
- } if
- dup PDFfile bytesavailable lt { % compare to to bytes left in file
- PDFfile fileposition % reposition to the end of stream
- add PDFfile exch setfileposition
- } {
- pop % bad stream length - do not reposition.
- % This will force a length warning below
- } ifelse
- } if
- pop % the mark from the Length dereference guard above.
- } ifelse
- } {
- pop
- % We're already reading from a stream, which we can't reposition.
- % Capture the sub-stream contents in a string.
- dup /Length oget string PDFsource exch readstring
- not {
- ( **** Error: Unexpected EOF in stream!\n) pdfformaterror
- ( Output may be incorrect.\n) pdfformaterror
- /stream cvx /rangecheck signalerror
- } if
- 1 index exch /File exch put
- } ifelse
- PDFsource token_nofail not { //null } if
- dup /endobj eq {
- % Another case that Acrobat Reader handles -- 'endobj' without 'endstream'.
- ( **** Error: stream missing 'endstream'.\n) pdfformaterror
- ( Output may be incorrect.\n) pdfformaterror
- pop /endstream % fake a valid endstream
- } if
- /endstream ne {
- ( **** Error: stream Length incorrect.\n) pdfformaterror
- ( Output may be incorrect.\n) pdfformaterror
- dup /Length undef % prevent the use of the incorrect length.
-
- %% Bug #696560 If we get a stream whose length is incorrect we cannot
- %% safely *assume* it has an object definition as we can get here when
- %% reading an XRef stream, and in that case we will not have the object
- %% and generation numbers on the stack!
- %% So before we call endobj and exit pdfrun, try and see if ths looks like
- %% a regular object or not. If it isn't then don't try and ahndle it as
- %% one, just return the object.
- count 3 ge {
- 1 index type /integertype eq 2 index type /integertype eq and {
- cvx endobj exit % exit from .pdfrun now.
- } if
- } if
- } {
- PDFsource (??) .peekstring pop (>>) eq { % Bug 690161, sample #1
- ( **** Error: Spurious '>>' after 'endstream' ignored.\n) pdfformaterror
- ( Output may be incorrect.\n) pdfformaterror
- PDFsource (12) readstring pop pop
- } if
- } ifelse
- cvx
-} bind executeonly def
-
-/endstream {
- exit
-} bind executeonly def
-
-% Contrary to the published PDF (1.3) specification, Acrobat Reader
-% accepts abbreviated filter names everywhere, not just for in-line images,
-% and some applications (notably htmldoc) rely on this.
-/unabbrevfilterdict mark
- /AHx /ASCIIHexDecode /A85 /ASCII85Decode /CCF /CCITTFaxDecode
- /DCT /DCTDecode /Fl /FlateDecode /LZW /LZWDecode /RL /RunLengthDecode
-.dicttomark readonly def
-
-% Extract and apply filters.
-/filterparms { % <dict> <DPkey> <Fkey> filterparms
- % <dict> <parms> <filternames>
- 2 index exch knownoget {
- oforce_recursive
- exch 2 index exch knownoget {
- dup length 0 eq {
- pop //false
- } {
- //true
- } ifelse
- } {
- //false
- } ifelse {
- % Both filters and parameters.
- oforce_recursive
- exch dup type /nametype eq {
- 1 array astore exch
- dup type /arraytype ne { 1 array astore } if exch
- } if
- } {
- % Filters, but no parameters.
- //null exch
- dup type /nametype eq { 1 array astore } if
- } ifelse
- } {
- % No filters: ignore parameters, if any.
- pop //null { }
- } ifelse
-} bind executeonly def
-/filtername { % <filtername> filtername <filtername'>
- //unabbrevfilterdict 1 index .knownget { exch pop } if
- dup /Filter resourcestatus { pop pop } {
- Repaired exch % this error is not the creator's fault
- RepairedAnError exch
- ( **** ERROR: Unable to process ) pdfformaterror
- 64 string cvs pdfformaterror
- ( data. Page will be missing data.\n) pdfformaterror
- /RepairedAnError exch store
- /Repaired exch store % restore the previous "Repaired" state
- % provide a filter that returns EOF (no data)
- /.EOFDecode
- } ifelse
-} bind executeonly def
-
-/pdf_rules_dict << /PDFRules //true >> readonly def
-
-% Add PDF option to ASCII85Decode filter
-% <source> <name> add_A85_param <source> <dict'> <name>
-% <source> <dict> <name> add_A85_param <source> <dict'> <name>
-/add_A85_param {
- dup /ASCII85Decode eq {
- 1 index type /dicttype eq {
- exch dup length 1 add dict copy
- dup /PDFRules //true put
- exch
- } {
- //pdf_rules_dict exch
- } ifelse
- } if
-} bind executeonly def
-
-currentdict /pdf_rules_dict undef
-
-/applyfilters { % <parms> <source> <filternames> applyfilters <stream>
- 2 index //null eq
- {
- { filtername add_A85_param filter }
- }
- {
- dup length 3 index length ne %% compare lengths of DecodeParmas and Filter arrays
- { %% if they aren't the same, ignore the decode params
- ( **** Error: ignoring stream /DecodeParams array as its length is different to the Filters array.\n) pdfformaterror
- ( Output may be incorrect.\n) pdfformaterror
- 3 -1 roll pop //null 3 1 roll
- { filtername add_A85_param filter }
- }
- {
- { % Stack: parms source filtername
- 2 index 0 oget dup type /dicttype ne
- { pop }
- {
- exch filtername dup /JBIG2Decode eq { exch jbig2cachectx exch } if
- } ifelse
- add_A85_param filter
- exch dup length 1 sub 1 exch getinterval exch
- }
- } ifelse
- } ifelse
- forall exch pop
-} bind executeonly def
-
-% JBIG2 streams have an optional 'globals' stream obj for
-% sharing redundant data between page images. Here we resolve
-% that stream reference (if any) and run it through the decoder,
-% creating a special -jbig2globalctx- postscript object our
-% JBIG2Decode filter implementation looks for in the parm dict.
-/jbig2cachectx { % <parmdict> jbig2cachectx <parmdict>
- dup /JBIG2Globals knownoget {
- % make global ctx
- PDFfile fileposition exch % resolvestream is not reentrant
- mark exch
- //true resolvestream % stack after: PDFfileposition -file-
- % Read the data in a loop until EOF to so we can move the strings into a bytestring
- [ { counttomark 1 add index 60000 string readstring not { exit } if } loop ]
- exch pop 0 1 index { length add } forall % compute the total length
- % now copy the data from the array of strings into a bytestring
- .bytestring exch 0 exch { 3 copy putinterval length add } forall pop
- % If this fails we don't want to abort totally, there may be more content
- % in the PDF file that we can render. So just run in a stopped context.
- {.jbig2makeglobalctx} stopped
- {
- cleartomark
- PDFfile exch setfileposition
- }
- {
- exch pop
- PDFfile 3 -1 roll setfileposition
- 1 index exch
- /.jbig2globalctx exch put
- } ifelse
- } if
-} bind executeonly def
-
-% Resolve a stream dictionary to a PostScript stream.
-% Streams with no filters require special handling:
-% - Whether we are going to interpret the stream, or If we are just
-% going to read data from them, we impose a SubFileDecode filter
-% that reads just the requisite amount of data.
-% Note that, in general, resolving a stream repositions PDFfile.
-% Clients must save and restore the position of PDFfile themselves.
-/resolvestream { % <streamdict> <readdata?> resolvestream <stream>
- 1 index /F knownoget {
- % This stream is stored on an external file.
- (r) file 3 -1 roll
- /FDecodeParms /FFilter filterparms
- % Stack: readdata? file dict parms filternames
- 4 -1 roll exch
- pdf_decrypt_stream
- applyfilters
- } {
- exch
- dup /Length knownoget { 0 eq } { //false } ifelse {
- () 0 () /SubFileDecode filter
- } {
- dup /FilePosition .knownget {
- 1 index /File get exch setfileposition
- } if
- % Stack: readdata? dict
- /DecodeParms /Filter filterparms
- % Stack: readdata? dict parms filternames
- 2 index /File .knownget not {
- ( **** Error: Stream object is missing the stream data.\n)
- ( Output may be incorrect.\n) pdfformaterror
- pdfformaterror
- ()
- } if exch
- % Stack: readdata? dict parms file/string filternames
- dup length 0 eq {
- % All the PDF filters have EOD markers, but in this case
- % there is no specified filter.
- exch dup type /filetype eq 5 index or {
- % Use length for any files or reading data from any source.
- 3 index /Length knownoget not { 0 } if
- } {
- 0 % Otherwise length of 0 for whole string
- } ifelse
- 4 index /IDFlag known { pop } { () /SubFileDecode filter } ifelse
- exch
- pdf_decrypt_stream % add decryption if needed
- pop exch pop
- } {
- % Stack: readdata? dict parms source filternames
- exch 3 index /Length knownoget {
- () /SubFileDecode filter
- } if exch
- pdf_decrypt_stream % add decryption if needed
- applyfilters
- } ifelse
- } ifelse
- } ifelse
- % Stack: readdata? dict file
- exch pop exch pop
-} bind executeonly def
-
-% ============================ Name/number trees ============================ %
-
-/nameoget { % <nametree> <key> nameoget <obj|null>
- exch /Names exch .treeget
-} bind executeonly def
-
-/numoget { % <numtree> <key> numoget <obj|null>
- exch /Nums exch .treeget
-} bind executeonly def
-
-/.treeget { % <key> <leafkey> <tree> .treeget <obj|null>
- dup /Kids knownoget {
- exch pop .branchget
- } {
- exch oget .leafget
- } ifelse
-} bind executeonly def
-
-/.branchget { % <key> <leafkey> <kids> .branchget <obj|null>
- dup length 0 eq {
- pop pop pop //null
- } {
- dup length -1 bitshift 2 copy oget
- % Stack: key leafkey kids mid kids[mid]
- dup /Limits oget aload pop
- % Stack: key leafkey kids mid kids[mid] min max
- 6 index lt {
- pop pop
- 1 add 1 index length 1 index sub getinterval .branchget
- } {
- 5 index gt {
- pop
- 0 exch getinterval .branchget
- } {
- exch pop exch pop .treeget
- } ifelse
- } ifelse
- } ifelse
-} bind executeonly def
-
-/.leafget { % <key> <pairs> .leafget <obj|null>
- null % <key> [pairs] null
- 0 2 3 index length 1 sub % <key> [pairs] null 0 2 length([pairs])
- { % <key> [pairs] null index
- 2 index % <key> [pairs] null index [pairs]
- exch % <key> [pairs] null [pairs] index
- 2 getinterval % <key> [pairs] null [<key1> <value>]
- dup 0 get % <key> [pairs] null [<key1> <value>] <key1>
- 4 index % <key> [pairs] null [<key1> <value>] <key1> <key>
- eq
- { % <key> [pairs] null [<key1> <value>]
- exch pop 1 oget exit % <key> [pairs] <obj>
- } {
- pop % <key> [pairs] null
- }ifelse
- } for
- % <key> [pairs] <obj|null>
- 3 1 roll pop pop % <obj|null>
-} bind executeonly def
-
-% The following variants return tree entry whose key is closest but
-% less or equal to the given key.
-
-/numogetle { % <numtree> <key> numogetle <key obj true|false>
- exch /Nums exch .treegetle
-} bind executeonly def
-
-/.treegetle { % <key> <leafkey> <tree> .treegetle <key obj true|false>
- dup /Kids knownoget {
- exch pop .branchgetle
- } {
- exch oget .leafgetle
- } ifelse
-} bind executeonly def
-
-/.branchgetle { % <key> <leafkey> <kids> .branchgetle <key obj true|false>
- dup length 0 eq {
- pop pop pop //false
- } {
- dup length -1 bitshift 2 copy oget
- dup /Limits oget aload pop
- % Stack: key leafkeyb kids mid kids[mid] min max
- 6 index ge {
- 5 index le {
- exch pop exch pop .treegetle
- } {
- pop 0 exch getinterval .branchgetle
- } ifelse
- } {
- pop 2 index length 2 index sub 1 gt {
- pop 1 index length 1 index sub getinterval .branchgetle
- } {
- exch pop exch pop .treegetle
- } ifelse
- } ifelse
- } ifelse
-} bind executeonly def
-
-/.leafgetle { % <key> <pairs> .leafget <obj|null>
- dup length 2 eq {
- dup 0 get
- 2 index le { exch pop aload pop //true } { pop pop //false } ifelse
- } {
- dup length -1 bitshift -2 and 2 copy oget
- % Stack: key pairs mid pairs[mid]
- 3 index gt { 0 exch } { 1 index length 1 index sub } ifelse
- getinterval .leafgetle
- } ifelse
-} bind executeonly def
-
-end % pdfdict
-.setglobal