diff options
author | Robin Watts <robin.watts@artifex.com> | 2014-01-13 18:11:51 +0000 |
---|---|---|
committer | Robin Watts <robin.watts@artifex.com> | 2014-01-13 18:20:36 +0000 |
commit | c3305e7280d446737fbad0dba13712385becf7ad (patch) | |
tree | 0ce600578101b976c5b1ce58da1f9c0743c24f15 /source/fitz | |
parent | a8c6cc692288d6778dfcfe2c29545721e3829b8c (diff) | |
download | mupdf-c3305e7280d446737fbad0dba13712385becf7ad.tar.xz |
Avoid rendering errors caused by linejoins on tiny distances.
If we perform a linejoin that ends up being over an impossibly small
distance, we can get a rendering error. This is caused by trying to
calculate scale = linewidth/sqrtf(len), where len < FLT_EPSILON.
Avoid this by rearranging the code slightly - no extra calculations
required.
Also given that sn == bn at all times within the stroking code, just
remove bn.
Credit for spotting this problem goes to Simon for tracking the
problem with rounding_artifact_due_to_closepath.pdf. My fix just
fixes the problem at a lower level than his does.
Diffstat (limited to 'source/fitz')
-rw-r--r-- | source/fitz/draw-path.c | 46 |
1 files changed, 28 insertions, 18 deletions
diff --git a/source/fitz/draw-path.c b/source/fitz/draw-path.c index b33ea8b4..b1bcb11b 100644 --- a/source/fitz/draw-path.c +++ b/source/fitz/draw-path.c @@ -134,7 +134,7 @@ struct sctx float miterlimit; fz_point beg[2]; fz_point seg[2]; - int sn, bn; + int sn; int dot; int from_bezier; @@ -249,18 +249,31 @@ fz_add_line_join(struct sctx *s, fz_point a, fz_point b, fz_point c, int join_un len0 = dx0 * dx0 + dy0 * dy0; if (len0 < FLT_EPSILON) + { linejoin = FZ_LINEJOIN_BEVEL; + dlx0 = 0; + dly0 = 0; + } + else + { + scale = linewidth / sqrtf(len0); + dlx0 = dy0 * scale; + dly0 = -dx0 * scale; + } + len1 = dx1 * dx1 + dy1 * dy1; if (len1 < FLT_EPSILON) + { linejoin = FZ_LINEJOIN_BEVEL; - - scale = linewidth / sqrtf(len0); - dlx0 = dy0 * scale; - dly0 = -dx0 * scale; - - scale = linewidth / sqrtf(len1); - dlx1 = dy1 * scale; - dly1 = -dx1 * scale; + dlx1 = 0; + dly1 = 0; + } + else + { + scale = linewidth / sqrtf(len1); + dlx1 = dy1 * scale; + dly1 = -dx1 * scale; + } dmx = (dlx0 + dlx1) * 0.5f; dmy = (dly0 + dly1) * 0.5f; @@ -429,7 +442,6 @@ fz_stroke_moveto(struct sctx *s, fz_point cur) s->seg[0] = cur; s->beg[0] = cur; s->sn = 1; - s->bn = 1; s->dot = 0; s->from_bezier = 0; } @@ -455,12 +467,13 @@ fz_stroke_lineto(struct sctx *s, fz_point cur, int from_bezier) s->seg[0] = s->seg[1]; s->seg[1] = cur; } + else + { + s->seg[1] = cur; + s->beg[1] = cur; + s->sn = 2; + } s->from_bezier = from_bezier; - - if (s->sn == 1) - s->seg[s->sn++] = cur; - if (s->bn == 1) - s->beg[s->bn++] = cur; } static void @@ -480,7 +493,6 @@ fz_stroke_closepath(struct sctx *s) } s->seg[0] = s->beg[0]; - s->bn = 1; s->sn = 1; s->dot = 0; s->from_bezier = 0; @@ -558,7 +570,6 @@ fz_flatten_stroke_path(fz_gel *gel, fz_path *path, const fz_stroke_state *stroke s.linewidth = linewidth * 0.5f; /* hairlines use a different value from the path value */ s.miterlimit = stroke->miterlimit; s.sn = 0; - s.bn = 0; s.dot = 0; s.dash_list = NULL; @@ -952,7 +963,6 @@ fz_flatten_dash_path(fz_gel *gel, fz_path *path, const fz_stroke_state *stroke, s.linewidth = linewidth * 0.5f; s.miterlimit = stroke->miterlimit; s.sn = 0; - s.bn = 0; s.dot = 0; s.dash_list = stroke->dash_list; |