--- gimp-2.4.1/app/paint/Makefile.am	Wed Jun 27 18:50:24 2007
+++ gimp-2.4.1_gpen_mixbrush/app/paint/Makefile.am	Thu Nov  1 01:40:57 2007
@@ -77,7 +77,17 @@
 	gimpsourcecore.c		\
 	gimpsourcecore.h		\
 	gimpsourceoptions.c		\
-	gimpsourceoptions.h
+	gimpsourceoptions.h		\
+	gimpink2.c				\
+	gimpink2.h				\
+	gimpink2undo.c			\
+	gimpink2undo.h			\
+	gimpink2options.c		\
+	gimpink2options.h		\
+	gimpmixbrush.c			\
+	gimpmixbrush.h			\
+	gimpmixbrushoptions.c	\
+	gimpmixbrushoptions.h
 
 libapppaint_a_built_sources = paint-enums.c
 
--- gimp-2.4.1/app/paint/Makefile.in	Wed Oct 31 17:09:06 2007
+++ gimp-2.4.1_gpen_mixbrush/app/paint/Makefile.in	Thu Nov  1 01:40:57 2007
@@ -70,7 +70,9 @@
 	gimppaintbrush.$(OBJEXT) gimpperspectiveclone.$(OBJEXT) \
 	gimpperspectivecloneoptions.$(OBJEXT) gimpsmudge.$(OBJEXT) \
 	gimpsmudgeoptions.$(OBJEXT) gimpsourcecore.$(OBJEXT) \
-	gimpsourceoptions.$(OBJEXT)
+	gimpsourceoptions.$(OBJEXT) \
+	gimpink2.$(OBJEXT) gimpink2options.$(OBJEXT) gimpink2undo.$(OBJEXT) \
+	gimpmixbrush.$(OBJEXT) gimpmixbrushoptions.$(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 +537,17 @@
 	gimpsourcecore.c		\
 	gimpsourcecore.h		\
 	gimpsourceoptions.c		\
-	gimpsourceoptions.h
+	gimpsourceoptions.h		\
+	gimpink2.c				\
+	gimpink2.h				\
+	gimpink2options.c		\
+	gimpink2options.h		\
+	gimpink2undo.c			\
+	gimpink2undo.h			\
+	gimpmixbrush.c			\
+	gimpmixbrush.h			\
+	gimpmixbrushoptions.c	\
+	gimpmixbrushoptions.h
 
 libapppaint_a_built_sources = paint-enums.c
 libapppaint_a_SOURCES = $(libapppaint_a_built_sources) $(libapppaint_a_sources)
@@ -625,6 +637,11 @@
 @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)/gimpink2.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpink2options.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpink2undo.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpmixbrush.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpmixbrushoptions.Po@am__quote@
 
 .c.o:
 @am__fastdepCC_TRUE@	if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
--- gimp-2.4.1/app/paint/gimp-paint.c	Wed Jul 25 03:45:42 2007
+++ gimp-2.4.1_gpen_mixbrush/app/paint/gimp-paint.c	Thu Nov  1 01:40:57 2007
@@ -39,6 +39,8 @@
 #include "gimppencil.h"
 #include "gimpperspectiveclone.h"
 #include "gimpsmudge.h"
+#include "gimpink2.h"
+#include "gimpmixbrush.h"
 
 
 /*  local function prototypes  */
@@ -68,7 +70,9 @@
     gimp_airbrush_register,
     gimp_eraser_register,
     gimp_paintbrush_register,
-    gimp_pencil_register
+    gimp_pencil_register,
+    gimp_ink2_register,
+    gimp_mixbrush_register
   };
 
   gint i;
--- gimp-2.4.1/app/paint/gimpbrushcore.c	Thu Aug 16 06:56:50 2007
+++ gimp-2.4.1_gpen_mixbrush/app/paint/gimpbrushcore.c	Thu Nov  1 01:40:57 2007
@@ -908,20 +908,23 @@
                                   gdouble           pressure)
 {
   gdouble scale = 1.0;
+  gdouble min_scale = paint_options->pressure_options->min_scale;
 
   if (GIMP_BRUSH_CORE_GET_CLASS (core)->use_scale)
     {
-      if (GIMP_PAINT_CORE (core)->use_pressure)
+      if (GIMP_PAINT_CORE (core)->use_pressure && min_scale < 1.0)
         {
           if (paint_options->pressure_options->inverse_size)
             scale = 1.0 - 0.9 * pressure;
           else if (paint_options->pressure_options->size)
             scale = pressure;
 
-          if (scale < 1 / 256.0)
-            scale = 1 / 16.0;
-          else
-            scale = sqrt (scale);
+          scale = sqrt (scale);
+
+          if (min_scale > 0)
+            scale = min_scale + (1.0 - min_scale) * scale;
+
+          scale = MAX (scale, 1 / 16.0);
         }
 
       scale *= paint_options->brush_scale;
--- gimp-2.4.1/app/paint/gimpink2.c	Thu Jan  1 09:00:00 1970
+++ gimp-2.4.1_gpen_mixbrush/app/paint/gimpink2.c	Thu Nov  1 01:40:57 2007
@@ -0,0 +1,915 @@
+/* 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/pixel-region.h"
+#include "base/temp-buf.h"
+#include "base/tile.h"
+#include "base/tile-manager.h"
+
+#include "paint-funcs/paint-funcs.h"
+
+#include "core/gimpdrawable.h"
+#include "core/gimpimage.h"
+#include "core/gimpimage-undo.h"
+
+#include "gimpink2options.h"
+#include "gimpink2.h"
+#include "gimpink-blob.h"
+#include "gimpink2undo.h"
+
+#include "gimp-intl.h"
+
+
+#define SUBSAMPLE 8
+
+
+/*  local function prototypes  */
+
+static void      gimp_ink2_finalize       (GObject          *object);
+
+static void      gimp_ink2_paint          (GimpPaintCore    *paint_core,
+                                           GimpDrawable     *drawable,
+                                           GimpPaintOptions *paint_options,
+                                           GimpPaintState    paint_state,
+                                           guint32           time);
+static TempBuf * gimp_ink2_get_paint_area (GimpPaintCore    *paint_core,
+                                           GimpDrawable     *drawable,
+                                           GimpPaintOptions *paint_options);
+static GimpUndo* gimp_ink2_push_undo      (GimpPaintCore    *core,
+                                           GimpImage        *image,
+                                           const gchar      *undo_desc);
+
+static void      gimp_ink2_motion         (GimpPaintCore    *paint_core,
+                                           GimpDrawable     *drawable,
+                                           GimpPaintOptions *paint_options,
+                                           guint32           time,
+                                           gboolean          at_last);
+
+static Blob    * ink2_pen_ellipse         (GimpInk2Options   *options,
+                                           gdouble           x_center,
+                                           gdouble           y_center,
+                                           gdouble           pressure,
+                                           gdouble           xtilt,
+                                           gdouble           ytilt,
+                                           gdouble           velocity);
+
+static void      time_smoother_add       (GimpInk2          *ink,
+                                          guint32           value);
+static guint32   time_smoother_result    (GimpInk2          *ink);
+static void      time_smoother_init      (GimpInk2          *ink,
+                                          guint32           initval);
+
+static void      dist_smoother_add       (GimpInk2          *ink,
+                                          gdouble           value);
+static gdouble   dist_smoother_result    (GimpInk2          *ink);
+static void      dist_smoother_init      (GimpInk2          *ink,
+                                          gdouble           initval);
+
+static void      render_blob             (Blob             *blob,
+                                          PixelRegion      *dest);
+
+/* Ink2 additional functions */
+static void       hist_init            (GimpInk2 *ink, GimpCoords* coords);
+static void       hist_add             (GimpInk2 *ink, GimpCoords* coords, gdouble speed);
+static GimpCoords hist_result          (GimpInk2 *ink, GimpInk2Options *options);
+static GimpCoords hist_result_velocity (GimpInk2 *ink, GimpInk2Options *options);
+
+static gdouble PI;
+/* */
+
+
+G_DEFINE_TYPE (GimpInk2, gimp_ink2, GIMP_TYPE_PAINT_CORE)
+
+#define parent_class gimp_ink2_parent_class
+
+
+void
+gimp_ink2_register (Gimp                      *gimp,
+                   GimpPaintRegisterCallback  callback)
+{
+  (* callback) (gimp,
+                GIMP_TYPE_INK2,
+                GIMP_TYPE_INK2_OPTIONS,
+                "gimp-ink2",
+                _("G-pen"),
+                "gimp-tool-ink2");
+}
+
+static void
+gimp_ink2_class_init (GimpInk2Class *klass)
+{
+  GObjectClass       *object_class     = G_OBJECT_CLASS (klass);
+  GimpPaintCoreClass *paint_core_class = GIMP_PAINT_CORE_CLASS (klass);
+
+  object_class->finalize           = gimp_ink2_finalize;
+
+  paint_core_class->paint          = gimp_ink2_paint;
+  paint_core_class->get_paint_area = gimp_ink2_get_paint_area;
+  paint_core_class->push_undo      = gimp_ink2_push_undo;
+
+  /* initialize internal variables */
+  PI = 4 * atan(1);
+}
+
+static void
+gimp_ink2_init (GimpInk2 *ink)
+{
+}
+
+static void
+gimp_ink2_finalize (GObject *object)
+{
+  GimpInk2 *ink = GIMP_INK2 (object);
+
+  if (ink->start_blob)
+    {
+      g_free (ink->start_blob);
+      ink->start_blob = NULL;
+    }
+
+  if (ink->last_blob)
+    {
+      g_free (ink->last_blob);
+      ink->last_blob = NULL;
+    }
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gimp_ink2_paint (GimpPaintCore    *paint_core,
+                GimpDrawable     *drawable,
+                GimpPaintOptions *paint_options,
+                GimpPaintState    paint_state,
+                guint32           time)
+{
+  GimpInk2 *ink = GIMP_INK2 (paint_core);
+
+  switch (paint_state)
+    {
+    case GIMP_PAINT_STATE_INIT:
+      if (paint_core->cur_coords.x == paint_core->last_coords.x &&
+          paint_core->cur_coords.y == paint_core->last_coords.y)
+        {
+          /*  start with new blobs if we're not interpolating  */
+
+          if (ink->start_blob)
+            {
+              g_free (ink->start_blob);
+              ink->start_blob = NULL;
+            }
+
+          if (ink->last_blob)
+            {
+              g_free (ink->last_blob);
+              ink->last_blob = NULL;
+            }
+        }
+      else if (ink->last_blob)
+        {
+          /*  save the start blob of the line for undo otherwise  */
+
+          if (ink->start_blob)
+            g_free (ink->start_blob);
+
+          ink->start_blob = blob_duplicate (ink->last_blob);
+        }
+      break;
+
+    case GIMP_PAINT_STATE_MOTION:
+      gimp_ink2_motion (paint_core, drawable, paint_options, time, FALSE);
+      break;
+
+    case GIMP_PAINT_STATE_FINISH:
+      gimp_ink2_motion (paint_core, drawable, paint_options, time, TRUE);
+      /*g_printf("\n");*/
+      break;
+    }
+}
+
+static TempBuf *
+gimp_ink2_get_paint_area (GimpPaintCore    *paint_core,
+                          GimpDrawable     *drawable,
+                          GimpPaintOptions *paint_options)
+{
+  GimpInk2 *ink  = GIMP_INK2 (paint_core);
+  gint      x, y;
+  gint      width, height;
+  gint      dwidth, dheight;
+  gint      x1, y1, x2, y2;
+  gint      bytes;
+
+  bytes = gimp_drawable_bytes_with_alpha (drawable);
+
+  blob_bounds (ink->cur_blob, &x, &y, &width, &height);
+
+  dwidth  = gimp_item_width  (GIMP_ITEM (drawable));
+  dheight = gimp_item_height (GIMP_ITEM (drawable));
+
+  x1 = CLAMP (x / SUBSAMPLE - 1,            0, dwidth);
+  y1 = CLAMP (y / SUBSAMPLE - 1,            0, dheight);
+  x2 = CLAMP ((x + width)  / SUBSAMPLE + 2, 0, dwidth);
+  y2 = CLAMP ((y + height) / SUBSAMPLE + 2, 0, dheight);
+
+  /*  configure the canvas buffer  */
+  if ((x2 - x1) && (y2 - y1))
+    paint_core->canvas_buf = temp_buf_resize (paint_core->canvas_buf, bytes,
+                                              x1, y1,
+                                              (x2 - x1), (y2 - y1));
+  else
+    return NULL;
+
+  return paint_core->canvas_buf;
+}
+
+static GimpUndo *
+gimp_ink2_push_undo (GimpPaintCore *core,
+                     GimpImage     *image,
+                     const gchar   *undo_desc)
+{
+  return gimp_image_undo_push (image, GIMP_TYPE_INK2_UNDO,
+                               GIMP_UNDO_INK, undo_desc,
+                               0,
+                               "paint-core", core,
+                               NULL);
+}
+
+static void
+gimp_ink2_motion (GimpPaintCore    *paint_core,
+                  GimpDrawable     *drawable,
+                  GimpPaintOptions *paint_options,
+                  guint32           time,
+                  gboolean          at_last)
+{
+  GimpInk2        *ink     = GIMP_INK2 (paint_core);
+  GimpInk2Options *options = GIMP_INK2_OPTIONS (paint_options);
+  GimpContext     *context = GIMP_CONTEXT (paint_options);
+  GimpImage       *image;
+  Blob            *blob_union = NULL;
+  Blob            *blob_to_render;
+  TempBuf         *area;
+  guchar           col[MAX_CHANNELS];
+  PixelRegion      blob_maskPR;
+
+  if (at_last && !options->compensate_at_last)
+    return;
+
+  image = gimp_item_get_image (GIMP_ITEM (drawable));
+
+  if (! ink->last_blob)
+    {
+      ink->last_blob = ink2_pen_ellipse (options,
+                                         paint_core->cur_coords.x,
+                                         paint_core->cur_coords.y,
+                                         paint_core->cur_coords.pressure,
+                                         paint_core->cur_coords.xtilt,
+                                         paint_core->cur_coords.ytilt,
+                                         10.0);
+
+      if (ink->start_blob)
+        g_free (ink->start_blob);
+
+      ink->start_blob = blob_duplicate (ink->last_blob);
+
+      time_smoother_init (ink, time);
+      ink->last_time = time;
+
+      dist_smoother_init (ink, 0.0);
+      ink->init_velocity = TRUE;
+
+      hist_init (ink, &paint_core->cur_coords);
+
+      blob_to_render = ink->last_blob;
+    }
+  else
+    {
+      Blob      *blob;
+      gdouble    dist;
+      gdouble    velocity;
+      guint32    lasttime = ink->last_time;
+      guint32    thistime;
+      GimpCoords average_hist;
+      GimpCoords average_velocity;
+
+      time_smoother_add (ink, time);
+      thistime = ink->last_time = time_smoother_result (ink);
+
+      /* 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 (ink->init_velocity)
+        {
+          dist_smoother_init (ink, dist);
+          ink->init_velocity = FALSE;
+        }
+      else
+        {
+          dist_smoother_add (ink, dist);
+          dist = dist_smoother_result (ink);
+        }
+
+      velocity = 10.0 * sqrt ((dist) / (gdouble) (thistime - lasttime));
+
+      /* g_printf("%f, %f, %f\n", paint_core->cur_coords.x, paint_core->cur_coords.y, velocity); */
+
+      if (!at_last && options->compensation_hist_size > 1) 
+        {
+          hist_add(ink, &paint_core->cur_coords, velocity);
+          average_hist = hist_result(ink, options);
+          blob = ink2_pen_ellipse (options,
+                                   average_hist.x,
+                                   average_hist.y,
+                                   paint_core->cur_coords.pressure,
+                                   paint_core->cur_coords.xtilt,
+                                   paint_core->cur_coords.ytilt,
+                                   velocity);
+          ink->last_point = average_hist;
+        }
+      else
+        {
+          blob = ink2_pen_ellipse (options,
+                                   paint_core->cur_coords.x,
+                                   paint_core->cur_coords.y,
+                                   paint_core->cur_coords.pressure,
+                                   paint_core->cur_coords.xtilt,
+                                   paint_core->cur_coords.ytilt,
+                                   velocity);
+        }
+
+      blob_union = blob_convex_union (ink->last_blob, blob);
+      g_free (ink->last_blob);
+      ink->last_blob = blob;
+
+      blob_to_render = blob_union;
+    }
+
+  /* Get the buffer */
+  ink->cur_blob = blob_to_render;
+  area = gimp_paint_core_get_paint_area (paint_core, drawable, paint_options);
+  ink->cur_blob = NULL;
+
+  if (! area)
+    return;
+
+  gimp_image_get_foreground (image, context, gimp_drawable_type (drawable), col);
+
+  /*  set the alpha channel  */
+  col[paint_core->canvas_buf->bytes - 1] = OPAQUE_OPACITY;
+
+  /*  color the pixels  */
+  color_pixels (temp_buf_data (paint_core->canvas_buf), col,
+                area->width * area->height, area->bytes);
+
+  gimp_paint_core_validate_canvas_tiles (paint_core,
+                                         paint_core->canvas_buf->x,
+                                         paint_core->canvas_buf->y,
+                                         paint_core->canvas_buf->width,
+                                         paint_core->canvas_buf->height);
+
+  /*  draw the blob directly to the canvas_tiles  */
+  pixel_region_init (&blob_maskPR, paint_core->canvas_tiles,
+                     paint_core->canvas_buf->x,
+                     paint_core->canvas_buf->y,
+                     paint_core->canvas_buf->width,
+                     paint_core->canvas_buf->height,
+                     TRUE);
+
+  render_blob (blob_to_render, &blob_maskPR);
+
+  /*  draw the canvas_buf using the just rendered canvas_tiles as mask */
+  pixel_region_init (&blob_maskPR, paint_core->canvas_tiles,
+                     paint_core->canvas_buf->x,
+                     paint_core->canvas_buf->y,
+                     paint_core->canvas_buf->width,
+                     paint_core->canvas_buf->height,
+                     FALSE);
+
+  gimp_paint_core_paste (paint_core, &blob_maskPR, drawable,
+                         GIMP_OPACITY_OPAQUE,
+                         gimp_context_get_opacity (context),
+                         gimp_context_get_paint_mode (context),
+                         GIMP_PAINT_CONSTANT);
+
+  if (blob_union)
+    g_free (blob_union);
+}
+
+static Blob *
+ink2_pen_ellipse (GimpInk2Options *options,
+                  gdouble         x_center,
+                  gdouble         y_center,
+                  gdouble         pressure,
+                  gdouble         xtilt,
+                  gdouble         ytilt,
+                  gdouble         velocity)
+{
+  BlobFunc blob_function;
+  gdouble  size;
+  gdouble  tsin, tcos;
+  gdouble  aspect, radmin;
+  gdouble  x,y;
+  gdouble  tscale;
+  gdouble  tscale_c;
+  gdouble  tscale_s;
+
+  /* Adjust the size depending on pressure. */
+
+  size = options->size * (1.0 + options->size_sensitivity *
+                          (2.0 * pressure - 1.0));
+
+  /* Adjust the size further depending on pointer velocity and
+   * velocity-sensitivity.  These 'magic constants' are 'feels
+   * natural' tigert-approved. --ADM
+   */
+
+  if (velocity < 3.0)
+    velocity = 3.0;
+
+#ifdef VERBOSE
+  g_printerr ("%g (%g) -> ", size, velocity);
+#endif
+
+  size = (options->vel_sensitivity *
+          ((4.5 * size) / (1.0 + options->vel_sensitivity * (2.0 * velocity)))
+          + (1.0 - options->vel_sensitivity) * size);
+
+#ifdef VERBOSE
+  g_printerr ("%g\n", (gfloat) size);
+#endif
+
+  /* Clamp resulting size to sane limits */
+
+  if (size > options->size * (1.0 + options->size_sensitivity))
+    size = options->size * (1.0 + options->size_sensitivity);
+
+  if (size * SUBSAMPLE < 1.0)
+    size = 1.0 / SUBSAMPLE;
+
+  /* Add brush angle/aspect to tilt vectorially */
+
+  /* I'm not happy with the way the brush widget info is combined with
+   * tilt info from the brush. My personal feeling is that
+   * representing both as affine transforms would make the most
+   * sense. -RLL
+   */
+
+  tscale   = options->tilt_sensitivity * 10.0;
+  tscale_c = tscale * cos (gimp_deg_to_rad (options->tilt_angle));
+  tscale_s = tscale * sin (gimp_deg_to_rad (options->tilt_angle));
+
+  x = (options->blob_aspect * cos (options->blob_angle) +
+       xtilt * tscale_c - ytilt * tscale_s);
+  y = (options->blob_aspect * sin (options->blob_angle) +
+       ytilt * tscale_c + xtilt * tscale_s);
+
+#ifdef VERBOSE
+  g_printerr ("angle %g aspect %g; %g %g; %g %g\n",
+              options->blob_angle, options->blob_aspect,
+              tscale_c, tscale_s, x, y);
+#endif
+
+  aspect = sqrt (x * x + y * y);
+
+  if (aspect != 0)
+    {
+      tcos = x / aspect;
+      tsin = y / aspect;
+    }
+  else
+    {
+      tsin = sin (options->blob_angle);
+      tcos = cos (options->blob_angle);
+    }
+
+  aspect = CLAMP (aspect, 1.0, 10.0);
+
+  radmin = MAX (1.0, SUBSAMPLE * size / aspect);
+
+  switch (options->blob_type)
+    {
+    case GIMP_INK_BLOB_TYPE_ELLIPSE:
+      blob_function = blob_ellipse;
+      break;
+
+    case GIMP_INK_BLOB_TYPE_SQUARE:
+      blob_function = blob_square;
+      break;
+
+    case GIMP_INK_BLOB_TYPE_DIAMOND:
+      blob_function = blob_diamond;
+      break;
+
+    default:
+      g_return_val_if_reached (NULL);
+      break;
+    }
+
+  return (* blob_function) (x_center * SUBSAMPLE,
+                            y_center * SUBSAMPLE,
+                            radmin * aspect * tcos,
+                            radmin * aspect * tsin,
+                            -radmin * tsin,
+                            radmin * tcos);
+}
+
+
+static void
+time_smoother_init (GimpInk2 *ink,
+                    guint32  initval)
+{
+  gint i;
+
+  ink->ts_index = 0;
+
+  for (i = 0; i < INK2_TIME_SMOOTHER_BUFFER; i++)
+    ink->ts_buffer[i] = initval;
+}
+
+static guint32
+time_smoother_result (GimpInk2 *ink)
+{
+  gint    i;
+  guint64 result = 0;
+
+  for (i = 0; i < INK2_TIME_SMOOTHER_BUFFER; i++)
+    result += ink->ts_buffer[i];
+
+  return (result / (guint64) INK2_TIME_SMOOTHER_BUFFER);
+}
+
+static void
+time_smoother_add (GimpInk2 *ink,
+                   guint32  value)
+{
+  guint64 long_value = (guint64) value;
+
+  /*  handle wrap-around of time values  */
+  if (long_value < ink->ts_buffer[ink->ts_index])
+    long_value += (guint64) + G_MAXUINT32;
+
+  ink->ts_buffer[ink->ts_index++] = long_value;
+
+  ink->ts_buffer[ink->ts_index++] = value;
+
+  if (ink->ts_index == INK2_TIME_SMOOTHER_BUFFER)
+    ink->ts_index = 0;
+}
+
+
+static void
+dist_smoother_init (GimpInk2 *ink,
+                    gdouble  initval)
+{
+  gint i;
+
+  ink->dt_index = 0;
+
+  for (i = 0; i < INK2_DIST_SMOOTHER_BUFFER; i++)
+    ink->dt_buffer[i] = initval;
+}
+
+static gdouble
+dist_smoother_result (GimpInk2 *ink)
+{
+  gint    i;
+  gdouble result = 0.0;
+
+  for (i = 0; i < INK2_DIST_SMOOTHER_BUFFER; i++)
+    result += ink->dt_buffer[i];
+
+  return (result / (gdouble) INK2_DIST_SMOOTHER_BUFFER);
+}
+
+static void
+dist_smoother_add (GimpInk2 *ink,
+                   gdouble  value)
+{
+  ink->dt_buffer[ink->dt_index++] = value;
+
+  if (ink->dt_index == INK2_DIST_SMOOTHER_BUFFER)
+    ink->dt_index = 0;
+}
+
+/**************************************************************/
+
+static void
+hist_init(GimpInk2 * ink, GimpCoords* coords)
+{
+  ink->hist_index = 0;
+  ink->hist_count = 0;
+  if (coords)
+    hist_add(ink, coords, 0);
+}
+
+#define HIST_IGNORE_THRESHOULD 0.0001
+
+static void
+hist_add(GimpInk2 *ink, GimpCoords* coords, gdouble speed)
+{
+  gdouble dist = 0;
+  if (coords) {
+    if (ink->hist_count > 0) {
+      gint prev_index = (ink->hist_index + INK2_HISTORY_BUFFER - 1) % INK2_HISTORY_BUFFER;
+      gdouble dist_x = coords->x - ink->hist_buffer[prev_index].x;
+      gdouble dist_y = coords->y - ink->hist_buffer[prev_index].y;
+      dist = sqrt(dist_x * dist_x + dist_y * dist_y);
+      if (dist < HIST_IGNORE_THRESHOULD)
+        return;
+    }
+    ink->hist_buffer[ink->hist_index] = *coords;
+    ink->hist_dist_buffer[ink->hist_index] = speed;
+    ink->hist_index ++;
+
+    if (ink->hist_count < INK2_HISTORY_BUFFER)
+      ink->hist_count ++;
+  
+    if (ink->hist_index == INK2_HISTORY_BUFFER)
+      ink->hist_index = 0;
+  }
+}
+
+static GimpCoords
+hist_result(GimpInk2 *ink, GimpInk2Options* options)
+{
+  gint i;
+  GimpCoords result;
+  result.x = result.y = 0.0;
+  gdouble scale_sum = 0.0;
+  if (ink->hist_count > 0) {
+    gint max_hist_count = MIN(ink->hist_count , options->compensation_hist_size);
+    gint cur_index = (ink->hist_index + INK2_HISTORY_BUFFER - 1) % INK2_HISTORY_BUFFER; 
+
+    gdouble gaussian_weight = 0.0;
+    gdouble gaussian_weight2 = options->compensation_rate_temperature * options->compensation_rate_temperature;
+    gdouble velocity_sum = 0.0;
+    if (gaussian_weight2 != 0.0)
+      gaussian_weight = 1 / (sqrt(2 * PI) * options->compensation_rate_temperature);
+
+    for (i = 0; i < max_hist_count; i ++, cur_index --) 
+      {
+        gdouble rate = 0;
+        if (cur_index == -1)
+          cur_index = INK2_HISTORY_BUFFER - 1;
+  
+        if (gaussian_weight2 != 0) 
+          {
+            /* We use gaussian function with velocity as a window function */
+            velocity_sum += ink->hist_dist_buffer[cur_index];
+            rate = gaussian_weight * exp(-velocity_sum*velocity_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;
+          }
+        else
+          {
+            rate = (i == 0) ? 1.0: 0.0;
+          }
+        scale_sum += rate;
+        result.x += rate * ink->hist_buffer[cur_index].x;
+        result.y += rate * ink->hist_buffer[cur_index].y;
+      }
+
+    if (scale_sum != 0.0)
+      {
+        result.x /= scale_sum;
+        result.y /= scale_sum;
+      }
+  }
+  return result;
+}
+
+/**************************************************************/
+
+/*********************************/
+/*  Rendering functions          */
+/*********************************/
+
+/* Some of this stuff should probably be combined with the
+ * code it was copied from in paint_core.c; but I wanted
+ * to learn this stuff, so I've kept it simple.
+ *
+ * The following only supports CONSTANT mode. Incremental
+ * would, I think, interact strangely with the way we
+ * do things. But it wouldn't be hard to implement at all.
+ */
+
+enum { ROW_START, ROW_STOP };
+
+/* The insertion sort here, for SUBSAMPLE = 8, tends to beat out
+ * qsort() by 4x with CFLAGS=-O2, 2x with CFLAGS=-g
+ */
+static void
+insert_sort (gint *data,
+             gint  n)
+{
+  gint i, j, k;
+  gint tmp1, tmp2;
+
+  for (i = 2; i < 2 * n; i += 2)
+    {
+      tmp1 = data[i];
+      tmp2 = data[i + 1];
+      j = 0;
+      while (data[j] < tmp1)
+        j += 2;
+
+      for (k = i; k > j; k -= 2)
+        {
+          data[k]     = data[k - 2];
+          data[k + 1] = data[k - 1];
+        }
+
+      data[j]     = tmp1;
+      data[j + 1] = tmp2;
+    }
+}
+
+static void
+fill_run (guchar *dest,
+          guchar  alpha,
+          gint    w)
+{
+  if (alpha == 255)
+    {
+      memset (dest, 255, w);
+    }
+  else
+    {
+      while (w--)
+        {
+          *dest = MAX (*dest, alpha);
+          dest++;
+        }
+    }
+}
+
+static void
+render_blob_line (Blob   *blob,
+                  guchar *dest,
+                  gint    x,
+                  gint    y,
+                  gint    width)
+{
+  gint  buf[4 * SUBSAMPLE];
+  gint *data    = buf;
+  gint  n       = 0;
+  gint  i, j;
+  gint  current = 0;  /* number of filled rows at this point
+                       * in the scan line
+                       */
+  gint last_x;
+
+  /* Sort start and ends for all lines */
+
+  j = y * SUBSAMPLE - blob->y;
+  for (i = 0; i < SUBSAMPLE; i++)
+    {
+      if (j >= blob->height)
+        break;
+
+      if ((j > 0) && (blob->data[j].left <= blob->data[j].right))
+        {
+          data[2 * n]                     = blob->data[j].left;
+          data[2 * n + 1]                 = ROW_START;
+          data[2 * SUBSAMPLE + 2 * n]     = blob->data[j].right;
+          data[2 * SUBSAMPLE + 2 * n + 1] = ROW_STOP;
+          n++;
+        }
+      j++;
+    }
+
+  /*   If we have less than SUBSAMPLE rows, compress */
+  if (n < SUBSAMPLE)
+    {
+      for (i = 0; i < 2 * n; i++)
+        data[2 * n + i] = data[2 * SUBSAMPLE + i];
+    }
+
+  /*   Now count start and end separately */
+  n *= 2;
+
+  insert_sort (data, n);
+
+  /* Discard portions outside of tile */
+
+  while ((n > 0) && (data[0] < SUBSAMPLE*x))
+    {
+      if (data[1] == ROW_START)
+        current++;
+      else
+        current--;
+      data += 2;
+      n--;
+    }
+
+  while ((n > 0) && (data[2*(n-1)] >= SUBSAMPLE*(x+width)))
+    n--;
+
+  /* Render the row */
+
+  last_x = 0;
+  for (i = 0; i < n;)
+    {
+      gint cur_x = data[2 * i] / SUBSAMPLE - x;
+      gint pixel;
+
+      /* Fill in portion leading up to this pixel */
+      if (current && cur_x != last_x)
+        fill_run (dest + last_x, (255 * current) / SUBSAMPLE, cur_x - last_x);
+
+      /* Compute the value for this pixel */
+      pixel = current * SUBSAMPLE;
+
+      while (i<n)
+        {
+          gint tmp_x = data[2 * i] / SUBSAMPLE;
+
+          if (tmp_x - x != cur_x)
+            break;
+
+          if (data[2 * i + 1] == ROW_START)
+            {
+              current++;
+              pixel += ((tmp_x + 1) * SUBSAMPLE) - data[2 * i];
+            }
+          else
+            {
+              current--;
+              pixel -= ((tmp_x + 1) * SUBSAMPLE) - data[2 * i];
+            }
+
+          i++;
+        }
+
+      dest[cur_x] = MAX (dest[cur_x], (pixel * 255) / (SUBSAMPLE * SUBSAMPLE));
+
+      last_x = cur_x + 1;
+    }
+
+  if (current != 0)
+    fill_run (dest + last_x, (255 * current)/ SUBSAMPLE, width - last_x);
+}
+
+static void
+render_blob (Blob        *blob,
+             PixelRegion *dest)
+{
+  gint      i;
+  gint      h;
+  guchar   *s;
+  gpointer  pr;
+
+  for (pr = pixel_regions_register (1, dest);
+       pr != NULL;
+       pr = pixel_regions_process (pr))
+    {
+      h = dest->h;
+      s = dest->data;
+
+      for (i=0; i<h; i++)
+        {
+          render_blob_line (blob, s,
+                            dest->x, dest->y + i, dest->w);
+          s += dest->rowstride;
+        }
+    }
+}
--- gimp-2.4.1/app/paint/gimpink2.h	Thu Jan  1 09:00:00 1970
+++ gimp-2.4.1_gpen_mixbrush/app/paint/gimpink2.h	Thu Nov  1 01:40:57 2007
@@ -0,0 +1,83 @@
+/* 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_INK2_H__
+#define  __GIMP_INK2_H__
+
+
+#include "gimppaintcore.h"
+#include "gimpink-blob.h"
+
+
+#define INK2_DIST_SMOOTHER_BUFFER 10
+#define INK2_TIME_SMOOTHER_BUFFER 10
+#define INK2_HISTORY_BUFFER 20
+
+
+#define GIMP_TYPE_INK2            (gimp_ink2_get_type ())
+#define GIMP_INK2(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_INK2, GimpInk2))
+#define GIMP_INK2_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_INK2, GimpInk2Class))
+#define GIMP_IS_INK2(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_INK2))
+#define GIMP_IS_INK2_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_INK2))
+#define GIMP_INK2_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_INK2, GimpInk2Class))
+
+
+typedef struct _GimpInk2Class GimpInk2Class;
+
+struct _GimpInk2
+{
+  GimpPaintCore  parent_instance;
+
+  Blob          *start_blob;   /*  starting blob (for undo)       */
+
+  Blob          *cur_blob;     /*  current blob                   */
+  Blob          *last_blob;    /*  blob for last cursor position  */
+
+  /* circular distance history buffer */
+  gdouble        dt_buffer[INK2_DIST_SMOOTHER_BUFFER];
+  gint           dt_index;
+
+  /* circular timing history buffer */
+  guint32        ts_buffer[INK2_TIME_SMOOTHER_BUFFER];
+  gint           ts_index;
+
+  GimpCoords     hist_buffer[INK2_HISTORY_BUFFER];
+  gdouble        hist_dist_buffer[INK2_HISTORY_BUFFER];
+  gint           hist_index;
+  gint           hist_count;
+
+  guint32        last_time;     /*  previous time of a motion event  */
+
+  GimpCoords     last_point;    /*  last compensated position */ 
+
+  gboolean       init_velocity;
+};
+
+struct _GimpInk2Class
+{
+  GimpPaintCoreClass  parent_class;
+};
+
+
+void    gimp_ink2_register (Gimp                      *gimp,
+                            GimpPaintRegisterCallback  callback);
+
+GType   gimp_ink2_get_type (void) G_GNUC_CONST;
+
+
+#endif  /*  __GIMP_INK2_H__  */
--- gimp-2.4.1/app/paint/gimpink2options.c	Thu Jan  1 09:00:00 1970
+++ gimp-2.4.1_gpen_mixbrush/app/paint/gimpink2options.c	Thu Nov  1 01:40:57 2007
@@ -0,0 +1,225 @@
+/* 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 "core/gimpdrawable.h"
+#include "core/gimppaintinfo.h"
+
+#include "gimpink2.h"
+#include "gimpink2options.h"
+#include "gimpink-blob.h"
+
+#include "gimp-intl.h"
+
+
+enum
+{
+  PROP_0,
+  PROP_SIZE,
+  PROP_TILT_ANGLE,
+  PROP_SIZE_SENSITIVITY,
+  PROP_VEL_SENSITIVITY,
+  PROP_TILT_SENSITIVITY,
+  PROP_BLOB_TYPE,
+  PROP_BLOB_ASPECT,
+  PROP_BLOB_ANGLE,
+  PROP_COMPENSATION_HIST_SIZE,
+  PROP_COMPENSATE_AT_LAST,
+  PROP_COMPENSATION_RATE_TEMPERATURE
+};
+
+
+static void   gimp_ink2_options_set_property (GObject      *object,
+                                              guint         property_id,
+                                              const GValue *value,
+                                              GParamSpec   *pspec);
+static void   gimp_ink2_options_get_property (GObject      *object,
+                                              guint         property_id,
+                                              GValue       *value,
+                                              GParamSpec   *pspec);
+
+
+G_DEFINE_TYPE (GimpInk2Options, gimp_ink2_options, GIMP_TYPE_PAINT_OPTIONS)
+
+
+static void
+gimp_ink2_options_class_init (GimpInk2OptionsClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->set_property = gimp_ink2_options_set_property;
+  object_class->get_property = gimp_ink2_options_get_property;
+
+  GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_SIZE,
+                                   "size", NULL,
+                                   0.0, 200.0, 16.0,
+                                   GIMP_PARAM_STATIC_STRINGS);
+  GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_TILT_ANGLE,
+                                   "tilt-angle", NULL,
+                                   -90.0, 90.0, 0.0,
+                                   GIMP_PARAM_STATIC_STRINGS);
+
+  GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_SIZE_SENSITIVITY,
+                                   "size-sensitivity", NULL,
+                                   0.0, 1.0, 1.0,
+                                   GIMP_PARAM_STATIC_STRINGS);
+  GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_VEL_SENSITIVITY,
+                                   "vel-sensitivity", NULL,
+                                   0.0, 1.0, 0.8,
+                                   GIMP_PARAM_STATIC_STRINGS);
+  GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_TILT_SENSITIVITY,
+                                   "tilt-sensitivity", NULL,
+                                   0.0, 1.0, 0.4,
+                                   GIMP_PARAM_STATIC_STRINGS);
+
+  GIMP_CONFIG_INSTALL_PROP_ENUM (object_class, PROP_BLOB_TYPE,
+                                 "blob-type", NULL,
+                                 GIMP_TYPE_INK_BLOB_TYPE,
+                                 GIMP_INK_BLOB_TYPE_ELLIPSE,
+                                 GIMP_PARAM_STATIC_STRINGS);
+  GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_BLOB_ASPECT,
+                                   "blob-aspect", NULL,
+                                   1.0, 10.0, 1.0,
+                                   GIMP_PARAM_STATIC_STRINGS);
+  GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_BLOB_ANGLE,
+                                   "blob-angle", NULL,
+                                   -90.0, 90.0, 0.0,
+                                   GIMP_PARAM_STATIC_STRINGS);
+
+  GIMP_CONFIG_INSTALL_PROP_INT    (object_class, PROP_COMPENSATION_HIST_SIZE,
+                                   "compensation-history-size", NULL,
+                                   1, INK2_HISTORY_BUFFER, MIN(20, INK2_HISTORY_BUFFER), 0);
+  GIMP_CONFIG_INSTALL_PROP_BOOLEAN(object_class, PROP_COMPENSATE_AT_LAST,
+                                   "compensate-at-last", NULL,
+                                   FALSE, 0);
+  GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_COMPENSATION_RATE_TEMPERATURE,
+                                   "compensation-rate-temperature", NULL,
+                                   0.0, 1000, 25,
+                                   0);
+}
+
+static void
+gimp_ink2_options_init (GimpInk2Options *options)
+{
+}
+
+static void
+gimp_ink2_options_set_property (GObject      *object,
+                               guint         property_id,
+                               const GValue *value,
+                               GParamSpec   *pspec)
+{
+  GimpInk2Options *options = GIMP_INK2_OPTIONS (object);
+
+  switch (property_id)
+    {
+    case PROP_SIZE:
+      options->size = g_value_get_double (value);
+      break;
+    case PROP_TILT_ANGLE:
+      options->tilt_angle = g_value_get_double (value);
+      break;
+    case PROP_SIZE_SENSITIVITY:
+      options->size_sensitivity = g_value_get_double (value);
+      break;
+    case PROP_VEL_SENSITIVITY:
+      options->vel_sensitivity = g_value_get_double (value);
+      break;
+    case PROP_TILT_SENSITIVITY:
+      options->tilt_sensitivity = g_value_get_double (value);
+      break;
+    case PROP_BLOB_TYPE:
+      options->blob_type = g_value_get_enum (value);
+      break;
+    case PROP_BLOB_ASPECT:
+      options->blob_aspect = g_value_get_double (value);
+      break;
+    case PROP_BLOB_ANGLE:
+      options->blob_angle = g_value_get_double (value);
+      break;
+    case PROP_COMPENSATION_HIST_SIZE:
+      options->compensation_hist_size = g_value_get_int (value);
+      break;
+    case PROP_COMPENSATE_AT_LAST:
+      options->compensate_at_last = g_value_get_boolean (value);
+      break;
+    case PROP_COMPENSATION_RATE_TEMPERATURE:
+      options->compensation_rate_temperature = g_value_get_double (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+static void
+gimp_ink2_options_get_property (GObject    *object,
+                               guint       property_id,
+                               GValue     *value,
+                               GParamSpec *pspec)
+{
+  GimpInk2Options *options = GIMP_INK2_OPTIONS (object);
+
+  switch (property_id)
+    {
+    case PROP_SIZE:
+      g_value_set_double (value, options->size);
+      break;
+    case PROP_TILT_ANGLE:
+      g_value_set_double (value, options->tilt_angle);
+      break;
+    case PROP_SIZE_SENSITIVITY:
+      g_value_set_double (value, options->size_sensitivity);
+      break;
+    case PROP_VEL_SENSITIVITY:
+      g_value_set_double (value, options->vel_sensitivity);
+      break;
+    case PROP_TILT_SENSITIVITY:
+      g_value_set_double (value, options->tilt_sensitivity);
+      break;
+    case PROP_BLOB_TYPE:
+      g_value_set_enum (value, options->blob_type);
+      break;
+    case PROP_BLOB_ASPECT:
+      g_value_set_double (value, options->blob_aspect);
+      break;
+    case PROP_BLOB_ANGLE:
+      g_value_set_double (value, options->blob_angle);
+      break;
+    case PROP_COMPENSATION_HIST_SIZE:
+      g_value_set_int (value, options->compensation_hist_size);
+      break;
+    case PROP_COMPENSATE_AT_LAST:
+      g_value_set_boolean (value, options->compensate_at_last);
+      break;
+    case PROP_COMPENSATION_RATE_TEMPERATURE:
+      g_value_set_double (value, options->compensation_rate_temperature);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
--- gimp-2.4.1/app/paint/gimpink2options.h	Thu Jan  1 09:00:00 1970
+++ gimp-2.4.1_gpen_mixbrush/app/paint/gimpink2options.h	Thu Nov  1 01:40:57 2007
@@ -0,0 +1,65 @@
+/* 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_INK2_OPTIONS_H__
+#define  __GIMP_INK2_OPTIONS_H__
+
+
+#include "gimppaintoptions.h"
+
+
+#define GIMP_TYPE_INK2_OPTIONS            (gimp_ink2_options_get_type ())
+#define GIMP_INK2_OPTIONS(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_INK2_OPTIONS, GimpInk2Options))
+#define GIMP_INK2_OPTIONS_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_INK2_OPTIONS, GimpInk2OptionsClass))
+#define GIMP_IS_INK2_OPTIONS(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_INK2_OPTIONS))
+#define GIMP_IS_INK2_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_INK2_OPTIONS))
+#define GIMP_INK2_OPTIONS_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_INK2_OPTIONS, GimpInk2OptionsClass))
+
+
+typedef struct _GimpInk2OptionsClass GimpInk2OptionsClass;
+
+struct _GimpInk2Options
+{
+  GimpPaintOptions  parent_instance;
+
+  gdouble           size;
+  gdouble           tilt_angle;
+
+  gdouble           size_sensitivity;
+  gdouble           vel_sensitivity;
+  gdouble           tilt_sensitivity;
+
+  GimpInkBlobType   blob_type;
+  gdouble           blob_aspect;
+  gdouble           blob_angle;
+
+  gint              compensation_hist_size;
+  gboolean          compensate_at_last;
+  gdouble           compensation_rate_temperature;
+};
+
+struct _GimpInk2OptionsClass
+{
+  GimpPaintOptionsClass  parent_instance;
+};
+
+
+GType   gimp_ink2_options_get_type (void) G_GNUC_CONST;
+
+
+#endif  /*  __GIMP_INK2_OPTIONS_H__  */
--- gimp-2.4.1/app/paint/gimpink2undo.c	Thu Jan  1 09:00:00 1970
+++ gimp-2.4.1_gpen_mixbrush/app/paint/gimpink2undo.c	Thu Nov  1 01:40:57 2007
@@ -0,0 +1,169 @@
+/* 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 "paint-types.h"
+
+#include "gimpink2.h"
+#include "gimpink-blob.h"
+#include "gimpink2undo.h"
+
+
+static GObject * gimp_ink2_undo_constructor  (GType                  type,
+                                              guint                  n_params,
+                                              GObjectConstructParam *params);
+
+static void      gimp_ink2_undo_pop          (GimpUndo              *undo,
+                                              GimpUndoMode           undo_mode,
+                                              GimpUndoAccumulator   *accum);
+static void      gimp_ink2_undo_free         (GimpUndo              *undo,
+                                              GimpUndoMode           undo_mode);
+
+
+G_DEFINE_TYPE (GimpInk2Undo, gimp_ink2_undo, GIMP_TYPE_PAINT_CORE_UNDO)
+
+#define parent_class gimp_ink2_undo_parent_class
+
+
+static void
+gimp_ink2_undo_class_init (GimpInk2UndoClass *klass)
+{
+  GObjectClass  *object_class = G_OBJECT_CLASS (klass);
+  GimpUndoClass *undo_class   = GIMP_UNDO_CLASS (klass);
+
+  object_class->constructor = gimp_ink2_undo_constructor;
+
+  undo_class->pop           = gimp_ink2_undo_pop;
+  undo_class->free          = gimp_ink2_undo_free;
+}
+
+static void
+gimp_ink2_undo_init (GimpInk2Undo *undo)
+{
+}
+
+static GObject *
+gimp_ink2_undo_constructor (GType                  type,
+                            guint                  n_params,
+                            GObjectConstructParam *params)
+{
+  GObject      *object;
+  GimpInk2Undo *ink_undo;
+  GimpInk2     *ink;
+
+  object = G_OBJECT_CLASS (parent_class)->constructor (type, n_params, params);
+
+  ink_undo = GIMP_INK2_UNDO (object);
+
+  g_assert (GIMP_IS_INK2 (GIMP_PAINT_CORE_UNDO (ink_undo)->paint_core));
+
+  ink = GIMP_INK2 (GIMP_PAINT_CORE_UNDO (ink_undo)->paint_core);
+
+  if (ink->start_blob)
+    ink_undo->last_blob = blob_duplicate (ink->start_blob);
+
+  memcpy (ink_undo->dt_buffer, ink->dt_buffer,
+          sizeof (ink_undo->dt_buffer));
+
+  ink_undo->dt_index = ink->dt_index;
+
+  memcpy (ink_undo->ts_buffer, ink->ts_buffer,
+          sizeof (ink_undo->ts_buffer));
+
+  ink_undo->ts_index = ink->ts_index;
+
+  ink_undo->last_time = ink->last_time;
+
+  ink_undo->init_velocity = ink->init_velocity;
+
+  return object;
+}
+
+static void
+gimp_ink2_undo_pop (GimpUndo              *undo,
+                   GimpUndoMode           undo_mode,
+                   GimpUndoAccumulator   *accum)
+{
+  GimpInk2Undo *ink_undo = GIMP_INK2_UNDO (undo);
+
+  GIMP_UNDO_CLASS (parent_class)->pop (undo, undo_mode, accum);
+
+  if (GIMP_PAINT_CORE_UNDO (ink_undo)->paint_core)
+    {
+      GimpInk2 *ink = GIMP_INK2 (GIMP_PAINT_CORE_UNDO (ink_undo)->paint_core);
+      Blob    *tmp_blob;
+      gint     tmp_int;
+      gdouble  tmp_double;
+      guint32  tmp_int_buf[INK2_DIST_SMOOTHER_BUFFER];
+      gdouble  tmp_double_buf[INK2_DIST_SMOOTHER_BUFFER];
+
+      tmp_blob = ink->last_blob;
+      ink->last_blob = ink_undo->last_blob;
+      ink_undo->last_blob = tmp_blob;
+
+      memcpy (tmp_double_buf, ink->dt_buffer,
+              sizeof (tmp_double_buf));
+      memcpy (ink->dt_buffer, ink_undo->dt_buffer,
+              sizeof (tmp_double_buf));
+      memcpy (ink_undo->dt_buffer, tmp_double_buf,
+              sizeof (tmp_double_buf));
+
+      tmp_int = ink->dt_index;
+      ink->dt_index = ink_undo->dt_index;
+      ink_undo->dt_index = tmp_int;
+
+      memcpy (tmp_int_buf, ink->ts_buffer,
+              sizeof (tmp_int_buf));
+      memcpy (ink->ts_buffer, ink_undo->ts_buffer,
+              sizeof (tmp_int_buf));
+      memcpy (ink_undo->ts_buffer, tmp_int_buf,
+              sizeof (tmp_int_buf));
+
+      tmp_int = ink->ts_index;
+      ink->ts_index = ink_undo->ts_index;
+      ink_undo->ts_index = tmp_int;
+
+      tmp_double = ink->last_time;
+      ink->last_time = ink_undo->last_time;
+      ink_undo->last_time = tmp_double;
+
+      tmp_int = ink->init_velocity;
+      ink->init_velocity = ink_undo->init_velocity;
+      ink_undo->init_velocity = tmp_int;
+    }
+}
+
+static void
+gimp_ink2_undo_free (GimpUndo     *undo,
+                    GimpUndoMode  undo_mode)
+{
+  GimpInk2Undo *ink_undo = GIMP_INK2_UNDO (undo);
+
+  if (ink_undo->last_blob)
+    {
+      g_free (ink_undo->last_blob);
+      ink_undo->last_blob = NULL;
+    }
+
+  GIMP_UNDO_CLASS (parent_class)->free (undo, undo_mode);
+}
--- gimp-2.4.1/app/paint/gimpink2undo.h	Thu Jan  1 09:00:00 1970
+++ gimp-2.4.1_gpen_mixbrush/app/paint/gimpink2undo.h	Thu Nov  1 01:40:57 2007
@@ -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.
+ */
+
+#ifndef __GIMP_INK2_UNDO_H__
+#define __GIMP_INK2_UNDO_H__
+
+
+#include "gimppaintcoreundo.h"
+#include "gimpink2.h"
+
+
+#define GIMP_TYPE_INK2_UNDO            (gimp_ink2_undo_get_type ())
+#define GIMP_INK2_UNDO(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_INK2_UNDO, GimpInk2Undo))
+#define GIMP_INK2_UNDO_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_INK2_UNDO, GimpInk2UndoClass))
+#define GIMP_IS_INK2_UNDO(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_INK2_UNDO))
+#define GIMP_IS_INK2_UNDO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_INK2_UNDO))
+#define GIMP_INK2_UNDO_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_INK2_UNDO, GimpInk2UndoClass))
+
+
+typedef struct _GimpInk2UndoClass GimpInk2UndoClass;
+
+struct _GimpInk2Undo
+{
+  GimpPaintCoreUndo  parent_instance;
+
+  Blob              *last_blob;
+
+  gdouble            dt_buffer[INK2_DIST_SMOOTHER_BUFFER];
+  gint               dt_index;
+
+  guint32            ts_buffer[INK2_TIME_SMOOTHER_BUFFER];
+  gint               ts_index;
+
+  gdouble            last_time;
+
+  gboolean           init_velocity;
+};
+
+struct _GimpInk2UndoClass
+{
+  GimpPaintCoreUndoClass  parent_class;
+};
+
+
+GType   gimp_ink2_undo_get_type (void) G_GNUC_CONST;
+
+
+#endif /* __GIMP_INK2_UNDO_H__ */
--- gimp-2.4.1/app/paint/gimpmixbrush.c	Thu Jan  1 09:00:00 1970
+++ gimp-2.4.1_gpen_mixbrush/app/paint/gimpmixbrush.c	Sat Nov  3 11:39:59 2007
@@ -0,0 +1,680 @@
+/* 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 "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 "gimpmixbrush.h"
+#include "gimpmixbrushoptions.h"
+
+#include "gimp-intl.h"
+
+
+/* Coords history */
+
+typedef struct _CoordsHistory
+{
+  GimpCoords coords;
+  GimpCoords prev_coords;
+  gdouble    pixel_dist;
+  guchar     color[MAX_CHANNELS];
+  gdouble    opacity;
+} CoordsHistory;
+
+
+static void    gimp_mixbrush_finalize        (GObject           *object);
+
+static void    gimp_mixbrush_start           (GimpPaintCore     *paint_core,
+                                              GimpDrawable      *drawable,
+                                              GimpPaintOptions  *paint_options);
+
+static void    gimp_mixbrush_finish          (GimpPaintCore     *paint_core,
+                                              GimpDrawable      *drawable,
+                                              GimpPaintOptions  *paint_options);
+
+static void    gimp_mixbrush_paint           (GimpPaintCore     *paint_core,
+                                              GimpDrawable      *drawable,
+                                              GimpPaintOptions  *paint_options,
+                                              GimpPaintState     paint_state,
+                                              guint32            time);
+
+static void    gimp_mixbrush_motion          (GimpPaintCore     *paint_core,
+                                              GimpDrawable      *drawable,
+                                              GimpPaintOptions  *paint_options);
+
+static void    _gimp_mixbrush_motion         (GimpPaintCore     *paint_core,
+                                              GimpDrawable      *drawable,
+                                              GimpPaintOptions  *paint_options,
+                                              gdouble           opacity);
+
+
+static void    gimp_mixbrush_paste_canvas    (GimpPaintCore    *paint_core,
+                                              GimpDrawable     *drawable,
+                                              GimpPaintOptions *paint_options);
+
+static void    coords_history_free           (CoordsHistory    *history,
+                                              gpointer          dummy);
+
+static inline gboolean pick_up_avarage_color (GimpPickable     *pickable,
+                                              GimpBrushCore    *brush_core,
+                                              gint              x,
+                                              gint              y,
+                                              gint              size_limit,
+                                              guchar           *color);
+
+static inline void color_to_alpha            (GimpRGB          *src,
+                                              const GimpRGB    *color);
+
+
+G_DEFINE_TYPE (GimpMixbrush, gimp_mixbrush, GIMP_TYPE_PAINTBRUSH)
+
+#define parent_class gimp_mixbrush_parent_class
+
+
+void
+gimp_mixbrush_register (Gimp                      *gimp,
+                        GimpPaintRegisterCallback  callback)
+{
+  (* callback) (gimp,
+                GIMP_TYPE_MIXBRUSH,
+                GIMP_TYPE_MIXBRUSH_OPTIONS,
+                "gimp-mixbrush",
+                _("Mixbrush"),
+                "gimp-tool-mixbrush");
+}
+
+static void
+gimp_mixbrush_class_init (GimpMixbrushClass *klass)
+{
+  GimpPaintCoreClass *paint_core_class = GIMP_PAINT_CORE_CLASS (klass);
+  GimpBrushCoreClass *brush_core_class = GIMP_BRUSH_CORE_CLASS (klass);
+
+  paint_core_class->paint              = gimp_mixbrush_paint;
+  G_OBJECT_CLASS (klass)->finalize     = gimp_mixbrush_finalize;
+
+  brush_core_class->handles_changing_brush = TRUE;
+}
+
+static void
+gimp_mixbrush_init (GimpMixbrush *mixbrush)
+{
+  mixbrush->history = NULL;
+}
+
+static void
+gimp_mixbrush_finalize (GObject *object)
+{
+  GimpMixbrush *mixbrush = GIMP_MIXBRUSH (object);
+
+  if (mixbrush->history) {
+    g_list_foreach (mixbrush->history, (GFunc)coords_history_free, NULL);
+    g_list_free (mixbrush->history);
+  }
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gimp_mixbrush_paint (GimpPaintCore    *paint_core,
+                     GimpDrawable     *drawable,
+                     GimpPaintOptions *paint_options,
+                     GimpPaintState    paint_state,
+                     guint32           time)
+{
+  switch (paint_state)
+    {
+    case GIMP_PAINT_STATE_INIT:
+      gimp_mixbrush_start (paint_core, drawable, paint_options);
+      GIMP_PAINT_CORE_CLASS (parent_class)->paint (paint_core, drawable,
+                                                   paint_options,
+                                                   paint_state, time);
+      break;
+
+    case GIMP_PAINT_STATE_MOTION:
+      gimp_mixbrush_motion (paint_core, drawable, paint_options);
+      break;
+
+    case GIMP_PAINT_STATE_FINISH:
+      gimp_mixbrush_finish (paint_core, drawable, paint_options);
+      GIMP_PAINT_CORE_CLASS (parent_class)->paint (paint_core, drawable,
+                                                   paint_options,
+                                                   paint_state, time);
+      break;
+
+    default:
+      break;
+    }
+}
+
+static void
+gimp_mixbrush_start (GimpPaintCore    *paint_core,
+                     GimpDrawable     *drawable,
+                     GimpPaintOptions *paint_options)
+{
+  GimpMixbrush             *mixbrush = GIMP_MIXBRUSH (paint_core);
+  GimpContext              *context  = GIMP_CONTEXT (paint_options);
+  GimpImage                *image;
+  guchar                   *color    = mixbrush->color;
+
+  image = gimp_item_get_image (GIMP_ITEM (drawable));
+  gimp_image_get_foreground (image, context, gimp_drawable_type (drawable), color);
+
+  switch (gimp_drawable_type_without_alpha (drawable))
+    {
+    case GIMP_RGB:
+      mixbrush->alpha_pix = ALPHA_PIX;
+      break;
+    case GIMP_GRAY:
+      mixbrush->alpha_pix = ALPHA_G_PIX;
+      break;
+    case GIMP_INDEXED:
+    default:
+      mixbrush->alpha_pix = ALPHA_I_PIX;
+    }
+
+  mixbrush->error[0] = 0;
+  mixbrush->error[1] = 0;
+  mixbrush->error[2] = 0;
+  mixbrush->error[3] = 0;
+}
+
+static void
+gimp_mixbrush_finish (GimpPaintCore    *paint_core,
+                      GimpDrawable     *drawable,
+                      GimpPaintOptions *paint_options)
+{
+  GimpMixbrush *mixbrush = GIMP_MIXBRUSH (paint_core);
+
+  if (!(GIMP_MIXBRUSH_OPTIONS (paint_options)->tail) && mixbrush->history)
+    {
+      g_list_foreach (mixbrush->history, (GFunc)coords_history_free, NULL);
+      g_list_free (mixbrush->history);
+      mixbrush->history = NULL;
+
+      return;
+    }
+
+  while (mixbrush->history)
+    gimp_mixbrush_paste_canvas (paint_core, drawable, paint_options);
+}
+
+static void
+gimp_mixbrush_motion (GimpPaintCore    *paint_core,
+                      GimpDrawable     *drawable,
+                      GimpPaintOptions *paint_options)
+{
+  _gimp_mixbrush_motion (paint_core, drawable, paint_options, GIMP_OPACITY_OPAQUE);
+}
+
+void
+_gimp_mixbrush_motion (GimpPaintCore    *paint_core,
+                       GimpDrawable     *drawable,
+                       GimpPaintOptions *paint_options,
+                       gdouble           opacity)
+{
+  GimpImage                *image;
+  GimpMixbrush             *mixbrush         = GIMP_MIXBRUSH (paint_core);
+  GimpMixbrushOptions      *mixbrush_options = GIMP_MIXBRUSH_OPTIONS (paint_options);
+  CoordsHistory            *history;
+
+  image = gimp_item_get_image (GIMP_ITEM (drawable));
+
+  opacity *= gimp_paint_options_get_fade (paint_options, image,
+                                          paint_core->pixel_dist);
+
+  /* Add history item */
+  history = g_new (CoordsHistory, 1);
+  history->coords = paint_core->cur_coords;
+  history->prev_coords = paint_core->last_coords;
+  history->pixel_dist = paint_core->pixel_dist;
+  {
+    GimpPickable *pickable;
+    GimpItem     *item = GIMP_ITEM (drawable);
+    gint offset_x, offset_y;
+    gboolean use_merged;
+
+    offset_x = CLAMP ((gint) history->coords.x, 0, gimp_item_width (item) - 1);
+    offset_y = CLAMP ((gint) history->coords.y, 0, gimp_item_height (item) - 1);
+
+    if ((use_merged = (mixbrush_options->merged && GIMP_IS_LAYER (drawable))))
+      {
+        gint item_offset_x, item_offset_y;
+
+        gimp_item_offsets (item, &item_offset_x, &item_offset_y);
+        offset_x += item_offset_x;
+        offset_y += item_offset_y;
+
+        pickable = GIMP_PICKABLE (image->projection);
+        gimp_pickable_flush (pickable);
+      }
+    else
+      pickable = GIMP_PICKABLE (drawable);
+
+    if (mixbrush_options->sample_size_limit > 1.0)
+      pick_up_avarage_color (pickable,
+                             GIMP_BRUSH_CORE (paint_core),
+                             offset_x, offset_y,
+                             mixbrush_options->sample_size_limit,
+                             history->color);
+    else
+      gimp_pickable_get_pixel_at (pickable,
+                                  offset_x, offset_y,
+                                  history->color);
+  }
+  history->opacity = opacity;
+  mixbrush->history = g_list_append (mixbrush->history, history);
+
+  /* Process a history item */
+  if (g_list_length (mixbrush->history) > mixbrush_options->delay)
+    gimp_mixbrush_paste_canvas (paint_core, drawable, paint_options);
+}
+
+static void
+gimp_mixbrush_paste_canvas (GimpPaintCore    *paint_core,
+                            GimpDrawable     *drawable,
+                            GimpPaintOptions *paint_options)
+{
+  GimpBrushCore            *brush_core       = GIMP_BRUSH_CORE (paint_core);
+  GimpContext              *context          = GIMP_CONTEXT (paint_options);
+  GimpPressureOptions      *pressure_options = paint_options->pressure_options;
+  GimpImage                *image;
+  TempBuf                  *area;
+  GimpMixbrush             *mixbrush         = GIMP_MIXBRUSH (paint_core);
+  guchar                   *color            = mixbrush->color;
+  GimpMixbrushOptions      *mixbrush_options = GIMP_MIXBRUSH_OPTIONS (paint_options);
+  GimpPaintApplicationMode  paint_appl_mode;
+  CoordsHistory            *history;
+  GimpCoords                orig_coords;
+  GimpCoords                prev_coords;
+
+  if (mixbrush->history == NULL)
+    return;
+
+  history = mixbrush->history->data;
+  mixbrush->history = g_list_delete_link (mixbrush->history, mixbrush->history);
+
+  if (history->opacity != 0.0)
+    {
+      image = gimp_item_get_image (GIMP_ITEM (drawable));
+
+      paint_appl_mode = paint_options->application_mode;
+
+      orig_coords = paint_core->cur_coords;
+      prev_coords = paint_core->last_coords;
+      paint_core->cur_coords = history->coords;
+      paint_core->last_coords = history->prev_coords;
+      area = gimp_paint_core_get_paint_area (paint_core, drawable, paint_options);
+
+      if (area) {
+        /* Preset the hidden color */
+        guchar hidden_color[4] = "\xff\xff\xff\xff"; /* white */
+
+        if (mixbrush_options->hidden_color == GIMP_HIDDEN_COLOR_BACKGROUND)
+          gimp_image_get_background (image, context,
+                                     gimp_drawable_type (drawable), hidden_color);
+
+        /* Mix brush color with underlying canvas color */
+        if (mixbrush_options->dryout > 0 || mixbrush_options->canvas_color_rate > 0.0)
+          {
+            guchar color_at_pos[4];
+            guchar color_at_pos2[4];
+            gboolean result;
+            int i;
+
+            /* Add original paint brush color */
+            if (mixbrush_options->original_color_rate > 0.0)
+              {
+                guchar orig_color[MAX_CHANNELS];
+                gdouble original_color_rate = mixbrush_options->original_color_rate;
+                gdouble previous_color_rate;
+                gdouble pressure_rate = mixbrush_options->original_color_pressure_rate;
+
+                if (pressure_rate != 0.0)
+                  {
+                    original_color_rate -= fabs (pressure_rate) *
+                      (pressure_rate < 0.0 ? history->coords.pressure : 1 - history->coords.pressure);
+                    if (original_color_rate < 0.0)
+                      original_color_rate = 0.0;
+                  }
+                previous_color_rate = 1 - original_color_rate;
+
+                gimp_image_get_foreground (image, context, gimp_drawable_type (drawable), orig_color);
+                for (i = 0; i < MAX_CHANNELS - 1; i ++) {
+                  color[i] = (guchar)(color[i] * previous_color_rate +
+                                      orig_color[i] * original_color_rate);
+                }
+              }
+
+            /* Get canvas color */
+            {
+              GimpPickable *pickable;
+              GimpItem     *item = GIMP_ITEM (drawable);
+              gint offset_x, offset_y;
+              gboolean use_merged;
+
+              offset_x = CLAMP ((gint) history->coords.x, 0, gimp_item_width (item) - 1);
+              offset_y = CLAMP ((gint) history->coords.y, 0, gimp_item_height (item) - 1);
+
+              if ((use_merged = (mixbrush_options->merged && GIMP_IS_LAYER (drawable))))
+                {
+                  gint item_offset_x, item_offset_y;
+
+                  gimp_item_offsets (item, &item_offset_x, &item_offset_y);
+                  offset_x += item_offset_x;
+                  offset_y += item_offset_y;
+
+                  pickable = GIMP_PICKABLE (image->projection);
+                  gimp_pickable_flush (pickable);
+                }
+              else
+                pickable = GIMP_PICKABLE (drawable);
+
+              if (mixbrush_options->sample_size_limit > 1.0)
+                result = pick_up_avarage_color (pickable,
+                                                brush_core,
+                                                offset_x, offset_y,
+                                                mixbrush_options->sample_size_limit,
+                                                color_at_pos);
+              else
+                result = gimp_pickable_get_pixel_at (pickable,
+                                                     offset_x, offset_y,
+                                                     color_at_pos);
+
+              if (result)
+                {
+                  gdouble mixed_color[4];
+                  gdouble bleed = mixbrush_options->bleed;
+                  gdouble pressure_rate = mixbrush_options->bleed_pressure_rate;
+
+                  if (mixbrush_options->hidden_color != GIMP_HIDDEN_COLOR_NORMAL &&
+                      (use_merged || gimp_drawable_has_alpha (drawable)))
+                    {
+                      gdouble src_opacity;
+
+                      src_opacity = (gdouble)color_at_pos[mixbrush->alpha_pix] / 255.0;
+
+                      for (i = 0; i < mixbrush->alpha_pix; i++)
+                        color_at_pos[i] = color_at_pos[i] * src_opacity + (gdouble) hidden_color[i] * (1.0 - src_opacity);
+
+                      src_opacity = (gdouble)history->color[mixbrush->alpha_pix] / 255.0;
+
+                      for (i = 0; i < mixbrush->alpha_pix; i++)
+                        color_at_pos2[i] = history->color[i] * src_opacity + (gdouble) hidden_color[i] * (1.0 - src_opacity);
+                    }
+                  else
+                    g_memmove (color_at_pos2, history->color, sizeof (guchar) * MAX_CHANNELS);
+
+                  color_at_pos[mixbrush->alpha_pix] = OPAQUE_OPACITY;
+                  color_at_pos2[mixbrush->alpha_pix] = OPAQUE_OPACITY;
+
+                  if (pressure_rate != 0.0)
+                    {
+                      bleed -= MIXBRUSH_BLEED_MAX_VALUE * fabs (pressure_rate) *
+                        (pressure_rate < 0.0 ? history->coords.pressure : 1 - history->coords.pressure);
+                      if (bleed < 0.0)
+                        bleed = 0.0;
+                    }
+
+                  for (i = 0; i < 4; i ++)
+                    {
+                      mixed_color[i] = CLAMP (color_at_pos[i] * (1.0 - bleed) +
+                                              color_at_pos2[i] * bleed + mixbrush->error[i],
+                                              0, 255);
+                      color_at_pos[i] = floor( mixed_color[i] + 0.5);
+                      mixbrush->error[i] = mixed_color[i] - color_at_pos[i];
+                    }
+                }
+            }
+
+            /* Mix current brush color with the canvas color */
+            if (result)
+              {
+                gdouble canvas_color_rate = mixbrush_options->canvas_color_rate;
+#if 1
+                gdouble previous_color_rate = 1 - canvas_color_rate;
+                gdouble pressure_rate = mixbrush_options->canvas_color_pressure_rate;
+
+                if (pressure_rate != 0.0)
+                  {
+                    previous_color_rate -=
+                      fabs (pressure_rate) * (pressure_rate < 0.0 ? 1 - history->coords.pressure : history->coords.pressure);
+                    if (previous_color_rate < 0.0)
+                      previous_color_rate = 0.0;
+                  }
+
+                canvas_color_rate = 1 - previous_color_rate;
+#else
+                gdouble previous_color_rate;
+                gdouble pressure_rate = mixbrush_options->canvas_color_pressure_rate;
+
+                if (pressure_rate != 0.0)
+                  {
+                    canvas_color_rate -=
+                      fabs (pressure_rate) * (pressure_rate < 0.0 ? history->coords.pressure : 1 - history->coords.pressure);
+                    if (canvas_color_rate < 0.0)
+                      canvas_color_rate = 0.0;
+                  }
+
+                previous_color_rate = 1 - canvas_color_rate;
+#endif
+
+                /*g_printerr("P %f /  C %f\n", previous_color_rate, canvas_color_rate);*/
+
+                if (mixbrush_options->dryout > 0)
+                  {
+                    if (history->pixel_dist >= mixbrush_options->dryout)
+                      previous_color_rate = 0.0;
+                    else
+                      previous_color_rate *= 1.0 - history->pixel_dist / mixbrush_options->dryout;
+
+                    canvas_color_rate = 1 - previous_color_rate;
+                  }
+
+                for (i = 0; i < MAX_CHANNELS - 1; i ++) {
+                  color[i] = (guchar)(color[i] * previous_color_rate +
+                                      color_at_pos[i] * canvas_color_rate);
+                }
+              }
+          }
+
+        //paint_appl_mode = GIMP_PAINT_INCREMENTAL;
+
+        if (mixbrush_options->remove_color &&
+            gimp_drawable_type_without_alpha (drawable) == GIMP_RGB_IMAGE)
+          {
+            /* Remove color */
+            GimpRGB color1, color2;
+            guchar paint_color[4];
+
+            gimp_rgba_set_uchar (&color1,
+                                 color[0], color[1], color[2], OPAQUE_OPACITY);
+            gimp_rgba_set_uchar (&color2,
+                                 hidden_color[0], hidden_color[1], hidden_color[2], OPAQUE_OPACITY);
+
+            color_to_alpha (&color1, &color2);
+
+            history->opacity *= color1.a;
+
+            gimp_rgba_get_uchar (&color1,
+                                 &paint_color[0], &paint_color[1], &paint_color[2], &paint_color[3]);
+            paint_color[mixbrush->alpha_pix] = OPAQUE_OPACITY;
+
+            color_pixels (temp_buf_data (area), paint_color,
+                          area->width * area->height,
+                          area->bytes);
+          }
+        else
+          {
+            color[mixbrush->alpha_pix] = OPAQUE_OPACITY;
+
+            color_pixels (temp_buf_data (area), color,
+                          area->width * area->height,
+                          area->bytes);
+          }
+
+        if (pressure_options->opacity)
+          history->opacity *= PRESSURE_SCALE * history->coords.pressure;
+
+        /* finally, let the brush core paste the colored area on the canvas */
+        gimp_brush_core_paste_canvas (brush_core, drawable,
+                                      MIN (history->opacity, GIMP_OPACITY_OPAQUE),
+                                      gimp_context_get_opacity (context),
+                                      gimp_context_get_paint_mode (context),
+                                      gimp_paint_options_get_brush_mode (paint_options),
+                                      paint_appl_mode);
+      }
+      paint_core->cur_coords = orig_coords;
+      paint_core->last_coords = prev_coords;
+    }
+
+  g_free (history);
+}
+
+
+static void
+coords_history_free (CoordsHistory *history, gpointer dummy)
+{
+  g_free (history);
+}
+
+static inline gboolean
+pick_up_avarage_color (GimpPickable  *pickable,
+                       GimpBrushCore *brush_core,
+                       gint           x,
+                       gint           y,
+                       gint           size_limit,
+                       guchar        *color)
+{
+  GimpRGB        rgb;
+  gint           index;
+  gboolean       result;
+  gint           width, height;
+
+  gimp_brush_scale_size (brush_core->brush, brush_core->scale, &width, &height);
+
+  result = gimp_pickable_pick_color (pickable,
+                                     x, y,
+                                     TRUE,
+                                     CLAMP (MIN (width, height), 1, size_limit) / 2.0,
+                                     &rgb,
+                                     &index);
+
+  if (result)
+    {
+      switch (gimp_pickable_get_image_type (pickable))
+        {
+        case GIMP_INDEXED_IMAGE:
+        case GIMP_INDEXEDA_IMAGE:
+          color[INDEXED_PIX] = index;
+          color[ALPHA_I_PIX] = OPAQUE_OPACITY;
+          break;
+        case GIMP_GRAY_IMAGE:
+        case GIMP_GRAYA_IMAGE:
+          gimp_rgba_get_uchar (&rgb, &color[GRAY_PIX], &color[GRAY_PIX], &color[GRAY_PIX], &color[ALPHA_G_PIX]);
+          break;
+        default:
+          gimp_rgba_get_uchar (&rgb, &color[0], &color[1], &color[2], &color[3]);
+        }
+    }
+  return result;
+}
+
+
+/* This function came from colortoalpha.c */
+
+static inline void
+color_to_alpha (GimpRGB       *src,
+                const GimpRGB *color)
+{
+  GimpRGB alpha;
+
+  alpha.a = src->a;
+
+  if (color->r < 0.0001)
+    alpha.r = src->r;
+  else if (src->r > color->r)
+    alpha.r = (src->r - color->r) / (1.0 - color->r);
+  else if (src->r < color->r)
+    alpha.r = (color->r - src->r) / color->r;
+  else alpha.r = 0.0;
+
+  if (color->g < 0.0001)
+    alpha.g = src->g;
+  else if (src->g > color->g)
+    alpha.g = (src->g - color->g) / (1.0 - color->g);
+  else if (src->g < color->g)
+    alpha.g = (color->g - src->g) / (color->g);
+  else alpha.g = 0.0;
+
+  if (color->b < 0.0001)
+    alpha.b = src->b;
+  else if (src->b > color->b)
+    alpha.b = (src->b - color->b) / (1.0 - color->b);
+  else if (src->b < color->b)
+    alpha.b = (color->b - src->b) / (color->b);
+  else alpha.b = 0.0;
+
+  if (alpha.r > alpha.g)
+    {
+      if (alpha.r > alpha.b)
+        {
+          src->a = alpha.r;
+        }
+      else
+        {
+          src->a = alpha.b;
+        }
+    }
+  else if (alpha.g > alpha.b)
+    {
+      src->a = alpha.g;
+    }
+  else
+    {
+      src->a = alpha.b;
+    }
+
+  if (src->a < 0.0001)
+    return;
+
+  src->r = (src->r - color->r) / src->a + color->r;
+  src->g = (src->g - color->g) / src->a + color->g;
+  src->b = (src->b - color->b) / src->a + color->b;
+
+  src->a *= alpha.a;
+}
--- gimp-2.4.1/app/paint/gimpmixbrush.h	Thu Jan  1 09:00:00 1970
+++ gimp-2.4.1_gpen_mixbrush/app/paint/gimpmixbrush.h	Thu Nov  1 01:40:57 2007
@@ -0,0 +1,60 @@
+/* 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_MIXBRUSH_H__
+#define __GIMP_MIXBRUSH_H__
+
+
+#include "gimppaintbrush.h"
+
+
+#define GIMP_TYPE_MIXBRUSH            (gimp_mixbrush_get_type ())
+#define GIMP_MIXBRUSH(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_MIXBRUSH, GimpMixbrush))
+#define GIMP_MIXBRUSH_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_MIXBRUSH, GimpMixbrushClass))
+#define GIMP_IS_MIXBRUSH(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_MIXBRUSH))
+#define GIMP_IS_MIXBRUSH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_MIXBRUSH))
+#define GIMP_MIXBRUSH_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_MIXBRUSH, GimpMixbrushClass))
+
+
+typedef struct _GimpMixbrushClass GimpMixbrushClass;
+
+struct _GimpMixbrush
+{
+  GimpPaintbrush    parent_instance;
+
+  GimpDrawable     *drawable;
+  GimpPaintOptions *paint_options;
+  gint              alpha_pix;
+  guchar            color[MAX_CHANNELS];
+  gdouble           error[4];
+  GList            *history;
+};
+
+struct _GimpMixbrushClass
+{
+  GimpPaintbrushClass parent_class;
+};
+
+
+void    gimp_mixbrush_register (Gimp                      *gimp,
+                                GimpPaintRegisterCallback  callback);
+
+GType   gimp_mixbrush_get_type (void) G_GNUC_CONST;
+
+
+#endif  /*  __GIMP_MIXBRUSH_H__  */
--- gimp-2.4.1/app/paint/gimpmixbrushoptions.c	Thu Jan  1 09:00:00 1970
+++ gimp-2.4.1_gpen_mixbrush/app/paint/gimpmixbrushoptions.c	Thu Nov  1 01:40:57 2007
@@ -0,0 +1,298 @@
+/* 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 "gimpmixbrushoptions.h"
+
+
+#define MIXBRUSH_DEFAULT_CANVAS_COLOR_RATE             0.8
+#define MIXBRUSH_DEFAULT_CANVAS_COLOR_PRESSURE_RATE   -0.8
+#define MIXBRUSH_DEFAULT_ORIGINAL_COLOR_RATE           0.5
+#define MIXBRUSH_DEFAULT_ORIGINAL_COLOR_PRESSURE_RATE  0.8
+#define MIXBRUSH_DEFAULT_BLEED                         0.0
+#define MIXBRUSH_DEFAULT_DRYOUT                        0.0
+#define MIXBRUSH_DEFAULT_DELAY                         3
+#define MIXBRUSH_DEFAULT_TAIL                          TRUE
+#define MIXBRUSH_DEFAULT_MERGED                        FALSE
+#define MIXBRUSH_DEFAULT_HIDDEN_COLOR                  GIMP_HIDDEN_COLOR_WHITE
+#define MIXBRUSH_DEFAULT_REMOVE_COLOR                  FALSE
+#define MIXBRUSH_DEFAULT_SAMPLE_SIZE_LIMIT             1
+
+
+enum
+{
+  PROP_0,
+  PROP_CANVAS_COLOR_RATE,
+  PROP_ORIGINAL_COLOR_RATE,
+  PROP_CANVAS_COLOR_PRESSURE_RATE,
+  PROP_ORIGINAL_COLOR_PRESSURE_RATE,
+  PROP_BLEED,
+  PROP_BLEED_PRESSURE_RATE,
+  PROP_DRYOUT,
+  PROP_DELAY,
+  PROP_TAIL,
+  PROP_MERGED,
+  PROP_HIDDEN_COLOR,
+  PROP_REMOVE_COLOR,
+  PROP_SAMPLE_SIZE_LIMIT
+};
+
+
+static void   gimp_mixbrush_options_set_property (GObject      *object,
+                                                  guint         property_id,
+                                                  const GValue *value,
+                                                  GParamSpec   *pspec);
+static void   gimp_mixbrush_options_get_property (GObject      *object,
+                                                  guint         property_id,
+                                                  GValue       *value,
+                                                  GParamSpec   *pspec);
+
+
+G_DEFINE_TYPE (GimpMixbrushOptions, gimp_mixbrush_options,
+               GIMP_TYPE_PAINT_OPTIONS)
+
+#define parent_class gimp_mixbrush_options_parent_class
+
+
+static void
+gimp_mixbrush_options_class_init (GimpMixbrushOptionsClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->set_property = gimp_mixbrush_options_set_property;
+  object_class->get_property = gimp_mixbrush_options_get_property;
+
+  GIMP_CONFIG_INSTALL_PROP_DOUBLE  (object_class, PROP_CANVAS_COLOR_RATE,
+                                    "canvas-color-rate", NULL,
+                                    0.0, 1.0, MIXBRUSH_DEFAULT_CANVAS_COLOR_RATE,
+                                    GIMP_PARAM_STATIC_STRINGS);
+
+  GIMP_CONFIG_INSTALL_PROP_DOUBLE  (object_class, PROP_CANVAS_COLOR_PRESSURE_RATE,
+                                    "canvas-color-pressure-rate", NULL,
+                                    -1.0, 1.0, MIXBRUSH_DEFAULT_CANVAS_COLOR_PRESSURE_RATE,
+                                    GIMP_PARAM_STATIC_STRINGS);
+
+  GIMP_CONFIG_INSTALL_PROP_DOUBLE  (object_class, PROP_ORIGINAL_COLOR_RATE,
+                                    "original-color-rate", NULL,
+                                    0.0, 1.0, MIXBRUSH_DEFAULT_ORIGINAL_COLOR_RATE,
+                                    GIMP_PARAM_STATIC_STRINGS);
+
+  GIMP_CONFIG_INSTALL_PROP_DOUBLE  (object_class, PROP_ORIGINAL_COLOR_PRESSURE_RATE,
+                                    "original-color-pressure-rate", NULL,
+                                    -1.0, 1.0, MIXBRUSH_DEFAULT_ORIGINAL_COLOR_PRESSURE_RATE,
+                                    GIMP_PARAM_STATIC_STRINGS);
+
+  GIMP_CONFIG_INSTALL_PROP_DOUBLE  (object_class, PROP_BLEED,
+                                    "bleed", NULL,
+                                    0.0, MIXBRUSH_BLEED_MAX_VALUE, MIXBRUSH_DEFAULT_BLEED,
+                                    GIMP_PARAM_STATIC_STRINGS);
+
+  GIMP_CONFIG_INSTALL_PROP_DOUBLE  (object_class, PROP_BLEED_PRESSURE_RATE,
+                                    "bleed-pressure-rate", NULL,
+                                    -1.0, 1.0, MIXBRUSH_DEFAULT_CANVAS_COLOR_RATE,
+                                    GIMP_PARAM_STATIC_STRINGS);
+
+  GIMP_CONFIG_INSTALL_PROP_UINT    (object_class, PROP_DRYOUT,
+                                    "dryout", NULL,
+                                    0, 10000, MIXBRUSH_DEFAULT_DRYOUT,
+                                    GIMP_PARAM_STATIC_STRINGS);
+
+  GIMP_CONFIG_INSTALL_PROP_UINT    (object_class, PROP_DELAY,
+                                    "delay", NULL,
+                                    0, 10, MIXBRUSH_DEFAULT_DELAY,
+                                    GIMP_PARAM_STATIC_STRINGS);
+
+  GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_TAIL,
+                                    "tail", NULL,
+                                    MIXBRUSH_DEFAULT_TAIL,
+                                    GIMP_PARAM_STATIC_STRINGS);
+
+  GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_MERGED,
+                                    "merged", NULL,
+                                    MIXBRUSH_DEFAULT_MERGED,
+                                    GIMP_PARAM_STATIC_STRINGS);
+
+  GIMP_CONFIG_INSTALL_PROP_ENUM    (object_class, PROP_HIDDEN_COLOR,
+                                    "hidden-color", NULL,
+                                    GIMP_TYPE_HIDDEN_COLOR,
+                                    MIXBRUSH_DEFAULT_HIDDEN_COLOR,
+                                    GIMP_PARAM_STATIC_STRINGS);
+
+  GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_REMOVE_COLOR,
+                                    "remove-color", NULL,
+                                    MIXBRUSH_DEFAULT_REMOVE_COLOR,
+                                    GIMP_PARAM_STATIC_STRINGS);
+
+  GIMP_CONFIG_INSTALL_PROP_UINT    (object_class, PROP_SAMPLE_SIZE_LIMIT,
+                                    "sample-size-limit", NULL,
+                                    1, 50, MIXBRUSH_DEFAULT_SAMPLE_SIZE_LIMIT,
+                                    GIMP_PARAM_STATIC_STRINGS);
+}
+
+static void
+gimp_mixbrush_options_init (GimpMixbrushOptions *options)
+{
+}
+
+static void
+gimp_mixbrush_options_set_property (GObject      *object,
+                                    guint         property_id,
+                                    const GValue *value,
+                                    GParamSpec   *pspec)
+{
+  GimpMixbrushOptions *options = GIMP_MIXBRUSH_OPTIONS (object);
+
+  switch (property_id)
+    {
+    case PROP_CANVAS_COLOR_RATE:
+      options->canvas_color_rate = g_value_get_double (value);
+      break;
+    case PROP_CANVAS_COLOR_PRESSURE_RATE:
+      options->canvas_color_pressure_rate = g_value_get_double (value);
+      break;
+    case PROP_ORIGINAL_COLOR_RATE:
+      options->original_color_rate = g_value_get_double (value);
+      break;
+    case PROP_ORIGINAL_COLOR_PRESSURE_RATE:
+      options->original_color_pressure_rate = g_value_get_double (value);
+      break;
+    case PROP_BLEED:
+      options->bleed = g_value_get_double (value);
+      break;
+    case PROP_BLEED_PRESSURE_RATE:
+      options->bleed_pressure_rate = g_value_get_double (value);
+      break;
+    case PROP_DRYOUT:
+      options->dryout = g_value_get_uint (value);
+      break;
+    case PROP_DELAY:
+      options->delay = g_value_get_uint (value);
+      break;
+    case PROP_TAIL:
+      options->tail = g_value_get_boolean (value);
+      break;
+    case PROP_MERGED:
+      options->merged = g_value_get_boolean (value);
+      break;
+    case PROP_HIDDEN_COLOR:
+      options->hidden_color = g_value_get_enum (value);
+      break;
+    case PROP_REMOVE_COLOR:
+      options->remove_color = g_value_get_boolean (value);
+      break;
+    case PROP_SAMPLE_SIZE_LIMIT:
+      options->sample_size_limit = g_value_get_uint (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+static void
+gimp_mixbrush_options_get_property (GObject    *object,
+                                    guint       property_id,
+                                    GValue     *value,
+                                    GParamSpec *pspec)
+{
+  GimpMixbrushOptions *options = GIMP_MIXBRUSH_OPTIONS (object);
+
+  switch (property_id)
+    {
+    case PROP_CANVAS_COLOR_RATE:
+      g_value_set_double (value, options->canvas_color_rate);
+      break;
+    case PROP_CANVAS_COLOR_PRESSURE_RATE:
+      g_value_set_double (value, options->canvas_color_pressure_rate);
+      break;
+    case PROP_ORIGINAL_COLOR_RATE:
+      g_value_set_double (value, options->original_color_rate);
+      break;
+    case PROP_ORIGINAL_COLOR_PRESSURE_RATE:
+      g_value_set_double (value, options->original_color_pressure_rate);
+      break;
+    case PROP_BLEED:
+      g_value_set_double (value, options->bleed);
+      break;
+    case PROP_BLEED_PRESSURE_RATE:
+      g_value_set_double (value, options->bleed_pressure_rate);
+      break;
+    case PROP_DRYOUT:
+      g_value_set_uint (value, options->dryout);
+      break;
+    case PROP_DELAY:
+      g_value_set_uint (value, options->delay);
+      break;
+    case PROP_TAIL:
+      g_value_set_boolean (value, options->tail);
+      break;
+    case PROP_MERGED:
+      g_value_set_boolean (value, options->merged);
+      break;
+    case PROP_HIDDEN_COLOR:
+      g_value_set_enum (value, options->hidden_color);
+      break;
+    case PROP_REMOVE_COLOR:
+      g_value_set_boolean (value, options->remove_color);
+      break;
+    case PROP_SAMPLE_SIZE_LIMIT:
+      g_value_set_uint (value, options->sample_size_limit);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+
+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;
+}
--- gimp-2.4.1/app/paint/gimpmixbrushoptions.h	Thu Jan  1 09:00:00 1970
+++ gimp-2.4.1_gpen_mixbrush/app/paint/gimpmixbrushoptions.h	Thu Nov  1 01:40:57 2007
@@ -0,0 +1,86 @@
+/* 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_MIXBRUSH_OPTIONS_H__
+#define __GIMP_MIXBRUSH_OPTIONS_H__
+
+
+#include "gimppaintoptions.h"
+
+
+/* enum(s) */
+
+typedef enum
+{
+  GIMP_HIDDEN_COLOR_NORMAL,
+  GIMP_HIDDEN_COLOR_WHITE,
+  GIMP_HIDDEN_COLOR_BACKGROUND
+} GimpHiddenColor;
+
+
+#define GIMP_TYPE_HIDDEN_COLOR                (gimp_hidden_color_get_type ())
+
+
+/* values(s) */
+
+#define MIXBRUSH_BLEED_MAX_VALUE              0.3
+
+
+
+GType   gimp_hidden_color_get_type (void) G_GNUC_CONST;
+
+
+#define GIMP_TYPE_MIXBRUSH_OPTIONS            (gimp_mixbrush_options_get_type ())
+#define GIMP_MIXBRUSH_OPTIONS(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_MIXBRUSH_OPTIONS, GimpMixbrushOptions))
+#define GIMP_MIXBRUSH_OPTIONS_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_MIXBRUSH_OPTIONS, GimpMixbrushOptionsClass))
+#define GIMP_IS_MIXBRUSH_OPTIONS(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_MIXBRUSH_OPTIONS))
+#define GIMP_IS_MIXBRUSH_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_MIXBRUSH_OPTIONS))
+#define GIMP_MIXBRUSH_OPTIONS_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_MIXBRUSH_OPTIONS, GimpMixbrushOptionsClass))
+
+
+typedef struct _GimpMixbrushOptionsClass GimpMixbrushOptionsClass;
+
+struct _GimpMixbrushOptions
+{
+  GimpPaintOptions  parent_instance;
+
+  gdouble           canvas_color_rate;
+  gdouble           canvas_color_pressure_rate;
+  gdouble           original_color_rate;
+  gdouble           original_color_pressure_rate;
+  gdouble           bleed;
+  gdouble           bleed_pressure_rate;
+  guint             dryout;
+  guint             delay;
+  gboolean          merged;
+  gboolean          tail;
+  GimpHiddenColor   hidden_color;
+  gboolean          remove_color;
+  guint             sample_size_limit;
+};
+
+struct _GimpMixbrushOptionsClass
+{
+  GimpPaintOptionsClass  parent_class;
+};
+
+
+GType   gimp_mixbrush_options_get_type (void) G_GNUC_CONST;
+
+
+#endif  /*  __GIMP_MIXBRUSH_OPTIONS_H__  */
--- gimp-2.4.1/app/paint/gimppaintbrush.c	Wed Oct 31 17:06:00 2007
+++ gimp-2.4.1_gpen_mixbrush/app/paint/gimppaintbrush.c	Sun Nov  4 02:40:02 2007
@@ -139,13 +139,14 @@
                           &col[RED_PIX],
                           &col[GREEN_PIX],
                           &col[BLUE_PIX]);
-      col[ALPHA_PIX] = OPAQUE_OPACITY;
+
+      col[area->bytes - 1] = OPAQUE_OPACITY;
 
       color_pixels (temp_buf_data (area), col,
                     area->width * area->height,
                     area->bytes);
 
-      paint_appl_mode = GIMP_PAINT_INCREMENTAL;
+      /*paint_appl_mode = GIMP_PAINT_INCREMENTAL;*/
     }
   /* otherwise check if the brush has a pixmap and use that to color the area */
   else if (brush_core->brush && brush_core->brush->pixmap)
@@ -154,7 +155,7 @@
                                               area,
                                               gimp_paint_options_get_brush_mode (paint_options));
 
-      paint_appl_mode = GIMP_PAINT_INCREMENTAL;
+      /*paint_appl_mode = GIMP_PAINT_INCREMENTAL;*/
     }
   /* otherwise fill the area with the foreground color */
   else
--- gimp-2.4.1/app/paint/gimppaintcore.c	Sat Sep 22 04:40:00 2007
+++ gimp-2.4.1_gpen_mixbrush/app/paint/gimppaintcore.c	Sun Nov  4 04:44:53 2007
@@ -155,6 +155,7 @@
 
   core->undo_tiles       = NULL;
   core->saved_proj_tiles = NULL;
+  core->color_tiles      = NULL;
   core->canvas_tiles     = NULL;
 
   core->orig_buf         = NULL;
@@ -380,6 +381,14 @@
                                                  tile_manager_bpp (tiles));
     }
 
+  /*  Allocate the color blocks structure  */
+  if (core->color_tiles)
+    tile_manager_unref (core->color_tiles);
+
+  core->color_tiles = tile_manager_new (gimp_item_width (item),
+                                        gimp_item_height (item),
+                                        gimp_drawable_bytes_without_alpha (drawable));
+
   /*  Allocate the canvas blocks structure  */
   if (core->canvas_tiles)
     tile_manager_unref (core->canvas_tiles);
@@ -526,6 +535,12 @@
       core->saved_proj_tiles = NULL;
     }
 
+  if (core->color_tiles)
+    {
+      tile_manager_unref (core->color_tiles);
+      core->color_tiles = NULL;
+    }
+
   if (core->canvas_tiles)
     {
       tile_manager_unref (core->canvas_tiles);
@@ -822,6 +837,119 @@
       if (paint_maskPR->tiles != core->canvas_tiles)
         {
           /*  initialize any invalid canvas tiles  */
+#if 1
+/* These macros came from paint-funcs-generic.c */
+#define INT_MULT(a,b,t)  ((t) = (a) * (b) + 0x80, ((((t) >> 8) + (t)) >> 8))
+#define INT_BLEND(a,b,alpha,tmp)  (INT_MULT((a) - (b), alpha, tmp) + (b))
+
+          gimp_paint_core_validate_canvas_tiles (core,
+                                                 core->canvas_buf->x,
+                                                 core->canvas_buf->y,
+                                                 core->canvas_buf->width,
+                                                 core->canvas_buf->height);
+
+#if 0 /* DEBUG */
+          static gint count = 0;
+          if ((count = (++count) % 500) == 0)
+            {
+              TileManager *tm = core->canvas_tiles;
+              gint w = tile_manager_width (tm);
+              gint h = tile_manager_height (tm);
+              gint bytes = tile_manager_bpp (tm);
+              gint len = w * h * bytes;
+              guchar *buf = g_new (guchar, len);
+
+              read_pixel_data (tm, 0, 0, w - 1, h - 1, buf, w * bytes );
+
+              g_file_set_contents ("r:\\out.raw", buf, len, NULL);
+
+              g_free (buf);
+              g_printerr ("wrote out.raw w:%d h:%d bpp:%d\n",w,h,bytes);
+            }
+          else
+            g_printerr ("count => %d\n", count);
+#endif
+          /* Update the color tiles */
+          {
+            PixelRegion canvas_bufPR, canvas_tilesPR, color_tilesPR, maskPR;
+            gpointer iter;
+            gint x, y, w, h;
+
+            x = core->canvas_buf->x;
+            y = core->canvas_buf->y;
+            w = core->canvas_buf->width;
+            h = core->canvas_buf->height;
+
+            pixel_region_init (&color_tilesPR, core->color_tiles,
+                               x, y, w, h,
+                               FALSE);
+            pixel_region_init (&canvas_tilesPR, core->canvas_tiles,
+                               x, y, w, h,
+                               FALSE);
+            pixel_region_init_temp_buf (&canvas_bufPR,
+                                        core->canvas_buf,
+                                        0, 0, w, h);
+
+            g_memmove (&maskPR, paint_maskPR, sizeof (maskPR));
+
+            for (iter = pixel_regions_register (4, &color_tilesPR,
+                                                &canvas_tilesPR,
+                                                &canvas_bufPR,
+                                                &maskPR);
+                 iter != NULL;
+                 iter = pixel_regions_process (iter))
+              {
+                guchar *canvas_tiles = canvas_tilesPR.data;
+                guchar *paint_mask   = maskPR.data;
+                guchar *color_tiles  = color_tilesPR.data;
+                guchar *canvas_buf   = canvas_bufPR.data;
+                gint    i, j, k;
+
+                for (i = 0; i < canvas_bufPR.h; i++)
+                  {
+                    for (j = 0;j < canvas_bufPR.w; j++)
+                      {
+                        guchar ct = canvas_tiles[j];
+                        guchar pm = paint_mask[j];
+
+                        if (ct == 0 || pm == 255)
+                          {
+                            for (k = 0; k < color_tilesPR.bytes; k++)
+                              color_tiles[j * color_tilesPR.bytes + k] =
+                                canvas_buf[j * canvas_bufPR.bytes + k];
+                          }
+                        else if (ct == 255 && pm == 0)
+                          {
+                            for (k = 0; k < color_tilesPR.bytes; k++)
+                              canvas_buf[j * canvas_bufPR.bytes + k] =
+                                color_tiles[j * color_tilesPR.bytes + k];
+                          }
+                        else
+                          {
+                            gint tmp;
+                            guchar value;
+
+                            for (k = 0; k < color_tilesPR.bytes; k++)
+                              {
+                                value = INT_BLEND (canvas_buf[j * canvas_bufPR.bytes + k],
+                                                   color_tiles[j * color_tilesPR.bytes + k],
+                                                   pm, tmp);
+                                canvas_buf[j * canvas_bufPR.bytes + k] = value;
+                                color_tiles[j * color_tilesPR.bytes + k] = value;
+                              }
+                          }
+                      }
+                    canvas_tiles += canvas_tilesPR.rowstride;
+                    canvas_buf   += canvas_bufPR.rowstride;
+                    paint_mask   += maskPR.rowstride;
+                    color_tiles  += color_tilesPR.rowstride;
+                  }
+
+              }
+          }
+
+          paint_mask_to_canvas_tiles (core, paint_maskPR, paint_opacity);
+#else
           gimp_paint_core_validate_canvas_tiles (core,
                                                  core->canvas_buf->x,
                                                  core->canvas_buf->y,
@@ -829,6 +957,7 @@
                                                  core->canvas_buf->height);
 
           paint_mask_to_canvas_tiles (core, paint_maskPR, paint_opacity);
+#endif
         }
 
       canvas_tiles_to_canvas_buf (core);
--- gimp-2.4.1/app/paint/gimppaintcore.h	Wed Apr 25 00:12:30 2007
+++ gimp-2.4.1_gpen_mixbrush/app/paint/gimppaintcore.h	Sat Nov  3 04:53:17 2007
@@ -60,6 +60,7 @@
 
   TileManager *undo_tiles;       /*  tiles which have been modified      */
   TileManager *saved_proj_tiles; /*  proj tiles which have been modified */
+  TileManager *color_tiles;      /*  the buffer to paint the color to    */
   TileManager *canvas_tiles;     /*  the buffer to paint the mask to     */
 
   TempBuf     *orig_buf;         /*  the unmodified drawable pixels      */
--- gimp-2.4.1/app/paint/gimppaintoptions.c	Wed Jul 25 03:45:42 2007
+++ gimp-2.4.1_gpen_mixbrush/app/paint/gimppaintoptions.c	Sun Nov  4 03:04:16 2007
@@ -45,6 +45,7 @@
 #define DEFAULT_PRESSURE_SIZE         FALSE
 #define DEFAULT_PRESSURE_INVERSE_SIZE FALSE
 #define DEFAULT_PRESSURE_COLOR        FALSE
+#define DEFAULT_PRESSURE_MIN_SCALE    0
 
 #define DEFAULT_USE_FADE              FALSE
 #define DEFAULT_FADE_LENGTH           100.0
@@ -74,6 +75,7 @@
   PROP_PRESSURE_SIZE,
   PROP_PRESSURE_INVERSE_SIZE,
   PROP_PRESSURE_COLOR,
+  PROP_PRESSURE_MIN_SCALE,
   PROP_USE_FADE,
   PROP_FADE_LENGTH,
   PROP_FADE_UNIT,
@@ -171,6 +173,10 @@
                                     "pressure-inverse-size", NULL,
                                     DEFAULT_PRESSURE_INVERSE_SIZE,
                                     GIMP_PARAM_STATIC_STRINGS);
+  GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_PRESSURE_MIN_SCALE,
+                                   "pressure-min-scale", NULL,
+                                   0.0, 1.0, DEFAULT_PRESSURE_MIN_SCALE,
+                                   GIMP_PARAM_STATIC_STRINGS);
 
   GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_USE_FADE,
                                     "use-fade", NULL,
@@ -334,6 +340,9 @@
     case PROP_PRESSURE_COLOR:
       pressure_options->color = g_value_get_boolean (value);
       break;
+    case PROP_PRESSURE_MIN_SCALE:
+      pressure_options->min_scale = g_value_get_double (value);
+      break;
 
     case PROP_USE_FADE:
       fade_options->use_fade = g_value_get_boolean (value);
@@ -449,6 +458,9 @@
     case PROP_PRESSURE_COLOR:
       g_value_set_boolean (value, pressure_options->color);
       break;
+    case PROP_PRESSURE_MIN_SCALE:
+      g_value_set_double (value, pressure_options->min_scale);
+      break;
 
     case PROP_USE_FADE:
       g_value_set_boolean (value, fade_options->use_fade);
@@ -514,7 +526,7 @@
 gimp_paint_options_notify (GObject    *object,
                            GParamSpec *pspec)
 {
-  GimpPaintOptions *options = GIMP_PAINT_OPTIONS (object);
+  /*GimpPaintOptions *options = GIMP_PAINT_OPTIONS (object);
 
   if (pspec->param_id == PROP_USE_GRADIENT)
     {
@@ -532,7 +544,7 @@
     }
 
   if (G_OBJECT_CLASS (parent_class)->notify)
-    G_OBJECT_CLASS (parent_class)->notify (object, pspec);
+    G_OBJECT_CLASS (parent_class)->notify (object, pspec);*/
 }
 
 GimpPaintOptions *
--- gimp-2.4.1/app/paint/gimppaintoptions.h	Tue Jan 23 19:14:06 2007
+++ gimp-2.4.1_gpen_mixbrush/app/paint/gimppaintoptions.h	Thu Nov  1 01:40:57 2007
@@ -44,6 +44,7 @@
   gboolean  size;
   gboolean  inverse_size;
   gboolean  color;
+  gdouble   min_scale;
 };
 
 struct _GimpFadeOptions
--- gimp-2.4.1/app/paint/paint-types.h	Thu Mar  8 18:53:40 2007
+++ gimp-2.4.1_gpen_mixbrush/app/paint/paint-types.h	Thu Nov  1 01:40:57 2007
@@ -41,6 +41,8 @@
 typedef struct _GimpPencil           GimpPencil;
 typedef struct _GimpPerspectiveClone GimpPerspectiveClone;
 typedef struct _GimpSmudge           GimpSmudge;
+typedef struct _GimpInk2             GimpInk2;
+typedef struct _GimpMixbrush         GimpMixbrush;
 
 
 /*  paint options  */
@@ -57,12 +59,15 @@
 typedef struct _GimpPencilOptions           GimpPencilOptions;
 typedef struct _GimpPerspectiveCloneOptions GimpPerspectiveCloneOptions;
 typedef struct _GimpSmudgeOptions           GimpSmudgeOptions;
+typedef struct _GimpInk2Options             GimpInk2Options;
+typedef struct _GimpMixbrushOptions         GimpMixbrushOptions;
 
 
 /*  paint undos  */
 
 typedef struct _GimpPaintCoreUndo GimpPaintCoreUndo;
 typedef struct _GimpInkUndo       GimpInkUndo;
+typedef struct _GimpInk2Undo      GimpInk2Undo;
 
 
 /*  functions  */
--- gimp-2.4.1/app/tools/Makefile.am	Wed Jun 27 18:50:24 2007
+++ gimp-2.4.1_gpen_mixbrush/app/tools/Makefile.am	Thu Nov  1 01:40:57 2007
@@ -167,7 +167,13 @@
 	gimpvectoroptions.c		\
 	gimpvectoroptions.h		\
 	gimpvectortool.c		\
-	gimpvectortool.h
+	gimpvectortool.h		\
+	gimpink2options-gui.c		\
+	gimpink2options-gui.h		\
+	gimpinktool2.c			\
+	gimpinktool2.h			\
+	gimpmixbrushtool.c			\
+	gimpmixbrushtool.h
 
 libapptools_a_built_sources = tools-enums.c
 
--- gimp-2.4.1/app/tools/Makefile.in	Wed Oct 31 17:09:08 2007
+++ gimp-2.4.1_gpen_mixbrush/app/tools/Makefile.in	Thu Nov  1 01:40:57 2007
@@ -100,7 +100,9 @@
 	gimptoolcontrol.$(OBJEXT) gimptooloptions-gui.$(OBJEXT) \
 	gimptransformoptions.$(OBJEXT) gimptransformtool.$(OBJEXT) \
 	gimptransformtoolundo.$(OBJEXT) gimpvectoroptions.$(OBJEXT) \
-	gimpvectortool.$(OBJEXT)
+	gimpvectortool.$(OBJEXT) \
+	gimpinktool2.$(OBJEXT) gimpink2options-gui.$(OBJEXT) \
+	gimpmixbrushtool.$(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 +657,13 @@
 	gimpvectoroptions.c		\
 	gimpvectoroptions.h		\
 	gimpvectortool.c		\
-	gimpvectortool.h
+	gimpvectortool.h		\
+	gimpinktool2.c			\
+	gimpinktool2.h			\
+	gimpink2options-gui.c	\
+	gimpink2options-gui.h	\
+	gimpmixbrushtool.c		\
+	gimpmixbrushtool.h
 
 libapptools_a_built_sources = tools-enums.c
 libapptools_a_SOURCES = $(libapptools_a_built_sources) $(libapptools_a_sources)
@@ -807,6 +815,9 @@
 @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)/gimpink2options-gui.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpinktool2.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpmixbrushtool.Po@am__quote@
 
 .c.o:
 @am__fastdepCC_TRUE@	if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
--- gimp-2.4.1/app/tools/gimp-tools.c	Wed Jul 25 03:45:40 2007
+++ gimp-2.4.1_gpen_mixbrush/app/tools/gimp-tools.c	Thu Nov  1 01:40:57 2007
@@ -77,6 +77,8 @@
 #include "gimpsmudgetool.h"
 #include "gimptexttool.h"
 #include "gimpvectortool.h"
+#include "gimpinktool2.h"
+#include "gimpmixbrushtool.h"
 
 #include "gimp-intl.h"
 
@@ -138,6 +140,8 @@
     gimp_blend_tool_register,
     gimp_bucket_fill_tool_register,
     gimp_text_tool_register,
+    gimp_ink2_tool_register,
+    gimp_mixbrush_tool_register,
 
     /*  transform tools  */
 
@@ -478,6 +482,14 @@
   else if (tool_type == GIMP_TYPE_INK_TOOL)
     {
       paint_core_name = "gimp-ink";
+    }
+  else if (tool_type == GIMP_TYPE_INK2_TOOL)
+    {
+      paint_core_name = "gimp-ink2";
+    }
+  else if (tool_type == GIMP_TYPE_MIXBRUSH_TOOL)
+    {
+      paint_core_name = "gimp-mixbrush";
     }
   else
     {
--- gimp-2.4.1/app/tools/gimpink2options-gui.c	Thu Jan  1 09:00:00 1970
+++ gimp-2.4.1_gpen_mixbrush/app/tools/gimpink2options-gui.c	Thu Nov  1 01:40:57 2007
@@ -0,0 +1,232 @@
+/* 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 "config/gimpconfig-utils.h"
+
+#include "paint/gimpink2options.h"
+#include "paint/gimpink2.h"
+
+#include "widgets/gimpblobeditor.h"
+
+#include "gimpink2options-gui.h"
+#include "gimppaintoptions-gui.h"
+
+#include "gimp-intl.h"
+
+
+static GtkWidget * blob_image_new (GimpInkBlobType blob_type);
+
+
+GtkWidget *
+gimp_ink2_options_gui (GimpToolOptions *tool_options)
+{
+  GObject         *config      = G_OBJECT (tool_options);
+  GimpInk2Options *ink_options = GIMP_INK2_OPTIONS (tool_options);
+  GtkWidget       *vbox        = gimp_paint_options_gui (tool_options);
+  GtkWidget       *frame;
+  GtkWidget       *table;
+  GtkWidget       *blob_vbox;
+  GtkWidget       *hbox;
+  GtkWidget       *editor;
+  GtkObject       *adj;
+  GtkWidget       *compensate_box;
+  GtkWidget       *compensate_vbox;
+  GtkWidget       *checkbox;
+
+  /* adjust sliders */
+  frame = gimp_frame_new (_("Adjustment"));
+  gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
+  gtk_widget_show (frame);
+
+  table = gtk_table_new (2, 3, FALSE);
+  gtk_table_set_col_spacings (GTK_TABLE (table), 2);
+  gtk_container_add (GTK_CONTAINER (frame), table);
+  gtk_widget_show (table);
+
+  /*  size slider  */
+  adj = gimp_prop_scale_entry_new (config, "size",
+                                   GTK_TABLE (table), 0, 0,
+                                   _("Size:"),
+                                   1.0, 2.0, 1,
+                                   FALSE, 0.0, 0.0);
+  gimp_scale_entry_set_logarithmic (adj, TRUE);
+
+  /* angle adjust slider */
+  gimp_prop_scale_entry_new (config, "tilt-angle",
+                             GTK_TABLE (table), 0, 1,
+                             _("Angle:"),
+                             1.0, 10.0, 1,
+                             FALSE, 0.0, 0.0);
+
+  /* sens sliders */
+  frame = gimp_frame_new (_("Sensitivity"));
+  gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
+  gtk_widget_show (frame);
+
+  table = gtk_table_new (3, 3, FALSE);
+  gtk_table_set_col_spacings (GTK_TABLE (table), 2);
+  gtk_container_add (GTK_CONTAINER (frame), table);
+  gtk_widget_show (table);
+
+  /* size sens slider */
+  gimp_prop_scale_entry_new (config, "size-sensitivity",
+                             GTK_TABLE (table), 0, 0,
+                             _("Size:"),
+                             0.01, 0.1, 1,
+                             FALSE, 0.0, 0.0);
+
+  /* tilt sens slider */
+  gimp_prop_scale_entry_new (config, "tilt-sensitivity",
+                             GTK_TABLE (table), 0, 1,
+                             _("Tilt:"),
+                             0.01, 0.1, 1,
+                             FALSE, 0.0, 0.0);
+
+  /* velocity sens slider */
+  gimp_prop_scale_entry_new (config, "vel-sensitivity",
+                             GTK_TABLE (table), 0, 2,
+                             _("Speed:"),
+                             0.01, 0.1, 1,
+                             FALSE, 0.0, 0.0);
+
+  /* compensate at last checkbox */
+  compensate_box = gtk_frame_new (_("Pointer Adjustment"));
+  gtk_box_pack_start (GTK_BOX (vbox), compensate_box, FALSE, TRUE, 0);
+  gtk_widget_show(compensate_box);
+  compensate_vbox = gtk_vbox_new (FALSE, 2);
+  gtk_container_add (GTK_CONTAINER (compensate_box), compensate_vbox);
+  gtk_widget_show (compensate_vbox);
+
+  table = gtk_table_new (3, 3, FALSE);
+  gtk_table_set_col_spacings (GTK_TABLE (table), 2);
+  gtk_box_pack_start (GTK_VBOX (compensate_vbox), table, TRUE, TRUE, 0);
+  gtk_widget_show (table);
+
+  /* compensation history size slider */
+  gimp_prop_scale_entry_new (config, "compensation-history-size",
+                             GTK_TABLE (table), 0, 0,
+                             _("Quality:"),
+                             1, 1, 0,
+                             FALSE, 1.0, INK2_HISTORY_BUFFER);
+
+  /* pointer tracking rate slider */
+  adj = gimp_prop_scale_entry_new (config, "compensation-rate-temperature",
+                             GTK_TABLE (table), 0, 1,
+                             _("Rate:"),
+                             1, 10, 1,
+                             FALSE, 0, 100);
+  gimp_scale_entry_set_logarithmic (adj, TRUE);
+
+  checkbox = 
+    gimp_prop_check_button_new (config, "compensate-at-last",
+                               _("Draw pen line to finished point:"));
+  gtk_box_pack_start (GTK_VBOX (compensate_vbox), checkbox, FALSE, FALSE, 0);
+  gtk_widget_show(checkbox);
+
+  /*  bottom hbox */
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+  gtk_widget_show (hbox);
+
+  /* Blob type radiobuttons */
+  frame = gimp_prop_enum_radio_frame_new (config, "blob-type",
+                                          _("Type"), 0, 0);
+  gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
+  gtk_widget_show (frame);
+
+  {
+    GList           *children;
+    GList           *list;
+    GimpInkBlobType  blob_type;
+
+    children =
+      gtk_container_get_children (GTK_CONTAINER (GTK_BIN (frame)->child));
+
+    for (list = children, blob_type = GIMP_INK_BLOB_TYPE_ELLIPSE;
+         list;
+         list = g_list_next (list), blob_type++)
+      {
+        GtkWidget *radio = GTK_WIDGET (list->data);
+        GtkWidget *blob;
+
+        gtk_container_remove (GTK_CONTAINER (radio), GTK_BIN (radio)->child);
+
+        blob = blob_image_new (blob_type);
+        gtk_container_add (GTK_CONTAINER (radio), blob);
+        gtk_widget_show (blob);
+      }
+
+    g_list_free (children);
+  }
+
+  /* Blob shape widget */
+  frame = gimp_frame_new (_("Shape"));
+  gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
+  gtk_widget_show (frame);
+
+  blob_vbox = gtk_vbox_new (FALSE, 2);
+  gtk_container_add (GTK_CONTAINER (frame), blob_vbox);
+  gtk_widget_show (blob_vbox);
+
+  frame = gtk_aspect_frame_new (NULL, 0.0, 0.5, 1.0, FALSE);
+  gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
+  gtk_box_pack_start (GTK_BOX (blob_vbox), frame, TRUE, TRUE, 0);
+  gtk_widget_show (frame);
+
+  editor = gimp_blob_editor_new (ink_options->blob_type,
+                                 ink_options->blob_aspect,
+                                 ink_options->blob_angle);
+  gtk_widget_set_size_request (editor, 60, 60);
+  gtk_container_add (GTK_CONTAINER (frame), editor);
+  gtk_widget_show (editor);
+
+  gimp_config_connect (config, G_OBJECT (editor), NULL);
+
+  return vbox;
+}
+
+static GtkWidget *
+blob_image_new (GimpInkBlobType blob_type)
+{
+  const gchar *stock_id = NULL;
+
+  switch (blob_type)
+    {
+    case GIMP_INK_BLOB_TYPE_ELLIPSE:
+      stock_id = GIMP_STOCK_SHAPE_CIRCLE;
+      break;
+
+    case GIMP_INK_BLOB_TYPE_SQUARE:
+      stock_id = GIMP_STOCK_SHAPE_SQUARE;
+      break;
+
+    case GIMP_INK_BLOB_TYPE_DIAMOND:
+      stock_id = GIMP_STOCK_SHAPE_DIAMOND;
+      break;
+    }
+
+  return gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_MENU);
+}
--- gimp-2.4.1/app/tools/gimpink2options-gui.h	Thu Jan  1 09:00:00 1970
+++ gimp-2.4.1_gpen_mixbrush/app/tools/gimpink2options-gui.h	Thu Nov  1 01:40:57 2007
@@ -0,0 +1,26 @@
+/* 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_INK2_OPTIONS_GUI_H__
+#define  __GIMP_INK2_OPTIONS_GUI_H__
+
+
+GtkWidget * gimp_ink2_options_gui      (GimpToolOptions *tool_options);
+
+
+#endif  /*  __GIMP_INK2_OPTIONS_GUI_H__  */
--- gimp-2.4.1/app/tools/gimpinktool2.c	Thu Jan  1 09:00:00 1970
+++ gimp-2.4.1_gpen_mixbrush/app/tools/gimpinktool2.c	Thu Nov  1 01:40:57 2007
@@ -0,0 +1,83 @@
+/* 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/gimpink2options.h"
+
+#include "widgets/gimphelp-ids.h"
+
+#include "gimpink2options-gui.h"
+#include "gimpinktool2.h"
+#include "gimptoolcontrol.h"
+
+#include "gimp-intl.h"
+
+
+G_DEFINE_TYPE (GimpInk2Tool, gimp_ink2_tool, GIMP_TYPE_PAINT_TOOL)
+
+#define parent_class gimp_ink2_tool_parent_class
+
+
+void
+gimp_ink2_tool_register (GimpToolRegisterCallback  callback,
+                         gpointer                  data)
+{
+  (* callback) (GIMP_TYPE_INK2_TOOL,
+                GIMP_TYPE_INK2_OPTIONS,
+                gimp_ink2_options_gui,
+                GIMP_CONTEXT_FOREGROUND_MASK |
+                GIMP_CONTEXT_BACKGROUND_MASK |
+                GIMP_CONTEXT_OPACITY_MASK    |
+                GIMP_CONTEXT_PAINT_MODE_MASK,
+                "gimp-ink2-tool",
+                _("G-pen"),
+                _("Draw in G-pen -2-"),
+                N_("G-pen"), "G",
+                NULL, GIMP_HELP_TOOL_INK,
+                GIMP_STOCK_TOOL_INK,
+                data);
+}
+
+static void
+gimp_ink2_tool_class_init (GimpInk2ToolClass *klass)
+{
+}
+
+static void
+gimp_ink2_tool_init (GimpInk2Tool *ink_tool)
+{
+  GimpTool *tool = GIMP_TOOL (ink_tool);
+
+  gimp_tool_control_set_tool_cursor    (tool->control, GIMP_TOOL_CURSOR_INK);
+  gimp_tool_control_set_action_value_2 (tool->control,
+                                        "tools/tools-ink-blob-size-set");
+  gimp_tool_control_set_action_value_3 (tool->control,
+                                        "tools/tools-ink-blob-aspect-set");
+  gimp_tool_control_set_action_value_4 (tool->control,
+                                        "tools/tools-ink-blob-angle-set");
+
+  gimp_paint_tool_enable_color_picker (GIMP_PAINT_TOOL (ink_tool),
+                                       GIMP_COLOR_PICK_MODE_FOREGROUND);
+}
--- gimp-2.4.1/app/tools/gimpinktool2.h	Thu Jan  1 09:00:00 1970
+++ gimp-2.4.1_gpen_mixbrush/app/tools/gimpinktool2.h	Thu Nov  1 01:40:57 2007
@@ -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_INK2_TOOL_H__
+#define  __GIMP_INK2_TOOL_H__
+
+
+#include "gimppainttool.h"
+
+
+#define GIMP_TYPE_INK2_TOOL            (gimp_ink2_tool_get_type ())
+#define GIMP_INK2_TOOL(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_INK2_TOOL, GimpInk2Tool))
+#define GIMP_INK2_TOOL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_INK2_TOOL, GimpInk2ToolClass))
+#define GIMP_IS_INK2_TOOL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_INK2_TOOL))
+#define GIMP_IS_INK2_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_INK2_TOOL))
+#define GIMP_INK2_TOOL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_INK2_TOOL, GimpInk2ToolClass))
+
+
+typedef struct _GimpInk2Tool      GimpInk2Tool;
+typedef struct _GimpInk2ToolClass GimpInk2ToolClass;
+
+struct _GimpInk2Tool
+{
+  GimpPaintTool parent_instance;
+};
+
+struct _GimpInk2ToolClass
+{
+  GimpPaintToolClass parent_class;
+};
+
+
+void    gimp_ink2_tool_register (GimpToolRegisterCallback  callback,
+                                 gpointer                  data);
+
+GType   gimp_ink2_tool_get_type (void) G_GNUC_CONST;
+
+
+#endif  /*  __GIMP_INK2_TOOL_H__  */
--- gimp-2.4.1/app/tools/gimpmixbrushtool.c	Thu Jan  1 09:00:00 1970
+++ gimp-2.4.1_gpen_mixbrush/app/tools/gimpmixbrushtool.c	Thu Nov  1 01:40:57 2007
@@ -0,0 +1,215 @@
+/* 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/gimpmixbrushoptions.h"
+
+#include "widgets/gimphelp-ids.h"
+
+#include "gimpmixbrushtool.h"
+#include "gimppaintoptions-gui.h"
+#include "gimptoolcontrol.h"
+
+#include "gimp-intl.h"
+
+
+static GtkWidget * gimp_mixbrush_options_gui (GimpToolOptions  *tool_options);
+
+
+G_DEFINE_TYPE (GimpMixbrushTool, gimp_mixbrush_tool, GIMP_TYPE_PAINTBRUSH_TOOL)
+
+
+void
+gimp_mixbrush_tool_register (GimpToolRegisterCallback  callback,
+                             gpointer                  data)
+{
+  (* callback) (GIMP_TYPE_MIXBRUSH_TOOL,
+                GIMP_TYPE_MIXBRUSH_OPTIONS,
+                gimp_mixbrush_options_gui,
+                GIMP_PAINT_OPTIONS_CONTEXT_MASK |
+                GIMP_CONTEXT_GRADIENT_MASK,
+                "gimp-mixbrush-tool",
+                _("Mixbrush"),
+                _("Mixbrush Tool: Brush with mixing color feature"),
+                N_("_Mixbrush"), "W",
+                NULL, GIMP_HELP_TOOL_PAINTBRUSH,
+                GIMP_STOCK_TOOL_PAINTBRUSH,
+                data);
+}
+
+static void
+gimp_mixbrush_tool_class_init (GimpMixbrushToolClass *klass)
+{
+}
+
+static void
+gimp_mixbrush_tool_init (GimpMixbrushTool *mixbrush)
+{
+  GimpTool *tool = GIMP_TOOL (mixbrush);
+
+  gimp_tool_control_set_tool_cursor (tool->control, GIMP_TOOL_CURSOR_PAINTBRUSH);
+
+  gimp_paint_tool_enable_color_picker (GIMP_PAINT_TOOL (mixbrush),
+                                       GIMP_COLOR_PICK_MODE_FOREGROUND);
+}
+
+
+/*  tool options stuff  */
+
+static GtkWidget *
+gimp_mixbrush_options_gui (GimpToolOptions *tool_options)
+{
+  GObject   *config = G_OBJECT (tool_options);
+  GtkWidget *vbox   = gimp_paint_options_gui (tool_options);
+  GtkWidget *table;
+  GtkWidget *mixbrush_box;
+  GtkWidget *mixbrush_vbox;
+  GtkWidget *mixbrush_button;
+  GtkWidget *mixbrush_frame;
+
+  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 */
+  mixbrush_box = gtk_frame_new (_("Canvas Color"));
+  gtk_box_pack_start (GTK_BOX (vbox), mixbrush_box, FALSE, TRUE, 0);
+  gtk_widget_show(mixbrush_box);
+  mixbrush_vbox = gtk_vbox_new (FALSE, 2);
+  gtk_container_add (GTK_CONTAINER (mixbrush_box), mixbrush_vbox);
+  gtk_widget_show (mixbrush_vbox);
+
+  table = gtk_table_new (3, 5, FALSE);
+  gtk_table_set_col_spacings (GTK_TABLE (table), 2);
+  gtk_box_pack_start (GTK_VBOX (mixbrush_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, -1.0, 1.0);
+
+  gimp_prop_scale_entry_new (config, "bleed",
+                             GTK_TABLE (table), 0, 2,
+                             _("Bleed:"),
+                             0.005, 0.025, 3,
+                             TRUE, 0.0, 0.3);
+
+  gimp_prop_scale_entry_new (config, "bleed-pressure-rate",
+                             GTK_TABLE (table), 0, 3,
+                             _("Pressure:"),
+                             0.01, 0.1, 2,
+                             FALSE, -1.0, 1.0);
+
+  /* Original Color Picking Configurations */
+  mixbrush_box = gtk_frame_new (_("Original Color"));
+  gtk_box_pack_start (GTK_BOX (vbox), mixbrush_box, FALSE, TRUE, 0);
+  gtk_widget_show(mixbrush_box);
+  mixbrush_vbox = gtk_vbox_new (FALSE, 2);
+  gtk_container_add (GTK_CONTAINER (mixbrush_box), mixbrush_vbox);
+  gtk_widget_show (mixbrush_vbox);
+
+  table = gtk_table_new (3, 4, FALSE);
+  gtk_table_set_col_spacings (GTK_TABLE (table), 2);
+  gtk_box_pack_start (GTK_VBOX (mixbrush_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, -1.0, 1.0);
+
+  gimp_prop_scale_entry_new (config, "dryout",
+                             GTK_TABLE (table), 0, 2,
+                             _("Dryout:"),
+                             10.0, 100.0, 0,
+                             TRUE, 0.0, 10000);
+
+  /* */
+  mixbrush_box = gtk_frame_new (_("Pick up"));
+  gtk_box_pack_start (GTK_BOX (vbox), mixbrush_box, FALSE, TRUE, 0);
+  gtk_widget_show(mixbrush_box);
+  mixbrush_vbox = gtk_vbox_new (FALSE, 2);
+  gtk_container_add (GTK_CONTAINER (mixbrush_box), mixbrush_vbox);
+  gtk_widget_show (mixbrush_vbox);
+
+  table = gtk_table_new (3, 1, FALSE);
+  gtk_table_set_col_spacings (GTK_TABLE (table), 2);
+  gtk_box_pack_start (GTK_VBOX (mixbrush_vbox), table, TRUE, TRUE, 0);
+  gtk_widget_show (table);
+
+  gimp_prop_scale_entry_new (config, "sample-size-limit",
+                             GTK_TABLE (table), 0, 0,
+                             _("Sample size:"),
+                             1.0, 10.0, 0,
+                             TRUE, 1.0, 100.0);
+
+  /*mixbrush_button = gimp_prop_check_button_new (config, "merged", _("Pick up underlying color"));*/
+  mixbrush_button = gimp_prop_check_button_new (config, "merged", _("Use merged color"));
+  gtk_box_pack_start (GTK_BOX (mixbrush_vbox), mixbrush_button, TRUE, TRUE, 0);
+  gtk_widget_show (mixbrush_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);
+
+  gimp_prop_scale_entry_new (config, "delay",
+                             GTK_TABLE (table), 0, 0,
+                             _("Delay:"),
+                             1.0, 2.0, 0,
+                             TRUE, 0.0, 10);
+
+  mixbrush_button = gimp_prop_check_button_new (config, "tail", _("Paint the tail of stroke (delay > 0)"));
+  gtk_box_pack_start (GTK_BOX (vbox), mixbrush_button, FALSE, TRUE, 0);
+  gtk_widget_show (mixbrush_button);
+
+  mixbrush_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), mixbrush_frame, FALSE, TRUE, 0);
+  gtk_widget_show (mixbrush_frame);
+
+  mixbrush_button = gimp_prop_check_button_new (config, "remove-color", _("Remove background color"));
+  gtk_box_pack_start (GTK_BOX (vbox), mixbrush_button, FALSE, TRUE, 0);
+  gtk_widget_show (mixbrush_button);
+
+  return vbox;
+}
--- gimp-2.4.1/app/tools/gimpmixbrushtool.h	Thu Jan  1 09:00:00 1970
+++ gimp-2.4.1_gpen_mixbrush/app/tools/gimpmixbrushtool.h	Thu Nov  1 01:40:57 2007
@@ -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_MIXBRUSH_TOOL_H__
+#define __GIMP_MIXBRUSH_TOOL_H__
+
+
+#include "gimppaintbrushtool.h"
+
+
+#define GIMP_TYPE_MIXBRUSH_TOOL            (gimp_mixbrush_tool_get_type ())
+#define GIMP_MIXBRUSH_TOOL(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_MIXBRUSH_TOOL, GimpMixbrushTool))
+#define GIMP_MIXBRUSH_TOOL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_MIXBRUSH_TOOL, GimpMixbrushToolClass))
+#define GIMP_IS_MIXBRUSH_TOOL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_MIXBRUSH_TOOL))
+#define GIMP_IS_MIXBRUSH_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_MIXBRUSH_TOOL))
+#define GIMP_MIXBRUSH_TOOL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_MIXBRUSH_TOOL, GimpMixbrushToolClass))
+
+
+typedef struct _GimpMixbrushTool      GimpMixbrushTool;
+typedef struct _GimpMixbrushToolClass GimpMixbrushToolClass;
+
+struct _GimpMixbrushTool
+{
+  GimpPaintbrushTool parent_instance;
+};
+
+struct _GimpMixbrushToolClass
+{
+  GimpPaintbrushToolClass parent_class;
+};
+
+
+void       gimp_mixbrush_tool_register (GimpToolRegisterCallback  callback,
+                                        gpointer                  data);
+
+GType      gimp_mixbrush_tool_get_type (void) G_GNUC_CONST;
+
+
+#endif  /*  __GIMP_MIXBRUSH_TOOL_H__  */
--- gimp-2.4.1/app/tools/gimppaintoptions-gui.c	Tue Oct 23 04:16:16 2007
+++ gimp-2.4.1_gpen_mixbrush/app/tools/gimppaintoptions-gui.c	Sun Nov  4 03:44:33 2007
@@ -46,6 +46,7 @@
 #include "gimppenciltool.h"
 #include "gimpperspectiveclonetool.h"
 #include "gimpsmudgetool.h"
+#include "gimpmixbrushtool.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_MIXBRUSH_TOOL ||
       tool_type == GIMP_TYPE_ERASER_TOOL)
     {
       incremental_toggle =
@@ -224,6 +226,8 @@
   GObject   *config = G_OBJECT (paint_options);
   GtkWidget *frame  = NULL;
   GtkWidget *wbox   = NULL;
+  //GtkWidget *vbox   = NULL;
+  GtkWidget *table;
   GtkWidget *button;
 
   if (g_type_is_a (tool_type, GIMP_TYPE_BRUSH_TOOL))
@@ -238,9 +242,17 @@
       gtk_container_add (GTK_CONTAINER (frame), inner_frame);
       gtk_widget_show (inner_frame);
 
+      table = gtk_table_new (3, 2, FALSE);
+      gtk_table_set_col_spacings (GTK_TABLE (table), 2);
+      gtk_container_add (GTK_CONTAINER (inner_frame), table);
+      gtk_widget_show (table);
+
       wbox = gtk_hwrap_box_new (FALSE);
       gtk_wrap_box_set_aspect_ratio (GTK_WRAP_BOX (wbox), 4);
-      gtk_container_add (GTK_CONTAINER (inner_frame), wbox);
+      //gtk_box_pack_start (GTK_VBOX (vbox), wbox, FALSE, FALSE, 0);
+      gtk_table_attach (GTK_TABLE (table), wbox, 0, 3, 0, 1,
+                        GTK_EXPAND | GTK_FILL, GTK_SHRINK | GTK_FILL,
+                        0, 0);
       gtk_widget_show (wbox);
     }
 
@@ -286,19 +298,25 @@
     }
 
   /*  the size toggle  */
-  if (tool_type == GIMP_TYPE_CLONE_TOOL             ||
+  if (g_type_is_a (tool_type, GIMP_TYPE_PAINTBRUSH_TOOL) ||
+      tool_type == GIMP_TYPE_CLONE_TOOL             ||
       tool_type == GIMP_TYPE_HEAL_TOOL              ||
       tool_type == GIMP_TYPE_PERSPECTIVE_CLONE_TOOL ||
       tool_type == GIMP_TYPE_CONVOLVE_TOOL          ||
       tool_type == GIMP_TYPE_DODGE_BURN_TOOL        ||
       tool_type == GIMP_TYPE_ERASER_TOOL            ||
-      tool_type == GIMP_TYPE_PAINTBRUSH_TOOL        ||
       tool_type == GIMP_TYPE_PENCIL_TOOL)
     {
       button = gimp_prop_check_button_new (config, "pressure-size",
                                            _("Size"));
       gtk_container_add (GTK_CONTAINER (wbox), button);
       gtk_widget_show (button);
+
+      gimp_prop_scale_entry_new (config, "pressure-min-scale",
+                                 GTK_TABLE (table), 0, 1,
+                                 _("Minimum scale:"),
+                                 0.01, 0.1, 2,
+                                 FALSE, 0.0, 1.0);
     }
 
   /* the inverse size toggle */
@@ -419,13 +437,13 @@
                                              _("Use color from gradient"),
                                              table, &button);
 
-      if (incremental_toggle)
+      /*if (incremental_toggle)
         {
           gtk_widget_set_sensitive (incremental_toggle,
                                     ! gradient->use_gradient);
           g_object_set_data (G_OBJECT (button), "inverse_sensitive",
                              incremental_toggle);
-        }
+        }*/
 
       /*  the gradient view  */
       button = gimp_prop_gradient_box_new (NULL, GIMP_CONTEXT (config), 2,