[gs-cvs] rev 8061 - in trunk/gs: doc lib src

alexcher at ghostscript.com alexcher at ghostscript.com
Mon Jun 18 19:39:15 PDT 2007


Author: alexcher
Date: 2007-06-18 19:39:15 -0700 (Mon, 18 Jun 2007)
New Revision: 8061

Modified:
   trunk/gs/doc/Language.htm
   trunk/gs/lib/pdf_draw.ps
   trunk/gs/lib/pdf_ops.ps
   trunk/gs/src/zupath.c
Log:
Use newly created operator .getpath to implement PDF path handling without
64K limit on the user path imposed by upath, which we had before.
Bug 689123, customer 870.

DIFFERENCES:
None


Modified: trunk/gs/doc/Language.htm
===================================================================
--- trunk/gs/doc/Language.htm	2007-06-18 17:07:28 UTC (rev 8060)
+++ trunk/gs/doc/Language.htm	2007-06-19 02:39:15 UTC (rev 8061)
@@ -724,6 +724,19 @@
 selected when Ghostscript was built.
 </dl>
 
+<dl>
+<dt><b><tt>- .getpath &lt;array&gt;</tt></b>
+<dd>Export the current path to an array of executable arrays. This
+operator is similar to <b><tt>upath</tt></b>, except
+
+<li>array of arrays is used to overcome 64K-1 limit on the
+array lemgth.
+<li>no <b><tt>ucache</tt></b> or <b><tt>setbbox</tt></b> entries are generated.
+<li>operators are used instead of executable names.
+<li>there's no special handling of an empty path or trailing <b><tt>moveto</tt></b>.
+The saved path can be restored by <b><tt>newpath { exec } forall</tt></b>.
+</dl>
+
 <h4><a name="Painting"></a>Painting operators</h4>
 
 <p>

Modified: trunk/gs/lib/pdf_draw.ps
===================================================================
--- trunk/gs/lib/pdf_draw.ps	2007-06-18 17:07:28 UTC (rev 8060)
+++ trunk/gs/lib/pdf_draw.ps	2007-06-19 02:39:15 UTC (rev 8061)
@@ -275,20 +275,16 @@
   /q { q } def
   /Q { Q } def
 			% Graphics state setting
-  /cm { { //false upath } stopped {
-	  pop	% discard 'false' (upath failed, probably no currentpoint).
-	  //cmmatrix astore concat
-	} {
-	  % update the CTM, then uappend.
-	  7 1 roll //cmmatrix astore concat
-	  newpath { mark exch uappend } stopped 
-	  cleartomark
-	} ifelse
+  /cm { //cmmatrix astore
+        .getpath      
+        exch concat
+        newpath { exec } forall
 	% If inside a BT/ET block, we need to update the TextSaveMatrix
 	currentdict /TextSaveMatrix .knownget {
 	  //cmmatrix exch dup concatmatrix pop
 	} if
       } bdef
+
   /i { 1 .min setflat } bdef
   /J /setlinecap load def
   /d /setdash load def

Modified: trunk/gs/lib/pdf_ops.ps
===================================================================
--- trunk/gs/lib/pdf_ops.ps	2007-06-18 17:07:28 UTC (rev 8060)
+++ trunk/gs/lib/pdf_ops.ps	2007-06-19 02:39:15 UTC (rev 8061)
@@ -102,13 +102,10 @@
 % of the PDF graphics state; see 4.4.1 of PDF reference 3rd ed.
 /grestore_nopath {
   % Collect the upath with an identity CTM
-  { matrix setmatrix //false upath } stopped {
-    pop grestore newpath
-  } {
+    matrix setmatrix .getpath
     % Save the CTM, set identity during the uappend, then set the CTM
     grestore matrix currentmatrix matrix setmatrix
-    exch newpath uappend setmatrix
-  } ifelse
+    exch newpath { exec } forall setmatrix
 } bdef
 
 /q {

Modified: trunk/gs/src/zupath.c
===================================================================
--- trunk/gs/src/zupath.c	2007-06-18 17:07:28 UTC (rev 8060)
+++ trunk/gs/src/zupath.c	2007-06-19 02:39:15 UTC (rev 8061)
@@ -460,6 +460,35 @@
     check_type(*op, t_boolean);
     return make_upath(i_ctx_p, op, igs, igs->path, op->value.boolval);
 }
+
+/* Compute the path length for user path purposes. */
+private int 
+path_length_for_upath(const gx_path *ppath)
+{
+    gs_path_enum penum;
+    int op, size = 0;
+    gs_fixed_point pts[3];
+
+    gx_path_enum_init(&penum, ppath);
+    while ((op = gx_path_enum_next(&penum, pts)) != 0) {
+	switch (op) {
+	    case gs_pe_moveto:
+	    case gs_pe_lineto:
+		size += 3;
+		continue;
+	    case gs_pe_curveto:
+		size += 7;
+		continue;
+	    case gs_pe_closepath:
+		size += 1;
+		continue;
+	    default:
+		return_error(e_unregistered);
+	}
+    }
+    return size;
+}
+
 int
 make_upath(i_ctx_t *i_ctx_p, ref *rupath, gs_state *pgs, gx_path *ppath,
 	   bool with_ucache)
@@ -485,28 +514,13 @@
 	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];
+    code = path_length_for_upath(ppath);
+    if (code < 0)
+        return code;
+    size += code;
+    if (size >= 65536)
+        return_error(e_limitcheck);
 
-	gx_path_enum_init(&penum, ppath);
-	while ((op = gx_path_enum_next(&penum, pts)) != 0) {
-	    switch (op) {
-		case gs_pe_moveto:
-		case gs_pe_lineto:
-		    size += 3;
-		    continue;
-		case gs_pe_curveto:
-		    size += 7;
-		    continue;
-		case gs_pe_closepath:
-		    size += 1;
-		    continue;
-		default:
-		    return_error(e_unregistered);
-	    }
-	}
-    }
     code = ialloc_ref_array(rupath, a_all | a_executable, size,
 			    "make_upath");
     if (code < 0)
@@ -575,6 +589,81 @@
     return 0;
 }
 
+
+private int
+zgetpath(i_ctx_t *i_ctx_p)
+{
+    os_ptr op = osp;
+    int i, code, path_size, leaf_count;
+    ref *main_ref, *operators[5];
+
+    push(1);
+    path_size = code = path_length_for_upath(igs->path);
+    if (code < 0)
+        return code;
+    leaf_count = (path_size + max_array_size - 1) / max_array_size;
+    code = ialloc_ref_array(op, a_all, leaf_count, "zgetpath_master");
+    if (code < 0)
+        return code;
+    if (path_size == 0)
+        return 0;
+
+    if (dict_find_string(systemdict, "moveto", &operators[1]) <= 0 ||
+  	dict_find_string(systemdict, "lineto", &operators[2]) <= 0 ||
+	dict_find_string(systemdict, "curveto", &operators[3]) <= 0 ||
+	dict_find_string(systemdict, "closepath", &operators[4]) <= 0)
+          return_error(e_undefined);
+
+    main_ref = op->value.refs;
+    for (i = 0; i < leaf_count; i++) {
+       int leaf_size = ( i == leaf_count - 1) ? path_size - i * max_array_size : max_array_size;
+       code = ialloc_ref_array(&main_ref[i], a_all | a_executable, leaf_size, "zgetpath_leaf");
+       if (code < 0)
+            return code;
+    }
+
+    {
+        int pe, j, k;
+        gs_path_enum penum;
+        static const int oper_count[5] = { 0, 2, 2, 6, 0 };
+	gs_point pts[3];
+        const double  *fts[6]; 
+
+        fts[0] = &pts[0].x;
+        fts[1] = &pts[0].y;
+        fts[2] = &pts[1].x;
+        fts[3] = &pts[1].y;
+        fts[4] = &pts[2].x;
+        fts[5] = &pts[2].y;
+
+        main_ref = op->value.refs;
+	gs_path_enum_copy_init(&penum, igs, false);
+        pe = gs_path_enum_next(&penum, pts);
+        k = 0;
+
+        for (i = 0; i < leaf_count; i++) {
+            int leaf_size = ( i == leaf_count - 1) ? path_size - i * max_array_size : max_array_size;
+            ref *leaf_ref = main_ref[i].value.refs;
+            
+            for (j = 0; j < leaf_size; j++) {
+                if (k < oper_count[pe])
+                   make_real_new(&leaf_ref[j], (float)*fts[k++]);
+                else {
+                    k = 0;
+                    ref_assign(&leaf_ref[j], operators[pe]);
+                    pe = gs_path_enum_next(&penum, pts);
+                    if (pe == 0)
+                        goto out;
+                    if (pe >= 5)
+                        return_error(e_unregistered);
+                }
+            }
+        }
+     }
+  out:
+  return 0;
+}
+
 /* ------ Internal routines ------ */
 
 /* Append a user path to the current path. */
@@ -798,5 +887,7 @@
     {"1upath", zupath},
     {"1ustroke", zustroke},
     {"1ustrokepath", zustrokepath},
+		/* Path access for PDF */
+    {"0.getpath", zgetpath},
     op_def_end(0)
 };



More information about the gs-cvs mailing list