[gimp] app: use gradient cache for conical gradients



commit 5970046e25f5b718bd08b1acbba8fb981e79de48
Author: Ell <ell_se yahoo com>
Date:   Wed Apr 25 13:58:09 2018 -0400

    app: use gradient cache for conical gradients
    
    Add gimp_drawable_gradient_adjust_coords(), which adjusts the
    gradient segment coords according to the gradient type, so that, in
    cases where the gradient span is unrelated to the segment length,
    the gradient cache (in GimpOperationGradient) is big enough not to
    produce banding.  Use the new function in gimp_drawable_gradient()
    and in the gradient tool, instead of duplicating the logic.
    
    Move the shapreburst coordinate-adjustment logic to the new
    function, and add appropriate logic for conical gradients.
    
    Remove the code that avoids using the gradient cache for conical
    gradients from GimpOperationGradient.

 app/core/gimpdrawable-gradient.c       |   86 ++++++++++++++++++++++++++++---
 app/core/gimpdrawable-gradient.h       |   57 ++++++++++++---------
 app/operations/gimpoperationgradient.c |   15 ------
 app/tools/gimpgradienttool.c           |   57 ++++++++++-----------
 4 files changed, 135 insertions(+), 80 deletions(-)
---
diff --git a/app/core/gimpdrawable-gradient.c b/app/core/gimpdrawable-gradient.c
index 5865ee6..4d1b37c 100644
--- a/app/core/gimpdrawable-gradient.c
+++ b/app/core/gimpdrawable-gradient.c
@@ -21,6 +21,8 @@
 #include <gegl.h>
 #include <gdk-pixbuf/gdk-pixbuf.h>
 
+#include "libgimpmath/gimpmath.h"
+
 #include "core-types.h"
 
 #include "gegl/gimp-gegl-apply-operation.h"
@@ -93,17 +95,13 @@ gimp_drawable_gradient (GimpDrawable                *drawable,
         gimp_drawable_gradient_shapeburst_distmap (drawable, metric,
                                                    GEGL_RECTANGLE (x, y, width, height),
                                                    progress);
-
-      /*  in shapeburst mode, make sure the "line" is long enough to
-       *  span across the selection, so the operation's cache has the
-       *  right size
-       */
-      startx = x;
-      starty = y;
-      endx   = x + width;
-      endy   = y + height;
     }
 
+  gimp_drawable_gradient_adjust_coords (drawable,
+                                        gradient_type,
+                                        GEGL_RECTANGLE (x, y, width, height),
+                                        &startx, &starty, &endx, &endy);
+
   render = gegl_node_new_child (NULL,
                                 "operation",                  "gimp:gradient",
                                 "context",                    context,
@@ -235,3 +233,73 @@ gimp_drawable_gradient_shapeburst_distmap (GimpDrawable        *drawable,
 
   return dist_buffer;
 }
+
+void
+gimp_drawable_gradient_adjust_coords (GimpDrawable        *drawable,
+                                      GimpGradientType     gradient_type,
+                                      const GeglRectangle *region,
+                                      gdouble             *startx,
+                                      gdouble             *starty,
+                                      gdouble             *endx,
+                                      gdouble             *endy)
+{
+  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
+  g_return_if_fail (region != NULL);
+  g_return_if_fail (startx != NULL);
+  g_return_if_fail (starty != NULL);
+  g_return_if_fail (endx != NULL);
+  g_return_if_fail (endy != NULL);
+
+  /* we potentially adjust the gradient coordinates according to the gradient
+   * type, so that in cases where the gradient span is not related to the
+   * segment length, the gradient cache (in GimpOperationGradient) is big
+   * enough not to produce banding.
+   */
+
+  switch (gradient_type)
+    {
+    /* for conical gradients, use a segment with the original origin and
+     * direction, whose length is the circumference of the largest circle
+     * centered at the origin, passing through one of the regions's vertices.
+     */
+    case GIMP_GRADIENT_CONICAL_SYMMETRIC:
+    case GIMP_GRADIENT_CONICAL_ASYMMETRIC:
+      {
+        gdouble     r = 0.0;
+        GimpVector2 v;
+
+        r = MAX (r, hypot (region->x - *startx,
+                           region->y - *starty));
+        r = MAX (r, hypot (region->x + region->width - *startx,
+                           region->y - *starty));
+        r = MAX (r, hypot (region->x - *startx,
+                           region->y + region->height - *starty));
+        r = MAX (r, hypot (region->x + region->width - *startx,
+                           region->y + region->height - *starty));
+
+        gimp_vector2_set (&v, *endx - *startx, *endy - *starty);
+        gimp_vector2_normalize (&v);
+        gimp_vector2_mul (&v, 2.0 * G_PI * r);
+
+        *endx = *startx + v.x;
+        *endy = *starty + v.y;
+      }
+      break;
+
+    /* for shaped gradients, only the segment's length matters; use the
+     * regions's diagonal, which is the largest possible distance between two
+     * points in the region.
+     */
+    case GIMP_GRADIENT_SHAPEBURST_ANGULAR:
+    case GIMP_GRADIENT_SHAPEBURST_SPHERICAL:
+    case GIMP_GRADIENT_SHAPEBURST_DIMPLED:
+      *startx = region->x;
+      *starty = region->y;
+      *endx   = region->x + region->width;
+      *endy   = region->y + region->height;
+      break;
+
+    default:
+      break;
+    }
+}
diff --git a/app/core/gimpdrawable-gradient.h b/app/core/gimpdrawable-gradient.h
index 75fe93d..9e628ae 100644
--- a/app/core/gimpdrawable-gradient.h
+++ b/app/core/gimpdrawable-gradient.h
@@ -19,32 +19,39 @@
 #define  __GIMP_DRAWABLE_GRADIENT_H__
 
 
-void   gimp_drawable_gradient (GimpDrawable                *drawable,
-                               GimpContext                 *context,
-                               GimpGradient                *gradient,
-                               GeglDistanceMetric           metric,
-                               GimpLayerMode                paint_mode,
-                               GimpGradientType             gradient_type,
-                               gdouble                      opacity,
-                               gdouble                      offset,
-                               GimpRepeatMode               repeat,
-                               gboolean                     reverse,
-                               GimpGradientBlendColorSpace  blend_color_space,
-                               gboolean                     supersample,
-                               gint                         max_depth,
-                               gdouble                      threshold,
-                               gboolean                     dither,
-                               gdouble                      startx,
-                               gdouble                      starty,
-                               gdouble                      endx,
-                               gdouble                      endy,
-                               GimpProgress                *progress);
+void         gimp_drawable_gradient                    (GimpDrawable                *drawable,
+                                                        GimpContext                 *context,
+                                                        GimpGradient                *gradient,
+                                                        GeglDistanceMetric           metric,
+                                                        GimpLayerMode                paint_mode,
+                                                        GimpGradientType             gradient_type,
+                                                        gdouble                      opacity,
+                                                        gdouble                      offset,
+                                                        GimpRepeatMode               repeat,
+                                                        gboolean                     reverse,
+                                                        GimpGradientBlendColorSpace  blend_color_space,
+                                                        gboolean                     supersample,
+                                                        gint                         max_depth,
+                                                        gdouble                      threshold,
+                                                        gboolean                     dither,
+                                                        gdouble                      startx,
+                                                        gdouble                      starty,
+                                                        gdouble                      endx,
+                                                        gdouble                      endy,
+                                                        GimpProgress                *progress);
 
-GeglBuffer *
-gimp_drawable_gradient_shapeburst_distmap (GimpDrawable        *drawable,
-                                           GeglDistanceMetric   metric,
-                                           const GeglRectangle *region,
-                                           GimpProgress        *progress);
+GeglBuffer * gimp_drawable_gradient_shapeburst_distmap (GimpDrawable                *drawable,
+                                                        GeglDistanceMetric           metric,
+                                                        const GeglRectangle         *region,
+                                                        GimpProgress                *progress);
+
+void         gimp_drawable_gradient_adjust_coords      (GimpDrawable                *drawable,
+                                                        GimpGradientType             gradient_type,
+                                                        const GeglRectangle         *region,
+                                                        gdouble                     *startx,
+                                                        gdouble                     *starty,
+                                                        gdouble                     *endx,
+                                                        gdouble                     *endy);
 
 
 #endif /* __GIMP_DRAWABLE_GRADIENT_H__ */
diff --git a/app/operations/gimpoperationgradient.c b/app/operations/gimpoperationgradient.c
index 7d6ca08..3e7d104 100644
--- a/app/operations/gimpoperationgradient.c
+++ b/app/operations/gimpoperationgradient.c
@@ -1226,21 +1226,6 @@ gimp_operation_gradient_validate_cache (GimpOperationGradient *self)
       return;
     }
 
-  switch (self->gradient_type)
-    {
-    case GIMP_GRADIENT_CONICAL_SYMMETRIC:
-    case GIMP_GRADIENT_CONICAL_ASYMMETRIC:
-      /*  don't use a gradient cache for conical gradients, since the necessary
-       *  cache size is not related to the line length
-       */
-      g_mutex_unlock (&self->gradient_cache_mutex);
-
-      return;
-
-    default:
-      break;
-    }
-
   cache_size = ceil (hypot (self->start_x - self->end_x,
                             self->start_y - self->end_y)) *
                GRADIENT_CACHE_N_SUPERSAMPLES;
diff --git a/app/tools/gimpgradienttool.c b/app/tools/gimpgradienttool.c
index ee6b5ce..bfb87d8 100644
--- a/app/tools/gimpgradienttool.c
+++ b/app/tools/gimpgradienttool.c
@@ -875,8 +875,9 @@ gimp_gradient_tool_create_graph (GimpGradientTool *gradient_tool)
 static void
 gimp_gradient_tool_update_graph (GimpGradientTool *gradient_tool)
 {
-  GimpTool *tool = GIMP_TOOL (gradient_tool);
-  gint      off_x, off_y;
+  GimpTool            *tool    = GIMP_TOOL (gradient_tool);
+  GimpGradientOptions *options = GIMP_GRADIENT_TOOL_GET_OPTIONS (gradient_tool);
+  gint                 off_x, off_y;
 
   gimp_item_get_offset (GIMP_ITEM (tool->drawable), &off_x, &off_y);
 
@@ -912,35 +913,29 @@ gimp_gradient_tool_update_graph (GimpGradientTool *gradient_tool)
   else
 #endif
     {
-      if (gimp_gradient_tool_is_shapeburst (gradient_tool))
-        {
-          /*  in shapeburst mode, make sure the "line" is long enough
-           *  to span across the selection, so the operation's cache
-           *  has the right size
-           */
+      GeglRectangle roi;
+      gdouble       start_x, start_y;
+      gdouble       end_x,   end_y;
 
-          GimpImage *image = gimp_display_get_image (tool->display);
-          gdouble    x, y, w, h;
+      gimp_item_mask_intersect (GIMP_ITEM (tool->drawable),
+                                &roi.x, &roi.y, &roi.width, &roi.height);
 
-          gimp_item_bounds_f (GIMP_ITEM (gimp_image_get_mask (image)),
-                              &x, &y, &w, &h);
+      start_x = gradient_tool->start_x - off_x;
+      start_y = gradient_tool->start_y - off_y;
+      end_x   = gradient_tool->end_x   - off_x;
+      end_y   = gradient_tool->end_y   - off_y;
 
-          gegl_node_set (gradient_tool->render_node,
-                         "start-x", x,
-                         "start-y", y,
-                         "end-x",   x + w,
-                         "end-y",   y + h,
-                         NULL);
-        }
-      else
-        {
-          gegl_node_set (gradient_tool->render_node,
-                         "start-x", gradient_tool->start_x - off_x,
-                         "start-y", gradient_tool->start_y - off_y,
-                         "end-x",   gradient_tool->end_x - off_x,
-                         "end-y",   gradient_tool->end_y - off_y,
-                         NULL);
-        }
+      gimp_drawable_gradient_adjust_coords (tool->drawable,
+                                            options->gradient_type,
+                                            &roi,
+                                            &start_x, &start_y, &end_x, &end_y);
+
+      gegl_node_set (gradient_tool->render_node,
+                     "start-x", start_x,
+                     "start-y", start_y,
+                     "end-x",   end_x,
+                     "end-y",   end_y,
+                     NULL);
     }
 }
 


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