From 001acb7d18a8e47ce9ab9dbd65d7df7b6d292c12 Mon Sep 17 00:00:00 2001 From: Ell Date: Fri, 19 Apr 2019 10:09:08 -0400 Subject: [PATCH] app: add smooth/corner curve-point types Allow setting the type of GimpCurve control-points to either SMOOTH or CORNER. Smooth points produce a smooth curve, while corner points produce a sharp curve (previously, all points were smooth). In GimpCureView, display corner points using a diamond shape, instead of a circle. In the Curves tool, allow changing the curve's point types. (cherry picked from commit 33e47c85a21dddccf67b4aa83692f5d372886884) --- app/core/core-enums.c | 29 +++ app/core/core-enums.h | 11 + app/core/gimpcurve.c | 206 ++++++++++++++---- app/core/gimpcurve.h | 112 +++++----- app/tools/gimpcurvestool.c | 75 ++++++- app/tools/gimpcurvestool.h | 1 + app/widgets/gimpcurveview.c | 52 ++++- app/widgets/gimpcurveview.h | 1 + icons/Color/16/gimp-curve-point-corner.png | Bin 0 -> 422 bytes icons/Color/16/gimp-curve-point-smooth.png | Bin 0 -> 541 bytes .../scalable/gimp-curve-point-corner.svg | 113 ++++++++++ .../scalable/gimp-curve-point-smooth.svg | 115 ++++++++++ icons/Legacy/16/gimp-curve-point-corner.png | Bin 0 -> 124 bytes icons/Legacy/16/gimp-curve-point-smooth.png | Bin 0 -> 155 bytes icons/Symbolic/16/gimp-curve-point-corner.png | Bin 0 -> 306 bytes icons/Symbolic/16/gimp-curve-point-smooth.png | Bin 0 -> 387 bytes .../scalable/gimp-curve-point-corner.svg | 94 ++++++++ .../scalable/gimp-curve-point-smooth.svg | 95 ++++++++ icons/icon-list.mk | 4 + 19 files changed, 810 insertions(+), 98 deletions(-) create mode 100644 icons/Color/16/gimp-curve-point-corner.png create mode 100644 icons/Color/16/gimp-curve-point-smooth.png create mode 100644 icons/Color/scalable/gimp-curve-point-corner.svg create mode 100644 icons/Color/scalable/gimp-curve-point-smooth.svg create mode 100644 icons/Legacy/16/gimp-curve-point-corner.png create mode 100644 icons/Legacy/16/gimp-curve-point-smooth.png create mode 100644 icons/Symbolic/16/gimp-curve-point-corner.png create mode 100644 icons/Symbolic/16/gimp-curve-point-smooth.png create mode 100644 icons/Symbolic/scalable/gimp-curve-point-corner.svg create mode 100644 icons/Symbolic/scalable/gimp-curve-point-smooth.svg diff --git a/app/core/core-enums.c b/app/core/core-enums.c index aa0db6bb59..1202ca35e3 100644 --- a/app/core/core-enums.c +++ b/app/core/core-enums.c @@ -329,6 +329,35 @@ gimp_convolution_type_get_type (void) return type; } +GType +gimp_curve_point_type_get_type (void) +{ + static const GEnumValue values[] = + { + { GIMP_CURVE_POINT_SMOOTH, "GIMP_CURVE_POINT_SMOOTH", "smooth" }, + { GIMP_CURVE_POINT_CORNER, "GIMP_CURVE_POINT_CORNER", "corner" }, + { 0, NULL, NULL } + }; + + static const GimpEnumDesc descs[] = + { + { GIMP_CURVE_POINT_SMOOTH, NC_("curve-point-type", "Smooth"), NULL }, + { GIMP_CURVE_POINT_CORNER, NC_("curve-point-type", "Corner"), NULL }, + { 0, NULL, NULL } + }; + + static GType type = 0; + + if (G_UNLIKELY (! type)) + { + type = g_enum_register_static ("GimpCurvePointType", values); + gimp_type_set_translation_context (type, "curve-point-type"); + gimp_enum_set_value_descriptions (type, descs); + } + + return type; +} + GType gimp_curve_type_get_type (void) { diff --git a/app/core/core-enums.h b/app/core/core-enums.h index 1c063a5bea..7cb5a71c09 100644 --- a/app/core/core-enums.h +++ b/app/core/core-enums.h @@ -176,6 +176,17 @@ typedef enum /*< pdb-skip >*/ } GimpConvolutionType; +#define GIMP_TYPE_CURVE_POINT_TYPE (gimp_curve_point_type_get_type ()) + +GType gimp_curve_point_type_get_type (void) G_GNUC_CONST; + +typedef enum /*< pdb-skip >*/ +{ + GIMP_CURVE_POINT_SMOOTH, /*< desc="Smooth" >*/ + GIMP_CURVE_POINT_CORNER /*< desc="Corner" >*/ +} GimpCurvePointType; + + #define GIMP_TYPE_CURVE_TYPE (gimp_curve_type_get_type ()) GType gimp_curve_type_get_type (void) G_GNUC_CONST; diff --git a/app/core/gimpcurve.c b/app/core/gimpcurve.c index 2a8e1f4302..ae12d15af3 100644 --- a/app/core/gimpcurve.c +++ b/app/core/gimpcurve.c @@ -46,6 +46,7 @@ enum PROP_CURVE_TYPE, PROP_N_POINTS, PROP_POINTS, + PROP_POINT_TYPES, PROP_N_SAMPLES, PROP_SAMPLES }; @@ -171,6 +172,17 @@ gimp_curve_class_init (GimpCurveClass *klass) GIMP_PARAM_STATIC_STRINGS | GIMP_CONFIG_PARAM_FLAGS)); + array_spec = g_param_spec_enum ("point-type", NULL, NULL, + GIMP_TYPE_CURVE_POINT_TYPE, + GIMP_CURVE_POINT_SMOOTH, + GIMP_PARAM_READWRITE); + g_object_class_install_property (object_class, PROP_POINT_TYPES, + gimp_param_spec_value_array ("point-types", + NULL, NULL, + array_spec, + GIMP_PARAM_STATIC_STRINGS | + GIMP_CONFIG_PARAM_FLAGS)); + GIMP_CONFIG_PROP_INT (object_class, PROP_N_SAMPLES, "n-samples", "Number of Samples", @@ -248,18 +260,22 @@ gimp_curve_set_property (GObject *object, case PROP_POINTS: { GimpValueArray *array = g_value_get_boxed (value); + GimpCurvePoint *points; gint length; + gint n_points; gint i; - curve->n_points = 0; - g_clear_pointer (&curve->points, g_free); - if (! array) - break; + { + gimp_curve_clear_points (curve); + + break; + } length = gimp_value_array_length (array) / 2; - curve->points = g_new (GimpVector2, length); + n_points = 0; + points = g_new (GimpCurvePoint, length); for (i = 0; i < length; i++) { @@ -270,22 +286,76 @@ gimp_curve_set_property (GObject *object, if (g_value_get_double (x) < 0.0) continue; - curve->points[curve->n_points].x = CLAMP (g_value_get_double (x), - 0.0, 1.0); - curve->points[curve->n_points].y = CLAMP (g_value_get_double (y), - 0.0, 1.0); + points[n_points].x = CLAMP (g_value_get_double (x), 0.0, 1.0); + points[n_points].y = CLAMP (g_value_get_double (y), 0.0, 1.0); - if (curve->n_points > 0) + if (n_points > 0) { - curve->points[curve->n_points].x = MAX ( - curve->points[curve->n_points].x, - curve->points[curve->n_points - 1].x); + points[n_points].x = MAX (points[n_points].x, + points[n_points - 1].x); } - curve->n_points++; + if (n_points < curve->n_points) + points[n_points].type = curve->points[n_points].type; + else + points[n_points].type = GIMP_CURVE_POINT_SMOOTH; + + n_points++; } + g_free (curve->points); + + curve->n_points = n_points; + curve->points = points; + g_object_notify (object, "n-points"); + g_object_notify (object, "point-types"); + } + break; + + case PROP_POINT_TYPES: + { + GimpValueArray *array = g_value_get_boxed (value); + GimpCurvePoint *points; + gint length; + gdouble x = 0.0; + gdouble y = 0.0; + gint i; + + if (! array) + { + gimp_curve_clear_points (curve); + + break; + } + + length = gimp_value_array_length (array); + + points = g_new (GimpCurvePoint, length); + + for (i = 0; i < length; i++) + { + GValue *type = gimp_value_array_index (array, i); + + points[i].type = g_value_get_enum (type); + + if (i < curve->n_points) + { + x = curve->points[i].x; + y = curve->points[i].y; + } + + points[i].x = x; + points[i].y = y; + } + + g_free (curve->points); + + curve->n_points = length; + curve->points = points; + + g_object_notify (object, "n-points"); + g_object_notify (object, "points"); } break; @@ -360,6 +430,26 @@ gimp_curve_get_property (GObject *object, } break; + case PROP_POINT_TYPES: + { + GimpValueArray *array = gimp_value_array_new (curve->n_points); + GValue v = G_VALUE_INIT; + gint i; + + g_value_init (&v, GIMP_TYPE_CURVE_POINT_TYPE); + + for (i = 0; i < curve->n_points; i++) + { + g_value_set_enum (&v, curve->points[i].type); + gimp_value_array_append (array, &v); + } + + g_value_unset (&v); + + g_value_take_boxed (value, array); + } + break; + case PROP_N_SAMPLES: g_value_set_int (value, curve->n_samples); break; @@ -397,7 +487,7 @@ gimp_curve_get_memsize (GimpObject *object, GimpCurve *curve = GIMP_CURVE (object); gint64 memsize = 0; - memsize += curve->n_points * sizeof (GimpVector2); + memsize += curve->n_points * sizeof (GimpCurvePoint); memsize += curve->n_samples * sizeof (gdouble); return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object, @@ -513,7 +603,7 @@ gimp_curve_equal (GimpConfig *a, if (a_curve->n_points != b_curve->n_points || memcmp (a_curve->points, b_curve->points, - sizeof (GimpVector2) * a_curve->n_points)) + sizeof (GimpCurvePoint) * a_curve->n_points)) { return FALSE; } @@ -602,16 +692,19 @@ gimp_curve_reset (GimpCurve *curve, g_free (curve->points); curve->n_points = 2; - curve->points = g_new (GimpVector2, 2); + curve->points = g_new (GimpCurvePoint, 2); - curve->points[0].x = 0.0; - curve->points[0].y = 0.0; + curve->points[0].x = 0.0; + curve->points[0].y = 0.0; + curve->points[0].type = GIMP_CURVE_POINT_SMOOTH; - curve->points[1].x = 1.0; - curve->points[1].y = 1.0; + curve->points[1].x = 1.0; + curve->points[1].y = 1.0; + curve->points[1].type = GIMP_CURVE_POINT_SMOOTH; g_object_notify (G_OBJECT (curve), "n-points"); g_object_notify (G_OBJECT (curve), "points"); + g_object_notify (G_OBJECT (curve), "point-types"); if (reset_type) { @@ -650,19 +743,21 @@ gimp_curve_set_curve_type (GimpCurve *curve, * points */ curve->n_points = 9; - curve->points = g_new (GimpVector2, 9); + curve->points = g_new (GimpCurvePoint, 9); for (i = 0; i < curve->n_points; i++) { gint sample = i * (curve->n_samples - 1) / (curve->n_points - 1); - curve->points[i].x = (gdouble) sample / - (gdouble) (curve->n_samples - 1); - curve->points[i].y = curve->samples[sample]; + curve->points[i].x = (gdouble) sample / + (gdouble) (curve->n_samples - 1); + curve->points[i].y = curve->samples[sample]; + curve->points[i].type = GIMP_CURVE_POINT_SMOOTH; } g_object_notify (G_OBJECT (curve), "n-points"); g_object_notify (G_OBJECT (curve), "points"); + g_object_notify (G_OBJECT (curve), "point-types"); } else { @@ -795,8 +890,8 @@ gimp_curve_add_point (GimpCurve *curve, gdouble x, gdouble y) { - GimpVector2 *points; - gint point; + GimpCurvePoint *points; + gint point; g_return_val_if_fail (GIMP_IS_CURVE (curve), -1); @@ -812,15 +907,16 @@ gimp_curve_add_point (GimpCurve *curve, break; } - points = g_new (GimpVector2, curve->n_points + 1); + points = g_new (GimpCurvePoint, curve->n_points + 1); memcpy (points, curve->points, - point * sizeof (GimpVector2)); + point * sizeof (GimpCurvePoint)); memcpy (points + point + 1, curve->points + point, - (curve->n_points - point) * sizeof (GimpVector2)); + (curve->n_points - point) * sizeof (GimpCurvePoint)); - points[point].x = x; - points[point].y = y; + points[point].x = x; + points[point].y = y; + points[point].type = GIMP_CURVE_POINT_SMOOTH; g_free (curve->points); @@ -829,6 +925,7 @@ gimp_curve_add_point (GimpCurve *curve, g_object_notify (G_OBJECT (curve), "n-points"); g_object_notify (G_OBJECT (curve), "points"); + g_object_notify (G_OBJECT (curve), "point-types"); gimp_data_dirty (GIMP_DATA (curve)); @@ -839,17 +936,17 @@ void gimp_curve_delete_point (GimpCurve *curve, gint point) { - GimpVector2 *points; + GimpCurvePoint *points; g_return_if_fail (GIMP_IS_CURVE (curve)); g_return_if_fail (point >= 0 && point < curve->n_points); - points = g_new (GimpVector2, curve->n_points - 1); + points = g_new (GimpCurvePoint, curve->n_points - 1); memcpy (points, curve->points, - point * sizeof (GimpVector2)); + point * sizeof (GimpCurvePoint)); memcpy (points + point, curve->points + point + 1, - (curve->n_points - point - 1) * sizeof (GimpVector2)); + (curve->n_points - point - 1) * sizeof (GimpCurvePoint)); g_free (curve->points); @@ -858,6 +955,7 @@ gimp_curve_delete_point (GimpCurve *curve, g_object_notify (G_OBJECT (curve), "n-points"); g_object_notify (G_OBJECT (curve), "points"); + g_object_notify (G_OBJECT (curve), "point-types"); gimp_data_dirty (GIMP_DATA (curve)); } @@ -913,6 +1011,31 @@ gimp_curve_get_point (GimpCurve *curve, if (y) *y = curve->points[point].y; } +void +gimp_curve_set_point_type (GimpCurve *curve, + gint point, + GimpCurvePointType type) +{ + g_return_if_fail (GIMP_IS_CURVE (curve)); + g_return_if_fail (point >= 0 && point < curve->n_points); + + curve->points[point].type = type; + + g_object_notify (G_OBJECT (curve), "point-types"); + + gimp_data_dirty (GIMP_DATA (curve)); +} + +GimpCurvePointType +gimp_curve_get_point_type (GimpCurve *curve, + gint point) +{ + g_return_val_if_fail (GIMP_IS_CURVE (curve), GIMP_CURVE_POINT_SMOOTH); + g_return_val_if_fail (point >= 0 && point < curve->n_points, GIMP_CURVE_POINT_SMOOTH); + + return curve->points[point].type; +} + void gimp_curve_clear_points (GimpCurve *curve) { @@ -925,6 +1048,7 @@ gimp_curve_clear_points (GimpCurve *curve) g_object_notify (G_OBJECT (curve), "n-points"); g_object_notify (G_OBJECT (curve), "points"); + g_object_notify (G_OBJECT (curve), "point-types"); gimp_data_dirty (GIMP_DATA (curve)); } @@ -1000,8 +1124,8 @@ gimp_curve_calculate (GimpCurve *curve) /* Initialize boundary curve points */ if (curve->n_points > 0) { - GimpVector2 point; - gint boundary; + GimpCurvePoint point; + gint boundary; point = curve->points[0]; boundary = ROUND (point.x * (gdouble) (curve->n_samples - 1)); @@ -1023,6 +1147,12 @@ gimp_curve_calculate (GimpCurve *curve) p3 = i + 1; p4 = MIN (i + 2, curve->n_points - 1); + if (curve->points[p2].type == GIMP_CURVE_POINT_CORNER) + p1 = p2; + + if (curve->points[p3].type == GIMP_CURVE_POINT_CORNER) + p4 = p3; + gimp_curve_plot (curve, p1, p2, p3, p4); } diff --git a/app/core/gimpcurve.h b/app/core/gimpcurve.h index b41794c168..71654aa184 100644 --- a/app/core/gimpcurve.h +++ b/app/core/gimpcurve.h @@ -30,21 +30,30 @@ #define GIMP_CURVE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_CURVE, GimpCurveClass)) +typedef struct _GimpCurvePoint GimpCurvePoint; typedef struct _GimpCurveClass GimpCurveClass; +struct _GimpCurvePoint +{ + gdouble x; + gdouble y; + + GimpCurvePointType type; +}; + struct _GimpCurve { - GimpData parent_instance; + GimpData parent_instance; - GimpCurveType curve_type; + GimpCurveType curve_type; - gint n_points; - GimpVector2 *points; + gint n_points; + GimpCurvePoint *points; - gint n_samples; - gdouble *samples; + gint n_samples; + gdouble *samples; - gboolean identity; /* whether the curve is an identity mapping */ + gboolean identity; /* whether the curve is an identity mapping */ }; struct _GimpCurveClass @@ -53,58 +62,63 @@ struct _GimpCurveClass }; -GType gimp_curve_get_type (void) G_GNUC_CONST; +GType gimp_curve_get_type (void) G_GNUC_CONST; -GimpData * gimp_curve_new (const gchar *name); -GimpData * gimp_curve_get_standard (void); +GimpData * gimp_curve_new (const gchar *name); +GimpData * gimp_curve_get_standard (void); -void gimp_curve_reset (GimpCurve *curve, - gboolean reset_type); +void gimp_curve_reset (GimpCurve *curve, + gboolean reset_type); -void gimp_curve_set_curve_type (GimpCurve *curve, - GimpCurveType curve_type); -GimpCurveType gimp_curve_get_curve_type (GimpCurve *curve); +void gimp_curve_set_curve_type (GimpCurve *curve, + GimpCurveType curve_type); +GimpCurveType gimp_curve_get_curve_type (GimpCurve *curve); -gint gimp_curve_get_n_points (GimpCurve *curve); +gint gimp_curve_get_n_points (GimpCurve *curve); -void gimp_curve_set_n_samples (GimpCurve *curve, - gint n_samples); -gint gimp_curve_get_n_samples (GimpCurve *curve); +void gimp_curve_set_n_samples (GimpCurve *curve, + gint n_samples); +gint gimp_curve_get_n_samples (GimpCurve *curve); -gint gimp_curve_get_point_at (GimpCurve *curve, - gdouble x); -gint gimp_curve_get_closest_point (GimpCurve *curve, - gdouble x, - gdouble y, - gdouble max_distance); +gint gimp_curve_get_point_at (GimpCurve *curve, + gdouble x); +gint gimp_curve_get_closest_point (GimpCurve *curve, + gdouble x, + gdouble y, + gdouble max_distance); -gint gimp_curve_add_point (GimpCurve *curve, - gdouble x, - gdouble y); -void gimp_curve_delete_point (GimpCurve *curve, - gint point); -void gimp_curve_set_point (GimpCurve *curve, - gint point, - gdouble x, - gdouble y); -void gimp_curve_move_point (GimpCurve *curve, - gint point, - gdouble y); -void gimp_curve_get_point (GimpCurve *curve, - gint point, - gdouble *x, - gdouble *y); -void gimp_curve_clear_points (GimpCurve *curve); +gint gimp_curve_add_point (GimpCurve *curve, + gdouble x, + gdouble y); +void gimp_curve_delete_point (GimpCurve *curve, + gint point); +void gimp_curve_set_point (GimpCurve *curve, + gint point, + gdouble x, + gdouble y); +void gimp_curve_move_point (GimpCurve *curve, + gint point, + gdouble y); +void gimp_curve_get_point (GimpCurve *curve, + gint point, + gdouble *x, + gdouble *y); +void gimp_curve_set_point_type (GimpCurve *curve, + gint point, + GimpCurvePointType type); +GimpCurvePointType gimp_curve_get_point_type (GimpCurve *curve, + gint point); +void gimp_curve_clear_points (GimpCurve *curve); -void gimp_curve_set_curve (GimpCurve *curve, - gdouble x, - gdouble y); +void gimp_curve_set_curve (GimpCurve *curve, + gdouble x, + gdouble y); -gboolean gimp_curve_is_identity (GimpCurve *curve); +gboolean gimp_curve_is_identity (GimpCurve *curve); -void gimp_curve_get_uchar (GimpCurve *curve, - gint n_samples, - guchar *samples); +void gimp_curve_get_uchar (GimpCurve *curve, + gint n_samples, + guchar *samples); #endif /* __GIMP_CURVE_H__ */ diff --git a/app/tools/gimpcurvestool.c b/app/tools/gimpcurvestool.c index 43217aa189..65c686962f 100644 --- a/app/tools/gimpcurvestool.c +++ b/app/tools/gimpcurvestool.c @@ -124,6 +124,8 @@ static void curves_graph_selection_callback (GtkWidget *widget static void curves_point_coords_callback (GtkWidget *widget, GimpCurvesTool *tool); +static void curves_point_type_callback (GtkWidget *widget, + GimpCurvesTool *tool); static void curves_curve_type_callback (GtkWidget *widget, GimpCurvesTool *tool); @@ -268,9 +270,19 @@ gimp_curves_tool_button_release (GimpTool *tool, if (point < 0) { + GimpCurvePointType type = GIMP_CURVE_POINT_SMOOTH; + + point = gimp_curve_view_get_selected ( + GIMP_CURVE_VIEW (c_tool->graph)); + + if (point >= 0) + type = gimp_curve_get_point_type (curve, point); + point = gimp_curve_add_point ( curve, value, gimp_curve_map_value (curve, value)); + + gimp_curve_set_point_type (curve, point, type); } gimp_curve_view_set_selected (GIMP_CURVE_VIEW (c_tool->graph), point); @@ -278,6 +290,16 @@ gimp_curves_tool_button_release (GimpTool *tool, else if (state & gimp_get_toggle_behavior_mask ()) { GimpHistogramChannel channel; + GimpCurvePointType type = GIMP_CURVE_POINT_SMOOTH; + gint point; + + point = gimp_curve_view_get_selected (GIMP_CURVE_VIEW (c_tool->graph)); + + if (point >= 0) + { + type = gimp_curve_get_point_type (config->curve[config->channel], + point); + } for (channel = GIMP_HISTOGRAM_VALUE; channel <= GIMP_HISTOGRAM_ALPHA; @@ -288,8 +310,6 @@ gimp_curves_tool_button_release (GimpTool *tool, if (value != -1) { - gint point; - point = gimp_curve_get_point_at (curve, value); if (point < 0) @@ -297,6 +317,8 @@ gimp_curves_tool_button_release (GimpTool *tool, point = gimp_curve_add_point ( curve, value, gimp_curve_map_value (curve, value)); + + gimp_curve_set_point_type (curve, point, type); } if (channel == config->channel) @@ -604,10 +626,25 @@ gimp_curves_tool_dialog (GimpFilterTool *filter_tool) gtk_label_set_mnemonic_widget (GTK_LABEL (label), tool->point_output); + label = gtk_label_new_with_mnemonic (_("T_ype:")); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + gtk_widget_show (label); + + hbox2 = gimp_enum_icon_box_new (GIMP_TYPE_CURVE_POINT_TYPE, + "gimp-curve-point", + GTK_ICON_SIZE_MENU, + G_CALLBACK (curves_point_type_callback), + tool, + &tool->point_type); + gtk_box_pack_start (GTK_BOX (hbox), hbox2, FALSE, FALSE, 0); + gtk_widget_show (hbox2); + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); gtk_box_pack_start (GTK_BOX (frame_vbox), hbox, FALSE, FALSE, 0); gtk_widget_show (hbox); + gtk_label_set_mnemonic_widget (GTK_LABEL (label), tool->point_type); + label = gtk_label_new_with_mnemonic (_("Curve _type:")); gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); gtk_widget_show (label); @@ -942,6 +979,18 @@ gimp_curves_tool_update_point (GimpCurvesTool *tool) g_signal_handlers_unblock_by_func (tool->point_output, curves_point_coords_callback, tool); + + g_signal_handlers_block_by_func (tool->point_type, + curves_point_type_callback, + tool); + + gimp_int_radio_group_set_active ( + GTK_RADIO_BUTTON (tool->point_type), + gimp_curve_get_point_type (curve, point)); + + g_signal_handlers_unblock_by_func (tool->point_type, + curves_point_type_callback, + tool); } } @@ -1049,6 +1098,28 @@ curves_point_coords_callback (GtkWidget *widget, } } +static void +curves_point_type_callback (GtkWidget *widget, + GimpCurvesTool *tool) +{ + GimpFilterTool *filter_tool = GIMP_FILTER_TOOL (tool); + GimpCurvesConfig *config = GIMP_CURVES_CONFIG (filter_tool->config); + GimpCurve *curve = config->curve[config->channel]; + gint point; + + point = gimp_curve_view_get_selected (GIMP_CURVE_VIEW (tool->graph)); + + if (point >= 0 && gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) + { + GimpCurvePointType type; + + type = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), + "gimp-item-data")); + + gimp_curve_set_point_type (curve, point, type); + } +} + static void curves_curve_type_callback (GtkWidget *widget, GimpCurvesTool *tool) diff --git a/app/tools/gimpcurvestool.h b/app/tools/gimpcurvestool.h index ba897ec008..e80f776cb7 100644 --- a/app/tools/gimpcurvestool.h +++ b/app/tools/gimpcurvestool.h @@ -46,6 +46,7 @@ struct _GimpCurvesTool GtkWidget *point_box; GtkWidget *point_input; GtkWidget *point_output; + GtkWidget *point_type; GtkWidget *curve_type; /* export dialog */ diff --git a/app/widgets/gimpcurveview.c b/app/widgets/gimpcurveview.c index 1e971569ac..121f5eb010 100644 --- a/app/widgets/gimpcurveview.c +++ b/app/widgets/gimpcurveview.c @@ -442,16 +442,38 @@ gimp_curve_view_draw_point (GimpCurveView *view, y = 1.0 - y; -#define RADIUS 3 +#define CIRCLE_RADIUS 3 +#define DIAMOND_RADIUS (G_SQRT2 * CIRCLE_RADIUS) - cairo_move_to (cr, - border + (gdouble) (width - 1) * x + RADIUS, - border + (gdouble) (height - 1) * y); - cairo_arc (cr, - border + (gdouble) (width - 1) * x, - border + (gdouble) (height - 1) * y, - RADIUS, - 0, 2 * G_PI); + switch (gimp_curve_get_point_type (view->curve, i)) + { + case GIMP_CURVE_POINT_SMOOTH: + cairo_move_to (cr, + border + (gdouble) (width - 1) * x + CIRCLE_RADIUS, + border + (gdouble) (height - 1) * y); + cairo_arc (cr, + border + (gdouble) (width - 1) * x, + border + (gdouble) (height - 1) * y, + CIRCLE_RADIUS, + 0, 2 * G_PI); + break; + + case GIMP_CURVE_POINT_CORNER: + cairo_move_to (cr, + border + (gdouble) (width - 1) * x, + border + (gdouble) (height - 1) * y - DIAMOND_RADIUS); + cairo_line_to (cr, + border + (gdouble) (width - 1) * x + DIAMOND_RADIUS, + border + (gdouble) (height - 1) * y); + cairo_line_to (cr, + border + (gdouble) (width - 1) * x, + border + (gdouble) (height - 1) * y + DIAMOND_RADIUS); + cairo_line_to (cr, + border + (gdouble) (width - 1) * x - DIAMOND_RADIUS, + border + (gdouble) (height - 1) * y); + cairo_close_path (cr); + break; + } } static void @@ -837,10 +859,17 @@ gimp_curve_view_button_press (GtkWidget *widget, if (point < 0) { + GimpCurvePointType type = GIMP_CURVE_POINT_SMOOTH; + if (bevent->state & gimp_get_constrain_behavior_mask ()) y = 1.0 - gimp_curve_map_value (view->orig_curve, x); + if (view->selected >= 0) + type = gimp_curve_get_point_type (curve, view->selected); + point = gimp_curve_add_point (curve, x, 1.0 - y); + + gimp_curve_set_point_type (curve, point, type); } if (point > 0) @@ -859,6 +888,8 @@ gimp_curve_view_button_press (GtkWidget *widget, view->offset_x = point_x - x; view->offset_y = (1.0 - point_y) - y; + + view->point_type = gimp_curve_get_point_type (curve, point); break; case GIMP_CURVE_FREE: @@ -972,6 +1003,9 @@ gimp_curve_view_motion_notify (GtkWidget *widget, gimp_curve_view_set_selected ( view, gimp_curve_add_point (curve, x, 1.0 - y)); + + gimp_curve_set_point_type (curve, + view->selected, view->point_type); } else { diff --git a/app/widgets/gimpcurveview.h b/app/widgets/gimpcurveview.h index 903c8ec393..add6048b89 100644 --- a/app/widgets/gimpcurveview.h +++ b/app/widgets/gimpcurveview.h @@ -50,6 +50,7 @@ struct _GimpCurveView gint selected; gdouble offset_x; gdouble offset_y; + GimpCurvePointType point_type; gdouble last_x; gdouble last_y; gdouble leftmost; diff --git a/icons/Color/16/gimp-curve-point-corner.png b/icons/Color/16/gimp-curve-point-corner.png new file mode 100644 index 0000000000000000000000000000000000000000..2274faa1c85f8d0851d1f6e504979a63017eff0d GIT binary patch literal 422 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#Vf4nJ z@ErkR#;MwT(m+AU64!{5;QX|b^2DN4hVt@qz0ADq;^f4FRK5J7^x5xhq=1T~L5e~$ zOL9^f+%t0v6rA&O@{1Halk@WwLNZcwQ#GaEaR8M$f|R+W7AF^F7L;V>=P|hEWhCY$ zr>5vAq~_%$7Nvt(6(y;8DXA$6C5d_I`MQZkCAvA8Nkyp&X+R_0J$(bxd3LM@8n)ik z#WBR9ck1Q6d`$)-Z4cMC3+G=t>ByGQ(0Ka+UytFe85Q+9Z9jG;EwC?p_jy}p)siDj zJR7da`9Iv2yZ-bhnTBMJhm*N-3+{jKU$x4>c-OjW#*2p+MF>qgrChzkV$z|T9-Mt{ z4B4}urKLsg>AO<;m*tGg$-DPm_4h>Cvu!Ap(SH|L^2>mye8H_f&U!*eRVV8BxpsYw zQ)w@+59N5sJm-03ndhu!FTY$jSerjd`nmp;MK`aew=c;6I-SAO)z4*}Q$iB}$CsYw literal 0 HcmV?d00001 diff --git a/icons/Color/16/gimp-curve-point-smooth.png b/icons/Color/16/gimp-curve-point-smooth.png new file mode 100644 index 0000000000000000000000000000000000000000..aaf78b74f039364d485ac3689b9ab7e1ea9bb6f1 GIT binary patch literal 541 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#Vf4nJ z@ErkR#;MwT(m+AU64!{5;QX|b^2DN4hVt@qz0ADq;^f4FRK5J7^x5xhq=1T~L5e~$ zOL9^f+%t0v6rA&O@{1Halk@WwLNZcwQ#GaEaR8M$f|R+W7AF^F7L;V>=P|hEWhCY$ zr>5vAq~_%$7Nvt(6(y;8DXA$6C5d_I`MQZkCAvA8Nkyp&X+R_0J$(bxd3LO3U|>}9 zba4!^=-oQWI_t25K->R9tJ9vMIXiopZ*hA(VAgPR)oSjaB%_de>8&YG-W{E9agJLT zvrZ1F+Tr`khb!96rC+D<&xQ?W&iyy+XZ;s^#wOvJV>sVm9*w2PR$qN}P@;JH^Pjp5 zJJ#*~Zj*04|9t!+jZ;yXL8n%}|Gl1J$4eH+4U>cXq|bV-EEHf_`%KG4(^Rik{OQvB z@9o!KfBk!19ixKp8NQriPd@X;ym+OG=eeD>3<=Lx>zvNZVRQ}jnelT| z6r=D}u}fM?zYZ0uxibjX?pXIbja!1R{k_YV$h8dfp6BK;I(1aN%j~s|SQD6So2BBd zxjc5lvi^|SbFNiwiP4jvtTI!Uul?l8=X(W`c1P&UJ8Ynn6U}ODedbMs^uI;<9}jiR VtX=$i4>0%{JYD@<);T3K0RXRA(y#yk literal 0 HcmV?d00001 diff --git a/icons/Color/scalable/gimp-curve-point-corner.svg b/icons/Color/scalable/gimp-curve-point-corner.svg new file mode 100644 index 0000000000..0f92e061a1 --- /dev/null +++ b/icons/Color/scalable/gimp-curve-point-corner.svg @@ -0,0 +1,113 @@ + + + + + + + image/svg+xml + + Gimp Color Icon Theme + + + many unknown and unnamed, Andrew Chadwick, Alexandre Prokoudine, Aryeom Han, Benoit Touchette, Jakub Steiner, Jehan, Johannes Matschke, Kevin Payne, Klaus Staedtler, Marek Dvoroznak, Michael Natterer + + + Enhanced, extended tango-art-libre for GIMP + + + + + + + + + + + + + + + + + + + + + + diff --git a/icons/Color/scalable/gimp-curve-point-smooth.svg b/icons/Color/scalable/gimp-curve-point-smooth.svg new file mode 100644 index 0000000000..cf5806d416 --- /dev/null +++ b/icons/Color/scalable/gimp-curve-point-smooth.svg @@ -0,0 +1,115 @@ + + + + + + + image/svg+xml + + Gimp Color Icon Theme + + + many unknown and unnamed, Andrew Chadwick, Alexandre Prokoudine, Aryeom Han, Benoit Touchette, Jakub Steiner, Jehan, Johannes Matschke, Kevin Payne, Klaus Staedtler, Marek Dvoroznak, Michael Natterer + + + Enhanced, extended tango-art-libre for GIMP + + + + + + + + + + + + + + + + + + + + + + diff --git a/icons/Legacy/16/gimp-curve-point-corner.png b/icons/Legacy/16/gimp-curve-point-corner.png new file mode 100644 index 0000000000000000000000000000000000000000..12fc69403009ef1095b65e516aa967294e0497e7 GIT binary patch literal 124 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`&YmugAr-fh6BZc0XiVB<`oH~= zoR`Vu91gRyF49f@#*WS%7ke%X1eq+BIOOuyLj5*(2&c;`7v)ePq0mW2p+>@i3=Aj! WhkicAuxlgGI0jEwKbLh*2~7ZW{U;Ux literal 0 HcmV?d00001 diff --git a/icons/Legacy/16/gimp-curve-point-smooth.png b/icons/Legacy/16/gimp-curve-point-smooth.png new file mode 100644 index 0000000000000000000000000000000000000000..c0a8ff41d7b554dcdc09f8bfe3a53cf2b11f3b46 GIT binary patch literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`NuDl_Ar-fh6C~CwXlZPGD8kHq zI9$VyRaBYdiKK*tpOJyVpW}`GPFEkW{4i0LZn}K)f9H{iy~SND%zlZ+541ViYFaas z7Mbjtz`Mh%Y2WG_JQ1!2?p zUk71ECym(^Ktah8*NBqf{Irtt#G+J&^73-M%)IR4#g<1Xt!J<>zE3D|ja7=P86_q~@mfEzw*JRNCU{;uvDlyY;dmUxNZq>%;Io zH;XBGkCwG(SxifgJ)&@lt2zJKe<3G^e=^4IY4_F`ryOu6w_~GJa7?{lm0xf>j=q o)TOS_1#Vk@6kkv8I{fg2-#71+H(Ad4pwMCPboFyt=akR{0Hfn>iU0rr literal 0 HcmV?d00001 diff --git a/icons/Symbolic/16/gimp-curve-point-smooth.png b/icons/Symbolic/16/gimp-curve-point-smooth.png new file mode 100644 index 0000000000000000000000000000000000000000..2bc58cbb874a05832dfcb6b06e3699c1743bb6ca GIT binary patch literal 387 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#Vf2?p zUk71ECym(^Ktah8*NBqf{Irtt#G+J&^73-M%)IR4#g<1Xt!J<>zE3D|ja7=P86_q~@mfEzw*JRC?9Z#WBR9_v|FYyh9EGuJ@Nj z-fxt4nYiFF!|lj946i!6xOeiIE8O1McFA>$^o6z7vvPl!Jg_k2Th?^{ZN|OX7qcE* z+_=A0py~9c9L_V1+lzmCU$R;n@}zQJ6>Dl_-gs3}Va)3}@E7%;k=2=lb#UPJB~!(H^xQ`qvmxFuTSsv`Ye_Ueuq_6{g77Xmhx4oi{N-WR)VOhi! Y_sMs|97B<}Ko2r_y85}Sb4q9e07IjhnE(I) literal 0 HcmV?d00001 diff --git a/icons/Symbolic/scalable/gimp-curve-point-corner.svg b/icons/Symbolic/scalable/gimp-curve-point-corner.svg new file mode 100644 index 0000000000..1a74071ecb --- /dev/null +++ b/icons/Symbolic/scalable/gimp-curve-point-corner.svg @@ -0,0 +1,94 @@ + + + + + + + image/svg+xml + + + + + Barbara Muraus, Jakub Steiner, Klaus Staedtler + + + Images originally created as the "Art Libre" icon set. Extended and adopted for GIMP + + + + + + + + + + + + + + + diff --git a/icons/Symbolic/scalable/gimp-curve-point-smooth.svg b/icons/Symbolic/scalable/gimp-curve-point-smooth.svg new file mode 100644 index 0000000000..aee5c7ecc7 --- /dev/null +++ b/icons/Symbolic/scalable/gimp-curve-point-smooth.svg @@ -0,0 +1,95 @@ + + + + + + + image/svg+xml + + + + + Barbara Muraus, Jakub Steiner, Klaus Staedtler + + + Images originally created as the "Art Libre" icon set. Extended and adopted for GIMP + + + + + + + + + + + + + + + diff --git a/icons/icon-list.mk b/icons/icon-list.mk index 6aa882ae39..637e7a0ce6 100644 --- a/icons/icon-list.mk +++ b/icons/icon-list.mk @@ -101,6 +101,8 @@ scalable_images = \ scalable/gimp-convert-rgb.svg \ scalable/gimp-cursor.svg \ scalable/gimp-curve-free.svg \ + scalable/gimp-curve-point-corner.svg \ + scalable/gimp-curve-point-smooth.svg \ scalable/gimp-curve-smooth.svg \ scalable/gimp-dashboard.svg \ scalable/gimp-default-colors.svg \ @@ -610,6 +612,8 @@ icons16_images = \ 16/gimp-convert-rgb.png \ 16/gimp-cursor.png \ 16/gimp-curve-free.png \ + 16/gimp-curve-point-corner.png \ + 16/gimp-curve-point-smooth.png \ 16/gimp-curve-smooth.png \ 16/gimp-dashboard.png \ 16/gimp-device-status.png \