summaryrefslogtreecommitdiff
path: root/src/cairo-png.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cairo-png.c')
-rw-r--r--src/cairo-png.c60
1 files changed, 42 insertions, 18 deletions
diff --git a/src/cairo-png.c b/src/cairo-png.c
index 532054e51..afe9e6ea1 100644
--- a/src/cairo-png.c
+++ b/src/cairo-png.c
@@ -36,6 +36,7 @@
*/
#include <png.h>
+#include <errno.h>
#include "cairoint.h"
/* Unpremultiplies data and converts native endian ARGB => RGBA bytes */
@@ -315,19 +316,15 @@ static cairo_surface_t *
read_png (png_rw_ptr read_func,
void *closure)
{
- cairo_surface_t *surface;
- png_byte *data;
+ cairo_surface_t *surface = (cairo_surface_t*) &_cairo_surface_nil;
+ png_byte *data = NULL;
int i;
- png_struct *png;
+ png_struct *png = NULL;
png_info *info;
png_uint_32 png_width, png_height, stride;
int depth, color_type, interlace;
unsigned int pixel_size;
- png_byte **row_pointers;
-
- surface = NULL;
- data = NULL;
- row_pointers = NULL;
+ png_byte **row_pointers = NULL;
/* XXX: Perhaps we'll want some other error handlers? */
png = png_create_read_struct (PNG_LIBPNG_VER_STRING,
@@ -335,7 +332,7 @@ read_png (png_rw_ptr read_func,
NULL,
NULL);
if (png == NULL)
- return NULL;
+ goto BAIL;
info = png_create_info_struct (png);
if (info == NULL)
@@ -343,8 +340,10 @@ read_png (png_rw_ptr read_func,
png_set_read_fn (png, closure, read_func);
- if (setjmp (png_jmpbuf (png)))
+ if (setjmp (png_jmpbuf (png))) {
+ surface = (cairo_surface_t*) &_cairo_surface_nil_read_error;
goto BAIL;
+ }
png_read_info (png, info);
@@ -402,13 +401,22 @@ read_png (png_rw_ptr read_func,
surface = cairo_image_surface_create_for_data (data,
CAIRO_FORMAT_ARGB32,
png_width, png_height, stride);
+ if (surface->status)
+ goto BAIL;
+
_cairo_image_surface_assume_ownership_of_data ((cairo_image_surface_t*)surface);
data = NULL;
BAIL:
- free (row_pointers);
- free (data);
- png_destroy_read_struct (&png, &info, NULL);
+ if (row_pointers)
+ free (row_pointers);
+ if (data)
+ free (data);
+ if (png)
+ png_destroy_read_struct (&png, &info, NULL);
+
+ if (surface->status)
+ _cairo_error (surface->status);
return surface;
}
@@ -431,8 +439,13 @@ stdio_read_func (png_structp png, png_bytep data, png_size_t size)
* given PNG file.
*
* Return value: a new #cairo_surface_t initialized with the contents
- * of the PNG file or %NULL if the file is not a valid PNG file or
- * memory could not be allocated for the operation.
+ * of the PNG file, or a "nil" surface if any error occurred. A nil
+ * surface can be checked for with cairo_surface_status(surface) which
+ * may return one of the following values:
+ *
+ * CAIRO_STATUS_NO_MEMORY
+ * CAIRO_STATUS_FILE_NOT_FOUND
+ * CAIRO_STATUS_READ_ERROR
**/
cairo_surface_t *
cairo_image_surface_create_from_png (const char *filename)
@@ -441,8 +454,19 @@ cairo_image_surface_create_from_png (const char *filename)
cairo_surface_t *surface;
fp = fopen (filename, "rb");
- if (fp == NULL)
- return NULL;
+ if (fp == NULL) {
+ switch (errno) {
+ case ENOMEM:
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_surface_t*) &_cairo_surface_nil;
+ case ENOENT:
+ _cairo_error (CAIRO_STATUS_FILE_NOT_FOUND);
+ return (cairo_surface_t*) &_cairo_surface_nil_file_not_found;
+ default:
+ _cairo_error (CAIRO_STATUS_READ_ERROR);
+ return (cairo_surface_t*) &_cairo_surface_nil_read_error;
+ }
+ }
surface = read_png (stdio_read_func, fp);
@@ -489,6 +513,6 @@ cairo_image_surface_create_from_png_stream (cairo_read_func_t read_func,
png_closure.read_func = read_func;
png_closure.closure = closure;
- return read_png (stream_read_func, &closure);
+ return read_png (stream_read_func, &png_closure);
}