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