Some updates for the Path-Tool.

Bye,
        Simon  (using Svens account)
This commit is contained in:
Sven Neumann 1999-10-03 19:13:54 +00:00
parent 7ccdba83bb
commit 2212b94fff
13 changed files with 1356 additions and 182 deletions

View File

@ -1,3 +1,32 @@
1999-10-3 Simon Budig <Simon.Budig@unix-ag.org>
* app/path_tool.h
* app/path_tool.c
* app/path_toolP.h
* app/path_curves.h
* app/path_curves.c
* app/path_bezier.h
* app/path_bezer.c
Lots of stuff for the bezier-tool which will be also used for the
interface for the intelligent scissors. I started to factor out the
formulas for the actual curve type, so it is some kind of independant.
To try this out simply change the "#if 0" in app/path_curve.c to
a "#if 1" to handle straight lines instead of strange beziers with
fixed handles :-)
The functions in app/path_curves.c implement some kind of
default-action, where useful. To implement a new curve-tzpe it
should be sufficient to overload the path_curve_get_point()
function. Of course, then the speed is not as performant... :-)
The API for other types is not yet completely fixed, esp. Im not
clear about when to give a Tool* or PathTool* as a parameter.
But it shows the way, I want to implement this. In the next step
I'll fill the stubs in app/path_bezer.c.
New handling functions: The Tool detects, when you are over an curve
and lets you split it there by shift clicking.
1999-10-03 Sven Neumann <sven@gimp.org> 1999-10-03 Sven Neumann <sven@gimp.org>
* app/channel_ops.c: copy resolution and unit information when duplicating * app/channel_ops.c: copy resolution and unit information when duplicating

View File

@ -131,3 +131,7 @@ checkin: populate
release: release:
$(MAKE) dist distdir=$(PACKAGE)`date +"%y%m%d"` $(MAKE) dist distdir=$(PACKAGE)`date +"%y%m%d"`
path_bezier.c \
path_bezier.h \
path_curves.c \
path_curves.h \

View File

@ -327,6 +327,10 @@ gimp_SOURCES = \
parasitelist.h \ parasitelist.h \
parasitelistF.h \ parasitelistF.h \
parasitelistP.h \ parasitelistP.h \
path_bezier.c \
path_bezier.h \
path_curves.c \
path_curves.h \
path_tool.c \ path_tool.c \
path_tool.h \ path_tool.h \
path_toolP.h \ path_toolP.h \

132
app/path_bezier.c Normal file
View File

@ -0,0 +1,132 @@
/* The GIMP -- an image manipulation program
*
* This file Copyright (C) 1999 Simon Budig
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "path_bezier.h"
/*
* This function is to get a set of npoints different coordinates for
* the range from start to end (each in the range from 0 to 1 and
* start < end.
* returns the number of created coords. Make sure that the points-
* Array is allocated.
*/
guint
path_bezier_get_points (PathTool *path_tool,
PathSegment *segment,
GdkPoint *points,
guint npoints,
gdouble start,
gdouble end)
{
return 0;
}
void
path_bezier_get_point (PathTool *path_tool,
PathSegment *segment,
gdouble position,
gdouble *x,
gdouble *y)
{
return;
}
void
path_bezier_draw_handles (Tool *tool,
PathSegment *segment)
{
return;
}
void
path_bezier_draw_segment (Tool *tool,
PathSegment *segment)
{
return;
}
gdouble
path_bezier_on_segment (Tool *tool,
PathSegment *segment,
gint x,
gint y,
gint halfwidth,
gint *distance)
{
return -1;
}
void
path_bezier_drag_segment (PathTool *path_tool,
PathSegment *segment,
gdouble position,
gint x,
gint y)
{
return;
}
gboolean
path_bezier_on_handles (PathTool *path_tool,
PathSegment *segment,
gint x,
gint y,
gint halfwidth)
{
return FALSE;
}
void
path_bezier_drag_handles (PathTool *path_tool,
PathSegment *segment,
gint x,
gint y)
{
return;
}
PathSegment *
path_bezier_insert_anchor (PathTool *path_tool,
PathSegment *segment,
gdouble position)
{
return NULL;
}
void
path_bezier_update_segment (PathTool *path_tool,
PathSegment *segment)
{
return;
}
void
path_bezier_flip_segment (PathTool *path_tool,
PathSegment *segment)
{
return;
}

103
app/path_bezier.h Normal file
View File

@ -0,0 +1,103 @@
/* The GIMP -- an image manipulation program
*
* This file Copyright (C) 1999 Simon Budig
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
* This function is to get a set of npoints different coordinates for
* the range from start to end (each in the range from 0 to 1 and
* start < end.
* returns the number of created coords. Make sure that the points-
* Array is allocated.
*/
#ifndef __PATH_BEZIER_H__
#define __PATH_BEZIER_H__
#include <gdk/gdk.h>
#include <glib.h>
#include "path_toolP.h"
guint
path_bezier_get_points (PathTool *path_tool,
PathSegment *segment,
GdkPoint *points,
guint npoints,
gdouble start,
gdouble end);
void
path_bezier_get_point (PathTool *path_tool,
PathSegment *segment,
gdouble position,
gdouble *x,
gdouble *y);
void
path_bezier_draw_handles (Tool *tool,
PathSegment *segment);
void
path_bezier_draw_segment (Tool *tool,
PathSegment *segment);
gdouble
path_bezier_on_segment (Tool *tool,
PathSegment *segment,
gint x,
gint y,
gint halfwidth,
gint *distance);
void
path_bezier_drag_segment (PathTool *path_tool,
PathSegment *segment,
gdouble position,
gint x,
gint y);
gboolean
path_bezier_on_handles (PathTool *path_tool,
PathSegment *segment,
gint x,
gint y,
gint halfwidth);
void
path_bezier_drag_handles (PathTool *path_tool,
PathSegment *segment,
gint x,
gint y);
PathSegment *
path_bezier_insert_anchor (PathTool *path_tool,
PathSegment *segment,
gdouble position);
void
path_bezier_update_segment (PathTool *path_tool,
PathSegment *segment);
void
path_bezier_flip_segment (PathTool *path_tool,
PathSegment *segment);
#endif /* __PATH_BEZIER_H__ */

307
app/path_curves.c Normal file
View File

@ -0,0 +1,307 @@
/* The GIMP -- an image manipulation program
*
* This file Copyright (C) 1999 Simon Budig
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <math.h>
#include "path_curves.h"
#include "path_bezier.h"
#ifdef PATH_TOOL_DEBUG
#include <stdio.h>
#endif
/* only here temporarily */
PathSegment * path_split_segment (PathSegment *, gdouble);
/* Here the different curves register their functions */
static CurveDescription CurveTypes[] =
{
/* SEGMENT_LINE */
{
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
},
/* SEGMENT_BEZIER */
{
path_bezier_get_points,
path_bezier_get_point,
path_bezier_draw_handles,
path_bezier_draw_segment,
path_bezier_on_segment,
path_bezier_drag_segment,
path_bezier_on_handles,
path_bezier_drag_handles,
path_bezier_insert_anchor,
path_bezier_update_segment,
path_bezier_flip_segment
}
};
/*
* these functions implement the dispatching for the different
* curve-types. It implements default actions, which happen
* to work with straight lines.
*/
guint
path_curve_get_points (PathTool *path_tool,
PathSegment *segment,
GdkPoint *points,
guint npoints,
gdouble start,
gdouble end)
{
gdouble pos, x, y;
gint index=0;
if (segment && CurveTypes[segment->type].get_points)
return (* CurveTypes[segment->type].get_points) (path_tool, segment, points, npoints, start, end);
else {
if (npoints > 1 && segment && segment->next) {
for (pos = start; pos <= end; pos += (end - start) / (npoints -1)) {
path_curve_get_point (path_tool, segment, pos, &x, &y);
points[index].x = (guint) (x + 0.5);
points[index].y = (guint) (y + 0.5);
index++;
}
return index;
} else
return 0;
}
}
void
path_curve_get_point (PathTool *path_tool,
PathSegment *segment,
gdouble position,
gdouble *x,
gdouble *y)
{
if (segment && CurveTypes[segment->type].get_point)
(* CurveTypes[segment->type].get_point) (path_tool, segment, position, x, y);
else {
if (segment && segment->next) {
#if 0
*x = segment->x + (segment->next->x - segment->x) * position;
*y = segment->y + (segment->next->y - segment->y) * position;
#else
/* Only here for debugging purposes: A bezier curve fith fixed tangents */
*x = (1-position)*(1-position)*(1-position) * segment->x +
3 * position *(1-position)*(1-position) * (segment->x - 60) +
3 * position * position *(1-position) * (segment->next->x + 60) +
position * position * position * (segment->next->x);
*y = (1-position)*(1-position)*(1-position) * segment->y +
3 * position *(1-position)*(1-position) * (segment->y + 60) +
3 * position * position *(1-position) * (segment->next->y + 60) +
position * position * position * (segment->next->y);
#endif
}
#ifdef PATH_TOOL_DEBUG
else
fprintf (stderr, "path_curve_get_point called without valid curve");
#endif
}
return;
}
void
path_curve_draw_handles (Tool *tool,
PathSegment *segment)
{
if (segment && CurveTypes[segment->type].draw_handles)
(* CurveTypes[segment->type].draw_handles) (tool, segment);
/* straight lines do not have handles... */
return;
}
void
path_curve_draw_segment (Tool *tool,
PathSegment *segment)
{
gint x, y, numpts, index;
if (segment && segment->next) {
if (CurveTypes[segment->type].draw_segment) {
(* CurveTypes[segment->type].draw_segment) (tool, segment);
return;
} else {
GdkPoint *coordinates = g_new (GdkPoint, 100);
numpts = path_curve_get_points (((PathTool *) tool->private), segment,
coordinates, 100, 0, 1);
for (index=0; index < numpts; index++) {
gdisplay_transform_coords (tool->gdisp_ptr,
coordinates[index].x,
coordinates[index].y,
&x, &y, FALSE);
coordinates[index].x = x;
coordinates[index].y = y;
}
gdk_draw_lines (((PathTool *) tool->private)->core->win,
((PathTool *) tool->private)->core->gc,
coordinates, numpts);
g_free (coordinates);
}
#ifdef PATH_TOOL_DEBUG
} else {
fprintf (stderr, "Fatal Error: path_curve_draw_segment called without valid segment *\n");
#endif
}
return;
}
gdouble
path_curve_on_segment (Tool *tool,
PathSegment *segment,
gint x,
gint y,
gint halfwidth,
gint *distance)
{
if (segment && CurveTypes[segment->type].on_segment)
return (* CurveTypes[segment->type].on_segment) (tool, segment, x, y, halfwidth, distance);
else {
if (segment && segment->next) {
#if 1
gint x1, y1, numpts, index;
GdkPoint *coordinates = g_new (GdkPoint, 100);
gint bestindex = -1;
*distance = halfwidth * halfwidth + 1;
numpts = path_curve_get_points (((PathTool *) tool->private), segment,
coordinates, 100, 0, 1);
for (index=0; index < numpts; index++) {
x1 = coordinates[index].x;
y1 = coordinates[index].y;
if (((x - x1) * (x - x1) + (y - y1) * (y - y1)) < *distance) {
*distance = (x - x1) * (x - x1) + (y - y1) * (y - y1);
bestindex = index;
}
}
g_free (coordinates);
if (numpts == 1) {
*distance = (gint) sqrt ((gdouble) *distance);
return bestindex;
}
if (bestindex >= 0 && (*distance <= halfwidth * halfwidth)) {
*distance = (gint) sqrt ((gdouble) *distance);
return bestindex == 0 ? 0 : ((gdouble) bestindex) / (numpts - 1);
}
#else
/* Special case for lines */
gdouble Ax, Ay, Bx, By, r, d;
Ax = segment->x;
Ay = segment->y;
Bx = segment->next->x;
By = segment->next->y;
r = (( x - Ax)*(Bx - Ax) + ( y - Ay)* (By - Ay)) /
((Bx - Ax)*(Bx - Ax) + (By - Ay)* (By - Ay)) ;
if (r >= 0 && r <= 1) {
d = (((Ax + (Bx - Ax) * r) - x) * ((Ax + (Bx - Ax) * r) - x) +
((Ay + (By - Ay) * r) - y) * ((Ay + (By - Ay) * r) - y));
if (d <= halfwidth * halfwidth) {
*distance = (gint) (d + 0.5);
return r;
}
}
#endif
}
}
return -1;
}
void
path_curve_drag_segment (PathTool *path_tool,
PathSegment *segment,
gdouble position,
gint x,
gint y
)
{
if (segment && CurveTypes[segment->type].drag_segment)
(* CurveTypes[segment->type].drag_segment) (path_tool, segment, position, x, y);
return;
}
gboolean
path_curve_on_handle (PathTool *path_tool,
PathSegment *segment,
gint x,
gint y,
gint halfwidth)
{
if (segment && CurveTypes[segment->type].on_handles)
return (* CurveTypes[segment->type].on_handles) (path_tool, segment, x, y, halfwidth);
return FALSE;
}
void
path_curve_drag_handle (PathTool *path_tool,
PathSegment *segment,
gint x,
gint y
)
{
if (segment && CurveTypes[segment->type].drag_handle)
(* CurveTypes[segment->type].drag_handle) (path_tool, segment, x, y);
}
PathSegment *
path_curve_insert_anchor (PathTool *path_tool,
PathSegment *segment,
gdouble position)
{
if (segment && CurveTypes[segment->type].insert_anchor)
return (* CurveTypes[segment->type].insert_anchor) (path_tool, segment, position);
else {
return path_split_segment (segment, position);
}
}
void
path_curve_flip_segment (PathTool *path_tool,
PathSegment *segment)
{
if (segment && CurveTypes[segment->type].flip_segment)
(* CurveTypes[segment->type].flip_segment) (path_tool, segment);
return;
}
void
path_curve_update_segment (PathTool *path_tool,
PathSegment *segment)
{
if (segment && CurveTypes[segment->type].update_segment)
(* CurveTypes[segment->type].update_segment) (path_tool, segment);
return;
}

201
app/path_curves.h Normal file
View File

@ -0,0 +1,201 @@
/* The GIMP -- an image manipulation program
*
* This file Copyright (C) 1999 Simon Budig
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __PATH_CURVES_H__
#define __PATH_CURVES_H__
#include <gdk/gdk.h>
#include "path_toolP.h"
/*
* This function is to get a set of npoints different coordinates for
* the range from start to end (each in the range from 0 to 1 and
* start < end).
* returns the number of created coords. Make sure that the points-
* Array is allocated.
*/
typedef guint (*PathGetPointsFunc) (PathTool *path_tool,
PathSegment *segment,
GdkPoint *points,
guint npoints,
gdouble start,
gdouble end);
typedef void (*PathGetPointFunc) (PathTool *path_tool,
PathSegment *segment,
gdouble position,
gdouble *x,
gdouble *y);
typedef void (*PathDrawHandlesFunc) (Tool *tool,
PathSegment *segment);
typedef void (*PathDrawSegmentFunc) (Tool *tool,
PathSegment *segment);
typedef gdouble (*PathOnSegmentFunc) (Tool *tool,
PathSegment *segment,
gint x,
gint y,
gint halfwidth,
gint *distance);
typedef void (*PathDragSegmentFunc) (PathTool *path_tool,
PathSegment *segment,
gdouble position,
gint x,
gint y
);
typedef gboolean (*PathOnHandlesFunc) (PathTool *path_tool,
PathSegment *segment,
gint x,
gint y,
gint halfwidth);
typedef void (*PathDragHandleFunc) (PathTool *path_tool,
PathSegment *segment,
gint x,
gint y
);
typedef PathSegment * (*PathInsertAnchorFunc) (PathTool *path_tool,
PathSegment *segment,
gdouble position);
typedef void (*PathUpdateSegmentFunc) (PathTool *path_tool,
PathSegment *segment);
typedef void (*PathFlipSegmentFunc) (PathTool *path_tool,
PathSegment *segment);
typedef struct {
PathGetPointsFunc get_points;
PathGetPointFunc get_point;
PathDrawHandlesFunc draw_handles;
PathDrawSegmentFunc draw_segment;
PathOnSegmentFunc on_segment;
PathDragSegmentFunc drag_segment;
PathOnHandlesFunc on_handles;
PathDragHandleFunc drag_handle;
PathInsertAnchorFunc insert_anchor;
PathUpdateSegmentFunc update_segment;
PathFlipSegmentFunc flip_segment;
} CurveDescription;
guint
path_curve_get_points (PathTool *path_tool,
PathSegment *segment,
GdkPoint *points,
guint npoints,
gdouble start,
gdouble end);
void
path_curve_get_point (PathTool *path_tool,
PathSegment *segment,
gdouble position,
gdouble *x,
gdouble *y);
void
path_curve_draw_handles (Tool *tool,
PathSegment *segment);
void
path_curve_draw_segment (Tool *tool,
PathSegment *segment);
gdouble
path_curve_on_segment (Tool *tool,
PathSegment *segment,
gint x,
gint y,
gint halfwidth,
gint *distance);
void
path_curve_drag_segment (PathTool *path_tool,
PathSegment *segment,
gdouble position,
gint x,
gint y
);
gboolean
path_curve_on_handle (PathTool *path_tool,
PathSegment *segment,
gint x,
gint y,
gint halfwidth);
void
path_curve_drag_handle (PathTool *path_tool,
PathSegment *segment,
gint x,
gint y);
PathSegment *
path_curve_insert_anchor (PathTool *path_tool,
PathSegment *segment,
gdouble position);
void
path_curve_update_segment (PathTool *path_tool,
PathSegment *segment);
void
path_curve_flip_segment (PathTool *path_tool,
PathSegment *segment);
/* This is, what Soleil (Olofs little daughter) has to say to this:
fc fc g hgvfvv drrrrrrtcc jctfcz w sdzs d bx cv^[ ^[c^[f c
vffvcccccccccccccggfc fvx^[c^[x^[x^[x^[x^[x^[x^[ v xbvcbvcxv cxxc xxxx^[x
xz^[c^[x^[x^[x^[x^[x^[x^[xxxxxxcccccccxxxxxxxxxxxxxxxvä"åp'
hj^[[24~^[[4~^[[1~^[[4~^[[1~^[[4~ ^[[D^[[Bk^[[B,,,,,
,^[[2~^[[4~^[[6~^[[4~l^[[6~,l' .holg^[[B^[[B n,,klmj ^[[B^[[1~j ^[[P^[[B
^[[D^[[4~^[[6~nb ^[[A^[[C ^[[Akj^[[B ^[[A^[[C^[[A
...^[[1~^[[D^[[4~^[[2~^[[C^[[B,^[[A^[[2~^[[C^[[2~^[[A^[[3~^[[A^[[4~ ^[[2~
^[[2~- ., å^[[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

@ -29,8 +29,6 @@
* segments between two anchors. * segments between two anchors.
*/ */
#undef PATH_TOOL_DEBUG
#include <math.h> #include <math.h>
/* #include "appenv.h" /* #include "appenv.h"
*/ */
@ -39,6 +37,7 @@
#include "cursorutil.h" #include "cursorutil.h"
#include "path_tool.h" #include "path_tool.h"
#include "path_toolP.h" #include "path_toolP.h"
#include "path_curves.h"
#ifdef PATH_TOOL_DEBUG #ifdef PATH_TOOL_DEBUG
#include <stdio.h> #include <stdio.h>
@ -63,51 +62,52 @@
/* Small functions to determine coordinates, iterate over path/curve/segment */ /* Small functions to determine coordinates, iterate over path/curve/segment */
static void path_segment_get_coordinates (PathSegment *, gdouble, gint *, gint *); void path_segment_get_coordinates (PathSegment *, gdouble, gint *, gint *);
static void path_traverse_path (Path *, PathTraverseFunc, CurveTraverseFunc, SegmentTraverseFunc, gpointer); void path_traverse_path (Path *, PathTraverseFunc, CurveTraverseFunc, SegmentTraverseFunc, gpointer);
static void path_traverse_curve (Path *, PathCurve *, CurveTraverseFunc, SegmentTraverseFunc, gpointer); void path_traverse_curve (Path *, PathCurve *, CurveTraverseFunc, SegmentTraverseFunc, gpointer);
static void path_traverse_segment (Path *, PathCurve *, PathSegment *, SegmentTraverseFunc, gpointer); void path_traverse_segment (Path *, PathCurve *, PathSegment *, SegmentTraverseFunc, gpointer);
static gdouble path_locate_point (Path *, PathCurve **, PathSegment **, gint, gint, gint, gint, gint); gdouble path_locate_point (Path *, PathCurve **, PathSegment **, gint, gint, gint, gint, gint);
/* Tools to manipulate paths, curves, segments */ /* Tools to manipulate paths, curves, segments */
static PathCurve * path_add_curve (Path *, gint, gint); PathCurve * path_add_curve (Path *, gint, gint);
static PathSegment * path_append_segment (Path *, PathCurve *, SegmentType, gint, gint); PathSegment * path_append_segment (Path *, PathCurve *, SegmentType, gint, gint);
static PathSegment * path_prepend_segment (Path *, PathCurve *, SegmentType, gint, gint); PathSegment * path_prepend_segment (Path *, PathCurve *, SegmentType, gint, gint);
static PathSegment * path_split_segment (PathSegment *, gdouble); PathSegment * path_split_segment (PathSegment *, gdouble);
static void path_join_curves (PathSegment *, PathSegment *); void path_join_curves (PathSegment *, PathSegment *);
static void path_flip_curve (PathCurve *); void path_flip_curve (PathCurve *);
static void path_free_path (Path *); void path_free_path (Path *);
static void path_free_curve (PathCurve *); void path_free_curve (PathCurve *);
static void path_free_segment (PathSegment *); void path_free_segment (PathSegment *);
static void path_delete_segment (PathSegment *); void path_delete_segment (PathSegment *);
static void path_print (Path *); void path_print (Path *);
static void path_offset_active (Path *, gdouble, gdouble); void path_offset_active (Path *, gdouble, gdouble);
static void path_set_flags (PathTool *, Path *, PathCurve *, PathSegment *, guint32, guint32); void path_set_flags (PathTool *, Path *, PathCurve *, PathSegment *, guint32, guint32);
/* High level image-manipulation functions */ /* High level image-manipulation functions */
static void path_stroke (PathTool *, Path *); void path_stroke (PathTool *, Path *);
static void path_to_selection (PathTool *, Path *); void path_to_selection (PathTool *, Path *);
/* Functions necessary for the tool */ /* Functions necessary for the tool */
static void path_tool_button_press (Tool *, GdkEventButton *, gpointer); void path_tool_button_press (Tool *, GdkEventButton *, gpointer);
static void path_tool_button_release (Tool *, GdkEventButton *, gpointer); void path_tool_button_release (Tool *, GdkEventButton *, gpointer);
static void path_tool_motion (Tool *, GdkEventMotion *, gpointer); void path_tool_motion (Tool *, GdkEventMotion *, gpointer);
static void path_tool_cursor_update (Tool *, GdkEventMotion *, gpointer); void path_tool_cursor_update (Tool *, GdkEventMotion *, gpointer);
static void path_tool_control (Tool *, ToolAction, gpointer); void path_tool_control (Tool *, ToolAction, gpointer);
static void path_tool_draw (Tool *); void path_tool_draw (Tool *);
static void path_tool_draw_curve (Tool *, PathCurve *); void path_tool_draw_curve (Tool *, PathCurve *);
static void path_tool_draw_segment (Tool *, PathSegment *); void path_tool_draw_segment (Tool *, PathSegment *);
static gboolean path_tool_on_anchors (Tool *, gint, gint, gint, Path**, PathCurve**, PathSegment**); gboolean path_tool_on_anchors (Tool *, gint, gint, gint, Path**, PathCurve**, PathSegment**);
static gboolean path_tool_on_handles (Tool *, gint, gint, gint); gdouble path_tool_on_curve (Tool *, gint, gint, gint, Path**, PathCurve**, PathSegment**);
static gboolean path_tool_on_curve (Tool *, gint, gint, gint); gboolean path_tool_on_handles (Tool *, gint, gint, gint);
static gint path_tool_button_press_canvas (Tool *, GdkEventButton *, GDisplay *); gint path_tool_button_press_canvas (Tool *, GdkEventButton *, GDisplay *);
static gint path_tool_button_press_anchor (Tool *, GdkEventButton *, GDisplay *); gint path_tool_button_press_anchor (Tool *, GdkEventButton *, GDisplay *);
static void path_tool_motion_anchor (Tool *, GdkEventMotion *, GDisplay *); gint path_tool_button_press_curve (Tool *, GdkEventButton *, GDisplay *);
static void path_tool_motion_curve (Tool *, GdkEventMotion *, GDisplay *); void path_tool_motion_anchor (Tool *, GdkEventMotion *, GDisplay *);
void path_tool_motion_curve (Tool *, GdkEventMotion *, GDisplay *);
/* the path tool options */ /* the path tool options */
@ -138,7 +138,7 @@ static ToolOptions *path_options = NULL;
* *
*/ */
static void void
path_traverse_path (Path *path, PathTraverseFunc pathfunc, CurveTraverseFunc curvefunc, SegmentTraverseFunc segmentfunc, gpointer data) path_traverse_path (Path *path, PathTraverseFunc pathfunc, CurveTraverseFunc curvefunc, SegmentTraverseFunc segmentfunc, gpointer data)
{ {
PathCurve *cur_curve; PathCurve *cur_curve;
@ -160,7 +160,7 @@ path_traverse_path (Path *path, PathTraverseFunc pathfunc, CurveTraverseFunc cur
} }
static void void
path_traverse_curve (Path *path, PathCurve *curve, CurveTraverseFunc curvefunc, SegmentTraverseFunc segmentfunc, gpointer data) path_traverse_curve (Path *path, PathCurve *curve, CurveTraverseFunc curvefunc, SegmentTraverseFunc segmentfunc, gpointer data)
{ {
PathSegment *cur_segment; PathSegment *cur_segment;
@ -181,13 +181,15 @@ path_traverse_curve (Path *path, PathCurve *curve, CurveTraverseFunc curvefunc,
} }
} }
static void void
path_traverse_segment (Path *path, PathCurve *curve, PathSegment *segment, SegmentTraverseFunc function, gpointer data) path_traverse_segment (Path *path, PathCurve *curve, PathSegment *segment, SegmentTraverseFunc function, gpointer data)
{ {
#ifdef PATH_TOOL_DEBUG #ifdef PATH_TOOL_DEBUG
fprintf(stderr, "path_traverse_segment\n"); fprintf(stderr, "path_traverse_segment\n");
#endif PATH_TOOL_DEBUG #endif PATH_TOOL_DEBUG
#warning here we need path_curve_get_point(s)
/* Something like: /* Something like:
* for i = 1 to subsamples { * for i = 1 to subsamples {
* (x,y) = get_coordinates(i / subsamples) * (x,y) = get_coordinates(i / subsamples)
@ -200,7 +202,7 @@ path_traverse_segment (Path *path, PathCurve *curve, PathSegment *segment, Segme
* Helper functions for manipulating the data-structures: * Helper functions for manipulating the data-structures:
*/ */
static PathCurve *path_add_curve (Path * cur_path, gint x, gint y) PathCurve *path_add_curve (Path * cur_path, gint x, gint y)
{ {
PathCurve * tmp = cur_path->curves; PathCurve * tmp = cur_path->curves;
PathCurve * new_curve = NULL; PathCurve * new_curve = NULL;
@ -233,7 +235,7 @@ static PathCurve *path_add_curve (Path * cur_path, gint x, gint y)
} }
static PathSegment * path_append_segment (Path * cur_path, PathCurve * cur_curve, SegmentType type, gint x, gint y) PathSegment * path_append_segment (Path * cur_path, PathCurve * cur_curve, SegmentType type, gint x, gint y)
{ {
PathSegment * tmp = cur_curve->segments; PathSegment * tmp = cur_curve->segments;
PathSegment * new_segment = NULL; PathSegment * new_segment = NULL;
@ -264,6 +266,9 @@ static PathSegment * path_append_segment (Path * cur_path, PathCurve * cur_curv
tmp->next = new_segment; tmp->next = new_segment;
cur_curve->cur_segment = new_segment; cur_curve->cur_segment = new_segment;
#warning we need initialisation of the segment here.
} }
#ifdef PATH_TOOL_DEBUG #ifdef PATH_TOOL_DEBUG
else else
@ -279,7 +284,7 @@ static PathSegment * path_append_segment (Path * cur_path, PathCurve * cur_curv
} }
static PathSegment * path_prepend_segment (Path * cur_path, PathCurve * cur_curve, SegmentType type, gint x, gint y) PathSegment * path_prepend_segment (Path * cur_path, PathCurve * cur_curve, SegmentType type, gint x, gint y)
{ {
PathSegment * tmp = cur_curve->segments; PathSegment * tmp = cur_curve->segments;
PathSegment * new_segment = NULL; PathSegment * new_segment = NULL;
@ -308,6 +313,7 @@ static PathSegment * path_prepend_segment (Path * cur_path, PathCurve * cur_cur
cur_curve->segments = new_segment; cur_curve->segments = new_segment;
cur_curve->cur_segment = new_segment; cur_curve->cur_segment = new_segment;
#warning we need initialisation of the segment here.
} }
#ifdef PATH_TOOL_DEBUG #ifdef PATH_TOOL_DEBUG
else else
@ -322,15 +328,47 @@ static PathSegment * path_prepend_segment (Path * cur_path, PathCurve * cur_cur
return new_segment; return new_segment;
} }
/* static PathSegment * path_split_segment (PathSegment *, gdouble); PathSegment * path_split_segment (PathSegment *segment, gdouble position)
*/ {
PathSegment * new_segment = NULL;
#ifdef PATH_TOOL_DEBUG
fprintf(stderr, "path_split_segment\n");
#endif PATH_TOOL_DEBUG
if (segment && segment->next) {
new_segment = g_new (PathSegment, 1);
new_segment->type = segment->type;
#warning Giving PathTool as NULL Pointer!
path_curve_get_point (NULL, segment, position, &(new_segment->x), &(new_segment->y));
new_segment->flags = 0;
new_segment->parent = segment->parent;
new_segment->next = segment->next;
new_segment->prev = segment;
new_segment->data = NULL;
#warning we need initialisation of the segment here.
new_segment->next->prev = new_segment;
segment->next = new_segment;
return new_segment;
}
#ifdef PATH_TOOL_DEBUG
else
fprintf(stderr, "path_split_segment without valid segment\n");
#endif PATH_TOOL_DEBUG
return NULL;
}
/* /*
* Join two arbitrary endpoints and free the parent from the second * Join two arbitrary endpoints and free the parent from the second
* segment, if it differs from the first parents. * segment, if it differs from the first parents.
*/ */
static void void
path_join_curves (PathSegment *segment1, PathSegment *segment2) { path_join_curves (PathSegment *segment1, PathSegment *segment2) {
PathCurve *curve1, *curve2; PathCurve *curve1, *curve2;
PathSegment *tmp; PathSegment *tmp;
@ -352,6 +390,7 @@ path_join_curves (PathSegment *segment1, PathSegment *segment2) {
segment2->prev = segment1; segment2->prev = segment1;
segment1->next = segment2; segment1->next = segment2;
} }
#warning Probably some segment-updates needed
return; return;
} }
@ -403,6 +442,7 @@ path_join_curves (PathSegment *segment1, PathSegment *segment2) {
tmp->parent = curve1; tmp->parent = curve1;
tmp = tmp->next; tmp = tmp->next;
} }
#warning Probably some segment-updates needed
return; return;
} }
@ -433,10 +473,11 @@ path_join_curves (PathSegment *segment1, PathSegment *segment2) {
tmp = tmp->prev; tmp = tmp->prev;
} }
return; return;
#warning Probably some segment-updates needed
} }
#ifdef PATH_TOOL_DEBUG #ifdef PATH_TOOL_DEBUG
fprintf (stderr, "Cant join these curves yet...\n"); fprintf (stderr, "Cant join these curves yet...\nThis should not happen.");
return; return;
#endif PATH_TOOL_DEBUG #endif PATH_TOOL_DEBUG
@ -446,7 +487,7 @@ path_join_curves (PathSegment *segment1, PathSegment *segment2) {
* This function reverses the order of the anchors. This is * This function reverses the order of the anchors. This is
* necessary for some joining operations. * necessary for some joining operations.
*/ */
static void void
path_flip_curve (PathCurve *curve) path_flip_curve (PathCurve *curve)
{ {
gpointer *end_data; gpointer *end_data;
@ -454,6 +495,8 @@ path_flip_curve (PathCurve *curve)
PathSegment *tmp, *tmp2; PathSegment *tmp, *tmp2;
#warning Please add path_curve_flip_segment here
if (!curve && !curve->segments) { if (!curve && !curve->segments) {
#ifdef PATH_TOOL_DEBUG #ifdef PATH_TOOL_DEBUG
fprintf (stderr, "path_flip_curve: No curve o no segments to flip!\n"); fprintf (stderr, "path_flip_curve: No curve o no segments to flip!\n");
@ -483,11 +526,12 @@ path_flip_curve (PathCurve *curve)
tmp->data = end_data; tmp->data = end_data;
} }
tmp = tmp->next; tmp = tmp->next;
#warning Probably some segment-updates needed
} }
} }
static void void
path_free_path (Path * path) path_free_path (Path * path)
{ {
PathCurve *tmp1, *tmp2; PathCurve *tmp1, *tmp2;
@ -495,18 +539,18 @@ path_free_path (Path * path)
if (path) if (path)
{ {
tmp2 = path->curves; tmp2 = path->curves;
g_string_free(path->name, TRUE);
g_free(path);
while ((tmp1 = tmp2) != NULL) while ((tmp1 = tmp2) != NULL)
{ {
tmp2 = tmp1->next; tmp2 = tmp1->next;
path_free_curve (tmp1); path_free_curve (tmp1);
} }
g_string_free(path->name, TRUE);
g_free(path);
} }
} }
static void void
path_free_curve (PathCurve *curve) path_free_curve (PathCurve *curve)
{ {
PathSegment *tmp1, *tmp2; PathSegment *tmp1, *tmp2;
@ -528,7 +572,7 @@ path_free_curve (PathCurve *curve)
} }
} }
static void void
path_free_segment (PathSegment *segment) path_free_segment (PathSegment *segment)
{ {
if (segment) if (segment)
@ -538,11 +582,12 @@ path_free_segment (PathSegment *segment)
segment->parent, segment, 0, SEGMENT_ACTIVE); segment->parent, segment, 0, SEGMENT_ACTIVE);
if (segment->data) if (segment->data)
g_free(segment->data); g_free(segment->data);
#warning Free Segment needs an own hook in the different curve-types!
g_free (segment); g_free (segment);
} }
} }
static void void
path_delete_curve (PathCurve *curve) path_delete_curve (PathCurve *curve)
{ {
if (curve) if (curve)
@ -560,7 +605,7 @@ path_delete_curve (PathCurve *curve)
} }
} }
static void void
path_delete_segment (PathSegment *segment) path_delete_segment (PathSegment *segment)
{ {
if (segment) if (segment)
@ -587,6 +632,7 @@ path_delete_segment (PathSegment *segment)
/* /*
* here we have to update the surrounding segments * here we have to update the surrounding segments
*/ */
#warning Please add path_curve_update_segment here
} }
} }
@ -595,14 +641,21 @@ path_delete_segment (PathSegment *segment)
* A function to determine, which object is hit by the cursor * A function to determine, which object is hit by the cursor
*/ */
static gint gint
path_tool_cursor_position (Tool *tool, gint x, gint y, gint halfwidth, Path **pathP, PathCurve **curveP, PathSegment **segmentP) path_tool_cursor_position (Tool *tool, gint x, gint y, gint halfwidth, Path **pathP, PathCurve **curveP, PathSegment **segmentP, gdouble *positionP)
{ {
gint location; gint location;
gdouble pos;
if (path_tool_on_anchors (tool, x, y, halfwidth, pathP, curveP, segmentP)) if (path_tool_on_anchors (tool, x, y, halfwidth, pathP, curveP, segmentP))
return ON_ANCHOR; return ON_ANCHOR;
pos = path_tool_on_curve (tool, x, y, halfwidth, pathP, curveP, segmentP);
if (pos >= 0 && pos <= 1) {
if (positionP) (*positionP) = pos;
return ON_CURVE;
}
return ON_CANVAS; return ON_CANVAS;
} }
@ -611,7 +664,7 @@ path_tool_cursor_position (Tool *tool, gint x, gint y, gint halfwidth, Path **pa
* The click-callbacks for the tool * The click-callbacks for the tool
*/ */
static void void
path_tool_button_press (Tool *tool, path_tool_button_press (Tool *tool,
GdkEventButton *bevent, GdkEventButton *bevent,
gpointer gdisp_ptr) gpointer gdisp_ptr)
@ -649,12 +702,13 @@ path_tool_button_press (Tool *tool,
* switch accordingly. * switch accordingly.
*/ */
path_tool->click_pos = path_tool_cursor_position(tool, x, y, halfwidth, path_tool->click_type = path_tool_cursor_position(tool, x, y, halfwidth,
&(path_tool->click_path), &(path_tool->click_path),
&(path_tool->click_curve), &(path_tool->click_curve),
&(path_tool->click_segment)); &(path_tool->click_segment),
&(path_tool->click_position));
switch (path_tool->click_pos) switch (path_tool->click_type)
{ {
case ON_CANVAS: case ON_CANVAS:
grab_pointer = path_tool_button_press_canvas(tool, bevent, gdisp); grab_pointer = path_tool_button_press_canvas(tool, bevent, gdisp);
@ -664,6 +718,10 @@ path_tool_button_press (Tool *tool,
grab_pointer = path_tool_button_press_anchor(tool, bevent, gdisp); grab_pointer = path_tool_button_press_anchor(tool, bevent, gdisp);
break; break;
case ON_CURVE:
grab_pointer = path_tool_button_press_curve(tool, bevent, gdisp);
break;
default: default:
g_message("Huh? Whats happening here? (button_press_*)"); g_message("Huh? Whats happening here? (button_press_*)");
} }
@ -679,7 +737,7 @@ path_tool_button_press (Tool *tool,
} }
static gint gint
path_tool_button_press_anchor (Tool *tool, path_tool_button_press_anchor (Tool *tool,
GdkEventButton *bevent, GdkEventButton *bevent,
GDisplay *gdisp) GDisplay *gdisp)
@ -789,6 +847,7 @@ path_tool_button_press_anchor (Tool *tool,
path_delete_segment (path_tool->click_segment); path_delete_segment (path_tool->click_segment);
path_tool->click_segment = NULL; 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)) else if (!(path_tool->click_segment->flags & SEGMENT_ACTIVE))
{ {
@ -797,14 +856,12 @@ path_tool_button_press_anchor (Tool *tool,
} }
/* Action goes here */
draw_core_resume(path_tool->core, tool); draw_core_resume(path_tool->core, tool);
return grab_pointer; return grab_pointer;
} }
static gint gint
path_tool_button_press_canvas (Tool *tool, path_tool_button_press_canvas (Tool *tool,
GdkEventButton *bevent, GdkEventButton *bevent,
GDisplay *gdisp) GDisplay *gdisp)
@ -857,7 +914,48 @@ path_tool_button_press_canvas (Tool *tool,
return 0; return 0;
} }
static void gint
path_tool_button_press_curve (Tool *tool,
GdkEventButton *bevent,
GDisplay *gdisp)
{
PathTool *path_tool = tool->private;
Path * cur_path = path_tool->cur_path;
PathCurve * cur_curve;
PathSegment * cur_segment;
gint grab_pointer;
#ifdef PATH_TOOL_DEBUG
fprintf(stderr, "path_tool_button_press_curve:\n");
#endif PATH_TOOL_DEBUG
grab_pointer = 1;
if (!cur_path) {
#ifdef PATH_TOOL_DEBUG
fprintf (stderr, "Fatal error: No current Path\n");
#endif PATH_TOOL_DEBUG
return 0;
}
draw_core_pause (path_tool->core, tool);
if (path_tool->click_modifier & GDK_SHIFT_MASK) {
cur_segment = path_curve_insert_anchor (path_tool, path_tool->click_segment, path_tool->click_position);
path_set_flags (path_tool, cur_path, NULL, NULL, 0, SEGMENT_ACTIVE);
path_set_flags (path_tool, cur_path, path_tool->click_curve, cur_segment, SEGMENT_ACTIVE, 0);
path_tool->click_type = ON_ANCHOR;
path_tool->click_segment = cur_segment;
}
draw_core_resume(path_tool->core, tool);
return 0;
}
void
path_tool_button_release (Tool *tool, path_tool_button_release (Tool *tool,
GdkEventButton *bevent, GdkEventButton *bevent,
gpointer gdisp_ptr) gpointer gdisp_ptr)
@ -883,7 +981,7 @@ path_tool_button_release (Tool *tool,
* The motion-callbacks for the tool * The motion-callbacks for the tool
*/ */
static void void
path_tool_motion (Tool *tool, path_tool_motion (Tool *tool,
GdkEventMotion *mevent, GdkEventMotion *mevent,
gpointer gdisp_ptr) gpointer gdisp_ptr)
@ -896,7 +994,7 @@ path_tool_motion (Tool *tool,
gdisp = (GDisplay *) gdisp_ptr; gdisp = (GDisplay *) gdisp_ptr;
path_tool = (PathTool *) tool->private; path_tool = (PathTool *) tool->private;
switch (path_tool->click_pos) { switch (path_tool->click_type) {
case ON_ANCHOR: case ON_ANCHOR:
path_tool_motion_anchor(tool, mevent, gdisp); path_tool_motion_anchor(tool, mevent, gdisp);
break; break;
@ -906,7 +1004,7 @@ path_tool_motion (Tool *tool,
} }
static void void
path_tool_motion_anchor (Tool *tool, path_tool_motion_anchor (Tool *tool,
GdkEventMotion *mevent, GdkEventMotion *mevent,
GDisplay *gdisp) GDisplay *gdisp)
@ -977,7 +1075,7 @@ path_tool_motion_anchor (Tool *tool,
} }
static void void
path_tool_cursor_update (Tool *tool, path_tool_cursor_update (Tool *tool,
GdkEventMotion *mevent, GdkEventMotion *mevent,
gpointer gdisp_ptr) gpointer gdisp_ptr)
@ -999,13 +1097,16 @@ path_tool_cursor_update (Tool *tool,
gdisplay_untransform_coords (gdisp, mevent->x + PATH_TOOL_HALFWIDTH, 0, &halfwidth, &dummy, TRUE, 0); gdisplay_untransform_coords (gdisp, mevent->x + PATH_TOOL_HALFWIDTH, 0, &halfwidth, &dummy, TRUE, 0);
halfwidth -= x; halfwidth -= x;
cursor_location = path_tool_cursor_position(tool, x, y, halfwidth, NULL, NULL, NULL); cursor_location = path_tool_cursor_position(tool, x, y, halfwidth, NULL, NULL, NULL, NULL);
switch (cursor_location) { switch (cursor_location) {
case ON_CANVAS: case ON_CANVAS:
gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE1AP_CURSOR); gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE1AP_CURSOR);
break; break;
case ON_ANCHOR: case ON_ANCHOR:
gdisplay_install_tool_cursor (gdisp, GDK_FLEUR);
break;
case ON_CURVE:
gdisplay_install_tool_cursor (gdisp, GDK_TCROSS); gdisplay_install_tool_cursor (gdisp, GDK_TCROSS);
break; break;
default: default:
@ -1018,7 +1119,7 @@ path_tool_cursor_update (Tool *tool,
* Tool-control functions * Tool-control functions
*/ */
static void void
path_tool_control (Tool *tool, path_tool_control (Tool *tool,
ToolAction action, ToolAction action,
gpointer gdisp_ptr) gpointer gdisp_ptr)
@ -1044,6 +1145,9 @@ path_tool_control (Tool *tool,
break; break;
case HALT: case HALT:
#ifdef PATH_TOOL_DEBUG
fprintf (stderr, "path_tool_control: HALT\n");
#endif PATH_TOOL_DEBUG
draw_core_stop (path_tool->core, tool); draw_core_stop (path_tool->core, tool);
tool->state = INACTIVE; tool->state = INACTIVE;
break; break;
@ -1051,6 +1155,9 @@ path_tool_control (Tool *tool,
default: default:
break; break;
} }
#ifdef PATH_TOOL_DEBUG
fprintf (stderr, "path_tool_control: end\n");
#endif PATH_TOOL_DEBUG
} }
Tool * Tool *
@ -1069,11 +1176,15 @@ tools_new_path_tool (void)
tool = tools_new_tool (PATH_TOOL); tool = tools_new_tool (PATH_TOOL);
private = g_new (PathTool, 1); private = g_new (PathTool, 1);
private->click_pos = ON_CANVAS; private->click_type = ON_CANVAS;
private->click_x = 0; private->click_x = 0;
private->click_y = 0; private->click_y = 0;
private->click_halfwidth = 0; private->click_halfwidth = 0;
private->click_modifier = 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->active_count = 0;
private->single_active_segment = NULL; private->single_active_segment = NULL;
@ -1108,6 +1219,9 @@ tools_free_path_tool (Tool *tool)
GDisplay * gdisp; GDisplay * gdisp;
PathTool * path_tool; PathTool * path_tool;
#ifdef PATH_TOOL_DEBUG
fprintf (stderr, "tools_free_path_tool start\n");
#endif PATH_TOOL_DEBUG
path_tool = (PathTool *) tool->private; path_tool = (PathTool *) tool->private;
gdisp = (GDisplay *) tool->gdisp_ptr; gdisp = (GDisplay *) tool->gdisp_ptr;
@ -1121,9 +1235,84 @@ tools_free_path_tool (Tool *tool)
draw_core_free (path_tool->core); draw_core_free (path_tool->core);
g_free (path_tool); g_free (path_tool);
#ifdef PATH_TOOL_DEBUG
fprintf (stderr, "tools_free_path_tool end\n");
#endif PATH_TOOL_DEBUG
} }
/**************************************************************
* Set of function to determine, if the click was on an segment
*/
typedef struct {
Tool *tool;
Path *path;
PathCurve *curve;
PathSegment *segment;
gint testx;
gint testy;
gint halfwidth;
gint distance;
gdouble position;
gboolean found;
} Path_on_curve_type;
/* This is a CurveTraverseFunc */
void
path_tool_on_curve_helper (Path *path, PathCurve *curve, PathSegment *segment, gpointer ptr)
{
gint distance;
gdouble position;
Path_on_curve_type *data = (Path_on_curve_type *) ptr;
if (segment && segment->next && data && data->distance > 0)
{
position = path_curve_on_segment (data->tool, segment, data->testx, data->testy, data->halfwidth, &distance);
if (position >= 0 && distance < data->distance )
{
data->path = path;
data->curve = curve;
data->segment = segment;
data->distance = distance;
data->position = position;
data->found = TRUE;
}
}
}
gdouble
path_tool_on_curve (Tool *tool, gint x, gint y, gint halfwidth, Path **ret_pathP, PathCurve **ret_curveP, PathSegment **ret_segmentP)
{
Path_on_curve_type *data = g_new (Path_on_curve_type, 1);
gdouble position;
data->tool = tool;
data->path = NULL;
data->segment = NULL;
data->segment = NULL;
data->testx = x;
data->testy = y;
data->halfwidth = halfwidth;
data->distance = halfwidth * halfwidth + 1;
data->position = -1;
data->found = FALSE;
path_traverse_path (((PathTool *) data->tool->private)->cur_path, NULL, path_tool_on_curve_helper, NULL, data);
if (ret_pathP) *ret_pathP = data->path;
if (ret_curveP) *ret_curveP = data->curve;
if (ret_segmentP) *ret_segmentP = data->segment;
position = data->position;
g_free(data);
return position;
}
/************************************************************** /**************************************************************
* Set of function to determine, if the click was on an anchor * Set of function to determine, if the click was on an anchor
*/ */
@ -1139,7 +1328,7 @@ typedef struct {
} Path_on_anchors_type; } Path_on_anchors_type;
/* This is a CurveTraverseFunc */ /* This is a CurveTraverseFunc */
static void void
path_tool_on_anchors_helper (Path *path, PathCurve *curve, PathSegment *segment, gpointer ptr) path_tool_on_anchors_helper (Path *path, PathCurve *curve, PathSegment *segment, gpointer ptr)
{ {
gint distance; gint distance;
@ -1161,7 +1350,7 @@ path_tool_on_anchors_helper (Path *path, PathCurve *curve, PathSegment *segment,
} }
} }
static gboolean gboolean
path_tool_on_anchors (Tool *tool, gint x, gint y, gint halfwidth, Path **ret_pathP, PathCurve **ret_curveP, PathSegment **ret_segmentP) path_tool_on_anchors (Tool *tool, gint x, gint y, gint halfwidth, Path **ret_pathP, PathCurve **ret_curveP, PathSegment **ret_segmentP)
{ {
Path_on_anchors_type *data = g_new (Path_on_anchors_type, 1); Path_on_anchors_type *data = g_new (Path_on_anchors_type, 1);
@ -1200,7 +1389,7 @@ typedef struct {
} Path_offset_active_type; } Path_offset_active_type;
/* This is a CurveTraverseFunc */ /* This is a CurveTraverseFunc */
static void void
path_offset_active_helper (Path *path, PathCurve *curve, PathSegment *segment, gpointer ptr) path_offset_active_helper (Path *path, PathCurve *curve, PathSegment *segment, gpointer ptr)
{ {
Path_offset_active_type *data = (Path_offset_active_type *) ptr; Path_offset_active_type *data = (Path_offset_active_type *) ptr;
@ -1209,9 +1398,10 @@ path_offset_active_helper (Path *path, PathCurve *curve, PathSegment *segment, g
segment->x += data->dx; segment->x += data->dx;
segment->y += data->dy; segment->y += data->dy;
} }
#warning Do a segment_update here!
} }
static void void
path_offset_active (Path *path, gdouble dx, gdouble dy) path_offset_active (Path *path, gdouble dx, gdouble dy)
{ {
Path_offset_active_type *data = g_new (Path_offset_active_type, 1); Path_offset_active_type *data = g_new (Path_offset_active_type, 1);
@ -1226,7 +1416,7 @@ path_offset_active (Path *path, gdouble dx, gdouble dy)
/************************************************************** /**************************************************************
* Set of function to set the state of all anchors to inactive * Set of function to set the state of all anchors
*/ */
typedef struct { typedef struct {
@ -1236,7 +1426,7 @@ typedef struct {
} Path_set_flags_type; } Path_set_flags_type;
/* This is a CurveTraverseFunc */ /* This is a CurveTraverseFunc */
static void void
path_set_flags_helper (Path *path, PathCurve *curve, PathSegment *segment, gpointer ptr) path_set_flags_helper (Path *path, PathCurve *curve, PathSegment *segment, gpointer ptr)
{ {
Path_set_flags_type *tmp = (Path_set_flags_type *) ptr; Path_set_flags_type *tmp = (Path_set_flags_type *) ptr;
@ -1272,7 +1462,7 @@ path_set_flags_helper (Path *path, PathCurve *curve, PathSegment *segment, gpoin
} }
} }
static void void
path_set_flags (PathTool *path_tool, Path *path, PathCurve *curve, PathSegment *segment, guint32 bits_set, guint32 bits_clear) path_set_flags (PathTool *path_tool, Path *path, PathCurve *curve, PathSegment *segment, guint32 bits_set, guint32 bits_clear)
{ {
Path_set_flags_type *tmp = g_new (Path_set_flags_type, 1); Path_set_flags_type *tmp = g_new (Path_set_flags_type, 1);
@ -1296,7 +1486,7 @@ path_set_flags (PathTool *path_tool, Path *path, PathCurve *curve, PathSegment *
*/ */
/* This is a CurveTraverseFunc */ /* This is a CurveTraverseFunc */
static void void
path_tool_draw_helper (Path *path, PathCurve *curve, PathSegment * segment, gpointer tool_ptr) path_tool_draw_helper (Path *path, PathCurve *curve, PathSegment * segment, gpointer tool_ptr)
{ {
Tool * tool = (Tool *) tool_ptr; Tool * tool = (Tool *) tool_ptr;
@ -1335,8 +1525,7 @@ path_tool_draw_helper (Path *path, PathCurve *curve, PathSegment * segment, gpoi
if (segment->next) if (segment->next)
{ {
gdisplay_transform_coords (gdisp, (gint) segment->next->x, (gint) segment->next->y, &x2, &y2, FALSE); path_curve_draw_segment (tool, segment);
gdk_draw_line (core->win, core->gc, x1, y1, x2, y2);
} }
} }
#ifdef PATH_TOOL_DEBUG #ifdef PATH_TOOL_DEBUG
@ -1345,7 +1534,7 @@ path_tool_draw_helper (Path *path, PathCurve *curve, PathSegment * segment, gpoi
#endif PATH_TOOL_DEBUG #endif PATH_TOOL_DEBUG
} }
static void void
path_tool_draw (Tool *tool) path_tool_draw (Tool *tool)
{ {
GDisplay * gdisp; GDisplay * gdisp;
@ -1363,4 +1552,10 @@ path_tool_draw (Tool *tool)
path_traverse_path (cur_path, NULL, path_tool_draw_helper, NULL, tool); path_traverse_path (cur_path, NULL, path_tool_draw_helper, NULL, tool);
#ifdef PATH_TOOL_DEBUG
fprintf (stderr, "path_tool_draw end.\n");
#endif PATH_TOOL_DEBUG
} }

View File

@ -1,5 +1,6 @@
/* The GIMP -- an image manipulation program /* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis *
* This file Copyright (C) 1999 Simon Budig
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -15,6 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
#ifndef __PATH_TOOL_H__ #ifndef __PATH_TOOL_H__
#define __PATH_TOOL_H__ #define __PATH_TOOL_H__

View File

@ -18,6 +18,9 @@
#ifndef __PATH_TOOLP_H__ #ifndef __PATH_TOOLP_H__
#define __PATH_TOOLP_H__ #define __PATH_TOOLP_H__
#undef PATH_TOOL_DEBUG
#include "draw_core.h"
#define IMAGE_COORDS 1 #define IMAGE_COORDS 1
#define AA_IMAGE_COORDS 2 #define AA_IMAGE_COORDS 2
@ -33,12 +36,10 @@
#define SUBDIVIDE 1000 #define SUBDIVIDE 1000
typedef enum { SEGMENT_LINE=0, SEGMENT_BEZIER} SegmentType;
enum { ON_ANCHOR, ON_HANDLE, ON_CURVE, ON_CANVAS }; enum { ON_ANCHOR, ON_HANDLE, ON_CURVE, ON_CANVAS };
typedef enum { SEGMENT_LINE, SEGMENT_BEZIER } SegmentType;
typedef struct _path_segment PathSegment; typedef struct _path_segment PathSegment;
typedef struct _path_curve PathCurve; typedef struct _path_curve PathCurve;
typedef struct _path Path; typedef struct _path Path;
@ -82,7 +83,7 @@ struct _path
struct _path_tool struct _path_tool
{ {
gint click_pos; /* where did the user click? */ gint click_type; /* where did the user click? */
gint click_x; /* X-coordinate of the click */ gint click_x; /* X-coordinate of the click */
gint click_y; /* Y-coordinate of the click */ gint click_y; /* Y-coordinate of the click */
gint click_halfwidth; gint click_halfwidth;
@ -90,6 +91,7 @@ struct _path_tool
Path *click_path; /* On which Path/Curve/Segment */ Path *click_path; /* On which Path/Curve/Segment */
PathCurve *click_curve; /* was the click? */ PathCurve *click_curve; /* was the click? */
PathSegment *click_segment; PathSegment *click_segment;
gdouble click_position; /* The position on the segment */
gint active_count; /* How many segments are active? */ gint active_count; /* How many segments are active? */
/* /*
@ -110,6 +112,4 @@ typedef void (*PathTraverseFunc) (Path *, PathCurve *, gpointer);
typedef void (*CurveTraverseFunc) (Path *, PathCurve *, PathSegment *, gpointer); typedef void (*CurveTraverseFunc) (Path *, PathCurve *, PathSegment *, gpointer);
typedef void (*SegmentTraverseFunc) (Path *, PathCurve *, PathSegment *, gint, gint, gpointer); typedef void (*SegmentTraverseFunc) (Path *, PathCurve *, PathSegment *, gint, gint, gpointer);
/* typedef void (*SegmentTraverseFunc) (PathTool *, GdkPoint *, gint, gpointer);*/
#endif /* __PATH_TOOLP_H__ */ #endif /* __PATH_TOOLP_H__ */

View File

@ -29,8 +29,6 @@
* segments between two anchors. * segments between two anchors.
*/ */
#undef PATH_TOOL_DEBUG
#include <math.h> #include <math.h>
/* #include "appenv.h" /* #include "appenv.h"
*/ */
@ -39,6 +37,7 @@
#include "cursorutil.h" #include "cursorutil.h"
#include "path_tool.h" #include "path_tool.h"
#include "path_toolP.h" #include "path_toolP.h"
#include "path_curves.h"
#ifdef PATH_TOOL_DEBUG #ifdef PATH_TOOL_DEBUG
#include <stdio.h> #include <stdio.h>
@ -63,51 +62,52 @@
/* Small functions to determine coordinates, iterate over path/curve/segment */ /* Small functions to determine coordinates, iterate over path/curve/segment */
static void path_segment_get_coordinates (PathSegment *, gdouble, gint *, gint *); void path_segment_get_coordinates (PathSegment *, gdouble, gint *, gint *);
static void path_traverse_path (Path *, PathTraverseFunc, CurveTraverseFunc, SegmentTraverseFunc, gpointer); void path_traverse_path (Path *, PathTraverseFunc, CurveTraverseFunc, SegmentTraverseFunc, gpointer);
static void path_traverse_curve (Path *, PathCurve *, CurveTraverseFunc, SegmentTraverseFunc, gpointer); void path_traverse_curve (Path *, PathCurve *, CurveTraverseFunc, SegmentTraverseFunc, gpointer);
static void path_traverse_segment (Path *, PathCurve *, PathSegment *, SegmentTraverseFunc, gpointer); void path_traverse_segment (Path *, PathCurve *, PathSegment *, SegmentTraverseFunc, gpointer);
static gdouble path_locate_point (Path *, PathCurve **, PathSegment **, gint, gint, gint, gint, gint); gdouble path_locate_point (Path *, PathCurve **, PathSegment **, gint, gint, gint, gint, gint);
/* Tools to manipulate paths, curves, segments */ /* Tools to manipulate paths, curves, segments */
static PathCurve * path_add_curve (Path *, gint, gint); PathCurve * path_add_curve (Path *, gint, gint);
static PathSegment * path_append_segment (Path *, PathCurve *, SegmentType, gint, gint); PathSegment * path_append_segment (Path *, PathCurve *, SegmentType, gint, gint);
static PathSegment * path_prepend_segment (Path *, PathCurve *, SegmentType, gint, gint); PathSegment * path_prepend_segment (Path *, PathCurve *, SegmentType, gint, gint);
static PathSegment * path_split_segment (PathSegment *, gdouble); PathSegment * path_split_segment (PathSegment *, gdouble);
static void path_join_curves (PathSegment *, PathSegment *); void path_join_curves (PathSegment *, PathSegment *);
static void path_flip_curve (PathCurve *); void path_flip_curve (PathCurve *);
static void path_free_path (Path *); void path_free_path (Path *);
static void path_free_curve (PathCurve *); void path_free_curve (PathCurve *);
static void path_free_segment (PathSegment *); void path_free_segment (PathSegment *);
static void path_delete_segment (PathSegment *); void path_delete_segment (PathSegment *);
static void path_print (Path *); void path_print (Path *);
static void path_offset_active (Path *, gdouble, gdouble); void path_offset_active (Path *, gdouble, gdouble);
static void path_set_flags (PathTool *, Path *, PathCurve *, PathSegment *, guint32, guint32); void path_set_flags (PathTool *, Path *, PathCurve *, PathSegment *, guint32, guint32);
/* High level image-manipulation functions */ /* High level image-manipulation functions */
static void path_stroke (PathTool *, Path *); void path_stroke (PathTool *, Path *);
static void path_to_selection (PathTool *, Path *); void path_to_selection (PathTool *, Path *);
/* Functions necessary for the tool */ /* Functions necessary for the tool */
static void path_tool_button_press (Tool *, GdkEventButton *, gpointer); void path_tool_button_press (Tool *, GdkEventButton *, gpointer);
static void path_tool_button_release (Tool *, GdkEventButton *, gpointer); void path_tool_button_release (Tool *, GdkEventButton *, gpointer);
static void path_tool_motion (Tool *, GdkEventMotion *, gpointer); void path_tool_motion (Tool *, GdkEventMotion *, gpointer);
static void path_tool_cursor_update (Tool *, GdkEventMotion *, gpointer); void path_tool_cursor_update (Tool *, GdkEventMotion *, gpointer);
static void path_tool_control (Tool *, ToolAction, gpointer); void path_tool_control (Tool *, ToolAction, gpointer);
static void path_tool_draw (Tool *); void path_tool_draw (Tool *);
static void path_tool_draw_curve (Tool *, PathCurve *); void path_tool_draw_curve (Tool *, PathCurve *);
static void path_tool_draw_segment (Tool *, PathSegment *); void path_tool_draw_segment (Tool *, PathSegment *);
static gboolean path_tool_on_anchors (Tool *, gint, gint, gint, Path**, PathCurve**, PathSegment**); gboolean path_tool_on_anchors (Tool *, gint, gint, gint, Path**, PathCurve**, PathSegment**);
static gboolean path_tool_on_handles (Tool *, gint, gint, gint); gdouble path_tool_on_curve (Tool *, gint, gint, gint, Path**, PathCurve**, PathSegment**);
static gboolean path_tool_on_curve (Tool *, gint, gint, gint); gboolean path_tool_on_handles (Tool *, gint, gint, gint);
static gint path_tool_button_press_canvas (Tool *, GdkEventButton *, GDisplay *); gint path_tool_button_press_canvas (Tool *, GdkEventButton *, GDisplay *);
static gint path_tool_button_press_anchor (Tool *, GdkEventButton *, GDisplay *); gint path_tool_button_press_anchor (Tool *, GdkEventButton *, GDisplay *);
static void path_tool_motion_anchor (Tool *, GdkEventMotion *, GDisplay *); gint path_tool_button_press_curve (Tool *, GdkEventButton *, GDisplay *);
static void path_tool_motion_curve (Tool *, GdkEventMotion *, GDisplay *); void path_tool_motion_anchor (Tool *, GdkEventMotion *, GDisplay *);
void path_tool_motion_curve (Tool *, GdkEventMotion *, GDisplay *);
/* the path tool options */ /* the path tool options */
@ -138,7 +138,7 @@ static ToolOptions *path_options = NULL;
* *
*/ */
static void void
path_traverse_path (Path *path, PathTraverseFunc pathfunc, CurveTraverseFunc curvefunc, SegmentTraverseFunc segmentfunc, gpointer data) path_traverse_path (Path *path, PathTraverseFunc pathfunc, CurveTraverseFunc curvefunc, SegmentTraverseFunc segmentfunc, gpointer data)
{ {
PathCurve *cur_curve; PathCurve *cur_curve;
@ -160,7 +160,7 @@ path_traverse_path (Path *path, PathTraverseFunc pathfunc, CurveTraverseFunc cur
} }
static void void
path_traverse_curve (Path *path, PathCurve *curve, CurveTraverseFunc curvefunc, SegmentTraverseFunc segmentfunc, gpointer data) path_traverse_curve (Path *path, PathCurve *curve, CurveTraverseFunc curvefunc, SegmentTraverseFunc segmentfunc, gpointer data)
{ {
PathSegment *cur_segment; PathSegment *cur_segment;
@ -181,13 +181,15 @@ path_traverse_curve (Path *path, PathCurve *curve, CurveTraverseFunc curvefunc,
} }
} }
static void void
path_traverse_segment (Path *path, PathCurve *curve, PathSegment *segment, SegmentTraverseFunc function, gpointer data) path_traverse_segment (Path *path, PathCurve *curve, PathSegment *segment, SegmentTraverseFunc function, gpointer data)
{ {
#ifdef PATH_TOOL_DEBUG #ifdef PATH_TOOL_DEBUG
fprintf(stderr, "path_traverse_segment\n"); fprintf(stderr, "path_traverse_segment\n");
#endif PATH_TOOL_DEBUG #endif PATH_TOOL_DEBUG
#warning here we need path_curve_get_point(s)
/* Something like: /* Something like:
* for i = 1 to subsamples { * for i = 1 to subsamples {
* (x,y) = get_coordinates(i / subsamples) * (x,y) = get_coordinates(i / subsamples)
@ -200,7 +202,7 @@ path_traverse_segment (Path *path, PathCurve *curve, PathSegment *segment, Segme
* Helper functions for manipulating the data-structures: * Helper functions for manipulating the data-structures:
*/ */
static PathCurve *path_add_curve (Path * cur_path, gint x, gint y) PathCurve *path_add_curve (Path * cur_path, gint x, gint y)
{ {
PathCurve * tmp = cur_path->curves; PathCurve * tmp = cur_path->curves;
PathCurve * new_curve = NULL; PathCurve * new_curve = NULL;
@ -233,7 +235,7 @@ static PathCurve *path_add_curve (Path * cur_path, gint x, gint y)
} }
static PathSegment * path_append_segment (Path * cur_path, PathCurve * cur_curve, SegmentType type, gint x, gint y) PathSegment * path_append_segment (Path * cur_path, PathCurve * cur_curve, SegmentType type, gint x, gint y)
{ {
PathSegment * tmp = cur_curve->segments; PathSegment * tmp = cur_curve->segments;
PathSegment * new_segment = NULL; PathSegment * new_segment = NULL;
@ -264,6 +266,9 @@ static PathSegment * path_append_segment (Path * cur_path, PathCurve * cur_curv
tmp->next = new_segment; tmp->next = new_segment;
cur_curve->cur_segment = new_segment; cur_curve->cur_segment = new_segment;
#warning we need initialisation of the segment here.
} }
#ifdef PATH_TOOL_DEBUG #ifdef PATH_TOOL_DEBUG
else else
@ -279,7 +284,7 @@ static PathSegment * path_append_segment (Path * cur_path, PathCurve * cur_curv
} }
static PathSegment * path_prepend_segment (Path * cur_path, PathCurve * cur_curve, SegmentType type, gint x, gint y) PathSegment * path_prepend_segment (Path * cur_path, PathCurve * cur_curve, SegmentType type, gint x, gint y)
{ {
PathSegment * tmp = cur_curve->segments; PathSegment * tmp = cur_curve->segments;
PathSegment * new_segment = NULL; PathSegment * new_segment = NULL;
@ -308,6 +313,7 @@ static PathSegment * path_prepend_segment (Path * cur_path, PathCurve * cur_cur
cur_curve->segments = new_segment; cur_curve->segments = new_segment;
cur_curve->cur_segment = new_segment; cur_curve->cur_segment = new_segment;
#warning we need initialisation of the segment here.
} }
#ifdef PATH_TOOL_DEBUG #ifdef PATH_TOOL_DEBUG
else else
@ -322,15 +328,47 @@ static PathSegment * path_prepend_segment (Path * cur_path, PathCurve * cur_cur
return new_segment; return new_segment;
} }
/* static PathSegment * path_split_segment (PathSegment *, gdouble); PathSegment * path_split_segment (PathSegment *segment, gdouble position)
*/ {
PathSegment * new_segment = NULL;
#ifdef PATH_TOOL_DEBUG
fprintf(stderr, "path_split_segment\n");
#endif PATH_TOOL_DEBUG
if (segment && segment->next) {
new_segment = g_new (PathSegment, 1);
new_segment->type = segment->type;
#warning Giving PathTool as NULL Pointer!
path_curve_get_point (NULL, segment, position, &(new_segment->x), &(new_segment->y));
new_segment->flags = 0;
new_segment->parent = segment->parent;
new_segment->next = segment->next;
new_segment->prev = segment;
new_segment->data = NULL;
#warning we need initialisation of the segment here.
new_segment->next->prev = new_segment;
segment->next = new_segment;
return new_segment;
}
#ifdef PATH_TOOL_DEBUG
else
fprintf(stderr, "path_split_segment without valid segment\n");
#endif PATH_TOOL_DEBUG
return NULL;
}
/* /*
* Join two arbitrary endpoints and free the parent from the second * Join two arbitrary endpoints and free the parent from the second
* segment, if it differs from the first parents. * segment, if it differs from the first parents.
*/ */
static void void
path_join_curves (PathSegment *segment1, PathSegment *segment2) { path_join_curves (PathSegment *segment1, PathSegment *segment2) {
PathCurve *curve1, *curve2; PathCurve *curve1, *curve2;
PathSegment *tmp; PathSegment *tmp;
@ -352,6 +390,7 @@ path_join_curves (PathSegment *segment1, PathSegment *segment2) {
segment2->prev = segment1; segment2->prev = segment1;
segment1->next = segment2; segment1->next = segment2;
} }
#warning Probably some segment-updates needed
return; return;
} }
@ -403,6 +442,7 @@ path_join_curves (PathSegment *segment1, PathSegment *segment2) {
tmp->parent = curve1; tmp->parent = curve1;
tmp = tmp->next; tmp = tmp->next;
} }
#warning Probably some segment-updates needed
return; return;
} }
@ -433,10 +473,11 @@ path_join_curves (PathSegment *segment1, PathSegment *segment2) {
tmp = tmp->prev; tmp = tmp->prev;
} }
return; return;
#warning Probably some segment-updates needed
} }
#ifdef PATH_TOOL_DEBUG #ifdef PATH_TOOL_DEBUG
fprintf (stderr, "Cant join these curves yet...\n"); fprintf (stderr, "Cant join these curves yet...\nThis should not happen.");
return; return;
#endif PATH_TOOL_DEBUG #endif PATH_TOOL_DEBUG
@ -446,7 +487,7 @@ path_join_curves (PathSegment *segment1, PathSegment *segment2) {
* This function reverses the order of the anchors. This is * This function reverses the order of the anchors. This is
* necessary for some joining operations. * necessary for some joining operations.
*/ */
static void void
path_flip_curve (PathCurve *curve) path_flip_curve (PathCurve *curve)
{ {
gpointer *end_data; gpointer *end_data;
@ -454,6 +495,8 @@ path_flip_curve (PathCurve *curve)
PathSegment *tmp, *tmp2; PathSegment *tmp, *tmp2;
#warning Please add path_curve_flip_segment here
if (!curve && !curve->segments) { if (!curve && !curve->segments) {
#ifdef PATH_TOOL_DEBUG #ifdef PATH_TOOL_DEBUG
fprintf (stderr, "path_flip_curve: No curve o no segments to flip!\n"); fprintf (stderr, "path_flip_curve: No curve o no segments to flip!\n");
@ -483,11 +526,12 @@ path_flip_curve (PathCurve *curve)
tmp->data = end_data; tmp->data = end_data;
} }
tmp = tmp->next; tmp = tmp->next;
#warning Probably some segment-updates needed
} }
} }
static void void
path_free_path (Path * path) path_free_path (Path * path)
{ {
PathCurve *tmp1, *tmp2; PathCurve *tmp1, *tmp2;
@ -495,18 +539,18 @@ path_free_path (Path * path)
if (path) if (path)
{ {
tmp2 = path->curves; tmp2 = path->curves;
g_string_free(path->name, TRUE);
g_free(path);
while ((tmp1 = tmp2) != NULL) while ((tmp1 = tmp2) != NULL)
{ {
tmp2 = tmp1->next; tmp2 = tmp1->next;
path_free_curve (tmp1); path_free_curve (tmp1);
} }
g_string_free(path->name, TRUE);
g_free(path);
} }
} }
static void void
path_free_curve (PathCurve *curve) path_free_curve (PathCurve *curve)
{ {
PathSegment *tmp1, *tmp2; PathSegment *tmp1, *tmp2;
@ -528,7 +572,7 @@ path_free_curve (PathCurve *curve)
} }
} }
static void void
path_free_segment (PathSegment *segment) path_free_segment (PathSegment *segment)
{ {
if (segment) if (segment)
@ -538,11 +582,12 @@ path_free_segment (PathSegment *segment)
segment->parent, segment, 0, SEGMENT_ACTIVE); segment->parent, segment, 0, SEGMENT_ACTIVE);
if (segment->data) if (segment->data)
g_free(segment->data); g_free(segment->data);
#warning Free Segment needs an own hook in the different curve-types!
g_free (segment); g_free (segment);
} }
} }
static void void
path_delete_curve (PathCurve *curve) path_delete_curve (PathCurve *curve)
{ {
if (curve) if (curve)
@ -560,7 +605,7 @@ path_delete_curve (PathCurve *curve)
} }
} }
static void void
path_delete_segment (PathSegment *segment) path_delete_segment (PathSegment *segment)
{ {
if (segment) if (segment)
@ -587,6 +632,7 @@ path_delete_segment (PathSegment *segment)
/* /*
* here we have to update the surrounding segments * here we have to update the surrounding segments
*/ */
#warning Please add path_curve_update_segment here
} }
} }
@ -595,14 +641,21 @@ path_delete_segment (PathSegment *segment)
* A function to determine, which object is hit by the cursor * A function to determine, which object is hit by the cursor
*/ */
static gint gint
path_tool_cursor_position (Tool *tool, gint x, gint y, gint halfwidth, Path **pathP, PathCurve **curveP, PathSegment **segmentP) path_tool_cursor_position (Tool *tool, gint x, gint y, gint halfwidth, Path **pathP, PathCurve **curveP, PathSegment **segmentP, gdouble *positionP)
{ {
gint location; gint location;
gdouble pos;
if (path_tool_on_anchors (tool, x, y, halfwidth, pathP, curveP, segmentP)) if (path_tool_on_anchors (tool, x, y, halfwidth, pathP, curveP, segmentP))
return ON_ANCHOR; return ON_ANCHOR;
pos = path_tool_on_curve (tool, x, y, halfwidth, pathP, curveP, segmentP);
if (pos >= 0 && pos <= 1) {
if (positionP) (*positionP) = pos;
return ON_CURVE;
}
return ON_CANVAS; return ON_CANVAS;
} }
@ -611,7 +664,7 @@ path_tool_cursor_position (Tool *tool, gint x, gint y, gint halfwidth, Path **pa
* The click-callbacks for the tool * The click-callbacks for the tool
*/ */
static void void
path_tool_button_press (Tool *tool, path_tool_button_press (Tool *tool,
GdkEventButton *bevent, GdkEventButton *bevent,
gpointer gdisp_ptr) gpointer gdisp_ptr)
@ -649,12 +702,13 @@ path_tool_button_press (Tool *tool,
* switch accordingly. * switch accordingly.
*/ */
path_tool->click_pos = path_tool_cursor_position(tool, x, y, halfwidth, path_tool->click_type = path_tool_cursor_position(tool, x, y, halfwidth,
&(path_tool->click_path), &(path_tool->click_path),
&(path_tool->click_curve), &(path_tool->click_curve),
&(path_tool->click_segment)); &(path_tool->click_segment),
&(path_tool->click_position));
switch (path_tool->click_pos) switch (path_tool->click_type)
{ {
case ON_CANVAS: case ON_CANVAS:
grab_pointer = path_tool_button_press_canvas(tool, bevent, gdisp); grab_pointer = path_tool_button_press_canvas(tool, bevent, gdisp);
@ -664,6 +718,10 @@ path_tool_button_press (Tool *tool,
grab_pointer = path_tool_button_press_anchor(tool, bevent, gdisp); grab_pointer = path_tool_button_press_anchor(tool, bevent, gdisp);
break; break;
case ON_CURVE:
grab_pointer = path_tool_button_press_curve(tool, bevent, gdisp);
break;
default: default:
g_message("Huh? Whats happening here? (button_press_*)"); g_message("Huh? Whats happening here? (button_press_*)");
} }
@ -679,7 +737,7 @@ path_tool_button_press (Tool *tool,
} }
static gint gint
path_tool_button_press_anchor (Tool *tool, path_tool_button_press_anchor (Tool *tool,
GdkEventButton *bevent, GdkEventButton *bevent,
GDisplay *gdisp) GDisplay *gdisp)
@ -789,6 +847,7 @@ path_tool_button_press_anchor (Tool *tool,
path_delete_segment (path_tool->click_segment); path_delete_segment (path_tool->click_segment);
path_tool->click_segment = NULL; 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)) else if (!(path_tool->click_segment->flags & SEGMENT_ACTIVE))
{ {
@ -797,14 +856,12 @@ path_tool_button_press_anchor (Tool *tool,
} }
/* Action goes here */
draw_core_resume(path_tool->core, tool); draw_core_resume(path_tool->core, tool);
return grab_pointer; return grab_pointer;
} }
static gint gint
path_tool_button_press_canvas (Tool *tool, path_tool_button_press_canvas (Tool *tool,
GdkEventButton *bevent, GdkEventButton *bevent,
GDisplay *gdisp) GDisplay *gdisp)
@ -857,7 +914,48 @@ path_tool_button_press_canvas (Tool *tool,
return 0; return 0;
} }
static void gint
path_tool_button_press_curve (Tool *tool,
GdkEventButton *bevent,
GDisplay *gdisp)
{
PathTool *path_tool = tool->private;
Path * cur_path = path_tool->cur_path;
PathCurve * cur_curve;
PathSegment * cur_segment;
gint grab_pointer;
#ifdef PATH_TOOL_DEBUG
fprintf(stderr, "path_tool_button_press_curve:\n");
#endif PATH_TOOL_DEBUG
grab_pointer = 1;
if (!cur_path) {
#ifdef PATH_TOOL_DEBUG
fprintf (stderr, "Fatal error: No current Path\n");
#endif PATH_TOOL_DEBUG
return 0;
}
draw_core_pause (path_tool->core, tool);
if (path_tool->click_modifier & GDK_SHIFT_MASK) {
cur_segment = path_curve_insert_anchor (path_tool, path_tool->click_segment, path_tool->click_position);
path_set_flags (path_tool, cur_path, NULL, NULL, 0, SEGMENT_ACTIVE);
path_set_flags (path_tool, cur_path, path_tool->click_curve, cur_segment, SEGMENT_ACTIVE, 0);
path_tool->click_type = ON_ANCHOR;
path_tool->click_segment = cur_segment;
}
draw_core_resume(path_tool->core, tool);
return 0;
}
void
path_tool_button_release (Tool *tool, path_tool_button_release (Tool *tool,
GdkEventButton *bevent, GdkEventButton *bevent,
gpointer gdisp_ptr) gpointer gdisp_ptr)
@ -883,7 +981,7 @@ path_tool_button_release (Tool *tool,
* The motion-callbacks for the tool * The motion-callbacks for the tool
*/ */
static void void
path_tool_motion (Tool *tool, path_tool_motion (Tool *tool,
GdkEventMotion *mevent, GdkEventMotion *mevent,
gpointer gdisp_ptr) gpointer gdisp_ptr)
@ -896,7 +994,7 @@ path_tool_motion (Tool *tool,
gdisp = (GDisplay *) gdisp_ptr; gdisp = (GDisplay *) gdisp_ptr;
path_tool = (PathTool *) tool->private; path_tool = (PathTool *) tool->private;
switch (path_tool->click_pos) { switch (path_tool->click_type) {
case ON_ANCHOR: case ON_ANCHOR:
path_tool_motion_anchor(tool, mevent, gdisp); path_tool_motion_anchor(tool, mevent, gdisp);
break; break;
@ -906,7 +1004,7 @@ path_tool_motion (Tool *tool,
} }
static void void
path_tool_motion_anchor (Tool *tool, path_tool_motion_anchor (Tool *tool,
GdkEventMotion *mevent, GdkEventMotion *mevent,
GDisplay *gdisp) GDisplay *gdisp)
@ -977,7 +1075,7 @@ path_tool_motion_anchor (Tool *tool,
} }
static void void
path_tool_cursor_update (Tool *tool, path_tool_cursor_update (Tool *tool,
GdkEventMotion *mevent, GdkEventMotion *mevent,
gpointer gdisp_ptr) gpointer gdisp_ptr)
@ -999,13 +1097,16 @@ path_tool_cursor_update (Tool *tool,
gdisplay_untransform_coords (gdisp, mevent->x + PATH_TOOL_HALFWIDTH, 0, &halfwidth, &dummy, TRUE, 0); gdisplay_untransform_coords (gdisp, mevent->x + PATH_TOOL_HALFWIDTH, 0, &halfwidth, &dummy, TRUE, 0);
halfwidth -= x; halfwidth -= x;
cursor_location = path_tool_cursor_position(tool, x, y, halfwidth, NULL, NULL, NULL); cursor_location = path_tool_cursor_position(tool, x, y, halfwidth, NULL, NULL, NULL, NULL);
switch (cursor_location) { switch (cursor_location) {
case ON_CANVAS: case ON_CANVAS:
gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE1AP_CURSOR); gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE1AP_CURSOR);
break; break;
case ON_ANCHOR: case ON_ANCHOR:
gdisplay_install_tool_cursor (gdisp, GDK_FLEUR);
break;
case ON_CURVE:
gdisplay_install_tool_cursor (gdisp, GDK_TCROSS); gdisplay_install_tool_cursor (gdisp, GDK_TCROSS);
break; break;
default: default:
@ -1018,7 +1119,7 @@ path_tool_cursor_update (Tool *tool,
* Tool-control functions * Tool-control functions
*/ */
static void void
path_tool_control (Tool *tool, path_tool_control (Tool *tool,
ToolAction action, ToolAction action,
gpointer gdisp_ptr) gpointer gdisp_ptr)
@ -1044,6 +1145,9 @@ path_tool_control (Tool *tool,
break; break;
case HALT: case HALT:
#ifdef PATH_TOOL_DEBUG
fprintf (stderr, "path_tool_control: HALT\n");
#endif PATH_TOOL_DEBUG
draw_core_stop (path_tool->core, tool); draw_core_stop (path_tool->core, tool);
tool->state = INACTIVE; tool->state = INACTIVE;
break; break;
@ -1051,6 +1155,9 @@ path_tool_control (Tool *tool,
default: default:
break; break;
} }
#ifdef PATH_TOOL_DEBUG
fprintf (stderr, "path_tool_control: end\n");
#endif PATH_TOOL_DEBUG
} }
Tool * Tool *
@ -1069,11 +1176,15 @@ tools_new_path_tool (void)
tool = tools_new_tool (PATH_TOOL); tool = tools_new_tool (PATH_TOOL);
private = g_new (PathTool, 1); private = g_new (PathTool, 1);
private->click_pos = ON_CANVAS; private->click_type = ON_CANVAS;
private->click_x = 0; private->click_x = 0;
private->click_y = 0; private->click_y = 0;
private->click_halfwidth = 0; private->click_halfwidth = 0;
private->click_modifier = 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->active_count = 0;
private->single_active_segment = NULL; private->single_active_segment = NULL;
@ -1108,6 +1219,9 @@ tools_free_path_tool (Tool *tool)
GDisplay * gdisp; GDisplay * gdisp;
PathTool * path_tool; PathTool * path_tool;
#ifdef PATH_TOOL_DEBUG
fprintf (stderr, "tools_free_path_tool start\n");
#endif PATH_TOOL_DEBUG
path_tool = (PathTool *) tool->private; path_tool = (PathTool *) tool->private;
gdisp = (GDisplay *) tool->gdisp_ptr; gdisp = (GDisplay *) tool->gdisp_ptr;
@ -1121,9 +1235,84 @@ tools_free_path_tool (Tool *tool)
draw_core_free (path_tool->core); draw_core_free (path_tool->core);
g_free (path_tool); g_free (path_tool);
#ifdef PATH_TOOL_DEBUG
fprintf (stderr, "tools_free_path_tool end\n");
#endif PATH_TOOL_DEBUG
} }
/**************************************************************
* Set of function to determine, if the click was on an segment
*/
typedef struct {
Tool *tool;
Path *path;
PathCurve *curve;
PathSegment *segment;
gint testx;
gint testy;
gint halfwidth;
gint distance;
gdouble position;
gboolean found;
} Path_on_curve_type;
/* This is a CurveTraverseFunc */
void
path_tool_on_curve_helper (Path *path, PathCurve *curve, PathSegment *segment, gpointer ptr)
{
gint distance;
gdouble position;
Path_on_curve_type *data = (Path_on_curve_type *) ptr;
if (segment && segment->next && data && data->distance > 0)
{
position = path_curve_on_segment (data->tool, segment, data->testx, data->testy, data->halfwidth, &distance);
if (position >= 0 && distance < data->distance )
{
data->path = path;
data->curve = curve;
data->segment = segment;
data->distance = distance;
data->position = position;
data->found = TRUE;
}
}
}
gdouble
path_tool_on_curve (Tool *tool, gint x, gint y, gint halfwidth, Path **ret_pathP, PathCurve **ret_curveP, PathSegment **ret_segmentP)
{
Path_on_curve_type *data = g_new (Path_on_curve_type, 1);
gdouble position;
data->tool = tool;
data->path = NULL;
data->segment = NULL;
data->segment = NULL;
data->testx = x;
data->testy = y;
data->halfwidth = halfwidth;
data->distance = halfwidth * halfwidth + 1;
data->position = -1;
data->found = FALSE;
path_traverse_path (((PathTool *) data->tool->private)->cur_path, NULL, path_tool_on_curve_helper, NULL, data);
if (ret_pathP) *ret_pathP = data->path;
if (ret_curveP) *ret_curveP = data->curve;
if (ret_segmentP) *ret_segmentP = data->segment;
position = data->position;
g_free(data);
return position;
}
/************************************************************** /**************************************************************
* Set of function to determine, if the click was on an anchor * Set of function to determine, if the click was on an anchor
*/ */
@ -1139,7 +1328,7 @@ typedef struct {
} Path_on_anchors_type; } Path_on_anchors_type;
/* This is a CurveTraverseFunc */ /* This is a CurveTraverseFunc */
static void void
path_tool_on_anchors_helper (Path *path, PathCurve *curve, PathSegment *segment, gpointer ptr) path_tool_on_anchors_helper (Path *path, PathCurve *curve, PathSegment *segment, gpointer ptr)
{ {
gint distance; gint distance;
@ -1161,7 +1350,7 @@ path_tool_on_anchors_helper (Path *path, PathCurve *curve, PathSegment *segment,
} }
} }
static gboolean gboolean
path_tool_on_anchors (Tool *tool, gint x, gint y, gint halfwidth, Path **ret_pathP, PathCurve **ret_curveP, PathSegment **ret_segmentP) path_tool_on_anchors (Tool *tool, gint x, gint y, gint halfwidth, Path **ret_pathP, PathCurve **ret_curveP, PathSegment **ret_segmentP)
{ {
Path_on_anchors_type *data = g_new (Path_on_anchors_type, 1); Path_on_anchors_type *data = g_new (Path_on_anchors_type, 1);
@ -1200,7 +1389,7 @@ typedef struct {
} Path_offset_active_type; } Path_offset_active_type;
/* This is a CurveTraverseFunc */ /* This is a CurveTraverseFunc */
static void void
path_offset_active_helper (Path *path, PathCurve *curve, PathSegment *segment, gpointer ptr) path_offset_active_helper (Path *path, PathCurve *curve, PathSegment *segment, gpointer ptr)
{ {
Path_offset_active_type *data = (Path_offset_active_type *) ptr; Path_offset_active_type *data = (Path_offset_active_type *) ptr;
@ -1209,9 +1398,10 @@ path_offset_active_helper (Path *path, PathCurve *curve, PathSegment *segment, g
segment->x += data->dx; segment->x += data->dx;
segment->y += data->dy; segment->y += data->dy;
} }
#warning Do a segment_update here!
} }
static void void
path_offset_active (Path *path, gdouble dx, gdouble dy) path_offset_active (Path *path, gdouble dx, gdouble dy)
{ {
Path_offset_active_type *data = g_new (Path_offset_active_type, 1); Path_offset_active_type *data = g_new (Path_offset_active_type, 1);
@ -1226,7 +1416,7 @@ path_offset_active (Path *path, gdouble dx, gdouble dy)
/************************************************************** /**************************************************************
* Set of function to set the state of all anchors to inactive * Set of function to set the state of all anchors
*/ */
typedef struct { typedef struct {
@ -1236,7 +1426,7 @@ typedef struct {
} Path_set_flags_type; } Path_set_flags_type;
/* This is a CurveTraverseFunc */ /* This is a CurveTraverseFunc */
static void void
path_set_flags_helper (Path *path, PathCurve *curve, PathSegment *segment, gpointer ptr) path_set_flags_helper (Path *path, PathCurve *curve, PathSegment *segment, gpointer ptr)
{ {
Path_set_flags_type *tmp = (Path_set_flags_type *) ptr; Path_set_flags_type *tmp = (Path_set_flags_type *) ptr;
@ -1272,7 +1462,7 @@ path_set_flags_helper (Path *path, PathCurve *curve, PathSegment *segment, gpoin
} }
} }
static void void
path_set_flags (PathTool *path_tool, Path *path, PathCurve *curve, PathSegment *segment, guint32 bits_set, guint32 bits_clear) path_set_flags (PathTool *path_tool, Path *path, PathCurve *curve, PathSegment *segment, guint32 bits_set, guint32 bits_clear)
{ {
Path_set_flags_type *tmp = g_new (Path_set_flags_type, 1); Path_set_flags_type *tmp = g_new (Path_set_flags_type, 1);
@ -1296,7 +1486,7 @@ path_set_flags (PathTool *path_tool, Path *path, PathCurve *curve, PathSegment *
*/ */
/* This is a CurveTraverseFunc */ /* This is a CurveTraverseFunc */
static void void
path_tool_draw_helper (Path *path, PathCurve *curve, PathSegment * segment, gpointer tool_ptr) path_tool_draw_helper (Path *path, PathCurve *curve, PathSegment * segment, gpointer tool_ptr)
{ {
Tool * tool = (Tool *) tool_ptr; Tool * tool = (Tool *) tool_ptr;
@ -1335,8 +1525,7 @@ path_tool_draw_helper (Path *path, PathCurve *curve, PathSegment * segment, gpoi
if (segment->next) if (segment->next)
{ {
gdisplay_transform_coords (gdisp, (gint) segment->next->x, (gint) segment->next->y, &x2, &y2, FALSE); path_curve_draw_segment (tool, segment);
gdk_draw_line (core->win, core->gc, x1, y1, x2, y2);
} }
} }
#ifdef PATH_TOOL_DEBUG #ifdef PATH_TOOL_DEBUG
@ -1345,7 +1534,7 @@ path_tool_draw_helper (Path *path, PathCurve *curve, PathSegment * segment, gpoi
#endif PATH_TOOL_DEBUG #endif PATH_TOOL_DEBUG
} }
static void void
path_tool_draw (Tool *tool) path_tool_draw (Tool *tool)
{ {
GDisplay * gdisp; GDisplay * gdisp;
@ -1363,4 +1552,10 @@ path_tool_draw (Tool *tool)
path_traverse_path (cur_path, NULL, path_tool_draw_helper, NULL, tool); path_traverse_path (cur_path, NULL, path_tool_draw_helper, NULL, tool);
#ifdef PATH_TOOL_DEBUG
fprintf (stderr, "path_tool_draw end.\n");
#endif PATH_TOOL_DEBUG
} }

View File

@ -1,5 +1,6 @@
/* The GIMP -- an image manipulation program /* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis *
* This file Copyright (C) 1999 Simon Budig
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -15,6 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
#ifndef __PATH_TOOL_H__ #ifndef __PATH_TOOL_H__
#define __PATH_TOOL_H__ #define __PATH_TOOL_H__

View File

@ -18,6 +18,9 @@
#ifndef __PATH_TOOLP_H__ #ifndef __PATH_TOOLP_H__
#define __PATH_TOOLP_H__ #define __PATH_TOOLP_H__
#undef PATH_TOOL_DEBUG
#include "draw_core.h"
#define IMAGE_COORDS 1 #define IMAGE_COORDS 1
#define AA_IMAGE_COORDS 2 #define AA_IMAGE_COORDS 2
@ -33,12 +36,10 @@
#define SUBDIVIDE 1000 #define SUBDIVIDE 1000
typedef enum { SEGMENT_LINE=0, SEGMENT_BEZIER} SegmentType;
enum { ON_ANCHOR, ON_HANDLE, ON_CURVE, ON_CANVAS }; enum { ON_ANCHOR, ON_HANDLE, ON_CURVE, ON_CANVAS };
typedef enum { SEGMENT_LINE, SEGMENT_BEZIER } SegmentType;
typedef struct _path_segment PathSegment; typedef struct _path_segment PathSegment;
typedef struct _path_curve PathCurve; typedef struct _path_curve PathCurve;
typedef struct _path Path; typedef struct _path Path;
@ -82,7 +83,7 @@ struct _path
struct _path_tool struct _path_tool
{ {
gint click_pos; /* where did the user click? */ gint click_type; /* where did the user click? */
gint click_x; /* X-coordinate of the click */ gint click_x; /* X-coordinate of the click */
gint click_y; /* Y-coordinate of the click */ gint click_y; /* Y-coordinate of the click */
gint click_halfwidth; gint click_halfwidth;
@ -90,6 +91,7 @@ struct _path_tool
Path *click_path; /* On which Path/Curve/Segment */ Path *click_path; /* On which Path/Curve/Segment */
PathCurve *click_curve; /* was the click? */ PathCurve *click_curve; /* was the click? */
PathSegment *click_segment; PathSegment *click_segment;
gdouble click_position; /* The position on the segment */
gint active_count; /* How many segments are active? */ gint active_count; /* How many segments are active? */
/* /*
@ -110,6 +112,4 @@ typedef void (*PathTraverseFunc) (Path *, PathCurve *, gpointer);
typedef void (*CurveTraverseFunc) (Path *, PathCurve *, PathSegment *, gpointer); typedef void (*CurveTraverseFunc) (Path *, PathCurve *, PathSegment *, gpointer);
typedef void (*SegmentTraverseFunc) (Path *, PathCurve *, PathSegment *, gint, gint, gpointer); typedef void (*SegmentTraverseFunc) (Path *, PathCurve *, PathSegment *, gint, gint, gpointer);
/* typedef void (*SegmentTraverseFunc) (PathTool *, GdkPoint *, gint, gpointer);*/
#endif /* __PATH_TOOLP_H__ */ #endif /* __PATH_TOOLP_H__ */