home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / share / gs-esp / 8.15 / lib / pdf_main.ps < prev    next >
Encoding:
Text File  |  2006-07-06  |  34.0 KB  |  1,081 lines

  1. %    Copyright (C) 1994, 2000 Aladdin Enterprises.  All rights reserved.
  2. % This software is provided AS-IS with no warranty, either express or
  3. % implied.
  4. % This software is distributed under license and may not be copied,
  5. % modified or distributed except as expressly authorized under the terms
  6. % of the license contained in the file LICENSE in this distribution.
  7. % For more information about licensing, please refer to
  8. % http://www.ghostscript.com/licensing/. For information on
  9. % commercial licensing, go to http://www.artifex.com/licensing/ or
  10. % contact Artifex Software, Inc., 101 Lucas Valley Road #110,
  11. % San Rafael, CA  94903, U.S.A., +1(415)492-9861.
  12.  
  13. % $Id: pdf_main.ps,v 1.71.2.7 2005/03/16 23:05:47 alexcher Exp $
  14. % pdf_main.ps
  15. % PDF file- and page-level operations.
  16.  
  17. /.setlanguagelevel where { pop 2 .setlanguagelevel } if
  18. .currentglobal true .setglobal
  19. /pdfdict where { pop } { /pdfdict 100 dict def } ifelse
  20. pdfdict begin
  21.  
  22. % Patch in an obsolete variable used by some third-party software.
  23. /#? false def
  24.  
  25. % Test whether the current output device handles pdfmark.
  26. /.writepdfmarkdict 1 dict dup /pdfmark null put readonly def
  27. /.writepdfmarks {    % - .writepdfmarks <bool>
  28.   currentdevice //.writepdfmarkdict .getdeviceparams
  29.   mark eq { false } { pop pop true } ifelse
  30.   systemdict /DOPDFMARKS known or 
  31. } bind def
  32.  
  33. % For simplicity, we use a single interpretation dictionary for all
  34. % PDF graphics execution, even though this is too liberal.
  35. /pdfopdict mark
  36.   objopdict { } forall
  37.   drawopdict { } forall
  38.   /endstream { exit } bind
  39.   (%%EOF) cvn { exit } bind        % for filters
  40.     % PDF 1.1 operators
  41.   /BX { /BXlevel BXlevel 1 add store } bind
  42.   /EX { /BXlevel BXlevel 1 sub store } bind
  43.   /PS { cvx exec } bind
  44.     % PDF 1.2 operators
  45.   /BMC { pop } bind
  46.   /BDC { pop pop } bind
  47.   /EMC { }
  48.   /MP { pop } bind
  49.   /DP { pop pop } bind
  50. .dicttomark readonly def
  51.  
  52. % ======================== Main program ======================== %
  53.  
  54. end            % pdfdict
  55. userdict begin
  56.  
  57. /defaultfontname /Times-Roman def
  58.  
  59. % Make sure the registered encodings are loaded, so we don't run the risk
  60. % that some of the indices for their names will overflow the packed
  61. % representation.  (Yes, this is a hack.)
  62. SymbolEncoding pop
  63. DingbatsEncoding pop
  64.  
  65. % Redefine 'run' so it recognizes PDF files.
  66. systemdict begin
  67. /.runps /run load def
  68. /run {
  69.   dup type /filetype ne { (r) file } if
  70.   dup ( ) .peekstring {
  71.     (%) eq {
  72.       dup (     ) .peekstring {
  73.     (%PDF-) eq {
  74.         dup (%stdin) (r) file eq {
  75.           % Copy PDF from stdin to temporary file then run it.
  76.           null (w+) //systemdict /.tempfile get exec exch 3 1 roll
  77.           % stack: tempname stdin tempfile
  78.           64000 string
  79.           {
  80.         % stack: tempname stdin tempfile string
  81.         2 index 1 index readstring
  82.         exch 3 index exch writestring
  83.         not { exit } if
  84.           }
  85.           loop
  86.           pop exch closefile
  87.           % stack: tempname tempfile
  88.           dup 0 setfileposition
  89.           dup runpdf
  90.           closefile deletefile
  91.         } {
  92.           runpdf
  93.         } ifelse
  94.       } {
  95.         cvx .runps % doesn't start with %PDF-
  96.       } ifelse
  97.     } {
  98.       pop cvx .runps % didn't read 5 characters
  99.     } ifelse
  100.     } {
  101.       cvx .runps % didn't start with %
  102.     } ifelse
  103.   } {
  104.     pop closefile % file was empty
  105.   } ifelse
  106. } bind odef
  107. currentdict /runpdfstring .undef
  108.  
  109.  
  110. /runpdfbegin {        % <file> runpdf -
  111.    userdict begin
  112.     % It turns out that the PDF interpreter uses memory more
  113.     % effectively if it is run under at least one level of save.
  114.     % This is counter-intuitive, and we don't understand why it happens,
  115.     % but the improvement is significant.
  116.    /PDFTopSave save def
  117.    0 setobjectformat
  118.    /Page# null def
  119.    /Page null def
  120.    /DSCPageCount 0 def
  121.    /PDFSave null def
  122.    GS_PDF_ProcSet begin
  123.    pdfdict begin
  124.    pdfopen begin
  125.    Trailer /Root oget /Pages oget /CropBox knownoget
  126.     { oforce_array mark /CropBox 3 -1 roll /PAGES pdfmark
  127.     }
  128.    if
  129.    /FirstPage where 
  130.     { pop FirstPage dup pdfpagecount gt
  131.       { (\nRequested FirstPage is greater than the number of pages in the file: ) print
  132.         pdfpagecount = flush
  133.       } if
  134.     } {
  135.       1
  136.     } ifelse
  137.    /LastPage where { pop LastPage pdfpagecount .min } { pdfpagecount } ifelse
  138.    1 index 1 index gt
  139.     { (   No pages will be processed \(FirstPage > LastPage\).) = flush }
  140.     { QUIET not
  141.       { (Processing pages ) print 1 index =only ( through ) print dup =only
  142.         (.) = flush
  143.       }
  144.      if
  145.     }
  146.    ifelse
  147. } bind def
  148.  
  149. /dopdfpages {   % firstpage# lastpage# dopdfpages -
  150.   << /PDFScanRules true >> setuserparams    % set scanning rules for PDF vs. PS
  151.   1 exch
  152.     { dup /Page# exch store
  153.       QUIET not { (Page ) print dup == flush } if
  154.       pdfgetpage pdfshowpage
  155.     } for
  156.   << /PDFScanRules null >> setuserparams    % restore scanning rules for PS
  157. } bind def
  158.  
  159. /runpdfend {
  160.    Repaired { printrepaired } if
  161.    currentdict pdfclose
  162.    end            % temporary dict
  163.    end            % pdfdict
  164.    end            % GS_PDF_ProcSet
  165.    PDFTopSave restore
  166.    end            % userdict
  167. } bind def
  168.  
  169. /runpdf {        % <file> runpdf -
  170.   runpdfbegin
  171.   dopdfpages
  172.   runpdfend
  173. } bind def
  174.  
  175. end            % systemdict
  176. % Redefine the procedure that the C code uses for running piped input.
  177. % It is OK to use { (%stdin) run } here, because a startjob cannot occur.
  178. /.runstdin {
  179.   { (%stdin) run } execute0
  180. } bind def
  181.  
  182. end            % userdict
  183. pdfdict begin
  184.  
  185. % ======================== File parsing ======================== %
  186.  
  187. % Read the cross-reference and trailer sections.
  188.  
  189. /traileropdict mark
  190.   (<<) cvn { mark } bind
  191.   (>>) cvn { { .dicttomark } stopped {
  192.           (   **** File has unbalanced >> in trailer.\n) pdfformaterror
  193.              } if } bind
  194.   ([) cvn { mark } bind        % ditto
  195.   (]) cvn dup load
  196. %  /true true        % see .pdfexectoken in pdf_base.ps
  197. %  /false false        % ibid.
  198. %  /null null        % ibid.
  199.   /R { /resolveR cvx 3 packedarray cvx } bind    % see Objects below
  200.   /startxref /exit load
  201. .dicttomark readonly def
  202.  
  203. % Because of EOL conversion, lines with fixed contents might be followed
  204. % by one or more blanks.
  205. /lineeq            % <filestr> <conststr> lineeq <bool>
  206.  { anchorsearch
  207.     { pop { ( ) anchorsearch not { () eq exit } if pop } loop }
  208.     { pop false }
  209.    ifelse
  210.  } bind def
  211. /linene { lineeq not } bind def
  212.  
  213. % Read the cross-reference table.
  214. /readxref        % <pos> readxref <trailerdict>
  215.  {
  216.    PDFoffset add PDFfile exch setfileposition
  217.         % In some PDF files, this position actually points to
  218.         % white space before the xref line.  Skip over this here.
  219.    { PDFfile fileposition PDFfile read pop 32 gt { exit } if pop
  220.    } loop
  221.    PDFfile exch setfileposition
  222.    0        % Initialize xref table error counter
  223.  
  224.         % The PDF specification says that the 'xref' must be on a line
  225.         % by itself. The code here formerly used readline and linene to
  226.         % check this. However, Acrobat Reader only requires the line to
  227.         % begin with 'xref', and there are enough applications producing
  228.         % non-compliant PDF files that we have to do this too.
  229.    PDFfile pdfstring 0 4 getinterval readstring pop
  230.    (xref) ne { /readxref cvx /syntaxerror signalerror } if
  231.         % Store the xref table entry position for each object.
  232.    { PDFfile token pop        % first object # or trailer
  233.      dup /trailer eq { pop exit } if
  234.      PDFfile pdfstring readline pop
  235.      token pop            % entry count
  236.      exch pop            % remove last
  237.         % This section might be adding new objects:
  238.         % ensure that Objects and Generations are big enough.
  239.         % stack: <err count> <first obj> <entry count>
  240.      2 copy add growPDFobjects
  241.      PDFfile fileposition
  242.      3 1 roll            % stack: <err count> <filepos> <first obj> <entry count>
  243.      {                % stack: <err count> <file pos> <obj num>
  244.         % Read xref line
  245.        PDFfile pdfstring readline pop  
  246.        token pop        % object position
  247.        exch token pop        % generation #
  248.        exch token pop        % n or f
  249.        exch pop            % Stack: <err count> <file pos> <obj#> <loc> <gen#> <tag>
  250.        dup /n eq {        % xref line tag is /n
  251.      pop            % pop dup of line tag
  252.          Objects 3 index lget null eq {    % later update might have set it
  253.        setxrefentry
  254.          } if
  255.        }
  256.        {            % xref line tag was not /n
  257.      /f ne            % verify that the tag was /f
  258.          { /setxrefentry cvx /syntaxerror signalerror
  259.      } if
  260.        } ifelse
  261.        pop pop            % pop <obj location> and <gen num>
  262.         % Check if line length is 20 chars (Adobe spec.)
  263.        exch            % stack: <err count> <obj num> <file pos>
  264.        PDFfile fileposition    % <err count> <obj#> <old pos> <new pos>
  265.        dup 4 1 roll        % <err count> <new Pos> <obj#> <old pos> <new pos>
  266.        exch sub 20 ne        % <err count> <new Pos> <obj#> <bool>
  267.        { 3 -1 roll 1 add 3 1 roll % Increment error count
  268.        } if
  269.        1 add            % increment object number
  270.      } repeat
  271.      pop pop            % pop <file pos> <obj #>
  272.    } loop
  273.    0 ne {
  274.      (   **** Warning:  length of some xref entries is not equal to 20 bytes.\n)
  275.      pdfformaterror
  276.    } if
  277.    PDFfile traileropdict .pdfrun
  278.  } bind def
  279.  
  280. % Open a PDF file and read the header, trailer, and cross-reference.
  281. /pdfopen {        % <file> pdfopen <dict>
  282.     % Color space substitution in PDF is handled somewhat differently
  283.     % than in PostScript. A given device color space will be substituted
  284.     % if the corresponding "Default..." entry exists in the Page's
  285.     % Resource dictionary (which might be inhereted); there is no
  286.     % UseCIEColor to enable/disable color mapping.
  287.     %
  288.     % This behavior is achieved by always setting UseCIEColor to true
  289.     % in the page device dictionary. If the value of this parameter was
  290.     % originally false (i.e.: the output device does not perform color
  291.     % space substitution by default), the instances DefaultGray,
  292.     % DefaultRGB, and DefaultCMYK of the (local) ColorSpace category
  293.     % are redefined to be DeviceGray, DeviceRGB, and DeviceCMYK,
  294.     % respectively. This is not done if UseCIEColor is true by default,
  295.     % as in that case color substitution is presumably desired even
  296.     % if the file does not request it.
  297.    currentpagedevice /UseCIEColor .knownget dup { pop } if not
  298.     { .currentglobal false .setglobal
  299.       /DefaultGray { /DeviceGray } cvlit /ColorSpace defineresource pop
  300.       /DefaultRGB { /DeviceRGB } cvlit /ColorSpace defineresource pop
  301.       /DefaultCMYK { /DeviceCMYK } cvlit /ColorSpace defineresource pop
  302.       .setglobal
  303.     }
  304.    if
  305.   pdfopenfile begin
  306.   pdfopencache
  307.   .writepdfmarks {
  308.     % Copy bookmarks (outline) to the output.
  309.     Trailer /Root oget /Outlines knownoget {
  310.       /First knownoget {
  311.     { dup writeoutline /Next knownoget not { exit } if } loop
  312.       } if
  313.     } if
  314.   } if        % end .writepdfmarks
  315.   currentdict end
  316. } bind def
  317.  
  318. /pdfopencache {        % - pdfopencache -
  319.     % Create and initialize some caches.
  320.   /PageCount pdfpagecount def
  321.   /PageNumbers PageCount 65534 .min dict def
  322.   /PageIndex PageCount 65534 .min array def
  323. } bind def
  324.  
  325. /pdfopenfile {        % <file> pdfopenfile <dict>
  326.    pdfdict readonly pop        % can't do it any earlier than this
  327.    15 dict begin
  328.    /LocalResources 0 dict def
  329.    /DefaultQstate //null def    % establish binding
  330.    /Printed where { pop } {
  331.         % Guess whether the output device is a printer.
  332.      /Printed currentpagedevice /OutputFile known def
  333.    } ifelse
  334.    /PSLevel1 where { pop } { /PSLevel1 false def } ifelse
  335.    % NB: PDFfile is used outside of the PDF code to determine that a
  336.    % PDF job is being processed; to not change or hide this key.
  337.    cvlit /PDFfile exch def
  338.    /PDFsource PDFfile def
  339.    /Repaired false def
  340.    PDFfile dup 0 setfileposition pdfstring readstring 
  341.    not {/pdfopen cvx /syntaxerror signalerror} if
  342.    (%PDF-) search not {/pdfopen cvx /syntaxerror signalerror} if
  343.    length /PDFoffset exch def pop cvr /PDFversion exch def
  344.     % Read the last cross-reference table.
  345.    count /pdfemptycount exch def
  346.    /Trailer << >> def        % Initialize to an emptry dict.
  347.    { initPDFobjects findxref readxref } .internalstopped {
  348.         % Read failed.  Attempt to recover xref data.
  349.      print_xref_warning 
  350.      count pdfemptycount sub { pop } repeat % remove anything left by readxref
  351.      search_objects
  352.      search_trailer
  353.    } { /Trailer exch def
  354.     % Read any previous cross-reference tables.
  355.      Trailer
  356.      { /Prev knownoget not { exit } if
  357.        { readxref } .internalstopped {
  358.          % Read failed.  Attempt to recover xref data.
  359.          print_xref_warning
  360.          count pdfemptycount sub { pop } repeat    % remove anything left by readxref
  361.      search_objects
  362.          search_trailer
  363.      exit
  364.        } if
  365.        % The PDF spec. says that each trailer dict should contain the required
  366.        % entries.  However we have seen a PDF file that only has a Prev entry in
  367.        % the initial trailer dict.  Acrobat complains but it accepts these files.
  368.        % To work with these files, we are copying any entries which we find in
  369.        % a previous trailer dict which are not present in the initial dict.
  370.        dup {
  371.          Trailer 2 index known {
  372.            pop pop              % discard if key already present
  373.          } {
  374.            Trailer 3 1 roll put % add key if not present
  375.          } ifelse
  376.        } forall
  377.      } loop
  378.    } ifelse
  379.    Trailer /Encrypt knownoget {
  380.      pop
  381.      pdf_process_Encrypt    % signal error
  382.    } if
  383.    currentdict end
  384.  } bind def
  385.  
  386. % Look for [\r\n]%%EO from the current position of the file.
  387. % Return the position of %%EO if found or -1 .
  388. /findeof {  % <file> find_eof <file> <position>
  389.   -1 exch
  390.   {
  391.     dup bytesavailable 4 lt { exit } if
  392.     dup 0 (%%EO) /SubFileDecode filter flushfile
  393.     dup dup fileposition 5 sub setfileposition
  394.     dup 5 string readstring not { pop exit } if
  395.     dup (\r%%EO) eq exch (\n%%EO) eq or {
  396.       dup fileposition 4 sub
  397.       3 1 roll exch pop
  398.     } if
  399.   } loop
  400.   exch
  401. } bind def
  402.  
  403. % Skip backward over the %%EOF at the end of the PDF file, and read
  404. % the preceding startxref line.  The PDF specification unambiguously
  405. % requires that the %%EOF appear on a line by itself, and that the
  406. % startxref and the following position value appear on separate lines;
  407. % however, some applications truncate the %%EOF to %%EO, and/or put the
  408. % startxref and the following value on the same line.
  409. % There seems to be no limit on the amount of garbage that can be
  410. % appended to the PDF file. Current record (60K) belongs to
  411. % PDF-Out (v 2.0 - 35). We start the search for %%EO from the last 1024
  412. % bytes and continue from the beginning of the file.
  413. /findxref {        % - findxref <xrefpos>
  414.   PDFfile dup dup dup 0 setfileposition bytesavailable
  415.   dup /PDFfilelen exch def
  416.     % Find the last %%EOF string (within 1024 bytes)
  417.   1024 sub PDFoffset .max
  418.   setfileposition findeof                  % search the last 1024 bytes
  419.   dup 0 le {
  420.     pop
  421.     dup PDFoffset setfileposition findeof  % search from the beginnibg
  422.     dup 0 le {
  423.        (ERROR: Cannot find a %%EOF marker anywhere in the file.\n)
  424.        pdfformaterror
  425.        /findxref cvx /syntaxerror signalerror
  426.     } if
  427.   } if
  428.   dup 3 1 roll setfileposition
  429.     % Stack: eofpos
  430.     % Check for whether this is, in fact, a valid PDF file.
  431.   dup PDFfilelen exch sub dup dup 7 gt exch 5 lt or {
  432.     pop true
  433.   } {
  434.     string PDFfile exch readstring pop
  435.     dup (%%EOF\n) eq exch dup (%%EOF\r) eq
  436.     exch dup (%%EOF\r\n) eq exch (%%EOF) eq or or or not
  437.   } ifelse {
  438.     (   **** Warning: File has a corrupted %%EOF marker, or garbage after %%EOF.\n)
  439.     pdfformaterror
  440.   } if
  441.   PDFfile exch setfileposition
  442.     % Now read the startxref and xref start position.
  443.   prevline token not { null } if dup type /integertype eq {
  444.     exch pop cvi        % xref start position
  445.     exch PDFfile exch setfileposition
  446.     prevline dup (startxref) linene {
  447.       % startxref not on a line by itself.  We have found PDF from
  448.       % www.verypdf.com in which the startxref was on the same line as
  449.       % the end of trailer dictionary.  Check for this.  Note:  This
  450.       % violates the spec.
  451.       dup (startxref) search {
  452.     % found startxref - print warning
  453.     pop pop pop             % clear strings from search
  454.         (   **** Warning: format of the startxref line in this file is invalid.\n)
  455.         pdfformaterror
  456.       } {                % no startxref - we have a problem.
  457.         /findxref cvx /syntaxerror signalerror
  458.       } ifelse
  459.     } if
  460.     pop pop
  461.   } {    % else, this file has 'startxref #####' format
  462.     (startxref) ne { /findxref cvx /syntaxerror signalerror } if
  463.     cvi        % xref start position
  464.     (   **** Warning: format of the startxref line in this file is invalid.\n)
  465.     pdfformaterror
  466.     exch PDFfile exch setfileposition
  467.   } ifelse
  468. } bind def
  469. /stderrfile (%stderr) (w) file def
  470. /stderrprint {                % <string> stderrprint -
  471.   //stderrfile dup 3 -1 roll writestring flushfile
  472. } bind def
  473. /pdfformaterror {    % <string> pdfformaterror -
  474.   stderrprint
  475.   /Repaired true store
  476. } bind def
  477.  
  478. /knownoget_safe
  479. { 2 copy knownoget { 3 1 roll pop pop //true } { pop pop //false } ifelse
  480. } odef
  481.  
  482. /printProducer {
  483.   Trailer /Info { knownoget_safe } stopped { pop pop false } if {
  484.     /Producer knownoget not { null } if
  485.   } {
  486.     null
  487.   } ifelse
  488.   dup null eq {
  489.     pop
  490.   } {
  491.     (   **** The file was produced by: \n   **** >>>> ) stderrprint
  492.     % Handle a Unicode Producer.
  493.     (\376\377) anchorsearch {
  494.       pop dup length 2 idiv string 0 1 2 index length 1 sub {
  495.         % Stack: origstr newstr i
  496.     1 index exch 3 index 1 index 2 mul 1 add get put
  497.       } for exch pop
  498.     } if
  499.     stderrprint
  500.     ( <<<<\n) stderrprint
  501.   } ifelse
  502. } bind def
  503. /printrepaired {
  504.    (\n   **** This file had errors that were repaired or ignored.\n)
  505.   stderrprint
  506.   printProducer
  507.   (   **** Please notify the author of the software that produced this\n)
  508.   stderrprint
  509.   (   **** file that it does not conform to Adobe's published PDF\n)
  510.   stderrprint
  511.   (   **** specification.\n\n)
  512.   stderrprint
  513. } bind def
  514.  
  515. % Write the outline structure for a file.  Uses linkdest (below).
  516. /writeoutline        % <outlinedict> writeoutline -
  517.  { mark
  518.    0 2 index /First knownoget
  519.     { { exch 1 add exch /Next knownoget not { exit } if } loop }
  520.    if
  521.         % stack: dict mark count
  522.    dup 0 eq
  523.     { pop 1 index
  524.     }
  525.     { 2 index /Count knownoget { 0 lt { neg } if } if
  526.       /Count exch 3 index
  527.     }
  528.    ifelse linkdest /Title oget /Title exch /OUT pdfmark
  529.    /First knownoget
  530.     { { dup writeoutline /Next knownoget not { exit } if } loop }
  531.    if
  532.  } bind def
  533.  
  534. % Close a PDF file.
  535. /pdfclose        % <dict> pdfclose -
  536.  { begin
  537.    PDFfile closefile
  538.    end
  539.  } bind def
  540.  
  541. % ======================== Page accessing ======================== %
  542.  
  543. % Get a (possibly inherited) attribute of a page.
  544. /pget            % <pagedict> <key> pget <value> -true-
  545.             % <pagedict> <key> pget -false-
  546.  { 2 copy knownoget
  547.     { exch pop exch pop true
  548.     }
  549.     { exch /Parent knownoget
  550.        { exch pget }
  551.        { pop false }
  552.       ifelse
  553.     }
  554.    ifelse
  555.  } bind def
  556.  
  557. % Get the value of a resource on a given page.
  558. /rget {            % <resname> <pagedict> <restype> rget <value> -true-
  559.             % <resname> <pagedict> <restype> rget -false-
  560.   LocalResources 1 index knownoget {
  561.      3 index knownoget
  562.   } {
  563.     false
  564.   } ifelse {
  565.     exch pop exch pop exch pop true
  566.   } {
  567.     exch /Resources pget {
  568.       exch knownoget { exch knownoget } { pop false } ifelse
  569.     } {
  570.       pop pop false
  571.     } ifelse
  572.   } ifelse
  573. } bind def
  574.  
  575. % Get the total number of pages in the document.
  576. /pdfpagecount        % - pdfpagecount <int>
  577.  { Trailer /Root oget /Pages oget /Count oget
  578.  } bind def
  579.  
  580. % Find the N'th page of the document by iterating through the Pages tree.
  581. % The first page is numbered 1.
  582. /pdffindpageref {        % <int> pdffindpage <objref>
  583.   dup Trailer /Root oget /Pages get
  584.     {        % We should be able to tell when we reach a leaf
  585.         % by finding a Type unequal to /Pages.  Unfortunately,
  586.         % some files distributed by Adobe lack the Type key
  587.         % in some of the Pages nodes!  Instead, we check for Kids.
  588.       dup oforce /Kids knownoget not { exit } if
  589.       exch pop null
  590.       0 1 3 index length 1 sub {
  591.          2 index exch get
  592.      dup oforce dup /Kids known { /Count oget } { pop 1 } ifelse
  593.         % Stack: index kids null noderef count
  594.      dup 5 index ge { pop exch pop exit } if
  595.      5 -1 roll exch sub 4 1 roll pop
  596.       } for exch pop
  597.         % Stack: index null|noderef
  598.       dup null eq { pop pop 1 null exit } if
  599.     } loop
  600.         % Stack: index countleft noderef
  601.    1 index 1 ne { pop pop /pdffindpage cvx /rangecheck signalerror } if
  602.    exch pop
  603.    PageIndex 2 index 1 sub 65533 .min 2 index oforce put
  604.    PageNumbers 1 index oforce 3 index dup 65534 le
  605.     { put }
  606.     { pop pop pop }    % don't store more than 65534 pagenumbers
  607.    ifelse
  608.    exch pop
  609. } bind def
  610. /pdffindpage {        % <int> pdffindpage <pagedict>
  611.   pdffindpageref oforce
  612. } bind def
  613.  
  614. % Find the N'th page of the document.
  615. % The first page is numbered 1.
  616. /pdfgetpage        % <int> pdfgetpage <pagedict>
  617.  { PageIndex 1 index 1 sub dup 65533 lt
  618.     { get }
  619.     { pop pop null }
  620.    ifelse
  621.    dup null ne
  622.     { exch pop oforce }
  623.     { pop pdffindpage }
  624.    ifelse
  625.  } bind def
  626.  
  627. % Find the page number of a page object (inverse of pdfgetpage).
  628. /pdfpagenumber        % <pagedict> pdfpagenumber <int>
  629.  {    % We use the simplest and stupidest of all possible algorithms....
  630.    PageNumbers 1 index .knownget
  631.     { exch pop
  632.     }
  633.     { 1 1 PageCount 1 add    % will give a rangecheck if not found
  634.        { dup pdfgetpage oforce 2 index eq { exit } if pop
  635.        }
  636.       for exch pop
  637.     }
  638.    ifelse
  639.  } bind def
  640.  
  641. % Display a given page.
  642. /boxrect        % <llx> <lly> <urx> <ury> boxrect <x> <y> <w> <h>
  643.  { exch 3 index sub exch 2 index sub
  644.  } bind def
  645. /resolvedest {        % <name|string|other> resolvedest <other|null>
  646.   dup type /nametype eq {
  647.     Trailer /Root oget /Dests knownoget {
  648.       exch knownoget not { null } if
  649.     } {
  650.       pop null
  651.     } ifelse
  652.   } {
  653.     dup type /stringtype eq {
  654.       Trailer /Root oget /Names knownoget {
  655.     /Dests knownoget {
  656.       exch nameoget
  657.     } {
  658.       pop null
  659.     } ifelse
  660.       } {
  661.     pop null
  662.       } ifelse
  663.     } if
  664.   } ifelse
  665. } bind def
  666. /linkdest {        % <link|outline> linkdest
  667.             %   ([/Page <n>] /View <view> | ) <link|outline>
  668.   dup /Dest knownoget
  669.     { resolvedest
  670.       dup type /dicttype eq { /D knownoget not { null } if } if
  671.       dup null eq
  672.        { pop }
  673.        { dup 0 oget
  674.          dup type /dicttype eq {
  675.            dup /Type knownoget {
  676.              /Page eq {
  677.                pdfpagenumber
  678.              } if
  679.            } if
  680.          } if
  681.          dup type /integertype ne 
  682.            { pop }
  683.            { /Page exch 4 -2 roll }
  684.          ifelse
  685.      dup length 1 sub 1 exch getinterval /View exch 3 -1 roll
  686.        }
  687.       ifelse
  688.     }
  689.    if
  690. } bind def
  691. % <pagedict> mark ... -proc- -
  692. /namedactions 8 dict dup begin
  693.   /FirstPage {
  694.     /Page 1 3 -1 roll
  695.   } def
  696.   /LastPage {
  697.     counttomark 2 add index pdfpagecount /Page exch 3 -1 roll
  698.   } def
  699.   /NextPage {
  700.     counttomark 2 add index pdfpagenumber 1 add /Page exch 3 -1 roll
  701.   } def
  702.   /PrevPage {
  703.     counttomark 2 add index pdfpagenumber 1 sub /Page exch 3 -1 roll
  704.   } def
  705. end readonly def
  706. % <pagedict> <annotdict> -proc- -
  707. /annottypes 5 dict dup begin
  708.   /Text {
  709.     mark exch
  710.      { /Rect /Open /Contents }
  711.      { 2 copy knownoget { 3 -1 roll } { pop } ifelse }
  712.     forall pop /ANN pdfmark
  713.   } bind def
  714.   /Link {
  715.     mark exch
  716.     dup /C knownoget { /Color exch 3 -1 roll } if
  717.      { /Rect /Border }
  718.      { 2 copy knownoget { 3 -1 roll } { pop } ifelse }
  719.     forall dup /A knownoget {
  720.       dup /URI known {
  721.         /A mark 3 2 roll    % <<>> /A [ <<action>>
  722.         { oforce } forall
  723.         .dicttomark
  724.         3 2 roll
  725.       } {
  726.         dup /D knownoget {
  727.       exch pop exch dup length dict copy dup /Dest 4 -1 roll put
  728.         } {
  729.       /N knownoget {        % Assume /S /Named
  730.          namedactions exch .knownget { exec } if
  731.       } if
  732.         } ifelse
  733.       } ifelse
  734.     } if
  735.     linkdest pop /LNK pdfmark
  736.   } bind def
  737. end readonly def
  738.  
  739. % **** The following procedure should not be changed to allow clients
  740. % **** to directly interface with the constituent procedures. GSview
  741. % **** and some Artifex customers rely on the pdfshowpage_init,
  742. % **** pdfshowpage_setpage, pdfshowpage_finish so all logic should be
  743. % **** implemented in one of those three procedures.
  744. /pdfshowpage        % <pagedict> pdfshowpage -
  745.  { dup /Page exch store
  746.    pdfshowpage_init 
  747.    pdfshowpage_setpage 
  748.    pdfshowpage_finish
  749.  } bind def
  750.  
  751. /pdfpagecontents    % <pagedict> pdfpagecontents <contents>
  752.  { } bind def
  753.  
  754. /pdfshowpage_init     % <pagedict> pdfshowpage_init <pagedict>
  755.  { /DSCPageCount DSCPageCount 1 add store
  756.  } bind def
  757.  
  758. /.pdfshowpage_Install {    % <pagedict> [<prevproc>] .pdfshowpage_Install -
  759.   exch
  760.     % We would like to clip to the CropBox here, but the subsequent
  761.     % initgraphics would override it.  Instead, we have to handle it
  762.     % in graphicsbeginpage.
  763.   dup /CropBox pget dup {exch pop} if systemdict /UseCropBox known and {
  764.     dup /CropBox pget pop
  765.   } {
  766.     dup /MediaBox pget pop    % There has to be a MediaBox
  767.   } ifelse
  768.   % stack: [<prevproc>] <pagedict> <Crop|Media Box>
  769.   exch pop oforce_array            % done with the pagedict
  770.   systemdict /PDFFitPage known {
  771.     PDFDEBUG { (Fiting PDF to imageable area of the page.) = flush } if
  772.     currentpagedevice /.HWMargins get aload pop
  773.     currentpagedevice /PageSize get aload pop
  774.     3 -1 roll sub 3 1 roll exch sub exch
  775.     % stack: [<prevproc>] <pagedict> <Crop|Media Box> Xmin Ymin Xmax Ymax
  776.     PDFDEBUG { (    Translate up by [ ) print 3 index =print (, ) print 2 index =print ( ]) = flush } if
  777.     3 index 3 index translate        % move origin up to imageable area
  778.     2 index sub exch 3 index sub exch 4 2 roll pop pop
  779.         % stack: [Box] XImageable YImageable
  780.     2 index aload pop 2 index sub exch 3 index sub exch 4 2 roll pop pop
  781.         % stack: [Box] XImageable YImageable XBox YBox
  782.     3 -1 roll exch div 3 1 roll div .min
  783.     PDFDEBUG { (    Scale by ) print dup = flush } if
  784.     dup scale
  785.   } if
  786.   % Now translate to the origin given in the Crop|Media Box
  787.   dup 0 get neg exch 1 get neg translate
  788.   0 get
  789.   exec
  790. } bind def
  791.  
  792. /pdfshowpage_setpage {    % <pagedict> pdfshowpage_setpage <pagedict>
  793.   5 dict begin        % for setpagedevice
  794.     % Stack: pagedict
  795.   % UseCIEColor is always true for PDF; see the comment in runpdf above
  796.   /UseCIEColor true def
  797.   currentpagedevice /Orientation 2 index /Rotate pget not { 0 } if 90 idiv
  798.     % Rotate specifies *clockwise* rotation!
  799.     neg 3 and def
  800.     % Stack: pagedict currentpagedict
  801.   1 index /CropBox pget dup {exch pop} if systemdict /UseCropBox known and {
  802.             % Set the page size.
  803.     1 index /CropBox pget pop oforce_elems
  804.     boxrect 2 array astore /PageSize exch def pop pop
  805.   } {
  806.     1 index /MediaBox pget {
  807.             % Set the page size.
  808.       oforce_elems boxrect 2 array astore /PageSize exch def pop pop
  809.     } if
  810.   } ifelse
  811.   % Don't change the page size if we are going to fit the PDF to the page
  812.   systemdict /PDFFitPage known { currentdict /PageSize undef } if
  813.   dup /Install .knownget {
  814.             % Don't let the Install procedure get more deeply
  815.             % nested after every page.
  816.       dup type dup /arraytype eq exch /packedarraytype eq or {
  817.     dup length 4 eq {
  818.       dup 2 get /.pdfshowpage_Install load eq {
  819.         1 get 0 get    % previous procedure
  820.       } if
  821.     } if
  822.       } if
  823.   } {
  824.     { }
  825.   } ifelse 1 array astore
  826.   2 index exch /.pdfshowpage_Install load /exec load
  827.   4 packedarray cvx
  828.     % Stack: pagedict currentpagedict installproc
  829.   /Install exch def
  830.     % Stack: pagedict currentpagedict
  831.   pop currentdict end setpagedevice
  832. } bind def
  833.  
  834. /pdfshowpage_finish {    % <pagedict> pdfshowpage_finish -
  835.    save /PDFSave exch store
  836.    /PDFdictstackcount countdictstack store
  837.    (before exec) VMDEBUG
  838.  
  839.    % set up color space substitution (this must be inside the page save)
  840.    pdfshowpage_setcspacesub
  841.  
  842.   .writepdfmarks {
  843.  
  844.     % Copy the crop box.
  845.     dup /CropBox knownoget {
  846.       oforce_array
  847.  
  848.         % .pdfshowpage_Install translates the origin -
  849.         % do same here with the CropBox.
  850.  
  851.       1 index /CropBox pget dup {exch pop} if systemdict /UseCropBox known and {
  852.         1 index /CropBox pget pop
  853.       } {
  854.         1 index /MediaBox pget pop    % There has to be a MediaBox
  855.       } ifelse
  856.       oforce_array
  857.       dup 0 get exch 1 get   % [] tx ty
  858.       2 index 0 get 2 index sub 3 index exch 0 exch put
  859.       2 index 2 get 2 index sub 3 index exch 2 exch put
  860.       2 index 1 get 1 index sub 3 index exch 1 exch put
  861.       2 index 3 get 1 index sub 3 index exch 3 exch put
  862.       pop pop
  863.  
  864.     % If the page has been rotated, rotate the CropBox.
  865.       mark /CropBox 3 -1 roll
  866.       3 index /Rotate pget {
  867.     90 idiv 1 and 0 ne {
  868.       aload pop 4 -2 roll exch 4 2 roll exch 4 array astore
  869.     } if
  870.       } if
  871.       /PAGE pdfmark
  872.     } if
  873.  
  874.     % Copy annotations and links.
  875.     dup /Annots knownoget {
  876.       0 1 2 index length 1 sub
  877.        { 1 index exch oget
  878.          dup /Subtype oget annottypes exch .knownget { exec } { pop } ifelse
  879.        }
  880.       for pop
  881.     } if
  882.  
  883.   } if        % end .writepdfmarks
  884.  
  885.     % Display the actual page contents.
  886.    6 dict begin
  887.    /BXlevel 0 def
  888.    /BGDefault currentblackgeneration def
  889.    /UCRDefault currentundercolorremoval def
  890.     %****** DOESN'T HANDLE COLOR TRANSFER YET ******
  891.    /TRDefault currenttransfer def
  892.   matrix currentmatrix 2 dict
  893.   2 index /CropBox knownoget {
  894.     oforce_elems boxrect 4 array astore 1 index /ClipRect 3 -1 roll put
  895.   } if
  896.   dictbeginpage setmatrix
  897.   /DefaultQstate qstate store
  898.  
  899.   dup          % for showing annotations below
  900.   count 1 sub /pdfemptycount exch store
  901.     % If the page uses any transparency features, show it within
  902.     % a transparency group.
  903.   dup pageusestransparency dup /PDFusingtransparency exch def {
  904.     % Show the page within a PDF 1.4 device filter.
  905.     0 .pushpdf14devicefilter {
  906.       % If the page has a Group, enclose contents in transparency group.
  907.       % (Adobe Tech Note 5407, sec 9.2)
  908.       dup /Group knownoget {
  909.     1 index /CropBox knownoget not {
  910.       1 index /MediaBox pget pop
  911.     } if oforce_array .beginformgroup {
  912.       showpagecontents
  913.     } .internalstopped {
  914.       .discardtransparencygroup stop
  915.     } if .endtransparencygroup
  916.       } {
  917.     showpagecontents
  918.       } ifelse
  919.     } .internalstopped {
  920.       % todo: discard
  921.       .popdevicefilter stop
  922.     } if .popdevicefilter
  923.   } {
  924.     showpagecontents
  925.   } ifelse
  926.   % check for extra garbage on the ostack and clean it up
  927.   count pdfemptycount sub dup 0 ne {
  928.     (   **** File did not complete the page properly and may be damaged.\n)
  929.     pdfformaterror
  930.     { pop } repeat
  931.   } {
  932.     pop
  933.   } ifelse
  934.   % todo: mixing drawing ops outside the device filter could cause
  935.   % problems, for example with the pnga device.
  936.   /Annots knownoget { { oforce drawannot } forall } if
  937.   endpage
  938.   end            % scratch dict
  939.   % Some PDF files don't have matching q/Q (gsave/grestore) so we need
  940.   % to clean up any left over dicts from the dictstack
  941.   countdictstack PDFdictstackcount sub dup 0 ne { 
  942.     (   **** Warning: File has imbalanced q/Q operators \(too many q's\)\n)
  943.     pdfformaterror
  944.     { end } repeat
  945.   } {
  946.     pop
  947.   } ifelse
  948.   (after exec) VMDEBUG
  949.   Repaired        % pass Repaired state around the restore
  950.   PDFSave restore
  951.   /Repaired exch def
  952. } bind def
  953. /showpagecontents {    % <pagedict> showpagecontents -
  954.   gsave        % preserve gstate for Annotations later
  955.   /Contents knownoget not { 0 array } if
  956.   dup type /arraytype ne { 1 array astore } if {
  957.     oforce false resolvestream pdfopdict .pdfrun
  958.   } forall
  959.   grestore
  960. } bind def
  961. /processcolorspace {    % - processcolorspace <colorspace>
  962.     % The following is per the PLRM3.
  963.   currentdevice 1 dict dup /ProcessColorModel dup put .getdeviceparams
  964.   exch pop exch pop
  965.   dup type /nametype ne { cvn } if
  966.   dup { setcolorspace } .internalstopped { pop /DeviceRGB } if
  967. } bind def
  968.  
  969. % ------ Transparency support ------ %
  970.  
  971. % Define minimum PDF version for checking for transparency features.
  972. % Transparency is a 1.4 feature however we have seen files that claimed
  973. % to be PDF 1.3 with transparency features.
  974. /PDFtransparencyversion 1.3 def
  975.  
  976. % Determine whether a page might invoke any transparency features:
  977. %    - Non-default BM, ca, CA, or SMask in an ExtGState
  978. %    - Image XObject with SMask
  979. % Note: we deliberately don't check to see whether a Group is defined,
  980. % because Adobe Illustrator 10 (and possibly other applications) define
  981. % a page-level group whether transparency is actually used or not.
  982. % Ignoring the presence of Group is justified because, in the absence
  983. % of any other transparency features, they have no effect.
  984. /pageusestransparency {        % <pagedict> pageusestransparency <bool>
  985.   PDFversion PDFtransparencyversion lt NOTRANSPARENCY or {
  986.     pop false
  987.   } {
  988.     false exch {
  989.       dup resourceusestransparency { pop not exit } if
  990.       /Parent knownoget not { exit } if
  991.     } loop
  992.   } ifelse
  993. } bind def
  994. % Check the Resources of a page or Form.
  995. /resourceusestransparency {    % <dict> resourceusestransparency <bool>
  996.   {    % Use loop to provide an exitable context.
  997.     /Resources knownoget not { 0 dict } if
  998.     dup /ExtGState knownoget {
  999.       false exch {
  1000.     exch pop oforce
  1001.     dup /BM knownoget { dup /Normal ne exch /Compatible ne and
  1002.                         { pop not exit } if
  1003.                           } if
  1004.     dup /ca knownoget { 1 ne { pop not exit } if } if
  1005.     dup /CA knownoget { 1 ne { pop not exit } if } if
  1006.     dup /SMask knownoget { /None ne { pop not exit } if } if
  1007.     pop
  1008.       } forall { pop true exit } if
  1009.     } if
  1010.     dup /XObject knownoget {
  1011.       false exch {
  1012.     exch pop oforce dup /Subtype get
  1013.     dup /Image eq { 1 index /SMask known { pop pop not exit } if } if
  1014.     /Form eq {
  1015.       resourceusestransparency { not exit } if
  1016.     } {
  1017.       pop
  1018.     } ifelse
  1019.       } forall { pop true exit } if
  1020.     } if
  1021.     pop false exit
  1022.   } loop
  1023. } bind def
  1024.  
  1025. % ------ ColorSpace substitution support ------ %
  1026.  
  1027. %
  1028. %  <pagedict>   pdfshowpage_setcspacesub   <pagedict>
  1029. %
  1030. % Set up color space substitution for a page. Invocations of this procedure
  1031. % must be bracketed by the save/restore operation for the page, to avoid
  1032. % unintended effects on other pages.
  1033. %
  1034. % If any color space substitution is used, and the current color space is a
  1035. % device dependent color space, make sure the current color space is updated.
  1036. % There is an optimization in the setcolorspace pseudo-operator that does
  1037. % nothing if both the current and operand color spaces are the same. For
  1038. % PostScript this optimization is disabled if the UseCIEColor page device
  1039. % parameter is true. This is not the case for PDF, as performance suffers
  1040. % significantly on some PDF files if color spaces are set repeatedly. Hence,
  1041. % if color space substitution is to be used, and the current color space
  1042. % is a device dependent color space, we must make sure to "transition" the
  1043. % current color space.
  1044. %
  1045. /pdfshowpage_setcspacesub
  1046.   {
  1047.     false
  1048.       { /DefaultGray /DefaultRGB /DefaultCMYK }
  1049.       {
  1050.         dup 3 index /ColorSpace //rget exec
  1051.           { resolvecolorspace /ColorSpace defineresource pop }
  1052.           { pop }
  1053.         ifelse
  1054.       }
  1055.     forall
  1056.  
  1057.     % if using color space substitution, "transition" the current color space
  1058.       {
  1059.         currentcolorspace dup length 1 eq   % always an array
  1060.           {
  1061.             0 get
  1062.             dup /DeviceGray eq 1 index /DeviceRGB eq or 1 index /DeviceCMYK or
  1063.               { /Pattern setcolorspace setcolorspace }
  1064.               { pop }
  1065.             ifelse
  1066.           }
  1067.           { pop }
  1068.         if
  1069.       }
  1070.     if
  1071.   }
  1072. bind def
  1073.  
  1074.  
  1075.  
  1076. end            % pdfdict
  1077. .setglobal
  1078.