[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