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