[clutter/wip/actor-content: 3/24] Add a module-based ImageLoader class



commit 698c825a250d8ff59692ec3c96636ed84739315f
Author: Emmanuele Bassi <ebassi linux intel com>
Date:   Mon Dec 6 17:39:56 2010 +0000

    Add a module-based ImageLoader class
    
    The ImageLoader is an abstract class that can be implemented through GIO
    extension points.

 clutter/Makefile.am                               |   14 ++
 clutter/clutter-image-loader.c                    |  153 +++++++++++++++++++++
 clutter/clutter-image-loader.h                    |  101 ++++++++++++++
 clutter/clutter-main.c                            |   67 +++++++++
 clutter/clutter-private.h                         |    2 +
 clutter/clutter.h                                 |    1 +
 clutter/image-loaders/clutter-image-loader-null.c |   68 +++++++++
 clutter/image-loaders/clutter-image-loader-null.h |   19 +++
 configure.ac                                      |    4 +-
 9 files changed, 428 insertions(+), 1 deletions(-)
---
diff --git a/clutter/Makefile.am b/clutter/Makefile.am
index 4e705e8..8d4ced7 100644
--- a/clutter/Makefile.am
+++ b/clutter/Makefile.am
@@ -23,6 +23,7 @@ INCLUDES = \
 	-I$(top_srcdir)/clutter/$(CLUTTER_WINSYS_BASE)	\
 	-I$(top_srcdir)/clutter/cally			\
 	-I$(top_srcdir)/clutter/evdev			\
+	-I$(top_srcdir)/clutter/image-loaders		\
 	-I$(top_builddir)				\
 	-I$(top_builddir)/clutter			\
 	$(NULL)
@@ -113,6 +114,7 @@ source_h =					\
 	$(srcdir)/clutter-flow-layout.h		\
 	$(srcdir)/clutter-frame-source.h        \
 	$(srcdir)/clutter-group.h 		\
+	$(srcdir)/clutter-image-loader.h	\
 	$(srcdir)/clutter-image.h		\
 	$(srcdir)/clutter-input-device.h	\
         $(srcdir)/clutter-interval.h            \
@@ -196,6 +198,7 @@ source_c = \
 	$(srcdir)/clutter-flow-layout.c		\
 	$(srcdir)/clutter-frame-source.c	\
 	$(srcdir)/clutter-group.c 		\
+	$(srcdir)/clutter-image-loader.c	\
 	$(srcdir)/clutter-image.c		\
 	$(srcdir)/clutter-input-device.c	\
 	$(srcdir)/clutter-interval.c            \
@@ -599,6 +602,15 @@ cally_include_HEADERS = $(cally_sources_h)
 pc_files += cally/cally-$(CLUTTER_API_VERSION).pc
 EXTRA_DIST += cally/cally.pc.in
 
+# image loader backends
+imageloader_sources_c = \
+	$(srcdir)/image-loaders/clutter-image-loader-null.c 	\
+	$(NULL)
+
+imageloader_sources_h = \
+	$(srcdir)/image-loaders/clutter-image-loader-null.h	\
+	$(NULL)
+
 # general build rules:
 # you should not need to modify anything below this point
 
@@ -652,6 +664,8 @@ libclutter_ CLUTTER_SONAME_INFIX@_ CLUTTER_API_VERSION@_la_SOURCES = \
 	$(backend_source_h) \
 	$(backend_source_c_priv) \
 	$(backend_source_h_priv) \
+	$(imageloader_sources_c) \
+	$(imageloader_sources_h) \
 	$(source_c) \
 	$(source_h) \
 	$(source_c_priv) \
diff --git a/clutter/clutter-image-loader.c b/clutter/clutter-image-loader.c
new file mode 100644
index 0000000..287ddae
--- /dev/null
+++ b/clutter/clutter-image-loader.c
@@ -0,0 +1,153 @@
+#include "config.h"
+
+#include "clutter-image-loader.h"
+
+#include <string.h>
+#include <gio/gio.h>
+
+#include "clutter-private.h"
+
+G_DEFINE_ABSTRACT_TYPE (ClutterImageLoader, clutter_image_loader, G_TYPE_OBJECT);
+
+static void
+clutter_image_loader_class_init (ClutterImageLoaderClass *klass)
+{
+}
+
+static void
+clutter_image_loader_init (ClutterImageLoader *loader)
+{
+}
+
+static gpointer
+get_default_image_loader (gpointer data)
+{
+  ClutterImageLoaderClass *chosen_class;
+  ClutterImageLoaderClass **ret = data;
+  GIOExtensionPoint *ep;
+  GList *extensions, *l;
+
+  _clutter_io_modules_ensure_loaded ();
+
+  ep = g_io_extension_point_lookup (CLUTTER_IMAGE_LOADER_EXTENSION_POINT_NAME);
+
+  extensions = g_io_extension_point_get_extensions (ep);
+
+  chosen_class = NULL;
+  for (l = extensions; l != NULL; l = l->next)
+    {
+      GIOExtension *extension = l->data;
+      ClutterImageLoaderClass *klass;
+
+      klass = CLUTTER_IMAGE_LOADER_CLASS (g_io_extension_ref_class (extension));
+
+      if (klass->is_supported ())
+        {
+          chosen_class = klass;
+          break;
+        }
+      else
+        g_type_class_unref (klass);
+    }
+
+  if (chosen_class)
+    {
+      *ret = chosen_class;
+      return (gpointer) G_TYPE_FROM_CLASS (chosen_class);
+    }
+  else
+    return (gpointer) G_TYPE_INVALID;
+}
+
+ClutterImageLoader *
+_clutter_image_loader_new (void)
+{
+  static GOnce once_init = G_ONCE_INIT;
+  GTypeClass *type_class = NULL;
+  ClutterImageLoader *loader;
+  GType type = G_TYPE_INVALID;
+
+  g_once (&once_init, get_default_image_loader, &type_class);
+  type = (GType) once_init.retval;
+  if (type == G_TYPE_INVALID)
+    {
+      g_critical ("Unable to load the default image loader. Check the "
+                  "compilation options of Clutter.");
+      return NULL;
+    }
+
+  loader = g_object_new (type, NULL);
+
+  if (type_class != NULL)
+    g_type_class_unref (type_class);
+
+  return loader;
+}
+
+void
+_clutter_image_loader_get_image_size (ClutterImageLoader *loader,
+                                      gint               *width,
+                                      gint               *height)
+{
+  g_return_if_fail (CLUTTER_IS_IMAGE_LOADER (loader));
+
+  CLUTTER_IMAGE_LOADER_GET_CLASS (loader)->get_image_size (loader,
+                                                           width,
+                                                           height);
+}
+
+CoglHandle
+_clutter_image_loader_get_texture_handle (ClutterImageLoader *loader)
+{
+  g_return_val_if_fail (CLUTTER_IS_IMAGE_LOADER (loader), NULL);
+
+  return CLUTTER_IMAGE_LOADER_GET_CLASS (loader)->get_texture_handle (loader);
+}
+
+gboolean
+_clutter_image_loader_load_stream (ClutterImageLoader  *loader,
+                                   GInputStream        *stream,
+                                   GCancellable        *cancellable,
+                                   GError             **error)
+{
+  g_return_val_if_fail (CLUTTER_IS_IMAGE_LOADER (loader), FALSE);
+  g_return_val_if_fail (G_IS_INPUT_STREAM (stream), FALSE);
+  g_return_val_if_fail (cancellable == NULL ||
+                        G_IS_CANCELLABLE (cancellable), FALSE);
+
+
+  return CLUTTER_IMAGE_LOADER_GET_CLASS (loader)->load_stream (loader, stream,
+                                                               cancellable,
+                                                               error);
+}
+
+void
+_clutter_image_loader_load_stream_async (ClutterImageLoader  *loader,
+                                         GInputStream        *stream,
+                                         GCancellable        *cancellable,
+                                         GAsyncReadyCallback  callback,
+                                         gpointer             user_data)
+{
+  g_return_if_fail (CLUTTER_IS_IMAGE_LOADER (loader));
+  g_return_if_fail (G_IS_INPUT_STREAM (stream));
+  g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+  g_return_if_fail (callback != NULL);
+
+  CLUTTER_IMAGE_LOADER_GET_CLASS (loader)->load_stream_async (loader, stream,
+                                                              cancellable,
+                                                              callback,
+                                                              user_data);
+}
+
+gboolean
+_clutter_image_loader_load_stream_finish (ClutterImageLoader  *loader,
+                                          GAsyncResult        *result,
+                                          GError             **error)
+{
+  g_return_val_if_fail (CLUTTER_IS_IMAGE_LOADER (loader), FALSE);
+  g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
+
+  return CLUTTER_IMAGE_LOADER_GET_CLASS (loader)->load_stream_finish (loader,
+                                                                      result,
+                                                                      error);
+}
diff --git a/clutter/clutter-image-loader.h b/clutter/clutter-image-loader.h
new file mode 100644
index 0000000..02b014f
--- /dev/null
+++ b/clutter/clutter-image-loader.h
@@ -0,0 +1,101 @@
+#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
+#error "Only <clutter/clutter.h> can be included directly."
+#endif
+
+#ifndef __CLUTTER_IMAGE_LOADER_H__
+#define __CLUTTER_IMAGE_LOADER_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <cogl/cogl.h>
+
+G_BEGIN_DECLS
+
+#define CLUTTER_TYPE_IMAGE_LOADER               (clutter_image_loader_get_type ())
+#define CLUTTER_IMAGE_LOADER(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_IMAGE_LOADER, ClutterImageLoader))
+#define CLUTTER_IS_IMAGE_LOADER(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_IMAGE_LOADER))
+#define CLUTTER_IMAGE_LOADER_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_IMAGE_LOADER, ClutterImageLoaderClass))
+#define CLUTTER_IS_IMAGE_LOADER_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_IMAGE_LOADER))
+#define CLUTTER_IMAGE_LOADER_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_IMAGE_LOADER, ClutterImageLoaderClass))
+
+#define CLUTTER_IMAGE_LOADER_EXTENSION_POINT_NAME       "clutter-image-loader"
+
+typedef struct _ClutterImageLoader              ClutterImageLoader;
+typedef struct _ClutterImageLoaderClass         ClutterImageLoaderClass;
+
+struct _ClutterImageLoader
+{
+  GObject parent_instance;
+};
+
+struct _ClutterImageLoaderClass
+{
+  GObjectClass parent_class;
+
+  gboolean (* is_supported) (void);
+
+  gboolean (* load_stream) (ClutterImageLoader *loader,
+                            GInputStream       *stream,
+                            GCancellable       *cancellable,
+                            GError            **error);
+
+  void (* load_stream_async) (ClutterImageLoader *loader,
+                              GInputStream       *stream,
+                              GCancellable       *cancellable,
+                              GAsyncReadyCallback      callback,
+                              gpointer            user_data);
+  gboolean (* load_stream_finish) (ClutterImageLoader  *loader,
+                                   GAsyncResult        *result,
+                                   GError             **error);
+
+  void (* get_image_size) (ClutterImageLoader *loader,
+                           gint               *width,
+                           gint               *height);
+
+  CoglHandle (* get_texture_handle) (ClutterImageLoader *loader);
+
+  void (* _clutter_image_loader__1) (void);
+  void (* _clutter_image_loader__2) (void);
+  void (* _clutter_image_loader__3) (void);
+  void (* _clutter_image_loader__4) (void);
+  void (* _clutter_image_loader__5) (void);
+  void (* _clutter_image_loader__6) (void);
+  void (* _clutter_image_loader__7) (void);
+  void (* _clutter_image_loader__8) (void);
+  void (* _clutter_image_loader__9) (void);
+  void (* _clutter_image_loader_10) (void);
+  void (* _clutter_image_loader_11) (void);
+  void (* _clutter_image_loader_12) (void);
+  void (* _clutter_image_loader_13) (void);
+};
+
+GType clutter_image_loader_get_type (void) G_GNUC_CONST;
+
+/*
+ * private
+ */
+
+ClutterImageLoader *    _clutter_image_loader_new                       (void);
+
+void                    _clutter_image_loader_get_image_size            (ClutterImageLoader   *loader,
+                                                                         gint                 *width,
+                                                                         gint                 *height);
+CoglHandle              _clutter_image_loader_get_texture_handle        (ClutterImageLoader   *loader);
+
+gboolean                _clutter_image_loader_load_stream               (ClutterImageLoader   *loader,
+                                                                         GInputStream         *stream,
+                                                                         GCancellable         *cancellable,
+                                                                         GError              **error);
+
+void                    _clutter_image_loader_load_stream_async         (ClutterImageLoader   *loader,
+                                                                         GInputStream         *stream,
+                                                                         GCancellable         *cancellable,
+                                                                         GAsyncReadyCallback   callback,
+                                                                         gpointer              user_data);
+gboolean                _clutter_image_loader_load_stream_finish        (ClutterImageLoader   *loader,
+                                                                         GAsyncResult         *result,
+                                                                         GError              **error);
+
+G_END_DECLS
+
+#endif /* __CLUTTER_IMAGE_LOADER_H__ */
diff --git a/clutter/clutter-main.c b/clutter/clutter-main.c
index c7d2f30..1a74ba4 100644
--- a/clutter/clutter-main.c
+++ b/clutter/clutter-main.c
@@ -92,6 +92,7 @@
 
 #include <stdlib.h>
 #include <glib/gi18n-lib.h>
+#include <gio/gio.h>
 #include <locale.h>
 
 #include "clutter-actor.h"
@@ -101,6 +102,7 @@
 #include "clutter-event.h"
 #include "clutter-feature.h"
 #include "clutter-frame-source.h"
+#include "clutter-image-loader.h"
 #include "clutter-main.h"
 #include "clutter-master-clock.h"
 #include "clutter-private.h"
@@ -3090,3 +3092,68 @@ _clutter_context_pop_shader_stack (ClutterActor *actor)
 
   return _clutter_context_peek_shader_stack ();
 }
+
+/*
+ * Clutter modules
+ */
+
+G_LOCK_DEFINE_STATIC (registered_extensions);
+G_LOCK_DEFINE_STATIC (loaded_dirs);
+
+void
+_clutter_io_modules_ensure_extensions_registered (void)
+{
+  static gboolean registered_extensions = FALSE;
+  GIOExtensionPoint *ep;
+
+  G_LOCK (registered_extensions);
+
+  if (!registered_extensions)
+    {
+      registered_extensions = TRUE;
+
+      /* register the extension points we expose */
+
+      ep = g_io_extension_point_register (CLUTTER_IMAGE_LOADER_EXTENSION_POINT_NAME);
+      g_io_extension_point_set_required_type (ep, CLUTTER_TYPE_IMAGE_LOADER);
+    }
+
+  G_UNLOCK (registered_extensions);
+}
+
+void
+_clutter_io_modules_ensure_loaded (void)
+{
+  static gboolean loaded_dirs = FALSE;
+  const gchar *module_path;
+
+  _clutter_io_modules_ensure_extensions_registered ();
+
+  G_LOCK (loaded_dirs);
+
+  if (!loaded_dirs)
+    {
+      loaded_dirs = TRUE;
+
+      g_io_modules_scan_all_in_directory (CLUTTER_MODULEDIR);
+
+      module_path = g_getenv ("CLUTTER_EXTRA_MODULES");
+
+      if (module_path)
+        {
+          gchar **paths;
+          int i;
+
+          paths = g_strsplit (module_path, ":", 0);
+
+          for (i = 0; paths[i] != NULL; i++)
+            g_io_modules_scan_all_in_directory (paths[i]);
+
+          g_strfreev (paths);
+        }
+
+      /* XXX Initialize types from built-in "modules" here XXX */
+    }
+
+  G_UNLOCK (loaded_dirs);
+}
diff --git a/clutter/clutter-private.h b/clutter/clutter-private.h
index 7476f0e..610e017 100644
--- a/clutter/clutter-private.h
+++ b/clutter/clutter-private.h
@@ -241,6 +241,8 @@ typedef enum _ClutterCullResult
   CLUTTER_CULL_RESULT_PARTIAL
 } ClutterCullResult;
 
+void _clutter_io_modules_ensure_loaded (void);
+
 G_END_DECLS
 
 #endif /* __CLUTTER_PRIVATE_H__ */
diff --git a/clutter/clutter.h b/clutter/clutter.h
index fae0766..1baf56e 100644
--- a/clutter/clutter.h
+++ b/clutter/clutter.h
@@ -74,6 +74,7 @@
 #include "clutter-flow-layout.h"
 #include "clutter-frame-source.h"
 #include "clutter-group.h"
+#include "clutter-image-loader.h"
 #include "clutter-image.h"
 #include "clutter-input-device.h"
 #include "clutter-interval.h"
diff --git a/clutter/image-loaders/clutter-image-loader-null.c b/clutter/image-loaders/clutter-image-loader-null.c
new file mode 100644
index 0000000..150fbc1
--- /dev/null
+++ b/clutter/image-loaders/clutter-image-loader-null.c
@@ -0,0 +1,68 @@
+#include "config.h"
+
+#include "clutter-image-loader-null.h"
+
+#include <cogl/cogl.h>
+#include <gio/gio.h>
+
+struct _ClutterImageLoaderNull
+{
+  ClutterImageLoader parent_instance;
+};
+
+#define clutter_image_loader_null_get_type    _clutter_image_loader_null_get_type
+G_DEFINE_TYPE_WITH_CODE (ClutterImageLoaderNull,
+                         clutter_image_loader_null,
+                         CLUTTER_TYPE_IMAGE_LOADER,
+                         g_io_extension_point_implement (CLUTTER_IMAGE_LOADER_EXTENSION_POINT_NAME,
+                                                         g_define_type_id,
+                                                         "null",
+                                                         0));
+
+static void
+clutter_image_loader_null_finalize (GObject *gobject)
+{
+  G_OBJECT_CLASS (clutter_image_loader_null_parent_class)->finalize (gobject);
+}
+
+static gboolean
+clutter_image_loader_null_is_supported (void)
+{
+  return FALSE;
+}
+
+static void
+clutter_image_loader_null_get_image_size (ClutterImageLoader *loader,
+                                          gint               *width,
+                                          gint               *height)
+{
+  if (width)
+    *width = 0;
+
+  if (height)
+    *height = 0;
+}
+
+static CoglHandle
+clutter_image_loader_null_get_texture_handle (ClutterImageLoader *loader)
+{
+  return COGL_INVALID_HANDLE;
+}
+
+static void
+clutter_image_loader_null_class_init (ClutterImageLoaderNullClass *klass)
+{
+  ClutterImageLoaderClass *loader_class = CLUTTER_IMAGE_LOADER_CLASS (klass);
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  gobject_class->finalize = clutter_image_loader_null_finalize;
+
+  loader_class->is_supported = clutter_image_loader_null_is_supported;
+  loader_class->get_image_size = clutter_image_loader_null_get_image_size;
+  loader_class->get_texture_handle = clutter_image_loader_null_get_texture_handle;
+}
+
+static void
+clutter_image_loader_null_init (ClutterImageLoaderNull *loader)
+{
+}
diff --git a/clutter/image-loaders/clutter-image-loader-null.h b/clutter/image-loaders/clutter-image-loader-null.h
new file mode 100644
index 0000000..8ecded4
--- /dev/null
+++ b/clutter/image-loaders/clutter-image-loader-null.h
@@ -0,0 +1,19 @@
+#ifndef __CLUTTER_IMAGE_LOADER_NULL_H__
+#define __CLUTTER_IMAGE_LOADER_NULL_H__
+
+#include <clutter/clutter-image-loader.h>
+
+G_BEGIN_DECLS
+
+#define CLUTTER_TYPE_IMAGE_LOADER_NULL          (_clutter_image_loader_null_get_type ())
+#define CLUTTER_IMAGE_LOADER_NULL(obj)          (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_IMAGE_LOADER_NULL, ClutterImageLoaderNull))
+#define CLUTTER_IS_IMAGE_LOADER_NULL(obj)       (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_IMAGE_LOADER_NULL))
+
+typedef struct _ClutterImageLoaderNull          ClutterImageLoaderNull;
+typedef struct _ClutterImageLoaderClass         ClutterImageLoaderNullClass;
+
+GType _clutter_image_loader_null_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* __CLUTTER_IMAGE_LOADER_NULL_H__ */
diff --git a/configure.ac b/configure.ac
index c1b2d2e..9bc5e2f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -155,7 +155,7 @@ AC_SUBST([XCOMPOSITE_REQ_VERSION], [xcomposite_req_version])
 AM_PATH_GLIB_2_0([glib_req_version],
                  [],
                  [AC_MSG_ERROR([glib-2.0 is required])],
-                 [gobject gthread gmodule-no-export])
+                 [gobject gthread gmodule-no-export gio])
 
 # Check for -Bsymbolic-functions to avoid intra-library PLT jumps
 AC_ARG_ENABLE([Bsymbolic],
@@ -800,6 +800,8 @@ AS_CASE([$COGL_IMAGE_BACKEND],
         [AC_MSG_ERROR([Unknown argument for --with-imagebackend])]
 )
 
+AM_CONDITIONAL([SUPPORT_GDK_PIXBUF], [test "x$COGL_IMAGE_BACKEND" = "xgdk-pixbuf"])
+
 dnl === X11 checks, only for X11-based backends ===============================
 X11_PC_FILES=""
 x11_tests=no



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