diff -uNr gimp-2.4.1/app/core/gimp-modules.c gimp-2.4.1-tmp/app/core/gimp-modules.c
--- gimp-2.4.1/app/core/gimp-modules.c	2007-01-23 19:13:46.000000000 +0900
+++ gimp-2.4.1-tmp/app/core/gimp-modules.c	2008-03-22 21:39:28.000000000 +0900
@@ -71,6 +71,8 @@
 
   g_return_if_fail (GIMP_IS_GIMP (gimp));
 
+  g_print("[Trace]:Start:gimp_modules_load\n");
+
   if (gimp->no_interface)
     return;
 
@@ -154,6 +156,7 @@
   path = gimp_config_path_expand (gimp->config->module_path, TRUE, NULL);
   gimp_module_db_load (gimp->module_db, path);
   g_free (path);
+  g_print("[Trace]:End  :gimp_modules_load\n");
 }
 
 static void
diff -uNr gimp-2.4.1/app/paint/Makefile.am gimp-2.4.1-tmp/app/paint/Makefile.am
--- gimp-2.4.1/app/paint/Makefile.am	2007-06-27 18:50:25.000000000 +0900
+++ gimp-2.4.1-tmp/app/paint/Makefile.am	2008-03-22 21:39:28.000000000 +0900
@@ -77,7 +77,15 @@
 	gimpsourcecore.c		\
 	gimpsourcecore.h		\
 	gimpsourceoptions.c		\
-	gimpsourceoptions.h
+	gimpsourceoptions.h		\
+	gimpbrushmodifiercore.c		\
+	gimpbrushmodifiercore.h		\
+	gimpblendmodifier.c		\
+	gimpblendmodifier.h		\
+	gimpcustombrush.c			\
+	gimpcustombrush.h			\
+	gimpcustombrushoptions.c	\
+	gimpcustombrushoptions.h
 
 libapppaint_a_built_sources = paint-enums.c
 
diff -uNr gimp-2.4.1/app/paint/Makefile.in gimp-2.4.1-tmp/app/paint/Makefile.in
--- gimp-2.4.1/app/paint/Makefile.in	2007-10-31 17:09:07.000000000 +0900
+++ gimp-2.4.1-tmp/app/paint/Makefile.in	2008-03-22 21:39:28.000000000 +0900
@@ -70,7 +70,11 @@
 	gimppaintbrush.$(OBJEXT) gimpperspectiveclone.$(OBJEXT) \
 	gimpperspectivecloneoptions.$(OBJEXT) gimpsmudge.$(OBJEXT) \
 	gimpsmudgeoptions.$(OBJEXT) gimpsourcecore.$(OBJEXT) \
-	gimpsourceoptions.$(OBJEXT)
+	gimpsourceoptions.$(OBJEXT) \
+	gimpcustombrush.$(OBJEXT) gimpcustombrushoptions.$(OBJEXT) \
+	gimpbrushmodifiercore.$(OBJEXT) gimpblendmodifier.$(OBJEXT) \
+	gimpbrushmodifieroptions.$(OBJEXT) gimpblendmodifieroptions.$(OBJEXT) \
+	gimpsmoothmodifier.$(OBJEXT) gimpsmoothmodifieroptions.$(OBJEXT)
 am_libapppaint_a_OBJECTS = $(am__objects_1) $(am__objects_2)
 libapppaint_a_OBJECTS = $(am_libapppaint_a_OBJECTS)
 DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
@@ -535,7 +539,23 @@
 	gimpsourcecore.c		\
 	gimpsourcecore.h		\
 	gimpsourceoptions.c		\
-	gimpsourceoptions.h
+	gimpsourceoptions.h		\
+	gimpbrushmodifiercore.c		\
+	gimpbrushmodifiercore.h		\
+	gimpbrushmodifieroptions.c	\
+	gimpbrushmodifieroptions.h	\
+	gimpblendmodifier.c		\
+	gimpblendmodifier.h		\
+	gimpblendmodifieroptions.c	\
+	gimpblendmodifieroptions.h	\
+	gimpsmoothmodifier.c		\
+	gimpsmoothmodifier.h		\
+	gimpsmoothmodifieroptions.c	\
+	gimpsmoothmodifieroptions.h	\
+	gimpcustombrush.c		\
+	gimpcustombrush.h		\
+	gimpcustombrushoptions.c	\
+	gimpcustombrushoptions.h
 
 libapppaint_a_built_sources = paint-enums.c
 libapppaint_a_SOURCES = $(libapppaint_a_built_sources) $(libapppaint_a_sources)
@@ -625,6 +645,8 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpsourcecore.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpsourceoptions.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/paint-enums.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpcustombrush.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpcustombrushoptions.Po@am__quote@
 
 .c.o:
 @am__fastdepCC_TRUE@	if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
diff -uNr gimp-2.4.1/app/paint/gimp-paint.c gimp-2.4.1-tmp/app/paint/gimp-paint.c
--- gimp-2.4.1/app/paint/gimp-paint.c	2007-07-25 03:45:42.000000000 +0900
+++ gimp-2.4.1-tmp/app/paint/gimp-paint.c	2008-03-22 21:39:28.000000000 +0900
@@ -39,6 +39,7 @@
 #include "gimppencil.h"
 #include "gimpperspectiveclone.h"
 #include "gimpsmudge.h"
+#include "gimpcustombrush.h"
 
 
 /*  local function prototypes  */
@@ -68,12 +69,14 @@
     gimp_airbrush_register,
     gimp_eraser_register,
     gimp_paintbrush_register,
-    gimp_pencil_register
+    gimp_pencil_register,
+    gimp_custom_brush_register
   };
 
   gint i;
 
   g_return_if_fail (GIMP_IS_GIMP (gimp));
+  g_print("[Trace]:gimp_paint_init\n");
 
   gimp->paint_info_list = gimp_list_new (GIMP_TYPE_PAINT_INFO, FALSE);
   gimp_object_set_static_name (GIMP_OBJECT (gimp->paint_info_list),
diff -uNr gimp-2.4.1/app/paint/gimpblendmodifier.c gimp-2.4.1-tmp/app/paint/gimpblendmodifier.c
--- gimp-2.4.1/app/paint/gimpblendmodifier.c	1970-01-01 09:00:00.000000000 +0900
+++ gimp-2.4.1-tmp/app/paint/gimpblendmodifier.c	2008-03-22 21:39:28.000000000 +0900
@@ -0,0 +1,594 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "libgimpcolor/gimpcolor.h"
+#include "libgimpmath/gimpmath.h"
+#include "libgimpbase/gimpbase.h"
+
+#include "paint-types.h"
+
+#include "base/temp-buf.h"
+
+#include "paint-funcs/paint-funcs.h"
+
+#include "core/gimp.h"
+#include "core/gimpbrush.h"
+#include "core/gimpdrawable.h"
+#include "core/gimplayer.h"
+#include "core/gimpgradient.h"
+#include "core/gimpimage.h"
+#include "core/gimppickable.h"
+#include "core/gimpprojection.h"
+#include "base/pixel-region.h"
+
+#include "gimpcustombrush.h"
+#include "gimpblendmodifier.h"
+#include "gimpcustombrushoptions.h"
+#include "gimpblendmodifieroptions.h"
+
+#include "gimp-intl.h"
+
+
+/* Debug option */
+//#define GIMP_BLENDMODIFIER_DEBUG_BLENDING
+
+
+
+
+static void     gimp_blend_modifier_finalize     (GObject           *object);
+
+static gboolean gimp_blend_modifier_init_motion  (GimpBrushModifierCore* core,
+						 GimpBrushCore     *brush_core,
+						 GimpDrawable      *drawable,
+						 GimpPaintOptions  *paint_options,
+						 guint32            time);
+
+gboolean
+gimp_blend_modifier_register_paste_canvas (GimpBrushModifierCore    *core,
+					   GimpBrushCorePasteCanvasInfo** info,
+					   GimpBrushCore            *brush_core,
+					   GimpPaintOptions         *paint_options,
+					   GimpDrawable             *drawable,
+					   TempBuf                  *area,
+					   gdouble                   brush_opacity,
+					   gdouble                   image_opacity,
+					   GimpLayerModeEffects      paint_mode,
+					   GimpBrushApplicationMode  brush_hardness,
+					   GimpPaintApplicationMode  mode);
+
+static inline gboolean
+blend_modifier_get_image_color_at               (GimpImage           *image,
+						 GimpDrawable        *drawable,
+						 GimpBlendModifierOptions *blendmodifier_options,
+						 gint                 x,
+						 gint                 y,
+						 GimpRGB             *color_at_pos);
+
+inline static void
+blend_modifier_register_info (GimpBlendModifier       *modifier,
+			      GimpBrushCorePasteCanvasInfo** head_info,
+			      GimpPaintCore           *paint_core,
+			      GimpPaintOptions         *paint_options,
+			      GimpDrawable             *drawable,
+			      TempBuf                  *area,
+			      gdouble                   paint_opacity,
+			      gdouble                   image_opacity,
+			      GimpLayerModeEffects      paint_mode,
+			      GimpBrushApplicationMode  brush_hardness,
+			      GimpPaintApplicationMode  mode);
+static gboolean
+blend_colors                              (GimpRGB *dest,
+					   int num_colors,
+					   ...);
+
+/*
+ * Utility functions
+ *
+ */
+
+static gboolean
+blend_colors(GimpRGB *dest,
+	     int num_colors,
+	     ...)
+{
+  va_list args;
+  GimpRGB *src;
+  gdouble opacity = dest->a;
+  int i;
+
+  va_start(args, num_colors);
+
+  if (num_colors < 1)
+    return FALSE;
+  dest->r *= dest->a;
+  dest->g *= dest->a;
+  dest->b *= dest->a;
+
+  for (i = 0; i < num_colors; i ++)
+    {
+      src = va_arg(args, GimpRGB*);
+      dest->r += src->r * src->a;
+      dest->g += src->g * src->a;
+      dest->b += src->b * src->a;
+      opacity += src->a;
+    }
+  va_end(args);
+
+  if (opacity > 1.0)
+    {
+      dest->r = CLAMP(dest->r, 0, 1.0);
+      dest->g = CLAMP(dest->g, 0, 1.0);
+      dest->b = CLAMP(dest->b, 0, 1.0);
+      opacity = 1.0;
+    }
+  else if (opacity > 0)
+    {
+      dest->r = CLAMP(dest->r / opacity, 0, 1.0);
+      dest->g = CLAMP(dest->g / opacity, 0, 1.0);
+      dest->b = CLAMP(dest->b / opacity, 0, 1.0);
+    }
+
+  dest->a = opacity;
+  
+  return TRUE;
+}
+
+
+static inline gboolean
+blend_modifier_get_image_color_at (GimpImage           *image,
+			     GimpDrawable        *drawable,
+			     GimpBlendModifierOptions *blend_modifier_options,
+			     gint                 x,
+			     gint                 y,
+			     GimpRGB             *color_at_pos)
+{
+  GimpPickable *pickable;
+
+  x = CLAMP (x, 0, gimp_item_width (GIMP_ITEM (drawable)) - 1);
+  y = CLAMP (y, 0, gimp_item_height (GIMP_ITEM (drawable)) - 1);
+			 
+  if (blend_modifier_options->merged)
+    {
+      gint item_offset_x, item_offset_y;
+      gimp_item_offsets (GIMP_ITEM (drawable), &item_offset_x, &item_offset_y);
+      x += item_offset_x;
+      y += item_offset_y;
+      
+      pickable = GIMP_PICKABLE (image->projection);
+      //      g_print ("pickable=%x\n", pickable);
+      gimp_pickable_flush (pickable);
+    }
+  else
+    pickable = GIMP_PICKABLE (drawable);
+
+  /* Pickup color from current drawable */
+  if (!gimp_pickable_get_color_at (pickable,
+				   x, y, color_at_pos))
+    {
+      g_print ("Failed: pick up color\n");
+      return FALSE;
+    }
+  return TRUE;
+}
+
+/*
+ * Pickup color from Canvas or Projection, and
+ * merge the color with delayed and hidden color.
+ */
+static inline gboolean
+blend_modifier_get_blended_image_color_at (GimpBlendModifier* blendmodifier,
+					 GimpImage* image,
+					 GimpContext* context, 
+					 GimpDrawable* drawable,
+					 GimpBlendModifierOptions* blend_modifier_options,
+					 //					 GimpRGB* delayed_color,
+					 gint x, gint y, 
+					 GimpRGB* result)
+{
+  gboolean      use_hidden_color = FALSE;
+  guchar        hidden_color_uchar[MAX_CHANNELS];
+  GimpRGB       color_at_pos;
+  GimpRGB       hidden_color;
+
+  /* Pickup color from current drawable */
+  if (!blend_modifier_get_image_color_at (image, drawable,
+					  blend_modifier_options,
+					  x, y, &color_at_pos))
+    {
+      g_print ("Failed: pick up color\n");
+      return FALSE;
+    }
+
+  switch (blend_modifier_options->hidden_color)
+    {
+    case GIMP_HIDDEN_COLOR_BACKGROUND:
+      /* pickup hidden color from current background color */
+      gimp_image_get_background (image, context,
+				 gimp_drawable_type (drawable),
+				 hidden_color_uchar);
+      hidden_color_uchar[ALPHA_PIX] = OPAQUE_OPACITY;
+      use_hidden_color = TRUE;
+      break;
+      
+    case GIMP_HIDDEN_COLOR_WHITE:
+      /* select white as a hidden color */
+      hidden_color_uchar[0] =
+	hidden_color_uchar[1] =
+	hidden_color_uchar[2] =
+	hidden_color_uchar[3] = OPAQUE_OPACITY;
+      use_hidden_color = TRUE;
+      break;
+      
+    default:
+      break;
+    }
+
+  if (use_hidden_color)
+    {
+      gdouble a;
+      gimp_rgba_set_uchar(&hidden_color,
+			  hidden_color_uchar[0],
+			  hidden_color_uchar[1],
+			  hidden_color_uchar[2],
+			  hidden_color_uchar[3]);
+      a         = color_at_pos.a;
+      result->r = color_at_pos.r * a + (1 - a) * hidden_color.r;
+      result->g = color_at_pos.g * a + (1 - a) * hidden_color.g;
+      result->b = color_at_pos.b * a + (1 - a) * hidden_color.b;
+      result->a = 1.0;
+    }
+  else
+    {
+      *result = color_at_pos;
+    }
+
+  return TRUE;
+}
+
+
+/*
+ * GimpCustomBrush class implementation
+ *
+ *
+ */
+
+
+G_DEFINE_TYPE (GimpBlendModifier, gimp_blend_modifier, GIMP_TYPE_BRUSH_MODIFIER_CORE)
+
+#define parent_class gimp_blend_modifier_parent_class
+
+
+static void
+gimp_blend_modifier_class_init (GimpBlendModifierClass *klass)
+{
+  G_OBJECT_CLASS (klass)->finalize                 = gimp_blend_modifier_finalize;
+}
+
+static void
+gimp_blend_modifier_init (GimpBlendModifier *blend_modifier)
+{
+  GimpBrushModifierCore *modifier = GIMP_BRUSH_MODIFIER_CORE(blend_modifier);
+
+  brush_modifier_delegator_bind(&modifier->init_motion_delegator,
+				modifier,
+				gimp_blend_modifier_init_motion);
+  
+  brush_modifier_delegator_bind(&modifier->register_paste_canvas_delegator,
+				modifier,
+				gimp_blend_modifier_register_paste_canvas);
+}
+
+
+static void
+gimp_blend_modifier_finalize (GObject *object)
+{
+  g_print("blend_modifier::finalize\n");
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+
+
+GimpBlendModifier* gimp_blend_modifier_new(void)
+{
+  GimpBlendModifier* result = (GimpBlendModifier*)g_object_new(GIMP_TYPE_BLEND_MODIFIER, NULL);
+  g_assert( result != NULL );
+  return result;
+}
+
+
+
+
+static gboolean
+gimp_blend_modifier_init_motion (GimpBrushModifierCore* core,
+				 GimpBrushCore    *brush_core,
+				 GimpDrawable     *drawable,
+				 GimpPaintOptions *paint_options,
+				 guint32           time)
+{
+  GimpRGB                  *next_color = &GIMP_BLEND_MODIFIER(core)->next_color;
+  GimpRGB                  *foreground_color = &GIMP_BLEND_MODIFIER(core)->foreground_color;
+  GimpCustomBrushOptions   *custom_brush_options = GIMP_CUSTOM_BRUSH_OPTIONS (paint_options);
+  GimpBlendModifierOptions *blend_modifier_options;
+  GimpCustomBrush          *custom_brush = GIMP_CUSTOM_BRUSH(brush_core);
+
+  blend_modifier_options = GIMP_BLEND_MODIFIER_OPTIONS(gimp_custom_brush_options_get_options_for(custom_brush_options,
+												 GIMP_TYPE_BLEND_MODIFIER));
+  *foreground_color = custom_brush->state.color;
+  *next_color       = *foreground_color;
+  
+  GIMP_BLEND_MODIFIER(core)->current_orig_color_rate =
+    blend_modifier_options->original_color_rate;
+
+  return TRUE;
+}
+
+
+
+
+gboolean
+gimp_blend_modifier_register_paste_canvas (GimpBrushModifierCore    *modifier,
+					   GimpBrushCorePasteCanvasInfo** info,
+					   GimpBrushCore            *brush_core,
+					   GimpPaintOptions         *paint_options,
+					   GimpDrawable             *drawable,
+					   TempBuf                  *area,
+					   gdouble                   brush_opacity,
+					   gdouble                   image_opacity,
+					   GimpLayerModeEffects      paint_mode,
+					   GimpBrushApplicationMode  brush_hardness,
+					   GimpPaintApplicationMode  paint_appl_mode)
+{
+  GimpBlendModifier         *blend_modifier         = GIMP_BLEND_MODIFIER (modifier);
+  GimpPaintCore             *paint_core       = GIMP_PAINT_CORE (brush_core);
+  GimpCustomBrush           *custom_brush           = GIMP_CUSTOM_BRUSH(brush_core);
+  GimpContext               *context          = GIMP_CONTEXT (paint_options);
+  GimpImage                 *image;
+  GimpRGB                   *next_color       = &blend_modifier->next_color;
+  GimpCustomBrushOptions    *custom_brush_options = GIMP_CUSTOM_BRUSH_OPTIONS (paint_options);
+  GimpBlendModifierOptions  *blend_modifier_options;
+  GimpRGB                   *foreground_color = &blend_modifier->foreground_color;
+  GimpRGB                    color_at_pos;
+  gdouble                    original_color_rate = blend_modifier->current_orig_color_rate;
+  gdouble                    canvas_color_rate;
+  gboolean                   result;
+
+  blend_modifier_options = GIMP_BLEND_MODIFIER_OPTIONS(gimp_custom_brush_options_get_options_for(custom_brush_options,
+												 GIMP_TYPE_BLEND_MODIFIER));
+  canvas_color_rate = blend_modifier_options->canvas_color_rate;
+
+
+  image = gimp_item_get_image (GIMP_ITEM (drawable));
+
+
+  if (brush_core->brush && brush_core->brush->pixmap)
+    {
+      /* if it's a pixmap, do pixmap stuff */
+      gimp_brush_core_color_area_with_pixmap (brush_core, drawable,
+                                              area,
+                                              gimp_paint_options_get_brush_mode (paint_options));
+
+      paint_appl_mode = GIMP_PAINT_INCREMENTAL;
+    }
+  else
+    {
+      /* Blend brush color with underlying canvas color */
+      if (blend_modifier_options->canvas_color_rate > 0.0)
+	{
+	  /* Blend brush stroke color with foreground paint brush color */
+	  if (blend_modifier->current_orig_color_rate > 0.0)
+	    {
+
+	      if (blend_modifier_options->original_color_pressure_rate > 0.0)
+		{
+		  gdouble inv_pressure =
+		    (blend_modifier_options->invert_original_color_pressure)?
+		    paint_core->cur_coords.pressure :
+		    1 - paint_core->cur_coords.pressure;
+		  
+		  original_color_rate -= blend_modifier->current_orig_color_rate *
+		    inv_pressure;
+		  original_color_rate = CLAMP(original_color_rate, 0, 1.0);
+		}
+	    }
+	  
+	  /* Blend brush color with underlying canvas color */
+	  if (blend_modifier_get_blended_image_color_at (blend_modifier,
+						 image, context, drawable,
+						 blend_modifier_options,
+						       //						 &history->color,
+						 (gint) paint_core->cur_coords.x,
+						 (gint) paint_core->cur_coords.y,
+						 &color_at_pos))
+	    {
+	      if (blend_modifier_options->canvas_color_pressure_rate > 0.0)
+		{
+		  gdouble inv_pressure =
+		    (blend_modifier_options->invert_canvas_color_pressure)?
+		    paint_core->cur_coords.pressure :
+		    1 - paint_core->cur_coords.pressure;
+		  
+		  canvas_color_rate +=
+		    blend_modifier_options->canvas_color_pressure_rate *
+		    inv_pressure;
+		  canvas_color_rate = CLAMP(canvas_color_rate, 0.0, 1.0);
+		}
+	      foreground_color->a  = original_color_rate * (1 - canvas_color_rate);
+	      color_at_pos.a      *= canvas_color_rate;
+	      next_color->a       *= (1 - original_color_rate) * (1 - canvas_color_rate);
+	      blend_colors(next_color, 2, &color_at_pos, foreground_color);
+	    }
+	}
+
+      paint_appl_mode = GIMP_PAINT_INCREMENTAL;
+    }
+
+  custom_brush->state.color = blend_modifier->next_color;
+  
+  if (next_color->a > 0)
+    {
+      blend_modifier_register_info (blend_modifier,
+				    info,
+				    paint_core,
+				    paint_options,
+				    drawable,
+				    area,
+				    brush_opacity,
+				    image_opacity,
+				    paint_mode,
+				    brush_hardness,
+				    paint_appl_mode);
+      result = TRUE;
+    }
+  else
+    {
+      result = FALSE;
+    }
+
+  return result;
+}
+
+
+/*
+ * BrushCorePasteCanvasInfo Implementation
+ *
+ */
+static gint
+blend_modifier_paste_canvas_pre_paint (GimpBrushCorePasteCanvasInfo *info,
+				       GimpBrushCore                *core,
+				       GimpDrawable                 *drawable)
+{
+  GimpBlendModifier *blend_modifier = GIMP_BLEND_MODIFIER (info->user_data);
+  TempBuf      *area = info->gimp_brush_area;
+  guchar        color[MAX_CHANNELS];
+  
+  gimp_rgba_get_uchar(&blend_modifier->next_color,
+		     &color[0], &color[1], &color[2], &color[3]);
+
+  color_pixels (temp_buf_data (area), color,
+		area->width * area->height,
+		area->bytes);
+  return 0;
+}
+
+
+static gint
+blend_modifier_paste_canvas_paint(GimpBrushCorePasteCanvasInfo *info,
+				 GimpBrushCore                *core,
+				 GimpDrawable                 *drawable,
+				 PixelRegion                  *canvasPR,
+				 PixelRegion                  *maskPR)
+{
+  GimpBlendModifier *blend_modifier = GIMP_BLEND_MODIFIER (info->user_data);
+
+  TempBuf       *area = info->gimp_brush_area;
+  gdouble        paint_opacity = info->brush_opacity;
+
+  PixelRegion    canvasPR1;
+  PixelRegion    srcPR1;
+
+  guchar        color[MAX_CHANNELS];
+  gimp_rgba_get_uchar(&blend_modifier->next_color,
+		     &color[0], &color[1], &color[2], &color[3]);
+  
+  /* srcPR will be the pixels under the current painthit from the drawable */
+  pixel_region_init (&srcPR1, gimp_drawable_get_tiles (drawable),
+                     area->x, area->y, area->width, area->height, FALSE);
+
+  canvasPR1 = *canvasPR;
+
+  /*
+   * New pixel is:
+   *  P = brush * image_opacity * brush_opacity * paint_opacity +
+   *      src  * (image_opacity) * (1 - paint_opacity) +
+   *      src  * (1 - image_opacity)
+   *    = image_opacity *
+   *        ((brush * brush_opacity) * paint_opacity + (1-paint_opacity) * src) +
+   *      (1-image_opacity) * src
+   *    = replace( src, shade( src, brush with opacity, paint_opacity), image_opacity)
+   */
+  shade_region(&srcPR1, &canvasPR1, color, CLAMP(paint_opacity * 255.0, 0, 255));
+  
+  return 0;
+}
+
+static gint
+blend_modifier_paste_canvas_apply(GimpBrushCorePasteCanvasInfo *info,
+				 GimpBrushCore                *brush_core,
+				 GimpDrawable                 *drawable,
+				 PixelRegion                  *srcPR,
+				 PixelRegion                  *maskPR,
+				 TileManager                  *undo_tiles)
+{
+  GimpPaintCore *paintcore     = GIMP_PAINT_CORE (brush_core);
+
+  /*  apply the paint area to the image  */
+  gimp_drawable_replace_region (drawable, srcPR,
+				FALSE, NULL,
+				info->image_opacity,
+				maskPR,
+				paintcore->canvas_buf->x,
+				paintcore->canvas_buf->y);
+  return 0;
+}
+
+inline static void
+blend_modifier_register_info (GimpBlendModifier       *modifier,
+			      GimpBrushCorePasteCanvasInfo** head_info,
+			      GimpPaintCore           *paint_core,
+			      GimpPaintOptions         *paint_options,
+			      GimpDrawable             *drawable,
+			      TempBuf                  *area,
+			      gdouble                   paint_opacity,
+			      gdouble                   image_opacity,
+			      GimpLayerModeEffects      paint_mode,
+			      GimpBrushApplicationMode  brush_hardness,
+			      GimpPaintApplicationMode  mode)
+{
+  GimpBrushCorePasteCanvasInfo *brush_info = &modifier->brush_info;
+
+  brush_info->gimp_brush_area   = area;
+  brush_info->brush_opacity     = paint_opacity; // [error]should be paint_opacity
+  brush_info->image_opacity     = CLAMP (image_opacity, 0, 1);
+  brush_info->paint_mode        = paint_mode;
+  brush_info->apply             = TRUE;
+  brush_info->brush_hardness    = brush_hardness;
+  brush_info->post_paint        = NULL;
+
+  if (gimp_drawable_has_alpha(drawable))
+    {
+      brush_info->pre_paint         = NULL;
+      brush_info->apply_operation   = blend_modifier_paste_canvas_apply;
+      brush_info->paint_operation   = blend_modifier_paste_canvas_paint;
+    }
+  else
+    {
+      brush_info->pre_paint         = blend_modifier_paste_canvas_pre_paint;
+      brush_info->apply_operation   = NULL;
+      brush_info->paint_operation   = NULL;
+    }
+  brush_info->user_data         = modifier; // [error]should be brush_opacity
+  brush_info->next              = NULL;
+
+  *head_info = brush_info;
+}
diff -uNr gimp-2.4.1/app/paint/gimpblendmodifier.h gimp-2.4.1-tmp/app/paint/gimpblendmodifier.h
--- gimp-2.4.1/app/paint/gimpblendmodifier.h	1970-01-01 09:00:00.000000000 +0900
+++ gimp-2.4.1-tmp/app/paint/gimpblendmodifier.h	2008-03-22 21:39:28.000000000 +0900
@@ -0,0 +1,73 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GIMP_BLEND_MODIFIER_H__
+#define __GIMP_BLEND_MODIFIER_H__
+
+
+#include "gimpbrushmodifiercore.h"
+
+
+#define GIMP_TYPE_BLEND_MODIFIER         (gimp_blend_modifier_get_type ())
+#define GIMP_BLEND_MODIFIER(obj)         (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_BLEND_MODIFIER, GimpBlendModifier))
+#define GIMP_BLEND_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_BLEND_MODIFIER, GimpBlendModifierClass))
+#define GIMP_IS_BLEND_MODIFIER(obj)      (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_BLEND_MODIFIER))
+#define GIMP_IS_BLEND_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_BLEND_MODIFIER))
+#define GIMP_BLEND_MODIFIER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_BLEND_MODIFIER, GimpBlendModifierClass))
+
+
+typedef struct _GimpBlendModifierCoordsHistory
+{
+  GimpCoords cur_coords;
+  GimpCoords last_coords;
+  gdouble    pixel_dist;
+  GimpRGB    color;
+} GimpBlendModifierCoordsHistory;
+
+typedef struct _GimpBlendModifier GimpBlendModifier;
+typedef struct _GimpBlendModifierClass GimpBlendModifierClass;
+
+#define GIMP_BLEND_MODIFIER_MAX_HISTORY 20
+struct _GimpBlendModifier
+{
+  GimpBrushModifierCore   parent_instance;
+
+  //  GimpDrawable             *drawable;
+  //  GimpPaintOptions         *paint_options;
+  gdouble                   current_orig_color_rate;
+  GimpRGB                   next_color;
+  GimpRGB                   foreground_color;
+
+  /* circular history buffer */
+  GimpBlendModifierCoordsHistory history[GIMP_BLEND_MODIFIER_MAX_HISTORY + 1];
+  gint                      history_head;
+  gint                      history_tail;
+  GimpBrushCorePasteCanvasInfo brush_info;
+};
+
+struct _GimpBlendModifierClass
+{
+  GimpBrushModifierCoreClass  parent_class;
+};
+
+
+GType     gimp_blend_modifier_get_type                  (void) G_GNUC_CONST;
+GimpBlendModifier* gimp_blend_modifier_new(void);
+
+
+#endif
diff -uNr gimp-2.4.1/app/paint/gimpblendmodifieroptions.c gimp-2.4.1-tmp/app/paint/gimpblendmodifieroptions.c
--- gimp-2.4.1/app/paint/gimpblendmodifieroptions.c	1970-01-01 09:00:00.000000000 +0900
+++ gimp-2.4.1-tmp/app/paint/gimpblendmodifieroptions.c	2008-03-23 04:58:46.000000000 +0900
@@ -0,0 +1,317 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+
+#include "libgimpconfig/gimpconfig.h"
+#include "paint-types.h"
+#include "core/gimp.h"
+
+#include "gimpblendmodifier.h"
+#include "gimpblendmodifieroptions.h"
+
+
+static gboolean
+gimp_blend_modifier_options_install     (GimpBrushModifierOptionsClass *klass,
+					 GimpPaintOptionsClass         *options_class,
+					 guint                         *base_property_id);
+
+
+
+static gboolean
+gimp_blend_modifier_options_set_property (GimpBrushModifierOptions *object,
+					  guint                     property_id,
+					  const GValue             *value,
+					  GParamSpec               *pspec);
+static gboolean
+gimp_blend_modifier_options_get_property (GimpBrushModifierOptions *object,
+					  guint                     property_id,
+					  GValue                   *value,
+					  GParamSpec               *pspec);
+
+
+#define BLEND_MODIFIER_DEFAULT_CANVAS_COLOR_RATE   0.8
+#define BLEND_MODIFIER_DEFAULT_ORIGINAL_COLOR_RATE 0.5
+#define BLEND_MODIFIER_DEFAULT_MERGED              FALSE
+#define BLEND_MODIFIER_DEFAULT_HIDDEN_COLOR        GIMP_HIDDEN_COLOR_WHITE
+#define BLEND_MODIFIER_DEFAULT_REMOVE_COLOR        FALSE
+
+
+enum
+{
+  PROP_ENABLED,
+  PROP_CANVAS_COLOR_RATE,
+  PROP_ORIGINAL_COLOR_RATE,
+  PROP_CANVAS_COLOR_PRESSURE_RATE,
+  PROP_ORIGINAL_COLOR_PRESSURE_RATE,
+  PROP_MERGED,
+  PROP_HIDDEN_COLOR,
+  PROP_INVERT_ORIGINAL_COLOR_PRESSURE,
+  PROP_INVERT_CANVAS_COLOR_PRESSURE
+};
+
+G_DEFINE_TYPE (GimpBlendModifierOptions, gimp_blend_modifier_options,
+               GIMP_TYPE_BRUSH_MODIFIER_OPTIONS)
+
+#define parent_class gimp_blend_modifier_options_parent_class
+
+
+static void
+gimp_blend_modifier_options_class_init (GimpBlendModifierOptionsClass *klass)
+{
+  GimpBrushModifierOptionsClass *modifier_class = GIMP_BRUSH_MODIFIER_OPTIONS_CLASS (klass);
+
+  modifier_class->base_property_id = 0;
+
+  modifier_class->install      = gimp_blend_modifier_options_install;
+  modifier_class->set_property = gimp_blend_modifier_options_set_property;
+  modifier_class->get_property = gimp_blend_modifier_options_get_property;
+}
+
+static void
+gimp_blend_modifier_options_init (GimpBlendModifierOptions *options)
+{
+  GimpBrushModifierOptions *modifier_options = GIMP_BRUSH_MODIFIER_OPTIONS(options);
+  g_print("[Trace]blend_modifier_options::init\n");
+  modifier_options->attached_to = GIMP_TYPE_BLEND_MODIFIER;
+}
+
+
+static gboolean
+gimp_blend_modifier_options_install(GimpBrushModifierOptionsClass *klass,
+				    GimpPaintOptionsClass         *options_class,
+				    guint                         *base_property_id)
+{
+  GObjectClass* object_class = G_OBJECT_CLASS(options_class);
+  guint         n_properties = 0;
+  klass->base_property_id = *base_property_id;
+  
+
+  g_print("[Trace]blend_modifier_options::install[%x]\n", *base_property_id);
+
+  /* enabled parameter should be handled automatically, but not yet implemented */
+  GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_ENABLED + *base_property_id,
+                                    "blend-enabled", NULL,
+                                    TRUE,
+                                    GIMP_PARAM_STATIC_STRINGS);
+  n_properties ++;
+
+
+  GIMP_CONFIG_INSTALL_PROP_DOUBLE  (object_class, PROP_CANVAS_COLOR_RATE + *base_property_id,
+                                    "canvas-color-rate", NULL,
+                                    0.0, 1.0, BLEND_MODIFIER_DEFAULT_CANVAS_COLOR_RATE,
+                                    GIMP_PARAM_STATIC_STRINGS);
+  n_properties ++;
+
+  GIMP_CONFIG_INSTALL_PROP_DOUBLE  (object_class, PROP_CANVAS_COLOR_PRESSURE_RATE + *base_property_id,
+                                    "canvas-color-pressure-rate", NULL,
+                                    0.0, 1.0, BLEND_MODIFIER_DEFAULT_CANVAS_COLOR_RATE,
+                                    GIMP_PARAM_STATIC_STRINGS);
+  n_properties ++;
+
+  GIMP_CONFIG_INSTALL_PROP_DOUBLE  (object_class, PROP_ORIGINAL_COLOR_RATE + *base_property_id,
+                                    "original-color-rate", NULL,
+                                    0.0, 1.0, BLEND_MODIFIER_DEFAULT_ORIGINAL_COLOR_RATE,
+                                    GIMP_PARAM_STATIC_STRINGS);
+  n_properties ++;
+
+  GIMP_CONFIG_INSTALL_PROP_DOUBLE  (object_class, PROP_ORIGINAL_COLOR_PRESSURE_RATE + *base_property_id,
+                                    "original-color-pressure-rate", NULL,
+                                    0.0, 1.0, BLEND_MODIFIER_DEFAULT_CANVAS_COLOR_RATE,
+                                    GIMP_PARAM_STATIC_STRINGS);
+  n_properties ++;
+
+  GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_MERGED + *base_property_id,
+                                    "merged", NULL,
+                                    BLEND_MODIFIER_DEFAULT_MERGED,
+                                    GIMP_PARAM_STATIC_STRINGS);
+  n_properties ++;
+
+  GIMP_CONFIG_INSTALL_PROP_ENUM    (object_class, PROP_HIDDEN_COLOR + *base_property_id,
+                                    "hidden-color", NULL,
+                                    GIMP_TYPE_HIDDEN_COLOR,
+                                    BLEND_MODIFIER_DEFAULT_HIDDEN_COLOR,
+                                    GIMP_PARAM_STATIC_STRINGS);
+  n_properties ++;
+
+  GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_INVERT_ORIGINAL_COLOR_PRESSURE + *base_property_id,
+                                    "invert-original-color-pressure", NULL,
+                                    FALSE,
+                                    GIMP_PARAM_STATIC_STRINGS);
+  n_properties ++;
+  
+  GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_INVERT_CANVAS_COLOR_PRESSURE + *base_property_id,
+                                    "invert-canvas-color-pressure", NULL,
+                                    FALSE,
+                                    GIMP_PARAM_STATIC_STRINGS);
+  n_properties ++;
+
+  *base_property_id += n_properties;
+
+  return TRUE;
+}
+
+
+static gboolean
+gimp_blend_modifier_options_set_property (GimpBrushModifierOptions *object,
+					  guint                     property_id,
+					  const GValue             *value,
+					  GParamSpec               *pspec)
+{
+  GimpBlendModifierOptions *options = GIMP_BLEND_MODIFIER_OPTIONS (object);
+
+  g_print("[Trace]blend_modifier_options::set_property[%x-%x]\n",
+	  property_id,
+	  GIMP_BRUSH_MODIFIER_OPTIONS_GET_CLASS(object)->base_property_id);
+
+  switch (property_id - GIMP_BRUSH_MODIFIER_OPTIONS_GET_CLASS(object)->base_property_id)
+    {
+    case PROP_ENABLED:
+      GIMP_BRUSH_MODIFIER_OPTIONS(options)->enabled = g_value_get_boolean (value);
+      g_print("[Trace]->PROP_ENABLED\n");
+      break;
+      
+    case PROP_CANVAS_COLOR_RATE:
+      options->canvas_color_rate = g_value_get_double (value);
+      g_print("[Trace]->PROP_CANVAS_COLOR_RATE\n");
+      break;
+    case PROP_CANVAS_COLOR_PRESSURE_RATE:
+      options->canvas_color_pressure_rate = g_value_get_double (value);
+      g_print("[Trace]->PROP_CANVAS_COLOR_PRESSURE_RATE\n");
+      break;
+    case PROP_ORIGINAL_COLOR_RATE:
+      options->original_color_rate = g_value_get_double (value);
+      g_print("[Trace]->PROP_ORIGINAL_COLOR_RATE\n");
+      break;
+    case PROP_ORIGINAL_COLOR_PRESSURE_RATE:
+      options->original_color_pressure_rate = g_value_get_double (value);
+      g_print("[Trace]->PROP_ORIGINAL_COLOR_PRESSURE_RATE\n");
+      break;
+    case PROP_MERGED:
+      options->merged = g_value_get_boolean (value);
+      g_print("[Trace]->PROP_MERGED\n");
+      break;
+    case PROP_HIDDEN_COLOR:
+      options->hidden_color = g_value_get_enum (value);
+      g_print("[Trace]->PROP_HIDDEN_COLOR\n");
+      break;
+    case PROP_INVERT_ORIGINAL_COLOR_PRESSURE:
+      options->invert_original_color_pressure = g_value_get_boolean (value);
+      g_print("[Trace]->PROP_INVERT_ORIGINAL_COLOR_PRESSURE\n");
+      break;
+    case PROP_INVERT_CANVAS_COLOR_PRESSURE:
+      options->invert_canvas_color_pressure = g_value_get_boolean (value);
+      g_print("[Trace]->PROP_INVERT_CANVAS_COLOR_PRESSURE\n");
+      break;
+    default:
+      return FALSE;
+      break;
+    }
+  return TRUE;
+}
+
+static gboolean
+gimp_blend_modifier_options_get_property (GimpBrushModifierOptions *object,
+					  guint                     property_id,
+					  GValue                   *value,
+					  GParamSpec               *pspec)
+{
+  GimpBlendModifierOptions *options = GIMP_BLEND_MODIFIER_OPTIONS (object);
+
+  g_print("[Trace]blend_modifier_options::get_property[%x-%x]\n",
+	  property_id,
+	  GIMP_BRUSH_MODIFIER_OPTIONS_GET_CLASS(object)->base_property_id);
+
+  switch (property_id - GIMP_BRUSH_MODIFIER_OPTIONS_GET_CLASS(object)->base_property_id)
+    {
+    case PROP_ENABLED:
+      g_value_set_boolean(value, GIMP_BRUSH_MODIFIER_OPTIONS(options)->enabled);
+      g_print("[Trace]->PROP_ENABLED\n");
+      break;
+      
+    case PROP_CANVAS_COLOR_RATE:
+      g_value_set_double (value, options->canvas_color_rate);
+      g_print("[Trace]->PROP_CANVAS_COLOR_RATE\n");
+      break;
+    case PROP_CANVAS_COLOR_PRESSURE_RATE:
+      g_value_set_double (value, options->canvas_color_pressure_rate);
+      g_print("[Trace]->PROP_CANVAS_COLOR_PRESSURE_RATE\n");
+      break;
+    case PROP_ORIGINAL_COLOR_RATE:
+      g_value_set_double (value, options->original_color_rate);
+      g_print("[Trace]->PROP_ORIGINAL_COLOR_RATE\n");
+      break;
+    case PROP_ORIGINAL_COLOR_PRESSURE_RATE:
+      g_value_set_double (value, options->original_color_pressure_rate);
+      g_print("[Trace]->PROP_ORIGINAL_COLOR_PRESSURE_RATE\n");
+      break;
+    case PROP_MERGED:
+      g_value_set_boolean (value, options->merged);
+      g_print("[Trace]->PROP_MERGED\n");
+      break;
+    case PROP_HIDDEN_COLOR:
+      g_value_set_enum (value, options->hidden_color);
+      g_print("[Trace]->PROP_HIDDEN_COLOR\n");
+      break;
+    case PROP_INVERT_ORIGINAL_COLOR_PRESSURE:
+      g_value_set_boolean (value, options->invert_original_color_pressure);
+      g_print("[Trace]->PROP_INVERT_ORIGINAL_COLOR_PRESSURE\n");
+      break;
+    case PROP_INVERT_CANVAS_COLOR_PRESSURE:
+      g_value_set_boolean (value, options->invert_canvas_color_pressure);
+      g_print("[Trace]->PROP_INVERT_CANVAS_COLOR_PRESSURE\n");
+      break;
+    default:
+      return FALSE;
+      break;
+    }
+  return TRUE;
+}
+
+
+GType
+gimp_hidden_color_get_type (void)
+{
+  static const GEnumValue values[] =
+  {
+    { GIMP_HIDDEN_COLOR_NORMAL, "GIMP_HIDDEN_COLOR_NORMAL", "normal" },
+    { GIMP_HIDDEN_COLOR_WHITE, "GIMP_HIDDEN_COLOR_WHITE", "white" },
+    { GIMP_HIDDEN_COLOR_BACKGROUND, "GIMP_HIDDEN_COLOR_BACKGROUND", "background color" },
+    { 0, NULL, NULL }
+  };
+
+  static const GimpEnumDesc descs[] =
+  {
+    { GIMP_HIDDEN_COLOR_NORMAL, "normal", NULL },
+    { GIMP_HIDDEN_COLOR_WHITE, "white", NULL },
+    { GIMP_HIDDEN_COLOR_BACKGROUND, "background color", NULL },
+    { 0, NULL, NULL }
+  };
+
+  static GType type = 0;
+
+  if (! type)
+    {
+      type = g_enum_register_static ("GimpHiddenColor", values);
+      gimp_enum_set_value_descriptions (type, descs);
+    }
+
+  return type;
+}
diff -uNr gimp-2.4.1/app/paint/gimpblendmodifieroptions.h gimp-2.4.1-tmp/app/paint/gimpblendmodifieroptions.h
--- gimp-2.4.1/app/paint/gimpblendmodifieroptions.h	1970-01-01 09:00:00.000000000 +0900
+++ gimp-2.4.1-tmp/app/paint/gimpblendmodifieroptions.h	2008-03-22 21:39:28.000000000 +0900
@@ -0,0 +1,79 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995-1999 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GIMP_BLEND_MODIFIER_OPTIONS_H__
+#define __GIMP_BLEND_MODIFIER_OPTIONS_H__
+
+
+#include "gimpbrushmodifieroptions.h"
+
+
+/* enum(s) */
+
+typedef enum
+{
+  GIMP_HIDDEN_COLOR_NORMAL,
+  GIMP_HIDDEN_COLOR_WHITE,
+  GIMP_HIDDEN_COLOR_BACKGROUND
+} GimpHiddenColor;
+
+GType   gimp_hidden_color_get_type (void) G_GNUC_CONST;
+#define GIMP_TYPE_HIDDEN_COLOR                (gimp_hidden_color_get_type ())
+
+
+/* class */
+
+#define GIMP_TYPE_BLEND_MODIFIER_OPTIONS            (gimp_blend_modifier_options_get_type ())
+#define GIMP_BLEND_MODIFIER_OPTIONS(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_BLEND_MODIFIER_OPTIONS, GimpBlendModifierOptions))
+#define GIMP_BLEND_MODIFIER_OPTIONS_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_BLEND_MODIFIER_OPTIONS, GimpBlendModifierOptionsClass))
+#define GIMP_IS_BLEND_MODIFIER_OPTIONS(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_BLEND_MODIFIER_OPTIONS))
+#define GIMP_IS_BLEND_MODIFIER_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_BLEND_MODIFIER_OPTIONS))
+#define GIMP_BLEND_MODIFIER_OPTIONS_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_BLEND_MODIFIER_OPTIONS, GimpBlendModifierOptionsClass))
+
+
+typedef struct _GimpBlendModifierOptionsClass GimpBlendModifierOptionsClass;
+typedef struct _GimpBlendModifierOptions      GimpBlendModifierOptions;
+
+
+struct _GimpBlendModifierOptions
+{
+  GimpBrushModifierOptions   parent_instance;
+
+  gdouble           canvas_color_rate;
+  gdouble           canvas_color_pressure_rate;
+  gdouble           original_color_rate;
+  gdouble           original_color_pressure_rate;
+  gdouble           delayed_color_rate;
+  guint             dryout;
+  guint             delay;
+  gboolean          merged;
+  gboolean          tail;
+  GimpHiddenColor   hidden_color;
+  gboolean          remove_color;
+  gboolean          invert_original_color_pressure;
+  gboolean          invert_canvas_color_pressure;
+};
+
+struct _GimpBlendModifierOptionsClass
+{
+  GimpBrushModifierOptionsClass  parent_class;
+};
+
+GType gimp_blend_modifier_options_get_type (void) G_GNUC_CONST;
+
+#endif  /*  __GIMP_BLEND_MODIFIER_OPTIONS_H__  */
diff -uNr gimp-2.4.1/app/paint/gimpbrushcore.c gimp-2.4.1-tmp/app/paint/gimpbrushcore.c
--- gimp-2.4.1/app/paint/gimpbrushcore.c	2007-08-16 06:56:50.000000000 +0900
+++ gimp-2.4.1-tmp/app/paint/gimpbrushcore.c	2008-03-22 21:39:28.000000000 +0900
@@ -41,6 +41,9 @@
 
 #include "gimp-intl.h"
 
+// Temporary needed!
+#include "paint-funcs/paint-funcs.h"
+#include "gimpairbrush.h"
 
 #define EPSILON  0.00001
 
@@ -810,13 +813,195 @@
                               GimpBrushApplicationMode  brush_hardness,
                               GimpPaintApplicationMode  mode)
 {
+  PixelRegion brush_maskPR;
+  if (gimp_brush_core_get_brush_maskPR(core, brush_hardness, &brush_maskPR))
+    {
+      gimp_paint_core_paste (GIMP_PAINT_CORE(core), &brush_maskPR, drawable,
+                             brush_opacity,
+                             image_opacity, paint_mode,
+                             mode);
+    }
+}
+
+
+struct _GimpBrushCorePasteCanvasInternal
+{
+  GimpPaintMaskInfo  info;
+  GimpBrushCorePasteCanvasInfo *pcinfo;
+  GimpBrushCore     *core;
+  GimpDrawable      *drawable;
+};
+typedef struct _GimpBrushCorePasteCanvasInternal GimpBrushCorePasteCanvasInternal;  
+
+static GimpBrushCorePasteCanvasInternal*
+brush_core_create_internal_list (gint num_items,
+				 GimpBrushCore *core,
+				 GimpDrawable  *drawable)
+{
+  GimpBrushCorePasteCanvasInternal *mask_info_list, *cur_mask_info;
+  gint i;
+  
+  cur_mask_info =
+    mask_info_list =
+    (GimpBrushCorePasteCanvasInternal*)g_malloc0(num_items * sizeof(GimpBrushCorePasteCanvasInternal));
+  if (!mask_info_list)
+    return NULL;
+
+  for (i = 0; i < num_items; i ++)
+    {
+      if (i == num_items - 1)
+	cur_mask_info->info.next         = NULL;
+      else
+	cur_mask_info->info.next         = &(cur_mask_info + 1)->info;
+      
+      cur_mask_info->info.delegator_data = cur_mask_info;
+      cur_mask_info->core                = core;
+      cur_mask_info->drawable            = drawable;
+      cur_mask_info ++;
+    }
+
+  return mask_info_list;
+}
+
+
+
+static gint
+gimp_brush_core_process_paste_canvas_pre_paint (GimpPaintMaskInfo        *info,
+						GimpPaintCore            *core,
+						GimpDrawable             *drawable,
+						GimpPaintApplicationMode  mode)
+{
+  GimpBrushCorePasteCanvasInternal *internal = (GimpBrushCorePasteCanvasInternal*)info->delegator_data;
+  internal->pcinfo->pre_paint(internal->pcinfo, GIMP_BRUSH_CORE(core), drawable);
+
+  return 0;
+}
+
+
+
+static gint
+gimp_brush_core_process_paste_canvas_paint (GimpPaintMaskInfo        *info,
+					    GimpPaintCore            *core,
+					    GimpDrawable             *drawable,
+					    GimpPaintApplicationMode  mode,
+					    PixelRegion              *srcPR)
+{
+  GimpBrushCorePasteCanvasInternal *internal = (GimpBrushCorePasteCanvasInternal*)info->delegator_data;
+  if (!gimp_brush_core_get_brush_maskPR(GIMP_BRUSH_CORE(core),
+					internal->pcinfo->brush_hardness,
+					info->paint_maskPR))
+    return -1;
+  {
+    PixelRegion paint_maskPR_copy = *info->paint_maskPR;
+    
+    if (internal->pcinfo->paint_operation)
+      return internal->pcinfo->paint_operation(internal->pcinfo, GIMP_BRUSH_CORE(core),
+					   drawable, srcPR, &paint_maskPR_copy);
+    else if (mode == GIMP_PAINT_CONSTANT)
+      /*  combine the mask to the canvas tiles  */
+      combine_mask_and_region (srcPR, &paint_maskPR_copy,
+			       info->paint_opacity * 255.999, GIMP_IS_AIRBRUSH (core));
+    else
+      /*  apply the mask  */
+      apply_mask_to_region (srcPR, &paint_maskPR_copy, info->paint_opacity * 255.999);
+  }
+  return 0;
+}
+
+
+
+static gint
+gimp_brush_core_process_paste_canvas_post_paint (GimpPaintMaskInfo        *info,
+						 GimpPaintCore            *core,
+						 GimpDrawable             *drawable,
+						 GimpPaintApplicationMode  mode)
+{
+  GimpBrushCorePasteCanvasInternal *internal = (GimpBrushCorePasteCanvasInternal*)info->delegator_data;
+  /* This function is called only if pcinfo->post_paint != NULL */
+    return internal->pcinfo->post_paint(internal->pcinfo, GIMP_BRUSH_CORE(core), drawable);
+
+  return 0;
+}
+
+
+
+static gint
+gimp_brush_core_process_paste_canvas_apply (GimpPaintMaskInfo        *info,
+					    GimpPaintCore            *core,
+					    GimpDrawable             *drawable,
+					    GimpPaintApplicationMode  mode,
+					    PixelRegion              *srcPR,
+					    TileManager              *undo_tiles)
+{
+  GimpBrushCorePasteCanvasInternal *internal = (GimpBrushCorePasteCanvasInternal*)info->delegator_data;
+  PixelRegion paint_maskPR_copy = *info->paint_maskPR;
+  /* This function is called only if pcinfo->apply_operation != NULL */
+  return internal->pcinfo->apply_operation(internal->pcinfo, GIMP_BRUSH_CORE(core),
+					   drawable, srcPR, &paint_maskPR_copy, undo_tiles);
+}
+
+
+void
+gimp_brush_core_process_paste_canvas (GimpBrushCore                *core,
+				      GimpDrawable                 *drawable,
+				      GimpBrushCorePasteCanvasInfo *info,
+				      GimpPaintApplicationMode      mode)
+{
+  PixelRegion brush_maskPR;
+  GimpBrushCorePasteCanvasInternal *mask_info_list, *cur_mask_info;
+  gint info_num = 0;
+  GimpBrushCorePasteCanvasInfo *cur_info = info;
+
+  /* Create GimpPaintMask Info list */
+  while (cur_info)
+    {
+      cur_info = cur_info->next;
+      info_num ++;
+    }
+
+  cur_mask_info =
+    mask_info_list =
+    brush_core_create_internal_list (info_num, core, drawable);
+ 
+  /* Setup info parameters */
+  while (info)
+    {
+      cur_mask_info->info.paint_maskPR   = &brush_maskPR;
+      cur_mask_info->info.paint_opacity  = info->brush_opacity;
+      cur_mask_info->info.image_opacity  = info->image_opacity;
+      cur_mask_info->info.apply          = info->apply;
+      cur_mask_info->info.paint_mode     = info->paint_mode;
+      cur_mask_info->pcinfo              = info;
+      cur_mask_info->info.paint_operation = gimp_brush_core_process_paste_canvas_paint;
+      if (info->pre_paint)
+	cur_mask_info->info.pre_paint      = gimp_brush_core_process_paste_canvas_pre_paint;
+      if (info->post_paint)
+	cur_mask_info->info.post_paint      = gimp_brush_core_process_paste_canvas_post_paint;
+      if (info->apply_operation)
+	cur_mask_info->info.apply_operation = gimp_brush_core_process_paste_canvas_apply;
+
+      cur_mask_info ++;
+      info          = info->next;
+    }
+
+  /* Execute paste processing */
+  gimp_paint_core_paste_mask_list (GIMP_PAINT_CORE(core), drawable,
+				   &mask_info_list->info,
+				   mode);
+  g_free (mask_info_list);
+}
+
+gboolean
+gimp_brush_core_get_brush_maskPR (GimpBrushCore            *core,
+				  GimpBrushApplicationMode  brush_hardness,
+				  PixelRegion              *brush_maskPR)
+{
   TempBuf *brush_mask = gimp_brush_core_get_brush_mask (core,
                                                         brush_hardness);
 
   if (brush_mask)
     {
       GimpPaintCore *paint_core = GIMP_PAINT_CORE (core);
-      PixelRegion    brush_maskPR;
       gint           x;
       gint           y;
       gint           off_x;
@@ -828,16 +1013,14 @@
       off_x = (x < 0) ? -x : 0;
       off_y = (y < 0) ? -y : 0;
 
-      pixel_region_init_temp_buf (&brush_maskPR, brush_mask,
+      pixel_region_init_temp_buf (brush_maskPR, brush_mask,
                                   off_x, off_y,
                                   paint_core->canvas_buf->width,
                                   paint_core->canvas_buf->height);
-
-      gimp_paint_core_paste (paint_core, &brush_maskPR, drawable,
-                             brush_opacity,
-                             image_opacity, paint_mode,
-                             mode);
+      return TRUE;
     }
+  else
+    return FALSE;
 }
 
 /* Similar to gimp_brush_core_paste_canvas, but replaces the alpha channel
diff -uNr gimp-2.4.1/app/paint/gimpbrushcore.h gimp-2.4.1-tmp/app/paint/gimpbrushcore.h
--- gimp-2.4.1/app/paint/gimpbrushcore.h	2007-07-25 03:45:42.000000000 +0900
+++ gimp-2.4.1-tmp/app/paint/gimpbrushcore.h	2008-03-22 21:39:28.000000000 +0900
@@ -98,6 +98,46 @@
                       GimpBrush     *brush);
 };
 
+typedef struct _GimpBrushCorePasteCanvasInfo GimpBrushCorePasteCanvasInfo;
+typedef gint (*GimpBrushCorePasteCanvasInfoEventCallback)
+     (GimpBrushCorePasteCanvasInfo *info,
+      GimpBrushCore                *core,
+      GimpDrawable                 *drawable);
+
+typedef gint (*GimpBrushCorePasteCanvasInfoPaintDelegator)
+     (GimpBrushCorePasteCanvasInfo *info,
+      GimpBrushCore                *core,
+      GimpDrawable                 *drawable,
+      PixelRegion                  *srcPR,
+      PixelRegion                  *brush_maskPR);
+					      
+typedef gint (*GimpBrushCorePasteCanvasInfoApplicationDelegator)
+     (GimpBrushCorePasteCanvasInfo *info,
+      GimpBrushCore                *core,
+      GimpDrawable                 *drawable,
+      PixelRegion                  *srcPR,
+      PixelRegion                  *maskPR,
+      TileManager                  *undo_tiles);
+
+
+struct _GimpBrushCorePasteCanvasInfo
+{
+  TempBuf                               *gimp_brush_area;
+  gdouble                                brush_opacity;
+  gdouble                                image_opacity;
+  GimpLayerModeEffects                   paint_mode;
+  GimpBrushApplicationMode               brush_hardness;
+  GimpPaintApplicationMode               mode;
+  GimpBrushCorePasteCanvasInfoPaintDelegator  paint_operation;
+  GimpBrushCorePasteCanvasInfoEventCallback  pre_paint;
+  GimpBrushCorePasteCanvasInfoEventCallback  post_paint;
+  GimpBrushCorePasteCanvasInfoApplicationDelegator  apply_operation;
+  gboolean                               apply;
+  void                                  *user_data;
+  GimpBrushCorePasteCanvasInfo          *next;
+};
+
+
 
 GType   gimp_brush_core_get_type       (void) G_GNUC_CONST;
 
@@ -113,6 +153,11 @@
                                         GimpLayerModeEffects      paint_mode,
                                         GimpBrushApplicationMode  brush_hardness,
                                         GimpPaintApplicationMode  mode);
+void    gimp_brush_core_process_paste_canvas
+                                       (GimpBrushCore                *core,
+					GimpDrawable                 *drawable,
+					GimpBrushCorePasteCanvasInfo *info,
+					GimpPaintApplicationMode      mode);
 void    gimp_brush_core_replace_canvas (GimpBrushCore            *core,
                                         GimpDrawable             *drawable,
                                         gdouble                   brush_opacity,
@@ -126,5 +171,9 @@
                                         TempBuf                  *area,
                                         GimpBrushApplicationMode  mode);
 
+gboolean
+gimp_brush_core_get_brush_maskPR       (GimpBrushCore            *core,
+					GimpBrushApplicationMode  brush_hardness,
+					PixelRegion              *brush_maskPR);
 
 #endif  /*  __GIMP_BRUSH_CORE_H__  */
diff -uNr gimp-2.4.1/app/paint/gimpbrushmodifiercore.c gimp-2.4.1-tmp/app/paint/gimpbrushmodifiercore.c
--- gimp-2.4.1/app/paint/gimpbrushmodifiercore.c	1970-01-01 09:00:00.000000000 +0900
+++ gimp-2.4.1-tmp/app/paint/gimpbrushmodifiercore.c	2008-03-22 21:39:28.000000000 +0900
@@ -0,0 +1,128 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <glib-object.h>
+
+#include "libgimpmath/gimpmath.h"
+
+#include "paint-types.h"
+
+#include "base/boundary.h"
+#include "base/pixel-region.h"
+#include "base/temp-buf.h"
+
+#include "core/gimpbrush.h"
+#include "core/gimpdrawable.h"
+
+#include "gimpbrushcore.h"
+
+#include "gimpbrushmodifiercore.h"
+
+/*  local function prototypes  */
+
+static void     gimp_brush_modifier_core_finalize (GObject          *object);
+
+
+/* BrushModifierDelegator stuff */
+
+void
+brush_modifier_delegator_init   (BrushModifierDelegator *delegator)
+{
+  g_assert(delegator != NULL);
+  delegator->callback = NULL;
+  delegator->modifier = NULL;
+  delegator->next     = NULL;
+}
+
+void
+brush_modifier_delegator_bind   (BrushModifierDelegator *delegator,
+				 GimpBrushModifierCore  *modifier,
+				 gpointer                callback)
+{
+  g_assert(delegator != NULL);
+  delegator->callback = callback;
+  delegator->modifier = modifier;
+}
+
+
+BrushModifierDelegator*
+brush_modifier_delegator_append (BrushModifierDelegator *delegators,
+				 BrushModifierDelegator *new_delegator)
+{
+  if (!delegators)
+    {
+      if ( !new_delegator ||
+	   !new_delegator->callback ||
+	   !new_delegator->modifier )
+	return NULL;
+      
+      new_delegator->next = NULL;
+      return new_delegator;
+    }
+  else
+    {
+      if ( new_delegator->callback != NULL &&
+	   new_delegator->modifier != NULL)
+	{
+	  BrushModifierDelegator *pointer = delegators;
+	  while (pointer->next != NULL)
+	    pointer = pointer->next;
+	  
+	  pointer->next       = new_delegator;
+	  new_delegator->next = NULL;
+	}
+    }
+  return delegators;
+}
+
+
+
+/* BrushModifierCore stuff */
+
+G_DEFINE_TYPE (GimpBrushModifierCore, gimp_brush_modifier_core, GIMP_TYPE_OBJECT)
+
+#define parent_class gimp_brush_modifier_core_parent_class
+
+
+static void
+gimp_brush_modifier_core_class_init (GimpBrushModifierCoreClass *klass)
+{
+  GObjectClass *object_class   = G_OBJECT_CLASS (klass);
+
+  object_class->finalize       = gimp_brush_modifier_core_finalize;
+}
+
+static void
+gimp_brush_modifier_core_init (GimpBrushModifierCore *modifier)
+{
+  brush_modifier_delegator_init(&modifier->init_motion_delegator);
+  brush_modifier_delegator_init(&modifier->motion_delegator);
+  brush_modifier_delegator_init(&modifier->finish_motion_delegator);
+  brush_modifier_delegator_init(&modifier->register_paste_canvas_delegator);
+  brush_modifier_delegator_init(&modifier->scale_mask_size_delegator);
+}
+
+static void
+gimp_brush_modifier_core_finalize (GObject *object)
+{
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
diff -uNr gimp-2.4.1/app/paint/gimpbrushmodifiercore.h gimp-2.4.1-tmp/app/paint/gimpbrushmodifiercore.h
--- gimp-2.4.1/app/paint/gimpbrushmodifiercore.h	1970-01-01 09:00:00.000000000 +0900
+++ gimp-2.4.1-tmp/app/paint/gimpbrushmodifiercore.h	2008-03-22 21:39:28.000000000 +0900
@@ -0,0 +1,176 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GIMP_BRUSHMODIFIER_CORE_H__
+#define __GIMP_BRUSHMODIFIER_CORE_H__
+
+
+#include "gimpbrushcore.h"
+
+
+#define GIMP_TYPE_BRUSH_MODIFIER_CORE         (gimp_brush_modifier_core_get_type ())
+#define GIMP_BRUSH_MODIFIER_CORE(obj)         (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_BRUSH_MODIFIER_CORE, GimpBrushModifierCore))
+#define GIMP_BRUSH_MODIFIER_CORE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_BRUSH_MODIFIER_CORE, GimpBrushModifierCoreClass))
+#define GIMP_IS_BRUSH_MODIFIER_CORE(obj)      (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_BRUSH_MODIFIER_CORE))
+#define GIMP_IS_BRUSH_MODIFIER_CORE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_BRUSH_MODIFIER_CORE))
+#define GIMP_BRUSH_MODIFIER_CORE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_BRUSH_MODIFIER_CORE, GimpBrushModifierCoreClass))
+
+
+typedef struct _GimpBrushModifierCore GimpBrushModifierCore;
+typedef struct _GimpBrushModifierCoreClass GimpBrushModifierCoreClass;
+
+
+typedef gboolean
+(* BrushModifierInitMotion)    (GimpBrushModifierCore *modifier,
+				GimpBrushCore    *paint_core,
+				GimpDrawable     *drawable,
+				GimpPaintOptions *paint_options,
+				guint32           time);
+
+typedef gboolean
+(* BrushModifierMotion)         (GimpBrushModifierCore *modifier,
+				 GimpBrushCore    *brush_core,
+				 GimpDrawable     *drawable,
+				 GimpPaintOptions *paint_options,
+				 guint32           time);
+
+typedef gboolean
+(* BrushModifierFinishMotion)  (GimpBrushModifierCore *modifier,
+				GimpBrushCore    *brush_core,
+				GimpDrawable     *drawable,
+				GimpPaintOptions *paint_options,
+				guint32           time);
+
+typedef gboolean
+(* BrushModifierRegisterPasteCanvas)(GimpBrushModifierCore    *modifier,
+				     GimpBrushCorePasteCanvasInfo** info,
+				     GimpBrushCore            *brush_core,
+				     GimpPaintOptions         *paint_options,
+				     GimpDrawable             *drawable,
+				     TempBuf                  *area,
+				     gdouble                   brush_opacity,
+				     gdouble                   image_opacity,
+				     GimpLayerModeEffects      paint_mode,
+				     GimpBrushApplicationMode  brush_hardness,
+				     GimpPaintApplicationMode  mode);
+
+typedef gboolean
+(* BrushModifierScaleMaskSize) (GimpBrushModifierCore *modifier,
+				GimpBrushCore    *brush_core,
+				GimpPaintOptions *paint_options,
+				gdouble           pressure);
+
+
+
+typedef struct _BrushModifierDelegator BrushModifierDelegator;
+struct _BrushModifierDelegator {
+  union {
+    BrushModifierInitMotion init_motion;
+    BrushModifierMotion     motion;
+    BrushModifierFinishMotion finish_motion;
+    BrushModifierRegisterPasteCanvas register_paste_canvas;
+    gpointer                         callback;
+  };
+  GimpBrushModifierCore  *modifier;
+  BrushModifierDelegator *next;
+};
+
+void
+brush_modifier_delegator_init   (BrushModifierDelegator *delegator);
+
+void
+brush_modifier_delegator_bind   (BrushModifierDelegator *delegator,
+				 GimpBrushModifierCore  *modifier,
+				 gpointer                callback);
+BrushModifierDelegator*
+brush_modifier_delegator_append (BrushModifierDelegator *delegators,
+				 BrushModifierDelegator *new_delegator);
+
+
+
+struct _GimpBrushModifierCore
+{
+  GimpObject   parent_instance;
+  
+  BrushModifierDelegator init_motion_delegator;
+  BrushModifierDelegator motion_delegator;
+  BrushModifierDelegator finish_motion_delegator;
+  BrushModifierDelegator register_paste_canvas_delegator;
+  BrushModifierDelegator scale_mask_size_delegator;
+};
+
+
+typedef struct _GimpCustomBrushState
+{
+  GimpRGB                   color;
+} GimpCustomBrushState;
+
+
+struct _GimpBrushModifierCoreClass
+{
+  GimpObjectClass  parent_class;
+
+  /*  virtual functions  */
+
+  /*  brushmodifier operations  */
+#if 0
+  gboolean   (* init_motion)    (GimpBrushModifierCore *modifier,
+				 GimpBrushCore    *paint_core,
+				 GimpDrawable     *drawable,
+				 GimpPaintOptions *paint_options,
+				 guint32           time);
+
+  gboolean   (* motion)         (GimpBrushModifierCore *modifier,
+				 GimpBrushCore    *brush_core,
+				 GimpDrawable     *drawable,
+				 GimpPaintOptions *paint_options,
+				 guint32           time);
+
+  gboolean   (* finish_motion)  (GimpBrushModifierCore *modifier,
+				 GimpBrushCore    *brush_core,
+				 GimpDrawable     *drawable,
+				 GimpPaintOptions *paint_options,
+				 guint32           time);
+
+  gboolean   (*register_paste_canvas)(GimpBrushModifierCore    *modifier,
+				      GimpBrushCorePasteCanvasInfo** info,
+				      GimpBrushCore            *brush_core,
+				      GimpPaintOptions         *paint_options,
+				      GimpDrawable             *drawable,
+				      TempBuf                  *area,
+				      gdouble                   brush_opacity,
+				      gdouble                   image_opacity,
+				      GimpLayerModeEffects      paint_mode,
+				      GimpBrushApplicationMode  brush_hardness,
+				      GimpPaintApplicationMode  mode);
+
+  gboolean   (* scale_mask_size)(GimpBrushModifierCore *modifier,
+				 GimpBrushCore    *brush_core,
+				 GimpPaintOptions *paint_options,
+				 gdouble           pressure);
+#endif
+  /* modifier properties  */
+  gboolean   (* get_priority)   (GimpBrushModifierCore *modifier,
+				 GimpPaintCore    *core,
+                                 GimpDrawable     *drawable);
+};
+
+
+GType     gimp_brush_modifier_core_get_type                  (void) G_GNUC_CONST;
+
+#endif
diff -uNr gimp-2.4.1/app/paint/gimpbrushmodifieroptions.c gimp-2.4.1-tmp/app/paint/gimpbrushmodifieroptions.c
--- gimp-2.4.1/app/paint/gimpbrushmodifieroptions.c	1970-01-01 09:00:00.000000000 +0900
+++ gimp-2.4.1-tmp/app/paint/gimpbrushmodifieroptions.c	2008-03-22 21:39:28.000000000 +0900
@@ -0,0 +1,188 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995-1999 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+
+#include "libgimpbase/gimpbase.h"
+#include "libgimpmath/gimpmath.h"
+#include "libgimpconfig/gimpconfig.h"
+#include "paint-types.h"
+#include "core/gimp.h"
+
+#include "gimpbrushmodifiercore.h"
+#include "gimpbrushmodifieroptions.h"
+
+
+/* static function declarations */
+
+static void   gimp_brush_modifier_options_finalize     (GObject      *object);
+
+static gboolean
+gimp_brush_modifier_options_real_install(GimpBrushModifierOptionsClass *klass,
+					 GimpPaintOptionsClass         *options_class,
+					 guint                         *base_property_id);
+
+static gboolean
+gimp_brush_modifier_options_real_set_property (GimpBrushModifierOptions *object,
+					       guint                     property_id,
+					       const GValue             *value,
+					       GParamSpec               *pspec);
+
+static gboolean
+gimp_brush_modifier_options_real_get_property (GimpBrushModifierOptions *object,
+					       guint                     property_id,
+					       GValue                   *value,
+					       GParamSpec               *pspec);
+
+static gboolean
+gimp_brush_modifier_options_real_notify       (GimpBrushModifierOptions *object,
+					       GParamSpec   *pspec);
+
+
+/*
+ * BrushModifier class definitions
+ *
+ *
+ */
+
+G_DEFINE_TYPE (GimpBrushModifierOptions, gimp_brush_modifier_options, GIMP_TYPE_OBJECT)
+
+#define parent_class gimp_brush_modifier_options_parent_class
+
+
+static void
+gimp_brush_modifier_options_class_init (GimpBrushModifierOptionsClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize     = gimp_brush_modifier_options_finalize;
+  klass->install      = gimp_brush_modifier_options_real_install;
+  klass->set_property = gimp_brush_modifier_options_real_set_property;
+  klass->get_property = gimp_brush_modifier_options_real_get_property;
+  klass->notify       = gimp_brush_modifier_options_real_notify;
+  
+  klass->base_property_id = 0;
+  klass->installed        = FALSE;
+}
+
+
+static void
+gimp_brush_modifier_options_init (GimpBrushModifierOptions *options)
+{
+  options->enabled = TRUE;
+  options->attached_to = GIMP_TYPE_BRUSH_MODIFIER_CORE;
+}
+
+
+static void
+gimp_brush_modifier_options_finalize (GObject *object)
+{
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+
+/* default method implementations */
+
+static
+gboolean gimp_brush_modifier_options_real_install(GimpBrushModifierOptionsClass *klass,
+						  GimpPaintOptionsClass         *options_class,
+						  guint                         *base_property_id)
+{
+  klass->base_property_id = *base_property_id;
+  return TRUE;
+}
+
+
+static gboolean
+gimp_brush_modifier_options_real_set_property (GimpBrushModifierOptions *options,
+					       guint         property_id,
+					       const GValue *value,
+					       GParamSpec   *pspec)
+{
+  return FALSE;
+}
+
+static gboolean
+gimp_brush_modifier_options_real_get_property (GimpBrushModifierOptions *options,
+					       guint         property_id,
+					       GValue       *value,
+					       GParamSpec   *pspec)
+{
+  return FALSE;
+}
+
+static gboolean
+gimp_brush_modifier_options_real_notify (GimpBrushModifierOptions *options,
+					 GParamSpec *pspec)
+{
+  return FALSE;
+}
+
+
+
+/* method definitions */
+
+gboolean
+gimp_brush_modifier_options_set_property (GimpBrushModifierOptions *options,
+					       guint         property_id,
+					       const GValue *value,
+					       GParamSpec   *pspec)
+{
+  return GIMP_BRUSH_MODIFIER_OPTIONS_GET_CLASS(options)->set_property(options, property_id, value, pspec);
+}
+
+gboolean
+gimp_brush_modifier_options_get_property (GimpBrushModifierOptions *options,
+					       guint         property_id,
+					       GValue       *value,
+					       GParamSpec   *pspec)
+{
+  return GIMP_BRUSH_MODIFIER_OPTIONS_GET_CLASS(options)->get_property(options, property_id, value, pspec);
+}
+
+
+gboolean
+gimp_brush_modifier_options_notify (GimpBrushModifierOptions *options,
+				    GParamSpec *pspec)
+{
+  return GIMP_BRUSH_MODIFIER_OPTIONS_GET_CLASS(options)->notify(options, pspec);
+}
+
+
+/* memory allocator */
+
+GimpBrushModifierOptions *
+gimp_brush_modifier_options_new ()
+{
+  /*
+  GimpBrushModifierOptions *options;
+
+  g_return_val_if_fail (GIMP_IS_BRUSH_MODIFIER_INFO (brush_modifier_info), NULL);
+
+  options = g_object_new (brush_modifier_info->brush_modifier_options_type,
+                          "gimp",       brush_modifier_info->gimp,
+                          "name",       GIMP_OBJECT (brush_modifier_info)->name,
+                          "brush_modifier-info", brush_modifier_info,
+                          NULL);
+
+  return options;
+  */
+  return NULL;
+}
diff -uNr gimp-2.4.1/app/paint/gimpbrushmodifieroptions.h gimp-2.4.1-tmp/app/paint/gimpbrushmodifieroptions.h
--- gimp-2.4.1/app/paint/gimpbrushmodifieroptions.h	1970-01-01 09:00:00.000000000 +0900
+++ gimp-2.4.1-tmp/app/paint/gimpbrushmodifieroptions.h	2008-03-22 21:39:28.000000000 +0900
@@ -0,0 +1,90 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995-1999 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GIMP_BRUSH_MODIFIER_OPTIONS_H__
+#define __GIMP_BRUSH_MODIFIER_OPTIONS_H__
+
+
+#include "gimppaintoptions.h"
+
+#define GIMP_TYPE_BRUSH_MODIFIER_OPTIONS            (gimp_brush_modifier_options_get_type ())
+#define GIMP_BRUSH_MODIFIER_OPTIONS(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_BRUSH_MODIFIER_OPTIONS, GimpBrushModifierOptions))
+#define GIMP_BRUSH_MODIFIER_OPTIONS_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_BRUSH_MODIFIER_OPTIONS, GimpBrushModifierOptionsClass))
+#define GIMP_IS_BRUSH_MODIFIER_OPTIONS(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_BRUSH_MODIFIER_OPTIONS))
+#define GIMP_IS_BRUSH_MODIFIER_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_BRUSH_MODIFIER_OPTIONS))
+#define GIMP_BRUSH_MODIFIER_OPTIONS_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_BRUSH_MODIFIER_OPTIONS, GimpBrushModifierOptionsClass))
+
+
+typedef struct _GimpBrushModifierOptionsClass GimpBrushModifierOptionsClass;
+typedef struct _GimpBrushModifierOptions      GimpBrushModifierOptions;
+
+
+struct _GimpBrushModifierOptions
+{
+  GimpObject   parent_instance;
+
+  GType        attached_to;
+  gboolean     enabled;
+};
+
+struct _GimpBrushModifierOptionsClass
+{
+  GimpObjectClass  parent_class;
+
+  guint        base_property_id;
+  gboolean     installed;
+  
+  /* static function */
+  gboolean (*install)     (GimpBrushModifierOptionsClass *class,
+			   GimpPaintOptionsClass         *options_class,
+			   guint                         *base_property_id);
+
+  /* instance functions */
+  gboolean (*set_property)(GimpBrushModifierOptions *options,
+			   guint                     property_id,
+			   const GValue             *value,
+			   GParamSpec               *pspec);
+
+  gboolean (*get_property)(GimpBrushModifierOptions *options,
+			   guint                     property_id,
+			   GValue                   *value,
+			   GParamSpec               *pspec);
+
+  gboolean (*notify)      (GimpBrushModifierOptions *options,
+			   GParamSpec               *pspec);
+};
+
+gboolean
+gimp_brush_modifier_options_set_property(GimpBrushModifierOptions *options,
+					 guint                     property_id,
+					 const GValue             *value,
+					 GParamSpec               *pspec);
+
+gboolean
+gimp_brush_modifier_options_get_property(GimpBrushModifierOptions *options,
+					 guint                     property_id,
+					 GValue                   *value,
+					 GParamSpec               *pspec);
+
+gboolean
+gimp_brush_modifier_options_notify      (GimpBrushModifierOptions *options,
+					 GParamSpec               *pspec);
+
+GType gimp_brush_modifier_options_get_type (void) G_GNUC_CONST;
+
+#endif  /*  __GIMP_BRUSH_MODIFIER_OPTIONS_H__  */
diff -uNr gimp-2.4.1/app/paint/gimpcustombrush.c gimp-2.4.1-tmp/app/paint/gimpcustombrush.c
--- gimp-2.4.1/app/paint/gimpcustombrush.c	1970-01-01 09:00:00.000000000 +0900
+++ gimp-2.4.1-tmp/app/paint/gimpcustombrush.c	2008-03-22 21:39:28.000000000 +0900
@@ -0,0 +1,458 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "libgimpcolor/gimpcolor.h"
+#include "libgimpmath/gimpmath.h"
+#include "libgimpbase/gimpbase.h"
+
+#include "paint-types.h"
+
+#include "base/temp-buf.h"
+
+#include "paint-funcs/paint-funcs.h"
+
+#include "core/gimp.h"
+#include "core/gimpbrush.h"
+#include "core/gimpdrawable.h"
+#include "core/gimplayer.h"
+#include "core/gimpgradient.h"
+#include "core/gimpimage.h"
+#include "core/gimppickable.h"
+#include "core/gimpprojection.h"
+#include "base/pixel-region.h"
+
+#include "gimpcustombrush.h"
+#include "gimpcustombrushoptions.h"
+
+#include "gimp-intl.h"
+
+
+/* Debug option */
+//#define GIMP_CUSTOM_BRUSH_DEBUG_MIXING
+
+
+
+
+static void    gimp_custom_brush_load      (GimpCustomBrush   *object);
+static void    gimp_custom_brush_unload    (GimpCustomBrush   *object);
+
+static void    gimp_custom_brush_finalize  (GObject           *object);
+static void    gimp_custom_brush_paint     (GimpPaintCore     *paint_core,
+					    GimpDrawable      *drawable,
+					    GimpPaintOptions  *paint_options,
+					    GimpPaintState     paint_state,
+					    guint32            time);
+
+inline
+static void    gimp_custom_brush_start     (GimpPaintCore     *paint_core,
+					    GimpDrawable      *drawable,
+					    GimpPaintOptions  *paint_options,
+					    guint32            time);
+
+inline
+static void    gimp_custom_brush_motion    (GimpPaintCore     *paint_core,
+					    GimpDrawable      *drawable,
+					    GimpPaintOptions  *paint_options,
+					    gdouble            opacity,
+					    guint32            time);
+
+inline
+static void    gimp_custom_brush_finish    (GimpPaintCore     *paint_core,
+                                           GimpDrawable      *drawable,
+                                           GimpPaintOptions  *paint_options,
+					   guint32            time);
+static gint
+custom_brush_default_pre_paint             (GimpBrushCorePasteCanvasInfo *info,
+					    GimpBrushCore                *brush_core,
+					    GimpDrawable                 *drawable);
+
+
+
+/* class definition */
+
+G_DEFINE_TYPE (GimpCustomBrush, gimp_custom_brush, GIMP_TYPE_PAINTBRUSH)
+
+#define parent_class gimp_custom_brush_parent_class
+
+
+void
+gimp_custom_brush_register (Gimp                      *gimp,
+			   GimpPaintRegisterCallback  callback)
+{
+  (* callback) (gimp,
+                GIMP_TYPE_CUSTOM_BRUSH,
+                GIMP_TYPE_CUSTOM_BRUSH_OPTIONS,
+                "gimp-custom-brush",
+                _("CustomBrush"),
+                "gimp-tool-custom-brush");
+}
+
+static void
+gimp_custom_brush_class_init (GimpCustomBrushClass *klass)
+{
+  GimpPaintCoreClass *paint_core_class = GIMP_PAINT_CORE_CLASS (klass);
+  GimpBrushCoreClass *brush_core_class = GIMP_BRUSH_CORE_CLASS (klass);
+  
+  paint_core_class->paint              = gimp_custom_brush_paint;
+  G_OBJECT_CLASS (klass)->finalize     = gimp_custom_brush_finalize;
+  
+  brush_core_class->handles_changing_brush = TRUE;
+}
+
+
+static void
+gimp_custom_brush_init (GimpCustomBrush *custom_brush)
+{
+  custom_brush->modifiers = NULL;
+  gimp_custom_brush_load(custom_brush);
+}
+
+
+static void
+gimp_custom_brush_finalize (GObject *object)
+{
+  gimp_custom_brush_unload(GIMP_CUSTOM_BRUSH(object));
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+/* load modifiers (should be dynamically loaded) */
+#include "gimpblendmodifier.h"
+#include "gimpsmoothmodifier.h"
+static void
+gimp_custom_brush_load (GimpCustomBrush *custom_brush)
+{
+  GimpBrushModifierCore* modifier;
+
+  modifier = GIMP_BRUSH_MODIFIER_CORE(gimp_blend_modifier_new());
+  custom_brush->modifiers = g_list_append(custom_brush->modifiers, (gpointer)modifier);
+
+  modifier = GIMP_BRUSH_MODIFIER_CORE(gimp_smooth_modifier_new());
+  custom_brush->modifiers = g_list_append(custom_brush->modifiers, (gpointer)modifier);
+}
+
+
+
+
+static void
+gimp_custom_brush_delete_link (gpointer data, gpointer user_data)
+{
+  g_object_unref(G_OBJECT(data));
+}
+
+
+static void
+gimp_custom_brush_unload (GimpCustomBrush *custom_brush)
+{
+  g_list_foreach(custom_brush->modifiers,
+		 gimp_custom_brush_delete_link,
+		 NULL);
+  g_list_free(custom_brush->modifiers);
+}
+
+
+
+static void
+gimp_custom_brush_paint (GimpPaintCore    *paint_core,
+                     GimpDrawable     *drawable,
+                     GimpPaintOptions *paint_options,
+                     GimpPaintState    paint_state,
+                     guint32           time)
+{
+  switch (paint_state)
+    {
+    case GIMP_PAINT_STATE_INIT:
+      gimp_custom_brush_start (paint_core, drawable, paint_options, time);
+      break;
+
+    case GIMP_PAINT_STATE_MOTION:
+      gimp_custom_brush_motion (paint_core, drawable, paint_options, GIMP_OPACITY_OPAQUE, time);
+      break;
+
+    case GIMP_PAINT_STATE_FINISH:
+      gimp_custom_brush_finish (paint_core, drawable, paint_options, time);
+      break;
+
+    default:
+      break;
+    }
+}
+
+
+void
+gimp_custom_brush_start (GimpPaintCore    *paint_core,
+			GimpDrawable     *drawable,
+			GimpPaintOptions *paint_options,
+			guint32           time)
+{
+  GimpContext              *context    = GIMP_CONTEXT (paint_options);
+  GimpImage                *image;
+  GimpCustomBrush        *custom_brush = GIMP_CUSTOM_BRUSH(paint_core);
+  GimpBrushCore          *brush_core   = GIMP_BRUSH_CORE(paint_core);
+  GList                  *modifier;
+  GList                  *first;
+  GimpCustomBrushOptions *options;
+  BrushModifierDelegator *delegator;
+  guchar col[MAX_CHANNELS];
+  TempBuf                  *area;
+
+  first          = g_list_first(custom_brush->modifiers);
+  options        = GIMP_CUSTOM_BRUSH_OPTIONS(paint_options);
+
+
+  custom_brush->init_motion_delegator           = NULL;
+  custom_brush->motion_delegator                = NULL;
+  custom_brush->finish_motion_delegator         = NULL;
+  custom_brush->register_paste_canvas_delegator = NULL;
+  
+
+  /* construct delegator list */
+  
+  for (modifier = first; modifier != NULL; modifier = g_list_next(modifier)) {
+    GimpBrushModifierCore    *modifier_core;
+    GimpBrushModifierOptions *modifier_options;
+    GType type;
+    
+    modifier_core    = GIMP_BRUSH_MODIFIER_CORE(modifier->data);
+    type             = G_OBJECT_TYPE(modifier_core);
+    modifier_options = gimp_custom_brush_options_get_options_for(options, type);
+
+    if (modifier_options && modifier_options->enabled)
+      {
+	custom_brush->init_motion_delegator =
+	  brush_modifier_delegator_append(custom_brush->init_motion_delegator,
+					  &modifier_core->init_motion_delegator);
+
+	custom_brush->motion_delegator = 
+	  brush_modifier_delegator_append(custom_brush->motion_delegator,
+					  &modifier_core->motion_delegator);
+	
+	custom_brush->finish_motion_delegator = 
+	  brush_modifier_delegator_append(custom_brush->finish_motion_delegator,
+					  &modifier_core->finish_motion_delegator);
+	
+	custom_brush->register_paste_canvas_delegator = 
+	  brush_modifier_delegator_append(custom_brush->register_paste_canvas_delegator,
+					  &modifier_core->register_paste_canvas_delegator);
+      }
+  }
+
+  /* initialize state data */
+  area = gimp_paint_core_get_paint_area (paint_core, drawable, paint_options);
+  if (! area)
+    return;
+  image = gimp_item_get_image (GIMP_ITEM (drawable));
+  gimp_image_get_foreground (image, context, gimp_drawable_type (drawable),
+			     col);
+  col[area->bytes - 1] = OPAQUE_OPACITY;
+  gimp_rgba_set_uchar(&custom_brush->state.color, col[0], col[1], col[2], col[3]);
+
+
+  /* invoke init_motion event chain */
+
+  for (delegator = custom_brush->init_motion_delegator;
+       delegator;
+       delegator = delegator->next) {
+    BrushModifierInitMotion callback;
+    callback = (BrushModifierInitMotion)delegator->callback;
+    (*callback)(delegator->modifier,
+		brush_core,
+		drawable,
+		paint_options,
+		time);
+  }
+}
+
+
+
+
+void
+gimp_custom_brush_motion (GimpPaintCore    *paint_core,
+			 GimpDrawable     *drawable,
+			 GimpPaintOptions *paint_options,
+			 gdouble           opacity,
+			 guint32           time)
+{
+  GimpCustomBrush          *custom_brush      = GIMP_CUSTOM_BRUSH(paint_core);
+  GimpContext              *context          = GIMP_CONTEXT (paint_options);
+  GimpBrushCore            *brush_core       = GIMP_BRUSH_CORE (paint_core);
+  GimpPressureOptions      *pressure_options = paint_options->pressure_options;
+  GimpImage                *image;
+  TempBuf                  *area;
+  GimpPaintApplicationMode      paint_appl_mode;
+  BrushModifierDelegator* delegator;
+  gboolean                      do_paste = TRUE;
+  GimpBrushCorePasteCanvasInfo *head_info = NULL;
+
+  
+  /* invoke motion event chain */
+  for (delegator = custom_brush->motion_delegator;
+       delegator;
+       delegator = delegator->next) {
+    BrushModifierMotion callback;
+    callback = (BrushModifierMotion)delegator->callback;
+    (*callback)(delegator->modifier,
+		brush_core,
+		drawable,
+		paint_options,
+		time);
+  }
+
+  image = gimp_item_get_image (GIMP_ITEM (drawable));
+  paint_appl_mode = paint_options->application_mode;
+
+  area = gimp_paint_core_get_paint_area (paint_core, drawable, paint_options);
+  if (! area)
+    return;
+
+  opacity *= gimp_paint_options_get_fade (paint_options, image,
+					  paint_core->pixel_dist);
+  if (opacity == 0.0)
+    return;
+
+  
+  if (pressure_options->opacity)
+    opacity *= PRESSURE_SCALE * paint_core->cur_coords.pressure;
+  
+  
+  /* execute PASTE_CANVAS event chain: construct GimpBrushCorePasteCanvasInfo chain. */
+  {
+    GimpLayerModeEffects        effect         = gimp_context_get_paint_mode(context);
+    GimpBrushApplicationMode    brush_hardness = gimp_paint_options_get_brush_mode(paint_options);
+    gdouble                     image_opacity  = gimp_context_get_opacity(context);
+
+    for (delegator = custom_brush->register_paste_canvas_delegator;
+	 delegator;
+	 delegator = delegator->next) {
+      BrushModifierRegisterPasteCanvas callback;
+      callback = (BrushModifierRegisterPasteCanvas)delegator->callback;
+      do_paste = (*callback)(delegator->modifier,
+			     &head_info,
+			     brush_core,
+			     paint_options,
+			     drawable,
+			     area,
+			     CLAMP (opacity, 0, 1.0),
+			     CLAMP (image_opacity, 0, 1.0),
+			     effect,
+			     brush_hardness,
+			     paint_appl_mode) && do_paste;
+    }
+  
+    /* finally, let the brush core paste the prepared area on the canvas */
+    if (do_paste)
+      {
+	GimpBrushCorePasteCanvasInfo brush_info;
+	if (!head_info)
+	  {
+	    /* if no modifier makes PasteCanvasInfo, then prepare default info structure. */
+	    brush_info.gimp_brush_area   = area;
+	    brush_info.brush_opacity     = CLAMP (opacity, 0, 1.0);
+	    brush_info.image_opacity     = CLAMP (image_opacity, 0, 1.0);
+	    brush_info.paint_mode        = effect;
+	    brush_info.apply             = TRUE;
+	    brush_info.brush_hardness    = brush_hardness;
+	    brush_info.post_paint        = NULL;
+	    brush_info.mode              = paint_appl_mode;
+	    
+	    brush_info.pre_paint         = custom_brush_default_pre_paint;
+	    brush_info.apply_operation   = NULL;
+	    brush_info.paint_operation   = NULL;
+	    
+	    brush_info.user_data         = NULL;
+	    brush_info.next              = NULL;
+	    head_info = &brush_info;
+	  }
+	gimp_brush_core_process_paste_canvas (GIMP_BRUSH_CORE(paint_core), drawable,
+					      head_info,
+					      paint_appl_mode);
+      }
+  }
+}
+
+
+void
+gimp_custom_brush_finish (GimpPaintCore    *paint_core,
+			 GimpDrawable     *drawable,
+			 GimpPaintOptions *paint_options,
+			 guint32           time)
+{
+
+  GimpCustomBrush *custom_brush = GIMP_CUSTOM_BRUSH(paint_core);
+  GimpBrushCore   *brush_core  = GIMP_BRUSH_CORE(paint_core);
+
+  /* invoke finish_motion event chain */
+  BrushModifierDelegator* delegator;
+
+  for (delegator = custom_brush->finish_motion_delegator;
+       delegator;
+       delegator = delegator->next) {
+    BrushModifierFinishMotion callback;
+    callback = (BrushModifierFinishMotion)delegator->callback;
+    (*callback)(delegator->modifier,
+		brush_core,
+		drawable,
+		paint_options,
+		time);
+  }
+}
+
+
+/*
+ * BrushCorePasteCanvasInfo Implementation
+ *
+ */
+static gint
+custom_brush_default_pre_paint (GimpBrushCorePasteCanvasInfo *info,
+				GimpBrushCore                *brush_core,
+				GimpDrawable                 *drawable)
+{
+  GimpCustomBrush          *custom_brush = GIMP_CUSTOM_BRUSH(brush_core);
+  //  GimpRGB                   gradient_color;
+  TempBuf                  *area = info->gimp_brush_area;
+  guchar                    col[MAX_CHANNELS];
+  GimpPaintApplicationMode  paint_appl_mode = info->mode;
+
+  /* otherwise check if the brush has a pixmap and use that to color the area */
+  if (brush_core->brush && brush_core->brush->pixmap)
+    {
+      gimp_brush_core_color_area_with_pixmap (brush_core, drawable,
+                                              area,
+                                              info->brush_hardness);
+
+      paint_appl_mode = GIMP_PAINT_INCREMENTAL;
+    }
+  /* otherwise fill the area with the foreground color */
+  else
+    {
+      gimp_rgba_get_uchar(&custom_brush->state.color,
+			  &col[0], &col[1], &col[2], &col[3]);
+
+      col[area->bytes - 1] = OPAQUE_OPACITY;
+
+      color_pixels (temp_buf_data (area), col,
+                    area->width * area->height,
+                    area->bytes);
+    }
+  return 0;
+}
diff -uNr gimp-2.4.1/app/paint/gimpcustombrush.h gimp-2.4.1-tmp/app/paint/gimpcustombrush.h
--- gimp-2.4.1/app/paint/gimpcustombrush.h	1970-01-01 09:00:00.000000000 +0900
+++ gimp-2.4.1-tmp/app/paint/gimpcustombrush.h	2008-03-22 21:39:28.000000000 +0900
@@ -0,0 +1,62 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GIMP_CUSTOM_BRUSH_H__
+#define __GIMP_CUSTOM_BRUSH_H__
+
+
+#include "gimppaintbrush.h"
+#include "gimpbrushmodifiercore.h"
+
+
+#define GIMP_TYPE_CUSTOM_BRUSH            (gimp_custom_brush_get_type ())
+#define GIMP_CUSTOM_BRUSH(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_CUSTOM_BRUSH, GimpCustomBrush))
+#define GIMP_CUSTOM_BRUSH_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_CUSTOM_BRUSH, GimpCustomBrushClass))
+#define GIMP_IS_CUSTOM_BRUSH(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_CUSTOM_BRUSH))
+#define GIMP_IS_CUSTOM_BRUSH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_CUSTOM_BRUSH))
+#define GIMP_CUSTOM_BRUSH_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_CUSTOM_BRUSH, GimpCustomBrushClass))
+
+struct _GimpCustomBrush
+{
+  GimpPaintbrush            parent_instance;
+
+  GimpDrawable             *drawable;
+  GimpPaintOptions         *paint_options;
+  GimpCustomBrushState      state;
+
+  GList                    *modifiers;
+  BrushModifierDelegator   *init_motion_delegator;
+  BrushModifierDelegator   *motion_delegator;
+  BrushModifierDelegator   *finish_motion_delegator;
+  BrushModifierDelegator   *register_paste_canvas_delegator;
+  
+};
+
+typedef struct _GimpCustomBrushClass
+{
+  GimpPaintbrushClass parent_class;
+} GimpCustomBrushClass;
+
+
+void    gimp_custom_brush_register (Gimp                      *gimp,
+				   GimpPaintRegisterCallback  callback);
+
+GType   gimp_custom_brush_get_type (void) G_GNUC_CONST;
+
+
+#endif  /*  __GIMP_CUSTOM_BRUSH_H__  */
diff -uNr gimp-2.4.1/app/paint/gimpcustombrushoptions.c gimp-2.4.1-tmp/app/paint/gimpcustombrushoptions.c
--- gimp-2.4.1/app/paint/gimpcustombrushoptions.c	1970-01-01 09:00:00.000000000 +0900
+++ gimp-2.4.1-tmp/app/paint/gimpcustombrushoptions.c	2008-03-23 04:51:29.000000000 +0900
@@ -0,0 +1,248 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+
+#include "libgimpconfig/gimpconfig.h"
+
+#include "paint-types.h"
+
+#include "gimpcustombrushoptions.h"
+
+static void
+gimp_custom_brush_options_set_property (GObject      *object,
+					guint         property_id,
+					const GValue *value,
+					GParamSpec   *pspec);
+static void
+gimp_custom_brush_options_get_property (GObject      *object,
+					guint         property_id,
+					GValue       *value,
+					GParamSpec   *pspec);
+
+/*
+ * class definition
+ *
+ *
+ */
+G_DEFINE_TYPE (GimpCustomBrushOptions, gimp_custom_brush_options,
+               GIMP_TYPE_PAINT_OPTIONS)
+
+#define parent_class gimp_custom_brush_options_parent_class
+
+
+
+static void
+gimp_custom_brush_options_register     (GimpCustomBrushOptions *options,
+					GimpBrushModifierOptions* modifier);
+     
+static void
+gimp_custom_brush_options_load         (GimpCustomBrushOptions *options);
+
+
+
+
+void
+gimp_custom_brush_options_register(GimpCustomBrushOptions   *options,
+				   GimpBrushModifierOptions *modifier)
+{
+  GimpBrushModifierOptionsClass *modifier_class;
+  GimpPaintOptionsClass         *options_class;
+  GimpCustomBrushOptionsClass   *custombrush_class;
+  
+  modifier_class = GIMP_BRUSH_MODIFIER_OPTIONS_GET_CLASS(modifier);
+  options_class  = GIMP_PAINT_OPTIONS_GET_CLASS(options);
+  custombrush_class = GIMP_CUSTOM_BRUSH_OPTIONS_GET_CLASS(options);
+
+  if (!modifier_class->installed)
+    {
+      modifier_class->install(modifier_class, options_class, &custombrush_class->base_id);
+      modifier_class->installed = TRUE;
+    }
+}
+
+
+static void
+gimp_custom_brush_options_class_init (GimpCustomBrushOptionsClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->set_property = gimp_custom_brush_options_set_property;
+  object_class->get_property = gimp_custom_brush_options_get_property;
+  g_object_class_list_properties(G_OBJECT_CLASS(klass), &klass->base_id);
+  klass->base_id ++;
+ }
+
+
+static void
+custom_brush_delete_hash (gpointer key, gpointer value, gpointer user_data)
+{
+  GObject *object = G_OBJECT(value);
+  g_object_unref(object);
+}
+
+
+static void
+gimp_custom_brush_options_init (GimpCustomBrushOptions *options)
+{
+  options->modifier_options = g_hash_table_new(g_direct_hash, g_int_equal);
+
+  g_print("[Trace]custom_brush_options::init\n");
+  
+  gimp_custom_brush_options_load(options);
+}
+
+
+static void
+gimp_custom_brush_options_finalize (GObject *object)
+{
+  GimpCustomBrushOptions *options = GIMP_CUSTOM_BRUSH_OPTIONS(object);
+  g_hash_table_foreach(options->modifier_options, custom_brush_delete_hash, NULL);
+  g_hash_table_destroy(options->modifier_options);
+}
+
+
+
+/* load modifier options (should be dynamically loaded) */
+#include "gimpblendmodifieroptions.h"
+#include "gimpsmoothmodifieroptions.h"
+void
+gimp_custom_brush_options_load(GimpCustomBrushOptions *options)
+{
+  GimpBrushModifierOptions* modifier;
+
+  modifier = GIMP_BRUSH_MODIFIER_OPTIONS(g_object_new (GIMP_TYPE_BLEND_MODIFIER_OPTIONS, NULL));
+  g_hash_table_insert(options->modifier_options, (gpointer)modifier->attached_to, modifier);
+  //  g_print("add type=%x, ptr=%x\n", (gpointer)modifier->attached_to, modifier);
+  gimp_custom_brush_options_register(options, modifier);
+
+  //  g_print("hash_size=%d\n", g_hash_table_size(options->modifier_options));
+
+  modifier = GIMP_BRUSH_MODIFIER_OPTIONS(g_object_new (GIMP_TYPE_SMOOTH_MODIFIER_OPTIONS, NULL));
+  g_hash_table_insert(options->modifier_options, (gpointer)modifier->attached_to, modifier);
+  //  g_print("add type=%x, ptr=%x\n", (gpointer)modifier->attached_to, modifier);
+
+  //  g_print("hash_size=%d\n", g_hash_table_size(options->modifier_options));
+  gimp_custom_brush_options_register(options, modifier);
+}
+
+
+static void
+gimp_custom_brush_options_set_property (GObject      *object,
+					guint         property_id,
+					const GValue *value,
+					GParamSpec   *pspec)
+{
+  GimpCustomBrushOptions *options = GIMP_CUSTOM_BRUSH_OPTIONS(object);
+#if 0
+    // GHashTableIter is introduced since 2.16 ...
+  GHashTableIter iter;
+  gpointer key, value;
+  g_hash_table_iter_init (&iter, options->modifier_options);
+  while (g_hash_table_iter_next (&iter, &key, &value))
+    {
+      GimpBrushModifierOptions *modifier_option = GIMP_BRUSH_MODIFIER_OPTIONS(value);
+      if (gimp_brush_modifier_options_set_property(modifier_option, prperty_id, value, pspec))
+	{
+	  return;
+	}
+    }
+#else
+  struct SetPropertyCallback {
+    GObject      *object;
+    guint         property_id;
+    const GValue *value;
+    GParamSpec   *pspec;
+    gboolean      result;
+  };
+  struct SetPropertyCallback args = { object, property_id, value, pspec, FALSE };
+  void custom_brush_set_property_callback(gpointer key, gpointer value, gpointer user_data) {
+    GimpBrushModifierOptions *modifier_option = GIMP_BRUSH_MODIFIER_OPTIONS(value);
+    struct SetPropertyCallback* callback_data = (struct SetPropertyCallback*)user_data;
+    callback_data->result =
+      callback_data->result ||
+      gimp_brush_modifier_options_set_property(modifier_option,
+					       callback_data->property_id,
+					       callback_data->value,
+					       callback_data->pspec);
+  }
+  g_hash_table_foreach(options->modifier_options, custom_brush_set_property_callback, &args);
+  if (args.result)
+    return;
+#endif
+  G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+gimp_custom_brush_options_get_property (GObject    *object,
+                                    guint       property_id,
+                                    GValue     *value,
+                                    GParamSpec *pspec)
+{
+  GimpCustomBrushOptions *options = GIMP_CUSTOM_BRUSH_OPTIONS(object);
+#if 0
+  // GHashTableIter is introduced since 2.16 ...
+  GHashTableIter iter;
+  gpointer key, value;
+  g_hash_table_iter_init (&iter, options->modifier_options);
+  while (g_hash_table_iter_next (&iter, &key, &value))
+    {
+      GimpBrushModifierOptions *modifier_option = GIMP_BRUSH_MODIFIER_OPTIONS(value);
+      if (gimp_brush_modifier_options_get_property(modifier_option, prperty_id, value, pspec))
+	{
+	  return;
+	}
+    }
+#else
+
+  struct GetPropertyCallback {
+    GObject    *object;
+    guint       property_id;
+    GValue     *value;
+    GParamSpec *pspec;
+    gboolean    result;
+  };
+  struct GetPropertyCallback args = { object, property_id, value, pspec, FALSE };
+  void custom_brush_get_property_callback(gpointer key, gpointer value, gpointer user_data) {
+    GimpBrushModifierOptions *modifier_option = GIMP_BRUSH_MODIFIER_OPTIONS(value);
+    struct GetPropertyCallback* callback_data = (struct GetPropertyCallback*)user_data;
+    callback_data->result =
+      callback_data->result ||
+      gimp_brush_modifier_options_get_property(modifier_option,
+					       callback_data->property_id,
+					       callback_data->value,
+					       callback_data->pspec);
+  }
+  g_hash_table_foreach(options->modifier_options, custom_brush_get_property_callback, &args);
+  if (args.result)
+    return;
+  
+#endif
+  G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+
+GimpBrushModifierOptions*
+gimp_custom_brush_options_get_options_for (GimpCustomBrushOptions *options,
+					   GType                   type)
+{
+  return GIMP_BRUSH_MODIFIER_OPTIONS(g_hash_table_lookup(options->modifier_options, (gpointer)type));
+}
+
diff -uNr gimp-2.4.1/app/paint/gimpcustombrushoptions.h gimp-2.4.1-tmp/app/paint/gimpcustombrushoptions.h
--- gimp-2.4.1/app/paint/gimpcustombrushoptions.h	1970-01-01 09:00:00.000000000 +0900
+++ gimp-2.4.1-tmp/app/paint/gimpcustombrushoptions.h	2008-03-23 04:42:48.000000000 +0900
@@ -0,0 +1,59 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GIMP_CUSTOM_BRUSH_OPTIONS_H__
+#define __GIMP_CUSTOM_BRUSH_OPTIONS_H__
+
+
+#include "gimppaintoptions.h"
+#include "gimpbrushmodifieroptions.h"
+
+
+
+#define GIMP_TYPE_CUSTOM_BRUSH_OPTIONS            (gimp_custom_brush_options_get_type ())
+#define GIMP_CUSTOM_BRUSH_OPTIONS(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_CUSTOM_BRUSH_OPTIONS, GimpCustomBrushOptions))
+#define GIMP_CUSTOM_BRUSH_OPTIONS_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_CUSTOM_BRUSH_OPTIONS, GimpCustomBrushOptionsClass))
+#define GIMP_IS_CUSTOM_BRUSH_OPTIONS(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_CUSTOM_BRUSH_OPTIONS))
+#define GIMP_IS_CUSTOM_BRUSH_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_CUSTOM_BRUSH_OPTIONS))
+#define GIMP_CUSTOM_BRUSH_OPTIONS_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_CUSTOM_BRUSH_OPTIONS, GimpCustomBrushOptionsClass))
+
+
+typedef struct _GimpCustomBrushOptionsClass GimpCustomBrushOptionsClass;
+
+struct _GimpCustomBrushOptions
+{
+  GimpPaintOptions  parent_instance;
+  GHashTable       *modifier_options;
+};
+
+struct _GimpCustomBrushOptionsClass
+{
+  GimpPaintOptionsClass  parent_class;
+  guint base_id;
+};
+
+
+GimpBrushModifierOptions*
+gimp_custom_brush_options_get_options_for (GimpCustomBrushOptions *options,
+					   GType                   type);
+
+
+GType   gimp_custom_brush_options_get_type (void) G_GNUC_CONST;
+
+
+#endif  /*  __GIMP_CUSTOM_BRUSH_OPTIONS_H__  */
diff -uNr gimp-2.4.1/app/paint/gimppaintcore.c gimp-2.4.1-tmp/app/paint/gimppaintcore.c
--- gimp-2.4.1/app/paint/gimppaintcore.c	2007-09-22 04:40:01.000000000 +0900
+++ gimp-2.4.1-tmp/app/paint/gimppaintcore.c	2008-03-22 21:39:28.000000000 +0900
@@ -873,6 +873,167 @@
                      core->canvas_buf->height);
 }
 
+
+/*
+ * Apply two or more paint mask to the canvas
+ */
+void
+gimp_paint_core_paste_mask_list (GimpPaintCore            *core,
+				 GimpDrawable             *drawable,
+				 GimpPaintMaskInfo        *info,
+				 GimpPaintApplicationMode  mode)
+{
+  GimpImage   *image;
+  TileManager *alt = NULL;
+  gint         off_x;
+  gint         off_y;
+  gboolean     canvas_valid = FALSE;
+
+  image = gimp_item_get_image (GIMP_ITEM (drawable));
+
+  gimp_item_offsets (GIMP_ITEM (drawable), &off_x, &off_y);
+
+  /*  set undo blocks  */
+  gimp_paint_core_validate_undo_tiles (core, drawable,
+                                       core->canvas_buf->x,
+                                       core->canvas_buf->y,
+                                       core->canvas_buf->width,
+                                       core->canvas_buf->height);
+
+  if (core->use_saved_proj)
+    {
+      GimpPickable *pickable = GIMP_PICKABLE (image->projection);
+
+      gimp_paint_core_validate_saved_proj_tiles (core, pickable,
+                                                 core->canvas_buf->x + off_x,
+                                                 core->canvas_buf->y + off_y,
+                                                 core->canvas_buf->width,
+                                                 core->canvas_buf->height);
+    }
+
+  while (info)
+    {
+      alt = NULL;
+      
+      /*  If the mode is CONSTANT:
+       *   combine the canvas buf, the paint mask to the canvas tiles
+       */
+      if (mode == GIMP_PAINT_CONSTANT)
+	{
+	  /* Some tools (ink) paint the mask to paint_core->canvas_tiles
+	   * directly. Don't need to copy it in this case.
+	   */
+	  if (info->paint_maskPR->tiles != core->canvas_tiles)
+	    {
+	      //	      if (!canvas_valid)
+		{
+		  /*  initialize any invalid canvas tiles  */
+		  gimp_paint_core_validate_canvas_tiles (core,
+							 core->canvas_buf->x,
+							 core->canvas_buf->y,
+							 core->canvas_buf->width,
+							 core->canvas_buf->height);
+		  canvas_valid = TRUE;
+		}
+
+	      if (info->pre_paint)
+		info->pre_paint (info, core, drawable, mode);
+
+	      if (info->paint_operation)
+		{
+		  PixelRegion srcPR;
+		  
+		  /*   combine the paint mask and the canvas tiles  */
+		  pixel_region_init (&srcPR, core->canvas_tiles,
+				     core->canvas_buf->x,
+				     core->canvas_buf->y,
+				     core->canvas_buf->width,
+				     core->canvas_buf->height,
+				     TRUE);
+		  
+		  info->paint_operation (info, core, drawable, mode, &srcPR);
+		}
+	      else
+		{
+		  paint_mask_to_canvas_tiles (core, info->paint_maskPR, info->paint_opacity);
+		}
+
+	      if (info->post_paint)
+		info->post_paint (info, core, drawable, mode);
+	    }
+
+	  canvas_tiles_to_canvas_buf (core);
+	  alt = core->undo_tiles;
+	}
+      /*  Otherwise:
+       *   combine the canvas buf and the paint mask to the canvas buf
+       */
+      else
+	{
+	  if (info->pre_paint)
+	    info->pre_paint (info, core, drawable, mode);
+
+
+	  /*  combine the canvas buf and the paint mask to the canvas buf  */
+	  if (info->paint_operation)
+	    {
+	      PixelRegion srcPR;
+	      pixel_region_init_temp_buf (&srcPR, core->canvas_buf,
+					  0, 0,
+					  core->canvas_buf->width,
+					  core->canvas_buf->height);
+	      info->paint_operation (info, core, drawable, mode, &srcPR);
+	    }
+	  else
+	    {
+	      paint_mask_to_canvas_buf (core, info->paint_maskPR, info->paint_opacity);
+	    }
+
+
+	  if (info->post_paint)
+	    info->post_paint (info, core, drawable, mode);
+	}
+
+      /*  intialize canvas buf source pixel regions  */
+      if (info->apply) {
+	PixelRegion  srcPR;
+	pixel_region_init_temp_buf (&srcPR, core->canvas_buf,
+				    0, 0,
+				    core->canvas_buf->width,
+				    core->canvas_buf->height);
+	  
+	/*  apply the paint area to the image  */
+	if (info->apply_operation)
+	  info->apply_operation(info, core, drawable, mode, &srcPR, alt);
+	else {
+	  gimp_drawable_apply_region (drawable, &srcPR,
+				      FALSE, NULL,
+				      info->image_opacity, info->paint_mode,
+				      alt,  /*  specify an alternative src1  */
+				      core->canvas_buf->x,
+				      core->canvas_buf->y);
+	}
+      }
+
+      info = info->next;
+    }
+      /*  Update the undo extents  */
+  core->x1 = MIN (core->x1, core->canvas_buf->x);
+  core->y1 = MIN (core->y1, core->canvas_buf->y);
+  core->x2 = MAX (core->x2, core->canvas_buf->x + core->canvas_buf->width);
+  core->y2 = MAX (core->y2, core->canvas_buf->y + core->canvas_buf->height);
+  
+  /*  Update the image -- It is important to call gimp_image_update()
+   *  instead of gimp_drawable_update() because we don't want the
+   *  drawable preview to be constantly invalidated
+   */
+  gimp_image_update (image,
+		     core->canvas_buf->x + off_x,
+		     core->canvas_buf->y + off_y,
+		     core->canvas_buf->width,
+		     core->canvas_buf->height);
+}
+
 /* This works similarly to gimp_paint_core_paste. However, instead of
  * combining the canvas to the paint core drawable using one of the
  * combination modes, it uses a "replace" mode (i.e. transparent
diff -uNr gimp-2.4.1/app/paint/gimppaintcore.h gimp-2.4.1-tmp/app/paint/gimppaintcore.h
--- gimp-2.4.1/app/paint/gimppaintcore.h	2007-04-25 00:12:31.000000000 +0900
+++ gimp-2.4.1-tmp/app/paint/gimppaintcore.h	2008-03-22 21:39:28.000000000 +0900
@@ -34,6 +34,41 @@
 
 typedef struct _GimpPaintCoreClass GimpPaintCoreClass;
 
+typedef struct _GimpPaintMaskInfo GimpPaintMaskInfo;
+typedef gint (*GimpPaintMaskPaintDelegator) (GimpPaintMaskInfo        *info,
+						 GimpPaintCore            *core,
+						 GimpDrawable             *drawable,
+						 GimpPaintApplicationMode  mode,
+						 PixelRegion              *srcPR);
+
+typedef gint (*GimpPaintMaskApplicationDelegator) (GimpPaintMaskInfo        *info,
+						   GimpPaintCore            *core,
+						   GimpDrawable             *drawable,
+						   GimpPaintApplicationMode  mode,
+						   PixelRegion              *srcPR,
+						   TileManager*             *undo_tiles);
+
+typedef gint (*GimpPaintMaskEventCallback) (GimpPaintMaskInfo        *info,
+					    GimpPaintCore            *core,
+					    GimpDrawable             *drawable,
+					    GimpPaintApplicationMode  mode);
+
+struct _GimpPaintMaskInfo
+{
+  PixelRegion              *paint_maskPR;
+  gdouble                   paint_opacity;
+  gdouble                   image_opacity;
+  gboolean                  apply;
+  GimpLayerModeEffects      paint_mode;
+
+  GimpPaintMaskEventCallback        pre_paint;
+  GimpPaintMaskEventCallback        post_paint;
+  GimpPaintMaskPaintDelegator       paint_operation;
+  GimpPaintMaskApplicationDelegator apply_operation;
+  void                     *delegator_data;
+  GimpPaintMaskInfo        *next;
+};
+
 struct _GimpPaintCore
 {
   GimpObject   parent_instance;
@@ -159,6 +194,10 @@
                                              gdouble                   image_opacity,
                                              GimpLayerModeEffects      paint_mode,
                                              GimpPaintApplicationMode  mode);
+void      gimp_paint_core_paste_mask_list   (GimpPaintCore            *core,
+                                             GimpDrawable             *drawable,
+					     GimpPaintMaskInfo        *info,
+                                             GimpPaintApplicationMode  mode);
 void      gimp_paint_core_replace           (GimpPaintCore            *core,
                                              PixelRegion              *paint_maskPR,
                                              GimpDrawable             *drawable,
diff -uNr gimp-2.4.1/app/paint/gimpsmoothmodifier.c gimp-2.4.1-tmp/app/paint/gimpsmoothmodifier.c
--- gimp-2.4.1/app/paint/gimpsmoothmodifier.c	1970-01-01 09:00:00.000000000 +0900
+++ gimp-2.4.1-tmp/app/paint/gimpsmoothmodifier.c	2008-03-22 21:39:28.000000000 +0900
@@ -0,0 +1,432 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "libgimpcolor/gimpcolor.h"
+#include "libgimpmath/gimpmath.h"
+#include "libgimpbase/gimpbase.h"
+
+#include "paint-types.h"
+
+#include "base/temp-buf.h"
+
+#include "paint-funcs/paint-funcs.h"
+
+#include "core/gimp.h"
+#include "core/gimpbrush.h"
+#include "core/gimpdrawable.h"
+#include "core/gimplayer.h"
+#include "core/gimpgradient.h"
+#include "core/gimpimage.h"
+#include "core/gimppickable.h"
+#include "core/gimpprojection.h"
+#include "base/pixel-region.h"
+
+#include "gimpsmoothmodifier.h"
+#include "gimpcustombrushoptions.h"
+#include "gimpsmoothmodifieroptions.h"
+
+#include "gimp-intl.h"
+
+
+
+static void     gimp_smooth_modifier_finalize     (GObject           *object);
+
+static gboolean gimp_smooth_modifier_init_motion  (GimpBrushModifierCore* core,
+						   GimpBrushCore     *brush_core,
+						   GimpDrawable      *drawable,
+						   GimpPaintOptions  *paint_options,
+						   guint32            time);
+
+static gboolean gimp_smooth_modifier_motion       (GimpBrushModifierCore* core,
+						   GimpBrushCore     *brush_core,
+						   GimpDrawable      *drawable,
+						   GimpPaintOptions  *paint_options,
+						   guint32            time);
+static gdouble PI;
+
+#define HIST_IGNORE_THRESHOULD 0.0001
+
+/*
+ * Utility functions
+ *
+ */
+
+
+/* Time and Dist smoothing functions (taken from GimpInk) */
+
+static void
+time_smoother_init (GimpSmoothModifier *modifier,
+                    guint32  initval)
+{
+  gint i;
+
+  modifier->ts_index = 0;
+
+  for (i = 0; i < GIMP_SMOOTH_MODIFIER_TIME_SMOOTHER_BUFFER; i++)
+    modifier->ts_buffer[i] = initval;
+}
+
+static guint32
+time_smoother_result (GimpSmoothModifier *modifier)
+{
+  gint    i;
+  guint64 result = 0;
+
+  for (i = 0; i < GIMP_SMOOTH_MODIFIER_TIME_SMOOTHER_BUFFER; i++)
+    result += modifier->ts_buffer[i];
+
+  return (result / (guint64) GIMP_SMOOTH_MODIFIER_TIME_SMOOTHER_BUFFER);
+}
+
+static void
+time_smoother_add (GimpSmoothModifier *modifier,
+                   guint32  value)
+{
+  guint64 long_value = (guint64) value;
+
+  /*  handle wrap-around of time values  */
+  if (long_value < modifier->ts_buffer[modifier->ts_index])
+    long_value += (guint64) + G_MAXUINT32;
+
+  modifier->ts_buffer[modifier->ts_index++] = long_value;
+
+  modifier->ts_buffer[modifier->ts_index++] = value;
+
+  if (modifier->ts_index == GIMP_SMOOTH_MODIFIER_TIME_SMOOTHER_BUFFER)
+    modifier->ts_index = 0;
+}
+
+
+static void
+dist_smoother_init (GimpSmoothModifier *modifier,
+                    gdouble  initval)
+{
+  gint i;
+
+  modifier->dt_index = 0;
+
+  for (i = 0; i < GIMP_SMOOTH_MODIFIER_DIST_SMOOTHER_BUFFER; i++)
+    modifier->dt_buffer[i] = initval;
+}
+
+static gdouble
+dist_smoother_result (GimpSmoothModifier *modifier)
+{
+  gint    i;
+  gdouble result = 0.0;
+
+  for (i = 0; i < GIMP_SMOOTH_MODIFIER_DIST_SMOOTHER_BUFFER; i++)
+    result += modifier->dt_buffer[i];
+
+  return (result / (gdouble) GIMP_SMOOTH_MODIFIER_DIST_SMOOTHER_BUFFER);
+}
+
+static void
+dist_smoother_add (GimpSmoothModifier *modifier,
+                   gdouble  value)
+{
+  modifier->dt_buffer[modifier->dt_index++] = value;
+
+  if (modifier->dt_index == GIMP_SMOOTH_MODIFIER_DIST_SMOOTHER_BUFFER)
+    modifier->dt_index = 0;
+}
+
+/* Coords history */
+/*
+ * [Memo]
+ * paint_history_* functions should be moved into GimpPaintCore in the future
+ * because G-pen patch can share the code.
+ */
+static inline void
+history_init (GimpSmoothModifier *modifier)
+{
+  modifier->hist_index = 0;
+  modifier->hist_count = 0;
+}
+
+
+static inline gint
+history_get_length (GimpSmoothModifier *modifier)
+{
+  return modifier->hist_count;
+}
+
+
+static inline void
+history_add (GimpSmoothModifier *modifier,
+	     GimpCoords    *coords,
+	     gdouble        pixel_dist)
+{
+  gdouble dist = 0;
+  
+  if (coords) {
+    if (modifier->hist_count > 0) {
+      gint prev_index = (modifier->hist_index + GIMP_SMOOTH_MODIFIER_MAX_HISTORY - 1) % GIMP_SMOOTH_MODIFIER_MAX_HISTORY;
+      gdouble dist_x = coords->x - modifier->history[prev_index].cur_coords.x;
+      gdouble dist_y = coords->y - modifier->history[prev_index].cur_coords.y;
+      
+      dist = sqrt(dist_x * dist_x + dist_y * dist_y);
+      
+      if (dist < HIST_IGNORE_THRESHOULD)
+        return;
+    }
+    modifier->history[modifier->hist_index].cur_coords = *coords;
+    modifier->history[modifier->hist_index].pixel_dist = pixel_dist;
+    modifier->hist_index ++;
+    
+    if (modifier->hist_count < GIMP_SMOOTH_MODIFIER_MAX_HISTORY)
+      modifier->hist_count ++;
+    
+    if (modifier->hist_index == GIMP_SMOOTH_MODIFIER_MAX_HISTORY)
+      modifier->hist_index = 0;
+  }
+}
+
+
+static GimpCoords
+history_result(GimpSmoothModifier *modifier,
+	    guint               history_size,
+	    gdouble             rate)
+{
+  gint i;
+  GimpCoords result;
+  gdouble scale_sum = 0.0;
+  result.x = result.y = 0.0;
+  if (modifier->hist_count > 0) {
+    gint max_hist_count = MIN(modifier->hist_count , history_size);
+    gint cur_index = (modifier->hist_index + GIMP_SMOOTH_MODIFIER_MAX_HISTORY - 1) % GIMP_SMOOTH_MODIFIER_MAX_HISTORY; 
+
+    gdouble gaussian_weight = 0.0;
+    gdouble gaussian_weight2;
+    gdouble dist_sum = 0.0;
+
+    gdouble base_rate = 0.0;
+
+    gaussian_weight2 = rate * rate;
+    
+    if (gaussian_weight2 != 0.0)
+      gaussian_weight = 1 / (sqrt(2 * PI) * rate);
+
+    for (i = 0; i < max_hist_count; i ++, cur_index --) 
+      {
+        gdouble rate = 0;
+        if (cur_index == -1)
+          cur_index = GIMP_SMOOTH_MODIFIER_MAX_HISTORY - 1;
+  
+        if (gaussian_weight2 != 0) 
+          {
+            /* We use gaussian function with velocity as a window function */
+            dist_sum += modifier->history[cur_index].pixel_dist;
+            rate = gaussian_weight * exp(-dist_sum*dist_sum / (2*gaussian_weight2));
+            /* If i == 0 && rate == 0.0, resulting value becomes zero.
+             * To avoid this, we treat this as a special case.
+             */
+            if (i == 0 && rate == 0.0)
+              rate = 1.0;
+#if 0
+	    //Debug
+	    if (base_rate == 0.0)
+	      base_rate = rate;
+	    g_print("%d:(x %3.5f)", i, base_rate > 0 ? rate / base_rate : 0);
+#endif
+          }
+        else
+          {
+            rate = (i == 0) ? 1.0: 0.0;
+          }
+        scale_sum += rate;
+        result.x += rate * modifier->history[cur_index].cur_coords.x;
+        result.y += rate * modifier->history[cur_index].cur_coords.y;
+      }
+#if 0
+    g_print("\n");
+#endif
+
+    if (scale_sum != 0.0)
+      {
+        result.x /= scale_sum;
+        result.y /= scale_sum;
+      }
+  }
+  return result;
+}
+
+
+
+
+/*
+ * GimpCustombrush class implementation
+ *
+ *
+ */
+
+
+G_DEFINE_TYPE (GimpSmoothModifier, gimp_smooth_modifier, GIMP_TYPE_BRUSH_MODIFIER_CORE)
+
+#define parent_class gimp_smooth_modifier_parent_class
+
+
+static void
+gimp_smooth_modifier_class_init (GimpSmoothModifierClass *klass)
+{
+  G_OBJECT_CLASS (klass)->finalize                 = gimp_smooth_modifier_finalize;
+
+  PI = 4 * atan(1);
+}
+
+static void
+gimp_smooth_modifier_init (GimpSmoothModifier *smooth_modifier)
+{
+  GimpBrushModifierCore* modifier;
+  modifier = GIMP_BRUSH_MODIFIER_CORE(smooth_modifier);
+  
+  g_print("smooth_modifier::init\n");
+  brush_modifier_delegator_bind(&modifier->init_motion_delegator, modifier, gimp_smooth_modifier_init_motion);
+  brush_modifier_delegator_bind(&modifier->motion_delegator, modifier, gimp_smooth_modifier_motion);
+}
+
+
+static void
+gimp_smooth_modifier_finalize (GObject *object)
+{
+  g_print("smooth_modifier::finalize\n");
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+
+
+GimpSmoothModifier* gimp_smooth_modifier_new(void)
+{
+  GimpSmoothModifier* result = (GimpSmoothModifier*)g_object_new(GIMP_TYPE_SMOOTH_MODIFIER, NULL);
+  g_assert( result != NULL );
+  return result;
+}
+
+
+
+
+static gboolean
+gimp_smooth_modifier_init_motion (GimpBrushModifierCore* modifier,
+				 GimpBrushCore    *brush_core,
+				 GimpDrawable     *drawable,
+				 GimpPaintOptions *paint_options,
+				 guint32           time)
+{
+  GimpSmoothModifier *smooth_modifier = GIMP_SMOOTH_MODIFIER (modifier);
+  GimpPaintCore      *paint_core      = GIMP_PAINT_CORE (brush_core);
+  history_init (smooth_modifier);
+  time_smoother_init (smooth_modifier, 0);
+
+  history_add  (smooth_modifier, &paint_core->cur_coords, 0);
+  time_smoother_add(smooth_modifier, time);
+  dist_smoother_init (smooth_modifier, 0.0);
+  smooth_modifier->last_time = time;
+
+  return TRUE;
+}
+
+
+static gboolean
+gimp_smooth_modifier_motion (GimpBrushModifierCore* modifier,
+			     GimpBrushCore    *brush_core,
+			     GimpDrawable     *drawable,
+			     GimpPaintOptions *paint_options,
+			     guint32           time)
+{
+  GimpSmoothModifier        *smooth_modifier     = GIMP_SMOOTH_MODIFIER(modifier);
+  GimpCustomBrushOptions    *custom_brush_options = GIMP_CUSTOM_BRUSH_OPTIONS(paint_options);
+  GimpPaintCore             *paint_core = GIMP_PAINT_CORE(brush_core);
+  GimpSmoothModifierOptions *options;
+
+  gdouble    dist;
+  //  gdouble    velocity;
+  guint32    lasttime = smooth_modifier->last_time;
+  guint32    thistime;
+  GimpCoords average_hist;
+  //  GimpCoords average_velocity;
+
+  options = GIMP_SMOOTH_MODIFIER_OPTIONS(gimp_custom_brush_options_get_options_for(custom_brush_options, G_OBJECT_TYPE(modifier)));
+
+  time_smoother_add (smooth_modifier, time);
+  thistime = smooth_modifier->last_time = time_smoother_result (smooth_modifier);
+  
+  /* The time resolution on X-based GDK motion events is bloody
+   * awful, hence the use of the smoothing function.  Sadly this
+   * also means that there is always the chance of having an
+   * indeterminite velocity since this event and the previous
+   * several may still appear to issue at the same
+   * instant. -ADM
+   */
+  if (thistime == lasttime)
+    thistime = lasttime + 1;
+  
+  dist = sqrt ((paint_core->last_coords.x - paint_core->cur_coords.x) *
+	       (paint_core->last_coords.x - paint_core->cur_coords.x) +
+	       (paint_core->last_coords.y - paint_core->cur_coords.y) *
+	       (paint_core->last_coords.y - paint_core->cur_coords.y));
+  
+  if (smooth_modifier->init_velocity)
+    {
+      dist_smoother_init (smooth_modifier, dist);
+      smooth_modifier->init_velocity = FALSE;
+    }
+  else
+    {
+      dist_smoother_add (smooth_modifier, dist);
+      dist = dist_smoother_result (smooth_modifier);
+    }
+
+  //  velocity = 10.0 * sqrt ((dist) / (gdouble) (thistime - lasttime));
+  
+  if (options->smoothing_hist_size > 1) 
+    {
+      history_add(smooth_modifier, &paint_core->cur_coords,
+		  options->distance_scale > 0 ? dist / options->distance_scale : 0.0);
+      average_hist = history_result(smooth_modifier, options->smoothing_hist_size, options->smoothing_rate);
+      paint_core->cur_coords.x = average_hist.x;
+      paint_core->cur_coords.y = average_hist.y;
+    }
+#if 0
+  {
+    gint a;
+    gdouble weight = 0;
+    gdouble dist = 0;
+    for (a = smooth_modifier->hist_count - 1; a >= 0; a --) {
+      gint index = smooth_modifier->hist_index + a;
+      while (index >= 20)
+	index -= 20;
+      GimpCoords* coords = &smooth_modifier->history[index].cur_coords;
+      dist += smooth_modifier->history[index].pixel_dist;
+      if (weight == 0)
+	weight = dist;
+      //      g_print(" %d: %f, %f, %f(x %3.5f)\n", a, coords->x, coords->y, dist, weight > 0 ? dist / weight : 0);
+      g_print("%d:(x %3.5f)", a, weight > 0 ? dist / weight : 0);
+    }
+    g_print("\n");
+  }
+
+  g_print(" -> %f, %f\n", paint_core->cur_coords.x, paint_core->cur_coords.y);
+#endif
+  return TRUE;
+}
diff -uNr gimp-2.4.1/app/paint/gimpsmoothmodifier.h gimp-2.4.1-tmp/app/paint/gimpsmoothmodifier.h
--- gimp-2.4.1/app/paint/gimpsmoothmodifier.h	1970-01-01 09:00:00.000000000 +0900
+++ gimp-2.4.1-tmp/app/paint/gimpsmoothmodifier.h	2008-03-22 21:39:28.000000000 +0900
@@ -0,0 +1,78 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GIMP_SMOOTH_MODIFIER_H__
+#define __GIMP_SMOOTH_MODIFIER_H__
+
+
+#include "gimpbrushmodifiercore.h"
+
+
+#define GIMP_TYPE_SMOOTH_MODIFIER         (gimp_smooth_modifier_get_type ())
+#define GIMP_SMOOTH_MODIFIER(obj)         (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_SMOOTH_MODIFIER, GimpSmoothModifier))
+#define GIMP_SMOOTH_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_SMOOTH_MODIFIER, GimpSmoothModifierClass))
+#define GIMP_IS_SMOOTH_MODIFIER(obj)      (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_SMOOTH_MODIFIER))
+#define GIMP_IS_SMOOTH_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_SMOOTH_MODIFIER))
+#define GIMP_SMOOTH_MODIFIER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_SMOOTH_MODIFIER, GimpSmoothModifierClass))
+
+
+typedef struct _GimpSmoothModifierCoordsHistory
+{
+  GimpCoords cur_coords;
+  gdouble    pixel_dist;
+} GimpSmoothModifierCoordsHistory;
+
+typedef struct _GimpSmoothModifier GimpSmoothModifier;
+typedef struct _GimpSmoothModifierClass GimpSmoothModifierClass;
+
+
+#define GIMP_SMOOTH_MODIFIER_DIST_SMOOTHER_BUFFER 10
+#define GIMP_SMOOTH_MODIFIER_TIME_SMOOTHER_BUFFER 10
+
+#define GIMP_SMOOTH_MODIFIER_MAX_HISTORY 20
+struct _GimpSmoothModifier
+{
+  GimpBrushModifierCore           parent_instance;
+
+  guint32                         last_time;
+  gdouble                         init_velocity;
+
+  guint32                         ts_buffer[GIMP_SMOOTH_MODIFIER_TIME_SMOOTHER_BUFFER];
+  gint                            ts_index;
+
+  /* circular distance history buffer */
+  gdouble                         dt_buffer[GIMP_SMOOTH_MODIFIER_DIST_SMOOTHER_BUFFER];
+  gint                            dt_index;
+
+  /* circular history buffer */
+  GimpSmoothModifierCoordsHistory history[GIMP_SMOOTH_MODIFIER_MAX_HISTORY + 1];
+  gint                            hist_count;
+  gint                            hist_index;
+};
+
+struct _GimpSmoothModifierClass
+{
+  GimpBrushModifierCoreClass  parent_class;
+};
+
+
+GType     gimp_smooth_modifier_get_type                  (void) G_GNUC_CONST;
+GimpSmoothModifier* gimp_smooth_modifier_new(void);
+
+
+#endif
diff -uNr gimp-2.4.1/app/paint/gimpsmoothmodifieroptions.c gimp-2.4.1-tmp/app/paint/gimpsmoothmodifieroptions.c
--- gimp-2.4.1/app/paint/gimpsmoothmodifieroptions.c	1970-01-01 09:00:00.000000000 +0900
+++ gimp-2.4.1-tmp/app/paint/gimpsmoothmodifieroptions.c	2008-03-23 04:55:27.000000000 +0900
@@ -0,0 +1,200 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+
+#include "libgimpconfig/gimpconfig.h"
+#include "paint-types.h"
+#include "core/gimp.h"
+
+#include "gimpsmoothmodifier.h"
+#include "gimpsmoothmodifieroptions.h"
+
+
+static gboolean
+gimp_smooth_modifier_options_install     (GimpBrushModifierOptionsClass *klass,
+					 GimpPaintOptionsClass         *options_class,
+					 guint                         *base_property_id);
+
+
+
+static gboolean
+gimp_smooth_modifier_options_set_property (GimpBrushModifierOptions *object,
+					  guint                     property_id,
+					  const GValue             *value,
+					  GParamSpec               *pspec);
+static gboolean
+gimp_smooth_modifier_options_get_property (GimpBrushModifierOptions *object,
+					  guint                     property_id,
+					  GValue                   *value,
+					  GParamSpec               *pspec);
+
+
+enum
+{
+  PROP_ENABLED,
+  PROP_COMPENSATION_HIST_SIZE,
+  PROP_DISTANCE_SCALE,
+  PROP_COMPENSATION_RATE
+};
+
+G_DEFINE_TYPE (GimpSmoothModifierOptions, gimp_smooth_modifier_options,
+               GIMP_TYPE_BRUSH_MODIFIER_OPTIONS)
+
+#define parent_class gimp_smooth_modifier_options_parent_class
+
+
+static void
+gimp_smooth_modifier_options_class_init (GimpSmoothModifierOptionsClass *klass)
+{
+  GimpBrushModifierOptionsClass *modifier_class = GIMP_BRUSH_MODIFIER_OPTIONS_CLASS (klass);
+
+  modifier_class->base_property_id = 0;
+
+  modifier_class->install      = gimp_smooth_modifier_options_install;
+  modifier_class->set_property = gimp_smooth_modifier_options_set_property;
+  modifier_class->get_property = gimp_smooth_modifier_options_get_property;
+}
+
+static void
+gimp_smooth_modifier_options_init (GimpSmoothModifierOptions *options)
+{
+  GimpBrushModifierOptions *modifier_options = GIMP_BRUSH_MODIFIER_OPTIONS(options);
+  g_print("[Trace]smooth_modifier_options::init\n");
+  modifier_options->attached_to = GIMP_TYPE_SMOOTH_MODIFIER;
+}
+
+
+static gboolean
+gimp_smooth_modifier_options_install(GimpBrushModifierOptionsClass *klass,
+				    GimpPaintOptionsClass         *options_class,
+				    guint                         *base_property_id)
+{
+  GObjectClass* object_class = G_OBJECT_CLASS(options_class);
+  guint         n_properties = 0;
+  klass->base_property_id = *base_property_id;
+  
+
+  g_print("[Trace]smooth_modifier_options::install[%x]\n", *base_property_id);
+
+  /* enabled parameter should be handled automatically, but not yet implemented */
+  GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_ENABLED + *base_property_id,
+                                    "smooth-enabled", NULL,
+                                    TRUE,
+                                    GIMP_PARAM_STATIC_STRINGS);
+  n_properties ++;
+
+  GIMP_CONFIG_INSTALL_PROP_INT    (object_class, PROP_COMPENSATION_HIST_SIZE + *base_property_id,
+                                   "smoothing-history-size", NULL,
+                                   1, 20, 20, 0);
+  n_properties ++;
+  
+  GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_DISTANCE_SCALE + *base_property_id,
+                                   "distance-scale", NULL,
+                                   0.0, 200, 25,
+                                   0);
+  n_properties ++;
+
+  GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_COMPENSATION_RATE + *base_property_id,
+                                   "smoothing-rate", NULL,
+                                   0.0, 10, 1,
+                                   0);
+  n_properties ++;
+
+  *base_property_id += n_properties;
+
+  return TRUE;
+}
+
+
+static gboolean
+gimp_smooth_modifier_options_set_property (GimpBrushModifierOptions *object,
+					  guint                     property_id,
+					  const GValue             *value,
+					  GParamSpec               *pspec)
+{
+  GimpSmoothModifierOptions *options = GIMP_SMOOTH_MODIFIER_OPTIONS (object);
+
+  g_print("[Trace]smooth_modifier_options::set_property[%x-%x]\n",
+	  property_id,
+	  GIMP_BRUSH_MODIFIER_OPTIONS_GET_CLASS(object)->base_property_id);
+
+  switch (property_id - GIMP_BRUSH_MODIFIER_OPTIONS_GET_CLASS(object)->base_property_id)
+    {
+    case PROP_ENABLED:
+      GIMP_BRUSH_MODIFIER_OPTIONS(options)->enabled = g_value_get_boolean (value);
+      g_print("[Trace]->PROP_ENABLED\n");
+      break;
+      
+    case PROP_COMPENSATION_HIST_SIZE:
+      options->smoothing_hist_size = g_value_get_int (value);
+      break;
+
+    case PROP_DISTANCE_SCALE:
+      options->distance_scale = g_value_get_double (value);
+      break;
+
+    case PROP_COMPENSATION_RATE:
+      options->smoothing_rate = g_value_get_double (value);
+      break;
+    default:
+      return FALSE;
+      break;
+    }
+  return TRUE;
+}
+
+static gboolean
+gimp_smooth_modifier_options_get_property (GimpBrushModifierOptions *object,
+					  guint                     property_id,
+					  GValue                   *value,
+					  GParamSpec               *pspec)
+{
+  GimpSmoothModifierOptions *options = GIMP_SMOOTH_MODIFIER_OPTIONS (object);
+
+  g_print("[Trace]smooth_modifier_options::get_property[%x-%x]\n",
+	  property_id,
+	  GIMP_BRUSH_MODIFIER_OPTIONS_GET_CLASS(object)->base_property_id);
+
+  switch (property_id - GIMP_BRUSH_MODIFIER_OPTIONS_GET_CLASS(object)->base_property_id)
+    {
+    case PROP_ENABLED:
+      g_value_set_boolean(value, GIMP_BRUSH_MODIFIER_OPTIONS(options)->enabled);
+      g_print("[Trace]->PROP_ENABLED\n");
+      break;
+      
+    case PROP_COMPENSATION_HIST_SIZE:
+      g_value_set_int (value, options->smoothing_hist_size);
+      break;
+
+    case PROP_DISTANCE_SCALE:
+      g_value_set_double (value, options->distance_scale);
+      break;
+
+    case PROP_COMPENSATION_RATE:
+      g_value_set_double (value, options->smoothing_rate);
+      break;
+
+    default:
+      return FALSE;
+      break;
+    }
+  return TRUE;
+}
diff -uNr gimp-2.4.1/app/paint/gimpsmoothmodifieroptions.h gimp-2.4.1-tmp/app/paint/gimpsmoothmodifieroptions.h
--- gimp-2.4.1/app/paint/gimpsmoothmodifieroptions.h	1970-01-01 09:00:00.000000000 +0900
+++ gimp-2.4.1-tmp/app/paint/gimpsmoothmodifieroptions.h	2008-03-22 21:39:28.000000000 +0900
@@ -0,0 +1,56 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995-1999 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GIMP_SMOOTH_MODIFIER_OPTIONS_H__
+#define __GIMP_SMOOTH_MODIFIER_OPTIONS_H__
+
+
+#include "gimpbrushmodifieroptions.h"
+
+
+/* class */
+
+#define GIMP_TYPE_SMOOTH_MODIFIER_OPTIONS            (gimp_smooth_modifier_options_get_type ())
+#define GIMP_SMOOTH_MODIFIER_OPTIONS(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_SMOOTH_MODIFIER_OPTIONS, GimpSmoothModifierOptions))
+#define GIMP_SMOOTH_MODIFIER_OPTIONS_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_SMOOTH_MODIFIER_OPTIONS, GimpSmoothModifierOptionsClass))
+#define GIMP_IS_SMOOTH_MODIFIER_OPTIONS(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_SMOOTH_MODIFIER_OPTIONS))
+#define GIMP_IS_SMOOTH_MODIFIER_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_SMOOTH_MODIFIER_OPTIONS))
+#define GIMP_SMOOTH_MODIFIER_OPTIONS_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_SMOOTH_MODIFIER_OPTIONS, GimpSmoothModifierOptionsClass))
+
+
+typedef struct _GimpSmoothModifierOptionsClass GimpSmoothModifierOptionsClass;
+typedef struct _GimpSmoothModifierOptions      GimpSmoothModifierOptions;
+
+
+struct _GimpSmoothModifierOptions
+{
+  GimpBrushModifierOptions parent_instance;
+
+  guint                    smoothing_hist_size;
+  gdouble                  distance_scale;
+  gdouble                  smoothing_rate;
+};
+
+struct _GimpSmoothModifierOptionsClass
+{
+  GimpBrushModifierOptionsClass  parent_class;
+};
+
+GType gimp_smooth_modifier_options_get_type (void) G_GNUC_CONST;
+
+#endif  /*  __GIMP_SMOOTH_MODIFIER_OPTIONS_H__  */
diff -uNr gimp-2.4.1/app/paint/paint-types.h gimp-2.4.1-tmp/app/paint/paint-types.h
--- gimp-2.4.1/app/paint/paint-types.h	2007-03-08 18:53:41.000000000 +0900
+++ gimp-2.4.1-tmp/app/paint/paint-types.h	2008-03-22 21:39:28.000000000 +0900
@@ -41,6 +41,7 @@
 typedef struct _GimpPencil           GimpPencil;
 typedef struct _GimpPerspectiveClone GimpPerspectiveClone;
 typedef struct _GimpSmudge           GimpSmudge;
+typedef struct _GimpCustomBrush      GimpCustomBrush;
 
 
 /*  paint options  */
@@ -57,6 +58,7 @@
 typedef struct _GimpPencilOptions           GimpPencilOptions;
 typedef struct _GimpPerspectiveCloneOptions GimpPerspectiveCloneOptions;
 typedef struct _GimpSmudgeOptions           GimpSmudgeOptions;
+typedef struct _GimpCustomBrushOptions      GimpCustomBrushOptions;
 
 
 /*  paint undos  */
diff -uNr gimp-2.4.1/app/paint-funcs/paint-funcs-generic.h gimp-2.4.1-tmp/app/paint-funcs/paint-funcs-generic.h
--- gimp-2.4.1/app/paint-funcs/paint-funcs-generic.h	2007-01-23 19:13:51.000000000 +0900
+++ gimp-2.4.1-tmp/app/paint-funcs/paint-funcs-generic.h	2008-03-22 21:39:28.000000000 +0900
@@ -348,10 +348,64 @@
               const guchar *col,
               guchar        blend,
               guint         w,
-              guint         bytes,
-              gboolean      has_alpha)
-{
+	      guint         bytes)
+	      //              guint         bytes,
+	      //              gboolean      has_alpha)
+{
+  if (HAS_ALPHA (bytes))
+    {
+      const guint blend1 = 255 - blend;
+      const guint blend2 = blend + 1;
+      const guint c      = bytes - 1;
+      const gint  a2 = blend2 * col[c];
+      gint  cola[MAX_CHANNELS];
+      guint       b;
+	  
+      for (b = 0; b < c; b++)
+	cola[b] = col[b] * a2;
+
+      while (w--)
+        {
+          const gint  a1 = blend1 * src[c];
+          const gint  a  = a1 + a2;
+
+          if (!a)
+            {
+              for (b = 0; b < bytes; b++)
+                dest[b] = 0;
+            }
+          else
+            {
+              for (b = 0; b < c; b++)
+                dest[b] =
+                  src[b] + (src[b] * a1 + cola[b] - a * src[b]) / a;
+
+              dest[c] = a >> 8;
+            }
+
+          src += bytes;
+          dest += bytes;
+        }
+    }
+  else
+    {
+      const guchar blend1 = 255 - blend;
+
+      while (w--)
+        {
+          guint b;
+
+          for (b = 0; b < bytes; b++)
+            dest[b] =
+              src[b] + (src[b] * blend1 + col[b] * blend - src[b] * 255) / 255;
+
+          src += bytes;
+          dest += bytes;
+        }
+    }
+#if 0
   const guchar blend2 = (255 - blend);
+  const guint  has_alpha = HAS_ALPHA(bytes);
   const guint  alpha = (has_alpha) ? bytes - 1 : bytes;
 
   while (w--)
@@ -367,6 +421,7 @@
       src += bytes;
       dest += bytes;
     }
+#endif
 }
 
 
diff -uNr gimp-2.4.1/app/paint-funcs/paint-funcs.c gimp-2.4.1-tmp/app/paint-funcs/paint-funcs.c
--- gimp-2.4.1/app/paint-funcs/paint-funcs.c	2007-10-23 04:16:17.000000000 +0900
+++ gimp-2.4.1-tmp/app/paint-funcs/paint-funcs.c	2008-03-22 21:39:28.000000000 +0900
@@ -1975,20 +1975,28 @@
               guchar      *color,
               guchar       blend)
 {
-  const guchar *s = src->data;
-  guchar       *d = dest->data;
-  gint          h = src->h;
+  gpointer pr;
 
-  while (h --)
+  for (pr = pixel_regions_register (2, src, dest);
+       pr != NULL;
+       pr = pixel_regions_process (pr))
     {
-      blend_pixels (s, d, color, blend, src->w, src->bytes);
+      const guchar *s = src->data;
+      guchar       *d  = dest->data;
+      gint          h  = src->h;
 
-      s += src->rowstride;
-      d += dest->rowstride;
+      while (h --)
+        {
+          shade_pixels (s, d, color, blend, src->w, src->bytes);
+
+          s += src->rowstride;
+          d += dest->rowstride;
+        }
     }
 }
 
 
+
 void
 copy_region (PixelRegion *src,
              PixelRegion *dest)
diff -uNr gimp-2.4.1/app/paint-funcs/paint-funcs.h gimp-2.4.1-tmp/app/paint-funcs/paint-funcs.h
--- gimp-2.4.1/app/paint-funcs/paint-funcs.h	2007-10-23 04:16:17.000000000 +0900
+++ gimp-2.4.1-tmp/app/paint-funcs/paint-funcs.h	2008-03-22 21:39:28.000000000 +0900
@@ -58,8 +58,9 @@
                              const guchar *color,
                              guchar        rblend,
                              guint         w,
-                             guint         bytes,
-                             gboolean      has_alpha);
+			     guint         bytes);
+			     //                             guint         bytes,
+			     //                             gboolean      has_alpha);
 
 void  extract_alpha_pixels  (const guchar *src,
                              const guchar *mask,
diff -uNr gimp-2.4.1/app/tools/Makefile.am gimp-2.4.1-tmp/app/tools/Makefile.am
--- gimp-2.4.1/app/tools/Makefile.am	2007-06-27 18:50:25.000000000 +0900
+++ gimp-2.4.1-tmp/app/tools/Makefile.am	2008-03-22 21:39:28.000000000 +0900
@@ -167,7 +167,9 @@
 	gimpvectoroptions.c		\
 	gimpvectoroptions.h		\
 	gimpvectortool.c		\
-	gimpvectortool.h
+	gimpvectortool.h		\
+	gimpcustombrushtool.c		\
+	gimpcustombrushtool.h
 
 libapptools_a_built_sources = tools-enums.c
 
diff -uNr gimp-2.4.1/app/tools/Makefile.in gimp-2.4.1-tmp/app/tools/Makefile.in
--- gimp-2.4.1/app/tools/Makefile.in	2007-10-31 17:09:08.000000000 +0900
+++ gimp-2.4.1-tmp/app/tools/Makefile.in	2008-03-22 21:39:28.000000000 +0900
@@ -100,7 +100,11 @@
 	gimptoolcontrol.$(OBJEXT) gimptooloptions-gui.$(OBJEXT) \
 	gimptransformoptions.$(OBJEXT) gimptransformtool.$(OBJEXT) \
 	gimptransformtoolundo.$(OBJEXT) gimpvectoroptions.$(OBJEXT) \
-	gimpvectortool.$(OBJEXT)
+	gimpvectortool.$(OBJEXT) \
+	gimpbrushmodifiertool.$(OBJEXT) \
+	gimpblendmodifiertool.$(OBJEXT) \
+	gimpsmoothmodifiertool.$(OBJEXT) \
+	gimpcustombrushtool.$(OBJEXT)
 am_libapptools_a_OBJECTS = $(am__objects_1) $(am__objects_2)
 libapptools_a_OBJECTS = $(am_libapptools_a_OBJECTS)
 DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
@@ -655,7 +659,15 @@
 	gimpvectoroptions.c		\
 	gimpvectoroptions.h		\
 	gimpvectortool.c		\
-	gimpvectortool.h
+	gimpvectortool.h		\
+	gimpbrushmodifiertool.c		\
+	gimpbrushmodifiertool.h		\
+	gimpblendmodifiertool.c		\
+	gimpblendmodifiertool.h		\
+	gimpsmoothmodifiertool.c	\
+	gimpsmoothmodifiertool.h	\
+	gimpcustombrushtool.c		\
+	gimpcustombrushtool.h
 
 libapptools_a_built_sources = tools-enums.c
 libapptools_a_SOURCES = $(libapptools_a_built_sources) $(libapptools_a_sources)
@@ -807,6 +819,7 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tool_manager.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tools-enums.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tools-utils.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpcustombrushtool.Po@am__quote@
 
 .c.o:
 @am__fastdepCC_TRUE@	if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
diff -uNr gimp-2.4.1/app/tools/gimp-tools.c gimp-2.4.1-tmp/app/tools/gimp-tools.c
--- gimp-2.4.1/app/tools/gimp-tools.c	2007-07-25 03:45:41.000000000 +0900
+++ gimp-2.4.1-tmp/app/tools/gimp-tools.c	2008-03-22 21:39:28.000000000 +0900
@@ -77,6 +77,7 @@
 #include "gimpsmudgetool.h"
 #include "gimptexttool.h"
 #include "gimpvectortool.h"
+#include "gimpcustombrushtool.h"
 
 #include "gimp-intl.h"
 
@@ -138,6 +139,7 @@
     gimp_blend_tool_register,
     gimp_bucket_fill_tool_register,
     gimp_text_tool_register,
+    gimp_custom_brush_tool_register,
 
     /*  transform tools  */
 
@@ -177,6 +179,8 @@
 
   g_return_if_fail (GIMP_IS_GIMP (gimp));
 
+  g_print("[Trace]:gimp_tool_init\n");
+
   tool_manager_init (gimp);
 
   gimp_container_freeze (gimp->tool_info_list);
@@ -426,7 +430,7 @@
   GimpToolInfo *tool_info;
   const gchar  *paint_core_name;
   gboolean      visible;
-
+  
   g_return_if_fail (GIMP_IS_GIMP (gimp));
   g_return_if_fail (g_type_is_a (tool_type, GIMP_TYPE_TOOL));
   g_return_if_fail (tool_options_type == G_TYPE_NONE ||
@@ -479,6 +483,10 @@
     {
       paint_core_name = "gimp-ink";
     }
+  else if (tool_type == GIMP_TYPE_CUSTOM_BRUSH_TOOL)
+    {
+      paint_core_name = "gimp-custom-brush";
+    }
   else
     {
       paint_core_name = "gimp-paintbrush";
diff -uNr gimp-2.4.1/app/tools/gimpblendmodifiertool.c gimp-2.4.1-tmp/app/tools/gimpblendmodifiertool.c
--- gimp-2.4.1/app/tools/gimpblendmodifiertool.c	1970-01-01 09:00:00.000000000 +0900
+++ gimp-2.4.1-tmp/app/tools/gimpblendmodifiertool.c	2008-03-22 21:39:28.000000000 +0900
@@ -0,0 +1,158 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "tools-types.h"
+
+#include "paint/gimpcustombrushoptions.h"
+
+#include "widgets/gimphelp-ids.h"
+
+#include "gimpblendmodifiertool.h"
+#include "gimppaintoptions-gui.h"
+#include "gimptoolcontrol.h"
+
+#include "gimp-intl.h"
+
+
+static void
+gimp_blend_modifier_options_gui (GimpBrushModifierTool *tool,
+				 GObject               *config,
+				 GtkContainer          *container);
+
+
+G_DEFINE_TYPE (GimpBlendModifierTool, gimp_blend_modifier_tool, GIMP_TYPE_BRUSH_MODIFIER_TOOL)
+
+
+static void
+gimp_blend_modifier_tool_class_init (GimpBlendModifierToolClass *klass)
+{
+  GimpBrushModifierToolClass *tool_class = GIMP_BRUSH_MODIFIER_TOOL_CLASS (klass);
+  tool_class->gui = gimp_blend_modifier_options_gui;
+}
+
+static void
+gimp_blend_modifier_tool_init (GimpBlendModifierTool *blend_modifier)
+{
+  GimpBrushModifierTool *tool = GIMP_BRUSH_MODIFIER_TOOL (blend_modifier);
+  tool->name = "Blend";
+  tool->enabled_options_name = "blend-enabled";
+  g_print("[Trace]blend_modifier_tool::init\n");
+}
+
+
+/*  tool options stuff  */
+
+void
+gimp_blend_modifier_options_gui (GimpBrushModifierTool *tool,
+				 GObject               *config,
+				 GtkContainer          *container)
+{
+  GtkWidget *vbox   = GTK_WIDGET(container);
+  GtkWidget *table;
+  GtkWidget *blend_modifier_box;
+  GtkWidget *blend_modifier_vbox;
+  GtkWidget *blend_modifier_button;
+  GtkWidget *blend_modifier_frame;
+
+  g_print("[Trace]:blend_modifier_tool::gui\n");
+
+  table = gtk_table_new (2, 3, FALSE);
+  gtk_table_set_col_spacing (GTK_TABLE (table), 0, 2);
+  gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
+  gtk_widget_show (table);
+
+  /* Canvas Color Picking Configurations */
+  blend_modifier_box = gtk_frame_new (_("Canvas Color"));
+  gtk_box_pack_start (GTK_BOX (vbox), blend_modifier_box, FALSE, TRUE, 0);
+  gtk_widget_show(blend_modifier_box);
+  blend_modifier_vbox = gtk_vbox_new (FALSE, 2);
+  gtk_container_add (GTK_CONTAINER (blend_modifier_box), blend_modifier_vbox);
+  gtk_widget_show (blend_modifier_vbox);
+
+  table = gtk_table_new (3, 5, FALSE);
+  gtk_table_set_col_spacings (GTK_TABLE (table), 2);
+  gtk_box_pack_start (GTK_BOX (blend_modifier_vbox), table, TRUE, TRUE, 0);
+  gtk_widget_show (table);
+  
+  gimp_prop_scale_entry_new (config, "canvas-color-rate",
+                             GTK_TABLE (table), 0, 0,
+                             _("Rate:"),
+                             0.01, 0.1, 2,
+                             FALSE, 0.0, 1.0);
+
+  gimp_prop_scale_entry_new (config, "canvas-color-pressure-rate",
+                             GTK_TABLE (table), 0, 1,
+                             _("Pressure:"),
+                             0.01, 0.1, 2,
+                             FALSE, 0.0, 1.0);
+
+  blend_modifier_button = gimp_prop_check_button_new (config, "invert-canvas-color-pressure", _("Invert Pressure"));
+  gtk_box_pack_start (GTK_BOX (blend_modifier_vbox), blend_modifier_button, FALSE, TRUE, 0);
+  gtk_widget_show (blend_modifier_button);
+
+  /* Original Color Picking Configurations */
+  blend_modifier_box = gtk_frame_new (_("Original Color"));
+  gtk_box_pack_start (GTK_BOX (vbox), blend_modifier_box, FALSE, TRUE, 0);
+  gtk_widget_show(blend_modifier_box);
+  blend_modifier_vbox = gtk_vbox_new (FALSE, 2);
+  gtk_container_add (GTK_CONTAINER (blend_modifier_box), blend_modifier_vbox);
+  gtk_widget_show (blend_modifier_vbox);
+
+  table = gtk_table_new (3, 4, FALSE);
+  gtk_table_set_col_spacings (GTK_TABLE (table), 2);
+  gtk_box_pack_start (GTK_BOX (blend_modifier_vbox), table, TRUE, TRUE, 0);
+  gtk_widget_show (table);
+
+  gimp_prop_scale_entry_new (config, "original-color-rate",
+                             GTK_TABLE (table), 0, 0,
+                             _("Rate:"),
+                             0.01, 0.1, 2,
+                             FALSE, 0.0, 1.0);
+
+  gimp_prop_scale_entry_new (config, "original-color-pressure-rate",
+                             GTK_TABLE (table), 0, 1,
+                             _("Pressure:"),
+                             0.01, 0.1, 2,
+                             FALSE, 0.0, 1.0);
+
+  blend_modifier_button = gimp_prop_check_button_new (config, "invert-original-color-pressure", _("Invert Pressure"));
+  gtk_box_pack_start (GTK_BOX (blend_modifier_vbox), blend_modifier_button, FALSE, TRUE, 0);
+  gtk_widget_show (blend_modifier_button);
+
+  table = gtk_table_new (3, 1, FALSE);
+  gtk_table_set_col_spacings (GTK_TABLE (table), 2);
+  gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0);
+  gtk_widget_show (table);
+
+  /*blend_modifier_button = gimp_prop_check_button_new (config, "merged", _("Pick up underlying color"));*/
+  blend_modifier_button = gimp_prop_check_button_new (config, "merged", _("Pick up merged color"));
+  gtk_box_pack_start (GTK_BOX (vbox), blend_modifier_button, FALSE, TRUE, 0);
+  gtk_widget_show (blend_modifier_button);
+
+  blend_modifier_frame = gimp_prop_enum_radio_frame_new (config, "hidden-color",
+                                                   _("Assume that the hidden color is:"),
+                                                   0, 0);
+  gtk_box_pack_start (GTK_BOX (vbox), blend_modifier_frame, FALSE, TRUE, 0);
+  gtk_widget_show (blend_modifier_frame);
+}
diff -uNr gimp-2.4.1/app/tools/gimpblendmodifiertool.h gimp-2.4.1-tmp/app/tools/gimpblendmodifiertool.h
--- gimp-2.4.1/app/tools/gimpblendmodifiertool.h	1970-01-01 09:00:00.000000000 +0900
+++ gimp-2.4.1-tmp/app/tools/gimpblendmodifiertool.h	2008-03-22 21:39:28.000000000 +0900
@@ -0,0 +1,50 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GIMP_BLEND_MODIFIER_TOOL_H__
+#define __GIMP_BLEND_MODIFIER_TOOL_H__
+
+
+#include "gimpbrushmodifiertool.h"
+
+
+#define GIMP_TYPE_BLEND_MODIFIER_TOOL            (gimp_blend_modifier_tool_get_type ())
+#define GIMP_BLEND_MODIFIER_TOOL(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_BLEND_MODIFIER_TOOL, GimpBlendModifierTool))
+#define GIMP_BLEND_MODIFIER_TOOL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_BLEND_MODIFIER_TOOL, GimpBlendModifierToolClass))
+#define GIMP_IS_BLEND_MODIFIER_TOOL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_BLEND_MODIFIER_TOOL))
+#define GIMP_IS_BLEND_MODIFIER_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_BLEND_MODIFIER_TOOL))
+#define GIMP_BLEND_MODIFIER_TOOL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_BLEND_MODIFIER_TOOL, GimpBlendModifierToolClass))
+
+
+typedef struct _GimpBlendModifierTool      GimpBlendModifierTool;
+typedef struct _GimpBlendModifierToolClass GimpBlendModifierToolClass;
+
+struct _GimpBlendModifierTool
+{
+  GimpBrushModifierTool parent_instance;
+};
+
+struct _GimpBlendModifierToolClass
+{
+  GimpBrushModifierToolClass parent_class;
+};
+
+GType      gimp_blend_modifier_tool_get_type (void) G_GNUC_CONST;
+
+
+#endif  /*  __GIMP_BLEND_MODIFIER_TOOL_H__  */
diff -uNr gimp-2.4.1/app/tools/gimpbrushmodifiertool.c gimp-2.4.1-tmp/app/tools/gimpbrushmodifiertool.c
--- gimp-2.4.1/app/tools/gimpbrushmodifiertool.c	1970-01-01 09:00:00.000000000 +0900
+++ gimp-2.4.1-tmp/app/tools/gimpbrushmodifiertool.c	2008-03-22 21:39:28.000000000 +0900
@@ -0,0 +1,63 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "tools-types.h"
+
+#include "paint/gimpbrushmodifieroptions.h"
+
+#include "widgets/gimphelp-ids.h"
+
+#include "gimp-intl.h"
+
+#include "gimpbrushmodifiertool.h"
+
+static void
+gimp_brush_modifier_tool_gui (GimpBrushModifierTool *tool,
+			      GObject               *config,
+			      GtkContainer          *container);
+
+
+G_DEFINE_TYPE (GimpBrushModifierTool, gimp_brush_modifier_tool, GIMP_TYPE_OBJECT)
+
+static void
+gimp_brush_modifier_tool_class_init (GimpBrushModifierToolClass *klass)
+{
+  klass->gui = gimp_brush_modifier_tool_gui;
+}
+
+static void
+gimp_brush_modifier_tool_init (GimpBrushModifierTool *brush_modifier)
+{
+  brush_modifier->name = "BrushModifier";
+}
+
+
+/*  tool options stuff  */
+
+static void
+gimp_brush_modifier_tool_gui (GimpBrushModifierTool *tool,
+			      GObject               *config,
+			      GtkContainer          *container)
+{
+}
diff -uNr gimp-2.4.1/app/tools/gimpbrushmodifiertool.h gimp-2.4.1-tmp/app/tools/gimpbrushmodifiertool.h
--- gimp-2.4.1/app/tools/gimpbrushmodifiertool.h	1970-01-01 09:00:00.000000000 +0900
+++ gimp-2.4.1-tmp/app/tools/gimpbrushmodifiertool.h	2008-03-22 21:39:28.000000000 +0900
@@ -0,0 +1,53 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GIMP_BRUSH_MODIFIER_TOOL_H__
+#define __GIMP_BRUSH_MODIFIER_TOOL_H__
+
+
+#define GIMP_TYPE_BRUSH_MODIFIER_TOOL            (gimp_brush_modifier_tool_get_type ())
+#define GIMP_BRUSH_MODIFIER_TOOL(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_BRUSH_MODIFIER_TOOL, GimpBrushModifierTool))
+#define GIMP_BRUSH_MODIFIER_TOOL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_BRUSH_MODIFIER_TOOL, GimpBrushModifierToolClass))
+#define GIMP_IS_BRUSH_MODIFIER_TOOL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_BRUSH_MODIFIER_TOOL))
+#define GIMP_IS_BRUSH_MODIFIER_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_BRUSH_MODIFIER_TOOL))
+#define GIMP_BRUSH_MODIFIER_TOOL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_BRUSH_MODIFIER_TOOL, GimpBrushModifierToolClass))
+
+
+typedef struct _GimpBrushModifierTool      GimpBrushModifierTool;
+typedef struct _GimpBrushModifierToolClass GimpBrushModifierToolClass;
+
+struct _GimpBrushModifierTool
+{
+  GimpObject  parent_instance;
+  char       *name;
+  char       *enabled_options_name;
+};
+
+struct _GimpBrushModifierToolClass
+{
+  GimpObjectClass parent_class;
+
+  void (*gui) (GimpBrushModifierTool *tool,
+	       GObject               *config,
+	       GtkContainer          *container);
+};
+
+GType      gimp_brush_modifier_tool_get_type (void) G_GNUC_CONST;
+
+
+#endif  /*  __GIMP_BRUSH_MODIFIER_TOOL_H__  */
diff -uNr gimp-2.4.1/app/tools/gimpcustombrushtool.c gimp-2.4.1-tmp/app/tools/gimpcustombrushtool.c
--- gimp-2.4.1/app/tools/gimpcustombrushtool.c	1970-01-01 09:00:00.000000000 +0900
+++ gimp-2.4.1-tmp/app/tools/gimpcustombrushtool.c	2008-03-22 21:39:28.000000000 +0900
@@ -0,0 +1,188 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "tools-types.h"
+
+#include "paint/gimpcustombrushoptions.h"
+
+#include "widgets/gimphelp-ids.h"
+
+#include "gimpcustombrushtool.h"
+#include "gimppaintoptions-gui.h"
+#include "gimptoolcontrol.h"
+
+#include "gimp-intl.h"
+
+
+static GtkWidget * gimp_custom_brush_options_gui (GimpToolOptions  *tool_options);
+
+static gboolean            modifier_tools_initialized = FALSE;
+static GList              *modifier_tools             = NULL;
+static void gimp_custom_brush_tool_load          (void);
+static void gimp_custom_brush_tool_unload        (void);
+
+G_DEFINE_TYPE (GimpCustomBrushTool, gimp_custom_brush_tool, GIMP_TYPE_PAINTBRUSH_TOOL)
+
+
+void
+gimp_custom_brush_tool_register (GimpToolRegisterCallback  callback,
+                             gpointer                  data)
+{
+  g_print("[Trace]:custom_brush_tool::register\n");
+  (* callback) (GIMP_TYPE_CUSTOM_BRUSH_TOOL,
+                GIMP_TYPE_CUSTOM_BRUSH_OPTIONS,
+                gimp_custom_brush_options_gui,
+                GIMP_PAINT_OPTIONS_CONTEXT_MASK |
+                GIMP_CONTEXT_GRADIENT_MASK,
+                "gimp-custom-brush-tool",
+                _("CustomBrush"),
+                _("CustomBrush Tool: Paint brush with extension features."),
+                N_("_CustomBrush"), "W",
+                NULL, GIMP_HELP_TOOL_PAINTBRUSH,
+                GIMP_STOCK_TOOL_PAINTBRUSH,
+                data);
+}
+
+
+static void
+gimp_custom_brush_tool_class_init (GimpCustomBrushToolClass *klass)
+{
+  gimp_custom_brush_tool_load();
+  g_print("[Trace]:custom_brush_tool_class::init\n");
+}
+
+#include "gimpblendmodifiertool.h"
+#include "gimpsmoothmodifiertool.h"
+static void
+gimp_custom_brush_tool_load ()
+{
+  if (!modifier_tools_initialized)
+    {
+      GObject* tool;
+      tool = g_object_new(GIMP_TYPE_BLEND_MODIFIER_TOOL, NULL);
+      modifier_tools = g_list_append(modifier_tools, (gpointer)tool);
+
+      tool = g_object_new(GIMP_TYPE_SMOOTH_MODIFIER_TOOL, NULL);
+      modifier_tools = g_list_append(modifier_tools, (gpointer)tool);
+
+      modifier_tools_initialized = TRUE;
+    }
+}
+
+static void
+gimp_custom_brush_tool_init (GimpCustomBrushTool *custom_tool)
+{
+  GimpTool *tool = GIMP_TOOL (custom_tool);
+
+  gimp_tool_control_set_tool_cursor (tool->control, GIMP_TOOL_CURSOR_PAINTBRUSH);
+
+  gimp_paint_tool_enable_color_picker (GIMP_PAINT_TOOL (custom_tool),
+                                       GIMP_COLOR_PICK_MODE_FOREGROUND);
+
+  g_print("[Trace]:custom_brush_tool::init\n");
+}
+
+
+static void
+gimp_custom_brush_tool_unlink (gpointer data, gpointer user_data)
+{
+  g_object_unref(G_OBJECT(data));
+}
+
+
+static void
+gimp_custom_brush_tool_unload ()
+{
+  g_list_foreach(modifier_tools,
+		 gimp_custom_brush_tool_unlink,
+		 NULL);
+  g_list_free(modifier_tools);
+}
+
+
+/*  tool options stuff  */
+static void
+modifier_enabled_toggled (GtkToggleButton *togglebutton,
+			  gpointer         user_data)
+{
+  GtkWidget* widget = GTK_WIDGET(user_data);
+
+  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(togglebutton)))
+    {
+      gtk_widget_show(widget);
+    }
+  else
+    {
+      gtk_widget_hide(widget);
+    }
+}
+
+static GtkWidget *
+gimp_custom_brush_options_gui (GimpToolOptions *tool_options)
+{
+  GObject   *config = G_OBJECT (tool_options);
+  GtkWidget *vbox   = gimp_paint_options_gui (tool_options);
+  GList     *list;
+  
+  g_print("[Trace]:custom_brush_tool::gui\n");
+  gimp_custom_brush_tool_load ();
+  
+  /* call GUI handlers of all modifiers */
+  for (list = g_list_first(modifier_tools);
+       list != NULL;
+       list = g_list_next(list))
+    {
+      GimpBrushModifierTool* tool = GIMP_BRUSH_MODIFIER_TOOL(list->data);
+      GtkWidget *custom_brush_box;
+      GtkWidget *custom_brush_vbox;
+      GtkWidget *enabled_check;
+      gboolean   enabled;
+
+      g_object_get(config, tool->enabled_options_name, &enabled, NULL);
+
+      enabled_check = gimp_prop_check_button_new (config, tool->enabled_options_name, _(tool->name));
+      gtk_box_pack_start (GTK_BOX (vbox), enabled_check, FALSE, TRUE, 0);
+      gtk_widget_show (enabled_check);
+
+      custom_brush_box = gtk_frame_new (NULL);
+      gtk_box_pack_start (GTK_BOX (vbox), custom_brush_box, FALSE, TRUE, 0);
+      gtk_widget_show(custom_brush_box);
+
+      
+      custom_brush_vbox = gtk_vbox_new (FALSE, 2);
+      gtk_container_add (GTK_CONTAINER (custom_brush_box), custom_brush_vbox);
+      g_print("here\n");
+      if (enabled)
+	gtk_widget_show (custom_brush_vbox);
+      else
+	gtk_widget_hide (custom_brush_vbox);
+
+      GIMP_BRUSH_MODIFIER_TOOL_GET_CLASS(tool)->gui(tool, config, GTK_CONTAINER(custom_brush_vbox));
+
+      g_signal_connect (GTK_OBJECT(enabled_check), "toggled",
+			GTK_SIGNAL_FUNC(modifier_enabled_toggled), (gpointer)custom_brush_vbox);
+    }
+
+  return vbox;
+}
diff -uNr gimp-2.4.1/app/tools/gimpcustombrushtool.h gimp-2.4.1-tmp/app/tools/gimpcustombrushtool.h
--- gimp-2.4.1/app/tools/gimpcustombrushtool.h	1970-01-01 09:00:00.000000000 +0900
+++ gimp-2.4.1-tmp/app/tools/gimpcustombrushtool.h	2008-03-22 21:39:28.000000000 +0900
@@ -0,0 +1,54 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GIMP_CUSTOM_BRUSH_TOOL_H__
+#define __GIMP_CUSTOM_BRUSH_TOOL_H__
+
+
+#include "gimppaintbrushtool.h"
+
+
+#define GIMP_TYPE_CUSTOM_BRUSH_TOOL            (gimp_custom_brush_tool_get_type ())
+#define GIMP_CUSTOM_BRUSH_TOOL(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_CUSTOM_BRUSH_TOOL, GimpCustomBrushTool))
+#define GIMP_CUSTOM_BRUSH_TOOL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_CUSTOM_BRUSH_TOOL, GimpCustomBrushToolClass))
+#define GIMP_IS_CUSTOM_BRUSH_TOOL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_CUSTOM_BRUSH_TOOL))
+#define GIMP_IS_CUSTOM_BRUSH_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_CUSTOM_BRUSH_TOOL))
+#define GIMP_CUSTOM_BRUSH_TOOL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_CUSTOM_BRUSH_TOOL, GimpCustomBrushToolClass))
+
+
+typedef struct _GimpCustomBrushTool      GimpCustomBrushTool;
+typedef struct _GimpCustomBrushToolClass GimpCustomBrushToolClass;
+
+struct _GimpCustomBrushTool
+{
+  GimpPaintbrushTool  parent_instance;
+};
+
+struct _GimpCustomBrushToolClass
+{
+  GimpPaintbrushToolClass parent_class;
+};
+
+
+void       gimp_custom_brush_tool_register (GimpToolRegisterCallback  callback,
+                                        gpointer                  data);
+
+GType      gimp_custom_brush_tool_get_type (void) G_GNUC_CONST;
+
+
+#endif  /*  __GIMP_CUSTOM_BRUSH_TOOL_H__  */
diff -uNr gimp-2.4.1/app/tools/gimppaintoptions-gui.c gimp-2.4.1-tmp/app/tools/gimppaintoptions-gui.c
--- gimp-2.4.1/app/tools/gimppaintoptions-gui.c	2007-10-23 04:16:17.000000000 +0900
+++ gimp-2.4.1-tmp/app/tools/gimppaintoptions-gui.c	2008-03-22 21:39:28.000000000 +0900
@@ -46,6 +46,7 @@
 #include "gimppenciltool.h"
 #include "gimpperspectiveclonetool.h"
 #include "gimpsmudgetool.h"
+#include "gimpcustombrushtool.h"
 #include "gimptooloptions-gui.h"
 
 #include "gimp-intl.h"
@@ -175,6 +176,7 @@
   /*  the "incremental" toggle  */
   if (tool_type == GIMP_TYPE_PENCIL_TOOL     ||
       tool_type == GIMP_TYPE_PAINTBRUSH_TOOL ||
+      tool_type == GIMP_TYPE_CUSTOM_BRUSH_TOOL ||
       tool_type == GIMP_TYPE_ERASER_TOOL)
     {
       incremental_toggle =
@@ -293,6 +295,7 @@
       tool_type == GIMP_TYPE_DODGE_BURN_TOOL        ||
       tool_type == GIMP_TYPE_ERASER_TOOL            ||
       tool_type == GIMP_TYPE_PAINTBRUSH_TOOL        ||
+      tool_type == GIMP_TYPE_CUSTOM_BRUSH_TOOL      ||
       tool_type == GIMP_TYPE_PENCIL_TOOL)
     {
       button = gimp_prop_check_button_new (config, "pressure-size",
diff -uNr gimp-2.4.1/app/tools/gimpsmoothmodifiertool.c gimp-2.4.1-tmp/app/tools/gimpsmoothmodifiertool.c
--- gimp-2.4.1/app/tools/gimpsmoothmodifiertool.c	1970-01-01 09:00:00.000000000 +0900
+++ gimp-2.4.1-tmp/app/tools/gimpsmoothmodifiertool.c	2008-03-22 21:39:28.000000000 +0900
@@ -0,0 +1,107 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "tools-types.h"
+
+#include "paint/gimpcustombrushoptions.h"
+
+#include "widgets/gimphelp-ids.h"
+
+#include "gimpsmoothmodifiertool.h"
+#include "gimppaintoptions-gui.h"
+#include "gimptoolcontrol.h"
+
+#include "gimp-intl.h"
+
+
+static void
+gimp_smooth_modifier_options_gui (GimpBrushModifierTool *tool,
+				 GObject               *config,
+				 GtkContainer          *container);
+
+
+G_DEFINE_TYPE (GimpSmoothModifierTool, gimp_smooth_modifier_tool, GIMP_TYPE_BRUSH_MODIFIER_TOOL)
+
+
+static void
+gimp_smooth_modifier_tool_class_init (GimpSmoothModifierToolClass *klass)
+{
+  GimpBrushModifierToolClass *tool_class = GIMP_BRUSH_MODIFIER_TOOL_CLASS (klass);
+  tool_class->gui = gimp_smooth_modifier_options_gui;
+}
+
+static void
+gimp_smooth_modifier_tool_init (GimpSmoothModifierTool *smooth_modifier)
+{
+  GimpBrushModifierTool *tool = GIMP_BRUSH_MODIFIER_TOOL (smooth_modifier);
+  tool->name = "Smooth";
+  tool->enabled_options_name = "smooth-enabled";
+  g_print("[Trace]smooth_modifier_tool::init\n");
+}
+
+
+/*  tool options stuff  */
+
+void
+gimp_smooth_modifier_options_gui (GimpBrushModifierTool *tool,
+				 GObject               *config,
+				 GtkContainer          *container)
+{
+  GtkWidget *vbox   = GTK_WIDGET(container);
+  GtkWidget *table;
+  GtkWidget *smooth_modifier_box;
+  GtkWidget *smooth_modifier_vbox;
+
+  GtkWidget *adj;
+
+  g_print("[Trace]:smooth_modifier_tool::gui\n");
+
+  /* smoothing options */
+  table = gtk_table_new (3, 3, FALSE);
+  gtk_table_set_col_spacings (GTK_TABLE (table), 2);
+  gtk_box_pack_start (GTK_BOX (container), table, TRUE, TRUE, 0);
+  gtk_widget_show (table);
+
+  /* smoothing history size slider */
+  gimp_prop_scale_entry_new (config, "smoothing-history-size",
+                             GTK_TABLE (table), 0, 0,
+                             _("Quality:"),
+                             1, 1, 0,
+                             FALSE, 1.0, 20);
+
+  /* smoothing scaling rate slider */
+  adj = gimp_prop_scale_entry_new (config, "distance-scale",
+				   GTK_TABLE (table), 0, 1,
+				   _("Distance Scale:"),
+				   1, 10, 1,
+				   FALSE, 0, 100);
+
+  /* smoothing rate slider */
+  adj = gimp_prop_scale_entry_new (config, "smoothing-rate",
+				   GTK_TABLE (table), 0, 2,
+				   _("Rate:"),
+				   1, 1, 2,
+				   FALSE, 0, 100);
+  gimp_scale_entry_set_logarithmic (adj, TRUE);
+}
diff -uNr gimp-2.4.1/app/tools/gimpsmoothmodifiertool.h gimp-2.4.1-tmp/app/tools/gimpsmoothmodifiertool.h
--- gimp-2.4.1/app/tools/gimpsmoothmodifiertool.h	1970-01-01 09:00:00.000000000 +0900
+++ gimp-2.4.1-tmp/app/tools/gimpsmoothmodifiertool.h	2008-03-22 21:39:28.000000000 +0900
@@ -0,0 +1,50 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GIMP_SMOOTH_MODIFIER_TOOL_H__
+#define __GIMP_SMOOTH_MODIFIER_TOOL_H__
+
+
+#include "gimpbrushmodifiertool.h"
+
+
+#define GIMP_TYPE_SMOOTH_MODIFIER_TOOL            (gimp_smooth_modifier_tool_get_type ())
+#define GIMP_SMOOTH_MODIFIER_TOOL(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_SMOOTH_MODIFIER_TOOL, GimpSmoothModifierTool))
+#define GIMP_SMOOTH_MODIFIER_TOOL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_SMOOTH_MODIFIER_TOOL, GimpSmoothModifierToolClass))
+#define GIMP_IS_SMOOTH_MODIFIER_TOOL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_SMOOTH_MODIFIER_TOOL))
+#define GIMP_IS_SMOOTH_MODIFIER_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_SMOOTH_MODIFIER_TOOL))
+#define GIMP_SMOOTH_MODIFIER_TOOL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_SMOOTH_MODIFIER_TOOL, GimpSmoothModifierToolClass))
+
+
+typedef struct _GimpSmoothModifierTool      GimpSmoothModifierTool;
+typedef struct _GimpSmoothModifierToolClass GimpSmoothModifierToolClass;
+
+struct _GimpSmoothModifierTool
+{
+  GimpBrushModifierTool parent_instance;
+};
+
+struct _GimpSmoothModifierToolClass
+{
+  GimpBrushModifierToolClass parent_class;
+};
+
+GType      gimp_smooth_modifier_tool_get_type (void) G_GNUC_CONST;
+
+
+#endif  /*  __GIMP_SMOOTH_MODIFIER_TOOL_H__  */
