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.

569 lines
19 KiB

1 month ago
  1. % Copyright (C) 2001-2024 Artifex Software, Inc.
  2. % All Rights Reserved.
  3. %
  4. % This software is provided AS-IS with no warranty, either express or
  5. % implied.
  6. %
  7. % This software is distributed under license and may not be copied,
  8. % modified or distributed except as expressly authorized under the terms
  9. % of the license contained in the file LICENSE in this distribution.
  10. %
  11. % Refer to licensing information at http://www.artifex.com or contact
  12. % Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
  13. % CA 94129, USA, for further information.
  14. %
  15. % Initialization file for PostScript LanguageLevel 3 functions.
  16. % This file must be loaded after gs_lev2.ps and gs_res.ps.
  17. % These definitions go into ll3dict or various ProcSets.
  18. % NOTE: the interpreter creates ll3dict.
  19. ll3dict begin
  20. % We need LanguageLevel 2 or higher in order to have setuserparams and
  21. % defineresource.
  22. languagelevel dup 2 .max .setlanguagelevel
  23. % ------ Idiom recognition ------ %
  24. /IdiomRecognition //false .definepsuserparam
  25. % Modify `bind' to apply idiom recognition afterwards.
  26. /.bindscratch 128 string def
  27. % Note that since this definition of `bind' may get bound in,
  28. % it has to function properly even at lower language levels,
  29. % where IdiomRecognition may not be defined.
  30. /.bind_ { % <proc> .bind <proc'>
  31. //.bind currentuserparams /IdiomRecognition
  32. .knownget not { //false } if
  33. {
  34. //false
  35. /IdiomSet //.findcategory exec .Instances
  36. {
  37. exch pop % pop the IdiomSet identifying key. Stack /proc /false [-dict- status size]
  38. 0 get % get resource instance, a dictionary. Stack : /proc false -dict-
  39. {
  40. exch pop % pop the instance identifying key
  41. % Stack: proc //false [template substitute]
  42. dup 1 get exch 0 get % Stack: proc //false substitute template
  43. 3 index .eqproc {
  44. % Stack: proc //false substitute
  45. 3 -1 roll pop exch not % Stack: substitute true
  46. } {
  47. pop % Stack: proc //false
  48. } ifelse
  49. } forall
  50. dup {exit} if % Stack proc <bool>
  51. } forall
  52. not % Not matched in global resources
  53. currentglobal not and % must not match local resources if currentglobal is true
  54. {
  55. //false
  56. .LocalInstances
  57. {
  58. exch pop % pop IdiomSet identifying key. Stack /proc /false [-dict- status size]
  59. 0 get % get resource instance, a dictionary Stack : /proc false -dict-
  60. {
  61. exch pop % pop instance identifier key
  62. % Stack: proc //false [template substitute]
  63. dup 1 get exch 0 get % Stack: proc //false substitute template
  64. 3 index .eqproc {
  65. % Stack: proc //false substitute
  66. 2 index gcheck % Stack: proc //false substitute _global?_
  67. 1 index gcheck not and % Stack: proc //false substitute _global?_ _global?_
  68. { % must not match if candidate in global VM and substitute in local
  69. pop % Stack: proc //false
  70. } {
  71. % Stack: proc //false substitute
  72. 3 -1 roll pop exch not % Stack: substitute true
  73. }ifelse
  74. } {
  75. pop % Stack: proc //false
  76. } ifelse
  77. } forall
  78. dup {exit} if
  79. } forall
  80. pop % Stack: proc/substitute
  81. } if
  82. end % .findcategory makes the category dictionary the current dict, so we must pop it from dict stack
  83. } if
  84. } def
  85. /.bind /.bind_ load odef % note that .bind_ will get bound
  86. currentdict /.bindscratch .undef
  87. DELAYBIND not {
  88. % We can't just do
  89. % /bind /.bind load def
  90. % because then /bind load == prints --.bind-- .
  91. /bind {//.bind_ exec} odef
  92. } if
  93. currentdict /.bind_ undef
  94. /.readbytestring { % <source> <bytestring> .readbytestring
  95. % <bytestring> <filled>
  96. % Note that since bytestrings don't implement getinterval,
  97. % if filled is false, there is no way to tell how much
  98. % was read.
  99. //true exch 0 1 2 index length 1 sub {
  100. % Stack: source true str index
  101. 3 index read not { pop exch not exch exit } if
  102. 3 copy put pop pop
  103. } for 3 -1 roll pop exch
  104. } .internalbind def
  105. /.bigstring { % <size> .bigstring <string|bytestring>
  106. count 1 lt { /.bigstring cvx /stackunderflow signalerror } if
  107. dup type /integertype ne {
  108. /.bigstring cvx /typecheck signalerror
  109. } if
  110. dup 65400 gt { .bytestring } { string } ifelse
  111. } .internalbind def
  112. % ------ HalftoneTypes 6, 10, 16 and HalftoneMode ------ %
  113. % This code depends on an internal HalftoneType 7 with the following keys:
  114. % Width, Height, Width2, Height2, TransferFunction:
  115. % as for HalftoneType 16.
  116. % Thresholds: a string or bytestring holding the thresholds,
  117. % (Width x Height + Width2 x Height2) x BitsPerSample / 8 bytes,
  118. % as for HalftoneType 16 except that the samples may be either
  119. % 8 or 16 bits wide.
  120. % BitsPerSample: 8 or 16.
  121. % Note that this HalftoneType never appears in halftone dictionaries given
  122. % to sethalftone, only as a component in those given to .sethalftone5,
  123. % so its numeric value can be chosen ad lib as long as it differs from the
  124. % other values that are legal in component dictionaries for .sethalftone5
  125. % (currently only 1 and 3).
  126. /.makehalftone7 { % <dict> <dict> <source> <Width> <Height>
  127. % (<Width2> <Height2> | null) <BPS> .makehalftone7
  128. % <setdict> <dict5> { .sethalftone5 }
  129. 8 dict begin
  130. /HalftoneType 7 def
  131. /BitsPerSample exch def
  132. dup //null eq {
  133. pop 0
  134. } {
  135. /Height2 1 index def /Width2 2 index def mul
  136. } ifelse 3 1 roll
  137. /Height 1 index def
  138. /Width 2 index def
  139. mul add BitsPerSample 8 idiv mul //.bigstring exec
  140. % Stack: dict dict source str
  141. dup type /stringtype eq { readstring } { //.readbytestring exec} ifelse
  142. not { /sethalftone .systemvar /rangecheck signalerror exit } if
  143. readonly /Thresholds exch def
  144. /TransferFunction .knownget { /TransferFunction exch def } if
  145. % If the original Thresholds was a file, replace it with
  146. % a new one.
  147. dup /Thresholds get type /filetype eq {
  148. dup /Thresholds [ Thresholds ] cvx 0 () .subfiledecode put
  149. } if
  150. mark /HalftoneType 5 /Default currentdict end .dicttomark
  151. { .sethalftone5 }
  152. } .internalbind def
  153. /.sethalftone6 { % <dict> <dict> .sethalftone6 <setdict> <dict5>
  154. % { .sethalftone5 }
  155. % Keys: Width, Height, Thresholds, T'Function
  156. dup /Thresholds get
  157. 1 index /Width get 2 index /Height get
  158. //null 8 //.makehalftone7 exec
  159. } .internalbind def
  160. /.sethalftone10 { % <dict> <dict> .sethalftone10 <setdict> <dict5>
  161. % { .sethalftone5 }
  162. % Keys: Xsquare, Ysquare, Thresholds, T'Function
  163. % Note that this is the only one of these three HalftoneTypes
  164. % that allows either a file or a string for Thresholds.
  165. dup /Thresholds get dup type /stringtype eq { 0 () .subfiledecode } if
  166. 1 index /Xsquare get dup 3 index /Ysquare get dup
  167. 8 //.makehalftone7 exec
  168. } .internalbind def
  169. /.sethalftone16 { % <dict> <dict> .sethalftone16 <setdict> <dict5>
  170. % { .sethalftone5 }
  171. % Keys: Width, Height, Width2, Height2,
  172. % Thresholds, T'Function
  173. dup /Thresholds get
  174. 1 index /Width get 2 index /Height get
  175. 3 index /Width2 .knownget { % 2-rectangle case
  176. 4 index /Height2 get
  177. } { % 1-rectangle case
  178. //null
  179. } ifelse 16 //.makehalftone7 exec
  180. } .internalbind def
  181. .halftonetypes begin
  182. 6 //.sethalftone6 def
  183. 10 //.sethalftone10 def
  184. 16 //.sethalftone16 def
  185. end
  186. % Redefine the halftone-setting operators to honor HalftoneMode.
  187. /setcolorscreen {
  188. /HalftoneMode getuserparam 0 eq {
  189. //setcolorscreen
  190. } {
  191. 12 { pop } repeat //.getdefaulthalftone exec
  192. currentglobal
  193. true setglobal
  194. { //sethalftone }
  195. { .setdefaulthalftone }
  196. ifelse
  197. setglobal
  198. } ifelse
  199. } odef
  200. /setscreen {
  201. /HalftoneMode getuserparam 0 eq {
  202. //setscreen
  203. } {
  204. pop pop pop //.getdefaulthalftone exec
  205. currentglobal
  206. true setglobal
  207. { //sethalftone }
  208. { .setdefaulthalftone }
  209. ifelse
  210. setglobal
  211. } ifelse
  212. } odef
  213. /sethalftone {
  214. /HalftoneMode getuserparam 0 eq {
  215. //sethalftone
  216. } {
  217. pop
  218. currentglobal
  219. true setglobal
  220. //.getdefaulthalftone exec
  221. { //sethalftone }
  222. { .setdefaulthalftone }
  223. ifelse
  224. setglobal
  225. } ifelse
  226. } odef
  227. % ------ ImageTypes 3 and 4 (masked images) ------ %
  228. % Put the new data source in the requested dictionary.
  229. % Copy the updated dictionary because it nay be used elsewhere.
  230. % <dict> <data> <name> update_image3 <dict'>
  231. /update_image3 {
  232. 3 -1 roll dup length dict copy dup % [data] /name <<image>> <<image>>
  233. 2 index get % [data] /name <<image>> <<sub-image>>
  234. dup length dict copy dup % [data] /name <<image>> <<sub-image>> <<sub-image>>
  235. /DataSource 6 -1 roll put % /name <<image>> <<sub-image>>
  236. exch dup % /name <<sub-image>> <<image>> <<image>>
  237. 4 2 roll % <<image>> <<image>> /name <<sub-image>>
  238. put % <<image>>
  239. } .internalbind def
  240. % Copy mask data source to a reusable stream
  241. % <dict> <source> buffer_mask <dict> <file>
  242. /buffer_mask {
  243. 1 index /MaskDict get
  244. dup /Width get
  245. 1 index /BitsPerComponent get mul 7 add 8 idiv
  246. exch /Height get mul () /SubFileDecode filter
  247. /ReusableStreamDecode filter
  248. } .internalbind def
  249. % Data type vs. mask type decission table.
  250. % All procedures have the signature:
  251. % <image dict> <data DataSource> <mask DataSource> proc <image dict'>
  252. /data_mask_dict mark
  253. /stringtype mark % data is a string
  254. /stringtype { pop pop } bind
  255. /arraytype { % convert data to proc, don't buffer mask
  256. pop
  257. dup type dup /arraytype eq exch /packedarraytype eq or {
  258. [ exch { 1 array astore cvx } forall ]
  259. } {
  260. 1 array astore cvx
  261. } ifelse
  262. /DataDict //update_image3 exec
  263. } bind
  264. /packedarraytype 1 index
  265. /filetype { % convert data to file, don't buffer mask
  266. pop
  267. dup type dup /arraytype eq exch /packedarraytype eq or {
  268. [ exch { 1 array astore cvx 0 () /SubFileDecode filter } forall ]
  269. } {
  270. 1 array astore cvx 0 () /SubFileDecode filter
  271. } ifelse
  272. /DataDict //update_image3 exec
  273. } .internalbind
  274. .dicttomark readonly
  275. /arraytype mark % data is a proc
  276. /stringtype { % convert mask to proc
  277. exch pop
  278. 1 array astore cvx
  279. /MaskDict //update_image3 exec
  280. } .internalbind
  281. /arraytype { % buffer mask in reusable stream and convert back to proc
  282. exch pop
  283. //buffer_mask exec
  284. 500 string
  285. { readstring pop } aload pop
  286. 4 packedarray cvx
  287. /MaskDict //update_image3 exec
  288. } .internalbind
  289. /packedarraytype 1 index
  290. /filetype 1 index
  291. .dicttomark readonly
  292. /packedarraytype 1 index
  293. /filetype mark % data is a file
  294. /stringtype { % convert mask to file
  295. exch pop
  296. 1 array astore cvx 0 () /SubFileDecode filter
  297. /MaskDict //update_image3 exec
  298. } .internalbind
  299. /arraytype { % buffer the mask and convert to file
  300. exch pop
  301. //buffer_mask exec
  302. /MaskDict //update_image3 exec
  303. } .internalbind
  304. /packedarraytype 1 index
  305. /filetype {
  306. //systemdict /userdict get /PDFTopSave known {
  307. pop pop % mask is already buffered by PDF interpreter
  308. } {
  309. exch pop % buffer the mask
  310. //buffer_mask exec
  311. /MaskDict //update_image3 exec
  312. } ifelse
  313. } .internalbind
  314. .dicttomark readonly
  315. .dicttomark readonly def
  316. .imagetypes
  317. dup 3 {
  318. dup /InterleaveType get 3 eq {
  319. % .image3 requires data sources of the image and mask to be of the
  320. % same type. Work around this restriction here.
  321. dup /DataDict get /DataSource get
  322. 1 index /MaskDict get /DataSource get % <<>> data mask
  323. dup type % <<>> data mask mask_type
  324. 2 index
  325. 4 index /DataDict get /MultipleDataSources .knownget {
  326. { 0 get } if
  327. } if
  328. type % <<>> data mask mask_type data_type
  329. //data_mask_dict exch .knownget {
  330. exch .knownget {
  331. exec
  332. } {
  333. pop pop % pass wrong type as is to .image3
  334. } ifelse
  335. } {
  336. pop pop pop % pass wrong type as is to .image3
  337. } ifelse
  338. } if
  339. .image3
  340. } .internalbind put
  341. dup 4 /.image4 load put
  342. % We also detect ImageType 103 here: it isn't worth making a separate file
  343. % just for this.
  344. /.image3x where { pop dup 103 /.image3x load put } if
  345. pop
  346. currentdict /data_mask_dict undef
  347. currentdict /update_image3 undef
  348. currentdict /buffer_mask undef
  349. % ------ Functions ------ %
  350. % Define the FunctionType resource category.
  351. /Generic /Category findresource dup maxlength 3 add dict .copydict begin
  352. /InstanceType /integertype def
  353. /FunctionType currentdict end /Category defineresource pop
  354. {0 2 3} { dup /FunctionType defineresource pop } forall
  355. % ------ Smooth shading ------ %
  356. % Define the ShadingType resource category.
  357. /Generic /Category findresource dup maxlength 3 add dict .copydict begin
  358. /InstanceType /integertype def
  359. /ShadingType currentdict end /Category defineresource pop
  360. systemdict /.shadingtypes mark % not ll3dict
  361. 1 /.buildshading1 load
  362. 2 /.buildshading2 load
  363. 3 /.buildshading3 load
  364. 4 /.buildshading4 load
  365. 5 /.buildshading5 load
  366. 6 /.buildshading6 load
  367. 7 /.buildshading7 load
  368. .dicttomark put
  369. systemdict /.reuseparamdict mark
  370. /Intent 2
  371. /AsyncRead //false
  372. /CloseSource //true
  373. .dicttomark readonly put
  374. /.buildshading { % <shadingdict> .buildshading <shading>
  375. dup rcheck not {
  376. % Adobe seems to access ColorSpace first and CET 12-14c checks this.
  377. /$error .systemvar /errorinfo [ /ColorSpace //null ] put
  378. /shfill .systemvar /invalidaccess signalerror
  379. } if
  380. % Unfortunately, we always need to make the DataSource reusable,
  381. % because if clipping is involved, even shfill may need to read
  382. % the source data multiple times. If it weren't for this,
  383. % we would only need to create a reusable stream if the ultimate
  384. % source of the data is a procedure (since the library can't
  385. % suspend shading to do a procedure callout).
  386. dup /DataSource .knownget {
  387. dup type /filetype eq {
  388. //.reuseparamdict /ReusableStreamDecode filter
  389. % Copy the dictionary to replace the DataSource, but make sure the
  390. % copy is in the same VM as the original.
  391. .currentglobal 2 index gcheck .setglobal
  392. % Stack: shdict rsdfile saveglobal
  393. 2 index dup length dict copy exch .setglobal
  394. dup /DataSource 4 -1 roll put exch pop
  395. } {
  396. pop
  397. } ifelse
  398. } if
  399. % The .buildshading operators use the current color space
  400. % for ColorSpace.
  401. dup /ShadingType .knownget not { % error handling for CET 12-14b conformance
  402. /$error .systemvar /errorinfo [ /ShadingType //null ] put
  403. /shfill .systemvar /undefined signalerror
  404. } if
  405. dup type /integertype ne {
  406. /$error .systemvar /errorinfo [ /ShadingType 4 index ] put
  407. /shfill .systemvar /typecheck signalerror
  408. } if
  409. //.shadingtypes 1 index .knownget not {
  410. /$error .systemvar /errorinfo [ /ShadingType 4 index ] put
  411. /shfill .systemvar /rangecheck signalerror
  412. } if
  413. exch pop 1 index /ColorSpace .knownget {
  414. { setcolorspace } stopped {
  415. /$error .systemvar /errorinfo [ /ColorSpace 4 index ] put
  416. /shfill .systemvar /$error .systemvar /errorname get signalerror
  417. } if
  418. exec
  419. } {
  420. /$error .systemvar /errorinfo [ /ColorSpace //null ] put
  421. /shfill .systemvar /undefined signalerror
  422. } ifelse
  423. } .internalbind def
  424. /.buildshading_and_shfill {
  425. //.buildshading exec .shfill
  426. } bind def
  427. systemdict /.reuseparamdict undef
  428. /.buildpattern2 { % <template> <matrix> .buildpattern2
  429. % <template> <pattern>
  430. % We want to build the pattern without doing gsave/grestore,
  431. % since we want it to load the CIE caches.
  432. 1 index /Shading get
  433. mark currentcolor currentcolorspace
  434. counttomark 4 add -3 roll mark 4 1 roll
  435. % Stack: -mark- ..color.. cspace -mark- template matrix shadingdict
  436. { //.buildshading exec} stopped {
  437. cleartomark setcolorspace setcolor pop stop
  438. } if
  439. .buildshadingpattern
  440. 3 -1 roll pop counttomark 1 add 2 roll setcolorspace setcolor pop
  441. } .internalbind def
  442. .patterntypes
  443. 2 //.buildpattern2 put
  444. /shfill { % <shadingdict> shfill -
  445. % Currently, .shfill requires that the color space
  446. % in the pattern be the current color space.
  447. % Disable overprintmode for shfill
  448. { dup gsave 0 .setoverprintmode .buildshading_and_shfill } stopped
  449. grestore {
  450. /$error .systemvar /errorinfo 2 copy known {
  451. pop pop
  452. } {
  453. //null put % CET 12-14c
  454. } ifelse
  455. stop
  456. } if
  457. pop
  458. } odef
  459. % Establish an initial smoothness value that matches Adobe RIPs.
  460. 0.02 setsmoothness
  461. % ------ DeviceN color space ------ %
  462. % gs_res.ps uses these entries in colorspacedict
  463. % to populate the ColorSpaceFamily resource, so we need
  464. % to add the supported spaces.
  465. %
  466. systemdict /colorspacedict get begin
  467. /CIEBasedDEF [] def
  468. /CIEBasedDEFG [] def
  469. /DeviceN [] def
  470. end
  471. % ------ Miscellaneous ------ %
  472. % Make the setoverprintmode and currentoverprintmode operators visible (3015)
  473. % Because of the requirements of PDF, the .currentoverprintmode and
  474. % .setoverprintmode operators have integer parameters. Thus we need to
  475. % convert the Postscript bool parameters to integers.
  476. %
  477. /setoverprintmode % bool setoverprint -
  478. {
  479. { 1 } { 0 } ifelse % convert bool to integer
  480. //.setoverprintmode
  481. } odef
  482. /currentoverprintmode % - currentoverprintmode bool
  483. {
  484. //.currentoverprintmode
  485. 0 ne % convert integers to bool
  486. } odef
  487. % Define additional user and system parameters.
  488. /HalftoneMode 0 .definepsuserparam
  489. /MaxSuperScreen 1016 .definepsuserparam
  490. % read-only, so use .forceput
  491. pssystemparams /MaxDisplayAndSourceList 160000 .forceput
  492. % Define the IdiomSet resource category.
  493. { /IdiomSet } {
  494. /Generic /Category findresource dup maxlength 3 add dict .copydict begin
  495. /InstanceType /dicttype def
  496. currentdict end /Category defineresource pop
  497. } forall
  498. (*) {
  499. dup type /nametype eq not {
  500. cvn
  501. } if
  502. /IdiomSet findresource pop
  503. } 256 string /IdiomSet resourceforall
  504. /languagelevel 3 def
  505. % When running in LanguageLevel 3 mode, this interpreter is supposed to be
  506. % compatible with Adobe version 3010.
  507. /version (3010) readonly def
  508. .setlanguagelevel
  509. % undefine things defined (or used) in this file and not referenced elsewhere
  510. [
  511. /.buildpattern2
  512. /.buildshading
  513. /.buildshading1 /.buildshading2 /.buildshading3 /.buildshading4
  514. /.buildshading5 /.buildshading6 /.buildshading7 /.buildshadingpattern
  515. /.makehalftone7 /.sethalftone6 /.sethalftone10 /.sethalftone16
  516. /.readbytestring /.bigstring
  517. ]
  518. dup currentdict .undefinternalnames
  519. systemdict .undefinternalnames
  520. end % ll3dict