[gimp] Bug 795207 - Add color space to blend(gradient) tool options



commit bf49b476209ed8350438fa496e7338c172b9b3b3
Author: Michael Natterer <mitch gimp org>
Date:   Fri Apr 13 22:33:16 2018 +0200

    Bug 795207 - Add color space to blend(gradient) tool options
    
    First WIP commit, adds:
    
    - enum GimpGradientBlendColorSpace { RGB_PERCEPTUAL, RGB_LINEAR }
    - linear blending mode for gradient segments
    - tool options GUI for the blend and paint tools which use gradients

 app/actions/gradient-editor-commands.c |    2 +
 app/core/gimpgradient.c                |  133 ++++++++++++++++++++------------
 app/core/gimpgradient.h                |    6 ++
 app/operations/gimpoperationblend.c    |   68 +++++++++++------
 app/operations/gimpoperationblend.h    |   25 +++---
 app/paint/gimppaintoptions.c           |   25 +++++-
 app/paint/gimppaintoptions.h           |    5 +-
 app/pdb/gradient-cmds.c                |   54 +++++++++----
 app/pdb/gradients-cmds.c               |   12 ++-
 app/tools/gimpblendoptions.c           |   10 +++
 app/tools/gimpblendoptions.h           |    2 +-
 app/tools/gimpblendtool-editor.c       |    7 +-
 app/tools/gimppaintoptions-gui.c       |   16 ++++-
 app/widgets/gimpgradienteditor.c       |    8 +-
 app/widgets/gimpgradienteditor.h       |    2 +
 app/widgets/gimpgradientselect.c       |    4 +-
 app/widgets/gimpviewablebox.c          |   47 +++++++++++-
 app/widgets/gimpviewablebox.h          |    4 +-
 app/widgets/gimpviewrenderergradient.c |   25 +++++-
 app/widgets/gimpviewrenderergradient.h |   24 ++++---
 libgimp/gimpenums.c.tail               |    2 +
 libgimpbase/gimpbase.def               |    1 +
 libgimpbase/gimpbaseenums.c            |   30 +++++++
 libgimpbase/gimpbaseenums.h            |   12 +++
 pdb/enums.pl                           |    8 ++
 pdb/groups/gradient.pdb                |   54 +++++++++----
 pdb/groups/gradients.pdb               |   12 ++-
 27 files changed, 445 insertions(+), 153 deletions(-)
---
diff --git a/app/actions/gradient-editor-commands.c b/app/actions/gradient-editor-commands.c
index 1e7e06f..9ffc70e 100644
--- a/app/actions/gradient-editor-commands.c
+++ b/app/actions/gradient-editor-commands.c
@@ -539,6 +539,7 @@ gradient_editor_split_midpoint_cmd_callback (GtkAction *action,
                                               data_editor->context,
                                               editor->control_sel_l,
                                               editor->control_sel_r,
+                                              editor->blend_color_space,
                                               &editor->control_sel_l,
                                               &editor->control_sel_r);
 }
@@ -911,6 +912,7 @@ gradient_editor_split_uniform_response (GtkWidget          *widget,
                                                  editor->control_sel_l,
                                                  editor->control_sel_r,
                                                  editor->split_parts,
+                                                 editor->blend_color_space,
                                                  &editor->control_sel_l,
                                                  &editor->control_sel_r);
     }
diff --git a/app/core/gimpgradient.c b/app/core/gimpgradient.c
index a84e6f0..9043ce8 100644
--- a/app/core/gimpgradient.c
+++ b/app/core/gimpgradient.c
@@ -98,6 +98,9 @@ G_DEFINE_TYPE_WITH_CODE (GimpGradient, gimp_gradient, GIMP_TYPE_DATA,
 
 #define parent_class gimp_gradient_parent_class
 
+static const Babl *fish_srgb_to_linear_rgb = NULL;
+static const Babl *fish_linear_rgb_to_srgb = NULL;
+
 
 static void
 gimp_gradient_class_init (GimpGradientClass *klass)
@@ -120,6 +123,11 @@ gimp_gradient_class_init (GimpGradientClass *klass)
   data_class->get_extension         = gimp_gradient_get_extension;
   data_class->copy                  = gimp_gradient_copy;
   data_class->compare               = gimp_gradient_compare;
+
+  fish_srgb_to_linear_rgb = babl_fish (babl_format ("R'G'B' double"),
+                                       babl_format ("RGB double"));
+  fish_linear_rgb_to_srgb = babl_fish (babl_format ("RGBA double"),
+                                       babl_format ("R'G'B'A double"));
 }
 
 static void
@@ -219,7 +227,9 @@ gimp_gradient_get_new_preview (GimpViewable *viewable,
   for (x = 0; x < width; x++)
     {
       seg = gimp_gradient_get_color_at (gradient, context, seg, cur_x,
-                                        FALSE, &color);
+                                        FALSE,
+                                        GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL,
+                                        &color);
 
       *p++ = ROUND (color.r * 255.0);
       *p++ = ROUND (color.g * 255.0);
@@ -413,12 +423,13 @@ gimp_gradient_get_extension (GimpData *data)
 
 /**
  * gimp_gradient_get_color_at:
- * @gradient: a gradient
- * @context:  a context
- * @seg:      a segment to seed the search with (or %NULL)
- * @pos:      position in the gradient (between 0.0 and 1.0)
- * @reverse:  when %TRUE, use the reversed gradient
- * @color:    returns the color
+ * @gradient:          a gradient
+ * @context:           a context
+ * @seg:               a segment to seed the search with (or %NULL)
+ * @pos:               position in the gradient (between 0.0 and 1.0)
+ * @reverse:           when %TRUE, use the reversed gradient
+ * @blend_color_space: color space to use for blending RGB segments
+ * @color:             returns the color
  *
  * If you are iterating over an gradient, you should pass the the
  * return value from the last call for @seg.
@@ -426,12 +437,13 @@ gimp_gradient_get_extension (GimpData *data)
  * Return value: the gradient segment the color is from
  **/
 GimpGradientSegment *
-gimp_gradient_get_color_at (GimpGradient        *gradient,
-                            GimpContext         *context,
-                            GimpGradientSegment *seg,
-                            gdouble              pos,
-                            gboolean             reverse,
-                            GimpRGB             *color)
+gimp_gradient_get_color_at (GimpGradient                *gradient,
+                            GimpContext                 *context,
+                            GimpGradientSegment         *seg,
+                            gdouble                      pos,
+                            gboolean                     reverse,
+                            GimpGradientBlendColorSpace  blend_color_space,
+                            GimpRGB                     *color)
 {
   gdouble  factor = 0.0;
   gdouble  seg_len;
@@ -502,9 +514,23 @@ gimp_gradient_get_color_at (GimpGradient        *gradient,
 
   if (seg->color == GIMP_GRADIENT_SEGMENT_RGB)
     {
+      if (blend_color_space == GIMP_GRADIENT_BLEND_RGB_LINEAR)
+        {
+          babl_process (fish_srgb_to_linear_rgb,
+                        &left_color, &left_color, 1);
+          babl_process (fish_srgb_to_linear_rgb,
+                        &right_color, &right_color, 1);
+        }
+
       rgb.r = left_color.r + (right_color.r - left_color.r) * factor;
       rgb.g = left_color.g + (right_color.g - left_color.g) * factor;
       rgb.b = left_color.b + (right_color.b - left_color.b) * factor;
+
+      if (blend_color_space == GIMP_GRADIENT_BLEND_RGB_LINEAR)
+        {
+          babl_process (fish_linear_rgb_to_srgb,
+                        &rgb, &rgb, 1);
+        }
     }
   else
     {
@@ -590,12 +616,13 @@ gimp_gradient_has_fg_bg_segments (GimpGradient *gradient)
 }
 
 void
-gimp_gradient_split_at (GimpGradient         *gradient,
-                        GimpContext          *context,
-                        GimpGradientSegment  *seg,
-                        gdouble               pos,
-                        GimpGradientSegment **newl,
-                        GimpGradientSegment **newr)
+gimp_gradient_split_at (GimpGradient                 *gradient,
+                        GimpContext                  *context,
+                        GimpGradientSegment          *seg,
+                        gdouble                       pos,
+                        GimpGradientBlendColorSpace   blend_color_space,
+                        GimpGradientSegment         **newl,
+                        GimpGradientSegment         **newr)
 {
   GimpRGB              color;
   GimpGradientSegment *newseg;
@@ -610,7 +637,7 @@ gimp_gradient_split_at (GimpGradient         *gradient,
 
   /* Get color at pos */
   gimp_gradient_get_color_at (gradient, context, seg, pos,
-                              FALSE, &color);
+                              FALSE, blend_color_space, &color);
 
   /* Create a new segment and insert it in the list */
 
@@ -779,11 +806,12 @@ gimp_gradient_segment_get_nth (GimpGradientSegment *seg,
 }
 
 void
-gimp_gradient_segment_split_midpoint (GimpGradient         *gradient,
-                                      GimpContext          *context,
-                                      GimpGradientSegment  *lseg,
-                                      GimpGradientSegment **newl,
-                                      GimpGradientSegment **newr)
+gimp_gradient_segment_split_midpoint (GimpGradient                 *gradient,
+                                      GimpContext                  *context,
+                                      GimpGradientSegment          *lseg,
+                                      GimpGradientBlendColorSpace   blend_color_space,
+                                      GimpGradientSegment         **newl,
+                                      GimpGradientSegment         **newr)
 {
   g_return_if_fail (GIMP_IS_GRADIENT (gradient));
   g_return_if_fail (GIMP_IS_CONTEXT (context));
@@ -791,16 +819,18 @@ gimp_gradient_segment_split_midpoint (GimpGradient         *gradient,
   g_return_if_fail (newl != NULL);
   g_return_if_fail (newr != NULL);
 
-  gimp_gradient_split_at (gradient, context, lseg, lseg->middle, newl, newr);
+  gimp_gradient_split_at (gradient, context, lseg, lseg->middle,
+                          blend_color_space, newl, newr);
 }
 
 void
-gimp_gradient_segment_split_uniform (GimpGradient         *gradient,
-                                     GimpContext          *context,
-                                     GimpGradientSegment  *lseg,
-                                     gint                  parts,
-                                     GimpGradientSegment **newl,
-                                     GimpGradientSegment **newr)
+gimp_gradient_segment_split_uniform (GimpGradient                 *gradient,
+                                     GimpContext                  *context,
+                                     GimpGradientSegment          *lseg,
+                                     gint                          parts,
+                                     GimpGradientBlendColorSpace   blend_color_space,
+                                     GimpGradientSegment         **newl,
+                                     GimpGradientSegment         **newr)
 {
   GimpGradientSegment *seg, *prev, *tmp;
   gdouble              seg_len;
@@ -835,9 +865,11 @@ gimp_gradient_segment_split_uniform (GimpGradient         *gradient,
       seg->right_color_type = GIMP_GRADIENT_COLOR_FIXED;
 
       gimp_gradient_get_color_at (gradient, context, lseg,
-                                  seg->left,  FALSE, &seg->left_color);
+                                  seg->left,  FALSE, blend_color_space,
+                                  &seg->left_color);
       gimp_gradient_get_color_at (gradient, context, lseg,
-                                  seg->right, FALSE, &seg->right_color);
+                                  seg->right, FALSE, blend_color_space,
+                                  &seg->right_color);
 
       seg->type  = lseg->type;
       seg->color = lseg->color;
@@ -1626,12 +1658,13 @@ gimp_gradient_segment_range_replicate (GimpGradient         *gradient,
 }
 
 void
-gimp_gradient_segment_range_split_midpoint (GimpGradient         *gradient,
-                                            GimpContext          *context,
-                                            GimpGradientSegment  *start_seg,
-                                            GimpGradientSegment  *end_seg,
-                                            GimpGradientSegment **final_start_seg,
-                                            GimpGradientSegment **final_end_seg)
+gimp_gradient_segment_range_split_midpoint (GimpGradient                 *gradient,
+                                            GimpContext                  *context,
+                                            GimpGradientSegment          *start_seg,
+                                            GimpGradientSegment          *end_seg,
+                                            GimpGradientBlendColorSpace   blend_color_space,
+                                            GimpGradientSegment         **final_start_seg,
+                                            GimpGradientSegment         **final_end_seg)
 {
   GimpGradientSegment *seg, *lseg, *rseg;
 
@@ -1648,7 +1681,8 @@ gimp_gradient_segment_range_split_midpoint (GimpGradient         *gradient,
   do
     {
       gimp_gradient_segment_split_midpoint (gradient, context,
-                                            seg, &lseg, &rseg);
+                                            seg, blend_color_space,
+                                            &lseg, &rseg);
       seg = rseg->next;
     }
   while (lseg != end_seg);
@@ -1663,13 +1697,14 @@ gimp_gradient_segment_range_split_midpoint (GimpGradient         *gradient,
 }
 
 void
-gimp_gradient_segment_range_split_uniform (GimpGradient         *gradient,
-                                           GimpContext          *context,
-                                           GimpGradientSegment  *start_seg,
-                                           GimpGradientSegment  *end_seg,
-                                           gint                  parts,
-                                           GimpGradientSegment **final_start_seg,
-                                           GimpGradientSegment **final_end_seg)
+gimp_gradient_segment_range_split_uniform (GimpGradient                 *gradient,
+                                           GimpContext                  *context,
+                                           GimpGradientSegment          *start_seg,
+                                           GimpGradientSegment          *end_seg,
+                                           gint                          parts,
+                                           GimpGradientBlendColorSpace   blend_color_space,
+                                           GimpGradientSegment         **final_start_seg,
+                                           GimpGradientSegment         **final_end_seg)
 {
   GimpGradientSegment *seg, *aseg, *lseg, *rseg, *lsel;
 
@@ -1696,7 +1731,7 @@ gimp_gradient_segment_range_split_uniform (GimpGradient         *gradient,
       aseg = seg;
 
       gimp_gradient_segment_split_uniform (gradient, context, seg,
-                                           parts,
+                                           parts, blend_color_space,
                                            &lseg, &rseg);
 
       if (seg == start_seg)
diff --git a/app/core/gimpgradient.h b/app/core/gimpgradient.h
index c550ba1..e228ec4 100644
--- a/app/core/gimpgradient.h
+++ b/app/core/gimpgradient.h
@@ -76,6 +76,7 @@ GimpGradientSegment * gimp_gradient_get_color_at   (GimpGradient        *gradien
                                                     GimpGradientSegment *seg,
                                                     gdouble              pos,
                                                     gboolean             reverse,
+                                                    GimpGradientBlendColorSpace blend_color_space,
                                                     GimpRGB             *color);
 GimpGradientSegment * gimp_gradient_get_segment_at (GimpGradient  *grad,
                                                     gdouble        pos);
@@ -83,6 +84,7 @@ void                  gimp_gradient_split_at       (GimpGradient         *gradie
                                                     GimpContext          *context,
                                                     GimpGradientSegment  *seg,
                                                     gdouble               pos,
+                                                    GimpGradientBlendColorSpace blend_color_space,
                                                     GimpGradientSegment **newl,
                                                     GimpGradientSegment **newr);
 
@@ -105,12 +107,14 @@ void                  gimp_gradient_segments_free     (GimpGradientSegment *seg)
 void    gimp_gradient_segment_split_midpoint  (GimpGradient         *gradient,
                                                GimpContext          *context,
                                                GimpGradientSegment  *lseg,
+                                               GimpGradientBlendColorSpace blend_color_space,
                                                GimpGradientSegment **newl,
                                                GimpGradientSegment **newr);
 void    gimp_gradient_segment_split_uniform   (GimpGradient         *gradient,
                                                GimpContext          *context,
                                                GimpGradientSegment  *lseg,
                                                gint                  parts,
+                                               GimpGradientBlendColorSpace blend_color_space,
                                                GimpGradientSegment **newl,
                                                GimpGradientSegment **newr);
 
@@ -247,6 +251,7 @@ void    gimp_gradient_segment_range_split_midpoint
                                                GimpContext          *context,
                                                GimpGradientSegment  *start_seg,
                                                GimpGradientSegment  *end_seg,
+                                               GimpGradientBlendColorSpace blend_color_space,
                                                GimpGradientSegment **final_start_seg,
                                                GimpGradientSegment **final_end_seg);
 
@@ -256,6 +261,7 @@ void    gimp_gradient_segment_range_split_uniform
                                                GimpGradientSegment  *start_seg,
                                                GimpGradientSegment  *end_seg,
                                                gint                  parts,
+                                               GimpGradientBlendColorSpace blend_color_space,
                                                GimpGradientSegment **final_start_seg,
                                                GimpGradientSegment **final_end_seg);
 
diff --git a/app/operations/gimpoperationblend.c b/app/operations/gimpoperationblend.c
index 0ad5494..8c43679 100644
--- a/app/operations/gimpoperationblend.c
+++ b/app/operations/gimpoperationblend.c
@@ -53,6 +53,7 @@ enum
   PROP_GRADIENT_REPEAT,
   PROP_OFFSET,
   PROP_GRADIENT_REVERSE,
+  PROP_GRADIENT_BLEND_COLOR_SPACE,
   PROP_SUPERSAMPLE,
   PROP_SUPERSAMPLE_DEPTH,
   PROP_SUPERSAMPLE_THRESHOLD,
@@ -61,24 +62,25 @@ enum
 
 typedef struct
 {
-  GimpGradient        *gradient;
-  gboolean             reverse;
+  GimpGradient                *gradient;
+  gboolean                     reverse;
+  GimpGradientBlendColorSpace  blend_color_space;
 #ifdef USE_GRADIENT_CACHE
-  GimpRGB             *gradient_cache;
-  gint                 gradient_cache_size;
+  GimpRGB                     *gradient_cache;
+  gint                         gradient_cache_size;
 #else
-  GimpGradientSegment *last_seg;
+  GimpGradientSegment         *last_seg;
 #endif
-  gdouble              offset;
-  gdouble              sx, sy;
-  GimpGradientType     gradient_type;
-  gdouble              dist;
-  gdouble              vec[2];
-  GimpRepeatMode       repeat;
-  GimpRGB              leftmost_color;
-  GimpRGB              rightmost_color;
-  GRand               *seed;
-  GeglBuffer          *dist_buffer;
+  gdouble                      offset;
+  gdouble                      sx, sy;
+  GimpGradientType             gradient_type;
+  gdouble                      dist;
+  gdouble                      vec[2];
+  GimpRepeatMode               repeat;
+  GimpRGB                      leftmost_color;
+  GimpRGB                      rightmost_color;
+  GRand                       *seed;
+  GeglBuffer                  *dist_buffer;
 } RenderBlendData;
 
 
@@ -281,6 +283,15 @@ gimp_operation_blend_class_init (GimpOperationBlendClass *klass)
                                                          G_PARAM_READWRITE |
                                                          G_PARAM_CONSTRUCT));
 
+  g_object_class_install_property (object_class, PROP_GRADIENT_BLEND_COLOR_SPACE,
+                                   g_param_spec_enum ("gradient-blend-color-space",
+                                                      "Blend Color Space",
+                                                      "Which color space to use when blending RGB gradient 
segments",
+                                                      GIMP_TYPE_GRADIENT_BLEND_COLOR_SPACE,
+                                                      GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL,
+                                                      G_PARAM_READWRITE |
+                                                      G_PARAM_CONSTRUCT));
+
   g_object_class_install_property (object_class, PROP_SUPERSAMPLE,
                                    g_param_spec_boolean ("supersample",
                                                          "Supersample",
@@ -380,6 +391,10 @@ gimp_operation_blend_get_property (GObject    *object,
       g_value_set_boolean (value, self->gradient_reverse);
       break;
 
+    case PROP_GRADIENT_BLEND_COLOR_SPACE:
+      g_value_set_enum (value, self->gradient_blend_color_space);
+      break;
+
     case PROP_SUPERSAMPLE:
       g_value_set_boolean (value, self->supersample);
       break;
@@ -423,11 +438,7 @@ gimp_operation_blend_set_property (GObject      *object,
       {
         GimpGradient *gradient = g_value_get_object (value);
 
-        if (self->gradient)
-          {
-            g_object_unref (self->gradient);
-            self->gradient = NULL;
-          }
+        g_clear_object (&self->gradient);
 
         if (gradient)
           {
@@ -471,6 +482,10 @@ gimp_operation_blend_set_property (GObject      *object,
       self->gradient_reverse = g_value_get_boolean (value);
       break;
 
+    case PROP_GRADIENT_BLEND_COLOR_SPACE:
+      self->gradient_blend_color_space = g_value_get_enum (value);
+      break;
+
     case PROP_SUPERSAMPLE:
       self->supersample = g_value_get_boolean (value);
       break;
@@ -928,7 +943,9 @@ gradient_render_pixel (gdouble   x,
 #else
       rbd->last_seg = gimp_gradient_get_color_at (rbd->gradient, NULL,
                                                   rbd->last_seg, factor,
-                                                  rbd->reverse, color);
+                                                  rbd->reverse,
+                                                  rbd->blend_color_space,
+                                                  color);
 #endif
     }
 }
@@ -993,8 +1010,9 @@ gimp_operation_blend_process (GeglOperation       *operation,
 
   RenderBlendData rbd = { 0, };
 
-  rbd.gradient = NULL;
-  rbd.reverse  = self->gradient_reverse;
+  rbd.gradient          = NULL;
+  rbd.reverse           = self->gradient_reverse;
+  rbd.blend_color_space = self->gradient_blend_color_space;
 
   if (self->gradient)
     rbd.gradient = g_object_ref (self->gradient);
@@ -1014,7 +1032,9 @@ gimp_operation_blend_process (GeglOperation       *operation,
         gdouble factor = (gdouble) i / (gdouble) (rbd.gradient_cache_size - 1);
 
         last_seg = gimp_gradient_get_color_at (rbd.gradient, NULL, last_seg,
-                                               factor, rbd.reverse,
+                                               factor,
+                                               rbd.reverse,
+                                               rbd.blend_color_space,
                                                rbd.gradient_cache + i);
       }
   }
diff --git a/app/operations/gimpoperationblend.h b/app/operations/gimpoperationblend.h
index 61bd319..763ff93 100644
--- a/app/operations/gimpoperationblend.h
+++ b/app/operations/gimpoperationblend.h
@@ -38,22 +38,23 @@ typedef struct _GimpOperationBlendClass GimpOperationBlendClass;
 
 struct _GimpOperationBlend
 {
-  GeglOperationFilter  parent_instance;
+  GeglOperationFilter           parent_instance;
 
-  GimpContext         *context;
+  GimpContext                  *context;
 
-  GimpGradient        *gradient;
-  gdouble              start_x, start_y, end_x, end_y;
-  GimpGradientType     gradient_type;
-  GimpRepeatMode       gradient_repeat;
-  gdouble              offset;
-  gboolean             gradient_reverse;
+  GimpGradient                 *gradient;
+  gdouble                       start_x, start_y, end_x, end_y;
+  GimpGradientType              gradient_type;
+  GimpRepeatMode                gradient_repeat;
+  gdouble                       offset;
+  gboolean                      gradient_reverse;
+  GimpGradientBlendColorSpace   gradient_blend_color_space;
 
-  gboolean             supersample;
-  gint                 supersample_depth;
-  gdouble              supersample_threshold;
+  gboolean                      supersample;
+  gint                          supersample_depth;
+  gdouble                       supersample_threshold;
 
-  gboolean             dither;
+  gboolean                      dither;
 };
 
 struct _GimpOperationBlendClass
diff --git a/app/paint/gimppaintoptions.c b/app/paint/gimppaintoptions.c
index 53290cd..de5d219 100644
--- a/app/paint/gimppaintoptions.c
+++ b/app/paint/gimppaintoptions.c
@@ -68,6 +68,7 @@
 #define DEFAULT_FADE_UNIT               GIMP_UNIT_PIXEL
 
 #define DEFAULT_GRADIENT_REVERSE        FALSE
+#define DEFAULT_GRADIENT_BLEND_SPACE    GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL
 #define DEFAULT_GRADIENT_REPEAT         GIMP_REPEAT_TRIANGULAR
 #define DEFAULT_GRADIENT_LENGTH         100.0
 #define DEFAULT_GRADIENT_UNIT           GIMP_UNIT_PIXEL
@@ -115,6 +116,7 @@ enum
   PROP_FADE_UNIT,
 
   PROP_GRADIENT_REVERSE,
+  PROP_GRADIENT_BLEND_COLOR_SPACE,
 
   PROP_BRUSH_VIEW_TYPE,
   PROP_BRUSH_VIEW_SIZE,
@@ -335,6 +337,13 @@ gimp_paint_options_class_init (GimpPaintOptionsClass *klass)
                             NULL, NULL,
                             DEFAULT_GRADIENT_REVERSE,
                             GIMP_PARAM_STATIC_STRINGS);
+  GIMP_CONFIG_PROP_ENUM (object_class, PROP_GRADIENT_BLEND_COLOR_SPACE,
+                         "gradient-blend-color-space",
+                         _("Blend Color Space"),
+                         _("Which color space to use when blending RGB gradient segments"),
+                         GIMP_TYPE_GRADIENT_BLEND_COLOR_SPACE,
+                         DEFAULT_GRADIENT_BLEND_SPACE,
+                         GIMP_PARAM_STATIC_STRINGS);
 
   GIMP_CONFIG_PROP_ENUM (object_class, PROP_BRUSH_VIEW_TYPE,
                          "brush-view-type",
@@ -576,6 +585,9 @@ gimp_paint_options_set_property (GObject      *object,
     case PROP_GRADIENT_REVERSE:
       gradient_options->gradient_reverse = g_value_get_boolean (value);
       break;
+    case PROP_GRADIENT_BLEND_COLOR_SPACE:
+      gradient_options->gradient_blend_color_space = g_value_get_enum (value);
+      break;
 
     case PROP_BRUSH_VIEW_TYPE:
       options->brush_view_type = g_value_get_enum (value);
@@ -736,6 +748,9 @@ gimp_paint_options_get_property (GObject    *object,
     case PROP_GRADIENT_REVERSE:
       g_value_set_boolean (value, gradient_options->gradient_reverse);
       break;
+    case PROP_GRADIENT_BLEND_COLOR_SPACE:
+      g_value_set_enum (value, gradient_options->gradient_blend_color_space);
+      break;
 
     case PROP_BRUSH_VIEW_TYPE:
       g_value_set_enum (value, options->brush_view_type);
@@ -951,6 +966,7 @@ gimp_paint_options_get_gradient_color (GimpPaintOptions *paint_options,
       gimp_gradient_get_color_at (gradient, GIMP_CONTEXT (paint_options),
                                   NULL, grad_point,
                                   gradient_options->gradient_reverse,
+                                  gradient_options->gradient_blend_color_space,
                                   color);
 
       return TRUE;
@@ -1192,16 +1208,19 @@ void
 gimp_paint_options_copy_gradient_props (GimpPaintOptions *src,
                                         GimpPaintOptions *dest)
 {
-  gboolean gradient_reverse;
+  gboolean                    gradient_reverse;
+  GimpGradientBlendColorSpace gradient_blend_color_space;
 
   g_return_if_fail (GIMP_IS_PAINT_OPTIONS (src));
   g_return_if_fail (GIMP_IS_PAINT_OPTIONS (dest));
 
   g_object_get (src,
-                "gradient-reverse", &gradient_reverse,
+                "gradient-reverse",           &gradient_reverse,
+                "gradient-blend-color-space", &gradient_blend_color_space,
                 NULL);
 
   g_object_set (dest,
-                "gradient-reverse", gradient_reverse,
+                "gradient-reverse",           gradient_reverse,
+                "gradient-blend-color-space", gradient_blend_color_space,
                 NULL);
 }
diff --git a/app/paint/gimppaintoptions.h b/app/paint/gimppaintoptions.h
index 6ae02c0..19b18e5 100644
--- a/app/paint/gimppaintoptions.h
+++ b/app/paint/gimppaintoptions.h
@@ -52,8 +52,9 @@ struct _GimpFadeOptions
 
 struct _GimpGradientOptions
 {
-  gboolean        gradient_reverse;
-  GimpRepeatMode  gradient_repeat;
+  gboolean                    gradient_reverse;
+  GimpGradientBlendColorSpace gradient_blend_color_space;
+  GimpRepeatMode              gradient_repeat;
 };
 
 struct _GimpSmoothingOptions
diff --git a/app/pdb/gradient-cmds.c b/app/pdb/gradient-cmds.c
index cfce30d..84b843c 100644
--- a/app/pdb/gradient-cmds.c
+++ b/app/pdb/gradient-cmds.c
@@ -335,7 +335,9 @@ gradient_get_uniform_samples_invoker (GimpProcedure         *procedure,
 
   if (success)
     {
-      GimpGradient *gradient = gimp_pdb_get_gradient (gimp, name, GIMP_PDB_DATA_ACCESS_READ, error);
+      GimpGradient *gradient = gimp_pdb_get_gradient (gimp, name,
+                                                      GIMP_PDB_DATA_ACCESS_READ,
+                                                      error);
 
       if (gradient)
         {
@@ -353,7 +355,9 @@ gradient_get_uniform_samples_invoker (GimpProcedure         *procedure,
               GimpRGB color;
 
               seg = gimp_gradient_get_color_at (gradient, context, seg,
-                                                pos, reverse, &color);
+                                                pos, reverse,
+                                                GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL,
+                                                &color);
 
               *sample++ = color.r;
               *sample++ = color.g;
@@ -403,7 +407,9 @@ gradient_get_custom_samples_invoker (GimpProcedure         *procedure,
 
   if (success)
     {
-      GimpGradient *gradient = gimp_pdb_get_gradient (gimp, name, GIMP_PDB_DATA_ACCESS_READ, error);
+      GimpGradient *gradient = gimp_pdb_get_gradient (gimp, name,
+                                                      GIMP_PDB_DATA_ACCESS_READ,
+                                                      error);
 
       if (gradient)
         {
@@ -420,7 +426,9 @@ gradient_get_custom_samples_invoker (GimpProcedure         *procedure,
 
               seg = gimp_gradient_get_color_at (gradient, context,
                                                 seg, *positions,
-                                                reverse, &color);
+                                                reverse,
+                                                GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL,
+                                                &color);
 
               *sample++ = color.r;
               *sample++ = color.g;
@@ -469,7 +477,8 @@ gradient_segment_get_left_color_invoker (GimpProcedure         *procedure,
       GimpGradient        *gradient;
       GimpGradientSegment *seg;
 
-      gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_READ, segment, &seg, error);
+      gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_READ, segment,
+                               &seg, error);
 
       if (seg)
         {
@@ -516,7 +525,8 @@ gradient_segment_set_left_color_invoker (GimpProcedure         *procedure,
       GimpGradient        *gradient;
       GimpGradientSegment *seg;
 
-      gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_WRITE, segment, &seg, error);
+      gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_WRITE, segment,
+                               &seg, error);
 
       if (seg)
         {
@@ -554,7 +564,8 @@ gradient_segment_get_right_color_invoker (GimpProcedure         *procedure,
       GimpGradient        *gradient;
       GimpGradientSegment *seg;
 
-      gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_READ, segment, &seg, error);
+      gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_READ, segment,
+                               &seg, error);
 
       if (seg)
         {
@@ -601,7 +612,8 @@ gradient_segment_set_right_color_invoker (GimpProcedure         *procedure,
       GimpGradient        *gradient;
       GimpGradientSegment *seg;
 
-      gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_WRITE, segment, &seg, error);
+      gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_WRITE, segment,
+                               &seg, error);
 
       if (seg)
         {
@@ -638,7 +650,8 @@ gradient_segment_get_left_pos_invoker (GimpProcedure         *procedure,
       GimpGradient        *gradient;
       GimpGradientSegment *seg;
 
-      gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_READ, segment, &seg, error);
+      gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_READ, segment,
+                               &seg, error);
 
       if (seg)
         {
@@ -681,7 +694,8 @@ gradient_segment_set_left_pos_invoker (GimpProcedure         *procedure,
       GimpGradient        *gradient;
       GimpGradientSegment *seg;
 
-      gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_WRITE, segment, &seg, error);
+      gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_WRITE, segment,
+                               &seg, error);
 
       if (seg)
         {
@@ -722,7 +736,8 @@ gradient_segment_get_middle_pos_invoker (GimpProcedure         *procedure,
       GimpGradient        *gradient;
       GimpGradientSegment *seg;
 
-      gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_READ, segment, &seg, error);
+      gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_READ, segment,
+                               &seg, error);
 
       if (seg)
         {
@@ -765,7 +780,8 @@ gradient_segment_set_middle_pos_invoker (GimpProcedure         *procedure,
       GimpGradient        *gradient;
       GimpGradientSegment *seg;
 
-      gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_WRITE, segment, &seg, error);
+      gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_WRITE, segment,
+                               &seg, error);
 
       if (seg)
         {
@@ -807,7 +823,8 @@ gradient_segment_get_right_pos_invoker (GimpProcedure         *procedure,
       GimpGradient        *gradient;
       GimpGradientSegment *seg;
 
-      gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_READ, segment, &seg, error);
+      gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_READ, segment,
+                               &seg, error);
 
       if (seg)
         {
@@ -850,7 +867,8 @@ gradient_segment_set_right_pos_invoker (GimpProcedure         *procedure,
       GimpGradient        *gradient;
       GimpGradientSegment *seg;
 
-      gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_WRITE, segment, &seg, error);
+      gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_WRITE, segment,
+                               &seg, error);
 
       if (seg)
         {
@@ -892,7 +910,8 @@ gradient_segment_get_blending_function_invoker (GimpProcedure         *procedure
       GimpGradient        *gradient;
       GimpGradientSegment *seg;
 
-      gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_READ, segment, &seg, error);
+      gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_READ, segment,
+                               &seg, error);
 
       if (seg)
         {
@@ -933,7 +952,8 @@ gradient_segment_get_coloring_type_invoker (GimpProcedure         *procedure,
       GimpGradient        *gradient;
       GimpGradientSegment *seg;
 
-      gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_READ, segment, &seg, error);
+      gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_READ, segment,
+                               &seg, error);
 
       if (seg)
         {
@@ -1149,6 +1169,7 @@ gradient_segment_range_split_midpoint_invoker (GimpProcedure         *procedure,
         {
           gimp_gradient_segment_range_split_midpoint (gradient, context,
                                                       start_seg, end_seg,
+                                                      GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL,
                                                       NULL, NULL);
         }
       else
@@ -1192,6 +1213,7 @@ gradient_segment_range_split_uniform_invoker (GimpProcedure         *procedure,
           gimp_gradient_segment_range_split_uniform (gradient, context,
                                                      start_seg, end_seg,
                                                      split_parts,
+                                                     GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL,
                                                      NULL, NULL);
         }
       else
diff --git a/app/pdb/gradients-cmds.c b/app/pdb/gradients-cmds.c
index a6002e7..12002ab 100644
--- a/app/pdb/gradients-cmds.c
+++ b/app/pdb/gradients-cmds.c
@@ -127,7 +127,9 @@ gradients_sample_uniform_invoker (GimpProcedure         *procedure,
       while (num_samples--)
         {
           seg = gimp_gradient_get_color_at (gradient, context, seg,
-                                            pos, reverse, &color);
+                                            pos, reverse,
+                                            GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL,
+                                            &color);
 
           *pv++ = color.r;
           *pv++ = color.g;
@@ -186,7 +188,9 @@ gradients_sample_custom_invoker (GimpProcedure         *procedure,
       while (num_samples--)
         {
           seg = gimp_gradient_get_color_at (gradient, context, seg,
-                                            *positions, reverse, &color);
+                                            *positions, reverse,
+                                            GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL,
+                                            &color);
 
           *pv++ = color.r;
           *pv++ = color.g;
@@ -261,7 +265,9 @@ gradients_get_gradient_data_invoker (GimpProcedure         *procedure,
           while (sample_size--)
             {
               seg = gimp_gradient_get_color_at (gradient, context, seg,
-                                                pos, reverse, &color);
+                                                pos, reverse,
+                                                GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL,
+                                                &color);
 
               *pv++ = color.r;
               *pv++ = color.g;
diff --git a/app/tools/gimpblendoptions.c b/app/tools/gimpblendoptions.c
index 40ecd29..7ef1d99 100644
--- a/app/tools/gimpblendoptions.c
+++ b/app/tools/gimpblendoptions.c
@@ -284,11 +284,21 @@ gimp_blend_options_gui (GimpToolOptions *tool_options)
                                        "gradient-view-type",
                                        "gradient-view-size",
                                        "gradient-reverse",
+                                       "gradient-blend-color-space",
                                        "gimp-gradient-editor",
                                        _("Edit this gradient"));
   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
   gtk_widget_show (button);
 
+  /*  the blend color space  */
+  combo = gimp_prop_enum_combo_box_new (config, "gradient-blend-color-space",
+                                        0, 0);
+  gimp_int_combo_box_set_label (GIMP_INT_COMBO_BOX (combo),
+                                _("Blend Color Space"));
+  g_object_set (combo, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
+  gtk_box_pack_start (GTK_BOX (vbox), combo, TRUE, TRUE, 0);
+  gtk_widget_show (combo);
+
   /*  the gradient type menu  */
   combo = gimp_prop_enum_combo_box_new (config, "gradient-type", 0, 0);
   gimp_int_combo_box_set_label (GIMP_INT_COMBO_BOX (combo), _("Shape"));
diff --git a/app/tools/gimpblendoptions.h b/app/tools/gimpblendoptions.h
index 7974a78..53a02f5 100644
--- a/app/tools/gimpblendoptions.h
+++ b/app/tools/gimpblendoptions.h
@@ -35,7 +35,7 @@ typedef struct _GimpPaintOptionsClass GimpBlendOptionsClass;
 
 struct _GimpBlendOptions
 {
-  GimpPaintOptions  paint_options;
+  GimpPaintOptions   paint_options;
 
   gdouble            offset;
   GimpGradientType   gradient_type;
diff --git a/app/tools/gimpblendtool-editor.c b/app/tools/gimpblendtool-editor.c
index 62d57df..9f1b1dc 100644
--- a/app/tools/gimpblendtool-editor.c
+++ b/app/tools/gimpblendtool-editor.c
@@ -932,7 +932,8 @@ static gint
 gimp_blend_tool_editor_add_stop (GimpBlendTool *blend_tool,
                                  gdouble        value)
 {
-  GimpBlendOptions    *options = GIMP_BLEND_TOOL_GET_OPTIONS (blend_tool);
+  GimpBlendOptions    *options       = GIMP_BLEND_TOOL_GET_OPTIONS (blend_tool);
+  GimpPaintOptions    *paint_options = GIMP_PAINT_OPTIONS (options);
   GimpGradientSegment *seg;
   gint                 stop;
   BlendInfo           *info;
@@ -941,7 +942,9 @@ gimp_blend_tool_editor_add_stop (GimpBlendTool *blend_tool,
   gimp_blend_tool_editor_freeze_gradient (blend_tool);
 
   gimp_gradient_split_at (blend_tool->gradient,
-                          GIMP_CONTEXT (options), NULL, value, &seg, NULL);
+                          GIMP_CONTEXT (options), NULL, value,
+                          paint_options->gradient_options->gradient_blend_color_space,
+                          &seg, NULL);
 
   stop =
     gimp_gradient_segment_range_get_n_segments (blend_tool->gradient,
diff --git a/app/tools/gimppaintoptions-gui.c b/app/tools/gimppaintoptions-gui.c
index f9fecbf..12093df 100644
--- a/app/tools/gimppaintoptions-gui.c
+++ b/app/tools/gimppaintoptions-gui.c
@@ -370,15 +370,29 @@ dynamics_options_gui (GimpPaintOptions *paint_options,
       gtk_box_pack_start (GTK_BOX (vbox), inner_frame, FALSE, FALSE, 0);
       gtk_widget_show (inner_frame);
 
+      inner_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
+      gtk_container_add (GTK_CONTAINER (inner_frame), inner_vbox);
+      gtk_widget_show (inner_vbox);
+
       box = gimp_prop_gradient_box_new (NULL, GIMP_CONTEXT (config),
                                         _("Gradient"), 2,
                                         "gradient-view-type",
                                         "gradient-view-size",
                                         "gradient-reverse",
+                                        "gradient-blend-color-space",
                                         "gimp-gradient-editor",
                                         _("Edit this gradient"));
-      gtk_container_add (GTK_CONTAINER (inner_frame), box);
+      gtk_box_pack_start (GTK_BOX (inner_vbox), box, FALSE, FALSE, 0);
       gtk_widget_show (box);
+
+      /*  the blend color space  */
+      combo = gimp_prop_enum_combo_box_new (config, "gradient-blend-color-space",
+                                            0, 0);
+      gimp_int_combo_box_set_label (GIMP_INT_COMBO_BOX (combo),
+                                    _("Blend Color Space"));
+      g_object_set (combo, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
+      gtk_box_pack_start (GTK_BOX (inner_vbox), combo, TRUE, TRUE, 0);
+      gtk_widget_show (combo);
     }
 
   return frame;
diff --git a/app/widgets/gimpgradienteditor.c b/app/widgets/gimpgradienteditor.c
index ed2cd5e..0d4ccd4 100644
--- a/app/widgets/gimpgradienteditor.c
+++ b/app/widgets/gimpgradienteditor.c
@@ -678,7 +678,9 @@ gradient_editor_drop_color (GtkWidget     *widget,
 
   gimp_gradient_segment_split_midpoint (gradient,
                                         GIMP_DATA_EDITOR (editor)->context,
-                                        seg, &lseg, &rseg);
+                                        seg,
+                                        editor->blend_color_space,
+                                        &lseg, &rseg);
 
   if (lseg)
     {
@@ -948,7 +950,7 @@ view_set_hint (GimpGradientEditor *editor,
 
   gimp_gradient_get_color_at (GIMP_GRADIENT (data_editor->data),
                               data_editor->context, NULL,
-                              xpos, FALSE, &rgb);
+                              xpos, FALSE, FALSE, &rgb);
 
   gimp_color_area_set_color (GIMP_COLOR_AREA (editor->current_color), &rgb);
 
@@ -987,7 +989,7 @@ view_pick_color (GimpGradientEditor *editor,
 
   gimp_gradient_get_color_at (GIMP_GRADIENT (data_editor->data),
                               data_editor->context, NULL,
-                              xpos, FALSE, &color);
+                              xpos, FALSE, FALSE, &color);
 
   gimp_color_area_set_color (GIMP_COLOR_AREA (editor->current_color), &color);
 
diff --git a/app/widgets/gimpgradienteditor.h b/app/widgets/gimpgradienteditor.h
index 6387c33..8f0429a 100644
--- a/app/widgets/gimpgradienteditor.h
+++ b/app/widgets/gimpgradienteditor.h
@@ -81,6 +81,8 @@ struct _GimpGradientEditor
   gdouble                 control_last_gx;      /* Last position (wrt gradient) when dragging */
   gdouble                 control_orig_pos;     /* Original click position when dragging */
 
+  GimpGradientBlendColorSpace  blend_color_space;
+
   /*  Split uniformly dialog  */
   gint          split_parts;
 
diff --git a/app/widgets/gimpgradientselect.c b/app/widgets/gimpgradientselect.c
index e54a0ba..79ca895 100644
--- a/app/widgets/gimpgradientselect.c
+++ b/app/widgets/gimpgradientselect.c
@@ -160,7 +160,9 @@ gimp_gradient_select_run_callback (GimpPdbDialog  *dialog,
   while (i--)
     {
       seg = gimp_gradient_get_color_at (gradient, dialog->caller_context,
-                                        seg, pos, FALSE, &color);
+                                        seg, pos, FALSE,
+                                        GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL,
+                                        &color);
 
       *pv++ = color.r;
       *pv++ = color.g;
diff --git a/app/widgets/gimpviewablebox.c b/app/widgets/gimpviewablebox.c
index d5642d3..070f2a0 100644
--- a/app/widgets/gimpviewablebox.c
+++ b/app/widgets/gimpviewablebox.c
@@ -67,6 +67,9 @@ static void   gimp_viewable_box_edit_clicked   (GtkWidget          *widget,
 static void   gimp_gradient_box_reverse_notify (GObject       *object,
                                                 GParamSpec    *pspec,
                                                 GimpView      *view);
+static void   gimp_gradient_box_blend_notify   (GObject       *object,
+                                                GParamSpec    *pspec,
+                                                GimpView      *view);
 
 
 /*  brush boxes  */
@@ -341,6 +344,7 @@ gradient_box_new (GimpContainer *container,
                   GimpViewType   view_type,
                   GimpViewSize   view_size,
                   const gchar   *reverse_prop,
+                  const gchar   *blend_color_space_prop,
                   const gchar   *editor_id,
                   const gchar   *editor_tooltip)
 {
@@ -402,6 +406,24 @@ gradient_box_new (GimpContainer *container,
                                         GIMP_VIEW (view));
     }
 
+  if (blend_color_space_prop)
+    {
+      GtkWidget *view;
+      gchar     *signal_name;
+
+      view = gtk_bin_get_child (GTK_BIN (button));
+
+      signal_name = g_strconcat ("notify::", blend_color_space_prop, NULL);
+      g_signal_connect_object (context, signal_name,
+                               G_CALLBACK (gimp_gradient_box_blend_notify),
+                               G_OBJECT (view), 0);
+      g_free (signal_name);
+
+      gimp_gradient_box_blend_notify (G_OBJECT (context),
+                                      NULL,
+                                      GIMP_VIEW (view));
+    }
+
   return hbox;
 }
 
@@ -410,7 +432,8 @@ gimp_gradient_box_new (GimpContainer *container,
                        GimpContext   *context,
                        const gchar   *label,
                        gint           spacing,
-                       const gchar   *reverse_prop)
+                       const gchar   *reverse_prop,
+                       const gchar   *blend_color_space_prop)
 {
   g_return_val_if_fail (container == NULL || GIMP_IS_CONTAINER (container),
                         NULL);
@@ -418,7 +441,7 @@ gimp_gradient_box_new (GimpContainer *container,
 
   return gradient_box_new (container, context, label, spacing,
                            GIMP_VIEW_TYPE_LIST, GIMP_VIEW_SIZE_LARGE,
-                           reverse_prop,
+                           reverse_prop, blend_color_space_prop,
                            NULL, NULL);
 }
 
@@ -430,6 +453,7 @@ gimp_prop_gradient_box_new (GimpContainer *container,
                             const gchar   *view_type_prop,
                             const gchar   *view_size_prop,
                             const gchar   *reverse_prop,
+                            const gchar   *blend_color_space_prop,
                             const gchar   *editor_id,
                             const gchar   *editor_tooltip)
 {
@@ -448,6 +472,7 @@ gimp_prop_gradient_box_new (GimpContainer *container,
   return view_props_connect (gradient_box_new (container, context, label, spacing,
                                                view_type, view_size,
                                                reverse_prop,
+                                               blend_color_space_prop,
                                                editor_id, editor_tooltip),
                              context,
                              view_type_prop, view_size_prop);
@@ -737,3 +762,21 @@ gimp_gradient_box_reverse_notify (GObject    *object,
 
   gimp_view_renderer_gradient_set_reverse (rendergrad, reverse);
 }
+
+static void
+gimp_gradient_box_blend_notify (GObject    *object,
+                                GParamSpec *pspec,
+                                GimpView   *view)
+{
+  GimpViewRendererGradient    *rendergrad;
+  GimpGradientBlendColorSpace  blend_color_space;
+
+  rendergrad = GIMP_VIEW_RENDERER_GRADIENT (view->renderer);
+
+  g_object_get (object,
+                "gradient-blend-color-space", &blend_color_space,
+                NULL);
+
+  gimp_view_renderer_gradient_set_blend_color_space (rendergrad,
+                                                     blend_color_space);
+}
diff --git a/app/widgets/gimpviewablebox.h b/app/widgets/gimpviewablebox.h
index 8ac22be..56c84d5 100644
--- a/app/widgets/gimpviewablebox.h
+++ b/app/widgets/gimpviewablebox.h
@@ -70,7 +70,8 @@ GtkWidget * gimp_gradient_box_new      (GimpContainer *container,
                                         GimpContext   *context,
                                         const gchar   *label,
                                         gint           scacing,
-                                        const gchar   *reverse_prop);
+                                        const gchar   *reverse_prop,
+                                        const gchar   *blend_color_space_prop);
 GtkWidget * gimp_prop_gradient_box_new (GimpContainer *container,
                                         GimpContext   *context,
                                         const gchar   *label,
@@ -78,6 +79,7 @@ GtkWidget * gimp_prop_gradient_box_new (GimpContainer *container,
                                         const gchar   *view_type_prop,
                                         const gchar   *view_size_prop,
                                         const gchar   *reverse_prop,
+                                        const gchar   *blend_color_space_prop,
                                         const gchar   *editor_id,
                                         const gchar   *editor_tooltip);
 
diff --git a/app/widgets/gimpviewrenderergradient.c b/app/widgets/gimpviewrenderergradient.c
index 3094842..a82895c 100644
--- a/app/widgets/gimpviewrenderergradient.c
+++ b/app/widgets/gimpviewrenderergradient.c
@@ -63,9 +63,8 @@ gimp_view_renderer_gradient_class_init (GimpViewRendererGradientClass *klass)
 static void
 gimp_view_renderer_gradient_init (GimpViewRendererGradient *renderer)
 {
-  renderer->left    = 0.0;
-  renderer->right   = 1.0;
-  renderer->reverse = FALSE;
+  renderer->left  = 0.0;
+  renderer->right = 1.0;
 }
 
 static void
@@ -177,7 +176,10 @@ gimp_view_renderer_gradient_render (GimpViewRenderer *renderer,
       guchar r, g, b, a;
 
       seg = gimp_gradient_get_color_at (gradient, renderer->context, seg,
-                                        cur_x, rendergrad->reverse, &color);
+                                        cur_x,
+                                        rendergrad->reverse,
+                                        rendergrad->blend_color_space,
+                                        &color);
       cur_x += dx;
 
       gimp_rgba_get_uchar (&color, &r, &g, &b, &a);
@@ -246,3 +248,18 @@ gimp_view_renderer_gradient_set_reverse (GimpViewRendererGradient *renderer,
       gimp_view_renderer_update (GIMP_VIEW_RENDERER (renderer));
     }
 }
+
+void
+gimp_view_renderer_gradient_set_blend_color_space (GimpViewRendererGradient    *renderer,
+                                                   GimpGradientBlendColorSpace  blend_color_space)
+{
+  g_return_if_fail (GIMP_IS_VIEW_RENDERER_GRADIENT (renderer));
+
+  if (blend_color_space != renderer->blend_color_space)
+    {
+      renderer->blend_color_space = blend_color_space;
+
+      gimp_view_renderer_invalidate (GIMP_VIEW_RENDERER (renderer));
+      gimp_view_renderer_update (GIMP_VIEW_RENDERER (renderer));
+    }
+}
diff --git a/app/widgets/gimpviewrenderergradient.h b/app/widgets/gimpviewrenderergradient.h
index c1edbc3..6d082a9 100644
--- a/app/widgets/gimpviewrenderergradient.h
+++ b/app/widgets/gimpviewrenderergradient.h
@@ -35,12 +35,13 @@ typedef struct _GimpViewRendererGradientClass  GimpViewRendererGradientClass;
 
 struct _GimpViewRendererGradient
 {
-  GimpViewRenderer  parent_instance;
+  GimpViewRenderer            parent_instance;
 
-  gdouble           left;
-  gdouble           right;
-  gboolean          reverse;
-  gboolean          has_fg_bg_segments;
+  gdouble                     left;
+  gdouble                     right;
+  gboolean                    reverse;
+  GimpGradientBlendColorSpace blend_color_space;
+  gboolean                    has_fg_bg_segments;
 };
 
 struct _GimpViewRendererGradientClass
@@ -51,11 +52,14 @@ struct _GimpViewRendererGradientClass
 
 GType   gimp_view_renderer_gradient_get_type    (void) G_GNUC_CONST;
 
-void    gimp_view_renderer_gradient_set_offsets (GimpViewRendererGradient *renderer,
-                                                 gdouble                   left,
-                                                 gdouble                   right);
-void    gimp_view_renderer_gradient_set_reverse (GimpViewRendererGradient *renderer,
-                                                 gboolean                  reverse);
+void    gimp_view_renderer_gradient_set_offsets (GimpViewRendererGradient    *renderer,
+                                                 gdouble                      left,
+                                                 gdouble                      right);
+void    gimp_view_renderer_gradient_set_reverse (GimpViewRendererGradient    *renderer,
+                                                 gboolean                     reverse);
+void    gimp_view_renderer_gradient_set_blend_color_space
+                                                (GimpViewRendererGradient    *renderer,
+                                                 GimpGradientBlendColorSpace  blend_color_space);
 
 
 #endif /* __GIMP_VIEW_RENDERER_GRADIENT_H__ */
diff --git a/libgimp/gimpenums.c.tail b/libgimp/gimpenums.c.tail
index e1d1c96..e8821e2 100644
--- a/libgimp/gimpenums.c.tail
+++ b/libgimp/gimpenums.c.tail
@@ -24,6 +24,7 @@ static const GimpGetTypeFunc get_type_funcs[] =
   gimp_dodge_burn_type_get_type,
   gimp_fill_type_get_type,
   gimp_foreground_extract_mode_get_type,
+  gimp_gradient_blend_color_space_get_type,
   gimp_gradient_segment_color_get_type,
   gimp_gradient_segment_type_get_type,
   gimp_gradient_type_get_type,
@@ -91,6 +92,7 @@ static const gchar * const type_names[] =
   "GimpDodgeBurnType",
   "GimpFillType",
   "GimpForegroundExtractMode",
+  "GimpGradientBlendColorSpace",
   "GimpGradientSegmentColor",
   "GimpGradientSegmentType",
   "GimpGradientType",
diff --git a/libgimpbase/gimpbase.def b/libgimpbase/gimpbase.def
index 794ec4c..3c7c6a4 100644
--- a/libgimpbase/gimpbase.def
+++ b/libgimpbase/gimpbase.def
@@ -61,6 +61,7 @@ EXPORTS
        gimp_flags_value_get_desc
        gimp_flags_value_get_help
        gimp_foreground_extract_mode_get_type
+       gimp_gradient_blend_color_space_get_type
        gimp_gradient_segment_color_get_type
        gimp_gradient_segment_type_get_type
        gimp_gradient_type_get_type
diff --git a/libgimpbase/gimpbaseenums.c b/libgimpbase/gimpbaseenums.c
index 648940d..2a47498 100644
--- a/libgimpbase/gimpbaseenums.c
+++ b/libgimpbase/gimpbaseenums.c
@@ -629,6 +629,36 @@ gimp_foreground_extract_mode_get_type (void)
 }
 
 GType
+gimp_gradient_blend_color_space_get_type (void)
+{
+  static const GEnumValue values[] =
+  {
+    { GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL, "GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL", "rgb-perceptual" },
+    { GIMP_GRADIENT_BLEND_RGB_LINEAR, "GIMP_GRADIENT_BLEND_RGB_LINEAR", "rgb-linear" },
+    { 0, NULL, NULL }
+  };
+
+  static const GimpEnumDesc descs[] =
+  {
+    { GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL, NC_("gradient-blend-color-space", "Perceptual RGB"), NULL },
+    { GIMP_GRADIENT_BLEND_RGB_LINEAR, NC_("gradient-blend-color-space", "Linear RGB"), NULL },
+    { 0, NULL, NULL }
+  };
+
+  static GType type = 0;
+
+  if (G_UNLIKELY (! type))
+    {
+      type = g_enum_register_static ("GimpGradientBlendColorSpace", values);
+      gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+      gimp_type_set_translation_context (type, "gradient-blend-color-space");
+      gimp_enum_set_value_descriptions (type, descs);
+    }
+
+  return type;
+}
+
+GType
 gimp_gradient_segment_color_get_type (void)
 {
   static const GEnumValue values[] =
diff --git a/libgimpbase/gimpbaseenums.h b/libgimpbase/gimpbaseenums.h
index 5064d7d..6b4ffb8 100644
--- a/libgimpbase/gimpbaseenums.h
+++ b/libgimpbase/gimpbaseenums.h
@@ -290,6 +290,7 @@ typedef enum
 #endif /* GIMP_DISABLE_DEPRECATED */
 } GimpDesaturateMode;
 
+
 #define GIMP_TYPE_DODGE_BURN_TYPE (gimp_dodge_burn_type_get_type ())
 
 GType gimp_dodge_burn_type_get_type (void) G_GNUC_CONST;
@@ -339,6 +340,17 @@ typedef enum
 } GimpForegroundExtractMode;
 
 
+#define GIMP_TYPE_GRADIENT_BLEND_COLOR_SPACE (gimp_gradient_blend_color_space_get_type ())
+
+GType gimp_gradient_blend_color_space_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+  GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL,  /*< desc="Perceptual RGB", nick=rgb-perceptual >*/
+  GIMP_GRADIENT_BLEND_RGB_LINEAR       /*< desc="Linear RGB",     nick=rgb-linear     >*/
+} GimpGradientBlendColorSpace;
+
+
 #define GIMP_TYPE_GRADIENT_SEGMENT_COLOR (gimp_gradient_segment_color_get_type ())
 
 GType gimp_gradient_segment_color_get_type (void) G_GNUC_CONST;
diff --git a/pdb/enums.pl b/pdb/enums.pl
index 3926580..7b26557 100644
--- a/pdb/enums.pl
+++ b/pdb/enums.pl
@@ -203,6 +203,14 @@ package Gimp::CodeGen::enums;
          mapping => { GIMP_FOREGROUND_EXTRACT_SIOX => '0',
                       GIMP_FOREGROUND_EXTRACT_MATTING => '1' }
        },
+    GimpGradientBlendColorSpace =>
+       { contig => 1,
+         header => 'libgimpbase/gimpbaseenums.h',
+         symbols => [ qw(GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL
+                         GIMP_GRADIENT_BLEND_RGB_LINEAR) ],
+         mapping => { GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL => '0',
+                      GIMP_GRADIENT_BLEND_RGB_LINEAR => '1' }
+       },
     GimpGradientSegmentColor =>
        { contig => 1,
          header => 'libgimpbase/gimpbaseenums.h',
diff --git a/pdb/groups/gradient.pdb b/pdb/groups/gradient.pdb
index 303c9f5..a6d84fa 100644
--- a/pdb/groups/gradient.pdb
+++ b/pdb/groups/gradient.pdb
@@ -251,7 +251,9 @@ HELP
     %invoke = (
        code => <<'CODE'
 {
-  GimpGradient *gradient = gimp_pdb_get_gradient (gimp, name, GIMP_PDB_DATA_ACCESS_READ, error);
+  GimpGradient *gradient = gimp_pdb_get_gradient (gimp, name,
+                                                  GIMP_PDB_DATA_ACCESS_READ,
+                                                  error);
 
   if (gradient)
     {
@@ -269,7 +271,9 @@ HELP
           GimpRGB color;
 
          seg = gimp_gradient_get_color_at (gradient, context, seg,
-                                            pos, reverse, &color);
+                                            pos, reverse,
+                                            GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL,
+                                            &color);
 
           *sample++ = color.r;
           *sample++ = color.g;
@@ -321,7 +325,9 @@ HELP
     %invoke = (
        code => <<'CODE'
 {
-  GimpGradient *gradient = gimp_pdb_get_gradient (gimp, name, GIMP_PDB_DATA_ACCESS_READ, error);
+  GimpGradient *gradient = gimp_pdb_get_gradient (gimp, name,
+                                                  GIMP_PDB_DATA_ACCESS_READ,
+                                                  error);
 
   if (gradient)
     {
@@ -338,7 +344,9 @@ HELP
 
           seg = gimp_gradient_get_color_at (gradient, context,
                                             seg, *positions,
-                                            reverse, &color);
+                                            reverse,
+                                            GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL,
+                                            &color);
 
           *sample++ = color.r;
           *sample++ = color.g;
@@ -385,7 +393,8 @@ HELP
   GimpGradient        *gradient;
   GimpGradientSegment *seg;
 
-  gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_READ, segment, &seg, error);
+  gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_READ, segment,
+                           &seg, error);
 
   if (seg)
     {
@@ -429,7 +438,8 @@ HELP
   GimpGradient        *gradient;
   GimpGradientSegment *seg;
 
-  gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_READ, segment, &seg, error);
+  gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_READ, segment,
+                           &seg, error);
 
   if (seg)
     {
@@ -470,7 +480,8 @@ HELP
   GimpGradient        *gradient;
   GimpGradientSegment *seg;
 
-  gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_WRITE, segment, &seg, error);
+  gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_WRITE, segment,
+                           &seg, error);
 
   if (seg)
     {
@@ -511,7 +522,8 @@ HELP
   GimpGradient        *gradient;
   GimpGradientSegment *seg;
 
-  gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_WRITE, segment, &seg, error);
+  gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_WRITE, segment,
+                           &seg, error);
 
   if (seg)
     {
@@ -553,7 +565,8 @@ HELP
   GimpGradient        *gradient;
   GimpGradientSegment *seg;
 
-  gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_READ, segment, &seg, error);
+  gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_READ, segment,
+                           &seg, error);
 
   if (seg)
     {
@@ -594,7 +607,8 @@ HELP
   GimpGradient        *gradient;
   GimpGradientSegment *seg;
 
-  gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_READ, segment, &seg, error);
+  gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_READ, segment,
+                           &seg, error);
 
   if (seg)
     {
@@ -635,7 +649,8 @@ HELP
   GimpGradient        *gradient;
   GimpGradientSegment *seg;
 
-  gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_READ, segment, &seg, error);
+  gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_READ, segment,
+                           &seg, error);
 
   if (seg)
     {
@@ -682,7 +697,8 @@ HELP
   GimpGradient        *gradient;
   GimpGradientSegment *seg;
 
-  gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_WRITE, segment, &seg, error);
+  gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_WRITE, segment,
+                           &seg, error);
 
   if (seg)
     {
@@ -729,7 +745,8 @@ HELP
   GimpGradient        *gradient;
   GimpGradientSegment *seg;
 
-  gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_WRITE, segment, &seg, error);
+  gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_WRITE, segment,
+                           &seg, error);
 
   if (seg)
     {
@@ -776,7 +793,8 @@ HELP
   GimpGradient        *gradient;
   GimpGradientSegment *seg;
 
-  gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_WRITE, segment, &seg, error);
+  gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_WRITE, segment,
+                           &seg, error);
 
   if (seg)
     {
@@ -819,7 +837,8 @@ HELP
   GimpGradient        *gradient;
   GimpGradientSegment *seg;
 
-  gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_READ, segment, &seg, error);
+  gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_READ, segment,
+                           &seg, error);
 
   if (seg)
     {
@@ -861,7 +880,8 @@ HELP
   GimpGradient        *gradient;
   GimpGradientSegment *seg;
 
-  gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_READ, segment, &seg, error);
+  gradient = gradient_get (gimp, name, GIMP_PDB_DATA_ACCESS_READ, segment,
+                           &seg, error);
 
   if (seg)
     {
@@ -1083,6 +1103,7 @@ HELP
     {
       gimp_gradient_segment_range_split_midpoint (gradient, context,
                                                   start_seg, end_seg,
+                                                  GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL,
                                                   NULL, NULL);
     }
   else
@@ -1129,6 +1150,7 @@ HELP
       gimp_gradient_segment_range_split_uniform (gradient, context,
                                                  start_seg, end_seg,
                                                  split_parts,
+                                                 GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL,
                                                  NULL, NULL);
     }
   else
diff --git a/pdb/groups/gradients.pdb b/pdb/groups/gradients.pdb
index 336c412..376de2f 100644
--- a/pdb/groups/gradients.pdb
+++ b/pdb/groups/gradients.pdb
@@ -108,7 +108,9 @@ sub gradients_sample_uniform {
   while (num_samples--)
     {
       seg = gimp_gradient_get_color_at (gradient, context, seg,
-                                        pos, reverse, &color);
+                                        pos, reverse,
+                                        GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL,
+                                        &color);
 
       *pv++ = color.r;
       *pv++ = color.g;
@@ -159,7 +161,9 @@ sub gradients_sample_custom {
   while (num_samples--)
     {
       seg = gimp_gradient_get_color_at (gradient, context, seg,
-                                        *positions, reverse, &color);
+                                        *positions, reverse,
+                                        GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL,
+                                        &color);
 
       *pv++ = color.r;
       *pv++ = color.g;
@@ -227,7 +231,9 @@ sub gradients_get_gradient_data {
       while (sample_size--)
        {
          seg = gimp_gradient_get_color_at (gradient, context, seg,
-                                            pos, reverse, &color);
+                                            pos, reverse,
+                                            GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL,
+                                            &color);
 
          *pv++ = color.r;
          *pv++ = color.g;


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