12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087 |
- % 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 10687 2010-02-02 07:23:57Z alexcher $
- % 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 } ifelse
- pdfdict 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
- /obj { ( **** Warning: Content stream is not terminated by 'endstream'.\n)
- pdfformaterror pop pop exit
- } bind
- % 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 {
- /BMClevel BMClevel 1 add store
- pop
- } bind
- /BDC {
- /BMClevel BMClevel 1 add store
- exch /OC eq {
- dup type /nametype eq {
- PDFfile fileposition exch % pos /Name
- Page /Properties rget {
- ocg-is-visible not {
- OFFlevels BMClevel dup put
- } if
- } if
- PDFfile exch setfileposition
- } {
- pop
- } ifelse
- } {
- pop
- } ifelse
- } bind
- /EMC {
- OFFlevels BMClevel
- 2 copy known {
- 2 copy undef
- } if
- 1 sub /BMClevel exch store
- pop
- } bind
- /MP { pop } bind
- /DP { pop pop } bind
- /- { 0 % Bug 690016
- ( **** Warning: Invalid operator '-' is assumed to be a number 0.\n)
- pdfformaterror
- } bind
- .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
- % 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
- exch pop
- {
- % Appletalk PAP sends short strings with %! header expecting a response.
- % 'gv' swallows the %!PS line, then sends DSC comments beginning with %%
- % and also waits for a response. The following avoids those hangs.
- dup 2 string .peekstring pop dup (%!) eq exch (%%) eq or {
- cvx .runps
- } {
- dup 1023 string .peekstring pop dup length 400 ge {
- % "1024 string" exceeds current %stdin buffer
- % Valid PDF file cannot be smaller than 400 bytes.
- (%PDF-) search {
- 3 1 roll pop pop
- dup (%!PS) search not {
- length 0 ne {
- 1 index exch readstring pop pop
- (%stderr) (w) file dup
- ( **** Warning: File has some garbage before %PDF- .\n)
- writestring flushfile
- } {
- pop
- } ifelse
- dup (%stdin) (r) file eq {
- % Copy PDF from stdin to temporary file then run it.
- null (w+) /.tempfile .systemvar 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
- } {
- pop pop pop pop cvx .runps % (%!PS) found first
- } ifelse
- } {
- pop cvx .runps % (%PDF-) not found
- } ifelse
- } {
- pop cvx .runps % too short for PDF
- } ifelse
- } ifelse
- } {
- closefile % file was empty
- } ifelse
- } bind odef
- currentdict /runpdfstring .undef
-
-
- /runpdfbegin { % <file> runpdfbegin -
- 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
- } bind def
-
- /runpdfpagerange { % - runpdfpagerange <firstpage#> <lastpage#>
- /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
- << /RenderTTNotdef systemdict
- /RENDERTTNOTDEF get >> setuserparams % Should we render TT /.notdef
- 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
- 2 vmreclaim % couldn't hurt
- } bind def
-
-
- % Copy stream to an external temporary file and
- % return the file name as PS name.
- /copy_embedded_file {
- //true resolvestream % strm
- dup 1023 string .peekstring pop % "1024 string" exceeds current %stdin buffer
- dup length 400 ge { % Valid PDF file cannot be smaller than 400 bytes.
- (%PDF-) search {
- pop pop pop //true
- } {
- pop //false
- } ifelse
- } {
- pop //false
- } ifelse {
- //null (w) /.tempfile % strm (name) null (w) /.tempfile
- .systemvar exec % strm (name) file
- 3 -1 roll % (name) file strm
- 32768 string % (name) file strm (buf)
- { 3 copy readstring % (name) file strm (buf) file (data) bool
- 3 1 roll % (name) file strm (buf) bool file (data)
- writestring % (name) file strm (buf) bool
- not { exit } if
- } loop
- pop closefile % (name) file
- closefile % (name)
- cvn % /name
- } {
- closefile
- } ifelse
- } bind def
-
-
- % Copy selected subfiles to temporary files and return the file names
- % as a PostScript names to protect them from restore.
- % Currently, all PDF files in the Portfolio are extracted and returned.
- %
- % - pdf_collection_files [ /temp_file_name ... /temp_file_name
- /pdf_collection_files {
- mark
- Trailer /Root oget
- dup /Collection oknown {
- /Names knownoget {
- /EmbeddedFiles knownoget {
- /Names knownoget {
- { oforce
- dup type /dicttype eq {
- /EF knownoget {
- /F knownoget {
- copy_embedded_file
- } if
- } if
- } {
- pop
- } ifelse
- } forall
- } if
- } if
- } if
- } {
- pop
- } ifelse
- } bind def
-
- /runpdf { % <file> runpdf -
- //runpdfbegin exec
- //pdf_collection_files exec
- dup mark eq {
- pop
- process_trailer_attrs
- //runpdfpagerange exec
- //dopdfpages exec
- //runpdfend exec
- } {
- //runpdfend exec
- ] {
- dup type /filetype eq {
- //runpdfbegin exec
- process_trailer_attrs
- //runpdfpagerange exec
- //dopdfpages exec
- //runpdfend exec
- closefile
- } {
- .namestring dup (r) file
- //runpdfbegin exec
- process_trailer_attrs
- //runpdfpagerange exec
- //dopdfpages exec
- //runpdfend exec
- deletefile
- } ifelse
- } forall
- } ifelse
- } bind def
-
- currentdict /pdf_collection_files .undef
-
- 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 % userdict
- pdfdict begin
-
- % ======================== File parsing ======================== %
-
- % Read the cross-reference and trailer sections.
-
- /traileropdict mark
- (<<) cvn { /dictlevelcount dictlevelcount 1 add store mark } bind
- (>>) cvn { { .dicttomark } stopped {
- ( **** File has unbalanced >> in trailer.\n) pdfformaterror
- } if
- /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
-
- % 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
- 2 copy or 0 eq {
- ( **** Warning: considering '0000000000 00000 n' as a free entry.\n)
- pdfformaterror
- } {
- 0 3 1 roll % Set ObjectStream object number = 0
- //false setxrefentry % Save xref entry, don't change existing entries
- 3 -1 roll pop % Remove ObjectStream object onumber
- } ifelse
- }
- { % 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
- /dictlevelcount 0 def
- 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
- //false 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 //false 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
- % Check that the given location is within the file.
- dup PDFfilelen gt {
- ( **** Warning: Specified xref location is beyond end of file.\n)
- pdfformaterror
- /readxref cvx /invalidaccess signalerror
- } if
- 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
- % if hybrid-reference PDF, also fetch the entries
- % found in the XRef stream pointed by /XRefStm
- dup /XRefStm knownoget {
- readpdf15xref pop
- } if
- }
- { 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
- currentdict end
- } bind def
-
- /process_trailer_attrs { % - process_trailer_attrs -
- writeoutputintents
- .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
- % Initialize OC groups
- Trailer /Root oget /OCProperties knownoget {
- % By default, OCGs are 'on'; mark only 'off' OCGs.
- /D knownoget {
- /OFF knownoget {
- { oforce dup type /dicttype eq {
- /OFF 0 put
- } {
- pop
- } ifelse
- } forall
- } if
- } if
- } if
- } 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 -
- { PDFfilelen
- 1 1 Objects llength 1 sub % stack: filesize 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.
- % Stack: <filesize> <obj num>
- 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 dup 3 index ge % Compare object location to file size
- { pop true } % Rebuild if location not in file
- { PDFfile exch setfileposition % Go to the object location
- true % Stack: <filesize> <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
- } ifelse
- } .internalstopped
- { true } if % If we stop then we need to rebuild
- % Stack: <filesize> <obj num> <need rebuild flag>
- {
- ( **** 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
- } {
- % The object is in an object stream. We currently do not rebuild
- % objects in an object stream. So If we find one, then abort the
- % verification of the xref table entries.
- pop exit % Pop object number and then exit loop
- } ifelse % If not in an object stream
- } if % If object entry is not free
- pop % Remove object number
- } for
- pop % Remove the size of the file
- } bind odef
-
- /pdfopencache { % - pdfopencache -
- % Create and initialize some caches.
- /PageCount pdfpagecount def
- /PageNumbers PageCount 65534 .min dict def
- /PageIndex PageCount 65534 .min 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
- /DefaultQstate //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
- % NB: PDFfile is used outside of the PDF code to determine that a
- % PDF job is being processed; to not change or hide this key.
- cvlit /PDFfile exch def
- /PDFsource PDFfile def
- /Repaired false def
- currentglobal true .setglobal globaldict begin
- /UndefProcList 0 dict def
- end .setglobal
- PDFfile dup 0 setfileposition
- 0 () /SubFileDecode filter % to avoid file closure
- pdfstring readstring pop
- (%PDF-) search not {/pdfopen cvx /syntaxerror signalerror} if
- length /PDFoffset exch def pop
- % some badly formed PDF's (Visioneer) have something other than EOL
- % after the version number. If we get an error, shorten the string
- % and try again.
- false exch % error encountered
- { { cvr } stopped
- { exch pop true exch 0 1 index length 1 sub dup 0 eq
- { pop 0 exit } if % exit if string now empty
- getinterval % trim character from right end and retry
- }
- { exch {
- ( **** Warning: PDF version number not followed by EOL.\n)
- pdfformaterror
- }
- if exit
- }
- ifelse
- } loop
-
- /PDFversion exch def
- % Read the last cross-reference table.
- count /pdfemptycount exch def
- /Trailer << >> def % Initialize to an emptry dict.
- { initPDFobjects findxref readxref } .internalstopped {
- recover_xref_data % Read failed. Attempt to recover xref data.
- search_trailer % Search for the primary trailer
- } {
- /Trailer exch def % Save trailer dict after first xref table
- % Read any previous cross-reference tables. When we are done,
- % verify that the entries in the xref tables are valid if NoVerifyXref
- % is not defined.
- Trailer
- { /Prev knownoget not { % If no previous xref table then ...
- /NoVerifyXref where { pop } { verify_xref } ifelse exit
- } if
- { readxref } .internalstopped {
- recover_xref_data % Read failed. Attempt to recover xref data.
- exit % Exit loop since recover gets all obj data.
- } if % If readxref stopped
- % The PDF spec. says that each trailer dict should contain the required
- % entries. However we have seen a PDF file that only has a Prev entry in
- % the initial trailer dict. Acrobat complains but it accepts these files.
- % To work with these files, we are copying any entries which we find in
- % a previous trailer dict which are not present in the initial dict.
- dup {
- Trailer 2 index known {
- pop pop % discard if key already present
- } {
- Trailer 3 1 roll put % add key if not present
- } ifelse
- } forall
- } loop % Loop to previous trailer
- } ifelse % Ifelse readxref stopped
-
- % Scan numbers in the range 2147483648..4294967295 in Encrypt dictionary
- % as unsigned integers for compatibility with Acrobat Reader. Bug 689010.
- << /PDFScanUnsigned //true >> setuserparams
- { Trailer /Encrypt knownoget {
- pop
- pdf_process_Encrypt % signal error
- } if
- } stopped
- << /PDFScanUnsigned //false >> setuserparams
- { stop } if
-
- % Check for recursion in the page tree. Bug 689954, MOAB-06-01-2007
- verify_page_tree
-
- currentdict end
- } bind def
-
- % Look for [\r\n]%%EO from the current position of the file.
- % Return the position of %%EO if found or -1 .
- /findeof { % <file> find_eof <file> <position>
- -1 exch
- {
- dup bytesavailable 4 lt { exit } if
- dup 0 (%%EO) /SubFileDecode filter flushfile
- dup dup fileposition 5 sub setfileposition
- dup 5 string readstring not { pop exit } if
- dup (\r%%EO) eq exch (\n%%EO) eq or {
- dup fileposition 4 sub
- 3 1 roll exch pop
- } if
- } loop
- exch
- } 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 truncate the %%EOF to %%EO, and/or put the
- % startxref and the following value on the same line.
- % There seems to be no limit on the amount of garbage that can be
- % appended to the PDF file. Current record (60K) belongs to
- % PDF-Out (v 2.0 - 35). We start the search for %%EO from the last 1024
- % bytes and continue from the beginning of the file.
- /findxref { % - findxref <xrefpos>
- PDFfile dup dup dup 0 setfileposition bytesavailable
- dup /PDFfilelen exch def
- % Find the last %%EOF string (within 1024 bytes)
- 1024 sub PDFoffset .max
- setfileposition findeof % search the last 1024 bytes
- dup 0 le {
- pop
- dup PDFoffset setfileposition findeof % search from the beginnibg
- dup 0 le {
- ( **** Error: Cannot find a %%EOF marker anywhere in the file.\n)
- pdfformaterror
- /findxref cvx /syntaxerror signalerror
- } if
- } if
- dup 3 1 roll setfileposition
- % Stack: eofpos
- % Check for whether this is, in fact, a valid PDF file.
- dup PDFfilelen exch sub dup dup 7 gt exch 5 lt or {
- pop true
- } {
- string PDFfile exch readstring pop
- dup (%%EOF\n) eq exch dup (%%EOF\r) eq
- exch dup (%%EOF\r\n) eq exch (%%EOF) eq or or or not
- } ifelse {
- ( **** Warning: File has a corrupted %%EOF marker, or garbage after %%EOF.\n)
- 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 dup (startxref) linene {
- % startxref not on a line by itself. We have found PDF from
- % www.verypdf.com in which the startxref was on the same line as
- % the end of trailer dictionary. Check for this. Note: This
- % violates the spec.
- dup (startxref) search {
- % found startxref - print warning
- pop pop pop % clear strings from search
- ( **** Warning: format of the startxref line in this file is invalid.\n)
- pdfformaterror
- } { % no startxref - we have a problem.
- /findxref cvx /syntaxerror signalerror
- } ifelse
- } if
- pop pop
- } { % else, this file has 'startxref #####' format
- (startxref) ne { /findxref cvx /syntaxerror signalerror } if
- cvi % xref start position
- ( **** Warning: format of the startxref line in this file is invalid.\n)
- pdfformaterror
- exch PDFfile exch setfileposition
- } ifelse
- } bind def
- /stderrfile (%stderr) (w) file def
- /stderrprint { % <string> stderrprint -
- //stderrfile dup 3 -1 roll writestring flushfile
- } bind def
- /pdfformaterror { % <string> pdfformaterror -
- stderrprint
- /Repaired true store
- } bind def
-
- /knownoget_safe
- { 2 copy knownoget { 3 1 roll pop pop //true } { pop pop //false } ifelse
- } odef
-
- /printProducer {
- Trailer /Info { knownoget_safe } stopped { pop pop false } if {
- /Producer knownoget not { null } if
- } {
- null
- } ifelse
- dup null eq {
- pop
- } {
- ( **** The file was produced by: \n **** >>>> ) 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
- ( <<<<\n) stderrprint
- } ifelse
- } bind def
- % The UndefProcList collects noisy warnings.
- % This gets rid of many multiple warnings from pdf_font.ps
- /printCollectedWarnings {
- UndefProcList length 0 gt {
- (\n **** Embedded font uses undefined procedure\(s\): ) stderrprint
- UndefProcList {
- exch .namestring stderrprint ( ) stderrprint
- =string cvs stderrprint ( times, ) stderrprint
- } forall
- (\n) stderrprint
- } if
- } bind def
- /printrepaired {
- printCollectedWarnings
- (\n **** This file had errors that were repaired or ignored.\n)
- stderrprint
- printProducer
- ( **** Please notify the author of the software that produced this\n)
- stderrprint
- ( **** file that it does not conform to Adobe's published PDF\n)
- stderrprint
- ( **** specification.\n\n)
- stderrprint
- } bind def
-
- % Write the outline structure for a file. Uses linkdest (below).
- % omit links to pages that don't exist.
- /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
- {
- dup /A knownoget {
- dup /URI known {
- /A mark 3 2 roll % <<>> /A [ <<action>>
- { oforce } forall
- .dicttomark
- 3 2 roll
- } {
- dup /D knownoget {
- exch pop exch dup length dict copy dup /Dest 4 -1 roll put
- } {
- /N knownoget { % Assume /S /Named
- namedactions exch .knownget { exec } if
- } if
- } ifelse
- } ifelse
- } if
- linkdest
- } stopped
- {
- cleartomark % ignore this link
- ( **** Warning: Outline has invalid link that was discarded.\n)
- pdfformaterror
- } {
- /Title oget /Title exch /OUT pdfmark
- }
- ifelse
- /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 }
- % finally see if the key is (misplaced) in the Root Catalog dict
- { dup Trailer /Root oget exch knownoget dup {
- 3 -1 roll ( **** Warning: The /) pdfformaterror 50 string cvs pdfformaterror
- ( key is missing from the Page tree.\n) pdfformaterror
- }
- { exch pop }
- ifelse
- }
- 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 {
- dup type /dicttype eq {
- 3 index knownoget
- } {
- //false exch {
- 4 index knownoget {
- exch not exit
- } if
- } forall
- } ifelse
- } {
- //false
- } ifelse {
- exch pop exch pop exch pop //true
- } {
- exch /Resources pget {
- exch knownoget { % /Name [<<>> ...]
- dup type /dicttype eq {
- exch knownoget
- } {
- % GS uses array of dicts if resources don't fit in one dict.
- //false 3 1 roll { % false /Name <<>>
- 1 index knownoget { % false /Name val
- exch pop exch not % i.e. true
- 0 exit
- } if
- } forall
- pop
- } ifelse
- } {
- 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
- dup /Count knownoget {
- dup 0 le {
- pop
- dup /Kids knownoget {
- pop
- ( **** Warning: Invalid Page count.\n) pdfformaterror
- % find the last page and use that as the Count
- 1 1 999999999 {
- dup pdffindpage?
- exch pop
- //null eq { exit } { pop } ifelse
- } for
- 1 sub % decrement to last page that we were able to find
- 2 copy /Count exch put
- } {
- 0 % return 0 and keep 0 page count.
- ( **** Warning: PDF document has no pages.\n) pdfformaterror
- } ifelse
- } if
- exch pop
- } {
- dup /Type oget /Page eq {
- << exch 1 array astore /Kids exch /Count 1 /Type /Pages >>
- Trailer /Root oget /Pages 3 -1 roll put
- 1
- ( **** Warning: No /Pages node. The document root directly point a page.\n)
- pdfformaterror
- } {
- ( **** Warning: Page count not found; assuming 1.\n)
- pdfformaterror
- pop 1
- } ifelse
- } ifelse
- } bind def
-
- % Check for loops in the 'page tree' but accept an acyclic graph.
- % - verify_page_tree -
- /verify_page_tree {
- Trailer /Root oget /Pages oget
- 10 dict begin
- /verify_page_tree_recursive {
- dup 1 def
- dup /Kids knownoget {
- { oforce
- currentdict 1 index known {
- ( **** Error: there's a loop in the page tree. Giving up.\n) pdfformaterror
- /verify_page_tree cvx /syntaxerror signalerror
- } if
- verify_page_tree_recursive
- } forall
- } if
- currentdict exch undef
- } def
- verify_page_tree_recursive
- end
- } bind def
-
- /pdffindpage? { % <int> pdffindpage? 1 null (page not found)
- % <int> pdffindpage? 1 noderef (page found)
- % <int> pdffindpage? 0 null (Error: page not found)
- 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
- } 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 pdffindpage?
- % Stack: index countleft noderef
- 1 index 1 ne { pop pop /pdffindpage cvx /rangecheck signalerror } if
- exch pop
- PageIndex 2 index 1 sub 65533 .min 2 index oforce put
- PageNumbers 1 index oforce 3 index dup 65534 le
- { put }
- { pop pop pop } % don't store more than 65534 pagenumbers
- ifelse
- 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 dup 65533 lt
- { get }
- { pop pop null }
- ifelse
- 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
-
- % Arrange the four elements that define a rectangle into a 'normal' order.
- /normrect_elems % <x1> <y1> <x2> <y2> normrect_elems <llx> <lly> <urx> <ury>
- {
- exch 4 1 roll % <x2> <x1> <y1> <y2>
- 2 copy gt { exch } if % <x2> <x1> <lly> <ury>
- 4 2 roll 2 copy lt { exch } if % <lly> <ury> <urx> <llx>
- 4 1 roll exch % <llx> <lly> <urx> <ury>
- } bind def
-
- % Arrange a rectangle into a 'normal' order. I.e the lower left corner
- % followed by the upper right corner.
- /normrect % <rect> normrect <rect>
- {
- aload pop normrect_elems 4 array astore
- } bind def
-
- /fix_empty_rect_elems % </Name> <x1> <y1> <x2> <y2> fix_empty_rect_elems <x1> <y1> <x2'> <y2'>
- { dup 3 index eq { //true } { 1 index 4 index eq } ifelse {
- pop pop pop pop
- ( **** Warning: File has an empty ) pdfformaterror pdfstring cvs pdfformaterror
- (. Using the current page size instead.\n) pdfformaterror
- 0 0 currentpagedevice /PageSize get aload pop
- } {
- 5 -1 roll pop
- } ifelse
- } bind def
-
- /boxrect % <llx> <lly> <urx> <ury> boxrect <x> <y> <w> <h>
- { 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
- } {
- pop 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
-
- % Procedures to do the necessary transformations of view destinations
- % <PDF2PS_matrix> <rot> <view> -- <view'>
- /viewdestprocs 8 dict dup begin
- /Fit { exch pop exch pop } bind def
- /FitH {
- aload pop
- 0 4 -1 roll 1 and 0 eq { exch } if
- 4 -1 roll transform exch pop
- 2 array astore
- } bind def
- /FitV {
- aload pop
- 0 4 -1 roll 1 and 0 ne { exch } if
- 4 -1 roll transform pop
- 2 array astore
- } bind def
- /FitB /Fit load def
- /FitBH /FitH load def
- /FitBV /FitV load def
- /XYZ {
- aload pop
- 3 1 roll
- 2 copy 7 -1 roll 1 and 0 ne { exch } if 4 2 roll % odd rotation switches x<->y
- 2 { dup null eq { pop 0 } if exch } repeat % replace nulls with 0
- 7 -1 roll transform % transform coordinates
- 2 { 3 -1 roll null eq { pop null } if exch } repeat % put the nulls back
- 3 -1 roll
- 4 array astore
- } bind def
- /FitR {
- exch pop
- aload pop
- 2 { 5 index transform 4 2 roll } repeat normrect_elems
- 5 array astore
- exch pop
- } bind def
- end readonly 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
- false % don't have a page# and transformation matrix (yet)
- 1 index type /dicttype eq {
- 1 index /Type knownoget {
- /Page eq {
- pop % the "false" flag
- dup pdf_cached_PDF2PS_matrix exch
- dup /Rotate pget not { 0 } if 90 idiv exch
- pdfpagenumber
- true % now we have a page# and a transformation matrix
- } if
- } if
- } if
- % stack: <link|outline> <dest> ( <PDF2PS_matrix> <rot> <page#> true | <page> false )
- {
- /Page exch 6 2 roll
- % stack: [/Page <page#>] <link|outline> <dest> <PDF2PS_matrix> <rot>
- 3 -1 roll dup length 1 sub 1 exch getinterval /View 4 1 roll
- % stack: [/Page <page#>] <link|outline> /View <PDF2PS_matrix> <rot> <view>
- //viewdestprocs 1 index 0 get get exec
- 3 -1 roll
- } {
- pop
- dup length 1 sub 1 exch getinterval /View exch 3 -1 roll
- } ifelse
- }
- ifelse
- }
- if
- } bind def
- % <pagedict> mark ... -proc- <page#> <error>
- /namedactions 8 dict dup begin
- /FirstPage { 1 //false } def
- /LastPage { pdfpagecount //false } def
- /NextPage { counttomark 2 add index pdfpagenumber 1 add dup pdfpagecount gt } bind def
- /PrevPage { counttomark 2 add index pdfpagenumber 1 sub dup 1 lt } bind def
- end readonly def
- % <pagedict> <annotdict> -proc- -
- /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
- dup /BS knownoget { << exch { oforce } forall >> /BS exch 3 -1 roll } if
- dup /F knownoget { /F exch 3 -1 roll } if
- dup /C knownoget { /Color exch 3 -1 roll } if
- dup /Rect knownoget { /Rect exch 3 -1 roll } if
- dup /Border knownoget {
- dup type /arraytype eq {
- dup length 3 lt
- } {
- //true
- } ifelse {
- pop [ 0 0 0 ] % Following AR5 use invisible border.
- } if
- /Border exch 3 -1 roll
- } if
- dup /A knownoget {
- dup /URI known {
- /A mark 3 2 roll % <<>> /A [ <<action>>
- { oforce } forall
- .dicttomark
- 3 2 roll
- } {
- dup /D knownoget {
- exch pop exch dup length dict copy dup /Dest 4 -1 roll put
- } {
- /N knownoget { % Assume /S /Named
- namedactions exch .knownget {
- exec {
- pop
- ( **** Warning: Ignoring a named action pointing out of the document page range.\n)
- pdfformaterror
- } {
- /Page exch 3 -1 roll
- } ifelse
- } if
- } if
- } ifelse
- } ifelse
- } if
- linkdest pop /LNK pdfmark
- } bind def
- end readonly def
-
- % **** The following procedure should not be changed to allow clients
- % **** to directly interface with the constituent procedures. GSview
- % **** and some Artifex customers rely on the pdfshowpage_init,
- % **** pdfshowpage_setpage, pdfshowpage_finish so all logic should be
- % **** implemented in one of those three procedures.
- /pdfshowpage % <pagedict> pdfshowpage -
- { dup /Page exch store
- pdfshowpage_init
- pdfshowpage_setpage
- pdfshowpage_finish
- } bind def
-
- /pdfpagecontents % <pagedict> pdfpagecontents <contents>
- { } bind def
-
- /pdfshowpage_init % <pagedict> pdfshowpage_init <pagedict>
- { /DSCPageCount DSCPageCount 1 add store
- } bind def
-
- /get_media_box { % <pagedict> get_media_box <box>
- /MediaBox pget not {
- ( **** Page has no /MediaBox attribute. Using the current page size.\n)
- pdfformaterror
- [ 0 0 currentpagedevice /PageSize get aload pop ]
- } if
- } bind def
-
- /get_any_box { % <pagedict> get_any_box <box name> <box>
- //systemdict /UseTrimBox .knownget dup { and } if {
- dup /TrimBox pget {
- exch pop /TrimBox exch
- } if
- } if
- dup type /arraytype ne {
- //systemdict /UseCropBox .knownget dup { and } if {
- dup /CropBox pget {
- exch pop /CropBox exch
- } if
- } if
- } if
- dup type /arraytype ne {
- /MediaBox exch get_media_box
- } if
- } bind def
-
- % Compute the matrix that transforms the PDF->PS "default" user space
- /pdf_PDF2PS_matrix { % <pdfpagedict> -- matrix
- matrix currentmatrix matrix setmatrix exch
- % stack: savedCTM <pdfpagedict>
- dup get_any_box
- % stack: savedCTM <pdfpagedict> /Trim|Crop|MediaBox <Trim|Crop|Media Box>
- oforce_elems normrect_elems fix_empty_rect_elems 4 array astore
- //systemdict /PDFFitPage known {
- PDFDEBUG { (Fiting PDF to imageable area of the page.) = flush } if
- currentpagedevice /.HWMargins get aload pop
- currentpagedevice /PageSize get aload pop
- % Adjust PageSize and .HWMargins for the page portrait/landscape orientation
- 2 copy gt
- 7 index aload pop 3 -1 roll sub 3 1 roll exch sub exch
- 10 index /Rotate pget not { 0 } if 90 idiv 1 and 0 ne { exch } if
- gt
- ne {
- 2 copy ne {
- % rotate the .HWMargins
- 2 copy lt {
- 6 2 roll 4 -1 roll 6 -2 roll
- } {
- 6 2 roll 4 1 roll 6 -2 roll
- } ifelse
- % rotate the page dimensions
- exch
- } if
- } if
- 3 -1 roll sub 3 1 roll exch sub exch
- % stack: savedCTM <pdfpagedict> <Crop|Media Box> Xmin Ymin Xmax Ymax
- PDFDEBUG { ( Translate up by [ ) print 3 index =print (, ) print 2 index =print ( ]) = flush } if
- 3 index 3 index translate % move origin up to imageable area
- 2 index sub exch 3 index sub exch 4 2 roll pop pop
- % stack: savedCTM <pdfpagedict> [Box] XImageable YImageable
- 2 index aload pop 2 index sub exch 3 index sub exch 4 2 roll pop pop
- 5 index /Rotate pget not { 0 } if 90 idiv 1 and 0 ne { exch } if
- % stack: savedCTM <pdfpagedict> [Box] XImageable YImageable XBox YBox
- 3 -1 roll exch div 3 1 roll div .min
- PDFDEBUG { ( Scale by ) print dup = flush } if
- } {
- //systemdict /NoUserUnit .knownget not { false } if {
- 1
- } {
- 1 index /UserUnit knownoget {
- PDFDEBUG { (Scaling due to UserUnit by ) print dup = flush } if
- } {
- 1
- } ifelse
- } ifelse
- } ifelse
- % stack: savedCTM <pdfpagedict> [Box] scale
- dup scale
- % Rotate according to /Rotate
- aload pop boxrect
- {
- { pop pop }
- { -90 rotate pop neg 0 translate }
- { 180 rotate neg exch neg exch translate }
- { 90 rotate neg 0 exch translate pop }
- }
- 5 index /Rotate pget not { 0 } if
- PDFDEBUG { dup 0 ne { (Rotating by ) print dup =print ( degrees.) = flush } if } if
- 90 idiv 3 and get exec
- % Now translate to the origin given in the Crop|Media Box
- exch neg exch neg translate
- % stack: savedCTM <pdfpagedict>
- pop
- matrix currentmatrix exch setmatrix
- } bind def
-
- % Cache the matrix that transforms the PDF->PS "default" user space
- % into <pdfpagedict> under the key //PDF2PS_matrix_key, then return it
- /PDF2PS_matrix_key (PDF->PS matrix) cvn def
- /pdf_cached_PDF2PS_matrix { % <pdfpagedict> -- <PDF2PS_matrix>
- dup //PDF2PS_matrix_key .knownget {
- exch pop
- } {
- dup dup pdf_PDF2PS_matrix //PDF2PS_matrix_key exch put
- //PDF2PS_matrix_key get
- } ifelse
- } bind def
- currentdict /PDF2PS_matrix_key undef
-
- /.pdfshowpage_Install { % <pagedict> [<prevproc>] .pdfshowpage_Install -
- 0 get exec
- pdf_cached_PDF2PS_matrix concat
- } bind def
-
- /pdfshowpage_setpage { % <pagedict> pdfshowpage_setpage <pagedict>
- 6 dict begin % for setpagedevice
- % Stack: pdfpagedict
- % UseCIEColor is always true for PDF; see the comment in runpdf above
- /UseCIEColor true def
- /Orientation 0 def
- currentpagedevice
- % Stack: pdfpagedict currentpagedevicedict
- 1 index get_any_box
- % Stack: pdfpagedict currentpagedevicedict /BoxName [box]
- oforce_elems normrect_elems fix_empty_rect_elems boxrect 4 2 roll pop pop
- 3 index /Rotate pget not { 0 } if 90 idiv 1 and 0 ne { exch } if
- % stack: pdfpagedict currentpagedevicedict boxwidth boxheight
- //systemdict /PDFFitPage known {
- % Preserve page size,
- % but choose portrait/landscape depending on box width:height ratio
- % (if box width == height, select portrait orientation)
- gt
- 1 index /PageSize get aload pop
- 2 copy gt
- 4 -1 roll ne { exch } if
- } {
- % Set the page size.
- //systemdict /NoUserUnit .knownget not { false } if not {
- 3 index /UserUnit knownoget {
- dup 4 -1 roll mul 3 1 roll mul
- } if
- } if
- } ifelse
- 2 array astore /PageSize exch def
- % Determine the number of spot colors used on the page. Note: This searches
- % the pages resources. It may be high if a spot color is in a resource but
- % is not actually used on the page.
- /PageSpotColors 2 index countspotcolors def
-
- % Let the device know if we will be using PDF 1.4 transparency.
- % The clist logic may need to adjust the size of bands.
- 1 index pageusestransparency /PageUsesTransparency exch def
- dup /Install .knownget {
- % Don't let the Install procedure get more deeply
- % nested after every page.
- dup type dup /arraytype eq exch /packedarraytype eq or {
- dup length 4 eq {
- dup 2 get /.pdfshowpage_Install load eq {
- 1 get 0 get % previous procedure
- } if
- } if
- } if
- } {
- { }
- } ifelse 1 array astore
- 2 index exch /.pdfshowpage_Install load /exec load
- 4 packedarray cvx
- % Stack: pagedict currentpagedict installproc
- /Install exch def
- % Stack: pagedict currentpagedict
- pop currentdict end setpagedevice
- } bind def
-
- /.free_page_resources { % - .free_page_resources -
- Page /Resources pget {
- /Shading knownoget {
- { {
- dup type /dicttype eq {
- dup /.shading_dict known {
- dup /.shading_dict undef
- } if
- } if
- pop pop
- } forall
- } big-res-forall
- } if
- } if
- } bind def
-
- /pdfshowpage_finish { % <pagedict> pdfshowpage_finish -
- save /PDFSave exch store
- /PDFdictstackcount countdictstack store
- (before exec) VMDEBUG
-
- % set up color space substitution (this must be inside the page save)
- pdfshowpage_setcspacesub
-
- .writepdfmarks {
-
- % Copy the crop box.
- dup /CropBox pget {
- % .pdfshowpage_Install transforms the user space -
- % do same here with the CropBox.
- oforce_elems
- 2 { Page pdf_cached_PDF2PS_matrix transform 4 2 roll } repeat
- normrect_elems /CropBox 5 1 roll fix_empty_rect_elems 4 array astore
- mark /CropBox 3 -1 roll
- /PAGE pdfmark
- } if
-
- % Copy annotations and links.
- dup /Annots knownoget {
- 0 1 2 index length 1 sub
- { 1 index exch oget
- dup type /dicttype eq {
- dup /Subtype oget annottypes exch .knownget { exec } { pop } ifelse
- } {
- pop
- } ifelse
- }
- for pop
- } if
-
- } if % end .writepdfmarks
-
- % Display the actual page contents.
- 8 dict begin
- /BXlevel 0 def
- /BMClevel 0 def
- /OFFlevels 0 dict def
- /BGDefault currentblackgeneration def
- /UCRDefault currentundercolorremoval def
- %****** DOESN'T HANDLE COLOR TRANSFER YET ******
- /TRDefault currenttransfer def
- matrix currentmatrix 2 dict
- 2 index /CropBox pget {
- oforce_elems normrect_elems boxrect
- 4 array astore 1 index /ClipRect 3 -1 roll put
- } if
- dictbeginpage setmatrix
- /DefaultQstate qstate store
-
- count 1 sub /pdfemptycount exch store
- % If the page uses any transparency features, show it within
- % a transparency group.
- dup pageusestransparency dup /PDFusingtransparency exch def {
- % Show the page within a PDF 1.4 device filter.
- 0 .pushpdf14devicefilter {
- /DefaultQstate qstate store % device has changed -- reset DefaultQstate
- % If the page has a Group, enclose contents in transparency group.
- % (Adobe Tech Note 5407, sec 9.2)
- dup /Group knownoget {
- 1 index /CropBox pget {
- /CropBox exch
- } {
- 1 index get_media_box /MediaBox exch
- } ifelse
- oforce_elems normrect_elems fix_empty_rect_elems 4 array astore .beginformgroup {
- showpagecontents
- } stopped {
- .discardtransparencygroup stop
- } if .endtransparencygroup
- } {
- showpagecontents
- } ifelse
- } stopped {
- % todo: discard
- .poppdf14devicefilter
- /DefaultQstate qstate store % device has changed -- reset DefaultQstate
- stop
- } if .poppdf14devicefilter
- /DefaultQstate qstate store % device has changed -- reset DefaultQstate
- } {
- showpagecontents
- } ifelse
- .free_page_resources
- % todo: mixing drawing ops outside the device filter could cause
- % problems, for example with the pnga device.
- endpage
- end % scratch dict
- % Indicate that the number of spot colors is unknown in case the next page
- % imaged is a PS file.
- << /PageSpotColors -1 >> .setpagedevice
- % Some PDF files don't have matching q/Q (gsave/grestore) so we need
- % to clean up any left over dicts from the dictstack
- countdictstack PDFdictstackcount sub dup 0 ne {
- ( **** Warning: File has unbalanced q/Q operators \(too many q's\)\n)
- pdfformaterror
- { end } repeat
- } {
- pop
- } ifelse
- (after exec) VMDEBUG
- Repaired % pass Repaired state around the restore
- PDFSave restore
- /Repaired exch def
- } bind def
-
- % Display the contents of a page (including annotations).
- /showpagecontents { % <pagedict> showpagecontents -
- dup % Save the pagedict for the Annotations
- count 1 sub /pdfemptycount exch store
- gsave % preserve gstate for Annotations later
- /Contents knownoget not { 0 array } if
- dup type /arraytype ne { 1 array astore } if {
- oforce false resolvestream pdfopdict .pdfrun
- } forall
- % check for extra garbage on the ostack and clean it up
- count pdfemptycount sub dup 0 ne {
- ( **** File did not complete the page properly and may be damaged.\n)
- pdfformaterror
- { pop } repeat
- } {
- pop
- } ifelse
- grestore
- % Draw the annotations
- //systemdict /ShowAnnots .knownget not { //true } if {
- /Annots knownoget {
- { oforce
- dup //null ne {
- drawannot
- } {
- pop
- } ifelse
- } forall
- } if
- } if
- //systemdict /ShowAcroForm .knownget { //true eq } { //false } ifelse {
- Trailer /Root oget /AcroForm knownoget { draw_acro_form } if
- } if
- } bind def
-
- /processcolorspace { % - processcolorspace <colorspace>
- % The following is per the PLRM3.
- currentdevice 1 dict dup /ProcessColorModel dup put .getdeviceparams
- exch pop exch pop
- dup type /nametype ne { cvn } if
- dup { setcolorspace } .internalstopped { pop /DeviceRGB } if
- } bind def
-
- % ------ Transparency support ------ %
-
- % Define minimum PDF version for checking for transparency features.
- % Transparency is a 1.4 feature however we have seen files that claimed
- % to be PDF 1.2 with transparency features. Bug 689288.
- /PDFtransparencyversion 1.2 def
-
- % Determine whether a page might invoke any transparency features:
- % - Non-default BM, ca, CA, or SMask in an ExtGState
- % - Image XObject with SMask
- % Note: we deliberately don't check to see whether a Group is defined,
- % because Adobe Illustrator 10 (and possibly other applications) define
- % a page-level group whether transparency is actually used or not.
- % Ignoring the presence of Group is justified because, in the absence
- % of any other transparency features, they have no effect.
- /pageusestransparency { % <pagedict> pageusestransparency <bool>
- PDFversion PDFtransparencyversion lt NOTRANSPARENCY or {
- pop //false
- } {
- dup //false exch {
- 4 dict 1 index resourceusestransparency { pop not exit } if
- /Parent knownoget not { exit } if
- } loop
- % Also check for transparency in the annotation (if not in resources).
- { pop //true } { annotsusetransparency } ifelse
- } ifelse
- } bind def
-
- % Check if transparency is specified in an ExtGState dict
- /extgstateusestransparency { % <gstate dict> extgstateusestransparency <bool>
- //false exch % Assume no transparency
- { % establish loop context
- dup /BM knownoget { dup /Normal ne exch /Compatible ne and
- { pop not exit } if
- } if
- dup /ca knownoget { 1 ne { pop not exit } if } if
- dup /CA knownoget { 1 ne { pop not exit } if } if
- dup /SMask knownoget { /None ne { pop not exit } if } if
- pop exit
- } loop
- } bind def
-
- % Check if transparency is used in a Pattern
- /patternusestransparency { % <Pattern dict> patternusestransparency <bool>
- NOTRANSPARENCY
- { pop //false }
- { //false exch % Assume no transparency
- {
- 4 dict 1 index resourceusestransparency { pop not exit } if
- dup /ExtGState knownoget { extgstateusestransparency { pop not exit } if } if
- pop exit
- } loop
- }
- ifelse
- } bind def
-
-
- % Check the Resources of a page or Form. Check for loops in the resource chain.
- /resourceusestransparency { % <dict> <dict> resourceusestransparency <bool>
- { % Use loop to provide an exitable context.
- /Resources knownoget not { 0 dict } if
- 2 copy .knownget {
- { % Some circular references may be missed because scanning stops
- % when the 1st transparency is found.
- ( **** File has circular references in resource dictionaries.\n)
- pdfformaterror
- } if
- pop //false exit
- } if
- 2 copy //true put % In the current chain.
- dup /ExtGState knownoget {
- //false exch
- { { exch pop oforce extgstateusestransparency { pop //true exit } if
- } forall
- dup { exit } if
- } big-res-forall
- { pop //true exit } if
- } if
- dup /Pattern knownoget {
- //false exch
- { { exch pop oforce patternusestransparency { pop //true exit } if
- } forall
- dup { exit } if
- } big-res-forall
- { pop //true exit } if
- } if
- dup /XObject knownoget {
- dup type dup /dicttype eq exch /arraytype eq or {
- //false exch
- { {
- exch pop oforce dup /Subtype get
- dup /Image eq { 1 index /SMask known { pop pop not exit } if } if
- /Form eq {
- 3 index exch resourceusestransparency { not exit } if
- } {
- pop
- } ifelse
- } forall
- dup { exit } if
- } big-res-forall
- { pop //true exit } if
- } {
- ( **** Ignoring non-dictionary /XObject attribute.\n)
- pdfformaterror
- pop
- } ifelse
- } if
- 2 copy //false put % Visited but not in the current chain.
- pop //false exit
- } loop
- exch pop
- } bind def
-
- % Check if the annotations on a page use transparency
- /annotsusetransparency { % <page dict> annotsusetransparency <bool>
- //false exch % Assume no transparency
- /Annots knownoget { % Get Annots array
- {
- oforce
- dup //null ne {
- /AP knownoget { % Get appearance dict for the annoation
- /N knownogetdict { % Get the /N (i.e. normal) appearance stream
- 4 dict exch resourceusestransparency { pop //true exit } if
- } if
- } if % If AP dict known
- } {
- pop
- } ifelse
- } forall % For all annots on the page
- } if
- } bind def
-
- % Add a color name to our spot color list. Ignore /All and /None
- /putspotcolor { % <name> <spotcolordict> putspotcolor -
- % The 'name' could be a string. If so then convert to a name.
- exch dup type /stringtype eq { cvn } if
- dup dup /None eq exch /All eq or { pop pop } { 0 put } ifelse
- } bind def
-
- % Determine which spot colors are used within a color space Note: This
- % dict will include all colors used in Separation or DeviceN color spaces.
- % Thus it may include Cyan, Magenta, Yellow, and Black.
- % <colorspace> <spotcolordict> colorspacespotcolors -
- /colorspacespotcolors {
- exch dup type /arraytype eq {
- % If we have an Indexed color space then get the base space.
- dup 0 oget dup /Indexed eq {
- pop 1 oget 2 copy colorspacespotcolors
- } {
- % Stack: <spotcolordict> <colorspace> <colorspacetype>
- dup /Separation eq exch /DeviceN eq or {
- dup 1 oget dup type /arraytype eq {
- { oforce 2 index putspotcolor } forall
- } {
- 2 index putspotcolor
- } ifelse
- } if
- } ifelse
- } if
- pop pop
- } bind def
-
- % Enumerate resource dictionary or an array of dictionaries
- % <object> <proc> big-res-forall -
- /big-res-forall {
- 1 index type /dicttype eq { 0 get } if
- forall
- } bind def
-
- % Check the Resources of a page, form, or annotation. Determine which spot
- % colors are used within the resource Note: The spot color dict will include
- % all colors used in Separation or DeviceN color spaces. Thus it may include
- % Cyan, Magenta, Yellow, and Black. We also pass a dict that is used to check
- % for loops in the resource list.
- % <spotcolordict> <loopdict> <page/form/annot dict>
- % resourcespotcolors <spotcolordict> <loopdict>
- /resourcespotcolors {
- { % Use loop to provide an exitable context.
- % Exit if no Resources entry
- /Resources knownoget not { exit } if
- % Exit if we have already seen this dict
- 2 copy known { pop exit } if
-
- % Save the Resources dict into our loop checking dict.
- 2 copy 0 put
-
- % Scan resources that might contain a color space.
- dup /ColorSpace knownoget {
- { { exch pop oforce 3 index colorspacespotcolors } forall } big-res-forall
- } if
- dup /Pattern knownoget {
- { { exch pop oforce 4 copy exch pop resourcespotcolors pop pop pop } forall } big-res-forall
- } if
- dup /Shading knownoget {
- { { exch pop oforce /ColorSpace oget 3 index colorspacespotcolors } forall } big-res-forall
- } if
- /XObject knownoget {
- dup type dup /dicttype eq exch /arraytype eq or {
- { { exch pop oforce dup
- /Subtype get /Form eq { resourcespotcolors } { pop } ifelse
- } forall
- } big-res-forall
- } {
- pop % Just ignore here, already reported by resourceusestransparency.
- } ifelse
- } if
- exit
- } loop
- } bind def
-
- % Determine which spot colors are used within the annotations. Note: This
- % dict will include all colors used in Separation or DeviceN color spaces.
- % Thus it may include Cyan, Magenta, Yellow, and Black.
- % <spotcolordict> <loopdict> <annotsarray>
- % annotsspotcolors <spotcolordict> <loopdict>
- /annotsspotcolors {
- { oforce
- dup //null ne {
- /AP knownoget { % Get appearance dict for the annoation
- /N knownogetdict { % Get the /N (i.e. normal) appearance stream
- resourcespotcolors
- } if % If normal appearance streamknown
- } if % If AP dict known
- } {
- pop
- } ifelse
- } forall
- } bind def
-
- % Determine spot colors are used within a page. We are creating a dict to
- % hold the spot color names as keys. Using a dict avoids having to worry
- % about duplicate entries. The keys in the dict contain the spot color
- % names. However the values have no meaning. Note: This dict will include
- % all colors used in Separation or DeviceN color spaces specified in the
- % page's resources. Thus it may include Cyan, Magenta, Yellow, and Black.
- % There is no attempt to verify that these color spaces are actually used
- % within the object streams for the page.
- /pagespotcolors { % <pagedict> pagespotcolors <spotcolordict>
- dup
- % Create a dict to hold spot color names.
- 0 dict exch
- % Create a dict to be used to check for reference loops.
- 4 dict exch
- % Check for color spaces in the Resources
- resourcespotcolors
- % Also check for color spaces in the annotations.
- 3 -1 roll
- /Annots knownoget { annotsspotcolors } if
- pop % Discard reference loop dict
- } bind def
-
- % Determine how many (if any) spot colors are used by a page.
- % Note: This count does not include Cyan, Magenta, Yellow, or Black
- /countspotcolors { % <pagedict> countspotcolors <count>
- pagespotcolors % Get dict with all spot colors
- dup length % spot color dict length
- % Remove CMYK from the spot color count.
- [ /Cyan /Magenta /Yellow /Black ]
- { 2 index exch known { 1 sub } if } forall
- exch pop % Remove spot color dict
- } bind def
-
- % ------ ColorSpace substitution support ------ %
-
- %
- % <pagedict> pdfshowpage_setcspacesub <pagedict>
- %
- % Set up color space substitution for a page. Invocations of this procedure
- % must be bracketed by the save/restore operation for the page, to avoid
- % unintended effects on other pages.
- %
- % If any color space substitution is used, and the current color space is a
- % device dependent color space, make sure the current color space is updated.
- % There is an optimization in the setcolorspace pseudo-operator that does
- % nothing if both the current and operand color spaces are the same. For
- % PostScript this optimization is disabled if the UseCIEColor page device
- % parameter is true. This is not the case for PDF, as performance suffers
- % significantly on some PDF files if color spaces are set repeatedly. Hence,
- % if color space substitution is to be used, and the current color space
- % is a device dependent color space, we must make sure to "transition" the
- % current color space.
- %
- /pdfshowpage_setcspacesub
- {
- false
- { /DefaultGray /DefaultRGB /DefaultCMYK }
- {
- dup 3 index /ColorSpace //rget exec
- { resolvecolorspace /ColorSpace defineresource pop }
- { pop }
- ifelse
- }
- forall
-
- % if using color space substitution, "transition" the current color space
- {
- currentcolorspace dup length 1 eq % always an array
- {
- 0 get
- dup /DeviceGray eq 1 index /DeviceRGB eq or 1 index /DeviceCMYK or
- { /Pattern setcolorspace setcolorspace }
- { pop }
- ifelse
- }
- { pop }
- if
- }
- if
- }
- bind def
-
- % Write OutputIntents to device if the device handles it
- /writeoutputintents {
- currentdevice 1 dict dup /OutputIntent //null put readonly
- .getdeviceparams
- mark ne { pop pop
- % device supports OutputIntent parameter
- Trailer /Root oget /OutputIntents knownoget {
- dup type /arraytype eq {
- { % process all output profiles present
- oforce
- dup length dict .copydict
- dup /DestOutputProfile knownoget {
- PDFfile fileposition exch
- mark exch { oforce } forall .dicttomark
- //true resolvestream
- [ { counttomark 1 add index
- 64000 string readstring
- not { exit } if
- } loop
- ] exch closefile
- 0 1 index { length add } forall .bytestring
- 0 3 2 roll {
- 3 copy putinterval
- length add
- } forall pop
- exch PDFfile exch setfileposition
- 1 index /DestOutputProfile 3 2 roll put
- } if
- % Convert to string array because it's easier for the device
- [ 1 index /OutputCondition knownoget not { () } if
- 2 index /OutputConditionIdentifier knownoget not { () } if
- 3 index /RegistryName knownoget not { () } if
- 4 index /Info knownoget not { () } if
- 5 index /DestOutputProfile knownoget not { () } if
- ]
- [ /OutputIntent 3 2 roll .pdfputparams pop pop
- pop % done with this OutputIntent dictionary
- } forall
- } {
- pop
- ( **** Warning: OutputIntent attribute of a wrong type is ignored.\n)
- pdfformaterror
- } ifelse
- } if % OutputIntents known
- % tell device there are no more OutputIntents
- [ /OutputIntent [ ] .pdfputparams pop pop
- } if
- } bind def
-
- end % pdfdict
- .setglobal
|