[gimp] app: Clean up smooth so it would be acceptable for master



commit 339deed1da1ec89d65a4993c85d0d2af96ea0d5e
Author: Alexia Death <alexiadeath gmail com>
Date:   Fri Jan 7 20:45:29 2011 +0200

    app: Clean up smooth so it would be acceptable for master

 app/paint/gimpbrushcore.c        |    8 +-
 app/paint/gimpink.c              |    7 +--
 app/paint/gimpink.h              |    1 -
 app/paint/gimppaintcore.c        |   78 +++++++++++++++++++--
 app/paint/gimppaintcore.h        |    8 ++-
 app/paint/gimppaintoptions.c     |  143 +++++---------------------------------
 app/paint/gimppaintoptions.h     |   25 +------
 app/tools/gimppaintoptions-gui.c |   12 ++--
 8 files changed, 108 insertions(+), 174 deletions(-)
---
diff --git a/app/paint/gimpbrushcore.c b/app/paint/gimpbrushcore.c
index f87d6c2..5adfe8b 100644
--- a/app/paint/gimpbrushcore.c
+++ b/app/paint/gimpbrushcore.c
@@ -398,7 +398,7 @@ gimp_brush_core_post_paint (GimpPaintCore    *paint_core,
                             guint32           time)
 {
   GimpBrushCore *core = GIMP_BRUSH_CORE (paint_core);
-  
+
   if (paint_state == GIMP_PAINT_STATE_MOTION)
     {
       core->brush = core->main_brush;
@@ -520,9 +520,9 @@ gimp_brush_core_interpolate (GimpPaintCore    *paint_core,
 
   gimp_paint_core_get_last_coords (paint_core, &last_coords);
   gimp_paint_core_get_current_coords (paint_core, &current_coords);
-  
-  if (paint_core->smoothing_history) {
-    current_coords = gimp_paint_options_get_smoothed_coords(paint_options, &current_coords, paint_core->smoothing_history);
+
+  if (paint_core->stroke_buffer) {
+    current_coords = gimp_paint_core_get_smoothed_coords(paint_core, paint_options, &current_coords);
     gimp_paint_core_set_current_coords (paint_core, &current_coords);
   }
 
diff --git a/app/paint/gimpink.c b/app/paint/gimpink.c
index 247063d..cd5af48 100644
--- a/app/paint/gimpink.c
+++ b/app/paint/gimpink.c
@@ -152,7 +152,6 @@ gimp_ink_paint (GimpPaintCore    *paint_core,
 
     case GIMP_PAINT_STATE_INIT:
       gimp_paint_core_get_last_coords (paint_core, &last_coords);
-      ink->queue = gimp_circular_queue_new(sizeof(GimpCoords), paint_options->smoothing_options->smoothing_history);
 
       if (coords->x == last_coords.x &&
           coords->y == last_coords.y)
@@ -187,8 +186,6 @@ gimp_ink_paint (GimpPaintCore    *paint_core,
       break;
 
     case GIMP_PAINT_STATE_FINISH:
-      gimp_circular_queue_free(ink->queue);
-      ink->queue = NULL;
       break;
     }
 }
@@ -260,8 +257,8 @@ gimp_ink_motion (GimpPaintCore    *paint_core,
   GimpCoords      modified_coords;
 
   image = gimp_item_get_image (GIMP_ITEM (drawable));
-  
-  modified_coords = gimp_paint_options_get_smoothed_coords(paint_options, coords, ink->queue);
+
+  modified_coords = gimp_paint_core_get_smoothed_coords(paint_core, paint_options, coords);
 
   if (! ink->last_blob)
     {
diff --git a/app/paint/gimpink.h b/app/paint/gimpink.h
index dbea24c..da98393 100644
--- a/app/paint/gimpink.h
+++ b/app/paint/gimpink.h
@@ -42,7 +42,6 @@ struct _GimpInk
 
   GimpBlob          *cur_blob;     /*  current blob                   */
   GimpBlob          *last_blob;    /*  blob for last cursor position  */
-  GimpCircularQueue *queue;
 };
 
 struct _GimpInkClass
diff --git a/app/paint/gimppaintcore.c b/app/paint/gimppaintcore.c
index 16df3a1..82aa954 100644
--- a/app/paint/gimppaintcore.c
+++ b/app/paint/gimppaintcore.c
@@ -49,6 +49,7 @@
 
 #include "gimp-intl.h"
 
+#define STROKE_BUFFER_INIT_SIZE      2000
 
 enum
 {
@@ -351,8 +352,16 @@ gimp_paint_core_start (GimpPaintCore     *core,
   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
   item = GIMP_ITEM (drawable);
-  
-  core->smoothing_history = gimp_circular_queue_new (sizeof(GimpCoords), paint_options->smoothing_options->smoothing_history);
+
+  if (core->stroke_buffer != NULL)
+   {
+     g_array_free(core->stroke_buffer, TRUE);
+     core->stroke_buffer = NULL;
+   }
+
+  core->stroke_buffer = g_array_sized_new (TRUE, TRUE,
+                                           sizeof(GimpCoords),
+                                           STROKE_BUFFER_INIT_SIZE);
 
   core->cur_coords = *coords;
 
@@ -420,10 +429,10 @@ gimp_paint_core_finish (GimpPaintCore *core,
   g_return_if_fail (GIMP_IS_PAINT_CORE (core));
   g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
   g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)));
-  
-  if (core->smoothing_history) {
-    gimp_circular_queue_free (core->smoothing_history);
-    core->smoothing_history = NULL;
+
+  if (core->stroke_buffer) {
+    g_array_free (core->stroke_buffer, TRUE);
+    core->stroke_buffer = NULL;
   }
 
   image = gimp_item_get_image (GIMP_ITEM (drawable));
@@ -1240,3 +1249,60 @@ gimp_paint_core_validate_canvas_tiles (GimpPaintCore *core,
         }
     }
 }
+
+GimpCoords gimp_paint_core_get_smoothed_coords (GimpPaintCore    *core,
+                                                GimpPaintOptions *paint_options,
+                                                const GimpCoords *original_coords)
+{
+  GimpSmoothingOptions *smoothing_options = paint_options->smoothing_options;
+  GArray   *history = core->stroke_buffer;
+
+  if (smoothing_options->use_smoothing && smoothing_options->smoothing_quality > 0)
+    {
+      int i;
+      guint length;
+      gint min_index;
+      GimpCoords result = *original_coords;
+      gdouble gaussian_weight = 0.0;
+      gdouble gaussian_weight2 = SQR (smoothing_options->smoothing_factor);
+      gdouble velocity_sum = 0.0;
+      gdouble scale_sum = 0.0;
+
+      result.x = result.y = 0.0;
+
+
+      g_array_append_val (history, *original_coords);
+
+      length = MIN(smoothing_options->smoothing_quality, history->len);
+
+      min_index = history->len - length;
+
+      if (gaussian_weight2 != 0.0)
+        gaussian_weight = 1 / (sqrt (2 * G_PI) * smoothing_options->smoothing_factor);
+
+      for (i = history->len - 1; i >= min_index; i--) {
+          gdouble rate = 0.0;
+          GimpCoords* next_coords = &g_array_index (history,
+                                                    GimpCoords, i);
+
+          if (gaussian_weight2 != 0.0)
+            {
+              /* We use gaussian function with velocity as a window function */
+              velocity_sum += next_coords->velocity * 100;
+              rate = gaussian_weight * exp (-velocity_sum*velocity_sum / (2 * gaussian_weight2));
+            }
+
+          scale_sum += rate;
+          result.x += rate * next_coords->x;
+          result.y += rate * next_coords->y;
+      }
+      if (scale_sum != 0.0)
+        {
+          result.x /= scale_sum;
+          result.y /= scale_sum;
+        }
+
+      return result;
+    }
+    return *original_coords;
+}
diff --git a/app/paint/gimppaintcore.h b/app/paint/gimppaintcore.h
index e914b46..4dbec5a 100644
--- a/app/paint/gimppaintcore.h
+++ b/app/paint/gimppaintcore.h
@@ -64,8 +64,8 @@ struct _GimpPaintCore
   TempBuf     *orig_buf;         /*  the unmodified drawable pixels      */
   TempBuf     *orig_proj_buf;    /*  the unmodified projection pixels    */
   TempBuf     *canvas_buf;       /*  the buffer to paint pixels to       */
-  
-  GimpCircularQueue *smoothing_history;
+
+  GArray      *stroke_buffer;
 };
 
 struct _GimpPaintCoreClass
@@ -204,5 +204,9 @@ void      gimp_paint_core_validate_canvas_tiles     (GimpPaintCore    *core,
                                                      gint              w,
                                                      gint              h);
 
+GimpCoords gimp_paint_core_get_smoothed_coords      (GimpPaintCore    *core,
+                                                     GimpPaintOptions *paint_options,
+                                                     const GimpCoords *original_coords);
+
 
 #endif  /*  __GIMP_PAINT_CORE_H__  */
diff --git a/app/paint/gimppaintoptions.c b/app/paint/gimppaintoptions.c
index 49f1e9e..1f9d43e 100644
--- a/app/paint/gimppaintoptions.c
+++ b/app/paint/gimppaintoptions.c
@@ -36,55 +36,6 @@
 
 #include "gimp-intl.h"
 
-GimpCircularQueue* gimp_circular_queue_new(guint element_size, guint queue_size)
-{
-  GimpCircularQueue* queue = g_new0(GimpCircularQueue, 1);
-  queue->data = g_malloc0(element_size * queue_size);
-  if (queue->data) {
-    queue->element_size = element_size;
-    queue->queue_size = queue_size;
-  }
-  queue->start = 0;
-  queue->end = 0;
-  return queue;
-}
-
-void gimp_circular_queue_free(GimpCircularQueue* queue)
-{
-  if (queue) {
-    if (queue->data)
-      g_free(queue->data);
-    g_free(queue);
-  }
-}
-
-void gimp_circular_queue_enqueue_data(GimpCircularQueue* queue, gpointer data)
-{
-  guint index = queue->end % queue->queue_size;
-
-  if (index > queue->start && index == queue->start % queue->queue_size)
-    queue->start ++;
-    
-  index *= queue->element_size;
-  g_memmove((guchar*)queue->data + index, data, queue->element_size);
-  queue->end ++;
-}
-
-gpointer gimp_circular_queue_get_nth_offset(GimpCircularQueue* queue, guint index)
-{
-  index = (queue->start + index) % queue->queue_size;
-  index *= queue->element_size;
-  return (guchar*)queue->data + index;
-}
-
-gpointer gimp_circular_queue_get_last_offset(GimpCircularQueue* queue)
-{
-  gint index = (queue->end - 1) % queue->queue_size;
-  index *= queue->element_size;
-  return (guchar*)queue->data + index;
-}
-
-
 #define DEFAULT_BRUSH_SIZE             20.0
 #define DEFAULT_BRUSH_ASPECT_RATIO     1.0
 #define DEFAULT_BRUSH_ANGLE            0.0
@@ -110,7 +61,7 @@ gpointer gimp_circular_queue_get_last_offset(GimpCircularQueue* queue)
 #define DYNAMIC_MAX_VALUE              1.0
 #define DYNAMIC_MIN_VALUE              0.0
 
-#define DEFAULT_SMOOTHING_HISTORY      20
+#define DEFAULT_SMOOTHING_QUALITY      20
 #define DEFAULT_SMOOTHING_FACTOR       50
 
 enum
@@ -148,7 +99,7 @@ enum
   PROP_GRADIENT_VIEW_SIZE,
 
   PROP_USE_SMOOTHING,
-  PROP_SMOOTHING_HISTORY,
+  PROP_SMOOTHING_QUALITY,
   PROP_SMOOTHING_FACTOR
 };
 
@@ -298,20 +249,22 @@ gimp_paint_options_class_init (GimpPaintOptionsClass *klass)
                                 GIMP_VIEW_SIZE_LARGE,
                                 GIMP_PARAM_STATIC_STRINGS);
 
-  GIMP_CONFIG_INSTALL_PROP_INT (object_class, PROP_SMOOTHING_HISTORY,
-                                "smoothing-history", NULL,
-                                1,
-                                100,
-                                DEFAULT_SMOOTHING_HISTORY,
-                                GIMP_PARAM_STATIC_STRINGS);
-
   GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_USE_SMOOTHING,
                                     "use-smoothing", NULL,
                                     FALSE,
                                     GIMP_PARAM_STATIC_STRINGS);
+  GIMP_CONFIG_INSTALL_PROP_INT (object_class, PROP_SMOOTHING_QUALITY,
+                                "smoothing-quality", NULL,
+                                1,
+                                100,
+                                DEFAULT_SMOOTHING_QUALITY,
+                                GIMP_PARAM_STATIC_STRINGS);
   GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_SMOOTHING_FACTOR,
                                    "smoothing-factor", NULL,
-                                   0.0, 1000.0, DEFAULT_SMOOTHING_FACTOR,
+                                   3.0, 1000.0, DEFAULT_SMOOTHING_FACTOR, /* Max velocity is set at 3.
+                                                                           * Allowing for smoothing factor to be
+                                                                           * less than velcoty results in numeric
+                                                                           * instablility */
                                    GIMP_PARAM_STATIC_STRINGS);
 }
 
@@ -459,8 +412,8 @@ gimp_paint_options_set_property (GObject      *object,
       smoothing_options->use_smoothing = g_value_get_boolean (value);
       break;
 
-    case PROP_SMOOTHING_HISTORY:
-      smoothing_options->smoothing_history = g_value_get_int (value);
+    case PROP_SMOOTHING_QUALITY:
+      smoothing_options->smoothing_quality = g_value_get_int (value);
       break;
 
     case PROP_SMOOTHING_FACTOR:
@@ -574,13 +527,13 @@ gimp_paint_options_get_property (GObject    *object,
     case PROP_GRADIENT_VIEW_SIZE:
       g_value_set_int (value, options->gradient_view_size);
       break;
-    
+
     case PROP_USE_SMOOTHING:
       g_value_set_boolean(value, smoothing_options->use_smoothing);
       break;
 
-    case PROP_SMOOTHING_HISTORY:
-      g_value_set_int (value, smoothing_options->smoothing_history);
+    case PROP_SMOOTHING_QUALITY:
+      g_value_set_int (value, smoothing_options->smoothing_quality);
       break;
 
     case PROP_SMOOTHING_FACTOR:
@@ -749,65 +702,3 @@ gimp_paint_options_get_brush_mode (GimpPaintOptions *paint_options)
 
   return GIMP_BRUSH_SOFT;
 }
-
-GimpCoords gimp_paint_options_get_smoothed_coords (GimpPaintOptions  *paint_options,
-                                                   const GimpCoords *original_coords,
-                                                   GimpCircularQueue *history)
-{
-  gdouble PI = 4 * atan(1);
-  GimpSmoothingOptions *smoothing_options = paint_options->smoothing_options;
-  if (smoothing_options->use_smoothing && smoothing_options->smoothing_history > 0) {
-    int i;
-    GimpCoords result = *original_coords;
-    guint length;
-    gdouble gaussian_weight = 0.0;
-    gdouble gaussian_weight2 = SQR (smoothing_options->smoothing_factor);
-    gdouble velocity_sum = 0.0;
-    gint min_index;
-    gdouble scale_sum = 0.0;
-    
-    result.x = result.y = 0.0;
-    gimp_circular_queue_enqueue(history, *original_coords);
-    length = gimp_circular_queue_length(history);
-    
-    min_index = length - MIN(length,  smoothing_options->smoothing_history);
-
-    if (gaussian_weight2 != 0.0)
-      gaussian_weight = 1 / (sqrt (2 * PI) * smoothing_options->smoothing_factor);
-      
-//    g_print("IN:%f-%f\n", original_coords->x, original_coords->y); 
-
-    for (i = (int)(length - 1); i >= min_index; i--) {
-        gdouble rate = 0;
-        GimpCoords* next_coords = &gimp_circular_queue_index(history, GimpCoords, i);
-//        g_print("%d: %f-%f\n", i,  next_coords->x, next_coords->y);
-  
-        if (gaussian_weight2 != 0) 
-          {
-            /* We use gaussian function with velocity as a window function */
-            velocity_sum += next_coords->velocity * 100;
-            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 * next_coords->x;
-        result.y += rate * next_coords->y;    
-    }
-    if (scale_sum != 0.0)
-      {
-        result.x /= scale_sum;
-        result.y /= scale_sum;
-      }
-//      g_print("OUT:%f-%f\n", result.x, result.y); 
-    return result;
-  }
-  return *original_coords;  
-}
diff --git a/app/paint/gimppaintoptions.h b/app/paint/gimppaintoptions.h
index 8cc0050..9ec361c 100644
--- a/app/paint/gimppaintoptions.h
+++ b/app/paint/gimppaintoptions.h
@@ -29,25 +29,6 @@
                                         GIMP_CONTEXT_BRUSH_MASK      | \
                                         GIMP_CONTEXT_DYNAMICS_MASK
 
-typedef struct _GimpCircularQueue   GimpCircularQueue;
-struct _GimpCircularQueue
-{
-  guint    element_size;
-  guint    queue_size;
-  guint    start;
-  guint    end;
-  gpointer data;
-};
-GimpCircularQueue* gimp_circular_queue_new(guint element_size, guint queue_size);
-void gimp_circular_queue_free(GimpCircularQueue* queue);
-void gimp_circular_queue_enqueue_data(GimpCircularQueue* queue, gpointer data);
-gpointer gimp_circular_queue_get_nth_offset(GimpCircularQueue* queue, guint index);
-gpointer gimp_circular_queue_get_last_offset(GimpCircularQueue* queue);
-#define gimp_circular_queue_length(q) ((q)->end - (q)->start)
-#define gimp_circular_queue_enqueue(q, a) gimp_circular_queue_enqueue_data(q, (void*)(&(a)))
-#define gimp_circular_queue_index(q, type, i) (*(type*)gimp_circular_queue_get_nth_offset(q, i))
-#define gimp_circular_queue_last(q, type) (*(type*)gimp_circular_queue_get_last_offset(q))
-
 
 typedef struct _GimpJitterOptions   GimpJitterOptions;
 typedef struct _GimpFadeOptions     GimpFadeOptions;
@@ -77,7 +58,7 @@ struct _GimpGradientOptions
 struct _GimpSmoothingOptions
 {
   gboolean use_smoothing;
-  gint     smoothing_history;
+  gint     smoothing_quality;
   gdouble  smoothing_factor;
 };
 
@@ -147,10 +128,6 @@ gboolean gimp_paint_options_get_gradient_color (GimpPaintOptions *paint_options,
                                                 gdouble           pixel_dist,
                                                 GimpRGB          *color);
 
-GimpCoords gimp_paint_options_get_smoothed_coords (GimpPaintOptions  *paint_options,
-                                                   const GimpCoords *original_coords,
-                                                   GimpCircularQueue *history);
-
 GimpBrushApplicationMode
              gimp_paint_options_get_brush_mode (GimpPaintOptions *paint_options);
 
diff --git a/app/tools/gimppaintoptions-gui.c b/app/tools/gimppaintoptions-gui.c
index 0c67618..0010cef 100644
--- a/app/tools/gimppaintoptions-gui.c
+++ b/app/tools/gimppaintoptions-gui.c
@@ -50,6 +50,8 @@
 
 #include "gimp-intl.h"
 
+
+
 static void gimp_paint_options_gui_reset_size (GtkWidget        *button,
                                                GimpPaintOptions *paint_options);
 
@@ -174,7 +176,6 @@ gimp_paint_options_gui (GimpToolOptions *tool_options)
     frame = smoothing_options_gui (options, tool_type);
     gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
     gtk_widget_show (frame);
-    
 
   /*  the "incremental" toggle  */
   if (tool_type == GIMP_TYPE_PENCIL_TOOL     ||
@@ -345,22 +346,21 @@ smoothing_options_gui (GimpPaintOptions *paint_options,
   gtk_table_set_col_spacings (GTK_TABLE (table), 2);
 
   frame = gimp_prop_expanding_frame_new (config, "use-smoothing",
-                                         _("Apply Smoothing"),
+                                         _("Smooth stroke"),
                                          table, NULL);
 
-  gimp_prop_scale_entry_new (config, "smoothing-history",
+  gimp_prop_scale_entry_new (config, "smoothing-quality",
                              GTK_TABLE (table), 0, 0,
                              _("Quality:"),
                              1, 10, 1,
                              FALSE, 0, 100);
-                             
+
   factor = gimp_prop_scale_entry_new (config, "smoothing-factor",
                                       GTK_TABLE (table), 0, 1,
                                       _("Factor:"),
                                       1, 10, 1,
                                       FALSE, 0, 100);
   gimp_scale_entry_set_logarithmic (factor, TRUE);
-  
+
   return frame;
 }
-



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]