[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 <array></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