home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
swCHIP 1991 January
/
swCHIP_95-1.bin
/
utility
/
gs333ini
/
gs3.33
/
pdf_main.ps
< prev
next >
Wrap
Text File
|
1995-12-09
|
11KB
|
371 lines
% Copyright (C) 1994, 1995 Aladdin Enterprises. All rights reserved.
% pdf_main.ps
% PDF file- and page-level operations.
% We don't handle the following PDF elements yet (identified by
% page number in the reference manual):
% Rotate (53)
% We do handle the following as yet undocumented PDF 1.1 extensions:
%
% - The Dest element of a link or outline entry can be a name,
% in which case it is looked up in the (optional) Dests dictionary
% that can appear as an element of the Catalog.
%
% - The page identifier in a link Dest element can be null, meaning
% the same page as the link itself appears on.
/.setlanguagelevel where { pop 2 .setlanguagelevel } if
.currentglobal true .setglobal
/pdfdict where { pop } { /pdfdict 100 dict def } ifelse
pdfdict begin
% 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
.dicttomark readonly def
% ======================== Main program ======================== %
end % pdfdict
userdict 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 pop
DingbatsEncoding pop
% Redefine 'run' so it recognizes PDF files.
systemdict begin
/runps /run load def
/run
{ dup type /filetype ne { (r) file } if
dup read
{ dup (%) 0 get eq
{ pop dup =string readline pop
(PDF-) anchorsearch
{ pop pop runpdf }
{ pop cvx exec }
ifelse
}
{ 2 copy unread pop cvx exec
}
ifelse
}
{ closefile
}
ifelse
} bind odef
/runpdf % <file> runpdf -
{ userdict begin
/PSFile where { pop PSFile (w) file /PSout exch def } if
/Page# null def
/Page null 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
(.\n) print flush
}
if
{ dup /Page# exch store
QUIET not { (Page ) print dup == flush } if
[ (%%Page: ) 2 index ( ) 1 index #dsc
pdfgetpage /Page exch store
save /PDFSave exch store
(before exec) VMDEBUG
Page pdfshowpage
(after exec) VMDEBUG
PDFSave restore
} for
currentdict pdfclose
end
end
end
} bind def
% Rebind procedures that invoke 'run'.
/runlibfile
{ findlibfile dup pop
{ exch pop run }
{ /undefinedfilename signalerror }
ifelse
} bind def
/.runlibfile /runlibfile load def
end % systemdict
end % userdict
pdfdict begin
% ======================== File parsing ======================== %
% Read the cross-reference and trailer sections.
/traileropdict mark
(<<) cvn { mark } bind
(>>) cvn /.dicttomark load
/[ { mark } bind % ditto
/] /] 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>
{ 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 pdfstring readline pop
dup (trailer) lineeq { pop exit } if
token pop % first object #
exch token pop % entry count
exch pop exch
% Stack: count obj#
PDFfile fileposition 3 -1 roll
{ Objects 2 index get null eq % later update might have set it
{ Objects 2 index 2 index cvx put }
if exch 1 add exch 20 add
}
repeat PDFfile exch setfileposition pop
} loop
PDFfile traileropdict pdfrun
} bind def
% Open a PDF file and read the trailer and cross-reference.
/pdfopen % <file> pdfopen <dict>
{ 10 dict begin
cvlit /PDFfile exch def
/PDFsource PDFfile def
PDFfile dup dup 0 setfileposition bytesavailable setfileposition
prevline (%%EOF) linene { /pdfopen cvx /syntaxerror signalerror } if
PDFfile exch setfileposition
prevline cvi % xref start position
exch PDFfile exch setfileposition
prevline (startxref) linene { /pdfopen cvx /syntaxerror signalerror } if
% Scan backwards for the start of the trailer,
% since we have to read the trailer before the first xref section.
{ PDFfile exch setfileposition
prevline (trailer) lineeq { exit } if
}
loop pop PDFfile traileropdict pdfrun
% Stack: xrefpos trailerdict
/Trailer exch def
Trailer /Size get
/Objects 1 index array def
/Generations exch string def
% Read the last cross-reference table.
readxref pop
% Read any previous cross-reference tables.
Trailer { /Prev .knownget not { exit } if readxref } loop
% Create and initialize some caches.
/PageCount pdfpagecount def
/PageNumbers PageCount dict def
% Write the DSC header if appropriate.
[ (%!PS-Adobe-1.0) #dsc
[ (%%Pages: ) pdfpagecount #dsc
[ (%%EndComments) #dsc
[ (%%BeginProlog) #dsc
[ (\(gs_pdf.ps\) /runlibfile where { pop runlibfile } { run } ifelse) #dsc
[ (GS_PDF_ProcSet begin) #dsc
[ (%%EndProlog) #dsc
% Copy bookmarks (outline) to the output.
Trailer /Root oget /Outlines knownoget
{ /First knownoget
{ { dup writeoutline /Next knownoget not { exit } if } loop }
if
}
if
currentdict end
} 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
/PSout where { pop [ (%%Trailer) #dsc PSout closefile } if
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 total number of pages in the document.
/pdfpagecount % - pdfpagecount <int>
{ Trailer /Root oget /Pages oget /Count oget
} bind def
% Get the N'th page of the document.
% The first page is numbered 1.
/pdfgetpage % <int> pdfgetpage <pagedict>
{ dup Trailer /Root oget /Pages oget
{ % 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 /Kids knownoget not { exit } if
exch pop null
0 1 3 index length 1 sub
{ 2 index exch oget
dup /Kids known { dup /Count oget } { 1 } ifelse
% Stack: index kids null node count
dup 5 index ge { pop exch pop exit } if
5 -1 roll exch sub 4 1 roll pop
}
for exch pop
dup null eq { pop pop 1 null exit } if
}
loop
1 index 1 ne { pop pop /pdfgetpage cvx /rangecheck signalerror } if
exch pop exch pop
} 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
PageNumbers 3 -1 roll 2 index put
}
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
/linkdest % <link|outline> linkdest
% ([/Page <n>] /View <view> | ) <link|outline>
{ dup /Dest knownoget
{ % Check for a name, to be looked up in Dests.
dup type /nametype eq
{ Trailer /Root oget /Dests oget exch oget /D get }
if
dup 0 oget
dup null eq
{ pop }
{ pdfpagenumber 1 add /Page exch 4 -2 roll }
ifelse
dup length 1 sub 1 exch getinterval /View exch 3 -1 roll
}
if
} bind def
/annottypes 5 dict dup begin
/Text
{ mark exch
{ /Rect /Open /Contents }
{ 2 copy knownoget { 3 -1 roll } { pop } ifelse }
forall pop /ANN pdfmark
} bind def
/Link
{ mark exch
{ /Rect /Border }
{ 2 copy knownoget { 3 -1 roll } { pop } ifelse }
forall linkdest pop /LNK pdfmark
} bind def
end def
/pdfshowpage % <pagedict> pdfshowpage -
{ dup /Contents knownoget not { 0 array } if
dup type /arraytype ne { 1 array astore } if
gsave
1 index /MediaBox pget
{ % We should really use setpagedevice to set the page size,
% but it doesn't work reliably yet.
boxrect statusdict /.setpagesize get exec
exch neg exch neg translate
}
{ initmatrix initclip
}
ifelse
1 index /CropBox pget
{ boxrect rectclip
1 index /CropBox knownoget { mark /CropBox 3 -1 roll /PAGE pdfmark } if
}
if
% Copy annotations and links.
1 index /Annots knownoget
{ 0 1 2 index length 1 sub
{ 1 index exch oget
dup /Subtype oget annottypes exch .knownget { exec } { pop } ifelse
}
for pop
}
if
exch pop
beginpage
{ oforce false resolvestream pdfopdict pdfrun } forall
endpage
grestore
/showpage 0 #
} bind def
end % pdfdict
.setglobal