home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / app / bucket_fill.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-17  |  17.4 KB  |  641 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 <gtk/gtk.h>
  22. #include <gdk/gdkkeysyms.h>
  23.  
  24. #include "apptypes.h"
  25.  
  26. #include "appenv.h"
  27. #include "bucket_fill.h"
  28. #include "cursorutil.h"
  29. #include "drawable.h"
  30. #include "fuzzy_select.h"
  31. #include "gdisplay.h"
  32. #include "gimage_mask.h"
  33. #include "gimprc.h"
  34. #include "gimpui.h"
  35. #include "paint_funcs.h"
  36. #include "paint_options.h"
  37. #include "selection.h"
  38. #include "tools.h"
  39. #include "undo.h"
  40.  
  41. #include "libgimp/gimpintl.h"
  42.  
  43. /*  the bucket fill structures  */
  44.  
  45. typedef struct _BucketTool BucketTool;
  46. struct _BucketTool
  47. {
  48.   gint  target_x;  /*  starting x coord  */
  49.   gint  target_y;  /*  starting y coord  */
  50. };
  51.  
  52. typedef struct _BucketOptions BucketOptions;
  53. struct _BucketOptions
  54. {
  55.   PaintOptions    paint_options;
  56.  
  57.   gboolean        sample_merged;
  58.   gboolean        sample_merged_d;
  59.   GtkWidget      *sample_merged_w;
  60.  
  61.   gdouble         threshold;
  62.   /* gdouble      threshold_d; (from gimprc) */
  63.   GtkObject      *threshold_w;
  64.  
  65.   BucketFillMode  fill_mode;
  66.   BucketFillMode  fill_mode_d;
  67.   GtkWidget      *fill_mode_w[3];
  68. };
  69.  
  70.  
  71. /*  the bucket fill tool options  */
  72. static BucketOptions *bucket_options = NULL;
  73.  
  74.  
  75. /*  local function prototypes  */
  76.  
  77. static void  bucket_fill_button_press    (Tool *, GdkEventButton *, gpointer);
  78. static void  bucket_fill_button_release  (Tool *, GdkEventButton *, gpointer);
  79. static void  bucket_fill_cursor_update   (Tool *, GdkEventMotion *, gpointer);
  80.  
  81. static void  bucket_fill_line_color      (guchar *, guchar *, guchar *,
  82.                       gboolean, gint, gint);
  83. static void  bucket_fill_line_pattern    (guchar *, guchar *, TempBuf *,
  84.                       gboolean, gint, gint, gint, gint);
  85.  
  86.  
  87. /*  functions  */
  88.  
  89. static void
  90. bucket_options_reset (void)
  91. {
  92.   BucketOptions *options = bucket_options;
  93.  
  94.   paint_options_reset ((PaintOptions *) options);
  95.  
  96.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->sample_merged_w),
  97.                 options->sample_merged_d);
  98.   gtk_adjustment_set_value (GTK_ADJUSTMENT (options->threshold_w),
  99.                 default_threshold);
  100.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->fill_mode_w[options->fill_mode_d]), TRUE);
  101. }
  102.  
  103. static BucketOptions *
  104. bucket_options_new (void)
  105. {
  106.   BucketOptions *options;
  107.  
  108.   GtkWidget *vbox;
  109.   GtkWidget *hbox;
  110.   GtkWidget *label;
  111.   GtkWidget *scale;
  112.   GtkWidget *frame;
  113.  
  114.   /*  the new bucket fill tool options structure  */
  115.   options = (BucketOptions *) g_malloc (sizeof (BucketOptions));
  116.   paint_options_init ((PaintOptions *) options,
  117.               BUCKET_FILL,
  118.               bucket_options_reset);
  119.   options->sample_merged = options->sample_merged_d = FALSE;
  120.   options->threshold                                = default_threshold;
  121.   options->fill_mode     = options->fill_mode_d     = FG_BUCKET_FILL;
  122.  
  123.   /*  the main vbox  */
  124.   vbox = ((ToolOptions *) options)->main_vbox;
  125.  
  126.   /*  the sample merged toggle  */
  127.   options->sample_merged_w =
  128.     gtk_check_button_new_with_label (_("Sample Merged"));
  129.   gtk_signal_connect (GTK_OBJECT (options->sample_merged_w), "toggled",
  130.               GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  131.               &options->sample_merged);
  132.   gtk_box_pack_start (GTK_BOX (vbox), options->sample_merged_w, FALSE, FALSE, 0);
  133.   gtk_widget_show (options->sample_merged_w);
  134.  
  135.   /*  the threshold scale  */
  136.   hbox = gtk_hbox_new (FALSE, 4);
  137.   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
  138.  
  139.   label = gtk_label_new (_("Threshold:"));
  140.   gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0);
  141.   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
  142.   gtk_widget_show (label);
  143.  
  144.   options->threshold_w =
  145.     gtk_adjustment_new (default_threshold, 1.0, 255.0, 1.0, 1.0, 0.0);
  146.   scale = gtk_hscale_new (GTK_ADJUSTMENT (options->threshold_w));
  147.   gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
  148.   gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP);
  149.   gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED);
  150.   gtk_signal_connect (GTK_OBJECT (options->threshold_w), "value_changed",
  151.               GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  152.               &options->threshold);
  153.   gtk_widget_show (scale);
  154.  
  155.   gtk_widget_show (hbox);
  156.  
  157.   /*  fill type  */
  158.   frame =
  159.     gimp_radio_group_new2 (TRUE, _("Fill Type"),
  160.                gimp_radio_button_update,
  161.                &options->fill_mode, (gpointer) options->fill_mode,
  162.  
  163.                _("FG Color Fill"),
  164.                (gpointer) FG_BUCKET_FILL,
  165.                &options->fill_mode_w[0],
  166.                _("BG Color Fill"),
  167.                (gpointer) BG_BUCKET_FILL,
  168.                &options->fill_mode_w[1],
  169.                _("Pattern Fill"),
  170.                (gpointer) PATTERN_BUCKET_FILL,
  171.                &options->fill_mode_w[2],
  172.  
  173.                NULL);
  174.  
  175.   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
  176.   gtk_widget_show (frame);
  177.  
  178.   return options;
  179. }
  180.  
  181. /*  bucket fill action functions  */
  182.  
  183. static void
  184. bucket_fill_button_press (Tool           *tool,
  185.               GdkEventButton *bevent,
  186.               gpointer        gdisp_ptr)
  187. {
  188.   GDisplay * gdisp;
  189.   BucketTool * bucket_tool;
  190.   gboolean use_offsets;
  191.  
  192.   gdisp = (GDisplay *) gdisp_ptr;
  193.   bucket_tool = (BucketTool *) tool->private;
  194.  
  195.   use_offsets = (bucket_options->sample_merged) ? FALSE : TRUE;
  196.  
  197.   gdisplay_untransform_coords (gdisp, bevent->x, bevent->y,
  198.                    &bucket_tool->target_x,
  199.                    &bucket_tool->target_y, FALSE, use_offsets);
  200.  
  201.   /*  Make the tool active and set the gdisplay which owns it  */
  202.   gdk_pointer_grab (gdisp->canvas->window, FALSE,
  203.             GDK_POINTER_MOTION_HINT_MASK |
  204.             GDK_BUTTON1_MOTION_MASK |
  205.             GDK_BUTTON_RELEASE_MASK,
  206.             NULL, NULL, bevent->time);
  207.  
  208.   /*  Make the tool active and set the gdisplay which owns it  */
  209.   tool->gdisp_ptr = gdisp_ptr;
  210.   tool->state = ACTIVE;
  211. }
  212.  
  213. static void
  214. bucket_fill_button_release (Tool           *tool,
  215.                 GdkEventButton *bevent,
  216.                 gpointer        gdisp_ptr)
  217. {
  218.   GDisplay * gdisp;
  219.   BucketTool * bucket_tool;
  220.   Argument *return_vals;
  221.   gint nreturn_vals;
  222.  
  223.   gdisp = (GDisplay *) gdisp_ptr;
  224.   bucket_tool = (BucketTool *) tool->private;
  225.  
  226.   gdk_pointer_ungrab (bevent->time);
  227.   gdk_flush ();
  228.  
  229.   /*  if the 3rd button isn't pressed, fill the selected region  */
  230.   if (! (bevent->state & GDK_BUTTON3_MASK))
  231.     {
  232.       return_vals =
  233.     procedural_db_run_proc ("gimp_bucket_fill",
  234.                 &nreturn_vals,
  235.                 PDB_DRAWABLE, drawable_ID (gimage_active_drawable (gdisp->gimage)),
  236.                 PDB_INT32, (gint32) bucket_options->fill_mode,
  237.                 PDB_INT32, (gint32) gimp_context_get_paint_mode (NULL),
  238.                 PDB_FLOAT, (gdouble) gimp_context_get_opacity (NULL) * 100,
  239.                 PDB_FLOAT, (gdouble) bucket_options->threshold,
  240.                 PDB_INT32, (gint32) bucket_options->sample_merged,
  241.                 PDB_FLOAT, (gdouble) bucket_tool->target_x,
  242.                 PDB_FLOAT, (gdouble) bucket_tool->target_y,
  243.                 PDB_END);
  244.  
  245.       if (return_vals && return_vals[0].value.pdb_int == PDB_SUCCESS)
  246.     gdisplays_flush ();
  247.       else
  248.     g_message (_("Bucket Fill operation failed."));
  249.  
  250.       procedural_db_destroy_args (return_vals, nreturn_vals);
  251.     }
  252.  
  253.   tool->state = INACTIVE;
  254. }
  255.  
  256. static void
  257. bucket_fill_cursor_update (Tool           *tool,
  258.                GdkEventMotion *mevent,
  259.                gpointer        gdisp_ptr)
  260. {
  261.   GDisplay *gdisp;
  262.   Layer    *layer;
  263.   GdkCursorType ctype      = GDK_TOP_LEFT_ARROW;
  264.   CursorModifier cmodifier = CURSOR_MODIFIER_NONE;
  265.   gint x, y;
  266.   gint off_x, off_y;
  267.  
  268.   gdisp = (GDisplay *) gdisp_ptr;
  269.  
  270.   gdisplay_untransform_coords (gdisp, mevent->x, mevent->y,
  271.                    &x, &y, FALSE, FALSE);
  272.   if ((layer = gimage_get_active_layer (gdisp->gimage))) 
  273.     {
  274.       drawable_offsets (GIMP_DRAWABLE (layer), &off_x, &off_y);
  275.  
  276.       if (x >= off_x && y >= off_y &&
  277.       x < (off_x + drawable_width (GIMP_DRAWABLE (layer))) &&
  278.       y < (off_y + drawable_height (GIMP_DRAWABLE (layer))))
  279.     {
  280.       /*  One more test--is there a selected region?
  281.        *  if so, is cursor inside?
  282.        */
  283.       if (gimage_mask_is_empty (gdisp->gimage) ||
  284.           gimage_mask_value (gdisp->gimage, x, y))
  285.         {
  286.           ctype = GIMP_MOUSE_CURSOR;
  287.  
  288.           switch (bucket_options->fill_mode)
  289.         {
  290.         case FG_BUCKET_FILL:
  291.           cmodifier = CURSOR_MODIFIER_FOREGROUND;
  292.           break;
  293.         case BG_BUCKET_FILL:
  294.           cmodifier = CURSOR_MODIFIER_BACKGROUND;
  295.           break;
  296.         case PATTERN_BUCKET_FILL:
  297.           cmodifier = CURSOR_MODIFIER_PATTERN;
  298.           break;
  299.         }
  300.         }
  301.     }
  302.     }
  303.  
  304.   gdisplay_install_tool_cursor (gdisp, ctype,
  305.                 BUCKET_FILL,
  306.                 cmodifier,
  307.                 FALSE);
  308. }
  309.  
  310. static void
  311. bucket_fill_modifier_key_func (Tool        *tool,
  312.                    GdkEventKey *kevent,
  313.                    gpointer     gdisp_ptr)
  314. {
  315.   switch (kevent->keyval)
  316.     {
  317.     case GDK_Alt_L: case GDK_Alt_R:
  318.       break;
  319.     case GDK_Shift_L: case GDK_Shift_R:
  320.       break;
  321.     case GDK_Control_L: case GDK_Control_R:
  322.       switch (bucket_options->fill_mode)
  323.     {
  324.     case FG_BUCKET_FILL:
  325.       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (bucket_options->fill_mode_w[BG_BUCKET_FILL]), TRUE);
  326.       break;
  327.     case BG_BUCKET_FILL:
  328.       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (bucket_options->fill_mode_w[FG_BUCKET_FILL]), TRUE);
  329.       break;
  330.     default:
  331.       break;
  332.     }
  333.       break;
  334.     }
  335. }
  336.  
  337. void
  338. bucket_fill (GimpImage      *gimage,
  339.          GimpDrawable   *drawable,
  340.          BucketFillMode  fill_mode,
  341.          gint            paint_mode,
  342.          gdouble         opacity,
  343.          gdouble         threshold,
  344.          gboolean        sample_merged,
  345.          gdouble         x,
  346.          gdouble         y)
  347. {
  348.   TileManager *buf_tiles;
  349.   PixelRegion  bufPR, maskPR;
  350.   Channel     *mask = NULL;
  351.   gint       bytes;
  352.   gboolean   has_alpha;
  353.   gint       x1, y1, x2, y2;
  354.   guchar     col [MAX_CHANNELS];
  355.   guchar    *d1, *d2;
  356.   GPattern  *pattern;
  357.   TempBuf   *pat_buf;
  358.   gboolean   new_buf = FALSE;
  359.  
  360.   pat_buf = NULL;
  361.  
  362.   if (fill_mode == FG_BUCKET_FILL)
  363.     gimage_get_foreground (gimage, drawable, col);
  364.   else if (fill_mode == BG_BUCKET_FILL)
  365.     gimage_get_background (gimage, drawable, col);
  366.   else if (fill_mode == PATTERN_BUCKET_FILL)
  367.     {
  368.       pattern = gimp_context_get_pattern (NULL);
  369.  
  370.       if (!pattern)
  371.     {
  372.       g_message (_("No available patterns for this operation."));
  373.       return;
  374.     }
  375.  
  376.       /*  If the pattern doesn't match the image in terms of color type,
  377.        *  transform it.  (ie  pattern is RGB, image is indexed)
  378.        */
  379.       if (((pattern->mask->bytes == 3) && !drawable_color (drawable)) ||
  380.       ((pattern->mask->bytes == 1) && !drawable_gray (drawable)))
  381.     {
  382.       int size;
  383.  
  384.       if ((pattern->mask->bytes == 1) && drawable_color (drawable))
  385.         pat_buf = temp_buf_new (pattern->mask->width, pattern->mask->height, 3, 0, 0, NULL);
  386.       else
  387.         pat_buf = temp_buf_new (pattern->mask->width, pattern->mask->height, 1, 0, 0, NULL);
  388.  
  389.       d1 = temp_buf_data (pattern->mask);
  390.       d2 = temp_buf_data (pat_buf);
  391.  
  392.       size = pattern->mask->width * pattern->mask->height;
  393.       while (size--)
  394.         {
  395.           gimage_transform_color (gimage, drawable, d1, d2,
  396.                       (pattern->mask->bytes == 3) ? RGB : GRAY);
  397.           d1 += pattern->mask->bytes;
  398.           d2 += pat_buf->bytes;
  399.         }
  400.  
  401.       new_buf = TRUE;
  402.     }
  403.       else
  404.     pat_buf = pattern->mask;
  405.     }
  406.  
  407.   gimp_add_busy_cursors ();
  408.  
  409.   bytes = drawable_bytes (drawable);
  410.   has_alpha = drawable_has_alpha (drawable);
  411.  
  412.   /*  If there is no selection mask, the do a seed bucket
  413.    *  fill...To do this, calculate a new contiguous region
  414.    */
  415.   if (! drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2))
  416.     {
  417.       mask = find_contiguous_region (gimage, drawable, TRUE, (int) threshold,
  418.                      (int) x, (int) y, sample_merged);
  419.  
  420.       channel_bounds (mask, &x1, &y1, &x2, &y2);
  421.  
  422.       /*  make sure we handle the mask correctly if it was sample-merged  */
  423.       if (sample_merged)
  424.     {
  425.       int off_x, off_y;
  426.  
  427.       /*  Limit the channel bounds to the drawable's extents  */
  428.       drawable_offsets (drawable, &off_x, &off_y);
  429.       x1 = CLAMP (x1, off_x, (off_x + drawable_width (drawable)));
  430.       y1 = CLAMP (y1, off_y, (off_y + drawable_height (drawable)));
  431.       x2 = CLAMP (x2, off_x, (off_x + drawable_width (drawable)));
  432.       y2 = CLAMP (y2, off_y, (off_y + drawable_height (drawable)));
  433.  
  434.       pixel_region_init (&maskPR, drawable_data (GIMP_DRAWABLE (mask)), 
  435.                  x1, y1, (x2 - x1), (y2 - y1), TRUE);
  436.  
  437.       /*  translate mask bounds to drawable coords  */
  438.       x1 -= off_x;
  439.       y1 -= off_y;
  440.       x2 -= off_x;
  441.       y2 -= off_y;
  442.     }
  443.       else
  444.     pixel_region_init (&maskPR, drawable_data (GIMP_DRAWABLE (mask)), 
  445.                x1, y1, (x2 - x1), (y2 - y1), TRUE);
  446.  
  447.       /*  if the gimage doesn't have an alpha channel,
  448.        *  make sure that the temp buf does.  We need the
  449.        *  alpha channel to fill with the region calculated above
  450.        */
  451.       if (! has_alpha)
  452.     {
  453.       bytes ++;
  454.       has_alpha = TRUE;
  455.     }
  456.     }
  457.  
  458.   buf_tiles = tile_manager_new ((x2 - x1), (y2 - y1), bytes);
  459.   pixel_region_init (&bufPR, buf_tiles, 0, 0, (x2 - x1), (y2 - y1), TRUE);
  460.  
  461.   if (mask)
  462.     bucket_fill_region (fill_mode, &bufPR, &maskPR, col, pat_buf, x1, y1, has_alpha);
  463.   else
  464.     bucket_fill_region (fill_mode, &bufPR, NULL, col, pat_buf, x1, y1, has_alpha);
  465.  
  466.   pixel_region_init (&bufPR, buf_tiles, 0, 0, (x2 - x1), (y2 - y1), FALSE);
  467.   gimage_apply_image (gimage, drawable, &bufPR, TRUE,
  468.               (opacity * 255) / 100, paint_mode, NULL, x1, y1);
  469.  
  470.   /*  update the image  */
  471.   drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
  472.  
  473.   /*  free the temporary buffer  */
  474.   tile_manager_destroy (buf_tiles);
  475.  
  476.   /*  free the mask  */
  477.   if (mask)
  478.     channel_delete (mask);
  479.  
  480.   if (new_buf)
  481.     temp_buf_free (pat_buf);
  482.  
  483.   gimp_remove_busy_cursors (NULL);
  484. }
  485.  
  486. static void
  487. bucket_fill_line_color (guchar   *buf,
  488.             guchar   *mask,
  489.             guchar   *col,
  490.             gboolean  has_alpha,
  491.             gint      bytes,
  492.             gint      width)
  493. {
  494.   gint alpha, b;
  495.  
  496.   alpha = (has_alpha) ? bytes - 1 : bytes;
  497.   while (width--)
  498.     {
  499.       for (b = 0; b < alpha; b++)
  500.     buf[b] = col[b];
  501.  
  502.       if (has_alpha)
  503.     {
  504.       if (mask)
  505.         buf[alpha] = *mask++;
  506.       else
  507.         buf[alpha] = OPAQUE_OPACITY;
  508.     }
  509.  
  510.       buf += bytes;
  511.     }
  512. }
  513.  
  514. static void
  515. bucket_fill_line_pattern (guchar   *buf,
  516.               guchar   *mask,
  517.               TempBuf  *pattern,
  518.               gboolean  has_alpha,
  519.               gint      bytes,
  520.               gint      x,
  521.               gint      y,
  522.               gint      width)
  523. {
  524.   guchar *pat, *p;
  525.   gint alpha, b;
  526.   gint i;
  527.  
  528.   /*  Get a pointer to the appropriate scanline of the pattern buffer  */
  529.   pat = temp_buf_data (pattern) +
  530.     (y % pattern->height) * pattern->width * pattern->bytes;
  531.  
  532.   alpha = (has_alpha) ? bytes - 1 : bytes;
  533.   for (i = 0; i < width; i++)
  534.     {
  535.       p = pat + ((i + x) % pattern->width) * pattern->bytes;
  536.  
  537.       for (b = 0; b < alpha; b++)
  538.     buf[b] = p[b];
  539.  
  540.       if (has_alpha)
  541.     {
  542.       if (mask)
  543.         buf[alpha] = *mask++;
  544.       else
  545.         buf[alpha] = OPAQUE_OPACITY;
  546.     }
  547.  
  548.       buf += bytes;
  549.     }
  550. }
  551.  
  552. void
  553. bucket_fill_region (BucketFillMode  fill_mode,
  554.             PixelRegion    *bufPR,
  555.             PixelRegion    *maskPR,
  556.             guchar         *col,
  557.             TempBuf        *pattern,
  558.             gint            off_x,
  559.             gint            off_y,
  560.             gboolean        has_alpha)
  561. {
  562.   guchar *s, *m;
  563.   gint y;
  564.   void *pr;
  565.  
  566.   for (pr = pixel_regions_register (2, bufPR, maskPR);
  567.        pr != NULL;
  568.        pr = pixel_regions_process (pr))
  569.     {
  570.       s = bufPR->data;
  571.       if (maskPR)
  572.     m = maskPR->data;
  573.       else
  574.     m = NULL;
  575.  
  576.       for (y = 0; y < bufPR->h; y++)
  577.     {
  578.       switch (fill_mode)
  579.         {
  580.         case FG_BUCKET_FILL:
  581.         case BG_BUCKET_FILL:
  582.           bucket_fill_line_color (s, m, col, has_alpha, bufPR->bytes, bufPR->w);
  583.           break;
  584.         case PATTERN_BUCKET_FILL:
  585.           bucket_fill_line_pattern (s, m, pattern, has_alpha, bufPR->bytes,
  586.                     off_x + bufPR->x, off_y + y + bufPR->y, bufPR->w);
  587.           break;
  588.         }
  589.       s += bufPR->rowstride;
  590.  
  591.       if (maskPR)
  592.         m += maskPR->rowstride;
  593.     }
  594.     }
  595. }
  596.  
  597. /**********************************/
  598. /*  Global bucket fill functions  */
  599. /**********************************/
  600.  
  601. Tool *
  602. tools_new_bucket_fill (void)
  603. {
  604.   Tool * tool;
  605.   BucketTool * private;
  606.  
  607.   /*  The tool options  */
  608.   if (! bucket_options)
  609.     {
  610.       bucket_options = bucket_options_new ();
  611.       tools_register (BUCKET_FILL, (ToolOptions *) bucket_options);
  612.  
  613.       /*  press all default buttons  */
  614.       bucket_options_reset ();
  615.     }
  616.  
  617.   tool = tools_new_tool (BUCKET_FILL);
  618.   private = g_new0 (BucketTool, 1);
  619.  
  620.   tool->scroll_lock = TRUE;  /*  Disallow scrolling  */
  621.  
  622.   tool->private = (void *) private;
  623.  
  624.   tool->button_press_func   = bucket_fill_button_press;
  625.   tool->button_release_func = bucket_fill_button_release;
  626.   tool->modifier_key_func   = bucket_fill_modifier_key_func;
  627.   tool->cursor_update_func  = bucket_fill_cursor_update;
  628.  
  629.   return tool;
  630. }
  631.  
  632. void
  633. tools_free_bucket_fill (Tool *tool)
  634. {
  635.   BucketTool * bucket_tool;
  636.  
  637.   bucket_tool = (BucketTool *) tool->private;
  638.  
  639.   g_free (bucket_tool);
  640. }
  641.