home *** CD-ROM | disk | FTP | other *** search
/ Komputer for Alle 2003 #12 / K-CD-12-2003.ISO / pdf995 / res / convert / pdf_main.ps < prev    next >
Encoding:
Text File  |  2002-04-03  |  23.4 KB  |  786 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.35.2.2 2002/04/02 13:57:27 mpsuzuki 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. /runpdfstring 50 string def        % length is arbitrary
  69. /run {
  70.   dup type /filetype ne { (r) file } if
  71.   dup ( ) .peekstring {
  72.     (%) eq {
  73.       dup (  ) .peekstring {
  74.     (%P) eq {
  75.       dup //runpdfstring {
  76.         % Some invalid files might have extra-long first lines....
  77.         { readline } .internalstopped not { pop pop exit } if
  78.         pop =string
  79.       } loop
  80.       //runpdfstring (%PDF-) anchorsearch {
  81.         pop pop runpdf
  82.       } {
  83.         pop cvx .runexec
  84.       } ifelse
  85.     } {
  86.       cvx .runps
  87.     } ifelse
  88.       } {
  89.     closefile
  90.       } ifelse
  91.     } {
  92.       cvx .runps
  93.     } ifelse
  94.   } {
  95.     closefile
  96.   } ifelse
  97. } bind odef
  98. currentdict /runpdfstring .undef
  99.  
  100. /runpdf            % <file> runpdf -
  101.  { userdict begin
  102.    /Page# null def
  103.    /Page null def
  104.    /DSCPageCount 0 def
  105.    /PDFSave null def
  106.    GS_PDF_ProcSet begin
  107.    pdfdict begin
  108.    pdfopen begin
  109.    Trailer /Root oget /Pages oget /CropBox knownoget
  110.     { mark /CropBox 3 -1 roll /PAGES pdfmark
  111.     }
  112.    if
  113.    /FirstPage where 
  114.     { pop FirstPage dup pdfpagecount gt
  115.       { (\nRequested FirstPage is greater than the number of pages in the file: ) print
  116.         pdfpagecount = flush
  117.       } if
  118.     } {
  119.       1
  120.     } ifelse
  121.    1
  122.    /LastPage where { pop LastPage pdfpagecount .min } { pdfpagecount } ifelse
  123.    2 index 1 index gt
  124.     { (   No pages will be processed \(FirstPage > LastPage\).) = flush }
  125.     { QUIET not
  126.       { (Processing pages ) print 2 index =only ( through ) print dup =only
  127.         (.) = flush
  128.       }
  129.      if
  130.     }
  131.    ifelse
  132.     { dup /Page# exch store
  133.       QUIET not { (Page ) print dup == flush } if
  134.       pdfgetpage pdfshowpage
  135.     } for
  136.    currentdict pdfclose
  137.    end            % temporary dict
  138.    end            % pdfdict
  139.    end            % userdict
  140.  } bind def
  141. end            % systemdict
  142. % Redefine the procedure that the C code uses for running piped input.
  143. % It is OK to use { (%stdin) run } here, because a startjob cannot occur.
  144. /.runstdin {
  145.   { (%stdin) run } execute0
  146. } bind def
  147.  
  148. end            % userdict
  149. pdfdict begin
  150.  
  151. % ======================== File parsing ======================== %
  152.  
  153. % Read the cross-reference and trailer sections.
  154.  
  155. /traileropdict mark
  156.   (<<) cvn { mark } bind
  157.   (>>) cvn /.dicttomark load
  158.   ([) cvn { mark } bind        % ditto
  159.   (]) cvn dup load
  160. %  /true true        % see .pdfexectoken in pdf_base.ps
  161. %  /false false        % ibid.
  162. %  /null null        % ibid.
  163.   /R { /resolveR cvx 3 packedarray cvx } bind    % see Objects below
  164.   /startxref /exit load
  165. .dicttomark readonly def
  166.  
  167. % Because of EOL conversion, lines with fixed contents might be followed
  168. % by one or more blanks.
  169. /lineeq            % <filestr> <conststr> lineeq <bool>
  170.  { anchorsearch
  171.     { pop { ( ) anchorsearch not { () eq exit } if pop } loop }
  172.     { pop false }
  173.    ifelse
  174.  } bind def
  175. /linene { lineeq not } bind def
  176.  
  177. % Read (mostly scan) the cross-reference table.
  178. /readxref        % <pos> readxref <trailerdict>
  179.  { PDFoffset add PDFfile exch setfileposition
  180.         % In some PDF files, this position actually points to
  181.         % white space before the xref line.  Skip over this here.
  182.    { PDFfile fileposition PDFfile read pop 32 gt { exit } if pop
  183.    } loop
  184.    PDFfile exch setfileposition
  185.         % The PDF specification says that the 'xref' must be on a line
  186.         % by itself. The code here formerly used readline and linene to
  187.         % check this. However, Acrobat Reader only requires the line to
  188.         % begin with 'xref', and there are enough applications producing
  189.         % non-compliant PDF files that we have to do this too.
  190.    PDFfile pdfstring 0 4 getinterval readstring pop
  191.    (xref) ne { /readxref cvx /syntaxerror signalerror } if
  192.         % Store the xref table entry position for each object.
  193.         % We only need to read the run headers, not every entry.
  194.     { PDFfile token pop        % first object # or trailer
  195.       dup /trailer eq { pop exit } if
  196.       PDFfile pdfstring readline pop
  197.       token pop            % entry count
  198.       exch pop exch
  199.         % This section might be adding new objects:
  200.         % ensure that Objects and Generations are big enough.
  201.         % Stack: count obj#
  202.       2 copy add growPDFobjects
  203.       PDFfile fileposition 3 -1 roll
  204.        { Objects 2 index lget null eq    % later update might have set it
  205.       { Objects 2 index 2 index cvx lput }
  206.          if exch 1 add exch 20 add
  207.        }
  208.       repeat PDFfile exch setfileposition pop
  209.     } loop
  210.    count /pdfemptycount exch def
  211.    PDFfile traileropdict .pdfrun
  212.  } bind def
  213.  
  214. % Open a PDF file and read the header, trailer, and cross-reference.
  215. /pdfopen {        % <file> pdfopen <dict>
  216.   pdfopenfile begin
  217.   pdfopencache
  218.   .writepdfmarks {
  219.     % Copy bookmarks (outline) to the output.
  220.     Trailer /Root oget /Outlines knownoget {
  221.       /First knownoget {
  222.     { dup writeoutline /Next knownoget not { exit } if } loop
  223.       } if
  224.     } if
  225.   } if        % end .writepdfmarks
  226.   currentdict end
  227. } bind def
  228. /pdfopencache {        % - pdfopencache -
  229.     % Create and initialize some caches.
  230.   /PageCount pdfpagecount def
  231.   /PageNumbers PageCount 65534 .min dict def
  232.   /PageIndex PageCount 65534 .min array def
  233. } bind def
  234. /pdfopenfile {        % <file> pdfopenfile <dict>
  235.    pdfdict readonly pop        % can't do it any earlier than this
  236.    15 dict begin
  237.    /LocalResources 0 dict def
  238.    /DefaultMatrix null def    % establish binding
  239.    /Printed where { pop } {
  240.         % Guess whether the output device is a printer.
  241.      /Printed currentpagedevice /OutputFile known def
  242.    } ifelse
  243.    /PSLevel1 where { pop } { /PSLevel1 false def } ifelse
  244.    cvlit /PDFfile exch def
  245.    /PDFsource PDFfile def
  246.    /Repaired false def
  247.    PDFfile dup 0 setfileposition pdfstring readstring 
  248.    not {/pdfopen cvx /syntaxerror signalerror} if
  249.    (%PDF-) search not {/pdfopen cvx /syntaxerror signalerror} if
  250.    length /PDFoffset exch def pop cvr /PDFversion exch def
  251.    findxref
  252.    initPDFobjects
  253.     % Read the last cross-reference table.
  254.    readxref /Trailer exch def
  255.    Trailer /Encrypt known
  256.     { pdf_process_Encrypt    % signal error
  257.     }
  258.    if
  259.     % Read any previous cross-reference tables.
  260.    Trailer { /Prev .knownget not { exit } if readxref } loop
  261.    Repaired { printrepaired } if
  262.    currentdict end
  263.  } bind def
  264.  
  265. % Skip backward over the %%EOF at the end of the PDF file, and read
  266. % the preceding startxref line.  The PDF specification unambiguously
  267. % requires that the %%EOF appear on a line by itself, and that the
  268. % startxref and the following position value appear on separate lines;
  269. % however, some applications (including, apparently, Acrobat Distiller
  270. % on the Macintosh) may add up to 2K of garbage after the %%EOF, and some
  271. % other applications also truncate the %%EOF to %%EO, and/or put the
  272. % startxref and the following value on the same line.
  273. % A file reported from Distiller 3.02b for AIX 4.1.1 has 2076 bytes
  274. % of garbage. The tolerance is increased to 4K to cover future
  275. % applications and bigger allocation units.
  276. /findxref {        % - findxref <xrefpos>
  277.   PDFfile dup dup 0 setfileposition bytesavailable
  278.   dup /PDFfilelen exch def
  279.     % Find the last %%EOF string (within 4096 bytes)
  280.   4096 sub PDFoffset .max
  281.   2 copy setfileposition
  282.   PDFfilelen exch sub string 1 index exch readstring pop {
  283.     (\015%%EO) search {        % Adobe can handle truncated key string
  284.       pop pop            % if found, keep searching 'post' string
  285.     } {
  286.       (\012%%EO) search
  287.     { pop pop } { exit } ifelse    % exit if neither string found
  288.     } ifelse
  289.   } loop
  290.   PDFfilelen exch length sub 4 sub PDFoffset .max exch 1 index setfileposition
  291.     % Stack: eofpos
  292.     % Check for whether this is, in fact, a valid PDF file.
  293.   dup PDFfilelen exch sub dup dup 7 gt exch 6 lt or {
  294.     pop true
  295.   } {
  296.     string PDFfile exch readstring pop
  297.     dup (%%EOF\n) eq exch dup (%%EOF\r) eq
  298.     exch (%%EOF\r\n) eq or or not
  299.   } ifelse {
  300.     (
  301.    **** This file has a corrupted %%EOF marker, or garbage after the %%EOF.
  302. ) pdfformaterror
  303.   } if
  304.   PDFfile exch setfileposition
  305.     % Now read the startxref and xref start position.
  306.   prevline token not { null } if dup type /integertype eq {
  307.     exch pop cvi        % xref start position
  308.     exch PDFfile exch setfileposition
  309.     prevline (startxref) linene { /findxref cvx /syntaxerror signalerror } if
  310.     pop
  311.   } {    % else, this file has 'startxref #####' format
  312.     (startxref) ne { /findxref cvx /syntaxerror signalerror } if
  313.     cvi        % xref start position
  314.     (
  315.    **** The format of the startxref line in this file is invalid.
  316. ) pdfformaterror
  317.     exch PDFfile exch setfileposition
  318.   } ifelse
  319. } bind def
  320. /stderrfile (%stderr) (w) file def
  321. /stderrprint {                % <string> stderrprint -
  322.   //stderrfile dup 3 -1 roll writestring flushfile
  323. } bind def
  324. /pdfformaterror {    % <string> pdfformaterror -
  325.   stderrprint
  326.   /Repaired true store
  327. } bind def
  328. /printrepaired {
  329.   Trailer /Info knownoget {
  330.     /Producer knownoget not { null } if
  331.   } {
  332.     null
  333.   } ifelse
  334.   dup null eq {
  335.     pop (\
  336.    **** Please notify the author of the software that produced this file
  337. )
  338.   } {
  339.     (   **** The file was produced by ) stderrprint
  340.     % Handle a Unicode Producer.
  341.     (\376\377) anchorsearch {
  342.       pop dup length 2 idiv string 0 1 2 index length 1 sub {
  343.         % Stack: origstr newstr i
  344.     1 index exch 3 index 1 index 2 mul 1 add get put
  345.       } for exch pop
  346.     } if
  347.     stderrprint
  348.     (:
  349.    **** please notify the author of this software
  350. )
  351.   } ifelse stderrprint
  352. (\
  353.    **** that the file does not conform to Adobe's published PDF
  354.    **** specification.  Processing of the file will continue normally.
  355.  
  356. ) stderrprint
  357. } bind def
  358.  
  359. % Write the outline structure for a file.  Uses linkdest (below).
  360. /writeoutline        % <outlinedict> writeoutline -
  361.  { mark
  362.    0 2 index /First knownoget
  363.     { { exch 1 add exch /Next knownoget not { exit } if } loop }
  364.    if
  365.         % stack: dict mark count
  366.    dup 0 eq
  367.     { pop 1 index
  368.     }
  369.     { 2 index /Count knownoget { 0 lt { neg } if } if
  370.       /Count exch 3 index
  371.     }
  372.    ifelse linkdest /Title oget /Title exch /OUT pdfmark
  373.    /First knownoget
  374.     { { dup writeoutline /Next knownoget not { exit } if } loop }
  375.    if
  376.  } bind def
  377.  
  378. % Close a PDF file.
  379. /pdfclose        % <dict> pdfclose -
  380.  { begin
  381.    PDFfile closefile
  382.    end
  383.  } bind def
  384.  
  385. % ======================== Page accessing ======================== %
  386.  
  387. % Get a (possibly inherited) attribute of a page.
  388. /pget            % <pagedict> <key> pget <value> -true-
  389.             % <pagedict> <key> pget -false-
  390.  { 2 copy knownoget
  391.     { exch pop exch pop true
  392.     }
  393.     { exch /Parent knownoget
  394.        { exch pget }
  395.        { pop false }
  396.       ifelse
  397.     }
  398.    ifelse
  399.  } bind def
  400.  
  401. % Get the value of a resource on a given page.
  402. /rget {            % <resname> <pagedict> <restype> rget <value> -true-
  403.             % <resname> <pagedict> <restype> rget -false-
  404.   LocalResources 1 index knownoget {
  405.      3 index knownoget
  406.   } {
  407.     false
  408.   } ifelse {
  409.     exch pop exch pop exch pop true
  410.   } {
  411.     exch /Resources pget {
  412.       exch knownoget { exch knownoget } { pop false } ifelse
  413.     } {
  414.       pop pop false
  415.     } ifelse
  416.   } ifelse
  417. } bind def
  418.  
  419. % Get the total number of pages in the document.
  420. /pdfpagecount        % - pdfpagecount <int>
  421.  { Trailer /Root oget /Pages oget /Count oget
  422.  } bind def
  423.  
  424. % Find the N'th page of the document by iterating through the Pages tree.
  425. % The first page is numbered 1.
  426. /pdffindpageref {        % <int> pdffindpage <objref>
  427.   dup Trailer /Root oget /Pages get
  428.     {        % We should be able to tell when we reach a leaf
  429.         % by finding a Type unequal to /Pages.  Unfortunately,
  430.         % some files distributed by Adobe lack the Type key
  431.         % in some of the Pages nodes!  Instead, we check for Kids.
  432.       dup oforce /Kids knownoget not { exit } if
  433.       exch pop null
  434.       0 1 3 index length 1 sub {
  435.          2 index exch get
  436.      dup oforce dup /Kids known { /Count oget } { pop 1 } ifelse
  437.         % Stack: index kids null noderef count
  438.      dup 5 index ge { pop exch pop exit } if
  439.      5 -1 roll exch sub 4 1 roll pop
  440.       } for exch pop
  441.         % Stack: index null|noderef
  442.       dup null eq { pop pop 1 null exit } if
  443.     } loop
  444.         % Stack: index countleft noderef
  445.    1 index 1 ne { pop pop /pdffindpage cvx /rangecheck signalerror } if
  446.    exch pop
  447.    PageIndex 2 index 1 sub 65533 .min 2 index oforce put
  448.    PageNumbers 1 index oforce 3 index dup 65534 le
  449.     { put }
  450.     { pop pop pop }    % don't store more than 65534 pagenumbers
  451.    ifelse
  452.    exch pop
  453. } bind def
  454. /pdffindpage {        % <int> pdffindpage <pagedict>
  455.   pdffindpageref oforce
  456. } bind def
  457.  
  458. % Find the N'th page of the document.
  459. % The first page is numbered 1.
  460. /pdfgetpage        % <int> pdfgetpage <pagedict>
  461.  { PageIndex 1 index 1 sub dup 65533 lt
  462.     { get }
  463.     { pop pop null }
  464.    ifelse
  465.    dup null ne
  466.     { exch pop oforce }
  467.     { pop pdffindpage }
  468.    ifelse
  469.  } bind def
  470.  
  471. % Find the page number of a page object (inverse of pdfgetpage).
  472. /pdfpagenumber        % <pagedict> pdfpagenumber <int>
  473.  {    % We use the simplest and stupidest of all possible algorithms....
  474.    PageNumbers 1 index .knownget
  475.     { exch pop
  476.     }
  477.     { 1 1 PageCount 1 add    % will give a rangecheck if not found
  478.        { dup pdfgetpage oforce 2 index eq { exit } if pop
  479.        }
  480.       for exch pop
  481.     }
  482.    ifelse
  483.  } bind def
  484.  
  485. % Display a given page.
  486. /boxrect        % [<llx> <lly> <urx> <ury>] boxrect <x> <y> <w> <h>
  487.  { aload pop exch 3 index sub exch 2 index sub
  488.  } bind def
  489. /resolvedest {        % <name|string|other> resolvedest <other|null>
  490.   dup type /nametype eq {
  491.     Trailer /Root oget /Dests knownoget {
  492.       exch knownoget not { null } if
  493.     } {
  494.       null
  495.     } ifelse
  496.   } {
  497.     dup type /stringtype eq {
  498.       Trailer /Root oget /Names knownoget {
  499.     /Dests knownoget {
  500.       exch nameoget
  501.     } {
  502.       pop null
  503.     } ifelse
  504.       } {
  505.     pop null
  506.       } ifelse
  507.     } if
  508.   } ifelse
  509. } bind def
  510. /linkdest {        % <link|outline> linkdest
  511.             %   ([/Page <n>] /View <view> | ) <link|outline>
  512.   dup /Dest knownoget
  513.     { resolvedest
  514.       dup type /dicttype eq { /D knownoget not { null } if } if
  515.       dup null eq
  516.        { pop }
  517.        { dup 0 oget
  518.      dup null eq
  519.       { pop }
  520.       { dup type /integertype ne { pdfpagenumber } if
  521.         /Page exch 4 -2 roll
  522.       }
  523.      ifelse
  524.      dup length 1 sub 1 exch getinterval /View exch 3 -1 roll
  525.        }
  526.       ifelse
  527.     }
  528.    if
  529. } bind def
  530. % <pagedict> mark ... -proc- -
  531. /namedactions 8 dict dup begin
  532.   /FirstPage {
  533.     /Page 1 3 -1 roll
  534.   } def
  535.   /LastPage {
  536.     counttomark 2 add index pdfpagecount /Page exch 3 -1 roll
  537.   } def
  538.   /NextPage {
  539.     counttomark 2 add index pdfpagenumber 1 add /Page exch 3 -1 roll
  540.   } def
  541.   /PrevPage {
  542.     counttomark 2 add index pdfpagenumber 1 sub /Page exch 3 -1 roll
  543.   } def
  544. end readonly def
  545. % <pagedict> <annotdict> -proc- -
  546. /annottypes 5 dict dup begin
  547.   /Text {
  548.     mark exch
  549.      { /Rect /Open /Contents }
  550.      { 2 copy knownoget { 3 -1 roll } { pop } ifelse }
  551.     forall pop /ANN pdfmark
  552.   } bind def
  553.   /Link {
  554.     mark exch
  555.      { /Rect /Border }
  556.      { 2 copy knownoget { 3 -1 roll } { pop } ifelse }
  557.     forall dup /A knownoget {
  558.       dup /URI known {
  559.         /A mark 3 2 roll    % <<>> /A [ <<action>>
  560.         { oforce } forall
  561.         .dicttomark
  562.         3 2 roll
  563.       } {
  564.         dup /D knownoget {
  565.       exch pop exch dup length dict copy dup /Dest 4 -1 roll put
  566.         } {
  567.       /N knownoget {        % Assume /S /Named
  568.          namedactions exch .knownget { exec } if
  569.       } if
  570.         } ifelse
  571.       } ifelse
  572.     } if
  573.     linkdest pop /LNK pdfmark
  574.   } bind def
  575. end readonly def
  576.  
  577. /pdfshowpage        % <pagedict> pdfshowpage -
  578.  { dup /Page exch store
  579.    pdfshowpage_init 
  580.    pdfshowpage_setpage 
  581.    save /PDFSave exch store
  582.    (before exec) VMDEBUG
  583.      pdfshowpage_finish
  584.    (after exec) VMDEBUG
  585.    PDFSave restore
  586.  } bind def
  587.  
  588. /pdfpagecontents    % <pagedict> pdfpagecontents <contents>
  589.  { } bind def
  590.  
  591. /pdfshowpage_init     % <pagedict> pdfshowpage_init <pagedict>
  592.  { /DSCPageCount DSCPageCount 1 add store
  593.  } bind def
  594.  
  595. /.pdfshowpage_Install {    % <pagedict> [<prevproc>] .pdfshowpage_Install -
  596.   exch
  597.     % We would like to clip to the CropBox here, but the subsequent
  598.     % initgraphics would override it.  Instead, we have to handle it
  599.     % in graphicsbeginpage.
  600.   dup /MediaBox pget {
  601.     dup 0 get neg exch 1 get neg translate
  602.   } if
  603.   pop 0 get exec
  604. } bind def
  605.  
  606. /pdfshowpage_setpage {    % <pagedict> pdfshowpage_setpage <pagedict>
  607.   4 dict begin        % for setpagedevice
  608.     % Stack: pagedict
  609.   currentpagedevice /Orientation 2 index /Rotate pget not { 0 } if 90 idiv
  610.     % Rotate specifies *clockwise* rotation!
  611.     neg 3 and def
  612.     % Stack: pagedict currentpagedict
  613.   1 index /MediaBox pget {
  614.             % Set the page size.
  615.     boxrect 2 array astore /PageSize exch def pop pop
  616.   } if
  617.   dup /Install .knownget {
  618.             % Don't let the Install procedure get more deeply
  619.             % nested after every page.
  620.       dup type dup /arraytype eq exch /packedarraytype eq or {
  621.     dup length 4 eq {
  622.       dup 2 get /.pdfshowpage_Install load eq {
  623.         1 get 0 get    % previous procedure
  624.       } if
  625.     } if
  626.       } if
  627.   } {
  628.     { }
  629.   } ifelse 1 array astore
  630.   2 index exch /.pdfshowpage_Install load /exec load
  631.   4 packedarray cvx
  632.     % Stack: pagedict currentpagedict installproc
  633.   /Install exch def
  634.     % Stack: pagedict currentpagedict
  635.   pop currentdict end setpagedevice
  636. } bind def
  637.  
  638. /pdfshowpage_finish {    % <pagedict> pdfshowpage_finish -
  639.  
  640.   .writepdfmarks {
  641.  
  642.     % Copy the crop box.
  643.     dup /CropBox knownoget {
  644.     % If the page has been rotated, rotate the CropBox.
  645.       mark /CropBox 3 -1 roll
  646.       3 index /Rotate pget {
  647.     90 idiv 1 and 0 ne {
  648.       aload pop 4 -2 roll exch 4 2 roll exch 4 array astore
  649.     } if
  650.       } if
  651.       /PAGE pdfmark
  652.     } if
  653.  
  654.     % Copy annotations and links.
  655.     dup /Annots knownoget {
  656.       0 1 2 index length 1 sub
  657.        { 1 index exch oget
  658.          dup /Subtype oget annottypes exch .knownget { exec } { pop } ifelse
  659.        }
  660.       for pop
  661.     } if
  662.  
  663.   } if        % end .writepdfmarks
  664.  
  665.     % Display the actual page contents.
  666.    6 dict begin
  667.    /BXlevel 0 def
  668.    /BGDefault currentblackgeneration def
  669.    /UCRDefault currentundercolorremoval def
  670.     %****** DOESN'T HANDLE COLOR TRANSFER YET ******
  671.    /TRDefault currenttransfer def
  672.   matrix currentmatrix 2 dict
  673.   2 index /CropBox knownoget {
  674.     boxrect 4 array astore 1 index /ClipRect 3 -1 roll put
  675.   } if
  676.   dictbeginpage /DefaultMatrix 1 index store setmatrix
  677.   dup          % for showing annotations below
  678.   count /pdfemptycount exch store
  679.   gsave
  680.     % If the page uses any transparency features, show it within
  681.     % a transparency group.
  682.   PDFversion 1.4 lt {
  683.     showpagecontents
  684.   } {
  685.     dup pageusestransparency {
  686.       % Show the page within a PDF 1.4 device filter.
  687.       0 .pushpdf14devicefilter {
  688.     % If the page has a Group, enclose contents in transparency group.
  689.         % (Adobe Tech Note 5407, sec 9.2)
  690.         dup /Group knownoget {
  691.       1 index /CropBox knownoget not {
  692.         1 index /MediaBox oget
  693.       } if .beginformgroup {
  694.         showpagecontents
  695.       } .internalstopped {
  696.         .discardtransparencygroup stop
  697.       } if .endtransparencygroup
  698.         } {
  699.       showpagecontents
  700.         } ifelse
  701.       } .internalstopped {
  702.     % todo: discard
  703.     .popdevicefilter stop
  704.       } if .popdevicefilter
  705.     } {
  706.       showpagecontents
  707.     } ifelse
  708.   } ifelse
  709.   grestore
  710.    % todo: mixing drawing ops outside the device filter could cause
  711.    % problems, for example with the pnga device.
  712.    /Annots knownoget { { oforce drawannot } forall } if
  713.    endpage
  714.    end            % scratch dict
  715. } bind def
  716. /showpagecontents {    % <pagedict> showpagecontents -
  717.   /Contents knownoget not { 0 array } if
  718.   dup type /arraytype ne { 1 array astore } if {
  719.     oforce false resolvestream pdfopdict .pdfrun
  720.   } forall
  721. } bind def
  722. /processcolorspace {    % - processcolorspace <colorspace>
  723.     % The following is per the PLRM3.
  724.   currentdevice 1 dict dup /ProcessColorModel dup put .getdeviceparams
  725.   exch pop exch pop
  726.   dup type /nametype ne { cvn } if
  727.   dup { setcolorspace } .internalstopped { pop /DeviceRGB } if
  728. } bind def
  729.  
  730. % ------ Transparency support ------ %
  731.  
  732. % Determine whether a page might invoke any transparency features:
  733. %    - Group in the page dictionary
  734. %    - Non-default ca, CA, or SMask in an ExtGState
  735. %    - Form XObject with Group
  736. %    - Image XObject with SMask
  737. % ****** DO WE NEED TO LOOK IN RESOURCE DICTS OF OTHER CONTENT STREAMS? ******
  738. /pageusestransparency {        % <pagedict> pageusestransparency <bool>
  739.   PDFversion 1.4 lt {
  740.     pop false
  741.   } {
  742.     dup /Group known {
  743.       pop true
  744.     } {
  745.       false exch {
  746.     dup resourceusestransparency { pop not exit } if
  747.     /Parent knownoget not { exit } if
  748.       } loop
  749.     } ifelse
  750.   } ifelse
  751. } bind def
  752. % Check the Resources of a page or Form.
  753. /resourceusestransparency {    % <dict> resourceusestransparency <bool>
  754.   {    % Use loop to provide an exitable context.
  755.     /Resources knownoget not { 0 dict } if
  756.     dup /ExtGState knownoget {
  757.       false exch {
  758.     exch pop oforce
  759.     dup /ca knownoget { 1 ne { pop not exit } if } if
  760.     dup /CA knownoget { 1 ne { pop not exit } if } if
  761.     dup /SMask knownoget { /None ne { pop not exit } if } if
  762.     pop
  763.       } forall { pop true exit } if
  764.     } if
  765.     dup /XObject knownoget {
  766.       false exch {
  767.     exch pop oforce dup /Subtype get
  768.     dup /Image eq { 1 index /SMask known { pop pop not exit } if } if
  769.     /Form eq {
  770.       dup /Group known { pop not exit } if
  771.       resourceusestransparency { not exit } if
  772.     } {
  773.       pop
  774.     } ifelse
  775.       } forall { pop true exit } if
  776.     } if
  777.     pop false exit
  778.   } loop
  779. } bind def
  780.  
  781. end            % pdfdict
  782. .setglobal
  783.