app/vectors/gimpstroke.[ch] Implemented direct moving of the curve. Whee!
2003-08-26 Simon Budig <simon@gimp.org> * app/vectors/gimpstroke.[ch] * app/vectors/gimpbezierstroke.c: Implemented direct moving of the curve. Whee! :-) * app/tools/gimpvectortool.[ch]: Use it.
This commit is contained in:
@ -1,3 +1,11 @@
|
||||
2003-08-26 Simon Budig <simon@gimp.org>
|
||||
|
||||
* app/vectors/gimpstroke.[ch]
|
||||
* app/vectors/gimpbezierstroke.c: Implemented direct moving of the
|
||||
curve. Whee! :-)
|
||||
|
||||
* app/tools/gimpvectortool.[ch]: Use it.
|
||||
|
||||
2003-08-25 Michael Natterer <mitch@gimp.org>
|
||||
|
||||
* app/core/core-enums.[ch]: added enum GimpContainerPolicy.
|
||||
|
@ -438,6 +438,21 @@ gimp_vector_tool_button_press (GimpTool *tool,
|
||||
|
||||
break; /* here it is... :-) */
|
||||
|
||||
case VECTORS_MOVE_CURVE:
|
||||
if (gimp_vector_tool_on_curve (tool, coords, gdisp,
|
||||
NULL, &pos, &segment_start, &stroke)
|
||||
&& gimp_stroke_point_is_movable (stroke, segment_start, pos))
|
||||
{
|
||||
vector_tool->cur_stroke = stroke;
|
||||
vector_tool->cur_anchor = segment_start;
|
||||
vector_tool->cur_position = pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
vector_tool->function = VECTORS_FINISHED;
|
||||
}
|
||||
break;
|
||||
|
||||
case VECTORS_CONVERT_EDGE:
|
||||
if (gimp_vector_tool_on_handle (tool, coords,
|
||||
GIMP_ANCHOR_ANCHOR, gdisp,
|
||||
@ -544,6 +559,14 @@ gimp_vector_tool_motion (GimpTool *tool,
|
||||
gimp_stroke_anchor_move_absolute (vector_tool->cur_stroke,
|
||||
vector_tool->cur_anchor,
|
||||
coords, vector_tool->restriction);
|
||||
break;
|
||||
|
||||
case VECTORS_MOVE_CURVE:
|
||||
gimp_stroke_point_move_absolute (vector_tool->cur_stroke,
|
||||
vector_tool->cur_anchor,
|
||||
vector_tool->cur_position,
|
||||
coords, vector_tool->restriction);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
@ -894,10 +917,8 @@ gimp_vector_tool_cursor_update (GimpTool *tool,
|
||||
cmodifier = GIMP_CURSOR_MODIFIER_HAND;
|
||||
break;
|
||||
case VECTORS_MOVE_ANCHOR:
|
||||
cmodifier = GIMP_CURSOR_MODIFIER_MOVE;
|
||||
break;
|
||||
case VECTORS_MOVE_CURVE:
|
||||
cmodifier = GIMP_CURSOR_MODIFIER_NONE;
|
||||
cmodifier = GIMP_CURSOR_MODIFIER_MOVE;
|
||||
break;
|
||||
default:
|
||||
cursor = GIMP_BAD_CURSOR;
|
||||
|
@ -63,10 +63,11 @@ struct _GimpVectorTool
|
||||
gint last_x; /* last x coordinate */
|
||||
gint last_y; /* last y coordinate */
|
||||
|
||||
GimpAnchor *cur_anchor; /* The current Anchor */
|
||||
GimpStroke *cur_stroke; /* The current Stroke */
|
||||
GimpVectors *vectors; /* The current Vector data */
|
||||
GList *active_anchors; /* The currently active anchors */
|
||||
GimpAnchor *cur_anchor; /* The current Anchor */
|
||||
GimpStroke *cur_stroke; /* The current Stroke */
|
||||
gdouble cur_position; /* The current Position on a segment */
|
||||
GimpVectors *vectors; /* The current Vector data */
|
||||
GList *active_anchors; /* The currently active anchors */
|
||||
};
|
||||
|
||||
struct _GimpVectorToolClass
|
||||
|
@ -62,6 +62,24 @@ static void gimp_bezier_stroke_anchor_convert (GimpStroke *stroke,
|
||||
GimpAnchorFeatureType feature);
|
||||
static void gimp_bezier_stroke_anchor_delete (GimpStroke *stroke,
|
||||
GimpAnchor *anchor);
|
||||
static gboolean gimp_bezier_stroke_point_is_movable
|
||||
(GimpStroke *stroke,
|
||||
GimpAnchor *predec,
|
||||
gdouble position);
|
||||
static void gimp_bezier_stroke_point_move_relative
|
||||
(GimpStroke *stroke,
|
||||
GimpAnchor *predec,
|
||||
gdouble position,
|
||||
const GimpCoords *deltacoord,
|
||||
GimpAnchorFeatureType feature);
|
||||
static void gimp_bezier_stroke_point_move_absolute
|
||||
(GimpStroke *stroke,
|
||||
GimpAnchor *predec,
|
||||
gdouble position,
|
||||
const GimpCoords *coord,
|
||||
GimpAnchorFeatureType feature);
|
||||
|
||||
|
||||
static GimpStroke * gimp_bezier_stroke_open (GimpStroke *stroke,
|
||||
GimpAnchor *end_anchor);
|
||||
static gboolean gimp_bezier_stroke_anchor_is_insertable
|
||||
@ -163,6 +181,9 @@ gimp_bezier_stroke_class_init (GimpBezierStrokeClass *klass)
|
||||
stroke_class->anchor_move_absolute = gimp_bezier_stroke_anchor_move_absolute;
|
||||
stroke_class->anchor_convert = gimp_bezier_stroke_anchor_convert;
|
||||
stroke_class->anchor_delete = gimp_bezier_stroke_anchor_delete;
|
||||
stroke_class->point_is_movable = gimp_bezier_stroke_point_is_movable;
|
||||
stroke_class->point_move_relative = gimp_bezier_stroke_point_move_relative;
|
||||
stroke_class->point_move_absolute = gimp_bezier_stroke_point_move_absolute;
|
||||
stroke_class->open = gimp_bezier_stroke_open;
|
||||
stroke_class->anchor_is_insertable = gimp_bezier_stroke_anchor_is_insertable;
|
||||
stroke_class->anchor_insert = gimp_bezier_stroke_anchor_insert;
|
||||
@ -409,6 +430,118 @@ gimp_bezier_stroke_anchor_insert (GimpStroke *stroke,
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
gimp_bezier_stroke_point_is_movable (GimpStroke *stroke,
|
||||
GimpAnchor *predec,
|
||||
gdouble position)
|
||||
{
|
||||
g_return_val_if_fail (GIMP_IS_BEZIER_STROKE (stroke), FALSE);
|
||||
|
||||
return (g_list_find (stroke->anchors, predec) != NULL);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gimp_bezier_stroke_point_move_relative (GimpStroke *stroke,
|
||||
GimpAnchor *predec,
|
||||
gdouble position,
|
||||
const GimpCoords *deltacoord,
|
||||
GimpAnchorFeatureType feature)
|
||||
{
|
||||
GimpCoords beziercoords[4];
|
||||
GList *segment_start, *list;
|
||||
gint i;
|
||||
gdouble feel_good;
|
||||
|
||||
g_return_if_fail (GIMP_IS_BEZIER_STROKE (stroke));
|
||||
|
||||
segment_start = g_list_find (stroke->anchors, predec);
|
||||
|
||||
g_return_if_fail (segment_start != NULL);
|
||||
|
||||
list = segment_start;
|
||||
|
||||
for (i=0; i <= 3; i++)
|
||||
{
|
||||
beziercoords[i] = ((GimpAnchor *) list->data)->position;
|
||||
list = g_list_next (list);
|
||||
if (!list)
|
||||
list = stroke->anchors;
|
||||
}
|
||||
|
||||
|
||||
if (position <= 0.5)
|
||||
feel_good = (pow(2 * position, 3)) / 2;
|
||||
else
|
||||
feel_good = (1 - pow((1-position)*2, 3)) / 2 + 0.5;
|
||||
|
||||
gimp_bezier_coords_mix (1.0, &(beziercoords[1]),
|
||||
(1-feel_good)/(3*position*(1-position)*(1-position)),
|
||||
deltacoord,
|
||||
&(beziercoords[1]));
|
||||
gimp_bezier_coords_mix (1.0, &(beziercoords[2]),
|
||||
feel_good/(3*position*position*(1-position)),
|
||||
deltacoord,
|
||||
&(beziercoords[2]));
|
||||
|
||||
list = segment_start;
|
||||
list = g_list_next (list);
|
||||
if (!list)
|
||||
list = stroke->anchors;
|
||||
|
||||
for (i=1; i <= 2; i++)
|
||||
{
|
||||
((GimpAnchor *) list->data)->position = beziercoords[i];
|
||||
list = g_list_next (list);
|
||||
if (!list)
|
||||
list = stroke->anchors;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gimp_bezier_stroke_point_move_absolute (GimpStroke *stroke,
|
||||
GimpAnchor *predec,
|
||||
gdouble position,
|
||||
const GimpCoords *coord,
|
||||
GimpAnchorFeatureType feature)
|
||||
{
|
||||
GimpCoords deltacoord;
|
||||
GimpCoords tmp1, tmp2, abs_pos;
|
||||
GimpCoords beziercoords[4];
|
||||
GList *segment_start, *list;
|
||||
gint i;
|
||||
|
||||
g_return_if_fail (GIMP_IS_BEZIER_STROKE (stroke));
|
||||
|
||||
segment_start = g_list_find (stroke->anchors, predec);
|
||||
|
||||
g_return_if_fail (segment_start != NULL);
|
||||
|
||||
list = segment_start;
|
||||
|
||||
for (i=0; i <= 3; i++)
|
||||
{
|
||||
beziercoords[i] = ((GimpAnchor *) list->data)->position;
|
||||
list = g_list_next (list);
|
||||
if (!list)
|
||||
list = stroke->anchors;
|
||||
}
|
||||
|
||||
gimp_bezier_coords_mix ((1-position)*(1-position)*(1-position), &(beziercoords[0]),
|
||||
3*(1-position)*(1-position)*position, &(beziercoords[1]),
|
||||
&tmp1);
|
||||
gimp_bezier_coords_mix (3*(1-position)*position*position, &(beziercoords[2]),
|
||||
position*position*position, &(beziercoords[3]),
|
||||
&tmp2);
|
||||
gimp_bezier_coords_add (&tmp1, &tmp2, &abs_pos);
|
||||
|
||||
gimp_bezier_coords_difference (coord, &abs_pos, &deltacoord);
|
||||
|
||||
gimp_bezier_stroke_point_move_relative (stroke, predec, position,
|
||||
&deltacoord, feature);
|
||||
}
|
||||
|
||||
static gdouble
|
||||
gimp_bezier_stroke_nearest_point_get (const GimpStroke *stroke,
|
||||
const GimpCoords *coord,
|
||||
|
@ -41,6 +41,12 @@ static void gimp_stroke_finalize (GObject *object);
|
||||
static gsize gimp_stroke_get_memsize (GimpObject *object,
|
||||
gsize *gui_size);
|
||||
|
||||
gdouble gimp_stroke_real_nearest_point_get (const GimpStroke *stroke,
|
||||
const GimpCoords *coord,
|
||||
const gdouble precision,
|
||||
GimpCoords *ret_point,
|
||||
GimpAnchor **ret_segment_start,
|
||||
gdouble *ret_pos);
|
||||
static GimpAnchor * gimp_stroke_real_anchor_get (const GimpStroke *stroke,
|
||||
const GimpCoords *coord);
|
||||
static GimpAnchor * gimp_stroke_real_anchor_get_next (const GimpStroke *stroke,
|
||||
@ -61,6 +67,23 @@ static void gimp_stroke_real_anchor_convert (GimpStroke *stroke,
|
||||
GimpAnchorFeatureType feature);
|
||||
static void gimp_stroke_real_anchor_delete (GimpStroke *stroke,
|
||||
GimpAnchor *anchor);
|
||||
static gboolean gimp_stroke_real_point_is_movable
|
||||
(GimpStroke *stroke,
|
||||
GimpAnchor *predec,
|
||||
gdouble position);
|
||||
static void gimp_stroke_real_point_move_relative
|
||||
(GimpStroke *stroke,
|
||||
GimpAnchor *predec,
|
||||
gdouble position,
|
||||
const GimpCoords *deltacoord,
|
||||
GimpAnchorFeatureType feature);
|
||||
static void gimp_stroke_real_point_move_absolute
|
||||
(GimpStroke *stroke,
|
||||
GimpAnchor *predec,
|
||||
gdouble position,
|
||||
const GimpCoords *coord,
|
||||
GimpAnchorFeatureType feature);
|
||||
|
||||
static GimpStroke * gimp_stroke_real_open (GimpStroke *stroke,
|
||||
GimpAnchor *end_anchor);
|
||||
static gboolean gimp_stroke_real_anchor_is_insertable
|
||||
@ -177,6 +200,11 @@ gimp_stroke_class_init (GimpStrokeClass *klass)
|
||||
klass->anchor_convert = gimp_stroke_real_anchor_convert;
|
||||
klass->anchor_delete = gimp_stroke_real_anchor_delete;
|
||||
|
||||
klass->point_is_movable = gimp_stroke_real_point_is_movable;
|
||||
klass->point_move_relative = gimp_stroke_real_point_move_relative;
|
||||
klass->point_move_absolute = gimp_stroke_real_point_move_absolute;
|
||||
|
||||
klass->nearest_point_get = gimp_stroke_real_nearest_point_get;
|
||||
klass->open = gimp_stroke_real_open;
|
||||
klass->anchor_is_insertable = gimp_stroke_real_anchor_is_insertable;
|
||||
klass->anchor_insert = gimp_stroke_real_anchor_insert;
|
||||
@ -252,12 +280,12 @@ gimp_stroke_anchor_get (const GimpStroke *stroke,
|
||||
|
||||
|
||||
gdouble
|
||||
gimp_stroke_nearest_point_get (const GimpStroke *stroke,
|
||||
const GimpCoords *coord,
|
||||
const gdouble precision,
|
||||
GimpCoords *ret_point,
|
||||
GimpAnchor **ret_segment_start,
|
||||
gdouble *ret_pos)
|
||||
gimp_stroke_nearest_point_get (const GimpStroke *stroke,
|
||||
const GimpCoords *coord,
|
||||
const gdouble precision,
|
||||
GimpCoords *ret_point,
|
||||
GimpAnchor **ret_segment_start,
|
||||
gdouble *ret_pos)
|
||||
{
|
||||
g_return_val_if_fail (GIMP_IS_STROKE (stroke), FALSE);
|
||||
g_return_val_if_fail (coord != NULL, FALSE);
|
||||
@ -270,6 +298,18 @@ gimp_stroke_nearest_point_get (const GimpStroke *stroke,
|
||||
ret_pos);
|
||||
}
|
||||
|
||||
gdouble
|
||||
gimp_stroke_real_nearest_point_get (const GimpStroke *stroke,
|
||||
const GimpCoords *coord,
|
||||
const gdouble precision,
|
||||
GimpCoords *ret_point,
|
||||
GimpAnchor **ret_segment_start,
|
||||
gdouble *ret_pos)
|
||||
{
|
||||
g_printerr ("gimp_stroke_nearest_point_get: default implementation\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static GimpAnchor *
|
||||
gimp_stroke_real_anchor_get (const GimpStroke *stroke,
|
||||
const GimpCoords *coord)
|
||||
@ -437,6 +477,78 @@ gimp_stroke_real_anchor_move_absolute (GimpStroke *stroke,
|
||||
anchor->position.y = coord->y;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gimp_stroke_point_is_movable (GimpStroke *stroke,
|
||||
GimpAnchor *predec,
|
||||
gdouble position)
|
||||
{
|
||||
g_return_val_if_fail (GIMP_IS_STROKE (stroke), FALSE);
|
||||
|
||||
return GIMP_STROKE_GET_CLASS (stroke)->point_is_movable (stroke, predec,
|
||||
position);
|
||||
}
|
||||
|
||||
|
||||
gboolean
|
||||
gimp_stroke_real_point_is_movable (GimpStroke *stroke,
|
||||
GimpAnchor *predec,
|
||||
gdouble position)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
gimp_stroke_point_move_relative (GimpStroke *stroke,
|
||||
GimpAnchor *predec,
|
||||
gdouble position,
|
||||
const GimpCoords *deltacoord,
|
||||
GimpAnchorFeatureType feature)
|
||||
{
|
||||
g_return_if_fail (GIMP_IS_STROKE (stroke));
|
||||
|
||||
GIMP_STROKE_GET_CLASS (stroke)->point_move_relative (stroke, predec,
|
||||
position, deltacoord,
|
||||
feature);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
gimp_stroke_real_point_move_relative (GimpStroke *stroke,
|
||||
GimpAnchor *predec,
|
||||
gdouble position,
|
||||
const GimpCoords *deltacoord,
|
||||
GimpAnchorFeatureType feature)
|
||||
{
|
||||
g_printerr ("gimp_stroke_point_move_relative: default implementation\n");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
gimp_stroke_point_move_absolute (GimpStroke *stroke,
|
||||
GimpAnchor *predec,
|
||||
gdouble position,
|
||||
const GimpCoords *coord,
|
||||
GimpAnchorFeatureType feature)
|
||||
{
|
||||
g_return_if_fail (GIMP_IS_STROKE (stroke));
|
||||
|
||||
GIMP_STROKE_GET_CLASS (stroke)->point_move_absolute (stroke, predec,
|
||||
position, coord,
|
||||
feature);
|
||||
}
|
||||
|
||||
void
|
||||
gimp_stroke_real_point_move_absolute (GimpStroke *stroke,
|
||||
GimpAnchor *predec,
|
||||
gdouble position,
|
||||
const GimpCoords *coord,
|
||||
GimpAnchorFeatureType feature)
|
||||
{
|
||||
g_printerr ("gimp_stroke_point_move_absolute: default implementation\n");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
gimp_stroke_close (GimpStroke *stroke)
|
||||
{
|
||||
|
@ -77,6 +77,20 @@ struct _GimpStrokeClass
|
||||
GimpAnchorFeatureType feature);
|
||||
void (* anchor_delete) (GimpStroke *stroke,
|
||||
GimpAnchor *anchor);
|
||||
|
||||
gboolean (* point_is_movable) (GimpStroke *stroke,
|
||||
GimpAnchor *predec,
|
||||
gdouble position);
|
||||
void (* point_move_relative) (GimpStroke *stroke,
|
||||
GimpAnchor *predec,
|
||||
gdouble position,
|
||||
const GimpCoords *deltacoord,
|
||||
GimpAnchorFeatureType feature);
|
||||
void (* point_move_absolute) (GimpStroke *stroke,
|
||||
GimpAnchor *predec,
|
||||
gdouble position,
|
||||
const GimpCoords *coord,
|
||||
GimpAnchorFeatureType feature);
|
||||
|
||||
GimpStroke * (* open) (GimpStroke *stroke,
|
||||
GimpAnchor *end_anchor);
|
||||
@ -88,6 +102,7 @@ struct _GimpStrokeClass
|
||||
gdouble position);
|
||||
gboolean (* is_extendable) (GimpStroke *stroke,
|
||||
GimpAnchor *neighbor);
|
||||
|
||||
GimpAnchor * (* extend) (GimpStroke *stroke,
|
||||
const GimpCoords *coords,
|
||||
GimpAnchor *neighbor,
|
||||
@ -184,6 +199,20 @@ void gimp_stroke_anchor_move_absolute (GimpStroke *stroke,
|
||||
const GimpCoords *coord,
|
||||
GimpAnchorFeatureType feature);
|
||||
|
||||
gboolean gimp_stroke_point_is_movable (GimpStroke *stroke,
|
||||
GimpAnchor *predec,
|
||||
gdouble position);
|
||||
void gimp_stroke_point_move_relative (GimpStroke *stroke,
|
||||
GimpAnchor *predec,
|
||||
gdouble position,
|
||||
const GimpCoords *deltacoord,
|
||||
GimpAnchorFeatureType feature);
|
||||
void gimp_stroke_point_move_absolute (GimpStroke *stroke,
|
||||
GimpAnchor *predec,
|
||||
gdouble position,
|
||||
const GimpCoords *coord,
|
||||
GimpAnchorFeatureType feature);
|
||||
|
||||
void gimp_stroke_close (GimpStroke *stroke);
|
||||
|
||||
void gimp_stroke_anchor_convert (GimpStroke *stroke,
|
||||
|
Reference in New Issue
Block a user