app: streamline GimpCurve
In GimpCurve, replace the use of a fixed-length control-point array with a dynamically-sized array. Adapt GimpCurve's interface, and the rest of the code. In addition to simplifying the code, this fixes a bug where the curve object could be broken by moving the mouse too fast (yep...), and allows more accurate point placement, both in the GUI editor, and through canvas interaction in the Curves tool (see issue #814).
This commit is contained in:
@ -37,6 +37,9 @@
|
|||||||
#include "gimp-intl.h"
|
#include "gimp-intl.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define EPSILON 1e-6
|
||||||
|
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
PROP_0,
|
PROP_0,
|
||||||
@ -155,7 +158,9 @@ gimp_curve_class_init (GimpCurveClass *klass)
|
|||||||
"n-points",
|
"n-points",
|
||||||
"Number of Points",
|
"Number of Points",
|
||||||
"The number of points",
|
"The number of points",
|
||||||
17, 17, 17, 0);
|
0, G_MAXINT, 0,
|
||||||
|
/* for backward compatibility */
|
||||||
|
GIMP_CONFIG_PARAM_IGNORE);
|
||||||
|
|
||||||
array_spec = g_param_spec_double ("point", NULL, NULL,
|
array_spec = g_param_spec_double ("point", NULL, NULL,
|
||||||
-1.0, 1.0, 0.0, GIMP_PARAM_READWRITE);
|
-1.0, 1.0, 0.0, GIMP_PARAM_READWRITE);
|
||||||
@ -237,7 +242,7 @@ gimp_curve_set_property (GObject *object,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case PROP_N_POINTS:
|
case PROP_N_POINTS:
|
||||||
gimp_curve_set_n_points (curve, g_value_get_int (value));
|
/* ignored */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PROP_POINTS:
|
case PROP_POINTS:
|
||||||
@ -246,19 +251,41 @@ gimp_curve_set_property (GObject *object,
|
|||||||
gint length;
|
gint length;
|
||||||
gint i;
|
gint i;
|
||||||
|
|
||||||
|
curve->n_points = 0;
|
||||||
|
g_clear_pointer (&curve->points, g_free);
|
||||||
|
|
||||||
if (! array)
|
if (! array)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
length = gimp_value_array_length (array);
|
length = gimp_value_array_length (array) / 2;
|
||||||
|
|
||||||
for (i = 0; i < curve->n_points && i * 2 < length; i++)
|
curve->points = g_new (GimpVector2, length);
|
||||||
|
|
||||||
|
for (i = 0; i < length; i++)
|
||||||
{
|
{
|
||||||
GValue *x = gimp_value_array_index (array, i * 2);
|
GValue *x = gimp_value_array_index (array, i * 2);
|
||||||
GValue *y = gimp_value_array_index (array, i * 2 + 1);
|
GValue *y = gimp_value_array_index (array, i * 2 + 1);
|
||||||
|
|
||||||
curve->points[i].x = g_value_get_double (x);
|
/* for backward compatibility */
|
||||||
curve->points[i].y = g_value_get_double (y);
|
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);
|
||||||
|
|
||||||
|
if (curve->n_points > 0)
|
||||||
|
{
|
||||||
|
curve->points[curve->n_points].x = MAX (
|
||||||
|
curve->points[curve->n_points].x,
|
||||||
|
curve->points[curve->n_points - 1].x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
curve->n_points++;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_notify (object, "n-points");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -281,7 +308,7 @@ gimp_curve_set_property (GObject *object,
|
|||||||
{
|
{
|
||||||
GValue *v = gimp_value_array_index (array, i);
|
GValue *v = gimp_value_array_index (array, i);
|
||||||
|
|
||||||
curve->samples[i] = g_value_get_double (v);
|
curve->samples[i] = CLAMP (g_value_get_double (v), 0.0, 1.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -484,11 +511,19 @@ gimp_curve_equal (GimpConfig *a,
|
|||||||
if (a_curve->curve_type != b_curve->curve_type)
|
if (a_curve->curve_type != b_curve->curve_type)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (memcmp (a_curve->points, b_curve->points,
|
if (a_curve->n_points != b_curve->n_points ||
|
||||||
sizeof (GimpVector2) * b_curve->n_points) ||
|
memcmp (a_curve->points, b_curve->points,
|
||||||
memcmp (a_curve->samples, b_curve->samples,
|
sizeof (GimpVector2) * a_curve->n_points))
|
||||||
sizeof (gdouble) * b_curve->n_samples))
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a_curve->n_samples != b_curve->n_samples ||
|
||||||
|
memcmp (a_curve->samples, b_curve->samples,
|
||||||
|
sizeof (gdouble) * a_curve->n_samples))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -564,18 +599,18 @@ gimp_curve_reset (GimpCurve *curve,
|
|||||||
|
|
||||||
g_object_notify (G_OBJECT (curve), "samples");
|
g_object_notify (G_OBJECT (curve), "samples");
|
||||||
|
|
||||||
|
g_free (curve->points);
|
||||||
|
|
||||||
|
curve->n_points = 2;
|
||||||
|
curve->points = g_new (GimpVector2, 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;
|
||||||
|
|
||||||
for (i = 1; i < curve->n_points - 1; i++)
|
curve->points[1].x = 1.0;
|
||||||
{
|
curve->points[1].y = 1.0;
|
||||||
curve->points[i].x = -1.0;
|
|
||||||
curve->points[i].y = -1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
curve->points[curve->n_points - 1].x = 1.0;
|
|
||||||
curve->points[curve->n_points - 1].y = 1.0;
|
|
||||||
|
|
||||||
|
g_object_notify (G_OBJECT (curve), "n-points");
|
||||||
g_object_notify (G_OBJECT (curve), "points");
|
g_object_notify (G_OBJECT (curve), "points");
|
||||||
|
|
||||||
if (reset_type)
|
if (reset_type)
|
||||||
@ -599,44 +634,46 @@ gimp_curve_set_curve_type (GimpCurve *curve,
|
|||||||
|
|
||||||
if (curve->curve_type != curve_type)
|
if (curve->curve_type != curve_type)
|
||||||
{
|
{
|
||||||
|
gimp_data_freeze (GIMP_DATA (curve));
|
||||||
|
|
||||||
g_object_freeze_notify (G_OBJECT (curve));
|
g_object_freeze_notify (G_OBJECT (curve));
|
||||||
|
|
||||||
curve->curve_type = curve_type;
|
curve->curve_type = curve_type;
|
||||||
|
|
||||||
if (curve_type == GIMP_CURVE_SMOOTH)
|
if (curve_type == GIMP_CURVE_SMOOTH)
|
||||||
{
|
{
|
||||||
gint n_points;
|
|
||||||
gint i;
|
gint i;
|
||||||
|
|
||||||
for (i = 0; i < curve->n_points; i++)
|
g_free (curve->points);
|
||||||
{
|
|
||||||
curve->points[i].x = -1;
|
|
||||||
curve->points[i].y = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* pick some points from the curve and make them control
|
/* pick some points from the curve and make them control
|
||||||
* points
|
* points
|
||||||
*/
|
*/
|
||||||
n_points = CLAMP (9, curve->n_points / 2, curve->n_points);
|
curve->n_points = 9;
|
||||||
|
curve->points = g_new (GimpVector2, 9);
|
||||||
|
|
||||||
for (i = 0; i < n_points; i++)
|
for (i = 0; i < curve->n_points; i++)
|
||||||
{
|
{
|
||||||
gint sample = i * (curve->n_samples - 1) / (n_points - 1);
|
gint sample = i * (curve->n_samples - 1) / (curve->n_points - 1);
|
||||||
gint point = i * (curve->n_points - 1) / (n_points - 1);
|
|
||||||
|
|
||||||
curve->points[point].x = ((gdouble) sample /
|
curve->points[i].x = (gdouble) sample /
|
||||||
(gdouble) (curve->n_samples - 1));
|
(gdouble) (curve->n_samples - 1);
|
||||||
curve->points[point].y = curve->samples[sample];
|
curve->points[i].y = curve->samples[sample];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_object_notify (G_OBJECT (curve), "n-points");
|
||||||
g_object_notify (G_OBJECT (curve), "points");
|
g_object_notify (G_OBJECT (curve), "points");
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gimp_curve_clear_points (curve);
|
||||||
|
}
|
||||||
|
|
||||||
g_object_notify (G_OBJECT (curve), "curve-type");
|
g_object_notify (G_OBJECT (curve), "curve-type");
|
||||||
|
|
||||||
g_object_thaw_notify (G_OBJECT (curve));
|
g_object_thaw_notify (G_OBJECT (curve));
|
||||||
|
|
||||||
gimp_data_dirty (GIMP_DATA (curve));
|
gimp_data_thaw (GIMP_DATA (curve));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -648,46 +685,6 @@ gimp_curve_get_curve_type (GimpCurve *curve)
|
|||||||
return curve->curve_type;
|
return curve->curve_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
gimp_curve_set_n_points (GimpCurve *curve,
|
|
||||||
gint n_points)
|
|
||||||
{
|
|
||||||
g_return_if_fail (GIMP_IS_CURVE (curve));
|
|
||||||
g_return_if_fail (n_points >= 2);
|
|
||||||
g_return_if_fail (n_points <= 1024);
|
|
||||||
|
|
||||||
if (n_points != curve->n_points)
|
|
||||||
{
|
|
||||||
gint i;
|
|
||||||
|
|
||||||
g_object_freeze_notify (G_OBJECT (curve));
|
|
||||||
|
|
||||||
curve->n_points = n_points;
|
|
||||||
g_object_notify (G_OBJECT (curve), "n-points");
|
|
||||||
|
|
||||||
curve->points = g_renew (GimpVector2, curve->points, curve->n_points);
|
|
||||||
|
|
||||||
curve->points[0].x = 0.0;
|
|
||||||
curve->points[0].y = 0.0;
|
|
||||||
|
|
||||||
for (i = 1; i < curve->n_points - 1; i++)
|
|
||||||
{
|
|
||||||
curve->points[i].x = -1.0;
|
|
||||||
curve->points[i].y = -1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
curve->points[curve->n_points - 1].x = 1.0;
|
|
||||||
curve->points[curve->n_points - 1].y = 1.0;
|
|
||||||
|
|
||||||
g_object_notify (G_OBJECT (curve), "points");
|
|
||||||
|
|
||||||
if (curve->curve_type == GIMP_CURVE_SMOOTH)
|
|
||||||
curve->identity = TRUE;
|
|
||||||
|
|
||||||
g_object_thaw_notify (G_OBJECT (curve));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gint
|
gint
|
||||||
gimp_curve_get_n_points (GimpCurve *curve)
|
gimp_curve_get_n_points (GimpCurve *curve)
|
||||||
{
|
{
|
||||||
@ -736,31 +733,135 @@ gimp_curve_get_n_samples (GimpCurve *curve)
|
|||||||
}
|
}
|
||||||
|
|
||||||
gint
|
gint
|
||||||
gimp_curve_get_closest_point (GimpCurve *curve,
|
gimp_curve_get_point_at (GimpCurve *curve,
|
||||||
gdouble x)
|
gdouble x)
|
||||||
{
|
{
|
||||||
gint closest_point = 0;
|
gint closest_point = -1;
|
||||||
gdouble distance = G_MAXDOUBLE;
|
gdouble distance = EPSILON;
|
||||||
gint i;
|
gint i;
|
||||||
|
|
||||||
g_return_val_if_fail (GIMP_IS_CURVE (curve), 0);
|
g_return_val_if_fail (GIMP_IS_CURVE (curve), -1);
|
||||||
|
|
||||||
for (i = 0; i < curve->n_points; i++)
|
for (i = 0; i < curve->n_points; i++)
|
||||||
{
|
{
|
||||||
if (curve->points[i].x >= 0.0 &&
|
gdouble point_distance;
|
||||||
fabs (x - curve->points[i].x) < distance)
|
|
||||||
{
|
|
||||||
distance = fabs (x - curve->points[i].x);
|
|
||||||
closest_point = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (distance > (1.0 / (curve->n_points * 2.0)))
|
point_distance = fabs (x - curve->points[i].x);
|
||||||
closest_point = ROUND (x * (gdouble) (curve->n_points - 1));
|
|
||||||
|
if (point_distance <= distance)
|
||||||
|
{
|
||||||
|
closest_point = i;
|
||||||
|
distance = point_distance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return closest_point;
|
return closest_point;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gint
|
||||||
|
gimp_curve_get_closest_point (GimpCurve *curve,
|
||||||
|
gdouble x,
|
||||||
|
gdouble y,
|
||||||
|
gdouble max_distance)
|
||||||
|
{
|
||||||
|
gint closest_point = -1;
|
||||||
|
gdouble distance2 = G_MAXDOUBLE;
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GIMP_IS_CURVE (curve), -1);
|
||||||
|
|
||||||
|
if (max_distance >= 0.0)
|
||||||
|
distance2 = SQR (max_distance);
|
||||||
|
|
||||||
|
for (i = curve->n_points - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
gdouble point_distance2;
|
||||||
|
|
||||||
|
point_distance2 = SQR (x - curve->points[i].x) +
|
||||||
|
SQR (y - curve->points[i].y);
|
||||||
|
|
||||||
|
if (point_distance2 <= distance2)
|
||||||
|
{
|
||||||
|
closest_point = i;
|
||||||
|
distance2 = point_distance2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return closest_point;
|
||||||
|
}
|
||||||
|
|
||||||
|
gint
|
||||||
|
gimp_curve_add_point (GimpCurve *curve,
|
||||||
|
gdouble x,
|
||||||
|
gdouble y)
|
||||||
|
{
|
||||||
|
GimpVector2 *points;
|
||||||
|
gint point;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GIMP_IS_CURVE (curve), -1);
|
||||||
|
|
||||||
|
if (curve->curve_type == GIMP_CURVE_FREE)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
x = CLAMP (x, 0.0, 1.0);
|
||||||
|
y = CLAMP (y, 0.0, 1.0);
|
||||||
|
|
||||||
|
for (point = 0; point < curve->n_points; point++)
|
||||||
|
{
|
||||||
|
if (curve->points[point].x > x)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
points = g_new (GimpVector2, curve->n_points + 1);
|
||||||
|
|
||||||
|
memcpy (points, curve->points,
|
||||||
|
point * sizeof (GimpVector2));
|
||||||
|
memcpy (points + point + 1, curve->points + point,
|
||||||
|
(curve->n_points - point) * sizeof (GimpVector2));
|
||||||
|
|
||||||
|
points[point].x = x;
|
||||||
|
points[point].y = y;
|
||||||
|
|
||||||
|
g_free (curve->points);
|
||||||
|
|
||||||
|
curve->n_points++;
|
||||||
|
curve->points = points;
|
||||||
|
|
||||||
|
g_object_notify (G_OBJECT (curve), "n-points");
|
||||||
|
g_object_notify (G_OBJECT (curve), "points");
|
||||||
|
|
||||||
|
gimp_data_dirty (GIMP_DATA (curve));
|
||||||
|
|
||||||
|
return point;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gimp_curve_delete_point (GimpCurve *curve,
|
||||||
|
gint point)
|
||||||
|
{
|
||||||
|
GimpVector2 *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);
|
||||||
|
|
||||||
|
memcpy (points, curve->points,
|
||||||
|
point * sizeof (GimpVector2));
|
||||||
|
memcpy (points + point, curve->points + point + 1,
|
||||||
|
(curve->n_points - point - 1) * sizeof (GimpVector2));
|
||||||
|
|
||||||
|
g_free (curve->points);
|
||||||
|
|
||||||
|
curve->n_points--;
|
||||||
|
curve->points = points;
|
||||||
|
|
||||||
|
g_object_notify (G_OBJECT (curve), "n-points");
|
||||||
|
g_object_notify (G_OBJECT (curve), "points");
|
||||||
|
|
||||||
|
gimp_data_dirty (GIMP_DATA (curve));
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
gimp_curve_set_point (GimpCurve *curve,
|
gimp_curve_set_point (GimpCurve *curve,
|
||||||
gint point,
|
gint point,
|
||||||
@ -769,14 +870,15 @@ gimp_curve_set_point (GimpCurve *curve,
|
|||||||
{
|
{
|
||||||
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);
|
||||||
g_return_if_fail (x == -1.0 || (x >= 0 && x <= 1.0));
|
|
||||||
g_return_if_fail (y == -1.0 || (y >= 0 && y <= 1.0));
|
|
||||||
|
|
||||||
if (curve->curve_type == GIMP_CURVE_FREE)
|
curve->points[point].x = CLAMP (x, 0.0, 1.0);
|
||||||
return;
|
curve->points[point].y = CLAMP (y, 0.0, 1.0);
|
||||||
|
|
||||||
curve->points[point].x = x;
|
if (point > 0)
|
||||||
curve->points[point].y = y;
|
curve->points[point].x = MAX (x, curve->points[point - 1].x);
|
||||||
|
|
||||||
|
if (point < curve->n_points - 1)
|
||||||
|
curve->points[point].x = MIN (x, curve->points[point + 1].x);
|
||||||
|
|
||||||
g_object_notify (G_OBJECT (curve), "points");
|
g_object_notify (G_OBJECT (curve), "points");
|
||||||
|
|
||||||
@ -790,40 +892,8 @@ gimp_curve_move_point (GimpCurve *curve,
|
|||||||
{
|
{
|
||||||
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);
|
||||||
g_return_if_fail (y >= 0 && y <= 1.0);
|
|
||||||
|
|
||||||
if (curve->curve_type == GIMP_CURVE_FREE)
|
curve->points[point].y = CLAMP (y, 0.0, 1.0);
|
||||||
return;
|
|
||||||
|
|
||||||
curve->points[point].y = y;
|
|
||||||
|
|
||||||
g_object_notify (G_OBJECT (curve), "points");
|
|
||||||
|
|
||||||
gimp_data_dirty (GIMP_DATA (curve));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
gimp_curve_delete_point (GimpCurve *curve,
|
|
||||||
gint point)
|
|
||||||
{
|
|
||||||
g_return_if_fail (GIMP_IS_CURVE (curve));
|
|
||||||
g_return_if_fail (point >= 0 && point < curve->n_points);
|
|
||||||
|
|
||||||
if (point == 0)
|
|
||||||
{
|
|
||||||
curve->points[0].x = 0.0;
|
|
||||||
curve->points[0].y = 0.0;
|
|
||||||
}
|
|
||||||
else if (point == curve->n_points - 1)
|
|
||||||
{
|
|
||||||
curve->points[curve->n_points - 1].x = 1.0;
|
|
||||||
curve->points[curve->n_points - 1].y = 1.0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
curve->points[point].x = -1.0;
|
|
||||||
curve->points[point].y = -1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_object_notify (G_OBJECT (curve), "points");
|
g_object_notify (G_OBJECT (curve), "points");
|
||||||
|
|
||||||
@ -839,18 +909,27 @@ gimp_curve_get_point (GimpCurve *curve,
|
|||||||
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);
|
||||||
|
|
||||||
if (curve->curve_type == GIMP_CURVE_FREE)
|
|
||||||
{
|
|
||||||
if (x) *x = -1.0;
|
|
||||||
if (y) *y = -1.0;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (x) *x = curve->points[point].x;
|
if (x) *x = curve->points[point].x;
|
||||||
if (y) *y = curve->points[point].y;
|
if (y) *y = curve->points[point].y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gimp_curve_clear_points (GimpCurve *curve)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GIMP_IS_CURVE (curve));
|
||||||
|
|
||||||
|
if (curve->points)
|
||||||
|
{
|
||||||
|
curve->n_points = 0;
|
||||||
|
g_clear_pointer (&curve->points, g_free);
|
||||||
|
|
||||||
|
g_object_notify (G_OBJECT (curve), "n-points");
|
||||||
|
g_object_notify (G_OBJECT (curve), "points");
|
||||||
|
|
||||||
|
gimp_data_dirty (GIMP_DATA (curve));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
gimp_curve_set_curve (GimpCurve *curve,
|
gimp_curve_set_curve (GimpCurve *curve,
|
||||||
gdouble x,
|
gdouble x,
|
||||||
@ -909,59 +988,49 @@ gimp_curve_get_uchar (GimpCurve *curve,
|
|||||||
static void
|
static void
|
||||||
gimp_curve_calculate (GimpCurve *curve)
|
gimp_curve_calculate (GimpCurve *curve)
|
||||||
{
|
{
|
||||||
gint *points;
|
|
||||||
gint i;
|
gint i;
|
||||||
gint num_pts;
|
|
||||||
gint p1, p2, p3, p4;
|
gint p1, p2, p3, p4;
|
||||||
|
|
||||||
if (gimp_data_is_frozen (GIMP_DATA (curve)))
|
if (gimp_data_is_frozen (GIMP_DATA (curve)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
points = g_newa (gint, curve->n_points);
|
|
||||||
|
|
||||||
switch (curve->curve_type)
|
switch (curve->curve_type)
|
||||||
{
|
{
|
||||||
case GIMP_CURVE_SMOOTH:
|
case GIMP_CURVE_SMOOTH:
|
||||||
/* cycle through the curves */
|
|
||||||
num_pts = 0;
|
|
||||||
for (i = 0; i < curve->n_points; i++)
|
|
||||||
if (curve->points[i].x >= 0.0)
|
|
||||||
points[num_pts++] = i;
|
|
||||||
|
|
||||||
/* Initialize boundary curve points */
|
/* Initialize boundary curve points */
|
||||||
if (num_pts != 0)
|
if (curve->n_points > 0)
|
||||||
{
|
{
|
||||||
GimpVector2 point;
|
GimpVector2 point;
|
||||||
gint boundary;
|
gint boundary;
|
||||||
|
|
||||||
point = curve->points[points[0]];
|
point = curve->points[0];
|
||||||
boundary = ROUND (point.x * (gdouble) (curve->n_samples - 1));
|
boundary = ROUND (point.x * (gdouble) (curve->n_samples - 1));
|
||||||
|
|
||||||
for (i = 0; i < boundary; i++)
|
for (i = 0; i < boundary; i++)
|
||||||
curve->samples[i] = point.y;
|
curve->samples[i] = point.y;
|
||||||
|
|
||||||
point = curve->points[points[num_pts - 1]];
|
point = curve->points[curve->n_points - 1];
|
||||||
boundary = ROUND (point.x * (gdouble) (curve->n_samples - 1));
|
boundary = ROUND (point.x * (gdouble) (curve->n_samples - 1));
|
||||||
|
|
||||||
for (i = boundary; i < curve->n_samples; i++)
|
for (i = boundary; i < curve->n_samples; i++)
|
||||||
curve->samples[i] = point.y;
|
curve->samples[i] = point.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < num_pts - 1; i++)
|
for (i = 0; i < curve->n_points - 1; i++)
|
||||||
{
|
{
|
||||||
p1 = points[MAX (i - 1, 0)];
|
p1 = MAX (i - 1, 0);
|
||||||
p2 = points[i];
|
p2 = i;
|
||||||
p3 = points[i + 1];
|
p3 = i + 1;
|
||||||
p4 = points[MIN (i + 2, num_pts - 1)];
|
p4 = MIN (i + 2, curve->n_points - 1);
|
||||||
|
|
||||||
gimp_curve_plot (curve, p1, p2, p3, p4);
|
gimp_curve_plot (curve, p1, p2, p3, p4);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ensure that the control points are used exactly */
|
/* ensure that the control points are used exactly */
|
||||||
for (i = 0; i < num_pts; i++)
|
for (i = 0; i < curve->n_points; i++)
|
||||||
{
|
{
|
||||||
gdouble x = curve->points[points[i]].x;
|
gdouble x = curve->points[i].x;
|
||||||
gdouble y = curve->points[points[i]].y;
|
gdouble y = curve->points[i].y;
|
||||||
|
|
||||||
curve->samples[ROUND (x * (gdouble) (curve->n_samples - 1))] = y;
|
curve->samples[ROUND (x * (gdouble) (curve->n_samples - 1))] = y;
|
||||||
}
|
}
|
||||||
@ -1013,7 +1082,16 @@ gimp_curve_plot (GimpCurve *curve,
|
|||||||
dx = x3 - x0;
|
dx = x3 - x0;
|
||||||
dy = y3 - y0;
|
dy = y3 - y0;
|
||||||
|
|
||||||
g_return_if_fail (dx > 0);
|
if (dx <= EPSILON)
|
||||||
|
{
|
||||||
|
gint index;
|
||||||
|
|
||||||
|
index = ROUND (x0 * (gdouble) (curve->n_samples - 1));
|
||||||
|
|
||||||
|
curve->samples[index] = y3;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (p1 == p2 && p3 == p4)
|
if (p1 == p2 && p3 == p4)
|
||||||
{
|
{
|
||||||
|
@ -65,17 +65,24 @@ 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);
|
||||||
|
|
||||||
void gimp_curve_set_n_points (GimpCurve *curve,
|
|
||||||
gint n_points);
|
|
||||||
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_closest_point (GimpCurve *curve,
|
gint gimp_curve_get_point_at (GimpCurve *curve,
|
||||||
gdouble x);
|
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,
|
void gimp_curve_set_point (GimpCurve *curve,
|
||||||
gint point,
|
gint point,
|
||||||
gdouble x,
|
gdouble x,
|
||||||
@ -83,12 +90,11 @@ void gimp_curve_set_point (GimpCurve *curve,
|
|||||||
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_delete_point (GimpCurve *curve,
|
|
||||||
gint point);
|
|
||||||
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_curve (GimpCurve *curve,
|
void gimp_curve_set_curve (GimpCurve *curve,
|
||||||
gdouble x,
|
gdouble x,
|
||||||
|
@ -421,13 +421,10 @@ gimp_curves_config_new_spline (gint32 channel,
|
|||||||
gimp_data_freeze (GIMP_DATA (curve));
|
gimp_data_freeze (GIMP_DATA (curve));
|
||||||
|
|
||||||
gimp_curve_set_curve_type (curve, GIMP_CURVE_SMOOTH);
|
gimp_curve_set_curve_type (curve, GIMP_CURVE_SMOOTH);
|
||||||
gimp_curve_set_n_points (curve, n_points);
|
gimp_curve_clear_points (curve);
|
||||||
|
|
||||||
/* unset the last point */
|
|
||||||
gimp_curve_set_point (curve, curve->n_points - 1, -1.0, -1.0);
|
|
||||||
|
|
||||||
for (i = 0; i < n_points; i++)
|
for (i = 0; i < n_points; i++)
|
||||||
gimp_curve_set_point (curve, i,
|
gimp_curve_add_point (curve,
|
||||||
(gdouble) points[i * 2],
|
(gdouble) points[i * 2],
|
||||||
(gdouble) points[i * 2 + 1]);
|
(gdouble) points[i * 2 + 1]);
|
||||||
|
|
||||||
@ -617,18 +614,18 @@ gimp_curves_config_load_cruft (GimpCurvesConfig *config,
|
|||||||
gimp_data_freeze (GIMP_DATA (curve));
|
gimp_data_freeze (GIMP_DATA (curve));
|
||||||
|
|
||||||
gimp_curve_set_curve_type (curve, GIMP_CURVE_SMOOTH);
|
gimp_curve_set_curve_type (curve, GIMP_CURVE_SMOOTH);
|
||||||
gimp_curve_set_n_points (curve, GIMP_CURVE_N_CRUFT_POINTS);
|
gimp_curve_clear_points (curve);
|
||||||
|
|
||||||
gimp_curve_reset (curve, FALSE);
|
|
||||||
|
|
||||||
for (j = 0; j < GIMP_CURVE_N_CRUFT_POINTS; j++)
|
for (j = 0; j < GIMP_CURVE_N_CRUFT_POINTS; j++)
|
||||||
{
|
{
|
||||||
if (index[i][j] < 0 || value[i][j] < 0)
|
gdouble x;
|
||||||
gimp_curve_set_point (curve, j, -1.0, -1.0);
|
gdouble y;
|
||||||
else
|
|
||||||
gimp_curve_set_point (curve, j,
|
x = (gdouble) index[i][j] / 255.0;
|
||||||
(gdouble) index[i][j] / 255.0,
|
y = (gdouble) value[i][j] / 255.0;
|
||||||
(gdouble) value[i][j] / 255.0);
|
|
||||||
|
if (x >= 0.0)
|
||||||
|
gimp_curve_add_point (curve, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
gimp_data_thaw (GIMP_DATA (curve));
|
gimp_data_thaw (GIMP_DATA (curve));
|
||||||
@ -662,50 +659,34 @@ gimp_curves_config_save_cruft (GimpCurvesConfig *config,
|
|||||||
GimpCurve *curve = config->curve[i];
|
GimpCurve *curve = config->curve[i];
|
||||||
gint j;
|
gint j;
|
||||||
|
|
||||||
if (curve->curve_type == GIMP_CURVE_FREE)
|
if (curve->curve_type == GIMP_CURVE_SMOOTH)
|
||||||
{
|
{
|
||||||
gint n_points;
|
g_object_ref (curve);
|
||||||
|
|
||||||
for (j = 0; j < curve->n_points; j++)
|
|
||||||
{
|
|
||||||
curve->points[j].x = -1;
|
|
||||||
curve->points[j].y = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* pick some points from the curve and make them control
|
|
||||||
* points
|
|
||||||
*/
|
|
||||||
n_points = CLAMP (9, curve->n_points / 2, curve->n_points);
|
|
||||||
|
|
||||||
for (j = 0; j < n_points; j++)
|
|
||||||
{
|
|
||||||
gint sample = j * (curve->n_samples - 1) / (n_points - 1);
|
|
||||||
gint point = j * (curve->n_points - 1) / (n_points - 1);
|
|
||||||
|
|
||||||
curve->points[point].x = ((gdouble) sample /
|
|
||||||
(gdouble) (curve->n_samples - 1));
|
|
||||||
curve->points[point].y = curve->samples[sample];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (j = 0; j < curve->n_points; j++)
|
|
||||||
{
|
|
||||||
/* don't use gimp_curve_get_point() because that doesn't
|
|
||||||
* work when the curve type is GIMP_CURVE_FREE
|
|
||||||
*/
|
|
||||||
gdouble x = curve->points[j].x;
|
|
||||||
gdouble y = curve->points[j].y;
|
|
||||||
|
|
||||||
if (x < 0.0 || y < 0.0)
|
|
||||||
{
|
|
||||||
g_string_append_printf (string, "%d %d ", -1, -1);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
g_string_append_printf (string, "%d %d ",
|
curve = GIMP_CURVE (gimp_data_duplicate (GIMP_DATA (curve)));
|
||||||
(gint) (x * 255.999),
|
|
||||||
(gint) (y * 255.999));
|
gimp_curve_set_curve_type (curve, GIMP_CURVE_SMOOTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (j = 0; j < GIMP_CURVE_N_CRUFT_POINTS; j++)
|
||||||
|
{
|
||||||
|
gint x = -1;
|
||||||
|
gint y = -1;
|
||||||
|
|
||||||
|
if (j < gimp_curve_get_n_points (curve))
|
||||||
|
{
|
||||||
|
gdouble point_x;
|
||||||
|
gdouble point_y;
|
||||||
|
|
||||||
|
gimp_curve_get_point (curve, j, &point_x, &point_y);
|
||||||
|
|
||||||
|
x = floor (point_x * 255.999);
|
||||||
|
y = floor (point_y * 255.999);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_string_append_printf (string, "%d %d ", x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_string_append_printf (string, "\n");
|
g_string_append_printf (string, "\n");
|
||||||
|
@ -715,17 +715,14 @@ gimp_levels_config_to_curves_config (GimpLevelsConfig *config)
|
|||||||
channel++)
|
channel++)
|
||||||
{
|
{
|
||||||
GimpCurve *curve = curves->curve[channel];
|
GimpCurve *curve = curves->curve[channel];
|
||||||
const gint n_points = gimp_curve_get_n_points (curve);
|
|
||||||
static const gint n = 8;
|
static const gint n = 8;
|
||||||
gint point = -1;
|
|
||||||
gdouble gamma = config->gamma[channel];
|
gdouble gamma = config->gamma[channel];
|
||||||
gdouble delta_in;
|
gdouble delta_in;
|
||||||
gdouble delta_out;
|
gdouble delta_out;
|
||||||
gdouble x, y;
|
gdouble x, y;
|
||||||
|
|
||||||
/* clear the points set by default */
|
/* clear the points set by default */
|
||||||
gimp_curve_set_point (curve, 0, -1, -1);
|
gimp_curve_clear_points (curve);
|
||||||
gimp_curve_set_point (curve, n_points - 1, -1, -1);
|
|
||||||
|
|
||||||
delta_in = config->high_input[channel] - config->low_input[channel];
|
delta_in = config->high_input[channel] - config->low_input[channel];
|
||||||
delta_out = config->high_output[channel] - config->low_output[channel];
|
delta_out = config->high_output[channel] - config->low_output[channel];
|
||||||
@ -733,8 +730,7 @@ gimp_levels_config_to_curves_config (GimpLevelsConfig *config)
|
|||||||
x = config->low_input[channel];
|
x = config->low_input[channel];
|
||||||
y = config->low_output[channel];
|
y = config->low_output[channel];
|
||||||
|
|
||||||
point = CLAMP (n_points * x, point + 1, n_points - 1 - n);
|
gimp_curve_add_point (curve, x, y);
|
||||||
gimp_curve_set_point (curve, point, x, y);
|
|
||||||
|
|
||||||
if (delta_out != 0 && gamma != 1.0)
|
if (delta_out != 0 && gamma != 1.0)
|
||||||
{
|
{
|
||||||
@ -774,8 +770,7 @@ gimp_levels_config_to_curves_config (GimpLevelsConfig *config)
|
|||||||
x = config->low_input[channel] + dx;
|
x = config->low_input[channel] + dx;
|
||||||
y = config->low_output[channel] + delta_out *
|
y = config->low_output[channel] + delta_out *
|
||||||
gimp_operation_levels_map_input (config, channel, x);
|
gimp_operation_levels_map_input (config, channel, x);
|
||||||
point = CLAMP (n_points * x, point + 1, n_points - 1 - n + i);
|
gimp_curve_add_point (curve, x, y);
|
||||||
gimp_curve_set_point (curve, point, x, y);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -811,8 +806,7 @@ gimp_levels_config_to_curves_config (GimpLevelsConfig *config)
|
|||||||
y = config->low_output[channel] + dy;
|
y = config->low_output[channel] + dy;
|
||||||
x = config->low_input[channel] + delta_in *
|
x = config->low_input[channel] + delta_in *
|
||||||
gimp_operation_levels_map_input (config_inv, channel, y);
|
gimp_operation_levels_map_input (config_inv, channel, y);
|
||||||
point = CLAMP (n_points * x, point + 1, n_points - 1 - n + i);
|
gimp_curve_add_point (curve, x, y);
|
||||||
gimp_curve_set_point (curve, point, x, y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
g_object_unref (config_inv);
|
g_object_unref (config_inv);
|
||||||
@ -822,8 +816,7 @@ gimp_levels_config_to_curves_config (GimpLevelsConfig *config)
|
|||||||
x = config->high_input[channel];
|
x = config->high_input[channel];
|
||||||
y = config->high_output[channel];
|
y = config->high_output[channel];
|
||||||
|
|
||||||
point = CLAMP (n_points * x, point + 1, n_points - 1);
|
gimp_curve_add_point (curve, x, y);
|
||||||
gimp_curve_set_point (curve, point, x, y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return curves;
|
return curves;
|
||||||
|
@ -242,16 +242,19 @@ gimp_curves_tool_button_release (GimpTool *tool,
|
|||||||
{
|
{
|
||||||
GimpCurve *curve = config->curve[config->channel];
|
GimpCurve *curve = config->curve[config->channel];
|
||||||
gdouble value = c_tool->picked_color[config->channel];
|
gdouble value = c_tool->picked_color[config->channel];
|
||||||
gint closest;
|
gint point;
|
||||||
|
|
||||||
closest = gimp_curve_get_closest_point (curve, value);
|
point = gimp_curve_get_point_at (curve, value);
|
||||||
|
|
||||||
gimp_curve_view_set_selected (GIMP_CURVE_VIEW (c_tool->graph),
|
if (point < 0)
|
||||||
closest);
|
{
|
||||||
|
point = gimp_curve_add_point (
|
||||||
gimp_curve_set_point (curve, closest,
|
curve,
|
||||||
value, gimp_curve_map_value (curve, value));
|
value, gimp_curve_map_value (curve, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gimp_curve_view_set_selected (GIMP_CURVE_VIEW (c_tool->graph), point);
|
||||||
|
}
|
||||||
else if (state & gimp_get_toggle_behavior_mask ())
|
else if (state & gimp_get_toggle_behavior_mask ())
|
||||||
{
|
{
|
||||||
GimpHistogramChannel channel;
|
GimpHistogramChannel channel;
|
||||||
@ -262,18 +265,26 @@ gimp_curves_tool_button_release (GimpTool *tool,
|
|||||||
{
|
{
|
||||||
GimpCurve *curve = config->curve[channel];
|
GimpCurve *curve = config->curve[channel];
|
||||||
gdouble value = c_tool->picked_color[channel];
|
gdouble value = c_tool->picked_color[channel];
|
||||||
gint closest;
|
|
||||||
|
|
||||||
if (value != -1)
|
if (value != -1)
|
||||||
{
|
{
|
||||||
closest = gimp_curve_get_closest_point (curve, value);
|
gint point;
|
||||||
|
|
||||||
gimp_curve_view_set_selected (GIMP_CURVE_VIEW (c_tool->graph),
|
point = gimp_curve_get_point_at (curve, value);
|
||||||
closest);
|
|
||||||
|
|
||||||
gimp_curve_set_point (curve, closest,
|
if (point < 0)
|
||||||
|
{
|
||||||
|
point = gimp_curve_add_point (
|
||||||
|
curve,
|
||||||
value, gimp_curve_map_value (curve, value));
|
value, gimp_curve_map_value (curve, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (channel == config->channel)
|
||||||
|
{
|
||||||
|
gimp_curve_view_set_selected (GIMP_CURVE_VIEW (c_tool->graph),
|
||||||
|
point);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,6 +40,9 @@
|
|||||||
#include "gimpwidgets-utils.h"
|
#include "gimpwidgets-utils.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define POINT_MAX_DISTANCE 16.0
|
||||||
|
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
PROP_0,
|
PROP_0,
|
||||||
@ -97,6 +100,12 @@ static void gimp_curve_view_cut_clipboard (GimpCurveView *view);
|
|||||||
static void gimp_curve_view_copy_clipboard (GimpCurveView *view);
|
static void gimp_curve_view_copy_clipboard (GimpCurveView *view);
|
||||||
static void gimp_curve_view_paste_clipboard (GimpCurveView *view);
|
static void gimp_curve_view_paste_clipboard (GimpCurveView *view);
|
||||||
|
|
||||||
|
static void gimp_curve_view_curve_dirty (GimpCurve *curve,
|
||||||
|
GimpCurveView *view);
|
||||||
|
static void gimp_curve_view_curve_notify_n_points (GimpCurve *curve,
|
||||||
|
GParamSpec *pspec,
|
||||||
|
GimpCurveView *view);
|
||||||
|
|
||||||
static void gimp_curve_view_set_cursor (GimpCurveView *view,
|
static void gimp_curve_view_set_cursor (GimpCurveView *view,
|
||||||
gdouble x,
|
gdouble x,
|
||||||
gdouble y);
|
gdouble y);
|
||||||
@ -211,7 +220,7 @@ static void
|
|||||||
gimp_curve_view_init (GimpCurveView *view)
|
gimp_curve_view_init (GimpCurveView *view)
|
||||||
{
|
{
|
||||||
view->curve = NULL;
|
view->curve = NULL;
|
||||||
view->selected = 0;
|
view->selected = -1;
|
||||||
view->offset_x = 0.0;
|
view->offset_x = 0.0;
|
||||||
view->offset_y = 0.0;
|
view->offset_y = 0.0;
|
||||||
view->last_x = 0.0;
|
view->last_x = 0.0;
|
||||||
@ -418,9 +427,6 @@ gimp_curve_view_draw_point (GimpCurveView *view,
|
|||||||
|
|
||||||
gimp_curve_get_point (view->curve, i, &x, &y);
|
gimp_curve_get_point (view->curve, i, &x, &y);
|
||||||
|
|
||||||
if (x < 0.0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
y = 1.0 - y;
|
y = 1.0 - y;
|
||||||
|
|
||||||
#define RADIUS 3
|
#define RADIUS 3
|
||||||
@ -789,10 +795,9 @@ gimp_curve_view_button_press (GtkWidget *widget,
|
|||||||
gint width, height;
|
gint width, height;
|
||||||
gdouble x;
|
gdouble x;
|
||||||
gdouble y;
|
gdouble y;
|
||||||
|
gint point;
|
||||||
gdouble point_x;
|
gdouble point_x;
|
||||||
gdouble point_y;
|
gdouble point_y;
|
||||||
gint closest_point;
|
|
||||||
gint i;
|
|
||||||
|
|
||||||
if (! curve || bevent->button != 1)
|
if (! curve || bevent->button != 1)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -809,8 +814,6 @@ gimp_curve_view_button_press (GtkWidget *widget,
|
|||||||
x = CLAMP (x, 0.0, 1.0);
|
x = CLAMP (x, 0.0, 1.0);
|
||||||
y = CLAMP (y, 0.0, 1.0);
|
y = CLAMP (y, 0.0, 1.0);
|
||||||
|
|
||||||
closest_point = gimp_curve_get_closest_point (curve, x);
|
|
||||||
|
|
||||||
view->grabbed = TRUE;
|
view->grabbed = TRUE;
|
||||||
|
|
||||||
view->orig_curve = GIMP_CURVE (gimp_data_duplicate (GIMP_DATA (curve)));
|
view->orig_curve = GIMP_CURVE (gimp_data_duplicate (GIMP_DATA (curve)));
|
||||||
@ -820,47 +823,34 @@ gimp_curve_view_button_press (GtkWidget *widget,
|
|||||||
switch (gimp_curve_get_curve_type (curve))
|
switch (gimp_curve_get_curve_type (curve))
|
||||||
{
|
{
|
||||||
case GIMP_CURVE_SMOOTH:
|
case GIMP_CURVE_SMOOTH:
|
||||||
/* determine the leftmost and rightmost points */
|
point = gimp_curve_get_closest_point (curve, x, 1.0 - y,
|
||||||
view->leftmost = -1.0;
|
POINT_MAX_DISTANCE /
|
||||||
for (i = closest_point - 1; i >= 0; i--)
|
MAX (width, height));
|
||||||
{
|
|
||||||
gimp_curve_get_point (curve, i, &point_x, NULL);
|
|
||||||
|
|
||||||
if (point_x >= 0.0)
|
if (point < 0)
|
||||||
{
|
|
||||||
view->leftmost = point_x;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
view->rightmost = 2.0;
|
|
||||||
for (i = closest_point + 1; i < curve->n_points; i++)
|
|
||||||
{
|
|
||||||
gimp_curve_get_point (curve, i, &point_x, NULL);
|
|
||||||
|
|
||||||
if (point_x >= 0.0)
|
|
||||||
{
|
|
||||||
view->rightmost = point_x;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gimp_curve_view_set_selected (view, closest_point);
|
|
||||||
|
|
||||||
gimp_curve_get_point (curve, view->selected, &point_x, &point_y);
|
|
||||||
|
|
||||||
if (point_x >= 0.0)
|
|
||||||
{
|
|
||||||
view->offset_x = point_x - x;
|
|
||||||
view->offset_y = (1.0 - point_y) - y;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
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);
|
||||||
|
|
||||||
gimp_curve_set_point (curve, view->selected, x, 1.0 - y);
|
point = gimp_curve_add_point (curve, x, 1.0 - y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (point > 0)
|
||||||
|
gimp_curve_get_point (curve, point - 1, &view->leftmost, NULL);
|
||||||
|
else
|
||||||
|
view->leftmost = -1.0;
|
||||||
|
|
||||||
|
if (point < gimp_curve_get_n_points (curve) - 1)
|
||||||
|
gimp_curve_get_point (curve, point + 1, &view->rightmost, NULL);
|
||||||
|
else
|
||||||
|
view->rightmost = 2.0;
|
||||||
|
|
||||||
|
gimp_curve_view_set_selected (view, point);
|
||||||
|
|
||||||
|
gimp_curve_get_point (curve, point, &point_x, &point_y);
|
||||||
|
|
||||||
|
view->offset_x = point_x - x;
|
||||||
|
view->offset_y = (1.0 - point_y) - y;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GIMP_CURVE_FREE:
|
case GIMP_CURVE_FREE:
|
||||||
@ -912,7 +902,7 @@ gimp_curve_view_motion_notify (GtkWidget *widget,
|
|||||||
gdouble y;
|
gdouble y;
|
||||||
gdouble point_x;
|
gdouble point_x;
|
||||||
gdouble point_y;
|
gdouble point_y;
|
||||||
gint closest_point;
|
gint point;
|
||||||
|
|
||||||
if (! curve)
|
if (! curve)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -932,17 +922,19 @@ gimp_curve_view_motion_notify (GtkWidget *widget,
|
|||||||
x = CLAMP (x, 0.0, 1.0);
|
x = CLAMP (x, 0.0, 1.0);
|
||||||
y = CLAMP (y, 0.0, 1.0);
|
y = CLAMP (y, 0.0, 1.0);
|
||||||
|
|
||||||
closest_point = gimp_curve_get_closest_point (curve, x);
|
|
||||||
|
|
||||||
switch (gimp_curve_get_curve_type (curve))
|
switch (gimp_curve_get_curve_type (curve))
|
||||||
{
|
{
|
||||||
case GIMP_CURVE_SMOOTH:
|
case GIMP_CURVE_SMOOTH:
|
||||||
if (! view->grabbed) /* If no point is grabbed... */
|
if (! view->grabbed) /* If no point is grabbed... */
|
||||||
{
|
{
|
||||||
gimp_curve_get_point (curve, closest_point, &point_x, &point_y);
|
point = gimp_curve_get_closest_point (curve, x, 1.0 - y,
|
||||||
|
POINT_MAX_DISTANCE /
|
||||||
|
MAX (width, height));
|
||||||
|
|
||||||
if (point_x >= 0.0)
|
if (point >= 0)
|
||||||
{
|
{
|
||||||
|
gimp_curve_get_point (curve, point, &point_x, &point_y);
|
||||||
|
|
||||||
new_cursor = GDK_FLEUR;
|
new_cursor = GDK_FLEUR;
|
||||||
|
|
||||||
x = point_x;
|
x = point_x;
|
||||||
@ -965,21 +957,28 @@ gimp_curve_view_motion_notify (GtkWidget *widget,
|
|||||||
|
|
||||||
gimp_data_freeze (GIMP_DATA (curve));
|
gimp_data_freeze (GIMP_DATA (curve));
|
||||||
|
|
||||||
gimp_curve_set_point (curve, view->selected, -1.0, -1.0);
|
|
||||||
|
|
||||||
if (x > view->leftmost && x < view->rightmost)
|
if (x > view->leftmost && x < view->rightmost)
|
||||||
{
|
{
|
||||||
gint n_points = gimp_curve_get_n_points (curve);
|
if (view->selected < 0)
|
||||||
|
{
|
||||||
closest_point = ROUND (x * (gdouble) (n_points - 1));
|
gimp_curve_view_set_selected (
|
||||||
|
view,
|
||||||
gimp_curve_get_point (curve, closest_point, &point_x, NULL);
|
gimp_curve_add_point (curve, x, 1.0 - y));
|
||||||
|
}
|
||||||
if (point_x < 0.0)
|
else
|
||||||
gimp_curve_view_set_selected (view, closest_point);
|
{
|
||||||
|
|
||||||
gimp_curve_set_point (curve, view->selected, x, 1.0 - y);
|
gimp_curve_set_point (curve, view->selected, x, 1.0 - y);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (view->selected >= 0)
|
||||||
|
{
|
||||||
|
gimp_curve_delete_point (curve, view->selected);
|
||||||
|
|
||||||
|
gimp_curve_view_set_selected (view, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
gimp_data_thaw (GIMP_DATA (curve));
|
gimp_data_thaw (GIMP_DATA (curve));
|
||||||
}
|
}
|
||||||
@ -1071,8 +1070,10 @@ gimp_curve_view_key_press (GtkWidget *widget,
|
|||||||
GimpCurve *curve = view->curve;
|
GimpCurve *curve = view->curve;
|
||||||
gboolean handled = FALSE;
|
gboolean handled = FALSE;
|
||||||
|
|
||||||
if (! view->grabbed && curve &&
|
if (! view->grabbed &&
|
||||||
gimp_curve_get_curve_type (curve) == GIMP_CURVE_SMOOTH)
|
curve &&
|
||||||
|
gimp_curve_get_curve_type (curve) == GIMP_CURVE_SMOOTH &&
|
||||||
|
view->selected >= 0)
|
||||||
{
|
{
|
||||||
gint i = view->selected;
|
gint i = view->selected;
|
||||||
gdouble x, y;
|
gdouble x, y;
|
||||||
@ -1209,6 +1210,21 @@ gimp_curve_view_paste_clipboard (GimpCurveView *view)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gimp_curve_view_curve_dirty (GimpCurve *curve,
|
||||||
|
GimpCurveView *view)
|
||||||
|
{
|
||||||
|
gtk_widget_queue_draw (GTK_WIDGET (view));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gimp_curve_view_curve_notify_n_points (GimpCurve *curve,
|
||||||
|
GParamSpec *pspec,
|
||||||
|
GimpCurveView *view)
|
||||||
|
{
|
||||||
|
gimp_curve_view_set_selected (view, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* public functions */
|
/* public functions */
|
||||||
|
|
||||||
@ -1218,13 +1234,6 @@ gimp_curve_view_new (void)
|
|||||||
return g_object_new (GIMP_TYPE_CURVE_VIEW, NULL);
|
return g_object_new (GIMP_TYPE_CURVE_VIEW, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
gimp_curve_view_curve_dirty (GimpCurve *curve,
|
|
||||||
GimpCurveView *view)
|
|
||||||
{
|
|
||||||
gtk_widget_queue_draw (GTK_WIDGET (view));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
gimp_curve_view_set_curve (GimpCurveView *view,
|
gimp_curve_view_set_curve (GimpCurveView *view,
|
||||||
GimpCurve *curve,
|
GimpCurve *curve,
|
||||||
@ -1241,6 +1250,9 @@ gimp_curve_view_set_curve (GimpCurveView *view,
|
|||||||
g_signal_handlers_disconnect_by_func (view->curve,
|
g_signal_handlers_disconnect_by_func (view->curve,
|
||||||
gimp_curve_view_curve_dirty,
|
gimp_curve_view_curve_dirty,
|
||||||
view);
|
view);
|
||||||
|
g_signal_handlers_disconnect_by_func (view->curve,
|
||||||
|
gimp_curve_view_curve_notify_n_points,
|
||||||
|
view);
|
||||||
g_object_unref (view->curve);
|
g_object_unref (view->curve);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1252,6 +1264,9 @@ gimp_curve_view_set_curve (GimpCurveView *view,
|
|||||||
g_signal_connect (view->curve, "dirty",
|
g_signal_connect (view->curve, "dirty",
|
||||||
G_CALLBACK (gimp_curve_view_curve_dirty),
|
G_CALLBACK (gimp_curve_view_curve_dirty),
|
||||||
view);
|
view);
|
||||||
|
g_signal_connect (view->curve, "notify::n-points",
|
||||||
|
G_CALLBACK (gimp_curve_view_curve_notify_n_points),
|
||||||
|
view);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (view->curve_color)
|
if (view->curve_color)
|
||||||
@ -1262,6 +1277,8 @@ gimp_curve_view_set_curve (GimpCurveView *view,
|
|||||||
else
|
else
|
||||||
view->curve_color = NULL;
|
view->curve_color = NULL;
|
||||||
|
|
||||||
|
gimp_curve_view_set_selected (view, -1);
|
||||||
|
|
||||||
gtk_widget_queue_draw (GTK_WIDGET (view));
|
gtk_widget_queue_draw (GTK_WIDGET (view));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user