[cairo-commit] src/cairo-png.c test/create-from-png.c
Chris Wilson
ickle at kemper.freedesktop.org
Tue Sep 25 15:47:29 PDT 2007
src/cairo-png.c | 57 ++++++++++++++++++++++-----------
test/create-from-png.c | 84 +++++++++++++++++++++++++++++++++++++++++++------
2 files changed, 113 insertions(+), 28 deletions(-)
New commits:
diff-tree 1469de5211e84e40490fa612538986768748bd55 (from f1d84271d363cc80cdef92ec9cac2cf29783bfe0)
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Tue Sep 25 23:35:25 2007 +0100
[cairo-png] Propagate error from read and write funcs.
Use the png_struct->error_ptr to propagate the error status from the
user/stdio read and write functions through the png_error() to the
cairo_surface_write_to_png*() and cairo_surface_read_from_png*()
functions. From there the error is returned back to the user either
directly or as the most appropriate error surface.
(Fixes https://bugs.freedesktop.org/show_bug.cgi?id=6909)
diff --git a/src/cairo-png.c b/src/cairo-png.c
index eaecbbd..8ad4c9a 100644
--- a/src/cairo-png.c
+++ b/src/cairo-png.c
@@ -91,8 +91,13 @@ static void
png_simple_error_callback (png_structp png_save_ptr,
png_const_charp error_msg)
{
- _cairo_error (CAIRO_STATUS_NO_MEMORY);
- longjmp (png_save_ptr->jmpbuf, CAIRO_STATUS_NO_MEMORY);
+ cairo_status_t *error = png_get_error_ptr (png_save_ptr);
+
+ /* default to the most likely error */
+ if (*error == CAIRO_STATUS_SUCCESS)
+ *error = CAIRO_STATUS_NO_MEMORY;
+
+ longjmp (png_save_ptr->jmpbuf, 1);
}
static void
@@ -108,7 +113,7 @@ write_png (cairo_surface_t *surface,
void *closure)
{
int i;
- volatile cairo_status_t status = CAIRO_STATUS_SUCCESS;
+ cairo_status_t status;
cairo_image_surface_t *image;
void *image_extra;
png_struct *png;
@@ -129,7 +134,7 @@ write_png (cairo_surface_t *surface,
return CAIRO_STATUS_SURFACE_TYPE_MISMATCH;
if (image->height && image->width) {
- rows = _cairo_malloc_ab (image->height, sizeof(png_byte*));
+ rows = _cairo_malloc_ab (image->height, sizeof (png_byte*));
if (rows == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
goto BAIL1;
@@ -139,7 +144,7 @@ write_png (cairo_surface_t *surface,
rows[i] = (png_byte *) image->data + i * image->stride;
}
- png = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL,
+ png = png_create_write_struct (PNG_LIBPNG_VER_STRING, &status,
png_simple_error_callback,
png_simple_warning_callback);
if (png == NULL) {
@@ -153,8 +158,7 @@ write_png (cairo_surface_t *surface,
goto BAIL3;
}
- status = setjmp (png_jmpbuf (png));
- if (status)
+ if (setjmp (png_jmpbuf (png)))
goto BAIL3;
png_set_write_fn (png, closure, write_func, NULL);
@@ -234,8 +238,11 @@ stdio_write_func (png_structp png, png_b
size_t ret = fwrite (data, 1, size, fp);
size -= ret;
data += ret;
- if (size && ferror (fp))
- png_error(png, "Write Error");
+ if (size && ferror (fp)) {
+ cairo_status_t *error = png_get_error_ptr (png);
+ *error = CAIRO_STATUS_WRITE_ERROR;
+ png_error (png, NULL);
+ }
}
}
@@ -286,8 +293,11 @@ stream_write_func (png_structp png, png_
png_closure = png_get_io_ptr (png);
status = png_closure->write_func (png_closure->closure, data, size);
- if (status)
- png_error(png, "Write Error");
+ if (status) {
+ cairo_status_t *error = png_get_error_ptr (png);
+ *error = status;
+ png_error (png, NULL);
+ }
}
/**
@@ -369,10 +379,11 @@ read_png (png_rw_ptr read_func,
int depth, color_type, interlace;
unsigned int i;
unsigned int pixel_size;
+ cairo_status_t status;
/* XXX: Perhaps we'll want some other error handlers? */
png = png_create_read_struct (PNG_LIBPNG_VER_STRING,
- NULL,
+ &status,
png_simple_error_callback,
png_simple_warning_callback);
if (png == NULL)
@@ -384,8 +395,10 @@ read_png (png_rw_ptr read_func,
png_set_read_fn (png, closure, read_func);
+ status = CAIRO_STATUS_SUCCESS;
if (setjmp (png_jmpbuf (png))) {
- surface = (cairo_surface_t*) &_cairo_surface_nil_read_error;
+ if (status != CAIRO_STATUS_NO_MEMORY)
+ surface = (cairo_surface_t*) &_cairo_surface_nil_read_error;
goto BAIL;
}
@@ -408,7 +421,7 @@ read_png (png_rw_ptr read_func,
png_set_gray_1_2_4_to_8 (png);
#endif
/* transform transparency to alpha */
- if (png_get_valid(png, info, PNG_INFO_tRNS))
+ if (png_get_valid (png, info, PNG_INFO_tRNS))
png_set_tRNS_to_alpha (png);
if (depth == 16)
@@ -436,7 +449,7 @@ read_png (png_rw_ptr read_func,
if (data == NULL)
goto BAIL;
- row_pointers = _cairo_malloc_ab (png_height, sizeof(char *));
+ row_pointers = _cairo_malloc_ab (png_height, sizeof (char *));
if (row_pointers == NULL)
goto BAIL;
@@ -479,8 +492,11 @@ stdio_read_func (png_structp png, png_by
size_t ret = fread (data, 1, size, fp);
size -= ret;
data += ret;
- if (size && ferror (fp))
- png_error(png, "Read Error");
+ if (size && ferror (fp)) {
+ cairo_status_t *error = png_get_error_ptr (png);
+ *error = CAIRO_STATUS_READ_ERROR;
+ png_error (png, NULL);
+ }
}
}
@@ -541,8 +557,11 @@ stream_read_func (png_structp png, png_b
png_closure = png_get_io_ptr (png);
status = png_closure->read_func (png_closure->closure, data, size);
- if (status)
- png_error(png, "Read Error");
+ if (status) {
+ cairo_status_t *error = png_get_error_ptr (png);
+ *error = status;
+ png_error (png, NULL);
+ }
}
/**
diff --git a/test/create-from-png.c b/test/create-from-png.c
index 4aefc34..fe08b30 100644
--- a/test/create-from-png.c
+++ b/test/create-from-png.c
@@ -39,6 +39,18 @@ cairo_test_t test = {
draw
};
+static cairo_status_t
+no_memory_error (void *closure, unsigned char *data, unsigned int size)
+{
+ return CAIRO_STATUS_NO_MEMORY;
+}
+
+static cairo_status_t
+read_error (void *closure, unsigned char *data, unsigned int size)
+{
+ return CAIRO_STATUS_READ_ERROR;
+}
+
static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
@@ -46,18 +58,10 @@ draw (cairo_t *cr, int width, int height
char *filename;
cairo_surface_t *surface;
- surface = cairo_image_surface_create_from_png ("___THIS_FILE_DOES_NOT_EXIST___");
- if (cairo_surface_status (surface) != CAIRO_STATUS_FILE_NOT_FOUND) {
- cairo_test_log ("Error: expected \"file not found\", but got: %s\n",
- cairo_status_to_string (cairo_surface_status (surface)));
- return CAIRO_TEST_FAILURE;
- }
-
xasprintf (&filename, "%s/%s", srcdir ? srcdir : ".",
"create-from-png-ref.png");
surface = cairo_image_surface_create_from_png (filename);
-
if (cairo_surface_status (surface)) {
cairo_test_log ("Error reading PNG image %s: %s\n",
filename,
@@ -65,7 +69,6 @@ draw (cairo_t *cr, int width, int height
free (filename);
return CAIRO_TEST_FAILURE;
}
-
free (filename);
cairo_set_source_surface (cr, surface, 0, 0);
@@ -79,5 +82,68 @@ draw (cairo_t *cr, int width, int height
int
main (void)
{
+ char *srcdir = getenv ("srcdir");
+ char *filename;
+ cairo_surface_t *surface;
+ cairo_status_t status;
+
+ surface = cairo_image_surface_create_from_png ("___THIS_FILE_DOES_NOT_EXIST___");
+ if (cairo_surface_status (surface) != CAIRO_STATUS_FILE_NOT_FOUND) {
+ cairo_test_log ("Error: expected \"file not found\", but got: %s\n",
+ cairo_status_to_string (cairo_surface_status (surface)));
+ cairo_surface_destroy (surface);
+ return CAIRO_TEST_FAILURE;
+ }
+
+ surface = cairo_image_surface_create_from_png_stream (no_memory_error, NULL);
+ if (cairo_surface_status (surface) != CAIRO_STATUS_NO_MEMORY) {
+ cairo_test_log ("Error: expected \"out of memory\", but got: %s\n",
+ cairo_status_to_string (cairo_surface_status (surface)));
+ cairo_surface_destroy (surface);
+ return CAIRO_TEST_FAILURE;
+ }
+
+ surface = cairo_image_surface_create_from_png_stream (read_error, NULL);
+ if (cairo_surface_status (surface) != CAIRO_STATUS_READ_ERROR) {
+ cairo_test_log ("Error: expected \"read error\", but got: %s\n",
+ cairo_status_to_string (cairo_surface_status (surface)));
+ cairo_surface_destroy (surface);
+ return CAIRO_TEST_FAILURE;
+ }
+
+ /* cheekily test error propagation from the user write funcs as well ... */
+ xasprintf (&filename, "%s/%s", srcdir ? srcdir : ".",
+ "create-from-png-ref.png");
+
+ surface = cairo_image_surface_create_from_png (filename);
+ if (cairo_surface_status (surface)) {
+ cairo_test_log ("Error reading PNG image %s: %s\n",
+ filename,
+ cairo_status_to_string (cairo_surface_status (surface)));
+ free (filename);
+ return CAIRO_TEST_FAILURE;
+ }
+ free (filename);
+
+ status = cairo_surface_write_to_png_stream (surface,
+ (cairo_write_func_t) no_memory_error,
+ NULL);
+ if (status != CAIRO_STATUS_NO_MEMORY) {
+ cairo_test_log ("Error: expected \"out of memory\", but got: %s\n",
+ cairo_status_to_string (status));
+ cairo_surface_destroy (surface);
+ return CAIRO_TEST_FAILURE;
+ }
+ status = cairo_surface_write_to_png_stream (surface,
+ (cairo_write_func_t) read_error,
+ NULL);
+ if (status != CAIRO_STATUS_READ_ERROR) {
+ cairo_test_log ("Error: expected \"read error\", but got: %s\n",
+ cairo_status_to_string (status));
+ cairo_surface_destroy (surface);
+ return CAIRO_TEST_FAILURE;
+ }
+ cairo_surface_destroy (surface);
+
return cairo_test (&test);
}
More information about the cairo-commit
mailing list