mirror of https://github.com/GNOME/gimp.git
app/core/core-types.h app/display/gimpdisplayshell-callbacks.c
2008-01-14 Sven Neumann <sven@gimp.org> * app/core/core-types.h * app/display/gimpdisplayshell-callbacks.c * app/display/gimpdisplayshell-coords.[ch] * app/display/gimpdisplayshell.h * app/paint/gimpink.[ch] * app/paint/gimpinkundo.[ch]: applied patch from Alexia Death that adds an event evaluation function that decides if an event is needed or can be discarded. As a side-product some useful dynamics parameters like velocity are added to the GimpCoords struct. The Ink tool is changed to use this information. See bug #508639. svn path=/trunk/; revision=24607
This commit is contained in:
parent
68c4cb9cc4
commit
524870327c
13
ChangeLog
13
ChangeLog
|
@ -1,3 +1,16 @@
|
|||
2008-01-14 Sven Neumann <sven@gimp.org>
|
||||
|
||||
* app/core/core-types.h
|
||||
* app/display/gimpdisplayshell-callbacks.c
|
||||
* app/display/gimpdisplayshell-coords.[ch]
|
||||
* app/display/gimpdisplayshell.h
|
||||
* app/paint/gimpink.[ch]
|
||||
* app/paint/gimpinkundo.[ch]: applied patch from Alexia Death that
|
||||
adds an event evaluation function that decides if an event is
|
||||
needed or can be discarded. As a side-product some useful dynamics
|
||||
parameters like velocity are added to the GimpCoords struct. The
|
||||
Ink tool is changed to use this information. See bug #508639.
|
||||
|
||||
2008-01-13 Michael Natterer <mitch@gimp.org>
|
||||
|
||||
* modules/colorsel_cmyk_lcms.c (colorsel_cmyk_config_changed): set
|
||||
|
|
|
@ -190,6 +190,11 @@ struct _GimpCoords
|
|||
gdouble xtilt;
|
||||
gdouble ytilt;
|
||||
gdouble wheel;
|
||||
gdouble delta_time;
|
||||
gdouble delta_x;
|
||||
gdouble delta_y;
|
||||
gdouble distance;
|
||||
gdouble velocity;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -902,7 +902,7 @@ gimp_display_shell_canvas_tool_events (GtkWidget *canvas,
|
|||
&image_coords,
|
||||
time, state, display);
|
||||
|
||||
shell->last_motion_time = bevent->time;
|
||||
shell->last_read_motion_time = bevent->time;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -1182,7 +1182,7 @@ gimp_display_shell_canvas_tool_events (GtkWidget *canvas,
|
|||
GdkTimeCoord **history_events;
|
||||
gint n_history_events;
|
||||
|
||||
/* if the first mouse button is down, check for automatic
|
||||
/* if the first mouse button is down, check for automatic
|
||||
* scrolling...
|
||||
*/
|
||||
if ((mevent->x < 0 ||
|
||||
|
@ -1194,11 +1194,19 @@ gimp_display_shell_canvas_tool_events (GtkWidget *canvas,
|
|||
gimp_display_shell_autoscroll_start (shell, state, mevent);
|
||||
}
|
||||
|
||||
if (gimp_tool_control_get_motion_mode (active_tool->control) ==
|
||||
GIMP_MOTION_MODE_EXACT &&
|
||||
/* gdk_device_get_history() has several quirks. First is
|
||||
* that events with borderline timestamps at both ends
|
||||
* are included. Because of that we need to add 1 to
|
||||
* lower border. The second is due to poor X event
|
||||
* resolution. We need to do -1 to ensure that the
|
||||
* amount of events between timestamps is final or
|
||||
* risk loosing some.
|
||||
*/
|
||||
if ((gimp_tool_control_get_motion_mode (active_tool->control) ==
|
||||
GIMP_MOTION_MODE_EXACT) &&
|
||||
gdk_device_get_history (mevent->device, mevent->window,
|
||||
shell->last_motion_time,
|
||||
mevent->time,
|
||||
shell->last_read_motion_time+1,
|
||||
mevent->time - 1,
|
||||
&history_events,
|
||||
&n_history_events))
|
||||
{
|
||||
|
@ -1206,6 +1214,7 @@ gimp_display_shell_canvas_tool_events (GtkWidget *canvas,
|
|||
|
||||
for (i = 0; i < n_history_events; i++)
|
||||
{
|
||||
|
||||
gimp_display_shell_get_time_coords (shell,
|
||||
mevent->device,
|
||||
history_events[i],
|
||||
|
@ -1231,33 +1240,71 @@ gimp_display_shell_canvas_tool_events (GtkWidget *canvas,
|
|||
x, y, width, height);
|
||||
}
|
||||
|
||||
tool_manager_motion_active (gimp,
|
||||
&image_coords,
|
||||
history_events[i]->time,
|
||||
state,
|
||||
display);
|
||||
/* Early removal of useless events saves CPU time.
|
||||
* Defaulting smoothing to 0.4.
|
||||
*/
|
||||
if (gimp_display_shell_eval_event (shell,
|
||||
&image_coords, 0.4,
|
||||
history_events[i]->time))
|
||||
{
|
||||
tool_manager_motion_active (gimp,
|
||||
&image_coords,
|
||||
history_events[i]->time,
|
||||
state,
|
||||
display);
|
||||
|
||||
shell->last_coords = image_coords;
|
||||
shell->last_disp_motion_time = history_events[i]->time;
|
||||
}
|
||||
|
||||
shell->last_read_motion_time=history_events[i]->time;
|
||||
}
|
||||
|
||||
gdk_device_free_history (history_events, n_history_events);
|
||||
}
|
||||
else
|
||||
{
|
||||
tool_manager_motion_active (gimp,
|
||||
&image_coords, time, state,
|
||||
display);
|
||||
}
|
||||
/* Early removal of useless events saves CPU time.
|
||||
* Defaulting smoothing to 0.4.
|
||||
*/
|
||||
if (gimp_display_shell_eval_event (shell,
|
||||
&image_coords, 0.4,
|
||||
time))
|
||||
{
|
||||
tool_manager_motion_active (gimp,
|
||||
&image_coords,
|
||||
time,
|
||||
state,
|
||||
display);
|
||||
|
||||
shell->last_motion_time = mevent->time;
|
||||
shell->last_coords = image_coords;
|
||||
shell->last_disp_motion_time = time;
|
||||
}
|
||||
|
||||
shell->last_read_motion_time=time;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! (state &
|
||||
(GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK)))
|
||||
{
|
||||
tool_manager_oper_update_active (gimp,
|
||||
&image_coords, state,
|
||||
shell->proximity,
|
||||
display);
|
||||
/* Early removal of useless events saves CPU time.
|
||||
* Smoothing coasting to avoid unpredicted jumps when making contact.
|
||||
* This may need a different solution but cant properly test it without
|
||||
* adjustment.
|
||||
*/
|
||||
if (gimp_display_shell_eval_event (shell, &image_coords, 0.4, time))
|
||||
{
|
||||
tool_manager_oper_update_active (gimp,
|
||||
&image_coords, state,
|
||||
shell->proximity,
|
||||
display);
|
||||
shell->last_coords = image_coords;
|
||||
shell->last_disp_motion_time = time;
|
||||
}
|
||||
|
||||
shell->last_read_motion_time = time;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libgimpmath/gimpmath.h"
|
||||
|
||||
#include "display-types.h"
|
||||
|
||||
#include "gimpdisplayshell.h"
|
||||
|
@ -131,7 +133,8 @@ gimp_display_shell_get_time_coords (GimpDisplayShell *shell,
|
|||
* requested axis does not exist.
|
||||
*/
|
||||
|
||||
if (gdk_device_get_axis (device, event->axes, GDK_AXIS_PRESSURE, &coords->pressure))
|
||||
if (gdk_device_get_axis (device,
|
||||
event->axes, GDK_AXIS_PRESSURE, &coords->pressure))
|
||||
coords->pressure = CLAMP (coords->pressure, GIMP_COORDS_MIN_PRESSURE,
|
||||
GIMP_COORDS_MAX_PRESSURE);
|
||||
else
|
||||
|
@ -177,3 +180,127 @@ gimp_display_shell_get_device_state (GimpDisplayShell *shell,
|
|||
{
|
||||
gdk_device_get_state (device, shell->canvas->window, NULL, state);
|
||||
}
|
||||
|
||||
/**
|
||||
* gimp_display_shell_eval_event:
|
||||
* @shell:
|
||||
* @coords:
|
||||
* @inertia_factor:
|
||||
* @time:
|
||||
*
|
||||
* This function evaluates the event to decide if the change is
|
||||
* big enough to need handling and returns FALSE, if change is less
|
||||
* than one image pixel or when smoothed event distance covers less
|
||||
* than one pixel taking a whole lot of load off any draw tools that
|
||||
* have no use for these sub-pixel events anyway. If the event is
|
||||
* seen fit at first look, it is evaluated for speed and smoothed.
|
||||
* Due to lousy time resolution of events pretty strong smoothing is
|
||||
* applied to timestamps for sensible speed result. This function is
|
||||
* also ideal for other event adjustment like pressure curve or
|
||||
* calculating other derived dynamics factors like angular velocity
|
||||
* calculation from tilt values, to allow for even more dynamic
|
||||
* brushes. Calculated distance to last event is stored in GimpCoords
|
||||
* because its a sideproduct of velocity calculation and is currently
|
||||
* calculated in each tool. If they were to use this distance, more
|
||||
* resouces on recalculating the same value would be saved.
|
||||
*
|
||||
* Return value:
|
||||
**/
|
||||
gboolean
|
||||
gimp_display_shell_eval_event (GimpDisplayShell *shell,
|
||||
GimpCoords *coords,
|
||||
gdouble inertia_factor,
|
||||
guint32 time)
|
||||
{
|
||||
guint32 thistime = time;
|
||||
gdouble dist;
|
||||
gdouble xy_sfactor = 0;
|
||||
const gdouble smooth_factor = 0.3;
|
||||
|
||||
if (shell->last_disp_motion_time == 0)
|
||||
{
|
||||
/* First pair is invalid to do any velocity calculation,
|
||||
* so we apply constant values.
|
||||
*/
|
||||
coords->velocity = 100;
|
||||
coords->delta_time = 0.001;
|
||||
coords->distance = 0;
|
||||
|
||||
shell->last_coords = *coords;
|
||||
}
|
||||
else
|
||||
{
|
||||
gdouble dx = coords->delta_x = shell->last_coords.x - coords->x;
|
||||
gdouble dy = coords->delta_y = shell->last_coords.y - coords->y;
|
||||
|
||||
/* Events with distances less than 1 in either motion direction
|
||||
* are not worth handling.
|
||||
*/
|
||||
if (fabs (dx) < 1.0 && fabs (dy) < 1.0)
|
||||
return FALSE;
|
||||
|
||||
coords->delta_time = thistime - shell->last_disp_motion_time;
|
||||
coords->delta_time = (shell->last_coords.delta_time * (1 - smooth_factor)
|
||||
+ coords->delta_time * smooth_factor);
|
||||
coords->distance = dist = sqrt (SQR (dx) + SQR (dy));
|
||||
|
||||
/* If even smoothed time resolution does not allow to guess for speed,
|
||||
* use last velocity.
|
||||
*/
|
||||
if ((coords->delta_time == 0))
|
||||
{
|
||||
coords->velocity = shell->last_coords.velocity;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
coords->velocity = (coords->distance / (gdouble) coords->delta_time) / 10;
|
||||
|
||||
/* A little smooth on this too, feels better in tools this way. */
|
||||
coords->velocity = (shell->last_coords.velocity * (1 - smooth_factor)
|
||||
+ coords->velocity * smooth_factor);
|
||||
/* Speed needs upper limit */
|
||||
coords->velocity=MIN(coords->velocity,1.0);
|
||||
}
|
||||
|
||||
if (inertia_factor > 0)
|
||||
{
|
||||
/* Apply smoothing to X and Y.
|
||||
*
|
||||
* The very high velocity values (yes, thats around 25
|
||||
* according to tests) happen at great zoom outs and scream
|
||||
* for heavyhanded smooth so I made it automatic. This
|
||||
* should be bound to zoom level once theres a GUI foob to
|
||||
* adjust smooth or disabled completely.
|
||||
*/
|
||||
|
||||
/*Apply smoothing to X and Y.
|
||||
Smooth is dampened for high speeds to minimize the whip effect.*/
|
||||
xy_sfactor = inertia_factor - inertia_factor * fabs (coords->velocity);
|
||||
coords->x = shell->last_coords.x - (shell->last_coords.delta_x * xy_sfactor
|
||||
+ coords->delta_x * (1 - xy_sfactor));
|
||||
coords->y = shell->last_coords.y - (shell->last_coords.delta_y * xy_sfactor
|
||||
+ coords->delta_y * (1 - xy_sfactor));
|
||||
|
||||
/* Recalculate distance */
|
||||
coords->distance = sqrt ((shell->last_coords.x - coords->x) *
|
||||
(shell->last_coords.x - coords->x) +
|
||||
(shell->last_coords.y - coords->y) *
|
||||
(shell->last_coords.y - coords->y));
|
||||
|
||||
}
|
||||
|
||||
#ifdef VERBOSE
|
||||
g_printerr ("DIST: %f, DT:%f, Vel:%f, Press:%f,smooth_dd:%f, sf %f\n",
|
||||
coords->distance,
|
||||
coords->delta_time,
|
||||
shell->last_coords.velocity,
|
||||
coords->pressure,
|
||||
coords->distance - dist,
|
||||
xy_sfactor);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -38,6 +38,10 @@ gboolean gimp_display_shell_get_event_state (GimpDisplayShell *shell,
|
|||
void gimp_display_shell_get_device_state (GimpDisplayShell *shell,
|
||||
GdkDevice *device,
|
||||
GdkModifierType *state);
|
||||
gboolean gimp_display_shell_eval_event (GimpDisplayShell *shell,
|
||||
GimpCoords *coords,
|
||||
gdouble inertia_factor,
|
||||
guint32 time);
|
||||
|
||||
|
||||
#endif /* __GIMP_DISPLAY_SHELL_COORDS_H__ */
|
||||
|
|
|
@ -178,13 +178,16 @@ struct _GimpDisplayShell
|
|||
gint scroll_start_x;
|
||||
gint scroll_start_y;
|
||||
gboolean button_press_before_focus;
|
||||
guint32 last_motion_time;
|
||||
guint32 last_disp_motion_time; /* previous time of a forwarded motion event */
|
||||
guint32 last_read_motion_time;
|
||||
|
||||
GdkRectangle *highlight; /* in image coordinates, can be NULL */
|
||||
GimpDrawable *mask;
|
||||
GimpChannelType mask_color;
|
||||
|
||||
gpointer scroll_info;
|
||||
|
||||
GimpCoords last_coords; /* last motion event */
|
||||
};
|
||||
|
||||
struct _GimpDisplayShellClass
|
||||
|
|
|
@ -77,18 +77,6 @@ static Blob * ink_pen_ellipse (GimpInkOptions *options,
|
|||
gdouble ytilt,
|
||||
gdouble velocity);
|
||||
|
||||
static void time_smoother_add (GimpInk *ink,
|
||||
guint32 value);
|
||||
static guint32 time_smoother_result (GimpInk *ink);
|
||||
static void time_smoother_init (GimpInk *ink,
|
||||
guint32 initval);
|
||||
|
||||
static void dist_smoother_add (GimpInk *ink,
|
||||
gdouble value);
|
||||
static gdouble dist_smoother_result (GimpInk *ink);
|
||||
static void dist_smoother_init (GimpInk *ink,
|
||||
gdouble initval);
|
||||
|
||||
static void render_blob (Blob *blob,
|
||||
PixelRegion *dest);
|
||||
|
||||
|
@ -270,67 +258,25 @@ gimp_ink_motion (GimpPaintCore *paint_core,
|
|||
paint_core->cur_coords.pressure,
|
||||
paint_core->cur_coords.xtilt,
|
||||
paint_core->cur_coords.ytilt,
|
||||
10.0);
|
||||
100);
|
||||
|
||||
if (ink->start_blob)
|
||||
g_free (ink->start_blob);
|
||||
|
||||
ink->start_blob = blob_duplicate (ink->last_blob);
|
||||
|
||||
time_smoother_init (ink, time);
|
||||
ink->last_time = time;
|
||||
|
||||
dist_smoother_init (ink, 0.0);
|
||||
ink->init_velocity = TRUE;
|
||||
|
||||
blob_to_render = ink->last_blob;
|
||||
}
|
||||
else
|
||||
{
|
||||
Blob *blob;
|
||||
gdouble dist;
|
||||
gdouble velocity;
|
||||
guint32 lasttime = ink->last_time;
|
||||
guint32 thistime;
|
||||
|
||||
time_smoother_add (ink, time);
|
||||
thistime = ink->last_time = time_smoother_result (ink);
|
||||
|
||||
/* The time resolution on X-based GDK motion events is bloody
|
||||
* awful, hence the use of the smoothing function. Sadly this
|
||||
* also means that there is always the chance of having an
|
||||
* indeterminite velocity since this event and the previous
|
||||
* several may still appear to issue at the same
|
||||
* instant. -ADM
|
||||
*/
|
||||
if (thistime == lasttime)
|
||||
thistime = lasttime + 1;
|
||||
|
||||
dist = sqrt ((paint_core->last_coords.x - paint_core->cur_coords.x) *
|
||||
(paint_core->last_coords.x - paint_core->cur_coords.x) +
|
||||
(paint_core->last_coords.y - paint_core->cur_coords.y) *
|
||||
(paint_core->last_coords.y - paint_core->cur_coords.y));
|
||||
|
||||
if (ink->init_velocity)
|
||||
{
|
||||
dist_smoother_init (ink, dist);
|
||||
ink->init_velocity = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
dist_smoother_add (ink, dist);
|
||||
dist = dist_smoother_result (ink);
|
||||
}
|
||||
|
||||
velocity = 10.0 * sqrt ((dist) / (gdouble) (thistime - lasttime));
|
||||
|
||||
blob = ink_pen_ellipse (options,
|
||||
paint_core->cur_coords.x,
|
||||
paint_core->cur_coords.y,
|
||||
paint_core->cur_coords.pressure,
|
||||
paint_core->cur_coords.xtilt,
|
||||
paint_core->cur_coords.ytilt,
|
||||
velocity);
|
||||
paint_core->cur_coords.velocity * 100);
|
||||
|
||||
blob_union = blob_convex_union (ink->last_blob, blob);
|
||||
g_free (ink->last_blob);
|
||||
|
@ -510,84 +456,6 @@ ink_pen_ellipse (GimpInkOptions *options,
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
time_smoother_init (GimpInk *ink,
|
||||
guint32 initval)
|
||||
{
|
||||
gint i;
|
||||
|
||||
ink->ts_index = 0;
|
||||
|
||||
for (i = 0; i < TIME_SMOOTHER_BUFFER; i++)
|
||||
ink->ts_buffer[i] = initval;
|
||||
}
|
||||
|
||||
static guint32
|
||||
time_smoother_result (GimpInk *ink)
|
||||
{
|
||||
guint64 result = 0;
|
||||
gint i;
|
||||
|
||||
for (i = 0; i < TIME_SMOOTHER_BUFFER; i++)
|
||||
result += ink->ts_buffer[i];
|
||||
|
||||
return (result / (guint64) TIME_SMOOTHER_BUFFER);
|
||||
}
|
||||
|
||||
static void
|
||||
time_smoother_add (GimpInk *ink,
|
||||
guint32 value)
|
||||
{
|
||||
guint64 long_value = (guint64) value;
|
||||
|
||||
/* handle wrap-around of time values */
|
||||
if (long_value < ink->ts_buffer[ink->ts_index])
|
||||
long_value += (guint64) + G_MAXUINT32;
|
||||
|
||||
ink->ts_buffer[ink->ts_index++] = long_value;
|
||||
|
||||
ink->ts_buffer[ink->ts_index++] = value;
|
||||
|
||||
if (ink->ts_index == TIME_SMOOTHER_BUFFER)
|
||||
ink->ts_index = 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
dist_smoother_init (GimpInk *ink,
|
||||
gdouble initval)
|
||||
{
|
||||
gint i;
|
||||
|
||||
ink->dt_index = 0;
|
||||
|
||||
for (i = 0; i < DIST_SMOOTHER_BUFFER; i++)
|
||||
ink->dt_buffer[i] = initval;
|
||||
}
|
||||
|
||||
static gdouble
|
||||
dist_smoother_result (GimpInk *ink)
|
||||
{
|
||||
gint i;
|
||||
gdouble result = 0.0;
|
||||
|
||||
for (i = 0; i < DIST_SMOOTHER_BUFFER; i++)
|
||||
result += ink->dt_buffer[i];
|
||||
|
||||
return (result / (gdouble) DIST_SMOOTHER_BUFFER);
|
||||
}
|
||||
|
||||
static void
|
||||
dist_smoother_add (GimpInk *ink,
|
||||
gdouble value)
|
||||
{
|
||||
ink->dt_buffer[ink->dt_index++] = value;
|
||||
|
||||
if (ink->dt_index == DIST_SMOOTHER_BUFFER)
|
||||
ink->dt_index = 0;
|
||||
}
|
||||
|
||||
|
||||
/*********************************/
|
||||
/* Rendering functions */
|
||||
/*********************************/
|
||||
|
|
|
@ -24,10 +24,6 @@
|
|||
#include "gimpink-blob.h"
|
||||
|
||||
|
||||
#define DIST_SMOOTHER_BUFFER 10
|
||||
#define TIME_SMOOTHER_BUFFER 10
|
||||
|
||||
|
||||
#define GIMP_TYPE_INK (gimp_ink_get_type ())
|
||||
#define GIMP_INK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_INK, GimpInk))
|
||||
#define GIMP_INK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_INK, GimpInkClass))
|
||||
|
@ -46,18 +42,6 @@ struct _GimpInk
|
|||
|
||||
Blob *cur_blob; /* current blob */
|
||||
Blob *last_blob; /* blob for last cursor position */
|
||||
|
||||
/* circular distance history buffer */
|
||||
gdouble dt_buffer[DIST_SMOOTHER_BUFFER];
|
||||
gint dt_index;
|
||||
|
||||
/* circular timing history buffer */
|
||||
guint32 ts_buffer[TIME_SMOOTHER_BUFFER];
|
||||
gint ts_index;
|
||||
|
||||
guint32 last_time; /* previous time of a motion event */
|
||||
|
||||
gboolean init_velocity;
|
||||
};
|
||||
|
||||
struct _GimpInkClass
|
||||
|
|
|
@ -82,20 +82,6 @@ gimp_ink_undo_constructor (GType type,
|
|||
if (ink->start_blob)
|
||||
ink_undo->last_blob = blob_duplicate (ink->start_blob);
|
||||
|
||||
memcpy (ink_undo->dt_buffer, ink->dt_buffer,
|
||||
sizeof (ink_undo->dt_buffer));
|
||||
|
||||
ink_undo->dt_index = ink->dt_index;
|
||||
|
||||
memcpy (ink_undo->ts_buffer, ink->ts_buffer,
|
||||
sizeof (ink_undo->ts_buffer));
|
||||
|
||||
ink_undo->ts_index = ink->ts_index;
|
||||
|
||||
ink_undo->last_time = ink->last_time;
|
||||
|
||||
ink_undo->init_velocity = ink->init_velocity;
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
|
@ -112,44 +98,11 @@ gimp_ink_undo_pop (GimpUndo *undo,
|
|||
{
|
||||
GimpInk *ink = GIMP_INK (GIMP_PAINT_CORE_UNDO (ink_undo)->paint_core);
|
||||
Blob *tmp_blob;
|
||||
gint tmp_int;
|
||||
gdouble tmp_double;
|
||||
guint32 tmp_int_buf[DIST_SMOOTHER_BUFFER];
|
||||
gdouble tmp_double_buf[DIST_SMOOTHER_BUFFER];
|
||||
|
||||
tmp_blob = ink->last_blob;
|
||||
ink->last_blob = ink_undo->last_blob;
|
||||
ink_undo->last_blob = tmp_blob;
|
||||
|
||||
memcpy (tmp_double_buf, ink->dt_buffer,
|
||||
sizeof (tmp_double_buf));
|
||||
memcpy (ink->dt_buffer, ink_undo->dt_buffer,
|
||||
sizeof (tmp_double_buf));
|
||||
memcpy (ink_undo->dt_buffer, tmp_double_buf,
|
||||
sizeof (tmp_double_buf));
|
||||
|
||||
tmp_int = ink->dt_index;
|
||||
ink->dt_index = ink_undo->dt_index;
|
||||
ink_undo->dt_index = tmp_int;
|
||||
|
||||
memcpy (tmp_int_buf, ink->ts_buffer,
|
||||
sizeof (tmp_int_buf));
|
||||
memcpy (ink->ts_buffer, ink_undo->ts_buffer,
|
||||
sizeof (tmp_int_buf));
|
||||
memcpy (ink_undo->ts_buffer, tmp_int_buf,
|
||||
sizeof (tmp_int_buf));
|
||||
|
||||
tmp_int = ink->ts_index;
|
||||
ink->ts_index = ink_undo->ts_index;
|
||||
ink_undo->ts_index = tmp_int;
|
||||
|
||||
tmp_double = ink->last_time;
|
||||
ink->last_time = ink_undo->last_time;
|
||||
ink_undo->last_time = tmp_double;
|
||||
|
||||
tmp_int = ink->init_velocity;
|
||||
ink->init_velocity = ink_undo->init_velocity;
|
||||
ink_undo->init_velocity = tmp_int;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -38,16 +38,6 @@ struct _GimpInkUndo
|
|||
GimpPaintCoreUndo parent_instance;
|
||||
|
||||
Blob *last_blob;
|
||||
|
||||
gdouble dt_buffer[DIST_SMOOTHER_BUFFER];
|
||||
gint dt_index;
|
||||
|
||||
guint32 ts_buffer[TIME_SMOOTHER_BUFFER];
|
||||
gint ts_index;
|
||||
|
||||
gdouble last_time;
|
||||
|
||||
gboolean init_velocity;
|
||||
};
|
||||
|
||||
struct _GimpInkUndoClass
|
||||
|
|
Loading…
Reference in New Issue