1 % Copyright (C) 1997, 1998 Aladdin Enterprises. All rights reserved.
3 % This file is part of GNU Ghostscript.
5 % GNU Ghostscript is distributed in the hope that it will be useful, but
6 % WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
7 % to anyone for the consequences of using it or for whether it serves any
8 % particular purpose or works at all, unless he says so in writing. Refer
9 % to the GNU General Public License for full details.
11 % Everyone is granted permission to copy, modify and redistribute GNU
12 % Ghostscript, but only under the conditions described in the GNU General
13 % Public License. A copy of this license is supposed to have been given
14 % to you along with GNU Ghostscript so you can know your rights and
15 % responsibilities. It should be in a file named COPYING. Among other
16 % things, the copyright notice and this notice must be preserved on all
19 % Aladdin Enterprises supports the work of the GNU Project, but is not
20 % affiliated with the Free Software Foundation or the GNU Project. GNU
21 % Ghostscript, as distributed by Aladdin Enterprises, does not require any
22 % GNU software to build or run it.
24 % $Id: gs_ll3.ps 956 2000-03-08 23:15:43Z mike $
25 % Initialization file for PostScript LanguageLevel 3 functions.
26 % Essentially all of these are stubs right now.
27 % This file must be loaded after gs_lev2.ps and gs_res.ps.
28 % These definitions go into ll3dict or various ProcSets.
29 % NOTE: the interpreter creates ll3dict.
33 % We need LanguageLevel 2 or higher in order to have setuserparams and
35 languagelevel dup 2 max .setlanguagelevel
37 % ------ Idiom recognition ------ %
39 /IdiomRecognition false .definepsuserparam
41 % Modify `bind' to apply idiom recognition afterwards.
42 /.bindscratch 128 string def
43 % Do the right thing if NOBIND or DELAYBIND is in effect.
44 % Note also that since this definition of `bind' may get bound in,
45 % it has to function properly even at lower language levels,
46 % where IdiomRecognition may not be defined.
47 /bind load /.bind load ne
48 /bind { % <proc> bind <proc'>
49 //.bind currentuserparams /IdiomRecognition
50 .knownget not { false } if {
52 /IdiomSet findresource
54 % Stack: proc false dummykey [template substitute]
55 exch pop dup 1 get exch 0 get
56 % Stack: proc false substitute template
58 2 index gcheck 1 index gcheck not and {
61 3 -1 roll pop exch not exit
67 } //.bindscratch /IdiomSet resourceforall
70 { /.bind /bind load def
73 currentdict /.bindscratch .undef
75 % ------ HalftoneTypes 6, 10, 16 ------ %
77 % This code depends on one new operator:
79 % <dict> <Width> <Height> <Thresholds> <bits> <shift> .setstriphalftone -
81 % <dict> is the dictionary that will be returned by .currenthalftone.
82 % The operator only looks at the TransferFunction entry.
83 % Width, Height: as for HalftoneType 3.
84 % Thresholds: a BigStringEncode filter holding the thresholds,
85 % Width x Height x BitsPerSample / 8 bytes.
86 % shift: the amount of X shift per Y repetition of the halftone,
88 % bits: bits per sample, 8 or 16.
90 % Eventually the code below will have to get hooked up to sethalftone
91 % and currenthalftone....
93 /.copybytes { % <source> <dest> <count> .copybytes -
94 { 1 index read not { /sethalftone load /rangecheck signalerror exit } if
99 /.copythresholds { % <dict> <Width> <Height> <bits> .copythresholds -
100 dup 8 idiv 3 index mul 2 index mul
101 dup /BigStringEncode filter 3 1 roll
102 % Stack: dict width height dest bits nbytes
103 5 index /Thresholds get 3 index 3 -1 roll .copybytes
108 /.sethalftone6 { % <dict> .sethalftone6 -
109 % Keys: Width, Height, Thresholds, T'Function
110 dup /Width get 1 index /Height get
114 /.copythresholds2 { % <dict> <Width> <Height> <Width2> <Height2>
115 % <bits> .copythresholds2 -
116 % The block height B is gcd(Height, Height2).
118 2 copy lt { exch } if dup 1 eq { pop exit } if exch 1 index mod
120 % The raster R is (Width * Height + Width2 * Height2) / B * bits/8.
121 5 index 5 index mul 4 index 4 index mul add 1 index idiv
123 % Currently I don't know how to compute the stride.
124 % ****** COMPUTE THE STRIDE SOMEHOW ******
125 % Push additional arguments onto the stack.
126 1 index 1 index mul /BigStringEncode filter 4 1 roll
127 9 index /Thresholds get
128 % Stack: dict width height width2 height2 bits
129 % dest B R stride source
130 % For the first rectangle, the number of blocks is Height / B;
132 5 copy 14 index 5 1 roll
133 14 index 5 index idiv 4 1 roll
135 % For the second rectangle, the number of blocks is Height2 / B;
136 % the offset is Width.
137 5 copy 12 index 5 1 roll
138 12 index 4 index idiv 4 1 roll
139 16 index exch .copyshifted
140 % Stack: dict width height width2 height2 bits
141 % dest B R stride source
142 % We want: dict R/(bits/8) B dest bits stride
143 pop exch 4 index 8 idiv idiv 4 1 roll
144 % R/(bits/8) dest B stride
145 exch 3 1 roll 5 -1 roll exch
146 9 -4 roll 4 { pop } repeat
150 % Copy a shifted rectangular threshold array into a BigStringEncode filter.
151 % Note that the width and shift are in bytes, not samples.
152 /.copyshifted { % <dest> <width> <B> <N> <R> <stride> <offset>
153 % <source> .copyshifted -
154 % Copy N blocks of <width> x B bytes from <source>.
155 % Row Y (0 <= Y < B) in group G (0 <= G < N) must get copied to byte position
156 % Y * R + (G * stride + offset) mod R
157 % in the destination.
158 1 index % Stack: ... rowstart
159 6 index { % iterate over rows within a block
160 5 index { % iterate over blocks
161 8 index 1 index setfileposition
162 1 index 9 index 9 index .copybytes
163 4 index add % + raster
165 3 index add 4 index mod % + stride, mod raster
166 } repeat % end row in block
170 /.sethalftone10 { % <dict> .sethalftone10 -
171 % Keys: XSquare, YSquare, Thresholds, T'Function
172 % ****** DOESN'T HANDLE STRING SOURCE ******
173 dup /XSquare get dup 2 index /YSquare get dup
177 /.sethalftone16 { % <dict> .sethalftone16 -
178 % Keys: Width, Height, Width2, Height2,
179 % Thresholds, T'Function
180 dup /Width get 1 index /Height get
181 2 index /Width2 .knownget { % 2-rectangle case
184 } { % 1-rectangle case
189 {6 10 16} { dup /HalftoneType defineresource pop } forall
191 % ------ ImageTypes 3 and 4 (masked images) ------ %
194 dup 3 /.image3 load put
197 % ------ Functions ------ %
199 % Define the FunctionType resource category.
200 /Generic /Category findresource dup maxlength 3 add dict .copydict begin
201 /InstanceType /integertype def
202 /FunctionType currentdict end /Category defineresource pop
204 {0 2 3} { dup /FunctionType defineresource pop } forall
206 % ------ Smooth shading ------ %
208 % Define the ShadingType resource category.
209 /Generic /Category findresource dup maxlength 3 add dict .copydict begin
210 /InstanceType /integertype def
211 /ShadingType currentdict end /Category defineresource pop
213 systemdict /.shadingtypes mark % not ll3dict
214 1 /.buildshading1 load
215 2 /.buildshading2 load
216 3 /.buildshading3 load
217 4 /.buildshading4 load
218 5 /.buildshading5 load
219 6 /.buildshading6 load
220 7 /.buildshading7 load
223 /.buildshading { % <shadingdict> .buildshading <shading>
224 % The .buildshading operators use the current color space
226 dup /ShadingType get //.shadingtypes exch get
227 1 index /ColorSpace get gsave { setcolorspace exec } stopped
230 /.buildpattern2 { % <template> <matrix> .buildpattern2
231 % <template> <pattern>
232 1 index /Shading get .buildshading .buildshadingpattern
236 2 /.buildpattern2 load put
238 /shfill { % <shadingdict> shfill -
239 % Currently, .shfill requires that the color space
240 % in the pattern be the current color space.
242 1 index /ColorSpace get
243 gsave { setcolorspace .shfill } stopped grestore { stop } if
247 % Establish an arbitrary initial smoothness value.
248 1 64 div setsmoothness
250 % ------ Trapping ------ %
252 % The PostScript-level trapping parameters are maintained in userdict,
253 % and explicitly reinstalled upon restore.
257 /settrapparams dup { % <paramdict> settrapparams -
258 /.trapparams .uservar dup length dict .copydict
260 % Stack: paramdict olddict olddict key value
261 2 index 2 index known { put dup } { pop pop } ifelse
263 dup .settrapparams % Let the operator check parameter validity.
264 .userdict /.trapparams 3 -1 roll put pop
267 /.copyparams { % <obj> .copyparams <obj'>
268 dup type /dicttype eq {
269 dup length dict .copydict
271 .copyparams 3 copy put pop pop
274 dup type /arraytype eq {
275 [ exch { .copyparams } forall ]
280 /currenttrapparams dup { % - currenttrapparams <paramdict>
281 /.trapparams .uservar .copyparams
284 /settrapzone dup { % - settrapzone -
285 % ****** DUMMY ******
289 % Define initial (dummy) trapping parameters.
290 % These values are mostly complete guesses.
291 userdict /.trapparams mark
293 /BlackDensityLimit 1.0
295 /ColorantZoneDetails 0 dict
298 /ImageInternalTrapping false
300 /ImageToObjectTrapping true
301 /ImageTrapPlacement /Center
302 /SlidingTrapLimit 1.0
304 /TrapColorScaling 0.0
307 .dicttomark readonly put
309 .dicttomark /ProcSet defineresource pop
311 % ------ Miscellaneous ------ %
313 % Define additional user and system parameters.
316 /MaxSuperScreen 1016 def
318 pssystemparams begin % read-only, so use .forcedef
319 /MaxDisplayAndSourceList 160000 .forcedef
322 % Define the IdiomSet, InkParams, and TrapParams resource categories.
323 { /IdiomSet /InkParams /TrapParams } {
324 /Generic /Category findresource dup maxlength 3 add dict .copydict begin
325 /InstanceType /dicttype def
326 currentdict end /Category defineresource pop
329 % Define the ReusableStreamDecode filter.
330 % ****** DOESN'T WORK FOR CONTENTS >64K ******
331 /.reusablestreamdecode { % <source> <dict> .reusablestreamdecode <file>
332 % <source> .reusablestreamdecode <file>
333 % Collect the filter parameters.
334 dup type /dicttype eq { 2 copy } { dup 0 dict } ifelse
336 % Construct the filter pipeline.
337 % The very first filter should use the value of CloseSource
338 % from the RSD dictionary; all the others should have
339 % CloseSource = true.
340 % Stack: source dict filters parms
341 2 index /CloseSource .knownget not { false } if 5 -1 roll
342 % Stack: dict filters parms CloseSource source
343 0 1 5 index length 1 sub {
345 % Stack: dict filters parms CloseSource source index filtname
349 4 index 2 index get dup null eq { pop } if
352 exch pop true exch % set CloseSource for further filters
354 % See if we can create the filter directly.
355 % Stack: dict filters parms CloseSource file
356 null 2 index { .reusablestream } .internalstopped {
358 % No luck. Read the entire contents of the stream now.
360 % Stack: dict filters parms CloseSource contdict file
361 dup 1000 string readstring
362 3 index dup length 4 -1 roll put not { break } if
364 % Concatenate the contents into one big string.
365 % Stack: dict filters parms CloseSource contdict
366 0 1 index { length exch pop add } forall string
368 % Stack: dict filters parms CloseSource string index substring
369 exch 1000 mul exch 2 index 3 1 roll putinterval
371 % Now create the stream on the string.
372 null 3 -1 roll .reusablestream
374 % We created the stream successfully: clean up.
375 4 { exch pop } repeat
376 dup type /dicttype eq { pop } if pop
378 filterdict /ReusableStreamDecode /.reusablestreamdecode load put
381 % When running in LanguageLevel 3 mode, this interpreter is supposed to be
382 % compatible with Adobe version 3010.
383 /version (3010) readonly def