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