summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2012-08-20 14:21:23 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2012-08-20 14:21:23 +0100
commitee7f5607192a3341df45199b1c7c8996f2b7347d (patch)
treef80debe60b37c525ab5df33ad9a32dcb45460b28
parent2a0d81743270aaff29e8951c896cde644fd4e576 (diff)
stroker: Avoid emitting a miter join for across an elided degenerate segment
Given the criteria of the rectlinear stroker that it only handles horizontal and vertical line segments, and eliminates degenerate segments before stroking, we must be careful not to apply a join between two horizontal segments (for example if the intervening vertical segment was degenerate and so elided). A miter join between two colinear segments is empty, yet we were blissfully extending the line caps to cover the join. Fixes: outline-tolerance Bugzilla: https://bugzilla.mozilla.org/show_bug.cgi?id=407107 Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/cairo-path-stroke-boxes.c18
1 files changed, 11 insertions, 7 deletions
diff --git a/src/cairo-path-stroke-boxes.c b/src/cairo-path-stroke-boxes.c
index 50c53f37..7f25bf76 100644
--- a/src/cairo-path-stroke-boxes.c
+++ b/src/cairo-path-stroke-boxes.c
@@ -203,7 +203,7 @@ _cairo_rectilinear_stroker_emit_segments (cairo_rectilinear_stroker_t *stroker)
cairo_fixed_t half_line_x = stroker->half_line_x;
cairo_fixed_t half_line_y = stroker->half_line_y;
cairo_status_t status;
- int i;
+ int i, j;
/* For each segment we generate a single rectangle.
* This rectangle is based on a perpendicular extension (by half the
@@ -221,20 +221,24 @@ _cairo_rectilinear_stroker_emit_segments (cairo_rectilinear_stroker_t *stroker)
/* We adjust the initial point of the segment to extend the
* rectangle to include the previous cap or join, (this
* adjustment applies to all segments except for the first
- * segment of open, butt-capped paths).
+ * segment of open, butt-capped paths). However, we must be
+ * careful not to emit a miter join across a degenerate segment
+ * which has been elided.
*
* Overlapping segments will be eliminated by the tessellation.
* Ideally, we would not emit these self-intersections at all,
* but that is tricky with segments shorter than half_line_width.
*/
- lengthen_initial = TRUE;
- lengthen_final = TRUE;
- if (stroker->open_sub_path && line_cap == CAIRO_LINE_CAP_BUTT) {
+ j = i == 0 ? stroker->num_segments - 1 : i-1;
+ lengthen_initial = (stroker->segments[i].flags ^ stroker->segments[j].flags) & HORIZONTAL;
+ j = i == stroker->num_segments - 1 ? 0 : i+1;
+ lengthen_final = (stroker->segments[i].flags ^ stroker->segments[j].flags) & HORIZONTAL;
+ if (stroker->open_sub_path) {
if (i == 0)
- lengthen_initial = FALSE;
+ lengthen_initial = line_cap != CAIRO_LINE_CAP_BUTT;
if (i == stroker->num_segments - 1)
- lengthen_final = FALSE;
+ lengthen_final = line_cap != CAIRO_LINE_CAP_BUTT;
}
/* Perform the adjustments of the endpoints. */