Bug 771678 - Parametric Brush Aspect Ratio and Angle values...

...are not submitted to respective Tool Options sliders

Treat brush angle and aspect ratio like all other paint options values
that can be linked to brush defaults and take their default values
from the brush. They were special casing their defaults to constants,
and GimpBrushGenerated was adding the passed dynamic radius and aspect
values to its own. This was totally incomprehensible.

Now GimpBrushGenerated's transform_size() and transform_mask()
implementations just translate between these APIs value ranges and the
brush's own value range and only use the passed values (not the
brush's native values), which makes the editor <-> tool options
interaction and the painted brush shape predictable.

Also connect the active brush's property notifications to the paint
options properties, so the paint options follow a brush edit live if
the respective "linked" toggles are checked.

And some cleanup.
This commit is contained in:
Michael Natterer 2016-10-11 00:57:25 +02:00
parent 8c10f8a409
commit 184f0929ce
5 changed files with 204 additions and 104 deletions

View File

@ -314,7 +314,8 @@ gimp_brush_get_new_preview (GimpViewable *viewable,
GimpBrushGenerated *gen_brush = GIMP_BRUSH_GENERATED (brush); GimpBrushGenerated *gen_brush = GIMP_BRUSH_GENERATED (brush);
mask_buf = gimp_brush_transform_mask (brush, NULL, scale, mask_buf = gimp_brush_transform_mask (brush, NULL, scale,
0.0, 0.0, (gimp_brush_generated_get_aspect_ratio (gen_brush) - 1.0) * 20.0 / 19.0,
gimp_brush_generated_get_angle (gen_brush) / 360.0,
gimp_brush_generated_get_hardness (gen_brush)); gimp_brush_generated_get_hardness (gen_brush));
} }
else else

View File

@ -301,22 +301,22 @@ gimp_brush_generated_transform_size (GimpBrush *gbrush,
GimpBrushGenerated *brush = GIMP_BRUSH_GENERATED (gbrush); GimpBrushGenerated *brush = GIMP_BRUSH_GENERATED (gbrush);
gdouble ratio; gdouble ratio;
if (aspect_ratio == 0.0) ratio = fabs (aspect_ratio) * 19.0 / 20.0 + 1.0;
{ ratio = MIN (ratio, 20);
ratio = brush->aspect_ratio;
}
else
{
ratio = MIN (fabs (aspect_ratio) + 1, 20);
/* Since generated brushes are symmetric the dont have input
* for aspect ratios < 1.0. its same as rotate by 90 degrees and
* 1 / ratio. So we fix the input up for this case. */
if (aspect_ratio < 0.0) /* Since generated brushes are symmetric they don't have aspect
{ * ratios < 1.0. it's the same as rotating by 90 degrees and 1 /
angle = angle + 0.25; * ratio, so we fix the input for this case.
} */
} if (aspect_ratio < 0.0)
angle = angle + 0.25;
angle *= 360;
if (angle < 0.0)
angle = -1.0 * fmod (angle, 180.0);
else if (angle > 180.0)
angle = fmod (angle, 180.0);
gimp_brush_generated_get_size (brush, gimp_brush_generated_get_size (brush,
brush->shape, brush->shape,
@ -324,7 +324,7 @@ gimp_brush_generated_transform_size (GimpBrush *gbrush,
brush->spikes, brush->spikes,
brush->hardness, brush->hardness,
ratio, ratio,
(brush->angle + 360 * angle), angle,
width, height, width, height,
NULL, NULL, NULL, NULL); NULL, NULL, NULL, NULL);
} }
@ -339,23 +339,22 @@ gimp_brush_generated_transform_mask (GimpBrush *gbrush,
GimpBrushGenerated *brush = GIMP_BRUSH_GENERATED (gbrush); GimpBrushGenerated *brush = GIMP_BRUSH_GENERATED (gbrush);
gdouble ratio; gdouble ratio;
if (aspect_ratio == 0.0) ratio = fabs (aspect_ratio) * 19.0 / 20.0 + 1.0;
{ ratio = MIN (ratio, 20);
ratio = brush->aspect_ratio;
}
else
{
ratio = MIN (fabs (aspect_ratio) + 1, 20);
/* Since generated brushes are symmetric the dont have input
* for aspect ratios < 1.0. its same as rotate by 90 degrees and
* 1 / ratio. So we fix the input up for this case. */
if (aspect_ratio < 0.0) /* Since generated brushes are symmetric they don't have aspect
{ * ratios < 1.0. it's the same as rotating by 90 degrees and 1 /
angle = angle + 0.25; * ratio, so we fix the input for this case.
} */
} if (aspect_ratio < 0.0)
angle = angle + 0.25;
angle *= 360;
if (angle < 0.0)
angle = -1.0 * fmod (angle, 180.0);
else if (angle > 180.0)
angle = fmod (angle, 180.0);
return gimp_brush_generated_calc (brush, return gimp_brush_generated_calc (brush,
brush->shape, brush->shape,
@ -363,7 +362,7 @@ gimp_brush_generated_transform_mask (GimpBrush *gbrush,
brush->spikes, brush->spikes,
hardness, hardness,
ratio, ratio,
(brush->angle + 360 * angle), angle,
NULL, NULL); NULL, NULL);
} }

View File

@ -980,6 +980,63 @@ gimp_paint_options_set_default_brush_size (GimpPaintOptions *paint_options,
} }
} }
void
gimp_paint_options_set_default_brush_angle (GimpPaintOptions *paint_options,
GimpBrush *brush)
{
g_return_if_fail (GIMP_IS_PAINT_OPTIONS (paint_options));
g_return_if_fail (brush == NULL || GIMP_IS_BRUSH (brush));
if (! brush)
brush = gimp_context_get_brush (GIMP_CONTEXT (paint_options));
if (GIMP_IS_BRUSH_GENERATED (brush))
{
GimpBrushGenerated *generated_brush = GIMP_BRUSH_GENERATED (brush);
g_object_set (paint_options,
"brush-angle", (gdouble) gimp_brush_generated_get_angle (generated_brush),
NULL);
}
else
{
g_object_set (paint_options,
"brush-angle", DEFAULT_BRUSH_ANGLE,
NULL);
}
}
void
gimp_paint_options_set_default_brush_aspect_ratio (GimpPaintOptions *paint_options,
GimpBrush *brush)
{
g_return_if_fail (GIMP_IS_PAINT_OPTIONS (paint_options));
g_return_if_fail (brush == NULL || GIMP_IS_BRUSH (brush));
if (! brush)
brush = gimp_context_get_brush (GIMP_CONTEXT (paint_options));
if (GIMP_IS_BRUSH_GENERATED (brush))
{
GimpBrushGenerated *generated_brush = GIMP_BRUSH_GENERATED (brush);
gdouble ratio;
ratio = gimp_brush_generated_get_aspect_ratio (generated_brush);
ratio = (ratio - 1.0) * 20.0 / 19.0;
g_object_set (paint_options,
"brush-aspect-ratio", ratio,
NULL);
}
else
{
g_object_set (paint_options,
"brush-aspect-ratio", DEFAULT_BRUSH_ASPECT_RATIO,
NULL);
}
}
void void
gimp_paint_options_set_default_brush_spacing (GimpPaintOptions *paint_options, gimp_paint_options_set_default_brush_spacing (GimpPaintOptions *paint_options,
GimpBrush *brush) GimpBrush *brush)
@ -1037,8 +1094,8 @@ gimp_paint_options_copy_brush_props (GimpPaintOptions *src,
gdouble brush_force; gdouble brush_force;
gboolean brush_link_size; gboolean brush_link_size;
gboolean brush_link_aspect_ratio;
gboolean brush_link_angle; gboolean brush_link_angle;
gboolean brush_link_aspect_ratio;
gboolean brush_link_spacing; gboolean brush_link_spacing;
gboolean brush_link_hardness; gboolean brush_link_hardness;
@ -1046,33 +1103,33 @@ gimp_paint_options_copy_brush_props (GimpPaintOptions *src,
g_return_if_fail (GIMP_IS_PAINT_OPTIONS (dest)); g_return_if_fail (GIMP_IS_PAINT_OPTIONS (dest));
g_object_get (src, g_object_get (src,
"brush-size", &brush_size, "brush-size", &brush_size,
"brush-zoom", &brush_zoom, "brush-zoom", &brush_zoom,
"brush-angle", &brush_angle, "brush-angle", &brush_angle,
"brush-aspect-ratio", &brush_aspect_ratio, "brush-aspect-ratio", &brush_aspect_ratio,
"brush-spacing", &brush_spacing, "brush-spacing", &brush_spacing,
"brush-hardness", &brush_hardness, "brush-hardness", &brush_hardness,
"brush-force", &brush_force, "brush-force", &brush_force,
"brush-link-size", &brush_link_size, "brush-link-size", &brush_link_size,
"brush-link-angle", &brush_link_angle, "brush-link-angle", &brush_link_angle,
"brush-link-aspect-ratio", &brush_link_aspect_ratio, "brush-link-aspect-ratio", &brush_link_aspect_ratio,
"brush-link-spacing", &brush_link_spacing, "brush-link-spacing", &brush_link_spacing,
"brush-link-hardness", &brush_link_hardness, "brush-link-hardness", &brush_link_hardness,
NULL); NULL);
g_object_set (dest, g_object_set (dest,
"brush-size", brush_size, "brush-size", brush_size,
"brush-zoom", brush_zoom, "brush-zoom", brush_zoom,
"brush-angle", brush_angle, "brush-angle", brush_angle,
"brush-aspect-ratio", brush_aspect_ratio, "brush-aspect-ratio", brush_aspect_ratio,
"brush-spacing", brush_spacing, "brush-spacing", brush_spacing,
"brush-hardness", brush_hardness, "brush-hardness", brush_hardness,
"brush-force", brush_force, "brush-force", brush_force,
"brush-link-size", brush_link_size, "brush-link-size", brush_link_size,
"brush-link-angle", brush_link_angle, "brush-link-angle", brush_link_angle,
"brush-link-aspect-ratio", brush_link_aspect_ratio, "brush-link-aspect-ratio", brush_link_aspect_ratio,
"brush-link-spacing", brush_link_spacing, "brush-link-spacing", brush_link_spacing,
"brush-link-hardness", brush_link_hardness, "brush-link-hardness", brush_link_hardness,
NULL); NULL);
} }
@ -1080,29 +1137,29 @@ void
gimp_paint_options_copy_dynamics_props (GimpPaintOptions *src, gimp_paint_options_copy_dynamics_props (GimpPaintOptions *src,
GimpPaintOptions *dest) GimpPaintOptions *dest)
{ {
gboolean dynamics_expanded; gboolean dynamics_expanded;
gboolean fade_reverse; gboolean fade_reverse;
gdouble fade_length; gdouble fade_length;
GimpUnit fade_unit; GimpUnit fade_unit;
GimpRepeatMode fade_repeat; GimpRepeatMode fade_repeat;
g_return_if_fail (GIMP_IS_PAINT_OPTIONS (src)); g_return_if_fail (GIMP_IS_PAINT_OPTIONS (src));
g_return_if_fail (GIMP_IS_PAINT_OPTIONS (dest)); g_return_if_fail (GIMP_IS_PAINT_OPTIONS (dest));
g_object_get (src, g_object_get (src,
"dynamics-expanded", &dynamics_expanded, "dynamics-expanded", &dynamics_expanded,
"fade-reverse", &fade_reverse, "fade-reverse", &fade_reverse,
"fade-length", &fade_length, "fade-length", &fade_length,
"fade-unit", &fade_unit, "fade-unit", &fade_unit,
"fade-repeat", &fade_repeat, "fade-repeat", &fade_repeat,
NULL); NULL);
g_object_set (dest, g_object_set (dest,
"dynamics-expanded", dynamics_expanded, "dynamics-expanded", dynamics_expanded,
"fade-reverse", fade_reverse, "fade-reverse", fade_reverse,
"fade-length", fade_length, "fade-length", fade_length,
"fade-unit", fade_unit, "fade-unit", fade_unit,
"fade-repeat", fade_repeat, "fade-repeat", fade_repeat,
NULL); NULL);
} }
@ -1110,7 +1167,7 @@ void
gimp_paint_options_copy_gradient_props (GimpPaintOptions *src, gimp_paint_options_copy_gradient_props (GimpPaintOptions *src,
GimpPaintOptions *dest) GimpPaintOptions *dest)
{ {
gboolean gradient_reverse; gboolean gradient_reverse;
g_return_if_fail (GIMP_IS_PAINT_OPTIONS (src)); g_return_if_fail (GIMP_IS_PAINT_OPTIONS (src));
g_return_if_fail (GIMP_IS_PAINT_OPTIONS (dest)); g_return_if_fail (GIMP_IS_PAINT_OPTIONS (dest));

View File

@ -82,6 +82,8 @@ struct _GimpPaintOptions
gboolean use_applicator; gboolean use_applicator;
GimpBrush *brush; /* weak-refed storage for the GUI */
gdouble brush_size; gdouble brush_size;
gboolean brush_zoom; gboolean brush_zoom;
gdouble brush_angle; gdouble brush_angle;
@ -147,7 +149,12 @@ GimpBrushApplicationMode
void gimp_paint_options_set_default_brush_size void gimp_paint_options_set_default_brush_size
(GimpPaintOptions *paint_options, (GimpPaintOptions *paint_options,
GimpBrush *brush); GimpBrush *brush);
void gimp_paint_options_set_default_brush_angle
(GimpPaintOptions *paint_options,
GimpBrush *brush);
void gimp_paint_options_set_default_brush_aspect_ratio
(GimpPaintOptions *paint_options,
GimpBrush *brush);
void gimp_paint_options_set_default_brush_spacing void gimp_paint_options_set_default_brush_spacing
(GimpPaintOptions *paint_options, (GimpPaintOptions *paint_options,
GimpBrush *brush); GimpBrush *brush);

View File

@ -53,7 +53,11 @@
static void gimp_paint_options_gui_brush_changed static void gimp_paint_options_gui_brush_changed
(GimpContext *context, (GimpContext *context,
GimpBrush *brush); GimpBrush *brush,
GtkWidget *gui);
static void gimp_paint_options_gui_brush_notify(GimpBrush *brush,
const GParamSpec *pspec,
GimpPaintOptions *options);
static void gimp_paint_options_gui_reset_size (GtkWidget *button, static void gimp_paint_options_gui_reset_size (GtkWidget *button,
GimpPaintOptions *paint_options); GimpPaintOptions *paint_options);
@ -171,7 +175,7 @@ gimp_paint_options_gui (GimpToolOptions *tool_options)
hbox = gimp_paint_options_gui_scale_with_buttons hbox = gimp_paint_options_gui_scale_with_buttons
(config, "brush-aspect-ratio", "brush-link-aspect-ratio", (config, "brush-aspect-ratio", "brush-link-aspect-ratio",
_("Reset aspect ratio to brush's native"), _("Reset aspect ratio to brush's native aspect ratio"),
0.1, 1.0, 2, -20.0, 20.0, 1.0, 1.0, 0.1, 1.0, 2, -20.0, 20.0, 1.0, 1.0,
G_CALLBACK (gimp_paint_options_gui_reset_aspect_ratio), link_group); G_CALLBACK (gimp_paint_options_gui_reset_aspect_ratio), link_group);
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
@ -179,7 +183,7 @@ gimp_paint_options_gui (GimpToolOptions *tool_options)
hbox = gimp_paint_options_gui_scale_with_buttons hbox = gimp_paint_options_gui_scale_with_buttons
(config, "brush-angle", "brush-link-angle", (config, "brush-angle", "brush-link-angle",
_("Reset angle to zero"), _("Reset angle to brush's native angle"),
0.1, 1.0, 2, -180.0, 180.0, 1.0, 1.0, 0.1, 1.0, 2, -180.0, 180.0, 1.0, 1.0,
G_CALLBACK (gimp_paint_options_gui_reset_angle), link_group); G_CALLBACK (gimp_paint_options_gui_reset_angle), link_group);
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
@ -195,7 +199,7 @@ gimp_paint_options_gui (GimpToolOptions *tool_options)
hbox = gimp_paint_options_gui_scale_with_buttons hbox = gimp_paint_options_gui_scale_with_buttons
(config, "brush-hardness", "brush-link-hardness", (config, "brush-hardness", "brush-link-hardness",
_("Reset hardness to default"), _("Reset hardness to brush's native hardness"),
0.1, 1.0, 1, 0.0, 100.0, 100.0, 1.0, 0.1, 1.0, 1, 0.0, 100.0, 100.0, 1.0,
G_CALLBACK (gimp_paint_options_gui_reset_hardness), link_group); G_CALLBACK (gimp_paint_options_gui_reset_hardness), link_group);
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
@ -228,9 +232,9 @@ gimp_paint_options_gui (GimpToolOptions *tool_options)
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
gtk_widget_show (frame); gtk_widget_show (frame);
g_signal_connect (options, "brush-changed", g_signal_connect_object (options, "brush-changed",
G_CALLBACK (gimp_paint_options_gui_brush_changed), G_CALLBACK (gimp_paint_options_gui_brush_changed),
NULL); G_OBJECT (vbox), 0);
} }
/* the "smooth stroke" options */ /* the "smooth stroke" options */
@ -420,31 +424,61 @@ smoothing_options_gui (GimpPaintOptions *paint_options,
static void static void
gimp_paint_options_gui_brush_changed (GimpContext *context, gimp_paint_options_gui_brush_changed (GimpContext *context,
GimpBrush *brush) GimpBrush *brush,
GtkWidget *gui)
{ {
GimpPaintOptions *options = GIMP_PAINT_OPTIONS (context); GimpPaintOptions *options = GIMP_PAINT_OPTIONS (context);
if (brush) if (options->brush)
{ {
if (options->brush_link_size) g_signal_handlers_disconnect_by_func (options->brush,
gimp_paint_options_set_default_brush_size (options, brush); gimp_paint_options_gui_brush_notify,
options);
if (options->brush_link_aspect_ratio) g_object_remove_weak_pointer (G_OBJECT (options->brush),
g_object_set (options, (gpointer) &options->brush);
"brush-aspect-ratio", 0.0,
NULL);
if (options->brush_link_angle)
g_object_set (options,
"brush-angle", 0.0,
NULL);
if (options->brush_link_spacing)
gimp_paint_options_set_default_brush_spacing (options, brush);
if (options->brush_link_hardness)
gimp_paint_options_set_default_brush_hardness (options, brush);
} }
options->brush = brush;
if (options->brush)
{
GClosure *closure;
g_object_add_weak_pointer (G_OBJECT (options->brush),
(gpointer) &options->brush);
closure = g_cclosure_new (G_CALLBACK (gimp_paint_options_gui_brush_notify),
options, NULL);
g_object_watch_closure (G_OBJECT (gui), closure);
g_signal_connect_closure (options->brush, "notify", closure, FALSE);
gimp_paint_options_gui_brush_notify (options->brush, NULL, options);
}
}
static void
gimp_paint_options_gui_brush_notify (GimpBrush *brush,
const GParamSpec *pspec,
GimpPaintOptions *options)
{
#define IS_PSPEC(p,n) (p == NULL || ! strcmp (n, p->name))
if (options->brush_link_size && IS_PSPEC (pspec, "radius"))
gimp_paint_options_set_default_brush_size (options, brush);
if (options->brush_link_aspect_ratio && IS_PSPEC (pspec, "aspect-ratio"))
gimp_paint_options_set_default_brush_aspect_ratio (options, brush);
if (options->brush_link_angle && IS_PSPEC (pspec, "angle"))
gimp_paint_options_set_default_brush_angle (options, brush);
if (options->brush_link_spacing && IS_PSPEC (pspec, "spacing"))
gimp_paint_options_set_default_brush_spacing (options, brush);
if (options->brush_link_hardness && IS_PSPEC (pspec, "hardness"))
gimp_paint_options_set_default_brush_hardness (options, brush);
#undef IS_SPEC
} }
static void static void
@ -461,18 +495,20 @@ static void
gimp_paint_options_gui_reset_aspect_ratio (GtkWidget *button, gimp_paint_options_gui_reset_aspect_ratio (GtkWidget *button,
GimpPaintOptions *paint_options) GimpPaintOptions *paint_options)
{ {
g_object_set (paint_options, GimpBrush *brush = gimp_context_get_brush (GIMP_CONTEXT (paint_options));
"brush-aspect-ratio", 0.0,
NULL); if (brush)
gimp_paint_options_set_default_brush_aspect_ratio (paint_options, brush);
} }
static void static void
gimp_paint_options_gui_reset_angle (GtkWidget *button, gimp_paint_options_gui_reset_angle (GtkWidget *button,
GimpPaintOptions *paint_options) GimpPaintOptions *paint_options)
{ {
g_object_set (paint_options, GimpBrush *brush = gimp_context_get_brush (GIMP_CONTEXT (paint_options));
"brush-angle", 0.0,
NULL); if (brush)
gimp_paint_options_set_default_brush_angle (paint_options, brush);
} }
static void static void