1.1 --- a/pidgin/gtkaccount.c
1.2 +++ b/pidgin/gtkaccount.c
1.3 @@ -2135,7 +2135,7 @@
1.4 gtk_list_store_clear(dialog->model);
1.5
1.6 if ((path = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/accounts/buddyicon")) != NULL) {
1.7 - GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(path, NULL);
1.8 + GdkPixbuf *pixbuf = pidgin_pixbuf_new_from_file(path);
1.9 if (pixbuf != NULL) {
1.10 global_buddyicon = gdk_pixbuf_scale_simple(pixbuf, 22, 22, GDK_INTERP_HYPER);
1.11 g_object_unref(G_OBJECT(pixbuf));
2.1 --- a/pidgin/gtkblist.c
2.2 +++ b/pidgin/gtkblist.c
2.3 @@ -2643,7 +2643,6 @@
2.4 gboolean scaled, gboolean greyed)
2.5 {
2.6 gsize len;
2.7 - GdkPixbufLoader *loader;
2.8 PurpleBuddy *buddy = NULL;
2.9 PurpleGroup *group = NULL;
2.10 const guchar *data = NULL;
2.11 @@ -2710,21 +2709,20 @@
2.12 return NULL;
2.13 }
2.14
2.15 - loader = gdk_pixbuf_loader_new();
2.16 - gdk_pixbuf_loader_write(loader, data, len, NULL);
2.17 - gdk_pixbuf_loader_close(loader, NULL);
2.18 -
2.19 + buf = pidgin_pixbuf_from_data(data, len);
2.20 + purple_buddy_icon_unref(icon);
2.21 + if (!buf) {
2.22 + purple_debug_warning("gtkblist", "Couldn't load buddy icon "
2.23 + "on account %s (%s) buddyname=%s "
2.24 + "custom_img_data=%p\n",
2.25 + account ? purple_account_get_username(account) : "(no account)",
2.26 + account ? purple_account_get_protocol_id(account) : "(no account)",
2.27 + buddy ? purple_buddy_get_name(buddy) : "(no buddy)",
2.28 + custom_img ? purple_imgstore_get_data(custom_img) : NULL);
2.29 + purple_imgstore_unref(custom_img);
2.30 + return NULL;
2.31 + }
2.32 purple_imgstore_unref(custom_img);
2.33 - purple_buddy_icon_unref(icon);
2.34 -
2.35 - buf = gdk_pixbuf_loader_get_pixbuf(loader);
2.36 - if (buf)
2.37 - g_object_ref(G_OBJECT(buf));
2.38 - g_object_unref(G_OBJECT(loader));
2.39 -
2.40 - if (!buf) {
2.41 - return NULL;
2.42 - }
2.43
2.44 if (greyed) {
2.45 gboolean offline = FALSE, idle = FALSE;
2.46 @@ -3952,7 +3950,7 @@
2.47 g_object_ref(pb);
2.48 g_free(path);
2.49 } else {
2.50 - pb = gdk_pixbuf_new_from_file(path, NULL);
2.51 + pb = pidgin_pixbuf_new_from_file(path);
2.52 if (pb != NULL) {
2.53 /* We don't want to own a ref to the pixbuf, but we need to keep clean up. */
2.54 /* I'm not sure if it would be better to just keep our ref and not let the emblem ever be destroyed */
3.1 --- a/pidgin/gtkconv.c
3.2 +++ b/pidgin/gtkconv.c
3.3 @@ -6392,8 +6392,8 @@
3.4 {
3.5 PidginConversation *gtkconv;
3.6 GtkIMHtmlSmiley *smiley;
3.7 - GdkPixbufLoader *loader;
3.8 const char *sml;
3.9 + GError *error = NULL;
3.10
3.11 sml = purple_account_get_protocol_name(conv->account);
3.12 gtkconv = PIDGIN_CONVERSATION(conv);
3.13 @@ -6406,11 +6406,24 @@
3.14 g_memmove((guchar *)smiley->data + smiley->datasize, data, size);
3.15 smiley->datasize += size;
3.16
3.17 - loader = smiley->loader;
3.18 - if (!loader)
3.19 + if (!smiley->loader)
3.20 return;
3.21
3.22 - gdk_pixbuf_loader_write(loader, data, size, NULL);
3.23 + if (!gdk_pixbuf_loader_write(smiley->loader, data, size, &error) || error) {
3.24 + purple_debug_warning("gtkconv", "gdk_pixbuf_loader_write() "
3.25 + "failed with size=%zu: %s\n", size,
3.26 + error ? error->message : "(no error message)");
3.27 + if (error)
3.28 + g_error_free(error);
3.29 + /* We must stop using the GdkPixbufLoader because trying to load
3.30 + certain invalid GIFs with at least gdk-pixbuf 2.23.3 can return
3.31 + a GdkPixbuf that will cause some operations (like
3.32 + gdk_pixbuf_scale_simple()) to consume memory in an infinite loop.
3.33 + But we also don't want to set smiley->loader to NULL because our
3.34 + code might expect it to be set. So create a new loader. */
3.35 + g_object_unref(G_OBJECT(smiley->loader));
3.36 + smiley->loader = gdk_pixbuf_loader_new();
3.37 + }
3.38 }
3.39
3.40 static void
3.41 @@ -6418,8 +6431,8 @@
3.42 {
3.43 PidginConversation *gtkconv;
3.44 GtkIMHtmlSmiley *smiley;
3.45 - GdkPixbufLoader *loader;
3.46 const char *sml;
3.47 + GError *error = NULL;
3.48
3.49 g_return_if_fail(conv != NULL);
3.50 g_return_if_fail(smile != NULL);
3.51 @@ -6431,17 +6444,27 @@
3.52 if (!smiley)
3.53 return;
3.54
3.55 - loader = smiley->loader;
3.56 -
3.57 - if (!loader)
3.58 + if (!smiley->loader)
3.59 return;
3.60
3.61 -
3.62 -
3.63 purple_debug_info("gtkconv", "About to close the smiley pixbuf\n");
3.64
3.65 - gdk_pixbuf_loader_close(loader, NULL);
3.66 -
3.67 + if (!gdk_pixbuf_loader_close(smiley->loader, &error) || error) {
3.68 + purple_debug_warning("gtkconv", "gdk_pixbuf_loader_close() "
3.69 + "failed: %s\n",
3.70 + error ? error->message : "(no error message)");
3.71 + if (error)
3.72 + g_error_free(error);
3.73 + /* We must stop using the GdkPixbufLoader because if we tried to
3.74 + load certain invalid GIFs with all current versions of GDK (as
3.75 + of 2011-06-15) then it's possible the loader will contain data
3.76 + that could cause some operations (like gdk_pixbuf_scale_simple())
3.77 + to consume memory in an infinite loop. But we also don't want
3.78 + to set smiley->loader to NULL because our code might expect it
3.79 + to be set. So create a new loader. */
3.80 + g_object_unref(G_OBJECT(smiley->loader));
3.81 + smiley->loader = gdk_pixbuf_loader_new();
3.82 + }
3.83 }
3.84
3.85 static void
3.86 @@ -6941,10 +6964,6 @@
3.87
3.88 PurpleBuddy *buddy;
3.89
3.90 - GdkPixbufLoader *loader;
3.91 - GdkPixbufAnimation *anim;
3.92 - GError *err = NULL;
3.93 -
3.94 PurpleStoredImage *custom_img = NULL;
3.95 gconstpointer data = NULL;
3.96 size_t len;
3.97 @@ -7022,7 +7041,6 @@
3.98
3.99 if (data == NULL) {
3.100 icon = purple_conv_im_get_icon(PURPLE_CONV_IM(conv));
3.101 -
3.102 if (icon == NULL)
3.103 {
3.104 gtk_widget_set_size_request(gtkconv->u.im->icon_container,
3.105 @@ -7031,7 +7049,6 @@
3.106 }
3.107
3.108 data = purple_buddy_icon_get_data(icon, &len);
3.109 -
3.110 if (data == NULL)
3.111 {
3.112 gtk_widget_set_size_request(gtkconv->u.im->icon_container,
3.113 @@ -7040,25 +7057,13 @@
3.114 }
3.115 }
3.116
3.117 - loader = gdk_pixbuf_loader_new();
3.118 - gdk_pixbuf_loader_write(loader, data, len, NULL);
3.119 - gdk_pixbuf_loader_close(loader, &err);
3.120 -
3.121 + gtkconv->u.im->anim = pidgin_pixbuf_anim_from_data(data, len);
3.122 purple_imgstore_unref(custom_img);
3.123
3.124 - anim = gdk_pixbuf_loader_get_animation(loader);
3.125 - if (anim)
3.126 - g_object_ref(G_OBJECT(anim));
3.127 - g_object_unref(loader);
3.128 -
3.129 - if (!anim)
3.130 + if (!gtkconv->u.im->anim) {
3.131 + purple_debug_error("gtkconv", "Couldn't load icon for conv %s\n",
3.132 + purple_conversation_get_name(conv));
3.133 return;
3.134 - gtkconv->u.im->anim = anim;
3.135 -
3.136 - if (err) {
3.137 - purple_debug(PURPLE_DEBUG_ERROR, "gtkconv",
3.138 - "Buddy icon error: %s\n", err->message);
3.139 - g_error_free(err);
3.140 }
3.141
3.142 if (gdk_pixbuf_animation_is_static_image(gtkconv->u.im->anim)) {
4.1 --- a/pidgin/gtkdialogs.c
4.2 +++ b/pidgin/gtkdialogs.c
4.3 @@ -433,7 +433,7 @@
4.4
4.5 /* Generate a logo with a version number */
4.6 filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "logo.png", NULL);
4.7 - pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
4.8 + pixbuf = pidgin_pixbuf_new_from_file(filename);
4.9 g_free(filename);
4.10
4.11 #if 0 /* Don't versionize the logo when the logo has the version in it */
5.1 --- a/pidgin/gtkft.c
5.2 +++ b/pidgin/gtkft.c
5.3 @@ -1149,8 +1149,8 @@
5.4
5.5 if (purple_xfer_get_size(xfer) <= PIDGIN_XFER_MAX_SIZE_IMAGE_THUMBNAIL) {
5.6 GdkPixbuf *thumbnail =
5.7 - gdk_pixbuf_new_from_file_at_size(
5.8 - purple_xfer_get_local_filename(xfer), 128, 128, NULL);
5.9 + pidgin_pixbuf_new_from_file_at_size(
5.10 + purple_xfer_get_local_filename(xfer), 128, 128);
5.11
5.12 if (thumbnail) {
5.13 gchar **formats_split = g_strsplit(formats, ",", 0);
6.1 --- a/pidgin/gtkimhtml.c
6.2 +++ b/pidgin/gtkimhtml.c
6.3 @@ -5057,16 +5057,8 @@
6.4
6.5 data = imhtml->funcs->image_get_data(image);
6.6 len = imhtml->funcs->image_get_size(image);
6.7 -
6.8 - if (data && len) {
6.9 - GdkPixbufLoader *loader = gdk_pixbuf_loader_new();
6.10 - gdk_pixbuf_loader_write(loader, data, len, NULL);
6.11 - gdk_pixbuf_loader_close(loader, NULL);
6.12 - anim = gdk_pixbuf_loader_get_animation(loader);
6.13 - if (anim)
6.14 - g_object_ref(G_OBJECT(anim));
6.15 - g_object_unref(G_OBJECT(loader));
6.16 - }
6.17 + if (data && len)
6.18 + anim = pidgin_pixbuf_anim_from_data(data, len);
6.19
6.20 }
6.21
7.1 --- a/pidgin/gtkmain.c
7.2 +++ b/pidgin/gtkmain.c
7.3 @@ -270,7 +270,7 @@
7.4 /* use the nice PNG icon for all the windows */
7.5 for(i=0; i<G_N_ELEMENTS(icon_sizes); i++) {
7.6 icon_path = g_build_filename(DATADIR, "icons", "hicolor", icon_sizes[i].dir, "apps", icon_sizes[i].filename, NULL);
7.7 - icon = gdk_pixbuf_new_from_file(icon_path, NULL);
7.8 + icon = pidgin_pixbuf_new_from_file(icon_path);
7.9 g_free(icon_path);
7.10 if (icon) {
7.11 icons = g_list_append(icons,icon);
8.1 --- a/pidgin/gtkprefs.c
8.2 +++ b/pidgin/gtkprefs.c
8.3 @@ -382,7 +382,7 @@
8.4 * LEAK - Gentoo memprof thinks pixbuf is leaking here... but it
8.5 * looks like it should be ok to me. Anyone know what's up? --Mark
8.6 */
8.7 - pixbuf = (theme->icon ? gdk_pixbuf_new_from_file(theme->icon, NULL) : NULL);
8.8 + pixbuf = (theme->icon ? pidgin_pixbuf_new_from_file(theme->icon) : NULL);
8.9
8.10 gtk_list_store_set(prefs_smiley_themes, &iter,
8.11 0, pixbuf,
8.12 @@ -452,7 +452,7 @@
8.13
8.14 image_full = purple_theme_get_image_full(theme);
8.15 if (image_full != NULL){
8.16 - pixbuf = gdk_pixbuf_new_from_file_at_scale(image_full, PREFS_OPTIMAL_ICON_SIZE, PREFS_OPTIMAL_ICON_SIZE, TRUE, NULL);
8.17 + pixbuf = pidgin_pixbuf_new_from_file_at_scale(image_full, PREFS_OPTIMAL_ICON_SIZE, PREFS_OPTIMAL_ICON_SIZE, TRUE);
8.18 g_free(image_full);
8.19 } else
8.20 pixbuf = NULL;
8.21 @@ -473,7 +473,7 @@
8.22
8.23 image_full = purple_theme_get_image_full(theme);
8.24 if (image_full != NULL){
8.25 - pixbuf = gdk_pixbuf_new_from_file_at_scale(image_full, PREFS_OPTIMAL_ICON_SIZE, PREFS_OPTIMAL_ICON_SIZE, TRUE, NULL);
8.26 + pixbuf = pidgin_pixbuf_new_from_file_at_scale(image_full, PREFS_OPTIMAL_ICON_SIZE, PREFS_OPTIMAL_ICON_SIZE, TRUE);
8.27 g_free(image_full);
8.28 } else
8.29 pixbuf = NULL;
8.30 @@ -529,7 +529,7 @@
8.31 purple_theme_manager_refresh();
8.32
8.33 tmp = g_build_filename(DATADIR, "icons", "hicolor", "32x32", "apps", "pidgin.png", NULL);
8.34 - pixbuf = gdk_pixbuf_new_from_file_at_scale(tmp, PREFS_OPTIMAL_ICON_SIZE, PREFS_OPTIMAL_ICON_SIZE, TRUE, NULL);
8.35 + pixbuf = pidgin_pixbuf_new_from_file_at_scale(tmp, PREFS_OPTIMAL_ICON_SIZE, PREFS_OPTIMAL_ICON_SIZE, TRUE);
8.36 g_free(tmp);
8.37
8.38 /* sound themes */
9.1 --- a/pidgin/gtkrequest.c
9.2 +++ b/pidgin/gtkrequest.c
9.3 @@ -653,35 +653,30 @@
9.4
9.5 /* Dialog icon. */
9.6 if (icon_data) {
9.7 - GdkPixbufLoader *loader = gdk_pixbuf_loader_new();
9.8 - GdkPixbuf *pixbuf = NULL;
9.9 - if (gdk_pixbuf_loader_write(loader, icon_data, icon_size, NULL)) {
9.10 - pixbuf = gdk_pixbuf_loader_get_pixbuf(loader);
9.11 - if (pixbuf) {
9.12 - /* scale the image if it is too large */
9.13 - int width = gdk_pixbuf_get_width(pixbuf);
9.14 - int height = gdk_pixbuf_get_height(pixbuf);
9.15 - if (width > 128 || height > 128) {
9.16 - int scaled_width = width > height ? 128 : (128 * width) / height;
9.17 - int scaled_height = height > width ? 128 : (128 * height) / width;
9.18 - GdkPixbuf *scaled =
9.19 - gdk_pixbuf_scale_simple(pixbuf, scaled_width, scaled_height,
9.20 - GDK_INTERP_BILINEAR);
9.21 + GdkPixbuf *pixbuf = pidgin_pixbuf_from_data(icon_data, icon_size);
9.22 + if (pixbuf) {
9.23 + /* scale the image if it is too large */
9.24 + int width = gdk_pixbuf_get_width(pixbuf);
9.25 + int height = gdk_pixbuf_get_height(pixbuf);
9.26 + if (width > 128 || height > 128) {
9.27 + int scaled_width = width > height ? 128 : (128 * width) / height;
9.28 + int scaled_height = height > width ? 128 : (128 * height) / width;
9.29 + GdkPixbuf *scaled =
9.30 + gdk_pixbuf_scale_simple(pixbuf, scaled_width, scaled_height,
9.31 + GDK_INTERP_BILINEAR);
9.32
9.33 - purple_debug_info("pidgin",
9.34 - "dialog icon was too large, scale it down\n");
9.35 - if (scaled) {
9.36 - g_object_unref(pixbuf);
9.37 - pixbuf = scaled;
9.38 - }
9.39 + purple_debug_info("pidgin",
9.40 + "dialog icon was too large, scaled it down\n");
9.41 + if (scaled) {
9.42 + g_object_unref(pixbuf);
9.43 + pixbuf = scaled;
9.44 }
9.45 - img = gtk_image_new_from_pixbuf(pixbuf);
9.46 }
9.47 + img = gtk_image_new_from_pixbuf(pixbuf);
9.48 + g_object_unref(pixbuf);
9.49 } else {
9.50 purple_debug_info("pidgin", "failed to parse dialog icon\n");
9.51 }
9.52 - gdk_pixbuf_loader_close(loader, NULL);
9.53 - g_object_unref(loader);
9.54 }
9.55
9.56 if (!img) {
9.57 @@ -1016,22 +1011,17 @@
9.58 {
9.59 GtkWidget *widget;
9.60 GdkPixbuf *buf, *scale;
9.61 - GdkPixbufLoader *loader;
9.62
9.63 - loader = gdk_pixbuf_loader_new();
9.64 - gdk_pixbuf_loader_write(loader,
9.65 - (const guchar *)purple_request_field_image_get_buffer(field),
9.66 - purple_request_field_image_get_size(field),
9.67 - NULL);
9.68 - gdk_pixbuf_loader_close(loader, NULL);
9.69 - buf = gdk_pixbuf_loader_get_pixbuf(loader);
9.70 + buf = pidgin_pixbuf_from_data(
9.71 + (const guchar *)purple_request_field_image_get_buffer(field),
9.72 + purple_request_field_image_get_size(field));
9.73
9.74 scale = gdk_pixbuf_scale_simple(buf,
9.75 purple_request_field_image_get_scale_x(field) * gdk_pixbuf_get_width(buf),
9.76 purple_request_field_image_get_scale_y(field) * gdk_pixbuf_get_height(buf),
9.77 GDK_INTERP_BILINEAR);
9.78 widget = gtk_image_new_from_pixbuf(scale);
9.79 - g_object_unref(G_OBJECT(loader));
9.80 + g_object_unref(G_OBJECT(buf));
9.81 g_object_unref(G_OBJECT(scale));
9.82
9.83 return widget;
9.84 @@ -1132,7 +1122,7 @@
9.85 GdkPixbuf* pixbuf = NULL;
9.86
9.87 if (icon_path)
9.88 - pixbuf = gdk_pixbuf_new_from_file(icon_path, NULL);
9.89 + pixbuf = pidgin_pixbuf_new_from_file(icon_path);
9.90
9.91 gtk_list_store_set(store, &iter,
9.92 0, purple_request_field_list_get_data(field, text),
10.1 --- a/pidgin/gtksmiley.c
10.2 +++ b/pidgin/gtksmiley.c
10.3 @@ -332,7 +332,7 @@
10.4
10.5 g_free(s->filename);
10.6 s->filename = g_strdup(filename);
10.7 - pixbuf = gdk_pixbuf_new_from_file_at_scale(filename, 64, 64, FALSE, NULL);
10.8 + pixbuf = pidgin_pixbuf_new_from_file_at_scale(filename, 64, 64, FALSE);
10.9 gtk_image_set_from_pixbuf(GTK_IMAGE(s->smiley_image), pixbuf);
10.10 if (pixbuf)
10.11 g_object_unref(G_OBJECT(pixbuf));
10.12 @@ -690,7 +690,6 @@
10.13 FILE *f;
10.14 gchar *path;
10.15 size_t wc;
10.16 - GError *err = NULL;
10.17 PidginSmiley *ps;
10.18 GdkPixbuf *image;
10.19
10.20 @@ -709,13 +708,11 @@
10.21 }
10.22 fclose(f);
10.23
10.24 - image = gdk_pixbuf_new_from_file(path, &err);
10.25 + image = pidgin_pixbuf_new_from_file(path);
10.26 g_unlink(path);
10.27 g_free(path);
10.28 - if (err) {
10.29 - g_error_free(err);
10.30 + if (!image)
10.31 return;
10.32 - }
10.33
10.34 ps = pidgin_smiley_edit(dialog->window, NULL);
10.35 pidgin_smiley_editor_set_image(ps, image);
11.1 --- a/pidgin/gtkstatusbox.c
11.2 +++ b/pidgin/gtkstatusbox.c
11.3 @@ -2225,22 +2225,45 @@
11.4
11.5 if (status_box->buddy_icon_img != NULL)
11.6 {
11.7 - GdkPixbuf *buf, *scale;
11.8 - int scale_width, scale_height;
11.9 - GdkPixbufLoader *loader = gdk_pixbuf_loader_new();
11.10 + GdkPixbufLoader *loader;
11.11 + GError *error = NULL;
11.12 +
11.13 + loader = gdk_pixbuf_loader_new();
11.14 +
11.15 g_signal_connect(G_OBJECT(loader), "size-prepared", G_CALLBACK(pixbuf_size_prepared_cb), NULL);
11.16 - gdk_pixbuf_loader_write(loader, purple_imgstore_get_data(status_box->buddy_icon_img),
11.17 - purple_imgstore_get_size(status_box->buddy_icon_img), NULL);
11.18 - gdk_pixbuf_loader_close(loader, NULL);
11.19 - buf = gdk_pixbuf_loader_get_pixbuf(loader);
11.20 - scale_width = gdk_pixbuf_get_width(buf);
11.21 - scale_height = gdk_pixbuf_get_height(buf);
11.22 - scale = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, scale_width, scale_height);
11.23 - gdk_pixbuf_fill(scale, 0x00000000);
11.24 - gdk_pixbuf_copy_area(buf, 0, 0, scale_width, scale_height, scale, 0, 0);
11.25 - if (pidgin_gdk_pixbuf_is_opaque(scale))
11.26 - pidgin_gdk_pixbuf_make_round(scale);
11.27 - status_box->buddy_icon = scale;
11.28 + if (!gdk_pixbuf_loader_write(loader,
11.29 + purple_imgstore_get_data(status_box->buddy_icon_img),
11.30 + purple_imgstore_get_size(status_box->buddy_icon_img),
11.31 + &error) || error)
11.32 + {
11.33 + purple_debug_warning("gtkstatusbox", "gdk_pixbuf_loader_write() "
11.34 + "failed with size=%zu: %s\n",
11.35 + purple_imgstore_get_size(status_box->buddy_icon_img),
11.36 + error ? error->message : "(no error message)");
11.37 + if (error)
11.38 + g_error_free(error);
11.39 + } else if (!gdk_pixbuf_loader_close(loader, &error) || error) {
11.40 + purple_debug_warning("gtkstatusbox", "gdk_pixbuf_loader_close() "
11.41 + "failed for image of size %zu: %s\n",
11.42 + purple_imgstore_get_size(status_box->buddy_icon_img),
11.43 + error ? error->message : "(no error message)");
11.44 + if (error)
11.45 + g_error_free(error);
11.46 + } else {
11.47 + GdkPixbuf *buf, *scale;
11.48 + int scale_width, scale_height;
11.49 +
11.50 + buf = gdk_pixbuf_loader_get_pixbuf(loader);
11.51 + scale_width = gdk_pixbuf_get_width(buf);
11.52 + scale_height = gdk_pixbuf_get_height(buf);
11.53 + scale = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, scale_width, scale_height);
11.54 + gdk_pixbuf_fill(scale, 0x00000000);
11.55 + gdk_pixbuf_copy_area(buf, 0, 0, scale_width, scale_height, scale, 0, 0);
11.56 + if (pidgin_gdk_pixbuf_is_opaque(scale))
11.57 + pidgin_gdk_pixbuf_make_round(scale);
11.58 + status_box->buddy_icon = scale;
11.59 + }
11.60 +
11.61 g_object_unref(loader);
11.62 }
11.63
12.1 --- a/pidgin/gtkutils.c
12.2 +++ b/pidgin/gtkutils.c
12.3 @@ -615,7 +615,7 @@
12.4 tmp, NULL);
12.5 g_free(tmp);
12.6
12.7 - pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
12.8 + pixbuf = pidgin_pixbuf_new_from_file(filename);
12.9 g_free(filename);
12.10
12.11 return pixbuf;
12.12 @@ -704,7 +704,7 @@
12.13 "16", "google-talk.png", NULL);
12.14 GtkWidget *item;
12.15
12.16 - pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
12.17 + pixbuf = pidgin_pixbuf_new_from_file(filename);
12.18 g_free(filename);
12.19
12.20 gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu),
12.21 @@ -723,7 +723,7 @@
12.22 "16", "facebook.png", NULL);
12.23 GtkWidget *item;
12.24
12.25 - pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
12.26 + pixbuf = pidgin_pixbuf_new_from_file(filename);
12.27 g_free(filename);
12.28
12.29 gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu),
12.30 @@ -1593,7 +1593,7 @@
12.31 }
12.32
12.33 /* Are we dealing with an image? */
12.34 - pb = gdk_pixbuf_new_from_file(filename, NULL);
12.35 + pb = pidgin_pixbuf_new_from_file(filename);
12.36 if (pb) {
12.37 _DndData *data = g_malloc(sizeof(_DndData));
12.38 gboolean ft = FALSE, im = FALSE;
12.39 @@ -2265,7 +2265,7 @@
12.40 filename = gtk_file_chooser_get_preview_filename(
12.41 GTK_FILE_CHOOSER(dialog->icon_filesel));
12.42
12.43 - if (!filename || g_stat(filename, &st) || !(pixbuf = gdk_pixbuf_new_from_file(filename, NULL)))
12.44 + if (!filename || g_stat(filename, &st) || !(pixbuf = pidgin_pixbuf_new_from_file(filename)))
12.45 {
12.46 gtk_image_set_from_pixbuf(GTK_IMAGE(dialog->icon_preview), NULL);
12.47 gtk_label_set_markup(GTK_LABEL(dialog->icon_text), "");
12.48 @@ -3086,17 +3086,134 @@
12.49 #endif
12.50 }
12.51
12.52 -GdkPixbuf * pidgin_pixbuf_from_imgstore(PurpleStoredImage *image)
12.53 +static GObject *pidgin_pixbuf_from_data_helper(const guchar *buf, gsize count, gboolean animated)
12.54 +{
12.55 + GObject *pixbuf;
12.56 + GdkPixbufLoader *loader;
12.57 + GError *error = NULL;
12.58 +
12.59 + loader = gdk_pixbuf_loader_new();
12.60 +
12.61 + if (!gdk_pixbuf_loader_write(loader, buf, count, &error) || error) {
12.62 + purple_debug_warning("gtkutils", "gdk_pixbuf_loader_write() "
12.63 + "failed with size=%zu: %s\n", count,
12.64 + error ? error->message : "(no error message)");
12.65 + if (error)
12.66 + g_error_free(error);
12.67 + g_object_unref(G_OBJECT(loader));
12.68 + return NULL;
12.69 + }
12.70 +
12.71 + if (!gdk_pixbuf_loader_close(loader, &error) || error) {
12.72 + purple_debug_warning("gtkutils", "gdk_pixbuf_loader_close() "
12.73 + "failed for image of size %zu: %s\n", count,
12.74 + error ? error->message : "(no error message)");
12.75 + if (error)
12.76 + g_error_free(error);
12.77 + g_object_unref(G_OBJECT(loader));
12.78 + return NULL;
12.79 + }
12.80 +
12.81 + if (animated)
12.82 + pixbuf = G_OBJECT(gdk_pixbuf_loader_get_animation(loader));
12.83 + else
12.84 + pixbuf = G_OBJECT(gdk_pixbuf_loader_get_pixbuf(loader));
12.85 + if (!pixbuf) {
12.86 + purple_debug_warning("gtkutils", "%s() returned NULL for image "
12.87 + "of size %zu\n",
12.88 + animated ? "gdk_pixbuf_loader_get_animation"
12.89 + : "gdk_pixbuf_loader_get_pixbuf", count);
12.90 + g_object_unref(G_OBJECT(loader));
12.91 + return NULL;
12.92 + }
12.93 +
12.94 + g_object_ref(pixbuf);
12.95 + g_object_unref(G_OBJECT(loader));
12.96 +
12.97 + return pixbuf;
12.98 +}
12.99 +
12.100 +GdkPixbuf *pidgin_pixbuf_from_data(const guchar *buf, gsize count)
12.101 +{
12.102 + return GDK_PIXBUF(pidgin_pixbuf_from_data_helper(buf, count, FALSE));
12.103 +}
12.104 +
12.105 +GdkPixbufAnimation *pidgin_pixbuf_anim_from_data(const guchar *buf, gsize count)
12.106 +{
12.107 + return GDK_PIXBUF_ANIMATION(pidgin_pixbuf_from_data_helper(buf, count, TRUE));
12.108 +}
12.109 +
12.110 +GdkPixbuf *pidgin_pixbuf_from_imgstore(PurpleStoredImage *image)
12.111 +{
12.112 + return pidgin_pixbuf_from_data(purple_imgstore_get_data(image),
12.113 + purple_imgstore_get_size(image));
12.114 +}
12.115 +
12.116 +GdkPixbuf *pidgin_pixbuf_new_from_file(const gchar *filename)
12.117 {
12.118 GdkPixbuf *pixbuf;
12.119 - GdkPixbufLoader *loader = gdk_pixbuf_loader_new();
12.120 - gdk_pixbuf_loader_write(loader, purple_imgstore_get_data(image),
12.121 - purple_imgstore_get_size(image), NULL);
12.122 - gdk_pixbuf_loader_close(loader, NULL);
12.123 - pixbuf = gdk_pixbuf_loader_get_pixbuf(loader);
12.124 - if (pixbuf)
12.125 - g_object_ref(pixbuf);
12.126 - g_object_unref(loader);
12.127 + GError *error = NULL;
12.128 +
12.129 + pixbuf = gdk_pixbuf_new_from_file(filename, &error);
12.130 + if (!pixbuf || error) {
12.131 + purple_debug_warning("gtkutils", "gdk_pixbuf_new_from_file() "
12.132 + "returned %s for file %s: %s\n",
12.133 + pixbuf ? "something" : "nothing",
12.134 + filename,
12.135 + error ? error->message : "(no error message)");
12.136 + if (error)
12.137 + g_error_free(error);
12.138 + if (pixbuf)
12.139 + g_object_unref(G_OBJECT(pixbuf));
12.140 + return NULL;
12.141 + }
12.142 +
12.143 + return pixbuf;
12.144 +}
12.145 +
12.146 +GdkPixbuf *pidgin_pixbuf_new_from_file_at_size(const char *filename, int width, int height)
12.147 +{
12.148 + GdkPixbuf *pixbuf;
12.149 + GError *error = NULL;
12.150 +
12.151 + pixbuf = gdk_pixbuf_new_from_file_at_size(filename,
12.152 + width, height, &error);
12.153 + if (!pixbuf || error) {
12.154 + purple_debug_warning("gtkutils", "gdk_pixbuf_new_from_file_at_size() "
12.155 + "returned %s for file %s: %s\n",
12.156 + pixbuf ? "something" : "nothing",
12.157 + filename,
12.158 + error ? error->message : "(no error message)");
12.159 + if (error)
12.160 + g_error_free(error);
12.161 + if (pixbuf)
12.162 + g_object_unref(G_OBJECT(pixbuf));
12.163 + return NULL;
12.164 + }
12.165 +
12.166 + return pixbuf;
12.167 +}
12.168 +
12.169 +GdkPixbuf *pidgin_pixbuf_new_from_file_at_scale(const char *filename, int width, int height, gboolean preserve_aspect_ratio)
12.170 +{
12.171 + GdkPixbuf *pixbuf;
12.172 + GError *error = NULL;
12.173 +
12.174 + pixbuf = gdk_pixbuf_new_from_file_at_scale(filename,
12.175 + width, height, preserve_aspect_ratio, &error);
12.176 + if (!pixbuf || error) {
12.177 + purple_debug_warning("gtkutils", "gdk_pixbuf_new_from_file_at_scale() "
12.178 + "returned %s for file %s: %s\n",
12.179 + pixbuf ? "something" : "nothing",
12.180 + filename,
12.181 + error ? error->message : "(no error message)");
12.182 + if (error)
12.183 + g_error_free(error);
12.184 + if (pixbuf)
12.185 + g_object_unref(G_OBJECT(pixbuf));
12.186 + return NULL;
12.187 + }
12.188 +
12.189 return pixbuf;
12.190 }
12.191
13.1 --- a/pidgin/gtkutils.h
13.2 +++ b/pidgin/gtkutils.h
13.3 @@ -834,6 +834,32 @@
13.4 GtkWidget *pidgin_add_widget_to_vbox(GtkBox *vbox, const char *widget_label, GtkSizeGroup *sg, GtkWidget *widget, gboolean expand, GtkWidget **p_label);
13.5
13.6 /**
13.7 + * Create a GdkPixbuf from a chunk of image data.
13.8 + *
13.9 + * @param buf The raw binary image data.
13.10 + * @param count The length of buf in bytes.
13.11 + *
13.12 + * @return A GdkPixbuf created from the image data, or NULL if
13.13 + * there was an error parsing the data.
13.14 + *
13.15 + * @since 2.9.0
13.16 + */
13.17 +GdkPixbuf *pidgin_pixbuf_from_data(const guchar *buf, gsize count);
13.18 +
13.19 +/**
13.20 + * Create a GdkPixbufAnimation from a chunk of image data.
13.21 + *
13.22 + * @param buf The raw binary image data.
13.23 + * @param count The length of buf in bytes.
13.24 + *
13.25 + * @return A GdkPixbufAnimation created from the image data, or NULL if
13.26 + * there was an error parsing the data.
13.27 + *
13.28 + * @since 2.9.0
13.29 + */
13.30 +GdkPixbufAnimation *pidgin_pixbuf_anim_from_data(const guchar *buf, gsize count);
13.31 +
13.32 +/**
13.33 * Create a GdkPixbuf from a PurpleStoredImage.
13.34 *
13.35 * @param image A PurpleStoredImage.
13.36 @@ -845,6 +871,86 @@
13.37 GdkPixbuf *pidgin_pixbuf_from_imgstore(PurpleStoredImage *image);
13.38
13.39 /**
13.40 + * Helper function that calls gdk_pixbuf_new_from_file() and checks both
13.41 + * the return code and the GError and returns NULL if either one failed.
13.42 + *
13.43 + * The gdk-pixbuf documentation implies that it is sufficient to check
13.44 + * the return value of gdk_pixbuf_new_from_file() to determine
13.45 + * whether the image was able to be loaded. However, this is not the case
13.46 + * with gdk-pixbuf 2.23.3 and probably many earlier versions. In some
13.47 + * cases a GdkPixbuf object is returned that will cause some operations
13.48 + * (like gdk_pixbuf_scale_simple()) to rapidly consume memory in an
13.49 + * infinite loop.
13.50 + *
13.51 + * This function shouldn't be necessary once Pidgin requires a version of
13.52 + * gdk-pixbuf where the aforementioned bug is fixed. However, it might be
13.53 + * nice to keep this function around for the debug message that it logs.
13.54 + *
13.55 + * @param filename Name of file to load, in the GLib file name encoding
13.56 + *
13.57 + * @return The GdkPixbuf if successful. Otherwise NULL is returned and
13.58 + * a warning is logged.
13.59 + *
13.60 + * @since 2.9.0
13.61 + */
13.62 +GdkPixbuf *pidgin_pixbuf_new_from_file(const char *filename);
13.63 +
13.64 +/**
13.65 + * Helper function that calls gdk_pixbuf_new_from_file_at_size() and checks
13.66 + * both the return code and the GError and returns NULL if either one failed.
13.67 + *
13.68 + * The gdk-pixbuf documentation implies that it is sufficient to check
13.69 + * the return value of gdk_pixbuf_new_from_file_at_size() to determine
13.70 + * whether the image was able to be loaded. However, this is not the case
13.71 + * with gdk-pixbuf 2.23.3 and probably many earlier versions. In some
13.72 + * cases a GdkPixbuf object is returned that will cause some operations
13.73 + * (like gdk_pixbuf_scale_simple()) to rapidly consume memory in an
13.74 + * infinite loop.
13.75 + *
13.76 + * This function shouldn't be necessary once Pidgin requires a version of
13.77 + * gdk-pixbuf where the aforementioned bug is fixed. However, it might be
13.78 + * nice to keep this function around for the debug message that it logs.
13.79 + *
13.80 + * @param filename Name of file to load, in the GLib file name encoding
13.81 + * @param width The width the image should have or -1 to not constrain the width
13.82 + * @param height The height the image should have or -1 to not constrain the height
13.83 + *
13.84 + * @return The GdkPixbuf if successful. Otherwise NULL is returned and
13.85 + * a warning is logged.
13.86 + *
13.87 + * @since 2.9.0
13.88 + */
13.89 +GdkPixbuf *pidgin_pixbuf_new_from_file_at_size(const char *filename, int width, int height);
13.90 +
13.91 +/**
13.92 + * Helper function that calls gdk_pixbuf_new_from_file_at_scale() and checks
13.93 + * both the return code and the GError and returns NULL if either one failed.
13.94 + *
13.95 + * The gdk-pixbuf documentation implies that it is sufficient to check
13.96 + * the return value of gdk_pixbuf_new_from_file_at_scale() to determine
13.97 + * whether the image was able to be loaded. However, this is not the case
13.98 + * with gdk-pixbuf 2.23.3 and probably many earlier versions. In some
13.99 + * cases a GdkPixbuf object is returned that will cause some operations
13.100 + * (like gdk_pixbuf_scale_simple()) to rapidly consume memory in an
13.101 + * infinite loop.
13.102 + *
13.103 + * This function shouldn't be necessary once Pidgin requires a version of
13.104 + * gdk-pixbuf where the aforementioned bug is fixed. However, it might be
13.105 + * nice to keep this function around for the debug message that it logs.
13.106 + *
13.107 + * @param filename Name of file to load, in the GLib file name encoding
13.108 + * @param width The width the image should have or -1 to not constrain the width
13.109 + * @param height The height the image should have or -1 to not constrain the height
13.110 + * @param preserve_aspect_ratio TRUE to preserve the image's aspect ratio
13.111 + *
13.112 + * @return The GdkPixbuf if successful. Otherwise NULL is returned and
13.113 + * a warning is logged.
13.114 + *
13.115 + * @since 2.9.0
13.116 + */
13.117 +GdkPixbuf *pidgin_pixbuf_new_from_file_at_scale(const char *filename, int width, int height, gboolean preserve_aspect_ratio);
13.118 +
13.119 +/**
13.120 * Add scrollbars to a widget
13.121 * @param widget The child widget
13.122 * @hscrollbar_policy Horizontal scrolling policy