app/Makefile.am app/path_bezier.[ch] app/path_curves.[ch]

2003-02-12  Sven Neumann  <sven@gimp.org>

	* 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.
This commit is contained in:
Sven Neumann 2003-02-12 13:06:13 +00:00 committed by Sven Neumann
parent b0161a5089
commit 4858a3750b
12 changed files with 11 additions and 4016 deletions

View File

@ -1,3 +1,13 @@
2003-02-12 Sven Neumann <sven@gimp.org>
* 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 <sven@gimp.org>
* app/tools/Makefile.am

View File

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

View File

@ -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 <gtk/gtk.h>
#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;
}

View File

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

View File

@ -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 <gtk/gtk.h>
#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;
}

View File

@ -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 <stdio.h>
#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~- ., å^[[Aöpl., k,km ,
m,^[[5~^[[6~^[[2~^[[C^[[3~p^[[A^[[^[[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__ */

View File

@ -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\" \

View File

@ -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 <gtk/gtk.h>
#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);
}

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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