Applied slightly modified and fixed patch from Alexia Death which adds a

2008-05-22  Michael Natterer  <mitch@gimp.org>

	Applied slightly modified and fixed patch from Alexia Death which
	adds a "random" axis to the paint dynamics and fixes some issues
	in the previous paint dynamics commits. Fixes bug #529431.

	* app/core/core-types.h: add a "random" axis to GimpCoords.

	* app/display/gimpdisplayshell-coords.c: set it to a random value.

	* app/display/gimpdisplayshell-callbacks.c: on button_press,
	use the dynamics from the last motion event to avoid blotches
	at the beginning of paint strokes.

	* app/paint/gimppaintoptions.[ch]: add random properties the same
	way we do pressure and velocity. Add get_dynamic_size(),
	get_dynamic_color() and get_dynamic_hardness() functions which
	look at all dynamic parameters of the passed coords.

	* app/tools/gimppaintoptions-gui.c: add gui for the random options.

	* app/paint/gimpbrushcore.[ch]: remove calc_brush_scale() and use
	gimp_paint_options_get_dynamic_size_instead().
	Add "dynamic_hardness" parameters to paste_canvas(),
	replace_canvas() and get_brush_mask().

	* app/paint/gimpairbrushoptions.c
	* app/paint/gimpclone.c
	* app/paint/gimpconvolve.c
	* app/paint/gimpdodgeburn.c
	* app/paint/gimperaser.c
	* app/paint/gimpheal.c
	* app/paint/gimppaintbrush.c
	* app/paint/gimpsmudge.c: calculate the dynamic hardness and pass
	it to above brush core functions. Use the get_dynamic_color() to
	calculate the gradient color.


svn path=/trunk/; revision=25758
This commit is contained in:
Michael Natterer 2008-05-22 16:38:57 +00:00 committed by Michael Natterer
parent ea80388073
commit fe70064f00
17 changed files with 548 additions and 146 deletions

View File

@ -1,3 +1,40 @@
2008-05-22 Michael Natterer <mitch@gimp.org>
Applied slightly modified and fixed patch from Alexia Death which
adds a "random" axis to the paint dynamics and fixes some issues
in the previous paint dynamics commits. Fixes bug #529431.
* app/core/core-types.h: add a "random" axis to GimpCoords.
* app/display/gimpdisplayshell-coords.c: set it to a random value.
* app/display/gimpdisplayshell-callbacks.c: on button_press,
use the dynamics from the last motion event to avoid blotches
at the beginning of paint strokes.
* app/paint/gimppaintoptions.[ch]: add random properties the same
way we do pressure and velocity. Add get_dynamic_size(),
get_dynamic_color() and get_dynamic_hardness() functions which
look at all dynamic parameters of the passed coords.
* app/tools/gimppaintoptions-gui.c: add gui for the random options.
* app/paint/gimpbrushcore.[ch]: remove calc_brush_scale() and use
gimp_paint_options_get_dynamic_size_instead().
Add "dynamic_hardness" parameters to paste_canvas(),
replace_canvas() and get_brush_mask().
* app/paint/gimpairbrushoptions.c
* app/paint/gimpclone.c
* app/paint/gimpconvolve.c
* app/paint/gimpdodgeburn.c
* app/paint/gimperaser.c
* app/paint/gimpheal.c
* app/paint/gimppaintbrush.c
* app/paint/gimpsmudge.c: calculate the dynamic hardness and pass
it to above brush core functions. Use the get_dynamic_color() to
calculate the gradient color.
2008-05-22 Sven Neumann <sven@gimp.org>
* app/tools/gimpposterizetool.c (gimp_posterize_tool_dialog):

View File

@ -204,6 +204,7 @@ struct _GimpCoords
gdouble delta_y;
gdouble distance;
gdouble velocity;
gdouble random;
};

View File

@ -810,6 +810,23 @@ gimp_display_shell_canvas_tool_events (GtkWidget *canvas,
if (initialized)
{
/* Use the last evaluated dynamic axes instead of
* the button_press event's ones because the click
* is usually at the same spot as the last motion
* event which would give us bogus dynamics.
*/
GimpCoords tmp_coords;
tmp_coords = shell->last_coords;
tmp_coords.x = image_coords.x;
tmp_coords.y = image_coords.y;
tmp_coords.pressure = image_coords.pressure;
tmp_coords.xtilt = image_coords.xtilt;
tmp_coords.ytilt = image_coords.ytilt;
image_coords = tmp_coords;
tool_manager_button_press_active (gimp,
&image_coords,
time, state, display);

View File

@ -226,7 +226,7 @@ gimp_display_shell_eval_event (GimpDisplayShell *shell,
/* First pair is invalid to do any velocity calculation,
* so we apply constant values.
*/
coords->velocity = 100;
coords->velocity = 1.0;
coords->delta_time = 0.001;
coords->distance = 1;
}
@ -252,6 +252,8 @@ gimp_display_shell_eval_event (GimpDisplayShell *shell,
+ coords->delta_time * SMOOTH_FACTOR);
coords->distance = dist = sqrt (SQR (dx) + SQR (dy));
coords->random = g_random_double_range (0.0, 1.0);
/* If even smoothed time resolution does not allow to guess for speed,
* use last velocity.
*/

View File

@ -36,7 +36,8 @@ enum
PROP_0,
PROP_RATE,
PROP_PRESSURE,
PROP_VELOCITY_SIZE
PROP_VELOCITY_SIZE,
PROP_VELOCITY_HARDNESS
};
@ -71,11 +72,17 @@ gimp_airbrush_options_class_init (GimpAirbrushOptionsClass *klass)
0.0, 100.0, AIRBRUSH_DEFAULT_PRESSURE,
GIMP_PARAM_STATIC_STRINGS);
/* override velocity size because its unavaliable to the airbrush */
/* override velocity size because its unnatural as a default for airbrush */
GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_VELOCITY_SIZE,
"velocity-size", NULL,
FALSE,
GIMP_PARAM_STATIC_STRINGS);
/* override velocity hardness to default to a true, because that is natural for airbrush */
GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_VELOCITY_HARDNESS,
"velocity-hardness", NULL,
TRUE,
GIMP_PARAM_STATIC_STRINGS);
}
static void
@ -102,6 +109,9 @@ gimp_airbrush_options_set_property (GObject *object,
case PROP_VELOCITY_SIZE:
GIMP_PAINT_OPTIONS (options)->velocity_options->size = g_value_get_boolean (value);
break;
case PROP_VELOCITY_HARDNESS:
GIMP_PAINT_OPTIONS (options)->velocity_options->hardness = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@ -128,6 +138,9 @@ gimp_airbrush_options_get_property (GObject *object,
case PROP_VELOCITY_SIZE:
g_value_set_boolean (value, GIMP_PAINT_OPTIONS (options)->velocity_options->size);
break;
case PROP_VELOCITY_HARDNESS:
g_value_set_boolean (value, GIMP_PAINT_OPTIONS (options)->velocity_options->hardness);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);

View File

@ -85,11 +85,6 @@ static TempBuf *gimp_brush_core_get_paint_area (GimpPaintCore *paint_core,
static void gimp_brush_core_real_set_brush (GimpBrushCore *core,
GimpBrush *brush);
static gdouble gimp_brush_core_calc_brush_scale (GimpBrushCore *core,
GimpPaintOptions *paint_options,
gdouble pressure,
gdouble velocity);
static inline void rotate_pointers (gulong **p,
guint32 n);
static TempBuf * gimp_brush_core_subsample_mask (GimpBrushCore *core,
@ -358,9 +353,10 @@ gimp_brush_core_start (GimpPaintCore *paint_core,
return FALSE;
}
core->scale = gimp_brush_core_calc_brush_scale (core, paint_options,
coords->pressure,
coords->velocity);
core->scale = gimp_paint_options_get_dynamic_size (paint_options,
coords,
paint_core->use_pressure,
GIMP_BRUSH_CORE_GET_CLASS (core)->handles_scaling_brush);
core->spacing = (gdouble) gimp_brush_get_spacing (core->main_brush) / 100.0;
@ -673,6 +669,7 @@ gimp_brush_core_interpolate (GimpPaintCore *paint_core,
paint_core->cur_coords.ytilt = paint_core->last_coords.ytilt + delta_ytilt;
paint_core->cur_coords.wheel = paint_core->last_coords.wheel + delta_wheel;
paint_core->cur_coords.velocity = paint_core->last_coords.velocity + delta_velocity;
paint_core->cur_coords.random = g_random_double_range (0.0, 1.0);
paint_core->distance = total;
paint_core->pixel_dist = pixel_initial + pixel_dist;
@ -693,9 +690,10 @@ gimp_brush_core_get_paint_area (GimpPaintCore *paint_core,
if (GIMP_BRUSH_CORE_GET_CLASS (core)->handles_scaling_brush)
{
core->scale = gimp_brush_core_calc_brush_scale (core, paint_options,
paint_core->cur_coords.pressure,
paint_core->cur_coords.velocity);
core->scale = gimp_paint_options_get_dynamic_size (paint_options,
&paint_core->cur_coords,
paint_core->use_pressure,
TRUE);
}
/* else use scale from start(), we don't support on-the-fly scaling */
@ -833,10 +831,12 @@ gimp_brush_core_paste_canvas (GimpBrushCore *core,
gdouble image_opacity,
GimpLayerModeEffects paint_mode,
GimpBrushApplicationMode brush_hardness,
gdouble dynamic_hardness,
GimpPaintApplicationMode mode)
{
TempBuf *brush_mask = gimp_brush_core_get_brush_mask (core,
brush_hardness);
brush_hardness,
dynamic_hardness);
if (brush_mask)
{
@ -875,10 +875,12 @@ gimp_brush_core_replace_canvas (GimpBrushCore *core,
gdouble brush_opacity,
gdouble image_opacity,
GimpBrushApplicationMode brush_hardness,
gdouble dynamic_hardness,
GimpPaintApplicationMode mode)
{
TempBuf *brush_mask = gimp_brush_core_get_brush_mask (core,
brush_hardness);
brush_hardness,
dynamic_hardness);
if (brush_mask)
{
@ -927,53 +929,6 @@ gimp_brush_core_invalidate_cache (GimpBrush *brush,
* LOCAL FUNCTION DEFINITIONS *
************************************************************/
static gdouble
gimp_brush_core_calc_brush_scale (GimpBrushCore *core,
GimpPaintOptions *paint_options,
gdouble pressure,
gdouble velocity)
{
gdouble scale = 1.0;
if (GIMP_BRUSH_CORE_GET_CLASS (core)->handles_scaling_brush)
{
if (! (GIMP_PAINT_CORE (core)->use_pressure &&
(paint_options->pressure_options->inverse_size ||
paint_options->pressure_options->size)))
{
pressure = -1;
}
else if (paint_options->pressure_options->inverse_size)
{
pressure = 1.0 - 0.9 * pressure;
}
if (paint_options->velocity_options->size)
{
velocity = 1.0 - sqrt (velocity);
}
else if (paint_options->velocity_options->inverse_size)
{
velocity = sqrt (velocity);
}
else
{
velocity = -1;
}
scale = gimp_paint_options_get_dynamics_mix (pressure, velocity);
if (scale < 1 / 64.0)
scale = 1 / 8.0;
else
scale = sqrt (scale);
}
scale *= paint_options->brush_scale;
return scale;
}
static inline void
rotate_pointers (gulong **p,
guint32 n)
@ -1393,12 +1348,11 @@ gimp_brush_core_scale_pixmap (GimpBrushCore *core,
TempBuf *
gimp_brush_core_get_brush_mask (GimpBrushCore *core,
GimpBrushApplicationMode brush_hardness)
GimpBrushApplicationMode brush_hardness,
gdouble dynamic_hardness)
{
GimpPaintCore *paint_core = GIMP_PAINT_CORE (core);
TempBuf *mask;
gdouble pressure;
gdouble velocity;
mask = gimp_brush_core_scale_mask (core, core->brush);
@ -1420,17 +1374,10 @@ gimp_brush_core_get_brush_mask (GimpBrushCore *core,
break;
case GIMP_BRUSH_PRESSURE:
if (! paint_core->use_pressure)
pressure = -1.0;
else
pressure = GIMP_PAINT_PRESSURE_SCALE * paint_core->cur_coords.pressure;
velocity = GIMP_PAINT_VELOCITY_SCALE * paint_core->cur_coords.velocity;
mask = gimp_brush_core_pressurize_mask (core, mask,
paint_core->cur_coords.x,
paint_core->cur_coords.y,
gimp_paint_options_get_dynamics_mix (pressure, velocity));
dynamic_hardness);
break;
default:

View File

@ -111,12 +111,14 @@ void gimp_brush_core_paste_canvas (GimpBrushCore *core,
gdouble image_opacity,
GimpLayerModeEffects paint_mode,
GimpBrushApplicationMode brush_hardness,
gdouble dynamic_hardness,
GimpPaintApplicationMode mode);
void gimp_brush_core_replace_canvas (GimpBrushCore *core,
GimpDrawable *drawable,
gdouble brush_opacity,
gdouble image_opacity,
GimpBrushApplicationMode brush_hardness,
gdouble dynamic_hardness,
GimpPaintApplicationMode mode);
void gimp_brush_core_color_area_with_pixmap
@ -126,7 +128,8 @@ void gimp_brush_core_color_area_with_pixmap
GimpBrushApplicationMode mode);
TempBuf * gimp_brush_core_get_brush_mask (GimpBrushCore *core,
GimpBrushApplicationMode brush_hardness);
GimpBrushApplicationMode brush_hardness,
gdouble dynamic_hardness);
#endif /* __GIMP_BRUSH_CORE_H__ */

View File

@ -172,6 +172,7 @@ gimp_clone_motion (GimpSourceCore *source_core,
gint y;
PixelRegion destPR;
GimpPattern *pattern = NULL;
gdouble hardness;
image = gimp_item_get_image (GIMP_ITEM (drawable));
@ -239,11 +240,16 @@ gimp_clone_motion (GimpSourceCore *source_core,
&paint_core->cur_coords,
paint_core->use_pressure);
hardness = gimp_paint_options_get_dynamic_hardness (paint_options,
&paint_core->cur_coords,
paint_core->use_pressure);
gimp_brush_core_paste_canvas (GIMP_BRUSH_CORE (paint_core), drawable,
MIN (opacity, GIMP_OPACITY_OPAQUE),
gimp_context_get_opacity (context),
gimp_context_get_paint_mode (context),
gimp_paint_options_get_brush_mode (paint_options),
hardness,
/* In fixed mode, paint incremental so the
* individual brushes are properly applied

View File

@ -211,6 +211,7 @@ gimp_convolve_motion (GimpPaintCore *paint_core,
MIN (opacity, GIMP_OPACITY_OPAQUE),
gimp_context_get_opacity (context),
gimp_paint_options_get_brush_mode (paint_options),
1.0,
GIMP_PAINT_INCREMENTAL);
}

View File

@ -170,6 +170,7 @@ gimp_dodge_burn_motion (GimpPaintCore *paint_core,
PixelRegion srcPR, destPR, tempPR;
guchar *temp_data;
gdouble opacity;
gdouble hardness;
image = gimp_item_get_image (GIMP_ITEM (drawable));
@ -239,11 +240,16 @@ gimp_dodge_burn_motion (GimpPaintCore *paint_core,
&paint_core->cur_coords,
paint_core->use_pressure);
hardness = gimp_paint_options_get_dynamic_hardness (paint_options,
&paint_core->cur_coords,
paint_core->use_pressure);
/* Replace the newly dodgedburned area (canvas_buf) to the image */
gimp_brush_core_replace_canvas (GIMP_BRUSH_CORE (paint_core), drawable,
MIN (opacity, GIMP_OPACITY_OPAQUE),
gimp_context_get_opacity (context),
gimp_paint_options_get_brush_mode (paint_options),
hardness,
GIMP_PAINT_CONSTANT);
}

View File

@ -108,6 +108,7 @@ gimp_eraser_motion (GimpPaintCore *paint_core,
gdouble opacity;
TempBuf *area;
guchar col[MAX_CHANNELS];
gdouble hardness;
image = gimp_item_get_image (GIMP_ITEM (drawable));
@ -134,11 +135,16 @@ gimp_eraser_motion (GimpPaintCore *paint_core,
&paint_core->cur_coords,
paint_core->use_pressure);
hardness = gimp_paint_options_get_dynamic_hardness (paint_options,
&paint_core->cur_coords,
paint_core->use_pressure);
gimp_brush_core_paste_canvas (GIMP_BRUSH_CORE (paint_core), drawable,
MIN (opacity, GIMP_OPACITY_OPAQUE),
gimp_context_get_opacity (context),
(options->anti_erase ?
GIMP_ANTI_ERASE_MODE : GIMP_ERASE_MODE),
gimp_paint_options_get_brush_mode (paint_options),
hardness,
paint_options->application_mode);
}

View File

@ -435,9 +435,15 @@ gimp_heal_motion (GimpSourceCore *source_core,
PixelRegion destPR;
GimpImageType src_type;
TempBuf *mask_buf;
gdouble hardness;
hardness = gimp_paint_options_get_dynamic_hardness (paint_options,
&paint_core->cur_coords,
paint_core->use_pressure);
mask_buf = gimp_brush_core_get_brush_mask (GIMP_BRUSH_CORE (source_core),
GIMP_BRUSH_HARD);
GIMP_BRUSH_HARD,
hardness);
src_type = gimp_pickable_get_image_type (src_pickable);
@ -550,5 +556,6 @@ gimp_heal_motion (GimpSourceCore *source_core,
MIN (opacity, GIMP_OPACITY_OPAQUE),
gimp_context_get_opacity (context),
gimp_paint_options_get_brush_mode (paint_options),
hardness,
GIMP_PAINT_INCREMENTAL);
}

View File

@ -114,7 +114,8 @@ _gimp_paintbrush_motion (GimpPaintCore *paint_core,
TempBuf *area;
guchar col[MAX_CHANNELS];
GimpPaintApplicationMode paint_appl_mode;
gdouble colmix = 0.0;
gdouble grad_point;
gdouble hardness;
image = gimp_item_get_image (GIMP_ITEM (drawable));
@ -127,28 +128,15 @@ _gimp_paintbrush_motion (GimpPaintCore *paint_core,
if (! area)
return;
if (paint_core->use_pressure &&
pressure_options->color &&
velocity_options->color)
{
colmix = (paint_core->cur_coords.pressure * 0.5 +
paint_core->cur_coords.velocity * 0.5);
}
else if (paint_core->use_pressure &&
pressure_options->color)
{
colmix = paint_core->cur_coords.pressure;
}
else if (velocity_options->color)
{
colmix = paint_core->cur_coords.velocity;
}
paint_appl_mode = paint_options->application_mode;
grad_point = gimp_paint_options_get_dynamic_color (paint_options,
&paint_core->cur_coords,
paint_core->use_pressure);
/* optionally take the color from the current gradient */
if (gimp_paint_options_get_gradient_color (paint_options, image,
colmix,
grad_point,
paint_core->pixel_dist,
&gradient_color))
{
@ -192,11 +180,16 @@ _gimp_paintbrush_motion (GimpPaintCore *paint_core,
&paint_core->cur_coords,
paint_core->use_pressure);
hardness = gimp_paint_options_get_dynamic_hardness (paint_options,
&paint_core->cur_coords,
paint_core->use_pressure);
/* finally, let the brush core paste the colored area on the canvas */
gimp_brush_core_paste_canvas (brush_core, drawable,
MIN (opacity, GIMP_OPACITY_OPAQUE),
gimp_context_get_opacity (context),
gimp_context_get_paint_mode (context),
gimp_paint_options_get_brush_mode (paint_options),
hardness,
paint_appl_mode);
}

View File

@ -54,6 +54,14 @@
#define DEFAULT_VELOCITY_INVERSE_SIZE FALSE
#define DEFAULT_VELOCITY_COLOR FALSE
#define DEFAULT_RANDOM_EXPANDED FALSE
#define DEFAULT_RANDOM_OPACITY FALSE
#define DEFAULT_RANDOM_HARDNESS FALSE
#define DEFAULT_RANDOM_RATE FALSE
#define DEFAULT_RANDOM_SIZE FALSE
#define DEFAULT_RANDOM_INVERSE_SIZE FALSE
#define DEFAULT_RANDOM_COLOR FALSE
#define DEFAULT_USE_FADE FALSE
#define DEFAULT_FADE_LENGTH 100.0
#define DEFAULT_FADE_UNIT GIMP_UNIT_PIXEL
@ -93,6 +101,14 @@ enum
PROP_VELOCITY_INVERSE_SIZE,
PROP_VELOCITY_COLOR,
PROP_RANDOM_EXPANDED,
PROP_RANDOM_OPACITY,
PROP_RANDOM_HARDNESS,
PROP_RANDOM_RATE,
PROP_RANDOM_SIZE,
PROP_RANDOM_INVERSE_SIZE,
PROP_RANDOM_COLOR,
PROP_USE_FADE,
PROP_FADE_LENGTH,
PROP_FADE_UNIT,
@ -115,17 +131,21 @@ enum
};
static void gimp_paint_options_finalize (GObject *object);
static void gimp_paint_options_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec);
static void gimp_paint_options_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec);
static void gimp_paint_options_notify (GObject *object,
GParamSpec *pspec);
static void gimp_paint_options_finalize (GObject *object);
static void gimp_paint_options_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec);
static void gimp_paint_options_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec);
static void gimp_paint_options_notify (GObject *object,
GParamSpec *pspec);
static gdouble gimp_paint_options_get_dynamics_mix (gdouble mix1,
gdouble mix2,
gdouble mix3);
G_DEFINE_TYPE (GimpPaintOptions, gimp_paint_options, GIMP_TYPE_TOOL_OPTIONS)
@ -222,6 +242,35 @@ gimp_paint_options_class_init (GimpPaintOptionsClass *klass)
DEFAULT_VELOCITY_INVERSE_SIZE,
GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_RANDOM_EXPANDED,
"random-expanded", NULL,
DEFAULT_RANDOM_EXPANDED,
GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_RANDOM_OPACITY,
"random-opacity", NULL,
DEFAULT_RANDOM_OPACITY,
GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_RANDOM_HARDNESS,
"random-hardness", NULL,
DEFAULT_RANDOM_HARDNESS,
GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_RANDOM_RATE,
"random-rate", NULL,
DEFAULT_RANDOM_RATE,
GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_RANDOM_SIZE,
"random-size", NULL,
DEFAULT_RANDOM_SIZE,
GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_RANDOM_COLOR,
"random-color", NULL,
DEFAULT_RANDOM_COLOR,
GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_RANDOM_INVERSE_SIZE,
"random-inverse-size", NULL,
DEFAULT_RANDOM_INVERSE_SIZE,
GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_USE_FADE,
"use-fade", NULL,
DEFAULT_USE_FADE,
@ -310,6 +359,7 @@ gimp_paint_options_init (GimpPaintOptions *options)
options->pressure_options = g_slice_new0 (GimpPressureOptions);
options->velocity_options = g_slice_new0 (GimpVelocityOptions);
options->random_options = g_slice_new0 (GimpRandomOptions);
options->fade_options = g_slice_new0 (GimpFadeOptions);
options->jitter_options = g_slice_new0 (GimpJitterOptions);
options->gradient_options = g_slice_new0 (GimpGradientOptions);
@ -325,6 +375,7 @@ gimp_paint_options_finalize (GObject *object)
g_slice_free (GimpPressureOptions, options->pressure_options);
g_slice_free (GimpVelocityOptions, options->velocity_options);
g_slice_free (GimpRandomOptions, options->random_options);
g_slice_free (GimpFadeOptions, options->fade_options);
g_slice_free (GimpJitterOptions, options->jitter_options);
g_slice_free (GimpGradientOptions, options->gradient_options);
@ -341,6 +392,7 @@ gimp_paint_options_set_property (GObject *object,
GimpPaintOptions *options = GIMP_PAINT_OPTIONS (object);
GimpPressureOptions *pressure_options = options->pressure_options;
GimpVelocityOptions *velocity_options = options->velocity_options;
GimpRandomOptions *random_options = options->random_options;
GimpFadeOptions *fade_options = options->fade_options;
GimpJitterOptions *jitter_options = options->jitter_options;
GimpGradientOptions *gradient_options = options->gradient_options;
@ -405,6 +457,28 @@ gimp_paint_options_set_property (GObject *object,
velocity_options->color = g_value_get_boolean (value);
break;
case PROP_RANDOM_EXPANDED:
random_options->expanded = g_value_get_boolean (value);
break;
case PROP_RANDOM_OPACITY:
random_options->opacity = g_value_get_boolean (value);
break;
case PROP_RANDOM_HARDNESS:
random_options->hardness = g_value_get_boolean (value);
break;
case PROP_RANDOM_RATE:
random_options->rate = g_value_get_boolean (value);
break;
case PROP_RANDOM_SIZE:
random_options->size = g_value_get_boolean (value);
break;
case PROP_RANDOM_INVERSE_SIZE:
random_options->inverse_size = g_value_get_boolean (value);
break;
case PROP_RANDOM_COLOR:
random_options->color = g_value_get_boolean (value);
break;
case PROP_USE_FADE:
fade_options->use_fade = g_value_get_boolean (value);
break;
@ -474,6 +548,7 @@ gimp_paint_options_get_property (GObject *object,
GimpPaintOptions *options = GIMP_PAINT_OPTIONS (object);
GimpPressureOptions *pressure_options = options->pressure_options;
GimpVelocityOptions *velocity_options = options->velocity_options;
GimpRandomOptions *random_options = options->random_options;
GimpFadeOptions *fade_options = options->fade_options;
GimpJitterOptions *jitter_options = options->jitter_options;
GimpGradientOptions *gradient_options = options->gradient_options;
@ -538,6 +613,28 @@ gimp_paint_options_get_property (GObject *object,
g_value_set_boolean (value, velocity_options->color);
break;
case PROP_RANDOM_EXPANDED:
g_value_set_boolean (value, random_options->expanded);
break;
case PROP_RANDOM_OPACITY:
g_value_set_boolean (value, random_options->opacity);
break;
case PROP_RANDOM_HARDNESS:
g_value_set_boolean (value, random_options->hardness);
break;
case PROP_RANDOM_RATE:
g_value_set_boolean (value, random_options->rate);
break;
case PROP_RANDOM_SIZE:
g_value_set_boolean (value, random_options->size);
break;
case PROP_RANDOM_INVERSE_SIZE:
g_value_set_boolean (value, random_options->inverse_size);
break;
case PROP_RANDOM_COLOR:
g_value_set_boolean (value, random_options->color);
break;
case PROP_USE_FADE:
g_value_set_boolean (value, fade_options->use_fade);
break;
@ -721,8 +818,6 @@ gimp_paint_options_get_gradient_color (GimpPaintOptions *paint_options,
gdouble pixel_dist,
GimpRGB *color)
{
GimpPressureOptions *pressure_options;
GimpVelocityOptions *velocity_options;
GimpGradientOptions *gradient_options;
GimpGradient *gradient;
@ -730,13 +825,13 @@ gimp_paint_options_get_gradient_color (GimpPaintOptions *paint_options,
g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE);
g_return_val_if_fail (color != NULL, FALSE);
pressure_options = paint_options->pressure_options;
velocity_options = paint_options->velocity_options;
gradient_options = paint_options->gradient_options;
gradient = gimp_context_get_gradient (GIMP_CONTEXT (paint_options));
if (pressure_options->color || velocity_options->color)
if (paint_options->pressure_options->color ||
paint_options->velocity_options->color ||
paint_options->random_options->color)
{
gimp_gradient_get_color_at (gradient, GIMP_CONTEXT (paint_options),
NULL, grad_point,
@ -810,7 +905,8 @@ gimp_paint_options_get_brush_mode (GimpPaintOptions *paint_options)
return GIMP_BRUSH_HARD;
if (paint_options->pressure_options->hardness ||
paint_options->velocity_options->hardness)
paint_options->velocity_options->hardness ||
paint_options->random_options->hardness)
return GIMP_BRUSH_PRESSURE;
return GIMP_BRUSH_SOFT;
@ -818,28 +914,38 @@ gimp_paint_options_get_brush_mode (GimpPaintOptions *paint_options)
/* Calculates dynamics mix to be used for same parameter
* (velocity/pressure) mix Needed in may places and tools.
* (velocity/pressure/random) mix Needed in may places and tools.
*/
gdouble
static gdouble
gimp_paint_options_get_dynamics_mix (gdouble mix1,
gdouble mix2)
gdouble mix2,
gdouble mix3)
{
gdouble mixpv = 1.0;
gdouble mixpv = 0.0;
gint dyn = 0;
if ((mix1 >= 0) && (mix2 >= 0))
if (mix1 >= 0)
{
mixpv = (mix1 + mix2) * 0.5;
}
else if (mix1 >= 0)
{
mixpv = mix1;
}
else if (mix2 >= 0)
{
mixpv = mix2;
mixpv += mix1;
dyn++;
}
return mixpv;
if (mix2 >= 0)
{
mixpv += mix2;
dyn++;
}
if (mix3 >= 0)
{
mixpv += mix3;
dyn++;
}
if (dyn == 0)
return 1.0;
else
return mixpv / (gdouble) dyn;
}
gdouble
@ -853,23 +959,78 @@ gimp_paint_options_get_dynamic_opacity (GimpPaintOptions *paint_options,
g_return_val_if_fail (coords != NULL, 1.0);
if (paint_options->pressure_options->opacity ||
paint_options->velocity_options->opacity)
paint_options->velocity_options->opacity ||
paint_options->random_options->opacity)
{
gdouble pressure = -1.0;
gdouble velocity = -1.0;
gdouble random = -1.0;
if (paint_options->pressure_options->opacity && use_pressure)
pressure = GIMP_PAINT_PRESSURE_SCALE * coords->pressure;
if (paint_options->velocity_options->opacity)
velocity = GIMP_PAINT_VELOCITY_SCALE * (1 - coords->velocity);
if (paint_options->random_options->opacity)
random = coords->random;
opacity = gimp_paint_options_get_dynamics_mix (pressure, velocity);
opacity = gimp_paint_options_get_dynamics_mix (pressure, velocity, random);
}
return opacity;
}
gdouble
gimp_paint_options_get_dynamic_size (GimpPaintOptions *paint_options,
const GimpCoords *coords,
gboolean use_pressure,
gboolean use_dynamics)
{
gdouble scale = 1.0;
if (use_dynamics)
{
gdouble pressure = -1.0;
gdouble velocity = -1.0;
gdouble random = -1.0;
if (paint_options->pressure_options->inverse_size)
{
pressure = 1.0 - 0.9 * coords->pressure;
}
if (paint_options->velocity_options->size)
{
velocity = 1.0 - sqrt (coords->velocity);
}
else if (paint_options->velocity_options->inverse_size)
{
velocity = sqrt (coords->velocity);
}
if (paint_options->random_options->size)
{
random = 1.0 - coords->random;
}
else if (paint_options->random_options->inverse_size)
{
random = coords->random;
}
scale = gimp_paint_options_get_dynamics_mix (pressure, velocity, random);
if (scale < 1 / 64.0)
scale = 1 / 8.0;
else
scale = sqrt (scale);
}
scale *= paint_options->brush_scale;
return scale;
}
gdouble
gimp_paint_options_get_dynamic_rate (GimpPaintOptions *paint_options,
const GimpCoords *coords,
@ -881,10 +1042,12 @@ gimp_paint_options_get_dynamic_rate (GimpPaintOptions *paint_options,
g_return_val_if_fail (coords != NULL, 1.0);
if (paint_options->pressure_options->rate ||
paint_options->velocity_options->rate)
paint_options->velocity_options->rate ||
paint_options->random_options->rate)
{
gdouble pressure = -1.0;
gdouble velocity = -1.0;
gdouble random = -1.0;
if (paint_options->pressure_options->rate && use_pressure)
pressure = GIMP_PAINT_PRESSURE_SCALE * coords->pressure;
@ -892,8 +1055,78 @@ gimp_paint_options_get_dynamic_rate (GimpPaintOptions *paint_options,
if (paint_options->velocity_options->rate)
velocity = GIMP_PAINT_VELOCITY_SCALE * (1 - coords->velocity);
rate = gimp_paint_options_get_dynamics_mix (pressure, velocity);
if (paint_options->random_options->rate)
random = coords->random;
rate = gimp_paint_options_get_dynamics_mix (pressure, velocity, random);
}
return rate;
}
gdouble
gimp_paint_options_get_dynamic_color (GimpPaintOptions *paint_options,
const GimpCoords *coords,
gboolean use_pressure)
{
gdouble color = 1.0;
g_return_val_if_fail (GIMP_IS_PAINT_OPTIONS (paint_options), 1.0);
g_return_val_if_fail (coords != NULL, 1.0);
if (paint_options->pressure_options->color ||
paint_options->velocity_options->color ||
paint_options->random_options->color)
{
gdouble pressure = -1.0;
gdouble velocity = -1.0;
gdouble random = -1.0;
if (paint_options->pressure_options->color && use_pressure)
pressure = GIMP_PAINT_PRESSURE_SCALE * coords->pressure;
if (paint_options->velocity_options->color)
velocity = GIMP_PAINT_VELOCITY_SCALE * coords->velocity;
if (paint_options->random_options->color)
random = coords->random;
color = gimp_paint_options_get_dynamics_mix (pressure, velocity, random);
}
return color;
}
gdouble
gimp_paint_options_get_dynamic_hardness (GimpPaintOptions *paint_options,
const GimpCoords *coords,
gboolean use_pressure)
{
gdouble hardness = 1.0;
g_return_val_if_fail (GIMP_IS_PAINT_OPTIONS (paint_options), 1.0);
g_return_val_if_fail (coords != NULL, 1.0);
if (paint_options->pressure_options->rate ||
paint_options->velocity_options->rate ||
paint_options->random_options->rate)
{
gdouble pressure = -1.0;
gdouble velocity = -1.0;
gdouble random = -1.0;
if (paint_options->pressure_options->hardness && use_pressure)
pressure = GIMP_PAINT_PRESSURE_SCALE * coords->pressure;
if (paint_options->velocity_options->hardness)
velocity = GIMP_PAINT_VELOCITY_SCALE * (1 - coords->velocity);
if (paint_options->random_options->hardness)
random = coords->random;
hardness = gimp_paint_options_get_dynamics_mix (pressure, velocity, random);
}
return hardness;
}

View File

@ -32,6 +32,7 @@
typedef struct _GimpPressureOptions GimpPressureOptions;
typedef struct _GimpVelocityOptions GimpVelocityOptions;
typedef struct _GimpRandomOptions GimpRandomOptions;
typedef struct _GimpFadeOptions GimpFadeOptions;
typedef struct _GimpJitterOptions GimpJitterOptions;
typedef struct _GimpGradientOptions GimpGradientOptions;
@ -58,6 +59,17 @@ struct _GimpVelocityOptions
gboolean color;
};
struct _GimpRandomOptions
{
gboolean expanded;
gboolean opacity;
gboolean hardness;
gboolean rate;
gboolean size;
gboolean inverse_size;
gboolean color;
};
struct _GimpFadeOptions
{
gboolean use_fade;
@ -108,6 +120,7 @@ struct _GimpPaintOptions
GimpPressureOptions *pressure_options;
GimpVelocityOptions *velocity_options;
GimpRandomOptions *random_options;
GimpFadeOptions *fade_options;
GimpJitterOptions *jitter_options;
GimpGradientOptions *gradient_options;
@ -146,14 +159,25 @@ gboolean gimp_paint_options_get_gradient_color (GimpPaintOptions *paint_options,
GimpBrushApplicationMode
gimp_paint_options_get_brush_mode (GimpPaintOptions *paint_options);
gdouble gimp_paint_options_get_dynamics_mix (gdouble mix1,
gdouble mix2);
gdouble gimp_paint_options_get_dynamic_opacity (GimpPaintOptions *paint_options,
const GimpCoords *coords,
gboolean use_pressure);
gdouble gimp_paint_options_get_dynamic_rate (GimpPaintOptions *paint_options,
gdouble gimp_paint_options_get_dynamic_size (GimpPaintOptions *paint_options,
const GimpCoords *coords,
gboolean use_pressure,
gboolean use_dynamics);
gdouble gimp_paint_options_get_dynamic_rate (GimpPaintOptions *paint_options,
const GimpCoords *coords,
gboolean use_pressure);
gdouble gimp_paint_options_get_dynamic_color (GimpPaintOptions *paint_options,
const GimpCoords *coords,
gboolean use_pressure);
gdouble gimp_paint_options_get_dynamic_hardness(GimpPaintOptions *paint_options,
const GimpCoords *coords,
gboolean use_pressure);

View File

@ -238,6 +238,7 @@ gimp_smudge_motion (GimpPaintCore *paint_core,
gdouble opacity;
gdouble dynamic_rate;
gint x, y, w, h;
gdouble hardness;
image = gimp_item_get_image (GIMP_ITEM (drawable));
@ -308,10 +309,15 @@ gimp_smudge_motion (GimpPaintCore *paint_core,
&paint_core->cur_coords,
paint_core->use_pressure);
hardness = gimp_paint_options_get_dynamic_hardness (paint_options,
&paint_core->cur_coords,
paint_core->use_pressure);
gimp_brush_core_replace_canvas (GIMP_BRUSH_CORE (paint_core), drawable,
MIN (opacity, GIMP_OPACITY_OPAQUE),
gimp_context_get_opacity (context),
gimp_paint_options_get_brush_mode (paint_options),
hardness,
GIMP_PAINT_INCREMENTAL);
}

View File

@ -54,7 +54,10 @@
static GtkWidget * pressure_options_gui (GimpPressureOptions *pressure,
GimpPaintOptions *paint_options,
GType tool_type);
static GtkWidget * velocity_options_gui (GimpVelocityOptions *pressure,
static GtkWidget * velocity_options_gui (GimpVelocityOptions *velocity,
GimpPaintOptions *paint_options,
GType tool_type);
static GtkWidget * random_options_gui (GimpRandomOptions *random,
GimpPaintOptions *paint_options,
GType tool_type);
static GtkWidget * fade_options_gui (GimpFadeOptions *fade,
@ -164,6 +167,14 @@ gimp_paint_options_gui (GimpToolOptions *tool_options)
gtk_widget_show (frame);
}
frame = random_options_gui (options->random_options,
options, tool_type);
if (frame)
{
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
gtk_widget_show (frame);
}
frame = fade_options_gui (options->fade_options,
options, tool_type);
if (frame)
@ -359,8 +370,7 @@ velocity_options_gui (GimpVelocityOptions *velocity,
}
/* the opacity toggle */
if ((g_type_is_a (tool_type, GIMP_TYPE_PAINTBRUSH_TOOL) &&
(tool_type != GIMP_TYPE_AIRBRUSH_TOOL)) ||
if (g_type_is_a (tool_type, GIMP_TYPE_PAINTBRUSH_TOOL)||
tool_type == GIMP_TYPE_CLONE_TOOL ||
tool_type == GIMP_TYPE_HEAL_TOOL ||
tool_type == GIMP_TYPE_PERSPECTIVE_CLONE_TOOL ||
@ -408,6 +418,7 @@ velocity_options_gui (GimpVelocityOptions *velocity,
tool_type == GIMP_TYPE_DODGE_BURN_TOOL ||
tool_type == GIMP_TYPE_ERASER_TOOL ||
tool_type == GIMP_TYPE_PAINTBRUSH_TOOL ||
tool_type == GIMP_TYPE_AIRBRUSH_TOOL ||
tool_type == GIMP_TYPE_PENCIL_TOOL)
{
button = gimp_prop_check_button_new (config, "velocity-size",
@ -416,15 +427,6 @@ velocity_options_gui (GimpVelocityOptions *velocity,
gtk_widget_show (button);
}
/* the inverse size toggle */
if (tool_type == GIMP_TYPE_AIRBRUSH_TOOL)
{
button = gimp_prop_check_button_new (config, "velocity-inverse-size",
_("Size"));
gtk_container_add (GTK_CONTAINER (wbox), button);
gtk_widget_show (button);
}
/* the color toggle */
if (g_type_is_a (tool_type, GIMP_TYPE_PAINTBRUSH_TOOL))
{
@ -437,6 +439,104 @@ velocity_options_gui (GimpVelocityOptions *velocity,
return frame;
}
static GtkWidget *
random_options_gui (GimpRandomOptions *random,
GimpPaintOptions *paint_options,
GType tool_type)
{
GObject *config = G_OBJECT (paint_options);
GtkWidget *frame = NULL;
GtkWidget *wbox = NULL;
GtkWidget *button;
if (g_type_is_a (tool_type, GIMP_TYPE_BRUSH_TOOL))
{
GtkWidget *inner_frame;
frame = gimp_prop_expander_new (G_OBJECT (paint_options),
"random-expanded",
_("Random sensitivity"));
inner_frame = gimp_frame_new ("<expander>");
gtk_container_add (GTK_CONTAINER (frame), inner_frame);
gtk_widget_show (inner_frame);
wbox = gtk_hwrap_box_new (FALSE);
gtk_wrap_box_set_aspect_ratio (GTK_WRAP_BOX (wbox), 4);
gtk_container_add (GTK_CONTAINER (inner_frame), wbox);
gtk_widget_show (wbox);
}
/* the opacity toggle */
if (g_type_is_a (tool_type, GIMP_TYPE_PAINTBRUSH_TOOL)||
tool_type == GIMP_TYPE_CLONE_TOOL ||
tool_type == GIMP_TYPE_HEAL_TOOL ||
tool_type == GIMP_TYPE_PERSPECTIVE_CLONE_TOOL ||
tool_type == GIMP_TYPE_DODGE_BURN_TOOL ||
tool_type == GIMP_TYPE_ERASER_TOOL)
{
button = gimp_prop_check_button_new (config, "random-opacity",
_("Opacity"));
gtk_container_add (GTK_CONTAINER (wbox), button);
gtk_widget_show (button);
}
/* the pressure toggle */
if (tool_type == GIMP_TYPE_AIRBRUSH_TOOL ||
tool_type == GIMP_TYPE_CLONE_TOOL ||
tool_type == GIMP_TYPE_HEAL_TOOL ||
tool_type == GIMP_TYPE_PERSPECTIVE_CLONE_TOOL ||
tool_type == GIMP_TYPE_CONVOLVE_TOOL ||
tool_type == GIMP_TYPE_DODGE_BURN_TOOL ||
tool_type == GIMP_TYPE_PAINTBRUSH_TOOL ||
tool_type == GIMP_TYPE_SMUDGE_TOOL)
{
button = gimp_prop_check_button_new (config, "random-hardness",
_("Hardness"));
gtk_container_add (GTK_CONTAINER (wbox), button);
gtk_widget_show (button);
}
/* the rate toggle */
if (tool_type == GIMP_TYPE_AIRBRUSH_TOOL ||
tool_type == GIMP_TYPE_CONVOLVE_TOOL ||
tool_type == GIMP_TYPE_SMUDGE_TOOL)
{
button = gimp_prop_check_button_new (config, "random-rate",
_("Rate"));
gtk_container_add (GTK_CONTAINER (wbox), button);
gtk_widget_show (button);
}
/* the size toggle */
if (tool_type == GIMP_TYPE_CLONE_TOOL ||
tool_type == GIMP_TYPE_HEAL_TOOL ||
tool_type == GIMP_TYPE_PERSPECTIVE_CLONE_TOOL ||
tool_type == GIMP_TYPE_CONVOLVE_TOOL ||
tool_type == GIMP_TYPE_DODGE_BURN_TOOL ||
tool_type == GIMP_TYPE_ERASER_TOOL ||
tool_type == GIMP_TYPE_PAINTBRUSH_TOOL ||
tool_type == GIMP_TYPE_AIRBRUSH_TOOL ||
tool_type == GIMP_TYPE_PENCIL_TOOL)
{
button = gimp_prop_check_button_new (config, "random-size",
_("Size"));
gtk_container_add (GTK_CONTAINER (wbox), button);
gtk_widget_show (button);
}
/* the color toggle */
if (g_type_is_a (tool_type, GIMP_TYPE_PAINTBRUSH_TOOL))
{
button = gimp_prop_check_button_new (config, "random-color",
_("Color"));
gtk_container_add (GTK_CONTAINER (wbox), button);
gtk_widget_show (button);
}
return frame;
}
static GtkWidget *
fade_options_gui (GimpFadeOptions *fade,
GimpPaintOptions *paint_options,