diff --git a/ChangeLog b/ChangeLog index f3028d95d0..2ba7344bf7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2003-02-12 Sven Neumann + + * app/Makefile.am + * app/path_bezier.[ch] + * app/path_curves.[ch] + * app/tools/Makefile.am + * app/tools/gimppathtool.[ch] + * app/tools/path_tool.[ch]: removed the abandoned path tool + prototype. + 2003-02-12 Sven Neumann * app/tools/Makefile.am diff --git a/app/Makefile.am b/app/Makefile.am index 522173aab6..5249c471a2 100644 --- a/app/Makefile.am +++ b/app/Makefile.am @@ -52,10 +52,6 @@ bye_sources = \ path.h \ pathP.h \ path_transform.h \ - path_curves.h \ - path_curves.c \ - path_bezier.h \ - path_bezier.c \ undo.c \ undo.h \ undo_types.h diff --git a/app/path_bezier.c b/app/path_bezier.c deleted file mode 100644 index b294d66228..0000000000 --- a/app/path_bezier.c +++ /dev/null @@ -1,277 +0,0 @@ -/* 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 "config.h" - -#include - -#include "libgimpmath/gimpmath.h" - -#include "core/core-types.h" -#include "tools/tools-types.h" - -#include "path_curves.h" -#include "path_bezier.h" - - -#define HANDLE_HALFWIDTH 3 -#define HANDLE_WIDTH 6 - -/* - * 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 (PathSegment *segment, - gfloat *points, - guint npoints, - gdouble start, - gdouble end) -{ - return 0; -} - -void -path_bezier_get_point (PathSegment *segment, - gdouble pos, - gdouble *x, - gdouble *y) -{ - PathBezierData *data = (PathBezierData *) segment->data; - - if (segment->next) { - - *x = (1-pos) * (1-pos) * (1-pos) * segment->x - + 3 * pos * (1-pos) * (1-pos) * (segment->x + data->x1) - + 3 * pos * pos * (1-pos) * (segment->next->x + data->x2) - + pos * pos * pos * (segment->next->x); - - *y = (1-pos) * (1-pos) * (1-pos) * segment->y - + 3 * pos * (1-pos) * (1-pos) * (segment->y + data->y1) - + 3 * pos * pos * (1-pos) * (segment->next->y + data->y2) - + pos * pos * pos * (segment->next->y); - } -#ifdef PATH_TOOL_DEBUG - else fprintf (stderr, "FIXME: path_bezier_get_point called with endpoint-segment!!!\n"); -#endif - - return; -} - -void -path_bezier_draw_handles (GimpDrawTool *tool, - PathSegment *segment) -{ -#if 0 - PathTool *path_tool = (PathTool *) (tool->private); - PathBezierData *data = (PathBezierData *) segment->data; - GimpDisplay * gdisp = tool->gdisp; - - gint sx, sy, hx, hy; - - if (segment->next) { - if (segment->flags & SEGMENT_ACTIVE) { - gdisplay_transform_coords (gdisp, - (gint) (segment->x), (gint) (segment->y), &sx, &sy, FALSE); - gdisplay_transform_coords (gdisp, - (gint) (segment->x + data->x1), - (gint) (segment->y + data->y1), &hx, &hy, FALSE); - - gdk_draw_line (path_tool->core->win, - path_tool->core->gc, hx, hy, sx, sy); - - gdk_draw_rectangle (path_tool->core->win, path_tool->core->gc, 0, - hx - HANDLE_HALFWIDTH, hy - HANDLE_HALFWIDTH, - HANDLE_WIDTH, HANDLE_WIDTH); - } - - if (segment->next->flags & SEGMENT_ACTIVE) { - gdisplay_transform_coords (gdisp, - (gint) (segment->next->x), (gint) (segment->next->y), &sx, &sy, FALSE); - gdisplay_transform_coords (gdisp, - (gint) (segment->next->x + data->x2), - (gint) (segment->next->y + data->y2), &hx, &hy, FALSE); - - gdk_draw_line (path_tool->core->win, - path_tool->core->gc, hx, hy, sx, sy); - - gdk_draw_rectangle (path_tool->core->win, path_tool->core->gc, 0, - hx - HANDLE_HALFWIDTH, hy - HANDLE_HALFWIDTH, - HANDLE_WIDTH, HANDLE_WIDTH); - } - } -#endif -} - -void -path_bezier_draw_segment (GimpDrawTool *tool, - PathSegment *segment) -{ - return; -} - - -gdouble -path_bezier_on_segment (PathSegment *segment, - gint x, - gint y, - gint halfwidth, - gint *distance) -{ - return -1; -} - -void -path_bezier_drag_segment (PathSegment *segment, - gdouble pos, - gdouble dx, - gdouble dy) -{ - PathBezierData *data = (PathBezierData *) segment->data; - gdouble feel_good; - - if (pos <= 0.5) - feel_good = (pow(2 * pos, 3)) / 2; - else - feel_good = (1 - pow((1-pos)*2, 3)) / 2 + 0.5; - - data->x1 += (dx / (3*pos*(1-pos)*(1-pos)))*(1-feel_good); - data->y1 += (dy / (3*pos*(1-pos)*(1-pos)))*(1-feel_good); - data->x2 += (dx / (3*pos*pos*(1-pos)))*feel_good; - data->y2 += (dy / (3*pos*pos*(1-pos)))*feel_good; - - return; -} - -gint -path_bezier_on_handles (PathSegment *segment, - gdouble x, - gdouble y, - gdouble halfwidth) -{ - PathBezierData *data = (PathBezierData *) segment->data; - - if (segment->flags & SEGMENT_ACTIVE && - fabs(segment->x + data->x1 - x) <= halfwidth && - fabs(segment->y + data->y1 - y) <= halfwidth) - return 1; - - if (segment->next && segment->next->flags & SEGMENT_ACTIVE && - fabs(segment->next->x + data->x2 - x) <= halfwidth && - fabs(segment->next->y + data->y2 - y) <= halfwidth) - return 2; - - return 0; -} - -void -path_bezier_drag_handles (PathSegment *segment, - gdouble dx, - gdouble dy, - gint handle_id) -{ - PathBezierData *data = (PathBezierData *) segment->data; - - if (handle_id == 1) { - data->x1 += dx; - data->y1 += dy; - } else { - data->x2 += dx; - data->y2 += dy; - } -} - - -PathSegment * -path_bezier_insert_anchor (PathSegment *segment, - gdouble position) -{ - return NULL; -} - -void -path_bezier_update_segment (PathSegment *segment) -{ - return; -} - - -void -path_bezier_flip_segment (PathSegment *segment) -{ - PathBezierData *data = (PathBezierData *) segment->data; - gdouble swap; - - swap = data->x1; - data->x1 = data->x2; - data->x2 = swap; - - swap = data->y1; - data->y1 = data->y2; - data->y2 = swap; - - return; -} - - -void -path_bezier_init_segment (PathSegment *segment) -{ - PathBezierData *data, *neardata; - - data = g_new(PathBezierData, 1); - data->x1 = 0; - data->y1 = 0; - data->x2 = 0; - data->y2 = 0; - if (segment->prev && segment->prev->type == SEGMENT_BEZIER) { - neardata = (PathBezierData *) segment->prev->data; - data->x1 = - neardata->x2; - data->y1 = - neardata->y2; - } - if (segment->next && segment->next->type == SEGMENT_BEZIER) { - neardata = (PathBezierData *) segment->next->data; - data->x2 = - neardata->x1; - data->y2 = - neardata->y1; - } - -#ifdef PATH_TOOL_DEBUG - if (segment->data) - fprintf(stderr, "Warning: path_bezier_init_segment called with already initialized segment\n"); -#endif - segment->data = data; - - return; -} - - -void -path_bezier_cleanup_segment (PathSegment *segment) -{ - g_free(segment->data); - segment->data = NULL; - - return; -} - - diff --git a/app/path_bezier.h b/app/path_bezier.h deleted file mode 100644 index fc2dcd4219..0000000000 --- a/app/path_bezier.h +++ /dev/null @@ -1,105 +0,0 @@ -/* 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__ - - -typedef struct -{ - gdouble x1; - gdouble y1; - gdouble x2; - gdouble y2; -} PathBezierData; - - -guint -path_bezier_get_points (PathSegment *segment, - gfloat *points, - guint npoints, - gdouble start, - gdouble end); - -void -path_bezier_get_point (PathSegment *segment, - gdouble position, - gdouble *x, - gdouble *y); - -void -path_bezier_draw_handles (GimpDrawTool *tool, - PathSegment *segment); - -void -path_bezier_draw_segment (GimpDrawTool *tool, - PathSegment *segment); - -gdouble -path_bezier_on_segment (PathSegment *segment, - gint x, - gint y, - gint halfwidth, - gint *distance); - -void -path_bezier_drag_segment (PathSegment *segment, - gdouble position, - gdouble dx, - gdouble dy); - -gint -path_bezier_on_handles (PathSegment *segment, - gdouble x, - gdouble y, - gdouble halfwidth); - -void -path_bezier_drag_handles (PathSegment *segment, - gdouble dx, - gdouble dy, - gint handle_id); - -PathSegment * -path_bezier_insert_anchor (PathSegment *segment, - gdouble position); - -void -path_bezier_update_segment (PathSegment *segment); - -void -path_bezier_flip_segment (PathSegment *segment); - -void -path_bezier_init_segment (PathSegment *segment); - -void -path_bezier_cleanup_segment (PathSegment *segment); - -#endif /* __PATH_BEZIER_H__ */ - - diff --git a/app/path_curves.c b/app/path_curves.c deleted file mode 100644 index 3ac3a90bfd..0000000000 --- a/app/path_curves.c +++ /dev/null @@ -1,321 +0,0 @@ -/* 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 "config.h" - -#include - -#include "libgimpmath/gimpmath.h" - -#include "core/core-types.h" -#include "tools/tools-types.h" - -#include "path_curves.h" -#include "path_bezier.h" - -#include "tools/gimpdrawtool.h" - - -/* 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, NULL, NULL - }, - - /* SEGMENT_BEZIER */ - { - NULL, /* path_bezier_get_points, */ - path_bezier_get_point, - NULL, /* path_bezier_draw_handles, */ - NULL, /* path_bezier_draw_segment, */ - NULL, /* path_bezier_on_segment, */ - path_bezier_drag_segment, - path_bezier_on_handles, - path_bezier_drag_handles, - NULL, /* path_bezier_insert_anchor, */ - NULL, /* path_bezier_update_segment, */ - path_bezier_flip_segment, - path_bezier_init_segment, - NULL /* path_bezier_cleanup_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 (PathSegment *segment, - gdouble *points, - guint npoints, - gdouble start, - gdouble end) -{ - gdouble pos; - - gint index=0; - - if (segment && segment->next) { - if (CurveTypes[segment->type].get_points) - return (* CurveTypes[segment->type].get_points) (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 (segment, pos, &points[index*2], - &points[index*2+1]); - index++; - } - return index; - } else - return 0; - } - } -#ifdef PATH_TOOL_DEBUG - else - fprintf (stderr, "path_curve_get_points called without valid curve"); -#endif - return 0; -} - - -void -path_curve_get_point (PathSegment *segment, - gdouble position, - gdouble *x, - gdouble *y) -{ - if (segment && segment->next) { - if (CurveTypes[segment->type].get_point) - (* CurveTypes[segment->type].get_point) (segment, position, x, y); - else { -#if 1 - *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 with 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 (GimpDrawTool *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 (GimpDrawTool *tool, - PathSegment *segment) -{ - gint num_pts; - - if (segment && segment->next) { - if (CurveTypes[segment->type].draw_segment) { - (* CurveTypes[segment->type].draw_segment) (tool, segment); - return; - } else { - gdouble *coordinates = g_new (gdouble, 200); - num_pts = path_curve_get_points (segment, coordinates, 100, 0, 1); - gimp_draw_tool_draw_lines (tool, coordinates, num_pts, FALSE, FALSE); - 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 (PathSegment *segment, - gint x, - gint y, - gint halfwidth, - gint *distance) -{ - - if (segment && CurveTypes[segment->type].on_segment) - return (* CurveTypes[segment->type].on_segment) (segment, x, y, halfwidth, distance); - else { - if (segment && segment->next) { -#if 1 - gint x1, y1, numpts, index; - gdouble *coordinates; - gint bestindex = -1; - - coordinates = g_new (gdouble, 200); - *distance = halfwidth * halfwidth + 1; - - numpts = path_curve_get_points (segment, coordinates, 100, 0, 1); - for (index=0; index < numpts; index++) { - x1 = coordinates[2*index]; - y1 = coordinates[2*index+1]; - 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 (PathSegment *segment, - gdouble position, - gdouble dx, - gdouble dy) -{ - if (segment && CurveTypes[segment->type].drag_segment) - (* CurveTypes[segment->type].drag_segment) (segment, position, dx, dy); - return; -} - -gint -path_curve_on_handle (PathSegment *segment, - gdouble x, - gdouble y, - gdouble halfwidth) -{ - if (segment && CurveTypes[segment->type].on_handles) - return (* CurveTypes[segment->type].on_handles) (segment, x, y, halfwidth); - return FALSE; -} - -void -path_curve_drag_handle (PathSegment *segment, - gdouble dx, - gdouble dy, - gint handle_id) -{ - if (segment && CurveTypes[segment->type].drag_handle) - (* CurveTypes[segment->type].drag_handle) (segment, dx, dy, handle_id); -} - -PathSegment * -path_curve_insert_anchor (PathSegment *segment, - gdouble position) -{ - if (segment && CurveTypes[segment->type].insert_anchor) - return (* CurveTypes[segment->type].insert_anchor) (segment, position); - else { - return path_split_segment (segment, position); - } -} - -void -path_curve_flip_segment (PathSegment *segment) -{ - if (segment && CurveTypes[segment->type].flip_segment) - (* CurveTypes[segment->type].flip_segment) (segment); - return; -} - -void -path_curve_update_segment (PathSegment *segment) -{ - if (segment && CurveTypes[segment->type].update_segment) - (* CurveTypes[segment->type].update_segment) (segment); - return; -} - -void -path_curve_init_segment (PathSegment *segment) -{ - if (segment && CurveTypes[segment->type].init_segment) - (* CurveTypes[segment->type].init_segment) (segment); - return; -} - -void -path_curve_cleanup_segment (PathSegment *segment) -{ - if (segment && CurveTypes[segment->type].cleanup_segment) - (* CurveTypes[segment->type].cleanup_segment) (segment); - return; -} - diff --git a/app/path_curves.h b/app/path_curves.h deleted file mode 100644 index 34dfd1c932..0000000000 --- a/app/path_curves.h +++ /dev/null @@ -1,271 +0,0 @@ -/* 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__ - -#define PATH_TOOL_DEBUG -#ifdef PATH_TOOL_DEBUG -#include -#endif - -#define IMAGE_COORDS 1 -#define AA_IMAGE_COORDS 2 -#define SCREEN_COORDS 3 - -#define SEGMENT_ACTIVE 1 - -#define PATH_TOOL_DRAG 1 - -#define PATH_TOOL_REDRAW_ALL 1 -#define PATH_TOOL_REDRAW_ACTIVE 2 -#define PATH_TOOL_REDRAW_HANDLES 4 - -#define SUBDIVIDE 1000 - -typedef enum { SEGMENT_LINE=0, SEGMENT_BEZIER} SegmentType; - -enum { ON_ANCHOR, ON_HANDLE, ON_CURVE, ON_CANVAS }; - -typedef struct _path_segment PathSegment; -typedef struct _path_curve PathCurve; -typedef struct _npath NPath; - - -struct _path_segment -{ - SegmentType type; /* What type of segment */ - gdouble x, y; /* location of starting-point in image space */ - gpointer data; /* Additional data, dependant of segment-type */ - - guint32 flags; /* Various Flags: Is the Segment active? */ - - PathCurve *parent; /* the parent Curve */ - PathSegment *next; /* Next Segment or NULL */ - PathSegment *prev; /* Previous Segment or NULL */ - -}; - - -struct _path_curve -{ - PathSegment *segments; /* The segments of the curve */ - PathSegment *cur_segment; /* the current segment */ - NPath *parent; /* the parent Path */ - PathCurve *next; /* Next Curve or NULL */ - PathCurve *prev; /* Previous Curve or NULL */ -}; - - -struct _npath -{ - PathCurve *curves; /* the curves */ - PathCurve *cur_curve; /* the current curve */ - GString *name; /* the name of the path */ - guint32 state; /* is the path locked? */ - /* GimpPathTool *path_tool; */ /* The parent Path Tool */ -}; - - -typedef void -(*PathTraverseFunc) (NPath *, - PathCurve *, - gpointer); -typedef void -(*CurveTraverseFunc) (NPath *, - PathCurve *, - PathSegment *, - gpointer); -typedef void -(*SegmentTraverseFunc) (NPath *, - PathCurve *, - PathSegment *, - gint, - gint, - gpointer); - - -/* - * 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) (PathSegment *segment, - gdouble *points, - guint npoints, - gdouble start, - gdouble end); - -typedef void (*PathGetPointFunc) (PathSegment *segment, - gdouble position, - gdouble *x, - gdouble *y); - -typedef void (*PathDrawHandlesFunc) (GimpDrawTool *tool, - PathSegment *segment); - -typedef void (*PathDrawSegmentFunc) (GimpDrawTool *tool, - PathSegment *segment); - - -typedef gdouble (*PathOnSegmentFunc) (PathSegment *segment, - gint x, - gint y, - gint halfwidth, - gint *distance); - -typedef void (*PathDragSegmentFunc) (PathSegment *segment, - gdouble position, - gdouble dx, - gdouble dy); - -typedef gint (*PathOnHandlesFunc) (PathSegment *segment, - gdouble x, - gdouble y, - gdouble halfwidth); - -typedef void (*PathDragHandleFunc) (PathSegment *segment, - gdouble dx, - gdouble dy, - gint handle_id); - -typedef PathSegment * (*PathInsertAnchorFunc) (PathSegment *segment, - gdouble position); - -typedef void (*PathUpdateSegmentFunc) (PathSegment *segment); - -typedef void (*PathFlipSegmentFunc) (PathSegment *segment); - -typedef void (*PathInitSegmentFunc) (PathSegment *segment); - -typedef void (*PathCleanupSegmentFunc) (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; - PathInitSegmentFunc init_segment; - PathCleanupSegmentFunc cleanup_segment; -} CurveDescription; - - -guint -path_curve_get_points (PathSegment *segment, - gdouble *points, - guint npoints, - gdouble start, - gdouble end); - -void -path_curve_get_point (PathSegment *segment, - gdouble position, - gdouble *x, - gdouble *y); - -void -path_curve_draw_handles (GimpDrawTool *tool, - PathSegment *segment); - -void -path_curve_draw_segment (GimpDrawTool *tool, - PathSegment *segment); - - -gdouble -path_curve_on_segment (PathSegment *segment, - gint x, - gint y, - gint halfwidth, - gint *distance); - -void -path_curve_drag_segment (PathSegment *segment, - gdouble position, - gdouble dx, - gdouble dy); - -gint -path_curve_on_handle (PathSegment *segment, - gdouble x, - gdouble y, - gdouble halfwidth); - -void -path_curve_drag_handle (PathSegment *segment, - gdouble dx, - gdouble dy, - gint handle_id); - -PathSegment * -path_curve_insert_anchor (PathSegment *segment, - gdouble position); - -void -path_curve_update_segment (PathSegment *segment); - -void -path_curve_flip_segment (PathSegment *segment); - -void -path_curve_init_segment (PathSegment *segment); - -void -path_curve_cleanup_segment (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/tools/Makefile.am b/app/tools/Makefile.am index c445b1adc0..1ee817294f 100644 --- a/app/tools/Makefile.am +++ b/app/tools/Makefile.am @@ -88,8 +88,6 @@ libapptools_a_SOURCES = \ gimppaintbrushtool.h \ gimppainttool.c \ gimppainttool.h \ - gimppathtool.c \ - gimppathtool.h \ gimppenciltool.c \ gimppenciltool.h \ gimpperspectivetool.c \ @@ -134,9 +132,7 @@ libapptools_a_SOURCES = \ tool_options.c \ tool_options.h \ tool_manager.c \ - tool_manager.h \ - path_tool.h \ - path_tool.c + tool_manager.h AM_CPPFLAGS = \ -DG_LOG_DOMAIN=\"Gimp-Tools\" \ diff --git a/app/tools/gimppathtool.c b/app/tools/gimppathtool.c deleted file mode 100644 index dd6ea4ecd6..0000000000 --- a/app/tools/gimppathtool.c +++ /dev/null @@ -1,890 +0,0 @@ -/* 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 "config.h" - -#include - -#include "libgimpmath/gimpmath.h" -#include "libgimpwidgets/gimpwidgets.h" - -#include "tools-types.h" - -#include "core/gimpimage.h" - -#include "display/gimpdisplay.h" -#include "display/gimpdisplayshell.h" - -#include "gimppathtool.h" -#include "path_tool.h" - -#include "path_curves.h" - -#include "libgimp/gimpintl.h" - - -/* local function prototypes */ - -static void gimp_path_tool_class_init (GimpPathToolClass *klass); -static void gimp_path_tool_init (GimpPathTool *tool); - -static void gimp_path_tool_finalize (GObject *object); - -static void gimp_path_tool_control (GimpTool *tool, - GimpToolAction action, - GimpDisplay *gdisp); - -static void gimp_path_tool_button_press (GimpTool *tool, - GimpCoords *coords, - guint32 time, - GdkModifierType state, - GimpDisplay *gdisp); -static gint gimp_path_tool_button_press_canvas (GimpPathTool *tool, - guint32 time, - GimpDisplay *gdisp); -static gint gimp_path_tool_button_press_anchor (GimpPathTool *tool, - guint32 time, - GimpDisplay *gdisp); -static gint gimp_path_tool_button_press_handle (GimpPathTool *tool, - guint32 time, - GimpDisplay *gdisp); -static gint gimp_path_tool_button_press_curve (GimpPathTool *tool, - guint32 time, - GimpDisplay *gdisp); - -static void gimp_path_tool_button_release (GimpTool *tool, - GimpCoords *coords, - guint32 time, - GdkModifierType state, - GimpDisplay *gdisp); - -static void gimp_path_tool_motion (GimpTool *tool, - GimpCoords *coords, - guint32 time, - GdkModifierType state, - GimpDisplay *gdisp); -static void gimp_path_tool_motion_anchor (GimpPathTool *path_tool, - GimpCoords *coords, - GdkModifierType state, - GimpDisplay *gdisp); -static void gimp_path_tool_motion_handle (GimpPathTool *path_tool, - GimpCoords *coords, - GdkModifierType state, - GimpDisplay *gdisp); -static void gimp_path_tool_motion_curve (GimpPathTool *path_tool, - GimpCoords *coords, - GdkModifierType state, - GimpDisplay *gdisp); - -static void gimp_path_tool_cursor_update (GimpTool *tool, - GimpCoords *coords, - GdkModifierType state, - GimpDisplay *gdisp); - -static void gimp_path_tool_draw (GimpDrawTool *draw_tool); - - - -static GimpDrawToolClass *parent_class = NULL; - - -void -gimp_path_tool_register (GimpToolRegisterCallback callback, - gpointer data) -{ - (* callback) (GIMP_TYPE_PATH_TOOL, - G_TYPE_NONE, NULL, - FALSE, - "gimp-path-tool", - _("Path"), - _("Path tool prototype"), - N_("/Tools/Path"), NULL, - NULL, "tools/path.html", - GIMP_STOCK_TOOL_PATH, - data); -} - -GType -gimp_path_tool_get_type (void) -{ - static GType tool_type = 0; - - if (! tool_type) - { - static const GTypeInfo tool_info = - { - sizeof (GimpPathToolClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) gimp_path_tool_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (GimpPathTool), - 0, /* n_preallocs */ - (GInstanceInitFunc) gimp_path_tool_init, - }; - - tool_type = g_type_register_static (GIMP_TYPE_DRAW_TOOL, - "GimpPathTool", - &tool_info, 0); - } - - return tool_type; -} - -static void -gimp_path_tool_class_init (GimpPathToolClass *klass) -{ - GObjectClass *object_class; - GimpToolClass *tool_class; - GimpDrawToolClass *draw_tool_class; - - object_class = G_OBJECT_CLASS (klass); - tool_class = GIMP_TOOL_CLASS (klass); - draw_tool_class = GIMP_DRAW_TOOL_CLASS (klass); - - parent_class = g_type_class_peek_parent (klass); - - object_class->finalize = gimp_path_tool_finalize; - - tool_class->control = gimp_path_tool_control; - tool_class->button_press = gimp_path_tool_button_press; - tool_class->button_release = gimp_path_tool_button_release; - tool_class->motion = gimp_path_tool_motion; - tool_class->cursor_update = gimp_path_tool_cursor_update; - - draw_tool_class->draw = gimp_path_tool_draw; -} - -static void -gimp_path_tool_init (GimpPathTool *path_tool) -{ - GimpTool *tool; - - tool = GIMP_TOOL (path_tool); - - path_tool->click_type = ON_CANVAS; - path_tool->click_x = 0; - path_tool->click_y = 0; - path_tool->click_halfwidth = 0; - path_tool->click_modifier = 0; - path_tool->click_path = NULL; - path_tool->click_curve = NULL; - path_tool->click_segment = NULL; - path_tool->click_position = -1; - - path_tool->active_count = 0; - path_tool->single_active_segment = NULL; - - path_tool->state = 0; - path_tool->draw = PATH_TOOL_REDRAW_ALL; - path_tool->cur_path = g_new0 (NPath, 1); - path_tool->scanlines = NULL; - - - /* Initial Path */ - path_tool->cur_path->curves = NULL; - path_tool->cur_path->cur_curve = NULL; - path_tool->cur_path->name = g_string_new ("Path 0"); - path_tool->cur_path->state = 0; - /* path_tool->cur_path->path_tool = path_tool; */ - -} - -static void -gimp_path_tool_finalize (GObject *object) -{ - GimpPathTool *path_tool; - - path_tool = GIMP_PATH_TOOL (object); - -#ifdef PATH_TOOL_DEBUG - g_printerr ("gimp_path_tool_free start\n"); -#endif - - if (path_tool->cur_path) - { - path_free_path (path_tool->cur_path); - path_tool->cur_path = NULL; - } - - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -gimp_path_tool_control (GimpTool *tool, - GimpToolAction action, - GimpDisplay *gdisp) -{ - GimpPathTool *path_tool; - -#ifdef PATH_TOOL_DEBUG - g_printerr ("path_tool_control\n"); -#endif - - path_tool = GIMP_PATH_TOOL (tool); - - switch (action) - { - case PAUSE: - break; - - case RESUME: - break; - - case HALT: - gimp_tool_control_halt (tool->control); - break; - - default: - break; - } - - GIMP_TOOL_CLASS (parent_class)->control (tool, action, gdisp); -} - -static void -gimp_path_tool_button_press (GimpTool *tool, - GimpCoords *coords, - guint32 time, - GdkModifierType state, - GimpDisplay *gdisp) -{ - GimpPathTool *path_tool; - GimpDisplayShell *shell; - gint grab_pointer = 0; - gint halfwidth, halfheight; - - path_tool = GIMP_PATH_TOOL (tool); - - shell = GIMP_DISPLAY_SHELL (gdisp->shell); - -#ifdef PATH_TOOL_DEBUG - g_printerr ("path_tool_button_press\n"); -#endif - - path_tool->click_x = coords->x; - path_tool->click_y = coords->y; - path_tool->click_modifier = state; - - /* get halfwidth in image coord */ - halfwidth = UNSCALEX (shell, PATH_TOOL_HALFWIDTH); - halfheight = UNSCALEY (shell, PATH_TOOL_HALFWIDTH); - - path_tool->click_halfwidth = halfwidth; - path_tool->click_halfheight = halfheight; - - tool->gdisp = gdisp; - gimp_tool_control_activate (tool->control); - - if (! path_tool->cur_path->curves) - gimp_draw_tool_start (GIMP_DRAW_TOOL (tool), gdisp); - - /* determine point, where clicked, - * switch accordingly. - */ - - path_tool->click_type = - path_tool_cursor_position (path_tool->cur_path, - coords->x, - coords->y, - halfwidth, - halfheight, - &path_tool->click_path, - &path_tool->click_curve, - &path_tool->click_segment, - &path_tool->click_position, - &path_tool->click_handle_id); - - switch (path_tool->click_type) - { - case ON_CANVAS: - grab_pointer = gimp_path_tool_button_press_canvas (path_tool, time, gdisp); - break; - - case ON_ANCHOR: - grab_pointer = gimp_path_tool_button_press_anchor (path_tool, time, gdisp); - break; - - case ON_HANDLE: - grab_pointer = gimp_path_tool_button_press_handle (path_tool, time, gdisp); - break; - - case ON_CURVE: - grab_pointer = gimp_path_tool_button_press_curve (path_tool, time, gdisp); - break; - - default: - g_message ("Huh? Whats happening here? (button_press_*)"); - } -} - -static gint -gimp_path_tool_button_press_anchor (GimpPathTool *path_tool, - guint32 time, - GimpDisplay *gdisp) -{ - static guint32 last_click_time=0; - gboolean doubleclick=FALSE; - - NPath * cur_path = path_tool->cur_path; - PathSegment *p_sas; - gint grab_pointer; - -#ifdef PATH_TOOL_DEBUG - g_printerr ("path_tool_button_press_anchor:\n"); -#endif - - grab_pointer = 1; - - if (!cur_path) { -#ifdef PATH_TOOL_DEBUG - g_printerr ("Fatal error: No current Path\n"); -#endif - return 0; - } - - /* - * We have to determine, if this was a doubleclick for ourself, because - * disp_callback.c ignores the GDK_[23]BUTTON_EVENT's and adding them to - * the switch statement confuses some tools. - */ - if (time - last_click_time < 250) { - doubleclick=TRUE; -#ifdef PATH_TOOL_DEBUG - g_printerr ("Doppelclick!\n"); -#endif - } else - doubleclick=FALSE; - last_click_time = time; - - - gimp_draw_tool_pause (GIMP_DRAW_TOOL(path_tool)); - - /* The user pressed on an anchor: - * normally this activates this anchor - * + SHIFT toggles the activity of an anchor. - * if this anchor is at the end of an open curve and the other - * end is active, close the curve. - * - * Doubleclick (de)activates the whole curve (not Path!). - */ - - p_sas = path_tool->single_active_segment; - -#ifdef PATH_TOOL_DEBUG - g_printerr ("p_sas: %p\n", p_sas); -#endif - - if (path_tool->click_modifier & GDK_SHIFT_MASK) { - if (path_tool->active_count == 1 && p_sas && p_sas != path_tool->click_segment && - (p_sas->next == NULL || p_sas->prev == NULL) && - (path_tool->click_segment->next == NULL || path_tool->click_segment->prev == NULL)) { - /* - * if this is the end of an open curve and the single active segment was another - * open end, connect those ends. - */ - path_join_curves (path_tool->click_segment, p_sas); - path_set_flags (path_tool, path_tool->click_path, path_tool->click_curve, - NULL, 0, SEGMENT_ACTIVE); - } - - if (doubleclick) - /* - * Doubleclick set the whole curve to the same state, depending on the - * state of the clicked anchor. - */ - if (path_tool->click_segment->flags & SEGMENT_ACTIVE) - path_set_flags (path_tool, path_tool->click_path, path_tool->click_curve, - NULL, SEGMENT_ACTIVE, 0); - else - path_set_flags (path_tool, path_tool->click_path, path_tool->click_curve, - NULL, 0, SEGMENT_ACTIVE); - else - /* - * Toggle the state of the clicked anchor. - */ - if (path_tool->click_segment->flags & SEGMENT_ACTIVE) - path_set_flags (path_tool, path_tool->click_path, path_tool->click_curve, - path_tool->click_segment, 0, SEGMENT_ACTIVE); - else - path_set_flags (path_tool, path_tool->click_path, path_tool->click_curve, - path_tool->click_segment, SEGMENT_ACTIVE, 0); - } - /* - * Delete anchors, when CONTROL is pressed - */ - else if (path_tool->click_modifier & GDK_CONTROL_MASK) - { - if (path_tool->click_segment->flags & SEGMENT_ACTIVE) - { - if (path_tool->click_segment->prev) - path_set_flags (path_tool, path_tool->click_path, path_tool->click_curve, - path_tool->click_segment->prev, SEGMENT_ACTIVE, 0); - else if (path_tool->click_segment->next) - path_set_flags (path_tool, path_tool->click_path, path_tool->click_curve, - path_tool->click_segment->next, SEGMENT_ACTIVE, 0); - } - - 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)) - { - path_set_flags (path_tool, cur_path, NULL, NULL, 0, SEGMENT_ACTIVE); - path_set_flags (path_tool, cur_path, path_tool->click_curve, path_tool->click_segment, SEGMENT_ACTIVE, 0); - } - - - gimp_draw_tool_resume (GIMP_DRAW_TOOL(path_tool)); - - return grab_pointer; -} - - -static gint -gimp_path_tool_button_press_handle (GimpPathTool *path_tool, - guint32 time, - GimpDisplay *gdisp) -{ - static guint32 last_click_time=0; - gboolean doubleclick=FALSE; - - NPath * cur_path = path_tool->cur_path; - gint grab_pointer; - -#ifdef PATH_TOOL_DEBUG - g_printerr ("path_tool_button_press_handle:\n"); -#endif - - grab_pointer = 1; - - if (!cur_path) { -#ifdef PATH_TOOL_DEBUG - g_printerr ("Fatal error: No current Path\n"); -#endif - return 0; - } - - /* gint click_halfwidth; - - * We have to determine, if this was a doubleclick for ourself, because - * disp_callback.c ignores the GDK_[23]BUTTON_EVENT's and adding them to - * the switch statement confuses some tools. - */ - if (time - last_click_time < 250) { - doubleclick=TRUE; -#ifdef PATH_TOOL_DEBUG - g_printerr ("Doppelclick!\n"); -#endif - } else - doubleclick=FALSE; - last_click_time = time; - - return grab_pointer; -} - -static gint -gimp_path_tool_button_press_canvas (GimpPathTool *path_tool, - guint32 time, - GimpDisplay *gdisp) -{ - NPath * cur_path = path_tool->cur_path; - PathCurve * cur_curve; - PathSegment * cur_segment; - gint grab_pointer; - -#ifdef PATH_TOOL_DEBUG - g_printerr ("path_tool_button_press_canvas:\n"); -#endif - - grab_pointer = 1; - - if (!cur_path) { -#ifdef PATH_TOOL_DEBUG - g_printerr ("Fatal error: No current Path\n"); -#endif - return 0; - } - - gimp_draw_tool_pause (GIMP_DRAW_TOOL(path_tool)); - - if (path_tool->active_count == 1 && path_tool->single_active_segment != NULL - && (path_tool->single_active_segment->prev == NULL || path_tool->single_active_segment->next == NULL)) { - cur_segment = path_tool->single_active_segment; - cur_curve = cur_segment->parent; - - path_set_flags (path_tool, cur_path, NULL, NULL, 0, SEGMENT_ACTIVE); - - if (cur_segment->next == NULL) - cur_curve->cur_segment = path_append_segment (cur_path, cur_curve, SEGMENT_BEZIER, path_tool->click_x, path_tool->click_y); - else - cur_curve->cur_segment = path_prepend_segment (cur_path, cur_curve, SEGMENT_BEZIER, path_tool->click_x, path_tool->click_y); - if (cur_curve->cur_segment) { - path_set_flags (path_tool, cur_path, cur_curve, cur_curve->cur_segment, SEGMENT_ACTIVE, 0); - } - } else { - if (path_tool->active_count == 0) { - path_set_flags (path_tool, cur_path, NULL, NULL, 0, SEGMENT_ACTIVE); - cur_path->cur_curve = path_add_curve (cur_path, path_tool->click_x, path_tool->click_y); - path_set_flags (path_tool, cur_path, cur_path->cur_curve, cur_path->cur_curve->segments, SEGMENT_ACTIVE, 0); - } else { - path_set_flags (path_tool, cur_path, NULL, NULL, 0, SEGMENT_ACTIVE); - } - } - - gimp_draw_tool_resume (GIMP_DRAW_TOOL(path_tool)); - - return 0; -} - -static gint -gimp_path_tool_button_press_curve (GimpPathTool *path_tool, - guint32 time, - GimpDisplay *gdisp) -{ - NPath * cur_path = path_tool->cur_path; - PathSegment * cur_segment; - gint grab_pointer; - -#ifdef PATH_TOOL_DEBUG - g_printerr ("path_tool_button_press_curve:\n"); -#endif - - grab_pointer = 1; - - if (!cur_path) { -#ifdef PATH_TOOL_DEBUG - g_printerr ("Fatal error: No current NPath\n"); -#endif - return 0; - } - - gimp_draw_tool_pause (GIMP_DRAW_TOOL(path_tool)); - - if (path_tool->click_modifier & GDK_SHIFT_MASK) { - cur_segment = path_curve_insert_anchor (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; - - } else { - path_set_flags (path_tool, cur_path, NULL, NULL, 0, SEGMENT_ACTIVE); - path_set_flags (path_tool, cur_path, path_tool->click_curve, path_tool->click_segment, SEGMENT_ACTIVE, 0); - path_set_flags (path_tool, cur_path, path_tool->click_curve, path_tool->click_segment->next, SEGMENT_ACTIVE, 0); - } - gimp_draw_tool_resume (GIMP_DRAW_TOOL(path_tool)); - - return 0; -} - - -static void -gimp_path_tool_button_release (GimpTool *tool, - GimpCoords *coords, - guint32 time, - GdkModifierType state, - GimpDisplay *gdisp) -{ - GimpPathTool *path_tool; - - path_tool = GIMP_PATH_TOOL (tool); - -#ifdef PATH_TOOL_DEBUG - g_printerr ("path_tool_button_release\n"); -#endif - - path_tool->state &= ~PATH_TOOL_DRAG; -} - - -static void -gimp_path_tool_motion (GimpTool *tool, - GimpCoords *coords, - guint32 time, - GdkModifierType state, - GimpDisplay *gdisp) -{ - GimpPathTool *path_tool; - - path_tool = GIMP_PATH_TOOL (tool); - - switch (path_tool->click_type) - { - case ON_ANCHOR: - gimp_path_tool_motion_anchor (path_tool, coords, state, gdisp); - break; - case ON_HANDLE: - gimp_path_tool_motion_handle (path_tool, coords, state, gdisp); - break; - case ON_CURVE: - gimp_path_tool_motion_curve (path_tool, coords, state, gdisp); - break; - default: - return; - } -} - - -static void -gimp_path_tool_motion_anchor (GimpPathTool *path_tool, - GimpCoords *coords, - GdkModifierType state, - GimpDisplay *gdisp) -{ - static gdouble dxsum = 0; - static gdouble dysum = 0; - - gdouble dx, dy, d; - - /* Dont do anything, if the user clicked with pressed CONTROL-Key, - * because he deleted an anchor. - */ - if (path_tool->click_modifier & GDK_CONTROL_MASK) - return; - - if (! (path_tool->state & PATH_TOOL_DRAG)) - { - path_tool->state |= PATH_TOOL_DRAG; - dxsum = 0; - dysum = 0; - } - - dx = coords->x - path_tool->click_x - dxsum; - dy = coords->y - path_tool->click_y - dysum; - - /* restrict to horizontal/vertical lines, if modifiers are pressed - * I'm not sure, if this is intuitive for the user. Esp. When moving - * an endpoint of an curve I'd expect, that the *line* is - * horiz/vertical - not the delta to the point, where the point was - * originally... - */ - if (state & GDK_MOD1_MASK) - { - if (state & GDK_CONTROL_MASK) - { - d = (fabs (dx) + fabs (dy)) / 2; - d = (fabs (coords->x - path_tool->click_x) + - fabs (coords->y - path_tool->click_y)) / 2; - dx = ((coords->x < path_tool->click_x) ? -d : d ) - dxsum; - dy = ((coords->y < path_tool->click_y) ? -d : d ) - dysum; - } - else - { - dx = - dxsum; - } - } - else if (state & GDK_CONTROL_MASK) - { - dy = - dysum; - } - - path_tool->draw |= PATH_TOOL_REDRAW_ACTIVE; - - gimp_draw_tool_pause (GIMP_DRAW_TOOL (path_tool)); - - path_offset_active (path_tool->cur_path, dx, dy); - - dxsum += dx; - dysum += dy; - - gimp_draw_tool_resume (GIMP_DRAW_TOOL (path_tool)); - - path_tool->draw &= ~PATH_TOOL_REDRAW_ACTIVE; -} - -static void -gimp_path_tool_motion_handle (GimpPathTool *path_tool, - GimpCoords *coords, - GdkModifierType state, - GimpDisplay *gdisp) -{ - static gdouble dxsum = 0; - static gdouble dysum = 0; - - gdouble dx, dy; - - /* Dont do anything, if the user clicked with pressed CONTROL-Key, - * because he moved the handle to the anchor an anchor. - * XXX: Not yet! :-) - */ - if (path_tool->click_modifier & GDK_CONTROL_MASK) - return; - - if (! (path_tool->state & PATH_TOOL_DRAG)) - { - path_tool->state |= PATH_TOOL_DRAG; - dxsum = 0; - dysum = 0; - } - - dx = coords->x - path_tool->click_x - dxsum; - dy = coords->y - path_tool->click_y - dysum; - - path_tool->draw |= PATH_TOOL_REDRAW_ACTIVE; - - gimp_draw_tool_pause (GIMP_DRAW_TOOL (path_tool)); - - path_curve_drag_handle (path_tool->click_segment, - dx, dy, - path_tool->click_handle_id); - - dxsum += dx; - dysum += dy; - - gimp_draw_tool_resume (GIMP_DRAW_TOOL (path_tool)); - - path_tool->draw &= ~PATH_TOOL_REDRAW_ACTIVE; -} - -static void -gimp_path_tool_motion_curve (GimpPathTool *path_tool, - GimpCoords *coords, - GdkModifierType state, - GimpDisplay *gdisp) -{ - static gdouble dxsum = 0; - static gdouble dysum = 0; - - gdouble dx, dy; - - if (! (path_tool->state & PATH_TOOL_DRAG)) - { - path_tool->state |= PATH_TOOL_DRAG; - dxsum = 0; - dysum = 0; - } - - dx = coords->x - path_tool->click_x - dxsum; - dy = coords->y - path_tool->click_y - dysum; - - path_tool->draw |= PATH_TOOL_REDRAW_ACTIVE; - - gimp_draw_tool_pause (GIMP_DRAW_TOOL (path_tool)); - - path_curve_drag_segment (path_tool->click_segment, - path_tool->click_position, - dx, dy); - - dxsum += dx; - dysum += dy; - - gimp_draw_tool_resume (GIMP_DRAW_TOOL (path_tool)); - - path_tool->draw &= ~PATH_TOOL_REDRAW_ACTIVE; -} - -static void -gimp_path_tool_cursor_update (GimpTool *tool, - GimpCoords *coords, - GdkModifierType state, - GimpDisplay *gdisp) -{ - GimpCursorModifier cmodifier = GIMP_CURSOR_MODIFIER_NONE; - gint cursor_location; - - cursor_location = path_tool_cursor_position (GIMP_PATH_TOOL (tool)->cur_path, - coords->x, - coords->y, - PATH_TOOL_HALFWIDTH, - PATH_TOOL_HALFWIDTH, - NULL, NULL, NULL, NULL, NULL); - - /* FIXME: add GIMP_PATH_TOOL_CURSOR */ - - switch (cursor_location) - { - case ON_CANVAS: - cmodifier = GIMP_CURSOR_MODIFIER_PLUS; - break; - case ON_ANCHOR: - cmodifier = GIMP_CURSOR_MODIFIER_MOVE; - break; - case ON_HANDLE: - cmodifier = GIMP_CURSOR_MODIFIER_MOVE; - break; - case ON_CURVE: - cmodifier = GIMP_CURSOR_MODIFIER_NONE; - break; - default: - g_warning ("gimp_path_tool_cursor_update(): bad cursor_location"); - break; - } - - gimp_tool_control_set_cursor_modifier (tool->control, cmodifier); - - GIMP_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, gdisp); -} - - -/* This is a CurveTraverseFunc */ -static void -gimp_path_tool_draw_helper (NPath *path, - PathCurve *curve, - PathSegment *segment, - gpointer tool) -{ - GimpPathTool *path_tool; - GimpDrawTool *draw_tool; - gboolean draw = TRUE; - - path_tool = GIMP_PATH_TOOL (tool); - draw_tool = GIMP_DRAW_TOOL (tool); - - if (path_tool->draw & PATH_TOOL_REDRAW_ACTIVE) - draw = (segment->flags & SEGMENT_ACTIVE || - (segment->next && segment->next->flags & SEGMENT_ACTIVE)); - - if (segment->flags & SEGMENT_ACTIVE) - { - gimp_draw_tool_draw_handle (draw_tool, - GIMP_HANDLE_CIRCLE, - segment->x, segment->y, - PATH_TOOL_WIDTH, - PATH_TOOL_WIDTH, - GTK_ANCHOR_CENTER, - FALSE); - } - else - { - gimp_draw_tool_draw_handle (draw_tool, - GIMP_HANDLE_FILLED_CIRCLE, - segment->x, segment->y, - PATH_TOOL_WIDTH, - PATH_TOOL_WIDTH, - GTK_ANCHOR_CENTER, - FALSE); - } - - if (segment->next) - path_curve_draw_segment (draw_tool, segment); -} - -static void -gimp_path_tool_draw (GimpDrawTool *draw_tool) -{ - GimpPathTool *path_tool; - - path_tool = GIMP_PATH_TOOL (draw_tool); - - path_traverse_path (path_tool->click_path, NULL, gimp_path_tool_draw_helper, NULL, draw_tool); -} - diff --git a/app/tools/gimppathtool.h b/app/tools/gimppathtool.h deleted file mode 100644 index 4da2767f3d..0000000000 --- a/app/tools/gimppathtool.h +++ /dev/null @@ -1,80 +0,0 @@ -/* 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 __GIMP_PATH_TOOL_H__ -#define __GIMP_PATH_TOOL_H__ - -#include "gimpdrawtool.h" -#include "path_curves.h" - - -#define GIMP_TYPE_PATH_TOOL (gimp_path_tool_get_type ()) -#define GIMP_PATH_TOOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_PATH_TOOL, GimpPathTool)) -#define GIMP_PATH_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_PATH_TOOL, GimpPathToolClass)) -#define GIMP_IS_PATH_TOOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_PATH_TOOL)) -#define GIMP_IS_PATH_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_PATH_TOOL)) -#define GIMP_PATH_TOOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_PATH_TOOL, GimpPathToolClass)) - - -typedef struct _GimpPathToolClass GimpPathToolClass; - -struct _GimpPathTool -{ - GimpDrawTool parent_instance; - - gint click_type; /* where did the user click? */ - gdouble click_x; /* X-coordinate of the click */ - gdouble click_y; /* Y-coordinate of the click */ - gint click_halfwidth; - gint click_halfheight; - guint click_modifier; /* what modifiers were pressed? */ - NPath *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 click_handle_id; /* The handle ID of the segment */ - - gint active_count; /* How many segments are active? */ - /* - * WARNING: single_active_segment may contain non NULL Values - * which point to the nirvana. But they are important! - * The pointer is garantueed to be valid, when active_count==1 - */ - PathSegment *single_active_segment; /* The only active segment */ - - gint state; /* state of tool */ - gint draw; /* all or part */ - NPath *cur_path; /* the current active path */ - GSList **scanlines; /* used in converting a path */ -}; - -struct _GimpPathToolClass -{ - GimpDrawToolClass parent_class; -}; - - -void gimp_path_tool_register (GimpToolRegisterCallback callback, - gpointer data); - -GType gimp_path_tool_get_type (void) G_GNUC_CONST; - - - -#endif /* __GIMP_PATH_TOOL_H__ */ diff --git a/app/tools/path_tool.c b/app/tools/path_tool.c deleted file mode 100644 index 1b4b05d746..0000000000 --- a/app/tools/path_tool.c +++ /dev/null @@ -1,1917 +0,0 @@ -/* 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. - */ - -/* - * Complete new path-tool by Simon Budig - * - * a path manipulation core independent of the underlying formula: - * implement bezier-curves, intelligent scissors-curves, splines... - * - * A Path is a collection of curves, which are constructed from - * segments between two anchors. - */ - -#include "config.h" - -#include - -#include "tools-types.h" - -#include "path_curves.h" -#include "path_tool.h" -#include "gimppathtool.h" - -#include "libgimp/gimpintl.h" - -/* - * Every new curve-type has to have a parameter between 0 and 1, and - * should go from a starting to a target point. - */ - - - -/* Some defines... */ - -#define PATH_TOOL_WIDTH 8 -#define PATH_TOOL_HALFWIDTH 4 - -/* local function prototypes */ - - -/* Small functions to determine coordinates, iterate over path/curve/segment */ - -void path_segment_get_coordinates (PathSegment *, - gdouble, - gint *, - gint *); -void path_traverse_path (NPath *, - PathTraverseFunc, - CurveTraverseFunc, - SegmentTraverseFunc, - gpointer); -void path_traverse_curve (NPath *, - PathCurve *, - CurveTraverseFunc, - SegmentTraverseFunc, - gpointer); -void path_traverse_segment (NPath *, - PathCurve *, - PathSegment *, - SegmentTraverseFunc, - gpointer); -gdouble path_locate_point (NPath *, - PathCurve **, - PathSegment **, - gint, - gint, - gint, - gint, - gint); - -gdouble path_tool_on_curve (NPath *path, - gint x, - gint y, - gint halfwidth, - NPath **ret_pathP, - PathCurve **ret_curveP, - PathSegment **ret_segmentP); - - -/* Tools to manipulate paths, curves, segments */ - -PathCurve * path_add_curve (NPath *, - gdouble, - gdouble); -PathSegment * path_append_segment (NPath *, - PathCurve *, - SegmentType, - gdouble, - gdouble); -PathSegment * path_prepend_segment (NPath *, - PathCurve *, - SegmentType, - gdouble, - gdouble); -PathSegment * path_split_segment (PathSegment *, - gdouble); -void path_join_curves (PathSegment *, - PathSegment *); -void path_flip_curve (PathCurve *); -void path_free_path (NPath *); -void path_free_curve (PathCurve *); -void path_free_segment (PathSegment *); -void path_delete_segment (PathSegment *); -void path_print (NPath *); -void path_offset_active (NPath *, gdouble, gdouble); -void path_set_flags (GimpPathTool *, - NPath *, - PathCurve *, - PathSegment *, - guint32, - guint32); - -/* High level image-manipulation functions */ - -void path_stroke (GimpPathTool *, - NPath *); -void path_to_selection (GimpPathTool *, - NPath *); - -/* Functions necessary for the tool */ - -gboolean path_tool_on_anchors (NPath *, gdouble, gdouble, gint, - NPath**, PathCurve**, PathSegment**); -gint path_tool_on_handles (NPath *, gdouble, gdouble, gint, - NPath **, PathCurve **, PathSegment **); - -#if 0 -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 *); - -gdouble path_tool_on_curve (Tool *, gint, gint, gint, - NPath**, PathCurve**, PathSegment**); - -gint path_tool_button_press_canvas (Tool *, GdkEventButton *, GimpDisplay *); -gint path_tool_button_press_anchor (Tool *, GdkEventButton *, GimpDisplay *); -gint path_tool_button_press_handle (Tool *, GdkEventButton *, GimpDisplay *); -gint path_tool_button_press_curve (Tool *, GdkEventButton *, GimpDisplay *); -void path_tool_motion_anchor (Tool *, GdkEventMotion *, GimpDisplay *); -void path_tool_motion_handle (Tool *, GdkEventMotion *, GimpDisplay *); -void path_tool_motion_curve (Tool *, GdkEventMotion *, GimpDisplay *); - -#endif - -/* the path tool options */ -static GimpToolOptions *path_options = NULL; - - -/* - * - * - * Here we go! - * - * - */ - -/* - * These functions are for applying a function over a complete - * path/curve/segment. They can pass information to each other - * with a arbitrary data structure - * - * The idea behind the three different functions is: - * if pathfunc != NULL - * call pathfunc for every curve - * else - * if curvefunc != NULL - * call curvefunc for every segment - * else - * call segmentfunc for every point - * - */ - -void -path_traverse_path (NPath *path, - PathTraverseFunc pathfunc, - CurveTraverseFunc curvefunc, - SegmentTraverseFunc segmentfunc, - gpointer data) -{ - PathCurve *cur_curve; - - if (path && path->curves) - { - cur_curve = path->curves; - if (pathfunc) - do { - (* pathfunc) (path, cur_curve, data); - cur_curve = cur_curve->next; - } while (cur_curve && cur_curve != path->curves); - else - do { - path_traverse_curve (path, cur_curve, curvefunc, segmentfunc, data); - cur_curve = cur_curve->next; - } while (cur_curve && cur_curve != path->curves); - } -} - - -void -path_traverse_curve (NPath *path, - PathCurve *curve, - CurveTraverseFunc curvefunc, - SegmentTraverseFunc segmentfunc, - gpointer data) -{ - PathSegment *cur_segment; - - if (curve && curve->segments) - { - cur_segment = curve->segments; - if (curvefunc) - do { - (* curvefunc) (path, curve, cur_segment, data); - cur_segment = cur_segment->next; - } while (cur_segment && cur_segment != curve->segments); - else - do { - path_traverse_segment (path, curve, cur_segment, segmentfunc, data); - cur_segment = cur_segment->next; - } while (cur_segment && cur_segment != curve->segments); - } -} - -void -path_traverse_segment (NPath *path, - PathCurve *curve, - PathSegment *segment, - SegmentTraverseFunc function, - gpointer data) -{ -#ifdef PATH_TOOL_DEBUG - g_printerr ("path_traverse_segment\n"); -#endif - - /* XXX: here we need path_curve_get_point(s) */ - - /* Something like: - * for i = 1 to subsamples { - * (x,y) = get_coordinates(i / subsamples) - * (* function) (....) - * } - */ -} - -/************************************************************** - * Helper functions for manipulating the data-structures: - */ - -PathCurve * -path_add_curve (NPath * cur_path, - gdouble x, - gdouble y) -{ - PathCurve * tmp = cur_path->curves; - PathCurve * new_curve = NULL; - -#ifdef PATH_TOOL_DEBUG - g_printerr ("path_add_curve\n"); -#endif - - if (cur_path) { - new_curve = g_new (PathCurve, 1); - - new_curve->parent = cur_path; - new_curve->next = tmp; - new_curve->prev = NULL; - new_curve->cur_segment = NULL; - new_curve->segments = NULL; - - if (tmp) tmp->prev = new_curve; - - cur_path->curves = cur_path->cur_curve = new_curve; - - new_curve->segments = path_prepend_segment (cur_path, new_curve, SEGMENT_BEZIER, x, y); - } -#ifdef PATH_TOOL_DEBUG - else - g_printerr ("Fatal Error: path_add_curve called without valid path\n"); -#endif - - return new_curve; -} - - -PathSegment * -path_append_segment (NPath * cur_path, - PathCurve * cur_curve, - SegmentType type, - gdouble x, - gdouble y) -{ - PathSegment * tmp = cur_curve->segments; - PathSegment * new_segment = NULL; - -#ifdef PATH_TOOL_DEBUG - g_printerr ("path_append_segment\n"); -#endif - - if (cur_curve) { - tmp = cur_curve->segments; - while (tmp && tmp->next && tmp->next != cur_curve->segments) { - tmp = tmp->next; - } - - if (tmp == NULL || tmp->next == NULL) { - new_segment = g_new (PathSegment, 1); - - new_segment->type = type; - new_segment->x = x; - new_segment->y = y; - new_segment->flags = 0; - new_segment->parent = cur_curve; - new_segment->next = NULL; - new_segment->prev = tmp; - new_segment->data = NULL; - - if (tmp) - tmp->next = new_segment; - - cur_curve->cur_segment = new_segment; - - path_curve_init_segment (new_segment); - - } -#ifdef PATH_TOOL_DEBUG - else - g_printerr ("Fatal Error: path_append_segment called with a closed curve\n"); -#endif - } -#ifdef PATH_TOOL_DEBUG - else - g_printerr ("Fatal Error: path_append_segment called without valid curve\n"); -#endif - - return new_segment; -} - - -PathSegment * -path_prepend_segment (NPath * cur_path, - PathCurve * cur_curve, - SegmentType type, - gdouble x, - gdouble y) -{ - PathSegment * tmp = cur_curve->segments; - PathSegment * new_segment = NULL; - -#ifdef PATH_TOOL_DEBUG - g_printerr ("path_prepend_segment\n"); -#endif - - if (cur_curve) { - tmp = cur_curve->segments; - - if (tmp == NULL || tmp->prev == NULL) { - new_segment = g_new (PathSegment, 1); - - new_segment->type = type; - new_segment->x = x; - new_segment->y = y; - new_segment->flags = 0; - new_segment->parent = cur_curve; - new_segment->next = tmp; - new_segment->prev = NULL; - new_segment->data = NULL; - - if (tmp) - tmp->prev = new_segment; - - cur_curve->segments = new_segment; - cur_curve->cur_segment = new_segment; - - path_curve_init_segment (new_segment); - } -#ifdef PATH_TOOL_DEBUG - else - g_printerr ("Fatal Error: path_prepend_segment called with a closed curve\n"); -#endif - } -#ifdef PATH_TOOL_DEBUG - else - g_printerr ("Fatal Error: path_prepend_segment called without valid curve\n"); -#endif - - return new_segment; -} - -PathSegment * -path_split_segment (PathSegment *segment, - gdouble position) -{ - PathSegment * new_segment = NULL; - -#ifdef PATH_TOOL_DEBUG - g_printerr ("path_split_segment\n"); -#endif - if (segment && segment->next) { - new_segment = g_new (PathSegment, 1); - - new_segment->type = segment->type; - path_curve_get_point (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; - - path_curve_init_segment (new_segment); - - new_segment->next->prev = new_segment; - segment->next = new_segment; - - return new_segment; - - } -#ifdef PATH_TOOL_DEBUG - else - g_printerr ("path_split_segment without valid segment\n"); -#endif - return NULL; - -} - -/* - * Join two arbitrary endpoints and free the parent from the second - * segment, if it differs from the first parents. - */ - -void -path_join_curves (PathSegment *segment1, - PathSegment *segment2) -{ - PathCurve *curve1, *curve2; - PathSegment *tmp; - - if ((segment1->next && segment1->prev) || (segment2->next && segment2->prev)) { -#ifdef PATH_TOOL_DEBUG - g_printerr ("Fatal Error: path_join_curves called with a closed segment\n"); -#endif - return; - } - if (segment1->parent == segment2->parent) { -#ifdef PATH_TOOL_DEBUG - g_printerr ("Joining beginning and end of the same curve...\n"); -#endif - if (segment2->next == NULL) { - segment2->next = segment1; - segment1->prev = segment2; - } else { - segment2->prev = segment1; - segment1->next = segment2; - } -/* XXX: Probably some segment-updates needed */ - return; - } - - if (segment1->next == NULL && segment2->next == NULL) { -#ifdef PATH_TOOL_DEBUG - g_printerr ("Flipping second curve (next, next)...\n"); -#endif - path_flip_curve (segment2->parent); - /* segment2 = segment2->parent->segments; - */ - } - - if (segment1->prev == NULL && segment2->prev == NULL) { -#ifdef PATH_TOOL_DEBUG - g_printerr ("Flipping second curve (prev, prev)...\n"); -#endif - path_flip_curve (segment2->parent); - /* segment2 = segment2->parent->segments; - * while (segment2->next) - * segment2 = segment2->next; - */ - } - - if (segment1->next == NULL && segment2->prev == NULL) { -#ifdef PATH_TOOL_DEBUG - g_printerr ("Appending second to first curve...\n"); -#endif - curve1 = segment1->parent; - curve2 = segment2->parent; - - segment1->next = segment2; - segment2->prev = segment1; - - curve2->segments = NULL; - - if (curve2->prev) - curve2->prev->next = curve2->next; - if (curve2->next) - curve2->next->prev = curve2->prev; - - if (curve2->parent->curves == curve2) - curve2->parent->curves = curve2->next; - - path_free_curve (curve2); - - tmp = segment2; - - while (tmp) { - tmp->parent = curve1; - tmp = tmp->next; - } -/* XXX: Probably some segment-updates needed */ - return; - } - - if (segment1->prev == NULL && segment2->next == NULL) { -#ifdef PATH_TOOL_DEBUG - g_printerr ("Prepending second to first curve...\n"); -#endif - curve1 = segment1->parent; - curve2 = segment2->parent; - - segment1->prev = segment2; - segment2->next = segment1; - - curve2->segments = NULL; - if (curve2->prev) - curve2->prev->next = curve2->next; - if (curve2->next) - curve2->next->prev = curve2->prev; - if (curve2->parent->curves == curve2) - curve2->parent->curves = curve2->next; - path_free_curve (curve2); - - tmp = segment2; - - while (tmp) { - tmp->parent = curve1; - curve1->segments = tmp; - tmp = tmp->prev; - } - return; -/* XXX: Probably some segment-updates needed */ - } - -#ifdef PATH_TOOL_DEBUG - g_printerr ("Cant join these curves yet...\nThis should not happen."); - return; -#endif - -} - -/* - * This function reverses the order of the anchors. This is - * necessary for some joining operations. - */ -void -path_flip_curve (PathCurve *curve) -{ - gpointer *end_data; - SegmentType end_type; - - PathSegment *tmp, *tmp2; - - if (!curve && !curve->segments) { -#ifdef PATH_TOOL_DEBUG - g_printerr ("path_flip_curve: No curve o no segments to flip!\n"); -#endif - return; - } - - tmp = curve->segments; - - while (tmp->next) - tmp = tmp->next; - - end_data = tmp->data; - end_type = tmp->type; - - tmp->parent->segments = tmp; - - while (tmp) { - tmp2 = tmp->next; - tmp->next = tmp->prev; - tmp->prev = tmp2; - if (tmp->next) { - tmp->type = tmp->next->type; - tmp->data = tmp->next->data; - } else { - tmp->type = end_type; - tmp->data = end_data; - } - path_curve_flip_segment (tmp); - tmp = tmp->next; - } -} - - -void -path_free_path (NPath * path) -{ - PathCurve *tmp1, *tmp2; - - if (path) - { - tmp2 = path->curves; - - while ((tmp1 = tmp2) != NULL) - { - tmp2 = tmp1->next; - path_free_curve (tmp1); - } - g_string_free(path->name, TRUE); - g_free(path); - } -} - -void -path_free_curve (PathCurve *curve) -{ - PathSegment *tmp1, *tmp2; - - if (curve) - { - tmp2 = curve->segments; - - /* break closed curves */ - if (tmp2 && tmp2->prev) - tmp2->prev->next = NULL; - - while ((tmp1 = tmp2) != NULL) - { - tmp2 = tmp1->next; - path_free_segment (tmp1); - } - g_free(curve); - } -} - -void -path_free_segment (PathSegment *segment) -{ - if (segment) - { - /* Clear the active flag to keep path_tool->single_active_segment - * consistent */ - - - path_set_flags (NULL, segment->parent->parent, - segment->parent, segment, 0, SEGMENT_ACTIVE); - - path_curve_cleanup_segment(segment); - - g_free (segment); - } -} - -void -path_delete_curve (PathCurve *curve) -{ - if (curve) - { - if (curve->next) - curve->next->prev = curve->prev; - if (curve->prev) - curve->prev->next = curve->next; - - if (curve == curve->parent->curves) { - curve->parent->curves = curve->next; - } - - path_free_curve (curve); - } -} - -void -path_delete_segment (PathSegment *segment) -{ - if (segment) - { - if (segment->next) - segment->next->prev = segment->prev; - if (segment->prev) - segment->prev->next = segment->next; - - /* If the remaining curve is closed and has a - * single point only, open it. - */ - if (segment->next == segment->prev && segment->next) - segment->next->next = segment->next->prev = NULL; - - if (segment == segment->parent->segments) - segment->parent->segments = segment->next; - - if (segment->parent->segments == NULL) - path_delete_curve (segment->parent); - - path_free_segment (segment); - - /* - * here we have to update the surrounding segments - */ -/* XXX: Please add path_curve_update_segment here */ - } -} - - -/* - * A function to determine, which object is hit by the cursor - */ - -gint -path_tool_cursor_position (NPath *path, - gdouble x, - gdouble y, - gint halfwidth, - gint halfheight, - NPath **pathP, - PathCurve **curveP, - PathSegment **segmentP, - gdouble *positionP, - gint *handle_idP) -{ - gdouble pos; - gint handle_id; - - if (path_tool_on_anchors (path, x, y, halfwidth, pathP, curveP, segmentP)) - return ON_ANCHOR; - - handle_id = path_tool_on_handles (path, x, y, halfwidth, pathP, curveP, segmentP); - if (handle_id) { - if (handle_idP) (*handle_idP) = handle_id; - return ON_HANDLE; - } - - pos = path_tool_on_curve (path, x, y, halfwidth, pathP, curveP, segmentP); - if (pos >= 0 && pos <= 1) { - if (positionP) (*positionP) = pos; - return ON_CURVE; - } - - - return ON_CANVAS; -} - - -#if 0 -/************************************************************** - * The click-callbacks for the tool - */ - -void -path_tool_button_press (Tool *tool, - GdkEventButton *bevent, - GimpDisplay *gdisp) -{ - PathTool * path_tool; - gint grab_pointer=0; - gint x, y, halfwidth, dummy; - -#ifdef PATH_TOOL_DEBUG - g_printerr ("path_tool_button_press\n"); -#endif - - path_tool = (PathTool *) tool->private; - tool->gdisp = gdisp; - - /* Transform window-coordinates to canvas-coordinates */ - gdisplay_untransform_coords (gdisp, bevent->x, bevent->y, &x, &y, TRUE, 0); -#ifdef PATH_TOOL_DEBUG - g_printerr ("Clickcoordinates %d, %d\n",x,y); -#endif - path_tool->click_x = x; - path_tool->click_y = y; - path_tool->click_modifier = bevent->state; - /* get halfwidth in image coord */ - gdisplay_untransform_coords (gdisp, bevent->x + PATH_TOOL_HALFWIDTH, 0, &halfwidth, &dummy, TRUE, 0); - halfwidth -= x; - path_tool->click_halfwidth = halfwidth; - - if (!path_tool->cur_path->curves) - draw_core_start (path_tool->core, gdisp->canvas->window, tool); - - /* determine point, where clicked, - * switch accordingly. - */ - - 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_position), - &(path_tool->click_handle_id)); - - switch (path_tool->click_type) - { - case ON_CANVAS: - grab_pointer = path_tool_button_press_canvas(tool, bevent, gdisp); - break; - - case ON_ANCHOR: - grab_pointer = path_tool_button_press_anchor(tool, bevent, gdisp); - break; - - case ON_HANDLE: - grab_pointer = path_tool_button_press_handle(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_*)"); - } - - if (grab_pointer) - gdk_pointer_grab (gdisp->canvas->window, FALSE, - GDK_POINTER_MOTION_HINT_MASK | - GDK_BUTTON1_MOTION_MASK | - GDK_BUTTON_RELEASE_MASK, - NULL, NULL, bevent->time); - - tool->state = ACTIVE; - -} - -gint -path_tool_button_press_anchor (Tool *tool, - GdkEventButton *bevent, - GimpDisplay *gdisp) -{ - static guint32 last_click_time=0; - gboolean doubleclick=FALSE; - PathTool *path_tool = tool->private; - - NPath * cur_path = path_tool->cur_path; - PathSegment *p_sas; - gint grab_pointer; - -#ifdef PATH_TOOL_DEBUG - g_printerr ("path_tool_button_press_anchor:\n"); -#endif - - grab_pointer = 1; - - if (!cur_path) { -#ifdef PATH_TOOL_DEBUG - g_printerr ("Fatal error: No current Path\n"); -#endif - return 0; - } - - /* - * We have to determine, if this was a doubleclick for ourself, because - * disp_callback.c ignores the GDK_[23]BUTTON_EVENT's and adding them to - * the switch statement confuses some tools. - */ - if (bevent->time - last_click_time < 250) { - doubleclick=TRUE; -#ifdef PATH_TOOL_DEBUG - g_printerr ("Doppelclick!\n"); -#endif - } else - doubleclick=FALSE; - last_click_time = bevent->time; - - - draw_core_pause (path_tool->core, tool); - - /* The user pressed on an anchor: - * normally this activates this anchor - * + SHIFT toggles the activity of an anchor. - * if this anchor is at the end of an open curve and the other - * end is active, close the curve. - * - * Doubleclick (de)activates the whole curve (not Path!). - */ - - p_sas = path_tool->single_active_segment; - -#ifdef PATH_TOOL_DEBUG - g_printerr ("p_sas: %p\n", p_sas); -#endif - - if (path_tool->click_modifier & GDK_SHIFT_MASK) { - if (path_tool->active_count == 1 && p_sas && p_sas != path_tool->click_segment && - (p_sas->next == NULL || p_sas->prev == NULL) && - (path_tool->click_segment->next == NULL || path_tool->click_segment->prev == NULL)) { - /* - * if this is the end of an open curve and the single active segment was another - * open end, connect those ends. - */ - path_join_curves (path_tool->click_segment, p_sas); - path_set_flags (path_tool, path_tool->click_path, path_tool->click_curve, - NULL, 0, SEGMENT_ACTIVE); - } - - if (doubleclick) - /* - * Doubleclick set the whole curve to the same state, depending on the - * state of the clicked anchor. - */ - if (path_tool->click_segment->flags & SEGMENT_ACTIVE) - path_set_flags (path_tool, path_tool->click_path, path_tool->click_curve, - NULL, SEGMENT_ACTIVE, 0); - else - path_set_flags (path_tool, path_tool->click_path, path_tool->click_curve, - NULL, 0, SEGMENT_ACTIVE); - else - /* - * Toggle the state of the clicked anchor. - */ - if (path_tool->click_segment->flags & SEGMENT_ACTIVE) - path_set_flags (path_tool, path_tool->click_path, path_tool->click_curve, - path_tool->click_segment, 0, SEGMENT_ACTIVE); - else - path_set_flags (path_tool, path_tool->click_path, path_tool->click_curve, - path_tool->click_segment, SEGMENT_ACTIVE, 0); - } - /* - * Delete anchors, when CONTROL is pressed - */ - else if (path_tool->click_modifier & GDK_CONTROL_MASK) - { - if (path_tool->click_segment->flags & SEGMENT_ACTIVE) - { - if (path_tool->click_segment->prev) - path_set_flags (path_tool, path_tool->click_path, path_tool->click_curve, - path_tool->click_segment->prev, SEGMENT_ACTIVE, 0); - else if (path_tool->click_segment->next) - path_set_flags (path_tool, path_tool->click_path, path_tool->click_curve, - path_tool->click_segment->next, SEGMENT_ACTIVE, 0); - } - - 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)) - { - path_set_flags (path_tool, cur_path, NULL, NULL, 0, SEGMENT_ACTIVE); - path_set_flags (path_tool, cur_path, path_tool->click_curve, path_tool->click_segment, SEGMENT_ACTIVE, 0); - } - - - draw_core_resume(path_tool->core, tool); - - return grab_pointer; -} - - -gint -path_tool_button_press_handle (Tool *tool, - GdkEventButton *bevent, - GimpDisplay *gdisp) -{ - static guint32 last_click_time=0; - gboolean doubleclick=FALSE; - PathTool *path_tool = tool->private; - - NPath * cur_path = path_tool->cur_path; - gint grab_pointer; - -#ifdef PATH_TOOL_DEBUG - g_printerr ("path_tool_button_press_handle:\n"); -#endif - - grab_pointer = 1; - - if (!cur_path) { -#ifdef PATH_TOOL_DEBUG - g_printerr ("Fatal error: No current Path\n"); -#endif - return 0; - } - - /* - * We have to determine, if this was a doubleclick for ourself, because - * disp_callback.c ignores the GDK_[23]BUTTON_EVENT's and adding them to - * the switch statement confuses some tools. - */ - if (bevent->time - last_click_time < 250) { - doubleclick=TRUE; -#ifdef PATH_TOOL_DEBUG - g_printerr ("Doppelclick!\n"); -#endif - } else - doubleclick=FALSE; - last_click_time = bevent->time; - - return grab_pointer; -} - -gint -path_tool_button_press_canvas (Tool *tool, - GdkEventButton *bevent, - GimpDisplay *gdisp) -{ - PathTool *path_tool = tool->private; - - NPath * cur_path = path_tool->cur_path; - PathCurve * cur_curve; - PathSegment * cur_segment; - gint grab_pointer; - -#ifdef PATH_TOOL_DEBUG - g_printerr ("path_tool_button_press_canvas:\n"); -#endif - - grab_pointer = 1; - - if (!cur_path) { -#ifdef PATH_TOOL_DEBUG - g_printerr ("Fatal error: No current Path\n"); -#endif - return 0; - } - - draw_core_pause (path_tool->core, tool); - - if (path_tool->active_count == 1 && path_tool->single_active_segment != NULL - && (path_tool->single_active_segment->prev == NULL || path_tool->single_active_segment->next == NULL)) { - cur_segment = path_tool->single_active_segment; - cur_curve = cur_segment->parent; - - path_set_flags (path_tool, cur_path, NULL, NULL, 0, SEGMENT_ACTIVE); - - if (cur_segment->next == NULL) - cur_curve->cur_segment = path_append_segment(cur_path, cur_curve, SEGMENT_BEZIER, path_tool->click_x, path_tool->click_y); - else - cur_curve->cur_segment = path_prepend_segment(cur_path, cur_curve, SEGMENT_BEZIER, path_tool->click_x, path_tool->click_y); - if (cur_curve->cur_segment) { - path_set_flags (path_tool, cur_path, cur_curve, cur_curve->cur_segment, SEGMENT_ACTIVE, 0); - } - } else { - if (path_tool->active_count == 0) { - path_set_flags (path_tool, cur_path, NULL, NULL, 0, SEGMENT_ACTIVE); - cur_path->cur_curve = path_add_curve(cur_path, path_tool->click_x, path_tool->click_y); - path_set_flags (path_tool, cur_path, cur_path->cur_curve, cur_path->cur_curve->segments, SEGMENT_ACTIVE, 0); - } else { - path_set_flags (path_tool, cur_path, NULL, NULL, 0, SEGMENT_ACTIVE); - } - } - - draw_core_resume(path_tool->core, tool); - - return 0; -} - -gint -path_tool_button_press_curve (Tool *tool, - GdkEventButton *bevent, - GimpDisplay *gdisp) -{ - PathTool *path_tool = tool->private; - - NPath * cur_path = path_tool->cur_path; - PathSegment * cur_segment; - gint grab_pointer; - -#ifdef PATH_TOOL_DEBUG - g_printerr ("path_tool_button_press_curve:\n"); -#endif - - grab_pointer = 1; - - if (!cur_path) { -#ifdef PATH_TOOL_DEBUG - g_printerr ("Fatal error: No current NPath\n"); -#endif - 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; - - } else { - path_set_flags (path_tool, cur_path, NULL, NULL, 0, SEGMENT_ACTIVE); - path_set_flags (path_tool, cur_path, path_tool->click_curve, path_tool->click_segment, SEGMENT_ACTIVE, 0); - path_set_flags (path_tool, cur_path, path_tool->click_curve, path_tool->click_segment->next, SEGMENT_ACTIVE, 0); - } - draw_core_resume(path_tool->core, tool); - - return 0; -} - -void -path_tool_button_release (Tool *tool, - GdkEventButton *bevent, - GimpDisplay *gdisp) -{ - PathTool * path_tool; - -#ifdef PATH_TOOL_DEBUG - g_printerr ("path_tool_button_release\n"); -#endif - - path_tool = (PathTool *) tool->private; - - path_tool->state &= ~PATH_TOOL_DRAG; - - gdk_pointer_ungrab (bevent->time); - gdk_flush (); -} - - -/************************************************************** - * The motion-callbacks for the tool - */ - -void -path_tool_motion (Tool *tool, - GdkEventMotion *mevent, - GimpDisplay *gdisp) -{ - PathTool * path_tool; - - if (gtk_events_pending()) return; - - path_tool = (PathTool *) tool->private; - - switch (path_tool->click_type) { - case ON_ANCHOR: - path_tool_motion_anchor (tool, mevent, gdisp); - break; - case ON_HANDLE: - path_tool_motion_handle (tool, mevent, gdisp); - break; - case ON_CURVE: - path_tool_motion_curve (tool, mevent, gdisp); - break; - default: - return; - } - -} - -void -path_tool_motion_anchor (Tool *tool, - GdkEventMotion *mevent, - GimpDisplay *gdisp) -{ - PathTool * path_tool; - gdouble dx, dy, d; - gint x,y; - static gint dxsum = 0; - static gint dysum = 0; - - path_tool = (PathTool *) tool->private; - - /* - * Dont do anything, if the user clicked with pressed CONTROL-Key, - * because he deleted an anchor. - */ - if (path_tool->click_modifier & GDK_CONTROL_MASK) - return; - - if (!(path_tool->state & PATH_TOOL_DRAG)) - { - path_tool->state |= PATH_TOOL_DRAG; - dxsum = 0; - dysum = 0; - } - - gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &x, &y, TRUE, 0); - - dx = x - path_tool->click_x - dxsum; - dy = y - path_tool->click_y - dysum; - - /* restrict to horizontal/vertical lines, if modifiers are pressed - * I'm not sure, if this is intuitive for the user. Esp. When moving - * an endpoint of an curve I'd expect, that the *line* is - * horiz/vertical - not the delta to the point, where the point was - * originally... - */ - if (mevent->state & GDK_MOD1_MASK) - { - if (mevent->state & GDK_CONTROL_MASK) - { - d = (fabs(dx) + fabs(dy)) / 2; - d = (fabs(x - path_tool->click_x) + fabs(y - path_tool->click_y)) / 2; - - dx = ((x < path_tool->click_x) ? -d : d ) - dxsum; - dy = ((y < path_tool->click_y) ? -d : d ) - dysum; - } - else - dx = - dxsum; - } - else if (mevent->state & GDK_CONTROL_MASK) - dy = - dysum; - - - path_tool->draw |= PATH_TOOL_REDRAW_ACTIVE; - - draw_core_pause (path_tool->core, tool); - - path_offset_active (path_tool->cur_path, dx, dy); - - dxsum += dx; - dysum += dy; - - draw_core_resume (path_tool->core, tool); - - path_tool->draw &= ~PATH_TOOL_REDRAW_ACTIVE; - -} - -void -path_tool_motion_handle (Tool *tool, - GdkEventMotion *mevent, - GimpDisplay *gdisp) -{ - PathTool * path_tool; - gdouble dx, dy; - gint x,y; - static gint dxsum = 0; - static gint dysum = 0; - - path_tool = (PathTool *) tool->private; - - /* - * Dont do anything, if the user clicked with pressed CONTROL-Key, - * because he moved the handle to the anchor an anchor. - * XXX: Not yet! :-) - */ - if (path_tool->click_modifier & GDK_CONTROL_MASK) - return; - - if (!(path_tool->state & PATH_TOOL_DRAG)) - { - path_tool->state |= PATH_TOOL_DRAG; - dxsum = 0; - dysum = 0; - } - - gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &x, &y, TRUE, 0); - - dx = x - path_tool->click_x - dxsum; - dy = y - path_tool->click_y - dysum; - - path_tool->draw |= PATH_TOOL_REDRAW_ACTIVE; - - draw_core_pause (path_tool->core, tool); - - path_curve_drag_handle (path_tool, path_tool->click_segment, dx, dy, path_tool->click_handle_id); - - dxsum += dx; - dysum += dy; - - draw_core_resume (path_tool->core, tool); - - path_tool->draw &= ~PATH_TOOL_REDRAW_ACTIVE; - -} - - -void -path_tool_motion_curve (Tool *tool, - GdkEventMotion *mevent, - GimpDisplay *gdisp) -{ - PathTool * path_tool; - gdouble dx, dy; - gint x,y; - static gint dxsum = 0; - static gint dysum = 0; - - path_tool = (PathTool *) tool->private; - - if (!(path_tool->state & PATH_TOOL_DRAG)) - { - path_tool->state |= PATH_TOOL_DRAG; - dxsum = 0; - dysum = 0; - } - - gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &x, &y, TRUE, 0); - - dx = x - path_tool->click_x - dxsum; - dy = y - path_tool->click_y - dysum; - - path_tool->draw |= PATH_TOOL_REDRAW_ACTIVE; - - draw_core_pause (path_tool->core, tool); - - path_curve_drag_segment (path_tool, path_tool->click_segment, path_tool->click_position, dx, dy); - - dxsum += dx; - dysum += dy; - - draw_core_resume (path_tool->core, tool); - - path_tool->draw &= ~PATH_TOOL_REDRAW_ACTIVE; - -} - - -void -path_tool_cursor_update (Tool *tool, - GdkEventMotion *mevent, - GimpDisplay *gdisp) -{ - PathTool *path_tool; - gint x, y, halfwidth, dummy, cursor_location; - -#ifdef PATH_TOOL_DEBUG - /* g_printerr ("path_tool_cursor_update\n"); - */ -#endif - - path_tool = (PathTool *) tool->private; - - gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &x, &y, TRUE, 0); - /* get halfwidth in image coord */ - 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, 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_HANDLE: - gdisplay_install_tool_cursor (gdisp, GDK_CROSSHAIR); - break; - case ON_CURVE: - gdisplay_install_tool_cursor (gdisp, GDK_CROSSHAIR); - break; - default: - gdisplay_install_tool_cursor (gdisp, GDK_QUESTION_ARROW); - break; - } -} - -/************************************************************** - * Tool-control functions - */ - -void -path_tool_control (Tool *tool, - ToolAction action, - GimpDisplay *gdisp) -{ - PathTool * path_tool; - -#ifdef PATH_TOOL_DEBUG - g_printerr ("path_tool_control\n"); -#endif - - path_tool = (PathTool *) tool->private; - - switch (action) - { - case PAUSE: - draw_core_pause (path_tool->core, tool); - break; - - case RESUME: - draw_core_resume (path_tool->core, tool); - break; - - case HALT: -#ifdef PATH_TOOL_DEBUG - g_printerr ("path_tool_control: HALT\n"); -#endif - draw_core_stop (path_tool->core, tool); - tool->state = INACTIVE; - break; - - default: - break; - } -#ifdef PATH_TOOL_DEBUG - g_printerr ("path_tool_control: end\n"); -#endif -} - -Tool * -tools_new_path_tool (void) -{ - Tool * tool; - PathTool * private; - - /* The tool options */ - if (! path_options) - { - path_options = tool_options_new (_("Path Tool")); - tools_register (PATH_TOOL, (GimpToolOptions *) path_options); - } - - tool = tools_new_tool (PATH_TOOL); - private = g_new0 (PathTool, 1); - - 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; - - private->state = 0; - private->draw = PATH_TOOL_REDRAW_ALL; - private->core = draw_core_new (path_tool_draw); - private->cur_path = g_new0(NPath, 1); - private->scanlines = NULL; - - - tool->private = (void *) private; - - tool->button_press_func = path_tool_button_press; - tool->button_release_func = path_tool_button_release; - tool->motion_func = path_tool_motion; - tool->cursor_update_func = path_tool_cursor_update; - tool->control_func = path_tool_control; - - private->cur_path->curves = NULL; - private->cur_path->cur_curve = NULL; - private->cur_path->name = g_string_new("Path 0"); - private->cur_path->state = 0; - private->cur_path->path_tool = private; - - return tool; -} - -void -tools_free_path_tool (Tool *tool) -{ - GimpDisplay * gdisp; - PathTool * path_tool; - -#ifdef PATH_TOOL_DEBUG - g_printerr ("tools_free_path_tool start\n"); -#endif - path_tool = (PathTool *) tool->private; - gdisp = tool->gdisp; - - if (tool->state == ACTIVE) - { - draw_core_stop (path_tool->core, tool); - } - - path_free_path (path_tool->cur_path); - - draw_core_free (path_tool->core); - - g_free (path_tool); -#ifdef PATH_TOOL_DEBUG - g_printerr ("tools_free_path_tool end\n"); -#endif - -} - -#endif - -/************************************************************** - * Set of function to determine, if the click was on a segment - */ - -typedef struct { - NPath *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 (NPath *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 (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 (NPath *path, - gint x, - gint y, - gint halfwidth, - NPath **ret_pathP, - PathCurve **ret_curveP, - PathSegment **ret_segmentP) -{ - Path_on_curve_type *data = g_new (Path_on_curve_type, 1); - gdouble position; - - data->path = path; - data->curve = 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 (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 - */ - -typedef struct { - NPath *path; - PathCurve *curve; - PathSegment *segment; - gdouble testx; - gdouble testy; - gint distance; - gboolean found; -} Path_on_anchors_type; - -/* This is a CurveTraverseFunc */ -void -path_tool_on_anchors_helper (NPath *path, - PathCurve *curve, - PathSegment *segment, - gpointer ptr) -{ - gint distance; - Path_on_anchors_type *data = (Path_on_anchors_type *) ptr; - - if (segment && data && data->distance > 0) - { - distance = ((data->testx - segment->x) * (data->testx - segment->x) + - (data->testy - segment->y) * (data->testy - segment->y)); - - if ( distance < data->distance ) - { - data->path = path; - data->curve = curve; - data->segment = segment; - data->distance = distance; - data->found = TRUE; - } - } -} - -gboolean -path_tool_on_anchors (NPath *path, - gdouble x, - gdouble y, - gint halfwidth, - NPath **ret_pathP, - PathCurve **ret_curveP, - PathSegment **ret_segmentP) -{ - Path_on_anchors_type *data = g_new (Path_on_anchors_type, 1); - gboolean ret_found; - - data->path = path; - data->curve = NULL; - data->segment = NULL; - data->testx = x; - data->testy = y; - data->distance = halfwidth * halfwidth + 1; - data->found = FALSE; - - path_traverse_path (path, NULL, path_tool_on_anchors_helper, NULL, data); - - if (ret_pathP) *ret_pathP = data->path; - if (ret_curveP) *ret_curveP = data->curve; - if (ret_segmentP) *ret_segmentP = data->segment; - - ret_found = data->found; - - g_free (data); - - return ret_found; - -} - -/************************************************************** - * Set of function to determine, if the click was on an handle - */ - -typedef struct { - NPath *path; - PathCurve *curve; - PathSegment *segment; - gdouble testx; - gdouble testy; - gint halfwidth; - gint handle_id; - gboolean found; -} Path_on_handles_type; - -/* This is a CurveTraverseFunc */ -void -path_tool_on_handles_helper (NPath *path, - PathCurve *curve, - PathSegment *segment, - gpointer ptr) -{ - Path_on_handles_type *data = (Path_on_handles_type *) ptr; - gint handle; - - if (segment && data && !data->found) - { - handle = path_curve_on_handle (segment, data->testx, data->testy, - data->halfwidth); - if (handle) - { - data->path = path; - data->curve = curve; - data->segment = segment; - data->handle_id = handle; - data->found = TRUE; - } - } -} - -gint -path_tool_on_handles (NPath *path, - gdouble x, - gdouble y, - gint halfwidth, - NPath **ret_pathP, - PathCurve **ret_curveP, - PathSegment **ret_segmentP) -{ - Path_on_handles_type *data = g_new (Path_on_handles_type, 1); - gint handle_ret; - - data->path = path; - data->curve = NULL; - data->segment = NULL; - data->testx = x; - data->testy = y; - data->halfwidth = halfwidth; - data->handle_id = 0; - data->found = FALSE; - - path_traverse_path (path, NULL, path_tool_on_handles_helper, NULL, data); - - if (ret_pathP) *ret_pathP = data->path; - if (ret_curveP) *ret_curveP = data->curve; - if (ret_segmentP) *ret_segmentP = data->segment; - - handle_ret = data->handle_id; - - g_free (data); - - return handle_ret; -} - - -/************************************************************** - * Set of function to offset all active anchors - */ - -typedef struct { - gdouble dx; - gdouble dy; -} Path_offset_active_type; - -/* This is a CurveTraverseFunc */ -void -path_offset_active_helper (NPath *path, - PathCurve *curve, - PathSegment *segment, - gpointer ptr) -{ - Path_offset_active_type *data = (Path_offset_active_type *) ptr; - - if (segment && data && (segment->flags & SEGMENT_ACTIVE)) { - segment->x += data->dx; - segment->y += data->dy; - } -/* XXX: Do a segment_update here! */ -} - -void -path_offset_active (NPath *path, - gdouble dx, - gdouble dy) -{ - Path_offset_active_type *data = g_new (Path_offset_active_type, 1); - data->dx = dx; - data->dy = dy; - - if (path) - path_traverse_path (path, NULL, path_offset_active_helper, NULL, data); - - g_free (data); -} - - -/************************************************************** - * Set of function to set the state of all anchors - */ - -typedef struct { - guint32 bits_set; - guint32 bits_clear; - GimpPathTool *path_tool; -} Path_set_flags_type; - -/* This is a CurveTraverseFunc */ -void -path_set_flags_helper (NPath *path, - PathCurve *curve, - PathSegment *segment, - gpointer ptr) -{ - Path_set_flags_type *tmp = (Path_set_flags_type *) ptr; - guint32 oldflags; - guint tmp_uint; - - if (segment) { - oldflags = segment->flags; - segment->flags &= ~(tmp->bits_clear); - segment->flags |= tmp->bits_set; - - /* - * Some black magic: We try to remember, which is the single active - * segment. We count, how many segments are active (in - * path_tool->active_count) and XOR path_tool->single_active_segment - * every time we select or deselect an anchor. So if exactly one anchor - * is active, path_tool->single_active_segment points to it. - */ - - /* If SEGMENT_ACTIVE state has changed change the PathTool data - * accordingly. - */ - if (((segment->flags ^ oldflags) & SEGMENT_ACTIVE) && tmp && tmp->path_tool) { - if (segment->flags & SEGMENT_ACTIVE) - tmp->path_tool->active_count++; - else - tmp->path_tool->active_count--; - - /* Does this work on all (16|32|64)-bit Machines? */ - - tmp_uint = GPOINTER_TO_UINT(tmp->path_tool->single_active_segment); - tmp_uint ^= GPOINTER_TO_UINT(segment); - tmp->path_tool->single_active_segment = GUINT_TO_POINTER(tmp_uint); - } - } -} - -void -path_set_flags (GimpPathTool *path_tool, - NPath *path, - PathCurve *curve, - PathSegment *segment, - guint32 bits_set, - guint32 bits_clear) -{ - Path_set_flags_type *tmp = g_new (Path_set_flags_type, 1); - tmp->bits_set=bits_set; - tmp->bits_clear=bits_clear; - tmp->path_tool = path_tool; - - if (segment) - path_set_flags_helper (path, curve, segment, tmp); - else if (curve) - path_traverse_curve (path, curve, path_set_flags_helper, NULL, tmp); - else if (path) - path_traverse_path (path, NULL, path_set_flags_helper, NULL, tmp); - - g_free (tmp); -} - - -/************************************************************** - * Set of functions to draw the segments to the window - */ - -/* This is a CurveTraverseFunc */ -void -path_tool_draw_helper (NPath *path, - PathCurve *curve, - PathSegment *segment, - gpointer tool_ptr) -{ -#if 0 - Tool * tool = (Tool *) tool_ptr; - GimpDisplay * gdisp; - PathTool * path_tool; - DrawCore * core; - gint x1, y1; - gboolean draw = TRUE; - - if (!tool) { -#ifdef PATH_TOOL_DEBUG - g_printerr ("Fatal Error: path_tool_draw_segment called without valid tool *\n"); -#endif - return; - } - - gdisp = tool->gdisp; - - path_tool = (PathTool *) tool->private; - core = path_tool->core; - - if (path_tool->draw & PATH_TOOL_REDRAW_ACTIVE) - draw = (segment->flags & SEGMENT_ACTIVE || (segment->next && segment->next->flags & SEGMENT_ACTIVE)); - - if (segment && draw) - { - gdisplay_transform_coords (gdisp, (gint) segment->x, (gint) segment->y, &x1, &y1, FALSE); - if (segment->flags & SEGMENT_ACTIVE) - gdk_draw_arc (core->win, core->gc, 0, - x1 - PATH_TOOL_HALFWIDTH, y1 - PATH_TOOL_HALFWIDTH, - PATH_TOOL_WIDTH, PATH_TOOL_WIDTH, 0, 23040); - else - gdk_draw_arc (core->win, core->gc, 1, - x1 - PATH_TOOL_HALFWIDTH, y1 - PATH_TOOL_HALFWIDTH, - PATH_TOOL_WIDTH, PATH_TOOL_WIDTH, 0, 23040); - - path_curve_draw_handles (tool, segment); - - if (segment->next) - { - path_curve_draw_segment (tool, segment); - } - } -#ifdef PATH_TOOL_DEBUG - else if (!segment) - g_printerr ("path_tool_draw_segment: no segment to draw\n"); -#endif -#endif -} - -#if 0 -void -path_tool_draw (Tool *tool) -{ - GimpDisplay * gdisp; - NPath * cur_path; - PathTool * path_tool; - -#ifdef PATH_TOOL_DEBUG - g_printerr ("path_tool_draw\n"); -#endif - - gdisp = tool->gdisp; - path_tool = tool->private; - cur_path = path_tool->cur_path; - - path_traverse_path (cur_path, NULL, path_tool_draw_helper, NULL, tool); - -#ifdef PATH_TOOL_DEBUG - /* g_printerr ("path_tool_draw end.\n"); - */ -#endif - -} -#endif - - diff --git a/app/tools/path_tool.h b/app/tools/path_tool.h deleted file mode 100644 index 1a41c883ab..0000000000 --- a/app/tools/path_tool.h +++ /dev/null @@ -1,144 +0,0 @@ -/* 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_TOOL_H__ -#define __PATH_TOOL_H__ - -/* - * Every new curve-type has to have a parameter between 0 and 1, and - * should go from a starting to a target point. - */ - -/* Some defines... */ - -#define PATH_TOOL_WIDTH 8 -#define PATH_TOOL_HALFWIDTH 4 - -/* function prototypes */ - - -/* Small functions to determine coordinates, iterate over path/curve/segment */ - -void path_segment_get_coordinates (PathSegment *, - gdouble, - gint *, - gint *); -void path_traverse_path (NPath *, - PathTraverseFunc, - CurveTraverseFunc, - SegmentTraverseFunc, - gpointer); -void path_traverse_curve (NPath *, - PathCurve *, - CurveTraverseFunc, - SegmentTraverseFunc, - gpointer); -void path_traverse_segment (NPath *, - PathCurve *, - PathSegment *, - SegmentTraverseFunc, - gpointer); -gdouble path_locate_point (NPath *, - PathCurve **, - PathSegment **, - gint, - gint, - gint, - gint, - gint); - -/* Tools to manipulate paths, curves, segments */ - -PathCurve * path_add_curve (NPath *, - gdouble, - gdouble); -PathSegment * path_append_segment (NPath *, - PathCurve *, - SegmentType, - gdouble, - gdouble); -PathSegment * path_prepend_segment (NPath *, - PathCurve *, - SegmentType, - gdouble, - gdouble); -PathSegment * path_split_segment (PathSegment *, - gdouble); -void path_join_curves (PathSegment *, - PathSegment *); -void path_flip_curve (PathCurve *); -void path_free_path (NPath *); -void path_free_curve (PathCurve *); -void path_free_segment (PathSegment *); -void path_delete_segment (PathSegment *); -void path_print (NPath *); -void path_offset_active (NPath *, - gdouble, - gdouble); -void path_set_flags (GimpPathTool *path_tool, - NPath *, - PathCurve *, - PathSegment *, - guint32, - guint32); - -gdouble gimp_path_tool_on_curve (GimpPathTool *path_tool, - gint, - gint, - gint, - NPath**, - PathCurve**, - PathSegment**); -gboolean gimp_path_tool_on_anchors (GimpPathTool *path_tool, - gint, - gint, - gint, - NPath**, - PathCurve**, - PathSegment**); -gint gimp_path_tool_on_handles (GimpPathTool *path_tool, - gint, - gint, - gint, - NPath **, - PathCurve **, - PathSegment **); - -gint path_tool_cursor_position (NPath *path, - gdouble x, - gdouble y, - gint halfwidth, - gint halfheight, - NPath **pathP, - PathCurve **curveP, - PathSegment **segmentP, - gdouble *positionP, - gint *handle_idP); - - -/* High level image-manipulation functions */ - -void path_stroke (GimpPathTool *path_tool, - NPath *); -void path_to_selection (GimpPathTool *path_tool, - NPath *); - - -#endif /* __PATH_TOOL_H__ */ - diff --git a/app/tools/tools.c b/app/tools/tools.c index 994e6ec092..bef82af94e 100644 --- a/app/tools/tools.c +++ b/app/tools/tools.c @@ -62,7 +62,6 @@ #include "gimpmeasuretool.h" #include "gimpmovetool.h" #include "gimppaintbrushtool.h" -#include "gimppathtool.h" #include "gimppenciltool.h" #include "gimpperspectivetool.h" #include "gimpposterizetool.h" @@ -126,7 +125,6 @@ tools_init (Gimp *gimp) /* non-modifying tools */ - gimp_path_tool_register, gimp_vector_tool_register, gimp_measure_tool_register, gimp_magnify_tool_register,