
2008-05-10 Michael Natterer <mitch@gimp.org> Applied modified patch from Alexia Death which adds velocity support to paint tools in the spirit of the pressure support we already have. Fixes bug #529431. * app/display/gimpdisplayshell-coords.c (gimp_display_shell_eval_event): tweak velocity calculation to work in screen coordinates. * app/paint/gimppaintoptions.[ch]: add velocity options in the same way as there are pressure options. Add utility functions which return dynamic opatity and dynamic rate according to the the option's settings and some GimpCoords' pressure and velocity. * app/tools/gimppaintoptions-gui.c: add GUI for the velocity options. * app/paint/gimpbrushcore.h: remove PRESSURE_SCALE define, it's now in gimppaintoptions.h. * app/paint/gimpbrushcore.c (gimp_brush_core_interpolate): inerpolate velocity too. (gimp_brush_core_calc_brush_scale): take velocity into account. (gimp_brush_core_get_brush_mask): always pressurize the mask in the GIMP_BRUSH_PRESSURE because there always is velocity (unlike pressure which is only there on tablets). * app/paint/gimpairbrush.c * app/paint/gimpclone.c * app/paint/gimpconvolve.c * app/paint/gimpdodgeburn.c * app/paint/gimperaser.c * app/paint/gimpheal.c * app/paint/gimppaintbrush.c * app/paint/gimpsmudge.c: get opacity and rate from the new paint options utility functions which take both pressure and velocity into account. * app/paint/gimppaintbrush.c: take velocity into account when calculating the gradient color offset. * app/paint/gimpairbrush.c: do some additional fiddling with velocity in the asynchronous airbrush timeout. * app/paint/gimpairbrushoptions.c: override the velocity-size property and have it default to FALSE. svn path=/trunk/; revision=25604
254 lines
7.8 KiB
C
254 lines
7.8 KiB
C
/* GIMP - The GNU Image Manipulation Program
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
*
|
|
* 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
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <glib-object.h>
|
|
|
|
#include "paint-types.h"
|
|
|
|
#include "base/pixel-region.h"
|
|
#include "base/temp-buf.h"
|
|
|
|
#include "paint-funcs/paint-funcs.h"
|
|
|
|
#include "core/gimp.h"
|
|
#include "core/gimpbrush.h"
|
|
#include "core/gimpdrawable.h"
|
|
#include "core/gimpimage.h"
|
|
#include "core/gimppickable.h"
|
|
|
|
#include "gimpconvolve.h"
|
|
#include "gimpconvolveoptions.h"
|
|
|
|
#include "gimp-intl.h"
|
|
|
|
|
|
#define FIELD_COLS 4
|
|
#define MIN_BLUR 64 /* (8/9 original pixel) */
|
|
#define MAX_BLUR 0.25 /* (1/33 original pixel) */
|
|
#define MIN_SHARPEN -512
|
|
#define MAX_SHARPEN -64
|
|
|
|
|
|
static void gimp_convolve_paint (GimpPaintCore *paint_core,
|
|
GimpDrawable *drawable,
|
|
GimpPaintOptions *paint_options,
|
|
GimpPaintState paint_state,
|
|
guint32 time);
|
|
static void gimp_convolve_motion (GimpPaintCore *paint_core,
|
|
GimpDrawable *drawable,
|
|
GimpPaintOptions *paint_options);
|
|
|
|
static void gimp_convolve_calculate_matrix (GimpConvolve *convolve,
|
|
GimpConvolveType type,
|
|
gdouble rate);
|
|
static gdouble gimp_convolve_sum_matrix (const gfloat *matrix);
|
|
|
|
|
|
G_DEFINE_TYPE (GimpConvolve, gimp_convolve, GIMP_TYPE_BRUSH_CORE)
|
|
|
|
|
|
void
|
|
gimp_convolve_register (Gimp *gimp,
|
|
GimpPaintRegisterCallback callback)
|
|
{
|
|
(* callback) (gimp,
|
|
GIMP_TYPE_CONVOLVE,
|
|
GIMP_TYPE_CONVOLVE_OPTIONS,
|
|
"gimp-convolve",
|
|
_("Convolve"),
|
|
"gimp-tool-blur");
|
|
}
|
|
|
|
static void
|
|
gimp_convolve_class_init (GimpConvolveClass *klass)
|
|
{
|
|
GimpPaintCoreClass *paint_core_class = GIMP_PAINT_CORE_CLASS (klass);
|
|
|
|
paint_core_class->paint = gimp_convolve_paint;
|
|
}
|
|
|
|
static void
|
|
gimp_convolve_init (GimpConvolve *convolve)
|
|
{
|
|
gint i;
|
|
|
|
for (i = 0; i < 9; i++)
|
|
convolve->matrix[i] = 1.0;
|
|
|
|
convolve->matrix_divisor = 9.0;
|
|
}
|
|
|
|
static void
|
|
gimp_convolve_paint (GimpPaintCore *paint_core,
|
|
GimpDrawable *drawable,
|
|
GimpPaintOptions *paint_options,
|
|
GimpPaintState paint_state,
|
|
guint32 time)
|
|
{
|
|
switch (paint_state)
|
|
{
|
|
case GIMP_PAINT_STATE_MOTION:
|
|
gimp_convolve_motion (paint_core, drawable, paint_options);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gimp_convolve_motion (GimpPaintCore *paint_core,
|
|
GimpDrawable *drawable,
|
|
GimpPaintOptions *paint_options)
|
|
{
|
|
GimpConvolve *convolve = GIMP_CONVOLVE (paint_core);
|
|
GimpBrushCore *brush_core = GIMP_BRUSH_CORE (paint_core);
|
|
GimpConvolveOptions *options = GIMP_CONVOLVE_OPTIONS (paint_options);
|
|
GimpContext *context = GIMP_CONTEXT (paint_options);
|
|
GimpImage *image;
|
|
TempBuf *area;
|
|
PixelRegion srcPR;
|
|
PixelRegion destPR;
|
|
PixelRegion tempPR;
|
|
guchar *buffer;
|
|
gdouble opacity;
|
|
gdouble rate;
|
|
gint bytes;
|
|
|
|
image = gimp_item_get_image (GIMP_ITEM (drawable));
|
|
|
|
if (gimp_drawable_is_indexed (drawable))
|
|
return;
|
|
|
|
/* If the brush is smaller than the convolution matrix, don't convolve */
|
|
if (brush_core->brush->mask->width < 3 ||
|
|
brush_core->brush->mask->height < 3)
|
|
return;
|
|
|
|
opacity = gimp_paint_options_get_fade (paint_options, image,
|
|
paint_core->pixel_dist);
|
|
if (opacity == 0.0)
|
|
return;
|
|
|
|
area = gimp_paint_core_get_paint_area (paint_core, drawable, paint_options);
|
|
if (! area)
|
|
return;
|
|
|
|
rate = options->rate;
|
|
|
|
rate *= gimp_paint_options_get_dynamic_rate (paint_options,
|
|
&paint_core->cur_coords,
|
|
paint_core->use_pressure);
|
|
|
|
gimp_convolve_calculate_matrix (convolve, options->type, rate);
|
|
|
|
/* configure the source pixel region */
|
|
pixel_region_init (&srcPR, gimp_drawable_get_tiles (drawable),
|
|
area->x, area->y, area->width, area->height, FALSE);
|
|
|
|
if (gimp_drawable_has_alpha (drawable))
|
|
{
|
|
bytes = srcPR.bytes;
|
|
|
|
buffer = g_malloc (area->height * bytes * area->width);
|
|
|
|
pixel_region_init_data (&tempPR, buffer,
|
|
bytes, bytes * area->width,
|
|
0, 0, area->width, area->height);
|
|
|
|
copy_region (&srcPR, &tempPR);
|
|
}
|
|
else
|
|
{
|
|
/* note: this particular approach needlessly convolves the totally-
|
|
opaque alpha channel. A faster approach would be to keep
|
|
tempPR the same number of bytes as srcPR, and extend the
|
|
paint_core_replace_canvas API to handle non-alpha images. */
|
|
|
|
bytes = srcPR.bytes + 1;
|
|
|
|
buffer = g_malloc (area->height * bytes * area->width);
|
|
|
|
pixel_region_init_data (&tempPR, buffer,
|
|
bytes, bytes * area->width,
|
|
0, 0, area->width, area->height);
|
|
|
|
add_alpha_region (&srcPR, &tempPR);
|
|
}
|
|
|
|
/* Convolve the region */
|
|
pixel_region_init_data (&tempPR, buffer,
|
|
bytes, bytes * area->width,
|
|
0, 0, area->width, area->height);
|
|
|
|
pixel_region_init_temp_buf (&destPR, area,
|
|
0, 0, area->width, area->height);
|
|
|
|
convolve_region (&tempPR, &destPR,
|
|
convolve->matrix, 3, convolve->matrix_divisor,
|
|
GIMP_NORMAL_CONVOL, TRUE);
|
|
|
|
g_free (buffer);
|
|
|
|
gimp_brush_core_replace_canvas (brush_core, drawable,
|
|
MIN (opacity, GIMP_OPACITY_OPAQUE),
|
|
gimp_context_get_opacity (context),
|
|
gimp_paint_options_get_brush_mode (paint_options),
|
|
GIMP_PAINT_INCREMENTAL);
|
|
}
|
|
|
|
static void
|
|
gimp_convolve_calculate_matrix (GimpConvolve *convolve,
|
|
GimpConvolveType type,
|
|
gdouble rate)
|
|
{
|
|
/* find percent of tool pressure */
|
|
gdouble percent = MIN (rate / 100.0, 1.0);
|
|
|
|
/* get the appropriate convolution matrix and size and divisor */
|
|
switch (type)
|
|
{
|
|
case GIMP_BLUR_CONVOLVE:
|
|
convolve->matrix[4] = MIN_BLUR + percent * (MAX_BLUR - MIN_BLUR);
|
|
break;
|
|
|
|
case GIMP_SHARPEN_CONVOLVE:
|
|
convolve->matrix[4] = MIN_SHARPEN + percent * (MAX_SHARPEN - MIN_SHARPEN);
|
|
break;
|
|
|
|
case GIMP_CUSTOM_CONVOLVE:
|
|
break;
|
|
}
|
|
|
|
convolve->matrix_divisor = gimp_convolve_sum_matrix (convolve->matrix);
|
|
}
|
|
|
|
static gdouble
|
|
gimp_convolve_sum_matrix (const gfloat *matrix)
|
|
{
|
|
gdouble sum = 0.0;
|
|
gint i;
|
|
|
|
for (i = 0; i < 9; i++)
|
|
sum += matrix[i];
|
|
|
|
return sum;
|
|
}
|