[cairo-commit] 2 commits - src/cairo-image-surface.c src/cairoint.h src/cairo-xlib-surface.c

Benjamin Otte company at kemper.freedesktop.org
Thu Sep 24 15:16:53 PDT 2009


 src/cairo-image-surface.c |   21 +++++++++----------
 src/cairo-xlib-surface.c  |   50 ++++++++++++++++++++++++++++++++++++++++------
 src/cairoint.h            |    2 -
 3 files changed, 55 insertions(+), 18 deletions(-)

New commits:
commit caa9eed4646e78a62ffb49d9c4f48c0b351c7a7f
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Sep 24 23:42:05 2009 +0200

    [xlib] Handle case in draw_image() where pixman format is not RGB
    
    When an image cannot be expressed as masks, its data cannot be used in
    an XImage. In that case, we use pixman to copy the image to the desired
    format.

diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 2b8d31a..45debd4 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -974,12 +974,11 @@ _draw_image_surface (cairo_xlib_surface_t   *surface,
     XImage ximage;
     cairo_format_masks_t image_masks;
     int native_byte_order = _native_byte_order_lsb () ? LSBFirst : MSBFirst;
+    pixman_image_t *pixman_image = NULL;
     cairo_status_t status;
     cairo_bool_t own_data;
     GC gc;
 
-    _pixman_format_to_masks (image->pixman_format, &image_masks);
-
     ximage.width = image->width;
     ximage.height = image->height;
     ximage.format = ZPixmap;
@@ -993,10 +992,47 @@ _draw_image_surface (cairo_xlib_surface_t   *surface,
     ximage.blue_mask = surface->b_mask;
     ximage.xoffset = 0;
 
-    if ((image_masks.alpha_mask == surface->a_mask || surface->a_mask == 0) &&
-	(image_masks.red_mask   == surface->r_mask || surface->r_mask == 0) &&
-	(image_masks.green_mask == surface->g_mask || surface->g_mask == 0) &&
-	(image_masks.blue_mask  == surface->b_mask || surface->b_mask == 0))
+    if (!_pixman_format_to_masks (image->pixman_format, &image_masks))
+    {
+        pixman_format_code_t intermediate_format;
+        int ret;
+
+        image_masks.alpha_mask = surface->a_mask;
+        image_masks.red_mask   = surface->r_mask;
+        image_masks.green_mask = surface->g_mask;
+        image_masks.blue_mask  = surface->b_mask;
+        ret = _pixman_format_from_masks (&image_masks, &intermediate_format);
+        assert (ret);
+
+        pixman_image = pixman_image_create_bits (intermediate_format,
+                                                 image->width,
+                                                 image->height,
+                                                 NULL,
+                                                 0);
+        if (pixman_image == NULL)
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+        pixman_image_composite (PIXMAN_OP_SRC,
+                                image->pixman_image,
+                                NULL,
+                                pixman_image,
+                                0, 0,
+                                0, 0,
+                                0, 0,
+                                image->width, image->height);
+
+	ximage.bits_per_pixel = image_masks.bpp;
+	ximage.data = (char *) pixman_image_get_data (pixman_image);
+	ximage.bytes_per_line = pixman_image_get_stride (pixman_image);
+	own_data = FALSE;
+
+	ret = XInitImage (&ximage);
+	assert (ret != 0);
+    }
+    else if ((image_masks.alpha_mask == surface->a_mask || surface->a_mask == 0) &&
+             (image_masks.red_mask   == surface->r_mask || surface->r_mask == 0) &&
+             (image_masks.green_mask == surface->g_mask || surface->g_mask == 0) &&
+             (image_masks.blue_mask  == surface->b_mask || surface->b_mask == 0))
     {
 	int ret;
 
@@ -1126,6 +1162,8 @@ _draw_image_surface (cairo_xlib_surface_t   *surface,
   BAIL:
     if (own_data)
 	free (ximage.data);
+    if (pixman_image)
+        pixman_image_unref (pixman_image);
 
     return CAIRO_STATUS_SUCCESS;
 }
commit 9f5fe6711566ee34afe210f271f1c5a061efa745
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Sep 24 22:57:39 2009 +0200

    [image] Return cairo_bool_t from _pixman_format_to_masks
    
    Return FALSE when the pixman format does not support ARGB masks. In
    particular, return FALSE for YUV formats.

diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index 0c5cc76..29ed119 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -231,11 +231,10 @@ _pixman_format_from_masks (cairo_format_masks_t *masks,
      * expected. This avoid any problems from something bizarre like
      * alpha in the least-significant bits, or insane channel order,
      * or whatever. */
-     _pixman_format_to_masks (format, &format_masks);
-
-     if (masks->bpp        != format_masks.bpp        ||
-	 masks->red_mask   != format_masks.red_mask   ||
-	 masks->green_mask != format_masks.green_mask ||
+     if (!_pixman_format_to_masks (format, &format_masks) ||
+         masks->bpp        != format_masks.bpp            ||
+	 masks->red_mask   != format_masks.red_mask       ||
+	 masks->green_mask != format_masks.green_mask     ||
 	 masks->blue_mask  != format_masks.blue_mask)
      {
 	 return FALSE;
@@ -248,7 +247,7 @@ _pixman_format_from_masks (cairo_format_masks_t *masks,
 /* A mask consisting of N bits set to 1. */
 #define MASK(N) ((1UL << (N))-1)
 
-void
+cairo_bool_t
 _pixman_format_to_masks (pixman_format_code_t	 format,
 			 cairo_format_masks_t	*masks)
 {
@@ -268,27 +267,27 @@ _pixman_format_to_masks (pixman_format_code_t	 format,
         masks->red_mask   = MASK (r) << (g + b);
         masks->green_mask = MASK (g) << (b);
         masks->blue_mask  = MASK (b);
-        return;
+        return TRUE;
     case PIXMAN_TYPE_ABGR:
         masks->alpha_mask = MASK (a) << (b + g + r);
         masks->blue_mask  = MASK (b) << (g + r);
         masks->green_mask = MASK (g) << (r);
         masks->red_mask   = MASK (r);
-        return;
+        return TRUE;
 #ifdef PIXMAN_TYPE_BGRA
     case PIXMAN_TYPE_BGRA:
         masks->blue_mask  = MASK (b) << (g + r + a);
         masks->green_mask = MASK (g) << (r + a);
         masks->red_mask   = MASK (r) << (a);
         masks->alpha_mask = MASK (a);
-        return;
+        return TRUE;
 #endif
     case PIXMAN_TYPE_A:
         masks->alpha_mask = MASK (a);
         masks->red_mask   = 0;
         masks->green_mask = 0;
         masks->blue_mask  = 0;
-        return;
+        return TRUE;
     case PIXMAN_TYPE_OTHER:
     case PIXMAN_TYPE_COLOR:
     case PIXMAN_TYPE_GRAY:
@@ -299,7 +298,7 @@ _pixman_format_to_masks (pixman_format_code_t	 format,
         masks->red_mask   = 0;
         masks->green_mask = 0;
         masks->blue_mask  = 0;
-        return;
+        return FALSE;
     }
 }
 
diff --git a/src/cairoint.h b/src/cairoint.h
index 8b82454..ccf790a 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -2230,7 +2230,7 @@ cairo_private cairo_bool_t
 _pixman_format_from_masks (cairo_format_masks_t *masks,
 			   pixman_format_code_t *format_ret);
 
-cairo_private void
+cairo_private cairo_bool_t
 _pixman_format_to_masks (pixman_format_code_t	 pixman_format,
 			 cairo_format_masks_t	*masks);
 


More information about the cairo-commit mailing list