[gimp] Bug 785001 - Enhanced smudge tool: Smudge with painting



commit bcda53ee7b7725a078cc9033cfb3717659da360e
Author: Michael Natterer <mitch gimp org>
Date:   Sat Jul 22 18:20:23 2017 +0200

    Bug 785001 - Enhanced smudge tool: Smudge with painting
    
    Apply patches from shark0r that alow to mix in both constant and
    gradient color while smudging; and clean up the patches.

 app/gegl/gimp-gegl-loops.c       |  159 +++++++++++++++++++++++++++++---------
 app/gegl/gimp-gegl-loops.h       |   16 ++--
 app/paint/gimpsmudge.c           |  141 +++++++++++++++++++++++----------
 app/paint/gimpsmudgeoptions.c    |   44 +++++++++--
 app/paint/gimpsmudgeoptions.h    |    2 +
 app/tools/gimppaintoptions-gui.c |    3 +-
 app/tools/gimpsmudgetool.c       |   13 +++-
 7 files changed, 284 insertions(+), 94 deletions(-)
---
diff --git a/app/gegl/gimp-gegl-loops.c b/app/gegl/gimp-gegl-loops.c
index 1824cdc..21508c8 100644
--- a/app/gegl/gimp-gegl-loops.c
+++ b/app/gegl/gimp-gegl-loops.c
@@ -20,6 +20,12 @@
 
 #include "config.h"
 
+#include <string.h>
+
+#if COMPILE_SSE2_INTRINISICS
+#include <emmintrin.h>
+#endif
+
 #include <cairo.h>
 #include <gdk-pixbuf/gdk-pixbuf.h>
 #include <gegl.h>
@@ -347,69 +353,148 @@ gimp_gegl_dodgeburn (GeglBuffer          *src_buffer,
     }
 }
 
-/*
- * blend_pixels patched 8-24-05 to fix bug #163721.  Note that this change
- * causes the function to treat src1 and src2 asymmetrically.  This gives the
- * right behavior for the smudge tool, which is the only user of this function
- * at the time of patching.  If you want to use the function for something
- * else, caveat emptor.
+/* helper function of gimp_gegl_smudge_with_paint()
+   src and dest can be the same address
+ */
+static void
+gimp_gegl_smudge_with_paint_blend (const gfloat *src1,
+                                   gfloat        src1_rate,
+                                   const gfloat *src2,
+                                   gfloat        src2_rate,
+                                   gfloat       *dest,
+                                   gboolean      no_erasing_src2)
+{
+
+/* 2017/4/13 shark0r : According to my test, SSE decreases about 25%
+ * execution time
+ */
+
+#if defined COMPILE_SSE2_INTRINISICS
+
+  __m128 v_src1  = _mm_loadu_ps (src1);
+  __m128 v_src2  = _mm_loadu_ps (src2);
+  __m128 *v_dest = (__v4sf *) dest;
+
+  gfloat orginal_src2_alpha = v_src2[3];
+  gfloat src1_alpha         = src1_rate * v_src1[3];
+  gfloat src2_alpha         = src2_rate * orginal_src2_alpha;
+  gfloat result_alpha       = src1_alpha + src2_alpha;
+
+  if (result_alpha == 0)
+    {
+      *v_dest = _mm_set1_ps (0);
+      return;
+    }
+
+  *v_dest = (v_src1 * _mm_set1_ps (src1_alpha) +
+             v_src2 * _mm_set1_ps (src2_alpha)) /
+            _mm_set1_ps (result_alpha);
+
+#else
+
+  gfloat orginal_src2_alpha = src2[3];
+  gfloat src1_alpha         = src1_rate * src1[3];
+  gfloat src2_alpha         = src2_rate * orginal_src2_alpha;
+  gfloat result_alpha       = src1_alpha + src2_alpha;
+  gint   b;
+
+  if (result_alpha == 0)
+    {
+      memset (dest, 0, sizeof (gfloat) * 4);
+      return;
+    }
+
+  for (b = 0; b < 3; b++)
+    dest[b] = (src1[b] * src1_alpha + src2[b] * src2_alpha) / result_alpha;
+
+#endif
+
+  if (no_erasing_src2)
+    {
+      result_alpha = MAX (result_alpha, orginal_src2_alpha);
+    }
+
+  dest[3] = result_alpha;
+}
+
+/*  smudge painting calculation. Currently only smudge tool uses this function
+ *  Accum = rate*Accum + (1-rate)*Canvas
+ *  if brush_color!=NULL
+ *    Paint = flow*brushColor + (1-flow)*Accum
+ *  else
+ *    Paint = flow*Paint + (1-flow)*Accum
  */
 void
-gimp_gegl_smudge_blend (GeglBuffer          *top_buffer,
-                        const GeglRectangle *top_rect,
-                        GeglBuffer          *bottom_buffer,
-                        const GeglRectangle *bottom_rect,
-                        GeglBuffer          *dest_buffer,
-                        const GeglRectangle *dest_rect,
-                        gdouble              blend)
+gimp_gegl_smudge_with_paint (GeglBuffer          *accum_buffer,
+                             const GeglRectangle *accum_rect,
+                             GeglBuffer          *canvas_buffer,
+                             const GeglRectangle *canvas_rect,
+                             const GimpRGB       *brush_color,
+                             GeglBuffer          *paint_buffer,
+                             gboolean             no_erasing,
+                             gdouble              flow,
+                             gdouble              rate)
 {
   GeglBufferIterator *iter;
+  gfloat              brush_color_float[4];
+  gfloat              brush_a = flow;
+  GeglAccessMode      paint_buffer_access_mode = (brush_color ?
+                                                  GEGL_ACCESS_WRITE :
+                                                  GEGL_ACCESS_READWRITE);
 
-  iter = gegl_buffer_iterator_new (top_buffer, top_rect, 0,
+  iter = gegl_buffer_iterator_new (accum_buffer, accum_rect, 0,
                                    babl_format ("RGBA float"),
-                                   GEGL_ACCESS_READ, GEGL_ABYSS_NONE);
+                                   GEGL_ACCESS_READWRITE, GEGL_ABYSS_NONE);
 
-  gegl_buffer_iterator_add (iter, bottom_buffer, bottom_rect, 0,
+  gegl_buffer_iterator_add (iter, canvas_buffer, canvas_rect, 0,
                             babl_format ("RGBA float"),
                             GEGL_ACCESS_READ, GEGL_ABYSS_NONE);
 
-  gegl_buffer_iterator_add (iter, dest_buffer, dest_rect, 0,
+  gegl_buffer_iterator_add (iter, paint_buffer, GEGL_RECTANGLE (0, 0, 0, 0), 0,
                             babl_format ("RGBA float"),
-                            GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE);
+                            paint_buffer_access_mode, GEGL_ABYSS_NONE);
+
+  /* convert brush color from double to float */
+  if (brush_color)
+    {
+      const gdouble *brush_color_ptr = &brush_color->r;
+      gint           b;
+
+      for (b = 0; b < 4; b++)
+        brush_color_float[b] = brush_color_ptr[b];
+
+      brush_a *= brush_color_ptr[3];
+    }
 
   while (gegl_buffer_iterator_next (iter))
     {
-      const gfloat *top    = iter->data[0];
-      const gfloat *bottom = iter->data[1];
-      gfloat       *dest   = iter->data[2];
+      gfloat       *accum  = iter->data[0];
+      const gfloat *canvas = iter->data[1];
+      gfloat       *paint  = iter->data[2];
       gint          count  = iter->length;
-      const gfloat  blend1 = 1.0 - blend;
-      const gfloat  blend2 = blend;
 
       while (count--)
         {
-          const gfloat a1 = blend1 * bottom[3];
-          const gfloat a2 = blend2 * top[3];
-          const gfloat a  = a1 + a2;
-          gint         b;
+          /* blend accum_buffer and canvas_buffer to accum_buffer */
+          gimp_gegl_smudge_with_paint_blend (accum, rate, canvas, 1 - rate,
+                                             accum, no_erasing);
 
-          if (a == 0)
+          /* blend accum_buffer and brush color/pixmap to paint_buffer */
+          if (brush_a == 0) /* pure smudge */
             {
-              for (b = 0; b < 4; b++)
-                dest[b] = 0;
+              memcpy (paint, accum, sizeof (gfloat) * 4);
             }
           else
             {
-              for (b = 0; b < 3; b++)
-                dest[b] =
-                  bottom[b] + (bottom[b] * a1 + top[b] * a2 - a * bottom[b]) / a;
+              gfloat *src1 = brush_color ? brush_color_float : paint;
 
-              dest[3] = a;
+              gimp_gegl_smudge_with_paint_blend (src1, flow, accum, 1 - flow,
+                                                 paint, no_erasing);
             }
 
-          top    += 4;
-          bottom += 4;
-          dest   += 4;
+          accum  += 4;
+          canvas += 4;
+          paint  += 4;
         }
     }
 }
diff --git a/app/gegl/gimp-gegl-loops.h b/app/gegl/gimp-gegl-loops.h
index e7dcc68..9528051 100644
--- a/app/gegl/gimp-gegl-loops.h
+++ b/app/gegl/gimp-gegl-loops.h
@@ -43,13 +43,15 @@ void   gimp_gegl_dodgeburn             (GeglBuffer               *src_buffer,
                                         GimpDodgeBurnType         type,
                                         GimpTransferMode          mode);
 
-void   gimp_gegl_smudge_blend          (GeglBuffer               *top_buffer,
-                                        const GeglRectangle      *top_rect,
-                                        GeglBuffer               *bottom_buffer,
-                                        const GeglRectangle      *bottom_rect,
-                                        GeglBuffer               *dest_buffer,
-                                        const GeglRectangle      *dest_rect,
-                                        gdouble                   blend);
+void   gimp_gegl_smudge_with_paint     (GeglBuffer               *accum_buffer,
+                                        const GeglRectangle      *accum_rect,
+                                        GeglBuffer               *canvas_buffer,
+                                        const GeglRectangle      *canvas_rect,
+                                        const GimpRGB            *brush_color,
+                                        GeglBuffer               *paint_buffer,
+                                        gboolean                  no_erasing,
+                                        gdouble                   flow,
+                                        gdouble                   rate);
 
 void   gimp_gegl_apply_mask            (GeglBuffer               *mask_buffer,
                                         const GeglRectangle      *mask_rect,
diff --git a/app/paint/gimpsmudge.c b/app/paint/gimpsmudge.c
index 5a1d8d4..6c1d9eb 100644
--- a/app/paint/gimpsmudge.c
+++ b/app/paint/gimpsmudge.c
@@ -277,23 +277,31 @@ gimp_smudge_motion (GimpPaintCore    *paint_core,
                     GimpPaintOptions *paint_options,
                     GimpSymmetry     *sym)
 {
-  GimpSmudge         *smudge   = GIMP_SMUDGE (paint_core);
-  GimpSmudgeOptions  *options  = GIMP_SMUDGE_OPTIONS (paint_options);
-  GimpContext        *context  = GIMP_CONTEXT (paint_options);
-  GimpDynamics       *dynamics = GIMP_BRUSH_CORE (paint_core)->dynamics;
-  GimpImage          *image    = gimp_item_get_image (GIMP_ITEM (drawable));
+  GimpSmudge         *smudge     = GIMP_SMUDGE (paint_core);
+  GimpBrushCore      *brush_core = GIMP_BRUSH_CORE (paint_core);
+  GimpSmudgeOptions  *options    = GIMP_SMUDGE_OPTIONS (paint_options);
+  GimpContext        *context    = GIMP_CONTEXT (paint_options);
+  GimpDynamics       *dynamics   = GIMP_BRUSH_CORE (paint_core)->dynamics;
+  GimpImage          *image      = gimp_item_get_image (GIMP_ITEM (drawable));
   GeglBuffer         *paint_buffer;
   gint                paint_buffer_x;
   gint                paint_buffer_y;
   gint                paint_buffer_width;
   gint                paint_buffer_height;
+  /* brush dynamics */
   gdouble             fade_point;
   gdouble             opacity;
   gdouble             rate;
-  gdouble             dynamic_rate;
+  gdouble             flow;
+  gdouble             grad_point;
+  /* brush color */
+  GimpRGB             brush_color;
+  GimpRGB            *brush_color_ptr; /* whether use single color or pixmap */
+  /* accum buffer */
   gint                x, y;
-  gdouble             force;
   GeglBuffer         *accum_buffer;
+  /* other variables */
+  gdouble             force;
   GimpCoords         *coords;
   GeglNode           *op;
   gint                paint_width, paint_height;
@@ -317,6 +325,52 @@ gimp_smudge_motion (GimpPaintCore    *paint_core,
                                            paint_options,
                                            coords);
 
+  /* Get brush dynamic values other than opacity */
+  rate = ((options->rate / 100.0) *
+          gimp_dynamics_get_linear_value (dynamics,
+                                          GIMP_DYNAMICS_OUTPUT_RATE,
+                                          coords,
+                                          paint_options,
+                                          fade_point));
+
+  flow = ((options->flow / 100.0) *
+          gimp_dynamics_get_linear_value (dynamics,
+                                          GIMP_DYNAMICS_OUTPUT_FLOW,
+                                          coords,
+                                          paint_options,
+                                          fade_point));
+
+  grad_point = gimp_dynamics_get_linear_value (dynamics,
+                                               GIMP_DYNAMICS_OUTPUT_COLOR,
+                                               coords,
+                                               paint_options,
+                                               fade_point);
+
+  /* Get current gradient color, brush pixmap, or foreground color */
+  brush_color_ptr = &brush_color;
+  if (gimp_paint_options_get_gradient_color (paint_options, image,
+                                             grad_point,
+                                             paint_core->pixel_dist,
+                                             &brush_color))
+    {
+      /* No more processing needed */
+    }
+  else if (brush_core->brush && gimp_brush_get_pixmap (brush_core->brush))
+    {
+      brush_color_ptr = NULL;
+    }
+  else
+    {
+      gimp_context_get_foreground (context, &brush_color);
+    }
+
+  /* Convert to linear RGBA */
+  if (brush_color_ptr)
+    gimp_pickable_srgb_to_pixel (GIMP_PICKABLE (drawable),
+                                 &brush_color,
+                                 babl_format ("RGBA double"),
+                                 &brush_color);
+
   n_strokes = gimp_symmetry_get_size (sym);
   for (i = 0; i < n_strokes; i++)
     {
@@ -343,16 +397,10 @@ gimp_smudge_motion (GimpPaintCore    *paint_core,
       /*  Get the unclipped acumulator coordinates  */
       gimp_smudge_accumulator_coords (paint_core, coords, i, &x, &y);
 
-      /* Enable dynamic rate */
-      dynamic_rate = gimp_dynamics_get_linear_value (dynamics,
-                                                     GIMP_DYNAMICS_OUTPUT_RATE,
-                                                     coords,
-                                                     paint_options,
-                                                     fade_point);
-
-      rate = (options->rate / 100.0) * dynamic_rate;
+      accum_buffer = g_list_nth_data (smudge->accum_buffers, i);
 
-      /*  Smudge uses the buffer Accum.
+      /* Old smudge tool:
+       *  Smudge uses the buffer Accum.
        *  For each successive painthit Accum is built like this
        *    Accum =  rate*Accum  + (1-rate)*I.
        *  where I is the pixels under the current painthit.
@@ -360,33 +408,42 @@ gimp_smudge_motion (GimpPaintCore    *paint_core,
        *    (Accum,1) (if no alpha),
        */
 
-      accum_buffer = g_list_nth_data (smudge->accum_buffers, i);
+      /* 2017/4/22: New smudge painting tool:
+       * Accum=rate*Accum + (1-rate)*I
+       * if brush_color_ptr!=NULL
+       *   Paint=(1-flow)*Accum + flow*BrushColor
+       * else, draw brush pixmap on the paint_buffer and
+       *   Paint=(1-flow)*Accum + flow*Paint
+       *
+       * For non-pixmap brushes, calculate blending in
+       * gimp_gegl_smudge_with_paint() instead of calling
+       * gegl_buffer_set_color() to reduce gegl's internal processing.
+       */
+      if (! brush_color_ptr)
+        {
+          gimp_brush_core_color_area_with_pixmap (brush_core, drawable,
+                                                  coords, op,
+                                                  paint_buffer,
+                                                  paint_buffer_x,
+                                                  paint_buffer_y,
+                                                  gimp_paint_options_get_brush_mode (paint_options));
+        }
 
-      gimp_gegl_smudge_blend (accum_buffer,
-                              GEGL_RECTANGLE (paint_buffer_x - x,
-                                              paint_buffer_y - y,
-                                              paint_buffer_width,
-                                              paint_buffer_height),
-                              gimp_drawable_get_buffer (drawable),
-                              GEGL_RECTANGLE (paint_buffer_x,
-                                              paint_buffer_y,
-                                              paint_buffer_width,
-                                              paint_buffer_height),
-                              accum_buffer,
-                              GEGL_RECTANGLE (paint_buffer_x - x,
-                                              paint_buffer_y - y,
-                                              paint_buffer_width,
-                                              paint_buffer_height),
-                              rate);
-
-      gegl_buffer_copy (accum_buffer,
-                        GEGL_RECTANGLE (paint_buffer_x - x,
-                                        paint_buffer_y - y,
-                                        paint_buffer_width,
-                                        paint_buffer_height),
-                        GEGL_ABYSS_NONE,
-                        paint_buffer,
-                        GEGL_RECTANGLE (0, 0, 0, 0));
+      gimp_gegl_smudge_with_paint (accum_buffer,
+                                   GEGL_RECTANGLE (paint_buffer_x - x,
+                                                   paint_buffer_y - y,
+                                                   paint_buffer_width,
+                                                   paint_buffer_height),
+                                   gimp_drawable_get_buffer (drawable),
+                                   GEGL_RECTANGLE (paint_buffer_x,
+                                                   paint_buffer_y,
+                                                   paint_buffer_width,
+                                                   paint_buffer_height),
+                                   brush_color_ptr,
+                                   paint_buffer,
+                                   options->no_erasing,
+                                   flow,
+                                   rate);
 
       if (gimp_dynamics_is_output_enabled (dynamics, GIMP_DYNAMICS_OUTPUT_FORCE))
         force = gimp_dynamics_get_linear_value (dynamics,
diff --git a/app/paint/gimpsmudgeoptions.c b/app/paint/gimpsmudgeoptions.c
index 73c98f0..1c0096b 100644
--- a/app/paint/gimpsmudgeoptions.c
+++ b/app/paint/gimpsmudgeoptions.c
@@ -29,13 +29,17 @@
 #include "gimp-intl.h"
 
 
-#define SMUDGE_DEFAULT_RATE 50.0
+#define SMUDGE_DEFAULT_RATE       50.0
+#define SMUDGE_DEFAULT_FLOW       0.0
+#define SMUDGE_DEFAULT_NO_ERASING FALSE
 
 
 enum
 {
   PROP_0,
-  PROP_RATE
+  PROP_RATE,
+  PROP_FLOW,
+  PROP_NO_ERASING,
 };
 
 
@@ -64,9 +68,23 @@ gimp_smudge_options_class_init (GimpSmudgeOptionsClass *klass)
   GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_RATE,
                            "rate",
                            C_("smudge-tool", "Rate"),
-                           NULL,
+                           _("The strength of smudging"),
                            0.0, 100.0, SMUDGE_DEFAULT_RATE,
                            GIMP_PARAM_STATIC_STRINGS);
+
+  GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_FLOW,
+                           "flow",
+                           C_("smudge-tool", "Flow"),
+                           _("The amount of brush color to blend"),
+                           0.0, 100.0, SMUDGE_DEFAULT_FLOW,
+                           GIMP_PARAM_STATIC_STRINGS);
+
+  GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_NO_ERASING,
+                            "no-erasing",
+                            C_("smudge-tool", "No erasing effect"),
+                            _("Never decrease alpha of existing pixels"),
+                            SMUDGE_DEFAULT_NO_ERASING,
+                            GIMP_PARAM_STATIC_STRINGS);
 }
 
 static void
@@ -87,6 +105,13 @@ gimp_smudge_options_set_property (GObject      *object,
     case PROP_RATE:
       options->rate = g_value_get_double (value);
       break;
+    case PROP_FLOW:
+      options->flow = g_value_get_double (value);
+      break;
+    case PROP_NO_ERASING:
+      options->no_erasing = g_value_get_boolean (value);
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
       break;
@@ -95,9 +120,9 @@ gimp_smudge_options_set_property (GObject      *object,
 
 static void
 gimp_smudge_options_get_property (GObject    *object,
-                                    guint       property_id,
-                                    GValue     *value,
-                                    GParamSpec *pspec)
+                                  guint       property_id,
+                                  GValue     *value,
+                                  GParamSpec *pspec)
 {
   GimpSmudgeOptions *options = GIMP_SMUDGE_OPTIONS (object);
 
@@ -106,6 +131,13 @@ gimp_smudge_options_get_property (GObject    *object,
     case PROP_RATE:
       g_value_set_double (value, options->rate);
       break;
+    case PROP_FLOW:
+      g_value_set_double (value, options->flow);
+      break;
+    case PROP_NO_ERASING:
+      g_value_set_boolean (value, options->no_erasing);
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
       break;
diff --git a/app/paint/gimpsmudgeoptions.h b/app/paint/gimpsmudgeoptions.h
index 3c1a07a..291feae 100644
--- a/app/paint/gimpsmudgeoptions.h
+++ b/app/paint/gimpsmudgeoptions.h
@@ -37,6 +37,8 @@ struct _GimpSmudgeOptions
   GimpPaintOptions  parent_instance;
 
   gdouble           rate;
+  gdouble           flow;
+  gboolean          no_erasing;
 };
 
 struct _GimpSmudgeOptionsClass
diff --git a/app/tools/gimppaintoptions-gui.c b/app/tools/gimppaintoptions-gui.c
index 0573b94..42f1852 100644
--- a/app/tools/gimppaintoptions-gui.c
+++ b/app/tools/gimppaintoptions-gui.c
@@ -364,7 +364,8 @@ dynamics_options_gui (GimpPaintOptions *paint_options,
   gtk_widget_show (checkbox);
 
   /* Color UI */
-  if (g_type_is_a (tool_type, GIMP_TYPE_PAINTBRUSH_TOOL))
+  if (g_type_is_a (tool_type, GIMP_TYPE_PAINTBRUSH_TOOL) ||
+      tool_type == GIMP_TYPE_SMUDGE_TOOL)
     {
       inner_frame = gimp_frame_new (_("Color Options"));
       gtk_box_pack_start (GTK_BOX (vbox), inner_frame, FALSE, FALSE, 0);
diff --git a/app/tools/gimpsmudgetool.c b/app/tools/gimpsmudgetool.c
index ee5be8a..c332d08 100644
--- a/app/tools/gimpsmudgetool.c
+++ b/app/tools/gimpsmudgetool.c
@@ -49,7 +49,8 @@ gimp_smudge_tool_register (GimpToolRegisterCallback  callback,
   (* callback) (GIMP_TYPE_SMUDGE_TOOL,
                 GIMP_TYPE_SMUDGE_OPTIONS,
                 gimp_smudge_options_gui,
-                GIMP_PAINT_OPTIONS_CONTEXT_MASK,
+                GIMP_PAINT_OPTIONS_CONTEXT_MASK |
+                GIMP_CONTEXT_PROP_MASK_GRADIENT,
                 "gimp-smudge-tool",
                 _("Smudge"),
                 _("Smudge Tool: Smudge selectively using a brush"),
@@ -86,6 +87,11 @@ gimp_smudge_options_gui (GimpToolOptions *tool_options)
   GObject   *config = G_OBJECT (tool_options);
   GtkWidget *vbox   = gimp_paint_options_gui (tool_options);
   GtkWidget *scale;
+  GtkWidget *button;
+
+  button = gimp_prop_check_button_new (config, "no-erasing", NULL);
+  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+  gtk_widget_show (button);
 
   /*  the rate scale  */
   scale = gimp_prop_spin_scale_new (config, "rate", NULL,
@@ -93,5 +99,10 @@ gimp_smudge_options_gui (GimpToolOptions *tool_options)
   gtk_box_pack_start (GTK_BOX (vbox), scale, FALSE, FALSE, 0);
   gtk_widget_show (scale);
 
+  scale = gimp_prop_spin_scale_new (config, "flow", NULL,
+                                    1.0, 10.0, 1);
+  gtk_box_pack_start (GTK_BOX (vbox), scale, FALSE, FALSE, 0);
+  gtk_widget_show (scale);
+
   return vbox;
 }


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