[cairo-commit] 11 commits - autogen.sh src/cairo-directfb-surface.c src/cairo-fallback-compositor.c src/cairo-gl-operand.c src/cairo-gl-surface.c src/cairo-image-surface.c src/cairo-image-surface-inline.h src/cairo-image-surface-private.h src/cairoint.h src/cairo-os2-surface.c src/cairo-quartz-image-surface.c src/cairo-quartz-surface.c src/cairo-surface-backend-private.h src/cairo-surface.c src/cairo-surface-observer.c src/cairo-surface-subsurface.c src/cairo-xcb-surface.c src/cairo-xlib-source.c src/cairo-xlib-surface.c src/cairo-xlib-xcb-surface.c src/skia src/win32 test/png.c

Andrea Canciani ranma42 at kemper.freedesktop.org
Sat May 26 07:10:47 PDT 2012


 autogen.sh                              |    8 -
 src/cairo-directfb-surface.c            |   13 -
 src/cairo-fallback-compositor.c         |   56 ++++---
 src/cairo-gl-operand.c                  |   11 -
 src/cairo-gl-surface.c                  |   33 ++--
 src/cairo-image-surface-inline.h        |    6 
 src/cairo-image-surface-private.h       |    9 +
 src/cairo-image-surface.c               |   48 ++++++
 src/cairo-os2-surface.c                 |    3 
 src/cairo-quartz-image-surface.c        |    9 -
 src/cairo-quartz-surface.c              |  210 ++++++++++-----------------
 src/cairo-surface-backend-private.h     |    2 
 src/cairo-surface-observer.c            |   20 --
 src/cairo-surface-subsurface.c          |   14 -
 src/cairo-surface.c                     |  241 ++++++++++++++++++++++----------
 src/cairo-xcb-surface.c                 |   31 ++--
 src/cairo-xlib-source.c                 |   25 ++-
 src/cairo-xlib-surface.c                |   21 +-
 src/cairo-xlib-xcb-surface.c            |   12 -
 src/cairoint.h                          |   10 +
 src/skia/cairo-skia-surface.cpp         |    3 
 src/win32/cairo-win32-display-surface.c |    8 -
 test/png.c                              |    1 
 23 files changed, 456 insertions(+), 338 deletions(-)

New commits:
commit fc33cc3c3af1fc616ae445a15d2b146a29090b0f
Author: Andrea Canciani <ranma42 at gmail.com>
Date:   Fri Jan 6 19:47:08 2012 +0100

    quartz: Provide a valid implementation of map_to_image
    
    and reuse it to implement acquire_source.
    
    Fixes
    
    cairo-quartz-surface.c: In function '_cairo_quartz_surface_map_to_image':
    cairo-quartz-surface.c:1568: warning: return from incompatible pointer type
    cairo-quartz-surface.c:1576: warning: return from incompatible pointer type

diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index 994b92f..7c8c453 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -43,7 +43,7 @@
 #include "cairo-compositor-private.h"
 #include "cairo-default-context-private.h"
 #include "cairo-error-private.h"
-#include "cairo-image-surface-private.h"
+#include "cairo-image-surface-inline.h"
 #include "cairo-pattern-private.h"
 #include "cairo-surface-backend-private.h"
 #include "cairo-surface-clipper-private.h"
@@ -1386,96 +1386,82 @@ _cairo_quartz_draw_source (cairo_quartz_drawing_state_t *state,
     }
 }
 
-/*
- * get source/dest image implementation
- */
-
-/* Read the image from the surface's front buffer */
-static cairo_int_status_t
-_cairo_quartz_get_image (cairo_quartz_surface_t *surface,
-			 cairo_image_surface_t **image_out)
+static cairo_image_surface_t *
+_cairo_quartz_surface_map_to_image (void *abstract_surface,
+				    const cairo_rectangle_int_t *extents)
 {
-    unsigned char *imageData;
-    cairo_image_surface_t *isurf;
+    cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
+    unsigned int stride, bitinfo, bpp, color_comps;
+    CGColorSpaceRef colorspace;
+    void *imageData;
+    cairo_format_t format;
 
-    if (IS_EMPTY (surface)) {
-	*image_out = (cairo_image_surface_t*) cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 0, 0);
-	return CAIRO_STATUS_SUCCESS;
-    }
+    if (surface->imageSurfaceEquiv)
+	return _cairo_surface_map_to_image (surface->imageSurfaceEquiv, extents);
 
-    if (surface->imageSurfaceEquiv) {
-	*image_out = (cairo_image_surface_t*) cairo_surface_reference (surface->imageSurfaceEquiv);
-	return CAIRO_STATUS_SUCCESS;
-    }
+    if (IS_EMPTY (surface))
+	return (cairo_image_surface_t *) cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 0, 0);
 
-    if (_cairo_quartz_is_cgcontext_bitmap_context (surface->cgContext)) {
-	unsigned int stride;
-	unsigned int bitinfo;
-	unsigned int bpc, bpp;
-	CGColorSpaceRef colorspace;
-	unsigned int color_comps;
+    if (! _cairo_quartz_is_cgcontext_bitmap_context (surface->cgContext))
+	return _cairo_image_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 
-	imageData = (unsigned char *) CGBitmapContextGetData (surface->cgContext);
+    bitinfo = CGBitmapContextGetBitmapInfo (surface->cgContext);
+    bpp = CGBitmapContextGetBitsPerPixel (surface->cgContext);
 
-	bitinfo = CGBitmapContextGetBitmapInfo (surface->cgContext);
-	stride = CGBitmapContextGetBytesPerRow (surface->cgContext);
-	bpp = CGBitmapContextGetBitsPerPixel (surface->cgContext);
-	bpc = CGBitmapContextGetBitsPerComponent (surface->cgContext);
+    // let's hope they don't add YUV under us
+    colorspace = CGBitmapContextGetColorSpace (surface->cgContext);
+    color_comps = CGColorSpaceGetNumberOfComponents (colorspace);
 
-	// let's hope they don't add YUV under us
-	colorspace = CGBitmapContextGetColorSpace (surface->cgContext);
-	color_comps = CGColorSpaceGetNumberOfComponents (colorspace);
+    /* XXX TODO: We can handle many more data formats by
+     * converting to pixman_format_t */
 
-	// XXX TODO: We can handle all of these by converting to
-	// pixman masks, including non-native-endian masks
-	if (bpc != 8)
-	    return CAIRO_INT_STATUS_UNSUPPORTED;
+    if (bpp == 32 && color_comps == 3 &&
+	(bitinfo & kCGBitmapAlphaInfoMask) == kCGImageAlphaPremultipliedFirst &&
+	(bitinfo & kCGBitmapByteOrderMask) == kCGBitmapByteOrder32Host)
+    {
+	format = CAIRO_FORMAT_ARGB32;
+    }
+    else if (bpp == 32 && color_comps == 3 &&
+	     (bitinfo & kCGBitmapAlphaInfoMask) == kCGImageAlphaNoneSkipFirst &&
+	     (bitinfo & kCGBitmapByteOrderMask) == kCGBitmapByteOrder32Host)
+    {
+	format = CAIRO_FORMAT_RGB24;
+    }
+    else if (bpp == 8 && color_comps == 1)
+    {
+	format = CAIRO_FORMAT_A1;
+    }
+    else
+    {
+	return _cairo_image_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+    }
 
-	if (bpp != 32 && bpp != 8)
-	    return CAIRO_INT_STATUS_UNSUPPORTED;
+    imageData = CGBitmapContextGetData (surface->cgContext);
+    stride = CGBitmapContextGetBytesPerRow (surface->cgContext);
 
-	if (color_comps != 3 && color_comps != 1)
-	    return CAIRO_INT_STATUS_UNSUPPORTED;
+    return (cairo_image_surface_t *) cairo_image_surface_create_for_data (imageData,
+									  format,
+									  extents->width,
+									  extents->height,
+									  stride);
+}
 
-	if (bpp == 32 && color_comps == 3 &&
-	    (bitinfo & kCGBitmapAlphaInfoMask) == kCGImageAlphaPremultipliedFirst &&
-	    (bitinfo & kCGBitmapByteOrderMask) == kCGBitmapByteOrder32Host)
-	{
-	    isurf = (cairo_image_surface_t *)
-		cairo_image_surface_create_for_data (imageData,
-						     CAIRO_FORMAT_ARGB32,
-						     surface->extents.width,
-						     surface->extents.height,
-						     stride);
-	} else if (bpp == 32 && color_comps == 3 &&
-		   (bitinfo & kCGBitmapAlphaInfoMask) == kCGImageAlphaNoneSkipFirst &&
-		   (bitinfo & kCGBitmapByteOrderMask) == kCGBitmapByteOrder32Host)
-	{
-	    isurf = (cairo_image_surface_t *)
-		cairo_image_surface_create_for_data (imageData,
-						     CAIRO_FORMAT_RGB24,
-						     surface->extents.width,
-						     surface->extents.height,
-						     stride);
-	} else if (bpp == 8 && color_comps == 1)
-	{
-	    isurf = (cairo_image_surface_t *)
-		cairo_image_surface_create_for_data (imageData,
-						     CAIRO_FORMAT_A8,
-						     surface->extents.width,
-						     surface->extents.height,
-						     stride);
-	} else {
-	    return CAIRO_INT_STATUS_UNSUPPORTED;
-	}
-    } else {
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-    }
+static cairo_int_status_t
+_cairo_quartz_surface_unmap_image (void *abstract_surface,
+				   cairo_image_surface_t *image)
+{
+    cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
+
+    if (surface->imageSurfaceEquiv)
+	return _cairo_surface_unmap_image (surface->imageSurfaceEquiv, image);
+
+    cairo_surface_finish (&image->base);
+    cairo_surface_destroy (&image->base);
 
-    *image_out = isurf;
     return CAIRO_STATUS_SUCCESS;
 }
 
+
 /*
  * Cairo surface backend implementations
  */
@@ -1514,35 +1500,20 @@ _cairo_quartz_surface_acquire_source_image (void *abstract_surface,
 					     cairo_image_surface_t **image_out,
 					     void **image_extra)
 {
-    cairo_int_status_t status;
     cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
 
     //ND ((stderr, "%p _cairo_quartz_surface_acquire_source_image\n", surface));
 
-    status = _cairo_quartz_get_image (surface, image_out);
-    if (unlikely (status))
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
     *image_extra = NULL;
 
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_surface_t *
-_cairo_quartz_surface_snapshot (void *abstract_surface)
-{
-    cairo_int_status_t status;
-    cairo_quartz_surface_t *surface = abstract_surface;
-    cairo_image_surface_t *image;
-
-    if (surface->imageSurfaceEquiv)
-	return NULL;
-
-    status = _cairo_quartz_get_image (surface, &image);
-    if (unlikely (status))
-        return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
+    *image_out = _cairo_quartz_surface_map_to_image (surface, &surface->extents);
+    if (unlikely (cairo_surface_status(&(*image_out)->base))) {
+	cairo_surface_destroy (&(*image_out)->base);
+	*image_out = NULL;
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    }
 
-    return &image->base;
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static void
@@ -1550,39 +1521,7 @@ _cairo_quartz_surface_release_source_image (void *abstract_surface,
 					    cairo_image_surface_t *image,
 					    void *image_extra)
 {
-    cairo_surface_destroy (&image->base);
-}
-
-
-static cairo_image_surface_t *
-_cairo_quartz_surface_map_to_image (void *abstract_surface,
-				    const cairo_rectangle_int_t *extents)
-{
-    cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
-    cairo_image_surface_t *image;
-    cairo_surface_t *subsurface;
-    cairo_status_t status;
-
-    status = _cairo_quartz_get_image (surface, &image);
-    if (unlikely (status))
-	return _cairo_surface_create_in_error (status);
-
-    /* Is this legitimate? shouldn't it return an image surface? */
-    /* XXX: BROKEN! */
-
-    subsurface = _cairo_surface_create_for_rectangle_int (&image->base, extents);
-    cairo_surface_destroy (&image->base);
-
-    return subsurface;
-}
-
-static cairo_int_status_t
-_cairo_quartz_surface_unmap_image (void *abstract_surface,
-				   cairo_image_surface_t *image)
-{
-    cairo_surface_destroy (&image->base);
-
-    return CAIRO_STATUS_SUCCESS;
+    _cairo_quartz_surface_unmap_image (abstract_surface, image);
 }
 
 static cairo_surface_t *
@@ -2221,7 +2160,7 @@ static const struct _cairo_surface_backend cairo_quartz_surface_backend = {
     _cairo_surface_default_source,
     _cairo_quartz_surface_acquire_source_image,
     _cairo_quartz_surface_release_source_image,
-    _cairo_quartz_surface_snapshot,
+    NULL, /* snapshot */
 
     NULL, /* copy_page */
     NULL, /* show_page */
commit a8a4a8dfd450a8ce97998b5e5e09971d07a957f4
Author: Andrea Canciani <ranma42 at gmail.com>
Date:   Fri Jan 6 20:13:39 2012 +0100

    quartz: Mark surfaces created clear as is_clear
    
    This might provide a speedup when clearing an already clear surface
    and is required by cairo_surface_create_similar().
    
    Fixes zero-mask.

diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index 832e9fc..994b92f 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -2275,6 +2275,7 @@ _cairo_quartz_surface_create_internal (CGContextRef cgContext,
 	surface->cgContext = NULL;
 	surface->cgContextBaseCTM = CGAffineTransformIdentity;
 	surface->imageData = NULL;
+	surface->base.is_clear = TRUE;
 	return surface;
     }
 
@@ -2438,6 +2439,8 @@ cairo_quartz_surface_create (cairo_format_t format,
 	return &surf->base;
     }
 
+    surf->base.is_clear = TRUE;
+
     surf->imageData = imageData;
     surf->imageSurfaceEquiv = cairo_image_surface_create_for_data (imageData, format, width, height, stride);
 
commit 3735881e38d2bee941128725b8cdde6779d60a30
Author: Andrea Canciani <ranma42 at gmail.com>
Date:   Tue Apr 10 22:58:18 2012 +0200

    quartz: Silence warning
    
    cairo-quartz-surface.c:177: warning: enumeration value
    'CAIRO_FORMAT_RGB30' not handled in switch

diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index 422ef06..832e9fc 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -203,8 +203,9 @@ CairoQuartzCreateCGImage (cairo_format_t format,
 	    break;
 #endif
 
-        case CAIRO_FORMAT_RGB16_565:
-        case CAIRO_FORMAT_INVALID:
+	case CAIRO_FORMAT_RGB30:
+	case CAIRO_FORMAT_RGB16_565:
+	case CAIRO_FORMAT_INVALID:
 	default:
 	    return NULL;
     }
commit 13b7364836e14b811bbeb3ba0849e6d6c0fb1dd3
Author: Andrea Canciani <ranma42 at gmail.com>
Date:   Wed Jan 11 17:17:29 2012 +0100

    surface: Use the internal map/unmap
    
    In many places Cairo maps/unmaps surfaces to perform operations on the
    raw image, but it doesn't care about the format being invalid. All of
    these are appropriate users of _cairo_surface_map_to_image().

diff --git a/src/cairo-fallback-compositor.c b/src/cairo-fallback-compositor.c
index efc8a79..3f6199f 100644
--- a/src/cairo-fallback-compositor.c
+++ b/src/cairo-fallback-compositor.c
@@ -42,6 +42,7 @@
 #include "cairoint.h"
 
 #include "cairo-compositor-private.h"
+#include "cairo-image-surface-private.h"
 #include "cairo-surface-offset-private.h"
 
 /* high-level compositor interface */
@@ -50,41 +51,43 @@ static cairo_int_status_t
 _cairo_fallback_compositor_paint (const cairo_compositor_t	*_compositor,
 				  cairo_composite_rectangles_t	*extents)
 {
-    cairo_surface_t *image;
+    cairo_image_surface_t *image;
     cairo_int_status_t status;
 
     TRACE ((stderr, "%s\n", __FUNCTION__));
-    image = cairo_surface_map_to_image (extents->surface, &extents->unbounded);
-    status = _cairo_surface_offset_paint (image,
+
+    image = _cairo_surface_map_to_image (extents->surface, &extents->unbounded);
+
+    status = _cairo_surface_offset_paint (&image->base,
 					  extents->unbounded.x,
 					  extents->unbounded.y,
 					  extents->op,
 					  &extents->source_pattern.base,
 					  extents->clip);
-    cairo_surface_unmap_image (extents->surface, image);
 
-    return status;
+    return _cairo_surface_unmap_image (extents->surface, image);
 }
 
 static cairo_int_status_t
 _cairo_fallback_compositor_mask (const cairo_compositor_t	*_compositor,
 				 cairo_composite_rectangles_t	*extents)
 {
-    cairo_surface_t *image;
+    cairo_image_surface_t *image;
     cairo_int_status_t status;
 
     TRACE ((stderr, "%s\n", __FUNCTION__));
-    image = cairo_surface_map_to_image (extents->surface, &extents->unbounded);
-    status = _cairo_surface_offset_mask (image,
+
+    image = _cairo_surface_map_to_image (extents->surface, &extents->unbounded);
+
+    status = _cairo_surface_offset_mask (&image->base,
 					 extents->unbounded.x,
 					 extents->unbounded.y,
 					 extents->op,
 					 &extents->source_pattern.base,
 					 &extents->mask_pattern.base,
 					 extents->clip);
-    cairo_surface_unmap_image (extents->surface, image);
 
-    return status;
+    return _cairo_surface_unmap_image (extents->surface, image);
 }
 
 static cairo_int_status_t
@@ -97,12 +100,14 @@ _cairo_fallback_compositor_stroke (const cairo_compositor_t	*_compositor,
 				   double			 tolerance,
 				   cairo_antialias_t		 antialias)
 {
-    cairo_surface_t *image;
+    cairo_image_surface_t *image;
     cairo_int_status_t status;
 
     TRACE ((stderr, "%s\n", __FUNCTION__));
-    image = cairo_surface_map_to_image (extents->surface, &extents->unbounded);
-    status = _cairo_surface_offset_stroke (image,
+
+    image = _cairo_surface_map_to_image (extents->surface, &extents->unbounded);
+
+    status = _cairo_surface_offset_stroke (&image->base,
 					   extents->unbounded.x,
 					   extents->unbounded.y,
 					   extents->op,
@@ -112,9 +117,8 @@ _cairo_fallback_compositor_stroke (const cairo_compositor_t	*_compositor,
 					   tolerance,
 					   antialias,
 					   extents->clip);
-    cairo_surface_unmap_image (extents->surface, image);
 
-    return status;
+    return _cairo_surface_unmap_image (extents->surface, image);
 }
 
 static cairo_int_status_t
@@ -125,12 +129,14 @@ _cairo_fallback_compositor_fill (const cairo_compositor_t	*_compositor,
 				 double				 tolerance,
 				 cairo_antialias_t		 antialias)
 {
-    cairo_surface_t *image;
+    cairo_image_surface_t *image;
     cairo_int_status_t status;
 
     TRACE ((stderr, "%s\n", __FUNCTION__));
-    image = cairo_surface_map_to_image (extents->surface, &extents->unbounded);
-    status = _cairo_surface_offset_fill (image,
+
+    image = _cairo_surface_map_to_image (extents->surface, &extents->unbounded);
+
+    status = _cairo_surface_offset_fill (&image->base,
 					 extents->unbounded.x,
 					 extents->unbounded.y,
 					 extents->op,
@@ -138,9 +144,8 @@ _cairo_fallback_compositor_fill (const cairo_compositor_t	*_compositor,
 					 path,
 					 fill_rule, tolerance, antialias,
 					 extents->clip);
-    cairo_surface_unmap_image (extents->surface, image);
 
-    return status;
+    return _cairo_surface_unmap_image (extents->surface, image);
 }
 
 static cairo_int_status_t
@@ -151,21 +156,22 @@ _cairo_fallback_compositor_glyphs (const cairo_compositor_t	*_compositor,
 				   int				 num_glyphs,
 				   cairo_bool_t			 overlap)
 {
-    cairo_surface_t *image;
+    cairo_image_surface_t *image;
     cairo_int_status_t status;
 
     TRACE ((stderr, "%s\n", __FUNCTION__));
-    image = cairo_surface_map_to_image (extents->surface, &extents->unbounded);
-    status = _cairo_surface_offset_glyphs (image,
+
+    image = _cairo_surface_map_to_image (extents->surface, &extents->unbounded);
+
+    status = _cairo_surface_offset_glyphs (&image->base,
 					   extents->unbounded.x,
 					   extents->unbounded.y,
 					   extents->op,
 					   &extents->source_pattern.base,
 					   scaled_font, glyphs, num_glyphs,
 					   extents->clip);
-    cairo_surface_unmap_image (extents->surface, image);
 
-    return status;
+    return _cairo_surface_unmap_image (extents->surface, image);
 }
 
 const cairo_compositor_t _cairo_fallback_compositor = {
diff --git a/src/cairo-gl-operand.c b/src/cairo-gl-operand.c
index bbb501e..d3df95b 100644
--- a/src/cairo-gl-operand.c
+++ b/src/cairo-gl-operand.c
@@ -292,7 +292,7 @@ _cairo_gl_pattern_texture_setup (cairo_gl_operand_t *operand,
     cairo_status_t status;
     cairo_gl_surface_t *surface;
     cairo_gl_context_t *ctx;
-    cairo_surface_t *image;
+    cairo_image_surface_t *image;
     cairo_bool_t src_is_gl_surface = FALSE;
     cairo_rectangle_int_t map_extents;
 
@@ -311,7 +311,7 @@ _cairo_gl_pattern_texture_setup (cairo_gl_operand_t *operand,
 					  extents->width, extents->height);
     map_extents = *extents;
     map_extents.x = map_extents.y = 0;
-    image = cairo_surface_map_to_image (&surface->base, &map_extents);
+    image = _cairo_surface_map_to_image (&surface->base, &map_extents);
 
     /* If the pattern is a GL surface, it belongs to some other GL context,
        so we need to release this device while we paint it to the image. */
@@ -321,7 +321,7 @@ _cairo_gl_pattern_texture_setup (cairo_gl_operand_t *operand,
 	    goto fail;
     }
 
-    status = _cairo_surface_offset_paint (image, extents->x, extents->y,
+    status = _cairo_surface_offset_paint (&image->base, extents->x, extents->y,
 					  CAIRO_OPERATOR_SOURCE, _src, NULL);
 
     if (src_is_gl_surface) {
@@ -330,7 +330,7 @@ _cairo_gl_pattern_texture_setup (cairo_gl_operand_t *operand,
 	    goto fail;
     }
 
-    cairo_surface_unmap_image (&surface->base, image);
+    status = _cairo_surface_unmap_image (&surface->base, image);
     status = _cairo_gl_context_release (ctx, status);
     if (unlikely (status))
 	goto fail;
diff --git a/src/cairo-surface-observer.c b/src/cairo-surface-observer.c
index 125f96b..83fd1f8 100644
--- a/src/cairo-surface-observer.c
+++ b/src/cairo-surface-observer.c
@@ -662,9 +662,9 @@ sync (cairo_surface_t *target, int x, int y)
     extents.width  = 1;
     extents.height = 1;
 
-    cairo_surface_unmap_image (target,
-			       cairo_surface_map_to_image (target,
-							   &extents));
+    _cairo_surface_unmap_image (target,
+				_cairo_surface_map_to_image (target,
+							     &extents));
 }
 
 static void
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 4aa3ddb..0e5484c 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -808,7 +808,6 @@ cairo_surface_map_to_image (cairo_surface_t  *surface,
 
     return imagesurf;
 }
-slim_hidden_def (cairo_surface_map_to_image);
 
 /**
  * cairo_surface_unmap_image:
@@ -864,7 +863,6 @@ error:
     cairo_surface_finish (image);
     cairo_surface_destroy (image);
 }
-slim_hidden_def (cairo_surface_unmap_image);
 
 cairo_surface_t *
 _cairo_surface_create_similar_solid (cairo_surface_t	 *other,
diff --git a/src/cairo-xlib-source.c b/src/cairo-xlib-source.c
index dec7622..ac0fdf8 100644
--- a/src/cairo-xlib-source.c
+++ b/src/cairo-xlib-source.c
@@ -259,7 +259,7 @@ render_pattern (cairo_xlib_surface_t *dst,
 {
     Display *dpy = dst->display->display;
     cairo_xlib_surface_t *src;
-    cairo_surface_t *image;
+    cairo_image_surface_t *image;
     cairo_status_t status;
     cairo_rectangle_int_t map_extents;
 
@@ -276,11 +276,11 @@ render_pattern (cairo_xlib_surface_t *dst,
     map_extents = *extents;
     map_extents.x = map_extents.y = 0;
 
-    image = cairo_surface_map_to_image (&src->base, &map_extents);
-    status = _cairo_surface_offset_paint (image, extents->x, extents->y,
+    image = _cairo_surface_map_to_image (&src->base, &map_extents);
+    status = _cairo_surface_offset_paint (&image->base, extents->x, extents->y,
 					  CAIRO_OPERATOR_SOURCE, pattern,
 					  NULL);
-    cairo_surface_unmap_image (&src->base, image);
+    status = _cairo_surface_unmap_image (&src->base, image);
     if (unlikely (status)) {
 	cairo_surface_destroy (&src->base);
 	return _cairo_surface_create_in_error (status);
@@ -913,7 +913,7 @@ surface_source (cairo_xlib_surface_t *dst,
 		int *src_x, int *src_y)
 {
     cairo_xlib_surface_t *src;
-    cairo_surface_t *image;
+    cairo_image_surface_t *image;
     cairo_surface_pattern_t local_pattern;
     cairo_status_t status;
     cairo_rectangle_int_t upload, limit, map_extents;
@@ -946,12 +946,12 @@ surface_source (cairo_xlib_surface_t *dst,
     map_extents = upload;
     map_extents.x = map_extents.y = 0;
 
-    image = cairo_surface_map_to_image (&src->base, &map_extents);
-    status = _cairo_surface_paint (image,
+    image = _cairo_surface_map_to_image (&src->base, &map_extents);
+    status = _cairo_surface_paint (&image->base,
 				   CAIRO_OPERATOR_SOURCE,
 				   &local_pattern.base,
 				   NULL);
-    cairo_surface_unmap_image (&src->base, image);
+    status = _cairo_surface_unmap_image (&src->base, image);
     _cairo_pattern_fini (&local_pattern.base);
 
     if (unlikely (status)) {
diff --git a/src/cairoint.h b/src/cairoint.h
index 5b3d653..2c9f2dd 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1922,7 +1922,6 @@ slim_hidden_proto (cairo_surface_get_font_options);
 slim_hidden_proto (cairo_surface_get_mime_data);
 slim_hidden_proto (cairo_surface_get_type);
 slim_hidden_proto (cairo_surface_has_show_text_glyphs);
-slim_hidden_proto (cairo_surface_map_to_image);
 slim_hidden_proto (cairo_surface_mark_dirty);
 slim_hidden_proto (cairo_surface_mark_dirty_rectangle);
 slim_hidden_proto_no_warn (cairo_surface_reference);
@@ -1932,7 +1931,6 @@ slim_hidden_proto (cairo_surface_set_mime_data);
 slim_hidden_proto (cairo_surface_show_page);
 slim_hidden_proto (cairo_surface_status);
 slim_hidden_proto (cairo_surface_supports_mime_type);
-slim_hidden_proto (cairo_surface_unmap_image);
 slim_hidden_proto (cairo_text_cluster_allocate);
 slim_hidden_proto (cairo_text_cluster_free);
 slim_hidden_proto (cairo_toy_font_face_create);
commit 37c5c2dbe55f64ee84ab248eb0072d5d7c5145cc
Author: Andrea Canciani <ranma42 at gmail.com>
Date:   Wed Jan 11 20:51:29 2012 +0100

    surface: Only use non-NULL extents for internal mapping
    
    _cairo_surface_map_to_image() requires the input extents to be
    non-NULL.

diff --git a/src/cairo-gl-operand.c b/src/cairo-gl-operand.c
index 1c7ad2f..bbb501e 100644
--- a/src/cairo-gl-operand.c
+++ b/src/cairo-gl-operand.c
@@ -294,6 +294,7 @@ _cairo_gl_pattern_texture_setup (cairo_gl_operand_t *operand,
     cairo_gl_context_t *ctx;
     cairo_surface_t *image;
     cairo_bool_t src_is_gl_surface = FALSE;
+    cairo_rectangle_int_t map_extents;
 
     if (_src->type == CAIRO_PATTERN_TYPE_SURFACE) {
 	cairo_surface_t* src_surface = ((cairo_surface_pattern_t *) _src)->surface;
@@ -308,7 +309,9 @@ _cairo_gl_pattern_texture_setup (cairo_gl_operand_t *operand,
 	_cairo_gl_surface_create_scratch (ctx,
 					  CAIRO_CONTENT_COLOR_ALPHA,
 					  extents->width, extents->height);
-    image = cairo_surface_map_to_image (&surface->base, NULL);
+    map_extents = *extents;
+    map_extents.x = map_extents.y = 0;
+    image = cairo_surface_map_to_image (&surface->base, &map_extents);
 
     /* If the pattern is a GL surface, it belongs to some other GL context,
        so we need to release this device while we paint it to the image. */
diff --git a/src/cairo-xlib-source.c b/src/cairo-xlib-source.c
index f8dac70..dec7622 100644
--- a/src/cairo-xlib-source.c
+++ b/src/cairo-xlib-source.c
@@ -261,6 +261,7 @@ render_pattern (cairo_xlib_surface_t *dst,
     cairo_xlib_surface_t *src;
     cairo_surface_t *image;
     cairo_status_t status;
+    cairo_rectangle_int_t map_extents;
 
     src = (cairo_xlib_surface_t *)
 	_cairo_surface_create_similar_scratch (&dst->base,
@@ -272,7 +273,10 @@ render_pattern (cairo_xlib_surface_t *dst,
 	return None;
     }
 
-    image = cairo_surface_map_to_image (&src->base, NULL);
+    map_extents = *extents;
+    map_extents.x = map_extents.y = 0;
+
+    image = cairo_surface_map_to_image (&src->base, &map_extents);
     status = _cairo_surface_offset_paint (image, extents->x, extents->y,
 					  CAIRO_OPERATOR_SOURCE, pattern,
 					  NULL);
@@ -912,7 +916,7 @@ surface_source (cairo_xlib_surface_t *dst,
     cairo_surface_t *image;
     cairo_surface_pattern_t local_pattern;
     cairo_status_t status;
-    cairo_rectangle_int_t upload, limit;
+    cairo_rectangle_int_t upload, limit, map_extents;
     cairo_matrix_t m;
 
     upload = *sample;
@@ -939,7 +943,10 @@ surface_source (cairo_xlib_surface_t *dst,
     cairo_matrix_init_translate (&local_pattern.base.matrix,
 				 upload.x, upload.y);
 
-    image = cairo_surface_map_to_image (&src->base, NULL);
+    map_extents = upload;
+    map_extents.x = map_extents.y = 0;
+
+    image = cairo_surface_map_to_image (&src->base, &map_extents);
     status = _cairo_surface_paint (image,
 				   CAIRO_OPERATOR_SOURCE,
 				   &local_pattern.base,
commit d6fb8d2134c989d2ad455ec37ce4f623d4769c46
Author: Andrea Canciani <ranma42 at gmail.com>
Date:   Wed Jan 11 17:17:15 2012 +0100

    surface: Make backend-specific map/unmap functions symmetric
    
    Map allocates a surface. Symmetrically, unmap should destroy it.

diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index 4c9c434..a6093b4 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -1170,11 +1170,18 @@ static cairo_int_status_t
 _cairo_gl_surface_unmap_image (void		      *abstract_surface,
 			       cairo_image_surface_t *image)
 {
-    return _cairo_gl_surface_draw_image (abstract_surface, image,
-					 0, 0,
-					 image->width, image->height,
-					 image->base.device_transform_inverse.x0,
-					 image->base.device_transform_inverse.y0);
+    cairo_int_status_t status;
+
+    status = _cairo_gl_surface_draw_image (abstract_surface, image,
+					   0, 0,
+					   image->width, image->height,
+					   image->base.device_transform_inverse.x0,
+					   image->base.device_transform_inverse.y0);
+
+    cairo_surface_finish (&image->base);
+    cairo_surface_destroy (&image->base);
+
+    return status;
 }
 
 static cairo_bool_t
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index 33f6160..13e1d03 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -821,6 +821,9 @@ cairo_int_status_t
 _cairo_image_surface_unmap_image (void *abstract_surface,
 				  cairo_image_surface_t *image)
 {
+    cairo_surface_finish (&image->base);
+    cairo_surface_destroy (&image->base);
+
     return CAIRO_INT_STATUS_SUCCESS;
 }
 
diff --git a/src/cairo-os2-surface.c b/src/cairo-os2-surface.c
index edef42e..1ab50f9 100644
--- a/src/cairo-os2-surface.c
+++ b/src/cairo-os2-surface.c
@@ -596,6 +596,7 @@ _cairo_os2_surface_map_to_image (void *abstract_surface,
     surface->pixel_array_lend_count++;
     DosReleaseMutexSem (local_os2_surface->hmtx_use_private_fields);
 
+    /* XXX: BROKEN! */
     *image_out = _cairo_surface_create_for_rectangle_int (surface->image_surface,
 							  extents);
 
diff --git a/src/cairo-quartz-image-surface.c b/src/cairo-quartz-image-surface.c
index da10a98..391ab01 100644
--- a/src/cairo-quartz-image-surface.c
+++ b/src/cairo-quartz-image-surface.c
@@ -112,8 +112,7 @@ _cairo_quartz_image_surface_map_to_image (void *asurface,
 					  const cairo_rectangle_int_t *extents)
 {
     cairo_quartz_image_surface_t *surface = (cairo_quartz_image_surface_t *) asurface;
-
-    return cairo_surface_map_to_image (&surface->imageSurface->base, extents);
+    return _cairo_surface_map_to_image (&surface->imageSurface->base, extents);
 }
 
 static cairo_int_status_t
@@ -121,9 +120,7 @@ _cairo_quartz_image_surface_unmap_image (void *asurface,
 					 cairo_image_surface_t *image)
 {
     cairo_quartz_image_surface_t *surface = (cairo_quartz_image_surface_t *) asurface;
-
-    cairo_surface_unmap_image (&surface->imageSurface->base, &image->base);
-    return cairo_surface_status (&surface->imageSurface->base);
+    return _cairo_surface_unmap_image (&surface->imageSurface->base, image);
 }
 
 static cairo_bool_t
diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index 3010988..422ef06 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -1567,6 +1567,7 @@ _cairo_quartz_surface_map_to_image (void *abstract_surface,
 	return _cairo_surface_create_in_error (status);
 
     /* Is this legitimate? shouldn't it return an image surface? */
+    /* XXX: BROKEN! */
 
     subsurface = _cairo_surface_create_for_rectangle_int (&image->base, extents);
     cairo_surface_destroy (&image->base);
diff --git a/src/cairo-surface-observer.c b/src/cairo-surface-observer.c
index 1922398..125f96b 100644
--- a/src/cairo-surface-observer.c
+++ b/src/cairo-surface-observer.c
@@ -479,11 +479,7 @@ _cairo_surface_observer_map_to_image (void *abstract_surface,
 				      const cairo_rectangle_int_t *extents)
 {
     cairo_surface_observer_t *surface = abstract_surface;
-
-    if (surface->target->backend->map_to_image == NULL)
-	return NULL;
-
-    return surface->target->backend->map_to_image (surface->target, extents);
+    return _cairo_surface_map_to_image (surface->target, extents);
 }
 
 static cairo_int_status_t
@@ -491,11 +487,7 @@ _cairo_surface_observer_unmap_image (void *abstract_surface,
 				     cairo_image_surface_t *image)
 {
     cairo_surface_observer_t *surface = abstract_surface;
-
-    if (surface->target->backend->unmap_image == NULL)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    return surface->target->backend->unmap_image (surface->target, image);
+    return _cairo_surface_unmap_image (surface->target, image);
 }
 
 static void
diff --git a/src/cairo-surface-subsurface.c b/src/cairo-surface-subsurface.c
index 020b961..90440c7 100644
--- a/src/cairo-surface-subsurface.c
+++ b/src/cairo-surface-subsurface.c
@@ -91,16 +91,12 @@ _cairo_surface_subsurface_map_to_image (void *abstract_surface,
     cairo_surface_subsurface_t *surface = abstract_surface;
     cairo_rectangle_int_t target_extents;
 
-    if (surface->target->backend->map_to_image == NULL)
-	return NULL;
-
     target_extents.x = extents->x + surface->extents.x;
     target_extents.y = extents->y + surface->extents.y;
     target_extents.width  = extents->width;
     target_extents.height = extents->height;
 
-    return surface->target->backend->map_to_image (surface->target,
-						   &target_extents);
+    return _cairo_surface_map_to_image (surface->target, &target_extents);
 }
 
 static cairo_int_status_t
@@ -108,11 +104,7 @@ _cairo_surface_subsurface_unmap_image (void *abstract_surface,
 				       cairo_image_surface_t *image)
 {
     cairo_surface_subsurface_t *surface = abstract_surface;
-
-    if (surface->target->backend->unmap_image == NULL)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    return surface->target->backend->unmap_image (surface->target, image);
+    return _cairo_surface_unmap_image (surface->target, image);
 }
 
 static cairo_int_status_t
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index e28e115..4aa3ddb 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -694,7 +694,7 @@ _cairo_surface_unmap_image (cairo_surface_t       *surface,
     {
 	status = surface->backend->unmap_image (surface, image);
 	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
-	    goto destroy;
+	    return status;
     }
 
     _cairo_pattern_init_for_surface (&pattern, &image->base);
diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c
index 489e17e..1a591ca 100644
--- a/src/cairo-xcb-surface.c
+++ b/src/cairo-xcb-surface.c
@@ -764,7 +764,7 @@ _cairo_xcb_surface_map_to_image (void *abstract_surface,
     cairo_status_t status;
 
     if (surface->fallback)
-	return surface->fallback->base.backend->map_to_image (&surface->fallback->base, extents);
+	return _cairo_surface_map_to_image (&surface->fallback->base, extents);
 
     image = _get_image (surface, TRUE,
 			extents->x, extents->y,
@@ -799,10 +799,17 @@ _cairo_xcb_surface_unmap (void *abstract_surface,
 			  cairo_image_surface_t *image)
 {
     cairo_xcb_surface_t *surface = abstract_surface;
+    cairo_int_status_t status;
 
     if (surface->fallback)
-	return surface->fallback->base.backend->unmap_image (&surface->fallback->base, image);
-    return _put_image (abstract_surface, image);
+	return _cairo_surface_unmap_image (&surface->fallback->base, image);
+
+    status = _put_image (abstract_surface, image);
+
+    cairo_surface_finish (&image->base);
+    cairo_surface_destroy (&image->base);
+
+    return status;
 }
 
 static cairo_surface_t *
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 9dadca6..59a7885 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -1294,11 +1294,18 @@ static cairo_int_status_t
 _cairo_xlib_surface_unmap_image (void *abstract_surface,
 				 cairo_image_surface_t *image)
 {
-    return _cairo_xlib_surface_draw_image (abstract_surface, image,
-					   0, 0,
-					   image->width, image->height,
-					   image->base.device_transform_inverse.x0,
-					   image->base.device_transform_inverse.y0);
+    cairo_int_status_t status;
+
+    status = _cairo_xlib_surface_draw_image (abstract_surface, image,
+					     0, 0,
+					     image->width, image->height,
+					     image->base.device_transform_inverse.x0,
+					     image->base.device_transform_inverse.y0);
+
+    cairo_surface_finish (&image->base);
+    cairo_surface_destroy (&image->base);
+
+    return status;
 }
 
 static cairo_bool_t
diff --git a/src/cairo-xlib-xcb-surface.c b/src/cairo-xlib-xcb-surface.c
index 1df5de8..c106964 100644
--- a/src/cairo-xlib-xcb-surface.c
+++ b/src/cairo-xlib-xcb-surface.c
@@ -121,7 +121,7 @@ _cairo_xlib_xcb_surface_map_to_image (void *abstract_surface,
 				      const cairo_rectangle_int_t *extents)
 {
     cairo_xlib_xcb_surface_t *surface = abstract_surface;
-    return cairo_surface_map_to_image (&surface->xcb->base, extents);
+    return _cairo_surface_map_to_image (&surface->xcb->base, extents);
 }
 
 static cairo_int_status_t
@@ -129,13 +129,7 @@ _cairo_xlib_xcb_surface_unmap (void *abstract_surface,
 			       cairo_image_surface_t *image)
 {
     cairo_xlib_xcb_surface_t *surface = abstract_surface;
-
-    /* cairo_surface_unmap_image destroys the surface, so get a new reference
-     * for it to destroy.
-     */
-    cairo_surface_reference (&image->base);
-    cairo_surface_unmap_image (&surface->xcb->base, &image->base);
-    return cairo_surface_status (&surface->xcb->base);
+    return _cairo_surface_unmap_image (&surface->xcb->base, image);
 }
 
 static cairo_surface_t *
commit df7829e2cca07c3bfcddda1c66ca56280edceaf4
Author: Andrea Canciani <ranma42 at gmail.com>
Date:   Tue Apr 10 20:15:04 2012 +0200

    surface: Make map_to_image return cairo_image_surface_t*
    
    This makes it easier to check that the funciton is returning the
    correct type of surfaces.

diff --git a/src/cairo-directfb-surface.c b/src/cairo-directfb-surface.c
index fd187bd..494ec07 100644
--- a/src/cairo-directfb-surface.c
+++ b/src/cairo-directfb-surface.c
@@ -40,7 +40,7 @@
 #include "cairo-compositor-private.h"
 #include "cairo-default-context-private.h"
 #include "cairo-error-private.h"
-#include "cairo-image-surface-private.h"
+#include "cairo-image-surface-inline.h"
 #include "cairo-pattern-private.h"
 #include "cairo-surface-backend-private.h"
 #include "cairo-surface-fallback-private.h"
@@ -171,7 +171,7 @@ _cairo_dfb_surface_finish (void *abstract_surface)
     return _cairo_image_surface_finish (abstract_surface);
 }
 
-static cairo_surface_t *
+static cairo_image_surface_t *
 _cairo_dfb_surface_map_to_image (void *abstract_surface,
 				 const cairo_rectangle_int_t *extents)
 {
@@ -184,7 +184,7 @@ _cairo_dfb_surface_map_to_image (void *abstract_surface,
 	int pitch;
 
 	if (buffer->Lock (buffer, DSLF_READ | DSLF_WRITE, &data, &pitch))
-	    return _cairo_surface_create_in_error(_cairo_error (CAIRO_STATUS_NO_MEMORY));
+	    return _cairo_image_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 
 	image = pixman_image_create_bits (surface->image.pixman_format,
 					  surface->image.width,
@@ -192,19 +192,20 @@ _cairo_dfb_surface_map_to_image (void *abstract_surface,
 					  data, pitch);
 	if (image == NULL) {
 	    buffer->Unlock (buffer);
-	    return _cairo_surface_create_in_error(_cairo_error (CAIRO_STATUS_NO_MEMORY));
+	    return _cairo_image_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 	}
 	_cairo_image_surface_init (&surface->image, image, surface->image.pixman_format);
     }
 
-    return _cairo_image_surface_map_to_image (&surface->image, extents);
+    return _cairo_surface_map_to_image (&surface->image.base, extents);
 }
 
 static cairo_int_status_t
 _cairo_dfb_surface_unmap_image (void *abstract_surface,
 				cairo_image_surface_t *image)
 {
-    return CAIRO_INT_STATUS_SUCCESS;
+    cairo_dfb_surface_t *surface = abstract_surface;
+    return _cairo_surface_unmap_image (&surface->image.base, image);
 }
 
 static cairo_status_t
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index c2e9687..4c9c434 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -46,7 +46,7 @@
 #include "cairo-compositor-private.h"
 #include "cairo-default-context-private.h"
 #include "cairo-error-private.h"
-#include "cairo-image-surface-private.h"
+#include "cairo-image-surface-inline.h"
 #include "cairo-surface-backend-private.h"
 
 static const cairo_surface_backend_t _cairo_gl_surface_backend;
@@ -985,7 +985,7 @@ _cairo_gl_surface_finish (void *abstract_surface)
     return _cairo_gl_context_release (ctx, status);
 }
 
-static cairo_surface_t *
+static cairo_image_surface_t *
 _cairo_gl_surface_map_to_image (void      *abstract_surface,
 				const cairo_rectangle_int_t   *extents)
 {
@@ -1050,15 +1050,15 @@ _cairo_gl_surface_map_to_image (void      *abstract_surface,
 							extents->height,
 							-1);
     if (unlikely (image->base.status))
-	return &image->base;
+	return image;
 
     if (surface->base.serial == 0)
-	return &image->base;
+	return image;
 
     status = _cairo_gl_context_acquire (surface->base.device, &ctx);
     if (unlikely (status)) {
 	cairo_surface_destroy (&image->base);
-	return _cairo_surface_create_in_error (status);
+	return _cairo_image_surface_create_in_error (status);
     }
 
     cairo_surface_set_device_offset (&image->base, -extents->x, -extents->y);
@@ -1092,7 +1092,7 @@ _cairo_gl_surface_map_to_image (void      *abstract_surface,
     status = _cairo_gl_context_release (ctx, status);
     if (unlikely (status)) {
 	cairo_surface_destroy (&image->base);
-	return _cairo_surface_create_in_error (status);
+	return _cairo_image_surface_create_in_error (status);
     }
 
     /* We must invert the image manualy if we lack GL_MESA_pack_invert */
@@ -1105,7 +1105,7 @@ _cairo_gl_surface_map_to_image (void      *abstract_surface,
 	    row = malloc (image->stride);
 	    if (unlikely (row == NULL)) {
 		cairo_surface_destroy (&image->base);
-		return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+		return _cairo_image_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 	    }
 	}
 
@@ -1121,7 +1121,7 @@ _cairo_gl_surface_map_to_image (void      *abstract_surface,
 	    free(row);
     }
 
-    return &image->base;
+    return image;
 }
 
 static cairo_surface_t *
diff --git a/src/cairo-image-surface-inline.h b/src/cairo-image-surface-inline.h
index 95cbb99..d529bde 100644
--- a/src/cairo-image-surface-inline.h
+++ b/src/cairo-image-surface-inline.h
@@ -42,6 +42,12 @@
 
 CAIRO_BEGIN_DECLS
 
+static inline cairo_image_surface_t *
+_cairo_image_surface_create_in_error (cairo_status_t status)
+{
+    return (cairo_image_surface_t *) _cairo_surface_create_in_error (status);
+}
+
 static inline void
 _cairo_image_surface_set_parent (cairo_image_surface_t *image,
 				 cairo_surface_t *parent)
diff --git a/src/cairo-image-surface-private.h b/src/cairo-image-surface-private.h
index 6f5f05b..8f7364c 100644
--- a/src/cairo-image-surface-private.h
+++ b/src/cairo-image-surface-private.h
@@ -151,7 +151,7 @@ _cairo_image_surface_init (cairo_image_surface_t *surface,
 			   pixman_image_t	*pixman_image,
 			   pixman_format_code_t	 pixman_format);
 
-cairo_private cairo_surface_t *
+cairo_private cairo_image_surface_t *
 _cairo_image_surface_map_to_image (void *abstract_other,
 				   const cairo_rectangle_int_t *extents);
 
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index 00369b6..33f6160 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -794,7 +794,7 @@ _cairo_image_surface_snapshot (void *abstract_surface)
     return &clone->base;
 }
 
-cairo_surface_t *
+cairo_image_surface_t *
 _cairo_image_surface_map_to_image (void *abstract_other,
 				   const cairo_rectangle_int_t *extents)
 {
@@ -814,7 +814,7 @@ _cairo_image_surface_map_to_image (void *abstract_other,
 							other->stride);
 
     cairo_surface_set_device_offset (surface, -extents->x, -extents->y);
-    return surface;
+    return (cairo_image_surface_t *) surface;
 }
 
 cairo_int_status_t
diff --git a/src/cairo-os2-surface.c b/src/cairo-os2-surface.c
index 19646fb..edef42e 100644
--- a/src/cairo-os2-surface.c
+++ b/src/cairo-os2-surface.c
@@ -585,7 +585,7 @@ _cairo_os2_surface_release_source_image (void                  *abstract_surface
     DosReleaseMutexSem (surface->hmtx_use_private_fields);
 }
 
-static cairo_surface_t *
+static cairo_image_surface_t *
 _cairo_os2_surface_map_to_image (void *abstract_surface,
 				 const cairo_rectangle_int_t *extents)
 {
diff --git a/src/cairo-quartz-image-surface.c b/src/cairo-quartz-image-surface.c
index 763ce96..da10a98 100644
--- a/src/cairo-quartz-image-surface.c
+++ b/src/cairo-quartz-image-surface.c
@@ -107,7 +107,7 @@ _cairo_quartz_image_surface_acquire_source_image (void *asurface,
     return CAIRO_STATUS_SUCCESS;
 }
 
-static cairo_surface_t *
+static cairo_image_surface_t *
 _cairo_quartz_image_surface_map_to_image (void *asurface,
 					  const cairo_rectangle_int_t *extents)
 {
diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index d216261..3010988 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -1553,7 +1553,7 @@ _cairo_quartz_surface_release_source_image (void *abstract_surface,
 }
 
 
-static cairo_surface_t *
+static cairo_image_surface_t *
 _cairo_quartz_surface_map_to_image (void *abstract_surface,
 				    const cairo_rectangle_int_t *extents)
 {
diff --git a/src/cairo-surface-backend-private.h b/src/cairo-surface-backend-private.h
index fbaa912..c275ce6 100644
--- a/src/cairo-surface-backend-private.h
+++ b/src/cairo-surface-backend-private.h
@@ -63,7 +63,7 @@ struct _cairo_surface_backend {
 				 int			 width,
 				 int			 height);
 
-    cairo_surface_t *
+    cairo_image_surface_t *
     (*map_to_image)		(void			*surface,
 				 const cairo_rectangle_int_t  *extents);
     cairo_int_status_t
diff --git a/src/cairo-surface-observer.c b/src/cairo-surface-observer.c
index 9247bc4..1922398 100644
--- a/src/cairo-surface-observer.c
+++ b/src/cairo-surface-observer.c
@@ -474,7 +474,7 @@ _cairo_surface_observer_create_similar_image (void *other,
     return NULL;
 }
 
-static cairo_surface_t *
+static cairo_image_surface_t *
 _cairo_surface_observer_map_to_image (void *abstract_surface,
 				      const cairo_rectangle_int_t *extents)
 {
diff --git a/src/cairo-surface-subsurface.c b/src/cairo-surface-subsurface.c
index dfea05c..020b961 100644
--- a/src/cairo-surface-subsurface.c
+++ b/src/cairo-surface-subsurface.c
@@ -84,7 +84,7 @@ _cairo_surface_subsurface_create_similar_image (void *other,
 							   width, height);
 }
 
-static cairo_surface_t *
+static cairo_image_surface_t *
 _cairo_surface_subsurface_map_to_image (void *abstract_surface,
 					const cairo_rectangle_int_t *extents)
 {
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 99cbfbe..e28e115 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -638,7 +638,7 @@ _cairo_surface_map_to_image (cairo_surface_t  *surface,
 
     /* TODO: require map_to_image != NULL */
     if (surface->backend->map_to_image)
-	image = (cairo_image_surface_t *) surface->backend->map_to_image (surface, extents);
+	image = surface->backend->map_to_image (surface, extents);
 
     if (image == NULL)
 	image = _cairo_image_surface_clone_subimage (surface, extents);
diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c
index c6a1d29..489e17e 100644
--- a/src/cairo-xcb-surface.c
+++ b/src/cairo-xcb-surface.c
@@ -45,8 +45,8 @@
 
 #include "cairo-composite-rectangles-private.h"
 #include "cairo-default-context-private.h"
+#include "cairo-image-surface-inline.h"
 #include "cairo-list-inline.h"
-#include "cairo-image-surface-private.h"
 #include "cairo-surface-backend-private.h"
 
 #if CAIRO_HAS_XLIB_XCB_FUNCTIONS
@@ -755,12 +755,13 @@ _cairo_xcb_surface_flush (void *abstract_surface)
     return status;
 }
 
-static cairo_surface_t *
+static cairo_image_surface_t *
 _cairo_xcb_surface_map_to_image (void *abstract_surface,
 				 const cairo_rectangle_int_t *extents)
 {
     cairo_xcb_surface_t *surface = abstract_surface;
     cairo_surface_t *image;
+    cairo_status_t status;
 
     if (surface->fallback)
 	return surface->fallback->base.backend->map_to_image (&surface->fallback->base, extents);
@@ -768,8 +769,11 @@ _cairo_xcb_surface_map_to_image (void *abstract_surface,
     image = _get_image (surface, TRUE,
 			extents->x, extents->y,
 			extents->width, extents->height);
-    if (unlikely (image->status))
-	return image;
+    status = cairo_surface_status (image);
+    if (unlikely (status)) {
+	cairo_surface_destroy(image);
+	return _cairo_image_surface_create_in_error (status);
+    }
 
     /* Do we have a deferred clear and this image surface does NOT cover the
      * whole xcb surface? Have to apply the clear in that case, else
@@ -778,16 +782,16 @@ _cairo_xcb_surface_map_to_image (void *abstract_surface,
     if (surface->deferred_clear &&
 	! (extents->width == surface->width &&
 	   extents->height == surface->height)) {
-	cairo_status_t status = _cairo_xcb_surface_clear (surface);
+	status = _cairo_xcb_surface_clear (surface);
 	if (unlikely (status)) {
 	    cairo_surface_destroy(image);
-	    return _cairo_surface_create_in_error (status);
+	    return _cairo_image_surface_create_in_error (status);
 	}
     }
     surface->deferred_clear = FALSE;
 
     cairo_surface_set_device_offset (image, -extents->x, -extents->y);
-    return image;
+    return (cairo_image_surface_t *) image;
 }
 
 static cairo_int_status_t
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index ae2153b..9dadca6 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -1278,7 +1278,7 @@ _cairo_xlib_surface_release_source_image (void                   *abstract_surfa
     cairo_surface_destroy (&image->base);
 }
 
-static cairo_surface_t *
+static cairo_image_surface_t *
 _cairo_xlib_surface_map_to_image (void                    *abstract_surface,
 				  const cairo_rectangle_int_t   *extents)
 {
@@ -1287,7 +1287,7 @@ _cairo_xlib_surface_map_to_image (void                    *abstract_surface,
     image = _get_image_surface (abstract_surface, extents);
     cairo_surface_set_device_offset (image, -extents->x, -extents->y);
 
-    return image;
+    return (cairo_image_surface_t *) image;
 }
 
 static cairo_int_status_t
diff --git a/src/cairo-xlib-xcb-surface.c b/src/cairo-xlib-xcb-surface.c
index caa9bd3..1df5de8 100644
--- a/src/cairo-xlib-xcb-surface.c
+++ b/src/cairo-xlib-xcb-surface.c
@@ -116,7 +116,7 @@ _cairo_xlib_xcb_surface_create_similar_image (void			*abstract_other,
     return cairo_surface_create_similar_image (&surface->xcb->base, format, width, height);
 }
 
-static cairo_surface_t *
+static cairo_image_surface_t *
 _cairo_xlib_xcb_surface_map_to_image (void *abstract_surface,
 				      const cairo_rectangle_int_t *extents)
 {
diff --git a/src/skia/cairo-skia-surface.cpp b/src/skia/cairo-skia-surface.cpp
index 71bebb0..cc76cfb 100644
--- a/src/skia/cairo-skia-surface.cpp
+++ b/src/skia/cairo-skia-surface.cpp
@@ -90,7 +90,7 @@ _cairo_skia_surface_finish (void *asurface)
     return CAIRO_STATUS_SUCCESS;
 }
 
-static cairo_surface_t *
+static cairo_image_surface_t *
 _cairo_skia_surface_map_to_image (void *asurface,
 				  const cairo_rectangle_int_t *extents)
 {
@@ -98,6 +98,7 @@ _cairo_skia_surface_map_to_image (void *asurface,
 
     surface->bitmap->lockPixels ();
 
+    /* XXX: Broken! */
     if (extents->width < surface->image.width ||
 	extents->height < surface->image.height)
     {
diff --git a/src/win32/cairo-win32-display-surface.c b/src/win32/cairo-win32-display-surface.c
index 7efa7d8..0d4c5f9 100644
--- a/src/win32/cairo-win32-display-surface.c
+++ b/src/win32/cairo-win32-display-surface.c
@@ -427,7 +427,7 @@ _cairo_win32_display_surface_finish (void *abstract_surface)
     return CAIRO_STATUS_SUCCESS;
 }
 
-static cairo_surface_t *
+static cairo_image_surface_t *
 _cairo_win32_display_surface_map_to_image (void                    *abstract_surface,
 					   const cairo_rectangle_int_t   *extents)
 {
@@ -464,13 +464,13 @@ _cairo_win32_display_surface_map_to_image (void                    *abstract_sur
     surface = to_win32_display_surface (surface->fallback);
 done:
     GdiFlush();
-    return _cairo_image_surface_map_to_image (surface->image, extents);
+    return _cairo_surface_map_to_image (&surface->image->base, extents);
 
 err:
     cairo_surface_destroy (surface->fallback);
     surface->fallback = NULL;
 
-    return _cairo_surface_create_in_error (status);
+    return _cairo_image_surface_create_in_error (status);
 }
 
 static cairo_int_status_t
@@ -499,7 +499,7 @@ _cairo_win32_display_surface_unmap_image (void                    *abstract_surf
 	    _cairo_damage_add_rectangle (surface->fallback->damage, &r);
     }
 
-    return CAIRO_INT_STATUS_SUCCESS;
+    return _cairo_surface_unmap_image (&surface->image->base, image);
 }
 
 static cairo_status_t
commit 10c0a1c68c34677273d2f48c5d5a6c1c15a320c0
Author: Andrea Canciani <ranma42 at gmail.com>
Date:   Sun Jan 8 15:30:03 2012 +0100

    surface: Define private map/unmap functions
    
    Cairo backends often need to map/unmap to a raster surface but they
    don't care about the pixel format, as Pixman will be doing the format
    handling.
    
    Cairo users cannot know how to access the raw data if the format is
    invalid.
    
    The two different scenarios call for different guarantees on the
    returned surface.
    
    The private map/unmap functions also makes it possible to simply
    return the status upon unmapping.

diff --git a/src/cairo-image-surface-private.h b/src/cairo-image-surface-private.h
index 3388c64..6f5f05b 100644
--- a/src/cairo-image-surface-private.h
+++ b/src/cairo-image-surface-private.h
@@ -216,6 +216,13 @@ _pixman_image_add_tristrip (pixman_image_t *image,
 			    int dst_x, int dst_y,
 			    cairo_tristrip_t *strip);
 
+cairo_private cairo_image_surface_t *
+_cairo_image_surface_clone_subimage (cairo_surface_t             *surface,
+				     const cairo_rectangle_int_t *extents);
+
+cairo_private cairo_bool_t
+_cairo_image_surface_is_clone (cairo_image_surface_t *surface);
+
 CAIRO_END_DECLS
 
 #endif /* CAIRO_IMAGE_SURFACE_PRIVATE_H */
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index 98f70c5..00369b6 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -1202,3 +1202,44 @@ _cairo_image_analyze_color (cairo_image_surface_t      *image)
 
     return image->color = CAIRO_IMAGE_IS_COLOR;
 }
+
+static const cairo_user_data_key_t clone_key;
+
+cairo_image_surface_t *
+_cairo_image_surface_clone_subimage (cairo_surface_t             *surface,
+				     const cairo_rectangle_int_t *extents)
+{
+    cairo_surface_t *image;
+    cairo_surface_pattern_t pattern;
+    cairo_status_t ignored;
+
+    image = cairo_surface_create_similar_image (surface,
+						_cairo_format_from_content (surface->content),
+						extents->width,
+						extents->height);
+    /* TODO: check me with non-identity device_transform. Should we
+     * clone the scaling, too? */
+    cairo_surface_set_device_offset (image,
+				     -extents->x,
+				     -extents->y);
+
+    _cairo_pattern_init_for_surface (&pattern, surface);
+    pattern.base.filter = CAIRO_FILTER_NEAREST;
+
+    ignored = _cairo_surface_paint (image,
+				    CAIRO_OPERATOR_SOURCE,
+				    &pattern.base,
+				    NULL);
+
+    _cairo_pattern_fini (&pattern.base);
+
+    cairo_surface_set_user_data (image, &clone_key, surface, NULL);
+
+    return (cairo_image_surface_t *) image;
+}
+
+cairo_bool_t
+_cairo_image_surface_is_clone (cairo_image_surface_t *image)
+{
+    return cairo_surface_get_user_data (&image->base, &clone_key) != NULL;
+}
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 35ac391..99cbfbe 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -599,6 +599,135 @@ cairo_surface_create_similar_image (cairo_surface_t  *other,
 slim_hidden_def (cairo_surface_create_similar_image);
 
 /**
+ * _cairo_surface_map_to_image:
+ * @surface: an existing surface used to extract the image from
+ * @extents: limit the extraction to an rectangular region
+ *
+ * Returns an image surface that is the most efficient mechanism for
+ * modifying the backing store of the target surface. The region
+ * retrieved is limited to @extents.
+ *
+ * Note, the use of the original surface as a target or source whilst
+ * it is mapped is undefined. The result of mapping the surface
+ * multiple times is undefined. Calling cairo_surface_destroy() or
+ * cairo_surface_finish() on the resulting image surface results in
+ * undefined behavior. Changing the device transform of the image
+ * surface or of @surface before the image surface is unmapped results
+ * in undefined behavior.
+ *
+ * Assumes that @surface is valid (CAIRO_STATUS_SUCCESS,
+ * non-finished).
+ *
+ * Return value: a pointer to the newly allocated image surface. The
+ * caller must use _cairo_surface_unmap_image() to destroy this image
+ * surface.
+ *
+ * This function always returns a valid pointer, but it will return a
+ * pointer to a "nil" surface if @other is already in an error state
+ * or any other error occurs.
+ *
+ * The returned image might have a %CAIRO_FORMAT_INVALID format.
+ **/
+cairo_image_surface_t *
+_cairo_surface_map_to_image (cairo_surface_t  *surface,
+			     const cairo_rectangle_int_t *extents)
+{
+    cairo_image_surface_t *image = NULL;
+
+    assert (extents != NULL);
+
+    /* TODO: require map_to_image != NULL */
+    if (surface->backend->map_to_image)
+	image = (cairo_image_surface_t *) surface->backend->map_to_image (surface, extents);
+
+    if (image == NULL)
+	image = _cairo_image_surface_clone_subimage (surface, extents);
+
+    return image;
+}
+
+/**
+ * _cairo_surface_unmap_image:
+ * @surface: the surface passed to _cairo_surface_map_to_image().
+ * @image: the currently mapped image
+ *
+ * Unmaps the image surface as returned from
+ * _cairo_surface_map_to_image().
+ *
+ * The content of the image will be uploaded to the target surface.
+ * Afterwards, the image is destroyed.
+ *
+ * Using an image surface which wasn't returned by
+ * _cairo_surface_map_to_image() results in undefined behavior.
+ *
+ * An image surface in error status can be passed to
+ * _cairo_surface_unmap_image().
+ *
+ * Return value: the unmap status.
+ *
+ * Even if the unmap status is not successful, @image is destroyed.
+ **/
+cairo_int_status_t
+_cairo_surface_unmap_image (cairo_surface_t       *surface,
+			    cairo_image_surface_t *image)
+{
+    cairo_surface_pattern_t pattern;
+    cairo_rectangle_int_t extents;
+    cairo_clip_t *clip;
+    cairo_int_status_t status;
+
+    /* map_to_image can return error surfaces */
+    if (unlikely (image->base.status)) {
+	status = image->base.status;
+	goto destroy;
+    }
+
+    /* If the image is untouched just skip the update */
+    if (image->base.serial == 0) {
+	status = CAIRO_STATUS_SUCCESS;
+	goto destroy;
+    }
+
+    /* TODO: require unmap_image != NULL */
+    if (surface->backend->unmap_image &&
+	! _cairo_image_surface_is_clone (image))
+    {
+	status = surface->backend->unmap_image (surface, image);
+	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+	    goto destroy;
+    }
+
+    _cairo_pattern_init_for_surface (&pattern, &image->base);
+    pattern.base.filter = CAIRO_FILTER_NEAREST;
+
+    /* We have to apply the translate from map_to_image's extents.x and .y */
+    cairo_matrix_init_translate (&pattern.base.matrix,
+				 image->base.device_transform.x0,
+				 image->base.device_transform.y0);
+
+    /* And we also have to clip the operation to the image's extents */
+    extents.x = image->base.device_transform_inverse.x0;
+    extents.y = image->base.device_transform_inverse.y0;
+    extents.width  = image->width;
+    extents.height = image->height;
+    clip = _cairo_clip_intersect_rectangle (NULL, &extents);
+
+    status = _cairo_surface_paint (surface,
+				   CAIRO_OPERATOR_SOURCE,
+				   &pattern.base,
+				   clip);
+
+    _cairo_pattern_fini (&pattern.base);
+    _cairo_clip_destroy (clip);
+
+destroy:
+    cairo_surface_finish (&image->base);
+    cairo_surface_destroy (&image->base);
+
+    return status;
+}
+
+/**
  * cairo_surface_map_to_image:
  * @surface: an existing surface used to extract the image from
  * @extents: limit the extraction to an rectangular region
@@ -607,17 +736,22 @@ slim_hidden_def (cairo_surface_create_similar_image);
  * modifying the backing store of the target surface. The region retrieved
  * may be limited to the @extents or %NULL for the whole surface
  *
- * Note, the use of the original surface as a target or source whilst it is
- * mapped is undefined. The result of mapping the surface multiple times is
- * undefined. Calling cairo_surface_destroy() or cairo_surface_finish() on the
- * resulting image surface results in undefined behavior.
+ * Note, the use of the original surface as a target or source whilst
+ * it is mapped is undefined. The result of mapping the surface
+ * multiple times is undefined. Calling cairo_surface_destroy() or
+ * cairo_surface_finish() on the resulting image surface results in
+ * undefined behavior. Changing the device transform of the image
+ * surface or of @surface before the image surface is unmapped results
+ * in undefined behavior.
  *
  * Return value: a pointer to the newly allocated image surface. The caller
  * must use cairo_surface_unmap_image() to destroy this image surface.
  *
  * This function always returns a valid pointer, but it will return a
  * pointer to a "nil" surface if @other is already in an error state
- * or any other error occurs.
+ * or any other error occurs. If the returned pointer does not have an
+ * error status, it is guaranteed to be an image surface whose format
+ * is not %CAIRO_FORMAT_INVALID.
  *
  * Since: 1.12
  **/
@@ -626,7 +760,9 @@ cairo_surface_map_to_image (cairo_surface_t  *surface,
 			    const cairo_rectangle_int_t *extents)
 {
     cairo_rectangle_int_t rect;
-    cairo_surface_t *image;
+    cairo_surface_t *imagesurf;
+    cairo_image_surface_t *image;
+    cairo_status_t status;
 
     if (unlikely (surface->status))
 	return _cairo_surface_create_in_error (surface->status);
@@ -649,37 +785,28 @@ cairo_surface_map_to_image (cairo_surface_t  *surface,
 	}
     }
 
-    image = NULL;
-    if (surface->backend->map_to_image)
-	image = surface->backend->map_to_image (surface, extents);
-
-    if (image == NULL) {
-	cairo_surface_pattern_t pattern;
-	cairo_status_t status;
-
-	image = cairo_surface_create_similar_image (surface,
-						    _cairo_format_from_content (surface->content),
-						    extents->width,
-						    extents->height);
-	cairo_surface_set_device_offset (image, -extents->x, -extents->y);
-
-	_cairo_pattern_init_for_surface (&pattern, surface);
-	pattern.base.filter = CAIRO_FILTER_NEAREST;
+    image = _cairo_surface_map_to_image (surface, extents);
+    imagesurf = &image->base;
 
-	status = _cairo_surface_paint (image,
-				       CAIRO_OPERATOR_SOURCE,
-				       &pattern.base,
-				       NULL);
+    status = cairo_surface_status (imagesurf);
+    if (unlikely (status)) {
+	cairo_surface_destroy (imagesurf);
+	return _cairo_surface_create_in_error (status);
+    }
 
-	_cairo_pattern_fini (&pattern.base);
+    if (cairo_image_surface_get_format (imagesurf) == CAIRO_FORMAT_INVALID) {
+	cairo_surface_destroy (imagesurf);
+	image = _cairo_image_surface_clone_subimage (surface, extents);
+	imagesurf = &image->base;
+    }
 
-	if (unlikely (status)) {
-	    cairo_surface_destroy (image);
-	    image = _cairo_surface_create_in_error (status);
-	}
+    status = cairo_surface_status (imagesurf);
+    if (unlikely (status)) {
+	cairo_surface_destroy (imagesurf);
+	return _cairo_surface_create_in_error (status);
     }
 
-    return image;
+    return imagesurf;
 }
 slim_hidden_def (cairo_surface_map_to_image);
 
@@ -702,7 +829,7 @@ void
 cairo_surface_unmap_image (cairo_surface_t *surface,
 			   cairo_surface_t *image)
 {
-    cairo_int_status_t status;
+    cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
 
     if (unlikely (surface->status)) {
 	status = surface->status;
@@ -712,7 +839,6 @@ cairo_surface_unmap_image (cairo_surface_t *surface,
 	status = _cairo_error (CAIRO_STATUS_SURFACE_FINISHED);
 	goto error;
     }
-
     if (unlikely (image->status)) {
 	status = image->status;
 	goto error;
@@ -726,50 +852,17 @@ cairo_surface_unmap_image (cairo_surface_t *surface,
 	goto error;
     }
 
-    /* If the image is untouched just skip the update */
-    if (image->serial == 0) {
-	status = CAIRO_STATUS_SUCCESS;
-	goto error;
-    }
-
-    status = CAIRO_INT_STATUS_UNSUPPORTED;
-    if (surface->backend->unmap_image)
-	status = surface->backend->unmap_image (surface, (cairo_image_surface_t *) image);
-    if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
-	cairo_image_surface_t *img = (cairo_image_surface_t *) image;
-	cairo_surface_pattern_t pattern;
-	cairo_clip_t *clip;
-	cairo_rectangle_int_t extents;
-
-	_cairo_pattern_init_for_surface (&pattern, image);
-	pattern.base.filter = CAIRO_FILTER_NEAREST;
-
-	/* We have to apply the translate from map_to_image's extents.x and .y */
-	cairo_matrix_init_translate (&pattern.base.matrix,
-				     image->device_transform.x0,
-				     image->device_transform.y0);
-
-	/* And we also have to clip the operation to the image's extents */
-	extents.x = image->device_transform_inverse.x0;
-	extents.y = image->device_transform_inverse.y0;
-	extents.width  = img->width;
-	extents.height = img->height;
-	clip = _cairo_clip_intersect_rectangle (NULL, &extents);
-
-	status = _cairo_surface_paint (surface,
-				       CAIRO_OPERATOR_SOURCE,
-				       &pattern.base,
-				       clip);
+    status = _cairo_surface_unmap_image (surface,
+					 (cairo_image_surface_t *) image);
+    if (unlikely (status))
+	_cairo_surface_set_error (surface, status);
 
-	_cairo_pattern_fini (&pattern.base);
-	_cairo_clip_destroy (clip);
-    }
+    return;
 
 error:
+    _cairo_surface_set_error (surface, status);
     cairo_surface_finish (image);
     cairo_surface_destroy (image);
-    if (status)
-	_cairo_surface_set_error (surface, status);
 }
 slim_hidden_def (cairo_surface_unmap_image);
 
diff --git a/src/cairoint.h b/src/cairoint.h
index d8070e5..5b3d653 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1304,6 +1304,14 @@ _cairo_surface_paint (cairo_surface_t	*surface,
 		      const cairo_pattern_t *source,
 		      const cairo_clip_t	    *clip);
 
+cairo_private cairo_image_surface_t *
+_cairo_surface_map_to_image (cairo_surface_t  *surface,
+			     const cairo_rectangle_int_t *extents);
+
+cairo_private cairo_int_status_t
+_cairo_surface_unmap_image (cairo_surface_t       *surface,
+			    cairo_image_surface_t *image);
+
 cairo_private cairo_status_t
 _cairo_surface_mask (cairo_surface_t	*surface,
 		     cairo_operator_t	 op,
commit 3e9895e95100ced3a6fcbedcba75e50ca450b4f0
Author: Andrea Canciani <ranma42 at gmail.com>
Date:   Mon May 7 19:05:05 2012 +0200

    png: Implement conversion of CAIRO_FORMAT_RGB30 to string
    
    Fixes
    
    png.c:55: warning: enumeration value ‘CAIRO_FORMAT_RGB30’ not handled
    in switch

diff --git a/test/png.c b/test/png.c
index e90ac66..3980ddc 100644
--- a/test/png.c
+++ b/test/png.c
@@ -57,6 +57,7 @@ format_to_string (cairo_format_t format)
     case CAIRO_FORMAT_A8:     return "a8";
     case CAIRO_FORMAT_RGB16_565:  return "rgb16";
     case CAIRO_FORMAT_RGB24:  return "rgb24";
+    case CAIRO_FORMAT_RGB30:  return "rgb30";
     case CAIRO_FORMAT_ARGB32: return "argb32";
     case CAIRO_FORMAT_INVALID:
     default: return "???";
commit afcbb7a2c5c8a05d11e054e09c8c4e53b571a435
Author: Andrea Canciani <ranma42 at gmail.com>
Date:   Mon May 14 10:44:31 2012 +0200

    build: Do not replace existing files
    
    The existing INSTALL file is currently being replaced at every
    autogen.sh run with the default one.
    
    This is not desired, because INSTALL contains some cairo-specific
    information.

diff --git a/autogen.sh b/autogen.sh
index acb23c7..4d113f8 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -25,7 +25,7 @@ fi
 > src/Makefile.am.features
 touch ChangeLog
 
-autoreconf --force --install --verbose || exit $?
+autoreconf --install --verbose || exit $?
 
 cd $ORIGDIR
 test -n "$NOCONFIGURE" || "$srcdir/configure" "$@"
commit 38d03ea7488097f2b1194f546bd1331af189b809
Author: Andrea Canciani <ranma42 at gmail.com>
Date:   Mon May 14 10:40:49 2012 +0200

    build: Allow autogen-eration on systems without GTK-doc
    
    The autogen.sh script fails if it cannot run gtkdocize. The absence of
    this command should not cause cairo builds to fail, it should only
    prevent the build of its documentation.
    
    Fixes:
    *** No GTK-Doc found, please install it ***
    
    on systems without gtkdoc tools.
    
    Fixes https://bugs.freedesktop.org/show_bug.cgi?id=50356

diff --git a/autogen.sh b/autogen.sh
index f085022..acb23c7 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -15,8 +15,9 @@ fi
 
 GTKDOCIZE=`which gtkdocize`
 if test -z $GTKDOCIZE; then
-        echo "*** No GTK-Doc found, please install it ***"
-        exit 1
+        echo "*** No GTK-Doc found, documentation won't be generated ***"
+else
+        gtkdocize || exit $?
 fi
 
 # create dummy */Makefile.am.features and ChangeLog to make automake happy
@@ -24,7 +25,6 @@ fi
 > src/Makefile.am.features
 touch ChangeLog
 
-gtkdocize || exit $?
 autoreconf --force --install --verbose || exit $?
 
 cd $ORIGDIR


More information about the cairo-commit mailing list