home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / app / path.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-17  |  8.2 KB  |  374 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1999 Andy Thomas alt@picnic.demon.co.uk
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License as published by
  6.  * the Free Software Foundation; either version 2 of the License, or
  7.  * (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17.  * Some of this code is based on the layers_dialog box code.
  18.  */
  19.  
  20. #include "config.h"
  21.  
  22. #include <stdlib.h>
  23. #include <string.h>
  24.  
  25. #include <glib.h>
  26.  
  27. #include "apptypes.h"
  28. #include "bezier_selectP.h"
  29. #include "gimpimage.h"
  30. #include "path.h"
  31. #include "pathP.h"
  32. #include "paths_dialog.h"
  33.  
  34. #include "libgimp/gimpmath.h"
  35.  
  36.  
  37. static gchar * unique_name (GimpImage *, gchar *);
  38.  
  39.  
  40. Path*
  41. path_new (GimpImage *gimage,
  42.       PathType   ptype,
  43.       GSList    *path_details,
  44.       gint       closed,
  45.       gint       state,
  46.       gint       locked,
  47.       gint       tattoo,  
  48.       gchar     *name)
  49. {
  50.   gchar *suniq;
  51.   Path  *path = g_new0 (Path, 1);
  52.  
  53.   suniq = unique_name (gimage, name);
  54.   if (suniq)
  55.     path->name = suniq;
  56.   else
  57.     path->name = g_strdup (name);
  58.  
  59.   path->path_details = path_details;
  60.   path->closed = closed;
  61.   path->state = state;
  62.   path->locked = locked;
  63.   path->pathtype = ptype;
  64.   if(tattoo)
  65.     path->tattoo = tattoo;
  66.   else
  67.     path->tattoo = gimp_image_get_new_tattoo (gimage);
  68.  
  69.   return path;
  70. }
  71.  
  72. Path*
  73. path_copy (GimpImage *gimage,
  74.        Path      *path)
  75. {
  76.   Path* p_copy = g_new0 (Path, 1);
  77.   gchar *name;
  78.   
  79.   name = unique_name (gimage, path->name);
  80.   if (name)
  81.     p_copy->name = name;
  82.   else
  83.     p_copy->name = g_strdup (path->name);
  84.  
  85.   p_copy->closed = path->closed;
  86.   p_copy->state = path->state;
  87.   p_copy->pathtype = path->pathtype;
  88.   p_copy->path_details = pathpoints_copy (path->path_details);
  89.   if (gimage)
  90.     p_copy->tattoo = gimp_image_get_new_tattoo (gimage);
  91.   else
  92.     p_copy->tattoo = path->tattoo;
  93.  
  94.   return p_copy;
  95. }
  96.  
  97. void 
  98. path_free (Path *path)
  99. {
  100.   g_return_if_fail (path != NULL);
  101.  
  102.   g_free (path->name);
  103.   pathpoints_free (path->path_details);
  104.   g_free (path);
  105. }
  106.  
  107.  
  108. PathPoint* 
  109. path_point_new (guint    type,
  110.         gdouble  x, 
  111.         gdouble  y)
  112. {
  113.   PathPoint* pathpoint = g_new0 (PathPoint,1);
  114.  
  115.   pathpoint->type = type;
  116.   pathpoint->x = x;
  117.   pathpoint->y = y;
  118.   return(pathpoint);
  119. }
  120.  
  121. void
  122. path_point_free (PathPoint *pathpoint)
  123. {
  124.   g_free (pathpoint);
  125. }
  126.  
  127. void 
  128. path_stroke (GimpImage *gimage,
  129.          PathList  *pl,
  130.          Path      *bzp)
  131. {
  132.   BezierSelect * bezier_sel;
  133.   GDisplay  * gdisp;
  134.  
  135.   gdisp = gdisplays_check_valid (pl->gdisp, gimage);
  136.   bezier_sel = path_to_beziersel (bzp);
  137.   bezier_stroke (bezier_sel, gdisp, SUBDIVIDE, !bzp->closed);
  138.   bezier_select_free (bezier_sel);
  139. }
  140.  
  141. gint 
  142. path_distance (Path    *bzp,
  143.            gdouble  dist,
  144.            gint    *x,
  145.            gint    *y, 
  146.            gdouble *grad)
  147. {
  148.   gint ret;
  149.   BezierSelect * bezier_sel;
  150.   bezier_sel = path_to_beziersel (bzp);
  151.   ret = bezier_distance_along (bezier_sel, !bzp->closed, dist, x, y, grad);
  152.   bezier_select_free (bezier_sel);
  153.   return (ret);
  154. }
  155.  
  156. Tattoo
  157. path_get_tattoo (Path* p)
  158. {
  159.   if(!p)
  160.     {
  161.       g_warning("path_get_tattoo: invalid path");
  162.       return 0;
  163.     }
  164.  
  165.   return (p->tattoo);
  166. }
  167.  
  168. Path*
  169. path_get_path_by_tattoo (GimpImage *gimage,
  170.              Tattoo     tattoo)
  171. {
  172.   GSList   *tlist;
  173.   PathList *plp;
  174.  
  175.   if(!gimage || !tattoo)
  176.     return NULL;
  177.  
  178.   /* Go around the list and check all tattoos. */
  179.  
  180.   /* Get path structure  */
  181.   plp = (PathList*) gimp_image_get_paths (gimage);
  182.  
  183.   if(!plp)
  184.     return (NULL);
  185.  
  186.   tlist = plp->bz_paths;
  187.   
  188.   while(tlist)
  189.     {
  190.       Path* p = (Path*)(tlist->data);
  191.       if(p->tattoo == tattoo)
  192.     return (p);
  193.       tlist = g_slist_next(tlist);
  194.     }
  195.   return (NULL);
  196. }
  197.  
  198. PathList *
  199. path_list_new (GimpImage *gimage,
  200.            gint       last_selected_row,
  201.            GSList    *bz_paths)
  202. {
  203.   PathList *pip = g_new0 (PathList, 1);
  204.   pip->gimage = gimage;
  205.   pip->last_selected_row = last_selected_row;
  206.   
  207.   /* add connector to image delete/destroy */
  208.   pip->sig_id = gtk_signal_connect(GTK_OBJECT (gimage),
  209.                    "destroy",
  210.                    GTK_SIGNAL_FUNC (paths_dialog_destroy_cb),
  211.                    pip);
  212.  
  213.   pip->bz_paths = bz_paths;
  214.  
  215.   return (PathList *)pip;
  216. }
  217.  
  218. void
  219. path_list_free (PathList* iml)
  220. {
  221.   g_return_if_fail (iml != NULL);
  222.   if (iml->bz_paths)
  223.     {
  224.       g_slist_foreach (iml->bz_paths, (GFunc)path_free, NULL);
  225.       g_slist_free (iml->bz_paths);
  226.     }
  227.   g_free (iml);
  228. }
  229.  
  230. BezierSelect *
  231. path_to_beziersel (Path *bzp)
  232. {
  233.   BezierSelect *bezier_sel;
  234.   BezierPoint  *bpnt = NULL;
  235.   GSList       *list;
  236.  
  237.   if (!bzp)
  238.     g_warning ("path_to_beziersel: NULL bzp");
  239.  
  240.   list = bzp->path_details;
  241.   bezier_sel = g_new0 (BezierSelect, 1);
  242.  
  243.   bezier_sel->num_points = 0;
  244.   bezier_sel->mask = NULL;
  245.   bezier_sel->core = NULL; /* not required will be reset in bezier code */
  246.   bezier_select_reset (bezier_sel);
  247.   bezier_sel->closed = bzp->closed;
  248. /*   bezier_sel->state = BEZIER_ADD; */
  249.   bezier_sel->state = bzp->state;
  250.  
  251.   while (list)
  252.     {
  253.       PathPoint *pdata;
  254.       pdata = (PathPoint*)list->data;
  255.       if (pdata->type == BEZIER_MOVE)
  256.     {
  257. /*       printf("Close last curve off\n"); */
  258.       bezier_sel->last_point->next = bpnt;
  259.       bpnt->prev = bezier_sel->last_point;
  260.       bezier_sel->cur_anchor = NULL;
  261.       bezier_sel->cur_control = NULL;
  262.       bpnt = NULL;
  263.     }
  264.       bezier_add_point (bezier_sel,
  265.             (gint) pdata->type,
  266.             RINT(pdata->x), /* ALT add rint() */
  267.             RINT(pdata->y));
  268.       if (bpnt == NULL)
  269.     bpnt = bezier_sel->last_point;
  270.       list = g_slist_next (list);
  271.     }
  272.   
  273.   if ( bezier_sel->closed )
  274.     {
  275.       bezier_sel->last_point->next = bpnt;
  276.       bpnt->prev = bezier_sel->last_point;
  277.       bezier_sel->cur_anchor = bezier_sel->points;
  278.       bezier_sel->cur_control = bezier_sel-> points->next;
  279.     }
  280.  
  281.   return bezier_sel;
  282. }
  283.  
  284.  
  285. /* Always return a copy that must be freed later */
  286.  
  287. static gchar *
  288. strip_off_cnumber (gchar *str)
  289. {
  290.   gchar *hashptr;
  291.   gint   num;
  292.   gchar *copy;
  293.  
  294.   if (!str)
  295.     return str;
  296.  
  297.   copy = g_strdup (str);
  298.  
  299.   if ((hashptr = strrchr (copy,'#')) &&              /* have a hash */
  300.       strlen(hashptr) > 0 &&                         /* followed by something */
  301.       (num = atoi(hashptr+1)) > 0 &&                 /* which is a number */
  302.       ((int) log10 (num) + 1) == strlen (hashptr+1)) /* which is at the end */
  303.     {
  304.       gchar * tstr;
  305.       /* Has a #<number> */
  306.       *hashptr = '\0';
  307.       tstr = g_strdup (copy);
  308.       g_free (copy);
  309.       copy = tstr;
  310.     }
  311.  
  312.   return copy;
  313. }
  314.  
  315. /* Return NULL if already unique else a unique string */
  316.  
  317. static gchar *
  318. unique_name (GimpImage *gimage,
  319.          gchar     *cstr)
  320. {
  321.   GSList *tlist;
  322.   PathList *plp;
  323.   gboolean unique = TRUE;
  324.   gchar *copy_cstr;
  325.   gchar *copy_test;
  326.   gchar *stripped_copy;
  327.   gint counter = 1;
  328.  
  329.   /* Get bzpath structure  */
  330.   if (!gimage || !(plp = (PathList*) gimp_image_get_paths(gimage)))
  331.     return NULL;
  332.  
  333.   tlist = plp->bz_paths;
  334.  
  335.   while (tlist)
  336.     {
  337.       gchar *test_str = ((Path*)(tlist->data))->name;
  338.       if (strcmp (cstr, test_str) == 0)
  339.     {
  340.         unique = FALSE;
  341.         break;
  342.     }
  343.       tlist = g_slist_next(tlist);
  344.     }
  345.  
  346.   if (unique)
  347.     return NULL;
  348.  
  349.   /* OK Clashes with something */
  350.   /* restart scan to find unique name */
  351.  
  352.   stripped_copy = strip_off_cnumber (cstr);
  353.   copy_cstr = g_strdup_printf ("%s#%d", stripped_copy, counter++);
  354.  
  355.   tlist = plp->bz_paths;
  356.  
  357.   while(tlist)
  358.     {
  359.       copy_test = ((Path*)(tlist->data))->name;
  360.       if(strcmp(copy_cstr,copy_test) == 0)
  361.     {
  362.       g_free(copy_cstr);
  363.       copy_cstr = g_strdup_printf("%s#%d",stripped_copy,counter++);
  364.       tlist = plp->bz_paths;
  365.       continue;
  366.     }
  367.       tlist = g_slist_next(tlist);
  368.     }
  369.  
  370.   g_free (stripped_copy);
  371.  
  372.   return copy_cstr;
  373. }
  374.