home *** CD-ROM | disk | FTP | other *** search
/ Chip 2002 October / Chip_2002-10_cd1.bin / zkuste / pdf / download / gs704w32.exe / gs7.04 / lib / pdf_main.ps < prev    next >
Encoding:
Text File  |  2002-01-31  |  23.6 KB  |  788 lines

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