mirror of https://github.com/GNOME/gimp.git
Bug 520078 – Rotate brushes
2009-02-05 Sven Neumann <sven@gimp.org> Bug 520078 – Rotate brushes Applied patch from Alexia Death: * app/core/gimpbrush.[ch] * app/core/gimpbrushgenerated.c * app/core/gimpbrush-transform.[ch]: affine transformations for brushes. So far only scaling and rotation is supported. The transformation is done using nearest-neighbour. This is a regression and we need to add back interpolation before the next release. * app/paint/gimpsmudge.c * app/paint/gimppaintoptions.[ch] * app/paint/gimpbrushcore.[ch]: allow to control the brush rotation angle. * app/tools/gimppaintoptions-gui.c * app/tools/gimpbrushtool.c: added UI for controlling the brush rotation angle. * app/actions/tools-actions.c * app/actions/tools-commands.[ch]: add actions for controlling the brush rotation angle. svn path=/trunk/; revision=27987
This commit is contained in:
parent
d2a716d37f
commit
30c118b53c
27
ChangeLog
27
ChangeLog
|
@ -1,3 +1,30 @@
|
|||
2009-02-05 Sven Neumann <sven@gimp.org>
|
||||
|
||||
Bug 520078 – Rotate brushes
|
||||
|
||||
Applied patch from Alexia Death:
|
||||
|
||||
* app/core/gimpbrush.[ch]
|
||||
* app/core/gimpbrushgenerated.c
|
||||
* app/core/gimpbrush-transform.[ch]: affine transformations for
|
||||
brushes. So far only scaling and rotation is supported. The
|
||||
transformation is done using nearest-neighbour. This is a
|
||||
regression and we need to add back interpolation before the next
|
||||
release.
|
||||
|
||||
* app/paint/gimpsmudge.c
|
||||
* app/paint/gimppaintoptions.[ch]
|
||||
* app/paint/gimpbrushcore.[ch]: allow to control the brush
|
||||
rotation angle.
|
||||
|
||||
* app/tools/gimppaintoptions-gui.c
|
||||
* app/tools/gimpbrushtool.c: added UI for controlling the
|
||||
brush rotation angle.
|
||||
|
||||
* app/actions/tools-actions.c
|
||||
* app/actions/tools-commands.[ch]: add actions for controlling the
|
||||
brush rotation angle.
|
||||
|
||||
2009-02-05 Michael Natterer <mitch@gimp.org>
|
||||
|
||||
* app/core/gimpdrawable.h
|
||||
|
|
|
@ -181,6 +181,42 @@ static const GimpEnumActionEntry tools_paint_brush_scale_actions[] =
|
|||
NULL },
|
||||
};
|
||||
|
||||
static const GimpEnumActionEntry tools_paint_brush_angle_actions[] =
|
||||
{
|
||||
{ "tools-paint-brush-angle-set", GIMP_STOCK_TOOL_PAINTBRUSH,
|
||||
"Set Brush Angle", NULL, NULL,
|
||||
GIMP_ACTION_SELECT_SET, TRUE,
|
||||
NULL },
|
||||
{ "tools-paint-brush-angle-set-to-default", GIMP_STOCK_TOOL_PAINTBRUSH,
|
||||
"Set Brush Angle To Default Value", NULL, NULL,
|
||||
GIMP_ACTION_SELECT_SET_TO_DEFAULT, FALSE,
|
||||
NULL },
|
||||
{ "tools-paint-brush-angle-minimum", GIMP_STOCK_TOOL_PAINTBRUSH,
|
||||
"Minimize Brush Angle", NULL, NULL,
|
||||
GIMP_ACTION_SELECT_FIRST, FALSE,
|
||||
NULL },
|
||||
{ "tools-paint-brush-angle-maximum", GIMP_STOCK_TOOL_PAINTBRUSH,
|
||||
"Maximize Brush Angle", NULL, NULL,
|
||||
GIMP_ACTION_SELECT_LAST, FALSE,
|
||||
NULL },
|
||||
{ "tools-paint-brush-angle-decrease", GIMP_STOCK_TOOL_PAINTBRUSH,
|
||||
"Decrease Brush Angle", NULL, NULL,
|
||||
GIMP_ACTION_SELECT_PREVIOUS, FALSE,
|
||||
NULL },
|
||||
{ "tools-paint-brush-angle-increase", GIMP_STOCK_TOOL_PAINTBRUSH,
|
||||
"Increase Brush Angle", NULL, NULL,
|
||||
GIMP_ACTION_SELECT_NEXT, FALSE,
|
||||
NULL },
|
||||
{ "tools-paint-brush-angle-decrease-skip", GIMP_STOCK_TOOL_PAINTBRUSH,
|
||||
"Decrease Brush Angle More", NULL, NULL,
|
||||
GIMP_ACTION_SELECT_SKIP_PREVIOUS, FALSE,
|
||||
NULL },
|
||||
{ "tools-paint-brush-angle-increase-skip", GIMP_STOCK_TOOL_PAINTBRUSH,
|
||||
"Increase Brush Angle More", NULL, NULL,
|
||||
GIMP_ACTION_SELECT_SKIP_NEXT, FALSE,
|
||||
NULL },
|
||||
};
|
||||
|
||||
static const GimpEnumActionEntry tools_ink_blob_size_actions[] =
|
||||
{
|
||||
{ "tools-ink-blob-size-set", GIMP_STOCK_TOOL_INK,
|
||||
|
@ -589,6 +625,11 @@ tools_actions_setup (GimpActionGroup *group)
|
|||
G_N_ELEMENTS (tools_paint_brush_scale_actions),
|
||||
G_CALLBACK (tools_paint_brush_scale_cmd_callback));
|
||||
|
||||
gimp_action_group_add_enum_actions (group, NULL,
|
||||
tools_paint_brush_angle_actions,
|
||||
G_N_ELEMENTS (tools_paint_brush_angle_actions),
|
||||
G_CALLBACK (tools_paint_brush_angle_cmd_callback));
|
||||
|
||||
gimp_action_group_add_enum_actions (group, NULL,
|
||||
tools_ink_blob_size_actions,
|
||||
G_N_ELEMENTS (tools_ink_blob_size_actions),
|
||||
|
|
|
@ -294,6 +294,26 @@ tools_paint_brush_scale_cmd_callback (GtkAction *action,
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
tools_paint_brush_angle_cmd_callback (GtkAction *action,
|
||||
gint value,
|
||||
gpointer data)
|
||||
{
|
||||
GimpContext *context;
|
||||
GimpToolInfo *tool_info;
|
||||
return_if_no_context (context, data);
|
||||
|
||||
tool_info = gimp_context_get_tool (context);
|
||||
|
||||
if (tool_info && GIMP_IS_PAINT_OPTIONS (tool_info->tool_options))
|
||||
{
|
||||
action_select_property ((GimpActionSelectType) value,
|
||||
G_OBJECT (tool_info->tool_options),
|
||||
"brush-angle",
|
||||
0.01, 0.1, 1.0, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
tools_ink_blob_size_cmd_callback (GtkAction *action,
|
||||
gint value,
|
||||
|
|
|
@ -45,6 +45,10 @@ void tools_paint_brush_scale_cmd_callback (GtkAction *action,
|
|||
gint value,
|
||||
gpointer data);
|
||||
|
||||
void tools_paint_brush_angle_cmd_callback (GtkAction *action,
|
||||
gint value,
|
||||
gpointer data);
|
||||
|
||||
void tools_ink_blob_size_cmd_callback (GtkAction *action,
|
||||
gint value,
|
||||
gpointer data);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* GIMP - The GNU Image Manipulation Program
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* gimpbrush-scale.c
|
||||
* gimpbrush-transform.c
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -23,26 +23,26 @@
|
|||
|
||||
#include "core-types.h"
|
||||
|
||||
#include "libgimpmath/gimpmath.h"
|
||||
|
||||
#include "gimpbrush.h"
|
||||
#include "gimpbrush-transform.h"
|
||||
|
||||
#include "base/pixel-region.h"
|
||||
#include "base/temp-buf.h"
|
||||
|
||||
#include "paint-funcs/scale-region.h"
|
||||
|
||||
|
||||
/* local function prototypes */
|
||||
|
||||
static TempBuf * gimp_brush_scale_buf_up (TempBuf *brush_buf,
|
||||
gint dest_width,
|
||||
gint dest_height);
|
||||
static TempBuf * gimp_brush_scale_mask_down (TempBuf *brush_mask,
|
||||
gint dest_width,
|
||||
gint dest_height);
|
||||
static TempBuf * gimp_brush_scale_pixmap_down (TempBuf *pixmap,
|
||||
gint dest_width,
|
||||
gint dest_height);
|
||||
static void gimp_brush_transform_matrix (GimpBrush *brush,
|
||||
gdouble scale,
|
||||
gdouble angle,
|
||||
GimpMatrix3 *matrix);
|
||||
static void gimp_brush_transform_bounding_box (GimpBrush *brush,
|
||||
const GimpMatrix3 *matrix,
|
||||
gint *x,
|
||||
gint *y,
|
||||
gint *width,
|
||||
gint *height);
|
||||
|
||||
|
||||
/* public functions */
|
||||
|
@ -50,421 +50,187 @@ static TempBuf * gimp_brush_scale_pixmap_down (TempBuf *pixmap,
|
|||
void
|
||||
gimp_brush_real_transform_size (GimpBrush *brush,
|
||||
gdouble scale,
|
||||
gdouble angle,
|
||||
gint *width,
|
||||
gint *height)
|
||||
{
|
||||
*width = (gint) (brush->mask->width * scale + 0.5);
|
||||
*height = (gint) (brush->mask->height * scale + 0.5);
|
||||
GimpMatrix3 matrix;
|
||||
gint x, y;
|
||||
|
||||
gimp_brush_transform_matrix (brush, scale, angle, &matrix);
|
||||
gimp_brush_transform_bounding_box (brush, &matrix, &x, &y, width, height);
|
||||
}
|
||||
|
||||
TempBuf *
|
||||
gimp_brush_real_transform_mask (GimpBrush *brush,
|
||||
gdouble scale)
|
||||
gdouble scale,
|
||||
gdouble angle)
|
||||
{
|
||||
gint dest_width;
|
||||
gint dest_height;
|
||||
TempBuf *result;
|
||||
guchar *dest;
|
||||
const guchar *src;
|
||||
GimpMatrix3 matrix;
|
||||
gint src_width;
|
||||
gint src_height;
|
||||
gint dest_width;
|
||||
gint dest_height;
|
||||
gint x, y;
|
||||
|
||||
gimp_brush_transform_size (brush, scale, &dest_width, &dest_height);
|
||||
gimp_brush_transform_matrix (brush, scale, angle, &matrix);
|
||||
|
||||
if (dest_width <= 0 || dest_height <= 0)
|
||||
return NULL;
|
||||
if (gimp_matrix3_is_identity (&matrix))
|
||||
return temp_buf_copy (brush->mask, NULL);
|
||||
|
||||
if (scale <= 1.0)
|
||||
src_width = brush->mask->width;
|
||||
src_height = brush->mask->height;
|
||||
|
||||
gimp_brush_transform_bounding_box (brush, &matrix,
|
||||
&x, &y, &dest_width, &dest_height);
|
||||
gimp_matrix3_translate (&matrix, -x, -y);
|
||||
gimp_matrix3_invert (&matrix);
|
||||
|
||||
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);
|
||||
|
||||
for (y = 0; y < dest_height; y++)
|
||||
{
|
||||
/* Downscaling with brush_transform_mask is much faster than with
|
||||
* gimp_brush_scale_buf.
|
||||
*/
|
||||
return gimp_brush_scale_mask_down (brush->mask,
|
||||
dest_width, dest_height);
|
||||
for (x = 0; x < dest_width; x++)
|
||||
{
|
||||
gdouble dx, dy;
|
||||
gint ix, iy;
|
||||
|
||||
gimp_matrix3_transform_point (&matrix, x, y, &dx, &dy);
|
||||
|
||||
ix = ROUND (dx);
|
||||
iy = ROUND (dy);
|
||||
|
||||
if (ix > 0 && ix < src_width &&
|
||||
iy > 0 && iy < src_height)
|
||||
{
|
||||
*dest = src[iy * src_width + ix];
|
||||
}
|
||||
else
|
||||
{
|
||||
*dest = 0;
|
||||
}
|
||||
|
||||
dest++;
|
||||
}
|
||||
}
|
||||
|
||||
return gimp_brush_scale_buf_up (brush->mask, dest_width, dest_height);
|
||||
return result;
|
||||
}
|
||||
|
||||
TempBuf *
|
||||
gimp_brush_real_transform_pixmap (GimpBrush *brush,
|
||||
gdouble scale)
|
||||
gdouble scale,
|
||||
gdouble angle)
|
||||
{
|
||||
gint dest_width;
|
||||
gint dest_height;
|
||||
TempBuf *result;
|
||||
guchar *dest;
|
||||
const guchar *src;
|
||||
GimpMatrix3 matrix;
|
||||
gint src_width;
|
||||
gint src_height;
|
||||
gint dest_width;
|
||||
gint dest_height;
|
||||
gint x, y;
|
||||
|
||||
gimp_brush_transform_size (brush, scale, &dest_width, &dest_height);
|
||||
gimp_brush_transform_matrix (brush, scale, angle, &matrix);
|
||||
|
||||
if (dest_width <= 0 || dest_height <= 0)
|
||||
return NULL;
|
||||
if (gimp_matrix3_is_identity (&matrix))
|
||||
return temp_buf_copy (brush->pixmap, NULL);
|
||||
|
||||
if (scale <= 1.0)
|
||||
src_width = brush->pixmap->width;
|
||||
src_height = brush->pixmap->height;
|
||||
|
||||
gimp_brush_transform_bounding_box (brush, &matrix,
|
||||
&x, &y, &dest_width, &dest_height);
|
||||
gimp_matrix3_translate (&matrix, -x, -y);
|
||||
gimp_matrix3_invert (&matrix);
|
||||
|
||||
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);
|
||||
|
||||
for (y = 0; y < dest_height; y++)
|
||||
{
|
||||
/* Downscaling with brush_scale_pixmap is much faster than with
|
||||
* gimp_brush_scale_buf.
|
||||
*/
|
||||
return gimp_brush_scale_pixmap_down (brush->pixmap,
|
||||
dest_width, dest_height);
|
||||
for (x = 0; x < dest_width; x++)
|
||||
{
|
||||
gdouble dx, dy;
|
||||
gint ix, iy;
|
||||
|
||||
gimp_matrix3_transform_point (&matrix, x, y, &dx, &dy);
|
||||
|
||||
ix = ROUND (dx);
|
||||
iy = ROUND (dy);
|
||||
|
||||
if (ix > 0 && ix < src_width &&
|
||||
iy > 0 && iy < src_height)
|
||||
{
|
||||
const guchar *s = src + 3 * (iy * src_width + ix);
|
||||
|
||||
dest[0] = s[0];
|
||||
dest[1] = s[1];
|
||||
dest[2] = s[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
dest[0] = 0;
|
||||
dest[1] = 0;
|
||||
dest[2] = 0;
|
||||
}
|
||||
|
||||
dest += 3;
|
||||
}
|
||||
}
|
||||
|
||||
return gimp_brush_scale_buf_up (brush->pixmap, dest_width, dest_height);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* private functions */
|
||||
|
||||
static TempBuf *
|
||||
gimp_brush_scale_buf_up (TempBuf *brush_buf,
|
||||
gint dest_width,
|
||||
gint dest_height)
|
||||
static void
|
||||
gimp_brush_transform_matrix (GimpBrush *brush,
|
||||
gdouble scale,
|
||||
gdouble angle,
|
||||
GimpMatrix3 *matrix)
|
||||
{
|
||||
PixelRegion source_region;
|
||||
PixelRegion dest_region;
|
||||
TempBuf *dest_brush_buf;
|
||||
const gdouble center_x = brush->mask->width / 2;
|
||||
const gdouble center_y = brush->mask->height / 2;
|
||||
|
||||
pixel_region_init_temp_buf (&source_region, brush_buf,
|
||||
0, 0, brush_buf->width, brush_buf->height);
|
||||
|
||||
dest_brush_buf = temp_buf_new (dest_width, dest_height, brush_buf->bytes,
|
||||
0, 0, NULL);
|
||||
|
||||
pixel_region_init_temp_buf (&dest_region, dest_brush_buf,
|
||||
0, 0, dest_width, dest_height);
|
||||
|
||||
scale_region (&source_region, &dest_region,
|
||||
GIMP_INTERPOLATION_LINEAR, NULL, NULL);
|
||||
|
||||
return dest_brush_buf;
|
||||
gimp_matrix3_identity (matrix);
|
||||
gimp_matrix3_translate (matrix, - center_x, - center_x);
|
||||
gimp_matrix3_rotate (matrix, 2 * G_PI * angle);
|
||||
gimp_matrix3_translate (matrix, center_x, center_y);
|
||||
gimp_matrix3_scale (matrix, scale, scale);
|
||||
}
|
||||
|
||||
static TempBuf *
|
||||
gimp_brush_scale_mask_down (TempBuf *brush_mask,
|
||||
gint dest_width,
|
||||
gint dest_height)
|
||||
static void
|
||||
gimp_brush_transform_bounding_box (GimpBrush *brush,
|
||||
const GimpMatrix3 *matrix,
|
||||
gint *x,
|
||||
gint *y,
|
||||
gint *width,
|
||||
gint *height)
|
||||
{
|
||||
TempBuf *scale_brush;
|
||||
gint src_width;
|
||||
gint src_height;
|
||||
gint value;
|
||||
gint area;
|
||||
gint i, j;
|
||||
gint x, x0, y, y0;
|
||||
gint dx, dx0, dy, dy0;
|
||||
gint fx, fx0, fy, fy0;
|
||||
guchar *src, *dest;
|
||||
const gdouble w = brush->mask->width;
|
||||
const gdouble h = brush->mask->height;
|
||||
gdouble x1, x2, x3, x4;
|
||||
gdouble y1, y2, y3, y4;
|
||||
|
||||
g_return_val_if_fail (brush_mask != NULL &&
|
||||
dest_width != 0 && dest_height != 0, NULL);
|
||||
gimp_matrix3_transform_point (matrix, 0, 0, &x1, &y1);
|
||||
gimp_matrix3_transform_point (matrix, w, 0, &x2, &y2);
|
||||
gimp_matrix3_transform_point (matrix, 0, h, &x3, &y3);
|
||||
gimp_matrix3_transform_point (matrix, w, h, &x4, &y4);
|
||||
|
||||
src_width = brush_mask->width;
|
||||
src_height = brush_mask->height;
|
||||
*x = floor (MIN (MIN (x1, x2), MIN (x3, x4)));
|
||||
*y = floor (MIN (MIN (y1, y2), MIN (y3, y4)));
|
||||
|
||||
scale_brush = temp_buf_new (dest_width, dest_height, 1, 0, 0, NULL);
|
||||
g_return_val_if_fail (scale_brush != NULL, NULL);
|
||||
|
||||
/* get the data */
|
||||
dest = temp_buf_get_data (scale_brush);
|
||||
src = temp_buf_get_data (brush_mask);
|
||||
|
||||
fx = fx0 = (src_width << 8) / dest_width;
|
||||
fy = fy0 = (src_height << 8) / dest_height;
|
||||
|
||||
area = (fx0 * fy0) >> 8;
|
||||
|
||||
x = x0 = 0;
|
||||
y = y0 = 0;
|
||||
dx = dx0 = 0;
|
||||
dy = dy0 = 0;
|
||||
|
||||
for (i = 0; i < dest_height; i++)
|
||||
{
|
||||
for (j = 0; j < dest_width; j++)
|
||||
{
|
||||
value = 0;
|
||||
|
||||
fy = fy0;
|
||||
y = y0;
|
||||
dy = dy0;
|
||||
|
||||
if (dy)
|
||||
{
|
||||
fx = fx0;
|
||||
x = x0;
|
||||
dx = dx0;
|
||||
|
||||
if (dx)
|
||||
{
|
||||
value += (dx * dy * src[x + src_width * y]) >> 8;
|
||||
x++;
|
||||
fx -= dx;
|
||||
dx = 0;
|
||||
}
|
||||
while (fx >= 256)
|
||||
{
|
||||
value += dy * src[x + src_width * y];
|
||||
x++;
|
||||
fx -= 256;
|
||||
}
|
||||
if (fx)
|
||||
{
|
||||
value += fx * dy * src[x + src_width * y] >> 8;
|
||||
dx = 256 - fx;
|
||||
}
|
||||
|
||||
y++;
|
||||
fy -= dy;
|
||||
dy = 0;
|
||||
}
|
||||
|
||||
while (fy >= 256)
|
||||
{
|
||||
fx = fx0;
|
||||
x = x0;
|
||||
dx = dx0;
|
||||
|
||||
if (dx)
|
||||
{
|
||||
value += dx * src[x + src_width * y];
|
||||
x++;
|
||||
fx -= dx;
|
||||
dx = 0;
|
||||
}
|
||||
while (fx >= 256)
|
||||
{
|
||||
value += 256 * src[x + src_width * y];
|
||||
x++;
|
||||
fx -= 256;
|
||||
}
|
||||
if (fx)
|
||||
{
|
||||
value += fx * src[x + src_width * y];
|
||||
dx = 256 - fx;
|
||||
}
|
||||
|
||||
y++;
|
||||
fy -= 256;
|
||||
}
|
||||
|
||||
if (fy)
|
||||
{
|
||||
fx = fx0;
|
||||
x = x0;
|
||||
dx = dx0;
|
||||
|
||||
if (dx)
|
||||
{
|
||||
value += (dx * fy * src[x + src_width * y]) >> 8;
|
||||
x++;
|
||||
fx -= dx;
|
||||
dx = 0;
|
||||
}
|
||||
while (fx >= 256)
|
||||
{
|
||||
value += fy * src[x + src_width * y];
|
||||
x++;
|
||||
fx -= 256;
|
||||
}
|
||||
if (fx)
|
||||
{
|
||||
value += (fx * fy * src[x + src_width * y]) >> 8;
|
||||
dx = 256 - fx;
|
||||
}
|
||||
|
||||
dy = 256 - fy;
|
||||
}
|
||||
|
||||
value /= area;
|
||||
*dest++ = MIN (value, 255);
|
||||
|
||||
x0 = x;
|
||||
dx0 = dx;
|
||||
}
|
||||
|
||||
x0 = 0;
|
||||
dx0 = 0;
|
||||
y0 = y;
|
||||
dy0 = dy;
|
||||
}
|
||||
|
||||
return scale_brush;
|
||||
*width = (gint) (ceil (MAX (MAX (x1, x2), MAX (x3, x4))) - *x);
|
||||
*height = (gint) (ceil (MAX (MAX (y1, y2), MAX (y3, y4))) - *y);
|
||||
}
|
||||
|
||||
|
||||
#define ADD_RGB(dest, factor, src) \
|
||||
dest[0] += factor * src[0]; \
|
||||
dest[1] += factor * src[1]; \
|
||||
dest[2] += factor * src[2];
|
||||
|
||||
static TempBuf *
|
||||
gimp_brush_scale_pixmap_down (TempBuf *pixmap,
|
||||
gint dest_width,
|
||||
gint dest_height)
|
||||
{
|
||||
TempBuf *scale_brush;
|
||||
gint src_width;
|
||||
gint src_height;
|
||||
gint value[3];
|
||||
gint factor;
|
||||
gint area;
|
||||
gint i, j;
|
||||
gint x, x0, y, y0;
|
||||
gint dx, dx0, dy, dy0;
|
||||
gint fx, fx0, fy, fy0;
|
||||
guchar *src, *src_ptr, *dest;
|
||||
|
||||
g_return_val_if_fail (pixmap != NULL && pixmap->bytes == 3 &&
|
||||
dest_width != 0 && dest_height != 0, NULL);
|
||||
|
||||
src_width = pixmap->width;
|
||||
src_height = pixmap->height;
|
||||
|
||||
scale_brush = temp_buf_new (dest_width, dest_height, 3, 0, 0, NULL);
|
||||
g_return_val_if_fail (scale_brush != NULL, NULL);
|
||||
|
||||
/* get the data */
|
||||
dest = temp_buf_get_data (scale_brush);
|
||||
src = temp_buf_get_data (pixmap);
|
||||
|
||||
fx = fx0 = (src_width << 8) / dest_width;
|
||||
fy = fy0 = (src_height << 8) / dest_height;
|
||||
area = (fx0 * fy0) >> 8;
|
||||
|
||||
x = x0 = 0;
|
||||
y = y0 = 0;
|
||||
dx = dx0 = 0;
|
||||
dy = dy0 = 0;
|
||||
|
||||
for (i = 0; i < dest_height; i++)
|
||||
{
|
||||
for (j=0; j<dest_width; j++)
|
||||
{
|
||||
value[0] = 0;
|
||||
value[1] = 0;
|
||||
value[2] = 0;
|
||||
|
||||
fy = fy0;
|
||||
y = y0;
|
||||
dy = dy0;
|
||||
|
||||
if (dy)
|
||||
{
|
||||
fx = fx0;
|
||||
x = x0;
|
||||
dx = dx0;
|
||||
|
||||
if (dx)
|
||||
{
|
||||
factor = (dx * dy) >> 8;
|
||||
src_ptr = src + 3 * (x + y * src_width);
|
||||
ADD_RGB (value, factor, src_ptr);
|
||||
x++;
|
||||
fx -= dx;
|
||||
dx = 0;
|
||||
}
|
||||
while (fx >= 256)
|
||||
{
|
||||
factor = dy;
|
||||
src_ptr = src + 3 * (x + y * src_width);
|
||||
ADD_RGB (value, factor, src_ptr);
|
||||
x++;
|
||||
fx -= 256;
|
||||
}
|
||||
if (fx)
|
||||
{
|
||||
factor = (fx * dy) >> 8;
|
||||
src_ptr = src + 3 * (x + y * src_width);
|
||||
ADD_RGB (value, factor, src_ptr);
|
||||
dx = 256 - fx;
|
||||
}
|
||||
|
||||
y++;
|
||||
fy -= dy;
|
||||
dy = 0;
|
||||
}
|
||||
|
||||
while (fy >= 256)
|
||||
{
|
||||
fx = fx0;
|
||||
x = x0;
|
||||
dx = dx0;
|
||||
|
||||
if (dx)
|
||||
{
|
||||
factor = dx;
|
||||
src_ptr = src + 3 * (x + y * src_width);
|
||||
ADD_RGB (value, factor, src_ptr);
|
||||
x++;
|
||||
fx -= dx;
|
||||
dx = 0;
|
||||
}
|
||||
while (fx >= 256)
|
||||
{
|
||||
factor = 256;
|
||||
src_ptr = src + 3 * (x + y * src_width);
|
||||
ADD_RGB (value, factor, src_ptr);
|
||||
x++;
|
||||
fx -= 256;
|
||||
}
|
||||
if (fx)
|
||||
{
|
||||
factor = fx;
|
||||
src_ptr = src + 3 * (x + y * src_width);
|
||||
ADD_RGB (value, factor, src_ptr);
|
||||
dx = 256 - fx;
|
||||
}
|
||||
|
||||
y++;
|
||||
fy -= 256;
|
||||
}
|
||||
|
||||
if (fy)
|
||||
{
|
||||
fx = fx0;
|
||||
x = x0;
|
||||
dx = dx0;
|
||||
|
||||
if (dx)
|
||||
{
|
||||
factor = (dx * fy) >> 8;
|
||||
src_ptr = src + 3 * (x + y * src_width);
|
||||
ADD_RGB (value, factor, src_ptr);
|
||||
x++;
|
||||
fx -= dx;
|
||||
dx = 0;
|
||||
}
|
||||
while (fx >= 256)
|
||||
{
|
||||
factor = fy;
|
||||
src_ptr = src + 3 * (x + y * src_width);
|
||||
ADD_RGB (value, factor, src_ptr);
|
||||
x++;
|
||||
fx -= 256;
|
||||
}
|
||||
if (fx)
|
||||
{
|
||||
factor = (fx * fy) >> 8;
|
||||
src_ptr = src + 3 * (x + y * src_width);
|
||||
ADD_RGB (value, factor, src_ptr);
|
||||
dx = 256 - fx;
|
||||
}
|
||||
|
||||
dy = 256 - fy;
|
||||
}
|
||||
|
||||
value[0] /= area;
|
||||
value[1] /= area;
|
||||
value[2] /= area;
|
||||
|
||||
*dest++ = MIN (value[0], 255);
|
||||
*dest++ = MIN (value[1], 255);
|
||||
*dest++ = MIN (value[2], 255);
|
||||
|
||||
x0 = x;
|
||||
dx0 = dx;
|
||||
}
|
||||
|
||||
x0 = 0;
|
||||
dx0 = 0;
|
||||
y0 = y;
|
||||
dy0 = dy;
|
||||
}
|
||||
|
||||
return scale_brush;
|
||||
}
|
||||
|
||||
#undef ADD_RGB
|
||||
|
|
|
@ -25,12 +25,15 @@
|
|||
|
||||
void gimp_brush_real_transform_size (GimpBrush *brush,
|
||||
gdouble scale,
|
||||
gdouble angle,
|
||||
gint *scaled_width,
|
||||
gint *scaled_height);
|
||||
TempBuf * gimp_brush_real_transform_mask (GimpBrush *brush,
|
||||
gdouble scale);
|
||||
gdouble scale,
|
||||
gdouble angle);
|
||||
TempBuf * gimp_brush_real_transform_pixmap (GimpBrush *brush,
|
||||
gdouble scale);
|
||||
gdouble scale,
|
||||
gdouble angle);
|
||||
|
||||
|
||||
#endif /* __GIMP_BRUSH_SCALE_H__ */
|
||||
|
|
|
@ -276,13 +276,13 @@ gimp_brush_get_new_preview (GimpViewable *viewable,
|
|||
|
||||
if (scale != 1.0)
|
||||
{
|
||||
mask_buf = gimp_brush_transform_mask (brush, scale);
|
||||
mask_buf = gimp_brush_transform_mask (brush, scale, 0.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);
|
||||
pixmap_buf = gimp_brush_transform_pixmap (brush, scale, 0.0);
|
||||
|
||||
mask_width = mask_buf->width;
|
||||
mask_height = mask_buf->height;
|
||||
|
@ -458,6 +458,7 @@ gimp_brush_want_null_motion (GimpBrush *brush,
|
|||
void
|
||||
gimp_brush_transform_size (GimpBrush *brush,
|
||||
gdouble scale,
|
||||
gdouble angle,
|
||||
gint *width,
|
||||
gint *height)
|
||||
{
|
||||
|
@ -466,7 +467,7 @@ gimp_brush_transform_size (GimpBrush *brush,
|
|||
g_return_if_fail (width != NULL);
|
||||
g_return_if_fail (height != NULL);
|
||||
|
||||
if (scale == 1.0)
|
||||
if ((scale == 1.0) && ((angle == 0.0) || (angle == 0.5) || (angle == 1.0)))
|
||||
{
|
||||
*width = brush->mask->width;
|
||||
*height = brush->mask->height;
|
||||
|
@ -474,34 +475,36 @@ gimp_brush_transform_size (GimpBrush *brush,
|
|||
return;
|
||||
}
|
||||
|
||||
GIMP_BRUSH_GET_CLASS (brush)->transform_size (brush, scale, width, height);
|
||||
GIMP_BRUSH_GET_CLASS (brush)->transform_size (brush, scale, angle, width, height);
|
||||
}
|
||||
|
||||
TempBuf *
|
||||
gimp_brush_transform_mask (GimpBrush *brush,
|
||||
gdouble scale)
|
||||
gdouble scale,
|
||||
gdouble angle)
|
||||
{
|
||||
g_return_val_if_fail (GIMP_IS_BRUSH (brush), NULL);
|
||||
g_return_val_if_fail (scale > 0.0, NULL);
|
||||
|
||||
if (scale == 1.0)
|
||||
if ((scale == 1.0) && (angle == 0.0))
|
||||
return temp_buf_copy (brush->mask, NULL);
|
||||
|
||||
return GIMP_BRUSH_GET_CLASS (brush)->transform_mask (brush, scale);
|
||||
return GIMP_BRUSH_GET_CLASS (brush)->transform_mask (brush, scale, angle);
|
||||
}
|
||||
|
||||
TempBuf *
|
||||
gimp_brush_transform_pixmap (GimpBrush *brush,
|
||||
gdouble scale)
|
||||
gdouble scale,
|
||||
gdouble angle)
|
||||
{
|
||||
g_return_val_if_fail (GIMP_IS_BRUSH (brush), NULL);
|
||||
g_return_val_if_fail (brush->pixmap != NULL, NULL);
|
||||
g_return_val_if_fail (scale > 0.0, NULL);
|
||||
|
||||
if (scale == 1.0)
|
||||
if ((scale == 1.0) && (angle == 0.0))
|
||||
return temp_buf_copy (brush->pixmap, NULL);
|
||||
|
||||
return GIMP_BRUSH_GET_CLASS (brush)->transform_pixmap (brush, scale);
|
||||
return GIMP_BRUSH_GET_CLASS (brush)->transform_pixmap (brush, scale, angle);
|
||||
}
|
||||
|
||||
TempBuf *
|
||||
|
|
|
@ -58,12 +58,15 @@ struct _GimpBrushClass
|
|||
GimpCoords *cur_coords);
|
||||
void (* transform_size) (GimpBrush *brush,
|
||||
gdouble scale,
|
||||
gdouble angle,
|
||||
gint *width,
|
||||
gint *height);
|
||||
TempBuf * (* transform_mask) (GimpBrush *brush,
|
||||
gdouble scale);
|
||||
gdouble scale,
|
||||
gdouble angle);
|
||||
TempBuf * (* transform_pixmap) (GimpBrush *brush,
|
||||
gdouble scale);
|
||||
gdouble scale,
|
||||
gdouble angle);
|
||||
|
||||
/* signals */
|
||||
void (* spacing_changed) (GimpBrush *brush);
|
||||
|
@ -85,12 +88,15 @@ gboolean gimp_brush_want_null_motion (GimpBrush *brush,
|
|||
/* Gets width and height of a transformed mask of the brush, for provided parameters. */
|
||||
void gimp_brush_transform_size (GimpBrush *brush,
|
||||
gdouble scale,
|
||||
gdouble angle,
|
||||
gint *width,
|
||||
gint *height);
|
||||
TempBuf * gimp_brush_transform_mask (GimpBrush *brush,
|
||||
gdouble scale);
|
||||
gdouble scale,
|
||||
gdouble angle);
|
||||
TempBuf * gimp_brush_transform_pixmap (GimpBrush *brush,
|
||||
gdouble scale);
|
||||
gdouble scale,
|
||||
gdouble angle);
|
||||
|
||||
TempBuf * gimp_brush_get_mask (const GimpBrush *brush);
|
||||
TempBuf * gimp_brush_get_pixmap (const GimpBrush *brush);
|
||||
|
|
|
@ -65,10 +65,12 @@ static GimpData * gimp_brush_generated_duplicate (GimpData *data);
|
|||
|
||||
static void gimp_brush_generated_transform_size(GimpBrush *gbrush,
|
||||
gdouble scale,
|
||||
gdouble angle,
|
||||
gint *width,
|
||||
gint *height);
|
||||
static TempBuf * gimp_brush_generated_transform_mask(GimpBrush *gbrush,
|
||||
gdouble scale);
|
||||
gdouble scale,
|
||||
gdouble angle);
|
||||
|
||||
static TempBuf * gimp_brush_generated_calc (GimpBrushGenerated *brush,
|
||||
GimpBrushGeneratedShape shape,
|
||||
|
@ -279,6 +281,7 @@ gimp_brush_generated_duplicate (GimpData *data)
|
|||
static void
|
||||
gimp_brush_generated_transform_size (GimpBrush *gbrush,
|
||||
gdouble scale,
|
||||
gdouble angle,
|
||||
gint *width,
|
||||
gint *height)
|
||||
{
|
||||
|
@ -292,7 +295,7 @@ gimp_brush_generated_transform_size (GimpBrush *gbrush,
|
|||
brush->spikes,
|
||||
brush->hardness,
|
||||
brush->aspect_ratio,
|
||||
brush->angle,
|
||||
(brush->angle + 360 * angle),
|
||||
&half_width, &half_height,
|
||||
NULL, NULL, NULL, NULL);
|
||||
|
||||
|
@ -302,7 +305,8 @@ gimp_brush_generated_transform_size (GimpBrush *gbrush,
|
|||
|
||||
static TempBuf *
|
||||
gimp_brush_generated_transform_mask (GimpBrush *gbrush,
|
||||
gdouble scale)
|
||||
gdouble scale,
|
||||
gdouble angle)
|
||||
{
|
||||
GimpBrushGenerated *brush = GIMP_BRUSH_GENERATED (gbrush);
|
||||
|
||||
|
@ -312,7 +316,7 @@ gimp_brush_generated_transform_mask (GimpBrush *gbrush,
|
|||
brush->spikes,
|
||||
brush->hardness,
|
||||
brush->aspect_ratio,
|
||||
brush->angle,
|
||||
(brush->angle + 360 * angle),
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
|
|
|
@ -154,9 +154,9 @@ gimp_brush_core_class_init (GimpBrushCoreClass *klass)
|
|||
paint_core_class->interpolate = gimp_brush_core_interpolate;
|
||||
paint_core_class->get_paint_area = gimp_brush_core_get_paint_area;
|
||||
|
||||
klass->handles_changing_brush = FALSE;
|
||||
klass->handles_scaling_brush = TRUE;
|
||||
klass->set_brush = gimp_brush_core_real_set_brush;
|
||||
klass->handles_changing_brush = FALSE;
|
||||
klass->handles_transforming_brush = TRUE;
|
||||
klass->set_brush = gimp_brush_core_real_set_brush;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -168,6 +168,7 @@ gimp_brush_core_init (GimpBrushCore *core)
|
|||
core->brush = NULL;
|
||||
core->spacing = 1.0;
|
||||
core->scale = 1.0;
|
||||
core->angle = 1.0;
|
||||
|
||||
core->pressure_brush = NULL;
|
||||
|
||||
|
@ -363,10 +364,14 @@ gimp_brush_core_start (GimpPaintCore *paint_core,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
core->scale = gimp_paint_options_get_dynamic_size (paint_options,
|
||||
coords,
|
||||
GIMP_BRUSH_CORE_GET_CLASS (core)->handles_scaling_brush);
|
||||
|
||||
if (GIMP_BRUSH_CORE_GET_CLASS (core)->handles_transforming_brush)
|
||||
{
|
||||
core->scale = gimp_paint_options_get_dynamic_size (paint_options,
|
||||
coords,
|
||||
TRUE);
|
||||
core->angle = gimp_paint_options_get_dynamic_angle (paint_options,
|
||||
coords);
|
||||
}
|
||||
core->spacing = (gdouble) gimp_brush_get_spacing (core->main_brush) / 100.0;
|
||||
|
||||
core->brush = core->main_brush;
|
||||
|
@ -696,14 +701,19 @@ gimp_brush_core_get_paint_area (GimpPaintCore *paint_core,
|
|||
gint drawable_width, drawable_height;
|
||||
gint brush_width, brush_height;
|
||||
|
||||
if (GIMP_BRUSH_CORE_GET_CLASS (core)->handles_scaling_brush)
|
||||
core->scale = gimp_paint_options_get_dynamic_size (paint_options,
|
||||
&paint_core->cur_coords,
|
||||
TRUE);
|
||||
if (GIMP_BRUSH_CORE_GET_CLASS (core)->handles_transforming_brush)
|
||||
{
|
||||
core->scale = gimp_paint_options_get_dynamic_size (paint_options,
|
||||
&paint_core->cur_coords,
|
||||
TRUE);
|
||||
|
||||
core->angle = gimp_paint_options_get_dynamic_angle (paint_options,
|
||||
&paint_core->cur_coords);
|
||||
}
|
||||
|
||||
core->scale = gimp_brush_core_clamp_brush_scale (core, core->scale);
|
||||
|
||||
gimp_brush_transform_size (core->brush, core->scale, &brush_width, &brush_height);
|
||||
gimp_brush_transform_size (core->brush, core->scale, core->angle, &brush_width, &brush_height);
|
||||
|
||||
/* adjust the x and y coordinates to the upper left corner of the brush */
|
||||
x = (gint) floor (paint_core->cur_coords.x) - (brush_width / 2);
|
||||
|
@ -783,18 +793,20 @@ gimp_brush_core_create_bound_segs (GimpBrushCore *core,
|
|||
{
|
||||
TempBuf *mask = NULL;
|
||||
gdouble scale;
|
||||
gdouble angle;
|
||||
|
||||
g_return_if_fail (GIMP_IS_BRUSH_CORE (core));
|
||||
g_return_if_fail (core->main_brush != NULL);
|
||||
g_return_if_fail (core->brush_bound_segs == NULL);
|
||||
|
||||
scale = paint_options->brush_scale;
|
||||
angle = paint_options->brush_angle;
|
||||
|
||||
if (scale > 0.0)
|
||||
{
|
||||
scale = gimp_brush_core_clamp_brush_scale (core, scale);
|
||||
|
||||
mask = gimp_brush_transform_mask (core->main_brush, scale);
|
||||
mask = gimp_brush_transform_mask (core->main_brush, scale, angle);
|
||||
}
|
||||
|
||||
if (mask)
|
||||
|
@ -1296,17 +1308,18 @@ 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)
|
||||
if ((core->scale == 1.0) && (core->angle == 0.0))
|
||||
return brush->mask;
|
||||
|
||||
gimp_brush_transform_size (brush, core->scale, &width, &height);
|
||||
gimp_brush_transform_size (brush, core->scale, core->angle, &width, &height);
|
||||
|
||||
if (! core->cache_invalid &&
|
||||
if (! core->cache_invalid &&
|
||||
core->transform_brush &&
|
||||
brush->mask == core->last_transform_brush &&
|
||||
width == core->last_transform_width &&
|
||||
height == core->last_transform_height &&
|
||||
core->scale == core->last_scale)
|
||||
core->scale == core->last_scale &&
|
||||
core->angle == core->last_angle)
|
||||
{
|
||||
return core->transform_brush;
|
||||
}
|
||||
|
@ -1315,11 +1328,13 @@ gimp_brush_core_transform_mask (GimpBrushCore *core,
|
|||
core->last_transform_width = width;
|
||||
core->last_transform_height = height;
|
||||
core->last_scale = core->scale;
|
||||
core->last_angle = core->angle;
|
||||
|
||||
|
||||
if (core->transform_brush)
|
||||
temp_buf_free (core->transform_brush);
|
||||
|
||||
core->transform_brush = gimp_brush_transform_mask (brush, core->scale);
|
||||
core->transform_brush = gimp_brush_transform_mask (brush, core->scale, core->angle);
|
||||
|
||||
core->cache_invalid = TRUE;
|
||||
core->solid_cache_invalid = TRUE;
|
||||
|
@ -1337,16 +1352,18 @@ gimp_brush_core_transform_pixmap (GimpBrushCore *core,
|
|||
if (core->scale <= 0.0)
|
||||
return NULL;
|
||||
|
||||
if (core->scale == 1.0)
|
||||
if ((core->scale == 1.0) && (core->angle == 0.0))
|
||||
return brush->pixmap;
|
||||
|
||||
gimp_brush_transform_size (brush, core->scale, &width, &height);
|
||||
gimp_brush_transform_size (brush, core->scale, core->angle, &width, &height);
|
||||
|
||||
|
||||
if (! core->cache_invalid &&
|
||||
core->transform_pixmap &&
|
||||
brush->pixmap == core->last_transform_pixmap &&
|
||||
width == core->last_transform_pixmap_width &&
|
||||
height == core->last_transform_pixmap_height)
|
||||
height == core->last_transform_pixmap_height&&
|
||||
core->angle == core->last_angle)
|
||||
{
|
||||
return core->transform_pixmap;
|
||||
}
|
||||
|
@ -1354,11 +1371,13 @@ 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;
|
||||
|
||||
if (core->transform_pixmap)
|
||||
temp_buf_free (core->transform_pixmap);
|
||||
|
||||
core->transform_pixmap = gimp_brush_transform_pixmap (brush, core->scale);
|
||||
|
||||
core->transform_pixmap = gimp_brush_transform_pixmap (brush, core->scale, core->angle);
|
||||
|
||||
core->cache_invalid = TRUE;
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@ struct _GimpBrushCore
|
|||
GimpBrush *brush;
|
||||
gdouble spacing;
|
||||
gdouble scale;
|
||||
gdouble angle;
|
||||
|
||||
/* brush buffers */
|
||||
TempBuf *pressure_brush;
|
||||
|
@ -58,6 +59,7 @@ struct _GimpBrushCore
|
|||
gint last_transform_width;
|
||||
gint last_transform_height;
|
||||
gdouble last_scale;
|
||||
gdouble last_angle;
|
||||
|
||||
TempBuf *transform_pixmap;
|
||||
TempBuf *last_transform_pixmap;
|
||||
|
@ -90,7 +92,8 @@ struct _GimpBrushCoreClass
|
|||
gboolean handles_changing_brush;
|
||||
|
||||
/* Set for tools that don't mind if the brush scales while painting */
|
||||
gboolean handles_scaling_brush;
|
||||
|
||||
gboolean handles_transforming_brush;
|
||||
|
||||
void (* set_brush) (GimpBrushCore *core,
|
||||
GimpBrush *brush);
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
|
||||
|
||||
#define DEFAULT_BRUSH_SCALE 1.0
|
||||
#define DEFAULT_BRUSH_ANGLE 0.0
|
||||
|
||||
#define DEFAULT_APPLICATION_MODE GIMP_PAINT_CONSTANT
|
||||
#define DEFAULT_HARD FALSE
|
||||
|
||||
|
@ -45,6 +47,7 @@
|
|||
#define DEFAULT_PRESSURE_SIZE FALSE
|
||||
#define DEFAULT_PRESSURE_INVERSE_SIZE FALSE
|
||||
#define DEFAULT_PRESSURE_COLOR FALSE
|
||||
#define DEFAULT_PRESSURE_ANGLE FALSE
|
||||
#define DEFAULT_PRESSURE_PRESCALE 1.0
|
||||
|
||||
#define DEFAULT_VELOCITY_OPACITY FALSE
|
||||
|
@ -53,6 +56,7 @@
|
|||
#define DEFAULT_VELOCITY_SIZE FALSE
|
||||
#define DEFAULT_VELOCITY_INVERSE_SIZE FALSE
|
||||
#define DEFAULT_VELOCITY_COLOR FALSE
|
||||
#define DEFAULT_VELOCITY_ANGLE FALSE
|
||||
#define DEFAULT_VELOCITY_PRESCALE 1.0
|
||||
|
||||
#define DEFAULT_RANDOM_OPACITY FALSE
|
||||
|
@ -61,6 +65,7 @@
|
|||
#define DEFAULT_RANDOM_SIZE FALSE
|
||||
#define DEFAULT_RANDOM_INVERSE_SIZE FALSE
|
||||
#define DEFAULT_RANDOM_COLOR FALSE
|
||||
#define DEFAULT_RANDOM_ANGLE FALSE
|
||||
#define DEFAULT_RANDOM_PRESCALE 1.0
|
||||
|
||||
#define DEFAULT_USE_FADE FALSE
|
||||
|
@ -82,7 +87,10 @@ enum
|
|||
PROP_0,
|
||||
|
||||
PROP_PAINT_INFO,
|
||||
|
||||
PROP_BRUSH_SCALE,
|
||||
PROP_BRUSH_ANGLE,
|
||||
|
||||
PROP_APPLICATION_MODE,
|
||||
PROP_HARD,
|
||||
|
||||
|
@ -94,6 +102,7 @@ enum
|
|||
PROP_PRESSURE_SIZE,
|
||||
PROP_PRESSURE_INVERSE_SIZE,
|
||||
PROP_PRESSURE_COLOR,
|
||||
PROP_PRESSURE_ANGLE,
|
||||
PROP_PRESSURE_PRESCALE,
|
||||
|
||||
PROP_VELOCITY_OPACITY,
|
||||
|
@ -102,6 +111,7 @@ enum
|
|||
PROP_VELOCITY_SIZE,
|
||||
PROP_VELOCITY_INVERSE_SIZE,
|
||||
PROP_VELOCITY_COLOR,
|
||||
PROP_VELOCITY_ANGLE,
|
||||
PROP_VELOCITY_PRESCALE,
|
||||
|
||||
PROP_RANDOM_OPACITY,
|
||||
|
@ -110,6 +120,7 @@ enum
|
|||
PROP_RANDOM_SIZE,
|
||||
PROP_RANDOM_INVERSE_SIZE,
|
||||
PROP_RANDOM_COLOR,
|
||||
PROP_RANDOM_ANGLE,
|
||||
PROP_RANDOM_PRESCALE,
|
||||
|
||||
PROP_USE_FADE,
|
||||
|
@ -180,6 +191,11 @@ gimp_paint_options_class_init (GimpPaintOptionsClass *klass)
|
|||
"brush-scale", NULL,
|
||||
0.01, 10.0, DEFAULT_BRUSH_SCALE,
|
||||
GIMP_PARAM_STATIC_STRINGS);
|
||||
GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_BRUSH_ANGLE,
|
||||
"brush-angle", NULL,
|
||||
-180.0, 180.0, DEFAULT_BRUSH_ANGLE,
|
||||
GIMP_PARAM_STATIC_STRINGS);
|
||||
|
||||
GIMP_CONFIG_INSTALL_PROP_ENUM (object_class, PROP_APPLICATION_MODE,
|
||||
"application-mode", NULL,
|
||||
GIMP_TYPE_PAINT_APPLICATION_MODE,
|
||||
|
@ -215,6 +231,10 @@ gimp_paint_options_class_init (GimpPaintOptionsClass *klass)
|
|||
"pressure-color", NULL,
|
||||
DEFAULT_PRESSURE_COLOR,
|
||||
GIMP_PARAM_STATIC_STRINGS);
|
||||
GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_PRESSURE_ANGLE,
|
||||
"pressure-angle", NULL,
|
||||
DEFAULT_PRESSURE_COLOR,
|
||||
GIMP_PARAM_STATIC_STRINGS);
|
||||
GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_PRESSURE_INVERSE_SIZE,
|
||||
"pressure-inverse-size", NULL,
|
||||
DEFAULT_PRESSURE_INVERSE_SIZE,
|
||||
|
@ -244,6 +264,10 @@ gimp_paint_options_class_init (GimpPaintOptionsClass *klass)
|
|||
"velocity-color", NULL,
|
||||
DEFAULT_VELOCITY_COLOR,
|
||||
GIMP_PARAM_STATIC_STRINGS);
|
||||
GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_VELOCITY_ANGLE,
|
||||
"velocity-angle", NULL,
|
||||
DEFAULT_VELOCITY_COLOR,
|
||||
GIMP_PARAM_STATIC_STRINGS);
|
||||
GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_VELOCITY_INVERSE_SIZE,
|
||||
"velocity-inverse-size", NULL,
|
||||
DEFAULT_VELOCITY_INVERSE_SIZE,
|
||||
|
@ -273,6 +297,10 @@ gimp_paint_options_class_init (GimpPaintOptionsClass *klass)
|
|||
"random-color", NULL,
|
||||
DEFAULT_RANDOM_COLOR,
|
||||
GIMP_PARAM_STATIC_STRINGS);
|
||||
GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_RANDOM_ANGLE,
|
||||
"random-angle", NULL,
|
||||
DEFAULT_RANDOM_COLOR,
|
||||
GIMP_PARAM_STATIC_STRINGS);
|
||||
GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_RANDOM_INVERSE_SIZE,
|
||||
"random-inverse-size", NULL,
|
||||
DEFAULT_RANDOM_INVERSE_SIZE,
|
||||
|
@ -418,6 +446,10 @@ gimp_paint_options_set_property (GObject *object,
|
|||
options->brush_scale = g_value_get_double (value);
|
||||
break;
|
||||
|
||||
case PROP_BRUSH_ANGLE:
|
||||
options->brush_angle = g_value_get_double (value) / 360.0;
|
||||
break;
|
||||
|
||||
case PROP_APPLICATION_MODE:
|
||||
options->application_mode = g_value_get_enum (value);
|
||||
break;
|
||||
|
@ -454,6 +486,10 @@ gimp_paint_options_set_property (GObject *object,
|
|||
pressure_options->color = g_value_get_boolean (value);
|
||||
break;
|
||||
|
||||
case PROP_PRESSURE_ANGLE:
|
||||
pressure_options->angle = g_value_get_boolean (value);
|
||||
break;
|
||||
|
||||
case PROP_PRESSURE_PRESCALE:
|
||||
pressure_options->prescale = g_value_get_double (value);
|
||||
break;
|
||||
|
@ -482,6 +518,10 @@ gimp_paint_options_set_property (GObject *object,
|
|||
velocity_options->color = g_value_get_boolean (value);
|
||||
break;
|
||||
|
||||
case PROP_VELOCITY_ANGLE:
|
||||
velocity_options->angle = g_value_get_boolean (value);
|
||||
break;
|
||||
|
||||
case PROP_VELOCITY_PRESCALE:
|
||||
velocity_options->prescale = g_value_get_double (value);
|
||||
break;
|
||||
|
@ -510,6 +550,10 @@ gimp_paint_options_set_property (GObject *object,
|
|||
random_options->color = g_value_get_boolean (value);
|
||||
break;
|
||||
|
||||
case PROP_RANDOM_ANGLE:
|
||||
random_options->angle = g_value_get_boolean (value);
|
||||
break;
|
||||
|
||||
case PROP_RANDOM_PRESCALE:
|
||||
random_options->prescale = g_value_get_double (value);
|
||||
break;
|
||||
|
@ -608,6 +652,10 @@ gimp_paint_options_get_property (GObject *object,
|
|||
g_value_set_double (value, options->brush_scale);
|
||||
break;
|
||||
|
||||
case PROP_BRUSH_ANGLE:
|
||||
g_value_set_double (value, options->brush_angle * 360.0);
|
||||
break;
|
||||
|
||||
case PROP_APPLICATION_MODE:
|
||||
g_value_set_enum (value, options->application_mode);
|
||||
break;
|
||||
|
@ -644,6 +692,10 @@ gimp_paint_options_get_property (GObject *object,
|
|||
g_value_set_boolean (value, pressure_options->color);
|
||||
break;
|
||||
|
||||
case PROP_PRESSURE_ANGLE:
|
||||
g_value_set_boolean (value, pressure_options->angle);
|
||||
break;
|
||||
|
||||
case PROP_PRESSURE_PRESCALE:
|
||||
g_value_set_double (value, pressure_options->prescale);
|
||||
break;
|
||||
|
@ -672,6 +724,10 @@ gimp_paint_options_get_property (GObject *object,
|
|||
g_value_set_boolean (value, velocity_options->color);
|
||||
break;
|
||||
|
||||
case PROP_VELOCITY_ANGLE:
|
||||
g_value_set_boolean (value, velocity_options->angle);
|
||||
break;
|
||||
|
||||
case PROP_VELOCITY_PRESCALE:
|
||||
g_value_set_double (value, velocity_options->prescale);
|
||||
break;
|
||||
|
@ -700,6 +756,10 @@ gimp_paint_options_get_property (GObject *object,
|
|||
g_value_set_boolean (value, random_options->color);
|
||||
break;
|
||||
|
||||
case PROP_RANDOM_ANGLE:
|
||||
g_value_set_boolean (value, random_options->angle);
|
||||
break;
|
||||
|
||||
case PROP_RANDOM_PRESCALE:
|
||||
g_value_set_double (value, random_options->prescale);
|
||||
break;
|
||||
|
@ -1244,3 +1304,40 @@ gimp_paint_options_get_dynamic_hardness (GimpPaintOptions *paint_options,
|
|||
|
||||
return hardness;
|
||||
}
|
||||
|
||||
gdouble
|
||||
gimp_paint_options_get_dynamic_angle (GimpPaintOptions *paint_options,
|
||||
const GimpCoords *coords)
|
||||
{
|
||||
gdouble angle = 1.0;
|
||||
|
||||
g_return_val_if_fail (GIMP_IS_PAINT_OPTIONS (paint_options), 1.0);
|
||||
g_return_val_if_fail (coords != NULL, 1.0);
|
||||
|
||||
if (paint_options->pressure_options->angle ||
|
||||
paint_options->velocity_options->angle ||
|
||||
paint_options->random_options->angle)
|
||||
{
|
||||
gdouble pressure = -1.0;
|
||||
gdouble velocity = -1.0;
|
||||
gdouble random = -1.0;
|
||||
|
||||
if (paint_options->pressure_options->angle)
|
||||
pressure = GIMP_PAINT_PRESSURE_SCALE * coords->pressure;
|
||||
|
||||
if (paint_options->velocity_options->angle)
|
||||
velocity = GIMP_PAINT_VELOCITY_SCALE * (1 - coords->velocity);
|
||||
|
||||
if (paint_options->random_options->angle)
|
||||
random = g_random_double_range (0.0, 1.0);
|
||||
|
||||
angle = gimp_paint_options_get_dynamics_mix (pressure,
|
||||
paint_options->pressure_options->prescale,
|
||||
velocity,
|
||||
paint_options->velocity_options->prescale,
|
||||
random,
|
||||
paint_options->random_options->prescale);
|
||||
}
|
||||
|
||||
return angle + paint_options->brush_angle;
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ struct _GimpDynamicOptions
|
|||
gboolean size;
|
||||
gboolean inverse_size;
|
||||
gboolean color;
|
||||
gboolean angle;
|
||||
gdouble prescale;
|
||||
};
|
||||
|
||||
|
@ -87,6 +88,7 @@ struct _GimpPaintOptions
|
|||
GimpPaintInfo *paint_info;
|
||||
|
||||
gdouble brush_scale;
|
||||
gdouble brush_angle;
|
||||
|
||||
GimpPaintApplicationMode application_mode;
|
||||
GimpPaintApplicationMode application_mode_save;
|
||||
|
@ -150,6 +152,9 @@ gdouble gimp_paint_options_get_dynamic_rate (GimpPaintOptions *paint_options,
|
|||
gdouble gimp_paint_options_get_dynamic_color (GimpPaintOptions *paint_options,
|
||||
const GimpCoords *coords);
|
||||
|
||||
gdouble gimp_paint_options_get_dynamic_angle (GimpPaintOptions *paint_options,
|
||||
const GimpCoords *coords);
|
||||
|
||||
gdouble gimp_paint_options_get_dynamic_hardness(GimpPaintOptions *paint_options,
|
||||
const GimpCoords *coords);
|
||||
|
||||
|
|
|
@ -89,7 +89,7 @@ gimp_smudge_class_init (GimpSmudgeClass *klass)
|
|||
|
||||
paint_core_class->paint = gimp_smudge_paint;
|
||||
|
||||
brush_core_class->handles_scaling_brush = FALSE;
|
||||
brush_core_class->handles_transforming_brush = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -329,7 +329,7 @@ gimp_smudge_brush_coords (GimpPaintCore *paint_core,
|
|||
gint height;
|
||||
|
||||
gimp_brush_transform_size (brush_core->brush, brush_core->scale,
|
||||
&width, &height);
|
||||
brush_core->angle, &width, &height);
|
||||
|
||||
/* Note: these are the brush mask size plus a border of 1 pixel */
|
||||
*x = (gint) paint_core->cur_coords.x - width / 2 - 1;
|
||||
|
|
|
@ -62,21 +62,21 @@ static void gimp_brush_tool_cursor_update (GimpTool *tool,
|
|||
|
||||
static void gimp_brush_tool_draw (GimpDrawTool *draw_tool);
|
||||
|
||||
static void gimp_brush_tool_brush_changed (GimpContext *context,
|
||||
GimpBrush *brush,
|
||||
GimpBrushTool *brush_tool);
|
||||
static void gimp_brush_tool_brush_scaled (GimpPaintOptions *options,
|
||||
GParamSpec *pspec,
|
||||
GimpBrushTool *brush_tool);
|
||||
static void gimp_brush_tool_set_brush (GimpBrushCore *brush_core,
|
||||
GimpBrush *brush,
|
||||
GimpBrushTool *brush_tool);
|
||||
static void gimp_brush_tool_set_brush_after(GimpBrushCore *brush_core,
|
||||
GimpBrush *brush,
|
||||
GimpBrushTool *brush_tool);
|
||||
static void gimp_brush_tool_notify_brush (GimpDisplayConfig *config,
|
||||
GParamSpec *pspec,
|
||||
GimpBrushTool *brush_tool);
|
||||
static void gimp_brush_tool_brush_changed (GimpContext *context,
|
||||
GimpBrush *brush,
|
||||
GimpBrushTool *brush_tool);
|
||||
static void gimp_brush_tool_brush_transformed (GimpPaintOptions *options,
|
||||
GParamSpec *pspec,
|
||||
GimpBrushTool *brush_tool);
|
||||
static void gimp_brush_tool_set_brush (GimpBrushCore *brush_core,
|
||||
GimpBrush *brush,
|
||||
GimpBrushTool *brush_tool);
|
||||
static void gimp_brush_tool_set_brush_after (GimpBrushCore *brush_core,
|
||||
GimpBrush *brush,
|
||||
GimpBrushTool *brush_tool);
|
||||
static void gimp_brush_tool_notify_brush (GimpDisplayConfig *config,
|
||||
GParamSpec *pspec,
|
||||
GimpBrushTool *brush_tool);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (GimpBrushTool, gimp_brush_tool, GIMP_TYPE_PAINT_TOOL)
|
||||
|
@ -155,7 +155,11 @@ gimp_brush_tool_constructor (GType type,
|
|||
G_CALLBACK (gimp_brush_tool_brush_changed),
|
||||
brush_tool, 0);
|
||||
g_signal_connect_object (gimp_tool_get_options (tool), "notify::brush-scale",
|
||||
G_CALLBACK (gimp_brush_tool_brush_scaled),
|
||||
G_CALLBACK (gimp_brush_tool_brush_transformed),
|
||||
brush_tool, 0);
|
||||
|
||||
g_signal_connect_object (gimp_tool_get_options (tool), "notify::brush-angle",
|
||||
G_CALLBACK (gimp_brush_tool_brush_transformed),
|
||||
brush_tool, 0);
|
||||
|
||||
g_signal_connect (paint_tool->core, "set-brush",
|
||||
|
@ -345,9 +349,9 @@ gimp_brush_tool_brush_changed (GimpContext *context,
|
|||
}
|
||||
|
||||
static void
|
||||
gimp_brush_tool_brush_scaled (GimpPaintOptions *options,
|
||||
GParamSpec *pspec,
|
||||
GimpBrushTool *brush_tool)
|
||||
gimp_brush_tool_brush_transformed (GimpPaintOptions *options,
|
||||
GParamSpec *pspec,
|
||||
GimpBrushTool *brush_tool)
|
||||
{
|
||||
GimpPaintTool *paint_tool = GIMP_PAINT_TOOL (brush_tool);
|
||||
GimpBrushCore *brush_core = GIMP_BRUSH_CORE (paint_tool->core);
|
||||
|
|
|
@ -52,6 +52,7 @@ static gboolean tool_has_hardness_dynamics (GType tool_type);
|
|||
static gboolean tool_has_rate_dynamics (GType tool_type);
|
||||
static gboolean tool_has_size_dynamics (GType tool_type);
|
||||
static gboolean tool_has_color_dynamics (GType tool_type);
|
||||
static gboolean tool_has_angle_dynamics (GType tool_type);
|
||||
|
||||
static void pressure_options_gui (GimpPaintOptions *paint_options,
|
||||
GType tool_type,
|
||||
|
@ -128,7 +129,8 @@ gimp_paint_options_gui (GimpToolOptions *tool_options)
|
|||
/* the brush */
|
||||
if (g_type_is_a (tool_type, GIMP_TYPE_BRUSH_TOOL))
|
||||
{
|
||||
GtkObject *adj;
|
||||
GtkObject *adj_scale;
|
||||
GtkObject *adj_angle;
|
||||
|
||||
button = gimp_prop_brush_box_new (NULL, GIMP_CONTEXT (tool_options), 2,
|
||||
"brush-view-type", "brush-view-size");
|
||||
|
@ -136,12 +138,20 @@ gimp_paint_options_gui (GimpToolOptions *tool_options)
|
|||
_("Brush:"), 0.0, 0.5,
|
||||
button, 2, FALSE);
|
||||
|
||||
adj = gimp_prop_scale_entry_new (config, "brush-scale",
|
||||
GTK_TABLE (table), 0, table_row++,
|
||||
_("Scale:"),
|
||||
0.01, 0.1, 2,
|
||||
FALSE, 0.0, 0.0);
|
||||
gimp_scale_entry_set_logarithmic (adj, TRUE);
|
||||
adj_scale = gimp_prop_scale_entry_new (config, "brush-scale",
|
||||
GTK_TABLE (table), 0, table_row++,
|
||||
_("Scale:"),
|
||||
0.01, 0.1, 2,
|
||||
FALSE, 0.0, 0.0);
|
||||
gimp_scale_entry_set_logarithmic (adj_scale, TRUE);
|
||||
|
||||
adj_angle = gimp_prop_scale_entry_new (config, "brush-angle",
|
||||
GTK_TABLE (table), 0, table_row++,
|
||||
_("Angle:"),
|
||||
1.0, 5.0, 2,
|
||||
FALSE, 0.0, 0.0);
|
||||
gimp_scale_entry_set_logarithmic (adj_angle, FALSE);
|
||||
|
||||
}
|
||||
|
||||
if (tool_has_opacity_dynamics (tool_type))
|
||||
|
@ -168,6 +178,12 @@ gimp_paint_options_gui (GimpToolOptions *tool_options)
|
|||
n_dynamics++;
|
||||
}
|
||||
|
||||
if (tool_has_angle_dynamics (tool_type))
|
||||
{
|
||||
dynamics_labels[n_dynamics] = gtk_label_new (_("Angle"));
|
||||
n_dynamics++;
|
||||
}
|
||||
|
||||
if (tool_has_color_dynamics (tool_type))
|
||||
{
|
||||
dynamics_labels[n_dynamics] = gtk_label_new (_("Color"));
|
||||
|
@ -339,6 +355,12 @@ tool_has_size_dynamics (GType tool_type)
|
|||
tool_type == GIMP_TYPE_ERASER_TOOL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
tool_has_angle_dynamics (GType tool_type)
|
||||
{
|
||||
return (g_type_is_a (tool_type, GIMP_TYPE_PAINTBRUSH_TOOL));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
tool_has_color_dynamics (GType tool_type)
|
||||
{
|
||||
|
@ -439,6 +461,16 @@ pressure_options_gui (GimpPaintOptions *paint_options,
|
|||
column++;
|
||||
}
|
||||
|
||||
if (tool_has_angle_dynamics (tool_type))
|
||||
{
|
||||
button = dynamics_check_button_new (config, "pressure-angle",
|
||||
table, column, row);
|
||||
g_signal_connect (button, "size-allocate",
|
||||
G_CALLBACK (dynamics_check_button_size_allocate),
|
||||
labels[column - 1]);
|
||||
column++;
|
||||
}
|
||||
|
||||
if (tool_has_color_dynamics (tool_type))
|
||||
{
|
||||
button = dynamics_check_button_new (config, "pressure-color",
|
||||
|
@ -489,6 +521,12 @@ velocity_options_gui (GimpPaintOptions *paint_options,
|
|||
table, column++, row);
|
||||
}
|
||||
|
||||
if (tool_has_angle_dynamics (tool_type))
|
||||
{
|
||||
dynamics_check_button_new (config, "velocity-angle",
|
||||
table, column++, row);
|
||||
}
|
||||
|
||||
if (tool_has_color_dynamics (tool_type))
|
||||
{
|
||||
dynamics_check_button_new (config, "velocity-color",
|
||||
|
@ -535,6 +573,12 @@ random_options_gui (GimpPaintOptions *paint_options,
|
|||
table, column++, row);
|
||||
}
|
||||
|
||||
if (tool_has_angle_dynamics (tool_type))
|
||||
{
|
||||
dynamics_check_button_new (config, "random-angle",
|
||||
table, column++, row);
|
||||
}
|
||||
|
||||
if (tool_has_color_dynamics (tool_type))
|
||||
{
|
||||
dynamics_check_button_new (config, "random-color",
|
||||
|
|
Loading…
Reference in New Issue