~canonical-dx-team/ubuntu/maverick/gtk+2.0/menuproxy

« back to all changes in this revision

Viewing changes to gdk-pixbuf/gdk-pixbuf-animation.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2007-05-04 12:24:25 UTC
  • mfrom: (1.1.21 upstream)
  • Revision ID: james.westby@ubuntu.com-20070504122425-0m8midgzrp40y8w2
Tags: 2.10.12-1ubuntu1
* Sync with Debian
* New upstream version:
  Fixed bugs:
  - 379414 file chooser warnings when changing path in the entry
  - 418585 GtkFileChooserDefault sizing code is not DPI independent
  - 419568 Crash in search if start with special letter
  - 435062 build dies with icon cache validation
  - 379399 Segfault to call gtk_print_operation_run twice.
  - 387889 cups backend has problems when there are too many printers
  - 418531 invalid read to gtkicontheme.c gtk_icon_theme_lookup_icon...
  - 423916 crash in color scheme code
  - 424042 Segmentation fault while quickly pressing Alt+arrows
  - 415260 Protect against negative indices when setting values in G...
  - 419171 XGetVisualInfo() may not set nxvisuals
  - 128852 Gdk cursors don't look good on win32
  - 344657 Ctrl-H doesn't toggle "Show Hidden Files" setting
  - 345345 PrintOperation::paginate is not emitted for class handler
  - 347567 GtkPrintOperation::end-print is not emitted if it's cance...
  - 369112 gtk_ui_manager_add_ui should accept unnamed separator
  - 392015 Selected menu item invisible on Windows Vista
  - 399253 MS-Windows Theme Bottom Tab placement rendering glitches
  - 399425 gtk_input_dialog_fill_axes() adds child to gtkscrolledwin...
  - 403251 [patch] little memory leak in GtkPrintJob
  - 403267 [patch] memory leak in GtkPageSetupUnixDialog
  - 403470 MS-Windows Theme tab placement other than on top leaks a ...
  - 404506 Windows system fonts that have multi-byte font names cann...
  - 405089 Incorrect window placement for GtkEventBox private window
  - 405515 Minor leak in gtkfilesystemmodel.c
  - 405539 gdk_pixbuf_save() for PNG saver can return FALSE without ...
  - 415681 gdk_window_clear_area includes an extra line and column o...
  - 418219 GtkRecentChooser should apply filter before sorting and c...
  - 418403 Scroll to printer after selecting it from settings
  - 421985 _gtk_print_operation_platform_backend_launch_preview
  - 421990 gtk_print_job_get_surface
  - 421993 gtk_print_operation_init
  - 423064 Conditional jump or move depends on uninitialised value(s...
  - 423722 Fix printing header in gtk-demo
  - 424168 gtk_print_operation_run on async preview
  - 425655 Don't install gtk+-unix-print-2.0.pc on non-UNIX platforms
  - 425786 GDK segfaults if XineramaQueryScreens fails
  - 428665 Lpr Backend gets stuck in infinite loop during gtk_enumer...
  - 429902 GtkPrintOperation leaks cairo contextes
  - 431997 First delay of GdkPixbufAnimationIter is wrong
  - 433242 Inconsistent scroll arrow position calculations
  - 433972 Placing gtk.Expander inside a gtk.TextView() changes gtk....
  - 434261 _gtk_toolbar_elide_underscores incorrectly handles some s...
  - 383354 ctrl-L should make 'Location' entry disappear
  - 418673 gtk_recent_manager_add_item
  - 429732 gtk_accel_group_finalize accesses invalid memory
  - 435028 WM_CLIENT_LEADER is wrong on the leader_window
  - 431067 Background of the header window is not updated
  - 338843 add recent files support inside the ui manager
  - 148535 add drop shadow to menus, tooltips, etc. under Windows XP
* debian/control.in:
  - Conflicts on ubuntulooks (<= 0.9.11-1)
* debian/patches/15_default-fallback-icon-theme.patch:
  - patch from Debian, fallback on gnome icon theme

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
 
2
/* GdkPixbuf library - Simple animation support
 
3
 *
 
4
 * Copyright (C) 1999 The Free Software Foundation
 
5
 *
 
6
 * Authors: Jonathan Blandford <jrb@redhat.com>
 
7
 *          Havoc Pennington <hp@redhat.com>
 
8
 *
 
9
 * This library is free software; you can redistribute it and/or
 
10
 * modify it under the terms of the GNU Lesser General Public
 
11
 * License as published by the Free Software Foundation; either
 
12
 * version 2 of the License, or (at your option) any later version.
 
13
 *
 
14
 * This library is distributed in the hope that it will be useful,
 
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
17
 * Lesser General Public License for more details.
 
18
 *
 
19
 * You should have received a copy of the GNU Lesser General Public
 
20
 * License along with this library; if not, write to the
 
21
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
22
 * Boston, MA 02111-1307, USA.
 
23
 */
 
24
 
 
25
#include <config.h>
 
26
#include <errno.h>
 
27
#include "gdk-pixbuf-private.h"
 
28
#include "gdk-pixbuf-io.h"
 
29
#include "gdk-pixbuf-i18n.h"
 
30
#include "gdk-pixbuf-animation.h"
 
31
#include "gdk-pixbuf-alias.h"
 
32
 
 
33
#include <glib/gstdio.h>
 
34
 
 
35
typedef struct _GdkPixbufNonAnim GdkPixbufNonAnim;
 
36
typedef struct _GdkPixbufNonAnimClass GdkPixbufNonAnimClass;
 
37
 
 
38
#define GDK_TYPE_PIXBUF_NON_ANIM              (gdk_pixbuf_non_anim_get_type ())
 
39
#define GDK_PIXBUF_NON_ANIM(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_PIXBUF_NON_ANIM, GdkPixbufNonAnim))
 
40
#define GDK_IS_PIXBUF_NON_ANIM(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_PIXBUF_NON_ANIM))
 
41
 
 
42
#define GDK_PIXBUF_NON_ANIM_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_PIXBUF_NON_ANIM, GdkPixbufNonAnimClass))
 
43
#define GDK_IS_PIXBUF_NON_ANIM_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_PIXBUF_NON_ANIM))
 
44
#define GDK_PIXBUF_NON_ANIM_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_PIXBUF_NON_ANIM, GdkPixbufNonAnimClass))
 
45
 
 
46
/* Private part of the GdkPixbufNonAnim structure */
 
47
struct _GdkPixbufNonAnim {
 
48
        GdkPixbufAnimation parent_instance;
 
49
 
 
50
        GdkPixbuf *pixbuf;
 
51
};
 
52
 
 
53
struct _GdkPixbufNonAnimClass {
 
54
        GdkPixbufAnimationClass parent_class;
 
55
        
 
56
};
 
57
 
 
58
static GType gdk_pixbuf_non_anim_get_type (void) G_GNUC_CONST;
 
59
 
 
60
 
 
61
 
 
62
typedef struct _GdkPixbufNonAnimIter GdkPixbufNonAnimIter;
 
63
typedef struct _GdkPixbufNonAnimIterClass GdkPixbufNonAnimIterClass;
 
64
 
 
65
 
 
66
#define GDK_TYPE_PIXBUF_NON_ANIM_ITER              (gdk_pixbuf_non_anim_iter_get_type ())
 
67
#define GDK_PIXBUF_NON_ANIM_ITER(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_PIXBUF_NON_ANIM_ITER, GdkPixbufNonAnimIter))
 
68
#define GDK_IS_PIXBUF_NON_ANIM_ITER(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_PIXBUF_NON_ANIM_ITER))
 
69
 
 
70
#define GDK_PIXBUF_NON_ANIM_ITER_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_PIXBUF_NON_ANIM_ITER, GdkPixbufNonAnimIterClass))
 
71
#define GDK_IS_PIXBUF_NON_ANIM_ITER_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_PIXBUF_NON_ANIM_ITER))
 
72
#define GDK_PIXBUF_NON_ANIM_ITER_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_PIXBUF_NON_ANIM_ITER, GdkPixbufNonAnimIterClass))
 
73
 
 
74
struct _GdkPixbufNonAnimIter {
 
75
        GdkPixbufAnimationIter parent_instance;
 
76
 
 
77
        GdkPixbufNonAnim   *non_anim;
 
78
};
 
79
 
 
80
struct _GdkPixbufNonAnimIterClass {
 
81
        GdkPixbufAnimationIterClass parent_class;
 
82
 
 
83
};
 
84
 
 
85
static GType gdk_pixbuf_non_anim_iter_get_type (void) G_GNUC_CONST;
 
86
 
 
87
 
 
88
 
 
89
GType
 
90
gdk_pixbuf_animation_get_type (void)
 
91
{
 
92
        static GType object_type = 0;
 
93
 
 
94
        if (!object_type) {
 
95
                static const GTypeInfo object_info = {
 
96
                        sizeof (GdkPixbufAnimationClass),
 
97
                        (GBaseInitFunc) NULL,
 
98
                        (GBaseFinalizeFunc) NULL,
 
99
                        (GClassInitFunc) NULL,
 
100
                        NULL,           /* class_finalize */
 
101
                        NULL,           /* class_data */
 
102
                        sizeof (GdkPixbufAnimation),
 
103
                        0,              /* n_preallocs */
 
104
                        (GInstanceInitFunc) NULL,
 
105
                };
 
106
                
 
107
                object_type = g_type_register_static (G_TYPE_OBJECT,
 
108
                                                      g_intern_static_string ("GdkPixbufAnimation"),
 
109
                                                      &object_info, 0);
 
110
        }
 
111
  
 
112
        return object_type;
 
113
}
 
114
 
 
115
 
 
116
 
 
117
/**
 
118
 * gdk_pixbuf_animation_new_from_file:
 
119
 * @filename: Name of file to load, in the GLib file name encoding
 
120
 * @error: return location for error
 
121
 *
 
122
 * Creates a new animation by loading it from a file.  The file format is
 
123
 * detected automatically.  If the file's format does not support multi-frame
 
124
 * images, then an animation with a single frame will be created. Possible errors
 
125
 * are in the #GDK_PIXBUF_ERROR and #G_FILE_ERROR domains.
 
126
 *
 
127
 * Return value: A newly-created animation with a reference count of 1, or %NULL
 
128
 * if any of several error conditions ocurred:  the file could not be opened,
 
129
 * there was no loader for the file's format, there was not enough memory to
 
130
 * allocate the image buffer, or the image file contained invalid data.
 
131
 **/
 
132
GdkPixbufAnimation *
 
133
gdk_pixbuf_animation_new_from_file (const char *filename,
 
134
                                    GError    **error)
 
135
{
 
136
        GdkPixbufAnimation *animation;
 
137
        int size;
 
138
        FILE *f;
 
139
        guchar buffer [1024];
 
140
        GdkPixbufModule *image_module;
 
141
        gchar *display_name;
 
142
        gboolean locked = FALSE;
 
143
 
 
144
        g_return_val_if_fail (filename != NULL, NULL);
 
145
        g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
146
 
 
147
        display_name = g_filename_display_name (filename);
 
148
        f = g_fopen (filename, "rb");
 
149
        if (!f) {
 
150
                gint save_errno = errno;
 
151
                g_set_error (error,
 
152
                             G_FILE_ERROR,
 
153
                             g_file_error_from_errno (save_errno),
 
154
                             _("Failed to open file '%s': %s"),
 
155
                             display_name,
 
156
                             g_strerror (save_errno));
 
157
                g_free (display_name);
 
158
                return NULL;
 
159
        }
 
160
 
 
161
        size = fread (&buffer, 1, sizeof (buffer), f);
 
162
 
 
163
        if (size == 0) {
 
164
                g_set_error (error,
 
165
                             GDK_PIXBUF_ERROR,
 
166
                             GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
 
167
                             _("Image file '%s' contains no data"),
 
168
                             display_name);
 
169
                g_free (display_name);
 
170
                fclose (f);
 
171
                return NULL;
 
172
        }
 
173
 
 
174
        image_module = _gdk_pixbuf_get_module (buffer, size, filename, error);
 
175
        if (!image_module) {
 
176
                g_free (display_name);
 
177
                fclose (f);
 
178
                return NULL;
 
179
        }
 
180
 
 
181
        if (image_module->module == NULL)
 
182
                if (!_gdk_pixbuf_load_module (image_module, error)) {
 
183
                        g_free (display_name);
 
184
                        fclose (f);
 
185
                        return NULL;
 
186
                }
 
187
 
 
188
        if (image_module->load_animation == NULL) {
 
189
                GdkPixbuf *pixbuf;
 
190
 
 
191
                /* Keep this logic in sync with gdk_pixbuf_new_from_file() */
 
192
 
 
193
                fseek (f, 0, SEEK_SET);
 
194
                pixbuf = _gdk_pixbuf_generic_image_load (image_module, f, error);
 
195
                fclose (f);
 
196
 
 
197
                if (pixbuf == NULL && error != NULL && *error == NULL) {
 
198
                        /* I don't trust these crufty longjmp()'ing image libs
 
199
                         * to maintain proper error invariants, and I don't
 
200
                         * want user code to segfault as a result. We need to maintain
 
201
                         * the invariant that error gets set if NULL is returned.
 
202
                         */
 
203
                        
 
204
                        g_warning ("Bug! gdk-pixbuf loader '%s' didn't set an error on failure.",
 
205
                                   image_module->module_name);
 
206
                        g_set_error (error,
 
207
                                     GDK_PIXBUF_ERROR,
 
208
                                     GDK_PIXBUF_ERROR_FAILED,
 
209
                                     _("Failed to load image '%s': reason not known, probably a corrupt image file"),
 
210
                                     display_name);
 
211
                }
 
212
                
 
213
                if (pixbuf == NULL) {
 
214
                        g_free (display_name);
 
215
                        animation = NULL;
 
216
                        goto out_unlock;
 
217
                }
 
218
 
 
219
                animation = gdk_pixbuf_non_anim_new (pixbuf);
 
220
 
 
221
                g_object_unref (pixbuf);
 
222
        } else {
 
223
                locked = _gdk_pixbuf_lock (image_module);
 
224
 
 
225
                fseek (f, 0, SEEK_SET);
 
226
                animation = (* image_module->load_animation) (f, error);
 
227
 
 
228
                if (animation == NULL && error != NULL && *error == NULL) {
 
229
                        /* I don't trust these crufty longjmp()'ing
 
230
                         * image libs to maintain proper error
 
231
                         * invariants, and I don't want user code to
 
232
                         * segfault as a result. We need to maintain
 
233
                         * the invariant that error gets set if NULL
 
234
                         * is returned.
 
235
                         */
 
236
                        
 
237
                        g_warning ("Bug! gdk-pixbuf loader '%s' didn't set an error on failure.",
 
238
                                   image_module->module_name);
 
239
                        g_set_error (error,
 
240
                                     GDK_PIXBUF_ERROR,
 
241
                                     GDK_PIXBUF_ERROR_FAILED,
 
242
                                     _("Failed to load animation '%s': reason not known, probably a corrupt animation file"),
 
243
                                     display_name);
 
244
                }
 
245
                
 
246
                fclose (f);
 
247
        }
 
248
 
 
249
        g_free (display_name);
 
250
 
 
251
 out_unlock:
 
252
        if (locked)
 
253
                _gdk_pixbuf_unlock (image_module);
 
254
        return animation;
 
255
}
 
256
 
 
257
#ifdef G_OS_WIN32
 
258
 
 
259
#undef gdk_pixbuf_animation_new_from_file
 
260
 
 
261
GdkPixbufAnimation *
 
262
gdk_pixbuf_animation_new_from_file (const char *filename,
 
263
                                    GError    **error)
 
264
{
 
265
        gchar *utf8_filename =
 
266
                g_locale_to_utf8 (filename, -1, NULL, NULL, error);
 
267
        GdkPixbufAnimation *retval;
 
268
 
 
269
        if (utf8_filename == NULL)
 
270
                return NULL;
 
271
 
 
272
        retval = gdk_pixbuf_animation_new_from_file_utf8 (utf8_filename, error);
 
273
 
 
274
        g_free (utf8_filename);
 
275
 
 
276
        return retval;
 
277
}
 
278
 
 
279
#endif
 
280
 
 
281
/**
 
282
 * gdk_pixbuf_animation_ref:
 
283
 * @animation: An animation.
 
284
 *
 
285
 * Adds a reference to an animation. 
 
286
 *
 
287
 * Return value: The same as the @animation argument.
 
288
 *
 
289
 * Deprecated: Use g_object_ref(). 
 
290
 **/
 
291
GdkPixbufAnimation *
 
292
gdk_pixbuf_animation_ref (GdkPixbufAnimation *animation)
 
293
{
 
294
        return (GdkPixbufAnimation*) g_object_ref (animation);
 
295
}
 
296
 
 
297
/**
 
298
 * gdk_pixbuf_animation_unref:
 
299
 * @animation: An animation.
 
300
 * 
 
301
 * Removes a reference from an animation. 
 
302
 *
 
303
 * Deprecated: Use g_object_unref().
 
304
 **/
 
305
void
 
306
gdk_pixbuf_animation_unref (GdkPixbufAnimation *animation)
 
307
{
 
308
        g_object_unref (animation);
 
309
}
 
310
 
 
311
/**
 
312
 * gdk_pixbuf_animation_is_static_image:
 
313
 * @animation: a #GdkPixbufAnimation
 
314
 * 
 
315
 * If you load a file with gdk_pixbuf_animation_new_from_file() and it turns
 
316
 * out to be a plain, unanimated image, then this function will return
 
317
 * %TRUE. Use gdk_pixbuf_animation_get_static_image() to retrieve
 
318
 * the image.
 
319
 * 
 
320
 * Return value: %TRUE if the "animation" was really just an image
 
321
 **/
 
322
gboolean
 
323
gdk_pixbuf_animation_is_static_image (GdkPixbufAnimation *animation)
 
324
{
 
325
        g_return_val_if_fail (GDK_IS_PIXBUF_ANIMATION (animation), FALSE);
 
326
 
 
327
        return GDK_PIXBUF_ANIMATION_GET_CLASS (animation)->is_static_image (animation);
 
328
}
 
329
 
 
330
/**
 
331
 * gdk_pixbuf_animation_get_static_image:
 
332
 * @animation: a #GdkPixbufAnimation
 
333
 * 
 
334
 * If an animation is really just a plain image (has only one frame),
 
335
 * this function returns that image. If the animation is an animation,
 
336
 * this function returns a reasonable thing to display as a static
 
337
 * unanimated image, which might be the first frame, or something more
 
338
 * sophisticated. If an animation hasn't loaded any frames yet, this
 
339
 * function will return %NULL.
 
340
 * 
 
341
 * Return value: unanimated image representing the animation
 
342
 **/
 
343
GdkPixbuf*
 
344
gdk_pixbuf_animation_get_static_image (GdkPixbufAnimation *animation)
 
345
{
 
346
        g_return_val_if_fail (GDK_IS_PIXBUF_ANIMATION (animation), NULL);
 
347
        
 
348
        return GDK_PIXBUF_ANIMATION_GET_CLASS (animation)->get_static_image (animation);
 
349
}
 
350
 
 
351
/**
 
352
 * gdk_pixbuf_animation_get_width:
 
353
 * @animation: An animation.
 
354
 *
 
355
 * Queries the width of the bounding box of a pixbuf animation.
 
356
 * 
 
357
 * Return value: Width of the bounding box of the animation.
 
358
 **/
 
359
int
 
360
gdk_pixbuf_animation_get_width (GdkPixbufAnimation *animation)
 
361
{
 
362
        int width;
 
363
        
 
364
        g_return_val_if_fail (GDK_IS_PIXBUF_ANIMATION (animation), 0);
 
365
 
 
366
        width = 0;
 
367
        GDK_PIXBUF_ANIMATION_GET_CLASS (animation)->get_size (animation,
 
368
                                                              &width, NULL);
 
369
        
 
370
 
 
371
        return width;
 
372
}
 
373
 
 
374
/**
 
375
 * gdk_pixbuf_animation_get_height:
 
376
 * @animation: An animation.
 
377
 *
 
378
 * Queries the height of the bounding box of a pixbuf animation.
 
379
 * 
 
380
 * Return value: Height of the bounding box of the animation.
 
381
 **/
 
382
int
 
383
gdk_pixbuf_animation_get_height (GdkPixbufAnimation *animation)
 
384
{
 
385
        int height;
 
386
        
 
387
        g_return_val_if_fail (GDK_IS_PIXBUF_ANIMATION (animation), 0);
 
388
 
 
389
        height = 0;
 
390
        GDK_PIXBUF_ANIMATION_GET_CLASS (animation)->get_size (animation,
 
391
                                                              NULL, &height);
 
392
        
 
393
 
 
394
        return height;
 
395
}
 
396
 
 
397
 
 
398
/**
 
399
 * gdk_pixbuf_animation_get_iter:
 
400
 * @animation: a #GdkPixbufAnimation
 
401
 * @start_time: time when the animation starts playing
 
402
 * 
 
403
 * Get an iterator for displaying an animation. The iterator provides
 
404
 * the frames that should be displayed at a given time.
 
405
 * It should be freed after use with g_object_unref().
 
406
 * 
 
407
 * @start_time would normally come from g_get_current_time(), and
 
408
 * marks the beginning of animation playback. After creating an
 
409
 * iterator, you should immediately display the pixbuf returned by
 
410
 * gdk_pixbuf_animation_iter_get_pixbuf(). Then, you should install a
 
411
 * timeout (with g_timeout_add()) or by some other mechanism ensure
 
412
 * that you'll update the image after
 
413
 * gdk_pixbuf_animation_iter_get_delay_time() milliseconds. Each time
 
414
 * the image is updated, you should reinstall the timeout with the new,
 
415
 * possibly-changed delay time.
 
416
 *
 
417
 * As a shortcut, if @start_time is %NULL, the result of
 
418
 * g_get_current_time() will be used automatically.
 
419
 *
 
420
 * To update the image (i.e. possibly change the result of
 
421
 * gdk_pixbuf_animation_iter_get_pixbuf() to a new frame of the animation),
 
422
 * call gdk_pixbuf_animation_iter_advance().
 
423
 *
 
424
 * If you're using #GdkPixbufLoader, in addition to updating the image
 
425
 * after the delay time, you should also update it whenever you
 
426
 * receive the area_updated signal and
 
427
 * gdk_pixbuf_animation_iter_on_currently_loading_frame() returns
 
428
 * %TRUE. In this case, the frame currently being fed into the loader
 
429
 * has received new data, so needs to be refreshed. The delay time for
 
430
 * a frame may also be modified after an area_updated signal, for
 
431
 * example if the delay time for a frame is encoded in the data after
 
432
 * the frame itself. So your timeout should be reinstalled after any
 
433
 * area_updated signal.
 
434
 *
 
435
 * A delay time of -1 is possible, indicating "infinite."
 
436
 * 
 
437
 * Return value: an iterator to move over the animation
 
438
 **/
 
439
GdkPixbufAnimationIter*
 
440
gdk_pixbuf_animation_get_iter (GdkPixbufAnimation *animation,
 
441
                               const GTimeVal     *start_time)
 
442
{
 
443
        GTimeVal val;
 
444
        
 
445
        g_return_val_if_fail (GDK_IS_PIXBUF_ANIMATION (animation), NULL);
 
446
 
 
447
 
 
448
        if (start_time)
 
449
                val = *start_time;
 
450
        else
 
451
                g_get_current_time (&val);
 
452
        
 
453
        return GDK_PIXBUF_ANIMATION_GET_CLASS (animation)->get_iter (animation, &val);
 
454
}
 
455
 
 
456
 
 
457
 
 
458
GType
 
459
gdk_pixbuf_animation_iter_get_type (void)
 
460
{
 
461
        static GType object_type = 0;
 
462
 
 
463
        if (!object_type) {
 
464
                static const GTypeInfo object_info = {
 
465
                        sizeof (GdkPixbufAnimationIterClass),
 
466
                        (GBaseInitFunc) NULL,
 
467
                        (GBaseFinalizeFunc) NULL,
 
468
                        (GClassInitFunc) NULL,
 
469
                        NULL,           /* class_finalize */
 
470
                        NULL,           /* class_data */
 
471
                        sizeof (GdkPixbufAnimationIter),
 
472
                        0,              /* n_preallocs */
 
473
                        (GInstanceInitFunc) NULL,
 
474
                };
 
475
                
 
476
                object_type = g_type_register_static (G_TYPE_OBJECT,
 
477
                                                      "GdkPixbufAnimationIter",
 
478
                                                      &object_info, 0);
 
479
        }
 
480
  
 
481
        return object_type;
 
482
}
 
483
 
 
484
/**
 
485
 * gdk_pixbuf_animation_iter_get_delay_time:
 
486
 * @iter: an animation iterator
 
487
 * 
 
488
 * Gets the number of milliseconds the current pixbuf should be displayed,
 
489
 * or -1 if the current pixbuf should be displayed forever. g_timeout_add()
 
490
 * conveniently takes a timeout in milliseconds, so you can use a timeout
 
491
 * to schedule the next update.
 
492
 *
 
493
 * Return value: delay time in milliseconds (thousandths of a second)
 
494
 **/
 
495
int
 
496
gdk_pixbuf_animation_iter_get_delay_time (GdkPixbufAnimationIter *iter)
 
497
{
 
498
        g_return_val_if_fail (GDK_IS_PIXBUF_ANIMATION_ITER (iter), -1);
 
499
  
 
500
        return GDK_PIXBUF_ANIMATION_ITER_GET_CLASS (iter)->get_delay_time (iter);
 
501
}
 
502
 
 
503
/**
 
504
 * gdk_pixbuf_animation_iter_get_pixbuf:
 
505
 * @iter: an animation iterator
 
506
 * 
 
507
 * Gets the current pixbuf which should be displayed; the pixbuf will
 
508
 * be the same size as the animation itself
 
509
 * (gdk_pixbuf_animation_get_width(), gdk_pixbuf_animation_get_height()). 
 
510
 * This pixbuf should be displayed for 
 
511
 * gdk_pixbuf_animation_iter_get_delay_time() milliseconds.  The caller
 
512
 * of this function does not own a reference to the returned pixbuf;
 
513
 * the returned pixbuf will become invalid when the iterator advances
 
514
 * to the next frame, which may happen anytime you call
 
515
 * gdk_pixbuf_animation_iter_advance(). Copy the pixbuf to keep it
 
516
 * (don't just add a reference), as it may get recycled as you advance
 
517
 * the iterator.
 
518
 *
 
519
 * Return value: the pixbuf to be displayed
 
520
 **/
 
521
GdkPixbuf*
 
522
gdk_pixbuf_animation_iter_get_pixbuf (GdkPixbufAnimationIter *iter)
 
523
{
 
524
        g_return_val_if_fail (GDK_IS_PIXBUF_ANIMATION_ITER (iter), NULL);
 
525
  
 
526
        return GDK_PIXBUF_ANIMATION_ITER_GET_CLASS (iter)->get_pixbuf (iter);
 
527
}
 
528
 
 
529
/**
 
530
 * gdk_pixbuf_animation_iter_on_currently_loading_frame:
 
531
 * @iter: a #GdkPixbufAnimationIter
 
532
 *
 
533
 * Used to determine how to respond to the area_updated signal on
 
534
 * #GdkPixbufLoader when loading an animation. area_updated is emitted
 
535
 * for an area of the frame currently streaming in to the loader. So if
 
536
 * you're on the currently loading frame, you need to redraw the screen for
 
537
 * the updated area.
 
538
 * 
 
539
 * Return value: %TRUE if the frame we're on is partially loaded, or the last frame
 
540
 **/
 
541
gboolean
 
542
gdk_pixbuf_animation_iter_on_currently_loading_frame (GdkPixbufAnimationIter *iter)
 
543
{
 
544
        g_return_val_if_fail (GDK_IS_PIXBUF_ANIMATION_ITER (iter), FALSE);
 
545
        
 
546
        return GDK_PIXBUF_ANIMATION_ITER_GET_CLASS (iter)->on_currently_loading_frame (iter);
 
547
}
 
548
 
 
549
/**
 
550
 * gdk_pixbuf_animation_iter_advance:
 
551
 * @iter: a #GdkPixbufAnimationIter
 
552
 * @current_time: current time
 
553
 *
 
554
 * Possibly advances an animation to a new frame. Chooses the frame based
 
555
 * on the start time passed to gdk_pixbuf_animation_get_iter().
 
556
 * 
 
557
 * @current_time would normally come from g_get_current_time(), and
 
558
 * must be greater than or equal to the time passed to
 
559
 * gdk_pixbuf_animation_get_iter(), and must increase or remain
 
560
 * unchanged each time gdk_pixbuf_animation_iter_get_pixbuf() is
 
561
 * called. That is, you can't go backward in time; animations only
 
562
 * play forward.
 
563
 *
 
564
 * As a shortcut, pass %NULL for the current time and g_get_current_time()
 
565
 * will be invoked on your behalf. So you only need to explicitly pass
 
566
 * @current_time if you're doing something odd like playing the animation
 
567
 * at double speed.
 
568
 *
 
569
 * If this function returns %FALSE, there's no need to update the animation
 
570
 * display, assuming the display had been rendered prior to advancing;
 
571
 * if %TRUE, you need to call gdk_animation_iter_get_pixbuf() and update the
 
572
 * display with the new pixbuf.
 
573
 *
 
574
 * Returns: %TRUE if the image may need updating
 
575
 * 
 
576
 **/
 
577
gboolean
 
578
gdk_pixbuf_animation_iter_advance (GdkPixbufAnimationIter *iter,
 
579
                                   const GTimeVal         *current_time)
 
580
{
 
581
        GTimeVal val;
 
582
        
 
583
        g_return_val_if_fail (GDK_IS_PIXBUF_ANIMATION_ITER (iter), FALSE);
 
584
 
 
585
        if (current_time)
 
586
                val = *current_time;
 
587
        else
 
588
                g_get_current_time (&val);
 
589
        
 
590
        return GDK_PIXBUF_ANIMATION_ITER_GET_CLASS (iter)->advance (iter, &val);
 
591
}
 
592
 
 
593
 
 
594
 
 
595
static void gdk_pixbuf_non_anim_class_init (GdkPixbufNonAnimClass *klass);
 
596
static void gdk_pixbuf_non_anim_finalize   (GObject        *object);
 
597
 
 
598
static gboolean                gdk_pixbuf_non_anim_is_static_image  (GdkPixbufAnimation *animation);
 
599
static GdkPixbuf*              gdk_pixbuf_non_anim_get_static_image (GdkPixbufAnimation *animation);
 
600
static void                    gdk_pixbuf_non_anim_get_size         (GdkPixbufAnimation *anim,
 
601
                                                                     int                *width,
 
602
                                                                     int                *height);
 
603
static GdkPixbufAnimationIter* gdk_pixbuf_non_anim_get_iter         (GdkPixbufAnimation *anim,
 
604
                                                                     const GTimeVal     *start_time);
 
605
 
 
606
 
 
607
 
 
608
 
 
609
 
 
610
static gpointer non_parent_class;
 
611
 
 
612
static GType
 
613
gdk_pixbuf_non_anim_get_type (void)
 
614
{
 
615
        static GType object_type = 0;
 
616
 
 
617
        if (!object_type) {
 
618
                static const GTypeInfo object_info = {
 
619
                        sizeof (GdkPixbufNonAnimClass),
 
620
                        (GBaseInitFunc) NULL,
 
621
                        (GBaseFinalizeFunc) NULL,
 
622
                        (GClassInitFunc) gdk_pixbuf_non_anim_class_init,
 
623
                        NULL,           /* class_finalize */
 
624
                        NULL,           /* class_data */
 
625
                        sizeof (GdkPixbufNonAnim),
 
626
                        0,              /* n_preallocs */
 
627
                        (GInstanceInitFunc) NULL,
 
628
                };
 
629
                
 
630
                object_type = g_type_register_static (GDK_TYPE_PIXBUF_ANIMATION,
 
631
                                                      "GdkPixbufNonAnim",
 
632
                                                      &object_info, 0);
 
633
        }
 
634
        
 
635
        return object_type;
 
636
}
 
637
 
 
638
static void
 
639
gdk_pixbuf_non_anim_class_init (GdkPixbufNonAnimClass *klass)
 
640
{
 
641
        GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
642
        GdkPixbufAnimationClass *anim_class = GDK_PIXBUF_ANIMATION_CLASS (klass);
 
643
        
 
644
        non_parent_class = g_type_class_peek_parent (klass);
 
645
        
 
646
        object_class->finalize = gdk_pixbuf_non_anim_finalize;
 
647
 
 
648
        anim_class->is_static_image = gdk_pixbuf_non_anim_is_static_image;
 
649
        anim_class->get_static_image = gdk_pixbuf_non_anim_get_static_image;
 
650
        anim_class->get_size = gdk_pixbuf_non_anim_get_size;
 
651
        anim_class->get_iter = gdk_pixbuf_non_anim_get_iter;
 
652
}
 
653
 
 
654
static void
 
655
gdk_pixbuf_non_anim_finalize (GObject *object)
 
656
{
 
657
        GdkPixbufNonAnim *non_anim = GDK_PIXBUF_NON_ANIM (object);
 
658
 
 
659
        if (non_anim->pixbuf)
 
660
                g_object_unref (non_anim->pixbuf);
 
661
        
 
662
        G_OBJECT_CLASS (non_parent_class)->finalize (object);
 
663
}
 
664
 
 
665
GdkPixbufAnimation*
 
666
gdk_pixbuf_non_anim_new (GdkPixbuf *pixbuf)
 
667
{
 
668
        GdkPixbufNonAnim *non_anim;
 
669
 
 
670
        non_anim = g_object_new (GDK_TYPE_PIXBUF_NON_ANIM, NULL);
 
671
 
 
672
        non_anim->pixbuf = pixbuf;
 
673
 
 
674
        if (pixbuf)
 
675
                g_object_ref (pixbuf);
 
676
 
 
677
        return GDK_PIXBUF_ANIMATION (non_anim);
 
678
}
 
679
 
 
680
static gboolean
 
681
gdk_pixbuf_non_anim_is_static_image  (GdkPixbufAnimation *animation)
 
682
{
 
683
 
 
684
        return TRUE;
 
685
}
 
686
 
 
687
static GdkPixbuf*
 
688
gdk_pixbuf_non_anim_get_static_image (GdkPixbufAnimation *animation)
 
689
{
 
690
        GdkPixbufNonAnim *non_anim;
 
691
 
 
692
        non_anim = GDK_PIXBUF_NON_ANIM (animation);
 
693
 
 
694
        return non_anim->pixbuf;
 
695
}
 
696
 
 
697
static void
 
698
gdk_pixbuf_non_anim_get_size (GdkPixbufAnimation *anim,
 
699
                              int                *width,
 
700
                              int                *height)
 
701
{
 
702
        GdkPixbufNonAnim *non_anim;
 
703
 
 
704
        non_anim = GDK_PIXBUF_NON_ANIM (anim);
 
705
 
 
706
        if (width)
 
707
                *width = gdk_pixbuf_get_width (non_anim->pixbuf);
 
708
 
 
709
        if (height)
 
710
                *height = gdk_pixbuf_get_height (non_anim->pixbuf);
 
711
}
 
712
 
 
713
 
 
714
static GdkPixbufAnimationIter*
 
715
gdk_pixbuf_non_anim_get_iter (GdkPixbufAnimation *anim,
 
716
                              const GTimeVal     *start_time)
 
717
{
 
718
        GdkPixbufNonAnimIter *iter;
 
719
 
 
720
        iter = g_object_new (GDK_TYPE_PIXBUF_NON_ANIM_ITER, NULL);
 
721
 
 
722
        iter->non_anim = GDK_PIXBUF_NON_ANIM (anim);
 
723
 
 
724
        g_object_ref (iter->non_anim);
 
725
        
 
726
        return GDK_PIXBUF_ANIMATION_ITER (iter);
 
727
}
 
728
 
 
729
 
 
730
 
 
731
static void gdk_pixbuf_non_anim_iter_class_init (GdkPixbufNonAnimIterClass *klass);
 
732
static void gdk_pixbuf_non_anim_iter_finalize   (GObject                   *object);
 
733
static int        gdk_pixbuf_non_anim_iter_get_delay_time             (GdkPixbufAnimationIter *iter);
 
734
static GdkPixbuf* gdk_pixbuf_non_anim_iter_get_pixbuf                 (GdkPixbufAnimationIter *iter);
 
735
static gboolean   gdk_pixbuf_non_anim_iter_on_currently_loading_frame (GdkPixbufAnimationIter *iter);
 
736
static gboolean   gdk_pixbuf_non_anim_iter_advance                    (GdkPixbufAnimationIter *iter,
 
737
                                                                       const GTimeVal         *current_time);
 
738
 
 
739
 
 
740
 
 
741
 
 
742
 
 
743
static gpointer non_iter_parent_class;
 
744
 
 
745
GType
 
746
gdk_pixbuf_non_anim_iter_get_type (void)
 
747
{
 
748
        static GType object_type = 0;
 
749
 
 
750
        if (!object_type) {
 
751
                static const GTypeInfo object_info = {
 
752
                        sizeof (GdkPixbufNonAnimIterClass),
 
753
                        (GBaseInitFunc) NULL,
 
754
                        (GBaseFinalizeFunc) NULL,
 
755
                        (GClassInitFunc) gdk_pixbuf_non_anim_iter_class_init,
 
756
                        NULL,           /* class_finalize */
 
757
                        NULL,           /* class_data */
 
758
                        sizeof (GdkPixbufNonAnimIter),
 
759
                        0,              /* n_preallocs */
 
760
                        (GInstanceInitFunc) NULL,
 
761
                };
 
762
                
 
763
                object_type = g_type_register_static (GDK_TYPE_PIXBUF_ANIMATION_ITER,
 
764
                                                      "GdkPixbufNonAnimIter",
 
765
                                                      &object_info, 0);
 
766
        }
 
767
        
 
768
        return object_type;
 
769
}
 
770
 
 
771
static void
 
772
gdk_pixbuf_non_anim_iter_class_init (GdkPixbufNonAnimIterClass *klass)
 
773
{
 
774
        GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
775
        GdkPixbufAnimationIterClass *anim_iter_class =
 
776
                GDK_PIXBUF_ANIMATION_ITER_CLASS (klass);
 
777
        
 
778
        non_iter_parent_class = g_type_class_peek_parent (klass);
 
779
        
 
780
        object_class->finalize = gdk_pixbuf_non_anim_iter_finalize;
 
781
 
 
782
        anim_iter_class->get_delay_time = gdk_pixbuf_non_anim_iter_get_delay_time;
 
783
        anim_iter_class->get_pixbuf = gdk_pixbuf_non_anim_iter_get_pixbuf;
 
784
        anim_iter_class->on_currently_loading_frame = gdk_pixbuf_non_anim_iter_on_currently_loading_frame;
 
785
        anim_iter_class->advance = gdk_pixbuf_non_anim_iter_advance;
 
786
}
 
787
 
 
788
static void
 
789
gdk_pixbuf_non_anim_iter_finalize (GObject *object)
 
790
{
 
791
        GdkPixbufNonAnimIter *iter = GDK_PIXBUF_NON_ANIM_ITER (object);
 
792
 
 
793
        g_object_unref (iter->non_anim);
 
794
        
 
795
        G_OBJECT_CLASS (non_iter_parent_class)->finalize (object);
 
796
}
 
797
 
 
798
static int
 
799
gdk_pixbuf_non_anim_iter_get_delay_time (GdkPixbufAnimationIter *iter)
 
800
{
 
801
        return -1; /* show only frame forever */
 
802
}
 
803
 
 
804
static GdkPixbuf*
 
805
gdk_pixbuf_non_anim_iter_get_pixbuf (GdkPixbufAnimationIter *iter)
 
806
{
 
807
        return GDK_PIXBUF_NON_ANIM_ITER (iter)->non_anim->pixbuf;
 
808
}
 
809
 
 
810
 
 
811
static gboolean
 
812
gdk_pixbuf_non_anim_iter_on_currently_loading_frame (GdkPixbufAnimationIter *iter)
 
813
{
 
814
        return TRUE;
 
815
}
 
816
        
 
817
static gboolean
 
818
gdk_pixbuf_non_anim_iter_advance (GdkPixbufAnimationIter *iter,
 
819
                                  const GTimeVal         *current_time)
 
820
{
 
821
 
 
822
        /* Advancing never requires a refresh */
 
823
        return FALSE;
 
824
}
 
825
 
 
826
#define __GDK_PIXBUF_ANIMATION_C__
 
827
#include "gdk-pixbuf-aliasdef.c"