1
0

pdf_main.ps 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787
  1. % Copyright (C) 1994, 2000 Aladdin Enterprises. All rights reserved.
  2. %
  3. % This file is part of AFPL Ghostscript.
  4. %
  5. % AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author or
  6. % distributor accepts any responsibility for the consequences of using it, or
  7. % for whether it serves any particular purpose or works at all, unless he or
  8. % she says so in writing. Refer to the Aladdin Free Public License (the
  9. % "License") for full details.
  10. %
  11. % Every copy of AFPL Ghostscript must include a copy of the License, normally
  12. % in a plain ASCII text file named PUBLIC. The License grants you the right
  13. % to copy, modify and redistribute AFPL Ghostscript, but only under certain
  14. % conditions described in the License. Among other things, the License
  15. % requires that the copyright notice and this notice be preserved on all
  16. % copies.
  17. % $Id: pdf_main.ps,v 1.35 2001/10/12 07:07:54 rayjj Exp $
  18. % pdf_main.ps
  19. % PDF file- and page-level operations.
  20. /.setlanguagelevel where { pop 2 .setlanguagelevel } if
  21. .currentglobal true .setglobal
  22. /pdfdict where { pop } { /pdfdict 100 dict def } ifelse
  23. pdfdict begin
  24. % Patch in an obsolete variable used by some third-party software.
  25. /#? false def
  26. % Test whether the current output device handles pdfmark.
  27. /.writepdfmarkdict 1 dict dup /pdfmark null put readonly def
  28. /.writepdfmarks { % - .writepdfmarks <bool>
  29. currentdevice //.writepdfmarkdict .getdeviceparams
  30. mark eq { false } { pop pop true } ifelse
  31. systemdict /DOPDFMARKS known or
  32. } bind def
  33. % For simplicity, we use a single interpretation dictionary for all
  34. % PDF graphics execution, even though this is too liberal.
  35. /pdfopdict mark
  36. objopdict { } forall
  37. drawopdict { } forall
  38. /endstream { exit } bind
  39. (%%EOF) cvn { exit } bind % for filters
  40. % PDF 1.1 operators
  41. /BX { /BXlevel BXlevel 1 add store } bind
  42. /EX { /BXlevel BXlevel 1 sub store } bind
  43. /PS { cvx exec } bind
  44. % PDF 1.2 operators
  45. /BMC { pop } bind
  46. /BDC { pop pop } bind
  47. /EMC { }
  48. /MP { pop } bind
  49. /DP { pop pop } bind
  50. .dicttomark readonly def
  51. % ======================== Main program ======================== %
  52. end % pdfdict
  53. userdict begin
  54. /defaultfontname /Times-Roman def
  55. % Make sure the registered encodings are loaded, so we don't run the risk
  56. % that some of the indices for their names will overflow the packed
  57. % representation. (Yes, this is a hack.)
  58. SymbolEncoding pop
  59. DingbatsEncoding pop
  60. % Redefine 'run' so it recognizes PDF files.
  61. systemdict begin
  62. /.runps /run load def
  63. /runpdfstring 50 string def % length is arbitrary
  64. /run {
  65. dup type /filetype ne { (r) file } if
  66. dup ( ) .peekstring {
  67. (%) eq {
  68. dup ( ) .peekstring {
  69. (%P) eq {
  70. dup //runpdfstring {
  71. % Some invalid files might have extra-long first lines....
  72. { readline } .internalstopped not { pop pop exit } if
  73. pop =string
  74. } loop
  75. //runpdfstring (%PDF-) anchorsearch {
  76. pop pop runpdf
  77. } {
  78. pop cvx .runexec
  79. } ifelse
  80. } {
  81. cvx .runps
  82. } ifelse
  83. } {
  84. closefile
  85. } ifelse
  86. } {
  87. cvx .runps
  88. } ifelse
  89. } {
  90. closefile
  91. } ifelse
  92. } bind odef
  93. currentdict /runpdfstring .undef
  94. /runpdf % <file> runpdf -
  95. { userdict begin
  96. /Page# null def
  97. /Page null def
  98. /DSCPageCount 0 def
  99. /PDFSave null def
  100. GS_PDF_ProcSet begin
  101. pdfdict begin
  102. pdfopen begin
  103. Trailer /Root oget /Pages oget /CropBox knownoget
  104. { mark /CropBox 3 -1 roll /PAGES pdfmark
  105. }
  106. if
  107. /FirstPage where
  108. { pop FirstPage dup pdfpagecount gt
  109. { (\nRequested FirstPage is greater than the number of pages in the file: ) print
  110. pdfpagecount = flush
  111. } if
  112. } {
  113. 1
  114. } ifelse
  115. 1
  116. /LastPage where { pop LastPage pdfpagecount .min } { pdfpagecount } ifelse
  117. 2 index 1 index gt
  118. { ( No pages will be processed \(FirstPage > LastPage\).) = flush }
  119. { QUIET not
  120. { (Processing pages ) print 2 index =only ( through ) print dup =only
  121. (.) = flush
  122. }
  123. if
  124. }
  125. ifelse
  126. { dup /Page# exch store
  127. QUIET not { (Page ) print dup == flush } if
  128. pdfgetpage pdfshowpage
  129. } for
  130. currentdict pdfclose
  131. end % temporary dict
  132. end % pdfdict
  133. end % userdict
  134. } bind def
  135. end % systemdict
  136. % Redefine the procedure that the C code uses for running piped input.
  137. % It is OK to use { (%stdin) run } here, because a startjob cannot occur.
  138. /.runstdin {
  139. { (%stdin) run } execute0
  140. } bind def
  141. end % userdict
  142. pdfdict begin
  143. % ======================== File parsing ======================== %
  144. % Read the cross-reference and trailer sections.
  145. /traileropdict mark
  146. (<<) cvn { mark } bind
  147. (>>) cvn /.dicttomark load
  148. ([) cvn { mark } bind % ditto
  149. (]) cvn dup load
  150. % /true true % see .pdfexectoken in pdf_base.ps
  151. % /false false % ibid.
  152. % /null null % ibid.
  153. /R { /resolveR cvx 3 packedarray cvx } bind % see Objects below
  154. /startxref /exit load
  155. .dicttomark readonly def
  156. % Because of EOL conversion, lines with fixed contents might be followed
  157. % by one or more blanks.
  158. /lineeq % <filestr> <conststr> lineeq <bool>
  159. { anchorsearch
  160. { pop { ( ) anchorsearch not { () eq exit } if pop } loop }
  161. { pop false }
  162. ifelse
  163. } bind def
  164. /linene { lineeq not } bind def
  165. % Read (mostly scan) the cross-reference table.
  166. /readxref % <pos> readxref <trailerdict>
  167. { PDFoffset add PDFfile exch setfileposition
  168. % In some PDF files, this position actually points to
  169. % white space before the xref line. Skip over this here.
  170. { PDFfile fileposition PDFfile read pop 32 gt { exit } if pop
  171. } loop
  172. PDFfile exch setfileposition
  173. % The PDF specification says that the 'xref' must be on a line
  174. % by itself. The code here formerly used readline and linene to
  175. % check this. However, Acrobat Reader only requires the line to
  176. % begin with 'xref', and there are enough applications producing
  177. % non-compliant PDF files that we have to do this too.
  178. PDFfile pdfstring 0 4 getinterval readstring pop
  179. (xref) ne { /readxref cvx /syntaxerror signalerror } if
  180. % Store the xref table entry position for each object.
  181. % We only need to read the run headers, not every entry.
  182. { PDFfile token pop % first object # or trailer
  183. dup /trailer eq { pop exit } if
  184. PDFfile pdfstring readline pop
  185. token pop % entry count
  186. exch pop exch
  187. % This section might be adding new objects:
  188. % ensure that Objects and Generations are big enough.
  189. % Stack: count obj#
  190. 2 copy add growPDFobjects
  191. PDFfile fileposition 3 -1 roll
  192. { Objects 2 index lget null eq % later update might have set it
  193. { Objects 2 index 2 index cvx lput }
  194. if exch 1 add exch 20 add
  195. }
  196. repeat PDFfile exch setfileposition pop
  197. } loop
  198. count /pdfemptycount exch def
  199. PDFfile traileropdict .pdfrun
  200. } bind def
  201. % Open a PDF file and read the header, trailer, and cross-reference.
  202. /pdfopen { % <file> pdfopen <dict>
  203. pdfopenfile begin
  204. pdfopencache
  205. .writepdfmarks {
  206. % Copy bookmarks (outline) to the output.
  207. Trailer /Root oget /Outlines knownoget {
  208. /First knownoget {
  209. { dup writeoutline /Next knownoget not { exit } if } loop
  210. } if
  211. } if
  212. } if % end .writepdfmarks
  213. currentdict end
  214. } bind def
  215. /pdfopencache { % - pdfopencache -
  216. % Create and initialize some caches.
  217. /PageCount pdfpagecount def
  218. /PageNumbers PageCount 65534 min dict def
  219. /PageIndex PageCount 65534 min array def
  220. } bind def
  221. /pdfopenfile { % <file> pdfopenfile <dict>
  222. pdfdict readonly pop % can't do it any earlier than this
  223. 15 dict begin
  224. /LocalResources 0 dict def
  225. /DefaultMatrix null def % establish binding
  226. /Printed where { pop } {
  227. % Guess whether the output device is a printer.
  228. /Printed currentpagedevice /OutputFile known def
  229. } ifelse
  230. /PSLevel1 where { pop } { /PSLevel1 false def } ifelse
  231. cvlit /PDFfile exch def
  232. /PDFsource PDFfile def
  233. /Repaired false def
  234. PDFfile dup 0 setfileposition pdfstring readstring
  235. not {/pdfopen cvx /syntaxerror signalerror} if
  236. (%PDF-) search not {/pdfopen cvx /syntaxerror signalerror} if
  237. length /PDFoffset exch def pop cvr /PDFversion exch def
  238. findxref
  239. initPDFobjects
  240. % Read the last cross-reference table.
  241. readxref /Trailer exch def
  242. Trailer /Encrypt known
  243. { pdf_process_Encrypt % signal error
  244. }
  245. if
  246. % Read any previous cross-reference tables.
  247. Trailer { /Prev .knownget not { exit } if readxref } loop
  248. Repaired { printrepaired } if
  249. currentdict end
  250. } bind def
  251. % Skip backward over the %%EOF at the end of the PDF file, and read
  252. % the preceding startxref line. The PDF specification unambiguously
  253. % requires that the %%EOF appear on a line by itself, and that the
  254. % startxref and the following position value appear on separate lines;
  255. % however, some applications (including, apparently, Acrobat Distiller
  256. % on the Macintosh) may add up to 2K of garbage after the %%EOF, and some
  257. % other applications also truncate the %%EOF to %%EO, and/or put the
  258. % startxref and the following value on the same line.
  259. % A file reported from Distiller 3.02b for AIX 4.1.1 has 2076 bytes
  260. % of garbage. The tolerance is increased to 4K to cover future
  261. % applications and bigger allocation units.
  262. /findxref { % - findxref <xrefpos>
  263. PDFfile dup dup 0 setfileposition bytesavailable
  264. dup /PDFfilelen exch def
  265. % Find the last %%EOF string (within 4096 bytes)
  266. 4096 sub PDFoffset .max
  267. 2 copy setfileposition
  268. PDFfilelen exch sub string 1 index exch readstring pop {
  269. (\015%%EO) search { % Adobe can handle truncated key string
  270. pop pop % if found, keep searching 'post' string
  271. } {
  272. (\012%%EO) search
  273. { pop pop } { exit } ifelse % exit if neither string found
  274. } ifelse
  275. } loop
  276. PDFfilelen exch length sub 4 sub PDFoffset .max exch 1 index setfileposition
  277. % Stack: eofpos
  278. % Check for whether this is, in fact, a valid PDF file.
  279. dup PDFfilelen exch sub dup dup 7 gt exch 6 lt or {
  280. pop true
  281. } {
  282. string PDFfile exch readstring pop
  283. dup (%%EOF\n) eq exch dup (%%EOF\r) eq
  284. exch (%%EOF\r\n) eq or or not
  285. } ifelse {
  286. (
  287. **** This file has a corrupted %%EOF marker, or garbage after the %%EOF.
  288. ) pdfformaterror
  289. } if
  290. PDFfile exch setfileposition
  291. % Now read the startxref and xref start position.
  292. prevline token not { null } if dup type /integertype eq {
  293. exch pop cvi % xref start position
  294. exch PDFfile exch setfileposition
  295. prevline (startxref) linene { /findxref cvx /syntaxerror signalerror } if
  296. pop
  297. } { % else, this file has 'startxref #####' format
  298. (startxref) ne { /findxref cvx /syntaxerror signalerror } if
  299. cvi % xref start position
  300. (
  301. **** The format of the startxref line in this file is invalid.
  302. ) pdfformaterror
  303. exch PDFfile exch setfileposition
  304. } ifelse
  305. } bind def
  306. /stderrfile (%stderr) (w) file def
  307. /stderrprint { % <string> stderrprint -
  308. //stderrfile dup 3 -1 roll writestring flushfile
  309. } bind def
  310. /pdfformaterror { % <string> pdfformaterror -
  311. stderrprint
  312. /Repaired true store
  313. } bind def
  314. /printrepaired {
  315. Trailer /Info knownoget {
  316. /Producer knownoget not { null } if
  317. } {
  318. null
  319. } ifelse
  320. dup null eq {
  321. pop (\
  322. **** Please notify the author of the software that produced this file
  323. )
  324. } {
  325. ( **** The file was produced by ) stderrprint
  326. % Handle a Unicode Producer.
  327. (\376\377) anchorsearch {
  328. pop dup length 2 idiv string 0 1 2 index length 1 sub {
  329. % Stack: origstr newstr i
  330. 1 index exch 3 index 1 index 2 mul 1 add get put
  331. } for exch pop
  332. } if
  333. stderrprint
  334. (:
  335. **** please notify the author of this software
  336. )
  337. } ifelse stderrprint
  338. (\
  339. **** that the file does not conform to Adobe's published PDF
  340. **** specification. Processing of the file will continue normally.
  341. ) stderrprint
  342. } bind def
  343. % Write the outline structure for a file. Uses linkdest (below).
  344. /writeoutline % <outlinedict> writeoutline -
  345. { mark
  346. 0 2 index /First knownoget
  347. { { exch 1 add exch /Next knownoget not { exit } if } loop }
  348. if
  349. % stack: dict mark count
  350. dup 0 eq
  351. { pop 1 index
  352. }
  353. { 2 index /Count knownoget { 0 lt { neg } if } if
  354. /Count exch 3 index
  355. }
  356. ifelse linkdest /Title oget /Title exch /OUT pdfmark
  357. /First knownoget
  358. { { dup writeoutline /Next knownoget not { exit } if } loop }
  359. if
  360. } bind def
  361. % Close a PDF file.
  362. /pdfclose % <dict> pdfclose -
  363. { begin
  364. PDFfile closefile
  365. end
  366. } bind def
  367. % ======================== Page accessing ======================== %
  368. % Get a (possibly inherited) attribute of a page.
  369. /pget % <pagedict> <key> pget <value> -true-
  370. % <pagedict> <key> pget -false-
  371. { 2 copy knownoget
  372. { exch pop exch pop true
  373. }
  374. { exch /Parent knownoget
  375. { exch pget }
  376. { pop false }
  377. ifelse
  378. }
  379. ifelse
  380. } bind def
  381. % Get the value of a resource on a given page.
  382. /rget { % <resname> <pagedict> <restype> rget <value> -true-
  383. % <resname> <pagedict> <restype> rget -false-
  384. LocalResources 1 index knownoget {
  385. 3 index knownoget
  386. } {
  387. false
  388. } ifelse {
  389. exch pop exch pop exch pop true
  390. } {
  391. exch /Resources pget {
  392. exch knownoget { exch knownoget } { pop false } ifelse
  393. } {
  394. pop pop false
  395. } ifelse
  396. } ifelse
  397. } bind def
  398. % Get the total number of pages in the document.
  399. /pdfpagecount % - pdfpagecount <int>
  400. { Trailer /Root oget /Pages oget /Count oget
  401. } bind def
  402. % Find the N'th page of the document by iterating through the Pages tree.
  403. % The first page is numbered 1.
  404. /pdffindpageref { % <int> pdffindpage <objref>
  405. dup Trailer /Root oget /Pages get
  406. { % We should be able to tell when we reach a leaf
  407. % by finding a Type unequal to /Pages. Unfortunately,
  408. % some files distributed by Adobe lack the Type key
  409. % in some of the Pages nodes! Instead, we check for Kids.
  410. dup oforce /Kids knownoget not { exit } if
  411. exch pop null
  412. 0 1 3 index length 1 sub {
  413. 2 index exch get
  414. dup oforce dup /Kids known { /Count oget } { pop 1 } ifelse
  415. % Stack: index kids null noderef count
  416. dup 5 index ge { pop exch pop exit } if
  417. 5 -1 roll exch sub 4 1 roll pop
  418. } for exch pop
  419. % Stack: index null|noderef
  420. dup null eq { pop pop 1 null exit } if
  421. } loop
  422. % Stack: index countleft noderef
  423. 1 index 1 ne { pop pop /pdffindpage cvx /rangecheck signalerror } if
  424. exch pop
  425. PageIndex 2 index 1 sub 65533 min 2 index oforce put
  426. PageNumbers 1 index oforce 3 index dup 65534 le
  427. { put }
  428. { pop pop pop } % don't store more than 65534 pagenumbers
  429. ifelse
  430. exch pop
  431. } bind def
  432. /pdffindpage { % <int> pdffindpage <pagedict>
  433. pdffindpageref oforce
  434. } bind def
  435. % Find the N'th page of the document.
  436. % The first page is numbered 1.
  437. /pdfgetpage % <int> pdfgetpage <pagedict>
  438. { PageIndex 1 index 1 sub dup 65533 lt
  439. { get }
  440. { pop pop null }
  441. ifelse
  442. dup null ne
  443. { exch pop oforce }
  444. { pop pdffindpage }
  445. ifelse
  446. } bind def
  447. % Find the page number of a page object (inverse of pdfgetpage).
  448. /pdfpagenumber % <pagedict> pdfpagenumber <int>
  449. { % We use the simplest and stupidest of all possible algorithms....
  450. PageNumbers 1 index .knownget
  451. { exch pop
  452. }
  453. { 1 1 PageCount 1 add % will give a rangecheck if not found
  454. { dup pdfgetpage oforce 2 index eq { exit } if pop
  455. }
  456. for exch pop
  457. }
  458. ifelse
  459. } bind def
  460. % Display a given page.
  461. /boxrect % [<llx> <lly> <urx> <ury>] boxrect <x> <y> <w> <h>
  462. { aload pop exch 3 index sub exch 2 index sub
  463. } bind def
  464. /resolvedest { % <name|string|other> resolvedest <other|null>
  465. dup type /nametype eq {
  466. Trailer /Root oget /Dests knownoget {
  467. exch knownoget not { null } if
  468. } {
  469. null
  470. } ifelse
  471. } {
  472. dup type /stringtype eq {
  473. Trailer /Root oget /Names knownoget {
  474. /Dests knownoget {
  475. exch nameoget
  476. } {
  477. pop null
  478. } ifelse
  479. } {
  480. pop null
  481. } ifelse
  482. } if
  483. } ifelse
  484. } bind def
  485. /linkdest { % <link|outline> linkdest
  486. % ([/Page <n>] /View <view> | ) <link|outline>
  487. dup /Dest knownoget
  488. { resolvedest
  489. dup type /dicttype eq { /D knownoget not { null } if } if
  490. dup null eq
  491. { pop }
  492. { dup 0 oget
  493. dup null eq
  494. { pop }
  495. { dup type /integertype ne { pdfpagenumber } if
  496. /Page exch 4 -2 roll
  497. }
  498. ifelse
  499. dup length 1 sub 1 exch getinterval /View exch 3 -1 roll
  500. }
  501. ifelse
  502. }
  503. if
  504. } bind def
  505. % <pagedict> mark ... -proc- -
  506. /namedactions 8 dict dup begin
  507. /FirstPage {
  508. /Page 1 3 -1 roll
  509. } def
  510. /LastPage {
  511. counttomark 2 add index pdfpagecount /Page exch 3 -1 roll
  512. } def
  513. /NextPage {
  514. counttomark 2 add index pdfpagenumber 1 add /Page exch 3 -1 roll
  515. } def
  516. /PrevPage {
  517. counttomark 2 add index pdfpagenumber 1 sub /Page exch 3 -1 roll
  518. } def
  519. end readonly def
  520. % <pagedict> <annotdict> -proc- -
  521. /annottypes 5 dict dup begin
  522. /Text {
  523. mark exch
  524. { /Rect /Open /Contents }
  525. { 2 copy knownoget { 3 -1 roll } { pop } ifelse }
  526. forall pop /ANN pdfmark
  527. } bind def
  528. /Link {
  529. mark exch
  530. { /Rect /Border }
  531. { 2 copy knownoget { 3 -1 roll } { pop } ifelse }
  532. forall dup /A knownoget {
  533. dup /URI known {
  534. /A mark 3 2 roll % <<>> /A [ <<action>>
  535. { oforce } forall
  536. .dicttomark
  537. 3 2 roll
  538. } {
  539. dup /D knownoget {
  540. exch pop exch dup length dict copy dup /Dest 4 -1 roll put
  541. } {
  542. /N knownoget { % Assume /S /Named
  543. namedactions exch .knownget { exec } if
  544. } if
  545. } ifelse
  546. } ifelse
  547. } if
  548. linkdest pop /LNK pdfmark
  549. } bind def
  550. end readonly def
  551. /pdfshowpage % <pagedict> pdfshowpage -
  552. { dup /Page exch store
  553. pdfshowpage_init
  554. pdfshowpage_setpage
  555. save /PDFSave exch store
  556. (before exec) VMDEBUG
  557. pdfshowpage_finish
  558. (after exec) VMDEBUG
  559. PDFSave restore
  560. } bind def
  561. /pdfpagecontents % <pagedict> pdfpagecontents <contents>
  562. { } bind def
  563. /pdfshowpage_init % <pagedict> pdfshowpage_init <pagedict>
  564. { /DSCPageCount DSCPageCount 1 add store
  565. } bind def
  566. /.pdfshowpage_Install { % <pagedict> [<prevproc>] .pdfshowpage_Install -
  567. exch
  568. % We would like to clip to the CropBox here, but the subsequent
  569. % initgraphics would override it. Instead, we have to handle it
  570. % in graphicsbeginpage.
  571. dup /MediaBox pget {
  572. dup 0 get neg exch 1 get neg translate
  573. } if
  574. pop 0 get exec
  575. } bind def
  576. /pdfshowpage_setpage { % <pagedict> pdfshowpage_setpage <pagedict>
  577. 4 dict begin % for setpagedevice
  578. % Stack: pagedict
  579. currentpagedevice /Orientation 2 index /Rotate pget not { 0 } if 90 idiv
  580. % Rotate specifies *clockwise* rotation!
  581. neg 3 and def
  582. % Stack: pagedict currentpagedict
  583. 1 index /MediaBox pget {
  584. % Set the page size.
  585. boxrect 2 array astore /PageSize exch def pop pop
  586. } if
  587. dup /Install .knownget {
  588. % Don't let the Install procedure get more deeply
  589. % nested after every page.
  590. dup type dup /arraytype eq exch /packedarraytype eq or {
  591. dup length 4 eq {
  592. dup 2 get /.pdfshowpage_Install load eq {
  593. 1 get 0 get % previous procedure
  594. } if
  595. } if
  596. } if
  597. } {
  598. { }
  599. } ifelse 1 array astore
  600. 2 index exch /.pdfshowpage_Install load /exec load
  601. 4 packedarray cvx
  602. % Stack: pagedict currentpagedict installproc
  603. /Install exch def
  604. % Stack: pagedict currentpagedict
  605. pop currentdict end setpagedevice
  606. } bind def
  607. /pdfshowpage_finish { % <pagedict> pdfshowpage_finish -
  608. .writepdfmarks {
  609. % Copy the crop box.
  610. dup /CropBox knownoget {
  611. % If the page has been rotated, rotate the CropBox.
  612. mark /CropBox 3 -1 roll
  613. 3 index /Rotate pget {
  614. 90 idiv 1 and 0 ne {
  615. aload pop 4 -2 roll exch 4 2 roll exch 4 array astore
  616. } if
  617. } if
  618. /PAGE pdfmark
  619. } if
  620. % Copy annotations and links.
  621. dup /Annots knownoget {
  622. 0 1 2 index length 1 sub
  623. { 1 index exch oget
  624. dup /Subtype oget annottypes exch .knownget { exec } { pop } ifelse
  625. }
  626. for pop
  627. } if
  628. } if % end .writepdfmarks
  629. % Display the actual page contents.
  630. 6 dict begin
  631. /BXlevel 0 def
  632. /BGDefault currentblackgeneration def
  633. /UCRDefault currentundercolorremoval def
  634. %****** DOESN'T HANDLE COLOR TRANSFER YET ******
  635. /TRDefault currenttransfer def
  636. matrix currentmatrix 2 dict
  637. 2 index /CropBox knownoget {
  638. boxrect 4 array astore 1 index /ClipRect 3 -1 roll put
  639. } if
  640. dictbeginpage /DefaultMatrix 1 index store setmatrix
  641. dup % for showing annotations below
  642. count /pdfemptycount exch store
  643. gsave
  644. % If the page uses any transparency features, show it within
  645. % a transparency group.
  646. PDFversion 1.4 lt {
  647. showpagecontents
  648. } {
  649. dup pageusestransparency {
  650. % Show the page within a PDF 1.4 device filter.
  651. 0 .pushpdf14devicefilter {
  652. % If the page has a Group, enclose contents in transparency group.
  653. % (Adobe Tech Note 5407, sec 9.2)
  654. dup /Group knownoget {
  655. 1 index /CropBox knownoget not {
  656. 1 index /MediaBox oget
  657. } if .beginformgroup {
  658. showpagecontents
  659. } .internalstopped {
  660. .discardtransparencygroup stop
  661. } if .endtransparencygroup
  662. } {
  663. showpagecontents
  664. } ifelse
  665. } .internalstopped {
  666. % todo: discard
  667. .popdevicefilter stop
  668. } if .popdevicefilter
  669. } {
  670. showpagecontents
  671. } ifelse
  672. } ifelse
  673. grestore
  674. % todo: mixing drawing ops outside the device filter could cause
  675. % problems, for example with the pnga device.
  676. /Annots knownoget { { oforce drawannot } forall } if
  677. endpage
  678. end % scratch dict
  679. } bind def
  680. /showpagecontents { % <pagedict> showpagecontents -
  681. /Contents knownoget not { 0 array } if
  682. dup type /arraytype ne { 1 array astore } if {
  683. oforce false resolvestream pdfopdict .pdfrun
  684. } forall
  685. } bind def
  686. /processcolorspace { % - processcolorspace <colorspace>
  687. % The following is per the PLRM3.
  688. currentdevice 1 dict dup /ProcessColorModel dup put .getdeviceparams
  689. exch pop exch pop
  690. dup type /nametype ne { cvn } if
  691. dup { setcolorspace } .internalstopped { pop /DeviceRGB } if
  692. } bind def
  693. % ------ Transparency support ------ %
  694. % Determine whether a page might invoke any transparency features:
  695. % - Group in the page dictionary
  696. % - Non-default ca, CA, or SMask in an ExtGState
  697. % - Form XObject with Group
  698. % - Image XObject with SMask
  699. % ****** DO WE NEED TO LOOK IN RESOURCE DICTS OF OTHER CONTENT STREAMS? ******
  700. /pageusestransparency { % <pagedict> pageusestransparency <bool>
  701. PDFversion 1.4 lt {
  702. pop false
  703. } {
  704. dup /Group known {
  705. pop true
  706. } {
  707. false exch {
  708. dup resourceusestransparency { pop not exit } if
  709. /Parent knownoget not { exit } if
  710. } loop
  711. } ifelse
  712. } ifelse
  713. } bind def
  714. % Check the Resources of a page or Form.
  715. /resourceusestransparency { % <dict> resourceusestransparency <bool>
  716. { % Use loop to provide an exitable context.
  717. /Resources knownoget not { 0 dict } if
  718. dup /ExtGState knownoget {
  719. false exch {
  720. exch pop oforce
  721. dup /ca knownoget { 1 ne { pop not exit } if } if
  722. dup /CA knownoget { 1 ne { pop not exit } if } if
  723. dup /SMask knownoget { /None ne { pop not exit } if } if
  724. pop
  725. } forall { pop true exit } if
  726. } if
  727. dup /XObject knownoget {
  728. false exch {
  729. exch pop oforce dup /Subtype get
  730. dup /Image eq { 1 index /SMask known { pop pop not exit } if } if
  731. /Form eq {
  732. dup /Group known { pop not exit } if
  733. resourceusestransparency { not exit } if
  734. } {
  735. pop
  736. } ifelse
  737. } forall { pop true exit } if
  738. } if
  739. pop false exit
  740. } loop
  741. } bind def
  742. end % pdfdict
  743. .setglobal