summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tests/Makefile.am1
-rw-r--r--tests/aero.gifbin0 -> 35480 bytes
-rw-r--r--tests/pixbuf-area-updated.c130
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
new file mode 100644
index 000000000..e8d941623
--- /dev/null
+++ b/tests/aero.gif
Binary files differ
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 ();
}