diff options
author | Benjamin Otte <otte@redhat.com> | 2011-03-23 14:45:25 +0100 |
---|---|---|
committer | Benjamin Otte <otte@redhat.com> | 2011-03-24 17:32:36 +0100 |
commit | 968e9ffb23f2a3b133d98b5bbea851253646da4c (patch) | |
tree | 75666df8aa8d7dff11b958c59d2c3bdbcbe4c505 | |
parent | 1722cff86cbc6a2f93696ac9c5331d731e9f91f4 (diff) |
Add a loader using GdkPixbuf
Use this to fall back when we don't have a dedicated loader for a
certain image type.
-rw-r--r-- | pig/Makefile.am | 22 | ||||
-rw-r--r-- | pig/pig-loader.c | 7 | ||||
-rw-r--r-- | pig/pig-pixbuf-loader-private.h | 55 | ||||
-rw-r--r-- | pig/pig-pixbuf-loader.c | 237 |
4 files changed, 318 insertions, 3 deletions
diff --git a/pig/Makefile.am b/pig/Makefile.am index 8027355..07cc987 100644 --- a/pig/Makefile.am +++ b/pig/Makefile.am @@ -1,16 +1,30 @@ lib_LTLIBRARIES = libpig-@PIG_MAJORMINOR@.la +loader_sources = +loader_headers = +loader_cflags = +loader_libs = + +if HAVE_PIXBUF +loader_sources += pig-pixbuf-loader.c +loader_headers += pig-pixbuf-loader-private.h +loader_cflags += $(PIXBUF_CFLAGS) +loader_libs += $(PIXBUF_LIBS) +endif + libpig_@PIG_MAJORMINOR@_la_SOURCES = \ pig-enums.c \ pig-loader.c \ pig-loading.c \ pig-marshal.c \ pig-picture.c \ - pig-version.c + pig-version.c \ + $(loader_sources) libpig_@PIG_MAJORMINOR@_la_CFLAGS = \ -I$(top_srcdir) $(GLOBAL_CFLAGS) \ $(CAIRO_CFLAGS) $(GLIB_CFLAGS) \ + $(loader_cflags) \ -DG_LOG_DOMAIN=\"Pig\" \ -DPIG_COMPILATION @@ -18,7 +32,8 @@ libpig_@PIG_MAJORMINOR@_la_LDFLAGS = \ $(SYMBOLIC_LDFLAGS) \ -version-info $(PIG_LIBVERSION) \ -export-symbols-regex '^(pig_.*)' \ - $(CAIRO_LIBS) $(GLIB_LIBS) + $(CAIRO_LIBS) $(GLIB_LIBS) \ + $(loader_libs) public_headers = \ pig.h \ @@ -63,7 +78,8 @@ nodist_libpig_@PIG_MAJORMINOR@include_HEADERS = \ noinst_HEADERS = \ pig-loader-private.h \ pig-marshal-private.h \ - pig-pixbuf-shared-private.h + pig-pixbuf-shared-private.h \ + $(loader_headers) EXTRA_DIST = \ pig-marshal.list \ diff --git a/pig/pig-loader.c b/pig/pig-loader.c index d208b18..cc01ab4 100644 --- a/pig/pig-loader.c +++ b/pig/pig-loader.c @@ -26,6 +26,10 @@ #include "pig-loading.h" +#ifdef HAVE_PIXBUF +#include "pig-pixbuf-loader-private.h" +#endif + G_DEFINE_INTERFACE (PigLoader, _pig_loader, PIG_TYPE_PICTURE) static void @@ -36,6 +40,9 @@ _pig_loader_default_init (PigLoaderInterface *iface) typedef GType (* GetTypeFunc) (void); GetTypeFunc registered_loaders[] = { +#ifdef HAVE_PIXBUF + _pig_pixbuf_loader_get_type, +#endif NULL }; diff --git a/pig/pig-pixbuf-loader-private.h b/pig/pig-pixbuf-loader-private.h new file mode 100644 index 0000000..bd8f49e --- /dev/null +++ b/pig/pig-pixbuf-loader-private.h @@ -0,0 +1,55 @@ +/* Pig + * Copyright (C) 2011 Benjamin Otte <otte@gnome.org> + * + * 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. + */ + +#ifndef __PIG_PIXBUF_LOADER_PRIVATE_H__ +#define __PIG_PIXBUF_LOADER_PRIVATE_H__ + +#include <pig/pig-picture.h> + + +G_BEGIN_DECLS + +#define PIG_TYPE_PIXBUF_LOADER (_pig_pixbuf_loader_get_type ()) +#define PIG_PIXBUF_LOADER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), PIG_TYPE_PIXBUF_LOADER, PigPixbufLoader)) +#define PIG_PIXBUF_LOADER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIG_TYPE_PIXBUF_LOADER, PigPixbufLoaderClass)) +#define PIG_IS_PIXBUF_LOADER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PIG_TYPE_PIXBUF_LOADER)) +#define PIG_IS_PIXBUF_LOADER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIG_TYPE_PIXBUF_LOADER)) +#define PIG_PIXBUF_LOADER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIG_TYPE_PIXBUF_LOADER, PigPixbufLoaderClass)) + +typedef struct _PigPixbufLoader PigPixbufLoader; +typedef struct _PigPixbufLoaderPrivate PigPixbufLoaderPrivate; +typedef struct _PigPixbufLoaderClass PigPixbufLoaderClass; + +struct _PigPixbufLoader { + /*< private >*/ + PigPicture parent_picture; + + PigPixbufLoaderPrivate *priv; +}; + +struct _PigPixbufLoaderClass { + /*< private >*/ + PigPictureClass parent_class; +}; + +GType _pig_pixbuf_loader_get_type (void); + +G_END_DECLS + +#endif /* __PIG_PIXBUF_LOADER_PRIVATE_H__ */ diff --git a/pig/pig-pixbuf-loader.c b/pig/pig-pixbuf-loader.c new file mode 100644 index 0000000..8514626 --- /dev/null +++ b/pig/pig-pixbuf-loader.c @@ -0,0 +1,237 @@ +/* Pig + * Copyright (C) 2011 Benjamin Otte <otte@gnome.org> + * + * 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 "pig-pixbuf-loader-private.h" + +#include <glib/gi18n.h> + +#include "pig-loader-private.h" +#include "pig-pixbuf-shared-private.h" + +struct _PigPixbufLoaderPrivate { + cairo_surface_t *surface; + + /* only valid while loading */ + GdkPixbufLoader *loader; +}; + +static char ** +pig_pixbuf_loader_get_mime_types (void) +{ + GPtrArray *mime_types; + GSList *formats, *walk; + + mime_types = g_ptr_array_new (); + formats = gdk_pixbuf_get_formats (); + + for (walk = formats; walk; walk = walk->next) + { + GdkPixbufFormat *format = walk->data; + char **format_types; + guint i; + + format_types = gdk_pixbuf_format_get_mime_types (format); + if (format_types == NULL) + continue; + + for (i = 0; format_types[i]; i++) + { + g_ptr_array_add (mime_types, format_types[i]); + } + + g_free (format_types); + } + + g_ptr_array_add (mime_types, NULL); + + g_slist_free (formats); + + return (char **) g_ptr_array_free (mime_types, FALSE); +} + +static void +pig_pixbuf_loader_finish_load (PigPixbufLoader *loader) +{ + PigPixbufLoaderPrivate *priv = loader->priv; + + g_object_unref (priv->loader); + priv->loader = NULL; +} + +static gboolean +pig_pixbuf_loader_write (PigLoader * loader, + const guchar *data, + gsize size, + GError ** error) +{ + PigPixbufLoader *pixbuf_loader = PIG_PIXBUF_LOADER (loader); + + if (!gdk_pixbuf_loader_write (pixbuf_loader->priv->loader, + data, + size, + error)) + { + pig_pixbuf_loader_finish_load (pixbuf_loader); + return FALSE; + } + + return TRUE; +} + +static gboolean +pig_pixbuf_loader_close (PigLoader * loader, + GError ** error) +{ + PigPixbufLoader *pixbuf_loader = PIG_PIXBUF_LOADER (loader); + gboolean result; + + result = gdk_pixbuf_loader_close (pixbuf_loader->priv->loader, + error); + + pig_pixbuf_loader_finish_load (pixbuf_loader); + + return result; +} + +static void +pig_pixbuf_loader_loader_init (PigLoaderInterface *iface) +{ + /* XXX: This will leak when the class is unreffed, omg! */ + iface->mime_types = (const char const **) pig_pixbuf_loader_get_mime_types (); + + iface->write = pig_pixbuf_loader_write; + iface->close = pig_pixbuf_loader_close; +} + +G_DEFINE_TYPE_WITH_CODE (PigPixbufLoader, _pig_pixbuf_loader, PIG_TYPE_PICTURE, + G_IMPLEMENT_INTERFACE (PIG_TYPE_LOADER, pig_pixbuf_loader_loader_init)) + +static void +pig_pixbuf_loader_dispose (GObject *object) +{ + PigPixbufLoader *loader = PIG_PIXBUF_LOADER (object); + PigPixbufLoaderPrivate *priv = loader->priv; + + if (priv->surface) + { + cairo_surface_destroy (priv->surface); + priv->surface = NULL; + } + if (priv->loader) + { + g_object_unref (priv->loader); + priv->loader = NULL; + } + + G_OBJECT_CLASS (_pig_pixbuf_loader_parent_class)->dispose (object); +} + +static cairo_surface_t * +pig_pixbuf_loader_ref_surface (PigPicture *picture) +{ + PigPixbufLoader *loader = PIG_PIXBUF_LOADER (picture); + PigPixbufLoaderPrivate *priv = loader->priv; + + if (priv->surface == NULL) + return cairo_image_surface_create (CAIRO_FORMAT_ARGB32, + pig_picture_get_width (PIG_PICTURE (loader)), + pig_picture_get_height (PIG_PICTURE (loader))); + + return cairo_surface_reference (priv->surface); +} + +static void +_pig_pixbuf_loader_class_init (PigPixbufLoaderClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + PigPictureClass *picture_class = PIG_PICTURE_CLASS (klass); + + object_class->dispose = pig_pixbuf_loader_dispose; + + picture_class->ref_surface = pig_pixbuf_loader_ref_surface; + + g_type_class_add_private (klass, sizeof (PigPixbufLoaderPrivate)); +} + +static void +pig_pixbuf_loader_size_prepared (GdkPixbufLoader *loader, + int width, + int height, + PigPixbufLoader *picture) +{ + g_assert (picture->priv->surface == NULL); + + pig_picture_resized (PIG_PICTURE (picture), width, height); +} + +static void +pig_pixbuf_loader_area_updated (GdkPixbufLoader *loader, + int x, + int y, + int width, + int height, + PigPixbufLoader *picture) +{ + PigPixbufLoaderPrivate *priv = loader->priv; + + if (priv->surface == NULL) + { + priv->surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, + pig_picture_get_width (PIG_PICTURE (loader)), + pig_picture_get_height (PIG_PICTURE (loader))); + } + + _pig_pixbuf_copy_to_surface (priv->surface, + gdk_pixbuf_loader_get_pixbuf (loader), + x, y, width, height); +} + +static GdkPixbufLoader * +pig_pixbuf_loader_create_loader (PigPixbufLoader *loader) +{ + GdkPixbufLoader *pixbuf_loader; + + pixbuf_loader = gdk_pixbuf_loader_new (); + g_signal_connect (pixbuf_loader, + "size-prepared", + G_CALLBACK (pig_pixbuf_loader_size_prepared), + loader); + g_signal_connect (pixbuf_loader, + "area-updated", + G_CALLBACK (pig_pixbuf_loader_area_updated), + loader); + + return pixbuf_loader; +} + +static void +_pig_pixbuf_loader_init (PigPixbufLoader *picture) +{ + PigPixbufLoaderPrivate *priv; + + picture->priv = G_TYPE_INSTANCE_GET_PRIVATE (picture, + PIG_TYPE_PIXBUF_LOADER, + PigPixbufLoaderPrivate); + priv = picture->priv; + + priv->loader = pig_pixbuf_loader_create_loader (picture); +} + |