diff options
author | Robin Watts <robin.watts@artifex.com> | 2016-01-20 20:15:42 +0000 |
---|---|---|
committer | Robin Watts <robin.watts@artifex.com> | 2016-01-21 21:21:53 +0000 |
commit | 064559beaa05329b1d9e6283e6d17a8c87765e7f (patch) | |
tree | 7cbf276aba42857f44d5f87d08299b5c4e45e33e /base/gxstroke.c | |
parent | 68dc00f46d402685f2060ce7ae1b64056996556f (diff) | |
download | ghostpdl-064559beaa05329b1d9e6283e6d17a8c87765e7f.tar.gz |
Bug 696466: Fix incorrect line joins in strokes.
When we flatten a path for stroking, we keep 'notes' on each
line to tell us whether each line was present in the original
path, or whether it was generated by the flattening process.
We further note which lines were generated by the flattening
process, and are NOT the first one in a given curve. We do this
so that we can apply the 'curve join' to the start of such line
segments.
The "curve_join" is an optimisation to speed path drawing. When
we've flattened a curve, it makes no sense to draw (say) a round
join between each flattened line, because they will be almost
parallel, and the join will be visually indistinguishable from
a simple bevel (in most cases).
It's still important that we draw the correct curve between any
preceeding line and the first line in the curve though.
Sometimes, (especially when setaccuratecurves is turned on), the
first line in a flattened curve may be degenerate (i.e. 0 length).
The stroker spots degenerate sections and skips them. Unfortunately
that means it also skips the note about it being the first line
from a curve, and the wrong join is used.
The fix implemented here is to alter the stroker so that when
it skips a degenerate section, it checks for the 'first line
from an arc' flag and carries it forwards.
Diffstat (limited to 'base/gxstroke.c')
-rw-r--r-- | base/gxstroke.c | 31 |
1 files changed, 24 insertions, 7 deletions
diff --git a/base/gxstroke.c b/base/gxstroke.c index a4670adf3..d58839092 100644 --- a/base/gxstroke.c +++ b/base/gxstroke.c @@ -720,6 +720,7 @@ gx_stroke_path_only_aux(gx_path * ppath, gx_path * to_path, gx_device * pdev, bool is_closed = ((const subpath *)pseg)->is_closed; partial_line pl, pl_prev, pl_first; bool zero_length = true; + int pseg_notes = pseg->notes; flags = nf_all_from_arc; @@ -733,9 +734,12 @@ gx_stroke_path_only_aux(gx_path * ppath, gx_path * to_path, gx_device * pdev, /* Compute the width parameters in device space. */ /* We work with unscaled values, for speed. */ fixed sx, udx, sy, udy; - bool is_dash_segment = false; + bool is_dash_segment; - d1:if (pseg->type == s_dash) { + pseg_notes = pseg->notes; + + d2:is_dash_segment = false; + d1:if (pseg->type == s_dash) { dash_segment *pd = (dash_segment *)pseg; sx = pd->pt.x; @@ -757,10 +761,10 @@ gx_stroke_path_only_aux(gx_path * ppath, gx_path * to_path, gx_device * pdev, } zero_length &= ((udx | udy) == 0); pl.o.p.x = x, pl.o.p.y = y; - d:flags = (((pseg->notes & sn_not_first) ? + d:flags = (((pseg_notes & sn_not_first) ? ((flags & nf_all_from_arc) | nf_some_from_arc) : 0) | - ((pseg->notes & sn_dash_head) ? nf_dash_head : 0) | - ((pseg->notes & sn_dash_tail) ? nf_dash_tail : 0) | + ((pseg_notes & sn_dash_head) ? nf_dash_head : 0) | + ((pseg_notes & sn_dash_tail) ? nf_dash_tail : 0) | (flags & ~nf_all_from_arc)); pl.e.p.x = sx, pl.e.p.y = sy; if (!(udx | udy) || pseg->type == s_dash || pseg->type == s_gap) { /* degenerate or short */ @@ -770,7 +774,20 @@ gx_stroke_path_only_aux(gx_path * ppath, gx_path * to_path, gx_device * pdev, * Otherwise, ignore the degenerate segment. */ if (index != 0 && pseg->type != s_dash && pseg->type != s_gap) - continue; + { + if (pseg->next == NULL || pseg->next->type == s_start) + continue; + pseg = pseg->next; + /* We're skipping a degenerate path segment; if it was + * labelled as being the first from a curve, then make + * sure the one we're skipping to is also labelled as + * being the first from a curve, otherwise we can get + * improper joins being used. See Bug 696466. */ + pseg_notes = (((pseg_notes & sn_not_first) == 0) ? + (pseg->notes & ~sn_not_first) : + pseg->notes); + goto d2; + } /* Check for a degenerate subpath. */ while ((pseg = pseg->next) != 0 && pseg->type != s_start @@ -942,7 +959,7 @@ gx_stroke_path_only_aux(gx_path * ppath, gx_path * to_path, gx_device * pdev, } if (index++) { gs_line_join join = - (pseg->notes & not_first ? curve_join : pgs_lp->join); + (pseg_notes & not_first ? curve_join : pgs_lp->join); int first; pl_ptr lptr; bool ensure_closed; |