mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2025-12-25 09:30:18 +01:00
Avoid malloc in _cairo_region_create_from_rectangle
This commit is contained in:
parent
efc9775149
commit
241482b550
5 changed files with 186 additions and 171 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue