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.
This commit is contained in:
Ell 2019-04-19 10:09:08 -04:00
parent 5140d903b8
commit 33e47c85a2
19 changed files with 810 additions and 98 deletions

View file

@ -360,6 +360,35 @@ gimp_convolution_type_get_type (void)
return type; 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 GType
gimp_curve_type_get_type (void) gimp_curve_type_get_type (void)
{ {

View file

@ -196,6 +196,17 @@ typedef enum /*< pdb-skip >*/
} GimpConvolutionType; } 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 ()) #define GIMP_TYPE_CURVE_TYPE (gimp_curve_type_get_type ())
GType gimp_curve_type_get_type (void) G_GNUC_CONST; GType gimp_curve_type_get_type (void) G_GNUC_CONST;

View file

@ -46,6 +46,7 @@ enum
PROP_CURVE_TYPE, PROP_CURVE_TYPE,
PROP_N_POINTS, PROP_N_POINTS,
PROP_POINTS, PROP_POINTS,
PROP_POINT_TYPES,
PROP_N_SAMPLES, PROP_N_SAMPLES,
PROP_SAMPLES PROP_SAMPLES
}; };
@ -171,6 +172,17 @@ gimp_curve_class_init (GimpCurveClass *klass)
GIMP_PARAM_STATIC_STRINGS | GIMP_PARAM_STATIC_STRINGS |
GIMP_CONFIG_PARAM_FLAGS)); 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, GIMP_CONFIG_PROP_INT (object_class, PROP_N_SAMPLES,
"n-samples", "n-samples",
"Number of Samples", "Number of Samples",
@ -248,18 +260,22 @@ gimp_curve_set_property (GObject *object,
case PROP_POINTS: case PROP_POINTS:
{ {
GimpValueArray *array = g_value_get_boxed (value); GimpValueArray *array = g_value_get_boxed (value);
GimpCurvePoint *points;
gint length; gint length;
gint n_points;
gint i; gint i;
curve->n_points = 0;
g_clear_pointer (&curve->points, g_free);
if (! array) if (! array)
break; {
gimp_curve_clear_points (curve);
break;
}
length = gimp_value_array_length (array) / 2; 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++) for (i = 0; i < length; i++)
{ {
@ -270,22 +286,76 @@ gimp_curve_set_property (GObject *object,
if (g_value_get_double (x) < 0.0) if (g_value_get_double (x) < 0.0)
continue; continue;
curve->points[curve->n_points].x = CLAMP (g_value_get_double (x), points[n_points].x = CLAMP (g_value_get_double (x), 0.0, 1.0);
0.0, 1.0); points[n_points].y = CLAMP (g_value_get_double (y), 0.0, 1.0);
curve->points[curve->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 ( points[n_points].x = MAX (points[n_points].x,
curve->points[curve->n_points].x, points[n_points - 1].x);
curve->points[curve->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, "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; break;
@ -360,6 +430,26 @@ gimp_curve_get_property (GObject *object,
} }
break; 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: case PROP_N_SAMPLES:
g_value_set_int (value, curve->n_samples); g_value_set_int (value, curve->n_samples);
break; break;
@ -397,7 +487,7 @@ gimp_curve_get_memsize (GimpObject *object,
GimpCurve *curve = GIMP_CURVE (object); GimpCurve *curve = GIMP_CURVE (object);
gint64 memsize = 0; gint64 memsize = 0;
memsize += curve->n_points * sizeof (GimpVector2); memsize += curve->n_points * sizeof (GimpCurvePoint);
memsize += curve->n_samples * sizeof (gdouble); memsize += curve->n_samples * sizeof (gdouble);
return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object, 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 || if (a_curve->n_points != b_curve->n_points ||
memcmp (a_curve->points, b_curve->points, memcmp (a_curve->points, b_curve->points,
sizeof (GimpVector2) * a_curve->n_points)) sizeof (GimpCurvePoint) * a_curve->n_points))
{ {
return FALSE; return FALSE;
} }
@ -602,16 +692,19 @@ gimp_curve_reset (GimpCurve *curve,
g_free (curve->points); g_free (curve->points);
curve->n_points = 2; 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].x = 0.0;
curve->points[0].y = 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].x = 1.0;
curve->points[1].y = 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), "n-points");
g_object_notify (G_OBJECT (curve), "points"); g_object_notify (G_OBJECT (curve), "points");
g_object_notify (G_OBJECT (curve), "point-types");
if (reset_type) if (reset_type)
{ {
@ -650,19 +743,21 @@ gimp_curve_set_curve_type (GimpCurve *curve,
* points * points
*/ */
curve->n_points = 9; curve->n_points = 9;
curve->points = g_new (GimpVector2, 9); curve->points = g_new (GimpCurvePoint, 9);
for (i = 0; i < curve->n_points; i++) for (i = 0; i < curve->n_points; i++)
{ {
gint sample = i * (curve->n_samples - 1) / (curve->n_points - 1); gint sample = i * (curve->n_samples - 1) / (curve->n_points - 1);
curve->points[i].x = (gdouble) sample / curve->points[i].x = (gdouble) sample /
(gdouble) (curve->n_samples - 1); (gdouble) (curve->n_samples - 1);
curve->points[i].y = curve->samples[sample]; 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), "n-points");
g_object_notify (G_OBJECT (curve), "points"); g_object_notify (G_OBJECT (curve), "points");
g_object_notify (G_OBJECT (curve), "point-types");
} }
else else
{ {
@ -795,8 +890,8 @@ gimp_curve_add_point (GimpCurve *curve,
gdouble x, gdouble x,
gdouble y) gdouble y)
{ {
GimpVector2 *points; GimpCurvePoint *points;
gint point; gint point;
g_return_val_if_fail (GIMP_IS_CURVE (curve), -1); g_return_val_if_fail (GIMP_IS_CURVE (curve), -1);
@ -812,15 +907,16 @@ gimp_curve_add_point (GimpCurve *curve,
break; break;
} }
points = g_new (GimpVector2, curve->n_points + 1); points = g_new (GimpCurvePoint, curve->n_points + 1);
memcpy (points, curve->points, memcpy (points, curve->points,
point * sizeof (GimpVector2)); point * sizeof (GimpCurvePoint));
memcpy (points + point + 1, curve->points + point, 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].x = x;
points[point].y = y; points[point].y = y;
points[point].type = GIMP_CURVE_POINT_SMOOTH;
g_free (curve->points); 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), "n-points");
g_object_notify (G_OBJECT (curve), "points"); g_object_notify (G_OBJECT (curve), "points");
g_object_notify (G_OBJECT (curve), "point-types");
gimp_data_dirty (GIMP_DATA (curve)); gimp_data_dirty (GIMP_DATA (curve));
@ -839,17 +936,17 @@ void
gimp_curve_delete_point (GimpCurve *curve, gimp_curve_delete_point (GimpCurve *curve,
gint point) gint point)
{ {
GimpVector2 *points; GimpCurvePoint *points;
g_return_if_fail (GIMP_IS_CURVE (curve)); g_return_if_fail (GIMP_IS_CURVE (curve));
g_return_if_fail (point >= 0 && point < curve->n_points); 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, memcpy (points, curve->points,
point * sizeof (GimpVector2)); point * sizeof (GimpCurvePoint));
memcpy (points + point, curve->points + point + 1, 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); 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), "n-points");
g_object_notify (G_OBJECT (curve), "points"); g_object_notify (G_OBJECT (curve), "points");
g_object_notify (G_OBJECT (curve), "point-types");
gimp_data_dirty (GIMP_DATA (curve)); gimp_data_dirty (GIMP_DATA (curve));
} }
@ -913,6 +1011,31 @@ gimp_curve_get_point (GimpCurve *curve,
if (y) *y = curve->points[point].y; 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 void
gimp_curve_clear_points (GimpCurve *curve) 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), "n-points");
g_object_notify (G_OBJECT (curve), "points"); g_object_notify (G_OBJECT (curve), "points");
g_object_notify (G_OBJECT (curve), "point-types");
gimp_data_dirty (GIMP_DATA (curve)); gimp_data_dirty (GIMP_DATA (curve));
} }
@ -1000,8 +1124,8 @@ gimp_curve_calculate (GimpCurve *curve)
/* Initialize boundary curve points */ /* Initialize boundary curve points */
if (curve->n_points > 0) if (curve->n_points > 0)
{ {
GimpVector2 point; GimpCurvePoint point;
gint boundary; gint boundary;
point = curve->points[0]; point = curve->points[0];
boundary = ROUND (point.x * (gdouble) (curve->n_samples - 1)); boundary = ROUND (point.x * (gdouble) (curve->n_samples - 1));
@ -1023,6 +1147,12 @@ gimp_curve_calculate (GimpCurve *curve)
p3 = i + 1; p3 = i + 1;
p4 = MIN (i + 2, curve->n_points - 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); gimp_curve_plot (curve, p1, p2, p3, p4);
} }

View file

@ -30,21 +30,30 @@
#define GIMP_CURVE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_CURVE, GimpCurveClass)) #define GIMP_CURVE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_CURVE, GimpCurveClass))
typedef struct _GimpCurvePoint GimpCurvePoint;
typedef struct _GimpCurveClass GimpCurveClass; typedef struct _GimpCurveClass GimpCurveClass;
struct _GimpCurvePoint
{
gdouble x;
gdouble y;
GimpCurvePointType type;
};
struct _GimpCurve struct _GimpCurve
{ {
GimpData parent_instance; GimpData parent_instance;
GimpCurveType curve_type; GimpCurveType curve_type;
gint n_points; gint n_points;
GimpVector2 *points; GimpCurvePoint *points;
gint n_samples; gint n_samples;
gdouble *samples; gdouble *samples;
gboolean identity; /* whether the curve is an identity mapping */ gboolean identity; /* whether the curve is an identity mapping */
}; };
struct _GimpCurveClass 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_new (const gchar *name);
GimpData * gimp_curve_get_standard (void); GimpData * gimp_curve_get_standard (void);
void gimp_curve_reset (GimpCurve *curve, void gimp_curve_reset (GimpCurve *curve,
gboolean reset_type); gboolean reset_type);
void gimp_curve_set_curve_type (GimpCurve *curve, void gimp_curve_set_curve_type (GimpCurve *curve,
GimpCurveType curve_type); GimpCurveType curve_type);
GimpCurveType gimp_curve_get_curve_type (GimpCurve *curve); 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, void gimp_curve_set_n_samples (GimpCurve *curve,
gint n_samples); gint n_samples);
gint gimp_curve_get_n_samples (GimpCurve *curve); gint gimp_curve_get_n_samples (GimpCurve *curve);
gint gimp_curve_get_point_at (GimpCurve *curve, gint gimp_curve_get_point_at (GimpCurve *curve,
gdouble x); gdouble x);
gint gimp_curve_get_closest_point (GimpCurve *curve, gint gimp_curve_get_closest_point (GimpCurve *curve,
gdouble x, gdouble x,
gdouble y, gdouble y,
gdouble max_distance); gdouble max_distance);
gint gimp_curve_add_point (GimpCurve *curve, gint gimp_curve_add_point (GimpCurve *curve,
gdouble x, gdouble x,
gdouble y); gdouble y);
void gimp_curve_delete_point (GimpCurve *curve, void gimp_curve_delete_point (GimpCurve *curve,
gint point); gint point);
void gimp_curve_set_point (GimpCurve *curve, void gimp_curve_set_point (GimpCurve *curve,
gint point, gint point,
gdouble x, gdouble x,
gdouble y); gdouble y);
void gimp_curve_move_point (GimpCurve *curve, void gimp_curve_move_point (GimpCurve *curve,
gint point, gint point,
gdouble y); gdouble y);
void gimp_curve_get_point (GimpCurve *curve, void gimp_curve_get_point (GimpCurve *curve,
gint point, gint point,
gdouble *x, gdouble *x,
gdouble *y); gdouble *y);
void gimp_curve_clear_points (GimpCurve *curve); 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, void gimp_curve_set_curve (GimpCurve *curve,
gdouble x, gdouble x,
gdouble y); gdouble y);
gboolean gimp_curve_is_identity (GimpCurve *curve); gboolean gimp_curve_is_identity (GimpCurve *curve);
void gimp_curve_get_uchar (GimpCurve *curve, void gimp_curve_get_uchar (GimpCurve *curve,
gint n_samples, gint n_samples,
guchar *samples); guchar *samples);
#endif /* __GIMP_CURVE_H__ */ #endif /* __GIMP_CURVE_H__ */

View file

@ -124,6 +124,8 @@ static void curves_graph_selection_callback (GtkWidget *widget
static void curves_point_coords_callback (GtkWidget *widget, static void curves_point_coords_callback (GtkWidget *widget,
GimpCurvesTool *tool); GimpCurvesTool *tool);
static void curves_point_type_callback (GtkWidget *widget,
GimpCurvesTool *tool);
static void curves_curve_type_callback (GtkWidget *widget, static void curves_curve_type_callback (GtkWidget *widget,
GimpCurvesTool *tool); GimpCurvesTool *tool);
@ -268,9 +270,19 @@ gimp_curves_tool_button_release (GimpTool *tool,
if (point < 0) 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 ( point = gimp_curve_add_point (
curve, curve,
value, gimp_curve_map_value (curve, value)); 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); 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 ()) else if (state & gimp_get_toggle_behavior_mask ())
{ {
GimpHistogramChannel channel; 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; for (channel = GIMP_HISTOGRAM_VALUE;
channel <= GIMP_HISTOGRAM_ALPHA; channel <= GIMP_HISTOGRAM_ALPHA;
@ -288,8 +310,6 @@ gimp_curves_tool_button_release (GimpTool *tool,
if (value != -1) if (value != -1)
{ {
gint point;
point = gimp_curve_get_point_at (curve, value); point = gimp_curve_get_point_at (curve, value);
if (point < 0) if (point < 0)
@ -297,6 +317,8 @@ gimp_curves_tool_button_release (GimpTool *tool,
point = gimp_curve_add_point ( point = gimp_curve_add_point (
curve, curve,
value, gimp_curve_map_value (curve, value)); value, gimp_curve_map_value (curve, value));
gimp_curve_set_point_type (curve, point, type);
} }
if (channel == config->channel) if (channel == config->channel)
@ -600,10 +622,25 @@ gimp_curves_tool_dialog (GimpFilterTool *filter_tool)
gtk_label_set_mnemonic_widget (GTK_LABEL (label), tool->point_output); 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); hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
gtk_box_pack_start (GTK_BOX (frame_vbox), hbox, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (frame_vbox), hbox, FALSE, FALSE, 0);
gtk_widget_show (hbox); gtk_widget_show (hbox);
gtk_label_set_mnemonic_widget (GTK_LABEL (label), tool->point_type);
label = gtk_label_new_with_mnemonic (_("Curve _type:")); label = gtk_label_new_with_mnemonic (_("Curve _type:"));
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
gtk_widget_show (label); gtk_widget_show (label);
@ -938,6 +975,18 @@ gimp_curves_tool_update_point (GimpCurvesTool *tool)
g_signal_handlers_unblock_by_func (tool->point_output, g_signal_handlers_unblock_by_func (tool->point_output,
curves_point_coords_callback, curves_point_coords_callback,
tool); 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);
} }
} }
@ -1045,6 +1094,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 static void
curves_curve_type_callback (GtkWidget *widget, curves_curve_type_callback (GtkWidget *widget,
GimpCurvesTool *tool) GimpCurvesTool *tool)

View file

@ -46,6 +46,7 @@ struct _GimpCurvesTool
GtkWidget *point_box; GtkWidget *point_box;
GtkWidget *point_input; GtkWidget *point_input;
GtkWidget *point_output; GtkWidget *point_output;
GtkWidget *point_type;
GtkWidget *curve_type; GtkWidget *curve_type;
/* export dialog */ /* export dialog */

View file

@ -440,16 +440,38 @@ gimp_curve_view_draw_point (GimpCurveView *view,
y = 1.0 - y; y = 1.0 - y;
#define RADIUS 3 #define CIRCLE_RADIUS 3
#define DIAMOND_RADIUS (G_SQRT2 * CIRCLE_RADIUS)
cairo_move_to (cr, switch (gimp_curve_get_point_type (view->curve, i))
border + (gdouble) (width - 1) * x + RADIUS, {
border + (gdouble) (height - 1) * y); case GIMP_CURVE_POINT_SMOOTH:
cairo_arc (cr, cairo_move_to (cr,
border + (gdouble) (width - 1) * x, border + (gdouble) (width - 1) * x + CIRCLE_RADIUS,
border + (gdouble) (height - 1) * y, border + (gdouble) (height - 1) * y);
RADIUS, cairo_arc (cr,
0, 2 * G_PI); 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 static void
@ -840,10 +862,17 @@ gimp_curve_view_button_press (GtkWidget *widget,
if (point < 0) if (point < 0)
{ {
GimpCurvePointType type = GIMP_CURVE_POINT_SMOOTH;
if (bevent->state & gimp_get_constrain_behavior_mask ()) if (bevent->state & gimp_get_constrain_behavior_mask ())
y = 1.0 - gimp_curve_map_value (view->orig_curve, x); 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); point = gimp_curve_add_point (curve, x, 1.0 - y);
gimp_curve_set_point_type (curve, point, type);
} }
if (point > 0) if (point > 0)
@ -862,6 +891,8 @@ gimp_curve_view_button_press (GtkWidget *widget,
view->offset_x = point_x - x; view->offset_x = point_x - x;
view->offset_y = (1.0 - point_y) - y; view->offset_y = (1.0 - point_y) - y;
view->point_type = gimp_curve_get_point_type (curve, point);
break; break;
case GIMP_CURVE_FREE: case GIMP_CURVE_FREE:
@ -975,6 +1006,9 @@ gimp_curve_view_motion_notify (GtkWidget *widget,
gimp_curve_view_set_selected ( gimp_curve_view_set_selected (
view, view,
gimp_curve_add_point (curve, x, 1.0 - y)); gimp_curve_add_point (curve, x, 1.0 - y));
gimp_curve_set_point_type (curve,
view->selected, view->point_type);
} }
else else
{ {

View file

@ -50,6 +50,7 @@ struct _GimpCurveView
gint selected; gint selected;
gdouble offset_x; gdouble offset_x;
gdouble offset_y; gdouble offset_y;
GimpCurvePointType point_type;
gdouble last_x; gdouble last_x;
gdouble last_y; gdouble last_y;
gdouble leftmost; gdouble leftmost;

Binary file not shown.

After

Width:  |  Height:  |  Size: 422 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 541 B

View file

@ -110,6 +110,8 @@ scalable_images = \
scalable/gimp-convert-rgb.svg \ scalable/gimp-convert-rgb.svg \
scalable/gimp-cursor.svg \ scalable/gimp-cursor.svg \
scalable/gimp-curve-free.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-curve-smooth.svg \
scalable/gimp-dashboard.svg \ scalable/gimp-dashboard.svg \
scalable/gimp-default-colors.svg \ scalable/gimp-default-colors.svg \
@ -615,6 +617,8 @@ icons16_images = \
16/gimp-convert-rgb.png \ 16/gimp-convert-rgb.png \
16/gimp-cursor.png \ 16/gimp-cursor.png \
16/gimp-curve-free.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-curve-smooth.png \
16/gimp-dashboard.png \ 16/gimp-dashboard.png \
16/gimp-device-status.png \ 16/gimp-device-status.png \

View file

@ -0,0 +1,113 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
width="16"
height="16"
id="svg2"
viewBox="0 0 16 16"
inkscape:version="0.91 r13725"
sodipodi:docname="gimp-shape-diamond.svg">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="640"
inkscape:window-height="480"
id="namedview1695"
showgrid="false"
inkscape:zoom="14.75"
inkscape:cx="-277.86868"
inkscape:cy="16.407786"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="0"
inkscape:current-layer="svg2" />
<metadata
id="metadata90">
<rdf:RDF>
<cc:Work>
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>Gimp Color Icon Theme</dc:title>
<dc:contributor>
<cc:Agent>
<dc:title>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</dc:title>
</cc:Agent>
</dc:contributor>
<dc:description>Enhanced, extended tango-art-libre for GIMP</dc:description>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs7386">
<linearGradient
gradientTransform="matrix(0,-735328.32,170712.69,0,2464326300,577972450)"
osb:paint="solid"
id="linearGradient19282">
<stop
stop-color="#b4b4b4"
id="stop19284" />
</linearGradient>
<linearGradient
osb:paint="gradient"
x1="231.55"
x2="320.70001"
gradientUnits="userSpaceOnUse"
id="linearGradient6057"
gradientTransform="matrix(0.01502614,0,0,0.01468232,2.9686133,1037.3257)">
<stop
stop-color="#a11f7c"
id="stop6053" />
<stop
stop-opacity="0.984"
stop-color="#541f31"
offset="1"
id="stop6055" />
</linearGradient>
<linearGradient
osb:paint="solid"
id="linearGradient5487">
<stop
id="stop5485"
offset="0"
style="stop-color:#888a85;stop-opacity:1;" />
</linearGradient>
</defs>
<g
style="display:inline"
transform="translate(-49.844428,63.91196)"
id="stock">
<g
id="gimp-shape-diamond"
style="display:inline"
transform="translate(-91.15577,-422.91196)">
<rect
y="359"
x="141.0002"
height="16"
width="16"
id="rect16020"
style="fill:none;stroke:none" />
<path
style="fill:#000000;fill-opacity:1;stroke:#ffffff;stroke-width:0.2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m -99,150 7,-7 7,7 -7,7 z"
id="path16026-7"
transform="translate(241.0002,217)"
inkscape:connector-curvature="0" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

View file

@ -0,0 +1,115 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
width="16"
height="16"
id="svg2"
viewBox="0 0 16 16"
inkscape:version="0.91 r13725"
sodipodi:docname="gimp-shape-circle.svg">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="640"
inkscape:window-height="480"
id="namedview1695"
showgrid="false"
inkscape:zoom="14.75"
inkscape:cx="-278.99683"
inkscape:cy="16.506886"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="0"
inkscape:current-layer="svg2" />
<metadata
id="metadata90">
<rdf:RDF>
<cc:Work>
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>Gimp Color Icon Theme</dc:title>
<dc:contributor>
<cc:Agent>
<dc:title>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</dc:title>
</cc:Agent>
</dc:contributor>
<dc:description>Enhanced, extended tango-art-libre for GIMP</dc:description>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs7386">
<linearGradient
gradientTransform="matrix(0,-735328.32,170712.69,0,2464326300,577972450)"
osb:paint="solid"
id="linearGradient19282">
<stop
stop-color="#b4b4b4"
id="stop19284" />
</linearGradient>
<linearGradient
osb:paint="gradient"
x1="231.55"
x2="320.70001"
gradientUnits="userSpaceOnUse"
id="linearGradient6057"
gradientTransform="matrix(0.01502614,0,0,0.01468232,2.9686133,1037.3257)">
<stop
stop-color="#a11f7c"
id="stop6053" />
<stop
stop-opacity="0.984"
stop-color="#541f31"
offset="1"
id="stop6055" />
</linearGradient>
<linearGradient
osb:paint="solid"
id="linearGradient5487">
<stop
id="stop5485"
offset="0"
style="stop-color:#888a85;stop-opacity:1;" />
</linearGradient>
</defs>
<g
style="display:inline"
transform="translate(-30.972582,63.81286)"
id="stock">
<g
id="gimp-shape-circle"
style="display:inline"
transform="translate(-90.027618,-422.81286)">
<rect
style="fill:none;stroke:none"
id="rect15985"
width="16"
height="16"
x="-120"
y="142"
transform="translate(241.0002,217)" />
<circle
r="4.5"
cy="150.5"
cx="-111.5"
style="fill:#000000;fill-opacity:1;stroke:#ffffff;stroke-width:0.15000007;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path16012-9"
transform="matrix(1.3333329,0,0,1.3333327,277.66682,166.33343)" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 306 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 387 B

View file

@ -0,0 +1,94 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
viewBox="0 0 15.999999 16"
id="svg7384"
height="16"
width="16"
version="1.1"
inkscape:version="0.91+devel r"
sodipodi:docname="gimp-shape-diamond.svg">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1051"
inkscape:window-height="432"
id="namedview1507"
showgrid="false"
inkscape:zoom="14.75"
inkscape:cx="-313.94434"
inkscape:cy="116.92552"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="0"
inkscape:current-layer="svg7384" />
<metadata
id="metadata90">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
<dc:contributor>
<cc:Agent>
<dc:title>Barbara Muraus, Jakub Steiner, Klaus Staedtler</dc:title>
</cc:Agent>
</dc:contributor>
<dc:description>Images originally created as the &quot;Art Libre&quot; icon set. Extended and adopted for GIMP</dc:description>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs7386">
<linearGradient
gradientTransform="matrix(0.34682586,0,0,0.30620888,-13.351872,402.03851)"
osb:paint="solid"
id="linearGradient19282-4">
<stop
id="stop19284-0"
offset="0"
style="stop-color:#bebebe;stop-opacity:1;" />
</linearGradient>
<linearGradient
gradientTransform="translate(442.70725,172.83693)"
gradientUnits="userSpaceOnUse"
y2="150"
x2="-85"
y1="150"
x1="-99"
id="linearGradient6866"
xlink:href="#linearGradient19282-4" />
</defs>
<g
transform="translate(15.103901,-5.80569)"
style="display:inline"
id="stock">
<g
id="gimp-shape-diamond"
style="display:inline"
transform="translate(-156.1041,-353.19431)">
<path
style="fill:url(#linearGradient6866);fill-opacity:1;stroke:none"
d="m -99,150 7,-7 7,7 -7,7 z"
id="path16026"
transform="translate(241.0002,217)"
inkscape:connector-curvature="0" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

View file

@ -0,0 +1,95 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
viewBox="0 0 15.999999 16"
id="svg7384"
height="16"
width="16"
version="1.1"
inkscape:version="0.91+devel r"
sodipodi:docname="gimp-shape-circle.svg">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1051"
inkscape:window-height="480"
id="namedview1507"
showgrid="false"
inkscape:zoom="14.75"
inkscape:cx="-313.13695"
inkscape:cy="115.75708"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="0"
inkscape:current-layer="svg7384" />
<metadata
id="metadata90">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
<dc:contributor>
<cc:Agent>
<dc:title>Barbara Muraus, Jakub Steiner, Klaus Staedtler</dc:title>
</cc:Agent>
</dc:contributor>
<dc:description>Images originally created as the &quot;Art Libre&quot; icon set. Extended and adopted for GIMP</dc:description>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs7386">
<linearGradient
gradientTransform="matrix(0.34682586,0,0,0.30620888,-33.35187,402.03851)"
osb:paint="solid"
id="linearGradient19282-4">
<stop
id="stop19284-0"
offset="0"
style="stop-color:#bebebe;stop-opacity:1;" />
</linearGradient>
<linearGradient
gradientTransform="translate(316.425,128.75143)"
gradientUnits="userSpaceOnUse"
y2="150.5"
x2="-107"
y1="150.5"
x1="-116"
id="linearGradient6860"
xlink:href="#linearGradient19282-4" />
</defs>
<g
transform="translate(35.91129,-4.63725)"
style="display:inline"
id="stock">
<g
id="gimp-shape-circle"
style="display:inline"
transform="translate(-156.91149,-354.36275)">
<circle
r="4.5"
cy="150.5"
cx="-111.5"
style="fill:url(#linearGradient6860);fill-opacity:1;stroke:none"
id="path16012"
transform="matrix(1.3333329,0,0,1.3333327,277.66682,166.33343)" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB