]> git.lizzy.rs Git - plan9front.git/blob - sys/lib/ghostscript/gs_dps.ps
merge
[plan9front.git] / sys / lib / ghostscript / gs_dps.ps
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   0 .currentscreenphase
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     0 le
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