diff options
author | Havoc Pennington <hp@redhat.com> | 2000-10-18 18:42:54 +0000 |
---|---|---|
committer | Havoc Pennington <hp@src.gnome.org> | 2000-10-18 18:42:54 +0000 |
commit | 7a4c68938789206bfec3c6d15cc4bb922daf6443 (patch) | |
tree | e5f031fc609e50a8b7b12e7d6abf63cc78cc88e7 /gdk-pixbuf/io-png.c | |
parent | 7420908815651a1ff2ceb1c0fb5e92fe9b260619 (diff) | |
download | gtk+-7a4c68938789206bfec3c6d15cc4bb922daf6443.tar.gz |
Some updates
2000-10-18 Havoc Pennington <hp@redhat.com>
* gtk/gtk-sections.txt: Some updates
* gdk/gdk-sections.txt: remove GdkPixbufAlphaMode
* gdk-pixbuf/gdk-pixbuf-sections.txt: Add new API, remove
GdkPixbufClass/GdkAnimationClass since those are private
* gdk-pixbuf/Makefile.am (IGNORE_HFILES): ignore more headers
2000-10-18 Havoc Pennington <hp@redhat.com>
* gtk/gtktextiter.c (gtk_text_iter_forward_to_newline): Fix a bug
where any number of empty lines would get skipped
* gtk/gtktextiter.h: Remove padding from GtkTextIter; live on the
edge.
* gtk/gtktextiter.c (gtk_text_iter_make_surreal): enhance the
warning about invalid iterators (explain more thoroughly)
(gtk_text_iter_in_region): rename gtk_text_iter_in_range
* gtk/gtktextview.c (FOCUS_EDGE_WIDTH): Make focus rectangle less
big
* demos/*.c: Add error handling
* gtk/gtktextbuffer.c: don't modify const iterators
* gtk/gdk-pixbuf-loader.c: Add full error handling here
* gtk/gtkimage.c (gtk_image_set_from_file): ignore errors
on file load
* gtk/gtkiconfactory.c: Update to reflect addition of error
handling to gdk-pixbuf loaders
2000-10-16 Havoc Pennington <hp@redhat.com>
* gdk-pixbuf-io.c (gdk_pixbuf_get_module)
(gdk_pixbuf_get_named_module) (gdk_pixbuf_load_module):
add error reporting here also
* make-inline-pixbuf.c (main): use GError
* io-xpm.c: include unistd.h
* gdk-pixbuf-util.c: include string.h
* io-*.c: add error reporting
* gdk-pixbuf-animation.c (gdk_pixbuf_animation_new_from_file): add
error reporting
* gdk-pixbuf-io.c (gdk_pixbuf_new_from_file): Add error reporting
* gdk-pixbuf-io.h: Add GError** to load_increment and load
methods
* gdk-pixbuf-io.c (gdk_pixbuf_save) (gdk_pixbuf_savev): return
a G_FILE_ERROR if we fail to write or close the file.
* gdk-pixbuf.h: remove GDK_PIXBUF_ERROR_IO, instead we'll use
G_FILE_ERROR_*. Rename enum to GdkPixbufError, properly following
the GError naming rules. Add GError** to load functions.
Diffstat (limited to 'gdk-pixbuf/io-png.c')
-rw-r--r-- | gdk-pixbuf/io-png.c | 135 |
1 files changed, 116 insertions, 19 deletions
diff --git a/gdk-pixbuf/io-png.c b/gdk-pixbuf/io-png.c index 33fa2cf68f..bd945f7943 100644 --- a/gdk-pixbuf/io-png.c +++ b/gdk-pixbuf/io-png.c @@ -140,6 +140,38 @@ setup_png_transformations(png_structp png_read_ptr, png_infop png_info_ptr, #endif } +static void +png_simple_error_callback(png_structp png_save_ptr, + png_const_charp error_msg) +{ + GError **error; + + error = png_get_error_ptr(png_save_ptr); + + /* I don't trust libpng to call the error callback only once, + * so check for already-set error + */ + if (error && *error == NULL) { + g_set_error (error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_FAILED, + _("Fatal error saving PNG image file: %s"), + error_msg); + } +} + +static void +png_simple_warning_callback(png_structp png_save_ptr, + png_const_charp warning_msg) +{ + /* Don't print anything; we should not be dumping junk to + * stderr, since that may be bad for some apps. If it's + * important enough to display, we need to add a GError + * **warning return location wherever we have an error return + * location. + */ +} + /* Destroy notification function for the pixbuf */ static void free_buffer (guchar *pixels, gpointer data) @@ -149,7 +181,7 @@ free_buffer (guchar *pixels, gpointer data) /* Shared library entry point */ GdkPixbuf * -gdk_pixbuf__png_image_load (FILE *f) +gdk_pixbuf__png_image_load (FILE *f, GError **error) { png_structp png_ptr; png_infop info_ptr, end_info; @@ -159,7 +191,10 @@ gdk_pixbuf__png_image_load (FILE *f) png_bytepp rows; guchar *pixels; - png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, + error, + png_simple_error_callback, + png_simple_warning_callback); if (!png_ptr) return NULL; @@ -197,6 +232,16 @@ gdk_pixbuf__png_image_load (FILE *f) pixels = malloc (w * h * bpp); if (!pixels) { + /* Check error NULL, normally this would be broken, + * but libpng makes me want to code defensively. + */ + if (error && *error == NULL) { + g_set_error (error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, + _("Insufficient memory to load PNG file")); + } + png_destroy_read_struct (&png_ptr, &info_ptr, &end_info); return NULL; } @@ -273,6 +318,7 @@ struct _LoadContext { guint fatal_error_occurred : 1; + GError **error; }; gpointer @@ -280,7 +326,8 @@ gdk_pixbuf__png_image_begin_load (ModulePreparedNotifyFunc prepare_func, ModuleUpdatedNotifyFunc update_func, ModuleFrameDoneNotifyFunc frame_done_func, ModuleAnimationDoneNotifyFunc anim_done_func, - gpointer user_data) + gpointer user_data, + GError **error) { LoadContext* lc; @@ -297,6 +344,7 @@ gdk_pixbuf__png_image_begin_load (ModulePreparedNotifyFunc prepare_func, lc->first_pass_seen_in_chunk = -1; lc->last_pass_seen_in_chunk = -1; lc->max_row_seen_in_chunk = -1; + lc->error = error; /* Create the main PNG context struct */ @@ -308,13 +356,15 @@ gdk_pixbuf__png_image_begin_load (ModulePreparedNotifyFunc prepare_func, if (lc->png_read_ptr == NULL) { g_free(lc); + /* error callback should have set the error */ return NULL; } - + if (setjmp (lc->png_read_ptr->jmpbuf)) { if (lc->png_info_ptr) png_destroy_read_struct(&lc->png_read_ptr, NULL, NULL); g_free(lc); + /* error callback should have set the error */ return NULL; } @@ -325,6 +375,7 @@ gdk_pixbuf__png_image_begin_load (ModulePreparedNotifyFunc prepare_func, if (lc->png_info_ptr == NULL) { png_destroy_read_struct(&lc->png_read_ptr, NULL, NULL); g_free(lc); + /* error callback should have set the error */ return NULL; } @@ -335,6 +386,11 @@ gdk_pixbuf__png_image_begin_load (ModulePreparedNotifyFunc prepare_func, png_end_callback); + /* We don't want to keep modifying error after returning here, + * it may no longer be valid. + */ + lc->error = NULL; + return lc; } @@ -352,7 +408,8 @@ gdk_pixbuf__png_image_stop_load (gpointer context) } gboolean -gdk_pixbuf__png_image_load_increment(gpointer context, guchar *buf, guint size) +gdk_pixbuf__png_image_load_increment(gpointer context, guchar *buf, guint size, + GError **error) { LoadContext* lc = context; @@ -364,17 +421,20 @@ gdk_pixbuf__png_image_load_increment(gpointer context, guchar *buf, guint size) lc->first_pass_seen_in_chunk = -1; lc->last_pass_seen_in_chunk = -1; lc->max_row_seen_in_chunk = -1; + lc->error = error; /* Invokes our callbacks as needed */ if (setjmp (lc->png_read_ptr->jmpbuf)) { + lc->error = NULL; return FALSE; } else { png_process_data(lc->png_read_ptr, lc->png_info_ptr, buf, size); } - if (lc->fatal_error_occurred) + if (lc->fatal_error_occurred) { + lc->error = NULL; return FALSE; - else { + } else { if (lc->first_row_seen_in_chunk >= 0) { /* We saw at least one row */ gint pass_diff = lc->last_pass_seen_in_chunk - lc->first_pass_seen_in_chunk; @@ -417,6 +477,8 @@ gdk_pixbuf__png_image_load_increment(gpointer context, guchar *buf, guint size) lc->notify_user_data); } } + + lc->error = NULL; return TRUE; } @@ -437,7 +499,6 @@ png_info_callback (png_structp png_read_ptr, if (lc->fatal_error_occurred) return; - setup_png_transformations(lc->png_read_ptr, lc->png_info_ptr, @@ -458,6 +519,13 @@ png_info_callback (png_structp png_read_ptr, if (lc->pixbuf == NULL) { /* Failed to allocate memory */ lc->fatal_error_occurred = TRUE; + if (lc->error && *lc->error == NULL) { + g_set_error (lc->error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, + _("Insufficient memory to store a %ld by %ld image; try exiting some applications to reduce memory usage"), + width, height); + } return; } @@ -521,8 +589,17 @@ png_error_callback(png_structp png_read_ptr, lc = png_get_error_ptr(png_read_ptr); lc->fatal_error_occurred = TRUE; - - fprintf(stderr, "Fatal error loading PNG: %s\n", error_msg); + + /* I don't trust libpng to call the error callback only once, + * so check for already-set error + */ + if (lc->error && *lc->error == NULL) { + g_set_error (lc->error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_CORRUPT_IMAGE, + _("Fatal error reading PNG image file: %s"), + error_msg); + } } static void @@ -532,12 +609,18 @@ png_warning_callback(png_structp png_read_ptr, LoadContext* lc; lc = png_get_error_ptr(png_read_ptr); - - fprintf(stderr, "Warning loading PNG: %s\n", warning_msg); + + /* Don't print anything; we should not be dumping junk to + * stderr, since that may be bad for some apps. If it's + * important enough to display, we need to add a GError + * **warning return location wherever we have an error return + * location. + */ } /* Save */ + gboolean gdk_pixbuf__png_image_save (FILE *f, GdkPixbuf *pixbuf, @@ -545,8 +628,6 @@ gdk_pixbuf__png_image_save (FILE *f, gchar **values, GError **error) { - /* FIXME error handling is broken */ - png_structp png_ptr; png_infop info_ptr; guchar *ptr; @@ -583,7 +664,9 @@ gdk_pixbuf__png_image_save (FILE *f, pixels = gdk_pixbuf_get_pixels (pixbuf); png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, - NULL, NULL, NULL); + error, + png_simple_error_callback, + png_simple_warning_callback); g_return_val_if_fail (png_ptr != NULL, FALSE); @@ -599,8 +682,8 @@ gdk_pixbuf__png_image_save (FILE *f, png_init_io (png_ptr, f); if (has_alpha) { png_set_IHDR (png_ptr, info_ptr, w, h, bpc, - PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); #ifdef WORDS_BIGENDIAN png_set_swap_alpha (png_ptr); #else @@ -608,9 +691,23 @@ gdk_pixbuf__png_image_save (FILE *f, #endif } else { png_set_IHDR (png_ptr, info_ptr, w, h, bpc, - PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); data = malloc (w * 3 * sizeof (char)); + + if (data == NULL) { + /* Check error NULL, normally this would be broken, + * but libpng makes me want to code defensively. + */ + if (error && *error == NULL) { + g_set_error (error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, + _("Insufficient memory to save PNG file")); + } + png_destroy_write_struct (&png_ptr, (png_infopp) NULL); + return FALSE; + } } sig_bit.red = bpc; sig_bit.green = bpc; |