[gimp] app: add GimpMotionBuffer class to swallow all the event smoothing code



commit e09520fb084bca1bd818389fc510f9638a2565b9
Author: Michael Natterer <mitch gimp org>
Date:   Sun Apr 17 18:53:42 2011 +0200

    app: add GimpMotionBuffer class to swallow all the event smoothing code
    
    This commit only adds the class and removes the members from
    GimpDisplayShell, so everything looks more ugly than before, but
    I wanted the member moving separate from any refactorings.

 app/display/Makefile.am                            |    4 +-
 app/display/display-types.h                        |    1 +
 app/display/gimpdisplayshell-coords.h              |   30 ---
 app/display/gimpdisplayshell-tool-events.c         |   78 ++++---
 app/display/gimpdisplayshell.c                     |   16 +-
 app/display/gimpdisplayshell.h                     |   17 +--
 ...impdisplayshell-coords.c => gimpmotionbuffer.c} |  263 +++++++++++++++-----
 app/display/gimpmotionbuffer.h                     |   84 +++++++
 8 files changed, 334 insertions(+), 159 deletions(-)
---
diff --git a/app/display/Makefile.am b/app/display/Makefile.am
index 9679084..c0b3fc6 100644
--- a/app/display/Makefile.am
+++ b/app/display/Makefile.am
@@ -83,8 +83,6 @@ libappdisplay_a_sources = \
 	gimpdisplayshell-callbacks.h		\
 	gimpdisplayshell-close.c		\
 	gimpdisplayshell-close.h		\
-	gimpdisplayshell-coords.c		\
-	gimpdisplayshell-coords.h		\
 	gimpdisplayshell-cursor.c		\
 	gimpdisplayshell-cursor.h		\
 	gimpdisplayshell-dnd.c			\
@@ -129,6 +127,8 @@ libappdisplay_a_sources = \
 	gimpdisplayshell-transform.h		\
 	gimpimagewindow.c			\
 	gimpimagewindow.h			\
+	gimpmotionbuffer.c			\
+	gimpmotionbuffer.h			\
 	gimpnavigationeditor.c			\
 	gimpnavigationeditor.h			\
 	gimpscalecombobox.c			\
diff --git a/app/display/display-types.h b/app/display/display-types.h
index 63d9132..251f9d5 100644
--- a/app/display/display-types.h
+++ b/app/display/display-types.h
@@ -30,6 +30,7 @@ typedef struct _GimpCanvasGroup       GimpCanvasGroup;
 
 typedef struct _GimpDisplay           GimpDisplay;
 typedef struct _GimpDisplayShell      GimpDisplayShell;
+typedef struct _GimpMotionBuffer      GimpMotionBuffer;
 
 typedef struct _GimpImageWindow       GimpImageWindow;
 
diff --git a/app/display/gimpdisplayshell-tool-events.c b/app/display/gimpdisplayshell-tool-events.c
index 7992bc0..6c230fe 100644
--- a/app/display/gimpdisplayshell-tool-events.c
+++ b/app/display/gimpdisplayshell-tool-events.c
@@ -50,7 +50,6 @@
 #include "gimpdisplay.h"
 #include "gimpdisplayshell.h"
 #include "gimpdisplayshell-autoscroll.h"
-#include "gimpdisplayshell-coords.h"
 #include "gimpdisplayshell-cursor.h"
 #include "gimpdisplayshell-grab.h"
 #include "gimpdisplayshell-layer-select.h"
@@ -59,6 +58,7 @@
 #include "gimpdisplayshell-tool-events.h"
 #include "gimpdisplayshell-transform.h"
 #include "gimpimagewindow.h"
+#include "gimpmotionbuffer.h"
 
 #include "gimp-log.h"
 
@@ -514,7 +514,7 @@ gimp_display_shell_canvas_tool_events (GtkWidget        *canvas,
                  */
                 GimpCoords tmp_coords;
 
-                tmp_coords = shell->last_coords;
+                tmp_coords = shell->motion_buffer->last_coords;
 
                 tmp_coords.x        = image_coords.x;
                 tmp_coords.y        = image_coords.y;
@@ -530,7 +530,7 @@ gimp_display_shell_canvas_tool_events (GtkWidget        *canvas,
                                                   GIMP_BUTTON_PRESS_NORMAL,
                                                   display);
 
-                shell->last_read_motion_time = bevent->time;
+                shell->motion_buffer->last_read_motion_time = bevent->time;
               }
             break;
 
@@ -663,7 +663,7 @@ gimp_display_shell_canvas_tool_events (GtkWidget        *canvas,
               {
                 if (gimp_tool_control_is_active (active_tool->control))
                   {
-                    if (shell->event_queue->len > 0)
+                    if (shell->motion_buffer->event_queue->len > 0)
                       gimp_display_shell_flush_event_queue (shell);
 
                     tool_manager_button_release_active (gimp,
@@ -899,7 +899,7 @@ gimp_display_shell_canvas_tool_events (GtkWidget        *canvas,
                      GIMP_MOTION_MODE_EXACT) &&
                     shell->display->config->use_event_history &&
                     gdk_device_get_history (mevent->device, mevent->window,
-                                            shell->last_read_motion_time + 1,
+                                            shell->motion_buffer->last_read_motion_time + 1,
                                             mevent->time - 1,
                                             &history_events,
                                             &n_history_events))
@@ -925,7 +925,9 @@ gimp_display_shell_canvas_tool_events (GtkWidget        *canvas,
 
                         /* Early removal of useless events saves CPU time.
                          */
-                        if (gimp_display_shell_eval_event (shell,
+                        if (gimp_motion_buffer_eval_event (shell->motion_buffer,
+                                                           shell->scale_x,
+                                                           shell->scale_y,
                                                            &image_coords,
                                                            active_tool->max_coord_smooth,
                                                            history_events[i]->time))
@@ -935,7 +937,7 @@ gimp_display_shell_canvas_tool_events (GtkWidget        *canvas,
                                                                     history_events[i]->time);
                           }
 
-                        shell->last_read_motion_time = history_events[i]->time;
+                        shell->motion_buffer->last_read_motion_time = history_events[i]->time;
                       }
 
                     tool_manager_control_active (gimp, GIMP_TOOL_ACTION_RESUME,
@@ -947,7 +949,9 @@ gimp_display_shell_canvas_tool_events (GtkWidget        *canvas,
                   {
                     /* Early removal of useless events saves CPU time.
                      */
-                    if (gimp_display_shell_eval_event (shell,
+                    if (gimp_motion_buffer_eval_event (shell->motion_buffer,
+                                                       shell->scale_x,
+                                                       shell->scale_y,
                                                        &image_coords,
                                                        active_tool->max_coord_smooth,
                                                        time))
@@ -957,7 +961,7 @@ gimp_display_shell_canvas_tool_events (GtkWidget        *canvas,
                                                                 time);
                       }
 
-                    shell->last_read_motion_time = time;
+                    shell->motion_buffer->last_read_motion_time = time;
                   }
               }
           }
@@ -968,13 +972,15 @@ gimp_display_shell_canvas_tool_events (GtkWidget        *canvas,
             /* Early removal of useless events saves CPU time.
              * Smoothing is 0.0 here for coasting.
              */
-            if (gimp_display_shell_eval_event (shell,
+            if (gimp_motion_buffer_eval_event (shell->motion_buffer,
+                                               shell->scale_x,
+                                               shell->scale_y,
                                                &image_coords,
                                                0.0,
                                                time))
               {
                 /* then update the tool. */
-                GimpCoords *buf_coords = &g_array_index (shell->event_queue,
+                GimpCoords *buf_coords = &g_array_index (shell->motion_buffer->event_queue,
                                                          GimpCoords, 0);
 
                 tool_manager_oper_update_active (gimp,
@@ -983,11 +989,12 @@ gimp_display_shell_canvas_tool_events (GtkWidget        *canvas,
                                                  display);
 
                 /* remove used event */
-                g_array_remove_index (shell->event_queue, 0);
+                g_array_remove_index (shell->motion_buffer->event_queue, 0);
               }
 
-            gimp_display_shell_push_event_history (shell, &image_coords);
-            shell->last_read_motion_time = time;
+            gimp_motion_buffer_push_event_history (shell->motion_buffer,
+                                                   &image_coords);
+            shell->motion_buffer->last_read_motion_time = time;
           }
 
         return_val = TRUE;
@@ -1727,23 +1734,24 @@ gimp_display_shell_flush_event_queue (GimpDisplayShell *shell)
 {
   GimpTool *active_tool = tool_manager_get_active (shell->display->gimp);
 
-  shell->event_delay = FALSE;
+  shell->motion_buffer->event_delay = FALSE;
 
   /* Set the timeout id to 0 */
-  shell->event_delay_timeout = 0;
+  shell->motion_buffer->event_delay_timeout = 0;
 
   if (active_tool                                        &&
       gimp_tool_control_is_active (active_tool->control) &&
-      shell->event_queue->len > 0)
+      shell->motion_buffer->event_queue->len > 0)
     {
-       GimpCoords last_coords = g_array_index (shell->event_queue,
-                                               GimpCoords, shell->event_queue->len - 1 );
+       GimpCoords last_coords = g_array_index (shell->motion_buffer->event_queue,
+                                               GimpCoords,
+                                               shell->motion_buffer->event_queue->len - 1 );
 
-       gimp_display_shell_push_event_history (shell, &last_coords);
+       gimp_motion_buffer_push_event_history (shell->motion_buffer, &last_coords);
 
        gimp_display_shell_process_event_queue (shell,
-                                               shell->last_active_state,
-                                               shell->last_read_motion_time);
+                                               shell->motion_buffer->last_active_state,
+                                               shell->motion_buffer->last_read_motion_time);
     }
 
   /* Return false so a potential timeout calling it gets removed */
@@ -1761,30 +1769,30 @@ gimp_display_shell_process_event_queue (GimpDisplayShell *shell,
   GimpCoords       keep_event;
   GimpCoords      *buf_coords = NULL;
 
-  if (shell->event_delay)
+  if (shell->motion_buffer->event_delay)
     {
       keep = 1; /* Holding one event in buf */
       /* If we are in delay we use LAST state, not current */
-      event_state = shell->last_active_state;
-      keep_event = g_array_index (shell->event_queue,
-                                  GimpCoords, shell->event_queue->len - 1 );
+      event_state = shell->motion_buffer->last_active_state;
+      keep_event = g_array_index (shell->motion_buffer->event_queue,
+                                  GimpCoords, shell->motion_buffer->event_queue->len - 1);
     }
   else
     {
       event_state = state; /* Save the state */
     }
 
-  if (shell->event_delay_timeout != 0)
-    g_source_remove (shell->event_delay_timeout);
+  if (shell->motion_buffer->event_delay_timeout != 0)
+    g_source_remove (shell->motion_buffer->event_delay_timeout);
 
-  shell->last_active_state = state;
+  shell->motion_buffer->last_active_state = state;
 
   tool_manager_control_active (shell->display->gimp,
                                GIMP_TOOL_ACTION_PAUSE, shell->display);
 
-  for (i = 0; i < (shell->event_queue->len - keep); i++)
+  for (i = 0; i < (shell->motion_buffer->event_queue->len - keep); i++)
     {
-      buf_coords = &g_array_index (shell->event_queue, GimpCoords, i);
+      buf_coords = &g_array_index (shell->motion_buffer->event_queue, GimpCoords, i);
 
       tool_manager_motion_active (shell->display->gimp,
                                   buf_coords,
@@ -1796,13 +1804,13 @@ gimp_display_shell_process_event_queue (GimpDisplayShell *shell,
   tool_manager_control_active (shell->display->gimp,
                                GIMP_TOOL_ACTION_RESUME, shell->display);
 
-  g_array_set_size (shell->event_queue, 0);
+  g_array_set_size (shell->motion_buffer->event_queue, 0);
 
-  if (shell->event_delay)
+  if (shell->motion_buffer->event_delay)
     {
-      g_array_append_val (shell->event_queue, keep_event);
+      g_array_append_val (shell->motion_buffer->event_queue, keep_event);
 
-      shell->event_delay_timeout =
+      shell->motion_buffer->event_delay_timeout =
         g_timeout_add (50,
                        (GSourceFunc) gimp_display_shell_flush_event_queue,
                        shell);
diff --git a/app/display/gimpdisplayshell.c b/app/display/gimpdisplayshell.c
index 86f8f5d..2b293c9 100644
--- a/app/display/gimpdisplayshell.c
+++ b/app/display/gimpdisplayshell.c
@@ -74,6 +74,7 @@
 #include "gimpdisplayshell-tool-events.h"
 #include "gimpdisplayshell-transform.h"
 #include "gimpimagewindow.h"
+#include "gimpmotionbuffer.h"
 #include "gimpstatusbar.h"
 
 #include "about.h"
@@ -304,8 +305,7 @@ gimp_display_shell_init (GimpDisplayShell *shell)
   shell->cursor_modifier = GIMP_CURSOR_MODIFIER_NONE;
   shell->override_cursor = (GimpCursorType) -1;
 
-  shell->event_history = g_array_new (FALSE, FALSE, sizeof (GimpCoords));
-  shell->event_queue   = g_array_new (FALSE, FALSE, sizeof (GimpCoords));
+  shell->motion_buffer   = gimp_motion_buffer_new ();
 
   shell->zoom_focus_pointer_queue = g_queue_new ();
 
@@ -789,16 +789,10 @@ gimp_display_shell_dispose (GObject *object)
 
   gimp_display_shell_items_free (shell);
 
-  if (shell->event_history)
+  if (shell->motion_buffer)
     {
-      g_array_free (shell->event_history, TRUE);
-      shell->event_history = NULL;
-    }
-
-  if (shell->event_queue)
-    {
-      g_array_free (shell->event_queue, TRUE);
-      shell->event_queue = NULL;
+      g_object_unref (shell->motion_buffer);
+      shell->motion_buffer = NULL;
     }
 
   if (shell->zoom_focus_pointer_queue)
diff --git a/app/display/gimpdisplayshell.h b/app/display/gimpdisplayshell.h
index d9ee501..5f64131 100644
--- a/app/display/gimpdisplayshell.h
+++ b/app/display/gimpdisplayshell.h
@@ -86,15 +86,6 @@ struct _GimpDisplayShell
   gint               last_offset_x;    /*  offsets used when reverting zoom   */
   gint               last_offset_y;
 
-  guint32            last_motion_time; /*  previous time of a forwarded motion event  */
-  guint32            last_read_motion_time;
-  gdouble            last_motion_delta_time;
-  gdouble            last_motion_delta_x;
-  gdouble            last_motion_delta_y;
-  gdouble            last_motion_distance;
-
-  GimpCoords         last_coords;      /* last motion event                   */
-
   gdouble            other_scale;      /*  scale factor entered in Zoom->Other*/
 
   gint               disp_width;       /*  width of drawing area              */
@@ -190,15 +181,9 @@ struct _GimpDisplayShell
   GimpDrawable      *mask;
   GimpRGB            mask_color;
 
-  GArray            *event_history;
-  GArray            *event_queue;
-  gboolean           event_delay;      /* TRUE if theres an unsent event in
-                                          the history buffer                  */
+  GimpMotionBuffer  *motion_buffer;
 
   GQueue            *zoom_focus_pointer_queue;
-
-  gint               event_delay_timeout;
-  GdkModifierType    last_active_state;
 };
 
 struct _GimpDisplayShellClass
diff --git a/app/display/gimpdisplayshell-coords.c b/app/display/gimpmotionbuffer.c
similarity index 50%
rename from app/display/gimpdisplayshell-coords.c
rename to app/display/gimpmotionbuffer.c
index 6f482b4..4092e94 100644
--- a/app/display/gimpdisplayshell-coords.c
+++ b/app/display/gimpmotionbuffer.c
@@ -17,35 +17,167 @@
 
 #include "config.h"
 
+#include <string.h>
+
+#include <gegl.h>
 #include <gtk/gtk.h>
 
 #include "libgimpmath/gimpmath.h"
 
 #include "display-types.h"
 
-#include "gimpdisplayshell.h"
-#include "gimpdisplayshell-coords.h"
-
 #include "core/gimpcoords.h"
 #include "core/gimpcoords-interpolate.h"
+#include "core/gimpmarshal.h"
+
+#include "gimpmotionbuffer.h"
 
 
 /* Velocity unit is screen pixels per millisecond we pass to tools as 1. */
 #define VELOCITY_UNIT        3.0
 #define EVENT_FILL_PRECISION 6.0
-#define DIRECTION_RADIUS     (1.5 / MAX (shell->scale_x, shell->scale_y))
+#define DIRECTION_RADIUS     (1.5 / MAX (scale_x, scale_y))
 #define SMOOTH_FACTOR        0.3
 
 
-static void gimp_display_shell_interpolate_stroke (GimpDisplayShell *shell,
-                                                   GimpCoords       *coords);
+enum
+{
+  PROP_0
+};
+
+enum
+{
+  MOTION,
+  LAST_SIGNAL
+};
+
+
+/*  local function prototypes  */
 
+static void   gimp_motion_buffer_constructed        (GObject          *object);
+static void   gimp_motion_buffer_dispose            (GObject          *object);
+static void   gimp_motion_buffer_finalize           (GObject          *object);
+static void   gimp_motion_buffer_set_property       (GObject          *object,
+                                                     guint             property_id,
+                                                     const GValue     *value,
+                                                     GParamSpec       *pspec);
+static void   gimp_motion_buffer_get_property       (GObject          *object,
+                                                     guint             property_id,
+                                                     GValue           *value,
+                                                     GParamSpec       *pspec);
+
+static void   gimp_motion_buffer_interpolate_stroke (GimpMotionBuffer *buffer,
+                                                     GimpCoords       *coords);
+
+
+G_DEFINE_TYPE (GimpMotionBuffer, gimp_motion_buffer, GIMP_TYPE_OBJECT)
+
+#define parent_class gimp_motion_buffer_parent_class
+
+static guint motion_buffer_signals[LAST_SIGNAL] = { 0 };
 
 static const GimpCoords default_coords = GIMP_COORDS_DEFAULT_VALUES;
 
 
+static void
+gimp_motion_buffer_class_init (GimpMotionBufferClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  motion_buffer_signals[MOTION] =
+    g_signal_new ("motion",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_FIRST,
+                  G_STRUCT_OFFSET (GimpMotionBufferClass, motion),
+                  NULL, NULL,
+                  gimp_marshal_VOID__VOID,
+                  G_TYPE_NONE, 0);
+
+  object_class->constructed  = gimp_motion_buffer_constructed;
+  object_class->dispose      = gimp_motion_buffer_dispose;
+  object_class->finalize     = gimp_motion_buffer_finalize;
+  object_class->set_property = gimp_motion_buffer_set_property;
+  object_class->get_property = gimp_motion_buffer_get_property;
+}
+
+static void
+gimp_motion_buffer_init (GimpMotionBuffer *buffer)
+{
+  buffer->event_history = g_array_new (FALSE, FALSE, sizeof (GimpCoords));
+  buffer->event_queue   = g_array_new (FALSE, FALSE, sizeof (GimpCoords));
+}
+
+static void
+gimp_motion_buffer_constructed (GObject *object)
+{
+  if (G_OBJECT_CLASS (parent_class)->constructed)
+    G_OBJECT_CLASS (parent_class)->constructed (object);
+}
+
+static void
+gimp_motion_buffer_dispose (GObject *object)
+{
+  GimpMotionBuffer *buffer = GIMP_MOTION_BUFFER (object);
+
+  if (buffer->event_history)
+    {
+      g_array_free (buffer->event_history, TRUE);
+      buffer->event_history = NULL;
+    }
+
+  if (buffer->event_queue)
+    {
+      g_array_free (buffer->event_queue, TRUE);
+      buffer->event_queue = NULL;
+    }
+
+  G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+gimp_motion_buffer_finalize (GObject *object)
+{
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gimp_motion_buffer_set_property (GObject      *object,
+                                 guint         property_id,
+                                 const GValue *value,
+                                 GParamSpec   *pspec)
+{
+  switch (property_id)
+    {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+static void
+gimp_motion_buffer_get_property (GObject    *object,
+                                 guint       property_id,
+                                 GValue     *value,
+                                 GParamSpec *pspec)
+{
+  switch (property_id)
+    {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+
 /*  public functions  */
 
+GimpMotionBuffer *
+gimp_motion_buffer_new (void)
+{
+  return g_object_new (GIMP_TYPE_MOTION_BUFFER,
+                       NULL);
+}
+
 /**
  * gimp_display_shell_eval_event:
  * @shell:
@@ -71,7 +203,9 @@ static const GimpCoords default_coords = GIMP_COORDS_DEFAULT_VALUES;
  * Return value:
  **/
 gboolean
-gimp_display_shell_eval_event (GimpDisplayShell *shell,
+gimp_motion_buffer_eval_event (GimpMotionBuffer *buffer,
+                               gdouble           scale_x,
+                               gdouble           scale_y,
                                GimpCoords       *coords,
                                gdouble           inertia_factor,
                                guint32           time)
@@ -82,20 +216,20 @@ gimp_display_shell_eval_event (GimpDisplayShell *shell,
   gdouble  dir_delta_x = 0.0;
   gdouble  dir_delta_y = 0.0;
   gdouble  distance    = 1.0;
-  gboolean event_fill  = (inertia_factor > 0);
+  gboolean event_fill  = (inertia_factor > 0.0);
 
   /*  Smoothing causes problems with cursor tracking when zoomed above
    *  screen resolution so we need to supress it.
    */
-  if (shell->scale_x > 1.0 || shell->scale_y > 1.0)
+  if (scale_x > 1.0 || scale_y > 1.0)
     {
       inertia_factor = 0.0;
     }
 
-  delta_time = (shell->last_motion_delta_time * (1 - SMOOTH_FACTOR) +
-                (time - shell->last_motion_time) * SMOOTH_FACTOR);
+  delta_time = (buffer->last_motion_delta_time * (1 - SMOOTH_FACTOR) +
+                (time - buffer->last_motion_time) * SMOOTH_FACTOR);
 
-  if (shell->last_motion_time == 0)
+  if (buffer->last_motion_time == 0)
     {
       /*  First pair is invalid to do any velocity calculation, so we
        *  apply a constant value.
@@ -104,10 +238,10 @@ gimp_display_shell_eval_event (GimpDisplayShell *shell,
     }
   else
     {
-      gdouble filter;
-      gdouble dist;
-      gdouble delta_dir;
-      GimpCoords last_dir_event = shell->last_coords;
+      GimpCoords last_dir_event = buffer->last_coords;
+      gdouble    filter;
+      gdouble    dist;
+      gdouble    delta_dir;
 
       delta_x = last_dir_event.x - coords->x;
       delta_y = last_dir_event.y - coords->y;
@@ -115,7 +249,7 @@ gimp_display_shell_eval_event (GimpDisplayShell *shell,
       /*  Events with distances less than the screen resolution are
        *  not worth handling.
        */
-      filter = MIN (1 / shell->scale_x, 1 / shell->scale_y) / 2.0;
+      filter = MIN (1 / scale_x, 1 / scale_y) / 2.0;
 
       if (fabs (delta_x) < filter && fabs (delta_y) < filter)
         return FALSE;
@@ -127,21 +261,20 @@ gimp_display_shell_eval_event (GimpDisplayShell *shell,
        */
       if (delta_time == 0)
         {
-          coords->velocity = shell->last_coords.velocity;
+          coords->velocity = buffer->last_coords.velocity;
         }
       else
         {
           /*  We need to calculate the velocity in screen coordinates
            *  for human interaction
            */
-          gdouble screen_distance = (distance *
-                                     MIN (shell->scale_x, shell->scale_y));
+          gdouble screen_distance = (distance * MIN (scale_x, scale_y));
 
           /* Calculate raw valocity */
           coords->velocity = ((screen_distance / delta_time) / VELOCITY_UNIT);
 
           /* Adding velocity dependent smoothing, feels better in tools. */
-          coords->velocity = (shell->last_coords.velocity *
+          coords->velocity = (buffer->last_coords.velocity *
                               (1 - MIN (SMOOTH_FACTOR, coords->velocity)) +
                               coords->velocity *
                               MIN (SMOOTH_FACTOR, coords->velocity));
@@ -152,7 +285,7 @@ gimp_display_shell_eval_event (GimpDisplayShell *shell,
 
       if (((fabs (delta_x) > DIRECTION_RADIUS) &&
            (fabs (delta_y) > DIRECTION_RADIUS)) ||
-          (shell->event_history->len < 4))
+          (buffer->event_history->len < 4))
         {
           dir_delta_x = delta_x;
           dir_delta_y = delta_y;
@@ -165,7 +298,7 @@ gimp_display_shell_eval_event (GimpDisplayShell *shell,
                   (fabs (dir_delta_y) < DIRECTION_RADIUS)) &&
                  (x >= 0))
             {
-              last_dir_event = g_array_index (shell->event_history,
+              last_dir_event = g_array_index (buffer->event_history,
                                               GimpCoords, x);
 
               dir_delta_x = last_dir_event.x - coords->x;
@@ -178,7 +311,7 @@ gimp_display_shell_eval_event (GimpDisplayShell *shell,
       if ((fabs (dir_delta_x) < DIRECTION_RADIUS) ||
           (fabs (dir_delta_y) < DIRECTION_RADIUS))
         {
-          coords->direction = shell->last_coords.direction;
+          coords->direction = buffer->last_coords.direction;
         }
       else
         {
@@ -187,22 +320,22 @@ gimp_display_shell_eval_event (GimpDisplayShell *shell,
 
       coords->direction = coords->direction - floor (coords->direction);
 
-      delta_dir = coords->direction - shell->last_coords.direction;
+      delta_dir = coords->direction - buffer->last_coords.direction;
 
       if ((fabs (delta_dir) > 0.5) && (delta_dir < 0.0))
         {
           coords->direction = (0.5 * coords->direction +
-                               0.5 * (shell->last_coords.direction - 1.0));
+                               0.5 * (buffer->last_coords.direction - 1.0));
         }
       else if ((fabs (delta_dir) > 0.5) && (delta_dir > 0.0))
         {
           coords->direction = (0.5 * coords->direction +
-                               0.5 * (shell->last_coords.direction + 1.0));
+                               0.5 * (buffer->last_coords.direction + 1.0));
         }
       else
         {
           coords->direction = (0.5 * coords->direction +
-                               0.5 * shell->last_coords.direction);
+                               0.5 * buffer->last_coords.direction);
         }
 
       coords->direction = coords->direction - floor (coords->direction);
@@ -210,31 +343,31 @@ gimp_display_shell_eval_event (GimpDisplayShell *shell,
       /* do event fill for devices that do not provide enough events */
       if (distance >= EVENT_FILL_PRECISION &&
           event_fill                       &&
-          shell->event_history->len >= 2)
+          buffer->event_history->len >= 2)
         {
-          if (shell->event_delay)
+          if (buffer->event_delay)
             {
-              gimp_display_shell_interpolate_stroke (shell, coords);
+              gimp_motion_buffer_interpolate_stroke (buffer, coords);
             }
           else
             {
-              shell->event_delay = TRUE;
-              gimp_display_shell_push_event_history (shell, coords);
+              buffer->event_delay = TRUE;
+              gimp_motion_buffer_push_event_history (buffer, coords);
             }
-          }
-        else
-          {
-            if (shell->event_delay)
-              shell->event_delay = FALSE;
+        }
+      else
+        {
+          if (buffer->event_delay)
+            buffer->event_delay = FALSE;
 
-            gimp_display_shell_push_event_history (shell, coords);
-          }
+          gimp_motion_buffer_push_event_history (buffer, coords);
+        }
 
 #ifdef EVENT_VERBOSE
       g_printerr ("DIST: %f, DT:%f, Vel:%f, Press:%f,smooth_dd:%f, POS: (%f, %f)\n",
                   distance,
                   delta_time,
-                  shell->last_coords.velocity,
+                  buffer->last_coords.velocity,
                   coords->pressure,
                   distance - dist,
                   coords->x,
@@ -242,48 +375,48 @@ gimp_display_shell_eval_event (GimpDisplayShell *shell,
 #endif
     }
 
-  g_array_append_val (shell->event_queue, *coords);
+  g_array_append_val (buffer->event_queue, *coords);
 
-  shell->last_coords            = *coords;
-  shell->last_motion_time       = time;
-  shell->last_motion_delta_time = delta_time;
-  shell->last_motion_delta_x    = delta_x;
-  shell->last_motion_delta_y    = delta_y;
-  shell->last_motion_distance   = distance;
+  buffer->last_coords            = *coords;
+  buffer->last_motion_time       = time;
+  buffer->last_motion_delta_time = delta_time;
+  buffer->last_motion_delta_x    = delta_x;
+  buffer->last_motion_delta_y    = delta_y;
+  buffer->last_motion_distance   = distance;
 
   return TRUE;
 }
 
-
-/* Helper function fo managing event history */
 void
-gimp_display_shell_push_event_history (GimpDisplayShell *shell,
+gimp_motion_buffer_push_event_history (GimpMotionBuffer *buffer,
                                        GimpCoords       *coords)
 {
-  if (shell->event_history->len == 4)
-    g_array_remove_index (shell->event_history, 0);
+  if (buffer->event_history->len == 4)
+    g_array_remove_index (buffer->event_history, 0);
 
-  g_array_append_val (shell->event_history, *coords);
+  g_array_append_val (buffer->event_history, *coords);
 }
 
+
+/*  private functions  */
+
 static void
-gimp_display_shell_interpolate_stroke (GimpDisplayShell *shell,
+gimp_motion_buffer_interpolate_stroke (GimpMotionBuffer *buffer,
                                        GimpCoords       *coords)
 {
   GArray *ret_coords;
-  gint    i = shell->event_history->len - 1;
+  gint    i = buffer->event_history->len - 1;
 
   /* Note that there must be exactly one event in buffer or bad things
-   * can happen. This should never get called under other
-   * circumstances.
+   * can happen. This must never get called under other circumstances.
    */
   ret_coords = g_array_new (FALSE, FALSE, sizeof (GimpCoords));
 
-  gimp_coords_interpolate_catmull (g_array_index (shell->event_history,
+  gimp_coords_interpolate_catmull (g_array_index (buffer->event_history,
                                                   GimpCoords, i - 1),
-                                   g_array_index (shell->event_history,
+                                   g_array_index (buffer->event_history,
                                                   GimpCoords, i),
-                                   g_array_index (shell->event_queue,
+                                   g_array_index (buffer->event_queue,
                                                   GimpCoords, 0),
                                    *coords,
                                    EVENT_FILL_PRECISION / 2,
@@ -291,13 +424,13 @@ gimp_display_shell_interpolate_stroke (GimpDisplayShell *shell,
                                    NULL);
 
   /* Push the last actual event in history */
-  gimp_display_shell_push_event_history (shell,
-                                         &g_array_index (shell->event_queue,
+  gimp_motion_buffer_push_event_history (buffer,
+                                         &g_array_index (buffer->event_queue,
                                                          GimpCoords, 0));
 
-  g_array_set_size (shell->event_queue, 0);
+  g_array_set_size (buffer->event_queue, 0);
 
-  g_array_append_vals (shell->event_queue,
+  g_array_append_vals (buffer->event_queue,
                        &g_array_index (ret_coords, GimpCoords, 0),
                        ret_coords->len);
 
diff --git a/app/display/gimpmotionbuffer.h b/app/display/gimpmotionbuffer.h
new file mode 100644
index 0000000..4a53c89
--- /dev/null
+++ b/app/display/gimpmotionbuffer.h
@@ -0,0 +1,84 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpmotionbuffer.h
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GIMP_MOTION_BUFFER_H__
+#define __GIMP_MOTION_BUFFER_H__
+
+
+#include "core/gimpobject.h"
+
+
+#define GIMP_TYPE_MOTION_BUFFER            (gimp_motion_buffer_get_type ())
+#define GIMP_MOTION_BUFFER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_MOTION_BUFFER, GimpMotionBuffer))
+#define GIMP_MOTION_BUFFER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_MOTION_BUFFER, GimpMotionBufferClass))
+#define GIMP_IS_MOTION_BUFFER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_MOTION_BUFFER))
+#define GIMP_IS_MOTION_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_MOTION_BUFFER))
+#define GIMP_MOTION_BUFFER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_MOTION_BUFFER, GimpMotionBufferClass))
+
+
+typedef struct _GimpMotionBufferClass  GimpMotionBufferClass;
+
+struct _GimpMotionBuffer
+{
+  GimpObject  parent_instance;
+
+  guint32     last_motion_time; /*  previous time of a forwarded motion event  */
+  guint32     last_read_motion_time;
+  gdouble     last_motion_delta_time;
+  gdouble     last_motion_delta_x;
+  gdouble     last_motion_delta_y;
+  gdouble     last_motion_distance;
+
+  GimpCoords  last_coords;      /* last motion event                   */
+
+  GArray     *event_history;
+  GArray     *event_queue;
+  gboolean    event_delay;      /* TRUE if theres an unsent event in
+                                 *  the history buffer
+                                 */
+
+  gint               event_delay_timeout;
+  GdkModifierType    last_active_state;
+};
+
+struct _GimpMotionBufferClass
+{
+  GtkBoxClass  parent_class;
+
+  void (* motion)    (GimpMotionBuffer *buffer,
+                      const GimpCoords *coords,
+                      guint32           time);
+};
+
+
+GType              gimp_motion_buffer_get_type (void) G_GNUC_CONST;
+
+GimpMotionBuffer * gimp_motion_buffer_new      (void);
+
+gboolean           gimp_motion_buffer_eval_event (GimpMotionBuffer *buffer,
+                                                  gdouble           scale_x,
+                                                  gdouble           scale_y,
+                                                  GimpCoords       *coords,
+                                                  gdouble           inertia_factor,
+                                                  guint32           time);
+void               gimp_motion_buffer_push_event_history (GimpMotionBuffer *buffer,
+                                                          GimpCoords       *coords);
+
+
+#endif /* __GIMP_MOTION_BUFFER_H__ */



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