[cairo] 'cairo_restore()' doesn't restore context in error case

Iosif Haidu iosif.haidu at gmail.com
Fri Feb 15 14:50:57 PST 2008


Hi,

I have recently experienced an interesting behavior of the 'cairo_restore()'
function. It doesn't restore the cairo context saved by 'cairo_save()' if an
error occurs when executing windows gdi functions.

When I used these two functions I assumed that they must provide a
transaction like functionality: 'cairo_save()' saves the cairo context while
'cairo_restore()' would restore it even if an error would occur by executing
cairo functions between. But this is not the case. If a cairo function fail
to execute between,  by failing one of the windows gdi function, then
'cairo_restore()' will not restore the previously saved context.
I have experienced such situation for the application I'm working on it. For
an unknown reason sometime some windows gdi functions (CreateCompatibleDC(),
BitBlt() and other) fail to execute with error code 6 and 8. In this
situation the cairo function responsible with that windows gdi function call
will set the error status to CAIRO_STATUS_NO_MEMORY and the
'cairo_restore()' will not restore the cairo context. I have noticed that
cairo context actually has not been damaged by the failure of the windows
gdi function, yet the context is not restored.
Also the cairo documentation doesn't mention that 'cairo_restore()' will not
restore the context if an error occurs in a cairo function between
'cairo_save()' and 'cairo_restore()'.

I would like to propose a change in the 'cairo_restore()' implementation,
such that:
  a) will restore the previously saved context by 'cairo_save()' even if in
an error occurs
  b) will return as result the error code generated by any cairo function
executed between 'cairo_save()' and 'cairo_restore()'
  c) will reset the error status to CAIRO_STATUS_SUCCESS so that any next
execution of 'cairo_save()' and 'cairo_restore()' will not exit because of a
previous status set to an error code.

The function would be something like:

int
cairo_restore (cairo_t *cr)
{
...
int result = CAIRO_STATUS_SUCESS;
if (cr->status != CAIRO_STATUS_SUCCESS)
{
    result = cr->status;
    cr->status = CAIRO_STATUS_SUCCESS;
    if ((cr->gstate) && (cr->gstate->target))
    {
        cr->gstate->target->status = CAIRO_STATUS_SUCCESS;
    }
}
// if (cr->status)
// return;
...
return result;
}


Best regards,
Iosif Haidu
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.cairographics.org/archives/cairo/attachments/20080216/718e667c/attachment.html 


More information about the cairo mailing list