gs_setpd.ps 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863
  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: gs_setpd.ps,v 1.27 2005/06/09 19:47:18 ray Exp $
  16. % The current implementation of setpagedevice has the following limitations:
  17. % - It doesn't attempt to "interact with the user" for Policy = 2.
  18. languagelevel 1 .setlanguagelevel
  19. level2dict begin
  20. % ---------------- Redefinitions ---------------- %
  21. % Redefine .beginpage and .endpage so that they call BeginPage and
  22. % EndPage respectively if appropriate.
  23. % We have to guard against the BeginPage procedure not popping its operand.
  24. % This is really stupid, but the Genoa CET does it.
  25. /.beginpage { % - .beginpage -
  26. .currentshowpagecount {
  27. .currentpagedevice pop
  28. dup //null ne { /BeginPage .knownget } { pop //false } ifelse {
  29. % Stack: ... pagecount proc
  30. count 2 .execn
  31. % Stack: ... ..???.. oldcount
  32. count 1 add exch sub { pop } repeat
  33. } {
  34. pop
  35. } ifelse
  36. } if
  37. } bind odef
  38. % Guard similarly against EndPage not popping its operand.
  39. /.endpage { % <reason> .endpage <print_bool>
  40. .currentshowpagecount {
  41. 1 index .currentpagedevice pop
  42. dup //null ne { /EndPage .knownget } { pop //false } ifelse {
  43. % Stack: ... reason pagecount reason proc
  44. count 2 .execn
  45. % Stack: ... ..???.. print oldcount
  46. count 2 add exch sub { exch pop } repeat
  47. } {
  48. pop pop 2 ne
  49. } ifelse
  50. } {
  51. 2 ne
  52. } ifelse
  53. } bind odef
  54. % Define interpreter callouts for handling gstate-saving operators,
  55. % to make sure that they create a page device dictionary for use by
  56. % the corresponding gstate-restoring operator.
  57. % We'd really like to avoid the cost of doing this, but we don't see how.
  58. % The names %gsavepagedevice, %savepagedevice, %gstatepagedevice,
  59. % %copygstatepagedevice, and %currentgstatepagedevice are known to the
  60. % interpreter.
  61. (%gsavepagedevice) cvn
  62. { currentpagedevice pop gsave
  63. } bind def
  64. (%savepagedevice) cvn
  65. { currentpagedevice pop save
  66. } bind def
  67. (%gstatepagedevice) cvn
  68. { currentpagedevice pop gstate
  69. } bind def
  70. (%copygstatepagedevice) cvn
  71. { currentpagedevice pop copy
  72. } bind def
  73. (%currentgstatepagedevice) cvn
  74. { currentpagedevice pop currentgstate
  75. } bind def
  76. % Define interpreter callouts for handling gstate-restoring operators
  77. % when the current page device needs to be changed.
  78. % The names %grestorepagedevice, %grestoreallpagedevice,
  79. % %restorepagedevice, %restore1pagedevice, and %setgstatepagedevice
  80. % are known to the interpreter.
  81. /.installpagedevice
  82. { % Since setpagedevice doesn't create new device objects,
  83. % we must (carefully) reinstall the old parameters in
  84. % the same device.
  85. .currentpagedevice pop //null currentdevice //null .trysetparams
  86. dup type /booleantype eq
  87. { pop pop }
  88. { % This should never happen!
  89. SETPDDEBUG { (Error in .trysetparams!) = pstack flush } if
  90. cleartomark pop pop pop
  91. /.installpagedevice cvx /rangecheck signalerror
  92. }
  93. ifelse pop pop
  94. % A careful reading of the Red Book reveals that an erasepage
  95. % should occur, but *not* an initgraphics.
  96. erasepage .beginpage
  97. } bind def
  98. /.uninstallpagedevice
  99. { 2 .endpage { .currentnumcopies //false .outputpage } if
  100. nulldevice
  101. } bind def
  102. (%grestorepagedevice) cvn
  103. { .uninstallpagedevice grestore .installpagedevice
  104. } bind def
  105. (%grestoreallpagedevice) cvn
  106. { .uninstallpagedevice grestore .installpagedevice grestoreall
  107. } bind def
  108. (%restore1pagedevice) cvn
  109. { .uninstallpagedevice grestore .installpagedevice restore
  110. } bind def
  111. (%restorepagedevice) cvn
  112. { .uninstallpagedevice restore .installpagedevice
  113. } bind def
  114. (%setgstatepagedevice) cvn
  115. { .uninstallpagedevice setgstate .installpagedevice
  116. } bind def
  117. % Redefine .currentnumcopies so it consults the NumCopies device parameter.
  118. /.numcopiesdict mark
  119. /NumCopies dup
  120. .dicttomark readonly def
  121. /.currentnumcopies
  122. { currentdevice //.numcopiesdict .getdeviceparams
  123. dup type /integertype eq
  124. { exch pop exch pop }
  125. { cleartomark #copies }
  126. ifelse
  127. } bind odef
  128. % Redefine .currentpagedevice and .setpagedevice so they convert between
  129. % null and a fixed empty directionary.
  130. /.nullpagedevice 0 dict readonly def
  131. /.currentpagedevice {
  132. //.currentpagedevice exch dup //null eq { pop //.nullpagedevice } if exch
  133. } bind odef
  134. /.setpagedevice {
  135. dup //.nullpagedevice eq { pop //null } if //.setpagedevice
  136. } bind odef
  137. % ---------------- Auxiliary definitions ---------------- %
  138. % Define the required attributes of all page devices, and their default values.
  139. % We don't include attributes such as .MediaSize, which all devices
  140. % are guaranteed to supply on their own.
  141. /.defaultpolicies mark
  142. /PolicyNotFound 1
  143. /PageSize 0
  144. /PolicyReport {
  145. dup /.LockSafetyParams known {
  146. % Only possible error is invalidaccess
  147. /setpagedevice .systemvar /invalidaccess signalerror
  148. }
  149. if
  150. pop
  151. } bind
  152. .dicttomark readonly def
  153. % Note that the values of .requiredattrs are executed, not just fetched.
  154. /.requiredattrs mark
  155. /PageDeviceName //null
  156. /PageOffset [0 0] readonly
  157. % We populate InputAttributes with all of the known page sizes
  158. % followed by a dummy media type that handles pages of any size.
  159. % This will create some duplicates, but that only slightly slows
  160. % down the media selection (loop is in zmedia2.c).
  161. %
  162. % Some PostScript creators assume that slot 0 is the default media
  163. % size and some can't handle a non-standard 4-element array which
  164. % is a 'range' type page size (always put last).
  165. %
  166. % Real Devices that can only handle specific page sizes will override this.
  167. /InputAttributes {
  168. mark
  169. % First put the device's default page size in slot 0
  170. % This satifies those that have devices built with a4 as the default
  171. 0 mark /PageSize currentdevice /PageSize gsgetdeviceprop .dicttomark
  172. statusdict /.pagetypenames get {
  173. counttomark 1 sub 2 idiv exch mark exch /PageSize exch
  174. % stack: mark --dict-- --dict-- ... key mark /PageSize pagetypename
  175. % see note above about pagetype executable array contents.
  176. load dup 0 get exch 1 get 2 array astore .dicttomark
  177. } forall
  178. % If NORANGEPAGESIZE is defined, (-dNORANGEPAGESIZE), then don't add
  179. % the 'match any' PageSize entry
  180. systemdict /NORANGEPAGESIZE known not {
  181. % Add one last entry which is the 4 element range array (non-standard)
  182. counttomark 2 idiv
  183. % PageSize with either dimension 0 will be detected in
  184. % match_page_size, so we can allow it here
  185. mark /PageSize [0 dup 16#7ffff dup] .dicttomark
  186. } if
  187. .dicttomark
  188. }
  189. (%MediaSource) 0
  190. /OutputAttributes {
  191. mark 0 mark .dicttomark readonly .dicttomark
  192. }
  193. (%MediaDestination) 0
  194. /Install {{.callinstall}} bind
  195. /BeginPage {{.callbeginpage}} bind
  196. /EndPage {{.callendpage}} bind
  197. /Policies .defaultpolicies
  198. /ImagingBBox //null % default value
  199. /UseCIEColor /.getuseciecolor load
  200. .dicttomark readonly def
  201. % Define currentpagedevice so it creates the dictionary on demand if needed,
  202. % adding all the required entries defined just above.
  203. % We have to deal specially with entries that the driver may change
  204. % on its own.
  205. /.dynamicppkeys mark
  206. /.MediaSize dup % because it changes when PageSize is set
  207. /PageCount dup
  208. /Colors dup
  209. /BitsPerPixel dup
  210. /ColorValues dup
  211. .dicttomark readonly def
  212. /.makecurrentpagedevice { % - .makecurrentpagedevice <dict>
  213. currentdevice //null .getdeviceparams
  214. % Make the dictionary large enough to add defaulted entries.
  215. counttomark 2 idiv .requiredattrs length add dict
  216. counttomark 2 idiv { dup 4 2 roll put } repeat exch pop
  217. % Add any missing required attributes.
  218. % Make a writable and (if possible) local copy of any default
  219. % dictionaries, to work around a bug in the output of WordPerfect,
  220. % which assumes that these dictionaries are writable and local.
  221. .currentglobal exch dup gcheck .setglobal
  222. .requiredattrs {
  223. 2 index 2 index known {
  224. 1 index /Policies eq {
  225. % Merge policies from the device driver with defaults
  226. 2 index % <<>> /key value <<>>
  227. 3 2 roll get % <<>> value <<policies>>
  228. exch {
  229. 2 index 2 index known {
  230. pop pop
  231. } {
  232. 2 index 3 1 roll put
  233. } ifelse
  234. } forall
  235. pop
  236. } {
  237. pop pop
  238. } ifelse
  239. } {
  240. exec 2 index 3 1 roll put
  241. } ifelse
  242. } forall exch .setglobal
  243. dup .setpagedevice
  244. } bind def
  245. /currentpagedevice {
  246. .currentpagedevice {
  247. dup length 0 eq {
  248. pop .makecurrentpagedevice
  249. } {
  250. % If any of the dynamic keys have changed,
  251. % we must update the page device dictionary.
  252. currentdevice //.dynamicppkeys .getdeviceparams .dicttomark {
  253. % Stack: current key value
  254. 2 index 2 index .knownget { 1 index ne } { //true } ifelse
  255. { 2 index wcheck not
  256. { % This is the first entry being updated.
  257. % Copy the dictionary to make it writable.
  258. 3 -1 roll
  259. currentglobal 1 index dup gcheck currentglobal and setglobal
  260. length dict
  261. exch setglobal
  262. .copydict
  263. 3 1 roll
  264. }
  265. if
  266. 2 index 3 1 roll put
  267. }
  268. { pop pop
  269. }
  270. ifelse
  271. } forall
  272. % If the device is the distiller device, update distillerparams that
  273. % may have been changed by setdistillerparams
  274. currentdevice .devicename /pdfwrite eq {
  275. currentdistillerparams {
  276. % Stack: current key value
  277. 2 index 2 index .knownget { 1 index ne } { //true } ifelse
  278. { 2 index 3 1 roll put } { pop pop } ifelse
  279. } forall
  280. } if
  281. % If the dictionary was global and is now local, copy
  282. % any global subsidiary dictionaries to local VM. This
  283. % too is to work around the Word Perfect bug (see above).
  284. dup gcheck not {
  285. dup {
  286. dup type /dicttype eq { dup gcheck } { //false } ifelse {
  287. % Copy-on-write, see above.
  288. 2 index wcheck not {
  289. 3 -1 roll dup length dict .copydict
  290. 3 1 roll
  291. } if
  292. .copytree 2 index 3 1 roll put
  293. } {
  294. pop pop
  295. } ifelse
  296. } forall
  297. } if
  298. % We would like to do a .setpagedevice so we don't keep
  299. % re-creating the dictionary. Unfortunately, the effect
  300. % of this is that if any dynamic key changes (PageCount
  301. % in particular), we will do the equivalent of a
  302. % setpagedevice at the next restore or grestore.
  303. % Therefore, we make the dictionary read-only, but
  304. % we don't store it away. I.e., NOT:
  305. % dup wcheck { .setpagedevice .currentpagedevice pop } if
  306. readonly
  307. } ifelse
  308. } if
  309. } bind odef
  310. % Copy a dictionary recursively.
  311. /.copytree { % <dict> .copytree <dict'>
  312. dup length dict exch {
  313. dup type /dicttype eq { .copytree } if 2 index 3 1 roll put
  314. } forall
  315. } bind def
  316. % The implementation of setpagedevice is quite complex. Currently,
  317. % everything but the media matching algorithm is implemented here.
  318. % By default, we only present the requested changes to the device,
  319. % but there are some parameters that require special merging action.
  320. % Define those parameters here, with the procedures that do the merging.
  321. % The procedures are called as follows:
  322. % <merged> <key> <new_value> -proc- <merged> <key> <new_value'>
  323. /.mergespecial mark
  324. /InputAttributes
  325. { dup //null eq
  326. { pop //null
  327. }
  328. { 3 copy pop .knownget
  329. { dup //null eq
  330. { pop dup length dict }
  331. { dup length 2 index length add dict .copydict }
  332. ifelse
  333. }
  334. { dup length dict
  335. }
  336. ifelse .copydict readonly
  337. }
  338. ifelse
  339. } bind
  340. /OutputAttributes 1 index
  341. /Policies
  342. { 3 copy pop .knownget
  343. { dup length 2 index length add dict .copydict }
  344. { dup length dict }
  345. ifelse copy readonly
  346. } bind
  347. .dicttomark readonly def
  348. % Define the keys used in input attribute matching.
  349. /.inputattrkeys [
  350. /PageSize /MediaColor /MediaWeight /MediaType /InsertSheet /ManualFeed
  351. % The following are documented in Adobe's supplement for v2017.
  352. /LeadingEdge /MediaClass
  353. ] readonly def
  354. % Define other keys used in media selection.
  355. /.inputselectionkeys [
  356. /MediaPosition /Orientation
  357. ] readonly def
  358. % Define the keys used in output attribute matching.
  359. /.outputattrkeys [
  360. /OutputType
  361. ] readonly def
  362. % Define all the parameters that should always be copied to the merged
  363. % dictionary.
  364. /.copiedkeys [
  365. /OutputDevice
  366. .mergespecial { pop } forall
  367. .inputattrkeys aload pop
  368. .inputselectionkeys aload pop
  369. .outputattrkeys aload pop
  370. ] readonly def
  371. % Define the parameters that should not be presented to the device.
  372. % The procedures are called as follows:
  373. % <merged> <key> <value> -proc-
  374. % The procedure leaves all its operands on the stack and returns
  375. % true iff the key/value pair should be presented to .putdeviceparams.
  376. /.presentspecial mark
  377. .dynamicppkeys { pop //false } forall
  378. % We must ignore an explicit request for .MediaSize,
  379. % because media matching always handles this.
  380. /.MediaSize //false
  381. /Name //false
  382. /OutputDevice //false
  383. /PageDeviceName //false
  384. /PageOffset //false
  385. /PageSize //false % obsolete alias for .MediaSize
  386. /InputAttributes //false
  387. .inputattrkeys
  388. { dup /PageSize eq
  389. { pop }
  390. { { 2 index /InputAttributes .knownget { //null eq } { //true } ifelse } }
  391. ifelse
  392. }
  393. forall
  394. .inputselectionkeys { //false } forall
  395. /OutputAttributes //false
  396. .outputattrkeys
  397. { { 2 index /OutputAttributes .knownget { //null eq } { //true } ifelse } }
  398. forall
  399. /Install //false
  400. /BeginPage //false
  401. /EndPage //false
  402. /Policies //false
  403. % Our extensions:
  404. /HWColorMap
  405. { % HACK: don't transmit the color map, because
  406. % window systems can change the color map on their own
  407. % incrementally. Someday we'll have a better
  408. % solution for this....
  409. //false
  410. }
  411. /ViewerPreProcess //false
  412. /ImagingBBox //false % This prevents the ImagingBBox value in the setpagedevice
  413. % from affecting the device's ImagingBBox parameter, but
  414. % does retain a 'shadow' copy at the PostScript level.
  415. % This is done for Adobe compatibility since Adobe does
  416. % render marks outside the ImagingBBox (and QuarkXpress
  417. % relies on it).
  418. .dicttomark readonly def
  419. % Define access to device defaults.
  420. /.defaultdeviceparams
  421. { finddevice //null .getdeviceparams
  422. } bind def
  423. % Select media (input or output). The hard work is done in an operator:
  424. % <pagedict> <attrdict> <policydict> <keys> .matchmedia <key> true
  425. % <pagedict> <attrdict> <policydict> <keys> .matchmedia false
  426. % <pagedict> null <policydict> <keys> .matchmedia null true
  427. /.selectmedia % <orig> <request> <merged> <failed> <-- retained
  428. % <attrdict> <policydict> <attrkeys> <mediakey>
  429. % .selectmedia
  430. { 5 index 5 -2 roll 4 index .matchmedia
  431. % Stack: orig request merged failed attrkeys mediakey
  432. % (key true | false)
  433. { 4 index 3 1 roll put pop
  434. }
  435. { % Adobe's implementations have a "big hairy heuristic"
  436. % to choose the set of keys to report as having failed the match.
  437. % For the moment, we report any keys that are in the request
  438. % and don't have the same value as in the original dictionary.
  439. 5 index 1 index .knownget
  440. { 4 index 3 1 roll put }
  441. { 3 index exch .undef }
  442. ifelse
  443. { % Stack: <orig> <request> <merged> <failed> <attrkey>
  444. 3 index 1 index .knownget
  445. { 5 index 2 index .knownget { ne } { pop //true } ifelse }
  446. { //true }
  447. ifelse % Stack: ... <failed> <attrkey> <report>
  448. { 2 copy /rangecheck put }
  449. if pop
  450. }
  451. forall
  452. }
  453. ifelse
  454. } bind def
  455. % Apply Policies to any unprocessed failed requests.
  456. % As we process each request entry, we replace the error name
  457. % in the <failed> dictionary with the policy value,
  458. % and we replace the key in the <merged> dictionary with its prior value
  459. % (or remove it if it had no prior value).
  460. /.policyprocs mark
  461. % These procedures are called with the following on the stack:
  462. % <orig> <merged> <failed> <Policies> <key> <policy>
  463. % They are expected to consume the top 2 operands.
  464. % NOTE: we currently treat all values other than 0, 1, or 7 (for PageSize)
  465. % the same as 0, i.e., we signal an error.
  466. 0 { % Set errorinfo and signal a configurationerror.
  467. pop dup 4 index exch get 2 array astore
  468. $error /errorinfo 3 -1 roll put
  469. cleartomark
  470. /setpagedevice load /configurationerror signalerror
  471. } bind
  472. 1 { % Roll back the failed request to its previous status.
  473. SETPDDEBUG { (Rolling back.) = pstack flush } if
  474. 3 index 2 index 3 -1 roll put
  475. 4 index 1 index .knownget
  476. { 4 index 3 1 roll put }
  477. { 3 index exch .undef }
  478. ifelse
  479. } bind
  480. 7 { % For PageSize only, just impose the request.
  481. 1 index /PageSize eq
  482. { pop pop 1 index /PageSize 7 put }
  483. { .policyprocs 0 get exec }
  484. ifelse
  485. } bind
  486. .dicttomark readonly def
  487. /.applypolicies % <orig> <merged> <failed> .applypolicies
  488. % <orig> <merged'> <failed'>
  489. { 1 index /Policies get 1 index
  490. { type /integertype eq
  491. { pop % already processed
  492. }
  493. { 2 copy .knownget not { 1 index /PolicyNotFound get } if
  494. % Stack: <orig> <merged> <failed> <Policies> <key>
  495. % <policy>
  496. .policyprocs 1 index .knownget not { .policyprocs 0 get } if exec
  497. }
  498. ifelse
  499. }
  500. forall pop
  501. } bind def
  502. % Prepare to present parameters to the device, by spreading them onto the
  503. % operand stack and removing any that shouldn't be presented.
  504. /.prepareparams % <params> .prepareparams -mark- <key1> <value1> ...
  505. { mark exch dup
  506. { % Stack: -mark- key1 value1 ... merged key value
  507. .presentspecial 2 index .knownget
  508. { exec { 3 -1 roll } { pop pop } ifelse }
  509. { 3 -1 roll }
  510. ifelse
  511. }
  512. forall pop
  513. } bind def
  514. % Put device parameters without resetting currentpagedevice.
  515. % (.putdeviceparams clears the current page device.)
  516. /.putdeviceparamsonly % <device> <Policies|null> <require_all> -mark-
  517. % <key1> <value1> ... .putdeviceparamsonly
  518. % On success: <device> <eraseflag>
  519. % On failure: <device> <Policies|null> <req_all> -mark-
  520. % <key1> <error1> ...
  521. { .currentpagedevice
  522. { counttomark 4 add 1 roll .putdeviceparams
  523. dup type /booleantype eq { 3 } { counttomark 5 add } ifelse -1 roll
  524. .setpagedevice
  525. }
  526. { pop .putdeviceparams
  527. }
  528. ifelse
  529. } bind def
  530. % Try setting the device parameters from the merged request.
  531. /.trysetparams % <merged> <(ignored)> <device> <Policies>
  532. % .trysetparams
  533. { //true 4 index .prepareparams
  534. % Add the computed .MediaSize.
  535. % Stack: merged (ignored) device Policies -true-
  536. % -mark- key1 value1 ...
  537. counttomark 5 add index .computemediasize
  538. exch pop exch pop /.MediaSize exch
  539. SETPDDEBUG { (Putting.) = pstack flush } if
  540. .putdeviceparamsonly
  541. SETPDDEBUG { (Result of putting.) = pstack flush } if
  542. } bind def
  543. % Compute the media size and initial matrix from a merged request (after
  544. % media selection).
  545. /.computemediasize % <request> .computemediasize
  546. % <request> <matrix> <[width height]>
  547. { dup /PageSize get % requested page size
  548. 1 index /InputAttributes get
  549. 2 index (%MediaSource) get get /PageSize get % media size
  550. % (may be a range)
  551. 2 index /Policies get
  552. dup /PageSize .knownget
  553. { exch pop } { /PolicyNotFound get } ifelse % PageSize policy,
  554. % affects scaling
  555. 3 index /Orientation .knownget not { //null } if
  556. 4 index /RollFedMedia .knownget not { //false } if
  557. matrix .matchpagesize not {
  558. % This is a "can't happen" condition!
  559. /setpagedevice load /rangecheck signalerror
  560. } if
  561. 2 array astore
  562. } bind def
  563. % ---------------- setpagedevice itself ---------------- %
  564. /setpagedevice
  565. { % We mustn't pop the argument until the very end,
  566. % so that the pseudo-operator machinery can restore the stack
  567. % if an error occurs.
  568. mark 1 index currentpagedevice
  569. % Check whether we are changing OutputDevice;
  570. % also handle the case where the current device
  571. % is not a page device.
  572. % Stack: mark <request> <current>
  573. SETPDDEBUG { (Checking.) = pstack flush } if
  574. dup /OutputDevice .knownget
  575. { % Current device is a page device.
  576. 2 index /OutputDevice .knownget
  577. { % A specific OutputDevice was requested.
  578. 2 copy eq
  579. { pop pop //null }
  580. { exch pop }
  581. ifelse
  582. }
  583. { pop //null
  584. }
  585. ifelse
  586. }
  587. { % Current device is not a page device.
  588. % Use the default device.
  589. 1 index /OutputDevice .knownget not { .defaultdevicename } if
  590. }
  591. ifelse
  592. dup //null eq
  593. { pop
  594. }
  595. { exch pop .defaultdeviceparams
  596. % In case of duplicate keys, .dicttomark takes the entry
  597. % lower on the stack, so we can just append the defaults here.
  598. .requiredattrs { exec } forall .dicttomark
  599. }
  600. ifelse
  601. % Check whether a viewer wants to intervene.
  602. % We must check both the request (which takes precedence)
  603. % and the current dictionary.
  604. % Stack: mark <request> <orig>
  605. exch dup /ViewerPreProcess .knownget
  606. { exec }
  607. { 1 index /ViewerPreProcess .knownget { exec } if }
  608. ifelse exch
  609. % Construct a merged request from the actual request plus
  610. % any keys that should always be propagated.
  611. % Stack: mark <request> <orig>
  612. SETPDDEBUG { (Merging.) = pstack flush } if
  613. exch 1 index length 1 index length add dict
  614. .copiedkeys
  615. { % Stack: <orig> <request> <merged> <key>
  616. 3 index 1 index .knownget { 3 copy put pop } if pop
  617. }
  618. forall
  619. % Stack: <orig> <request> <merged>
  620. dup 2 index
  621. { % stack: <orig> <request> <merged> <merged> <rkey> <rvalue>
  622. .mergespecial 2 index .knownget { exec } if
  623. put dup
  624. }
  625. forall pop
  626. % Hack: if FIXEDRESOLUTION is true, discard any attempt to
  627. % change HWResolution.
  628. FIXEDRESOLUTION { dup /HWResolution .undef } if
  629. % Hack: if FIXEDMEDIA is true, discard any attempt to change
  630. % PageSize or HWSize.
  631. FIXEDMEDIA
  632. { dup /PageSize 4 index /PageSize get put
  633. dup /HWSize 4 index /HWSize get put
  634. } if
  635. % Hack: to work around some files that take a PageSize
  636. % from InputAttributes and impose it, discard any attempt
  637. % to set PageSize to a 4-element value.
  638. % Stack: mark <orig> <request> <merged>
  639. dup /PageSize .knownget {
  640. length 2 ne {
  641. dup /PageSize 4 index /PageSize get put
  642. } if
  643. } if
  644. % Select input and output media.
  645. % Stack: mark <orig> <request> <merged>
  646. SETPDDEBUG { (Selecting.) = pstack flush } if
  647. 0 dict % <failed>
  648. 1 index /InputAttributes .knownget
  649. { 2 index /Policies get
  650. .inputattrkeys (%MediaSource) cvn .selectmedia
  651. } if
  652. 1 index /OutputAttributes .knownget
  653. { 2 index /Policies get
  654. .outputattrkeys (%MediaDestination) cvn .selectmedia
  655. } if
  656. 3 -1 roll 4 1 roll % temporarily swap orig & request
  657. .applypolicies
  658. 3 -1 roll 4 1 roll % swap back
  659. % Construct the new device, and attempt to set its attributes.
  660. % Stack: mark <orig> <request> <merged> <failed>
  661. SETPDDEBUG { (Constructing.) = pstack flush } if
  662. currentdevice .devicename 2 index /OutputDevice get eq
  663. { currentdevice }
  664. { 1 index /OutputDevice get finddevice }
  665. ifelse
  666. %**************** We should copy the device here,
  667. %**************** but since we can't close the old device,
  668. %**************** we don't. This is WRONG.
  669. %****************copydevice
  670. 2 index /Policies get
  671. .trysetparams
  672. dup type /booleantype ne
  673. { % The request failed.
  674. % Stack: ... <orig> <request> <merged> <failed> <device>
  675. % <Policies> true mark <name> <errorname> ...
  676. SETPDDEBUG { (Recovering.) = pstack flush } if
  677. counttomark 4 add index
  678. counttomark 2 idiv { dup 4 -2 roll put } repeat
  679. pop pop pop
  680. % Stack: mark ... <orig> <request> <merged> <failed> <device>
  681. % <Policies>
  682. 6 2 roll 3 -1 roll 4 1 roll
  683. .applypolicies
  684. 3 -1 roll 4 1 roll 6 -2 roll
  685. .trysetparams % shouldn't fail!
  686. dup type /booleantype ne
  687. { 2 { counttomark 1 add 1 roll cleartomark } repeat
  688. /setpagedevice load exch signalerror
  689. }
  690. if
  691. }
  692. if
  693. % The attempt succeeded. Install the new device.
  694. % Stack: mark ... <merged> <failed> <device> <eraseflag>
  695. SETPDDEBUG { (Installing.) = pstack flush } if
  696. pop 2 .endpage
  697. { 1 //true .outputpage
  698. (>>setpagedevice, press <return> to continue<<\n) .confirm
  699. }
  700. if
  701. % .setdevice clears the current page device!
  702. .currentpagedevice pop exch
  703. .setdevice pop
  704. .setpagedevice
  705. % Implement UseCIEColor directly if this is a LL3 system.
  706. % The color substitution feature is now implemented in
  707. % the interpreter, and this is used as an optimization.
  708. %
  709. % NB: This shoud be the only use of the .setuseciecolor
  710. % operator anywhere.
  711. %
  712. % If UseCIEColor is transitioned to false, set some
  713. % color space other than /DeviceGray, to insure that
  714. % initgraphics will actually perform a setcolorspace
  715. % operation (there is an optimization in setcolorspace
  716. % that does nothing if the operand and current color
  717. % spaces are the same, and UseCIEColor is false).
  718. /.setuseciecolor where
  719. {
  720. pop 1 index /UseCIEColor .knownget
  721. {
  722. dup .setuseciecolor not
  723. { /DeviceRGB setcolorspace }
  724. if
  725. }
  726. if
  727. }
  728. if
  729. % Merge the request into the current page device,
  730. % unless we're changing the OutputDevice.
  731. % Stack: mark ... <merged> <failed>
  732. exch currentpagedevice dup length 2 index length add dict
  733. % Stack: mark ... <failed> <merged> <current> <newdict>
  734. 2 index /OutputDevice .knownget {
  735. 2 index /OutputDevice .knownget not { //null } if eq
  736. } {
  737. //true
  738. } ifelse {
  739. % Same OutputDevice, merge the dictionaries.
  740. .copydict
  741. } {
  742. % Different OutputDevice, discard the old dictionary.
  743. exch pop
  744. } ifelse .copydict
  745. % Initialize the default matrix, taking media matching
  746. % into account.
  747. .computemediasize pop initmatrix concat
  748. dup /PageOffset .knownget
  749. { % Translate by the given number of 1/72" units in device X/Y.
  750. dup 0 get exch 1 get
  751. 2 index /HWResolution get dup 1 get exch 0 get
  752. 4 -1 roll mul 72 div 3 1 roll mul 72 div
  753. idtransform translate
  754. }
  755. if
  756. % We must install the new page device dictionary
  757. % before calling the Install procedure.
  758. dup .setpagedevice
  759. .setdefaulthalftone % Set the default screen before calling Install.
  760. dup /Install .knownget {
  761. { .execinstall } stopped { .postinstall stop } { .postinstall } ifelse
  762. } {
  763. .postinstall
  764. } ifelse
  765. } odef
  766. % We break out the code after calling the Install procedure into a
  767. % separate procedure, since it is executed even if Install causes an error.
  768. % By making .execinstall a separate operator procedure, we get the stacks
  769. % restored if it fails.
  770. /.execinstall { % <proc> .execinstall -
  771. % Because the interpreter optimizes tail calls, we can't just let
  772. % the body of this procedure be 'exec', because that would lose
  773. % the stack protection that is the whole reason for having the
  774. % procedure in the first place. We hack this by adding a couple
  775. % of extra tokens to ensure that the operator procedure is still
  776. % on the stack during the exec.
  777. exec
  778. 0 pop % See above.
  779. } odef
  780. /.postinstall { % mark ... <failed> <merged> .postinstall -
  781. matrix currentmatrix .setdefaultmatrix
  782. % Erase and initialize the page.
  783. initgraphics
  784. currentoverprint //false setoverprint 1 setcolor
  785. .fillpage
  786. 0 setcolor setoverprint
  787. .beginpage
  788. % Clean up, calling PolicyReport if needed.
  789. % Stack: mark ... <failed> <merged>
  790. SETPDDEBUG { (Finishing.) = pstack flush } if
  791. exch dup length 0 ne
  792. { 1 index /Policies get /PolicyReport get
  793. counttomark 1 add 2 roll cleartomark
  794. exec
  795. }
  796. { cleartomark
  797. }
  798. ifelse pop
  799. } odef
  800. end % level2dict
  801. .setlanguagelevel