From 2212b94fff753e37e47b72785b32136a52bd35ae Mon Sep 17 00:00:00 2001 From: Sven Neumann Date: Sun, 3 Oct 1999 19:13:54 +0000 Subject: [PATCH] Some updates for the Path-Tool. Bye, Simon (using Svens account) --- ChangeLog | 29 ++++ Makefile.am | 4 + app/Makefile.am | 4 + app/path_bezier.c | 132 +++++++++++++++ app/path_bezier.h | 103 ++++++++++++ app/path_curves.c | 307 ++++++++++++++++++++++++++++++++++ app/path_curves.h | 201 +++++++++++++++++++++++ app/path_tool.c | 363 +++++++++++++++++++++++++++++++---------- app/path_tool.h | 4 +- app/path_toolP.h | 12 +- app/tools/path_tool.c | 363 +++++++++++++++++++++++++++++++---------- app/tools/path_tool.h | 4 +- app/tools/path_toolP.h | 12 +- 13 files changed, 1356 insertions(+), 182 deletions(-) create mode 100644 app/path_bezier.c create mode 100644 app/path_bezier.h create mode 100644 app/path_curves.c create mode 100644 app/path_curves.h diff --git a/ChangeLog b/ChangeLog index 804ebb020d..da5c32e451 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,32 @@ +1999-10-3 Simon Budig + + * app/path_tool.h + * app/path_tool.c + * app/path_toolP.h + * app/path_curves.h + * app/path_curves.c + * app/path_bezier.h + * app/path_bezer.c + + Lots of stuff for the bezier-tool which will be also used for the + interface for the intelligent scissors. I started to factor out the + formulas for the actual curve type, so it is some kind of independant. + To try this out simply change the "#if 0" in app/path_curve.c to + a "#if 1" to handle straight lines instead of strange beziers with + fixed handles :-) + The functions in app/path_curves.c implement some kind of + default-action, where useful. To implement a new curve-tzpe it + should be sufficient to overload the path_curve_get_point() + function. Of course, then the speed is not as performant... :-) + + The API for other types is not yet completely fixed, esp. Im not + clear about when to give a Tool* or PathTool* as a parameter. + But it shows the way, I want to implement this. In the next step + I'll fill the stubs in app/path_bezer.c. + + New handling functions: The Tool detects, when you are over an curve + and lets you split it there by shift clicking. + 1999-10-03 Sven Neumann * app/channel_ops.c: copy resolution and unit information when duplicating diff --git a/Makefile.am b/Makefile.am index 29582e6a07..271c1fce4f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -131,3 +131,7 @@ checkin: populate release: $(MAKE) dist distdir=$(PACKAGE)`date +"%y%m%d"` + path_bezier.c \ + path_bezier.h \ + path_curves.c \ + path_curves.h \ diff --git a/app/Makefile.am b/app/Makefile.am index 8bf685fa87..2e3f29f35c 100644 --- a/app/Makefile.am +++ b/app/Makefile.am @@ -327,6 +327,10 @@ gimp_SOURCES = \ parasitelist.h \ parasitelistF.h \ parasitelistP.h \ + path_bezier.c \ + path_bezier.h \ + path_curves.c \ + path_curves.h \ path_tool.c \ path_tool.h \ path_toolP.h \ diff --git a/app/path_bezier.c b/app/path_bezier.c new file mode 100644 index 0000000000..a6b015e2c6 --- /dev/null +++ b/app/path_bezier.c @@ -0,0 +1,132 @@ +/* The GIMP -- an image manipulation program + * + * This file Copyright (C) 1999 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "path_bezier.h" + +/* + * This function is to get a set of npoints different coordinates for + * the range from start to end (each in the range from 0 to 1 and + * start < end. + * returns the number of created coords. Make sure that the points- + * Array is allocated. + */ + +guint +path_bezier_get_points (PathTool *path_tool, + PathSegment *segment, + GdkPoint *points, + guint npoints, + gdouble start, + gdouble end) +{ + return 0; +} + +void +path_bezier_get_point (PathTool *path_tool, + PathSegment *segment, + gdouble position, + gdouble *x, + gdouble *y) +{ + return; +} + +void +path_bezier_draw_handles (Tool *tool, + PathSegment *segment) +{ + return; +} + +void +path_bezier_draw_segment (Tool *tool, + PathSegment *segment) +{ + return; +} + + +gdouble +path_bezier_on_segment (Tool *tool, + PathSegment *segment, + gint x, + gint y, + gint halfwidth, + gint *distance) +{ + return -1; +} + +void +path_bezier_drag_segment (PathTool *path_tool, + PathSegment *segment, + gdouble position, + gint x, + gint y) +{ + return; +} + +gboolean +path_bezier_on_handles (PathTool *path_tool, + PathSegment *segment, + gint x, + gint y, + gint halfwidth) +{ + return FALSE; +} + +void +path_bezier_drag_handles (PathTool *path_tool, + PathSegment *segment, + gint x, + gint y) +{ + return; +} + + +PathSegment * +path_bezier_insert_anchor (PathTool *path_tool, + PathSegment *segment, + gdouble position) +{ + return NULL; +} + +void +path_bezier_update_segment (PathTool *path_tool, + PathSegment *segment) +{ + return; +} + + +void +path_bezier_flip_segment (PathTool *path_tool, + PathSegment *segment) +{ + return; +} + + + + diff --git a/app/path_bezier.h b/app/path_bezier.h new file mode 100644 index 0000000000..cc37f61e92 --- /dev/null +++ b/app/path_bezier.h @@ -0,0 +1,103 @@ +/* The GIMP -- an image manipulation program + * + * This file Copyright (C) 1999 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * This function is to get a set of npoints different coordinates for + * the range from start to end (each in the range from 0 to 1 and + * start < end. + * returns the number of created coords. Make sure that the points- + * Array is allocated. + */ + +#ifndef __PATH_BEZIER_H__ +#define __PATH_BEZIER_H__ + +#include +#include + +#include "path_toolP.h" + +guint +path_bezier_get_points (PathTool *path_tool, + PathSegment *segment, + GdkPoint *points, + guint npoints, + gdouble start, + gdouble end); + +void +path_bezier_get_point (PathTool *path_tool, + PathSegment *segment, + gdouble position, + gdouble *x, + gdouble *y); + +void +path_bezier_draw_handles (Tool *tool, + PathSegment *segment); + +void +path_bezier_draw_segment (Tool *tool, + PathSegment *segment); + + +gdouble +path_bezier_on_segment (Tool *tool, + PathSegment *segment, + gint x, + gint y, + gint halfwidth, + gint *distance); + +void +path_bezier_drag_segment (PathTool *path_tool, + PathSegment *segment, + gdouble position, + gint x, + gint y); + +gboolean +path_bezier_on_handles (PathTool *path_tool, + PathSegment *segment, + gint x, + gint y, + gint halfwidth); + +void +path_bezier_drag_handles (PathTool *path_tool, + PathSegment *segment, + gint x, + gint y); + +PathSegment * +path_bezier_insert_anchor (PathTool *path_tool, + PathSegment *segment, + gdouble position); + +void +path_bezier_update_segment (PathTool *path_tool, + PathSegment *segment); + +void +path_bezier_flip_segment (PathTool *path_tool, + PathSegment *segment); + +#endif /* __PATH_BEZIER_H__ */ + + diff --git a/app/path_curves.c b/app/path_curves.c new file mode 100644 index 0000000000..9dc6632cc6 --- /dev/null +++ b/app/path_curves.c @@ -0,0 +1,307 @@ +/* The GIMP -- an image manipulation program + * + * This file Copyright (C) 1999 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include "path_curves.h" +#include "path_bezier.h" + +#ifdef PATH_TOOL_DEBUG +#include +#endif + +/* only here temporarily */ +PathSegment * path_split_segment (PathSegment *, gdouble); + +/* Here the different curves register their functions */ + +static CurveDescription CurveTypes[] = +{ + /* SEGMENT_LINE */ + { + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL + }, + + /* SEGMENT_BEZIER */ + { + path_bezier_get_points, + path_bezier_get_point, + path_bezier_draw_handles, + path_bezier_draw_segment, + path_bezier_on_segment, + path_bezier_drag_segment, + path_bezier_on_handles, + path_bezier_drag_handles, + path_bezier_insert_anchor, + path_bezier_update_segment, + path_bezier_flip_segment + } +}; + + +/* + * these functions implement the dispatching for the different + * curve-types. It implements default actions, which happen + * to work with straight lines. + */ + + +guint +path_curve_get_points (PathTool *path_tool, + PathSegment *segment, + GdkPoint *points, + guint npoints, + gdouble start, + gdouble end) +{ + gdouble pos, x, y; + gint index=0; + + if (segment && CurveTypes[segment->type].get_points) + return (* CurveTypes[segment->type].get_points) (path_tool, segment, points, npoints, start, end); + else { + if (npoints > 1 && segment && segment->next) { + for (pos = start; pos <= end; pos += (end - start) / (npoints -1)) { + path_curve_get_point (path_tool, segment, pos, &x, &y); + points[index].x = (guint) (x + 0.5); + points[index].y = (guint) (y + 0.5); + index++; + } + return index; + } else + return 0; + } +} + + +void +path_curve_get_point (PathTool *path_tool, + PathSegment *segment, + gdouble position, + gdouble *x, + gdouble *y) +{ + if (segment && CurveTypes[segment->type].get_point) + (* CurveTypes[segment->type].get_point) (path_tool, segment, position, x, y); + else { + if (segment && segment->next) { +#if 0 + *x = segment->x + (segment->next->x - segment->x) * position; + *y = segment->y + (segment->next->y - segment->y) * position; +#else + /* Only here for debugging purposes: A bezier curve fith fixed tangents */ + *x = (1-position)*(1-position)*(1-position) * segment->x + + 3 * position *(1-position)*(1-position) * (segment->x - 60) + + 3 * position * position *(1-position) * (segment->next->x + 60) + + position * position * position * (segment->next->x); + *y = (1-position)*(1-position)*(1-position) * segment->y + + 3 * position *(1-position)*(1-position) * (segment->y + 60) + + 3 * position * position *(1-position) * (segment->next->y + 60) + + position * position * position * (segment->next->y); +#endif + } +#ifdef PATH_TOOL_DEBUG + else + fprintf (stderr, "path_curve_get_point called without valid curve"); +#endif + } + return; +} + +void +path_curve_draw_handles (Tool *tool, + PathSegment *segment) +{ + if (segment && CurveTypes[segment->type].draw_handles) + (* CurveTypes[segment->type].draw_handles) (tool, segment); + + /* straight lines do not have handles... */ + return; +} + +void +path_curve_draw_segment (Tool *tool, + PathSegment *segment) +{ + gint x, y, numpts, index; + + if (segment && segment->next) { + if (CurveTypes[segment->type].draw_segment) { + (* CurveTypes[segment->type].draw_segment) (tool, segment); + return; + } else { + GdkPoint *coordinates = g_new (GdkPoint, 100); + numpts = path_curve_get_points (((PathTool *) tool->private), segment, + coordinates, 100, 0, 1); + for (index=0; index < numpts; index++) { + gdisplay_transform_coords (tool->gdisp_ptr, + coordinates[index].x, + coordinates[index].y, + &x, &y, FALSE); + coordinates[index].x = x; + coordinates[index].y = y; + } + gdk_draw_lines (((PathTool *) tool->private)->core->win, + ((PathTool *) tool->private)->core->gc, + coordinates, numpts); + g_free (coordinates); + } + +#ifdef PATH_TOOL_DEBUG + } else { + fprintf (stderr, "Fatal Error: path_curve_draw_segment called without valid segment *\n"); +#endif + + } + + return; +} + + +gdouble +path_curve_on_segment (Tool *tool, + PathSegment *segment, + gint x, + gint y, + gint halfwidth, + gint *distance) +{ + + if (segment && CurveTypes[segment->type].on_segment) + return (* CurveTypes[segment->type].on_segment) (tool, segment, x, y, halfwidth, distance); + else { + if (segment && segment->next) { +#if 1 + gint x1, y1, numpts, index; + GdkPoint *coordinates = g_new (GdkPoint, 100); + gint bestindex = -1; + + *distance = halfwidth * halfwidth + 1; + + numpts = path_curve_get_points (((PathTool *) tool->private), segment, + coordinates, 100, 0, 1); + for (index=0; index < numpts; index++) { + x1 = coordinates[index].x; + y1 = coordinates[index].y; + if (((x - x1) * (x - x1) + (y - y1) * (y - y1)) < *distance) { + *distance = (x - x1) * (x - x1) + (y - y1) * (y - y1); + bestindex = index; + } + } + g_free (coordinates); + if (numpts == 1) { + *distance = (gint) sqrt ((gdouble) *distance); + return bestindex; + } + if (bestindex >= 0 && (*distance <= halfwidth * halfwidth)) { + *distance = (gint) sqrt ((gdouble) *distance); + return bestindex == 0 ? 0 : ((gdouble) bestindex) / (numpts - 1); + } + +#else + + /* Special case for lines */ + gdouble Ax, Ay, Bx, By, r, d; + Ax = segment->x; + Ay = segment->y; + Bx = segment->next->x; + By = segment->next->y; + + r = (( x - Ax)*(Bx - Ax) + ( y - Ay)* (By - Ay)) / + ((Bx - Ax)*(Bx - Ax) + (By - Ay)* (By - Ay)) ; + + if (r >= 0 && r <= 1) { + d = (((Ax + (Bx - Ax) * r) - x) * ((Ax + (Bx - Ax) * r) - x) + + ((Ay + (By - Ay) * r) - y) * ((Ay + (By - Ay) * r) - y)); + if (d <= halfwidth * halfwidth) { + *distance = (gint) (d + 0.5); + return r; + } + } +#endif + } + } + + return -1; +} + +void +path_curve_drag_segment (PathTool *path_tool, + PathSegment *segment, + gdouble position, + gint x, + gint y + ) +{ + if (segment && CurveTypes[segment->type].drag_segment) + (* CurveTypes[segment->type].drag_segment) (path_tool, segment, position, x, y); + return; +} + +gboolean +path_curve_on_handle (PathTool *path_tool, + PathSegment *segment, + gint x, + gint y, + gint halfwidth) +{ + if (segment && CurveTypes[segment->type].on_handles) + return (* CurveTypes[segment->type].on_handles) (path_tool, segment, x, y, halfwidth); + return FALSE; +} + +void +path_curve_drag_handle (PathTool *path_tool, + PathSegment *segment, + gint x, + gint y + ) +{ + if (segment && CurveTypes[segment->type].drag_handle) + (* CurveTypes[segment->type].drag_handle) (path_tool, segment, x, y); +} + +PathSegment * +path_curve_insert_anchor (PathTool *path_tool, + PathSegment *segment, + gdouble position) +{ + if (segment && CurveTypes[segment->type].insert_anchor) + return (* CurveTypes[segment->type].insert_anchor) (path_tool, segment, position); + else { + return path_split_segment (segment, position); + } +} + +void +path_curve_flip_segment (PathTool *path_tool, + PathSegment *segment) +{ + if (segment && CurveTypes[segment->type].flip_segment) + (* CurveTypes[segment->type].flip_segment) (path_tool, segment); + return; +} + +void +path_curve_update_segment (PathTool *path_tool, + PathSegment *segment) +{ + if (segment && CurveTypes[segment->type].update_segment) + (* CurveTypes[segment->type].update_segment) (path_tool, segment); + return; +} diff --git a/app/path_curves.h b/app/path_curves.h new file mode 100644 index 0000000000..cd7aadddb0 --- /dev/null +++ b/app/path_curves.h @@ -0,0 +1,201 @@ +/* The GIMP -- an image manipulation program + * + * This file Copyright (C) 1999 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __PATH_CURVES_H__ +#define __PATH_CURVES_H__ + +#include +#include "path_toolP.h" + + +/* + * This function is to get a set of npoints different coordinates for + * the range from start to end (each in the range from 0 to 1 and + * start < end). + * returns the number of created coords. Make sure that the points- + * Array is allocated. + */ + +typedef guint (*PathGetPointsFunc) (PathTool *path_tool, + PathSegment *segment, + GdkPoint *points, + guint npoints, + gdouble start, + gdouble end); + +typedef void (*PathGetPointFunc) (PathTool *path_tool, + PathSegment *segment, + gdouble position, + gdouble *x, + gdouble *y); + +typedef void (*PathDrawHandlesFunc) (Tool *tool, + PathSegment *segment); + +typedef void (*PathDrawSegmentFunc) (Tool *tool, + PathSegment *segment); + + +typedef gdouble (*PathOnSegmentFunc) (Tool *tool, + PathSegment *segment, + gint x, + gint y, + gint halfwidth, + gint *distance); + +typedef void (*PathDragSegmentFunc) (PathTool *path_tool, + PathSegment *segment, + gdouble position, + gint x, + gint y + ); + +typedef gboolean (*PathOnHandlesFunc) (PathTool *path_tool, + PathSegment *segment, + gint x, + gint y, + gint halfwidth); + +typedef void (*PathDragHandleFunc) (PathTool *path_tool, + PathSegment *segment, + gint x, + gint y + ); + +typedef PathSegment * (*PathInsertAnchorFunc) (PathTool *path_tool, + PathSegment *segment, + gdouble position); + +typedef void (*PathUpdateSegmentFunc) (PathTool *path_tool, + PathSegment *segment); + +typedef void (*PathFlipSegmentFunc) (PathTool *path_tool, + PathSegment *segment); + +typedef struct { + PathGetPointsFunc get_points; + PathGetPointFunc get_point; + PathDrawHandlesFunc draw_handles; + PathDrawSegmentFunc draw_segment; + PathOnSegmentFunc on_segment; + PathDragSegmentFunc drag_segment; + PathOnHandlesFunc on_handles; + PathDragHandleFunc drag_handle; + PathInsertAnchorFunc insert_anchor; + PathUpdateSegmentFunc update_segment; + PathFlipSegmentFunc flip_segment; +} CurveDescription; + + +guint +path_curve_get_points (PathTool *path_tool, + PathSegment *segment, + GdkPoint *points, + guint npoints, + gdouble start, + gdouble end); + +void +path_curve_get_point (PathTool *path_tool, + PathSegment *segment, + gdouble position, + gdouble *x, + gdouble *y); + +void +path_curve_draw_handles (Tool *tool, + PathSegment *segment); + +void +path_curve_draw_segment (Tool *tool, + PathSegment *segment); + + +gdouble +path_curve_on_segment (Tool *tool, + PathSegment *segment, + gint x, + gint y, + gint halfwidth, + gint *distance); + +void +path_curve_drag_segment (PathTool *path_tool, + PathSegment *segment, + gdouble position, + gint x, + gint y + ); + +gboolean +path_curve_on_handle (PathTool *path_tool, + PathSegment *segment, + gint x, + gint y, + gint halfwidth); + +void +path_curve_drag_handle (PathTool *path_tool, + PathSegment *segment, + gint x, + gint y); + +PathSegment * +path_curve_insert_anchor (PathTool *path_tool, + PathSegment *segment, + gdouble position); + +void +path_curve_update_segment (PathTool *path_tool, + PathSegment *segment); + +void +path_curve_flip_segment (PathTool *path_tool, + PathSegment *segment); + + + + + + + + + + +/* This is, what Soleil (Olofs little daughter) has to say to this: + +fc fc g hgvfvv drrrrrrtcc jctfcz w sdzs d bx cv^[ ^[c^[f c +vffvcccccccccccccggfc fvx^[c^[x^[x^[x^[x^[x^[x^[ v xbvcbvcxv cxxc xxxx^[x +xz^[c^[x^[x^[x^[x^[x^[x^[xxxxxxcccccccxxxxxxxxxxxxxxxvä"åp' +hj^[[24~^[[4~^[[1~^[[4~^[[1~^[[4~ ^[[D^[[Bk^[[B,,,,, +,^[[2~^[[4~^[[6~^[[4~l^[[6~,l' .holg^[[B^[[B n,,klmj ^[[B^[[1~j ^[[P^[[B +^[[D^[[4~^[[6~nb ^[[A^[[C ^[[Akj^[[B ^[[A^[[C^[[A + + +...^[[1~^[[D^[[4~^[[2~^[[C^[[B,^[[A^[[2~^[[C^[[2~^[[A^[[3~^[[A^[[4~ ^[[2~ +^[[2~pö- ., å^[[Aöpl., k,km , +m,^[[5~^[[6~^[[2~^[[C^[[3~p^[[A^[[Bö^[[2~^[[B^[[6~^[[1~, .^[[D^[[4~^[[2~^[[Db +.l, .,.,m ^[[2~pöl. ik +^[[20~kl9i^[[20~^[[20~^[[20~^[[21~^[[21~^[[21~^[[21~^[[21~^[[21~^[[20~m + +^[[A^[[5~^[[G^[[D ^[[5~^[[1+^[[C + +*/ + +#endif /* __PATH_CURVES_H__ */ + diff --git a/app/path_tool.c b/app/path_tool.c index 3308d02b27..ae97b3868f 100644 --- a/app/path_tool.c +++ b/app/path_tool.c @@ -29,8 +29,6 @@ * segments between two anchors. */ -#undef PATH_TOOL_DEBUG - #include /* #include "appenv.h" */ @@ -39,6 +37,7 @@ #include "cursorutil.h" #include "path_tool.h" #include "path_toolP.h" +#include "path_curves.h" #ifdef PATH_TOOL_DEBUG #include @@ -63,51 +62,52 @@ /* Small functions to determine coordinates, iterate over path/curve/segment */ -static void path_segment_get_coordinates (PathSegment *, gdouble, gint *, gint *); -static void path_traverse_path (Path *, PathTraverseFunc, CurveTraverseFunc, SegmentTraverseFunc, gpointer); -static void path_traverse_curve (Path *, PathCurve *, CurveTraverseFunc, SegmentTraverseFunc, gpointer); -static void path_traverse_segment (Path *, PathCurve *, PathSegment *, SegmentTraverseFunc, gpointer); -static gdouble path_locate_point (Path *, PathCurve **, PathSegment **, gint, gint, gint, gint, gint); +void path_segment_get_coordinates (PathSegment *, gdouble, gint *, gint *); +void path_traverse_path (Path *, PathTraverseFunc, CurveTraverseFunc, SegmentTraverseFunc, gpointer); +void path_traverse_curve (Path *, PathCurve *, CurveTraverseFunc, SegmentTraverseFunc, gpointer); +void path_traverse_segment (Path *, PathCurve *, PathSegment *, SegmentTraverseFunc, gpointer); +gdouble path_locate_point (Path *, PathCurve **, PathSegment **, gint, gint, gint, gint, gint); /* Tools to manipulate paths, curves, segments */ -static PathCurve * path_add_curve (Path *, gint, gint); -static PathSegment * path_append_segment (Path *, PathCurve *, SegmentType, gint, gint); -static PathSegment * path_prepend_segment (Path *, PathCurve *, SegmentType, gint, gint); -static PathSegment * path_split_segment (PathSegment *, gdouble); -static void path_join_curves (PathSegment *, PathSegment *); -static void path_flip_curve (PathCurve *); -static void path_free_path (Path *); -static void path_free_curve (PathCurve *); -static void path_free_segment (PathSegment *); -static void path_delete_segment (PathSegment *); -static void path_print (Path *); -static void path_offset_active (Path *, gdouble, gdouble); -static void path_set_flags (PathTool *, Path *, PathCurve *, PathSegment *, guint32, guint32); +PathCurve * path_add_curve (Path *, gint, gint); +PathSegment * path_append_segment (Path *, PathCurve *, SegmentType, gint, gint); +PathSegment * path_prepend_segment (Path *, PathCurve *, SegmentType, gint, gint); +PathSegment * path_split_segment (PathSegment *, gdouble); +void path_join_curves (PathSegment *, PathSegment *); +void path_flip_curve (PathCurve *); +void path_free_path (Path *); +void path_free_curve (PathCurve *); +void path_free_segment (PathSegment *); +void path_delete_segment (PathSegment *); +void path_print (Path *); +void path_offset_active (Path *, gdouble, gdouble); +void path_set_flags (PathTool *, Path *, PathCurve *, PathSegment *, guint32, guint32); /* High level image-manipulation functions */ -static void path_stroke (PathTool *, Path *); -static void path_to_selection (PathTool *, Path *); +void path_stroke (PathTool *, Path *); +void path_to_selection (PathTool *, Path *); /* Functions necessary for the tool */ -static void path_tool_button_press (Tool *, GdkEventButton *, gpointer); -static void path_tool_button_release (Tool *, GdkEventButton *, gpointer); -static void path_tool_motion (Tool *, GdkEventMotion *, gpointer); -static void path_tool_cursor_update (Tool *, GdkEventMotion *, gpointer); -static void path_tool_control (Tool *, ToolAction, gpointer); -static void path_tool_draw (Tool *); -static void path_tool_draw_curve (Tool *, PathCurve *); -static void path_tool_draw_segment (Tool *, PathSegment *); -static gboolean path_tool_on_anchors (Tool *, gint, gint, gint, Path**, PathCurve**, PathSegment**); -static gboolean path_tool_on_handles (Tool *, gint, gint, gint); -static gboolean path_tool_on_curve (Tool *, gint, gint, gint); +void path_tool_button_press (Tool *, GdkEventButton *, gpointer); +void path_tool_button_release (Tool *, GdkEventButton *, gpointer); +void path_tool_motion (Tool *, GdkEventMotion *, gpointer); +void path_tool_cursor_update (Tool *, GdkEventMotion *, gpointer); +void path_tool_control (Tool *, ToolAction, gpointer); +void path_tool_draw (Tool *); +void path_tool_draw_curve (Tool *, PathCurve *); +void path_tool_draw_segment (Tool *, PathSegment *); +gboolean path_tool_on_anchors (Tool *, gint, gint, gint, Path**, PathCurve**, PathSegment**); +gdouble path_tool_on_curve (Tool *, gint, gint, gint, Path**, PathCurve**, PathSegment**); +gboolean path_tool_on_handles (Tool *, gint, gint, gint); -static gint path_tool_button_press_canvas (Tool *, GdkEventButton *, GDisplay *); -static gint path_tool_button_press_anchor (Tool *, GdkEventButton *, GDisplay *); -static void path_tool_motion_anchor (Tool *, GdkEventMotion *, GDisplay *); -static void path_tool_motion_curve (Tool *, GdkEventMotion *, GDisplay *); +gint path_tool_button_press_canvas (Tool *, GdkEventButton *, GDisplay *); +gint path_tool_button_press_anchor (Tool *, GdkEventButton *, GDisplay *); +gint path_tool_button_press_curve (Tool *, GdkEventButton *, GDisplay *); +void path_tool_motion_anchor (Tool *, GdkEventMotion *, GDisplay *); +void path_tool_motion_curve (Tool *, GdkEventMotion *, GDisplay *); /* the path tool options */ @@ -138,7 +138,7 @@ static ToolOptions *path_options = NULL; * */ -static void +void path_traverse_path (Path *path, PathTraverseFunc pathfunc, CurveTraverseFunc curvefunc, SegmentTraverseFunc segmentfunc, gpointer data) { PathCurve *cur_curve; @@ -160,7 +160,7 @@ path_traverse_path (Path *path, PathTraverseFunc pathfunc, CurveTraverseFunc cur } -static void +void path_traverse_curve (Path *path, PathCurve *curve, CurveTraverseFunc curvefunc, SegmentTraverseFunc segmentfunc, gpointer data) { PathSegment *cur_segment; @@ -181,13 +181,15 @@ path_traverse_curve (Path *path, PathCurve *curve, CurveTraverseFunc curvefunc, } } -static void +void path_traverse_segment (Path *path, PathCurve *curve, PathSegment *segment, SegmentTraverseFunc function, gpointer data) { #ifdef PATH_TOOL_DEBUG fprintf(stderr, "path_traverse_segment\n"); #endif PATH_TOOL_DEBUG + #warning here we need path_curve_get_point(s) + /* Something like: * for i = 1 to subsamples { * (x,y) = get_coordinates(i / subsamples) @@ -200,7 +202,7 @@ path_traverse_segment (Path *path, PathCurve *curve, PathSegment *segment, Segme * Helper functions for manipulating the data-structures: */ -static PathCurve *path_add_curve (Path * cur_path, gint x, gint y) +PathCurve *path_add_curve (Path * cur_path, gint x, gint y) { PathCurve * tmp = cur_path->curves; PathCurve * new_curve = NULL; @@ -233,7 +235,7 @@ static PathCurve *path_add_curve (Path * cur_path, gint x, gint y) } -static PathSegment * path_append_segment (Path * cur_path, PathCurve * cur_curve, SegmentType type, gint x, gint y) +PathSegment * path_append_segment (Path * cur_path, PathCurve * cur_curve, SegmentType type, gint x, gint y) { PathSegment * tmp = cur_curve->segments; PathSegment * new_segment = NULL; @@ -264,6 +266,9 @@ static PathSegment * path_append_segment (Path * cur_path, PathCurve * cur_curv tmp->next = new_segment; cur_curve->cur_segment = new_segment; + + #warning we need initialisation of the segment here. + } #ifdef PATH_TOOL_DEBUG else @@ -279,7 +284,7 @@ static PathSegment * path_append_segment (Path * cur_path, PathCurve * cur_curv } -static PathSegment * path_prepend_segment (Path * cur_path, PathCurve * cur_curve, SegmentType type, gint x, gint y) +PathSegment * path_prepend_segment (Path * cur_path, PathCurve * cur_curve, SegmentType type, gint x, gint y) { PathSegment * tmp = cur_curve->segments; PathSegment * new_segment = NULL; @@ -308,6 +313,7 @@ static PathSegment * path_prepend_segment (Path * cur_path, PathCurve * cur_cur cur_curve->segments = new_segment; cur_curve->cur_segment = new_segment; + #warning we need initialisation of the segment here. } #ifdef PATH_TOOL_DEBUG else @@ -322,15 +328,47 @@ static PathSegment * path_prepend_segment (Path * cur_path, PathCurve * cur_cur return new_segment; } -/* static PathSegment * path_split_segment (PathSegment *, gdouble); - */ +PathSegment * path_split_segment (PathSegment *segment, gdouble position) +{ + PathSegment * new_segment = NULL; + +#ifdef PATH_TOOL_DEBUG + fprintf(stderr, "path_split_segment\n"); +#endif PATH_TOOL_DEBUG + if (segment && segment->next) { + new_segment = g_new (PathSegment, 1); + + new_segment->type = segment->type; + #warning Giving PathTool as NULL Pointer! + path_curve_get_point (NULL, segment, position, &(new_segment->x), &(new_segment->y)); + new_segment->flags = 0; + new_segment->parent = segment->parent; + new_segment->next = segment->next; + new_segment->prev = segment; + new_segment->data = NULL; + + #warning we need initialisation of the segment here. + + new_segment->next->prev = new_segment; + segment->next = new_segment; + + return new_segment; + + } +#ifdef PATH_TOOL_DEBUG + else + fprintf(stderr, "path_split_segment without valid segment\n"); +#endif PATH_TOOL_DEBUG + return NULL; + +} /* * Join two arbitrary endpoints and free the parent from the second * segment, if it differs from the first parents. */ -static void +void path_join_curves (PathSegment *segment1, PathSegment *segment2) { PathCurve *curve1, *curve2; PathSegment *tmp; @@ -352,6 +390,7 @@ path_join_curves (PathSegment *segment1, PathSegment *segment2) { segment2->prev = segment1; segment1->next = segment2; } +#warning Probably some segment-updates needed return; } @@ -403,6 +442,7 @@ path_join_curves (PathSegment *segment1, PathSegment *segment2) { tmp->parent = curve1; tmp = tmp->next; } +#warning Probably some segment-updates needed return; } @@ -433,10 +473,11 @@ path_join_curves (PathSegment *segment1, PathSegment *segment2) { tmp = tmp->prev; } return; +#warning Probably some segment-updates needed } #ifdef PATH_TOOL_DEBUG - fprintf (stderr, "Cant join these curves yet...\n"); + fprintf (stderr, "Cant join these curves yet...\nThis should not happen."); return; #endif PATH_TOOL_DEBUG @@ -446,7 +487,7 @@ path_join_curves (PathSegment *segment1, PathSegment *segment2) { * This function reverses the order of the anchors. This is * necessary for some joining operations. */ -static void +void path_flip_curve (PathCurve *curve) { gpointer *end_data; @@ -454,6 +495,8 @@ path_flip_curve (PathCurve *curve) PathSegment *tmp, *tmp2; +#warning Please add path_curve_flip_segment here + if (!curve && !curve->segments) { #ifdef PATH_TOOL_DEBUG fprintf (stderr, "path_flip_curve: No curve o no segments to flip!\n"); @@ -483,11 +526,12 @@ path_flip_curve (PathCurve *curve) tmp->data = end_data; } tmp = tmp->next; +#warning Probably some segment-updates needed } } -static void +void path_free_path (Path * path) { PathCurve *tmp1, *tmp2; @@ -495,18 +539,18 @@ path_free_path (Path * path) if (path) { tmp2 = path->curves; - g_string_free(path->name, TRUE); - g_free(path); while ((tmp1 = tmp2) != NULL) { tmp2 = tmp1->next; path_free_curve (tmp1); } + g_string_free(path->name, TRUE); + g_free(path); } } -static void +void path_free_curve (PathCurve *curve) { PathSegment *tmp1, *tmp2; @@ -528,7 +572,7 @@ path_free_curve (PathCurve *curve) } } -static void +void path_free_segment (PathSegment *segment) { if (segment) @@ -538,11 +582,12 @@ path_free_segment (PathSegment *segment) segment->parent, segment, 0, SEGMENT_ACTIVE); if (segment->data) g_free(segment->data); +#warning Free Segment needs an own hook in the different curve-types! g_free (segment); } } -static void +void path_delete_curve (PathCurve *curve) { if (curve) @@ -560,7 +605,7 @@ path_delete_curve (PathCurve *curve) } } -static void +void path_delete_segment (PathSegment *segment) { if (segment) @@ -587,6 +632,7 @@ path_delete_segment (PathSegment *segment) /* * here we have to update the surrounding segments */ +#warning Please add path_curve_update_segment here } } @@ -595,14 +641,21 @@ path_delete_segment (PathSegment *segment) * A function to determine, which object is hit by the cursor */ -static gint -path_tool_cursor_position (Tool *tool, gint x, gint y, gint halfwidth, Path **pathP, PathCurve **curveP, PathSegment **segmentP) +gint +path_tool_cursor_position (Tool *tool, gint x, gint y, gint halfwidth, Path **pathP, PathCurve **curveP, PathSegment **segmentP, gdouble *positionP) { gint location; + gdouble pos; if (path_tool_on_anchors (tool, x, y, halfwidth, pathP, curveP, segmentP)) return ON_ANCHOR; + pos = path_tool_on_curve (tool, x, y, halfwidth, pathP, curveP, segmentP); + if (pos >= 0 && pos <= 1) { + if (positionP) (*positionP) = pos; + return ON_CURVE; + } + return ON_CANVAS; } @@ -611,7 +664,7 @@ path_tool_cursor_position (Tool *tool, gint x, gint y, gint halfwidth, Path **pa * The click-callbacks for the tool */ -static void +void path_tool_button_press (Tool *tool, GdkEventButton *bevent, gpointer gdisp_ptr) @@ -649,12 +702,13 @@ path_tool_button_press (Tool *tool, * switch accordingly. */ - path_tool->click_pos = path_tool_cursor_position(tool, x, y, halfwidth, + path_tool->click_type = path_tool_cursor_position(tool, x, y, halfwidth, &(path_tool->click_path), &(path_tool->click_curve), - &(path_tool->click_segment)); + &(path_tool->click_segment), + &(path_tool->click_position)); - switch (path_tool->click_pos) + switch (path_tool->click_type) { case ON_CANVAS: grab_pointer = path_tool_button_press_canvas(tool, bevent, gdisp); @@ -664,6 +718,10 @@ path_tool_button_press (Tool *tool, grab_pointer = path_tool_button_press_anchor(tool, bevent, gdisp); break; + case ON_CURVE: + grab_pointer = path_tool_button_press_curve(tool, bevent, gdisp); + break; + default: g_message("Huh? Whats happening here? (button_press_*)"); } @@ -679,7 +737,7 @@ path_tool_button_press (Tool *tool, } -static gint +gint path_tool_button_press_anchor (Tool *tool, GdkEventButton *bevent, GDisplay *gdisp) @@ -789,6 +847,7 @@ path_tool_button_press_anchor (Tool *tool, path_delete_segment (path_tool->click_segment); path_tool->click_segment = NULL; + /* Maybe CTRL-ALT Click should remove the whole curve? Or the active points? */ } else if (!(path_tool->click_segment->flags & SEGMENT_ACTIVE)) { @@ -797,14 +856,12 @@ path_tool_button_press_anchor (Tool *tool, } - /* Action goes here */ - draw_core_resume(path_tool->core, tool); return grab_pointer; } -static gint +gint path_tool_button_press_canvas (Tool *tool, GdkEventButton *bevent, GDisplay *gdisp) @@ -857,7 +914,48 @@ path_tool_button_press_canvas (Tool *tool, return 0; } -static void +gint +path_tool_button_press_curve (Tool *tool, + GdkEventButton *bevent, + GDisplay *gdisp) +{ + PathTool *path_tool = tool->private; + + Path * cur_path = path_tool->cur_path; + PathCurve * cur_curve; + PathSegment * cur_segment; + gint grab_pointer; + +#ifdef PATH_TOOL_DEBUG + fprintf(stderr, "path_tool_button_press_curve:\n"); +#endif PATH_TOOL_DEBUG + + grab_pointer = 1; + + if (!cur_path) { +#ifdef PATH_TOOL_DEBUG + fprintf (stderr, "Fatal error: No current Path\n"); +#endif PATH_TOOL_DEBUG + return 0; + } + + draw_core_pause (path_tool->core, tool); + + if (path_tool->click_modifier & GDK_SHIFT_MASK) { + cur_segment = path_curve_insert_anchor (path_tool, path_tool->click_segment, path_tool->click_position); + path_set_flags (path_tool, cur_path, NULL, NULL, 0, SEGMENT_ACTIVE); + path_set_flags (path_tool, cur_path, path_tool->click_curve, cur_segment, SEGMENT_ACTIVE, 0); + path_tool->click_type = ON_ANCHOR; + path_tool->click_segment = cur_segment; + + } + + draw_core_resume(path_tool->core, tool); + + return 0; +} + +void path_tool_button_release (Tool *tool, GdkEventButton *bevent, gpointer gdisp_ptr) @@ -883,7 +981,7 @@ path_tool_button_release (Tool *tool, * The motion-callbacks for the tool */ -static void +void path_tool_motion (Tool *tool, GdkEventMotion *mevent, gpointer gdisp_ptr) @@ -896,7 +994,7 @@ path_tool_motion (Tool *tool, gdisp = (GDisplay *) gdisp_ptr; path_tool = (PathTool *) tool->private; - switch (path_tool->click_pos) { + switch (path_tool->click_type) { case ON_ANCHOR: path_tool_motion_anchor(tool, mevent, gdisp); break; @@ -906,7 +1004,7 @@ path_tool_motion (Tool *tool, } -static void +void path_tool_motion_anchor (Tool *tool, GdkEventMotion *mevent, GDisplay *gdisp) @@ -977,7 +1075,7 @@ path_tool_motion_anchor (Tool *tool, } -static void +void path_tool_cursor_update (Tool *tool, GdkEventMotion *mevent, gpointer gdisp_ptr) @@ -999,13 +1097,16 @@ path_tool_cursor_update (Tool *tool, gdisplay_untransform_coords (gdisp, mevent->x + PATH_TOOL_HALFWIDTH, 0, &halfwidth, &dummy, TRUE, 0); halfwidth -= x; - cursor_location = path_tool_cursor_position(tool, x, y, halfwidth, NULL, NULL, NULL); + cursor_location = path_tool_cursor_position(tool, x, y, halfwidth, NULL, NULL, NULL, NULL); switch (cursor_location) { case ON_CANVAS: gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE1AP_CURSOR); break; case ON_ANCHOR: + gdisplay_install_tool_cursor (gdisp, GDK_FLEUR); + break; + case ON_CURVE: gdisplay_install_tool_cursor (gdisp, GDK_TCROSS); break; default: @@ -1018,7 +1119,7 @@ path_tool_cursor_update (Tool *tool, * Tool-control functions */ -static void +void path_tool_control (Tool *tool, ToolAction action, gpointer gdisp_ptr) @@ -1044,6 +1145,9 @@ path_tool_control (Tool *tool, break; case HALT: +#ifdef PATH_TOOL_DEBUG + fprintf (stderr, "path_tool_control: HALT\n"); +#endif PATH_TOOL_DEBUG draw_core_stop (path_tool->core, tool); tool->state = INACTIVE; break; @@ -1051,6 +1155,9 @@ path_tool_control (Tool *tool, default: break; } +#ifdef PATH_TOOL_DEBUG + fprintf (stderr, "path_tool_control: end\n"); +#endif PATH_TOOL_DEBUG } Tool * @@ -1069,11 +1176,15 @@ tools_new_path_tool (void) tool = tools_new_tool (PATH_TOOL); private = g_new (PathTool, 1); - private->click_pos = ON_CANVAS; + private->click_type = ON_CANVAS; private->click_x = 0; private->click_y = 0; private->click_halfwidth = 0; private->click_modifier = 0; + private->click_path = NULL; + private->click_curve = NULL; + private->click_segment = NULL; + private->click_position = -1; private->active_count = 0; private->single_active_segment = NULL; @@ -1108,6 +1219,9 @@ tools_free_path_tool (Tool *tool) GDisplay * gdisp; PathTool * path_tool; +#ifdef PATH_TOOL_DEBUG + fprintf (stderr, "tools_free_path_tool start\n"); +#endif PATH_TOOL_DEBUG path_tool = (PathTool *) tool->private; gdisp = (GDisplay *) tool->gdisp_ptr; @@ -1121,9 +1235,84 @@ tools_free_path_tool (Tool *tool) draw_core_free (path_tool->core); g_free (path_tool); +#ifdef PATH_TOOL_DEBUG + fprintf (stderr, "tools_free_path_tool end\n"); +#endif PATH_TOOL_DEBUG + } +/************************************************************** + * Set of function to determine, if the click was on an segment + */ + +typedef struct { + Tool *tool; + Path *path; + PathCurve *curve; + PathSegment *segment; + gint testx; + gint testy; + gint halfwidth; + gint distance; + gdouble position; + gboolean found; +} Path_on_curve_type; + +/* This is a CurveTraverseFunc */ +void +path_tool_on_curve_helper (Path *path, PathCurve *curve, PathSegment *segment, gpointer ptr) +{ + gint distance; + gdouble position; + Path_on_curve_type *data = (Path_on_curve_type *) ptr; + + if (segment && segment->next && data && data->distance > 0) + { + position = path_curve_on_segment (data->tool, segment, data->testx, data->testy, data->halfwidth, &distance); + if (position >= 0 && distance < data->distance ) + { + data->path = path; + data->curve = curve; + data->segment = segment; + data->distance = distance; + data->position = position; + data->found = TRUE; + } + } +} + +gdouble +path_tool_on_curve (Tool *tool, gint x, gint y, gint halfwidth, Path **ret_pathP, PathCurve **ret_curveP, PathSegment **ret_segmentP) +{ + Path_on_curve_type *data = g_new (Path_on_curve_type, 1); + gdouble position; + + data->tool = tool; + data->path = NULL; + data->segment = NULL; + data->segment = NULL; + data->testx = x; + data->testy = y; + data->halfwidth = halfwidth; + data->distance = halfwidth * halfwidth + 1; + data->position = -1; + data->found = FALSE; + + path_traverse_path (((PathTool *) data->tool->private)->cur_path, NULL, path_tool_on_curve_helper, NULL, data); + + if (ret_pathP) *ret_pathP = data->path; + if (ret_curveP) *ret_curveP = data->curve; + if (ret_segmentP) *ret_segmentP = data->segment; + + position = data->position; + + g_free(data); + + return position; + +} + /************************************************************** * Set of function to determine, if the click was on an anchor */ @@ -1139,7 +1328,7 @@ typedef struct { } Path_on_anchors_type; /* This is a CurveTraverseFunc */ -static void +void path_tool_on_anchors_helper (Path *path, PathCurve *curve, PathSegment *segment, gpointer ptr) { gint distance; @@ -1161,7 +1350,7 @@ path_tool_on_anchors_helper (Path *path, PathCurve *curve, PathSegment *segment, } } -static gboolean +gboolean path_tool_on_anchors (Tool *tool, gint x, gint y, gint halfwidth, Path **ret_pathP, PathCurve **ret_curveP, PathSegment **ret_segmentP) { Path_on_anchors_type *data = g_new (Path_on_anchors_type, 1); @@ -1200,7 +1389,7 @@ typedef struct { } Path_offset_active_type; /* This is a CurveTraverseFunc */ -static void +void path_offset_active_helper (Path *path, PathCurve *curve, PathSegment *segment, gpointer ptr) { Path_offset_active_type *data = (Path_offset_active_type *) ptr; @@ -1209,9 +1398,10 @@ path_offset_active_helper (Path *path, PathCurve *curve, PathSegment *segment, g segment->x += data->dx; segment->y += data->dy; } +#warning Do a segment_update here! } -static void +void path_offset_active (Path *path, gdouble dx, gdouble dy) { Path_offset_active_type *data = g_new (Path_offset_active_type, 1); @@ -1226,7 +1416,7 @@ path_offset_active (Path *path, gdouble dx, gdouble dy) /************************************************************** - * Set of function to set the state of all anchors to inactive + * Set of function to set the state of all anchors */ typedef struct { @@ -1236,7 +1426,7 @@ typedef struct { } Path_set_flags_type; /* This is a CurveTraverseFunc */ -static void +void path_set_flags_helper (Path *path, PathCurve *curve, PathSegment *segment, gpointer ptr) { Path_set_flags_type *tmp = (Path_set_flags_type *) ptr; @@ -1272,7 +1462,7 @@ path_set_flags_helper (Path *path, PathCurve *curve, PathSegment *segment, gpoin } } -static void +void path_set_flags (PathTool *path_tool, Path *path, PathCurve *curve, PathSegment *segment, guint32 bits_set, guint32 bits_clear) { Path_set_flags_type *tmp = g_new (Path_set_flags_type, 1); @@ -1296,7 +1486,7 @@ path_set_flags (PathTool *path_tool, Path *path, PathCurve *curve, PathSegment * */ /* This is a CurveTraverseFunc */ -static void +void path_tool_draw_helper (Path *path, PathCurve *curve, PathSegment * segment, gpointer tool_ptr) { Tool * tool = (Tool *) tool_ptr; @@ -1335,8 +1525,7 @@ path_tool_draw_helper (Path *path, PathCurve *curve, PathSegment * segment, gpoi if (segment->next) { - gdisplay_transform_coords (gdisp, (gint) segment->next->x, (gint) segment->next->y, &x2, &y2, FALSE); - gdk_draw_line (core->win, core->gc, x1, y1, x2, y2); + path_curve_draw_segment (tool, segment); } } #ifdef PATH_TOOL_DEBUG @@ -1345,7 +1534,7 @@ path_tool_draw_helper (Path *path, PathCurve *curve, PathSegment * segment, gpoi #endif PATH_TOOL_DEBUG } -static void +void path_tool_draw (Tool *tool) { GDisplay * gdisp; @@ -1363,4 +1552,10 @@ path_tool_draw (Tool *tool) path_traverse_path (cur_path, NULL, path_tool_draw_helper, NULL, tool); +#ifdef PATH_TOOL_DEBUG + fprintf (stderr, "path_tool_draw end.\n"); +#endif PATH_TOOL_DEBUG + } + + diff --git a/app/path_tool.h b/app/path_tool.h index 9a21b8e1d1..c80df93fe5 100644 --- a/app/path_tool.h +++ b/app/path_tool.h @@ -1,5 +1,6 @@ /* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This file Copyright (C) 1999 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 @@ -15,6 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + #ifndef __PATH_TOOL_H__ #define __PATH_TOOL_H__ diff --git a/app/path_toolP.h b/app/path_toolP.h index 0c26613b4d..c9c9dd2bbc 100644 --- a/app/path_toolP.h +++ b/app/path_toolP.h @@ -18,6 +18,9 @@ #ifndef __PATH_TOOLP_H__ #define __PATH_TOOLP_H__ +#undef PATH_TOOL_DEBUG + +#include "draw_core.h" #define IMAGE_COORDS 1 #define AA_IMAGE_COORDS 2 @@ -33,12 +36,10 @@ #define SUBDIVIDE 1000 +typedef enum { SEGMENT_LINE=0, SEGMENT_BEZIER} SegmentType; enum { ON_ANCHOR, ON_HANDLE, ON_CURVE, ON_CANVAS }; -typedef enum { SEGMENT_LINE, SEGMENT_BEZIER } SegmentType; - - typedef struct _path_segment PathSegment; typedef struct _path_curve PathCurve; typedef struct _path Path; @@ -82,7 +83,7 @@ struct _path struct _path_tool { - gint click_pos; /* where did the user click? */ + gint click_type; /* where did the user click? */ gint click_x; /* X-coordinate of the click */ gint click_y; /* Y-coordinate of the click */ gint click_halfwidth; @@ -90,6 +91,7 @@ struct _path_tool Path *click_path; /* On which Path/Curve/Segment */ PathCurve *click_curve; /* was the click? */ PathSegment *click_segment; + gdouble click_position; /* The position on the segment */ gint active_count; /* How many segments are active? */ /* @@ -110,6 +112,4 @@ typedef void (*PathTraverseFunc) (Path *, PathCurve *, gpointer); typedef void (*CurveTraverseFunc) (Path *, PathCurve *, PathSegment *, gpointer); typedef void (*SegmentTraverseFunc) (Path *, PathCurve *, PathSegment *, gint, gint, gpointer); -/* typedef void (*SegmentTraverseFunc) (PathTool *, GdkPoint *, gint, gpointer);*/ - #endif /* __PATH_TOOLP_H__ */ diff --git a/app/tools/path_tool.c b/app/tools/path_tool.c index 3308d02b27..ae97b3868f 100644 --- a/app/tools/path_tool.c +++ b/app/tools/path_tool.c @@ -29,8 +29,6 @@ * segments between two anchors. */ -#undef PATH_TOOL_DEBUG - #include /* #include "appenv.h" */ @@ -39,6 +37,7 @@ #include "cursorutil.h" #include "path_tool.h" #include "path_toolP.h" +#include "path_curves.h" #ifdef PATH_TOOL_DEBUG #include @@ -63,51 +62,52 @@ /* Small functions to determine coordinates, iterate over path/curve/segment */ -static void path_segment_get_coordinates (PathSegment *, gdouble, gint *, gint *); -static void path_traverse_path (Path *, PathTraverseFunc, CurveTraverseFunc, SegmentTraverseFunc, gpointer); -static void path_traverse_curve (Path *, PathCurve *, CurveTraverseFunc, SegmentTraverseFunc, gpointer); -static void path_traverse_segment (Path *, PathCurve *, PathSegment *, SegmentTraverseFunc, gpointer); -static gdouble path_locate_point (Path *, PathCurve **, PathSegment **, gint, gint, gint, gint, gint); +void path_segment_get_coordinates (PathSegment *, gdouble, gint *, gint *); +void path_traverse_path (Path *, PathTraverseFunc, CurveTraverseFunc, SegmentTraverseFunc, gpointer); +void path_traverse_curve (Path *, PathCurve *, CurveTraverseFunc, SegmentTraverseFunc, gpointer); +void path_traverse_segment (Path *, PathCurve *, PathSegment *, SegmentTraverseFunc, gpointer); +gdouble path_locate_point (Path *, PathCurve **, PathSegment **, gint, gint, gint, gint, gint); /* Tools to manipulate paths, curves, segments */ -static PathCurve * path_add_curve (Path *, gint, gint); -static PathSegment * path_append_segment (Path *, PathCurve *, SegmentType, gint, gint); -static PathSegment * path_prepend_segment (Path *, PathCurve *, SegmentType, gint, gint); -static PathSegment * path_split_segment (PathSegment *, gdouble); -static void path_join_curves (PathSegment *, PathSegment *); -static void path_flip_curve (PathCurve *); -static void path_free_path (Path *); -static void path_free_curve (PathCurve *); -static void path_free_segment (PathSegment *); -static void path_delete_segment (PathSegment *); -static void path_print (Path *); -static void path_offset_active (Path *, gdouble, gdouble); -static void path_set_flags (PathTool *, Path *, PathCurve *, PathSegment *, guint32, guint32); +PathCurve * path_add_curve (Path *, gint, gint); +PathSegment * path_append_segment (Path *, PathCurve *, SegmentType, gint, gint); +PathSegment * path_prepend_segment (Path *, PathCurve *, SegmentType, gint, gint); +PathSegment * path_split_segment (PathSegment *, gdouble); +void path_join_curves (PathSegment *, PathSegment *); +void path_flip_curve (PathCurve *); +void path_free_path (Path *); +void path_free_curve (PathCurve *); +void path_free_segment (PathSegment *); +void path_delete_segment (PathSegment *); +void path_print (Path *); +void path_offset_active (Path *, gdouble, gdouble); +void path_set_flags (PathTool *, Path *, PathCurve *, PathSegment *, guint32, guint32); /* High level image-manipulation functions */ -static void path_stroke (PathTool *, Path *); -static void path_to_selection (PathTool *, Path *); +void path_stroke (PathTool *, Path *); +void path_to_selection (PathTool *, Path *); /* Functions necessary for the tool */ -static void path_tool_button_press (Tool *, GdkEventButton *, gpointer); -static void path_tool_button_release (Tool *, GdkEventButton *, gpointer); -static void path_tool_motion (Tool *, GdkEventMotion *, gpointer); -static void path_tool_cursor_update (Tool *, GdkEventMotion *, gpointer); -static void path_tool_control (Tool *, ToolAction, gpointer); -static void path_tool_draw (Tool *); -static void path_tool_draw_curve (Tool *, PathCurve *); -static void path_tool_draw_segment (Tool *, PathSegment *); -static gboolean path_tool_on_anchors (Tool *, gint, gint, gint, Path**, PathCurve**, PathSegment**); -static gboolean path_tool_on_handles (Tool *, gint, gint, gint); -static gboolean path_tool_on_curve (Tool *, gint, gint, gint); +void path_tool_button_press (Tool *, GdkEventButton *, gpointer); +void path_tool_button_release (Tool *, GdkEventButton *, gpointer); +void path_tool_motion (Tool *, GdkEventMotion *, gpointer); +void path_tool_cursor_update (Tool *, GdkEventMotion *, gpointer); +void path_tool_control (Tool *, ToolAction, gpointer); +void path_tool_draw (Tool *); +void path_tool_draw_curve (Tool *, PathCurve *); +void path_tool_draw_segment (Tool *, PathSegment *); +gboolean path_tool_on_anchors (Tool *, gint, gint, gint, Path**, PathCurve**, PathSegment**); +gdouble path_tool_on_curve (Tool *, gint, gint, gint, Path**, PathCurve**, PathSegment**); +gboolean path_tool_on_handles (Tool *, gint, gint, gint); -static gint path_tool_button_press_canvas (Tool *, GdkEventButton *, GDisplay *); -static gint path_tool_button_press_anchor (Tool *, GdkEventButton *, GDisplay *); -static void path_tool_motion_anchor (Tool *, GdkEventMotion *, GDisplay *); -static void path_tool_motion_curve (Tool *, GdkEventMotion *, GDisplay *); +gint path_tool_button_press_canvas (Tool *, GdkEventButton *, GDisplay *); +gint path_tool_button_press_anchor (Tool *, GdkEventButton *, GDisplay *); +gint path_tool_button_press_curve (Tool *, GdkEventButton *, GDisplay *); +void path_tool_motion_anchor (Tool *, GdkEventMotion *, GDisplay *); +void path_tool_motion_curve (Tool *, GdkEventMotion *, GDisplay *); /* the path tool options */ @@ -138,7 +138,7 @@ static ToolOptions *path_options = NULL; * */ -static void +void path_traverse_path (Path *path, PathTraverseFunc pathfunc, CurveTraverseFunc curvefunc, SegmentTraverseFunc segmentfunc, gpointer data) { PathCurve *cur_curve; @@ -160,7 +160,7 @@ path_traverse_path (Path *path, PathTraverseFunc pathfunc, CurveTraverseFunc cur } -static void +void path_traverse_curve (Path *path, PathCurve *curve, CurveTraverseFunc curvefunc, SegmentTraverseFunc segmentfunc, gpointer data) { PathSegment *cur_segment; @@ -181,13 +181,15 @@ path_traverse_curve (Path *path, PathCurve *curve, CurveTraverseFunc curvefunc, } } -static void +void path_traverse_segment (Path *path, PathCurve *curve, PathSegment *segment, SegmentTraverseFunc function, gpointer data) { #ifdef PATH_TOOL_DEBUG fprintf(stderr, "path_traverse_segment\n"); #endif PATH_TOOL_DEBUG + #warning here we need path_curve_get_point(s) + /* Something like: * for i = 1 to subsamples { * (x,y) = get_coordinates(i / subsamples) @@ -200,7 +202,7 @@ path_traverse_segment (Path *path, PathCurve *curve, PathSegment *segment, Segme * Helper functions for manipulating the data-structures: */ -static PathCurve *path_add_curve (Path * cur_path, gint x, gint y) +PathCurve *path_add_curve (Path * cur_path, gint x, gint y) { PathCurve * tmp = cur_path->curves; PathCurve * new_curve = NULL; @@ -233,7 +235,7 @@ static PathCurve *path_add_curve (Path * cur_path, gint x, gint y) } -static PathSegment * path_append_segment (Path * cur_path, PathCurve * cur_curve, SegmentType type, gint x, gint y) +PathSegment * path_append_segment (Path * cur_path, PathCurve * cur_curve, SegmentType type, gint x, gint y) { PathSegment * tmp = cur_curve->segments; PathSegment * new_segment = NULL; @@ -264,6 +266,9 @@ static PathSegment * path_append_segment (Path * cur_path, PathCurve * cur_curv tmp->next = new_segment; cur_curve->cur_segment = new_segment; + + #warning we need initialisation of the segment here. + } #ifdef PATH_TOOL_DEBUG else @@ -279,7 +284,7 @@ static PathSegment * path_append_segment (Path * cur_path, PathCurve * cur_curv } -static PathSegment * path_prepend_segment (Path * cur_path, PathCurve * cur_curve, SegmentType type, gint x, gint y) +PathSegment * path_prepend_segment (Path * cur_path, PathCurve * cur_curve, SegmentType type, gint x, gint y) { PathSegment * tmp = cur_curve->segments; PathSegment * new_segment = NULL; @@ -308,6 +313,7 @@ static PathSegment * path_prepend_segment (Path * cur_path, PathCurve * cur_cur cur_curve->segments = new_segment; cur_curve->cur_segment = new_segment; + #warning we need initialisation of the segment here. } #ifdef PATH_TOOL_DEBUG else @@ -322,15 +328,47 @@ static PathSegment * path_prepend_segment (Path * cur_path, PathCurve * cur_cur return new_segment; } -/* static PathSegment * path_split_segment (PathSegment *, gdouble); - */ +PathSegment * path_split_segment (PathSegment *segment, gdouble position) +{ + PathSegment * new_segment = NULL; + +#ifdef PATH_TOOL_DEBUG + fprintf(stderr, "path_split_segment\n"); +#endif PATH_TOOL_DEBUG + if (segment && segment->next) { + new_segment = g_new (PathSegment, 1); + + new_segment->type = segment->type; + #warning Giving PathTool as NULL Pointer! + path_curve_get_point (NULL, segment, position, &(new_segment->x), &(new_segment->y)); + new_segment->flags = 0; + new_segment->parent = segment->parent; + new_segment->next = segment->next; + new_segment->prev = segment; + new_segment->data = NULL; + + #warning we need initialisation of the segment here. + + new_segment->next->prev = new_segment; + segment->next = new_segment; + + return new_segment; + + } +#ifdef PATH_TOOL_DEBUG + else + fprintf(stderr, "path_split_segment without valid segment\n"); +#endif PATH_TOOL_DEBUG + return NULL; + +} /* * Join two arbitrary endpoints and free the parent from the second * segment, if it differs from the first parents. */ -static void +void path_join_curves (PathSegment *segment1, PathSegment *segment2) { PathCurve *curve1, *curve2; PathSegment *tmp; @@ -352,6 +390,7 @@ path_join_curves (PathSegment *segment1, PathSegment *segment2) { segment2->prev = segment1; segment1->next = segment2; } +#warning Probably some segment-updates needed return; } @@ -403,6 +442,7 @@ path_join_curves (PathSegment *segment1, PathSegment *segment2) { tmp->parent = curve1; tmp = tmp->next; } +#warning Probably some segment-updates needed return; } @@ -433,10 +473,11 @@ path_join_curves (PathSegment *segment1, PathSegment *segment2) { tmp = tmp->prev; } return; +#warning Probably some segment-updates needed } #ifdef PATH_TOOL_DEBUG - fprintf (stderr, "Cant join these curves yet...\n"); + fprintf (stderr, "Cant join these curves yet...\nThis should not happen."); return; #endif PATH_TOOL_DEBUG @@ -446,7 +487,7 @@ path_join_curves (PathSegment *segment1, PathSegment *segment2) { * This function reverses the order of the anchors. This is * necessary for some joining operations. */ -static void +void path_flip_curve (PathCurve *curve) { gpointer *end_data; @@ -454,6 +495,8 @@ path_flip_curve (PathCurve *curve) PathSegment *tmp, *tmp2; +#warning Please add path_curve_flip_segment here + if (!curve && !curve->segments) { #ifdef PATH_TOOL_DEBUG fprintf (stderr, "path_flip_curve: No curve o no segments to flip!\n"); @@ -483,11 +526,12 @@ path_flip_curve (PathCurve *curve) tmp->data = end_data; } tmp = tmp->next; +#warning Probably some segment-updates needed } } -static void +void path_free_path (Path * path) { PathCurve *tmp1, *tmp2; @@ -495,18 +539,18 @@ path_free_path (Path * path) if (path) { tmp2 = path->curves; - g_string_free(path->name, TRUE); - g_free(path); while ((tmp1 = tmp2) != NULL) { tmp2 = tmp1->next; path_free_curve (tmp1); } + g_string_free(path->name, TRUE); + g_free(path); } } -static void +void path_free_curve (PathCurve *curve) { PathSegment *tmp1, *tmp2; @@ -528,7 +572,7 @@ path_free_curve (PathCurve *curve) } } -static void +void path_free_segment (PathSegment *segment) { if (segment) @@ -538,11 +582,12 @@ path_free_segment (PathSegment *segment) segment->parent, segment, 0, SEGMENT_ACTIVE); if (segment->data) g_free(segment->data); +#warning Free Segment needs an own hook in the different curve-types! g_free (segment); } } -static void +void path_delete_curve (PathCurve *curve) { if (curve) @@ -560,7 +605,7 @@ path_delete_curve (PathCurve *curve) } } -static void +void path_delete_segment (PathSegment *segment) { if (segment) @@ -587,6 +632,7 @@ path_delete_segment (PathSegment *segment) /* * here we have to update the surrounding segments */ +#warning Please add path_curve_update_segment here } } @@ -595,14 +641,21 @@ path_delete_segment (PathSegment *segment) * A function to determine, which object is hit by the cursor */ -static gint -path_tool_cursor_position (Tool *tool, gint x, gint y, gint halfwidth, Path **pathP, PathCurve **curveP, PathSegment **segmentP) +gint +path_tool_cursor_position (Tool *tool, gint x, gint y, gint halfwidth, Path **pathP, PathCurve **curveP, PathSegment **segmentP, gdouble *positionP) { gint location; + gdouble pos; if (path_tool_on_anchors (tool, x, y, halfwidth, pathP, curveP, segmentP)) return ON_ANCHOR; + pos = path_tool_on_curve (tool, x, y, halfwidth, pathP, curveP, segmentP); + if (pos >= 0 && pos <= 1) { + if (positionP) (*positionP) = pos; + return ON_CURVE; + } + return ON_CANVAS; } @@ -611,7 +664,7 @@ path_tool_cursor_position (Tool *tool, gint x, gint y, gint halfwidth, Path **pa * The click-callbacks for the tool */ -static void +void path_tool_button_press (Tool *tool, GdkEventButton *bevent, gpointer gdisp_ptr) @@ -649,12 +702,13 @@ path_tool_button_press (Tool *tool, * switch accordingly. */ - path_tool->click_pos = path_tool_cursor_position(tool, x, y, halfwidth, + path_tool->click_type = path_tool_cursor_position(tool, x, y, halfwidth, &(path_tool->click_path), &(path_tool->click_curve), - &(path_tool->click_segment)); + &(path_tool->click_segment), + &(path_tool->click_position)); - switch (path_tool->click_pos) + switch (path_tool->click_type) { case ON_CANVAS: grab_pointer = path_tool_button_press_canvas(tool, bevent, gdisp); @@ -664,6 +718,10 @@ path_tool_button_press (Tool *tool, grab_pointer = path_tool_button_press_anchor(tool, bevent, gdisp); break; + case ON_CURVE: + grab_pointer = path_tool_button_press_curve(tool, bevent, gdisp); + break; + default: g_message("Huh? Whats happening here? (button_press_*)"); } @@ -679,7 +737,7 @@ path_tool_button_press (Tool *tool, } -static gint +gint path_tool_button_press_anchor (Tool *tool, GdkEventButton *bevent, GDisplay *gdisp) @@ -789,6 +847,7 @@ path_tool_button_press_anchor (Tool *tool, path_delete_segment (path_tool->click_segment); path_tool->click_segment = NULL; + /* Maybe CTRL-ALT Click should remove the whole curve? Or the active points? */ } else if (!(path_tool->click_segment->flags & SEGMENT_ACTIVE)) { @@ -797,14 +856,12 @@ path_tool_button_press_anchor (Tool *tool, } - /* Action goes here */ - draw_core_resume(path_tool->core, tool); return grab_pointer; } -static gint +gint path_tool_button_press_canvas (Tool *tool, GdkEventButton *bevent, GDisplay *gdisp) @@ -857,7 +914,48 @@ path_tool_button_press_canvas (Tool *tool, return 0; } -static void +gint +path_tool_button_press_curve (Tool *tool, + GdkEventButton *bevent, + GDisplay *gdisp) +{ + PathTool *path_tool = tool->private; + + Path * cur_path = path_tool->cur_path; + PathCurve * cur_curve; + PathSegment * cur_segment; + gint grab_pointer; + +#ifdef PATH_TOOL_DEBUG + fprintf(stderr, "path_tool_button_press_curve:\n"); +#endif PATH_TOOL_DEBUG + + grab_pointer = 1; + + if (!cur_path) { +#ifdef PATH_TOOL_DEBUG + fprintf (stderr, "Fatal error: No current Path\n"); +#endif PATH_TOOL_DEBUG + return 0; + } + + draw_core_pause (path_tool->core, tool); + + if (path_tool->click_modifier & GDK_SHIFT_MASK) { + cur_segment = path_curve_insert_anchor (path_tool, path_tool->click_segment, path_tool->click_position); + path_set_flags (path_tool, cur_path, NULL, NULL, 0, SEGMENT_ACTIVE); + path_set_flags (path_tool, cur_path, path_tool->click_curve, cur_segment, SEGMENT_ACTIVE, 0); + path_tool->click_type = ON_ANCHOR; + path_tool->click_segment = cur_segment; + + } + + draw_core_resume(path_tool->core, tool); + + return 0; +} + +void path_tool_button_release (Tool *tool, GdkEventButton *bevent, gpointer gdisp_ptr) @@ -883,7 +981,7 @@ path_tool_button_release (Tool *tool, * The motion-callbacks for the tool */ -static void +void path_tool_motion (Tool *tool, GdkEventMotion *mevent, gpointer gdisp_ptr) @@ -896,7 +994,7 @@ path_tool_motion (Tool *tool, gdisp = (GDisplay *) gdisp_ptr; path_tool = (PathTool *) tool->private; - switch (path_tool->click_pos) { + switch (path_tool->click_type) { case ON_ANCHOR: path_tool_motion_anchor(tool, mevent, gdisp); break; @@ -906,7 +1004,7 @@ path_tool_motion (Tool *tool, } -static void +void path_tool_motion_anchor (Tool *tool, GdkEventMotion *mevent, GDisplay *gdisp) @@ -977,7 +1075,7 @@ path_tool_motion_anchor (Tool *tool, } -static void +void path_tool_cursor_update (Tool *tool, GdkEventMotion *mevent, gpointer gdisp_ptr) @@ -999,13 +1097,16 @@ path_tool_cursor_update (Tool *tool, gdisplay_untransform_coords (gdisp, mevent->x + PATH_TOOL_HALFWIDTH, 0, &halfwidth, &dummy, TRUE, 0); halfwidth -= x; - cursor_location = path_tool_cursor_position(tool, x, y, halfwidth, NULL, NULL, NULL); + cursor_location = path_tool_cursor_position(tool, x, y, halfwidth, NULL, NULL, NULL, NULL); switch (cursor_location) { case ON_CANVAS: gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE1AP_CURSOR); break; case ON_ANCHOR: + gdisplay_install_tool_cursor (gdisp, GDK_FLEUR); + break; + case ON_CURVE: gdisplay_install_tool_cursor (gdisp, GDK_TCROSS); break; default: @@ -1018,7 +1119,7 @@ path_tool_cursor_update (Tool *tool, * Tool-control functions */ -static void +void path_tool_control (Tool *tool, ToolAction action, gpointer gdisp_ptr) @@ -1044,6 +1145,9 @@ path_tool_control (Tool *tool, break; case HALT: +#ifdef PATH_TOOL_DEBUG + fprintf (stderr, "path_tool_control: HALT\n"); +#endif PATH_TOOL_DEBUG draw_core_stop (path_tool->core, tool); tool->state = INACTIVE; break; @@ -1051,6 +1155,9 @@ path_tool_control (Tool *tool, default: break; } +#ifdef PATH_TOOL_DEBUG + fprintf (stderr, "path_tool_control: end\n"); +#endif PATH_TOOL_DEBUG } Tool * @@ -1069,11 +1176,15 @@ tools_new_path_tool (void) tool = tools_new_tool (PATH_TOOL); private = g_new (PathTool, 1); - private->click_pos = ON_CANVAS; + private->click_type = ON_CANVAS; private->click_x = 0; private->click_y = 0; private->click_halfwidth = 0; private->click_modifier = 0; + private->click_path = NULL; + private->click_curve = NULL; + private->click_segment = NULL; + private->click_position = -1; private->active_count = 0; private->single_active_segment = NULL; @@ -1108,6 +1219,9 @@ tools_free_path_tool (Tool *tool) GDisplay * gdisp; PathTool * path_tool; +#ifdef PATH_TOOL_DEBUG + fprintf (stderr, "tools_free_path_tool start\n"); +#endif PATH_TOOL_DEBUG path_tool = (PathTool *) tool->private; gdisp = (GDisplay *) tool->gdisp_ptr; @@ -1121,9 +1235,84 @@ tools_free_path_tool (Tool *tool) draw_core_free (path_tool->core); g_free (path_tool); +#ifdef PATH_TOOL_DEBUG + fprintf (stderr, "tools_free_path_tool end\n"); +#endif PATH_TOOL_DEBUG + } +/************************************************************** + * Set of function to determine, if the click was on an segment + */ + +typedef struct { + Tool *tool; + Path *path; + PathCurve *curve; + PathSegment *segment; + gint testx; + gint testy; + gint halfwidth; + gint distance; + gdouble position; + gboolean found; +} Path_on_curve_type; + +/* This is a CurveTraverseFunc */ +void +path_tool_on_curve_helper (Path *path, PathCurve *curve, PathSegment *segment, gpointer ptr) +{ + gint distance; + gdouble position; + Path_on_curve_type *data = (Path_on_curve_type *) ptr; + + if (segment && segment->next && data && data->distance > 0) + { + position = path_curve_on_segment (data->tool, segment, data->testx, data->testy, data->halfwidth, &distance); + if (position >= 0 && distance < data->distance ) + { + data->path = path; + data->curve = curve; + data->segment = segment; + data->distance = distance; + data->position = position; + data->found = TRUE; + } + } +} + +gdouble +path_tool_on_curve (Tool *tool, gint x, gint y, gint halfwidth, Path **ret_pathP, PathCurve **ret_curveP, PathSegment **ret_segmentP) +{ + Path_on_curve_type *data = g_new (Path_on_curve_type, 1); + gdouble position; + + data->tool = tool; + data->path = NULL; + data->segment = NULL; + data->segment = NULL; + data->testx = x; + data->testy = y; + data->halfwidth = halfwidth; + data->distance = halfwidth * halfwidth + 1; + data->position = -1; + data->found = FALSE; + + path_traverse_path (((PathTool *) data->tool->private)->cur_path, NULL, path_tool_on_curve_helper, NULL, data); + + if (ret_pathP) *ret_pathP = data->path; + if (ret_curveP) *ret_curveP = data->curve; + if (ret_segmentP) *ret_segmentP = data->segment; + + position = data->position; + + g_free(data); + + return position; + +} + /************************************************************** * Set of function to determine, if the click was on an anchor */ @@ -1139,7 +1328,7 @@ typedef struct { } Path_on_anchors_type; /* This is a CurveTraverseFunc */ -static void +void path_tool_on_anchors_helper (Path *path, PathCurve *curve, PathSegment *segment, gpointer ptr) { gint distance; @@ -1161,7 +1350,7 @@ path_tool_on_anchors_helper (Path *path, PathCurve *curve, PathSegment *segment, } } -static gboolean +gboolean path_tool_on_anchors (Tool *tool, gint x, gint y, gint halfwidth, Path **ret_pathP, PathCurve **ret_curveP, PathSegment **ret_segmentP) { Path_on_anchors_type *data = g_new (Path_on_anchors_type, 1); @@ -1200,7 +1389,7 @@ typedef struct { } Path_offset_active_type; /* This is a CurveTraverseFunc */ -static void +void path_offset_active_helper (Path *path, PathCurve *curve, PathSegment *segment, gpointer ptr) { Path_offset_active_type *data = (Path_offset_active_type *) ptr; @@ -1209,9 +1398,10 @@ path_offset_active_helper (Path *path, PathCurve *curve, PathSegment *segment, g segment->x += data->dx; segment->y += data->dy; } +#warning Do a segment_update here! } -static void +void path_offset_active (Path *path, gdouble dx, gdouble dy) { Path_offset_active_type *data = g_new (Path_offset_active_type, 1); @@ -1226,7 +1416,7 @@ path_offset_active (Path *path, gdouble dx, gdouble dy) /************************************************************** - * Set of function to set the state of all anchors to inactive + * Set of function to set the state of all anchors */ typedef struct { @@ -1236,7 +1426,7 @@ typedef struct { } Path_set_flags_type; /* This is a CurveTraverseFunc */ -static void +void path_set_flags_helper (Path *path, PathCurve *curve, PathSegment *segment, gpointer ptr) { Path_set_flags_type *tmp = (Path_set_flags_type *) ptr; @@ -1272,7 +1462,7 @@ path_set_flags_helper (Path *path, PathCurve *curve, PathSegment *segment, gpoin } } -static void +void path_set_flags (PathTool *path_tool, Path *path, PathCurve *curve, PathSegment *segment, guint32 bits_set, guint32 bits_clear) { Path_set_flags_type *tmp = g_new (Path_set_flags_type, 1); @@ -1296,7 +1486,7 @@ path_set_flags (PathTool *path_tool, Path *path, PathCurve *curve, PathSegment * */ /* This is a CurveTraverseFunc */ -static void +void path_tool_draw_helper (Path *path, PathCurve *curve, PathSegment * segment, gpointer tool_ptr) { Tool * tool = (Tool *) tool_ptr; @@ -1335,8 +1525,7 @@ path_tool_draw_helper (Path *path, PathCurve *curve, PathSegment * segment, gpoi if (segment->next) { - gdisplay_transform_coords (gdisp, (gint) segment->next->x, (gint) segment->next->y, &x2, &y2, FALSE); - gdk_draw_line (core->win, core->gc, x1, y1, x2, y2); + path_curve_draw_segment (tool, segment); } } #ifdef PATH_TOOL_DEBUG @@ -1345,7 +1534,7 @@ path_tool_draw_helper (Path *path, PathCurve *curve, PathSegment * segment, gpoi #endif PATH_TOOL_DEBUG } -static void +void path_tool_draw (Tool *tool) { GDisplay * gdisp; @@ -1363,4 +1552,10 @@ path_tool_draw (Tool *tool) path_traverse_path (cur_path, NULL, path_tool_draw_helper, NULL, tool); +#ifdef PATH_TOOL_DEBUG + fprintf (stderr, "path_tool_draw end.\n"); +#endif PATH_TOOL_DEBUG + } + + diff --git a/app/tools/path_tool.h b/app/tools/path_tool.h index 9a21b8e1d1..c80df93fe5 100644 --- a/app/tools/path_tool.h +++ b/app/tools/path_tool.h @@ -1,5 +1,6 @@ /* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This file Copyright (C) 1999 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 @@ -15,6 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + #ifndef __PATH_TOOL_H__ #define __PATH_TOOL_H__ diff --git a/app/tools/path_toolP.h b/app/tools/path_toolP.h index 0c26613b4d..c9c9dd2bbc 100644 --- a/app/tools/path_toolP.h +++ b/app/tools/path_toolP.h @@ -18,6 +18,9 @@ #ifndef __PATH_TOOLP_H__ #define __PATH_TOOLP_H__ +#undef PATH_TOOL_DEBUG + +#include "draw_core.h" #define IMAGE_COORDS 1 #define AA_IMAGE_COORDS 2 @@ -33,12 +36,10 @@ #define SUBDIVIDE 1000 +typedef enum { SEGMENT_LINE=0, SEGMENT_BEZIER} SegmentType; enum { ON_ANCHOR, ON_HANDLE, ON_CURVE, ON_CANVAS }; -typedef enum { SEGMENT_LINE, SEGMENT_BEZIER } SegmentType; - - typedef struct _path_segment PathSegment; typedef struct _path_curve PathCurve; typedef struct _path Path; @@ -82,7 +83,7 @@ struct _path struct _path_tool { - gint click_pos; /* where did the user click? */ + gint click_type; /* where did the user click? */ gint click_x; /* X-coordinate of the click */ gint click_y; /* Y-coordinate of the click */ gint click_halfwidth; @@ -90,6 +91,7 @@ struct _path_tool Path *click_path; /* On which Path/Curve/Segment */ PathCurve *click_curve; /* was the click? */ PathSegment *click_segment; + gdouble click_position; /* The position on the segment */ gint active_count; /* How many segments are active? */ /* @@ -110,6 +112,4 @@ typedef void (*PathTraverseFunc) (Path *, PathCurve *, gpointer); typedef void (*CurveTraverseFunc) (Path *, PathCurve *, PathSegment *, gpointer); typedef void (*SegmentTraverseFunc) (Path *, PathCurve *, PathSegment *, gint, gint, gpointer); -/* typedef void (*SegmentTraverseFunc) (PathTool *, GdkPoint *, gint, gpointer);*/ - #endif /* __PATH_TOOLP_H__ */