[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
- Previous message: [cairo-commit] rcairo/test test_constants.rb, 1.1, 1.2 test_font_face.rb, 1.4, 1.5 test_font_options.rb, 1.1, 1.2 test_scaled_font.rb, 1.2, 1.3 test_text_to_glyphs_data.rb, 1.1, 1.2
- Next message: [cairo-commit] 4 commits - build/aclocal.cairo.m4 build/configure.ac.features build/configure.ac.system src/cairo-atomic-private.h src/cairo-compiler-private.h src/cairo-image-surface.c src/cairo-mutex-impl-private.h src/cairo-mutex-private.h src/cairo-os2-private.h src/cairo-reference-count-private.h src/cairo-region-private.h src/cairo-types-private.h src/cairo-wideint-type-private.h src/check-cairoint.sh src/check-includes.sh src/Makefile.am
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
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
- Previous message: [cairo-commit] rcairo/test test_constants.rb, 1.1, 1.2 test_font_face.rb, 1.4, 1.5 test_font_options.rb, 1.1, 1.2 test_scaled_font.rb, 1.2, 1.3 test_text_to_glyphs_data.rb, 1.1, 1.2
- Next message: [cairo-commit] 4 commits - build/aclocal.cairo.m4 build/configure.ac.features build/configure.ac.system src/cairo-atomic-private.h src/cairo-compiler-private.h src/cairo-image-surface.c src/cairo-mutex-impl-private.h src/cairo-mutex-private.h src/cairo-os2-private.h src/cairo-reference-count-private.h src/cairo-region-private.h src/cairo-types-private.h src/cairo-wideint-type-private.h src/check-cairoint.sh src/check-includes.sh src/Makefile.am
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the cairo-commit
mailing list