[cairo-commit] src/cairo-path-stroke-boxes.c

Chris Wilson ickle at kemper.freedesktop.org
Mon Aug 20 06:26:53 PDT 2012


 src/cairo-path-stroke-boxes.c |   18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)

New commits:
commit ee7f5607192a3341df45199b1c7c8996f2b7347d
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Aug 20 14:21:23 2012 +0100

    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 at chris-wilson.co.uk>

diff --git a/src/cairo-path-stroke-boxes.c b/src/cairo-path-stroke-boxes.c
index 50c53f3..7f25bf7 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. */


More information about the cairo-commit mailing list