[cairo-commit] 18 commits - src/cairo-gl-surface.c src/cairo-pdf-surface.c src/cairo-ps-surface.c src/cairo-surface.c src/cairo-surface-subsurface.c src/cairo-svg-surface.c src/cairo-tee-surface.c src/cairo-xcb-surface.c src/cairo-xlib-surface.c test/api-special-cases.c

Benjamin Otte company at kemper.freedesktop.org
Mon Jul 5 15:46:35 PDT 2010


 src/cairo-gl-surface.c         |   12 
 src/cairo-pdf-surface.c        |   10 
 src/cairo-ps-surface.c         |   41 ++-
 src/cairo-surface-subsurface.c |    2 
 src/cairo-surface.c            |   12 
 src/cairo-svg-surface.c        |   10 
 src/cairo-tee-surface.c        |   15 +
 src/cairo-xcb-surface.c        |   10 
 src/cairo-xlib-surface.c       |   18 +
 test/api-special-cases.c       |  499 +++++++++++++++++++++++++++++++++++++++--
 10 files changed, 578 insertions(+), 51 deletions(-)

New commits:
commit 75f269b14e1e4cdadd8c08566a07b2460ae3364b
Author: Benjamin Otte <otte at redhat.com>
Date:   Tue Jul 6 00:41:12 2010 +0200

    test: Add documentation to the api-special-cases test
    
    Hopefully people add other backend APIs to the testsuite.

diff --git a/test/api-special-cases.c b/test/api-special-cases.c
index d5f6198..b4b4c0a 100644
--- a/test/api-special-cases.c
+++ b/test/api-special-cases.c
@@ -23,6 +23,33 @@
  * Author: Benjamin Otte <otte at redhat.com>
  */
 
+/*
+ * WHAT THIS TEST DOES
+ *
+ * This test tests that for all public APIs Cairo behaves correct, consistent
+ * and most of all doesn't crash. It does this by calling all APIs that take
+ * surfaces and calling them on specially prepared surfaces that should fail 
+ * when called on this function.
+ *
+ * ADDING NEW FUNCTIONS
+ *
+ * You need (for adding the function cairo_surface_foo):
+ * 1) A surface_test_func_t named test_cairo_surface_foo that gets passed the
+ *    prepared surface and has the job of calling the function and checking
+ *    the return value (if one exists) for correctness. The top of this file
+ *    contains all these shim functions.
+ * 2) Knowledge if the function behaves like a setter or like a setter. A 
+ *    setter should set an error status on the surface, a getter does not
+ *    modify the function.
+ * 3) Knowledge if the function only works for a specific surface type and for
+ *    which one.
+ * 4) An entry in the tests array using the TEST() macro. It takes as arguments:
+ *    - The function name
+ *    - TRUE if the function modifies the surface, FALSE otherwise
+ *    - the surface type for which the function is valid or -1 if it is valid
+ *      for all surface types.
+ */
+
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
commit 398870e64a18f32f1854cb19f64c34e2b1987140
Author: Benjamin Otte <otte at redhat.com>
Date:   Tue Jul 6 00:21:38 2010 +0200

    xlib: Setters should set finished surfaces into an error status
    
    Caught by api-special-cases test

diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index baf4302..ddc745c 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -3494,16 +3494,21 @@ cairo_xlib_surface_set_size (cairo_surface_t *abstract_surface,
 
     if (unlikely (abstract_surface->status))
 	return;
+    if (unlikely (abstract_surface->finished)) {
+	status = _cairo_surface_set_error (abstract_surface,
+		                           _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
+	return;
+    }
 
     if (! _cairo_surface_is_xlib (abstract_surface)) {
 	status = _cairo_surface_set_error (abstract_surface,
-		                           CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
+		                           _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
 	return;
     }
 
     if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX) {
 	status = _cairo_surface_set_error (abstract_surface,
-		                           CAIRO_STATUS_INVALID_SIZE);
+		                           _cairo_error (CAIRO_STATUS_INVALID_SIZE));
 	return;
     }
 
@@ -3535,16 +3540,21 @@ cairo_xlib_surface_set_drawable (cairo_surface_t   *abstract_surface,
 
     if (unlikely (abstract_surface->status))
 	return;
+    if (unlikely (abstract_surface->finished)) {
+	status = _cairo_surface_set_error (abstract_surface,
+		                           _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
+	return;
+    }
 
     if (! _cairo_surface_is_xlib (abstract_surface)) {
 	status = _cairo_surface_set_error (abstract_surface,
-		                           CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
+		                           _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
 	return;
     }
 
     if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX) {
 	status = _cairo_surface_set_error (abstract_surface,
-		                           CAIRO_STATUS_INVALID_SIZE);
+		                           _cairo_error (CAIRO_STATUS_INVALID_SIZE));
 	return;
     }
 
commit 6e562d1448eb70b7269f8f2f280719aa2aeb3ce7
Author: Benjamin Otte <otte at redhat.com>
Date:   Tue Jul 6 00:20:57 2010 +0200

    xcb: Setters should set finished surfaces into an error status
    
    Caught by api-special-cases test

diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c
index 49b2dfb..60425a4 100644
--- a/src/cairo-xcb-surface.c
+++ b/src/cairo-xcb-surface.c
@@ -1326,16 +1326,22 @@ cairo_xcb_surface_set_size (cairo_surface_t *abstract_surface,
 
     if (unlikely (abstract_surface->status))
 	return;
+    if (unlikely (abstract_surface->finished)) {
+	status_ignored = _cairo_surface_set_error (abstract_surface,
+						   _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
+	return;
+    }
+
 
     if (abstract_surface->type != CAIRO_SURFACE_TYPE_XCB) {
 	status_ignored = _cairo_surface_set_error (abstract_surface,
-						   CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
+						   _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
 	return;
     }
 
     if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX) {
 	status_ignored = _cairo_surface_set_error (abstract_surface,
-						   CAIRO_STATUS_INVALID_SIZE);
+						   _cairo_error (CAIRO_STATUS_INVALID_SIZE));
 	return;
     }
 
commit fa070704966f10e7264778a3ffb401054a68e8f7
Author: Benjamin Otte <otte at redhat.com>
Date:   Tue Jul 6 00:20:36 2010 +0200

    test: Add xcb and xlib functions to api-special-cases test

diff --git a/test/api-special-cases.c b/test/api-special-cases.c
index 85dc9a4..d5f6198 100644
--- a/test/api-special-cases.c
+++ b/test/api-special-cases.c
@@ -494,6 +494,83 @@ test_cairo_svg_surface_restrict_to_version (cairo_surface_t *surface)
 
 #endif /* CAIRO_HAS_SVG_SURFACE */
 
+#if CAIRO_HAS_XCB_SURFACE
+
+static cairo_test_status_t
+test_cairo_xcb_surface_set_size (cairo_surface_t *surface)
+{
+    cairo_xcb_surface_set_size (surface, 5, 5);
+    return CAIRO_TEST_SUCCESS;
+}
+
+#endif
+
+#if CAIRO_HAS_XLIB_SURFACE
+
+static cairo_test_status_t
+test_cairo_xlib_surface_set_size (cairo_surface_t *surface)
+{
+    cairo_xlib_surface_set_size (surface, 5, 5);
+    return CAIRO_TEST_SUCCESS;
+}
+
+static cairo_test_status_t
+test_cairo_xlib_surface_set_drawable (cairo_surface_t *surface)
+{
+    cairo_xlib_surface_set_drawable (surface, 0, 5, 5);
+    return CAIRO_TEST_SUCCESS;
+}
+
+static cairo_test_status_t
+test_cairo_xlib_surface_get_display (cairo_surface_t *surface)
+{
+    Display *display = cairo_xlib_surface_get_display (surface);
+    return display == NULL || surface_has_type (surface, CAIRO_SURFACE_TYPE_XLIB) ? CAIRO_TEST_SUCCESS : CAIRO_TEST_ERROR;
+}
+
+static cairo_test_status_t
+test_cairo_xlib_surface_get_screen (cairo_surface_t *surface)
+{
+    Screen *screen = cairo_xlib_surface_get_screen (surface);
+    return screen == NULL || surface_has_type (surface, CAIRO_SURFACE_TYPE_XLIB) ? CAIRO_TEST_SUCCESS : CAIRO_TEST_ERROR;
+}
+
+static cairo_test_status_t
+test_cairo_xlib_surface_get_visual (cairo_surface_t *surface)
+{
+    Visual *visual = cairo_xlib_surface_get_visual (surface);
+    return visual == NULL || surface_has_type (surface, CAIRO_SURFACE_TYPE_XLIB) ? CAIRO_TEST_SUCCESS : CAIRO_TEST_ERROR;
+}
+
+static cairo_test_status_t
+test_cairo_xlib_surface_get_drawable (cairo_surface_t *surface)
+{
+    Drawable drawable = cairo_xlib_surface_get_drawable (surface);
+    return drawable == 0 || surface_has_type (surface, CAIRO_SURFACE_TYPE_XLIB) ? CAIRO_TEST_SUCCESS : CAIRO_TEST_ERROR;
+}
+
+static cairo_test_status_t
+test_cairo_xlib_surface_get_depth (cairo_surface_t *surface)
+{
+    int depth = cairo_xlib_surface_get_depth (surface);
+    return depth == 0 || surface_has_type (surface, CAIRO_SURFACE_TYPE_XLIB) ? CAIRO_TEST_SUCCESS : CAIRO_TEST_ERROR;
+}
+
+static cairo_test_status_t
+test_cairo_xlib_surface_get_width (cairo_surface_t *surface)
+{
+    int width = cairo_xlib_surface_get_width (surface);
+    return width == 0 || surface_has_type (surface, CAIRO_SURFACE_TYPE_XLIB) ? CAIRO_TEST_SUCCESS : CAIRO_TEST_ERROR;
+}
+
+static cairo_test_status_t
+test_cairo_xlib_surface_get_height (cairo_surface_t *surface)
+{
+    int height = cairo_xlib_surface_get_height (surface);
+    return height == 0 || surface_has_type (surface, CAIRO_SURFACE_TYPE_XLIB) ? CAIRO_TEST_SUCCESS : CAIRO_TEST_ERROR;
+}
+
+#endif
 
 
 #define TEST(name, surface_type, sets_status) { #name, test_ ## name, surface_type, sets_status }
@@ -562,6 +639,20 @@ struct {
 #if CAIRO_HAS_SVG_SURFACE
     TEST (cairo_svg_surface_restrict_to_version, CAIRO_SURFACE_TYPE_SVG, TRUE),
 #endif
+#if CAIRO_HAS_XCB_SURFACE
+    TEST (cairo_xcb_surface_set_size, CAIRO_SURFACE_TYPE_XCB, TRUE),
+#endif
+#if CAIRO_HAS_XLIB_SURFACE
+    TEST (cairo_xlib_surface_set_size, CAIRO_SURFACE_TYPE_XLIB, TRUE),
+    TEST (cairo_xlib_surface_set_drawable, CAIRO_SURFACE_TYPE_XLIB, TRUE),
+    TEST (cairo_xlib_surface_get_display, CAIRO_SURFACE_TYPE_XLIB, FALSE),
+    TEST (cairo_xlib_surface_get_drawable, CAIRO_SURFACE_TYPE_XLIB, FALSE),
+    TEST (cairo_xlib_surface_get_screen, CAIRO_SURFACE_TYPE_XLIB, FALSE),
+    TEST (cairo_xlib_surface_get_visual, CAIRO_SURFACE_TYPE_XLIB, FALSE),
+    TEST (cairo_xlib_surface_get_depth, CAIRO_SURFACE_TYPE_XLIB, FALSE),
+    TEST (cairo_xlib_surface_get_width, CAIRO_SURFACE_TYPE_XLIB, FALSE),
+    TEST (cairo_xlib_surface_get_height, CAIRO_SURFACE_TYPE_XLIB, FALSE),
+#endif
 };
 
 static cairo_test_status_t
commit c4068fe9414bad663f77c030ac96fa4b4cba87ba
Author: Benjamin Otte <otte at redhat.com>
Date:   Mon Jul 5 23:14:33 2010 +0200

    test: Add ps, pdf and svg to the api-special-cases test

diff --git a/test/api-special-cases.c b/test/api-special-cases.c
index 92685c4..85dc9a4 100644
--- a/test/api-special-cases.c
+++ b/test/api-special-cases.c
@@ -44,6 +44,9 @@
 #if CAIRO_HAS_PS_SURFACE
 #include <cairo-ps.h>
 #endif
+#if CAIRO_HAS_SVG_SURFACE
+#include <cairo-svg.h>
+#endif
 #if CAIRO_HAS_XCB_SURFACE
 #include <cairo-xcb.h>
 #endif
@@ -409,6 +412,90 @@ test_cairo_gl_surface_swapbuffers (cairo_surface_t *surface)
 
 #endif /* CAIRO_HAS_GL_SURFACE */
 
+#if CAIRO_HAS_PDF_SURFACE
+
+static cairo_test_status_t
+test_cairo_pdf_surface_restrict_to_version (cairo_surface_t *surface)
+{
+    cairo_pdf_surface_restrict_to_version (surface, CAIRO_PDF_VERSION_1_4);
+    return CAIRO_TEST_SUCCESS;
+}
+
+static cairo_test_status_t
+test_cairo_pdf_surface_set_size (cairo_surface_t *surface)
+{
+    cairo_pdf_surface_set_size (surface, 5, 5);
+    return CAIRO_TEST_SUCCESS;
+}
+
+#endif /* CAIRO_HAS_PDF_SURFACE */
+
+#if CAIRO_HAS_PS_SURFACE
+
+static cairo_test_status_t
+test_cairo_ps_surface_restrict_to_level (cairo_surface_t *surface)
+{
+    cairo_ps_surface_restrict_to_level (surface, CAIRO_PS_LEVEL_2);
+    return CAIRO_TEST_SUCCESS;
+}
+
+static cairo_test_status_t
+test_cairo_ps_surface_set_eps (cairo_surface_t *surface)
+{
+    cairo_ps_surface_set_eps (surface, TRUE);
+    return CAIRO_TEST_SUCCESS;
+}
+
+static cairo_test_status_t
+test_cairo_ps_surface_get_eps (cairo_surface_t *surface)
+{
+    cairo_bool_t eps = cairo_ps_surface_get_eps (surface);
+    return eps ? CAIRO_TEST_ERROR : CAIRO_TEST_SUCCESS;
+}
+
+static cairo_test_status_t
+test_cairo_ps_surface_set_size (cairo_surface_t *surface)
+{
+    cairo_ps_surface_set_size (surface, 5, 5);
+    return CAIRO_TEST_SUCCESS;
+}
+
+static cairo_test_status_t
+test_cairo_ps_surface_dsc_comment (cairo_surface_t *surface)
+{
+    cairo_ps_surface_dsc_comment (surface, "54, 74, 90, 2010");
+    return CAIRO_TEST_SUCCESS;
+}
+
+static cairo_test_status_t
+test_cairo_ps_surface_dsc_begin_setup (cairo_surface_t *surface)
+{
+    cairo_ps_surface_dsc_begin_setup (surface);
+    return CAIRO_TEST_SUCCESS;
+}
+
+static cairo_test_status_t
+test_cairo_ps_surface_dsc_begin_page_setup (cairo_surface_t *surface)
+{
+    cairo_ps_surface_dsc_begin_page_setup (surface);
+    return CAIRO_TEST_SUCCESS;
+}
+
+#endif /* CAIRO_HAS_PS_SURFACE */
+
+#if CAIRO_HAS_SVG_SURFACE
+
+static cairo_test_status_t
+test_cairo_svg_surface_restrict_to_version (cairo_surface_t *surface)
+{
+    cairo_svg_surface_restrict_to_version (surface, CAIRO_SVG_VERSION_1_1);
+    return CAIRO_TEST_SUCCESS;
+}
+
+#endif /* CAIRO_HAS_SVG_SURFACE */
+
+
+
 #define TEST(name, surface_type, sets_status) { #name, test_ ## name, surface_type, sets_status }
 
 struct {
@@ -459,6 +546,22 @@ struct {
     TEST (cairo_gl_surface_get_height, CAIRO_SURFACE_TYPE_GL, FALSE),
     TEST (cairo_gl_surface_swapbuffers, CAIRO_SURFACE_TYPE_GL, TRUE),
 #endif
+#if CAIRO_HAS_PDF_SURFACE
+    TEST (cairo_pdf_surface_restrict_to_version, CAIRO_SURFACE_TYPE_PDF, TRUE),
+    TEST (cairo_pdf_surface_set_size, CAIRO_SURFACE_TYPE_PDF, TRUE),
+#endif
+#if CAIRO_HAS_PS_SURFACE
+    TEST (cairo_ps_surface_restrict_to_level, CAIRO_SURFACE_TYPE_PS, TRUE),
+    TEST (cairo_ps_surface_set_eps, CAIRO_SURFACE_TYPE_PS, TRUE),
+    TEST (cairo_ps_surface_get_eps, CAIRO_SURFACE_TYPE_PS, FALSE),
+    TEST (cairo_ps_surface_set_size, CAIRO_SURFACE_TYPE_PS, TRUE),
+    TEST (cairo_ps_surface_dsc_comment, CAIRO_SURFACE_TYPE_PS, TRUE),
+    TEST (cairo_ps_surface_dsc_begin_setup, CAIRO_SURFACE_TYPE_PS, TRUE),
+    TEST (cairo_ps_surface_dsc_begin_page_setup, CAIRO_SURFACE_TYPE_PS, TRUE),
+#endif
+#if CAIRO_HAS_SVG_SURFACE
+    TEST (cairo_svg_surface_restrict_to_version, CAIRO_SURFACE_TYPE_SVG, TRUE),
+#endif
 };
 
 static cairo_test_status_t
commit 3e008e8ab0a1c5254bd1d8a58c9e9a89846fe7ac
Author: Benjamin Otte <otte at redhat.com>
Date:   Mon Jul 5 23:14:19 2010 +0200

    svg: Set error when extracting from finished surface
    
    Caught by api-special-cases test

diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index f83e44c..4c96a3a 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -262,6 +262,11 @@ _extract_svg_surface (cairo_surface_t		 *surface,
 
     if (surface->status)
 	return FALSE;
+    if (surface->finished) {
+	status_ignored = _cairo_surface_set_error (surface,
+						   _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
+        return FALSE;
+    }
 
     if (! _cairo_surface_is_paginated (surface)) {
 	status_ignored = _cairo_surface_set_error (surface,
@@ -275,6 +280,11 @@ _extract_svg_surface (cairo_surface_t		 *surface,
 						   target->status);
 	return FALSE;
     }
+    if (target->finished) {
+	status_ignored = _cairo_surface_set_error (surface,
+						   _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
+        return FALSE;
+    }
 
     if (! _cairo_surface_is_svg (target)) {
 	status_ignored = _cairo_surface_set_error (surface,
commit 2e66cbaee2efc4a8eb2117f945d68e2816349cfe
Author: Benjamin Otte <otte at redhat.com>
Date:   Mon Jul 5 23:10:12 2010 +0200

    ps: Allow specifying if errors on extract_surface should be set
    
    Getters should not set errors on passed in input. So we don't.
    
    Caught by api-special-cases test

diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 3e854d8..092a2df 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -1097,6 +1097,7 @@ _cairo_surface_is_ps (cairo_surface_t *surface)
  */
 static cairo_bool_t
 _extract_ps_surface (cairo_surface_t	 *surface,
+                     cairo_bool_t         set_error_on_failure,
 		     cairo_ps_surface_t **ps_surface)
 {
     cairo_surface_t *target;
@@ -1105,31 +1106,36 @@ _extract_ps_surface (cairo_surface_t	 *surface,
     if (surface->status)
 	return FALSE;
     if (surface->finished) {
-	status_ignored = _cairo_surface_set_error (surface,
-						   _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
+        if (set_error_on_failure)
+            status_ignored = _cairo_surface_set_error (surface,
+                                                       _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
 	return FALSE;
     }
 
     if (! _cairo_surface_is_paginated (surface)) {
-	status_ignored = _cairo_surface_set_error (surface,
-						   _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
+        if (set_error_on_failure)
+            status_ignored = _cairo_surface_set_error (surface,
+                                                       _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
 	return FALSE;
     }
 
     target = _cairo_paginated_surface_get_target (surface);
     if (target->status) {
-	status_ignored = _cairo_surface_set_error (surface, target->status);
+        if (set_error_on_failure)
+            status_ignored = _cairo_surface_set_error (surface, target->status);
 	return FALSE;
     }
     if (target->finished) {
-	status_ignored = _cairo_surface_set_error (surface,
-						   _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
+        if (set_error_on_failure)
+            status_ignored = _cairo_surface_set_error (surface,
+                                                       _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
 	return FALSE;
     }
 
     if (! _cairo_surface_is_ps (target)) {
-	status_ignored = _cairo_surface_set_error (surface,
-						   _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
+        if (set_error_on_failure)
+            status_ignored = _cairo_surface_set_error (surface,
+                                                       _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
 	return FALSE;
     }
 
@@ -1159,7 +1165,7 @@ cairo_ps_surface_restrict_to_level (cairo_surface_t  *surface,
 {
     cairo_ps_surface_t *ps_surface = NULL;
 
-    if (! _extract_ps_surface (surface, &ps_surface))
+    if (! _extract_ps_surface (surface, TRUE, &ps_surface))
 	return;
 
     if (level < CAIRO_PS_LEVEL_LAST)
@@ -1230,7 +1236,7 @@ cairo_ps_surface_set_eps (cairo_surface_t	*surface,
 {
     cairo_ps_surface_t *ps_surface = NULL;
 
-    if (! _extract_ps_surface (surface, &ps_surface))
+    if (! _extract_ps_surface (surface, TRUE, &ps_surface))
 	return;
 
     ps_surface->eps = eps;
@@ -1251,8 +1257,7 @@ cairo_ps_surface_get_eps (cairo_surface_t	*surface)
 {
     cairo_ps_surface_t *ps_surface = NULL;
 
-    /* XXX this should not call _cairo_surface_set_error on error */
-    if (! _extract_ps_surface (surface, &ps_surface))
+    if (! _extract_ps_surface (surface, FALSE, &ps_surface))
 	return FALSE;
 
     return ps_surface->eps;
@@ -1282,7 +1287,7 @@ cairo_ps_surface_set_size (cairo_surface_t	*surface,
 {
     cairo_ps_surface_t *ps_surface = NULL;
 
-    if (! _extract_ps_surface (surface, &ps_surface))
+    if (! _extract_ps_surface (surface, TRUE, &ps_surface))
 	return;
 
     ps_surface->width = width_in_points;
@@ -1388,7 +1393,7 @@ cairo_ps_surface_dsc_comment (cairo_surface_t	*surface,
     cairo_status_t status;
     char *comment_copy;
 
-    if (! _extract_ps_surface (surface, &ps_surface))
+    if (! _extract_ps_surface (surface, TRUE, &ps_surface))
 	return;
 
     /* A couple of sanity checks on the comment value. */
@@ -1438,7 +1443,7 @@ cairo_ps_surface_dsc_begin_setup (cairo_surface_t *surface)
 {
     cairo_ps_surface_t *ps_surface = NULL;
 
-    if (! _extract_ps_surface (surface, &ps_surface))
+    if (! _extract_ps_surface (surface, TRUE, &ps_surface))
 	return;
 
     if (ps_surface->dsc_comment_target == &ps_surface->dsc_header_comments)
@@ -1467,7 +1472,7 @@ cairo_ps_surface_dsc_begin_page_setup (cairo_surface_t *surface)
 {
     cairo_ps_surface_t *ps_surface = NULL;
 
-    if (! _extract_ps_surface (surface, &ps_surface))
+    if (! _extract_ps_surface (surface, TRUE, &ps_surface))
 	return;
 
     if (ps_surface->dsc_comment_target == &ps_surface->dsc_header_comments ||
commit f5dfc3ce6eab3bf836f2d7f7cf72d2834c42d72f
Author: Benjamin Otte <otte at redhat.com>
Date:   Mon Jul 5 23:08:08 2010 +0200

    ps: Set error when extracting from finished surface
    
    Caught by api-special-cases test

diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 15a6752..3e854d8 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -1104,6 +1104,11 @@ _extract_ps_surface (cairo_surface_t	 *surface,
 
     if (surface->status)
 	return FALSE;
+    if (surface->finished) {
+	status_ignored = _cairo_surface_set_error (surface,
+						   _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
+	return FALSE;
+    }
 
     if (! _cairo_surface_is_paginated (surface)) {
 	status_ignored = _cairo_surface_set_error (surface,
@@ -1116,6 +1121,11 @@ _extract_ps_surface (cairo_surface_t	 *surface,
 	status_ignored = _cairo_surface_set_error (surface, target->status);
 	return FALSE;
     }
+    if (target->finished) {
+	status_ignored = _cairo_surface_set_error (surface,
+						   _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
+	return FALSE;
+    }
 
     if (! _cairo_surface_is_ps (target)) {
 	status_ignored = _cairo_surface_set_error (surface,
commit 106357f6e28467f6db02e8d69c4aea459aca781c
Author: Benjamin Otte <otte at redhat.com>
Date:   Mon Jul 5 23:07:24 2010 +0200

    pdf: Set error when extracting from finished surface
    
    Caught by api-special-cases test

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 350f7d0..8b49805 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -498,6 +498,11 @@ _extract_pdf_surface (cairo_surface_t		 *surface,
 
     if (surface->status)
 	return FALSE;
+    if (surface->finished) {
+	status_ignored = _cairo_surface_set_error (surface,
+						   _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
+        return FALSE;
+    }
 
     if (! _cairo_surface_is_paginated (surface)) {
 	status_ignored = _cairo_surface_set_error (surface,
@@ -511,6 +516,11 @@ _extract_pdf_surface (cairo_surface_t		 *surface,
 						   target->status);
 	return FALSE;
     }
+    if (target->finished) {
+	status_ignored = _cairo_surface_set_error (surface,
+						   _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
+	return FALSE;
+    }
 
     if (! _cairo_surface_is_pdf (target)) {
 	status_ignored = _cairo_surface_set_error (surface,
commit 702aa19fdae8bd511c4374f580dde6503afd3341
Author: Benjamin Otte <otte at redhat.com>
Date:   Mon Jul 5 22:50:44 2010 +0200

    gl: Fail properly when called with finished functions
    
    Caught by api-special-cases test

diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index a36d7b7..cfc1f44 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -366,11 +366,16 @@ cairo_gl_surface_set_size (cairo_surface_t *abstract_surface,
 
     if (unlikely (abstract_surface->status))
 	return;
+    if (unlikely (abstract_surface->finished)) {
+	status = _cairo_surface_set_error (abstract_surface,
+		                           _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
+        return;
+    }
 
     if (! _cairo_surface_is_gl (abstract_surface) ||
         ! _cairo_gl_surface_is_texture (surface)) {
 	status = _cairo_surface_set_error (abstract_surface,
-		                           CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
+		                           _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
 	return;
     }
 
@@ -408,6 +413,11 @@ cairo_gl_surface_swapbuffers (cairo_surface_t *abstract_surface)
 
     if (unlikely (abstract_surface->status))
 	return;
+    if (unlikely (abstract_surface->finished)) {
+	status = _cairo_surface_set_error (abstract_surface,
+		                           _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
+        return;
+    }
 
     if (! _cairo_surface_is_gl (abstract_surface)) {
 	status = _cairo_surface_set_error (abstract_surface,
commit b87be76bdfcbd329c79a9f11b24d22010ad15dde
Author: Benjamin Otte <otte at redhat.com>
Date:   Mon Jul 5 22:50:18 2010 +0200

    test: Add gl functions to the tests

diff --git a/test/api-special-cases.c b/test/api-special-cases.c
index a72f86a..92685c4 100644
--- a/test/api-special-cases.c
+++ b/test/api-special-cases.c
@@ -334,7 +334,7 @@ test_cairo_surface_write_to_png_stream (cairo_surface_t *surface)
     return status && status != CAIRO_STATUS_WRITE_ERROR ? CAIRO_TEST_SUCCESS : CAIRO_TEST_ERROR;
 }
 
-#endif
+#endif /* CAIRO_HAS_PNG_FUNCTIONS */
 
 static cairo_test_status_t
 test_cairo_recording_surface_ink_extents (cairo_surface_t *surface)
@@ -377,6 +377,37 @@ test_cairo_tee_surface_index (cairo_surface_t *surface)
     return status ? CAIRO_TEST_SUCCESS : CAIRO_TEST_ERROR;
 }
 
+#if CAIRO_HAS_GL_SURFACE
+
+static cairo_test_status_t
+test_cairo_gl_surface_set_size (cairo_surface_t *surface)
+{
+    cairo_gl_surface_set_size (surface, 5, 5);
+    return CAIRO_TEST_SUCCESS;
+}
+
+static cairo_test_status_t
+test_cairo_gl_surface_get_width (cairo_surface_t *surface)
+{
+    unsigned int width = cairo_gl_surface_get_width (surface);
+    return width == 0 || surface_has_type (surface, CAIRO_SURFACE_TYPE_GL) ? CAIRO_TEST_SUCCESS : CAIRO_TEST_ERROR;
+}
+
+static cairo_test_status_t
+test_cairo_gl_surface_get_height (cairo_surface_t *surface)
+{
+    unsigned int height = cairo_gl_surface_get_height (surface);
+    return height == 0 || surface_has_type (surface, CAIRO_SURFACE_TYPE_GL) ? CAIRO_TEST_SUCCESS : CAIRO_TEST_ERROR;
+}
+
+static cairo_test_status_t
+test_cairo_gl_surface_swapbuffers (cairo_surface_t *surface)
+{
+    cairo_gl_surface_swapbuffers (surface);
+    return CAIRO_TEST_SUCCESS;
+}
+
+#endif /* CAIRO_HAS_GL_SURFACE */
 
 #define TEST(name, surface_type, sets_status) { #name, test_ ## name, surface_type, sets_status }
 
@@ -422,6 +453,12 @@ struct {
     TEST (cairo_tee_surface_add, CAIRO_SURFACE_TYPE_TEE, TRUE),
     TEST (cairo_tee_surface_remove, CAIRO_SURFACE_TYPE_TEE, TRUE),
     TEST (cairo_tee_surface_index, CAIRO_SURFACE_TYPE_TEE, FALSE),
+#if CAIRO_HAS_GL_SURFACE
+    TEST (cairo_gl_surface_set_size, CAIRO_SURFACE_TYPE_GL, TRUE),
+    TEST (cairo_gl_surface_get_width, CAIRO_SURFACE_TYPE_GL, FALSE),
+    TEST (cairo_gl_surface_get_height, CAIRO_SURFACE_TYPE_GL, FALSE),
+    TEST (cairo_gl_surface_swapbuffers, CAIRO_SURFACE_TYPE_GL, TRUE),
+#endif
 };
 
 static cairo_test_status_t
commit 448653e7b9938100c3f2e30e026fbc4d9de7d0d5
Author: Benjamin Otte <otte at redhat.com>
Date:   Mon Jul 5 22:41:43 2010 +0200

    Call _cairo_error() when setting the FINISHED error on surfaces

diff --git a/src/cairo-surface-subsurface.c b/src/cairo-surface-subsurface.c
index f39dcd2..01ea7e2 100644
--- a/src/cairo-surface-subsurface.c
+++ b/src/cairo-surface-subsurface.c
@@ -497,7 +497,7 @@ cairo_surface_create_for_rectangle (cairo_surface_t *target,
     if (unlikely (target->status))
 	return _cairo_surface_create_in_error (target->status);
     if (unlikely (target->finished))
-	return _cairo_surface_create_in_error (CAIRO_STATUS_SURFACE_FINISHED);
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
 
     surface = malloc (sizeof (cairo_surface_subsurface_t));
     if (unlikely (surface == NULL))
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index a5439c2..8906c5f 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -858,7 +858,7 @@ cairo_surface_set_mime_data (cairo_surface_t		*surface,
     if (unlikely (surface->status))
 	return surface->status;
     if (surface->finished)
-	return _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED);
+	return _cairo_surface_set_error (surface, _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
 
     status = _cairo_intern_string (&mime_type, -1);
     if (unlikely (status))
@@ -954,7 +954,7 @@ _cairo_surface_set_font_options (cairo_surface_t       *surface,
 
     if (surface->finished) {
 	status = _cairo_surface_set_error (surface,
-		                           CAIRO_STATUS_SURFACE_FINISHED);
+		                           _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
 	return;
     }
 
@@ -1083,7 +1083,7 @@ cairo_surface_mark_dirty_rectangle (cairo_surface_t *surface,
     assert (surface->snapshot_of == NULL);
 
     if (surface->finished) {
-	status = _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED);
+	status = _cairo_surface_set_error (surface, _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
 	return;
     }
 
@@ -1142,7 +1142,7 @@ _cairo_surface_set_device_scale (cairo_surface_t *surface,
     assert (surface->snapshot_of == NULL);
 
     if (surface->finished) {
-	status = _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED);
+	status = _cairo_surface_set_error (surface, _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
 	return;
     }
 
@@ -1192,7 +1192,7 @@ cairo_surface_set_device_offset (cairo_surface_t *surface,
     assert (surface->snapshot_of == NULL);
 
     if (surface->finished) {
-	status = _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED);
+	status = _cairo_surface_set_error (surface, _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
 	return;
     }
 
@@ -1279,7 +1279,7 @@ cairo_surface_set_fallback_resolution (cairo_surface_t	*surface,
     assert (surface->snapshot_of == NULL);
 
     if (surface->finished) {
-	status = _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED);
+	status = _cairo_surface_set_error (surface, _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
 	return;
     }
 
commit 19da8e138d317c1770d8bbd21a49c657d954f126
Author: Benjamin Otte <otte at redhat.com>
Date:   Mon Jul 5 22:40:54 2010 +0200

    tee: Add proper error handling
    
    Caught by api-special-cases

diff --git a/src/cairo-tee-surface.c b/src/cairo-tee-surface.c
index be530e0..f17c37c 100644
--- a/src/cairo-tee-surface.c
+++ b/src/cairo-tee-surface.c
@@ -468,6 +468,11 @@ cairo_tee_surface_add (cairo_surface_t *abstract_surface,
 
     if (unlikely (abstract_surface->status))
 	return;
+    if (unlikely (abstract_surface->finished)) {
+	status = _cairo_surface_set_error (abstract_surface,
+					   _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
+	return;
+    }
 
     if (abstract_surface->backend != &cairo_tee_surface_backend) {
 	status = _cairo_surface_set_error (abstract_surface,
@@ -500,6 +505,14 @@ cairo_tee_surface_remove (cairo_surface_t *abstract_surface,
     int n, num_slaves;
     cairo_status_t status;
 
+    if (unlikely (abstract_surface->status))
+	return;
+    if (unlikely (abstract_surface->finished)) {
+	status = _cairo_surface_set_error (abstract_surface,
+					   _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
+	return;
+    }
+
     if (abstract_surface->backend != &cairo_tee_surface_backend) {
 	status = _cairo_surface_set_error (abstract_surface,
 					   _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
@@ -540,6 +553,8 @@ cairo_tee_surface_index (cairo_surface_t *abstract_surface,
 
     if (unlikely (abstract_surface->status))
 	return _cairo_surface_create_in_error (abstract_surface->status);
+    if (unlikely (abstract_surface->finished))
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
 
     if (abstract_surface->backend != &cairo_tee_surface_backend)
 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
commit a9f30fc1f0c3e50715468b09707477973bf5268b
Author: Benjamin Otte <otte at redhat.com>
Date:   Mon Jul 5 22:30:55 2010 +0200

    test: Add recording and tee surface functions to api-special-cases

diff --git a/test/api-special-cases.c b/test/api-special-cases.c
index ad8629b..a72f86a 100644
--- a/test/api-special-cases.c
+++ b/test/api-special-cases.c
@@ -336,6 +336,46 @@ test_cairo_surface_write_to_png_stream (cairo_surface_t *surface)
 
 #endif
 
+static cairo_test_status_t
+test_cairo_recording_surface_ink_extents (cairo_surface_t *surface)
+{
+    double x, y, w, h;
+
+    cairo_recording_surface_ink_extents (surface, &x, &y, &w, &h);
+    return x == 0 && y == 0 && w == 0 && h == 0 ? CAIRO_TEST_SUCCESS : CAIRO_TEST_ERROR;
+}
+
+static cairo_test_status_t
+test_cairo_tee_surface_add (cairo_surface_t *surface)
+{
+    cairo_surface_t *image = cairo_image_surface_create (CAIRO_FORMAT_A8, 10, 10);
+
+    cairo_tee_surface_add (surface, image);
+    cairo_surface_destroy (image);
+    return CAIRO_TEST_SUCCESS;
+}
+
+static cairo_test_status_t
+test_cairo_tee_surface_remove (cairo_surface_t *surface)
+{
+    cairo_surface_t *image = cairo_image_surface_create (CAIRO_FORMAT_A8, 10, 10);
+
+    cairo_tee_surface_remove (surface, image);
+    cairo_surface_destroy (image);
+    return CAIRO_TEST_SUCCESS;
+}
+
+static cairo_test_status_t
+test_cairo_tee_surface_index (cairo_surface_t *surface)
+{
+    cairo_surface_t *master;
+    cairo_status_t status;
+
+    master = cairo_tee_surface_index (surface, 0);
+    status = cairo_surface_status (master);
+    cairo_surface_destroy (master);
+    return status ? CAIRO_TEST_SUCCESS : CAIRO_TEST_ERROR;
+}
 
 
 #define TEST(name, surface_type, sets_status) { #name, test_ ## name, surface_type, sets_status }
@@ -378,6 +418,10 @@ struct {
     TEST (cairo_surface_write_to_png, -1, FALSE),
     TEST (cairo_surface_write_to_png_stream, -1, FALSE),
 #endif
+    TEST (cairo_recording_surface_ink_extents, CAIRO_SURFACE_TYPE_RECORDING, FALSE),
+    TEST (cairo_tee_surface_add, CAIRO_SURFACE_TYPE_TEE, TRUE),
+    TEST (cairo_tee_surface_remove, CAIRO_SURFACE_TYPE_TEE, TRUE),
+    TEST (cairo_tee_surface_index, CAIRO_SURFACE_TYPE_TEE, FALSE),
 };
 
 static cairo_test_status_t
commit 41abc0ca37855751ed06051a30c0d866977ed2bd
Author: Benjamin Otte <otte at redhat.com>
Date:   Mon Jul 5 22:19:05 2010 +0200

    test: add PNG functions

diff --git a/test/api-special-cases.c b/test/api-special-cases.c
index 954b703..ad8629b 100644
--- a/test/api-special-cases.c
+++ b/test/api-special-cases.c
@@ -304,6 +304,38 @@ test_cairo_image_surface_get_stride (cairo_surface_t *surface)
     return stride == 0 || surface_has_type (surface, CAIRO_SURFACE_TYPE_IMAGE) ? CAIRO_TEST_SUCCESS : CAIRO_TEST_ERROR;
 }
 
+#if CAIRO_HAS_PNG_FUNCTIONS
+
+static cairo_test_status_t
+test_cairo_surface_write_to_png (cairo_surface_t *surface)
+{
+    cairo_status_t status;
+
+    status = cairo_surface_write_to_png (surface, "/this/file/will/definitely/not/exist.png");
+    
+    return status ? CAIRO_TEST_SUCCESS : CAIRO_TEST_ERROR;
+}
+
+static cairo_status_t
+write_func_that_always_fails (void *closure, const unsigned char *data, unsigned int length)
+{
+    return CAIRO_STATUS_WRITE_ERROR;
+}
+
+static cairo_test_status_t
+test_cairo_surface_write_to_png_stream (cairo_surface_t *surface)
+{
+    cairo_status_t status;
+
+    status = cairo_surface_write_to_png_stream (surface,
+                                                write_func_that_always_fails,
+                                                NULL);
+    
+    return status && status != CAIRO_STATUS_WRITE_ERROR ? CAIRO_TEST_SUCCESS : CAIRO_TEST_ERROR;
+}
+
+#endif
+
 
 
 #define TEST(name, surface_type, sets_status) { #name, test_ ## name, surface_type, sets_status }
@@ -342,6 +374,10 @@ struct {
     TEST (cairo_image_surface_get_width, CAIRO_SURFACE_TYPE_IMAGE, FALSE),
     TEST (cairo_image_surface_get_height, CAIRO_SURFACE_TYPE_IMAGE, FALSE),
     TEST (cairo_image_surface_get_stride, CAIRO_SURFACE_TYPE_IMAGE, FALSE),
+#if CAIRO_HAS_PNG_FUNCTIONS
+    TEST (cairo_surface_write_to_png, -1, FALSE),
+    TEST (cairo_surface_write_to_png_stream, -1, FALSE),
+#endif
 };
 
 static cairo_test_status_t
commit 897eaa3e97f865ad2c28442c26efaf4ba391cf03
Author: Benjamin Otte <otte at redhat.com>
Date:   Mon Jul 5 22:11:23 2010 +0200

    test: Add a non-error surface check
    
    In that check, we call functions that require a specific surface type
    with surfaces of a different type and check that they don't crash and
    set the correct error.

diff --git a/test/api-special-cases.c b/test/api-special-cases.c
index 6fdaddb..954b703 100644
--- a/test/api-special-cases.c
+++ b/test/api-special-cases.c
@@ -422,6 +422,42 @@ draw (cairo_t *cr, int width, int height)
         }
     }
 
+    /* Test a normal surface for functions that have the wrong type */
+    for (i = 0; i < ARRAY_LENGTH (tests); i++) {
+        cairo_status_t desired_status;
+
+        if (tests[i].surface_type == -1)
+            continue;
+        similar = cairo_surface_create_similar (target,
+                                                cairo_surface_get_content (target),
+                                                10, 10);
+        if (cairo_surface_get_type (similar) == (cairo_surface_type_t) tests[i].surface_type) {
+            cairo_surface_destroy (similar);
+            continue;
+        }
+
+        test_status = tests[i].func (similar);
+        status = cairo_surface_status (similar);
+        cairo_surface_destroy (similar);
+
+        if (test_status != CAIRO_TEST_SUCCESS) {
+            cairo_test_log (ctx,
+                            "Failed test %s with %d\n",
+                            tests[i].name, (int) test_status);
+            return test_status;
+        }
+
+        desired_status = tests[i].modifies_surface ? CAIRO_STATUS_SURFACE_TYPE_MISMATCH : CAIRO_STATUS_SUCCESS;
+        if (status != desired_status) {
+            cairo_test_log (ctx,
+                            "Failed test %s: Surface status should be %u (%s), but is %u (%s)\n",
+                            tests[i].name,
+                            desired_status, cairo_status_to_string (desired_status),
+                            status, cairo_status_to_string (status));
+            return CAIRO_TEST_ERROR;
+        }
+    }
+
     /* 565-compatible gray background */
     cairo_set_source_rgb (cr, 0.51613, 0.55555, 0.51613);
     cairo_paint (cr);
commit 986ddf565215dc01065eade46921abe8a4b7912e
Author: Benjamin Otte <otte at redhat.com>
Date:   Mon Jul 5 22:03:42 2010 +0200

    test: add image surface functions to api-special-cases test

diff --git a/test/api-special-cases.c b/test/api-special-cases.c
index d1eaff8..6fdaddb 100644
--- a/test/api-special-cases.c
+++ b/test/api-special-cases.c
@@ -52,6 +52,7 @@
 #endif
 
 #define ARRAY_LENGTH(array) (sizeof (array) / sizeof ((array)[0]))
+#define surface_has_type(surface,type) (cairo_surface_get_type (surface) == (type))
 
 typedef cairo_test_status_t (* surface_test_func_t) (cairo_surface_t *surface);
 
@@ -268,38 +269,79 @@ test_cairo_surface_has_show_text_glyphs (cairo_surface_t *surface)
     return CAIRO_TEST_SUCCESS;
 }
 
+static cairo_test_status_t
+test_cairo_image_surface_get_data (cairo_surface_t *surface)
+{
+    unsigned char *data = cairo_image_surface_get_data (surface);
+    return data == NULL || surface_has_type (surface, CAIRO_SURFACE_TYPE_IMAGE) ? CAIRO_TEST_SUCCESS : CAIRO_TEST_ERROR;
+}
+
+static cairo_test_status_t
+test_cairo_image_surface_get_format (cairo_surface_t *surface)
+{
+    cairo_format_t format = cairo_image_surface_get_format (surface);
+    return format == CAIRO_FORMAT_INVALID || surface_has_type (surface, CAIRO_SURFACE_TYPE_IMAGE) ? CAIRO_TEST_SUCCESS : CAIRO_TEST_ERROR;
+}
+
+static cairo_test_status_t
+test_cairo_image_surface_get_width (cairo_surface_t *surface)
+{
+    unsigned int width = cairo_image_surface_get_width (surface);
+    return width == 0 || surface_has_type (surface, CAIRO_SURFACE_TYPE_IMAGE) ? CAIRO_TEST_SUCCESS : CAIRO_TEST_ERROR;
+}
+
+static cairo_test_status_t
+test_cairo_image_surface_get_height (cairo_surface_t *surface)
+{
+    unsigned int height = cairo_image_surface_get_height (surface);
+    return height == 0 || surface_has_type (surface, CAIRO_SURFACE_TYPE_IMAGE) ? CAIRO_TEST_SUCCESS : CAIRO_TEST_ERROR;
+}
+
+static cairo_test_status_t
+test_cairo_image_surface_get_stride (cairo_surface_t *surface)
+{
+    unsigned int stride = cairo_image_surface_get_stride (surface);
+    return stride == 0 || surface_has_type (surface, CAIRO_SURFACE_TYPE_IMAGE) ? CAIRO_TEST_SUCCESS : CAIRO_TEST_ERROR;
+}
+
 
 
-#define TEST(name, sets_status) { #name, test_ ## name, sets_status }
+#define TEST(name, surface_type, sets_status) { #name, test_ ## name, surface_type, sets_status }
 
 struct {
     const char *name;
     surface_test_func_t func;
+    int surface_type; /* cairo_surface_type_t or -1 */
     cairo_bool_t modifies_surface;
 } tests[] = {
-    TEST (cairo_surface_create_similar, FALSE),
-    TEST (cairo_surface_create_for_rectangle, FALSE),
-    TEST (cairo_surface_reference, FALSE),
-    TEST (cairo_surface_finish, TRUE),
-    TEST (cairo_surface_get_device, FALSE),
-    TEST (cairo_surface_get_reference_count, FALSE),
-    TEST (cairo_surface_status, FALSE),
-    TEST (cairo_surface_get_type, FALSE),
-    TEST (cairo_surface_get_content, FALSE),
-    TEST (cairo_surface_set_user_data, FALSE),
-    TEST (cairo_surface_set_mime_data, TRUE),
-    TEST (cairo_surface_get_mime_data, FALSE),
-    TEST (cairo_surface_get_font_options, FALSE),
-    TEST (cairo_surface_flush, TRUE),
-    TEST (cairo_surface_mark_dirty, TRUE),
-    TEST (cairo_surface_mark_dirty_rectangle, TRUE),
-    TEST (cairo_surface_set_device_offset, TRUE),
-    TEST (cairo_surface_get_device_offset, FALSE),
-    TEST (cairo_surface_set_fallback_resolution, TRUE),
-    TEST (cairo_surface_get_fallback_resolution, FALSE),
-    TEST (cairo_surface_copy_page, TRUE),
-    TEST (cairo_surface_show_page, TRUE),
-    TEST (cairo_surface_has_show_text_glyphs, FALSE)
+    TEST (cairo_surface_create_similar, -1, FALSE),
+    TEST (cairo_surface_create_for_rectangle, -1, FALSE),
+    TEST (cairo_surface_reference, -1, FALSE),
+    TEST (cairo_surface_finish, -1, TRUE),
+    TEST (cairo_surface_get_device, -1, FALSE),
+    TEST (cairo_surface_get_reference_count, -1, FALSE),
+    TEST (cairo_surface_status, -1, FALSE),
+    TEST (cairo_surface_get_type, -1, FALSE),
+    TEST (cairo_surface_get_content, -1, FALSE),
+    TEST (cairo_surface_set_user_data, -1, FALSE),
+    TEST (cairo_surface_set_mime_data, -1, TRUE),
+    TEST (cairo_surface_get_mime_data, -1, FALSE),
+    TEST (cairo_surface_get_font_options, -1, FALSE),
+    TEST (cairo_surface_flush, -1, TRUE),
+    TEST (cairo_surface_mark_dirty, -1, TRUE),
+    TEST (cairo_surface_mark_dirty_rectangle, -1, TRUE),
+    TEST (cairo_surface_set_device_offset, -1, TRUE),
+    TEST (cairo_surface_get_device_offset, -1, FALSE),
+    TEST (cairo_surface_set_fallback_resolution, -1, TRUE),
+    TEST (cairo_surface_get_fallback_resolution, -1, FALSE),
+    TEST (cairo_surface_copy_page, -1, TRUE),
+    TEST (cairo_surface_show_page, -1, TRUE),
+    TEST (cairo_surface_has_show_text_glyphs, -1, FALSE),
+    TEST (cairo_image_surface_get_data, CAIRO_SURFACE_TYPE_IMAGE, FALSE),
+    TEST (cairo_image_surface_get_format, CAIRO_SURFACE_TYPE_IMAGE, FALSE),
+    TEST (cairo_image_surface_get_width, CAIRO_SURFACE_TYPE_IMAGE, FALSE),
+    TEST (cairo_image_surface_get_height, CAIRO_SURFACE_TYPE_IMAGE, FALSE),
+    TEST (cairo_image_surface_get_stride, CAIRO_SURFACE_TYPE_IMAGE, FALSE),
 };
 
 static cairo_test_status_t
commit 72878d70ea75be03f47fa9d53f8305e76162054e
Author: Benjamin Otte <otte at redhat.com>
Date:   Mon Jul 5 20:47:19 2010 +0200

    test: Add a new test variant to api-special-cases test
    
    This variant tests a (hopefully) inert error surface.

diff --git a/test/api-special-cases.c b/test/api-special-cases.c
index ebac5c5..d1eaff8 100644
--- a/test/api-special-cases.c
+++ b/test/api-special-cases.c
@@ -27,6 +27,7 @@
 #include "config.h"
 #endif
 
+#include <assert.h>
 #include <limits.h>
 
 #include "cairo-test.h"
@@ -304,6 +305,39 @@ struct {
 static cairo_test_status_t
 preamble (cairo_test_context_t *ctx)
 {
+    cairo_surface_t *surface;
+    cairo_test_status_t test_status;
+    cairo_status_t status_before, status_after;
+    unsigned int i;
+
+    /* Test an error surface */
+    for (i = 0; i < ARRAY_LENGTH (tests); i++) {
+        surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, INT_MAX, INT_MAX);
+        status_before = cairo_surface_status (surface);
+        assert (status_before);
+
+        test_status = tests[i].func (surface);
+
+        status_after = cairo_surface_status (surface);
+        cairo_surface_destroy (surface);
+
+        if (test_status != CAIRO_TEST_SUCCESS) {
+            cairo_test_log (ctx,
+                            "Failed test %s with %d\n",
+                            tests[i].name, (int) test_status);
+            return test_status;
+        }
+
+        if (status_before != status_after) {
+            cairo_test_log (ctx,
+                            "Failed test %s: Modified surface status from %u (%s) to %u (%s)\n",
+                            tests[i].name,
+                            status_before, cairo_status_to_string (status_before),
+                            status_after, cairo_status_to_string (status_after));
+            return CAIRO_TEST_ERROR;
+        }
+    }
+
     return CAIRO_TEST_SUCCESS;
 }
 
@@ -318,6 +352,7 @@ draw (cairo_t *cr, int width, int height)
 
     target = cairo_get_target (cr);
 
+    /* Test a finished similar surface */
     for (i = 0; i < ARRAY_LENGTH (tests); i++) {
         similar = cairo_surface_create_similar (target,
                                                 cairo_surface_get_content (target),


More information about the cairo-commit mailing list