Commit | Line | Data |
---|---|---|
5d8dbb5f WJ |
1 | /* Copyright (C) 1989, 1992 Aladdin Enterprises. All rights reserved. |
2 | Distributed by Free Software Foundation, Inc. | |
3 | ||
4 | This file is part of Ghostscript. | |
5 | ||
6 | Ghostscript is distributed in the hope that it will be useful, but | |
7 | WITHOUT ANY WARRANTY. No author or distributor accepts responsibility | |
8 | to anyone for the consequences of using it or for whether it serves any | |
9 | particular purpose or works at all, unless he says so in writing. Refer | |
10 | to the Ghostscript General Public License for full details. | |
11 | ||
12 | Everyone is granted permission to copy, modify and redistribute | |
13 | Ghostscript, but only under the conditions described in the Ghostscript | |
14 | General Public License. A copy of this license is supposed to have been | |
15 | given to you along with Ghostscript so you can know your rights and | |
16 | responsibilities. It should be in a file named COPYING. Among other | |
17 | things, the copyright notice and this notice must be preserved on all | |
18 | copies. */ | |
19 | ||
20 | /* zgstate.c */ | |
21 | /* Graphics state operators for Ghostscript */ | |
22 | #include "ghost.h" | |
23 | #include "errors.h" | |
24 | #include "oper.h" | |
25 | #include "alloc.h" | |
26 | #include "gsmatrix.h" | |
27 | #include "gsstate.h" | |
28 | #include "state.h" | |
29 | #include "store.h" | |
30 | ||
31 | /* Forward references */ | |
32 | private int near num_param(P2(os_ptr, int (*)(P2(gs_state *, floatp)))); | |
33 | private int near line_param(P2(os_ptr, int *)); | |
34 | ||
35 | /* The current graphics state */ | |
36 | gs_state *igs; | |
37 | int_gstate istate; | |
38 | ||
39 | /* Initialize the graphics stack. */ | |
40 | void | |
41 | gs_init() | |
42 | { igs = gs_state_alloc(alloc, alloc_free); | |
43 | istate.saved = 0; | |
44 | make_null(&istate.screen_proc); | |
45 | make_null(&istate.transfer_procs.red); | |
46 | make_null(&istate.transfer_procs.green); | |
47 | make_null(&istate.transfer_procs.blue); | |
48 | make_null(&istate.transfer_procs.gray); | |
49 | /* gsave and grestore only work properly */ | |
50 | /* if there are always at least 2 entries on the stack. */ | |
51 | /* We count on the PostScript initialization code to do a gsave. */ | |
52 | } | |
53 | ||
54 | /* gsave */ | |
55 | int | |
56 | zgsave(register os_ptr op) | |
57 | { int_gstate *pis = (int_gstate *)alloc(1, sizeof(int_gstate), "gsave"); | |
58 | int code; | |
59 | if ( pis == 0 ) return e_VMerror; | |
60 | code = gs_gsave(igs); | |
61 | if ( code < 0 ) | |
62 | { alloc_free((char *)pis, 1, sizeof(int_gstate), "gsave"); | |
63 | return code; | |
64 | } | |
65 | *pis = istate; | |
66 | istate.saved = pis; | |
67 | return 0; | |
68 | } | |
69 | ||
70 | /* grestore */ | |
71 | int | |
72 | zgrestore(register os_ptr op) | |
73 | { int code = gs_grestore(igs); | |
74 | int_gstate *pis; | |
75 | if ( code < 0 ) return code; | |
76 | pis = istate.saved; | |
77 | istate = *pis; | |
78 | if ( istate.saved ) | |
79 | alloc_free((char *)pis, 1, sizeof(int_gstate), "grestore"); | |
80 | else /* bottom of stack */ | |
81 | istate.saved = pis; | |
82 | return 0; | |
83 | } | |
84 | ||
85 | /* grestoreall */ | |
86 | int | |
87 | zgrestoreall(register os_ptr op) | |
88 | { while ( istate.saved->saved ) | |
89 | { int code = zgrestore(op); | |
90 | if ( code < 0 ) return code; | |
91 | } | |
92 | return zgrestore(op); | |
93 | } | |
94 | ||
95 | /* initgraphics */ | |
96 | int | |
97 | zinitgraphics(register os_ptr op) | |
98 | { return gs_initgraphics(igs); | |
99 | } | |
100 | ||
101 | /* setlinewidth */ | |
102 | int | |
103 | zsetlinewidth(register os_ptr op) | |
104 | { return num_param(op, gs_setlinewidth); | |
105 | } | |
106 | ||
107 | /* currentlinewidth */ | |
108 | int | |
109 | zcurrentlinewidth(register os_ptr op) | |
110 | { push(1); | |
111 | make_real(op, gs_currentlinewidth(igs)); | |
112 | return 0; | |
113 | } | |
114 | ||
115 | /* setlinecap */ | |
116 | int | |
117 | zsetlinecap(register os_ptr op) | |
118 | { int param; | |
119 | int code = line_param(op, ¶m); | |
120 | if ( !code ) code = gs_setlinecap(igs, (gs_line_cap)param); | |
121 | return code; | |
122 | } | |
123 | ||
124 | /* currentlinecap */ | |
125 | int | |
126 | zcurrentlinecap(register os_ptr op) | |
127 | { push(1); | |
128 | make_int(op, (int)gs_currentlinecap(igs)); | |
129 | return 0; | |
130 | } | |
131 | ||
132 | /* setlinejoin */ | |
133 | int | |
134 | zsetlinejoin(register os_ptr op) | |
135 | { int param; | |
136 | int code = line_param(op, ¶m); | |
137 | if ( !code ) code = gs_setlinejoin(igs, (gs_line_join)param); | |
138 | return code; | |
139 | } | |
140 | ||
141 | /* currentlinejoin */ | |
142 | int | |
143 | zcurrentlinejoin(register os_ptr op) | |
144 | { push(1); | |
145 | make_int(op, (int)gs_currentlinejoin(igs)); | |
146 | return 0; | |
147 | } | |
148 | ||
149 | /* setmiterlimit */ | |
150 | int | |
151 | zsetmiterlimit(register os_ptr op) | |
152 | { return num_param(op, gs_setmiterlimit); | |
153 | } | |
154 | ||
155 | /* currentmiterlimit */ | |
156 | int | |
157 | zcurrentmiterlimit(register os_ptr op) | |
158 | { push(1); | |
159 | make_real(op, gs_currentmiterlimit(igs)); | |
160 | return 0; | |
161 | } | |
162 | ||
163 | /* setdash */ | |
164 | int | |
165 | zsetdash(register os_ptr op) | |
166 | { float offset; | |
167 | uint n, i; | |
168 | ref *dfrom; | |
169 | float *pattern, *dto; | |
170 | int code = real_param(op, &offset); | |
171 | if ( code ) return code; | |
172 | check_array(op[-1]); | |
173 | check_read(op[-1]); | |
174 | /* Unpack the dash pattern and check it */ | |
175 | dfrom = op[-1].value.refs; | |
176 | i = n = r_size(op - 1); | |
177 | pattern = dto = (float *)alloc(n, sizeof(float), "setdash"); | |
178 | while ( i-- ) | |
179 | { switch ( r_type(dfrom) ) | |
180 | { | |
181 | case t_integer: | |
182 | *dto++ = dfrom->value.intval; | |
183 | break; | |
184 | case t_real: | |
185 | *dto++ = dfrom->value.realval; | |
186 | break; | |
187 | default: | |
188 | alloc_free((char *)dto, n, sizeof(float), "setdash"); | |
189 | return e_typecheck; | |
190 | } | |
191 | dfrom++; | |
192 | } | |
193 | code = gs_setdash(igs, pattern, n, offset); | |
194 | if ( !code ) pop(2); | |
195 | return code; | |
196 | } | |
197 | ||
198 | /* currentdash */ | |
199 | int | |
200 | zcurrentdash(register os_ptr op) | |
201 | { int n = gs_currentdash_length(igs); | |
202 | int i = n; | |
203 | ref *pattern = alloc_refs(n, "currentdash"); | |
204 | ref *dto = pattern; | |
205 | float *dfrom = (float *)((char *)pattern + n * (sizeof(ref) - sizeof(float))); | |
206 | gs_currentdash_pattern(igs, dfrom); | |
207 | while ( i-- ) | |
208 | { make_real(dto, *dfrom); | |
209 | dto++, dfrom++; | |
210 | } | |
211 | push(2); | |
212 | make_tasv(op - 1, t_array, a_all, n, refs, pattern); | |
213 | make_real(op, gs_currentdash_offset(igs)); | |
214 | return 0; | |
215 | } | |
216 | ||
217 | /* setflat */ | |
218 | int | |
219 | zsetflat(register os_ptr op) | |
220 | { return num_param(op, gs_setflat); | |
221 | } | |
222 | ||
223 | /* currentflat */ | |
224 | int | |
225 | zcurrentflat(register os_ptr op) | |
226 | { push(1); | |
227 | make_real(op, gs_currentflat(igs)); | |
228 | return 0; | |
229 | } | |
230 | ||
231 | /* ------ Initialization procedure ------ */ | |
232 | ||
233 | op_def zgstate_op_defs[] = { | |
234 | {"0currentdash", zcurrentdash}, | |
235 | {"0currentflat", zcurrentflat}, | |
236 | {"0currentlinecap", zcurrentlinecap}, | |
237 | {"0currentlinejoin", zcurrentlinejoin}, | |
238 | {"0currentlinewidth", zcurrentlinewidth}, | |
239 | {"0currentmiterlimit", zcurrentmiterlimit}, | |
240 | {"0grestore", zgrestore}, | |
241 | {"0grestoreall", zgrestoreall}, | |
242 | {"0gsave", zgsave}, | |
243 | {"0initgraphics", zinitgraphics}, | |
244 | {"2setdash", zsetdash}, | |
245 | {"1setflat", zsetflat}, | |
246 | {"1setlinecap", zsetlinecap}, | |
247 | {"1setlinejoin", zsetlinejoin}, | |
248 | {"1setlinewidth", zsetlinewidth}, | |
249 | {"1setmiterlimit", zsetmiterlimit}, | |
250 | op_def_end(0) | |
251 | }; | |
252 | ||
253 | /* ------ Internal routines ------ */ | |
254 | ||
255 | /* Get a numeric parameter */ | |
256 | private int near | |
257 | num_param(os_ptr op, int (*pproc)(P2(gs_state *, floatp))) | |
258 | { float param; | |
259 | int code = real_param(op, ¶m); | |
260 | if ( !code ) code = (*pproc)(igs, param); | |
261 | if ( !code ) pop(1); | |
262 | return code; | |
263 | } | |
264 | ||
265 | /* Get an integer parameter 0-2. */ | |
266 | private int near | |
267 | line_param(register os_ptr op, int *pparam) | |
268 | { check_type(*op, t_integer); | |
269 | if ( op->value.intval < 0 || op->value.intval > 2 ) | |
270 | return e_rangecheck; | |
271 | *pparam = (int)op->value.intval; | |
272 | pop(1); | |
273 | return 0; | |
274 | } |