pixman region operations can fail, propagate the error.

Copying the clip region could fail, add error returns and propagate up
the call stack.
This commit is contained in:
Chris Wilson 2007-04-09 15:31:28 +01:00 committed by Carl Worth
parent b0a256aaf3
commit b82e595449
5 changed files with 53 additions and 22 deletions

View file

@ -84,10 +84,10 @@ struct _cairo_clip {
cairo_private void
_cairo_clip_init (cairo_clip_t *clip, cairo_surface_t *target);
cairo_private void
cairo_private cairo_status_t
_cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other);
cairo_private void
cairo_private cairo_status_t
_cairo_clip_init_deep_copy (cairo_clip_t *clip,
cairo_clip_t *other,
cairo_surface_t *target);

View file

@ -67,7 +67,7 @@ _cairo_clip_init (cairo_clip_t *clip, cairo_surface_t *target)
clip->path = NULL;
}
void
cairo_status_t
_cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other)
{
clip->mode = other->mode;
@ -80,13 +80,20 @@ _cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other)
pixman_region_init (&clip->region);
if (other->has_region) {
pixman_region_copy (&clip->region, &other->region);
if (pixman_region_copy (&clip->region, &other->region) !=
PIXMAN_REGION_STATUS_SUCCESS) {
pixman_region_fini (&clip->region);
cairo_surface_destroy (clip->surface);
return CAIRO_STATUS_NO_MEMORY;
}
clip->has_region = TRUE;
} else {
clip->has_region = FALSE;
}
clip->path = _cairo_clip_path_reference (other->path);
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
@ -342,18 +349,20 @@ _cairo_clip_intersect_region (cairo_clip_t *clip,
status = CAIRO_STATUS_SUCCESS;
if (!clip->has_region) {
pixman_region_copy (&clip->region, &region);
clip->has_region = TRUE;
if (pixman_region_copy (&clip->region, &region) ==
PIXMAN_REGION_STATUS_SUCCESS)
clip->has_region = TRUE;
} else {
pixman_region16_t intersection;
pixman_region_init (&intersection);
if (PIXMAN_REGION_STATUS_SUCCESS ==
pixman_region_intersect (&intersection, &clip->region, &region)) {
pixman_region_copy (&clip->region, &intersection);
} else {
status = CAIRO_STATUS_NO_MEMORY;
}
if (PIXMAN_REGION_STATUS_SUCCESS !=
pixman_region_intersect (&intersection,
&clip->region,
&region) ||
PIXMAN_REGION_STATUS_SUCCESS !=
pixman_region_copy (&clip->region, &intersection))
status = CAIRO_STATUS_NO_MEMORY;
pixman_region_fini (&intersection);
}
@ -544,7 +553,7 @@ _cairo_clip_path_reapply_clip_path (cairo_clip_t *clip,
clip_path->antialias);
}
void
cairo_status_t
_cairo_clip_init_deep_copy (cairo_clip_t *clip,
cairo_clip_t *other,
cairo_surface_t *target)
@ -556,17 +565,21 @@ _cairo_clip_init_deep_copy (cairo_clip_t *clip,
* whatever the right handling is happen */
} else {
if (other->has_region) {
pixman_region_copy (&clip->region, &other->region);
clip->has_region = TRUE;
if (pixman_region_copy (&clip->region, &other->region) !=
PIXMAN_REGION_STATUS_SUCCESS)
goto BAIL;
clip->has_region = TRUE;
}
if (other->surface) {
_cairo_surface_clone_similar (target, other->surface,
if (_cairo_surface_clone_similar (target, other->surface,
other->surface_rect.x,
other->surface_rect.y,
other->surface_rect.width,
other->surface_rect.height,
&clip->surface);
&clip->surface) !=
CAIRO_STATUS_SUCCESS)
goto BAIL;
clip->surface_rect = other->surface_rect;
}
@ -574,6 +587,16 @@ _cairo_clip_init_deep_copy (cairo_clip_t *clip,
_cairo_clip_path_reapply_clip_path (clip, other->path);
}
}
return CAIRO_STATUS_SUCCESS;
BAIL:
if (clip->has_region)
pixman_region_fini (&clip->region);
if (clip->surface)
cairo_surface_destroy (clip->surface);
return CAIRO_STATUS_NO_MEMORY;
}
const cairo_rectangle_list_t _cairo_rectangles_nil =

View file

@ -129,7 +129,9 @@ _cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other)
_cairo_font_options_init_copy (&gstate->font_options , &other->font_options);
_cairo_clip_init_copy (&gstate->clip, &other->clip);
status = _cairo_clip_init_copy (&gstate->clip, &other->clip);
if (status)
return status;
gstate->target = cairo_surface_reference (other->target);
/* parent_target is always set to NULL; it's only ever set by redirect_target */
@ -299,9 +301,11 @@ _cairo_gstate_recursive_apply_clip_path (cairo_gstate_t *gstate,
* original #cairo_t target, the clip will be INVALID after this call,
* and the caller should either recreate or reset the clip.
**/
void
cairo_status_t
_cairo_gstate_redirect_target (cairo_gstate_t *gstate, cairo_surface_t *child)
{
cairo_status_t status;
/* If this gstate is already redirected, this is an error; we need a
* new gstate to be able to redirect */
assert (gstate->parent_target == NULL);
@ -317,13 +321,17 @@ _cairo_gstate_redirect_target (cairo_gstate_t *gstate, cairo_surface_t *child)
gstate->target = cairo_surface_reference (child);
_cairo_clip_reset (&gstate->clip);
_cairo_clip_init_deep_copy (&gstate->clip, &gstate->next->clip, child);
status = _cairo_clip_init_deep_copy (&gstate->clip, &gstate->next->clip, child);
if (status)
return status;
/* The clip is in surface backend coordinates for the previous target;
* translate it into the child's backend coordinates. */
_cairo_clip_translate (&gstate->clip,
_cairo_fixed_from_double (child->device_transform.x0 - gstate->parent_target->device_transform.x0),
_cairo_fixed_from_double (child->device_transform.y0 - gstate->parent_target->device_transform.y0));
return CAIRO_STATUS_SUCCESS;
}
/**

View file

@ -517,7 +517,7 @@ cairo_push_group_with_content (cairo_t *cr, cairo_content_t content)
if (cr->status)
goto bail;
_cairo_gstate_redirect_target (cr->gstate, group_surface);
status = _cairo_gstate_redirect_target (cr->gstate, group_surface);
bail:
cairo_surface_destroy (group_surface);

View file

@ -1257,7 +1257,7 @@ _cairo_gstate_restore (cairo_gstate_t **gstate);
cairo_private cairo_bool_t
_cairo_gstate_is_redirected (cairo_gstate_t *gstate);
cairo_private void
cairo_private cairo_status_t
_cairo_gstate_redirect_target (cairo_gstate_t *gstate, cairo_surface_t *child);
cairo_private cairo_surface_t *