mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2025-12-20 05:50:10 +01:00
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:
parent
e0b741de90
commit
5d95ae924e
3 changed files with 30 additions and 15 deletions
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
26
src/cairo.c
26
src/cairo.c
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue