gstate: Set an error status when restoring a push_group

cairo_push_group (cr) followed by cairo_restore (cr) should put cr in
an error status of CAIRO_STATUS_INVALID_RESTORE.

Fixes group-state.
This commit is contained in:
Andrea Canciani 2011-01-20 01:44:29 +01:00
parent e0b741de90
commit 5d95ae924e
3 changed files with 30 additions and 15 deletions

View file

@ -87,6 +87,9 @@ _cairo_gstate_save (cairo_gstate_t **gstate, cairo_gstate_t **freelist);
cairo_private cairo_status_t
_cairo_gstate_restore (cairo_gstate_t **gstate, cairo_gstate_t **freelist);
cairo_private cairo_bool_t
_cairo_gstate_is_group (cairo_gstate_t *gstate);
cairo_private cairo_bool_t
_cairo_gstate_is_redirected (cairo_gstate_t *gstate);

View file

@ -341,6 +341,22 @@ _cairo_gstate_redirect_target (cairo_gstate_t *gstate, cairo_surface_t *child)
&matrix);
}
/**
* _cairo_gstate_is_group
* @gstate: a #cairo_gstate_t
*
* Check if _cairo_gstate_redirect_target has been called on the head
* of the stack.
*
* Return value: %TRUE if @gstate is redirected to a target different
* than the previous state in the stack, %FALSE otherwise.
**/
cairo_bool_t
_cairo_gstate_is_group (cairo_gstate_t *gstate)
{
return gstate->parent_target != NULL;
}
/**
* _cairo_gstate_is_redirected
* @gstate: a #cairo_gstate_t

View file

@ -585,6 +585,11 @@ cairo_restore (cairo_t *cr)
if (unlikely (cr->status))
return;
if (unlikely (_cairo_gstate_is_group (cr->gstate))) {
_cairo_set_error (cr, _cairo_error (CAIRO_STATUS_INVALID_RESTORE));
return;
}
status = _cairo_gstate_restore (&cr->gstate, &cr->gstate_freelist);
if (unlikely (status))
_cairo_set_error (cr, status);
@ -754,7 +759,7 @@ slim_hidden_def(cairo_push_group_with_content);
cairo_pattern_t *
cairo_pop_group (cairo_t *cr)
{
cairo_surface_t *group_surface, *parent_target;
cairo_surface_t *group_surface;
cairo_pattern_t *group_pattern;
cairo_matrix_t group_matrix, device_transform_matrix;
cairo_status_t status;
@ -762,27 +767,18 @@ cairo_pop_group (cairo_t *cr)
if (unlikely (cr->status))
return _cairo_pattern_create_in_error (cr->status);
/* Grab the active surfaces */
group_surface = _cairo_gstate_get_target (cr->gstate);
parent_target = _cairo_gstate_get_parent_target (cr->gstate);
/* Verify that we are at the right nesting level */
if (parent_target == NULL) {
if (unlikely (! _cairo_gstate_is_group (cr->gstate))) {
_cairo_set_error (cr, CAIRO_STATUS_INVALID_POP_GROUP);
return _cairo_pattern_create_in_error (CAIRO_STATUS_INVALID_POP_GROUP);
}
/* We need to save group_surface before we restore; we don't need
* to reference parent_target and original_target, since the
* gstate will still hold refs to them once we restore. */
/* Get a reference to the active surface before restoring */
group_surface = _cairo_gstate_get_target (cr->gstate);
group_surface = cairo_surface_reference (group_surface);
cairo_restore (cr);
if (unlikely (cr->status)) {
group_pattern = _cairo_pattern_create_in_error (cr->status);
goto done;
}
status = _cairo_gstate_restore (&cr->gstate, &cr->gstate_freelist);
assert (status == CAIRO_STATUS_SUCCESS);
group_pattern = cairo_pattern_create_for_surface (group_surface);
status = group_pattern->status;