diff options
Diffstat (limited to 'src/cairo-surface.c')
-rw-r--r-- | src/cairo-surface.c | 66 |
1 files changed, 59 insertions, 7 deletions
diff --git a/src/cairo-surface.c b/src/cairo-surface.c index e080c31e..aaab3134 100644 --- a/src/cairo-surface.c +++ b/src/cairo-surface.c @@ -51,8 +51,10 @@ const cairo_surface_t name = { \ CAIRO_CONTENT_COLOR, /* content */ \ CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */ \ status, /* status */ \ - FALSE, /* finished */ \ 0, /* unique id */ \ + FALSE, /* finished */ \ + TRUE, /* is_clear */ \ + FALSE, /* has_font_options */ \ { 0, 0, 0, NULL, }, /* user_data */ \ { 0, 0, 0, NULL, }, /* mime_data */ \ { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, /* device_transform */ \ @@ -68,7 +70,6 @@ const cairo_surface_t name = { \ 0, /* element_size */ \ NULL, /* elements */ \ }, /* snapshots */ \ - FALSE, /* has_font_options */ \ { CAIRO_ANTIALIAS_DEFAULT, /* antialias */ \ CAIRO_SUBPIXEL_ORDER_DEFAULT, /* subpixel_order */ \ CAIRO_HINT_STYLE_DEFAULT, /* hint_style */ \ @@ -343,8 +344,9 @@ _cairo_surface_init (cairo_surface_t *surface, CAIRO_REFERENCE_COUNT_INIT (&surface->ref_count, 1); surface->status = CAIRO_STATUS_SUCCESS; - surface->finished = FALSE; surface->unique_id = _cairo_surface_allocate_unique_id (); + surface->finished = FALSE; + surface->is_clear = FALSE; _cairo_user_data_array_init (&surface->user_data); _cairo_user_data_array_init (&surface->mime_data); @@ -1030,6 +1032,8 @@ cairo_surface_mark_dirty_rectangle (cairo_surface_t *surface, * call mark_dirty()). */ assert (! _cairo_surface_has_snapshots (surface)); + surface->is_clear = FALSE; + if (surface->backend->mark_dirty_rectangle != NULL) { /* XXX: FRAGILE: We're ignoring the scaling component of * device_transform here. I don't know what the right thing to @@ -1924,6 +1928,14 @@ _cairo_surface_paint (cairo_surface_t *surface, if (clip && clip->all_clipped) return CAIRO_STATUS_SUCCESS; + if (op == CAIRO_OPERATOR_CLEAR) { + if (surface->is_clear) + return CAIRO_STATUS_SUCCESS; + + if (clip == NULL) + surface->is_clear = TRUE; + } + _cairo_surface_begin_modification (surface); if (surface->backend->paint != NULL) { @@ -1935,6 +1947,8 @@ _cairo_surface_paint (cairo_surface_t *surface, status = _cairo_surface_fallback_paint (surface, op, source, clip); FINISH: + surface->is_clear &= op == CAIRO_OPERATOR_CLEAR; + return _cairo_surface_set_error (surface, status); } @@ -1953,6 +1967,16 @@ _cairo_surface_mask (cairo_surface_t *surface, if (clip && clip->all_clipped) return CAIRO_STATUS_SUCCESS; + if (op == CAIRO_OPERATOR_CLEAR && surface->is_clear) + return CAIRO_STATUS_SUCCESS; + + /* If the mask is blank, this is just an expensive no-op */ + if (mask->type == CAIRO_PATTERN_TYPE_SURFACE) { + const cairo_surface_pattern_t *spattern = (cairo_surface_pattern_t *) mask; + if (spattern->surface->is_clear) + return CAIRO_STATUS_SUCCESS; + } + _cairo_surface_begin_modification (surface); if (surface->backend->mask != NULL) { @@ -1964,6 +1988,8 @@ _cairo_surface_mask (cairo_surface_t *surface, status = _cairo_surface_fallback_mask (surface, op, source, mask, clip); FINISH: + surface->is_clear &= op == CAIRO_OPERATOR_CLEAR; + return _cairo_surface_set_error (surface, status); } @@ -1992,6 +2018,13 @@ _cairo_surface_fill_stroke (cairo_surface_t *surface, if (clip && clip->all_clipped) return CAIRO_STATUS_SUCCESS; + if (surface->is_clear && + fill_op == CAIRO_OPERATOR_CLEAR && + stroke_op == CAIRO_OPERATOR_CLEAR) + { + return CAIRO_STATUS_SUCCESS; + } + _cairo_surface_begin_modification (surface); if (surface->backend->fill_stroke) { @@ -2009,23 +2042,27 @@ _cairo_surface_fill_stroke (cairo_surface_t *surface, clip); if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return _cairo_surface_set_error (surface, status); + goto FINISH; } status = _cairo_surface_fill (surface, fill_op, fill_source, path, fill_rule, fill_tolerance, fill_antialias, clip); if (unlikely (status)) - return _cairo_surface_set_error (surface, status); + goto FINISH; status = _cairo_surface_stroke (surface, stroke_op, stroke_source, path, stroke_style, stroke_ctm, stroke_ctm_inverse, stroke_tolerance, stroke_antialias, clip); if (unlikely (status)) - return _cairo_surface_set_error (surface, status); + goto FINISH; - return CAIRO_STATUS_SUCCESS; + FINISH: + surface->is_clear &= fill_op == CAIRO_OPERATOR_CLEAR; + surface->is_clear &= stroke_op == CAIRO_OPERATOR_CLEAR; + + return _cairo_surface_set_error (surface, status); } cairo_status_t @@ -2048,6 +2085,9 @@ _cairo_surface_stroke (cairo_surface_t *surface, if (clip && clip->all_clipped) return CAIRO_STATUS_SUCCESS; + if (op == CAIRO_OPERATOR_CLEAR && surface->is_clear) + return CAIRO_STATUS_SUCCESS; + _cairo_surface_begin_modification (surface); if (surface->backend->stroke != NULL) { @@ -2068,6 +2108,8 @@ _cairo_surface_stroke (cairo_surface_t *surface, clip); FINISH: + surface->is_clear &= op == CAIRO_OPERATOR_CLEAR; + return _cairo_surface_set_error (surface, status); } @@ -2089,6 +2131,9 @@ _cairo_surface_fill (cairo_surface_t *surface, if (clip && clip->all_clipped) return CAIRO_STATUS_SUCCESS; + if (op == CAIRO_OPERATOR_CLEAR && surface->is_clear) + return CAIRO_STATUS_SUCCESS; + _cairo_surface_begin_modification (surface); if (surface->backend->fill != NULL) { @@ -2107,6 +2152,8 @@ _cairo_surface_fill (cairo_surface_t *surface, clip); FINISH: + surface->is_clear &= op == CAIRO_OPERATOR_CLEAR; + return _cairo_surface_set_error (surface, status); } @@ -2408,6 +2455,9 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface, if (clip && clip->all_clipped) return CAIRO_STATUS_SUCCESS; + if (op == CAIRO_OPERATOR_CLEAR && surface->is_clear) + return CAIRO_STATUS_SUCCESS; + _cairo_surface_begin_modification (surface); if (_cairo_surface_has_device_transform (surface) && @@ -2504,6 +2554,8 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface, if (dev_scaled_font != scaled_font) cairo_scaled_font_destroy (dev_scaled_font); + surface->is_clear &= op == CAIRO_OPERATOR_CLEAR; + return _cairo_surface_set_error (surface, status); } |