diff options
author | Reinhard Kotucha <reinhard.kotucha@web.de> | 2015-05-05 21:26:28 +0000 |
---|---|---|
committer | Reinhard Kotucha <reinhard.kotucha@web.de> | 2015-05-05 21:26:28 +0000 |
commit | c51296e843e35a3d133557000409674baae01b54 (patch) | |
tree | 571fdfb2f2660b3c7d6bd5d522a1268a776f8ab4 /Master/tlpkg | |
parent | fe576e3d01b31dbc35e1bc4008052c06c47d3cf3 (diff) |
texlua scripts revised
pdfopt.tlu is using -dFastWebView now instead of pdfopt.ps
git-svn-id: svn://tug.org/texlive/trunk@37204 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/tlpkg')
-rw-r--r-- | Master/tlpkg/tlgs/lib/pdfopt.ps | 1272 |
1 files changed, 0 insertions, 1272 deletions
diff --git a/Master/tlpkg/tlgs/lib/pdfopt.ps b/Master/tlpkg/tlgs/lib/pdfopt.ps deleted file mode 100644 index 88a8943f278..00000000000 --- a/Master/tlpkg/tlgs/lib/pdfopt.ps +++ /dev/null @@ -1,1272 +0,0 @@ -% Copyright (C) 2001-2012 Artifex Software, Inc. -% 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. -% -% Refer to licensing information at http://www.artifex.com or contact -% Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, San Rafael, -% CA 94903, U.S.A., +1(415)492-9861, for further information. -% - -% PDF linearizer ("optimizer"). - -.currentglobal true .setglobal -/pdfoptdict 200 dict def -pdfoptdict begin - -% This linearizer is designed for simplicity, not for performance. -% See the main program (the last procedure in the file) for comments -% describing the main processing sequence. - -% ---------------- Utilities ---------------- % - -% ------ Data structures ------ % - -% Distinguish dictionaries, arrays, and everything else. -/ifdaelse { % <obj> <dictproc> <arrayproc> <otherproc> ifdaelse - - 3 index type dup /dicttype eq { - pop pop pop - } { - dup /arraytype ne exch /packedarraytype ne and { - exch - } if pop exch pop - } ifelse exec -} bind def - -% Implement dynamically growable arrays using a dictionary. -/darray { % <size> darray <darray> - dict -} bind def -/dadd { % <darray> <value> dadd - - 1 index length exch put -} bind def -/daforall { % <darray> <proc> daforall - - /exch cvx /get cvx 3 -1 roll /exec cvx 5 packedarray cvx - 0 1 2 index 0 get length 1 sub 4 -1 roll for -} bind def -/dacontents { % <darray> dacontents <array> - [ exch { } daforall ] -} bind def -/dacontstring { % <darray> dacontstring <string> - 0 1 index { exch pop length add } forall string - dup /NullEncode filter - % Stack: darray str filter - 3 -1 roll { 1 index exch writestring } daforall - closefile -} bind def - -% Force an object, mapping it if it is a reference. -/omforcenew { % <obj> omforce <obj'> <notseen> - dup oforce 2 copy eq { pop true } { exch 0 get omapnew exch pop } ifelse -} bind def -/omforce { % <obj> omforce <obj'> - omforcenew pop -} bind def -/omget { % <dict|array> <key> omget <obj> - get omforce -} bind def -% Visit an entire tree. -/omvisit { % <obj> omvisit - - omforcenew { - { { omvisit omvisit } forall } - { { omvisit } forall } - { pop } - ifdaelse - } { - pop - } ifelse -} bind def -% Visit a tree, stopping at references to Page objects. -% (This is only needed for the OpenAction in the Catalog.) -/omvisitnopage { % <obj> omvisitnopage - - dup oforce dup type /dicttype eq { - /Type .knownget { /Page eq } { false } ifelse - } { - pop false - } ifelse { - pop % Page reference - } { - omforcenew { - { { omvisitnopage omvisitnopage } forall } - { { omvisitnopage } forall } - { pop } - ifdaelse - } { - pop - } ifelse - } ifelse -} bind def - -% Collect the list of currently mapped object numbers, in order. -/omapped { % - omapped <obj#s> - RMap ld_length larray exch lgrowto - RMap { - 2 index 3 1 roll 1 sub exch lput - } ld_forall -} bind def - -% Collect the list of object numbers passed to omap by a procedure. -/visited { % <proc> visited <obj#s> - false currentomap 2 .execn - omapped exch setomap -} bind def - -% ------ Output ------ % - -% Provide a framework for closure-based streams. -.currentglobal false .setglobal -userdict /clostreams 20 dict put % stream -> [data endproc] -.setglobal -% Create a closure-based stream. -/clostream { % <data> <proc> <endproc> clostream <stream> - 2 index 3 -1 roll /exec load 3 packedarray cvx - /NullEncode filter - % Stack: data endproc stream - clostreams 1 index 5 -2 roll 2 array astore put -} bind def -% Close a closure-based stream. -/closend { % <stream> closend <result> - dup closefile clostreams exch - 2 copy get 3 1 roll undef aload pop exec -} bind def - -% Implement in-memory output streams. -/msproc { % <data> <more> <accum> msproc <scratch> - 3 -1 roll dadd { 100 string } { () } ifelse -} bind def -/mstream { % - mstream <mstream> - 10 darray {msproc} {dacontstring} clostream -} bind def -/mcontents { % <mstream> mcontents <string> - closend -} bind def - -% Implement a stream that only keeps track of its position. -% (All streams should do this, but the PLRM doesn't require it.) -/posbuf 100 string def -/posproc { % <data> <more> <accum> posproc <scratch> - 0 2 copy get 5 -1 roll length add put - pop //posbuf -} bind def -/postream { % - postream <postream> - [0] {posproc} {0 get} clostream -} bind def -/poslength { % <postream> poslength <pos> - closend -} bind def - -% Implement streams with variable-bit-width data. -% Note that these are dictionary objects, not stream objects. -/bitstream { % <stream> bitstream <bstream> - 4 dict begin /S exch def /N 8 def /B 0 def - currentdict end -} bind def -/bitwrite { % <bstream> <value> <width> bitwrite - - PDFOPTDEBUG { ( ) print 1 index =only (:) print dup = } if - 3 -1 roll begin - N exch sub dup 0 ge { - /N exch def N bitshift B add - } { - 2 copy bitshift B add S exch write - % Stack: value -left - { 8 add dup 0 ge { exit } if - 2 copy bitshift 255 and S exch write - } loop - /N 1 index def bitshift 255 and - } ifelse /B exch def - end -} bind def -/bitflush { % <bstream> bitflush - - begin N 8 ne { S B write /B 0 def /N 8 def } if end -} bind def - -/bwn { % <value> <width> bwn - - 2 copy % v w v w - 2 exch exp ge { % v w v>=2**w - /bwn cvx /rangecheck signalerror - } if - bits 3 1 roll bitwrite -} def - -% Capture OFile output on the temporary file, in memory, or just as a length. -/totemp { % <proc> totemp <start> <end> - TFile fileposition OFile - /OFile TFile def 3 .execn - /OFile exch def - TFile fileposition -} bind def -/tomemory { % <proc> tomemory <string> - OFile /OFile mstream def 2 .execn - OFile mcontents exch /OFile exch def -} bind def -/tolength { % <proc> tolength <string> - OFile /OFile postream def 2 .execn - OFile poslength exch /OFile exch def -} bind def - -% Copy a range of bytes from TFile to OFile. -/copyrange { % <start> <end> copybytes - - TFile 2 index setfileposition - exch sub 1024 string exch { - % Stack: buf left - 2 copy 1 index length .min 0 exch getinterval - TFile exch readstring pop OFile exch writestring - 1 index length sub dup 0 le { exit } if - } loop pop pop -} bind def - -% Pad with blanks to a specified position. -/padto { % <pos> padto - - OFile fileposition sub - dup 0 lt { - (ERROR: file position incorrect by ) print = - /padto cvx /rangecheck signalerror - } { - { ( ) ows } repeat - } ifelse -} bind def - -% ---------------- Read objects into memory ---------------- % - -/touch { % <object> touch - - { - { touch touch } forall - } { - dup xcheck { - % Executable array, must be an indirect object. - dup 0 get resolved? { pop pop } { oforce touch } ifelse - } { - { touch } forall - } ifelse - } { - pop - } ifdaelse -} bind def - -% ---------------- Replace references with referents ---------------- % - -/replaceable? { % <value> replaceable? <bool> - dup type /integertype eq exch xcheck not and -} bind def -/replacement { % <obj|ref> replacement <obj'> - dup oforce dup replaceable? { exch } if pop -} bind def - -/replacerefs { % <object> replacerefs <object> - { - dup { - 2 index 2 index undef - exch replacement exch replacement - 2 index 3 1 roll put - } forall - } { - 0 1 2 index length 1 sub { - 1 index exch 2 copy get replacement put - } for - } { - } ifdaelse -} bind def - -/replaceReferences { % - replaceReferences - - Objects { replacerefs pop } lforall - % Delete replaced objects. - 0 1 Objects llength 1 sub { - Objects 1 index lget replaceable? { - PDFOPTDEBUG { (Deleting ) print dup = } if - Generations 1 index 0 lput - } if pop - } for -} bind def - -% ---------------- Create new objects ---------------- % - -/createObjects { % [<obj>...] createObjects <firstobj#> - Objects llength dup - dup 3 index length add growPDFobjects - % Stack: objects objn objn - 3 1 roll exch { - Objects 2 index 3 -1 roll lput - Generations 1 index 1 lput - 1 add - } forall pop -} bind def - -% ---------------- Propagate attributes ---------------- % - -/nopropattrs << - % Never propagate these. - /Type dup /Kids dup /Count dup /Parent dup - % Handle Resources specially. - /Resources dup ->> def - -% Merge Resources. -/mergeres { % <fromdict> <todict> mergeres - - % Values in todict take priority over fromdict. - 1 index /Resources .knownget { - 1 index /Resources .knownget { - % Stack: fromdict todict fromres tores - exch oforce exch oforce - % todict's Resources may be shared, so make a copy. - dup length dict .copydict - exch { - % Stack: fromdict todict tores' fromkey fromvalue - 2 index 2 index knownoget { - % Stack: fromdict todict tores' fromkey fromvalue tovalue - exch oforce exch - % ProcSet is an array, other types are dictionaries. - dup type /dicttype eq { - % Dictionary, not ProcSet. - exch dup length 2 index length add dict .copydict .copydict - } { - % Array or packed array, ProcSet. - % Use dictionaries to do the merge. - dup length 2 index length add dict begin - exch { dup def } forall { dup def } forall - mark currentdict end { pop } forall .packtomark - } ifelse - } if - 2 index 3 1 roll put - } forall - } if /Resources exch put pop - } { - pop pop - } ifelse -} bind def - -% Merge attributes other than Resources. -/mergeattrs { % <fromdict> <todict> mergeattrs <fromdict> <todict> - % Values in todict take priority over fromdict. - 1 index { - % Stack: fromdict todict fromkey fromvalue - //nopropattrs 2 index known { - pop pop - } { - 2 index 2 index known { pop pop } { 2 index 3 1 roll put } ifelse - } ifelse - } forall -} bind def - -% Propagate attributes to a subtree. -/proppage { % <attrs> <subtree> proppage - - % 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 { - % Accumulate inherited values. - 3 1 roll - % Stack: kids attrs pagesnode - dup length dict .copydict mergeattrs - dup 3 1 roll mergeres - exch { oforce 1 index exch proppage } forall pop - } { - % Merge inherited values into the leaf. - mergeattrs mergeres - } ifelse -} bind def - -% Propagate attributes to all pages. -/propagateAttributes { % - propagateAttributes - - 0 dict Trailer /Root oget /Pages oget proppage -} bind def - -% ---------------- Identify document-level objects ---------------- % - -/identifyDocumentObjects { % - identifyDocumentObjects <obj#s> - { - Trailer /Root omget - dup /PageMode .knownget { omvisit } if - % Don't allow omvisit to trace references to Page objects. - dup /OpenAction .knownget { omvisitnopage } if - Trailer /Encrypt .knownget { omvisit } if - dup /Threads .knownget { - omforce dup //null ne { { omvisitnopage } forall } { pop } ifelse - } if - dup /AcroForm .knownget { omvisitnopage } if - pop - } visited -} bind def - -% ---------------- Identify the objects of each page ---------------- % - -/identifyfont { % <fontref> identifyfont - - omforce { - exch /FontDescriptor eq { - omforce dup /Flags .knownget { 32 and 0 ne } { false } ifelse - exch { - exch dup dup /FontFile eq exch /FontFile2 eq or - exch /FontFile3 eq or 2 index and { - fontfiles exch dadd - } { - omvisit - } ifelse - } forall pop - } { - omvisit - } ifelse - } forall -} bind def - -% Collect all the objects referenced from a page. The first object number -% (which may not be the smallest one) is that of the page object itself. -/identifyPageObjects { % <extra> <page#> identifyPageObjects <obj#s> - PDFOPTDEBUG { - (%Objects for page: ) print dup = - } if - pdffindpageref - dup 0 get 3 1 roll - 4 dict begin - /filter_params 10 darray def - /images 10 darray def - /fontfiles 10 darray def - { - omforce - % Stack: pageobj# extra page - % Visit any extra objects if applicable. - exch omvisitnopage - % Visit Annots, if any. - % We don't try to defer the drawing information. - dup /Annots .knownget { omvisitnopage } if - % Visit beads. - dup /B .knownget { omvisitnopage } if - % Visit resources dictionaries. - dup /Resources .knownget { - omforce dup { - % Visit the first-level Resource dictionaries. - omforce pop pop - } forall { - % Visit the resources themselves. - % Skip Image XObjects, and FontFile streams if the - % FontDescriptor Flags have bit 6 set. - % We don't try to visit the resources in the order in which - % the Contents stream(s) reference(s) them. - exch dup /XObject eq { - pop oforce { - dup oforce /Subtype get /Image eq { - dup oforce /DecodeParms .knownget { - oforce { - exch /JBIG2Globals eq { - filter_params exch dadd - } { - pop - } ifelse - } forall - } if - images exch dadd - } { - omvisit - } ifelse pop - } forall - } { - /Font eq { - oforce { identifyfont pop } forall - } { - oforce omvisit - } ifelse - } ifelse - } forall - } if - % Visit the Contents stream(s). - dup /Contents .knownget { omvisit } if - % Visit Image XObjects. We don't try to visit them in - % reference order. - filter_params { omvisit } daforall - images { omvisit } daforall - % Visit FontFile streams. We don't try to visit them in - % reference order. - fontfiles { omvisit } daforall - pop - } visited end - % Stack: pageobj# obj#s_larray - [ 3 1 roll { - 2 copy eq { pop } { exch } ifelse - } lforall counttomark 1 roll ] - PDFOPTDEBUG { - (%Objects = ) print dup === flush - } if -} bind def - -% Identify the objects of the first page. -/identifyFirstPageObjects { % - identifyFirstPageObjects <obj#s> - Trailer /Root oget null - 1 index /PageMode knownoget { - /UseOutlines eq { - 1 index /Outlines knownoget { exch pop } if - } if - } if exch pop - 1 identifyPageObjects -} bind def - -% Identify the non-shared objects of the other pages, and the shared objects. -% Note that the page objects themselves may appear to be shared, because of -% references from Dest entries in annotations, but they must be treated as -% non-shared. Note also that some objects referenced on the first page may -% also be referenced from other pages. -/identifyOtherPageObjects { % - identifyOtherPageObjects [<pageobj#s> ...] - % <sharedobj#s> - 4 dict begin - /marks lstring Objects llength lgrowto def - % Collect objects of other pages and identify sharing. - [ 2 1 pdfpagecount { null exch identifyPageObjects } for ] - dup { - { marks exch 2 copy lget 1 add 254 .min lput } forall - } forall - % Mark document-level and first page objects. - CatalogNs { marks exch 255 lput } lforall - FirstPageNs { marks exch 255 lput } forall - % Mark the page objects themselves as non-shared. - dup { - 0 get marks exch 1 lput - } forall - % Collect the non-shared objects of each page. - dup - [ exch { - [ exch { - marks 1 index lget 1 ne { pop } if - } forall ] - } forall ] - % Collect the shared objects of each page. - exch - [ exch { - [ exch { - marks 1 index lget dup 1 le exch 255 eq or { pop } if - } forall ] - } forall ] - - % Collect the shared objects. - [ 1 1 marks llength 1 sub { - marks 1 index lget dup 1 le exch 255 eq or { pop } if - } for ] - - end -} bind def - -% Identify objects not associated with any page. -/identifyNonPageObjects { % - identifyNonPageObjects <obj#s> - 4 dict begin - /marks lstring Objects llength lgrowto def - - LPDictN marks exch 1 lput - PHSN marks exch 1 lput - CatalogNs { marks exch 1 lput } lforall - FirstPageNs { marks exch 1 lput } forall - SharedNs { marks exch 1 lput } forall - OtherPageNs { { marks exch 1 lput } forall } forall - - %****** PUT THESE IN A REASONABLE ORDER ****** - /npobj larray - 0 - 1 1 Objects llength 1 sub { - marks 1 index lget 0 eq { - Generations exch lget 0 ne { 1 add } if - } { - pop - } ifelse - } for - lgrowto def - - 0 - 1 1 Objects llength 1 sub { - marks 1 index lget 0 eq { - % i - Generations 1 index lget 0 ne { - % i - npobj 2 index % i nobj 0 - 3 -1 roll % nobj 0 i - lput 1 add - } { - pop - } ifelse - } { - pop - } ifelse - } for - pop - - npobj - end -} bind def - -% ---------------- Assign object numbers ---------------- % - -% Assign object numbers to all objects that will be copied. -% Return the first (translated) object number in the First Page xref table. -/assignObjectNumbers { % - assignObjectNumbers - - OtherPageNs { { omap pop } forall } forall - SharedNs { omap pop } forall - NonPageNs { omap pop } lforall - % Assign object numbers for the First Page xref table last. - LPDictN omap % don't pop, this is the return value - CatalogNs { omap pop } lforall - FirstPageNs { omap pop } forall - PHSN omap pop -} bind def - -% ---------------- Create the LPDict ---------------- % - -% Create the contents of the LPDict. -/createLPDict { % <phsstart> <phsend> <firstpageend> - % <xref0start> <filelength> createLPDict - - LPDict - dup /Linearized 1 put - dup /L 4 -1 roll put % filelength - dup /T 4 -1 roll put % xref0start - dup /E 4 -1 roll put % firstpageend - dup /H 5 -2 roll 1 index sub 2 array astore put % phsstart, end-start - dup /O 1 pdffindpageref 0 get omap put - /N pdfpagecount put -} bind def - -% ---------------- Adjust object positions ---------------- % - -/adjustObjectPositions { % <boundary> <deltabelow> <deltaabove> - % adjustObjectPositions - - % Objects fall into 4 categories: LPDict, PHS, Catalog, and others. - % We handle the first two as special cases. - XRef { - % Stack: bdy below above key loc - dup 5 index ge { 2 } { 3 } ifelse index add - XRef 3 1 roll ld_put - } ld_forall pop pop pop - XRef LPDictN omap HeaderLength ld_put - XRef PHSN omap PHSStart ld_put -} bind def - -% ---------------- Write the output file ---------------- % - -% Write objects identified by object number. -/writeobjn { % <obj#> writeobjn - - Generations 1 index lget pdfwriteobj -} bind def -/writeobjns { % <obj#s> writeobjns - - { writeobjn } forall -} bind def -/lwriteobjns { % <obj#s> writeobjns - - { writeobjn } lforall -} bind def - -% Write a part of the output file. -/writePart { % <proc> <label> writePart - - PDFOPTDEBUG { - dup print ( count=) print count =only ( start=) print - OFile { .fileposition } stopped { pop (???) } if = - 2 .execn - print ( end=) print - OFile { .fileposition } stopped { pop (???) } if = - } { - pop exec - } ifelse -} bind def - -% Write the header. -/writePart1 { % - writePart1 - - { - pdfwriteheader - } (part1) writePart -} bind def - -% Write the linearization parameters dictionary. -/writePart2 { % - writePart2 - - { - LPDictN writeobjn - } (part2) writePart -} bind def - -% Write the First Page xref table and trailer. -% Free variables: FirstPageXN. -/writePart3 { % <xrefstart> writePart3 - - { - FirstPageXN NObjects 1 add 1 index sub pdfwritexref - Trailer dup length 1 add dict copy Trailer xcheck { cvx } if - dup /Size NObjects 1 add put - dup /Prev 4 -1 roll put - pdfwritetrailer - 0 pdfwritestartxref - } (part3) writePart -} bind def - -% Write the Catalog and other required document-level objects. -% Free variables: CatalogNs. -/writePart4 { % - writePart4 - - { - CatalogNs lwriteobjns - } (part4) writePart -} bind def - -% Write the Primary Hint Stream. -/writePart5 { % - writePart5 - - { - PHSN writeobjn - } (part5) writePart -} bind def - -% Write the First Page's objects. -% Free variables: FirstPageNs. -/writePart6 { % - writePart6 - - { - FirstPageNs writeobjns - } (part6) writePart -} bind def - -% Write the objects of other pages (Page + non-shared objects). -% Free variables: OtherPageNs. -/writePart7 { % - writePart7 <lengths> - { - [ OtherPageNs { - OFile fileposition exch - writeobjns OFile fileposition exch sub - } forall ] - } (part7) writePart -} bind def - -% Write the shared objects of other pages. -% Free variables: SharedNs. -/writePart8 { % - writePart8 - - { - SharedNs writeobjns - } (part8) writePart -} bind def - -% Write the other objects not associated with pages. -% Free variables: NonPageNs. -/writePart9 { % - writePart9 - - { - NonPageNs { writeobjn } lforall - } (part9) writePart -} bind def - -% Write the main xref table and trailer. -% Free variables: FirstPageXN. -/writePart11xref { % writePart11 - - { - 0 FirstPageXN pdfwritexref - } (part11xref) writePart -} bind def -/writePart11rest { % <part3start> writePart11rest - - { - << /Size FirstPageXN >> pdfwritetrailer - pdfwritestartxref - } (part11rest) writePart -} bind def - -% ---------------- Write hint tables ---------------- % - -/bitsneeded { % <maxvalue> bitsneeded <#bits> - 0 exch { dup 0 eq { pop exit } if exch 1 add exch 2 idiv } loop -} bind def - -% Find the start and end of objects in the output. -/omstart { % <obj#> omstart <pos> - PDFOPTDEBUG { (start\() print dup =only } if - omap - PDFOPTDEBUG { (=>) print dup =only } if - XRef exch ld_get - PDFOPTDEBUG { (\) = ) print dup = } if -} bind def -/omend { % <obj#> omend <pos> - % The end of an object is the start of the next object. - % The caller must be sure that this object is not the last one - % in part 9. - PDFOPTDEBUG { (end\() print dup =only } if - omap - PDFOPTDEBUG { (=>) print dup =only } if - 1 add - % Check that the requested object wasn't the last one in part 6: - % the next object in the output file is the first in part 7. - PHSN omap 1 index eq { pop 1 } if - XRef exch ld_get - PDFOPTDEBUG { (\) = ) print dup = } if -} bind def -/omlength { % <obj#> omlength <length> - dup omend exch omstart sub -} bind def - -% Find the Contents of a page. -/contentsobjects { % <pagedict> contentsobjects <firstobj#> <lastobj#> true - % <pagedict> contentsobjects false - /Contents .knownget { - dup oforce % ref [] - dup type /dicttype eq { - pop 0 get dup true % ref ref - } { - exch pop % [] - dup length 0 ne { - dup 0 get 0 get % [] 1st - exch dup % 1st [] [] - length 1 sub get 0 get % 1st last - true - } { - pop false - } ifelse - } ifelse - } { - false - } ifelse -} bind def - -/contentsstart { % <pagedict> contentsstart <pos> true - % <pagedict> contentsstart false - contentsobjects { pop omstart true } { false } ifelse -} bind def - -/contentslength { % <pagedict> contentslength <length> - contentsobjects { omend exch omstart sub } { 0 } ifelse -} bind def - -/writePageOffsetHints { - PDFOPTDEBUG { /writePageOffsetHints == } if - 20 dict begin - /bits OFile bitstream def - - % Calculate least length of a page. - FirstPageLength OtherPageLengths { .min } forall - /minpl exch def - - % Calculate least contents length. - FirstPageNs 0 get Objects exch lget contentslength - OtherPageNs { 0 get Objects exch lget contentslength .min } forall - /mincl exch def - - % The Adobe documentation says that all versions of Acrobat - % require item 8 (mincl) to be zero. Patch this here. - /mincl 0 def - - % Calculate bits needed to represent greatest page length. - FirstPageLength OtherPageLengths { .max } forall - minpl sub bitsneeded /maxplbits exch def - % Calculate bits needed to represent the greatest Contents length. - FirstPageNs 0 get Objects exch lget contentslength - OtherPageNs { 0 get Objects exch lget contentslength .max } forall - mincl sub bitsneeded /maxclbits exch def - - % Per Adobe documentation, Acrobat requires that item 5 (maxplbits) - % be equal to item 9 (maxclbits). Set both to the max of the two. - maxplbits maxclbits .max /maxplbits 1 index def /maxclbits exch def - - % Mapping from object number to shared object reference - /shared_id_dict FirstPageNs length SharedNs length add dict begin - 0 FirstPageNs { 1 index def 1 add } forall - SharedNs { 1 index def 1 add } forall - pop - currentdict end def - - % Table F.3 Page offset hint table, header section - - % 1: Least number of objects in a page: - FirstPageNs length OtherPageNs { length .min } forall - /minnop 1 index def 32 bwn - % 2: Location of first page's Page object: - FirstPageNs 0 get omap XRef exch ld_get 32 bwn - % 3: Bits needed to represent greatest # of objects in a page: - FirstPageNs length OtherPageNs { length .max } forall - minnop sub bitsneeded /maxnopbits 1 index def 16 bwn - % 4: Least length of a page: - minpl 32 bwn - % 5: Bits needed to represent the greatest page length: - maxplbits 16 bwn - % 6: Least start of Contents offset: - 0 % (Acrobat requires that this be 0.) - /minsco 1 index def 32 bwn - % 7: Bits needed to represent the greatest start of Contents - % offset: - 0 % (Acrobat ignores this.) - /maxscobits 1 index def 16 bwn - % 8: Least contents length: - mincl 32 bwn - % 9: Bits needed to represent the greatest Contents length: - maxclbits 16 bwn - % 10: Bits needed to represent the greatest number of Shared - % Object references: - FirstPageNs length SharedPageNs { length .max } forall bitsneeded - /maxsorbits 1 index def 16 bwn - % 11: Bits needed to identify a Shared Object: - FirstPageNs length SharedNs length add bitsneeded - /sobits 1 index def 16 bwn - % 12: Bits needed to represent numerator of fraction: - 2 - /numfbits 1 index def 16 bwn - % 13: Denominator of fraction: - 1 - /denf 1 index def 16 bwn - - % Table F.4 Page offset hint table, per-page entry - - % 1: Number of objects in pages: - FirstPageNs length minnop sub maxnopbits bwn - OtherPageNs { - length minnop sub maxnopbits bwn - } forall - bits bitflush - - % 2: Total length of pages in bytes; - FirstPageLength minpl sub maxplbits bwn - OtherPageLengths { - minpl sub maxplbits bwn - } forall - bits bitflush - - % 3: Number of shared objects referenced from page: - FirstPageNs length maxsorbits bwn - SharedPageNs { length maxsorbits bwn } forall - bits bitflush - % 4: A shared object identifier: - FirstPageNs { shared_id_dict exch get sobits bwn } forall - SharedPageNs { - { shared_id_dict exch get sobits bwn - } forall - } forall - bits bitflush - - % 5: Numerator of fractional position for each shared object: - FirstPageNs { pop 0 numfbits bwn } forall - SharedPageNs { - { pop 0 numfbits bwn - } forall - } forall - bits bitflush - - % 6: Contents offsets: - % Following Implementation Note 133 section 6 is empty. - maxscobits 0 gt { - [FirstPageNs OtherPageNs aload pop] { - 0 get Objects exch lget contentsstart { minsco sub } { 0 } ifelse - maxscobits bwn - } forall - bits bitflush - } if - - % 7: Contents lengths: - [FirstPageNs OtherPageNs aload pop] { - 0 get Objects exch lget contentslength mincl sub maxclbits bwn - } forall - bits bitflush - - end - -} bind def - -/writeSharedObjectHints { - PDFOPTDEBUG { /writeSharedObjectHints == } if - 20 dict begin - /bits OFile bitstream def - /obj_count SharedNs length FirstPageNs length add def - - % Table F.5 Shared object hint table, header section - - % 1: Object number of first object in Shared Objects section - 0 32 bwn - % 2: Location of first object in Shared Objects section: - % If there are no shared objects, - % Acrobat sets this to the location of linearization - % parameters object (the very first object). - { pdfwriteheader } tomemory length 32 bwn - % 3: Number of Shared Object entries for first page: - FirstPageNs length 32 bwn - % 4: Number of Shared Object entries for Shared Objects - % section - obj_count 32 bwn - % 5: Bits needed to represent the greatest number of objects - % in a shared object group (always 0, because all groups - % have only 1 object): - 0 16 bwn - % 6: Least length of a Shared Object Group in bytes: - 16#7fffffff FirstPageNs { omlength .min } forall - SharedNs { omlength .min } forall - /minsol 1 index def 32 bwn - % 7: Bits needed to represent the greatest length of a - % Shared Object Group: - 0 FirstPageNs { omlength .max } forall - SharedNs { omlength .max } forall - minsol sub bitsneeded - /maxsolbits 1 index def 16 bwn - - % Table F.6 Shared object hint table, shared object group entry - - % 1: Lengths of shared object groups: - FirstPageNs { omlength minsol sub maxsolbits bwn } forall - SharedNs { omlength minsol sub maxsolbits bwn } forall - bits bitflush - % 2: MD5 flag: - obj_count { 0 1 bwn } repeat - bits bitflush - % 3: No MD5 shared object signatures. - - % 4: No number_number_of_objects_in_the_group - 1 - end -} bind def - -% ---------------- Main program ---------------- % - -/pdfOptimize { % <infile> <outfile> pdfOptimize - - realtime 3 1 roll - exch pdfdict begin pdfopenfile dup begin - 40 dict begin - /IDict exch def - /OFile exch def - % Disable check for the max object number because pdfopt adds new objects. - /NumObjects 16#7fffffff store - /starttime exch def - /ToWrite 100 dict def - /now { - QUIET { pop } { print (, t = ) print realtime starttime sub = flush } ifelse - } def - omapinit - - % Create and open a temporary file. - % Because of .setsafe, we have to open it as read-write, rather than - % opening for writing, then closing it and reopening it for reading. - - null (w+) .tempfile /TFile exch def /TFileName exch def - .setsafe - - % Read all objects into memory. - - Trailer touch - (Read objects) now - - % Encrypted files are not yet supported. - Trailer /Encrypt known { - (ERROR: Encrypted files are not yet supported.) = flush - /pdfOptimize cvx /limitcheck signalerror - } if - - % Replace indirect references to numbers. This is needed - % for the Length of streams, and doesn't hurt anything else. - - replaceReferences - (Replaced references) now - - % Create the two new objects: the linearization parameter - % dictionary, and the Primary Hint Stream. - - /LPDict 10 dict def - /PHS 10 dict cvx def % executable = stream - [LPDict PHS] createObjects - /LPDictN 1 index def 1 add - /PHSN exch def - PDFOPTDEBUG { << /LPDictN LPDictN /PHSN PHSN >> === } if - - % Count the number of objects in the output. - - 0 0 1 Objects llength 1 sub { - Generations exch lget 0 ne { 1 add } if - } for - /NObjects exch def - QUIET not { NObjects =only ( objects total) = flush } if - - % Propagate inherited attributes down the page tree. - - propagateAttributes - (Propagated attributes) now - - % Identify the document-level objects (part 4). - - identifyDocumentObjects /CatalogNs exch def - QUIET not { CatalogNs === flush } if - (Identified Catalog) now - - % Identify the first page's objects (part 6), - % including the Outlines tree if appropriate. - - pdfopencache - /FirstPageNs identifyFirstPageObjects def - QUIET not { FirstPageNs === flush } if - (Identified first page) now - - % Identify shared vs. non-shared objects for remaining pages - % (parts 7 and 8). - - identifyOtherPageObjects - /SharedNs exch def - /SharedPageNs exch def - /OtherPageNs exch def - QUIET not { OtherPageNs === flush SharedNs === flush } if - (Identified other pages) now - - % Identify objects not associated with any page (part 9). - - /NonPageNs identifyNonPageObjects def - QUIET not { NonPageNs { === } forall flush } if - (Identified non-pages) now - - % Assign final object numbers to all the objects. - % (The omap is currently empty.) - - /FirstPageXN assignObjectNumbers def - (Assigned objects #s) now - - % Write the document-level objects (part 4). - - { writePart4 } totemp - /CatalogTempEnd exch def /CatalogTempStart exch def - (Wrote Catalog) now - - % Write the first page's objects (part 6). - - { writePart6 } totemp - /FirstPageTempEnd exch def /FirstPageTempStart exch def - (Wrote first page) now - - % Write the non-shared objects for other pages (part 7). - - { writePart7 /OtherPageLengths exch def } totemp - /OtherPageTempEnd exch def /OtherPageTempStart exch def - (Wrote other pages) now - - % Write the shared objects for other pages (part 8). - - { writePart8 } totemp - /SharedTempEnd exch def /SharedTempStart exch def - (Wrote shared objects) now - - % Write the objects not associated with pages (part 9). - - { writePart9 } totemp - /NonPageTempEnd exch def /NonPageTempStart exch def - - % Compute conservative lengths of parts 2,3,5,11 of the output. - % It's OK for these to be too large, but not too small. - - % Make dummy XRef entres for LPDict and PHS. - XRef LPDictN omap 0 ld_put - XRef PHSN omap 0 ld_put - - /HeaderLength { % this is exact - writePart1 % part 1 - } tolength def - /CatalogLength % this is exact - CatalogTempEnd CatalogTempStart sub def % part 4 - /FirstPageLength % this is exact - FirstPageTempEnd FirstPageTempStart sub def % part 6 - /OtherObjectsLength % this is exact - NonPageTempEnd OtherPageTempStart sub def % parts 7,8,9 - /ObjectsLength % this is exact - CatalogLength FirstPageLength add OtherObjectsLength add def - /XrefLength { % part 11 - % The LPDict must end within the first 1024 bytes, - % so the start of the FirstPage xref table can't exceed 1024. - writePart11xref 1024 writePart11rest - } tolength def - /NominalFileLength % Make a generous allowance for parts 2,3,5. - HeaderLength ObjectsLength 3 mul add 10000 add 99999 .max def - /FirstPageXrefLength { % part 3 - NominalFileLength writePart3 - } tolength def - /LPDictLength { % part 2 - NominalFileLength dup 2 mul 2 copy add 1 index dup createLPDict writePart2 - } tolength def - - % Compute a few additional values from the above. - - /XrefBeginLength { - (xref\n0 ) ows - OFile FirstPageXN write= - } tolength def - HeaderLength LPDictLength add - /FirstPageXrefStart 1 index def - FirstPageXrefLength add - /CatalogStart 1 index def - CatalogLength add % phsstart - /PHSStart exch def - - % Adjust the object positions ignoring PHS. - % (Writing the PHS needs these.) - - 0 0 CatalogStart CatalogTempStart sub adjustObjectPositions - % Make a temporary XRef entry for the PHS, for the benefit of omend. - XRef PHSN omap CatalogStart ld_put - (Adjusted positions) now - - % Construct the hint tables (part 5). - - { writePageOffsetHints } totemp - pop /PHSTempStart exch def - { writeSharedObjectHints } totemp - exch PHSTempStart sub PHS /S 3 -1 roll put - PHSTempStart sub /PHSTempLength exch def - (Wrote hints) now - - % Prepare to read TFile. -% TFile closefile -% /TFile TFileName (r) file def - - PHS - dup /File TFile put - dup /FilePosition PHSTempStart put - dup /Length PHSTempLength put - pop - /PHSLength { writePart5 } tolength def - - % Construct the linearization parameter dictionary (part 2). - - PHSStart - dup PHSLength add % phsend - /FirstPageStart 1 index def - dup FirstPageLength add % firstpageend - dup OtherObjectsLength add - /XrefStart 1 index def - XrefBeginLength add % xref0start - dup XrefBeginLength sub XrefLength add % fileend - % Because of a bug, Acrobat Reader doesn't recognize any file - % shorter than 1K as linearized. Patch this here. - % Acrobat 9 insists on 4KB - 4096 .max - /FileLength 1 index def - createLPDict - - % Adjust the object positions again, taking the PHS into account. - - PHSStart 0 PHSLength adjustObjectPositions - (Readjusted positions) now - - % Finally, write the output file. - - writePart1 - writePart2 - FirstPageXrefStart padto - XrefStart writePart3 - CatalogStart padto - CatalogTempStart CatalogTempEnd copyrange % part 4 - writePart5 - FirstPageStart padto - FirstPageTempStart NonPageTempEnd copyrange % parts 6,7,8,9 - % No Overflow Hint Stream (part 10). - XrefStart padto - writePart11xref - { FirstPageXrefStart writePart11rest } tomemory - FileLength 1 index length sub padto ows - (Wrote output file) now - - % Wrap up. - - TFile closefile TFileName deletefile - end % temporary dict - end % IDict -} bind def - -end % pdfoptdict -.setglobal - -% Check for command line arguments. -[ shellarguments { - ] dup length 2 eq { - % Load the pdfwrite utilities if necessary. - /omapinit where { pop } { (pdfwrite.ps) runlibfile } ifelse - save exch - aload pop exch (r) file exch (w) file - 3000000 setvmthreshold - 0 setobjectformat - pdfoptdict begin pdfOptimize end - restore - } { - (Usage: gs -dNODISPLAY -- pdfopt.ps input.pdf output.pdf) = flush quit - } ifelse -} { - pop -} ifelse |