[cairo-commit] 6 commits - src/cairo-bentley-ottmann.c src/cairoint.h src/cairo-path-fill.c src/cairo-path-stroke.c src/cairo-slope.c src/cairo-surface-fallback.c src/cairo-traps.c test/.gitignore test/Makefile.am test/rectilinear-fill.c test/rectilinear-fill-ref.png

Chris Wilson ickle at kemper.freedesktop.org
Fri Sep 19 09:01:00 PDT 2008


 src/cairo-bentley-ottmann.c   |   53 +++++------
 src/cairo-path-fill.c         |   16 ++-
 src/cairo-path-stroke.c       |   47 +++++----
 src/cairo-slope.c             |    6 -
 src/cairo-surface-fallback.c  |   12 --
 src/cairo-traps.c             |  201 +++++++++++++++++++-----------------------
 src/cairoint.h                |   33 ++++--
 test/.gitignore               |    1 
 test/Makefile.am              |    2 
 test/rectilinear-fill-ref.png |binary
 test/rectilinear-fill.c       |   92 +++++++++++++++++++
 11 files changed, 285 insertions(+), 178 deletions(-)

New commits:
commit a6c0ebee7aa9298af24859c37d8005eba772c4c6
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Sep 19 16:15:55 2008 +0100

    [tessellator] Only run sweep-line validator when debugging
    
    The tessellator is well-proven now. However, the sweep-line validator
    consumes around 50% of the total time required to draw the fractal
    Pythagoras tree (the leaves are sub-pixel rectangles, so lots of edges
    to sweep through). So disable the validator, but keep it available for
    debugging.

diff --git a/src/cairo-bentley-ottmann.c b/src/cairo-bentley-ottmann.c
index e89e1fd..b5c757e 100644
--- a/src/cairo-bentley-ottmann.c
+++ b/src/cairo-bentley-ottmann.c
@@ -39,6 +39,9 @@
 #include "cairo-skiplist-private.h"
 #include "cairo-freelist-private.h"
 
+#define DEBUG_VALIDATE 0
+#define DEBUG_PRINT_STATE 0
+
 typedef cairo_point_t cairo_bo_point32_t;
 
 typedef struct _cairo_bo_point128 {
@@ -941,7 +944,6 @@ _cairo_bo_sweep_line_swap (cairo_bo_sweep_line_t	*sweep_line,
     left->prev = right;
 }
 
-#define DEBUG_PRINT_STATE 0
 #if DEBUG_PRINT_STATE
 static void
 _cairo_bo_edge_print (cairo_bo_edge_t *edge)
@@ -1177,6 +1179,7 @@ _cairo_bo_traps_fini (cairo_bo_traps_t *bo_traps)
     _cairo_freelist_fini (&bo_traps->freelist);
 }
 
+#if DEBUG_VALIDATE
 static void
 _cairo_bo_sweep_line_validate (cairo_bo_sweep_line_t *sweep_line)
 {
@@ -1202,6 +1205,7 @@ _cairo_bo_sweep_line_validate (cairo_bo_sweep_line_t *sweep_line)
 	exit (1);
     }
 }
+#endif
 
 
 static cairo_status_t
@@ -1324,9 +1328,8 @@ _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_edge_t	*edges,
 #if DEBUG_PRINT_STATE
 	    print_state ("After processing start", &event_queue, &sweep_line);
 #endif
-	    _cairo_bo_sweep_line_validate (&sweep_line);
-
 	    break;
+
 	case CAIRO_BO_EVENT_TYPE_STOP:
 	    edge = event->e1;
 
@@ -1346,9 +1349,8 @@ _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_edge_t	*edges,
 #if DEBUG_PRINT_STATE
 	    print_state ("After processing stop", &event_queue, &sweep_line);
 #endif
-	    _cairo_bo_sweep_line_validate (&sweep_line);
-
 	    break;
+
 	case CAIRO_BO_EVENT_TYPE_INTERSECTION:
 	    edge1 = event->e1;
 	    edge2 = event->e2;
@@ -1382,10 +1384,11 @@ _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_edge_t	*edges,
 #if DEBUG_PRINT_STATE
 	    print_state ("After processing intersection", &event_queue, &sweep_line);
 #endif
-	    _cairo_bo_sweep_line_validate (&sweep_line);
-
 	    break;
 	}
+#if DEBUG_VALIDATE
+	_cairo_bo_sweep_line_validate (&sweep_line);
+#endif
     }
 
     *num_intersections = intersection_count;
commit 91f0b8b1eac967d4534201794c9ba7880ddfaa17
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Sep 19 13:29:01 2008 +0100

    [fill] Construct trap using rectangle directly.
    
    Avoid the overhead in sorting the edges within
    _cairo_traps_tessellate_convex_quad() by using our prior knowledge that we
    have a simple rectangle and construct the trap from the extreme points.

diff --git a/src/cairo-path-fill.c b/src/cairo-path-fill.c
index ba33114..7555798 100644
--- a/src/cairo-path-fill.c
+++ b/src/cairo-path-fill.c
@@ -215,8 +215,20 @@ _cairo_path_fixed_fill_rectangle (cairo_path_fixed_t	*path,
 				  cairo_traps_t		*traps)
 {
     if (_cairo_path_fixed_is_box (path, NULL)) {
-	return _cairo_traps_tessellate_convex_quad (traps,
-                                                    path->buf_head.base.points);
+	cairo_point_t *p = path->buf_head.base.points;
+	cairo_point_t *top_left, *bot_right;
+	int n;
+
+	top_left = &p[0];
+	bot_right = &p[0];
+	for (n = 1; n < 4; n++) {
+	    if (p[n].x <= top_left->x && p[n].y <= top_left->y)
+		top_left = &p[n];
+	    if (p[n].x >= bot_right->x && p[n].y >= bot_right->y)
+		bot_right = &p[n];
+	}
+
+	return _cairo_traps_tessellate_rectangle (traps, top_left, bot_right);
     }
 
     return CAIRO_INT_STATUS_UNSUPPORTED;
commit e749b58af827e4cc28353bcc6bc4b2ab8d47aaf6
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Sep 19 13:19:51 2008 +0100

    [test] Add rectilinear-fill
    
    Add a test-case to exercise pixel-aligned fills to verify the optimised
    rectilinear filler.

diff --git a/test/.gitignore b/test/.gitignore
index 6454dd3..0ad92da 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -168,6 +168,7 @@ svg-surface-source.svg
 pixman-rotate
 pthread-show-text
 rectangle-rounding-error
+rectilinear-fill
 rectilinear-miter-limit
 rectilinear-stroke
 reflected-stroke
diff --git a/test/Makefile.am b/test/Makefile.am
index 72aa9e0..1dcde7d 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -121,6 +121,7 @@ push-group$(EXEEXT)					\
 radial-gradient$(EXEEXT)				\
 random-intersections$(EXEEXT)				\
 rectangle-rounding-error$(EXEEXT)			\
+rectilinear-fill$(EXEEXT)				\
 rectilinear-miter-limit$(EXEEXT)			\
 rectilinear-stroke$(EXEEXT)				\
 reflected-stroke$(EXEEXT)				\
@@ -600,6 +601,7 @@ REFERENCE_IMAGES = \
 	random-intersections-quartz-ref.png \
 	rgb24-ignore-alpha-ref.png \
 	rectangle-rounding-error-ref.png	\
+	rectilinear-fill-ref.png	\
 	rectilinear-miter-limit-ref.png		\
 	rectilinear-miter-limit-ps-ref.png	\
 	rectilinear-stroke-ref.png	\
diff --git a/test/rectilinear-fill-ref.png b/test/rectilinear-fill-ref.png
new file mode 100644
index 0000000..84b5967
Binary files /dev/null and b/test/rectilinear-fill-ref.png differ
diff --git a/test/rectilinear-fill.c b/test/rectilinear-fill.c
new file mode 100644
index 0000000..14fc511
--- /dev/null
+++ b/test/rectilinear-fill.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright © 2008 Chris Wilson
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Author: Chris Wilson <chris at chris-wilson.co.uk>
+ */
+
+#include "cairo-test.h"
+
+#define SIZE 24
+
+static cairo_test_draw_function_t draw;
+
+static const cairo_test_t test = {
+    "rectilinear-fill",
+    "Test rectilinear fill operations (covering only whole pixels)",
+    SIZE, 2 * SIZE,
+    draw
+};
+
+static void
+draw_rectangles (cairo_t *cr)
+{
+    cairo_save (cr);
+
+    /* test constructing single rectangles */
+    cairo_rectangle (cr, 0, 0, SIZE/2, 2);
+    cairo_fill (cr);
+
+    cairo_rectangle (cr, 0, 5, SIZE/2, -2);
+    cairo_fill (cr);
+
+    cairo_rectangle (cr, SIZE/2, 6, -SIZE/2, 2);
+    cairo_fill (cr);
+
+    cairo_rectangle (cr, SIZE/2, 11, -SIZE/2, -2);
+    cairo_fill (cr);
+
+    /* test constructing multiple rectangles */
+    cairo_translate (cr, 0, 12);
+    cairo_rectangle (cr, 0, 0, SIZE/2, 2);
+    cairo_rectangle (cr, 0, 5, SIZE/2, -2);
+    cairo_rectangle (cr, SIZE/2, 6, -SIZE/2, 2);
+    cairo_rectangle (cr, SIZE/2, 11, -SIZE/2, -2);
+    cairo_fill (cr);
+
+    cairo_restore (cr);
+}
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+    /* Paint background white, then draw in black. */
+    cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */
+    cairo_paint (cr);
+    cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); /* black */
+
+    draw_rectangles (cr);
+
+    /* and check using cw winding */
+    cairo_translate (cr, SIZE, SIZE);
+    cairo_scale (cr, -1, 1);
+
+    draw_rectangles (cr);
+
+    return CAIRO_TEST_SUCCESS;
+}
+
+int
+main (void)
+{
+    return cairo_test (&test);
+}
commit d5cd7ee74fb64b00597880a75b2e62065fac59b3
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Sep 19 13:22:51 2008 +0100

    [stroke] Optimise rectilinear strokes.
    
    Avoid the overhead of sorting the rectangle in
    _cairo_traps_tessellate_convex_quad() by constructing the trap directly
    from the line segment. This also has secondary effects in only passing
     the non-degenerate trap to _cairo_traps_add_trap().
    
    For rectilinear Hilbert curves this makes the rectilinear stoker over 4x
    faster.

diff --git a/src/cairo-path-stroke.c b/src/cairo-path-stroke.c
index 16cc434..24d0550 100644
--- a/src/cairo-path-stroke.c
+++ b/src/cairo-path-stroke.c
@@ -1257,12 +1257,12 @@ _cairo_rectilinear_stroker_emit_segments (cairo_rectilinear_stroker_t *stroker)
     cairo_status_t status;
     cairo_line_cap_t line_cap = stroker->stroke_style->line_cap;
     cairo_fixed_t half_line_width = stroker->half_line_width;
-    cairo_bool_t lengthen_initial, shorten_final, lengthen_final;
-    cairo_point_t *a, *b;
-    cairo_point_t r[4];
     int i;
 
     for (i = 0; i < stroker->num_segments; i++) {
+	cairo_point_t *a, *b;
+	cairo_bool_t lengthen_initial, shorten_final, lengthen_final;
+
 	a = &stroker->segments[i].p1;
 	b = &stroker->segments[i].p2;
 
@@ -1315,6 +1315,14 @@ _cairo_rectilinear_stroker_emit_segments (cairo_rectilinear_stroker_t *stroker)
 		else if (lengthen_final)
 		    b->x -= half_line_width;
 	    }
+
+	    if (a->x > b->x) {
+		cairo_point_t *t;
+
+		t = a;
+		a = b;
+		b = t;
+	    }
 	} else {
 	    if (a->y < b->y) {
 		if (lengthen_initial)
@@ -1331,27 +1339,27 @@ _cairo_rectilinear_stroker_emit_segments (cairo_rectilinear_stroker_t *stroker)
 		else if (lengthen_final)
 		    b->y -= half_line_width;
 	    }
+
+	    if (a->y > b->y) {
+		cairo_point_t *t;
+
+		t = a;
+		a = b;
+		b = t;
+	    }
 	}
 
 	/* Form the rectangle by expanding by half the line width in
 	 * either perpendicular direction. */
-	r[0] = *a;
-	r[1] = *b;
-	r[2] = *b;
-	r[3] = *a;
 	if (a->y == b->y) {
-	    r[0].y -= half_line_width;
-	    r[1].y -= half_line_width;
-	    r[2].y += half_line_width;
-	    r[3].y += half_line_width;
+	    a->y -= half_line_width;
+	    b->y += half_line_width;
 	} else {
-	    r[0].x -= half_line_width;
-	    r[1].x -= half_line_width;
-	    r[2].x += half_line_width;
-	    r[3].x += half_line_width;
+	    a->x -= half_line_width;
+	    b->x += half_line_width;
 	}
 
-	status = _cairo_traps_tessellate_convex_quad (stroker->traps, r);
+	status = _cairo_traps_tessellate_rectangle (stroker->traps, a, b);
 	if (status)
 	    return status;
     }
@@ -1439,7 +1447,7 @@ _cairo_path_fixed_stroke_rectilinear (cairo_path_fixed_t	*path,
     /* This special-case rectilinear stroker only supports
      * miter-joined lines (not curves) and no dashing and a
      * translation-only matrix (though it could probably be extended
-     * to support a matrix with uniform, integer sacling).
+     * to support a matrix with uniform, integer scaling).
      *
      * It also only supports horizontal and vertical line_to
      * elements. But we don't catch that here, but instead return
diff --git a/src/cairo-traps.c b/src/cairo-traps.c
index fabfecb..1267015 100644
--- a/src/cairo-traps.c
+++ b/src/cairo-traps.c
@@ -352,6 +352,24 @@ _cairo_traps_tessellate_triangle (cairo_traps_t *traps,
 }
 
 cairo_status_t
+_cairo_traps_tessellate_rectangle (cairo_traps_t *traps,
+				   const cairo_point_t *top_left,
+				   const cairo_point_t *bottom_right)
+{
+    cairo_line_t left;
+    cairo_line_t right;
+
+     left.p1.x =  left.p2.x = top_left->x;
+     left.p1.y = right.p1.y = top_left->y;
+    right.p1.x = right.p2.x = bottom_right->x;
+     left.p2.y = right.p2.y = bottom_right->y;
+
+    _cairo_traps_add_trap (traps, top_left->y, bottom_right->y, &left, &right);
+
+    return traps->status;
+}
+
+cairo_status_t
 _cairo_traps_tessellate_convex_quad (cairo_traps_t *traps,
 				     const cairo_point_t q[4])
 {
diff --git a/src/cairoint.h b/src/cairoint.h
index 3769094..a032c12 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -2191,6 +2191,11 @@ cairo_private cairo_status_t
 _cairo_traps_tessellate_convex_quad (cairo_traps_t *traps,
 				     const cairo_point_t q[4]);
 
+cairo_private cairo_status_t
+_cairo_traps_tessellate_rectangle (cairo_traps_t *traps,
+				   const cairo_point_t *top_left,
+				   const cairo_point_t *bottom_right);
+
 cairo_private void
 _cairo_traps_add_trap (cairo_traps_t *traps,
 		       cairo_fixed_t top, cairo_fixed_t bottom,
commit 9930eefbbd4448d598faff12fc0f7127555c8c94
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Sep 19 10:54:13 2008 +0100

    Simple perf tweaks for a rectilinear Hilbert curve.
    
    Some tweaks to avoid stack copies and branches that save ~25% in
    _cairo_traps_tessellate_convex_quad().

diff --git a/src/cairo-bentley-ottmann.c b/src/cairo-bentley-ottmann.c
index 8e97f1f..e89e1fd 100644
--- a/src/cairo-bentley-ottmann.c
+++ b/src/cairo-bentley-ottmann.c
@@ -1078,35 +1078,35 @@ _cairo_bo_edge_end_trap (cairo_bo_edge_t	*left,
 
     /* Only emit trapezoids with positive height. */
     if (fixed_top < fixed_bot) {
-	cairo_point_t left_top, left_bot, right_top, right_bot;
+	cairo_line_t left_line;
+	cairo_line_t right_line;
 	cairo_fixed_t xmin = bo_traps->xmin;
 	cairo_fixed_t ymin = bo_traps->ymin;
 	fixed_top += ymin;
 	fixed_bot += ymin;
 
-	left_top.x = left->top.x + xmin;
-	left_top.y = left->top.y + ymin;
-	right_top.x = right->top.x + xmin;
-	right_top.y = right->top.y + ymin;
-	left_bot.x = left->bottom.x + xmin;
-	left_bot.y = left->bottom.y + ymin;
-	right_bot.x = right->bottom.x + xmin;
-	right_bot.y = right->bottom.y + ymin;
+	left_line.p1.x  = left->top.x + xmin;
+	left_line.p1.y  = left->top.y + ymin;
+	right_line.p1.x = right->top.x + xmin;
+	right_line.p1.y = right->top.y + ymin;
+
+	left_line.p2.x  = left->bottom.x + xmin;
+	left_line.p2.y  = left->bottom.y + ymin;
+	right_line.p2.x = right->bottom.x + xmin;
+	right_line.p2.y = right->bottom.y + ymin;
 
 	/* Avoid emitting the trapezoid if it is obviously degenerate.
 	 * TODO: need a real collinearity test here for the cases
 	 * where the trapezoid is degenerate, yet the top and bottom
 	 * coordinates aren't equal.  */
-	if (left_top.x != right_top.x ||
-	    left_top.y != right_top.y ||
-	    left_bot.x != right_bot.x ||
-	    left_bot.y != right_bot.y)
+	if (left_line.p1.x != right_line.p1.x ||
+	    left_line.p1.y != right_line.p1.y ||
+	    left_line.p2.x != right_line.p2.x ||
+	    left_line.p2.y != right_line.p2.y)
 	{
-	    _cairo_traps_add_trap_from_points (bo_traps->traps,
-					       fixed_top,
-					       fixed_bot,
-					       left_top, left_bot,
-					       right_top, right_bot);
+	    _cairo_traps_add_trap (bo_traps->traps,
+				   fixed_top, fixed_bot,
+				   &left_line, &right_line);
 
 #if DEBUG_PRINT_STATE
 	    printf ("Deferred trap: left=(%08x, %08x)-(%08x,%08x) "
diff --git a/src/cairo-slope.c b/src/cairo-slope.c
index d3f0db4..e3a070b 100644
--- a/src/cairo-slope.c
+++ b/src/cairo-slope.c
@@ -37,7 +37,9 @@
 #include "cairoint.h"
 
 void
-_cairo_slope_init (cairo_slope_t *slope, cairo_point_t *a, cairo_point_t *b)
+_cairo_slope_init (cairo_slope_t *slope,
+		   const cairo_point_t *a,
+		   const cairo_point_t *b)
 {
     slope->dx = b->x - a->x;
     slope->dy = b->y - a->y;
@@ -62,7 +64,7 @@ _cairo_slope_init (cairo_slope_t *slope, cairo_point_t *a, cairo_point_t *b)
    >  0 => a more positive than b
 */
 int
-_cairo_slope_compare (cairo_slope_t *a, cairo_slope_t *b)
+_cairo_slope_compare (const cairo_slope_t *a, const cairo_slope_t *b)
 {
     cairo_fixed_48_16_t diff;
 
diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c
index 427554b..c7c7b11 100644
--- a/src/cairo-surface-fallback.c
+++ b/src/cairo-surface-fallback.c
@@ -702,9 +702,7 @@ _cairo_surface_fallback_paint (cairo_surface_t	*surface,
     box.p2.x = _cairo_fixed_from_int (extents.x + extents.width);
     box.p2.y = _cairo_fixed_from_int (extents.y + extents.height);
 
-    status = _cairo_traps_init_box (&traps, &box);
-    if (status)
-	return status;
+    _cairo_traps_init_box (&traps, &box);
 
     status = _clip_and_composite_trapezoids (source,
 				             op,
@@ -830,7 +828,6 @@ _cairo_surface_fallback_stroke (cairo_surface_t		*surface,
     box.p2.y = _cairo_fixed_from_int (extents.y + extents.height);
 
     _cairo_traps_init (&traps);
-
     _cairo_traps_limit (&traps, &box);
 
     status = _cairo_path_fixed_stroke_to_traps (path,
@@ -838,10 +835,8 @@ _cairo_surface_fallback_stroke (cairo_surface_t		*surface,
 						ctm, ctm_inverse,
 						tolerance,
 						&traps);
-    if (status) {
-	_cairo_traps_fini (&traps);
-	return status;
-    }
+    if (status)
+	goto FAIL;
 
     status = _clip_and_composite_trapezoids (source,
 				             op,
@@ -850,6 +845,7 @@ _cairo_surface_fallback_stroke (cairo_surface_t		*surface,
 					     surface->clip,
 					     antialias);
 
+FAIL:
     _cairo_traps_fini (&traps);
 
     return status;
diff --git a/src/cairo-traps.c b/src/cairo-traps.c
index cdfdadd..fabfecb 100644
--- a/src/cairo-traps.c
+++ b/src/cairo-traps.c
@@ -41,13 +41,6 @@
 
 /* private functions */
 
-static cairo_status_t
-_cairo_traps_grow (cairo_traps_t *traps);
-
-static void
-_cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom,
-		       cairo_line_t *left, cairo_line_t *right);
-
 static int
 _compare_point_fixed_by_y (const void *av, const void *bv);
 
@@ -94,12 +87,8 @@ _cairo_traps_clear (cairo_traps_t *traps)
 void
 _cairo_traps_fini (cairo_traps_t *traps)
 {
-    if (traps->traps && traps->traps != traps->traps_embedded)
+    if (traps->traps != traps->traps_embedded)
 	free (traps->traps);
-
-    traps->traps = NULL;
-    traps->traps_size = 0;
-    traps->num_traps = 0;
 }
 
 /**
@@ -111,9 +100,9 @@ _cairo_traps_fini (cairo_traps_t *traps)
  * Initializes a #cairo_traps_t to contain a single rectangular
  * trapezoid.
  **/
-cairo_status_t
+void
 _cairo_traps_init_box (cairo_traps_t *traps,
-		       cairo_box_t   *box)
+		       const cairo_box_t   *box)
 {
     _cairo_traps_init (traps);
 
@@ -131,25 +120,41 @@ _cairo_traps_init_box (cairo_traps_t *traps,
     traps->traps[0].right.p2 = box->p2;
 
     traps->extents = *box;
-
-    return traps->status;
 }
 
-cairo_status_t
-_cairo_traps_status (cairo_traps_t *traps)
+/* make room for at least one more trap */
+static cairo_bool_t
+_cairo_traps_grow (cairo_traps_t *traps)
 {
-    return traps->status;
+    cairo_trapezoid_t *new_traps;
+    int new_size = 2 * MAX (traps->traps_size, 16);
+
+    if (traps->traps == traps->traps_embedded) {
+	new_traps = _cairo_malloc_ab (new_size, sizeof (cairo_trapezoid_t));
+	if (new_traps != NULL)
+	    memcpy (new_traps, traps->traps, sizeof (traps->traps_embedded));
+    } else {
+	new_traps = _cairo_realloc_ab (traps->traps,
+	                               new_size, sizeof (cairo_trapezoid_t));
+    }
+
+    if (new_traps == NULL) {
+	traps->status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	return FALSE;
+    }
+
+    traps->traps = new_traps;
+    traps->traps_size = new_size;
+    return TRUE;
 }
 
-static void
-_cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom,
+void
+_cairo_traps_add_trap (cairo_traps_t *traps,
+		       cairo_fixed_t top, cairo_fixed_t bottom,
 		       cairo_line_t *left, cairo_line_t *right)
 {
     cairo_trapezoid_t *trap;
 
-    if (traps->status)
-	return;
-
     /* Note: With the goofy trapezoid specification, (where an
      * arbitrary two points on the lines can specified for the left
      * and right edges), these limit checks would not work in
@@ -209,9 +214,8 @@ _cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bo
 	return;
     }
 
-    if (traps->num_traps >= traps->traps_size) {
-	traps->status = _cairo_traps_grow (traps);
-	if (traps->status)
+    if (traps->num_traps == traps->traps_size) {
+	if (! _cairo_traps_grow (traps))
 	    return;
     }
 
@@ -246,51 +250,6 @@ _cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bo
     traps->num_traps++;
 }
 
-void
-_cairo_traps_add_trap_from_points (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom,
-				   cairo_point_t left_p1, cairo_point_t left_p2,
-				   cairo_point_t right_p1, cairo_point_t right_p2)
-{
-    cairo_line_t left;
-    cairo_line_t right;
-
-    if (traps->status)
-	return;
-
-    left.p1 = left_p1;
-    left.p2 = left_p2;
-
-    right.p1 = right_p1;
-    right.p2 = right_p2;
-
-    _cairo_traps_add_trap (traps, top, bottom, &left, &right);
-}
-
-/* make room for at least one more trap */
-static cairo_status_t
-_cairo_traps_grow (cairo_traps_t *traps)
-{
-    cairo_trapezoid_t *new_traps;
-    int new_size = 2 * MAX (traps->traps_size, 16);
-
-    if (traps->traps == traps->traps_embedded) {
-	new_traps = _cairo_malloc_ab (new_size, sizeof (cairo_trapezoid_t));
-	if (new_traps)
-	    memcpy (new_traps, traps->traps, sizeof (traps->traps_embedded));
-    } else {
-	new_traps = _cairo_realloc_ab (traps->traps,
-	                               new_size, sizeof (cairo_trapezoid_t));
-    }
-
-    if (new_traps == NULL)
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-    traps->traps = new_traps;
-    traps->traps_size = new_size;
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
 static int
 _compare_point_fixed_by_y (const void *av, const void *bv)
 {
@@ -379,7 +338,8 @@ _cairo_trapezoid_array_translate_and_scale (cairo_trapezoid_t *offset_traps,
  * quadrilateral. We would not benefit from having any distinct
  * implementation of triangle vs. quadrilateral tessellation here. */
 cairo_status_t
-_cairo_traps_tessellate_triangle (cairo_traps_t *traps, cairo_point_t t[3])
+_cairo_traps_tessellate_triangle (cairo_traps_t *traps,
+				  const cairo_point_t t[3])
 {
     cairo_point_t quad[4];
 
@@ -392,12 +352,15 @@ _cairo_traps_tessellate_triangle (cairo_traps_t *traps, cairo_point_t t[3])
 }
 
 cairo_status_t
-_cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4])
+_cairo_traps_tessellate_convex_quad (cairo_traps_t *traps,
+				     const cairo_point_t q[4])
 {
     int a, b, c, d;
     int i;
     cairo_slope_t ab, ad;
     cairo_bool_t b_left_of_d;
+    cairo_line_t left;
+    cairo_line_t right;
 
     /* Choose a as a point with minimal y */
     a = 0;
@@ -462,15 +425,13 @@ _cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4])
 	     *  | /      \|     \ \  c.y d.y  cd   ad
 	     *  d         d       d
 	     */
-	    _cairo_traps_add_trap_from_points (traps,
-					       q[a].y, q[b].y,
-					       q[a], q[b], q[a], q[d]);
-	    _cairo_traps_add_trap_from_points (traps,
-					       q[b].y, q[c].y,
-					       q[b], q[c], q[a], q[d]);
-	    _cairo_traps_add_trap_from_points (traps,
-					       q[c].y, q[d].y,
-					       q[c], q[d], q[a], q[d]);
+	    left.p1  = q[a]; left.p2  = q[b];
+	    right.p1 = q[a]; right.p2 = q[d];
+	    _cairo_traps_add_trap (traps, q[a].y, q[b].y, &left, &right);
+	    left.p1  = q[b]; left.p2  = q[c];
+	    _cairo_traps_add_trap (traps, q[b].y, q[c].y, &left, &right);
+	    left.p1  = q[c]; left.p2  = q[d];
+	    _cairo_traps_add_trap (traps, q[c].y, q[d].y, &left, &right);
 	} else {
 	    /* Y-sort is abcd and b is right of d, (slope(ab) <= slope (ad))
 	     *
@@ -482,15 +443,13 @@ _cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4])
 	     *  / /     |/      \ | c.y d.y  ad  cd
 	     *  d       d         d
 	     */
-	    _cairo_traps_add_trap_from_points (traps,
-					       q[a].y, q[b].y,
-					       q[a], q[d], q[a], q[b]);
-	    _cairo_traps_add_trap_from_points (traps,
-					       q[b].y, q[c].y,
-					       q[a], q[d], q[b], q[c]);
-	    _cairo_traps_add_trap_from_points (traps,
-					       q[c].y, q[d].y,
-					       q[a], q[d], q[c], q[d]);
+	    left.p1  = q[a]; left.p2  = q[d];
+	    right.p1 = q[a]; right.p2 = q[b];
+	    _cairo_traps_add_trap (traps, q[a].y, q[b].y, &left, &right);
+	    right.p1 = q[b]; right.p2 = q[c];
+	    _cairo_traps_add_trap (traps, q[b].y, q[c].y, &left, &right);
+	    right.p1 = q[c]; right.p2 = q[d];
+	    _cairo_traps_add_trap (traps, q[c].y, q[d].y, &left, &right);
 	}
     } else {
 	if (b_left_of_d) {
@@ -504,15 +463,13 @@ _cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4])
 	     *  //         \ /     \|  d.y c.y  bc  dc
 	     *  c           c       c
 	     */
-	    _cairo_traps_add_trap_from_points (traps,
-					       q[a].y, q[b].y,
-					       q[a], q[b], q[a], q[d]);
-	    _cairo_traps_add_trap_from_points (traps,
-					       q[b].y, q[d].y,
-					       q[b], q[c], q[a], q[d]);
-	    _cairo_traps_add_trap_from_points (traps,
-					       q[d].y, q[c].y,
-					       q[b], q[c], q[d], q[c]);
+	    left.p1  = q[a]; left.p2  = q[b];
+	    right.p1 = q[a]; right.p2 = q[d];
+	    _cairo_traps_add_trap (traps, q[a].y, q[b].y, &left, &right);
+	    left.p1  = q[b]; left.p2  = q[c];
+	    _cairo_traps_add_trap (traps, q[b].y, q[d].y, &left, &right);
+	    right.p1 = q[d]; right.p2 = q[c];
+	    _cairo_traps_add_trap (traps, q[d].y, q[c].y, &left, &right);
 	} else {
 	    /* Y-sort is abdc and b is right of d, (slope (ab) <= slope (ad))
 	     *
@@ -524,15 +481,13 @@ _cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4])
 	     *  |/     \ /         \\  d.y c.y  dc  bc
 	     *  c       c	   c
 	     */
-	    _cairo_traps_add_trap_from_points (traps,
-					       q[a].y, q[b].y,
-					       q[a], q[d], q[a], q[b]);
-	    _cairo_traps_add_trap_from_points (traps,
-					       q[b].y, q[d].y,
-					       q[a], q[d], q[b], q[c]);
-	    _cairo_traps_add_trap_from_points (traps,
-					       q[d].y, q[c].y,
-					       q[d], q[c], q[b], q[c]);
+	    left.p1  = q[a]; left.p2  = q[d];
+	    right.p1 = q[a]; right.p2 = q[b];
+	    _cairo_traps_add_trap (traps, q[a].y, q[b].y, &left, &right);
+	    right.p1 = q[b]; right.p2 = q[c];
+	    _cairo_traps_add_trap (traps, q[b].y, q[d].y, &left, &right);
+	    left.p1  = q[d]; left.p2  = q[c];
+	    _cairo_traps_add_trap (traps, q[d].y, q[c].y, &left, &right);
 	}
     }
 
diff --git a/src/cairoint.h b/src/cairoint.h
index 80fde84..3769094 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -2168,9 +2168,9 @@ cairo_private cairo_bool_t
 _cairo_traps_get_limit (cairo_traps_t *traps,
                         cairo_box_t   *limits);
 
-cairo_private cairo_status_t
+cairo_private void
 _cairo_traps_init_box (cairo_traps_t *traps,
-		       cairo_box_t   *box);
+		       const cairo_box_t   *box);
 
 cairo_private void
 _cairo_traps_clear (cairo_traps_t *traps);
@@ -2178,22 +2178,23 @@ _cairo_traps_clear (cairo_traps_t *traps);
 cairo_private void
 _cairo_traps_fini (cairo_traps_t *traps);
 
-cairo_private cairo_status_t
-_cairo_traps_status (cairo_traps_t *traps);
+#define _cairo_traps_status(T) (T)->status
 
 cairo_private void
 _cairo_traps_translate (cairo_traps_t *traps, int x, int y);
 
 cairo_private cairo_status_t
-_cairo_traps_tessellate_triangle (cairo_traps_t *traps, cairo_point_t t[3]);
+_cairo_traps_tessellate_triangle (cairo_traps_t *traps,
+				  const cairo_point_t t[3]);
 
 cairo_private cairo_status_t
-_cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4]);
+_cairo_traps_tessellate_convex_quad (cairo_traps_t *traps,
+				     const cairo_point_t q[4]);
 
 cairo_private void
-_cairo_traps_add_trap_from_points (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom,
-				   cairo_point_t left_p1, cairo_point_t left_p2,
-				   cairo_point_t right_p1, cairo_point_t right_p2);
+_cairo_traps_add_trap (cairo_traps_t *traps,
+		       cairo_fixed_t top, cairo_fixed_t bottom,
+		       cairo_line_t *left, cairo_line_t *right);
 
 cairo_private cairo_status_t
 _cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t         *traps,
@@ -2225,10 +2226,12 @@ _cairo_trapezoid_array_translate_and_scale (cairo_trapezoid_t *offset_traps,
 
 /* cairo-slope.c */
 cairo_private void
-_cairo_slope_init (cairo_slope_t *slope, cairo_point_t *a, cairo_point_t *b);
+_cairo_slope_init (cairo_slope_t *slope,
+		   const cairo_point_t *a,
+		   const cairo_point_t *b);
 
 cairo_private int
-_cairo_slope_compare (cairo_slope_t *a, cairo_slope_t *b);
+_cairo_slope_compare (const cairo_slope_t *a, const cairo_slope_t *b);
 
 /* cairo-pattern.c */
 
commit 27ee8dd9c64ac0fd36ce7b58729ee732e3396ee1
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Sep 19 11:48:57 2008 +0100

    [trap] Fixup a double _cairo_traps_fini().
    
    The rectilinear stroke finalized the cairo_traps_t passed to it - which
    was then subsequently used without re-initialized. So instead of
    finalizing the structure, just remove any traps that we may have added
    (leaving the limits and memory intact).

diff --git a/src/cairo-path-stroke.c b/src/cairo-path-stroke.c
index 3663ba7..16cc434 100644
--- a/src/cairo-path-stroke.c
+++ b/src/cairo-path-stroke.c
@@ -1334,7 +1334,7 @@ _cairo_rectilinear_stroker_emit_segments (cairo_rectilinear_stroker_t *stroker)
 	}
 
 	/* Form the rectangle by expanding by half the line width in
-	 * either perdendicular direction. */
+	 * either perpendicular direction. */
 	r[0] = *a;
 	r[1] = *b;
 	r[2] = *b;
@@ -1484,11 +1484,10 @@ _cairo_path_fixed_stroke_rectilinear (cairo_path_fixed_t	*path,
     status = _cairo_rectilinear_stroker_emit_segments (&rectilinear_stroker);
 
 BAIL:
-
     _cairo_rectilinear_stroker_fini (&rectilinear_stroker);
 
     if (status)
-	_cairo_traps_fini (traps);
+	_cairo_traps_clear (traps);
 
     return status;
 }
diff --git a/src/cairo-traps.c b/src/cairo-traps.c
index fcb0208..cdfdadd 100644
--- a/src/cairo-traps.c
+++ b/src/cairo-traps.c
@@ -84,6 +84,14 @@ _cairo_traps_get_limit (cairo_traps_t *traps,
 }
 
 void
+_cairo_traps_clear (cairo_traps_t *traps)
+{
+    traps->status = CAIRO_STATUS_SUCCESS;
+
+    traps->num_traps = 0;
+}
+
+void
 _cairo_traps_fini (cairo_traps_t *traps)
 {
     if (traps->traps && traps->traps != traps->traps_embedded)
diff --git a/src/cairoint.h b/src/cairoint.h
index 94d8904..80fde84 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -2173,6 +2173,9 @@ _cairo_traps_init_box (cairo_traps_t *traps,
 		       cairo_box_t   *box);
 
 cairo_private void
+_cairo_traps_clear (cairo_traps_t *traps);
+
+cairo_private void
 _cairo_traps_fini (cairo_traps_t *traps);
 
 cairo_private cairo_status_t


More information about the cairo-commit mailing list