--- a/gdk-pixbuf/io-icns.c	2009-06-04 21:18:03.000000000 +0200
+++ b/gdk-pixbuf/io-icns.c	2010-09-13 07:25:02.856771153 +0200
@@ -43,6 +43,17 @@
 };
 typedef struct IcnsBlockHeader IcnsBlockHeader;
 
+struct icns_progressive_state
+{
+  GdkPixbufModuleSizeFunc size_func;
+  GdkPixbufModulePreparedFunc prepared_func;
+  GdkPixbufModuleUpdatedFunc updated_func;
+  gpointer user_data;
+
+  GByteArray *byteArray;
+  GdkPixbuf *pixbuf;      /* Our "target" */
+};
+
 /*
  * load raw icon data from 'icns' resource
  *
@@ -366,6 +377,108 @@
   return pixbuf;
 }
 
+static void
+context_free (struct icns_progressive_state *context)
+{
+  g_byte_array_free (context->byteArray, TRUE);
+
+  if (context->pixbuf)
+    g_object_unref (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)
+{
+  struct icns_progressive_state *context;
+
+  context = g_new0(struct icns_progressive_state, 1);
+  context->size_func = size_func;
+  context->prepared_func = prepared_func;
+  context->updated_func = updated_func;
+  context->user_data = user_data;
+  context->byteArray = g_byte_array_new();
+  context->pixbuf = NULL;
+
+  return context;
+}
+
+static gboolean
+gdk_pixbuf__icns_image_stop_load(gpointer data,
+                                 GError **error)
+{
+  struct icns_progressive_state *context =
+    (struct icns_progressive_state *) 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)
+{
+  struct icns_progressive_state *context =
+    (struct icns_progressive_state *) data;
+  int i;
+  int filesize;
+  gint w, h;
+
+  context->byteArray = g_byte_array_append (context->byteArray, buf, size);
+
+  if (context->byteArray->len < 8)
+    return TRUE;
+
+  filesize = (context->byteArray->data[4] << 24) |
+    (context->byteArray->data[5] << 16) |
+    (context->byteArray->data[6] << 8) |
+    (context->byteArray->data[7]);
+  if (context->byteArray->len < filesize)
+    return TRUE;
+
+  for (i = 0; i < G_N_ELEMENTS(sizes) && !context->pixbuf; i++)
+    context->pixbuf = load_icon (sizes[i],
+				 context->byteArray->data,
+				 context->byteArray->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 +488,9 @@
 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)
