diff options
-rw-r--r-- | tests/Makefile.am | 1 | ||||
-rw-r--r-- | tests/aero.gif | bin | 0 -> 35480 bytes | |||
-rw-r--r-- | tests/pixbuf-area-updated.c | 130 |
3 files changed, 131 insertions, 0 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am index dcec2df1b..c03f3bba2 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -66,6 +66,7 @@ dist_installed_test_data = \ test-image.pixdata \ test-image-rle.pixdata \ bug775693.pixdata \ + aero.gif \ $(wildcard $(srcdir)/test-images/fail/*) \ $(wildcard $(srcdir)/test-images/randomly-modified/*) \ $(wildcard $(srcdir)/test-images/reftests/*.*) \ diff --git a/tests/aero.gif b/tests/aero.gif Binary files differnew file mode 100644 index 000000000..e8d941623 --- /dev/null +++ b/tests/aero.gif diff --git a/tests/pixbuf-area-updated.c b/tests/pixbuf-area-updated.c index 9c4f0e8dc..5cd308e33 100644 --- a/tests/pixbuf-area-updated.c +++ b/tests/pixbuf-area-updated.c @@ -23,6 +23,20 @@ #include <stdio.h> #include <gdk-pixbuf/gdk-pixbuf.h> +/* maximum number of frames in animation(before repeating) */ +#define MAX_NUMBER_FRAMES 1000 + +/* Information about currently loading frame of animation. + * + * pixbuf == NULL means that animation is fully loaded + * (no currently loading frames exist). + */ +typedef struct { + GdkPixbufAnimationIter* iter; /* iterator pointed to the frame */ + GTimeVal time; /* time when this frame appears */ + GdkPixbuf *pixbuf; /* current content of the frame */ +} FrameData; + /* Auxiliary function, returns numeric representation of pixel. * For RGB format it is rrggbb(in hex), for RGBA - rrggbbaa. */ static guint32 @@ -193,11 +207,127 @@ test_area_updated_ico (gconstpointer data) g_object_unref (loader); } +/* Auxiliary function - look for frame that's currently loading. */ +static void +update_currently_loaded_frame (FrameData* frame) +{ + int tmp_count; + + if (gdk_pixbuf_animation_iter_on_currently_loading_frame(frame->iter)) + return; /* frame is currently being loaded */ + /* clear old content of pixbuf */ + if (frame->pixbuf) + g_object_unref (frame->pixbuf); + frame->pixbuf = NULL; + + tmp_count = 0; + do { + int delay_time; + + if (++tmp_count > MAX_NUMBER_FRAMES) { + /* protection against frames repeating */ + return; + } + + delay_time = gdk_pixbuf_animation_iter_get_delay_time (frame->iter); + if (delay_time < 0) { + /* this is last frame in the animation */ + return; + } + g_time_val_add (&frame->time, delay_time * 1000); + gdk_pixbuf_animation_iter_advance (frame->iter, &frame->time); + } while (!gdk_pixbuf_animation_iter_on_currently_loading_frame (frame->iter)); + /* store current content of the frame */ + frame->pixbuf = gdk_pixbuf_copy (gdk_pixbuf_animation_iter_get_pixbuf (frame->iter)); +} + +static void +callback_area_updated_anim (GdkPixbufLoader *loader, + int x, + int y, + int width, + int height, + FrameData *frame_old) +{ + GdkPixbuf *pixbuf_new; + + /* "area-updated" signal was emitted after animation had fully loaded. */ + g_assert_nonnull (frame_old->pixbuf); + + pixbuf_new = gdk_pixbuf_animation_iter_get_pixbuf (frame_old->iter); + pixbuf_not_changed_outside_area (pixbuf_new, frame_old->pixbuf, x, y, width, height); + gdk_pixbuf_copy_area (pixbuf_new, x, y, width, height, frame_old->pixbuf, x, y); + update_currently_loaded_frame (frame_old); +} + +/* free resources used in callback_area_updated_anim */ +static void +callback_closed_anim(GdkPixbufLoader *loader, FrameData *frame_copy) +{ + g_object_unref (frame_copy->iter); + if(frame_copy->pixbuf != NULL) + g_object_unref (frame_copy->pixbuf); + g_free (frame_copy); +} +/* prepare frame information and register other callbacks */ +static void +callback_area_prepared_anim (GdkPixbufLoader* loader) +{ + GdkPixbufAnimation *anim; + FrameData* frame_copy = g_new (FrameData, 1); + + g_signal_connect (loader, "area-updated", + (GCallback) callback_area_updated_anim, (gpointer) frame_copy); + g_signal_connect (loader, "closed", + (GCallback) callback_closed_anim, (gpointer) frame_copy); + + frame_copy->time.tv_sec = frame_copy->time.tv_usec = 0; /* some time */ + + anim = gdk_pixbuf_loader_get_animation (loader); + frame_copy->iter = gdk_pixbuf_animation_get_iter (anim, &frame_copy->time); + frame_copy->pixbuf = gdk_pixbuf_copy (gdk_pixbuf_animation_iter_get_pixbuf (frame_copy->iter)); + update_currently_loaded_frame (frame_copy); +} + +static void +test_area_updated_anim (gconstpointer data) +{ + const char *filename; + GIOChannel *channel; + GdkPixbufLoader *loader; + + filename = g_test_get_filename (G_TEST_DIST, data, NULL); + + channel = g_io_channel_new_file (filename, "r", NULL); + g_assert_nonnull (channel); + g_io_channel_set_encoding(channel, NULL, NULL); + /*create loader */ + loader = gdk_pixbuf_loader_new (); + g_assert_nonnull (loader); + + g_signal_connect (loader, "area-prepared", + (GCallback) callback_area_prepared_anim, NULL); + /* other callbacks will be registered inside callback_area_prepared_anim */ + + /*read animation by portions of bytes */ +#if 0 + while(loader_write_from_channel(loader, channel, 20) == 20); +#endif + /* or read it at once */ + loader_write_from_channel (loader, channel, G_MAXSIZE); + + /* free resources */ + g_io_channel_unref (channel); + gdk_pixbuf_loader_close (loader, NULL); + g_object_unref (loader); +} + int main(int argc, char **argv) { g_test_init (&argc, &argv, NULL); g_test_add_data_func ("/pixbuf/area-updated/ico", (gconstpointer) "test-images/reftests/squares.ico", test_area_updated_ico); + g_test_add_data_func ("/pixbuf/area-updated/gif", (gconstpointer) "aero.gif", test_area_updated_anim); return g_test_run (); } |