[cairo-commit] 4 commits - src/cairo.h src/cairo-surface.c src/cairo-xlib-xcb-surface.c test/map-to-image.c

Uli Schlachter psychon at kemper.freedesktop.org
Mon Aug 8 12:07:23 PDT 2011


 src/cairo-surface.c          |   11 +++++++++++
 src/cairo-xlib-xcb-surface.c |    4 ++++
 src/cairo.h                  |    1 +
 test/map-to-image.c          |   42 ++++++++++++++++++++++++++++++++++++------
 4 files changed, 52 insertions(+), 6 deletions(-)

New commits:
commit 7b97533221aa5713168b9ddefb4a647cff98c510
Author: Uli Schlachter <psychon at znc.in>
Date:   Fri Aug 5 21:32:03 2011 +0200

    map-to-image: Handle non-32bpp formats
    
    Fixes: map-all-to-image, map-bit-to-image for image16
    
    Signed-off-by: Uli Schlachter <psychon at znc.in>

diff --git a/test/map-to-image.c b/test/map-to-image.c
index 8528fa0..b7d6df8 100644
--- a/test/map-to-image.c
+++ b/test/map-to-image.c
@@ -30,7 +30,30 @@
 #define HEIGHT	3
 
 /* A single, black pixel */
-static const uint32_t black_pixel = 0xff000000;
+static const uint32_t black_pixel_argb = 0xff000000;
+static const uint32_t black_pixel      = 0x00000000;
+
+static cairo_bool_t
+set_pixel_black(uint8_t *data, int stride,
+	  cairo_format_t format, int x, int y)
+{
+    switch (format) {
+    case CAIRO_FORMAT_ARGB32:
+    case CAIRO_FORMAT_RGB24:
+	*(uint32_t *)(data + y * stride + 4*x) = black_pixel_argb;
+	break;
+    case CAIRO_FORMAT_RGB16_565:
+	*(uint16_t *)(data + y * stride + 2*x) = black_pixel;
+	break;
+    case CAIRO_FORMAT_RGB30:
+    case CAIRO_FORMAT_A8:
+    case CAIRO_FORMAT_A1:
+    case CAIRO_FORMAT_INVALID:
+    default:
+	return FALSE;
+    }
+    return TRUE;
+}
 
 static cairo_test_status_t
 all (cairo_t *cr, int width, int height)
@@ -38,6 +61,7 @@ all (cairo_t *cr, int width, int height)
     cairo_surface_t *surface;
     uint8_t *data;
     int stride;
+    cairo_format_t format;
     int i, j;
 
     /* Fill background white */
@@ -46,12 +70,14 @@ all (cairo_t *cr, int width, int height)
 
     surface = cairo_surface_map_to_image (cairo_get_target (cr), NULL);
     cairo_surface_flush (surface);
+    format = cairo_image_surface_get_format (surface);
     stride = cairo_image_surface_get_stride (surface);
     data = cairo_image_surface_get_data (surface);
     if (data) {
-	    for (j = 0; j < HEIGHT; j++)
-		    for (i = 0; i < WIDTH; i++)
-			    *(uint32_t *)(data + j * stride + 4*i) = black_pixel;
+	for (j = 0; j < HEIGHT; j++)
+	    for (i = 0; i < WIDTH; i++)
+		if (! set_pixel_black (data, stride, format, i, j))
+		    return CAIRO_TEST_FAILURE;
     }
     cairo_surface_mark_dirty (surface);
     cairo_surface_unmap_image (cairo_get_target (cr), surface);
@@ -64,6 +90,7 @@ bit (cairo_t *cr, int width, int height)
 {
     cairo_surface_t *surface;
     cairo_rectangle_t extents;
+    cairo_format_t format;
     uint8_t *data;
 
     extents.x = extents.y = extents.width = extents.height = 1;
@@ -75,8 +102,11 @@ bit (cairo_t *cr, int width, int height)
     surface = cairo_surface_map_to_image (cairo_get_target (cr), &extents);
     cairo_surface_flush (surface);
     data = cairo_image_surface_get_data (surface);
-    if (data)
-	    *(uint32_t *)data = black_pixel;
+    format = cairo_image_surface_get_format (surface);
+    if (data) {
+	if (! set_pixel_black (data, 0, format, 0, 0))
+	    return CAIRO_TEST_FAILURE;
+    }
     cairo_surface_mark_dirty (surface);
     cairo_surface_unmap_image (cairo_get_target (cr), surface);
 
commit 5a26018313f40a832a1ec378c1a137ee4a852742
Author: Uli Schlachter <psychon at znc.in>
Date:   Fri Aug 5 22:03:19 2011 +0200

    map_to_image: Verify the given extents
    
    User shouldn't be able to use extents that are not completely inside of the
    surface's extents.
    
    Signed-off-by: Uli Schlachter <psychon at znc.in>

diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index b699393..71f8aea 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -611,7 +611,18 @@ cairo_surface_map_to_image (cairo_surface_t  *surface,
 	if (unlikely (! surface->backend->get_extents (surface, &rect)))
 	    return _cairo_surface_create_in_error (CAIRO_STATUS_INVALID_SIZE);
     } else {
+	cairo_rectangle_int_t surface_extents;
 	_cairo_rectangle_int_from_double (&rect, extents);
+
+	/* If this surface is bounded, we can't map parts
+	 * that are outside of it. */
+	if (likely (surface->backend->get_extents (surface, &surface_extents))) {
+	    if (unlikely (rect.x < surface_extents.x ||
+			  rect.y < surface_extents.y ||
+			  rect.x + rect.width > surface_extents.x + surface_extents.width ||
+			  rect.y + rect.height > surface_extents.y + surface_extents.height))
+		return _cairo_surface_create_in_error (CAIRO_STATUS_INVALID_SIZE);
+	}
     }
 
     image = NULL;
commit 03cda5c0e51ec6ef78ee56cb4d72b6213d6d89e4
Author: Uli Schlachter <psychon at znc.in>
Date:   Fri Aug 5 21:07:38 2011 +0200

    xlib-xcb: Fix a double free in surface_unmap
    
    cairo_surface_unmap_image() destroys the image that was passed to it. Since
    xlib-xcb calls cairo_surface_unmap_image() again for the underlying xcb surface,
    the surface was destroyed twice.
    
    Work around this problem by incrementing the image's reference count via
    cairo_surface_reference().
    
    No idea why I didn't catch this problem when implementing these functions, I'm
    sure I ran the relevant tests. :-(
    
    lt-cairo-test-suite: cairo-surface.c:853: cairo_surface_destroy: Assertion
    `((*&(&surface->ref_count)->ref_count) > 0)' failed.
    
    Fixes: map-to-image-fill map-bit-to-image map-all-to-image
    
    Signed-off-by: Uli Schlachter <psychon at znc.in>

diff --git a/src/cairo-xlib-xcb-surface.c b/src/cairo-xlib-xcb-surface.c
index aa74223..6da44a1 100644
--- a/src/cairo-xlib-xcb-surface.c
+++ b/src/cairo-xlib-xcb-surface.c
@@ -134,6 +134,10 @@ _cairo_xlib_xcb_surface_unmap (void *abstract_surface,
 {
     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);
 }
commit 73e93078554849673c54d82b229f76bfb918b7d0
Author: Uli Schlachter <psychon at znc.in>
Date:   Thu Aug 4 22:51:37 2011 +0200

    cairo.h: Document CAIRO_DEVICE_TYPE_INVALID
    
    Signed-off-by: Uli Schlachter <psychon at znc.in>

diff --git a/src/cairo.h b/src/cairo.h
index 1eb30d7..9d788cc 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -1999,6 +1999,7 @@ cairo_device_reference (cairo_device_t *device);
  * @CAIRO_DEVICE_TYPE_XCB: The device is of type xcb
  * @CAIRO_DEVICE_TYPE_XLIB: The device is of type xlib
  * @CAIRO_DEVICE_TYPE_XML: The device is of type XML
+ * @CAIRO_DEVICE_TYPE_INVALID: The device is invalid
  *
  * #cairo_device_type_t is used to describe the type of a given
  * device. The devices types are also known as "backends" within cairo.


More information about the cairo-commit mailing list