[gdk-pixbuf] icns: Add progressive loading support



commit 59e3b147287679fe214f39822f3918dba61c9e8f
Author: Damjan Jovanovic <damjan jov gmail com>
Date:   Mon Sep 13 05:29:00 2010 +0000

    icns: Add progressive loading support
    
    This fixes thumbnailing of ICNS files in nautilus.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=629474

 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 ddc88ee..a432e46 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)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]