mirror of https://github.com/GNOME/gimp.git
657 lines
15 KiB
C
657 lines
15 KiB
C
/* The GIMP -- an image manipulation program
|
|
* Copyright (C) 1999 Andy Thomas alt@gimp.org
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
* Some of this code is based on the layers_dialog box code.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include "appenv.h"
|
|
#include "general.h"
|
|
#include "gimage.h"
|
|
#include "pathsP.h"
|
|
#include "paths_cmds.h"
|
|
|
|
#include "libgimp/gimpintl.h"
|
|
|
|
static int success;
|
|
|
|
/* These are the PDB functions that interact with the PATHS structures. */
|
|
|
|
/* List the paths that an image has */
|
|
|
|
static Argument *
|
|
path_list_invoker (Argument *args)
|
|
{
|
|
Argument *return_args;
|
|
gchar **paths_list;
|
|
gint num_paths;
|
|
GImage *gimage;
|
|
gint int_value;
|
|
|
|
gimage = NULL;
|
|
|
|
success = TRUE;
|
|
if (success)
|
|
{
|
|
int_value = args[0].value.pdb_int;
|
|
if ((gimage = gimage_get_ID (int_value)) == NULL)
|
|
success = FALSE;
|
|
}
|
|
|
|
return_args = procedural_db_return_args (&path_list_proc, success);
|
|
|
|
if (success)
|
|
{
|
|
PathsList *plist = gimage->paths;
|
|
|
|
if(plist && plist->bz_paths)
|
|
{
|
|
gint count = 0;
|
|
GSList *pl = plist->bz_paths;
|
|
|
|
num_paths = g_slist_length(plist->bz_paths);
|
|
return_args[1].value.pdb_int = num_paths;
|
|
|
|
paths_list = g_malloc(sizeof(gchar *) * num_paths);
|
|
while(pl)
|
|
{
|
|
PATHP pptr = pl->data;
|
|
paths_list[count++] = g_strdup(pptr->name->str);
|
|
pl = g_slist_next(pl);
|
|
}
|
|
return_args[2].value.pdb_pointer = paths_list;
|
|
}
|
|
else
|
|
{
|
|
return_args[1].value.pdb_int = 0;
|
|
return_args[2].value.pdb_pointer = NULL;
|
|
}
|
|
}
|
|
|
|
return return_args;
|
|
}
|
|
|
|
/* The procedure definition */
|
|
ProcArg path_list_in_args[] =
|
|
{
|
|
{ PDB_IMAGE,
|
|
"image",
|
|
"the image to list the paths from"
|
|
},
|
|
};
|
|
|
|
ProcArg path_list_out_args[] =
|
|
{
|
|
{ PDB_INT32,
|
|
"num_paths",
|
|
"The number of paths returned"
|
|
},
|
|
{ PDB_STRINGARRAY,
|
|
"paths_list",
|
|
"list of the paths belonging to this image"
|
|
}
|
|
};
|
|
|
|
ProcRecord path_list_proc =
|
|
{
|
|
"gimp_path_list",
|
|
"List the paths associated with the passed image",
|
|
"List the paths associated with the passed image",
|
|
"Andy Thomas",
|
|
"Andy Thomas",
|
|
"1999",
|
|
PDB_INTERNAL,
|
|
|
|
/* Input arguments */
|
|
sizeof(path_list_in_args)/sizeof(path_list_in_args[0]),
|
|
path_list_in_args,
|
|
|
|
/* Output arguments */
|
|
sizeof(path_list_out_args)/sizeof(path_list_out_args[0]),
|
|
path_list_out_args,
|
|
|
|
/* Exec method */
|
|
{ { path_list_invoker } },
|
|
};
|
|
|
|
/* Get the points the named path is composed of */
|
|
|
|
static Argument *
|
|
path_get_points_invoker (Argument *args)
|
|
{
|
|
Argument *return_args = NULL;
|
|
GImage *gimage;
|
|
gchar *pname;
|
|
gint int_value;
|
|
|
|
gimage = NULL;
|
|
|
|
success = TRUE;
|
|
int_value = args[0].value.pdb_int;
|
|
if ((gimage = gimage_get_ID (int_value)) == NULL)
|
|
success = FALSE;
|
|
|
|
if (success)
|
|
{
|
|
/* Get the path with the given name */
|
|
PathsList *plist = gimage->paths;
|
|
pname = args[1].value.pdb_pointer;
|
|
|
|
if(pname && plist && plist->bz_paths)
|
|
{
|
|
GSList *pl = plist->bz_paths;
|
|
PATHP pptr = NULL;
|
|
|
|
while(pl)
|
|
{
|
|
pptr = pl->data;
|
|
if(strcmp(pname,pptr->name->str) == 0)
|
|
{
|
|
/* Found the path */
|
|
break;
|
|
}
|
|
pl = g_slist_next(pl);
|
|
pptr = NULL;
|
|
}
|
|
|
|
if(pl && pptr)
|
|
{
|
|
gint num_pdetails;
|
|
gdouble *pnts;
|
|
GSList *points_list;
|
|
gint pcount = 0;
|
|
|
|
return_args = procedural_db_return_args (&path_get_points_proc, success);
|
|
/* Get the details for this path */
|
|
return_args[1].value.pdb_int = pptr->pathtype;
|
|
return_args[2].value.pdb_int = pptr->closed;
|
|
|
|
points_list = pptr->path_details;
|
|
if(points_list)
|
|
{
|
|
num_pdetails = g_slist_length(points_list);
|
|
return_args[3].value.pdb_int = num_pdetails*3; /* 3 floats for each point */
|
|
|
|
pnts = g_malloc(sizeof(gdouble)*3*num_pdetails);
|
|
|
|
/* fill points and types in */
|
|
while(points_list)
|
|
{
|
|
PATHPOINTP ppoint = points_list->data;
|
|
pnts[pcount] = ppoint->x;
|
|
pnts[pcount+1] = ppoint->y;
|
|
pnts[pcount+2] = (gfloat)ppoint->type; /* Bit of fiddle but should be understandable why it was done */
|
|
pcount += 3;
|
|
points_list = g_slist_next(points_list);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return_args[3].value.pdb_int = 0;
|
|
pnts = NULL;
|
|
}
|
|
|
|
return_args[4].value.pdb_pointer = pnts;
|
|
}
|
|
else
|
|
{
|
|
success = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
success = FALSE;
|
|
}
|
|
}
|
|
|
|
if(!success)
|
|
{
|
|
return_args = procedural_db_return_args (&path_get_points_proc, success);
|
|
}
|
|
|
|
return return_args;
|
|
}
|
|
|
|
/* The procedure definition */
|
|
ProcArg path_get_points_in_args[] =
|
|
{
|
|
{ PDB_IMAGE,
|
|
"image",
|
|
"the image to list the paths from"
|
|
},
|
|
{ PDB_STRING,
|
|
"pathname",
|
|
"the name of the path whose points should be listed"
|
|
},
|
|
};
|
|
|
|
ProcArg path_get_points_out_args[] =
|
|
{
|
|
{ PDB_INT32,
|
|
"paths_type",
|
|
"The type of the path. Currently only one type (1 = Bezier) is supported"
|
|
},
|
|
{ PDB_INT32,
|
|
"pathclosed",
|
|
"Return if the path is closed. {0=path open, 1= path closed}"
|
|
},
|
|
{ PDB_INT32,
|
|
"num_path_point_details",
|
|
"The number of point returned. Each point is made up of (x,y,pnt_type) of floats"
|
|
},
|
|
{ PDB_FLOATARRAY,
|
|
"points_pairs",
|
|
"The points in the path represented as 3 floats. The first is the x pos, next is the y pos, last is the type of the pnt. The type field is dependant on the path type. For beziers (type 1 paths) the type can either be {1.0= BEZIER_ANCHOR, 2.0= BEZIER_CONTROL}. Note all points are returned in pixel resolution"
|
|
}
|
|
};
|
|
|
|
ProcRecord path_get_points_proc =
|
|
{
|
|
"gimp_path_get_points",
|
|
"List the points associated with the named path",
|
|
"List the points associated with the named path",
|
|
"Andy Thomas",
|
|
"Andy Thomas",
|
|
"1999",
|
|
PDB_INTERNAL,
|
|
|
|
/* Input arguments */
|
|
sizeof(path_get_points_in_args)/sizeof(path_get_points_in_args[0]),
|
|
path_get_points_in_args,
|
|
|
|
/* Output arguments */
|
|
sizeof(path_get_points_out_args)/sizeof(path_get_points_out_args[0]),
|
|
path_get_points_out_args,
|
|
|
|
/* Exec method */
|
|
{ { path_get_points_invoker } },
|
|
};
|
|
|
|
/* Get the name of the current path (of the passed image) */
|
|
|
|
static Argument *
|
|
path_get_current_invoker (Argument *args)
|
|
{
|
|
Argument *return_args = NULL;
|
|
GImage *gimage;
|
|
gint int_value;
|
|
|
|
gimage = NULL;
|
|
|
|
success = TRUE;
|
|
int_value = args[0].value.pdb_int;
|
|
|
|
if ((gimage = gimage_get_ID (int_value)) == NULL)
|
|
success = FALSE;
|
|
|
|
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);
|
|
return_args = procedural_db_return_args (&path_get_current_proc, success);
|
|
return_args[1].value.pdb_pointer = g_strdup(pptr->name->str);
|
|
}
|
|
else
|
|
{
|
|
success = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
success = FALSE;
|
|
}
|
|
}
|
|
|
|
if(!success)
|
|
{
|
|
return_args = procedural_db_return_args (&path_get_points_proc, success);
|
|
}
|
|
|
|
return return_args;
|
|
}
|
|
|
|
/* The procedure definition */
|
|
ProcArg path_get_current_in_args[] =
|
|
{
|
|
{ PDB_IMAGE,
|
|
"image",
|
|
"the image to get the current paths from"
|
|
}
|
|
};
|
|
|
|
ProcArg path_get_current_out_args[] =
|
|
{
|
|
{ PDB_STRING,
|
|
"current_path_name",
|
|
"The name of the current path"
|
|
}
|
|
};
|
|
|
|
ProcRecord path_get_current_proc =
|
|
{
|
|
"gimp_path_get_current",
|
|
"The name of the current path. Error if no paths",
|
|
"The name of the current path. Error if no paths",
|
|
"Andy Thomas",
|
|
"Andy Thomas",
|
|
"1999",
|
|
PDB_INTERNAL,
|
|
|
|
/* Input arguments */
|
|
sizeof(path_get_current_in_args)/sizeof(path_get_current_in_args[0]),
|
|
path_get_current_in_args,
|
|
|
|
/* Output arguments */
|
|
sizeof(path_get_current_out_args)/sizeof(path_get_current_out_args[0]),
|
|
path_get_current_out_args,
|
|
|
|
/* Exec method */
|
|
{ { path_get_current_invoker } },
|
|
};
|
|
|
|
|
|
/* Set the name of the current path (of the passed image) */
|
|
|
|
static Argument *
|
|
path_set_current_invoker (Argument *args)
|
|
{
|
|
Argument *return_args = NULL;
|
|
GImage *gimage;
|
|
gint int_value;
|
|
gchar *pname;
|
|
|
|
gimage = NULL;
|
|
|
|
success = TRUE;
|
|
int_value = args[0].value.pdb_int;
|
|
|
|
if ((gimage = gimage_get_ID (int_value)) == NULL)
|
|
success = FALSE;
|
|
|
|
if (success)
|
|
{
|
|
/* Set the current path to the given name */
|
|
pname = args[1].value.pdb_pointer;
|
|
|
|
if(pname && paths_set_path(gimage,pname))
|
|
{
|
|
success = TRUE;
|
|
}
|
|
else
|
|
{
|
|
success = FALSE;
|
|
}
|
|
}
|
|
|
|
return_args = procedural_db_return_args (&path_set_current_proc, success);
|
|
|
|
return return_args;
|
|
}
|
|
|
|
/* The procedure definition */
|
|
ProcArg path_set_current_in_args[] =
|
|
{
|
|
{ PDB_IMAGE,
|
|
"image",
|
|
"the image to set the current paths"
|
|
},
|
|
{ PDB_STRING,
|
|
"set_current_path_name",
|
|
"The name of the path to set the current path to"
|
|
}
|
|
};
|
|
|
|
/* NO out args.. Either works or errors. */
|
|
|
|
ProcRecord path_set_current_proc =
|
|
{
|
|
"gimp_path_set_current",
|
|
"The name path to set to the current. Error if path does not exist.",
|
|
"The name path to set to the current. Error if path does not exist.",
|
|
"Andy Thomas",
|
|
"Andy Thomas",
|
|
"1999",
|
|
PDB_INTERNAL,
|
|
|
|
/* Input arguments */
|
|
sizeof(path_set_current_in_args)/sizeof(path_set_current_in_args[0]),
|
|
path_set_current_in_args,
|
|
|
|
/* Output arguments */
|
|
0,
|
|
NULL,
|
|
|
|
/* Exec method */
|
|
{ { path_set_current_invoker } },
|
|
};
|
|
|
|
|
|
/* Set a path up from the given points */
|
|
/* Currently only the creation of bezier curves is allowed.
|
|
* The type parameter must be set to (1) to indicate a BEZIER type curve.
|
|
*/
|
|
/* For BEZIERS..
|
|
*
|
|
* Note the that points must be given in the following order...
|
|
* ACCACCACC ...
|
|
* The last control point is missing for non closed curves.
|
|
*/
|
|
|
|
static Argument *
|
|
path_set_points_invoker (Argument *args)
|
|
{
|
|
Argument *return_args = NULL;
|
|
GImage *gimage;
|
|
gchar *pname;
|
|
gint int_value;
|
|
gint ptype;
|
|
gint numpoints;
|
|
gint pclosed = FALSE;
|
|
gdouble *pnts;
|
|
|
|
gimage = NULL;
|
|
|
|
success = TRUE;
|
|
int_value = args[0].value.pdb_int;
|
|
if ((gimage = gimage_get_ID (int_value)) == NULL)
|
|
success = FALSE;
|
|
|
|
if (success)
|
|
{
|
|
pname = args[1].value.pdb_pointer;
|
|
ptype = args[2].value.pdb_int;
|
|
numpoints = args[3].value.pdb_int;
|
|
|
|
if((numpoints/2)%3 == 0)
|
|
pclosed = TRUE;
|
|
else if ((numpoints/2)%3 != 2)
|
|
success = FALSE;
|
|
|
|
pnts = args[4].value.pdb_pointer;
|
|
}
|
|
|
|
if(success)
|
|
{
|
|
|
|
if(paths_set_path_points(gimage,pname,ptype,pclosed,numpoints,pnts))
|
|
return_args = procedural_db_return_args (&path_get_points_proc, success);
|
|
else
|
|
success = FALSE;
|
|
}
|
|
else
|
|
{
|
|
success = FALSE;
|
|
}
|
|
|
|
if(!success)
|
|
{
|
|
return_args = procedural_db_return_args (&path_get_points_proc, success);
|
|
}
|
|
|
|
return return_args;
|
|
}
|
|
|
|
/* The procedure definition */
|
|
ProcArg path_set_points_in_args[] =
|
|
{
|
|
{ PDB_IMAGE,
|
|
"image",
|
|
"the image to list the paths from"
|
|
},
|
|
{ PDB_STRING,
|
|
"pathname",
|
|
"the name of the path to create (if it exists then all current points are removed). This will not be set as the current path.You will have to do a gimp_set_current_path after creating the path to make it current."
|
|
},
|
|
{ PDB_INT32,
|
|
"path_type",
|
|
"The type of the path. Currently only one type (1 = Bezier) is supported"
|
|
},
|
|
{ PDB_INT32,
|
|
"num_path_points",
|
|
"The number of points in the path. Each point is made up of (x,y) of floats. "
|
|
"Currently only the creation of bezier curves is allowed. "
|
|
"The type parameter must be set to (1) to indicate a BEZIER type curve.\n"
|
|
"For BEZIERS.\n"
|
|
"Note the that points must be given in the following order... "
|
|
"ACCACCAC ... "
|
|
"If the path is not closed the last control point is missed off. "
|
|
"Points consist of three control points (control/anchor/control) "
|
|
"so for a curve that is not closed there must be at least two points passed (2 x,y pairs). "
|
|
"If num_path_pnts%3 = 0 then the path is assumed to be closed and the points are ACCACCACCACC."
|
|
},
|
|
{ PDB_FLOATARRAY,
|
|
"points_pairs",
|
|
"The points in the path represented as 2 floats. The first is the x pos, next is the y pos. The order of points define there types (see num_path_points comment)."
|
|
}
|
|
|
|
};
|
|
|
|
/* No Out args */
|
|
|
|
ProcRecord path_set_points_proc =
|
|
{
|
|
"gimp_path_set_points",
|
|
"Set the points associated with the named path",
|
|
"Set the points associated with the named path",
|
|
"Andy Thomas",
|
|
"Andy Thomas",
|
|
"1999",
|
|
PDB_INTERNAL,
|
|
|
|
/* Input arguments */
|
|
sizeof(path_set_points_in_args)/sizeof(path_set_points_in_args[0]),
|
|
path_set_points_in_args,
|
|
|
|
/* Output arguments */
|
|
0,
|
|
NULL,
|
|
|
|
/* Exec method */
|
|
{ { path_set_points_invoker } },
|
|
};
|
|
|
|
|
|
/* Stroke the current path */
|
|
/* Note it will ONLY do the current path.. */
|
|
|
|
static Argument *
|
|
path_stroke_current_invoker (Argument *args)
|
|
{
|
|
Argument *return_args = NULL;
|
|
GImage *gimage;
|
|
gint int_value;
|
|
|
|
gimage = NULL;
|
|
success = TRUE;
|
|
int_value = args[0].value.pdb_int;
|
|
|
|
if ((gimage = gimage_get_ID (int_value)) == NULL)
|
|
success = FALSE;
|
|
|
|
if (success)
|
|
{
|
|
/* Get the path with the given name */
|
|
PathsList *plist = gimage->paths;
|
|
|
|
if(plist && plist->bz_paths)
|
|
{
|
|
GSList *pl = 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)))
|
|
{
|
|
/* Found the path to stroke.. */
|
|
paths_stroke(gimage,plist,pptr);
|
|
}
|
|
else
|
|
{
|
|
success = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
success = FALSE;
|
|
}
|
|
}
|
|
|
|
return_args = procedural_db_return_args (&path_set_current_proc, success);
|
|
|
|
return return_args;
|
|
}
|
|
|
|
/* The procedure definition */
|
|
ProcArg path_stroke_current_in_args[] =
|
|
{
|
|
{ PDB_IMAGE,
|
|
"image",
|
|
"the image which contains the path to stroke"
|
|
},
|
|
};
|
|
|
|
/* NO out args.. Either works or errors. */
|
|
|
|
ProcRecord path_stroke_current_proc =
|
|
{
|
|
"gimp_path_stroke_current",
|
|
"Stroke the current path in the passed image",
|
|
"Stroke the current path in the passed image",
|
|
"Andy Thomas",
|
|
"Andy Thomas",
|
|
"1999",
|
|
PDB_INTERNAL,
|
|
|
|
/* Input arguments */
|
|
sizeof(path_stroke_current_in_args)/sizeof(path_stroke_current_in_args[0]),
|
|
path_stroke_current_in_args,
|
|
|
|
/* Output arguments */
|
|
0,
|
|
NULL,
|
|
|
|
/* Exec method */
|
|
{ { path_stroke_current_invoker } },
|
|
};
|