mirror of https://github.com/GNOME/gimp.git
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.
This commit is contained in:
parent
3d7e0f2fef
commit
e09520fb08
|
@ -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 \
|
||||
|
|
|
@ -30,6 +30,7 @@ typedef struct _GimpCanvasGroup GimpCanvasGroup;
|
|||
|
||||
typedef struct _GimpDisplay GimpDisplay;
|
||||
typedef struct _GimpDisplayShell GimpDisplayShell;
|
||||
typedef struct _GimpMotionBuffer GimpMotionBuffer;
|
||||
|
||||
typedef struct _GimpImageWindow GimpImageWindow;
|
||||
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
/* GIMP - The GNU Image Manipulation Program
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* 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_DISPLAY_SHELL_COORDS_H__
|
||||
#define __GIMP_DISPLAY_SHELL_COORDS_H__
|
||||
|
||||
|
||||
gboolean gimp_display_shell_eval_event (GimpDisplayShell *shell,
|
||||
GimpCoords *coords,
|
||||
gdouble inertia_factor,
|
||||
guint32 time);
|
||||
void gimp_display_shell_push_event_history (GimpDisplayShell *shell,
|
||||
GimpCoords *coords);
|
||||
|
||||
|
||||
#endif /* __GIMP_DISPLAY_SHELL_COORDS_H__ */
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
@ -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__ */
|
Loading…
Reference in New Issue