mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-01-06 10:50:17 +01:00
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.
This commit is contained in:
parent
216a2e24c7
commit
5d57aeaa23
4 changed files with 77 additions and 19 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
||||
if (unlikely (rects == NULL))
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
}
|
||||
|
||||
rect_count = 0;
|
||||
for (i = 0; i < traps->num_traps; i++) {
|
||||
cairo_rectangle_int_t rect;
|
||||
|
||||
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 */
|
||||
|
|
|
|||
|
|
@ -2373,6 +2373,10 @@ cairo_region_create (void);
|
|||
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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue