xref: /plan9-contrib/sys/src/cmd/gs/src/zpath1.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
17dd7cddfSDavid du Colombier /* Copyright (C) 1989, 1995, 1997, 1998, 1999 Aladdin Enterprises.  All rights reserved.
27dd7cddfSDavid du Colombier 
3*593dc095SDavid du Colombier   This software is provided AS-IS with no warranty, either express or
4*593dc095SDavid du Colombier   implied.
57dd7cddfSDavid du Colombier 
6*593dc095SDavid du Colombier   This software is distributed under license and may not be copied,
7*593dc095SDavid du Colombier   modified or distributed except as expressly authorized under the terms
8*593dc095SDavid du Colombier   of the license contained in the file LICENSE in this distribution.
97dd7cddfSDavid du Colombier 
10*593dc095SDavid du Colombier   For more information about licensing, please refer to
11*593dc095SDavid du Colombier   http://www.ghostscript.com/licensing/. For information on
12*593dc095SDavid du Colombier   commercial licensing, go to http://www.artifex.com/licensing/ or
13*593dc095SDavid du Colombier   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14*593dc095SDavid du Colombier   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
157dd7cddfSDavid du Colombier */
167dd7cddfSDavid du Colombier 
17*593dc095SDavid du Colombier /* $Id: zpath1.c,v 1.5 2002/06/16 03:43:51 lpd Exp $ */
187dd7cddfSDavid du Colombier /* PostScript Level 1 additional path operators */
197dd7cddfSDavid du Colombier #include "memory_.h"
207dd7cddfSDavid du Colombier #include "ghost.h"
217dd7cddfSDavid du Colombier #include "oper.h"
227dd7cddfSDavid du Colombier #include "oparc.h"		/* for prototypes */
237dd7cddfSDavid du Colombier #include "estack.h"		/* for pathforall */
247dd7cddfSDavid du Colombier #include "ialloc.h"
257dd7cddfSDavid du Colombier #include "igstate.h"
267dd7cddfSDavid du Colombier #include "gsstruct.h"
277dd7cddfSDavid du Colombier #include "gspath.h"
287dd7cddfSDavid du Colombier #include "store.h"
297dd7cddfSDavid du Colombier 
307dd7cddfSDavid du Colombier /* Forward references */
31*593dc095SDavid du Colombier private int common_arc(i_ctx_t *,
32*593dc095SDavid du Colombier 	  int (*)(gs_state *, floatp, floatp, floatp, floatp, floatp));
33*593dc095SDavid du Colombier private int common_arct(i_ctx_t *, float *);
347dd7cddfSDavid du Colombier 
357dd7cddfSDavid du Colombier /* <x> <y> <r> <ang1> <ang2> arc - */
367dd7cddfSDavid du Colombier int
zarc(i_ctx_t * i_ctx_p)377dd7cddfSDavid du Colombier zarc(i_ctx_t *i_ctx_p)
387dd7cddfSDavid du Colombier {
397dd7cddfSDavid du Colombier     return common_arc(i_ctx_p, gs_arc);
407dd7cddfSDavid du Colombier }
417dd7cddfSDavid du Colombier 
427dd7cddfSDavid du Colombier /* <x> <y> <r> <ang1> <ang2> arcn - */
437dd7cddfSDavid du Colombier int
zarcn(i_ctx_t * i_ctx_p)447dd7cddfSDavid du Colombier zarcn(i_ctx_t *i_ctx_p)
457dd7cddfSDavid du Colombier {
467dd7cddfSDavid du Colombier     return common_arc(i_ctx_p, gs_arcn);
477dd7cddfSDavid du Colombier }
487dd7cddfSDavid du Colombier 
497dd7cddfSDavid du Colombier /* Common code for arc[n] */
507dd7cddfSDavid du Colombier private int
common_arc(i_ctx_t * i_ctx_p,int (* aproc)(gs_state *,floatp,floatp,floatp,floatp,floatp))517dd7cddfSDavid du Colombier common_arc(i_ctx_t *i_ctx_p,
52*593dc095SDavid du Colombier       int (*aproc)(gs_state *, floatp, floatp, floatp, floatp, floatp))
537dd7cddfSDavid du Colombier {
547dd7cddfSDavid du Colombier     os_ptr op = osp;
557dd7cddfSDavid du Colombier     double xyra[5];		/* x, y, r, ang1, ang2 */
567dd7cddfSDavid du Colombier     int code = num_params(op, 5, xyra);
577dd7cddfSDavid du Colombier 
587dd7cddfSDavid du Colombier     if (code < 0)
597dd7cddfSDavid du Colombier 	return code;
607dd7cddfSDavid du Colombier     code = (*aproc)(igs, xyra[0], xyra[1], xyra[2], xyra[3], xyra[4]);
617dd7cddfSDavid du Colombier     if (code >= 0)
627dd7cddfSDavid du Colombier 	pop(5);
637dd7cddfSDavid du Colombier     return code;
647dd7cddfSDavid du Colombier }
657dd7cddfSDavid du Colombier 
667dd7cddfSDavid du Colombier /* <x1> <y1> <x2> <y2> <r> arct - */
677dd7cddfSDavid du Colombier int
zarct(i_ctx_t * i_ctx_p)687dd7cddfSDavid du Colombier zarct(i_ctx_t *i_ctx_p)
697dd7cddfSDavid du Colombier {
707dd7cddfSDavid du Colombier     int code = common_arct(i_ctx_p, (float *)0);
717dd7cddfSDavid du Colombier 
727dd7cddfSDavid du Colombier     if (code < 0)
737dd7cddfSDavid du Colombier 	return code;
747dd7cddfSDavid du Colombier     pop(5);
757dd7cddfSDavid du Colombier     return 0;
767dd7cddfSDavid du Colombier }
777dd7cddfSDavid du Colombier 
787dd7cddfSDavid du Colombier /* <x1> <y1> <x2> <y2> <r> arcto <xt1> <yt1> <xt2> <yt2> */
797dd7cddfSDavid du Colombier private int
zarcto(i_ctx_t * i_ctx_p)807dd7cddfSDavid du Colombier zarcto(i_ctx_t *i_ctx_p)
817dd7cddfSDavid du Colombier {
827dd7cddfSDavid du Colombier     os_ptr op = osp;
837dd7cddfSDavid du Colombier     float tanxy[4];		/* xt1, yt1, xt2, yt2 */
847dd7cddfSDavid du Colombier     int code = common_arct(i_ctx_p, tanxy);
857dd7cddfSDavid du Colombier 
867dd7cddfSDavid du Colombier     if (code < 0)
877dd7cddfSDavid du Colombier 	return code;
887dd7cddfSDavid du Colombier     make_real(op - 4, tanxy[0]);
897dd7cddfSDavid du Colombier     make_real(op - 3, tanxy[1]);
907dd7cddfSDavid du Colombier     make_real(op - 2, tanxy[2]);
917dd7cddfSDavid du Colombier     make_real(op - 1, tanxy[3]);
927dd7cddfSDavid du Colombier     pop(1);
937dd7cddfSDavid du Colombier     return 0;
947dd7cddfSDavid du Colombier }
957dd7cddfSDavid du Colombier 
967dd7cddfSDavid du Colombier /* Common code for arct[o] */
977dd7cddfSDavid du Colombier private int
common_arct(i_ctx_t * i_ctx_p,float * tanxy)987dd7cddfSDavid du Colombier common_arct(i_ctx_t *i_ctx_p, float *tanxy)
997dd7cddfSDavid du Colombier {
1007dd7cddfSDavid du Colombier     os_ptr op = osp;
1017dd7cddfSDavid du Colombier     double args[5];		/* x1, y1, x2, y2, r */
1027dd7cddfSDavid du Colombier     int code = num_params(op, 5, args);
1037dd7cddfSDavid du Colombier 
1047dd7cddfSDavid du Colombier     if (code < 0)
1057dd7cddfSDavid du Colombier 	return code;
1067dd7cddfSDavid du Colombier     return gs_arcto(igs, args[0], args[1], args[2], args[3], args[4], tanxy);
1077dd7cddfSDavid du Colombier }
1087dd7cddfSDavid du Colombier 
1097dd7cddfSDavid du Colombier /* - .dashpath - */
1107dd7cddfSDavid du Colombier private int
zdashpath(i_ctx_t * i_ctx_p)1117dd7cddfSDavid du Colombier zdashpath(i_ctx_t *i_ctx_p)
1127dd7cddfSDavid du Colombier {
1137dd7cddfSDavid du Colombier     return gs_dashpath(igs);
1147dd7cddfSDavid du Colombier }
1157dd7cddfSDavid du Colombier 
1167dd7cddfSDavid du Colombier /* - flattenpath - */
1177dd7cddfSDavid du Colombier private int
zflattenpath(i_ctx_t * i_ctx_p)1187dd7cddfSDavid du Colombier zflattenpath(i_ctx_t *i_ctx_p)
1197dd7cddfSDavid du Colombier {
1207dd7cddfSDavid du Colombier     return gs_flattenpath(igs);
1217dd7cddfSDavid du Colombier }
1227dd7cddfSDavid du Colombier 
1237dd7cddfSDavid du Colombier /* - reversepath - */
1247dd7cddfSDavid du Colombier private int
zreversepath(i_ctx_t * i_ctx_p)1257dd7cddfSDavid du Colombier zreversepath(i_ctx_t *i_ctx_p)
1267dd7cddfSDavid du Colombier {
1277dd7cddfSDavid du Colombier     return gs_reversepath(igs);
1287dd7cddfSDavid du Colombier }
1297dd7cddfSDavid du Colombier 
1307dd7cddfSDavid du Colombier /* - strokepath - */
1317dd7cddfSDavid du Colombier private int
zstrokepath(i_ctx_t * i_ctx_p)1327dd7cddfSDavid du Colombier zstrokepath(i_ctx_t *i_ctx_p)
1337dd7cddfSDavid du Colombier {
1347dd7cddfSDavid du Colombier     return gs_strokepath(igs);
1357dd7cddfSDavid du Colombier }
1367dd7cddfSDavid du Colombier 
1377dd7cddfSDavid du Colombier /* - clippath - */
1387dd7cddfSDavid du Colombier private int
zclippath(i_ctx_t * i_ctx_p)1397dd7cddfSDavid du Colombier zclippath(i_ctx_t *i_ctx_p)
1407dd7cddfSDavid du Colombier {
1417dd7cddfSDavid du Colombier     return gs_clippath(igs);
1427dd7cddfSDavid du Colombier }
1437dd7cddfSDavid du Colombier 
1447dd7cddfSDavid du Colombier /* <bool> .pathbbox <llx> <lly> <urx> <ury> */
1457dd7cddfSDavid du Colombier private int
zpathbbox(i_ctx_t * i_ctx_p)1467dd7cddfSDavid du Colombier zpathbbox(i_ctx_t *i_ctx_p)
1477dd7cddfSDavid du Colombier {
1487dd7cddfSDavid du Colombier     os_ptr op = osp;
1497dd7cddfSDavid du Colombier     gs_rect box;
1507dd7cddfSDavid du Colombier     int code;
1517dd7cddfSDavid du Colombier 
1527dd7cddfSDavid du Colombier     check_type(*op, t_boolean);
1537dd7cddfSDavid du Colombier     code = gs_upathbbox(igs, &box, op->value.boolval);
1547dd7cddfSDavid du Colombier     if (code < 0)
1557dd7cddfSDavid du Colombier 	return code;
1567dd7cddfSDavid du Colombier     push(3);
1577dd7cddfSDavid du Colombier     make_real(op - 3, box.p.x);
1587dd7cddfSDavid du Colombier     make_real(op - 2, box.p.y);
1597dd7cddfSDavid du Colombier     make_real(op - 1, box.q.x);
1607dd7cddfSDavid du Colombier     make_real(op, box.q.y);
1617dd7cddfSDavid du Colombier     return 0;
1627dd7cddfSDavid du Colombier }
1637dd7cddfSDavid du Colombier 
1647dd7cddfSDavid du Colombier /* <moveproc> <lineproc> <curveproc> <closeproc> pathforall - */
165*593dc095SDavid du Colombier private int path_continue(i_ctx_t *);
166*593dc095SDavid du Colombier private int path_cleanup(i_ctx_t *);
1677dd7cddfSDavid du Colombier private int
zpathforall(i_ctx_t * i_ctx_p)1687dd7cddfSDavid du Colombier zpathforall(i_ctx_t *i_ctx_p)
1697dd7cddfSDavid du Colombier {
1707dd7cddfSDavid du Colombier     os_ptr op = osp;
1717dd7cddfSDavid du Colombier     gs_path_enum *penum;
1727dd7cddfSDavid du Colombier     int code;
1737dd7cddfSDavid du Colombier 
1747dd7cddfSDavid du Colombier     check_proc(op[-3]);
1757dd7cddfSDavid du Colombier     check_proc(op[-2]);
1767dd7cddfSDavid du Colombier     check_proc(op[-1]);
1777dd7cddfSDavid du Colombier     check_proc(*op);
1787dd7cddfSDavid du Colombier     check_estack(8);
1797dd7cddfSDavid du Colombier     if ((penum = gs_path_enum_alloc(imemory, "pathforall")) == 0)
1807dd7cddfSDavid du Colombier 	return_error(e_VMerror);
1817dd7cddfSDavid du Colombier     code = gs_path_enum_init(penum, igs);
1827dd7cddfSDavid du Colombier     if (code < 0) {
1837dd7cddfSDavid du Colombier 	ifree_object(penum, "path_cleanup");
1847dd7cddfSDavid du Colombier 	return code;
1857dd7cddfSDavid du Colombier     }
1867dd7cddfSDavid du Colombier     /* Push a mark, the four procedures, and the path enumerator. */
1877dd7cddfSDavid du Colombier     push_mark_estack(es_for, path_cleanup);	/* iterator */
1887dd7cddfSDavid du Colombier     memcpy(esp + 1, op - 3, 4 * sizeof(ref));	/* 4 procs */
1897dd7cddfSDavid du Colombier     esp += 5;
1907dd7cddfSDavid du Colombier     make_istruct(esp, 0, penum);
1917dd7cddfSDavid du Colombier     push_op_estack(path_continue);
1927dd7cddfSDavid du Colombier     pop(4);
1937dd7cddfSDavid du Colombier     op -= 4;
1947dd7cddfSDavid du Colombier     return o_push_estack;
1957dd7cddfSDavid du Colombier }
1967dd7cddfSDavid du Colombier /* Continuation procedure for pathforall */
197*593dc095SDavid du Colombier private void pf_push(i_ctx_t *, gs_point *, int);
1987dd7cddfSDavid du Colombier private int
path_continue(i_ctx_t * i_ctx_p)1997dd7cddfSDavid du Colombier path_continue(i_ctx_t *i_ctx_p)
2007dd7cddfSDavid du Colombier {
2017dd7cddfSDavid du Colombier     gs_path_enum *penum = r_ptr(esp, gs_path_enum);
2027dd7cddfSDavid du Colombier     gs_point ppts[3];
2037dd7cddfSDavid du Colombier     int code;
2047dd7cddfSDavid du Colombier 
2057dd7cddfSDavid du Colombier     /* Make sure we have room on the o-stack for the worst case */
2067dd7cddfSDavid du Colombier     /* before we enumerate the next path element. */
2077dd7cddfSDavid du Colombier     check_ostack(6);		/* 3 points for curveto */
2087dd7cddfSDavid du Colombier     code = gs_path_enum_next(penum, ppts);
2097dd7cddfSDavid du Colombier     switch (code) {
2107dd7cddfSDavid du Colombier 	case 0:		/* all done */
2117dd7cddfSDavid du Colombier 	    esp -= 6;
2127dd7cddfSDavid du Colombier 	    path_cleanup(i_ctx_p);
2137dd7cddfSDavid du Colombier 	    return o_pop_estack;
2147dd7cddfSDavid du Colombier 	default:		/* error */
2157dd7cddfSDavid du Colombier 	    return code;
2167dd7cddfSDavid du Colombier 	case gs_pe_moveto:
2177dd7cddfSDavid du Colombier 	    esp[2] = esp[-4];	/* moveto proc */
2187dd7cddfSDavid du Colombier 	    pf_push(i_ctx_p, ppts, 1);
2197dd7cddfSDavid du Colombier 	    break;
2207dd7cddfSDavid du Colombier 	case gs_pe_lineto:
2217dd7cddfSDavid du Colombier 	    esp[2] = esp[-3];	/* lineto proc */
2227dd7cddfSDavid du Colombier 	    pf_push(i_ctx_p, ppts, 1);
2237dd7cddfSDavid du Colombier 	    break;
2247dd7cddfSDavid du Colombier 	case gs_pe_curveto:
2257dd7cddfSDavid du Colombier 	    esp[2] = esp[-2];	/* curveto proc */
2267dd7cddfSDavid du Colombier 	    pf_push(i_ctx_p, ppts, 3);
2277dd7cddfSDavid du Colombier 	    break;
2287dd7cddfSDavid du Colombier 	case gs_pe_closepath:
2297dd7cddfSDavid du Colombier 	    esp[2] = esp[-1];	/* closepath proc */
2307dd7cddfSDavid du Colombier 	    break;
2317dd7cddfSDavid du Colombier     }
2327dd7cddfSDavid du Colombier     push_op_estack(path_continue);
2337dd7cddfSDavid du Colombier     ++esp;			/* include pushed procedure */
2347dd7cddfSDavid du Colombier     return o_push_estack;
2357dd7cddfSDavid du Colombier }
2367dd7cddfSDavid du Colombier /* Internal procedure to push one or more points */
2377dd7cddfSDavid du Colombier private void
pf_push(i_ctx_t * i_ctx_p,gs_point * ppts,int n)2387dd7cddfSDavid du Colombier pf_push(i_ctx_t *i_ctx_p, gs_point * ppts, int n)
2397dd7cddfSDavid du Colombier {
2407dd7cddfSDavid du Colombier     os_ptr op = osp;
2417dd7cddfSDavid du Colombier 
2427dd7cddfSDavid du Colombier     while (n--) {
2437dd7cddfSDavid du Colombier 	op += 2;
2447dd7cddfSDavid du Colombier 	make_real(op - 1, ppts->x);
2457dd7cddfSDavid du Colombier 	make_real(op, ppts->y);
2467dd7cddfSDavid du Colombier 	ppts++;
2477dd7cddfSDavid du Colombier     }
2487dd7cddfSDavid du Colombier     osp = op;
2497dd7cddfSDavid du Colombier }
2507dd7cddfSDavid du Colombier /* Clean up after a pathforall */
2517dd7cddfSDavid du Colombier private int
path_cleanup(i_ctx_t * i_ctx_p)2527dd7cddfSDavid du Colombier path_cleanup(i_ctx_t *i_ctx_p)
2537dd7cddfSDavid du Colombier {
2547dd7cddfSDavid du Colombier     gs_path_enum *penum = r_ptr(esp + 6, gs_path_enum);
2557dd7cddfSDavid du Colombier 
2567dd7cddfSDavid du Colombier     gs_path_enum_cleanup(penum);
2577dd7cddfSDavid du Colombier     ifree_object(penum, "path_cleanup");
2587dd7cddfSDavid du Colombier     return 0;
2597dd7cddfSDavid du Colombier }
2607dd7cddfSDavid du Colombier 
2617dd7cddfSDavid du Colombier /* ------ Initialization procedure ------ */
2627dd7cddfSDavid du Colombier 
2637dd7cddfSDavid du Colombier const op_def zpath1_op_defs[] =
2647dd7cddfSDavid du Colombier {
2657dd7cddfSDavid du Colombier     {"5arc", zarc},
2667dd7cddfSDavid du Colombier     {"5arcn", zarcn},
2677dd7cddfSDavid du Colombier     {"5arct", zarct},
2687dd7cddfSDavid du Colombier     {"5arcto", zarcto},
2697dd7cddfSDavid du Colombier     {"0clippath", zclippath},
2707dd7cddfSDavid du Colombier     {"0.dashpath", zdashpath},
2717dd7cddfSDavid du Colombier     {"0flattenpath", zflattenpath},
2727dd7cddfSDavid du Colombier     {"4pathforall", zpathforall},
2737dd7cddfSDavid du Colombier     {"0reversepath", zreversepath},
2747dd7cddfSDavid du Colombier     {"0strokepath", zstrokepath},
2757dd7cddfSDavid du Colombier     {"1.pathbbox", zpathbbox},
2767dd7cddfSDavid du Colombier 		/* Internal operators */
2777dd7cddfSDavid du Colombier     {"0%path_continue", path_continue},
2787dd7cddfSDavid du Colombier     op_def_end(0)
2797dd7cddfSDavid du Colombier };
280