diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2011-07-29 18:36:52 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2011-07-29 18:39:27 +0100 |
commit | 2342e4da4fdbeed5672d586742fa19cf1018264c (patch) | |
tree | 17fc49ee2cbd2fe2e7c4da707bd65659ff84598f /src/cairo-image-surface.c | |
parent | d2ea8bd070f3bff87ec952af490093375cbc1f05 (diff) |
image: extend support of direct replay for paginated surfaces
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'src/cairo-image-surface.c')
-rw-r--r-- | src/cairo-image-surface.c | 72 |
1 files changed, 60 insertions, 12 deletions
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c index 3eb4e051..7a0ddc6d 100644 --- a/src/cairo-image-surface.c +++ b/src/cairo-image-surface.c @@ -44,9 +44,10 @@ #include "cairo-composite-rectangles-private.h" #include "cairo-default-context-private.h" #include "cairo-error-private.h" +#include "cairo-paginated-private.h" +#include "cairo-pattern-private.h" #include "cairo-recording-surface-private.h" #include "cairo-region-private.h" -#include "cairo-pattern-private.h" #include "cairo-scaled-font-private.h" #include "cairo-surface-snapshot-private.h" #include "cairo-surface-subsurface-private.h" @@ -2912,22 +2913,68 @@ _composite_unaligned_boxes (cairo_image_surface_t *dst, static cairo_bool_t is_recording_pattern (const cairo_pattern_t *pattern) { - const cairo_surface_pattern_t *surface_pattern; + cairo_surface_t *surface; if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE) return FALSE; - surface_pattern = (const cairo_surface_pattern_t *) pattern; - return _cairo_surface_is_recording (surface_pattern->surface); + surface = ((const cairo_surface_pattern_t *) pattern)->surface; + if (_cairo_surface_is_paginated (surface)) + surface = _cairo_paginated_surface_get_recording (surface); + return _cairo_surface_is_recording (surface); } static cairo_surface_t * -pattern_get_surface (const cairo_pattern_t *pattern) +recording_pattern_get_surface (const cairo_pattern_t *pattern) +{ + cairo_surface_t *surface; + + surface = ((const cairo_surface_pattern_t *) pattern)->surface; + if (_cairo_surface_is_paginated (surface)) + surface = _cairo_paginated_surface_get_recording (surface); + return surface; +} + +static cairo_bool_t +op_reduces_to_source (cairo_operator_t op, + cairo_image_surface_t *dst) +{ + if (op == CAIRO_OPERATOR_SOURCE) + return TRUE; + + if (dst->base.is_clear) + return op == CAIRO_OPERATOR_OVER || op == CAIRO_OPERATOR_ADD; + + return FALSE; +} + +static cairo_bool_t +recording_pattern_contains_sample (const cairo_pattern_t *pattern, + const cairo_rectangle_int_t *extents) { - const cairo_surface_pattern_t *surface_pattern; + cairo_rectangle_int_t area; + cairo_recording_surface_t *surface; + + if (! is_recording_pattern (pattern)) + return FALSE; + + if (pattern->extend == CAIRO_EXTEND_NONE) + return TRUE; - surface_pattern = (const cairo_surface_pattern_t *) pattern; - return surface_pattern->surface; + surface = (cairo_recording_surface_t *) recording_pattern_get_surface (pattern); + if (surface->unbounded) + return TRUE; + + sampled_area ((cairo_surface_pattern_t *) pattern, extents, &area); + if (area.x >= surface->extents.x && + area.y >= surface->extents.y && + area.x + area.width <= surface->extents.x + surface->extents.width && + area.y + area.height <= surface->extents.y + surface->extents.height) + { + return TRUE; + } + + return FALSE; } static cairo_status_t @@ -2970,12 +3017,13 @@ _composite_boxes (cairo_image_surface_t *dst, /* Are we just copying a recording surface? */ if (! need_clip_mask && - op == CAIRO_OPERATOR_SOURCE && - pattern->extend == CAIRO_EXTEND_NONE && /* or if sample is contained */ - is_recording_pattern (pattern)) + op_reduces_to_source (op, dst) && + recording_pattern_contains_sample (pattern, &extents->bounded)) { cairo_clip_t *recording_clip; + /* XXX could also do tiling repeat modes... */ + /* first clear the area about to be overwritten */ if (! dst->base.is_clear) { for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) { @@ -3000,7 +3048,7 @@ _composite_boxes (cairo_image_surface_t *dst, } recording_clip = _cairo_clip_from_boxes (boxes); - status = _cairo_recording_surface_replay_with_clip (pattern_get_surface (pattern), + status = _cairo_recording_surface_replay_with_clip (recording_pattern_get_surface (pattern), &pattern->matrix, &dst->base, recording_clip); |