1 /* $Id: fb_gdkpixbuf.c,v 1.21 2004/11/08 17:14:06 ukai Exp $ */
2 /**************************************************************************
3 fb_gdkpixbuf.c 0.3 Copyright (C) 2002, hito
4 **************************************************************************/
8 #include <glib-object.h>
11 #include <gdk-pixbuf/gdk-pixbuf.h>
15 static void draw(FB_IMAGE * img, int x, int y, int w, int h,
17 static GdkPixbuf *resize_image(GdkPixbuf * pixbuf, int width, int height);
21 get_animation_size(GdkPixbufAnimation * animation, int *w, int *h, int *delay)
23 GdkPixbufAnimationIter *iter;
27 g_get_current_time(&time);
28 iter = gdk_pixbuf_animation_get_iter(animation, &time);
29 *w = gdk_pixbuf_animation_get_width(animation);
30 *h = gdk_pixbuf_animation_get_height(animation);
32 gdk_pixbuf_animation_iter_on_currently_loading_frame(iter) != TRUE;
35 tmp = gdk_pixbuf_animation_iter_get_delay_time(iter);
36 g_time_val_add(&time, tmp * 1000);
39 gdk_pixbuf_animation_iter_advance(iter, &time);
44 g_object_unref(G_OBJECT(iter));
49 get_animation_size(GdkPixbufAnimation * animation, int *w, int *h, int *delay)
52 int iw, ih, n, i, d = -1;
54 frames = gdk_pixbuf_animation_get_frames(animation);
55 n = gdk_pixbuf_animation_get_num_frames(animation);
56 *w = gdk_pixbuf_animation_get_width(animation);
57 *h = gdk_pixbuf_animation_get_height(animation);
58 for (i = 0; i < n; i++) {
59 GdkPixbufFrame *frame;
63 frame = (GdkPixbufFrame *) g_list_nth_data(frames, i);
64 tmp = gdk_pixbuf_frame_get_delay_time(frame);
67 pixbuf = gdk_pixbuf_frame_get_pixbuf(frame);
68 iw = gdk_pixbuf_frame_get_x_offset(frame)
69 + gdk_pixbuf_get_width(pixbuf);
70 ih = gdk_pixbuf_frame_get_y_offset(frame)
71 + gdk_pixbuf_get_height(pixbuf);
92 get_image_size(char *filename, int *w, int *h)
94 GdkPixbufAnimation *animation;
98 animation = gdk_pixbuf_animation_new_from_file(filename, NULL);
100 animation = gdk_pixbuf_animation_new_from_file(filename);
102 if (animation == NULL)
104 get_animation_size(animation, w, h, NULL);
105 #if defined(USE_GTK2)
106 g_object_unref(G_OBJECT(animation));
108 gdk_pixbuf_animation_unref(animation);
114 fb_image_load(char *filename, int w, int h, int max_anim)
116 GdkPixbufAnimation *animation;
117 #if defined(USE_GTK2)
118 GdkPixbufAnimationIter *iter;
124 double ratio_w, ratio_h;
125 int n, j, fw, fh, frame_num, delay;
126 FB_IMAGE **fb_frame = NULL, *tmp_image = NULL;
128 if (filename == NULL)
130 #if defined(USE_GTK2)
131 animation = gdk_pixbuf_animation_new_from_file(filename, NULL);
133 animation = gdk_pixbuf_animation_new_from_file(filename);
135 if (animation == NULL)
137 frame_num = n = get_animation_size(animation, &fw, &fh, &delay);
141 frame_num = (-max_anim > n) ? n : -max_anim;
143 else if (max_anim > 0) {
144 frame_num = n = (max_anim > n) ? n : max_anim;
146 if (w < 1 || h < 1) {
149 ratio_w = ratio_h = 1;
152 ratio_w = 1.0 * w / fw;
153 ratio_h = 1.0 * h / fh;
156 fb_frame = fb_frame_new(w, h, frame_num);
157 if (fb_frame == NULL)
160 tmp_image = fb_image_new(w, h);
161 if (tmp_image == NULL) {
162 fb_frame_free(fb_frame);
167 if (bg_r != 0 || bg_g != 0 || bg_b != 0) {
168 fb_image_fill(tmp_image, bg_r, bg_g, bg_b);
171 #if defined(USE_GTK2)
172 g_get_current_time(&time);
173 iter = gdk_pixbuf_animation_get_iter(animation, &time);
175 if (max_anim < 0 && n > -max_anim) {
176 max_anim = n + max_anim;
177 for (j = 0; j < max_anim; j++) {
178 g_time_val_add(&time,
179 gdk_pixbuf_animation_iter_get_delay_time(iter) * 1000);
180 gdk_pixbuf_animation_iter_advance(iter, &time);
183 for (j = 0; j < n; j++) {
184 GdkPixbuf *org_pixbuf, *pixbuf;
186 org_pixbuf = gdk_pixbuf_animation_iter_get_pixbuf(iter);
187 pixbuf = resize_image(org_pixbuf, w, h);
189 fb_frame[j]->delay = gdk_pixbuf_animation_iter_get_delay_time(iter);
190 g_time_val_add(&time, fb_frame[j]->delay * 1000);
191 draw(fb_frame[j], 0, 0, w, h, pixbuf);
192 if (org_pixbuf != pixbuf)
193 g_object_unref(G_OBJECT(pixbuf));
194 gdk_pixbuf_animation_iter_advance(iter, &time);
197 frames = gdk_pixbuf_animation_get_frames(animation);
199 for (j = 0; j < n; j++) {
200 GdkPixbufFrame *frame;
201 GdkPixbuf *org_pixbuf, *pixbuf;
202 int width, height, ofstx, ofsty;
205 i = (j - n + frame_num > 0) ? (j - n + frame_num) : 0;
210 frame = (GdkPixbufFrame *) g_list_nth_data(frames, j);
211 org_pixbuf = gdk_pixbuf_frame_get_pixbuf(frame);
212 ofstx = gdk_pixbuf_frame_get_x_offset(frame);
213 ofsty = gdk_pixbuf_frame_get_y_offset(frame);
214 width = gdk_pixbuf_get_width(org_pixbuf);
215 height = gdk_pixbuf_get_height(org_pixbuf);
216 if (ofstx == 0 && ofsty == 0 && width == fw && height == fh) {
217 pixbuf = resize_image(org_pixbuf, w, h);
221 resize_image(org_pixbuf, width * ratio_w, height * ratio_h);
225 width = gdk_pixbuf_get_width(pixbuf);
226 height = gdk_pixbuf_get_height(pixbuf);
228 fb_frame[i]->delay = gdk_pixbuf_frame_get_delay_time(frame);
229 fb_image_copy(fb_frame[i], tmp_image);
230 draw(fb_frame[i], ofstx, ofsty, width, height, pixbuf);
232 switch (gdk_pixbuf_frame_get_action(frame)) {
233 case GDK_PIXBUF_FRAME_RETAIN:
234 fb_image_copy(tmp_image, fb_frame[i]);
236 case GDK_PIXBUF_FRAME_DISPOSE:
237 fb_image_fill(tmp_image, bg_r, bg_g, bg_b);
239 case GDK_PIXBUF_FRAME_REVERT:
240 fb_image_copy(tmp_image, fb_frame[0]);
243 fb_image_copy(tmp_image, fb_frame[0]);
246 if (org_pixbuf != pixbuf)
247 gdk_pixbuf_finalize(pixbuf);
252 fb_image_free(tmp_image);
253 #if defined(USE_GTK2)
254 g_object_unref(G_OBJECT(animation));
256 gdk_pixbuf_animation_unref(animation);
261 draw(FB_IMAGE * img, int x, int y, int w, int h, GdkPixbuf * pixbuf)
263 int i, j, r, g, b, offset, bpp, rowstride;
266 if (img == NULL || pixbuf == NULL)
268 rowstride = gdk_pixbuf_get_rowstride(pixbuf);
269 pixels = gdk_pixbuf_get_pixels(pixbuf);
270 alpha = gdk_pixbuf_get_has_alpha(pixbuf);
272 for (j = 0; j < h; j++) {
273 offset = j * rowstride;
274 for (i = 0; i < w; i++, offset += bpp) {
276 g = pixels[offset + 1];
277 b = pixels[offset + 2];
278 if (!alpha || pixels[offset + 3] != 0) {
279 fb_image_pset(img, i + x, j + y, r, g, b);
286 resize_image(GdkPixbuf * pixbuf, int width, int height)
288 GdkPixbuf *resized_pixbuf;
292 w = gdk_pixbuf_get_width(pixbuf);
293 h = gdk_pixbuf_get_height(pixbuf);
294 if (width < 1 || height < 1)
296 if (w == width && h == height)
299 gdk_pixbuf_scale_simple(pixbuf, width, height, GDK_INTERP_HYPER);
300 if (resized_pixbuf == NULL)
302 return resized_pixbuf;