% Copyright (C) 1994, 2000 Aladdin Enterprises. All rights reserved.% % This file is part of Aladdin Ghostscript.% % Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author% or distributor accepts any responsibility for the consequences of using it,% or for whether it serves any particular purpose or works at all, unless he% or she says so in writing. Refer to the Aladdin Ghostscript Free Public% License (the "License") for full details.% % Every copy of Aladdin Ghostscript must include a copy of the License,% normally in a plain ASCII text file named PUBLIC. The License grants you% the right to copy, modify and redistribute Aladdin Ghostscript, but only% under certain conditions described in the License. Among other things, the% License requires that the copyright notice and this notice be preserved on% all copies. % $Id: pdf_main.ps,v 1.2 2000/03/10 03:56:11 lpd Exp $% pdf_main.ps% PDF file- and page-level operations. /.setlanguagelevel where { pop 2 .setlanguagelevel } if.currentglobal true .setglobal/pdfdict where { pop } { /pdfdict 100 dict def } ifelsepdfdict begin % Patch in an obsolete variable used by some third-party software./#? false def % For simplicity, we use a single interpretation dictionary for all% PDF graphics execution, even though this is too liberal./pdfopdict mark objopdict { } forall drawopdict { } forall /endstream { exit } bind (%%EOF) cvn { exit } bind % for filters % PDF 1.1 operators /BX { /BXlevel BXlevel 1 add store } bind /EX { /BXlevel BXlevel 1 sub store } bind /PS { cvx exec } bind % PDF 1.2 operators /BMC { pop } bind /BDC { pop pop } bind /EMC { } /MP { pop } bind /DP { pop pop } bind.dicttomark readonly def % ======================== Main program ======================== % end % pdfdictuserdict begin /defaultfontname /Times-Roman def % Make sure the registered encodings are loaded, so we don't run the risk% that some of the indices for their names will overflow the packed% representation. (Yes, this is a hack.)SymbolEncoding popDingbatsEncoding pop % Redefine 'run' so it recognizes PDF files.systemdict begin/.runps /run load def/runpdfstring 50 string def % length is arbitrary/run { dup type /filetype ne { (r) file } if dup read { dup (%) 0 get eq { pop dup //runpdfstring % Some invalid files might have extra-long first lines.... { { readline } .internalstopped not { pop pop exit } if pop =string } loop //runpdfstring (PDF-) anchorsearch { pop pop runpdf } { pop cvx .runexec } ifelse } { 2 copy unread pop .runps } ifelse } { closefile } ifelse } bind odef/runpdf % <file> runpdf - { userdict begin /Page# null def /Page null def /DSCPageCount 0 def /PDFSave null def GS_PDF_ProcSet begin pdfdict begin pdfopen begin Trailer /Root oget /Pages oget /CropBox knownoget { mark /CropBox 3 -1 roll /PAGES pdfmark } if /FirstPage where { pop FirstPage } { 1 } ifelse 1 /LastPage where { pop LastPage } { pdfpagecount } ifelse QUIET not { (Processing pages ) print 2 index =only ( through ) print dup =only (.) = flush } if { dup /Page# exch store QUIET not { (Page ) print dup == flush } if pdfgetpage pdfshowpage } for currentdict pdfclose end % temporary dict end % pdfdict end % userdict } bind defend % systemdict% Redefine the procedure that the C code uses for running piped input.% It is OK to use { (%stdin) run } here, because a startjob cannot occur./.runstdin { { (%stdin) run } execute0} bind def end % userdictpdfdict begin % ======================== File parsing ======================== % % Read the cross-reference and trailer sections. /traileropdict mark (<<) cvn { mark } bind (>>) cvn /.dicttomark load ([) cvn { mark } bind % ditto (]) cvn dup load /true true /false false /null null /R { /resolveR cvx 3 packedarray cvx } bind % see Objects below /startxref /exit load.dicttomark readonly def % Because of EOL conversion, lines with fixed contents might be followed% by one or more blanks./lineeq % <filestr> <conststr> lineeq <bool> { anchorsearch { pop { ( ) anchorsearch not { () eq exit } if pop } loop } { pop false } ifelse } bind def/linene { lineeq not } bind def % Read (mostly scan) the cross-reference table./readxref % <pos> readxref <trailerdict> { PDFoffset add PDFfile exch setfileposition % In some PDF files, this position actually points to % white space before the xref line. Skip over this here. { PDFfile fileposition PDFfile read pop 32 gt { exit } if pop } loop PDFfile exch setfileposition PDFfile pdfstring readline pop (xref) linene { /readxref cvx /syntaxerror signalerror } if % Store the xref table entry position for each object. % We only need to read the run headers, not every entry. { PDFfile token pop % first object # or trailer dup /trailer eq { pop exit } if PDFfile pdfstring readline pop token pop % entry count exch pop exch % This section might be adding new objects: % ensure that Objects and Generations are big enough. % Stack: count obj# 2 copy add growPDFobjects PDFfile fileposition 3 -1 roll { Objects 2 index lget null eq % later update might have set it { Objects 2 index 2 index cvx lput } if exch 1 add exch 20 add } repeat PDFfile exch setfileposition pop } loop count /pdfemptycount exch def PDFfile traileropdict .pdfrun } bind def % Open a PDF file and read the header, trailer, and cross-reference./pdfopen % <file> pdfopen <dict> { pdfdict readonly pop % can't do it any earlier than this 15 dict begin /LocalResources 0 dict def /PSLevel1 where { pop } { /PSLevel1 false def } ifelse cvlit /PDFfile exch def /PDFsource PDFfile def PDFfile dup 0 setfileposition pdfstring readstring not {/pdfopen cvx /syntaxerror signalerror} if (%PDF-) search not {/pdfopen cvx /syntaxerror signalerror} if length /PDFoffset exch def pop cvr /PDFversion exch def findxref initPDFobjects % Read the last cross-reference table. readxref /Trailer exch def Trailer /Encrypt known { pdf_process_Encrypt % signal error } if % Read any previous cross-reference tables. Trailer { /Prev .knownget not { exit } if readxref } loop % Create and initialize some caches. /PageCount pdfpagecount def /PageNumbers PageCount dict def /PageIndex PageCount array def % Copy bookmarks (outline) to the output. Trailer /Root oget /Outlines knownoget { /First knownoget { { dup writeoutline /Next knownoget not { exit } if } loop } if } if currentdict end } bind def % Skip backward over the %%EOF at the end of the PDF file, and read% the preceding startxref line. We put this in a separate procedure so% we can offer the option of accepting certain invalid files that Acrobat% Reader also accepts.% ****** NOTE: this will be changed in a future release so that %%EO% ****** (missing the F), and startxref followed by a blank rather than% ****** an EOL, will no longer be accepted./findxref { % - findxref <xrefpos> PDFfile dup dup 0 setfileposition bytesavailable { % Scan backwards over trailing control-character garbage % (nulls, ^Zs, EOLs, blanks). 1 sub 2 copy setfileposition 1 index read pop 32 gt {exit} if } loop % Stack: file endpos % The top of the stack is now the file position of the last % non-garbage character. % We can't use prevline to check for the %%EOF, because if the % %%EOF isn't followed by an EOL, prevline will read past the % end of the file, and the file will get closed. % Acrobat apparently accepts files in which the %%EOF was % truncated to %%EO (!); we do the same. 5 sub 2 copy setfileposition 1 index (xxxxxx) readstring pop (\015%%EO) anchorsearch { pop pop } { (\012%%EO) anchorsearch { pop pop } { pop findxreferror } ifelse } ifelse 1 add setfileposition % Now read the startxref and xref start position. prevline token pop dup type /integertype eq { exch pop cvi % xref start position exch PDFfile exch setfileposition prevline (startxref) linene { findxreferror } if pop } { % else, this file has 'startxref #####' format (startxref) ne { findxreferror } if cvi % xref start position exch PDFfile exch setfileposition } ifelse} bind def/findxreferror { (\n) = ( **** The PDF input file appears to be corrupted, or not a PDF file.) = ( **** Try preceding the input file with lib/pdfeof.ps.) = ( **** If the file then is processed without error, please notify the) = ( **** author of the software that produced the PDF file that the file) = ( **** does not conform to Adobe's published PDF specification.) = (\n) = flush /pdfopen cvx /syntaxerror signalerror} bind def % Write the outline structure for a file. Uses linkdest (below)./writeoutline % <outlinedict> writeoutline - { mark 0 2 index /First knownoget { { exch 1 add exch /Next knownoget not { exit } if } loop } if % stack: dict mark count dup 0 eq { pop 1 index } { 2 index /Count knownoget { 0 lt { neg } if } if /Count exch 3 index } ifelse linkdest /Title oget /Title exch /OUT pdfmark /First knownoget { { dup writeoutline /Next knownoget not { exit } if } loop } if } bind def % Close a PDF file./pdfclose % <dict> pdfclose - { begin PDFfile closefile end } bind def % ======================== Page accessing ======================== % % Get a (possibly inherited) attribute of a page./pget % <pagedict> <key> pget <value> -true- % <pagedict> <key> pget -false- { 2 copy knownoget { exch pop exch pop true } { exch /Parent knownoget { exch pget } { pop false } ifelse } ifelse } bind def % Get the value of a resource on a given page./rget { % <resname> <pagedict> <restype> rget <value> -true- % <resname> <pagedict> <restype> rget -false- LocalResources 1 index knownoget { 3 index knownoget } { false } ifelse { exch pop exch pop exch pop true } { exch /Resources pget { exch knownoget { exch knownoget } { pop false } ifelse } { pop pop false } ifelse } ifelse} bind def % Get the total number of pages in the document./pdfpagecount % - pdfpagecount <int> { Trailer /Root oget /Pages oget /Count oget } bind def % Find the N'th page of the document by iterating through the Pages tree.% The first page is numbered 1./pdffindpage % <int> pdffindpage <pagedict> { dup Trailer /Root oget /Pages oget { % We should be able to tell when we reach a leaf % by finding a Type unequal to /Pages. Unfortunately, % some files distributed by Adobe lack the Type key % in some of the Pages nodes! Instead, we check for Kids. dup /Kids knownoget not { exit } if exch pop null 0 1 3 index length 1 sub { 2 index exch oget dup /Kids known { dup /Count oget } { 1 } ifelse % Stack: index kids null node count dup 5 index ge { pop exch pop exit } if 5 -1 roll exch sub 4 1 roll pop } for exch pop dup null eq { pop pop 1 null exit } if } loop % Stack: index countleft node 1 index 1 ne { pop pop /pdffindpage cvx /rangecheck signalerror } if exch pop PageIndex 2 index 1 sub 2 index put PageNumbers 1 index 3 index put exch pop } bind def % Find the N'th page of the document.% The first page is numbered 1./pdfgetpage % <int> pdfgetpage <pagedict> { PageIndex 1 index 1 sub get dup null ne { exch pop } { pop pdffindpage } ifelse } bind def % Find the page number of a page object (inverse of pdfgetpage)./pdfpagenumber % <pagedict> pdfpagenumber <int> { % We use the simplest and stupidest of all possible algorithms.... PageNumbers 1 index .knownget { exch pop } { 1 1 PageCount 1 add % will give a rangecheck if not found { dup pdfgetpage oforce 2 index eq { exit } if pop } for exch pop } ifelse } bind def % Display a given page./boxrect % [<llx> <lly> <urx> <ury>] boxrect <x> <y> <w> <h> { aload pop exch 3 index sub exch 2 index sub } bind def/resolvedest { % <name|string|other> resolvedest <other|null> dup type /nametype eq { Trailer /Root oget /Dests knownoget { exch knownoget not { null } if } { null } ifelse } { dup type /stringtype eq { Trailer /Root oget /Names knownoget { /Dests knownoget { exch nameoget } { pop null } ifelse } { pop null } ifelse } if } ifelse} bind def/linkdest { % <link|outline> linkdest % ([/Page <n>] /View <view> | ) <link|outline> dup /Dest knownoget { resolvedest dup type /dicttype eq { /D knownoget not { null } if } if dup null eq { pop } { dup 0 oget dup null eq { pop } { dup type /integertype ne { pdfpagenumber } if /Page exch 4 -2 roll } ifelse dup length 1 sub 1 exch getinterval /View exch 3 -1 roll } ifelse } if} bind def% <pagedict> mark ... -proc- -/namedactions 8 dict dup begin /FirstPage { /Page 1 3 -1 roll } def /LastPage { counttomark 2 add index pdfpagecount /Page exch 3 -1 roll } def /NextPage { counttomark 2 add index pdfpagenumber 1 add /Page exch 3 -1 roll } def /PrevPage { counttomark 2 add index pdfpagenumber 1 sub /Page exch 3 -1 roll } defend readonly def% <pagedict> <annotdict> -proc- -/annottypes 5 dict dup begin /Text { mark exch { /Rect /Open /Contents } { 2 copy knownoget { 3 -1 roll } { pop } ifelse } forall pop /ANN pdfmark } bind def /Link { mark exch { /Rect /Border } { 2 copy knownoget { 3 -1 roll } { pop } ifelse } forall dup /A knownoget { dup /D knownoget { exch pop exch dup length dict copy dup /Dest 4 -1 roll put } { /N knownoget { % Assume /S /Named namedactions exch .knownget { exec } if } if } ifelse } if linkdest pop /LNK pdfmark } bind defend readonly def /pdfshowpage % <pagedict> pdfshowpage - { dup /Page exch store pdfshowpage_init pdfshowpage_setpage save /PDFSave exch store (before exec) VMDEBUG pdfshowpage_finish (after exec) VMDEBUG PDFSave restore } bind def /pdfpagecontents % <pagedict> pdfpagecontents <contents> { } bind def /pdfshowpage_init % <pagedict> pdfshowpage_init <pagedict> { /DSCPageCount DSCPageCount 1 add store } bind def /.pdfshowpage_Install { % <tx> <ty> [<prevproc>] .pdfshowpage_Install - 3 1 roll translate 0 get exec} bind def /pdfshowpage_setpage { % <pagedict> pdfshowpage_setpage <pagedict> 4 dict begin % for setpagedeviceLines 1–500 of 586. Load more
% Copyright (C) 1994, 2000 Aladdin Enterprises. All rights reserved. % % This file is part of Aladdin Ghostscript. % % Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author % or distributor accepts any responsibility for the consequences of using it, % or for whether it serves any particular purpose or works at all, unless he % or she says so in writing. Refer to the Aladdin Ghostscript Free Public % License (the "License") for full details. % % Every copy of Aladdin Ghostscript must include a copy of the License, % normally in a plain ASCII text file named PUBLIC. The License grants you % the right to copy, modify and redistribute Aladdin Ghostscript, but only % under certain conditions described in the License. Among other things, the % License requires that the copyright notice and this notice be preserved on % all copies. % $Id: pdf_main.ps,v 1.2 2000/03/10 03:56:11 lpd Exp $ % pdf_main.ps % PDF file- and page-level operations. /.setlanguagelevel where { pop 2 .setlanguagelevel } if .currentglobal true .setglobal /pdfdict where { pop } { /pdfdict 100 dict def } ifelse pdfdict begin % Patch in an obsolete variable used by some third-party software. /#? false def % For simplicity, we use a single interpretation dictionary for all % PDF graphics execution, even though this is too liberal. /pdfopdict mark objopdict { } forall drawopdict { } forall /endstream { exit } bind (%%EOF) cvn { exit } bind % for filters % PDF 1.1 operators /BX { /BXlevel BXlevel 1 add store } bind /EX { /BXlevel BXlevel 1 sub store } bind /PS { cvx exec } bind % PDF 1.2 operators /BMC { pop } bind /BDC { pop pop } bind /EMC { } /MP { pop } bind /DP { pop pop } bind .dicttomark readonly def % ======================== Main program ======================== % end % pdfdict userdict begin /defaultfontname /Times-Roman def % Make sure the registered encodings are loaded, so we don't run the risk % that some of the indices for their names will overflow the packed % representation. (Yes, this is a hack.) SymbolEncoding pop DingbatsEncoding pop % Redefine 'run' so it recognizes PDF files. systemdict begin /.runps /run load def /runpdfstring 50 string def % length is arbitrary /run { dup type /filetype ne { (r) file } if dup read { dup (%) 0 get eq { pop dup //runpdfstring % Some invalid files might have extra-long first lines.... { { readline } .internalstopped not { pop pop exit } if pop =string } loop //runpdfstring (PDF-) anchorsearch { pop pop runpdf } { pop cvx .runexec } ifelse } { 2 copy unread pop .runps } ifelse } { closefile } ifelse } bind odef /runpdf % <file> runpdf - { userdict begin /Page# null def /Page null def /DSCPageCount 0 def /PDFSave null def GS_PDF_ProcSet begin pdfdict begin pdfopen begin Trailer /Root oget /Pages oget /CropBox knownoget { mark /CropBox 3 -1 roll /PAGES pdfmark } if /FirstPage where { pop FirstPage } { 1 } ifelse 1 /LastPage where { pop LastPage } { pdfpagecount } ifelse QUIET not { (Processing pages ) print 2 index =only ( through ) print dup =only (.) = flush } if { dup /Page# exch store QUIET not { (Page ) print dup == flush } if pdfgetpage pdfshowpage } for currentdict pdfclose end % temporary dict end % pdfdict end % userdict } bind def end % systemdict % Redefine the procedure that the C code uses for running piped input. % It is OK to use { (%stdin) run } here, because a startjob cannot occur. /.runstdin { { (%stdin) run } execute0 } bind def end % userdict pdfdict begin % ======================== File parsing ======================== % % Read the cross-reference and trailer sections. /traileropdict mark (<<) cvn { mark } bind (>>) cvn /.dicttomark load ([) cvn { mark } bind % ditto (]) cvn dup load /true true /false false /null null /R { /resolveR cvx 3 packedarray cvx } bind % see Objects below /startxref /exit load .dicttomark readonly def % Because of EOL conversion, lines with fixed contents might be followed % by one or more blanks. /lineeq % <filestr> <conststr> lineeq <bool> { anchorsearch { pop { ( ) anchorsearch not { () eq exit } if pop } loop } { pop false } ifelse } bind def /linene { lineeq not } bind def % Read (mostly scan) the cross-reference table. /readxref % <pos> readxref <trailerdict> { PDFoffset add PDFfile exch setfileposition % In some PDF files, this position actually points to % white space before the xref line. Skip over this here. { PDFfile fileposition PDFfile read pop 32 gt { exit } if pop } loop PDFfile exch setfileposition PDFfile pdfstring readline pop (xref) linene { /readxref cvx /syntaxerror signalerror } if % Store the xref table entry position for each object. % We only need to read the run headers, not every entry. { PDFfile token pop % first object # or trailer dup /trailer eq { pop exit } if PDFfile pdfstring readline pop token pop % entry count exch pop exch % This section might be adding new objects: % ensure that Objects and Generations are big enough. % Stack: count obj# 2 copy add growPDFobjects PDFfile fileposition 3 -1 roll { Objects 2 index lget null eq % later update might have set it { Objects 2 index 2 index cvx lput } if exch 1 add exch 20 add } repeat PDFfile exch setfileposition pop } loop count /pdfemptycount exch def PDFfile traileropdict .pdfrun } bind def % Open a PDF file and read the header, trailer, and cross-reference. /pdfopen % <file> pdfopen <dict> { pdfdict readonly pop % can't do it any earlier than this 15 dict begin /LocalResources 0 dict def /PSLevel1 where { pop } { /PSLevel1 false def } ifelse cvlit /PDFfile exch def /PDFsource PDFfile def PDFfile dup 0 setfileposition pdfstring readstring not {/pdfopen cvx /syntaxerror signalerror} if (%PDF-) search not {/pdfopen cvx /syntaxerror signalerror} if length /PDFoffset exch def pop cvr /PDFversion exch def findxref initPDFobjects % Read the last cross-reference table. readxref /Trailer exch def Trailer /Encrypt known { pdf_process_Encrypt % signal error } if % Read any previous cross-reference tables. Trailer { /Prev .knownget not { exit } if readxref } loop % Create and initialize some caches. /PageCount pdfpagecount def /PageNumbers PageCount dict def /PageIndex PageCount array def % Copy bookmarks (outline) to the output. Trailer /Root oget /Outlines knownoget { /First knownoget { { dup writeoutline /Next knownoget not { exit } if } loop } if } if currentdict end } bind def % Skip backward over the %%EOF at the end of the PDF file, and read % the preceding startxref line. We put this in a separate procedure so % we can offer the option of accepting certain invalid files that Acrobat % Reader also accepts. % ****** NOTE: this will be changed in a future release so that %%EO % ****** (missing the F), and startxref followed by a blank rather than % ****** an EOL, will no longer be accepted. /findxref { % - findxref <xrefpos> PDFfile dup dup 0 setfileposition bytesavailable { % Scan backwards over trailing control-character garbage % (nulls, ^Zs, EOLs, blanks). 1 sub 2 copy setfileposition 1 index read pop 32 gt {exit} if } loop % Stack: file endpos % The top of the stack is now the file position of the last % non-garbage character. % We can't use prevline to check for the %%EOF, because if the % %%EOF isn't followed by an EOL, prevline will read past the % end of the file, and the file will get closed. % Acrobat apparently accepts files in which the %%EOF was % truncated to %%EO (!); we do the same. 5 sub 2 copy setfileposition 1 index (xxxxxx) readstring pop (\015%%EO) anchorsearch { pop pop } { (\012%%EO) anchorsearch { pop pop } { pop findxreferror } ifelse } ifelse 1 add setfileposition % Now read the startxref and xref start position. prevline token pop dup type /integertype eq { exch pop cvi % xref start position exch PDFfile exch setfileposition prevline (startxref) linene { findxreferror } if pop } { % else, this file has 'startxref #####' format (startxref) ne { findxreferror } if cvi % xref start position exch PDFfile exch setfileposition } ifelse } bind def /findxreferror { (\n) = ( **** The PDF input file appears to be corrupted, or not a PDF file.) = ( **** Try preceding the input file with lib/pdfeof.ps.) = ( **** If the file then is processed without error, please notify the) = ( **** author of the software that produced the PDF file that the file) = ( **** does not conform to Adobe's published PDF specification.) = (\n) = flush /pdfopen cvx /syntaxerror signalerror } bind def % Write the outline structure for a file. Uses linkdest (below). /writeoutline % <outlinedict> writeoutline - { mark 0 2 index /First knownoget { { exch 1 add exch /Next knownoget not { exit } if } loop } if % stack: dict mark count dup 0 eq { pop 1 index } { 2 index /Count knownoget { 0 lt { neg } if } if /Count exch 3 index } ifelse linkdest /Title oget /Title exch /OUT pdfmark /First knownoget { { dup writeoutline /Next knownoget not { exit } if } loop } if } bind def % Close a PDF file. /pdfclose % <dict> pdfclose - { begin PDFfile closefile end } bind def % ======================== Page accessing ======================== % % Get a (possibly inherited) attribute of a page. /pget % <pagedict> <key> pget <value> -true- % <pagedict> <key> pget -false- { 2 copy knownoget { exch pop exch pop true } { exch /Parent knownoget { exch pget } { pop false } ifelse } ifelse } bind def % Get the value of a resource on a given page. /rget { % <resname> <pagedict> <restype> rget <value> -true- % <resname> <pagedict> <restype> rget -false- LocalResources 1 index knownoget { 3 index knownoget } { false } ifelse { exch pop exch pop exch pop true } { exch /Resources pget { exch knownoget { exch knownoget } { pop false } ifelse } { pop pop false } ifelse } ifelse } bind def % Get the total number of pages in the document. /pdfpagecount % - pdfpagecount <int> { Trailer /Root oget /Pages oget /Count oget } bind def % Find the N'th page of the document by iterating through the Pages tree. % The first page is numbered 1. /pdffindpage % <int> pdffindpage <pagedict> { dup Trailer /Root oget /Pages oget { % We should be able to tell when we reach a leaf % by finding a Type unequal to /Pages. Unfortunately, % some files distributed by Adobe lack the Type key % in some of the Pages nodes! Instead, we check for Kids. dup /Kids knownoget not { exit } if exch pop null 0 1 3 index length 1 sub { 2 index exch oget dup /Kids known { dup /Count oget } { 1 } ifelse % Stack: index kids null node count dup 5 index ge { pop exch pop exit } if 5 -1 roll exch sub 4 1 roll pop } for exch pop dup null eq { pop pop 1 null exit } if } loop % Stack: index countleft node 1 index 1 ne { pop pop /pdffindpage cvx /rangecheck signalerror } if exch pop PageIndex 2 index 1 sub 2 index put PageNumbers 1 index 3 index put exch pop } bind def % Find the N'th page of the document. % The first page is numbered 1. /pdfgetpage % <int> pdfgetpage <pagedict> { PageIndex 1 index 1 sub get dup null ne { exch pop } { pop pdffindpage } ifelse } bind def % Find the page number of a page object (inverse of pdfgetpage). /pdfpagenumber % <pagedict> pdfpagenumber <int> { % We use the simplest and stupidest of all possible algorithms.... PageNumbers 1 index .knownget { exch pop } { 1 1 PageCount 1 add % will give a rangecheck if not found { dup pdfgetpage oforce 2 index eq { exit } if pop } for exch pop } ifelse } bind def % Display a given page. /boxrect % [<llx> <lly> <urx> <ury>] boxrect <x> <y> <w> <h> { aload pop exch 3 index sub exch 2 index sub } bind def /resolvedest { % <name|string|other> resolvedest <other|null> dup type /nametype eq { Trailer /Root oget /Dests knownoget { exch knownoget not { null } if } { null } ifelse } { dup type /stringtype eq { Trailer /Root oget /Names knownoget { /Dests knownoget { exch nameoget } { pop null } ifelse } { pop null } ifelse } if } ifelse } bind def /linkdest { % <link|outline> linkdest % ([/Page <n>] /View <view> | ) <link|outline> dup /Dest knownoget { resolvedest dup type /dicttype eq { /D knownoget not { null } if } if dup null eq { pop } { dup 0 oget dup null eq { pop } { dup type /integertype ne { pdfpagenumber } if /Page exch 4 -2 roll } ifelse dup length 1 sub 1 exch getinterval /View exch 3 -1 roll } ifelse } if } bind def % <pagedict> mark ... -proc- - /namedactions 8 dict dup begin /FirstPage { /Page 1 3 -1 roll } def /LastPage { counttomark 2 add index pdfpagecount /Page exch 3 -1 roll } def /NextPage { counttomark 2 add index pdfpagenumber 1 add /Page exch 3 -1 roll } def /PrevPage { counttomark 2 add index pdfpagenumber 1 sub /Page exch 3 -1 roll } def end readonly def % <pagedict> <annotdict> -proc- - /annottypes 5 dict dup begin /Text { mark exch { /Rect /Open /Contents } { 2 copy knownoget { 3 -1 roll } { pop } ifelse } forall pop /ANN pdfmark } bind def /Link { mark exch { /Rect /Border } { 2 copy knownoget { 3 -1 roll } { pop } ifelse } forall dup /A knownoget { dup /D knownoget { exch pop exch dup length dict copy dup /Dest 4 -1 roll put } { /N knownoget { % Assume /S /Named namedactions exch .knownget { exec } if } if } ifelse } if linkdest pop /LNK pdfmark } bind def end readonly def /pdfshowpage % <pagedict> pdfshowpage - { dup /Page exch store pdfshowpage_init pdfshowpage_setpage save /PDFSave exch store (before exec) VMDEBUG pdfshowpage_finish (after exec) VMDEBUG PDFSave restore } bind def /pdfpagecontents % <pagedict> pdfpagecontents <contents> { } bind def /pdfshowpage_init % <pagedict> pdfshowpage_init <pagedict> { /DSCPageCount DSCPageCount 1 add store } bind def /.pdfshowpage_Install { % <tx> <ty> [<prevproc>] .pdfshowpage_Install - 3 1 roll translate 0 get exec } bind def /pdfshowpage_setpage { % <pagedict> pdfshowpage_setpage <pagedict> 4 dict begin % for setpagedevice