summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cairo-clip-boxes.c17
-rw-r--r--src/cairo-clip-private.h15
-rw-r--r--src/cairo-clip.c67
-rw-r--r--src/cairo-image-surface.c64
-rw-r--r--src/cairo-recording-surface-private.h6
-rw-r--r--src/cairo-recording-surface.c68
-rw-r--r--src/cairo-surface-wrapper-private.h13
-rw-r--r--src/cairo-surface-wrapper.c190
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