[gs-commits] ghostpdl branch, master, updated. ghostpdl-9.02-1002-g93bf2df

Robin Watts robin at ghostscript.com
Fri Mar 9 20:13:13 UTC 2012


The ghostpdl branch, master has been updated
       via  93bf2df8f6a6b2ed60a8c3f5037865b8646243db (commit)
      from  91b362b05a16c4d74f9309d92fa7387899fed53a (commit)

----------------------------------------------------------------------
commit 93bf2df8f6a6b2ed60a8c3f5037865b8646243db
Author: Robin Watts <robin.watts at artifex.com>
Date:   Mon Feb 27 03:11:02 2012 +0000

    Support HPGL style path handling. (Work in progress)
    
    HPGL handles paths slightly differently to the postscript imaging model.
    
    When a path is filled, successive moveto's are treated as linetos.
    (i.e. the 'place we close the path to' is left at the first moveto,
    and the area remains fillable). Stroking is unaffected however.
    
    To model this in Ghostscript we add a new path segment type 's_gap'.
    The filling code treats this as a lineto. The stroking code is updated
    to not stroke such edges (and not to break the subpath at this point).
    
    We add a new parameter to the imager state (hpgl_fill_mode), new
    accessor functions (gs_sethpglfillmode, gs_currenthpglfillmode),
    and new postscript operators (.sethpglfillmode and .currenthpglfillmode).
    
    If hpgl fill mode is set to a non-zero value, then path construction
    treats movetos in an open subpath as gaptos.
    
    Still to do:
      * Double check the output from this code matches HPGL.
      * Update the clist code to send hpgl fill mode changes.
      * Update PDF write to spot such paths and to convert them as
        appropriate when writing out.

diff --git a/gs/base/gdevpdfd.c b/gs/base/gdevpdfd.c
index b5ad319..0f05851 100644
--- a/gs/base/gdevpdfd.c
+++ b/gs/base/gdevpdfd.c
@@ -260,6 +260,7 @@ pdf_is_same_clip_path(gx_device_pdf * pdev, const gx_clip_path * pcpath)
                     return 0;
             case gs_pe_moveto:
             case gs_pe_lineto:
+            case gs_pe_gapto:
                 if (vs0[0].x != vs1[0].x || vs0[0].y != vs1[0].y)
                     return 0;
         }
diff --git a/gs/base/gdevtrac.c b/gs/base/gdevtrac.c
index 535cebc..be1492f 100644
--- a/gs/base/gdevtrac.c
+++ b/gs/base/gdevtrac.c
@@ -100,6 +100,10 @@ trace_path(const gx_path *path)
             dprintf2("    %g %g lineto\n", fixed2float(pts[0].x),
                      fixed2float(pts[0].y));
             continue;
+        case gs_pe_gapto:
+            dprintf2("    %g %g gapto\n", fixed2float(pts[0].x),
+                     fixed2float(pts[0].y));
+            continue;
         case gs_pe_curveto:
             dprintf6("    %g %g %g %g %g %g curveto\n", fixed2float(pts[0].x),
                      fixed2float(pts[0].y), fixed2float(pts[1].x),
diff --git a/gs/base/gdevvec.c b/gs/base/gdevvec.c
index b4a6ef4..ecff2d2 100644
--- a/gs/base/gdevvec.c
+++ b/gs/base/gdevvec.c
@@ -101,6 +101,7 @@ gdev_vector_dopath(gx_device_vector *vdev, const gx_path * ppath,
     sw:
         if (type & gx_path_type_optimize) {
         opt:
+            /* RJW: We fail to optimize gaptos */
             if (pe_op == gs_pe_lineto) {
                 if (!incomplete_line) {
                     line_end = vs[0];
@@ -173,6 +174,7 @@ gdev_vector_dopath(gx_device_vector *vdev, const gx_path * ppath,
             }
             goto draw;
         case gs_pe_lineto:
+        case gs_pe_gapto:
             if (need_moveto) {	/* see gs_pe_moveto case */
                 code = gdev_vector_dopath_segment(&state, gs_pe_moveto,
                                                   &line_start);
@@ -642,6 +644,7 @@ gdev_vector_dopath_segment(gdev_vector_dopath_state_t *state, int pe_op,
             state->prev = vp[0];
             break;
         case gs_pe_lineto:
+        case gs_pe_gapto: /* FIXME */
             code = gs_point_transform_inverse(fixed2float(vs[0].x),
                                        fixed2float(vs[0].y), pmat, &vp[0]);
             if (code < 0)
diff --git a/gs/base/gspath.c b/gs/base/gspath.c
index 4964b2a..dbdd7be 100644
--- a/gs/base/gspath.c
+++ b/gs/base/gspath.c
@@ -154,12 +154,21 @@ gs_moveto_aux(gs_imager_state *pis, gx_path *ppath, floatp x, floatp y)
     code = clamp_point_aux(pis->clamp_coordinates, &pt, x, y);
     if (code < 0)
         return code;
-    code = gx_path_add_point(ppath, pt.x, pt.y);
-    if (code < 0)
-        return code;
-    ppath->start_flags = ppath->state_flags;
+    if (path_subpath_open(ppath) && pis->hpgl_fill_mode)
+    {
+        code = gx_path_add_gap_notes(ppath, pt.x, pt.y, 0);
+        if (code < 0)
+            return code;
+    }
+    else
+    {
+        code = gx_path_add_point(ppath, pt.x, pt.y);
+        if (code < 0)
+            return code;
+        ppath->start_flags = ppath->state_flags;
+        pis->subpath_start = pis->current_point;
+    }
     gx_setcurrentpoint(pis, x, y);
-    pis->subpath_start = pis->current_point;
     pis->current_point_valid = true;
     return 0;
 }
diff --git a/gs/base/gspath1.c b/gs/base/gspath1.c
index 4f4d760..f886460 100644
--- a/gs/base/gspath1.c
+++ b/gs/base/gspath1.c
@@ -641,6 +641,7 @@ gs_path_enum_next(gs_path_enum * penum, gs_point ppts[3])
             /* falls through */
         case gs_pe_moveto:
         case gs_pe_lineto:
+        case gs_pe_gapto:
             if ((code = gs_point_transform_inverse(
                                                       fixed2float(fpts[0].x),
                                                       fixed2float(fpts[0].y),
diff --git a/gs/base/gspenum.h b/gs/base/gspenum.h
index 920a72d..5cda503 100644
--- a/gs/base/gspenum.h
+++ b/gs/base/gspenum.h
@@ -22,6 +22,7 @@
 #define gs_pe_lineto 2
 #define gs_pe_curveto 3
 #define gs_pe_closepath 4
+#define gs_pe_gapto 5
 
 /* Define an abstract type for the path enumerator. */
 typedef struct gs_path_enum_s gs_path_enum;
diff --git a/gs/base/gsstate.c b/gs/base/gsstate.c
index 470ca8e..d279ace 100644
--- a/gs/base/gsstate.c
+++ b/gs/base/gsstate.c
@@ -839,6 +839,20 @@ gs_currenttextrenderingmode(const gs_state * pgs)
     return pgs->text_rendering_mode;
 }
 
+/* sethpglfillmode */
+void
+gs_sethpglfillmode(gs_state * pgs, int fill)
+{
+    pgs->hpgl_fill_mode = fill;
+}
+
+/* currenthpglfillmode */
+int
+gs_currenthpglfillmode(const gs_state * pgs)
+{
+    return pgs->hpgl_fill_mode;
+}
+
 /* ------ Internal routines ------ */
 
 /* Free the privately allocated parts of a gstate. */
diff --git a/gs/base/gsstate.h b/gs/base/gsstate.h
index 5b6bea5..7fa8cee 100644
--- a/gs/base/gsstate.h
+++ b/gs/base/gsstate.h
@@ -90,5 +90,7 @@ void gs_settextrenderingmode(gs_state * pgs, uint trm);
 uint gs_currenttextrenderingmode(const gs_state * pgs);
 #include "gscpm.h"
 gs_in_cache_device_t gs_incachedevice(const gs_state *);
+void gs_sethpglfillmode(gs_state *, int);
+int gs_currenthpglfillmode(const gs_state *);
 
 #endif /* gsstate_INCLUDED */
diff --git a/gs/base/gxclpath.c b/gs/base/gxclpath.c
index 01fa187..df250cd 100644
--- a/gs/base/gxclpath.c
+++ b/gs/base/gxclpath.c
@@ -1340,6 +1340,7 @@ cmd_put_path(gx_device_clist_writer * cldev, gx_clist_state * pcls,
                           fixed2float(px), fixed2float(py));
                 break;
             case gs_pe_lineto:
+            case gs_pe_gapto:
                 {
                     int next_side = which_side(B);
                     segment_notes notes =
diff --git a/gs/base/gxcpath.c b/gs/base/gxcpath.c
index d0ada37..05bbcb0 100644
--- a/gs/base/gxcpath.c
+++ b/gs/base/gxcpath.c
@@ -421,6 +421,10 @@ gx_cpath_to_path_synthesize(const gx_clip_path * pcpath, gx_path * ppath)
                 code = gx_path_add_line_notes(ppath, pts[0].x, pts[0].y,
                                            gx_cpath_enum_notes(&cenum));
                 break;
+            case gs_pe_gapto:
+                code = gx_path_add_gap_notes(ppath, pts[0].x, pts[0].y,
+                                           gx_cpath_enum_notes(&cenum));
+                break;
             case gs_pe_curveto:
                 code = gx_path_add_curve_notes(ppath, pts[0].x, pts[0].y,
                                                pts[1].x, pts[1].y,
diff --git a/gs/base/gxistate.h b/gs/base/gxistate.h
index e1ac8a1..9923ae8 100644
--- a/gs/base/gxistate.h
+++ b/gs/base/gxistate.h
@@ -235,6 +235,7 @@ typedef struct gs_xstate_trans_flags {
         gs_memory_t *memory;\
         void *client_data;\
         gx_line_params line_params;\
+        bool hpgl_fill_mode;\
         gs_matrix_fixed ctm;\
         bool current_point_valid;\
         gs_point current_point;\
@@ -294,7 +295,7 @@ struct gs_imager_state_s {
 
 /* Initialization for gs_imager_state */
 #define gs_imager_state_initial(scale, is_gstate)\
-  is_gstate, 0, 0, { gx_line_params_initial },\
+  is_gstate, 0, 0, { gx_line_params_initial }, 0,\
    { (float)(scale), 0.0, 0.0, (float)(-(scale)), 0.0, 0.0 },\
   false, {0, 0}, {0, 0}, false, \
   lop_default, gx_max_color_value, BLEND_MODE_Compatible,\
diff --git a/gs/base/gxline.h b/gs/base/gxline.h
index 36072b4..851878f 100644
--- a/gs/base/gxline.h
+++ b/gs/base/gxline.h
@@ -72,6 +72,6 @@ int gx_set_dot_length(gx_line_params *, floatp, bool);
 #define gx_line_params_initial\
  0.0, gs_cap_butt, gs_cap_butt, gs_cap_butt, gs_join_miter, -1,\
  10.0, (float)0.20305866, 0.0, 0/*false*/,\
-  { identity_matrix_body }, { gx_dash_params_initial }
+ { identity_matrix_body }, { gx_dash_params_initial }
 
 #endif /* gxline_INCLUDED */
diff --git a/gs/base/gxpath.c b/gs/base/gxpath.c
index b4ef514..f7c5a85 100644
--- a/gs/base/gxpath.c
+++ b/gs/base/gxpath.c
@@ -66,6 +66,7 @@ static rc_free_proc(rc_free_path_segments_local);
 static int
     gz_path_add_point(gx_path *, fixed, fixed),
     gz_path_add_line_notes(gx_path *, fixed, fixed, segment_notes),
+    gz_path_add_gap_notes(gx_path *, fixed, fixed, segment_notes),
     gz_path_add_curve_notes(gx_path *, fixed, fixed, fixed, fixed, fixed, fixed, segment_notes),
     gz_path_close_subpath_notes(gx_path *, segment_notes);
 static byte gz_path_state_flags(gx_path *ppath, byte flags);
@@ -73,6 +74,7 @@ static byte gz_path_state_flags(gx_path *ppath, byte flags);
 static gx_path_procs default_path_procs = {
     gz_path_add_point,
     gz_path_add_line_notes,
+    gz_path_add_gap_notes,
     gz_path_add_curve_notes,
     gz_path_close_subpath_notes,
     gz_path_state_flags
@@ -84,12 +86,14 @@ static gx_path_procs default_path_procs = {
 static int
     gz_path_bbox_add_point(gx_path *, fixed, fixed),
     gz_path_bbox_add_line_notes(gx_path *, fixed, fixed, segment_notes),
+    gz_path_bbox_add_gap_notes(gx_path *, fixed, fixed, segment_notes),
     gz_path_bbox_add_curve_notes(gx_path *, fixed, fixed, fixed, fixed, fixed, fixed, segment_notes),
     gz_path_bbox_close_subpath_notes(gx_path *, segment_notes);
 
 static gx_path_procs path_bbox_procs = {
     gz_path_bbox_add_point,
     gz_path_bbox_add_line_notes,
+    gz_path_bbox_add_gap_notes,
     gz_path_bbox_add_curve_notes,
     gz_path_bbox_close_subpath_notes,
     gz_path_state_flags
@@ -588,6 +592,36 @@ gz_path_bbox_add_line_notes(gx_path * ppath, fixed x, fixed y, segment_notes not
     gz_path_bbox_move(ppath, x, y);
     return 0;
 }
+/* Add a gap to the current path (lineto). */
+int
+gx_path_add_gap_notes(gx_path * ppath, fixed x, fixed y, segment_notes notes)
+{
+    return ppath->procs->add_gap(ppath, x, y, notes);
+}
+static int
+gz_path_add_gap_notes(gx_path * ppath, fixed x, fixed y, segment_notes notes)
+{
+    subpath *psub;
+    line_segment *lp;
+
+    if (ppath->bbox_set)
+        check_in_bbox(ppath, x, y);
+    path_open();
+    path_alloc_segment(lp, line_segment, &st_line, s_gap, notes,
+                       "gx_path_add_gap");
+    path_alloc_link(lp);
+    path_set_point(lp, x, y);
+    path_update_draw(ppath);
+    trace_segment("[P]", (segment *) lp);
+    return 0;
+}
+static int
+gz_path_bbox_add_gap_notes(gx_path * ppath, fixed x, fixed y, segment_notes notes)
+{
+    gz_path_bbox_add(ppath, x, y);
+    gz_path_bbox_move(ppath, x, y);
+    return 0;
+}
 
 /* Add multiple lines to the current path. */
 /* Note that all lines have the same notes. */
@@ -1019,6 +1053,9 @@ gx_print_segment(const segment * pseg)
         case s_line:
             dprintf3("   %1.4f %1.4f lineto\t%% %s\n", px, py, out);
             break;
+        case s_gap:
+            dprintf3("   %1.4f %1.4f gapto\t%% %s\n", px, py, out);
+            break;
         case s_dash:{
                 const dash_segment *const pd = (const dash_segment *)pseg;
 
diff --git a/gs/base/gxpath.h b/gs/base/gxpath.h
index b8dedaf..48b6328 100644
--- a/gs/base/gxpath.h
+++ b/gs/base/gxpath.h
@@ -141,6 +141,7 @@ int gx_path_new(gx_path *),
     gx_path_add_point(gx_path *, fixed, fixed),
     gx_path_add_relative_point(gx_path *, fixed, fixed),
     gx_path_add_line_notes(gx_path *, fixed, fixed, segment_notes),
+    gx_path_add_gap_notes(gx_path *, fixed, fixed, segment_notes),
     gx_path_add_dash_notes(gx_path * ppath, fixed x, fixed y, fixed dx, fixed dy, segment_notes notes),
     gx_path_add_lines_notes(gx_path *, const gs_fixed_point *, int, segment_notes),
     gx_path_add_rectangle(gx_path *, fixed, fixed, fixed, fixed),
diff --git a/gs/base/gxpath2.c b/gs/base/gxpath2.c
index 01caed3..653cc03 100644
--- a/gs/base/gxpath2.c
+++ b/gs/base/gxpath2.c
@@ -186,7 +186,7 @@ gx_subpath_is_rectangular(const subpath * pseg0, gs_fixed_rect * pbox,
         ) {
         if ((pseg4 = pseg3->next) == 0 || pseg4->type == s_start)
             type = prt_open;	/* M, L, L, L */
-        else if (pseg4->type != s_line)		/* must be s_line_close */
+        else if (pseg4->type != s_line && pseg4->type != s_gap) /* must be s_line_close */
             type = prt_closed;	/* M, L, L, L, C */
         else if (pseg4->pt.x != pseg0->pt.x ||
                  pseg4->pt.y != pseg0->pt.y
@@ -194,7 +194,7 @@ gx_subpath_is_rectangular(const subpath * pseg0, gs_fixed_rect * pbox,
             return prt_none;
         else if (pseg4->next == 0 || pseg4->next->type == s_start)
             type = prt_fake_closed;	/* Mo, L, L, L, Lo */
-        else if (pseg4->next->type != s_line)	/* must be s_line_close */
+        else if (pseg4->next->type != s_line && pseg4->next->type != s_gap) /* must be s_line_close */
             type = prt_closed;	/* Mo, L, L, L, Lo, C */
         else
             return prt_none;
@@ -405,6 +405,10 @@ gx_path_copy_reversed(const gx_path * ppath_old, gx_path * ppath)
                     code = gx_path_add_line_notes(ppath,
                                         prev->pt.x, prev->pt.y, prev_notes);
                     break;
+                case s_gap:
+                    code = gx_path_add_gap_notes(ppath,
+                                        prev->pt.x, prev->pt.y, prev_notes);
+                    break;
                 case s_line_close:
                     /* Skip the closing line. */
                     code = gx_path_add_point(ppath, prev->pt.x,
@@ -504,6 +508,10 @@ gx_path_append_reversed(const gx_path * ppath_old, gx_path * ppath)
                     code = gx_path_add_line_notes(ppath,
                                         prev->pt.x, prev->pt.y, prev_notes);
                     break;
+                case s_gap:
+                    code = gx_path_add_gap_notes(ppath,
+                                        prev->pt.x, prev->pt.y, prev_notes);
+                    break;
                 case s_line_close:
                     /* Skip the closing line. */
                     code = gx_path_add_point(ppath, prev->pt.x,
@@ -588,6 +596,9 @@ gx_path_enum_next(gs_path_enum * penum, gs_fixed_point ppts[3])
         case s_line:
             ppts[0] = pseg->pt;
             return gs_pe_lineto;
+        case s_gap:
+            ppts[0] = pseg->pt;
+            return gs_pe_gapto;
         case s_line_close:
             ppts[0] = pseg->pt;
             return gs_pe_closepath;
diff --git a/gs/base/gxpcopy.c b/gs/base/gxpcopy.c
index fa8dc7a..06b46ee 100644
--- a/gs/base/gxpcopy.c
+++ b/gs/base/gxpcopy.c
@@ -52,6 +52,32 @@ break_line_if_long(gx_path *ppath, const segment *pseg)
     }
     return 0;
 }
+static inline int
+break_gap_if_long(gx_path *ppath, const segment *pseg)
+{
+    fixed x0 = ppath->position.x;
+    fixed y0 = ppath->position.y;
+
+    if (gx_check_fixed_diff_overflow(pseg->pt.x, x0) ||
+        gx_check_fixed_diff_overflow(pseg->pt.y, y0)) {
+        fixed x, y;
+
+        if (gx_check_fixed_sum_overflow(pseg->pt.x, x0))
+            x = (pseg->pt.x >> 1) + (x0 >> 1);
+        else
+            x = (pseg->pt.x + x0) >> 1;
+        if (gx_check_fixed_sum_overflow(pseg->pt.y, y0))
+            y = (pseg->pt.y >> 1) + (y0 >> 1);
+        else
+            y = (pseg->pt.y + y0) >> 1;
+        return gx_path_add_gap_notes(ppath, x, y, pseg->notes);
+        /* WARNING: Stringly speaking, the next half segment must get
+           the sn_not_first flag. We don't bother, because that flag
+           has no important meaning with colinear segments.
+         */
+    }
+    return 0;
+}
 
 /* Copy a path, optionally flattening or monotonizing it. */
 /* If the copy fails, free the new path. */
@@ -221,6 +247,14 @@ gx_path_copy_reducing(const gx_path *ppath_old, gx_path *ppath,
                                        pseg->pt.x, pseg->pt.y, pseg->notes);
                 vd_lineto(pseg->pt.x, pseg->pt.y);
                 break;
+            case s_gap:
+                code = break_gap_if_long(ppath, pseg);
+                if (code < 0)
+                    break;
+                code = gx_path_add_gap_notes(ppath,
+                                       pseg->pt.x, pseg->pt.y, pseg->notes);
+                vd_lineto(pseg->pt.x, pseg->pt.y);
+                break;
             case s_dash:
                 {
                     const dash_segment *pd = (const dash_segment *)pseg;
@@ -348,6 +382,7 @@ gx_path__check_curves(const gx_path * ppath, gx_path_copy_options options, fixed
                 }
                 break;
             case s_line:
+            case s_gap:
                 if (gx_check_fixed_diff_overflow(pseg->pt.x, pt0.x) ||
                     gx_check_fixed_diff_overflow(pseg->pt.y, pt0.y))
                     return false;
@@ -697,12 +732,15 @@ find_contacting_segments(const subpath *sp0, segment *sp0last,
        Instead it either quickly finds something, or maybe not. */
     for (s0 = sp0last, count0 = 0; count0 < search_limit && s0 != (segment *)sp0; s0 = s0->prev, count0++) {
         s0s = s0->prev;
-        if (s0->type == s_line && (s0s->pt.x == s0->pt.x ||
-            (any_abs(s0s->pt.x - s0->pt.x) == 1 && any_abs(s0s->pt.y - s0->pt.y) > min_length))) {
+        if ((s0->type == s_line || s0->type == s_gap) &&
+            (s0s->pt.x == s0->pt.x ||
+             (any_abs(s0s->pt.x - s0->pt.x) == 1 &&
+              any_abs(s0s->pt.y - s0->pt.y) > min_length))) {
             for (s1 = sp1last, count1 = 0; count1 < search_limit && s1 != (segment *)sp1; s1 = s1->prev, count1++) {
                 s1s = s1->prev;
-                if (s1->type == s_line && (s1s->pt.x == s1->pt.x ||
-                    (any_abs(s1s->pt.x - s1->pt.x) == 1 && any_abs(s1s->pt.y - s1->pt.y) > min_length))) {
+                if ((s1->type == s_line || s1->type == s_gap) &&
+                    (s1s->pt.x == s1->pt.x ||
+                     (any_abs(s1s->pt.x - s1->pt.x) == 1 && any_abs(s1s->pt.y - s1->pt.y) > min_length))) {
                     if (s0s->pt.x == s1s->pt.x || s0->pt.x == s1->pt.x || s0->pt.x == s1s->pt.x || s0s->pt.x == s1->pt.x) {
                         if (s0s->pt.y < s0->pt.y && s1s->pt.y > s1->pt.y) {
                             fixed y0 = max(s0s->pt.y, s1->pt.y);
diff --git a/gs/base/gxpdash.c b/gs/base/gxpdash.c
index 9732990..6284f30 100644
--- a/gs/base/gxpdash.c
+++ b/gs/base/gxpdash.c
@@ -90,7 +90,7 @@ subpath_expand_dashes(const subpath * psub, gx_path * ppath,
     elt_length = dash->init_dist_left;
     x = x0, y = y0;
     pseg = (const segment *)psub;
-    while ((pseg = pseg->next) != 0 && pseg->type != s_start) {
+    while ((pseg = pseg->next) != 0 && pseg->type != s_start && pseg->type != s_gap) {
         fixed sx = pseg->pt.x, sy = pseg->pt.y;
         fixed udx = sx - x, udy = sy - y;
         double length, dx, dy;
@@ -179,7 +179,7 @@ subpath_expand_dashes(const subpath * psub, gx_path * ppath,
             const segment *pseg2 = pseg->next;
 
             end_notes = 0;
-            while (pseg2 != 0 && pseg2->type != s_start)
+            while (pseg2 != 0 && pseg2->type != s_start && pseg2->type != s_gap)
             {
                 if ((pseg2->pt.x != sx) || (pseg2->pt.x != sy)) {
                     /* Non degenerate. We aren't the last one */
@@ -216,7 +216,10 @@ subpath_expand_dashes(const subpath * psub, gx_path * ppath,
             code = gx_path_add_point(ppath, sx, sy);
             notes &= ~sn_not_first;
             if (elt_length < fixed2float(fixed_epsilon) &&
-                (pseg->next == 0 || pseg->next->type == s_start || elt_length == 0)) {
+                (pseg->next == 0 ||
+                 pseg->next->type == s_start ||
+                 pseg->next->type == s_gap ||
+                 elt_length == 0)) {
                 /*
                  * Ink is off, but we're within epsilon of the end
                  * of the dash element.
@@ -231,7 +234,9 @@ subpath_expand_dashes(const subpath * psub, gx_path * ppath,
                 if (++index == count)
                     index = 0;
                 elt_length1 = pattern[index] * scale;
-                if (pseg->next == 0 || pseg->next->type == s_start) {
+                if (pseg->next == 0 ||
+                    pseg->next->type == s_start ||
+                    pseg->next->type == s_gap) {
                     elt_length = elt_length1;
                     left = 0;
                     ink_on = true;
diff --git a/gs/base/gxstroke.c b/gs/base/gxstroke.c
index 86d5502..b9d3eba 100644
--- a/gs/base/gxstroke.c
+++ b/gs/base/gxstroke.c
@@ -146,6 +146,7 @@ gx_stroke_path_expansion(const gs_imager_state * pis, const gx_path * ppath,
                 if (!(pseg->pt.x == prev.x || pseg->pt.y == prev.y))
                     goto not_exact;
                 break;
+            case s_gap:
             default:            /* other/unknown segment type */
                 goto not_exact;
             }
@@ -706,6 +707,7 @@ gx_stroke_path_only_aux(gx_path * ppath, gx_path * to_path, gx_device * pdev,
             /* We work with unscaled values, for speed. */
             fixed sx, udx, sy, udy;
             bool is_dash_segment = false;
+            bool is_gap_segment = pseg->type == s_gap;
 
          d1:if (pseg->type != s_dash) {
                 sx = pseg->pt.x;
@@ -739,7 +741,8 @@ gx_stroke_path_only_aux(gx_path * ppath, gx_path * to_path, gx_device * pdev,
                     continue;
                 /* Check for a degenerate subpath. */
                 while ((pseg = pseg->next) != 0 &&
-                       pseg->type != s_start
+                       pseg->type != s_start &&
+                       pseg->type != s_gap
                     ) {
                     if (is_dash_segment)
                         break;
@@ -793,7 +796,7 @@ gx_stroke_path_only_aux(gx_path * ppath, gx_path * to_path, gx_device * pdev,
                         udy = fixed_1;
                     }
                 }
-                if (sx == x && sy == y && (pseg == NULL || pseg->type == s_start)) {
+                if (sx == x && sy == y && (pseg == NULL || pseg->type == s_start || pseg->type == s_gap)) {
                     double scale = device_dot_length /
                                 hypot((double)udx, (double)udy);
                     fixed udx1, udy1;
@@ -892,14 +895,14 @@ gx_stroke_path_only_aux(gx_path * ppath, gx_path * to_path, gx_device * pdev,
                     if (index)
                         dev->sgr.stroke_stored = false;
                     adjust_stroke(dev, &pl, pis, false,
-                            (pseg->prev == 0 || pseg->prev->type == s_start) &&
-                            (pseg->next == 0 || pseg->next->type == s_start) &&
+                            (pseg->prev == 0 || pseg->prev->type == s_start || pseg->prev->type == s_gap) &&
+                            (pseg->next == 0 || pseg->next->type == s_start || pseg->next->type == s_gap) &&
                             (zero_length || !is_closed),
                             COMBINE_FLAGS(flags));
                     compute_caps(&pl);
                 }
             }
-            if (index++) {
+            if ((pseg->prev && pseg->prev->type != s_gap) && index++) {
                 gs_line_join join =
                     (pseg->notes & not_first ? curve_join : pgs_lp->join);
                 int first;
@@ -920,6 +923,8 @@ gx_stroke_path_only_aux(gx_path * ppath, gx_path * to_path, gx_device * pdev,
                 if (is_dash_segment) /* Never join to a dash segment */
                     lptr = NULL;
 #endif
+                if (lptr && pseg->type == s_gap)
+                    lptr = NULL;
                 ensure_closed = ((to_path == &stroke_path_body &&
                                   lop_is_idempotent(pis->log_op)) ||
                                  (lptr == NULL ? true : lptr->thin));
@@ -955,6 +960,9 @@ gx_stroke_path_only_aux(gx_path * ppath, gx_path * to_path, gx_device * pdev,
             if (lptr && psub->type == s_dash)
                 lptr = NULL;
 #endif
+            if (psub && psub->next && psub->next->type == s_gap)
+                lptr = NULL;
+            
             flags = (((notes & sn_not_first) ?
                       ((flags & nf_all_from_arc) | nf_some_from_arc) : 0) |
                      ((notes & sn_dash_head) ? nf_dash_head : 0) |
diff --git a/gs/base/gxttfb.c b/gs/base/gxttfb.c
index 418d20c..83d68d2 100644
--- a/gs/base/gxttfb.c
+++ b/gs/base/gxttfb.c
@@ -562,6 +562,7 @@ path_to_hinter(t1_hinter *h, gx_path *path)
                     code = t1_hinter__rmoveto(h, pts[0].x - p.x, pts[0].y - p.y);
                 break;
             case gs_pe_lineto:
+            case gs_pe_gapto:
                 code = t1_hinter__rlineto(h, pts[0].x - p.x, pts[0].y - p.y);
                 break;
             case gs_pe_curveto:
diff --git a/gs/base/gzpath.h b/gs/base/gzpath.h
index 4d48f8b..181154b 100644
--- a/gs/base/gzpath.h
+++ b/gs/base/gzpath.h
@@ -37,7 +37,8 @@ typedef enum {
     s_line,
     s_line_close,
     s_curve,
-    s_dash /* only for internal use of the stroking algorithm */
+    s_dash, /* only for internal use of the stroking algorithm */
+    s_gap
 } segment_type;
 
 /* Define the common structure for all segments. */
@@ -282,6 +283,7 @@ typedef enum {
 typedef struct gx_path_procs_s {
     int (*add_point)(gx_path *, fixed, fixed);
     int (*add_line)(gx_path *, fixed, fixed, segment_notes);
+    int (*add_gap)(gx_path *, fixed, fixed, segment_notes);
     int (*add_curve)(gx_path *, fixed, fixed, fixed, fixed, fixed, fixed, segment_notes);
     int (*close_subpath)(gx_path *, segment_notes);
     byte (*state_flags)(gx_path *, byte);
diff --git a/gs/psi/zgstate.c b/gs/psi/zgstate.c
index 1c06bfd..f913018 100644
--- a/gs/psi/zgstate.c
+++ b/gs/psi/zgstate.c
@@ -513,6 +513,20 @@ zcurrenttextrenderingmode(i_ctx_t *i_ctx_p)
     return zcurrent_uint(i_ctx_p, gs_currenttextrenderingmode);
 }
 
+/* <int> .sethpglfill - */
+static int
+zsethpglfillmode(i_ctx_t *i_ctx_p)
+{
+    return zset_uint(i_ctx_p, gs_sethpglfillmode);
+}
+
+/* - .currenttextrenderingmode <int> */
+static int
+zcurrenthpglfillmode(i_ctx_t *i_ctx_p)
+{
+    return zcurrent_uint(i_ctx_p, gs_currenthpglfillmode);
+}
+
 /* ------ Initialization procedure ------ */
 
 /* We need to split the table because of the 16-element limit. */
@@ -555,6 +569,8 @@ const op_def zgstate2_op_defs[] = {
 const op_def zgstate3_op_defs[] = {
     {"0.settextrenderingmode", zsettextrenderingmode},
     {"0.currenttextrenderingmode", zcurrenttextrenderingmode},
+    {"0.sethpglfillmode", zsethpglfillmode},
+    {"0.currenthpglfillmode", zcurrenthpglfillmode},
     op_def_end(0)
 };
 


Summary of changes:
 gs/base/gdevpdfd.c |    1 +
 gs/base/gdevtrac.c |    4 ++++
 gs/base/gdevvec.c  |    3 +++
 gs/base/gspath.c   |   19 ++++++++++++++-----
 gs/base/gspath1.c  |    1 +
 gs/base/gspenum.h  |    1 +
 gs/base/gsstate.c  |   14 ++++++++++++++
 gs/base/gsstate.h  |    2 ++
 gs/base/gxclpath.c |    1 +
 gs/base/gxcpath.c  |    4 ++++
 gs/base/gxistate.h |    3 ++-
 gs/base/gxline.h   |    2 +-
 gs/base/gxpath.c   |   37 +++++++++++++++++++++++++++++++++++++
 gs/base/gxpath.h   |    1 +
 gs/base/gxpath2.c  |   15 +++++++++++++--
 gs/base/gxpcopy.c  |   46 ++++++++++++++++++++++++++++++++++++++++++----
 gs/base/gxpdash.c  |   13 +++++++++----
 gs/base/gxstroke.c |   18 +++++++++++++-----
 gs/base/gxttfb.c   |    1 +
 gs/base/gzpath.h   |    4 +++-
 gs/psi/zgstate.c   |   16 ++++++++++++++++
 21 files changed, 183 insertions(+), 23 deletions(-)



More information about the gs-commits mailing list