1 % Copyright (C) 1997, 2000 Aladdin Enterprises. All rights reserved.
3 % This software is provided AS-IS with no warranty, either express or
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.
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.
16 % $Id: gs_dps.ps,v 1.8 2002/11/14 17:24:00 raph Exp $
17 % Initialization file for Display PostScript functions.
19 % ------ Contexts ------ %
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.
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.
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.
44 % Save copies of local dictionaries at the end of system initialization.
45 % Also save the initial gstate.
47 .currentglobal true .setglobal
48 //systemdict /savedlocaldicts mark //systemdict {
52 dup type /dicttype eq {
53 % Save a copy of this dictionary in global VM.
54 dup maxlength dict .copydict readonly
59 } forall .dicttomark readonly put
60 % Create localdicts for the current context.
62 userdict /localdicts mark savedlocaldicts {
64 } forall /internaldict dup load
65 .dicttomark readonly put
66 % Save a copy of the initial gstate.
68 //systemdict /savedinitialgstate gstate readonly put
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
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 -
86 .currentglobal //systemdict begin
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.
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
101 mark savedlocaldicts {
102 1 index /userdict eq {
103 % Stack: userdict mark ... /userdict inituserdict
104 counttomark 1 add index .copydict
106 1 index /userparams eq {
107 % Stack: userdict mark ... /userparams inituserparams
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
126 % Check whether an object is a procedure.
127 /.proccheck { % <obj> .proccheck <bool>
129 exch type dup /arraytype eq exch /packedarraytype eq or and
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
140 pop .setglobal /localfork cvx /typecheck signalerror
142 {exec .initlocaldicts} aload pop
143 3 1 roll 3 packedarray cvx
144 4 1 roll 5 -1 roll pop .setglobal .localfork
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
154 /fork { % <mark> <obj1> ... <objN> <proc> fork <context>
155 .currentglobal false .setglobal 1 index
157 pop .setglobal /fork cvx /typecheck signalerror
159 {exec .postfork} aload pop
160 3 1 roll 3 packedarray cvx
161 3 1 roll exch pop .setglobal .fork
164 % ------ Halftone phase ------ %
166 /sethalftonephase { % <x> <y> sethalftonephase -
167 -1 2 index 2 index .setscreenphase pop pop
169 /currenthalftonephase { % - currenthalftonephase <x> <y>
170 0 .currentscreenphase
173 % ------ Device-source images ------ */
175 .imagetypes 2 /.image2 load put
177 % ------ Device information ------ %
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
186 /ColorValues .knownget {
188 { currentdict /ColorValues undef }
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
201 currentdict end readonly
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?
208 .dicttomark readonly def
209 /wtranslation { % - wtranslation <x> <y>
210 currentdevice //.wtdict .getdeviceparams exch pop exch pop aload pop
212 currentdict /.wtdict .undef
214 % ------ View clipping ------ %
216 /rectviewclip { % <x> <y> <width> <height> rectviewclip -
217 % <numarray|numstring> rectviewclip -
218 newpath .rectappend viewclip