mirror of https://github.com/GNOME/gimp.git
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.
This commit is contained in:
parent
37b6a205d3
commit
9774988f30
|
@ -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;
|
||||
}
|
|
@ -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__ */
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue