Index: app/paint/gimpbrushcore.c
===================================================================
--- app/paint/gimpbrushcore.c	(revision 26794)
+++ app/paint/gimpbrushcore.c	(working copy)
@@ -77,6 +77,14 @@
                                                    GimpDrawable     *drawable,
                                                    GimpPaintOptions *paint_options,
                                                    guint32           time);
+static void     gimp_brush_core_linear_interpolate(GimpPaintCore    *core,
+                                                   GimpDrawable     *drawable,
+                                                   GimpPaintOptions *paint_options,
+                                                   guint32           time);
+static void     gimp_brush_core_spline_interpolate(GimpPaintCore    *core,
+                                                   GimpDrawable     *drawable,
+                                                   GimpPaintOptions *paint_options,
+                                                   guint32           time);
 
 static TempBuf *gimp_brush_core_get_paint_area    (GimpPaintCore    *paint_core,
                                                    GimpDrawable     *drawable,
@@ -108,7 +116,13 @@
 static void      gimp_brush_core_invalidate_cache (GimpBrush        *brush,
                                                    GimpBrushCore    *core);
 
+static gdouble   gimp_brush_core_get_cr_spline_point (gdouble  t,
+									                  gdouble  p0,
+				 					                  gdouble  p1,
+									                  gdouble  p2,
+									                  gdouble  p3);
 
+
 /*  brush pipe utility functions  */
 static void      paint_line_pixmap_mask           (GimpImage        *dest,
                                                    GimpDrawable     *drawable,
@@ -211,6 +225,9 @@
   core->n_brush_bound_segs       = 0;
   core->brush_bound_width        = 0;
   core->brush_bound_height       = 0;
+	
+  core->delayed                  = FALSE;
+
 }
 
 static void
@@ -364,6 +381,8 @@
   core->jitter =
     gimp_paint_options_get_jitter (paint_options,
                                    gimp_item_get_image (GIMP_ITEM (drawable)));
+    core->first_segment = TRUE;
+	core->delayed = FALSE;
 
   return TRUE;
 }
@@ -393,7 +412,6 @@
       *x = integral + (1 - EPSILON);
     }
 }
-
 static void
 gimp_brush_core_interpolate (GimpPaintCore    *paint_core,
                              GimpDrawable     *drawable,
@@ -406,6 +424,83 @@
   gdouble        delta_xtilt, delta_ytilt;
   gdouble        delta_wheel;
   gdouble        delta_velocity;
+  gdouble        distance;
+
+  g_return_if_fail (GIMP_IS_BRUSH (core->brush));
+
+  delta_vec.x    = paint_core->cur_coords.x        - paint_core->last_coords.x;
+  delta_vec.y    = paint_core->cur_coords.y        - paint_core->last_coords.y;
+  delta_pressure = paint_core->cur_coords.pressure - paint_core->last_coords.pressure;
+  delta_xtilt    = paint_core->cur_coords.xtilt    - paint_core->last_coords.xtilt;
+  delta_ytilt    = paint_core->cur_coords.ytilt    - paint_core->last_coords.ytilt;
+  delta_wheel    = paint_core->cur_coords.wheel    - paint_core->last_coords.wheel;
+  delta_velocity = paint_core->cur_coords.velocity - paint_core->last_coords.velocity;
+
+  /*  return if there has been no motion  */
+  if (! delta_vec.x    &&
+      ! delta_vec.y    &&
+      ! delta_pressure &&
+      ! delta_xtilt    &&
+      ! delta_ytilt    &&
+      ! delta_wheel    &&
+      ! delta_velocity)
+    return;
+
+  distance = sqrt (SQR (delta_vec.x) + SQR (delta_vec.y));
+	
+  if ( (distance < BRUSH_CORE_SPLINE_THRESHOLD) || core->first_segment)
+	{  
+	  if( core->delayed )
+		{
+		  gimp_brush_core_spline_interpolate (paint_core,
+                                              drawable,
+                                              paint_options,
+                                              time);
+		  core->delayed = FALSE;
+		}
+			
+	  gimp_brush_core_linear_interpolate (paint_core,
+                                          drawable,
+                                          paint_options,
+                                          time);
+	  core->p0_coords = core->p1_coords;
+      core->p1_coords = paint_core->last_coords;
+      core->p2_coords = paint_core->cur_coords;
+	  core->first_segment = FALSE;
+
+	}
+  else
+	{
+	  if ( core->delayed )
+		{
+		  gimp_brush_core_spline_interpolate (paint_core,
+                                              drawable,
+                                              paint_options,
+                                              time);
+		}
+	  else
+		{
+		  core->delayed = TRUE;
+          core->p0_coords = core->p1_coords;
+          core->p1_coords = core->p2_coords;
+          core->p2_coords = paint_core->cur_coords;
+		}
+	}
+	
+}
+
+static void
+gimp_brush_core_linear_interpolate (GimpPaintCore    *paint_core,
+                                    GimpDrawable     *drawable,
+                                    GimpPaintOptions *paint_options,
+                                    guint32           time)
+{
+  GimpBrushCore *core = GIMP_BRUSH_CORE (paint_core);
+  GimpVector2    delta_vec;
+  gdouble        delta_pressure;
+  gdouble        delta_xtilt, delta_ytilt;
+  gdouble        delta_wheel;
+  gdouble        delta_velocity;
   GimpVector2    temp_vec;
   gint           n, num_points;
   gdouble        t0, dt, tn;
@@ -675,6 +770,133 @@
   paint_core->last_coords = paint_core->cur_coords;
 }
 
+static void
+gimp_brush_core_spline_interpolate (GimpPaintCore    *paint_core,
+                                    GimpDrawable     *drawable,
+                                    GimpPaintOptions *paint_options,
+                                    guint32           time)
+{
+  GimpBrushCore *core = GIMP_BRUSH_CORE (paint_core);
+  GimpVector2    delta_vec;
+  gdouble        delta_pressure;
+  gdouble        delta_xtilt, delta_ytilt;
+  gdouble        delta_wheel;
+  gdouble        delta_velocity;
+  gdouble        ratio_velocity;
+  gdouble        distance;
+  gint           num_points;
+  gint           n;
+  GimpCoords     past_coords;
+  GimpCoords     start_coords;
+  GimpCoords     end_coords;
+  GimpCoords     future_coords;
+
+  g_return_if_fail (GIMP_IS_BRUSH (core->brush));
+
+  gimp_avoid_exact_integer (&paint_core->last_coords.x);
+  gimp_avoid_exact_integer (&paint_core->last_coords.y);
+  gimp_avoid_exact_integer (&paint_core->cur_coords.x);
+  gimp_avoid_exact_integer (&paint_core->cur_coords.y);
+
+  delta_vec.x    = paint_core->cur_coords.x        - paint_core->last_coords.x;
+  delta_vec.y    = paint_core->cur_coords.y        - paint_core->last_coords.y;
+  delta_pressure = paint_core->cur_coords.pressure - paint_core->last_coords.pressure;
+  delta_xtilt    = paint_core->cur_coords.xtilt    - paint_core->last_coords.xtilt;
+  delta_ytilt    = paint_core->cur_coords.ytilt    - paint_core->last_coords.ytilt;
+  delta_wheel    = paint_core->cur_coords.wheel    - paint_core->last_coords.wheel;
+  delta_velocity = paint_core->cur_coords.velocity - paint_core->last_coords.velocity;
+  ratio_velocity = paint_core->cur_coords.velocity / paint_core->last_coords.velocity;
+
+
+  /* Catmull-Rom interpolation requires 4 points. Two endpoints plus one more at 
+	 each end. Getting the event from two events ago is just a matter of saving it,
+	 but the next point we need to predict. */
+
+  past_coords  = core->p0_coords;
+  start_coords = core->p1_coords;
+  end_coords   = core->p2_coords;	
+  future_coords   = paint_core->cur_coords;
+
+  distance  = sqrt (SQR (delta_vec.x) + SQR (delta_vec.y));
+
+  num_points = distance / BRUSH_CORE_SPLINE_THRESHOLD;
+  
+	
+  
+
+  for (n = 1; n <=num_points; n++)
+    {
+	
+    gdouble p = (gdouble) n / num_points;
+	
+	paint_core->cur_coords.x = gimp_brush_core_get_cr_spline_point (p,
+								                            	    past_coords.x,
+				 					                                start_coords.x,
+									                                end_coords.x,
+									                                future_coords.x);
+/*	printf("p:%f, past:%f, start:%f, end:%f, next:%f , curr:%f\n", p,
+		                                                           past_coords.x,
+		                                                           start_coords.x,
+		                                                           end_coords.x,
+		                                                           future_coords.x,
+		                                                           paint_core->cur_coords.x);
+*/
+	paint_core->cur_coords.y = gimp_brush_core_get_cr_spline_point (p,
+								                            	    past_coords.y,
+				 					                                start_coords.y,
+									                                end_coords.y,
+									                                future_coords.y);
+	
+	paint_core->cur_coords.pressure = gimp_brush_core_get_cr_spline_point (p,
+								                            	    past_coords.pressure,
+				 					                                start_coords.pressure,
+									                                end_coords.pressure,
+									                                future_coords.pressure);
+	paint_core->cur_coords.xtilt = gimp_brush_core_get_cr_spline_point (p,
+								                            	    past_coords.xtilt,
+				 					                                start_coords.xtilt,
+									                                end_coords.xtilt,
+									                                future_coords.xtilt);
+	paint_core->cur_coords.ytilt = gimp_brush_core_get_cr_spline_point (p,
+								                            	    past_coords.ytilt,
+				 					                                start_coords.ytilt,
+									                                end_coords.ytilt,
+									                                future_coords.ytilt);
+	paint_core->cur_coords.wheel = gimp_brush_core_get_cr_spline_point (p,
+								                            	    past_coords.wheel,
+				 					                                start_coords.wheel,
+									                                end_coords.wheel,
+									                                future_coords.wheel);
+	paint_core->cur_coords.velocity = gimp_brush_core_get_cr_spline_point (p,
+								                            	    past_coords.velocity,
+				 					                                start_coords.velocity,
+									                                end_coords.velocity,
+									                                future_coords.velocity);
+
+      gimp_brush_core_linear_interpolate (paint_core, drawable, paint_options,
+                                          time);
+	  
+    }
+
+	  core->p0_coords = start_coords;
+	  core->p1_coords = end_coords;
+      core->p2_coords = future_coords;
+ }
+
+
+static gdouble
+gimp_brush_core_get_cr_spline_point (gdouble  t,
+									 gdouble  p0,
+									 gdouble  p1,
+									 gdouble  p2,
+									 gdouble  p3)
+{
+
+   return (((-t+2.0)*t-1.0)*t/2.0) * p0 + ((((3.0*t-5.0)*t)*t+2-0)/2.0) * p1 
+		+ (((-3.0*t+4.0)*t+1.0)*t/2.0) * p2 + (((t-1)*t*t)/2.0) * p3;
+}
+
+
 static TempBuf *
 gimp_brush_core_get_paint_area (GimpPaintCore    *paint_core,
                                 GimpDrawable     *drawable,
Index: app/paint/gimpbrushcore.h
===================================================================
--- app/paint/gimpbrushcore.h	(revision 26794)
+++ app/paint/gimpbrushcore.h	(working copy)
@@ -26,6 +26,7 @@
 #define BRUSH_CORE_SUBSAMPLE        4
 #define BRUSH_CORE_SOLID_SUBSAMPLE  2
 #define BRUSH_CORE_JITTER_LUTSIZE   360
+#define BRUSH_CORE_SPLINE_THRESHOLD 2.0
 
 
 #define GIMP_TYPE_BRUSH_CORE            (gimp_brush_core_get_type ())
@@ -81,6 +82,15 @@
   gint           n_brush_bound_segs;
   gint           brush_bound_width;
   gint           brush_bound_height;
+  
+  /* Catmull-rom inerpolation needs events from two events ago, so we neeed to 
+     save them. There needs to be one event delay to avoid predicting future
+     event */
+  GimpCoords     p0_coords;
+  GimpCoords     p1_coords;
+  GimpCoords     p2_coords;
+  gboolean       first_segment;
+  gboolean       delayed;
 };
 
 struct _GimpBrushCoreClass
