[cairo-commit] src/cairo.h src/cairoint.h src/cairo-region.c src/cairo-traps.c
Søren Sandmann Pedersen
sandmann at kemper.freedesktop.org
Mon Jun 15 02:47:55 PDT 2009
src/cairo-region.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
src/cairo-traps.c | 47 ++++++++++++++++++++++++++++-------------------
src/cairo.h | 4 ++++
src/cairoint.h | 1 +
4 files changed, 77 insertions(+), 19 deletions(-)
New commits:
commit 5d57aeaa23566739ba01a0fac1c3b90ce27b28cd
Author: Søren Sandmann Pedersen <sandmann at redhat.com>
Date: Tue May 26 17:53:37 2009 -0400
Reinstate cairo_region_create_rectangles()
cairo_region_union_rectangle() is linear in the number of rectangles
in the region. There is no way to make it significantly faster without
losing the ability to return errors synchronously, so a
cairo_region_create_rectangles() is needed to avoid a large
performance regression.
diff --git a/src/cairo-region.c b/src/cairo-region.c
index c355b4a..aeb2ef2 100644
--- a/src/cairo-region.c
+++ b/src/cairo-region.c
@@ -134,6 +134,50 @@ cairo_region_create (void)
}
slim_hidden_def (cairo_region_create);
+cairo_region_t *
+cairo_region_create_rectangles (cairo_rectangle_int_t *rects,
+ int count)
+{
+ pixman_box32_t stack_pboxes[CAIRO_STACK_ARRAY_LENGTH (pixman_box32_t)];
+ pixman_box32_t *pboxes = stack_pboxes;
+ cairo_region_t *region;
+ int i;
+
+ region = _cairo_malloc (sizeof (cairo_region_t));
+
+ if (!region)
+ return (cairo_region_t *)&_cairo_region_nil;
+
+ region->status = CAIRO_STATUS_SUCCESS;
+
+ if (count > ARRAY_LENGTH (stack_pboxes)) {
+ pboxes = _cairo_malloc_ab (count, sizeof (pixman_box32_t));
+
+ if (unlikely (pboxes == NULL)) {
+ free (region);
+ return (cairo_region_t *)&_cairo_region_nil;
+ }
+ }
+
+ for (i = 0; i < count; i++) {
+ pboxes[i].x1 = rects[i].x;
+ pboxes[i].y1 = rects[i].y;
+ pboxes[i].x2 = rects[i].x + rects[i].width;
+ pboxes[i].y2 = rects[i].y + rects[i].height;
+ }
+
+ if (! pixman_region32_init_rects (®ion->rgn, pboxes, count)) {
+ free (region);
+
+ region = (cairo_region_t *)&_cairo_region_nil;
+ }
+
+ if (pboxes != stack_pboxes)
+ free (pboxes);
+
+ return region;
+}
+
/**
* cairo_region_create_rectangle:
* @rectangle: a #cairo_rectangle_int_t
diff --git a/src/cairo-traps.c b/src/cairo-traps.c
index 092bd9d..d8464cc 100644
--- a/src/cairo-traps.c
+++ b/src/cairo-traps.c
@@ -619,9 +619,10 @@ cairo_int_status_t
_cairo_traps_extract_region (const cairo_traps_t *traps,
cairo_region_t **region)
{
+ cairo_rectangle_int_t stack_rects[CAIRO_STACK_ARRAY_LENGTH (cairo_rectangle_int_t)];
+ cairo_rectangle_int_t *rects = stack_rects;
cairo_int_status_t status;
- cairo_region_t *r;
- int i;
+ int i, rect_count;
for (i = 0; i < traps->num_traps; i++) {
if (traps->traps[i].left.p1.x != traps->traps[i].left.p2.x ||
@@ -635,13 +636,15 @@ _cairo_traps_extract_region (const cairo_traps_t *traps,
}
}
- r = cairo_region_create ();
- if (unlikely (r->status))
- return r->status;
+ if (traps->num_traps > ARRAY_LENGTH (stack_rects)) {
+ rects = _cairo_malloc_ab (traps->num_traps, sizeof (cairo_rectangle_int_t));
- for (i = 0; i < traps->num_traps; i++) {
- cairo_rectangle_int_t rect;
+ if (unlikely (rects == NULL))
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ }
+ rect_count = 0;
+ for (i = 0; i < traps->num_traps; i++) {
int x1 = _cairo_fixed_integer_part (traps->traps[i].left.p1.x);
int y1 = _cairo_fixed_integer_part (traps->traps[i].top);
int x2 = _cairo_fixed_integer_part (traps->traps[i].right.p1.x);
@@ -652,21 +655,27 @@ _cairo_traps_extract_region (const cairo_traps_t *traps,
*/
if (x1 == x2 || y1 == y2)
continue;
+
+ rects[rect_count].x = x1;
+ rects[rect_count].y = y1;
+ rects[rect_count].width = x2 - x1;
+ rects[rect_count].height = y2 - y1;
- rect.x = x1;
- rect.y = y1;
- rect.width = x2 - x1;
- rect.height = y2 - y1;
-
- status = cairo_region_union_rectangle (r, &rect);
- if (unlikely (status)) {
- cairo_region_destroy (r);
- return status;
- }
+ rect_count++;
}
+
+ *region = cairo_region_create_rectangles (rects, rect_count);
+ status = cairo_region_status (*region);
- *region = r;
- return CAIRO_STATUS_SUCCESS;
+ if (rects != stack_rects)
+ free (rects);
+
+ if (unlikely (status)) {
+ cairo_region_destroy (*region);
+ *region = NULL;
+ }
+
+ return status;
}
/* moves trap points such that they become the actual corners of the trapezoid */
diff --git a/src/cairo.h b/src/cairo.h
index 2fef37c..e21cc8a 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -2374,6 +2374,10 @@ cairo_public cairo_region_t *
cairo_region_create_rectangle (const cairo_rectangle_int_t *rectangle);
cairo_public cairo_region_t *
+cairo_region_create_rectangles (cairo_rectangle_int_t *rects,
+ int count);
+
+cairo_public cairo_region_t *
cairo_region_copy (cairo_region_t *original);
cairo_public void
diff --git a/src/cairoint.h b/src/cairoint.h
index 9021ebf..0bb4d02 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -2742,6 +2742,7 @@ slim_hidden_proto (cairo_user_to_device_distance);
slim_hidden_proto (cairo_version_string);
slim_hidden_proto (cairo_region_create);
slim_hidden_proto (cairo_region_create_rectangle);
+slim_hidden_proto (cairo_region_create_rectangles);
slim_hidden_proto (cairo_region_copy);
slim_hidden_proto (cairo_region_destroy);
slim_hidden_proto (cairo_region_status);
More information about the cairo-commit
mailing list