[cairo-commit] src/cairo-pattern.c src/cairo-surface.c src/cairo-surface-fallback.c
Vladimir Vukicevic
vladimir at kemper.freedesktop.org
Tue Aug 28 16:47:34 PDT 2007
src/cairo-pattern.c | 32 ------------------------
src/cairo-surface-fallback.c | 30 ++++++++++++----------
src/cairo-surface.c | 57 ++++++++++++++++++++++---------------------
3 files changed, 47 insertions(+), 72 deletions(-)
New commits:
diff-tree 93aee43690c329f43be9e7b840851267ceb17956 (from 6525d4debb6df67126b04609bb04d23d9c9bd7a6)
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date: Tue Aug 28 16:47:24 2007 -0700
Fix previous create_similar fallback patch
We can't use composite, as some backends don't implement it.
Use paint() instead.
diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index abda368..b75040b 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -1677,38 +1677,6 @@ _cairo_pattern_acquire_surface_for_surfa
status = _cairo_surface_clone_similar (dst, pattern->surface,
x, y, width, height, out);
-
- if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
-
- cairo_t *cr;
-
- *out = cairo_surface_create_similar (dst, dst->content,
- width, height);
- status = cairo_surface_status (*out);
- if (status) {
- cairo_surface_destroy (*out);
- *out = NULL;
- return status;
- }
-
- (*out)->device_transform = pattern->surface->device_transform;
- (*out)->device_transform_inverse = pattern->surface->device_transform_inverse;
-
- /* XXX Use _cairo_surface_composite directly */
- cr = cairo_create (*out);
-
- cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
- cairo_set_source_surface (cr, pattern->surface, -x, -y);
- cairo_paint (cr);
-
- status = cairo_status (cr);
- cairo_destroy (cr);
-
- if (status) {
- cairo_surface_destroy (*out);
- *out = NULL;
- }
- }
}
return status;
diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c
index 75b9f12..ab19d2c 100644
--- a/src/cairo-surface-fallback.c
+++ b/src/cairo-surface-fallback.c
@@ -1264,8 +1264,8 @@ _cairo_surface_fallback_clone_similar (c
cairo_surface_t **clone_out)
{
cairo_status_t status;
- cairo_pattern_union_t src_pattern;
cairo_surface_t *new_surface = NULL;
+ cairo_t *cr;
new_surface = _cairo_surface_create_similar_scratch (surface,
cairo_surface_get_content (src),
@@ -1273,18 +1273,22 @@ _cairo_surface_fallback_clone_similar (c
if (new_surface->status)
return new_surface->status;
- _cairo_pattern_init_for_surface (&src_pattern.surface, src);
-
- status = _cairo_surface_composite (CAIRO_OPERATOR_SOURCE,
- &src_pattern.base,
- NULL,
- new_surface,
- src_x, src_y,
- 0, 0,
- 0, 0,
- width, height);
-
- _cairo_pattern_fini (&src_pattern.base);
+ /* We have to copy these here, so that the coordinate spaces are correct */
+ new_surface->device_transform = src->device_transform;
+ new_surface->device_transform_inverse = src->device_transform_inverse;
+
+ /* We can't use _cairo_composite directly, because backends that
+ * implement the "high-level" API may not have it implemented.
+ * (For example, SVG.) We can fix this by either checking if the
+ * destination supports composite first, or we can make clone a
+ * required "high-level" operation.
+ */
+ cr = cairo_create (new_surface);
+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+ cairo_set_source_surface (cr, src, -src_x, -src_y);
+ cairo_paint (cr);
+ status = cairo_status (cr);
+ cairo_destroy (cr);
if (status == CAIRO_STATUS_SUCCESS)
*clone_out = new_surface;
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index a87b776..b44b853 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -1024,46 +1024,49 @@ _cairo_surface_clone_similar (cairo_surf
int height,
cairo_surface_t **clone_out)
{
- cairo_status_t status;
+ cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
cairo_image_surface_t *image;
void *image_extra;
if (surface->finished)
return CAIRO_STATUS_SURFACE_FINISHED;
- if (surface->backend->clone_similar == NULL)
- return (cairo_int_status_t)
- _cairo_surface_fallback_clone_similar (surface, src,
- src_x, src_y,
- width, height,
- clone_out);
-
- status = surface->backend->clone_similar (surface, src, src_x, src_y,
- width, height, clone_out);
- if (status == CAIRO_STATUS_SUCCESS && *clone_out != src)
- (*clone_out)->device_transform = src->device_transform;
+ if (surface->backend->clone_similar) {
+ status = surface->backend->clone_similar (surface, src, src_x, src_y,
+ width, height, clone_out);
+
+ if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
+ /* If we failed, try again with an image surface */
+ status = _cairo_surface_acquire_source_image (src, &image, &image_extra);
+ if (status == CAIRO_STATUS_SUCCESS) {
+ status =
+ surface->backend->clone_similar (surface, &image->base,
+ src_x, src_y,
+ width, height,
+ clone_out);
- if (status != CAIRO_INT_STATUS_UNSUPPORTED)
- return status;
+ _cairo_surface_release_source_image (src, image, image_extra);
+ }
+ }
+ }
- status = _cairo_surface_acquire_source_image (src, &image, &image_extra);
- if (status != CAIRO_STATUS_SUCCESS)
+ /* If we're still unsupported, hit our fallback path to get a clone */
+ if (status == CAIRO_INT_STATUS_UNSUPPORTED)
+ status =
+ _cairo_surface_fallback_clone_similar (surface, src, src_x, src_y,
+ width, height, clone_out);
+
+ /* We should never get UNSUPPORTED here, so if we have an error, bail. */
+ if (status)
return status;
- status = surface->backend->clone_similar (surface, &image->base, src_x,
- src_y, width, height, clone_out);
- if (status == CAIRO_STATUS_SUCCESS && *clone_out != src) {
+ /* Update the clone's device_transform (which the underlying surface
+ * backend knows nothing about) */
+ if (*clone_out != src) {
(*clone_out)->device_transform = src->device_transform;
(*clone_out)->device_transform_inverse = src->device_transform_inverse;
- }
-
- /* If the above failed point, we could implement a full fallback
- * using acquire_dest_image, but that's going to be very
- * inefficient compared to a backend-specific implementation of
- * clone_similar() with an image source. So we don't bother
- */
+ }
- _cairo_surface_release_source_image (src, image, image_extra);
return status;
}
More information about the cairo-commit
mailing list