星火微课系统客户端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

pdf_main.ps 68KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087
  1. % Copyright (C) 1994, 2000 Aladdin Enterprises. All rights reserved.
  2. %
  3. % This software is provided AS-IS with no warranty, either express or
  4. % implied.
  5. %
  6. % This software is distributed under license and may not be copied,
  7. % modified or distributed except as expressly authorized under the terms
  8. % of the license contained in the file LICENSE in this distribution.
  9. %
  10. % For more information about licensing, please refer to
  11. % http://www.ghostscript.com/licensing/. For information on
  12. % commercial licensing, go to http://www.artifex.com/licensing/ or
  13. % contact Artifex Software, Inc., 101 Lucas Valley Road #110,
  14. % San Rafael, CA 94903, U.S.A., +1(415)492-9861.
  15. % $Id: pdf_main.ps 10687 2010-02-02 07:23:57Z alexcher $
  16. % pdf_main.ps
  17. % PDF file- and page-level operations.
  18. /.setlanguagelevel where { pop 2 .setlanguagelevel } if
  19. .currentglobal true .setglobal
  20. /pdfdict where { pop } { /pdfdict 100 dict def } ifelse
  21. pdfdict begin
  22. % Patch in an obsolete variable used by some third-party software.
  23. /#? false def
  24. % Test whether the current output device handles pdfmark.
  25. /.writepdfmarkdict 1 dict dup /pdfmark null put readonly def
  26. /.writepdfmarks { % - .writepdfmarks <bool>
  27. currentdevice //.writepdfmarkdict .getdeviceparams
  28. mark eq { false } { pop pop true } ifelse
  29. systemdict /DOPDFMARKS known or
  30. } bind def
  31. % For simplicity, we use a single interpretation dictionary for all
  32. % PDF graphics execution, even though this is too liberal.
  33. /pdfopdict mark
  34. objopdict { } forall
  35. drawopdict { } forall
  36. /endstream { exit } bind
  37. (%%EOF) cvn { exit } bind % for filters
  38. /obj { ( **** Warning: Content stream is not terminated by 'endstream'.\n)
  39. pdfformaterror pop pop exit
  40. } bind
  41. % PDF 1.1 operators
  42. /BX { /BXlevel BXlevel 1 add store } bind
  43. /EX { /BXlevel BXlevel 1 sub store } bind
  44. /PS { cvx exec } bind
  45. % PDF 1.2 operators
  46. /BMC {
  47. /BMClevel BMClevel 1 add store
  48. pop
  49. } bind
  50. /BDC {
  51. /BMClevel BMClevel 1 add store
  52. exch /OC eq {
  53. dup type /nametype eq {
  54. PDFfile fileposition exch % pos /Name
  55. Page /Properties rget {
  56. ocg-is-visible not {
  57. OFFlevels BMClevel dup put
  58. } if
  59. } if
  60. PDFfile exch setfileposition
  61. } {
  62. pop
  63. } ifelse
  64. } {
  65. pop
  66. } ifelse
  67. } bind
  68. /EMC {
  69. OFFlevels BMClevel
  70. 2 copy known {
  71. 2 copy undef
  72. } if
  73. 1 sub /BMClevel exch store
  74. pop
  75. } bind
  76. /MP { pop } bind
  77. /DP { pop pop } bind
  78. /- { 0 % Bug 690016
  79. ( **** Warning: Invalid operator '-' is assumed to be a number 0.\n)
  80. pdfformaterror
  81. } bind
  82. .dicttomark readonly def
  83. % ======================== Main program ======================== %
  84. end % pdfdict
  85. userdict begin
  86. /defaultfontname /Times-Roman def
  87. % Make sure the registered encodings are loaded, so we don't run the risk
  88. % that some of the indices for their names will overflow the packed
  89. % representation. (Yes, this is a hack.)
  90. SymbolEncoding pop
  91. DingbatsEncoding pop
  92. % Redefine 'run' so it recognizes PDF files.
  93. systemdict begin
  94. /.runps /run load def
  95. /run {
  96. dup type /filetype ne { (r) file } if
  97. % skip leading whitespace characters (actually anything less than or equal to <sp>)
  98. { dup ( ) .peekstring not { false exit } if
  99. dup 0 get 32 le { pop dup read pop pop } { true exit } ifelse
  100. } loop
  101. exch pop
  102. {
  103. % Appletalk PAP sends short strings with %! header expecting a response.
  104. % 'gv' swallows the %!PS line, then sends DSC comments beginning with %%
  105. % and also waits for a response. The following avoids those hangs.
  106. dup 2 string .peekstring pop dup (%!) eq exch (%%) eq or {
  107. cvx .runps
  108. } {
  109. dup 1023 string .peekstring pop dup length 400 ge {
  110. % "1024 string" exceeds current %stdin buffer
  111. % Valid PDF file cannot be smaller than 400 bytes.
  112. (%PDF-) search {
  113. 3 1 roll pop pop
  114. dup (%!PS) search not {
  115. length 0 ne {
  116. 1 index exch readstring pop pop
  117. (%stderr) (w) file dup
  118. ( **** Warning: File has some garbage before %PDF- .\n)
  119. writestring flushfile
  120. } {
  121. pop
  122. } ifelse
  123. dup (%stdin) (r) file eq {
  124. % Copy PDF from stdin to temporary file then run it.
  125. null (w+) /.tempfile .systemvar exec exch 3 1 roll
  126. % stack: tempname stdin tempfile
  127. 64000 string
  128. {
  129. % stack: tempname stdin tempfile string
  130. 2 index 1 index readstring
  131. exch 3 index exch writestring
  132. not { exit } if
  133. }
  134. loop
  135. pop exch closefile
  136. % stack: tempname tempfile
  137. dup 0 setfileposition
  138. dup runpdf
  139. closefile deletefile
  140. } {
  141. runpdf
  142. } ifelse
  143. } {
  144. pop pop pop pop cvx .runps % (%!PS) found first
  145. } ifelse
  146. } {
  147. pop cvx .runps % (%PDF-) not found
  148. } ifelse
  149. } {
  150. pop cvx .runps % too short for PDF
  151. } ifelse
  152. } ifelse
  153. } {
  154. closefile % file was empty
  155. } ifelse
  156. } bind odef
  157. currentdict /runpdfstring .undef
  158. /runpdfbegin { % <file> runpdfbegin -
  159. userdict begin
  160. % It turns out that the PDF interpreter uses memory more
  161. % effectively if it is run under at least one level of save.
  162. % This is counter-intuitive, and we don't understand why it happens,
  163. % but the improvement is significant.
  164. /PDFTopSave save def
  165. 0 setobjectformat
  166. /Page# null def
  167. /Page null def
  168. /DSCPageCount 0 def
  169. /PDFSave null def
  170. GS_PDF_ProcSet begin
  171. pdfdict begin
  172. pdfopen begin
  173. } bind def
  174. /runpdfpagerange { % - runpdfpagerange <firstpage#> <lastpage#>
  175. /FirstPage where
  176. { pop FirstPage dup pdfpagecount gt
  177. { (\nRequested FirstPage is greater than the number of pages in the file: ) print
  178. pdfpagecount = flush
  179. } if
  180. } {
  181. 1
  182. } ifelse
  183. /LastPage where { pop LastPage pdfpagecount .min } { pdfpagecount } ifelse
  184. 1 index 1 index gt
  185. { ( No pages will be processed \(FirstPage > LastPage\).) = flush }
  186. { QUIET not
  187. { (Processing pages ) print 1 index =only ( through ) print dup =only
  188. (.) = flush
  189. }
  190. if
  191. }
  192. ifelse
  193. } bind def
  194. /dopdfpages { % firstpage# lastpage# dopdfpages -
  195. << /PDFScanRules //true >> setuserparams % set scanning rules for PDF vs. PS
  196. << /RenderTTNotdef systemdict
  197. /RENDERTTNOTDEF get >> setuserparams % Should we render TT /.notdef
  198. 1 exch
  199. { dup /Page# exch store
  200. QUIET not { (Page ) print dup == flush } if
  201. pdfgetpage pdfshowpage
  202. } for
  203. << /PDFScanRules //null >> setuserparams % restore scanning rules for PS
  204. } bind def
  205. /runpdfend {
  206. Repaired { printrepaired } if
  207. currentdict pdfclose
  208. end % temporary dict
  209. end % pdfdict
  210. end % GS_PDF_ProcSet
  211. PDFTopSave restore
  212. end % userdict
  213. 2 vmreclaim % couldn't hurt
  214. } bind def
  215. % Copy stream to an external temporary file and
  216. % return the file name as PS name.
  217. /copy_embedded_file {
  218. //true resolvestream % strm
  219. dup 1023 string .peekstring pop % "1024 string" exceeds current %stdin buffer
  220. dup length 400 ge { % Valid PDF file cannot be smaller than 400 bytes.
  221. (%PDF-) search {
  222. pop pop pop //true
  223. } {
  224. pop //false
  225. } ifelse
  226. } {
  227. pop //false
  228. } ifelse {
  229. //null (w) /.tempfile % strm (name) null (w) /.tempfile
  230. .systemvar exec % strm (name) file
  231. 3 -1 roll % (name) file strm
  232. 32768 string % (name) file strm (buf)
  233. { 3 copy readstring % (name) file strm (buf) file (data) bool
  234. 3 1 roll % (name) file strm (buf) bool file (data)
  235. writestring % (name) file strm (buf) bool
  236. not { exit } if
  237. } loop
  238. pop closefile % (name) file
  239. closefile % (name)
  240. cvn % /name
  241. } {
  242. closefile
  243. } ifelse
  244. } bind def
  245. % Copy selected subfiles to temporary files and return the file names
  246. % as a PostScript names to protect them from restore.
  247. % Currently, all PDF files in the Portfolio are extracted and returned.
  248. %
  249. % - pdf_collection_files [ /temp_file_name ... /temp_file_name
  250. /pdf_collection_files {
  251. mark
  252. Trailer /Root oget
  253. dup /Collection oknown {
  254. /Names knownoget {
  255. /EmbeddedFiles knownoget {
  256. /Names knownoget {
  257. { oforce
  258. dup type /dicttype eq {
  259. /EF knownoget {
  260. /F knownoget {
  261. copy_embedded_file
  262. } if
  263. } if
  264. } {
  265. pop
  266. } ifelse
  267. } forall
  268. } if
  269. } if
  270. } if
  271. } {
  272. pop
  273. } ifelse
  274. } bind def
  275. /runpdf { % <file> runpdf -
  276. //runpdfbegin exec
  277. //pdf_collection_files exec
  278. dup mark eq {
  279. pop
  280. process_trailer_attrs
  281. //runpdfpagerange exec
  282. //dopdfpages exec
  283. //runpdfend exec
  284. } {
  285. //runpdfend exec
  286. ] {
  287. dup type /filetype eq {
  288. //runpdfbegin exec
  289. process_trailer_attrs
  290. //runpdfpagerange exec
  291. //dopdfpages exec
  292. //runpdfend exec
  293. closefile
  294. } {
  295. .namestring dup (r) file
  296. //runpdfbegin exec
  297. process_trailer_attrs
  298. //runpdfpagerange exec
  299. //dopdfpages exec
  300. //runpdfend exec
  301. deletefile
  302. } ifelse
  303. } forall
  304. } ifelse
  305. } bind def
  306. currentdict /pdf_collection_files .undef
  307. end % systemdict
  308. % Redefine the procedure that the C code uses for running piped input.
  309. % It is OK to use { (%stdin) run } here, because a startjob cannot occur.
  310. /.runstdin {
  311. { (%stdin) run } execute0
  312. } bind def
  313. end % userdict
  314. pdfdict begin
  315. % ======================== File parsing ======================== %
  316. % Read the cross-reference and trailer sections.
  317. /traileropdict mark
  318. (<<) cvn { /dictlevelcount dictlevelcount 1 add store mark } bind
  319. (>>) cvn { { .dicttomark } stopped {
  320. ( **** File has unbalanced >> in trailer.\n) pdfformaterror
  321. } if
  322. /dictlevelcount dictlevelcount 1 sub def
  323. dictlevelcount 0 eq { exit } if
  324. } bind
  325. ([) cvn { mark } bind % ditto
  326. (]) cvn dup load
  327. % /true true % see .pdfexectoken in pdf_base.ps
  328. % /false false % ibid.
  329. % /null null % ibid.
  330. /R { /resolveR cvx 3 packedarray cvx } bind % see Objects below
  331. .dicttomark readonly def
  332. % Because of EOL conversion, lines with fixed contents might be followed
  333. % by one or more blanks.
  334. /lineeq % <filestr> <conststr> lineeq <bool>
  335. { anchorsearch
  336. { pop { ( ) anchorsearch not { () eq exit } if pop } loop }
  337. { pop false }
  338. ifelse
  339. } bind def
  340. /linene { lineeq not } bind def
  341. % Read original version (pre PDF 1.5) of the xref table.
  342. % Note: The position is the location of 'xref'. The current PDFfile
  343. % position is just after the 'XREF'.
  344. /readorigxref % <pos> readorigxref <trailerdict>
  345. {
  346. pop % We do not need the position.
  347. 0 % Initialize xref table error counter
  348. { PDFfile token pop % first object # or trailer
  349. dup /trailer eq { pop exit } if
  350. PDFfile pdfstring readline pop
  351. token pop % entry count
  352. % remaining must be whitespace only (otherwise this xref Size was invalid.
  353. exch dup length 0 ne {
  354. false 1 index { 32 gt { pop true exit } if } forall {
  355. ( **** Warning: xref subsection header has extra characters.\n)
  356. pdfformaterror
  357. /setxrefentry cvx /syntaxerror signalerror
  358. } if
  359. } if
  360. pop % remove last
  361. % This section might be adding new objects:
  362. % ensure that Objects and Generations are big enough.
  363. % stack: <err count> <first obj> <entry count>
  364. 2 copy add growPDFobjects
  365. { % stack: <err count> <obj num>
  366. % Read xref line
  367. PDFfile 20 string readstring pop % always read 20 chars.
  368. token pop % object position
  369. exch token pop % generation #
  370. exch token pop % n or f
  371. exch % stack: <err count> <obj#> <loc> <gen#> <tag> <remainder of line>
  372. dup length 0 ne {
  373. % check to make sure trailing garbage is just white space
  374. dup { 32 gt { 5 -1 roll 1 add 5 1 roll } if } forall % bump error count on garbage
  375. } if
  376. pop % Stack: <err count> <obj#> <loc> <gen#> <tag>
  377. dup /n eq { % xref line tag is /n
  378. pop % pop dup of line tag
  379. 2 copy or 0 eq {
  380. ( **** Warning: considering '0000000000 00000 n' as a free entry.\n)
  381. pdfformaterror
  382. } {
  383. 0 3 1 roll % Set ObjectStream object number = 0
  384. //false setxrefentry % Save xref entry, don't change existing entries
  385. 3 -1 roll pop % Remove ObjectStream object onumber
  386. } ifelse
  387. }
  388. { % xref line tag was not /n
  389. /f ne % verify that the tag was /f
  390. { /setxrefentry cvx /syntaxerror signalerror
  391. } if
  392. } ifelse
  393. pop pop % pop <obj location> and <gen num>
  394. % stack: <err count> <obj num>
  395. 1 add % increment object number
  396. } repeat
  397. pop % pop <obj #>
  398. } loop
  399. 0 ne {
  400. ( **** Warning: length of some xref entries is not equal to 20 bytes.\n)
  401. pdfformaterror
  402. } if
  403. /dictlevelcount 0 def
  404. PDFfile traileropdict .pdfrun
  405. } bind def
  406. % This dicitonary is used to read the xref dictionary. It should work for
  407. % reading any dictionary. dictlevelcount must contain 0.
  408. /xrefopdict mark
  409. (<<) cvn { /dictlevelcount dictlevelcount 1 add def mark } bind
  410. (>>) cvn { .dicttomark /dictlevelcount dictlevelcount 1 sub def
  411. dictlevelcount 0 eq { exit} if } bind
  412. ([) cvn { mark } bind % ditto
  413. (]) cvn dup load
  414. % /true true % see .pdfexectoken in pdf_base.ps
  415. % /false false % ibid.
  416. % /null null % ibid.
  417. /R { /resolveR cvx 3 packedarray cvx } bind % see Objects below
  418. .dicttomark readonly def
  419. % Get a variable length positive integer value from a stream. A value
  420. % of zero is returned if the count is zero.
  421. /getintn { % <stream> <count> getintn int
  422. 0 exch { 256 mul 1 index read pop add } repeat
  423. exch pop % Discard stream
  424. } bind def
  425. % This array contains handlers for processing the different types of
  426. % entries in the XRef stream.
  427. % Stack: <Xrefdict> <xref stream> <Index array> <pair loc> <obj num>
  428. % <field 2> <field 3>
  429. % The handlers leave the stack unchanged.
  430. /xref15entryhandlers [
  431. { % XRef entry type 0 - free or f type xref entry
  432. % (free ) print
  433. % (obj num: ) print 2 index pdfstring cvs print ( ) print
  434. % (loc: ) print 1 index pdfstring cvs print ( ) print
  435. % (gen: ) print dup === flush
  436. } bind % Do nothing for free xref entries
  437. % XRef entry type 1 - normal or n type xref entry
  438. { % field 2 = obj loc, field 3 = gen num
  439. % (normal ) print
  440. % (obj num: ) print 2 index pdfstring cvs print ( ) print
  441. % (loc: ) print 1 index pdfstring cvs print ( ) print
  442. % (gen: ) print dup === flush
  443. 0 3 1 roll % set stream number = 0
  444. //false setxrefentry
  445. 3 -1 roll pop % remove stream number
  446. } bind
  447. % XRef entry type 2 - compressed object type xref entry
  448. { % field 2 = object stream num, field 3 = index into object stream
  449. % (Compressed objects: ) print
  450. % (obj num: ) print 2 index pdfstring cvs print ( ) print
  451. % (field 2: ) print 1 index pdfstring cvs print ( ) print
  452. % (field 3: ) print dup === flush
  453. 0 //false setxrefentry pop % set generation number = 0
  454. } bind
  455. ] def
  456. % Read the PDF 1.5 version of the xref table.
  457. % Note: The position is the location of the start of the dictionary object
  458. % In PDF 1.5, the XRef dictionary also serves as the trailer dictionary
  459. /readpdf15xref % <pos> readpdf15xref <trailerdict>
  460. {
  461. PDFfile exch setfileposition % move to start of object
  462. % Get object number, revision, and 'obj' and discard
  463. PDFfile token pop pop
  464. PDFfile token pop pop
  465. PDFfile token pop pop
  466. % Get the XRef dicitionary
  467. /dictlevelcount 0 def PDFfile xrefopdict .pdfrun
  468. % Verify that we have an XRef dictionary
  469. dup /Type get /XRef ne {
  470. /readpdf15xref cvx /syntaxerror signalerror
  471. } if
  472. % Ensure that we we have room in the objects array, etc.
  473. dup /Size get growPDFobjects
  474. % Create a stream for the XRef data
  475. PDFfile token pop pop % Skip over 'stream'
  476. dup stream false resolvestream
  477. % Stack: <XRefdict> <xref stream>
  478. % The Index array defines the ranges of object numbers in the
  479. % XRef stream. Each value pair is consists of starting object
  480. % number and the count of consecutive objects.
  481. % Get the Index array, if present
  482. 1 index /Index .knownget not { % If no Index array ...
  483. [ 0 3 index /Size get ] % Default = [ 0 Size ]
  484. } if
  485. % Loop through the Index array
  486. 0 2 2 index length 1 sub {
  487. % Get start and end of object range
  488. 2 copy get % Start of the range
  489. dup 3 index 3 index 1 add get % Number of entries in range
  490. % Loop through the range of object numbers
  491. add 1 sub 1 exch { % Form end of range, set increment = 1
  492. % Stack: <Xrefdict> <xref stream> <Index array> <pair loc> <obj num>
  493. % Get xref parameters. Note: The number of bytes for each parameter
  494. % is defined by the entries in the W array.
  495. 4 index /W get aload pop % Get W array values
  496. % The first field indicates type of entry. Get first field value.
  497. % If the num. of bytes for field 1 is 0 then default field value is 1
  498. 3 -1 roll dup 0 eq { pop 1 } { 6 index exch getintn } ifelse
  499. % Get the handler for the xref entry type. We will execute the
  500. % handler after we get the other two field values.
  501. xref15entryhandlers exch get
  502. 3 -1 roll 6 index exch getintn % Get second field
  503. 3 -1 roll 6 index exch getintn % Get third field
  504. 3 -1 roll exec % Execute Xref entry handler
  505. pop pop pop % Remove field values and obj num
  506. } for % Loop through Xref entries
  507. pop % Remove Index array pair loc
  508. } for % Loop through Index array entries
  509. pop pop % Remove Index array and xref stream
  510. } bind def
  511. % Read the cross-reference table.
  512. % <pos> is the position either from the startxref statement or the /Prev
  513. % entry in the prior trailer dictionary.
  514. /readxref % <pos> readxref <trailerdict>
  515. {
  516. PDFoffset add PDFfile exch
  517. % Check that the given location is within the file.
  518. dup PDFfilelen gt {
  519. ( **** Warning: Specified xref location is beyond end of file.\n)
  520. pdfformaterror
  521. /readxref cvx /invalidaccess signalerror
  522. } if
  523. setfileposition
  524. % In some PDF files, this position actually points to
  525. % white space before the xref line. Skip over this here.
  526. {
  527. PDFfile fileposition PDFfile read pop 32 gt { exit } if pop
  528. } loop
  529. dup % Make copy of the file position (before last char was read).
  530. PDFfile exch setfileposition
  531. % The PDF specification says that the 'xref' must be on a line
  532. % by itself. The code here formerly used readline and linene to
  533. % check this. However, Acrobat Reader only requires the line to
  534. % begin with 'xref', and there are enough applications producing
  535. % non-compliant PDF files that we have to do this too.
  536. PDFfile pdfstring 0 4 getinterval readstring pop
  537. (xref) eq
  538. {
  539. readorigxref % 'xref' -> original xref table
  540. % if hybrid-reference PDF, also fetch the entries
  541. % found in the XRef stream pointed by /XRefStm
  542. dup /XRefStm knownoget {
  543. readpdf15xref pop
  544. } if
  545. }
  546. { readpdf15xref } % otherwise assume PDF 1.5 xref stream
  547. ifelse
  548. } bind def
  549. % Open a PDF file and read the header, trailer, and cross-reference.
  550. /pdfopen { % <file> pdfopen <dict>
  551. % Color space substitution in PDF is handled somewhat differently
  552. % than in PostScript. A given device color space will be substituted
  553. % if the corresponding "Default..." entry exists in the Page's
  554. % Resource dictionary (which might be inhereted); there is no
  555. % UseCIEColor to enable/disable color mapping.
  556. %
  557. % This behavior is achieved by always setting UseCIEColor to true
  558. % in the page device dictionary. If the value of this parameter was
  559. % originally false (i.e.: the output device does not perform color
  560. % space substitution by default), the instances DefaultGray,
  561. % DefaultRGB, and DefaultCMYK of the (local) ColorSpace category
  562. % are redefined to be DeviceGray, DeviceRGB, and DeviceCMYK,
  563. % respectively. This is not done if UseCIEColor is true by default,
  564. % as in that case color substitution is presumably desired even
  565. % if the file does not request it.
  566. currentpagedevice /UseCIEColor .knownget dup { pop } if not
  567. { .currentglobal false .setglobal
  568. /DefaultGray { /DeviceGray } cvlit /ColorSpace defineresource pop
  569. /DefaultRGB { /DeviceRGB } cvlit /ColorSpace defineresource pop
  570. /DefaultCMYK { /DeviceCMYK } cvlit /ColorSpace defineresource pop
  571. .setglobal
  572. }
  573. if
  574. pdfopenfile begin
  575. pdfopencache
  576. currentdict end
  577. } bind def
  578. /process_trailer_attrs { % - process_trailer_attrs -
  579. writeoutputintents
  580. .writepdfmarks {
  581. % Copy bookmarks (outline) to the output.
  582. Trailer /Root oget /Outlines knownoget {
  583. /First knownoget {
  584. { dup writeoutline /Next knownoget not { exit } if } loop
  585. } if
  586. } if
  587. } if % end .writepdfmarks
  588. % Initialize OC groups
  589. Trailer /Root oget /OCProperties knownoget {
  590. % By default, OCGs are 'on'; mark only 'off' OCGs.
  591. /D knownoget {
  592. /OFF knownoget {
  593. { oforce dup type /dicttype eq {
  594. /OFF 0 put
  595. } {
  596. pop
  597. } ifelse
  598. } forall
  599. } if
  600. } if
  601. } if
  602. } bind def
  603. % Verify that each entry in the xref table is pointing at an object with
  604. % the correct object number and generation number.
  605. /verify_xref % - verify_xref -
  606. { PDFfilelen
  607. 1 1 Objects llength 1 sub % stack: filesize 1 1 <number of objects - 1>
  608. { % Check if the object is free (i.e. not used). The values in
  609. % Generations is the generation number plus 1. If the value in
  610. % Generations is zero then the object is free.
  611. % Stack: <filesize> <obj num>
  612. Generations 1 index lget % Get the genration number
  613. 0 ne { % Skip if object number is free
  614. ObjectStream 1 index lget % Check if object is in objectstream
  615. 0 eq { % We only check objects not in an objectstream
  616. { % Use stop context since we may get an error if object is invalid
  617. dup Objects exch lget % Get the object location
  618. PDFoffset add dup 3 index ge % Compare object location to file size
  619. { pop true } % Rebuild if location not in file
  620. { PDFfile exch setfileposition % Go to the object location
  621. true % Stack: <filesize> <obj num> <true>
  622. PDFfile token pop % Read object number from file
  623. 2 index eq { % Verify object number
  624. PDFfile token pop % Read generation number from file
  625. Generations 3 index % Get specified generaton number
  626. lget 1 sub % Gen numbs are stored with 1 added.
  627. eq { % Verify generation number
  628. PDFfile token pop
  629. /obj eq { % Verify 'obj' text
  630. pop false % We have valid object, do not rebuild
  631. } if
  632. } if
  633. } if
  634. } ifelse
  635. } .internalstopped
  636. { true } if % If we stop then we need to rebuild
  637. % Stack: <filesize> <obj num> <need rebuild flag>
  638. {
  639. ( **** Warning: File has an invalid xref entry: )
  640. pdfformaterror
  641. pdfstring cvs pdfformaterror
  642. (. Rebuilding xref table.\n) pdfformaterror
  643. search_objects
  644. exit
  645. } if % If the entry is invalid
  646. } {
  647. % The object is in an object stream. We currently do not rebuild
  648. % objects in an object stream. So If we find one, then abort the
  649. % verification of the xref table entries.
  650. pop exit % Pop object number and then exit loop
  651. } ifelse % If not in an object stream
  652. } if % If object entry is not free
  653. pop % Remove object number
  654. } for
  655. pop % Remove the size of the file
  656. } bind odef
  657. /pdfopencache { % - pdfopencache -
  658. % Create and initialize some caches.
  659. /PageCount pdfpagecount def
  660. /PageNumbers PageCount 65534 .min dict def
  661. /PageIndex PageCount 65534 .min array def
  662. } bind def
  663. /pdfopenfile { % <file> pdfopenfile <dict>
  664. pdfdict readonly pop % can't do it any earlier than this
  665. 15 dict begin
  666. /LocalResources 0 dict def
  667. /DefaultQstate //null def % establish binding
  668. /Printed where { pop } {
  669. % Guess whether the output device is a printer.
  670. /Printed currentpagedevice /OutputFile known def
  671. } ifelse
  672. /PSLevel1 where { pop } { /PSLevel1 false def } ifelse
  673. % NB: PDFfile is used outside of the PDF code to determine that a
  674. % PDF job is being processed; to not change or hide this key.
  675. cvlit /PDFfile exch def
  676. /PDFsource PDFfile def
  677. /Repaired false def
  678. currentglobal true .setglobal globaldict begin
  679. /UndefProcList 0 dict def
  680. end .setglobal
  681. PDFfile dup 0 setfileposition
  682. 0 () /SubFileDecode filter % to avoid file closure
  683. pdfstring readstring pop
  684. (%PDF-) search not {/pdfopen cvx /syntaxerror signalerror} if
  685. length /PDFoffset exch def pop
  686. % some badly formed PDF's (Visioneer) have something other than EOL
  687. % after the version number. If we get an error, shorten the string
  688. % and try again.
  689. false exch % error encountered
  690. { { cvr } stopped
  691. { exch pop true exch 0 1 index length 1 sub dup 0 eq
  692. { pop 0 exit } if % exit if string now empty
  693. getinterval % trim character from right end and retry
  694. }
  695. { exch {
  696. ( **** Warning: PDF version number not followed by EOL.\n)
  697. pdfformaterror
  698. }
  699. if exit
  700. }
  701. ifelse
  702. } loop
  703. /PDFversion exch def
  704. % Read the last cross-reference table.
  705. count /pdfemptycount exch def
  706. /Trailer << >> def % Initialize to an emptry dict.
  707. { initPDFobjects findxref readxref } .internalstopped {
  708. recover_xref_data % Read failed. Attempt to recover xref data.
  709. search_trailer % Search for the primary trailer
  710. } {
  711. /Trailer exch def % Save trailer dict after first xref table
  712. % Read any previous cross-reference tables. When we are done,
  713. % verify that the entries in the xref tables are valid if NoVerifyXref
  714. % is not defined.
  715. Trailer
  716. { /Prev knownoget not { % If no previous xref table then ...
  717. /NoVerifyXref where { pop } { verify_xref } ifelse exit
  718. } if
  719. { readxref } .internalstopped {
  720. recover_xref_data % Read failed. Attempt to recover xref data.
  721. exit % Exit loop since recover gets all obj data.
  722. } if % If readxref stopped
  723. % The PDF spec. says that each trailer dict should contain the required
  724. % entries. However we have seen a PDF file that only has a Prev entry in
  725. % the initial trailer dict. Acrobat complains but it accepts these files.
  726. % To work with these files, we are copying any entries which we find in
  727. % a previous trailer dict which are not present in the initial dict.
  728. dup {
  729. Trailer 2 index known {
  730. pop pop % discard if key already present
  731. } {
  732. Trailer 3 1 roll put % add key if not present
  733. } ifelse
  734. } forall
  735. } loop % Loop to previous trailer
  736. } ifelse % Ifelse readxref stopped
  737. % Scan numbers in the range 2147483648..4294967295 in Encrypt dictionary
  738. % as unsigned integers for compatibility with Acrobat Reader. Bug 689010.
  739. << /PDFScanUnsigned //true >> setuserparams
  740. { Trailer /Encrypt knownoget {
  741. pop
  742. pdf_process_Encrypt % signal error
  743. } if
  744. } stopped
  745. << /PDFScanUnsigned //false >> setuserparams
  746. { stop } if
  747. % Check for recursion in the page tree. Bug 689954, MOAB-06-01-2007
  748. verify_page_tree
  749. currentdict end
  750. } bind def
  751. % Look for [\r\n]%%EO from the current position of the file.
  752. % Return the position of %%EO if found or -1 .
  753. /findeof { % <file> find_eof <file> <position>
  754. -1 exch
  755. {
  756. dup bytesavailable 4 lt { exit } if
  757. dup 0 (%%EO) /SubFileDecode filter flushfile
  758. dup dup fileposition 5 sub setfileposition
  759. dup 5 string readstring not { pop exit } if
  760. dup (\r%%EO) eq exch (\n%%EO) eq or {
  761. dup fileposition 4 sub
  762. 3 1 roll exch pop
  763. } if
  764. } loop
  765. exch
  766. } bind def
  767. % Skip backward over the %%EOF at the end of the PDF file, and read
  768. % the preceding startxref line. The PDF specification unambiguously
  769. % requires that the %%EOF appear on a line by itself, and that the
  770. % startxref and the following position value appear on separate lines;
  771. % however, some applications truncate the %%EOF to %%EO, and/or put the
  772. % startxref and the following value on the same line.
  773. % There seems to be no limit on the amount of garbage that can be
  774. % appended to the PDF file. Current record (60K) belongs to
  775. % PDF-Out (v 2.0 - 35). We start the search for %%EO from the last 1024
  776. % bytes and continue from the beginning of the file.
  777. /findxref { % - findxref <xrefpos>
  778. PDFfile dup dup dup 0 setfileposition bytesavailable
  779. dup /PDFfilelen exch def
  780. % Find the last %%EOF string (within 1024 bytes)
  781. 1024 sub PDFoffset .max
  782. setfileposition findeof % search the last 1024 bytes
  783. dup 0 le {
  784. pop
  785. dup PDFoffset setfileposition findeof % search from the beginnibg
  786. dup 0 le {
  787. ( **** Error: Cannot find a %%EOF marker anywhere in the file.\n)
  788. pdfformaterror
  789. /findxref cvx /syntaxerror signalerror
  790. } if
  791. } if
  792. dup 3 1 roll setfileposition
  793. % Stack: eofpos
  794. % Check for whether this is, in fact, a valid PDF file.
  795. dup PDFfilelen exch sub dup dup 7 gt exch 5 lt or {
  796. pop true
  797. } {
  798. string PDFfile exch readstring pop
  799. dup (%%EOF\n) eq exch dup (%%EOF\r) eq
  800. exch dup (%%EOF\r\n) eq exch (%%EOF) eq or or or not
  801. } ifelse {
  802. ( **** Warning: File has a corrupted %%EOF marker, or garbage after %%EOF.\n)
  803. pdfformaterror
  804. } if
  805. PDFfile exch setfileposition
  806. % Now read the startxref and xref start position.
  807. prevline token not { null } if dup type /integertype eq {
  808. exch pop cvi % xref start position
  809. exch PDFfile exch setfileposition
  810. prevline dup (startxref) linene {
  811. % startxref not on a line by itself. We have found PDF from
  812. % www.verypdf.com in which the startxref was on the same line as
  813. % the end of trailer dictionary. Check for this. Note: This
  814. % violates the spec.
  815. dup (startxref) search {
  816. % found startxref - print warning
  817. pop pop pop % clear strings from search
  818. ( **** Warning: format of the startxref line in this file is invalid.\n)
  819. pdfformaterror
  820. } { % no startxref - we have a problem.
  821. /findxref cvx /syntaxerror signalerror
  822. } ifelse
  823. } if
  824. pop pop
  825. } { % else, this file has 'startxref #####' format
  826. (startxref) ne { /findxref cvx /syntaxerror signalerror } if
  827. cvi % xref start position
  828. ( **** Warning: format of the startxref line in this file is invalid.\n)
  829. pdfformaterror
  830. exch PDFfile exch setfileposition
  831. } ifelse
  832. } bind def
  833. /stderrfile (%stderr) (w) file def
  834. /stderrprint { % <string> stderrprint -
  835. //stderrfile dup 3 -1 roll writestring flushfile
  836. } bind def
  837. /pdfformaterror { % <string> pdfformaterror -
  838. stderrprint
  839. /Repaired true store
  840. } bind def
  841. /knownoget_safe
  842. { 2 copy knownoget { 3 1 roll pop pop //true } { pop pop //false } ifelse
  843. } odef
  844. /printProducer {
  845. Trailer /Info { knownoget_safe } stopped { pop pop false } if {
  846. /Producer knownoget not { null } if
  847. } {
  848. null
  849. } ifelse
  850. dup null eq {
  851. pop
  852. } {
  853. ( **** The file was produced by: \n **** >>>> ) stderrprint
  854. % Handle a Unicode Producer.
  855. (\376\377) anchorsearch {
  856. pop dup length 2 idiv string 0 1 2 index length 1 sub {
  857. % Stack: origstr newstr i
  858. 1 index exch 3 index 1 index 2 mul 1 add get put
  859. } for exch pop
  860. } if
  861. stderrprint
  862. ( <<<<\n) stderrprint
  863. } ifelse
  864. } bind def
  865. % The UndefProcList collects noisy warnings.
  866. % This gets rid of many multiple warnings from pdf_font.ps
  867. /printCollectedWarnings {
  868. UndefProcList length 0 gt {
  869. (\n **** Embedded font uses undefined procedure\(s\): ) stderrprint
  870. UndefProcList {
  871. exch .namestring stderrprint ( ) stderrprint
  872. =string cvs stderrprint ( times, ) stderrprint
  873. } forall
  874. (\n) stderrprint
  875. } if
  876. } bind def
  877. /printrepaired {
  878. printCollectedWarnings
  879. (\n **** This file had errors that were repaired or ignored.\n)
  880. stderrprint
  881. printProducer
  882. ( **** Please notify the author of the software that produced this\n)
  883. stderrprint
  884. ( **** file that it does not conform to Adobe's published PDF\n)
  885. stderrprint
  886. ( **** specification.\n\n)
  887. stderrprint
  888. } bind def
  889. % Write the outline structure for a file. Uses linkdest (below).
  890. % omit links to pages that don't exist.
  891. /writeoutline % <outlinedict> writeoutline -
  892. { mark
  893. 0 2 index /First knownoget
  894. { { exch 1 add exch /Next knownoget not { exit } if } loop }
  895. if
  896. % stack: dict mark count
  897. dup 0 eq
  898. { pop 1 index }
  899. { 2 index /Count knownoget { 0 lt { neg } if } if
  900. /Count exch 3 index
  901. }
  902. ifelse
  903. {
  904. dup /A knownoget {
  905. dup /URI known {
  906. /A mark 3 2 roll % <<>> /A [ <<action>>
  907. { oforce } forall
  908. .dicttomark
  909. 3 2 roll
  910. } {
  911. dup /D knownoget {
  912. exch pop exch dup length dict copy dup /Dest 4 -1 roll put
  913. } {
  914. /N knownoget { % Assume /S /Named
  915. namedactions exch .knownget { exec } if
  916. } if
  917. } ifelse
  918. } ifelse
  919. } if
  920. linkdest
  921. } stopped
  922. {
  923. cleartomark % ignore this link
  924. ( **** Warning: Outline has invalid link that was discarded.\n)
  925. pdfformaterror
  926. } {
  927. /Title oget /Title exch /OUT pdfmark
  928. }
  929. ifelse
  930. /First knownoget
  931. { { dup writeoutline /Next knownoget not { exit } if } loop }
  932. if
  933. } bind def
  934. % Close a PDF file.
  935. /pdfclose % <dict> pdfclose -
  936. { begin
  937. PDFfile closefile
  938. end
  939. } bind def
  940. % ======================== Page accessing ======================== %
  941. % Get a (possibly inherited) attribute of a page.
  942. /pget % <pagedict> <key> pget <value> -true-
  943. % <pagedict> <key> pget -false-
  944. {
  945. 2 copy knownoget
  946. { exch pop exch pop true }
  947. { exch /Parent knownoget
  948. { exch pget }
  949. % finally see if the key is (misplaced) in the Root Catalog dict
  950. { dup Trailer /Root oget exch knownoget dup {
  951. 3 -1 roll ( **** Warning: The /) pdfformaterror 50 string cvs pdfformaterror
  952. ( key is missing from the Page tree.\n) pdfformaterror
  953. }
  954. { exch pop }
  955. ifelse
  956. }
  957. ifelse
  958. }
  959. ifelse
  960. } bind def
  961. % Get the value of a resource on a given page.
  962. /rget { % <resname> <pagedict> <restype> rget <value> -true-
  963. % <resname> <pagedict> <restype> rget -false-
  964. LocalResources 1 index knownoget {
  965. dup type /dicttype eq {
  966. 3 index knownoget
  967. } {
  968. //false exch {
  969. 4 index knownoget {
  970. exch not exit
  971. } if
  972. } forall
  973. } ifelse
  974. } {
  975. //false
  976. } ifelse {
  977. exch pop exch pop exch pop //true
  978. } {
  979. exch /Resources pget {
  980. exch knownoget { % /Name [<<>> ...]
  981. dup type /dicttype eq {
  982. exch knownoget
  983. } {
  984. % GS uses array of dicts if resources don't fit in one dict.
  985. //false 3 1 roll { % false /Name <<>>
  986. 1 index knownoget { % false /Name val
  987. exch pop exch not % i.e. true
  988. 0 exit
  989. } if
  990. } forall
  991. pop
  992. } ifelse
  993. } {
  994. pop //false
  995. } ifelse
  996. } {
  997. pop pop //false
  998. } ifelse
  999. } ifelse
  1000. } bind def
  1001. % Get the total number of pages in the document.
  1002. /pdfpagecount % - pdfpagecount <int>
  1003. { Trailer /Root oget /Pages oget
  1004. dup /Count knownoget {
  1005. dup 0 le {
  1006. pop
  1007. dup /Kids knownoget {
  1008. pop
  1009. ( **** Warning: Invalid Page count.\n) pdfformaterror
  1010. % find the last page and use that as the Count
  1011. 1 1 999999999 {
  1012. dup pdffindpage?
  1013. exch pop
  1014. //null eq { exit } { pop } ifelse
  1015. } for
  1016. 1 sub % decrement to last page that we were able to find
  1017. 2 copy /Count exch put
  1018. } {
  1019. 0 % return 0 and keep 0 page count.
  1020. ( **** Warning: PDF document has no pages.\n) pdfformaterror
  1021. } ifelse
  1022. } if
  1023. exch pop
  1024. } {
  1025. dup /Type oget /Page eq {
  1026. << exch 1 array astore /Kids exch /Count 1 /Type /Pages >>
  1027. Trailer /Root oget /Pages 3 -1 roll put
  1028. 1
  1029. ( **** Warning: No /Pages node. The document root directly point a page.\n)
  1030. pdfformaterror
  1031. } {
  1032. ( **** Warning: Page count not found; assuming 1.\n)
  1033. pdfformaterror
  1034. pop 1
  1035. } ifelse
  1036. } ifelse
  1037. } bind def
  1038. % Check for loops in the 'page tree' but accept an acyclic graph.
  1039. % - verify_page_tree -
  1040. /verify_page_tree {
  1041. Trailer /Root oget /Pages oget
  1042. 10 dict begin
  1043. /verify_page_tree_recursive {
  1044. dup 1 def
  1045. dup /Kids knownoget {
  1046. { oforce
  1047. currentdict 1 index known {
  1048. ( **** Error: there's a loop in the page tree. Giving up.\n) pdfformaterror
  1049. /verify_page_tree cvx /syntaxerror signalerror
  1050. } if
  1051. verify_page_tree_recursive
  1052. } forall
  1053. } if
  1054. currentdict exch undef
  1055. } def
  1056. verify_page_tree_recursive
  1057. end
  1058. } bind def
  1059. /pdffindpage? { % <int> pdffindpage? 1 null (page not found)
  1060. % <int> pdffindpage? 1 noderef (page found)
  1061. % <int> pdffindpage? 0 null (Error: page not found)
  1062. Trailer /Root oget /Pages get
  1063. { % We should be able to tell when we reach a leaf
  1064. % by finding a Type unequal to /Pages. Unfortunately,
  1065. % some files distributed by Adobe lack the Type key
  1066. % in some of the Pages nodes! Instead, we check for Kids.
  1067. dup oforce /Kids knownoget not { exit } if
  1068. exch pop null
  1069. 0 1 3 index length 1 sub {
  1070. 2 index exch get
  1071. dup oforce dup /Kids known { /Count oget } { pop 1 } ifelse
  1072. % Stack: index kids null noderef count
  1073. dup 5 index ge { pop exch pop exit } if
  1074. 5 -1 roll exch sub 4 1 roll pop
  1075. } for exch pop
  1076. % Stack: index null|noderef
  1077. dup null eq { pop pop 1 null exit } if
  1078. } loop
  1079. } bind def
  1080. % Find the N'th page of the document by iterating through the Pages tree.
  1081. % The first page is numbered 1.
  1082. /pdffindpageref { % <int> pdffindpage <objref>
  1083. dup pdffindpage?
  1084. % Stack: index countleft noderef
  1085. 1 index 1 ne { pop pop /pdffindpage cvx /rangecheck signalerror } if
  1086. exch pop
  1087. PageIndex 2 index 1 sub 65533 .min 2 index oforce put
  1088. PageNumbers 1 index oforce 3 index dup 65534 le
  1089. { put }
  1090. { pop pop pop } % don't store more than 65534 pagenumbers
  1091. ifelse
  1092. exch pop
  1093. } bind def
  1094. /pdffindpage { % <int> pdffindpage <pagedict>
  1095. pdffindpageref oforce
  1096. } bind def
  1097. % Find the N'th page of the document.
  1098. % The first page is numbered 1.
  1099. /pdfgetpage % <int> pdfgetpage <pagedict>
  1100. { PageIndex 1 index 1 sub dup 65533 lt
  1101. { get }
  1102. { pop pop null }
  1103. ifelse
  1104. dup null ne
  1105. { exch pop oforce }
  1106. { pop pdffindpage }
  1107. ifelse
  1108. } bind def
  1109. % Find the page number of a page object (inverse of pdfgetpage).
  1110. /pdfpagenumber % <pagedict> pdfpagenumber <int>
  1111. { % We use the simplest and stupidest of all possible algorithms....
  1112. PageNumbers 1 index .knownget
  1113. { exch pop
  1114. }
  1115. { 1 1 PageCount 1 add % will give a rangecheck if not found
  1116. { dup pdfgetpage oforce 2 index eq { exit } if pop
  1117. }
  1118. for exch pop
  1119. }
  1120. ifelse
  1121. } bind def
  1122. % Arrange the four elements that define a rectangle into a 'normal' order.
  1123. /normrect_elems % <x1> <y1> <x2> <y2> normrect_elems <llx> <lly> <urx> <ury>
  1124. {
  1125. exch 4 1 roll % <x2> <x1> <y1> <y2>
  1126. 2 copy gt { exch } if % <x2> <x1> <lly> <ury>
  1127. 4 2 roll 2 copy lt { exch } if % <lly> <ury> <urx> <llx>
  1128. 4 1 roll exch % <llx> <lly> <urx> <ury>
  1129. } bind def
  1130. % Arrange a rectangle into a 'normal' order. I.e the lower left corner
  1131. % followed by the upper right corner.
  1132. /normrect % <rect> normrect <rect>
  1133. {
  1134. aload pop normrect_elems 4 array astore
  1135. } bind def
  1136. /fix_empty_rect_elems % </Name> <x1> <y1> <x2> <y2> fix_empty_rect_elems <x1> <y1> <x2'> <y2'>
  1137. { dup 3 index eq { //true } { 1 index 4 index eq } ifelse {
  1138. pop pop pop pop
  1139. ( **** Warning: File has an empty ) pdfformaterror pdfstring cvs pdfformaterror
  1140. (. Using the current page size instead.\n) pdfformaterror
  1141. 0 0 currentpagedevice /PageSize get aload pop
  1142. } {
  1143. 5 -1 roll pop
  1144. } ifelse
  1145. } bind def
  1146. /boxrect % <llx> <lly> <urx> <ury> boxrect <x> <y> <w> <h>
  1147. { exch 3 index sub exch 2 index sub
  1148. } bind def
  1149. /resolvedest { % <name|string|other> resolvedest <other|null>
  1150. dup type /nametype eq {
  1151. Trailer /Root oget /Dests knownoget {
  1152. exch knownoget not { null } if
  1153. } {
  1154. pop null
  1155. } ifelse
  1156. } {
  1157. dup type /stringtype eq {
  1158. Trailer /Root oget /Names knownoget {
  1159. /Dests knownoget {
  1160. exch nameoget
  1161. } {
  1162. pop null
  1163. } ifelse
  1164. } {
  1165. pop null
  1166. } ifelse
  1167. } if
  1168. } ifelse
  1169. } bind def
  1170. % Procedures to do the necessary transformations of view destinations
  1171. % <PDF2PS_matrix> <rot> <view> -- <view'>
  1172. /viewdestprocs 8 dict dup begin
  1173. /Fit { exch pop exch pop } bind def
  1174. /FitH {
  1175. aload pop
  1176. 0 4 -1 roll 1 and 0 eq { exch } if
  1177. 4 -1 roll transform exch pop
  1178. 2 array astore
  1179. } bind def
  1180. /FitV {
  1181. aload pop
  1182. 0 4 -1 roll 1 and 0 ne { exch } if
  1183. 4 -1 roll transform pop
  1184. 2 array astore
  1185. } bind def
  1186. /FitB /Fit load def
  1187. /FitBH /FitH load def
  1188. /FitBV /FitV load def
  1189. /XYZ {
  1190. aload pop
  1191. 3 1 roll
  1192. 2 copy 7 -1 roll 1 and 0 ne { exch } if 4 2 roll % odd rotation switches x<->y
  1193. 2 { dup null eq { pop 0 } if exch } repeat % replace nulls with 0
  1194. 7 -1 roll transform % transform coordinates
  1195. 2 { 3 -1 roll null eq { pop null } if exch } repeat % put the nulls back
  1196. 3 -1 roll
  1197. 4 array astore
  1198. } bind def
  1199. /FitR {
  1200. exch pop
  1201. aload pop
  1202. 2 { 5 index transform 4 2 roll } repeat normrect_elems
  1203. 5 array astore
  1204. exch pop
  1205. } bind def
  1206. end readonly def
  1207. /linkdest { % <link|outline> linkdest
  1208. % ([/Page <n>] /View <view> | ) <link|outline>
  1209. dup /Dest knownoget
  1210. { resolvedest
  1211. dup type /dicttype eq { /D knownoget not { null } if } if
  1212. dup null eq
  1213. { pop }
  1214. { dup 0 oget
  1215. false % don't have a page# and transformation matrix (yet)
  1216. 1 index type /dicttype eq {
  1217. 1 index /Type knownoget {
  1218. /Page eq {
  1219. pop % the "false" flag
  1220. dup pdf_cached_PDF2PS_matrix exch
  1221. dup /Rotate pget not { 0 } if 90 idiv exch
  1222. pdfpagenumber
  1223. true % now we have a page# and a transformation matrix
  1224. } if
  1225. } if
  1226. } if
  1227. % stack: <link|outline> <dest> ( <PDF2PS_matrix> <rot> <page#> true | <page> false )
  1228. {
  1229. /Page exch 6 2 roll
  1230. % stack: [/Page <page#>] <link|outline> <dest> <PDF2PS_matrix> <rot>
  1231. 3 -1 roll dup length 1 sub 1 exch getinterval /View 4 1 roll
  1232. % stack: [/Page <page#>] <link|outline> /View <PDF2PS_matrix> <rot> <view>
  1233. //viewdestprocs 1 index 0 get get exec
  1234. 3 -1 roll
  1235. } {
  1236. pop
  1237. dup length 1 sub 1 exch getinterval /View exch 3 -1 roll
  1238. } ifelse
  1239. }
  1240. ifelse
  1241. }
  1242. if
  1243. } bind def
  1244. % <pagedict> mark ... -proc- <page#> <error>
  1245. /namedactions 8 dict dup begin
  1246. /FirstPage { 1 //false } def
  1247. /LastPage { pdfpagecount //false } def
  1248. /NextPage { counttomark 2 add index pdfpagenumber 1 add dup pdfpagecount gt } bind def
  1249. /PrevPage { counttomark 2 add index pdfpagenumber 1 sub dup 1 lt } bind def
  1250. end readonly def
  1251. % <pagedict> <annotdict> -proc- -
  1252. /annottypes 5 dict dup begin
  1253. /Text {
  1254. mark exch
  1255. { /Rect /Open /Contents }
  1256. { 2 copy knownoget { 3 -1 roll } { pop } ifelse }
  1257. forall pop /ANN pdfmark
  1258. } bind def
  1259. /Link {
  1260. mark exch
  1261. dup /BS knownoget { << exch { oforce } forall >> /BS exch 3 -1 roll } if
  1262. dup /F knownoget { /F exch 3 -1 roll } if
  1263. dup /C knownoget { /Color exch 3 -1 roll } if
  1264. dup /Rect knownoget { /Rect exch 3 -1 roll } if
  1265. dup /Border knownoget {
  1266. dup type /arraytype eq {
  1267. dup length 3 lt
  1268. } {
  1269. //true
  1270. } ifelse {
  1271. pop [ 0 0 0 ] % Following AR5 use invisible border.
  1272. } if
  1273. /Border exch 3 -1 roll
  1274. } if
  1275. dup /A knownoget {
  1276. dup /URI known {
  1277. /A mark 3 2 roll % <<>> /A [ <<action>>
  1278. { oforce } forall
  1279. .dicttomark
  1280. 3 2 roll
  1281. } {
  1282. dup /D knownoget {
  1283. exch pop exch dup length dict copy dup /Dest 4 -1 roll put
  1284. } {
  1285. /N knownoget { % Assume /S /Named
  1286. namedactions exch .knownget {
  1287. exec {
  1288. pop
  1289. ( **** Warning: Ignoring a named action pointing out of the document page range.\n)
  1290. pdfformaterror
  1291. } {
  1292. /Page exch 3 -1 roll
  1293. } ifelse
  1294. } if
  1295. } if
  1296. } ifelse
  1297. } ifelse
  1298. } if
  1299. linkdest pop /LNK pdfmark
  1300. } bind def
  1301. end readonly def
  1302. % **** The following procedure should not be changed to allow clients
  1303. % **** to directly interface with the constituent procedures. GSview
  1304. % **** and some Artifex customers rely on the pdfshowpage_init,
  1305. % **** pdfshowpage_setpage, pdfshowpage_finish so all logic should be
  1306. % **** implemented in one of those three procedures.
  1307. /pdfshowpage % <pagedict> pdfshowpage -
  1308. { dup /Page exch store
  1309. pdfshowpage_init
  1310. pdfshowpage_setpage
  1311. pdfshowpage_finish
  1312. } bind def
  1313. /pdfpagecontents % <pagedict> pdfpagecontents <contents>
  1314. { } bind def
  1315. /pdfshowpage_init % <pagedict> pdfshowpage_init <pagedict>
  1316. { /DSCPageCount DSCPageCount 1 add store
  1317. } bind def
  1318. /get_media_box { % <pagedict> get_media_box <box>
  1319. /MediaBox pget not {
  1320. ( **** Page has no /MediaBox attribute. Using the current page size.\n)
  1321. pdfformaterror
  1322. [ 0 0 currentpagedevice /PageSize get aload pop ]
  1323. } if
  1324. } bind def
  1325. /get_any_box { % <pagedict> get_any_box <box name> <box>
  1326. //systemdict /UseTrimBox .knownget dup { and } if {
  1327. dup /TrimBox pget {
  1328. exch pop /TrimBox exch
  1329. } if
  1330. } if
  1331. dup type /arraytype ne {
  1332. //systemdict /UseCropBox .knownget dup { and } if {
  1333. dup /CropBox pget {
  1334. exch pop /CropBox exch
  1335. } if
  1336. } if
  1337. } if
  1338. dup type /arraytype ne {
  1339. /MediaBox exch get_media_box
  1340. } if
  1341. } bind def
  1342. % Compute the matrix that transforms the PDF->PS "default" user space
  1343. /pdf_PDF2PS_matrix { % <pdfpagedict> -- matrix
  1344. matrix currentmatrix matrix setmatrix exch
  1345. % stack: savedCTM <pdfpagedict>
  1346. dup get_any_box
  1347. % stack: savedCTM <pdfpagedict> /Trim|Crop|MediaBox <Trim|Crop|Media Box>
  1348. oforce_elems normrect_elems fix_empty_rect_elems 4 array astore
  1349. //systemdict /PDFFitPage known {
  1350. PDFDEBUG { (Fiting PDF to imageable area of the page.) = flush } if
  1351. currentpagedevice /.HWMargins get aload pop
  1352. currentpagedevice /PageSize get aload pop
  1353. % Adjust PageSize and .HWMargins for the page portrait/landscape orientation
  1354. 2 copy gt
  1355. 7 index aload pop 3 -1 roll sub 3 1 roll exch sub exch
  1356. 10 index /Rotate pget not { 0 } if 90 idiv 1 and 0 ne { exch } if
  1357. gt
  1358. ne {
  1359. 2 copy ne {
  1360. % rotate the .HWMargins
  1361. 2 copy lt {
  1362. 6 2 roll 4 -1 roll 6 -2 roll
  1363. } {
  1364. 6 2 roll 4 1 roll 6 -2 roll
  1365. } ifelse
  1366. % rotate the page dimensions
  1367. exch
  1368. } if
  1369. } if
  1370. 3 -1 roll sub 3 1 roll exch sub exch
  1371. % stack: savedCTM <pdfpagedict> <Crop|Media Box> Xmin Ymin Xmax Ymax
  1372. PDFDEBUG { ( Translate up by [ ) print 3 index =print (, ) print 2 index =print ( ]) = flush } if
  1373. 3 index 3 index translate % move origin up to imageable area
  1374. 2 index sub exch 3 index sub exch 4 2 roll pop pop
  1375. % stack: savedCTM <pdfpagedict> [Box] XImageable YImageable
  1376. 2 index aload pop 2 index sub exch 3 index sub exch 4 2 roll pop pop
  1377. 5 index /Rotate pget not { 0 } if 90 idiv 1 and 0 ne { exch } if
  1378. % stack: savedCTM <pdfpagedict> [Box] XImageable YImageable XBox YBox
  1379. 3 -1 roll exch div 3 1 roll div .min
  1380. PDFDEBUG { ( Scale by ) print dup = flush } if
  1381. } {
  1382. //systemdict /NoUserUnit .knownget not { false } if {
  1383. 1
  1384. } {
  1385. 1 index /UserUnit knownoget {
  1386. PDFDEBUG { (Scaling due to UserUnit by ) print dup = flush } if
  1387. } {
  1388. 1
  1389. } ifelse
  1390. } ifelse
  1391. } ifelse
  1392. % stack: savedCTM <pdfpagedict> [Box] scale
  1393. dup scale
  1394. % Rotate according to /Rotate
  1395. aload pop boxrect
  1396. {
  1397. { pop pop }
  1398. { -90 rotate pop neg 0 translate }
  1399. { 180 rotate neg exch neg exch translate }
  1400. { 90 rotate neg 0 exch translate pop }
  1401. }
  1402. 5 index /Rotate pget not { 0 } if
  1403. PDFDEBUG { dup 0 ne { (Rotating by ) print dup =print ( degrees.) = flush } if } if
  1404. 90 idiv 3 and get exec
  1405. % Now translate to the origin given in the Crop|Media Box
  1406. exch neg exch neg translate
  1407. % stack: savedCTM <pdfpagedict>
  1408. pop
  1409. matrix currentmatrix exch setmatrix
  1410. } bind def
  1411. % Cache the matrix that transforms the PDF->PS "default" user space
  1412. % into <pdfpagedict> under the key //PDF2PS_matrix_key, then return it
  1413. /PDF2PS_matrix_key (PDF->PS matrix) cvn def
  1414. /pdf_cached_PDF2PS_matrix { % <pdfpagedict> -- <PDF2PS_matrix>
  1415. dup //PDF2PS_matrix_key .knownget {
  1416. exch pop
  1417. } {
  1418. dup dup pdf_PDF2PS_matrix //PDF2PS_matrix_key exch put
  1419. //PDF2PS_matrix_key get
  1420. } ifelse
  1421. } bind def
  1422. currentdict /PDF2PS_matrix_key undef
  1423. /.pdfshowpage_Install { % <pagedict> [<prevproc>] .pdfshowpage_Install -
  1424. 0 get exec
  1425. pdf_cached_PDF2PS_matrix concat
  1426. } bind def
  1427. /pdfshowpage_setpage { % <pagedict> pdfshowpage_setpage <pagedict>
  1428. 6 dict begin % for setpagedevice
  1429. % Stack: pdfpagedict
  1430. % UseCIEColor is always true for PDF; see the comment in runpdf above
  1431. /UseCIEColor true def
  1432. /Orientation 0 def
  1433. currentpagedevice
  1434. % Stack: pdfpagedict currentpagedevicedict
  1435. 1 index get_any_box
  1436. % Stack: pdfpagedict currentpagedevicedict /BoxName [box]
  1437. oforce_elems normrect_elems fix_empty_rect_elems boxrect 4 2 roll pop pop
  1438. 3 index /Rotate pget not { 0 } if 90 idiv 1 and 0 ne { exch } if
  1439. % stack: pdfpagedict currentpagedevicedict boxwidth boxheight
  1440. //systemdict /PDFFitPage known {
  1441. % Preserve page size,
  1442. % but choose portrait/landscape depending on box width:height ratio
  1443. % (if box width == height, select portrait orientation)
  1444. gt
  1445. 1 index /PageSize get aload pop
  1446. 2 copy gt
  1447. 4 -1 roll ne { exch } if
  1448. } {
  1449. % Set the page size.
  1450. //systemdict /NoUserUnit .knownget not { false } if not {
  1451. 3 index /UserUnit knownoget {
  1452. dup 4 -1 roll mul 3 1 roll mul
  1453. } if
  1454. } if
  1455. } ifelse
  1456. 2 array astore /PageSize exch def
  1457. % Determine the number of spot colors used on the page. Note: This searches
  1458. % the pages resources. It may be high if a spot color is in a resource but
  1459. % is not actually used on the page.
  1460. /PageSpotColors 2 index countspotcolors def
  1461. % Let the device know if we will be using PDF 1.4 transparency.
  1462. % The clist logic may need to adjust the size of bands.
  1463. 1 index pageusestransparency /PageUsesTransparency exch def
  1464. dup /Install .knownget {
  1465. % Don't let the Install procedure get more deeply
  1466. % nested after every page.
  1467. dup type dup /arraytype eq exch /packedarraytype eq or {
  1468. dup length 4 eq {
  1469. dup 2 get /.pdfshowpage_Install load eq {
  1470. 1 get 0 get % previous procedure
  1471. } if
  1472. } if
  1473. } if
  1474. } {
  1475. { }
  1476. } ifelse 1 array astore
  1477. 2 index exch /.pdfshowpage_Install load /exec load
  1478. 4 packedarray cvx
  1479. % Stack: pagedict currentpagedict installproc
  1480. /Install exch def
  1481. % Stack: pagedict currentpagedict
  1482. pop currentdict end setpagedevice
  1483. } bind def
  1484. /.free_page_resources { % - .free_page_resources -
  1485. Page /Resources pget {
  1486. /Shading knownoget {
  1487. { {
  1488. dup type /dicttype eq {
  1489. dup /.shading_dict known {
  1490. dup /.shading_dict undef
  1491. } if
  1492. } if
  1493. pop pop
  1494. } forall
  1495. } big-res-forall
  1496. } if
  1497. } if
  1498. } bind def
  1499. /pdfshowpage_finish { % <pagedict> pdfshowpage_finish -
  1500. save /PDFSave exch store
  1501. /PDFdictstackcount countdictstack store
  1502. (before exec) VMDEBUG
  1503. % set up color space substitution (this must be inside the page save)
  1504. pdfshowpage_setcspacesub
  1505. .writepdfmarks {
  1506. % Copy the crop box.
  1507. dup /CropBox pget {
  1508. % .pdfshowpage_Install transforms the user space -
  1509. % do same here with the CropBox.
  1510. oforce_elems
  1511. 2 { Page pdf_cached_PDF2PS_matrix transform 4 2 roll } repeat
  1512. normrect_elems /CropBox 5 1 roll fix_empty_rect_elems 4 array astore
  1513. mark /CropBox 3 -1 roll
  1514. /PAGE pdfmark
  1515. } if
  1516. % Copy annotations and links.
  1517. dup /Annots knownoget {
  1518. 0 1 2 index length 1 sub
  1519. { 1 index exch oget
  1520. dup type /dicttype eq {
  1521. dup /Subtype oget annottypes exch .knownget { exec } { pop } ifelse
  1522. } {
  1523. pop
  1524. } ifelse
  1525. }
  1526. for pop
  1527. } if
  1528. } if % end .writepdfmarks
  1529. % Display the actual page contents.
  1530. 8 dict begin
  1531. /BXlevel 0 def
  1532. /BMClevel 0 def
  1533. /OFFlevels 0 dict def
  1534. /BGDefault currentblackgeneration def
  1535. /UCRDefault currentundercolorremoval def
  1536. %****** DOESN'T HANDLE COLOR TRANSFER YET ******
  1537. /TRDefault currenttransfer def
  1538. matrix currentmatrix 2 dict
  1539. 2 index /CropBox pget {
  1540. oforce_elems normrect_elems boxrect
  1541. 4 array astore 1 index /ClipRect 3 -1 roll put
  1542. } if
  1543. dictbeginpage setmatrix
  1544. /DefaultQstate qstate store
  1545. count 1 sub /pdfemptycount exch store
  1546. % If the page uses any transparency features, show it within
  1547. % a transparency group.
  1548. dup pageusestransparency dup /PDFusingtransparency exch def {
  1549. % Show the page within a PDF 1.4 device filter.
  1550. 0 .pushpdf14devicefilter {
  1551. /DefaultQstate qstate store % device has changed -- reset DefaultQstate
  1552. % If the page has a Group, enclose contents in transparency group.
  1553. % (Adobe Tech Note 5407, sec 9.2)
  1554. dup /Group knownoget {
  1555. 1 index /CropBox pget {
  1556. /CropBox exch
  1557. } {
  1558. 1 index get_media_box /MediaBox exch
  1559. } ifelse
  1560. oforce_elems normrect_elems fix_empty_rect_elems 4 array astore .beginformgroup {
  1561. showpagecontents
  1562. } stopped {
  1563. .discardtransparencygroup stop
  1564. } if .endtransparencygroup
  1565. } {
  1566. showpagecontents
  1567. } ifelse
  1568. } stopped {
  1569. % todo: discard
  1570. .poppdf14devicefilter
  1571. /DefaultQstate qstate store % device has changed -- reset DefaultQstate
  1572. stop
  1573. } if .poppdf14devicefilter
  1574. /DefaultQstate qstate store % device has changed -- reset DefaultQstate
  1575. } {
  1576. showpagecontents
  1577. } ifelse
  1578. .free_page_resources
  1579. % todo: mixing drawing ops outside the device filter could cause
  1580. % problems, for example with the pnga device.
  1581. endpage
  1582. end % scratch dict
  1583. % Indicate that the number of spot colors is unknown in case the next page
  1584. % imaged is a PS file.
  1585. << /PageSpotColors -1 >> .setpagedevice
  1586. % Some PDF files don't have matching q/Q (gsave/grestore) so we need
  1587. % to clean up any left over dicts from the dictstack
  1588. countdictstack PDFdictstackcount sub dup 0 ne {
  1589. ( **** Warning: File has unbalanced q/Q operators \(too many q's\)\n)
  1590. pdfformaterror
  1591. { end } repeat
  1592. } {
  1593. pop
  1594. } ifelse
  1595. (after exec) VMDEBUG
  1596. Repaired % pass Repaired state around the restore
  1597. PDFSave restore
  1598. /Repaired exch def
  1599. } bind def
  1600. % Display the contents of a page (including annotations).
  1601. /showpagecontents { % <pagedict> showpagecontents -
  1602. dup % Save the pagedict for the Annotations
  1603. count 1 sub /pdfemptycount exch store
  1604. gsave % preserve gstate for Annotations later
  1605. /Contents knownoget not { 0 array } if
  1606. dup type /arraytype ne { 1 array astore } if {
  1607. oforce false resolvestream pdfopdict .pdfrun
  1608. } forall
  1609. % check for extra garbage on the ostack and clean it up
  1610. count pdfemptycount sub dup 0 ne {
  1611. ( **** File did not complete the page properly and may be damaged.\n)
  1612. pdfformaterror
  1613. { pop } repeat
  1614. } {
  1615. pop
  1616. } ifelse
  1617. grestore
  1618. % Draw the annotations
  1619. //systemdict /ShowAnnots .knownget not { //true } if {
  1620. /Annots knownoget {
  1621. { oforce
  1622. dup //null ne {
  1623. drawannot
  1624. } {
  1625. pop
  1626. } ifelse
  1627. } forall
  1628. } if
  1629. } if
  1630. //systemdict /ShowAcroForm .knownget { //true eq } { //false } ifelse {
  1631. Trailer /Root oget /AcroForm knownoget { draw_acro_form } if
  1632. } if
  1633. } bind def
  1634. /processcolorspace { % - processcolorspace <colorspace>
  1635. % The following is per the PLRM3.
  1636. currentdevice 1 dict dup /ProcessColorModel dup put .getdeviceparams
  1637. exch pop exch pop
  1638. dup type /nametype ne { cvn } if
  1639. dup { setcolorspace } .internalstopped { pop /DeviceRGB } if
  1640. } bind def
  1641. % ------ Transparency support ------ %
  1642. % Define minimum PDF version for checking for transparency features.
  1643. % Transparency is a 1.4 feature however we have seen files that claimed
  1644. % to be PDF 1.2 with transparency features. Bug 689288.
  1645. /PDFtransparencyversion 1.2 def
  1646. % Determine whether a page might invoke any transparency features:
  1647. % - Non-default BM, ca, CA, or SMask in an ExtGState
  1648. % - Image XObject with SMask
  1649. % Note: we deliberately don't check to see whether a Group is defined,
  1650. % because Adobe Illustrator 10 (and possibly other applications) define
  1651. % a page-level group whether transparency is actually used or not.
  1652. % Ignoring the presence of Group is justified because, in the absence
  1653. % of any other transparency features, they have no effect.
  1654. /pageusestransparency { % <pagedict> pageusestransparency <bool>
  1655. PDFversion PDFtransparencyversion lt NOTRANSPARENCY or {
  1656. pop //false
  1657. } {
  1658. dup //false exch {
  1659. 4 dict 1 index resourceusestransparency { pop not exit } if
  1660. /Parent knownoget not { exit } if
  1661. } loop
  1662. % Also check for transparency in the annotation (if not in resources).
  1663. { pop //true } { annotsusetransparency } ifelse
  1664. } ifelse
  1665. } bind def
  1666. % Check if transparency is specified in an ExtGState dict
  1667. /extgstateusestransparency { % <gstate dict> extgstateusestransparency <bool>
  1668. //false exch % Assume no transparency
  1669. { % establish loop context
  1670. dup /BM knownoget { dup /Normal ne exch /Compatible ne and
  1671. { pop not exit } if
  1672. } if
  1673. dup /ca knownoget { 1 ne { pop not exit } if } if
  1674. dup /CA knownoget { 1 ne { pop not exit } if } if
  1675. dup /SMask knownoget { /None ne { pop not exit } if } if
  1676. pop exit
  1677. } loop
  1678. } bind def
  1679. % Check if transparency is used in a Pattern
  1680. /patternusestransparency { % <Pattern dict> patternusestransparency <bool>
  1681. NOTRANSPARENCY
  1682. { pop //false }
  1683. { //false exch % Assume no transparency
  1684. {
  1685. 4 dict 1 index resourceusestransparency { pop not exit } if
  1686. dup /ExtGState knownoget { extgstateusestransparency { pop not exit } if } if
  1687. pop exit
  1688. } loop
  1689. }
  1690. ifelse
  1691. } bind def
  1692. % Check the Resources of a page or Form. Check for loops in the resource chain.
  1693. /resourceusestransparency { % <dict> <dict> resourceusestransparency <bool>
  1694. { % Use loop to provide an exitable context.
  1695. /Resources knownoget not { 0 dict } if
  1696. 2 copy .knownget {
  1697. { % Some circular references may be missed because scanning stops
  1698. % when the 1st transparency is found.
  1699. ( **** File has circular references in resource dictionaries.\n)
  1700. pdfformaterror
  1701. } if
  1702. pop //false exit
  1703. } if
  1704. 2 copy //true put % In the current chain.
  1705. dup /ExtGState knownoget {
  1706. //false exch
  1707. { { exch pop oforce extgstateusestransparency { pop //true exit } if
  1708. } forall
  1709. dup { exit } if
  1710. } big-res-forall
  1711. { pop //true exit } if
  1712. } if
  1713. dup /Pattern knownoget {
  1714. //false exch
  1715. { { exch pop oforce patternusestransparency { pop //true exit } if
  1716. } forall
  1717. dup { exit } if
  1718. } big-res-forall
  1719. { pop //true exit } if
  1720. } if
  1721. dup /XObject knownoget {
  1722. dup type dup /dicttype eq exch /arraytype eq or {
  1723. //false exch
  1724. { {
  1725. exch pop oforce dup /Subtype get
  1726. dup /Image eq { 1 index /SMask known { pop pop not exit } if } if
  1727. /Form eq {
  1728. 3 index exch resourceusestransparency { not exit } if
  1729. } {
  1730. pop
  1731. } ifelse
  1732. } forall
  1733. dup { exit } if
  1734. } big-res-forall
  1735. { pop //true exit } if
  1736. } {
  1737. ( **** Ignoring non-dictionary /XObject attribute.\n)
  1738. pdfformaterror
  1739. pop
  1740. } ifelse
  1741. } if
  1742. 2 copy //false put % Visited but not in the current chain.
  1743. pop //false exit
  1744. } loop
  1745. exch pop
  1746. } bind def
  1747. % Check if the annotations on a page use transparency
  1748. /annotsusetransparency { % <page dict> annotsusetransparency <bool>
  1749. //false exch % Assume no transparency
  1750. /Annots knownoget { % Get Annots array
  1751. {
  1752. oforce
  1753. dup //null ne {
  1754. /AP knownoget { % Get appearance dict for the annoation
  1755. /N knownogetdict { % Get the /N (i.e. normal) appearance stream
  1756. 4 dict exch resourceusestransparency { pop //true exit } if
  1757. } if
  1758. } if % If AP dict known
  1759. } {
  1760. pop
  1761. } ifelse
  1762. } forall % For all annots on the page
  1763. } if
  1764. } bind def
  1765. % Add a color name to our spot color list. Ignore /All and /None
  1766. /putspotcolor { % <name> <spotcolordict> putspotcolor -
  1767. % The 'name' could be a string. If so then convert to a name.
  1768. exch dup type /stringtype eq { cvn } if
  1769. dup dup /None eq exch /All eq or { pop pop } { 0 put } ifelse
  1770. } bind def
  1771. % Determine which spot colors are used within a color space Note: This
  1772. % dict will include all colors used in Separation or DeviceN color spaces.
  1773. % Thus it may include Cyan, Magenta, Yellow, and Black.
  1774. % <colorspace> <spotcolordict> colorspacespotcolors -
  1775. /colorspacespotcolors {
  1776. exch dup type /arraytype eq {
  1777. % If we have an Indexed color space then get the base space.
  1778. dup 0 oget dup /Indexed eq {
  1779. pop 1 oget 2 copy colorspacespotcolors
  1780. } {
  1781. % Stack: <spotcolordict> <colorspace> <colorspacetype>
  1782. dup /Separation eq exch /DeviceN eq or {
  1783. dup 1 oget dup type /arraytype eq {
  1784. { oforce 2 index putspotcolor } forall
  1785. } {
  1786. 2 index putspotcolor
  1787. } ifelse
  1788. } if
  1789. } ifelse
  1790. } if
  1791. pop pop
  1792. } bind def
  1793. % Enumerate resource dictionary or an array of dictionaries
  1794. % <object> <proc> big-res-forall -
  1795. /big-res-forall {
  1796. 1 index type /dicttype eq { 0 get } if
  1797. forall
  1798. } bind def
  1799. % Check the Resources of a page, form, or annotation. Determine which spot
  1800. % colors are used within the resource Note: The spot color dict will include
  1801. % all colors used in Separation or DeviceN color spaces. Thus it may include
  1802. % Cyan, Magenta, Yellow, and Black. We also pass a dict that is used to check
  1803. % for loops in the resource list.
  1804. % <spotcolordict> <loopdict> <page/form/annot dict>
  1805. % resourcespotcolors <spotcolordict> <loopdict>
  1806. /resourcespotcolors {
  1807. { % Use loop to provide an exitable context.
  1808. % Exit if no Resources entry
  1809. /Resources knownoget not { exit } if
  1810. % Exit if we have already seen this dict
  1811. 2 copy known { pop exit } if
  1812. % Save the Resources dict into our loop checking dict.
  1813. 2 copy 0 put
  1814. % Scan resources that might contain a color space.
  1815. dup /ColorSpace knownoget {
  1816. { { exch pop oforce 3 index colorspacespotcolors } forall } big-res-forall
  1817. } if
  1818. dup /Pattern knownoget {
  1819. { { exch pop oforce 4 copy exch pop resourcespotcolors pop pop pop } forall } big-res-forall
  1820. } if
  1821. dup /Shading knownoget {
  1822. { { exch pop oforce /ColorSpace oget 3 index colorspacespotcolors } forall } big-res-forall
  1823. } if
  1824. /XObject knownoget {
  1825. dup type dup /dicttype eq exch /arraytype eq or {
  1826. { { exch pop oforce dup
  1827. /Subtype get /Form eq { resourcespotcolors } { pop } ifelse
  1828. } forall
  1829. } big-res-forall
  1830. } {
  1831. pop % Just ignore here, already reported by resourceusestransparency.
  1832. } ifelse
  1833. } if
  1834. exit
  1835. } loop
  1836. } bind def
  1837. % Determine which spot colors are used within the annotations. Note: This
  1838. % dict will include all colors used in Separation or DeviceN color spaces.
  1839. % Thus it may include Cyan, Magenta, Yellow, and Black.
  1840. % <spotcolordict> <loopdict> <annotsarray>
  1841. % annotsspotcolors <spotcolordict> <loopdict>
  1842. /annotsspotcolors {
  1843. { oforce
  1844. dup //null ne {
  1845. /AP knownoget { % Get appearance dict for the annoation
  1846. /N knownogetdict { % Get the /N (i.e. normal) appearance stream
  1847. resourcespotcolors
  1848. } if % If normal appearance streamknown
  1849. } if % If AP dict known
  1850. } {
  1851. pop
  1852. } ifelse
  1853. } forall
  1854. } bind def
  1855. % Determine spot colors are used within a page. We are creating a dict to
  1856. % hold the spot color names as keys. Using a dict avoids having to worry
  1857. % about duplicate entries. The keys in the dict contain the spot color
  1858. % names. However the values have no meaning. Note: This dict will include
  1859. % all colors used in Separation or DeviceN color spaces specified in the
  1860. % page's resources. Thus it may include Cyan, Magenta, Yellow, and Black.
  1861. % There is no attempt to verify that these color spaces are actually used
  1862. % within the object streams for the page.
  1863. /pagespotcolors { % <pagedict> pagespotcolors <spotcolordict>
  1864. dup
  1865. % Create a dict to hold spot color names.
  1866. 0 dict exch
  1867. % Create a dict to be used to check for reference loops.
  1868. 4 dict exch
  1869. % Check for color spaces in the Resources
  1870. resourcespotcolors
  1871. % Also check for color spaces in the annotations.
  1872. 3 -1 roll
  1873. /Annots knownoget { annotsspotcolors } if
  1874. pop % Discard reference loop dict
  1875. } bind def
  1876. % Determine how many (if any) spot colors are used by a page.
  1877. % Note: This count does not include Cyan, Magenta, Yellow, or Black
  1878. /countspotcolors { % <pagedict> countspotcolors <count>
  1879. pagespotcolors % Get dict with all spot colors
  1880. dup length % spot color dict length
  1881. % Remove CMYK from the spot color count.
  1882. [ /Cyan /Magenta /Yellow /Black ]
  1883. { 2 index exch known { 1 sub } if } forall
  1884. exch pop % Remove spot color dict
  1885. } bind def
  1886. % ------ ColorSpace substitution support ------ %
  1887. %
  1888. % <pagedict> pdfshowpage_setcspacesub <pagedict>
  1889. %
  1890. % Set up color space substitution for a page. Invocations of this procedure
  1891. % must be bracketed by the save/restore operation for the page, to avoid
  1892. % unintended effects on other pages.
  1893. %
  1894. % If any color space substitution is used, and the current color space is a
  1895. % device dependent color space, make sure the current color space is updated.
  1896. % There is an optimization in the setcolorspace pseudo-operator that does
  1897. % nothing if both the current and operand color spaces are the same. For
  1898. % PostScript this optimization is disabled if the UseCIEColor page device
  1899. % parameter is true. This is not the case for PDF, as performance suffers
  1900. % significantly on some PDF files if color spaces are set repeatedly. Hence,
  1901. % if color space substitution is to be used, and the current color space
  1902. % is a device dependent color space, we must make sure to "transition" the
  1903. % current color space.
  1904. %
  1905. /pdfshowpage_setcspacesub
  1906. {
  1907. false
  1908. { /DefaultGray /DefaultRGB /DefaultCMYK }
  1909. {
  1910. dup 3 index /ColorSpace //rget exec
  1911. { resolvecolorspace /ColorSpace defineresource pop }
  1912. { pop }
  1913. ifelse
  1914. }
  1915. forall
  1916. % if using color space substitution, "transition" the current color space
  1917. {
  1918. currentcolorspace dup length 1 eq % always an array
  1919. {
  1920. 0 get
  1921. dup /DeviceGray eq 1 index /DeviceRGB eq or 1 index /DeviceCMYK or
  1922. { /Pattern setcolorspace setcolorspace }
  1923. { pop }
  1924. ifelse
  1925. }
  1926. { pop }
  1927. if
  1928. }
  1929. if
  1930. }
  1931. bind def
  1932. % Write OutputIntents to device if the device handles it
  1933. /writeoutputintents {
  1934. currentdevice 1 dict dup /OutputIntent //null put readonly
  1935. .getdeviceparams
  1936. mark ne { pop pop
  1937. % device supports OutputIntent parameter
  1938. Trailer /Root oget /OutputIntents knownoget {
  1939. dup type /arraytype eq {
  1940. { % process all output profiles present
  1941. oforce
  1942. dup length dict .copydict
  1943. dup /DestOutputProfile knownoget {
  1944. PDFfile fileposition exch
  1945. mark exch { oforce } forall .dicttomark
  1946. //true resolvestream
  1947. [ { counttomark 1 add index
  1948. 64000 string readstring
  1949. not { exit } if
  1950. } loop
  1951. ] exch closefile
  1952. 0 1 index { length add } forall .bytestring
  1953. 0 3 2 roll {
  1954. 3 copy putinterval
  1955. length add
  1956. } forall pop
  1957. exch PDFfile exch setfileposition
  1958. 1 index /DestOutputProfile 3 2 roll put
  1959. } if
  1960. % Convert to string array because it's easier for the device
  1961. [ 1 index /OutputCondition knownoget not { () } if
  1962. 2 index /OutputConditionIdentifier knownoget not { () } if
  1963. 3 index /RegistryName knownoget not { () } if
  1964. 4 index /Info knownoget not { () } if
  1965. 5 index /DestOutputProfile knownoget not { () } if
  1966. ]
  1967. [ /OutputIntent 3 2 roll .pdfputparams pop pop
  1968. pop % done with this OutputIntent dictionary
  1969. } forall
  1970. } {
  1971. pop
  1972. ( **** Warning: OutputIntent attribute of a wrong type is ignored.\n)
  1973. pdfformaterror
  1974. } ifelse
  1975. } if % OutputIntents known
  1976. % tell device there are no more OutputIntents
  1977. [ /OutputIntent [ ] .pdfputparams pop pop
  1978. } if
  1979. } bind def
  1980. end % pdfdict
  1981. .setglobal