[gdk-pixbuf] tests: Add test case for bug 581484



commit 25d31da79e590d73b86c868cd87cf71213aa11fd
Author: Bastien Nocera <hadess hadess net>
Date:   Thu Dec 29 16:55:26 2016 +0100

    tests: Add test case for bug 581484
    
    This time for the GIF animation.
    
    Adapted from Andrey Tsyvarev's original animation test program.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=581484

 tests/Makefile.am           |    1 +
 tests/aero.gif              |  Bin 0 -> 35480 bytes
 tests/pixbuf-area-updated.c |  130 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 131 insertions(+), 0 deletions(-)
---
diff --git a/tests/Makefile.am b/tests/Makefile.am
index dcec2df..c03f3bb 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 0000000..e8d9416
Binary files /dev/null and b/tests/aero.gif differ
diff --git a/tests/pixbuf-area-updated.c b/tests/pixbuf-area-updated.c
index 9c4f0e8..5cd308e 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 ();
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]