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

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  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.  */
  18.  
  19. #include "config.h"
  20.  
  21. #include <string.h>
  22.  
  23. #include <gtk/gtk.h>
  24.  
  25. #include "apptypes.h"
  26.  
  27. #include "appenv.h"
  28. #include "cursorutil.h"
  29. #include "draw_core.h"
  30. #include "edit_selection.h"
  31. #include "errors.h"
  32. #include "gdisplay.h"
  33. #include "gimage_mask.h"
  34. #include "rect_select.h"
  35. #include "bezier_select.h"
  36. #include "bezier_selectP.h"
  37. #include "paths_dialogP.h"
  38. #include "selection_options.h"
  39. #include "undo.h"
  40.  
  41. #include "libgimp/gimpmath.h"
  42.  
  43. #include "libgimp/gimpintl.h"
  44.  
  45. /* Bezier extensions made by Raphael FRANCOIS (fraph@ibm.net)
  46.  
  47.   BEZIER_EXTENDS VER 1.0 
  48.  
  49.   - work as the cut/copy/paste named functions.
  50.   - allow to add/remove/replace bezier curves
  51.   - allow to modify the control/anchor points even if the selection is made
  52.   - allow to add/remove control/anchor points on a curve
  53.   - allow to update a previous saved curve
  54.  
  55.   - cannot operate on open or multiple curves simultaneously
  56. */
  57.  
  58. #define BEZIER_DRAW_CURVE   1
  59. #define BEZIER_DRAW_CURRENT 2
  60. #define BEZIER_DRAW_HANDLES 4
  61. #define BEZIER_DRAW_ALL     (BEZIER_DRAW_CURVE | BEZIER_DRAW_HANDLES)
  62.  
  63. #define BEZIER_WIDTH     8
  64. #define BEZIER_HALFWIDTH 4
  65.  
  66.  
  67. #define SUPERSAMPLE   3
  68. #define SUPERSAMPLE2  9
  69.  
  70. #define NO  0
  71. #define YES 1
  72.  
  73. /*  the bezier select structures  */
  74.  
  75. typedef double BezierMatrix[4][4];
  76.  
  77. /*  The named paste dialog  */
  78. typedef struct _PasteNamedDlg PasteNamedDlg;
  79. struct _PasteNamedDlg
  80. {
  81.   GtkWidget   *shell;
  82.   GtkWidget   *list;
  83.   GDisplay    *gdisp; 
  84. };
  85.  
  86. /*  The named buffer structure...  */
  87. typedef struct _named_buffer BezierNamedBuffer;
  88. struct _named_buffer
  89. {
  90.   BezierSelect *sel;
  91.   char *        name;
  92. };
  93.  
  94.  
  95. typedef struct {
  96.   CountCurves  curve_count;         /* Must be the first element */
  97.   gdouble *stroke_points;
  98.   gint       num_stroke_points;    /* num of valid points */
  99.   gint       len_stroke_points;    /* allocated length */
  100.   void    *next_curve;          /* Next curve in list -- we draw all curves 
  101.                  * separately.
  102.                  */
  103. } BezierRenderPnts;
  104.  
  105. typedef struct {
  106.   CountCurves  curve_count;         /* Must be the first element */
  107.   gboolean firstpnt;
  108.   gdouble  curdist;
  109.   gdouble  dist;
  110.   gdouble  *gradient;
  111.   gint     *x;
  112.   gint     *y;
  113.   gdouble  lastx;
  114.   gdouble  lasty;
  115.   gboolean found;
  116. } BezierDistance;
  117.  
  118. typedef struct {
  119.   CountCurves  curve_count;         /* Must be the first element */
  120.   gint         x;
  121.   gint         y;
  122.   gint         halfwidth;
  123.   gint         found;
  124. } BezierCheckPnts;
  125.  
  126. /*  the bezier selection tool options  */ 
  127. static SelectionOptions *bezier_options = NULL;
  128.  
  129. /*  local variables  */
  130. static BezierMatrix basis =
  131. {
  132.   { -1,  3, -3,  1 },
  133.   {  3, -6,  3,  0 },
  134.   { -3,  3,  0,  0 },
  135.   {  1,  0,  0,  0 },
  136. };
  137.  
  138. /*
  139. static BezierMatrix basis =
  140. {
  141.   { -1/6.0,  3/6.0, -3/6.0,  1/6.0 },
  142.   {  3/6.0, -6/6.0,  3/6.0,  0 },
  143.   { -3/6.0,  0,  3/6.0,  0 },
  144.   {  1/6.0,  4/6.0,  1,  0 },
  145. };
  146. */
  147.  
  148. /*  The named buffer list  */
  149. GSList *bezier_named_buffers = NULL;
  150.  
  151. /*  Global Static Variable to maintain informations about the "contexte"  */
  152. static BezierSelect * curSel;
  153. static Tool * curTool;
  154. static GDisplay * curGdisp;
  155. static DrawCore * curCore;
  156. static int ModeEdit = EXTEND_NEW;
  157.  
  158.  
  159. /*  local function prototypes  */
  160. static void  bezier_select_button_press    (Tool *, GdkEventButton *, gpointer);
  161. static void  bezier_select_button_release  (Tool *, GdkEventButton *, gpointer);
  162. static void  bezier_select_motion          (Tool *, GdkEventMotion *, gpointer);
  163. static void  bezier_select_control         (Tool *, ToolAction,       gpointer);
  164. static void  bezier_select_cursor_update   (Tool *, GdkEventMotion *, gpointer);
  165. static void  bezier_select_draw            (Tool *);
  166.  
  167. static void  bezier_offset_point           (BezierPoint *, int, int);
  168. static int   bezier_check_point            (BezierPoint *, int, int, int);
  169. static void  bezier_draw_handles           (BezierSelect *, gint);
  170. static void  bezier_draw_current           (BezierSelect *);
  171. static void  bezier_draw_point             (BezierSelect *, BezierPoint *, int);
  172. static void  bezier_draw_line              (BezierSelect *, BezierPoint *, BezierPoint *);
  173. static void  bezier_draw_segment           (BezierSelect *, BezierPoint *, int, int, BezierPointsFunc,gpointer);
  174. static void  bezier_draw_segment_points    (BezierSelect *, GdkPoint *, int, gpointer);
  175. static void  bezier_compose                (BezierMatrix, BezierMatrix, BezierMatrix);
  176.  
  177. static void  bezier_convert                (BezierSelect *, GDisplay *, int, int);
  178. static void  bezier_convert_points         (BezierSelect *, GdkPoint *, int, gpointer);
  179. static void  bezier_convert_line           (GSList **, int, int, int, int);
  180. static GSList * bezier_insert_in_list      (GSList *, int);
  181.  
  182. static int   test_add_point_on_segment     (BezierSelect *, BezierPoint *, int, int, int, int, int);
  183. static void  bezier_to_sel_internal        (BezierSelect *, Tool *, GDisplay *, gint, gint);
  184. static void  bezier_stack_points       (BezierSelect *, GdkPoint *, int, gpointer);
  185. static gboolean stroke_interpolatable    (int, int, int, int, gdouble);
  186. static void bezier_stack_points_aux      (GdkPoint *, int, int, gdouble, BezierRenderPnts *);
  187. static gint count_points_on_curve(BezierPoint *);
  188.  
  189.  
  190. /*  functions  */
  191.  
  192. static void
  193. bezier_select_options_reset ()
  194. {
  195.   selection_options_reset (bezier_options);
  196. }
  197.  
  198. Tool*
  199. tools_new_bezier_select ()
  200. {
  201.   Tool * tool;
  202.   BezierSelect * private;
  203.  
  204.   /*  The tool options  */
  205.   if (! bezier_options)
  206.     {
  207.       bezier_options =
  208.     selection_options_new (BEZIER_SELECT, bezier_select_options_reset);
  209.       tools_register (BEZIER_SELECT, (ToolOptions *) bezier_options);
  210.     }
  211.  
  212.  
  213.   tool = tools_new_tool (BEZIER_SELECT);
  214.   private = g_new0 (BezierSelect, 1);
  215.  
  216.   private->num_points = 0;
  217.   private->mask = NULL;
  218.   private->core = draw_core_new (bezier_select_draw);
  219.   bezier_select_reset (private);
  220.  
  221.   tool->scroll_lock = TRUE;   /*  Disallow scrolling  */
  222.   tool->preserve    = FALSE;  /*  Don't preserve on drawable change  */
  223.  
  224.   tool->private = (void *) private;
  225.  
  226.   tool->button_press_func   = bezier_select_button_press;
  227.   tool->button_release_func = bezier_select_button_release;
  228.   tool->motion_func         = bezier_select_motion;
  229.   tool->cursor_update_func  = bezier_select_cursor_update;
  230.   tool->control_func        = bezier_select_control;
  231.  
  232.   curCore = private->core;
  233.   curSel  = private;
  234.   curTool = tool;
  235.  
  236.   paths_new_bezier_select_tool ();
  237.  
  238.   return tool;
  239. }
  240.  
  241. void
  242. tools_free_bezier_select (Tool *tool)
  243. {
  244.   BezierSelect * bezier_sel;
  245.  
  246.   bezier_sel = tool->private;
  247.  
  248.   if (tool->state == ACTIVE)
  249.     draw_core_stop (bezier_sel->core, tool);
  250.   draw_core_free (bezier_sel->core);
  251.  
  252.   bezier_select_reset (bezier_sel);
  253.  
  254.   g_free (bezier_sel);
  255. }
  256.  
  257. int
  258. bezier_select_load (void        *gdisp_ptr,
  259.             BezierPoint *pts,
  260.             int          num_pts,
  261.             int          closed)
  262. {
  263.   GDisplay * gdisp;
  264.   Tool * tool;
  265.   BezierSelect * bezier_sel;
  266.  
  267.   gdisp = (GDisplay *) gdisp_ptr;
  268.  
  269.   /*  select the bezier tool  */
  270.   gimp_context_set_tool (gimp_context_get_user (), BEZIER_SELECT);
  271.   tool = active_tool;
  272.   tool->state = ACTIVE;
  273.   tool->gdisp_ptr = gdisp_ptr;
  274.   bezier_sel = (BezierSelect *) tool->private;
  275.  
  276.   bezier_sel->points = pts;
  277.   bezier_sel->last_point = pts->prev;
  278.   bezier_sel->num_points = num_pts;
  279.   bezier_sel->closed = closed;
  280.   bezier_sel->state = BEZIER_EDIT;
  281.   bezier_sel->draw = BEZIER_DRAW_ALL;
  282.  
  283.   bezier_convert (bezier_sel, tool->gdisp_ptr, SUBDIVIDE, NO);
  284.  
  285.   draw_core_start (bezier_sel->core, gdisp->canvas->window, tool);
  286.  
  287.   return 1;
  288. }
  289.  
  290. static BezierPoint *
  291. valid_curve_segment(BezierPoint *points)
  292. {
  293.   /* Valid curve segment is made up of four points */
  294.   if(points && 
  295.      points->next && 
  296.      points->next->next && 
  297.      points->next->next->next )
  298.     return(points);
  299.  
  300.   return (NULL);
  301. }
  302.  
  303. static BezierPoint *
  304. next_anchor(BezierPoint *points,BezierPoint **next_curve)
  305. {
  306.   int loop;
  307.  
  308.   *next_curve = NULL;
  309.  
  310.   if(!points)
  311.     return (NULL);
  312.  
  313.   for(loop = 0; loop < 3; loop++)
  314.   {
  315.        points = points->next; 
  316.        if (!points) 
  317.       return (NULL);
  318.        if(points->next_curve)
  319.        {
  320.       *next_curve = points->next_curve;
  321.        }
  322.   }
  323.   return valid_curve_segment(points);
  324. }
  325.  
  326. void
  327. bezier_draw_curve (BezierSelect    *bezier_sel,
  328.            BezierPointsFunc func, 
  329.            gint             coord,
  330.            gpointer         udata)
  331. {
  332.   BezierPoint * points;
  333.   BezierPoint * start_pt;
  334.   BezierPoint * next_curve;
  335.   CountCurves * cnt = (CountCurves *)udata;
  336.   gint point_counts = 0;
  337.  
  338. /*   printSel(bezier_sel); */
  339.  
  340.   if(cnt)
  341.     cnt->count = 0;
  342.   points = bezier_sel->points;
  343.   start_pt = bezier_sel->points;
  344.  
  345.   if(bezier_sel->num_points >= 4)
  346.     {
  347.       do {
  348.     point_counts = count_points_on_curve(points);
  349.     if(point_counts >= 4)
  350.       {
  351.         do {
  352.           bezier_draw_segment (bezier_sel, points,
  353.                    SUBDIVIDE, coord,
  354.                    func,
  355.                    udata);
  356.           
  357.           points = next_anchor(points,&next_curve);
  358.           /*       g_print ("next_anchor = %p\n",points); */
  359.         } while (points != start_pt && points);
  360.         if(cnt)
  361.           cnt->count++;
  362.         start_pt = next_curve;
  363.         points = next_curve;
  364.       }
  365.     else
  366.       break; /* must be last curve since only this one is allowed < 4
  367.           * points.
  368.           */
  369.       } while(next_curve);
  370.     }
  371. }
  372.  
  373. void
  374. bezier_select_reset (BezierSelect *bezier_sel)
  375. {
  376.   BezierPoint * points;
  377.   BezierPoint * start_pt;
  378.   BezierPoint * temp_pt;
  379.   BezierPoint * next_curve;
  380.  
  381.   if (bezier_sel->num_points > 0)
  382.     {
  383.       points = bezier_sel->points;
  384.       start_pt = bezier_sel->points;
  385.  
  386.       do {
  387.     do {
  388.       temp_pt = points;
  389.       next_curve = points->next_curve;
  390.       points = points->next;
  391.       if(points != start_pt && next_curve)
  392.         {
  393.           g_warning("Curve points out of sync");
  394.         }
  395.       g_free (temp_pt);
  396.     } while (points != start_pt && points);
  397.     points = next_curve;
  398.     start_pt = next_curve;
  399.       } while (next_curve);
  400.     }
  401.  
  402.   if (bezier_sel->mask)
  403.     channel_delete (bezier_sel->mask);
  404.  
  405.   bezier_sel->state = BEZIER_START;    /* we are starting the curve */
  406.   bezier_sel->draw = BEZIER_DRAW_ALL;  /* draw everything by default */
  407.   bezier_sel->closed = 0;              /* the curve is initally open */
  408.   bezier_sel->points = NULL;           /* initially there are no points */
  409.   bezier_sel->cur_anchor = NULL;
  410.   bezier_sel->cur_control = NULL;
  411.   bezier_sel->last_point = NULL;
  412.   bezier_sel->num_points = 0;          /* intially there are no points */
  413.   bezier_sel->mask = NULL;             /* empty mask */
  414.   bezier_sel->scanlines = NULL;
  415. }
  416.  
  417. void
  418. bezier_select_free (BezierSelect *bezier_sel)
  419. {
  420.   bezier_select_reset (bezier_sel);
  421.   g_free (bezier_sel);
  422. }
  423.  
  424. /* Find the curve that points to this curve. This makes to_check point
  425.  * the start of a curve. 
  426.  */
  427. static BezierPoint * 
  428. check_for_next_curve(BezierSelect *bezier_sel,
  429.              BezierPoint  *to_check)
  430. {
  431.   BezierPoint *points = bezier_sel->points;
  432.   gint num_points = bezier_sel->num_points;
  433.  
  434.   while (points && num_points)
  435.    {
  436.      if(points->next_curve == to_check)
  437.        return (points);
  438.  
  439.      if(points->next_curve)
  440.        points = points->next_curve;
  441.      else
  442.        points = points->next;
  443.      num_points--;
  444.    }
  445.   return (NULL);
  446. }
  447.  
  448. static gint 
  449. count_points_on_curve(BezierPoint *points)
  450. {
  451.   BezierPoint *start = points;
  452.   gint count = 0;
  453.   
  454.   while(points && points->next != start)
  455.     {
  456.       points = points->next;
  457.       count++;
  458.     }
  459.  
  460.   return (count);
  461. }
  462.  
  463. /* Find the start of the last open curve, if curve already closed
  464.  * this is an error..
  465.  */
  466.  
  467. static BezierPoint *
  468. find_start_open_curve(BezierSelect *bsel)
  469. {
  470.   BezierPoint *start_pnt = NULL;
  471.   BezierPoint *this_pnt = bsel->last_point;
  472.  
  473.   /* Could be one of the first points */
  474.   if(!bsel->last_point)
  475.     {
  476.       return NULL;
  477.     }
  478.  
  479.   if(bsel->closed)
  480.     {
  481.       g_message(_("Bezier path already closed."));
  482.       return NULL;
  483.     }
  484.  
  485.   /* Step backwards until the prev point is null.
  486.    * in this case this is the start of the open curve.
  487.    * The start_pnt stuff is to stop us going around forever.
  488.    * If we even have a closed curve then we are in seroius 
  489.    * trouble.
  490.    */
  491.  
  492.   while(this_pnt->prev && start_pnt != this_pnt)
  493.     {
  494.       if(!start_pnt)
  495.     start_pnt = this_pnt;
  496.       this_pnt = this_pnt->prev;
  497.     }
  498.  
  499.   /* Must be an anchor to be the start */
  500.   if(start_pnt == this_pnt || this_pnt->type != BEZIER_ANCHOR)
  501.     {
  502.       g_message(_("Corrupt curve"));
  503.       return NULL;
  504.     }
  505.  
  506. /*   g_print ("Returned start pnt of curve %p is %p\n",bsel->last_point,this_pnt); */
  507.   return (this_pnt);
  508. }
  509.  
  510. /* Delete a whole curve. Watch out for special cases.
  511.  * start_pnt must always be the start point if the curve to delete.
  512.  */
  513.  
  514. static void
  515. delete_whole_curve(BezierSelect   *bezier_sel,
  516.            BezierPoint    *start_pnt)
  517. {
  518.   BezierPoint    *tmppnt;
  519.   BezierPoint    *next_curve = NULL; /* Next curve this one 
  520.                       * points at (if any) 
  521.                       */
  522.   BezierPoint    *prev_curve; /* Does a curve point to this one? */
  523.   gint            cnt_pnts = 0; /* Count how many pnts deleted */
  524.   gint            reset_last = FALSE;
  525.  
  526.   /* shift and del means delete whole curve */
  527.   /* Three cases, this is first curve, middle curve 
  528.    * or end curve.
  529.    */
  530.   
  531.   /* Does this curve have another chained on the end? 
  532.    * or is this curve pointed to another one?
  533.    */
  534.  
  535. /*   g_print ("delete_whole_curve::\n"); */
  536.  
  537.   tmppnt = start_pnt;
  538.   do {
  539.     if(tmppnt->next_curve)
  540.       {
  541.     next_curve = tmppnt->next_curve;
  542.     break;
  543.       }
  544.     tmppnt = tmppnt->next;
  545.   } while (tmppnt != start_pnt && tmppnt);
  546.  
  547.   prev_curve = check_for_next_curve(bezier_sel,start_pnt);
  548.   
  549.   /* First curve ?*/
  550.   if(bezier_sel->points == start_pnt)
  551.     bezier_sel->points = next_curve;
  552.   else 
  553.     {
  554.       /* better have a previous curve else how did we get here? */
  555.       prev_curve->next_curve = next_curve;
  556.     }
  557.      
  558.   /* start_pnt points to the curve we should free .. ignoring the next_curve */
  559.  
  560.   tmppnt = start_pnt;
  561.   do {
  562.     BezierPoint *fpnt;
  563.     fpnt = tmppnt;
  564.     tmppnt = tmppnt->next;
  565.     if(fpnt == bezier_sel->last_point)
  566.       reset_last = TRUE;
  567.     g_free (fpnt);
  568.     cnt_pnts++;
  569.   } while (tmppnt != start_pnt && tmppnt);
  570.  
  571.   bezier_sel->num_points -= cnt_pnts;
  572.   
  573.   /* if deleted curve was unclosed then must have been the last curve 
  574.    * and thus this curve becomes closed.
  575.    */
  576.   if(!tmppnt && bezier_sel->num_points > 0)
  577.     {
  578.       bezier_sel->closed = 1;
  579.       bezier_sel->state = BEZIER_EDIT;
  580.     }
  581.  
  582.   if(bezier_sel->num_points <= 0)
  583.     {
  584.       bezier_select_reset(bezier_sel);
  585.     }
  586.  
  587.   bezier_sel->cur_anchor = NULL;
  588.   bezier_sel->cur_control = NULL;
  589.  
  590.   /* The last point could have been on this curve as well... */
  591.   if(reset_last)
  592.     {
  593.       BezierPoint *points = bezier_sel->points;
  594.       BezierPoint *l_pnt = NULL;
  595.       gint num_points = bezier_sel->num_points;
  596.       
  597.       while (points && num_points)
  598.     {
  599.       l_pnt = points;
  600.       if(points->next_curve)
  601.         points = points->next_curve;
  602.       else
  603.         points = points->next;
  604.       num_points--;
  605.     }
  606.       bezier_sel->last_point = l_pnt;
  607.     }
  608. }
  609.  
  610. static gint
  611. bezier_edit_point_on_curve(int             x,
  612.                int             y,
  613.                int             halfwidth,
  614.                GDisplay       *gdisp,
  615.                BezierSelect   *bezier_sel,
  616.                Tool           *tool,
  617.                GdkEventButton *bevent)
  618. {
  619.   gint grab_pointer = 0;
  620.   BezierPoint  *next_curve;
  621.   BezierPoint  *points = bezier_sel->points;
  622.   BezierPoint  *start_pt = bezier_sel->points;
  623.   BezierPoint  *last_curve = NULL;
  624.   gint point_counts = 0;
  625.  
  626.   /* find if the button press occurred on a point */
  627.   do {
  628.     point_counts = count_points_on_curve(points);
  629.     do {
  630.       if (bezier_check_point (points, x, y, halfwidth))
  631.     {
  632.       BezierPoint *finded=points;
  633.       BezierPoint *start_op; 
  634.       BezierPoint *end_op; 
  635.       
  636.       if (ModeEdit== EXTEND_REMOVE)
  637.         {
  638.  
  639.           if((bevent->state & GDK_SHIFT_MASK) || (point_counts <= 7))
  640.         {
  641.           /* Case 1: GDK_SHIFT_MASK - The user explicitly wishes the present 
  642.                      curve to go away.
  643.                      Case 2: The current implementation cannot cope with less than
  644.                      7 points ie: 2 anchors points and 4 controls: the minimal closed curve.
  645.                      Since the user wishes less than this implementation minimum,
  646.                      we take this for an implicit wish that the entire curve go away.
  647.                      G'bye dear curve. 
  648.           */
  649.  
  650.           delete_whole_curve(bezier_sel,start_pt);
  651.           return (1);
  652.         }
  653.           else if(!finded->prev || !finded->prev->prev) 
  654.         {
  655.           /* This is the first point on the curve */
  656.           /* Clear current anchor and control */
  657.           bezier_sel->cur_anchor = NULL;
  658.           bezier_sel->cur_control = NULL;
  659.           /* Where are we?  reset to first point... */
  660.           /*if(last_curve == NULL)*/
  661.           if(start_pt == bezier_sel->points)
  662.             {
  663.               finded = bezier_sel->points;
  664.               bezier_sel->points = finded->next->next->next;
  665.               bezier_sel->points->prev = NULL;
  666.             }
  667.           else
  668.             {
  669.                finded = last_curve->next_curve; 
  670.                last_curve->next_curve = finded->next->next->next; 
  671.                last_curve->next_curve->prev = NULL; 
  672.             }
  673.           
  674.           bezier_sel->num_points -= 3;
  675.           
  676.           g_free( finded->next->next );
  677.           g_free( finded->next );
  678.           g_free( finded );
  679.         }
  680.           else if(!bezier_sel->closed && 
  681.               (finded == bezier_sel->last_point ||
  682.                finded == bezier_sel->last_point->prev || 
  683.                finded == bezier_sel->last_point->prev->prev))
  684.         {
  685.           /* This is the last point on the curve */
  686.           /* Clear current anchor and control */
  687.           /* Where are we?  reset to last point... */
  688.           finded =  bezier_sel->last_point->prev;
  689.           bezier_sel->last_point = finded->prev->prev;
  690.           bezier_sel->last_point->next = NULL;
  691.           
  692.           bezier_sel->cur_anchor = NULL;
  693.           bezier_sel->cur_control = NULL;
  694.          
  695.  
  696.           bezier_sel->num_points -= 3;
  697.           
  698.           g_free( finded->prev );
  699.           g_free( finded->next );
  700.           g_free( finded );
  701.         }
  702.           else
  703.         {
  704.           if ( finded->type == BEZIER_CONTROL )
  705.             {
  706.               if (finded->next->type == BEZIER_CONTROL)
  707.             finded = finded->prev;
  708.               else
  709.             finded = finded->next;
  710.             }
  711.           
  712.           start_op = finded->prev->prev;
  713.           end_op = finded->next->next;
  714.  
  715.           /* we can use next_curve here since we are going to 
  716.            * drop out the bottom anyways.
  717.            */
  718.           next_curve = 
  719.             check_for_next_curve(bezier_sel,finded);
  720.  
  721.           if(next_curve)
  722.             {
  723.               /* Deleteing first point of next curve*/
  724.               next_curve->next_curve = finded->prev->prev->prev;
  725.             }
  726.           else /* Can't be both first and a next curve!*/
  727.             {
  728.               if (bezier_sel->points == finded)
  729.             {
  730. /*               g_print ("Deleting first point %p\n",finded); */
  731.               bezier_sel->points = finded->prev->prev->prev;
  732.             }
  733.             }
  734.  
  735.           /* Make sure the chain of curves is preserved */
  736.           if(finded->prev->next_curve)
  737.             {
  738. /*               g_print ("Moving curve on next_curve %p\n",finded->prev->next_curve); */
  739.               /* last point on closed multi-path */
  740.               finded->prev->prev->prev->prev->next_curve = finded->prev->next_curve;
  741.             }
  742.           
  743.           if(bezier_sel->last_point == finded->prev)
  744.             {
  745. /*               g_print ("Deleting last point %p\n",finded->prev); */
  746.               bezier_sel->last_point = bezier_sel->last_point->prev->prev->prev;
  747.             }
  748.  
  749.           start_op->next = end_op;
  750.           end_op->prev = start_op;
  751.  
  752. /*           if ( (bezier_sel->last_point == finded) ||  */
  753. /*                (bezier_sel->last_point == finded->next) ||  */
  754. /*                (bezier_sel->last_point  == finded->prev)) */
  755. /*             { */
  756. /*               bezier_sel->last_point = start_op->prev->prev; */
  757. /*               bezier_sel->points = start_op->prev; */
  758. /*             } */
  759.           
  760.           bezier_sel->num_points -= 3;
  761.           
  762.           g_free( finded->prev );
  763.           g_free( finded->next );
  764.           g_free( finded );
  765.           /* Clear current anchor and control */
  766.           bezier_sel->cur_anchor = NULL;
  767.           bezier_sel->cur_control = NULL;
  768.         }
  769.         }
  770.       else
  771.         {
  772.           /* set the current anchor and control points */
  773.           switch (points->type)
  774.         {
  775.         case BEZIER_ANCHOR:
  776.           bezier_sel->cur_anchor = points;
  777.           bezier_sel->cur_control = bezier_sel->cur_anchor->next;
  778.           break;
  779.         case BEZIER_CONTROL:
  780.           bezier_sel->cur_control = points;
  781.           if (bezier_sel->cur_control->next &&
  782.               bezier_sel->cur_control->next->type == BEZIER_ANCHOR)
  783.             bezier_sel->cur_anchor = bezier_sel->cur_control->next;
  784.           else
  785.             bezier_sel->cur_anchor = bezier_sel->cur_control->prev;
  786.           break;
  787.         }
  788.         }
  789.       return(1);
  790.     }
  791.  
  792.       next_curve = points->next_curve;
  793.       if(next_curve)
  794.     last_curve = points;
  795.       points = points->next;
  796.     } while (points != start_pt && points);
  797.     start_pt = next_curve;
  798.     points = next_curve;
  799.   } while (next_curve);
  800.     
  801.   return grab_pointer;
  802. }
  803.  
  804. static gint
  805. bezier_add_point_on_segment(int           x,
  806.                 int           y,
  807.                 int           halfwidth,
  808.                 GDisplay     *gdisp,
  809.                 BezierSelect *bezier_sel,
  810.                 Tool         *tool)
  811. {
  812.   BezierPoint  *points = bezier_sel->points;
  813.   BezierPoint  *start_pt = bezier_sel->points;
  814.   BezierPoint  *next_curve;
  815.  
  816.   do {
  817.     do {
  818.       if (test_add_point_on_segment (bezier_sel,       
  819.                      points,
  820.                      SUBDIVIDE, 
  821.                      IMAGE_COORDS,
  822.                      x, y,
  823.                      halfwidth))
  824.     {
  825.       return 1;
  826.     }
  827.       
  828.       points = points->next;
  829.       
  830.       if(!points)
  831.     return 0;
  832.       
  833.       points = points->next;
  834.       
  835.       if(!points)
  836.     return 0;
  837.       
  838.       next_curve = points->next_curve;
  839.       points = points->next;
  840.     } while (points != start_pt && points);
  841.     start_pt = next_curve;
  842.     points = next_curve;
  843.   } while (next_curve);
  844.   return 0;
  845. }
  846.  
  847.  
  848. static void
  849. bezier_start_new_segment(BezierSelect *bezier_sel,gint x,gint y)
  850. {
  851.   /* Must be closed to do this! */
  852.   if(!bezier_sel->closed)
  853.     return;
  854.   bezier_sel->closed = 0; /* End is no longer closed !*/
  855.   bezier_sel->state = BEZIER_ADD;
  856.   bezier_add_point (bezier_sel, BEZIER_MOVE, (gdouble)x, (gdouble)y);
  857.   bezier_add_point (bezier_sel, BEZIER_CONTROL, (gdouble)x, (gdouble)y);
  858. }
  859.  
  860. static void
  861. bezier_select_button_press (Tool           *tool,
  862.                 GdkEventButton *bevent,
  863.                 gpointer        gdisp_ptr)
  864. {
  865.   GDisplay *gdisp;
  866.   BezierSelect *bezier_sel;
  867.   BezierPoint *points;
  868.   BezierPoint *start_pt;
  869.   BezierPoint *curve_start;
  870.   int grab_pointer;
  871.   int op, replace;
  872.   int x, y;
  873.   int halfwidth, dummy;
  874.  
  875.   gdisp = (GDisplay *) gdisp_ptr;
  876.  
  877.   tool->drawable = gimage_active_drawable (gdisp->gimage);
  878.  
  879.   bezier_sel = tool->private;
  880.   grab_pointer = 0;
  881.  
  882.   if (bezier_options->extend)
  883.     {
  884.       tool->gdisp_ptr = gdisp_ptr;
  885.     }
  886.   else
  887.     {
  888.       /*  If the tool was being used in another image...reset it  */
  889.       if (tool->state == ACTIVE && gdisp_ptr != tool->gdisp_ptr) {
  890.         draw_core_stop(bezier_sel->core, tool);
  891.         bezier_select_reset (bezier_sel);
  892.       }
  893.     }
  894.  
  895.   gdisplay_untransform_coords (gdisp, bevent->x, bevent->y, &x, &y, TRUE, 0);
  896.  
  897.   /* get halfwidth in image coord */
  898.   gdisplay_untransform_coords (gdisp, bevent->x + BEZIER_HALFWIDTH, 0, &halfwidth, &dummy, TRUE, 0);
  899.   halfwidth -= x;
  900.  
  901.   curTool = active_tool;
  902.   curSel = curTool->private;
  903.   curGdisp = (GDisplay *) gdisp_ptr;
  904.   active_tool->gdisp_ptr = gdisp_ptr;
  905.   curCore = bezier_sel->core;
  906.  
  907.   switch (bezier_sel->state)
  908.     {
  909.     case BEZIER_START:
  910.       if(ModeEdit != EXTEND_NEW)
  911.     break;
  912.       grab_pointer = 1;
  913.       tool->state = ACTIVE;
  914.       tool->gdisp_ptr = gdisp_ptr;
  915.  
  916. /*       if (bevent->state & GDK_MOD1_MASK) */
  917. /*     { */
  918. /*       init_edit_selection (tool, gdisp_ptr, bevent, EDIT_MASK_TRANSLATE); */
  919. /*       break; */
  920. /*     } */
  921. /*       else if (!(bevent->state & GDK_SHIFT_MASK) && !(bevent->state & GDK_CONTROL_MASK)) */
  922. /*     if (! (layer_is_floating_sel (gimage_get_active_layer (gdisp->gimage))) && */
  923. /*         gdisplay_mask_value (gdisp, bevent->x, bevent->y) > HALF_WAY) */
  924. /*       { */
  925. /*         init_edit_selection (tool, gdisp_ptr, bevent, EDIT_MASK_TO_LAYER_TRANSLATE); */
  926. /*         break; */
  927. /*       } */
  928.  
  929.       bezier_sel->state = BEZIER_ADD;
  930.       /*bezier_sel->draw = BEZIER_DRAW_CURVE; | BEZIER_DRAW_HANDLES;*/
  931.       bezier_sel->draw = BEZIER_DRAW_CURRENT;
  932.  
  933.       bezier_add_point (bezier_sel, BEZIER_ANCHOR, (gdouble)x, (gdouble)y);
  934.       bezier_add_point (bezier_sel, BEZIER_CONTROL, (gdouble)x, (gdouble)y);
  935.  
  936.       draw_core_start (bezier_sel->core, gdisp->canvas->window, tool);
  937.       break;
  938.     case BEZIER_ADD:
  939.  
  940.       grab_pointer = 1;
  941.  
  942.       if(ModeEdit == EXTEND_EDIT)
  943.     { 
  944.       /* erase the handles */
  945.       if(bezier_sel->closed)
  946.         bezier_sel->draw = BEZIER_DRAW_ALL;  
  947.       else
  948.         bezier_sel->draw = BEZIER_DRAW_CURVE;  
  949.       draw_core_pause (bezier_sel->core, tool);
  950.       /* unset the current anchor and control */
  951.       bezier_sel->cur_anchor = NULL;
  952.       bezier_sel->cur_control = NULL;
  953.  
  954.       grab_pointer = bezier_edit_point_on_curve(x,y,halfwidth,gdisp,bezier_sel,tool,bevent);
  955.  
  956.       bezier_sel->draw = BEZIER_DRAW_ALL;  
  957.       draw_core_resume (bezier_sel->core, tool);
  958.  
  959.       if (grab_pointer)
  960.         gdk_pointer_grab (gdisp->canvas->window, FALSE,
  961.                   GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
  962.                   NULL, NULL, bevent->time);
  963.       else
  964.         {
  965.           paths_dialog_set_default_op();
  966.           /* recursive call */
  967.           bezier_select_button_press(tool,bevent,gdisp_ptr);
  968.         }
  969.       return;
  970.     }
  971.  
  972.       if(ModeEdit == EXTEND_REMOVE)
  973.     { 
  974. /*       if(bezier_sel->num_points < 6) */
  975. /*         return; */
  976.  
  977.       /* erase the handles */
  978.       bezier_sel->draw = BEZIER_DRAW_ALL; 
  979.       draw_core_pause (bezier_sel->core, tool);
  980.       /* unset the current anchor and control */
  981.       bezier_sel->cur_anchor = NULL;
  982.       bezier_sel->cur_control = NULL;
  983.  
  984.       /*kkk*/
  985.       bezier_sel->draw = BEZIER_DRAW_ALL; 
  986.       draw_core_resume (bezier_sel->core, tool);
  987.       bezier_sel->draw = BEZIER_DRAW_ALL; 
  988.       draw_core_pause (bezier_sel->core, tool);
  989.       /*kkk*/
  990.  
  991.       grab_pointer = bezier_edit_point_on_curve(x,y,halfwidth,gdisp,bezier_sel,tool,bevent);
  992.  
  993.       bezier_sel->draw = BEZIER_DRAW_ALL; 
  994.       draw_core_resume (bezier_sel->core, tool);
  995.       if(bezier_sel->num_points == 0)
  996.         {
  997.           draw_core_pause(bezier_sel->core, tool);
  998.           paths_dialog_set_default_op();
  999.         }
  1000.  
  1001.       if(!grab_pointer)
  1002.         {
  1003.           paths_dialog_set_default_op();
  1004.           /* recursive call */
  1005.           bezier_select_button_press(tool,bevent,gdisp_ptr);
  1006.         }
  1007.       return;
  1008.     }
  1009.  
  1010.       if(ModeEdit == EXTEND_ADD)
  1011.     {
  1012.       if(bezier_sel->num_points < 5)
  1013.         return;
  1014.       bezier_sel->draw = BEZIER_DRAW_ALL; 
  1015.       draw_core_pause (bezier_sel->core, tool); 
  1016.  
  1017.       grab_pointer = bezier_add_point_on_segment(x,y,halfwidth,gdisp,bezier_sel,tool);
  1018.  
  1019.       bezier_sel->draw = BEZIER_DRAW_ALL;
  1020.       draw_core_resume (bezier_sel->core, tool);
  1021.       if (grab_pointer)
  1022.         gdk_pointer_grab (gdisp->canvas->window, FALSE,
  1023.                   GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
  1024.                   NULL, NULL, bevent->time);
  1025.       else
  1026.         {
  1027.           paths_dialog_set_default_op();
  1028.           /* recursive call */
  1029.           bezier_select_button_press(tool,bevent,gdisp_ptr);
  1030.         }
  1031.       return;
  1032.     }
  1033.  
  1034.       if(bezier_sel->cur_anchor)
  1035.     {
  1036.       if (bezier_check_point (bezier_sel->cur_anchor, x, y, halfwidth))
  1037.         {
  1038.           break;
  1039.         }
  1040.       
  1041.       if (bezier_sel->cur_anchor->next &&
  1042.           bezier_check_point (bezier_sel->cur_anchor->next, x, y, halfwidth))
  1043.         {
  1044.           bezier_sel->cur_control = bezier_sel->cur_anchor->next;
  1045.           break;
  1046.         }
  1047.  
  1048.       if (bezier_sel->cur_anchor->prev &&
  1049.           bezier_check_point (bezier_sel->cur_anchor->prev, x, y, halfwidth))
  1050.         {
  1051.           bezier_sel->cur_control = bezier_sel->cur_anchor->prev;
  1052.           break;
  1053.         }
  1054.     }
  1055.  
  1056.       curve_start = find_start_open_curve(bezier_sel);
  1057.  
  1058.       if (curve_start && bezier_check_point (curve_start, x, y, halfwidth))
  1059.     {
  1060.       bezier_sel->draw = BEZIER_DRAW_ALL;
  1061.       draw_core_pause (bezier_sel->core, tool);
  1062.  
  1063.       bezier_add_point (bezier_sel, BEZIER_CONTROL, (gdouble)x, (gdouble)y);
  1064.       bezier_sel->last_point->next = curve_start;
  1065.       curve_start->prev = bezier_sel->last_point;
  1066.        bezier_sel->cur_anchor = curve_start;
  1067.        bezier_sel->cur_control = curve_start->next;
  1068.  
  1069.       bezier_sel->closed = 1;
  1070.       bezier_sel->state = BEZIER_EDIT;
  1071.       bezier_sel->draw = BEZIER_DRAW_ALL;
  1072.  
  1073.       draw_core_resume (bezier_sel->core, tool);
  1074.     }
  1075.       else
  1076.     {
  1077.       if(bezier_sel->cur_anchor)
  1078.         bezier_sel->cur_anchor->pointflags = 1;
  1079.        bezier_sel->draw = BEZIER_DRAW_HANDLES; 
  1080.        draw_core_pause (bezier_sel->core, tool); 
  1081.  
  1082.       bezier_add_point (bezier_sel, BEZIER_CONTROL, (gdouble)x, (gdouble)y);
  1083.       bezier_add_point (bezier_sel, BEZIER_ANCHOR, (gdouble)x, (gdouble)y);
  1084.       bezier_add_point (bezier_sel, BEZIER_CONTROL, (gdouble)x, (gdouble)y);
  1085.  
  1086.       bezier_sel->draw = BEZIER_DRAW_CURRENT | BEZIER_DRAW_HANDLES;
  1087.  
  1088.       draw_core_resume (bezier_sel->core, tool);
  1089.     }
  1090.       break;
  1091.     case BEZIER_EDIT:
  1092.       if (!bezier_sel->closed)
  1093.     gimp_fatal_error ("bezier_select_button_press(): Tried to edit on open bezier curve in edit selection");
  1094.  
  1095.       /* erase the handles */
  1096.       bezier_sel->draw = BEZIER_DRAW_ALL; 
  1097.       draw_core_pause (bezier_sel->core, tool);
  1098.  
  1099.       /* unset the current anchor and control */
  1100.       bezier_sel->cur_anchor = NULL;
  1101.       bezier_sel->cur_control = NULL;
  1102.  
  1103.       points = bezier_sel->points;
  1104.       start_pt = bezier_sel->points;
  1105.  
  1106.       if (ModeEdit == EXTEND_ADD)
  1107.     {
  1108.       if (bezier_sel->closed)
  1109.         {
  1110.           grab_pointer = bezier_add_point_on_segment(x,y,halfwidth,gdisp,bezier_sel,tool);
  1111.         }
  1112.     }
  1113.       else
  1114.     {
  1115.       grab_pointer = bezier_edit_point_on_curve(x,y,halfwidth,gdisp,bezier_sel,tool,bevent);
  1116.       if(grab_pointer && bezier_sel->num_points == 0)
  1117.         {
  1118.           draw_core_pause(bezier_sel->core, tool);
  1119.           paths_dialog_set_default_op();
  1120.         }
  1121.     }
  1122.  
  1123.       if (!grab_pointer && channel_value (bezier_sel->mask, x, y))
  1124.     {
  1125.       replace = 0;
  1126.       if ((bevent->state & GDK_SHIFT_MASK) && !(bevent->state & GDK_CONTROL_MASK))
  1127.         op = ADD;
  1128.       else if ((bevent->state & GDK_CONTROL_MASK) && !(bevent->state & GDK_SHIFT_MASK))
  1129.         op = SUB;
  1130.       else if ((bevent->state & GDK_CONTROL_MASK) && (bevent->state & GDK_SHIFT_MASK))
  1131.         op = INTERSECT;
  1132.       else
  1133.         {
  1134.           op = ADD;
  1135.           replace = 1;
  1136.         }
  1137.       bezier_to_sel_internal(bezier_sel,tool,gdisp,op,replace);
  1138.       draw_core_resume (bezier_sel->core, tool);
  1139.     }
  1140.       else
  1141.     {
  1142.       /* draw the handles */
  1143.       if(!grab_pointer)
  1144.         {
  1145.           paths_dialog_set_default_op();
  1146.           bezier_start_new_segment(bezier_sel,x,y);
  1147.         }
  1148.        bezier_sel->draw = BEZIER_DRAW_ALL; 
  1149.  
  1150.       draw_core_resume (bezier_sel->core, tool);
  1151.     }
  1152.       break;
  1153.     }
  1154.  
  1155.   if (grab_pointer)
  1156.     gdk_pointer_grab (gdisp->canvas->window, FALSE,
  1157.               GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
  1158.               NULL, NULL, bevent->time);
  1159.  
  1160.   /* Don't bother doing this if we don't have any points */
  1161.   if(bezier_sel->num_points > 0)
  1162.     paths_first_button_press(bezier_sel,gdisp);
  1163. }
  1164.  
  1165. static void
  1166. bezier_select_button_release (Tool           *tool,
  1167.                   GdkEventButton *bevent,
  1168.                   gpointer        gdisp_ptr)
  1169. {
  1170.   GDisplay * gdisp;
  1171.   BezierSelect *bezier_sel;
  1172.  
  1173.   gdisp = tool->gdisp_ptr;
  1174.   bezier_sel = tool->private;
  1175.   bezier_sel->state &= ~(BEZIER_DRAG);
  1176.  
  1177.   gdk_pointer_ungrab (bevent->time);
  1178.   gdk_flush ();
  1179.  
  1180.   if (bezier_sel->closed)
  1181.     bezier_convert (bezier_sel, tool->gdisp_ptr, SUBDIVIDE, NO);
  1182.  
  1183.   /* Here ?*/
  1184.   paths_newpoint_current(bezier_sel,gdisp);
  1185. }
  1186.  
  1187.  
  1188. /* unused
  1189. static void
  1190. bez_copy_points(BezierSelect *tobez,
  1191.         BezierSelect *frombez)
  1192. {
  1193.   BezierPoint *pts;
  1194.   gint i;
  1195.   BezierPoint  *bpnt = NULL;
  1196.   int need_move = 0;
  1197.  
  1198.   pts = (BezierPoint *) frombez->points;
  1199.  
  1200.   for (i=0; i< frombez->num_points; i++)
  1201.     {
  1202.       if(need_move)
  1203.     {
  1204.       bezier_add_point( tobez, BEZIER_MOVE, pts->x, pts->y);
  1205.       need_move = 0;
  1206.     }
  1207.       else
  1208.     bezier_add_point( tobez, pts->type, pts->x, pts->y);
  1209.  
  1210.       if(pts == frombez->cur_anchor)
  1211.     tobez->cur_anchor = tobez->last_point;
  1212.       else if(pts == frombez->cur_control)
  1213.     tobez->cur_control = tobez->last_point;
  1214.  
  1215.       if(bpnt == NULL)
  1216.     bpnt = tobez->last_point;
  1217.  
  1218.       if(pts->next_curve)
  1219.     {
  1220.       tobez->last_point->next = bpnt;
  1221.       bpnt->prev = tobez->last_point;
  1222.       bpnt = NULL;
  1223.       need_move = 1;
  1224.       pts = pts->next_curve;
  1225.     }
  1226.       else
  1227.     {
  1228.       pts = pts->next;
  1229.     }
  1230.     }
  1231.       
  1232.   if ( frombez->closed )
  1233.     {
  1234.       tobez->last_point->next = bpnt;
  1235.       bpnt->prev = tobez->last_point;
  1236.       tobez->closed = 1;
  1237.     }
  1238. }
  1239. */
  1240.  
  1241. static void
  1242. bezier_select_motion (Tool           *tool,
  1243.               GdkEventMotion *mevent,
  1244.               gpointer        gdisp_ptr)
  1245. {
  1246.   static int lastx, lasty;
  1247.  
  1248.   GDisplay * gdisp;
  1249.   BezierSelect * bezier_sel;
  1250.   BezierPoint * anchor;
  1251.   BezierPoint * opposite_control;
  1252.   int offsetx;
  1253.   int offsety;
  1254.   int x, y;
  1255.  
  1256.   if (tool->state != ACTIVE)
  1257.     return;
  1258.  
  1259.   gdisp = gdisp_ptr;
  1260.   bezier_sel = tool->private;
  1261.  
  1262.   if (!bezier_sel->cur_anchor || !bezier_sel->cur_control)
  1263.     return;
  1264.  
  1265.   if (mevent->state & GDK_MOD1_MASK)
  1266.     {
  1267.       bezier_sel->draw = BEZIER_DRAW_ALL;
  1268.     }
  1269.   else
  1270.     {
  1271.       bezier_sel->draw = BEZIER_DRAW_CURRENT | BEZIER_DRAW_HANDLES;
  1272.     }
  1273.  
  1274.  
  1275.   draw_core_pause (bezier_sel->core, tool); 
  1276.  
  1277.   gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &x, &y, TRUE, 0);
  1278.  
  1279.   /* If this is the first point then change the state and "remember" the point.
  1280.    */
  1281.   if (!(bezier_sel->state & BEZIER_DRAG))
  1282.     {
  1283.       bezier_sel->state |= BEZIER_DRAG;
  1284.       lastx = x;
  1285.       lasty = y;
  1286.     }
  1287.  
  1288.   /* The Alt key is down... Move all the points of the bezier curve */
  1289.  
  1290.   if (mevent->state & GDK_MOD1_MASK)
  1291.     {
  1292.       BezierPoint *tmp = bezier_sel->points;
  1293.       gint num_points = bezier_sel->num_points;
  1294.       offsetx = x - lastx;
  1295.       offsety = y - lasty;
  1296.  
  1297.       if(mevent->state & GDK_SHIFT_MASK)
  1298.     {
  1299.       /* Only move this curve */
  1300.       BezierPoint *start_pt = bezier_sel->cur_anchor;
  1301.  
  1302. /*       g_print ("moving only one curve\n"); */
  1303.  
  1304.       tmp = start_pt;
  1305.       
  1306.       do {
  1307.         bezier_offset_point (tmp, offsetx, offsety);
  1308.         tmp = tmp->next;
  1309.       } while (tmp != start_pt && tmp);
  1310.       /* Check if need to go backwards because curve is open */
  1311.       if(!tmp && bezier_sel->cur_anchor->prev)
  1312.         {
  1313.           BezierPoint *start_pt = bezier_sel->cur_anchor->prev;
  1314.           tmp = start_pt;
  1315.           
  1316.           do {
  1317.         bezier_offset_point (tmp, offsetx, offsety);
  1318.         tmp = tmp->prev;
  1319.           } while (tmp != start_pt && tmp);
  1320.         }
  1321.     }
  1322.       else
  1323.     {
  1324.       while (tmp && num_points)
  1325.         {
  1326.           bezier_offset_point (tmp, offsetx, offsety);
  1327.           if(tmp->next_curve)
  1328.         tmp = tmp->next_curve;
  1329.           else
  1330.         tmp = tmp->next;
  1331.           num_points--;
  1332.         }
  1333.     }
  1334.     }
  1335.   else
  1336.   if (mevent->state & GDK_CONTROL_MASK)
  1337.     {
  1338.       /* the control key is down ... move the current anchor point */
  1339.       /* we must also move the neighboring control points appropriately */
  1340.  
  1341.       offsetx = x - lastx;
  1342.       offsety = y - lasty;
  1343.  
  1344.       bezier_offset_point (bezier_sel->cur_anchor, offsetx, offsety);
  1345.       bezier_offset_point (bezier_sel->cur_anchor->next, offsetx, offsety);
  1346.       bezier_offset_point (bezier_sel->cur_anchor->prev, offsetx, offsety);
  1347.     }
  1348.   else
  1349.     {
  1350.       /* the control key is not down ... we move the current control point */
  1351.  
  1352.       offsetx = x - bezier_sel->cur_control->x;
  1353.       offsety = y - bezier_sel->cur_control->y;
  1354.  
  1355.       bezier_offset_point (bezier_sel->cur_control, offsetx, offsety);
  1356.  
  1357.       /* if the shift key is not down then we align the opposite control */
  1358.       /* point...ie the opposite control point acts like a mirror of the */
  1359.       /* current control point */
  1360.  
  1361.       if (!(mevent->state & GDK_SHIFT_MASK))
  1362.     {
  1363.       anchor = NULL;
  1364.       opposite_control = NULL;
  1365.  
  1366.       if (bezier_sel->cur_control->next)
  1367.         {
  1368.           if (bezier_sel->cur_control->next->type == BEZIER_ANCHOR)
  1369.         {
  1370.           anchor = bezier_sel->cur_control->next;
  1371.           opposite_control = anchor->next;
  1372.         }
  1373.         }
  1374.       if (bezier_sel->cur_control->prev)
  1375.         {
  1376.           if (bezier_sel->cur_control->prev->type == BEZIER_ANCHOR)
  1377.         {
  1378.           anchor = bezier_sel->cur_control->prev;
  1379.           opposite_control = anchor->prev;
  1380.         }
  1381.         }
  1382.  
  1383.       if (!anchor)
  1384.         gimp_fatal_error ("bezier_select_motion(): Encountered orphaned bezier control point");
  1385.  
  1386.       if (opposite_control)
  1387.         {
  1388.           offsetx = bezier_sel->cur_control->x - anchor->x;
  1389.           offsety = bezier_sel->cur_control->y - anchor->y;
  1390.  
  1391.           opposite_control->x = anchor->x - offsetx;
  1392.           opposite_control->y = anchor->y - offsety;
  1393.         }
  1394.     }
  1395.     }
  1396.  
  1397.   /* As we're moving all the control points of the curve,
  1398.      we have to redraw all !!!
  1399.      */
  1400.  
  1401.   if ( mevent->state & GDK_MOD1_MASK)
  1402.     bezier_sel->draw = BEZIER_DRAW_ALL;
  1403.   else
  1404.     bezier_sel->draw = BEZIER_DRAW_CURRENT | BEZIER_DRAW_HANDLES;
  1405.  
  1406.   draw_core_resume (bezier_sel->core, tool);
  1407.  
  1408.   lastx = x;
  1409.   lasty = y;
  1410. }
  1411.  
  1412. /* returns 0 if not on control point, else BEZIER_ANCHOR or BEZIER_CONTROL */
  1413. static gint
  1414. bezier_on_control_point(GDisplay     *gdisp,
  1415.             BezierSelect *bezier_sel,
  1416.             gint         x,
  1417.             gint         y,
  1418.             gint         halfwidth)
  1419. {
  1420.   BezierPoint * points;
  1421.   gint num_points;
  1422.  
  1423.   /* transform the points from image space to screen space */
  1424.   points = bezier_sel->points;
  1425.   num_points = bezier_sel->num_points;
  1426.  
  1427.   while (points && num_points)
  1428.    {
  1429.      if(bezier_check_point(points,x,y,halfwidth))
  1430.        return points->type;
  1431.  
  1432.      if(points->next_curve)
  1433.        points = points->next_curve;
  1434.      else
  1435.        points = points->next;
  1436.      num_points--;
  1437.     }
  1438.  
  1439.   return FALSE;
  1440. }
  1441.  
  1442. static void
  1443. bezier_check_points (BezierSelect *bezier_sel,
  1444.              GdkPoint     *points,
  1445.              int           npoints,
  1446.              gpointer      udata)
  1447. {
  1448.   gint loop;
  1449.   int l, r, t, b;
  1450.   BezierCheckPnts *chkpnts = udata;
  1451.   gint halfwidth = chkpnts->halfwidth;
  1452.  
  1453.   /* Quick exit if already found */
  1454.  
  1455.   if(chkpnts->found)
  1456.     return;
  1457.  
  1458.   for(loop = 0 ; loop < npoints; loop++)
  1459.     {
  1460.       l = points[loop].x - halfwidth;
  1461.       r = points[loop].x + halfwidth;
  1462.       t = points[loop].y - halfwidth;
  1463.       b = points[loop].y + halfwidth;
  1464.  
  1465. /*       g_print ("x,y = [%d,%d] halfwidth %d l,r,t,d [%d,%d,%d,%d]\n", */
  1466. /*          points[loop].x, */
  1467. /*          points[loop].y, */
  1468. /*          halfwidth, */
  1469. /*          l,r,t,b); */
  1470.  
  1471.       if ((chkpnts->x >= l) && 
  1472.       (chkpnts->x <= r) && 
  1473.       (chkpnts->y >= t) && 
  1474.       (chkpnts->y <= b))
  1475.     {
  1476.       chkpnts->found = TRUE;
  1477.     }
  1478.     }
  1479. }
  1480.  
  1481. static gboolean 
  1482. points_in_box(BezierPoint *points,
  1483.           gint         x,
  1484.           gint         y)
  1485. {
  1486.   /* below code adapted from Wm. Randolph Franklin <wrf@ecse.rpi.edu>
  1487.    */
  1488.   int i, j, c = 0;
  1489.   double yp[4],xp[4];
  1490.  
  1491.   for (i = 0; i < 4; i++)
  1492.     {
  1493.       xp[i] = points->x;
  1494.       yp[i] = points->y;
  1495.       points = points->next;
  1496.     }
  1497.  
  1498.   /* Check if straight line ..below don't work if it is! */
  1499.   if((xp[0] == xp[1] && yp[0] == yp[1]) || 
  1500.      (xp[2] == xp[3] && yp[0] == yp[1]))
  1501.     return TRUE;
  1502.  
  1503.   for (i = 0, j = 3; i < 4; j = i++) {
  1504.     if ((((yp[i]<=y) && (y<yp[j])) ||
  1505.      ((yp[j]<=y) && (y<yp[i]))) &&
  1506.     (x < (xp[j] - xp[i]) * (y - yp[i]) / (yp[j] - yp[i]) + xp[i]))
  1507.       c = !c;
  1508.   }
  1509.  
  1510.   return c;
  1511. }
  1512.  
  1513. static gint
  1514. bezier_point_on_curve (GDisplay     *gdisp,
  1515.                BezierSelect *bezier_sel,
  1516.                gint          x,
  1517.                gint          y,
  1518.                gint          halfwidth)
  1519. {
  1520.   BezierCheckPnts chkpnts;
  1521.   BezierPoint * points;
  1522.   BezierPoint * start_pt;
  1523.   BezierPoint * next_curve;
  1524.   CountCurves * cnt = (CountCurves *)&chkpnts;
  1525.   gint point_counts = 0;
  1526.  
  1527.   chkpnts.x = x;
  1528.   chkpnts.y = y;
  1529.   chkpnts.halfwidth = halfwidth;
  1530.   chkpnts.found = FALSE;
  1531.  
  1532.   if (cnt)
  1533.     cnt->count = 0;
  1534.   points = bezier_sel->points;
  1535.   start_pt = bezier_sel->points;
  1536.  
  1537.   if (bezier_sel->num_points >= 4)
  1538.     {
  1539.       do
  1540.     {
  1541.       point_counts = count_points_on_curve(points);
  1542.       if (point_counts >= 4)
  1543.         {
  1544.           do
  1545.         {
  1546.           if (points_in_box (points, x, y))
  1547.             {
  1548.               bezier_draw_segment (bezier_sel, points,
  1549.                        SUBDIVIDE, IMAGE_COORDS,
  1550.                        bezier_check_points,
  1551.                        &chkpnts);
  1552.             }
  1553.           points = next_anchor (points, &next_curve);
  1554.           /*       g_print ("next_anchor = %p\n",points); */
  1555.         }
  1556.           while (points != start_pt && points);
  1557.           if (cnt)
  1558.         cnt->count++;
  1559.           start_pt = next_curve;
  1560.           points = next_curve;
  1561.         }
  1562.       else
  1563.         break; /* must be last curve since only this one is allowed < 4
  1564.             * points.
  1565.             */
  1566.     }
  1567.       while (next_curve);
  1568.     }
  1569.  
  1570.   return chkpnts.found;
  1571. }
  1572.  
  1573. static void
  1574. bezier_select_cursor_update (Tool           *tool,
  1575.                  GdkEventMotion *mevent,
  1576.                  gpointer        gdisp_ptr)
  1577. {
  1578.   GDisplay *gdisp;
  1579.   BezierSelect * bezier_sel;
  1580.   gboolean on_curve;
  1581.   gboolean on_control_pnt;
  1582.   gboolean in_selection_area;
  1583.   gint halfwidth,dummy;
  1584.   gint x,y;
  1585.  
  1586.   gdisp = (GDisplay *) gdisp_ptr;
  1587.  
  1588.   bezier_sel = tool->private;
  1589.  
  1590.   if (gdisp != tool->gdisp_ptr || bezier_sel->core->draw_state == INVISIBLE)
  1591.     {
  1592.       gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
  1593.                     BEZIER_SELECT,
  1594.                     CURSOR_MODIFIER_NONE,
  1595.                     FALSE);
  1596.       return;
  1597.     }
  1598.  
  1599.   gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &x, &y, TRUE, 0);
  1600.  
  1601.   /* get halfwidth in image coord */
  1602.   gdisplay_untransform_coords (gdisp, mevent->x + BEZIER_HALFWIDTH, 0,
  1603.                    &halfwidth, &dummy, TRUE, 0);
  1604.   halfwidth -= x;
  1605.  
  1606.   on_control_pnt = bezier_on_control_point (gdisp, bezier_sel, x, y, halfwidth);
  1607.  
  1608.   on_curve = bezier_point_on_curve (gdisp, bezier_sel, x, y, halfwidth);
  1609.  
  1610.   if (bezier_sel->mask && bezier_sel->closed &&
  1611.       channel_value(bezier_sel->mask, x, y) && 
  1612.       !on_control_pnt &&
  1613.       (!on_curve || ModeEdit != EXTEND_ADD))
  1614.     {
  1615.       in_selection_area = TRUE;
  1616.       if ((mevent->state & GDK_SHIFT_MASK) &&
  1617.       !(mevent->state & GDK_CONTROL_MASK))
  1618.     {
  1619.       gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
  1620.                     RECT_SELECT,
  1621.                     CURSOR_MODIFIER_PLUS,
  1622.                     FALSE);
  1623.     }
  1624.       else if ((mevent->state & GDK_CONTROL_MASK) &&
  1625.            !(mevent->state & GDK_SHIFT_MASK))
  1626.     {
  1627.       gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
  1628.                     RECT_SELECT,
  1629.                     CURSOR_MODIFIER_MINUS,
  1630.                     FALSE);
  1631.     }
  1632.       else if ((mevent->state & GDK_CONTROL_MASK) &&
  1633.            (mevent->state & GDK_SHIFT_MASK))
  1634.     {
  1635.       gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
  1636.                     RECT_SELECT,
  1637.                     CURSOR_MODIFIER_INTERSECT,
  1638.                     FALSE);
  1639.     }
  1640.       else
  1641.     {
  1642.       gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
  1643.                     RECT_SELECT,
  1644.                     CURSOR_MODIFIER_NONE,
  1645.                     FALSE);
  1646.     }
  1647.       return;
  1648.     }
  1649.  
  1650.   if (mevent->state & GDK_MOD1_MASK)
  1651.     {
  1652.       /* Moving curve */
  1653.       if (mevent->state & GDK_SHIFT_MASK)
  1654.     {
  1655.       /* moving on 1 curve */
  1656.       gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
  1657.                     BEZIER_SELECT,
  1658.                     CURSOR_MODIFIER_MOVE,
  1659.                     FALSE);
  1660.     }
  1661.       else
  1662.     {
  1663.       gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
  1664.                     BEZIER_SELECT,
  1665.                     CURSOR_MODIFIER_MOVE,
  1666.                     FALSE);
  1667.     }
  1668.     }
  1669.   else
  1670.     {
  1671.       switch (ModeEdit)
  1672.     {
  1673.     case EXTEND_NEW:
  1674.       if (on_control_pnt && bezier_sel->closed)
  1675.         {
  1676.           gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
  1677.                         BEZIER_SELECT,
  1678.                         CURSOR_MODIFIER_CONTROL,
  1679.                         FALSE);
  1680. /*           g_print ("add to curve cursor\n"); */
  1681.         }
  1682.       else if (on_curve)
  1683.         {
  1684.           gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
  1685.                         BEZIER_SELECT,
  1686.                         CURSOR_MODIFIER_NONE,
  1687.                         FALSE);
  1688. /*           g_print ("edit control point cursor\n"); */
  1689.         }
  1690.       else
  1691.         {
  1692.           gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
  1693.                         BEZIER_SELECT,
  1694.                         CURSOR_MODIFIER_NONE,
  1695.                         FALSE);
  1696.         }
  1697.       break;
  1698.     case EXTEND_ADD:
  1699.       if (on_curve)
  1700.         {
  1701.           gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
  1702.                         BEZIER_SELECT,
  1703.                         CURSOR_MODIFIER_PLUS,
  1704.                         FALSE);
  1705. /*           g_print ("add to curve cursor\n"); */
  1706.         }
  1707.       else
  1708.         {
  1709.           gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
  1710.                         BEZIER_SELECT,
  1711.                         CURSOR_MODIFIER_NONE,
  1712.                         FALSE);
  1713. /*           g_print ("default no action cursor\n"); */
  1714.         }
  1715.       break;
  1716.     case EXTEND_EDIT:
  1717.       if (on_control_pnt)
  1718.         {
  1719.           gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
  1720.                         BEZIER_SELECT,
  1721.                         CURSOR_MODIFIER_CONTROL,
  1722.                         FALSE);
  1723. /*           g_print ("edit control point cursor\n"); */
  1724.         }
  1725.       else
  1726.         {
  1727.           gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
  1728.                         BEZIER_SELECT,
  1729.                         CURSOR_MODIFIER_NONE,
  1730.                         FALSE);
  1731. /*           g_print ("default no action cursor\n"); */
  1732.         }
  1733.       break;
  1734.     case EXTEND_REMOVE:
  1735.       if (on_control_pnt && mevent->state & GDK_SHIFT_MASK)
  1736.         {
  1737.           gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
  1738.                         BEZIER_SELECT,
  1739.                         CURSOR_MODIFIER_MINUS,
  1740.                         FALSE);
  1741. /*            g_print ("delete whole curve cursor\n"); */
  1742.         }
  1743.       else if (on_control_pnt)
  1744.         {
  1745.           gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
  1746.                         BEZIER_SELECT,
  1747.                         CURSOR_MODIFIER_MINUS,
  1748.                         FALSE);
  1749. /*           g_print ("remove point cursor\n"); */
  1750.         }
  1751.       else
  1752.         {
  1753.           gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
  1754.                         BEZIER_SELECT,
  1755.                         CURSOR_MODIFIER_NONE,
  1756.                         FALSE);
  1757. /*           g_print ("default no action cursor\n"); */
  1758.         }
  1759.       break;
  1760.     default:
  1761.       g_print ("In default\n");
  1762.       gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
  1763.                     BEZIER_SELECT,
  1764.                     CURSOR_MODIFIER_NONE,
  1765.                     FALSE);
  1766.       break;
  1767.     }
  1768.     }
  1769. }
  1770.  
  1771. static void
  1772. bezier_select_control (Tool       *tool,
  1773.                ToolAction  action,
  1774.                gpointer    gdisp_ptr)
  1775. {
  1776.   BezierSelect * bezier_sel;
  1777.  
  1778.   bezier_sel = tool->private;
  1779.  
  1780.   switch (action)
  1781.     {
  1782.     case PAUSE :
  1783.       draw_core_pause (bezier_sel->core, tool);
  1784.       break;
  1785.  
  1786.     case RESUME :
  1787.       draw_core_resume (bezier_sel->core, tool);
  1788.       break;
  1789.  
  1790.     case HALT :
  1791.       draw_core_stop (bezier_sel->core, tool);
  1792.       bezier_select_reset (bezier_sel);
  1793.       break;
  1794.  
  1795.     default:
  1796.       break;
  1797.     }
  1798. }
  1799.  
  1800. void 
  1801. bezier_draw(GDisplay * gdisp,BezierSelect * bezier_sel)
  1802. {
  1803.   BezierPoint * points;
  1804.   int num_points;
  1805.   int draw_curve;
  1806.   int draw_handles;
  1807.   int draw_current;
  1808.  
  1809.  
  1810.   if (!bezier_sel->draw)
  1811.     return;
  1812.  
  1813.   draw_curve = bezier_sel->draw & BEZIER_DRAW_CURVE;
  1814.   draw_current = bezier_sel->draw & BEZIER_DRAW_CURRENT;
  1815.   draw_handles = bezier_sel->draw & BEZIER_DRAW_HANDLES;
  1816.  
  1817.   /* reset to the default drawing state of drawing the curve and handles */
  1818.   bezier_sel->draw = BEZIER_DRAW_ALL;
  1819.  
  1820.   /* transform the points from image space to screen space */
  1821.   points = bezier_sel->points;
  1822.   num_points = bezier_sel->num_points;
  1823.  
  1824.   while (points && num_points)
  1825.    {
  1826.       gdisplay_transform_coords (gdisp, points->x, points->y,
  1827.                  &points->sx, &points->sy, 0);
  1828.       if(points->next_curve)
  1829.     points = points->next_curve;
  1830.       else
  1831.     points = points->next;
  1832.       num_points--;
  1833.     }
  1834.  
  1835.   if (draw_curve)
  1836.     {
  1837.       bezier_draw_curve (bezier_sel,bezier_draw_segment_points,SCREEN_COORDS,NULL);
  1838.       bezier_draw_handles (bezier_sel,1);
  1839.     }
  1840.   else if (draw_current)
  1841.     {
  1842.       bezier_draw_current (bezier_sel);
  1843.       bezier_draw_handles (bezier_sel,0);
  1844.     }
  1845.   else if (draw_handles) 
  1846.     {
  1847.       bezier_draw_handles (bezier_sel,0); 
  1848.     }
  1849.  
  1850. }
  1851.  
  1852. static void
  1853. bezier_select_draw (Tool *tool)
  1854. {
  1855.   GDisplay * gdisp;
  1856.   BezierSelect * bezier_sel;
  1857.  
  1858.   gdisp = tool->gdisp_ptr;
  1859.   bezier_sel = tool->private;
  1860.  
  1861.   bezier_draw(gdisp,bezier_sel);
  1862. }
  1863.  
  1864.  
  1865.  
  1866. void
  1867. bezier_add_point (BezierSelect *bezier_sel,
  1868.           int           type,
  1869.           gdouble       x,
  1870.           gdouble       y)
  1871. {
  1872.   BezierPoint *newpt;
  1873.  
  1874.   newpt = g_new0 (BezierPoint,1);
  1875.  
  1876.   newpt->type = type;
  1877.   newpt->x = x;
  1878.   newpt->y = y;
  1879.   newpt->next = NULL;
  1880.   newpt->prev = NULL;
  1881.   newpt->next_curve = NULL;
  1882.  
  1883.   if(type == BEZIER_MOVE &&
  1884.      bezier_sel->last_point)
  1885.     {
  1886. /*       g_print ("Adding move point\n"); */
  1887.       newpt->type = BEZIER_ANCHOR;
  1888.       bezier_sel->last_point->next_curve = newpt;
  1889.       bezier_sel->last_point = newpt;
  1890.       bezier_sel->cur_anchor = newpt;
  1891.     }
  1892.   else
  1893.     {
  1894.       if(type == BEZIER_MOVE) 
  1895.     {
  1896.       newpt->type = BEZIER_ANCHOR;
  1897. /*       g_print ("Adding MOVE point to null curve\n"); */
  1898.     }
  1899.  
  1900.       if (bezier_sel->last_point)
  1901.     {
  1902.       bezier_sel->last_point->next = newpt;
  1903.       newpt->prev = bezier_sel->last_point;
  1904.       bezier_sel->last_point = newpt;
  1905.     }
  1906.       else
  1907.     {
  1908.       bezier_sel->points = newpt;
  1909.       bezier_sel->last_point = newpt;
  1910.     }
  1911.       
  1912.       switch (type)
  1913.     {
  1914.     case BEZIER_ANCHOR:
  1915.       bezier_sel->cur_anchor = newpt;
  1916.       break;
  1917.     case BEZIER_CONTROL:
  1918.       bezier_sel->cur_control = newpt;
  1919.       break;
  1920.     }
  1921.     }
  1922.  
  1923.   bezier_sel->num_points += 1;
  1924. }
  1925.  
  1926. static void
  1927. bezier_offset_point (BezierPoint *pt,
  1928.              int          x,
  1929.              int          y)
  1930. {
  1931.   if (pt)
  1932.     {
  1933.       pt->x += x;
  1934.       pt->y += y;
  1935.     }
  1936. }
  1937.  
  1938. static int
  1939. bezier_check_point (BezierPoint *pt,
  1940.             int          x,
  1941.             int          y,
  1942.             int         halfwidth)
  1943. {
  1944.   int l, r, t, b;
  1945.  
  1946.   if (pt)
  1947.     {
  1948.       l = pt->x - halfwidth;
  1949.       r = pt->x + halfwidth;
  1950.       t = pt->y - halfwidth;
  1951.       b = pt->y + halfwidth;
  1952.  
  1953.       return ((x >= l) && (x <= r) && (y >= t) && (y <= b));
  1954.     }
  1955.  
  1956.   return 0;
  1957. }
  1958.  
  1959.  
  1960. static void
  1961. bezier_draw_handles (BezierSelect *bezier_sel,gint doAll)
  1962. {
  1963.   BezierPoint * points;
  1964.   int num_points;
  1965.  
  1966.   points = bezier_sel->points;
  1967.   num_points = bezier_sel->num_points;
  1968.  
  1969.   if (num_points <= 0)
  1970.     return;
  1971.  
  1972.   while (num_points && num_points > 0)
  1973.   {
  1974.       if (points == bezier_sel->cur_anchor)
  1975.     {
  1976. /*     g_print ("bezier_draw_handles:: found cur_anchor %p\n",points); */
  1977.       bezier_draw_point (bezier_sel, points, 0);
  1978.       bezier_draw_point (bezier_sel, points->next, 0);
  1979.       bezier_draw_point (bezier_sel, points->prev, 0);
  1980.       bezier_draw_line (bezier_sel, points, points->next);
  1981.       bezier_draw_line (bezier_sel, points, points->prev);
  1982.     }
  1983.       else
  1984.     {
  1985. /*     g_print ("bezier_draw_handles:: not found cur_anchor %p\n",points); */
  1986.       if(doAll || points->pointflags == 1)
  1987.         {
  1988.           bezier_draw_point (bezier_sel, points, 1);
  1989.           points->pointflags = 0;
  1990.         }
  1991.     }
  1992.  
  1993.       if(points)
  1994.       {
  1995.         if(points->next_curve)
  1996.           points = points->next_curve;
  1997.         else
  1998.           points = points->next;
  1999.       }
  2000.  
  2001.       if(points)
  2002.       {
  2003.         if(points->next_curve)
  2004.           points = points->next_curve;
  2005.         else
  2006.           points = points->next;
  2007.       }
  2008.  
  2009.       if(points)
  2010.       {
  2011.         if(points->next_curve)
  2012.           points = points->next_curve;
  2013.         else
  2014.           points = points->next;
  2015.       }
  2016.  
  2017.       num_points -= 3;
  2018.    }
  2019. }
  2020.  
  2021. static void
  2022. bezier_draw_current (BezierSelect *bezier_sel)
  2023. {
  2024.   BezierPoint * points;
  2025.  
  2026.   points = bezier_sel->cur_anchor;
  2027.  
  2028.   if (points) points = points->prev;
  2029.   if (points) points = points->prev;
  2030.   if (points) points = points->prev;
  2031.  
  2032.   if (points)
  2033.     bezier_draw_segment (bezier_sel, points,
  2034.              SUBDIVIDE, SCREEN_COORDS,
  2035.              bezier_draw_segment_points,
  2036.              NULL);
  2037.  
  2038.   if (points != bezier_sel->cur_anchor)
  2039.     {
  2040.       points = bezier_sel->cur_anchor;
  2041.  
  2042.       if (points) points = points->next;
  2043.       if (points) points = points->next;
  2044.       if (points) points = points->next;
  2045.  
  2046.       if (points)
  2047.     bezier_draw_segment (bezier_sel, bezier_sel->cur_anchor,
  2048.                  SUBDIVIDE, SCREEN_COORDS,
  2049.                  bezier_draw_segment_points,
  2050.                  NULL);
  2051.     }
  2052. }
  2053.  
  2054. static void
  2055. bezier_draw_point (BezierSelect *bezier_sel,
  2056.            BezierPoint  *pt,
  2057.            int           fill)
  2058. {
  2059.   if (pt)
  2060.     {
  2061.       switch (pt->type)
  2062.     {
  2063.     case BEZIER_ANCHOR:
  2064.       if (fill)
  2065.         {
  2066.           gdk_draw_arc (bezier_sel->core->win, bezier_sel->core->gc, 1,
  2067.                 pt->sx - BEZIER_HALFWIDTH, pt->sy - BEZIER_HALFWIDTH,
  2068.                 BEZIER_WIDTH, BEZIER_WIDTH, 0, 23040);
  2069.         }
  2070.       else
  2071.         {
  2072.           gdk_draw_arc (bezier_sel->core->win, bezier_sel->core->gc, 0,
  2073.                 pt->sx - BEZIER_HALFWIDTH, pt->sy - BEZIER_HALFWIDTH,
  2074.                 BEZIER_WIDTH, BEZIER_WIDTH, 0, 23040);
  2075.         }
  2076.       break;
  2077.     case BEZIER_CONTROL:
  2078.       if (fill)
  2079.         {
  2080.           gdk_draw_rectangle (bezier_sel->core->win, bezier_sel->core->gc, 1,
  2081.                   pt->sx - BEZIER_HALFWIDTH, pt->sy - BEZIER_HALFWIDTH,
  2082.                   BEZIER_WIDTH, BEZIER_WIDTH);
  2083.         }
  2084.       else
  2085.         {
  2086.           gdk_draw_rectangle (bezier_sel->core->win, bezier_sel->core->gc, 0,
  2087.                   pt->sx - BEZIER_HALFWIDTH, pt->sy - BEZIER_HALFWIDTH,
  2088.                   BEZIER_WIDTH, BEZIER_WIDTH);
  2089.         }
  2090.       break;
  2091.     }
  2092.     }
  2093. }
  2094.  
  2095. static void
  2096. bezier_draw_line (BezierSelect *bezier_sel,
  2097.           BezierPoint  *pt1,
  2098.           BezierPoint  *pt2)
  2099. {
  2100.   if (pt1 && pt2)
  2101.     {
  2102.       gdk_draw_line (bezier_sel->core->win,
  2103.              bezier_sel->core->gc,
  2104.              pt1->sx, pt1->sy, pt2->sx, pt2->sy);
  2105.     }
  2106. }
  2107.  
  2108. static void
  2109. bezier_draw_segment (BezierSelect     *bezier_sel,
  2110.              BezierPoint      *points,
  2111.              int               subdivisions,
  2112.              int               space,
  2113.              BezierPointsFunc  points_func,
  2114.              gpointer          udata)
  2115. {
  2116.   static GdkPoint gdk_points[256];
  2117.   static int npoints = 256;
  2118.  
  2119.   BezierMatrix geometry;
  2120.   BezierMatrix tmp1, tmp2;
  2121.   BezierMatrix deltas;
  2122.   double x, dx, dx2, dx3;
  2123.   double y, dy, dy2, dy3;
  2124.   double d, d2, d3;
  2125.   int lastx, lasty; 
  2126.   int newx, newy;   
  2127.   int index;
  2128.   int i;
  2129.  
  2130.   /* construct the geometry matrix from the segment */
  2131.   /* assumes that a valid segment containing 4 points is passed in */
  2132.  
  2133.   for (i = 0; i < 4; i++)
  2134.     {
  2135.       if (!points)
  2136.     gimp_fatal_error ("bezier_draw_segment(): Bad bezier segment");
  2137.  
  2138.       switch (space)
  2139.     {
  2140.     case IMAGE_COORDS:
  2141.       geometry[i][0] = points->x;
  2142.       geometry[i][1] = points->y;
  2143.       break;
  2144.     case AA_IMAGE_COORDS:
  2145.       geometry[i][0] = (points->x * SUPERSAMPLE); 
  2146.       geometry[i][1] = (points->y * SUPERSAMPLE); 
  2147.       break;
  2148.     case SCREEN_COORDS:
  2149.       geometry[i][0] = points->sx;
  2150.       geometry[i][1] = points->sy;
  2151.       break;
  2152.     default:
  2153.       gimp_fatal_error ("bezier_draw_segment(): Unknown coordinate space: %d", space);
  2154.       break;
  2155.     }
  2156.  
  2157.       geometry[i][2] = 0;
  2158.       geometry[i][3] = 0;
  2159.  
  2160.       points = points->next;
  2161.     }
  2162.  
  2163.   /* subdivide the curve n times */
  2164.   /* n can be adjusted to give a finer or coarser curve */
  2165.  
  2166.   d = 1.0 / subdivisions;
  2167.   d2 = d * d;
  2168.   d3 = d * d * d;
  2169.  
  2170.   /* construct a temporary matrix for determining the forward diffencing deltas */
  2171.  
  2172.   tmp2[0][0] = 0;     tmp2[0][1] = 0;     tmp2[0][2] = 0;    tmp2[0][3] = 1;
  2173.   tmp2[1][0] = d3;    tmp2[1][1] = d2;    tmp2[1][2] = d;    tmp2[1][3] = 0;
  2174.   tmp2[2][0] = 6*d3;  tmp2[2][1] = 2*d2;  tmp2[2][2] = 0;    tmp2[2][3] = 0;
  2175.   tmp2[3][0] = 6*d3;  tmp2[3][1] = 0;     tmp2[3][2] = 0;    tmp2[3][3] = 0;
  2176.  
  2177.   /* compose the basis and geometry matrices */
  2178.   bezier_compose (basis, geometry, tmp1);
  2179.  
  2180.   /* compose the above results to get the deltas matrix */
  2181.   bezier_compose (tmp2, tmp1, deltas);
  2182.  
  2183.   /* extract the x deltas */
  2184.   x = deltas[0][0];
  2185.   dx = deltas[1][0];
  2186.   dx2 = deltas[2][0];
  2187.   dx3 = deltas[3][0];
  2188.  
  2189.   /* extract the y deltas */
  2190.   y = deltas[0][1];
  2191.   dy = deltas[1][1];
  2192.   dy2 = deltas[2][1];
  2193.   dy3 = deltas[3][1];
  2194.  
  2195.   lastx = x;
  2196.   lasty = y;
  2197.  
  2198.   gdk_points[0].x = (lastx); 
  2199.   gdk_points[0].y = (lasty); 
  2200.   index = 1;
  2201.  
  2202.   /* loop over the curve */
  2203.   for (i = 0; i < subdivisions; i++)
  2204.     {
  2205.       /* increment the x values */
  2206.       x += dx;
  2207.       dx += dx2;
  2208.       dx2 += dx3;
  2209.  
  2210.       /* increment the y values */
  2211.       y += dy;
  2212.       dy += dy2;
  2213.       dy2 += dy3;
  2214.  
  2215.       newx = ROUND (x);
  2216.       newy = ROUND (y);
  2217.  
  2218.       /* if this point is different than the last one...then draw it */
  2219.       if ((lastx != newx) || (lasty != newy))
  2220.     {
  2221.       /* add the point to the point buffer */
  2222.       gdk_points[index].x = (newx); 
  2223.       gdk_points[index].y = (newy); 
  2224.       index++;
  2225.  
  2226.       /* if the point buffer is full put it to the screen and zero it out */
  2227.       if (index >= npoints)
  2228.         {
  2229.           (* points_func) (bezier_sel, gdk_points, index, udata);
  2230.           index = 0;
  2231.         }
  2232.     }
  2233.  
  2234.       lastx = newx;
  2235.       lasty = newy;
  2236.     }
  2237.  
  2238.   /* if there are points in the buffer, then put them on the screen */
  2239.   if (index)
  2240.     (* points_func) (bezier_sel, gdk_points, index, udata);
  2241. }
  2242.  
  2243. static void
  2244. bezier_draw_segment_points (BezierSelect *bezier_sel,
  2245.                 GdkPoint     *points,
  2246.                 int           npoints,
  2247.                 gpointer      udata)
  2248. {
  2249.   gdk_draw_points (bezier_sel->core->win,
  2250.            bezier_sel->core->gc, points, npoints);
  2251. }
  2252.  
  2253. static void
  2254. bezier_compose (BezierMatrix a,
  2255.         BezierMatrix b,
  2256.         BezierMatrix ab)
  2257. {
  2258.   int i, j;
  2259.  
  2260.   for (i = 0; i < 4; i++)
  2261.     {
  2262.       for (j = 0; j < 4; j++)
  2263.         {
  2264.           ab[i][j] = (a[i][0] * b[0][j] +
  2265.                       a[i][1] * b[1][j] +
  2266.                       a[i][2] * b[2][j] +
  2267.                       a[i][3] * b[3][j]);
  2268.         }
  2269.     }
  2270. }
  2271.  
  2272. static int start_convert;
  2273. static int width, height;
  2274. static int lastx;
  2275. static int lasty;
  2276.  
  2277. static void
  2278. bezier_convert (BezierSelect *bezier_sel,
  2279.         GDisplay     *gdisp,
  2280.         int           subdivisions,
  2281.         int           antialias)
  2282. {
  2283.   PixelRegion maskPR;
  2284.   BezierPoint * points;
  2285.   BezierPoint * start_pt;
  2286.   BezierPoint * next_curve;
  2287.   GSList * list;
  2288.   unsigned char *buf, *b;
  2289.   int draw_type;
  2290.   int * vals, val;
  2291.   int start, end;
  2292.   int x, x2, w;
  2293.   int i, j;
  2294.  
  2295.   if (!bezier_sel->closed)
  2296.     gimp_fatal_error ("bezier_convert(): tried to convert an open bezier curve");
  2297.  
  2298.   /* destroy previous mask */
  2299.   if (bezier_sel->mask)
  2300.     {
  2301.       channel_delete (bezier_sel->mask);
  2302.       bezier_sel->mask = NULL;
  2303.     }
  2304.  
  2305.   /* get the new mask's maximum extents */
  2306.   if (antialias)
  2307.     {
  2308.       buf = (unsigned char *) g_malloc (width);
  2309.       width = gdisp->gimage->width * SUPERSAMPLE;
  2310.       height = gdisp->gimage->height * SUPERSAMPLE;
  2311.       draw_type = AA_IMAGE_COORDS;
  2312.       /* allocate value array  */
  2313.       vals = (int *) g_malloc (sizeof (int) * width);
  2314.     }
  2315.   else
  2316.     {
  2317.       buf = NULL;
  2318.       width = gdisp->gimage->width;
  2319.       height = gdisp->gimage->height;
  2320.       draw_type = IMAGE_COORDS;
  2321.       vals = NULL;
  2322.     }
  2323.  
  2324.   /* create a new mask */
  2325.   bezier_sel->mask = channel_ref (channel_new_mask (gdisp->gimage, 
  2326.                             gdisp->gimage->width,
  2327.                             gdisp->gimage->height));
  2328.  
  2329.   /* allocate room for the scanlines */
  2330.   bezier_sel->scanlines = g_malloc (sizeof (GSList *) * height);
  2331.  
  2332.   /* zero out the scanlines */
  2333.   for (i = 0; i < height; i++)
  2334.     bezier_sel->scanlines[i] = NULL;
  2335.  
  2336.   /* scan convert the curve */
  2337.   points = bezier_sel->points;
  2338.   start_pt = bezier_sel->points;
  2339.  
  2340.   do {
  2341.     start_convert = 1;
  2342.     do {
  2343.       bezier_draw_segment (bezier_sel, points,
  2344.                subdivisions, draw_type,
  2345.                bezier_convert_points,
  2346.                NULL);
  2347.  
  2348.       /*  advance to the next segment  */
  2349.       points = next_anchor(points,&next_curve);
  2350.     } while (points != start_pt && points);
  2351.     start_pt = next_curve;
  2352.     points = next_curve;
  2353.   } while (next_curve);
  2354.  
  2355.   pixel_region_init (&maskPR, drawable_data (GIMP_DRAWABLE(bezier_sel->mask)), 
  2356.              0, 0,
  2357.              drawable_width (GIMP_DRAWABLE(bezier_sel->mask)),
  2358.              drawable_height (GIMP_DRAWABLE(bezier_sel->mask)), TRUE);
  2359.   for (i = 0; i < height; i++)
  2360.     {
  2361.       list = bezier_sel->scanlines[i];
  2362.  
  2363.       /*  zero the vals array  */
  2364.       if (antialias && !(i % SUPERSAMPLE))
  2365.     memset (vals, 0, width * sizeof (int));
  2366.  
  2367.       while (list)
  2368.         {
  2369.           x = (long) list->data; 
  2370.           list = list->next; 
  2371. /*
  2372.           if (!list)
  2373.         g_message ("cannot properly scanline convert bezier curve: %d", i);
  2374.           else
  2375. */
  2376.             {
  2377.           /*  bounds checking  */
  2378.           x = CLAMP (x, 0, width);
  2379.           x2 = CLAMP ((long) list->data, 0, width);
  2380.  
  2381.           w = x2 - x;
  2382.  
  2383.           if (!antialias)
  2384.         channel_add_segment (bezier_sel->mask, x, i, w, 255);
  2385.           else
  2386.         for (j = 0; j < w; j++)
  2387.           vals[j + x] += 255;
  2388.  
  2389.               list = g_slist_next (list);
  2390.             }
  2391.         }
  2392.  
  2393.       if (antialias && !((i+1) % SUPERSAMPLE))
  2394.     {
  2395.       b = buf;
  2396.       start = 0;
  2397.       end = width;
  2398.       for (j = start; j < end; j += SUPERSAMPLE)
  2399.         {
  2400.           val = 0;
  2401.           for (x = 0; x < SUPERSAMPLE; x++)
  2402.         val += vals[j + x];
  2403.  
  2404.           *b++ = (unsigned char) (val / SUPERSAMPLE2);
  2405.         }
  2406.  
  2407.       pixel_region_set_row (&maskPR, 0, (i / SUPERSAMPLE), 
  2408.                 drawable_width (GIMP_DRAWABLE(bezier_sel->mask)), buf);
  2409.     }
  2410.  
  2411.       g_slist_free (bezier_sel->scanlines[i]);
  2412.     }
  2413.  
  2414.   if (antialias)
  2415.     {
  2416.       g_free (vals);
  2417.       g_free (buf);
  2418.     }
  2419.  
  2420.   g_free (bezier_sel->scanlines);
  2421.   bezier_sel->scanlines = NULL;
  2422.  
  2423.   channel_invalidate_bounds (bezier_sel->mask);
  2424. }
  2425.  
  2426. static void
  2427. bezier_convert_points (BezierSelect *bezier_sel,
  2428.                GdkPoint     *points,
  2429.                int           npoints,
  2430.                gpointer      udata)
  2431. {
  2432.   int i;
  2433.  
  2434.   if (start_convert)
  2435.     start_convert = 0;
  2436.   else
  2437.     bezier_convert_line (bezier_sel->scanlines, lastx, lasty, points[0].x, points[0].y);
  2438.  
  2439.   for (i = 0; i < (npoints - 1); i++)
  2440.     {
  2441.       bezier_convert_line (bezier_sel->scanlines,
  2442.                points[i].x, points[i].y,
  2443.                points[i+1].x, points[i+1].y);
  2444.     }
  2445.  
  2446.   lastx = points[npoints-1].x;
  2447.   lasty = points[npoints-1].y;
  2448. }
  2449.  
  2450. static void
  2451. bezier_convert_line (GSList ** scanlines,
  2452.              int       x1,
  2453.              int       y1,
  2454.              int       x2,
  2455.              int       y2)
  2456. {
  2457.   int    dx, dy; 
  2458.   int    error, inc; 
  2459.   int    tmp;
  2460.   double slope;
  2461.  
  2462.   if (y1 == y2)
  2463.     return;
  2464.  
  2465.   if (y1 > y2)
  2466.     {
  2467.       tmp = y2; y2 = y1; y1 = tmp;
  2468.       tmp = x2; x2 = x1; x1 = tmp;
  2469.     }
  2470.  
  2471.   if (y1 < 0)
  2472.     {
  2473.       if (y2 < 0)
  2474.     return;
  2475.  
  2476.       if (x2 == x1)
  2477.     {
  2478.       y1 = 0;
  2479.     }
  2480.       else
  2481.     {
  2482.       slope = (double) (y2 - y1) / (double) (x2 - x1); 
  2483.       x1 = x2 + (int)(0.5 + (double)(0 - y2) / slope);
  2484.       y1 = 0;
  2485.     }
  2486.     }
  2487.  
  2488.   if (y2 >= height)
  2489.     {
  2490.       if (y1 >= height)
  2491.     return;
  2492.  
  2493.       if (x2 == x1)
  2494.     {
  2495.       y2 = height;
  2496.     }
  2497.       else
  2498.     {
  2499.       slope = (double) (y2 - y1) / (double) (x2 - x1); 
  2500.       x2 = x1 + (int)(0.5 + (double)(height - y1) / slope);
  2501.       y2 = height;
  2502.     }
  2503.     }
  2504.  
  2505.   if (y1 == y2)
  2506.     return;
  2507.  
  2508.   dx = x2 - x1;
  2509.   dy = y2 - y1;
  2510.  
  2511.   scanlines = &scanlines[y1];
  2512.  
  2513.   if (((dx < 0) ? -dx : dx) > ((dy < 0) ? -dy : dy))
  2514.     {
  2515.       if (dx < 0)
  2516.         {
  2517.           inc = -1;
  2518.           dx = -dx;
  2519.         }
  2520.       else
  2521.         {
  2522.           inc = 1;
  2523.         }
  2524.  
  2525.       error = -dx /2;
  2526.       while (x1 != x2)
  2527.         {
  2528.           error += dy;
  2529.           if (error > 0)
  2530.             {
  2531.               error -= dx;
  2532.           *scanlines = bezier_insert_in_list (*scanlines, x1); 
  2533.           scanlines++;
  2534.             }
  2535.  
  2536.           x1 += inc;
  2537.         }
  2538.     }
  2539.   else
  2540.     {
  2541.       error = -dy /2;
  2542.       if (dx < 0)
  2543.         {
  2544.           dx = -dx;
  2545.           inc = -1;
  2546.         }
  2547.       else
  2548.         {
  2549.           inc = 1;
  2550.         }
  2551.  
  2552.       while (y1++ < y2)
  2553.         {
  2554.       *scanlines = bezier_insert_in_list (*scanlines, x1); 
  2555.       scanlines++;
  2556.  
  2557.           error += dx;
  2558.           if (error > 0)
  2559.             {
  2560.               error -= dy;
  2561.               x1 += inc;
  2562.             }
  2563.         }
  2564.     }
  2565. }
  2566.  
  2567. static GSList *
  2568. bezier_insert_in_list (GSList * list,
  2569.                int      x)
  2570. {
  2571.   GSList * orig = list;
  2572.   GSList * rest;
  2573.  
  2574.   if (!list)
  2575.     return g_slist_prepend (list, (void *) ((long) x));
  2576.  
  2577.   while (list)
  2578.     {
  2579.       rest = g_slist_next (list);
  2580.       if (x < (long) list->data)
  2581.         {
  2582.           rest = g_slist_prepend (rest, list->data);
  2583.           list->next = rest;
  2584.           list->data = (void *) ((long) x);
  2585.           return orig;
  2586.         }
  2587.       else if (!rest)
  2588.         {
  2589.           g_slist_append (list, (void *) ((long) x));
  2590.           return orig;
  2591.         }
  2592.       list = g_slist_next (list);
  2593.     }
  2594.  
  2595.   return orig;
  2596. }
  2597.  
  2598. gboolean 
  2599. bezier_tool_selected()
  2600. {
  2601.   return(active_tool &&
  2602.      active_tool->type == BEZIER_SELECT &&
  2603.      active_tool->state == ACTIVE);
  2604. }
  2605.  
  2606. void
  2607. bezier_paste_bezierselect_to_current(GDisplay *gdisp,BezierSelect *bsel)
  2608. {
  2609.   BezierPoint *pts;
  2610.   gint i;
  2611.   Tool * tool;
  2612.   BezierPoint  *bpnt = NULL;
  2613.   int need_move = 0;
  2614.  
  2615. /*   g_print ("bezier_paste_bezierselect_to_current::\n"); */
  2616. /*   printSel(bsel); */
  2617.  
  2618.   /*  If the tool was being used before clear it */
  2619.   if (active_tool &&
  2620.       active_tool->type == BEZIER_SELECT &&
  2621.       active_tool->state == ACTIVE)
  2622.     {
  2623.       BezierSelect *bezier_sel = (BezierSelect*)active_tool->private;
  2624.       if(bezier_sel)
  2625.     {
  2626.       draw_core_stop ( curSel->core, active_tool );
  2627.       bezier_select_reset (bezier_sel);
  2628.     }
  2629.     }
  2630.  
  2631.   gimp_context_set_tool (gimp_context_get_user (), BEZIER_SELECT);
  2632.   active_tool->paused_count = 0;
  2633.   active_tool->gdisp_ptr = gdisp;
  2634.   active_tool->drawable = gimage_active_drawable (gdisp->gimage);  
  2635.  
  2636.   tool = active_tool;
  2637.  
  2638.   bezier_select_reset( curSel );
  2639.  
  2640.   draw_core_start (curSel->core, gdisp->canvas->window, tool);
  2641.  
  2642.   tool->state = ACTIVE;
  2643.  
  2644.   pts = (BezierPoint *) bsel->points;
  2645.  
  2646.   for (i=0; i< bsel->num_points; i++)
  2647.     {
  2648.       if(need_move)
  2649.     {
  2650.       bezier_add_point( curSel, BEZIER_MOVE, pts->x, pts->y);
  2651.       need_move = 0;
  2652.     }
  2653.       else
  2654.     bezier_add_point( curSel, pts->type, pts->x, pts->y);
  2655.  
  2656.       if(bpnt == NULL)
  2657.     bpnt = curSel->last_point;
  2658.  
  2659.       if(pts->next_curve)
  2660.     {
  2661. /*       g_print ("bezier_paste_bezierselect_to_current:: Close last curve off \n"); */
  2662.       curSel->last_point->next = bpnt;
  2663.       bpnt->prev = curSel->last_point;
  2664.       curSel->cur_anchor = NULL;
  2665.       curSel->cur_control = NULL;
  2666.       bpnt = NULL;
  2667.       need_move = 1;
  2668.       pts = pts->next_curve;
  2669.     }
  2670.       else
  2671.     {
  2672.       pts = pts->next;
  2673.     }
  2674.     }
  2675.       
  2676.   if ( bsel->closed )
  2677.     {
  2678.       curSel->last_point->next = bpnt;
  2679.       bpnt->prev = curSel->last_point;
  2680.       curSel->cur_anchor = curSel->points;
  2681.       curSel->cur_control = curSel->points->next;
  2682.       curSel->closed = 1;
  2683.       if (curTool->gdisp_ptr)
  2684.     bezier_convert(curSel, curTool->gdisp_ptr, SUBDIVIDE, NO);
  2685.     }
  2686.  
  2687. /*   g_print ("After pasting...\n"); */
  2688. /*   printSel(curSel); */
  2689.  
  2690.   if(bsel->num_points == 0)
  2691.     {
  2692.       curSel->state = BEZIER_START;
  2693.       curSel->draw = 0;
  2694.       draw_core_stop( curSel->core, curTool);
  2695.     }
  2696.   else
  2697.     {
  2698.       curSel->state = bsel->state;
  2699.       curSel->draw = BEZIER_DRAW_ALL;
  2700.       draw_core_resume( curSel->core, curTool);
  2701.     }
  2702. }
  2703.  
  2704. static void
  2705. bezier_to_sel_internal(BezierSelect  *bezier_sel,
  2706.                Tool          *tool,
  2707.                GDisplay      *gdisp,
  2708.                gint           op, 
  2709.                gint           replace)
  2710. {
  2711.   /*  If we're antialiased, then recompute the
  2712.    *  mask...
  2713.    */
  2714.   if (bezier_options->antialias)
  2715.     bezier_convert (bezier_sel, tool->gdisp_ptr, SUBDIVIDE, YES);
  2716.   
  2717. /*   if (!bezier_options->extend) */
  2718. /*     { */
  2719. /*       tool->state = INACTIVE; */
  2720. /*       bezier_sel->draw = BEZIER_DRAW_CURVE; */
  2721. /*       draw_core_resume (bezier_sel->core, tool); */
  2722.       
  2723. /*       bezier_sel->draw = 0; */
  2724. /*       draw_core_stop (bezier_sel->core, tool); */
  2725. /*     } */
  2726.  
  2727.    if (replace)
  2728.     gimage_mask_clear (gdisp->gimage);
  2729.   else
  2730.     gimage_mask_undo (gdisp->gimage);
  2731.   
  2732.   if (bezier_options->feather)
  2733.     channel_feather (bezier_sel->mask,
  2734.              gimage_get_mask (gdisp->gimage),
  2735.              bezier_options->feather_radius, 
  2736.              bezier_options->feather_radius, 
  2737.              op, 0, 0);
  2738.   else
  2739.     channel_combine_mask (gimage_get_mask (gdisp->gimage),
  2740.               bezier_sel->mask, op, 0, 0);
  2741.   
  2742.   /*  show selection on all views  */
  2743.   gdisplays_flush ();
  2744. }
  2745.  
  2746. static int
  2747. test_add_point_on_segment (BezierSelect     *bezier_sel,
  2748.                 BezierPoint      *pt,
  2749.                 int               subdivisions,
  2750.                 int               space,
  2751.                 int xpos, 
  2752.                 int ypos, 
  2753.                 int halfwidth)
  2754.  
  2755. {
  2756.   BezierPoint *points;
  2757.   BezierMatrix geometry;
  2758.   BezierMatrix tmp1, tmp2;
  2759.   BezierMatrix deltas;
  2760.   double x, dx, dx2, dx3;
  2761.   double y, dy, dy2, dy3;
  2762.   double d, d2, d3;
  2763.   int lastx, lasty;
  2764.   int newx, newy;
  2765.   int i;
  2766.   double ratio;
  2767.  
  2768.   /* construct the geometry matrix from the segment */
  2769.   /* assumes that a valid segment containing 4 points is passed in */
  2770.   /* ALT ignore invalid segments since we might be working on an open curve */
  2771.  
  2772.   points = pt;
  2773.  
  2774.   ratio = -1.0;
  2775.  
  2776.   for (i = 0; i < 4; i++)
  2777.     {
  2778.       if (!points)
  2779.     return 0;
  2780.  
  2781.       switch (space)
  2782.     {
  2783.     case IMAGE_COORDS:
  2784.       geometry[i][0] = points->x;
  2785.       geometry[i][1] = points->y;
  2786.       break;
  2787.     case AA_IMAGE_COORDS:
  2788.       geometry[i][0] = RINT(points->x * SUPERSAMPLE);
  2789.       geometry[i][1] = RINT(points->y * SUPERSAMPLE);
  2790.       break;
  2791.     case SCREEN_COORDS:
  2792.       geometry[i][0] = points->sx;
  2793.       geometry[i][1] = points->sy;
  2794.       break;
  2795.     default:
  2796.       gimp_fatal_error ("test_add_point_on_segment(): Unknown coordinate space: %d", space);
  2797.       break;
  2798.     }
  2799.  
  2800.       geometry[i][2] = 0;
  2801.       geometry[i][3] = 0;
  2802.  
  2803.       points = points->next;
  2804.     }
  2805.  
  2806.   /* subdivide the curve n times */
  2807.   /* n can be adjusted to give a finer or coarser curve */
  2808.  
  2809.   d = 1.0 / subdivisions;
  2810.   d2 = d * d;
  2811.   d3 = d * d * d;
  2812.  
  2813.   /* construct a temporary matrix for determining the forward diffencing deltas */
  2814.  
  2815.   tmp2[0][0] = 0;     tmp2[0][1] = 0;     tmp2[0][2] = 0;    tmp2[0][3] = 1;
  2816.   tmp2[1][0] = d3;    tmp2[1][1] = d2;    tmp2[1][2] = d;    tmp2[1][3] = 0;
  2817.   tmp2[2][0] = 6*d3;  tmp2[2][1] = 2*d2;  tmp2[2][2] = 0;    tmp2[2][3] = 0;
  2818.   tmp2[3][0] = 6*d3;  tmp2[3][1] = 0;     tmp2[3][2] = 0;    tmp2[3][3] = 0;
  2819.  
  2820.   /* compose the basis and geometry matrices */
  2821.   bezier_compose (basis, geometry, tmp1);
  2822.  
  2823.   /* compose the above results to get the deltas matrix */
  2824.   bezier_compose (tmp2, tmp1, deltas);
  2825.  
  2826.   /* extract the x deltas */
  2827.   x = deltas[0][0];
  2828.   dx = deltas[1][0];
  2829.   dx2 = deltas[2][0];
  2830.   dx3 = deltas[3][0];
  2831.  
  2832.   /* extract the y deltas */
  2833.   y = deltas[0][1];
  2834.   dy = deltas[1][1];
  2835.   dy2 = deltas[2][1];
  2836.   dy3 = deltas[3][1];
  2837.  
  2838.   lastx = x;
  2839.   lasty = y;
  2840.  
  2841.   /* loop over the curve */
  2842.   for (i = 0; i < subdivisions; i++)
  2843.     {
  2844.       /* increment the x values */
  2845.       x += dx;
  2846.       dx += dx2;
  2847.       dx2 += dx3;
  2848.  
  2849.       /* increment the y values */
  2850.       y += dy;
  2851.       dy += dy2;
  2852.       dy2 += dy3;
  2853.  
  2854.       newx = ROUND (x);
  2855.       newy = ROUND (y);
  2856.  
  2857.       /* if this point is different than the last one...then test it */
  2858.       if ((lastx != newx) || (lasty != newy))
  2859.     {
  2860.       int l, r, b, t;
  2861.       
  2862.       l = newx - halfwidth;
  2863.       r = newx + halfwidth;
  2864.       t = newy - halfwidth;
  2865.       b = newy + halfwidth;
  2866.       
  2867.       if  ((xpos >= l) && (xpos <= r) && (ypos >= t) && (ypos <= b))
  2868.         {
  2869.           /* so we found one point in the square hit */
  2870.           
  2871.           ratio = (double)i/(double)subdivisions;
  2872.  
  2873.           /* We found the exact point on the curve, so take it ...*/
  2874.  
  2875.           if ((xpos==newx) && (ypos==newy)) break;
  2876.  
  2877.           /* to Implement :
  2878.  
  2879.          keep each time the nearest point of the curve from where we've clicked
  2880.          in the case where we haven't click exactely on the curve.
  2881.           */
  2882.  
  2883.         }
  2884.     }
  2885.       lastx = newx;
  2886.       lasty = newy;
  2887.     }
  2888.  
  2889.   /* we found a point on the curve */
  2890.  
  2891.   if (ratio >= 0.0)
  2892.     {
  2893.       BezierPoint *pts, *pt1, *pt2, *pt3;
  2894.       BezierPoint *P00, *P01, *P02, *P03;
  2895.       BezierPoint P10, P11, P12;
  2896.       BezierPoint P20, P21;
  2897.       BezierPoint P30;
  2898.  
  2899.       pts = pt;
  2900.  
  2901.       P00 = pts;
  2902.       pts = pts->next;
  2903.       P01 = pts;
  2904.       pts = pts->next;
  2905.       P02 = pts;
  2906.       pts = pts->next;
  2907.       P03 = pts;
  2908.  
  2909.       /* De Casteljau algorithme 
  2910.      [Advanced Animation & Randering Technics / Alan & Mark WATT]
  2911.      [ADDISON WESLEY ref 54412]
  2912.      Iteratif way of drawing a Bezier curve by geometrical approch 
  2913.      
  2914.      P0x represent the four controls points ( anchor / control /control /anchor ) 
  2915.      P30 represent the new anchor point to add on the curve 
  2916.      P2x represent the new control points of P30
  2917.      P1x represent the new values of the control points P01 and P02
  2918.  
  2919.      so if we moves ratio from 0 to 1 we draw the all curve between P00 and P03
  2920.       */
  2921.      
  2922.       P10.x = (int)((1-ratio)*P00->x + ratio * P01->x);
  2923.       P10.y = (int)((1-ratio)*P00->y + ratio * P01->y);
  2924.  
  2925.       P11.x = (1-ratio)*P01->x + ratio * P02->x;
  2926.       P11.y = (1-ratio)*P01->y + ratio * P02->y;
  2927.  
  2928.       P12.x = (1-ratio)*P02->x + ratio * P03->x;
  2929.       P12.y = (1-ratio)*P02->y + ratio * P03->y;
  2930.  
  2931.       P20.x = (1-ratio)*P10.x + ratio * P11.x;
  2932.       P20.y = (1-ratio)*P10.y + ratio * P11.y;
  2933.  
  2934.       P21.x = (1-ratio)*P11.x + ratio * P12.x;
  2935.       P21.y = (1-ratio)*P11.y + ratio * P12.y;
  2936.  
  2937.       P30.x = (1-ratio)*P20.x + ratio * P21.x;
  2938.       P30.y = (1-ratio)*P20.y + ratio * P21.y;
  2939.       
  2940.       P01->x = P10.x;
  2941.       P01->y = P10.y;
  2942.  
  2943.       P02->x = P12.x;
  2944.       P02->y = P12.y;
  2945.  
  2946.       /* All the computes are done, let's insert the new point on the curve */
  2947.  
  2948.       pt1 = g_new0(BezierPoint,1);
  2949.       pt2 = g_new0(BezierPoint,1);
  2950.       pt3 = g_new0(BezierPoint,1);
  2951.       
  2952.       pt1->type = BEZIER_CONTROL;
  2953.       pt2->type = BEZIER_ANCHOR;
  2954.       pt3->type = BEZIER_CONTROL;
  2955.       
  2956.       pt1->x = P20.x; pt1->y = P20.y;    
  2957.       pt2->x = P30.x; pt2->y = P30.y;
  2958.       pt3->x = P21.x; pt3->y = P21.y;
  2959.       
  2960.       pt3->next_curve = P01->next_curve;
  2961.       P01->next  = pt1;
  2962.       
  2963.       pt1->prev = P01;
  2964.       pt1->next = pt2;
  2965.       
  2966.       pt2->prev = pt1;
  2967.       pt2->next = pt3;
  2968.       
  2969.       pt3->prev = pt2; 
  2970.       pt3->next = P02;
  2971.       
  2972.       P02->prev = pt3;
  2973.       
  2974.       bezier_sel->num_points += 3;
  2975.  
  2976.       bezier_sel->cur_anchor = pt2;
  2977.       bezier_sel->cur_control = pt1;
  2978.  
  2979.       return 1;
  2980.     }
  2981.  
  2982.   return 0;
  2983.   
  2984. }
  2985.  
  2986. void bezier_select_mode(gint mode)
  2987. {
  2988.   ModeEdit = mode;
  2989. }
  2990.  
  2991. /* The curve has to be closed to do a selection. */
  2992.  
  2993. void
  2994. bezier_to_selection(BezierSelect *bezier_sel,
  2995.             GDisplay     *gdisp)
  2996. {
  2997.   /* Call the internal function */
  2998.   if(!bezier_sel->closed)
  2999.     {
  3000.       g_message(_("Curve not closed!"));
  3001.       return;
  3002.     }
  3003.  
  3004.   /* force the passed selection to be the current selection..*/
  3005.   /* This loads it into curSel for this image */
  3006.   bezier_paste_bezierselect_to_current(gdisp,bezier_sel);
  3007.   bezier_to_sel_internal(curSel,curTool,gdisp,ADD,1);
  3008. }
  3009.  
  3010. void printSel( BezierSelect *sel)
  3011. {
  3012.   BezierPoint *pt;
  3013.   BezierPoint *start_pt;
  3014.   int i;
  3015.  
  3016.   pt = sel->points;
  3017.   start_pt = pt;
  3018.  
  3019.   g_print ("\n");
  3020.  
  3021.   for(i=0; i<sel->num_points; i++)
  3022.     {
  3023.       g_print ("%d(%p) x,y=%f,%f type=%d next=%p prev=%p next_curve=%p\n", i,pt, pt->x, pt->y,pt->type,pt->next,pt->prev,pt->next_curve);
  3024.       if(pt->next != start_pt && pt->next_curve)
  3025.     g_print ("Curve out a sync!!\n");
  3026.       if(pt->next_curve)
  3027.     {
  3028.       pt = pt->next_curve;
  3029.       start_pt = pt;
  3030.     }
  3031.       else
  3032.     pt = pt->next;
  3033.     }
  3034.  
  3035.   g_print ("core : %p\n", sel->core);
  3036.   g_print ("closed : %d\n", sel->closed);
  3037.   g_print ("draw : %d\n", sel->draw);
  3038.   g_print ("state: %d\n", sel->state);
  3039. }
  3040.  
  3041. /* check whether vectors (offx, offy), (l_offx, l_offy) have the same angle. */
  3042. static gboolean
  3043. stroke_interpolatable (int offx, int offy, int l_offx, int l_offy, gdouble error)
  3044. {
  3045.   if      ((offx == l_offx) & (offy == l_offy))
  3046.     return TRUE;
  3047.   else if ((offx == 0) | (l_offx == 0))
  3048.     if (offx == l_offx)
  3049.       return ((0 <= offy) & (0 <= offy)) | ((offy < 0) & (l_offy < 0));
  3050.     else
  3051.       return FALSE;
  3052.   else if ((offy == 0) | (l_offy == 0))
  3053.     if (offy == l_offy)
  3054.       return ((0 < offx) & (0 < l_offx)) | ((offx < 0) & (l_offx < 0));
  3055.     else
  3056.       return FALSE;
  3057.   /* At this point, we can assert: offx, offy, l_offx, l_offy != 0 */
  3058.   else if (((0 < offx) & (0 < l_offx)) | ((offx < 0) & (l_offx < 0)))
  3059.     {
  3060.       gdouble    grad1, grad2;
  3061.  
  3062.       if (ABS (offy) < ABS (offx))
  3063.     {
  3064.       grad1 = (gdouble) offy / (gdouble) offx;
  3065.       grad2 = (gdouble) l_offy / (gdouble) l_offx;
  3066.     }
  3067.       else
  3068.     {
  3069.       grad1 = (gdouble) offx / (gdouble) offy;
  3070.       grad2 = (gdouble) l_offx / (gdouble) l_offy;
  3071.     }
  3072.       /* printf ("error: %f / %f\n", ABS (grad1 - grad2), error); */
  3073.       return (ABS (grad1 - grad2) <= error);
  3074.     }
  3075.   else
  3076.     return FALSE;
  3077. }
  3078.  
  3079. static void
  3080. bezier_stack_points_aux (GdkPoint *points,
  3081.              int      start,
  3082.              int      end,
  3083.              gdouble  error,
  3084.              BezierRenderPnts *rpnts)
  3085. {
  3086.   const gint    expand_size = 32;
  3087.   gint        med;
  3088.   gint        offx, offy, l_offx, l_offy;
  3089.  
  3090.   if (rpnts->stroke_points == NULL)
  3091.     return;
  3092.  
  3093.   /* BASE CASE: stack the end point */
  3094.   if (end - start <= 1)
  3095.     {
  3096.       if ((rpnts->stroke_points[rpnts->num_stroke_points * 2 - 2] == points[end].x)
  3097.       && (rpnts->stroke_points[rpnts->num_stroke_points * 2 - 1] == points[end].y))
  3098.     return;
  3099.  
  3100.       rpnts->num_stroke_points++;
  3101.       if (rpnts->len_stroke_points <= rpnts->num_stroke_points)
  3102.     {
  3103.       rpnts->len_stroke_points += expand_size;
  3104.       rpnts->stroke_points = g_renew (double, rpnts->stroke_points, 2 * rpnts->len_stroke_points);
  3105.       if (rpnts->stroke_points == NULL)
  3106.         {
  3107.           rpnts->len_stroke_points = rpnts->num_stroke_points = 0;
  3108.           return;
  3109.         }
  3110.     }
  3111.       rpnts->stroke_points[rpnts->num_stroke_points * 2 - 2] = points[end].x;
  3112.       rpnts->stroke_points[rpnts->num_stroke_points * 2 - 1] = points[end].y;
  3113.       return;
  3114.     }
  3115.  
  3116.   if (end - start <= 32)
  3117.     {
  3118.       gint i;
  3119.  
  3120.       for (i = start+ 1; i <= end; i++)
  3121.     bezier_stack_points_aux (points, i, i, 0,rpnts);
  3122.       return;
  3123.     }
  3124.   /* Otherwise, check whether to divide the segment recursively */
  3125.   offx = points[end].x - points[start].x;
  3126.   offy = points[end].y - points[start].y;
  3127.   med = (end + start) / 2;
  3128.  
  3129.   l_offx = points[med].x - points[start].x;
  3130.   l_offy = points[med].y - points[start].y;
  3131.  
  3132.   if (! stroke_interpolatable (offx, offy, l_offx, l_offy, error))
  3133.     {
  3134.       bezier_stack_points_aux (points, start, med, error, rpnts);
  3135.       bezier_stack_points_aux (points, med, end, error, rpnts);
  3136.       return;
  3137.     }
  3138.  
  3139.   l_offx = points[end].x - points[med].x;
  3140.   l_offy = points[end].y - points[med].y;
  3141.  
  3142.   if (! stroke_interpolatable (offx, offy, l_offx, l_offy, error))
  3143.     {
  3144.       bezier_stack_points_aux (points, start, med, error, rpnts);
  3145.       bezier_stack_points_aux (points, med, end, error, rpnts);
  3146.       return;
  3147.     }
  3148.   /* Now, the curve can be represented by a points pair: (start, end).
  3149.      So, add the last point to stroke_points. */
  3150.   bezier_stack_points_aux (points, end, end, 0, rpnts);
  3151. }
  3152.  
  3153. static void
  3154. bezier_stack_points (BezierSelect *bezier_sel,
  3155.              GdkPoint     *points,
  3156.              int           npoints,
  3157.              gpointer      udata)
  3158. {
  3159.   gint    i;
  3160.   gint    expand_size = 32;
  3161.   gint    minx, maxx, miny, maxy;
  3162.   gdouble error;
  3163.   BezierRenderPnts *rpnts = udata;
  3164.  
  3165.   if (npoints < 2)        /* Does this happen? */
  3166.     return;
  3167.  
  3168.   if (rpnts->stroke_points == NULL)    /*  initialize it here */
  3169.     {
  3170.       rpnts->num_stroke_points = 0;
  3171.       rpnts->len_stroke_points = expand_size;
  3172.       rpnts->stroke_points = g_new (double, 2 * rpnts->len_stroke_points);
  3173.     }
  3174.  
  3175.   maxx = minx = points[0].x;
  3176.   maxy = miny = points[0].y;
  3177.   for (i = 1; i < npoints; i++)
  3178.     {
  3179.       if (points[i].x < minx)
  3180.     minx = points[i].x;
  3181.       else if (maxx < points[i].x)
  3182.     maxx = points[i].x;
  3183.       if (points[i].y < miny)
  3184.     miny = points[i].x;
  3185.       else if (maxy < points[i].y)
  3186.     maxy = points[i].y;
  3187.     }
  3188.   /* allow one pixel fluctuation */
  3189.   error = 2.0 / MAX(maxx - minx, maxy - miny);
  3190.   error = 0.0; /* ALT */
  3191.  
  3192.   /* add the start point */
  3193.   bezier_stack_points_aux (points, 0, 0, 0, rpnts);
  3194.  
  3195.   /* divide segments recursively */
  3196.   bezier_stack_points_aux (points, 0, npoints - 1, error, rpnts);
  3197.  
  3198.   /* printf ("npoints: %d\n", npoints); */
  3199. }
  3200.  
  3201. static gint
  3202. bezier_gen_points(BezierSelect     *bezier_sel,
  3203.           int                open_path,
  3204.           BezierRenderPnts *rpnts)
  3205. {
  3206.   BezierPoint * points;
  3207.   BezierPoint * start_pt;
  3208.   BezierPoint * next_curve;
  3209.   BezierRenderPnts *next_rpnts = rpnts;
  3210.   gint point_counts = 0; 
  3211.  
  3212.   /* stack points */
  3213.   points = bezier_sel->points;
  3214.   start_pt = bezier_sel->points;
  3215.       
  3216.   if(bezier_sel->num_points >= 4)
  3217.     {
  3218.       do {
  3219.      point_counts = count_points_on_curve(points); 
  3220.     if(point_counts < 4)
  3221.       return(TRUE);
  3222.     do {
  3223.       bezier_draw_segment (bezier_sel, points,
  3224.                    SUBDIVIDE, AA_IMAGE_COORDS,
  3225.                    bezier_stack_points,
  3226.                    (gpointer)next_rpnts);
  3227.       
  3228.       points = next_anchor(points,&next_curve);
  3229.     } while (points != start_pt && points);
  3230.     start_pt = next_curve;
  3231.     points = next_curve;
  3232.     if(next_curve)
  3233.       {
  3234.         next_rpnts->next_curve = g_new0(BezierRenderPnts,1);
  3235.         next_rpnts = next_rpnts->next_curve;
  3236.       }
  3237.       } while (next_curve);
  3238.     }
  3239.   
  3240.   return (TRUE);
  3241. }
  3242.  
  3243. void
  3244. bezier_stroke (BezierSelect *bezier_sel,
  3245.            GDisplay     *gdisp,
  3246.            int          subdivisions,
  3247.            int        open_path)
  3248. {
  3249.   Argument *return_vals;
  3250.   int nreturn_vals;
  3251.   BezierRenderPnts *next_rpnts;
  3252.   BezierRenderPnts *rpnts = g_new0(BezierRenderPnts,1);
  3253.  
  3254.   /*  Start an undo group  */
  3255.   undo_push_group_start (gdisp->gimage, PAINT_CORE_UNDO);
  3256.  
  3257.   bezier_gen_points(bezier_sel,open_path,rpnts);
  3258.   do
  3259.     {
  3260.   if (rpnts->stroke_points)
  3261.     {
  3262.       GimpDrawable *drawable;
  3263.       int offset_x, offset_y;
  3264.       gdouble *ptr;
  3265.     
  3266.       drawable = gimage_active_drawable (gdisp->gimage);
  3267.       gimp_drawable_offsets (drawable, &offset_x, &offset_y);
  3268.  
  3269.       ptr = rpnts->stroke_points;
  3270.       while (ptr < rpnts->stroke_points + (rpnts->num_stroke_points * 2))
  3271.     {
  3272.       *ptr /= SUPERSAMPLE;
  3273.       *ptr++ -= offset_x;
  3274.       *ptr /= SUPERSAMPLE;
  3275.       *ptr++ -= offset_y;
  3276.     }
  3277.  
  3278.       /* Stroke with the correct tool */
  3279.       return_vals = procedural_db_run_proc (tool_active_PDB_string(),
  3280.                         &nreturn_vals,
  3281.                         PDB_DRAWABLE, drawable_ID (drawable),
  3282.                         PDB_INT32, (gint32) rpnts->num_stroke_points * 2,
  3283.                         PDB_FLOATARRAY, rpnts->stroke_points,
  3284.                         PDB_END);
  3285.  
  3286.       if (return_vals && return_vals[0].value.pdb_int != PDB_SUCCESS)
  3287.     g_message (_("Paintbrush operation failed."));
  3288.  
  3289.       procedural_db_destroy_args (return_vals, nreturn_vals);
  3290.  
  3291.       g_free (rpnts->stroke_points);
  3292.     }
  3293.     next_rpnts = rpnts->next_curve;
  3294.     rpnts->stroke_points = NULL;
  3295.     rpnts->len_stroke_points = rpnts->num_stroke_points = 0;
  3296.     g_free(rpnts);
  3297.     rpnts = next_rpnts;
  3298.     } while (rpnts);
  3299.   /*  End an undo group  */
  3300.   undo_push_group_end (gdisp->gimage);
  3301.   gdisplays_flush ();
  3302. }
  3303.  
  3304. static void
  3305. bezier_draw_segment_for_distance (BezierSelect     *bezier_sel,
  3306.                   BezierPoint      *points,
  3307.                   int               subdivisions,
  3308.                   BezierDistance   *bdist)
  3309. {
  3310.   BezierMatrix geometry;
  3311.   BezierMatrix tmp1, tmp2;
  3312.   BezierMatrix deltas;
  3313.   double x, dx, dx2, dx3;
  3314.   double y, dy, dy2, dy3;
  3315.   double d, d2, d3;
  3316.   int index;
  3317.   int i;
  3318.  
  3319.   /* construct the geometry matrix from the segment */
  3320.   /* assumes that a valid segment containing 4 points is passed in */
  3321.  
  3322.   if(bdist->found)
  3323.     return;
  3324.  
  3325.   for (i = 0; i < 4; i++)
  3326.     {
  3327.       if (!points)
  3328.     gimp_fatal_error ("bezier_draw_segment_for_distance(): Bad bezier segment");
  3329.  
  3330.       geometry[i][0] = points->x;
  3331.       geometry[i][1] = points->y;
  3332.       geometry[i][2] = 0;
  3333.       geometry[i][3] = 0;
  3334.  
  3335.       points = points->next;
  3336.     }
  3337.  
  3338.   /* subdivide the curve n times */
  3339.   /* n can be adjusted to give a finer or coarser curve */
  3340.  
  3341.   d = 1.0 / subdivisions;
  3342.   d2 = d * d;
  3343.   d3 = d * d * d;
  3344.  
  3345.   /* construct a temporary matrix for determining the forward diffencing deltas */
  3346.  
  3347.   tmp2[0][0] = 0;     tmp2[0][1] = 0;     tmp2[0][2] = 0;    tmp2[0][3] = 1;
  3348.   tmp2[1][0] = d3;    tmp2[1][1] = d2;    tmp2[1][2] = d;    tmp2[1][3] = 0;
  3349.   tmp2[2][0] = 6*d3;  tmp2[2][1] = 2*d2;  tmp2[2][2] = 0;    tmp2[2][3] = 0;
  3350.   tmp2[3][0] = 6*d3;  tmp2[3][1] = 0;     tmp2[3][2] = 0;    tmp2[3][3] = 0;
  3351.  
  3352.   /* compose the basis and geometry matrices */
  3353.   bezier_compose (basis, geometry, tmp1);
  3354.  
  3355.   /* compose the above results to get the deltas matrix */
  3356.   bezier_compose (tmp2, tmp1, deltas);
  3357.  
  3358.   /* extract the x deltas */
  3359.   x = deltas[0][0];
  3360.   dx = deltas[1][0];
  3361.   dx2 = deltas[2][0];
  3362.   dx3 = deltas[3][0];
  3363.  
  3364.   /* extract the y deltas */
  3365.   y = deltas[0][1];
  3366.   dy = deltas[1][1];
  3367.   dy2 = deltas[2][1];
  3368.   dy3 = deltas[3][1];
  3369.  
  3370.   index = 1;
  3371.  
  3372.   /* loop over the curve */
  3373.   for (i = 0; i < subdivisions; i++)
  3374.     {
  3375.       /* increment the x values */
  3376.       x += dx;
  3377.       dx += dx2;
  3378.       dx2 += dx3;
  3379.  
  3380.       /* increment the y values */
  3381.       y += dy;
  3382.       dy += dy2;
  3383.       dy2 += dy3;
  3384.  
  3385. /*       g_print ("x = %g, y = %g\n",x,y); */
  3386.  
  3387.       /* if this point is different than the last one...then draw it */
  3388.       /* Note :
  3389.        * It assumes the udata is the place we want the 
  3390.        * floating version of the coords to be stuffed.
  3391.        * These are needed when we calculate the gradient of the 
  3392.        * curve.
  3393.        */
  3394.  
  3395.       if(!bdist->firstpnt)
  3396.     {
  3397.       gdouble rx = x;
  3398.       gdouble ry = y;
  3399.        gdouble dx = bdist->lastx - rx; 
  3400.        gdouble dy = bdist->lasty - ry; 
  3401.  
  3402.        bdist->curdist += sqrt((dx*dx)+(dy*dy)); 
  3403.        if(bdist->curdist >= bdist->dist) 
  3404.          { 
  3405.            *(bdist->x) = ROUND((rx + dx/2)); 
  3406.            *(bdist->y) = ROUND((ry + dy/2)); 
  3407.            if(dx == 0.0) 
  3408.          *(bdist->gradient) = G_MAXDOUBLE; 
  3409.            else 
  3410.          *(bdist->gradient) = dy/dx; 
  3411.  
  3412. /*           g_print ("found x = %d, y = %d\n",*(bdist->x),*(bdist->y)); */
  3413.           bdist->found = TRUE;
  3414.            break; 
  3415.          } 
  3416.        bdist->lastx = rx; 
  3417.        bdist->lasty = ry; 
  3418.     }
  3419.       else
  3420.     {
  3421.       bdist->firstpnt = FALSE;
  3422.       bdist->lastx = x;
  3423.       bdist->lasty = y;
  3424.     }
  3425.     }
  3426. }
  3427.  
  3428. static void
  3429. bezier_draw_curve_for_distance (BezierSelect    *bezier_sel,
  3430.                 BezierDistance  *udata)
  3431. {
  3432.   BezierPoint * points;
  3433.   BezierPoint * start_pt;
  3434.   BezierPoint * next_curve;
  3435.  
  3436.   points = bezier_sel->points;
  3437.   start_pt = bezier_sel->points;
  3438.  
  3439.   if(bezier_sel->num_points >= 4)
  3440.     {
  3441.       do {
  3442.     do {
  3443.       bezier_draw_segment_for_distance (bezier_sel, points,
  3444.                         SUBDIVIDE, 
  3445.                         udata);
  3446.       points = next_anchor(points,&next_curve);
  3447.     } while (points != start_pt && points);
  3448.     start_pt = next_curve;
  3449.     points = next_curve;
  3450.       } while (next_curve);
  3451.     }
  3452. }
  3453.  
  3454. gint
  3455. bezier_distance_along(BezierSelect *bezier_sel,
  3456.               int        open_path,
  3457.               gdouble       dist,
  3458.               gint         *x,
  3459.               gint         *y,
  3460.               gdouble      *gradient)
  3461. {
  3462.   /* Render the curve as points then walk along it... */
  3463.   BezierDistance *bdist = g_new0(BezierDistance,1);
  3464.   gint ret;
  3465.  
  3466.   bdist->firstpnt = TRUE;
  3467.   bdist->curdist = 0.0;
  3468.   bdist->lastx = 0.0;
  3469.   bdist->lasty = 0.0;
  3470.   bdist->dist = dist;
  3471.   bdist->x = x;
  3472.   bdist->y = y;
  3473.   bdist->gradient = gradient;
  3474.   bdist->found = FALSE;
  3475.  
  3476.   bezier_draw_curve_for_distance (bezier_sel,bdist);
  3477.   ret = bdist->found;
  3478.  
  3479.   g_free(bdist);
  3480.   return (ret);
  3481. }
  3482.