Mercurial > pidgin.yaz
diff pidgin/gtkutils.c @ 32156:1693114a2655
applied changes from 6cf1aee8ac5e3c836af832eaf26ccedd611dc70b
through e802003adbf0be4496de3de8ac03b47c1e471d00
Original commit message:
Start looking at the GError parameter every time we call these functions:
- gdk_pixbuf_loader_write
- gdk_pixbuf_loader_close
- gdk_pixbuf_new_from_file
- gdk_pixbuf_new_from_file_at_size
- gdk_pixbuf_new_from_file_at_scale
There are times when gdkpixbuf returns a semi-invalid GdkPixbuf object and
also sets the GError. If this happens we want to discard and ignore the
GdkPixbuf object because it can cause problems. For example, calling
gdk_pixbuf_scale_simple() causes gdkpixbuf to rapidly consume memory in
an infinite loop. And that's bad.
This commit adds some helper functions to gtkutils.[c|h] that make it a
little easier to check the GError value. We should use them everywhere
we call any of the above functions.
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Wed, 22 Jun 2011 07:09:42 +0000 |
parents | d72d728226dc |
children | accce7b79737 70ff869a74d1 |
line wrap: on
line diff
--- a/pidgin/gtkutils.c Wed Jun 22 02:48:46 2011 +0000 +++ b/pidgin/gtkutils.c Wed Jun 22 07:09:42 2011 +0000 @@ -615,7 +615,7 @@ tmp, NULL); g_free(tmp); - pixbuf = gdk_pixbuf_new_from_file(filename, NULL); + pixbuf = pidgin_pixbuf_new_from_file(filename); g_free(filename); return pixbuf; @@ -704,7 +704,7 @@ "16", "google-talk.png", NULL); GtkWidget *item; - pixbuf = gdk_pixbuf_new_from_file(filename, NULL); + pixbuf = pidgin_pixbuf_new_from_file(filename); g_free(filename); gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu), @@ -723,7 +723,7 @@ "16", "facebook.png", NULL); GtkWidget *item; - pixbuf = gdk_pixbuf_new_from_file(filename, NULL); + pixbuf = pidgin_pixbuf_new_from_file(filename); g_free(filename); gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu), @@ -1593,7 +1593,7 @@ } /* Are we dealing with an image? */ - pb = gdk_pixbuf_new_from_file(filename, NULL); + pb = pidgin_pixbuf_new_from_file(filename); if (pb) { _DndData *data = g_malloc(sizeof(_DndData)); gboolean ft = FALSE, im = FALSE; @@ -2265,7 +2265,7 @@ filename = gtk_file_chooser_get_preview_filename( GTK_FILE_CHOOSER(dialog->icon_filesel)); - if (!filename || g_stat(filename, &st) || !(pixbuf = gdk_pixbuf_new_from_file(filename, NULL))) + if (!filename || g_stat(filename, &st) || !(pixbuf = pidgin_pixbuf_new_from_file(filename))) { gtk_image_set_from_pixbuf(GTK_IMAGE(dialog->icon_preview), NULL); gtk_label_set_markup(GTK_LABEL(dialog->icon_text), ""); @@ -3086,17 +3086,134 @@ #endif } -GdkPixbuf * pidgin_pixbuf_from_imgstore(PurpleStoredImage *image) +static GObject *pidgin_pixbuf_from_data_helper(const guchar *buf, gsize count, gboolean animated) +{ + GObject *pixbuf; + GdkPixbufLoader *loader; + GError *error = NULL; + + loader = gdk_pixbuf_loader_new(); + + if (!gdk_pixbuf_loader_write(loader, buf, count, &error) || error) { + purple_debug_warning("gtkutils", "gdk_pixbuf_loader_write() " + "failed with size=%zu: %s\n", count, + error ? error->message : "(no error message)"); + if (error) + g_error_free(error); + g_object_unref(G_OBJECT(loader)); + return NULL; + } + + if (!gdk_pixbuf_loader_close(loader, &error) || error) { + purple_debug_warning("gtkutils", "gdk_pixbuf_loader_close() " + "failed for image of size %zu: %s\n", count, + error ? error->message : "(no error message)"); + if (error) + g_error_free(error); + g_object_unref(G_OBJECT(loader)); + return NULL; + } + + if (animated) + pixbuf = G_OBJECT(gdk_pixbuf_loader_get_animation(loader)); + else + pixbuf = G_OBJECT(gdk_pixbuf_loader_get_pixbuf(loader)); + if (!pixbuf) { + purple_debug_warning("gtkutils", "%s() returned NULL for image " + "of size %zu\n", + animated ? "gdk_pixbuf_loader_get_animation" + : "gdk_pixbuf_loader_get_pixbuf", count); + g_object_unref(G_OBJECT(loader)); + return NULL; + } + + g_object_ref(pixbuf); + g_object_unref(G_OBJECT(loader)); + + return pixbuf; +} + +GdkPixbuf *pidgin_pixbuf_from_data(const guchar *buf, gsize count) +{ + return GDK_PIXBUF(pidgin_pixbuf_from_data_helper(buf, count, FALSE)); +} + +GdkPixbufAnimation *pidgin_pixbuf_anim_from_data(const guchar *buf, gsize count) +{ + return GDK_PIXBUF_ANIMATION(pidgin_pixbuf_from_data_helper(buf, count, TRUE)); +} + +GdkPixbuf *pidgin_pixbuf_from_imgstore(PurpleStoredImage *image) +{ + return pidgin_pixbuf_from_data(purple_imgstore_get_data(image), + purple_imgstore_get_size(image)); +} + +GdkPixbuf *pidgin_pixbuf_new_from_file(const gchar *filename) { GdkPixbuf *pixbuf; - GdkPixbufLoader *loader = gdk_pixbuf_loader_new(); - gdk_pixbuf_loader_write(loader, purple_imgstore_get_data(image), - purple_imgstore_get_size(image), NULL); - gdk_pixbuf_loader_close(loader, NULL); - pixbuf = gdk_pixbuf_loader_get_pixbuf(loader); - if (pixbuf) - g_object_ref(pixbuf); - g_object_unref(loader); + GError *error = NULL; + + pixbuf = gdk_pixbuf_new_from_file(filename, &error); + if (!pixbuf || error) { + purple_debug_warning("gtkutils", "gdk_pixbuf_new_from_file() " + "returned %s for file %s: %s\n", + pixbuf ? "something" : "nothing", + filename, + error ? error->message : "(no error message)"); + if (error) + g_error_free(error); + if (pixbuf) + g_object_unref(G_OBJECT(pixbuf)); + return NULL; + } + + return pixbuf; +} + +GdkPixbuf *pidgin_pixbuf_new_from_file_at_size(const char *filename, int width, int height) +{ + GdkPixbuf *pixbuf; + GError *error = NULL; + + pixbuf = gdk_pixbuf_new_from_file_at_size(filename, + width, height, &error); + if (!pixbuf || error) { + purple_debug_warning("gtkutils", "gdk_pixbuf_new_from_file_at_size() " + "returned %s for file %s: %s\n", + pixbuf ? "something" : "nothing", + filename, + error ? error->message : "(no error message)"); + if (error) + g_error_free(error); + if (pixbuf) + g_object_unref(G_OBJECT(pixbuf)); + return NULL; + } + + return pixbuf; +} + +GdkPixbuf *pidgin_pixbuf_new_from_file_at_scale(const char *filename, int width, int height, gboolean preserve_aspect_ratio) +{ + GdkPixbuf *pixbuf; + GError *error = NULL; + + pixbuf = gdk_pixbuf_new_from_file_at_scale(filename, + width, height, preserve_aspect_ratio, &error); + if (!pixbuf || error) { + purple_debug_warning("gtkutils", "gdk_pixbuf_new_from_file_at_scale() " + "returned %s for file %s: %s\n", + pixbuf ? "something" : "nothing", + filename, + error ? error->message : "(no error message)"); + if (error) + g_error_free(error); + if (pixbuf) + g_object_unref(G_OBJECT(pixbuf)); + return NULL; + } + return pixbuf; }