1 /* Copyright (C) 1989, 1995, 1997, 1998, 1999 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
17 /* $Id: zpath1.c,v 1.5 2002/06/16 03:43:51 lpd Exp $ */
18 /* PostScript Level 1 additional path operators */
19 #include "memory_.h"
20 #include "ghost.h"
21 #include "oper.h"
22 #include "oparc.h" /* for prototypes */
23 #include "estack.h" /* for pathforall */
24 #include "ialloc.h"
25 #include "igstate.h"
26 #include "gsstruct.h"
27 #include "gspath.h"
28 #include "store.h"
29
30 /* Forward references */
31 private int common_arc(i_ctx_t *,
32 int (*)(gs_state *, floatp, floatp, floatp, floatp, floatp));
33 private int common_arct(i_ctx_t *, float *);
34
35 /* <x> <y> <r> <ang1> <ang2> arc - */
36 int
zarc(i_ctx_t * i_ctx_p)37 zarc(i_ctx_t *i_ctx_p)
38 {
39 return common_arc(i_ctx_p, gs_arc);
40 }
41
42 /* <x> <y> <r> <ang1> <ang2> arcn - */
43 int
zarcn(i_ctx_t * i_ctx_p)44 zarcn(i_ctx_t *i_ctx_p)
45 {
46 return common_arc(i_ctx_p, gs_arcn);
47 }
48
49 /* Common code for arc[n] */
50 private int
common_arc(i_ctx_t * i_ctx_p,int (* aproc)(gs_state *,floatp,floatp,floatp,floatp,floatp))51 common_arc(i_ctx_t *i_ctx_p,
52 int (*aproc)(gs_state *, floatp, floatp, floatp, floatp, floatp))
53 {
54 os_ptr op = osp;
55 double xyra[5]; /* x, y, r, ang1, ang2 */
56 int code = num_params(op, 5, xyra);
57
58 if (code < 0)
59 return code;
60 code = (*aproc)(igs, xyra[0], xyra[1], xyra[2], xyra[3], xyra[4]);
61 if (code >= 0)
62 pop(5);
63 return code;
64 }
65
66 /* <x1> <y1> <x2> <y2> <r> arct - */
67 int
zarct(i_ctx_t * i_ctx_p)68 zarct(i_ctx_t *i_ctx_p)
69 {
70 int code = common_arct(i_ctx_p, (float *)0);
71
72 if (code < 0)
73 return code;
74 pop(5);
75 return 0;
76 }
77
78 /* <x1> <y1> <x2> <y2> <r> arcto <xt1> <yt1> <xt2> <yt2> */
79 private int
zarcto(i_ctx_t * i_ctx_p)80 zarcto(i_ctx_t *i_ctx_p)
81 {
82 os_ptr op = osp;
83 float tanxy[4]; /* xt1, yt1, xt2, yt2 */
84 int code = common_arct(i_ctx_p, tanxy);
85
86 if (code < 0)
87 return code;
88 make_real(op - 4, tanxy[0]);
89 make_real(op - 3, tanxy[1]);
90 make_real(op - 2, tanxy[2]);
91 make_real(op - 1, tanxy[3]);
92 pop(1);
93 return 0;
94 }
95
96 /* Common code for arct[o] */
97 private int
common_arct(i_ctx_t * i_ctx_p,float * tanxy)98 common_arct(i_ctx_t *i_ctx_p, float *tanxy)
99 {
100 os_ptr op = osp;
101 double args[5]; /* x1, y1, x2, y2, r */
102 int code = num_params(op, 5, args);
103
104 if (code < 0)
105 return code;
106 return gs_arcto(igs, args[0], args[1], args[2], args[3], args[4], tanxy);
107 }
108
109 /* - .dashpath - */
110 private int
zdashpath(i_ctx_t * i_ctx_p)111 zdashpath(i_ctx_t *i_ctx_p)
112 {
113 return gs_dashpath(igs);
114 }
115
116 /* - flattenpath - */
117 private int
zflattenpath(i_ctx_t * i_ctx_p)118 zflattenpath(i_ctx_t *i_ctx_p)
119 {
120 return gs_flattenpath(igs);
121 }
122
123 /* - reversepath - */
124 private int
zreversepath(i_ctx_t * i_ctx_p)125 zreversepath(i_ctx_t *i_ctx_p)
126 {
127 return gs_reversepath(igs);
128 }
129
130 /* - strokepath - */
131 private int
zstrokepath(i_ctx_t * i_ctx_p)132 zstrokepath(i_ctx_t *i_ctx_p)
133 {
134 return gs_strokepath(igs);
135 }
136
137 /* - clippath - */
138 private int
zclippath(i_ctx_t * i_ctx_p)139 zclippath(i_ctx_t *i_ctx_p)
140 {
141 return gs_clippath(igs);
142 }
143
144 /* <bool> .pathbbox <llx> <lly> <urx> <ury> */
145 private int
zpathbbox(i_ctx_t * i_ctx_p)146 zpathbbox(i_ctx_t *i_ctx_p)
147 {
148 os_ptr op = osp;
149 gs_rect box;
150 int code;
151
152 check_type(*op, t_boolean);
153 code = gs_upathbbox(igs, &box, op->value.boolval);
154 if (code < 0)
155 return code;
156 push(3);
157 make_real(op - 3, box.p.x);
158 make_real(op - 2, box.p.y);
159 make_real(op - 1, box.q.x);
160 make_real(op, box.q.y);
161 return 0;
162 }
163
164 /* <moveproc> <lineproc> <curveproc> <closeproc> pathforall - */
165 private int path_continue(i_ctx_t *);
166 private int path_cleanup(i_ctx_t *);
167 private int
zpathforall(i_ctx_t * i_ctx_p)168 zpathforall(i_ctx_t *i_ctx_p)
169 {
170 os_ptr op = osp;
171 gs_path_enum *penum;
172 int code;
173
174 check_proc(op[-3]);
175 check_proc(op[-2]);
176 check_proc(op[-1]);
177 check_proc(*op);
178 check_estack(8);
179 if ((penum = gs_path_enum_alloc(imemory, "pathforall")) == 0)
180 return_error(e_VMerror);
181 code = gs_path_enum_init(penum, igs);
182 if (code < 0) {
183 ifree_object(penum, "path_cleanup");
184 return code;
185 }
186 /* Push a mark, the four procedures, and the path enumerator. */
187 push_mark_estack(es_for, path_cleanup); /* iterator */
188 memcpy(esp + 1, op - 3, 4 * sizeof(ref)); /* 4 procs */
189 esp += 5;
190 make_istruct(esp, 0, penum);
191 push_op_estack(path_continue);
192 pop(4);
193 op -= 4;
194 return o_push_estack;
195 }
196 /* Continuation procedure for pathforall */
197 private void pf_push(i_ctx_t *, gs_point *, int);
198 private int
path_continue(i_ctx_t * i_ctx_p)199 path_continue(i_ctx_t *i_ctx_p)
200 {
201 gs_path_enum *penum = r_ptr(esp, gs_path_enum);
202 gs_point ppts[3];
203 int code;
204
205 /* Make sure we have room on the o-stack for the worst case */
206 /* before we enumerate the next path element. */
207 check_ostack(6); /* 3 points for curveto */
208 code = gs_path_enum_next(penum, ppts);
209 switch (code) {
210 case 0: /* all done */
211 esp -= 6;
212 path_cleanup(i_ctx_p);
213 return o_pop_estack;
214 default: /* error */
215 return code;
216 case gs_pe_moveto:
217 esp[2] = esp[-4]; /* moveto proc */
218 pf_push(i_ctx_p, ppts, 1);
219 break;
220 case gs_pe_lineto:
221 esp[2] = esp[-3]; /* lineto proc */
222 pf_push(i_ctx_p, ppts, 1);
223 break;
224 case gs_pe_curveto:
225 esp[2] = esp[-2]; /* curveto proc */
226 pf_push(i_ctx_p, ppts, 3);
227 break;
228 case gs_pe_closepath:
229 esp[2] = esp[-1]; /* closepath proc */
230 break;
231 }
232 push_op_estack(path_continue);
233 ++esp; /* include pushed procedure */
234 return o_push_estack;
235 }
236 /* Internal procedure to push one or more points */
237 private void
pf_push(i_ctx_t * i_ctx_p,gs_point * ppts,int n)238 pf_push(i_ctx_t *i_ctx_p, gs_point * ppts, int n)
239 {
240 os_ptr op = osp;
241
242 while (n--) {
243 op += 2;
244 make_real(op - 1, ppts->x);
245 make_real(op, ppts->y);
246 ppts++;
247 }
248 osp = op;
249 }
250 /* Clean up after a pathforall */
251 private int
path_cleanup(i_ctx_t * i_ctx_p)252 path_cleanup(i_ctx_t *i_ctx_p)
253 {
254 gs_path_enum *penum = r_ptr(esp + 6, gs_path_enum);
255
256 gs_path_enum_cleanup(penum);
257 ifree_object(penum, "path_cleanup");
258 return 0;
259 }
260
261 /* ------ Initialization procedure ------ */
262
263 const op_def zpath1_op_defs[] =
264 {
265 {"5arc", zarc},
266 {"5arcn", zarcn},
267 {"5arct", zarct},
268 {"5arcto", zarcto},
269 {"0clippath", zclippath},
270 {"0.dashpath", zdashpath},
271 {"0flattenpath", zflattenpath},
272 {"4pathforall", zpathforall},
273 {"0reversepath", zreversepath},
274 {"0strokepath", zstrokepath},
275 {"1.pathbbox", zpathbbox},
276 /* Internal operators */
277 {"0%path_continue", path_continue},
278 op_def_end(0)
279 };
280