[cairo-commit] 13 commits - src/cairo.c src/cairo.h src/cairo-image-surface.c src/cairoint.h src/cairo-pattern.c src/cairo-scaled-font.c src/cairo-surface.c src/cairo-xlib-surface.c src/cairo-xlib-xrender.h test/a8-mask.c test/get-xrender-format.c test/.gitignore test/Makefile.am test/meta-surface-pattern-pdf-ref.png test/meta-surface-pattern-pdf-rgb24-ref.png

Carl Worth cworth at kemper.freedesktop.org
Mon Jan 28 16:15:37 PST 2008


 src/cairo-image-surface.c                   |   78 +++++++++++++---
 src/cairo-pattern.c                         |   11 ++
 src/cairo-scaled-font.c                     |    3 
 src/cairo-surface.c                         |    3 
 src/cairo-xlib-surface.c                    |   23 ++++
 src/cairo-xlib-xrender.h                    |    3 
 src/cairo.c                                 |    4 
 src/cairo.h                                 |   30 +++++-
 src/cairoint.h                              |    6 -
 test/.gitignore                             |    1 
 test/Makefile.am                            |    9 +
 test/a8-mask.c                              |  135 ++++++++++++++++++++++++----
 test/get-xrender-format.c                   |  115 +++++++++++++++++++++++
 test/meta-surface-pattern-pdf-ref.png       |binary
 test/meta-surface-pattern-pdf-rgb24-ref.png |binary
 15 files changed, 377 insertions(+), 44 deletions(-)

New commits:
commit 8709b943c6f0025c65081b23ea24ce606150cf49
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Jan 28 16:15:28 2008 -0800

    Fix some documentation typos

diff --git a/src/cairo.h b/src/cairo.h
index bddf315..bbc8bc6 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -142,7 +142,7 @@ typedef struct _cairo_matrix {
  *
  * Other than various cairo_pattern_create_<emphasis>type</emphasis>
  * functions, some of the pattern types can be implicitly created
- * using vairous cairo_set_source_<emphasis>type</emphasis> functions;
+ * using various cairo_set_source_<emphasis>type</emphasis> functions;
  * for example cairo_set_source_rgb().
  *
  * The type of a pattern can be queried with cairo_pattern_get_type().
@@ -202,7 +202,7 @@ typedef struct _cairo_user_data_key {
  * @CAIRO_STATUS_INVALID_INDEX: invalid index passed to getter (Since 1.4)
  * @CAIRO_STATUS_CLIP_NOT_REPRESENTABLE: clip region not representable in desired format (Since 1.4)
  * @CAIRO_STATUS_TEMP_FILE_ERROR: error creating or writing to a temporary file (Since 1.6)
- * @CAIRO_STATUS_INVALID_STRIDE: invalide value for stride (Since 1.6)
+ * @CAIRO_STATUS_INVALID_STRIDE: invalid value for stride (Since 1.6)
  *
  * #cairo_status_t is used to indicate errors that can occur when
  * using Cairo. In some cases it is returned directly by functions.
@@ -288,7 +288,7 @@ typedef cairo_status_t (*cairo_write_func_t) (void		  *closure,
  * @length: the amount of data to read
  *
  * #cairo_read_func_t is the type of function which is called when a
- * backend needs to read data from an intput stream.  It is passed the
+ * backend needs to read data from an input stream.  It is passed the
  * closure which was specified by the user at the time the read
  * function was registered, the buffer to read the data into and the
  * length of the data in bytes.  The read function should return
commit e48d7ca802acba300aee99def0eb01727fe2f58a
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Jan 28 16:11:39 2008 -0800

    Add example to documentation of cairo_pattern_set_filter
    
    It's helpful to let the reade know about cairo_get_source here.

diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index ccd7622..62f75aa 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -1050,6 +1050,17 @@ cairo_pattern_get_matrix (cairo_pattern_t *pattern, cairo_matrix_t *matrix)
  *
  * Sets the filter to be used for resizing when using this pattern.
  * See #cairo_filter_t for details on each filter.
+ *
+ * * Note that you might want to control filtering even when you do not
+ * have an explicit #cairo_pattern_t object, (for example when using
+ * cairo_set_source_surface()). In these cases, it is convenient to
+ * use cairo_get_source() to get access to the pattern that cairo
+ * creates implicitly. For example:
+ *
+ * <informatlexample><programlisting>
+ * cairo_set_source_surface (cr, image, x, y);
+ * cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST);
+ * </programlisting></informatlexample>
  **/
 void
 cairo_pattern_set_filter (cairo_pattern_t *pattern, cairo_filter_t filter)
commit cd26fa266b51ffd91aa9f2c60dd353c53729291e
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Jan 28 16:10:10 2008 -0800

    Add documentation for cairo_filter_t

diff --git a/src/cairo.h b/src/cairo.h
index aa7c1ce..bddf315 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -1793,6 +1793,24 @@ cairo_pattern_set_extend (cairo_pattern_t *pattern, cairo_extend_t extend);
 cairo_public cairo_extend_t
 cairo_pattern_get_extend (cairo_pattern_t *pattern);
 
+/**
+ * cairo_filter_t
+ * @CAIRO_FILTER_FAST: A high-performance filter, with quality similar
+ *     to NEAREST
+ * @CAIRO_FILTER_GOOD: A reasonable-performance filter, with quality
+ *     similar to BILINEAR
+ * @CAIRO_FILTER_BEST: The highest-quality available, performance may
+ *     not be suitable for interactive use.
+ * @CAIRO_FILTER_NEAREST: Nearest-neighbor filtering
+ * @CAIRO_FILTER_BILINEAR: Linear interpolation in two dimensions
+ * @CAIRO_FILTER_GAUSSIAN: This filter value is currently
+ *     unimplemented, and should not be used in current code.
+ *
+ * #cairo_filter_t is used to indicate what filtering should be
+ * applied when reading pixel values from patterns. See
+ * cairo_pattern_set_source() for indicating the desired filter to be
+ * used with a particular pattern.
+ */
 typedef enum _cairo_filter {
     CAIRO_FILTER_FAST,
     CAIRO_FILTER_GOOD,
commit 7c00269e00332974c3a2843272f84960a90b9fb7
Author: Carl Worth <cworth at cworth.org>
Date:   Sun Jan 27 12:36:19 2008 -0800

    Add pdf-specific reference images for meta-surface-pattern
    
    This test has been "failing" ever since we had native
    replay of metasurfaces to pdf. But looking at the results,
    they are actually superior to the image-backend reference
    images.

diff --git a/test/meta-surface-pattern-pdf-ref.png b/test/meta-surface-pattern-pdf-ref.png
new file mode 100644
index 0000000..2e561b2
Binary files /dev/null and b/test/meta-surface-pattern-pdf-ref.png differ
diff --git a/test/meta-surface-pattern-pdf-rgb24-ref.png b/test/meta-surface-pattern-pdf-rgb24-ref.png
new file mode 100644
index 0000000..680f0f5
Binary files /dev/null and b/test/meta-surface-pattern-pdf-rgb24-ref.png differ
commit 9cd198d200e4470d3451581b9e672a87d5d91719
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Jan 28 15:37:22 2008 -0800

    Test the no-Render-extension-available case in get-xrender-format

diff --git a/test/get-xrender-format.c b/test/get-xrender-format.c
index 3309f40..0c9ce9a 100644
--- a/test/get-xrender-format.c
+++ b/test/get-xrender-format.c
@@ -29,6 +29,8 @@
 #include "cairo-xlib.h"
 #include "cairo-xlib-xrender.h"
 
+#include "cairo-boilerplate-xlib.h"
+
 int
 main (void)
 {
@@ -94,7 +96,16 @@ main (void)
 	return CAIRO_TEST_FAILURE;
     }
 
-    cairo_surface_destroy (surface);
+    cairo_test_log ("Testing without the X Render extension.\n");
+
+    cairo_boilerplate_xlib_surface_disable_render (surface);
+
+    format = cairo_xlib_surface_get_xrender_format (surface);
+    if (format != NULL) {
+	cairo_test_log ("Error: did not receive a NULL format as expected\n");
+	return CAIRO_TEST_FAILURE;
+    }
+
 
     XCloseDisplay (dpy);
 
commit d7fd3bd536465881446686305622d31fdc6fd48f
Author: Carl Worth <cworth at cworth.org>
Date:   Sun Jan 27 12:14:51 2008 -0800

    Add get-xrender-format test to test cairo_xlib_surface_get_xrender_format

diff --git a/test/.gitignore b/test/.gitignore
index 15e66c2..51b64ac 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -72,6 +72,7 @@ get-and-set
 get-clip
 get-group-target
 get-path-extents
+get-render-format
 glyph-cache-pressure
 gradient-alpha
 gradient-zero-stops
diff --git a/test/Makefile.am b/test/Makefile.am
index fb56d4c..a425e91 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -58,6 +58,7 @@ get-and-set$(EXEEXT)					\
 get-clip$(EXEEXT)					\
 get-group-target$(EXEEXT)				\
 get-path-extents$(EXEEXT)				\
+get-xrender-format$(EXEEXT)				\
 gradient-alpha$(EXEEXT)					\
 gradient-zero-stops$(EXEEXT)				\
 infinite-join$(EXEEXT)					\
@@ -212,6 +213,10 @@ if CAIRO_HAS_XLIB_SURFACE
 TESTS += xlib-surface$(EXEEXT)
 endif
 
+if CAIRO_HAS_XLIB_XRENDER_SURFACE
+TESTS += get-xrender-format$(EXEEXT)
+endif
+
 if CAIRO_HAS_MULTI_PAGE_SURFACES
 TESTS += multi-page$(EXEEXT)
 endif
diff --git a/test/get-xrender-format.c b/test/get-xrender-format.c
new file mode 100644
index 0000000..3309f40
--- /dev/null
+++ b/test/get-xrender-format.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright © 2008 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Author: Carl D. Worth <cworth at cworth.org>
+ */
+
+#include "cairo-test.h"
+
+#include "cairo-xlib.h"
+#include "cairo-xlib-xrender.h"
+
+int
+main (void)
+{
+    Display *dpy;
+    XRenderPictFormat *orig_format, *format;
+    cairo_surface_t *surface;
+    Pixmap pixmap;
+    int screen;
+
+    cairo_test_init ("get-xrender-format");
+
+    dpy = XOpenDisplay (NULL);
+    if (! dpy) {
+	cairo_test_log ("Error: Cannot open display: %s.\n",
+			XDisplayName (NULL));
+	cairo_test_fini ();
+	return CAIRO_TEST_UNTESTED;
+    }
+
+    screen = DefaultScreen (dpy);
+
+    cairo_test_log ("Testing with image surface.\n");
+
+    surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
+
+    format = cairo_xlib_surface_get_xrender_format (surface);
+    if (format != NULL) {
+	cairo_test_log ("Error: expected NULL for image surface\n");
+	return CAIRO_TEST_FAILURE;
+    }
+
+    cairo_surface_destroy (surface);
+
+    cairo_test_log ("Testing with non-xrender xlib surface.\n");
+
+    pixmap = XCreatePixmap (dpy, DefaultRootWindow (dpy),
+			    1, 1, DefaultDepth (dpy, screen));
+    surface = cairo_xlib_surface_create (dpy, pixmap,
+					 DefaultVisual (dpy, screen),
+					 1, 1);
+    orig_format = XRenderFindVisualFormat (dpy, DefaultVisual (dpy, screen));
+    format = cairo_xlib_surface_get_xrender_format (surface);
+    if (format != orig_format) {
+	cairo_test_log ("Error: did not receive the same format as XRenderFindVisualFormat\n");
+	return CAIRO_TEST_FAILURE;
+    }
+    cairo_surface_destroy (surface);
+    XFreePixmap (dpy, pixmap);
+
+    cairo_test_log ("Testing with xlib xrender surface.\n");
+
+    orig_format = XRenderFindStandardFormat (dpy, PictStandardARGB32);
+    pixmap = XCreatePixmap (dpy, DefaultRootWindow (dpy),
+			    1, 1, 32);
+    surface = cairo_xlib_surface_create_with_xrender_format (dpy,
+							     pixmap,
+							     DefaultScreenOfDisplay (dpy),
+							     orig_format,
+							     1, 1);
+    format = cairo_xlib_surface_get_xrender_format (surface);
+    if (format != orig_format) {
+	cairo_test_log ("Error: did not receive the same format originally set\n");
+	return CAIRO_TEST_FAILURE;
+    }
+
+    cairo_surface_destroy (surface);
+
+    XCloseDisplay (dpy);
+
+    cairo_test_fini ();
+
+    return CAIRO_TEST_SUCCESS;
+}
commit cc94dce25085fef936b7cb36cf9fc41569668eba
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Jan 28 15:26:15 2008 -0800

    Return NULL from cairo_xlib_surface_get_xrender_format without an error
    
    The NULL return value will only happen if the X Render extension
    is not available. We've already got that NULL return value
    documented, so it's not an error if the user asks for it. In
    particular, it's definitely not a surface-type mismatch.

diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 96d4d73..c777810 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -2168,7 +2168,7 @@ slim_hidden_def (cairo_xlib_surface_create_with_xrender_format);
  *
  * Return value: the XRenderPictFormat* with which the surface was
  * originally created, (or NULL if the surface is not an xlib surface
- * or if the Render extension is not available).
+ * or if the X Render extension is not available).
  */
 XRenderPictFormat *
 cairo_xlib_surface_get_xrender_format (cairo_surface_t *surface)
@@ -2181,10 +2181,6 @@ cairo_xlib_surface_get_xrender_format (cairo_surface_t *surface)
 	return NULL;
     }
 
-    /* And also for an xlib surface that is not an xlib-xrender surface */
-    if (xlib_surface->xrender_format == NULL)
-	_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
-
     return xlib_surface->xrender_format;
 }
 #endif
commit 3c018a6e5abe099fa916f45ecf0c8e9dd5771fae
Author: Carl Worth <cworth at cworth.org>
Date:   Sun Jan 27 12:13:13 2008 -0800

    Add new API cairo_xlib_surface_get_render_format

diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index be5aa09..96d4d73 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -2160,6 +2160,33 @@ cairo_xlib_surface_create_with_xrender_format (Display		    *dpy,
 						NULL, format, width, height, 0);
 }
 slim_hidden_def (cairo_xlib_surface_create_with_xrender_format);
+
+/**
+ * cairo_xlib_surface_get_xrender_format
+ * @surface: an xlib surface created by
+ * cairo_xlib_surface_create_with_render_format
+ *
+ * Return value: the XRenderPictFormat* with which the surface was
+ * originally created, (or NULL if the surface is not an xlib surface
+ * or if the Render extension is not available).
+ */
+XRenderPictFormat *
+cairo_xlib_surface_get_xrender_format (cairo_surface_t *surface)
+{
+    cairo_xlib_surface_t *xlib_surface = (cairo_xlib_surface_t *) surface;
+
+    /* Throw an error for a non-xlib surface */
+    if (! _cairo_surface_is_xlib (surface)) {
+	_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
+	return NULL;
+    }
+
+    /* And also for an xlib surface that is not an xlib-xrender surface */
+    if (xlib_surface->xrender_format == NULL)
+	_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
+
+    return xlib_surface->xrender_format;
+}
 #endif
 
 /**
diff --git a/src/cairo-xlib-xrender.h b/src/cairo-xlib-xrender.h
index 572049d..6dd584f 100644
--- a/src/cairo-xlib-xrender.h
+++ b/src/cairo-xlib-xrender.h
@@ -54,6 +54,9 @@ cairo_xlib_surface_create_with_xrender_format (Display		 *dpy,
                                                int		  width,
                                                int		  height);
 
+cairo_public XRenderPictFormat *
+cairo_xlib_surface_get_xrender_format (cairo_surface_t *surface);
+
 CAIRO_END_DECLS
 
 #else  /* CAIRO_HAS_XLIB_XRENDER_SURFACE */
commit 88811540722d891b987efa6fa8edcbab7e10feeb
Author: Carl Worth <cworth at cworth.org>
Date:   Sun Jan 27 11:12:14 2008 -0800

    Add missing cairo_private (for _pixman_format_to_masks)

diff --git a/src/cairoint.h b/src/cairoint.h
index 34de5d2..ee2d331 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1811,7 +1811,7 @@ _cairo_image_surface_create_for_pixman_image (pixman_image_t		*pixman_image,
 cairo_private pixman_format_code_t
 _pixman_format_from_masks (cairo_format_masks_t *masks);
 
-void
+cairo_private void
 _pixman_format_to_masks (pixman_format_code_t	 pixman_format,
 			 uint32_t		*bpp,
 			 uint32_t		*red,
commit 3841cc0932ac77540c306c1c70a6171d7d00cf3e
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Jan 28 15:12:38 2008 -0800

    Clarify the documentation of stride within cairo_image_surface_create_for_data

diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index b4e7c45..32c755e 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -440,12 +440,9 @@ cairo_format_stride_for_width (cairo_format_t	format,
  * @width: the width of the image to be stored in the buffer
  * @height: the height of the image to be stored in the buffer
  * @stride: the number of bytes between the start of rows in the
- *    buffer. For performance reasons, not all values are legal stride
- *    values. Use cairo_format_stride_for_width() to compute a legal
- *    stride value for the desired width, (and use that value to
- *    allocate data of the correct size). An illegal stride value will
- *    cause a nil surface to be resutrned with a status of
- *    CAIRO_STATUS_INVALD_STRIDE.
+ *     buffer as allocated. This value should always be computed by
+ *     cairo_format_stride_for_width() before allocating the data
+ *     buffer.
  *
  * Creates an image surface for the provided pixel data. The output
  * buffer must be kept around until the #cairo_surface_t is destroyed
@@ -454,13 +451,23 @@ cairo_format_stride_for_width (cairo_format_t	format,
  * must explicitly clear the buffer, using, for example,
  * cairo_rectangle() and cairo_fill() if you want it cleared.
  *
+ * Note that the stride will often be larger than
+ * width*bytes_per_pixel to provide proper alignment for each
+ * row. This alignment is required to allow high-performance rendering
+ * within cairo. The correct way to obtain a legal stride value is to
+ * call cairo_format_stride_for_width() with the desired format and
+ * maximum image width value, and the use the resulting stride value
+ * to allocate the data and to create the image surface. See
+ * cairo_format_stride_for_width() for example code.
+ *
  * Return value: a pointer to the newly created surface. The caller
  * owns the surface and should call cairo_surface_destroy when done
  * with it.
  *
  * This function always returns a valid pointer, but it will return a
- * pointer to a "nil" surface if an error such as out of memory
- * occurs. You can use cairo_surface_status() to check for this.
+ * pointer to a "nil" surface in the case of an error such as out of
+ * memory or an invalid stride value. You can use
+ * cairo_surface_status() to check for this.
  *
  * See cairo_surface_set_user_data() for a means of attaching a
  * destroy-notification fallback to the surface if necessary.
commit 13a5624277adf7e87f66d674ce8073013b53bece
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Jan 28 14:29:36 2008 -0800

    Rename cairo_image_surface_stride_for_width to cairo_format_stride_for_width
    
    Thanks for Behdad for the suggested name improvement. Also, make
    it more clear that the stride passed to cairo_image_surface_create_for_data
    should come from calling cairo_format_stride_for_width with the
    same width.

diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index d6a3a95..b4e7c45 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -395,8 +395,8 @@ _cairo_image_surface_create_with_content (cairo_content_t	content,
 }
 
 /**
- * cairo_image_surface_stride_for_width:
- * @format: The desired format of an image surface to be created.
+ * cairo_format_stride_for_width:
+ * @format: A cairo_format_t value
  * @width: The desired width of an image surface to be created.
  *
  * Return value: the appropriate stride to use given the desired
@@ -411,17 +411,17 @@ _cairo_image_surface_create_with_content (cairo_content_t	content,
  * unsigned char *data;
  * cairo_surface_t *surface;
  *
- * stride = cairo_image_surface_stride_for_width (format, width);
+ * stride = cairo_format_stride_for_width (format, width);
  * data = malloc (stride * height);
- * surface = cairo_image_surface_create_for_data (date, format,
+ * surface = cairo_image_surface_create_for_data (data, format,
  *						  width, height);
  * </programlisting></informalexample>
  *
  * Since: 1.6
  */
 int
-cairo_image_surface_stride_for_width (cairo_format_t	format,
-				      int		width)
+cairo_format_stride_for_width (cairo_format_t	format,
+			       int		width)
 {
     int bpp = _cairo_format_bits_per_pixel (format);
 
@@ -441,10 +441,11 @@ cairo_image_surface_stride_for_width (cairo_format_t	format,
  * @height: the height of the image to be stored in the buffer
  * @stride: the number of bytes between the start of rows in the
  *    buffer. For performance reasons, not all values are legal stride
- *    values. Use cairo_image_surface_stride_for_width() to compute a
- *    legal stride value, (and use that value to allocate data of the
- *    correct size). An illegal stride value will cause a nil surface
- *    to be resutrned with a status of CAIRO_STATUS_INVALD_STRIDE.
+ *    values. Use cairo_format_stride_for_width() to compute a legal
+ *    stride value for the desired width, (and use that value to
+ *    allocate data of the correct size). An illegal stride value will
+ *    cause a nil surface to be resutrned with a status of
+ *    CAIRO_STATUS_INVALD_STRIDE.
  *
  * Creates an image surface for the provided pixel data. The output
  * buffer must be kept around until the #cairo_surface_t is destroyed
diff --git a/src/cairo.h b/src/cairo.h
index bfd9284..aa7c1ce 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -1627,8 +1627,8 @@ cairo_image_surface_create (cairo_format_t	format,
 			    int			height);
 
 cairo_public int
-cairo_image_surface_stride_for_width (cairo_format_t	format,
-				      int		width);
+cairo_format_stride_for_width (cairo_format_t	format,
+			       int		width);
 
 cairo_public cairo_surface_t *
 cairo_image_surface_create_for_data (unsigned char	       *data,
diff --git a/test/a8-mask.c b/test/a8-mask.c
index bdfb90a..14d4f8f 100644
--- a/test/a8-mask.c
+++ b/test/a8-mask.c
@@ -20,7 +20,8 @@
  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
  * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  *
- * Author: Jeff Muizelaar <jeff at infidigm.net>
+ * Authors: Jeff Muizelaar <jeff at infidigm.net>
+ *	    Carl Worth <cworth at cworth.org>
  */
 
 #include "cairo-test.h"
@@ -106,8 +107,8 @@ draw (cairo_t *cr, int dst_width, int dst_height)
     cairo_status_t expected;
 
     for (test_width = 0; test_width < 40; test_width++) {
-	stride = cairo_image_surface_stride_for_width (CAIRO_FORMAT_A8,
-						       test_width);
+	stride = cairo_format_stride_for_width (CAIRO_FORMAT_A8,
+						test_width);
 
 	/* First create a surface using the width as the stride, (most
 	 * of these should fail). */
@@ -131,8 +132,8 @@ draw (cairo_t *cr, int dst_width, int dst_height)
 
     /* Now test actually drawing through our mask data, allocating and
      * copying with the proper stride. */
-    stride = cairo_image_surface_stride_for_width (CAIRO_FORMAT_A8,
-						   MASK_WIDTH);
+    stride = cairo_format_stride_for_width (CAIRO_FORMAT_A8,
+					    MASK_WIDTH);
 
     mask_aligned = malloc (stride * MASK_HEIGHT);
 
commit dc67de3d8b6154b74a243cd7b63e45f343520256
Author: Carl Worth <cworth at cworth.org>
Date:   Sat Jan 26 23:12:14 2008 -0800

    Add cairo_image_surface_stride_for_width
    
    Document this function as a required call to get the correct
    stride value before calling cairo_image_surface_create_for_data.
    This means that previously-failing calls with non-multiple-of-4
    stride values are now documented as errors. Also, we now have
    the possibility of moving to more stringent alignment constraints,
    (one can imagine doing 64-bit or 128-bit boundaries for example).

diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index 9273f17..d6a3a95 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -395,16 +395,56 @@ _cairo_image_surface_create_with_content (cairo_content_t	content,
 }
 
 /**
+ * cairo_image_surface_stride_for_width:
+ * @format: The desired format of an image surface to be created.
+ * @width: The desired width of an image surface to be created.
+ *
+ * Return value: the appropriate stride to use given the desired
+ * format and width.
+ *
+ * This function provides a stride value that will respect all
+ * alignment requirements of the accelerated image-rendering code
+ * within cairo. Typical usage will be of the form:
+ *
+ * <informalexample><programlisting>
+ * int stride;
+ * unsigned char *data;
+ * cairo_surface_t *surface;
+ *
+ * stride = cairo_image_surface_stride_for_width (format, width);
+ * data = malloc (stride * height);
+ * surface = cairo_image_surface_create_for_data (date, format,
+ *						  width, height);
+ * </programlisting></informalexample>
+ *
+ * Since: 1.6
+ */
+int
+cairo_image_surface_stride_for_width (cairo_format_t	format,
+				      int		width)
+{
+    int bpp = _cairo_format_bits_per_pixel (format);
+
+    /* Convert from bits-per-row to bytes-per-row with rounding to the
+     * next 4-byte boundary. This satisifies the current alignment
+     * requirements of pixman. */
+    return (((bpp * width) + 31) >> 5) << 2;
+}
+
+/**
  * cairo_image_surface_create_for_data:
- * @data: a pointer to a buffer supplied by the application
- *    in which to write contents.
+ * @data: a pointer to a buffer supplied by the application in which
+ *     to write contents. This pointer must be suitably aligned for any
+ *     kind of variable, (for example, a pointer returned by malloc).
  * @format: the format of pixels in the buffer
  * @width: the width of the image to be stored in the buffer
  * @height: the height of the image to be stored in the buffer
- * @stride: the number of bytes between the start of rows
- *   in the buffer. Having this be specified separate from @width
- *   allows for padding at the end of rows, or for writing
- *   to a subportion of a larger image.
+ * @stride: the number of bytes between the start of rows in the
+ *    buffer. For performance reasons, not all values are legal stride
+ *    values. Use cairo_image_surface_stride_for_width() to compute a
+ *    legal stride value, (and use that value to allocate data of the
+ *    correct size). An illegal stride value will cause a nil surface
+ *    to be resutrned with a status of CAIRO_STATUS_INVALD_STRIDE.
  *
  * Creates an image surface for the provided pixel data. The output
  * buffer must be kept around until the #cairo_surface_t is destroyed
@@ -433,12 +473,12 @@ cairo_image_surface_create_for_data (unsigned char     *data,
 {
     pixman_format_code_t pixman_format;
 
-    /* XXX pixman does not support images with arbitrary strides and
-     * attempting to create such surfaces will failure but we will interpret
-     * such failure as CAIRO_STATUS_NO_MEMORY.  */
-    if (! CAIRO_FORMAT_VALID (format) || stride % sizeof (uint32_t) != 0)
+    if (! CAIRO_FORMAT_VALID (format))
 	return _cairo_surface_create_in_error (_cairo_error(CAIRO_STATUS_INVALID_FORMAT));
 
+    if (stride % sizeof (uint32_t) != 0)
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE));
+
     pixman_format = _cairo_format_to_pixman_format_code (format);
 
     return _cairo_image_surface_create_with_pixman_format (data, pixman_format,
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 2883460..9716c06 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -86,6 +86,7 @@ static DEFINE_NIL_SURFACE(CAIRO_STATUS_FILE_NOT_FOUND, _cairo_surface_nil_file_n
 static DEFINE_NIL_SURFACE(CAIRO_STATUS_TEMP_FILE_ERROR, _cairo_surface_nil_temp_file_error);
 static DEFINE_NIL_SURFACE(CAIRO_STATUS_READ_ERROR, _cairo_surface_nil_read_error);
 static DEFINE_NIL_SURFACE(CAIRO_STATUS_WRITE_ERROR, _cairo_surface_nil_write_error);
+static DEFINE_NIL_SURFACE(CAIRO_STATUS_INVALID_STRIDE, _cairo_surface_nil_invalid_stride);
 
 static cairo_status_t
 _cairo_surface_copy_pattern_for_destination (const cairo_pattern_t *pattern,
@@ -2430,6 +2431,8 @@ _cairo_surface_create_in_error (cairo_status_t status)
 	return (cairo_surface_t *) &_cairo_surface_nil_file_not_found;
     case CAIRO_STATUS_TEMP_FILE_ERROR:
 	return (cairo_surface_t *) &_cairo_surface_nil_temp_file_error;
+    case CAIRO_STATUS_INVALID_STRIDE:
+	return (cairo_surface_t *) &_cairo_surface_nil_invalid_stride;
     default:
 	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
 	return (cairo_surface_t *) &_cairo_surface_nil;
diff --git a/src/cairo.c b/src/cairo.c
index 8ad1893..6ab384e 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -67,7 +67,7 @@ static const cairo_t _cairo_nil = {
  * a bit of a pain, but it should be easy to always catch as long as
  * one adds a new test case to test a trigger of the new status value.
  */
-#define CAIRO_STATUS_LAST_STATUS CAIRO_STATUS_TEMP_FILE_ERROR
+#define CAIRO_STATUS_LAST_STATUS CAIRO_STATUS_INVALID_STRIDE
 
 /**
  * _cairo_error:
@@ -3634,6 +3634,8 @@ cairo_status_to_string (cairo_status_t status)
         return "clip region not representable in desired format";
     case CAIRO_STATUS_TEMP_FILE_ERROR:
 	return "error creating or writing to a temporary file";
+    case CAIRO_STATUS_INVALID_STRIDE:
+	return "invalid value for stride";
     }
 
     return "<unknown error status>";
diff --git a/src/cairo.h b/src/cairo.h
index 177d2b1..bfd9284 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -202,6 +202,7 @@ typedef struct _cairo_user_data_key {
  * @CAIRO_STATUS_INVALID_INDEX: invalid index passed to getter (Since 1.4)
  * @CAIRO_STATUS_CLIP_NOT_REPRESENTABLE: clip region not representable in desired format (Since 1.4)
  * @CAIRO_STATUS_TEMP_FILE_ERROR: error creating or writing to a temporary file (Since 1.6)
+ * @CAIRO_STATUS_INVALID_STRIDE: invalide value for stride (Since 1.6)
  *
  * #cairo_status_t is used to indicate errors that can occur when
  * using Cairo. In some cases it is returned directly by functions.
@@ -235,7 +236,8 @@ typedef enum _cairo_status {
     CAIRO_STATUS_INVALID_DSC_COMMENT,
     CAIRO_STATUS_INVALID_INDEX,
     CAIRO_STATUS_CLIP_NOT_REPRESENTABLE,
-    CAIRO_STATUS_TEMP_FILE_ERROR
+    CAIRO_STATUS_TEMP_FILE_ERROR,
+    CAIRO_STATUS_INVALID_STRIDE
     /* after adding a new error: update CAIRO_STATUS_LAST_STATUS in cairo.c */
 } cairo_status_t;
 
@@ -1624,6 +1626,10 @@ cairo_image_surface_create (cairo_format_t	format,
 			    int			width,
 			    int			height);
 
+cairo_public int
+cairo_image_surface_stride_for_width (cairo_format_t	format,
+				      int		width);
+
 cairo_public cairo_surface_t *
 cairo_image_surface_create_for_data (unsigned char	       *data,
 				     cairo_format_t		format,
diff --git a/test/Makefile.am b/test/Makefile.am
index f752fe6..fb56d4c 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -520,11 +520,7 @@ $(REFERENCE_IMAGES)
 # Of course, before any "release" of cairo we should eliminate
 # everything from this list by fixing the bugs. (We don't necessarily
 # have to be that strict for "snapshots" though.)
-#
-# Also, any test listed here should call cairo_test_expect_failure and
-# provide an explanation for the expected failure.
 XFAIL_TESTS =					\
-a8-mask$(EXEEXT)				\
 big-trap$(EXEEXT)				\
 extend-pad$(EXEEXT)				\
 extend-pad-similar$(EXEEXT)			\
diff --git a/test/a8-mask.c b/test/a8-mask.c
index e21b9df..bdfb90a 100644
--- a/test/a8-mask.c
+++ b/test/a8-mask.c
@@ -29,42 +29,142 @@ static cairo_test_draw_function_t draw;
 
 cairo_test_t test = {
     "a8-mask",
-    "test masks of CAIRO_FORMAT_A8"
-    "\nimage backend fails because libpixman only handles (stride % sizeof(pixman_bits) == 0)",
+    "test masks of CAIRO_FORMAT_A8",
     8, 8,
     draw
 };
 
-static unsigned char mask[] = {
-    0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0,
-    0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0,
-    0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0,
-    0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0,
-    0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0,
-    0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0,
-    0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0,
-    0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0
+#define MASK_WIDTH 8
+#define MASK_HEIGHT 8
+
+static unsigned char mask[MASK_WIDTH * MASK_HEIGHT] = {
+    0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0,
+    0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0,
+    0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0,
+    0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0,
+    0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0,
+    0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0,
+    0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0,
+    0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0,
 };
 
 static cairo_test_status_t
-draw (cairo_t *cr, int width, int height)
+check_status (cairo_status_t status, cairo_status_t expected)
+{
+    if (status == expected)
+	return CAIRO_TEST_SUCCESS;
+
+    cairo_test_log ("Error: Expected status value %d (%s), received %d (%s)\n",
+		    expected,
+		    cairo_status_to_string (expected),
+		    status,
+		    cairo_status_to_string (status));
+    return CAIRO_TEST_FAILURE;
+}
+
+static cairo_test_status_t
+test_surface_with_width_and_stride (int width, int stride,
+				    cairo_status_t expected)
+{
+    cairo_test_status_t status;
+    cairo_surface_t *surface;
+    cairo_t *cr;
+    unsigned char *data;
+
+    cairo_test_log ("Creating surface with width %d and stride %d\n",
+		    width, stride);
+
+    data = malloc (stride);
+
+    surface = cairo_image_surface_create_for_data (data, CAIRO_FORMAT_A8,
+						   width, 1, stride);
+    cr = cairo_create (surface);
+
+    cairo_paint (cr);
+
+    status = check_status (cairo_surface_status (surface), expected);
+    if (status)
+	return status;
+
+    status = check_status (cairo_status (cr), expected);
+    if (status)
+	return status;
+
+    free (data);
+
+    return CAIRO_TEST_SUCCESS;
+}
+
+static cairo_test_status_t
+draw (cairo_t *cr, int dst_width, int dst_height)
 {
+    int test_width, stride, row;
+    unsigned char *src, *dst, *mask_aligned;
     cairo_surface_t *surface;
     cairo_pattern_t *pattern;
+    cairo_test_status_t status;
+    cairo_status_t expected;
+
+    for (test_width = 0; test_width < 40; test_width++) {
+	stride = cairo_image_surface_stride_for_width (CAIRO_FORMAT_A8,
+						       test_width);
+
+	/* First create a surface using the width as the stride, (most
+	 * of these should fail). */
+	expected = (stride == test_width) ?
+	    CAIRO_STATUS_SUCCESS : CAIRO_STATUS_INVALID_STRIDE;
 
-    cairo_set_source_rgb (cr, 0, 0, 1);
+	status = test_surface_with_width_and_stride (test_width,
+						     test_width,
+						     expected);
+	if (status)
+	    return status;
+
+	/* Then create a surface using the correct stride, (should
+	   always succeed).*/
+	status = test_surface_with_width_and_stride (test_width,
+						     stride,
+						     CAIRO_STATUS_SUCCESS);
+	if (status)
+	    return status;
+    }
+
+    /* Now test actually drawing through our mask data, allocating and
+     * copying with the proper stride. */
+    stride = cairo_image_surface_stride_for_width (CAIRO_FORMAT_A8,
+						   MASK_WIDTH);
+
+    mask_aligned = malloc (stride * MASK_HEIGHT);
+
+    src = mask;
+    dst = mask_aligned;
+    for (row = 0; row < MASK_HEIGHT; row++) {
+	memcpy (dst, src, MASK_WIDTH);
+	src += MASK_WIDTH;
+	dst += stride;
+    }
+
+    surface = cairo_image_surface_create_for_data (mask,
+						   CAIRO_FORMAT_A8,
+						   MASK_WIDTH,
+						   MASK_HEIGHT,
+						   stride);
+
+    /* Paint background blue */
+    cairo_set_source_rgb (cr, 0, 0, 1); /* blue */
     cairo_paint (cr);
 
-    surface = cairo_image_surface_create_for_data (mask, CAIRO_FORMAT_A8,
-						   7, 8, 7);
+    /* Then paint red through our mask */
     pattern = cairo_pattern_create_for_surface (surface);
 
-    cairo_set_source_rgb (cr, 1, 0, 0);
+    cairo_set_source_rgb (cr, 1, 0, 0); /* red */
     cairo_mask (cr, pattern);
 
     cairo_pattern_destroy (pattern);
     cairo_surface_destroy (surface);
 
+    free (mask_aligned);
+
     return CAIRO_TEST_SUCCESS;
 }
 
commit b151cb0709364bed03e4918b79f26ef3243948ca
Author: Carl Worth <cworth at cworth.org>
Date:   Sat Jan 26 16:42:26 2008 -0800

    Rename cairo_format_width to cairo_format_bits_per_pixel and correct its logic

diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index 5f31d93..9273f17 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -615,14 +615,14 @@ _cairo_content_from_format (cairo_format_t format)
     return CAIRO_CONTENT_COLOR_ALPHA;
 }
 
-cairo_private cairo_format_t
-_cairo_format_width (cairo_format_t format)
+int
+_cairo_format_bits_per_pixel (cairo_format_t format)
 {
     switch (format) {
     case CAIRO_FORMAT_ARGB32:
 	return 32;
     case CAIRO_FORMAT_RGB24:
-	return 24;
+	return 32;
     case CAIRO_FORMAT_A8:
 	return 8;
     case CAIRO_FORMAT_A1:
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index e21cd61..fa597cb 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -1270,7 +1270,8 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t    *scaled_font,
 	/* If we have glyphs of different formats, we "upgrade" the mask
 	 * to the wider of the formats. */
 	if (glyph_surface->format != mask_format &&
-	    _cairo_format_width (mask_format) < _cairo_format_width (glyph_surface->format) )
+	    _cairo_format_bits_per_pixel (mask_format) <
+	    _cairo_format_bits_per_pixel (glyph_surface->format) )
 	{
 	    cairo_surface_t *new_mask;
 	    cairo_surface_pattern_t mask_pattern;
diff --git a/src/cairoint.h b/src/cairoint.h
index b5b69d2..34de5d2 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1795,8 +1795,8 @@ _cairo_surface_has_device_transform (cairo_surface_t *surface);
 						      CAIRO_CONTENT_COLOR_ALPHA))\
 				       == 0))
 
-cairo_private cairo_format_t
-_cairo_format_width (cairo_format_t format);
+cairo_private int
+_cairo_format_bits_per_pixel (cairo_format_t format);
 
 cairo_private cairo_format_t
 _cairo_format_from_content (cairo_content_t content);


More information about the cairo-commit mailing list