[gimp/wip/gradient-edit: 28/39] app: modify the gradient in response to blend-tool slider motion



commit 5bd0d7cdcf0bf6aec471e2b9f632bd1a1f0d6e8f
Author: Ell <ell_se yahoo com>
Date:   Tue Aug 1 14:04:28 2017 -0400

    app: modify the gradient in response to blend-tool slider motion
    
    Update the gradient's segment endpoint and midpoint positions,
    according to the sliders.

 app/tools/gimpblendtool-editor.c |  156 ++++++++++++++++++++++++++++++++++++--
 app/tools/gimpblendtool-editor.h |    2 +
 app/tools/gimpblendtool.c        |    2 +
 3 files changed, 153 insertions(+), 7 deletions(-)
---
diff --git a/app/tools/gimpblendtool-editor.c b/app/tools/gimpblendtool-editor.c
index f9552eb..effa1b8 100644
--- a/app/tools/gimpblendtool-editor.c
+++ b/app/tools/gimpblendtool-editor.c
@@ -21,6 +21,7 @@
 #include <gtk/gtk.h>
 #include <gdk/gdkkeysyms.h>
 
+#include "libgimpmath/gimpmath.h"
 #include "libgimpwidgets/gimpwidgets.h"
 
 #include "tools-types.h"
@@ -43,18 +44,24 @@
 #include "gimp-intl.h"
 
 
+#define EPSILON 1e-10
+
+
 /*  local function prototypes  */
 
-static gboolean   gimp_blend_tool_editor_is_gradient_editable (GimpBlendTool *blend_tool);
+static gboolean              gimp_blend_tool_editor_is_gradient_editable (GimpBlendTool *blend_tool);
 
-static void       gimp_blend_tool_editor_block_handlers       (GimpBlendTool *blend_tool);
-static void       gimp_blend_tool_editor_unblock_handlers     (GimpBlendTool *blend_tool);
-static gboolean   gimp_blend_tool_editor_are_handlers_blocked (GimpBlendTool *blend_tool);
+static GimpGradientSegment * gimp_blend_tool_editor_handle_get_segment   (GimpBlendTool *blend_tool,
+                                                                          gint           handle);
 
-static void       gimp_blend_tool_editor_freeze_gradient      (GimpBlendTool *blend_tool);
-static void       gimp_blend_tool_editor_thaw_gradient        (GimpBlendTool *blend_tool);
+static void                  gimp_blend_tool_editor_block_handlers       (GimpBlendTool *blend_tool);
+static void                  gimp_blend_tool_editor_unblock_handlers     (GimpBlendTool *blend_tool);
+static gboolean              gimp_blend_tool_editor_are_handlers_blocked (GimpBlendTool *blend_tool);
 
-static void       gimp_blend_tool_editor_update_sliders       (GimpBlendTool *blend_tool);
+static void                  gimp_blend_tool_editor_freeze_gradient      (GimpBlendTool *blend_tool);
+static void                  gimp_blend_tool_editor_thaw_gradient        (GimpBlendTool *blend_tool);
+
+static void                  gimp_blend_tool_editor_update_sliders       (GimpBlendTool *blend_tool);
 
 
 /*  private functions  */
@@ -69,6 +76,37 @@ gimp_blend_tool_editor_is_gradient_editable (GimpBlendTool *blend_tool)
          gimp_data_is_writable (GIMP_DATA (blend_tool->gradient));
 }
 
+static GimpGradientSegment *
+gimp_blend_tool_editor_handle_get_segment (GimpBlendTool *blend_tool,
+                                           gint           handle)
+{
+  switch (handle)
+    {
+    case GIMP_TOOL_LINE_HANDLE_START:
+      return blend_tool->gradient->segments;
+
+    case GIMP_TOOL_LINE_HANDLE_END:
+      return gimp_gradient_segment_get_last (blend_tool->gradient->segments);
+
+    default:
+      {
+        const GimpControllerSlider *sliders;
+        gint                        n_sliders;
+        gint                        seg_i;
+
+        sliders = gimp_tool_line_get_sliders (GIMP_TOOL_LINE (blend_tool->widget),
+                                              &n_sliders);
+
+        g_assert (handle >= 0 && handle < n_sliders);
+
+        seg_i = GPOINTER_TO_INT (sliders[handle].data);
+
+        return gimp_gradient_segment_get_nth (blend_tool->gradient->segments,
+                                              seg_i);
+      }
+    }
+}
+
 static void
 gimp_blend_tool_editor_block_handlers (GimpBlendTool *blend_tool)
 {
@@ -227,9 +265,14 @@ gimp_blend_tool_editor_update_sliders (GimpBlendTool *blend_tool)
       sliders[i].max   = (1.0 - offset) * sliders[i].max   + offset;
     }
 
+  /* avoid updating the gradient in gimp_blend_tool_editor_line_changed() */
+  gimp_blend_tool_editor_block_handlers (blend_tool);
+
   gimp_tool_line_set_sliders (GIMP_TOOL_LINE (blend_tool->widget),
                               sliders, n_sliders);
 
+  gimp_blend_tool_editor_unblock_handlers (blend_tool);
+
   g_free (sliders);
 }
 
@@ -280,6 +323,105 @@ gimp_blend_tool_editor_options_notify (GimpBlendTool    *blend_tool,
 }
 
 void
+gimp_blend_tool_editor_line_changed (GimpBlendTool *blend_tool)
+{
+  GimpBlendOptions           *options       = GIMP_BLEND_TOOL_GET_OPTIONS (blend_tool);
+  GimpPaintOptions           *paint_options = GIMP_PAINT_OPTIONS (options);
+  gdouble                     offset        = options->offset / 100.0;
+  const GimpControllerSlider *sliders;
+  gint                        n_sliders;
+  gint                        i;
+  GimpGradientSegment        *seg;
+  gboolean                    changed       = FALSE;
+
+  if (gimp_blend_tool_editor_are_handlers_blocked (blend_tool))
+    return;
+
+  if (! blend_tool->gradient || offset == 1.0)
+    return;
+
+  sliders = gimp_tool_line_get_sliders (GIMP_TOOL_LINE (blend_tool->widget),
+                                        &n_sliders);
+
+  if (n_sliders == 0)
+    return;
+
+  /* update the midpoints first, since moving the gradient stops may change the
+   * gradient's midpoints w.r.t. the sliders, but not the other way around.
+   */
+  for (seg = blend_tool->gradient->segments, i = n_sliders / 2;
+       seg;
+       seg = seg->next, i++)
+    {
+      gdouble value;
+
+      value = sliders[i].value;
+
+      /* adjust slider value according to the offset */
+      value = (value - offset) / (1.0 - offset);
+
+      /* flip the slider value, if necessary */
+      if (paint_options->gradient_options->gradient_reverse)
+        value = 1.0 - value;
+
+      if (fabs (value - seg->middle) > EPSILON)
+        {
+          if (! changed)
+            {
+              gimp_blend_tool_editor_freeze_gradient (blend_tool);
+
+              /* refetch the segment, since the gradient might have changed */
+              seg = gimp_blend_tool_editor_handle_get_segment (blend_tool, i);
+
+              changed = TRUE;
+            }
+
+          seg->middle = value;
+        }
+    }
+
+  /* update the gradient stops */
+  for (seg = blend_tool->gradient->segments, i = 0;
+       seg->next;
+       seg = seg->next, i++)
+    {
+      gdouble value;
+
+      value = sliders[i].value;
+
+      /* adjust slider value according to the offset */
+      value = (value - offset) / (1.0 - offset);
+
+      /* flip the slider value, if necessary */
+      if (paint_options->gradient_options->gradient_reverse)
+        value = 1.0 - value;
+
+      if (fabs (value - seg->right) > EPSILON)
+        {
+          if (! changed)
+            {
+              gimp_blend_tool_editor_freeze_gradient (blend_tool);
+
+              /* refetch the segment, since the gradient might have changed */
+              seg = gimp_blend_tool_editor_handle_get_segment (blend_tool, i);
+
+              changed = TRUE;
+            }
+
+          gimp_gradient_segment_range_compress (blend_tool->gradient,
+                                                seg, seg,
+                                                seg->left, value);
+          gimp_gradient_segment_range_compress (blend_tool->gradient,
+                                                seg->next, seg->next,
+                                                value, seg->next->right);
+        }
+    }
+
+  if (changed)
+    gimp_blend_tool_editor_thaw_gradient (blend_tool);
+}
+
+void
 gimp_blend_tool_editor_gradient_dirty (GimpBlendTool *blend_tool)
 {
   if (gimp_blend_tool_editor_are_handlers_blocked (blend_tool))
diff --git a/app/tools/gimpblendtool-editor.h b/app/tools/gimpblendtool-editor.h
index d34324b..0012ad3 100644
--- a/app/tools/gimpblendtool-editor.h
+++ b/app/tools/gimpblendtool-editor.h
@@ -23,6 +23,8 @@ void   gimp_blend_tool_editor_options_notify   (GimpBlendTool    *blend_tool,
                                                 GimpToolOptions  *options,
                                                 const GParamSpec *pspec);
 
+void   gimp_blend_tool_editor_line_changed     (GimpBlendTool    *blend_tool);
+
 void   gimp_blend_tool_editor_gradient_dirty   (GimpBlendTool    *blend_tool);
 
 void   gimp_blend_tool_editor_gradient_changed (GimpBlendTool    *blend_tool);
diff --git a/app/tools/gimpblendtool.c b/app/tools/gimpblendtool.c
index 90bef0a..7fd8eb8 100644
--- a/app/tools/gimpblendtool.c
+++ b/app/tools/gimpblendtool.c
@@ -749,6 +749,8 @@ gimp_blend_tool_line_changed (GimpToolWidget *widget,
 
   gimp_blend_tool_update_graph (blend_tool);
   gimp_drawable_filter_apply (blend_tool->filter, NULL);
+
+  gimp_blend_tool_editor_line_changed (blend_tool);
 }
 
 static void


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