xref: /plan9/sys/src/cmd/gs/src/zupath.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
17dd7cddfSDavid du Colombier /* Copyright (C) 1990, 1996, 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: zupath.c,v 1.10 2004/08/04 19:36:13 stefan Exp $ */
187dd7cddfSDavid du Colombier /* Operators related to user paths */
197dd7cddfSDavid du Colombier #include "ghost.h"
207dd7cddfSDavid du Colombier #include "oper.h"
217dd7cddfSDavid du Colombier #include "oparc.h"
227dd7cddfSDavid du Colombier #include "idict.h"
237dd7cddfSDavid du Colombier #include "dstack.h"
247dd7cddfSDavid du Colombier #include "igstate.h"
257dd7cddfSDavid du Colombier #include "iname.h"
267dd7cddfSDavid du Colombier #include "iutil.h"
277dd7cddfSDavid du Colombier #include "store.h"
287dd7cddfSDavid du Colombier #include "stream.h"
297dd7cddfSDavid du Colombier #include "ibnum.h"
307dd7cddfSDavid du Colombier #include "gsmatrix.h"
317dd7cddfSDavid du Colombier #include "gsstate.h"
327dd7cddfSDavid du Colombier #include "gscoord.h"
337dd7cddfSDavid du Colombier #include "gspaint.h"
347dd7cddfSDavid du Colombier #include "gxfixed.h"
357dd7cddfSDavid du Colombier #include "gxdevice.h"
367dd7cddfSDavid du Colombier #include "gspath.h"
377dd7cddfSDavid du Colombier #include "gzpath.h"		/* for saving path */
387dd7cddfSDavid du Colombier #include "gzstate.h"		/* for accessing path */
397dd7cddfSDavid du Colombier 
407dd7cddfSDavid du Colombier /* Imported data */
417dd7cddfSDavid du Colombier extern const gx_device gs_hit_device;
427dd7cddfSDavid du Colombier extern const int gs_hit_detected;
437dd7cddfSDavid du Colombier 
447dd7cddfSDavid du Colombier /* Forward references */
45*593dc095SDavid du Colombier private int upath_append(os_ptr, i_ctx_t *);
46*593dc095SDavid du Colombier private int upath_stroke(i_ctx_t *, gs_matrix *);
477dd7cddfSDavid du Colombier 
487dd7cddfSDavid du Colombier /* ---------------- Insideness testing ---------------- */
497dd7cddfSDavid du Colombier 
507dd7cddfSDavid du Colombier /* Forward references */
51*593dc095SDavid du Colombier private int in_test(i_ctx_t *, int (*)(gs_state *));
52*593dc095SDavid du Colombier private int in_path(os_ptr, i_ctx_t *, gx_device *);
53*593dc095SDavid du Colombier private int in_path_result(i_ctx_t *, int, int);
54*593dc095SDavid du Colombier private int in_utest(i_ctx_t *, int (*)(gs_state *));
55*593dc095SDavid du Colombier private int in_upath(i_ctx_t *, gx_device *);
56*593dc095SDavid du Colombier private int in_upath_result(i_ctx_t *, int, int);
577dd7cddfSDavid du Colombier 
587dd7cddfSDavid du Colombier /* <x> <y> ineofill <bool> */
597dd7cddfSDavid du Colombier /* <userpath> ineofill <bool> */
607dd7cddfSDavid du Colombier private int
zineofill(i_ctx_t * i_ctx_p)617dd7cddfSDavid du Colombier zineofill(i_ctx_t *i_ctx_p)
627dd7cddfSDavid du Colombier {
637dd7cddfSDavid du Colombier     return in_test(i_ctx_p, gs_eofill);
647dd7cddfSDavid du Colombier }
657dd7cddfSDavid du Colombier 
667dd7cddfSDavid du Colombier /* <x> <y> infill <bool> */
677dd7cddfSDavid du Colombier /* <userpath> infill <bool> */
687dd7cddfSDavid du Colombier private int
zinfill(i_ctx_t * i_ctx_p)697dd7cddfSDavid du Colombier zinfill(i_ctx_t *i_ctx_p)
707dd7cddfSDavid du Colombier {
717dd7cddfSDavid du Colombier     return in_test(i_ctx_p, gs_fill);
727dd7cddfSDavid du Colombier }
737dd7cddfSDavid du Colombier 
747dd7cddfSDavid du Colombier /* <x> <y> instroke <bool> */
757dd7cddfSDavid du Colombier /* <userpath> instroke <bool> */
767dd7cddfSDavid du Colombier private int
zinstroke(i_ctx_t * i_ctx_p)777dd7cddfSDavid du Colombier zinstroke(i_ctx_t *i_ctx_p)
787dd7cddfSDavid du Colombier {
797dd7cddfSDavid du Colombier     return in_test(i_ctx_p, gs_stroke);
807dd7cddfSDavid du Colombier }
817dd7cddfSDavid du Colombier 
827dd7cddfSDavid du Colombier /* <x> <y> <userpath> inueofill <bool> */
837dd7cddfSDavid du Colombier /* <userpath1> <userpath2> inueofill <bool> */
847dd7cddfSDavid du Colombier private int
zinueofill(i_ctx_t * i_ctx_p)857dd7cddfSDavid du Colombier zinueofill(i_ctx_t *i_ctx_p)
867dd7cddfSDavid du Colombier {
877dd7cddfSDavid du Colombier     return in_utest(i_ctx_p, gs_eofill);
887dd7cddfSDavid du Colombier }
897dd7cddfSDavid du Colombier 
907dd7cddfSDavid du Colombier /* <x> <y> <userpath> inufill <bool> */
917dd7cddfSDavid du Colombier /* <userpath1> <userpath2> inufill <bool> */
927dd7cddfSDavid du Colombier private int
zinufill(i_ctx_t * i_ctx_p)937dd7cddfSDavid du Colombier zinufill(i_ctx_t *i_ctx_p)
947dd7cddfSDavid du Colombier {
957dd7cddfSDavid du Colombier     return in_utest(i_ctx_p, gs_fill);
967dd7cddfSDavid du Colombier }
977dd7cddfSDavid du Colombier 
987dd7cddfSDavid du Colombier /* <x> <y> <userpath> inustroke <bool> */
997dd7cddfSDavid du Colombier /* <x> <y> <userpath> <matrix> inustroke <bool> */
1007dd7cddfSDavid du Colombier /* <userpath1> <userpath2> inustroke <bool> */
1017dd7cddfSDavid du Colombier /* <userpath1> <userpath2> <matrix> inustroke <bool> */
1027dd7cddfSDavid du Colombier private int
zinustroke(i_ctx_t * i_ctx_p)1037dd7cddfSDavid du Colombier zinustroke(i_ctx_t *i_ctx_p)
1047dd7cddfSDavid du Colombier {	/* This is different because of the optional matrix operand. */
1057dd7cddfSDavid du Colombier     os_ptr op = osp;
1067dd7cddfSDavid du Colombier     int code = gs_gsave(igs);
1077dd7cddfSDavid du Colombier     int spop, npop;
1087dd7cddfSDavid du Colombier     gs_matrix mat;
1097dd7cddfSDavid du Colombier     gx_device hdev;
1107dd7cddfSDavid du Colombier 
1117dd7cddfSDavid du Colombier     if (code < 0)
1127dd7cddfSDavid du Colombier 	return code;
1137dd7cddfSDavid du Colombier     if ((spop = upath_stroke(i_ctx_p, &mat)) < 0) {
1147dd7cddfSDavid du Colombier 	gs_grestore(igs);
1157dd7cddfSDavid du Colombier 	return spop;
1167dd7cddfSDavid du Colombier     }
1177dd7cddfSDavid du Colombier     if ((npop = in_path(op - spop, i_ctx_p, &hdev)) < 0) {
1187dd7cddfSDavid du Colombier 	gs_grestore(igs);
1197dd7cddfSDavid du Colombier 	return npop;
1207dd7cddfSDavid du Colombier     }
1217dd7cddfSDavid du Colombier     if (npop > 1)		/* matrix was supplied */
1227dd7cddfSDavid du Colombier 	code = gs_concat(igs, &mat);
1237dd7cddfSDavid du Colombier     if (code >= 0)
1247dd7cddfSDavid du Colombier 	code = gs_stroke(igs);
1257dd7cddfSDavid du Colombier     return in_upath_result(i_ctx_p, npop + spop, code);
1267dd7cddfSDavid du Colombier }
1277dd7cddfSDavid du Colombier 
1287dd7cddfSDavid du Colombier /* ------ Internal routines ------ */
1297dd7cddfSDavid du Colombier 
1307dd7cddfSDavid du Colombier /* Do the work of the non-user-path insideness operators. */
1317dd7cddfSDavid du Colombier private int
in_test(i_ctx_t * i_ctx_p,int (* paintproc)(gs_state *))132*593dc095SDavid du Colombier in_test(i_ctx_t *i_ctx_p, int (*paintproc)(gs_state *))
1337dd7cddfSDavid du Colombier {
1347dd7cddfSDavid du Colombier     os_ptr op = osp;
1357dd7cddfSDavid du Colombier     gx_device hdev;
1367dd7cddfSDavid du Colombier     int npop = in_path(op, i_ctx_p, &hdev);
1377dd7cddfSDavid du Colombier     int code;
1387dd7cddfSDavid du Colombier 
1397dd7cddfSDavid du Colombier     if (npop < 0)
1407dd7cddfSDavid du Colombier 	return npop;
1417dd7cddfSDavid du Colombier     code = (*paintproc)(igs);
1427dd7cddfSDavid du Colombier     return in_path_result(i_ctx_p, npop, code);
1437dd7cddfSDavid du Colombier }
1447dd7cddfSDavid du Colombier 
1457dd7cddfSDavid du Colombier /* Set up a clipping path and device for insideness testing. */
1467dd7cddfSDavid du Colombier private int
in_path(os_ptr oppath,i_ctx_t * i_ctx_p,gx_device * phdev)1477dd7cddfSDavid du Colombier in_path(os_ptr oppath, i_ctx_t *i_ctx_p, gx_device * phdev)
1487dd7cddfSDavid du Colombier {
1497dd7cddfSDavid du Colombier     int code = gs_gsave(igs);
1507dd7cddfSDavid du Colombier     int npop;
1517dd7cddfSDavid du Colombier     double uxy[2];
1527dd7cddfSDavid du Colombier 
1537dd7cddfSDavid du Colombier     if (code < 0)
1547dd7cddfSDavid du Colombier 	return code;
1557dd7cddfSDavid du Colombier     code = num_params(oppath, 2, uxy);
1567dd7cddfSDavid du Colombier     if (code >= 0) {		/* Aperture is a single pixel. */
1577dd7cddfSDavid du Colombier 	gs_point dxy;
1587dd7cddfSDavid du Colombier 	gs_fixed_rect fr;
1597dd7cddfSDavid du Colombier 
1607dd7cddfSDavid du Colombier 	gs_transform(igs, uxy[0], uxy[1], &dxy);
1617dd7cddfSDavid du Colombier 	fr.p.x = fixed_floor(float2fixed(dxy.x));
1627dd7cddfSDavid du Colombier 	fr.p.y = fixed_floor(float2fixed(dxy.y));
1637dd7cddfSDavid du Colombier 	fr.q.x = fr.p.x + fixed_1;
1647dd7cddfSDavid du Colombier 	fr.q.y = fr.p.y + fixed_1;
1657dd7cddfSDavid du Colombier 	code = gx_clip_to_rectangle(igs, &fr);
1667dd7cddfSDavid du Colombier 	npop = 2;
1677dd7cddfSDavid du Colombier     } else {			/* Aperture is a user path. */
1687dd7cddfSDavid du Colombier 	/* We have to set the clipping path without disturbing */
1697dd7cddfSDavid du Colombier 	/* the current path. */
1707dd7cddfSDavid du Colombier 	gx_path *ipath = igs->path;
1717dd7cddfSDavid du Colombier 	gx_path save;
1727dd7cddfSDavid du Colombier 
1737dd7cddfSDavid du Colombier 	gx_path_init_local(&save, imemory);
1747dd7cddfSDavid du Colombier 	gx_path_assign_preserve(&save, ipath);
1757dd7cddfSDavid du Colombier 	gs_newpath(igs);
1767dd7cddfSDavid du Colombier 	code = upath_append(oppath, i_ctx_p);
1777dd7cddfSDavid du Colombier 	if (code >= 0)
1787dd7cddfSDavid du Colombier 	    code = gx_clip_to_path(igs);
1797dd7cddfSDavid du Colombier 	gx_path_assign_free(igs->path, &save);
1807dd7cddfSDavid du Colombier 	npop = 1;
1817dd7cddfSDavid du Colombier     }
1827dd7cddfSDavid du Colombier     if (code < 0) {
1837dd7cddfSDavid du Colombier 	gs_grestore(igs);
1847dd7cddfSDavid du Colombier 	return code;
1857dd7cddfSDavid du Colombier     }
1867dd7cddfSDavid du Colombier     /* Install the hit detection device. */
1877dd7cddfSDavid du Colombier     gx_set_device_color_1(igs);
1887dd7cddfSDavid du Colombier     gx_device_init((gx_device *) phdev, (const gx_device *)&gs_hit_device,
1897dd7cddfSDavid du Colombier 		   NULL, true);
1907dd7cddfSDavid du Colombier     phdev->width = phdev->height = max_int;
1917dd7cddfSDavid du Colombier     gx_device_fill_in_procs(phdev);
1927dd7cddfSDavid du Colombier     gx_set_device_only(igs, phdev);
1937dd7cddfSDavid du Colombier     return npop;
1947dd7cddfSDavid du Colombier }
1957dd7cddfSDavid du Colombier 
1967dd7cddfSDavid du Colombier /* Finish an insideness test. */
1977dd7cddfSDavid du Colombier private int
in_path_result(i_ctx_t * i_ctx_p,int npop,int code)1987dd7cddfSDavid du Colombier in_path_result(i_ctx_t *i_ctx_p, int npop, int code)
1997dd7cddfSDavid du Colombier {
2007dd7cddfSDavid du Colombier     os_ptr op = osp;
2017dd7cddfSDavid du Colombier     bool result;
2027dd7cddfSDavid du Colombier 
2037dd7cddfSDavid du Colombier     gs_grestore(igs);		/* matches gsave in in_path */
2047dd7cddfSDavid du Colombier     if (code == gs_hit_detected)
2057dd7cddfSDavid du Colombier 	result = true;
2067dd7cddfSDavid du Colombier     else if (code == 0)		/* completed painting without a hit */
2077dd7cddfSDavid du Colombier 	result = false;
2087dd7cddfSDavid du Colombier     else			/* error */
2097dd7cddfSDavid du Colombier 	return code;
2107dd7cddfSDavid du Colombier     npop--;
2117dd7cddfSDavid du Colombier     pop(npop);
2127dd7cddfSDavid du Colombier     op -= npop;
2137dd7cddfSDavid du Colombier     make_bool(op, result);
2147dd7cddfSDavid du Colombier     return 0;
2157dd7cddfSDavid du Colombier 
2167dd7cddfSDavid du Colombier }
2177dd7cddfSDavid du Colombier 
2187dd7cddfSDavid du Colombier /* Do the work of the user-path insideness operators. */
2197dd7cddfSDavid du Colombier private int
in_utest(i_ctx_t * i_ctx_p,int (* paintproc)(gs_state *))220*593dc095SDavid du Colombier in_utest(i_ctx_t *i_ctx_p, int (*paintproc)(gs_state *))
2217dd7cddfSDavid du Colombier {
2227dd7cddfSDavid du Colombier     gx_device hdev;
2237dd7cddfSDavid du Colombier     int npop = in_upath(i_ctx_p, &hdev);
2247dd7cddfSDavid du Colombier     int code;
2257dd7cddfSDavid du Colombier 
2267dd7cddfSDavid du Colombier     if (npop < 0)
2277dd7cddfSDavid du Colombier 	return npop;
2287dd7cddfSDavid du Colombier     code = (*paintproc)(igs);
2297dd7cddfSDavid du Colombier     return in_upath_result(i_ctx_p, npop, code);
2307dd7cddfSDavid du Colombier }
2317dd7cddfSDavid du Colombier 
2327dd7cddfSDavid du Colombier /* Set up a clipping path and device for insideness testing */
2337dd7cddfSDavid du Colombier /* with a user path. */
2347dd7cddfSDavid du Colombier private int
in_upath(i_ctx_t * i_ctx_p,gx_device * phdev)2357dd7cddfSDavid du Colombier in_upath(i_ctx_t *i_ctx_p, gx_device * phdev)
2367dd7cddfSDavid du Colombier {
2377dd7cddfSDavid du Colombier     os_ptr op = osp;
2387dd7cddfSDavid du Colombier     int code = gs_gsave(igs);
2397dd7cddfSDavid du Colombier     int npop;
2407dd7cddfSDavid du Colombier 
2417dd7cddfSDavid du Colombier     if (code < 0)
2427dd7cddfSDavid du Colombier 	return code;
2437dd7cddfSDavid du Colombier     if ((code = upath_append(op, i_ctx_p)) < 0 ||
2447dd7cddfSDavid du Colombier 	(npop = in_path(op - 1, i_ctx_p, phdev)) < 0
2457dd7cddfSDavid du Colombier 	) {
2467dd7cddfSDavid du Colombier 	gs_grestore(igs);
2477dd7cddfSDavid du Colombier 	return code;
2487dd7cddfSDavid du Colombier     }
2497dd7cddfSDavid du Colombier     return npop + 1;
2507dd7cddfSDavid du Colombier }
2517dd7cddfSDavid du Colombier 
2527dd7cddfSDavid du Colombier /* Finish an insideness test with a user path. */
2537dd7cddfSDavid du Colombier private int
in_upath_result(i_ctx_t * i_ctx_p,int npop,int code)2547dd7cddfSDavid du Colombier in_upath_result(i_ctx_t *i_ctx_p, int npop, int code)
2557dd7cddfSDavid du Colombier {
2567dd7cddfSDavid du Colombier     gs_grestore(igs);		/* matches gsave in in_upath */
2577dd7cddfSDavid du Colombier     return in_path_result(i_ctx_p, npop, code);
2587dd7cddfSDavid du Colombier }
2597dd7cddfSDavid du Colombier 
2607dd7cddfSDavid du Colombier /* ---------------- User paths ---------------- */
2617dd7cddfSDavid du Colombier 
2627dd7cddfSDavid du Colombier /* User path operator codes */
2637dd7cddfSDavid du Colombier typedef enum {
2647dd7cddfSDavid du Colombier     upath_op_setbbox = 0,
2657dd7cddfSDavid du Colombier     upath_op_moveto = 1,
2667dd7cddfSDavid du Colombier     upath_op_rmoveto = 2,
2677dd7cddfSDavid du Colombier     upath_op_lineto = 3,
2687dd7cddfSDavid du Colombier     upath_op_rlineto = 4,
2697dd7cddfSDavid du Colombier     upath_op_curveto = 5,
2707dd7cddfSDavid du Colombier     upath_op_rcurveto = 6,
2717dd7cddfSDavid du Colombier     upath_op_arc = 7,
2727dd7cddfSDavid du Colombier     upath_op_arcn = 8,
2737dd7cddfSDavid du Colombier     upath_op_arct = 9,
2747dd7cddfSDavid du Colombier     upath_op_closepath = 10,
2757dd7cddfSDavid du Colombier     upath_op_ucache = 11
2767dd7cddfSDavid du Colombier } upath_op;
2777dd7cddfSDavid du Colombier 
2787dd7cddfSDavid du Colombier #define UPATH_MAX_OP 11
2797dd7cddfSDavid du Colombier #define UPATH_REPEAT 32
2807dd7cddfSDavid du Colombier static const byte up_nargs[UPATH_MAX_OP + 1] = {
2817dd7cddfSDavid du Colombier     4, 2, 2, 2, 2, 6, 6, 5, 5, 5, 0, 0
2827dd7cddfSDavid du Colombier };
2837dd7cddfSDavid du Colombier 
2847dd7cddfSDavid du Colombier /* Declare operator procedures not declared in opextern.h. */
285*593dc095SDavid du Colombier int zsetbbox(i_ctx_t *);
286*593dc095SDavid du Colombier private int zucache(i_ctx_t *);
2877dd7cddfSDavid du Colombier 
2887dd7cddfSDavid du Colombier #undef zp
2897dd7cddfSDavid du Colombier static const op_proc_t up_ops[UPATH_MAX_OP + 1] = {
2907dd7cddfSDavid du Colombier     zsetbbox, zmoveto, zrmoveto, zlineto, zrlineto,
2917dd7cddfSDavid du Colombier     zcurveto, zrcurveto, zarc, zarcn, zarct,
2927dd7cddfSDavid du Colombier     zclosepath, zucache
2937dd7cddfSDavid du Colombier };
2947dd7cddfSDavid du Colombier 
2957dd7cddfSDavid du Colombier /* - ucache - */
2967dd7cddfSDavid du Colombier private int
zucache(i_ctx_t * i_ctx_p)2977dd7cddfSDavid du Colombier zucache(i_ctx_t *i_ctx_p)
2987dd7cddfSDavid du Colombier {
2997dd7cddfSDavid du Colombier     /* A no-op for now. */
3007dd7cddfSDavid du Colombier     return 0;
3017dd7cddfSDavid du Colombier }
3027dd7cddfSDavid du Colombier 
3037dd7cddfSDavid du Colombier /* <userpath> uappend - */
3047dd7cddfSDavid du Colombier private int
zuappend(i_ctx_t * i_ctx_p)3057dd7cddfSDavid du Colombier zuappend(i_ctx_t *i_ctx_p)
3067dd7cddfSDavid du Colombier {
3077dd7cddfSDavid du Colombier     os_ptr op = osp;
3087dd7cddfSDavid du Colombier     int code = gs_gsave(igs);
3097dd7cddfSDavid du Colombier 
3107dd7cddfSDavid du Colombier     if (code < 0)
3117dd7cddfSDavid du Colombier 	return code;
3127dd7cddfSDavid du Colombier     if ((code = upath_append(op, i_ctx_p)) >= 0)
3137dd7cddfSDavid du Colombier 	code = gs_upmergepath(igs);
3147dd7cddfSDavid du Colombier     gs_grestore(igs);
3157dd7cddfSDavid du Colombier     if (code < 0)
3167dd7cddfSDavid du Colombier 	return code;
3177dd7cddfSDavid du Colombier     pop(1);
3187dd7cddfSDavid du Colombier     return 0;
3197dd7cddfSDavid du Colombier }
3207dd7cddfSDavid du Colombier 
3217dd7cddfSDavid du Colombier /* <userpath> ueofill - */
3227dd7cddfSDavid du Colombier private int
zueofill(i_ctx_t * i_ctx_p)3237dd7cddfSDavid du Colombier zueofill(i_ctx_t *i_ctx_p)
3247dd7cddfSDavid du Colombier {
3257dd7cddfSDavid du Colombier     os_ptr op = osp;
3267dd7cddfSDavid du Colombier     int code = gs_gsave(igs);
3277dd7cddfSDavid du Colombier 
3287dd7cddfSDavid du Colombier     if (code < 0)
3297dd7cddfSDavid du Colombier 	return code;
3307dd7cddfSDavid du Colombier     if ((code = upath_append(op, i_ctx_p)) >= 0)
3317dd7cddfSDavid du Colombier 	code = gs_eofill(igs);
3327dd7cddfSDavid du Colombier     gs_grestore(igs);
3337dd7cddfSDavid du Colombier     if (code < 0)
3347dd7cddfSDavid du Colombier 	return code;
3357dd7cddfSDavid du Colombier     pop(1);
3367dd7cddfSDavid du Colombier     return 0;
3377dd7cddfSDavid du Colombier }
3387dd7cddfSDavid du Colombier 
3397dd7cddfSDavid du Colombier /* <userpath> ufill - */
3407dd7cddfSDavid du Colombier private int
zufill(i_ctx_t * i_ctx_p)3417dd7cddfSDavid du Colombier zufill(i_ctx_t *i_ctx_p)
3427dd7cddfSDavid du Colombier {
3437dd7cddfSDavid du Colombier     os_ptr op = osp;
3447dd7cddfSDavid du Colombier     int code = gs_gsave(igs);
3457dd7cddfSDavid du Colombier 
3467dd7cddfSDavid du Colombier     if (code < 0)
3477dd7cddfSDavid du Colombier 	return code;
3487dd7cddfSDavid du Colombier     if ((code = upath_append(op, i_ctx_p)) >= 0)
3497dd7cddfSDavid du Colombier 	code = gs_fill(igs);
3507dd7cddfSDavid du Colombier     gs_grestore(igs);
3517dd7cddfSDavid du Colombier     if (code < 0)
3527dd7cddfSDavid du Colombier 	return code;
3537dd7cddfSDavid du Colombier     pop(1);
3547dd7cddfSDavid du Colombier     return 0;
3557dd7cddfSDavid du Colombier }
3567dd7cddfSDavid du Colombier 
3577dd7cddfSDavid du Colombier /* <userpath> ustroke - */
3587dd7cddfSDavid du Colombier /* <userpath> <matrix> ustroke - */
3597dd7cddfSDavid du Colombier private int
zustroke(i_ctx_t * i_ctx_p)3607dd7cddfSDavid du Colombier zustroke(i_ctx_t *i_ctx_p)
3617dd7cddfSDavid du Colombier {
3627dd7cddfSDavid du Colombier     int code = gs_gsave(igs);
3637dd7cddfSDavid du Colombier     int npop;
3647dd7cddfSDavid du Colombier 
3657dd7cddfSDavid du Colombier     if (code < 0)
3667dd7cddfSDavid du Colombier 	return code;
3677dd7cddfSDavid du Colombier     if ((code = npop = upath_stroke(i_ctx_p, NULL)) >= 0)
3687dd7cddfSDavid du Colombier 	code = gs_stroke(igs);
3697dd7cddfSDavid du Colombier     gs_grestore(igs);
3707dd7cddfSDavid du Colombier     if (code < 0)
3717dd7cddfSDavid du Colombier 	return code;
3727dd7cddfSDavid du Colombier     pop(npop);
3737dd7cddfSDavid du Colombier     return 0;
3747dd7cddfSDavid du Colombier }
3757dd7cddfSDavid du Colombier 
3767dd7cddfSDavid du Colombier /* <userpath> ustrokepath - */
3777dd7cddfSDavid du Colombier /* <userpath> <matrix> ustrokepath - */
3787dd7cddfSDavid du Colombier private int
zustrokepath(i_ctx_t * i_ctx_p)3797dd7cddfSDavid du Colombier zustrokepath(i_ctx_t *i_ctx_p)
3807dd7cddfSDavid du Colombier {
3817dd7cddfSDavid du Colombier     gx_path save;
3827dd7cddfSDavid du Colombier     int code, npop;
3837dd7cddfSDavid du Colombier 
3847dd7cddfSDavid du Colombier     /* Save and reset the path. */
3857dd7cddfSDavid du Colombier     gx_path_init_local(&save, imemory);
3867dd7cddfSDavid du Colombier     gx_path_assign_preserve(&save, igs->path);
3877dd7cddfSDavid du Colombier     if ((code = npop = upath_stroke(i_ctx_p, NULL)) < 0 ||
3887dd7cddfSDavid du Colombier 	(code = gs_strokepath(igs)) < 0
3897dd7cddfSDavid du Colombier 	) {
3907dd7cddfSDavid du Colombier 	gx_path_assign_free(igs->path, &save);
3917dd7cddfSDavid du Colombier 	return code;
3927dd7cddfSDavid du Colombier     }
3937dd7cddfSDavid du Colombier     gx_path_free(&save, "ustrokepath");
3947dd7cddfSDavid du Colombier     pop(npop);
3957dd7cddfSDavid du Colombier     return 0;
3967dd7cddfSDavid du Colombier }
3977dd7cddfSDavid du Colombier 
3987dd7cddfSDavid du Colombier /* <with_ucache> upath <userpath> */
3997dd7cddfSDavid du Colombier /* We do all the work in a procedure that is also used to construct */
4007dd7cddfSDavid du Colombier /* the UnpaintedPath user path for ImageType 2 images. */
401*593dc095SDavid du Colombier int make_upath(i_ctx_t *i_ctx_p, ref *rupath, gs_state *pgs, gx_path *ppath,
402*593dc095SDavid du Colombier 	       bool with_ucache);
4037dd7cddfSDavid du Colombier private int
zupath(i_ctx_t * i_ctx_p)4047dd7cddfSDavid du Colombier zupath(i_ctx_t *i_ctx_p)
4057dd7cddfSDavid du Colombier {
4067dd7cddfSDavid du Colombier     os_ptr op = osp;
4077dd7cddfSDavid du Colombier 
4087dd7cddfSDavid du Colombier     check_type(*op, t_boolean);
4097dd7cddfSDavid du Colombier     return make_upath(i_ctx_p, op, igs, igs->path, op->value.boolval);
4107dd7cddfSDavid du Colombier }
4117dd7cddfSDavid du Colombier int
make_upath(i_ctx_t * i_ctx_p,ref * rupath,gs_state * pgs,gx_path * ppath,bool with_ucache)4127dd7cddfSDavid du Colombier make_upath(i_ctx_t *i_ctx_p, ref *rupath, gs_state *pgs, gx_path *ppath,
4137dd7cddfSDavid du Colombier 	   bool with_ucache)
4147dd7cddfSDavid du Colombier {
4157dd7cddfSDavid du Colombier     int size = (with_ucache ? 6 : 5);
4167dd7cddfSDavid du Colombier     gs_path_enum penum;
4177dd7cddfSDavid du Colombier     int op;
4187dd7cddfSDavid du Colombier     ref *next;
4197dd7cddfSDavid du Colombier     int code;
4207dd7cddfSDavid du Colombier 
4217dd7cddfSDavid du Colombier     /* Compute the size of the user path array. */
4227dd7cddfSDavid du Colombier     {
4237dd7cddfSDavid du Colombier 	gs_fixed_point pts[3];
4247dd7cddfSDavid du Colombier 
4257dd7cddfSDavid du Colombier 	gx_path_enum_init(&penum, ppath);
4267dd7cddfSDavid du Colombier 	while ((op = gx_path_enum_next(&penum, pts)) != 0) {
4277dd7cddfSDavid du Colombier 	    switch (op) {
4287dd7cddfSDavid du Colombier 		case gs_pe_moveto:
4297dd7cddfSDavid du Colombier 		case gs_pe_lineto:
4307dd7cddfSDavid du Colombier 		    size += 3;
4317dd7cddfSDavid du Colombier 		    continue;
4327dd7cddfSDavid du Colombier 		case gs_pe_curveto:
4337dd7cddfSDavid du Colombier 		    size += 7;
4347dd7cddfSDavid du Colombier 		    continue;
4357dd7cddfSDavid du Colombier 		case gs_pe_closepath:
4367dd7cddfSDavid du Colombier 		    size += 1;
4377dd7cddfSDavid du Colombier 		    continue;
4387dd7cddfSDavid du Colombier 		default:
4397dd7cddfSDavid du Colombier 		    return_error(e_unregistered);
4407dd7cddfSDavid du Colombier 	    }
4417dd7cddfSDavid du Colombier 	}
4427dd7cddfSDavid du Colombier     }
4437dd7cddfSDavid du Colombier     code = ialloc_ref_array(rupath, a_all | a_executable, size,
4447dd7cddfSDavid du Colombier 			    "make_upath");
4457dd7cddfSDavid du Colombier     if (code < 0)
4467dd7cddfSDavid du Colombier 	return code;
4477dd7cddfSDavid du Colombier     /* Construct the path. */
4487dd7cddfSDavid du Colombier     next = rupath->value.refs;
4497dd7cddfSDavid du Colombier     if (with_ucache) {
450*593dc095SDavid du Colombier         if ((code = name_enter_string(pgs->memory, "ucache", next)) < 0)
4517dd7cddfSDavid du Colombier 	    return code;
4527dd7cddfSDavid du Colombier 	r_set_attrs(next, a_executable | l_new);
4537dd7cddfSDavid du Colombier 	++next;
4547dd7cddfSDavid du Colombier     } {
4557dd7cddfSDavid du Colombier 	gs_rect bbox;
4567dd7cddfSDavid du Colombier 
457*593dc095SDavid du Colombier 	if ((code = gs_upathbbox(pgs, &bbox, true)) < 0) {
458*593dc095SDavid du Colombier 	    /*
459*593dc095SDavid du Colombier 	     * Note: Adobe throws 'nocurrentpoint' error, but the PLRM
460*593dc095SDavid du Colombier 	     * not list this as a possible error from 'upath', so we
461*593dc095SDavid du Colombier 	     * set a reasonable default bbox instead.
462*593dc095SDavid du Colombier 	     */
463*593dc095SDavid du Colombier 	    if (code != e_nocurrentpoint)
464*593dc095SDavid du Colombier 		return code;
465*593dc095SDavid du Colombier 	    bbox.p.x = bbox.p.y = bbox.q.x = bbox.q.y = 0;
466*593dc095SDavid du Colombier 	}
4677dd7cddfSDavid du Colombier 	make_real_new(next, bbox.p.x);
4687dd7cddfSDavid du Colombier 	make_real_new(next + 1, bbox.p.y);
4697dd7cddfSDavid du Colombier 	make_real_new(next + 2, bbox.q.x);
4707dd7cddfSDavid du Colombier 	make_real_new(next + 3, bbox.q.y);
4717dd7cddfSDavid du Colombier 	next += 4;
472*593dc095SDavid du Colombier 	if ((code = name_enter_string(pgs->memory, "setbbox", next)) < 0)
4737dd7cddfSDavid du Colombier 	    return code;
4747dd7cddfSDavid du Colombier 	r_set_attrs(next, a_executable | l_new);
4757dd7cddfSDavid du Colombier 	++next;
4767dd7cddfSDavid du Colombier     }
4777dd7cddfSDavid du Colombier     {
4787dd7cddfSDavid du Colombier 	gs_point pts[3];
4797dd7cddfSDavid du Colombier 
4807dd7cddfSDavid du Colombier 	/* Patch the path in the gstate to set up the enumerator. */
4817dd7cddfSDavid du Colombier 	gx_path *save_path = pgs->path;
4827dd7cddfSDavid du Colombier 
4837dd7cddfSDavid du Colombier 	pgs->path = ppath;
4847dd7cddfSDavid du Colombier 	gs_path_enum_copy_init(&penum, pgs, false);
4857dd7cddfSDavid du Colombier 	pgs->path = save_path;
4867dd7cddfSDavid du Colombier 	while ((op = gs_path_enum_next(&penum, pts)) != 0) {
4877dd7cddfSDavid du Colombier 	    const char *opstr;
4887dd7cddfSDavid du Colombier 
4897dd7cddfSDavid du Colombier 	    switch (op) {
4907dd7cddfSDavid du Colombier 		case gs_pe_moveto:
4917dd7cddfSDavid du Colombier 		    opstr = "moveto";
4927dd7cddfSDavid du Colombier 		    goto ml;
4937dd7cddfSDavid du Colombier 		case gs_pe_lineto:
4947dd7cddfSDavid du Colombier 		    opstr = "lineto";
4957dd7cddfSDavid du Colombier 		  ml:make_real_new(next, pts[0].x);
4967dd7cddfSDavid du Colombier 		    make_real_new(next + 1, pts[0].y);
4977dd7cddfSDavid du Colombier 		    next += 2;
4987dd7cddfSDavid du Colombier 		    break;
4997dd7cddfSDavid du Colombier 		case gs_pe_curveto:
5007dd7cddfSDavid du Colombier 		    opstr = "curveto";
5017dd7cddfSDavid du Colombier 		    make_real_new(next, pts[0].x);
5027dd7cddfSDavid du Colombier 		    make_real_new(next + 1, pts[0].y);
5037dd7cddfSDavid du Colombier 		    make_real_new(next + 2, pts[1].x);
5047dd7cddfSDavid du Colombier 		    make_real_new(next + 3, pts[1].y);
5057dd7cddfSDavid du Colombier 		    make_real_new(next + 4, pts[2].x);
5067dd7cddfSDavid du Colombier 		    make_real_new(next + 5, pts[2].y);
5077dd7cddfSDavid du Colombier 		    next += 6;
5087dd7cddfSDavid du Colombier 		    break;
5097dd7cddfSDavid du Colombier 		case gs_pe_closepath:
5107dd7cddfSDavid du Colombier 		    opstr = "closepath";
5117dd7cddfSDavid du Colombier 		    break;
5127dd7cddfSDavid du Colombier 		default:
5137dd7cddfSDavid du Colombier 		    return_error(e_unregistered);
5147dd7cddfSDavid du Colombier 	    }
515*593dc095SDavid du Colombier 	    if ((code = name_enter_string(pgs->memory, opstr, next)) < 0)
5167dd7cddfSDavid du Colombier 		return code;
5177dd7cddfSDavid du Colombier 	    r_set_attrs(next, a_executable);
5187dd7cddfSDavid du Colombier 	    ++next;
5197dd7cddfSDavid du Colombier 	}
5207dd7cddfSDavid du Colombier     }
5217dd7cddfSDavid du Colombier     return 0;
5227dd7cddfSDavid du Colombier }
5237dd7cddfSDavid du Colombier 
5247dd7cddfSDavid du Colombier /* ------ Internal routines ------ */
5257dd7cddfSDavid du Colombier 
5267dd7cddfSDavid du Colombier /* Append a user path to the current path. */
527*593dc095SDavid du Colombier private inline int
upath_append_aux(os_ptr oppath,i_ctx_t * i_ctx_p)528*593dc095SDavid du Colombier upath_append_aux(os_ptr oppath, i_ctx_t *i_ctx_p)
5297dd7cddfSDavid du Colombier {
530*593dc095SDavid du Colombier     ref opcodes;
5317dd7cddfSDavid du Colombier     check_read(*oppath);
5327dd7cddfSDavid du Colombier     gs_newpath(igs);
5337dd7cddfSDavid du Colombier /****** ROUND tx AND ty ******/
534*593dc095SDavid du Colombier     if (!r_is_array(oppath))
535*593dc095SDavid du Colombier 	return_error(e_typecheck);
536*593dc095SDavid du Colombier 
537*593dc095SDavid du Colombier     if ( r_size(oppath) == 2 &&
538*593dc095SDavid du Colombier 	 array_get(imemory, oppath, 1, &opcodes) >= 0 &&
539*593dc095SDavid du Colombier          r_has_type(&opcodes, t_string)
540*593dc095SDavid du Colombier 	) {			/* 1st element is operands, 2nd is operators */
541*593dc095SDavid du Colombier 	ref operands;
5427dd7cddfSDavid du Colombier 	int code, format;
5437dd7cddfSDavid du Colombier 	int repcount = 1;
5447dd7cddfSDavid du Colombier 	const byte *opp;
5457dd7cddfSDavid du Colombier 	uint ocount, i = 0;
5467dd7cddfSDavid du Colombier 
547*593dc095SDavid du Colombier         array_get(imemory, oppath, 0, &operands);
548*593dc095SDavid du Colombier         code = num_array_format(&operands);
5497dd7cddfSDavid du Colombier 	if (code < 0)
5507dd7cddfSDavid du Colombier 	    return code;
5517dd7cddfSDavid du Colombier 	format = code;
552*593dc095SDavid du Colombier 	opp = opcodes.value.bytes;
553*593dc095SDavid du Colombier 	ocount = r_size(&opcodes);
5547dd7cddfSDavid du Colombier 	while (ocount--) {
5557dd7cddfSDavid du Colombier 	    byte opx = *opp++;
5567dd7cddfSDavid du Colombier 
5577dd7cddfSDavid du Colombier 	    if (opx > UPATH_REPEAT)
5587dd7cddfSDavid du Colombier 		repcount = opx - UPATH_REPEAT;
5597dd7cddfSDavid du Colombier 	    else if (opx > UPATH_MAX_OP)
5607dd7cddfSDavid du Colombier 		return_error(e_rangecheck);
5617dd7cddfSDavid du Colombier 	    else {		/* operator */
5627dd7cddfSDavid du Colombier 		do {
5637dd7cddfSDavid du Colombier 		    os_ptr op = osp;
5647dd7cddfSDavid du Colombier 		    byte opargs = up_nargs[opx];
5657dd7cddfSDavid du Colombier 
5667dd7cddfSDavid du Colombier 		    while (opargs--) {
5677dd7cddfSDavid du Colombier 			push(1);
568*593dc095SDavid du Colombier 			code = num_array_get(imemory, &operands, format, i++, op);
5697dd7cddfSDavid du Colombier 			switch (code) {
5707dd7cddfSDavid du Colombier 			    case t_integer:
5717dd7cddfSDavid du Colombier 				r_set_type_attrs(op, t_integer, 0);
5727dd7cddfSDavid du Colombier 				break;
5737dd7cddfSDavid du Colombier 			    case t_real:
5747dd7cddfSDavid du Colombier 				r_set_type_attrs(op, t_real, 0);
5757dd7cddfSDavid du Colombier 				break;
5767dd7cddfSDavid du Colombier 			    default:
5777dd7cddfSDavid du Colombier 				return_error(e_typecheck);
5787dd7cddfSDavid du Colombier 			}
5797dd7cddfSDavid du Colombier 		    }
5807dd7cddfSDavid du Colombier 		    code = (*up_ops[opx])(i_ctx_p);
5817dd7cddfSDavid du Colombier 		    if (code < 0)
5827dd7cddfSDavid du Colombier 			return code;
5837dd7cddfSDavid du Colombier 		}
5847dd7cddfSDavid du Colombier 		while (--repcount);
5857dd7cddfSDavid du Colombier 		repcount = 1;
5867dd7cddfSDavid du Colombier 	    }
5877dd7cddfSDavid du Colombier 	}
588*593dc095SDavid du Colombier     } else {	/* Ordinary executable array. */
5897dd7cddfSDavid du Colombier 	const ref *arp = oppath;
5907dd7cddfSDavid du Colombier 	uint ocount = r_size(oppath);
5917dd7cddfSDavid du Colombier 	long index = 0;
5927dd7cddfSDavid du Colombier 	int argcount = 0;
5937dd7cddfSDavid du Colombier 	op_proc_t oproc;
5947dd7cddfSDavid du Colombier 	int opx, code;
5957dd7cddfSDavid du Colombier 
5967dd7cddfSDavid du Colombier 	for (; index < ocount; index++) {
5977dd7cddfSDavid du Colombier 	    ref rup;
5987dd7cddfSDavid du Colombier 	    ref *defp;
5997dd7cddfSDavid du Colombier 	    os_ptr op = osp;
6007dd7cddfSDavid du Colombier 
601*593dc095SDavid du Colombier 	    array_get(imemory, arp, index, &rup);
6027dd7cddfSDavid du Colombier 	    switch (r_type(&rup)) {
6037dd7cddfSDavid du Colombier 		case t_integer:
6047dd7cddfSDavid du Colombier 		case t_real:
6057dd7cddfSDavid du Colombier 		    argcount++;
6067dd7cddfSDavid du Colombier 		    push(1);
6077dd7cddfSDavid du Colombier 		    *op = rup;
6087dd7cddfSDavid du Colombier 		    break;
6097dd7cddfSDavid du Colombier 		case t_name:
6107dd7cddfSDavid du Colombier 		    if (!r_has_attr(&rup, a_executable))
6117dd7cddfSDavid du Colombier 			return_error(e_typecheck);
6127dd7cddfSDavid du Colombier 		    if (dict_find(systemdict, &rup, &defp) <= 0)
6137dd7cddfSDavid du Colombier 			return_error(e_undefined);
6147dd7cddfSDavid du Colombier 		    if (r_btype(defp) != t_operator)
6157dd7cddfSDavid du Colombier 			return_error(e_typecheck);
6167dd7cddfSDavid du Colombier 		    goto xop;
6177dd7cddfSDavid du Colombier 		case t_operator:
6187dd7cddfSDavid du Colombier 		    defp = &rup;
6197dd7cddfSDavid du Colombier 		  xop:if (!r_has_attr(defp, a_executable))
6207dd7cddfSDavid du Colombier 			return_error(e_typecheck);
6217dd7cddfSDavid du Colombier 		    oproc = real_opproc(defp);
6227dd7cddfSDavid du Colombier 		    for (opx = 0; opx <= UPATH_MAX_OP; opx++)
6237dd7cddfSDavid du Colombier 			if (oproc == up_ops[opx])
6247dd7cddfSDavid du Colombier 			    break;
6257dd7cddfSDavid du Colombier 		    if (opx > UPATH_MAX_OP || argcount != up_nargs[opx])
6267dd7cddfSDavid du Colombier 			return_error(e_typecheck);
6277dd7cddfSDavid du Colombier 		    code = (*oproc)(i_ctx_p);
6287dd7cddfSDavid du Colombier 		    if (code < 0)
6297dd7cddfSDavid du Colombier 			return code;
6307dd7cddfSDavid du Colombier 		    argcount = 0;
6317dd7cddfSDavid du Colombier 		    break;
6327dd7cddfSDavid du Colombier 		default:
6337dd7cddfSDavid du Colombier 		    return_error(e_typecheck);
6347dd7cddfSDavid du Colombier 	    }
6357dd7cddfSDavid du Colombier 	}
6367dd7cddfSDavid du Colombier 	if (argcount)
6377dd7cddfSDavid du Colombier 	    return_error(e_typecheck);	/* leftover args */
638*593dc095SDavid du Colombier     }
639*593dc095SDavid du Colombier     return 0;
640*593dc095SDavid du Colombier }
641*593dc095SDavid du Colombier private int
upath_append(os_ptr oppath,i_ctx_t * i_ctx_p)642*593dc095SDavid du Colombier upath_append(os_ptr oppath, i_ctx_t *i_ctx_p)
643*593dc095SDavid du Colombier {
644*593dc095SDavid du Colombier     int code = upath_append_aux(oppath, i_ctx_p);
645*593dc095SDavid du Colombier 
646*593dc095SDavid du Colombier     if (code < 0)
647*593dc095SDavid du Colombier 	return code;
648*593dc095SDavid du Colombier     igs->current_point.x = fixed2float(igs->path->position.x);
649*593dc095SDavid du Colombier     igs->current_point.y = fixed2float(igs->path->position.y);
6507dd7cddfSDavid du Colombier     return 0;
6517dd7cddfSDavid du Colombier }
6527dd7cddfSDavid du Colombier 
6537dd7cddfSDavid du Colombier /* Append a user path to the current path, and then apply or return */
6547dd7cddfSDavid du Colombier /* a transformation if one is supplied. */
6557dd7cddfSDavid du Colombier private int
upath_stroke(i_ctx_t * i_ctx_p,gs_matrix * pmat)6567dd7cddfSDavid du Colombier upath_stroke(i_ctx_t *i_ctx_p, gs_matrix *pmat)
6577dd7cddfSDavid du Colombier {
6587dd7cddfSDavid du Colombier     os_ptr op = osp;
6597dd7cddfSDavid du Colombier     int code, npop;
6607dd7cddfSDavid du Colombier     gs_matrix mat;
6617dd7cddfSDavid du Colombier 
662*593dc095SDavid du Colombier     if ((code = read_matrix(imemory, op, &mat)) >= 0) {
6637dd7cddfSDavid du Colombier 	if ((code = upath_append(op - 1, i_ctx_p)) >= 0) {
6647dd7cddfSDavid du Colombier 	    if (pmat)
6657dd7cddfSDavid du Colombier 		*pmat = mat;
6667dd7cddfSDavid du Colombier 	    else
6677dd7cddfSDavid du Colombier 		code = gs_concat(igs, &mat);
6687dd7cddfSDavid du Colombier 	}
6697dd7cddfSDavid du Colombier 	npop = 2;
6707dd7cddfSDavid du Colombier     } else {
6717dd7cddfSDavid du Colombier 	if ((code = upath_append(op, i_ctx_p)) >= 0)
6727dd7cddfSDavid du Colombier 	    if (pmat)
6737dd7cddfSDavid du Colombier 		gs_make_identity(pmat);
6747dd7cddfSDavid du Colombier 	npop = 1;
6757dd7cddfSDavid du Colombier     }
6767dd7cddfSDavid du Colombier     return (code < 0 ? code : npop);
6777dd7cddfSDavid du Colombier }
6787dd7cddfSDavid du Colombier 
6797dd7cddfSDavid du Colombier /* ---------------- Initialization procedure ---------------- */
6807dd7cddfSDavid du Colombier 
6817dd7cddfSDavid du Colombier const op_def zupath_l2_op_defs[] =
6827dd7cddfSDavid du Colombier {
6837dd7cddfSDavid du Colombier     op_def_begin_level2(),
6847dd7cddfSDavid du Colombier 		/* Insideness testing */
6857dd7cddfSDavid du Colombier     {"1ineofill", zineofill},
6867dd7cddfSDavid du Colombier     {"1infill", zinfill},
6877dd7cddfSDavid du Colombier     {"1instroke", zinstroke},
6887dd7cddfSDavid du Colombier     {"2inueofill", zinueofill},
6897dd7cddfSDavid du Colombier     {"2inufill", zinufill},
6907dd7cddfSDavid du Colombier     {"2inustroke", zinustroke},
6917dd7cddfSDavid du Colombier 		/* User paths */
6927dd7cddfSDavid du Colombier     {"1uappend", zuappend},
6937dd7cddfSDavid du Colombier     {"0ucache", zucache},
6947dd7cddfSDavid du Colombier     {"1ueofill", zueofill},
6957dd7cddfSDavid du Colombier     {"1ufill", zufill},
6967dd7cddfSDavid du Colombier     {"1upath", zupath},
6977dd7cddfSDavid du Colombier     {"1ustroke", zustroke},
6987dd7cddfSDavid du Colombier     {"1ustrokepath", zustrokepath},
6997dd7cddfSDavid du Colombier     op_def_end(0)
7007dd7cddfSDavid du Colombier };
701