diff --git a/ChangeLog b/ChangeLog index 2ffe26f0e5..0e35e24400 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2002-12-29 Simon Budig + + * app/core/gimpimage-mask-select.c + * app/paint/gimppaintcore-stroke.c + * app/tools/gimpvectortool.c + * app/vectors/gimpbezierstroke.[ch] + * app/vectors/gimpstroke.[ch] + * app/vectors/gimpvectors-preview.c: some more stuff for the + vectors tool: bezier interpolation is available, we have preview + generation. Usage is still weird. + 2002-12-28 Simon Budig * app/vectors/gimpbezierstroke.c: untested and unused stuff diff --git a/app/core/gimpchannel-select.c b/app/core/gimpchannel-select.c index 4bf98aec6f..45b6be5495 100644 --- a/app/core/gimpchannel-select.c +++ b/app/core/gimpchannel-select.c @@ -189,8 +189,7 @@ gimp_image_mask_select_vectors (GimpImage *gimage, gdouble feather_radius_y) { GimpStroke *stroke; - GimpCoords *coords = NULL; - gint n_coords; + GArray *coords = NULL; gboolean closed; g_return_if_fail (GIMP_IS_IMAGE (gimage)); @@ -200,9 +199,7 @@ gimp_image_mask_select_vectors (GimpImage *gimage, */ for (stroke = vectors->strokes; stroke; stroke = stroke->next) { - coords = gimp_stroke_interpolate (stroke, 1.0, - &n_coords, - &closed); + coords = gimp_stroke_interpolate (stroke, 1.0, &closed); if (coords) break; @@ -213,18 +210,16 @@ gimp_image_mask_select_vectors (GimpImage *gimage, GimpVector2 *points; gint i; - points = g_new0 (GimpVector2, n_coords); + points = g_new0 (GimpVector2, coords->len); - for (i = 0; i < n_coords; i++) + for (i = 0; i < coords->len; i++) { - points[i].x = coords[i].x; - points[i].y = coords[i].y; + points[i].x = g_array_index (coords, GimpCoords, i).x; + points[i].y = g_array_index (coords, GimpCoords, i).y; } - g_free (coords); - gimp_image_mask_select_polygon (GIMP_ITEM (vectors)->gimage, - n_coords, + coords->len, points, op, antialias, @@ -232,6 +227,7 @@ gimp_image_mask_select_vectors (GimpImage *gimage, feather_radius_x, feather_radius_y); + g_array_free (coords, TRUE); g_free (points); } } diff --git a/app/core/gimpimage-mask-select.c b/app/core/gimpimage-mask-select.c index 4bf98aec6f..45b6be5495 100644 --- a/app/core/gimpimage-mask-select.c +++ b/app/core/gimpimage-mask-select.c @@ -189,8 +189,7 @@ gimp_image_mask_select_vectors (GimpImage *gimage, gdouble feather_radius_y) { GimpStroke *stroke; - GimpCoords *coords = NULL; - gint n_coords; + GArray *coords = NULL; gboolean closed; g_return_if_fail (GIMP_IS_IMAGE (gimage)); @@ -200,9 +199,7 @@ gimp_image_mask_select_vectors (GimpImage *gimage, */ for (stroke = vectors->strokes; stroke; stroke = stroke->next) { - coords = gimp_stroke_interpolate (stroke, 1.0, - &n_coords, - &closed); + coords = gimp_stroke_interpolate (stroke, 1.0, &closed); if (coords) break; @@ -213,18 +210,16 @@ gimp_image_mask_select_vectors (GimpImage *gimage, GimpVector2 *points; gint i; - points = g_new0 (GimpVector2, n_coords); + points = g_new0 (GimpVector2, coords->len); - for (i = 0; i < n_coords; i++) + for (i = 0; i < coords->len; i++) { - points[i].x = coords[i].x; - points[i].y = coords[i].y; + points[i].x = g_array_index (coords, GimpCoords, i).x; + points[i].y = g_array_index (coords, GimpCoords, i).y; } - g_free (coords); - gimp_image_mask_select_polygon (GIMP_ITEM (vectors)->gimage, - n_coords, + coords->len, points, op, antialias, @@ -232,6 +227,7 @@ gimp_image_mask_select_vectors (GimpImage *gimage, feather_radius_x, feather_radius_y); + g_array_free (coords, TRUE); g_free (points); } } diff --git a/app/paint/gimppaintcore-stroke.c b/app/paint/gimppaintcore-stroke.c index 6450d4edeb..4aace19948 100644 --- a/app/paint/gimppaintcore-stroke.c +++ b/app/paint/gimppaintcore-stroke.c @@ -83,8 +83,7 @@ gimp_paint_core_stroke_vectors (GimpPaintCore *core, GimpVectors *vectors) { GimpStroke *stroke; - GimpCoords *coords = NULL; - gint n_coords; + GArray *coords = NULL; gboolean closed; g_return_val_if_fail (GIMP_IS_PAINT_CORE (core), FALSE); @@ -97,9 +96,7 @@ gimp_paint_core_stroke_vectors (GimpPaintCore *core, */ for (stroke = vectors->strokes; stroke; stroke = stroke->next) { - coords = gimp_stroke_interpolate (stroke, 1.0, - &n_coords, - &closed); + coords = gimp_stroke_interpolate (stroke, 1.0, &closed); if (coords) break; @@ -108,9 +105,10 @@ gimp_paint_core_stroke_vectors (GimpPaintCore *core, if (! coords) return FALSE; - if (! gimp_paint_core_start (core, drawable, paint_options, &coords[0])) + if (! gimp_paint_core_start (core, drawable, paint_options, + &(g_array_index (coords, GimpCoords, 0)))) { - g_free (coords); + g_array_free (coords, TRUE); return FALSE; } @@ -120,14 +118,14 @@ gimp_paint_core_stroke_vectors (GimpPaintCore *core, { gint i; - core->start_coords = coords[0]; - core->last_coords = coords[0]; + core->start_coords = g_array_index (coords, GimpCoords, 0); + core->last_coords = g_array_index (coords, GimpCoords, 0); gimp_paint_core_paint (core, drawable, paint_options, MOTION_PAINT); - for (i = 1; i < n_coords; i++) + for (i = 1; i < coords->len; i++) { - core->cur_coords = coords[i]; + core->cur_coords = g_array_index (coords, GimpCoords, i); gimp_paint_core_interpolate (core, drawable, paint_options); @@ -136,14 +134,14 @@ gimp_paint_core_stroke_vectors (GimpPaintCore *core, if (closed) { - core->cur_coords = coords[0]; + core->cur_coords = g_array_index (coords, GimpCoords, 0); gimp_paint_core_interpolate (core, drawable, paint_options); core->last_coords = core->cur_coords; } - g_free (coords); + g_array_free (coords, TRUE); coords = NULL; if (stroke->next) @@ -153,9 +151,7 @@ gimp_paint_core_stroke_vectors (GimpPaintCore *core, /* see above */ for ( ; stroke; stroke = stroke->next) { - coords = gimp_stroke_interpolate (stroke, 1.0, - &n_coords, - &closed); + coords = gimp_stroke_interpolate (stroke, 1.0, &closed); if (coords) break; diff --git a/app/tools/gimpvectortool.c b/app/tools/gimpvectortool.c index 83b178d633..698b87e363 100644 --- a/app/tools/gimpvectortool.c +++ b/app/tools/gimpvectortool.c @@ -232,10 +232,10 @@ gimp_vector_tool_control (GimpTool *tool, static void gimp_vector_tool_button_press (GimpTool *tool, - GimpCoords *coords, - guint32 time, - GdkModifierType state, - GimpDisplay *gdisp) + GimpCoords *coords, + guint32 time, + GdkModifierType state, + GimpDisplay *gdisp) { GimpVectorTool *vector_tool; VectorOptions *options; @@ -342,10 +342,16 @@ gimp_vector_tool_button_release (GimpTool *tool, GimpDisplay *gdisp) { GimpVectorTool *vector_tool; + GimpViewable *viewable; vector_tool = GIMP_VECTOR_TOOL (tool); vector_tool->function = VECTORS_ADDING; + + /* THIS DOES NOT BELONG HERE! */ + viewable = GIMP_VIEWABLE (vector_tool->vectors); + gimp_viewable_invalidate_preview (viewable); + } static void @@ -430,8 +436,7 @@ gimp_vector_tool_draw (GimpDrawTool *draw_tool) GimpAnchor *cur_anchor = NULL; GimpStroke *cur_stroke = NULL; GimpVectors *vectors; - GimpCoords *coords; - gint num_coords; + GArray *coords; gboolean closed; vector_tool = GIMP_VECTOR_TOOL (draw_tool); @@ -453,10 +458,16 @@ gimp_vector_tool_draw (GimpDrawTool *draw_tool) GTK_ANCHOR_CENTER, FALSE); } - coords = gimp_stroke_interpolate (cur_stroke, 1.0, &num_coords, &closed); - gimp_draw_tool_draw_strokes (draw_tool, coords, num_coords, FALSE, FALSE); + coords = gimp_stroke_interpolate (cur_stroke, 1.0, &closed); - g_free (coords); + g_printerr ("Got %d coords from gimp_stroke_interpolate\n", coords->len); + + if (coords->len) + gimp_draw_tool_draw_strokes (draw_tool, + & (g_array_index (coords, GimpCoords, 0)), + coords->len, FALSE, FALSE); + + g_array_free (coords, TRUE); } } diff --git a/app/vectors/gimpbezierstroke.c b/app/vectors/gimpbezierstroke.c index 0210333f32..e725f07b11 100644 --- a/app/vectors/gimpbezierstroke.c +++ b/app/vectors/gimpbezierstroke.c @@ -50,8 +50,7 @@ static void gimp_bezier_coords_average (GimpCoords *a, static void gimp_bezier_coords_subdivide (GimpCoords *beziercoords, const gdouble precision, - gint *ret_ncoords, - GimpCoords *ret_coords); + GArray **ret_coords); GType gimp_bezier_stroke_get_type (void) @@ -128,6 +127,9 @@ gimp_bezier_stroke_new (const GimpCoords *start) anchor->position.x = start->x; anchor->position.y = start->y; anchor->position.pressure = 1; + anchor->position.xtilt = 0.5; + anchor->position.ytilt = 0.5; + anchor->position.wheel = 0.5; g_printerr ("Adding at %f, %f\n", start->x, start->y); @@ -161,9 +163,7 @@ gimp_bezier_stroke_new_from_coords (const GimpCoords *coords, &(coords[count]), last_anchor); } - } - return stroke; } @@ -215,9 +215,13 @@ gimp_bezier_stroke_extend (GimpBezierStroke *bezier_stroke, anchor->position.ytilt = 0.5; anchor->position.wheel = 0.5; - anchor->type = 0; /* FIXME */ + /* FIXME */ + if (((GimpAnchor *) listneighbor->data)->type == 0) + anchor->type = 1; + else + anchor->type = 0; - g_printerr ("Extending at %f, %f\n", coords->x, coords->y); + g_printerr ("Extending at %f, %f, type %d\n", coords->x, coords->y, anchor->type); } else anchor = NULL; @@ -232,42 +236,42 @@ gimp_bezier_stroke_extend (GimpBezierStroke *bezier_stroke, } -GimpCoords * +GArray * gimp_bezier_stroke_interpolate (const GimpStroke *stroke, gdouble precision, - gint *ret_numcoords, gboolean *ret_closed) { - gint count, alloccount; - gint chunksize = 100; - GimpCoords *ret_coords; + GArray *ret_coords; GimpAnchor *anchor; GList *anchorlist; + GimpCoords segmentcoords[4]; + gint count; g_return_val_if_fail (GIMP_IS_BEZIER_STROKE (stroke), NULL); - g_return_val_if_fail (ret_numcoords != NULL, NULL); g_return_val_if_fail (ret_closed != NULL, NULL); + ret_coords = g_array_new (FALSE, FALSE, sizeof (GimpCoords)); + count = 0; - alloccount = 0; - ret_coords = NULL; for (anchorlist = stroke->anchors; anchorlist; anchorlist = g_list_next (anchorlist)) { - if (count >= alloccount) - { - ret_coords = g_renew (GimpCoords, ret_coords, alloccount + chunksize); - alloccount += chunksize; - } - anchor = anchorlist->data; - ret_coords[count] = anchor->position; + segmentcoords[count] = anchor->position; count++; + + if (count == 4) + { + gimp_bezier_coords_subdivide (segmentcoords, precision, &ret_coords); + segmentcoords[0] = segmentcoords[3]; + count = 1; + } } - *ret_numcoords = count; + /* ret_coords = g_array_append_val (ret_coords, anchor->position); */ + *ret_closed = FALSE; return ret_coords; @@ -288,11 +292,11 @@ gimp_bezier_coords_mix (gdouble amul, if (b) { ret_val->x = amul * a->x + bmul * b->x ; - ret_val->y = amul * a->y + bmul * b->x ; - ret_val->pressure = amul * a->pressure + bmul * b->x ; - ret_val->xtilt = amul * a->xtilt + bmul * b->x ; - ret_val->ytilt = amul * a->ytilt + bmul * b->x ; - ret_val->wheel = amul * a->wheel + bmul * b->x ; + ret_val->y = amul * a->y + bmul * b->y ; + ret_val->pressure = amul * a->pressure + bmul * b->pressure ; + ret_val->xtilt = amul * a->xtilt + bmul * b->xtilt ; + ret_val->ytilt = amul * a->ytilt + bmul * b->ytilt ; + ret_val->wheel = amul * a->wheel + bmul * b->wheel ; } else { @@ -414,6 +418,8 @@ gimp_bezier_coords_is_straight (GimpCoords *beziercoords) } else { + /* Tangents are too big for the small baseline */ + /* g_printerr ("Zu grosse Tangenten bei zu kleiner Basislinie\n"); */ return 0; } } @@ -431,14 +437,22 @@ gimp_bezier_coords_is_straight (GimpCoords *beziercoords) s2 = gimp_bezier_coords_scalarprod (&line, &tan2) / l2; if (s1 < 0 || s1 > 1 || s2 < 0 || s2 > 1 || s2 < s1) - return 0; + { + /* The tangents get projected outside the baseline */ + /* g_printerr ("Tangenten projezieren sich ausserhalb der Basisline\n"); */ + return 0; + } gimp_bezier_coords_mix (1.0, &tan1, - s1, &line, &d1); gimp_bezier_coords_mix (1.0, &tan2, - s2, &line, &d2); if ((gimp_bezier_coords_length2 (&d1) > DETAIL * DETAIL) || (gimp_bezier_coords_length2 (&d2) > DETAIL * DETAIL)) - return 0; + { + /* The control points are too far away from the baseline */ + /* g_printerr ("Zu grosser Abstand zur Basislinie\n"); */ + return 0; + } return 1; } @@ -446,10 +460,10 @@ gimp_bezier_coords_is_straight (GimpCoords *beziercoords) static void -gimp_bezier_coords_subdivide (GimpCoords *beziercoords, - const gdouble precision, - gint *ret_ncoords, - GimpCoords *ret_coords) +gimp_bezier_coords_subdivide2 (GimpCoords *beziercoords, + const gdouble precision, + GArray **ret_coords, + gint depth) { /* * beziercoords has to contain four GimpCoords with the four control points @@ -457,11 +471,12 @@ gimp_bezier_coords_subdivide (GimpCoords *beziercoords, */ GimpCoords subdivided[8]; - gint i; subdivided[0] = beziercoords[0]; subdivided[6] = beziercoords[3]; + if (!depth) g_printerr ("Hit rekursion depth limit!\n"); + gimp_bezier_coords_average (&(beziercoords[0]), &(beziercoords[1]), &(subdivided[1])); @@ -490,40 +505,37 @@ gimp_bezier_coords_subdivide (GimpCoords *beziercoords, * if the stroke is sufficiently close to a straight line. */ - if (gimp_bezier_coords_is_straight (&(subdivided[0])) /* stroke 1 */) + if (!depth || + gimp_bezier_coords_is_straight (&(subdivided[0]))) /* 1st half */ { - for (i=0; i < 3; i++) - { - /* if necessary, allocate new memory for return coords */ - ret_coords[*ret_ncoords] = subdivided[i]; - (*ret_ncoords)++; - } + *ret_coords = g_array_append_vals (*ret_coords, &(subdivided[0]), 3); } else { - gimp_bezier_coords_subdivide (&(subdivided[0]), precision, - ret_ncoords, ret_coords); + gimp_bezier_coords_subdivide2 (&(subdivided[0]), precision, + ret_coords, depth-1); } - if (gimp_bezier_coords_is_straight (&(subdivided[3])) /* stroke 1 */) + if (!depth || + gimp_bezier_coords_is_straight (&(subdivided[3]))) /* 2nd half */ { - for (i=0; i < 3; i++) - { - /* if necessary, allocate new memory for return coords */ - ret_coords[*ret_ncoords] = subdivided[i+3]; - (*ret_ncoords)++; - } + *ret_coords = g_array_append_vals (*ret_coords, &(subdivided[3]), 3); } else { - gimp_bezier_coords_subdivide (&(subdivided[3]), precision, - ret_ncoords, ret_coords); + gimp_bezier_coords_subdivide2 (&(subdivided[3]), precision, + ret_coords, depth-1); } - if ( /* last iteration */ 0) - { - /* if necessary, allocate new memory for return coords */ - ret_coords[*ret_ncoords] = subdivided[6]; - (*ret_ncoords)++; - } + /* g_printerr ("gimp_bezier_coords_subdivide end: %d entries\n", (*ret_coords)->len); */ } + + +static void +gimp_bezier_coords_subdivide (GimpCoords *beziercoords, + const gdouble precision, + GArray **ret_coords) +{ + gimp_bezier_coords_subdivide2 (beziercoords, precision, ret_coords, 10); +} + diff --git a/app/vectors/gimpbezierstroke.h b/app/vectors/gimpbezierstroke.h index 7641d41891..c7fe491814 100644 --- a/app/vectors/gimpbezierstroke.h +++ b/app/vectors/gimpbezierstroke.h @@ -65,9 +65,8 @@ GimpAnchor * gimp_bezier_stroke_extend (GimpBezierStroke *bezier_stroke, const GimpCoords *coords, GimpAnchor *neighbor); -GimpCoords * gimp_bezier_stroke_interpolate (const GimpStroke *stroke, +GArray * gimp_bezier_stroke_interpolate (const GimpStroke *stroke, const gdouble precision, - gint *ret_numcoords, gboolean *ret_closed); #endif /* __GIMP_BEZIER_STROKE_H__ */ diff --git a/app/vectors/gimpstroke.c b/app/vectors/gimpstroke.c index d04523155c..418285b31a 100644 --- a/app/vectors/gimpstroke.c +++ b/app/vectors/gimpstroke.c @@ -336,10 +336,9 @@ gimp_stroke_get_distance (const GimpStroke *stroke, } -GimpCoords * +GArray * gimp_stroke_interpolate (const GimpStroke *stroke, const gdouble precision, - gint *ret_numcoords, gboolean *ret_closed) { GimpStrokeClass *stroke_class; @@ -350,7 +349,7 @@ gimp_stroke_interpolate (const GimpStroke *stroke, if (stroke_class->interpolate) return stroke_class->interpolate (stroke, precision, - ret_numcoords, ret_closed); + ret_closed); else g_printerr ("gimp_stroke_interpolate: default implementation\n"); diff --git a/app/vectors/gimpstroke.h b/app/vectors/gimpstroke.h index 660199f394..119caf4d00 100644 --- a/app/vectors/gimpstroke.h +++ b/app/vectors/gimpstroke.h @@ -78,9 +78,8 @@ struct _GimpStrokeClass gdouble (* get_distance) (const GimpStroke *stroke, const GimpCoords *coord); - GimpCoords * (* interpolate) (const GimpStroke *stroke, + GArray * (* interpolate) (const GimpStroke *stroke, const gdouble precision, - gint *ret_numcoords, gboolean *ret_closed); @@ -137,9 +136,8 @@ gdouble gimp_stroke_get_distance (const GimpStroke *stroke, const GimpCoords *coord); /* returns the number of valid coordinates */ -GimpCoords * gimp_stroke_interpolate (const GimpStroke *stroke, +GArray * gimp_stroke_interpolate (const GimpStroke *stroke, gdouble precision, - gint *ret_numcoords, gboolean *ret_closed); diff --git a/app/vectors/gimpvectors-preview.c b/app/vectors/gimpvectors-preview.c index 0fe4dc5381..d5fb7a767c 100644 --- a/app/vectors/gimpvectors-preview.c +++ b/app/vectors/gimpvectors-preview.c @@ -26,6 +26,8 @@ #include "base/temp-buf.h" +#include "core/gimpimage.h" +#include "gimpstroke.h" #include "gimpvectors.h" #include "gimpvectors-preview.h" @@ -38,12 +40,45 @@ gimp_vectors_get_new_preview (GimpViewable *viewable, gint height) { GimpVectors *vectors; + GimpItem *item; + GArray *coords; + GimpCoords point; + GimpStroke *cur_stroke = NULL; + gdouble xscale, yscale, xres, yres; + gint x, y; + guchar *data; + gboolean closed; + TempBuf *temp_buf; guchar white[1] = { 255 }; + gint i; vectors = GIMP_VECTORS (viewable); + item = GIMP_ITEM (viewable); + xscale = ((gdouble) width) / gimp_image_get_width (item->gimage); + yscale = ((gdouble) height) / gimp_image_get_height (item->gimage); + temp_buf = temp_buf_new (width, height, 1, 0, 0, white); + data = temp_buf_data (temp_buf); + + while ((cur_stroke = gimp_vectors_stroke_get_next (vectors, cur_stroke))) + { + coords = gimp_stroke_interpolate (cur_stroke, 1.0, &closed); + + for (i=0; i < coords->len; i++) + { + point = g_array_index (coords, GimpCoords, i); + + x = (gint) (point.x * xscale + 0.5); + y = (gint) (point.y * yscale + 0.5); + + if (x >= 0 && y >= 0 && x < width && y < height) + data[y * width + x] = 0; + } + + g_array_free (coords, TRUE); + } return temp_buf; }