diff options
Diffstat (limited to 'src/cairo-recording-surface.c')
-rw-r--r-- | src/cairo-recording-surface.c | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/src/cairo-recording-surface.c b/src/cairo-recording-surface.c index 55a98d023..eb9af464f 100644 --- a/src/cairo-recording-surface.c +++ b/src/cairo-recording-surface.c @@ -87,6 +87,7 @@ #include "cairo-error-private.h" #include "cairo-image-surface-private.h" #include "cairo-recording-surface-inline.h" +#include "cairo-surface-snapshot-inline.h" #include "cairo-surface-wrapper-private.h" #include "cairo-traps-private.h" @@ -420,6 +421,8 @@ cairo_recording_surface_create (cairo_content_t content, surface->indices = NULL; surface->num_indices = 0; surface->optimize_clears = TRUE; + surface->has_bilevel_alpha = FALSE; + surface->has_only_op_over = FALSE; return &surface->base; } @@ -1603,6 +1606,65 @@ _cairo_recording_surface_get_visible_commands (cairo_recording_surface_t *surfac return num_visible; } +static void +_cairo_recording_surface_merge_source_attributes (cairo_recording_surface_t *surface, + cairo_operator_t op, + const cairo_pattern_t *source) +{ + if (op != CAIRO_OPERATOR_OVER) + surface->has_only_op_over = FALSE; + + if (source->type == CAIRO_PATTERN_TYPE_SURFACE) { + cairo_surface_pattern_t *surf_pat = (cairo_surface_pattern_t *) source; + cairo_surface_t *surf = surf_pat->surface; + cairo_surface_t *free_me; + + if (_cairo_surface_is_snapshot (surf)) + free_me = surf = _cairo_surface_snapshot_get_target (surf); + + if (surf->type == CAIRO_SURFACE_TYPE_RECORDING) { + cairo_recording_surface_t *rec_surf = (cairo_recording_surface_t *) surf; + + if (! _cairo_recording_surface_has_only_bilevel_alpha (rec_surf)) + surface->has_bilevel_alpha = FALSE; + + if (! _cairo_recording_surface_has_only_op_over (rec_surf)) + surface->has_only_op_over = FALSE; + + } else if (surf->type == CAIRO_SURFACE_TYPE_IMAGE) { + cairo_image_surface_t *img_surf = (cairo_image_surface_t *) surf; + + if (_cairo_image_analyze_transparency (img_surf) == CAIRO_IMAGE_HAS_ALPHA) + surface->has_bilevel_alpha = FALSE; + + } + + cairo_surface_destroy (free_me); + return; + + } else if (source->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) { + cairo_surface_t *image; + cairo_surface_t *raster; + + image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1); + raster = _cairo_raster_source_pattern_acquire (source, image, NULL); + cairo_surface_destroy (image); + if (raster) { + if (raster->type == CAIRO_SURFACE_TYPE_IMAGE) { + if (_cairo_image_analyze_transparency ((cairo_image_surface_t *)raster) == CAIRO_IMAGE_HAS_ALPHA) + surface->has_bilevel_alpha = FALSE; + } + + _cairo_raster_source_pattern_release (source, raster); + if (raster->type == CAIRO_SURFACE_TYPE_IMAGE) + return; + } + } + + if (!_cairo_pattern_is_clear (source) && !_cairo_pattern_is_opaque (source, NULL)) + surface->has_bilevel_alpha = FALSE; +} + static cairo_status_t _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface, const cairo_rectangle_int_t *surface_extents, @@ -1652,6 +1714,9 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface, if (! _cairo_surface_wrapper_get_target_extents (&wrapper, &extents)) goto done; + surface->has_bilevel_alpha = TRUE; + surface->has_only_op_over = TRUE; + num_elements = surface->commands.num_elements; elements = _cairo_array_index (&surface->commands, 0); if (extents.width < r->width || extents.height < r->height) { @@ -1675,6 +1740,11 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface, command->header.op, &command->paint.source.base, command->header.clip); + if (type == CAIRO_RECORDING_CREATE_REGIONS) { + _cairo_recording_surface_merge_source_attributes (surface, + command->header.op, + &command->paint.source.base); + } break; case CAIRO_COMMAND_MASK: @@ -1683,6 +1753,14 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface, &command->mask.source.base, &command->mask.mask.base, command->header.clip); + if (type == CAIRO_RECORDING_CREATE_REGIONS) { + _cairo_recording_surface_merge_source_attributes (surface, + command->header.op, + &command->mask.source.base); + _cairo_recording_surface_merge_source_attributes (surface, + command->header.op, + &command->mask.mask.base); + } break; case CAIRO_COMMAND_STROKE: @@ -1696,6 +1774,11 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface, command->stroke.tolerance, command->stroke.antialias, command->header.clip); + if (type == CAIRO_RECORDING_CREATE_REGIONS) { + _cairo_recording_surface_merge_source_attributes (surface, + command->header.op, + &command->stroke.source.base); + } break; case CAIRO_COMMAND_FILL: @@ -1737,6 +1820,14 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface, stroke_command->stroke.tolerance, stroke_command->stroke.antialias, command->header.clip); + if (type == CAIRO_RECORDING_CREATE_REGIONS) { + _cairo_recording_surface_merge_source_attributes (surface, + command->header.op, + &command->fill.source.base); + _cairo_recording_surface_merge_source_attributes (surface, + command->header.op, + &command->stroke.source.base); + } i++; } } @@ -1749,6 +1840,11 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface, command->fill.tolerance, command->fill.antialias, command->header.clip); + if (type == CAIRO_RECORDING_CREATE_REGIONS) { + _cairo_recording_surface_merge_source_attributes (surface, + command->header.op, + &command->fill.source.base); + } } break; @@ -1762,6 +1858,11 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface, command->show_text_glyphs.cluster_flags, command->show_text_glyphs.scaled_font, command->header.clip); + if (type == CAIRO_RECORDING_CREATE_REGIONS) { + _cairo_recording_surface_merge_source_attributes (surface, + command->header.op, + &command->show_text_glyphs.source.base); + } break; default: @@ -2070,3 +2171,15 @@ cairo_recording_surface_get_extents (cairo_surface_t *surface, *extents = record->extents_pixels; return TRUE; } + +cairo_bool_t +_cairo_recording_surface_has_only_bilevel_alpha (cairo_recording_surface_t *surface) +{ + return surface->has_bilevel_alpha; +} + +cairo_bool_t +_cairo_recording_surface_has_only_op_over (cairo_recording_surface_t *surface) +{ + return surface->has_only_op_over; +} |