[gtk+] GdkPixbuf loader for QTIF format



commit 4b22b461b6ece49563fef808ff8d3b2fe6660713
Author: Kevin Peng <kevin zycomtech com>
Date:   Sun Oct 25 22:03:19 2009 +0100

    GdkPixbuf loader for QTIF format
    
    Fixes https://bugzilla.gnome.org/show_bug.cgi?id=366217

 configure.in               |    3 +-
 gdk-pixbuf/Makefile.am     |   16 ++
 gdk-pixbuf/gdk-pixbuf-io.c |    7 +
 gdk-pixbuf/io-qtif.c       |  607 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 632 insertions(+), 1 deletions(-)
---
diff --git a/configure.in b/configure.in
index 1e0a0a8..13409b0 100644
--- a/configure.in
+++ b/configure.in
@@ -990,7 +990,7 @@ fi
 # because some important apps like GIMP need to read and write
 # arbitrary tEXt chunks which doesn't seem to be possible through GDI+
 
-all_loaders="ani,icns,pcx,ras,tga,png,pnm,wbmp,xbm,xpm"
+all_loaders="ani,icns,pcx,ras,tga,png,pnm,wbmp,xbm,xpm,qtif"
 if test x$with_libjasper != xno; then
   all_loaders="$all_loaders,jasper"
 fi
@@ -1061,6 +1061,7 @@ AM_CONDITIONAL(INCLUDE_TGA, [test x"$INCLUDE_tga" = xyes])
 AM_CONDITIONAL(INCLUDE_PCX, [test x"$INCLUDE_pcx" = xyes])
 AM_CONDITIONAL(INCLUDE_ICNS, [test x"$INCLUDE_icns" = xyes])
 AM_CONDITIONAL(INCLUDE_JASPER, [test x"$INCLUDE_jasper" = xyes])
+AM_CONDITIONAL(INCLUDE_QTIF, [test x"$INCLUDE_qtif" = xyes])
 # As all GDI+ loaders are either built-in or not, arbitrarily just
 # check one of the variables here
 AM_CONDITIONAL(INCLUDE_GDIPLUS, [test x"$INCLUDE_gdip_ico" = xyes])
diff --git a/gdk-pixbuf/Makefile.am b/gdk-pixbuf/Makefile.am
index 39b52f3..ae6e2ea 100644
--- a/gdk-pixbuf/Makefile.am
+++ b/gdk-pixbuf/Makefile.am
@@ -193,6 +193,14 @@ libpixbufloader_jasper_la_SOURCES = io-jasper.c
 libpixbufloader_jasper_la_LDFLAGS = -avoid-version -module $(no_undefined)
 libpixbufloader_jasper_la_LIBADD = $(LIBJASPER) $(module_libs)
 
+#
+# The QTIF loader
+#
+libstatic_pixbufloader_qtif_la_SOURCES = io-qtif.c
+libpixbufloader_qtif_la_SOURCES = io-qtif.c
+libpixbufloader_qtif_la_LDFLAGS = -avoid-version -module $(no_undefined)
+libpixbufloader_qtif_la_LIBADD = $(module_libs)
+
 if BUILD_GDIPLUS_LOADERS
 
 if INCLUDE_GDIPLUS
@@ -451,6 +459,12 @@ JASPER_LIB = libpixbufloader-jasper.la
 endif
 endif
 
+if INCLUDE_QTIF
+STATIC_QTIF_LIB = libstatic-pixbufloader-qtif.la
+else
+QTIF_LIB = libpixbufloader-qtif.la
+endif
+
 if BUILD_DYNAMIC_MODULES
 
 loader_LTLIBRARIES = 	\
@@ -470,6 +484,7 @@ loader_LTLIBRARIES = 	\
 	$(ICNS_LIB)	\
 	$(PCX_LIB)	\
 	$(JASPER_LIB)	\
+	$(QTIF_LIB)	\
 	$(GDIPLUS_LIBS)
 
 
@@ -492,6 +507,7 @@ noinst_LTLIBRARIES =		\
 	$(STATIC_ICNS_LIB)	\
 	$(STATIC_PCX_LIB)	\
 	$(STATIC_JASPER_LIB)	\
+	$(STATIC_QTIF_LIB)	\
 	$(STATIC_GDIPLUS_LIBS)
 
 builtin_objs = @INCLUDED_LOADER_OBJ@
diff --git a/gdk-pixbuf/gdk-pixbuf-io.c b/gdk-pixbuf/gdk-pixbuf-io.c
index 646b0f1..56271e1 100644
--- a/gdk-pixbuf/gdk-pixbuf-io.c
+++ b/gdk-pixbuf/gdk-pixbuf-io.c
@@ -396,6 +396,9 @@ gdk_pixbuf_io_init (void)
 #ifdef INCLUDE_jasper
 	load_one_builtin_module (jasper);
 #endif
+#ifdef INCLUDE_qtif
+	load_one_builtin_module (qtif);
+#endif
 #ifdef INCLUDE_gdiplus
 	/* We don't bother having the GDI+ loaders individually selectable
 	 * for building in or not.
@@ -589,6 +592,7 @@ module (tga);
 module (pcx);
 module (icns);
 module (jasper);
+module (qtif);
 module (gdip_ico);
 module (gdip_wmf);
 module (gdip_emf);
@@ -667,6 +671,9 @@ gdk_pixbuf_load_module_unlocked (GdkPixbufModule *image_module,
 #ifdef INCLUDE_jasper
 	try_module (jasper,jasper);
 #endif
+#ifdef INCLUDE_qtif
+	try_module (qtif,qtif);
+#endif
 #ifdef INCLUDE_gdiplus
 	try_module (ico,gdip_ico);
 	try_module (wmf,gdip_wmf);
diff --git a/gdk-pixbuf/io-qtif.c b/gdk-pixbuf/io-qtif.c
new file mode 100644
index 0000000..0b80fe0
--- /dev/null
+++ b/gdk-pixbuf/io-qtif.c
@@ -0,0 +1,607 @@
+/* -*- mode: C; c-file-style: "linux" -*- */
+/* GdkPixbuf library - QTIF image loader
+ *
+ * This module extracts image data from QTIF format and uses
+ * other GDK pixbuf modules to decode the image data.
+ *
+ * Copyright (C) 2008 Kevin Peng
+ *
+ * Authors: Kevin Peng <kevin zycomtech 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 <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <setjmp.h>
+#include "gdk-pixbuf.h"
+#include "gdk-pixbuf-private.h"
+#include "gdk-pixbuf-io.h"
+
+/***
+ * Definitions
+ */
+/* Read buffer size */
+#define READ_BUFFER_SIZE    8192
+
+/* Only allow atom of size up to 10MB. */
+#define ATOM_SIZE_MAX       100000000
+
+/* Aborts after going to through this many atoms. */
+#define QTIF_ATOM_COUNT_MAX 10u
+
+/* QTIF static image data tag "idat". */
+#define QTIF_TAG_IDATA      0x69646174u
+
+
+/***
+ * Types
+ */
+/* QTIF State */
+typedef enum {
+    STATE_READY,
+    STATE_DATA,
+    STATE_OTHER
+} QTIFState;
+
+/* QTIF Atom Header */
+typedef struct {
+    guint32 length;
+    guint32 tag;
+} QtHeader;
+
+/* QTIF loader context */
+typedef struct {
+    GdkPixbufLoader *loader;
+    gpointer        user_data;
+    QTIFState       state;
+    guint32         run_length;
+    gint            atom_count;
+
+    guchar          header_buffer[sizeof(QtHeader)];
+
+    GdkPixbufModuleSizeFunc     size_func;
+    GdkPixbufModulePreparedFunc prepare_func;
+    GdkPixbufModuleUpdatedFunc  update_func;
+    gint            cb_prepare_count;
+    gint            cb_update_count;
+} QTIFContext;
+
+/***
+ * Local function prototypes
+ */
+static GdkPixbuf *gdk_pixbuf__qtif_image_load (FILE *f, GError **error);
+static gpointer gdk_pixbuf__qtif_image_begin_load (GdkPixbufModuleSizeFunc size_func,
+                                                   GdkPixbufModulePreparedFunc prepare_func,
+                                                   GdkPixbufModuleUpdatedFunc update_func,
+                                                   gpointer user_data,
+                                                   GError **error);
+static gboolean gdk_pixbuf__qtif_image_stop_load (gpointer context, GError **error);
+static gboolean gdk_pixbuf__qtif_image_load_increment(gpointer context,
+                                                      const guchar *buf, guint size,
+                                                      GError **error);
+static gboolean gdk_pixbuf__qtif_image_create_loader (QTIFContext *context, GError **error);
+static gboolean gdk_pixbuf__qtif_image_free_loader (QTIFContext *context, GError **error);
+
+static void gdk_pixbuf__qtif_cb_size_prepared(GdkPixbufLoader *loader,
+                                              gint width,
+                                              gint height,
+                                              gpointer user_data);
+static void gdk_pixbuf__qtif_cb_area_prepared(GdkPixbufLoader *loader, gpointer user_data);
+static void gdk_pixbuf__qtif_cb_area_updated(GdkPixbufLoader *loader,
+                                             gint x,
+                                             gint y,
+                                             gint width,
+                                             gint height,
+                                             gpointer user_data);
+
+/***
+ * Function definitions.
+ */
+
+/* Load QTIF from a file handler. */
+static GdkPixbuf *gdk_pixbuf__qtif_image_load (FILE *f, GError **error)
+{
+    guint count;
+
+    if(f == NULL)
+    {
+        g_set_error_literal (error, GDK_PIXBUF_ERROR,
+                             GDK_PIXBUF_ERROR_BAD_OPTION,
+                             _("Input file descriptor is NULL."));
+        return NULL;
+    }
+
+    for(count = QTIF_ATOM_COUNT_MAX; count != 0u; count--)
+    {
+        QtHeader hdr;
+        size_t rd;
+
+        /* Read QtHeader. */
+        rd = fread(&hdr, 1, sizeof(QtHeader), f);
+        if(rd != sizeof(QtHeader))
+        {
+            g_set_error_literal(error, GDK_PIXBUF_ERROR,
+                                GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+                                _("Failed to read QTIF header"));
+            return NULL;
+        }
+
+        hdr.length = GUINT32_FROM_BE(hdr.length) - sizeof(QtHeader);
+        if(hdr.length > ATOM_SIZE_MAX)
+        {
+            g_set_error(error, GDK_PIXBUF_ERROR,
+                        GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+                        _("QTIF atom size too large (%d bytes)"), hdr.length);
+            return NULL;
+        }
+
+        switch(GUINT32_FROM_BE(hdr.tag))
+        {
+        case QTIF_TAG_IDATA: /* "idat" data atom. */
+            {
+                /* Load image using GdkPixbufLoader. */
+                guchar *buf;
+                GdkPixbufLoader *loader;
+                GdkPixbuf *pixbuf = NULL;
+                GError *tmp = NULL;
+
+                /* Allocate read buffer. */
+                buf = g_try_malloc(READ_BUFFER_SIZE);
+                if(buf == NULL)
+                {
+                    g_set_error(error, GDK_PIXBUF_ERROR,
+                                GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
+                                _("Failed to allocate %d bytes for file read buffer"), READ_BUFFER_SIZE);
+                    return NULL;
+                }
+
+                /* Create GdkPixbufLoader. */
+                loader = gdk_pixbuf_loader_new();
+                if(loader == NULL)
+                {
+                    g_set_error(error, GDK_PIXBUF_ERROR,
+                                GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+                                _("QTIF atom size too large (%d bytes)"), hdr.length);
+                    goto clean_up;
+                }
+
+                /* Read atom data. */
+                while(hdr.length != 0u)
+                {
+                    rd = (hdr.length > READ_BUFFER_SIZE) ? READ_BUFFER_SIZE : hdr.length;
+
+                    rd = fread(buf, 1, rd, f);
+                    if(rd < 0)
+                    {
+                        g_set_error(error, GDK_PIXBUF_ERROR,
+                                    GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+                                    _("File error when reading QTIF atom: %s"), g_strerror(errno));
+                        break;
+                    }
+
+                    if(!gdk_pixbuf_loader_write(loader, buf, rd, &tmp))
+                    {
+                        g_propagate_error (error, tmp);
+                        break;
+                    }
+                    hdr.length -= rd;
+                }
+
+clean_up:
+                /* Release loader */
+                if(loader != NULL)
+                {
+                    gdk_pixbuf_loader_close(loader, NULL);
+                    pixbuf = gdk_pixbuf_loader_get_pixbuf(loader);
+                    if(pixbuf != NULL)
+                    {
+                        g_object_ref(pixbuf);
+                    }
+                    g_object_unref(loader);
+                }
+                if(buf != NULL)
+                {
+                    g_free(buf);
+                }
+                return pixbuf;
+            }
+
+        default:
+            /* Skip any other types of atom. */
+            if(!fseek(f, hdr.length, SEEK_CUR))
+            {
+                g_set_error(error, GDK_PIXBUF_ERROR,
+                            GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+                            _("Failed to skip the next %d bytes with seek()."), hdr.length);
+                return NULL;
+            }
+            break;
+        }
+    }
+    return NULL;
+}
+
+/* Incremental load begin. */
+static gpointer gdk_pixbuf__qtif_image_begin_load (GdkPixbufModuleSizeFunc size_func,
+                                                   GdkPixbufModulePreparedFunc prepare_func,
+                                                   GdkPixbufModuleUpdatedFunc update_func,
+                                                   gpointer user_data,
+                                                   GError **error)
+{
+    QTIFContext *context;
+
+    /* Create context struct. */
+    context = g_new0(QTIFContext, 1);
+    if(context == NULL)
+    {
+        g_set_error_literal (error, GDK_PIXBUF_ERROR,
+                             GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
+                             _("Failed to QTIF context structure."));
+        return NULL;
+    }
+
+    /* Fill context parameters. */
+    context->loader = NULL;
+    context->user_data = user_data;
+    context->state = STATE_READY;
+    context->run_length = 0u;
+    context->atom_count = QTIF_ATOM_COUNT_MAX;
+    context->size_func = size_func;
+    context->prepare_func = prepare_func;
+    context->update_func = update_func;
+
+	return context;
+}
+
+/* Incremental load clean up. */
+static gboolean gdk_pixbuf__qtif_image_stop_load (gpointer data, GError **error)
+{
+    QTIFContext *context = (QTIFContext *)data;
+    gboolean ret;
+
+    if(context->loader != NULL)
+    {
+        GError *tmp = NULL;
+
+        ret = gdk_pixbuf__qtif_image_free_loader(context, &tmp);
+        if(!ret)
+        {
+            g_propagate_error (error, tmp);
+        }
+    }
+    g_free(context);
+	return ret;
+}
+
+/* Create a new GdkPixbufLoader and connect to its signals. */
+static gboolean gdk_pixbuf__qtif_image_create_loader (QTIFContext *context, GError **error)
+{
+    GError *tmp = NULL;
+
+    if(context == NULL)
+    {
+        return FALSE;
+    }
+
+    /* Free existing loader. */
+    if(context->loader != NULL)
+    {
+        gdk_pixbuf__qtif_image_free_loader(context, &tmp);
+    }
+
+    /* Create GdkPixbufLoader object. */
+    context->loader = gdk_pixbuf_loader_new();
+    if(context->loader == NULL)
+    {
+        g_set_error_literal (error, GDK_PIXBUF_ERROR,
+                             GDK_PIXBUF_ERROR_FAILED,
+                             _("Failed to create GdkPixbufLoader object."));
+        return FALSE;
+    }
+
+    /* Connect signals. */
+    context->cb_prepare_count = 0;
+    context->cb_update_count = 0;
+    if(context->size_func != NULL)
+    {
+        g_signal_connect(context->loader, "size-prepared",
+                         G_CALLBACK(gdk_pixbuf__qtif_cb_size_prepared),
+                         context);
+    }
+    if(context->prepare_func != NULL)
+    {
+        g_signal_connect(context->loader, "area-prepared",
+                         G_CALLBACK(gdk_pixbuf__qtif_cb_area_prepared),
+                         context);
+    }
+    if(context->update_func != NULL)
+    {
+        g_signal_connect(context->loader, "area-updated",
+                         G_CALLBACK(gdk_pixbuf__qtif_cb_area_updated),
+                         context);
+    }
+    return TRUE;
+}
+
+/* Free the GdkPixbufLoader and perform callback if haven't done so. */
+static gboolean gdk_pixbuf__qtif_image_free_loader (QTIFContext *context, GError **error)
+{
+    GdkPixbuf *pixbuf;
+    GError *tmp = NULL;
+    gboolean ret;
+
+    if((context == NULL) || (context->loader == NULL))
+    {
+        return FALSE;
+    }
+
+    /* Close GdkPixbufLoader. */
+    ret = gdk_pixbuf_loader_close(context->loader, &tmp);
+    if(!ret)
+    {
+        g_propagate_error (error, tmp);
+    }
+
+
+    /* Get GdkPixbuf from GdkPixbufLoader. */
+    pixbuf = gdk_pixbuf_loader_get_pixbuf(context->loader);
+    if(pixbuf != NULL)
+    {
+        g_object_ref(pixbuf);
+    }
+
+    /* Free GdkPixbufLoader. */
+    g_object_ref(context->loader);
+    context->loader = NULL;
+
+    if(pixbuf != NULL)
+    {
+        /* Callback functions should be called for at least once. */
+        if((context->prepare_func != NULL) && (context->cb_prepare_count == 0))
+        {
+            (context->prepare_func)(pixbuf, NULL, context->user_data);
+        }
+
+        if((context->update_func != NULL) && (context->cb_update_count == 0))
+        {
+            gint width;
+            gint height;
+
+            width = gdk_pixbuf_get_width(pixbuf);
+            height = gdk_pixbuf_get_height(pixbuf);
+            (context->update_func)(pixbuf, 0, 0, width, height, context->user_data);
+        }
+
+        /* Free GdkPixbuf (callback function should ref it). */
+        g_object_ref(pixbuf);
+    }
+
+    return ret;
+}
+
+
+/* Incrementally load the next chunk of data. */
+static gboolean gdk_pixbuf__qtif_image_load_increment (gpointer data,
+                                                       const guchar *buf, guint size,
+                                                       GError **error)
+{
+    QTIFContext *context = (QTIFContext *)data;
+    GError *tmp = NULL;
+    gboolean ret = TRUE; /* Return TRUE for insufficient data. */
+
+    while(ret && (size != 0u))
+    {
+        switch(context->state)
+        {
+        case STATE_READY:
+            /* Abort if we have seen too mant atoms. */
+            if(context->atom_count == 0u)
+            {
+                g_set_error_literal (error, GDK_PIXBUF_ERROR,
+                                     GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+                                     _("Failed to find an image data atom."));
+                return FALSE;
+            }
+            context->atom_count--;
+
+            /* Copy to header buffer in context, in case supplied data is not enough. */
+            while(context->run_length < sizeof(QtHeader))
+            {
+                context->header_buffer[context->run_length] = *buf;
+                context->run_length++;
+                buf++;
+                size--;
+            }
+
+            /* Parse buffer as QT header. */
+            if(context->run_length == sizeof(QtHeader))
+            {
+                QtHeader *hdr = (QtHeader *)context->header_buffer;
+                context->run_length = GUINT32_FROM_BE(hdr->length) - sizeof(QtHeader);
+
+                /* Atom max size check. */
+                if(context->run_length > ATOM_SIZE_MAX)
+                {
+                    g_set_error(error, GDK_PIXBUF_ERROR,
+                                       GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+                                       _("QTIF atom size too large (%d bytes)"), hdr->length);
+                    return FALSE;
+                }
+
+                /* Set state according to atom type. */
+                if(GUINT32_FROM_BE(hdr->tag) == QTIF_TAG_IDATA)
+                {
+                    GError *tmp = NULL;
+
+                    context->state = STATE_DATA;
+
+                    /* Create GdkPixbufLoader for this image data. */
+                    ret = gdk_pixbuf__qtif_image_create_loader(context, &tmp);
+                    if(!ret)
+                    {
+                        g_propagate_error (error, tmp);
+                    }
+                }
+                else
+                {
+                    context->state = STATE_OTHER;
+                }
+            }
+            break;
+
+        default: /* Both STATE_DATA and STATE_OTHER will come here. */
+            /* Check for atom boundary. */
+            if(context->run_length > size)
+            {
+                /* Supply image data to GdkPixbufLoader if in STATE_DATA. */
+                if(context->state == STATE_DATA)
+                {
+                    tmp = NULL;
+                    ret = gdk_pixbuf_loader_write(context->loader, buf, size, &tmp);
+                    if(!ret && (error != NULL) && (*error == NULL))
+                    {
+                        g_propagate_error (error, tmp);
+                    }
+                }
+                context->run_length -= size;
+                size = 0u;
+            }
+            else
+            {
+                /* Supply image data to GdkPixbufLoader if in STATE_DATA. */
+                if(context->state == STATE_DATA)
+                {
+                    gboolean r;
+
+                    /* Here we should have concluded a complete image atom. */
+                    tmp = NULL;
+                    ret = gdk_pixbuf_loader_write(context->loader, buf, context->run_length, &tmp);
+                    if(!ret && (error != NULL) && (*error == NULL))
+                    {
+                        g_propagate_error (error, tmp);
+                    }
+
+                    /* Free GdkPixbufLoader and handle callback. */
+                    tmp = NULL;
+                    r = gdk_pixbuf__qtif_image_free_loader(context, &tmp);
+                    if(!r)
+                    {
+                        if((error != NULL) && (*error == NULL))
+                        {
+                            g_propagate_error (error, tmp);
+                        }
+                        ret = FALSE;
+                    }
+                }
+                buf = &buf[context->run_length];
+                size -= context->run_length;
+                context->run_length = 0u;
+                context->state = STATE_READY;
+            }
+            break;
+        }
+    }
+
+    return ret;
+}
+
+/* Event handlers */
+static void gdk_pixbuf__qtif_cb_size_prepared(GdkPixbufLoader *loader,
+                                              gint width,
+                                              gint height,
+                                              gpointer user_data)
+{
+    QTIFContext *context = (QTIFContext *)user_data;
+    if((context != NULL) && (context->size_func != NULL))
+    {
+        (context->size_func)(&width, &height, context->user_data);
+        context->cb_prepare_count++;
+    }
+}
+
+static void gdk_pixbuf__qtif_cb_area_prepared(GdkPixbufLoader *loader, gpointer user_data)
+{
+    QTIFContext *context = (QTIFContext *)user_data;
+    if((loader != NULL) && (context != NULL) && (context->prepare_func != NULL))
+    {
+        GdkPixbuf *pixbuf = gdk_pixbuf_loader_get_pixbuf(context->loader);
+        (context->prepare_func)(pixbuf, NULL, context->user_data);
+        context->cb_update_count++;
+    }
+}
+
+static void gdk_pixbuf__qtif_cb_area_updated(GdkPixbufLoader *loader,
+                                             gint x,
+                                             gint y,
+                                             gint width,
+                                             gint height,
+                                             gpointer user_data)
+{
+    QTIFContext *context = (QTIFContext *)user_data;
+    if((loader != NULL) && (context != NULL) && (context->update_func != NULL))
+    {
+        GdkPixbuf *pixbuf = gdk_pixbuf_loader_get_pixbuf(context->loader);
+        (context->update_func)(pixbuf, x, y, width, height, context->user_data);
+    }
+}
+
+
+#ifndef INCLUDE_qtif
+#define MODULE_ENTRY(function) G_MODULE_EXPORT void function
+#else
+#define MODULE_ENTRY(function) void _gdk_pixbuf__qtif_ ## function
+#endif
+
+MODULE_ENTRY (fill_vtable) (GdkPixbufModule *module)
+{
+    module->load = gdk_pixbuf__qtif_image_load;
+    module->begin_load = gdk_pixbuf__qtif_image_begin_load;
+    module->stop_load = gdk_pixbuf__qtif_image_stop_load;
+    module->load_increment = gdk_pixbuf__qtif_image_load_increment;
+}
+
+MODULE_ENTRY (fill_info) (GdkPixbufFormat *info)
+{
+    static GdkPixbufModulePattern signature[] = {
+        { "abcdidsc", "xxxx    ", 100 },
+        { "abcdidat", "xxxx    ", 100 },
+        { NULL, NULL, 0 }
+    };
+    static gchar * mime_types[] = {
+        "image/x-quicktime",
+        "image/qtif",
+        NULL
+    };
+    static gchar * extensions[] = {
+        "qtif",
+        "qif",
+        NULL
+    };
+
+    info->name = "qtif";
+    info->signature = signature;
+    info->description = N_("The QTIF image format");
+    info->mime_types = mime_types;
+    info->extensions = extensions;
+    info->flags = GDK_PIXBUF_FORMAT_THREADSAFE;
+    info->license = "LGPL";
+}
+



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