⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pdf_base.ps

📁 GhostScript的源代码
💻 PS
📖 第 1 页 / 共 2 页
字号:
%    Copyright (C) 1994, 1996, 1997, 1998 Aladdin Enterprises.  All rights reserved.
% 
% This file is part of Aladdin Ghostscript.
% 
% Aladdin 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 Ghostscript Free Public
% License (the "License") for full details.
% 
% Every copy of Aladdin 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 Aladdin 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_base.ps $
% pdf_base.ps
% Basic parser for PDF reader.

% This handles basic parsing of the file (including the trailer
% and cross-reference table), as well as objects, object references,
% streams, and name/number trees; it doesn't include any facilities for
% making marks on the page.

/.setlanguagelevel where { pop 2 .setlanguagelevel } if
.currentglobal true .setglobal
/pdfdict where { pop } { /pdfdict 100 dict def } ifelse
pdfdict begin

% Define the name interpretation dictionary for reading values.
/valueopdict mark
  (<<) cvn { mark } bind	% don't push an actual mark!
  (>>) cvn /.dicttomark load
  ([) cvn { mark } bind		% ditto
  (]) cvn dup load
  /true true
  /false false
  /null null
  /F dup cvx		% see Objects section below
  /R dup cvx		% see Objects section below
  /stream dup cvx	% see Streams section below
.dicttomark readonly def

% ------ Utilities ------ %

% Define a scratch string.  The PDF language definition says that
% no line in a PDF file can exceed 255 characters.
/pdfstring 255 string def

% Read the previous line of a file.  If we aren't at a line boundary,
% read the line containing the current position.
% Skip any blank lines.
/prevline		% - prevline <startpos> <substring>
 { PDFfile fileposition dup () pdfstring
   2 index 257 sub 0 .max PDFfile exch setfileposition
    {		% Stack: initpos linepos line string
      PDFfile fileposition
      PDFfile 2 index readline pop
      dup length 0 gt
       { 3 2 roll 5 -2 roll pop pop 2 index }
       { pop }
      ifelse
		% Stack: initpos linepos line string startpos
      PDFfile fileposition 5 index ge { exit } if
      pop
    }
   loop pop pop 3 -1 roll pop
 } bind def

% Read a token from a file, recognizing the PDF 1.2 #nn escape convention.
% This should be done in C!
/.pdftoken {			% <file> .pdftoken <obj> -true-
				% <file> .pdftoken -false-
  token {
    dup type /nametype eq {
      dup xcheck {
	true
      } {
	PDFversion 1.2 ge {
	  dup .namestring (#) search {
	    name#escape cvn exch pop
	  } {
	    pop
	  } ifelse
	} if true
      } ifelse
    } {
      true
    } ifelse
  } {
    false
  } ifelse
} bind def
/name#escape			% <post> <(#)> <pre> name#escape <string>
{ exch pop
  1 index 2 () /SubFileDecode filter dup (x) readhexstring
		% Stack: post pre stream char t/f
  not { /.pdftoken cvx /syntaxerror signalerror } if
  exch closefile concatstrings
  exch 2 1 index length 2 sub getinterval
  (#) search { name#escape } if concatstrings
} bind def

% Execute a file, interpreting its executable names in a given
% dictionary.  The name procedures may do whatever they want
% to the operand stack.
/.pdfrun			% <file> <opdict> .pdfrun -
 {	% Construct a procedure with the stack depth, file and opdict
	% bound into it.
   1 index cvlit count 2 sub 3 1 roll mark mark 5 2 roll
    {	% Stack: ..operands.. count opdict file
      .pdftoken not { (%%EOF) cvn cvx } if
      dup xcheck
       { DEBUG { dup == flush } if
	 2 copy .knownget
	  { exch pop exch pop exch pop exec }
	  { BXlevel 0 le
	     { (%stderr) (w) file
	       dup (****************Unknown operator: ) writestring
	       dup 2 index .writecvs dup (\n) writestring flushfile
	     }
	    if pop pop
	    count exch sub { pop } repeat	% pop all the operands
	  }
	 ifelse
       }
       { exch pop exch pop DEBUG { dup ==only ( ) print flush } if
       }
      ifelse
    }
   aload pop .packtomark cvx
   /loop cvx 2 packedarray cvx
    { stopped /PDFsource } aload pop
   PDFsource
    { store { stop } if } aload pop .packtomark cvx
   /PDFsource 3 -1 roll store exec
 } bind def

% Execute a file, like .pdfrun, for a marking context.
% This temporarily rebinds LocalResources.
/.pdfruncontext {		% <resdict> <file> <opdict> .pdfruncontext -
  /.pdfrun load /LocalResources LocalResources /store load
  /LocalResources 8 -1 roll store 4 .execn
} bind def

% ------ File reading ------ %

% Read the cross-reference entry for an (unresolved) object.
% The caller must save and restore the PDFfile position if desired.
% For invalid (free) objects, we return 0.
/readxrefentry		% <object#> readxrefentry <objpos>
 { dup Objects exch lget
   PDFfile exch setfileposition
   PDFfile token pop		% object position
   PDFfile token pop		% generation #
   PDFfile token pop		% n or f
   dup /n eq
    { pop 1 add dup 255 gt
       { Generations ltype /stringtype eq
	  {		% Convert Generations from a string to an array.
	    larray Generations llength lgrowto dup
	    0 1 2 index llength 1 sub
	     { Generations 1 index lget lput dup
	     }
	    for pop /Generations exch store
	  }
	 if
       }
      if
    }
    { /f eq
       { pop 0 }
       { /readxrefentry cvx /syntaxerror signalerror }
      ifelse
    }
   ifelse
		% Stack: obj# objpos 1+gen#
   Generations 4 -1 roll 3 -1 roll lput
 } bind def

% ================================ Objects ================================ %

% Since we may have more than 64K objects, we have to use a 2-D array to
% hold them (and the parallel Generations structure).
/lshift 9 def
/lnshift lshift neg def
/lsubmask 1 lshift bitshift 1 sub def
/lsublen lsubmask 1 add def
/larray {	% - larray <larray>
  [ [] ]
} bind def
/lstring {	% - lstring <lstring>
  [ () ]
} bind def
/ltype {	% <lseq> type <type
  0 get type
} bind def
/lget {		% <lseq> <index> lget <value>
  dup //lsubmask and 3 1 roll //lnshift bitshift get exch get
} bind def
/lput {		% <lseq> <index> <value> lput -
  3 1 roll
  dup //lsubmask and 4 1 roll //lnshift bitshift get
  3 1 roll put
} bind def
/llength {	% <lseq> llength <length>
  dup length 1 sub dup //lshift bitshift
  3 1 roll get length add
} bind def
% lgrowto assumes newlength > llength(lseq)
/growto {	% <string/array> <length> growto <string'/array'>
  1 index type /stringtype eq { string } { array } ifelse
  2 copy copy pop exch pop
} bind def
/lgrowto {	% <lseq> <newlength> lgrowto <lseq'>
    dup //lsubmask add //lnshift bitshift dup 3 index length gt {
	% Add more sub-arrays.  Start by completing the last existing one.
		% Stack: lseq newlen newtoplen
    3 -1 roll dup llength 1 sub //lsubmask or 1 add lgrowto
		% Stack: newlen newtoplen lseq
    [ exch aload pop
    counttomark 2 add -1 roll		% newtoplen
    counttomark sub { dup 0 0 getinterval lsublen growto } repeat
    dup 0 0 getinterval ] exch
  } {
    pop
  } ifelse
	% Expand the last sub-array.
  1 sub //lsubmask and 1 add
  exch dup dup length 1 sub 2 copy
		% Stack: newsublen lseq lseq len-1 lseq len-1
  get 5 -1 roll growto put
} bind def

% We keep track of PDF objects using the following PostScript variables:
%
%	Generations (lstring): Generations[N] holds 1+ the current
%	    generation number for object number N.  (As far as we can tell,
%	    this is needed only for error checking.)  For free objects,
%	    Generations[N] is 0.
%
%	Objects (larray): If object N is loaded, Objects[N] is the actual
%	    object; otherwise, Objects[N] is an executable integer giving
%	    the file offset of the object's entry in the cross-reference
%	    table.
%
%	GlobalObjects (dictionary): If object N has been resolved in
%	    global VM, GlobalObjects[N] is the same as Objects[N]
%	    (except that GlobalObjects itself is stored in global VM,
%	    so the entry will not be deleted at the end of the page).
%
%	IsGlobal (lstring): IsGlobal[N] = 1 iff object N was resolved in
%	    global VM.  This is an accelerator to avoid having to do a
%	    dictionary lookup in GlobalObjects when resolving every object.

% Initialize the PDF object tables.
/initPDFobjects {		% - initPDFobjects -
  /Objects larray def
  /Generations lstring def
  .currentglobal true .setglobal
  /GlobalObjects 20 dict def
  .setglobal
  /IsGlobal lstring def
} bind def

% Grow the tables to a specified size.
/growPDFobjects {		% <minsize> growPDFobjects -
  dup Objects llength gt {
    dup Objects exch lgrowto /Objects exch def
  } if
  dup Generations llength gt {
    dup Generations exch lgrowto /Generations exch def
  } if
  dup IsGlobal llength gt {
    dup IsGlobal exch lgrowto /IsGlobal exch def
  } if
  pop
} bind def

% We represent an unresolved object reference by a procedure of the form
% {obj# gen# resolveR}.  This is not a possible PDF object, because PDF has
% no way to represent procedures.  Since PDF in fact has no way to represent
% any PostScript object that doesn't evaluate to itself, we can 'force'
% a possibly indirect object painlessly with 'exec'.
% Note that since we represent streams by executable dictionaries
% (see below), we need both an xcheck and a type check to determine
% whether an object has been resolved.
/unresolved? {		% <object#> unresolved? <bool>
  Objects 1 index lget dup xcheck exch type /integertype eq and {
    IsGlobal 1 index lget 0 eq {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -