Avoid malloc in _cairo_region_create_from_rectangle

This commit is contained in:
Mathias Hasselmann 2007-03-14 00:28:49 +01:00 committed by Behdad Esfahbod
parent efc9775149
commit 241482b550
5 changed files with 186 additions and 171 deletions

View file

@ -181,26 +181,24 @@ _cairo_clip_intersect_to_rectangle (cairo_clip_t *clip,
}
if (clip->has_region) {
pixman_region16_t *intersection;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
pixman_region_status_t pixman_status;
pixman_region16_t intersection;
intersection = _cairo_region_create_from_rectangle (rectangle);
if (intersection == NULL)
if (_cairo_region_init_from_rectangle (&intersection, rectangle))
return CAIRO_STATUS_NO_MEMORY;
pixman_status = pixman_region_intersect (intersection,
&clip->region,
intersection);
if (pixman_status == PIXMAN_REGION_STATUS_SUCCESS)
_cairo_region_extents_rectangle (intersection, rectangle);
else
if (PIXMAN_REGION_STATUS_SUCCESS !=
pixman_region_intersect (&intersection, &clip->region,
&intersection)) {
status = CAIRO_STATUS_NO_MEMORY;
} else {
_cairo_region_extents_rectangle (&intersection, rectangle);
}
pixman_region_destroy (intersection);
pixman_region_uninit (&intersection);
if (status)
return status;
if (status)
return status;
}
if (clip->surface)
@ -224,24 +222,20 @@ _cairo_clip_intersect_to_region (cairo_clip_t *clip,
pixman_region_intersect (region, &clip->region, region);
if (clip->surface) {
pixman_region16_t *clip_rect;
pixman_region_status_t pixman_status;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
pixman_region16_t clip_rect;
clip_rect = _cairo_region_create_from_rectangle (&clip->surface_rect);
if (clip_rect == NULL)
if (_cairo_region_init_from_rectangle (&clip_rect, &clip->surface_rect))
return CAIRO_STATUS_NO_MEMORY;
pixman_status = pixman_region_intersect (region,
clip_rect,
region);
if (pixman_status != PIXMAN_REGION_STATUS_SUCCESS)
if (PIXMAN_REGION_STATUS_SUCCESS !=
pixman_region_intersect (region, &clip_rect, region))
status = CAIRO_STATUS_NO_MEMORY;
pixman_region_destroy (clip_rect);
pixman_region_uninit (&clip_rect);
if (status)
return status;
if (status)
return status;
}
return CAIRO_STATUS_SUCCESS;

View file

@ -36,30 +36,28 @@
#include "cairoint.h"
/**
* _cairo_region_create_from_rectangle:
* _cairo_region_init_from_rectangle:
* @region: a #pixman_region16_t
* @rect: a #cairo_rectangle_int16_t
*
* Creates a region with extents initialized from the given
* rectangle.
* Initializes a region with extents from the given rectangle.
*
* Return value: a newly created #pixman_region16_t or %NULL if
* memory couldn't a allocated.
* Return value: #CAIRO_STATUS_SUCCESS on success, or
* #CAIRO_STATUS_NO_MEMORY when pixman fails to initialize
* the region.
**/
pixman_region16_t *
_cairo_region_create_from_rectangle (cairo_rectangle_int16_t *rect)
cairo_status_t
_cairo_region_init_from_rectangle (pixman_region16_t *region,
cairo_rectangle_int16_t *rect)
{
/* We can't use pixman_region_create_simple(), because it doesn't
* have an error return
*/
pixman_region16_t *region = pixman_region_create ();
if (pixman_region_union_rect (region, region,
rect->x, rect->y,
rect->width, rect->height) != PIXMAN_REGION_STATUS_SUCCESS) {
pixman_region_destroy (region);
return NULL;
}
pixman_region_init (region, NULL);
return region;
if (PIXMAN_REGION_STATUS_SUCCESS == pixman_region_union_rect (
region, region, rect->x, rect->y, rect->width, rect->height))
return CAIRO_STATUS_SUCCESS;
pixman_region_uninit (region);
return CAIRO_STATUS_NO_MEMORY;
}
/**

View file

@ -513,145 +513,157 @@ _clip_and_composite_trapezoids (cairo_pattern_t *src,
cairo_antialias_t antialias)
{
cairo_status_t status;
pixman_region16_t *trap_region = NULL;
pixman_region16_t *clear_region = NULL;
pixman_region16_t trap_region;
pixman_region16_t clear_region;
cairo_bool_t has_trap_region = FALSE;
cairo_bool_t has_clear_region = FALSE;
cairo_rectangle_int16_t extents;
cairo_composite_traps_info_t traps_info;
if (traps->num_traps == 0)
return CAIRO_STATUS_SUCCESS;
return CAIRO_STATUS_SUCCESS;
status = _cairo_surface_get_extents (dst, &extents);
if (status)
return status;
return status;
status = _cairo_traps_extract_region (traps, &trap_region);
if (status)
return status;
if (_cairo_operator_bounded_by_mask (op))
{
cairo_rectangle_int16_t trap_extents;
if (trap_region) {
status = _cairo_clip_intersect_to_region (clip, trap_region);
if (status)
goto out;
_cairo_region_extents_rectangle (trap_region, &trap_extents);
} else {
cairo_box_t trap_box;
_cairo_traps_extents (traps, &trap_box);
_cairo_box_round_to_rectangle (&trap_box, &trap_extents);
}
_cairo_rectangle_intersect (&extents, &trap_extents);
status = _cairo_clip_intersect_to_rectangle (clip, &extents);
if (status)
goto out;
if (CAIRO_INT_STATUS_UNSUPPORTED == status) {
has_trap_region = FALSE;
} else if (status) {
return status;
} else {
has_trap_region = TRUE;
}
else
{
cairo_surface_t *clip_surface = clip ? clip->surface : NULL;
if (trap_region && !clip_surface) {
/* If we optimize drawing with an unbounded operator to
* _cairo_surface_fill_rectangles() or to drawing with a
* clip region, then we have an additional region to clear.
*/
clear_region = _cairo_region_create_from_rectangle (&extents);
if (clear_region == NULL)
return CAIRO_STATUS_NO_MEMORY;
if (_cairo_operator_bounded_by_mask (op)) {
cairo_rectangle_int16_t trap_extents;
status = _cairo_clip_intersect_to_region (clip, clear_region);
if (status)
return status;
if (has_trap_region) {
status = _cairo_clip_intersect_to_region (clip, &trap_region);
_cairo_region_extents_rectangle (clear_region, &extents);
if (status)
goto out;
if (pixman_region_subtract (clear_region, clear_region, trap_region) != PIXMAN_REGION_STATUS_SUCCESS)
return CAIRO_STATUS_NO_MEMORY;
_cairo_region_extents_rectangle (&trap_region, &trap_extents);
} else {
cairo_box_t trap_box;
_cairo_traps_extents (traps, &trap_box);
_cairo_box_round_to_rectangle (&trap_box, &trap_extents);
}
if (!pixman_region_not_empty (clear_region)) {
pixman_region_destroy (clear_region);
clear_region = NULL;
}
} else {
status = _cairo_clip_intersect_to_rectangle (clip, &extents);
if (status)
return status;
}
_cairo_rectangle_intersect (&extents, &trap_extents);
status = _cairo_clip_intersect_to_rectangle (clip, &extents);
if (status)
goto out;
} else {
cairo_surface_t *clip_surface = clip ? clip->surface : NULL;
if (has_trap_region && !clip_surface) {
/* If we optimize drawing with an unbounded operator to
* _cairo_surface_fill_rectangles() or to drawing with a
* clip region, then we have an additional region to clear.
*/
if (_cairo_region_init_from_rectangle (&clear_region, &extents)) {
status = CAIRO_STATUS_NO_MEMORY;
goto out;
}
has_clear_region = TRUE;
status = _cairo_clip_intersect_to_region (clip, &clear_region);
if (status)
goto out;
_cairo_region_extents_rectangle (&clear_region, &extents);
if (PIXMAN_REGION_STATUS_SUCCESS !=
pixman_region_subtract (&clear_region, &clear_region, &trap_region)) {
status = CAIRO_STATUS_NO_MEMORY;
goto out;
}
if (!pixman_region_not_empty (&clear_region)) {
pixman_region_uninit (&clear_region);
has_clear_region = FALSE;
}
} else {
status = _cairo_clip_intersect_to_rectangle (clip, &extents);
}
}
if (status)
goto out;
goto out;
if (trap_region)
{
cairo_surface_t *clip_surface = clip ? clip->surface : NULL;
if (has_trap_region) {
cairo_surface_t *clip_surface = clip ? clip->surface : NULL;
if ((src->type == CAIRO_PATTERN_TYPE_SOLID || op == CAIRO_OPERATOR_CLEAR) &&
!clip_surface)
{
const cairo_color_t *color;
if ((src->type == CAIRO_PATTERN_TYPE_SOLID ||
op == CAIRO_OPERATOR_CLEAR) && !clip_surface) {
const cairo_color_t *color;
if (op == CAIRO_OPERATOR_CLEAR)
color = CAIRO_COLOR_TRANSPARENT;
else
color = &((cairo_solid_pattern_t *)src)->color;
if (op == CAIRO_OPERATOR_CLEAR) {
color = CAIRO_COLOR_TRANSPARENT;
} else {
color = &((cairo_solid_pattern_t *)src)->color;
}
/* Solid rectangles special case */
status = _cairo_surface_fill_region (dst, op, color, trap_region);
if (!status && clear_region)
status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR,
CAIRO_COLOR_TRANSPARENT,
clear_region);
/* Solid rectangles special case */
status = _cairo_surface_fill_region (dst, op, color, &trap_region);
goto out;
}
if (!status && has_clear_region)
status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR,
CAIRO_COLOR_TRANSPARENT,
&clear_region);
if ((_cairo_operator_bounded_by_mask (op) && op != CAIRO_OPERATOR_SOURCE) ||
!clip_surface)
{
/* For a simple rectangle, we can just use composite(), for more
* rectangles, we have to set a clip region. The cost of rasterizing
* trapezoids is pretty high for most backends currently, so it's
* worthwhile even if a region is needed.
*
* If we have a clip surface, we set it as the mask; this only works
* for bounded operators other than SOURCE; for unbounded operators,
* clip and mask cannot be interchanged. For SOURCE, the operator
* as implemented by the backends is different in it's handling
* of the mask then what we want.
*
* CAIRO_INT_STATUS_UNSUPPORTED will be returned if the region has
* more than rectangle and the destination doesn't support clip
* regions. In that case, we fall through.
*/
status = _composite_trap_region (clip, src, op, dst,
trap_region, &extents);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
{
if (!status && clear_region)
status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR,
CAIRO_COLOR_TRANSPARENT,
clear_region);
goto out;
}
}
goto out;
}
if ((_cairo_operator_bounded_by_mask (op) &&
op != CAIRO_OPERATOR_SOURCE) || !clip_surface) {
/* For a simple rectangle, we can just use composite(), for more
* rectangles, we have to set a clip region. The cost of rasterizing
* trapezoids is pretty high for most backends currently, so it's
* worthwhile even if a region is needed.
*
* If we have a clip surface, we set it as the mask; this only works
* for bounded operators other than SOURCE; for unbounded operators,
* clip and mask cannot be interchanged. For SOURCE, the operator
* as implemented by the backends is different in it's handling
* of the mask then what we want.
*
* CAIRO_INT_STATUS_UNSUPPORTED will be returned if the region has
* more than rectangle and the destination doesn't support clip
* regions. In that case, we fall through.
*/
status = _composite_trap_region (clip, src, op, dst,
&trap_region, &extents);
if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
if (!status && has_clear_region)
status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR,
CAIRO_COLOR_TRANSPARENT,
&clear_region);
goto out;
}
}
}
traps_info.traps = traps;
traps_info.antialias = antialias;
status = _clip_and_composite (clip, op, src,
_composite_traps_draw_func, &traps_info,
dst, &extents);
_composite_traps_draw_func,
&traps_info, dst, &extents);
out:
if (trap_region)
pixman_region_destroy (trap_region);
if (clear_region)
pixman_region_destroy (clear_region);
out:
if (has_trap_region)
pixman_region_uninit (&trap_region);
if (has_clear_region)
pixman_region_uninit (&clear_region);
return status;
}

View file

@ -1869,9 +1869,11 @@ _cairo_surface_composite_fixup_unbounded_internal (cairo_surface_t *dst,
{
cairo_rectangle_int16_t dst_rectangle;
cairo_rectangle_int16_t drawn_rectangle;
pixman_region16_t *drawn_region;
pixman_region16_t *clear_region;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_bool_t has_drawn_region = FALSE;
cairo_bool_t has_clear_region = FALSE;
pixman_region16_t drawn_region;
pixman_region16_t clear_region;
cairo_status_t status;
/* The area that was drawn is the area in the destination rectangle but not within
* the source or the mask.
@ -1884,34 +1886,42 @@ _cairo_surface_composite_fixup_unbounded_internal (cairo_surface_t *dst,
drawn_rectangle = dst_rectangle;
if (src_rectangle)
_cairo_rectangle_intersect (&drawn_rectangle, src_rectangle);
_cairo_rectangle_intersect (&drawn_rectangle, src_rectangle);
if (mask_rectangle)
_cairo_rectangle_intersect (&drawn_rectangle, mask_rectangle);
_cairo_rectangle_intersect (&drawn_rectangle, mask_rectangle);
/* Now compute the area that is in dst_rectangle but not in drawn_rectangle
*/
drawn_region = _cairo_region_create_from_rectangle (&drawn_rectangle);
clear_region = _cairo_region_create_from_rectangle (&dst_rectangle);
if (!drawn_region || !clear_region) {
status = CAIRO_STATUS_NO_MEMORY;
goto CLEANUP_REGIONS;
if (_cairo_region_init_from_rectangle (&drawn_region, &drawn_rectangle)) {
status = CAIRO_STATUS_NO_MEMORY;
goto CLEANUP_REGIONS;
}
if (pixman_region_subtract (clear_region, clear_region, drawn_region) != PIXMAN_REGION_STATUS_SUCCESS) {
status = CAIRO_STATUS_NO_MEMORY;
goto CLEANUP_REGIONS;
has_drawn_region = TRUE;
if (_cairo_region_init_from_rectangle (&clear_region, &dst_rectangle)) {
status = CAIRO_STATUS_NO_MEMORY;
goto CLEANUP_REGIONS;
}
has_clear_region = TRUE;
if (PIXMAN_REGION_STATUS_SUCCESS !=
pixman_region_subtract (&clear_region, &clear_region, &drawn_region)) {
status = CAIRO_STATUS_NO_MEMORY;
goto CLEANUP_REGIONS;
}
status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_SOURCE,
CAIRO_COLOR_TRANSPARENT,
clear_region);
CAIRO_COLOR_TRANSPARENT,
&clear_region);
CLEANUP_REGIONS:
if (drawn_region)
pixman_region_destroy (drawn_region);
if (clear_region)
pixman_region_destroy (clear_region);
CLEANUP_REGIONS:
if (has_drawn_region)
pixman_region_uninit (&drawn_region);
if (has_clear_region)
pixman_region_uninit (&clear_region);
return status;
}

View file

@ -2429,8 +2429,9 @@ _cairo_gstate_get_antialias (cairo_gstate_t *gstate);
/* cairo-region.c */
cairo_private pixman_region16_t *
_cairo_region_create_from_rectangle (cairo_rectangle_int16_t *rect);
cairo_private cairo_status_t
_cairo_region_init_from_rectangle (pixman_region16_t *region,
cairo_rectangle_int16_t *rect);
cairo_private void
_cairo_region_extents_rectangle (pixman_region16_t *region,