386BSD 0.1 development
[unix-history] / usr / othersrc / public / ghostscript-2.4.1 / zdps1.c
CommitLineData
1d8a1861
WJ
1/* Copyright (C) 1990, 1992 Aladdin Enterprises. All rights reserved.
2 Distributed by Free Software Foundation, Inc.
3
4This file is part of Ghostscript.
5
6Ghostscript is distributed in the hope that it will be useful, but
7WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
8to anyone for the consequences of using it or for whether it serves any
9particular purpose or works at all, unless he says so in writing. Refer
10to the Ghostscript General Public License for full details.
11
12Everyone is granted permission to copy, modify and redistribute
13Ghostscript, but only under the conditions described in the Ghostscript
14General Public License. A copy of this license is supposed to have been
15given to you along with Ghostscript so you can know your rights and
16responsibilities. It should be in a file named COPYING. Among other
17things, the copyright notice and this notice must be preserved on all
18copies. */
19
20/* zdps1.c */
21/* Display PostScript graphics extensions */
22#include "ghost.h"
23#include "errors.h"
24#include "oper.h"
25#include "gsmatrix.h"
26#include "gspath.h"
27#include "gsstate.h"
28#include "state.h"
29#include "store.h"
30#include "stream.h"
31#include "bnum.h"
32
33/* ------ Graphics states ------ */
34
35/* Structure for saving a graphics state. */
36typedef struct gstate_obj_s {
37 int_gstate istate;
38 gs_state *pgs;
39} gstate_obj;
40
41/* gstate */
42int
43zgstate(register os_ptr op)
44{ gs_state *pnew = gs_gstate(igs);
45 gstate_obj *pso =
46 (gstate_obj *)alloc(1, sizeof(gstate_obj), "gstate");
47 if ( pnew == 0 || pso == 0 ) return e_VMerror;
48 pso->istate = istate;
49 int_gstate_map_refs(&pso->istate, ref_mark_new);
50 pso->pgs = pnew;
51 push(1);
52 make_tv(op, t_gstate, pgstate, pso);
53 return 0;
54}
55
56/* currentgstate */
57int
58zcurrentgstate(register os_ptr op)
59{ int code;
60 int_gstate *pistate;
61 check_type(*op, t_gstate);
62 /****** DOESN'T GET FULLY UNDONE BY RESTORE ******/
63 code = gs_currentgstate(op->value.pgstate->pgs, igs);
64 if ( code < 0 ) return code;
65 pistate = &op->value.pgstate->istate;
66#define gsref_save(p) ref_save(p, "currentgstate")
67 int_gstate_map_refs(pistate, gsref_save);
68#undef gsref_save
69 *pistate = istate;
70 int_gstate_map_refs(pistate, ref_mark_new);
71 return 0;
72}
73
74/* setgstate */
75int
76zsetgstate(register os_ptr op)
77{ int code;
78 check_type(*op, t_gstate);
79 code = gs_setgstate(igs, op->value.pgstate->pgs);
80 if ( code < 0 ) return code;
81 istate = op->value.pgstate->istate;
82 pop(1);
83 return 0;
84}
85
86/* ------ Rectangles ------- */
87
88/* We preallocate a short list for rectangles, because */
89/* the rectangle operators usually will involve very few rectangles. */
90#define max_local_rect 5
91typedef struct local_rects_s {
92 gs_rect *pr;
93 uint count;
94 gs_rect rl[max_local_rect];
95} local_rects;
96
97/* Forward references */
98private int rect_get(P2(local_rects *, os_ptr));
99private void rect_release(P1(local_rects *));
100
101/* rectappend */
102int
103zrectappend(os_ptr op)
104{ local_rects lr;
105 int npop = rect_get(&lr, op);
106 int code;
107 if ( npop < 0 ) return npop;
108 code = gs_rectappend(igs, lr.pr, lr.count);
109 rect_release(&lr);
110 if ( code < 0 ) return code;
111 pop(npop);
112 return 0;
113}
114
115/* rectclip */
116int
117zrectclip(os_ptr op)
118{ local_rects lr;
119 int npop = rect_get(&lr, op);
120 int code;
121 if ( npop < 0 ) return npop;
122 code = gs_rectclip(igs, lr.pr, lr.count);
123 rect_release(&lr);
124 if ( code < 0 ) return code;
125 pop(npop);
126 return 0;
127}
128
129/* rectfill */
130int
131zrectfill(os_ptr op)
132{ local_rects lr;
133 int npop = rect_get(&lr, op);
134 int code;
135 if ( npop < 0 ) return npop;
136 code = gs_rectfill(igs, lr.pr, lr.count);
137 rect_release(&lr);
138 if ( code < 0 ) return code;
139 pop(npop);
140 return 0;
141}
142
143/* rectstroke */
144int
145zrectstroke(os_ptr op)
146{ gs_matrix mat;
147 local_rects lr;
148 int npop, code;
149 if ( read_matrix(op, &mat) >= 0 )
150 { /* Concatenate the matrix to the CTM just before */
151 /* stroking the path. */
152 npop = rect_get(&lr, op - 1);
153 if ( npop < 0 ) return npop;
154 code = gs_rectstroke(igs, lr.pr, lr.count, &mat);
155 npop++;
156 }
157 else
158 { /* No matrix. */
159 npop = rect_get(&lr, op);
160 if ( npop < 0 ) return npop;
161 code = gs_rectstroke(igs, lr.pr, lr.count, (gs_matrix *)0);
162 }
163 rect_release(&lr);
164 if ( code < 0 ) return code;
165 pop(npop);
166 return 0;
167}
168
169/* --- Internal routines --- */
170
171/* Get rectangles from the stack. */
172/* Return the number of elements to pop (>0) if OK, <0 if error. */
173private int
174rect_get(local_rects *plr, os_ptr op)
175{ int code, npop;
176 stream st;
177 uint n, count;
178 gs_rect *pr;
179 switch ( r_type(op) )
180 {
181 case t_array:
182 case t_string:
183 code = sread_num_array(&st, op);
184 if ( code < 0 ) return code;
185 count = scount_num_stream(&st);
186 if ( count % 4 ) return e_typecheck;
187 count /= 4, npop = 1;
188 break;
189 default: /* better be 4 numbers */
190 sread_string(&st, (byte *)(op - 3), sizeof(ref) * 4);
191 st.num_format = num_array;
192 count = 1, npop = 4;
193 break;
194 }
195 plr->count = count;
196 if ( count <= max_local_rect )
197 pr = plr->rl;
198 else
199 { pr = (gs_rect *)alloc(count, sizeof(gs_rect), "rect_get");
200 if ( pr == 0 ) return e_VMerror;
201 }
202 plr->pr = pr;
203 for ( n = 0; n < count; n++, pr++ )
204 { ref rnum;
205 float rv[4];
206 int i;
207 for ( i = 0; i < 4; i++ )
208 { switch ( code = sget_encoded_number(&st, &rnum) )
209 {
210 case t_integer:
211 rv[i] = rnum.value.intval;
212 break;
213 case t_real:
214 rv[i] = rnum.value.realval;
215 break;
216 default: /* code < 0 */
217 return code;
218 }
219 }
220 pr->q.x = (pr->p.x = rv[0]) + rv[2];
221 pr->q.y = (pr->p.y = rv[1]) + rv[3];
222 }
223 return npop;
224}
225
226/* Release the rectangle list if needed. */
227private void
228rect_release(local_rects *plr)
229{ if ( plr->pr != plr->rl )
230 alloc_free((char *)plr->pr, plr->count, sizeof(gs_rect),
231 "rect_release");
232}
233
234/* ------ Graphics state ------ */
235
236/* currentstrokeadjust */
237int
238zcurrentstrokeadjust(register os_ptr op)
239{ push(1);
240 make_bool(op, gs_currentstrokeadjust(igs));
241 return 0;
242}
243
244/* setbbox */
245int
246zsetbbox(register os_ptr op)
247{ float box[4];
248 int code = num_params(op, 4, box);
249 if ( code < 0 ) return code;
250 if ( (code = gs_setbbox(igs, box[0], box[1], box[2], box[3])) < 0 )
251 return code;
252 pop(4);
253 return 0;
254}
255
256/* setstrokeadjust */
257int
258zsetstrokeadjust(register os_ptr op)
259{ check_type(*op, t_boolean);
260 gs_setstrokeadjust(igs, op->value.index);
261 pop(1);
262 return 0;
263}
264
265/* ------ Initialization procedure ------ */
266
267op_def zdps1_op_defs[] = {
268 /* Graphics state objects */
269 {"0gstate", zgstate},
270 {"1currentgstate", zcurrentgstate},
271 {"1setgstate", zsetgstate},
272 /* Rectangles */
273 {"1rectappend", zrectappend},
274 {"1rectclip", zrectclip},
275 {"1rectfill", zrectfill},
276 {"1rectstroke", zrectstroke},
277 /* Graphics state components */
278 {"0currentstrokeadjust", zcurrentstrokeadjust},
279 {"4setbbox", zsetbbox},
280 {"1setstrokeadjust", zsetstrokeadjust},
281 op_def_end(0)
282};