]> Pileus Git - ~andy/gtk/blob - gdk-pixbuf/gdk-pixbuf-animation.c
b2fbbb8f4027cd70f8f04744d4a4d92e20c3faac
[~andy/gtk] / gdk-pixbuf / gdk-pixbuf-animation.c
1 /* GdkPixbuf library - Simple animation support
2  *
3  * Copyright (C) 1999 The Free Software Foundation
4  *
5  * Authors: Jonathan Blandford <jrb@redhat.com>
6  *          Havoc Pennington <hp@redhat.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library 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  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 #include <config.h>
25 #include "gdk-pixbuf-io.h"
26 #include "gdk-pixbuf-private.h"
27
28 \f
29
30 /**
31  * gdk_pixbuf_animation_new_from_file:
32  * @filename: Name of file to load.
33  *
34  * Creates a new animation by loading it from a file.  The file format is
35  * detected automatically.  If the file's format does not support multi-frame
36  * images, then an animation with a single frame will be created.
37  *
38  * Return value: A newly created animation with a reference count of 1, or NULL
39  * if any of several error conditions ocurred:  the file could not be opened,
40  * there was no loader for the file's format, there was not enough memory to
41  * allocate the image buffer, or the image file contained invalid data.
42  **/
43 GdkPixbufAnimation *
44 gdk_pixbuf_animation_new_from_file (const char *filename)
45 {
46         GdkPixbufAnimation *animation;
47         int size;
48         FILE *f;
49         guchar buffer [128];
50         GdkPixbufModule *image_module;
51
52         g_return_val_if_fail (filename != NULL, NULL);
53
54         f = fopen (filename, "r");
55         if (!f)
56                 return NULL;
57
58         size = fread (&buffer, 1, sizeof (buffer), f);
59
60         if (size == 0) {
61                 fclose (f);
62                 return NULL;
63         }
64
65         image_module = gdk_pixbuf_get_module (buffer, size);
66         if (!image_module) {
67                 g_warning ("Unable to find handler for file: %s", filename);
68                 fclose (f);
69                 return NULL;
70         }
71
72         if (image_module->module == NULL)
73                 gdk_pixbuf_load_module (image_module);
74
75         if (image_module->load_animation == NULL) {
76                 GdkPixbuf *pixbuf;
77                 GdkPixbufFrame *frame;
78
79                 /* Keep this logic in sync with gdk_pixbuf_new_from_file() */
80
81                 if (image_module->load == NULL) {
82                         fclose (f);
83                         return NULL;
84                 }
85
86                 fseek (f, 0, SEEK_SET);
87                 pixbuf = (* image_module->load) (f);
88                 fclose (f);
89
90                 if (pixbuf)
91                         g_assert (pixbuf->ref_count > 0);
92                 else
93                         return NULL;
94
95                 frame = g_new (GdkPixbufFrame, 1);
96                 frame->pixbuf = pixbuf;
97                 frame->x_offset = 0;
98                 frame->y_offset = 0;
99                 frame->delay_time = -1;
100                 frame->action = GDK_PIXBUF_FRAME_RETAIN;
101
102                 animation = g_new0 (GdkPixbufAnimation, 1);
103                 animation->ref_count = 1;
104                 animation->n_frames = 1;
105                 animation->frames = g_list_prepend (NULL, frame);
106                 animation->width = gdk_pixbuf_get_width (pixbuf);
107                 animation->height = gdk_pixbuf_get_height (pixbuf);
108         } else {
109                 fseek (f, 0, SEEK_SET);
110                 animation = (* image_module->load_animation) (f);
111                 fclose (f);
112         }
113
114         return animation;
115 }
116
117 /**
118  * gdk_pixbuf_animation_ref:
119  * @animation: An animation.
120  *
121  * Adds a reference to an animation.  It must be released afterwards using
122  * gdk_pixbuf_animation_unref().
123  *
124  * Return value: The same as the @animation argument.
125  **/
126 GdkPixbufAnimation *
127 gdk_pixbuf_animation_ref (GdkPixbufAnimation *animation)
128 {
129         g_return_val_if_fail (animation != NULL, NULL);
130         g_return_val_if_fail (animation->ref_count > 0, NULL);
131
132         animation->ref_count++;
133         return animation;
134 }
135
136 /**
137  * gdk_pixbuf_animation_unref:
138  * @animation: An animation.
139  * 
140  * Removes a reference from an animation.  It will be destroyed when the
141  * reference count drops to zero.  At that point, all the frames in the
142  * animation will be freed and their corresponding pixbufs will be unreferenced.
143  **/
144 void
145 gdk_pixbuf_animation_unref (GdkPixbufAnimation *animation)
146 {
147         g_return_if_fail (animation != NULL);
148         g_return_if_fail (animation->ref_count > 0);
149
150         animation->ref_count--;
151
152         if (animation->ref_count == 0) {
153                 GList *l;
154                 GdkPixbufFrame *frame;
155
156                 for (l = animation->frames; l; l = l->next) {
157                         frame = l->data;
158                         gdk_pixbuf_unref (frame->pixbuf);
159                         g_free (frame);
160                 }
161
162                 g_list_free (animation->frames);
163                 g_free (animation);
164         }
165 }
166
167 /**
168  * gdk_pixbuf_animation_get_width:
169  * @animation: An animation.
170  * 
171  * Return the width of @animation.
172  **/
173 int
174 gdk_pixbuf_animation_get_width (GdkPixbufAnimation *animation)
175 {
176         g_return_val_if_fail (animation != NULL, 0);
177         g_return_val_if_fail (animation->ref_count > 0, 0);
178
179         return animation->width;
180 }
181
182 /**
183  * gdk_pixbuf_animation_get_height:
184  * @animation: An animation.
185  * 
186  * Return the height of @animation.
187  **/
188 int
189 gdk_pixbuf_animation_get_height (GdkPixbufAnimation *animation)
190 {
191         g_return_val_if_fail (animation != NULL, 0);
192         g_return_val_if_fail (animation->ref_count > 0, 0);
193
194         return animation->height;
195 }
196
197 /**
198  * gdk_pixbuf_animation_get_num_frames:
199  * @animation: An animation.
200  * 
201  * Return the number of frames in @animation.
202  **/
203 int
204 gdk_pixbuf_animation_get_num_frames (GdkPixbufAnimation *animation)
205 {
206         g_return_val_if_fail (animation != NULL, 0);
207         g_return_val_if_fail (animation->ref_count > 0, 0);
208
209         return animation->n_frames;
210 }
211
212 /**
213  * gdk_pixbuf_animation_get_frames:
214  * @animation: An animation.
215  * 
216  * Return the frames of @animation as a list of
217  * GdkPixbufAnimationFrame objects.
218  **/
219 GList *
220 gdk_pixbuf_animation_get_frames (GdkPixbufAnimation *animation)
221 {
222         g_return_val_if_fail (animation != NULL, 0);
223         g_return_val_if_fail (animation->ref_count > 0, 0);
224
225         return animation->frames;
226 }
227
228 \f
229
230 /**
231  * gdk_pixbuf_frame_get_pixbuf:
232  * @frame: A pixbuf animation frame.
233  * 
234  * Queries the pixbuf of an animation frame.
235  * 
236  * Return value: A pixbuf.
237  **/
238 GdkPixbuf *
239 gdk_pixbuf_frame_get_pixbuf (GdkPixbufFrame *frame)
240 {
241         g_return_val_if_fail (frame != NULL, NULL);
242
243         return frame->pixbuf;
244 }
245
246 /**
247  * gdk_pixbuf_frame_get_x_offset:
248  * @frame: A pixbuf animation frame.
249  * 
250  * Queries the X offset of an animation frame.
251  * 
252  * Return value: X offset from the top left corner of the animation.
253  **/
254 int
255 gdk_pixbuf_frame_get_x_offset (GdkPixbufFrame *frame)
256 {
257         g_return_val_if_fail (frame != NULL, -1);
258
259         return frame->x_offset;
260 }
261
262 /**
263  * gdk_pixbuf_frame_get_y_offset:
264  * @frame: A pixbuf animation frame.
265  * 
266  * Queries the Y offset of an animation frame.
267  * 
268  * Return value: Y offset from the top left corner of the animation.
269  **/
270 int
271 gdk_pixbuf_frame_get_y_offset (GdkPixbufFrame *frame)
272 {
273         g_return_val_if_fail (frame != NULL, -1);
274
275         return frame->y_offset;
276 }
277
278 /**
279  * gdk_pixbuf_frame_get_delay_time:
280  * @frame: A pixbuf animation frame.
281  * 
282  * Queries the delay time in milliseconds of an animation frame.
283  * 
284  * Return value: Delay time in milliseconds.
285  **/
286 int
287 gdk_pixbuf_frame_get_delay_time (GdkPixbufFrame *frame)
288 {
289         g_return_val_if_fail (frame != NULL, -1);
290
291         return frame->delay_time;
292 }
293
294 /**
295  * gdk_pixbuf_frame_get_action:
296  * @frame: A pixbuf animation frame.
297  * 
298  * Queries the overlay action of an animation frame.
299  * 
300  * Return value: Overlay action for this frame.
301  **/
302 GdkPixbufFrameAction
303 gdk_pixbuf_frame_get_action (GdkPixbufFrame *frame)
304 {
305         g_return_val_if_fail (frame != NULL, GDK_PIXBUF_FRAME_RETAIN);
306
307         return frame->action;
308 }