[cairo-commit] 6 commits - src/cairo-array.c src/cairo-base85-stream.c src/cairo.c src/cairo-deflate-stream.c src/cairo-glitz-surface.c src/cairo-image-surface.c src/cairoint.h src/cairo-meta-surface.c src/cairo-os2-surface.c src/cairo-output-stream.c src/cairo-output-stream-private.h src/cairo-paginated-surface.c src/cairo-pdf-surface.c src/cairo-png.c src/cairo-ps-surface.c src/cairo-quartz-surface.c src/cairo-surface.c src/cairo-surface-fallback.c src/cairo-svg-surface.c src/cairo-type1-fallback.c src/cairo-type1-subset.c src/cairo-win32-printing-surface.c src/cairo-win32-surface.c src/cairo-xcb-surface.c src/cairo-xlib-surface.c src/Makefile.am src/test-fallback-surface.c src/test-meta-surface.c src/test-paginated-surface.c

Chris Wilson ickle at kemper.freedesktop.org
Wed Jan 16 09:06:55 PST 2008


 src/Makefile.am                    |    2 
 src/cairo-array.c                  |    3 
 src/cairo-base85-stream.c          |    3 
 src/cairo-deflate-stream.c         |    7 
 src/cairo-glitz-surface.c          |   20 --
 src/cairo-image-surface.c          |  136 +----------------
 src/cairo-meta-surface.c           |   12 -
 src/cairo-os2-surface.c            |   22 +-
 src/cairo-output-stream-private.h  |    3 
 src/cairo-output-stream.c          |   26 +++
 src/cairo-paginated-surface.c      |    8 -
 src/cairo-pdf-surface.c            |  296 ++++++++++++++++++-------------------
 src/cairo-png.c                    |   38 ++--
 src/cairo-ps-surface.c             |   49 +++---
 src/cairo-quartz-surface.c         |   32 +---
 src/cairo-surface-fallback.c       |    6 
 src/cairo-surface.c                |   62 +++++--
 src/cairo-svg-surface.c            |  136 ++++++++---------
 src/cairo-type1-fallback.c         |    8 -
 src/cairo-type1-subset.c           |    5 
 src/cairo-win32-printing-surface.c |   10 -
 src/cairo-win32-surface.c          |   37 +---
 src/cairo-xcb-surface.c            |   18 --
 src/cairo-xlib-surface.c           |   26 +--
 src/cairo.c                        |    4 
 src/cairoint.h                     |    6 
 src/test-fallback-surface.c        |    5 
 src/test-meta-surface.c            |   18 +-
 src/test-paginated-surface.c       |    5 
 29 files changed, 452 insertions(+), 551 deletions(-)

New commits:
commit 1bccbd88c38c4438e94cf8936228c75e47be0af4
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Jan 16 16:33:22 2008 +0000

    [cairo-pdf-surface] Review error propagation from output stream.
    
    Ensure that errors encountered whilst processing the output stream are
    propagated back to the surface (and the user).

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 9ad9e1a..238f4f9 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -164,7 +164,7 @@ _cairo_pdf_surface_add_font (unsigned int        font_id,
 static void
 _cairo_pdf_group_resources_init (cairo_pdf_group_resources_t *res);
 
-static cairo_pdf_resource_t
+static cairo_status_t
 _cairo_pdf_surface_open_stream (cairo_pdf_surface_t	*surface,
 				cairo_pdf_resource_t    *resource,
                                 cairo_bool_t             compressed,
@@ -234,7 +234,7 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t	*output,
 					       double			 height)
 {
     cairo_pdf_surface_t *surface;
-    cairo_status_t status;
+    cairo_status_t status, status_ignored;
 
     surface = malloc (sizeof (cairo_pdf_surface_t));
     if (surface == NULL) {
@@ -264,14 +264,16 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t	*output,
 
     surface->font_subsets = _cairo_scaled_font_subsets_create_composite ();
     if (! surface->font_subsets) {
-	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	goto BAIL0;
     }
 
     surface->next_available_resource.id = 1;
     surface->pages_resource = _cairo_pdf_surface_new_object (surface);
-    if (surface->pages_resource.id == 0)
+    if (surface->pages_resource.id == 0) {
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
         goto BAIL1;
+    }
 
     surface->compress_content = TRUE;
     surface->pdf_stream.active = FALSE;
@@ -303,7 +305,8 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t	*output,
 					  CAIRO_CONTENT_COLOR_ALPHA,
 					  width, height,
 					  &cairo_pdf_surface_paginated_backend);
-    if (surface->paginated_surface->status == CAIRO_STATUS_SUCCESS)
+    status = surface->paginated_surface->status;
+    if (status == CAIRO_STATUS_SUCCESS)
 	return surface->paginated_surface;
 
 BAIL1:
@@ -313,9 +316,9 @@ BAIL0:
     free (surface);
 
     /* destroy stream on behalf of caller */
-    status = _cairo_output_stream_destroy (output);
+    status_ignored = _cairo_output_stream_destroy (output);
 
-    return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
+    return _cairo_surface_create_in_error (status);
 }
 
 /**
@@ -344,13 +347,11 @@ cairo_pdf_surface_create_for_stream (cairo_write_func_t		 write_func,
 				     double			 width_in_points,
 				     double			 height_in_points)
 {
-    cairo_status_t status;
     cairo_output_stream_t *output;
 
     output = _cairo_output_stream_create (write_func, NULL, closure);
-    status = _cairo_output_stream_get_status (output);
-    if (status)
-	return _cairo_surface_create_in_error (status);
+    if (_cairo_output_stream_get_status (output))
+	return _cairo_surface_create_in_error (_cairo_output_stream_destroy (output));
 
     return _cairo_pdf_surface_create_for_stream_internal (output,
 							  width_in_points,
@@ -381,13 +382,11 @@ cairo_pdf_surface_create (const char		*filename,
 			  double		 width_in_points,
 			  double		 height_in_points)
 {
-    cairo_status_t status;
     cairo_output_stream_t *output;
 
     output = _cairo_output_stream_create_for_filename (filename);
-    status = _cairo_output_stream_get_status (output);
-    if (status)
-	return _cairo_surface_create_in_error (status);
+    if (_cairo_output_stream_get_status (output))
+	return _cairo_surface_create_in_error (_cairo_output_stream_destroy (output));
 
     return _cairo_pdf_surface_create_for_stream_internal (output,
 							  width_in_points,
@@ -813,7 +812,7 @@ _cairo_pdf_surface_add_pdf_pattern (cairo_pdf_surface_t		*surface,
     return CAIRO_STATUS_SUCCESS;
 }
 
-static cairo_pdf_resource_t
+static cairo_status_t
 _cairo_pdf_surface_open_stream (cairo_pdf_surface_t	*surface,
 				cairo_pdf_resource_t    *resource,
 				cairo_bool_t             compressed,
@@ -830,19 +829,17 @@ _cairo_pdf_surface_open_stream (cairo_pdf_surface_t	*surface,
     } else {
 	self = _cairo_pdf_surface_new_object (surface);
 	if (self.id == 0)
-	    return self;
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     }
 
     length = _cairo_pdf_surface_new_object (surface);
     if (length.id == 0)
-	return length;
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     if (compressed) {
 	output = _cairo_deflate_stream_create (surface->output);
-	if (_cairo_output_stream_get_status (output)) {
-	    self.id = 0;
-	    return self;
-	}
+	if (_cairo_output_stream_get_status (output))
+	    return _cairo_output_stream_destroy (output);
     }
 
     surface->pdf_stream.active = TRUE;
@@ -878,7 +875,7 @@ _cairo_pdf_surface_open_stream (cairo_pdf_surface_t	*surface,
 	_cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
     }
 
-    return surface->pdf_stream.self;
+    return _cairo_output_stream_get_status (surface->output);
 }
 
 static cairo_status_t
@@ -916,6 +913,9 @@ _cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface)
 
     surface->pdf_stream.active = FALSE;
 
+    if (status == CAIRO_STATUS_SUCCESS)
+	status = _cairo_output_stream_get_status (surface->output);
+
     return status;
 }
 
@@ -1046,7 +1046,7 @@ _cairo_pdf_surface_close_group (cairo_pdf_surface_t *surface,
     if (group)
 	*group = surface->group_stream.resource;
 
-    status2 =  _cairo_output_stream_destroy (surface->group_stream.mem_stream);
+    status2 = _cairo_output_stream_destroy (surface->group_stream.mem_stream);
     if (status == CAIRO_STATUS_SUCCESS)
 	status = status2;
 
@@ -1058,9 +1058,10 @@ _cairo_pdf_surface_close_group (cairo_pdf_surface_t *surface,
 
 static cairo_status_t
 _cairo_pdf_surface_open_content_stream (cairo_pdf_surface_t  *surface,
-					cairo_pdf_resource_t *resource,
 					cairo_bool_t          is_form)
 {
+    cairo_status_t status;
+
     assert (surface->pdf_stream.active == FALSE);
     assert (surface->group_stream.active == FALSE);
 
@@ -1069,7 +1070,7 @@ _cairo_pdf_surface_open_content_stream (cairo_pdf_surface_t  *surface,
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     if (is_form) {
-	*resource =
+	status =
 	    _cairo_pdf_surface_open_stream (surface,
 					    NULL,
 					    surface->compress_content,
@@ -1085,21 +1086,23 @@ _cairo_pdf_surface_open_content_stream (cairo_pdf_surface_t  *surface,
 					    surface->width,
 					    surface->height,
 					    surface->content_resources.id);
-	if (resource->id == 0)
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	if (status)
+	    return status;
     } else {
-	surface->content =
+	status =
 	    _cairo_pdf_surface_open_stream (surface,
 					    NULL,
 					    surface->compress_content,
 					    NULL);
-	if (surface->content.id == 0)
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	if (status)
+	    return status;
     }
 
+    surface->content = surface->pdf_stream.self;
+
     _cairo_output_stream_printf (surface->output, "q\r\n");
 
-    return CAIRO_STATUS_SUCCESS;
+    return _cairo_output_stream_get_status (surface->output);
 }
 
 static cairo_status_t
@@ -1123,7 +1126,7 @@ _cairo_pdf_surface_close_content_stream (cairo_pdf_surface_t *surface)
     _cairo_output_stream_printf (surface->output,
 				 "endobj\r\n");
 
-    return CAIRO_STATUS_SUCCESS;
+    return _cairo_output_stream_get_status (surface->output);
 }
 
 static cairo_surface_t *
@@ -1230,7 +1233,7 @@ _cairo_pdf_surface_start_page (void *abstract_surface)
 
     surface->has_fallback_images = FALSE;
     _cairo_pdf_group_resources_clear (&surface->resources);
-    status = _cairo_pdf_surface_open_content_stream (surface, &surface->content, TRUE);
+    status = _cairo_pdf_surface_open_content_stream (surface, TRUE);
     if (status)
 	return status;
 
@@ -1281,11 +1284,13 @@ _cairo_pdf_surface_emit_smask (cairo_pdf_surface_t	*surface,
     uint8_t a;
     int src_bit, dst_bit;
 
-    /* This is the only image format we support, which simplfies things. */
+    /* This is the only image format we support, which simplifies things. */
     assert (image->format == CAIRO_FORMAT_ARGB32 ||
 	    image->format == CAIRO_FORMAT_A8 ||
 	    image->format == CAIRO_FORMAT_A1 );
 
+    stream_ret->id = 0;
+
     if (image->format == CAIRO_FORMAT_A1)
 	alpha_size = (image->height * image->width + 7)/8;
     else
@@ -1342,10 +1347,8 @@ _cairo_pdf_surface_emit_smask (cairo_pdf_surface_t	*surface,
     }
 
     /* Bail out without emitting smask if it's all opaque. */
-    if (opaque) {
-	stream_ret->id = 0;
+    if (opaque)
 	goto CLEANUP_ALPHA;
-    }
 
     alpha_compressed = compress_dup (alpha, alpha_size, &alpha_compressed_size);
     if (alpha_compressed == NULL) {
@@ -1353,22 +1356,22 @@ _cairo_pdf_surface_emit_smask (cairo_pdf_surface_t	*surface,
 	goto CLEANUP_ALPHA;
     }
 
-    *stream_ret = _cairo_pdf_surface_open_stream (surface,
-						  NULL,
-                                                  FALSE,
-						  "   /Type /XObject\r\n"
-						  "   /Subtype /Image\r\n"
-						  "   /Width %d\r\n"
-						  "   /Height %d\r\n"
-						  "   /ColorSpace /DeviceGray\r\n"
-						  "   /BitsPerComponent %d\r\n"
-						  "   /Filter /FlateDecode\r\n",
-						  image->width, image->height,
-						  image->format == CAIRO_FORMAT_A1 ? 1 : 8);
-    if (stream_ret->id == 0) {
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    status = _cairo_pdf_surface_open_stream (surface,
+					     NULL,
+					     FALSE,
+					     "   /Type /XObject\r\n"
+					     "   /Subtype /Image\r\n"
+					     "   /Width %d\r\n"
+					     "   /Height %d\r\n"
+					     "   /ColorSpace /DeviceGray\r\n"
+					     "   /BitsPerComponent %d\r\n"
+					     "   /Filter /FlateDecode\r\n",
+					     image->width, image->height,
+					     image->format == CAIRO_FORMAT_A1 ? 1 : 8);
+    if (status)
 	goto CLEANUP_ALPHA_COMPRESSED;
-    }
+
+    *stream_ret = surface->pdf_stream.self;
 
     _cairo_output_stream_write (surface->output, alpha_compressed, alpha_compressed_size);
     _cairo_output_stream_printf (surface->output, "\r\n");
@@ -1480,26 +1483,26 @@ _cairo_pdf_surface_emit_image (cairo_pdf_surface_t   *surface,
 				"   /Filter /FlateDecode\r\n"
 
     if (need_smask)
-	*image_ret = _cairo_pdf_surface_open_stream (surface,
-						     NULL,
-                                                     FALSE,
-						     IMAGE_DICTIONARY
-						     "   /SMask %d 0 R\r\n",
-						     image->width, image->height,
-						     smask.id);
+	status = _cairo_pdf_surface_open_stream (surface,
+						 NULL,
+						 FALSE,
+						 IMAGE_DICTIONARY
+						 "   /SMask %d 0 R\r\n",
+						 image->width, image->height,
+						 smask.id);
     else
-	*image_ret = _cairo_pdf_surface_open_stream (surface,
-						     NULL,
-                                                     FALSE,
-						     IMAGE_DICTIONARY,
-						     image->width, image->height);
-    if (image_ret->id == 0){
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	status = _cairo_pdf_surface_open_stream (surface,
+						 NULL,
+						 FALSE,
+						 IMAGE_DICTIONARY,
+						 image->width, image->height);
+    if (status)
 	goto CLEANUP_COMPRESSED;
-    }
 
 #undef IMAGE_DICTIONARY
 
+    *image_ret = surface->pdf_stream.self;
+
     _cairo_output_stream_write (surface->output, compressed, compressed_size);
     _cairo_output_stream_printf (surface->output, "\r\n");
     status = _cairo_pdf_surface_close_stream (surface);
@@ -1523,10 +1526,10 @@ _cairo_pdf_surface_emit_image_surface (cairo_pdf_surface_t     *surface,
     cairo_surface_attributes_t pat_attr;
     cairo_image_surface_t *image;
     void *image_extra;
-    cairo_status_t status = CAIRO_STATUS_SUCCESS;
+    cairo_status_t status;
 
-    status = _cairo_pattern_acquire_surface ((cairo_pattern_t *)pattern,
-					     (cairo_surface_t *)surface,
+    status = _cairo_pattern_acquire_surface (&pattern->base,
+					     &surface->base,
 					     0, 0, -1, -1,
 					     &pat_surface, &pat_attr);
     if (status)
@@ -1546,7 +1549,7 @@ _cairo_pdf_surface_emit_image_surface (cairo_pdf_surface_t     *surface,
 BAIL:
     _cairo_surface_release_source_image (pat_surface, image, image_extra);
 BAIL2:
-    _cairo_pattern_release_surface ((cairo_pattern_t *)pattern, pat_surface, &pat_attr);
+    _cairo_pattern_release_surface (&pattern->base, pat_surface, &pat_attr);
 
     return status;
 }
@@ -1583,7 +1586,7 @@ _cairo_pdf_surface_emit_meta_surface (cairo_pdf_surface_t  *surface,
 						  surface->cairo_to_pdf);
 
     _cairo_pdf_group_resources_clear (&surface->resources);
-    status = _cairo_pdf_surface_open_content_stream (surface, &surface->content, TRUE);
+    status = _cairo_pdf_surface_open_content_stream (surface, TRUE);
     if (status)
 	return status;
 
@@ -1624,7 +1627,7 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t	*surface,
 					 cairo_pdf_pattern_t	*pdf_pattern)
 {
     cairo_surface_pattern_t *pattern = (cairo_surface_pattern_t *) pdf_pattern->pattern;
-    cairo_status_t status = CAIRO_STATUS_SUCCESS;
+    cairo_status_t status;
     cairo_pdf_resource_t pattern_resource = {0}; /* squelch bogus compiler warning */
     cairo_matrix_t cairo_p2d, pdf_p2d;
     cairo_extend_t extend = cairo_pattern_get_extend (&pattern->base);
@@ -1755,27 +1758,26 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t	*surface,
     cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
 
     _cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res);
-    if (_cairo_pdf_surface_open_stream (surface,
-				        &pdf_pattern->pattern_res,
-					FALSE,
-					"   /PatternType 1\r\n"
-					"   /BBox [0 0 %d %d]\r\n"
-					"   /XStep %f\r\n"
-					"   /YStep %f\r\n"
-					"   /TilingType 1\r\n"
-					"   /PaintType 1\r\n"
-					"   /Matrix [ %f %f %f %f %f %f ]\r\n"
-					"   /Resources << /XObject << /x%d %d 0 R >> >>\r\n",
-					bbox_x, bbox_y,
-					xstep, ystep,
-					pdf_p2d.xx, pdf_p2d.yx,
-					pdf_p2d.xy, pdf_p2d.yy,
-					pdf_p2d.x0, pdf_p2d.y0,
-					pattern_resource.id,
-					pattern_resource.id).id == 0)
-    {
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-    }
+    status = _cairo_pdf_surface_open_stream (surface,
+				             &pdf_pattern->pattern_res,
+					     FALSE,
+					     "   /PatternType 1\r\n"
+					     "   /BBox [0 0 %d %d]\r\n"
+					     "   /XStep %f\r\n"
+					     "   /YStep %f\r\n"
+					     "   /TilingType 1\r\n"
+					     "   /PaintType 1\r\n"
+					     "   /Matrix [ %f %f %f %f %f %f ]\r\n"
+					     "   /Resources << /XObject << /x%d %d 0 R >> >>\r\n",
+					     bbox_x, bbox_y,
+					     xstep, ystep,
+					     pdf_p2d.xx, pdf_p2d.yx,
+					     pdf_p2d.xy, pdf_p2d.yy,
+					     pdf_p2d.x0, pdf_p2d.y0,
+					     pattern_resource.id,
+					     pattern_resource.id);
+    if (status)
+	return status;
 
     if (_cairo_surface_is_meta (pattern->surface)) {
 	if (extend == CAIRO_EXTEND_REFLECT) {
@@ -1808,7 +1810,7 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t	*surface,
     if (status)
 	return status;
 
-    return CAIRO_STATUS_SUCCESS;
+    return _cairo_output_stream_get_status (surface->output);
 }
 
 typedef struct _cairo_pdf_color_stop {
@@ -1992,7 +1994,7 @@ _cairo_pdf_surface_emit_stitched_colorgradient (cairo_pdf_surface_t    *surface,
 
     *function = res;
 
-    return CAIRO_STATUS_SUCCESS;
+    return _cairo_output_stream_get_status (surface->output);
 }
 
 
@@ -2085,7 +2087,7 @@ _cairo_pdf_surface_emit_pattern_stops (cairo_pdf_surface_t      *surface,
                 goto BAIL;
         }
     } else {
-        /* multiple stops: stitch. XXX possible optimization: regulary spaced
+        /* multiple stops: stitch. XXX possible optimization: regularly spaced
          * stops do not require stitching. XXX */
         status = _cairo_pdf_surface_emit_stitched_colorgradient (surface,
                                                                  n_stops,
@@ -2169,7 +2171,7 @@ _cairo_pdf_surface_emit_repeating_function (cairo_pdf_surface_t      *surface,
 
     *function = res;
 
-    return CAIRO_STATUS_SUCCESS;
+    return _cairo_output_stream_get_status (surface->output);
 }
 
 static cairo_status_t
@@ -2177,34 +2179,34 @@ cairo_pdf_surface_emit_transparency_group (cairo_pdf_surface_t  *surface,
 					   cairo_pdf_resource_t  gstate_resource,
 					   cairo_pdf_resource_t  gradient_mask)
 {
-    cairo_pdf_resource_t xobj_resource, smask_resource;
+    cairo_pdf_resource_t smask_resource;
     cairo_status_t status;
 
-    xobj_resource = _cairo_pdf_surface_open_stream (surface,
-						    NULL,
-                                                    surface->compress_content,
-                                                    "   /Type /XObject\r\n"
-                                                    "   /Subtype /Form\r\n"
-                                                    "   /FormType 1\r\n"
-                                                    "   /BBox [ 0 0 %f %f ]\r\n"
-                                                    "   /Resources\r\n"
-                                                    "      << /ExtGState\r\n"
-                                                    "            << /a0 << /ca 1 /CA 1 >>"
-                                                    "      >>\r\n"
-                                                    "         /Pattern\r\n"
-                                                    "            << /p%d %d 0 R >>\r\n"
-                                                    "      >>\r\n"
-                                                    "   /Group\r\n"
-                                                    "      << /Type /Group\r\n"
-                                                    "         /S /Transparency\r\n"
-                                                    "         /CS /DeviceGray\r\n"
-                                                    "      >>\r\n",
-                                                    surface->width,
-                                                    surface->height,
-                                                    gradient_mask.id,
-                                                    gradient_mask.id);
-    if (xobj_resource.id == 0)
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    status = _cairo_pdf_surface_open_stream (surface,
+					     NULL,
+					     surface->compress_content,
+					     "   /Type /XObject\r\n"
+					     "   /Subtype /Form\r\n"
+					     "   /FormType 1\r\n"
+					     "   /BBox [ 0 0 %f %f ]\r\n"
+					     "   /Resources\r\n"
+					     "      << /ExtGState\r\n"
+					     "            << /a0 << /ca 1 /CA 1 >>"
+					     "      >>\r\n"
+					     "         /Pattern\r\n"
+					     "            << /p%d %d 0 R >>\r\n"
+					     "      >>\r\n"
+					     "   /Group\r\n"
+					     "      << /Type /Group\r\n"
+					     "         /S /Transparency\r\n"
+					     "         /CS /DeviceGray\r\n"
+					     "      >>\r\n",
+					     surface->width,
+					     surface->height,
+					     gradient_mask.id,
+					     gradient_mask.id);
+    if (status)
+	return status;
 
     _cairo_output_stream_printf (surface->output,
                                  "q\r\n"
@@ -2233,7 +2235,7 @@ cairo_pdf_surface_emit_transparency_group (cairo_pdf_surface_t  *surface,
                                  ">>\r\n"
                                  "endobj\r\n",
                                  smask_resource.id,
-                                 xobj_resource.id);
+                                 surface->pdf_stream.self.id);
 
     /* Create GState which uses the transparency group as an SMask. */
     _cairo_pdf_surface_update_object (surface, gstate_resource);
@@ -2250,7 +2252,7 @@ cairo_pdf_surface_emit_transparency_group (cairo_pdf_surface_t  *surface,
                                  gstate_resource.id,
                                  smask_resource.id);
 
-    return CAIRO_STATUS_SUCCESS;
+    return _cairo_output_stream_get_status (surface->output);
 }
 
 static cairo_status_t
@@ -2450,7 +2452,7 @@ _cairo_pdf_surface_emit_linear_pattern (cairo_pdf_surface_t    *surface,
 	    return status;
     }
 
-    return CAIRO_STATUS_SUCCESS;
+    return _cairo_output_stream_get_status (surface->output);
 }
 
 static cairo_status_t
@@ -2567,7 +2569,7 @@ _cairo_pdf_surface_emit_radial_pattern (cairo_pdf_surface_t    *surface,
 	    return status;
     }
 
-    return CAIRO_STATUS_SUCCESS;
+    return _cairo_output_stream_get_status (surface->output);
 }
 
 static cairo_status_t
@@ -2683,7 +2685,7 @@ _cairo_pdf_surface_get_extents (void		        *abstract_surface,
     rectangle->y = 0;
 
     /* XXX: The conversion to integers here is pretty bogus, (not to
-     * mention the aribitray limitation of width to a short(!). We
+     * mention the arbitrary limitation of width to a short(!). We
      * may need to come up with a better interface for get_size.
      */
     rectangle->width  = (int) ceil (surface->width);
@@ -2765,7 +2767,7 @@ _cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface)
     _cairo_output_stream_printf (surface->output, "   /Count %d\r\n", num_pages);
 
 
-    /* TODO: Figure out wich other defaults to be inherited by /Page
+    /* TODO: Figure out which other defaults to be inherited by /Page
      * objects. */
     _cairo_output_stream_printf (surface->output,
 				 ">>\r\n"
@@ -2801,12 +2803,12 @@ _cairo_pdf_surface_emit_to_unicode_stream (cairo_pdf_surface_t		*surface,
 	    return status;
     }
 
-    *stream = _cairo_pdf_surface_open_stream (surface,
+    status = _cairo_pdf_surface_open_stream (surface,
 					      NULL,
 					      surface->compress_content,
 					      NULL);
-    if (stream->id == 0)
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    if (status)
+	return status;
 
     _cairo_output_stream_printf (surface->output,
                                  "/CIDInit /ProcSet findresource begin\r\n"
@@ -2863,6 +2865,7 @@ _cairo_pdf_surface_emit_to_unicode_stream (cairo_pdf_surface_t		*surface,
                                  "end\r\n"
                                  "end\r\n");
 
+    *stream = surface->pdf_stream.self;
     return _cairo_pdf_surface_close_stream (surface);
 }
 
@@ -3407,16 +3410,18 @@ _cairo_pdf_surface_emit_bitmap_glyph (cairo_pdf_surface_t	*surface,
 	    return status;
     }
 
-    *glyph_ret = _cairo_pdf_surface_open_stream (surface,
-						 NULL,
-						 surface->compress_content,
-						 NULL);
-    if (glyph_ret->id == 0) {
+    status = _cairo_pdf_surface_open_stream (surface,
+				             NULL,
+					     surface->compress_content,
+					     NULL);
+    if (status) {
 	if (image != scaled_glyph->surface)
 	    cairo_surface_destroy (&image->base);
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	return status;
     }
 
+    *glyph_ret = surface->pdf_stream.self;
+
     _cairo_output_stream_printf (surface->output,
 				 "%f 0 %f %f %f %f d1\r\n",
                                  x_advance,
@@ -4021,7 +4026,7 @@ _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface)
 	    return status;
 
 	_cairo_pdf_group_resources_clear (&surface->resources);
-	status = _cairo_pdf_surface_open_content_stream (surface, &surface->content, FALSE);
+	status = _cairo_pdf_surface_open_content_stream (surface, FALSE);
 	if (status)
 	    return status;
 
@@ -4215,9 +4220,7 @@ _cairo_pdf_surface_start_fallback (cairo_pdf_surface_t *surface)
 
     surface->has_fallback_images = TRUE;
     _cairo_pdf_group_resources_clear (&surface->resources);
-    return _cairo_pdf_surface_open_content_stream (surface,
-						   &surface->content,
-						   TRUE);
+    return _cairo_pdf_surface_open_content_stream (surface, TRUE);
 }
 
 static cairo_int_status_t
commit 20151fc53401dcc53ef3ab6a78c91a0a02afe497
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Jan 16 16:33:22 2008 +0000

    [cairo-ps-surface] Review error propagation during surface creation.
    
    Track the error during surface creation so that it can be returned to
    the user via _cairo_surface_create_in_error().

diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index f8c3f8c..327243f 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -940,7 +940,7 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
 					      double		     width,
 					      double		     height)
 {
-    cairo_status_t status;
+    cairo_status_t status, status_ignored;
     cairo_ps_surface_t *surface;
 
     surface = malloc (sizeof (cairo_ps_surface_t));
@@ -970,11 +970,13 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
     surface->stream = _cairo_output_stream_create_for_file (surface->tmpfile);
     status = _cairo_output_stream_get_status (surface->stream);
     if (status)
-	goto CLEANUP_TMPFILE;
+	goto CLEANUP_OUTPUT_STREAM;
 
     surface->font_subsets = _cairo_scaled_font_subsets_create_simple ();
-    if (! surface->font_subsets)
+    if (surface->font_subsets == NULL) {
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	goto CLEANUP_OUTPUT_STREAM;
+    }
 
     surface->eps = FALSE;
     surface->ps_level = CAIRO_PS_LEVEL_3;
@@ -998,21 +1000,21 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
 					   CAIRO_CONTENT_COLOR_ALPHA,
 					   width, height,
 					   &cairo_ps_surface_paginated_backend);
-    if (surface->paginated_surface->status == CAIRO_STATUS_SUCCESS)
+    status = surface->paginated_surface->status;
+    if (status == CAIRO_STATUS_SUCCESS)
 	return surface->paginated_surface;
 
     _cairo_scaled_font_subsets_destroy (surface->font_subsets);
  CLEANUP_OUTPUT_STREAM:
-    status = _cairo_output_stream_destroy (surface->stream);
-    /* Ignore status---we're already on a failure path. */
- CLEANUP_TMPFILE:
+    status_ignored = _cairo_output_stream_destroy (surface->stream);
     fclose (surface->tmpfile);
  CLEANUP_SURFACE:
     free (surface);
  CLEANUP:
     /* destroy stream on behalf of caller */
-    status = _cairo_output_stream_destroy (stream);
-    return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+    status_ignored = _cairo_output_stream_destroy (stream);
+
+    return _cairo_surface_create_in_error (status);
 }
 
 /**
@@ -1044,13 +1046,11 @@ cairo_ps_surface_create (const char		*filename,
 			 double			 width_in_points,
 			 double			 height_in_points)
 {
-    cairo_status_t status;
     cairo_output_stream_t *stream;
 
     stream = _cairo_output_stream_create_for_filename (filename);
-    status = _cairo_output_stream_get_status (stream);
-    if (status)
-	return _cairo_surface_create_in_error (status);
+    if (_cairo_output_stream_get_status (stream))
+	return _cairo_surface_create_in_error (_cairo_output_stream_destroy (stream));
 
     return _cairo_ps_surface_create_for_stream_internal (stream,
 							 width_in_points,
@@ -1088,13 +1088,11 @@ cairo_ps_surface_create_for_stream (cairo_write_func_t	write_func,
 				    double		width_in_points,
 				    double		height_in_points)
 {
-    cairo_status_t status;
     cairo_output_stream_t *stream;
 
     stream = _cairo_output_stream_create (write_func, NULL, closure);
-    status = _cairo_output_stream_get_status (stream);
-    if (status)
-	return _cairo_surface_create_in_error (status);
+    if (_cairo_output_stream_get_status (stream))
+	return _cairo_surface_create_in_error (_cairo_output_stream_destroy (stream));
 
     return _cairo_ps_surface_create_for_stream_internal (stream,
 							 width_in_points,
@@ -2031,13 +2029,13 @@ _cairo_ps_surface_emit_base85_string (cairo_ps_surface_t    *surface,
     string_array_stream = _string_array_stream_create (surface->stream);
     status = _cairo_output_stream_get_status (string_array_stream);
     if (status)
-	return status;
+	return _cairo_output_stream_destroy (string_array_stream);
 
     base85_stream = _cairo_base85_stream_create (string_array_stream);
     status = _cairo_output_stream_get_status (base85_stream);
     if (status) {
 	status2 = _cairo_output_stream_destroy (string_array_stream);
-	return status;
+	return _cairo_output_stream_destroy (base85_stream);
     }
 
     _cairo_output_stream_write (base85_stream, data, length);
commit 3daa63693c2f8f9cc3c7fa41ef1e4d69bd67b3cc
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Jan 16 16:33:22 2008 +0000

    [cairo-svg-surface] Review error propagation during surface creation.
    
    Track the error during surface creation so that it can be returned to
    the user via _cairo_surface_create_in_error().

diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index df59ef7..2c3cb58 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -118,11 +118,12 @@ typedef struct {
     cairo_meta_surface_t *meta;
 } cairo_meta_snapshot_t;
 
-static cairo_svg_document_t *
-_cairo_svg_document_create (cairo_output_stream_t   *stream,
-			    double		     width,
-			    double		     height,
-			    cairo_svg_version_t	     version);
+static cairo_status_t
+_cairo_svg_document_create (cairo_output_stream_t	 *stream,
+			    double			  width,
+			    double			  height,
+			    cairo_svg_version_t		  version,
+			    cairo_svg_document_t	**document_out);
 
 static cairo_status_t
 _cairo_svg_document_destroy (cairo_svg_document_t *document);
@@ -173,13 +174,11 @@ cairo_svg_surface_create_for_stream (cairo_write_func_t		 write_func,
 				     double			 width,
 				     double			 height)
 {
-    cairo_status_t status;
     cairo_output_stream_t *stream;
 
     stream = _cairo_output_stream_create (write_func, NULL, closure);
-    status = _cairo_output_stream_get_status (stream);
-    if (status)
-	return _cairo_surface_create_in_error (status);
+    if (_cairo_output_stream_get_status (stream))
+	return _cairo_surface_create_in_error (_cairo_output_stream_destroy (stream));
 
     return _cairo_svg_surface_create_for_stream_internal (stream, width, height, CAIRO_SVG_VERSION_1_1);
 }
@@ -208,13 +207,11 @@ cairo_svg_surface_create (const char	*filename,
 			  double	 width,
 			  double	 height)
 {
-    cairo_status_t status;
     cairo_output_stream_t *stream;
 
     stream = _cairo_output_stream_create_for_filename (filename);
-    status = _cairo_output_stream_get_status (stream);
-    if (status)
-	return _cairo_surface_create_in_error (status);
+    if (_cairo_output_stream_get_status (stream))
+	return _cairo_surface_create_in_error (_cairo_output_stream_destroy (stream));
 
     return _cairo_svg_surface_create_for_stream_internal (stream, width, height, CAIRO_SVG_VERSION_1_1);
 }
@@ -330,7 +327,7 @@ _cairo_svg_surface_create_for_document (cairo_svg_document_t	*document,
 {
     cairo_svg_surface_t *surface;
     cairo_surface_t *paginated;
-    cairo_status_t status;
+    cairo_status_t status, status_ignored;
 
     surface = malloc (sizeof (cairo_svg_surface_t));
     if (surface == NULL)
@@ -351,8 +348,9 @@ _cairo_svg_surface_create_for_document (cairo_svg_document_t	*document,
     surface->is_base_clip_emitted = FALSE;
 
     surface->xml_node = _cairo_memory_stream_create ();
-    if (_cairo_output_stream_get_status (surface->xml_node))
-	goto CLEANUP_DOCUMENT;
+    status = _cairo_output_stream_get_status (surface->xml_node);
+    if (status)
+	goto CLEANUP;
 
     _cairo_array_init (&surface->page_set, sizeof (cairo_svg_page_t));
 
@@ -362,8 +360,9 @@ _cairo_svg_surface_create_for_document (cairo_svg_document_t	*document,
 				     "style=\"opacity: 1; stroke: none; "
 				     "fill: rgb(0,0,0);\"/>\n",
 				     width, height);
-	if (_cairo_output_stream_get_status (surface->xml_node))
-	    goto CLEANUP_STREAM;
+	status = _cairo_output_stream_get_status (surface->xml_node);
+	if (status)
+	    goto CLEANUP;
     }
 
     surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE;
@@ -375,17 +374,18 @@ _cairo_svg_surface_create_for_document (cairo_svg_document_t	*document,
 					         surface->width,
 						 surface->height,
 						 &cairo_svg_surface_paginated_backend);
-    if (! paginated->status)
+    status = paginated->status;
+    if (status == CAIRO_STATUS_SUCCESS)
 	return paginated;
 
     /* ignore status as we are on the error path */
-CLEANUP_STREAM:
-    status = _cairo_output_stream_destroy (surface->xml_node);
-CLEANUP_DOCUMENT:
-    status = _cairo_svg_document_destroy (document);
+CLEANUP:
+    status_ignored = _cairo_output_stream_destroy (surface->xml_node);
+    status_ignored = _cairo_svg_document_destroy (document);
 
     free (surface);
-    return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+
+    return _cairo_surface_create_in_error (status);
 }
 
 static cairo_surface_t *
@@ -394,15 +394,18 @@ _cairo_svg_surface_create_for_stream_internal (cairo_output_stream_t	*stream,
 					       double			 height,
 					       cairo_svg_version_t	 version)
 {
-    cairo_svg_document_t *document;
+    cairo_svg_document_t *document = NULL; /* silence compiler */
     cairo_surface_t *surface;
     cairo_status_t status;
 
-    document = _cairo_svg_document_create (stream, width, height, version);
-    if (document == NULL) {
+    status = _cairo_svg_document_create (stream,
+	                                 width, height, version,
+					 &document);
+    if (status) {
+	surface =  _cairo_surface_create_in_error (status);
 	/* consume the output stream on behalf of caller */
 	status = _cairo_output_stream_destroy (stream);
-	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+	return surface;
     }
 
     surface = _cairo_svg_surface_create_for_document (document, CAIRO_CONTENT_COLOR_ALPHA,
@@ -426,20 +429,21 @@ _cairo_svg_surface_store_page (cairo_svg_surface_t *surface)
     unsigned int i;
     cairo_svg_page_t page;
     cairo_output_stream_t *stream;
+    cairo_status_t status;
 
     stream = _cairo_memory_stream_create ();
-    if (stream->status)
+    if (_cairo_output_stream_get_status (stream)) {
+	status = _cairo_output_stream_destroy (stream);
 	return NULL;
+    }
 
     page.surface_id = surface->id;
     page.clip_level = surface->clip_level;
     page.xml_node = surface->xml_node;
 
-    if (_cairo_array_append (&surface->page_set, &page) != CAIRO_STATUS_SUCCESS)
-    {
-	cairo_status_t status = _cairo_output_stream_destroy (stream);
+    if (_cairo_array_append (&surface->page_set, &page)) {
+	status = _cairo_output_stream_destroy (stream);
 	return NULL;
-	(void) status;
     }
 
     surface->xml_node = stream;
@@ -1954,8 +1958,8 @@ _cairo_svg_surface_paint (void		    *abstract_surface,
 	}
 
 	surface->xml_node = _cairo_memory_stream_create ();
-	status = _cairo_output_stream_get_status (surface->xml_node);
-	if (status) {
+	if (_cairo_output_stream_get_status (surface->xml_node)) {
+	    status = _cairo_output_stream_destroy (surface->xml_node);
 	    surface->xml_node = NULL;
 	    return status;
 	}
@@ -2000,9 +2004,8 @@ _cairo_svg_surface_mask (void		    *abstract_surface,
      * document->xml_node_defs so we need to write the mask element to
      * a temporary stream and then copy that to xml_node_defs. */
     mask_stream = _cairo_memory_stream_create ();
-    status = _cairo_output_stream_get_status (mask_stream);
-    if (status)
-	return status;
+    if (_cairo_output_stream_get_status (mask_stream))
+	return _cairo_output_stream_destroy (mask_stream);
 
     _cairo_output_stream_printf (mask_stream,
 				 "<mask id=\"mask%d\">\n"
@@ -2240,28 +2243,29 @@ static const cairo_surface_backend_t cairo_svg_surface_backend = {
 	_cairo_svg_surface_fill_stroke
 };
 
-static cairo_svg_document_t *
-_cairo_svg_document_create (cairo_output_stream_t	*output_stream,
-			    double			 width,
-			    double			 height,
-			    cairo_svg_version_t		 version)
+static cairo_status_t
+_cairo_svg_document_create (cairo_output_stream_t	 *output_stream,
+			    double			  width,
+			    double			  height,
+			    cairo_svg_version_t		  version,
+			    cairo_svg_document_t	**document_out)
 {
     cairo_svg_document_t *document;
-    cairo_status_t status;
+    cairo_status_t status, status_ignored;
 
     if (output_stream->status)
-	return NULL;
+	return output_stream->status;
 
     document = malloc (sizeof (cairo_svg_document_t));
-    if (document == NULL) {
-	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	return NULL;
-    }
+    if (document == NULL)
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     /* The use of defs for font glyphs imposes no per-subset limit. */
     document->font_subsets = _cairo_scaled_font_subsets_create_scaled ();
-    if (document->font_subsets == NULL)
+    if (document->font_subsets == NULL) {
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	goto CLEANUP_DOCUMENT;
+    }
 
     document->output_stream = output_stream;
     document->refcount = 1;
@@ -2279,12 +2283,14 @@ _cairo_svg_document_create (cairo_output_stream_t	*output_stream,
     document->mask_id = 0;
 
     document->xml_node_defs = _cairo_memory_stream_create ();
-    if (_cairo_output_stream_get_status (document->xml_node_defs))
-	goto CLEANUP_FONT_SUBSETS;
+    status = _cairo_output_stream_get_status (document->xml_node_defs);
+    if (status)
+	goto CLEANUP_NODE_DEFS;
 
     document->xml_node_glyphs = _cairo_memory_stream_create ();
-    if (_cairo_output_stream_get_status (document->xml_node_glyphs))
-	goto CLEANUP_NODE_DEFS;
+    status = _cairo_output_stream_get_status (document->xml_node_glyphs);
+    if (status)
+	goto CLEANUP_NODE_GLYPHS;
 
     document->alpha_filter = FALSE;
 
@@ -2293,15 +2299,17 @@ _cairo_svg_document_create (cairo_output_stream_t	*output_stream,
 
     document->svg_version = version;
 
-    return document;
+    *document_out = document;
+    return CAIRO_STATUS_SUCCESS;
 
+  CLEANUP_NODE_GLYPHS:
+    status_ignored = _cairo_output_stream_destroy (document->xml_node_glyphs);
   CLEANUP_NODE_DEFS:
-    status = _cairo_output_stream_destroy (document->xml_node_defs);
-  CLEANUP_FONT_SUBSETS:
+    status_ignored = _cairo_output_stream_destroy (document->xml_node_defs);
     _cairo_scaled_font_subsets_destroy (document->font_subsets);
   CLEANUP_DOCUMENT:
     free (document);
-    return NULL;
+    return status;
 }
 
 static cairo_svg_document_t *
commit 7111b18c27d7ee0439339a6aa72f0e4244f883f9
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Jan 16 16:23:23 2008 +0000

    [cairo-surface] Introduce _cairo_surface_create_in_error().
    
    Unexport all the static error surfaces and use a function to select
    the appropriate error surface for the status.

diff --git a/src/cairo-array.c b/src/cairo-array.c
index 0313caa..470b327 100644
--- a/src/cairo-array.c
+++ b/src/cairo-array.c
@@ -396,8 +396,7 @@ _cairo_user_data_array_get_data (cairo_user_data_array_t     *array,
     int i, num_slots;
     cairo_user_data_slot_t *slots;
 
-    /* We allow this to support degenerate objects such as
-     * cairo_image_surface_nil. */
+    /* We allow this to support degenerate objects such as cairo_surface_nil. */
     if (array == NULL)
 	return NULL;
 
diff --git a/src/cairo-glitz-surface.c b/src/cairo-glitz-surface.c
index 05e80db..04084e1 100644
--- a/src/cairo-glitz-surface.c
+++ b/src/cairo-glitz-surface.c
@@ -88,20 +88,16 @@ _cairo_glitz_surface_create_similar (void	    *abstract_src,
     gformat =
 	glitz_find_standard_format (drawable,
 				    _glitz_format_from_content (content));
-    if (!gformat) {
-	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	return (cairo_surface_t*) &_cairo_surface_nil;
-    }
+    if (!gformat)
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 
     surface = glitz_surface_create (drawable, gformat,
 				    width <= 0 ? 1 : width,
 				    height <= 0 ? 1 : height,
 				    0, NULL);
 
-    if (surface == NULL) {
-	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	return (cairo_surface_t*) &_cairo_surface_nil;
-    }
+    if (surface == NULL)
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 
     crsurface = cairo_glitz_surface_create (surface);
 
@@ -2456,13 +2452,11 @@ cairo_glitz_surface_create (glitz_surface_t *surface)
     glitz_format_t *format;
 
     if (surface == NULL)
-	return (cairo_surface_t*) &_cairo_surface_nil;
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NULL_POINTER));
 
     crsurface = malloc (sizeof (cairo_glitz_surface_t));
-    if (crsurface == NULL) {
-	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	return (cairo_surface_t*) &_cairo_surface_nil;
-    }
+    if (crsurface == NULL)
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 
     format = glitz_surface_get_format (surface);
     _cairo_surface_init (&crsurface->base, &cairo_glitz_surface_backend,
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index cf19a8f..8787185 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -37,101 +37,6 @@
 
 #include "cairoint.h"
 
-static const cairo_image_surface_t _cairo_image_surface_nil_invalid_format = {
-    {
-	&cairo_image_surface_backend,	/* backend */
-	CAIRO_SURFACE_TYPE_IMAGE,
-	CAIRO_CONTENT_COLOR,
-	CAIRO_REFERENCE_COUNT_INVALID,	/* ref_count */
-	CAIRO_STATUS_INVALID_FORMAT,	/* status */
-	FALSE,				/* finished */
-	{ 0,	/* size */
-	  0,	/* num_elements */
-	  0,	/* element_size */
-	  NULL,	/* elements */
-	},				/* user_data */
-	{ 1.0, 0.0,
-	  0.0, 1.0,
-	  0.0, 0.0
-	},				/* device_transform */
-	{ 1.0, 0.0,
-	  0.0, 1.0,
-	  0.0, 0.0
-	},				/* device_transform_inverse */
-	0.0,				/* x_resolution */
-	0.0,				/* y_resolution */
-	0.0,				/* x_fallback_resolution */
-	0.0,				/* y_fallback_resolution */
-	NULL,				/* clip */
-	0,				/* next_clip_serial */
-	0,				/* current_clip_serial */
-	FALSE,				/* is_snapshot */
-	FALSE,				/* has_font_options */
-	{ CAIRO_ANTIALIAS_DEFAULT,
-	  CAIRO_SUBPIXEL_ORDER_DEFAULT,
-	  CAIRO_HINT_STYLE_DEFAULT,
-	  CAIRO_HINT_METRICS_DEFAULT
-	}				/* font_options */
-    },					/* base */
-    PIXMAN_a8r8g8b8,			/* pixman_format */
-    CAIRO_FORMAT_ARGB32,		/* format */
-    NULL,				/* data */
-    FALSE,				/* owns_data */
-    FALSE,				/* has_clip */
-    0,					/* width */
-    0,					/* height */
-    0,					/* stride */
-    0,					/* depth */
-    NULL				/* pixman_image */
-};
-static const cairo_image_surface_t _cairo_image_surface_nil_invalid_content = {
-    {
-	&cairo_image_surface_backend,	/* backend */
-	CAIRO_SURFACE_TYPE_IMAGE,
-	CAIRO_CONTENT_COLOR,
-	CAIRO_REFERENCE_COUNT_INVALID,	/* ref_count */
-	CAIRO_STATUS_INVALID_CONTENT,	/* status */
-	FALSE,				/* finished */
-	{ 0,	/* size */
-	  0,	/* num_elements */
-	  0,	/* element_size */
-	  NULL,	/* elements */
-	},				/* user_data */
-	{ 1.0, 0.0,
-	  0.0, 1.0,
-	  0.0, 0.0
-	},				/* device_transform */
-	{ 1.0, 0.0,
-	  0.0, 1.0,
-	  0.0, 0.0
-	},				/* device_transform_inverse */
-	0.0,				/* x_resolution */
-	0.0,				/* y_resolution */
-	0.0,				/* x_fallback_resolution */
-	0.0,				/* y_fallback_resolution */
-	NULL,				/* clip */
-	0,				/* next_clip_serial */
-	0,				/* current_clip_serial */
-	FALSE,				/* is_snapshot */
-	FALSE,				/* has_font_options */
-	{ CAIRO_ANTIALIAS_DEFAULT,
-	  CAIRO_SUBPIXEL_ORDER_DEFAULT,
-	  CAIRO_HINT_STYLE_DEFAULT,
-	  CAIRO_HINT_METRICS_DEFAULT
-	}				/* font_options */
-    },					/* base */
-    PIXMAN_a8r8g8b8,			/* pixman_format */
-    CAIRO_FORMAT_ARGB32,		/* format */
-    NULL,				/* data */
-    FALSE,				/* owns_data */
-    FALSE,				/* has_clip */
-    0,					/* width */
-    0,					/* height */
-    0,					/* stride */
-    0,					/* depth */
-    NULL				/* pixman_image */
-};
-
 static cairo_format_t
 _cairo_format_from_pixman_format (pixman_format_code_t pixman_format)
 {
@@ -213,10 +118,8 @@ _cairo_image_surface_create_for_pixman_image (pixman_image_t		*pixman_image,
     cairo_image_surface_t *surface;
 
     surface = malloc (sizeof (cairo_image_surface_t));
-    if (surface == NULL) {
-	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	return (cairo_surface_t*) &_cairo_surface_nil;
-    }
+    if (surface == NULL)
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 
     _cairo_surface_init (&surface->base, &cairo_image_surface_backend,
 			 _cairo_content_from_pixman_format (pixman_format));
@@ -432,16 +335,13 @@ _cairo_image_surface_create_with_pixman_format (unsigned char		*data,
     pixman_image = pixman_image_create_bits (pixman_format, width, height,
 					     (uint32_t *) data, stride);
 
-    if (pixman_image == NULL) {
-	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	return (cairo_surface_t*) &_cairo_surface_nil;
-    }
+    if (pixman_image == NULL)
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 
     surface = _cairo_image_surface_create_for_pixman_image (pixman_image,
 							    pixman_format);
-    if (cairo_surface_status (surface)) {
+    if (cairo_surface_status (surface))
 	pixman_image_unref (pixman_image);
-    }
 
     return surface;
 }
@@ -473,10 +373,8 @@ cairo_image_surface_create (cairo_format_t	format,
 {
     pixman_format_code_t pixman_format;
 
-    if (! CAIRO_FORMAT_VALID (format)) {
-	_cairo_error_throw (CAIRO_STATUS_INVALID_FORMAT);
-	return (cairo_surface_t*) &_cairo_image_surface_nil_invalid_format;
-    }
+    if (! CAIRO_FORMAT_VALID (format))
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
 
     pixman_format = _cairo_format_to_pixman_format_code (format);
 
@@ -490,10 +388,8 @@ _cairo_image_surface_create_with_content (cairo_content_t	content,
 					  int			width,
 					  int			height)
 {
-    if (! CAIRO_CONTENT_VALID (content)) {
-	_cairo_error_throw (CAIRO_STATUS_INVALID_CONTENT);
-	return (cairo_surface_t*) &_cairo_image_surface_nil_invalid_content;
-    }
+    if (! CAIRO_CONTENT_VALID (content))
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_CONTENT));
 
     return cairo_image_surface_create (_cairo_format_from_content (content),
 				       width, height);
@@ -541,10 +437,8 @@ cairo_image_surface_create_for_data (unsigned char     *data,
     /* XXX pixman does not support images with arbitrary strides and
      * attempting to create such surfaces will failure but we will interpret
      * such failure as CAIRO_STATUS_NO_MEMORY.  */
-    if (! CAIRO_FORMAT_VALID (format) || stride % sizeof (uint32_t) != 0) {
-	_cairo_error_throw (CAIRO_STATUS_INVALID_FORMAT);
-	return (cairo_surface_t*) &_cairo_image_surface_nil_invalid_format;
-    }
+    if (! CAIRO_FORMAT_VALID (format) || stride % sizeof (uint32_t) != 0)
+	return _cairo_surface_create_in_error (_cairo_error(CAIRO_STATUS_INVALID_FORMAT));
 
     pixman_format = _cairo_format_to_pixman_format_code (format);
 
@@ -560,10 +454,8 @@ _cairo_image_surface_create_for_data_with_content (unsigned char	*data,
 						   int			 height,
 						   int			 stride)
 {
-    if (! CAIRO_CONTENT_VALID (content)) {
-	_cairo_error_throw (CAIRO_STATUS_INVALID_CONTENT);
-	return (cairo_surface_t*) &_cairo_image_surface_nil_invalid_content;
-    }
+    if (! CAIRO_CONTENT_VALID (content))
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_CONTENT));
 
     return cairo_image_surface_create_for_data (data,
 						_cairo_format_from_content (content),
@@ -1382,7 +1274,7 @@ _cairo_image_surface_clone (cairo_image_surface_t	*surface,
 
     if (status) {
 	cairo_surface_destroy (&clone->base);
-	return (cairo_image_surface_t *) &_cairo_surface_nil;
+	return (cairo_image_surface_t *) _cairo_surface_create_in_error (status);
     }
 
     return clone;
diff --git a/src/cairo-meta-surface.c b/src/cairo-meta-surface.c
index 5b4f4ff..51ed382 100644
--- a/src/cairo-meta-surface.c
+++ b/src/cairo-meta-surface.c
@@ -83,10 +83,8 @@ _cairo_meta_surface_create (cairo_content_t	content,
     cairo_meta_surface_t *meta;
 
     meta = malloc (sizeof (cairo_meta_surface_t));
-    if (meta == NULL) {
-	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	return (cairo_surface_t*) &_cairo_surface_nil;
-    }
+    if (meta == NULL)
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 
     _cairo_surface_init (&meta->base, &cairo_meta_surface_backend,
 			 content);
@@ -498,10 +496,8 @@ _cairo_meta_surface_snapshot (void *abstract_other)
     cairo_meta_surface_t *meta;
 
     meta = malloc (sizeof (cairo_meta_surface_t));
-    if (meta == NULL) {
-	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	return (cairo_surface_t*) &_cairo_surface_nil;
-    }
+    if (meta == NULL)
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 
     _cairo_surface_init (&meta->base, &cairo_meta_surface_backend,
 			 other->base.content);
diff --git a/src/cairo-os2-surface.c b/src/cairo-os2-surface.c
index 86ab82c..f382484 100644
--- a/src/cairo-os2-surface.c
+++ b/src/cairo-os2-surface.c
@@ -722,6 +722,7 @@ cairo_os2_surface_create (HPS hps_client_window,
                           int height)
 {
     cairo_os2_surface_t *local_os2_surface;
+    cairo_status_t status;
     int rc;
 
     /* Check the size of the window */
@@ -729,15 +730,13 @@ cairo_os2_surface_create (HPS hps_client_window,
         (height <= 0))
     {
         /* Invalid window size! */
-        _cairo_error (CAIRO_STATUS_NO_MEMORY);
-        return (cairo_surface_t *) &_cairo_surface_nil;
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
     }
 
     local_os2_surface = (cairo_os2_surface_t *) malloc (sizeof (cairo_os2_surface_t));
     if (!local_os2_surface) {
         /* Not enough memory! */
-        _cairo_error (CAIRO_STATUS_NO_MEMORY);
-        return (cairo_surface_t *) &_cairo_surface_nil;
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
     }
 
     /* Initialize the OS/2 specific parts of the surface! */
@@ -749,8 +748,7 @@ cairo_os2_surface_create (HPS hps_client_window,
                             FALSE);
     if (rc != NO_ERROR) {
         /* Could not create mutex semaphore! */
-        _cairo_error (CAIRO_STATUS_NO_MEMORY);
-        return (cairo_surface_t *) &_cairo_surface_nil;
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
     }
 
     /* Save PS handle */
@@ -769,8 +767,7 @@ cairo_os2_surface_create (HPS hps_client_window,
         /* Could not create event semaphore! */
         DosCloseMutexSem (local_os2_surface->hmtx_use_private_fields);
         free (local_os2_surface);
-        _cairo_error (CAIRO_STATUS_NO_MEMORY);
-        return (cairo_surface_t *) &_cairo_surface_nil;
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
     }
 
     /* Prepare BITMAPINFO2 structure for our buffer */
@@ -788,8 +785,7 @@ cairo_os2_surface_create (HPS hps_client_window,
         DosCloseEventSem (local_os2_surface->hev_pixel_array_came_back);
         DosCloseMutexSem (local_os2_surface->hmtx_use_private_fields);
         free (local_os2_surface);
-        _cairo_error (CAIRO_STATUS_NO_MEMORY);
-        return (cairo_surface_t *) &_cairo_surface_nil;
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
     }
 
     /* Create image surface from pixel array */
@@ -800,14 +796,14 @@ cairo_os2_surface_create (HPS hps_client_window,
                                              height,     /* Height */
                                              width * 4); /* Rowstride */
 
-    if (local_os2_surface->image_surface->base.status) {
+    status = local_os2_surface->image_surface->base.status;
+    if (status) {
         /* Could not create image surface! */
         _buffer_free (local_os2_surface->pixels);
         DosCloseEventSem (local_os2_surface->hev_pixel_array_came_back);
         DosCloseMutexSem (local_os2_surface->hmtx_use_private_fields);
         free (local_os2_surface);
-        _cairo_error (CAIRO_STATUS_NO_MEMORY);
-        return (cairo_surface_t *) &_cairo_surface_nil;
+        return _cairo_surface_create_in_error (status);
     }
 
     /* Initialize base surface */
diff --git a/src/cairo-paginated-surface.c b/src/cairo-paginated-surface.c
index 6af4be6..98ec061 100644
--- a/src/cairo-paginated-surface.c
+++ b/src/cairo-paginated-surface.c
@@ -74,10 +74,11 @@ _cairo_paginated_surface_create (cairo_surface_t				*target,
 				 const cairo_paginated_surface_backend_t	*backend)
 {
     cairo_paginated_surface_t *surface;
+    cairo_status_t status;
 
     surface = malloc (sizeof (cairo_paginated_surface_t));
     if (surface == NULL) {
-	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	goto FAIL;
     }
 
@@ -97,7 +98,8 @@ _cairo_paginated_surface_create (cairo_surface_t				*target,
     surface->backend = backend;
 
     surface->meta = _cairo_meta_surface_create (content, width, height);
-    if (cairo_surface_status (surface->meta))
+    status = cairo_surface_status (surface->meta);
+    if (status)
 	goto FAIL_CLEANUP_SURFACE;
 
     surface->page_num = 1;
@@ -108,7 +110,7 @@ _cairo_paginated_surface_create (cairo_surface_t				*target,
   FAIL_CLEANUP_SURFACE:
     free (surface);
   FAIL:
-    return (cairo_surface_t*) &_cairo_surface_nil;
+    return _cairo_surface_create_in_error (status);
 }
 
 cairo_bool_t
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 29c2c41..9ad9e1a 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -240,8 +240,7 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t	*output,
     if (surface == NULL) {
 	/* destroy stream on behalf of caller */
 	status = _cairo_output_stream_destroy (output);
-	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	return (cairo_surface_t*) &_cairo_surface_nil;
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
     }
 
     _cairo_surface_init (&surface->base, &cairo_pdf_surface_backend,
@@ -316,7 +315,7 @@ BAIL0:
     /* destroy stream on behalf of caller */
     status = _cairo_output_stream_destroy (output);
 
-    return (cairo_surface_t*) &_cairo_surface_nil;
+    return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
 }
 
 /**
@@ -351,7 +350,7 @@ cairo_pdf_surface_create_for_stream (cairo_write_func_t		 write_func,
     output = _cairo_output_stream_create (write_func, NULL, closure);
     status = _cairo_output_stream_get_status (output);
     if (status)
-	return (cairo_surface_t*) &_cairo_surface_nil;
+	return _cairo_surface_create_in_error (status);
 
     return _cairo_pdf_surface_create_for_stream_internal (output,
 							  width_in_points,
@@ -388,9 +387,7 @@ cairo_pdf_surface_create (const char		*filename,
     output = _cairo_output_stream_create_for_filename (filename);
     status = _cairo_output_stream_get_status (output);
     if (status)
-	return (status == CAIRO_STATUS_WRITE_ERROR) ?
-		(cairo_surface_t*) &_cairo_surface_nil_write_error :
-		(cairo_surface_t*) &_cairo_surface_nil;
+	return _cairo_surface_create_in_error (status);
 
     return _cairo_pdf_surface_create_for_stream_internal (output,
 							  width_in_points,
diff --git a/src/cairo-png.c b/src/cairo-png.c
index b76b525..a78da3f 100644
--- a/src/cairo-png.c
+++ b/src/cairo-png.c
@@ -382,7 +382,7 @@ static cairo_surface_t *
 read_png (png_rw_ptr	read_func,
 	  void		*closure)
 {
-    cairo_surface_t *surface = (cairo_surface_t*) &_cairo_surface_nil;
+    cairo_surface_t *surface;
     png_struct *png = NULL;
     png_info *info;
     png_byte *data = NULL;
@@ -398,20 +398,23 @@ read_png (png_rw_ptr	read_func,
                                   &status,
 	                          png_simple_error_callback,
 	                          png_simple_warning_callback);
-    if (png == NULL)
+    if (png == NULL) {
+	surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 	goto BAIL;
+    }
 
     info = png_create_info_struct (png);
-    if (info == NULL)
+    if (info == NULL) {
+	surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 	goto BAIL;
+    }
 
     png_set_read_fn (png, closure, read_func);
 
     status = CAIRO_STATUS_SUCCESS;
 #ifdef PNG_SETJMP_SUPPORTED
     if (setjmp (png_jmpbuf (png))) {
-	if (status != CAIRO_STATUS_NO_MEMORY)
-	    surface = (cairo_surface_t*) &_cairo_surface_nil_read_error;
+	surface = _cairo_surface_create_in_error (status);
 	goto BAIL;
     }
 #endif
@@ -460,12 +463,16 @@ read_png (png_rw_ptr	read_func,
 
     pixel_size = 4;
     data = _cairo_malloc_abc (png_height, png_width, pixel_size);
-    if (data == NULL)
+    if (data == NULL) {
+	surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 	goto BAIL;
+    }
 
     row_pointers = _cairo_malloc_ab (png_height, sizeof (char *));
-    if (row_pointers == NULL)
+    if (row_pointers == NULL) {
+	surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 	goto BAIL;
+    }
 
     for (i = 0; i < png_height; i++)
         row_pointers[i] = &data[i * png_width * pixel_size];
@@ -490,9 +497,6 @@ read_png (png_rw_ptr	read_func,
     if (png)
 	png_destroy_read_struct (&png, &info, NULL);
 
-    if (surface->status)
-	_cairo_error_throw (surface->status);
-
     return surface;
 }
 
@@ -538,17 +542,19 @@ cairo_image_surface_create_from_png (const char *filename)
 
     fp = fopen (filename, "rb");
     if (fp == NULL) {
+	cairo_status_t status;
 	switch (errno) {
 	case ENOMEM:
-	    _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	    return (cairo_surface_t*) &_cairo_surface_nil;
+	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    break;
 	case ENOENT:
-	    _cairo_error_throw (CAIRO_STATUS_FILE_NOT_FOUND);
-	    return (cairo_surface_t*) &_cairo_surface_nil_file_not_found;
+	    status = _cairo_error (CAIRO_STATUS_FILE_NOT_FOUND);
+	    break;
 	default:
-	    _cairo_error_throw (CAIRO_STATUS_READ_ERROR);
-	    return (cairo_surface_t*) &_cairo_surface_nil_read_error;
+	    status = _cairo_error (CAIRO_STATUS_READ_ERROR);
+	    break;
 	}
+	return _cairo_surface_create_in_error (status);
     }
 
     surface = read_png (stdio_read_func, fp);
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 93c9055..f8c3f8c 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -1012,8 +1012,7 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
  CLEANUP:
     /* destroy stream on behalf of caller */
     status = _cairo_output_stream_destroy (stream);
-    _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-    return (cairo_surface_t*) &_cairo_surface_nil;
+    return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 }
 
 /**
@@ -1051,9 +1050,7 @@ cairo_ps_surface_create (const char		*filename,
     stream = _cairo_output_stream_create_for_filename (filename);
     status = _cairo_output_stream_get_status (stream);
     if (status)
-	return (status == CAIRO_STATUS_WRITE_ERROR) ?
-		(cairo_surface_t*) &_cairo_surface_nil_write_error :
-		(cairo_surface_t*) &_cairo_surface_nil;
+	return _cairo_surface_create_in_error (status);
 
     return _cairo_ps_surface_create_for_stream_internal (stream,
 							 width_in_points,
@@ -1097,7 +1094,7 @@ cairo_ps_surface_create_for_stream (cairo_write_func_t	write_func,
     stream = _cairo_output_stream_create (write_func, NULL, closure);
     status = _cairo_output_stream_get_status (stream);
     if (status)
-	return (cairo_surface_t*) &_cairo_surface_nil;
+	return _cairo_surface_create_in_error (status);
 
     return _cairo_ps_surface_create_for_stream_internal (stream,
 							 width_in_points,
diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index 1990062..3cb6389 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -1865,10 +1865,8 @@ _cairo_quartz_surface_create_internal (CGContextRef cgContext,
 
     /* Init the base surface */
     surface = malloc(sizeof(cairo_quartz_surface_t));
-    if (surface == NULL) {
-	_cairo_error (CAIRO_STATUS_NO_MEMORY);
-	return NULL;
-    }
+    if (surface == NULL)
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 
     memset(surface, 0, sizeof(cairo_quartz_surface_t));
 
@@ -1940,10 +1938,10 @@ cairo_quartz_surface_create_for_cg_context (CGContextRef cgContext,
 
     surf = _cairo_quartz_surface_create_internal (cgContext, CAIRO_CONTENT_COLOR_ALPHA,
 						  width, height);
-    if (!surf) {
+    if (surf->base.status) {
 	CGContextRelease (cgContext);
 	// create_internal will have set an error
-	return (cairo_surface_t*) &_cairo_surface_nil;
+	return surf;
     }
 
     return (cairo_surface_t *) surf;
@@ -1978,10 +1976,8 @@ cairo_quartz_surface_create (cairo_format_t format,
     int bitsPerComponent;
 
     // verify width and height of surface
-    if (!verify_surface_size(width, height)) {
-	_cairo_error (CAIRO_STATUS_NO_MEMORY);
-	return (cairo_surface_t*) &_cairo_surface_nil;
-    }
+    if (!verify_surface_size(width, height))
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 
     if (width == 0 || height == 0) {
 	return (cairo_surface_t*) _cairo_quartz_surface_create_internal (NULL, _cairo_content_from_format (format),
@@ -2011,18 +2007,15 @@ cairo_quartz_surface_create (cairo_format_t format,
 	 * cairo_format_t -- these are 1-bit pixels stored in 32-bit
 	 * quantities.
 	 */
-	_cairo_error (CAIRO_STATUS_INVALID_FORMAT);
-	return (cairo_surface_t*) &_cairo_surface_nil;
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
     } else {
-	_cairo_error (CAIRO_STATUS_INVALID_FORMAT);
-	return (cairo_surface_t*) &_cairo_surface_nil;
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
     }
 
     imageData = _cairo_malloc_ab (height, stride);
     if (!imageData) {
 	CGColorSpaceRelease (cgColorspace);
-	_cairo_error (CAIRO_STATUS_NO_MEMORY);
-	return (cairo_surface_t*) &_cairo_surface_nil;
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
     }
     /* zero the memory to match the image surface behaviour */
     memset (imageData, 0, height * stride);
@@ -2037,9 +2030,8 @@ cairo_quartz_surface_create (cairo_format_t format,
     CGColorSpaceRelease (cgColorspace);
 
     if (!cgc) {
-	_cairo_error (CAIRO_STATUS_NO_MEMORY);
 	free (imageData);
-	return (cairo_surface_t*) &_cairo_surface_nil;
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
     }
 
     /* flip the Y axis */
@@ -2048,11 +2040,11 @@ cairo_quartz_surface_create (cairo_format_t format,
 
     surf = _cairo_quartz_surface_create_internal (cgc, _cairo_content_from_format (format),
 						  width, height);
-    if (!surf) {
+    if (surf->base.status) {
 	CGContextRelease (cgc);
 	free (imageData);
 	// create_internal will have set an error
-	return (cairo_surface_t*) &_cairo_surface_nil;
+	return surf;
     }
 
     surf->imageData = imageData;
diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c
index ef28d9d..02a2e9d 100644
--- a/src/cairo-surface-fallback.c
+++ b/src/cairo-surface-fallback.c
@@ -1043,8 +1043,8 @@ _cairo_surface_fallback_snapshot (cairo_surface_t *surface)
 
     status = _cairo_surface_acquire_source_image (surface,
 						  &image, &image_extra);
-    if (status != CAIRO_STATUS_SUCCESS)
-	return (cairo_surface_t *) &_cairo_surface_nil;
+    if (status)
+	return _cairo_surface_create_in_error (status);
 
     snapshot = cairo_image_surface_create (image->format,
 					   image->width,
@@ -1073,7 +1073,7 @@ _cairo_surface_fallback_snapshot (cairo_surface_t *surface)
 
     if (status) {
 	cairo_surface_destroy (snapshot);
-	return (cairo_surface_t *) &_cairo_surface_nil;
+	return _cairo_surface_create_in_error (status);
     }
 
     snapshot->device_transform = surface->device_transform;
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index f6f26c7..8860c95 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -78,10 +78,14 @@ const cairo_surface_t name = {					\
     }					/* font_options */	\
 }
 
-DEFINE_NIL_SURFACE(CAIRO_STATUS_NO_MEMORY, _cairo_surface_nil);
-DEFINE_NIL_SURFACE(CAIRO_STATUS_FILE_NOT_FOUND, _cairo_surface_nil_file_not_found);
-DEFINE_NIL_SURFACE(CAIRO_STATUS_READ_ERROR, _cairo_surface_nil_read_error);
-DEFINE_NIL_SURFACE(CAIRO_STATUS_WRITE_ERROR, _cairo_surface_nil_write_error);
+static DEFINE_NIL_SURFACE(CAIRO_STATUS_NO_MEMORY, _cairo_surface_nil);
+static DEFINE_NIL_SURFACE(CAIRO_STATUS_INVALID_CONTENT, _cairo_surface_nil_invalid_content);
+static DEFINE_NIL_SURFACE(CAIRO_STATUS_INVALID_FORMAT, _cairo_surface_nil_invalid_format);
+static DEFINE_NIL_SURFACE(CAIRO_STATUS_INVALID_VISUAL, _cairo_surface_nil_invalid_visual);
+static DEFINE_NIL_SURFACE(CAIRO_STATUS_FILE_NOT_FOUND, _cairo_surface_nil_file_not_found);
+static DEFINE_NIL_SURFACE(CAIRO_STATUS_TEMP_FILE_ERROR, _cairo_surface_nil_temp_file_error);
+static DEFINE_NIL_SURFACE(CAIRO_STATUS_READ_ERROR, _cairo_surface_nil_read_error);
+static DEFINE_NIL_SURFACE(CAIRO_STATUS_WRITE_ERROR, _cairo_surface_nil_write_error);
 
 static cairo_status_t
 _cairo_surface_copy_pattern_for_destination (const cairo_pattern_t *pattern,
@@ -228,7 +232,7 @@ _cairo_surface_create_similar_scratch (cairo_surface_t *other,
     cairo_format_t format = _cairo_format_from_content (content);
 
     if (other->status)
-	return (cairo_surface_t*) &_cairo_surface_nil;
+	return _cairo_surface_create_in_error (other->status);
 
     if (other->backend->create_similar) {
 	surface = other->backend->create_similar (other, content, width, height);
@@ -289,12 +293,10 @@ cairo_surface_create_similar (cairo_surface_t  *other,
 			      int		height)
 {
     if (other->status)
-	return (cairo_surface_t*) &_cairo_surface_nil;
+	return _cairo_surface_create_in_error (other->status);
 
-    if (! CAIRO_CONTENT_VALID (content)) {
-	_cairo_error_throw (CAIRO_STATUS_INVALID_CONTENT);
-	return (cairo_surface_t*) &_cairo_surface_nil;
-    }
+    if (! CAIRO_CONTENT_VALID (content))
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_CONTENT));
 
     return _cairo_surface_create_similar_solid (other, content,
 						width, height,
@@ -317,17 +319,14 @@ _cairo_surface_create_similar_solid (cairo_surface_t	 *other,
 
     surface = _cairo_surface_create_similar_scratch (other, content,
 						     width, height);
-    if (surface->status) {
-	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	return (cairo_surface_t*) &_cairo_surface_nil;
-    }
+    if (surface->status)
+	return surface;
 
     if (pattern == NULL) {
 	source = _cairo_pattern_create_solid (color, content);
 	if (source->status) {
 	    cairo_surface_destroy (surface);
-	    _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	    return (cairo_surface_t*) &_cairo_surface_nil;
+	    return _cairo_surface_create_in_error (source->status);
 	}
     } else
 	source = pattern;
@@ -342,8 +341,7 @@ _cairo_surface_create_similar_solid (cairo_surface_t	 *other,
 
     if (status) {
 	cairo_surface_destroy (surface);
-	_cairo_error_throw (status);
-	return (cairo_surface_t*) &_cairo_surface_nil;
+	return _cairo_surface_create_in_error (status);
     }
 
     return surface;
@@ -1141,7 +1139,7 @@ cairo_surface_t *
 _cairo_surface_snapshot (cairo_surface_t *surface)
 {
     if (surface->finished)
-	return (cairo_surface_t *) &_cairo_surface_nil;
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
 
     if (surface->backend->snapshot)
 	return surface->backend->snapshot (surface);
@@ -2412,5 +2410,31 @@ _cairo_surface_set_resolution (cairo_surface_t *surface,
     surface->y_resolution = y_res;
 }
 
+cairo_surface_t *
+_cairo_surface_create_in_error (cairo_status_t status)
+{
+    switch (status) {
+    case CAIRO_STATUS_NO_MEMORY:
+	return (cairo_surface_t *) &_cairo_surface_nil;
+    case CAIRO_STATUS_INVALID_CONTENT:
+	return (cairo_surface_t *) &_cairo_surface_nil_invalid_content;
+    case CAIRO_STATUS_INVALID_FORMAT:
+	return (cairo_surface_t *) &_cairo_surface_nil_invalid_format;
+    case CAIRO_STATUS_INVALID_VISUAL:
+	return (cairo_surface_t *) &_cairo_surface_nil_invalid_visual;
+    case CAIRO_STATUS_READ_ERROR:
+	return (cairo_surface_t *) &_cairo_surface_nil_read_error;
+    case CAIRO_STATUS_WRITE_ERROR:
+	return (cairo_surface_t *) &_cairo_surface_nil_write_error;
+    case CAIRO_STATUS_FILE_NOT_FOUND:
+	return (cairo_surface_t *) &_cairo_surface_nil_file_not_found;
+    case CAIRO_STATUS_TEMP_FILE_ERROR:
+	return (cairo_surface_t *) &_cairo_surface_nil_temp_file_error;
+    default:
+	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+	return (cairo_surface_t *) &_cairo_surface_nil;
+    }
+}
+
 /*  LocalWords:  rasterized
  */
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index acddb16..df59ef7 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -179,7 +179,7 @@ cairo_svg_surface_create_for_stream (cairo_write_func_t		 write_func,
     stream = _cairo_output_stream_create (write_func, NULL, closure);
     status = _cairo_output_stream_get_status (stream);
     if (status)
-	return (cairo_surface_t *) &_cairo_surface_nil;
+	return _cairo_surface_create_in_error (status);
 
     return _cairo_svg_surface_create_for_stream_internal (stream, width, height, CAIRO_SVG_VERSION_1_1);
 }
@@ -214,9 +214,7 @@ cairo_svg_surface_create (const char	*filename,
     stream = _cairo_output_stream_create_for_filename (filename);
     status = _cairo_output_stream_get_status (stream);
     if (status)
-	return (status == CAIRO_STATUS_WRITE_ERROR) ?
-		(cairo_surface_t *) &_cairo_surface_nil_write_error :
-		(cairo_surface_t *) &_cairo_surface_nil;
+	return _cairo_surface_create_in_error (status);
 
     return _cairo_svg_surface_create_for_stream_internal (stream, width, height, CAIRO_SVG_VERSION_1_1);
 }
@@ -335,10 +333,8 @@ _cairo_svg_surface_create_for_document (cairo_svg_document_t	*document,
     cairo_status_t status;
 
     surface = malloc (sizeof (cairo_svg_surface_t));
-    if (surface == NULL) {
-	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	return (cairo_surface_t*) &_cairo_surface_nil;
-    }
+    if (surface == NULL)
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 
     _cairo_surface_init (&surface->base, &cairo_svg_surface_backend,
 			 content);
@@ -389,8 +385,7 @@ CLEANUP_DOCUMENT:
     status = _cairo_svg_document_destroy (document);
 
     free (surface);
-    _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-    return (cairo_surface_t*) &_cairo_surface_nil;
+    return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 }
 
 static cairo_surface_t *
@@ -407,15 +402,14 @@ _cairo_svg_surface_create_for_stream_internal (cairo_output_stream_t	*stream,
     if (document == NULL) {
 	/* consume the output stream on behalf of caller */
 	status = _cairo_output_stream_destroy (stream);
-	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	return (cairo_surface_t *) &_cairo_surface_nil;
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
     }
 
     surface = _cairo_svg_surface_create_for_document (document, CAIRO_CONTENT_COLOR_ALPHA,
 						      width, height);
     if (surface->status) {
 	status = _cairo_svg_document_destroy (document);
-	return (cairo_surface_t *) &_cairo_surface_nil;
+	return surface;
     }
 
     document->owner = surface;
diff --git a/src/cairo-win32-printing-surface.c b/src/cairo-win32-printing-surface.c
index 3a5a3b8..d589f23 100644
--- a/src/cairo-win32-printing-surface.c
+++ b/src/cairo-win32-printing-surface.c
@@ -71,7 +71,6 @@
 #endif
 
 #define PELS_72DPI  ((LONG)(72. / 0.0254))
-#define NIL_SURFACE ((cairo_surface_t*)&_cairo_surface_nil)
 
 static const cairo_surface_backend_t cairo_win32_printing_surface_backend;
 static const cairo_paginated_surface_backend_t cairo_win32_surface_paginated_backend;
@@ -1467,15 +1466,12 @@ cairo_win32_printing_surface_create (HDC hdc)
     if (GetClipBox (hdc, &rect) == ERROR) {
 	_cairo_win32_print_gdi_error ("cairo_win32_surface_create");
 	/* XXX: Can we make a more reasonable guess at the error cause here? */
-	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	return NIL_SURFACE;
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
     }
 
     surface = malloc (sizeof (cairo_win32_surface_t));
-    if (surface == NULL) {
-	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	return NIL_SURFACE;
-    }
+    if (surface == NULL)
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 
     surface->image = NULL;
     surface->format = CAIRO_FORMAT_RGB24;
diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
index 2342230..881532b 100644
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -67,7 +67,6 @@
 #endif
 
 #define PELS_72DPI  ((LONG)(72. / 0.0254))
-#define NIL_SURFACE ((cairo_surface_t*)&_cairo_surface_nil)
 
 static const cairo_surface_backend_t cairo_win32_surface_backend;
 
@@ -333,10 +332,8 @@ _cairo_win32_surface_create_for_dc (HDC             original_dc,
     int rowstride;
 
     surface = malloc (sizeof (cairo_win32_surface_t));
-    if (surface == NULL) {
-	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	return NIL_SURFACE;
-    }
+    if (surface == NULL)
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 
     status = _create_dc_and_bitmap (surface, original_dc, format,
 				    width, height,
@@ -346,10 +343,9 @@ _cairo_win32_surface_create_for_dc (HDC             original_dc,
 
     surface->image = cairo_image_surface_create_for_data (bits, format,
 							  width, height, rowstride);
-    if (surface->image->status) {
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    status = surface->image->status;
+    if (status)
 	goto FAIL;
-    }
 
     surface->format = format;
 
@@ -365,7 +361,7 @@ _cairo_win32_surface_create_for_dc (HDC             original_dc,
     _cairo_surface_init (&surface->base, &cairo_win32_surface_backend,
 			 _cairo_content_from_format (format));
 
-    return (cairo_surface_t *)surface;
+    return &surface->base;
 
  FAIL:
     if (surface->bitmap) {
@@ -373,10 +369,9 @@ _cairo_win32_surface_create_for_dc (HDC             original_dc,
 	DeleteObject (surface->bitmap);
 	DeleteDC (surface->dc);
     }
-    if (surface)
-	free (surface);
+    free (surface);
 
-    return NIL_SURFACE;
+    return _cairo_surface_create_in_error (status);
 }
 
 static cairo_surface_t *
@@ -1720,8 +1715,7 @@ cairo_win32_surface_create (HDC hdc)
     if (clipBoxType == ERROR) {
 	_cairo_win32_print_gdi_error ("cairo_win32_surface_create");
 	/* XXX: Can we make a more reasonable guess at the error cause here? */
-	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	return NIL_SURFACE;
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
     }
 
     if (GetDeviceCaps(hdc, TECHNOLOGY) == DT_RASDISPLAY) {
@@ -1738,18 +1732,15 @@ cairo_win32_surface_create (HDC hdc)
 	    format = CAIRO_FORMAT_A1;
 	else {
 	    _cairo_win32_print_gdi_error("cairo_win32_surface_create(bad BITSPIXEL)");
-	    _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	    return NIL_SURFACE;
+	    return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
 	}
     } else {
 	format = CAIRO_FORMAT_RGB24;
     }
 
     surface = malloc (sizeof (cairo_win32_surface_t));
-    if (surface == NULL) {
-	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	return NIL_SURFACE;
-    }
+    if (surface == NULL)
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 
     surface->image = NULL;
     surface->format = format;
@@ -1837,7 +1828,7 @@ cairo_win32_surface_create_with_ddb (HDC hdc,
     HBITMAP saved_dc_bitmap;
 
     if (format != CAIRO_FORMAT_RGB24)
-	return NIL_SURFACE;
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
 /* XXX handle these eventually
 	format != CAIRO_FORMAT_A8 ||
 	format != CAIRO_FORMAT_A1)
@@ -1853,7 +1844,7 @@ cairo_win32_surface_create_with_ddb (HDC hdc,
     ddb_dc = CreateCompatibleDC (hdc);
     if (ddb_dc == NULL) {
 	_cairo_win32_print_gdi_error("CreateCompatibleDC");
-	new_surf = (cairo_win32_surface_t*) NIL_SURFACE;
+	new_surf = (cairo_win32_surface_t*) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 	goto FINISH;
     }
 
@@ -1866,7 +1857,7 @@ cairo_win32_surface_create_with_ddb (HDC hdc,
 	 * video memory is probably exhausted.
 	 */
 	_cairo_win32_print_gdi_error("CreateCompatibleBitmap");
-	new_surf = (cairo_win32_surface_t*) NIL_SURFACE;
+	new_surf = (cairo_win32_surface_t*) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 	goto FINISH;
     }
 
diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c
index 451cc8f..2b1f888 100644
--- a/src/cairo-xcb-surface.c
+++ b/src/cairo-xcb-surface.c
@@ -196,10 +196,8 @@ _cairo_xcb_surface_create_similar (void		       *abstract_src,
 	cairo_xcb_surface_create_with_xrender_format (dpy, pixmap, src->screen,
 						      xrender_format,
 						      width, height);
-    if (surface->base.status) {
-	_cairo_error (CAIRO_STATUS_NO_MEMORY);
-	return (cairo_surface_t*) &_cairo_surface_nil;
-    }
+    if (surface->base.status)
+	return surface;
 
     surface->owns_pixmap = TRUE;
 
@@ -1730,10 +1728,8 @@ _cairo_xcb_surface_create_internal (xcb_connection_t	     *dpy,
     const xcb_render_query_version_reply_t *r;
 
     surface = malloc (sizeof (cairo_xcb_surface_t));
-    if (surface == NULL) {
-	_cairo_error (CAIRO_STATUS_NO_MEMORY);
-	return (cairo_surface_t*) &_cairo_surface_nil;
-    }
+    if (surface == NULL)
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 
     if (xrender_format) {
 	depth = xrender_format->depth;
@@ -1873,10 +1869,8 @@ cairo_xcb_surface_create (xcb_connection_t *c,
 {
     xcb_screen_t	*screen = _cairo_xcb_screen_from_visual (c, visual);
 
-    if (screen == NULL) {
-	_cairo_error (CAIRO_STATUS_INVALID_VISUAL);
-	return (cairo_surface_t*) &_cairo_surface_nil;
-    }
+    if (screen == NULL)
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL));
 
     return _cairo_xcb_surface_create_internal (c, drawable, screen,
 					       visual, NULL,
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index bd1a3e8..93cd6f8 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -176,10 +176,9 @@ _cairo_xlib_surface_create_similar_with_format (void	       *abstract_src,
 	cairo_xlib_surface_create_with_xrender_format (dpy, pix, src->screen,
 						       xrender_format,
 						       width, height);
-    if (surface->base.status != CAIRO_STATUS_SUCCESS) {
+    if (surface->base.status) {
 	XFreePixmap (dpy, pix);
-	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	return (cairo_surface_t*) &_cairo_surface_nil;
+	return &surface->base;
     }
 
     surface->owns_pixmap = TRUE;
@@ -258,8 +257,7 @@ _cairo_xlib_surface_create_similar (void	       *abstract_src,
 						       width, height);
     if (surface->base.status != CAIRO_STATUS_SUCCESS) {
 	XFreePixmap (src->dpy, pix);
-	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	return (cairo_surface_t*) &_cairo_surface_nil;
+	return &surface->base;
     }
 
     surface->owns_pixmap = TRUE;
@@ -1949,24 +1947,20 @@ _cairo_xlib_surface_create_internal (Display		       *dpy,
     cairo_xlib_screen_info_t *screen_info;
 
     screen_info = _cairo_xlib_screen_info_get (dpy, screen);
-    if (screen_info == NULL) {
-	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	return (cairo_surface_t*) &_cairo_surface_nil;
-    }
+    if (screen_info == NULL)
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 
     surface = malloc (sizeof (cairo_xlib_surface_t));
     if (surface == NULL) {
 	_cairo_xlib_screen_info_destroy (screen_info);
-	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	return (cairo_surface_t*) &_cairo_surface_nil;
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
     }
 
     if (! _cairo_xlib_add_close_display_hook (dpy,
 	    _cairo_xlib_surface_detach_display, surface, surface)) {
 	free (surface);
 	_cairo_xlib_screen_info_destroy (screen_info);
-	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	return (cairo_surface_t*) &_cairo_surface_nil;
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
     }
 
     if (xrender_format) {
@@ -2096,10 +2090,8 @@ cairo_xlib_surface_create (Display     *dpy,
 {
     Screen *screen = _cairo_xlib_screen_from_visual (dpy, visual);
 
-    if (screen == NULL) {
-	_cairo_error_throw (CAIRO_STATUS_INVALID_VISUAL);
-	return (cairo_surface_t*) &_cairo_surface_nil;
-    }
+    if (screen == NULL)
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL));
 
     CAIRO_MUTEX_INITIALIZE ();
 
diff --git a/src/cairo.c b/src/cairo.c
index 6136597..676aeb1 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -3323,7 +3323,7 @@ cairo_surface_t *
 cairo_get_target (cairo_t *cr)
 {
     if (cr->status)
-	return (cairo_surface_t*) &_cairo_surface_nil;
+	return _cairo_surface_create_in_error (cr->status);
 
     return _cairo_gstate_get_original_target (cr->gstate);
 }
@@ -3352,7 +3352,7 @@ cairo_surface_t *
 cairo_get_group_target (cairo_t *cr)
 {
     if (cr->status)
-	return (cairo_surface_t*) &_cairo_surface_nil;
+	return _cairo_surface_create_in_error (cr->status);
 
     return _cairo_gstate_get_target (cr->gstate);
 }
diff --git a/src/cairoint.h b/src/cairoint.h
index c284779..889862d 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1476,10 +1476,8 @@ _cairo_stroke_style_fini (cairo_stroke_style_t *style);
 
 /* cairo-surface.c */
 
-extern const cairo_private cairo_surface_t _cairo_surface_nil;
-extern const cairo_private cairo_surface_t _cairo_surface_nil_read_error;
-extern const cairo_private cairo_surface_t _cairo_surface_nil_write_error;
-extern const cairo_private cairo_surface_t _cairo_surface_nil_file_not_found;
+cairo_private cairo_surface_t *
+_cairo_surface_create_in_error (cairo_status_t status);
 
 cairo_private cairo_status_t
 _cairo_surface_set_error (cairo_surface_t	*surface,
diff --git a/src/test-fallback-surface.c b/src/test-fallback-surface.c
index f56db45..0bac87e 100644
--- a/src/test-fallback-surface.c
+++ b/src/test-fallback-surface.c
@@ -76,13 +76,12 @@ _cairo_test_fallback_surface_create (cairo_content_t	content,
 
     backing = _cairo_image_surface_create_with_content (content, width, height);
     if (cairo_surface_status (backing))
-	return (cairo_surface_t*) &_cairo_surface_nil;
+	return backing;
 
     surface = malloc (sizeof (test_fallback_surface_t));
     if (surface == NULL) {
 	cairo_surface_destroy (backing);
-	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	return (cairo_surface_t*) &_cairo_surface_nil;
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
     }
 
     _cairo_surface_init (&surface->base, &test_fallback_surface_backend,
diff --git a/src/test-meta-surface.c b/src/test-meta-surface.c
index 4c08601..e56efcc 100644
--- a/src/test-meta-surface.c
+++ b/src/test-meta-surface.c
@@ -74,21 +74,26 @@ _cairo_test_meta_surface_create (cairo_content_t	content,
 			   int		 	height)
 {
     test_meta_surface_t *surface;
+    cairo_status_t status;
 
     surface = malloc (sizeof (test_meta_surface_t));
-    if (surface == NULL)
+    if (surface == NULL) {
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	goto FAIL;
+    }
 
     _cairo_surface_init (&surface->base, &test_meta_surface_backend,
 			 content);
 
     surface->meta = _cairo_meta_surface_create (content, width, height);
-    if (cairo_surface_status (surface->meta))
+    status = cairo_surface_status (surface->meta);
+    if (status)
 	goto FAIL_CLEANUP_SURFACE;
 
     surface->image = _cairo_image_surface_create_with_content (content,
 							       width, height);
-    if (cairo_surface_status (surface->image))
+    status = cairo_surface_status (surface->image);
+    if (status)
 	goto FAIL_CLEANUP_META;
 
     surface->image_reflects_meta = FALSE;
@@ -100,8 +105,7 @@ _cairo_test_meta_surface_create (cairo_content_t	content,
   FAIL_CLEANUP_SURFACE:
     free (surface);
   FAIL:
-    _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-    return (cairo_surface_t*) &_cairo_surface_nil;
+    return _cairo_surface_create_in_error (status);
 }
 
 static cairo_status_t
@@ -309,7 +313,7 @@ _test_meta_surface_snapshot (void *abstract_other)
 
     status = _cairo_surface_get_extents (other->image, &extents);
     if (status)
-	return (cairo_surface_t*) &_cairo_surface_nil;
+	return _cairo_surface_create_in_error (status);
 
     surface = cairo_surface_create_similar (other->image,
 					    CAIRO_CONTENT_COLOR_ALPHA,
@@ -319,7 +323,7 @@ _test_meta_surface_snapshot (void *abstract_other)
     status = _cairo_meta_surface_replay (other->meta, surface);
     if (status) {
 	cairo_surface_destroy (surface);
-	surface = (cairo_surface_t*) &_cairo_surface_nil;
+	surface = _cairo_surface_create_in_error (status);
     }
 
     return surface;
diff --git a/src/test-paginated-surface.c b/src/test-paginated-surface.c
index 7d341ad..f640b60 100644
--- a/src/test-paginated-surface.c
+++ b/src/test-paginated-surface.c
@@ -77,13 +77,12 @@ _cairo_test_paginated_surface_create_for_data (unsigned char		*data,
 								stride);
     status = cairo_surface_status (target);
     if (status)
-	return (cairo_surface_t *) &_cairo_surface_nil;
+	return target;
 
     surface = malloc (sizeof (test_paginated_surface_t));
     if (surface == NULL) {
 	cairo_surface_destroy (target);
-	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	return (cairo_surface_t *) &_cairo_surface_nil;
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
     }
 
     _cairo_surface_init (&surface->base, &test_paginated_surface_backend,
commit 5cbc45488e276cb6e6ecfa7bc7dd4fae342de85e
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Jan 16 16:29:19 2008 +0000

    [cairo-output-stream] Introduce _cairo_output_stream_create_in_error()
    
    Use a utility function to wrap an incoming error status into a new
    error stream. As a side-effect, all error streams must be destroyed as
    in the general case the caller can not distinguish between a static
    error object and one allocated to hold an unusual error status.

diff --git a/src/cairo-base85-stream.c b/src/cairo-base85-stream.c
index 97ef263..b7dc9b1 100644
--- a/src/cairo-base85-stream.c
+++ b/src/cairo-base85-stream.c
@@ -113,6 +113,9 @@ _cairo_base85_stream_create (cairo_output_stream_t *output)
 {
     cairo_base85_stream_t *stream;
 
+    if (output->status)
+	return _cairo_output_stream_create_in_error (output->status);
+
     stream = malloc (sizeof (cairo_base85_stream_t));
     if (stream == NULL) {
 	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
diff --git a/src/cairo-deflate-stream.c b/src/cairo-deflate-stream.c
index 707832d..8734b17 100644
--- a/src/cairo-deflate-stream.c
+++ b/src/cairo-deflate-stream.c
@@ -117,11 +117,8 @@ _cairo_deflate_stream_create (cairo_output_stream_t *output)
 {
     cairo_deflate_stream_t *stream;
 
-    if (output->status) {
-	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	return (cairo_output_stream_t *) &_cairo_output_stream_nil;
-    }
-
+    if (output->status)
+	return _cairo_output_stream_create_in_error (output->status);
 
     stream = malloc (sizeof (cairo_deflate_stream_t));
     if (stream == NULL) {
diff --git a/src/cairo-output-stream-private.h b/src/cairo-output-stream-private.h
index 0e7d4db..8377eca 100644
--- a/src/cairo-output-stream-private.h
+++ b/src/cairo-output-stream-private.h
@@ -87,6 +87,9 @@ _cairo_output_stream_create (cairo_write_func_t		write_func,
 			     cairo_close_func_t		close_func,
 			     void			*closure);
 
+cairo_private cairo_output_stream_t *
+_cairo_output_stream_create_in_error (cairo_status_t status);
+
 /* Returns the final status value associated with this object, just
  * before its last gasp. This final status value will capture any
  * status failure returned by the stream's close_func as well. */
diff --git a/src/cairo-output-stream.c b/src/cairo-output-stream.c
index 6451b0f..2cb9e03 100644
--- a/src/cairo-output-stream.c
+++ b/src/cairo-output-stream.c
@@ -134,6 +134,29 @@ _cairo_output_stream_create (cairo_write_func_t		write_func,
     return &stream->base;
 }
 
+cairo_output_stream_t *
+_cairo_output_stream_create_in_error (cairo_status_t status)
+{
+    cairo_output_stream_t *stream;
+
+    /* check for the common ones */
+    if (status == CAIRO_STATUS_NO_MEMORY)
+	return (cairo_output_stream_t *) &_cairo_output_stream_nil;
+    if (status == CAIRO_STATUS_WRITE_ERROR)
+	return (cairo_output_stream_t *) &_cairo_output_stream_nil_write_error;
+
+    stream = malloc (sizeof (cairo_output_stream_t));
+    if (stream == NULL) {
+	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+	return (cairo_output_stream_t *) &_cairo_output_stream_nil;
+    }
+
+    _cairo_output_stream_init (stream, NULL, NULL);
+    stream->status = status;
+
+    return stream;
+}
+
 cairo_status_t
 _cairo_output_stream_close (cairo_output_stream_t *stream)
 {
@@ -165,8 +188,7 @@ _cairo_output_stream_destroy (cairo_output_stream_t *stream)
 {
     cairo_status_t status;
 
-    if (stream == NULL)
-	return _cairo_error (CAIRO_STATUS_NULL_POINTER);
+    assert (stream != NULL);
 
     if (stream == &_cairo_output_stream_nil ||
 	stream == &_cairo_output_stream_nil_write_error)
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index e2695bf..93c9055 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -176,6 +176,9 @@ _word_wrap_stream_create (cairo_output_stream_t *output, int max_column)
 {
     word_wrap_stream_t *stream;
 
+    if (output->status)
+	return _cairo_output_stream_create_in_error (output->status);
+
     stream = malloc (sizeof (word_wrap_stream_t));
     if (stream == NULL) {
 	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
@@ -301,7 +304,7 @@ _cairo_ps_surface_emit_path (cairo_ps_surface_t	   *surface,
     word_wrap = _word_wrap_stream_create (stream, 79);
     status = _cairo_output_stream_get_status (word_wrap);
     if (status)
-	return status;
+	return _cairo_output_stream_destroy (word_wrap);
 
     path_info.surface = surface;
     path_info.stream = word_wrap;
@@ -3255,9 +3258,10 @@ _cairo_ps_surface_show_glyphs (void		     *abstract_surface,
             _cairo_output_stream_printf (surface->stream, "<%02x> S\n", glyph_ids[i].glyph_id);
         } else {
             word_wrap = _word_wrap_stream_create (surface->stream, 79);
-	    status = _cairo_output_stream_get_status (word_wrap);
-	    if (status)
+	    if (_cairo_output_stream_get_status (word_wrap)) {
+		status = _cairo_output_stream_destroy (word_wrap);
 		goto fail;
+	    }
 
             _cairo_output_stream_printf (word_wrap, "<");
             for (j = i; j < last+1; j++)
diff --git a/src/cairo-type1-fallback.c b/src/cairo-type1-fallback.c
index 3532692..0ca4998 100644
--- a/src/cairo-type1-fallback.c
+++ b/src/cairo-type1-fallback.c
@@ -601,10 +601,8 @@ cairo_type1_font_write_private_dict (cairo_type1_font_t *font,
         cairo_type1_write_stream_encrypted,
         NULL,
         font);
-    if (encrypted_output == NULL) {
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto fail;
-    }
+    if (_cairo_output_stream_get_status (encrypted_output))
+	return  _cairo_output_stream_destroy (encrypted_output);
 
     /* Note: the first four spaces at the start of this private dict
      * are the four "random" bytes of plaintext required by the
@@ -697,6 +695,8 @@ cairo_type1_font_generate (cairo_type1_font_t *font, const char *name)
 	return status;
 
     font->output = _cairo_output_stream_create (cairo_type1_write_stream, NULL, font);
+    if (_cairo_output_stream_get_status (font->output))
+	return _cairo_output_stream_destroy (font->output);
 
     status = cairo_type1_font_write (font, name);
     if (status)
diff --git a/src/cairo-type1-subset.c b/src/cairo-type1-subset.c
index 2d57368..bc46954 100644
--- a/src/cairo-type1-subset.c
+++ b/src/cairo-type1-subset.c
@@ -1126,9 +1126,10 @@ cairo_type1_font_subset_generate (void       *abstract_font,
 	goto fail;
 
     font->output = _cairo_output_stream_create (type1_font_write, NULL, font);
-    status = _cairo_output_stream_get_status (font->output);
-    if (status)
+    if (_cairo_output_stream_get_status (font->output)) {
+	status = _cairo_output_stream_destroy (font->output);
 	goto fail;
+    }
 
     status = cairo_type1_font_subset_write (font, name);
     if (status)
commit 2c10c7559db11ccf511e119f4d4fb2da97508786
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Jan 16 13:37:48 2008 +0000

    [Makefile.am] Add -I$(builddir) for .c.i target
    
    Updated the CPP command so that it can find <cairo-features.h> in the
    local build directory.

diff --git a/src/Makefile.am b/src/Makefile.am
index 172e062..8f6d4f1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -323,7 +323,7 @@ EXTRA_DIST += $(TESTS) check-has-hidden-symbols.c
 # The pre-processed result is used by check-{def,plt}.sh to determine whether
 # cairo has been compiled with symbol hiding.
 .c.i: $(cairoinclude_HEADERS) $(nodist_cairoinclude_HEADERS) cairoint.h $(top_builddir)/config.h
-	$(CPP) -DHAVE_CONFIG_H -I$(top_builddir) $(libcairo_la_CFLAGS) $< -o $@
+	$(CPP) -DHAVE_CONFIG_H -I$(top_builddir) -I$(builddir) $(libcairo_la_CFLAGS) $< -o $@
 
 SPARSE = sparse
 sparse:


More information about the cairo-commit mailing list