summaryrefslogtreecommitdiff
path: root/source/fitz/draw-path.c
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2017-11-09 16:48:39 +0000
committerRobin Watts <robin.watts@artifex.com>2017-11-10 13:04:34 +0000
commit93ec9fcda7fdc74284c9ffe03915760650c02670 (patch)
tree35fb62d73081d9673525fc0e180676d32ca39d1b /source/fitz/draw-path.c
parent62fe02de29a64f4a642bc41964dfe5ba69f39ab7 (diff)
downloadmupdf-93ec9fcda7fdc74284c9ffe03915760650c02670.tar.xz
Fix potential problem with null path segments leaving dots.
When stroking paths if we meet segments of 0 length, we can't determine a direction, thus start/end caps are omitted. Line widths are irrelevant, and we thus render nothing. (Note that moves on their own do NOT count as a line segment). The exception to this is where we are using round caps, whereupon whatever direction the path is taken to have, the appearance will be the same - and this we render the segment as a dot. We have code in the renderer already to do this, but it looks to me like it could be fooled into leaving a dot by us first doing a move, a lineto the same point, and then a lineto to somewhere else. The current code sets the 'dot' value to 1 when it detects the degenerate line, and doesn't reset when it meets a non-degenerate line later. Accordingly I've changed the code here to account for such a circumstance. This produces no diffs in the cluster testing, but seems more correct to me.
Diffstat (limited to 'source/fitz/draw-path.c')
-rw-r--r--source/fitz/draw-path.c23
1 files changed, 14 insertions, 9 deletions
diff --git a/source/fitz/draw-path.c b/source/fitz/draw-path.c
index 2c3d8e37..09cb06db 100644
--- a/source/fitz/draw-path.c
+++ b/source/fitz/draw-path.c
@@ -305,6 +305,12 @@ fz_flatten_fill_path(fz_context *ctx, fz_rasterizer *rast, const fz_path *path,
return fz_is_empty_irect(fz_intersect_irect(bbox, &local_bbox));
}
+enum {
+ ONLY_MOVES = 0,
+ NON_NULL_LINE = 1,
+ NULL_LINE
+};
+
typedef struct sctx
{
fz_rasterizer *rast;
@@ -720,10 +726,8 @@ fz_stroke_flush(fz_context *ctx, sctx *s, fz_linecap start_cap, fz_linecap end_c
fz_add_line_cap(ctx, s, s->beg[1].x, s->beg[1].y, s->beg[0].x, s->beg[0].y, start_cap, 2);
fz_add_line_cap(ctx, s, s->seg[0].x, s->seg[0].y, s->seg[1].x, s->seg[1].y, end_cap, 0);
}
- else if (s->dot)
- {
+ else if (s->dot == NULL_LINE)
fz_add_line_dot(ctx, s, s->beg[0].x, s->beg[0].y);
- }
fz_gap_rasterizer(ctx, s->rast);
}
@@ -735,7 +739,7 @@ fz_stroke_moveto(fz_context *ctx, void *s_, float x, float y)
s->seg[0].x = s->beg[0].x = x;
s->seg[0].y = s->beg[0].y = y;
s->sn = 1;
- s->dot = 0;
+ s->dot = ONLY_MOVES;
s->from_bezier = 0;
}
@@ -750,10 +754,11 @@ fz_stroke_lineto(fz_context *ctx, sctx *s, float x, float y, int from_bezier)
if (dx * dx + dy * dy < FLT_EPSILON)
{
- if (s->cap == FZ_LINECAP_ROUND || s->dash_list)
- s->dot = 1;
+ if (s->dot == ONLY_MOVES && (s->cap == FZ_LINECAP_ROUND || s->dash_list))
+ s->dot = NULL_LINE;
return;
}
+ s->dot = NON_NULL_LINE;
if (s->sn == 2)
fz_add_line_join(ctx, s, s->seg[0].x, s->seg[0].y, ox, oy, x, y, s->from_bezier & from_bezier);
@@ -805,12 +810,12 @@ fz_stroke_closepath(fz_context *ctx, sctx *s)
else
fz_add_line_join(ctx, s, s->seg[1].x, s->seg[1].y, s->beg[0].x, s->beg[0].y, s->beg[1].x, s->beg[1].y, 0);
}
- else if (s->dot)
+ else if (s->dot == NULL_LINE)
fz_add_line_dot(ctx, s, s->beg[0].x, s->beg[0].y);
s->seg[0] = s->beg[0];
s->sn = 1;
- s->dot = 0;
+ s->dot = ONLY_MOVES;
s->from_bezier = 0;
fz_gap_rasterizer(ctx, s->rast);
@@ -1409,7 +1414,7 @@ do_flatten_stroke(fz_context *ctx, fz_rasterizer *rast, const fz_path *path, con
s.linewidth = linewidth * 0.5f; /* hairlines use a different value from the path value */
s.miterlimit = stroke->miterlimit;
s.sn = 0;
- s.dot = 0;
+ s.dot = ONLY_MOVES;
s.toggle = 0;
s.offset = 0;
s.phase = 0;