summaryrefslogtreecommitdiff
path: root/base/gxstroke.c
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2016-01-20 20:15:42 +0000
committerRobin Watts <robin.watts@artifex.com>2016-01-21 21:21:53 +0000
commit064559beaa05329b1d9e6283e6d17a8c87765e7f (patch)
tree7cbf276aba42857f44d5f87d08299b5c4e45e33e /base/gxstroke.c
parent68dc00f46d402685f2060ce7ae1b64056996556f (diff)
downloadghostpdl-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.c31
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;