Blame gdk-pixbuf/io-qtif.c

Packit a4058c
/* -*- mode: C; c-file-style: "linux" -*- */
Packit a4058c
/* GdkPixbuf library - QTIF image loader
Packit a4058c
 *
Packit a4058c
 * This module extracts image data from QTIF format and uses
Packit a4058c
 * other GDK pixbuf modules to decode the image data.
Packit a4058c
 *
Packit a4058c
 * Copyright (C) 2008 Kevin Peng
Packit a4058c
 *
Packit a4058c
 * Authors: Kevin Peng <kevin@zycomtech.com>
Packit a4058c
 *
Packit a4058c
 * This library is free software; you can redistribute it and/or
Packit a4058c
 * modify it under the terms of the GNU Lesser General Public
Packit a4058c
 * License as published by the Free Software Foundation; either
Packit a4058c
 * version 2 of the License, or (at your option) any later version.
Packit a4058c
 *
Packit a4058c
 * This library is distributed in the hope that it will be useful,
Packit a4058c
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit a4058c
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit a4058c
 * Lesser General Public License for more details.
Packit a4058c
 *
Packit a4058c
 * You should have received a copy of the GNU Lesser General Public
Packit a4058c
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
Packit a4058c
 */
Packit a4058c
Packit a4058c
Packit a4058c
#include "config.h"
Packit a4058c
#include <errno.h>
Packit a4058c
#include <libintl.h>
Packit a4058c
#include <stdio.h>
Packit a4058c
#include <stdlib.h>
Packit a4058c
#include <string.h>
Packit a4058c
#include <setjmp.h>
Packit a4058c
#include "gdk-pixbuf.h"
Packit a4058c
#include "gdk-pixbuf-private.h"
Packit a4058c
Packit a4058c
/***
Packit a4058c
 * Definitions
Packit a4058c
 */
Packit a4058c
/* Read buffer size */
Packit a4058c
#define READ_BUFFER_SIZE    8192
Packit a4058c
Packit a4058c
/* Only allow atom of size up to 10MB. */
Packit a4058c
#define ATOM_SIZE_MAX       100000000
Packit a4058c
Packit a4058c
/* Aborts after going to through this many atoms. */
Packit a4058c
#define QTIF_ATOM_COUNT_MAX 10u
Packit a4058c
Packit a4058c
/* QTIF static image data tag "idat". */
Packit a4058c
#define QTIF_TAG_IDATA      0x69646174u
Packit a4058c
Packit a4058c
Packit a4058c
/***
Packit a4058c
 * Types
Packit a4058c
 */
Packit a4058c
/* QTIF State */
Packit a4058c
typedef enum {
Packit a4058c
    STATE_READY,
Packit a4058c
    STATE_DATA,
Packit a4058c
    STATE_OTHER
Packit a4058c
} QTIFState;
Packit a4058c
Packit a4058c
/* QTIF Atom Header */
Packit a4058c
typedef struct {
Packit a4058c
    guint32 length;
Packit a4058c
    guint32 tag;
Packit a4058c
} QtHeader;
Packit a4058c
Packit a4058c
/* QTIF loader context */
Packit a4058c
typedef struct {
Packit a4058c
    GdkPixbufLoader *loader;
Packit a4058c
    gpointer        user_data;
Packit a4058c
    QTIFState       state;
Packit a4058c
    guint32         run_length;
Packit a4058c
    gint            atom_count;
Packit a4058c
Packit a4058c
    guchar          header_buffer[sizeof(QtHeader)];
Packit a4058c
Packit a4058c
    GdkPixbufModuleSizeFunc     size_func;
Packit a4058c
    GdkPixbufModulePreparedFunc prepare_func;
Packit a4058c
    GdkPixbufModuleUpdatedFunc  update_func;
Packit a4058c
    gint            cb_prepare_count;
Packit a4058c
    gint            cb_update_count;
Packit a4058c
} QTIFContext;
Packit a4058c
Packit a4058c
/***
Packit a4058c
 * Local function prototypes
Packit a4058c
 */
Packit a4058c
static GdkPixbuf *gdk_pixbuf__qtif_image_load (FILE *f, GError **error);
Packit a4058c
static gpointer gdk_pixbuf__qtif_image_begin_load (GdkPixbufModuleSizeFunc size_func,
Packit a4058c
                                                   GdkPixbufModulePreparedFunc prepare_func,
Packit a4058c
                                                   GdkPixbufModuleUpdatedFunc update_func,
Packit a4058c
                                                   gpointer user_data,
Packit a4058c
                                                   GError **error);
Packit a4058c
static gboolean gdk_pixbuf__qtif_image_stop_load (gpointer context, GError **error);
Packit a4058c
static gboolean gdk_pixbuf__qtif_image_load_increment(gpointer context,
Packit a4058c
                                                      const guchar *buf, guint size,
Packit a4058c
                                                      GError **error);
Packit a4058c
static gboolean gdk_pixbuf__qtif_image_create_loader (QTIFContext *context, GError **error);
Packit a4058c
static gboolean gdk_pixbuf__qtif_image_free_loader (QTIFContext *context, GError **error);
Packit a4058c
Packit a4058c
static void gdk_pixbuf__qtif_cb_size_prepared(GdkPixbufLoader *loader,
Packit a4058c
                                              gint width,
Packit a4058c
                                              gint height,
Packit a4058c
                                              gpointer user_data);
Packit a4058c
static void gdk_pixbuf__qtif_cb_area_prepared(GdkPixbufLoader *loader, gpointer user_data);
Packit a4058c
static void gdk_pixbuf__qtif_cb_area_updated(GdkPixbufLoader *loader,
Packit a4058c
                                             gint x,
Packit a4058c
                                             gint y,
Packit a4058c
                                             gint width,
Packit a4058c
                                             gint height,
Packit a4058c
                                             gpointer user_data);
Packit a4058c
Packit a4058c
/***
Packit a4058c
 * Function definitions.
Packit a4058c
 */
Packit a4058c
Packit a4058c
/* Load QTIF from a file handler. */
Packit a4058c
static GdkPixbuf *gdk_pixbuf__qtif_image_load (FILE *f, GError **error)
Packit a4058c
{
Packit a4058c
    guint count;
Packit a4058c
Packit a4058c
    if(f == NULL)
Packit a4058c
    {
Packit a4058c
        g_set_error_literal (error, GDK_PIXBUF_ERROR,
Packit a4058c
                             GDK_PIXBUF_ERROR_BAD_OPTION,
Packit a4058c
                             _("Input file descriptor is NULL."));
Packit a4058c
        return NULL;
Packit a4058c
    }
Packit a4058c
Packit a4058c
    for(count = QTIF_ATOM_COUNT_MAX; count != 0u; count--)
Packit a4058c
    {
Packit a4058c
        QtHeader hdr;
Packit a4058c
        size_t rd;
Packit a4058c
Packit a4058c
        /* Read QtHeader. */
Packit a4058c
        rd = fread(&hdr, 1, sizeof(QtHeader), f);
Packit a4058c
        if(rd != sizeof(QtHeader))
Packit a4058c
        {
Packit a4058c
            g_set_error_literal(error, GDK_PIXBUF_ERROR,
Packit a4058c
                                GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
Packit a4058c
                                _("Failed to read QTIF header"));
Packit a4058c
            return NULL;
Packit a4058c
        }
Packit a4058c
Packit a4058c
        hdr.length = GUINT32_FROM_BE(hdr.length) - sizeof(QtHeader);
Packit a4058c
        if(hdr.length > ATOM_SIZE_MAX)
Packit a4058c
        {
Packit a4058c
            g_set_error(error, GDK_PIXBUF_ERROR,
Packit a4058c
                        GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
Packit a4058c
                        ngettext (  "QTIF atom size too large (%d byte)",
Packit a4058c
                                    "QTIF atom size too large (%d bytes)",
Packit a4058c
                                    hdr.length),
Packit a4058c
                        hdr.length);
Packit a4058c
            return NULL;
Packit a4058c
        }
Packit a4058c
Packit a4058c
        switch(GUINT32_FROM_BE(hdr.tag))
Packit a4058c
        {
Packit a4058c
        case QTIF_TAG_IDATA: /* "idat" data atom. */
Packit a4058c
            {
Packit a4058c
                /* Load image using GdkPixbufLoader. */
Packit a4058c
                guchar *buf;
Packit a4058c
                GdkPixbufLoader *loader;
Packit a4058c
                GdkPixbuf *pixbuf = NULL;
Packit a4058c
                GError *tmp = NULL;
Packit a4058c
Packit a4058c
                /* Allocate read buffer. */
Packit a4058c
                buf = g_try_malloc(READ_BUFFER_SIZE);
Packit a4058c
                if(buf == NULL)
Packit a4058c
                {
Packit a4058c
                    g_set_error(error, GDK_PIXBUF_ERROR,
Packit a4058c
                                GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
Packit a4058c
                                ngettext ( "Failed to allocate %d byte for file read buffer",
Packit a4058c
                                           "Failed to allocate %d bytes for file read buffer",
Packit a4058c
                                           READ_BUFFER_SIZE
Packit a4058c
                                ),
Packit a4058c
                                READ_BUFFER_SIZE);
Packit a4058c
                    return NULL;
Packit a4058c
                }
Packit a4058c
Packit a4058c
                /* Create GdkPixbufLoader. */
Packit a4058c
                loader = gdk_pixbuf_loader_new();
Packit a4058c
                if(loader == NULL)
Packit a4058c
                {
Packit a4058c
                    g_set_error(error, GDK_PIXBUF_ERROR,
Packit a4058c
                                GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
Packit a4058c
                                ngettext (  "QTIF atom size too large (%d byte)",
Packit a4058c
                                            "QTIF atom size too large (%d bytes)",
Packit a4058c
                                            hdr.length),
Packit a4058c
                                hdr.length);
Packit a4058c
                    goto clean_up;
Packit a4058c
                }
Packit a4058c
Packit a4058c
                /* Read atom data. */
Packit a4058c
                while(hdr.length != 0u)
Packit a4058c
                {
Packit a4058c
                    if(fread(buf, 1, rd, f) != rd)
Packit a4058c
                    {
Packit a4058c
                        g_set_error(error, GDK_PIXBUF_ERROR,
Packit a4058c
                                    GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
Packit a4058c
                                    _("File error when reading QTIF atom: %s"), g_strerror(errno));
Packit a4058c
                        break;
Packit a4058c
                    }
Packit a4058c
Packit a4058c
                    if(!gdk_pixbuf_loader_write(loader, buf, rd, &tmp))
Packit a4058c
                    {
Packit a4058c
                        g_propagate_error (error, tmp);
Packit a4058c
                        break;
Packit a4058c
                    }
Packit a4058c
                    hdr.length -= rd;
Packit a4058c
                }
Packit a4058c
Packit a4058c
clean_up:
Packit a4058c
                /* Release loader */
Packit a4058c
                if(loader != NULL)
Packit a4058c
                {
Packit a4058c
                    gdk_pixbuf_loader_close(loader, NULL);
Packit a4058c
                    pixbuf = gdk_pixbuf_loader_get_pixbuf(loader);
Packit a4058c
                    if(pixbuf != NULL)
Packit a4058c
                    {
Packit a4058c
                        g_object_ref(pixbuf);
Packit a4058c
                    }
Packit a4058c
                    g_object_unref(loader);
Packit a4058c
                }
Packit a4058c
                if(buf != NULL)
Packit a4058c
                {
Packit a4058c
                    g_free(buf);
Packit a4058c
                }
Packit a4058c
                return pixbuf;
Packit a4058c
            }
Packit a4058c
Packit a4058c
        default:
Packit a4058c
            /* Skip any other types of atom. */
Packit a4058c
            if(!fseek(f, hdr.length, SEEK_CUR))
Packit a4058c
            {
Packit a4058c
                g_set_error(error, GDK_PIXBUF_ERROR,
Packit a4058c
                            GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
Packit a4058c
                            ngettext (  "Failed to skip the next %d byte with seek().",
Packit a4058c
                                        "Failed to skip the next %d bytes with seek().",
Packit a4058c
                                        hdr.length),
Packit a4058c
                            hdr.length);
Packit a4058c
                return NULL;
Packit a4058c
            }
Packit a4058c
            break;
Packit a4058c
        }
Packit a4058c
    }
Packit a4058c
    return NULL;
Packit a4058c
}
Packit a4058c
Packit a4058c
/* Incremental load begin. */
Packit a4058c
static gpointer gdk_pixbuf__qtif_image_begin_load (GdkPixbufModuleSizeFunc size_func,
Packit a4058c
                                                   GdkPixbufModulePreparedFunc prepare_func,
Packit a4058c
                                                   GdkPixbufModuleUpdatedFunc update_func,
Packit a4058c
                                                   gpointer user_data,
Packit a4058c
                                                   GError **error)
Packit a4058c
{
Packit a4058c
    QTIFContext *context;
Packit a4058c
Packit a4058c
    /* Create context struct. */
Packit a4058c
    context = g_new0(QTIFContext, 1);
Packit a4058c
    if(context == NULL)
Packit a4058c
    {
Packit a4058c
        g_set_error_literal (error, GDK_PIXBUF_ERROR,
Packit a4058c
                             GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
Packit a4058c
                             _("Failed to allocate QTIF context structure."));
Packit a4058c
        return NULL;
Packit a4058c
    }
Packit a4058c
Packit a4058c
    /* Fill context parameters. */
Packit a4058c
    context->loader = NULL;
Packit a4058c
    context->user_data = user_data;
Packit a4058c
    context->state = STATE_READY;
Packit a4058c
    context->run_length = 0u;
Packit a4058c
    context->atom_count = QTIF_ATOM_COUNT_MAX;
Packit a4058c
    context->size_func = size_func;
Packit a4058c
    context->prepare_func = prepare_func;
Packit a4058c
    context->update_func = update_func;
Packit a4058c
Packit a4058c
    return context;
Packit a4058c
}
Packit a4058c
Packit a4058c
/* Incremental load clean up. */
Packit a4058c
static gboolean gdk_pixbuf__qtif_image_stop_load (gpointer data, GError **error)
Packit a4058c
{
Packit a4058c
    QTIFContext *context = (QTIFContext *)data;
Packit a4058c
    gboolean ret = TRUE;
Packit a4058c
Packit a4058c
    if(context->loader != NULL)
Packit a4058c
    {
Packit a4058c
        GError *tmp = NULL;
Packit a4058c
Packit a4058c
        ret = gdk_pixbuf__qtif_image_free_loader(context, &tmp);
Packit a4058c
        if(!ret)
Packit a4058c
        {
Packit a4058c
            g_propagate_error (error, tmp);
Packit a4058c
        }
Packit a4058c
    }
Packit a4058c
    g_free(context);
Packit a4058c
Packit a4058c
    return ret;
Packit a4058c
}
Packit a4058c
Packit a4058c
/* Create a new GdkPixbufLoader and connect to its signals. */
Packit a4058c
static gboolean gdk_pixbuf__qtif_image_create_loader (QTIFContext *context, GError **error)
Packit a4058c
{
Packit a4058c
    GError *tmp = NULL;
Packit a4058c
Packit a4058c
    if(context == NULL)
Packit a4058c
    {
Packit a4058c
        return FALSE;
Packit a4058c
    }
Packit a4058c
Packit a4058c
    /* Free existing loader. */
Packit a4058c
    if(context->loader != NULL)
Packit a4058c
    {
Packit a4058c
        gdk_pixbuf__qtif_image_free_loader(context, &tmp);
Packit a4058c
    }
Packit a4058c
Packit a4058c
    /* Create GdkPixbufLoader object. */
Packit a4058c
    context->loader = gdk_pixbuf_loader_new();
Packit a4058c
    if(context->loader == NULL)
Packit a4058c
    {
Packit a4058c
        g_set_error_literal (error, GDK_PIXBUF_ERROR,
Packit a4058c
                             GDK_PIXBUF_ERROR_FAILED,
Packit a4058c
                             _("Failed to create GdkPixbufLoader object."));
Packit a4058c
        return FALSE;
Packit a4058c
    }
Packit a4058c
Packit a4058c
    /* Connect signals. */
Packit a4058c
    context->cb_prepare_count = 0;
Packit a4058c
    context->cb_update_count = 0;
Packit a4058c
    if(context->size_func != NULL)
Packit a4058c
    {
Packit a4058c
        g_signal_connect(context->loader, "size-prepared",
Packit a4058c
                         G_CALLBACK(gdk_pixbuf__qtif_cb_size_prepared),
Packit a4058c
                         context);
Packit a4058c
    }
Packit a4058c
    if(context->prepare_func != NULL)
Packit a4058c
    {
Packit a4058c
        g_signal_connect(context->loader, "area-prepared",
Packit a4058c
                         G_CALLBACK(gdk_pixbuf__qtif_cb_area_prepared),
Packit a4058c
                         context);
Packit a4058c
    }
Packit a4058c
    if(context->update_func != NULL)
Packit a4058c
    {
Packit a4058c
        g_signal_connect(context->loader, "area-updated",
Packit a4058c
                         G_CALLBACK(gdk_pixbuf__qtif_cb_area_updated),
Packit a4058c
                         context);
Packit a4058c
    }
Packit a4058c
    return TRUE;
Packit a4058c
}
Packit a4058c
Packit a4058c
/* Free the GdkPixbufLoader and perform callback if haven't done so. */
Packit a4058c
static gboolean gdk_pixbuf__qtif_image_free_loader (QTIFContext *context, GError **error)
Packit a4058c
{
Packit a4058c
    GdkPixbuf *pixbuf;
Packit a4058c
    GError *tmp = NULL;
Packit a4058c
    gboolean ret;
Packit a4058c
Packit a4058c
    if((context == NULL) || (context->loader == NULL))
Packit a4058c
    {
Packit a4058c
        return FALSE;
Packit a4058c
    }
Packit a4058c
Packit a4058c
    /* Close GdkPixbufLoader. */
Packit a4058c
    ret = gdk_pixbuf_loader_close(context->loader, &tmp);
Packit a4058c
    if(!ret)
Packit a4058c
    {
Packit a4058c
        g_propagate_error (error, tmp);
Packit a4058c
    }
Packit a4058c
Packit a4058c
Packit a4058c
    /* Get GdkPixbuf from GdkPixbufLoader. */
Packit a4058c
    pixbuf = gdk_pixbuf_loader_get_pixbuf(context->loader);
Packit a4058c
    if(pixbuf != NULL)
Packit a4058c
    {
Packit a4058c
        g_object_ref(pixbuf);
Packit a4058c
    }
Packit a4058c
Packit a4058c
    /* Free GdkPixbufLoader. */
Packit a4058c
    g_object_ref(context->loader);
Packit a4058c
    context->loader = NULL;
Packit a4058c
Packit a4058c
    if(pixbuf != NULL)
Packit a4058c
    {
Packit a4058c
        /* Callback functions should be called for at least once. */
Packit a4058c
        if((context->prepare_func != NULL) && (context->cb_prepare_count == 0))
Packit a4058c
        {
Packit a4058c
            (context->prepare_func)(pixbuf, NULL, context->user_data);
Packit a4058c
        }
Packit a4058c
Packit a4058c
        if((context->update_func != NULL) && (context->cb_update_count == 0))
Packit a4058c
        {
Packit a4058c
            gint width;
Packit a4058c
            gint height;
Packit a4058c
Packit a4058c
            width = gdk_pixbuf_get_width(pixbuf);
Packit a4058c
            height = gdk_pixbuf_get_height(pixbuf);
Packit a4058c
            (context->update_func)(pixbuf, 0, 0, width, height, context->user_data);
Packit a4058c
        }
Packit a4058c
Packit a4058c
        /* Free GdkPixbuf (callback function should ref it). */
Packit a4058c
        g_object_ref(pixbuf);
Packit a4058c
    }
Packit a4058c
Packit a4058c
    return ret;
Packit a4058c
}
Packit a4058c
Packit a4058c
Packit a4058c
/* Incrementally load the next chunk of data. */
Packit a4058c
static gboolean gdk_pixbuf__qtif_image_load_increment (gpointer data,
Packit a4058c
                                                       const guchar *buf, guint size,
Packit a4058c
                                                       GError **error)
Packit a4058c
{
Packit a4058c
    QTIFContext *context = (QTIFContext *)data;
Packit a4058c
    GError *tmp = NULL;
Packit a4058c
    gboolean ret = TRUE; /* Return TRUE for insufficient data. */
Packit a4058c
Packit a4058c
    while(ret && (size != 0u))
Packit a4058c
    {
Packit a4058c
        switch(context->state)
Packit a4058c
        {
Packit a4058c
        case STATE_READY:
Packit a4058c
            /* Abort if we have seen too many atoms. */
Packit a4058c
            if(context->atom_count == 0u)
Packit a4058c
            {
Packit a4058c
                g_set_error_literal (error, GDK_PIXBUF_ERROR,
Packit a4058c
                                     GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
Packit a4058c
                                     _("Failed to find an image data atom."));
Packit a4058c
                return FALSE;
Packit a4058c
            }
Packit a4058c
            context->atom_count--;
Packit a4058c
Packit a4058c
            /* Copy to header buffer in context, in case supplied data is not enough. */
Packit a4058c
            while (context->run_length < sizeof(QtHeader) && size > 0u)
Packit a4058c
            {
Packit a4058c
                context->header_buffer[context->run_length] = *buf;
Packit a4058c
                context->run_length++;
Packit a4058c
                buf++;
Packit a4058c
                size--;
Packit a4058c
            }
Packit a4058c
Packit a4058c
            /* Parse buffer as QT header. */
Packit a4058c
            if(context->run_length == sizeof(QtHeader))
Packit a4058c
            {
Packit a4058c
                QtHeader *hdr = (QtHeader *)context->header_buffer;
Packit a4058c
                context->run_length = GUINT32_FROM_BE(hdr->length) - sizeof(QtHeader);
Packit a4058c
Packit a4058c
                /* Atom max size check. */
Packit a4058c
                if(context->run_length > ATOM_SIZE_MAX)
Packit a4058c
                {
Packit a4058c
                    g_set_error(error, GDK_PIXBUF_ERROR,
Packit a4058c
                                       GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
Packit a4058c
                                       ngettext (  "QTIF atom size too large (%d byte)",
Packit a4058c
                                                   "QTIF atom size too large (%d bytes)",
Packit a4058c
                                                    hdr->length),
Packit a4058c
                                       hdr->length);
Packit a4058c
                    return FALSE;
Packit a4058c
                }
Packit a4058c
Packit a4058c
                /* Set state according to atom type. */
Packit a4058c
                if(GUINT32_FROM_BE(hdr->tag) == QTIF_TAG_IDATA)
Packit a4058c
                {
Packit a4058c
                    GError *tmp = NULL;
Packit a4058c
Packit a4058c
                    context->state = STATE_DATA;
Packit a4058c
Packit a4058c
                    /* Create GdkPixbufLoader for this image data. */
Packit a4058c
                    ret = gdk_pixbuf__qtif_image_create_loader(context, &tmp);
Packit a4058c
                    if(!ret)
Packit a4058c
                    {
Packit a4058c
                        g_propagate_error (error, tmp);
Packit a4058c
                    }
Packit a4058c
                }
Packit a4058c
                else
Packit a4058c
                {
Packit a4058c
                    context->state = STATE_OTHER;
Packit a4058c
                }
Packit a4058c
            }
Packit a4058c
            break;
Packit a4058c
Packit a4058c
        default: /* Both STATE_DATA and STATE_OTHER will come here. */
Packit a4058c
            /* Check for atom boundary. */
Packit a4058c
            if(context->run_length > size)
Packit a4058c
            {
Packit a4058c
                /* Supply image data to GdkPixbufLoader if in STATE_DATA. */
Packit a4058c
                if(context->state == STATE_DATA)
Packit a4058c
                {
Packit a4058c
                    tmp = NULL;
Packit a4058c
                    ret = gdk_pixbuf_loader_write(context->loader, buf, size, &tmp);
Packit a4058c
                    if(!ret && (error != NULL) && (*error == NULL))
Packit a4058c
                    {
Packit a4058c
                        g_propagate_error (error, tmp);
Packit a4058c
                    }
Packit a4058c
                }
Packit a4058c
                context->run_length -= size;
Packit a4058c
                size = 0u;
Packit a4058c
            }
Packit a4058c
            else
Packit a4058c
            {
Packit a4058c
                /* Supply image data to GdkPixbufLoader if in STATE_DATA. */
Packit a4058c
                if(context->state == STATE_DATA)
Packit a4058c
                {
Packit a4058c
                    gboolean r;
Packit a4058c
Packit a4058c
                    /* Here we should have concluded a complete image atom. */
Packit a4058c
                    tmp = NULL;
Packit a4058c
                    ret = gdk_pixbuf_loader_write(context->loader, buf, context->run_length, &tmp);
Packit a4058c
                    if(!ret && (error != NULL) && (*error == NULL))
Packit a4058c
                    {
Packit a4058c
                        g_propagate_error (error, tmp);
Packit a4058c
                    }
Packit a4058c
Packit a4058c
                    /* Free GdkPixbufLoader and handle callback. */
Packit a4058c
                    tmp = NULL;
Packit a4058c
                    r = gdk_pixbuf__qtif_image_free_loader(context, &tmp);
Packit a4058c
                    if(!r)
Packit a4058c
                    {
Packit a4058c
                        if((error != NULL) && (*error == NULL))
Packit a4058c
                        {
Packit a4058c
                            g_propagate_error (error, tmp);
Packit a4058c
                        }
Packit a4058c
                        ret = FALSE;
Packit a4058c
                    }
Packit a4058c
                }
Packit a4058c
                buf = &buf[context->run_length];
Packit a4058c
                size -= context->run_length;
Packit a4058c
                context->run_length = 0u;
Packit a4058c
                context->state = STATE_READY;
Packit a4058c
            }
Packit a4058c
            break;
Packit a4058c
        }
Packit a4058c
    }
Packit a4058c
Packit a4058c
    return ret;
Packit a4058c
}
Packit a4058c
Packit a4058c
/* Event handlers */
Packit a4058c
static void gdk_pixbuf__qtif_cb_size_prepared(GdkPixbufLoader *loader,
Packit a4058c
                                              gint width,
Packit a4058c
                                              gint height,
Packit a4058c
                                              gpointer user_data)
Packit a4058c
{
Packit a4058c
    QTIFContext *context = (QTIFContext *)user_data;
Packit a4058c
    if((context != NULL) && (context->size_func != NULL))
Packit a4058c
    {
Packit a4058c
        (context->size_func)(&width, &height, context->user_data);
Packit a4058c
        context->cb_prepare_count++;
Packit a4058c
    }
Packit a4058c
}
Packit a4058c
Packit a4058c
static void gdk_pixbuf__qtif_cb_area_prepared(GdkPixbufLoader *loader, gpointer user_data)
Packit a4058c
{
Packit a4058c
    QTIFContext *context = (QTIFContext *)user_data;
Packit a4058c
    if((loader != NULL) && (context != NULL) && (context->prepare_func != NULL))
Packit a4058c
    {
Packit a4058c
        GdkPixbuf *pixbuf = gdk_pixbuf_loader_get_pixbuf(context->loader);
Packit a4058c
        (context->prepare_func)(pixbuf, NULL, context->user_data);
Packit a4058c
        context->cb_update_count++;
Packit a4058c
    }
Packit a4058c
}
Packit a4058c
Packit a4058c
static void gdk_pixbuf__qtif_cb_area_updated(GdkPixbufLoader *loader,
Packit a4058c
                                             gint x,
Packit a4058c
                                             gint y,
Packit a4058c
                                             gint width,
Packit a4058c
                                             gint height,
Packit a4058c
                                             gpointer user_data)
Packit a4058c
{
Packit a4058c
    QTIFContext *context = (QTIFContext *)user_data;
Packit a4058c
    if((loader != NULL) && (context != NULL) && (context->update_func != NULL))
Packit a4058c
    {
Packit a4058c
        GdkPixbuf *pixbuf = gdk_pixbuf_loader_get_pixbuf(context->loader);
Packit a4058c
        (context->update_func)(pixbuf, x, y, width, height, context->user_data);
Packit a4058c
    }
Packit a4058c
}
Packit a4058c
Packit a4058c
Packit a4058c
#ifndef INCLUDE_qtif
Packit a4058c
#define MODULE_ENTRY(function) G_MODULE_EXPORT void function
Packit a4058c
#else
Packit a4058c
#define MODULE_ENTRY(function) void _gdk_pixbuf__qtif_ ## function
Packit a4058c
#endif
Packit a4058c
Packit a4058c
MODULE_ENTRY (fill_vtable) (GdkPixbufModule *module)
Packit a4058c
{
Packit a4058c
    module->load = gdk_pixbuf__qtif_image_load;
Packit a4058c
    module->begin_load = gdk_pixbuf__qtif_image_begin_load;
Packit a4058c
    module->stop_load = gdk_pixbuf__qtif_image_stop_load;
Packit a4058c
    module->load_increment = gdk_pixbuf__qtif_image_load_increment;
Packit a4058c
}
Packit a4058c
Packit a4058c
MODULE_ENTRY (fill_info) (GdkPixbufFormat *info)
Packit a4058c
{
Packit a4058c
    static const GdkPixbufModulePattern signature[] = {
Packit a4058c
        { "abcdidsc", "xxxx    ", 100 },
Packit a4058c
        { "abcdidat", "xxxx    ", 100 },
Packit a4058c
        { NULL, NULL, 0 }
Packit a4058c
    };
Packit a4058c
    static const gchar *mime_types[] = {
Packit a4058c
        "image/x-quicktime",
Packit a4058c
        "image/qtif",
Packit a4058c
        NULL
Packit a4058c
    };
Packit a4058c
    static const gchar *extensions[] = {
Packit a4058c
        "qtif",
Packit a4058c
        "qif",
Packit a4058c
        NULL
Packit a4058c
    };
Packit a4058c
Packit a4058c
    info->name = "qtif";
Packit a4058c
    info->signature = (GdkPixbufModulePattern *) signature;
Packit a4058c
    info->description = NC_("image format", "QuickTime");
Packit a4058c
    info->mime_types = (gchar **) mime_types;
Packit a4058c
    info->extensions = (gchar **) extensions;
Packit a4058c
    info->flags = GDK_PIXBUF_FORMAT_THREADSAFE;
Packit a4058c
    info->license = "LGPL";
Packit a4058c
}
Packit a4058c