[cairo-commit] 25 commits - boilerplate/Makefile.am boilerplate/xmalloc.c doc/public src/cairo.c src/cairo-debug.c src/cairo-font-face.c src/cairo-font-options.c src/cairo-ft-font.c src/cairo-gstate.c src/cairo.h src/cairoint.h src/cairo-matrix.c src/cairo-mutex-list-private.h src/cairo-output-stream-private.h src/cairo-pdf-operators.c src/cairo-pdf-surface.c src/cairo-png.c src/cairo-ps-surface.c src/cairo-scaled-font.c src/cairo-surface.c src/cairo-win32-font.c test/a1-image-sample.c test/a8-mask.c test/bitmap-font.c test/font-options.c test/.gitignore test/glitz-surface-source.c test/glitz-surface-source-ref.png test/image-surface-source.c test/image-surface-source-ref.png test/invalid-matrix.c test/Makefile.am test/pdf-surface-source.c test/pdf-surface-source-ref.png test/ps-surface-source.c test/ps-surface-source-ref.png test/surface-source.c test/svg-surface-source.c test/svg-surface-source-ref.png test/xlib-surface-source.c test/xlib-surface-source-ref.png

Chris Wilson ickle at kemper.freedesktop.org
Fri Feb 15 06:57:24 PST 2008


 boilerplate/Makefile.am           |   14 +-
 boilerplate/xmalloc.c             |   27 +++--
 doc/public/Makefile.am            |    2 
 src/cairo-debug.c                 |    2 
 src/cairo-font-face.c             |    8 -
 src/cairo-font-options.c          |   36 ++----
 src/cairo-ft-font.c               |   23 ++--
 src/cairo-gstate.c                |    2 
 src/cairo-matrix.c                |    2 
 src/cairo-mutex-list-private.h    |    1 
 src/cairo-output-stream-private.h |    6 -
 src/cairo-pdf-operators.c         |    2 
 src/cairo-pdf-surface.c           |   10 -
 src/cairo-png.c                   |   24 ++--
 src/cairo-ps-surface.c            |   37 ++-----
 src/cairo-scaled-font.c           |   76 +++++++++++---
 src/cairo-surface.c               |   18 ++-
 src/cairo-win32-font.c            |    4 
 src/cairo.c                       |   20 +--
 src/cairo.h                       |    2 
 src/cairoint.h                    |   15 ++
 test/.gitignore                   |    6 +
 test/Makefile.am                  |   34 +++++-
 test/a1-image-sample.c            |    2 
 test/a8-mask.c                    |   14 +-
 test/bitmap-font.c                |    2 
 test/font-options.c               |   65 ++++++++----
 test/glitz-surface-source-ref.png |binary
 test/glitz-surface-source.c       |  196 ++++++++++++++++++++++++++++++++++++++
 test/image-surface-source-ref.png |binary
 test/image-surface-source.c       |   35 ++++++
 test/invalid-matrix.c             |  179 ++++++++++++++++++++++++++++++++++
 test/pdf-surface-source-ref.png   |binary
 test/pdf-surface-source.c         |   41 +++++++
 test/ps-surface-source-ref.png    |binary
 test/ps-surface-source.c          |   41 +++++++
 test/surface-source.c             |   93 ++++++++++++++++++
 test/svg-surface-source-ref.png   |binary
 test/svg-surface-source.c         |   41 +++++++
 test/xlib-surface-source-ref.png  |binary
 test/xlib-surface-source.c        |   76 ++++++++++++++
 41 files changed, 986 insertions(+), 170 deletions(-)

New commits:
commit 536e1963b774038d9afc7fbf63303e118b0250a2
Author: Shailendra Jain <shailen.n.jain at gmail.com>
Date:   Fri Feb 15 13:21:29 2008 +0000

    Compile fix for AIX.
    
    Minor correction for a build failure on AIX:
    "mozilla/gfx/cairo/cairo/src/cairo-gstate.c", line 45.43: 1506-294 (S)
    Syntax error in expression on #if directive.
    
    (Fixes https://bugzilla.mozilla.org/show_bug.cgi?id=415867.)

diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index 99f842e..37a8031 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -42,7 +42,7 @@
 #include "cairo-clip-private.h"
 #include "cairo-gstate-private.h"
 
-#if _XOPEN_SOURCE >= 600 || _ISOC99_SOURCE
+#if _XOPEN_SOURCE >= 600 || defined (_ISOC99_SOURCE)
 #define ISFINITE(x) isfinite (x)
 #else
 #define ISFINITE(x) ((x) * (x) >= 0.) /* check for NaNs */
diff --git a/src/cairo-matrix.c b/src/cairo-matrix.c
index b86b1fd..d10d156 100644
--- a/src/cairo-matrix.c
+++ b/src/cairo-matrix.c
@@ -38,7 +38,7 @@
 
 #include "cairoint.h"
 
-#if _XOPEN_SOURCE >= 600 || _ISOC99_SOURCE
+#if _XOPEN_SOURCE >= 600 || defined (_ISOC99_SOURCE)
 #define ISFINITE(x) isfinite (x)
 #else
 #define ISFINITE(x) ((x) * (x) >= 0.) /* check for NaNs */
diff --git a/test/invalid-matrix.c b/test/invalid-matrix.c
index 5d3bcbc..42240bc 100644
--- a/test/invalid-matrix.c
+++ b/test/invalid-matrix.c
@@ -26,7 +26,7 @@
 
 #include "cairo-test.h"
 
-#if _XOPEN_SOURCE >= 600 || _ISOC99_SOURCE
+#if _XOPEN_SOURCE >= 600 || defined (_ISOC99_SOURCE)
 #define HAVE_INFINITY 1
 #endif
 
commit 31a67c5f22eb2cbb94878d47be19b32ff319c5b3
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Feb 15 13:16:58 2008 +0000

    [pdf] Minor make check fix.
    
    Add a missing '%' in the documentation.

diff --git a/src/cairo-pdf-operators.c b/src/cairo-pdf-operators.c
index 365dd69..f870b92 100644
--- a/src/cairo-pdf-operators.c
+++ b/src/cairo-pdf-operators.c
@@ -296,7 +296,7 @@ _cairo_pdf_path_close_path (void *closure)
  * value, while cairo draws something only for round caps).
  *
  * When using this function to emit a path to be filled, rather than
- * stroked, simply pass CAIRO_LINE_CAP_ROUND which will guarantee that
+ * stroked, simply pass %CAIRO_LINE_CAP_ROUND which will guarantee that
  * the stroke workaround will not modify the path being emitted.
  */
 static cairo_status_t
commit 9e9fda047879f0336c2627483c78499af8ef5458
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Feb 12 11:16:37 2008 +0000

    [test/bitmap-font] Destroy the font options after use.
    
    Fix the leak of the font options.

diff --git a/test/bitmap-font.c b/test/bitmap-font.c
index a9e4e8b..7bebb6c 100644
--- a/test/bitmap-font.c
+++ b/test/bitmap-font.c
@@ -204,6 +204,8 @@ draw (cairo_t *cr, int width, int height)
     cairo_text_path (cr, " a lazy dog");
     cairo_fill (cr);
 
+    cairo_font_options_destroy (font_options);
+
     return CAIRO_TEST_SUCCESS;
 }
 
commit 92970ec83687435e75e60110cb7434670515ae57
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Feb 11 17:00:30 2008 +0000

    [test/invalid-matrix] Test detection of infinities.
    
    Feed infinities into the API and check that we correctly return
    INVALID_MATRIX.

diff --git a/test/invalid-matrix.c b/test/invalid-matrix.c
index 08a81fe..5d3bcbc 100644
--- a/test/invalid-matrix.c
+++ b/test/invalid-matrix.c
@@ -26,6 +26,10 @@
 
 #include "cairo-test.h"
 
+#if _XOPEN_SOURCE >= 600 || _ISOC99_SOURCE
+#define HAVE_INFINITY 1
+#endif
+
 static cairo_test_draw_function_t draw;
 
 cairo_test_t test = {
@@ -45,7 +49,7 @@ draw (cairo_t *cr, int width, int height)
     cairo_scaled_font_t *scaled_font;
     cairo_pattern_t *pattern;
     cairo_t *cr2;
-    cairo_matrix_t identity, bogus, invalid = {
+    cairo_matrix_t identity, bogus, inf, invalid = {
 	4.0, 4.0,
 	4.0, 4.0,
 	4.0, 4.0
@@ -71,6 +75,13 @@ if ((status) == CAIRO_STATUS_SUCCESS) {							\
     status = cairo_matrix_invert (&bogus);
     CHECK_STATUS (status, "cairo_matrix_invert(NaN)");
 
+#if HAVE_INFINITY
+    inf.x0 = inf.xy = inf.xx = INFINITY;
+    inf.y0 = inf.yx = inf.yy = inf.xx;
+    status = cairo_matrix_invert (&inf);
+    CHECK_STATUS (status, "cairo_matrix_invert(infinity)");
+#endif
+
     /* test cairo_matrix_invert with invalid matrix */
     status = cairo_matrix_invert (&invalid);
     CHECK_STATUS (status, "cairo_matrix_invert(invalid)");
@@ -96,6 +107,16 @@ if ((status) == CAIRO_STATUS_SUCCESS) {							\
     cairo_destroy (cr2);
     CHECK_STATUS (status, "cairo_transform(NaN)");
 
+#if HAVE_INFINITY
+    /* test cairo_transform with ∞ matrix */
+    cr2 = cairo_create (target);
+    cairo_transform (cr2, &inf);
+
+    status = cairo_status (cr2);
+    cairo_destroy (cr2);
+    CHECK_STATUS (status, "cairo_transform(infinity)");
+#endif
+
 
     /* test cairo_set_matrix with invalid matrix */
     cr2 = cairo_create (target);
@@ -113,6 +134,16 @@ if ((status) == CAIRO_STATUS_SUCCESS) {							\
     cairo_destroy (cr2);
     CHECK_STATUS (status, "cairo_set_matrix(NaN)");
 
+#if HAVE_INFINITY
+    /* test cairo_set_matrix with ∞ matrix */
+    cr2 = cairo_create (target);
+    cairo_set_matrix (cr2, &inf);
+
+    status = cairo_status (cr2);
+    cairo_destroy (cr2);
+    CHECK_STATUS (status, "cairo_set_matrix(infinity)");
+#endif
+
 
     /* test cairo_set_font_matrix with invalid matrix */
     cr2 = cairo_create (target);
@@ -136,6 +167,19 @@ if ((status) == CAIRO_STATUS_SUCCESS) {							\
     cairo_destroy (cr2);
     CHECK_STATUS (status, "cairo_set_font_matrix(NaN)");
 
+#if HAVE_INFINITY
+    /* test cairo_set_font_matrix with ∞ matrix */
+    cr2 = cairo_create (target);
+    cairo_set_font_matrix (cr2, &inf);
+
+    /* draw some text to force the font to be resolved */
+    cairo_show_text (cr2, "hello");
+
+    status = cairo_status (cr2);
+    cairo_destroy (cr2);
+    CHECK_STATUS (status, "cairo_set_font_matrix(infinity)");
+#endif
+
 
     /* test cairo_scaled_font_create with invalid matrix */
     cr2 = cairo_create (target);
@@ -187,6 +231,33 @@ if ((status) == CAIRO_STATUS_SUCCESS) {							\
     cairo_font_options_destroy (font_options);
     cairo_destroy (cr2);
 
+#if HAVE_INFINITY
+    /* test cairo_scaled_font_create with ∞ matrix */
+    cr2 = cairo_create (target);
+    font_face = cairo_get_font_face (cr2);
+    font_options = cairo_font_options_create ();
+    cairo_get_font_options (cr, font_options);
+    scaled_font = cairo_scaled_font_create (font_face,
+					    &inf,
+					    &identity,
+					    font_options);
+    status = cairo_scaled_font_status (scaled_font);
+    CHECK_STATUS (status, "cairo_scaled_font_create(infinity)");
+
+    cairo_scaled_font_destroy (scaled_font);
+
+    scaled_font = cairo_scaled_font_create (font_face,
+					    &identity,
+					    &inf,
+					    font_options);
+    status = cairo_scaled_font_status (scaled_font);
+    CHECK_STATUS (status, "cairo_scaled_font_create(infinity)");
+
+    cairo_scaled_font_destroy (scaled_font);
+    cairo_font_options_destroy (font_options);
+    cairo_destroy (cr2);
+#endif
+
 
     /* test cairo_pattern_set_matrix with invalid matrix */
     pattern = cairo_pattern_create_rgb (1.0, 1.0, 1.0);
@@ -202,6 +273,15 @@ if ((status) == CAIRO_STATUS_SUCCESS) {							\
     CHECK_STATUS (status, "cairo_pattern_set_matrix(NaN)");
     cairo_pattern_destroy (pattern);
 
+#if HAVE_INFINITY
+    /* test cairo_pattern_set_matrix with ∞ matrix */
+    pattern = cairo_pattern_create_rgb (1.0, 1.0, 1.0);
+    cairo_pattern_set_matrix (pattern, &inf);
+    status = cairo_pattern_status (pattern);
+    CHECK_STATUS (status, "cairo_pattern_set_matrix(infinity)");
+    cairo_pattern_destroy (pattern);
+#endif
+
 
     /* test invalid transformations */
     cr2 = cairo_create (target);
@@ -219,6 +299,23 @@ if ((status) == CAIRO_STATUS_SUCCESS) {							\
     CHECK_STATUS (status, "cairo_translate(NaN, 0)");
     cairo_destroy (cr2);
 
+#if HAVE_INFINITY
+    cr2 = cairo_create (target);
+    cairo_translate (cr2, inf.xx, inf.yy);
+    CHECK_STATUS (status, "cairo_translate(∞, ∞)");
+    cairo_destroy (cr2);
+
+    cr2 = cairo_create (target);
+    cairo_translate (cr2, 0, inf.yy);
+    CHECK_STATUS (status, "cairo_translate(0, ∞)");
+    cairo_destroy (cr2);
+
+    cr2 = cairo_create (target);
+    cairo_translate (cr2, inf.xx, 0);
+    CHECK_STATUS (status, "cairo_translate(∞, 0)");
+    cairo_destroy (cr2);
+#endif
+
 
     cr2 = cairo_create (target);
     cairo_scale (cr2, bogus.xx, bogus.yy);
@@ -235,6 +332,23 @@ if ((status) == CAIRO_STATUS_SUCCESS) {							\
     CHECK_STATUS (status, "cairo_scale(NaN, 1)");
     cairo_destroy (cr2);
 
+#if HAVE_INFINITY
+    cr2 = cairo_create (target);
+    cairo_scale (cr2, inf.xx, inf.yy);
+    CHECK_STATUS (status, "cairo_scale(∞, ∞)");
+    cairo_destroy (cr2);
+
+    cr2 = cairo_create (target);
+    cairo_scale (cr2, 1, inf.yy);
+    CHECK_STATUS (status, "cairo_scale(1, ∞)");
+    cairo_destroy (cr2);
+
+    cr2 = cairo_create (target);
+    cairo_scale (cr2, inf.xx, 1);
+    CHECK_STATUS (status, "cairo_scale(∞, 1)");
+    cairo_destroy (cr2);
+#endif
+
     cr2 = cairo_create (target);
     cairo_scale (cr2, bogus.xx, bogus.yy);
     CHECK_STATUS (status, "cairo_scale(0, 0)");
@@ -256,6 +370,13 @@ if ((status) == CAIRO_STATUS_SUCCESS) {							\
     CHECK_STATUS (status, "cairo_rotate(NaN)");
     cairo_destroy (cr2);
 
+#if HAVE_INFINITY
+    cr2 = cairo_create (target);
+    cairo_rotate (cr2, inf.xx);
+    CHECK_STATUS (status, "cairo_rotate(∞)");
+    cairo_destroy (cr2);
+#endif
+
     return CAIRO_TEST_SUCCESS;
 }
 
commit 012f68e043d3594fa6cb5235eafb1ca1bfe2d099
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Feb 11 16:48:24 2008 +0000

    [test/invalid-matrix] Check scale(0,0)
    
    Test that INVALID_MATRIX is returned if the user calls cairo_scale(0,0)
    or a variant thereof.

diff --git a/test/invalid-matrix.c b/test/invalid-matrix.c
index 77534e7..08a81fe 100644
--- a/test/invalid-matrix.c
+++ b/test/invalid-matrix.c
@@ -236,6 +236,22 @@ if ((status) == CAIRO_STATUS_SUCCESS) {							\
     cairo_destroy (cr2);
 
     cr2 = cairo_create (target);
+    cairo_scale (cr2, bogus.xx, bogus.yy);
+    CHECK_STATUS (status, "cairo_scale(0, 0)");
+    cairo_destroy (cr2);
+
+    cr2 = cairo_create (target);
+    cairo_scale (cr2, 1, bogus.yy);
+    CHECK_STATUS (status, "cairo_scale(1, 0)");
+    cairo_destroy (cr2);
+
+    cr2 = cairo_create (target);
+    cairo_scale (cr2, bogus.xx, 1);
+    CHECK_STATUS (status, "cairo_scale(0, 1)");
+    cairo_destroy (cr2);
+
+
+    cr2 = cairo_create (target);
     cairo_rotate (cr2, bogus.xx);
     CHECK_STATUS (status, "cairo_rotate(NaN)");
     cairo_destroy (cr2);
commit eb7488e1e67b872d29d1bd459bb7994ad3789576
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Feb 11 16:45:18 2008 +0000

    [test/invalid-matrix] Promote incorrect status warning to an error.
    
    As the last warning for an incorrect status has been resolved, throw an
    error if we regress and no longer report an INVALID_MATRIX under testing.

diff --git a/test/invalid-matrix.c b/test/invalid-matrix.c
index 0f0ef0c..77534e7 100644
--- a/test/invalid-matrix.c
+++ b/test/invalid-matrix.c
@@ -57,11 +57,12 @@ if ((status) == CAIRO_STATUS_SUCCESS) {							\
 		    (function_name));							\
     return CAIRO_TEST_FAILURE;								\
 } else if ((status) != CAIRO_STATUS_INVALID_MATRIX) {					\
-    cairo_test_log ("Warning: %s with invalid matrix returned unexpected status "	\
+    cairo_test_log ("Error: %s with invalid matrix returned unexpected status "	\
 		    "(%d): %s\n",							\
 		    (function_name),							\
 		    status,								\
 		    cairo_status_to_string (status));					\
+    return CAIRO_TEST_FAILURE;								\
 }
 
     /* create a bogus matrix and check results of attempted inversion */
commit fc732c3aaa53d8abcea46ad28da696ad08d09b63
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Feb 11 16:17:34 2008 +0000

    [cairo-scaled-font] Create error objects on demand.
    
    In order to correctly report the error back to the user during the
    creation of a scaled font, we need to support a nil object per error.
    Instead of statically allocating all possible errors, lazily allocate
    the nil object the first time we need to report a particular error.
    
    This fixes the misreporting of an INVALID_MATRIX or NULL_POINTER that
    are common user errors during the construction of a scaled font.

diff --git a/src/cairo-debug.c b/src/cairo-debug.c
index c4b7edf..da20527 100644
--- a/src/cairo-debug.c
+++ b/src/cairo-debug.c
@@ -69,5 +69,7 @@ cairo_debug_reset_static_data (void)
 
     _cairo_pattern_reset_static_data ();
 
+    _cairo_scaled_font_reset_static_data ();
+
     CAIRO_MUTEX_FINALIZE ();
 }
diff --git a/src/cairo-mutex-list-private.h b/src/cairo-mutex-list-private.h
index 89fe770..1fe5bd5 100644
--- a/src/cairo-mutex-list-private.h
+++ b/src/cairo-mutex-list-private.h
@@ -37,6 +37,7 @@ CAIRO_MUTEX_DECLARE (_cairo_pattern_solid_surface_cache_lock);
 
 CAIRO_MUTEX_DECLARE (_cairo_font_face_mutex);
 CAIRO_MUTEX_DECLARE (_cairo_scaled_font_map_mutex);
+CAIRO_MUTEX_DECLARE (_cairo_scaled_font_error_mutex);
 
 #if CAIRO_HAS_FT_FONT
 CAIRO_MUTEX_DECLARE (_cairo_ft_unscaled_font_map_mutex);
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index 8d79648..3d9e32a 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -178,7 +178,7 @@ _cairo_scaled_glyph_destroy (void *abstract_glyph)
 }
 
 #define ZOMBIE 0
-const cairo_scaled_font_t _cairo_scaled_font_nil = {
+static const cairo_scaled_font_t _cairo_scaled_font_nil = {
     { ZOMBIE },			/* hash_entry */
     CAIRO_STATUS_NO_MEMORY,	/* status */
     CAIRO_REFERENCE_COUNT_INVALID,	/* ref_count */
@@ -621,17 +621,18 @@ cairo_scaled_font_create (cairo_font_face_t          *font_face,
     cairo_scaled_font_t key, *scaled_font = NULL;
 
     if (font_face->status)
-	return (cairo_scaled_font_t *)&_cairo_scaled_font_nil;
+	return _cairo_scaled_font_create_in_error (font_face->status);
 
-    if (cairo_font_options_status ((cairo_font_options_t *) options))
-	return (cairo_scaled_font_t *)&_cairo_scaled_font_nil;
+    status = cairo_font_options_status ((cairo_font_options_t *) options);
+    if (status)
+	return _cairo_scaled_font_create_in_error (status);
 
     /* Note that degenerate ctm or font_matrix *are* allowed.
      * We want to support a font size of 0. */
 
     font_map = _cairo_scaled_font_map_lock ();
     if (font_map == NULL)
-	return (cairo_scaled_font_t *)&_cairo_scaled_font_nil;
+	return _cairo_scaled_font_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 
     _cairo_scaled_font_init_key (&key, font_face,
 				 font_matrix, ctm, options);
@@ -682,7 +683,7 @@ cairo_scaled_font_create (cairo_font_face_t          *font_face,
     if (status) {
 	_cairo_scaled_font_map_unlock ();
 	status = _cairo_font_face_set_error (font_face, status);
-	return (cairo_scaled_font_t *)&_cairo_scaled_font_nil;
+	return _cairo_scaled_font_create_in_error (status);
     }
 
     status = _cairo_hash_table_insert (font_map->hash_table,
@@ -695,13 +696,63 @@ cairo_scaled_font_create (cairo_font_face_t          *font_face,
 	 * hash table. */
 	_cairo_scaled_font_fini (scaled_font);
 	free (scaled_font);
-	return (cairo_scaled_font_t *)&_cairo_scaled_font_nil;
+	return _cairo_scaled_font_create_in_error (status);
     }
 
     return scaled_font;
 }
 slim_hidden_def (cairo_scaled_font_create);
 
+static cairo_scaled_font_t *_cairo_scaled_font_nil_objects[CAIRO_STATUS_LAST_STATUS + 1];
+
+/* XXX This should disappear in favour of a common pool of error objects. */
+cairo_scaled_font_t *
+_cairo_scaled_font_create_in_error (cairo_status_t status)
+{
+    cairo_scaled_font_t *scaled_font;
+
+    assert (status != CAIRO_STATUS_SUCCESS);
+
+    if (status == CAIRO_STATUS_NO_MEMORY)
+	return (cairo_scaled_font_t *) &_cairo_scaled_font_nil;
+
+    CAIRO_MUTEX_LOCK (_cairo_scaled_font_error_mutex);
+    scaled_font = _cairo_scaled_font_nil_objects[status];
+    if (scaled_font == NULL) {
+	scaled_font = malloc (sizeof (cairo_scaled_font_t));
+	if (scaled_font == NULL) {
+	    CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_error_mutex);
+	    _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+	    return (cairo_scaled_font_t *) &_cairo_scaled_font_nil;
+	}
+
+	*scaled_font = _cairo_scaled_font_nil;
+	scaled_font->status = status;
+	_cairo_scaled_font_nil_objects[status] = scaled_font;
+    }
+    CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_error_mutex);
+
+    return scaled_font;
+}
+
+void
+_cairo_scaled_font_reset_static_data (void)
+{
+    int status;
+
+    CAIRO_MUTEX_LOCK (_cairo_scaled_font_error_mutex);
+    for (status = CAIRO_STATUS_SUCCESS;
+	 status <= CAIRO_STATUS_LAST_STATUS;
+	 status++)
+    {
+	if (_cairo_scaled_font_nil_objects[status] != NULL) {
+	    free (_cairo_scaled_font_nil_objects[status]);
+	    _cairo_scaled_font_nil_objects[status] = NULL;
+	}
+    }
+    CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_error_mutex);
+}
+
 /**
  * cairo_scaled_font_reference:
  * @scaled_font: a #cairo_scaled_font_t, (may be %NULL in which case
diff --git a/src/cairo.c b/src/cairo.c
index ebb6603..7f5e1ec 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -63,12 +63,6 @@ static const cairo_t _cairo_nil = {
 
 #include <assert.h>
 
-/* This has to be updated whenever #cairo_status_t is extended.  That's
- * 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_INVALID_STRIDE
-
 /**
  * _cairo_error:
  * @status: a status value indicating an error, (eg. not
@@ -2869,12 +2863,12 @@ cairo_get_scaled_font (cairo_t *cr)
     cairo_scaled_font_t *scaled_font;
 
     if (cr->status)
-	return (cairo_scaled_font_t *)&_cairo_scaled_font_nil;
+	return _cairo_scaled_font_create_in_error (cr->status);
 
     status = _cairo_gstate_get_scaled_font (cr->gstate, &scaled_font);
     if (status) {
 	_cairo_set_error (cr, status);
-	return (cairo_scaled_font_t *)&_cairo_scaled_font_nil;
+	return _cairo_scaled_font_create_in_error (status);
     }
 
     return scaled_font;
diff --git a/src/cairo.h b/src/cairo.h
index 0c244ba..5988f3a 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -238,7 +238,7 @@ typedef enum _cairo_status {
     CAIRO_STATUS_CLIP_NOT_REPRESENTABLE,
     CAIRO_STATUS_TEMP_FILE_ERROR,
     CAIRO_STATUS_INVALID_STRIDE
-    /* after adding a new error: update CAIRO_STATUS_LAST_STATUS in cairo.c */
+    /* after adding a new error: update CAIRO_STATUS_LAST_STATUS in cairoint.h */
 } cairo_status_t;
 
 /**
diff --git a/src/cairoint.h b/src/cairoint.h
index 0ca08f4..8f8685f 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -105,6 +105,14 @@ _cairo_win32_tmpfile (void);
 #undef  ARRAY_LENGTH
 #define ARRAY_LENGTH(__array) ((int) (sizeof (__array) / sizeof (__array[0])))
 
+
+/* This has to be updated whenever #cairo_status_t is extended.  That's
+ * 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_INVALID_STRIDE
+
+
 /* Size in bytes of buffer to use off the stack per functions.
  * Mostly used by text functions.  For larger allocations, they'll
  * malloc(). */
@@ -1227,8 +1235,13 @@ cairo_private cairo_status_t
 _cairo_scaled_font_set_error (cairo_scaled_font_t *scaled_font,
 			      cairo_status_t status);
 
+cairo_private cairo_scaled_font_t *
+_cairo_scaled_font_create_in_error (cairo_status_t status);
+
+cairo_private void
+_cairo_scaled_font_reset_static_data (void);
+
 extern const cairo_private cairo_font_face_t _cairo_font_face_nil;
-extern const cairo_private cairo_scaled_font_t _cairo_scaled_font_nil;
 
 cairo_private void
 _cairo_font_face_init (cairo_font_face_t               *font_face,
diff --git a/test/font-options.c b/test/font-options.c
index 50c1fb8..b0e111e 100644
--- a/test/font-options.c
+++ b/test/font-options.c
@@ -96,7 +96,7 @@ main (void)
     scaled_font = cairo_scaled_font_create (cairo_get_font_face (cr),
 	                                    &identity, &identity,
 					    NULL);
-    assert (cairo_scaled_font_status (scaled_font) == CAIRO_STATUS_NO_MEMORY); /* XXX */
+    assert (cairo_scaled_font_status (scaled_font) == CAIRO_STATUS_NULL_POINTER);
     cairo_scaled_font_get_font_options (scaled_font, NULL);
     cairo_scaled_font_destroy (scaled_font);
 
commit 38fcc015a5106e5007035c22355da863b3bc9def
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Feb 11 16:14:40 2008 +0000

    [cairo-ft-font] Propagate error detected during determination of scale factors.
    
    Ensure that if an invalid matrix is detected when creating the toy font,
    the error is propagated to the caller.

diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 504f4b1..f570fdc 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -1602,6 +1602,11 @@ _cairo_ft_scaled_font_create_toy (cairo_toy_font_face_t	      *toy_face,
     cairo_ft_font_transform_t sf;
     cairo_ft_options_t ft_options;
 
+    cairo_matrix_multiply (&scale, font_matrix, ctm);
+    status = _compute_transform (&sf, &scale);
+    if (status)
+	return status;
+
     pattern = FcPatternCreate ();
     if (!pattern)
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
@@ -1648,9 +1653,6 @@ _cairo_ft_scaled_font_create_toy (cairo_toy_font_face_t	      *toy_face,
 	goto FREE_PATTERN;
     }
 
-    cairo_matrix_multiply (&scale, font_matrix, ctm);
-    _compute_transform (&sf, &scale);
-
     if (! FcPatternAddDouble (pattern, FC_PIXEL_SIZE, sf.y_scale)) {
 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	goto FREE_PATTERN;
commit ad265cc9f26a20f2336747d69b28bc6ca0d91f4b
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Feb 11 14:58:21 2008 +0000

    [cairo-font-options] Disallow use of NULL font-options.
    
    Partial revert of commit 0086db893cba90dc73824d77c661d2965ad48112.
    
    This is a follow to the earlier commit that allowed creation of scaled
    fonts using a NULL font options (by interpreting the NULL as meaning
    use the default options) to reflect the comments made by Behdad
    (http://lists.cairographics.org/archives/cairo/2008-January/012714.html).
    
    The intent is that the public font options getter/setter API has similar
    defensive behaviour to that of the core objects - i.e. do not overwrite
    the nil object and if the object is in error then return the default
    value. For the indirect use of a NULL/nil font options (e.g. creation of
    scaled fonts), then an error should be returned rather than crashing.

diff --git a/src/cairo-font-face.c b/src/cairo-font-face.c
index 397dd56..2077120 100644
--- a/src/cairo-font-face.c
+++ b/src/cairo-font-face.c
@@ -476,11 +476,9 @@ _cairo_toy_font_face_scaled_font_create (void                *abstract_font_face
     if (font_face->base.status)
 	return font_face->base.status;
 
-    if (options != NULL) {
-	status = cairo_font_options_status ((cairo_font_options_t *) options);
-	if (status)
-	    return status;
-    }
+    status = cairo_font_options_status ((cairo_font_options_t *) options);
+    if (status)
+	return status;
 
     return _cairo_font_face_set_error (&font_face->base,
 	                               backend->create_toy (font_face,
diff --git a/src/cairo-font-options.c b/src/cairo-font-options.c
index f9a1059..c49603e 100644
--- a/src/cairo-font-options.c
+++ b/src/cairo-font-options.c
@@ -52,9 +52,6 @@ static const cairo_font_options_t _cairo_font_options_nil = {
 void
 _cairo_font_options_init_default (cairo_font_options_t *options)
 {
-    if (cairo_font_options_status (options))
-	return;
-
     options->antialias = CAIRO_ANTIALIAS_DEFAULT;
     options->subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
     options->hint_style = CAIRO_HINT_STYLE_DEFAULT;
@@ -65,13 +62,10 @@ void
 _cairo_font_options_init_copy (cairo_font_options_t		*options,
 			       const cairo_font_options_t	*other)
 {
-    if (other != NULL) {
-	options->antialias = other->antialias;
-	options->subpixel_order = other->subpixel_order;
-	options->hint_style = other->hint_style;
-	options->hint_metrics = other->hint_metrics;
-    } else
-	_cairo_font_options_init_default (options);
+    options->antialias = other->antialias;
+    options->subpixel_order = other->subpixel_order;
+    options->hint_style = other->hint_style;
+    options->hint_metrics = other->hint_metrics;
 }
 
 /**
@@ -121,11 +115,8 @@ cairo_font_options_copy (const cairo_font_options_t *original)
 {
     cairo_font_options_t *options;
 
-    if (original != NULL &&
-	cairo_font_options_status ((cairo_font_options_t *) original))
-    {
+    if (cairo_font_options_status ((cairo_font_options_t *) original))
 	return (cairo_font_options_t *) &_cairo_font_options_nil;
-    }
 
     options = malloc (sizeof (cairo_font_options_t));
     if (!options) {
@@ -193,7 +184,6 @@ cairo_font_options_merge (cairo_font_options_t       *options,
     if (cairo_font_options_status (options))
 	return;
 
-    /* A NULL other maps to the defaults and would not overwrite options */
     if (cairo_font_options_status ((cairo_font_options_t *) other))
 	return;
 
@@ -215,16 +205,18 @@ slim_hidden_def (cairo_font_options_merge);
  *
  * Compares two font options objects for equality.
  *
- * Return value: %TRUE if all fields of the two font options objects match
+ * Return value: %TRUE if all fields of the two font options objects match.
+ *	Note that this function will return %FALSE is either object is in
+ *	error.
  **/
 cairo_bool_t
 cairo_font_options_equal (const cairo_font_options_t *options,
 			  const cairo_font_options_t *other)
 {
-    if (options == NULL)
-	options = &_cairo_font_options_nil;
-    if (other == NULL)
-	other = &_cairo_font_options_nil;
+    if (cairo_font_options_status ((cairo_font_options_t *) options))
+	return FALSE;
+    if (cairo_font_options_status ((cairo_font_options_t *) other))
+	return FALSE;
 
     if (options == other)
 	return TRUE;
@@ -251,8 +243,8 @@ slim_hidden_def (cairo_font_options_equal);
 unsigned long
 cairo_font_options_hash (const cairo_font_options_t *options)
 {
-    if (options == NULL)
-	options = &_cairo_font_options_nil;
+    if (cairo_font_options_status ((cairo_font_options_t *) options))
+	options = &_cairo_font_options_nil; /* force default values */
 
     return ((options->antialias) |
 	    (options->subpixel_order << 4) |
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 6f3a29f..504f4b1 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -1661,11 +1661,9 @@ _cairo_ft_scaled_font_create_toy (cairo_toy_font_face_t	      *toy_face,
 	goto FREE_PATTERN;
     }
 
-    if (font_options != NULL) {
-	status = _cairo_ft_font_options_substitute (font_options, pattern);
-	if (status)
-	    goto FREE_PATTERN;
-    }
+    status = _cairo_ft_font_options_substitute (font_options, pattern);
+    if (status)
+	goto FREE_PATTERN;
 
     FcDefaultSubstitute (pattern);
 
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index 1e532bc..8d79648 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -466,11 +466,9 @@ _cairo_scaled_font_init (cairo_scaled_font_t               *scaled_font,
 {
     cairo_status_t status;
 
-    if (options != NULL) {
-	status = cairo_font_options_status ((cairo_font_options_t *) options);
-	if (status)
-	    return status;
-    }
+    status = cairo_font_options_status ((cairo_font_options_t *) options);
+    if (status)
+	return status;
 
     _cairo_scaled_font_init_key (scaled_font, font_face,
 				 font_matrix, ctm, options);
@@ -625,11 +623,8 @@ cairo_scaled_font_create (cairo_font_face_t          *font_face,
     if (font_face->status)
 	return (cairo_scaled_font_t *)&_cairo_scaled_font_nil;
 
-    if (options != NULL &&
-	cairo_font_options_status ((cairo_font_options_t *) options))
-    {
+    if (cairo_font_options_status ((cairo_font_options_t *) options))
 	return (cairo_scaled_font_t *)&_cairo_scaled_font_nil;
-    }
 
     /* Note that degenerate ctm or font_matrix *are* allowed.
      * We want to support a font size of 0. */
diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c
index 34c2736..b560b48 100644
--- a/src/cairo-win32-font.c
+++ b/src/cairo-win32-font.c
@@ -277,7 +277,7 @@ _win32_scaled_font_create (LOGFONTW                   *logfont,
      * XXX: The other option we could pay attention to, but don't
      *      here is the hint_metrics options.
      */
-    if (options == NULL || options->antialias == CAIRO_ANTIALIAS_DEFAULT)
+    if (options->antialias == CAIRO_ANTIALIAS_DEFAULT)
 	f->quality = _get_system_quality ();
     else {
 	switch (options->antialias) {
@@ -304,7 +304,7 @@ _win32_scaled_font_create (LOGFONTW                   *logfont,
 
     if (f->quality == logfont->lfQuality ||
         (logfont->lfQuality == DEFAULT_QUALITY &&
-         (options == NULL || options->antialias == CAIRO_ANTIALIAS_DEFAULT))) {
+         options->antialias == CAIRO_ANTIALIAS_DEFAULT)) {
         /* If face_hfont is non-NULL, then we can use it to avoid creating our
          * own --- because the constraints on face_hfont mentioned above
          * guarantee it was created in exactly the same way that
diff --git a/src/cairo.c b/src/cairo.c
index fd65a34..ebb6603 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -2764,12 +2764,10 @@ cairo_set_font_options (cairo_t                    *cr,
     if (cr->status)
 	return;
 
-    if (options != NULL) {
-	status = cairo_font_options_status ((cairo_font_options_t *) options);
-	if (status) {
-	    _cairo_set_error (cr, status);
-	    return;
-	}
+    status = cairo_font_options_status ((cairo_font_options_t *) options);
+    if (status) {
+	_cairo_set_error (cr, status);
+	return;
     }
 
     _cairo_gstate_set_font_options (cr->gstate, options);
diff --git a/test/font-options.c b/test/font-options.c
index aab4045..50c1fb8 100644
--- a/test/font-options.c
+++ b/test/font-options.c
@@ -38,48 +38,53 @@
 int
 main (void)
 {
-    cairo_font_options_t *options1;
-    cairo_font_options_t *options2;
+    cairo_font_options_t *default_options;
+    cairo_font_options_t *nil_options;
     cairo_surface_t *surface;
     cairo_matrix_t identity;
     cairo_t *cr;
     cairo_scaled_font_t *scaled_font;
 
     /* first check NULL handling of cairo_font_options_t */
-    options1 = cairo_font_options_create ();
-    options2 = cairo_font_options_copy (NULL);
-
-    assert (cairo_font_options_equal (options1, options2));
-    assert (cairo_font_options_equal (NULL, options2));
-    assert (cairo_font_options_equal (options1, NULL));
-
-    assert (cairo_font_options_hash (options1) == cairo_font_options_hash (options2));
-    assert (cairo_font_options_hash (NULL) == cairo_font_options_hash (options2));
-    assert (cairo_font_options_hash (options1) == cairo_font_options_hash (NULL));
+    default_options = cairo_font_options_create ();
+    assert (cairo_font_options_status (default_options) == CAIRO_STATUS_SUCCESS);
+    nil_options = cairo_font_options_copy (NULL);
+    assert (cairo_font_options_status (nil_options) == CAIRO_STATUS_NO_MEMORY);
+
+    assert (cairo_font_options_equal (default_options, default_options));
+    assert (! cairo_font_options_equal (default_options, nil_options));
+    assert (! cairo_font_options_equal (NULL, nil_options));
+    assert (! cairo_font_options_equal (nil_options, nil_options));
+    assert (! cairo_font_options_equal (default_options, NULL));
+    assert (! cairo_font_options_equal (NULL, default_options));
+
+    assert (cairo_font_options_hash (default_options) == cairo_font_options_hash (nil_options));
+    assert (cairo_font_options_hash (NULL) == cairo_font_options_hash (nil_options));
+    assert (cairo_font_options_hash (default_options) == cairo_font_options_hash (NULL));
 
     cairo_font_options_merge (NULL, NULL);
-    cairo_font_options_merge (options1, NULL);
-    cairo_font_options_merge (options1, options2);
+    cairo_font_options_merge (default_options, NULL);
+    cairo_font_options_merge (default_options, nil_options);
 
     cairo_font_options_set_antialias (NULL, CAIRO_ANTIALIAS_DEFAULT);
     cairo_font_options_get_antialias (NULL);
-    assert (cairo_font_options_get_antialias (options1) == CAIRO_ANTIALIAS_DEFAULT);
+    assert (cairo_font_options_get_antialias (default_options) == CAIRO_ANTIALIAS_DEFAULT);
 
     cairo_font_options_set_subpixel_order (NULL, CAIRO_SUBPIXEL_ORDER_DEFAULT);
     cairo_font_options_get_subpixel_order (NULL);
-    assert (cairo_font_options_get_subpixel_order (options1) ==  CAIRO_SUBPIXEL_ORDER_DEFAULT);
+    assert (cairo_font_options_get_subpixel_order (default_options) ==  CAIRO_SUBPIXEL_ORDER_DEFAULT);
 
     cairo_font_options_set_hint_style (NULL, CAIRO_HINT_STYLE_DEFAULT);
     cairo_font_options_get_hint_style (NULL);
-    assert (cairo_font_options_get_hint_style (options1) == CAIRO_HINT_STYLE_DEFAULT);
+    assert (cairo_font_options_get_hint_style (default_options) == CAIRO_HINT_STYLE_DEFAULT);
 
     cairo_font_options_set_hint_metrics (NULL, CAIRO_HINT_METRICS_DEFAULT);
     cairo_font_options_get_hint_metrics (NULL);
-    assert (cairo_font_options_get_hint_metrics (options1) == CAIRO_HINT_METRICS_DEFAULT);
+    assert (cairo_font_options_get_hint_metrics (default_options) == CAIRO_HINT_METRICS_DEFAULT);
 
     cairo_font_options_destroy (NULL);
-    cairo_font_options_destroy (options1);
-    cairo_font_options_destroy (options2);
+    cairo_font_options_destroy (default_options);
+    cairo_font_options_destroy (nil_options);
 
 
     /* Now try creating fonts with NULLs */
@@ -91,12 +96,14 @@ main (void)
     scaled_font = cairo_scaled_font_create (cairo_get_font_face (cr),
 	                                    &identity, &identity,
 					    NULL);
-    assert (cairo_scaled_font_status (scaled_font) == CAIRO_STATUS_SUCCESS);
+    assert (cairo_scaled_font_status (scaled_font) == CAIRO_STATUS_NO_MEMORY); /* XXX */
     cairo_scaled_font_get_font_options (scaled_font, NULL);
     cairo_scaled_font_destroy (scaled_font);
 
-    cairo_set_font_options (cr, NULL);
+    assert (cairo_status (cr) == CAIRO_STATUS_SUCCESS);
     cairo_get_font_options (cr, NULL);
+    cairo_set_font_options (cr, NULL);
+    assert (cairo_status (cr) == CAIRO_STATUS_NULL_POINTER);
 
     cairo_destroy (cr);
 
commit 790eaef71cbd30e1994c9499ab553f2ef5e5d620
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Feb 11 10:31:33 2008 +0000

    [boilerplage] Add getopts to the boilerplate library.
    
    Remember to compile the _cairo_getopts() function into the boilerplate
    convenience library for cairo-perf.

diff --git a/boilerplate/Makefile.am b/boilerplate/Makefile.am
index 2caebe6..fdf46fa 100644
--- a/boilerplate/Makefile.am
+++ b/boilerplate/Makefile.am
@@ -2,12 +2,14 @@ EXTRA_DIST = Makefile.win32
 
 EXTRA_LTLIBRARIES = libcairoboilerplate.la
 
-libcairoboilerplate_la_SOURCES =\
-cairo-boilerplate.c	\
-cairo-boilerplate.h	\
-cairo-boilerplate-scaled-font.h	\
-xmalloc.c		\
-xmalloc.h
+libcairoboilerplate_la_SOURCES =	\
+	cairo-boilerplate.c		\
+	cairo-boilerplate.h		\
+	cairo-boilerplate-getopt.c	\
+	cairo-boilerplate-getopt.h	\
+	cairo-boilerplate-scaled-font.h	\
+	xmalloc.c			\
+	xmalloc.h
 libcairoboilerplate_la_LIBADD = $(top_builddir)/src/libcairo.la $(CAIRO_LDADD)
 
 if CAIRO_HAS_BEOS_SURFACE
commit fe93038ef343c769b38b9e7f15c1be415e6bcdd9
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Feb 8 08:36:34 2008 +0000

    [test/font-options] Check for HAVE_FCFINI
    
    Only pull in the fontconfig headers if we actually use FcFini().

diff --git a/test/font-options.c b/test/font-options.c
index 5277b22..aab4045 100644
--- a/test/font-options.c
+++ b/test/font-options.c
@@ -31,7 +31,9 @@
 #include <assert.h>
 #include <stdlib.h>
 
+#if HAVE_FCFINI
 #include <fontconfig/fontconfig.h>
+#endif
 
 int
 main (void)
commit 2eb03b8cf2b2c0520d018127b377071a8a63799d
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Feb 7 17:07:43 2008 +0000

    [cairo-ps-surface] Tidy return from _analyze_image_transparency().
    
    _analyze_image_transparency() only returned SUCCESS, so use the return
    parameter to pass back the transparency type instead of using an out
    parameter.

diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 869bafc..45f8686 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -1346,43 +1346,38 @@ color_is_gray (double red, double green, double blue)
 	    fabs (red - blue) < epsilon);
 }
 
-static cairo_status_t
-_analyze_image_transparency (cairo_image_surface_t      *image,
-			     cairo_image_transparency_t *transparency)
+static cairo_image_transparency_t
+_analyze_image_transparency (cairo_image_surface_t      *image)
 {
     int x, y;
+    cairo_image_transparency_t transparency;
 
-    if (image->format == CAIRO_FORMAT_RGB24) {
-	*transparency = CAIRO_IMAGE_IS_OPAQUE;
-	return CAIRO_STATUS_SUCCESS;
-    }
+    if (image->format == CAIRO_FORMAT_RGB24)
+	return CAIRO_IMAGE_IS_OPAQUE;
 
     if (image->format != CAIRO_FORMAT_ARGB32) {
 	/* If the PS surface does not support the image format, assume
 	 * that it does have alpha. The image will be converted to
 	 * rgb24 when the PS surface blends the image into the page
 	 * color to remove the transparency. */
-	*transparency = CAIRO_IMAGE_HAS_ALPHA;
-	return CAIRO_STATUS_SUCCESS;
+	return CAIRO_IMAGE_HAS_ALPHA;
     }
 
-    *transparency = CAIRO_IMAGE_IS_OPAQUE;
+    transparency = CAIRO_IMAGE_IS_OPAQUE;
     for (y = 0; y < image->height; y++) {
-	int a;
 	uint32_t *pixel = (uint32_t *) (image->data + y * image->stride);
 
 	for (x = 0; x < image->width; x++, pixel++) {
-	    a = (*pixel & 0xff000000) >> 24;
+	    int a = (*pixel & 0xff000000) >> 24;
 	    if (a > 0 && a < 255) {
-		*transparency = CAIRO_IMAGE_HAS_ALPHA;
-		return CAIRO_STATUS_SUCCESS;
+		return CAIRO_IMAGE_HAS_ALPHA;
 	    } else if (a == 0) {
-		*transparency = CAIRO_IMAGE_HAS_BILEVEL_ALPHA;
+		transparency = CAIRO_IMAGE_HAS_BILEVEL_ALPHA;
 	    }
 	}
     }
 
-    return CAIRO_STATUS_SUCCESS;
+    return transparency;
 }
 
 static cairo_int_status_t
@@ -1403,10 +1398,7 @@ _cairo_ps_surface_analyze_surface_pattern_transparency (cairo_ps_surface_t
     if (image->base.status)
 	return image->base.status;
 
-    status = _analyze_image_transparency (image, &transparency);
-    if (status)
-	goto RELEASE_SOURCE;
-
+    transparency = _analyze_image_transparency (image);
     switch (transparency) {
     case CAIRO_IMAGE_IS_OPAQUE:
 	status = CAIRO_STATUS_SUCCESS;
@@ -1426,7 +1418,6 @@ _cairo_ps_surface_analyze_surface_pattern_transparency (cairo_ps_surface_t
 	break;
     }
 
-RELEASE_SOURCE:
     _cairo_surface_release_source_image (pattern->surface, image, image_extra);
 
     return status;
@@ -1853,9 +1844,7 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t    *surface,
     if (image->base.status)
 	return image->base.status;
 
-    status = _analyze_image_transparency (image, &transparency);
-    if (status)
-	return status;
+    transparency = _analyze_image_transparency (image);
 
     /* PostScript can not represent the alpha channel, so we blend the
        current image over a white (or black for CONTENT_COLOR
commit bc83e028b8d12223164263a9f9cfc822ed40f8c8
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Feb 7 11:47:11 2008 +0000

    [cairo-output-stream] Add format(printf) markup.
    
    Add CAIRO_PRINTF_FORMAT attribute to the printf-esque output stream
    functions, and fixup the one warning caught by the compiler.

diff --git a/src/cairo-output-stream-private.h b/src/cairo-output-stream-private.h
index 2ee43de..9e9e3ad 100644
--- a/src/cairo-output-stream-private.h
+++ b/src/cairo-output-stream-private.h
@@ -115,11 +115,13 @@ _cairo_dtostr (char *buffer, size_t size, double d);
 
 cairo_private void
 _cairo_output_stream_vprintf (cairo_output_stream_t *stream,
-			      const char *fmt, va_list ap);
+			      const char *fmt,
+			      va_list ap) CAIRO_PRINTF_FORMAT ( 2, 0);
 
 cairo_private void
 _cairo_output_stream_printf (cairo_output_stream_t *stream,
-			     const char *fmt, ...);
+			     const char *fmt,
+			     ...) CAIRO_PRINTF_FORMAT (2, 3);
 
 cairo_private long
 _cairo_output_stream_get_position (cairo_output_stream_t *stream);
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index e7068b0..4604e04 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -2805,11 +2805,11 @@ _cairo_pdf_surface_emit_to_unicode_stream (cairo_pdf_surface_t		*surface,
         }
         if (is_composite) {
             _cairo_output_stream_printf (surface->output,
-                                         "<%04x> <%04x>\r\n",
+                                         "<%04x> <%04lx>\r\n",
                                          i + 1, font_subset->to_unicode[i + 1]);
         } else {
             _cairo_output_stream_printf (surface->output,
-                                         "<%02x> <%04x>\r\n",
+                                         "<%02x> <%04lx>\r\n",
                                          i + 1, font_subset->to_unicode[i + 1]);
         }
     }
commit 4430157841d4b55061c6af58576cfe6ec66fcfe5
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Feb 6 11:37:13 2008 +0000

    [test] Summarise the tests failures per backend.
    
    After the summary, show the total number of failures per backend.

diff --git a/test/Makefile.am b/test/Makefile.am
index e082307..5aac23e 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -571,11 +571,26 @@ check-local:
 	done; \
 	if test -n "$$FAILED_TESTS"; then \
 	    echo "Failed tests:"; \
+	    surfaces=""; \
 	    for t in $$FAILED_TESTS; do \
 		echo -n "     $$t: "; \
 		grep -e '\<FAIL\>' $$t.log | sed -e 's/.*TARGET: \([^ ]*\).*/\1/' | sort | uniq | tr '\n' ' '; \
 		echo; \
+		for s in `grep -e '\<FAIL\>' $$t.log | sed -e 's/.*TARGET: \([^ ]*\).*/\1/' | sort | uniq`; do \
+		    eval ss=`echo $$s | tr '-' '_'`; \
+		    eval $$ss=$$[$$ss + 1]; \
+		    echo $$surfaces | grep $$ss >/dev/null || surfaces="$$surfaces $$ss"; \
+		done; \
 	    done; \
+	    echo -n "Failures per surface - "; \
+	    first=""; \
+	    for s in $$surfaces; do \
+	        eval ss=`echo $$s | tr '_' '-'`; \
+		test -n "$$first" && echo -n ", "; \
+	        echo -n "$$ss: $$[$$s + 0]"; \
+		first="false"; \
+	    done; \
+	    echo "."; \
 	fi
 
 check_PROGRAMS =
commit af88d4d9ae66152ac885531bfc73a47eb78d1d03
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Jan 30 15:20:50 2008 +0000

    [test/a8-mask] Fix memleak.
    
    Destroy the auxiallary surfaces and contexts.

diff --git a/test/a8-mask.c b/test/a8-mask.c
index 14d4f8f..fec2fea 100644
--- a/test/a8-mask.c
+++ b/test/a8-mask.c
@@ -75,7 +75,7 @@ test_surface_with_width_and_stride (int width, int stride,
     cairo_test_log ("Creating surface with width %d and stride %d\n",
 		    width, stride);
 
-    data = malloc (stride);
+    data = xmalloc (stride);
 
     surface = cairo_image_surface_create_for_data (data, CAIRO_FORMAT_A8,
 						   width, 1, stride);
@@ -85,15 +85,17 @@ test_surface_with_width_and_stride (int width, int stride,
 
     status = check_status (cairo_surface_status (surface), expected);
     if (status)
-	return status;
+	goto BAIL;
 
     status = check_status (cairo_status (cr), expected);
     if (status)
-	return status;
+	goto BAIL;
 
+  BAIL:
+    cairo_destroy (cr);
+    cairo_surface_destroy (surface);
     free (data);
-
-    return CAIRO_TEST_SUCCESS;
+    return status;
 }
 
 static cairo_test_status_t
@@ -135,7 +137,7 @@ draw (cairo_t *cr, int dst_width, int dst_height)
     stride = cairo_format_stride_for_width (CAIRO_FORMAT_A8,
 					    MASK_WIDTH);
 
-    mask_aligned = malloc (stride * MASK_HEIGHT);
+    mask_aligned = xmalloc (stride * MASK_HEIGHT);
 
     src = mask;
     dst = mask_aligned;
commit a3f071aee707e66e637587f1e9ae327b21243a60
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Jan 30 15:19:49 2008 +0000

    [cairo-ft-font] Tidy usage of cairo_error().
    
    Remove a redundant use of cairo_error(NO_MEMORY).

diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index a502813..6f3a29f 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -932,7 +932,7 @@ _get_bitmap_surface (FT_Bitmap		     *bitmap,
 					     width, height, stride);
     if ((*surface)->base.status) {
 	free (data);
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	return (*surface)->base.status;
     }
 
     if (subpixel)
@@ -1051,9 +1051,8 @@ _render_glyph_outline (FT_Face                    face,
 	bitmap.width = width * hmul;
 	bitmap.rows = height * vmul;
 	bitmap.buffer = calloc (stride, bitmap.rows);
-	if (bitmap.buffer == NULL) {
+	if (bitmap.buffer == NULL)
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	}
 
 	FT_Outline_Translate (outline, -cbox.xMin*hmul, -cbox.yMin*vmul);
 
@@ -2310,7 +2309,7 @@ _cairo_ft_font_face_create (cairo_ft_unscaled_font_t *unscaled,
 	    font_face->ft_options.extra_flags == ft_options->extra_flags &&
 	    cairo_font_options_equal (&font_face->ft_options.base, &ft_options->base))
 	{
-	    if (! font_face->base.status)
+	    if (font_face->base.status == CAIRO_STATUS_SUCCESS)
 		return cairo_font_face_reference (&font_face->base);
 
 	    /* The font_face has been left in an error state, abandon it. */
commit a4c960a93cf5f37819b933d19f92e17e6c047c66
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Jan 18 17:14:17 2008 +0000

    [test] Add tests using each backend as a source.
    
    Inspired by bug 7362 (painting a glitz surface onto an xlib surface
    crashes cairo) and the lack of coverage for
    _cairo_paginated_surface_acquire_source_image(), these tests attempt
    to use each backend as a source surface for all the other backends.
    For example, this checks that one can construct a PS file ready for
    printing and then copy that surface to an image/xlib for previewing.

diff --git a/test/.gitignore b/test/.gitignore
index 51b64ac..12b9973 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -73,10 +73,12 @@ get-clip
 get-group-target
 get-path-extents
 get-render-format
+glitz-surface-source
 glyph-cache-pressure
 gradient-alpha
 gradient-zero-stops
 imagediff
+image-surface-source
 infinite-join
 in-fill-empty-trapezoid
 in-fill-trapezoid
@@ -117,9 +119,11 @@ pattern-getters
 pdf2png
 pdf-features
 pdf-features.pdf
+pdf-surface-source
 png-flatten
 ps-features
 ps-features.ps
+ps-surface-source
 push-group
 radial-gradient
 random-intersections
@@ -129,6 +133,7 @@ svg-clip
 svg-clip.svg
 svg-surface
 svg-surface.svg
+svg-surface-source
 pixman-rotate
 pthread-show-text
 rectangle-rounding-error
@@ -171,6 +176,7 @@ unantialiased-shapes
 unbounded-operator
 user-data
 xlib-surface
+xlib-surface-source
 zero-alpha
 valgrind-log
 *-out.pdf
diff --git a/test/Makefile.am b/test/Makefile.am
index 39d5e06..e082307 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -59,9 +59,10 @@ get-group-target$(EXEEXT)				\
 get-path-extents$(EXEEXT)				\
 gradient-alpha$(EXEEXT)					\
 gradient-zero-stops$(EXEEXT)				\
+image-surface-source$(EXEEXT)				\
 infinite-join$(EXEEXT)					\
 in-fill-empty-trapezoid$(EXEEXT)			\
-in-fill-trapezoid$(EXEEXT)			\
+in-fill-trapezoid$(EXEEXT)				\
 invalid-matrix$(EXEEXT)					\
 leaky-dash$(EXEEXT)					\
 leaky-polygon$(EXEEXT)					\
@@ -194,21 +195,30 @@ TESTS += ft-text-vertical-layout-type3$(EXEEXT)
 TESTS += ft-text-antialias-none$(EXEEXT)
 endif
 
-if CAIRO_HAS_SVG_SURFACE
-TESTS += svg-surface$(EXEEXT)
-TESTS += svg-clip$(EXEEXT)
+# Need to add win32-surface-source, quartz-surface-source
+if CAIRO_HAS_GLITZ_SURFACE
+TESTS += glitz-surface-source$(EXEEXT)
 endif
 
 if CAIRO_HAS_PDF_SURFACE
 TESTS += pdf-features$(EXEEXT)
+TESTS += pdf-surface-source$(EXEEXT)
 endif
 
 if CAIRO_HAS_PS_SURFACE
 TESTS += ps-features$(EXEEXT)
+TESTS += ps-surface-source$(EXEEXT)
+endif
+
+if CAIRO_HAS_SVG_SURFACE
+TESTS += svg-surface$(EXEEXT)
+TESTS += svg-clip$(EXEEXT)
+TESTS += svg-surface-source$(EXEEXT)
 endif
 
 if CAIRO_HAS_XLIB_SURFACE
 TESTS += xlib-surface$(EXEEXT)
+TESTS += xlib-surface-source$(EXEEXT)
 endif
 
 if CAIRO_HAS_XLIB_XRENDER_SURFACE
@@ -515,6 +525,7 @@ EXTRA_DIST =		\
 6x13.pcf		\
 make-html.pl		\
 romedalen.png		\
+surface-source.c	\
 $(REFERENCE_IMAGES)
 
 # Any test for which the code committed to CVS is expected to fail
diff --git a/test/glitz-surface-source-ref.png b/test/glitz-surface-source-ref.png
new file mode 100644
index 0000000..3fa8bbe
Binary files /dev/null and b/test/glitz-surface-source-ref.png differ
diff --git a/test/glitz-surface-source.c b/test/glitz-surface-source.c
new file mode 100644
index 0000000..d70940a
--- /dev/null
+++ b/test/glitz-surface-source.c
@@ -0,0 +1,196 @@
+/*
+ * Copyright © 2008 Chris Wilson
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Chris Wilson not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Chris Wilson makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * CHRIS WILSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL CHRIS WILSON BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Chris Wilson <chris at chris-wilson.co.uk>
+ */
+
+#include "cairo-test.h"
+#include <cairo-glitz.h>
+#include <cairo-xlib.h>
+#include <cairo-xlib-xrender.h>
+
+#include <assert.h>
+
+#define NAME "glitz"
+#include "surface-source.c"
+
+static cairo_user_data_key_t closure_key;
+
+#if CAIRO_CAN_TEST_GLITZ_GLX_SURFACE
+#include <glitz-glx.h>
+
+struct closure {
+    Display        *dpy;
+    Window          win;
+};
+
+static void
+cleanup (void *data)
+{
+    struct closure *closure = data;
+
+    glitz_glx_fini ();
+
+    if (closure->win)
+	XDestroyWindow (closure->dpy, closure->win);
+
+    XCloseDisplay (closure->dpy);
+
+    free (closure);
+}
+
+static glitz_surface_t *
+_glitz_glx_create_surface (glitz_format_name_t		  formatname,
+			   int				  width,
+			   int				  height,
+			   struct closure		*closure)
+{
+    Display                 * dpy = closure->dpy;
+    int			      scr = DefaultScreen(dpy);
+    glitz_drawable_format_t   templ;
+    glitz_drawable_format_t * dformat = NULL;
+    unsigned long             mask;
+    glitz_drawable_t        * drawable = NULL;
+    glitz_format_t          * format;
+    glitz_surface_t         * sr;
+
+    XSizeHints                xsh;
+    XSetWindowAttributes      xswa;
+    XVisualInfo             * vinfo;
+
+    memset(&templ, 0, sizeof(templ));
+    templ.color.red_size = 8;
+    templ.color.green_size = 8;
+    templ.color.blue_size = 8;
+    templ.color.alpha_size = 8;
+    templ.color.fourcc = GLITZ_FOURCC_RGB;
+    templ.samples = 1;
+
+    glitz_glx_init (NULL);
+
+    mask = GLITZ_FORMAT_SAMPLES_MASK |
+	   GLITZ_FORMAT_FOURCC_MASK |
+	   GLITZ_FORMAT_RED_SIZE_MASK |
+	   GLITZ_FORMAT_GREEN_SIZE_MASK |
+	   GLITZ_FORMAT_BLUE_SIZE_MASK;
+    if (formatname == GLITZ_STANDARD_ARGB32)
+	mask |= GLITZ_FORMAT_ALPHA_SIZE_MASK;
+
+    /* Try for a pbuffer first */
+    if (!getenv("CAIRO_TEST_FORCE_GLITZ_WINDOW"))
+	dformat = glitz_glx_find_pbuffer_format (dpy, scr, mask, &templ, 0);
+
+    if (dformat) {
+	closure->win = None;
+
+	drawable = glitz_glx_create_pbuffer_drawable (dpy, scr, dformat,
+						      width, height);
+	if (!drawable)
+	    goto FAIL;
+    } else {
+	/* No pbuffer, try window */
+	dformat = glitz_glx_find_window_format (dpy, scr, mask, &templ, 0);
+
+	if (!dformat)
+	    goto FAIL;
+
+	vinfo = glitz_glx_get_visual_info_from_format(dpy,
+						      DefaultScreen(dpy),
+						      dformat);
+
+	if (!vinfo)
+	    goto FAIL;
+
+	xsh.flags = PSize;
+	xsh.x = 0;
+	xsh.y = 0;
+	xsh.width = width;
+	xsh.height = height;
+
+	xswa.colormap = XCreateColormap (dpy, RootWindow(dpy, scr),
+					 vinfo->visual, AllocNone);
+	closure->win = XCreateWindow (dpy, RootWindow(dpy, scr),
+				      xsh.x, xsh.y, xsh.width, xsh.height,
+				      0, vinfo->depth, CopyFromParent,
+				      vinfo->visual, CWColormap, &xswa);
+	XFree (vinfo);
+
+	drawable =
+	    glitz_glx_create_drawable_for_window (dpy, scr,
+						  dformat, closure->win,
+						  width, height);
+
+	if (!drawable)
+	    goto DESTROY_WINDOW;
+    }
+
+    format = glitz_find_standard_format (drawable, formatname);
+    if (!format)
+	goto DESTROY_DRAWABLE;
+
+    sr = glitz_surface_create (drawable, format, width, height, 0, NULL);
+    if (!sr)
+	goto DESTROY_DRAWABLE;
+
+    if (closure->win == None || dformat->doublebuffer) {
+	glitz_surface_attach (sr, drawable, GLITZ_DRAWABLE_BUFFER_BACK_COLOR);
+    } else {
+	XMapWindow (closure->dpy, closure->win);
+	glitz_surface_attach (sr, drawable, GLITZ_DRAWABLE_BUFFER_FRONT_COLOR);
+    }
+
+    glitz_drawable_destroy (drawable);
+
+    return sr;
+ DESTROY_DRAWABLE:
+    glitz_drawable_destroy (drawable);
+ DESTROY_WINDOW:
+    if (closure->win)
+	XDestroyWindow (dpy, closure->win);
+ FAIL:
+    return NULL;
+}
+
+static cairo_surface_t *
+create_source_surface (int size)
+{
+    struct closure *closure;
+    glitz_surface_t  * glitz_surface;
+    cairo_surface_t *surface;
+
+    closure = xcalloc (1, sizeof (struct closure));
+
+    closure->dpy = XOpenDisplay (getenv("CAIRO_TEST_GLITZ_DISPLAY"));
+    assert (closure->dpy);
+
+    glitz_surface = _glitz_glx_create_surface (GLITZ_STANDARD_ARGB32,
+					       size, size,
+					       closure);
+    assert (glitz_surface != NULL);
+
+    surface = cairo_glitz_surface_create (glitz_surface);
+
+    cairo_surface_set_user_data (surface, &closure_key, closure, cleanup);
+
+    return surface;
+}
+#endif
diff --git a/test/image-surface-source-ref.png b/test/image-surface-source-ref.png
new file mode 100644
index 0000000..3fa8bbe
Binary files /dev/null and b/test/image-surface-source-ref.png differ
diff --git a/test/image-surface-source.c b/test/image-surface-source.c
new file mode 100644
index 0000000..e675ecd
--- /dev/null
+++ b/test/image-surface-source.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright © 2008 Chris Wilson
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Chris Wilson not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Chris Wilson makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * CHRIS WILSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL CHRIS WILSON BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Chris Wilson <chris at chris-wilson.co.uk>
+ */
+
+#include "cairo-test.h"
+
+#define NAME "image"
+#include "surface-source.c"
+
+static cairo_surface_t *
+create_source_surface (int size)
+{
+    return cairo_image_surface_create (CAIRO_FORMAT_ARGB32, size, size);
+}
diff --git a/test/pdf-surface-source-ref.png b/test/pdf-surface-source-ref.png
new file mode 100644
index 0000000..3fa8bbe
Binary files /dev/null and b/test/pdf-surface-source-ref.png differ
diff --git a/test/pdf-surface-source.c b/test/pdf-surface-source.c
new file mode 100644
index 0000000..680eeef
--- /dev/null
+++ b/test/pdf-surface-source.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright © 2008 Chris Wilson
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Chris Wilson not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Chris Wilson makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * CHRIS WILSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL CHRIS WILSON BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Chris Wilson <chris at chris-wilson.co.uk>
+ */
+
+#include "cairo-test.h"
+#include <cairo-pdf.h>
+
+#define NAME "pdf"
+#include "surface-source.c"
+
+static cairo_surface_t *
+create_source_surface (int size)
+{
+    cairo_surface_t *surface;
+
+    surface = cairo_pdf_surface_create ("pdf-surface-source.pdf", size, size);
+    cairo_surface_set_fallback_resolution (surface, 72., 72.);
+
+    return surface;
+}
diff --git a/test/ps-surface-source-ref.png b/test/ps-surface-source-ref.png
new file mode 100644
index 0000000..3fa8bbe
Binary files /dev/null and b/test/ps-surface-source-ref.png differ
diff --git a/test/ps-surface-source.c b/test/ps-surface-source.c
new file mode 100644
index 0000000..8f584d6
--- /dev/null
+++ b/test/ps-surface-source.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright © 2008 Chris Wilson
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Chris Wilson not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Chris Wilson makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * CHRIS WILSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL CHRIS WILSON BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Chris Wilson <chris at chris-wilson.co.uk>
+ */
+
+#include "cairo-test.h"
+#include <cairo-ps.h>
+
+#define NAME "ps"
+#include "surface-source.c"
+
+static cairo_surface_t *
+create_source_surface (int size)
+{
+    cairo_surface_t *surface;
+
+    surface = cairo_ps_surface_create ("ps-surface-source.ps", size, size);
+    cairo_surface_set_fallback_resolution (surface, 72., 72.);
+
+    return surface;
+}
diff --git a/test/surface-source.c b/test/surface-source.c
new file mode 100644
index 0000000..c7f3334
--- /dev/null
+++ b/test/surface-source.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright © 2008 Chris Wilson
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Chris Wilson not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Chris Wilson makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * CHRIS WILSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL CHRIS WILSON BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Chris Wilson <chris at chris-wilson.co.uk>
+ */
+
+#include "cairo-test.h"
+
+static cairo_test_draw_function_t draw;
+static cairo_surface_t *create_source_surface (int size);
+
+#define SIZE 90
+
+cairo_test_t test = {
+    NAME "-surface-source",
+    "Test using various surfaces as the source",
+    SIZE, SIZE,
+    draw
+};
+
+static void
+draw_pattern (cairo_surface_t *surface, int surface_size)
+{
+    cairo_t *cr = cairo_create (surface);
+
+    cairo_set_source_rgb (cr, 1, 1, 1);
+    cairo_rectangle (cr,
+		     0, 0,
+		     surface_size / 2, surface_size / 2);
+    cairo_fill (cr);
+    cairo_set_source_rgb (cr, 1, 0, 0);
+    cairo_rectangle (cr,
+		     surface_size / 2, 0,
+		     surface_size / 2, surface_size / 2);
+    cairo_fill (cr);
+    cairo_set_source_rgb (cr, 0, 1, 0);
+    cairo_rectangle (cr,
+		     0, surface_size / 2,
+		     surface_size / 2, surface_size / 2);
+    cairo_fill (cr);
+    cairo_set_source_rgb (cr, 0, 0, 1);
+    cairo_rectangle (cr,
+		     surface_size / 2, surface_size / 2,
+		     surface_size / 2, surface_size / 2);
+    cairo_fill (cr);
+
+    cairo_destroy (cr);
+}
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+    cairo_surface_t *surface;
+    int surface_size;
+
+    cairo_set_source_rgb (cr, 0, 0, 0);
+    cairo_paint (cr);
+
+    surface_size = SIZE - 30;
+    surface = create_source_surface (surface_size);
+    draw_pattern (surface, surface_size);
+
+    cairo_set_source_surface (cr, surface, 15, 15);
+    cairo_surface_destroy (surface);
+    cairo_paint (cr);
+
+    return CAIRO_TEST_SUCCESS;
+}
+
+int
+main (void)
+{
+    return cairo_test (&test);
+}
diff --git a/test/svg-surface-source-ref.png b/test/svg-surface-source-ref.png
new file mode 100644
index 0000000..3fa8bbe
Binary files /dev/null and b/test/svg-surface-source-ref.png differ
diff --git a/test/svg-surface-source.c b/test/svg-surface-source.c
new file mode 100644
index 0000000..c8042c4
--- /dev/null
+++ b/test/svg-surface-source.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright © 2008 Chris Wilson
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Chris Wilson not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Chris Wilson makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * CHRIS WILSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL CHRIS WILSON BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Chris Wilson <chris at chris-wilson.co.uk>
+ */
+
+#include "cairo-test.h"
+#include <cairo-svg.h>
+
+#define NAME "svg"
+#include "surface-source.c"
+
+static cairo_surface_t *
+create_source_surface (int size)
+{
+    cairo_surface_t *surface;
+
+    surface = cairo_svg_surface_create ("svg-surface-source.svg", size, size);
+    cairo_surface_set_fallback_resolution (surface, 72., 72.);
+
+    return surface;
+}
diff --git a/test/xlib-surface-source-ref.png b/test/xlib-surface-source-ref.png
new file mode 100644
index 0000000..3fa8bbe
Binary files /dev/null and b/test/xlib-surface-source-ref.png differ
diff --git a/test/xlib-surface-source.c b/test/xlib-surface-source.c
new file mode 100644
index 0000000..3a70a4d
--- /dev/null
+++ b/test/xlib-surface-source.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright © 2008 Chris Wilson
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Chris Wilson not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Chris Wilson makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * CHRIS WILSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL CHRIS WILSON BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Chris Wilson <chris at chris-wilson.co.uk>
+ */
+
+#include "cairo-test.h"
+#include <cairo-xlib.h>
+#if CAIRO_HAS_XLIB_XRENDER_SURFACE
+#include <cairo-xlib-xrender.h>
+#endif
+
+#define NAME "xlib"
+#include "surface-source.c"
+
+static cairo_user_data_key_t closure_key;
+
+struct closure {
+    Display *dpy;
+    Pixmap pix;
+};
+
+static void
+cleanup (void *data)
+{
+    struct closure *arg = data;
+
+    XFreePixmap (arg->dpy, arg->pix);
+    XCloseDisplay (arg->dpy);
+
+    free (arg);
+}
+
+static cairo_surface_t *
+create_source_surface (int size)
+{
+    XRenderPictFormat *xrender_format;
+    struct closure *data;
+    cairo_surface_t *surface;
+
+    data = xmalloc (sizeof (struct closure));
+
+    data->dpy = XOpenDisplay (NULL);
+    xrender_format = XRenderFindStandardFormat (data->dpy, PictStandardARGB32);
+
+    data->pix = XCreatePixmap (data->dpy, DefaultRootWindow (data->dpy),
+			       size, size, xrender_format->depth);
+
+    surface = cairo_xlib_surface_create_with_xrender_format (data->dpy,
+	                                                     data->pix,
+							     DefaultScreenOfDisplay (data->dpy),
+							     xrender_format,
+							     size, size);
+    cairo_surface_set_user_data (surface, &closure_key, data, cleanup);
+
+    return surface;
+}
commit f59f22eecba7cbf2151e01533ba936ca94d25056
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jan 29 09:29:10 2008 +0000

    [check] Only build documents during make check if we have GTK_DOC
    
    Check that gtk-doc has been enabled before running attempting to build
    the docs during make check.

diff --git a/doc/public/Makefile.am b/doc/public/Makefile.am
index faca782..bd5036e 100644
--- a/doc/public/Makefile.am
+++ b/doc/public/Makefile.am
@@ -70,7 +70,9 @@ include $(top_srcdir)/gtk-doc.make
 # Version information for marking the documentation
 EXTRA_DIST += version.xml.in
 
+if ENABLE_GTK_DOC
 check: doc
+endif
 
 TESTS_ENVIRONMENT = srcdir="$(srcdir)" top_srcdir="$(top_srcdir)" MAKE="$(MAKE)"
 TESTS = check-doc-coverage.sh check-doc-syntax.sh
commit e5f0253b67801ad79eb881e189b9835aea0fcf57
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jan 29 09:07:14 2008 +0000

    [cairo-surface] Hide the compiler warnings.
    
    Assign the return value from _cairo_surface_set_error() to hide the
    compiler warnings.

diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 16c48f1..ac594ae 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -1662,13 +1662,16 @@ _cairo_surface_composite_trapezoids (cairo_operator_t		op,
 void
 cairo_surface_copy_page (cairo_surface_t *surface)
 {
+    cairo_status_t status_ignored;
+
     assert (! surface->is_snapshot);
 
     if (surface->status)
 	return;
 
     if (surface->finished) {
-	_cairo_surface_set_error (surface,CAIRO_STATUS_SURFACE_FINISHED);
+	status_ignored = _cairo_surface_set_error (surface,
+		                                 CAIRO_STATUS_SURFACE_FINISHED);
 	return;
     }
 
@@ -1676,8 +1679,8 @@ cairo_surface_copy_page (cairo_surface_t *surface)
     if (surface->backend->copy_page == NULL)
 	return;
 
-    _cairo_surface_set_error (surface,
-			      surface->backend->copy_page (surface));
+    status_ignored = _cairo_surface_set_error (surface,
+			                 surface->backend->copy_page (surface));
 }
 slim_hidden_def (cairo_surface_copy_page);
 
@@ -1693,13 +1696,16 @@ slim_hidden_def (cairo_surface_copy_page);
 void
 cairo_surface_show_page (cairo_surface_t *surface)
 {
+    cairo_status_t status_ignored;
+
     assert (! surface->is_snapshot);
 
     if (surface->status)
 	return;
 
     if (surface->finished) {
-	_cairo_surface_set_error (surface,CAIRO_STATUS_SURFACE_FINISHED);
+	status_ignored = _cairo_surface_set_error (surface,
+		                                 CAIRO_STATUS_SURFACE_FINISHED);
 	return;
     }
 
@@ -1707,8 +1713,8 @@ cairo_surface_show_page (cairo_surface_t *surface)
     if (surface->backend->show_page == NULL)
 	return;
 
-    _cairo_surface_set_error (surface,
-			      surface->backend->show_page (surface));
+    status_ignored = _cairo_surface_set_error (surface,
+			                 surface->backend->show_page (surface));
 }
 slim_hidden_def (cairo_surface_show_page);
 
commit 53c1ed25abb7e8e22b24aa64fcd29d210c6b7903
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jan 29 08:52:28 2008 +0000

    [test/a1-sample-image] Fix the memleak.
    
    Destroy the surface after use.

diff --git a/test/a1-image-sample.c b/test/a1-image-sample.c
index 2dc4254..a95c577 100644
--- a/test/a1-image-sample.c
+++ b/test/a1-image-sample.c
@@ -73,6 +73,8 @@ draw (cairo_t *cr, int width, int height)
 	    cairo_paint (cr);
 	}
 
+    cairo_surface_destroy (surface);
+
     return CAIRO_TEST_SUCCESS;
 }
 
commit 5efc88e9108df2331772cc22dc52ef0a9cc93869
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jan 29 08:50:25 2008 +0000

    [xmalloc] Hide valgrind warning.
    
    Allocate the string to the next integer boundary to hide a valgrind
    warning.

diff --git a/boilerplate/xmalloc.c b/boilerplate/xmalloc.c
index c2cbe23..dfd4946 100644
--- a/boilerplate/xmalloc.c
+++ b/boilerplate/xmalloc.c
@@ -89,10 +89,10 @@ xasprintf (char **strp, const char *fmt, ...)
 #define BUF_SIZE 1024
     va_list va;
     char buffer[BUF_SIZE];
-    int ret;
+    int ret, len;
 
     va_start (va, fmt);
-    ret = vsnprintf (buffer, sizeof(buffer), fmt, va);
+    ret = vsnprintf (buffer, sizeof (buffer), fmt, va);
     va_end (va);
 
     if (ret < 0) {
@@ -100,15 +100,26 @@ xasprintf (char **strp, const char *fmt, ...)
 	exit (1);
     }
 
-    if (strlen (buffer) == sizeof(buffer) - 1) {
-	CAIRO_BOILERPLATE_LOG ("Overflowed fixed buffer\n");
+    len = (ret + sizeof (int)) & -sizeof (int);
+    *strp = malloc (len);
+    if (*strp == NULL) {
+	CAIRO_BOILERPLATE_LOG ("Out of memory\n");
 	exit (1);
     }
 
-    *strp = strdup (buffer);
-    if (!*strp) {
-	CAIRO_BOILERPLATE_LOG ("Out of memory\n");
-	exit (1);
+    if ((unsigned) ret < sizeof (buffer)) {
+	memcpy (*strp, buffer, ret);
+    } else {
+	va_start (va, fmt);
+	ret = vsnprintf (*strp, len, fmt, va);
+	va_end (va);
+
+	if (ret >= len) {
+	    free (*strp);
+	    CAIRO_BOILERPLATE_LOG ("Overflowed dynamic buffer\n");
+	    exit (1);
+	}
     }
+    memset (*strp + ret, 0, len-ret);
 #endif /* !HAVE_VASNPRINTF */
 }
commit 1faf208093a8cce77d2f7d6b248bc1eb1bd19a8a
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Jan 18 14:41:03 2008 +0000

    [cairo-png] Improve error return for invalid parameters.
    
    Only translate an UNSUPPORTED error into a SURFACE_TYPE_MISMATCH, all
    others can be returned to the user unadulterated.
    
    PNG doesn't support width==0 or height==0 and generates an error
    whilst writing - which without further information is assumed to be
    a NO_MEMORY error. So check the image size at the start and return a
    WRITE_ERROR for a zero sized image.

diff --git a/src/cairo-png.c b/src/cairo-png.c
index 429ebf8..40cebe7 100644
--- a/src/cairo-png.c
+++ b/src/cairo-png.c
@@ -132,22 +132,24 @@ write_png (cairo_surface_t	*surface,
 						  &image,
 						  &image_extra);
 
-    if (status == CAIRO_STATUS_NO_MEMORY)
-        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-    else if (status != CAIRO_STATUS_SUCCESS)
+    if (status == CAIRO_INT_STATUS_UNSUPPORTED)
 	return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
+    else if (status)
+        return status;
 
-    if (image->height && image->width) {
-	rows = _cairo_malloc_ab (image->height, sizeof (png_byte*));
-	if (rows == NULL) {
-	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	    goto BAIL1;
-	}
+    /* PNG complains about "Image width or height is zero in IHDR" */
+    if (image->width == 0 || image->height == 0)
+	return _cairo_error (CAIRO_STATUS_WRITE_ERROR);
 
-	for (i = 0; i < image->height; i++)
-	    rows[i] = (png_byte *) image->data + i * image->stride;
+    rows = _cairo_malloc_ab (image->height, sizeof (png_byte*));
+    if (rows == NULL) {
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	goto BAIL1;
     }
 
+    for (i = 0; i < image->height; i++)
+	rows[i] = (png_byte *) image->data + i * image->stride;
+
     png = png_create_write_struct (PNG_LIBPNG_VER_STRING, &status,
 	                           png_simple_error_callback,
 	                           png_simple_warning_callback);
commit d0cc1d929119d2e05578a60af3b873af1d7f6b13
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Jan 18 14:34:41 2008 +0000

    [cairo-pdf-surface] Minor code tidy.
    
    Remove code duplication.

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 46cae59..e7068b0 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1072,17 +1072,15 @@ _cairo_pdf_surface_open_content_stream (cairo_pdf_surface_t  *surface,
 					    surface->width,
 					    surface->height,
 					    surface->content_resources.id);
-	if (status)
-	    return status;
     } else {
 	status =
 	    _cairo_pdf_surface_open_stream (surface,
 					    NULL,
 					    surface->compress_content,
 					    NULL);
-	if (status)
-	    return status;
     }
+    if (status)
+	return status;
 
     surface->content = surface->pdf_stream.self;
 
commit d7ce0582f1eb86b2af5964820378b75297822dd1
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Jan 17 23:18:46 2008 +0000

    [test/font-options] Check the defaults values.
    
    Exercise the getters by checking that a fresh cairo_font_options_t has
    the default values.

diff --git a/test/font-options.c b/test/font-options.c
index fdcde15..5277b22 100644
--- a/test/font-options.c
+++ b/test/font-options.c
@@ -23,10 +23,16 @@
  * Author: Chris Wilson <chris at chris-wilson.co.uk>
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <cairo.h>
 #include <assert.h>
 #include <stdlib.h>
 
+#include <fontconfig/fontconfig.h>
+
 int
 main (void)
 {
@@ -53,21 +59,26 @@ main (void)
     cairo_font_options_merge (options1, NULL);
     cairo_font_options_merge (options1, options2);
 
-    cairo_font_options_destroy (NULL);
-    cairo_font_options_destroy (options1);
-    cairo_font_options_destroy (options2);
-
     cairo_font_options_set_antialias (NULL, CAIRO_ANTIALIAS_DEFAULT);
     cairo_font_options_get_antialias (NULL);
+    assert (cairo_font_options_get_antialias (options1) == CAIRO_ANTIALIAS_DEFAULT);
 
     cairo_font_options_set_subpixel_order (NULL, CAIRO_SUBPIXEL_ORDER_DEFAULT);
     cairo_font_options_get_subpixel_order (NULL);
+    assert (cairo_font_options_get_subpixel_order (options1) ==  CAIRO_SUBPIXEL_ORDER_DEFAULT);
 
     cairo_font_options_set_hint_style (NULL, CAIRO_HINT_STYLE_DEFAULT);
     cairo_font_options_get_hint_style (NULL);
+    assert (cairo_font_options_get_hint_style (options1) == CAIRO_HINT_STYLE_DEFAULT);
 
     cairo_font_options_set_hint_metrics (NULL, CAIRO_HINT_METRICS_DEFAULT);
     cairo_font_options_get_hint_metrics (NULL);
+    assert (cairo_font_options_get_hint_metrics (options1) == CAIRO_HINT_METRICS_DEFAULT);
+
+    cairo_font_options_destroy (NULL);
+    cairo_font_options_destroy (options1);
+    cairo_font_options_destroy (options2);
+
 
     /* Now try creating fonts with NULLs */
     surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, 0, 0);
@@ -87,5 +98,10 @@ main (void)
 
     cairo_destroy (cr);
 
+    cairo_debug_reset_static_data ();
+#if HAVE_FCFINI
+    FcFini ();
+#endif
+
     return 0;
 }
commit f40f24e272cf05a7a727217ae7a35844bf95f5d2
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Jan 17 23:05:53 2008 +0000

    [test/invalid] Test cairo_translate() and friends for NaN safety.
    
    Pass NaNs to cairo_translate() and friends and check that they raise
    an INVALID_MATRIX error.

diff --git a/test/invalid-matrix.c b/test/invalid-matrix.c
index 8a5a9bf..0f0ef0c 100644
--- a/test/invalid-matrix.c
+++ b/test/invalid-matrix.c
@@ -202,6 +202,43 @@ if ((status) == CAIRO_STATUS_SUCCESS) {							\
     cairo_pattern_destroy (pattern);
 
 
+    /* test invalid transformations */
+    cr2 = cairo_create (target);
+    cairo_translate (cr2, bogus.xx, bogus.yy);
+    CHECK_STATUS (status, "cairo_translate(NaN, NaN)");
+    cairo_destroy (cr2);
+
+    cr2 = cairo_create (target);
+    cairo_translate (cr2, 0, bogus.yy);
+    CHECK_STATUS (status, "cairo_translate(0, NaN)");
+    cairo_destroy (cr2);
+
+    cr2 = cairo_create (target);
+    cairo_translate (cr2, bogus.xx, 0);
+    CHECK_STATUS (status, "cairo_translate(NaN, 0)");
+    cairo_destroy (cr2);
+
+
+    cr2 = cairo_create (target);
+    cairo_scale (cr2, bogus.xx, bogus.yy);
+    CHECK_STATUS (status, "cairo_scale(NaN, NaN)");
+    cairo_destroy (cr2);
+
+    cr2 = cairo_create (target);
+    cairo_scale (cr2, 1, bogus.yy);
+    CHECK_STATUS (status, "cairo_scale(1, NaN)");
+    cairo_destroy (cr2);
+
+    cr2 = cairo_create (target);
+    cairo_scale (cr2, bogus.xx, 1);
+    CHECK_STATUS (status, "cairo_scale(NaN, 1)");
+    cairo_destroy (cr2);
+
+    cr2 = cairo_create (target);
+    cairo_rotate (cr2, bogus.xx);
+    CHECK_STATUS (status, "cairo_rotate(NaN)");
+    cairo_destroy (cr2);
+
     return CAIRO_TEST_SUCCESS;
 }
 


More information about the cairo-commit mailing list