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.

1246 lines
43 KiB

1 month ago
  1. % Copyright (C) 2001-2023 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. % Initialization file for Level 2 functions.
  16. % When this is run, systemdict is still writable,
  17. % but (almost) everything defined here goes into level2dict.
  18. level2dict begin
  19. % ------ System and user parameters ------ %
  20. % User parameters must obey save/restore, and must also be maintained
  21. % per-context. We implement the former, and some of the latter, here
  22. % with PostScript code. NOTE: our implementation assumes that user
  23. % parameters change only as a result of setuserparams -- that there are
  24. % no user parameters that are ever changed dynamically by the interpreter
  25. % (although the interpreter may adjust the value presented to setuserparams)
  26. %
  27. % There are two types of user parameters: those which are actually
  28. % maintained in the interpreter, and those which exist only at the
  29. % PostScript level. We maintain the current state of both types in
  30. % a read-only local dictionary named userparams, defined in systemdict.
  31. % In a multi-context system, each context has its own copy of this
  32. % dictionary. In addition, there is a constant dictionary named
  33. % psuserparams where each key is the name of a user parameter that exists
  34. % only in PostScript and the value is a procedure to check that the value
  35. % is legal: setuserparams uses this for checking the values.
  36. % setuserparams updates userparams explicitly, in addition to setting
  37. % any user parameters in the interpreter; thus we can use userparams
  38. % to reset those parameters after a restore or a context switch.
  39. % NOTE: the name userparams is known to the interpreter, and in fact
  40. % the interpreter creates the userparams dictionary.
  41. % Check parameters that are managed at the PostScript level.
  42. /.checkparamtype { % <newvalue> <type> .checkparamtype <bool>
  43. exch type eq
  44. } .forcebind def
  45. /.checksetparams { % <newdict> <opname> <checkdict>
  46. % .checksetparams <newdict>
  47. 2 .argindex {
  48. % Stack: newdict opname checkdict key newvalue
  49. 3 copy 3 1 roll .knownget {
  50. exec not {
  51. pop pop pop load /typecheck signalerror
  52. } if
  53. dup type /stringtype eq {
  54. dup rcheck not {
  55. pop pop pop load /invalidaccess signalerror
  56. } if
  57. } if
  58. } {
  59. pop
  60. } ifelse pop pop
  61. } forall pop pop
  62. } .forcebind def
  63. % currentuser/systemparams creates and returns a dictionary in the
  64. % current VM. The easiest way to make this work is to copy any composite
  65. % PostScript-level parameters to global VM. Currently we have strings
  66. % as well as arrays. For arrays, we also need to copy any contents that
  67. % are in VM. Also copying string parameters insures the contents won't
  68. % be changed. Also be careful to preserve 'executable' state.
  69. /.copyparam { % <value> .copyparam <value'>
  70. dup type /arraytype eq {
  71. .currentglobal //true .setglobal exch
  72. dup wcheck exch dup xcheck exch % original attributes
  73. dup length array exch dup { % stack: destination_array original_array original_array
  74. dup type /arraytype eq {
  75. dup 2 index ne { % avoid recursion
  76. .copyparam % recurse to handle composite array elements
  77. } {
  78. % this array self referenced, do it again (yuk!)
  79. pop 1 index % get copy of destination array
  80. } ifelse
  81. } {
  82. dup type /stringtype eq {
  83. .copyparam
  84. } if
  85. }
  86. ifelse 3 1 roll % keep arrays on top
  87. } forall pop astore
  88. exch { cvx } if % set executable state
  89. exch not { readonly } if % set readonly attribute as original
  90. exch .setglobal
  91. } if
  92. dup type /stringtype eq {
  93. dup wcheck exch % save attr for setting readonly
  94. .currentglobal //true .setglobal
  95. 1 index length string exch .setglobal
  96. copy exch not { readonly } if
  97. } if
  98. } .forcebind odef
  99. % Some user parameters are managed entirely at the PostScript level.
  100. % We take care of that here.
  101. systemdict begin
  102. /psuserparams 48 dict def
  103. /getuserparam { % <name> getuserparam <value>
  104. /userparams .systemvar 1 .argindex get exch pop
  105. } odef
  106. % Fill in userparams (created by the interpreter) with current values.
  107. mark .currentuserparams
  108. counttomark 2 idiv {
  109. userparams 3 1 roll put
  110. } repeat pop
  111. /.definepsuserparam { % <name> <value> .definepsuserparam -
  112. psuserparams 3 copy pop
  113. type cvlit //.checkparamtype /exec load 3 packedarray cvx put
  114. userparams 3 1 roll put
  115. } .forcebind def
  116. end
  117. /currentuserparams { % - currentuserparams <dict>
  118. /userparams .systemvar dup length dict .copydict
  119. } odef
  120. % We break out setuserparams into a separate procedure so that setvmxxx
  121. % can use it without affecting the command in case of an error.
  122. /.setuserparams2 {
  123. % Check that we will be able to set the PostScript-level
  124. % user parameters.
  125. /setuserparams /psuserparams .systemvar //.checksetparams exec
  126. % Set the C-level user params. If this succeeds, we know that
  127. % the password check succeeded.
  128. dup .setuserparams
  129. % Now set the PostScript-level params.
  130. % The interpreter may have adjusted the values of some of the
  131. % parameters, so we have to read them back.
  132. dup {
  133. /userparams .systemvar 2 index known {
  134. psuserparams 2 index known not {
  135. pop dup .getuserparam
  136. } if
  137. .copyparam
  138. % special protection for the security related parameters
  139. [ /PermitFileReading /PermitFileWriting /PermitFileControl ]
  140. { 2 index eq { % force all strings to readonly but make sure the
  141. % array is in the correct VM space (local/global).
  142. currentglobal exch dup gcheck setglobal
  143. dup length array exch { readonly exch } forall astore
  144. exch setglobal
  145. } if
  146. } forall
  147. % protect top level of parameters that we copied
  148. dup type dup /arraytype eq exch /stringtype eq or { readonly } if
  149. /userparams .systemvar 3 1 roll .forceput % userparams is read-only
  150. } executeonly
  151. {
  152. pop pop
  153. } ifelse
  154. } executeonly forall
  155. % A context switch might have occurred during the above loop,
  156. % causing the interpreter-level parameters to be reset.
  157. % Set them again to the new values. From here on, we are safe,
  158. % since a context switch will consult userparams.
  159. .setuserparams
  160. } .forcebind odef % must be bound and hidden for .forceput
  161. /setuserparams { % <dict> setuserparams -
  162. {.setuserparams2} stopped
  163. {/setuserparams load $error /errorname get signalerror} if
  164. } .forcebind odef
  165. % Initialize user parameters managed here.
  166. /JobName () .definepsuserparam
  167. % Restore must restore the user parameters.
  168. % (Since userparams is in local VM, save takes care of saving them.)
  169. /restore { % <save> restore -
  170. //restore /userparams .systemvar .setuserparams
  171. } .forcebind odef
  172. % The pssystemparams dictionary holds some system parameters that
  173. % are managed entirely at the PostScript level.
  174. systemdict begin
  175. currentdict /pssystemparams known not {
  176. /pssystemparams 40 dict readonly def
  177. } if
  178. /getsystemparam { % <name> getsystemparam <value>
  179. //pssystemparams 1 .argindex .knownget { exch pop } { .getsystemparam } ifelse
  180. } odef
  181. end
  182. /currentsystemparams { % - currentsystemparams <dict>
  183. mark .currentsystemparams //pssystemparams { } forall .dicttomark
  184. } odef
  185. /setsystemparams { % <dict> setsystemparams -
  186. % Check that we will be able to set the PostScript-level
  187. % system parameters.
  188. dup pop % check # of args
  189. /SAFETY .systemvar /safe get {
  190. % SAFER mode disallows some changes
  191. [ /GenericResourceDir /FontResourceDir /GenericResourcePathSep ] {
  192. 2 copy .knownget {
  193. exch //pssystemparams exch .knownget {
  194. ne { /setsystemparams cvx /invalidaccess signalerror } if
  195. } {
  196. pop
  197. } ifelse
  198. } {
  199. pop
  200. } ifelse
  201. } forall
  202. } if
  203. /setsystemparams //pssystemparams mark exch {
  204. type cvlit //.checkparamtype /exec load 3 packedarray cvx
  205. } forall .dicttomark //.checksetparams exec
  206. % Set the C-level system params. If this succeeds, we know that
  207. % the password check succeeded.
  208. dup .setsystemparams
  209. % Now set the PostScript-level params. We must copy local strings
  210. % into global VM.
  211. dup
  212. { //pssystemparams 2 index known
  213. { % Stack: key newvalue
  214. .copyparam
  215. % protect top level parameters that we copied
  216. dup type dup /arraytype eq exch /stringtype eq or { readonly } if
  217. //pssystemparams 3 1 roll .forceput % pssystemparams is read-only
  218. } executeonly
  219. { pop pop
  220. }
  221. ifelse
  222. } executeonly
  223. forall pop
  224. } .forcebind odef
  225. % Initialize the passwords.
  226. % NOTE: the names StartJobPassword and SystemParamsPassword are known to
  227. % the interpreter, and must be bound to noaccess strings.
  228. % The length of these strings must be max_password (iutil2.h) + 1.
  229. /StartJobPassword 65 string noaccess def
  230. /SystemParamsPassword 65 string noaccess def
  231. % Redefine cache parameter setting to interact properly with userparams.
  232. /setcachelimit {
  233. { mark /MaxFontItem 2 .argindex .dicttomark setuserparams pop }
  234. stopped
  235. { /setcachelimit .systemvar $error /errorname get signalerror
  236. } if
  237. } .forcebind odef
  238. /setcacheparams {
  239. % The MaxFontCache parameter is a system parameter, which we might
  240. % not be able to set. Fortunately, this doesn't matter, because
  241. % system parameters don't have to be synchronized between this code
  242. % and the VM.
  243. counttomark 1 add copy setcacheparams
  244. currentcacheparams % mark size lower upper
  245. 3 -1 roll pop
  246. /MinFontCompress 3 1 roll
  247. /MaxFontItem exch
  248. .dicttomark { setuserparams cleartomark } stopped {
  249. /setcacheparams .systemvar $error /errorname get signalerror
  250. } if
  251. } .forcebind odef
  252. % Add bogus user and system parameters to satisfy badly written PostScript
  253. % programs that incorrectly assume the existence of all the parameters
  254. % listed in Appendix C of the Red Book. Note that some of these may become
  255. % real parameters later: code near the end of gs_init.ps takes care of
  256. % removing any such parameters from ps{user,system}params.
  257. % psuserparams
  258. /MaxFormItem 100000 .definepsuserparam
  259. /MaxPatternItem 20000 .definepsuserparam
  260. /MaxScreenItem 48000 .definepsuserparam
  261. /MaxUPathItem 0 .definepsuserparam
  262. % File Access Permission parameters
  263. .currentglobal //true .setglobal
  264. /.checkFilePermitparams {
  265. type /arraytype eq {
  266. currentuserparams /LockFilePermissions get {
  267. 5 { pop } repeat /setuserparams cvx /invalidaccess signalerror
  268. }{
  269. % in addition to validating the value, ensure the value is read/only
  270. dup { readonly exch } forall
  271. .currentglobal exch dup gcheck .setglobal length array exch .setglobal
  272. astore readonly
  273. }
  274. ifelse
  275. } {
  276. 5 { pop } repeat /setuserparams cvx /typecheck signalerror
  277. }
  278. ifelse
  279. //true
  280. } .forcebind def
  281. % Initialize the File Permission access control to wide open
  282. % These will only be accessed via current/set userparams.
  283. % Values are a string containing multiple nul terminated path strings
  284. /PermitFileReading dup [ (*) ] .definepsuserparam
  285. psuserparams exch /.checkFilePermitparams load put
  286. /PermitFileWriting dup [ (*) ] .definepsuserparam
  287. psuserparams exch /.checkFilePermitparams load put
  288. /PermitFileControl dup [ (*) ] .definepsuserparam
  289. psuserparams exch /.checkFilePermitparams load put
  290. .setglobal
  291. pssystemparams
  292. dup /CurDisplayList 0 .forceput
  293. dup /CurFormCache 0 .forceput
  294. dup /CurInputDevice () .forceput
  295. dup /CurOutlineCache 0 .forceput
  296. dup /CurOutputDevice () .forceput
  297. dup /CurPatternCache 0 .forceput
  298. dup /CurUPathCache 0 .forceput
  299. dup /CurScreenStorage 0 .forceput
  300. dup /CurSourceList 0 .forceput
  301. dup /DoPrintErrors //false .forceput
  302. dup /JobTimeout 0 .forceput
  303. dup /LicenseID (LN-001) .forceput % bogus
  304. dup /MaxDisplayList 140000 .forceput
  305. dup /MaxFormCache 100000 .forceput
  306. dup /MaxImageBuffer 524288 .forceput
  307. dup /MaxOutlineCache 65000 .forceput
  308. dup /MaxPatternCache 100000 .forceput
  309. dup /MaxUPathCache 300000 .forceput
  310. dup /MaxScreenStorage 84000 .forceput
  311. dup /MaxSourceList 25000 .forceput
  312. dup /PrinterName product .forceput
  313. dup /RamSize 4194304 .forceput
  314. /WaitTimeout 40 .forceput
  315. % Define the procedures for handling comment scanning. The names
  316. % %ProcessComment and %ProcessDSCComment are known to the interpreter.
  317. % These procedures take the file and comment string and file as operands.
  318. /.checkprocesscomment {
  319. dup //null eq {
  320. pop //true
  321. } {
  322. dup xcheck {
  323. type dup /arraytype eq exch /packedarraytype eq or
  324. } {
  325. pop //false
  326. } ifelse
  327. } ifelse
  328. } .forcebind def
  329. /ProcessComment //null .definepsuserparam
  330. psuserparams /ProcessComment {//.checkprocesscomment exec} put
  331. (%ProcessComment) cvn {
  332. /ProcessComment getuserparam
  333. dup //null eq { pop pop pop } { exec } ifelse
  334. } .internalbind def
  335. /ProcessDSCComment //null .definepsuserparam
  336. psuserparams /ProcessDSCComment {//.checkprocesscomment exec} put
  337. /.loadingfont //false def
  338. (%ProcessDSCComment) cvn {
  339. /ProcessDSCComment getuserparam
  340. dup //null eq .loadingfont or { pop pop pop } { exec } ifelse
  341. } .internalbind def
  342. % ------ Miscellaneous ------ %
  343. (<<) cvn % - << -mark-
  344. /mark load def
  345. % (>> is defined primitively.)
  346. /languagelevel 2 def
  347. % When running in Level 2 mode, this interpreter is supposed to be
  348. % compatible with Adobe version 2017.
  349. /version (2017) readonly def
  350. % If binary tokens are supported by this interpreter,
  351. % set an appropriate default binary object format.
  352. /setobjectformat where
  353. { pop
  354. /RealFormat getsystemparam (IEEE) eq { 1 } { 3 } ifelse
  355. /ByteOrder getsystemparam { 1 add } if
  356. setobjectformat
  357. } if
  358. % Aldus Freehand versions 2.x check for the presence of the
  359. % setcolor operator, and if it is missing, substitute a procedure.
  360. % Unfortunately, the procedure takes different parameters from
  361. % the operator. As a result, files produced by this application
  362. % cause an error if the setcolor operator is actually defined
  363. % and 'bind' is ever used. Aldus fixed this bug in Freehand 3.0,
  364. % but there are a lot of files created by the older versions
  365. % still floating around. Therefore, at Adobe's suggestion,
  366. % we implement the following dreadful hack in the 'where' operator:
  367. % If the key is /setcolor, and
  368. % there is a dictionary named FreeHandDict, and
  369. % currentdict is that dictionary,
  370. % then "where" consults only that dictionary and not any other
  371. % dictionaries on the dictionary stack.
  372. .wheredict /setcolor {
  373. /FreeHandDict .where {
  374. /FreeHandDict get currentdict eq {
  375. pop currentdict /setcolor known { currentdict //true } { //false } ifelse
  376. } {
  377. .where
  378. } ifelse
  379. } {
  380. .where
  381. } ifelse
  382. } .internalbind put
  383. % ------ Virtual memory ------ %
  384. /currentglobal % - currentglobal <bool>
  385. /currentshared load def
  386. /gcheck % <obj> gcheck <bool>
  387. /scheck load def
  388. /setglobal % <bool> setglobal -
  389. /setshared load def
  390. % We can make the global dictionaries very small, because they auto-expand.
  391. /globaldict currentdict /shareddict .knownget not { 4 dict } if def
  392. /GlobalFontDirectory SharedFontDirectory def
  393. % VMReclaim and VMThreshold are user parameters.
  394. /setvmthreshold { % <int> setvmthreshold -
  395. mark /VMThreshold 2 .argindex .dicttomark {.setuserparams2} stopped
  396. {pop /setvmthreshold load $error /errorname get signalerror}
  397. {pop} ifelse
  398. } odef
  399. /vmreclaim { % <int> vmreclaim -
  400. dup 0 gt {
  401. dup 2 le 1 index type /integertype eq and {
  402. pop % ignore user requests for vmreclaim
  403. % (reclaim will still happen controlled by vmthreshold)
  404. }
  405. { .vmreclaim } % let internal operator handle error conditions
  406. ifelse
  407. } {
  408. % VMReclaim userparam controls enable/disable GC
  409. mark /VMReclaim 2 index .dicttomark {.setuserparams2} stopped
  410. {pop /vmreclaim load $error /errorname get signalerror}
  411. {pop} ifelse
  412. } ifelse
  413. } .forcebind odef
  414. -1 setvmthreshold
  415. % ------ IODevices ------ %
  416. /.getdevparams where {
  417. pop /currentdevparams { % <iodevice> currentdevparams <dict>
  418. .getdevparams .dicttomark
  419. } odef
  420. } if
  421. /.putdevparams where {
  422. pop /setdevparams { % <iodevice> <dict> setdevparams -
  423. dup type /dicttype ne { /setdevparams .systemvar /typecheck signalerror } if
  424. mark 1 index { } forall counttomark 2 add index
  425. .putdevparams pop pop
  426. } odef
  427. } if
  428. % ------ Job control ------ %
  429. serverdict begin
  430. % We could protect the job information better, but we aren't attempting
  431. % (currently) to protect ourselves against maliciousness.
  432. /.jobsave //null def % top-level save object
  433. /.jobsavelevel 0 def % save depth of job (0 if .jobsave is null,
  434. % 1 otherwise)
  435. /.adminjob //true def % status of current unencapsulated job
  436. end % serverdict
  437. % Because there may be objects on the e-stack created since the job save,
  438. % we have to clear the e-stack before doing the end-of-job restore.
  439. % We do this by executing a 2 .stop, which is caught by the 2 .stopped
  440. % in .runexec; we leave on the o-stack a procedure to execute aftewards.
  441. %
  442. %**************** The definition of startjob is not complete yet, since
  443. % it doesn't reset stdin/stdout.
  444. /.startnewjob { % <exit_bool> <password_level>
  445. % .startnewjob -
  446. serverdict /.jobsave get dup //null eq { pop } { restore } ifelse
  447. exch {
  448. % Unencapsulated job
  449. serverdict /.jobsave //null put
  450. serverdict /.jobsavelevel 0 put
  451. serverdict /.adminjob 3 -1 roll 1 gt put
  452. } {
  453. % Encapsulated job
  454. pop
  455. serverdict /.jobsave save put
  456. serverdict /.jobsavelevel 1 put
  457. .userdict /quit { stop } .forcebind put % CET 28-10 requires a procedure
  458. } ifelse
  459. % Reset the interpreter state.
  460. clear cleardictstack
  461. initgraphics
  462. //false setglobal
  463. } .internalbind def
  464. /.startjob { % <exit_bool> <password> <finish_proc>
  465. % .startjob <ok_bool>
  466. vmstatus pop pop serverdict /.jobsavelevel get eq
  467. 2 .argindex .checkpassword 0 gt and {
  468. exch .checkpassword exch count 3 roll count 3 sub { pop } repeat
  469. cleardictstack
  470. % Reset the e-stack back to the 2 .stopped in .runexec,
  471. % passing the finish_proc to be executed afterwards.
  472. 2 .stop
  473. } { % Password check failed
  474. pop pop pop //false
  475. } ifelse
  476. } odef
  477. /startjob { % <exit_bool> <password> startjob <ok_bool>
  478. % This is a hack. We really need some way to indicate explicitly
  479. % to the interpreter that we are under control of a job server.
  480. 1 .argindex type /booleantype ne {
  481. /startjob .systemvar /typecheck signalerror
  482. } if
  483. { .startnewjob //true } .startjob
  484. } odef
  485. systemdict begin
  486. /quit { % - quit -
  487. //systemdict begin serverdict /.jobsave get //null eq
  488. { end //quit }
  489. { /quit .systemvar /invalidaccess /signalerror load end exec }
  490. ifelse
  491. } .internalbind odef
  492. end
  493. % We would like to define exitserver as a procedure, using the code
  494. % that the Red Book says is equivalent to it. However, since startjob
  495. % resets the exec stack, we can't do this, because control would never
  496. % proceed past the call on startjob if the exitserver is successful.
  497. % Instead, we need to construct exitserver out of pieces of startjob.
  498. serverdict begin
  499. /exitserver { % <password> exitserver -
  500. //true exch { .startnewjob } .startjob not {
  501. /exitserver cvx /invalidaccess signalerror
  502. } if
  503. } .internalbind def
  504. end % serverdict
  505. % ------ Compatibility ------ %
  506. % In Level 2 mode, the following replace the definitions that gs_statd.ps
  507. % installs in statusdict and serverdict.
  508. % Note that statusdict must be allocated in local VM.
  509. % We don't bother with many of these yet.
  510. % convenience function to make a dictionary from an object and a key
  511. /.pair2dict { exch mark 3 1 roll .dicttomark } .internalbind def
  512. currentglobal //false setglobal 25 dict exch setglobal begin
  513. currentsystemparams
  514. % The following do not depend on the presence of setpagedevice.
  515. /buildtime 1 index /BuildTime get def
  516. % Also define /buildtime in systemdict because Adobe does so and some fonts use it as ID
  517. systemdict /buildtime dup load put
  518. /byteorder 1 index /ByteOrder get def
  519. /checkpassword { .checkpassword 0 gt } .internalbind def
  520. dup /DoStartPage known
  521. { /dostartpage { /DoStartPage getsystemparam } .internalbind def
  522. /setdostartpage { /DoStartPage //.pair2dict exec setsystemparams } .internalbind def
  523. } if
  524. dup /StartupMode known
  525. { /dosysstart { /StartupMode getsystemparam 0 ne } .internalbind def
  526. /setdosysstart { { 1 } { 0 } ifelse /StartupMode //.pair2dict exec setsystemparams } .internalbind def
  527. } if
  528. %****** Setting jobname is supposed to set userparams.JobName, too.
  529. /jobname { /JobName getuserparam } .internalbind def
  530. /jobtimeout { /JobTimeout getuserparam } .internalbind def
  531. /ramsize { /RamSize getsystemparam } .internalbind def
  532. /realformat 1 index /RealFormat get def
  533. dup /PrinterName known
  534. { /setprintername { /PrinterName //.pair2dict exec setsystemparams } .internalbind def
  535. } if
  536. /printername
  537. { currentsystemparams /PrinterName .knownget not { () } if exch copy
  538. } .internalbind def
  539. currentuserparams /WaitTimeout known
  540. { /waittimeout { /WaitTimeout getuserparam } .internalbind def
  541. } if
  542. % The following do require setpagedevice.
  543. /.setpagedevice where { pop } { (%END PAGEDEVICE) .skipeof } ifelse
  544. /defaulttimeouts
  545. { currentsystemparams dup
  546. /JobTimeout .knownget not { 0 } if
  547. exch /WaitTimeout .knownget not { 0 } if
  548. currentpagedevice /ManualFeedTimeout .knownget not { 0 } if
  549. } .internalbind def
  550. /margins
  551. { currentpagedevice /Margins .knownget { exch } { [0 0] } ifelse
  552. } .internalbind def
  553. /pagemargin
  554. { currentpagedevice /PageOffset .knownget { 0 get } { 0 } ifelse
  555. } .internalbind def
  556. /pageparams
  557. { currentpagedevice
  558. dup /Orientation .knownget { 1 and ORIENT1 { 1 xor } if } { 0 } ifelse exch
  559. dup /PageSize get aload pop 3 index 0 ne { exch } if 3 2 roll
  560. /PageOffset .knownget { 0 get } { 0 } ifelse 4 -1 roll
  561. } .internalbind def
  562. /setdefaulttimeouts
  563. { exch mark /ManualFeedTimeout 3 -1 roll
  564. /Policies mark /ManualFeedTimeout 1 .dicttomark
  565. .dicttomark setpagedevice
  566. /WaitTimeout exch mark /JobTimeout 5 2 roll .dicttomark setsystemparams
  567. } .internalbind def
  568. /setduplexmode { /Duplex //.pair2dict exec setpagedevice } .internalbind def
  569. /setmargins
  570. { exch 2 array astore /Margins //.pair2dict exec setpagedevice
  571. } .internalbind def
  572. /setpagemargin { 0 2 array astore /PageOffset //.pair2dict exec setpagedevice } .internalbind def
  573. /setpageparams
  574. { mark /PageSize 6 -2 roll
  575. 4 index 1 and ORIENT1 { 1 } { 0 } ifelse ne { exch } if 2 array astore
  576. /Orientation 5 -1 roll ORIENT1 { 1 xor } if
  577. /PageOffset counttomark 2 add -1 roll 0 2 array astore
  578. .dicttomark setpagedevice
  579. } .internalbind def
  580. /setresolution
  581. { count 1 lt { /setresolution cvx /stackunderflow signalerror } if
  582. dup type dup /integertype eq exch /realtype eq or not
  583. {
  584. /setresolution cvx /typecheck signalerror
  585. } if
  586. dup 2 array astore /HWResolution //.pair2dict exec { setpagedevice } stopped {
  587. pop /setresolution cvx $error /errorname get signalerror
  588. } if
  589. } .internalbind def
  590. %END PAGEDEVICE
  591. % The following are not implemented yet.
  592. %manualfeed
  593. %manualfeedtimeout
  594. %pagecount
  595. %pagestackorder
  596. %setpagestackorder
  597. % -------- ICC manager -------- %
  598. % All color management is going
  599. % through ICC flow. We need
  600. % to have the default device
  601. % spaces gray, RGB and CMYK
  602. % defined by ICC profiles
  603. //systemdict /ICCProfilesDir .knownget {
  604. % Set the directory sepcified by the command line option
  605. mark exch /ICCProfilesDir exch .dicttomark .setuserparams2
  606. } {
  607. % First see if the current value is valid so we don't have to guess
  608. mark .currentuserparams .dicttomark /ICCProfilesDir get
  609. (default_gray.icc) concatstrings {status} //.internalstopped exec
  610. {pop //false} if
  611. {
  612. pop pop pop pop % current value was OK. Just clean up stack
  613. } {
  614. % Search for valid (iccprofiles) directory as a sibling to (Resource)
  615. % and set it as a default if found.
  616. LIBPATH {
  617. (Resource) rsearch {
  618. exch pop exch pop (iccprofiles) concatstrings
  619. .file_name_separator concatstrings
  620. dup (default_gray.icc) concatstrings status {
  621. pop pop pop pop
  622. mark exch /ICCProfilesDir exch .dicttomark .setuserparams2
  623. exit
  624. } {
  625. pop
  626. } ifelse
  627. } {
  628. pop
  629. } ifelse
  630. } forall
  631. } ifelse % if currentuserparams ICCProfilesDir
  632. } ifelse % ICCProfilesDir set in systemdict (command line option)
  633. mark % collect dict key value pairs for anything set in systemdict (command line options)
  634. [ /DefaultRGBProfile /DefaultGrayProfile /DefaultCMYKProfile /DeviceNProfile
  635. /NamedProfile /SourceObjectICC /OverrideICC
  636. ]
  637. { dup //systemdict exch .knownget not {
  638. pop % discard keys not in systemdict
  639. } if
  640. } forall
  641. .dicttomark .setuserparams2
  642. pop % currentsystemparams
  643. % Flag the current dictionary so it will be swapped when we
  644. % change language levels. (See zmisc2.c for more information.)
  645. /statusdict currentdict def
  646. currentdict end
  647. currentdict exch /statusdict exch .forceput % statusdict is local, systemdict is global
  648. % The following compatibility operators are in systemdict. They are
  649. % defined here, rather than in gs_init.ps, because they require the
  650. % resource machinery.
  651. /devforall { % <proc> <scratch> devforall -
  652. exch {
  653. 1 index currentdevparams
  654. /Type .knownget { /FileSystem eq } { //false } ifelse
  655. { exec } { pop pop } ifelse
  656. } /exec load 3 packedarray cvx exch
  657. (*) 3 1 roll /IODevice resourceforall
  658. } odef
  659. /devstatus { % <(%disk*%)> devstatus <searchable> <writable>
  660. % <hasNames> <mounted> <removable> <searchOrder>
  661. % <freePages> <size> true
  662. % <string> devstatus false
  663. dup length 5 ge {
  664. dup 0 5 getinterval (%disk) eq {
  665. dup /IODevice resourcestatus {
  666. pop pop dup currentdevparams
  667. dup /Searchable get
  668. exch dup /Writeable get
  669. exch dup /HasNames get
  670. exch dup /Mounted get
  671. exch dup /Removable get
  672. exch dup /SearchOrder get
  673. exch dup /Free get
  674. exch /LogicalSize get
  675. 9 -1 roll pop //true
  676. } {
  677. pop //false
  678. } ifelse
  679. } {
  680. pop //false
  681. } ifelse
  682. } {
  683. pop //false
  684. } ifelse
  685. } odef
  686. % ------ Color spaces ------ %
  687. % gs_res.ps uses these entries in colorspacedict
  688. % to populate the ColorSpaceFamily resource, so we need
  689. % to add the supported spaces.
  690. %
  691. systemdict /colorspacedict get begin
  692. /CIEBasedA [] def
  693. /CIEBasedABC [] def
  694. /DevicePixel [] def
  695. /Indexed [] def
  696. /Pattern [] def
  697. /Separation [] def
  698. end
  699. % ------ CIE color rendering ------ %
  700. % Define findcolorrendering and a default ColorRendering ProcSet.
  701. /findcolorrendering { % <intentname> findcolorrendering
  702. % <crdname> <found>
  703. % Adobe interpreters report /findcolorrendering (literal name), not the
  704. % operator itself, if an error occurs in findcolorrendering.
  705. /findcolorrendering {
  706. /ColorRendering /ProcSet findresource
  707. 1 .argindex dup type /nametype eq { .namestring } if (.) concatstrings
  708. 1 index /GetPageDeviceName get exec dup type /nametype eq { .namestring } if (.) concatstrings
  709. 2 index /GetHalftoneName get exec dup type /nametype eq { .namestring } if
  710. concatstrings concatstrings cvn % stack: intentname procset crdname
  711. dup /ColorRendering resourcestatus {
  712. pop pop exch pop exch pop //true
  713. } {
  714. pop /GetSubstituteCRD get exec //false
  715. } ifelse
  716. } .errorexec
  717. } odef
  718. 5 dict dup begin
  719. /GetPageDeviceName { % - GetPageDeviceName <name>
  720. currentpagedevice dup /PageDeviceName .knownget {
  721. exch pop dup //null eq { pop /none } if
  722. } {
  723. pop /none
  724. } ifelse
  725. } .internalbind def
  726. /GetHalftoneName { % - GetHalftoneName <name>
  727. currenthalftone /HalftoneName .knownget not { /none } if
  728. } .internalbind def
  729. /GetSubstituteCRD { % <intentname> GetSubstituteCRD <crdname>
  730. pop /DefaultColorRendering
  731. } .internalbind def
  732. end
  733. % The resource machinery hasn't been activated, so just save the ProcSet
  734. % and let .fixresources finish the installation process.
  735. /ColorRendering exch def
  736. % Define setcolorrendering.
  737. /.colorrenderingtypes 5 dict def
  738. /setcolorrendering { % <crd> setcolorrendering -
  739. dup /ColorRenderingType get
  740. dup type /integertype ne {
  741. /setcolorrendering .systemvar /typecheck signalerror
  742. } if
  743. //.colorrenderingtypes exch .knownget {
  744. exec
  745. } {
  746. /setcolorrendering .systemvar /rangecheck signalerror
  747. } ifelse
  748. } odef
  749. /.setcolorrendering1 where { pop } { (%END CRD) .skipeof } ifelse
  750. .colorrenderingtypes 1 {
  751. % Adobe ProcSet "Adobe_AGM_Core 2.0 0" places an /Intent key into CRD's
  752. dup /Intent .knownget {
  753. //.renderingintentdict exch .knownget { .setrenderingintent } if
  754. } if
  755. dup .buildcolorrendering1 .setcolorrendering1
  756. } .forcebind put
  757. % Note: the value 101 in the next line must be the same as the value of
  758. % GX_DEVICE_CRD1_TYPE in gscrdp.h.
  759. .colorrenderingtypes 101 {
  760. dup .builddevicecolorrendering1 .setdevicecolorrendering1
  761. } .forcebind put
  762. % sRGB output CRD, D65 white point
  763. mark
  764. /ColorRenderingType 1
  765. /RangePQR [ -0.5 2 -0.5 2 -0.5 2 ] readonly
  766. % Bradford Cone Space
  767. /MatrixPQR [ 0.8951 -0.7502 0.0389
  768. 0.2664 1.7135 -0.0685
  769. -0.1614 0.0367 1.0296] readonly
  770. /MatrixLMN [ 3.240449 -0.969265 0.055643
  771. -1.537136 1.876011 -0.204026
  772. -0.498531 0.041556 1.057229 ] readonly
  773. % Inverse sRGB gamma transform
  774. /EncodeABC [ { dup 0.00304 le
  775. { 12.92321 mul }
  776. { 1 2.4 div exp 1.055 mul 0.055 sub }
  777. ifelse
  778. } bind dup dup
  779. ] readonly
  780. /WhitePoint [ 0.9505 1 1.0890 ] readonly % D65
  781. /BlackPoint [ 0 0 0 ] readonly
  782. % VonKries-like transform in Bradford Cone Space
  783. /TransformPQR
  784. % The implementations have been moved to C for performance.
  785. [ { .TransformPQR_scale_WB0 } bind
  786. { .TransformPQR_scale_WB1 } bind
  787. { .TransformPQR_scale_WB2 } bind
  788. ] readonly
  789. .dicttomark setcolorrendering
  790. %END CRD
  791. % Initialize a CIEBased color space for sRGB.
  792. /CIEsRGB [ /CIEBasedABC
  793. mark
  794. /DecodeLMN [ {
  795. dup 0.03928 le { 12.92321 div } { 0.055 add 1.055 div 2.4 exp } ifelse
  796. } .internalbind dup dup ] readonly
  797. /MatrixLMN [
  798. 0.412457 0.212673 0.019334
  799. 0.357576 0.715152 0.119192
  800. 0.180437 0.072175 0.950301
  801. ] readonly
  802. /WhitePoint [0.9505 1.0 1.0890] readonly
  803. .dicttomark readonly
  804. ] readonly def
  805. % Special type to install
  806. % sRGB ICC profile color space
  807. /CIEsRGBICC [ /ICCBased
  808. mark
  809. /N 3
  810. /DataSource (srgb)
  811. /Alternate [/DeviceRGB]
  812. /Name (srgb)
  813. .dicttomark
  814. ] def
  815. % Special type to install
  816. % sGray ICC profile color space
  817. /CIEsGRAYICC [ /ICCBased
  818. mark
  819. /N 1
  820. /DataSource (sgray)
  821. /Alternate [/DeviceGray]
  822. /Name (sgray)
  823. .dicttomark
  824. ] def
  825. % Special type to install
  826. % e-sRGB ICC profile color space
  827. /CIEesRGBICC [ /ICCBased
  828. mark
  829. /N 3
  830. /DataSource (esrgb)
  831. /Alternate [/DeviceRGB]
  832. /Name (esrgb)
  833. .dicttomark
  834. ] def
  835. % Special type to install
  836. % rommRGB ICC profile color space
  837. /CIErommRGBICC [ /ICCBased
  838. mark
  839. /N 3
  840. /DataSource (rommrgb)
  841. /Alternate [/DeviceRGB]
  842. /Name (rommrgb)
  843. .dicttomark
  844. ] def
  845. % ------ Painting ------ %
  846. % A straightforward definition of execform that doesn't actually
  847. % do any caching.
  848. /.execform1 {
  849. % This is a separate operator so that the stacks will be restored
  850. % properly if an error occurs.
  851. %% High level forms need the CTM before the Form Matrix is applied
  852. /UNROLLFORMS where {/UNROLLFORMS get}{//false}ifelse not
  853. {matrix currentmatrix exch} if
  854. dup /Matrix get concat
  855. dup /BBox get aload pop
  856. exch 3 index sub exch 2 index sub rectclip
  857. dup /PaintProc get
  858. 1 index /Implementation known not {
  859. 1 index dup /Implementation //null .forceput readonly pop
  860. } executeonly if
  861. /UNROLLFORMS where {/UNROLLFORMS get}{//false}ifelse not
  862. %% [CTM] <<Form>> PaintProc .beginform -
  863. {
  864. %% First,, check to see if we have no /Implementation already defined (see above)
  865. 1 index /Implementation get //null eq
  866. {
  867. %% We don't, so copy the form dictionary
  868. 1 index 4 1 roll
  869. %% tell devices we're starting a form, run the PaintProc, and then tell the devices we've finished
  870. 3 -1 roll 2 index
  871. .beginform exec
  872. %% This is all horrible code to deal with illegal forms which leave junk on the operand stack
  873. %% Starting from 1 (not 0, we don't want to look at the loop count) and going up to the
  874. %% number of objects on the stack, check each object to see if its the Form dict (it is
  875. %% *supposed* to be the top object after executing the PaintProc). I don't currently check to see if
  876. %% the PaintProc ate the dict, but if there are extra objects, remove them and tell
  877. %% the user.
  878. %%
  879. count 1 1 3 -1 roll {
  880. dup index
  881. dup type /dicttype eq {
  882. /Implementation known {
  883. 2 sub 0 1 3 -1 roll {
  884. QUIET not {
  885. (\n WARNING - Form PaintProc left operands on the stack after execution.\n This is technically illegal and these have been removed, \n if output is incorrect run again with -dUNROLLFORMS.\n) =
  886. } if
  887. pop pop
  888. } for
  889. exit
  890. }if
  891. } {
  892. pop pop
  893. }ifelse
  894. } for
  895. .endform
  896. %% Ask devices if they have cached the form, and what ID to use if so
  897. %% returning -1 means 'no ID'
  898. .get_form_id dup -1 eq
  899. {pop pop}
  900. {
  901. %% The form is cached with a specific ID. Make a dictionary (which we'll store in the
  902. %% Form dictioanry using the /Implementation key).
  903. 1 dict dup /FormID 4 -1 roll put
  904. 1 index exch /Implementation exch .forceput readonly pop
  905. } executeonly
  906. ifelse
  907. }
  908. {
  909. %% We have a (non-null) Implementation, get the dictionary and pull the
  910. %% FormID key from it, then tell the device to use the stored form with the
  911. %% specified key.
  912. pop dup /Implementation get /FormID get .repeatform
  913. }ifelse
  914. }
  915. {exec} ifelse
  916. } .forcebind odef % must .internalbind .forceput
  917. /.formtypes 5 dict
  918. dup 1 /.execform1 load put
  919. def
  920. /execform { % <form> execform -
  921. gsave {
  922. dup /FormType get //.formtypes exch get exec
  923. } stopped grestore { stop } if
  924. } odef
  925. /.patterntypes 5 dict
  926. dup 1 /.buildpattern1 load put
  927. def
  928. /makepattern { % <proto_dict> <matrix> makepattern <pattern>
  929. dup type /dicttype eq {
  930. % "<dict> makepattern" reports /typecheck on Adobe
  931. /makepattern .systemvar /typecheck signalerror
  932. } if
  933. //.patterntypes 2 .argindex /PatternType get .knownget not {
  934. /makepattern .systemvar /rangecheck signalerror
  935. } if
  936. .currentglobal //false .setglobal exch
  937. % Stack: proto matrix global buildproc
  938. 3 index dup length 1 add dict .copydict
  939. % Stack: proto matrix global buildproc newdict
  940. 3 index 3 -1 roll exec
  941. % Stack: proto matrix global newdict instance
  942. % Create an 'Implementation' entry for the pattern dict. The PRLM 3rd says
  943. % this about the contents of Implementation: "The type and value of this
  944. % entry are implementation-dependent." The CET (page 2 of 18-02f) expects
  945. % that this entry be an array and that the second element of the array be a
  946. % gstate. We put our pattern instance struct into the first element of the
  947. % array.
  948. 1 index /Implementation 3 -1 roll
  949. .getCPSImode { gstate } { //null } ifelse 2 array astore
  950. put % put Implementation into the pattern dict.
  951. % Stack: proto matrix global newdict
  952. readonly exch .setglobal exch pop exch pop
  953. } odef
  954. /setpattern { % [<comp1> ...] <pattern> setpattern -
  955. { currentcolorspace 0 get /Pattern ne {
  956. [ /Pattern currentcolorspace ] setcolorspace
  957. } if setcolor
  958. } stopped {
  959. /setpattern .systemvar $error /errorname get signalerror
  960. } if
  961. } odef
  962. % The following functions emulate the actions of findcmykcustomcolor and
  963. % setcustomcolor. These functions are described in Adobe's TN 5044. That
  964. % same document also says "The following "operators" are not defined in the
  965. % PostScript Language Reference Manual, but should be used as pseudo-operators
  966. % in your PostScript language output. Separation applications from Adobe
  967. % Systems and other vendors will redefine these convention operators to
  968. % separate your documents. Your application should conditionally define
  969. % procedures with these special names, as shown later in this document."
  970. %
  971. % We are providing these functions because we have found files created by
  972. % "QuarkXPress: pictwpstops filter 1.0" which produce bad shading dictionaries
  973. % if these operators are not defined.
  974. % Also we add a findrgbcustomcolor that was discovered in Adobe Illustrator
  975. % AI5 (Adobe Illustrator (R) Version 7.0 Full Prolog) ProcSet that allows
  976. % us to create Separation colorspace with a /DeviceRGB tint transform.
  977. % Conditionally disable the TN 5044 psuedo-ops if NO_TN5044 specified
  978. /NO_TN5044 where { pop (%END TN 5044 psuedo-ops) .skipeof } if
  979. % TN 5044 does not define the contents of the array. We are simply putting
  980. % the values given into an array. This is consistent with what we see when
  981. % testing with Adobe Distiller 6.0.
  982. % <cyan> <magenta> <yellow> <black> <key> findcmykcustomcolor <array>
  983. /findcmykcustomcolor { 5 array astore } .internalbind def
  984. % The following isn't documented by Adobe, but was found in Adobe Illustrator (R)
  985. % Version 7.0 Full Prolog
  986. /findrgbcustomcolor { 4 array astore } .internalbind def
  987. % Build a tint transform function for use by setcustomcolor. This function
  988. % is for a Separation color space which has either a DeviceCMYK base color space
  989. % (i.e. 1 input and 4 outputs) or a DeviceRGB colorspace (1 in, 3 out).
  990. % The input to buildcustomtinttransform is the array created by findcmykcustomcolor
  991. % and the length of the array is used to determine the alternate colorspace.
  992. % The resulting function for CMYK is:
  993. % { dup cyan mul exch dup magenta mul exch dup yellow mul exch black mul }
  994. % Where cyan, magenta, yellow, and black are values from the array.
  995. % For RGB, since the resulting function is:
  996. % { dup red mul exch dup green mul exch blue mul }
  997. /buildcustomtinttransform % <array> buildcustomtinttransform <function>
  998. {
  999. dup length 5 eq {
  1000. % CMYK
  1001. [ /dup load 2 index 0 get /mul load
  1002. /exch load /dup load 6 index 1 get /mul load
  1003. /exch load /dup load 10 index 2 get /mul load
  1004. /exch load 13 index 3 get /mul load
  1005. ]
  1006. } {
  1007. % RGB is assumed
  1008. [ /dup load 2 index 0 get /mul load
  1009. /exch load /dup load 6 index 1 get /mul load
  1010. /exch load 9 index 2 get /mul load
  1011. ]
  1012. } ifelse
  1013. cvx bind exch pop % Make executable and remove the input array
  1014. } .internalbind def
  1015. % Construct the colorspace array to be used by setcolorspace from the array
  1016. % result of either findcmykcustomcolor or findrgbcustomcolor.
  1017. /buildcolorspacearray % <array> buildcustomtinttransform <colorspace_array>
  1018. { % as with buildcustomtinttransform, the length of the array is used to
  1019. % determine the alternate colorspace
  1020. dup length 5 eq {
  1021. % Start building Separation colorspace with CMYK alternate
  1022. [ /Separation 2 index 4 get % Get separation name from array's key
  1023. /DeviceCMYK
  1024. 4 index //buildcustomtinttransform exec % build the tint transform function
  1025. ]
  1026. } {
  1027. [ /Separation 2 index 3 get % Get separation name from array's key
  1028. /DeviceRGB
  1029. 4 index //buildcustomtinttransform exec % build the tint transform function
  1030. ]
  1031. } ifelse
  1032. exch pop % remove the input array
  1033. } .internalbind def
  1034. % Set a custom color based upon a tint and array which describes the custom
  1035. % color. See findcmykcustomcolor. First we create and then set a Separation
  1036. % colorspace. Then we set the specified color.
  1037. % Note that older Adobe ProcSets apparently allow for 'null' as the tint
  1038. % for some reason, so an alternate operational mode is tolerated:
  1039. % null setcustomcolor -
  1040. /setcustomcolor % <array> <tint> setcustomcolor -
  1041. {
  1042. dup //null eq {
  1043. pop pop
  1044. }{
  1045. % Check that the tint is a number between 0 and 1
  1046. dup type dup /integertype eq exch /realtype eq or not {
  1047. /setcustomcolor cvx /typecheck signalerror
  1048. } if
  1049. % Bug 703869. Apparently Adobe (at least Acrobat Pro) silently clamps values
  1050. dup 1 le not {
  1051. pop 1
  1052. } if
  1053. dup 0 ge not {
  1054. pop 0
  1055. } if
  1056. % The array is supposed to be the result of fundcmykcustomcolor. Our
  1057. % implementation just pushes all the arguments into the array and that's
  1058. % what buildcolorspacearray expects. So check that now.
  1059. % Starting with the first N-1 elemenst which must be numbers where 0 <= x <= 1
  1060. 1 index
  1061. 0 1 2 index length 2 sub
  1062. {
  1063. 1 index exch get dup
  1064. type dup /integertype eq exch /realtype eq or not {
  1065. /setcustomcolor cvx /typecheck signalerror
  1066. } if
  1067. dup
  1068. 1 le not {
  1069. /setcustomcolor cvx /rangecheck signalerror
  1070. } if
  1071. 0 ge not {
  1072. /setcustomcolor cvx /rangecheck signalerror
  1073. } if
  1074. } for
  1075. % Finally, check the last element of the array, which must be a string.
  1076. dup length 1 sub get type /stringtype eq not {
  1077. /setcustomcolor cvx /typecheck signalerror
  1078. } if
  1079. exch //buildcolorspacearray exec
  1080. setcolorspace % Set the Separation color space as current
  1081. setcolor % Set the tint as the current color
  1082. } ifelse
  1083. } .internalbind def
  1084. % This proc is supposed to implement a version of overprinting. TN 5044 says
  1085. % that this proc is not used by any shipping host-based application. We have
  1086. % only found it being used in a proc set in files by Canvas from Deneba Systems.
  1087. % Even their proc set does not actually do any overprinting. However their
  1088. % files crash if this is not defined. Thus we have a copy of this proc but
  1089. % we are simply checking for inputs being -1 and if so then we set the value
  1090. % to 0.
  1091. /setcmykoverprint {
  1092. 4 { dup -1 eq { pop 0 } if 4 1 roll } repeat setcmykcolor
  1093. } .internalbind def
  1094. /separation_all [/Separation /All /DeviceCMYK { dup dup dup } .internalbind ] readonly def
  1095. % Collect the arguments into the image dictionary
  1096. % <width> <height> <bits/sample> <matrix> <proc> args2dict <dict>
  1097. /args2dict {
  1098. 10 dict begin
  1099. {1 0} 1
  1100. { /ImageType /Decode /DataSource /ImageMatrix /BitsPerComponent /Height /Width
  1101. } { exch def } forall
  1102. currentdict end
  1103. } .internalbind def
  1104. % Prints (1-gray) on all separations.
  1105. % <gray> setseparationgray -
  1106. /setseparationgray {
  1107. //separation_all setcolorspace
  1108. 1 exch sub setcolor
  1109. } .internalbind def
  1110. % Renders an image whose sample values specify the amount of the custom color.
  1111. % <width> <height> <bits/sample> <matrix> <proc> <array> customcolorimage -
  1112. /customcolorimage {
  1113. gsave
  1114. //buildcolorspacearray exec setcolorspace
  1115. //args2dict exec image
  1116. grestore
  1117. } .internalbind def
  1118. % Renders an image on all process and custom color plates.
  1119. % <width> <height> <bits/sample> <matrix> <proc>
  1120. /separationimage {
  1121. gsave
  1122. //separation_all setcolorspace
  1123. //args2dict exec image
  1124. grestore
  1125. } .internalbind def
  1126. { /buildcustomtinttransform /buildcolorspacearray /separation_all /args2dict }
  1127. { currentdict exch undef } forall
  1128. %END TN 5044 psuedo-ops
  1129. end % level2dict
  1130. % undefine things defined in this file and not referenced elsewhere
  1131. [
  1132. /.checkprocesscomment
  1133. /.pair2dict
  1134. /.setcolorrendering1
  1135. /.checkparamtype
  1136. /.checksetparams
  1137. ] dup level2dict .undefinternalnames
  1138. systemdict .undefinternalnames