diff --git a/ChangeLog b/ChangeLog index 7e81450479..48caff34cf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2003-04-14 Simon Budig + + * app/vectors/gimpstroke.[ch] + * app/vectors/gimpvectors.[ch]: Changed vectors->strokes to a + GList and removed stroke->next. Implemented stuff for duplicating + strokes. Duplicating a vector works now. + + * app/tools/gimpvectortool.c: added not-yet-used function to + determine where a click has been. Refcounting stuff changed. + + * app/core/gimpimage-mask-select.c + * app/paint/gimppaintcore-stroke.c: Changed accordingly. + 2003-04-13 Michael Natterer * app/widgets/gimpcontainergridview.c: connect to "realize" of the diff --git a/app/core/gimpchannel-select.c b/app/core/gimpchannel-select.c index b4c86e454c..ac7773cb14 100644 --- a/app/core/gimpchannel-select.c +++ b/app/core/gimpchannel-select.c @@ -191,9 +191,9 @@ gimp_image_mask_select_vectors (GimpImage *gimage, gdouble feather_radius_x, gdouble feather_radius_y) { - GimpStroke *stroke; - GArray *coords = NULL; - gboolean closed; + GList *stroke; + GArray *coords = NULL; + gboolean closed; g_return_if_fail (GIMP_IS_IMAGE (gimage)); @@ -202,8 +202,8 @@ gimp_image_mask_select_vectors (GimpImage *gimage, */ for (stroke = vectors->strokes; stroke; stroke = stroke->next) { - coords = gimp_stroke_interpolate (stroke, 1.0, &closed); - + coords = gimp_stroke_interpolate (GIMP_STROKE (stroke->data), + 1.0, &closed); if (coords) break; } diff --git a/app/core/gimpimage-mask-select.c b/app/core/gimpimage-mask-select.c index b4c86e454c..ac7773cb14 100644 --- a/app/core/gimpimage-mask-select.c +++ b/app/core/gimpimage-mask-select.c @@ -191,9 +191,9 @@ gimp_image_mask_select_vectors (GimpImage *gimage, gdouble feather_radius_x, gdouble feather_radius_y) { - GimpStroke *stroke; - GArray *coords = NULL; - gboolean closed; + GList *stroke; + GArray *coords = NULL; + gboolean closed; g_return_if_fail (GIMP_IS_IMAGE (gimage)); @@ -202,8 +202,8 @@ gimp_image_mask_select_vectors (GimpImage *gimage, */ for (stroke = vectors->strokes; stroke; stroke = stroke->next) { - coords = gimp_stroke_interpolate (stroke, 1.0, &closed); - + coords = gimp_stroke_interpolate (GIMP_STROKE (stroke->data), + 1.0, &closed); if (coords) break; } diff --git a/app/paint/gimppaintcore-stroke.c b/app/paint/gimppaintcore-stroke.c index 866023eb7a..3a83df86d6 100644 --- a/app/paint/gimppaintcore-stroke.c +++ b/app/paint/gimppaintcore-stroke.c @@ -83,7 +83,7 @@ gimp_paint_core_stroke_vectors (GimpPaintCore *core, GimpPaintOptions *paint_options, GimpVectors *vectors) { - GimpStroke *stroke; + GList *stroke; GArray *coords = NULL; gboolean closed; @@ -97,8 +97,8 @@ gimp_paint_core_stroke_vectors (GimpPaintCore *core, */ for (stroke = vectors->strokes; stroke; stroke = stroke->next) { - coords = gimp_stroke_interpolate (stroke, 1.0, &closed); - + coords = gimp_stroke_interpolate (GIMP_STROKE (stroke->data), + 1.0, &closed); if (coords) break; } @@ -152,8 +152,8 @@ gimp_paint_core_stroke_vectors (GimpPaintCore *core, /* see above */ for ( ; stroke; stroke = stroke->next) { - coords = gimp_stroke_interpolate (stroke, 1.0, &closed); - + coords = gimp_stroke_interpolate (GIMP_STROKE (stroke), + 1.0, &closed); if (coords) break; } diff --git a/app/tools/gimpvectortool.c b/app/tools/gimpvectortool.c index 71d81de200..e3f24ebf51 100644 --- a/app/tools/gimpvectortool.c +++ b/app/tools/gimpvectortool.c @@ -2,7 +2,7 @@ * Copyright (C) 1995 Spencer Kimball and Peter Mattis * * Vector tool - * Copyright (C) 1999 Sven Neumann + * Copyright (C) 2002 Simon Budig * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -51,15 +51,12 @@ #define TARGET 9 -#define ARC_RADIUS 30 -#define STATUSBAR_SIZE 128 /* local function prototypes */ static void gimp_vector_tool_class_init (GimpVectorToolClass *klass); static void gimp_vector_tool_init (GimpVectorTool *tool); -static void gimp_vector_tool_finalize (GObject *object); static void gimp_vector_tool_control (GimpTool *tool, GimpToolAction action, @@ -84,6 +81,11 @@ static void gimp_vector_tool_cursor_update (GimpTool *tool, GdkModifierType state, GimpDisplay *gdisp); +static gboolean gimp_vector_tool_on_handle (GimpTool *tool, + GimpCoords *coords, + GimpAnchorType preferred, + GimpAnchor **ret_anchor); + static void gimp_vector_tool_draw (GimpDrawTool *draw_tool); @@ -148,8 +150,6 @@ gimp_vector_tool_class_init (GimpVectorToolClass *klass) parent_class = g_type_class_peek_parent (klass); - object_class->finalize = gimp_vector_tool_finalize; - tool_class->control = gimp_vector_tool_control; tool_class->button_press = gimp_vector_tool_button_press; tool_class->button_release = gimp_vector_tool_button_release; @@ -178,20 +178,6 @@ gimp_vector_tool_init (GimpVectorTool *vector_tool) vector_tool->active_anchors = NULL; } -static void -gimp_vector_tool_finalize (GObject *object) -{ - GimpVectorTool *vector_tool = GIMP_VECTOR_TOOL (object); - - if (vector_tool->vectors) - { - g_signal_handlers_disconnect_by_func (vector_tool->vectors, - gimp_vector_tool_clear_vectors, - vector_tool); - } - - G_OBJECT_CLASS (parent_class)->finalize (object); -} static void gimp_vector_tool_control (GimpTool *tool, @@ -213,6 +199,7 @@ gimp_vector_tool_control (GimpTool *tool, case HALT: /* gimp_tool_pop_status (tool); */ gimp_tool_control_halt (tool->control); + gimp_vector_tool_clear_vectors (vector_tool); break; default: @@ -297,6 +284,10 @@ gimp_vector_tool_button_press (GimpTool *tool, gimp_draw_tool_resume (GIMP_DRAW_TOOL (vector_tool)); } + else if (vector_tool->vectors) /* not on an anchor */ + { + vector_tool->function = VECTORS_ADDING; + } } if (!vector_tool->vectors || vector_tool->function == VECTORS_CREATING) @@ -316,6 +307,7 @@ gimp_vector_tool_button_press (GimpTool *tool, gimp_image_add_vectors (gdisp->gimage, vectors, -1); vector_tool->vectors = vectors; + g_object_ref (G_OBJECT (vectors)); g_signal_connect_object (vectors, "removed", G_CALLBACK (gimp_vector_tool_clear_vectors), @@ -399,6 +391,7 @@ gimp_vector_tool_button_release (GimpTool *tool, } + static void gimp_vector_tool_motion (GimpTool *tool, GimpCoords *coords, @@ -432,6 +425,67 @@ gimp_vector_tool_motion (GimpTool *tool, gimp_draw_tool_resume (GIMP_DRAW_TOOL (vector_tool)); } + +static gboolean gimp_vector_tool_on_handle (GimpTool *tool, + GimpCoords *coords, + GimpAnchorType preferred, + GimpAnchor **ret_anchor) +{ + GimpVectorTool *vector_tool; + GimpStroke *stroke = NULL; + GimpAnchor *anchor = NULL, *pref_anchor = NULL; + GList *list, *anchor_list = NULL; + gdouble dx, dy, pref_mindist= -1, mindist = -1; + + vector_tool = GIMP_VECTOR_TOOL (tool); + + if (!vector_tool->vectors) + { + if (ret_anchor) + *ret_anchor = NULL; + return FALSE; + } + + while ((stroke = gimp_vectors_stroke_get_next (vector_tool->vectors, stroke)) + != NULL) + { + list = gimp_stroke_get_draw_anchors (stroke); + anchor_list = g_list_concat (anchor_list, list); + + list = gimp_stroke_get_draw_controls (stroke); + anchor_list = g_list_concat (anchor_list, list); + } + + while (anchor_list) + { + dx = coords->x - ((GimpAnchor *) anchor_list->data)->position.x; + dy = coords->y - ((GimpAnchor *) anchor_list->data)->position.y; + if (mindist < 0 || mindist > dx * dx + dy * dy) + { + mindist = dx * dx + dy * dy; + anchor = (GimpAnchor *) anchor_list->data; + } + if ((pref_mindist < 0 || pref_mindist > dx * dx + dy * dy) && + ((GimpAnchor *) anchor_list->data)->type == preferred) + { + pref_mindist = dx * dx + dy * dy; + pref_anchor = (GimpAnchor *) anchor_list->data; + } + anchor_list = anchor_list->next; + } + + g_list_free (anchor_list); + + if (pref_anchor) + anchor = pref_anchor; + + if (ret_anchor) + *ret_anchor = anchor; + + return (anchor != NULL); +} + + static void gimp_vector_tool_cursor_update (GimpTool *tool, GimpCoords *coords, @@ -473,6 +527,7 @@ gimp_vector_tool_cursor_update (GimpTool *tool, GIMP_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, gdisp); } + static void gimp_vector_tool_draw (GimpDrawTool *draw_tool) { @@ -608,6 +663,7 @@ gimp_vector_tool_set_vectors (GimpVectorTool *vector_tool, g_signal_handlers_disconnect_by_func (vector_tool->vectors, gimp_vector_tool_clear_vectors, vector_tool); + g_object_unref (G_OBJECT (vector_tool->vectors)); } vector_tool->vectors = vectors; @@ -618,6 +674,7 @@ gimp_vector_tool_set_vectors (GimpVectorTool *vector_tool, if (vector_tool->vectors) { + g_object_ref (G_OBJECT (vector_tool->vectors)); g_signal_connect_object (vectors, "removed", G_CALLBACK (gimp_vector_tool_clear_vectors), vector_tool, diff --git a/app/vectors/gimpstroke.c b/app/vectors/gimpstroke.c index 2640ce83d0..986aa09df0 100644 --- a/app/vectors/gimpstroke.c +++ b/app/vectors/gimpstroke.c @@ -50,7 +50,7 @@ static void gimp_stroke_real_anchor_move_absolute (GimpStroke *stroke, GimpAnchor *anchor, const GimpCoords *deltacoord, const GimpAnchorFeatureType feature); - +static GimpStroke * gimp_stroke_real_duplicate (const GimpStroke *stroke); /* private variables */ @@ -118,6 +118,7 @@ gimp_stroke_class_init (GimpStrokeClass *klass) klass->temp_anchor_set = NULL; klass->temp_anchor_fix = NULL; + klass->duplicate = gimp_stroke_real_duplicate; klass->make_bezier = NULL; klass->get_draw_anchors = NULL; @@ -128,8 +129,8 @@ gimp_stroke_class_init (GimpStrokeClass *klass) static void gimp_stroke_init (GimpStroke *stroke) { - stroke->anchors = NULL; - stroke->next = NULL; + stroke->anchors = NULL; + stroke->temp_anchor = NULL; }; static void @@ -193,6 +194,8 @@ gimp_stroke_real_anchor_get (const GimpStroke *stroke, list = list->next; } + g_list_free (list); + list = gimp_stroke_get_draw_anchors (stroke); while (list) @@ -207,6 +210,8 @@ gimp_stroke_real_anchor_get (const GimpStroke *stroke, list = list->next; } + g_list_free (list); + return anchor; } @@ -500,6 +505,56 @@ gimp_stroke_temp_anchor_fix (GimpStroke *stroke) } +GimpStroke * +gimp_stroke_duplicate (const GimpStroke *stroke) +{ + g_return_val_if_fail (GIMP_IS_STROKE (stroke), NULL); + + return (GIMP_STROKE_GET_CLASS (stroke))->duplicate (stroke); +} + + +GimpStroke * +gimp_stroke_real_duplicate (const GimpStroke *stroke) +{ + GimpStroke *new_stroke; + GimpObject *new_gimpobject; + GList *anchorlist; + GimpAnchor *new_anchor; + GType stroke_type = G_OBJECT_TYPE (stroke); + + new_stroke = g_object_new (stroke_type, NULL); + new_gimpobject = GIMP_OBJECT (new_stroke); + + gimp_object_set_name (new_gimpobject, GIMP_OBJECT (stroke)->name); + + anchorlist = g_list_copy (stroke->anchors); + + new_stroke->anchors = anchorlist; + + while (anchorlist) + { + new_anchor = g_new0 (GimpAnchor, 1); + *new_anchor = *((GimpAnchor *) (anchorlist->data)); + + anchorlist->data = (gpointer) new_anchor; + anchorlist = g_list_next (anchorlist); + } + + if (stroke->temp_anchor) + { + new_stroke->temp_anchor = g_new0 (GimpAnchor, 1); + *(new_stroke->temp_anchor) = *(stroke->temp_anchor); + } + else + { + new_stroke->temp_anchor = NULL; + } + + return new_stroke; +} + + GimpStroke * gimp_stroke_make_bezier (const GimpStroke *stroke) { diff --git a/app/vectors/gimpstroke.h b/app/vectors/gimpstroke.h index 15710ffc57..1648a3e7a1 100644 --- a/app/vectors/gimpstroke.h +++ b/app/vectors/gimpstroke.h @@ -36,13 +36,11 @@ struct _GimpStroke { - GimpObject parent_instance; - - GList *anchors; - - GimpStroke *next; - - GimpAnchor *temp_anchor; + GimpObject parent_instance; + + GList * anchors; + + GimpAnchor * temp_anchor; /* Stuff missing? */ }; @@ -101,9 +99,10 @@ struct _GimpStrokeClass gboolean (* temp_anchor_fix) (GimpStroke *stroke); + GimpStroke * (* duplicate) (const GimpStroke *stroke); + GimpStroke * (* make_bezier) (const GimpStroke *stroke); - GList * (* get_draw_anchors) (const GimpStroke *stroke); GList * (* get_draw_controls) (const GimpStroke *stroke); @@ -176,17 +175,19 @@ GimpAnchor * gimp_stroke_temp_anchor_set (GimpStroke *stroke, gboolean gimp_stroke_temp_anchor_fix (GimpStroke *stroke); +GimpStroke * gimp_stroke_duplicate (const GimpStroke *stroke); + /* usually overloaded */ /* creates a bezier approximation. */ -GimpStroke * gimp_stroke_make_bezier (const GimpStroke *stroke); +GimpStroke * gimp_stroke_make_bezier (const GimpStroke *stroke); -GList * gimp_stroke_get_draw_anchors (const GimpStroke *stroke); - -GList * gimp_stroke_get_draw_controls (const GimpStroke *stroke); - -GArray * gimp_stroke_get_draw_lines (const GimpStroke *stroke); +GList * gimp_stroke_get_draw_anchors (const GimpStroke *stroke); + +GList * gimp_stroke_get_draw_controls (const GimpStroke *stroke); + +GArray * gimp_stroke_get_draw_lines (const GimpStroke *stroke); #endif /* __GIMP_STROKE_H__ */ diff --git a/app/vectors/gimpvectors.c b/app/vectors/gimpvectors.c index 10a4f09211..9c64fd13d4 100644 --- a/app/vectors/gimpvectors.c +++ b/app/vectors/gimpvectors.c @@ -80,6 +80,7 @@ gimp_vectors_get_type (void) return vectors_type; } + static void gimp_vectors_class_init (GimpVectorsClass *klass) { @@ -121,12 +122,14 @@ gimp_vectors_class_init (GimpVectorsClass *klass) klass->make_bezier = NULL; } + static void gimp_vectors_init (GimpVectors *vectors) { vectors->strokes = NULL; }; + static void gimp_vectors_finalize (GObject *object) { @@ -137,21 +140,24 @@ gimp_vectors_finalize (GObject *object) G_OBJECT_CLASS (parent_class)->finalize (object); } + static gsize gimp_vectors_get_memsize (GimpObject *object) { GimpVectors *vectors; - GimpStroke *stroke; + GList *stroke; gsize memsize = 0; vectors = GIMP_VECTORS (object); for (stroke = vectors->strokes; stroke; stroke = stroke->next) - memsize += gimp_object_get_memsize (GIMP_OBJECT (stroke)); + memsize += gimp_object_get_memsize (GIMP_OBJECT (stroke->data)) + + sizeof (GList); return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object); } + static GimpItem * gimp_vectors_duplicate (GimpItem *item, GType new_type, @@ -195,16 +201,25 @@ gimp_vectors_new (GimpImage *gimage, return vectors; } + void gimp_vectors_copy_strokes (const GimpVectors *src_vectors, GimpVectors *dest_vectors) { + GList *current_lstroke; + g_return_if_fail (GIMP_IS_VECTORS (src_vectors)); g_return_if_fail (GIMP_IS_VECTORS (dest_vectors)); + g_return_if_fail (dest_vectors->strokes == NULL); -#ifdef __GNUC__ -#warning FIXME: implement gimp_vectors_copy_strokes() -#endif + dest_vectors->strokes = g_list_copy (src_vectors->strokes); + current_lstroke = dest_vectors->strokes; + + while (current_lstroke) + { + current_lstroke->data = gimp_stroke_duplicate (current_lstroke->data); + current_lstroke = g_list_next (current_lstroke); + } } @@ -226,14 +241,14 @@ gimp_vectors_anchor_get (const GimpVectors *vectors, else { gdouble dx, dy, mindist; - GimpStroke *stroke; + GList *stroke; GimpAnchor *anchor = NULL, *minanchor = NULL; mindist = -1; - for (stroke = vectors->strokes; stroke; stroke = stroke->next) + for (stroke = vectors->strokes; stroke; stroke = g_list_next (stroke)) { - anchor = gimp_stroke_anchor_get (stroke, coord); + anchor = gimp_stroke_anchor_get (GIMP_STROKE (stroke->data), coord); if (anchor) { dx = coord->x - anchor->position.x; @@ -243,7 +258,7 @@ gimp_vectors_anchor_get (const GimpVectors *vectors, mindist = dx * dx + dy * dy; minanchor = anchor; if (ret_stroke) - *ret_stroke = stroke; + *ret_stroke = stroke->data; } } } @@ -271,8 +286,7 @@ gimp_vectors_stroke_add (GimpVectors *vectors, } else { - stroke->next = vectors->strokes; - vectors->strokes = stroke; + vectors->strokes = g_list_prepend (vectors->strokes, stroke); g_object_ref (stroke); } } @@ -293,16 +307,16 @@ gimp_vectors_stroke_get (const GimpVectors *vectors, else { gdouble dx, dy, mindist; - GimpStroke *stroke; + GList *stroke; GimpStroke *minstroke = NULL; GimpAnchor *anchor = NULL; mindist = -1; - stroke = GIMP_STROKE (vectors->strokes); + stroke = vectors->strokes; while (stroke) { - anchor = gimp_stroke_anchor_get (stroke, coord); + anchor = gimp_stroke_anchor_get (stroke->data, coord); if (anchor) { dx = coord->x - anchor->position.x; @@ -310,10 +324,10 @@ gimp_vectors_stroke_get (const GimpVectors *vectors, if (mindist > dx * dx + dy * dy || mindist < 0) { mindist = dx * dx + dy * dy; - minstroke = stroke; + minstroke = GIMP_STROKE (stroke->data); } } - stroke = stroke->next; + stroke = g_list_next (stroke); } return minstroke; } @@ -338,12 +352,14 @@ gimp_vectors_stroke_get_next (const GimpVectors *vectors, { if (!prev) { - return vectors->strokes; + return vectors->strokes->data; } else { - g_return_val_if_fail (GIMP_IS_STROKE (prev), NULL); - return prev->next; + GList *stroke; + stroke = g_list_find (vectors->strokes, prev); + g_return_val_if_fail (stroke != NULL, NULL); + return stroke->next ? GIMP_STROKE (stroke->next->data) : NULL; } } diff --git a/app/vectors/gimpvectors.h b/app/vectors/gimpvectors.h index 7d58a44c8c..746e6ef02a 100644 --- a/app/vectors/gimpvectors.h +++ b/app/vectors/gimpvectors.h @@ -41,7 +41,7 @@ struct _GimpVectors gboolean locked; /* transformation locking */ /* Should the following be a GList of GimpStrokes? */ - GimpStroke * strokes; /* The first stroke */ + GList * strokes; /* The List of GimpStrokes */ /* Stuff missing */ };