Commit 08bd7a19 authored by Simon Budig's avatar Simon Budig Committed by Simon Budig

app/vectors/gimpstroke.[ch] Implemented function to connect two strokes.

2003-08-27  Simon Budig  <simon@gimp.org>

	* app/vectors/gimpstroke.[ch]
	* app/vectors/gimpbezierstroke.c: Implemented function to
	connect two strokes.

	* app/tools/gimpvectortool.[ch]: Use it. Right now you have
	to click on one endpoint, and then SHIFT+CTRL+ALT-Click on
	the other endpoint.

	Suggestions on how to solve that more sanely are welcome...
parent 1ce30550
2003-08-27 Simon Budig <simon@gimp.org>
* app/vectors/gimpstroke.[ch]
* app/vectors/gimpbezierstroke.c: Implemented function to
connect two strokes.
* app/tools/gimpvectortool.[ch]: Use it. Right now you have
to click on one endpoint, and then SHIFT+CTRL+ALT-Click on
the other endpoint.
Suggestions on how to solve that more sanely are welcome...
2003-08-27 Michael Natterer <mitch@gimp.org>
* app/composite/gimp-composite-generic.c
......@@ -428,16 +428,34 @@ gimp_vector_tool_button_press (GimpTool *tool,
if (vector_tool->function == VECTORS_MOVE_HANDLE)
gimp_vector_tool_on_handle (tool, coords, GIMP_ANCHOR_CONTROL,
gdisp, &anchor, &stroke);
/* hackish */
if (state & GDK_MOD1_MASK)
gimp_stroke_close (stroke);
}
vector_tool->cur_stroke = stroke;
vector_tool->cur_anchor = anchor;
break; /* here it is... :-) */
case VECTORS_CONNECT_STROKES:
gimp_vector_tool_on_handle (tool, coords, GIMP_ANCHOR_ANCHOR,
gdisp, &anchor, &stroke);
if (anchor && stroke &&
vector_tool->cur_anchor && vector_tool->cur_stroke &&
anchor != vector_tool->cur_anchor &&
gimp_stroke_is_extendable (stroke, anchor) &&
gimp_stroke_is_extendable (vector_tool->cur_stroke,
vector_tool->cur_anchor))
{
gimp_stroke_connect_stroke (vector_tool->cur_stroke,
vector_tool->cur_anchor,
stroke, anchor);
if (stroke != vector_tool->cur_stroke
&& gimp_stroke_is_empty (stroke))
gimp_vectors_stroke_remove (vector_tool->vectors, stroke);
vector_tool->cur_anchor = anchor;
vector_tool->function = VECTORS_MOVE_ANCHOR;
}
break;
case VECTORS_MOVE_CURVE:
if (gimp_vector_tool_on_curve (tool, coords, gdisp,
NULL, &pos, &segment_start, &stroke)
......@@ -813,7 +831,10 @@ gimp_vector_tool_oper_update (GimpTool *tool,
{
if (state & GDK_SHIFT_MASK)
{
vector_tool->function = VECTORS_CONVERT_EDGE;
if (state & GDK_MOD1_MASK)
vector_tool->function = VECTORS_CONNECT_STROKES;
else
vector_tool->function = VECTORS_CONVERT_EDGE;
}
else
{
......@@ -855,7 +876,10 @@ gimp_vector_tool_oper_update (GimpTool *tool,
}
else
{
vector_tool->function = VECTORS_MOVE_CURVE;
if (!options->polygonal)
vector_tool->function = VECTORS_MOVE_CURVE;
else
vector_tool->function = VECTORS_ADD_ANCHOR;
}
}
else
......@@ -920,6 +944,9 @@ gimp_vector_tool_cursor_update (GimpTool *tool,
case VECTORS_MOVE_CURVE:
cmodifier = GIMP_CURSOR_MODIFIER_MOVE;
break;
case VECTORS_CONNECT_STROKES:
cmodifier = GIMP_CURSOR_MODIFIER_INTERSECT;
break;
default:
cursor = GIMP_BAD_CURSOR;
cmodifier = GIMP_CURSOR_MODIFIER_NONE;
......
......@@ -37,6 +37,7 @@ typedef enum
VECTORS_MOVE_CURVE,
VECTORS_INSERT_ANCHOR,
VECTORS_DELETE_ANCHOR,
VECTORS_CONNECT_STROKES,
VECTORS_DELETE_SEGMENT,
VECTORS_CONVERT_EDGE,
VECTORS_FINISHED
......
......@@ -89,14 +89,21 @@ static gboolean gimp_bezier_stroke_anchor_is_insertable
static GimpAnchor * gimp_bezier_stroke_anchor_insert (GimpStroke *stroke,
GimpAnchor *predec,
gdouble position);
static gboolean gimp_bezier_stroke_is_extendable (GimpStroke *stroke,
GimpAnchor *neighbor);
static gboolean gimp_bezier_stroke_is_extendable (GimpStroke *stroke,
GimpAnchor *neighbor);
static gboolean gimp_bezier_stroke_connect_stroke (GimpStroke *stroke,
GimpAnchor *anchor,
GimpStroke *extension,
GimpAnchor *neighbor);
static GArray * gimp_bezier_stroke_interpolate (const GimpStroke *stroke,
const gdouble precision,
gboolean *closed);
static void gimp_bezier_stroke_finalize (GObject *object);
static GList * gimp_bezier_stroke_get_anchor_listitem (GList *list);
static void gimp_bezier_coords_mix (const gdouble amul,
const GimpCoords *a,
const gdouble bmul,
......@@ -189,6 +196,7 @@ gimp_bezier_stroke_class_init (GimpBezierStrokeClass *klass)
stroke_class->anchor_insert = gimp_bezier_stroke_anchor_insert;
stroke_class->is_extendable = gimp_bezier_stroke_is_extendable;
stroke_class->extend = gimp_bezier_stroke_extend;
stroke_class->connect_stroke = gimp_bezier_stroke_connect_stroke;
stroke_class->interpolate = gimp_bezier_stroke_interpolate;
}
......@@ -1051,6 +1059,54 @@ gimp_bezier_stroke_extend (GimpStroke *stroke,
}
}
static gboolean
gimp_bezier_stroke_connect_stroke (GimpStroke *stroke,
GimpAnchor *anchor,
GimpStroke *extension,
GimpAnchor *neighbor)
{
GList *list1, *list2;
g_return_val_if_fail (stroke->closed == FALSE &&
extension->closed == FALSE, FALSE);
list1 = g_list_find (stroke->anchors, anchor);
list1 = gimp_bezier_stroke_get_anchor_listitem (list1);
list2 = g_list_find (extension->anchors, neighbor);
list2 = gimp_bezier_stroke_get_anchor_listitem (list2);
g_return_val_if_fail (list1 != NULL && list2 != NULL, FALSE);
if (stroke == extension)
{
g_return_val_if_fail ((list1->prev && list1->prev->prev == NULL &&
list2->next && list2->next->next == NULL) ||
(list1->next && list1->next->next == NULL &&
list2->prev && list2->prev->prev == NULL), FALSE);
gimp_stroke_close (stroke);
return TRUE;
}
if (list1->prev && list1->prev->prev == NULL)
{
stroke->anchors = g_list_reverse (stroke->anchors);
}
g_return_val_if_fail (list1->next && list1->next->next == NULL, FALSE);
if (list2->next && list2->next->next == NULL)
{
extension->anchors = g_list_reverse (extension->anchors);
}
g_return_val_if_fail (list2->prev && list2->prev->prev == NULL, FALSE);
stroke->anchors = g_list_concat (stroke->anchors, extension->anchors);
extension->anchors = NULL;
return TRUE;
}
static void
gimp_bezier_stroke_anchor_move_relative (GimpStroke *stroke,
......@@ -1252,6 +1308,25 @@ gimp_bezier_stroke_interpolate (const GimpStroke *stroke,
}
static GList *
gimp_bezier_stroke_get_anchor_listitem (GList *list)
{
if (!list)
return NULL;
if (GIMP_ANCHOR (list->data)->type == GIMP_ANCHOR_ANCHOR)
return list;
if (list->prev && GIMP_ANCHOR (list->prev->data)->type == GIMP_ANCHOR_ANCHOR)
return list->prev;
if (list->next && GIMP_ANCHOR (list->next->data)->type == GIMP_ANCHOR_ANCHOR)
return list->next;
g_return_val_if_fail (/* bezier stroke inconsistent! */ FALSE, NULL);
}
/* local helper functions for bezier subdivision */
/* amul * a + bmul * b */
......
......@@ -97,10 +97,16 @@ static GimpAnchor * gimp_stroke_real_anchor_insert (GimpStroke *stroke,
static gboolean gimp_stroke_real_is_extendable (GimpStroke *stroke,
GimpAnchor *neighbor);
static GimpAnchor * gimp_stroke_real_extend (GimpStroke *stroke,
const GimpCoords *coords,
GimpAnchor *neighbor,
GimpVectorExtendMode extend_mode);
static GimpAnchor * gimp_stroke_real_extend (GimpStroke *stroke,
const GimpCoords *coords,
GimpAnchor *neighbor,
GimpVectorExtendMode extend_mode);
gboolean gimp_stroke_real_connect_stroke (GimpStroke *stroke,
GimpAnchor *anchor,
GimpStroke *extension,
GimpAnchor *neighbor);
static gboolean gimp_stroke_real_is_empty (const GimpStroke *stroke);
......@@ -210,6 +216,7 @@ gimp_stroke_class_init (GimpStrokeClass *klass)
klass->anchor_insert = gimp_stroke_real_anchor_insert;
klass->is_extendable = gimp_stroke_real_is_extendable;
klass->extend = gimp_stroke_real_extend;
klass->connect_stroke = gimp_stroke_real_connect_stroke;
klass->is_empty = gimp_stroke_real_is_empty;
klass->get_length = gimp_stroke_real_get_length;
......@@ -249,6 +256,9 @@ gimp_stroke_finalize (GObject *object)
for (list = stroke->anchors; list; list = list->next)
gimp_anchor_free (GIMP_ANCHOR (list->data));
g_list_free (stroke->anchors);
stroke->anchors = NULL;
G_OBJECT_CLASS (parent_class)->finalize (object);
}
......@@ -687,9 +697,33 @@ gimp_stroke_real_extend (GimpStroke *stroke,
GimpAnchor *neighbor,
GimpVectorExtendMode extend_mode)
{
g_printerr ("gimp_stroke_extend: default implementation\n");
return NULL;
}
gboolean
gimp_stroke_connect_stroke (GimpStroke *stroke,
GimpAnchor *anchor,
GimpStroke *extension,
GimpAnchor *neighbor)
{
g_return_val_if_fail (GIMP_IS_STROKE (stroke), FALSE);
g_return_val_if_fail (GIMP_IS_STROKE (extension), FALSE);
return GIMP_STROKE_GET_CLASS (stroke)->connect_stroke (stroke, anchor,
extension, neighbor);
}
gboolean
gimp_stroke_real_connect_stroke (GimpStroke *stroke,
GimpAnchor *anchor,
GimpStroke *extension,
GimpAnchor *neighbor)
{
g_printerr ("gimp_stroke_connect_stroke: default implementation\n");
return FALSE;
}
gboolean
gimp_stroke_is_empty (const GimpStroke *stroke)
{
......
......@@ -102,11 +102,14 @@ struct _GimpStrokeClass
gdouble position);
gboolean (* is_extendable) (GimpStroke *stroke,
GimpAnchor *neighbor);
GimpAnchor * (* extend) (GimpStroke *stroke,
const GimpCoords *coords,
GimpAnchor *neighbor,
GimpVectorExtendMode extend_mode);
gboolean (* connect_stroke) (GimpStroke *stroke,
GimpAnchor *anchor,
GimpStroke *extension,
GimpAnchor *neighbor);
gboolean (* is_empty) (const GimpStroke *stroke);
gdouble (* get_length) (const GimpStroke *stroke);
......@@ -239,6 +242,11 @@ GimpAnchor * gimp_stroke_extend (GimpStroke *stroke,
GimpAnchor *neighbor,
GimpVectorExtendMode extend_mode);
gboolean gimp_stroke_connect_stroke (GimpStroke *stroke,
GimpAnchor *anchor,
GimpStroke *extension,
GimpAnchor *neighbor);
gboolean gimp_stroke_is_empty (const GimpStroke *stroke);
/* accessing the shape of the curve */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment