1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
2/* GdkPixbuf library - Simple transformations of animations
3 *
4 * Copyright (C) Red Hat, Inc
5 *
6 * Authors: Matthias Clasen <mclasen@redhat.com>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
20 *
21 */
22
23#include <glib.h>
24
25#include "gdk-pixbuf.h"
26#include "gdk-pixbuf-io.h"
27#include "gdk-pixbuf-scaled-anim.h"
28
29
30struct _GdkPixbufScaledAnimClass
31{
32 GdkPixbufAnimationClass parent_class;
33};
34
35struct _GdkPixbufScaledAnim
36{
37 GdkPixbufAnimation parent_instance;
38
39 GdkPixbufAnimation *anim;
40 gdouble xscale;
41 gdouble yscale;
42 gdouble tscale;
43
44 GdkPixbuf *current;
45};
46
47struct _GdkPixbufScaledAnimIterClass
48{
49 GdkPixbufAnimationClass parent_class;
50};
51
52struct _GdkPixbufScaledAnimIter
53{
54 GdkPixbufAnimationIter parent_instance;
55
56 GdkPixbufScaledAnim *scaled;
57 GdkPixbufAnimationIter *iter;
58};
59
60typedef struct _GdkPixbufScaledAnimIter GdkPixbufScaledAnimIter;
61typedef struct _GdkPixbufScaledAnimIterClass GdkPixbufScaledAnimIterClass;
62
63GdkPixbufScaledAnim *
64_gdk_pixbuf_scaled_anim_new (GdkPixbufAnimation *anim,
65 gdouble xscale,
66 gdouble yscale,
67 gdouble tscale)
68{
69 GdkPixbufScaledAnim *scaled;
70
71 scaled = g_object_new (GDK_TYPE_PIXBUF_SCALED_ANIM, NULL);
72
73 scaled->anim = g_object_ref (anim);
74 scaled->xscale = xscale;
75 scaled->yscale = yscale;
76 scaled->tscale = tscale;
77
78 return scaled;
79}
80
81G_DEFINE_TYPE (GdkPixbufScaledAnim, gdk_pixbuf_scaled_anim, GDK_TYPE_PIXBUF_ANIMATION);
82
83static void
84gdk_pixbuf_scaled_anim_init (GdkPixbufScaledAnim *scaled)
85{
86 scaled->xscale = 1.0;
87 scaled->yscale = 1.0;
88 scaled->tscale = 1.0;
89}
90
91static void
92gdk_pixbuf_scaled_anim_finalize (GObject *object)
93{
94 GdkPixbufScaledAnim *scaled = (GdkPixbufScaledAnim *)object;
95
96 if (scaled->anim) {
97 g_object_unref (object: scaled->anim);
98 scaled->anim = NULL;
99 }
100
101 if (scaled->current) {
102 g_object_unref (object: scaled->current);
103 scaled->current = NULL;
104 }
105
106 G_OBJECT_CLASS (gdk_pixbuf_scaled_anim_parent_class)->finalize (object);
107}
108
109static gboolean
110is_static_image (GdkPixbufAnimation *anim)
111{
112 GdkPixbufScaledAnim *scaled = (GdkPixbufScaledAnim *)anim;
113
114 return gdk_pixbuf_animation_is_static_image (animation: scaled->anim);
115}
116
117static GdkPixbuf *
118get_scaled_pixbuf (GdkPixbufScaledAnim *scaled,
119 GdkPixbuf *pixbuf)
120{
121 GQuark quark;
122 gchar **options;
123
124 if (scaled->current)
125 g_object_unref (object: scaled->current);
126
127 /* Preserve the options associated with the original pixbuf
128 (if present), mostly so that client programs can use the
129 "orientation" option (if present) to rotate the image
130 appropriately. gdk_pixbuf_scale_simple (and most other
131 gdk transform operations) does not preserve the attached
132 options when returning a new pixbuf. */
133
134 quark = g_quark_from_static_string (string: "gdk_pixbuf_options");
135 options = g_object_get_qdata (G_OBJECT (pixbuf), quark);
136
137 /* Get a new scaled pixbuf */
138 scaled->current = gdk_pixbuf_scale_simple (src: pixbuf,
139 MAX((int) ((gdouble) gdk_pixbuf_get_width (pixbuf) * scaled->xscale + .5), 1),
140 MAX((int) ((gdouble) gdk_pixbuf_get_height (pixbuf) * scaled->yscale + .5), 1),
141 interp_type: GDK_INTERP_BILINEAR);
142
143 /* Copy the original pixbuf options to the scaled pixbuf */
144 if (options && scaled->current)
145 g_object_set_qdata_full (G_OBJECT (scaled->current), quark,
146 data: g_strdupv (str_array: options), destroy: (GDestroyNotify) g_strfreev);
147
148 return scaled->current;
149}
150
151static GdkPixbuf *
152get_static_image (GdkPixbufAnimation *anim)
153{
154 GdkPixbufScaledAnim *scaled = (GdkPixbufScaledAnim *)anim;
155 GdkPixbuf *pixbuf;
156
157 pixbuf = gdk_pixbuf_animation_get_static_image (animation: scaled->anim);
158 return get_scaled_pixbuf (scaled, pixbuf);
159}
160
161static void
162get_size (GdkPixbufAnimation *anim,
163 int *width,
164 int *height)
165{
166 GdkPixbufScaledAnim *scaled = (GdkPixbufScaledAnim *)anim;
167
168 GDK_PIXBUF_ANIMATION_GET_CLASS (scaled->anim)->get_size (scaled->anim, width, height);
169 if (width)
170 *width = (int)(*width * scaled->xscale + .5);
171 if (height)
172 *height = (int)(*height * scaled->yscale + .5);
173}
174
175G_GNUC_BEGIN_IGNORE_DEPRECATIONS
176static GdkPixbufAnimationIter *
177get_iter (GdkPixbufAnimation *anim,
178 const GTimeVal *start_time)
179{
180 GdkPixbufScaledAnim *scaled = (GdkPixbufScaledAnim *)anim;
181 GdkPixbufScaledAnimIter *iter;
182
183 iter = g_object_new (GDK_TYPE_PIXBUF_SCALED_ANIM_ITER, NULL);
184
185 iter->scaled = g_object_ref (scaled);
186 iter->iter = gdk_pixbuf_animation_get_iter (animation: scaled->anim, start_time);
187
188 return (GdkPixbufAnimationIter*)iter;
189}
190G_GNUC_END_IGNORE_DEPRECATIONS
191
192static void
193gdk_pixbuf_scaled_anim_class_init (GdkPixbufScaledAnimClass *klass)
194{
195 GObjectClass *object_class;
196 GdkPixbufAnimationClass *anim_class;
197
198 object_class = G_OBJECT_CLASS (klass);
199 anim_class = GDK_PIXBUF_ANIMATION_CLASS (klass);
200
201 object_class->finalize = gdk_pixbuf_scaled_anim_finalize;
202
203 anim_class->is_static_image = is_static_image;
204 anim_class->get_static_image = get_static_image;
205 anim_class->get_size = get_size;
206 anim_class->get_iter = get_iter;
207}
208
209
210G_DEFINE_TYPE (GdkPixbufScaledAnimIter, gdk_pixbuf_scaled_anim_iter, GDK_TYPE_PIXBUF_ANIMATION_ITER);
211
212static void
213gdk_pixbuf_scaled_anim_iter_init (GdkPixbufScaledAnimIter *iter)
214{
215}
216
217static int
218get_delay_time (GdkPixbufAnimationIter *iter)
219{
220 GdkPixbufScaledAnimIter *scaled = (GdkPixbufScaledAnimIter *)iter;
221 int delay;
222
223 delay = gdk_pixbuf_animation_iter_get_delay_time (iter: scaled->iter);
224 delay = (int)(delay * scaled->scaled->tscale);
225
226 return delay;
227}
228
229static GdkPixbuf *
230get_pixbuf (GdkPixbufAnimationIter *iter)
231{
232 GdkPixbufScaledAnimIter *scaled = (GdkPixbufScaledAnimIter *)iter;
233 GdkPixbuf *pixbuf;
234
235 pixbuf = gdk_pixbuf_animation_iter_get_pixbuf (iter: scaled->iter);
236 return get_scaled_pixbuf (scaled: scaled->scaled, pixbuf);
237}
238
239static gboolean
240on_currently_loading_frame (GdkPixbufAnimationIter *iter)
241{
242 GdkPixbufScaledAnimIter *scaled = (GdkPixbufScaledAnimIter *)iter;
243
244 return gdk_pixbuf_animation_iter_on_currently_loading_frame (iter: scaled->iter);
245}
246
247G_GNUC_BEGIN_IGNORE_DEPRECATIONS
248static gboolean
249advance (GdkPixbufAnimationIter *iter,
250 const GTimeVal *current_time)
251{
252 GdkPixbufScaledAnimIter *scaled = (GdkPixbufScaledAnimIter *)iter;
253
254 return gdk_pixbuf_animation_iter_advance (iter: scaled->iter, current_time);
255}
256G_GNUC_END_IGNORE_DEPRECATIONS
257
258static void
259gdk_pixbuf_scaled_anim_iter_finalize (GObject *object)
260{
261 GdkPixbufScaledAnimIter *iter = (GdkPixbufScaledAnimIter *)object;
262
263 g_object_unref (object: iter->iter);
264 g_object_unref (object: iter->scaled);
265
266 G_OBJECT_CLASS (gdk_pixbuf_scaled_anim_iter_parent_class)->finalize (object);
267}
268
269static void
270gdk_pixbuf_scaled_anim_iter_class_init (GdkPixbufScaledAnimIterClass *klass)
271{
272 GObjectClass *object_class;
273 GdkPixbufAnimationIterClass *anim_iter_class;
274
275 object_class = G_OBJECT_CLASS (klass);
276 anim_iter_class = GDK_PIXBUF_ANIMATION_ITER_CLASS (klass);
277
278 object_class->finalize = gdk_pixbuf_scaled_anim_iter_finalize;
279
280 anim_iter_class->get_delay_time = get_delay_time;
281 anim_iter_class->get_pixbuf = get_pixbuf;
282 anim_iter_class->on_currently_loading_frame = on_currently_loading_frame;
283 anim_iter_class->advance = advance;
284}
285

source code of gtk/subprojects/gdk-pixbuf/gdk-pixbuf/gdk-pixbuf-scaled-anim.c