2 |
- |
1 |
% Copyright (C) 1997, 2000 Aladdin Enterprises. All rights reserved.
|
|
|
2 |
%
|
|
|
3 |
% This software is provided AS-IS with no warranty, either express or
|
|
|
4 |
% implied.
|
|
|
5 |
%
|
|
|
6 |
% This software is distributed under license and may not be copied,
|
|
|
7 |
% modified or distributed except as expressly authorized under the terms
|
|
|
8 |
% of the license contained in the file LICENSE in this distribution.
|
|
|
9 |
%
|
|
|
10 |
% For more information about licensing, please refer to
|
|
|
11 |
% http://www.ghostscript.com/licensing/. For information on
|
|
|
12 |
% commercial licensing, go to http://www.artifex.com/licensing/ or
|
|
|
13 |
% contact Artifex Software, Inc., 101 Lucas Valley Road #110,
|
|
|
14 |
% San Rafael, CA 94903, U.S.A., +1(415)492-9861.
|
|
|
15 |
|
|
|
16 |
% $Id: gs_dps.ps,v 1.8 2002/11/14 17:24:00 raph Exp $
|
|
|
17 |
% Initialization file for Display PostScript functions.
|
|
|
18 |
|
|
|
19 |
% ------ Contexts ------ %
|
|
|
20 |
|
|
|
21 |
% To create a context with private local VM, we use the .localfork
|
|
|
22 |
% operator to actually create the context, the new VM, and an empty
|
|
|
23 |
% userdict, and then we call the .initlocaldicts procedure to make
|
|
|
24 |
% local copies of the initial contents of the dictionaries in local VM.
|
|
|
25 |
% savedlocaldicts in systemdict is a global read-only dictionary whose
|
|
|
26 |
% elements are global read-only copies of these initial contents;
|
|
|
27 |
% we just copy its elements into local VM and install them in systemdict.
|
|
|
28 |
% userdict and internaldict require special handling.
|
|
|
29 |
|
|
|
30 |
% Switching between contexts with different local VMs requires
|
|
|
31 |
% changing the bindings in systemdict that reference local objects.
|
|
|
32 |
% For this purpose, each userdict has an entry called localdicts
|
|
|
33 |
% which holds the local copies of the elements of savedlocaldicts,
|
|
|
34 |
% plus internaldict. The context switching code in the interpreter
|
|
|
35 |
% effectively copies this dictionary into systemdict.
|
|
|
36 |
% NOTE: the name localdicts is known to the interpreter.
|
|
|
37 |
|
|
|
38 |
% Switching between contexts also requires resetting the user parameters.
|
|
|
39 |
% The interpreter records the value of userparams (a local dictionary
|
|
|
40 |
% referenced from systemdict) for each context, and uses it for this.
|
|
|
41 |
% See gs_lev2.ps for more details.
|
|
|
42 |
% NOTE: the name userparams is known to the interpreter.
|
|
|
43 |
|
|
|
44 |
% Save copies of local dictionaries at the end of system initialization.
|
|
|
45 |
% Also save the initial gstate.
|
|
|
46 |
/.savelocalstate {
|
|
|
47 |
.currentglobal true .setglobal
|
|
|
48 |
//systemdict /savedlocaldicts mark //systemdict {
|
|
|
49 |
dup gcheck {
|
|
|
50 |
pop pop
|
|
|
51 |
} {
|
|
|
52 |
dup type /dicttype eq {
|
|
|
53 |
% Save a copy of this dictionary in global VM.
|
|
|
54 |
dup maxlength dict .copydict readonly
|
|
|
55 |
} {
|
|
|
56 |
pop pop
|
|
|
57 |
} ifelse
|
|
|
58 |
} ifelse
|
|
|
59 |
} forall .dicttomark readonly put
|
|
|
60 |
% Create localdicts for the current context.
|
|
|
61 |
false .setglobal
|
|
|
62 |
userdict /localdicts mark savedlocaldicts {
|
|
|
63 |
pop dup load
|
|
|
64 |
} forall /internaldict dup load
|
|
|
65 |
.dicttomark readonly put
|
|
|
66 |
% Save a copy of the initial gstate.
|
|
|
67 |
true .setglobal
|
|
|
68 |
//systemdict /savedinitialgstate gstate readonly put
|
|
|
69 |
.setglobal
|
|
|
70 |
} .bind def
|
|
|
71 |
|
|
|
72 |
% Initialize local dictionaries and gstate when creating a new context.
|
|
|
73 |
% Note that until this completes, we are in the anomalous situation of
|
|
|
74 |
% having systemdict point to dictionaries that are in a non-current
|
|
|
75 |
% local VM. Because of this, we turn off garbage collection temporarily.
|
|
|
76 |
/.copylocal { % <name> <dict> .copylocal <name> <dict'>
|
|
|
77 |
% Copy a dictionary to the current (local) VM,
|
|
|
78 |
% and make it read-only if its current definition is.
|
|
|
79 |
dup maxlength dict .copydict
|
|
|
80 |
1 index load wcheck not { readonly } if
|
|
|
81 |
} .bind def
|
|
|
82 |
% When this is called, the dictionary stack is in its initial state,
|
|
|
83 |
% and there is (anomalously) only one gstate on the gstate stack.
|
|
|
84 |
/.initlocaldicts { % - .initlocaldicts -
|
|
|
85 |
-2 vmreclaim
|
|
|
86 |
.currentglobal //systemdict begin
|
|
|
87 |
false .setglobal
|
|
|
88 |
% Since localdicts doesn't exist yet, references from
|
|
|
89 |
% systemdict to local objects won't get restored if
|
|
|
90 |
% a context switch happens in this code. Therefore,
|
|
|
91 |
% until localdicts is defined, we have to keep all our
|
|
|
92 |
% state on the operand stack.
|
|
|
93 |
|
|
|
94 |
% Acquire userdict.
|
|
|
95 |
%****** WRONG IF NON-STANDARD INITIAL DSTACK ******
|
|
|
96 |
countdictstack array dictstack
|
|
|
97 |
{ dup gcheck not { exit } if pop } forall
|
|
|
98 |
% Create localdicts with a local copy of each dictionary,
|
|
|
99 |
% except for userdict and userparams, which just need
|
|
|
100 |
% to be filled in.
|
|
|
101 |
mark savedlocaldicts {
|
|
|
102 |
1 index /userdict eq {
|
|
|
103 |
% Stack: userdict mark ... /userdict inituserdict
|
|
|
104 |
counttomark 1 add index .copydict
|
|
|
105 |
} {
|
|
|
106 |
1 index /userparams eq {
|
|
|
107 |
% Stack: userdict mark ... /userparams inituserparams
|
|
|
108 |
userparams .copydict
|
|
|
109 |
} {
|
|
|
110 |
.copylocal
|
|
|
111 |
} ifelse
|
|
|
112 |
} ifelse
|
|
|
113 |
} forall /internaldict dup .makeinternaldict .makeoperator
|
|
|
114 |
.dicttomark readonly /localdicts exch put
|
|
|
115 |
% localdicts is now defined in userdict.
|
|
|
116 |
% Copy the definitions into systemdict.
|
|
|
117 |
localdicts { .forcedef } forall
|
|
|
118 |
% Set the user parameters.
|
|
|
119 |
userparams readonly .setuserparams
|
|
|
120 |
% Establish the initial gstate(s).
|
|
|
121 |
/savedinitialgstate .systemvar setgstate gsave
|
|
|
122 |
% Wrap up.
|
|
|
123 |
end .setglobal
|
|
|
124 |
} odef
|
|
|
125 |
|
|
|
126 |
% Check whether an object is a procedure.
|
|
|
127 |
/.proccheck { % <obj> .proccheck <bool>
|
|
|
128 |
dup xcheck
|
|
|
129 |
exch type dup /arraytype eq exch /packedarraytype eq or and
|
|
|
130 |
} bind def
|
|
|
131 |
|
|
|
132 |
% Create a context with private local VM.
|
|
|
133 |
% The .localfork operator does all the work, but we must ensure that
|
|
|
134 |
% .initlocaldicts gets called when the new context starts up.
|
|
|
135 |
/localfork { % <mark> <obj1> ... <objN> <proc>
|
|
|
136 |
% <stdin|null> <stdout|null>
|
|
|
137 |
% localfork <context>
|
|
|
138 |
.currentglobal true .setglobal 3 index
|
|
|
139 |
dup .proccheck not {
|
|
|
140 |
pop .setglobal /localfork cvx /typecheck signalerror
|
|
|
141 |
} if
|
|
|
142 |
{exec .initlocaldicts} aload pop
|
|
|
143 |
3 1 roll 3 packedarray cvx
|
|
|
144 |
4 1 roll 5 -1 roll pop .setglobal .localfork
|
|
|
145 |
} odef
|
|
|
146 |
|
|
|
147 |
% Fork a context that shares VM. The .fork operator creates an empty
|
|
|
148 |
% userparams dictionary for the context, but we still need to initialize
|
|
|
149 |
% this dictionary when the new context starts up.
|
|
|
150 |
/.postfork { % - .postfork -
|
|
|
151 |
% Initialize the user parameters.
|
|
|
152 |
savedlocaldicts /userparams get userparams .copydict readonly pop
|
|
|
153 |
} odef
|
|
|
154 |
/fork { % <mark> <obj1> ... <objN> <proc> fork <context>
|
|
|
155 |
.currentglobal false .setglobal 1 index
|
|
|
156 |
dup .proccheck not {
|
|
|
157 |
pop .setglobal /fork cvx /typecheck signalerror
|
|
|
158 |
} if
|
|
|
159 |
{exec .postfork} aload pop
|
|
|
160 |
3 1 roll 3 packedarray cvx
|
|
|
161 |
3 1 roll exch pop .setglobal .fork
|
|
|
162 |
} odef
|
|
|
163 |
|
|
|
164 |
% ------ Halftone phase ------ %
|
|
|
165 |
|
|
|
166 |
/sethalftonephase { % <x> <y> sethalftonephase -
|
|
|
167 |
-1 2 index 2 index .setscreenphase pop pop
|
|
|
168 |
} odef
|
|
|
169 |
/currenthalftonephase { % - currenthalftonephase <x> <y>
|
|
|
170 |
|
|
|
171 |
} odef
|
|
|
172 |
|
|
|
173 |
% ------ Device-source images ------ */
|
|
|
174 |
|
|
|
175 |
.imagetypes 2 /.image2 load put
|
|
|
176 |
|
|
|
177 |
% ------ Device information ------ %
|
|
|
178 |
|
|
|
179 |
/.deviceinfodict mark
|
|
|
180 |
/Colors null /GrayValues null /RedValues null /GreenValues null
|
|
|
181 |
/BlueValues null /ColorValues null
|
|
|
182 |
.dicttomark readonly def
|
|
|
183 |
/deviceinfo { % - deviceinfo <dict>
|
|
|
184 |
currentdevice //.deviceinfodict .getdeviceparams .dicttomark
|
|
|
185 |
dup begin
|
|
|
186 |
/ColorValues .knownget {
|
|
|
187 |
|
|
|
188 |
{ currentdict /ColorValues undef }
|
|
|
189 |
{
|
|
|
190 |
% hack around devices that incorrect set GrayValues
|
|
|
191 |
Colors 3 eq { 1 } { GrayValues } ifelse
|
|
|
192 |
RedValues mul GreenValues mul BlueValues mul ColorValues ne
|
|
|
193 |
{ currentdict /GrayValues undef
|
|
|
194 |
currentdict /RedValues undef
|
|
|
195 |
currentdict /GreenValues undef
|
|
|
196 |
currentdict /BlueValues undef
|
|
|
197 |
} if
|
|
|
198 |
}
|
|
|
199 |
ifelse
|
|
|
200 |
} if
|
|
|
201 |
currentdict end readonly
|
|
|
202 |
} odef
|
|
|
203 |
|
|
|
204 |
% The current implementation allocates a 2-element array each time.
|
|
|
205 |
% Perhaps we should change this to 2 separate parameters for X and Y?
|
|
|
206 |
/.wtdict mark
|
|
|
207 |
/wtranslation null
|
|
|
208 |
.dicttomark readonly def
|
|
|
209 |
/wtranslation { % - wtranslation <x> <y>
|
|
|
210 |
currentdevice //.wtdict .getdeviceparams exch pop exch pop aload pop
|
|
|
211 |
} odef
|
|
|
212 |
currentdict /.wtdict .undef
|
|
|
213 |
|
|
|
214 |
% ------ View clipping ------ %
|
|
|
215 |
|
|
|
216 |
/rectviewclip { % <x> <y> <width> <height> rectviewclip -
|
|
|
217 |
% <numarray|numstring> rectviewclip -
|
|
|
218 |
newpath .rectappend viewclip
|
|
|
219 |
} odef
|