xref: /plan9/sys/src/cmd/gs/src/zpath1.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
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