From e2f373cbd292534bd8555e23f45d2f80ea1165e3 Mon Sep 17 00:00:00 2001 From: Simon Budig Date: Sat, 7 Apr 2001 14:55:39 +0000 Subject: [PATCH] app/Makefile.am app/apptypes.h app/path_bezier.[ch] app/path_curves.[ch] 2001-04-07 Simon Budig * app/Makefile.am * app/apptypes.h * app/path_bezier.[ch] * app/path_curves.[ch] * app/pixmaps2.h * app/tools/Makefile.am * app/tools/gimpdrawtool.[ch] * app/tools/path_tool.[ch] * app/tools/path_toolP.h * app/tools/tools.c new files: * app/tools/gimppathtool.c * app/tools/gimppathtool.h Reactivated (at least partially) the old new path tool. It will undergo major restructuring. Especially the path data will become proper objects. This definitely is work in progress and totally unuseable now. --- ChangeLog | 22 ++ app/Makefile.am | 4 + app/apptypes.h | 1 + app/path_bezier.c | 36 +- app/path_bezier.h | 34 +- app/path_curves.c | 89 ++--- app/path_curves.h | 143 +++++-- app/pixmaps2.h | 2 - app/tools/Makefile.am | 7 +- app/tools/gimpdrawtool.c | 69 ++++ app/tools/gimpdrawtool.h | 11 + app/tools/gimppathtool.c | 830 +++++++++++++++++++++++++++++++++++++++ app/tools/gimppathtool.h | 101 +++++ app/tools/path_tool.c | 190 +++++---- app/tools/path_tool.h | 87 +++- app/tools/path_toolP.h | 27 +- app/tools/tools.c | 2 + 17 files changed, 1414 insertions(+), 241 deletions(-) create mode 100644 app/tools/gimppathtool.c create mode 100644 app/tools/gimppathtool.h diff --git a/ChangeLog b/ChangeLog index 5c3f6b0b0c..f066db885d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2001-04-07 Simon Budig + + * app/Makefile.am + * app/apptypes.h + * app/path_bezier.[ch] + * app/path_curves.[ch] + * app/pixmaps2.h + * app/tools/Makefile.am + * app/tools/gimpdrawtool.[ch] + * app/tools/path_tool.[ch] + * app/tools/path_toolP.h + * app/tools/tools.c + + new files: + * app/tools/gimppathtool.c + * app/tools/gimppathtool.h + + Reactivated (at least partially) the old new path tool. It + will undergo major restructuring. Especially the path stuff + will become proper objects. This definitely is work in progress + and totally unuseable now. + 2001-04-07 Michael Natterer * configure.in diff --git a/app/Makefile.am b/app/Makefile.am index dd533aa4e9..9d4b120d3e 100644 --- a/app/Makefile.am +++ b/app/Makefile.am @@ -240,6 +240,10 @@ gimp_SOURCES = \ paths_dialog.c \ paths_dialog.h \ paths_dialogP.h \ + path_curves.h \ + path_curves.c \ + path_bezier.h \ + path_bezier.c \ pattern_header.h \ pattern_select.c \ pattern_select.h \ diff --git a/app/apptypes.h b/app/apptypes.h index 228e598fe7..dd374fffcb 100644 --- a/app/apptypes.h +++ b/app/apptypes.h @@ -79,6 +79,7 @@ typedef struct _GimpToolInfo GimpToolInfo; typedef struct _GimpTool GimpTool; typedef struct _GimpPaintTool GimpPaintTool; typedef struct _GimpDrawTool GimpDrawTool; +typedef struct _GimpPathTool GimpPathTool; typedef struct _GimpTransformTool GimpTransformTool; typedef struct _GimpBezierSelectPoint GimpBezierSelectPoint; diff --git a/app/path_bezier.c b/app/path_bezier.c index b3175dbb2e..7d8c9f6927 100644 --- a/app/path_bezier.c +++ b/app/path_bezier.c @@ -19,6 +19,10 @@ #include +#include +#include +#include "apptypes.h" +#include "path_curves.h" #include "path_bezier.h" #define HANDLE_HALFWIDTH 3 @@ -33,9 +37,8 @@ */ guint -path_bezier_get_points (PathTool *path_tool, - PathSegment *segment, - GdkPoint *points, +path_bezier_get_points (PathSegment *segment, + gfloat *points, guint npoints, gdouble start, gdouble end) @@ -44,8 +47,7 @@ path_bezier_get_points (PathTool *path_tool, } void -path_bezier_get_point (PathTool *path_tool, - PathSegment *segment, +path_bezier_get_point (PathSegment *segment, gdouble pos, gdouble *x, gdouble *y) @@ -72,9 +74,10 @@ path_bezier_get_point (PathTool *path_tool, } void -path_bezier_draw_handles (GimpTool *tool, +path_bezier_draw_handles (GimpDrawTool *tool, PathSegment *segment) { +#if 0 PathTool *path_tool = (PathTool *) (tool->private); PathBezierData *data = (PathBezierData *) segment->data; GDisplay * gdisp = tool->gdisp; @@ -112,10 +115,11 @@ path_bezier_draw_handles (GimpTool *tool, HANDLE_WIDTH, HANDLE_WIDTH); } } +#endif } void -path_bezier_draw_segment (GimpTool *tool, +path_bezier_draw_segment (GimpDrawTool *tool, PathSegment *segment) { return; @@ -123,8 +127,7 @@ path_bezier_draw_segment (GimpTool *tool, gdouble -path_bezier_on_segment (GimpTool *tool, - PathSegment *segment, +path_bezier_on_segment (PathSegment *segment, gint x, gint y, gint halfwidth, @@ -134,8 +137,7 @@ path_bezier_on_segment (GimpTool *tool, } void -path_bezier_drag_segment (PathTool *path_tool, - PathSegment *segment, +path_bezier_drag_segment (PathSegment *segment, gdouble pos, gdouble dx, gdouble dy) @@ -157,8 +159,7 @@ path_bezier_drag_segment (PathTool *path_tool, } gint -path_bezier_on_handles (PathTool *path_tool, - PathSegment *segment, +path_bezier_on_handles (PathSegment *segment, gdouble x, gdouble y, gdouble halfwidth) @@ -179,8 +180,7 @@ path_bezier_on_handles (PathTool *path_tool, } void -path_bezier_drag_handles (PathTool *path_tool, - PathSegment *segment, +path_bezier_drag_handles (PathSegment *segment, gdouble dx, gdouble dy, gint handle_id) @@ -198,16 +198,14 @@ path_bezier_drag_handles (PathTool *path_tool, PathSegment * -path_bezier_insert_anchor (PathTool *path_tool, - PathSegment *segment, +path_bezier_insert_anchor (PathSegment *segment, gdouble position) { return NULL; } void -path_bezier_update_segment (PathTool *path_tool, - PathSegment *segment) +path_bezier_update_segment (PathSegment *segment) { return; } diff --git a/app/path_bezier.h b/app/path_bezier.h index 988f4cae3f..fc2dcd4219 100644 --- a/app/path_bezier.h +++ b/app/path_bezier.h @@ -29,79 +29,67 @@ #define __PATH_BEZIER_H__ -#include "path_toolP.h" - typedef struct { gdouble x1; gdouble y1; gdouble x2; gdouble y2; - } PathBezierData; guint -path_bezier_get_points (PathTool *path_tool, - PathSegment *segment, - GdkPoint *points, +path_bezier_get_points (PathSegment *segment, + gfloat *points, guint npoints, gdouble start, gdouble end); void -path_bezier_get_point (PathTool *path_tool, - PathSegment *segment, +path_bezier_get_point (PathSegment *segment, gdouble position, gdouble *x, gdouble *y); void -path_bezier_draw_handles (GimpTool *tool, +path_bezier_draw_handles (GimpDrawTool *tool, PathSegment *segment); void -path_bezier_draw_segment (GimpTool *tool, +path_bezier_draw_segment (GimpDrawTool *tool, PathSegment *segment); - gdouble -path_bezier_on_segment (GimpTool *tool, - PathSegment *segment, +path_bezier_on_segment (PathSegment *segment, gint x, gint y, gint halfwidth, gint *distance); void -path_bezier_drag_segment (PathTool *path_tool, - PathSegment *segment, +path_bezier_drag_segment (PathSegment *segment, gdouble position, gdouble dx, gdouble dy); gint -path_bezier_on_handles (PathTool *path_tool, - PathSegment *segment, +path_bezier_on_handles (PathSegment *segment, gdouble x, gdouble y, gdouble halfwidth); void -path_bezier_drag_handles (PathTool *path_tool, - PathSegment *segment, +path_bezier_drag_handles (PathSegment *segment, gdouble dx, gdouble dy, gint handle_id); PathSegment * -path_bezier_insert_anchor (PathTool *path_tool, - PathSegment *segment, +path_bezier_insert_anchor (PathSegment *segment, gdouble position); void -path_bezier_update_segment (PathTool *path_tool, - PathSegment *segment); +path_bezier_update_segment (PathSegment *segment); void path_bezier_flip_segment (PathSegment *segment); diff --git a/app/path_curves.c b/app/path_curves.c index 63fab6f05f..66723f32a0 100644 --- a/app/path_curves.c +++ b/app/path_curves.c @@ -18,9 +18,14 @@ */ #include +#include +#include +#include "apptypes.h" #include "path_curves.h" #include "path_bezier.h" +#include "tools/gimpdrawtool.h" + /* only here temporarily */ PathSegment * path_split_segment (PathSegment *, gdouble); @@ -37,7 +42,7 @@ static CurveDescription CurveTypes[] = { NULL, /* path_bezier_get_points, */ path_bezier_get_point, - path_bezier_draw_handles, + NULL, /* path_bezier_draw_handles, */ NULL, /* path_bezier_draw_segment, */ NULL, /* path_bezier_on_segment, */ path_bezier_drag_segment, @@ -60,25 +65,25 @@ static CurveDescription CurveTypes[] = guint -path_curve_get_points (PathTool *path_tool, - PathSegment *segment, - GdkPoint *points, +path_curve_get_points (PathSegment *segment, + gdouble *points, guint npoints, gdouble start, gdouble end) { gdouble pos, x, y; + gint index=0; if (segment && segment->next) { if (CurveTypes[segment->type].get_points) - return (* CurveTypes[segment->type].get_points) (path_tool, segment, points, npoints, start, end); + 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 (path_tool, segment, pos, &x, &y); - points[index].x = (guint) (x + 0.5); - points[index].y = (guint) (y + 0.5); + path_curve_get_point (segment, pos, &points[index*2], + &points[index*2+1]); index++; } return index; @@ -95,21 +100,20 @@ path_curve_get_points (PathTool *path_tool, void -path_curve_get_point (PathTool *path_tool, - PathSegment *segment, +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) (path_tool, segment, position, x, y); + (* CurveTypes[segment->type].get_point) (segment, position, x, y); else { #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 */ + /* 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) + @@ -130,7 +134,7 @@ path_curve_get_point (PathTool *path_tool, } void -path_curve_draw_handles (Tool *tool, +path_curve_draw_handles (GimpDrawTool *tool, PathSegment *segment) { if (segment && CurveTypes[segment->type].draw_handles) @@ -141,7 +145,7 @@ path_curve_draw_handles (Tool *tool, } void -path_curve_draw_segment (Tool *tool, +path_curve_draw_segment (GimpDrawTool *tool, PathSegment *segment) { gint x, y, numpts, index; @@ -151,20 +155,9 @@ path_curve_draw_segment (Tool *tool, (* 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, - 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); + gdouble *coordinates = g_new (gdouble, 200); + numpts = path_curve_get_points (segment, coordinates, 100, 0, 1); + gimp_draw_tool_draw_lines (tool, coordinates, 100, FALSE); g_free (coordinates); } @@ -180,8 +173,7 @@ path_curve_draw_segment (Tool *tool, gdouble -path_curve_on_segment (Tool *tool, - PathSegment *segment, +path_curve_on_segment (PathSegment *segment, gint x, gint y, gint halfwidth, @@ -189,21 +181,21 @@ path_curve_on_segment (Tool *tool, { if (segment && CurveTypes[segment->type].on_segment) - return (* CurveTypes[segment->type].on_segment) (tool, segment, x, y, halfwidth, distance); + return (* CurveTypes[segment->type].on_segment) (segment, x, y, halfwidth, distance); else { if (segment && segment->next) { #if 1 gint x1, y1, numpts, index; - GdkPoint *coordinates = g_new (GdkPoint, 100); + gdouble *coordinates; gint bestindex = -1; + coordinates = g_new (gdouble, 200); *distance = halfwidth * halfwidth + 1; - numpts = path_curve_get_points (((PathTool *) tool->private), segment, - coordinates, 100, 0, 1); + numpts = path_curve_get_points (segment, coordinates, 100, 0, 1); for (index=0; index < numpts; index++) { - x1 = coordinates[index].x; - y1 = coordinates[index].y; + 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; @@ -247,47 +239,43 @@ path_curve_on_segment (Tool *tool, } void -path_curve_drag_segment (PathTool *path_tool, - PathSegment *segment, +path_curve_drag_segment (PathSegment *segment, gdouble position, gdouble dx, gdouble dy) { if (segment && CurveTypes[segment->type].drag_segment) - (* CurveTypes[segment->type].drag_segment) (path_tool, segment, position, dx, dy); + (* CurveTypes[segment->type].drag_segment) (segment, position, dx, dy); return; } gint -path_curve_on_handle (PathTool *path_tool, - PathSegment *segment, +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) (path_tool, segment, x, y, halfwidth); + return (* CurveTypes[segment->type].on_handles) (segment, x, y, halfwidth); return FALSE; } void -path_curve_drag_handle (PathTool *path_tool, - PathSegment *segment, +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) (path_tool, segment, dx, dy, handle_id); + (* CurveTypes[segment->type].drag_handle) (segment, dx, dy, handle_id); } PathSegment * -path_curve_insert_anchor (PathTool *path_tool, - PathSegment *segment, +path_curve_insert_anchor (PathSegment *segment, gdouble position) { if (segment && CurveTypes[segment->type].insert_anchor) - return (* CurveTypes[segment->type].insert_anchor) (path_tool, segment, position); + return (* CurveTypes[segment->type].insert_anchor) (segment, position); else { return path_split_segment (segment, position); } @@ -302,11 +290,10 @@ path_curve_flip_segment (PathSegment *segment) } void -path_curve_update_segment (PathTool *path_tool, - PathSegment *segment) +path_curve_update_segment (PathSegment *segment) { if (segment && CurveTypes[segment->type].update_segment) - (* CurveTypes[segment->type].update_segment) (path_tool, segment); + (* CurveTypes[segment->type].update_segment) (segment); return; } diff --git a/app/path_curves.h b/app/path_curves.h index f9ae820aef..a480537815 100644 --- a/app/path_curves.h +++ b/app/path_curves.h @@ -20,8 +20,85 @@ #ifndef __PATH_CURVES_H__ #define __PATH_CURVES_H__ -#include -#include "path_toolP.h" +#undef PATH_TOOL_DEBUG +#ifdef PATH_TOOL_DEBUG +#include +#endif + +#define IMAGE_COORDS 1 +#define AA_IMAGE_COORDS 2 +#define SCREEN_COORDS 3 + +#define SEGMENT_ACTIVE 1 + +#define PATH_TOOL_DRAG 1 + +#define PATH_TOOL_REDRAW_ALL 1 +#define PATH_TOOL_REDRAW_ACTIVE 2 +#define PATH_TOOL_REDRAW_HANDLES 4 + +#define SUBDIVIDE 1000 + +typedef enum { SEGMENT_LINE=0, SEGMENT_BEZIER} SegmentType; + +enum { ON_ANCHOR, ON_HANDLE, ON_CURVE, ON_CANVAS }; + +typedef struct _path_segment PathSegment; +typedef struct _path_curve PathCurve; +typedef struct _npath NPath; + + +struct _path_segment +{ + SegmentType type; /* What type of segment */ + gdouble x, y; /* location of starting-point in image space */ + gpointer data; /* Additional data, dependant of segment-type */ + + guint32 flags; /* Various Flags: Is the Segment active? */ + + PathCurve *parent; /* the parent Curve */ + PathSegment *next; /* Next Segment or NULL */ + PathSegment *prev; /* Previous Segment or NULL */ + +}; + + +struct _path_curve +{ + PathSegment *segments; /* The segments of the curve */ + PathSegment *cur_segment; /* the current segment */ + NPath *parent; /* the parent Path */ + PathCurve *next; /* Next Curve or NULL */ + PathCurve *prev; /* Previous Curve or NULL */ +}; + + +struct _npath +{ + PathCurve *curves; /* the curves */ + PathCurve *cur_curve; /* the current curve */ + GString *name; /* the name of the path */ + guint32 state; /* is the path locked? */ + /* GimpPathTool *path_tool; */ /* The parent Path Tool */ +}; + + +typedef void +(*PathTraverseFunc) (NPath *, + PathCurve *, + gpointer); +typedef void +(*CurveTraverseFunc) (NPath *, + PathCurve *, + PathSegment *, + gpointer); +typedef void +(*SegmentTraverseFunc) (NPath *, + PathCurve *, + PathSegment *, + gint, + gint, + gpointer); /* @@ -32,57 +109,49 @@ * Array is allocated. */ -typedef guint (*PathGetPointsFunc) (PathTool *path_tool, - PathSegment *segment, - GdkPoint *points, +typedef guint (*PathGetPointsFunc) (PathSegment *segment, + gdouble *points, guint npoints, gdouble start, gdouble end); -typedef void (*PathGetPointFunc) (PathTool *path_tool, - PathSegment *segment, +typedef void (*PathGetPointFunc) (PathSegment *segment, gdouble position, gdouble *x, gdouble *y); -typedef void (*PathDrawHandlesFunc) (Tool *tool, +typedef void (*PathDrawHandlesFunc) (GimpDrawTool *tool, PathSegment *segment); -typedef void (*PathDrawSegmentFunc) (Tool *tool, +typedef void (*PathDrawSegmentFunc) (GimpDrawTool *tool, PathSegment *segment); -typedef gdouble (*PathOnSegmentFunc) (Tool *tool, - PathSegment *segment, +typedef gdouble (*PathOnSegmentFunc) (PathSegment *segment, gint x, gint y, gint halfwidth, gint *distance); -typedef void (*PathDragSegmentFunc) (PathTool *path_tool, - PathSegment *segment, +typedef void (*PathDragSegmentFunc) (PathSegment *segment, gdouble position, gdouble dx, gdouble dy); -typedef gint (*PathOnHandlesFunc) (PathTool *path_tool, - PathSegment *segment, +typedef gint (*PathOnHandlesFunc) (PathSegment *segment, gdouble x, gdouble y, gdouble halfwidth); -typedef void (*PathDragHandleFunc) (PathTool *path_tool, - PathSegment *segment, +typedef void (*PathDragHandleFunc) (PathSegment *segment, gdouble dx, gdouble dy, gint handle_id); -typedef PathSegment * (*PathInsertAnchorFunc) (PathTool *path_tool, - PathSegment *segment, +typedef PathSegment * (*PathInsertAnchorFunc) (PathSegment *segment, gdouble position); -typedef void (*PathUpdateSegmentFunc) (PathTool *path_tool, - PathSegment *segment); +typedef void (*PathUpdateSegmentFunc) (PathSegment *segment); typedef void (*PathFlipSegmentFunc) (PathSegment *segment); @@ -108,66 +177,58 @@ typedef struct { guint -path_curve_get_points (PathTool *path_tool, - PathSegment *segment, - GdkPoint *points, +path_curve_get_points (PathSegment *segment, + gdouble *points, guint npoints, gdouble start, gdouble end); void -path_curve_get_point (PathTool *path_tool, - PathSegment *segment, +path_curve_get_point (PathSegment *segment, gdouble position, gdouble *x, gdouble *y); void -path_curve_draw_handles (Tool *tool, +path_curve_draw_handles (GimpDrawTool *tool, PathSegment *segment); void -path_curve_draw_segment (Tool *tool, +path_curve_draw_segment (GimpDrawTool *tool, PathSegment *segment); gdouble -path_curve_on_segment (Tool *tool, - PathSegment *segment, +path_curve_on_segment (PathSegment *segment, gint x, gint y, gint halfwidth, gint *distance); void -path_curve_drag_segment (PathTool *path_tool, - PathSegment *segment, +path_curve_drag_segment (PathSegment *segment, gdouble position, gdouble dx, gdouble dy); gint -path_curve_on_handle (PathTool *path_tool, - PathSegment *segment, +path_curve_on_handle (PathSegment *segment, gdouble x, gdouble y, gdouble halfwidth); void -path_curve_drag_handle (PathTool *path_tool, - PathSegment *segment, +path_curve_drag_handle (PathSegment *segment, gdouble dx, gdouble dy, gint handle_id); PathSegment * -path_curve_insert_anchor (PathTool *path_tool, - PathSegment *segment, - gdouble position); +path_curve_insert_anchor (PathSegment *segment, + gdouble position); void -path_curve_update_segment (PathTool *path_tool, - PathSegment *segment); +path_curve_update_segment (PathSegment *segment); void path_curve_flip_segment (PathSegment *segment); diff --git a/app/pixmaps2.h b/app/pixmaps2.h index a253d04d0c..e114f8551b 100644 --- a/app/pixmaps2.h +++ b/app/pixmaps2.h @@ -1012,7 +1012,6 @@ static char *xinput_airbrush_bits [] = /* GIMP icon image format -- S. Kimball, P. Mattis */ /* Image name: path_tool */ -/* #define path_tool_width 22 #define path_tool_height 22 static char *path_tool_bits [] = @@ -1040,7 +1039,6 @@ static char *path_tool_bits [] = "..a...................", "......................" }; -*/ /* GIMP icon image format -- S. Kimball, P. Mattis */ /* Image name: by_color_select */ diff --git a/app/tools/Makefile.am b/app/tools/Makefile.am index c887bc820f..25a902c621 100644 --- a/app/tools/Makefile.am +++ b/app/tools/Makefile.am @@ -54,6 +54,8 @@ libapptools_la_SOURCES = \ gimppainttool.c \ gimppainttool.h \ gimppainttool_kernels.h \ + gimppathtool.c \ + gimppathtool.h \ gimppenciltool.c \ gimppenciltool.h \ ## gimpperspectivetool.c \ @@ -90,7 +92,10 @@ libapptools_la_SOURCES = \ gimptoolinfo.h \ tool_manager.c \ tool_manager.h \ - tools.c + tools.c \ + path_tool.h \ + path_tool.c \ + path_toolP.h ## brightness_contrast.c \ ## brightness_contrast.h \ diff --git a/app/tools/gimpdrawtool.c b/app/tools/gimpdrawtool.c index 12ae7e48a6..15a7560d09 100644 --- a/app/tools/gimpdrawtool.c +++ b/app/tools/gimpdrawtool.c @@ -22,7 +22,9 @@ #include "apptypes.h" +#include "gdisplay.h" #include "gimpdrawtool.h" +#include "libgimpmath/gimpmath.h" enum @@ -225,3 +227,70 @@ gimp_draw_tool_pause (GimpDrawTool *core) core->paused_count++; } + + +void +gimp_draw_tool_draw_handle (GimpDrawTool *draw_tool, + gdouble x, + gdouble y, + gint size, + gint type) +{ + GimpTool *tool = GIMP_TOOL (draw_tool); + gdouble hx, hy; + gint filled; + + gdisplay_transform_coords_f (tool->gdisp, x, y, &hx, &hy, TRUE); + + hx = ROUND (hx); + hy = ROUND (hy); + + filled = type % 2; + + if (type < 2) + gdk_draw_rectangle (tool->gdisp->canvas->window, + draw_tool->gc, filled, + hx - size/2, hy - size/2, + size, size); + else + gdk_draw_arc (tool->gdisp->canvas->window, + draw_tool->gc, filled, + hx - size/2, hy - size/2, + size, size, 0, 360); + +} + + +void +gimp_draw_tool_draw_lines (GimpDrawTool *draw_tool, + gdouble *points, + gint npoints, + gint filled) +{ + GimpTool *tool = GIMP_TOOL (draw_tool); + GdkPoint *coords = g_new (GdkPoint, npoints); + + gint i; + gdouble sx, sy; + + for (i=0; i < npoints ; i++) + { + gdisplay_transform_coords_f (tool->gdisp, points[i*2], points[i*2+1], + &sx, &sy, TRUE); + coords[i].x = ROUND (sx); + coords[i].y = ROUND (sy); + } + + + if (filled) + gdk_draw_polygon (tool->gdisp->canvas->window, + draw_tool->gc, TRUE, + coords, npoints); + else + gdk_draw_lines (tool->gdisp->canvas->window, + draw_tool->gc, + coords, npoints); + + g_free (coords); + +} diff --git a/app/tools/gimpdrawtool.h b/app/tools/gimpdrawtool.h index 7409ed6003..598c37eb51 100644 --- a/app/tools/gimpdrawtool.h +++ b/app/tools/gimpdrawtool.h @@ -70,5 +70,16 @@ void gimp_draw_tool_stop (GimpDrawTool *draw_tool); void gimp_draw_tool_pause (GimpDrawTool *draw_tool); void gimp_draw_tool_resume (GimpDrawTool *draw_tool); +void gimp_draw_tool_draw_handle (GimpDrawTool *draw_tool, + gdouble x, + gdouble y, + gint size, + gint type); + +void gimp_draw_tool_draw_lines (GimpDrawTool *draw_tool, + gdouble *points, + gint npoints, + gint filled); + #endif /* __GIMP_DRAW_TOOL_H__ */ diff --git a/app/tools/gimppathtool.c b/app/tools/gimppathtool.c new file mode 100644 index 0000000000..371f52cfec --- /dev/null +++ b/app/tools/gimppathtool.c @@ -0,0 +1,830 @@ +/* The GIMP -- an image manipulation program + * + * This file Copyright (C) 1999 Simon Budig + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include + +#include + +#include "libgimpmath/gimpmath.h" +#include "libgimpwidgets/gimpwidgets.h" + +#include "apptypes.h" + +#include "gdisplay.h" +#include "path_curves.h" +#include "gimpdrawtool.h" +#include "gimppathtool.h" +#include "tool_manager.h" +#include "tool_options.h" + +#include "libgimp/gimpintl.h" + +#include "path_tool.h" +#include "pixmaps2.h" + + +/* definitions */ + + +/* 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_destroy (GtkObject *object); + +static void gimp_path_tool_control (GimpTool *tool, + ToolAction action, + GDisplay *gdisp); +static void gimp_path_tool_button_press (GimpTool *tool, + GdkEventButton *bevent, + GDisplay *gdisp); +static void gimp_path_tool_button_release (GimpTool *tool, + GdkEventButton *bevent, + GDisplay *gdisp); +static void gimp_path_tool_motion (GimpTool *tool, + GdkEventMotion *mevent, + GDisplay *gdisp); +static void gimp_path_tool_cursor_update (GimpTool *tool, + GdkEventMotion *mevent, + GDisplay *gdisp); + +static void gimp_path_tool_draw (GimpDrawTool *draw_tool); + + + +static GimpDrawToolClass *parent_class = NULL; + +/* the move tool options */ +static ToolOptions *path_options = NULL; + + +void +gimp_path_tool_register (void) +{ + tool_manager_register_tool (GIMP_TYPE_PATH_TOOL, + FALSE, + "gimp:path_tool", + _("Path Tool"), + _("Path tool prototype"), + N_("/Tools/Path"), NULL, + NULL, "tools/path.html", + (const gchar **) path_tool_bits); +} + +GtkType +gimp_path_tool_get_type (void) +{ + static GtkType tool_type = 0; + + if (! tool_type) + { + GtkTypeInfo tool_info = + { + "GimpPathTool", + sizeof (GimpPathTool), + sizeof (GimpPathToolClass), + (GtkClassInitFunc) gimp_path_tool_class_init, + (GtkObjectInitFunc) gimp_path_tool_init, + /* reserved_1 */ NULL, + /* reserved_2 */ NULL, + (GtkClassInitFunc) NULL, + }; + + tool_type = gtk_type_unique (GIMP_TYPE_DRAW_TOOL, &tool_info); + } + + return tool_type; +} + +static void +gimp_path_tool_class_init (GimpPathToolClass *klass) +{ + GtkObjectClass *object_class; + GimpToolClass *tool_class; + GimpDrawToolClass *draw_tool_class; + + object_class = (GtkObjectClass *) klass; + tool_class = (GimpToolClass *) klass; + draw_tool_class = (GimpDrawToolClass *) klass; + + parent_class = gtk_type_class (GIMP_TYPE_DRAW_TOOL); + + object_class->destroy = gimp_path_tool_destroy; + + 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); + + /* The tool options */ + if (! path_options) + { + path_options = tool_options_new (); + + tool_manager_register_tool_options (GIMP_TYPE_PATH_TOOL, + (ToolOptions *) path_options); + } + + + tool->preserve = TRUE; /* Preserve on drawable change */ + + 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_destroy (GtkObject *object) +{ + GimpPathTool *path_tool = GIMP_PATH_TOOL (object); + +#ifdef PATH_TOOL_DEBUG + fprintf (stderr, "tools_free_path_tool start\n"); +#endif PATH_TOOL_DEBUG + + path_free_path (path_tool->cur_path); + + if (GTK_OBJECT_CLASS (parent_class)->destroy) + GTK_OBJECT_CLASS (parent_class)->destroy (object); +} + +static void +gimp_path_tool_control (GimpTool *tool, + ToolAction action, + GDisplay *gdisp) +{ + GimpPathTool *path_tool; + +#ifdef PATH_TOOL_DEBUG + fprintf (stderr, "path_tool_control\n"); +#endif PATH_TOOL_DEBUG + + path_tool = GIMP_PATH_TOOL (tool); + + switch (action) + { + case PAUSE: + break; + + case RESUME: + break; + + case HALT: + tool->state = INACTIVE; + break; + + default: + break; + } + + if (GIMP_TOOL_CLASS (parent_class)->control) + GIMP_TOOL_CLASS (parent_class)->control (tool, action, gdisp); +} + +static void +gimp_path_tool_button_press (GimpTool *tool, + GdkEventButton *bevent, + GDisplay *gdisp) +{ + GimpPathTool *path_tool = GIMP_PATH_TOOL (tool); + gint grab_pointer=0; + gint x, y, halfwidth, dummy; + +#ifdef PATH_TOOL_DEBUG + fprintf (stderr, "path_tool_button_press\n"); +#endif PATH_TOOL_DEBUG + + /* Transform window-coordinates to canvas-coordinates */ + gdisplay_untransform_coords (gdisp, bevent->x, bevent->y, &x, &y, TRUE, 0); +#ifdef PATH_TOOL_DEBUG + fprintf(stderr, "Clickcoordinates %d, %d\n",x,y); +#endif PATH_TOOL_DEBUG + path_tool->click_x = x; + path_tool->click_y = y; + path_tool->click_modifier = bevent->state; + /* get halfwidth in image coord */ + gdisplay_untransform_coords (gdisp, bevent->x + PATH_TOOL_HALFWIDTH, 0, &halfwidth, &dummy, TRUE, 0); + halfwidth -= x; + path_tool->click_halfwidth = halfwidth; + + if (!path_tool->cur_path->curves) + gimp_draw_tool_start (GIMP_DRAW_TOOL(path_tool), gdisp->canvas->window); + + /* determine point, where clicked, + * switch accordingly. + */ + + path_tool->click_type = + path_tool_cursor_position (path_tool->cur_path, x, y, halfwidth, + &(path_tool->click_path), + &(path_tool->click_curve), + &(path_tool->click_segment), + &(path_tool->click_position), + &(path_tool->click_handle_id)); + + switch (path_tool->click_type) + { + case ON_CANVAS: + grab_pointer = gimp_path_tool_button_press_canvas(path_tool, bevent, gdisp); + break; + + case ON_ANCHOR: + grab_pointer = gimp_path_tool_button_press_anchor(path_tool, bevent, gdisp); + break; + + case ON_HANDLE: + grab_pointer = gimp_path_tool_button_press_handle(path_tool, bevent, gdisp); + break; + + case ON_CURVE: + grab_pointer = gimp_path_tool_button_press_curve(path_tool, bevent, gdisp); + break; + + default: + g_message("Huh? Whats happening here? (button_press_*)"); + } + + if (grab_pointer) + gdk_pointer_grab (gdisp->canvas->window, FALSE, + GDK_POINTER_MOTION_HINT_MASK | + GDK_BUTTON1_MOTION_MASK | + GDK_BUTTON_RELEASE_MASK, + NULL, NULL, bevent->time); + + tool->state = ACTIVE; + +} + +gint +gimp_path_tool_button_press_anchor (GimpPathTool *path_tool, + GdkEventButton *bevent, + GDisplay *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 + fprintf(stderr, "path_tool_button_press_anchor:\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; + } + + /* + * We have to determine, if this was a doubleclick for ourself, because + * disp_callback.c ignores the GDK_[23]BUTTON_EVENT's and adding them to + * the switch statement confuses some tools. + */ + if (bevent->time - last_click_time < 250) { + doubleclick=TRUE; +#ifdef PATH_TOOL_DEBUG + fprintf (stderr, "Doppelclick!\n"); +#endif PATH_TOOL_DEBUG + } else + doubleclick=FALSE; + last_click_time = bevent->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 + fprintf (stderr, "p_sas: %p\n", p_sas); +#endif PATH_TOOL_DEBUG + + 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; +} + + +gint +gimp_path_tool_button_press_handle (GimpPathTool *path_tool, + GdkEventButton *bevent, + GDisplay *gdisp) +{ + static guint32 last_click_time=0; + gboolean doubleclick=FALSE; + + NPath * cur_path = path_tool->cur_path; + gint grab_pointer; + +#ifdef PATH_TOOL_DEBUG + fprintf(stderr, "path_tool_button_press_handle:\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; + } + + /* + * We have to determine, if this was a doubleclick for ourself, because + * disp_callback.c ignores the GDK_[23]BUTTON_EVENT's and adding them to + * the switch statement confuses some tools. + */ + if (bevent->time - last_click_time < 250) { + doubleclick=TRUE; +#ifdef PATH_TOOL_DEBUG + fprintf (stderr, "Doppelclick!\n"); +#endif PATH_TOOL_DEBUG + } else + doubleclick=FALSE; + last_click_time = bevent->time; + + return grab_pointer; +} + +gint +gimp_path_tool_button_press_canvas (GimpPathTool *path_tool, + GdkEventButton *bevent, + GDisplay *gdisp) +{ + + NPath * 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_canvas:\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; + } + + 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; +} + +gint +gimp_path_tool_button_press_curve (GimpPathTool *path_tool, + GdkEventButton *bevent, + GDisplay *gdisp) +{ + NPath * cur_path = path_tool->cur_path; + 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 NPath\n"); +#endif PATH_TOOL_DEBUG + 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, + GdkEventButton *bevent, + GDisplay *gdisp) +{ + GimpPathTool *path_tool = GIMP_PATH_TOOL (tool); + +#ifdef PATH_TOOL_DEBUG + fprintf (stderr, "path_tool_button_release\n"); +#endif PATH_TOOL_DEBUG + + path_tool->state &= ~PATH_TOOL_DRAG; + + gdk_pointer_ungrab (bevent->time); + gdk_flush (); +} + + +static void +gimp_path_tool_motion (GimpTool *tool, + GdkEventMotion *mevent, + GDisplay *gdisp) +{ + GimpPathTool *path_tool; + + path_tool = GIMP_PATH_TOOL (tool); + + if (gtk_events_pending()) return; + + switch (path_tool->click_type) { + case ON_ANCHOR: + gimp_path_tool_motion_anchor (path_tool, mevent, gdisp); + break; + case ON_HANDLE: + gimp_path_tool_motion_handle (path_tool, mevent, gdisp); + break; + case ON_CURVE: + gimp_path_tool_motion_curve (path_tool, mevent, gdisp); + break; + default: + return; + } +} + + + +void +gimp_path_tool_motion_anchor (GimpPathTool *path_tool, + GdkEventMotion *mevent, + GDisplay *gdisp) +{ + gdouble dx, dy, d; + gint x,y; + static gint dxsum = 0; + static gint dysum = 0; + + /* + * Dont do anything, if the user clicked with pressed CONTROL-Key, + * because he deleted an anchor. + */ + if (path_tool->click_modifier & GDK_CONTROL_MASK) + return; + + if (!(path_tool->state & PATH_TOOL_DRAG)) + { + path_tool->state |= PATH_TOOL_DRAG; + dxsum = 0; + dysum = 0; + } + + gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &x, &y, TRUE, 0); + + dx = x - path_tool->click_x - dxsum; + dy = y - path_tool->click_y - dysum; + + /* restrict to horizontal/vertical lines, if modifiers are pressed + * I'm not sure, if this is intuitive for the user. Esp. When moving + * an endpoint of an curve I'd expect, that the *line* is + * horiz/vertical - not the delta to the point, where the point was + * originally... + */ + if (mevent->state & GDK_MOD1_MASK) + { + if (mevent->state & GDK_CONTROL_MASK) + { + d = (fabs(dx) + fabs(dy)) / 2; + d = (fabs(x - path_tool->click_x) + fabs(y - path_tool->click_y)) / 2; + dx = ((x < path_tool->click_x) ? -d : d ) - dxsum; + dy = ((y < path_tool->click_y) ? -d : d ) - dysum; + } + else + dx = - dxsum; + } + else if (mevent->state & GDK_CONTROL_MASK) + dy = - dysum; + + + path_tool->draw |= PATH_TOOL_REDRAW_ACTIVE; + + 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; + +} + +void +gimp_path_tool_motion_handle (GimpPathTool *path_tool, + GdkEventMotion *mevent, + GDisplay *gdisp) +{ + gdouble dx, dy; + gint x,y; + static gint dxsum = 0; + static gint dysum = 0; + + /* + * Dont do anything, if the user clicked with pressed CONTROL-Key, + * because he moved the handle to the anchor an anchor. + * XXX: Not yet! :-) + */ + if (path_tool->click_modifier & GDK_CONTROL_MASK) + return; + + if (!(path_tool->state & PATH_TOOL_DRAG)) + { + path_tool->state |= PATH_TOOL_DRAG; + dxsum = 0; + dysum = 0; + } + + gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &x, &y, TRUE, 0); + + dx = x - path_tool->click_x - dxsum; + dy = y - path_tool->click_y - dysum; + + path_tool->draw |= PATH_TOOL_REDRAW_ACTIVE; + + 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; + +} + + +void +gimp_path_tool_motion_curve (GimpPathTool *path_tool, + GdkEventMotion *mevent, + GDisplay *gdisp) +{ + gdouble dx, dy; + gint x,y; + static gint dxsum = 0; + static gint dysum = 0; + + if (!(path_tool->state & PATH_TOOL_DRAG)) + { + path_tool->state |= PATH_TOOL_DRAG; + dxsum = 0; + dysum = 0; + } + + gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &x, &y, TRUE, 0); + + dx = x - path_tool->click_x - dxsum; + dy = y - path_tool->click_y - dysum; + + path_tool->draw |= PATH_TOOL_REDRAW_ACTIVE; + + 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, + GdkEventMotion *mevent, + GDisplay *gdisp) +{ + GimpPathTool *path_tool = GIMP_PATH_TOOL (tool); +#if 0 + gint x, y, halfwidth, dummy, cursor_location; + +#ifdef PATH_TOOL_DEBUG + /* fprintf (stderr, "path_tool_cursor_update\n"); + */ +#endif PATH_TOOL_DEBUG + + path_tool = (PathTool *) tool->private; + + gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &x, &y, TRUE, 0); + /* get halfwidth in image coord */ + gdisplay_untransform_coords (gdisp, mevent->x + PATH_TOOL_HALFWIDTH, 0, &halfwidth, &dummy, TRUE, 0); + halfwidth -= x; + + cursor_location = path_tool_cursor_position (tool, x, y, halfwidth, NULL, NULL, NULL, NULL, NULL); + + switch (cursor_location) { + case ON_CANVAS: + gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE1AP_CURSOR); + break; + case ON_ANCHOR: + gdisplay_install_tool_cursor (gdisp, GDK_FLEUR); + break; + case ON_HANDLE: + gdisplay_install_tool_cursor (gdisp, GDK_CROSSHAIR); + break; + case ON_CURVE: + gdisplay_install_tool_cursor (gdisp, GDK_CROSSHAIR); + break; + default: + gdisplay_install_tool_cursor (gdisp, GDK_QUESTION_ARROW); + break; + } + +/* New Syntax */ + gdisplay_install_tool_cursor (gdisp, + ctype, + GIMP_MEASURE_TOOL_CURSOR, + cmodifier); +#endif +} + + +static void +gimp_path_tool_draw (GimpDrawTool *draw_tool) +{ + GimpPathTool *path_tool; + GimpTool *tool; + + path_tool = GIMP_PATH_TOOL (draw_tool); + tool = GIMP_TOOL (draw_tool); + +} + diff --git a/app/tools/gimppathtool.h b/app/tools/gimppathtool.h new file mode 100644 index 0000000000..9f7ccb474e --- /dev/null +++ b/app/tools/gimppathtool.h @@ -0,0 +1,101 @@ +/* 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) (GTK_CHECK_CAST ((obj), GIMP_TYPE_PATH_TOOL, GimpPathTool)) +#define GIMP_IS_PATH_TOOL(obj) (GTK_CHECK_TYPE ((obj), GIMP_TYPE_PATH_TOOL)) +#define GIMP_PATH_TOOL_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GIMP_TYPE_PATH_TOOL, GimpPathToolClass)) +#define GIMP_IS_PATH_TOOL_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_PATH_TOOL)) + + +typedef struct _GimpPathToolClass GimpPathToolClass; + +struct _GimpPathTool +{ + GimpDrawTool parent_instance; + + gint click_type; /* where did the user click? */ + gint click_x; /* X-coordinate of the click */ + gint click_y; /* Y-coordinate of the click */ + gint click_halfwidth; + 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 (void); + +GtkType gimp_path_tool_get_type (void); + +void gimp_path_tool_button_press (GimpTool *, GdkEventButton *, GDisplay *); +void gimp_path_tool_button_release (GimpTool *, GdkEventButton *, GDisplay *); +void gimp_path_tool_motion (GimpTool *, GdkEventMotion *, GDisplay *); +void gimp_path_tool_cursor_update (GimpTool *, GdkEventMotion *, GDisplay *); +void gimp_path_tool_control (GimpTool *, ToolAction, GDisplay *); +void gimp_path_tool_draw (GimpDrawTool *); +void gimp_path_tool_draw_curve (GimpPathTool *, PathCurve *); +void gimp_path_tool_draw_segment (GimpPathTool *, PathSegment *); + +gdouble gimp_path_tool_on_curve (GimpPathTool *, gint, gint, gint, + NPath**, PathCurve**, PathSegment**); +gboolean gimp_path_tool_on_anchors (GimpPathTool *, gint, gint, gint, + NPath**, PathCurve**, PathSegment**); +gint gimp_path_tool_on_handles (GimpPathTool *, gint, gint, gint, + NPath **, PathCurve **, PathSegment **); + +gint gimp_path_tool_button_press_canvas (GimpPathTool *, GdkEventButton *, GDisplay *); +gint gimp_path_tool_button_press_anchor (GimpPathTool *, GdkEventButton *, GDisplay *); +gint gimp_path_tool_button_press_handle (GimpPathTool *, GdkEventButton *, GDisplay *); +gint gimp_path_tool_button_press_curve (GimpPathTool *, GdkEventButton *, GDisplay *); +void gimp_path_tool_motion_anchor (GimpPathTool *, GdkEventMotion *, GDisplay *); +void gimp_path_tool_motion_handle (GimpPathTool *, GdkEventMotion *, GDisplay *); +void gimp_path_tool_motion_curve (GimpPathTool *, GdkEventMotion *, GDisplay *); + + + +#endif /* __GIMP_PATH_TOOL_H__ */ diff --git a/app/tools/path_tool.c b/app/tools/path_tool.c index f25924ddaa..ac5175b05a 100644 --- a/app/tools/path_tool.c +++ b/app/tools/path_tool.c @@ -27,18 +27,20 @@ * segments between two anchors. */ +/* #include -/* #include "appenv.h" - */ -#include "draw_core.h" -#include "cursorutil.h" -#include "path_tool.h" -#include "path_toolP.h" + #include "path_curves.h" - #include "config.h" #include "libgimp/gimpintl.h" +*/ + +#include +#include +#include "apptypes.h" +#include "path_curves.h" +#include "path_tool.h" /* * Every new curve-type has to have a parameter between 0 and 1, and @@ -61,22 +63,22 @@ void path_segment_get_coordinates (PathSegment *, gdouble, gint *, gint *); -void path_traverse_path (Path *, +void path_traverse_path (NPath *, PathTraverseFunc, CurveTraverseFunc, SegmentTraverseFunc, gpointer); -void path_traverse_curve (Path *, +void path_traverse_curve (NPath *, PathCurve *, CurveTraverseFunc, SegmentTraverseFunc, gpointer); -void path_traverse_segment (Path *, +void path_traverse_segment (NPath *, PathCurve *, PathSegment *, SegmentTraverseFunc, gpointer); -gdouble path_locate_point (Path *, +gdouble path_locate_point (NPath *, PathCurve **, PathSegment **, gint, @@ -85,17 +87,26 @@ gdouble path_locate_point (Path *, gint, gint); +gdouble path_tool_on_curve (NPath *path, + gint x, + gint y, + gint halfwidth, + NPath **ret_pathP, + PathCurve **ret_curveP, + PathSegment **ret_segmentP); + + /* Tools to manipulate paths, curves, segments */ -PathCurve * path_add_curve (Path *, +PathCurve * path_add_curve (NPath *, gint, gint); -PathSegment * path_append_segment (Path *, +PathSegment * path_append_segment (NPath *, PathCurve *, SegmentType, gint, gint); -PathSegment * path_prepend_segment (Path *, +PathSegment * path_prepend_segment (NPath *, PathCurve *, SegmentType, gint, @@ -105,14 +116,14 @@ PathSegment * path_split_segment (PathSegment *, void path_join_curves (PathSegment *, PathSegment *); void path_flip_curve (PathCurve *); -void path_free_path (Path *); +void path_free_path (NPath *); void path_free_curve (PathCurve *); void path_free_segment (PathSegment *); void path_delete_segment (PathSegment *); -void path_print (Path *); -void path_offset_active (Path *, gdouble, gdouble); -void path_set_flags (PathTool *, - Path *, +void path_print (NPath *); +void path_offset_active (NPath *, gdouble, gdouble); +void path_set_flags (GimpPathTool *, + NPath *, PathCurve *, PathSegment *, guint32, @@ -120,13 +131,14 @@ void path_set_flags (PathTool *, /* High level image-manipulation functions */ -void path_stroke (PathTool *, - Path *); -void path_to_selection (PathTool *, - Path *); +void path_stroke (GimpPathTool *, + NPath *); +void path_to_selection (GimpPathTool *, + NPath *); /* Functions necessary for the tool */ +#if 0 void path_tool_button_press (Tool *, GdkEventButton *, gpointer); void path_tool_button_release (Tool *, GdkEventButton *, gpointer); void path_tool_motion (Tool *, GdkEventMotion *, gpointer); @@ -137,11 +149,11 @@ void path_tool_draw_curve (Tool *, PathCurve *); void path_tool_draw_segment (Tool *, PathSegment *); gdouble path_tool_on_curve (Tool *, gint, gint, gint, - Path**, PathCurve**, PathSegment**); + NPath**, PathCurve**, PathSegment**); gboolean path_tool_on_anchors (Tool *, gint, gint, gint, - Path**, PathCurve**, PathSegment**); + NPath**, PathCurve**, PathSegment**); gint path_tool_on_handles (Tool *, gint, gint, gint, - Path **, PathCurve **, PathSegment **); + NPath **, PathCurve **, PathSegment **); gint path_tool_button_press_canvas (Tool *, GdkEventButton *, GDisplay *); gint path_tool_button_press_anchor (Tool *, GdkEventButton *, GDisplay *); @@ -151,6 +163,7 @@ void path_tool_motion_anchor (Tool *, GdkEventMotion *, GDisplay *); void path_tool_motion_handle (Tool *, GdkEventMotion *, GDisplay *); void path_tool_motion_curve (Tool *, GdkEventMotion *, GDisplay *); +#endif /* the path tool options */ static ToolOptions *path_options = NULL; @@ -181,7 +194,7 @@ static ToolOptions *path_options = NULL; */ void -path_traverse_path (Path *path, +path_traverse_path (NPath *path, PathTraverseFunc pathfunc, CurveTraverseFunc curvefunc, SegmentTraverseFunc segmentfunc, @@ -207,7 +220,7 @@ path_traverse_path (Path *path, void -path_traverse_curve (Path *path, +path_traverse_curve (NPath *path, PathCurve *curve, CurveTraverseFunc curvefunc, SegmentTraverseFunc segmentfunc, @@ -232,7 +245,7 @@ path_traverse_curve (Path *path, } void -path_traverse_segment (Path *path, +path_traverse_segment (NPath *path, PathCurve *curve, PathSegment *segment, SegmentTraverseFunc function, @@ -257,7 +270,7 @@ path_traverse_segment (Path *path, */ PathCurve * -path_add_curve (Path * cur_path, +path_add_curve (NPath * cur_path, gint x, gint y) { @@ -293,7 +306,7 @@ path_add_curve (Path * cur_path, PathSegment * -path_append_segment (Path * cur_path, +path_append_segment (NPath * cur_path, PathCurve * cur_curve, SegmentType type, gint x, @@ -347,7 +360,7 @@ path_append_segment (Path * cur_path, PathSegment * -path_prepend_segment (Path * cur_path, +path_prepend_segment (NPath * cur_path, PathCurve * cur_curve, SegmentType type, gint x, @@ -409,8 +422,7 @@ path_split_segment (PathSegment *segment, new_segment = g_new (PathSegment, 1); new_segment->type = segment->type; - /* XXX: Giving PathTool as NULL Pointer! */ - path_curve_get_point (NULL, segment, position, &(new_segment->x), &(new_segment->y)); + path_curve_get_point (segment, position, &(new_segment->x), &(new_segment->y)); new_segment->flags = 0; new_segment->parent = segment->parent; new_segment->next = segment->next; @@ -602,7 +614,7 @@ path_flip_curve (PathCurve *curve) void -path_free_path (Path * path) +path_free_path (NPath * path) { PathCurve *tmp1, *tmp2; @@ -651,7 +663,7 @@ path_free_segment (PathSegment *segment) * consistent */ - path_set_flags (segment->parent->parent->path_tool, segment->parent->parent, + path_set_flags (NULL, segment->parent->parent, segment->parent, segment, 0, SEGMENT_ACTIVE); path_curve_cleanup_segment(segment); @@ -715,11 +727,11 @@ path_delete_segment (PathSegment *segment) */ gint -path_tool_cursor_position (Tool *tool, +path_tool_cursor_position (NPath *path, gint x, gint y, gint halfwidth, - Path **pathP, + NPath **pathP, PathCurve **curveP, PathSegment **segmentP, gdouble *positionP, @@ -728,16 +740,16 @@ path_tool_cursor_position (Tool *tool, gdouble pos; gint handle_id; - if (path_tool_on_anchors (tool, x, y, halfwidth, pathP, curveP, segmentP)) + if (path_tool_on_anchors (path, x, y, halfwidth, pathP, curveP, segmentP)) return ON_ANCHOR; - handle_id = path_tool_on_handles (tool, x, y, halfwidth, pathP, curveP, segmentP); + handle_id = path_tool_on_handles (path, x, y, halfwidth, pathP, curveP, segmentP); if (handle_id) { if (handle_idP) (*handle_idP) = handle_id; return ON_HANDLE; } - pos = path_tool_on_curve (tool, x, y, halfwidth, pathP, curveP, segmentP); + pos = path_tool_on_curve (path, x, y, halfwidth, pathP, curveP, segmentP); if (pos >= 0 && pos <= 1) { if (positionP) (*positionP) = pos; return ON_CURVE; @@ -748,6 +760,7 @@ path_tool_cursor_position (Tool *tool, } +#if 0 /************************************************************** * The click-callbacks for the tool */ @@ -837,7 +850,7 @@ path_tool_button_press_anchor (Tool *tool, gboolean doubleclick=FALSE; PathTool *path_tool = tool->private; - Path * cur_path = path_tool->cur_path; + NPath * cur_path = path_tool->cur_path; PathSegment *p_sas; gint grab_pointer; @@ -962,7 +975,7 @@ path_tool_button_press_handle (Tool *tool, gboolean doubleclick=FALSE; PathTool *path_tool = tool->private; - Path * cur_path = path_tool->cur_path; + NPath * cur_path = path_tool->cur_path; gint grab_pointer; #ifdef PATH_TOOL_DEBUG @@ -1002,7 +1015,7 @@ path_tool_button_press_canvas (Tool *tool, { PathTool *path_tool = tool->private; - Path * cur_path = path_tool->cur_path; + NPath * cur_path = path_tool->cur_path; PathCurve * cur_curve; PathSegment * cur_segment; gint grab_pointer; @@ -1058,7 +1071,7 @@ path_tool_button_press_curve (Tool *tool, { PathTool *path_tool = tool->private; - Path * cur_path = path_tool->cur_path; + NPath * cur_path = path_tool->cur_path; PathSegment * cur_segment; gint grab_pointer; @@ -1070,7 +1083,7 @@ path_tool_button_press_curve (Tool *tool, if (!cur_path) { #ifdef PATH_TOOL_DEBUG - fprintf (stderr, "Fatal error: No current Path\n"); + fprintf (stderr, "Fatal error: No current NPath\n"); #endif PATH_TOOL_DEBUG return 0; } @@ -1421,7 +1434,7 @@ tools_new_path_tool (void) private->state = 0; private->draw = PATH_TOOL_REDRAW_ALL; private->core = draw_core_new (path_tool_draw); - private->cur_path = g_new0(Path, 1); + private->cur_path = g_new0(NPath, 1); private->scanlines = NULL; @@ -1470,14 +1483,14 @@ tools_free_path_tool (Tool *tool) } +#endif /************************************************************** * Set of function to determine, if the click was on a segment */ typedef struct { - Tool *tool; - Path *path; + NPath *path; PathCurve *curve; PathSegment *segment; gint testx; @@ -1490,7 +1503,7 @@ typedef struct { /* This is a CurveTraverseFunc */ void -path_tool_on_curve_helper (Path *path, +path_tool_on_curve_helper (NPath *path, PathCurve *curve, PathSegment *segment, gpointer ptr) @@ -1501,7 +1514,7 @@ path_tool_on_curve_helper (Path *path, if (segment && segment->next && data && data->distance > 0) { - position = path_curve_on_segment (data->tool, segment, data->testx, data->testy, data->halfwidth, &distance); + position = path_curve_on_segment (segment, data->testx, data->testy, data->halfwidth, &distance); if (position >= 0 && distance < data->distance ) { data->path = path; @@ -1515,20 +1528,19 @@ path_tool_on_curve_helper (Path *path, } gdouble -path_tool_on_curve (Tool *tool, +path_tool_on_curve (NPath *path, gint x, gint y, gint halfwidth, - Path **ret_pathP, + NPath **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->path = path; + data->curve = NULL; data->segment = NULL; data->testx = x; data->testy = y; @@ -1537,7 +1549,7 @@ path_tool_on_curve (Tool *tool, data->position = -1; data->found = FALSE; - path_traverse_path (((PathTool *) data->tool->private)->cur_path, NULL, path_tool_on_curve_helper, NULL, data); + path_traverse_path (path, NULL, path_tool_on_curve_helper, NULL, data); if (ret_pathP) *ret_pathP = data->path; if (ret_curveP) *ret_curveP = data->curve; @@ -1556,7 +1568,7 @@ path_tool_on_curve (Tool *tool, */ typedef struct { - Path *path; + NPath *path; PathCurve *curve; PathSegment *segment; gint testx; @@ -1567,7 +1579,7 @@ typedef struct { /* This is a CurveTraverseFunc */ void -path_tool_on_anchors_helper (Path *path, +path_tool_on_anchors_helper (NPath *path, PathCurve *curve, PathSegment *segment, gpointer ptr) @@ -1592,18 +1604,18 @@ path_tool_on_anchors_helper (Path *path, } gboolean -path_tool_on_anchors (Tool *tool, +path_tool_on_anchors (NPath *path, gint x, gint y, gint halfwidth, - Path **ret_pathP, + NPath **ret_pathP, PathCurve **ret_curveP, PathSegment **ret_segmentP) { Path_on_anchors_type *data = g_new (Path_on_anchors_type, 1); gboolean ret_found; - data->path = NULL; + data->path = path; data->curve = NULL; data->segment = NULL; data->testx = x; @@ -1611,7 +1623,7 @@ path_tool_on_anchors (Tool *tool, data->distance = halfwidth * halfwidth + 1; data->found = FALSE; - path_traverse_path (((PathTool *) tool->private)->cur_path, NULL, path_tool_on_anchors_helper, NULL, data); + path_traverse_path (path, NULL, path_tool_on_anchors_helper, NULL, data); if (ret_pathP) *ret_pathP = data->path; if (ret_curveP) *ret_curveP = data->curve; @@ -1630,7 +1642,7 @@ path_tool_on_anchors (Tool *tool, */ typedef struct { - Path *path; + NPath *path; PathCurve *curve; PathSegment *segment; gint testx; @@ -1642,7 +1654,7 @@ typedef struct { /* This is a CurveTraverseFunc */ void -path_tool_on_handles_helper (Path *path, +path_tool_on_handles_helper (NPath *path, PathCurve *curve, PathSegment *segment, gpointer ptr) @@ -1652,8 +1664,8 @@ path_tool_on_handles_helper (Path *path, if (segment && data && !data->found) { - handle = path_curve_on_handle (NULL, segment, data->testx, data->testy, - data->halfwidth); + handle = path_curve_on_handle (segment, data->testx, data->testy, + data->halfwidth); if (handle) { data->path = path; @@ -1666,18 +1678,18 @@ path_tool_on_handles_helper (Path *path, } gint -path_tool_on_handles (Tool *tool, +path_tool_on_handles (NPath *path, gint x, gint y, gint halfwidth, - Path **ret_pathP, + NPath **ret_pathP, PathCurve **ret_curveP, PathSegment **ret_segmentP) { Path_on_handles_type *data = g_new (Path_on_handles_type, 1); gint handle_ret; - data->path = NULL; + data->path = path; data->curve = NULL; data->segment = NULL; data->testx = x; @@ -1686,7 +1698,7 @@ path_tool_on_handles (Tool *tool, data->handle_id = 0; data->found = FALSE; - path_traverse_path (((PathTool *) tool->private)->cur_path, NULL, path_tool_on_handles_helper, NULL, data); + path_traverse_path (path, NULL, path_tool_on_handles_helper, NULL, data); if (ret_pathP) *ret_pathP = data->path; if (ret_curveP) *ret_curveP = data->curve; @@ -1711,7 +1723,7 @@ typedef struct { /* This is a CurveTraverseFunc */ void -path_offset_active_helper (Path *path, +path_offset_active_helper (NPath *path, PathCurve *curve, PathSegment *segment, gpointer ptr) @@ -1726,7 +1738,7 @@ path_offset_active_helper (Path *path, } void -path_offset_active (Path *path, +path_offset_active (NPath *path, gdouble dx, gdouble dy) { @@ -1748,12 +1760,12 @@ path_offset_active (Path *path, typedef struct { guint32 bits_set; guint32 bits_clear; - PathTool *path_tool; + GimpPathTool *path_tool; } Path_set_flags_type; /* This is a CurveTraverseFunc */ void -path_set_flags_helper (Path *path, +path_set_flags_helper (NPath *path, PathCurve *curve, PathSegment *segment, gpointer ptr) @@ -1768,14 +1780,17 @@ path_set_flags_helper (Path *path, segment->flags |= tmp->bits_set; /* - * Some black magic: We try to remember, which is the single active segment. - * We count, how many segments are active (in path_tool->active_count) and - * XOR path_tool->single_active_segment every time we select or deselect - * an anchor. So if exactly one anchor is active, path_tool->single_active_segment - * points to it. + * Some black magic: We try to remember, which is the single active + * segment. We count, how many segments are active (in + * path_tool->active_count) and XOR path_tool->single_active_segment + * every time we select or deselect an anchor. So if exactly one anchor + * is active, path_tool->single_active_segment points to it. */ - /* If SEGMENT_ACTIVE state has changed change the PathTool data accordingly.*/ +#if 0 + /* If SEGMENT_ACTIVE state has changed change the PathTool data + * accordingly. + */ if (((segment->flags ^ oldflags) & SEGMENT_ACTIVE) && tmp && tmp->path_tool) { if (segment->flags & SEGMENT_ACTIVE) tmp->path_tool->active_count++; @@ -1788,12 +1803,13 @@ path_set_flags_helper (Path *path, tmp_uint ^= GPOINTER_TO_UINT(segment); tmp->path_tool->single_active_segment = GUINT_TO_POINTER(tmp_uint); } +#endif } } void -path_set_flags (PathTool *path_tool, - Path *path, +path_set_flags (GimpPathTool *path_tool, + NPath *path, PathCurve *curve, PathSegment *segment, guint32 bits_set, @@ -1821,11 +1837,12 @@ path_set_flags (PathTool *path_tool, /* This is a CurveTraverseFunc */ void -path_tool_draw_helper (Path *path, +path_tool_draw_helper (NPath *path, PathCurve *curve, PathSegment *segment, gpointer tool_ptr) { +#if 0 Tool * tool = (Tool *) tool_ptr; GDisplay * gdisp; PathTool * path_tool; @@ -1871,13 +1888,15 @@ path_tool_draw_helper (Path *path, else if (!segment) fprintf(stderr, "path_tool_draw_segment: no segment to draw\n"); #endif PATH_TOOL_DEBUG +#endif } void path_tool_draw (Tool *tool) { +#if 0 GDisplay * gdisp; - Path * cur_path; + NPath * cur_path; PathTool * path_tool; #ifdef PATH_TOOL_DEBUG @@ -1894,6 +1913,7 @@ path_tool_draw (Tool *tool) /* fprintf (stderr, "path_tool_draw end.\n"); */ #endif PATH_TOOL_DEBUG +#endif } diff --git a/app/tools/path_tool.h b/app/tools/path_tool.h index 158e244599..f5f9910be1 100644 --- a/app/tools/path_tool.h +++ b/app/tools/path_tool.h @@ -1,5 +1,5 @@ /* 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 @@ -20,14 +20,89 @@ #ifndef __PATH_TOOL_H__ #define __PATH_TOOL_H__ -#include "tools.h" +/* + * Every new curve-type has to have a parameter between 0 and 1, and + * should go from a starting to a target point. + */ -/* path functions */ +/* Some defines... */ -Tool * tools_new_path_tool (void); -void tools_free_path_tool (Tool *); +#define PATH_TOOL_WIDTH 8 +#define PATH_TOOL_HALFWIDTH 4 + +/* function prototypes */ -#endif /* __PATH_TOOL_H__ */ +/* 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 *, + gint, + gint); +PathSegment * path_append_segment (NPath *, + PathCurve *, + SegmentType, + gint, + gint); +PathSegment * path_prepend_segment (NPath *, + PathCurve *, + SegmentType, + gint, + gint); +PathSegment * path_split_segment (PathSegment *, + gdouble); +void path_join_curves (PathSegment *, + PathSegment *); +void path_flip_curve (PathCurve *); +void path_free_path (NPath *); +void path_free_curve (PathCurve *); +void path_free_segment (PathSegment *); +void path_delete_segment (PathSegment *); +void path_print (NPath *); +void path_offset_active (NPath *, gdouble, gdouble); +void path_set_flags (GimpPathTool *, + NPath *, + PathCurve *, + PathSegment *, + guint32, + guint32); + +/* High level image-manipulation functions */ + +void path_stroke (GimpPathTool *, + NPath *); +void path_to_selection (GimpPathTool *, + NPath *); +#endif /* __PATH_TOOL_H__ */ + diff --git a/app/tools/path_toolP.h b/app/tools/path_toolP.h index 73cde47273..782326db00 100644 --- a/app/tools/path_toolP.h +++ b/app/tools/path_toolP.h @@ -20,12 +20,12 @@ #undef PATH_TOOL_DEBUG -#include "draw_core.h" - #ifdef PATH_TOOL_DEBUG #include #endif +#include "apptypes.h" + #define IMAGE_COORDS 1 #define AA_IMAGE_COORDS 2 #define SCREEN_COORDS 3 @@ -46,9 +46,7 @@ enum { ON_ANCHOR, ON_HANDLE, ON_CURVE, ON_CANVAS }; typedef struct _path_segment PathSegment; typedef struct _path_curve PathCurve; -typedef struct _path Path; - -typedef struct _path_tool PathTool; +typedef struct _npath NPath; struct _path_segment { @@ -69,22 +67,23 @@ struct _path_curve { PathSegment *segments; /* The segments of the curve */ PathSegment *cur_segment; /* the current segment */ - Path *parent; /* the parent Path */ + NPath *parent; /* the parent Path */ PathCurve *next; /* Next Curve or NULL */ PathCurve *prev; /* Previous Curve or NULL */ }; -struct _path +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? */ - PathTool *path_tool; /* The parent Path Tool */ + /* GimpPathTool *path_tool; */ /* The parent Path Tool */ }; +#if 0 struct _path_tool { gint click_type; /* where did the user click? */ @@ -92,7 +91,7 @@ struct _path_tool gint click_y; /* Y-coordinate of the click */ gint click_halfwidth; guint click_modifier; /* what modifiers were pressed? */ - Path *click_path; /* On which Path/Curve/Segment */ + 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 */ @@ -109,21 +108,23 @@ struct _path_tool gint state; /* state of tool */ gint draw; /* all or part */ DrawCore *core; /* Core drawing object */ - Path *cur_path; /* the current active path */ + NPath *cur_path; /* the current active path */ GSList **scanlines; /* used in converting a path */ }; +#endif + typedef void -(*PathTraverseFunc) (Path *, +(*PathTraverseFunc) (NPath *, PathCurve *, gpointer); typedef void -(*CurveTraverseFunc) (Path *, +(*CurveTraverseFunc) (NPath *, PathCurve *, PathSegment *, gpointer); typedef void -(*SegmentTraverseFunc) (Path *, +(*SegmentTraverseFunc) (NPath *, PathCurve *, PathSegment *, gint, diff --git a/app/tools/tools.c b/app/tools/tools.c index 138f4ca1a0..b7ecc3449c 100644 --- a/app/tools/tools.c +++ b/app/tools/tools.c @@ -46,6 +46,7 @@ #include "gimpmeasuretool.h" #include "gimpmovetool.h" #include "gimppaintbrushtool.h" +#include "gimppathtool.h" #include "gimppenciltool.h" #include "gimpperspectivetool.h" #include "gimprectselecttool.h" @@ -88,6 +89,7 @@ register_tools (void) /* non-modifying tools */ + gimp_path_tool_register (); gimp_measure_tool_register (); gimp_magnify_tool_register (); gimp_color_picker_tool_register ();