[gegl-gtk] Tests: Test redraws on GeglNode:computed



commit 8171d6456c34844e92b9d0c3bb9386e1b5a223e0
Author: Jon Nordby <jononor gmail com>
Date:   Fri Jul 22 00:47:38 2011 +0200

    Tests: Test redraws on GeglNode:computed

 gegl-gtk/gegl-gtk-view.c |   39 ++++++++++++++++++++++-
 tests/test-view.c        |   80 ++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 115 insertions(+), 4 deletions(-)
---
diff --git a/gegl-gtk/gegl-gtk-view.c b/gegl-gtk/gegl-gtk-view.c
index d454eeb..936dd4d 100644
--- a/gegl-gtk/gegl-gtk-view.c
+++ b/gegl-gtk/gegl-gtk-view.c
@@ -36,6 +36,12 @@ enum
   PROP_BLOCK
 };
 
+enum
+{
+  SIGNAL_REDRAW,
+  N_SIGNALS
+};
+
 
 typedef struct _GeglGtkViewPrivate
 {
@@ -54,6 +60,8 @@ G_DEFINE_TYPE (GeglGtkView, gegl_gtk_view, GTK_TYPE_DRAWING_AREA)
 #define GEGL_GTK_VIEW_GET_PRIVATE(obj) \
   (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GEGL_GTK_TYPE_VIEW, GeglGtkViewPrivate))
 
+static guint gegl_gtk_view_signals[N_SIGNALS] = { 0 };
+
 static void      gegl_gtk_view_class_init (GeglGtkViewClass  *klass);
 static void      gegl_gtk_view_init       (GeglGtkView       *self);
 static void      finalize             (GObject        *gobject);
@@ -74,6 +82,10 @@ static gboolean  draw                 (GtkWidget * widget,
                                        cairo_t *cr);
 #endif
 
+static void      redraw_event (GeglGtkView *view,
+                               GeglRectangle *rect,
+                               gpointer data);
+
 static void      gegl_gtk_view_repaint       (GeglGtkView *view);
 
 static void
@@ -129,6 +141,16 @@ gegl_gtk_view_class_init (GeglGtkViewClass * klass)
                                                         FALSE,
                                                         G_PARAM_READWRITE));
 
+  /* Emitted when a redraw is needed, with the area that needs redrawing.
+   * Exposed so that it can be tested. */
+  gegl_gtk_view_signals[SIGNAL_REDRAW] = g_signal_new ("redraw",
+                G_TYPE_FROM_CLASS (klass),
+                G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                0,
+                NULL, NULL,
+                g_cclosure_marshal_VOID__BOXED,
+                G_TYPE_NONE, 1,
+                GEGL_TYPE_RECTANGLE);
 
    g_type_class_add_private (klass, sizeof (GeglGtkViewPrivate));
 }
@@ -143,6 +165,8 @@ gegl_gtk_view_init (GeglGtkView *self)
   priv->scale       = 1.0;
   priv->monitor_id  = 0;
   priv->processor   = NULL;
+
+  g_signal_connect(self, "redraw", G_CALLBACK (redraw_event), NULL);
 }
 
 static void
@@ -176,8 +200,21 @@ computed_event (GeglNode      *self,
   gint y = priv->scale * (rect->y) - priv->y;
   gint w = ceil (priv->scale * rect->width  + 1);
   gint h = ceil (priv->scale * rect->height + 1);
+  GeglRectangle redraw_rect = {x, y, w, h};
+
+  g_signal_emit (view, gegl_gtk_view_signals[SIGNAL_REDRAW],
+	         0, &redraw_rect, NULL);
+
+}
 
-  gtk_widget_queue_draw_area (GTK_WIDGET (view), x, y, w, h);
+static void
+redraw_event (GeglGtkView *view,
+              GeglRectangle *rect,
+              gpointer data)
+{
+  gtk_widget_queue_draw_area (GTK_WIDGET (view),
+			      rect->x, rect->y,
+			      rect->width, rect->height);
 }
 
 
diff --git a/tests/test-view.c b/tests/test-view.c
index 11d3f4f..e427668 100644
--- a/tests/test-view.c
+++ b/tests/test-view.c
@@ -12,7 +12,7 @@ test_utils_display_is_set () {
 void
 test_utils_print_rect (GeglRectangle *rect) {
 
-    g_print ("GeglRectangle: %d,%d %dx%d\n", rect->x, rect->y, rect->width, rect->height);
+    g_print ("GeglRectangle: %d,%d %dx%d", rect->x, rect->y, rect->width, rect->height);
 }
 
 static gboolean
@@ -21,6 +21,20 @@ test_utils_quit_gtk_main (gpointer data)
     gtk_main_quit();
 }
 
+/* Compare two rectangles, output */
+gboolean
+test_utils_compare_rect (GeglRectangle *r, GeglRectangle *s)
+{
+    gboolean equal = gegl_rectangle_equal (r, s);
+    if (!equal) {
+        test_utils_print_rect (r);
+        g_printf ("%s", " != ");
+        test_utils_print_rect (s);
+
+    }
+    return equal;
+}
+
 /* Stores the state used in widget tests.*/
 typedef struct {
     GtkWidget *window, *view;
@@ -120,16 +134,75 @@ test_processing (void)
     teardown_widget_test(&test);
 }
 
+typedef struct {
+    gboolean needs_redraw_called;
+    GeglRectangle *expected_result;
+} RedrawTestState;
+
+static void
+needs_redraw_event (GeglGtkView *view,
+                GeglRectangle *rect,
+                RedrawTestState *data)
+{
+    data->needs_redraw_called = TRUE;
+
+    g_assert (test_utils_compare_rect (rect, data->expected_result));
+}
+
+/* Test that the redraw signal is emitted when the GeglNode has been computed.
+ *
+ * NOTE: Does not test that the actual drawing happens, or even
+ * that queue_redraw is called, as this is hard to observe reliably
+ * Redraws can be triggered by other things, and the exposed events
+ * can be coalesced. */
+static void
+test_redraw_on_computed (void)
+{
+    ViewWidgetTest test;
+    GeglRectangle computed_rect = {0, 0, 128, 128};
+    RedrawTestState test_data;
+    test_data.expected_result = &computed_rect;
+
+    setup_widget_test(&test);
+    /* Setup will invalidate the node, make sure those events are processed. */
+    while (gtk_events_pending ()) {
+        gtk_main_iteration ();
+    }
+    gegl_node_process (test.out);
+
+    g_assert (GEGL_GTK_IS_VIEW (test.view));
+
+    /* TODO: when adding tests for transformed cases,
+     * split out a function for testing the redrawn area, given
+     * the input area and the transformation (translation, scaling, rotation) */
+    g_signal_connect (G_OBJECT (test.view), "redraw",
+                      G_CALLBACK (needs_redraw_event),
+                      &test_data);
+
+
+
+    g_signal_emit_by_name (test.out, "computed", &computed_rect, NULL);
+
+    g_timeout_add (300, test_utils_quit_gtk_main, NULL);
+    gtk_main ();
+
+    g_assert(test_data.needs_redraw_called);
+
+    teardown_widget_test(&test);
+}
 
 /* TODO:
- * - Test redraw logic
  * - Test redraw with translation
  * - Test redraw with scaling
  * - Test redraw with rotation
  * Benchmarks for cases above
+ * Actual drawing tests, checking the output of the widget against a
+ * well known reference. Ideally done with a fake/dummy windowing backend,
+ * so it can be done quickly, without external influences.
  */
 
-/* Note that ideally only a few tests requires setting up a mainloop. */
+/* Note that ideally only a few tests requires setting up a mainloop, and
+having a real widget backend present. */
 
 int
 main (int argc, char **argv) {
@@ -149,6 +222,7 @@ main (int argc, char **argv) {
 
     g_test_add_func("/widgets/view/sanity", test_sanity);
     g_test_add_func("/widgets/view/processing", test_processing);
+    g_test_add_func("/widgets/view/redraw-on-computed", test_redraw_on_computed);
 
     retval = g_test_run();
     gegl_exit();



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