[gs-cvs] rev 7512 - trunk/gs/src

lpd at ghostscript.com lpd at ghostscript.com
Fri Dec 15 10:08:58 PST 2006


Author: lpd
Date: 2006-12-15 10:08:57 -0800 (Fri, 15 Dec 2006)
New Revision: 7512

Modified:
   trunk/gs/src/zupath.c
Log:
Fixes several user path problems: upath didn't signal nocurrentpoint for
empty paths in CPSI mode; appending an empty user path didn't set current
point in CPSI mode. (PS3 CET 13-27-3, 13-28-4, 13-29-3)


Modified: trunk/gs/src/zupath.c
===================================================================
--- trunk/gs/src/zupath.c	2006-12-15 18:06:08 UTC (rev 7511)
+++ trunk/gs/src/zupath.c	2006-12-15 18:08:57 UTC (rev 7512)
@@ -38,6 +38,17 @@
 extern const gx_device gs_hit_device;
 extern const int gs_hit_detected;
 
+/*
+ * CPSI mode affects two algorithms in this file:
+ * - CPSI allows ucache to appear anywhere in user paths, even though the
+ *   PLRM says ucache must appear (if at all) at the beginning
+ *   (PLRM3 p, 199);
+ * - After appending an empty user path, in CPSI the current point is
+ *   defined, even though the PLRM strongly implies this is incorrect
+ *   (PLRM3 p. 712).
+ * The 'upath_compat' Boolean controls this behavior.
+ */
+
 extern bool CPSI_mode;
 
 /* Forward references */
@@ -313,13 +324,33 @@
 int zsetbbox(i_ctx_t *);
 private int zucache(i_ctx_t *);
 
+/* Forward references */
+private int upath_setbbox(i_ctx_t *);
+
 #undef zp
 static const op_proc_t up_ops[UPATH_MAX_OP + 1] = {
     zsetbbox, zmoveto, zrmoveto, zlineto, zrlineto,
     zcurveto, zrcurveto, zarc, zarcn, zarct,
     zclosepath, zucache
 };
+static const op_proc_t up_ops_compat[UPATH_MAX_OP + 1] = {
+    upath_setbbox, zmoveto, zrmoveto, zlineto, zrlineto,
+    zcurveto, zrcurveto, zarc, zarcn, zarct,
+    zclosepath, zucache
+};
 
+/* In CPSI compatibility mode, setbbox must also do a moveto. */
+private int
+upath_setbbox(i_ctx_t *i_ctx_p)
+{
+    int code = zsetbbox(i_ctx_p);
+
+    if (code < 0) return code;
+    /* "Restore" the first two stack operands. */
+    osp += 2;
+    return zmoveto(i_ctx_p);
+}
+
 /* - ucache - */
 private int
 zucache(i_ctx_t *i_ctx_p)
@@ -337,7 +368,7 @@
 
     if (code < 0)
 	return code;
-    if ((code = upath_append(op, i_ctx_p, false)) >= 0)
+    if ((code = upath_append(op, i_ctx_p, CPSI_mode)) >= 0)
 	code = gs_upmergepath(igs);
     gs_grestore(igs);
     igs->current_point.x = fixed2float(igs->path->position.x);
@@ -456,10 +487,25 @@
 {
     int size = (with_ucache ? 6 : 5);
     gs_path_enum penum;
+    gs_rect bbox;
     int op;
     ref *next;
     int code;
 
+
+    /* Compute the bounding box. */
+    if ((code = gs_upathbbox(pgs, &bbox, true)) < 0) {
+	/*
+	 * Note: Adobe throws 'nocurrentpoint' error, but the PLRM does
+	 * not list this as a possible error from 'upath', so if we are
+	 * not in CPSI compatibility mode, we set a reasonable default
+	 * bbox instead.
+	 */
+	if (code != e_nocurrentpoint || CPSI_mode)
+	    return code;
+	bbox.p.x = bbox.p.y = bbox.q.x = bbox.q.y = 0;
+    }
+
     /* Compute the size of the user path array. */
     {
 	gs_fixed_point pts[3];
@@ -493,29 +539,16 @@
 	    return code;
 	r_set_attrs(next, a_executable | l_new);
 	++next;
-    } {
-	gs_rect bbox;
-
-	if ((code = gs_upathbbox(pgs, &bbox, true)) < 0) {
-	    /*
-	     * Note: Adobe throws 'nocurrentpoint' error, but the PLRM
-	     * not list this as a possible error from 'upath', so we
-	     * set a reasonable default bbox instead.
-	     */
-	    if (code != e_nocurrentpoint)
-		return code;
-	    bbox.p.x = bbox.p.y = bbox.q.x = bbox.q.y = 0;
-	}
-	make_real_new(next, bbox.p.x);
-	make_real_new(next + 1, bbox.p.y);
-	make_real_new(next + 2, bbox.q.x);
-	make_real_new(next + 3, bbox.q.y);
-	next += 4;
-	if ((code = name_enter_string(pgs->memory, "setbbox", next)) < 0)
-	    return code;
-	r_set_attrs(next, a_executable | l_new);
-	++next;
     }
+    make_real_new(next, bbox.p.x);
+    make_real_new(next + 1, bbox.p.y);
+    make_real_new(next + 2, bbox.q.x);
+    make_real_new(next + 3, bbox.q.y);
+    next += 4;
+    if ((code = name_enter_string(pgs->memory, "setbbox", next)) < 0)
+	return code;
+    r_set_attrs(next, a_executable | l_new);
+    ++next;
     {
 	gs_point pts[3];
 
@@ -567,9 +600,10 @@
 
 /* Append a user path to the current path. */
 private inline int
-upath_append_aux(os_ptr oppath, i_ctx_t *i_ctx_p, int *pnargs, bool ucache_kludge)
+upath_append_aux(os_ptr oppath, i_ctx_t *i_ctx_p, int *pnargs, bool upath_compat)
 {
     upath_state ups = UPS_INITIAL;
+    const op_proc_t *ops = (upath_compat ? up_ops_compat : up_ops);
     ref opcodes;
 
     if (r_has_type(oppath, t__invalid))
@@ -609,7 +643,7 @@
 		const up_data_t data = up_data[opx];
 
 		*pnargs = data.num_args; /* in case of error */
-		if (ucache_kludge && opx == upath_op_ucache) {
+		if (upath_compat && opx == upath_op_ucache) {
 		    /* CPSI does not complain about incorrect ucache
 		       placement, even though PLRM3 says it's illegal. */
 		    ups = ups == UPS_PATH ? ups : data.state_after;
@@ -636,7 +670,7 @@
 				return_error(e_typecheck);
 			}
 		    }
-		    code = (*up_ops[opx])(i_ctx_p);
+		    code = (*ops[opx])(i_ctx_p);
 		    if (code < 0)
 			return code;
 		}
@@ -686,7 +720,7 @@
 		    data = up_data[opx];
 		    if (argcount != data.num_args)
 			return_error(e_typecheck);
-		    if (ucache_kludge && opx == upath_op_ucache) {
+		    if (upath_compat && opx == upath_op_ucache) {
 			/* CPSI does not complain about incorrect ucache
 			   placement, even though PLRM3 says it's illegal. */
 			ups = ups == UPS_PATH ? ups : data.state_after;
@@ -695,7 +729,8 @@
 			    return_error(e_typecheck);
 			ups = data.state_after;
 		    }
-		    code = (*oproc)(i_ctx_p);
+		    /* If in compat mode, use up_ops_compat */
+		    code = (*ops[opx])(i_ctx_p);
 		    if (code < 0) {
 			if (code == e_nocurrentpoint)
                             return_error(e_rangecheck); /* CET 11-22 */
@@ -715,10 +750,10 @@
     return 0;
 }
 private int
-upath_append(os_ptr oppath, i_ctx_t *i_ctx_p, bool ucache_kludge)
+upath_append(os_ptr oppath, i_ctx_t *i_ctx_p, bool upath_compat)
 {
     int nargs = 0;
-    int code = upath_append_aux(oppath, i_ctx_p, &nargs, ucache_kludge);
+    int code = upath_append_aux(oppath, i_ctx_p, &nargs, upath_compat);
 
     if (code < 0) {
 	/* Pop args on error, to match Adobe interpreters. */
@@ -733,14 +768,14 @@
 /* Append a user path to the current path, and then apply or return */
 /* a transformation if one is supplied. */
 private int
-upath_stroke(i_ctx_t *i_ctx_p, gs_matrix *pmat, bool ucache_kludge)
+upath_stroke(i_ctx_t *i_ctx_p, gs_matrix *pmat, bool upath_compat)
 {
     os_ptr op = osp;
     int code, npop;
     gs_matrix mat;
 
     if ((code = read_matrix(imemory, op, &mat)) >= 0) {
-	if ((code = upath_append(op - 1, i_ctx_p, ucache_kludge)) >= 0) {
+	if ((code = upath_append(op - 1, i_ctx_p, upath_compat)) >= 0) {
 	    if (pmat)
 		*pmat = mat;
 	    else
@@ -748,7 +783,7 @@
 	}
 	npop = 2;
     } else {
-	if ((code = upath_append(op, i_ctx_p, ucache_kludge)) >= 0)
+	if ((code = upath_append(op, i_ctx_p, upath_compat)) >= 0)
 	    if (pmat)
 		gs_make_identity(pmat);
 	npop = 1;



More information about the gs-cvs mailing list