Commit 38a67ce2 authored by Sven Neumann's avatar Sven Neumann

a patch to the path tool from Simon Budig

and some cleanup in plug-ins/common/vpropagate.c


--Sven
parent 9b90608c
This diff is collapsed.
......@@ -17,8 +17,13 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <math.h>
#include "path_bezier.h"
#define HANDLE_HALFWIDTH 3
#define HANDLE_WIDTH 6
/*
* This function is to get a set of npoints different coordinates for
* the range from start to end (each in the range from 0 to 1 and
......@@ -41,10 +46,28 @@ path_bezier_get_points (PathTool *path_tool,
void
path_bezier_get_point (PathTool *path_tool,
PathSegment *segment,
gdouble position,
gdouble pos,
gdouble *x,
gdouble *y)
{
PathBezierData *data = (PathBezierData *) segment->data;
if (segment->next) {
*x = (1-pos) * (1-pos) * (1-pos) * segment->x
+ 3 * pos * (1-pos) * (1-pos) * (segment->x + data->x1)
+ 3 * pos * pos * (1-pos) * (segment->next->x + data->x2)
+ pos * pos * pos * (segment->next->x);
*y = (1-pos) * (1-pos) * (1-pos) * segment->y
+ 3 * pos * (1-pos) * (1-pos) * (segment->y + data->y1)
+ 3 * pos * pos * (1-pos) * (segment->next->y + data->y2)
+ pos * pos * pos * (segment->next->y);
}
#ifdef PATH_TOOL_DEBUG
else fprintf (stderr, "FIXME: path_bezier_get_point called with endpoint-segment!!!\n");
#endif
return;
}
......@@ -52,16 +75,52 @@ void
path_bezier_draw_handles (Tool *tool,
PathSegment *segment)
{
return;
PathTool *path_tool = (PathTool *) (tool->private);
PathBezierData *data = (PathBezierData *) segment->data;
GDisplay * gdisp = tool->gdisp_ptr;
gint sx, sy, hx, hy;
if (segment->next) {
if (segment->flags & SEGMENT_ACTIVE) {
gdisplay_transform_coords (gdisp,
(gint) (segment->x), (gint) (segment->y), &sx, &sy, FALSE);
gdisplay_transform_coords (gdisp,
(gint) (segment->x + data->x1),
(gint) (segment->y + data->y1), &hx, &hy, FALSE);
gdk_draw_line (path_tool->core->win,
path_tool->core->gc, hx, hy, sx, sy);
gdk_draw_rectangle (path_tool->core->win, path_tool->core->gc, 0,
hx - HANDLE_HALFWIDTH, hy - HANDLE_HALFWIDTH,
HANDLE_WIDTH, HANDLE_WIDTH);
}
if (segment->next->flags & SEGMENT_ACTIVE) {
gdisplay_transform_coords (gdisp,
(gint) (segment->next->x), (gint) (segment->next->y), &sx, &sy, FALSE);
gdisplay_transform_coords (gdisp,
(gint) (segment->next->x + data->x2),
(gint) (segment->next->y + data->y2), &hx, &hy, FALSE);
gdk_draw_line (path_tool->core->win,
path_tool->core->gc, hx, hy, sx, sy);
gdk_draw_rectangle (path_tool->core->win, path_tool->core->gc, 0,
hx - HANDLE_HALFWIDTH, hy - HANDLE_HALFWIDTH,
HANDLE_WIDTH, HANDLE_WIDTH);
}
}
}
void
path_bezier_draw_segment (Tool *tool,
PathSegment *segment)
{
return;
}
gdouble
path_bezier_on_segment (Tool *tool,
......@@ -77,31 +136,64 @@ path_bezier_on_segment (Tool *tool,
void
path_bezier_drag_segment (PathTool *path_tool,
PathSegment *segment,
gdouble position,
gint x,
gint y)
gdouble pos,
gdouble dx,
gdouble dy)
{
PathBezierData *data = (PathBezierData *) segment->data;
gdouble feel_good;
if (pos <= 0.5)
feel_good = (pow(2 * pos, 3)) / 2;
else
feel_good = (1 - pow((1-pos)*2, 3)) / 2 + 0.5;
data->x1 += (dx / (3*pos*(1-pos)*(1-pos)))*(1-feel_good);
data->y1 += (dy / (3*pos*(1-pos)*(1-pos)))*(1-feel_good);
data->x2 += (dx / (3*pos*pos*(1-pos)))*feel_good;
data->y2 += (dy / (3*pos*pos*(1-pos)))*feel_good;
return;
}
gint
path_bezier_on_handles (PathTool *path_tool,
PathSegment *segment,
gint x,
gint y,
gint halfwidth)
gdouble x,
gdouble y,
gdouble halfwidth)
{
return FALSE;
PathBezierData *data = (PathBezierData *) segment->data;
if (segment->flags & SEGMENT_ACTIVE &&
fabs(segment->x + data->x1 - x) <= halfwidth &&
fabs(segment->y + data->y1 - y) <= halfwidth)
return 1;
if (segment->next && segment->next->flags & SEGMENT_ACTIVE &&
fabs(segment->next->x + data->x2 - x) <= halfwidth &&
fabs(segment->next->y + data->y2 - y) <= halfwidth)
return 2;
return 0;
}
void
path_bezier_drag_handles (PathTool *path_tool,
PathSegment *segment,
gint x,
gint y,
gdouble dx,
gdouble dy,
gint handle_id)
{
return;
PathBezierData *data = (PathBezierData *) segment->data;
if (handle_id == 1) {
data->x1 += dx;
data->y1 += dy;
} else {
data->x2 += dx;
data->y2 += dy;
}
}
......@@ -117,33 +209,66 @@ void
path_bezier_update_segment (PathTool *path_tool,
PathSegment *segment)
{
return;
return;
}
void
path_bezier_flip_segment (PathTool *path_tool,
PathSegment *segment)
path_bezier_flip_segment (PathSegment *segment)
{
return;
PathBezierData *data = (PathBezierData *) segment->data;
gdouble swap;
swap = data->x1;
data->x1 = data->x2;
data->x2 = swap;
swap = data->y1;
data->y1 = data->y2;
data->y2 = swap;
return;
}
void
path_bezier_init_segment (PathTool *path_tool,
PathSegment *segment)
path_bezier_init_segment (PathSegment *segment)
{
return;
PathBezierData *data, *neardata;
data = g_new(PathBezierData, 1);
data->x1 = 0;
data->y1 = 0;
data->x2 = 0;
data->y2 = 0;
if (segment->prev && segment->prev->type == SEGMENT_BEZIER) {
neardata = (PathBezierData *) segment->prev->data;
data->x1 = - neardata->x2;
data->y1 = - neardata->y2;
}
if (segment->next && segment->next->type == SEGMENT_BEZIER) {
neardata = (PathBezierData *) segment->next->data;
data->x2 = - neardata->x1;
data->y2 = - neardata->y1;
}
#ifdef PATH_TOOL_DEBUG
if (segment->data)
fprintf(stderr, "Warning: path_bezier_init_segment called with already initialized segment\n");
#endif
segment->data = data;
return;
}
void
path_bezier_cleanup_segment (PathTool *path_tool,
PathSegment *segment)
path_bezier_cleanup_segment (PathSegment *segment)
{
return;
}
g_free(segment->data);
segment->data = NULL;
return;
}
......@@ -79,21 +79,21 @@ void
path_bezier_drag_segment (PathTool *path_tool,
PathSegment *segment,
gdouble position,
gint x,
gint y);
gdouble dx,
gdouble dy);
gint
path_bezier_on_handles (PathTool *path_tool,
PathSegment *segment,
gint x,
gint y,
gint halfwidth);
gdouble x,
gdouble y,
gdouble halfwidth);
void
path_bezier_drag_handles (PathTool *path_tool,
PathSegment *segment,
gint x,
gint y,
gdouble dx,
gdouble dy,
gint handle_id);
PathSegment *
......@@ -106,16 +106,13 @@ path_bezier_update_segment (PathTool *path_tool,
PathSegment *segment);
void
path_bezier_flip_segment (PathTool *path_tool,
PathSegment *segment);
path_bezier_flip_segment (PathSegment *segment);
void
path_bezier_init_segment (PathTool *path_tool,
PathSegment *segment);
path_bezier_init_segment (PathSegment *segment);
void
path_bezier_cleanup_segment (PathTool *path_tool,
PathSegment *segment);
path_bezier_cleanup_segment (PathSegment *segment);
#endif /* __PATH_BEZIER_H__ */
......
......@@ -21,10 +21,6 @@
#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);
......@@ -39,19 +35,19 @@ static CurveDescription CurveTypes[] =
/* SEGMENT_BEZIER */
{
path_bezier_get_points,
NULL, /* path_bezier_get_points, */
path_bezier_get_point,
path_bezier_draw_handles,
path_bezier_draw_segment,
path_bezier_on_segment,
NULL, /* path_bezier_draw_segment, */
NULL, /* 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_drag_handles,
NULL, /* path_bezier_insert_anchor, */
NULL, /* path_bezier_update_segment, */
path_bezier_flip_segment,
path_bezier_init_segment,
path_bezier_cleanup_segment
NULL /* path_bezier_cleanup_segment */
}
};
......@@ -74,20 +70,27 @@ path_curve_get_points (PathTool *path_tool,
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;
if (segment && segment->next) {
if (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;
}
}
#ifdef PATH_TOOL_DEBUG
else
fprintf (stderr, "path_curve_get_point called without valid curve");
#endif
return 0;
}
......@@ -98,15 +101,16 @@ path_curve_get_point (PathTool *path_tool,
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 (segment && segment->next) {
if (CurveTypes[segment->type].get_point)
(* CurveTypes[segment->type].get_point) (path_tool, segment, position, x, y);
else {
#if 0
*x = segment->x + (segment->next->x - segment->x) * position;
*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 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) +
......@@ -117,11 +121,11 @@ path_curve_get_point (PathTool *path_tool,
position * position * position * (segment->next->y);
#endif
}
}
#ifdef PATH_TOOL_DEBUG
else
fprintf (stderr, "path_curve_get_point called without valid curve");
else
fprintf (stderr, "path_curve_get_point called without valid curve");
#endif
}
return;
}
......@@ -246,20 +250,20 @@ void
path_curve_drag_segment (PathTool *path_tool,
PathSegment *segment,
gdouble position,
gint x,
gint y)
gdouble dx,
gdouble dy)
{
if (segment && CurveTypes[segment->type].drag_segment)
(* CurveTypes[segment->type].drag_segment) (path_tool, segment, position, x, y);
(* CurveTypes[segment->type].drag_segment) (path_tool, segment, position, dx, dy);
return;
}
gint
path_curve_on_handle (PathTool *path_tool,
PathSegment *segment,
gint x,
gint y,
gint halfwidth)
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);
......@@ -269,12 +273,12 @@ path_curve_on_handle (PathTool *path_tool,
void
path_curve_drag_handle (PathTool *path_tool,
PathSegment *segment,
gint x,
gint y,
gdouble dx,
gdouble dy,
gint handle_id)
{
if (segment && CurveTypes[segment->type].drag_handle)
(* CurveTypes[segment->type].drag_handle) (path_tool, segment, x, y, handle_id);
(* CurveTypes[segment->type].drag_handle) (path_tool, segment, dx, dy, handle_id);
}
PathSegment *
......@@ -290,11 +294,10 @@ path_curve_insert_anchor (PathTool *path_tool,
}
void
path_curve_flip_segment (PathTool *path_tool,
PathSegment *segment)
path_curve_flip_segment (PathSegment *segment)
{
if (segment && CurveTypes[segment->type].flip_segment)
(* CurveTypes[segment->type].flip_segment) (path_tool, segment);
(* CurveTypes[segment->type].flip_segment) (segment);
return;
}
......@@ -308,19 +311,18 @@ path_curve_update_segment (PathTool *path_tool,
}
void
path_curve_init_segment (PathTool *path_tool,
PathSegment *segment)
path_curve_init_segment (PathSegment *segment)
{
if (segment && CurveTypes[segment->type].init_segment)
(* CurveTypes[segment->type].init_segment) (path_tool, segment);
(* CurveTypes[segment->type].init_segment) (segment);
return;
}
void
path_curve_cleanup_segment (PathTool *path_tool,
PathSegment *segment)
path_curve_cleanup_segment (PathSegment *segment)
{
if (segment && CurveTypes[segment->type].cleanup_segment)
(* CurveTypes[segment->type].cleanup_segment) (path_tool, segment);
(* CurveTypes[segment->type].cleanup_segment) (segment);
return;
}
......@@ -62,19 +62,19 @@ typedef gdouble (*PathOnSegmentFunc) (Tool *tool,
typedef void (*PathDragSegmentFunc) (PathTool *path_tool,
PathSegment *segment,
gdouble position,
gint x,
gint y);
gdouble dx,
gdouble dy);
typedef gint (*PathOnHandlesFunc) (PathTool *path_tool,
PathSegment *segment,
gint x,
gint y,
gint halfwidth);
gdouble x,
gdouble y,
gdouble halfwidth);
typedef void (*PathDragHandleFunc) (PathTool *path_tool,
PathSegment *segment,
gint x,
gint y,
gdouble dx,
gdouble dy,
gint handle_id);
typedef PathSegment * (*PathInsertAnchorFunc) (PathTool *path_tool,
......@@ -84,14 +84,11 @@ typedef PathSegment * (*PathInsertAnchorFunc) (PathTool *path_tool,
typedef void (*PathUpdateSegmentFunc) (PathTool *path_tool,
PathSegment *segment);
typedef void (*PathFlipSegmentFunc) (PathTool *path_tool,
PathSegment *segment);
typedef void (*PathFlipSegmentFunc) (PathSegment *segment);
typedef void (*PathInitSegmentFunc) (PathTool *path_tool,
PathSegment *segment);
typedef void (*PathInitSegmentFunc) (PathSegment *segment);
typedef void (*PathCleanupSegmentFunc) (PathTool *path_tool,
PathSegment *segment);
typedef void (*PathCleanupSegmentFunc) (PathSegment *segment);
typedef struct {
PathGetPointsFunc get_points;
......@@ -146,21 +143,21 @@ void
path_curve_drag_segment (PathTool *path_tool,
PathSegment *segment,
gdouble position,
gint x,
gint y);
gdouble dx,
gdouble dy);
gint
path_curve_on_handle (PathTool *path_tool,
PathSegment *segment,
gint x,
gint y,
gint halfwidth);
gdouble x,
gdouble y,
gdouble halfwidth);
void
path_curve_drag_handle (PathTool *path_tool,
PathSegment *segment,
gint x,
gint y,
gdouble dx,
gdouble dy,
gint handle_id);
PathSegment *
......@@ -173,16 +170,13 @@ path_curve_update_segment (PathTool *path_tool,
PathSegment *segment);
void
path_curve_flip_segment (PathTool *path_tool,
PathSegment *segment);
path_curve_flip_segment (PathSegment *segment);
void
path_curve_init_segment (PathTool *path_tool,
PathSegment *segment);
path_curve_init_segment (PathSegment *segment);
void
path_curve_cleanup_segment (PathTool *path_tool,
PathSegment *segment);
path_curve_cleanup_segment (PathSegment *segment);
......
......@@ -37,10 +37,6 @@
#include "path_toolP.h"
#include "path_curves.h"
#ifdef PATH_TOOL_DEBUG
#include <stdio.h>
#endif PATH_TOOL_DEBUG
#include "libgimp/gimpintl.h"
/*
......@@ -138,16 +134,20 @@ void path_tool_control (Tool *, ToolAction, gpointer);
void path_tool_draw (Tool *);
void path_tool_draw_curve (Tool *, PathCurve *);
void path_tool_draw_segment (Tool *, PathSegment *);
gboolean path_tool_on_anchors (Tool *, gint, gint, gint,
Path**, PathCurve**, PathSegment**);
gdouble path_tool_on_curve (Tool *, gint, gint, gint,
Path**, PathCurve**, PathSegment**);
gboolean path_tool_on_handles (Tool *, gint, gint, gint);
gboolean path_tool_on_anchors (Tool *, gint, gint, gint,
Path**, PathCurve**, PathSegment**);
gint path_tool_on_handles (Tool *, gint, gint, gint,
Path **, PathCurve **, PathSegment **);
gint path_tool_button_press_canvas (Tool *, GdkEventButton *, GDisplay *);
gint path_tool_button_press_anchor (Tool *, GdkEventButton *, GDisplay *);
gint path_tool_button_press_handle (Tool *, GdkEventButton *, GDisplay *);
gint path_tool_button_press_curve (Tool *, GdkEventButton *, GDisplay *);
void path_tool_motion_anchor (Tool *, GdkEventMotion *, GDisplay *);
void path_tool_motion_handle (Tool *, GdkEventMotion *, GDisplay *);
void path_tool_motion_curve (Tool *, GdkEventMotion *, GDisplay *);
......@@ -280,7 +280,7 @@ path_add_curve (Path * cur_path,
cur_path->curves = cur_path->cur_curve = new_curve;
new_curve->segments = path_prepend_segment (cur_path, new_curve, SEGMENT_LINE, x, y);
new_curve->segments = path_prepend_segment (cur_path, new_curve, SEGMENT_BEZIER, x, y);
}
#ifdef PATH_TOOL_DEBUG
else
......@@ -327,8 +327,8 @@ path_append_segment (Path * cur_path,
tmp->next = new_segment;
cur_curve->cur_segment = new_segment;
/* XXX: we need initialisation of the segment here. */
path_curve_init_segment (new_segment);
}
#ifdef PATH_TOOL_DEBUG
......@@ -379,7 +379,8 @@ path_prepend_segment (Path * cur_path,
cur_curve->segments = new_segment;
cur_curve->cur_segment = new_segment;
/* XXX: we need initialisation of the segment here. */
path_curve_init_segment (new_segment);
}
#ifdef PATH_TOOL_DEBUG
else
......@@ -415,7 +416,7 @@ path_split_segment (PathSegment *segment,
new_segment->prev = segment;
new_segment->data = NULL;
/* XXX: we need initialisation of the segment here. */
path_curve_init_segment (new_segment);
new_segment->next->prev = new_segment;
segment->next = new_segment;
......@@ -565,8 +566,6 @@ path_flip_curve (PathCurve *curve)
PathSegment *tmp, *tmp2;
/* XXX: Please add path_curve_flip_segment here */
if (!curve && !curve->segments) {
#ifdef PATH_TOOL_DEBUG
fprintf (stderr, "path_flip_curve: No curve o no segments to flip!\n");
......@@ -595,8 +594,8 @@ path_flip_curve (PathCurve *curve)
tmp->type = end_type;
tmp->data = end_data;
}
path_curve_flip_segment (tmp);
tmp = tmp->next;
/* XXX: Probably some segment-updates needed */
}
}
......@@ -647,12 +646,15 @@ path_free_segment (PathSegment *segment)
{
if (segment)
{
/* Clear the active flag to keep path_tool->single_active_segment consistent */
/* Clear the active flag to keep path_tool->single_active_segment
* consistent */
path_set_flags (segment->parent->parent->path_tool, segment->parent->parent,
segment->parent, segment, 0, SEGMENT_ACTIVE);
if (segment->data)
g_free(segment->data);
/* XXX: Free Segment needs an own hook in the different curve-types! */
path_curve_cleanup_segment(segment);
g_free (segment);
}
}
......@@ -719,19 +721,28 @@ path_tool_cursor_position (Tool *tool,
Path **pathP,
PathCurve **curveP,
PathSegment **segmentP,
gdouble *positionP)
gdouble *positionP,
gint *handle_idP)
{
gdouble pos;
gint handle_id;
if (path_tool_on_anchors (tool, x, y, halfwidth, pathP, curveP, segmentP))
return ON_ANCHOR;
handle_id = path_tool_on_handles (tool, 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);
if (pos >= 0 && pos <= 1) {
if (positionP) (*positionP) = pos;
return ON_CURVE;
}
return ON_CANVAS;
}
......@@ -778,11 +789,12 @@ path_tool_button_press (Tool *tool,
* switch accordingly.
*/
path_tool->click_type = path_tool_cursor_position(tool, x, y, halfwidth,
&(path_tool->click_path),
&(path_tool->click_curve),
&(path_tool->click_segment),
&(path_tool->click_position));
path_tool->click_type = path_tool_cursor_position (tool, x, y, halfwidth,
&(path_tool->click_path),
&(path_tool->click_curve),
&(path_tool->click_segment),