[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