mirror of https://github.com/GNOME/gimp.git
Bug 471344 – Circular brush strokes are not smooth and have corners
2009-01-10 Sven Neumann <sven@gimp.org> Bug 471344 – Circular brush strokes are not smooth and have corners Bug 127785 – stroking with size linked to pressure sensitivity should scale the spacing * app/core/gimpcoords-interpolate.[ch] * app/display/gimpdisplayshell.[ch] * app/display/gimpdisplayshell-callbacks.[ch] * app/display/gimpdisplayshell-coords.[ch]: applied patch from Alexia Death that introduces a Catmul-Rom splines based event interpolation and also adapts the brush spacing to brush size. svn path=/trunk/; revision=27898
This commit is contained in:
parent
eeae281bc0
commit
f171d10506
23
ChangeLog
23
ChangeLog
|
@ -1,3 +1,26 @@
|
|||
2009-01-10 Sven Neumann <sven@gimp.org>
|
||||
|
||||
Bug 471344 – Circular brush strokes are not smooth and have corners
|
||||
|
||||
Bug 127785 – stroking with size linked to pressure sensitivity
|
||||
should scale the spacing
|
||||
|
||||
* app/core/gimpcoords-interpolate.[ch]
|
||||
* app/display/gimpdisplayshell.[ch]
|
||||
* app/display/gimpdisplayshell-callbacks.[ch]
|
||||
* app/display/gimpdisplayshell-coords.[ch]: applied patch from
|
||||
Alexia Death that introduces a Catmul-Rom splines based event
|
||||
interpolation and also adapts the brush spacing to brush size.
|
||||
|
||||
2009-01-06 Sven Neumann <sven@gimp.org>
|
||||
|
||||
Bug 565046 – Point snapping to guides does not work outside the
|
||||
canvas
|
||||
|
||||
* app/core/gimpimage-snap.c: applied patch from Daniel Hornung
|
||||
that introduces the utility function gimp_image_snap_grid() to
|
||||
clean up and fix guide snapping.
|
||||
|
||||
2009-01-06 Sven Neumann <sven@gimp.org>
|
||||
|
||||
Bug 566498 – Noise distribution error in RGB Noise and HSV Noise
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "gimpcoords.h"
|
||||
#include "gimpcoords-interpolate.h"
|
||||
|
||||
|
||||
/* Local helper functions declarations*/
|
||||
static void gimp_coords_interpolate_bezier_internal (const GimpCoords bezier_pt1,
|
||||
const GimpCoords bezier_pt2,
|
||||
|
@ -40,6 +41,11 @@ static void gimp_coords_interpolate_bezier_internal (const GimpCoords bezie
|
|||
GArray **ret_coords,
|
||||
GArray **ret_params,
|
||||
gint depth);
|
||||
static gdouble gimp_coords_get_catmull_spline_point (gdouble t,
|
||||
gdouble p0,
|
||||
gdouble p1,
|
||||
gdouble p2,
|
||||
gdouble p3);
|
||||
|
||||
/* Functions for bezier subdivision */
|
||||
|
||||
|
@ -190,7 +196,7 @@ gimp_coords_bezier_is_straight (const GimpCoords bezier_pt1,
|
|||
const GimpCoords bezier_pt2,
|
||||
const GimpCoords bezier_pt3,
|
||||
const GimpCoords bezier_pt4,
|
||||
gdouble precision)
|
||||
gdouble precision)
|
||||
{
|
||||
GimpCoords pt1, pt2;
|
||||
|
||||
|
@ -208,3 +214,116 @@ gimp_coords_bezier_is_straight (const GimpCoords bezier_pt1,
|
|||
return (gimp_coords_manhattan_dist (&bezier_pt2, &pt1) < precision &&
|
||||
gimp_coords_manhattan_dist (&bezier_pt3, &pt2) < precision);
|
||||
}
|
||||
|
||||
|
||||
/* Functions for camull-rom interpolation */
|
||||
|
||||
void
|
||||
gimp_coords_interpolate_catmull (const GimpCoords catmul_pt1,
|
||||
const GimpCoords catmul_pt2,
|
||||
const GimpCoords catmul_pt3,
|
||||
const GimpCoords catmul_pt4,
|
||||
gdouble precision,
|
||||
GArray **ret_coords,
|
||||
GArray **ret_params)
|
||||
{
|
||||
gdouble delta_x, delta_y;
|
||||
gdouble distance;
|
||||
gint num_points;
|
||||
gint n;
|
||||
|
||||
GimpCoords past_coords;
|
||||
GimpCoords start_coords;
|
||||
GimpCoords end_coords;
|
||||
GimpCoords future_coords;
|
||||
|
||||
delta_x = catmul_pt3.x - catmul_pt2.x;
|
||||
delta_y = catmul_pt3.y - catmul_pt2.y;
|
||||
|
||||
/* Catmull-Rom interpolation requires 4 points.
|
||||
* Two endpoints plus one more at each end.
|
||||
*/
|
||||
|
||||
past_coords = catmul_pt1;
|
||||
start_coords = catmul_pt2;
|
||||
end_coords = catmul_pt3;
|
||||
future_coords = catmul_pt4;
|
||||
|
||||
distance = sqrt (SQR (delta_x) + SQR (delta_y));
|
||||
|
||||
num_points = distance / precision;
|
||||
|
||||
for (n = 1; n <=num_points; n++)
|
||||
{
|
||||
GimpCoords res_coords;
|
||||
gdouble velocity;
|
||||
gdouble p = (gdouble) n / num_points;
|
||||
|
||||
res_coords.x =
|
||||
gimp_coords_get_catmull_spline_point (p,
|
||||
past_coords.x,
|
||||
start_coords.x,
|
||||
end_coords.x,
|
||||
future_coords.x);
|
||||
|
||||
res_coords.y =
|
||||
gimp_coords_get_catmull_spline_point (p,
|
||||
past_coords.y,
|
||||
start_coords.y,
|
||||
end_coords.y,
|
||||
future_coords.y);
|
||||
|
||||
res_coords.pressure =
|
||||
gimp_coords_get_catmull_spline_point (p,
|
||||
past_coords.pressure,
|
||||
start_coords.pressure,
|
||||
end_coords.pressure,
|
||||
future_coords.pressure);
|
||||
|
||||
res_coords.xtilt =
|
||||
gimp_coords_get_catmull_spline_point (p,
|
||||
past_coords.xtilt,
|
||||
start_coords.xtilt,
|
||||
end_coords.xtilt,
|
||||
future_coords.xtilt);
|
||||
res_coords.ytilt =
|
||||
gimp_coords_get_catmull_spline_point (p,
|
||||
past_coords.ytilt,
|
||||
start_coords.ytilt,
|
||||
end_coords.ytilt,
|
||||
future_coords.ytilt);
|
||||
|
||||
res_coords.wheel =
|
||||
gimp_coords_get_catmull_spline_point (p,
|
||||
past_coords.wheel,
|
||||
start_coords.wheel,
|
||||
end_coords.wheel,
|
||||
future_coords.wheel);
|
||||
|
||||
velocity = gimp_coords_get_catmull_spline_point (p,
|
||||
past_coords.velocity,
|
||||
start_coords.velocity,
|
||||
end_coords.velocity,
|
||||
future_coords.velocity);
|
||||
res_coords.velocity = CLAMP (velocity, 0.0, 1.0);
|
||||
|
||||
g_array_append_val (*ret_coords, res_coords);
|
||||
|
||||
if (ret_params)
|
||||
g_array_append_val (*ret_params, p);
|
||||
}
|
||||
}
|
||||
|
||||
static gdouble
|
||||
gimp_coords_get_catmull_spline_point (gdouble t,
|
||||
gdouble p0,
|
||||
gdouble p1,
|
||||
gdouble p2,
|
||||
gdouble p3)
|
||||
{
|
||||
|
||||
return ((((-t + 2.0) * t - 1.0) * t / 2.0) * p0 +
|
||||
((((3.0 * t - 5.0) * t) * t + 2.0) / 2.0) * p1 +
|
||||
(((-3.0 * t + 4.0) * t + 1.0) * t / 2.0) * p2 +
|
||||
(((t - 1) * t * t) / 2.0) * p3);
|
||||
}
|
||||
|
|
|
@ -21,18 +21,26 @@
|
|||
#ifndef __GIMP_COORDS_INTERPOLATE_H__
|
||||
#define __GIMP_COORDS_INTERPOLATE_H__
|
||||
|
||||
void gimp_coords_interpolate_bezier (const GimpCoords bezier_pt1,
|
||||
const GimpCoords bezier_pt2,
|
||||
const GimpCoords bezier_pt3,
|
||||
const GimpCoords bezier_pt4,
|
||||
gdouble precision,
|
||||
GArray **ret_coords,
|
||||
GArray **ret_params);
|
||||
void gimp_coords_interpolate_bezier (const GimpCoords bezier_pt1,
|
||||
const GimpCoords bezier_pt2,
|
||||
const GimpCoords bezier_pt3,
|
||||
const GimpCoords bezier_pt4,
|
||||
gdouble precision,
|
||||
GArray **ret_coords,
|
||||
GArray **ret_params);
|
||||
|
||||
gboolean gimp_coords_bezier_is_straight (const GimpCoords bezier_pt1,
|
||||
const GimpCoords bezier_pt2,
|
||||
const GimpCoords bezier_pt3,
|
||||
const GimpCoords bezier_pt4,
|
||||
gdouble precision);
|
||||
gboolean gimp_coords_bezier_is_straight (const GimpCoords bezier_pt1,
|
||||
const GimpCoords bezier_pt2,
|
||||
const GimpCoords bezier_pt3,
|
||||
const GimpCoords bezier_pt4,
|
||||
gdouble precision);
|
||||
|
||||
void gimp_coords_interpolate_catmull (const GimpCoords catmul_pt1,
|
||||
const GimpCoords catmul_pt2,
|
||||
const GimpCoords catmul_pt3,
|
||||
const GimpCoords catmul_pt4,
|
||||
gdouble precision,
|
||||
GArray **ret_coords,
|
||||
GArray **ret_params);
|
||||
|
||||
#endif /* __GIMP_COORDS_INTERPOLATE_H__ */
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "tools/gimppainttool.h"
|
||||
#include "tools/gimptoolcontrol.h"
|
||||
#include "tools/tool_manager.h"
|
||||
#include "tools/tools-enums.h"
|
||||
|
||||
#include "widgets/gimpcontrollers.h"
|
||||
#include "widgets/gimpcontrollerkeyboard.h"
|
||||
|
@ -80,28 +81,31 @@
|
|||
|
||||
/* local function prototypes */
|
||||
|
||||
static void gimp_display_shell_vscrollbar_update (GtkAdjustment *adjustment,
|
||||
GimpDisplayShell *shell);
|
||||
static void gimp_display_shell_hscrollbar_update (GtkAdjustment *adjustment,
|
||||
GimpDisplayShell *shell);
|
||||
static gboolean gimp_display_shell_vscrollbar_update_range (GtkRange *range,
|
||||
GtkScrollType scroll,
|
||||
gdouble value,
|
||||
GimpDisplayShell *shell);
|
||||
static void gimp_display_shell_vscrollbar_update (GtkAdjustment *adjustment,
|
||||
GimpDisplayShell *shell);
|
||||
static void gimp_display_shell_hscrollbar_update (GtkAdjustment *adjustment,
|
||||
GimpDisplayShell *shell);
|
||||
static gboolean gimp_display_shell_vscrollbar_update_range (GtkRange *range,
|
||||
GtkScrollType scroll,
|
||||
gdouble value,
|
||||
GimpDisplayShell *shell);
|
||||
|
||||
static gboolean gimp_display_shell_hscrollbar_update_range (GtkRange *range,
|
||||
GtkScrollType scroll,
|
||||
gdouble value,
|
||||
GimpDisplayShell *shell);
|
||||
static gboolean gimp_display_shell_hscrollbar_update_range (GtkRange *range,
|
||||
GtkScrollType scroll,
|
||||
gdouble value,
|
||||
GimpDisplayShell *shell);
|
||||
static GdkModifierType
|
||||
gimp_display_shell_key_to_state (gint key);
|
||||
gimp_display_shell_key_to_state (gint key);
|
||||
|
||||
static GdkEvent * gimp_display_shell_compress_motion (GimpDisplayShell *shell);
|
||||
static GdkEvent * gimp_display_shell_compress_motion (GimpDisplayShell *shell);
|
||||
|
||||
static void gimp_display_shell_canvas_expose_image (GimpDisplayShell *shell,
|
||||
GdkEventExpose *eevent);
|
||||
static void gimp_display_shell_canvas_expose_drop_zone (GimpDisplayShell *shell,
|
||||
GdkEventExpose *eevent);
|
||||
static void gimp_display_shell_canvas_expose_image (GimpDisplayShell *shell,
|
||||
GdkEventExpose *eevent);
|
||||
static void gimp_display_shell_canvas_expose_drop_zone (GimpDisplayShell *shell,
|
||||
GdkEventExpose *eevent);
|
||||
static void gimp_display_shell_process_tool_event_queue (GimpDisplayShell *shell,
|
||||
GdkModifierType state,
|
||||
guint32 time);
|
||||
|
||||
|
||||
/* public functions */
|
||||
|
@ -1002,6 +1006,10 @@ gimp_display_shell_canvas_tool_events (GtkWidget *canvas,
|
|||
{
|
||||
if (gimp_tool_control_is_active (active_tool->control))
|
||||
{
|
||||
|
||||
if (shell->event_queue->len > 0)
|
||||
gimp_display_shell_flush_event_queue (shell);
|
||||
|
||||
tool_manager_button_release_active (gimp,
|
||||
&image_coords,
|
||||
time, state,
|
||||
|
@ -1253,8 +1261,11 @@ gimp_display_shell_canvas_tool_events (GtkWidget *canvas,
|
|||
{
|
||||
gint i;
|
||||
|
||||
tool_manager_control_active (gimp, GIMP_TOOL_ACTION_PAUSE, display);
|
||||
|
||||
for (i = 0; i < n_history_events; i++)
|
||||
{
|
||||
|
||||
gimp_display_shell_get_time_coords (shell,
|
||||
mevent->device,
|
||||
history_events[i],
|
||||
|
@ -1286,20 +1297,21 @@ gimp_display_shell_canvas_tool_events (GtkWidget *canvas,
|
|||
active_tool->max_coord_smooth,
|
||||
history_events[i]->time))
|
||||
{
|
||||
tool_manager_motion_active (gimp,
|
||||
&image_coords,
|
||||
history_events[i]->time,
|
||||
state,
|
||||
display);
|
||||
gimp_display_shell_process_tool_event_queue (shell,
|
||||
state,
|
||||
history_events[i]->time);
|
||||
}
|
||||
|
||||
shell->last_read_motion_time = history_events[i]->time;
|
||||
}
|
||||
|
||||
tool_manager_control_active (gimp, GIMP_TOOL_ACTION_RESUME, display);
|
||||
|
||||
gdk_device_free_history (history_events, n_history_events);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Early removal of useless events saves CPU time.
|
||||
*/
|
||||
if (gimp_display_shell_eval_event (shell,
|
||||
|
@ -1307,11 +1319,9 @@ gimp_display_shell_canvas_tool_events (GtkWidget *canvas,
|
|||
active_tool->max_coord_smooth,
|
||||
time))
|
||||
{
|
||||
tool_manager_motion_active (gimp,
|
||||
&image_coords,
|
||||
time,
|
||||
state,
|
||||
display);
|
||||
gimp_display_shell_process_tool_event_queue (shell,
|
||||
state,
|
||||
time);
|
||||
}
|
||||
|
||||
shell->last_read_motion_time = time;
|
||||
|
@ -1325,17 +1335,25 @@ 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,
|
||||
&image_coords,
|
||||
0.0,
|
||||
time))
|
||||
{
|
||||
tool_manager_oper_update_active (gimp,
|
||||
&image_coords, state,
|
||||
shell->proximity,
|
||||
display);
|
||||
/* then update the tool. */
|
||||
GimpCoords *buf_coords = &g_array_index (shell->event_queue,
|
||||
GimpCoords, 0);
|
||||
tool_manager_oper_update_active (gimp,
|
||||
buf_coords, state,
|
||||
shell->proximity,
|
||||
display);
|
||||
/* remove used event */
|
||||
g_array_remove_index (shell->event_queue, 0);
|
||||
|
||||
}
|
||||
|
||||
gimp_display_shell_push_event_history (shell, &image_coords);
|
||||
shell->last_read_motion_time = time;
|
||||
}
|
||||
|
||||
|
@ -1778,7 +1796,97 @@ gimp_display_shell_nav_button_press (GtkWidget *widget,
|
|||
}
|
||||
|
||||
|
||||
/* Event delay timeout handler & generic event flusher */
|
||||
gboolean
|
||||
gimp_display_shell_flush_event_queue (GimpDisplayShell *shell)
|
||||
{
|
||||
|
||||
GimpTool *active_tool = tool_manager_get_active (shell->display->gimp);
|
||||
|
||||
shell->event_delay = FALSE;
|
||||
|
||||
/* Set the timeout id to 0 */
|
||||
shell->event_delay_timeout = 0;
|
||||
|
||||
if (active_tool &&
|
||||
gimp_tool_control_is_active (active_tool->control) &&
|
||||
shell->event_queue->len > 0)
|
||||
{
|
||||
GimpCoords last_coords = g_array_index (shell->event_queue,
|
||||
GimpCoords, shell->event_queue->len - 1 );
|
||||
|
||||
gimp_display_shell_push_event_history (shell, &last_coords);
|
||||
|
||||
gimp_display_shell_process_tool_event_queue (shell,
|
||||
shell->last_active_state,
|
||||
shell->last_read_motion_time);
|
||||
}
|
||||
|
||||
/* Return false so a potential timeout calling it gets removed */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* private functions */
|
||||
static void
|
||||
gimp_display_shell_process_tool_event_queue (GimpDisplayShell *shell,
|
||||
GdkModifierType state,
|
||||
guint32 time)
|
||||
{
|
||||
gint i;
|
||||
gint keep = 0;
|
||||
GdkModifierType event_state;
|
||||
GimpCoords keep_event;
|
||||
GimpCoords *buf_coords = NULL;
|
||||
|
||||
if (shell->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 );
|
||||
}
|
||||
else
|
||||
{
|
||||
event_state = state; /* Save the state */
|
||||
}
|
||||
|
||||
if (shell->event_delay_timeout != 0)
|
||||
g_source_remove (shell->event_delay_timeout);
|
||||
|
||||
shell->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++)
|
||||
{
|
||||
buf_coords = &g_array_index (shell->event_queue, GimpCoords, i);
|
||||
|
||||
tool_manager_motion_active (shell->display->gimp,
|
||||
buf_coords,
|
||||
time,
|
||||
event_state,
|
||||
shell->display);
|
||||
|
||||
}
|
||||
|
||||
tool_manager_control_active (shell->display->gimp,
|
||||
GIMP_TOOL_ACTION_RESUME, shell->display);
|
||||
|
||||
g_array_set_size (shell->event_queue, 0);
|
||||
|
||||
if (shell->event_delay)
|
||||
{
|
||||
g_array_append_val (shell->event_queue, keep_event);
|
||||
|
||||
shell->event_delay_timeout =
|
||||
g_timeout_add (50,
|
||||
(GSourceFunc) gimp_display_shell_flush_event_queue,
|
||||
shell);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_display_shell_vscrollbar_update (GtkAdjustment *adjustment,
|
||||
|
|
|
@ -56,6 +56,7 @@ void gimp_display_shell_quick_mask_toggled (GtkWidget *widget,
|
|||
gboolean gimp_display_shell_nav_button_press (GtkWidget *widget,
|
||||
GdkEventButton *bevent,
|
||||
GimpDisplayShell *shell);
|
||||
gboolean gimp_display_shell_flush_event_queue (GimpDisplayShell *shell);
|
||||
|
||||
|
||||
#endif /* __GIMP_DISPLAY_SHELL_CALLBACKS_H__ */
|
||||
|
|
|
@ -27,9 +27,16 @@
|
|||
#include "gimpdisplayshell.h"
|
||||
#include "gimpdisplayshell-coords.h"
|
||||
|
||||
#include "core/gimpcoords-interpolate.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
|
||||
|
||||
static void gimp_display_shell_interpolate_stroke (GimpDisplayShell *shell,
|
||||
GimpCoords *coords);
|
||||
|
||||
/* public functions */
|
||||
|
||||
gboolean
|
||||
|
@ -210,13 +217,14 @@ gimp_display_shell_get_device_state (GimpDisplayShell *shell,
|
|||
gboolean
|
||||
gimp_display_shell_eval_event (GimpDisplayShell *shell,
|
||||
GimpCoords *coords,
|
||||
gdouble inertia_factor,
|
||||
guint32 time)
|
||||
gdouble inertia_factor,
|
||||
guint32 time)
|
||||
{
|
||||
gdouble delta_time = 0.001;
|
||||
gdouble delta_x = 0.0;
|
||||
gdouble delta_y = 0.0;
|
||||
gdouble distance = 1.0;
|
||||
gdouble delta_time = 0.001;
|
||||
gdouble delta_x = 0.0;
|
||||
gdouble delta_y = 0.0;
|
||||
gdouble distance = 1.0;
|
||||
gboolean event_fill = (inertia_factor > 0);
|
||||
|
||||
/* Smoothing causes problems with cursor tracking
|
||||
* when zoomed above screen resolution so we need to supress it.
|
||||
|
@ -340,18 +348,48 @@ gimp_display_shell_eval_event (GimpDisplayShell *shell,
|
|||
distance = sqrt (SQR (delta_x) + SQR (delta_y));
|
||||
}
|
||||
|
||||
/* do event fill for devices that do not provide enough events*/
|
||||
|
||||
if (distance >= EVENT_FILL_PRECISION &&
|
||||
event_fill &&
|
||||
shell->event_history->len >= 2)
|
||||
{
|
||||
if (shell->event_delay)
|
||||
{
|
||||
gimp_display_shell_interpolate_stroke (shell,
|
||||
coords);
|
||||
}
|
||||
else
|
||||
{
|
||||
shell->event_delay = TRUE;
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (shell->event_delay)
|
||||
{
|
||||
shell->event_delay = FALSE;
|
||||
|
||||
}
|
||||
gimp_display_shell_push_event_history (shell, coords);
|
||||
|
||||
|
||||
}
|
||||
|
||||
#ifdef VERBOSE
|
||||
g_printerr ("DIST: %f, DT:%f, Vel:%f, Press:%f,smooth_dd:%f, sf %f\n",
|
||||
distance,
|
||||
delta_time,
|
||||
shell->last_coords.velocity,
|
||||
coords->pressure,
|
||||
coords->distance - dist,
|
||||
distance - dist,
|
||||
inertia_factor);
|
||||
#endif
|
||||
}
|
||||
|
||||
shell->last_coords = *coords;
|
||||
g_array_append_val (shell->event_queue, *coords);
|
||||
|
||||
shell->last_motion_time = time;
|
||||
shell->last_motion_delta_time = delta_time;
|
||||
|
@ -361,3 +399,51 @@ gimp_display_shell_eval_event (GimpDisplayShell *shell,
|
|||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* Helper function fo managing event history */
|
||||
void
|
||||
gimp_display_shell_push_event_history (GimpDisplayShell *shell,
|
||||
GimpCoords *coords)
|
||||
{
|
||||
if (shell->event_history->len == 4)
|
||||
g_array_remove_index (shell->event_history, 0);
|
||||
g_array_append_val (shell->event_history, *coords);
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_display_shell_interpolate_stroke (GimpDisplayShell *shell,
|
||||
GimpCoords *coords)
|
||||
{
|
||||
GArray *ret_coords;
|
||||
gint i = shell->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.
|
||||
*/
|
||||
ret_coords = g_array_new (FALSE, FALSE, sizeof (GimpCoords));
|
||||
|
||||
gimp_coords_interpolate_catmull (g_array_index (shell->event_history,
|
||||
GimpCoords, i - 1),
|
||||
g_array_index (shell->event_history,
|
||||
GimpCoords, i),
|
||||
g_array_index (shell->event_queue,
|
||||
GimpCoords, 0),
|
||||
*coords,
|
||||
EVENT_FILL_PRECISION / 2,
|
||||
&ret_coords,
|
||||
NULL);
|
||||
|
||||
/* Push the last actual event in history */
|
||||
gimp_display_shell_push_event_history (shell,
|
||||
&g_array_index (shell->event_queue,
|
||||
GimpCoords, 0));
|
||||
|
||||
g_array_set_size(shell->event_queue, 0);
|
||||
|
||||
g_array_append_vals (shell->event_queue,
|
||||
&g_array_index (ret_coords, GimpCoords, 0),
|
||||
ret_coords->len);
|
||||
|
||||
g_array_free(ret_coords, TRUE);
|
||||
}
|
||||
|
|
|
@ -20,28 +20,30 @@
|
|||
#define __GIMP_DISPLAY_SHELL_COORDS_H__
|
||||
|
||||
|
||||
gboolean gimp_display_shell_get_event_coords (GimpDisplayShell *shell,
|
||||
GdkEvent *event,
|
||||
GdkDevice *device,
|
||||
GimpCoords *coords);
|
||||
void gimp_display_shell_get_device_coords (GimpDisplayShell *shell,
|
||||
GdkDevice *device,
|
||||
GimpCoords *coords);
|
||||
void gimp_display_shell_get_time_coords (GimpDisplayShell *shell,
|
||||
GdkDevice *device,
|
||||
GdkTimeCoord *event,
|
||||
GimpCoords *coords);
|
||||
gboolean gimp_display_shell_get_event_state (GimpDisplayShell *shell,
|
||||
GdkEvent *event,
|
||||
GdkDevice *device,
|
||||
GdkModifierType *state);
|
||||
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);
|
||||
gboolean gimp_display_shell_get_event_coords (GimpDisplayShell *shell,
|
||||
GdkEvent *event,
|
||||
GdkDevice *device,
|
||||
GimpCoords *coords);
|
||||
void gimp_display_shell_get_device_coords (GimpDisplayShell *shell,
|
||||
GdkDevice *device,
|
||||
GimpCoords *coords);
|
||||
void gimp_display_shell_get_time_coords (GimpDisplayShell *shell,
|
||||
GdkDevice *device,
|
||||
GdkTimeCoord *event,
|
||||
GimpCoords *coords);
|
||||
gboolean gimp_display_shell_get_event_state (GimpDisplayShell *shell,
|
||||
GdkEvent *event,
|
||||
GdkDevice *device,
|
||||
GdkModifierType *state);
|
||||
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);
|
||||
void gimp_display_shell_push_event_history (GimpDisplayShell *shell,
|
||||
GimpCoords *coords);
|
||||
|
||||
|
||||
#endif /* __GIMP_DISPLAY_SHELL_COORDS_H__ */
|
||||
|
|
|
@ -82,7 +82,6 @@
|
|||
|
||||
#include "gimp-intl.h"
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
|
@ -356,6 +355,17 @@ gimp_display_shell_init (GimpDisplayShell *shell)
|
|||
shell->highlight = NULL;
|
||||
shell->mask = NULL;
|
||||
|
||||
shell->event_history = g_array_new (FALSE, FALSE,
|
||||
sizeof (GimpCoords));
|
||||
shell->event_queue = g_array_new (FALSE, FALSE,
|
||||
sizeof (GimpCoords));
|
||||
shell->event_delay = FALSE;
|
||||
|
||||
shell->event_delay_timeout = 0;
|
||||
|
||||
shell->last_active_state = 0;
|
||||
|
||||
|
||||
gtk_window_set_role (GTK_WINDOW (shell), "gimp-image-window");
|
||||
gtk_window_set_resizable (GTK_WINDOW (shell), TRUE);
|
||||
|
||||
|
@ -498,6 +508,18 @@ gimp_display_shell_destroy (GtkObject *object)
|
|||
shell->mask = NULL;
|
||||
}
|
||||
|
||||
if (shell->event_history)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
if (shell->title_idle_id)
|
||||
{
|
||||
g_source_remove (shell->title_idle_id);
|
||||
|
|
|
@ -206,6 +206,14 @@ struct _GimpDisplayShell
|
|||
GdkRectangle *highlight; /* in image coordinates, can be NULL */
|
||||
GimpDrawable *mask;
|
||||
GimpChannelType mask_color;
|
||||
|
||||
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 _GimpDisplayShellClass
|
||||
|
|
Loading…
Reference in New Issue