summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gs/base/gdevpdfd.c1
-rw-r--r--gs/base/gdevtrac.c4
-rw-r--r--gs/base/gdevvec.c3
-rw-r--r--gs/base/gspath.c19
-rw-r--r--gs/base/gspath1.c1
-rw-r--r--gs/base/gspenum.h1
-rw-r--r--gs/base/gsstate.c14
-rw-r--r--gs/base/gsstate.h2
-rw-r--r--gs/base/gxclpath.c1
-rw-r--r--gs/base/gxcpath.c4
-rw-r--r--gs/base/gxistate.h3
-rw-r--r--gs/base/gxline.h2
-rw-r--r--gs/base/gxpath.c37
-rw-r--r--gs/base/gxpath.h1
-rw-r--r--gs/base/gxpath2.c15
-rw-r--r--gs/base/gxpcopy.c46
-rw-r--r--gs/base/gxpdash.c13
-rw-r--r--gs/base/gxstroke.c18
-rw-r--r--gs/base/gxttfb.c1
-rw-r--r--gs/base/gzpath.h4
-rw-r--r--gs/psi/zgstate.c16
21 files changed, 183 insertions, 23 deletions
diff --git a/gs/base/gdevpdfd.c b/gs/base/gdevpdfd.c
index b5ad3199a..0f058515d 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 535cebc01..be1492f01 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 b4a6ef4b3..ecff2d230 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 4964b2a08..dbdd7be53 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 4f4d760ae..f886460f8 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 920a72d92..5cda5033d 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 470ca8eea..d279acecd 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 5b6bea5a0..7fa8ceea6 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 01fa187ef..df250cd94 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 d0ada3762..05bbcb004 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 e1ac8a1e2..9923ae83b 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 36072b4ef..851878f29 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 b4ef51468..f7c5a853a 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 b8dedafd7..48b6328d8 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 01caed385..653cc03cf 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 fa8dc7a79..06b46eed2 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 9732990bb..6284f30c2 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 86d550227..b9d3eba0d 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 418d20ca8..83d68d20f 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 4d48f8bbd..181154b63 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 1c06bfd24..f91301853 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)
};