diff options
author | Robin Watts <robin.watts@artifex.com> | 2012-04-18 16:24:57 +0100 |
---|---|---|
committer | Robin Watts <robin.watts@artifex.com> | 2012-04-19 00:37:47 +0100 |
commit | 7aa46e79f2f4994ec94aa94d4a1129e10b6cbd4d (patch) | |
tree | cffeb572b7c1e06ba44087bbd9ee8e56ca178152 /draw/draw_path.c | |
parent | ab29b6831c384048c1011e72dc2a061ac4e66927 (diff) | |
download | mupdf-7aa46e79f2f4994ec94aa94d4a1129e10b6cbd4d.tar.xz |
Bug 692990: Fix 'underjoin' of strokes.
See Bug 688655 for analysis of what we SHOULD be doing. The code changes
to do this are actually quite small.
Essentially, when we join we only draw the 'top' (or 'outer') join in a
join dependent way. The 'under' join was always joined as a bevel before
as this was easy. This produces bad effects when the lines have a
significant angle between them and a large linewidth.
The correct (i.e. matching Acrobat and others) way to work is to
join the bottom of the line via the centre point. The sole exception
to this is when drawing under beziers, as we don't want to make our
approximation-by-lines obvious.
All fixed in this patch.
Diffstat (limited to 'draw/draw_path.c')
-rw-r--r-- | draw/draw_path.c | 46 |
1 files changed, 28 insertions, 18 deletions
diff --git a/draw/draw_path.c b/draw/draw_path.c index 2ef8cf3a..458ce349 100644 --- a/draw/draw_path.c +++ b/draw/draw_path.c @@ -135,6 +135,7 @@ struct sctx fz_point seg[2]; int sn, bn; int dot; + int from_bezier; float *dash_list; float dash_phase; @@ -212,7 +213,7 @@ fz_add_line_stroke(struct sctx *s, fz_point a, fz_point b) } static void -fz_add_line_join(struct sctx *s, fz_point a, fz_point b, fz_point c) +fz_add_line_join(struct sctx *s, fz_point a, fz_point b, fz_point c, int join_under) { float miterlimit = s->miterlimit; float linewidth = s->linewidth; @@ -265,6 +266,16 @@ fz_add_line_join(struct sctx *s, fz_point a, fz_point b, fz_point c) if (cross * cross < FLT_EPSILON && dx0 * dx1 + dy0 * dy1 >= 0) linejoin = FZ_LINEJOIN_BEVEL; + if (join_under) + { + fz_add_line(s, b.x + dlx1, b.y + dly1, b.x + dlx0, b.y + dly0); + } + else + { + fz_add_line(s, b.x + dlx1, b.y + dly1, b.x, b.y); + fz_add_line(s, b.x, b.y, b.x + dlx0, b.y + dly0); + } + /* XPS miter joins are clipped at miterlength, rather than simply * being converted to bevelled joins. */ if (linejoin == FZ_LINEJOIN_MITER_XPS) @@ -285,7 +296,6 @@ fz_add_line_join(struct sctx *s, fz_point a, fz_point b, fz_point c) t1x = b.x - dmx + k * (dmx - dlx1); t1y = b.y - dmy + k * (dmy - dly1); - fz_add_line(s, b.x + dlx1, b.y + dly1, b.x + dlx0, b.y + dly0); fz_add_line(s, b.x - dlx0, b.y - dly0, t0x, t0y); fz_add_line(s, t0x, t0y, t1x, t1y); fz_add_line(s, t1x, t1y, b.x - dlx1, b.y - dly1); @@ -301,7 +311,6 @@ fz_add_line_join(struct sctx *s, fz_point a, fz_point b, fz_point c) dmx *= scale; dmy *= scale; - fz_add_line(s, b.x + dlx1, b.y + dly1, b.x + dlx0, b.y + dly0); fz_add_line(s, b.x - dlx0, b.y - dly0, b.x - dmx, b.y - dmy); fz_add_line(s, b.x - dmx, b.y - dmy, b.x - dlx1, b.y - dly1); } @@ -309,12 +318,10 @@ fz_add_line_join(struct sctx *s, fz_point a, fz_point b, fz_point c) if (linejoin == FZ_LINEJOIN_BEVEL) { fz_add_line(s, b.x - dlx0, b.y - dly0, b.x - dlx1, b.y - dly1); - fz_add_line(s, b.x + dlx1, b.y + dly1, b.x + dlx0, b.y + dly0); } if (linejoin == FZ_LINEJOIN_ROUND) { - fz_add_line(s, b.x + dlx1, b.y + dly1, b.x + dlx0, b.y + dly0); fz_add_arc(s, b.x, b.y, -dlx0, -dly0, -dlx1, -dly1); } } @@ -421,10 +428,11 @@ fz_stroke_moveto(struct sctx *s, fz_point cur) s->sn = 1; s->bn = 1; s->dot = 0; + s->from_bezier = 0; } static void -fz_stroke_lineto(struct sctx *s, fz_point cur) +fz_stroke_lineto(struct sctx *s, fz_point cur, int from_bezier) { float dx = cur.x - s->seg[s->sn-1].x; float dy = cur.y - s->seg[s->sn-1].y; @@ -440,10 +448,11 @@ fz_stroke_lineto(struct sctx *s, fz_point cur) if (s->sn == 2) { - fz_add_line_join(s, s->seg[0], s->seg[1], cur); + fz_add_line_join(s, s->seg[0], s->seg[1], cur, s->from_bezier & from_bezier); s->seg[0] = s->seg[1]; s->seg[1] = cur; } + s->from_bezier = from_bezier; if (s->sn == 1) s->seg[s->sn++] = cur; @@ -456,11 +465,11 @@ fz_stroke_closepath(struct sctx *s) { if (s->sn == 2) { - fz_stroke_lineto(s, s->beg[0]); + fz_stroke_lineto(s, s->beg[0], 0); if (s->seg[1].x == s->beg[0].x && s->seg[1].y == s->beg[0].y) - fz_add_line_join(s, s->seg[0], s->beg[0], s->beg[1]); + fz_add_line_join(s, s->seg[0], s->beg[0], s->beg[1], 0); else - fz_add_line_join(s, s->seg[1], s->beg[0], s->beg[1]); + fz_add_line_join(s, s->seg[1], s->beg[0], s->beg[1], 0); } else if (s->dot) { @@ -471,6 +480,7 @@ fz_stroke_closepath(struct sctx *s) s->bn = 1; s->sn = 1; s->dot = 0; + s->from_bezier = 0; } static void @@ -498,7 +508,7 @@ fz_stroke_bezier(struct sctx *s, fz_point p; p.x = xd; p.y = yd; - fz_stroke_lineto(s, p); + fz_stroke_lineto(s, p, 1); return; } @@ -579,7 +589,7 @@ fz_flatten_stroke_path(fz_gel *gel, fz_path *path, fz_stroke_state *stroke, fz_m case FZ_LINETO: p1.x = path->items[i++].v; p1.y = path->items[i++].v; - fz_stroke_lineto(&s, p1); + fz_stroke_lineto(&s, p1, 0); p0 = p1; break; @@ -630,7 +640,7 @@ fz_dash_moveto(struct sctx *s, fz_point a, fz_linecap start_cap, fz_linecap end_ } static void -fz_dash_lineto(struct sctx *s, fz_point b, int dash_cap) +fz_dash_lineto(struct sctx *s, fz_point b, int dash_cap, int from_bezier) { float dx, dy; float total, used, ratio; @@ -652,7 +662,7 @@ fz_dash_lineto(struct sctx *s, fz_point b, int dash_cap) if (s->toggle) { - fz_stroke_lineto(s, m); + fz_stroke_lineto(s, m, from_bezier); } else { @@ -674,7 +684,7 @@ fz_dash_lineto(struct sctx *s, fz_point b, int dash_cap) if (s->toggle) { - fz_stroke_lineto(s, b); + fz_stroke_lineto(s, b, from_bezier); } } @@ -704,7 +714,7 @@ fz_dash_bezier(struct sctx *s, fz_point p; p.x = xd; p.y = yd; - fz_dash_lineto(s, p, dash_cap); + fz_dash_lineto(s, p, dash_cap, 1); return; } @@ -794,7 +804,7 @@ fz_flatten_dash_path(fz_gel *gel, fz_path *path, fz_stroke_state *stroke, fz_mat case FZ_LINETO: p1.x = path->items[i++].v; p1.y = path->items[i++].v; - fz_dash_lineto(&s, p1, stroke->dash_cap); + fz_dash_lineto(&s, p1, stroke->dash_cap, 0); p0 = p1; break; @@ -810,7 +820,7 @@ fz_flatten_dash_path(fz_gel *gel, fz_path *path, fz_stroke_state *stroke, fz_mat break; case FZ_CLOSE_PATH: - fz_dash_lineto(&s, beg, stroke->dash_cap); + fz_dash_lineto(&s, beg, stroke->dash_cap, 0); p0 = p1 = beg; break; } |