[gdk-pixbuf/resources: 3/4] Add pixbuf loader for GdkPixdata files



commit 8043382c29bb5998fd6df7472ba4b799cc015d80
Author: Alexander Larsson <alexl redhat com>
Date:   Tue Jan 31 14:48:57 2012 +0100

    Add pixbuf loader for GdkPixdata files

 gdk-pixbuf/Makefile.am     |   12 +++-
 gdk-pixbuf/gdk-pixbuf-io.c |   16 +++-
 gdk-pixbuf/io-pixdata.c    |  192 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 216 insertions(+), 4 deletions(-)
---
diff --git a/gdk-pixbuf/Makefile.am b/gdk-pixbuf/Makefile.am
index 31e91eb..215c476 100644
--- a/gdk-pixbuf/Makefile.am
+++ b/gdk-pixbuf/Makefile.am
@@ -86,6 +86,11 @@ libpixbufloader_wbmp_la_LDFLAGS = -avoid-version -module $(no_undefined)
 libpixbufloader_wbmp_la_LIBADD = $(module_libs)
 
 #
+# The GdkPixdata loader, always built in
+#
+libstatic_pixbufloader_pixdata_la_SOURCES = io-pixdata.c
+
+#
 # The GIF loader
 #
 libstatic_pixbufloader_gif_la_SOURCES = io-gif.c io-gif-animation.c io-gif-animation.h
@@ -456,6 +461,9 @@ else
 QTIF_LIB = libpixbufloader-qtif.la
 endif
 
+# Always included
+STATIC_PIXDATA_LIB = libstatic-pixbufloader-pixdata.la
+
 if BUILD_DYNAMIC_MODULES
 
 loader_LTLIBRARIES = 	\
@@ -482,6 +490,7 @@ loader_LTLIBRARIES = 	\
 endif
 
 noinst_LTLIBRARIES =		\
+	$(STATIC_PIXDATA_LIB)	\
 	$(STATIC_PNG_LIB)	\
 	$(STATIC_BMP_LIB)	\
 	$(STATIC_WBMP_LIB)	\
@@ -501,8 +510,7 @@ noinst_LTLIBRARIES =		\
 	$(STATIC_QTIF_LIB)	\
 	$(STATIC_GDIPLUS_LIBS)
 
-builtin_objs = @INCLUDED_LOADER_OBJ@
-
+builtin_objs = @INCLUDED_LOADER_OBJ@ $(STATIC_PIXDATA_LIB)
 
 DEPS = libgdk_pixbuf-$(GDK_PIXBUF_API_VERSION).la
 INCLUDES = \
diff --git a/gdk-pixbuf/gdk-pixbuf-io.c b/gdk-pixbuf/gdk-pixbuf-io.c
index 4a8b9fd..da9705b 100644
--- a/gdk-pixbuf/gdk-pixbuf-io.c
+++ b/gdk-pixbuf/gdk-pixbuf-io.c
@@ -136,7 +136,6 @@
  */
 
 
-#ifndef GDK_PIXBUF_USE_GIO_MIME 
 static gint 
 format_check (GdkPixbufModule *module, guchar *buffer, int size)
 {
@@ -188,7 +187,6 @@ format_check (GdkPixbufModule *module, guchar *buffer, int size)
         }
         return 0;
 }
-#endif
 
 G_LOCK_DEFINE_STATIC (init_lock);
 G_LOCK_DEFINE_STATIC (threadunsafe_loader_lock);
@@ -436,6 +434,9 @@ gdk_pixbuf_io_init (void)
         else                                                            \
                 g_free (builtin_module)
 
+	/* Always include GdkPixdata format */
+        load_one_builtin_module (pixdata);
+
 #ifdef INCLUDE_ani
         load_one_builtin_module (ani);
 #endif
@@ -664,6 +665,7 @@ gdk_pixbuf_io_init (void)
   extern void _gdk_pixbuf__##type##_fill_info   (GdkPixbufFormat *info);   \
   extern void _gdk_pixbuf__##type##_fill_vtable (GdkPixbufModule *module)
 
+module (pixdata);
 module (png);
 module (jpeg);
 module (gif);
@@ -711,6 +713,9 @@ gdk_pixbuf_load_module_unlocked (GdkPixbufModule *image_module,
                 fill_info = _gdk_pixbuf__##id##_fill_info;              \
                 fill_vtable = _gdk_pixbuf__##id##_fill_vtable;  \
         }
+
+        try_module (pixdata,pixdata);
+
 #ifdef INCLUDE_png      
         try_module (png,png);
 #endif
@@ -918,6 +923,13 @@ _gdk_pixbuf_get_module (guchar *buffer, guint size,
                         }
                         g_free (type);
                 }
+
+		/* Make sure the builtin GdkPixdata support works even without mime sniffing */
+		if (strcmp (info->name, "GdkPixdata") == 0 &&
+		    format_check (module, buffer, size) == 100) {
+			selected = module;
+			break;
+		}
         }
         g_free (mime_type);
 #else
diff --git a/gdk-pixbuf/io-pixdata.c b/gdk-pixbuf/io-pixdata.c
new file mode 100644
index 0000000..08ae20b
--- /dev/null
+++ b/gdk-pixbuf/io-pixdata.c
@@ -0,0 +1,192 @@
+/* GdkPixdata loader
+ *
+ * Copyright (c) 2012 Alexander Larsson <alexl redhat com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include "gdk-pixbuf-private.h"
+#include "gdk-pixdata.h"
+
+G_MODULE_EXPORT void fill_vtable (GdkPixbufModule * module);
+G_MODULE_EXPORT void fill_info (GdkPixbufFormat * info);
+
+struct pixdata_context {
+  GdkPixbufModuleSizeFunc size_func;
+  GdkPixbufModuleUpdatedFunc updated_func;
+  GdkPixbufModulePreparedFunc prepared_func;
+  gpointer user_data;
+
+  GString *data;
+
+  GdkPixdata pixdata;
+  gboolean got_header;
+  gboolean got_pixbuf;
+};
+
+static void
+free_pixdata_context (struct pixdata_context *context)
+{
+  if (!context)
+    return;
+
+  g_free (context);
+}
+
+static gpointer
+pixdata_image_begin_load (GdkPixbufModuleSizeFunc size_func,
+			  GdkPixbufModulePreparedFunc prepared_func,
+			  GdkPixbufModuleUpdatedFunc updated_func,
+			  gpointer user_data, GError **error)
+{
+  struct pixdata_context *context;
+
+  context = g_new0 (struct pixdata_context, 1);
+  if (!context)
+    return NULL;
+
+  context->size_func = size_func;
+  context->updated_func = updated_func;
+  context->prepared_func = prepared_func;
+  context->user_data = user_data;
+
+  context->data = g_string_new ("");
+
+  return context;
+}
+
+static gboolean try_load (struct pixdata_context *context, GError **error)
+{
+  GdkPixbuf *pixbuf;
+
+  if (context->got_pixbuf)
+    return TRUE;
+
+  if (!gdk_pixdata_deserialize (&context->pixdata,
+				context->data->len,
+				(guchar *)context->data->str,
+				error))
+    return FALSE;
+
+  pixbuf = gdk_pixbuf_from_pixdata (&context->pixdata,
+				    TRUE, error);
+  if (pixbuf == NULL)
+    return FALSE;
+
+  context->got_pixbuf = TRUE;
+
+  if (context->prepared_func)
+    (* context->prepared_func) (pixbuf,
+				NULL,
+				context->user_data);
+  if (context->updated_func)
+    (* context->updated_func) (pixbuf, 0, 0, pixbuf->width, pixbuf->height, context->user_data);
+
+  return TRUE;
+}
+
+static gboolean
+pixdata_image_stop_load (gpointer data, GError **error)
+{
+  struct pixdata_context *context = (struct pixdata_context *) data;
+  gboolean res;
+
+  res = try_load (context, error);
+
+  g_string_free (context->data, TRUE);
+
+  free_pixdata_context (context);
+
+  return res;
+}
+
+static gboolean
+pixdata_image_load_increment (gpointer data, const guchar *buf, guint size, GError **error)
+{
+  struct pixdata_context *context = (struct pixdata_context *) data;
+
+  g_string_append_len (context->data, (char *)buf, size);
+
+  if (!context->got_header && context->data->len >= GDK_PIXDATA_HEADER_LENGTH)
+    {
+      /* This never reads past the header anyway, and we know we have at least
+	 the header size, so we pass it a really large size to avoid any error reporting
+	 due to missing data */
+      if (!gdk_pixdata_deserialize (&context->pixdata,
+				    G_MAXUINT,
+				    (guchar *)context->data->str,
+				    error))
+	return FALSE;
+
+      context->got_header = TRUE;
+
+      if (context->size_func)
+	{
+	  gint w = context->pixdata.width;
+	  gint h = context->pixdata.height;
+	  (* context->size_func) (&w, &h, context->user_data);
+
+	  if (w == 0 || h == 0)
+	    {
+	      g_set_error_literal (error,
+				   GDK_PIXBUF_ERROR,
+				   GDK_PIXBUF_ERROR_FAILED,
+				   _("Transformed pixbuf has zero width or height."));
+	      return FALSE;
+	    }
+	}
+    }
+
+  try_load (context, NULL);
+
+  return TRUE;
+}
+
+/* Always included */
+#define MODULE_ENTRY(function) void _gdk_pixbuf__pixdata_ ## function
+
+MODULE_ENTRY (fill_vtable) (GdkPixbufModule * module)
+{
+	module->begin_load = pixdata_image_begin_load;
+	module->stop_load = pixdata_image_stop_load;
+	module->load_increment = pixdata_image_load_increment;
+}
+
+MODULE_ENTRY (fill_info) (GdkPixbufFormat * info)
+{
+	static GdkPixbufModulePattern signature[] = {
+		{ "GdkP", NULL, 100 },		/* file begins with 'GdkP' at offset 0 */
+		{ NULL, NULL, 0 }
+	};
+	static gchar *mime_types[] = {
+		"image/x-gdkpixdata",
+		NULL
+	};
+	static gchar *extensions[] = {
+		"gdkp",
+		NULL
+	};
+
+	info->name = "GdkPixdata";
+	info->signature = signature;
+	info->description = N_("The GdkPixdata format");
+	info->mime_types = mime_types;
+	info->extensions = extensions;
+	info->flags = GDK_PIXBUF_FORMAT_THREADSAFE;
+	info->license = "LGPL";
+	info->disabled = FALSE;
+}



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