mirror of https://github.com/GNOME/gimp.git
Changed:-
Mon Apr 5 22:24:30 BST 1999 Andy Thomas <alt@gimp.org> Changed:- * app/bezier_select.c * app/bezier_selectP.h * app/paths_cmds.c * app/pathsP.h * app/paths_dialog.c * app/xcf.c * tools/pdbgen/pdb/paths.pdb New PDB functions. gimp_path_get_point_at_dist (gets the x,y of a point a given distance along the curve & the normal at the point). gimp_path_get_tattoo gimp_get_path_by_tattoo Paths now have tattoos (similar to the layer and image tattoos). * app/move.c * app/scroll.c Try to fix the problem where mouse events from the rulers get mixed up with those from the canvas causing guides & image dragging to "jump" around when the mouse enters the ruler areas.
This commit is contained in:
parent
7f74800d26
commit
67dbf49bf2
28
ChangeLog
28
ChangeLog
|
@ -1,3 +1,31 @@
|
||||||
|
Mon Apr 5 23:24:30 BST 1999 Andy Thomas <alt@gimp.org>
|
||||||
|
|
||||||
|
Changed:-
|
||||||
|
|
||||||
|
* app/bezier_select.c
|
||||||
|
* app/bezier_selectP.h
|
||||||
|
* app/paths_cmds.c
|
||||||
|
* app/pathsP.h
|
||||||
|
* app/paths_dialog.c
|
||||||
|
* app/xcf.c
|
||||||
|
* tools/pdbgen/pdb/paths.pdb
|
||||||
|
|
||||||
|
New PDB functions.
|
||||||
|
gimp_path_get_point_at_dist (gets the x,y of a point a given distance
|
||||||
|
along the curve & the normal at the point).
|
||||||
|
gimp_path_get_tattoo
|
||||||
|
gimp_get_path_by_tattoo
|
||||||
|
|
||||||
|
|
||||||
|
Paths now have tattoos (similar to the layer and image tattoos).
|
||||||
|
|
||||||
|
* app/move.c
|
||||||
|
* app/scroll.c
|
||||||
|
|
||||||
|
Try to fix the problem where mouse events from the rulers get
|
||||||
|
mixed up with those from the canvas causing guides & image dragging
|
||||||
|
to "jump" around when the mouse enters the ruler areas.
|
||||||
|
|
||||||
Mon Apr 5 23:59:37 MEST 1999 Sven Neumann <sven@gimp.org>
|
Mon Apr 5 23:59:37 MEST 1999 Sven Neumann <sven@gimp.org>
|
||||||
|
|
||||||
* app/color_balance.c: Color-balance didn't work when used
|
* app/color_balance.c: Color-balance didn't work when used
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
#include "appenv.h"
|
#include "appenv.h"
|
||||||
#include "draw_core.h"
|
#include "draw_core.h"
|
||||||
#include "edit_selection.h"
|
#include "edit_selection.h"
|
||||||
|
@ -61,6 +62,8 @@
|
||||||
#define NO 0
|
#define NO 0
|
||||||
#define YES 1
|
#define YES 1
|
||||||
|
|
||||||
|
#define ROUND(x) ((int) ((x) + 0.5))
|
||||||
|
|
||||||
/* bezier select type definitions */
|
/* bezier select type definitions */
|
||||||
|
|
||||||
typedef double BezierMatrix[4][4];
|
typedef double BezierMatrix[4][4];
|
||||||
|
@ -84,6 +87,24 @@ struct _named_buffer
|
||||||
char * name;
|
char * name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
gdouble *stroke_points;
|
||||||
|
gint num_stroke_points; /* num of valid points */
|
||||||
|
gint len_stroke_points; /* allocated length */
|
||||||
|
} BezierRenderPnts;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
gboolean firstpnt;
|
||||||
|
gdouble curdist;
|
||||||
|
gdouble dist;
|
||||||
|
gdouble *gradient;
|
||||||
|
gint *x;
|
||||||
|
gint *y;
|
||||||
|
gdouble lastx;
|
||||||
|
gdouble lasty;
|
||||||
|
gboolean found;
|
||||||
|
} BezierDistance;
|
||||||
|
|
||||||
static void bezier_select_button_press (Tool *, GdkEventButton *, gpointer);
|
static void bezier_select_button_press (Tool *, GdkEventButton *, gpointer);
|
||||||
static void bezier_select_button_release (Tool *, GdkEventButton *, gpointer);
|
static void bezier_select_button_release (Tool *, GdkEventButton *, gpointer);
|
||||||
static void bezier_select_motion (Tool *, GdkEventMotion *, gpointer);
|
static void bezier_select_motion (Tool *, GdkEventMotion *, gpointer);
|
||||||
|
@ -96,20 +117,20 @@ static void bezier_draw_handles (BezierSelect *);
|
||||||
static void bezier_draw_current (BezierSelect *);
|
static void bezier_draw_current (BezierSelect *);
|
||||||
static void bezier_draw_point (BezierSelect *, BezierPoint *, int);
|
static void bezier_draw_point (BezierSelect *, BezierPoint *, int);
|
||||||
static void bezier_draw_line (BezierSelect *, BezierPoint *, BezierPoint *);
|
static void bezier_draw_line (BezierSelect *, BezierPoint *, BezierPoint *);
|
||||||
static void bezier_draw_segment (BezierSelect *, BezierPoint *, int, int, BezierPointsFunc);
|
static void bezier_draw_segment (BezierSelect *, BezierPoint *, int, int, BezierPointsFunc,gpointer);
|
||||||
static void bezier_draw_segment_points (BezierSelect *, GdkPoint *, int);
|
static void bezier_draw_segment_points (BezierSelect *, GdkPoint *, int, gpointer);
|
||||||
static void bezier_compose (BezierMatrix, BezierMatrix, BezierMatrix);
|
static void bezier_compose (BezierMatrix, BezierMatrix, BezierMatrix);
|
||||||
|
|
||||||
static void bezier_convert (BezierSelect *, GDisplay *, int, int);
|
static void bezier_convert (BezierSelect *, GDisplay *, int, int);
|
||||||
static void bezier_convert_points (BezierSelect *, GdkPoint *, int);
|
static void bezier_convert_points (BezierSelect *, GdkPoint *, int, gpointer);
|
||||||
static void bezier_convert_line (GSList **, int, int, int, int);
|
static void bezier_convert_line (GSList **, int, int, int, int);
|
||||||
static GSList * bezier_insert_in_list (GSList *, int);
|
static GSList * bezier_insert_in_list (GSList *, int);
|
||||||
|
|
||||||
static int test_add_point_on_segment (BezierSelect *, BezierPoint *, int, int, int, int, int);
|
static int test_add_point_on_segment (BezierSelect *, BezierPoint *, int, int, int, int, int);
|
||||||
static void bezier_to_sel_internal (BezierSelect *, Tool *, GDisplay *, gint, gint);
|
static void bezier_to_sel_internal (BezierSelect *, Tool *, GDisplay *, gint, gint);
|
||||||
static void bezier_stack_points (BezierSelect *, GdkPoint *, int);
|
static void bezier_stack_points (BezierSelect *, GdkPoint *, int, gpointer);
|
||||||
static gboolean stroke_interpolatable (int, int, int, int, gdouble);
|
static gboolean stroke_interpolatable (int, int, int, int, gdouble);
|
||||||
static void bezier_stack_points_aux (GdkPoint *, int, int, gdouble);
|
static void bezier_stack_points_aux (GdkPoint *, int, int, gdouble, BezierRenderPnts *);
|
||||||
|
|
||||||
static BezierMatrix basis =
|
static BezierMatrix basis =
|
||||||
{
|
{
|
||||||
|
@ -233,7 +254,10 @@ bezier_select_load (void *gdisp_ptr,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
bezier_draw_curve (BezierSelect *bezier_sel,BezierPointsFunc func, gint coord)
|
bezier_draw_curve (BezierSelect *bezier_sel,
|
||||||
|
BezierPointsFunc func,
|
||||||
|
gint coord,
|
||||||
|
gpointer udata)
|
||||||
{
|
{
|
||||||
BezierPoint * points;
|
BezierPoint * points;
|
||||||
BezierPoint * start_pt;
|
BezierPoint * start_pt;
|
||||||
|
@ -248,7 +272,8 @@ bezier_draw_curve (BezierSelect *bezier_sel,BezierPointsFunc func, gint coord)
|
||||||
do {
|
do {
|
||||||
bezier_draw_segment (bezier_sel, points,
|
bezier_draw_segment (bezier_sel, points,
|
||||||
SUBDIVIDE, coord,
|
SUBDIVIDE, coord,
|
||||||
func);
|
func,
|
||||||
|
udata);
|
||||||
|
|
||||||
points = points->next;
|
points = points->next;
|
||||||
points = points->next;
|
points = points->next;
|
||||||
|
@ -263,7 +288,8 @@ bezier_draw_curve (BezierSelect *bezier_sel,BezierPointsFunc func, gint coord)
|
||||||
{
|
{
|
||||||
bezier_draw_segment (bezier_sel, points,
|
bezier_draw_segment (bezier_sel, points,
|
||||||
SUBDIVIDE, coord,
|
SUBDIVIDE, coord,
|
||||||
func);
|
func,
|
||||||
|
udata);
|
||||||
|
|
||||||
points = points->next;
|
points = points->next;
|
||||||
points = points->next;
|
points = points->next;
|
||||||
|
@ -447,7 +473,7 @@ bezier_add_point_on_segment(int x,
|
||||||
if (test_add_point_on_segment (bezier_sel,
|
if (test_add_point_on_segment (bezier_sel,
|
||||||
points,
|
points,
|
||||||
SUBDIVIDE,
|
SUBDIVIDE,
|
||||||
SCREEN_COORDS,
|
IMAGE_COORDS,
|
||||||
x, y,
|
x, y,
|
||||||
halfwidth))
|
halfwidth))
|
||||||
{
|
{
|
||||||
|
@ -953,7 +979,7 @@ bezier_select_draw (Tool *tool)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (draw_curve)
|
if (draw_curve)
|
||||||
bezier_draw_curve (bezier_sel,bezier_draw_segment_points,SCREEN_COORDS);
|
bezier_draw_curve (bezier_sel,bezier_draw_segment_points,SCREEN_COORDS,NULL);
|
||||||
if (draw_handles)
|
if (draw_handles)
|
||||||
bezier_draw_handles (bezier_sel);
|
bezier_draw_handles (bezier_sel);
|
||||||
if (draw_current)
|
if (draw_current)
|
||||||
|
@ -1082,7 +1108,8 @@ bezier_draw_current (BezierSelect *bezier_sel)
|
||||||
if (points)
|
if (points)
|
||||||
bezier_draw_segment (bezier_sel, points,
|
bezier_draw_segment (bezier_sel, points,
|
||||||
SUBDIVIDE, SCREEN_COORDS,
|
SUBDIVIDE, SCREEN_COORDS,
|
||||||
bezier_draw_segment_points);
|
bezier_draw_segment_points,
|
||||||
|
NULL);
|
||||||
|
|
||||||
if (points != bezier_sel->cur_anchor)
|
if (points != bezier_sel->cur_anchor)
|
||||||
{
|
{
|
||||||
|
@ -1095,7 +1122,8 @@ bezier_draw_current (BezierSelect *bezier_sel)
|
||||||
if (points)
|
if (points)
|
||||||
bezier_draw_segment (bezier_sel, bezier_sel->cur_anchor,
|
bezier_draw_segment (bezier_sel, bezier_sel->cur_anchor,
|
||||||
SUBDIVIDE, SCREEN_COORDS,
|
SUBDIVIDE, SCREEN_COORDS,
|
||||||
bezier_draw_segment_points);
|
bezier_draw_segment_points,
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1158,7 +1186,8 @@ bezier_draw_segment (BezierSelect *bezier_sel,
|
||||||
BezierPoint *points,
|
BezierPoint *points,
|
||||||
int subdivisions,
|
int subdivisions,
|
||||||
int space,
|
int space,
|
||||||
BezierPointsFunc points_func)
|
BezierPointsFunc points_func,
|
||||||
|
gpointer udata)
|
||||||
{
|
{
|
||||||
#define ROUND(x) ((int) ((x) + 0.5))
|
#define ROUND(x) ((int) ((x) + 0.5))
|
||||||
|
|
||||||
|
@ -1275,7 +1304,7 @@ bezier_draw_segment (BezierSelect *bezier_sel,
|
||||||
/* if the point buffer is full put it to the screen and zero it out */
|
/* if the point buffer is full put it to the screen and zero it out */
|
||||||
if (index >= npoints)
|
if (index >= npoints)
|
||||||
{
|
{
|
||||||
(* points_func) (bezier_sel, gdk_points, index);
|
(* points_func) (bezier_sel, gdk_points, index, udata);
|
||||||
index = 0;
|
index = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1286,13 +1315,14 @@ bezier_draw_segment (BezierSelect *bezier_sel,
|
||||||
|
|
||||||
/* if there are points in the buffer, then put them on the screen */
|
/* if there are points in the buffer, then put them on the screen */
|
||||||
if (index)
|
if (index)
|
||||||
(* points_func) (bezier_sel, gdk_points, index);
|
(* points_func) (bezier_sel, gdk_points, index, udata);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bezier_draw_segment_points (BezierSelect *bezier_sel,
|
bezier_draw_segment_points (BezierSelect *bezier_sel,
|
||||||
GdkPoint *points,
|
GdkPoint *points,
|
||||||
int npoints)
|
int npoints,
|
||||||
|
gpointer udata)
|
||||||
{
|
{
|
||||||
gdk_draw_points (bezier_sel->core->win,
|
gdk_draw_points (bezier_sel->core->win,
|
||||||
bezier_sel->core->gc, points, npoints);
|
bezier_sel->core->gc, points, npoints);
|
||||||
|
@ -1388,7 +1418,8 @@ bezier_convert (BezierSelect *bezier_sel,
|
||||||
do {
|
do {
|
||||||
bezier_draw_segment (bezier_sel, points,
|
bezier_draw_segment (bezier_sel, points,
|
||||||
subdivisions, draw_type,
|
subdivisions, draw_type,
|
||||||
bezier_convert_points);
|
bezier_convert_points,
|
||||||
|
NULL);
|
||||||
|
|
||||||
/* advance to the next segment */
|
/* advance to the next segment */
|
||||||
points = points->next;
|
points = points->next;
|
||||||
|
@ -1478,7 +1509,8 @@ bezier_convert (BezierSelect *bezier_sel,
|
||||||
static void
|
static void
|
||||||
bezier_convert_points (BezierSelect *bezier_sel,
|
bezier_convert_points (BezierSelect *bezier_sel,
|
||||||
GdkPoint *points,
|
GdkPoint *points,
|
||||||
int npoints)
|
int npoints,
|
||||||
|
gpointer udata)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -1765,8 +1797,6 @@ test_add_point_on_segment (BezierSelect *bezier_sel,
|
||||||
int halfwidth)
|
int halfwidth)
|
||||||
|
|
||||||
{
|
{
|
||||||
#define ROUND(x) ((int) ((x) + 0.5))
|
|
||||||
|
|
||||||
BezierPoint *points;
|
BezierPoint *points;
|
||||||
BezierMatrix geometry;
|
BezierMatrix geometry;
|
||||||
BezierMatrix tmp1, tmp2;
|
BezierMatrix tmp1, tmp2;
|
||||||
|
@ -2042,10 +2072,6 @@ void printSel( BezierSelect *sel)
|
||||||
printf("state: %d\n", sel->state);
|
printf("state: %d\n", sel->state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gdouble *stroke_points = NULL;
|
|
||||||
static gint num_stroke_points = 0; /* num of valid points */
|
|
||||||
static gint len_stroke_points = 0; /* allocated length */
|
|
||||||
|
|
||||||
/* check whether vectors (offx, offy), (l_offx, l_offy) have the same angle. */
|
/* check whether vectors (offx, offy), (l_offx, l_offy) have the same angle. */
|
||||||
static gboolean
|
static gboolean
|
||||||
stroke_interpolatable (int offx, int offy, int l_offx, int l_offy, gdouble error)
|
stroke_interpolatable (int offx, int offy, int l_offx, int l_offy, gdouble error)
|
||||||
|
@ -2088,35 +2114,36 @@ static void
|
||||||
bezier_stack_points_aux (GdkPoint *points,
|
bezier_stack_points_aux (GdkPoint *points,
|
||||||
int start,
|
int start,
|
||||||
int end,
|
int end,
|
||||||
gdouble error)
|
gdouble error,
|
||||||
|
BezierRenderPnts *rpnts)
|
||||||
{
|
{
|
||||||
const gint expand_size = 32;
|
const gint expand_size = 32;
|
||||||
gint med;
|
gint med;
|
||||||
gint offx, offy, l_offx, l_offy;
|
gint offx, offy, l_offx, l_offy;
|
||||||
|
|
||||||
if (stroke_points == NULL)
|
if (rpnts->stroke_points == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* BASE CASE: stack the end point */
|
/* BASE CASE: stack the end point */
|
||||||
if (end - start <= 1)
|
if (end - start <= 1)
|
||||||
{
|
{
|
||||||
if ((stroke_points[num_stroke_points * 2 - 2] == points[end].x)
|
if ((rpnts->stroke_points[rpnts->num_stroke_points * 2 - 2] == points[end].x)
|
||||||
&& (stroke_points[num_stroke_points * 2 - 1] == points[end].y))
|
&& (rpnts->stroke_points[rpnts->num_stroke_points * 2 - 1] == points[end].y))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
num_stroke_points++;
|
rpnts->num_stroke_points++;
|
||||||
if (len_stroke_points <= num_stroke_points)
|
if (rpnts->len_stroke_points <= rpnts->num_stroke_points)
|
||||||
{
|
{
|
||||||
len_stroke_points += expand_size;
|
rpnts->len_stroke_points += expand_size;
|
||||||
stroke_points = g_renew (double, stroke_points, 2 * len_stroke_points);
|
rpnts->stroke_points = g_renew (double, rpnts->stroke_points, 2 * rpnts->len_stroke_points);
|
||||||
if (stroke_points == NULL)
|
if (rpnts->stroke_points == NULL)
|
||||||
{
|
{
|
||||||
len_stroke_points = num_stroke_points = 0;
|
rpnts->len_stroke_points = rpnts->num_stroke_points = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stroke_points[num_stroke_points * 2 - 2] = points[end].x;
|
rpnts->stroke_points[rpnts->num_stroke_points * 2 - 2] = points[end].x;
|
||||||
stroke_points[num_stroke_points * 2 - 1] = points[end].y;
|
rpnts->stroke_points[rpnts->num_stroke_points * 2 - 1] = points[end].y;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2125,7 +2152,7 @@ bezier_stack_points_aux (GdkPoint *points,
|
||||||
gint i;
|
gint i;
|
||||||
|
|
||||||
for (i = start+ 1; i <= end; i++)
|
for (i = start+ 1; i <= end; i++)
|
||||||
bezier_stack_points_aux (points, i, i, 0);
|
bezier_stack_points_aux (points, i, i, 0,rpnts);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* Otherwise, check whether to divide the segment recursively */
|
/* Otherwise, check whether to divide the segment recursively */
|
||||||
|
@ -2138,8 +2165,8 @@ bezier_stack_points_aux (GdkPoint *points,
|
||||||
|
|
||||||
if (! stroke_interpolatable (offx, offy, l_offx, l_offy, error))
|
if (! stroke_interpolatable (offx, offy, l_offx, l_offy, error))
|
||||||
{
|
{
|
||||||
bezier_stack_points_aux (points, start, med, error);
|
bezier_stack_points_aux (points, start, med, error, rpnts);
|
||||||
bezier_stack_points_aux (points, med, end, error);
|
bezier_stack_points_aux (points, med, end, error, rpnts);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2148,33 +2175,35 @@ bezier_stack_points_aux (GdkPoint *points,
|
||||||
|
|
||||||
if (! stroke_interpolatable (offx, offy, l_offx, l_offy, error))
|
if (! stroke_interpolatable (offx, offy, l_offx, l_offy, error))
|
||||||
{
|
{
|
||||||
bezier_stack_points_aux (points, start, med, error);
|
bezier_stack_points_aux (points, start, med, error, rpnts);
|
||||||
bezier_stack_points_aux (points, med, end, error);
|
bezier_stack_points_aux (points, med, end, error, rpnts);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* Now, the curve can be represented by a points pair: (start, end).
|
/* Now, the curve can be represented by a points pair: (start, end).
|
||||||
So, add the last point to stroke_points. */
|
So, add the last point to stroke_points. */
|
||||||
bezier_stack_points_aux (points, end, end, 0);
|
bezier_stack_points_aux (points, end, end, 0, rpnts);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bezier_stack_points (BezierSelect *bezier_sel,
|
bezier_stack_points (BezierSelect *bezier_sel,
|
||||||
GdkPoint *points,
|
GdkPoint *points,
|
||||||
int npoints)
|
int npoints,
|
||||||
|
gpointer udata)
|
||||||
{
|
{
|
||||||
gint i;
|
gint i;
|
||||||
gint expand_size = 32;
|
gint expand_size = 32;
|
||||||
gint minx, maxx, miny, maxy;
|
gint minx, maxx, miny, maxy;
|
||||||
gdouble error;
|
gdouble error;
|
||||||
|
BezierRenderPnts *rpnts = udata;
|
||||||
|
|
||||||
if (npoints < 2) /* Does this happen? */
|
if (npoints < 2) /* Does this happen? */
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (stroke_points == NULL) /* initialize it here */
|
if (rpnts->stroke_points == NULL) /* initialize it here */
|
||||||
{
|
{
|
||||||
num_stroke_points = 0;
|
rpnts->num_stroke_points = 0;
|
||||||
len_stroke_points = expand_size;
|
rpnts->len_stroke_points = expand_size;
|
||||||
stroke_points = g_new (double, 2 * len_stroke_points);
|
rpnts->stroke_points = g_new (double, 2 * rpnts->len_stroke_points);
|
||||||
}
|
}
|
||||||
|
|
||||||
maxx = minx = points[0].x;
|
maxx = minx = points[0].x;
|
||||||
|
@ -2194,24 +2223,21 @@ bezier_stack_points (BezierSelect *bezier_sel,
|
||||||
error = 2.0 / MAX(maxx - minx, maxy - miny);
|
error = 2.0 / MAX(maxx - minx, maxy - miny);
|
||||||
|
|
||||||
/* add the start point */
|
/* add the start point */
|
||||||
bezier_stack_points_aux (points, 0, 0, 0);
|
bezier_stack_points_aux (points, 0, 0, 0, rpnts);
|
||||||
|
|
||||||
/* divide segments recursively */
|
/* divide segments recursively */
|
||||||
bezier_stack_points_aux (points, 0, npoints - 1, error);
|
bezier_stack_points_aux (points, 0, npoints - 1, error, rpnts);
|
||||||
|
|
||||||
/* printf ("npoints: %d\n", npoints); */
|
/* printf ("npoints: %d\n", npoints); */
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static gint
|
||||||
bezier_stroke (BezierSelect *bezier_sel,
|
bezier_gen_points(BezierSelect *bezier_sel,
|
||||||
GDisplay *gdisp,
|
int open_path,
|
||||||
int subdivisions,
|
BezierRenderPnts *rpnts)
|
||||||
int open_path)
|
|
||||||
{
|
{
|
||||||
BezierPoint * points;
|
BezierPoint * points;
|
||||||
int num_points;
|
int num_points;
|
||||||
Argument *return_vals;
|
|
||||||
int nreturn_vals;
|
|
||||||
int redraw = FALSE;
|
int redraw = FALSE;
|
||||||
|
|
||||||
/* stack points */
|
/* stack points */
|
||||||
|
@ -2227,7 +2253,8 @@ bezier_stroke (BezierSelect *bezier_sel,
|
||||||
do {
|
do {
|
||||||
bezier_draw_segment (bezier_sel, points,
|
bezier_draw_segment (bezier_sel, points,
|
||||||
SUBDIVIDE, IMAGE_COORDS,
|
SUBDIVIDE, IMAGE_COORDS,
|
||||||
bezier_stack_points);
|
bezier_stack_points,
|
||||||
|
(gpointer)rpnts);
|
||||||
|
|
||||||
points = points->next;
|
points = points->next;
|
||||||
points = points->next;
|
points = points->next;
|
||||||
|
@ -2245,7 +2272,8 @@ bezier_stroke (BezierSelect *bezier_sel,
|
||||||
{
|
{
|
||||||
bezier_draw_segment (bezier_sel, points,
|
bezier_draw_segment (bezier_sel, points,
|
||||||
SUBDIVIDE, IMAGE_COORDS,
|
SUBDIVIDE, IMAGE_COORDS,
|
||||||
bezier_stack_points);
|
bezier_stack_points,
|
||||||
|
(gpointer)rpnts);
|
||||||
|
|
||||||
points = points->next;
|
points = points->next;
|
||||||
points = points->next;
|
points = points->next;
|
||||||
|
@ -2254,7 +2282,23 @@ bezier_stroke (BezierSelect *bezier_sel,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stroke_points)
|
return (redraw);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
bezier_stroke (BezierSelect *bezier_sel,
|
||||||
|
GDisplay *gdisp,
|
||||||
|
int subdivisions,
|
||||||
|
int open_path)
|
||||||
|
{
|
||||||
|
Argument *return_vals;
|
||||||
|
int nreturn_vals;
|
||||||
|
int redraw;
|
||||||
|
BezierRenderPnts *rpnts = g_new0(BezierRenderPnts,1);
|
||||||
|
|
||||||
|
redraw = bezier_gen_points(bezier_sel,open_path,rpnts);
|
||||||
|
|
||||||
|
if (rpnts->stroke_points)
|
||||||
{
|
{
|
||||||
GimpDrawable *drawable;
|
GimpDrawable *drawable;
|
||||||
int offset_x, offset_y;
|
int offset_x, offset_y;
|
||||||
|
@ -2266,8 +2310,8 @@ bezier_stroke (BezierSelect *bezier_sel,
|
||||||
{
|
{
|
||||||
gdouble *ptr;
|
gdouble *ptr;
|
||||||
|
|
||||||
ptr = stroke_points;
|
ptr = rpnts->stroke_points;
|
||||||
while (ptr < stroke_points + (num_stroke_points * 2))
|
while (ptr < rpnts->stroke_points + (rpnts->num_stroke_points * 2))
|
||||||
{
|
{
|
||||||
*ptr++ -= offset_x;
|
*ptr++ -= offset_x;
|
||||||
*ptr++ -= offset_y;
|
*ptr++ -= offset_y;
|
||||||
|
@ -2278,8 +2322,8 @@ bezier_stroke (BezierSelect *bezier_sel,
|
||||||
&nreturn_vals,
|
&nreturn_vals,
|
||||||
PDB_DRAWABLE, drawable_ID (drawable),
|
PDB_DRAWABLE, drawable_ID (drawable),
|
||||||
PDB_FLOAT, (gdouble) 0,
|
PDB_FLOAT, (gdouble) 0,
|
||||||
PDB_INT32, (gint32) num_stroke_points * 2,
|
PDB_INT32, (gint32) rpnts->num_stroke_points * 2,
|
||||||
PDB_FLOATARRAY, stroke_points,
|
PDB_FLOATARRAY, rpnts->stroke_points,
|
||||||
PDB_END);
|
PDB_END);
|
||||||
|
|
||||||
if (return_vals[0].value.pdb_int == PDB_SUCCESS)
|
if (return_vals[0].value.pdb_int == PDB_SUCCESS)
|
||||||
|
@ -2295,10 +2339,206 @@ bezier_stroke (BezierSelect *bezier_sel,
|
||||||
|
|
||||||
procedural_db_destroy_args (return_vals, nreturn_vals);
|
procedural_db_destroy_args (return_vals, nreturn_vals);
|
||||||
|
|
||||||
g_free (stroke_points);
|
g_free (rpnts->stroke_points);
|
||||||
}
|
}
|
||||||
/* printf ("num_stroke_points: %d\ndone.\n", num_stroke_points); */
|
/* printf ("num_stroke_points: %d\ndone.\n", num_stroke_points); */
|
||||||
|
|
||||||
stroke_points = NULL;
|
rpnts->stroke_points = NULL;
|
||||||
len_stroke_points = num_stroke_points = 0;
|
rpnts->len_stroke_points = rpnts->num_stroke_points = 0;
|
||||||
|
|
||||||
|
g_free(rpnts);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
bezier_draw_segment_for_distance (BezierSelect *bezier_sel,
|
||||||
|
BezierPoint *points,
|
||||||
|
int subdivisions,
|
||||||
|
BezierDistance *bdist)
|
||||||
|
{
|
||||||
|
BezierMatrix geometry;
|
||||||
|
BezierMatrix tmp1, tmp2;
|
||||||
|
BezierMatrix deltas;
|
||||||
|
double x, dx, dx2, dx3;
|
||||||
|
double y, dy, dy2, dy3;
|
||||||
|
double d, d2, d3;
|
||||||
|
int index;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* construct the geometry matrix from the segment */
|
||||||
|
/* assumes that a valid segment containing 4 points is passed in */
|
||||||
|
|
||||||
|
if(bdist->found)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
if (!points)
|
||||||
|
fatal_error (_("bad bezier segment"));
|
||||||
|
|
||||||
|
geometry[i][0] = points->x;
|
||||||
|
geometry[i][1] = points->y;
|
||||||
|
geometry[i][2] = 0;
|
||||||
|
geometry[i][3] = 0;
|
||||||
|
|
||||||
|
points = points->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* subdivide the curve n times */
|
||||||
|
/* n can be adjusted to give a finer or coarser curve */
|
||||||
|
|
||||||
|
d = 1.0 / subdivisions;
|
||||||
|
d2 = d * d;
|
||||||
|
d3 = d * d * d;
|
||||||
|
|
||||||
|
/* construct a temporary matrix for determining the forward diffencing deltas */
|
||||||
|
|
||||||
|
tmp2[0][0] = 0; tmp2[0][1] = 0; tmp2[0][2] = 0; tmp2[0][3] = 1;
|
||||||
|
tmp2[1][0] = d3; tmp2[1][1] = d2; tmp2[1][2] = d; tmp2[1][3] = 0;
|
||||||
|
tmp2[2][0] = 6*d3; tmp2[2][1] = 2*d2; tmp2[2][2] = 0; tmp2[2][3] = 0;
|
||||||
|
tmp2[3][0] = 6*d3; tmp2[3][1] = 0; tmp2[3][2] = 0; tmp2[3][3] = 0;
|
||||||
|
|
||||||
|
/* compose the basis and geometry matrices */
|
||||||
|
bezier_compose (basis, geometry, tmp1);
|
||||||
|
|
||||||
|
/* compose the above results to get the deltas matrix */
|
||||||
|
bezier_compose (tmp2, tmp1, deltas);
|
||||||
|
|
||||||
|
/* extract the x deltas */
|
||||||
|
x = deltas[0][0];
|
||||||
|
dx = deltas[1][0];
|
||||||
|
dx2 = deltas[2][0];
|
||||||
|
dx3 = deltas[3][0];
|
||||||
|
|
||||||
|
/* extract the y deltas */
|
||||||
|
y = deltas[0][1];
|
||||||
|
dy = deltas[1][1];
|
||||||
|
dy2 = deltas[2][1];
|
||||||
|
dy3 = deltas[3][1];
|
||||||
|
|
||||||
|
index = 1;
|
||||||
|
|
||||||
|
/* loop over the curve */
|
||||||
|
for (i = 0; i < subdivisions; i++)
|
||||||
|
{
|
||||||
|
/* increment the x values */
|
||||||
|
x += dx;
|
||||||
|
dx += dx2;
|
||||||
|
dx2 += dx3;
|
||||||
|
|
||||||
|
/* increment the y values */
|
||||||
|
y += dy;
|
||||||
|
dy += dy2;
|
||||||
|
dy2 += dy3;
|
||||||
|
|
||||||
|
/* printf("x = %g, y = %g\n",x,y); */
|
||||||
|
|
||||||
|
/* if this point is different than the last one...then draw it */
|
||||||
|
/* Note :
|
||||||
|
* It assumes the udata is the place we want the
|
||||||
|
* floating version of the coords to be stuffed.
|
||||||
|
* These are needed when we calculate the gradient of the
|
||||||
|
* curve.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if(!bdist->firstpnt)
|
||||||
|
{
|
||||||
|
gdouble rx = x;
|
||||||
|
gdouble ry = y;
|
||||||
|
gdouble dx = bdist->lastx - rx;
|
||||||
|
gdouble dy = bdist->lasty - ry;
|
||||||
|
|
||||||
|
bdist->curdist += sqrt((dx*dx)+(dy*dy));
|
||||||
|
if(bdist->curdist >= bdist->dist)
|
||||||
|
{
|
||||||
|
*(bdist->x) = (gint)ROUND((rx + dx/2));
|
||||||
|
*(bdist->y) = (gint)ROUND((ry + dy/2));
|
||||||
|
if(dx == 0.0)
|
||||||
|
*(bdist->gradient) = G_MAXDOUBLE;
|
||||||
|
else
|
||||||
|
*(bdist->gradient) = dy/dx;
|
||||||
|
|
||||||
|
/* printf("found x = %d, y = %d\n",*(bdist->x),*(bdist->y)); */
|
||||||
|
bdist->found = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
bdist->lastx = rx;
|
||||||
|
bdist->lasty = ry;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bdist->firstpnt = FALSE;
|
||||||
|
bdist->lastx = x;
|
||||||
|
bdist->lasty = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
bezier_draw_curve_for_distance (BezierSelect *bezier_sel,
|
||||||
|
BezierDistance *udata)
|
||||||
|
{
|
||||||
|
BezierPoint * points;
|
||||||
|
BezierPoint * start_pt;
|
||||||
|
int num_points;
|
||||||
|
|
||||||
|
points = bezier_sel->points;
|
||||||
|
|
||||||
|
if (bezier_sel->closed)
|
||||||
|
{
|
||||||
|
start_pt = bezier_sel->points;
|
||||||
|
|
||||||
|
do {
|
||||||
|
bezier_draw_segment_for_distance (bezier_sel, points,
|
||||||
|
SUBDIVIDE,
|
||||||
|
udata);
|
||||||
|
|
||||||
|
points = points->next;
|
||||||
|
points = points->next;
|
||||||
|
points = points->next;
|
||||||
|
} while (points != start_pt);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
num_points = bezier_sel->num_points;
|
||||||
|
|
||||||
|
while (num_points >= 4)
|
||||||
|
{
|
||||||
|
bezier_draw_segment_for_distance (bezier_sel, points,
|
||||||
|
SUBDIVIDE,
|
||||||
|
udata);
|
||||||
|
points = points->next;
|
||||||
|
points = points->next;
|
||||||
|
points = points->next;
|
||||||
|
num_points -= 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gint
|
||||||
|
bezier_distance_along(BezierSelect *bezier_sel,
|
||||||
|
int open_path,
|
||||||
|
gdouble dist,
|
||||||
|
gint *x,
|
||||||
|
gint *y,
|
||||||
|
gdouble *gradient)
|
||||||
|
{
|
||||||
|
/* Render the curve as points then walk along it... */
|
||||||
|
BezierDistance *bdist = g_new0(BezierDistance,1);
|
||||||
|
gint ret;
|
||||||
|
|
||||||
|
bdist->firstpnt = TRUE;
|
||||||
|
bdist->curdist = 0.0;
|
||||||
|
bdist->lastx = 0.0;
|
||||||
|
bdist->lasty = 0.0;
|
||||||
|
bdist->dist = dist;
|
||||||
|
bdist->x = x;
|
||||||
|
bdist->y = y;
|
||||||
|
bdist->gradient = gradient;
|
||||||
|
bdist->found = FALSE;
|
||||||
|
|
||||||
|
bezier_draw_curve_for_distance (bezier_sel,bdist);
|
||||||
|
ret = bdist->found;
|
||||||
|
|
||||||
|
g_free(bdist);
|
||||||
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,17 +63,17 @@ struct _bezier_select
|
||||||
GSList **scanlines; /* used in converting a curve */
|
GSList **scanlines; /* used in converting a curve */
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef void (*BezierPointsFunc) (BezierSelect *, GdkPoint *, int);
|
typedef void (*BezierPointsFunc) (BezierSelect *, GdkPoint *, int,gpointer);
|
||||||
|
|
||||||
/* Functions */
|
/* Functions */
|
||||||
int bezier_select_load (void *, BezierPoint *, int, int);
|
int bezier_select_load (void *, BezierPoint *, int, int);
|
||||||
void bezier_draw_curve (BezierSelect *,BezierPointsFunc, int);
|
void bezier_draw_curve (BezierSelect *,BezierPointsFunc, int,gpointer);
|
||||||
void bezier_select_reset (BezierSelect *);
|
void bezier_select_reset (BezierSelect *);
|
||||||
void bezier_add_point (BezierSelect *, int, int, int);
|
void bezier_add_point (BezierSelect *, int, int, int);
|
||||||
void bezier_paste_bezierselect_to_current (GDisplay *,BezierSelect *);
|
void bezier_paste_bezierselect_to_current (GDisplay *,BezierSelect *);
|
||||||
void bezier_select_mode (gint);
|
void bezier_select_mode (gint);
|
||||||
void bezier_stroke (BezierSelect *, GDisplay *, int, int);
|
void bezier_stroke (BezierSelect *, GDisplay *, int, int);
|
||||||
void bezier_to_selection (BezierSelect *, GDisplay *);
|
void bezier_to_selection (BezierSelect *, GDisplay *);
|
||||||
|
gint bezier_distance_along (BezierSelect *, gint, gdouble,gint *,gint *,gdouble *);
|
||||||
|
|
||||||
#endif /* __BEZIER_SELECTP_H__ */
|
#endif /* __BEZIER_SELECTP_H__ */
|
||||||
|
|
|
@ -85,6 +85,11 @@ void
|
||||||
grab_and_scroll (GDisplay *gdisp,
|
grab_and_scroll (GDisplay *gdisp,
|
||||||
GdkEventMotion *mevent)
|
GdkEventMotion *mevent)
|
||||||
{
|
{
|
||||||
|
if(mevent && mevent->window != gdisp->canvas->window)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
scroll_display (gdisp, (startx - mevent->x - gdisp->offset_x),
|
scroll_display (gdisp, (startx - mevent->x - gdisp->offset_x),
|
||||||
(starty - mevent->y - gdisp->offset_y));
|
(starty - mevent->y - gdisp->offset_y));
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,6 +85,11 @@ void
|
||||||
grab_and_scroll (GDisplay *gdisp,
|
grab_and_scroll (GDisplay *gdisp,
|
||||||
GdkEventMotion *mevent)
|
GdkEventMotion *mevent)
|
||||||
{
|
{
|
||||||
|
if(mevent && mevent->window != gdisp->canvas->window)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
scroll_display (gdisp, (startx - mevent->x - gdisp->offset_x),
|
scroll_display (gdisp, (startx - mevent->x - gdisp->offset_x),
|
||||||
(starty - mevent->y - gdisp->offset_y));
|
(starty - mevent->y - gdisp->offset_y));
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,6 +102,8 @@ typedef struct {
|
||||||
PATHP bzp;
|
PATHP bzp;
|
||||||
} PATHWIDGET, *PATHWIDGETP;
|
} PATHWIDGET, *PATHWIDGETP;
|
||||||
|
|
||||||
|
static gchar * unique_name(gchar *);
|
||||||
|
|
||||||
static gint path_widget_preview_events (GtkWidget *, GdkEvent *);
|
static gint path_widget_preview_events (GtkWidget *, GdkEvent *);
|
||||||
static void paths_dialog_realized (GtkWidget *widget);
|
static void paths_dialog_realized (GtkWidget *widget);
|
||||||
static void paths_select_row (GtkWidget *widget,gint row,gint column,GdkEventButton *event,gpointer data);
|
static void paths_select_row (GtkWidget *widget,gint row,gint column,GdkEventButton *event,gpointer data);
|
||||||
|
@ -386,17 +388,22 @@ path_free(gpointer data,gpointer user_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
static PATHP
|
static PATHP
|
||||||
bzpath_dialog_new(gint name_seed, gpointer udata)
|
path_dialog_new(GimpImage *gimage,gint name_seed, gpointer udata)
|
||||||
{
|
{
|
||||||
PATHP bzp = g_new0(PATH,1);
|
PATHP bzp;
|
||||||
|
|
||||||
GString *s = g_string_new (NULL);
|
GString *s = g_string_new (NULL);
|
||||||
|
gchar *suniq;
|
||||||
|
|
||||||
g_string_sprintf (s, "path %d",name_seed);
|
g_string_sprintf (s, "path %d",name_seed);
|
||||||
|
suniq = unique_name(s->str);
|
||||||
bzp->pathtype = BEZIER;
|
if(suniq)
|
||||||
bzp->name = s;
|
{
|
||||||
bzp->path_details = (GSList *)udata; /* If called via button/menu this will be NULL */
|
g_string_free(s,TRUE);
|
||||||
|
s = g_string_new(suniq);
|
||||||
|
g_free(suniq);
|
||||||
|
}
|
||||||
|
bzp = path_new(gimage,BEZIER,(GSList *)udata,0,0,0,0,s->str);
|
||||||
|
g_string_free(s,TRUE);
|
||||||
return bzp;
|
return bzp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -493,7 +500,7 @@ unique_name(gchar *cstr)
|
||||||
}
|
}
|
||||||
|
|
||||||
static PATHP
|
static PATHP
|
||||||
path_copy(PATHP p)
|
path_copy(GimpImage *gimage,PATHP p)
|
||||||
{
|
{
|
||||||
PATHP p_copy = g_new0(PATH,1);
|
PATHP p_copy = g_new0(PATH,1);
|
||||||
gchar *ext;
|
gchar *ext;
|
||||||
|
@ -505,7 +512,7 @@ path_copy(PATHP p)
|
||||||
p_copy->state = p->state;
|
p_copy->state = p->state;
|
||||||
p_copy->pathtype = p->pathtype;
|
p_copy->pathtype = p->pathtype;
|
||||||
p_copy->path_details = pathpoints_copy(p->path_details);
|
p_copy->path_details = pathpoints_copy(p->path_details);
|
||||||
|
p_copy->tattoo = gimp_image_get_new_tattoo(gimage);
|
||||||
return p_copy;
|
return p_copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1148,7 +1155,7 @@ static PATHP
|
||||||
paths_dialog_new_path(PATHIMAGELISTP *plp,gpointer points,GimpImage *gimage,gint pos)
|
paths_dialog_new_path(PATHIMAGELISTP *plp,gpointer points,GimpImage *gimage,gint pos)
|
||||||
{
|
{
|
||||||
static gint nseed = 0;
|
static gint nseed = 0;
|
||||||
PATHP bzp = bzpath_dialog_new(nseed++,points);
|
PATHP bzp = path_dialog_new(gimage,nseed++,points);
|
||||||
*plp = path_add_to_current(*plp,bzp,gimage,pos);
|
*plp = path_add_to_current(*plp,bzp,gimage,pos);
|
||||||
return(bzp);
|
return(bzp);
|
||||||
}
|
}
|
||||||
|
@ -1239,7 +1246,7 @@ paths_dialog_dup_path_callback (GtkWidget * widget, gpointer udata)
|
||||||
bzp = (PATHP)g_slist_nth_data(plp->bz_paths,row);
|
bzp = (PATHP)g_slist_nth_data(plp->bz_paths,row);
|
||||||
|
|
||||||
/* Insert at the current position */
|
/* Insert at the current position */
|
||||||
bzp = path_copy(bzp);
|
bzp = path_copy(paths_dialog->gimage,bzp);
|
||||||
plp->bz_paths = g_slist_insert(plp->bz_paths,bzp,row);
|
plp->bz_paths = g_slist_insert(plp->bz_paths,bzp,row);
|
||||||
paths_add_path(bzp,row);
|
paths_add_path(bzp,row);
|
||||||
|
|
||||||
|
@ -1277,7 +1284,7 @@ paths_dialog_path_to_sel_callback (GtkWidget * widget, gpointer udata)
|
||||||
|
|
||||||
if(!bzp->closed)
|
if(!bzp->closed)
|
||||||
{
|
{
|
||||||
PATHP bzpcopy = path_copy(bzp);
|
PATHP bzpcopy = path_copy(paths_dialog->gimage,bzp);
|
||||||
/* Close it */
|
/* Close it */
|
||||||
path_close(bzpcopy);
|
path_close(bzpcopy);
|
||||||
bezier_sel = path_to_beziersel(bzpcopy);
|
bezier_sel = path_to_beziersel(bzpcopy);
|
||||||
|
@ -1450,7 +1457,8 @@ paths_replaced_current(PATHIMAGELISTP plp,BezierSelect *bezier_sel)
|
||||||
static void
|
static void
|
||||||
paths_draw_segment_points(BezierSelect *bezier_sel,
|
paths_draw_segment_points(BezierSelect *bezier_sel,
|
||||||
GdkPoint *pnt,
|
GdkPoint *pnt,
|
||||||
int npoints)
|
int npoints,
|
||||||
|
gpointer udata)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* hopefully the image points are already in image space co-ords.
|
* hopefully the image points are already in image space co-ords.
|
||||||
|
@ -1520,7 +1528,7 @@ paths_update_preview(BezierSelect *bezier_sel)
|
||||||
clear_pixmap_preview(pwidget);
|
clear_pixmap_preview(pwidget);
|
||||||
|
|
||||||
/* update .. */
|
/* update .. */
|
||||||
bezier_draw_curve (bezier_sel,paths_draw_segment_points,IMAGE_COORDS);
|
bezier_draw_curve (bezier_sel,paths_draw_segment_points,IMAGE_COORDS,NULL);
|
||||||
|
|
||||||
/* update the pixmap */
|
/* update the pixmap */
|
||||||
|
|
||||||
|
@ -1661,11 +1669,13 @@ pathpoint_new(gint type,
|
||||||
}
|
}
|
||||||
|
|
||||||
PATHP
|
PATHP
|
||||||
path_new(PathType ptype,
|
path_new(GimpImage *gimage,
|
||||||
|
PathType ptype,
|
||||||
GSList *path_details,
|
GSList *path_details,
|
||||||
gint closed,
|
gint closed,
|
||||||
gint state,
|
gint state,
|
||||||
gint locked,
|
gint locked,
|
||||||
|
gint tattoo,
|
||||||
gchar *name)
|
gchar *name)
|
||||||
{
|
{
|
||||||
PATHP path = g_new0(PATH,1);
|
PATHP path = g_new0(PATH,1);
|
||||||
|
@ -1676,6 +1686,10 @@ path_new(PathType ptype,
|
||||||
path->locked = locked;
|
path->locked = locked;
|
||||||
path->name = g_string_new(name);
|
path->name = g_string_new(name);
|
||||||
path->pathtype = ptype;
|
path->pathtype = ptype;
|
||||||
|
if(tattoo)
|
||||||
|
path->tattoo = tattoo;
|
||||||
|
else
|
||||||
|
path->tattoo = gimp_image_get_new_tattoo(gimage);
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
@ -1789,11 +1803,13 @@ static void file_ok_callback(GtkWidget * widget, gpointer client_data)
|
||||||
pts_list = g_slist_append(pts_list,bpt);
|
pts_list = g_slist_append(pts_list,bpt);
|
||||||
}
|
}
|
||||||
|
|
||||||
bzpath = path_new(BEZIER,
|
bzpath = path_new(paths_dialog->gimage,
|
||||||
|
BEZIER,
|
||||||
pts_list,
|
pts_list,
|
||||||
closed,
|
closed,
|
||||||
state,
|
state,
|
||||||
0, /* Can't be locked */
|
0, /* Can't be locked */
|
||||||
|
0, /* No tattoo assigned */
|
||||||
txt);
|
txt);
|
||||||
|
|
||||||
g_free(txtstart);
|
g_free(txtstart);
|
||||||
|
@ -2027,11 +2043,13 @@ paths_set_path_points(GimpImage * gimage,
|
||||||
{
|
{
|
||||||
GSList *bzp_list = NULL;
|
GSList *bzp_list = NULL;
|
||||||
/* No paths at all.... create one & rename */
|
/* No paths at all.... create one & rename */
|
||||||
bzpath = path_new(ptype,
|
bzpath = path_new(gimage,
|
||||||
|
ptype,
|
||||||
pts_list,
|
pts_list,
|
||||||
pclosed,
|
pclosed,
|
||||||
(pclosed)?BEZIER_EDIT:BEZIER_ADD,/*state,*/
|
(pclosed)?BEZIER_EDIT:BEZIER_ADD,/*state,*/
|
||||||
0, /* Can't be locked */
|
0, /* Can't be locked */
|
||||||
|
0, /* No tattoo assigned */
|
||||||
pname);
|
pname);
|
||||||
bzp_list = g_slist_append(bzp_list,bzpath);
|
bzp_list = g_slist_append(bzp_list,bzpath);
|
||||||
plist = pathsList_new(gimage,0,bzp_list);
|
plist = pathsList_new(gimage,0,bzp_list);
|
||||||
|
@ -2075,11 +2093,13 @@ paths_set_path_points(GimpImage * gimage,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bzpath = path_new(ptype,
|
bzpath = path_new(gimage,
|
||||||
|
ptype,
|
||||||
pts_list,
|
pts_list,
|
||||||
pclosed,
|
pclosed,
|
||||||
(pclosed)?BEZIER_EDIT:BEZIER_ADD,/*state,*/
|
(pclosed)?BEZIER_EDIT:BEZIER_ADD,/*state,*/
|
||||||
0, /* Can't be locked */
|
0, /* Can't be locked */
|
||||||
|
0, /* No tattoo assigned */
|
||||||
pname);
|
pname);
|
||||||
|
|
||||||
path_add_to_current(plist,bzpath,gimage,-1);
|
path_add_to_current(plist,bzpath,gimage,-1);
|
||||||
|
@ -2123,3 +2143,55 @@ paths_stroke(GimpImage *gimage,PathsList *pl,PATHP bzp)
|
||||||
bezier_stroke (bezier_sel, gdisp, SUBDIVIDE, !bzp->closed);
|
bezier_stroke (bezier_sel, gdisp, SUBDIVIDE, !bzp->closed);
|
||||||
beziersel_free(bezier_sel);
|
beziersel_free(bezier_sel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gint
|
||||||
|
paths_distance(PATHP bzp,gdouble dist,gint *x,gint *y, gdouble *grad)
|
||||||
|
{
|
||||||
|
gint ret;
|
||||||
|
BezierSelect * bezier_sel;
|
||||||
|
bezier_sel = path_to_beziersel(bzp);
|
||||||
|
ret = bezier_distance_along(bezier_sel,!bzp->closed,dist,x,y,grad);
|
||||||
|
beziersel_free(bezier_sel);
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
Tattoo
|
||||||
|
paths_get_tattoo(PATHP p)
|
||||||
|
{
|
||||||
|
if(!p)
|
||||||
|
{
|
||||||
|
g_warning(_("paths_get_tattoo: invalid path"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (p->tattoo);
|
||||||
|
}
|
||||||
|
|
||||||
|
PATHP
|
||||||
|
paths_get_path_by_tattoo(GimpImage *gimage,Tattoo tattoo)
|
||||||
|
{
|
||||||
|
GSList *tlist;
|
||||||
|
PATHIMAGELISTP plp;
|
||||||
|
|
||||||
|
if(!gimage || !tattoo)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Go around the list and check all tattoos. */
|
||||||
|
|
||||||
|
/* Get path structure */
|
||||||
|
plp = (PATHIMAGELISTP)gimp_image_get_paths(gimage);
|
||||||
|
|
||||||
|
if(!plp)
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
|
tlist = plp->bz_paths;
|
||||||
|
|
||||||
|
while(tlist)
|
||||||
|
{
|
||||||
|
PATHP p = (PATHP)(tlist->data);
|
||||||
|
if(p->tattoo == tattoo)
|
||||||
|
return (p);
|
||||||
|
tlist = g_slist_next(tlist);
|
||||||
|
}
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
|
@ -263,6 +263,12 @@ move_tool_motion (Tool *tool,
|
||||||
{
|
{
|
||||||
move_draw_guide (gdisp, private->guide);
|
move_draw_guide (gdisp, private->guide);
|
||||||
|
|
||||||
|
if(mevent && mevent->window != gdisp->canvas->window)
|
||||||
|
{
|
||||||
|
private->guide->position = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (mevent)
|
if (mevent)
|
||||||
{
|
{
|
||||||
gdisplay_untransform_coords (gdisp, mevent->x, mevent->y,
|
gdisplay_untransform_coords (gdisp, mevent->x, mevent->y,
|
||||||
|
|
|
@ -34,6 +34,7 @@ typedef struct {
|
||||||
gboolean closed;
|
gboolean closed;
|
||||||
guint32 state;
|
guint32 state;
|
||||||
guint32 locked; /* Only bottom bit used */
|
guint32 locked; /* Only bottom bit used */
|
||||||
|
Tattoo tattoo; /* The tattoo for the path */
|
||||||
GString * name;
|
GString * name;
|
||||||
} PATH, *PATHP;
|
} PATH, *PATHP;
|
||||||
|
|
||||||
|
@ -58,11 +59,14 @@ typedef enum {
|
||||||
} PathType;
|
} PathType;
|
||||||
|
|
||||||
PATHPOINTP pathpoint_new(gint,gdouble,gdouble);
|
PATHPOINTP pathpoint_new(gint,gdouble,gdouble);
|
||||||
PATHP path_new(PathType,GSList *,gint,gint,gint,gchar *);
|
PATHP path_new(GimpImage *,PathType,GSList *,gint,gint,gint,gint,gchar *);
|
||||||
PathsList * pathsList_new(GimpImage *,gint,GSList *);
|
PathsList * pathsList_new(GimpImage *,gint,GSList *);
|
||||||
gboolean paths_set_path(GimpImage *,gchar *);
|
gboolean paths_set_path(GimpImage *,gchar *);
|
||||||
gboolean paths_set_path_points(GimpImage *,gchar *,gint,gint,gint,gdouble *);
|
gboolean paths_set_path_points(GimpImage *,gchar *,gint,gint,gint,gdouble *);
|
||||||
void paths_stroke(GimpImage *,PathsList *,PATHP);
|
void paths_stroke(GimpImage *,PathsList *,PATHP);
|
||||||
|
gint paths_distance(PATHP ,gdouble ,gint *,gint *, gdouble *);
|
||||||
|
Tattoo paths_get_tattoo(PATHP);
|
||||||
|
PATHP paths_get_path_by_tattoo(GimpImage *,Tattoo);
|
||||||
|
|
||||||
|
|
||||||
#endif /* __PATHSP_H__ */
|
#endif /* __PATHSP_H__ */
|
||||||
|
|
281
app/paths_cmds.c
281
app/paths_cmds.c
|
@ -29,6 +29,9 @@ static ProcRecord path_get_current_proc;
|
||||||
static ProcRecord path_set_current_proc;
|
static ProcRecord path_set_current_proc;
|
||||||
static ProcRecord path_set_points_proc;
|
static ProcRecord path_set_points_proc;
|
||||||
static ProcRecord path_stroke_current_proc;
|
static ProcRecord path_stroke_current_proc;
|
||||||
|
static ProcRecord path_get_point_at_dist_proc;
|
||||||
|
static ProcRecord path_get_tattoo_proc;
|
||||||
|
static ProcRecord get_path_by_tattoo_proc;
|
||||||
|
|
||||||
void
|
void
|
||||||
register_paths_procs (void)
|
register_paths_procs (void)
|
||||||
|
@ -39,6 +42,9 @@ register_paths_procs (void)
|
||||||
procedural_db_register (&path_set_current_proc);
|
procedural_db_register (&path_set_current_proc);
|
||||||
procedural_db_register (&path_set_points_proc);
|
procedural_db_register (&path_set_points_proc);
|
||||||
procedural_db_register (&path_stroke_current_proc);
|
procedural_db_register (&path_stroke_current_proc);
|
||||||
|
procedural_db_register (&path_get_point_at_dist_proc);
|
||||||
|
procedural_db_register (&path_get_tattoo_proc);
|
||||||
|
procedural_db_register (&get_path_by_tattoo_proc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Argument *
|
static Argument *
|
||||||
|
@ -525,3 +531,278 @@ static ProcRecord path_stroke_current_proc =
|
||||||
NULL,
|
NULL,
|
||||||
{ { path_stroke_current_invoker } }
|
{ { path_stroke_current_invoker } }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static Argument *
|
||||||
|
path_get_point_at_dist_invoker (Argument *args)
|
||||||
|
{
|
||||||
|
gboolean success = TRUE;
|
||||||
|
Argument *return_args;
|
||||||
|
GimpImage *gimage;
|
||||||
|
gdouble distance;
|
||||||
|
gint32 x_point = 0;
|
||||||
|
gint32 y_point = 0;
|
||||||
|
gdouble gradient = 0;
|
||||||
|
|
||||||
|
gimage = pdb_id_to_image (args[0].value.pdb_int);
|
||||||
|
if (gimage == NULL)
|
||||||
|
success = FALSE;
|
||||||
|
|
||||||
|
distance = args[1].value.pdb_float;
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
/* Get the path with the given name */
|
||||||
|
PathsList *plist = gimage->paths;
|
||||||
|
|
||||||
|
if(plist && plist->bz_paths)
|
||||||
|
{
|
||||||
|
PATHP pptr = NULL;
|
||||||
|
|
||||||
|
if(plist->last_selected_row >= 0)
|
||||||
|
{
|
||||||
|
pptr = (PATHP)g_slist_nth_data(plist->bz_paths,plist->last_selected_row);
|
||||||
|
success = paths_distance(pptr,distance,&x_point,&y_point,&gradient);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
success = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
success = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return_args = procedural_db_return_args (&path_get_point_at_dist_proc, success);
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
return_args[1].value.pdb_int = x_point;
|
||||||
|
return_args[2].value.pdb_int = y_point;
|
||||||
|
return_args[3].value.pdb_float = gradient;
|
||||||
|
}
|
||||||
|
|
||||||
|
return return_args;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ProcArg path_get_point_at_dist_inargs[] =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
PDB_IMAGE,
|
||||||
|
"image",
|
||||||
|
"The ID of the image the paths belongs to"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PDB_FLOAT,
|
||||||
|
"distance",
|
||||||
|
"The distance along the path"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static ProcArg path_get_point_at_dist_outargs[] =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
PDB_INT32,
|
||||||
|
"x_point",
|
||||||
|
"The x position of the point"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PDB_INT32,
|
||||||
|
"y_point",
|
||||||
|
"The y position of the point"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PDB_FLOAT,
|
||||||
|
"gradient",
|
||||||
|
"The gradient at the specified point"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static ProcRecord path_get_point_at_dist_proc =
|
||||||
|
{
|
||||||
|
"gimp_path_get_point_at_dist",
|
||||||
|
"Get point on a path at a specified distance along the path",
|
||||||
|
"This will return the x,y position of a point at a given distance along the bezier curve. The distance will the obtained by first digitizing the curve internally an then walking along the curve. For a closed curve the start of the path is the first point on the path that was created. This might not be obvious. Note the current path is used.",
|
||||||
|
"Andy Thomas",
|
||||||
|
"Andy Thomas",
|
||||||
|
"1999",
|
||||||
|
PDB_INTERNAL,
|
||||||
|
2,
|
||||||
|
path_get_point_at_dist_inargs,
|
||||||
|
3,
|
||||||
|
path_get_point_at_dist_outargs,
|
||||||
|
{ { path_get_point_at_dist_invoker } }
|
||||||
|
};
|
||||||
|
|
||||||
|
static Argument *
|
||||||
|
path_get_tattoo_invoker (Argument *args)
|
||||||
|
{
|
||||||
|
gboolean success = TRUE;
|
||||||
|
Argument *return_args;
|
||||||
|
GimpImage *gimage;
|
||||||
|
gchar *pname;
|
||||||
|
gint32 tattoo = 0;
|
||||||
|
PathsList *plist;
|
||||||
|
|
||||||
|
gimage = pdb_id_to_image (args[0].value.pdb_int);
|
||||||
|
if (gimage == NULL)
|
||||||
|
success = FALSE;
|
||||||
|
|
||||||
|
pname = (gchar *) args[1].value.pdb_pointer;
|
||||||
|
if (pname == NULL)
|
||||||
|
success = FALSE;
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
PATHP pptr = NULL;
|
||||||
|
/* Get the path with the given name */
|
||||||
|
plist = gimage->paths;
|
||||||
|
|
||||||
|
if (plist && plist->bz_paths)
|
||||||
|
{
|
||||||
|
GSList *pl = plist->bz_paths;
|
||||||
|
|
||||||
|
while (pl)
|
||||||
|
{
|
||||||
|
pptr = pl->data;
|
||||||
|
|
||||||
|
if (strcmp (pname, pptr->name->str) == 0)
|
||||||
|
break; /* Found the path */
|
||||||
|
|
||||||
|
pl = pl->next;
|
||||||
|
pptr = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pl && pptr)
|
||||||
|
{
|
||||||
|
tattoo = paths_get_tattoo(pptr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
success = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return_args = procedural_db_return_args (&path_get_tattoo_proc, success);
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
return_args[1].value.pdb_int = tattoo;
|
||||||
|
|
||||||
|
return return_args;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ProcArg path_get_tattoo_inargs[] =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
PDB_IMAGE,
|
||||||
|
"image",
|
||||||
|
"The ID of the image"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PDB_STRING,
|
||||||
|
"pathname",
|
||||||
|
"the name of the path whose tattoo should be obtained"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static ProcArg path_get_tattoo_outargs[] =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
PDB_INT32,
|
||||||
|
"tattoo",
|
||||||
|
"The tattoo associated with the name path"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static ProcRecord path_get_tattoo_proc =
|
||||||
|
{
|
||||||
|
"gimp_path_get_tattoo",
|
||||||
|
"Returns the tattoo associated with the name path",
|
||||||
|
"This procedure returns the tattoo associated with the specified path. A tattoo is a unique and permenant identifier attached to a path that can be used to uniquely identify a path within an image even between sessions.",
|
||||||
|
"Andy Thomas",
|
||||||
|
"Andy Thomas",
|
||||||
|
"1999",
|
||||||
|
PDB_INTERNAL,
|
||||||
|
2,
|
||||||
|
path_get_tattoo_inargs,
|
||||||
|
1,
|
||||||
|
path_get_tattoo_outargs,
|
||||||
|
{ { path_get_tattoo_invoker } }
|
||||||
|
};
|
||||||
|
|
||||||
|
static Argument *
|
||||||
|
get_path_by_tattoo_invoker (Argument *args)
|
||||||
|
{
|
||||||
|
gboolean success = TRUE;
|
||||||
|
Argument *return_args;
|
||||||
|
GimpImage *gimage;
|
||||||
|
gint32 tattoo;
|
||||||
|
PathsList *plist;
|
||||||
|
PATHP pptr = NULL;
|
||||||
|
|
||||||
|
gimage = pdb_id_to_image (args[0].value.pdb_int);
|
||||||
|
if (gimage == NULL)
|
||||||
|
success = FALSE;
|
||||||
|
|
||||||
|
tattoo = args[1].value.pdb_int;
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
/* Get the path with the given name */
|
||||||
|
plist = gimage->paths;
|
||||||
|
|
||||||
|
if (plist && plist->bz_paths)
|
||||||
|
{
|
||||||
|
if((pptr = paths_get_path_by_tattoo(gimage,tattoo)) == NULL)
|
||||||
|
success = FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
success = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return_args = procedural_db_return_args (&get_path_by_tattoo_proc, success);
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
return_args[1].value.pdb_pointer = g_strdup (pptr->name->str);
|
||||||
|
|
||||||
|
return return_args;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ProcArg get_path_by_tattoo_inargs[] =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
PDB_IMAGE,
|
||||||
|
"image",
|
||||||
|
"The ID of the image"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PDB_INT32,
|
||||||
|
"tattoo",
|
||||||
|
"The tattoo of the required path"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static ProcArg get_path_by_tattoo_outargs[] =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
PDB_STRING,
|
||||||
|
"path_name",
|
||||||
|
"The name of the path with the specified tattoo"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static ProcRecord get_path_by_tattoo_proc =
|
||||||
|
{
|
||||||
|
"gimp_get_path_by_tattoo",
|
||||||
|
"Return the name of the path with the given tattoo",
|
||||||
|
"The procedure returns the name of the path in the specified image which has the passed tattoo. The tattoos are unique within the image and will be preserved across sessions and through renaming of the path. An error is returned if no path woth the specified tattoo can be found.",
|
||||||
|
"Andy Thomas",
|
||||||
|
"Andy Thomas",
|
||||||
|
"1999",
|
||||||
|
PDB_INTERNAL,
|
||||||
|
2,
|
||||||
|
get_path_by_tattoo_inargs,
|
||||||
|
1,
|
||||||
|
get_path_by_tattoo_outargs,
|
||||||
|
{ { get_path_by_tattoo_invoker } }
|
||||||
|
};
|
||||||
|
|
|
@ -102,6 +102,8 @@ typedef struct {
|
||||||
PATHP bzp;
|
PATHP bzp;
|
||||||
} PATHWIDGET, *PATHWIDGETP;
|
} PATHWIDGET, *PATHWIDGETP;
|
||||||
|
|
||||||
|
static gchar * unique_name(gchar *);
|
||||||
|
|
||||||
static gint path_widget_preview_events (GtkWidget *, GdkEvent *);
|
static gint path_widget_preview_events (GtkWidget *, GdkEvent *);
|
||||||
static void paths_dialog_realized (GtkWidget *widget);
|
static void paths_dialog_realized (GtkWidget *widget);
|
||||||
static void paths_select_row (GtkWidget *widget,gint row,gint column,GdkEventButton *event,gpointer data);
|
static void paths_select_row (GtkWidget *widget,gint row,gint column,GdkEventButton *event,gpointer data);
|
||||||
|
@ -386,17 +388,22 @@ path_free(gpointer data,gpointer user_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
static PATHP
|
static PATHP
|
||||||
bzpath_dialog_new(gint name_seed, gpointer udata)
|
path_dialog_new(GimpImage *gimage,gint name_seed, gpointer udata)
|
||||||
{
|
{
|
||||||
PATHP bzp = g_new0(PATH,1);
|
PATHP bzp;
|
||||||
|
|
||||||
GString *s = g_string_new (NULL);
|
GString *s = g_string_new (NULL);
|
||||||
|
gchar *suniq;
|
||||||
|
|
||||||
g_string_sprintf (s, "path %d",name_seed);
|
g_string_sprintf (s, "path %d",name_seed);
|
||||||
|
suniq = unique_name(s->str);
|
||||||
bzp->pathtype = BEZIER;
|
if(suniq)
|
||||||
bzp->name = s;
|
{
|
||||||
bzp->path_details = (GSList *)udata; /* If called via button/menu this will be NULL */
|
g_string_free(s,TRUE);
|
||||||
|
s = g_string_new(suniq);
|
||||||
|
g_free(suniq);
|
||||||
|
}
|
||||||
|
bzp = path_new(gimage,BEZIER,(GSList *)udata,0,0,0,0,s->str);
|
||||||
|
g_string_free(s,TRUE);
|
||||||
return bzp;
|
return bzp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -493,7 +500,7 @@ unique_name(gchar *cstr)
|
||||||
}
|
}
|
||||||
|
|
||||||
static PATHP
|
static PATHP
|
||||||
path_copy(PATHP p)
|
path_copy(GimpImage *gimage,PATHP p)
|
||||||
{
|
{
|
||||||
PATHP p_copy = g_new0(PATH,1);
|
PATHP p_copy = g_new0(PATH,1);
|
||||||
gchar *ext;
|
gchar *ext;
|
||||||
|
@ -505,7 +512,7 @@ path_copy(PATHP p)
|
||||||
p_copy->state = p->state;
|
p_copy->state = p->state;
|
||||||
p_copy->pathtype = p->pathtype;
|
p_copy->pathtype = p->pathtype;
|
||||||
p_copy->path_details = pathpoints_copy(p->path_details);
|
p_copy->path_details = pathpoints_copy(p->path_details);
|
||||||
|
p_copy->tattoo = gimp_image_get_new_tattoo(gimage);
|
||||||
return p_copy;
|
return p_copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1148,7 +1155,7 @@ static PATHP
|
||||||
paths_dialog_new_path(PATHIMAGELISTP *plp,gpointer points,GimpImage *gimage,gint pos)
|
paths_dialog_new_path(PATHIMAGELISTP *plp,gpointer points,GimpImage *gimage,gint pos)
|
||||||
{
|
{
|
||||||
static gint nseed = 0;
|
static gint nseed = 0;
|
||||||
PATHP bzp = bzpath_dialog_new(nseed++,points);
|
PATHP bzp = path_dialog_new(gimage,nseed++,points);
|
||||||
*plp = path_add_to_current(*plp,bzp,gimage,pos);
|
*plp = path_add_to_current(*plp,bzp,gimage,pos);
|
||||||
return(bzp);
|
return(bzp);
|
||||||
}
|
}
|
||||||
|
@ -1239,7 +1246,7 @@ paths_dialog_dup_path_callback (GtkWidget * widget, gpointer udata)
|
||||||
bzp = (PATHP)g_slist_nth_data(plp->bz_paths,row);
|
bzp = (PATHP)g_slist_nth_data(plp->bz_paths,row);
|
||||||
|
|
||||||
/* Insert at the current position */
|
/* Insert at the current position */
|
||||||
bzp = path_copy(bzp);
|
bzp = path_copy(paths_dialog->gimage,bzp);
|
||||||
plp->bz_paths = g_slist_insert(plp->bz_paths,bzp,row);
|
plp->bz_paths = g_slist_insert(plp->bz_paths,bzp,row);
|
||||||
paths_add_path(bzp,row);
|
paths_add_path(bzp,row);
|
||||||
|
|
||||||
|
@ -1277,7 +1284,7 @@ paths_dialog_path_to_sel_callback (GtkWidget * widget, gpointer udata)
|
||||||
|
|
||||||
if(!bzp->closed)
|
if(!bzp->closed)
|
||||||
{
|
{
|
||||||
PATHP bzpcopy = path_copy(bzp);
|
PATHP bzpcopy = path_copy(paths_dialog->gimage,bzp);
|
||||||
/* Close it */
|
/* Close it */
|
||||||
path_close(bzpcopy);
|
path_close(bzpcopy);
|
||||||
bezier_sel = path_to_beziersel(bzpcopy);
|
bezier_sel = path_to_beziersel(bzpcopy);
|
||||||
|
@ -1450,7 +1457,8 @@ paths_replaced_current(PATHIMAGELISTP plp,BezierSelect *bezier_sel)
|
||||||
static void
|
static void
|
||||||
paths_draw_segment_points(BezierSelect *bezier_sel,
|
paths_draw_segment_points(BezierSelect *bezier_sel,
|
||||||
GdkPoint *pnt,
|
GdkPoint *pnt,
|
||||||
int npoints)
|
int npoints,
|
||||||
|
gpointer udata)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* hopefully the image points are already in image space co-ords.
|
* hopefully the image points are already in image space co-ords.
|
||||||
|
@ -1520,7 +1528,7 @@ paths_update_preview(BezierSelect *bezier_sel)
|
||||||
clear_pixmap_preview(pwidget);
|
clear_pixmap_preview(pwidget);
|
||||||
|
|
||||||
/* update .. */
|
/* update .. */
|
||||||
bezier_draw_curve (bezier_sel,paths_draw_segment_points,IMAGE_COORDS);
|
bezier_draw_curve (bezier_sel,paths_draw_segment_points,IMAGE_COORDS,NULL);
|
||||||
|
|
||||||
/* update the pixmap */
|
/* update the pixmap */
|
||||||
|
|
||||||
|
@ -1661,11 +1669,13 @@ pathpoint_new(gint type,
|
||||||
}
|
}
|
||||||
|
|
||||||
PATHP
|
PATHP
|
||||||
path_new(PathType ptype,
|
path_new(GimpImage *gimage,
|
||||||
|
PathType ptype,
|
||||||
GSList *path_details,
|
GSList *path_details,
|
||||||
gint closed,
|
gint closed,
|
||||||
gint state,
|
gint state,
|
||||||
gint locked,
|
gint locked,
|
||||||
|
gint tattoo,
|
||||||
gchar *name)
|
gchar *name)
|
||||||
{
|
{
|
||||||
PATHP path = g_new0(PATH,1);
|
PATHP path = g_new0(PATH,1);
|
||||||
|
@ -1676,6 +1686,10 @@ path_new(PathType ptype,
|
||||||
path->locked = locked;
|
path->locked = locked;
|
||||||
path->name = g_string_new(name);
|
path->name = g_string_new(name);
|
||||||
path->pathtype = ptype;
|
path->pathtype = ptype;
|
||||||
|
if(tattoo)
|
||||||
|
path->tattoo = tattoo;
|
||||||
|
else
|
||||||
|
path->tattoo = gimp_image_get_new_tattoo(gimage);
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
@ -1789,11 +1803,13 @@ static void file_ok_callback(GtkWidget * widget, gpointer client_data)
|
||||||
pts_list = g_slist_append(pts_list,bpt);
|
pts_list = g_slist_append(pts_list,bpt);
|
||||||
}
|
}
|
||||||
|
|
||||||
bzpath = path_new(BEZIER,
|
bzpath = path_new(paths_dialog->gimage,
|
||||||
|
BEZIER,
|
||||||
pts_list,
|
pts_list,
|
||||||
closed,
|
closed,
|
||||||
state,
|
state,
|
||||||
0, /* Can't be locked */
|
0, /* Can't be locked */
|
||||||
|
0, /* No tattoo assigned */
|
||||||
txt);
|
txt);
|
||||||
|
|
||||||
g_free(txtstart);
|
g_free(txtstart);
|
||||||
|
@ -2027,11 +2043,13 @@ paths_set_path_points(GimpImage * gimage,
|
||||||
{
|
{
|
||||||
GSList *bzp_list = NULL;
|
GSList *bzp_list = NULL;
|
||||||
/* No paths at all.... create one & rename */
|
/* No paths at all.... create one & rename */
|
||||||
bzpath = path_new(ptype,
|
bzpath = path_new(gimage,
|
||||||
|
ptype,
|
||||||
pts_list,
|
pts_list,
|
||||||
pclosed,
|
pclosed,
|
||||||
(pclosed)?BEZIER_EDIT:BEZIER_ADD,/*state,*/
|
(pclosed)?BEZIER_EDIT:BEZIER_ADD,/*state,*/
|
||||||
0, /* Can't be locked */
|
0, /* Can't be locked */
|
||||||
|
0, /* No tattoo assigned */
|
||||||
pname);
|
pname);
|
||||||
bzp_list = g_slist_append(bzp_list,bzpath);
|
bzp_list = g_slist_append(bzp_list,bzpath);
|
||||||
plist = pathsList_new(gimage,0,bzp_list);
|
plist = pathsList_new(gimage,0,bzp_list);
|
||||||
|
@ -2075,11 +2093,13 @@ paths_set_path_points(GimpImage * gimage,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bzpath = path_new(ptype,
|
bzpath = path_new(gimage,
|
||||||
|
ptype,
|
||||||
pts_list,
|
pts_list,
|
||||||
pclosed,
|
pclosed,
|
||||||
(pclosed)?BEZIER_EDIT:BEZIER_ADD,/*state,*/
|
(pclosed)?BEZIER_EDIT:BEZIER_ADD,/*state,*/
|
||||||
0, /* Can't be locked */
|
0, /* Can't be locked */
|
||||||
|
0, /* No tattoo assigned */
|
||||||
pname);
|
pname);
|
||||||
|
|
||||||
path_add_to_current(plist,bzpath,gimage,-1);
|
path_add_to_current(plist,bzpath,gimage,-1);
|
||||||
|
@ -2123,3 +2143,55 @@ paths_stroke(GimpImage *gimage,PathsList *pl,PATHP bzp)
|
||||||
bezier_stroke (bezier_sel, gdisp, SUBDIVIDE, !bzp->closed);
|
bezier_stroke (bezier_sel, gdisp, SUBDIVIDE, !bzp->closed);
|
||||||
beziersel_free(bezier_sel);
|
beziersel_free(bezier_sel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gint
|
||||||
|
paths_distance(PATHP bzp,gdouble dist,gint *x,gint *y, gdouble *grad)
|
||||||
|
{
|
||||||
|
gint ret;
|
||||||
|
BezierSelect * bezier_sel;
|
||||||
|
bezier_sel = path_to_beziersel(bzp);
|
||||||
|
ret = bezier_distance_along(bezier_sel,!bzp->closed,dist,x,y,grad);
|
||||||
|
beziersel_free(bezier_sel);
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
Tattoo
|
||||||
|
paths_get_tattoo(PATHP p)
|
||||||
|
{
|
||||||
|
if(!p)
|
||||||
|
{
|
||||||
|
g_warning(_("paths_get_tattoo: invalid path"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (p->tattoo);
|
||||||
|
}
|
||||||
|
|
||||||
|
PATHP
|
||||||
|
paths_get_path_by_tattoo(GimpImage *gimage,Tattoo tattoo)
|
||||||
|
{
|
||||||
|
GSList *tlist;
|
||||||
|
PATHIMAGELISTP plp;
|
||||||
|
|
||||||
|
if(!gimage || !tattoo)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Go around the list and check all tattoos. */
|
||||||
|
|
||||||
|
/* Get path structure */
|
||||||
|
plp = (PATHIMAGELISTP)gimp_image_get_paths(gimage);
|
||||||
|
|
||||||
|
if(!plp)
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
|
tlist = plp->bz_paths;
|
||||||
|
|
||||||
|
while(tlist)
|
||||||
|
{
|
||||||
|
PATHP p = (PATHP)(tlist->data);
|
||||||
|
if(p->tattoo == tattoo)
|
||||||
|
return (p);
|
||||||
|
tlist = g_slist_next(tlist);
|
||||||
|
}
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
|
@ -85,6 +85,11 @@ void
|
||||||
grab_and_scroll (GDisplay *gdisp,
|
grab_and_scroll (GDisplay *gdisp,
|
||||||
GdkEventMotion *mevent)
|
GdkEventMotion *mevent)
|
||||||
{
|
{
|
||||||
|
if(mevent && mevent->window != gdisp->canvas->window)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
scroll_display (gdisp, (startx - mevent->x - gdisp->offset_x),
|
scroll_display (gdisp, (startx - mevent->x - gdisp->offset_x),
|
||||||
(starty - mevent->y - gdisp->offset_y));
|
(starty - mevent->y - gdisp->offset_y));
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
#include "appenv.h"
|
#include "appenv.h"
|
||||||
#include "draw_core.h"
|
#include "draw_core.h"
|
||||||
#include "edit_selection.h"
|
#include "edit_selection.h"
|
||||||
|
@ -61,6 +62,8 @@
|
||||||
#define NO 0
|
#define NO 0
|
||||||
#define YES 1
|
#define YES 1
|
||||||
|
|
||||||
|
#define ROUND(x) ((int) ((x) + 0.5))
|
||||||
|
|
||||||
/* bezier select type definitions */
|
/* bezier select type definitions */
|
||||||
|
|
||||||
typedef double BezierMatrix[4][4];
|
typedef double BezierMatrix[4][4];
|
||||||
|
@ -84,6 +87,24 @@ struct _named_buffer
|
||||||
char * name;
|
char * name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
gdouble *stroke_points;
|
||||||
|
gint num_stroke_points; /* num of valid points */
|
||||||
|
gint len_stroke_points; /* allocated length */
|
||||||
|
} BezierRenderPnts;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
gboolean firstpnt;
|
||||||
|
gdouble curdist;
|
||||||
|
gdouble dist;
|
||||||
|
gdouble *gradient;
|
||||||
|
gint *x;
|
||||||
|
gint *y;
|
||||||
|
gdouble lastx;
|
||||||
|
gdouble lasty;
|
||||||
|
gboolean found;
|
||||||
|
} BezierDistance;
|
||||||
|
|
||||||
static void bezier_select_button_press (Tool *, GdkEventButton *, gpointer);
|
static void bezier_select_button_press (Tool *, GdkEventButton *, gpointer);
|
||||||
static void bezier_select_button_release (Tool *, GdkEventButton *, gpointer);
|
static void bezier_select_button_release (Tool *, GdkEventButton *, gpointer);
|
||||||
static void bezier_select_motion (Tool *, GdkEventMotion *, gpointer);
|
static void bezier_select_motion (Tool *, GdkEventMotion *, gpointer);
|
||||||
|
@ -96,20 +117,20 @@ static void bezier_draw_handles (BezierSelect *);
|
||||||
static void bezier_draw_current (BezierSelect *);
|
static void bezier_draw_current (BezierSelect *);
|
||||||
static void bezier_draw_point (BezierSelect *, BezierPoint *, int);
|
static void bezier_draw_point (BezierSelect *, BezierPoint *, int);
|
||||||
static void bezier_draw_line (BezierSelect *, BezierPoint *, BezierPoint *);
|
static void bezier_draw_line (BezierSelect *, BezierPoint *, BezierPoint *);
|
||||||
static void bezier_draw_segment (BezierSelect *, BezierPoint *, int, int, BezierPointsFunc);
|
static void bezier_draw_segment (BezierSelect *, BezierPoint *, int, int, BezierPointsFunc,gpointer);
|
||||||
static void bezier_draw_segment_points (BezierSelect *, GdkPoint *, int);
|
static void bezier_draw_segment_points (BezierSelect *, GdkPoint *, int, gpointer);
|
||||||
static void bezier_compose (BezierMatrix, BezierMatrix, BezierMatrix);
|
static void bezier_compose (BezierMatrix, BezierMatrix, BezierMatrix);
|
||||||
|
|
||||||
static void bezier_convert (BezierSelect *, GDisplay *, int, int);
|
static void bezier_convert (BezierSelect *, GDisplay *, int, int);
|
||||||
static void bezier_convert_points (BezierSelect *, GdkPoint *, int);
|
static void bezier_convert_points (BezierSelect *, GdkPoint *, int, gpointer);
|
||||||
static void bezier_convert_line (GSList **, int, int, int, int);
|
static void bezier_convert_line (GSList **, int, int, int, int);
|
||||||
static GSList * bezier_insert_in_list (GSList *, int);
|
static GSList * bezier_insert_in_list (GSList *, int);
|
||||||
|
|
||||||
static int test_add_point_on_segment (BezierSelect *, BezierPoint *, int, int, int, int, int);
|
static int test_add_point_on_segment (BezierSelect *, BezierPoint *, int, int, int, int, int);
|
||||||
static void bezier_to_sel_internal (BezierSelect *, Tool *, GDisplay *, gint, gint);
|
static void bezier_to_sel_internal (BezierSelect *, Tool *, GDisplay *, gint, gint);
|
||||||
static void bezier_stack_points (BezierSelect *, GdkPoint *, int);
|
static void bezier_stack_points (BezierSelect *, GdkPoint *, int, gpointer);
|
||||||
static gboolean stroke_interpolatable (int, int, int, int, gdouble);
|
static gboolean stroke_interpolatable (int, int, int, int, gdouble);
|
||||||
static void bezier_stack_points_aux (GdkPoint *, int, int, gdouble);
|
static void bezier_stack_points_aux (GdkPoint *, int, int, gdouble, BezierRenderPnts *);
|
||||||
|
|
||||||
static BezierMatrix basis =
|
static BezierMatrix basis =
|
||||||
{
|
{
|
||||||
|
@ -233,7 +254,10 @@ bezier_select_load (void *gdisp_ptr,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
bezier_draw_curve (BezierSelect *bezier_sel,BezierPointsFunc func, gint coord)
|
bezier_draw_curve (BezierSelect *bezier_sel,
|
||||||
|
BezierPointsFunc func,
|
||||||
|
gint coord,
|
||||||
|
gpointer udata)
|
||||||
{
|
{
|
||||||
BezierPoint * points;
|
BezierPoint * points;
|
||||||
BezierPoint * start_pt;
|
BezierPoint * start_pt;
|
||||||
|
@ -248,7 +272,8 @@ bezier_draw_curve (BezierSelect *bezier_sel,BezierPointsFunc func, gint coord)
|
||||||
do {
|
do {
|
||||||
bezier_draw_segment (bezier_sel, points,
|
bezier_draw_segment (bezier_sel, points,
|
||||||
SUBDIVIDE, coord,
|
SUBDIVIDE, coord,
|
||||||
func);
|
func,
|
||||||
|
udata);
|
||||||
|
|
||||||
points = points->next;
|
points = points->next;
|
||||||
points = points->next;
|
points = points->next;
|
||||||
|
@ -263,7 +288,8 @@ bezier_draw_curve (BezierSelect *bezier_sel,BezierPointsFunc func, gint coord)
|
||||||
{
|
{
|
||||||
bezier_draw_segment (bezier_sel, points,
|
bezier_draw_segment (bezier_sel, points,
|
||||||
SUBDIVIDE, coord,
|
SUBDIVIDE, coord,
|
||||||
func);
|
func,
|
||||||
|
udata);
|
||||||
|
|
||||||
points = points->next;
|
points = points->next;
|
||||||
points = points->next;
|
points = points->next;
|
||||||
|
@ -447,7 +473,7 @@ bezier_add_point_on_segment(int x,
|
||||||
if (test_add_point_on_segment (bezier_sel,
|
if (test_add_point_on_segment (bezier_sel,
|
||||||
points,
|
points,
|
||||||
SUBDIVIDE,
|
SUBDIVIDE,
|
||||||
SCREEN_COORDS,
|
IMAGE_COORDS,
|
||||||
x, y,
|
x, y,
|
||||||
halfwidth))
|
halfwidth))
|
||||||
{
|
{
|
||||||
|
@ -953,7 +979,7 @@ bezier_select_draw (Tool *tool)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (draw_curve)
|
if (draw_curve)
|
||||||
bezier_draw_curve (bezier_sel,bezier_draw_segment_points,SCREEN_COORDS);
|
bezier_draw_curve (bezier_sel,bezier_draw_segment_points,SCREEN_COORDS,NULL);
|
||||||
if (draw_handles)
|
if (draw_handles)
|
||||||
bezier_draw_handles (bezier_sel);
|
bezier_draw_handles (bezier_sel);
|
||||||
if (draw_current)
|
if (draw_current)
|
||||||
|
@ -1082,7 +1108,8 @@ bezier_draw_current (BezierSelect *bezier_sel)
|
||||||
if (points)
|
if (points)
|
||||||
bezier_draw_segment (bezier_sel, points,
|
bezier_draw_segment (bezier_sel, points,
|
||||||
SUBDIVIDE, SCREEN_COORDS,
|
SUBDIVIDE, SCREEN_COORDS,
|
||||||
bezier_draw_segment_points);
|
bezier_draw_segment_points,
|
||||||
|
NULL);
|
||||||
|
|
||||||
if (points != bezier_sel->cur_anchor)
|
if (points != bezier_sel->cur_anchor)
|
||||||
{
|
{
|
||||||
|
@ -1095,7 +1122,8 @@ bezier_draw_current (BezierSelect *bezier_sel)
|
||||||
if (points)
|
if (points)
|
||||||
bezier_draw_segment (bezier_sel, bezier_sel->cur_anchor,
|
bezier_draw_segment (bezier_sel, bezier_sel->cur_anchor,
|
||||||
SUBDIVIDE, SCREEN_COORDS,
|
SUBDIVIDE, SCREEN_COORDS,
|
||||||
bezier_draw_segment_points);
|
bezier_draw_segment_points,
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1158,7 +1186,8 @@ bezier_draw_segment (BezierSelect *bezier_sel,
|
||||||
BezierPoint *points,
|
BezierPoint *points,
|
||||||
int subdivisions,
|
int subdivisions,
|
||||||
int space,
|
int space,
|
||||||
BezierPointsFunc points_func)
|
BezierPointsFunc points_func,
|
||||||
|
gpointer udata)
|
||||||
{
|
{
|
||||||
#define ROUND(x) ((int) ((x) + 0.5))
|
#define ROUND(x) ((int) ((x) + 0.5))
|
||||||
|
|
||||||
|
@ -1275,7 +1304,7 @@ bezier_draw_segment (BezierSelect *bezier_sel,
|
||||||
/* if the point buffer is full put it to the screen and zero it out */
|
/* if the point buffer is full put it to the screen and zero it out */
|
||||||
if (index >= npoints)
|
if (index >= npoints)
|
||||||
{
|
{
|
||||||
(* points_func) (bezier_sel, gdk_points, index);
|
(* points_func) (bezier_sel, gdk_points, index, udata);
|
||||||
index = 0;
|
index = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1286,13 +1315,14 @@ bezier_draw_segment (BezierSelect *bezier_sel,
|
||||||
|
|
||||||
/* if there are points in the buffer, then put them on the screen */
|
/* if there are points in the buffer, then put them on the screen */
|
||||||
if (index)
|
if (index)
|
||||||
(* points_func) (bezier_sel, gdk_points, index);
|
(* points_func) (bezier_sel, gdk_points, index, udata);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bezier_draw_segment_points (BezierSelect *bezier_sel,
|
bezier_draw_segment_points (BezierSelect *bezier_sel,
|
||||||
GdkPoint *points,
|
GdkPoint *points,
|
||||||
int npoints)
|
int npoints,
|
||||||
|
gpointer udata)
|
||||||
{
|
{
|
||||||
gdk_draw_points (bezier_sel->core->win,
|
gdk_draw_points (bezier_sel->core->win,
|
||||||
bezier_sel->core->gc, points, npoints);
|
bezier_sel->core->gc, points, npoints);
|
||||||
|
@ -1388,7 +1418,8 @@ bezier_convert (BezierSelect *bezier_sel,
|
||||||
do {
|
do {
|
||||||
bezier_draw_segment (bezier_sel, points,
|
bezier_draw_segment (bezier_sel, points,
|
||||||
subdivisions, draw_type,
|
subdivisions, draw_type,
|
||||||
bezier_convert_points);
|
bezier_convert_points,
|
||||||
|
NULL);
|
||||||
|
|
||||||
/* advance to the next segment */
|
/* advance to the next segment */
|
||||||
points = points->next;
|
points = points->next;
|
||||||
|
@ -1478,7 +1509,8 @@ bezier_convert (BezierSelect *bezier_sel,
|
||||||
static void
|
static void
|
||||||
bezier_convert_points (BezierSelect *bezier_sel,
|
bezier_convert_points (BezierSelect *bezier_sel,
|
||||||
GdkPoint *points,
|
GdkPoint *points,
|
||||||
int npoints)
|
int npoints,
|
||||||
|
gpointer udata)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -1765,8 +1797,6 @@ test_add_point_on_segment (BezierSelect *bezier_sel,
|
||||||
int halfwidth)
|
int halfwidth)
|
||||||
|
|
||||||
{
|
{
|
||||||
#define ROUND(x) ((int) ((x) + 0.5))
|
|
||||||
|
|
||||||
BezierPoint *points;
|
BezierPoint *points;
|
||||||
BezierMatrix geometry;
|
BezierMatrix geometry;
|
||||||
BezierMatrix tmp1, tmp2;
|
BezierMatrix tmp1, tmp2;
|
||||||
|
@ -2042,10 +2072,6 @@ void printSel( BezierSelect *sel)
|
||||||
printf("state: %d\n", sel->state);
|
printf("state: %d\n", sel->state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gdouble *stroke_points = NULL;
|
|
||||||
static gint num_stroke_points = 0; /* num of valid points */
|
|
||||||
static gint len_stroke_points = 0; /* allocated length */
|
|
||||||
|
|
||||||
/* check whether vectors (offx, offy), (l_offx, l_offy) have the same angle. */
|
/* check whether vectors (offx, offy), (l_offx, l_offy) have the same angle. */
|
||||||
static gboolean
|
static gboolean
|
||||||
stroke_interpolatable (int offx, int offy, int l_offx, int l_offy, gdouble error)
|
stroke_interpolatable (int offx, int offy, int l_offx, int l_offy, gdouble error)
|
||||||
|
@ -2088,35 +2114,36 @@ static void
|
||||||
bezier_stack_points_aux (GdkPoint *points,
|
bezier_stack_points_aux (GdkPoint *points,
|
||||||
int start,
|
int start,
|
||||||
int end,
|
int end,
|
||||||
gdouble error)
|
gdouble error,
|
||||||
|
BezierRenderPnts *rpnts)
|
||||||
{
|
{
|
||||||
const gint expand_size = 32;
|
const gint expand_size = 32;
|
||||||
gint med;
|
gint med;
|
||||||
gint offx, offy, l_offx, l_offy;
|
gint offx, offy, l_offx, l_offy;
|
||||||
|
|
||||||
if (stroke_points == NULL)
|
if (rpnts->stroke_points == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* BASE CASE: stack the end point */
|
/* BASE CASE: stack the end point */
|
||||||
if (end - start <= 1)
|
if (end - start <= 1)
|
||||||
{
|
{
|
||||||
if ((stroke_points[num_stroke_points * 2 - 2] == points[end].x)
|
if ((rpnts->stroke_points[rpnts->num_stroke_points * 2 - 2] == points[end].x)
|
||||||
&& (stroke_points[num_stroke_points * 2 - 1] == points[end].y))
|
&& (rpnts->stroke_points[rpnts->num_stroke_points * 2 - 1] == points[end].y))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
num_stroke_points++;
|
rpnts->num_stroke_points++;
|
||||||
if (len_stroke_points <= num_stroke_points)
|
if (rpnts->len_stroke_points <= rpnts->num_stroke_points)
|
||||||
{
|
{
|
||||||
len_stroke_points += expand_size;
|
rpnts->len_stroke_points += expand_size;
|
||||||
stroke_points = g_renew (double, stroke_points, 2 * len_stroke_points);
|
rpnts->stroke_points = g_renew (double, rpnts->stroke_points, 2 * rpnts->len_stroke_points);
|
||||||
if (stroke_points == NULL)
|
if (rpnts->stroke_points == NULL)
|
||||||
{
|
{
|
||||||
len_stroke_points = num_stroke_points = 0;
|
rpnts->len_stroke_points = rpnts->num_stroke_points = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stroke_points[num_stroke_points * 2 - 2] = points[end].x;
|
rpnts->stroke_points[rpnts->num_stroke_points * 2 - 2] = points[end].x;
|
||||||
stroke_points[num_stroke_points * 2 - 1] = points[end].y;
|
rpnts->stroke_points[rpnts->num_stroke_points * 2 - 1] = points[end].y;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2125,7 +2152,7 @@ bezier_stack_points_aux (GdkPoint *points,
|
||||||
gint i;
|
gint i;
|
||||||
|
|
||||||
for (i = start+ 1; i <= end; i++)
|
for (i = start+ 1; i <= end; i++)
|
||||||
bezier_stack_points_aux (points, i, i, 0);
|
bezier_stack_points_aux (points, i, i, 0,rpnts);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* Otherwise, check whether to divide the segment recursively */
|
/* Otherwise, check whether to divide the segment recursively */
|
||||||
|
@ -2138,8 +2165,8 @@ bezier_stack_points_aux (GdkPoint *points,
|
||||||
|
|
||||||
if (! stroke_interpolatable (offx, offy, l_offx, l_offy, error))
|
if (! stroke_interpolatable (offx, offy, l_offx, l_offy, error))
|
||||||
{
|
{
|
||||||
bezier_stack_points_aux (points, start, med, error);
|
bezier_stack_points_aux (points, start, med, error, rpnts);
|
||||||
bezier_stack_points_aux (points, med, end, error);
|
bezier_stack_points_aux (points, med, end, error, rpnts);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2148,33 +2175,35 @@ bezier_stack_points_aux (GdkPoint *points,
|
||||||
|
|
||||||
if (! stroke_interpolatable (offx, offy, l_offx, l_offy, error))
|
if (! stroke_interpolatable (offx, offy, l_offx, l_offy, error))
|
||||||
{
|
{
|
||||||
bezier_stack_points_aux (points, start, med, error);
|
bezier_stack_points_aux (points, start, med, error, rpnts);
|
||||||
bezier_stack_points_aux (points, med, end, error);
|
bezier_stack_points_aux (points, med, end, error, rpnts);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* Now, the curve can be represented by a points pair: (start, end).
|
/* Now, the curve can be represented by a points pair: (start, end).
|
||||||
So, add the last point to stroke_points. */
|
So, add the last point to stroke_points. */
|
||||||
bezier_stack_points_aux (points, end, end, 0);
|
bezier_stack_points_aux (points, end, end, 0, rpnts);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bezier_stack_points (BezierSelect *bezier_sel,
|
bezier_stack_points (BezierSelect *bezier_sel,
|
||||||
GdkPoint *points,
|
GdkPoint *points,
|
||||||
int npoints)
|
int npoints,
|
||||||
|
gpointer udata)
|
||||||
{
|
{
|
||||||
gint i;
|
gint i;
|
||||||
gint expand_size = 32;
|
gint expand_size = 32;
|
||||||
gint minx, maxx, miny, maxy;
|
gint minx, maxx, miny, maxy;
|
||||||
gdouble error;
|
gdouble error;
|
||||||
|
BezierRenderPnts *rpnts = udata;
|
||||||
|
|
||||||
if (npoints < 2) /* Does this happen? */
|
if (npoints < 2) /* Does this happen? */
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (stroke_points == NULL) /* initialize it here */
|
if (rpnts->stroke_points == NULL) /* initialize it here */
|
||||||
{
|
{
|
||||||
num_stroke_points = 0;
|
rpnts->num_stroke_points = 0;
|
||||||
len_stroke_points = expand_size;
|
rpnts->len_stroke_points = expand_size;
|
||||||
stroke_points = g_new (double, 2 * len_stroke_points);
|
rpnts->stroke_points = g_new (double, 2 * rpnts->len_stroke_points);
|
||||||
}
|
}
|
||||||
|
|
||||||
maxx = minx = points[0].x;
|
maxx = minx = points[0].x;
|
||||||
|
@ -2194,24 +2223,21 @@ bezier_stack_points (BezierSelect *bezier_sel,
|
||||||
error = 2.0 / MAX(maxx - minx, maxy - miny);
|
error = 2.0 / MAX(maxx - minx, maxy - miny);
|
||||||
|
|
||||||
/* add the start point */
|
/* add the start point */
|
||||||
bezier_stack_points_aux (points, 0, 0, 0);
|
bezier_stack_points_aux (points, 0, 0, 0, rpnts);
|
||||||
|
|
||||||
/* divide segments recursively */
|
/* divide segments recursively */
|
||||||
bezier_stack_points_aux (points, 0, npoints - 1, error);
|
bezier_stack_points_aux (points, 0, npoints - 1, error, rpnts);
|
||||||
|
|
||||||
/* printf ("npoints: %d\n", npoints); */
|
/* printf ("npoints: %d\n", npoints); */
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static gint
|
||||||
bezier_stroke (BezierSelect *bezier_sel,
|
bezier_gen_points(BezierSelect *bezier_sel,
|
||||||
GDisplay *gdisp,
|
int open_path,
|
||||||
int subdivisions,
|
BezierRenderPnts *rpnts)
|
||||||
int open_path)
|
|
||||||
{
|
{
|
||||||
BezierPoint * points;
|
BezierPoint * points;
|
||||||
int num_points;
|
int num_points;
|
||||||
Argument *return_vals;
|
|
||||||
int nreturn_vals;
|
|
||||||
int redraw = FALSE;
|
int redraw = FALSE;
|
||||||
|
|
||||||
/* stack points */
|
/* stack points */
|
||||||
|
@ -2227,7 +2253,8 @@ bezier_stroke (BezierSelect *bezier_sel,
|
||||||
do {
|
do {
|
||||||
bezier_draw_segment (bezier_sel, points,
|
bezier_draw_segment (bezier_sel, points,
|
||||||
SUBDIVIDE, IMAGE_COORDS,
|
SUBDIVIDE, IMAGE_COORDS,
|
||||||
bezier_stack_points);
|
bezier_stack_points,
|
||||||
|
(gpointer)rpnts);
|
||||||
|
|
||||||
points = points->next;
|
points = points->next;
|
||||||
points = points->next;
|
points = points->next;
|
||||||
|
@ -2245,7 +2272,8 @@ bezier_stroke (BezierSelect *bezier_sel,
|
||||||
{
|
{
|
||||||
bezier_draw_segment (bezier_sel, points,
|
bezier_draw_segment (bezier_sel, points,
|
||||||
SUBDIVIDE, IMAGE_COORDS,
|
SUBDIVIDE, IMAGE_COORDS,
|
||||||
bezier_stack_points);
|
bezier_stack_points,
|
||||||
|
(gpointer)rpnts);
|
||||||
|
|
||||||
points = points->next;
|
points = points->next;
|
||||||
points = points->next;
|
points = points->next;
|
||||||
|
@ -2254,7 +2282,23 @@ bezier_stroke (BezierSelect *bezier_sel,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stroke_points)
|
return (redraw);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
bezier_stroke (BezierSelect *bezier_sel,
|
||||||
|
GDisplay *gdisp,
|
||||||
|
int subdivisions,
|
||||||
|
int open_path)
|
||||||
|
{
|
||||||
|
Argument *return_vals;
|
||||||
|
int nreturn_vals;
|
||||||
|
int redraw;
|
||||||
|
BezierRenderPnts *rpnts = g_new0(BezierRenderPnts,1);
|
||||||
|
|
||||||
|
redraw = bezier_gen_points(bezier_sel,open_path,rpnts);
|
||||||
|
|
||||||
|
if (rpnts->stroke_points)
|
||||||
{
|
{
|
||||||
GimpDrawable *drawable;
|
GimpDrawable *drawable;
|
||||||
int offset_x, offset_y;
|
int offset_x, offset_y;
|
||||||
|
@ -2266,8 +2310,8 @@ bezier_stroke (BezierSelect *bezier_sel,
|
||||||
{
|
{
|
||||||
gdouble *ptr;
|
gdouble *ptr;
|
||||||
|
|
||||||
ptr = stroke_points;
|
ptr = rpnts->stroke_points;
|
||||||
while (ptr < stroke_points + (num_stroke_points * 2))
|
while (ptr < rpnts->stroke_points + (rpnts->num_stroke_points * 2))
|
||||||
{
|
{
|
||||||
*ptr++ -= offset_x;
|
*ptr++ -= offset_x;
|
||||||
*ptr++ -= offset_y;
|
*ptr++ -= offset_y;
|
||||||
|
@ -2278,8 +2322,8 @@ bezier_stroke (BezierSelect *bezier_sel,
|
||||||
&nreturn_vals,
|
&nreturn_vals,
|
||||||
PDB_DRAWABLE, drawable_ID (drawable),
|
PDB_DRAWABLE, drawable_ID (drawable),
|
||||||
PDB_FLOAT, (gdouble) 0,
|
PDB_FLOAT, (gdouble) 0,
|
||||||
PDB_INT32, (gint32) num_stroke_points * 2,
|
PDB_INT32, (gint32) rpnts->num_stroke_points * 2,
|
||||||
PDB_FLOATARRAY, stroke_points,
|
PDB_FLOATARRAY, rpnts->stroke_points,
|
||||||
PDB_END);
|
PDB_END);
|
||||||
|
|
||||||
if (return_vals[0].value.pdb_int == PDB_SUCCESS)
|
if (return_vals[0].value.pdb_int == PDB_SUCCESS)
|
||||||
|
@ -2295,10 +2339,206 @@ bezier_stroke (BezierSelect *bezier_sel,
|
||||||
|
|
||||||
procedural_db_destroy_args (return_vals, nreturn_vals);
|
procedural_db_destroy_args (return_vals, nreturn_vals);
|
||||||
|
|
||||||
g_free (stroke_points);
|
g_free (rpnts->stroke_points);
|
||||||
}
|
}
|
||||||
/* printf ("num_stroke_points: %d\ndone.\n", num_stroke_points); */
|
/* printf ("num_stroke_points: %d\ndone.\n", num_stroke_points); */
|
||||||
|
|
||||||
stroke_points = NULL;
|
rpnts->stroke_points = NULL;
|
||||||
len_stroke_points = num_stroke_points = 0;
|
rpnts->len_stroke_points = rpnts->num_stroke_points = 0;
|
||||||
|
|
||||||
|
g_free(rpnts);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
bezier_draw_segment_for_distance (BezierSelect *bezier_sel,
|
||||||
|
BezierPoint *points,
|
||||||
|
int subdivisions,
|
||||||
|
BezierDistance *bdist)
|
||||||
|
{
|
||||||
|
BezierMatrix geometry;
|
||||||
|
BezierMatrix tmp1, tmp2;
|
||||||
|
BezierMatrix deltas;
|
||||||
|
double x, dx, dx2, dx3;
|
||||||
|
double y, dy, dy2, dy3;
|
||||||
|
double d, d2, d3;
|
||||||
|
int index;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* construct the geometry matrix from the segment */
|
||||||
|
/* assumes that a valid segment containing 4 points is passed in */
|
||||||
|
|
||||||
|
if(bdist->found)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
if (!points)
|
||||||
|
fatal_error (_("bad bezier segment"));
|
||||||
|
|
||||||
|
geometry[i][0] = points->x;
|
||||||
|
geometry[i][1] = points->y;
|
||||||
|
geometry[i][2] = 0;
|
||||||
|
geometry[i][3] = 0;
|
||||||
|
|
||||||
|
points = points->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* subdivide the curve n times */
|
||||||
|
/* n can be adjusted to give a finer or coarser curve */
|
||||||
|
|
||||||
|
d = 1.0 / subdivisions;
|
||||||
|
d2 = d * d;
|
||||||
|
d3 = d * d * d;
|
||||||
|
|
||||||
|
/* construct a temporary matrix for determining the forward diffencing deltas */
|
||||||
|
|
||||||
|
tmp2[0][0] = 0; tmp2[0][1] = 0; tmp2[0][2] = 0; tmp2[0][3] = 1;
|
||||||
|
tmp2[1][0] = d3; tmp2[1][1] = d2; tmp2[1][2] = d; tmp2[1][3] = 0;
|
||||||
|
tmp2[2][0] = 6*d3; tmp2[2][1] = 2*d2; tmp2[2][2] = 0; tmp2[2][3] = 0;
|
||||||
|
tmp2[3][0] = 6*d3; tmp2[3][1] = 0; tmp2[3][2] = 0; tmp2[3][3] = 0;
|
||||||
|
|
||||||
|
/* compose the basis and geometry matrices */
|
||||||
|
bezier_compose (basis, geometry, tmp1);
|
||||||
|
|
||||||
|
/* compose the above results to get the deltas matrix */
|
||||||
|
bezier_compose (tmp2, tmp1, deltas);
|
||||||
|
|
||||||
|
/* extract the x deltas */
|
||||||
|
x = deltas[0][0];
|
||||||
|
dx = deltas[1][0];
|
||||||
|
dx2 = deltas[2][0];
|
||||||
|
dx3 = deltas[3][0];
|
||||||
|
|
||||||
|
/* extract the y deltas */
|
||||||
|
y = deltas[0][1];
|
||||||
|
dy = deltas[1][1];
|
||||||
|
dy2 = deltas[2][1];
|
||||||
|
dy3 = deltas[3][1];
|
||||||
|
|
||||||
|
index = 1;
|
||||||
|
|
||||||
|
/* loop over the curve */
|
||||||
|
for (i = 0; i < subdivisions; i++)
|
||||||
|
{
|
||||||
|
/* increment the x values */
|
||||||
|
x += dx;
|
||||||
|
dx += dx2;
|
||||||
|
dx2 += dx3;
|
||||||
|
|
||||||
|
/* increment the y values */
|
||||||
|
y += dy;
|
||||||
|
dy += dy2;
|
||||||
|
dy2 += dy3;
|
||||||
|
|
||||||
|
/* printf("x = %g, y = %g\n",x,y); */
|
||||||
|
|
||||||
|
/* if this point is different than the last one...then draw it */
|
||||||
|
/* Note :
|
||||||
|
* It assumes the udata is the place we want the
|
||||||
|
* floating version of the coords to be stuffed.
|
||||||
|
* These are needed when we calculate the gradient of the
|
||||||
|
* curve.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if(!bdist->firstpnt)
|
||||||
|
{
|
||||||
|
gdouble rx = x;
|
||||||
|
gdouble ry = y;
|
||||||
|
gdouble dx = bdist->lastx - rx;
|
||||||
|
gdouble dy = bdist->lasty - ry;
|
||||||
|
|
||||||
|
bdist->curdist += sqrt((dx*dx)+(dy*dy));
|
||||||
|
if(bdist->curdist >= bdist->dist)
|
||||||
|
{
|
||||||
|
*(bdist->x) = (gint)ROUND((rx + dx/2));
|
||||||
|
*(bdist->y) = (gint)ROUND((ry + dy/2));
|
||||||
|
if(dx == 0.0)
|
||||||
|
*(bdist->gradient) = G_MAXDOUBLE;
|
||||||
|
else
|
||||||
|
*(bdist->gradient) = dy/dx;
|
||||||
|
|
||||||
|
/* printf("found x = %d, y = %d\n",*(bdist->x),*(bdist->y)); */
|
||||||
|
bdist->found = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
bdist->lastx = rx;
|
||||||
|
bdist->lasty = ry;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bdist->firstpnt = FALSE;
|
||||||
|
bdist->lastx = x;
|
||||||
|
bdist->lasty = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
bezier_draw_curve_for_distance (BezierSelect *bezier_sel,
|
||||||
|
BezierDistance *udata)
|
||||||
|
{
|
||||||
|
BezierPoint * points;
|
||||||
|
BezierPoint * start_pt;
|
||||||
|
int num_points;
|
||||||
|
|
||||||
|
points = bezier_sel->points;
|
||||||
|
|
||||||
|
if (bezier_sel->closed)
|
||||||
|
{
|
||||||
|
start_pt = bezier_sel->points;
|
||||||
|
|
||||||
|
do {
|
||||||
|
bezier_draw_segment_for_distance (bezier_sel, points,
|
||||||
|
SUBDIVIDE,
|
||||||
|
udata);
|
||||||
|
|
||||||
|
points = points->next;
|
||||||
|
points = points->next;
|
||||||
|
points = points->next;
|
||||||
|
} while (points != start_pt);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
num_points = bezier_sel->num_points;
|
||||||
|
|
||||||
|
while (num_points >= 4)
|
||||||
|
{
|
||||||
|
bezier_draw_segment_for_distance (bezier_sel, points,
|
||||||
|
SUBDIVIDE,
|
||||||
|
udata);
|
||||||
|
points = points->next;
|
||||||
|
points = points->next;
|
||||||
|
points = points->next;
|
||||||
|
num_points -= 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gint
|
||||||
|
bezier_distance_along(BezierSelect *bezier_sel,
|
||||||
|
int open_path,
|
||||||
|
gdouble dist,
|
||||||
|
gint *x,
|
||||||
|
gint *y,
|
||||||
|
gdouble *gradient)
|
||||||
|
{
|
||||||
|
/* Render the curve as points then walk along it... */
|
||||||
|
BezierDistance *bdist = g_new0(BezierDistance,1);
|
||||||
|
gint ret;
|
||||||
|
|
||||||
|
bdist->firstpnt = TRUE;
|
||||||
|
bdist->curdist = 0.0;
|
||||||
|
bdist->lastx = 0.0;
|
||||||
|
bdist->lasty = 0.0;
|
||||||
|
bdist->dist = dist;
|
||||||
|
bdist->x = x;
|
||||||
|
bdist->y = y;
|
||||||
|
bdist->gradient = gradient;
|
||||||
|
bdist->found = FALSE;
|
||||||
|
|
||||||
|
bezier_draw_curve_for_distance (bezier_sel,bdist);
|
||||||
|
ret = bdist->found;
|
||||||
|
|
||||||
|
g_free(bdist);
|
||||||
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,17 +63,17 @@ struct _bezier_select
|
||||||
GSList **scanlines; /* used in converting a curve */
|
GSList **scanlines; /* used in converting a curve */
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef void (*BezierPointsFunc) (BezierSelect *, GdkPoint *, int);
|
typedef void (*BezierPointsFunc) (BezierSelect *, GdkPoint *, int,gpointer);
|
||||||
|
|
||||||
/* Functions */
|
/* Functions */
|
||||||
int bezier_select_load (void *, BezierPoint *, int, int);
|
int bezier_select_load (void *, BezierPoint *, int, int);
|
||||||
void bezier_draw_curve (BezierSelect *,BezierPointsFunc, int);
|
void bezier_draw_curve (BezierSelect *,BezierPointsFunc, int,gpointer);
|
||||||
void bezier_select_reset (BezierSelect *);
|
void bezier_select_reset (BezierSelect *);
|
||||||
void bezier_add_point (BezierSelect *, int, int, int);
|
void bezier_add_point (BezierSelect *, int, int, int);
|
||||||
void bezier_paste_bezierselect_to_current (GDisplay *,BezierSelect *);
|
void bezier_paste_bezierselect_to_current (GDisplay *,BezierSelect *);
|
||||||
void bezier_select_mode (gint);
|
void bezier_select_mode (gint);
|
||||||
void bezier_stroke (BezierSelect *, GDisplay *, int, int);
|
void bezier_stroke (BezierSelect *, GDisplay *, int, int);
|
||||||
void bezier_to_selection (BezierSelect *, GDisplay *);
|
void bezier_to_selection (BezierSelect *, GDisplay *);
|
||||||
|
gint bezier_distance_along (BezierSelect *, gint, gdouble,gint *,gint *,gdouble *);
|
||||||
|
|
||||||
#endif /* __BEZIER_SELECTP_H__ */
|
#endif /* __BEZIER_SELECTP_H__ */
|
||||||
|
|
|
@ -263,6 +263,12 @@ move_tool_motion (Tool *tool,
|
||||||
{
|
{
|
||||||
move_draw_guide (gdisp, private->guide);
|
move_draw_guide (gdisp, private->guide);
|
||||||
|
|
||||||
|
if(mevent && mevent->window != gdisp->canvas->window)
|
||||||
|
{
|
||||||
|
private->guide->position = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (mevent)
|
if (mevent)
|
||||||
{
|
{
|
||||||
gdisplay_untransform_coords (gdisp, mevent->x, mevent->y,
|
gdisplay_untransform_coords (gdisp, mevent->x, mevent->y,
|
||||||
|
|
|
@ -263,6 +263,12 @@ move_tool_motion (Tool *tool,
|
||||||
{
|
{
|
||||||
move_draw_guide (gdisp, private->guide);
|
move_draw_guide (gdisp, private->guide);
|
||||||
|
|
||||||
|
if(mevent && mevent->window != gdisp->canvas->window)
|
||||||
|
{
|
||||||
|
private->guide->position = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (mevent)
|
if (mevent)
|
||||||
{
|
{
|
||||||
gdisplay_untransform_coords (gdisp, mevent->x, mevent->y,
|
gdisplay_untransform_coords (gdisp, mevent->x, mevent->y,
|
||||||
|
|
23
app/xcf.c
23
app/xcf.c
|
@ -777,13 +777,14 @@ static void write_one_path(gpointer pptr, gpointer iptr)
|
||||||
info->cp += xcf_write_int32(info->fp, &closed,1);
|
info->cp += xcf_write_int32(info->fp, &closed,1);
|
||||||
num_points = g_slist_length(bzp->path_details);
|
num_points = g_slist_length(bzp->path_details);
|
||||||
info->cp += xcf_write_int32(info->fp, &num_points,1);
|
info->cp += xcf_write_int32(info->fp, &num_points,1);
|
||||||
version = 2;
|
version = 3;
|
||||||
info->cp += xcf_write_int32(info->fp, &version,1);
|
info->cp += xcf_write_int32(info->fp, &version,1);
|
||||||
info->cp += xcf_write_int32(info->fp, &bzp->pathtype,1);
|
info->cp += xcf_write_int32(info->fp, &bzp->pathtype,1);
|
||||||
|
info->cp += xcf_write_int32(info->fp, &bzp->tattoo,1);
|
||||||
g_slist_foreach(bzp->path_details,write_bz_point,info);
|
g_slist_foreach(bzp->path_details,write_bz_point,info);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PATHP read_one_path(XcfInfo *info)
|
static PATHP read_one_path(GImage *gimage,XcfInfo *info)
|
||||||
{
|
{
|
||||||
PATHP bzp;
|
PATHP bzp;
|
||||||
gchar *name;
|
gchar *name;
|
||||||
|
@ -792,6 +793,7 @@ static PATHP read_one_path(XcfInfo *info)
|
||||||
guint32 closed;
|
guint32 closed;
|
||||||
guint32 num_points;
|
guint32 num_points;
|
||||||
guint32 version; /* changed from num_paths */
|
guint32 version; /* changed from num_paths */
|
||||||
|
Tattoo tattoo = 0;
|
||||||
GSList *pts_list = NULL;
|
GSList *pts_list = NULL;
|
||||||
PathType ptype;
|
PathType ptype;
|
||||||
|
|
||||||
|
@ -825,12 +827,25 @@ static PATHP read_one_path(XcfInfo *info)
|
||||||
pts_list = g_slist_append(pts_list,bpt);
|
pts_list = g_slist_append(pts_list,bpt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(version == 3)
|
||||||
|
{
|
||||||
|
/* Has extra tatto field */
|
||||||
|
info->cp += xcf_read_int32(info->fp, (guint32 *)&ptype,1);
|
||||||
|
info->cp += xcf_read_int32(info->fp, (guint32 *)&tattoo,1);
|
||||||
|
while(num_points-- > 0)
|
||||||
|
{
|
||||||
|
PATHPOINTP bpt;
|
||||||
|
/* Read in a path */
|
||||||
|
bpt = read_bz_point(info);
|
||||||
|
pts_list = g_slist_append(pts_list,bpt);
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
g_warning("Unknown path type..Possibly corrupt XCF file");
|
g_warning("Unknown path type..Possibly corrupt XCF file");
|
||||||
}
|
}
|
||||||
|
|
||||||
bzp = path_new(ptype,pts_list,closed,(gint)state,locked,name);
|
bzp = path_new(gimage,ptype,pts_list,closed,(gint)state,locked,tattoo,name);
|
||||||
|
|
||||||
return(bzp);
|
return(bzp);
|
||||||
}
|
}
|
||||||
|
@ -866,7 +881,7 @@ static PathsList * read_bzpaths(GImage *gimage, XcfInfo *info)
|
||||||
{
|
{
|
||||||
PATHP bzp;
|
PATHP bzp;
|
||||||
/* Read in a path */
|
/* Read in a path */
|
||||||
bzp = read_one_path(info);
|
bzp = read_one_path(gimage,info);
|
||||||
bzp_list = g_slist_append(bzp_list,bzp);
|
bzp_list = g_slist_append(bzp_list,bzp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -777,13 +777,14 @@ static void write_one_path(gpointer pptr, gpointer iptr)
|
||||||
info->cp += xcf_write_int32(info->fp, &closed,1);
|
info->cp += xcf_write_int32(info->fp, &closed,1);
|
||||||
num_points = g_slist_length(bzp->path_details);
|
num_points = g_slist_length(bzp->path_details);
|
||||||
info->cp += xcf_write_int32(info->fp, &num_points,1);
|
info->cp += xcf_write_int32(info->fp, &num_points,1);
|
||||||
version = 2;
|
version = 3;
|
||||||
info->cp += xcf_write_int32(info->fp, &version,1);
|
info->cp += xcf_write_int32(info->fp, &version,1);
|
||||||
info->cp += xcf_write_int32(info->fp, &bzp->pathtype,1);
|
info->cp += xcf_write_int32(info->fp, &bzp->pathtype,1);
|
||||||
|
info->cp += xcf_write_int32(info->fp, &bzp->tattoo,1);
|
||||||
g_slist_foreach(bzp->path_details,write_bz_point,info);
|
g_slist_foreach(bzp->path_details,write_bz_point,info);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PATHP read_one_path(XcfInfo *info)
|
static PATHP read_one_path(GImage *gimage,XcfInfo *info)
|
||||||
{
|
{
|
||||||
PATHP bzp;
|
PATHP bzp;
|
||||||
gchar *name;
|
gchar *name;
|
||||||
|
@ -792,6 +793,7 @@ static PATHP read_one_path(XcfInfo *info)
|
||||||
guint32 closed;
|
guint32 closed;
|
||||||
guint32 num_points;
|
guint32 num_points;
|
||||||
guint32 version; /* changed from num_paths */
|
guint32 version; /* changed from num_paths */
|
||||||
|
Tattoo tattoo = 0;
|
||||||
GSList *pts_list = NULL;
|
GSList *pts_list = NULL;
|
||||||
PathType ptype;
|
PathType ptype;
|
||||||
|
|
||||||
|
@ -825,12 +827,25 @@ static PATHP read_one_path(XcfInfo *info)
|
||||||
pts_list = g_slist_append(pts_list,bpt);
|
pts_list = g_slist_append(pts_list,bpt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(version == 3)
|
||||||
|
{
|
||||||
|
/* Has extra tatto field */
|
||||||
|
info->cp += xcf_read_int32(info->fp, (guint32 *)&ptype,1);
|
||||||
|
info->cp += xcf_read_int32(info->fp, (guint32 *)&tattoo,1);
|
||||||
|
while(num_points-- > 0)
|
||||||
|
{
|
||||||
|
PATHPOINTP bpt;
|
||||||
|
/* Read in a path */
|
||||||
|
bpt = read_bz_point(info);
|
||||||
|
pts_list = g_slist_append(pts_list,bpt);
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
g_warning("Unknown path type..Possibly corrupt XCF file");
|
g_warning("Unknown path type..Possibly corrupt XCF file");
|
||||||
}
|
}
|
||||||
|
|
||||||
bzp = path_new(ptype,pts_list,closed,(gint)state,locked,name);
|
bzp = path_new(gimage,ptype,pts_list,closed,(gint)state,locked,tattoo,name);
|
||||||
|
|
||||||
return(bzp);
|
return(bzp);
|
||||||
}
|
}
|
||||||
|
@ -866,7 +881,7 @@ static PathsList * read_bzpaths(GImage *gimage, XcfInfo *info)
|
||||||
{
|
{
|
||||||
PATHP bzp;
|
PATHP bzp;
|
||||||
/* Read in a path */
|
/* Read in a path */
|
||||||
bzp = read_one_path(info);
|
bzp = read_one_path(gimage,info);
|
||||||
bzp_list = g_slist_append(bzp_list,bzp);
|
bzp_list = g_slist_append(bzp_list,bzp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -316,10 +316,182 @@ CODE
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub path_get_point_at_dist {
|
||||||
|
$blurb = 'Get point on a path at a specified distance along the path';
|
||||||
|
|
||||||
|
$help = <<'HELP';
|
||||||
|
This will return the x,y position of a point at a given distance along the
|
||||||
|
bezier curve. The distance will the obtained by first digitizing the
|
||||||
|
curve internally an then walking along the curve. For a closed curve the
|
||||||
|
start of the path is the first point on the path that was created. This might
|
||||||
|
not be obvious. Note the current path is used.
|
||||||
|
HELP
|
||||||
|
|
||||||
|
&pdb_misc;
|
||||||
|
|
||||||
|
@inargs = ( &std_image_arg,
|
||||||
|
{ name => 'distance',
|
||||||
|
type => 'float',
|
||||||
|
desc => 'The distance along the path'
|
||||||
|
}
|
||||||
|
);
|
||||||
|
$inargs[0]->{desc} = 'The ID of the image the paths belongs to';
|
||||||
|
|
||||||
|
@outargs = (
|
||||||
|
{ name => 'x_point',
|
||||||
|
init => 1,
|
||||||
|
type => 'int32',
|
||||||
|
desc => 'The x position of the point'
|
||||||
|
},
|
||||||
|
{ name => 'y_point',
|
||||||
|
type => 'int32',
|
||||||
|
desc => 'The y position of the point',
|
||||||
|
init => 1
|
||||||
|
},
|
||||||
|
{ name => 'gradient',
|
||||||
|
type => 'float',
|
||||||
|
desc => 'The gradient at the specified point',
|
||||||
|
init => 1
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
%invoke = (
|
||||||
|
code => <<'CODE'
|
||||||
|
{
|
||||||
|
/* Get the path with the given name */
|
||||||
|
PathsList *plist = gimage->paths;
|
||||||
|
|
||||||
|
if(plist && plist->bz_paths)
|
||||||
|
{
|
||||||
|
PATHP pptr = NULL;
|
||||||
|
|
||||||
|
if(plist->last_selected_row >= 0)
|
||||||
|
{
|
||||||
|
pptr = (PATHP)g_slist_nth_data(plist->bz_paths,plist->last_selected_row);
|
||||||
|
success = paths_distance(pptr,distance,&x_point,&y_point,&gradient);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
success = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
success = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CODE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub path_get_tattoo {
|
||||||
|
$blurb = 'Returns the tattoo associated with the name path';
|
||||||
|
|
||||||
|
$help = <<'HELP';
|
||||||
|
This procedure returns the tattoo associated with the specified path. A tattoo is a unique and permenant identifier attached to a path that can be used to uniquely identify a path within an image even between sessions.
|
||||||
|
HELP
|
||||||
|
|
||||||
|
&pdb_misc;
|
||||||
|
|
||||||
|
@inargs = (
|
||||||
|
&std_image_arg,
|
||||||
|
{ name => 'pathname', type => 'string',
|
||||||
|
desc => 'the name of the path whose tattoo should be obtained',
|
||||||
|
alias => 'pname' }
|
||||||
|
);
|
||||||
|
$inargs[0]->{desc} = 'The ID of the image';
|
||||||
|
|
||||||
|
@outargs = (
|
||||||
|
{ name => 'tattoo',
|
||||||
|
type => 'int32',
|
||||||
|
init => 1,
|
||||||
|
desc => 'The tattoo associated with the name path',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
%invoke = (
|
||||||
|
vars => [ 'PathsList *plist' ],
|
||||||
|
code => <<'CODE'
|
||||||
|
{
|
||||||
|
PATHP pptr = NULL;
|
||||||
|
/* Get the path with the given name */
|
||||||
|
plist = gimage->paths;
|
||||||
|
|
||||||
|
if (plist && plist->bz_paths)
|
||||||
|
{
|
||||||
|
GSList *pl = plist->bz_paths;
|
||||||
|
|
||||||
|
while (pl)
|
||||||
|
{
|
||||||
|
pptr = pl->data;
|
||||||
|
|
||||||
|
if (strcmp (pname, pptr->name->str) == 0)
|
||||||
|
break; /* Found the path */
|
||||||
|
|
||||||
|
pl = pl->next;
|
||||||
|
pptr = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pl && pptr)
|
||||||
|
{
|
||||||
|
tattoo = paths_get_tattoo(pptr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
success = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CODE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub get_path_by_tattoo {
|
||||||
|
$blurb = 'Return the name of the path with the given tattoo';
|
||||||
|
|
||||||
|
$help = <<'HELP';
|
||||||
|
The procedure returns the name of the path in the specified image which has the passed tattoo. The tattoos are unique within the image and will be preserved across sessions and through renaming of the path. An error is returned if no path woth the specified tattoo can be found.
|
||||||
|
HELP
|
||||||
|
|
||||||
|
&pdb_misc;
|
||||||
|
@inargs = (
|
||||||
|
&std_image_arg,
|
||||||
|
{ name => 'tattoo', type => 'int32',
|
||||||
|
desc => 'The tattoo of the required path',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
$inargs[0]->{desc} = 'The ID of the image';
|
||||||
|
|
||||||
|
@outargs = (
|
||||||
|
{ name => 'path_name', type => 'string',
|
||||||
|
desc => 'The name of the path with the specified tattoo',
|
||||||
|
alias => 'g_strdup (pptr->name->str)', no_declare => 1 }
|
||||||
|
);
|
||||||
|
|
||||||
|
%invoke = (
|
||||||
|
vars => [ 'PathsList *plist', 'PATHP pptr = NULL' ],
|
||||||
|
code => <<'CODE'
|
||||||
|
{
|
||||||
|
/* Get the path with the given name */
|
||||||
|
plist = gimage->paths;
|
||||||
|
|
||||||
|
if (plist && plist->bz_paths)
|
||||||
|
{
|
||||||
|
if((pptr = paths_get_path_by_tattoo(gimage,tattoo)) == NULL)
|
||||||
|
success = FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
success = FALSE;
|
||||||
|
}
|
||||||
|
CODE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@headers = qw("gimage.h" "pathsP.h");
|
@headers = qw("gimage.h" "pathsP.h");
|
||||||
|
|
||||||
@procs = qw(path_list path_get_points path_get_current path_set_current
|
@procs = qw(path_list path_get_points path_get_current path_set_current
|
||||||
path_set_points path_stroke_current);
|
path_set_points path_stroke_current path_get_point_at_dist
|
||||||
|
path_get_tattoo get_path_by_tattoo);
|
||||||
%exports = (app => [@procs]);
|
%exports = (app => [@procs]);
|
||||||
|
|
||||||
$desc = 'Paths';
|
$desc = 'Paths';
|
||||||
|
|
Loading…
Reference in New Issue