diff options
author | Damjan Jovanovic <damjan.jov@gmail.com> | 2010-09-13 05:29:00 +0000 |
---|---|---|
committer | Bastien Nocera <hadess@hadess.net> | 2014-10-24 15:00:46 +0200 |
commit | 59e3b147287679fe214f39822f3918dba61c9e8f (patch) | |
tree | eb001e332210a9091c2db0c5ab19f5d98b9bf730 | |
parent | 0da968fd5f1c5f8b05f4549be6bf77fe2f1daa62 (diff) | |
download | gdk-pixbuf-59e3b147287679fe214f39822f3918dba61c9e8f.tar.gz |
icns: Add progressive loading support
This fixes thumbnailing of ICNS files in nautilus.
https://bugzilla.gnome.org/show_bug.cgi?id=629474
-rw-r--r-- | gdk-pixbuf/io-icns.c | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/gdk-pixbuf/io-icns.c b/gdk-pixbuf/io-icns.c index ddc88ee1e..a432e463f 100644 --- a/gdk-pixbuf/io-icns.c +++ b/gdk-pixbuf/io-icns.c @@ -43,6 +43,17 @@ struct IcnsBlockHeader }; typedef struct IcnsBlockHeader IcnsBlockHeader; +typedef struct +{ + GdkPixbufModuleSizeFunc size_func; + GdkPixbufModulePreparedFunc prepared_func; + GdkPixbufModuleUpdatedFunc updated_func; + gpointer user_data; + + GByteArray *byte_array; + GdkPixbuf *pixbuf; /* Our "target" */ +} IcnsProgressiveState; + /* * load raw icon data from 'icns' resource * @@ -366,6 +377,106 @@ icns_image_load (FILE *f, GError ** error) return pixbuf; } +static void +context_free (IcnsProgressiveState *context) +{ + g_byte_array_free (context->byte_array, TRUE); + g_clear_object (&context->pixbuf); + g_free (context); +} + +static gpointer +gdk_pixbuf__icns_image_begin_load (GdkPixbufModuleSizeFunc size_func, + GdkPixbufModulePreparedFunc prepared_func, + GdkPixbufModuleUpdatedFunc updated_func, + gpointer user_data, + GError **error) +{ + IcnsProgressiveState *context; + + context = g_new0 (IcnsProgressiveState, 1); + context->size_func = size_func; + context->prepared_func = prepared_func; + context->updated_func = updated_func; + context->user_data = user_data; + context->byte_array = g_byte_array_new (); + + return context; +} + +static gboolean +gdk_pixbuf__icns_image_stop_load (gpointer data, + GError **error) +{ + IcnsProgressiveState *context = data; + + g_return_val_if_fail (context != NULL, TRUE); + + context_free (context); + return TRUE; +} + +static gboolean +gdk_pixbuf__icns_image_load_increment (gpointer data, + const guchar *buf, + guint size, + GError **error) +{ + IcnsProgressiveState *context = data; + int i; + int filesize; + gint w, h; + + context->byte_array = g_byte_array_append (context->byte_array, buf, size); + + if (context->byte_array->len < 8) + return TRUE; + + filesize = (context->byte_array->data[4] << 24) | + (context->byte_array->data[5] << 16) | + (context->byte_array->data[6] << 8) | + (context->byte_array->data[7]); + + if (context->byte_array->len < filesize) + return TRUE; + + for (i = 0; i < G_N_ELEMENTS(sizes) && !context->pixbuf; i++) + context->pixbuf = load_icon (sizes[i], + context->byte_array->data, + context->byte_array->len); + + if (!context->pixbuf) + { + g_set_error_literal (error, GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_CORRUPT_IMAGE, + _("Could not decode ICNS file")); + return FALSE; + } + + w = gdk_pixbuf_get_width (context->pixbuf); + h = gdk_pixbuf_get_height (context->pixbuf); + + if (context->size_func != NULL) + (*context->size_func) (&w, + &h, + context->user_data); + + if (context->prepared_func != NULL) + (*context->prepared_func) (context->pixbuf, + NULL, + context->user_data); + + if (context->updated_func != NULL) + (*context->updated_func) (context->pixbuf, + 0, + 0, + gdk_pixbuf_get_width (context->pixbuf), + gdk_pixbuf_get_height (context->pixbuf), + context->user_data); + + return TRUE; +} + #ifndef INCLUDE_icns #define MODULE_ENTRY(function) G_MODULE_EXPORT void function #else @@ -375,6 +486,9 @@ icns_image_load (FILE *f, GError ** error) MODULE_ENTRY (fill_vtable) (GdkPixbufModule * module) { module->load = icns_image_load; + module->begin_load = gdk_pixbuf__icns_image_begin_load; + module->stop_load = gdk_pixbuf__icns_image_stop_load; + module->load_increment = gdk_pixbuf__icns_image_load_increment; } MODULE_ENTRY (fill_info) (GdkPixbufFormat * info) |