diff --git a/src/cairo-clip.c b/src/cairo-clip.c index 74b0a6816..1698ddb66 100644 --- a/src/cairo-clip.c +++ b/src/cairo-clip.c @@ -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; diff --git a/src/cairo-region.c b/src/cairo-region.c index 4ba28522d..1e1c86fda 100644 --- a/src/cairo-region.c +++ b/src/cairo-region.c @@ -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; } /** diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c index 004de6893..b950145bb 100644 --- a/src/cairo-surface-fallback.c +++ b/src/cairo-surface-fallback.c @@ -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; } diff --git a/src/cairo-surface.c b/src/cairo-surface.c index 9b69b6589..7f30c339c 100644 --- a/src/cairo-surface.c +++ b/src/cairo-surface.c @@ -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; } diff --git a/src/cairoint.h b/src/cairoint.h index c5333fb69..08414d03c 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -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,