[gimp] app: Clean up smooth so it would be acceptable for master
- From: Alexia Death <alexiade src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] app: Clean up smooth so it would be acceptable for master
- Date: Sat, 8 Jan 2011 20:20:58 +0000 (UTC)
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, ¤t_coords);
-
- if (paint_core->smoothing_history) {
- current_coords = gimp_paint_options_get_smoothed_coords(paint_options, ¤t_coords, paint_core->smoothing_history);
+
+ if (paint_core->stroke_buffer) {
+ current_coords = gimp_paint_core_get_smoothed_coords(paint_core, paint_options, ¤t_coords);
gimp_paint_core_set_current_coords (paint_core, ¤t_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]