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 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 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 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 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 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 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 111 zdashpath(i_ctx_t *i_ctx_p) 112 { 113 return gs_dashpath(igs); 114 } 115 116 /* - flattenpath - */ 117 private int 118 zflattenpath(i_ctx_t *i_ctx_p) 119 { 120 return gs_flattenpath(igs); 121 } 122 123 /* - reversepath - */ 124 private int 125 zreversepath(i_ctx_t *i_ctx_p) 126 { 127 return gs_reversepath(igs); 128 } 129 130 /* - strokepath - */ 131 private int 132 zstrokepath(i_ctx_t *i_ctx_p) 133 { 134 return gs_strokepath(igs); 135 } 136 137 /* - clippath - */ 138 private int 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 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 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 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 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 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