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



commit ac54b0b0d554d590de28626d875cff25e1a8af45
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 |  158 ++++++++++++++++++++++++++++++++++++--
 app/tools/gimpblendtool-editor.h |    2 +
 app/tools/gimpblendtool.c        |    2 +
 app/tools/gimpblendtool.h        |    4 +
 4 files changed, 159 insertions(+), 7 deletions(-)
---
diff --git a/app/tools/gimpblendtool-editor.c b/app/tools/gimpblendtool-editor.c
index e4d32e9..6cdf095 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,14 +44,20 @@
 #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_freeze_gradient      (GimpBlendTool  *blend_tool);
-static void       gimp_blend_tool_editor_thaw_gradient        (GimpBlendTool  *blend_tool);
+static GimpGradientSegment * gimp_blend_tool_editor_handle_get_segment   (GimpBlendTool  *blend_tool,
+                                                                          gint            handle);
 
-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  */
@@ -66,6 +73,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_freeze_gradient (GimpBlendTool *blend_tool)
 {
@@ -117,9 +155,11 @@ gimp_blend_tool_editor_update_sliders (GimpBlendTool *blend_tool)
   GimpControllerSlider *slider;
   gint                  i;
 
-  if (! blend_tool->widget || options->instant)
+  if (! blend_tool->widget || options->instant || blend_tool->modifying)
     return;
 
+  blend_tool->modifying = TRUE;
+
   editable = gimp_blend_tool_editor_is_gradient_editable (blend_tool);
 
   n_segments = gimp_gradient_segment_range_get_n_segments (
@@ -203,6 +243,8 @@ gimp_blend_tool_editor_update_sliders (GimpBlendTool *blend_tool)
                               sliders, n_sliders);
 
   g_free (sliders);
+
+  blend_tool->modifying = FALSE;
 }
 
 
@@ -252,9 +294,111 @@ 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;
+
+  if (offset == 1.0 || ! blend_tool->gradient || blend_tool->modifying)
+    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 (! blend_tool->modifying)
+            {
+              blend_tool->modifying = TRUE;
+
+              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);
+            }
+
+          gimp_gradient_segment_set_middle_pos (blend_tool->gradient,
+                                                seg, 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 (! blend_tool->modifying)
+            {
+              blend_tool->modifying = TRUE;
+
+              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);
+            }
+
+          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 (blend_tool->modifying)
+    {
+      gimp_blend_tool_editor_thaw_gradient (blend_tool);
+
+      blend_tool->modifying = FALSE;
+
+      gimp_blend_tool_editor_update_sliders (blend_tool);
+    }
+}
+
+void
 gimp_blend_tool_editor_gradient_dirty (GimpBlendTool *blend_tool)
 {
-  if (blend_tool->widget)
+  if (blend_tool->widget && ! blend_tool->modifying)
     {
       gimp_blend_tool_editor_update_sliders (blend_tool);
 
@@ -283,7 +427,7 @@ gimp_blend_tool_editor_gradient_changed (GimpBlendTool *blend_tool)
                               ! gimp_data_is_writable (GIMP_DATA (blend_tool->gradient)));
     }
 
-  if (blend_tool->widget)
+  if (blend_tool->widget && ! blend_tool->modifying)
     {
       gimp_blend_tool_editor_update_sliders (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 425007b..8b91866 100644
--- a/app/tools/gimpblendtool.c
+++ b/app/tools/gimpblendtool.c
@@ -746,6 +746,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
diff --git a/app/tools/gimpblendtool.h b/app/tools/gimpblendtool.h
index df7a032..2da233e 100644
--- a/app/tools/gimpblendtool.h
+++ b/app/tools/gimpblendtool.h
@@ -61,6 +61,10 @@ struct _GimpBlendTool
   GeglNode           *dist_node;
   GeglBuffer         *dist_buffer;
   GimpDrawableFilter *filter;
+
+  /*  editor  */
+
+  gboolean            modifying;
 };
 
 struct _GimpBlendToolClass


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