Fix _cairo_surface_paint not setting is_clear

In commit 10e58a4a I changed the code in cairo-surface.c to avoid
setting surface->is_clear = FALSE; in some situations where it was not
necessary, because the operation did not actually modify anything (it
returned CAIRO_INT_STATUS_NOTHING_TO_DO). However, that change
accidentally also caused _cairo_surface_paint() not to set
surface->is_clear = TRUE; in similar cases. That was unintended.

This commit fixes that by always setting is_clear = TRUE when necessary,
but keeps the optimisation of not setting is_clear = FALSE when not
necessary.

The connection to the below issue is that the issue happened with
surfaces with width=0. Clearing such a surface with CAIRO_OPERATOR_CLEAR
causes CAIRO_INT_STATUS_NOTHING_TO_DO and thus is_clear = TRUE was not
set. This error was later caught by a failed assertion.

Fixes: https://gitlab.freedesktop.org/cairo/cairo/-/issues/283
Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
Uli Schlachter 2021-01-11 18:37:52 +01:00
parent 9508d25d6a
commit a7c49ec861

View file

@ -2174,6 +2174,7 @@ _cairo_surface_paint (cairo_surface_t *surface,
const cairo_clip_t *clip)
{
cairo_int_status_t status;
cairo_bool_t is_clear;
TRACE ((stderr, "%s\n", __FUNCTION__));
if (unlikely (surface->status))
@ -2196,8 +2197,9 @@ _cairo_surface_paint (cairo_surface_t *surface,
return status;
status = surface->backend->paint (surface, op, source, clip);
if (status != CAIRO_INT_STATUS_NOTHING_TO_DO) {
surface->is_clear = op == CAIRO_OPERATOR_CLEAR && clip == NULL;
is_clear = op == CAIRO_OPERATOR_CLEAR && clip == NULL;
if (status != CAIRO_INT_STATUS_NOTHING_TO_DO || is_clear) {
surface->is_clear = is_clear;
surface->serial++;
}