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.

1344 lines
44 KiB

1 month ago
  1. % Copyright (C) 2001-2024 Artifex Software, Inc.
  2. % All Rights Reserved.
  3. %
  4. % This software is provided AS-IS with no warranty, either express or
  5. % implied.
  6. %
  7. % This software is distributed under license and may not be copied,
  8. % modified or distributed except as expressly authorized under the terms
  9. % of the license contained in the file LICENSE in this distribution.
  10. %
  11. % Refer to licensing information at http://www.artifex.com or contact
  12. % Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
  13. % CA 94129, USA, for further information.
  14. %
  15. % pdf_main.ps
  16. % PDF file- and page-level operations.
  17. /.setlanguagelevel where { pop 2 .setlanguagelevel } if
  18. .currentglobal //true .setglobal
  19. % ======================== Main program ======================== %
  20. userdict begin
  21. % Redefine 'run' so it recognizes PDF files.
  22. systemdict begin
  23. systemdict /OLDPDF known {
  24. systemdict /OLDPDF get {
  25. ( **** WARNING ****\n) print
  26. (The old, written in PostScript, PDF interpreter has been removed entirely.\n) print
  27. (You should cease using -dOLDPF as it has no effect now.\n) print
  28. (Continuing to process PDF file using the new, written in C, PDF interpreter.\n\n) print
  29. } if
  30. } if
  31. systemdict /NEWPDF known {
  32. systemdict /NEWPDF get not {
  33. (The old, written in PostScript, PDF interpreter has been removed entirely.\n) print
  34. (You should cease using -dNEWDPF as it has no effect now.\n) print
  35. (Continuing to process PDF file using the new, written in C, PDF interpreter.\n) print
  36. } if
  37. } if
  38. % PostScript interface to the ghostpdf C-based interpreter
  39. %
  40. % Promised or documented as used by customers
  41. % ===========================================
  42. % runpdf <file> runpdf -
  43. % Called from the modified run operator (which copies stdin to a temp
  44. % file if required). Calls runpdfbegin, check for PDF collections. Then
  45. % calls process_trailer_attrs, runpdfpagerange, dopdfpages and runpdfend
  46. % to process all the required pages.
  47. %
  48. % runpdfbegin <file> runpdfbegin -
  49. % creates /pdfdict in userdict set userparmas (ProcessDSCComment
  50. % setobjectformat to 0 /Page# /Page to null DSCPageCount to 0
  51. % /PDFSave /null.
  52. % calls pdfopen and then 'begin's the returned dictionary.
  53. % Also disables page handler device.
  54. %
  55. % pdfgetpage <int> pdfgetpage <pagedict> | <null>
  56. % int is a number from 1 to N indicating the desired page number from
  57. % the PDF file. Returns a dictionary, apparently the /Page dictionary. Probably
  58. % we only need the Boxes and Rotate key ? If this fails, returns a null object.
  59. %
  60. % pdfshowpage_init <int> pdfshowpage_init <dict>
  61. % This simply adds 1 to the /DSCPageCount value in the supplied dictioanry
  62. %
  63. % pdfshowpage_setpage <pagedict> pdfshowpage_setpage <pagedict>
  64. % Takes a dictionary as returned from pdfgetpage, extracts various
  65. % parameters from it, and sets the media size for the page, taking into
  66. % account the boxes, and requested Box, Rotate value and PDFFitPage.
  67. %
  68. % pdfshowpage_finish <pagedict> pdfshowpage_finish -
  69. % Takes a dictionary as returned from pdfgetpage, renders the page content
  70. % executes showpage to transfer the rendered content to the device.
  71. %
  72. % runpdfend -
  73. % Uses currentdict as an argument to pdfclose, which closes /PDFfile. Also
  74. % executes restore and various cleanup activities.
  75. %
  76. % pdfavailable - pdfavailable <bool>
  77. % Determines if there is a PDF interpreter available
  78. %
  79. % Also Used by gsview 5
  80. % =====================
  81. % pdfopen <file> pdfopen <dict>
  82. % According to the comments; open a PDF file and read the header, trailer
  83. % and cross-reference. Calls pdfopenfile and 'begin's the returned dictionary
  84. % calls pdfopencache and then closes the current dictionary.
  85. % pdfopenfile appears to create a dictionary containing a load of stuff but
  86. % most importantly, sets /PDFfile to the passed-in file. Probably also contains
  87. % the Trailer dictionary.
  88. %
  89. % pdfclose <dict> pdfclose -
  90. % The supplied dictionary contains /PDFfile and it executes closefile on that
  91. % supplied file.
  92. %
  93. % Supplied by Ray to customer
  94. % ============================
  95. % pdfshowpage <pagedict> pdfshowpage
  96. % Takes a dictionary returned from pdfgetpage and calls the pdfshowpage_init
  97. % pdfshowpage_setpage, pdfshowpage_finish trio to start the page, set up the
  98. % media and render the page.
  99. %
  100. % dopdfpages <int> <int> dopdfpages -
  101. % The integers are the first and last pages to be run from the file. Runs a loop from
  102. % the fist integer to the last. NOTE! If the current dictionary contains a PDFPageList
  103. % array then we 'get' the entry from the array corresponding to the current loop
  104. % index, and use that to determine whether we should draw the page. Otherwise we
  105. % simply draw the page. Uses pdfshowpage to actually render the page.
  106. %
  107. % Additionallly useful ?
  108. % =======================
  109. % runpdfpagerange - runpdfpagerange <int> <int>
  110. % Processes the PostScript /FirstPage, /LastPage and /PageList parameters to build an array
  111. % of page numbers to run (if PageList is present) and a FirstPage and LastPage value.
  112. % There seems no point in rewriting this, may as well use it to control page processing.
  113. %
  114. % Normal operation
  115. % =================
  116. % runpdf - runpdfbegin - pdfopen
  117. % - process_trailer_attrs
  118. % - runpdfpagerange
  119. % - dopdfpages - pdfgetpage
  120. % - pdfshowpage - pdfshowpage_init
  121. % - pdfshowpage_setpage
  122. % - pdfshowpage_finish
  123. % - runpdfend - pdfclose
  124. %
  125. /DisablePageHandlerDevice
  126. {
  127. systemdict /FirstPage known
  128. systemdict /LastPage known or
  129. systemdict /PageList known or
  130. {
  131. <</DisablePageHandler //true>> setpagedevice
  132. } if
  133. } .internalbind def
  134. /EnablePageHandlerDevice
  135. {
  136. systemdict /FirstPage known
  137. systemdict /LastPage known or
  138. systemdict /PageList known or
  139. {
  140. <</DisablePageHandler //false>> setpagedevice
  141. } if
  142. } .internalbind def
  143. /newpdf_pdfformaterror { % <string> pdfformaterror -
  144. (%stdout) (w) file
  145. dup 3 -1 roll writestring flushfile
  146. } .internalbind def
  147. % This routine sets up the transparency compositor requirement, and
  148. % number of spot channels required (if any) in the device. This needs
  149. % to be done before we set the media size, so that the erasepage is
  150. % correct. Called with the dictionary returned from .PDFPageInfo
  151. /newpdf_device_setup
  152. {
  153. 2 dict exch % <<page dict>> << >>
  154. dup /UsesTransparency get % << >> <<page dict>> bool
  155. /PageUsesTransparency exch % << >> <<page dict>> /PageUsesTransparency bool
  156. 3 index 3 1 roll % << >> <<page dict>> <<info dict>> << >> /PageUsesTransparency bool
  157. put % <</PageUsesTransparency bool>> <<page dict>>
  158. currentpagedevice /PageSpotColors known {
  159. /NumSpots get % <</PageUsesTransparency bool>> int
  160. /PageSpotColors exch % <</PageUsesTransparency bool>> /PageSpotColors int
  161. 2 index 3 1 roll % <</PageUsesTransparency bool>> <<page dict>> /PageSpotColors int
  162. put % <</PageUsesTransparency bool /PageSpotColors int >>
  163. }{
  164. pop
  165. } ifelse
  166. setpagedevice
  167. }.internalbind def
  168. % Takes the selected Box as a parameter and scales it to fit the current media.
  169. % If the amount of scaling would be reduced by rotating the content, then
  170. % rotate the content.
  171. % Caters for the box non-zero lower left x and y (ie cropping)
  172. /NewPDF_FitPage
  173. {
  174. dup 2 get 1 index 0 get sub %urx -llx = width
  175. 1 index 3 get 2 index 1 get sub %ury - lly = height
  176. currentpagedevice /PageSize get aload pop % Stack - box boxwidth boxheight mediawidth mediaheight
  177. % Start by deciding if we should rotate the page to better fit the media.
  178. 4 copy eq
  179. 3 1 roll eq
  180. or % square media or square page, no point in rotating
  181. {
  182. pop pop pop pop
  183. //false
  184. }
  185. {
  186. gt
  187. { % landscape media
  188. ge
  189. { % landscape media, landscape box, no rotation
  190. //false
  191. }
  192. { % landscape media, portrait box, rotate it to landscape
  193. //true
  194. } ifelse
  195. }
  196. { % portrait media
  197. ge
  198. { % portrait media, landscape box, rotate it to portrait
  199. //true
  200. }
  201. { % portrait media, portrait box, no rotation
  202. //false
  203. } ifelse
  204. }ifelse
  205. } ifelse
  206. % Store values for calculating scale, we do this here because we want to
  207. % swap the media width and height (for the scale calculation) if we are
  208. % rotating the page
  209. 1 index 2 get 2 index 0 get sub % urx -llx = width
  210. 2 index 3 get 3 index 1 get sub % ury - lly = height
  211. currentpagedevice /PageSize get aload pop % Stack - box rotate boxwidth boxheight mediawidth mediaheight
  212. 5 -1 roll % Stack - box boxwidth boxheight mediawidth mediaheight rotate
  213. % If we need to rotate, recalculate the box
  214. {
  215. % We take any existing /Rotate key in the dictionary into account as well, because
  216. % that way we will preserve the orientation which would be used when displaying
  217. % the original, un-modified page. Note that PostScript's rotate operator works
  218. % counter-clockwise, while PDF works clockwise....
  219. %
  220. 7 index dup /Rotate known {/Rotate get}{pop 90}ifelse
  221. 270 eq {
  222. 90 rotate
  223. 0 2 index neg translate % move 0,0 to bottom right of media to account for rotation
  224. exch % swap media width/height for scaling calculation
  225. }
  226. {
  227. 270 rotate
  228. dup neg 0 translate % move 0,0 to bottom right of media to account for rotation
  229. exch % swap media width/height for scaling calculation
  230. } ifelse
  231. }if
  232. % Now use the box and media values to calculate the required x/y scale factors
  233. 4 copy % Stack - box boxwidth boxheight mediawidth mediaheight boxwidth boxheight mediawidth mediaheight
  234. 3 -1 roll div % box boxwidth boxheight mediawidth mediaheight boxwidth mediawidth (mediaheight / boxheight)
  235. 3 1 roll % box boxwidth boxheight mediawidth mediaheight (mediaheight / boxheight) boxwidth mediawidth
  236. exch % box boxwidth boxheight mediawidth mediaheight (mediaheight / boxheight) mediawidth boxwidth
  237. div % box boxwidth boxheight mediawidth mediaheight (mediaheight / boxheight) (mediawidth / boxwidth)
  238. % Stack - box boxwidth boxheight mediawidth mediaheight Yscale Xscale
  239. % Centre the output on the media
  240. 2 copy % box boxwidth boxheight mediawidth mediaheight Yscale Xscale Yscale Xscale
  241. gt {
  242. exch pop % box boxwidth boxheight mediawidth mediaheight Xscale
  243. dup 4 index mul % box boxwidth boxheight mediawidth mediaheight Xscale (boxheight * Xscale)
  244. 3 -1 roll sub dup
  245. 0 lt {-1 mul} if % box boxwidth boxheight mediawidth Xscale ((boxheight * Xscale) - mediaheight)
  246. dup 0 ne {2 div} if % box boxwidth boxheight mediawidth Xscale (heightdiff / 2)
  247. 0 exch translate % box boxwidth boxheight mediawidth Xscale
  248. } {
  249. pop % box boxwidth boxheight mediawidth mediaheight Yscale
  250. dup 5 index mul % box boxwidth boxheight mediawidth mediaheight Yscale (boxwidth * Yscale)
  251. 4 -1 roll sub dup
  252. 0 lt {-1 mul} if % box boxwidth boxheight mediaheight Yscale ((boxwidth * Yscale) - mediawidth)
  253. dup 0 ne {2 div} if % box boxwidth boxheight mediawidth Yscale (widthdiff / 2)
  254. 0 translate % box boxwidth boxheight mediawidth Yscale
  255. } ifelse
  256. % Apply any 'offset' in the Box. Tht is, if the llx and lly are not 0, then we need to
  257. % shift the origin of the content so that they become 0,0. We need to take into
  258. % account the scaling from above.
  259. 4 index aload pop pop pop
  260. neg 2 index mul exch neg 2 index mul exch
  261. translate
  262. dup scale % scale both axes the same
  263. pop pop pop % remove the leftover boxwidth, boxheight and mediawidth/height
  264. } .internalbind def
  265. /newpdf_get_media_box { % <pagedict> get_media_box <box> <bool>
  266. dup /MediaBox known {
  267. /MediaBox get
  268. dup length 4 eq {
  269. //true
  270. }
  271. {
  272. pop
  273. ( **** Error: Page has an invalid /MediaBox attribute. Using the current page size.\n)
  274. newpdf_pdfformaterror
  275. ( Output may be incorrect.\n) pdfformaterror
  276. [ 0 0 currentpagedevice /PageSize get aload pop ]
  277. //false
  278. }ifelse
  279. }
  280. {
  281. pop
  282. ( **** Error: Page has no /MediaBox attribute. Using the current page size.\n)
  283. newpdf_pdfformaterror
  284. ( Output may be incorrect.\n) newpdf_pdfformaterror
  285. [ 0 0 currentpagedevice /PageSize get aload pop ] //false
  286. } ifelse
  287. } .internalbind def
  288. % [llx lly urx ury] newpdf_check_empty_box [llx lly urx ury] true | false
  289. % rturns true and the original array if its valid, otherwise returns false
  290. /newpdf_check_empty_box
  291. {
  292. dup type /arraytype eq
  293. {
  294. dup aload pop
  295. dup 3 index eq
  296. {
  297. //true
  298. }
  299. {
  300. 1 index 4 index eq
  301. } ifelse
  302. {
  303. pop pop pop pop
  304. ( **** Warning: File has an empty Box parameter.\n) print
  305. ( Using the MediaBox instead.\n) print
  306. ( Output may be incorrect.\n) print flush
  307. pop //false
  308. }
  309. {
  310. pop pop pop pop
  311. //true
  312. } ifelse
  313. }
  314. {
  315. ( **** Warning: File has an invalid Box parameter.\n) print
  316. ( Using the MediaBox instead.\n) print
  317. ( Output may be incorrect.\n) print flush
  318. pop //false
  319. } ifelse
  320. } .internalbind def
  321. /newpdf_get_any_box { % <pagedict> get_any_box <box name> <box>
  322. //systemdict /UseBleedBox .knownget dup { and } if {
  323. dup /BleedBox .knownget {
  324. newpdf_check_empty_box
  325. {
  326. /BleedBox exch
  327. } if
  328. } if
  329. } if
  330. dup type /arraytype ne {
  331. //systemdict /UseTrimBox .knownget dup { and } if {
  332. dup /TrimBox .knownget {
  333. newpdf_check_empty_box
  334. {
  335. /TrimBox exch
  336. } if
  337. } if
  338. } if
  339. } if
  340. dup type /arraytype ne {
  341. //systemdict /UseArtBox .knownget dup { and } if {
  342. dup /ArtBox .knownget {
  343. newpdf_check_empty_box
  344. {
  345. /ArtBox exch
  346. } if
  347. } if
  348. } if
  349. } if
  350. dup type /arraytype ne {
  351. //systemdict /UseCropBox .knownget dup { and } if {
  352. dup /CropBox .knownget {
  353. newpdf_check_empty_box
  354. {
  355. /CropBox exch
  356. } if
  357. } if
  358. } if
  359. } if
  360. dup type /arraytype ne {
  361. /MediaBox exch newpdf_get_media_box pop
  362. } {
  363. %% Complicated stuff. We need to use the 'Box' we identified (if any), but we
  364. %% need to clamp the boundaries of the 'Box' to the MediaBox. This appears to
  365. %% be what Acrobat does. The complication arises because the Box values don't
  366. %% have to be sensibly positive, its permissible to have the MediaBox set up
  367. %% so that it extends down and left instead of up and right. We take care of the
  368. %% content when we st up the CTM, but we do need to make sure that we clamp
  369. %% the BoundingBox, and that means we need to take direcitonality into account...
  370. aload pop
  371. 6 -1 roll newpdf_get_media_box { % /SomeBox x0 y0 x1 y1 [MediaBox]
  372. aload pop % /SomeBox x0 y0 x1 y1 X0 Y0 X1 Y1
  373. %% Start with the width, get the X0 and X1 values of the MediaBox
  374. 3 index % /SomeBox x0 y0 x1 y1 X0 Y0 X1 Y1 X0
  375. 2 index % /SomeBox x0 y0 x1 y1 X0 Y0 X1 Y1 X0 X1
  376. gt {
  377. %% Media extends to left
  378. 4 -1 roll % /SomeBox x0 y0 x1 y1 Y0 X1 Y1 X0
  379. 8 -1 roll % /SomeBox y0 x1 y1 Y0 X1 Y1 X0 x0
  380. .min % /SomeBox y0 x1 y1 Y0 X1 Y1 mX0
  381. 7 1 roll % /SomeBox mX0 y0 x1 y1 Y0 X1 Y1
  382. exch % /SomeBox mX0 y0 x1 y1 Y0 Y1 X1
  383. 5 -1 roll % /SomeBox mX0 y0 y1 Y0 Y1 X1 x1
  384. .max % /SomeBox mX0 y0 y1 Y0 Y1 mX1
  385. 5 1 roll % /SomeBox mX0 mX1 y0 y1 Y0 Y1
  386. }{
  387. %% Media extends to right
  388. 4 -1 roll % /SomeBox x0 y0 x1 y1 Y0 X1 Y1 X0
  389. 8 -1 roll % /SomeBox y0 x1 y1 Y0 X1 Y1 X0 x0
  390. .max % /SomeBox y0 x1 y1 Y0 X1 Y1 mX0
  391. 7 1 roll % /SomeBox mX0 y0 x1 y1 Y0 X1 Y1
  392. exch % /SomeBox mX0 y0 x1 y1 Y0 Y1 X1
  393. 5 -1 roll % /SomeBox mX0 y0 y1 Y0 Y1 X1 x1
  394. .min % /SomeBox mX0 y0 y1 Y0 Y1 mX1
  395. 5 1 roll % /SomeBox mX0 mX1 y0 y1 Y0 Y1
  396. } ifelse
  397. %% Now deal with the height
  398. 2 copy % /SomeBox mX0 mX1 y0 y1 Y0 Y1 Y0 Y1
  399. gt {
  400. %% Media extends down
  401. exch % /SomeBox mX0 mX1 y0 y1 Y1 Y0
  402. 4 -1 roll % /SomeBox mX0 mX1 y1 Y1 Y0 y0
  403. .min % /SomeBox mX0 mX1 y1 Y1 mY0
  404. 3 1 roll % /SomeBox mX0 mX1 mY0 y1 Y1
  405. .max % /SomeBox mX0 mX1 mY0 mY1
  406. }{
  407. %% Media extends up
  408. exch % /SomeBox mX0 mX1 y0 y1 Y1 Y0
  409. 4 -1 roll % /SomeBox mX0 mX1 y1 Y1 Y0 y0
  410. .max % /SomeBox mX0 mX1 y1 Y1 mY0
  411. 3 1 roll % /SomeBox mX0 mX1 mY0 y1 Y1
  412. .min % /SomeBox mX0 mX1 mY0 mY1
  413. } ifelse
  414. exch % /SomeBox mX0 mX1 mY1 mY0
  415. 3 1 roll % /SomeBox mX0 mY0 mX1 mY1
  416. } {
  417. pop
  418. } ifelse
  419. 4 array astore % /SomeBox [mX0 mY0 mX1 mY1]
  420. } ifelse
  421. } .internalbind def
  422. % This routine is used to set the PostScript /PageSize from the requested Box of the
  423. % PDF file. Much of this is copied from the old pdfshowpage_setpage routine which
  424. % is used for the PDF interpreter written in PostScript.
  425. %
  426. % Called with a dictionary containing the PDF page information.
  427. %
  428. /newpdf_set_pagesize
  429. {
  430. % Stack: pdfpagedict
  431. % Don't understand this at all, removed for now replace if we ever figure out
  432. % what it's for.
  433. % Only lock in Orientation if we need to for pdfmarks
  434. % .writepdfmarks { /Orientation 0 def } if
  435. dup
  436. dup newpdf_get_any_box % Stack: pdfpagedict pdfpagedict /BoxName [box]
  437. % Check that the box is 'normal' and make it so if not
  438. % Also check the array is 4 elements and if it isn't then use the
  439. % current PageSize. The normalise arithmetic assumes the array is a 4
  440. % element array.
  441. dup length 4 ne {
  442. % Invalid size of mediabox
  443. pop currentpagedevice /PageSize get
  444. } {
  445. aload 5 1 roll % array x1 y1 x2 y2
  446. exch % array x1 y1 y2 x2
  447. 4 -1 roll % array y1 y2 x2 x1
  448. 2 copy gt {
  449. exch % array y1 y2 xmin xmax
  450. } if
  451. 4 -2 roll % array xmin xmax y1 y2
  452. 2 copy gt {
  453. exch % array xmin xmax ymin ymax
  454. } if
  455. 4 1 roll
  456. exch 4 -1 roll
  457. 5 -1 roll
  458. astore
  459. } ifelse
  460. //systemdict /PDFFitPage known {
  461. NewPDF_FitPage
  462. } {
  463. 6 dict begin % for setpagedevice
  464. % Set the page size.
  465. 2 index /UserUnit known
  466. {
  467. systemdict /NoUserUnit .knownget not {//false} if
  468. {
  469. 2 index /UserUnit undef
  470. % No scaling required, calculate PageSize as the width and height of the box
  471. aload 5 1 roll % box llx lly urx ury
  472. 2 index sub % box llx lly urx (ury - lly)
  473. exch 3 index sub % box llx lly (ury - lly) (urx - llx)
  474. exch
  475. }
  476. {
  477. 2 index /UserUnit get
  478. /PassUserUnit /GetDeviceParam .special_op {exch pop} {//false} ifelse {
  479. [ /UserUnit 3 -1 roll .pdfputparams pop pop
  480. % No media scaling required, calculate PageSize as the width and height of the box
  481. aload 5 1 roll % box llx lly urx ury
  482. 2 index sub % box llx lly urx (ury - lly)
  483. exch 3 index sub % box llx lly (ury - lly) (urx - llx)
  484. exch
  485. }{
  486. % The PageSize needs to be multiplied too
  487. exch aload 5 1 roll % UserUnit box llx lly urx ury
  488. 2 index sub exch % UserUnit box llx lly (ury - lly) urx
  489. 3 index sub % UserUnit box llx lly boxheight boxwidth
  490. 5 index mul % UserUnit box llx lly boxheight (Boxwidth*UserUnit)
  491. exch
  492. 5 index mul % UserUnit box llx lly (Boxwidth*UserUnit) (boxheight*UserUnit)
  493. 4 -2 roll
  494. 5 index mul exch % UserUnit box (Boxwidth*UserUnit) (boxheight*UserUnit) (lly*UserUnit) llx
  495. 5 index mul exch % UserUnit box (Boxwidth*UserUnit) (boxheight*UserUnit) (llx*UserUnit) (lly*UserUnit)
  496. 4 2 roll % UserUnit box (llx*UserUnit) (lly*UserUnit) (Boxwidth*UserUnit) (boxheight*UserUnit)
  497. 6 -1 roll pop % box (llx*UserUnit) (lly*UserUnit) (Boxwidth*UserUnit) (boxheight*UserUnit)
  498. } ifelse
  499. } ifelse
  500. }
  501. {
  502. /PassUserUnit /GetDeviceParam .special_op {
  503. exch pop {
  504. [ /UserUnit 1 .pdfputparams pop pop
  505. } if
  506. }if
  507. % No scaling required, calculate PageSize as the width and height of the box
  508. aload 5 1 roll % box llx lly urx ury
  509. 2 index sub % box llx lly urx (ury - lly)
  510. exch 3 index sub % box llx lly (ury - lly) (urx - llx)
  511. exch
  512. } ifelse
  513. % handle page rotation here
  514. 6 index /Rotate known {
  515. % PDF page rotation runs clockwise and must be a multiple of 90, unlike PostScript.....
  516. % convert Rotate into a quadrant number
  517. 6 index /Rotate get 90 div cvi
  518. % Make sure quadrant is 0-3
  519. dup 0 lt {
  520. % Negative rotation... Turn it into a positive rotation
  521. % Again, limit the quadrant to -0 to -3
  522. dup -4 lt {4 mod} if
  523. % Adding 360 degrees results in the same positive rotation
  524. 4 add
  525. } if
  526. dup 3 gt {4 mod} if
  527. dup 0 eq
  528. {
  529. pop
  530. 2 array astore /PageSize exch def
  531. currentdict end setpagedevice
  532. neg exch neg exch
  533. translate
  534. }
  535. {
  536. dup 1 eq
  537. {
  538. pop
  539. exch 4 2 roll exch 4 2 roll
  540. 2 array astore dup /PageSize exch def
  541. currentdict end setpagedevice
  542. 270 rotate
  543. 1 get add neg exch neg
  544. translate
  545. }
  546. {
  547. 2 eq
  548. {
  549. 2 array astore dup /PageSize exch def
  550. currentdict end setpagedevice
  551. 180 rotate
  552. aload pop 3 -1 roll add neg 3 1 roll add neg exch
  553. translate
  554. }
  555. {
  556. exch 4 2 roll exch 4 2 roll
  557. 2 array astore dup /PageSize exch def
  558. currentdict end setpagedevice
  559. 90 rotate
  560. 0 get 3 -1 roll add
  561. neg exch neg exch
  562. translate
  563. } ifelse
  564. } ifelse
  565. } ifelse
  566. }
  567. {
  568. 2 array astore /PageSize exch def
  569. currentdict end setpagedevice
  570. neg exch neg exch
  571. translate
  572. }ifelse
  573. % scale the co-ordinate system by the UserUnit
  574. % We have to do this after setting the PageSize, because
  575. % setpagedevice does an implicit initgraphics, resetting the CTM.
  576. %
  577. //systemdict /NoUserUnit .knownget not { //false } if not
  578. {
  579. 2 index /UserUnit known {
  580. /PassUserUnit /GetDeviceParam .special_op {
  581. exch pop not
  582. } {
  583. true
  584. }ifelse
  585. % If PassUserUnit isn't handled by the device, or it returns 'false'
  586. % then scale the content by the UserUnit. Otherwise do not scale.
  587. {
  588. 2 index /UserUnit get
  589. dup scale
  590. } if
  591. } if
  592. } if
  593. } ifelse
  594. 3 1 roll % <page dict> /BoxName [box dimensions] -> [box dimensions] <page dict> /BoxName
  595. % If we are using the MediaBox (and only the MediaBox) then we
  596. % want to clip to the CropBox, if there is one present. For every
  597. % other case, clip to the given Box.
  598. /MediaBox eq {
  599. dup /CropBox known {
  600. /CropBox get
  601. aload pop 2 index sub exch 3 index sub exch rectclip
  602. pop % [box dimensions] array
  603. } {
  604. pop % <page dict>
  605. aload % Load the co-ordinates of the box onto the stack
  606. pop % The array with the box co-ordinates
  607. % llx lly urx ury
  608. 2 index sub % ll lly urx (ury - lly)
  609. exch % llx lly height urx
  610. 3 index sub % llx lly height (urx - llx)
  611. exch % llx lly width height
  612. rectclip
  613. } ifelse
  614. } {
  615. pop % <page dict>
  616. aload % Load the co-ordinates of the box onto the stack
  617. pop % The array with the box co-ordinates
  618. % llx lly urx ury
  619. 2 index sub % ll lly urx (ury - lly)
  620. exch % llx lly height urx
  621. 3 index sub % llx lly height (urx - llx)
  622. exch % llx lly width height
  623. rectclip
  624. }ifelse
  625. pop
  626. } .internalbind def
  627. % This routine checks a list of known/implemented command line switches to see if they
  628. % have been defined in the PostScript environment. If they have we construct a dictionary
  629. % containing the names and their values, and return it. That dictionary can then be
  630. % passed to a custom PostScript operator and used to configure the PDF interpreter.
  631. %
  632. % NB device parameters will already have been sent to the device and used to configure it
  633. % so here we should only handle parameters which control the behaviour of the interpreter.
  634. %
  635. /PDFSwitches [ /QUIET /PDFPassword /PDFDEBUG /PDFSTOPONERROR /PDFSTOPONWARNING /NOTRANSPARENCY /FirstPage /LastPage
  636. /PDFA /PDFACompatibilityPolicy /PDFNOCIDFALLBACK /NO_PDFMARK_OUTLINES /NO_PDFMARK_DESTS /PDFFitPage /Printed /UsePDFX3Profile
  637. /UseBleedBox /UseCropBox /UseArtBox /UseTrimBox /ShowAcroForm /ShowAnnots /PreserveAnnots
  638. /NoUserUnit /RENDERTTNOTDEF /DOPDFMARKS /PDFINFO /ShowAnnotTypes /PreserveAnnotTypes
  639. /CIDFSubstPath /CIDFSubstFont /SUBSTFONT /IgnoreToUnicode /NONATIVEFONTMAP /PreserveMarkedContent /OutputFile
  640. /PreserveDocView /PreserveEmbeddedFiles ] def
  641. /newpdf_gather_parameters
  642. {
  643. 10 dict begin
  644. //PDFSwitches {
  645. dup where
  646. { exch dup 3 1 roll get def }
  647. { pop } ifelse
  648. } forall
  649. % This isn't a command line parameter, we track it internally, but we need to
  650. % send it to the interpreter. It is used to 'offset' the page Dest for Link
  651. % annotations and Outlines by the numebr of pages processed so far.
  652. /PageCount /CumulativePageCount where { /CumulativePageCount get }{currentpagedevice /PageCount get} ifelse def
  653. currentdict end
  654. } .internalbind def
  655. currentdict /PDFSwitches undef
  656. /pdfpagecount
  657. {
  658. currentdict /PDFInfo known
  659. {
  660. PDFInfo
  661. }
  662. {
  663. PDFFile //null eq not
  664. {
  665. PDFSTOPONERROR
  666. {
  667. PDFFile .PDFInfo //false
  668. }
  669. {
  670. PDFFile {.PDFInfo} stopped
  671. } ifelse
  672. }
  673. {
  674. //true
  675. }ifelse
  676. {
  677. <</NumPages 0>>
  678. } if
  679. } ifelse
  680. dup /NumPages known
  681. {
  682. /NumPages get
  683. }
  684. {
  685. pop 0
  686. } ifelse
  687. }.internalbind def
  688. /runpdfpagerange
  689. {
  690. /PageList where {
  691. pop
  692. PageList pdfpagecount .PDFparsePageList
  693. dup 0 eq { % No ranges, error
  694. (\n **** Error: Invalid PageList: ) print
  695. PageList print
  696. (\n No pages will be processed.) = flush
  697. /runpdfpagerange cvx /syntaxerror signalerror
  698. } if
  699. array astore % move integer triples from the stack to the array
  700. % newpdf PDFPageList is an array of 3 elements per range: even/odd flag, start, end
  701. /PDFPageList exch def
  702. QUIET not {
  703. (Processing pages ) print PageList =only (.) = flush
  704. } if
  705. 1 pdfpagecount % dummy parameters for newpdf_dopages
  706. }{
  707. /FirstPage where {
  708. pop FirstPage dup pdfpagecount gt {
  709. (\nRequested FirstPage is greater than the number of pages in the file: ) print
  710. pdfpagecount = flush
  711. } if
  712. } {
  713. 1
  714. } ifelse
  715. /LastPage where {pop LastPage pdfpagecount .min } { pdfpagecount } ifelse
  716. 1 index 1 index gt {
  717. ( No pages will be processed \(FirstPage > LastPage\).) = flush
  718. } {
  719. QUIET not {
  720. (Processing pages ) print 1 index =only ( through ) print dup =only
  721. (.) = flush
  722. } if
  723. } ifelse
  724. } ifelse
  725. } .internalbind def
  726. /runpdf_collection_entry
  727. {
  728. <</PreserveDocView false>> runpdfbegin_with_params % <file> runpdfbegin -
  729. PDFInfo type /dicttype eq
  730. {
  731. PDFInfo /Collection known
  732. {
  733. PDFInfo /Collection get
  734. pdfclose
  735. dup length 1 sub 0 2 3 -1 roll
  736. {
  737. 1 index exch get (r) file runpdf_collection_entry
  738. } for
  739. pop
  740. }
  741. {
  742. process_trailer_attrs % - process_trailer_attrs -
  743. runpdfpagerange % - runpdfpagerange <int> <int>
  744. dopdfpages % <int> <int> dopdfpages -
  745. runpdfend % - runpdfend -
  746. } ifelse
  747. } {
  748. pop pop
  749. }ifelse
  750. } .internalbind def
  751. % <file> runpdf -
  752. /newpdf_runpdf
  753. {
  754. runpdfbegin % <file> runpdfbegin -
  755. PDFInfo type /dicttype eq
  756. {
  757. PDFInfo /Collection known
  758. {
  759. PDFInfo /Collection get
  760. pdfclose
  761. dup length 1 sub 0 2 3 -1 roll
  762. {
  763. 1 index exch get (r) file runpdf_collection_entry
  764. } for
  765. pop
  766. % We need to do this, even though we called pdfclose above, in order to clean
  767. % up our dictionary and restore the state. We can't use runpdfend above because
  768. % if we do then we will delete all the temporary files containing the embedded
  769. % PDF files.
  770. runpdfend
  771. }
  772. {
  773. process_trailer_attrs % - process_trailer_attrs -
  774. runpdfpagerange % - runpdfpagerange <int> <int>
  775. dopdfpages % <int> <int> dopdfpages -
  776. runpdfend % - runpdfend -
  777. } ifelse
  778. } {
  779. pop pop
  780. }ifelse
  781. } .internalbind def
  782. % start a PDF file, and specify interpreter parameters to be used
  783. % to override any command line ones.
  784. % Mostly for the benefit of PDF Collections where we want to disable
  785. %preserving DocView information for pdfwrite.
  786. %
  787. % file <dict> runpdfbegin_with_params -
  788. /runpdfbegin_with_params
  789. {
  790. /pdfdict 10 dict def
  791. pdfdict begin
  792. currentpagedevice /PageCount get
  793. /CumulativePageCount exch def
  794. % This is for the benefit of pdf2dsc which assumes it will be present
  795. /Trailer << >> def
  796. /PDFSave save def
  797. % Define these in the current dictionary, if anyone uses
  798. % systemdict then this will be defeated so we'll add extra
  799. % code to the systemdict definitions as well.
  800. % /pdfpagecount /newpdf_pagecount load def
  801. % /pdfgetpage /newpdf_pdfgetpage load def
  802. % /pdfshowpage /newpdf_pdfshowpage load def
  803. % /pdfshowpage_init /newpdf_pdfshowpage_init load def
  804. % /pdfshowpage_setpage /newpdf_pdfshowpage_setpage load def
  805. % /pdfshowpage_finish /newpdf_pdfshowpage_finish load def
  806. % /pdfopen /newpdf_pdfopen load def
  807. % /pdfclose /newpdf_pdfclose load def
  808. % /dopdfpages /newpdf_dopdfpages load def
  809. % /runpdfend /newpdf_runpdfend load def
  810. % /runpdfpagerange /newpdf_runpdfpagerange load def
  811. % /process_trailer_attrs /newpdf_process_trailer_attrs load def
  812. % These are also for the benefit of pdf2dsc, which assumes they
  813. % are available.
  814. /knownoget {2 copy known {get //true}{pop pop //false}ifelse} bind def
  815. /pget {2 copy known {get //true}{pop pop //false}ifelse}bind def
  816. newpdf_gather_parameters % <parameter overrides dict> <parameter dict>
  817. exch {2 index 3 1 roll put} forall
  818. PDFSTOPONERROR
  819. {
  820. .PDFInit
  821. /PDFFile exch def
  822. pdfopen
  823. /PDFInfo exch def
  824. pop
  825. }
  826. {
  827. {.PDFInit} stopped
  828. {
  829. ( **** Error: Failed to initialise PDF interpreter.\n) newpdf_pdfformaterror
  830. /PDFFile //null def
  831. /PDFInfo //null def
  832. }
  833. {
  834. /PDFFile exch def
  835. pdfopen
  836. /PDFInfo exch def
  837. pop
  838. }ifelse
  839. }ifelse
  840. } .internalbind def
  841. % -file- runpdfbegin -
  842. /runpdfbegin
  843. {
  844. <<>> runpdfbegin_with_params
  845. } .internalbind def
  846. /pdfgetpage
  847. {
  848. dup 1 sub
  849. PDFSTOPONERROR
  850. {
  851. PDFFile exch .PDFPageInfo
  852. dup 3 -1 roll
  853. /Page# exch put
  854. }
  855. {
  856. PDFFile exch {.PDFPageInfo} stopped
  857. {
  858. pop pop
  859. ( **** Error: Couldn't get page info.\n) newpdf_pdfformaterror
  860. ( Output may be incorrect.\n) newpdf_pdfformaterror
  861. //null
  862. }{
  863. dup 3 -1 roll
  864. /Page# exch put
  865. } ifelse
  866. }ifelse
  867. } .internalbind def
  868. /process_trailer_attrs
  869. {
  870. }.internalbind def
  871. /pdfshowpage_init
  872. {
  873. } .internalbind def
  874. /pdfshowpage_setpage
  875. {
  876. dup newpdf_device_setup
  877. dup newpdf_set_pagesize
  878. } .internalbind def
  879. /pdfshowpage_finish
  880. {
  881. PDFSTOPONERROR
  882. {
  883. /Page# get PDFFile exch 1 sub .PDFDrawPage
  884. showpage
  885. }
  886. {
  887. /Page# get PDFFile exch 1 sub {.PDFDrawPage} stopped
  888. {
  889. pop pop
  890. ( **** Error: Page drawing error occurred.\n) newpdf_pdfformaterror
  891. ( Output may be incorrect.\n) newpdf_pdfformaterror
  892. } if
  893. {showpage} stopped
  894. {
  895. ( **** Error: Page drawing error occurred.\n) newpdf_pdfformaterror
  896. ( Could not draw this page at all, page will be missing in the output.\n) newpdf_pdfformaterror
  897. } if
  898. }ifelse
  899. } .internalbind def
  900. /pdfshowpage
  901. {
  902. /PDFINFO where {/PDFINFO get}{//false}ifelse
  903. {
  904. /Page# get PDFFile exch 1 sub {.PDFDrawPage} stopped pop
  905. }
  906. {
  907. pdfshowpage_init
  908. pdfshowpage_setpage
  909. pdfshowpage_finish
  910. }ifelse
  911. } .internalbind def
  912. /runpdfend
  913. {
  914. % Get the accumulated count of pages processed so far
  915. % and the number of pages in this file. Do this before
  916. % we close the file and restore the state. Save the values
  917. % on the stack.
  918. pdfpagecount
  919. CumulativePageCount
  920. pdfclose
  921. PDFSave restore
  922. end % pdfdict
  923. % add the number of pages in this file to the accumulated count,
  924. % and store that in the device for later reuse. This allows us to
  925. % add the number of pages already in the output to the 'Dest' of
  926. % Outlines and Link annotations.
  927. add <</PageCount 3 -1 roll >> setpagedevice
  928. } .internalbind def
  929. /pdfopen
  930. {
  931. dup PDFFile //null ne
  932. {
  933. PDFSTOPONERROR
  934. {
  935. PDFFile .PDFStream
  936. PDFFile .PDFInfo
  937. }
  938. {
  939. PDFFile {.PDFStream} stopped
  940. {
  941. pop pop
  942. ( **** Error: Couldn't initialise file.\n) newpdf_pdfformaterror
  943. ( Output may be incorrect.\n) newpdf_pdfformaterror
  944. <</NumPages 0>>
  945. }
  946. {
  947. PDFFile {.PDFInfo} stopped
  948. {
  949. pop
  950. ( **** Error: Couldn't get page information.\n) newpdf_pdfformaterror
  951. ( Output may be incorrect.\n) newpdf_pdfformaterror
  952. <</NumPages 0>>
  953. } if
  954. } ifelse
  955. }ifelse
  956. }
  957. {
  958. pop
  959. <</NumPages 0>>
  960. } ifelse
  961. } .internalbind def
  962. /pdfclose
  963. {
  964. PDFSTOPONERROR
  965. {
  966. PDFFile .PDFClose
  967. }
  968. {
  969. PDFFile {.PDFClose} stopped
  970. {
  971. pop
  972. } if
  973. }ifelse
  974. } .internalbind def
  975. /pdfavailable
  976. {
  977. .PDFAvailable
  978. } .internalbind def
  979. % <int> <int> dopdfpages -
  980. % First Page and then LastPage
  981. % If PDFPageList array exists, the parameters are 1 pdfpagecount and are ignored.
  982. /dopdfpages
  983. {
  984. //DisablePageHandlerDevice exec
  985. %% If we have a array of page ranges to render, use it.
  986. /PDFPageList where {
  987. pop
  988. pop pop % don't use dummy parameters
  989. PDFPageList
  990. % process the ranges (3 elements per range)
  991. 0 3 2 index length 1 sub {
  992. 1 index 1 index get % even = 2, odd = 1 any = 0
  993. 2 index 2 index 1 add get % start of range
  994. exch
  995. 3 index 3 index 2 add get % end of range
  996. exch
  997. % stack: start end even/odd
  998. 0 eq { 1 } { 2 } ifelse
  999. 2 index 2 index gt { neg } if % negate increment for reverse range
  1000. exch
  1001. {
  1002. pdfgetpage
  1003. dup //null ne {
  1004. pdfshowpage
  1005. } {
  1006. PDFSTOPONERROR {
  1007. /dopdfpages cvx /syntaxerror signalerror
  1008. } {
  1009. pop pop
  1010. ( **** Error: page) newpdf_pdfformaterror
  1011. ( not found.\n) newpdf_pdfformaterror
  1012. } ifelse
  1013. } ifelse
  1014. } for
  1015. pop % for loop index
  1016. } for
  1017. pop % done with array
  1018. } {
  1019. % else, Process the pages given by the FirstPage, LastPage
  1020. 1 exch
  1021. {
  1022. pdfgetpage
  1023. dup //null ne {
  1024. pdfshowpage
  1025. } {
  1026. PDFSTOPONERROR {
  1027. /dopdfpages cvx /syntaxerror signalerror
  1028. } {
  1029. pop pop
  1030. ( **** Error: page) newpdf_pdfformaterror
  1031. ( not found.\n) newpdf_pdfformaterror
  1032. } ifelse
  1033. } ifelse
  1034. } for
  1035. } ifelse
  1036. //EnablePageHandlerDevice exec
  1037. } .internalbind def
  1038. /.runps /run load def
  1039. /run {
  1040. dup type /filetype ne { (r) file } if
  1041. % skip leading whitespace characters (actually anything less than or equal to <sp>)
  1042. { dup ( ) .peekstring not { //false exit } if
  1043. dup 0 get 32 le { pop dup read pop pop } { //true exit } ifelse
  1044. } loop
  1045. exch pop
  1046. {
  1047. % Appletalk PAP sends short strings with %! header expecting a response.
  1048. % 'gv' swallows the %!PS line, then sends DSC comments beginning with %%
  1049. % and also waits for a response. The following avoids those hangs.
  1050. dup 2 string .peekstring pop dup (%!) eq exch (%%) eq or {
  1051. cvx .runps
  1052. } {
  1053. dup 1023 string .peekstring pop
  1054. % "1024 string" exceeds current %stdin buffer
  1055. % Valid PDF file cannot be smaller than 400 bytes.
  1056. (%PDF-) search {
  1057. 3 1 roll pop pop
  1058. dup (%!PS) search not {
  1059. length 0 ne {
  1060. 1 index exch readstring pop pop
  1061. (%stderr) (w) file dup
  1062. ( **** Warning: File has some garbage before %PDF- .\n)
  1063. writestring flushfile
  1064. PDFSTOPONWARNING {
  1065. /run cvx /unregistered signalerror
  1066. } if
  1067. } {
  1068. pop
  1069. } ifelse
  1070. dup (%stdin) (r) file eq {
  1071. % Copy PDF from stdin to temporary file then run it.
  1072. //null (w+) /.tempfile .systemvar exec exch 3 1 roll
  1073. % stack: tempname stdin tempfile
  1074. 64000 string
  1075. {
  1076. % stack: tempname stdin tempfile string
  1077. 2 index 1 index readstring
  1078. exch 3 index exch writestring
  1079. not { exit } if
  1080. }
  1081. loop
  1082. pop exch closefile
  1083. % stack: tempname tempfile
  1084. dup 0 setfileposition
  1085. dup
  1086. pdfavailable {
  1087. runpdf
  1088. }{
  1089. closefile
  1090. (%stderr) (w) file ( **** ERROR: No PDF interpreter available, unable to process PDF files as input.\n)writestring
  1091. } ifelse
  1092. closefile deletefile
  1093. } {
  1094. pdfavailable {
  1095. runpdf
  1096. }{
  1097. closefile
  1098. (%stderr) (w) file ( **** ERROR: No PDF interpreter available, unable to process PDF files as input.\n)writestring
  1099. } ifelse
  1100. } ifelse
  1101. } {
  1102. pop pop pop pop cvx .runps % (%!PS) found first
  1103. } ifelse
  1104. } {
  1105. pop cvx .runps % (%PDF-) not found
  1106. } ifelse
  1107. } ifelse
  1108. } {
  1109. closefile % file was empty
  1110. } ifelse
  1111. } .internalbind odef
  1112. currentdict /runpdfstring .undef
  1113. currentdict /DisablePageHandlerDevice undef
  1114. currentdict /EnablePageHandlerDevice undef
  1115. % Copy stream to an external temporary file and
  1116. % return the file name as PS name.
  1117. /copy_embedded_file {
  1118. //true resolvestream % strm
  1119. dup 1023 string .peekstring pop % "1024 string" exceeds current %stdin buffer
  1120. dup length 400 ge { % Valid PDF file cannot be smaller than 400 bytes.
  1121. (%PDF-) search {
  1122. pop pop pop //true
  1123. } {
  1124. pop //false
  1125. } ifelse
  1126. } {
  1127. pop //false
  1128. } ifelse {
  1129. //null (w) /.tempfile % strm (name) null (w) /.tempfile
  1130. .systemvar exec % strm (name) file
  1131. 3 -1 roll % (name) file strm
  1132. 32768 string % (name) file strm (buf)
  1133. { 3 copy readstring % (name) file strm (buf) file (data) bool
  1134. 3 1 roll % (name) file strm (buf) bool file (data)
  1135. writestring % (name) file strm (buf) bool
  1136. not { exit } if
  1137. } loop
  1138. pop closefile % (name) file
  1139. closefile % (name)
  1140. cvn % /name
  1141. } {
  1142. closefile
  1143. } ifelse
  1144. } .internalbind def
  1145. % Recursively enumerate /Names entries
  1146. % <node> pdf_collection_names /temp_file_name ...
  1147. /pdf_collection_names {
  1148. dup /Names knownoget {
  1149. exch pop
  1150. { oforce
  1151. dup type /dicttype eq {
  1152. /EF knownoget {
  1153. /F knownoget {
  1154. copy_embedded_file
  1155. } if
  1156. } if
  1157. } {
  1158. pop
  1159. } ifelse
  1160. } forall
  1161. } {
  1162. /Kids knownoget {
  1163. { oforce
  1164. dup //null ne {
  1165. pdf_collection_names
  1166. } {
  1167. pop
  1168. } ifelse
  1169. } forall
  1170. } if
  1171. } ifelse
  1172. } .internalbind def
  1173. /runpdf { % <file> runpdf -
  1174. dup type /filetype eq
  1175. {
  1176. dup
  1177. PDFSTOPONERROR
  1178. {
  1179. newpdf_runpdf
  1180. }
  1181. {
  1182. {newpdf_runpdf} stopped
  1183. {
  1184. ( **** Error: PDF interpreter encountered an error processing the file.\n) pdfformaterror
  1185. } if
  1186. }ifelse
  1187. closefile
  1188. }
  1189. {
  1190. ( **** Error: Attempt to process something other than a file object in runpdf.\n) pdfformaterror
  1191. } ifelse
  1192. } .internalbind odef
  1193. end % systemdict
  1194. % Redefine the procedure that the C code uses for running piped input.
  1195. % It is OK to use { (%stdin) run } here, because a startjob cannot occur.
  1196. /.runstdin {
  1197. { (%stdin) run } execute0
  1198. } .internalbind def
  1199. end % userdict
  1200. % ------ Transparency support ------ %
  1201. systemdict /ALLOWPSTRANSPARENCY get
  1202. {
  1203. /.setopacityalpha
  1204. {
  1205. /.setfillconstantalpha where
  1206. {
  1207. pop
  1208. ( **** WARNING: .setopacityalpha is deprecated (as of 9.53.0) and will be removed in a future release\n) print
  1209. ( **** See .setfillconstantalpha/.setalphaisshape for the improved solution\n) print flush
  1210. false .setalphaisshape
  1211. dup .setfillconstantalpha
  1212. .setstrokeconstantalpha
  1213. }
  1214. {
  1215. /.setopacityalpha /undefined cvx signalerror
  1216. } ifelse
  1217. } .internalbind def
  1218. /.setshapealpha
  1219. {
  1220. /.setfillconstantalpha where
  1221. {
  1222. pop
  1223. ( **** WARNING: .setshapealpha is deprecated (as of 9.53.0) and will be removed in a future release.\n) print
  1224. ( **** See .setfillconstantalpha/.setalphaisshape for the improved solution\n) print flush
  1225. true .setalphaisshape
  1226. dup .setfillconstantalpha
  1227. .setstrokeconstantalpha
  1228. }
  1229. {
  1230. /.setshapealpha /undefined cvx signalerror
  1231. } ifelse
  1232. } .internalbind def
  1233. } if
  1234. .setglobal
  1235. %% This list of operators are used internally by various parts of the Ghostscript PDF interpreter.
  1236. %% Since each operator is a potential security vulnerability, and any operator listed here
  1237. %% is not required once the initislisation is complete and functions are bound, we undefine
  1238. %% the ones that aren't needed at runtime.
  1239. [
  1240. /.setdistillerparams
  1241. ] systemdict .undefinternalnames
  1242. % The following are split out allowing control via ALLOWPSTRANSPARENCY command line param
  1243. % The examples/transparency_example.ps uses some of these (on the first line).
  1244. [
  1245. /.pushpdf14devicefilter /.poppdf14devicefilter /.setstrokeconstantalpha /.setfillconstantalpha /.endtransparencygroup
  1246. /.currentblendmode /.currenttextknockout /.begintransparencytextgroup
  1247. /.endtransparencytextgroup /.begintransparencymaskgroup /.begintransparencymaskimage /.begintransparencypagegroup
  1248. /.endtransparencymask /.image3x /.abortpdf14devicefilter /.setstrokeconstantalpha /.setfillconstantalpha /.setalphaisshape /.currentalphaisshape
  1249. % undefining these causes errors/incorrect output
  1250. %/.setblendmode /.begintransparencygroup /.settextknockout /.setstrokeoverprint /.setfilloverprint
  1251. %/.currentstrokeoverprint /.currentfilloverprint /.currentfillconstantalpha /.currentstrokeconstantalpha
  1252. %/.setSMask /.currentSMask
  1253. ] systemdict dup /ALLOWPSTRANSPARENCY get {pop pop}{.undefinternalnames}ifelse