diff options
-rw-r--r-- | src/cairo-clip-boxes.c | 17 | ||||
-rw-r--r-- | src/cairo-clip-private.h | 15 | ||||
-rw-r--r-- | src/cairo-clip.c | 67 | ||||
-rw-r--r-- | src/cairo-image-surface.c | 64 | ||||
-rw-r--r-- | src/cairo-recording-surface-private.h | 6 | ||||
-rw-r--r-- | src/cairo-recording-surface.c | 68 | ||||
-rw-r--r-- | src/cairo-surface-wrapper-private.h | 13 | ||||
-rw-r--r-- | src/cairo-surface-wrapper.c | 190 |
8 files changed, 337 insertions, 103 deletions
diff --git a/src/cairo-clip-boxes.c b/src/cairo-clip-boxes.c index 95ed265bf..98d1a18b0 100644 --- a/src/cairo-clip-boxes.c +++ b/src/cairo-clip-boxes.c @@ -560,3 +560,20 @@ _cairo_clip_to_boxes (cairo_clip_t *clip, return CAIRO_STATUS_SUCCESS; } + +cairo_clip_t * +_cairo_clip_from_boxes (const cairo_boxes_t *boxes) +{ + cairo_clip_t *clip = _cairo_clip_create (); + if (clip == NULL) + return _cairo_clip_set_all_clipped (clip); + + /* XXX cow-boxes? */ + clip->boxes = _cairo_boxes_to_array (boxes, &clip->num_boxes, TRUE); + if (clip->boxes == NULL) + return _cairo_clip_set_all_clipped (clip); + + _cairo_boxes_extents (boxes, &clip->extents); + + return clip; +} diff --git a/src/cairo-clip-private.h b/src/cairo-clip-private.h index 2ad53efdc..7f44bdfc8 100644 --- a/src/cairo-clip-private.h +++ b/src/cairo-clip-private.h @@ -116,6 +116,18 @@ _cairo_clip_copy_intersect_rectangle (const cairo_clip_t *clip, } cairo_private cairo_clip_t * +_cairo_clip_intersect_clip (cairo_clip_t *clip, + const cairo_clip_t *other); + +static inline cairo_clip_t * +_cairo_clip_copy_intersect_clip (const cairo_clip_t *clip, + const cairo_clip_t *other) +{ + return _cairo_clip_intersect_clip (_cairo_clip_copy (clip), other); +} + + +cairo_private cairo_clip_t * _cairo_clip_intersect_box (cairo_clip_t *clip, const cairo_box_t *box); @@ -151,6 +163,9 @@ cairo_private cairo_status_t _cairo_clip_to_boxes (cairo_clip_t *clip, cairo_boxes_t *boxes); +cairo_private cairo_clip_t * +_cairo_clip_from_boxes (const cairo_boxes_t *boxes); + cairo_private cairo_region_t * _cairo_clip_get_region (const cairo_clip_t *clip); diff --git a/src/cairo-clip.c b/src/cairo-clip.c index e5979d525..99336bd7c 100644 --- a/src/cairo-clip.c +++ b/src/cairo-clip.c @@ -250,14 +250,14 @@ _cairo_clip_intersect_path (cairo_clip_t *clip, if (clip == NULL) { clip = _cairo_clip_create (); if (unlikely (clip == NULL)) - return _cairo_clip_set_all_clipped (clip); + return _cairo_clip_set_all_clipped (clip); clip->extents = extents; } clip_path = _cairo_clip_path_create (clip); if (unlikely (clip_path == NULL)) - return _cairo_clip_set_all_clipped (clip); + return _cairo_clip_set_all_clipped (clip); status = _cairo_path_fixed_init_copy (&clip_path->path, path); if (unlikely (status)) @@ -267,7 +267,70 @@ _cairo_clip_intersect_path (cairo_clip_t *clip, clip_path->tolerance = tolerance; clip_path->antialias = antialias; + if (clip->region) { + cairo_region_destroy (clip->region); + clip->region = NULL; + } + + clip->is_region = FALSE; + return clip; +} + +static cairo_clip_t * +_cairo_clip_intersect_clip_path (cairo_clip_t *clip, + const cairo_clip_path_t *clip_path) +{ + if (clip_path->prev) + clip = _cairo_clip_intersect_clip_path (clip, clip_path->prev); + + return _cairo_clip_intersect_path (clip, + &clip_path->path, + clip_path->fill_rule, + clip_path->tolerance, + clip_path->antialias); +} + +cairo_clip_t * +_cairo_clip_intersect_clip (cairo_clip_t *clip, + const cairo_clip_t *other) +{ + if (_cairo_clip_is_all_clipped (clip)) + return clip; + + if (other == NULL) + return clip; + + if (clip == NULL) + return _cairo_clip_copy (other); + + if (_cairo_clip_is_all_clipped (other)) + return _cairo_clip_set_all_clipped (clip); + + if (! _cairo_rectangle_intersect (&clip->extents, &other->extents)) + return _cairo_clip_set_all_clipped (clip); + + if (other->num_boxes) { + cairo_boxes_t boxes; + + _cairo_boxes_init_for_array (&boxes, other->boxes, other->num_boxes); + clip = _cairo_clip_intersect_boxes (clip, &boxes); + } + + if (! _cairo_clip_is_all_clipped (clip)) { + if (other->path) { + if (clip->path == NULL) + clip->path = _cairo_clip_path_reference (other->path); + else + clip = _cairo_clip_intersect_clip_path (clip, other->path); + } + } + + if (clip->region) { + cairo_region_destroy (clip->region); + clip->region = NULL; + } clip->is_region = FALSE; + return clip; } diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c index a03e1abb1..f727b84ac 100644 --- a/src/cairo-image-surface.c +++ b/src/cairo-image-surface.c @@ -44,6 +44,7 @@ #include "cairo-composite-rectangles-private.h" #include "cairo-default-context-private.h" #include "cairo-error-private.h" +#include "cairo-recording-surface-private.h" #include "cairo-region-private.h" #include "cairo-pattern-private.h" #include "cairo-scaled-font-private.h" @@ -2878,6 +2879,27 @@ _composite_unaligned_boxes (cairo_image_surface_t *dst, return status; } +static cairo_bool_t +is_recording_pattern (const cairo_pattern_t *pattern) +{ + const cairo_surface_pattern_t *surface_pattern; + + 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); +} + +static cairo_surface_t * +pattern_get_surface (const cairo_pattern_t *pattern) +{ + const cairo_surface_pattern_t *surface_pattern; + + surface_pattern = (const cairo_surface_pattern_t *) pattern; + return surface_pattern->surface; +} + static cairo_status_t _composite_boxes (cairo_image_surface_t *dst, cairo_operator_t op, @@ -2916,6 +2938,47 @@ _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)) + { + cairo_clip_t *recording_clip; + + /* first clear the area about to be overwritten */ + if (! dst->base.is_clear) { + for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) { + cairo_box_t *box = chunk->base; + + for (i = 0; i < chunk->count; i++) { + int x1 = _cairo_fixed_integer_round_down (box[i].p1.x); + int y1 = _cairo_fixed_integer_round_down (box[i].p1.y); + int x2 = _cairo_fixed_integer_round_down (box[i].p2.x); + int y2 = _cairo_fixed_integer_round_down (box[i].p2.y); + + if (x2 == x1 || y2 == y1) + continue; + + pixman_fill ((uint32_t *) dst->data, + dst->stride / sizeof (uint32_t), + PIXMAN_FORMAT_BPP (dst->pixman_format), + x1, y1, x2 - x1, y2 - y1, + 0); + } + } + } + + recording_clip = _cairo_clip_from_boxes (boxes); + status = _cairo_recording_surface_replay_with_clip (pattern_get_surface (pattern), + &pattern->matrix, + &dst->base, + recording_clip); + _cairo_clip_destroy (recording_clip); + + return status; + } + status = CAIRO_STATUS_SUCCESS; if (! need_clip_mask && pattern_to_pixel ((cairo_solid_pattern_t *) pattern, op, dst->pixman_format, @@ -4476,7 +4539,6 @@ _cairo_image_surface_coerce (cairo_image_surface_t *surface) { return _cairo_image_surface_coerce_to_format (surface, _cairo_format_from_content (surface->base.content)); - } /* A convenience function for when one needs to coerce an image diff --git a/src/cairo-recording-surface-private.h b/src/cairo-recording-surface-private.h index a901e7b14..cc23d80c6 100644 --- a/src/cairo-recording-surface-private.h +++ b/src/cairo-recording-surface-private.h @@ -145,6 +145,12 @@ _cairo_recording_surface_replay (cairo_surface_t *surface, cairo_surface_t *target); cairo_private cairo_status_t +_cairo_recording_surface_replay_with_clip (cairo_surface_t *surface, + const cairo_matrix_t *surface_transform, + cairo_surface_t *target, + const cairo_clip_t *target_clip); + +cairo_private cairo_status_t _cairo_recording_surface_replay_and_create_regions (cairo_surface_t *surface, cairo_surface_t *target); cairo_private cairo_status_t diff --git a/src/cairo-recording-surface.c b/src/cairo-recording-surface.c index ea5ee0178..96c71fd49 100644 --- a/src/cairo-recording-surface.c +++ b/src/cairo-recording-surface.c @@ -251,14 +251,6 @@ _cairo_recording_surface_acquire_source_image_transformed (void *abstract_s double width; double height; - image = _cairo_surface_has_snapshot (&surface->base, - &_cairo_image_surface_backend); - if (image != NULL) { - *image_out = (cairo_image_surface_t *) cairo_surface_reference (image); - *image_extra = NULL; - return CAIRO_STATUS_SUCCESS; - } - width = surface->extents.width * device_transform->xx; height = surface->extents.height * device_transform->yy; image = _cairo_image_surface_create_with_content (surface->content, @@ -278,8 +270,6 @@ _cairo_recording_surface_acquire_source_image_transformed (void *abstract_s return status; } - _cairo_surface_attach_snapshot (&surface->base, image, NULL); - *image_out = (cairo_image_surface_t *) image; *image_extra = NULL; return CAIRO_STATUS_SUCCESS; @@ -291,11 +281,29 @@ _cairo_recording_surface_acquire_source_image (void *abstract_surface, void **image_extra) { cairo_matrix_t identity; + cairo_surface_t *image; + cairo_status_t status; + + image = _cairo_surface_has_snapshot (abstract_surface, + &_cairo_image_surface_backend); + if (image != NULL) { + *image_out = (cairo_image_surface_t *) cairo_surface_reference (image); + *image_extra = NULL; + return CAIRO_STATUS_SUCCESS; + } cairo_matrix_init_identity (&identity); - return _cairo_recording_surface_acquire_source_image_transformed ( - abstract_surface, &identity, image_out, image_extra); + status = + _cairo_recording_surface_acquire_source_image_transformed (abstract_surface, &identity, image_out, image_extra); + if (unlikely (status)) + return status; + + _cairo_surface_attach_snapshot (abstract_surface, + &(*image_out)->base, + NULL); + return CAIRO_STATUS_SUCCESS; + } static void @@ -817,7 +825,9 @@ _cairo_recording_surface_get_path (cairo_surface_t *surface, static cairo_status_t _cairo_recording_surface_replay_internal (cairo_surface_t *surface, const cairo_rectangle_int_t *surface_extents, + const cairo_matrix_t *surface_transform, cairo_surface_t *target, + const cairo_clip_t *target_clip, cairo_recording_replay_type_t type, cairo_recording_region_type_t region) { @@ -843,6 +853,8 @@ _cairo_recording_surface_replay_internal (cairo_surface_t *surface, _cairo_surface_wrapper_init (&wrapper, target); _cairo_surface_wrapper_set_extents (&wrapper, surface_extents); + _cairo_surface_wrapper_set_inverse_transform (&wrapper, surface_transform); + _cairo_surface_wrapper_set_clip (&wrapper, target_clip); recording_surface = (cairo_recording_surface_t *) surface; status = CAIRO_STATUS_SUCCESS; @@ -854,7 +866,8 @@ _cairo_recording_surface_replay_internal (cairo_surface_t *surface, cairo_command_t *command = elements[i]; cairo_clip_t *clip = command->header.clip; - if (type == CAIRO_RECORDING_REPLAY && region != CAIRO_RECORDING_REGION_ALL) { + if (type == CAIRO_RECORDING_REPLAY && + region != CAIRO_RECORDING_REGION_ALL) { if (command->header.region != region) continue; } @@ -881,7 +894,6 @@ _cairo_recording_surface_replay_internal (cairo_surface_t *surface, break; case CAIRO_COMMAND_STROKE: - { status = _cairo_surface_wrapper_stroke (&wrapper, command->header.op, &command->stroke.source.base, @@ -893,7 +905,7 @@ _cairo_recording_surface_replay_internal (cairo_surface_t *surface, command->stroke.antialias, clip); break; - } + case CAIRO_COMMAND_FILL: { cairo_command_t *stroke_command; @@ -945,6 +957,7 @@ _cairo_recording_surface_replay_internal (cairo_surface_t *surface, } break; } + case CAIRO_COMMAND_SHOW_TEXT_GLYPHS: { cairo_glyph_t *glyphs = command->show_text_glyphs.glyphs; @@ -975,6 +988,7 @@ _cairo_recording_surface_replay_internal (cairo_surface_t *surface, free (glyphs_copy); break; } + default: ASSERT_NOT_REACHED; } @@ -1017,8 +1031,20 @@ cairo_status_t _cairo_recording_surface_replay (cairo_surface_t *surface, cairo_surface_t *target) { - return _cairo_recording_surface_replay_internal (surface, NULL, - target, + return _cairo_recording_surface_replay_internal (surface, NULL, NULL, + target, NULL, + CAIRO_RECORDING_REPLAY, + CAIRO_RECORDING_REGION_ALL); +} + +cairo_status_t +_cairo_recording_surface_replay_with_clip (cairo_surface_t *surface, + const cairo_matrix_t *surface_transform, + cairo_surface_t *target, + const cairo_clip_t *target_clip) +{ + return _cairo_recording_surface_replay_internal (surface, NULL, surface_transform, + target, target_clip, CAIRO_RECORDING_REPLAY, CAIRO_RECORDING_REGION_ALL); } @@ -1033,8 +1059,8 @@ cairo_status_t _cairo_recording_surface_replay_and_create_regions (cairo_surface_t *surface, cairo_surface_t *target) { - return _cairo_recording_surface_replay_internal (surface, NULL, - target, + return _cairo_recording_surface_replay_internal (surface, NULL, NULL, + target, NULL, CAIRO_RECORDING_CREATE_REGIONS, CAIRO_RECORDING_REGION_ALL); } @@ -1045,8 +1071,8 @@ _cairo_recording_surface_replay_region (cairo_surface_t *surface, cairo_surface_t *target, cairo_recording_region_type_t region) { - return _cairo_recording_surface_replay_internal (surface, surface_extents, - target, + return _cairo_recording_surface_replay_internal (surface, surface_extents, NULL, + target, NULL, CAIRO_RECORDING_REPLAY, region); } diff --git a/src/cairo-surface-wrapper-private.h b/src/cairo-surface-wrapper-private.h index b3d3a55ae..97ac8097a 100644 --- a/src/cairo-surface-wrapper-private.h +++ b/src/cairo-surface-wrapper-private.h @@ -46,8 +46,13 @@ CAIRO_BEGIN_DECLS struct _cairo_surface_wrapper { cairo_surface_t *target; + cairo_matrix_t transform; + cairo_bool_t has_extents; cairo_rectangle_int_t extents; + const cairo_clip_t *clip; + + cairo_bool_t needs_transform; }; cairo_private void @@ -59,6 +64,14 @@ _cairo_surface_wrapper_set_extents (cairo_surface_wrapper_t *wrapper, const cairo_rectangle_int_t *extents); cairo_private void +_cairo_surface_wrapper_set_inverse_transform (cairo_surface_wrapper_t *wrapper, + const cairo_matrix_t *transform); + +cairo_private void +_cairo_surface_wrapper_set_clip (cairo_surface_wrapper_t *wrapper, + const cairo_clip_t *clip); + +cairo_private void _cairo_surface_wrapper_fini (cairo_surface_wrapper_t *wrapper); cairo_private cairo_status_t diff --git a/src/cairo-surface-wrapper.c b/src/cairo-surface-wrapper.c index 9e746f9c6..8dc40f842 100644 --- a/src/cairo-surface-wrapper.c +++ b/src/cairo-surface-wrapper.c @@ -54,18 +54,6 @@ _copy_transformed_pattern (cairo_pattern_t *pattern, _cairo_pattern_transform (pattern, ctm_inverse); } -static inline cairo_bool_t -_cairo_surface_wrapper_needs_device_transform (cairo_surface_wrapper_t *wrapper) -{ - return ! _cairo_matrix_is_identity (&wrapper->target->device_transform); -} - -static cairo_bool_t -_cairo_surface_wrapper_needs_extents_transform (cairo_surface_wrapper_t *wrapper) -{ - return wrapper->has_extents && (wrapper->extents.x | wrapper->extents.y); -} - cairo_status_t _cairo_surface_wrapper_acquire_source_image (cairo_surface_wrapper_t *wrapper, cairo_image_surface_t **image_out, @@ -86,6 +74,24 @@ _cairo_surface_wrapper_release_source_image (cairo_surface_wrapper_t *wrapper, _cairo_surface_release_source_image (wrapper->target, image, image_extra); } +static void +_cairo_surface_wrapper_get_transform (cairo_surface_wrapper_t *wrapper, + cairo_matrix_t *m) +{ + cairo_matrix_init_identity (m); + + if (wrapper->has_extents && (wrapper->extents.x || wrapper->extents.y)) + cairo_matrix_translate (m, -wrapper->extents.x, -wrapper->extents.y); + + if (! _cairo_matrix_is_identity (&wrapper->transform)) + cairo_matrix_multiply (m, &wrapper->transform, m); + + + if (! _cairo_matrix_is_identity (&wrapper->target->device_transform)) + cairo_matrix_multiply (m, &wrapper->target->device_transform, m); +} + + cairo_status_t _cairo_surface_wrapper_paint (cairo_surface_wrapper_t *wrapper, cairo_operator_t op, @@ -108,21 +114,15 @@ _cairo_surface_wrapper_paint (cairo_surface_wrapper_t *wrapper, goto FINISH; } - if (_cairo_surface_wrapper_needs_device_transform (wrapper) || - _cairo_surface_wrapper_needs_extents_transform (wrapper)) - { + if (wrapper->needs_transform) { cairo_matrix_t m; - cairo_matrix_init_identity (&m); - - if (_cairo_surface_wrapper_needs_extents_transform (wrapper)) - cairo_matrix_translate (&m, -wrapper->extents.x, -wrapper->extents.y); - - if (_cairo_surface_wrapper_needs_device_transform (wrapper)) - cairo_matrix_multiply (&m, &wrapper->target->device_transform, &m); + _cairo_surface_wrapper_get_transform (wrapper, &m); /* XXX */ - dev_clip = _cairo_clip_copy_with_translation (clip, wrapper->extents.x, wrapper->extents.y); + dev_clip = _cairo_clip_copy_with_translation (dev_clip, + wrapper->extents.x, + wrapper->extents.y); status = cairo_matrix_invert (&m); assert (status == CAIRO_STATUS_SUCCESS); @@ -131,6 +131,9 @@ _cairo_surface_wrapper_paint (cairo_surface_wrapper_t *wrapper, source = &source_copy.base; } + if (wrapper->clip) + dev_clip = _cairo_clip_copy_intersect_clip (dev_clip, wrapper->clip); + status = _cairo_surface_paint (wrapper->target, op, source, dev_clip); FINISH: @@ -164,21 +167,14 @@ _cairo_surface_wrapper_mask (cairo_surface_wrapper_t *wrapper, goto FINISH; } - if (_cairo_surface_wrapper_needs_device_transform (wrapper) || - _cairo_surface_wrapper_needs_extents_transform (wrapper)) - { + if (wrapper->needs_transform) { cairo_matrix_t m; - cairo_matrix_init_identity (&m); - - if (_cairo_surface_wrapper_needs_extents_transform (wrapper)) - cairo_matrix_translate (&m, -wrapper->extents.x, -wrapper->extents.y); + _cairo_surface_wrapper_get_transform (wrapper, &m); - if (_cairo_surface_wrapper_needs_device_transform (wrapper)) - cairo_matrix_multiply (&m, &wrapper->target->device_transform, &m); - - /* XXX */ - dev_clip = _cairo_clip_copy_with_translation (clip, wrapper->extents.x, wrapper->extents.y); + dev_clip = _cairo_clip_copy_with_translation (dev_clip, + wrapper->extents.x, + wrapper->extents.y); status = cairo_matrix_invert (&m); assert (status == CAIRO_STATUS_SUCCESS); @@ -190,6 +186,9 @@ _cairo_surface_wrapper_mask (cairo_surface_wrapper_t *wrapper, mask = &mask_copy.base; } + if (wrapper->clip) + dev_clip = _cairo_clip_copy_intersect_clip (dev_clip, wrapper->clip); + status = _cairo_surface_mask (wrapper->target, op, source, mask, dev_clip); FINISH: @@ -230,18 +229,10 @@ _cairo_surface_wrapper_stroke (cairo_surface_wrapper_t *wrapper, goto FINISH; } - if (_cairo_surface_wrapper_needs_device_transform (wrapper) || - _cairo_surface_wrapper_needs_extents_transform (wrapper)) - { + if (wrapper->needs_transform) { cairo_matrix_t m; - cairo_matrix_init_identity (&m); - - if (_cairo_surface_wrapper_needs_extents_transform (wrapper)) - cairo_matrix_translate (&m, -wrapper->extents.x, -wrapper->extents.y); - - if (_cairo_surface_wrapper_needs_device_transform (wrapper)) - cairo_matrix_multiply (&m, &wrapper->target->device_transform, &m); + _cairo_surface_wrapper_get_transform (wrapper, &m); status = _cairo_path_fixed_init_copy (&path_copy, dev_path); if (unlikely (status)) @@ -251,7 +242,9 @@ _cairo_surface_wrapper_stroke (cairo_surface_wrapper_t *wrapper, dev_path = &path_copy; /* XXX */ - dev_clip = _cairo_clip_copy_with_translation (clip, wrapper->extents.x, wrapper->extents.y); + dev_clip = _cairo_clip_copy_with_translation (dev_clip, + wrapper->extents.x, + wrapper->extents.y); cairo_matrix_multiply (&dev_ctm, &dev_ctm, &m); @@ -264,6 +257,9 @@ _cairo_surface_wrapper_stroke (cairo_surface_wrapper_t *wrapper, source = &source_copy.base; } + if (wrapper->clip) + dev_clip = _cairo_clip_copy_intersect_clip (dev_clip, wrapper->clip); + status = _cairo_surface_stroke (wrapper->target, op, source, dev_path, stroke_style, &dev_ctm, &dev_ctm_inverse, @@ -316,18 +312,10 @@ _cairo_surface_wrapper_fill_stroke (cairo_surface_wrapper_t *wrapper, goto FINISH; } - if (_cairo_surface_wrapper_needs_device_transform (wrapper) || - _cairo_surface_wrapper_needs_extents_transform (wrapper)) - { + if (wrapper->needs_transform) { cairo_matrix_t m; - cairo_matrix_init_identity (&m); - - if (_cairo_surface_wrapper_needs_extents_transform (wrapper)) - cairo_matrix_translate (&m, -wrapper->extents.x, -wrapper->extents.y); - - if (_cairo_surface_wrapper_needs_device_transform (wrapper)) - cairo_matrix_multiply (&m, &wrapper->target->device_transform, &m); + _cairo_surface_wrapper_get_transform (wrapper, &m); status = _cairo_path_fixed_init_copy (&path_copy, dev_path); if (unlikely (status)) @@ -337,7 +325,9 @@ _cairo_surface_wrapper_fill_stroke (cairo_surface_wrapper_t *wrapper, dev_path = &path_copy; /* XXX */ - dev_clip = _cairo_clip_copy_with_translation (clip, wrapper->extents.x, wrapper->extents.y); + dev_clip = _cairo_clip_copy_with_translation (dev_clip, + wrapper->extents.x, + wrapper->extents.y); cairo_matrix_multiply (&dev_ctm, &dev_ctm, &m); @@ -353,6 +343,9 @@ _cairo_surface_wrapper_fill_stroke (cairo_surface_wrapper_t *wrapper, fill_source = &fill_source_copy.base; } + if (wrapper->clip) + dev_clip = _cairo_clip_copy_intersect_clip (dev_clip, wrapper->clip); + status = _cairo_surface_fill_stroke (wrapper->target, fill_op, fill_source, fill_rule, fill_tolerance, fill_antialias, @@ -399,18 +392,10 @@ _cairo_surface_wrapper_fill (cairo_surface_wrapper_t *wrapper, goto FINISH; } - if (_cairo_surface_wrapper_needs_device_transform (wrapper) || - _cairo_surface_wrapper_needs_extents_transform (wrapper)) - { + if (wrapper->needs_transform) { cairo_matrix_t m; - cairo_matrix_init_identity (&m); - - if (_cairo_surface_wrapper_needs_extents_transform (wrapper)) - cairo_matrix_translate (&m, -wrapper->extents.x, -wrapper->extents.y); - - if (_cairo_surface_wrapper_needs_device_transform (wrapper)) - cairo_matrix_multiply (&m, &wrapper->target->device_transform, &m); + _cairo_surface_wrapper_get_transform (wrapper, &m); status = _cairo_path_fixed_init_copy (&path_copy, dev_path); if (unlikely (status)) @@ -420,7 +405,9 @@ _cairo_surface_wrapper_fill (cairo_surface_wrapper_t *wrapper, dev_path = &path_copy; /* XXX */ - dev_clip = _cairo_clip_copy_with_translation (clip, wrapper->extents.x, wrapper->extents.y); + dev_clip = _cairo_clip_copy_with_translation (dev_clip, + wrapper->extents.x, + wrapper->extents.y); status = cairo_matrix_invert (&m); assert (status == CAIRO_STATUS_SUCCESS); @@ -429,6 +416,9 @@ _cairo_surface_wrapper_fill (cairo_surface_wrapper_t *wrapper, source = &source_copy.base; } + if (wrapper->clip) + dev_clip = _cairo_clip_copy_intersect_clip (dev_clip, wrapper->clip); + status = _cairo_surface_fill (wrapper->target, op, source, dev_path, fill_rule, tolerance, antialias, @@ -477,22 +467,16 @@ _cairo_surface_wrapper_show_text_glyphs (cairo_surface_wrapper_t *wrapper, goto FINISH; } - if (_cairo_surface_wrapper_needs_device_transform (wrapper) || - _cairo_surface_wrapper_needs_extents_transform (wrapper)) - { + if (wrapper->needs_transform) { cairo_matrix_t m; int i; - cairo_matrix_init_identity (&m); - - if (_cairo_surface_wrapper_needs_extents_transform (wrapper)) - cairo_matrix_translate (&m, -wrapper->extents.x, -wrapper->extents.y); - - if (_cairo_surface_wrapper_needs_device_transform (wrapper)) - cairo_matrix_multiply (&m, &wrapper->target->device_transform, &m); + _cairo_surface_wrapper_get_transform (wrapper, &m); /* XXX */ - dev_clip = _cairo_clip_copy_with_translation (clip, wrapper->extents.x, wrapper->extents.y); + dev_clip = _cairo_clip_copy_with_translation (dev_clip, + wrapper->extents.x, + wrapper->extents.y); dev_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t)); if (dev_glyphs == NULL) { @@ -512,6 +496,9 @@ _cairo_surface_wrapper_show_text_glyphs (cairo_surface_wrapper_t *wrapper, source = &source_copy.base; } + if (wrapper->clip) + dev_clip = _cairo_clip_copy_intersect_clip (dev_clip, wrapper->clip); + status = _cairo_surface_show_text_glyphs (wrapper->target, op, source, utf8, utf8_len, dev_glyphs, num_glyphs, @@ -555,6 +542,15 @@ _cairo_surface_wrapper_get_extents (cairo_surface_wrapper_t *wrapper, } } +static cairo_bool_t +_cairo_surface_wrapper_needs_device_transform (cairo_surface_wrapper_t *wrapper) +{ + return + (wrapper->has_extents && (wrapper->extents.x | wrapper->extents.y)) || + ! _cairo_matrix_is_identity (&wrapper->transform) || + ! _cairo_matrix_is_identity (&wrapper->target->device_transform); +} + void _cairo_surface_wrapper_set_extents (cairo_surface_wrapper_t *wrapper, const cairo_rectangle_int_t *extents) @@ -565,6 +561,38 @@ _cairo_surface_wrapper_set_extents (cairo_surface_wrapper_t *wrapper, } else { wrapper->has_extents = FALSE; } + + wrapper->needs_transform = + _cairo_surface_wrapper_needs_device_transform (wrapper); +} + +void +_cairo_surface_wrapper_set_inverse_transform (cairo_surface_wrapper_t *wrapper, + const cairo_matrix_t *transform) +{ + cairo_status_t status; + + if (transform == NULL || _cairo_matrix_is_identity (transform)) { + cairo_matrix_init_identity (&wrapper->transform); + + wrapper->needs_transform = + _cairo_surface_wrapper_needs_device_transform (wrapper); + } else { + wrapper->transform = *transform; + status = cairo_matrix_invert (&wrapper->transform); + /* should always be invertible unless given pathological input */ + assert (status == CAIRO_STATUS_SUCCESS); + + wrapper->needs_transform = TRUE; + } + +} + +void +_cairo_surface_wrapper_set_clip (cairo_surface_wrapper_t *wrapper, + const cairo_clip_t *clip) +{ + wrapper->clip = clip; } void @@ -590,8 +618,12 @@ void _cairo_surface_wrapper_init (cairo_surface_wrapper_t *wrapper, cairo_surface_t *target) { + _cairo_surface_wrapper_set_inverse_transform (wrapper, NULL); + wrapper->target = cairo_surface_reference (target); wrapper->has_extents = FALSE; + wrapper->needs_transform = + ! _cairo_matrix_is_identity (&wrapper->target->device_transform); } void |