[cairo-commit] cairo/src cairo_image_surface.c, 1.22, 1.23 cairo_pattern.c, 1.17, 1.18 cairo_pdf_surface.c, 1.10, 1.11 cairo_png_surface.c, 1.13, 1.14 cairo_ps_surface.c, 1.20, 1.21 cairo_surface.c, 1.38, 1.39 cairo_xlib_surface.c, 1.42, 1.43 cairoint.h, 1.91, 1.92

Owen Taylor commit at pdx.freedesktop.org
Mon Jan 31 08:50:24 PST 2005


Committed by: otaylor

Update of /cvs/cairo/cairo/src
In directory gabe:/tmp/cvs-serv20332/src

Modified Files:
	cairo_image_surface.c cairo_pattern.c cairo_pdf_surface.c 
	cairo_png_surface.c cairo_ps_surface.c cairo_surface.c 
	cairo_xlib_surface.c cairoint.h 
Log Message:
2005-01-31  Owen Taylor  <otaylor at redhat.com>

        * src/cairoint.h src/cairo_image_surface.c
        src/cairo_pdf_surface.c src/cairo_png_surface.c
        src/cairo_surface.c src/cairo_xlib_surface.c: Replace
        the get_image()/set_image() backend operations with
        a more specific {acquire,release}_{source,dest}_image()
        and clone_similar().

        * src/cairoint.h src/cairo_pattern.c: Replace
        _cairo_pattern_get_surface() with a
        _cairo_pattern_begin_draw()/_cairo_pattern_end_draw() pair.

        * src/cairo_image_surface.c: Save the format for which
        an image is created so we can access it later. (Needed
        for the _cairo_xlib_surface_clone_similar())

        * src/cairoint.h src/cairo_image_surface.c:
        Add _cairo_surface_is_image().

        * src/cairoint.h: Add CAIRO_OK(status) to check
        for CAIRO_STATUS_SUCCESS.

        * src/cairo_xlib_surface.c: In the absence of of
        RENDER, make cairo_xlib_surface_create_similar()
        return an image surface.

        * src/cairo_xlib_surface.c: Don't try to use RENDER
        to composite glyphs in the absence of the RENDER
        extension.


Index: cairo_image_surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo_image_surface.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -d -r1.22 -r1.23
--- cairo_image_surface.c	28 Jan 2005 03:57:32 -0000	1.22
+++ cairo_image_surface.c	31 Jan 2005 16:50:22 -0000	1.23
@@ -54,7 +54,8 @@
 }
 
 static cairo_image_surface_t *
-_cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image)
+_cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image,
+					      cairo_format_t  format)
 {
     cairo_image_surface_t *surface;
 
@@ -66,6 +67,7 @@
 
     surface->pixman_image = pixman_image;
 
+    surface->format = format;
     surface->data = (char *) pixman_image_get_data (pixman_image);
     surface->owns_data = 0;
 
@@ -105,7 +107,8 @@
     if (pixman_image == NULL)
 	return NULL;
 
-    surface = _cairo_image_surface_create_for_pixman_image (pixman_image);
+    surface = _cairo_image_surface_create_for_pixman_image (pixman_image,
+							    (cairo_format_t)-1);
 
     return surface;
 }
@@ -150,7 +153,7 @@
     if (pixman_image == NULL)
 	return NULL;
 
-    surface = _cairo_image_surface_create_for_pixman_image (pixman_image);
+    surface = _cairo_image_surface_create_for_pixman_image (pixman_image, format);
 
     return &surface->base;
 }
@@ -180,7 +183,7 @@
     if (pixman_image == NULL)
 	return NULL;
 
-    surface = _cairo_image_surface_create_for_pixman_image (pixman_image);
+    surface = _cairo_image_surface_create_for_pixman_image (pixman_image, format);
 
     return &surface->base;
 }
@@ -224,25 +227,66 @@
     return 96.0;
 }
 
-static cairo_image_surface_t *
-_cairo_image_surface_get_image (void *abstract_surface)
+static cairo_status_t
+_cairo_image_surface_acquire_source_image (void                    *abstract_surface,
+					   cairo_image_surface_t  **image_out,
+					   void                   **image_extra)
+{
+    *image_out = abstract_surface;
+    
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+_cairo_image_surface_release_source_image (void                   *abstract_surface,
+					   cairo_image_surface_t  *image,
+					   void                   *image_extra)
+{
+}
+
+static cairo_status_t
+_cairo_image_surface_acquire_dest_image (void                    *abstract_surface,
+					 cairo_rectangle_t       *interest_rect,
+					 cairo_image_surface_t  **image_out,
+					 cairo_rectangle_t       *image_rect_out,
+					 void                   **image_extra)
 {
     cairo_image_surface_t *surface = abstract_surface;
+    
+    image_rect_out->x = 0;
+    image_rect_out->y = 0;
+    image_rect_out->width = surface->width;
+    image_rect_out->height = surface->height;
 
-    cairo_surface_reference (&surface->base);
+    *image_out = surface;
 
-    return surface;
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+_cairo_image_surface_release_dest_image (void                   *abstract_surface,
+					 cairo_rectangle_t      *interest_rect,
+					 cairo_image_surface_t  *image,
+					 cairo_rectangle_t      *image_rect,
+					 void                   *image_extra)
+{
 }
 
 static cairo_status_t
-_cairo_image_surface_set_image (void			*abstract_surface,
-				cairo_image_surface_t	*image)
+_cairo_image_surface_clone_similar (void		*abstract_surface,
+				    cairo_surface_t	*src,
+				    cairo_surface_t    **clone_out)
 {
-    if (image == abstract_surface)
-	return CAIRO_STATUS_SUCCESS;
+    cairo_image_surface_t *surface = abstract_surface;
 
-    /* XXX: This case has not yet been implemented. We'll lie for now. */
-    return CAIRO_STATUS_SUCCESS;
+    if (src->backend == surface->base.backend) {
+	*clone_out = src;
+	cairo_surface_reference (src);
+
+	return CAIRO_STATUS_SUCCESS;
+    }	
+    
+    return CAIRO_INT_STATUS_UNSUPPORTED;
 }
 
 static cairo_status_t
@@ -382,30 +426,40 @@
 {
     cairo_image_surface_t *dst = abstract_dst;
     cairo_image_surface_t *src;
-    cairo_image_surface_t *mask = (cairo_image_surface_t *) generic_mask;
-    int x_offset, y_offset;
+    cairo_image_surface_t *mask = NULL;
+    void *mask_extra;
+    cairo_pattern_info_t pattern_info;
+    cairo_status_t status;
 
-    src = (cairo_image_surface_t *)
-	_cairo_pattern_get_surface (pattern, &dst->base,
-				    src_x, src_y, width, height,
-				    &x_offset, &y_offset);
-    if (src == NULL)
-	return CAIRO_STATUS_NO_MEMORY; /* Or not supported? */
+    status = _cairo_pattern_begin_draw (pattern, &pattern_info,
+					&dst->base,
+					src_x, src_y, width, height);
+    if (!CAIRO_OK (status))
+	return status;
 
-    if (generic_mask && (generic_mask->backend != dst->base.backend))
-	return CAIRO_INT_STATUS_UNSUPPORTED;
+    src = (cairo_image_surface_t *)pattern_info.src;
+
+    /* XXX This stuff can go when we change the mask to be a pattern also. */
+    if (generic_mask) {
+	status = _cairo_surface_acquire_source_image (generic_mask, &mask, &mask_extra);
+	if (!CAIRO_OK (status))
+	    goto FAIL;
+    }
 
     pixman_composite (_pixman_operator (operator),
 		      src->pixman_image,
 		      mask ? mask->pixman_image : NULL,
 		      dst->pixman_image,
-		      src_x - x_offset, src_y - y_offset,
+		      src_x - pattern_info.x_offset, src_y - pattern_info.y_offset,
 		      mask_x, mask_y,
 		      dst_x, dst_y,
 		      width, height);
 
-    cairo_surface_destroy (&src->base);
-
+    if (mask)
+	_cairo_surface_release_source_image (generic_mask, mask, mask_extra);
+ FAIL:
+    _cairo_pattern_end_draw (pattern, &pattern_info);
+    
     return CAIRO_STATUS_SUCCESS;
 }
 
@@ -447,19 +501,18 @@
 {
     cairo_image_surface_t *dst = abstract_dst;
     cairo_image_surface_t *src;
-    int x_offset, y_offset;
+    cairo_pattern_info_t pattern_info;
     int render_reference_x, render_reference_y;
     int render_src_x, render_src_y;
+    cairo_status_t status;
 
-    src = (cairo_image_surface_t *)
-	_cairo_pattern_get_surface (pattern, &dst->base,
-				    src_x, src_y,
-				    width, height,
-				    &x_offset, &y_offset);
-    if (src == NULL)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
+    status = _cairo_pattern_begin_draw (pattern, &pattern_info,
+					&dst->base,
+					src_x, src_y, width, height);
+    if (!CAIRO_OK (status))
+	return status;
 
-    _cairo_pattern_prepare_surface (pattern, &src->base);
+    src = (cairo_image_surface_t *)pattern_info.src;
 
     if (traps[0].left.p1.y < traps[0].left.p2.y) {
 	render_reference_x = _cairo_fixed_integer_floor (traps[0].left.p1.x);
@@ -477,13 +530,11 @@
     pixman_composite_trapezoids (operator,
 				 src->pixman_image,
 				 dst->pixman_image,
-				 render_src_x - x_offset,
-				 render_src_y - y_offset,
+				 render_src_x - pattern_info.x_offset,
+				 render_src_y - pattern_info.y_offset,
 				 (pixman_trapezoid_t *) traps, num_traps);
 
-    _cairo_pattern_restore_surface (pattern, &src->base);
-
-    cairo_surface_destroy (&src->base);
+    _cairo_pattern_end_draw (pattern, &pattern_info);
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -530,13 +581,30 @@
 
     return CAIRO_STATUS_SUCCESS;
 }
-  
+
+/**
+ * _cairo_surface_is_image:
+ * @surface: a #cairo_surface_t
+ * 
+ * Checks if a surface is an #cairo_image_surface_t
+ * 
+ * Return value: True if the surface is an image surface
+ **/
+int
+_cairo_surface_is_image (cairo_surface_t *surface)
+{
+    return surface->backend == &cairo_image_surface_backend;
+}
+
 static const cairo_surface_backend_t cairo_image_surface_backend = {
     _cairo_image_surface_create_similar,
     _cairo_image_abstract_surface_destroy,
     _cairo_image_surface_pixels_per_inch,
-    _cairo_image_surface_get_image,
-    _cairo_image_surface_set_image,
+    _cairo_image_surface_acquire_source_image,
+    _cairo_image_surface_release_source_image,
+    _cairo_image_surface_acquire_dest_image,
+    _cairo_image_surface_release_dest_image,
+    _cairo_image_surface_clone_similar,
     _cairo_image_abstract_surface_set_matrix,
     _cairo_image_abstract_surface_set_filter,
     _cairo_image_abstract_surface_set_repeat,

Index: cairo_pattern.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo_pattern.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -d -r1.17 -r1.18
--- cairo_pattern.c	30 Jan 2005 19:28:14 -0000	1.17
+++ cairo_pattern.c	31 Jan 2005 16:50:22 -0000	1.18
@@ -670,164 +670,246 @@
 	}
     }
 }
- 
-cairo_surface_t *
-_cairo_pattern_get_surface (cairo_pattern_t	*pattern,
-			    cairo_surface_t	*dst,			    
-			    int			x,
-			    int			y,
-			    unsigned int	width,
-			    unsigned int	height,
-			    int			*x_offset,
-			    int			*y_offset)
+
+static cairo_status_t
+_cairo_pattern_begin_draw_gradient (cairo_pattern_t	*pattern,
+				    cairo_pattern_info_t *info,
+				    cairo_surface_t	*dst,
+				    int			 x,
+				    int			 y,
+				    unsigned int	 width,
+				    unsigned int	 height)
 {
-    cairo_surface_t *surface, *src;
     cairo_image_surface_t *image;
     cairo_status_t status;
     char *data;
+    
+    data = malloc (width * height * 4);
+    if (!data)
+	return CAIRO_STATUS_NO_MEMORY;
+    
+    if (pattern->type == CAIRO_PATTERN_RADIAL)
+	_cairo_image_data_set_radial (pattern, x, y, (int *) data,
+				      width, height);
+    else
+	_cairo_image_data_set_linear (pattern, x, y, (int *) data,
+				      width, height);
 
-    *x_offset = 0;
-    *y_offset = 0;
-
-    switch (pattern->type) {
-    case CAIRO_PATTERN_LINEAR:
-    case CAIRO_PATTERN_RADIAL:
-	data = malloc (width * height * 4);
-	if (!data)
-	    return NULL;
-	
-	if (pattern->type == CAIRO_PATTERN_RADIAL)
-	    _cairo_image_data_set_radial (pattern, x, y, (int *) data,
-					  width, height);
-	else
-	    _cairo_image_data_set_linear (pattern, x, y, (int *) data,
-					  width, height);
+    info->x_offset = x;
+    info->y_offset = y;
 
-	*x_offset = x;
-	*y_offset = y;
+    image = (cairo_image_surface_t *)
+	cairo_image_surface_create_for_data (data,
+					     CAIRO_FORMAT_ARGB32,
+					     width, height,
+					     width * 4);
+    
+    if (image == NULL) {
+	free (data);
+	return CAIRO_STATUS_NO_MEMORY;
+    }
 
-	image = (cairo_image_surface_t *)
-	    cairo_image_surface_create_for_data (data,
-						 CAIRO_FORMAT_ARGB32,
-						 width, height,
-						 width * 4);
+    _cairo_image_surface_assume_ownership_of_data (image);
+    
+    status = _cairo_surface_clone_similar (dst, &image->base, &info->src);
+    info->acquired = 0;
 	
-	if (image == NULL) {
-	    free (data);
-	    return NULL;
-	}
-
-	_cairo_image_surface_assume_ownership_of_data (image);
-	if (image->base.backend == dst->backend)
-	    return &image->base;
-
-	surface = cairo_surface_create_similar (dst,
-						CAIRO_FORMAT_ARGB32,
-						width, height);
-	if (surface == NULL) {
-	    cairo_surface_destroy (&image->base);
-	    return NULL;
-	}
-
-	_cairo_surface_set_image (surface, image);
-	cairo_surface_destroy (&image->base);
-
-	return surface;
-
-    case CAIRO_PATTERN_SOLID:
-	surface = _cairo_surface_create_similar_solid (dst,
-						       CAIRO_FORMAT_ARGB32,
-						       1, 1,
-						       &pattern->color);
-	if (surface == NULL)
-	    return NULL;
-
-	cairo_surface_set_repeat (surface, 1);
-	return surface;
-
-    case CAIRO_PATTERN_SURFACE:
-	/* handle pattern opacity */
-	if (pattern->color.alpha != 1.0) {
-	    cairo_surface_t *alpha_surface;
-	    double save_alpha;
-	    int save_repeat;
+    cairo_surface_destroy (&image->base);
+    
+    return status;
+}
 
-	    surface = cairo_surface_create_similar (dst,
-						    CAIRO_FORMAT_ARGB32,
-						    width, height);
-	    if (surface == NULL)
-		return NULL;
+static cairo_status_t
+_cairo_pattern_begin_draw_solid (cairo_pattern_t      *pattern,
+				 cairo_pattern_info_t *info,
+				 cairo_surface_t      *dst,
+				 int		       x,
+				 int		       y,
+				 unsigned int	       width,
+				 unsigned int	       height)
+{
+    info->x_offset = 0;
+    info->y_offset = 0;
 
-	    alpha_surface =
-		_cairo_surface_create_similar_solid (surface,
-						     CAIRO_FORMAT_A8,
+    info->src = _cairo_surface_create_similar_solid (dst,
+						     CAIRO_FORMAT_ARGB32,
 						     1, 1,
 						     &pattern->color);
-	    if (alpha_surface == NULL) {
-		cairo_surface_destroy (surface);
-		return NULL;
-	    }
-
-	    cairo_surface_set_repeat (alpha_surface, 1);
-
-	    save_repeat = pattern->u.surface.surface->repeat;
-	    if (pattern->extend == CAIRO_EXTEND_REPEAT ||
-		pattern->u.surface.surface->repeat == 1)
-		cairo_surface_set_repeat (pattern->u.surface.surface, 1);
-	    else
-		cairo_surface_set_repeat (pattern->u.surface.surface, 0);
-
-	    save_alpha = pattern->color.alpha;
-	    pattern->color.alpha = 1.0;
+    info->acquired = 0;
+    
+    if (info->src == NULL)
+	return CAIRO_STATUS_NO_MEMORY;
 
-	    status = _cairo_surface_composite (CAIRO_OPERATOR_OVER,
-					       pattern,
-					       alpha_surface,
-					       surface,
-					       x, y, 0, 0, 0, 0,
-					       width, height);
+    cairo_surface_set_repeat (info->src, 1);
+    
+    return CAIRO_STATUS_SUCCESS;
+}
 
-	    pattern->color.alpha = save_alpha;
+static cairo_status_t
+_cairo_pattern_begin_draw_surface (cairo_pattern_t      *pattern,
+				   cairo_pattern_info_t *info,
+				   cairo_surface_t      *dst,
+				   int		         x,
+				   int		         y,
+				   unsigned int	         width,
+				   unsigned int	         height)
+{
+    cairo_surface_t *surface;
+    cairo_status_t status;
 
-	    cairo_surface_set_repeat (pattern->u.surface.surface,
-				      save_repeat);
-            
-	    cairo_surface_destroy (alpha_surface);
+    /* handle pattern opacity */
+    if (pattern->color.alpha != 1.0) {
+	cairo_surface_t *alpha_surface;
+	double save_alpha;
+	int save_repeat;
+	
+	surface = cairo_surface_create_similar (dst,
+						CAIRO_FORMAT_ARGB32,
+						width, height);
+	if (surface == NULL)
+	    return CAIRO_STATUS_NO_MEMORY;
+	
+	alpha_surface =
+	    _cairo_surface_create_similar_solid (surface,
+						 CAIRO_FORMAT_A8,
+						 1, 1,
+						 &pattern->color);
+	if (alpha_surface == NULL) {
+	    cairo_surface_destroy (surface);
+	    return CAIRO_STATUS_NO_MEMORY;
+	}
+	
+	cairo_surface_set_repeat (alpha_surface, 1);
+	
+	save_repeat = pattern->u.surface.surface->repeat;
+	if (pattern->extend == CAIRO_EXTEND_REPEAT ||
+	    pattern->u.surface.surface->repeat == 1)
+	    cairo_surface_set_repeat (pattern->u.surface.surface, 1);
+	else
+	    cairo_surface_set_repeat (pattern->u.surface.surface, 0);
+	
+	save_alpha = pattern->color.alpha;
+	pattern->color.alpha = 1.0;
+	
+	status = _cairo_surface_composite (CAIRO_OPERATOR_OVER,
+					   pattern,
+					   alpha_surface,
+					   surface,
+					   x, y, 0, 0, 0, 0,
+					   width, height);
+	
+	pattern->color.alpha = save_alpha;
+	
+	cairo_surface_set_repeat (pattern->u.surface.surface,
+				  save_repeat);
+	
+	cairo_surface_destroy (alpha_surface);
 
-	    if (status == CAIRO_STATUS_SUCCESS) {
-		*x_offset = x;
-		*y_offset = y;
-		return surface;
-	    }
-	    else {
-		cairo_surface_destroy (surface);
-		return NULL;
-	    }
+	if (status == CAIRO_STATUS_SUCCESS) {
+	    info->src = surface;
+	    info->acquired = 0;
+	    info->x_offset = x;
+	    info->y_offset = y;
 	} else {
-	    src = pattern->u.surface.surface;
-	    if (src->backend == dst->backend) {
-		cairo_surface_reference (src);
-		return src;
+	    cairo_surface_destroy (surface);
+	}
+	
+	return status;
+    } else {
+	if (_cairo_surface_is_image (dst)) {
+	    cairo_image_surface_t *image;
+	    
+	    status = _cairo_surface_acquire_source_image (pattern->u.surface.surface,
+							  &image, &info->extra);
+	    if (CAIRO_OK (status)) {
+		info->src = &image->base;
+		info->acquired = 1;
+		info->x_offset = 0;
+		info->y_offset = 0;
 	    }
-
-	    image = _cairo_surface_get_image (src);
 	    
-	    surface = cairo_surface_create_similar (dst,
-						    CAIRO_FORMAT_ARGB32,
-						    image->width, image->height);
-	    if (surface == NULL)
-		return NULL;
-
-	    cairo_surface_set_filter (surface, cairo_surface_get_filter(src));
-	    _cairo_surface_set_image (surface, image);
-	    cairo_surface_set_matrix (surface, &(image->base.matrix));
-	    cairo_surface_set_repeat (surface, image->base.repeat);
-	    cairo_surface_destroy (&image->base);
+	    return status;
+	} else {
+	    status = _cairo_surface_clone_similar (dst, pattern->u.surface.surface,
+						   &info->src);
+	    info->acquired = 0;
+	    info->x_offset = 0;
+	    info->y_offset = 0;
 
-	    return surface;
+	    return status;
 	}
+    }
+}
 
+/**
+ * _cairo_pattern_begin_draw:
+ * @pattern: a #cairo_pattern_t
+ * @info: a structure to fill in with information about the drawing operation
+ * @dst: destination surface
+ * @x: X coordinate in source corresponding to left side of destination area
+ * @y: Y coordinate in source corresponding to top side of destination area
+ * @width: width and height of destination area
+ * @height: height of destination area
+ * 
+ * A convenience function to obtain a surface (stored in @info->src) to use as
+ * the source for drawing on @dst. If the pattern contains a surface and that
+ * surface is being used directly, it's attributes may be temporarily modified
+ * to match the pattern.
+ * 
+ * Return value: %CAIRO_STATUS_SUCCESS on success. Otherwise an error such
+ *  as CAIRO_STATUS_NO_MEMORY or CAIRO_INT_STATUS_UNSUPPORTED.
+ **/
+cairo_status_t
+_cairo_pattern_begin_draw (cairo_pattern_t	*pattern,
+			   cairo_pattern_info_t *info,
+			   cairo_surface_t	*dst,
+			   int			 x,
+			   int			 y,
+			   unsigned int	 	 width,
+			   unsigned int	         height)
+{
+    cairo_status_t status;
+    
+    switch (pattern->type) {
+    case CAIRO_PATTERN_LINEAR:
+    case CAIRO_PATTERN_RADIAL:
+	status = _cairo_pattern_begin_draw_gradient (pattern, info, dst, x, y, width, height);
+	break;
+    case CAIRO_PATTERN_SOLID:
+	status = _cairo_pattern_begin_draw_solid (pattern, info, dst, x, y, width, height);
+	break;
+    case CAIRO_PATTERN_SURFACE:
+	status = _cairo_pattern_begin_draw_surface (pattern, info, dst, x, y, width, height);
+	break;
     default:
-	return NULL;
+	return CAIRO_INT_STATUS_UNSUPPORTED;
     }
+
+    if (CAIRO_OK (status))
+	_cairo_pattern_prepare_surface (pattern, info->src);
+
+    return status;
+}
+
+/**
+ * _cairo_pattern_end_draw:
+ * @pattern: a #cairo_pattern_t
+ * @info: pointer to #cairo_pattern_info_t filled in by
+ *        _cairo_pattern_begin_draw
+ * 
+ * Releases resources obtained by _cairo_pattern_begin_draw() and restores
+ * the pattern to its original form.
+ **/
+void
+_cairo_pattern_end_draw (cairo_pattern_t      *pattern,
+			 cairo_pattern_info_t *info)
+{
+    _cairo_pattern_restore_surface (pattern, info->src);
+
+    if (info->acquired)
+	_cairo_surface_release_source_image (pattern->u.surface.surface,
+					     (cairo_image_surface_t *)info->src,
+					     info->extra);
+    else
+	cairo_surface_destroy (info->src);
 }

Index: cairo_pdf_surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo_pdf_surface.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- cairo_pdf_surface.c	27 Jan 2005 18:46:20 -0000	1.10
+++ cairo_pdf_surface.c	31 Jan 2005 16:50:22 -0000	1.11
@@ -1098,15 +1098,44 @@
     }
 }
 
-static cairo_image_surface_t *
-_cairo_pdf_surface_get_image (void *abstract_surface)
+static cairo_status_t
+_cairo_pdf_surface_acquire_source_image (void                    *abstract_surface,
+					 cairo_image_surface_t  **image_out,
+					 void                   **image_extra)
+{
+    return CAIRO_INT_STATUS_UNSUPPORTED;
+}
+
+static void
+_cairo_pdf_surface_release_source_image (void                   *abstract_surface,
+					 cairo_image_surface_t  *image,
+					 void                   *image_extra)
 {
-    return NULL;
 }
 
 static cairo_status_t
-_cairo_pdf_surface_set_image (void			*abstract_surface,
-			      cairo_image_surface_t	*image)
+_cairo_pdf_surface_acquire_dest_image (void                    *abstract_surface,
+				       cairo_rectangle_t       *interest_rect,
+				       cairo_image_surface_t  **image_out,
+				       cairo_rectangle_t       *image_rect,
+				       void                   **image_extra)
+{
+    return CAIRO_INT_STATUS_UNSUPPORTED;
+}
+
+static void
+_cairo_pdf_surface_release_dest_image (void                   *abstract_surface,
+				       cairo_rectangle_t      *interest_rect,
+				       cairo_image_surface_t  *image,
+				       cairo_rectangle_t      *image_rect,
+				       void                   *image_extra)
+{
+}
+
+static cairo_status_t
+_cairo_pdf_surface_clone_similar (void			*abstract_surface,
+				  cairo_surface_t	*src,
+				  cairo_surface_t     **clone_out)
 {
     return CAIRO_INT_STATUS_UNSUPPORTED;
 }
@@ -1303,20 +1332,29 @@
 			      unsigned int	height)
 {
     cairo_pdf_surface_t *dst = abstract_dst;
-    cairo_pdf_surface_t *src;
-    cairo_image_surface_t *image;
+    cairo_surface_t *src;
 
     if (pattern->type != CAIRO_PATTERN_SURFACE)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
-    src = (cairo_pdf_surface_t *) pattern->u.surface.surface;
+    src = pattern->u.surface.surface;
 
-    if (src->base.backend == &cairo_pdf_surface_backend) {
-	return _cairo_pdf_surface_composite_pdf (dst, src, width, height);
+    if (src->backend == &cairo_pdf_surface_backend) {
+	return _cairo_pdf_surface_composite_pdf (dst,
+						 (cairo_pdf_surface_t *)src,
+						 width, height);
     }
     else {
-	image = _cairo_surface_get_image (&src->base);
-	return _cairo_pdf_surface_composite_image (dst, image);
+	cairo_status_t status;
+	cairo_image_surface_t *image;
+	void *image_extra;
+
+	status = _cairo_surface_acquire_source_image (src, &image, &image_extra);
+	if (!CAIRO_OK (status))
+	    return status;
+	status = _cairo_pdf_surface_composite_image (dst, image);
+	_cairo_surface_release_source_image (src, image, image_extra);
+	return status;
     }
 }
 
@@ -1357,6 +1395,8 @@
     FILE *file = document->file;
     cairo_pdf_stream_t *stream;
     cairo_image_surface_t *image;
+    void *image_extra;
+    cairo_status_t status;
     char entries[250];
     unsigned int id, alpha;
     cairo_matrix_t pm;
@@ -1364,8 +1404,10 @@
     if (pattern->u.surface.surface->backend == &cairo_pdf_surface_backend) {
 	return;
     }
-    
-    image = _cairo_surface_get_image (pattern->u.surface.surface);
+
+    status = _cairo_surface_acquire_source_image (pattern->u.surface.surface, &image, &image_extra);
+    if (!CAIRO_OK (status))
+	return;
 
     _cairo_pdf_document_close_stream (document);
 
@@ -1402,6 +1444,8 @@
     fprintf (file,
 	     "/Pattern cs /res%d scn /a%d gs\r\n",
 	     stream->id, alpha);
+
+    _cairo_surface_release_source_image (pattern->u.surface.surface, image, image_extra);
 }
 
 static unsigned int
@@ -1750,8 +1794,11 @@
     _cairo_pdf_surface_create_similar,
     _cairo_pdf_surface_destroy,
     _cairo_pdf_surface_pixels_per_inch,
-    _cairo_pdf_surface_get_image,
-    _cairo_pdf_surface_set_image,
+    _cairo_pdf_surface_acquire_source_image,
+    _cairo_pdf_surface_release_source_image,
+    _cairo_pdf_surface_acquire_dest_image,
+    _cairo_pdf_surface_release_dest_image,
+    _cairo_pdf_surface_clone_similar,
     _cairo_pdf_surface_set_matrix,
     _cairo_pdf_surface_set_filter,
     _cairo_pdf_surface_set_repeat,

Index: cairo_png_surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo_png_surface.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- cairo_png_surface.c	28 Jan 2005 20:27:23 -0000	1.13
+++ cairo_png_surface.c	31 Jan 2005 16:50:22 -0000	1.14
@@ -185,28 +185,58 @@
     return 96.0;
 }
 
-static cairo_image_surface_t *
-_cairo_png_surface_get_image (void *abstract_surface)
+static cairo_status_t
+_cairo_png_surface_acquire_source_image (void                    *abstract_surface,
+					 cairo_image_surface_t  **image_out,
+					 void                   **image_extra)
 {
     cairo_png_surface_t *surface = abstract_surface;
+    
+    *image_out = surface->image;
 
-    cairo_surface_reference (&surface->image->base);
+    return CAIRO_STATUS_SUCCESS;
+}
 
-    return surface->image;
+static void
+_cairo_png_surface_release_source_image (void                   *abstract_surface,
+					 cairo_image_surface_t  *image,
+					 void                   *image_extra)
+{
 }
 
 static cairo_status_t
-_cairo_png_surface_set_image (void			*abstract_surface,
-			      cairo_image_surface_t	*image)
+_cairo_png_surface_acquire_dest_image (void                    *abstract_surface,
+				       cairo_rectangle_t       *interest_rect,
+				       cairo_image_surface_t  **image_out,
+				       cairo_rectangle_t       *image_rect,
+				       void                   **image_extra)
 {
     cairo_png_surface_t *surface = abstract_surface;
+    
+    image_rect->x = 0;
+    image_rect->y = 0;
+    image_rect->width = surface->image->width;
+    image_rect->height = surface->image->height;
+    
+    *image_out = surface->image;
 
-    if (image == surface->image)
-	return CAIRO_STATUS_SUCCESS;
+    return CAIRO_STATUS_SUCCESS;
+}
 
-    /* XXX: Need to call _cairo_image_surface_set_image here, but it's
-       not implemented yet. */
+static void
+_cairo_png_surface_release_dest_image (void                   *abstract_surface,
+				       cairo_rectangle_t      *interest_rect,
+				       cairo_image_surface_t  *image,
+				       cairo_rectangle_t      *image_rect,
+				       void                   *image_extra)
+{
+}
 
+static cairo_status_t
+_cairo_png_surface_clone_similar (void			*abstract_surface,
+				  cairo_surface_t	*src,
+				  cairo_surface_t     **clone_out)
+{
     return CAIRO_INT_STATUS_UNSUPPORTED;
 }
 
@@ -405,8 +435,11 @@
     _cairo_png_surface_create_similar,
     _cairo_png_surface_destroy,
     _cairo_png_surface_pixels_per_inch,
-    _cairo_png_surface_get_image,
-    _cairo_png_surface_set_image,
+    _cairo_png_surface_acquire_source_image,
+    _cairo_png_surface_release_source_image,
+    _cairo_png_surface_acquire_dest_image,
+    _cairo_png_surface_release_dest_image,
+    _cairo_png_surface_clone_similar,
     _cairo_png_surface_set_matrix,
     _cairo_png_surface_set_filter,
     _cairo_png_surface_set_repeat,

Index: cairo_ps_surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo_ps_surface.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -d -r1.20 -r1.21
--- cairo_ps_surface.c	30 Jan 2005 19:37:48 -0000	1.20
+++ cairo_ps_surface.c	31 Jan 2005 16:50:22 -0000	1.21
@@ -208,28 +208,58 @@
     return surface->y_ppi;
 }
 
-static cairo_image_surface_t *
-_cairo_ps_surface_get_image (void *abstract_surface)
+static cairo_status_t
+_cairo_ps_surface_acquire_source_image (void                    *abstract_surface,
+					cairo_image_surface_t  **image_out,
+					void                   **image_extra)
 {
     cairo_ps_surface_t *surface = abstract_surface;
+    
+    *image_out = surface->image;
 
-    cairo_surface_reference (&surface->image->base);
+    return CAIRO_STATUS_SUCCESS;
+}
 
-    return surface->image;
+static void
+_cairo_ps_surface_release_source_image (void                   *abstract_surface,
+					cairo_image_surface_t  *image,
+					void                   *image_extra)
+{
 }
 
 static cairo_status_t
-_cairo_ps_surface_set_image (void			*abstract_surface,
-			     cairo_image_surface_t	*image)
+_cairo_ps_surface_acquire_dest_image (void                    *abstract_surface,
+				      cairo_rectangle_t       *interest_rect,
+				      cairo_image_surface_t  **image_out,
+				      cairo_rectangle_t       *image_rect,
+				      void                   **image_extra)
 {
     cairo_ps_surface_t *surface = abstract_surface;
+    
+    image_rect->x = 0;
+    image_rect->y = 0;
+    image_rect->width = surface->image->width;
+    image_rect->height = surface->image->height;
+    
+    *image_out = surface->image;
 
-    if (image == surface->image)
-	return CAIRO_STATUS_SUCCESS;
+    return CAIRO_STATUS_SUCCESS;
+}
 
-    /* XXX: Need to call _cairo_image_surface_set_image here, but it's
-       not implemented yet. */
+static void
+_cairo_ps_surface_release_dest_image (void                   *abstract_surface,
+				      cairo_rectangle_t      *interest_rect,
+				      cairo_image_surface_t  *image,
+				      cairo_rectangle_t      *image_rect,
+				      void                   *image_extra)
+{
+}
 
+static cairo_status_t
+_cairo_ps_surface_clone_similar (void			*abstract_surface,
+				 cairo_surface_t	*src,
+				 cairo_surface_t     **clone_out)
+{
     return CAIRO_INT_STATUS_UNSUPPORTED;
 }
 
@@ -262,7 +292,7 @@
 
 static cairo_int_status_t
 _cairo_ps_surface_composite (cairo_operator_t	operator,
-			     cairo_surface_t	*generic_src,
+			     cairo_pattern_t	*src,
 			     cairo_surface_t	*generic_mask,
 			     void		*abstract_dst,
 			     int		src_x,
@@ -425,8 +455,11 @@
     _cairo_ps_surface_create_similar,
     _cairo_ps_surface_destroy,
     _cairo_ps_surface_pixels_per_inch,
-    _cairo_ps_surface_get_image,
-    _cairo_ps_surface_set_image,
+    _cairo_ps_surface_acquire_source_image,
+    _cairo_ps_surface_release_source_image,
+    _cairo_ps_surface_acquire_dest_image,
+    _cairo_ps_surface_release_dest_image,
+    _cairo_ps_surface_clone_similar,
     _cairo_ps_surface_set_matrix,
     _cairo_ps_surface_set_filter,
     _cairo_ps_surface_set_repeat,

Index: cairo_surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo_surface.c,v
retrieving revision 1.38
retrieving revision 1.39
diff -u -d -r1.38 -r1.39
--- cairo_surface.c	27 Jan 2005 18:46:20 -0000	1.38
+++ cairo_surface.c	31 Jan 2005 16:50:22 -0000	1.39
@@ -151,16 +151,151 @@
     return surface->backend->pixels_per_inch (surface);
 }
 
-cairo_image_surface_t *
-_cairo_surface_get_image (cairo_surface_t *surface)
+/**
+ * _cairo_surface_acquire_source_image:
+ * @surface: a #cairo_surface_t
+ * @image_out: location to store a pointer to an image surface that includes at least
+ *    the intersection of @interest_rect with the visible area of @surface.
+ *    This surface could be @surface itself, a surface held internal to @surface,
+ *    or it could be a new surface with a copy of the relevant portion of @surface.
+ * @image_extra: location to store image specific backend data
+ * 
+ * Gets an image surface to use when drawing as a fallback when drawing with
+ * @surface as a source. _cairo_surface_release_source_image() must be called
+ * when finished.
+ * 
+ * Return value: %CAIRO_STATUS_SUCCESS if a an image was stored in @image_out.
+ * %CAIRO_INT_STATUS_UNSUPPORTED if an image cannot be retrieved for the specified
+ * surface. Or %CAIRO_STATUS_NO_MEMORY.
+ **/
+cairo_private cairo_status_t
+_cairo_surface_acquire_source_image (cairo_surface_t         *surface,
+				     cairo_image_surface_t  **image_out,
+				     void                   **image_extra)
 {
-    return surface->backend->get_image (surface);
+    return surface->backend->acquire_source_image (surface,  image_out, image_extra);
 }
 
+/**
+ * _cairo_surface_release_source_image:
+ * @surface: a #cairo_surface_t
+ * @image_extra: same as return from the matching _cairo_surface_acquire_dest_image()
+ * 
+ * Releases any resources obtained with _cairo_surface_acquire_source_image()
+ **/
+cairo_private void
+_cairo_surface_release_source_image (cairo_surface_t        *surface,
+				     cairo_image_surface_t  *image,
+				     void                   *image_extra)
+{
+    surface->backend->release_source_image (surface, image, image_extra);
+}
+
+/**
+ * _cairo_surface_acquire_dest_image:
+ * @surface: a #cairo_surface_t
+ * @interest_rect: area of @surface for which fallback drawing is being done.
+ *    A value of %NULL indicates that the entire surface is desired.
+ * @image_out: location to store a pointer to an image surface that includes at least
+ *    the intersection of @interest_rect with the visible area of @surface.
+ *    This surface could be @surface itself, a surface held internal to @surface,
+ *    or it could be a new surface with a copy of the relevant portion of @surface.
+ * @image_rect: location to store area of the original surface occupied 
+ *    by the surface stored in @image.
+ * @image_extra: location to store image specific backend data
+ * 
+ * Retrieves a local image for a surface for implementing a fallback drawing
+ * operation. After calling this function, the implementation of the fallback
+ * drawing operation draws the primitive to the surface stored in @image_out
+ * then calls _cairo_surface_release_dest_fallback(),
+ * which, if a temporary surface was created, copies the bits back to the
+ * main surface and frees the temporary surface.
+ * 
+ * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY.
+ *  %CAIRO_INT_STATUS_UNSUPPORTED can be returned but this will mean that
+ *  the backend can't draw with fallbacks. It's possible for the routine
+ *  to store NULL in @local_out and return %CAIRO_STATUS_SUCCESS;
+ *  that indicates that no part of @interest_rect is visible, so no drawing
+ *  is necessary. _cairo_surface_release_dest_fallback() should not be called in that
+ *  case.
+ **/
 cairo_status_t
-_cairo_surface_set_image (cairo_surface_t *surface, cairo_image_surface_t *image)
+_cairo_surface_acquire_dest_image (cairo_surface_t         *surface,
+				   cairo_rectangle_t       *interest_rect,
+				   cairo_image_surface_t  **image_out,
+				   cairo_rectangle_t       *image_rect,
+				   void                   **image_extra)
 {
-    return surface->backend->set_image (surface, image);
+    return surface->backend->acquire_dest_image (surface, interest_rect,
+						 image_out, image_rect, image_extra);
+}
+
+/**
+ * _cairo_surface_end_fallback:
+ * @surface: a #cairo_surface_t
+ * @interest_rect: same as passed to the matching _cairo_surface_acquire_dest_image()
+ * @image: same as returned from the matching _cairo_surface_acquire_dest_image()
+ * @image_rect: same as returned from the matching _cairo_surface_acquire_dest_image()
+ * @image_extra: same as return from the matching _cairo_surface_acquire_dest_image()
+ * 
+ * Finishes the operation started with _cairo_surface_acquire_dest_image(), by, if
+ * necessary, copying the image from @image back to @surface and freeing any
+ * resources that were allocated.
+ **/
+void
+_cairo_surface_release_dest_image (cairo_surface_t        *surface,
+				   cairo_rectangle_t      *interest_rect,
+				   cairo_image_surface_t  *image,
+				   cairo_rectangle_t      *image_rect,
+				   void                   *image_extra)
+{
+    surface->backend->release_dest_image (surface, interest_rect,
+					  image, image_rect, image_extra);
+}
+
+/**
+ * _cairo_surface_clone_similar:
+ * @surface: a #cairo_surface_t
+ * @src: the source image
+ * @clone_out: location to store a surface compatible with @surface
+ *   and with contents identical to @src. The caller must call
+ *   cairo_surface_destroy() on the result.
+ * 
+ * Creates a surface with contents identical to @src but that
+ *   can be used efficiently with @surface. If @surface and @src are
+ *   already compatible then it may return a new reference to @src.
+ * 
+ * Return value: %CAIRO_STATUS_SUCCESS if a surface was created and stored
+ *   in @clone_out. Otherwise %CAIRO_INT_STATUS_UNSUPPORTED or another
+ *   error like %CAIRO_STATUS_NO_MEMORY.
+ **/
+cairo_status_t
+_cairo_surface_clone_similar (cairo_surface_t  *surface,
+			      cairo_surface_t  *src,
+			      cairo_surface_t **clone_out)
+{
+    cairo_status_t status;
+    cairo_image_surface_t *image;
+    void *image_extra;
+    
+    status = surface->backend->clone_similar (surface, src, clone_out);
+    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+	return status;
+
+    status = _cairo_surface_acquire_source_image (src, &image, &image_extra);
+    if (status != CAIRO_STATUS_SUCCESS)
+	return status;
+    
+    status = surface->backend->clone_similar (surface, &image->base, clone_out);
+
+    /* 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;
 }
 
 cairo_status_t
@@ -228,6 +363,73 @@
 }
 slim_hidden_def(cairo_surface_set_repeat);
 
+typedef struct {
+    cairo_surface_t *dst;
+    cairo_rectangle_t extents;
+    cairo_image_surface_t *image;
+    cairo_rectangle_t image_rect;
+    void *image_extra;
+} fallback_state_t;
+
+static cairo_status_t
+_fallback_init (fallback_state_t *state,
+		cairo_surface_t  *dst,
+		int               x,
+		int               y,
+		int               width,
+		int               height)
+{
+    state->extents.x = x;
+    state->extents.y = y;
+    state->extents.width = width;
+    state->extents.height = height;
+    
+    state->dst = dst;
+
+    return _cairo_surface_acquire_dest_image (dst, &state->extents,
+					      &state->image, &state->image_rect, &state->image_extra);
+}
+
+static void
+_fallback_cleanup (fallback_state_t *state)
+{
+    _cairo_surface_release_dest_image (state->dst, &state->extents,
+				       state->image, &state->image_rect, &state->image_extra);
+}
+
+static cairo_status_t
+_fallback_composite (cairo_operator_t	operator,
+		     cairo_pattern_t	*pattern,
+		     cairo_surface_t	*mask,
+		     cairo_surface_t	*dst,
+		     int		src_x,
+		     int		src_y,
+		     int		mask_x,
+		     int		mask_y,
+		     int		dst_x,
+		     int		dst_y,
+		     unsigned int	width,
+		     unsigned int	height)
+{
+    fallback_state_t state;
+    cairo_status_t status;
+
+    status = _fallback_init (&state, dst, dst_x, dst_y, width, height);
+    if (!CAIRO_OK (status) || !state.image)
+	return status;
+
+    state.image->base.backend->composite (operator, pattern, mask,
+					  &state.image->base,
+					  src_x, src_y, mask_x, mask_y,
+					  dst_x - state.image_rect.x,
+					  dst_y - state.image_rect.y,
+					  width, height);
+
+    _fallback_cleanup (&state);
+	
+    return status;
+}
+
 cairo_status_t
 _cairo_surface_composite (cairo_operator_t	operator,
 			  cairo_pattern_t	*pattern,
@@ -243,7 +445,6 @@
 			  unsigned int		height)
 {
     cairo_int_status_t status;
-    cairo_image_surface_t *mask_image = 0, *dst_image;
 
     status = dst->backend->composite (operator,
 				      pattern, mask, dst,
@@ -254,26 +455,12 @@
     if (status != CAIRO_INT_STATUS_UNSUPPORTED)
 	return status;
 
-    if (mask)
-	mask_image = _cairo_surface_get_image (mask);
-    dst_image = _cairo_surface_get_image (dst);
-
-    dst_image->base.backend->composite (operator,
-					pattern,
-					mask ? &mask_image->base : NULL,
-					dst_image,
-					src_x, src_y,
-					mask_x, mask_y,
-					dst_x, dst_y,
-					width, height);
-
-    status = _cairo_surface_set_image (dst, dst_image);
-
-    if (mask)
-	cairo_surface_destroy (&mask_image->base);
-    cairo_surface_destroy (&dst_image->base);
-
-    return status;
+    return _fallback_composite (operator,
+				pattern, mask, dst,
+				src_x, src_y,
+				mask_x, mask_y,
+				dst_x, dst_y,
+				width, height);
 }
 
 cairo_status_t
@@ -295,6 +482,77 @@
     return _cairo_surface_fill_rectangles (surface, operator, color, &rect, 1);
 }
 
+static cairo_status_t
+_fallback_fill_rectangles (cairo_surface_t	*surface,
+			   cairo_operator_t	operator,
+			   const cairo_color_t	*color,
+			   cairo_rectangle_t	*rects,
+			   int			num_rects)
+{
+    fallback_state_t state;
+    cairo_rectangle_t *offset_rects = NULL;
+    cairo_status_t status;
+    int x1, y1, x2, y2;
+    int i;
+
+    if (num_rects <= 0)
+	return CAIRO_STATUS_SUCCESS;
+
+    /* Compute the bounds of the rectangles, so that we know what area of the
+     * destination surface to fetch
+     */
+    x1 = rects[0].x;
+    y1 = rects[0].y;
+    x2 = rects[0].x + rects[0].width;
+    y2 = rects[0].y + rects[0].height;
+    
+    for (i = 1; i < num_rects; i++) {
+	if (rects[0].x < x1)
+	    x1 = rects[0].x;
+	if (rects[0].y < y1)
+	    y1 = rects[0].y;
+
+	if (rects[0].x + rects[0].width > x2)
+	    x2 = rects[0].x + rects[0].width;
+	if (rects[0].y + rects[0].height > y2)
+	    y2 = rects[0].y + rects[0].height;
+    }
+
+    status = _fallback_init (&state, surface, x1, y1, x2 - x1, y2 - y1);
+    if (!CAIRO_OK (status) || !state.image)
+	return status;
+
+    /* If the fetched image isn't at 0,0, we need to offset the rectangles */
+    
+    if (state.image_rect.x != 0 || state.image_rect.y != 0) {
+	offset_rects = malloc (sizeof (cairo_rectangle_t) * num_rects);
+	if (!offset_rects) {
+	    status = CAIRO_STATUS_NO_MEMORY;
+	    goto FAIL;
+	}
+
+	for (i = 0; i < num_rects; i++) {
+	    offset_rects[i].x = rects[i].x - state.image_rect.x;
+	    offset_rects[i].y = rects[i].y - state.image_rect.y;
+	    offset_rects[i].width = rects[i].width;
+	    offset_rects[i].height = rects[i].height;
+	}
+
+	rects = offset_rects;
+    }
+
+    state.image->base.backend->fill_rectangles (&state.image->base, operator, color,
+						rects, num_rects);
+
+    if (offset_rects)
+	free (offset_rects);
+
+ FAIL:
+    _fallback_cleanup (&state);
+    
+    return status;
+}
+
 cairo_status_t
 _cairo_surface_fill_rectangles (cairo_surface_t		*surface,
 				cairo_operator_t	operator,
@@ -303,7 +561,6 @@
 				int			num_rects)
 {
     cairo_int_status_t status;
-    cairo_image_surface_t *surface_image;
 
     if (num_rects == 0)
 	return CAIRO_STATUS_SUCCESS;
@@ -315,20 +572,76 @@
     if (status != CAIRO_INT_STATUS_UNSUPPORTED)
 	return status;
 
-    surface_image = _cairo_surface_get_image (surface);
+    return _fallback_fill_rectangles (surface, operator, color, rects, num_rects);
+}
 
-    surface_image->base.backend->fill_rectangles (surface_image,
-						  operator,
-						  color,
-						  rects, num_rects);
+static cairo_status_t
+_fallback_composite_trapezoids (cairo_operator_t	operator,
+				cairo_pattern_t		*pattern,
+				cairo_surface_t		*dst,
+				int			src_x,
+				int			src_y,
+				int			dst_x,
+				int			dst_y,
+				unsigned int		width,
+				unsigned int		height,
+				cairo_trapezoid_t	*traps,
+				int			num_traps)
+{
+    fallback_state_t state;
+    cairo_trapezoid_t *offset_traps = NULL;
+    cairo_status_t status;
+    int i;
 
-    status = _cairo_surface_set_image (surface, surface_image);
+    status = _fallback_init (&state, dst, dst_x, dst_y, width, height);
+    if (!CAIRO_OK (status) || !state.image)
+	return status;
 
-    cairo_surface_destroy (&surface_image->base);
+    /* If the destination image isn't at 0,0, we need to offset the trapezoids */
+    
+    if (state.image_rect.x != 0 || state.image_rect.y != 0) {
+
+	cairo_fixed_t xoff = _cairo_fixed_from_int (state.image_rect.x);
+	cairo_fixed_t yoff = _cairo_fixed_from_int (state.image_rect.y);
+	
+	offset_traps = malloc (sizeof (cairo_trapezoid_t) * num_traps);
+	if (!offset_traps) {
+	    status = CAIRO_STATUS_NO_MEMORY;
+	    goto FAIL;
+	}
 
+	for (i = 0; i < num_traps; i++) {
+	    offset_traps[i].top = traps[i].top - yoff;
+	    offset_traps[i].bottom = traps[i].bottom - yoff;
+	    offset_traps[i].left.p1.x = traps[i].left.p1.x - xoff;
+	    offset_traps[i].left.p1.y = traps[i].left.p1.y - yoff;
+	    offset_traps[i].left.p2.x = traps[i].left.p2.x - xoff;
+	    offset_traps[i].left.p2.y = traps[i].left.p2.y - yoff;
+	    offset_traps[i].right.p1.x = traps[i].right.p1.x - xoff;
+	    offset_traps[i].right.p1.y = traps[i].right.p1.y - yoff;
+	    offset_traps[i].right.p2.x = traps[i].right.p2.x - xoff;
+	    offset_traps[i].right.p2.y = traps[i].right.p2.y - yoff;
+	}
+
+	traps = offset_traps;
+    }
+
+    state.image->base.backend->composite_trapezoids (operator, pattern,
+						     &state.image->base,
+						     src_x, src_y,
+						     dst_x - state.image_rect.x,
+						     dst_x - state.image_rect.y,
+						     width, height, traps, num_traps);
+    if (offset_traps)
+	free (offset_traps);
+
+ FAIL:
+    _fallback_cleanup (&state);
+    
     return status;
 }
 
+
 cairo_status_t
 _cairo_surface_composite_trapezoids (cairo_operator_t		operator,
 				     cairo_pattern_t		*pattern,
@@ -343,7 +656,6 @@
 				     int			num_traps)
 {
     cairo_int_status_t status;
-    cairo_image_surface_t *dst_image;
 
     status = dst->backend->composite_trapezoids (operator,
 						 pattern, dst,
@@ -354,21 +666,11 @@
     if (status != CAIRO_INT_STATUS_UNSUPPORTED)
 	return status;
 
-    dst_image = _cairo_surface_get_image (dst);
-
-    dst_image->base.backend->composite_trapezoids (operator,
-						   pattern,
-						   dst_image,
-						   src_x, src_y,
-						   dst_x, dst_y,
-						   width, height,
-						   traps, num_traps);
-
-    status = _cairo_surface_set_image (dst, dst_image);
-
-    cairo_surface_destroy (&dst_image->base);
-
-    return status;
+    return _fallback_composite_trapezoids (operator, pattern, dst,
+					   src_x, src_y,
+					   dst_x, dst_y,
+					   width, height,
+					   traps, num_traps);
 }
 
 cairo_status_t

Index: cairo_xlib_surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo_xlib_surface.c,v
retrieving revision 1.42
retrieving revision 1.43
diff -u -d -r1.42 -r1.43
--- cairo_xlib_surface.c	28 Jan 2005 03:57:32 -0000	1.42
+++ cairo_xlib_surface.c	31 Jan 2005 16:50:22 -0000	1.43
@@ -103,6 +103,8 @@
 
 #define CAIRO_SURFACE_RENDER_HAS_CREATE_PICTURE(surface)		CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 0)
 #define CAIRO_SURFACE_RENDER_HAS_COMPOSITE(surface)		CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 0)
+#define CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT(surface)	CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 0)
+
 
 #define CAIRO_SURFACE_RENDER_HAS_FILL_RECTANGLE(surface)		CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 1)
 #define CAIRO_SURFACE_RENDER_HAS_FILL_RECTANGLES(surface)		CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 1)
@@ -157,18 +159,13 @@
     Pixmap pix;
     cairo_xlib_surface_t *surface;
 
-    /* XXX: There's a pretty lame heuristic here. This assumes that
-     * all non-Render X servers do not support depth-32 pixmaps, (and
-     * that they do support depths 1, 8, and 24). Obviously, it would
-     * be much better to check the depths that are actually
-     * supported. */
-    if (!dpy
-	|| (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE (src)
-	    && format == CAIRO_FORMAT_ARGB32))
-    {
-	return NULL;
+    /* As a good first approximation, if the display doesn't have COMPOSITE,
+     * we're better off using image surfaces for all temporary operations
+     */
+    if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE(src)) {
+	return cairo_image_surface_create (format, width, height);
     }
-
+    
     scr = DefaultScreen (dpy);
 
     pix = XCreatePixmap (dpy, DefaultRootWindow (dpy),
@@ -212,15 +209,17 @@
     return 96.0;
 }
 
-static cairo_image_surface_t *
-_cairo_xlib_surface_get_image (void *abstract_surface)
+static cairo_status_t
+_get_image_surface (cairo_xlib_surface_t   *surface,
+		    cairo_rectangle_t      *interest_rect,
+		    cairo_image_surface_t **image_out,
+		    cairo_rectangle_t      *image_rect)
 {
-    cairo_xlib_surface_t *surface = abstract_surface;
     cairo_image_surface_t *image;
-
     XImage *ximage;
     Window root_ignore;
     int x_ignore, y_ignore, bwidth_ignore, depth_ignore;
+    int x1, y1, x2, y2;
 
     XGetGeometry (surface->dpy, 
 		  surface->drawable, 
@@ -228,11 +227,39 @@
 		  &surface->width, &surface->height,
 		  &bwidth_ignore, &depth_ignore);
 
+    x1 = 0;
+    y1 = 0;
+    x2 = surface->width;
+    y2 = surface->height;
+
+    if (interest_rect) {
+	if (interest_rect->x > x1)
+	    x1 = interest_rect->x;
+	if (interest_rect->y > y1)
+	    y1 = interest_rect->y;
+	if (interest_rect->x + interest_rect->width < x2)
+	    x2 = interest_rect->x + interest_rect->width;
+	if (interest_rect->y + interest_rect->height < y2)
+	    y2 = interest_rect->y + interest_rect->height;
+
+	if (x1 >= x2 || y1 >= y2) {
+	    *image_out = NULL;
+	    return CAIRO_STATUS_SUCCESS;
+	}
+    }
+
+    if (image_rect) {
+	image_rect->x = x1;
+	image_rect->y = y1;
+	image_rect->width = x2 - x1;
+	image_rect->height = y2 - y1;
+    }
+
     /* XXX: This should try to use the XShm extension if availible */
     ximage = XGetImage (surface->dpy,
 			surface->drawable,
-			0, 0,
-			surface->width, surface->height,
+			x1, y1,
+			x2 - x1, y2 - y1,
 			AllPlanes, ZPixmap);
 
     if (surface->visual) {
@@ -269,7 +296,8 @@
     _cairo_image_surface_set_repeat (image, surface->base.repeat);
     _cairo_image_surface_set_matrix (image, &(surface->base.matrix));
 
-    return image;
+    *image_out = image;
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static void
@@ -282,10 +310,11 @@
 }
 
 static cairo_status_t
-_cairo_xlib_surface_set_image (void			*abstract_surface,
-			       cairo_image_surface_t	*image)
+_draw_image_surface (cairo_xlib_surface_t   *surface,
+		     cairo_image_surface_t  *image,
+		     int                    dst_x,
+		     int                    dst_y)
 {
-    cairo_xlib_surface_t *surface = abstract_surface;
     XImage *ximage;
     unsigned bitmap_pad;
 
@@ -311,9 +340,8 @@
 
     _cairo_xlib_surface_ensure_gc (surface);
     XPutImage(surface->dpy, surface->drawable, surface->gc,
-	      ximage, 0, 0, 0, 0,
-	      surface->width,
-	      surface->height);
+	      ximage, 0, 0, dst_x, dst_y,
+	      image->width, image->height);
 
     /* Foolish XDestroyImage thinks it can free my data, but I won't
        stand for it. */
@@ -321,6 +349,109 @@
     XDestroyImage (ximage);
 
     return CAIRO_STATUS_SUCCESS;
+
+}
+
+static cairo_status_t
+_cairo_xlib_surface_acquire_source_image (void                    *abstract_surface,
+					  cairo_image_surface_t  **image_out,
+					  void                   **image_extra)
+{
+    cairo_xlib_surface_t *surface = abstract_surface;
+    cairo_image_surface_t *image;
+    cairo_status_t status;
+
+    status = _get_image_surface (surface, NULL, &image, NULL);
+    if (status == CAIRO_STATUS_SUCCESS) {
+	cairo_surface_set_filter (&image->base, surface->base.filter);
+	cairo_surface_set_matrix (&image->base, &surface->base.matrix);
+	cairo_surface_set_repeat (&image->base, surface->base.repeat);
+
+	*image_out = image;
+    }
+
+    return status;
+}
+
+static void
+_cairo_xlib_surface_release_source_image (void                   *abstract_surface,
+					  cairo_image_surface_t  *image,
+					  void                   *image_extra)
+{
+    cairo_surface_destroy (&image->base);
+}
+
+static cairo_status_t
+_cairo_xlib_surface_acquire_dest_image (void                    *abstract_surface,
+					cairo_rectangle_t       *interest_rect,
+					cairo_image_surface_t  **image_out,
+					cairo_rectangle_t       *image_rect_out,
+					void                   **image_extra)
+{
+    cairo_xlib_surface_t *surface = abstract_surface;
+    cairo_image_surface_t *image;
+    cairo_status_t status;
+
+    status = _get_image_surface (surface, interest_rect, &image, image_rect_out);
+    if (status == CAIRO_STATUS_SUCCESS)
+	*image_out = image;
+
+    return status;
+}
+
+static void
+_cairo_xlib_surface_release_dest_image (void                   *abstract_surface,
+					cairo_rectangle_t      *interest_rect,
+					cairo_image_surface_t  *image,
+					cairo_rectangle_t      *image_rect,
+					void                   *image_extra)
+{
+    cairo_xlib_surface_t *surface = abstract_surface;
+
+    /* ignore errors */
+    _draw_image_surface (surface, image, image_rect->x, image_rect->y);
+
+    cairo_surface_destroy (&image->base);
+}
+
+static cairo_status_t
+_cairo_xlib_surface_clone_similar (void			*abstract_surface,
+				   cairo_surface_t	*src,
+				   cairo_surface_t     **clone_out)
+{
+    cairo_xlib_surface_t *surface = abstract_surface;
+    cairo_xlib_surface_t *clone;
+
+    if (src->backend == surface->base.backend ) {
+	cairo_xlib_surface_t *xlib_src = (cairo_xlib_surface_t *)src;
+
+	if (xlib_src->dpy == surface->dpy) {
+	    *clone_out = src;
+	    cairo_surface_reference (src);
+	    
+	    return CAIRO_STATUS_SUCCESS;
+	}
+    } else if (_cairo_surface_is_image (src)) {
+	cairo_image_surface_t *image_src = (cairo_image_surface_t *)src;
+    
+	clone = (cairo_xlib_surface_t *)
+	    _cairo_xlib_surface_create_similar (surface, image_src->format, 0,
+						image_src->width, image_src->height);
+	if (clone == NULL)
+	    return CAIRO_STATUS_NO_MEMORY;
+	
+	_draw_image_surface (clone, image_src, 0, 0);
+	
+	cairo_surface_set_filter (&clone->base, src->filter);
+	cairo_surface_set_matrix (&clone->base, &src->matrix);
+	cairo_surface_set_repeat (&clone->base, src->repeat);
+	
+	*clone_out = &clone->base;
+
+	return CAIRO_STATUS_SUCCESS;
+    }
+    
+    return CAIRO_INT_STATUS_UNSUPPORTED;
 }
 
 static cairo_status_t
@@ -410,35 +541,6 @@
     return CAIRO_STATUS_SUCCESS;
 }
 
-static cairo_xlib_surface_t *
-_cairo_xlib_surface_clone_similar (cairo_surface_t	*src,
-				   cairo_xlib_surface_t	*template,
-				   cairo_format_t	format,
-				   int			depth)
-{
-    cairo_xlib_surface_t *clone;
-    cairo_image_surface_t *src_image;
-
-    src_image = _cairo_surface_get_image (src);
-
-    clone = (cairo_xlib_surface_t *)
-	_cairo_xlib_surface_create_similar (template, format, 0,
-					    src_image->width,
-					    src_image->height);
-    if (clone == NULL)
-	return NULL;
-
-    _cairo_xlib_surface_set_filter (clone, cairo_surface_get_filter(src));
-
-    _cairo_xlib_surface_set_image (clone, src_image);
-
-    _cairo_xlib_surface_set_matrix (clone, &(src_image->base.matrix));
-
-    cairo_surface_destroy (&src_image->base);
-
-    return clone;
-}
-
 static int
 _render_operator (cairo_operator_t operator)
 {
@@ -493,27 +595,29 @@
     cairo_xlib_surface_t *dst = abstract_dst;
     cairo_xlib_surface_t *src;
     cairo_xlib_surface_t *mask = (cairo_xlib_surface_t *) generic_mask;
-    cairo_xlib_surface_t *mask_clone = NULL;
+    cairo_surface_t *mask_clone = NULL;
     XGCValues gc_values;
     int src_x_off, src_y_off, dst_x_off, dst_y_off;
-    int x_offset, y_offset;
+    cairo_pattern_info_t pattern_info;
+    cairo_status_t status;
 
     if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE (dst))
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
-    src = (cairo_xlib_surface_t *)
-	_cairo_pattern_get_surface (pattern, &dst->base,
-				    src_x, src_y,
-				    width, height,
-				    &x_offset, &y_offset);
+    status = _cairo_pattern_begin_draw (pattern, &pattern_info,
+					&dst->base,
+					src_x, src_y, width, height);
+    if (!CAIRO_OK (status))
+	return status;
 
+    src = (cairo_xlib_surface_t *)pattern_info.src;
+    
     /* XXX This stuff can go when we change the mask to be a pattern also. */
     if (generic_mask && (generic_mask->backend != dst->base.backend || mask->dpy != dst->dpy)) {
-	mask_clone = _cairo_xlib_surface_clone_similar (generic_mask, dst,
-							CAIRO_FORMAT_A8, 8);
-	if (!mask_clone)
-	    return CAIRO_INT_STATUS_UNSUPPORTED;
-	mask = mask_clone;
+	status = _cairo_surface_clone_similar (abstract_dst, generic_mask, &mask_clone);
+	if (!CAIRO_OK (status))
+	    goto FAIL;
+	mask = (cairo_xlib_surface_t *)mask_clone;
     }
 
     if (operator == CAIRO_OPERATOR_SRC 
@@ -530,30 +634,31 @@
 		  src->drawable, 
 		  dst->drawable, 
 		  dst->gc, 
-		  src_x + src_x_off, 
-		  src_y + src_y_off, 
-		  width, height, 
+		  src_x + src_x_off - pattern_info.x_offset, 
+		  src_y + src_y_off - pattern_info.y_offset,
+		  width, height,
 		  dst_x + dst_x_off, 
 		  dst_y + dst_y_off);
 	XSetGraphicsExposures(dst->dpy, dst->gc, gc_values.graphics_exposures);
 
     } else {	
-    XRenderComposite (dst->dpy,
-		      _render_operator (operator),
-		      src->picture,
-		      mask ? mask->picture : 0,
-		      dst->picture,
-		      src_x, src_y,
-		      mask_x, mask_y,
-		      dst_x, dst_y,
-		      width, height);
+	XRenderComposite (dst->dpy,
+			  _render_operator (operator),
+			  src->picture,
+			  mask ? mask->picture : 0,
+			  dst->picture,
+			  src_x - pattern_info.x_offset,
+			  src_y - pattern_info.y_offset,
+			  mask_x, mask_y,
+			  dst_x, dst_y,
+			  width, height);
     }
 
-    /* XXX: This is messed up. If I can xlib_surface_create, then I
-       should be able to xlib_surface_destroy. */
-    cairo_surface_destroy (&src->base);
     if (mask_clone)
-	cairo_surface_destroy (&mask_clone->base);
+	cairo_surface_destroy (mask_clone);
+
+ FAIL:
+    _cairo_pattern_end_draw (pattern, &pattern_info);
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -600,21 +705,21 @@
 {
     cairo_xlib_surface_t *dst = abstract_dst;
     cairo_xlib_surface_t *src;
-    int x_offset, y_offset;
+    cairo_pattern_info_t pattern_info;
     int render_reference_x, render_reference_y;
     int render_src_x, render_src_y;
+    cairo_status_t status;
 
     if (!CAIRO_SURFACE_RENDER_HAS_TRAPEZOIDS (dst))
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
-    src = (cairo_xlib_surface_t *) 
-	_cairo_pattern_get_surface (pattern, &dst->base,
-				    src_x, src_y, width, height,
-				    &x_offset, &y_offset);
-    if (src == NULL)
-	return CAIRO_STATUS_NO_MEMORY;
+    status = _cairo_pattern_begin_draw (pattern, &pattern_info,
+					&dst->base,
+					src_x, src_y, width, height);
+    if (!CAIRO_OK (status))
+	return status;
 
-    _cairo_pattern_prepare_surface (pattern, &src->base);
+    src = (cairo_xlib_surface_t *)pattern_info.src;
 
     if (traps[0].left.p1.y < traps[0].left.p2.y) {
 	render_reference_x = _cairo_fixed_integer_floor (traps[0].left.p1.x);
@@ -632,15 +737,11 @@
 				_render_operator (operator),
 				src->picture, dst->picture,
 				XRenderFindStandardFormat (dst->dpy, PictStandardA8),
-				render_src_x - x_offset, 
-				render_src_y - y_offset,
+				render_src_x - pattern_info.x_offset, 
+				render_src_y - pattern_info.y_offset,
 				(XTrapezoid *) traps, num_traps);
 
-    _cairo_pattern_restore_surface (pattern, &src->base);
-
-    /* XXX: This is messed up. If I can xlib_surface_create, then I
-       should be able to xlib_surface_destroy. */
-    cairo_surface_destroy (&src->base);
+    _cairo_pattern_end_draw (pattern, &pattern_info);
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -739,8 +840,11 @@
     _cairo_xlib_surface_create_similar,
     _cairo_xlib_surface_destroy,
     _cairo_xlib_surface_pixels_per_inch,
-    _cairo_xlib_surface_get_image,
-    _cairo_xlib_surface_set_image,
+    _cairo_xlib_surface_acquire_source_image,
+    _cairo_xlib_surface_release_source_image,
+    _cairo_xlib_surface_acquire_dest_image,
+    _cairo_xlib_surface_release_dest_image,
+    _cairo_xlib_surface_clone_similar,
     _cairo_xlib_surface_set_matrix,
     _cairo_xlib_surface_set_filter,
     _cairo_xlib_surface_set_repeat,
@@ -1300,14 +1404,18 @@
 {
     unsigned int elt_size;
     cairo_xlib_surface_t *self = abstract_surface;
+    cairo_pattern_info_t pattern_info;
     cairo_xlib_surface_t *src;
     glyphset_cache_t *g;
     cairo_status_t status = CAIRO_STATUS_NO_MEMORY;
     cairo_glyph_cache_key_t key;
     glyphset_cache_entry_t **entries;
     glyphset_cache_entry_t *stack_entries [N_STACK_BUF];
-    int i, x_offset, y_offset;
+    int i;
 
+    if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT (self))
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+    
     /* Acquire an entry array of suitable size. */
     if (num_glyphs < N_STACK_BUF) {
 	entries = stack_entries;
@@ -1318,17 +1426,13 @@
 	    goto FAIL;
     }
 
-    src = (cairo_xlib_surface_t *)
-	_cairo_pattern_get_surface (pattern, &self->base,
-				    source_x, source_y,
-				    width, height,
-				    &x_offset, &y_offset);
-    if (src == NULL) {
-	status = CAIRO_STATUS_NO_MEMORY;
+    status = _cairo_pattern_begin_draw (pattern, &pattern_info,
+					&self->base,
+					source_x, source_y, width, height);
+    if (!CAIRO_OK (status))
 	goto FREE_ENTRIES;
-    }
 
-    _cairo_pattern_prepare_surface (pattern, &src->base);
+    src = (cairo_xlib_surface_t *)pattern_info.src;
 
     _lock_xlib_glyphset_caches ();
     g = _get_glyphset_cache (self->dpy);
@@ -1366,15 +1470,18 @@
 
     if (elt_size == 8)
 	status = _cairo_xlib_surface_show_glyphs8 (font, operator, g, &key, src, self,
-						    source_x, source_y, 
+						   source_x - pattern_info.x_offset,
+						   source_y - pattern_info.y_offset, 
 						   glyphs, entries, num_glyphs);
     else if (elt_size == 16)
 	status = _cairo_xlib_surface_show_glyphs16 (font, operator, g, &key, src, self,
-						    source_x, source_y, 
+						    source_x - pattern_info.x_offset,
+						    source_y - pattern_info.y_offset, 
 						    glyphs, entries, num_glyphs);
     else 
 	status = _cairo_xlib_surface_show_glyphs32 (font, operator, g, &key, src, self,
-						    source_x, source_y, 
+						    source_x - pattern_info.x_offset,
+						    source_y - pattern_info.y_offset, 
 						    glyphs, entries, num_glyphs);
 
     for (i = 0; i < num_glyphs; ++i)
@@ -1382,8 +1489,7 @@
 
  UNLOCK:
     _unlock_xlib_glyphset_caches ();
-    _cairo_pattern_restore_surface (pattern, &src->base);
-    cairo_surface_destroy (&src->base);
+    _cairo_pattern_end_draw (pattern, &pattern_info);
 
  FREE_ENTRIES:
     if (num_glyphs >= N_STACK_BUF)

Index: cairoint.h
===================================================================
RCS file: /cvs/cairo/cairo/src/cairoint.h,v
retrieving revision 1.91
retrieving revision 1.92
diff -u -d -r1.91 -r1.92
--- cairoint.h	28 Jan 2005 20:27:23 -0000	1.91
+++ cairoint.h	31 Jan 2005 16:50:22 -0000	1.92
@@ -169,6 +169,8 @@
     CAIRO_INT_STATUS_UNSUPPORTED
 } cairo_int_status_t;
 
+#define CAIRO_OK(status) ((status) == CAIRO_STATUS_SUCCESS)
+
 typedef enum cairo_path_op {
     CAIRO_PATH_OP_MOVE_TO = 0,
     CAIRO_PATH_OP_LINE_TO = 1,
@@ -540,18 +542,35 @@
     double
     (*pixels_per_inch)		(void			*surface);
 
-    /* XXX: We could use a better name than get_image here. Something
-       to suggest the fact that the function will create a new
-       surface, (and hence that it needs to be destroyed). Perhaps
-       clone_image or maybe simply clone? */
+    cairo_status_t
+    (* acquire_source_image)    (void                    *abstract_surface,
+				 cairo_image_surface_t  **image_out,
+				 void                   **image_extra);
 
-    cairo_image_surface_t *
-    (*get_image)		(void			*surface);
+    void
+    (* release_source_image)    (void                   *abstract_surface,
+				 cairo_image_surface_t  *image,
+				 void                   *image_extra);
 
     cairo_status_t
-    (*set_image)		(void			*surface,
-				 cairo_image_surface_t	*image);
+    (*acquire_dest_image)       (void                   *abstract_surface,
+				 cairo_rectangle_t       *interest_rect,
+				 cairo_image_surface_t  **image_out,
+				 cairo_rectangle_t       *image_rect,
+				 void                   **image_extra);
 
+    void
+    (*release_dest_image)       (void                   *abstract_surface,
+				 cairo_rectangle_t      *interest_rect,
+				 cairo_image_surface_t  *image,
+				 cairo_rectangle_t      *image_rect,
+				 void                   *image_extra);
+	
+    cairo_status_t
+    (*clone_similar)            (void                   *surface,
+				 cairo_surface_t        *src,
+				 cairo_surface_t       **clone_out);
+				 
     cairo_status_t
     (*set_matrix)		(void			*surface,
 				 cairo_matrix_t		*matrix);
@@ -655,6 +674,7 @@
     cairo_surface_t base;
 
     /* libic-specific fields */
+    cairo_format_t format;
     char *data;
     int owns_data;
 
@@ -748,6 +768,15 @@
     } u;
 };
 
+typedef struct {
+    cairo_surface_t *src;
+    int x_offset;
+    int y_offset;
+
+    int acquired;		/* If we used _cairo_surface_acquire_source_image */
+    void *extra;
+} cairo_pattern_info_t;
+
 typedef struct _cairo_traps {
     cairo_trapezoid_t *traps;
     int num_traps;
@@ -1424,12 +1453,34 @@
 cairo_private double
 _cairo_surface_pixels_per_inch (cairo_surface_t *surface);
 
-cairo_private cairo_image_surface_t *
-_cairo_surface_get_image (cairo_surface_t *surface);
+cairo_private cairo_status_t
+_cairo_surface_acquire_source_image (cairo_surface_t         *urface,
+				     cairo_image_surface_t  **image_out,
+				     void                   **image_extra);
+
+cairo_private void
+_cairo_surface_release_source_image (cairo_surface_t        *surface,
+				     cairo_image_surface_t  *image,
+				     void                   *image_extra);
 
 cairo_private cairo_status_t
-_cairo_surface_set_image (cairo_surface_t	*surface,
-			  cairo_image_surface_t	*image);
+_cairo_surface_acquire_dest_image (cairo_surface_t         *surface,
+				   cairo_rectangle_t       *interest_rect,
+				   cairo_image_surface_t  **image_out,
+				   cairo_rectangle_t       *image_rect,
+				   void                   **image_extra);
+
+cairo_private void
+_cairo_surface_release_dest_image (cairo_surface_t        *surface,
+				   cairo_rectangle_t      *interest_rect,
+				   cairo_image_surface_t  *image,
+				   cairo_rectangle_t      *image_rect,
+				   void                   *image_extra);
+    
+cairo_private cairo_status_t
+_cairo_surface_clone_similar (cairo_surface_t  *surface,
+			      cairo_surface_t  *src,
+			      cairo_surface_t **clone_out);
 
 cairo_private cairo_status_t
 _cairo_surface_set_clip_region (cairo_surface_t *surface, pixman_region16_t *region);
@@ -1462,6 +1513,9 @@
 _cairo_image_surface_set_clip_region (cairo_image_surface_t *surface,
 				      pixman_region16_t *region);
 
+cairo_private int
+_cairo_surface_is_image (cairo_surface_t *surface);
+
 /* cairo_pen.c */
 cairo_private cairo_status_t
 _cairo_pen_init (cairo_pen_t *pen, double radius, cairo_gstate_t *gstate);
@@ -1656,15 +1710,18 @@
 				    cairo_fixed_t factor,
 				    int *pixel);
 
-cairo_private cairo_surface_t *
-_cairo_pattern_get_surface (cairo_pattern_t	*pattern,
-			    cairo_surface_t	*dst,
-			    int			x,
-			    int			y,
-			    unsigned int	width,
-			    unsigned int	height,
-			    int			*x_offset,
-			    int			*y_offset);
+cairo_private cairo_status_t
+_cairo_pattern_begin_draw (cairo_pattern_t	*pattern,
+			   cairo_pattern_info_t *info,
+			   cairo_surface_t	*dst,
+			   int			 x,
+			   int			 y,
+			   unsigned int	 	 width,
+			   unsigned int	         height);
+
+cairo_private void
+_cairo_pattern_end_draw (cairo_pattern_t      *pattern,
+			 cairo_pattern_info_t *info);
 
 /* Avoid unnecessary PLT entries.  */
 




More information about the cairo-commit mailing list