mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-04 21:08:10 +02:00
[xlib] Allocate bounded region on stack.
Eliminate the extremely short-lived and oft unnecessary heap allocation of the region by first checking to see whether the clip exceeds the surface bounds and only then intersect the clip with a local stack-allocated region.
This commit is contained in:
parent
75b06b8bdb
commit
ad83765a14
3 changed files with 71 additions and 20 deletions
|
|
@ -76,6 +76,29 @@ _cairo_region_set_error (cairo_region_t *region,
|
|||
return _cairo_error (status);
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_region_init (cairo_region_t *region)
|
||||
{
|
||||
region->status = CAIRO_STATUS_SUCCESS;
|
||||
pixman_region32_init (®ion->rgn);
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_region_init_rectangle (cairo_region_t *region,
|
||||
const cairo_rectangle_int_t *rectangle)
|
||||
{
|
||||
region->status = CAIRO_STATUS_SUCCESS;
|
||||
pixman_region32_init_rect (®ion->rgn,
|
||||
rectangle->x, rectangle->y,
|
||||
rectangle->width, rectangle->height);
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_region_fini (cairo_region_t *region)
|
||||
{
|
||||
pixman_region32_fini (®ion->rgn);
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_region_create:
|
||||
*
|
||||
|
|
|
|||
|
|
@ -2269,6 +2269,32 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t op,
|
|||
return status;
|
||||
}
|
||||
|
||||
static cairo_region_t *
|
||||
_surface_maybe_clip_region (cairo_xlib_surface_t *surface,
|
||||
cairo_region_t *clip,
|
||||
cairo_region_t *bounded)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
|
||||
cairo_region_get_extents (clip, &rect);
|
||||
if (rect.x >= 0 &&
|
||||
rect.y >= 0 &&
|
||||
rect.x + rect.width <= surface->width &&
|
||||
rect.y + rect.height <= surface->height)
|
||||
{
|
||||
return clip;
|
||||
}
|
||||
|
||||
rect.x = rect.y = 0;
|
||||
rect.width = surface->width;
|
||||
rect.height = surface->height;
|
||||
_cairo_region_init_rectangle (bounded, &rect);
|
||||
|
||||
bounded->status = cairo_region_intersect (bounded, clip);
|
||||
|
||||
return bounded;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_xlib_surface_set_clip_region (void *abstract_surface,
|
||||
cairo_region_t *region)
|
||||
|
|
@ -2288,33 +2314,24 @@ _cairo_xlib_surface_set_clip_region (void *abstract_surface,
|
|||
surface->num_clip_rects = 0;
|
||||
|
||||
if (region != NULL) {
|
||||
cairo_status_t status;
|
||||
XRectangle *rects = NULL;
|
||||
int n_rects, i;
|
||||
cairo_rectangle_int_t rect;
|
||||
cairo_region_t *bounded;
|
||||
|
||||
rect.x = rect.y = 0;
|
||||
rect.width = surface->width;
|
||||
rect.height = surface->height;
|
||||
cairo_region_t bounded;
|
||||
|
||||
/* Intersect the region with the bounds of the surface. This
|
||||
* is necessary so we don't wrap around when we convert cairo's
|
||||
* 32 bit region into 16 bit rectangles.
|
||||
*/
|
||||
bounded = cairo_region_create_rectangle (&rect);
|
||||
status = cairo_region_intersect (bounded, region);
|
||||
if (unlikely (status)) {
|
||||
cairo_region_destroy (bounded);
|
||||
return status;
|
||||
}
|
||||
|
||||
n_rects = cairo_region_num_rectangles (bounded);
|
||||
region = _surface_maybe_clip_region (surface, region, &bounded);
|
||||
if (unlikely (region->status))
|
||||
return region->status;
|
||||
|
||||
n_rects = cairo_region_num_rectangles (region);
|
||||
if (n_rects > ARRAY_LENGTH (surface->embedded_clip_rects)) {
|
||||
rects = _cairo_malloc_ab (n_rects, sizeof (XRectangle));
|
||||
if (unlikely (rects == NULL)) {
|
||||
cairo_region_destroy (bounded);
|
||||
if (unlikely (region == &bounded))
|
||||
_cairo_region_fini (&bounded);
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
}
|
||||
} else {
|
||||
|
|
@ -2323,16 +2340,17 @@ _cairo_xlib_surface_set_clip_region (void *abstract_surface,
|
|||
|
||||
for (i = 0; i < n_rects; i++) {
|
||||
cairo_rectangle_int_t rect;
|
||||
|
||||
cairo_region_get_rectangle (bounded, i, &rect);
|
||||
|
||||
cairo_region_get_rectangle (region, i, &rect);
|
||||
|
||||
rects[i].x = rect.x;
|
||||
rects[i].y = rect.y;
|
||||
rects[i].width = rect.width;
|
||||
rects[i].height = rect.height;
|
||||
}
|
||||
|
||||
cairo_region_destroy (bounded);
|
||||
|
||||
if (unlikely (region == &bounded))
|
||||
_cairo_region_fini (&bounded);
|
||||
|
||||
surface->have_clip_rects = TRUE;
|
||||
surface->clip_rects = rects;
|
||||
|
|
|
|||
|
|
@ -2534,6 +2534,16 @@ struct _cairo_region {
|
|||
pixman_region32_t rgn;
|
||||
};
|
||||
|
||||
cairo_private void
|
||||
_cairo_region_init (cairo_region_t *region);
|
||||
|
||||
cairo_private void
|
||||
_cairo_region_init_rectangle (cairo_region_t *region,
|
||||
const cairo_rectangle_int_t *rectangle);
|
||||
|
||||
cairo_private void
|
||||
_cairo_region_fini (cairo_region_t *region);
|
||||
|
||||
/* cairo-unicode.c */
|
||||
|
||||
cairo_private int
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue