1337 lines · 44.4 KB · Text
RawDownload
%    Copyright (C) 1994, 2000 Aladdin Enterprises.  All rights reserved.% % This software is provided AS-IS with no warranty, either express or% implied.% % This software is distributed under license and may not be copied,% modified or distributed except as expressly authorized under the terms% of the license contained in the file LICENSE in this distribution.% % For more information about licensing, please refer to% http://www.ghostscript.com/licensing/. For information on% commercial licensing, go to http://www.artifex.com/licensing/ or% contact Artifex Software, Inc., 101 Lucas Valley Road #110,% San Rafael, CA  94903, U.S.A., +1(415)492-9861. % $Id: pdf_main.ps,v 1.100 2005/09/23 18:21:23 ray 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  systemdict /DOPDFMARKS known or } 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/run {  dup type /filetype ne { (r) file } if  % skip leading whitespace characters (actually anything less than or equal to <sp>)  { dup ( ) .peekstring not { false exit } if    dup 0 get 32 le { pop dup read pop pop } { true exit } ifelse  } loop  {    (%) eq {      dup (     ) .peekstring {	(%PDF-) eq {	    dup (%stdin) (r) file eq {	      % Copy PDF from stdin to temporary file then run it.	      null (w+) //systemdict /.tempfile get exec exch 3 1 roll	      % stack: tempname stdin tempfile	      64000 string	      {		% stack: tempname stdin tempfile string		2 index 1 index readstring		exch 3 index exch writestring		not { exit } if	      }	      loop	      pop exch closefile	      % stack: tempname tempfile	      dup 0 setfileposition	      dup runpdf	      closefile deletefile	    } {	      runpdf	    } ifelse	  } {	    cvx .runps % doesn't start with %PDF-	  } ifelse	} {	  pop cvx .runps % didn't read 5 characters	} ifelse    } {      cvx .runps % didn't start with %    } ifelse  } {    pop closefile % file was empty  } ifelse} bind odefcurrentdict /runpdfstring .undef  /runpdfbegin {		% <file> runpdf -   userdict begin	% It turns out that the PDF interpreter uses memory more	% effectively if it is run under at least one level of save.	% This is counter-intuitive, and we don't understand why it happens,	% but the improvement is significant.   /PDFTopSave save def   0 setobjectformat   /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    { oforce_array normrect mark /CropBox 3 -1 roll /PAGES pdfmark    }   if   /FirstPage where     { pop FirstPage dup pdfpagecount gt      { (\nRequested FirstPage is greater than the number of pages in the file: ) print        pdfpagecount = flush      } if    } {      1    } ifelse   /LastPage where { pop LastPage pdfpagecount .min } { pdfpagecount } ifelse   1 index 1 index gt    { (   No pages will be processed \(FirstPage > LastPage\).) = flush }    { QUIET not      { (Processing pages ) print 1 index =only ( through ) print dup =only        (.) = flush      }     if    }   ifelse} bind def /dopdfpages {   % firstpage# lastpage# dopdfpages -  << /PDFScanRules true >> setuserparams	% set scanning rules for PDF vs. PS  1 exch    { dup /Page# exch store      QUIET not { (Page ) print dup == flush } if      pdfgetpage pdfshowpage    } for  << /PDFScanRules null >> setuserparams	% restore scanning rules for PS} bind def /runpdfend {   Repaired { printrepaired } if   currentdict pdfclose   end			% temporary dict   end			% pdfdict   end			% GS_PDF_ProcSet   PDFTopSave restore   end			% userdict} bind def /runpdf {		% <file> runpdf -  runpdfbegin  dopdfpages  runpdfend} bind def end			% 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 } stopped {	      (   **** File has unbalanced >> in trailer.\n) pdfformaterror             } if } bind  ([) cvn { mark } bind		% ditto  (]) cvn dup load%  /true true		% see .pdfexectoken in pdf_base.ps%  /false false		% ibid.%  /null null		% ibid.  /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 original version (pre PDF 1.5) of the xref table. %  Note:  The position is the location of 'xref'.  The current PDFfile %  position is just after the 'XREF'./readorigxref		% <pos> readorigxref <trailerdict> {   pop				% We do not need the position.   0				% Initialize xref table error counter   { PDFfile token pop		% first object # or trailer     dup /trailer eq { pop exit } if     PDFfile pdfstring readline pop     token pop			% entry count     % remaining must be whitespace only (otherwise this xref Size was invalid.     exch dup length 0 ne {       false 1 index { 32 gt { pop true exit } if } forall {         (   **** Warning: xref subsection header has extra characters.\n)         pdfformaterror         /setxrefentry cvx /syntaxerror signalerror       } if     } if     pop			% remove last		% This section might be adding new objects:		% ensure that Objects and Generations are big enough.		% stack: <err count> <first obj> <entry count>     2 copy add growPDFobjects     {				% stack: <err count> <obj num>		% Read xref line       PDFfile 20 string readstring pop  % always read 20 chars.       token pop		% object position       exch token pop		% generation #       exch token pop		% n or f       exch			% stack: <err count> <obj#> <loc> <gen#> <tag> <remainder of line>       dup length 0 ne {         % check to make sure trailing garbage is just white space	 dup { 32 gt { 5 -1 roll 1 add 5 1 roll } if } forall   % bump error count on garbage       } if       pop			% Stack: <err count> <obj#> <loc> <gen#> <tag>       dup /n eq {		% xref line tag is /n	 pop			% pop dup of line tag         Objects 3 index lget null eq {	% later update might have set it	   0 3 1 roll		% Set ObjectStream object number = 0	   setxrefentry		% Save xref entry	   3 -1 roll pop	% Remove ObjectStream object onumber         } if       }       {			% xref line tag was not /n	 /f ne			% verify that the tag was /f         { /setxrefentry cvx /syntaxerror signalerror	 } if       } ifelse       pop pop			% pop <obj location> and <gen num>       % stack: <err count> <obj num>       1 add			% increment object number     } repeat     pop			% pop <obj #>   } loop   0 ne {     (   **** Warning:  length of some xref entries is not equal to 20 bytes.\n)     pdfformaterror   } if   PDFfile traileropdict .pdfrun } bind def  % This dicitonary is used to read the xref dictionary.  It should work for % reading any dictionary.  dictlevelcount must contain 0./xrefopdict mark  (<<) cvn { /dictlevelcount dictlevelcount 1 add def mark } bind  (>>) cvn { .dicttomark /dictlevelcount dictlevelcount 1 sub def  	     dictlevelcount 0 eq { exit} if } bind  ([) cvn { mark } bind		% ditto  (]) cvn dup load%  /true true		% see .pdfexectoken in pdf_base.ps%  /false false		% ibid.%  /null null		% ibid.  /R { /resolveR cvx 3 packedarray cvx } bind	% see Objects below.dicttomark readonly def % Get a variable length positive integer value from a stream.  A value% of zero is returned if the count is zero./getintn {	% <stream> <count> getintn int  0 exch { 256 mul 1 index read pop add } repeat  exch pop			% Discard stream} bind def % This array contains handlers for processing the different types of% entries in the XRef stream.% Stack: <Xrefdict> <xref stream> <Index array> <pair loc> <obj num>% 	 <field 2> <field 3>% The handlers leave the stack unchanged./xref15entryhandlers [  {	% XRef entry type 0 - free or f type xref entry%    (free ) print%    (obj num: ) print 2 index pdfstring cvs print ( ) print%    (loc: ) print 1 index pdfstring cvs print ( ) print%    (gen: ) print dup === flush  } bind		% Do nothing for free xref entries	% XRef entry type 1 - normal or n type xref entry  {	% field 2 = obj loc, field 3 = gen num%    (normal ) print%    (obj num: ) print 2 index pdfstring cvs print ( ) print%    (loc: ) print 1 index pdfstring cvs print ( ) print%    (gen: ) print dup === flush    0 3 1 roll			% set stream number = 0    setxrefentry    3 -1 roll pop		% remove stream number  } bind	% XRef entry type 2 - compressed object type xref entry  {	% field 2 = object stream num, field 3 = index into object stream%    (Compressed objects: ) print%    (obj num: ) print 2 index pdfstring cvs print ( ) print%    (field 2: ) print 1 index pdfstring cvs print ( ) print%    (field 3: ) print dup === flush    0 setxrefentry pop		% set generation number = 0  } bind] def  %  Read the PDF 1.5 version of the xref table. %  Note:  The position is the location of the start of the dictionary object %  In PDF 1.5, the XRef dictionary also serves as the trailer dictionary/readpdf15xref		% <pos> readpdf15xref <trailerdict> {   PDFfile exch setfileposition		% move to start of object   	% Get object number, revision, and 'obj' and discard   PDFfile token pop pop   PDFfile token pop pop   PDFfile token pop pop	% Get the XRef dicitionary   /dictlevelcount 0 def PDFfile xrefopdict .pdfrun	% Verify that we have an XRef dictionary   dup /Type get /XRef ne {     /readpdf15xref cvx /syntaxerror signalerror   } if   	% Ensure that we we have room in the objects array, etc.   dup /Size get growPDFobjects	% Create a stream for the XRef data   PDFfile token pop pop		% Skip over 'stream'   dup stream false resolvestream   	% Stack: <XRefdict> <xref stream>	% The Index array defines the ranges of object numbers in the	% XRef stream.  Each value pair is consists of starting object	% number and the count of consecutive objects.	% Get the Index array, if present   1 index /Index .knownget not {	% If no Index array ...     [ 0 3 index /Size get ]		% Default = [ 0 Size ]   } if	% Loop through the Index array   0 2 2 index length 1 sub {	% Get start and end of object range     2 copy get				% Start of the range     dup 3 index 3 index 1 add get 	% Number of entries in range     	% Loop through the range of object numbers     add 1 sub 1 exch {			% Form end of range, set increment = 1	% Stack: <Xrefdict> <xref stream> <Index array> <pair loc> <obj num>	% Get xref parameters.  Note:  The number of bytes for each parameter	% is defined by the entries in the W array.       4 index /W get aload pop		% Get W array values       	% The first field indicates type of entry.  Get first field value.	% If the num. of bytes for field 1 is 0 then default field value is 1       3 -1 roll dup 0 eq { pop 1 } { 6 index exch getintn } ifelse	% Get the handler for the xref entry type.  We will execute the	% handler after we get the other two field values.       xref15entryhandlers exch get       3 -1 roll 6 index exch getintn	% Get second field       3 -1 roll 6 index exch getintn	% Get third field       3 -1 roll exec			% Execute Xref entry handler       pop pop pop			% Remove field values and obj num     } for				% Loop through Xref entries     pop				% Remove Index array pair loc   } for				% Loop through Index array entries   pop pop				% Remove Index array and xref stream } bind def % Read the cross-reference table.% <pos> is the position either from the startxref statement or the /Prev% entry in the prior trailer dictionary./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   dup		% Make copy of the file position (before last char was read).   PDFfile exch setfileposition		% The PDF specification says that the 'xref' must be on a line		% by itself. The code here formerly used readline and linene to		% check this. However, Acrobat Reader only requires the line to		% begin with 'xref', and there are enough applications producing		% non-compliant PDF files that we have to do this too.   PDFfile pdfstring 0 4 getinterval readstring pop   (xref) eq   { readorigxref } 	% 'xref' -> original xref table   { readpdf15xref }	% otherwise assume PDF 1.5 xref stream   ifelse } bind def % Open a PDF file and read the header, trailer, and cross-reference./pdfopen {		% <file> pdfopen <dict>	% Color space substitution in PDF is handled somewhat differently	% than in PostScript. A given device color space will be substituted	% if the corresponding "Default..." entry exists in the Page's	% Resource dictionary (which might be inhereted); there is no	% UseCIEColor to enable/disable color mapping.	%	% This behavior is achieved by always setting UseCIEColor to true	% in the page device dictionary. If the value of this parameter was	% originally false (i.e.: the output device does not perform color	% space substitution by default), the instances DefaultGray,	% DefaultRGB, and DefaultCMYK of the (local) ColorSpace category	% are redefined to be DeviceGray, DeviceRGB, and DeviceCMYK,	% respectively. This is not done if UseCIEColor is true by default,	% as in that case color substitution is presumably desired even	% if the file does not request it.   currentpagedevice /UseCIEColor .knownget dup { pop } if not    { .currentglobal false .setglobal      /DefaultGray { /DeviceGray } cvlit /ColorSpace defineresource pop      /DefaultRGB { /DeviceRGB } cvlit /ColorSpace defineresource pop      /DefaultCMYK { /DeviceCMYK } cvlit /ColorSpace defineresource pop      .setglobal    }   if  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 % Verify that each entry in the xref table is pointing at an object with% the correct object number and generation number./verify_xref				% - verify_xref -{ 1 1 Objects llength 1 sub		% stack: 1 1 <number of objects - 1>  {	% Check if the object is free (i.e. not used).  The values in	% Generations is the generation number plus 1.  If the value in	% Generations is zero then the object is free.    Generations 1 index lget 		% Get the genration number    0 ne {				% Skip if object number is free      ObjectStream 1 index lget 	% Check if object is in objectstream      0 eq {	% We only check objects not in an objectstream        {	% Use stop context since we may get an error if object is invalid          dup Objects exch lget 	% Get the object location	  PDFoffset add PDFfile exch setfileposition	  true				% Stack:  <obj num> <true>	  PDFfile token pop		% Read object number from file	  2 index eq {			% Verify object number	    PDFfile token pop		% Read generation number from file	    Generations 3 index		% Get specified generaton number	    lget 1 sub			% Gen numbs are stored with 1 added.	    eq { 			% Verify generation number	      PDFfile token pop /obj eq { % Verify 'obj' text		pop false		% We have valid object, do not rebuild	      } if	    } if	  } if	} .internalstopped	{ true } if			% If we stop then we need to rebuild	{ 	  (   **** Warning:  File has an invalid xref entry:  )	  pdfformaterror	  pdfstring cvs pdfformaterror	  (.  Rebuilding xref table.\n) pdfformaterror	  search_objects	  exit	} if				% If the entry is invalid      } if				% If not in an object stream    } if				% If object entry is not free    pop					% Remove object number  } for} bind odef /pdfopencache {		% - pdfopencache -	% Create and initialize some caches.  /PageCount pdfpagecount def  /PageNumbers PageCount 65534 .min dict def  /PageIndex PageCount 65534 .min array def

Lines 1–500 of 1337.