星火微课系统客户端
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.

gs_setpd.ps 29KB

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