Blame gdk-pixbuf/gdk-pixbuf-scaled-anim.c

Packit a4058c
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
Packit a4058c
/* GdkPixbuf library - Simple transformations of animations
Packit a4058c
 *
Packit a4058c
 * Copyright (C) Red Hat, Inc
Packit a4058c
 *
Packit a4058c
 * Authors: Matthias Clasen <mclasen@redhat.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 <glib.h>
Packit a4058c
Packit a4058c
#include "gdk-pixbuf.h"
Packit a4058c
#include "gdk-pixbuf-io.h"
Packit a4058c
#include "gdk-pixbuf-scaled-anim.h"
Packit a4058c
Packit a4058c
Packit a4058c
struct _GdkPixbufScaledAnimClass
Packit a4058c
{
Packit a4058c
        GdkPixbufAnimationClass parent_class;
Packit a4058c
};
Packit a4058c
Packit a4058c
struct _GdkPixbufScaledAnim
Packit a4058c
{
Packit a4058c
 	GdkPixbufAnimation parent_instance;
Packit a4058c
Packit a4058c
	GdkPixbufAnimation *anim;
Packit a4058c
	gdouble xscale;
Packit a4058c
	gdouble yscale;
Packit a4058c
	gdouble tscale;
Packit a4058c
Packit a4058c
	GdkPixbuf *current;
Packit a4058c
};
Packit a4058c
Packit a4058c
struct _GdkPixbufScaledAnimIterClass
Packit a4058c
{
Packit a4058c
        GdkPixbufAnimationClass parent_class;
Packit a4058c
};
Packit a4058c
Packit a4058c
struct _GdkPixbufScaledAnimIter
Packit a4058c
{
Packit a4058c
 	GdkPixbufAnimationIter parent_instance;
Packit a4058c
Packit a4058c
	GdkPixbufScaledAnim *scaled;
Packit a4058c
        GdkPixbufAnimationIter *iter;
Packit a4058c
};
Packit a4058c
Packit a4058c
typedef struct _GdkPixbufScaledAnimIter GdkPixbufScaledAnimIter;
Packit a4058c
typedef struct _GdkPixbufScaledAnimIterClass GdkPixbufScaledAnimIterClass;
Packit a4058c
Packit a4058c
GdkPixbufScaledAnim *
Packit a4058c
_gdk_pixbuf_scaled_anim_new (GdkPixbufAnimation *anim,
Packit a4058c
                             gdouble             xscale,
Packit a4058c
                             gdouble             yscale,
Packit a4058c
                             gdouble             tscale)
Packit a4058c
{
Packit a4058c
	GdkPixbufScaledAnim *scaled;
Packit a4058c
Packit a4058c
	scaled = g_object_new (GDK_TYPE_PIXBUF_SCALED_ANIM, NULL);
Packit a4058c
Packit a4058c
	scaled->anim = g_object_ref (anim);
Packit a4058c
	scaled->xscale = xscale;
Packit a4058c
	scaled->yscale = yscale;
Packit a4058c
	scaled->tscale = tscale;
Packit a4058c
Packit a4058c
	return scaled;
Packit a4058c
}
Packit a4058c
Packit a4058c
G_DEFINE_TYPE (GdkPixbufScaledAnim, gdk_pixbuf_scaled_anim, GDK_TYPE_PIXBUF_ANIMATION);
Packit a4058c
Packit a4058c
static void
Packit a4058c
gdk_pixbuf_scaled_anim_init (GdkPixbufScaledAnim *scaled)
Packit a4058c
{
Packit a4058c
	scaled->xscale = 1.0;
Packit a4058c
	scaled->yscale = 1.0;
Packit a4058c
	scaled->tscale = 1.0;
Packit a4058c
}
Packit a4058c
Packit a4058c
static void
Packit a4058c
gdk_pixbuf_scaled_anim_finalize (GObject *object)
Packit a4058c
{
Packit a4058c
	GdkPixbufScaledAnim *scaled = (GdkPixbufScaledAnim *)object;
Packit a4058c
Packit a4058c
	if (scaled->anim) {
Packit a4058c
		g_object_unref (scaled->anim);
Packit a4058c
		scaled->anim = NULL;
Packit a4058c
	}
Packit a4058c
Packit a4058c
	if (scaled->current) {
Packit a4058c
		g_object_unref (scaled->current);
Packit a4058c
		scaled->current = NULL;
Packit a4058c
	}
Packit a4058c
Packit a4058c
	G_OBJECT_CLASS (gdk_pixbuf_scaled_anim_parent_class)->finalize (object);
Packit a4058c
}
Packit a4058c
Packit a4058c
static gboolean
Packit a4058c
is_static_image (GdkPixbufAnimation *anim)
Packit a4058c
{
Packit a4058c
	GdkPixbufScaledAnim *scaled = (GdkPixbufScaledAnim *)anim;
Packit a4058c
Packit a4058c
	return gdk_pixbuf_animation_is_static_image (scaled->anim);
Packit a4058c
}	
Packit a4058c
Packit a4058c
static GdkPixbuf *
Packit a4058c
get_scaled_pixbuf (GdkPixbufScaledAnim *scaled, 
Packit a4058c
                   GdkPixbuf           *pixbuf)
Packit a4058c
{
Packit a4058c
	GQuark  quark;
Packit a4058c
	gchar **options;
Packit a4058c
Packit a4058c
	if (scaled->current) 
Packit a4058c
		g_object_unref (scaled->current);
Packit a4058c
Packit a4058c
	/* Preserve the options associated with the original pixbuf 
Packit a4058c
	   (if present), mostly so that client programs can use the
Packit a4058c
	   "orientation" option (if present) to rotate the image 
Packit a4058c
	   appropriately. gdk_pixbuf_scale_simple (and most other
Packit a4058c
           gdk transform operations) does not preserve the attached
Packit a4058c
           options when returning a new pixbuf. */
Packit a4058c
Packit a4058c
	quark = g_quark_from_static_string ("gdk_pixbuf_options");
Packit a4058c
	options = g_object_get_qdata (G_OBJECT (pixbuf), quark);
Packit a4058c
Packit a4058c
	/* Get a new scaled pixbuf */
Packit a4058c
	scaled->current  = gdk_pixbuf_scale_simple (pixbuf, 
Packit a4058c
                        MAX((int) ((gdouble) gdk_pixbuf_get_width (pixbuf) * scaled->xscale + .5), 1),
Packit a4058c
                        MAX((int) ((gdouble) gdk_pixbuf_get_height (pixbuf) * scaled->yscale + .5), 1),
Packit a4058c
			GDK_INTERP_BILINEAR);
Packit a4058c
Packit a4058c
	/* Copy the original pixbuf options to the scaled pixbuf */
Packit a4058c
        if (options && scaled->current)
Packit a4058c
	          g_object_set_qdata_full (G_OBJECT (scaled->current), quark, 
Packit a4058c
                                           g_strdupv (options), (GDestroyNotify) g_strfreev);
Packit a4058c
Packit a4058c
	return scaled->current;
Packit a4058c
}
Packit a4058c
Packit a4058c
static GdkPixbuf *
Packit a4058c
get_static_image (GdkPixbufAnimation *anim)
Packit a4058c
{
Packit a4058c
	GdkPixbufScaledAnim *scaled = (GdkPixbufScaledAnim *)anim;
Packit a4058c
	GdkPixbuf *pixbuf;
Packit a4058c
	
Packit a4058c
	pixbuf = gdk_pixbuf_animation_get_static_image (scaled->anim);
Packit a4058c
	return get_scaled_pixbuf (scaled, pixbuf);
Packit a4058c
}
Packit a4058c
Packit a4058c
static void
Packit a4058c
get_size (GdkPixbufAnimation *anim,
Packit a4058c
	  int                *width,
Packit a4058c
	  int 		     *height)
Packit a4058c
{
Packit a4058c
	GdkPixbufScaledAnim *scaled = (GdkPixbufScaledAnim *)anim;
Packit a4058c
Packit a4058c
        GDK_PIXBUF_ANIMATION_GET_CLASS (scaled->anim)->get_size (scaled->anim, width, height);
Packit a4058c
	if (width) 
Packit a4058c
		*width = (int)(*width * scaled->xscale + .5);
Packit a4058c
	if (height)
Packit a4058c
		*height = (int)(*height * scaled->yscale + .5);
Packit a4058c
}
Packit a4058c
Packit a4058c
static GdkPixbufAnimationIter *
Packit a4058c
get_iter (GdkPixbufAnimation *anim,
Packit a4058c
          const GTimeVal     *start_time)
Packit a4058c
{
Packit a4058c
	GdkPixbufScaledAnim *scaled = (GdkPixbufScaledAnim *)anim;
Packit a4058c
	GdkPixbufScaledAnimIter *iter;
Packit a4058c
Packit a4058c
	iter = g_object_new (GDK_TYPE_PIXBUF_SCALED_ANIM_ITER, NULL);
Packit a4058c
Packit a4058c
	iter->scaled = g_object_ref (scaled);
Packit a4058c
	iter->iter = gdk_pixbuf_animation_get_iter (scaled->anim, start_time);
Packit a4058c
	
Packit a4058c
	return (GdkPixbufAnimationIter*)iter;
Packit a4058c
}
Packit a4058c
Packit a4058c
static void
Packit a4058c
gdk_pixbuf_scaled_anim_class_init (GdkPixbufScaledAnimClass *klass)
Packit a4058c
{
Packit a4058c
        GObjectClass *object_class;
Packit a4058c
        GdkPixbufAnimationClass *anim_class;
Packit a4058c
Packit a4058c
        object_class = G_OBJECT_CLASS (klass);
Packit a4058c
        anim_class = GDK_PIXBUF_ANIMATION_CLASS (klass);
Packit a4058c
        
Packit a4058c
        object_class->finalize = gdk_pixbuf_scaled_anim_finalize;
Packit a4058c
        
Packit a4058c
        anim_class->is_static_image = is_static_image;
Packit a4058c
        anim_class->get_static_image = get_static_image;
Packit a4058c
        anim_class->get_size = get_size;
Packit a4058c
        anim_class->get_iter = get_iter;
Packit a4058c
}
Packit a4058c
Packit a4058c
Packit a4058c
G_DEFINE_TYPE (GdkPixbufScaledAnimIter, gdk_pixbuf_scaled_anim_iter, GDK_TYPE_PIXBUF_ANIMATION_ITER);
Packit a4058c
Packit a4058c
static void
Packit a4058c
gdk_pixbuf_scaled_anim_iter_init (GdkPixbufScaledAnimIter *iter)
Packit a4058c
{
Packit a4058c
}
Packit a4058c
Packit a4058c
static int
Packit a4058c
get_delay_time (GdkPixbufAnimationIter *iter)
Packit a4058c
{
Packit a4058c
	GdkPixbufScaledAnimIter *scaled = (GdkPixbufScaledAnimIter *)iter;
Packit a4058c
	int delay;
Packit a4058c
Packit a4058c
	delay = gdk_pixbuf_animation_iter_get_delay_time (scaled->iter);
Packit a4058c
	delay = (int)(delay * scaled->scaled->tscale);
Packit a4058c
Packit a4058c
	return delay;
Packit a4058c
}
Packit a4058c
Packit a4058c
static GdkPixbuf *
Packit a4058c
get_pixbuf (GdkPixbufAnimationIter *iter)
Packit a4058c
{
Packit a4058c
	GdkPixbufScaledAnimIter *scaled = (GdkPixbufScaledAnimIter *)iter;
Packit a4058c
	GdkPixbuf *pixbuf;
Packit a4058c
Packit a4058c
	pixbuf = gdk_pixbuf_animation_iter_get_pixbuf (scaled->iter);
Packit a4058c
	return get_scaled_pixbuf (scaled->scaled, pixbuf);
Packit a4058c
}
Packit a4058c
Packit a4058c
static gboolean 
Packit a4058c
on_currently_loading_frame (GdkPixbufAnimationIter *iter)
Packit a4058c
{
Packit a4058c
	GdkPixbufScaledAnimIter *scaled = (GdkPixbufScaledAnimIter *)iter;
Packit a4058c
Packit a4058c
	return gdk_pixbuf_animation_iter_on_currently_loading_frame (scaled->iter);
Packit a4058c
}
Packit a4058c
Packit a4058c
static gboolean
Packit a4058c
advance (GdkPixbufAnimationIter *iter,
Packit a4058c
	 const GTimeVal         *current_time)
Packit a4058c
{
Packit a4058c
	GdkPixbufScaledAnimIter *scaled = (GdkPixbufScaledAnimIter *)iter;
Packit a4058c
Packit a4058c
	return gdk_pixbuf_animation_iter_advance (scaled->iter, current_time);
Packit a4058c
}
Packit a4058c
Packit a4058c
static void
Packit a4058c
gdk_pixbuf_scaled_anim_iter_finalize (GObject *object)
Packit a4058c
{
Packit a4058c
        GdkPixbufScaledAnimIter *iter = (GdkPixbufScaledAnimIter *)object;
Packit a4058c
        
Packit a4058c
	g_object_unref (iter->iter);
Packit a4058c
   	g_object_unref (iter->scaled);
Packit a4058c
Packit a4058c
	G_OBJECT_CLASS (gdk_pixbuf_scaled_anim_iter_parent_class)->finalize (object);
Packit a4058c
}
Packit a4058c
Packit a4058c
static void
Packit a4058c
gdk_pixbuf_scaled_anim_iter_class_init (GdkPixbufScaledAnimIterClass *klass)
Packit a4058c
{
Packit a4058c
        GObjectClass *object_class;
Packit a4058c
        GdkPixbufAnimationIterClass *anim_iter_class;
Packit a4058c
Packit a4058c
        object_class = G_OBJECT_CLASS (klass);
Packit a4058c
        anim_iter_class = GDK_PIXBUF_ANIMATION_ITER_CLASS (klass);
Packit a4058c
        
Packit a4058c
        object_class->finalize = gdk_pixbuf_scaled_anim_iter_finalize;
Packit a4058c
        
Packit a4058c
        anim_iter_class->get_delay_time = get_delay_time;
Packit a4058c
        anim_iter_class->get_pixbuf = get_pixbuf;
Packit a4058c
        anim_iter_class->on_currently_loading_frame = on_currently_loading_frame;
Packit a4058c
        anim_iter_class->advance = advance;
Packit a4058c
}