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>
|
||||
|
||||
* app/color_balance.c: Color-balance didn't work when used
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "appenv.h"
|
||||
#include "draw_core.h"
|
||||
#include "edit_selection.h"
|
||||
|
@ -61,6 +62,8 @@
|
|||
#define NO 0
|
||||
#define YES 1
|
||||
|
||||
#define ROUND(x) ((int) ((x) + 0.5))
|
||||
|
||||
/* bezier select type definitions */
|
||||
|
||||
typedef double BezierMatrix[4][4];
|
||||
|
@ -84,6 +87,24 @@ struct _named_buffer
|
|||
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_release (Tool *, GdkEventButton *, 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_point (BezierSelect *, BezierPoint *, int);
|
||||
static void bezier_draw_line (BezierSelect *, BezierPoint *, BezierPoint *);
|
||||
static void bezier_draw_segment (BezierSelect *, BezierPoint *, int, int, BezierPointsFunc);
|
||||
static void bezier_draw_segment_points (BezierSelect *, GdkPoint *, int);
|
||||
static void bezier_draw_segment (BezierSelect *, BezierPoint *, int, int, BezierPointsFunc,gpointer);
|
||||
static void bezier_draw_segment_points (BezierSelect *, GdkPoint *, int, gpointer);
|
||||
static void bezier_compose (BezierMatrix, BezierMatrix, BezierMatrix);
|
||||
|
||||
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 GSList * bezier_insert_in_list (GSList *, 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_stack_points (BezierSelect *, GdkPoint *, int);
|
||||
static void bezier_stack_points (BezierSelect *, GdkPoint *, int, gpointer);
|
||||
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 =
|
||||
{
|
||||
|
@ -233,7 +254,10 @@ bezier_select_load (void *gdisp_ptr,
|
|||
}
|
||||
|
||||
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 * start_pt;
|
||||
|
@ -248,7 +272,8 @@ bezier_draw_curve (BezierSelect *bezier_sel,BezierPointsFunc func, gint coord)
|
|||
do {
|
||||
bezier_draw_segment (bezier_sel, points,
|
||||
SUBDIVIDE, coord,
|
||||
func);
|
||||
func,
|
||||
udata);
|
||||
|
||||
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,
|
||||
SUBDIVIDE, coord,
|
||||
func);
|
||||
func,
|
||||
udata);
|
||||
|
||||
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,
|
||||
points,
|
||||
SUBDIVIDE,
|
||||
SCREEN_COORDS,
|
||||
IMAGE_COORDS,
|
||||
x, y,
|
||||
halfwidth))
|
||||
{
|
||||
|
@ -953,7 +979,7 @@ bezier_select_draw (Tool *tool)
|
|||
}
|
||||
|
||||
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)
|
||||
bezier_draw_handles (bezier_sel);
|
||||
if (draw_current)
|
||||
|
@ -1082,7 +1108,8 @@ bezier_draw_current (BezierSelect *bezier_sel)
|
|||
if (points)
|
||||
bezier_draw_segment (bezier_sel, points,
|
||||
SUBDIVIDE, SCREEN_COORDS,
|
||||
bezier_draw_segment_points);
|
||||
bezier_draw_segment_points,
|
||||
NULL);
|
||||
|
||||
if (points != bezier_sel->cur_anchor)
|
||||
{
|
||||
|
@ -1095,7 +1122,8 @@ bezier_draw_current (BezierSelect *bezier_sel)
|
|||
if (points)
|
||||
bezier_draw_segment (bezier_sel, bezier_sel->cur_anchor,
|
||||
SUBDIVIDE, SCREEN_COORDS,
|
||||
bezier_draw_segment_points);
|
||||
bezier_draw_segment_points,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1158,7 +1186,8 @@ bezier_draw_segment (BezierSelect *bezier_sel,
|
|||
BezierPoint *points,
|
||||
int subdivisions,
|
||||
int space,
|
||||
BezierPointsFunc points_func)
|
||||
BezierPointsFunc points_func,
|
||||
gpointer udata)
|
||||
{
|
||||
#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 (index >= npoints)
|
||||
{
|
||||
(* points_func) (bezier_sel, gdk_points, index);
|
||||
(* points_func) (bezier_sel, gdk_points, index, udata);
|
||||
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 (index)
|
||||
(* points_func) (bezier_sel, gdk_points, index);
|
||||
(* points_func) (bezier_sel, gdk_points, index, udata);
|
||||
}
|
||||
|
||||
static void
|
||||
bezier_draw_segment_points (BezierSelect *bezier_sel,
|
||||
GdkPoint *points,
|
||||
int npoints)
|
||||
int npoints,
|
||||
gpointer udata)
|
||||
{
|
||||
gdk_draw_points (bezier_sel->core->win,
|
||||
bezier_sel->core->gc, points, npoints);
|
||||
|
@ -1388,7 +1418,8 @@ bezier_convert (BezierSelect *bezier_sel,
|
|||
do {
|
||||
bezier_draw_segment (bezier_sel, points,
|
||||
subdivisions, draw_type,
|
||||
bezier_convert_points);
|
||||
bezier_convert_points,
|
||||
NULL);
|
||||
|
||||
/* advance to the next segment */
|
||||
points = points->next;
|
||||
|
@ -1478,7 +1509,8 @@ bezier_convert (BezierSelect *bezier_sel,
|
|||
static void
|
||||
bezier_convert_points (BezierSelect *bezier_sel,
|
||||
GdkPoint *points,
|
||||
int npoints)
|
||||
int npoints,
|
||||
gpointer udata)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -1765,8 +1797,6 @@ test_add_point_on_segment (BezierSelect *bezier_sel,
|
|||
int halfwidth)
|
||||
|
||||
{
|
||||
#define ROUND(x) ((int) ((x) + 0.5))
|
||||
|
||||
BezierPoint *points;
|
||||
BezierMatrix geometry;
|
||||
BezierMatrix tmp1, tmp2;
|
||||
|
@ -2042,10 +2072,6 @@ void printSel( BezierSelect *sel)
|
|||
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. */
|
||||
static gboolean
|
||||
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,
|
||||
int start,
|
||||
int end,
|
||||
gdouble error)
|
||||
gdouble error,
|
||||
BezierRenderPnts *rpnts)
|
||||
{
|
||||
const gint expand_size = 32;
|
||||
gint med;
|
||||
gint offx, offy, l_offx, l_offy;
|
||||
|
||||
if (stroke_points == NULL)
|
||||
if (rpnts->stroke_points == NULL)
|
||||
return;
|
||||
|
||||
/* BASE CASE: stack the end point */
|
||||
if (end - start <= 1)
|
||||
{
|
||||
if ((stroke_points[num_stroke_points * 2 - 2] == points[end].x)
|
||||
&& (stroke_points[num_stroke_points * 2 - 1] == points[end].y))
|
||||
if ((rpnts->stroke_points[rpnts->num_stroke_points * 2 - 2] == points[end].x)
|
||||
&& (rpnts->stroke_points[rpnts->num_stroke_points * 2 - 1] == points[end].y))
|
||||
return;
|
||||
|
||||
num_stroke_points++;
|
||||
if (len_stroke_points <= num_stroke_points)
|
||||
rpnts->num_stroke_points++;
|
||||
if (rpnts->len_stroke_points <= rpnts->num_stroke_points)
|
||||
{
|
||||
len_stroke_points += expand_size;
|
||||
stroke_points = g_renew (double, stroke_points, 2 * len_stroke_points);
|
||||
if (stroke_points == NULL)
|
||||
rpnts->len_stroke_points += expand_size;
|
||||
rpnts->stroke_points = g_renew (double, rpnts->stroke_points, 2 * rpnts->len_stroke_points);
|
||||
if (rpnts->stroke_points == NULL)
|
||||
{
|
||||
len_stroke_points = num_stroke_points = 0;
|
||||
rpnts->len_stroke_points = rpnts->num_stroke_points = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
stroke_points[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 - 2] = points[end].x;
|
||||
rpnts->stroke_points[rpnts->num_stroke_points * 2 - 1] = points[end].y;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2125,7 +2152,7 @@ bezier_stack_points_aux (GdkPoint *points,
|
|||
gint 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;
|
||||
}
|
||||
/* 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))
|
||||
{
|
||||
bezier_stack_points_aux (points, start, med, error);
|
||||
bezier_stack_points_aux (points, med, end, error);
|
||||
bezier_stack_points_aux (points, start, med, error, rpnts);
|
||||
bezier_stack_points_aux (points, med, end, error, rpnts);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2148,33 +2175,35 @@ bezier_stack_points_aux (GdkPoint *points,
|
|||
|
||||
if (! stroke_interpolatable (offx, offy, l_offx, l_offy, error))
|
||||
{
|
||||
bezier_stack_points_aux (points, start, med, error);
|
||||
bezier_stack_points_aux (points, med, end, error);
|
||||
bezier_stack_points_aux (points, start, med, error, rpnts);
|
||||
bezier_stack_points_aux (points, med, end, error, rpnts);
|
||||
return;
|
||||
}
|
||||
/* Now, the curve can be represented by a points pair: (start, end).
|
||||
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
|
||||
bezier_stack_points (BezierSelect *bezier_sel,
|
||||
GdkPoint *points,
|
||||
int npoints)
|
||||
int npoints,
|
||||
gpointer udata)
|
||||
{
|
||||
gint i;
|
||||
gint expand_size = 32;
|
||||
gint minx, maxx, miny, maxy;
|
||||
gdouble error;
|
||||
BezierRenderPnts *rpnts = udata;
|
||||
|
||||
if (npoints < 2) /* Does this happen? */
|
||||
return;
|
||||
|
||||
if (stroke_points == NULL) /* initialize it here */
|
||||
if (rpnts->stroke_points == NULL) /* initialize it here */
|
||||
{
|
||||
num_stroke_points = 0;
|
||||
len_stroke_points = expand_size;
|
||||
stroke_points = g_new (double, 2 * len_stroke_points);
|
||||
rpnts->num_stroke_points = 0;
|
||||
rpnts->len_stroke_points = expand_size;
|
||||
rpnts->stroke_points = g_new (double, 2 * rpnts->len_stroke_points);
|
||||
}
|
||||
|
||||
maxx = minx = points[0].x;
|
||||
|
@ -2194,24 +2223,21 @@ bezier_stack_points (BezierSelect *bezier_sel,
|
|||
error = 2.0 / MAX(maxx - minx, maxy - miny);
|
||||
|
||||
/* add the start point */
|
||||
bezier_stack_points_aux (points, 0, 0, 0);
|
||||
bezier_stack_points_aux (points, 0, 0, 0, rpnts);
|
||||
|
||||
/* 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); */
|
||||
}
|
||||
|
||||
void
|
||||
bezier_stroke (BezierSelect *bezier_sel,
|
||||
GDisplay *gdisp,
|
||||
int subdivisions,
|
||||
int open_path)
|
||||
static gint
|
||||
bezier_gen_points(BezierSelect *bezier_sel,
|
||||
int open_path,
|
||||
BezierRenderPnts *rpnts)
|
||||
{
|
||||
BezierPoint * points;
|
||||
int num_points;
|
||||
Argument *return_vals;
|
||||
int nreturn_vals;
|
||||
int redraw = FALSE;
|
||||
|
||||
/* stack points */
|
||||
|
@ -2227,7 +2253,8 @@ bezier_stroke (BezierSelect *bezier_sel,
|
|||
do {
|
||||
bezier_draw_segment (bezier_sel, points,
|
||||
SUBDIVIDE, IMAGE_COORDS,
|
||||
bezier_stack_points);
|
||||
bezier_stack_points,
|
||||
(gpointer)rpnts);
|
||||
|
||||
points = points->next;
|
||||
points = points->next;
|
||||
|
@ -2245,7 +2272,8 @@ bezier_stroke (BezierSelect *bezier_sel,
|
|||
{
|
||||
bezier_draw_segment (bezier_sel, points,
|
||||
SUBDIVIDE, IMAGE_COORDS,
|
||||
bezier_stack_points);
|
||||
bezier_stack_points,
|
||||
(gpointer)rpnts);
|
||||
|
||||
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;
|
||||
int offset_x, offset_y;
|
||||
|
@ -2266,8 +2310,8 @@ bezier_stroke (BezierSelect *bezier_sel,
|
|||
{
|
||||
gdouble *ptr;
|
||||
|
||||
ptr = stroke_points;
|
||||
while (ptr < stroke_points + (num_stroke_points * 2))
|
||||
ptr = rpnts->stroke_points;
|
||||
while (ptr < rpnts->stroke_points + (rpnts->num_stroke_points * 2))
|
||||
{
|
||||
*ptr++ -= offset_x;
|
||||
*ptr++ -= offset_y;
|
||||
|
@ -2278,8 +2322,8 @@ bezier_stroke (BezierSelect *bezier_sel,
|
|||
&nreturn_vals,
|
||||
PDB_DRAWABLE, drawable_ID (drawable),
|
||||
PDB_FLOAT, (gdouble) 0,
|
||||
PDB_INT32, (gint32) num_stroke_points * 2,
|
||||
PDB_FLOATARRAY, stroke_points,
|
||||
PDB_INT32, (gint32) rpnts->num_stroke_points * 2,
|
||||
PDB_FLOATARRAY, rpnts->stroke_points,
|
||||
PDB_END);
|
||||
|
||||
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);
|
||||
|
||||
g_free (stroke_points);
|
||||
g_free (rpnts->stroke_points);
|
||||
}
|
||||
/* printf ("num_stroke_points: %d\ndone.\n", num_stroke_points); */
|
||||
|
||||
stroke_points = NULL;
|
||||
len_stroke_points = num_stroke_points = 0;
|
||||
rpnts->stroke_points = NULL;
|
||||
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 */
|
||||
};
|
||||
|
||||
typedef void (*BezierPointsFunc) (BezierSelect *, GdkPoint *, int);
|
||||
typedef void (*BezierPointsFunc) (BezierSelect *, GdkPoint *, int,gpointer);
|
||||
|
||||
/* Functions */
|
||||
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_add_point (BezierSelect *, int, int, int);
|
||||
void bezier_paste_bezierselect_to_current (GDisplay *,BezierSelect *);
|
||||
void bezier_select_mode (gint);
|
||||
void bezier_stroke (BezierSelect *, GDisplay *, int, int);
|
||||
void bezier_to_selection (BezierSelect *, GDisplay *);
|
||||
|
||||
gint bezier_distance_along (BezierSelect *, gint, gdouble,gint *,gint *,gdouble *);
|
||||
|
||||
#endif /* __BEZIER_SELECTP_H__ */
|
||||
|
|
|
@ -85,6 +85,11 @@ void
|
|||
grab_and_scroll (GDisplay *gdisp,
|
||||
GdkEventMotion *mevent)
|
||||
{
|
||||
if(mevent && mevent->window != gdisp->canvas->window)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
scroll_display (gdisp, (startx - mevent->x - gdisp->offset_x),
|
||||
(starty - mevent->y - gdisp->offset_y));
|
||||
}
|
||||
|
|
|
@ -85,6 +85,11 @@ void
|
|||
grab_and_scroll (GDisplay *gdisp,
|
||||
GdkEventMotion *mevent)
|
||||
{
|
||||
if(mevent && mevent->window != gdisp->canvas->window)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
scroll_display (gdisp, (startx - mevent->x - gdisp->offset_x),
|
||||
(starty - mevent->y - gdisp->offset_y));
|
||||
}
|
||||
|
|
|
@ -102,6 +102,8 @@ typedef struct {
|
|||
PATHP bzp;
|
||||
} PATHWIDGET, *PATHWIDGETP;
|
||||
|
||||
static gchar * unique_name(gchar *);
|
||||
|
||||
static gint path_widget_preview_events (GtkWidget *, GdkEvent *);
|
||||
static void paths_dialog_realized (GtkWidget *widget);
|
||||
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
|
||||
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);
|
||||
gchar *suniq;
|
||||
|
||||
g_string_sprintf (s, "path %d",name_seed);
|
||||
|
||||
bzp->pathtype = BEZIER;
|
||||
bzp->name = s;
|
||||
bzp->path_details = (GSList *)udata; /* If called via button/menu this will be NULL */
|
||||
suniq = unique_name(s->str);
|
||||
if(suniq)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -493,7 +500,7 @@ unique_name(gchar *cstr)
|
|||
}
|
||||
|
||||
static PATHP
|
||||
path_copy(PATHP p)
|
||||
path_copy(GimpImage *gimage,PATHP p)
|
||||
{
|
||||
PATHP p_copy = g_new0(PATH,1);
|
||||
gchar *ext;
|
||||
|
@ -505,7 +512,7 @@ path_copy(PATHP p)
|
|||
p_copy->state = p->state;
|
||||
p_copy->pathtype = p->pathtype;
|
||||
p_copy->path_details = pathpoints_copy(p->path_details);
|
||||
|
||||
p_copy->tattoo = gimp_image_get_new_tattoo(gimage);
|
||||
return p_copy;
|
||||
}
|
||||
|
||||
|
@ -1148,7 +1155,7 @@ static PATHP
|
|||
paths_dialog_new_path(PATHIMAGELISTP *plp,gpointer points,GimpImage *gimage,gint pos)
|
||||
{
|
||||
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);
|
||||
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);
|
||||
|
||||
/* 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);
|
||||
paths_add_path(bzp,row);
|
||||
|
||||
|
@ -1277,7 +1284,7 @@ paths_dialog_path_to_sel_callback (GtkWidget * widget, gpointer udata)
|
|||
|
||||
if(!bzp->closed)
|
||||
{
|
||||
PATHP bzpcopy = path_copy(bzp);
|
||||
PATHP bzpcopy = path_copy(paths_dialog->gimage,bzp);
|
||||
/* Close it */
|
||||
path_close(bzpcopy);
|
||||
bezier_sel = path_to_beziersel(bzpcopy);
|
||||
|
@ -1450,7 +1457,8 @@ paths_replaced_current(PATHIMAGELISTP plp,BezierSelect *bezier_sel)
|
|||
static void
|
||||
paths_draw_segment_points(BezierSelect *bezier_sel,
|
||||
GdkPoint *pnt,
|
||||
int npoints)
|
||||
int npoints,
|
||||
gpointer udata)
|
||||
{
|
||||
/*
|
||||
* 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);
|
||||
|
||||
/* 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 */
|
||||
|
||||
|
@ -1661,11 +1669,13 @@ pathpoint_new(gint type,
|
|||
}
|
||||
|
||||
PATHP
|
||||
path_new(PathType ptype,
|
||||
path_new(GimpImage *gimage,
|
||||
PathType ptype,
|
||||
GSList *path_details,
|
||||
gint closed,
|
||||
gint state,
|
||||
gint locked,
|
||||
gint tattoo,
|
||||
gchar *name)
|
||||
{
|
||||
PATHP path = g_new0(PATH,1);
|
||||
|
@ -1676,6 +1686,10 @@ path_new(PathType ptype,
|
|||
path->locked = locked;
|
||||
path->name = g_string_new(name);
|
||||
path->pathtype = ptype;
|
||||
if(tattoo)
|
||||
path->tattoo = tattoo;
|
||||
else
|
||||
path->tattoo = gimp_image_get_new_tattoo(gimage);
|
||||
|
||||
return path;
|
||||
}
|
||||
|
@ -1789,11 +1803,13 @@ static void file_ok_callback(GtkWidget * widget, gpointer client_data)
|
|||
pts_list = g_slist_append(pts_list,bpt);
|
||||
}
|
||||
|
||||
bzpath = path_new(BEZIER,
|
||||
bzpath = path_new(paths_dialog->gimage,
|
||||
BEZIER,
|
||||
pts_list,
|
||||
closed,
|
||||
state,
|
||||
0, /* Can't be locked */
|
||||
0, /* No tattoo assigned */
|
||||
txt);
|
||||
|
||||
g_free(txtstart);
|
||||
|
@ -2027,11 +2043,13 @@ paths_set_path_points(GimpImage * gimage,
|
|||
{
|
||||
GSList *bzp_list = NULL;
|
||||
/* No paths at all.... create one & rename */
|
||||
bzpath = path_new(ptype,
|
||||
bzpath = path_new(gimage,
|
||||
ptype,
|
||||
pts_list,
|
||||
pclosed,
|
||||
(pclosed)?BEZIER_EDIT:BEZIER_ADD,/*state,*/
|
||||
0, /* Can't be locked */
|
||||
0, /* No tattoo assigned */
|
||||
pname);
|
||||
bzp_list = g_slist_append(bzp_list,bzpath);
|
||||
plist = pathsList_new(gimage,0,bzp_list);
|
||||
|
@ -2075,11 +2093,13 @@ paths_set_path_points(GimpImage * gimage,
|
|||
}
|
||||
else
|
||||
{
|
||||
bzpath = path_new(ptype,
|
||||
bzpath = path_new(gimage,
|
||||
ptype,
|
||||
pts_list,
|
||||
pclosed,
|
||||
(pclosed)?BEZIER_EDIT:BEZIER_ADD,/*state,*/
|
||||
0, /* Can't be locked */
|
||||
0, /* No tattoo assigned */
|
||||
pname);
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
if(mevent && mevent->window != gdisp->canvas->window)
|
||||
{
|
||||
private->guide->position = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (mevent)
|
||||
{
|
||||
gdisplay_untransform_coords (gdisp, mevent->x, mevent->y,
|
||||
|
|
|
@ -34,6 +34,7 @@ typedef struct {
|
|||
gboolean closed;
|
||||
guint32 state;
|
||||
guint32 locked; /* Only bottom bit used */
|
||||
Tattoo tattoo; /* The tattoo for the path */
|
||||
GString * name;
|
||||
} PATH, *PATHP;
|
||||
|
||||
|
@ -58,11 +59,14 @@ typedef enum {
|
|||
} PathType;
|
||||
|
||||
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 *);
|
||||
gboolean paths_set_path(GimpImage *,gchar *);
|
||||
gboolean paths_set_path_points(GimpImage *,gchar *,gint,gint,gint,gdouble *);
|
||||
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__ */
|
||||
|
|
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_points_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
|
||||
register_paths_procs (void)
|
||||
|
@ -39,6 +42,9 @@ register_paths_procs (void)
|
|||
procedural_db_register (&path_set_current_proc);
|
||||
procedural_db_register (&path_set_points_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 *
|
||||
|
@ -525,3 +531,278 @@ static ProcRecord path_stroke_current_proc =
|
|||
NULL,
|
||||
{ { 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;
|
||||
} PATHWIDGET, *PATHWIDGETP;
|
||||
|
||||
static gchar * unique_name(gchar *);
|
||||
|
||||
static gint path_widget_preview_events (GtkWidget *, GdkEvent *);
|
||||
static void paths_dialog_realized (GtkWidget *widget);
|
||||
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
|
||||
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);
|
||||
gchar *suniq;
|
||||
|
||||
g_string_sprintf (s, "path %d",name_seed);
|
||||
|
||||
bzp->pathtype = BEZIER;
|
||||
bzp->name = s;
|
||||
bzp->path_details = (GSList *)udata; /* If called via button/menu this will be NULL */
|
||||
suniq = unique_name(s->str);
|
||||
if(suniq)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -493,7 +500,7 @@ unique_name(gchar *cstr)
|
|||
}
|
||||
|
||||
static PATHP
|
||||
path_copy(PATHP p)
|
||||
path_copy(GimpImage *gimage,PATHP p)
|
||||
{
|
||||
PATHP p_copy = g_new0(PATH,1);
|
||||
gchar *ext;
|
||||
|
@ -505,7 +512,7 @@ path_copy(PATHP p)
|
|||
p_copy->state = p->state;
|
||||
p_copy->pathtype = p->pathtype;
|
||||
p_copy->path_details = pathpoints_copy(p->path_details);
|
||||
|
||||
p_copy->tattoo = gimp_image_get_new_tattoo(gimage);
|
||||
return p_copy;
|
||||
}
|
||||
|
||||
|
@ -1148,7 +1155,7 @@ static PATHP
|
|||
paths_dialog_new_path(PATHIMAGELISTP *plp,gpointer points,GimpImage *gimage,gint pos)
|
||||
{
|
||||
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);
|
||||
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);
|
||||
|
||||
/* 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);
|
||||
paths_add_path(bzp,row);
|
||||
|
||||
|
@ -1277,7 +1284,7 @@ paths_dialog_path_to_sel_callback (GtkWidget * widget, gpointer udata)
|
|||
|
||||
if(!bzp->closed)
|
||||
{
|
||||
PATHP bzpcopy = path_copy(bzp);
|
||||
PATHP bzpcopy = path_copy(paths_dialog->gimage,bzp);
|
||||
/* Close it */
|
||||
path_close(bzpcopy);
|
||||
bezier_sel = path_to_beziersel(bzpcopy);
|
||||
|
@ -1450,7 +1457,8 @@ paths_replaced_current(PATHIMAGELISTP plp,BezierSelect *bezier_sel)
|
|||
static void
|
||||
paths_draw_segment_points(BezierSelect *bezier_sel,
|
||||
GdkPoint *pnt,
|
||||
int npoints)
|
||||
int npoints,
|
||||
gpointer udata)
|
||||
{
|
||||
/*
|
||||
* 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);
|
||||
|
||||
/* 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 */
|
||||
|
||||
|
@ -1661,11 +1669,13 @@ pathpoint_new(gint type,
|
|||
}
|
||||
|
||||
PATHP
|
||||
path_new(PathType ptype,
|
||||
path_new(GimpImage *gimage,
|
||||
PathType ptype,
|
||||
GSList *path_details,
|
||||
gint closed,
|
||||
gint state,
|
||||
gint locked,
|
||||
gint tattoo,
|
||||
gchar *name)
|
||||
{
|
||||
PATHP path = g_new0(PATH,1);
|
||||
|
@ -1676,6 +1686,10 @@ path_new(PathType ptype,
|
|||
path->locked = locked;
|
||||
path->name = g_string_new(name);
|
||||
path->pathtype = ptype;
|
||||
if(tattoo)
|
||||
path->tattoo = tattoo;
|
||||
else
|
||||
path->tattoo = gimp_image_get_new_tattoo(gimage);
|
||||
|
||||
return path;
|
||||
}
|
||||
|
@ -1789,11 +1803,13 @@ static void file_ok_callback(GtkWidget * widget, gpointer client_data)
|
|||
pts_list = g_slist_append(pts_list,bpt);
|
||||
}
|
||||
|
||||
bzpath = path_new(BEZIER,
|
||||
bzpath = path_new(paths_dialog->gimage,
|
||||
BEZIER,
|
||||
pts_list,
|
||||
closed,
|
||||
state,
|
||||
0, /* Can't be locked */
|
||||
0, /* No tattoo assigned */
|
||||
txt);
|
||||
|
||||
g_free(txtstart);
|
||||
|
@ -2027,11 +2043,13 @@ paths_set_path_points(GimpImage * gimage,
|
|||
{
|
||||
GSList *bzp_list = NULL;
|
||||
/* No paths at all.... create one & rename */
|
||||
bzpath = path_new(ptype,
|
||||
bzpath = path_new(gimage,
|
||||
ptype,
|
||||
pts_list,
|
||||
pclosed,
|
||||
(pclosed)?BEZIER_EDIT:BEZIER_ADD,/*state,*/
|
||||
0, /* Can't be locked */
|
||||
0, /* No tattoo assigned */
|
||||
pname);
|
||||
bzp_list = g_slist_append(bzp_list,bzpath);
|
||||
plist = pathsList_new(gimage,0,bzp_list);
|
||||
|
@ -2075,11 +2093,13 @@ paths_set_path_points(GimpImage * gimage,
|
|||
}
|
||||
else
|
||||
{
|
||||
bzpath = path_new(ptype,
|
||||
bzpath = path_new(gimage,
|
||||
ptype,
|
||||
pts_list,
|
||||
pclosed,
|
||||
(pclosed)?BEZIER_EDIT:BEZIER_ADD,/*state,*/
|
||||
0, /* Can't be locked */
|
||||
0, /* No tattoo assigned */
|
||||
pname);
|
||||
|
||||
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);
|
||||
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,
|
||||
GdkEventMotion *mevent)
|
||||
{
|
||||
if(mevent && mevent->window != gdisp->canvas->window)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
scroll_display (gdisp, (startx - mevent->x - gdisp->offset_x),
|
||||
(starty - mevent->y - gdisp->offset_y));
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "appenv.h"
|
||||
#include "draw_core.h"
|
||||
#include "edit_selection.h"
|
||||
|
@ -61,6 +62,8 @@
|
|||
#define NO 0
|
||||
#define YES 1
|
||||
|
||||
#define ROUND(x) ((int) ((x) + 0.5))
|
||||
|
||||
/* bezier select type definitions */
|
||||
|
||||
typedef double BezierMatrix[4][4];
|
||||
|
@ -84,6 +87,24 @@ struct _named_buffer
|
|||
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_release (Tool *, GdkEventButton *, 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_point (BezierSelect *, BezierPoint *, int);
|
||||
static void bezier_draw_line (BezierSelect *, BezierPoint *, BezierPoint *);
|
||||
static void bezier_draw_segment (BezierSelect *, BezierPoint *, int, int, BezierPointsFunc);
|
||||
static void bezier_draw_segment_points (BezierSelect *, GdkPoint *, int);
|
||||
static void bezier_draw_segment (BezierSelect *, BezierPoint *, int, int, BezierPointsFunc,gpointer);
|
||||
static void bezier_draw_segment_points (BezierSelect *, GdkPoint *, int, gpointer);
|
||||
static void bezier_compose (BezierMatrix, BezierMatrix, BezierMatrix);
|
||||
|
||||
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 GSList * bezier_insert_in_list (GSList *, 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_stack_points (BezierSelect *, GdkPoint *, int);
|
||||
static void bezier_stack_points (BezierSelect *, GdkPoint *, int, gpointer);
|
||||
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 =
|
||||
{
|
||||
|
@ -233,7 +254,10 @@ bezier_select_load (void *gdisp_ptr,
|
|||
}
|
||||
|
||||
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 * start_pt;
|
||||
|
@ -248,7 +272,8 @@ bezier_draw_curve (BezierSelect *bezier_sel,BezierPointsFunc func, gint coord)
|
|||
do {
|
||||
bezier_draw_segment (bezier_sel, points,
|
||||
SUBDIVIDE, coord,
|
||||
func);
|
||||
func,
|
||||
udata);
|
||||
|
||||
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,
|
||||
SUBDIVIDE, coord,
|
||||
func);
|
||||
func,
|
||||
udata);
|
||||
|
||||
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,
|
||||
points,
|
||||
SUBDIVIDE,
|
||||
SCREEN_COORDS,
|
||||
IMAGE_COORDS,
|
||||
x, y,
|
||||
halfwidth))
|
||||
{
|
||||
|
@ -953,7 +979,7 @@ bezier_select_draw (Tool *tool)
|
|||
}
|
||||
|
||||
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)
|
||||
bezier_draw_handles (bezier_sel);
|
||||
if (draw_current)
|
||||
|
@ -1082,7 +1108,8 @@ bezier_draw_current (BezierSelect *bezier_sel)
|
|||
if (points)
|
||||
bezier_draw_segment (bezier_sel, points,
|
||||
SUBDIVIDE, SCREEN_COORDS,
|
||||
bezier_draw_segment_points);
|
||||
bezier_draw_segment_points,
|
||||
NULL);
|
||||
|
||||
if (points != bezier_sel->cur_anchor)
|
||||
{
|
||||
|
@ -1095,7 +1122,8 @@ bezier_draw_current (BezierSelect *bezier_sel)
|
|||
if (points)
|
||||
bezier_draw_segment (bezier_sel, bezier_sel->cur_anchor,
|
||||
SUBDIVIDE, SCREEN_COORDS,
|
||||
bezier_draw_segment_points);
|
||||
bezier_draw_segment_points,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1158,7 +1186,8 @@ bezier_draw_segment (BezierSelect *bezier_sel,
|
|||
BezierPoint *points,
|
||||
int subdivisions,
|
||||
int space,
|
||||
BezierPointsFunc points_func)
|
||||
BezierPointsFunc points_func,
|
||||
gpointer udata)
|
||||
{
|
||||
#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 (index >= npoints)
|
||||
{
|
||||
(* points_func) (bezier_sel, gdk_points, index);
|
||||
(* points_func) (bezier_sel, gdk_points, index, udata);
|
||||
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 (index)
|
||||
(* points_func) (bezier_sel, gdk_points, index);
|
||||
(* points_func) (bezier_sel, gdk_points, index, udata);
|
||||
}
|
||||
|
||||
static void
|
||||
bezier_draw_segment_points (BezierSelect *bezier_sel,
|
||||
GdkPoint *points,
|
||||
int npoints)
|
||||
int npoints,
|
||||
gpointer udata)
|
||||
{
|
||||
gdk_draw_points (bezier_sel->core->win,
|
||||
bezier_sel->core->gc, points, npoints);
|
||||
|
@ -1388,7 +1418,8 @@ bezier_convert (BezierSelect *bezier_sel,
|
|||
do {
|
||||
bezier_draw_segment (bezier_sel, points,
|
||||
subdivisions, draw_type,
|
||||
bezier_convert_points);
|
||||
bezier_convert_points,
|
||||
NULL);
|
||||
|
||||
/* advance to the next segment */
|
||||
points = points->next;
|
||||
|
@ -1478,7 +1509,8 @@ bezier_convert (BezierSelect *bezier_sel,
|
|||
static void
|
||||
bezier_convert_points (BezierSelect *bezier_sel,
|
||||
GdkPoint *points,
|
||||
int npoints)
|
||||
int npoints,
|
||||
gpointer udata)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -1765,8 +1797,6 @@ test_add_point_on_segment (BezierSelect *bezier_sel,
|
|||
int halfwidth)
|
||||
|
||||
{
|
||||
#define ROUND(x) ((int) ((x) + 0.5))
|
||||
|
||||
BezierPoint *points;
|
||||
BezierMatrix geometry;
|
||||
BezierMatrix tmp1, tmp2;
|
||||
|
@ -2042,10 +2072,6 @@ void printSel( BezierSelect *sel)
|
|||
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. */
|
||||
static gboolean
|
||||
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,
|
||||
int start,
|
||||
int end,
|
||||
gdouble error)
|
||||
gdouble error,
|
||||
BezierRenderPnts *rpnts)
|
||||
{
|
||||
const gint expand_size = 32;
|
||||
gint med;
|
||||
gint offx, offy, l_offx, l_offy;
|
||||
|
||||
if (stroke_points == NULL)
|
||||
if (rpnts->stroke_points == NULL)
|
||||
return;
|
||||
|
||||
/* BASE CASE: stack the end point */
|
||||
if (end - start <= 1)
|
||||
{
|
||||
if ((stroke_points[num_stroke_points * 2 - 2] == points[end].x)
|
||||
&& (stroke_points[num_stroke_points * 2 - 1] == points[end].y))
|
||||
if ((rpnts->stroke_points[rpnts->num_stroke_points * 2 - 2] == points[end].x)
|
||||
&& (rpnts->stroke_points[rpnts->num_stroke_points * 2 - 1] == points[end].y))
|
||||
return;
|
||||
|
||||
num_stroke_points++;
|
||||
if (len_stroke_points <= num_stroke_points)
|
||||
rpnts->num_stroke_points++;
|
||||
if (rpnts->len_stroke_points <= rpnts->num_stroke_points)
|
||||
{
|
||||
len_stroke_points += expand_size;
|
||||
stroke_points = g_renew (double, stroke_points, 2 * len_stroke_points);
|
||||
if (stroke_points == NULL)
|
||||
rpnts->len_stroke_points += expand_size;
|
||||
rpnts->stroke_points = g_renew (double, rpnts->stroke_points, 2 * rpnts->len_stroke_points);
|
||||
if (rpnts->stroke_points == NULL)
|
||||
{
|
||||
len_stroke_points = num_stroke_points = 0;
|
||||
rpnts->len_stroke_points = rpnts->num_stroke_points = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
stroke_points[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 - 2] = points[end].x;
|
||||
rpnts->stroke_points[rpnts->num_stroke_points * 2 - 1] = points[end].y;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2125,7 +2152,7 @@ bezier_stack_points_aux (GdkPoint *points,
|
|||
gint 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;
|
||||
}
|
||||
/* 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))
|
||||
{
|
||||
bezier_stack_points_aux (points, start, med, error);
|
||||
bezier_stack_points_aux (points, med, end, error);
|
||||
bezier_stack_points_aux (points, start, med, error, rpnts);
|
||||
bezier_stack_points_aux (points, med, end, error, rpnts);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2148,33 +2175,35 @@ bezier_stack_points_aux (GdkPoint *points,
|
|||
|
||||
if (! stroke_interpolatable (offx, offy, l_offx, l_offy, error))
|
||||
{
|
||||
bezier_stack_points_aux (points, start, med, error);
|
||||
bezier_stack_points_aux (points, med, end, error);
|
||||
bezier_stack_points_aux (points, start, med, error, rpnts);
|
||||
bezier_stack_points_aux (points, med, end, error, rpnts);
|
||||
return;
|
||||
}
|
||||
/* Now, the curve can be represented by a points pair: (start, end).
|
||||
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
|
||||
bezier_stack_points (BezierSelect *bezier_sel,
|
||||
GdkPoint *points,
|
||||
int npoints)
|
||||
int npoints,
|
||||
gpointer udata)
|
||||
{
|
||||
gint i;
|
||||
gint expand_size = 32;
|
||||
gint minx, maxx, miny, maxy;
|
||||
gdouble error;
|
||||
BezierRenderPnts *rpnts = udata;
|
||||
|
||||
if (npoints < 2) /* Does this happen? */
|
||||
return;
|
||||
|
||||
if (stroke_points == NULL) /* initialize it here */
|
||||
if (rpnts->stroke_points == NULL) /* initialize it here */
|
||||
{
|
||||
num_stroke_points = 0;
|
||||
len_stroke_points = expand_size;
|
||||
stroke_points = g_new (double, 2 * len_stroke_points);
|
||||
rpnts->num_stroke_points = 0;
|
||||
rpnts->len_stroke_points = expand_size;
|
||||
rpnts->stroke_points = g_new (double, 2 * rpnts->len_stroke_points);
|
||||
}
|
||||
|
||||
maxx = minx = points[0].x;
|
||||
|
@ -2194,24 +2223,21 @@ bezier_stack_points (BezierSelect *bezier_sel,
|
|||
error = 2.0 / MAX(maxx - minx, maxy - miny);
|
||||
|
||||
/* add the start point */
|
||||
bezier_stack_points_aux (points, 0, 0, 0);
|
||||
bezier_stack_points_aux (points, 0, 0, 0, rpnts);
|
||||
|
||||
/* 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); */
|
||||
}
|
||||
|
||||
void
|
||||
bezier_stroke (BezierSelect *bezier_sel,
|
||||
GDisplay *gdisp,
|
||||
int subdivisions,
|
||||
int open_path)
|
||||
static gint
|
||||
bezier_gen_points(BezierSelect *bezier_sel,
|
||||
int open_path,
|
||||
BezierRenderPnts *rpnts)
|
||||
{
|
||||
BezierPoint * points;
|
||||
int num_points;
|
||||
Argument *return_vals;
|
||||
int nreturn_vals;
|
||||
int redraw = FALSE;
|
||||
|
||||
/* stack points */
|
||||
|
@ -2227,7 +2253,8 @@ bezier_stroke (BezierSelect *bezier_sel,
|
|||
do {
|
||||
bezier_draw_segment (bezier_sel, points,
|
||||
SUBDIVIDE, IMAGE_COORDS,
|
||||
bezier_stack_points);
|
||||
bezier_stack_points,
|
||||
(gpointer)rpnts);
|
||||
|
||||
points = points->next;
|
||||
points = points->next;
|
||||
|
@ -2245,7 +2272,8 @@ bezier_stroke (BezierSelect *bezier_sel,
|
|||
{
|
||||
bezier_draw_segment (bezier_sel, points,
|
||||
SUBDIVIDE, IMAGE_COORDS,
|
||||
bezier_stack_points);
|
||||
bezier_stack_points,
|
||||
(gpointer)rpnts);
|
||||
|
||||
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;
|
||||
int offset_x, offset_y;
|
||||
|
@ -2266,8 +2310,8 @@ bezier_stroke (BezierSelect *bezier_sel,
|
|||
{
|
||||
gdouble *ptr;
|
||||
|
||||
ptr = stroke_points;
|
||||
while (ptr < stroke_points + (num_stroke_points * 2))
|
||||
ptr = rpnts->stroke_points;
|
||||
while (ptr < rpnts->stroke_points + (rpnts->num_stroke_points * 2))
|
||||
{
|
||||
*ptr++ -= offset_x;
|
||||
*ptr++ -= offset_y;
|
||||
|
@ -2278,8 +2322,8 @@ bezier_stroke (BezierSelect *bezier_sel,
|
|||
&nreturn_vals,
|
||||
PDB_DRAWABLE, drawable_ID (drawable),
|
||||
PDB_FLOAT, (gdouble) 0,
|
||||
PDB_INT32, (gint32) num_stroke_points * 2,
|
||||
PDB_FLOATARRAY, stroke_points,
|
||||
PDB_INT32, (gint32) rpnts->num_stroke_points * 2,
|
||||
PDB_FLOATARRAY, rpnts->stroke_points,
|
||||
PDB_END);
|
||||
|
||||
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);
|
||||
|
||||
g_free (stroke_points);
|
||||
g_free (rpnts->stroke_points);
|
||||
}
|
||||
/* printf ("num_stroke_points: %d\ndone.\n", num_stroke_points); */
|
||||
|
||||
stroke_points = NULL;
|
||||
len_stroke_points = num_stroke_points = 0;
|
||||
rpnts->stroke_points = NULL;
|
||||
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 */
|
||||
};
|
||||
|
||||
typedef void (*BezierPointsFunc) (BezierSelect *, GdkPoint *, int);
|
||||
typedef void (*BezierPointsFunc) (BezierSelect *, GdkPoint *, int,gpointer);
|
||||
|
||||
/* Functions */
|
||||
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_add_point (BezierSelect *, int, int, int);
|
||||
void bezier_paste_bezierselect_to_current (GDisplay *,BezierSelect *);
|
||||
void bezier_select_mode (gint);
|
||||
void bezier_stroke (BezierSelect *, GDisplay *, int, int);
|
||||
void bezier_to_selection (BezierSelect *, GDisplay *);
|
||||
|
||||
gint bezier_distance_along (BezierSelect *, gint, gdouble,gint *,gint *,gdouble *);
|
||||
|
||||
#endif /* __BEZIER_SELECTP_H__ */
|
||||
|
|
|
@ -263,6 +263,12 @@ move_tool_motion (Tool *tool,
|
|||
{
|
||||
move_draw_guide (gdisp, private->guide);
|
||||
|
||||
if(mevent && mevent->window != gdisp->canvas->window)
|
||||
{
|
||||
private->guide->position = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (mevent)
|
||||
{
|
||||
gdisplay_untransform_coords (gdisp, mevent->x, mevent->y,
|
||||
|
|
|
@ -263,6 +263,12 @@ move_tool_motion (Tool *tool,
|
|||
{
|
||||
move_draw_guide (gdisp, private->guide);
|
||||
|
||||
if(mevent && mevent->window != gdisp->canvas->window)
|
||||
{
|
||||
private->guide->position = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (mevent)
|
||||
{
|
||||
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);
|
||||
num_points = g_slist_length(bzp->path_details);
|
||||
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, &bzp->pathtype,1);
|
||||
info->cp += xcf_write_int32(info->fp, &bzp->tattoo,1);
|
||||
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;
|
||||
gchar *name;
|
||||
|
@ -792,6 +793,7 @@ static PATHP read_one_path(XcfInfo *info)
|
|||
guint32 closed;
|
||||
guint32 num_points;
|
||||
guint32 version; /* changed from num_paths */
|
||||
Tattoo tattoo = 0;
|
||||
GSList *pts_list = NULL;
|
||||
PathType ptype;
|
||||
|
||||
|
@ -825,12 +827,25 @@ static PATHP read_one_path(XcfInfo *info)
|
|||
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
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
@ -866,7 +881,7 @@ static PathsList * read_bzpaths(GImage *gimage, XcfInfo *info)
|
|||
{
|
||||
PATHP bzp;
|
||||
/* Read in a path */
|
||||
bzp = read_one_path(info);
|
||||
bzp = read_one_path(gimage,info);
|
||||
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);
|
||||
num_points = g_slist_length(bzp->path_details);
|
||||
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, &bzp->pathtype,1);
|
||||
info->cp += xcf_write_int32(info->fp, &bzp->tattoo,1);
|
||||
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;
|
||||
gchar *name;
|
||||
|
@ -792,6 +793,7 @@ static PATHP read_one_path(XcfInfo *info)
|
|||
guint32 closed;
|
||||
guint32 num_points;
|
||||
guint32 version; /* changed from num_paths */
|
||||
Tattoo tattoo = 0;
|
||||
GSList *pts_list = NULL;
|
||||
PathType ptype;
|
||||
|
||||
|
@ -825,12 +827,25 @@ static PATHP read_one_path(XcfInfo *info)
|
|||
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
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
@ -866,7 +881,7 @@ static PathsList * read_bzpaths(GImage *gimage, XcfInfo *info)
|
|||
{
|
||||
PATHP bzp;
|
||||
/* Read in a path */
|
||||
bzp = read_one_path(info);
|
||||
bzp = read_one_path(gimage,info);
|
||||
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");
|
||||
|
||||
@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]);
|
||||
|
||||
$desc = 'Paths';
|
||||
|
|
Loading…
Reference in New Issue