home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / app / eraser.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-17  |  9.4 KB  |  354 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 "cursorutil.h"
  28. #include "drawable.h"
  29. #include "gdisplay.h"
  30. #include "gimage_mask.h"
  31. #include "gimpui.h"
  32. #include "paint_funcs.h"
  33. #include "paint_core.h"
  34. #include "paint_options.h"
  35. #include "eraser.h"
  36. #include "selection.h"
  37. #include "tools.h"
  38.  
  39. #include "libgimp/gimpintl.h"
  40.  
  41.  
  42. /* Defaults */
  43. #define ERASER_DEFAULT_HARD        FALSE
  44. #define ERASER_DEFAULT_INCREMENTAL FALSE
  45. #define ERASER_DEFAULT_ANTI_ERASE  FALSE
  46.  
  47. /*  the eraser structures  */
  48.  
  49. typedef struct _EraserOptions EraserOptions;
  50. struct _EraserOptions
  51. {
  52.   PaintOptions  paint_options;
  53.  
  54.   gboolean      hard;
  55.   gboolean      hard_d;
  56.   GtkWidget    *hard_w;
  57.  
  58.   gboolean    anti_erase;
  59.   gboolean    anti_erase_d;
  60.   GtkWidget    *anti_erase_w;
  61. };
  62.  
  63.  
  64. /*  the eraser tool options  */
  65. static EraserOptions *eraser_options = NULL;
  66.  
  67. /*  local variables  */
  68. static gboolean       non_gui_hard;
  69. static gboolean       non_gui_incremental;
  70. static gboolean          non_gui_anti_erase;
  71.  
  72. /*  forward function declarations  */
  73. static void       eraser_motion            (PaintCore *, GimpDrawable *,
  74.                         PaintPressureOptions *,
  75.                         gboolean, gboolean, gboolean);
  76.  
  77.  
  78. /*  functions  */
  79.  
  80. static void
  81. eraser_options_reset (void)
  82. {
  83.   EraserOptions *options = eraser_options;
  84.  
  85.   paint_options_reset ((PaintOptions *) options);
  86.  
  87.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->hard_w),
  88.                 options->hard_d);
  89.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->anti_erase_w),
  90.                 options->anti_erase_d);
  91. }
  92.   
  93. static EraserOptions *
  94. eraser_options_new (void)
  95. {
  96.   EraserOptions *options;
  97.  
  98.   GtkWidget *vbox;
  99.  
  100.   /*  the new eraser tool options structure  */
  101.   options = g_new (EraserOptions, 1);
  102.   paint_options_init ((PaintOptions *) options,
  103.               ERASER,
  104.               eraser_options_reset);
  105.   options->hard        = options->hard_d        = ERASER_DEFAULT_HARD;
  106.   options->anti_erase  = options->anti_erase_d  = ERASER_DEFAULT_ANTI_ERASE;
  107.  
  108.   /*  the main vbox  */
  109.   vbox = ((ToolOptions *) options)->main_vbox;
  110.  
  111.   /* the hard toggle */
  112.   options->hard_w = gtk_check_button_new_with_label (_("Hard Edge"));
  113.   gtk_box_pack_start (GTK_BOX (vbox), options->hard_w, FALSE, FALSE, 0);
  114.   gtk_signal_connect (GTK_OBJECT (options->hard_w), "toggled",
  115.               GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  116.               &options->hard);
  117.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->hard_w),
  118.                 options->hard_d);
  119.   gtk_widget_show (options->hard_w);
  120.  
  121.   /* the anti_erase toggle */
  122.   options->anti_erase_w = gtk_check_button_new_with_label (_("Anti Erase"));
  123.   gtk_box_pack_start (GTK_BOX (vbox), options->anti_erase_w, FALSE, FALSE, 0);
  124.   gtk_signal_connect (GTK_OBJECT (options->anti_erase_w), "toggled",
  125.               GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  126.               &options->anti_erase);
  127.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->anti_erase_w),
  128.                 options->anti_erase_d);
  129.   gtk_widget_show (options->anti_erase_w);
  130.  
  131.   return options;
  132. }
  133.  
  134. static void
  135. eraser_modifier_key_func (Tool        *tool,
  136.               GdkEventKey *kevent,
  137.               gpointer     gdisp_ptr)
  138. {
  139.   switch (kevent->keyval)
  140.     {
  141.     case GDK_Alt_L: 
  142.     case GDK_Alt_R:
  143.       break;
  144.     case GDK_Shift_L: 
  145.     case GDK_Shift_R:
  146.       if (kevent->state & GDK_CONTROL_MASK)    /* reset tool toggle */
  147.     gtk_toggle_button_set_active
  148.       (GTK_TOGGLE_BUTTON (eraser_options->anti_erase_w),
  149.        ! eraser_options->anti_erase);
  150.       break;
  151.     case GDK_Control_L: 
  152.     case GDK_Control_R:
  153.       if (!(kevent->state & GDK_SHIFT_MASK)) /* shift enables line draw mode */
  154.     gtk_toggle_button_set_active
  155.       (GTK_TOGGLE_BUTTON (eraser_options->anti_erase_w),
  156.        ! eraser_options->anti_erase);
  157.       break;
  158.     }
  159.  
  160.   tool->toggled = eraser_options->anti_erase;
  161. }
  162.  
  163.  
  164. void *
  165. eraser_paint_func (PaintCore    *paint_core,
  166.            GimpDrawable *drawable,
  167.            int           state)
  168. {
  169.   switch (state)
  170.     {
  171.     case INIT_PAINT:
  172.       break;
  173.  
  174.     case MOTION_PAINT:
  175.       eraser_motion (paint_core,
  176.              drawable,
  177.              eraser_options->paint_options.pressure_options,
  178.              eraser_options->hard,
  179.              eraser_options->paint_options.incremental,
  180.              eraser_options->anti_erase);
  181.       break;
  182.  
  183.     case FINISH_PAINT:
  184.       break;
  185.  
  186.     default:
  187.       break;
  188.     }
  189.  
  190.   return NULL;
  191. }
  192.  
  193. Tool *
  194. tools_new_eraser (void)
  195. {
  196.   Tool * tool;
  197.   PaintCore * private;
  198.  
  199.   /*  The tool options  */
  200.   if (! eraser_options)
  201.     {
  202.       eraser_options = eraser_options_new ();
  203.       tools_register (ERASER, (ToolOptions *) eraser_options);
  204.     }
  205.  
  206.   tool = paint_core_new (ERASER);
  207.  
  208.   private = (PaintCore *) tool->private;
  209.   private->paint_func = eraser_paint_func;
  210.   private->flags |= TOOL_CAN_HANDLE_CHANGING_BRUSH; 
  211.   tool->modifier_key_func = eraser_modifier_key_func;
  212.  
  213.   return tool;
  214. }
  215.  
  216.  
  217. void
  218. tools_free_eraser (Tool *tool)
  219. {
  220.   paint_core_free (tool);
  221. }
  222.  
  223.  
  224. static void
  225. eraser_motion (PaintCore            *paint_core,
  226.            GimpDrawable         *drawable,
  227.            PaintPressureOptions *pressure_options,
  228.            gboolean              hard,
  229.            gboolean              incremental,
  230.            gboolean                 anti_erase)
  231. {
  232.   GImage *gimage;
  233.   gint opacity;
  234.   TempBuf * area;
  235.   unsigned char col[MAX_CHANNELS];
  236.   gdouble scale;
  237.  
  238.   if (! (gimage = drawable_gimage (drawable)))
  239.     return;
  240.  
  241.   gimage_get_background (gimage, drawable, col);
  242.  
  243.   if (pressure_options->size)
  244.     scale = paint_core->curpressure;
  245.   else
  246.     scale = 1.0;
  247.  
  248.   /*  Get a region which can be used to paint to  */
  249.   if (! (area = paint_core_get_paint_area (paint_core, drawable, scale)))
  250.     return;
  251.  
  252.   /*  set the alpha channel  */
  253.   col[area->bytes - 1] = OPAQUE_OPACITY;
  254.  
  255.   /*  color the pixels  */
  256.   color_pixels (temp_buf_data (area), col,
  257.         area->width * area->height, area->bytes);
  258.  
  259.   opacity = 255 * gimp_context_get_opacity (NULL);
  260.   if (pressure_options->opacity)
  261.     opacity = opacity * 2.0 * paint_core->curpressure;
  262.  
  263.   /*  paste the newly painted canvas to the gimage which is being worked on  */
  264.   paint_core_paste_canvas (paint_core, drawable, 
  265.                MIN (opacity, 255),
  266.                (int) (gimp_context_get_opacity (NULL) * 255),
  267.                anti_erase ? ANTI_ERASE_MODE : ERASE_MODE,
  268.                hard ? HARD : (pressure_options->pressure ? PRESSURE : SOFT),
  269.                scale,
  270.                incremental ? INCREMENTAL : CONSTANT);
  271. }
  272.  
  273.  
  274. static void *
  275. eraser_non_gui_paint_func (PaintCore    *paint_core,
  276.                GimpDrawable *drawable,
  277.                int           state)
  278. {
  279.   eraser_motion (paint_core, drawable,
  280.          &non_gui_pressure_options,
  281.          non_gui_hard, non_gui_incremental, non_gui_anti_erase);
  282.  
  283.   return NULL;
  284. }
  285.  
  286. gboolean
  287. eraser_non_gui_default (GimpDrawable *drawable,
  288.             int           num_strokes,
  289.             double       *stroke_array)
  290. {
  291.   gboolean  hardness   = ERASER_DEFAULT_HARD;
  292.   gboolean  method     = ERASER_DEFAULT_INCREMENTAL;
  293.   gboolean  anti_erase = ERASER_DEFAULT_ANTI_ERASE;
  294.  
  295.   EraserOptions *options = eraser_options;
  296.  
  297.   if (options)
  298.     {
  299.       hardness   = options->hard;
  300.       method     = options->paint_options.incremental;
  301.       anti_erase = options->anti_erase;
  302.     }
  303.  
  304.   return eraser_non_gui (drawable, num_strokes, stroke_array,
  305.              hardness, method, anti_erase);
  306. }
  307.  
  308. gboolean
  309. eraser_non_gui (GimpDrawable *drawable,
  310.             int           num_strokes,
  311.         double       *stroke_array,
  312.         int           hardness,
  313.         int           method,
  314.         int          anti_erase)
  315. {
  316.   int i;
  317.   
  318.   if (paint_core_init (&non_gui_paint_core, drawable,
  319.                stroke_array[0], stroke_array[1]))
  320.     {
  321.       non_gui_hard        = hardness;
  322.       non_gui_incremental = method;
  323.       non_gui_anti_erase  = anti_erase;
  324.  
  325.       /* Set the paint core's paint func */
  326.       non_gui_paint_core.paint_func = eraser_non_gui_paint_func;
  327.  
  328.       non_gui_paint_core.startx = non_gui_paint_core.lastx = stroke_array[0];
  329.       non_gui_paint_core.starty = non_gui_paint_core.lasty = stroke_array[1];
  330.  
  331.       eraser_non_gui_paint_func (&non_gui_paint_core, drawable, 0);
  332.  
  333.       for (i = 1; i < num_strokes; i++)
  334.     {
  335.       non_gui_paint_core.curx = stroke_array[i * 2 + 0];
  336.       non_gui_paint_core.cury = stroke_array[i * 2 + 1];
  337.  
  338.       paint_core_interpolate (&non_gui_paint_core, drawable);
  339.  
  340.       non_gui_paint_core.lastx = non_gui_paint_core.curx;
  341.       non_gui_paint_core.lasty = non_gui_paint_core.cury;
  342.     }
  343.  
  344.       /* Finish the painting */
  345.       paint_core_finish (&non_gui_paint_core, drawable, -1);
  346.  
  347.       /* Cleanup */
  348.       paint_core_cleanup ();
  349.       return TRUE;
  350.     }
  351.   else
  352.     return FALSE;
  353. }
  354.