mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-04-21 13:31:00 +02:00
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:
parent
b0a256aaf3
commit
b82e595449
5 changed files with 53 additions and 22 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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, ®ion);
|
||||
clip->has_region = TRUE;
|
||||
if (pixman_region_copy (&clip->region, ®ion) ==
|
||||
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, ®ion)) {
|
||||
pixman_region_copy (&clip->region, &intersection);
|
||||
} else {
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
if (PIXMAN_REGION_STATUS_SUCCESS !=
|
||||
pixman_region_intersect (&intersection,
|
||||
&clip->region,
|
||||
®ion) ||
|
||||
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 =
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 *
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue