henesyinit from p9f0ed2a895 years agoHistory
740 lines · 21.1 KB · Text
RawDownload
%    Copyright (C) 1994, 2000 Aladdin Enterprises.  All rights reserved.% % This file is part of AFPL Ghostscript.% % AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author or% distributor accepts any responsibility for the consequences of using it, or% for whether it serves any particular purpose or works at all, unless he or% she says so in writing.  Refer to the Aladdin Free Public License (the% "License") for full details.% % Every copy of AFPL Ghostscript must include a copy of the License, normally% in a plain ASCII text file named PUBLIC.  The License grants you the right% to copy, modify and redistribute AFPL Ghostscript, but only under certain% conditions described in the License.  Among other things, the License% requires that the copyright notice and this notice be preserved on all% copies. % $Id: pdf_main.ps,v 1.19.2.4 2000/11/25 21:58:19 raph Exp $% pdf_main.ps% PDF file- and page-level operations. /.setlanguagelevel where { pop 2 .setlanguagelevel } if.currentglobal true .setglobal/pdfdict where { pop } { /pdfdict 100 dict def } ifelsepdfdict begin % Patch in an obsolete variable used by some third-party software./#? false def % Test whether the current output device handles pdfmark./.writepdfmarkdict 1 dict dup /pdfmark null put readonly def/.writepdfmarks {	% - .writepdfmarks <bool>  currentdevice //.writepdfmarkdict .getdeviceparams  mark eq { false } { pop pop true } ifelse} bind def % For simplicity, we use a single interpretation dictionary for all% PDF graphics execution, even though this is too liberal./pdfopdict mark  objopdict { } forall  drawopdict { } forall  /endstream { exit } bind  (%%EOF) cvn { exit } bind		% for filters	% PDF 1.1 operators  /BX { /BXlevel BXlevel 1 add store } bind  /EX { /BXlevel BXlevel 1 sub store } bind  /PS { cvx exec } bind	% PDF 1.2 operators  /BMC { pop } bind  /BDC { pop pop } bind  /EMC { }  /MP { pop } bind  /DP { pop pop } bind.dicttomark readonly def % ======================== Main program ======================== % end			% pdfdictuserdict begin /defaultfontname /Times-Roman def % Make sure the registered encodings are loaded, so we don't run the risk% that some of the indices for their names will overflow the packed% representation.  (Yes, this is a hack.)SymbolEncoding popDingbatsEncoding pop % Redefine 'run' so it recognizes PDF files.systemdict begin/.runps /run load def/runpdfstring 50 string def		% length is arbitrary/run {  dup type /filetype ne { (r) file } if  dup ( ) .peekstring {    (%) eq {      dup (  ) .peekstring {	(%P) eq {	  dup //runpdfstring {		% Some invalid files might have extra-long first lines....	    { readline } .internalstopped not { pop pop exit } if	    pop =string	  } loop	  //runpdfstring (%PDF-) anchorsearch {	    pop pop runpdf	  } {	    pop cvx .runexec	  } ifelse	} {	  cvx .runps	} ifelse      } {	closefile      } ifelse    } {      cvx .runps    } ifelse  } {    closefile  } ifelse} bind odefcurrentdict /runpdfstring .undef /runpdf			% <file> runpdf - { userdict begin   /Page# null def   /Page null def   /DSCPageCount 0 def   /PDFSave null def   GS_PDF_ProcSet begin   pdfdict begin   pdfopen begin   Trailer /Root oget /Pages oget /CropBox knownoget    { mark /CropBox 3 -1 roll /PAGES pdfmark    }   if   /FirstPage where { pop FirstPage } { 1 } ifelse   1   /LastPage where { pop LastPage } { pdfpagecount } ifelse   QUIET not    { (Processing pages ) print 2 index =only ( through ) print dup =only      (.) = flush    }   if    { dup /Page# exch store      QUIET not { (Page ) print dup == flush } if      pdfgetpage pdfshowpage    } for   currentdict pdfclose   end			% temporary dict   end			% pdfdict   end			% userdict } bind defend			% systemdict% Redefine the procedure that the C code uses for running piped input.% It is OK to use { (%stdin) run } here, because a startjob cannot occur./.runstdin {  { (%stdin) run } execute0} bind def end			% userdictpdfdict begin % ======================== File parsing ======================== % % Read the cross-reference and trailer sections. /traileropdict mark  (<<) cvn { mark } bind  (>>) cvn /.dicttomark load  ([) cvn { mark } bind		% ditto  (]) cvn dup load  /true true  /false false  /null null  /R { /resolveR cvx 3 packedarray cvx } bind	% see Objects below  /startxref /exit load.dicttomark readonly def % Because of EOL conversion, lines with fixed contents might be followed% by one or more blanks./lineeq			% <filestr> <conststr> lineeq <bool> { anchorsearch    { pop { ( ) anchorsearch not { () eq exit } if pop } loop }    { pop false }   ifelse } bind def/linene { lineeq not } bind def % Read (mostly scan) the cross-reference table./readxref		% <pos> readxref <trailerdict> { PDFoffset add PDFfile exch setfileposition		% In some PDF files, this position actually points to		% white space before the xref line.  Skip over this here.   { PDFfile fileposition PDFfile read pop 32 gt { exit } if pop   } loop   PDFfile exch setfileposition   PDFfile pdfstring readline pop   (xref) linene { /readxref cvx /syntaxerror signalerror } if		% Store the xref table entry position for each object.		% We only need to read the run headers, not every entry.    { PDFfile token pop		% first object # or trailer      dup /trailer eq { pop exit } if      PDFfile pdfstring readline pop      token pop			% entry count      exch pop exch		% This section might be adding new objects:		% ensure that Objects and Generations are big enough.		% Stack: count obj#      2 copy add growPDFobjects      PDFfile fileposition 3 -1 roll       { Objects 2 index lget null eq	% later update might have set it	  { Objects 2 index 2 index cvx lput }         if exch 1 add exch 20 add       }      repeat PDFfile exch setfileposition pop    } loop   count /pdfemptycount exch def   PDFfile traileropdict .pdfrun } bind def % Open a PDF file and read the header, trailer, and cross-reference./pdfopen {		% <file> pdfopen <dict>  pdfopenfile begin  pdfopencache  .writepdfmarks {	% Copy bookmarks (outline) to the output.    Trailer /Root oget /Outlines knownoget {      /First knownoget {	{ dup writeoutline /Next knownoget not { exit } if } loop      } if    } if  } if		% end .writepdfmarks  currentdict end} bind def/pdfopencache {		% - pdfopencache -	% Create and initialize some caches.  /PageCount pdfpagecount def  /PageNumbers PageCount dict def  /PageIndex PageCount array def} bind def/pdfopenfile {		% <file> pdfopenfile <dict>   pdfdict readonly pop		% can't do it any earlier than this   15 dict begin   /LocalResources 0 dict def   /DefaultMatrix null def	% establish binding   /Printed where { pop } {		% Guess whether the output device is a printer.     /Printed currentpagedevice /OutputFile known def   } ifelse   /PSLevel1 where { pop } { /PSLevel1 false def } ifelse   cvlit /PDFfile exch def   /PDFsource PDFfile def   /Repaired false def   PDFfile dup 0 setfileposition pdfstring readstring    not {/pdfopen cvx /syntaxerror signalerror} if   (%PDF-) search not {/pdfopen cvx /syntaxerror signalerror} if   length /PDFoffset exch def pop cvr /PDFversion exch def   findxref   initPDFobjects	% Read the last cross-reference table.   readxref /Trailer exch def   Trailer /Encrypt known    { pdf_process_Encrypt	% signal error    }   if	% Read any previous cross-reference tables.   Trailer { /Prev .knownget not { exit } if readxref } loop   Repaired { printrepaired } if   currentdict end } bind def % Skip backward over the %%EOF at the end of the PDF file, and read% the preceding startxref line.  The PDF specification unambiguously% requires that the %%EOF appear on a line by itself, and that the% startxref and the following position value appear on separate lines;% however, some applications (including, apparently, Acrobat Distiller% on the Macintosh) may add up to 2K of garbage after the %%EOF, and some% other applications also truncate the %%EOF to %%EO, and/or put the% startxref and the following value on the same line./findxref {		% - findxref <xrefpos>  PDFfile dup dup 0 setfileposition bytesavailable  dup /PDFfilelen exch def	% Find the last %%EOF string (within 2048 bytes)  2048 sub PDFoffset .max  2 copy setfileposition  PDFfilelen exch sub string 1 index exch readstring pop {    (\015%%EO) search {		% Adobe can handle truncated key string      pop pop			% if found, keep searching 'post' string    } {      (\012%%EO) search	{ pop pop } { exit } ifelse	% exit if neither string found    } ifelse  } loop  PDFfilelen exch length sub 4 sub PDFoffset .max exch 1 index setfileposition	% Stack: eofpos	% Check for whether this is, in fact, a valid PDF file.  dup PDFfilelen exch sub dup dup 7 gt exch 6 lt or {    pop true  } {    string PDFfile exch readstring pop    dup (%%EOF\n) eq exch dup (%%EOF\r) eq    exch (%%EOF\r\n) eq or or not  } ifelse {    (   **** This file has a corrupted %%EOF marker, or garbage after the %%EOF.) pdfformaterror  } if  PDFfile exch setfileposition	% Now read the startxref and xref start position.  prevline token not { null } if dup type /integertype eq {    exch pop cvi		% xref start position    exch PDFfile exch setfileposition    prevline (startxref) linene { /findxref cvx /syntaxerror signalerror } if    pop  } {	% else, this file has 'startxref #####' format    (startxref) ne { /findxref cvx /syntaxerror signalerror } if    cvi		% xref start position    (   **** The format of the startxref line in this file is invalid.) pdfformaterror    exch PDFfile exch setfileposition  } ifelse} bind def/stderrprint {		% <string> stderrprint -  (%stderr) (w) file dup dup 4 -1 roll writestring flushfile closefile} bind def/pdfformaterror {	% <string> pdfformaterror -  stderrprint  /Repaired true store} bind def/printrepaired {  Trailer /Info knownoget {    /Producer knownoget not { null } if  } {    null  } ifelse  dup null eq {    pop (\   **** Please notify the author of the software that produced this file)  } {    (   **** The file was produced by ) stderrprint	% Handle a Unicode Producer.    (\376\377) anchorsearch {      pop dup length 2 idiv string 0 1 2 index length 1 sub {		% Stack: origstr newstr i	1 index exch 3 index 1 index 2 mul 1 add get put      } for exch pop    } if    stderrprint    (:   **** please notify the author of this software)  } ifelse stderrprint(\   **** that the file does not conform to Adobe's published PDF   **** specification.  Processing of the file will continue normally. ) stderrprint} bind def % Write the outline structure for a file.  Uses linkdest (below)./writeoutline		% <outlinedict> writeoutline - { mark   0 2 index /First knownoget    { { exch 1 add exch /Next knownoget not { exit } if } loop }   if		% stack: dict mark count   dup 0 eq    { pop 1 index    }    { 2 index /Count knownoget { 0 lt { neg } if } if      /Count exch 3 index    }   ifelse linkdest /Title oget /Title exch /OUT pdfmark   /First knownoget    { { dup writeoutline /Next knownoget not { exit } if } loop }   if } bind def % Close a PDF file./pdfclose		% <dict> pdfclose - { begin   PDFfile closefile   end } bind def % ======================== Page accessing ======================== % % Get a (possibly inherited) attribute of a page./pget			% <pagedict> <key> pget <value> -true-			% <pagedict> <key> pget -false- { 2 copy knownoget    { exch pop exch pop true    }    { exch /Parent knownoget       { exch pget }       { pop false }      ifelse    }   ifelse } bind def % Get the value of a resource on a given page./rget {			% <resname> <pagedict> <restype> rget <value> -true-			% <resname> <pagedict> <restype> rget -false-  LocalResources 1 index knownoget {     3 index knownoget  } {    false  } ifelse {    exch pop exch pop exch pop true  } {    exch /Resources pget {      exch knownoget { exch knownoget } { pop false } ifelse    } {      pop pop false    } ifelse  } ifelse} bind def % Get the total number of pages in the document./pdfpagecount		% - pdfpagecount <int> { Trailer /Root oget /Pages oget /Count oget } bind def % Find the N'th page of the document by iterating through the Pages tree.% The first page is numbered 1./pdffindpageref {		% <int> pdffindpage <objref>  dup Trailer /Root oget /Pages get    {		% We should be able to tell when we reach a leaf		% by finding a Type unequal to /Pages.  Unfortunately,		% some files distributed by Adobe lack the Type key		% in some of the Pages nodes!  Instead, we check for Kids.      dup oforce /Kids knownoget not { exit } if      exch pop null      0 1 3 index length 1 sub {         2 index exch get	 dup oforce dup /Kids known { /Count oget } { pop 1 } ifelse		% Stack: index kids null noderef count	 dup 5 index ge { pop exch pop exit } if	 5 -1 roll exch sub 4 1 roll pop      } for exch pop		% Stack: index null|noderef      dup null eq { pop pop 1 null exit } if    } loop		% Stack: index countleft noderef   1 index 1 ne { pop pop /pdffindpage cvx /rangecheck signalerror } if   exch pop   PageIndex 2 index 1 sub 2 index oforce put   PageNumbers 1 index oforce 3 index put   exch pop} bind def/pdffindpage {		% <int> pdffindpage <pagedict>  pdffindpageref oforce} bind def % Find the N'th page of the document.% The first page is numbered 1./pdfgetpage		% <int> pdfgetpage <pagedict> { PageIndex 1 index 1 sub get dup null ne    { exch pop oforce }    { pop pdffindpage }   ifelse } bind def % Find the page number of a page object (inverse of pdfgetpage)./pdfpagenumber		% <pagedict> pdfpagenumber <int> {	% We use the simplest and stupidest of all possible algorithms....   PageNumbers 1 index .knownget    { exch pop    }    { 1 1 PageCount 1 add	% will give a rangecheck if not found       { dup pdfgetpage oforce 2 index eq { exit } if pop       }      for exch pop    }   ifelse } bind def % Display a given page./boxrect		% [<llx> <lly> <urx> <ury>] boxrect <x> <y> <w> <h> { aload pop exch 3 index sub exch 2 index sub } bind def/resolvedest {		% <name|string|other> resolvedest <other|null>  dup type /nametype eq {    Trailer /Root oget /Dests knownoget {      exch knownoget not { null } if    } {      null    } ifelse  } {    dup type /stringtype eq {      Trailer /Root oget /Names knownoget {	/Dests knownoget {	  exch nameoget	} {	  pop null	} ifelse      } {	pop null      } ifelse    } if  } ifelse} bind def/linkdest {		% <link|outline> linkdest			%   ([/Page <n>] /View <view> | ) <link|outline>  dup /Dest knownoget    { resolvedest      dup type /dicttype eq { /D knownoget not { null } if } if      dup null eq       { pop }       { dup 0 oget	 dup null eq	  { pop }	  { dup type /integertype ne { pdfpagenumber } if	    /Page exch 4 -2 roll	  }	 ifelse

Lines 1–500 of 740.