app/core/gimpimage-mask-select.c app/paint/gimppaintcore-stroke.c

2002-12-29  Simon Budig  <simon@gimp.org>

        * 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.
This commit is contained in:
Simon Budig 2002-12-28 23:52:29 +00:00 committed by Simon Budig
parent 40fa262749
commit d3e9fc6405
10 changed files with 169 additions and 116 deletions

View File

@ -1,3 +1,14 @@
2002-12-29 Simon Budig <simon@gimp.org>
* 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 <simon@gimp.org>
* app/vectors/gimpbezierstroke.c: untested and unused stuff

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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__ */

View File

@ -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");

View File

@ -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);

View File

@ -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;
}