[gimp] Real dynamic hardness support for both generated and pixmap brushes.



commit 9774988f30746d64383cf893c4384bf2eedb1478
Author: Alexia Death <alexiadeath gmail com>
Date:   Fri Jan 1 15:41:07 2010 +0200

    Real dynamic hardness support for both generated and pixmap brushes.
    
    For generated brushes, dynamic input is applied on top of the set hardness as a factor.
    For pixmaps, it influences the amount of blur applied to the stamp. Be warned, process is slow
    for large pixmaps. The odd feature previously advertised as hardness is left in but disabled.
    If I figure out what it should be exposed as, it might be made available again.

 app/core/gimpbrush-transform.c |  170 +++++++++++++++++++++++++++++++---------
 app/core/gimpbrush-transform.h |    6 +-
 app/core/gimpbrush.c           |   18 +++--
 app/core/gimpbrush.h           |   12 ++-
 app/core/gimpbrushgenerated.c  |    8 +-
 app/paint-funcs/paint-funcs.c  |  134 +++++++++++++++++++++++++++++++
 app/paint-funcs/paint-funcs.h  |    8 ++
 app/paint/gimpbrushcore.c      |   34 ++++++--
 app/paint/gimpbrushcore.h      |    2 +
 app/paint/gimppaintoptions.c   |    7 +-
 10 files changed, 333 insertions(+), 66 deletions(-)
---
diff --git a/app/core/gimpbrush-transform.c b/app/core/gimpbrush-transform.c
index 9305146..b2792cf 100644
--- a/app/core/gimpbrush-transform.c
+++ b/app/core/gimpbrush-transform.c
@@ -30,22 +30,30 @@
 
 #include "base/temp-buf.h"
 
+#include "paint-funcs/paint-funcs.h"
 
 /*  local function prototypes  */
 
-static void  gimp_brush_transform_matrix       (GimpBrush         *brush,
-                                                gdouble            scale_x,
-                                                gdouble            scale_y,
-                                                gdouble            angle,
-                                                GimpMatrix3       *matrix);
-static void  gimp_brush_transform_bounding_box (GimpBrush         *brush,
-                                                const GimpMatrix3 *matrix,
-                                                gint              *x,
-                                                gint              *y,
-                                                gint              *width,
-                                                gint              *height);
-
-
+static void    gimp_brush_transform_matrix       (TempBuf           *brush,
+                                                  gdouble            scale_x,
+                                                  gdouble            scale_y,
+                                                  gdouble            angle,
+                                                  GimpMatrix3       *matrix);
+static void    gimp_brush_transform_bounding_box (TempBuf           *brush,
+                                                  const GimpMatrix3 *matrix,
+                                                  gint              *x,
+                                                  gint              *y,
+                                                  gint              *width,
+                                                  gint              *height);
+
+static gdouble gimp_brush_transform_array_sum    (gfloat            *arr, 
+                                                  gint               len);
+static void    gimp_brush_transform_fill_blur_kernel (gfloat            *arr,
+                                                      gint               len);
+static gint    gimp_brush_transform_blur_kernel_size (gint height, 
+                                                      gint width, 
+                                                      gdouble hardness);
+#define MAX_BLUR_KERNEL   15
 /*  public functions  */
 
 void
@@ -60,13 +68,13 @@ gimp_brush_real_transform_size (GimpBrush *brush,
   gint        x, y;
 
   if (aspect_ratio < 1.0)
-    gimp_brush_transform_matrix (brush,
+    gimp_brush_transform_matrix (brush->mask,
                                  scale * aspect_ratio, scale, angle, &matrix);
   else
-    gimp_brush_transform_matrix (brush,
+    gimp_brush_transform_matrix (brush->mask,
                                  scale, scale / aspect_ratio, angle, &matrix);
 
-  gimp_brush_transform_bounding_box (brush, &matrix, &x, &y, width, height);
+  gimp_brush_transform_bounding_box (brush->mask, &matrix, &x, &y, width, height);
 }
 
 /*
@@ -99,9 +107,11 @@ TempBuf *
 gimp_brush_real_transform_mask (GimpBrush *brush,
                                 gdouble    scale,
                                 gdouble    aspect_ratio,
-                                gdouble    angle)
+                                gdouble    angle,
+                                gdouble    hardness)
 {
   TempBuf      *result;
+  TempBuf      *source;
   guchar       *dest;
   const guchar *src;
   GimpMatrix3   matrix;
@@ -135,7 +145,6 @@ gimp_brush_real_transform_mask (GimpBrush *brush,
   gint          opposite_x, distance_from_true_x;
   gint          opposite_y, distance_from_true_y;
 
-
   /*
    * tl, tr etc are used because it is easier to visualize top left,
    * top right etc corners of the forward transformed source image
@@ -166,23 +175,24 @@ gimp_brush_real_transform_mask (GimpBrush *brush,
    */
   const guint fraction_bitmask = pow(2, fraction_bits) - 1 ;
 
+  source = temp_buf_copy (brush->mask, NULL);
 
    if (aspect_ratio < 1.0)
-    gimp_brush_transform_matrix (brush,
+    gimp_brush_transform_matrix (source,
                                  scale * aspect_ratio, scale, angle, &matrix);
   else
-    gimp_brush_transform_matrix (brush,
+    gimp_brush_transform_matrix (source,
                                  scale, scale / aspect_ratio, angle, &matrix);
 
   if (gimp_matrix3_is_identity (&matrix))
-    return temp_buf_copy (brush->mask, NULL);
+    return temp_buf_copy (source, NULL);
 
-  src_width  = brush->mask->width;
-  src_height = brush->mask->height;
+  src_width  = source->width;
+  src_height = source->height;
   src_width_minus_one  = src_width  - 1;
   src_height_minus_one = src_height - 1;
 
-  gimp_brush_transform_bounding_box (brush, &matrix,
+  gimp_brush_transform_bounding_box (source, &matrix,
                                      &x, &y, &dest_width, &dest_height);
   gimp_matrix3_translate (&matrix, -x, -y);
   gimp_matrix3_invert (&matrix);
@@ -190,7 +200,7 @@ gimp_brush_real_transform_mask (GimpBrush *brush,
   result = temp_buf_new (dest_width, dest_height, 1, 0, 0, NULL);
 
   dest = temp_buf_get_data (result);
-  src  = temp_buf_get_data (brush->mask);
+  src  = temp_buf_get_data (source);
 
   /* prevent disappearance of 1x1 pixel brush at some rotations when
      scaling < 1 */
@@ -322,7 +332,26 @@ gimp_brush_real_transform_mask (GimpBrush *brush,
         src_space_cur_pos_y = src_space_cur_pos_y_i >> fraction_bits;
 
     } /* end for y */
+  if (hardness < 1.0)
+    {
+      TempBuf      *blur_src;
+
+      gint kernel_size = gimp_brush_transform_blur_kernel_size ( result->height, 
+                                                                 result->width,
+                                                                 hardness);
+      gint kernel_len  = kernel_size * kernel_size;
+      gfloat blur_kernel [kernel_len];
+
+      gimp_brush_transform_fill_blur_kernel ( blur_kernel, kernel_len);
+
+      blur_src = temp_buf_copy (result, NULL);
 
+      convolve_tempbuf (blur_src, result, blur_kernel, kernel_size,
+                        gimp_brush_transform_array_sum(blur_kernel, kernel_len),
+                        GIMP_NORMAL_CONVOL, FALSE);
+
+    }
+  
   return result;
 }
 
@@ -361,9 +390,11 @@ TempBuf *
 gimp_brush_real_transform_pixmap (GimpBrush *brush,
                                   gdouble    scale,
                                   gdouble    aspect_ratio,
-                                  gdouble    angle)
+                                  gdouble    angle,
+                                  gdouble    hardness)
 {
   TempBuf      *result;
+  TempBuf      *source;
   guchar       *dest;
   const guchar *src;
   GimpMatrix3   matrix;
@@ -397,6 +428,7 @@ gimp_brush_real_transform_pixmap (GimpBrush *brush,
   gint          opposite_x, distance_from_true_x;
   gint          opposite_y, distance_from_true_y;
 
+  source = brush->pixmap;
 
   /*
    * tl, tr etc are used because it is easier to visualize top left,
@@ -430,21 +462,21 @@ gimp_brush_real_transform_pixmap (GimpBrush *brush,
 
 
   if (aspect_ratio < 1.0)
-    gimp_brush_transform_matrix (brush,
+    gimp_brush_transform_matrix (source,
                                  scale * aspect_ratio, scale, angle, &matrix);
   else
-    gimp_brush_transform_matrix (brush,
+    gimp_brush_transform_matrix (source,
                                  scale, scale / aspect_ratio, angle, &matrix);
 
   if (gimp_matrix3_is_identity (&matrix))
-    return temp_buf_copy (brush->pixmap, NULL);
+    return temp_buf_copy (source, NULL);
 
-  src_width  = brush->pixmap->width;
-  src_height = brush->pixmap->height;
+  src_width  = source->width;
+  src_height = source->height;
   src_width_minus_one  = src_width  - 1;
   src_height_minus_one = src_height - 1;
 
-  gimp_brush_transform_bounding_box (brush, &matrix,
+  gimp_brush_transform_bounding_box (source, &matrix,
                                      &x, &y, &dest_width, &dest_height);
   gimp_matrix3_translate (&matrix, -x, -y);
   gimp_matrix3_invert (&matrix);
@@ -452,7 +484,7 @@ gimp_brush_real_transform_pixmap (GimpBrush *brush,
   result = temp_buf_new (dest_width, dest_height, 3, 0, 0, NULL);
 
   dest = temp_buf_get_data (result);
-  src  = temp_buf_get_data (brush->pixmap);
+  src  = temp_buf_get_data (source);
 
   gimp_matrix3_transform_point (&matrix, 0,          0,           &tlx, &tly);
   gimp_matrix3_transform_point (&matrix, dest_width, 0,           &trx, &try);
@@ -590,6 +622,25 @@ gimp_brush_real_transform_pixmap (GimpBrush *brush,
         src_space_cur_pos_y = src_space_cur_pos_y_i >> fraction_bits;
     } /* end for y */
 
+  if (hardness < 1.0)
+    {
+      TempBuf      *blur_src;
+      gint kernel_size = gimp_brush_transform_blur_kernel_size ( result->height, 
+                                                                 result->width,
+                                                                 hardness);
+      gint kernel_len = kernel_size * kernel_size;
+      gfloat blur_kernel [kernel_len];
+
+      gimp_brush_transform_fill_blur_kernel ( blur_kernel, kernel_len);
+
+      blur_src = temp_buf_copy (result, NULL);
+
+      convolve_tempbuf (blur_src, result, blur_kernel, kernel_size,
+                        gimp_brush_transform_array_sum(blur_kernel, kernel_len),
+                        GIMP_NORMAL_CONVOL, FALSE);
+
+    }
+
   return result;
 }
 
@@ -597,14 +648,14 @@ gimp_brush_real_transform_pixmap (GimpBrush *brush,
 /*  private functions  */
 
 static void
-gimp_brush_transform_matrix (GimpBrush   *brush,
+gimp_brush_transform_matrix (TempBuf     *brush,
                              gdouble      scale_x,
                              gdouble      scale_y,
                              gdouble      angle,
                              GimpMatrix3 *matrix)
 {
-  const gdouble center_x = brush->mask->width  / 2;
-  const gdouble center_y = brush->mask->height / 2;
+  const gdouble center_x = brush->width  / 2;
+  const gdouble center_y = brush->height / 2;
 
   gimp_matrix3_identity (matrix);
   gimp_matrix3_translate (matrix, - center_x, - center_y);
@@ -614,15 +665,15 @@ gimp_brush_transform_matrix (GimpBrush   *brush,
 }
 
 static void
-gimp_brush_transform_bounding_box (GimpBrush         *brush,
+gimp_brush_transform_bounding_box (TempBuf           *brush,
                                    const GimpMatrix3 *matrix,
                                    gint              *x,
                                    gint              *y,
                                    gint              *width,
                                    gint              *height)
 {
-  const gdouble  w = brush->mask->width;
-  const gdouble  h = brush->mask->height;
+  const gdouble  w = brush->width;
+  const gdouble  h = brush->height;
   gdouble        x1, x2, x3, x4;
   gdouble        y1, y2, y3, y4;
 
@@ -641,3 +692,44 @@ gimp_brush_transform_bounding_box (GimpBrush         *brush,
   *width  = MAX(1, *width);
   *height = MAX(1, *height);
 }
+
+static gdouble
+gimp_brush_transform_array_sum (gfloat *arr, gint len)
+{
+  int i;
+  gfloat total = 0;
+  for (i = 0; i < len; i++)
+    {
+      total += arr [i];
+    }
+  return total;
+}
+
+static void
+gimp_brush_transform_fill_blur_kernel (gfloat *arr, gint len)
+{
+  int i;
+  gint half_point = ((gint) len / 2) + 1;
+
+  for (i = 0; i < len; i++)
+    {
+      if (i < half_point)
+        arr [i] = half_point - i;
+      else arr [i] = i - half_point;
+    }
+}
+
+static gint
+gimp_brush_transform_blur_kernel_size (gint height, 
+                                       gint width, 
+                                       gdouble hardness)
+{
+
+  gint kernel_size = MIN (MAX_BLUR_KERNEL, MIN(width, height)) * 
+                        ((MIN (width, height) * (1.0 - hardness)) / MIN (width, height));
+
+  /*Kernel size must be odd*/
+  if ( kernel_size % 2 == 0) kernel_size++;
+  
+  return kernel_size;
+}
\ No newline at end of file
diff --git a/app/core/gimpbrush-transform.h b/app/core/gimpbrush-transform.h
index db7fe76..91bdfee 100644
--- a/app/core/gimpbrush-transform.h
+++ b/app/core/gimpbrush-transform.h
@@ -32,11 +32,13 @@ void      gimp_brush_real_transform_size   (GimpBrush *brush,
 TempBuf * gimp_brush_real_transform_mask   (GimpBrush *brush,
                                             gdouble    scale,
                                             gdouble    aspect_ratio,
-                                            gdouble    angle);
+                                            gdouble    angle,
+                                            gdouble    hardness);
 TempBuf * gimp_brush_real_transform_pixmap (GimpBrush *brush,
                                             gdouble    scale,
                                             gdouble    aspect_ratio,
-                                            gdouble    angle);
+                                            gdouble    angle,
+                                            gdouble    hardness);
 
 
 #endif  /*  __GIMP_BRUSH_SCALE_H__  */
diff --git a/app/core/gimpbrush.c b/app/core/gimpbrush.c
index 804052e..f297b54 100644
--- a/app/core/gimpbrush.c
+++ b/app/core/gimpbrush.c
@@ -277,13 +277,13 @@ gimp_brush_get_new_preview (GimpViewable *viewable,
 
       if (scale != 1.0)
         {
-          mask_buf = gimp_brush_transform_mask (brush, scale, 1.0, 0.0);
+          mask_buf = gimp_brush_transform_mask (brush, scale, 1.0, 0.0, 1.0);
 
           if (! mask_buf)
             mask_buf = temp_buf_new (1, 1, 1, 0, 0, transp);
 
           if (pixmap_buf)
-            pixmap_buf = gimp_brush_transform_pixmap (brush, scale, 1.0, 0.0);
+            pixmap_buf = gimp_brush_transform_pixmap (brush, scale, 1.0, 0.0, 1.0);
 
           mask_width  = mask_buf->width;
           mask_height = mask_buf->height;
@@ -483,23 +483,25 @@ TempBuf *
 gimp_brush_transform_mask (GimpBrush *brush,
                            gdouble    scale,
                            gdouble    aspect_ratio,
-                           gdouble    angle)
+                           gdouble    angle,
+                           gdouble    hardness)
 {
   g_return_val_if_fail (GIMP_IS_BRUSH (brush), NULL);
   g_return_val_if_fail (scale > 0.0, NULL);
   g_return_val_if_fail (aspect_ratio > 0.0, NULL);
 
-  if ((scale == 1.0) && (aspect_ratio == 1.0) && (angle == 0.0))
+  if ((scale == 1.0) && (aspect_ratio == 1.0) && (angle == 0.0) && (hardness == 1.0))
     return temp_buf_copy (brush->mask, NULL);
 
-  return GIMP_BRUSH_GET_CLASS (brush)->transform_mask (brush, scale, aspect_ratio, angle);
+  return GIMP_BRUSH_GET_CLASS (brush)->transform_mask (brush, scale, aspect_ratio, angle, hardness);
 }
 
 TempBuf *
 gimp_brush_transform_pixmap (GimpBrush *brush,
                              gdouble    scale,
                              gdouble    aspect_ratio,
-                             gdouble    angle)
+                             gdouble    angle,
+                             gdouble    hardness)
 {
   g_return_val_if_fail (GIMP_IS_BRUSH (brush), NULL);
   g_return_val_if_fail (brush->pixmap != NULL, NULL);
@@ -507,10 +509,10 @@ gimp_brush_transform_pixmap (GimpBrush *brush,
   g_return_val_if_fail (aspect_ratio > 0.0, NULL);
 
 
-  if ((scale == 1.0) && (aspect_ratio == 1.0) && (angle == 0.0))
+  if ((scale == 1.0) && (aspect_ratio == 1.0) && (angle == 0.0) && (hardness == 1.0))
     return temp_buf_copy (brush->pixmap, NULL);
 
-  return GIMP_BRUSH_GET_CLASS (brush)->transform_pixmap (brush, scale, aspect_ratio, angle);
+  return GIMP_BRUSH_GET_CLASS (brush)->transform_pixmap (brush, scale, aspect_ratio, angle, hardness);
 }
 
 TempBuf *
diff --git a/app/core/gimpbrush.h b/app/core/gimpbrush.h
index 9c5df28..2a1e96d 100644
--- a/app/core/gimpbrush.h
+++ b/app/core/gimpbrush.h
@@ -65,11 +65,13 @@ struct _GimpBrushClass
   TempBuf   * (* transform_mask)   (GimpBrush        *brush,
                                     gdouble           scale_x,
                                     gdouble           scale_y,
-                                    gdouble           angle);
+                                    gdouble           angle,
+                                    gdouble           hardness);
   TempBuf   * (* transform_pixmap) (GimpBrush        *brush,
                                     gdouble           scale_x,
                                     gdouble           scale_y,
-                                    gdouble           angle);
+                                    gdouble           angle,
+                                    gdouble           hardness);
 
   /*  signals  */
   void        (* spacing_changed)  (GimpBrush        *brush);
@@ -98,11 +100,13 @@ void        gimp_brush_transform_size   (GimpBrush        *brush,
 TempBuf   * gimp_brush_transform_mask   (GimpBrush        *brush,
                                          gdouble           scale_x,
                                          gdouble           scale_y,
-                                         gdouble           angle);
+                                         gdouble           angle,
+                                         gdouble           hardness);
 TempBuf   * gimp_brush_transform_pixmap (GimpBrush        *brush,
                                          gdouble           scale_x,
                                          gdouble           scale_y,
-                                         gdouble           angle);
+                                         gdouble           angle,
+                                         gdouble           hardness);
 
 TempBuf   * gimp_brush_get_mask         (const GimpBrush  *brush);
 TempBuf   * gimp_brush_get_pixmap       (const GimpBrush  *brush);
diff --git a/app/core/gimpbrushgenerated.c b/app/core/gimpbrushgenerated.c
index 3bde69b..639fc1e 100644
--- a/app/core/gimpbrushgenerated.c
+++ b/app/core/gimpbrushgenerated.c
@@ -74,7 +74,8 @@ static void          gimp_brush_generated_transform_size(GimpBrush    *gbrush,
 static TempBuf     * gimp_brush_generated_transform_mask(GimpBrush    *gbrush,
                                                          gdouble       scale,
                                                          gdouble       aspect_ratio,
-                                                         gdouble       angle);
+                                                         gdouble       angle,
+                                                         gdouble       hardness);
 
 static TempBuf     * gimp_brush_generated_calc          (GimpBrushGenerated      *brush,
                                                          GimpBrushGeneratedShape  shape,
@@ -328,7 +329,8 @@ static TempBuf *
 gimp_brush_generated_transform_mask (GimpBrush *gbrush,
                                      gdouble    scale,
                                      gdouble    aspect_ratio,
-                                     gdouble    angle)
+                                     gdouble    angle,
+                                     gdouble    hardness)
 {
   GimpBrushGenerated *brush  = GIMP_BRUSH_GENERATED (gbrush);
 
@@ -346,7 +348,7 @@ gimp_brush_generated_transform_mask (GimpBrush *gbrush,
                                     brush->shape,
                                     brush->radius * scale ,
                                     brush->spikes,
-                                    brush->hardness,
+                                    brush->hardness * hardness,
                                     brush->aspect_ratio * aspect_ratio,
                                     (brush->angle + 360 * angle),
                                     NULL, NULL);
diff --git a/app/paint-funcs/paint-funcs.c b/app/paint-funcs/paint-funcs.c
index 942f48a..8ff36b1 100644
--- a/app/paint-funcs/paint-funcs.c
+++ b/app/paint-funcs/paint-funcs.c
@@ -2333,6 +2333,140 @@ convolve_region (PixelRegion         *srcR,
     }
 }
 
+void
+convolve_tempbuf (TempBuf             *srcR,
+                  TempBuf             *destR,
+                  const gfloat        *matrix,
+                  gint                 size,
+                  gdouble              divisor,
+                  GimpConvolutionType  mode,
+                  gboolean             alpha_weighting)
+{
+  /*  Convolve the src image using the convolution matrix, writing to dest  */
+  /*  Convolve is not tile-enabled--use accordingly  */
+  const guchar *src       = temp_buf_get_data(srcR);
+  guchar       *dest      = temp_buf_get_data(destR);
+  const gint    bytes     = srcR->bytes;
+  const gint    a_byte    = bytes - 1;
+  const gint    rowstride = bytes * srcR->width;
+  const gint    dest_rowstride = bytes * destR->width;
+  const gint    margin    = size / 2;
+  const gint    x1        = srcR->x;
+  const gint    y1        = srcR->y;
+  const gint    x2        = srcR->x + srcR->width - 1;
+  const gint    y2        = srcR->y + srcR->height - 1;
+  gint          x, y;
+  gint          offset;
+
+  /*  If the mode is NEGATIVE_CONVOL, the offset should be 128  */
+  if (mode == GIMP_NEGATIVE_CONVOL)
+    {
+      offset = 128;
+      mode = GIMP_NORMAL_CONVOL;
+    }
+  else
+    {
+      offset = 0;
+    }
+
+  for (y = 0; y < destR->height; y++)
+    {
+      guchar *d = dest;
+
+      if (alpha_weighting && FALSE)
+        {
+          for (x = 0; x < destR->width; x++)
+            {
+              const gfloat *m                = matrix;
+              gdouble       total[4]         = { 0.0, 0.0, 0.0, 0.0 };
+              gdouble       weighted_divisor = 0.0;
+              gint          i, j, b;
+
+              for (j = y - margin; j <= y + margin; j++)
+                {
+                  for (i = x - margin; i <= x + margin; i++, m++)
+                    {
+                      gint          xx = CLAMP (i, x1, x2);
+                      gint          yy = CLAMP (j, y1, y2);
+                      const guchar *s  = src + yy * rowstride + xx * bytes;
+                      const guchar  a  = s[a_byte];
+
+                      if (a)
+                        {
+                          gdouble mult_alpha = *m * a;
+
+                          weighted_divisor += mult_alpha;
+
+                          for (b = 0; b < a_byte; b++)
+                            total[b] += mult_alpha * s[b];
+
+                          total[a_byte] += mult_alpha;
+                        }
+                    }
+                }
+
+              if (weighted_divisor == 0.0)
+                weighted_divisor = divisor;
+
+              for (b = 0; b < a_byte; b++)
+                total[b] /= weighted_divisor;
+
+              total[a_byte] /= divisor;
+
+              for (b = 0; b < bytes; b++)
+                {
+                  total[b] += offset;
+
+                  if (mode != GIMP_NORMAL_CONVOL && total[b] < 0.0)
+                    total[b] = - total[b];
+
+                  if (total[b] < 0.0)
+                    *d++ = 0;
+                  else
+                    *d++ = (total[b] > 255.0) ? 255 : (guchar) ROUND (total[b]);
+                }
+            }
+        }
+      else
+        {
+          for (x = 0; x < destR->width; x++)
+            {
+              const gfloat *m        = matrix;
+              gdouble       total[4] = { 0.0, 0.0, 0.0, 0.0 };
+              gint          i, j, b;
+
+              for (j = y - margin; j <= y + margin; j++)
+                {
+                  for (i = x - margin; i <= x + margin; i++, m++)
+                    {
+                      gint          xx = CLAMP (i, x1, x2);
+                      gint          yy = CLAMP (j, y1, y2);
+                      const guchar *s  = src + yy * rowstride + xx * bytes;
+
+                      for (b = 0; b < bytes; b++)
+                        total[b] += *m * s[b];
+                    }
+                }
+
+              for (b = 0; b < bytes; b++)
+                {
+                  total[b] = total[b] / divisor + offset;
+
+                  if (mode != GIMP_NORMAL_CONVOL && total[b] < 0.0)
+                    total[b] = - total[b];
+
+                  if (total[b] < 0.0)
+                    *d++ = 0.0;
+                  else
+                    *d++ = (total[b] > 255.0) ? 255 : (guchar) ROUND (total[b]);
+                }
+            }
+        }
+
+      dest += dest_rowstride;
+    }
+}
+
 /* Convert from separated alpha to premultiplied alpha. Only works on
    non-tiled regions! */
 void
diff --git a/app/paint-funcs/paint-funcs.h b/app/paint-funcs/paint-funcs.h
index ed4d3fb..9f16426 100644
--- a/app/paint-funcs/paint-funcs.h
+++ b/app/paint-funcs/paint-funcs.h
@@ -400,6 +400,14 @@ void  convolve_region                     (PixelRegion         *srcR,
                                            GimpConvolutionType  mode,
                                            gboolean             alpha_weighting);
 
+void  convolve_tempbuf                    (TempBuf             *srcR,
+                                           TempBuf             *destR,
+                                           const gfloat        *matrix,
+                                           gint                 size,
+                                           gdouble              divisor,
+                                           GimpConvolutionType  mode,
+                                           gboolean             alpha_weighting);
+
 void  multiply_alpha_region               (PixelRegion *srcR);
 
 void  separate_alpha_region               (PixelRegion *srcR);
diff --git a/app/paint/gimpbrushcore.c b/app/paint/gimpbrushcore.c
index 81e6376..5c8e028 100644
--- a/app/paint/gimpbrushcore.c
+++ b/app/paint/gimpbrushcore.c
@@ -189,6 +189,7 @@ gimp_brush_core_init (GimpBrushCore *core)
   core->spacing                      = 1.0;
   core->scale                        = 1.0;
   core->angle                        = 1.0;
+  core->hardness                     = 1.0;
 
   core->pressure_brush               = NULL;
 
@@ -827,6 +828,11 @@ gimp_brush_core_get_paint_area (GimpPaintCore    *paint_core,
                                                                  paint_options,
                                                                  fade_point);
 
+          core->hardness = gimp_dynamics_output_get_linear_value (core->dynamics->hardness_output,
+                                                                  coords,
+                                                                  paint_options,
+                                                                  fade_point);
+
           core->aspect_ratio *= gimp_dynamics_output_get_aspect_value (core->dynamics->aspect_ratio_output,
                                                                        coords,
                                                                        paint_options,
@@ -943,6 +949,7 @@ gimp_brush_core_create_bound_segs (GimpBrushCore    *core,
   gdouble  scale;
   gdouble  angle;
   gdouble  aspect_ratio;
+  gdouble  hardness;
 
   g_return_if_fail (GIMP_IS_BRUSH_CORE (core));
   g_return_if_fail (core->main_brush != NULL);
@@ -957,7 +964,7 @@ gimp_brush_core_create_bound_segs (GimpBrushCore    *core,
       scale = gimp_brush_core_clamp_brush_scale (core, scale);
 
       mask = gimp_brush_transform_mask (core->main_brush,
-                                        scale, aspect_ratio, angle);
+                                        scale, aspect_ratio, angle, 1.0);
     }
 
   if (mask)
@@ -1463,7 +1470,10 @@ gimp_brush_core_transform_mask (GimpBrushCore *core,
   if (core->scale <= 0.0)
     return NULL; /* Should never happen now, with scale clamping. */
 
-  if ((core->scale == 1.0) && (core->angle == 0.0) && (core->aspect_ratio == 1.0))
+  if ((core->scale == 1.0) &&
+      (core->angle == 0.0) &&
+      (core->hardness == 1.0) && 
+      (core->aspect_ratio == 1.0))
     return brush->mask;
 
   gimp_brush_transform_size (brush,
@@ -1477,6 +1487,7 @@ gimp_brush_core_transform_mask (GimpBrushCore *core,
       height             == core->last_transform_height &&
       core->scale        == core->last_scale            &&
       core->angle        == core->last_angle            &&
+      core->hardness     == core->last_hardness         &&
       core->aspect_ratio == core->last_aspect_ratio)
     {
       return core->transform_brush;
@@ -1487,16 +1498,17 @@ gimp_brush_core_transform_mask (GimpBrushCore *core,
   core->last_transform_height = height;
   core->last_scale        = core->scale;
   core->last_angle        = core->angle;
+  core->last_hardness     = core->hardness;
   core->last_aspect_ratio = core->aspect_ratio;
 
-
   if (core->transform_brush)
     temp_buf_free (core->transform_brush);
 
   core->transform_brush = gimp_brush_transform_mask (brush,
                                                      core->scale,
                                                      core->aspect_ratio,
-                                                     core->angle);
+                                                     core->angle,
+                                                     core->hardness);
 
   core->cache_invalid       = TRUE;
   core->solid_cache_invalid = TRUE;
@@ -1514,7 +1526,10 @@ gimp_brush_core_transform_pixmap (GimpBrushCore *core,
   if (core->scale <= 0.0)
     return NULL;
 
-  if ((core->scale == 1.0) && (core->angle == 0.0) && (core->aspect_ratio == 1.0))
+  if ((core->scale        == 1.0) &&
+      (core->angle        == 0.0) &&
+      (core->hardness     == 1.0) &&
+      (core->aspect_ratio == 1.0))
     return brush->pixmap;
 
   gimp_brush_transform_size (brush,
@@ -1527,6 +1542,7 @@ gimp_brush_core_transform_pixmap (GimpBrushCore *core,
       width              == core->last_transform_pixmap_width  &&
       height             == core->last_transform_pixmap_height &&
       core->angle        == core->last_angle                   &&
+      core->hardness     == core->last_hardness                &&
       core->aspect_ratio == core->last_aspect_ratio)
     {
       return core->transform_pixmap;
@@ -1535,8 +1551,9 @@ gimp_brush_core_transform_pixmap (GimpBrushCore *core,
   core->last_transform_pixmap        = brush->pixmap;
   core->last_transform_pixmap_width  = width;
   core->last_transform_pixmap_height = height;
-  core->last_angle = core->angle;
-  core->last_aspect_ratio = core->aspect_ratio;
+  core->last_angle                   = core->angle;
+  core->last_hardness                = core->hardness;
+  core->last_aspect_ratio            = core->aspect_ratio;
 
   if (core->transform_pixmap)
     temp_buf_free (core->transform_pixmap);
@@ -1545,7 +1562,8 @@ gimp_brush_core_transform_pixmap (GimpBrushCore *core,
   core->transform_pixmap = gimp_brush_transform_pixmap (brush,
                                                         core->scale,
                                                         core->aspect_ratio,
-                                                        core->angle);
+                                                        core->angle,
+                                                        core->hardness);
 
   core->cache_invalid = TRUE;
 
diff --git a/app/paint/gimpbrushcore.h b/app/paint/gimpbrushcore.h
index 03806c0..05fb34a 100644
--- a/app/paint/gimpbrushcore.h
+++ b/app/paint/gimpbrushcore.h
@@ -47,6 +47,7 @@ struct _GimpBrushCore
   gdouble        spacing;
   gdouble        scale;
   gdouble        angle;
+  gdouble        hardness;
   gdouble        aspect_ratio;
 
   /*  brush buffers  */
@@ -62,6 +63,7 @@ struct _GimpBrushCore
   gint           last_transform_height;
   gdouble        last_scale;
   gdouble        last_angle;
+  gdouble        last_hardness;
   gdouble        last_aspect_ratio;
 
   TempBuf       *transform_pixmap;
diff --git a/app/paint/gimppaintoptions.c b/app/paint/gimppaintoptions.c
index 3468c0e..1d2f1bb 100644
--- a/app/paint/gimppaintoptions.c
+++ b/app/paint/gimppaintoptions.c
@@ -646,8 +646,11 @@ gimp_paint_options_get_brush_mode (GimpPaintOptions *paint_options)
 
   dynamics = gimp_context_get_dynamics (GIMP_CONTEXT (paint_options));
 
-  if (gimp_dynamics_output_is_enabled(dynamics->hardness_output))
-    return GIMP_BRUSH_PRESSURE;
+/*  Im leaving the pressurize code in here, but Im not sure how,
+ *  or if at all it should be used. Not as hardness anyway.
+ * 
+ *  if (gimp_dynamics_output_is_enabled(dynamics->hardness_output))
+ *    return GIMP_BRUSH_PRESSURE; */
 
   return GIMP_BRUSH_SOFT;
 }



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