app: add GimpBrushCache which stores brush stuff based on transform parameters

such as masks and outlines. The cache is currently very stupid and
only cacheds the last transformed object. Add caches to GimpBrush for
its mask, its pixmap and its boundary, and remove the same caches and
a ton of members from GimpBrushCore. This involves adding lots of
const qualifiers because GimpBrush returns const pointers now for
trasnformed stuff.
This commit is contained in:
Michael Natterer 2011-04-05 22:11:27 +02:00
parent 8d5ac2c780
commit 21b8007b29
11 changed files with 766 additions and 396 deletions

View File

@ -62,6 +62,8 @@ libappcore_a_sources = \
gimpbrush-load.h \ gimpbrush-load.h \
gimpbrush-transform.c \ gimpbrush-transform.c \
gimpbrush-transform.h \ gimpbrush-transform.h \
gimpbrushcache.c \
gimpbrushcache.h \
gimpbrushclipboard.c \ gimpbrushclipboard.c \
gimpbrushclipboard.h \ gimpbrushclipboard.h \
gimpbrushgenerated.c \ gimpbrushgenerated.c \

View File

@ -101,6 +101,7 @@ typedef struct _GimpToolInfo GimpToolInfo;
typedef struct _GimpDataFactory GimpDataFactory; typedef struct _GimpDataFactory GimpDataFactory;
typedef struct _GimpData GimpData; typedef struct _GimpData GimpData;
typedef struct _GimpBrush GimpBrush; typedef struct _GimpBrush GimpBrush;
typedef struct _GimpBrushCache GimpBrushCache;
typedef struct _GimpBrushClipboard GimpBrushClipboard; typedef struct _GimpBrushClipboard GimpBrushClipboard;
typedef struct _GimpBrushGenerated GimpBrushGenerated; typedef struct _GimpBrushGenerated GimpBrushGenerated;
typedef struct _GimpBrushPipe GimpBrushPipe; typedef struct _GimpBrushPipe GimpBrushPipe;

View File

@ -38,7 +38,7 @@ gimp_brush_transform_boundary_exact (GimpBrush *brush,
gdouble angle, gdouble angle,
gdouble hardness) gdouble hardness)
{ {
TempBuf *mask; const TempBuf *mask;
mask = gimp_brush_transform_mask (brush, mask = gimp_brush_transform_mask (brush,
scale, aspect_ratio, angle, hardness); scale, aspect_ratio, angle, hardness);
@ -49,7 +49,7 @@ gimp_brush_transform_boundary_exact (GimpBrush *brush,
BoundSeg *bound_segs; BoundSeg *bound_segs;
gint n_bound_segs; gint n_bound_segs;
pixel_region_init_temp_buf (&maskPR, mask, pixel_region_init_temp_buf (&maskPR, (TempBuf *) mask,
0, 0, mask->width, mask->height); 0, 0, mask->width, mask->height);
bound_segs = boundary_find (&maskPR, BOUNDARY_WITHIN_BOUNDS, bound_segs = boundary_find (&maskPR, BOUNDARY_WITHIN_BOUNDS,
@ -57,8 +57,6 @@ gimp_brush_transform_boundary_exact (GimpBrush *brush,
0, 0,
&n_bound_segs); &n_bound_segs);
temp_buf_free (mask);
if (bound_segs) if (bound_segs)
{ {
BoundSeg *stroke_segs; BoundSeg *stroke_segs;

View File

@ -18,6 +18,7 @@
#include "config.h" #include "config.h"
#include <glib-object.h> #include <glib-object.h>
#include <cairo.h>
#include "libgimpbase/gimpbase.h" #include "libgimpbase/gimpbase.h"
#include "libgimpmath/gimpmath.h" #include "libgimpmath/gimpmath.h"
@ -26,10 +27,12 @@
#include "base/temp-buf.h" #include "base/temp-buf.h"
#include "gimpbezierdesc.h"
#include "gimpbrush.h" #include "gimpbrush.h"
#include "gimpbrush-boundary.h" #include "gimpbrush-boundary.h"
#include "gimpbrush-load.h" #include "gimpbrush-load.h"
#include "gimpbrush-transform.h" #include "gimpbrush-transform.h"
#include "gimpbrushcache.h"
#include "gimpbrushgenerated.h" #include "gimpbrushgenerated.h"
#include "gimpmarshal.h" #include "gimpmarshal.h"
#include "gimptagged.h" #include "gimptagged.h"
@ -52,6 +55,7 @@ enum
static void gimp_brush_tagged_iface_init (GimpTaggedInterface *iface); static void gimp_brush_tagged_iface_init (GimpTaggedInterface *iface);
static void gimp_brush_finalize (GObject *object);
static void gimp_brush_set_property (GObject *object, static void gimp_brush_set_property (GObject *object,
guint property_id, guint property_id,
const GValue *value, const GValue *value,
@ -60,7 +64,6 @@ static void gimp_brush_get_property (GObject *obj
guint property_id, guint property_id,
GValue *value, GValue *value,
GParamSpec *pspec); GParamSpec *pspec);
static void gimp_brush_finalize (GObject *object);
static gint64 gimp_brush_get_memsize (GimpObject *object, static gint64 gimp_brush_get_memsize (GimpObject *object,
gint64 *gui_size); gint64 *gui_size);
@ -74,6 +77,8 @@ static TempBuf * gimp_brush_get_new_preview (GimpViewable *vie
gint height); gint height);
static gchar * gimp_brush_get_description (GimpViewable *viewable, static gchar * gimp_brush_get_description (GimpViewable *viewable,
gchar **tooltip); gchar **tooltip);
static void gimp_brush_dirty (GimpData *data);
static const gchar * gimp_brush_get_extension (GimpData *data); static const gchar * gimp_brush_get_extension (GimpData *data);
static GimpBrush * gimp_brush_real_select_brush (GimpBrush *brush, static GimpBrush * gimp_brush_real_select_brush (GimpBrush *brush,
@ -112,9 +117,9 @@ gimp_brush_class_init (GimpBrushClass *klass)
gimp_marshal_VOID__VOID, gimp_marshal_VOID__VOID,
G_TYPE_NONE, 0); G_TYPE_NONE, 0);
object_class->finalize = gimp_brush_finalize;
object_class->get_property = gimp_brush_get_property; object_class->get_property = gimp_brush_get_property;
object_class->set_property = gimp_brush_set_property; object_class->set_property = gimp_brush_set_property;
object_class->finalize = gimp_brush_finalize;
gimp_object_class->get_memsize = gimp_brush_get_memsize; gimp_object_class->get_memsize = gimp_brush_get_memsize;
@ -123,6 +128,7 @@ gimp_brush_class_init (GimpBrushClass *klass)
viewable_class->get_new_preview = gimp_brush_get_new_preview; viewable_class->get_new_preview = gimp_brush_get_new_preview;
viewable_class->get_description = gimp_brush_get_description; viewable_class->get_description = gimp_brush_get_description;
data_class->dirty = gimp_brush_dirty;
data_class->get_extension = gimp_brush_get_extension; data_class->get_extension = gimp_brush_get_extension;
klass->select_brush = gimp_brush_real_select_brush; klass->select_brush = gimp_brush_real_select_brush;
@ -160,6 +166,44 @@ gimp_brush_init (GimpBrush *brush)
brush->y_axis.y = 15.0; brush->y_axis.y = 15.0;
} }
static void
gimp_brush_finalize (GObject *object)
{
GimpBrush *brush = GIMP_BRUSH (object);
if (brush->mask)
{
temp_buf_free (brush->mask);
brush->mask = NULL;
}
if (brush->pixmap)
{
temp_buf_free (brush->pixmap);
brush->pixmap = NULL;
}
if (brush->mask_cache)
{
g_object_unref (brush->mask_cache);
brush->mask_cache = NULL;
}
if (brush->pixmap_cache)
{
g_object_unref (brush->pixmap_cache);
brush->pixmap_cache = NULL;
}
if (brush->boundary_cache)
{
g_object_unref (brush->boundary_cache);
brush->boundary_cache = NULL;
}
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void static void
gimp_brush_set_property (GObject *object, gimp_brush_set_property (GObject *object,
guint property_id, guint property_id,
@ -200,26 +244,6 @@ gimp_brush_get_property (GObject *object,
} }
} }
static void
gimp_brush_finalize (GObject *object)
{
GimpBrush *brush = GIMP_BRUSH (object);
if (brush->mask)
{
temp_buf_free (brush->mask);
brush->mask = NULL;
}
if (brush->pixmap)
{
temp_buf_free (brush->pixmap);
brush->pixmap = NULL;
}
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static gint64 static gint64
gimp_brush_get_memsize (GimpObject *object, gimp_brush_get_memsize (GimpObject *object,
gint64 *gui_size) gint64 *gui_size)
@ -253,17 +277,18 @@ gimp_brush_get_new_preview (GimpViewable *viewable,
gint width, gint width,
gint height) gint height)
{ {
GimpBrush *brush = GIMP_BRUSH (viewable); GimpBrush *brush = GIMP_BRUSH (viewable);
TempBuf *mask_buf = NULL; const TempBuf *mask_buf = NULL;
TempBuf *pixmap_buf = NULL; gboolean free_mask = FALSE;
TempBuf *return_buf = NULL; const TempBuf *pixmap_buf = NULL;
gint mask_width; TempBuf *return_buf = NULL;
gint mask_height; gint mask_width;
guchar transp[4] = { 0, 0, 0, 0 }; gint mask_height;
guchar *mask; guchar transp[4] = { 0, 0, 0, 0 };
guchar *buf; guchar *mask;
gint x, y; guchar *buf;
gboolean scaled = FALSE; gint x, y;
gboolean scaled = FALSE;
mask_buf = brush->mask; mask_buf = brush->mask;
pixmap_buf = brush->pixmap; pixmap_buf = brush->pixmap;
@ -279,13 +304,20 @@ gimp_brush_get_new_preview (GimpViewable *viewable,
if (scale != 1.0) if (scale != 1.0)
{ {
mask_buf = gimp_brush_transform_mask (brush, scale, 0.0, 0.0, 1.0); gimp_brush_start_use (brush);
mask_buf = gimp_brush_transform_mask (brush, scale,
0.0, 0.0, 1.0);
if (! mask_buf) if (! mask_buf)
mask_buf = temp_buf_new (1, 1, 1, 0, 0, transp); {
mask_buf = temp_buf_new (1, 1, 1, 0, 0, transp);
free_mask = TRUE;
}
if (pixmap_buf) if (pixmap_buf)
pixmap_buf = gimp_brush_transform_pixmap (brush, scale, 0.0, 0.0, 1.0); pixmap_buf = gimp_brush_transform_pixmap (brush, scale,
0.0, 0.0, 1.0);
mask_width = mask_buf->width; mask_width = mask_buf->width;
mask_height = mask_buf->height; mask_height = mask_buf->height;
@ -330,10 +362,10 @@ gimp_brush_get_new_preview (GimpViewable *viewable,
if (scaled) if (scaled)
{ {
temp_buf_free (mask_buf); if (free_mask)
temp_buf_free ((TempBuf *) mask_buf);
if (pixmap_buf) gimp_brush_end_use (brush);
temp_buf_free (pixmap_buf);
} }
return return_buf; return return_buf;
@ -351,6 +383,23 @@ gimp_brush_get_description (GimpViewable *viewable,
brush->mask->height); brush->mask->height);
} }
static void
gimp_brush_dirty (GimpData *data)
{
GimpBrush *brush = GIMP_BRUSH (data);
if (brush->mask_cache)
gimp_brush_cache_clear (brush->mask_cache);
if (brush->pixmap_cache)
gimp_brush_cache_clear (brush->pixmap_cache);
if (brush->boundary_cache)
gimp_brush_cache_clear (brush->boundary_cache);
GIMP_DATA_CLASS (parent_class)->dirty (data);
}
static const gchar * static const gchar *
gimp_brush_get_extension (GimpData *data) gimp_brush_get_extension (GimpData *data)
{ {
@ -486,54 +535,106 @@ gimp_brush_transform_size (GimpBrush *brush,
width, height); width, height);
} }
TempBuf * const TempBuf *
gimp_brush_transform_mask (GimpBrush *brush, gimp_brush_transform_mask (GimpBrush *brush,
gdouble scale, gdouble scale,
gdouble aspect_ratio, gdouble aspect_ratio,
gdouble angle, gdouble angle,
gdouble hardness) gdouble hardness)
{ {
const TempBuf *mask;
gint width;
gint height;
g_return_val_if_fail (GIMP_IS_BRUSH (brush), NULL); g_return_val_if_fail (GIMP_IS_BRUSH (brush), NULL);
g_return_val_if_fail (scale > 0.0, NULL); g_return_val_if_fail (scale > 0.0, NULL);
if (scale == 1.0 && gimp_brush_transform_size (brush,
aspect_ratio == 0.0 && scale, aspect_ratio, angle,
angle == 0.0 && &width, &height);
hardness == 1.0)
mask = gimp_brush_cache_get (brush->mask_cache,
width, height,
scale, aspect_ratio, angle, hardness);
if (! mask)
{ {
return temp_buf_copy (brush->mask, NULL); if (scale == 1.0 &&
aspect_ratio == 0.0 &&
angle == 0.0 &&
hardness == 1.0)
{
mask = temp_buf_copy (brush->mask, NULL);
}
else
{
mask = GIMP_BRUSH_GET_CLASS (brush)->transform_mask (brush,
scale,
aspect_ratio,
angle,
hardness);
}
gimp_brush_cache_add (brush->mask_cache,
(gpointer) mask,
width, height,
scale, aspect_ratio, angle, hardness);
} }
return GIMP_BRUSH_GET_CLASS (brush)->transform_mask (brush, return mask;
scale, aspect_ratio,
angle, hardness);
} }
TempBuf * const TempBuf *
gimp_brush_transform_pixmap (GimpBrush *brush, gimp_brush_transform_pixmap (GimpBrush *brush,
gdouble scale, gdouble scale,
gdouble aspect_ratio, gdouble aspect_ratio,
gdouble angle, gdouble angle,
gdouble hardness) gdouble hardness)
{ {
const TempBuf *pixmap;
gint width;
gint height;
g_return_val_if_fail (GIMP_IS_BRUSH (brush), NULL); g_return_val_if_fail (GIMP_IS_BRUSH (brush), NULL);
g_return_val_if_fail (brush->pixmap != NULL, NULL); g_return_val_if_fail (brush->pixmap != NULL, NULL);
g_return_val_if_fail (scale > 0.0, NULL); g_return_val_if_fail (scale > 0.0, NULL);
if (scale == 1.0 && gimp_brush_transform_size (brush,
aspect_ratio == 0.0 && scale, aspect_ratio, angle,
angle == 0.0 && &width, &height);
hardness == 1.0)
pixmap = gimp_brush_cache_get (brush->pixmap_cache,
width, height,
scale, aspect_ratio, angle, hardness);
if (! pixmap)
{ {
return temp_buf_copy (brush->pixmap, NULL); if (scale == 1.0 &&
aspect_ratio == 0.0 &&
angle == 0.0 &&
hardness == 1.0)
{
pixmap = temp_buf_copy (brush->pixmap, NULL);
}
else
{
pixmap = GIMP_BRUSH_GET_CLASS (brush)->transform_pixmap (brush,
scale,
aspect_ratio,
angle,
hardness);
}
gimp_brush_cache_add (brush->pixmap_cache,
(gpointer) pixmap,
width, height,
scale, aspect_ratio, angle, hardness);
} }
return GIMP_BRUSH_GET_CLASS (brush)->transform_pixmap (brush, return pixmap;
scale, aspect_ratio,
angle, hardness);
} }
GimpBezierDesc * const GimpBezierDesc *
gimp_brush_transform_boundary (GimpBrush *brush, gimp_brush_transform_boundary (GimpBrush *brush,
gdouble scale, gdouble scale,
gdouble aspect_ratio, gdouble aspect_ratio,
@ -542,15 +643,38 @@ gimp_brush_transform_boundary (GimpBrush *brush,
gint *width, gint *width,
gint *height) gint *height)
{ {
const GimpBezierDesc *boundary;
g_return_val_if_fail (GIMP_IS_BRUSH (brush), NULL); g_return_val_if_fail (GIMP_IS_BRUSH (brush), NULL);
g_return_val_if_fail (scale > 0.0, NULL); g_return_val_if_fail (scale > 0.0, NULL);
g_return_val_if_fail (width != NULL, NULL); g_return_val_if_fail (width != NULL, NULL);
g_return_val_if_fail (height != NULL, NULL); g_return_val_if_fail (height != NULL, NULL);
return GIMP_BRUSH_GET_CLASS (brush)->transform_boundary (brush, gimp_brush_transform_size (brush,
scale, aspect_ratio, scale, aspect_ratio, angle,
angle, hardness, width, height);
width, height);
boundary = gimp_brush_cache_get (brush->boundary_cache,
*width, *height,
scale, aspect_ratio, angle, hardness);
if (! boundary)
{
boundary = GIMP_BRUSH_GET_CLASS (brush)->transform_boundary (brush,
scale,
aspect_ratio,
angle,
hardness,
width,
height);
gimp_brush_cache_add (brush->boundary_cache,
(gpointer) boundary,
*width, *height,
scale, aspect_ratio, angle, hardness);
}
return boundary;
} }
gdouble gdouble
@ -612,6 +736,18 @@ gimp_brush_start_use (GimpBrush *brush)
g_return_if_fail (GIMP_IS_BRUSH (brush)); g_return_if_fail (GIMP_IS_BRUSH (brush));
brush->use_count++; brush->use_count++;
if (brush->use_count == 1)
{
brush->mask_cache =
gimp_brush_cache_new ((GDestroyNotify) temp_buf_free, 'M', 'm');
brush->pixmap_cache =
gimp_brush_cache_new ((GDestroyNotify) temp_buf_free, 'P', 'p');
brush->boundary_cache =
gimp_brush_cache_new ((GDestroyNotify) gimp_bezier_desc_free, 'B', 'b');
}
} }
void void
@ -624,6 +760,13 @@ gimp_brush_end_use (GimpBrush *brush)
if (brush->use_count == 0) if (brush->use_count == 0)
{ {
/* flush caches */ g_object_unref (brush->mask_cache);
brush->mask_cache = NULL;
g_object_unref (brush->pixmap_cache);
brush->pixmap_cache = NULL;
g_object_unref (brush->boundary_cache);
brush->boundary_cache = NULL;
} }
} }

View File

@ -35,16 +35,19 @@ typedef struct _GimpBrushClass GimpBrushClass;
struct _GimpBrush struct _GimpBrush
{ {
GimpData parent_instance; GimpData parent_instance;
TempBuf *mask; /* the actual mask */ TempBuf *mask; /* the actual mask */
TempBuf *pixmap; /* optional pixmap data */ TempBuf *pixmap; /* optional pixmap data */
gint spacing; /* brush's spacing */ gint spacing; /* brush's spacing */
GimpVector2 x_axis; /* for calculating brush spacing */ GimpVector2 x_axis; /* for calculating brush spacing */
GimpVector2 y_axis; /* for calculating brush spacing */ GimpVector2 y_axis; /* for calculating brush spacing */
gint use_count; /* for keeping the caches alive */ gint use_count; /* for keeping the caches alive */
GimpBrushCache *mask_cache;
GimpBrushCache *pixmap_cache;
GimpBrushCache *boundary_cache;
}; };
struct _GimpBrushClass struct _GimpBrushClass
@ -87,58 +90,58 @@ struct _GimpBrushClass
}; };
GType gimp_brush_get_type (void) G_GNUC_CONST; GType gimp_brush_get_type (void) G_GNUC_CONST;
GimpData * gimp_brush_new (GimpContext *context, GimpData * gimp_brush_new (GimpContext *context,
const gchar *name); const gchar *name);
GimpData * gimp_brush_get_standard (GimpContext *context); GimpData * gimp_brush_get_standard (GimpContext *context);
GimpBrush * gimp_brush_select_brush (GimpBrush *brush, GimpBrush * gimp_brush_select_brush (GimpBrush *brush,
const GimpCoords *last_coords, const GimpCoords *last_coords,
const GimpCoords *current_coords); const GimpCoords *current_coords);
gboolean gimp_brush_want_null_motion (GimpBrush *brush, gboolean gimp_brush_want_null_motion (GimpBrush *brush,
const GimpCoords *last_coords, const GimpCoords *last_coords,
const GimpCoords *current_coords); const GimpCoords *current_coords);
/* Gets width and height of a transformed mask of the brush, for /* Gets width and height of a transformed mask of the brush, for
* provided parameters. * provided parameters.
*/ */
void gimp_brush_transform_size (GimpBrush *brush, void gimp_brush_transform_size (GimpBrush *brush,
gdouble scale, gdouble scale,
gdouble aspect_ratio, gdouble aspect_ratio,
gdouble angle, gdouble angle,
gint *width, gint *width,
gint *height); gint *height);
TempBuf * gimp_brush_transform_mask (GimpBrush *brush, const TempBuf * gimp_brush_transform_mask (GimpBrush *brush,
gdouble scale, gdouble scale,
gdouble aspect_ratio, gdouble aspect_ratio,
gdouble angle, gdouble angle,
gdouble hardness); gdouble hardness);
TempBuf * gimp_brush_transform_pixmap (GimpBrush *brush, const TempBuf * gimp_brush_transform_pixmap (GimpBrush *brush,
gdouble scale, gdouble scale,
gdouble aspect_ratio, gdouble aspect_ratio,
gdouble angle, gdouble angle,
gdouble hardness); gdouble hardness);
GimpBezierDesc * gimp_brush_transform_boundary (GimpBrush *brush, const GimpBezierDesc * gimp_brush_transform_boundary (GimpBrush *brush,
gdouble scale, gdouble scale,
gdouble aspect_ratio, gdouble aspect_ratio,
gdouble angle, gdouble angle,
gdouble hardness, gdouble hardness,
gint *width, gint *width,
gint *height); gint *height);
gdouble gimp_brush_clamp_scale (GimpBrush *brush, gdouble gimp_brush_clamp_scale (GimpBrush *brush,
gdouble scale); gdouble scale);
TempBuf * gimp_brush_get_mask (const GimpBrush *brush); TempBuf * gimp_brush_get_mask (const GimpBrush *brush);
TempBuf * gimp_brush_get_pixmap (const GimpBrush *brush); TempBuf * gimp_brush_get_pixmap (const GimpBrush *brush);
gint gimp_brush_get_spacing (const GimpBrush *brush); gint gimp_brush_get_spacing (const GimpBrush *brush);
void gimp_brush_set_spacing (GimpBrush *brush, void gimp_brush_set_spacing (GimpBrush *brush,
gint spacing); gint spacing);
void gimp_brush_start_use (GimpBrush *brush); void gimp_brush_start_use (GimpBrush *brush);
void gimp_brush_end_use (GimpBrush *brush); void gimp_brush_end_use (GimpBrush *brush);
#endif /* __GIMP_BRUSH_H__ */ #endif /* __GIMP_BRUSH_H__ */

232
app/core/gimpbrushcache.c Normal file
View File

@ -0,0 +1,232 @@
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimpbrushcache.c
* Copyright (C) 2011 Michael Natterer <mitch@gimp.org>
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <gegl.h>
#include "core-types.h"
#include "gimpbrushcache.h"
#include "gimp-intl.h"
enum
{
PROP_0,
PROP_DATA_DESTROY
};
static void gimp_brush_cache_constructed (GObject *object);
static void gimp_brush_cache_finalize (GObject *object);
static void gimp_brush_cache_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec);
static void gimp_brush_cache_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec);
G_DEFINE_TYPE (GimpBrushCache, gimp_brush_cache, GIMP_TYPE_OBJECT)
#define parent_class gimp_brush_cache_parent_class
static void
gimp_brush_cache_class_init (GimpBrushCacheClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->constructed = gimp_brush_cache_constructed;
object_class->finalize = gimp_brush_cache_finalize;
object_class->set_property = gimp_brush_cache_set_property;
object_class->get_property = gimp_brush_cache_get_property;
g_object_class_install_property (object_class, PROP_DATA_DESTROY,
g_param_spec_pointer ("data-destroy",
NULL, NULL,
GIMP_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
}
static void
gimp_brush_cache_init (GimpBrushCache *brush)
{
}
static void
gimp_brush_cache_constructed (GObject *object)
{
GimpBrushCache *cache = GIMP_BRUSH_CACHE (object);
if (G_OBJECT_CLASS (parent_class)->constructed)
G_OBJECT_CLASS (parent_class)->constructed (object);
g_assert (cache->data_destroy != NULL);
}
static void
gimp_brush_cache_finalize (GObject *object)
{
GimpBrushCache *cache = GIMP_BRUSH_CACHE (object);
if (cache->last_data)
{
cache->data_destroy (cache->last_data);
cache->last_data = NULL;
}
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
gimp_brush_cache_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
GimpBrushCache *cache = GIMP_BRUSH_CACHE (object);
switch (property_id)
{
case PROP_DATA_DESTROY:
cache->data_destroy = g_value_get_pointer (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
gimp_brush_cache_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
GimpBrushCache *cache = GIMP_BRUSH_CACHE (object);
switch (property_id)
{
case PROP_DATA_DESTROY:
g_value_set_pointer (value, cache->data_destroy);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
/* public functions */
GimpBrushCache *
gimp_brush_cache_new (GDestroyNotify data_destroy,
gchar debug_hit,
gchar debug_miss)
{
GimpBrushCache *cache;
g_return_val_if_fail (data_destroy != NULL, NULL);
cache = g_object_new (GIMP_TYPE_BRUSH_CACHE,
"data-destroy", data_destroy,
NULL);
cache->debug_hit = debug_hit;
cache->debug_miss = debug_miss;
return cache;
}
void
gimp_brush_cache_clear (GimpBrushCache *cache)
{
g_return_if_fail (GIMP_IS_BRUSH_CACHE (cache));
if (cache->last_data)
{
cache->data_destroy (cache->last_data);
cache->last_data = NULL;
}
}
gconstpointer
gimp_brush_cache_get (GimpBrushCache *cache,
gint width,
gint height,
gdouble scale,
gdouble aspect_ratio,
gdouble angle,
gdouble hardness)
{
g_return_val_if_fail (GIMP_IS_BRUSH_CACHE (cache), NULL);
if (cache->last_data &&
cache->last_width == width &&
cache->last_height == height &&
cache->last_scale == scale &&
cache->last_aspect_ratio == aspect_ratio &&
cache->last_angle == angle &&
cache->last_hardness == hardness)
{
g_printerr ("%c", cache->debug_hit);
return (gconstpointer) cache->last_data;
}
g_printerr ("%c", cache->debug_miss);
return NULL;
}
void
gimp_brush_cache_add (GimpBrushCache *cache,
gpointer data,
gint width,
gint height,
gdouble scale,
gdouble aspect_ratio,
gdouble angle,
gdouble hardness)
{
g_return_if_fail (GIMP_IS_BRUSH_CACHE (cache));
g_return_if_fail (data != NULL);
if (data == cache->last_data)
return;
if (cache->last_data)
cache->data_destroy (cache->last_data);
cache->last_data = data;
cache->last_width = width;
cache->last_height = height;
cache->last_scale = scale;
cache->last_aspect_ratio = aspect_ratio;
cache->last_angle = angle;
cache->last_hardness = hardness;
}

87
app/core/gimpbrushcache.h Normal file
View File

@ -0,0 +1,87 @@
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimpbrushcache.h
* Copyright (C) 2011 Michael Natterer <mitch@gimp.org>
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GIMP_BRUSH_CACHE_H__
#define __GIMP_BRUSH_CACHE_H__
#include "gimpobject.h"
#define GIMP_TYPE_BRUSH_CACHE (gimp_brush_cache_get_type ())
#define GIMP_BRUSH_CACHE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_BRUSH_CACHE, GimpBrushCache))
#define GIMP_BRUSH_CACHE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_BRUSH_CACHE, GimpBrushCacheClass))
#define GIMP_IS_BRUSH_CACHE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_BRUSH_CACHE))
#define GIMP_IS_BRUSH_CACHE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_BRUSH_CACHE))
#define GIMP_BRUSH_CACHE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_BRUSH_CACHE, GimpBrushCacheClass))
typedef struct _GimpBrushCacheClass GimpBrushCacheClass;
struct _GimpBrushCache
{
GimpObject parent_instance;
GDestroyNotify data_destroy;
gpointer last_data;
gint last_width;
gint last_height;
gdouble last_scale;
gdouble last_aspect_ratio;
gdouble last_angle;
gdouble last_hardness;
gchar debug_hit;
gchar debug_miss;
};
struct _GimpBrushCacheClass
{
GimpObjectClass parent_class;
};
GType gimp_brush_cache_get_type (void) G_GNUC_CONST;
GimpBrushCache * gimp_brush_cache_new (GDestroyNotify data_destory,
gchar debug_hit,
gchar debug_miss);
void gimp_brush_cache_clear (GimpBrushCache *cache);
gconstpointer gimp_brush_cache_get (GimpBrushCache *cache,
gint width,
gint height,
gdouble scale,
gdouble aspect_ratio,
gdouble angle,
gdouble hardness);
void gimp_brush_cache_add (GimpBrushCache *cache,
gpointer data,
gint width,
gint height,
gdouble scale,
gdouble aspect_ratio,
gdouble angle,
gdouble hardness);
#endif /* __GIMP_BRUSH_CACHE_H__ */

View File

@ -58,73 +58,70 @@ enum
/* local function prototypes */ /* local function prototypes */
static void gimp_brush_core_finalize (GObject *object); static void gimp_brush_core_finalize (GObject *object);
static gboolean gimp_brush_core_start (GimpPaintCore *core, static gboolean gimp_brush_core_start (GimpPaintCore *core,
GimpDrawable *drawable, GimpDrawable *drawable,
GimpPaintOptions *paint_options, GimpPaintOptions *paint_options,
const GimpCoords *coords, const GimpCoords *coords,
GError **error); GError **error);
static gboolean gimp_brush_core_pre_paint (GimpPaintCore *core, static gboolean gimp_brush_core_pre_paint (GimpPaintCore *core,
GimpDrawable *drawable, GimpDrawable *drawable,
GimpPaintOptions *paint_options, GimpPaintOptions *paint_options,
GimpPaintState paint_state, GimpPaintState paint_state,
guint32 time); guint32 time);
static void gimp_brush_core_post_paint (GimpPaintCore *core, static void gimp_brush_core_post_paint (GimpPaintCore *core,
GimpDrawable *drawable, GimpDrawable *drawable,
GimpPaintOptions *paint_options, GimpPaintOptions *paint_options,
GimpPaintState paint_state, GimpPaintState paint_state,
guint32 time); guint32 time);
static void gimp_brush_core_interpolate (GimpPaintCore *core, static void gimp_brush_core_interpolate (GimpPaintCore *core,
GimpDrawable *drawable, GimpDrawable *drawable,
GimpPaintOptions *paint_options, GimpPaintOptions *paint_options,
guint32 time); guint32 time);
static TempBuf *gimp_brush_core_get_paint_area (GimpPaintCore *paint_core, static TempBuf * gimp_brush_core_get_paint_area (GimpPaintCore *paint_core,
GimpDrawable *drawable, GimpDrawable *drawable,
GimpPaintOptions *paint_options, GimpPaintOptions *paint_options,
const GimpCoords *coords); const GimpCoords *coords);
static void gimp_brush_core_real_set_brush (GimpBrushCore *core, static void gimp_brush_core_real_set_brush (GimpBrushCore *core,
GimpBrush *brush); GimpBrush *brush);
static void gimp_brush_core_real_set_dynamics (GimpBrushCore *core, static void gimp_brush_core_real_set_dynamics (GimpBrushCore *core,
GimpDynamics *dynamics); GimpDynamics *dynamics);
static inline void rotate_pointers (gulong **p, static const TempBuf * gimp_brush_core_subsample_mask (GimpBrushCore *core,
guint32 n); const TempBuf *mask,
static TempBuf * gimp_brush_core_subsample_mask (GimpBrushCore *core, gdouble x,
TempBuf *mask, gdouble y);
gdouble x, static const TempBuf * gimp_brush_core_pressurize_mask (GimpBrushCore *core,
gdouble y); const TempBuf *brush_mask,
static TempBuf * gimp_brush_core_pressurize_mask (GimpBrushCore *core, gdouble x,
TempBuf *brush_mask, gdouble y,
gdouble x, gdouble pressure);
gdouble y, static const TempBuf * gimp_brush_core_solidify_mask (GimpBrushCore *core,
gdouble pressure); const TempBuf *brush_mask,
static TempBuf * gimp_brush_core_solidify_mask (GimpBrushCore *core, gdouble x,
TempBuf *brush_mask, gdouble y);
gdouble x, static const TempBuf * gimp_brush_core_transform_mask (GimpBrushCore *core,
gdouble y); GimpBrush *brush);
static TempBuf * gimp_brush_core_transform_mask (GimpBrushCore *core, static const TempBuf * gimp_brush_core_transform_pixmap (GimpBrushCore *core,
GimpBrush *brush); GimpBrush *brush);
static TempBuf * gimp_brush_core_transform_pixmap (GimpBrushCore *core,
GimpBrush *brush);
static void gimp_brush_core_invalidate_cache (GimpBrush *brush,
GimpBrushCore *core);
static void gimp_brush_core_invalidate_cache (GimpBrush *brush,
GimpBrushCore *core);
/* brush pipe utility functions */ /* brush pipe utility functions */
static void paint_line_pixmap_mask (GimpImage *dest, static void gimp_brush_core_paint_line_pixmap_mask (GimpImage *dest,
GimpDrawable *drawable, GimpDrawable *drawable,
TempBuf *pixmap_mask, const TempBuf *pixmap_mask,
TempBuf *brush_mask, const TempBuf *brush_mask,
guchar *d, guchar *d,
gint x, gint x,
gint y, gint y,
gint bytes, gint bytes,
gint width, gint width,
GimpBrushApplicationMode mode); GimpBrushApplicationMode mode);
G_DEFINE_TYPE (GimpBrushCore, gimp_brush_core, GIMP_TYPE_PAINT_CORE) G_DEFINE_TYPE (GimpBrushCore, gimp_brush_core, GIMP_TYPE_PAINT_CORE)
@ -192,19 +189,12 @@ gimp_brush_core_init (GimpBrushCore *core)
core->pressure_brush = NULL; core->pressure_brush = NULL;
core->last_solid_brush = NULL; core->last_solid_brush_mask = NULL;
core->solid_cache_invalid = FALSE; core->solid_cache_invalid = FALSE;
core->transform_brush = NULL; core->transform_brush = NULL;
core->last_transform_brush = NULL;
core->last_transform_width = 0;
core->last_transform_height = 0;
core->last_scale = 1.0;
core->transform_pixmap = NULL; core->transform_pixmap = NULL;
core->last_transform_pixmap = NULL;
core->last_transform_pixmap_width = 0;
core->last_transform_pixmap_height = 0;
core->last_brush_mask = NULL; core->last_brush_mask = NULL;
core->cache_invalid = FALSE; core->cache_invalid = FALSE;
@ -259,18 +249,6 @@ gimp_brush_core_finalize (GObject *object)
core->solid_brushes[i][j] = NULL; core->solid_brushes[i][j] = NULL;
} }
if (core->transform_brush)
{
temp_buf_free (core->transform_brush);
core->transform_brush = NULL;
}
if (core->transform_pixmap)
{
temp_buf_free (core->transform_pixmap);
core->transform_pixmap = NULL;
}
if (core->rand) if (core->rand)
{ {
g_rand_free (core->rand); g_rand_free (core->rand);
@ -934,10 +912,10 @@ gimp_brush_core_paste_canvas (GimpBrushCore *core,
gdouble dynamic_force, gdouble dynamic_force,
GimpPaintApplicationMode mode) GimpPaintApplicationMode mode)
{ {
TempBuf *brush_mask = gimp_brush_core_get_brush_mask (core, const TempBuf *brush_mask = gimp_brush_core_get_brush_mask (core,
coords, coords,
brush_hardness, brush_hardness,
dynamic_force); dynamic_force);
if (brush_mask) if (brush_mask)
{ {
@ -954,7 +932,7 @@ gimp_brush_core_paste_canvas (GimpBrushCore *core,
off_x = (x < 0) ? -x : 0; off_x = (x < 0) ? -x : 0;
off_y = (y < 0) ? -y : 0; off_y = (y < 0) ? -y : 0;
pixel_region_init_temp_buf (&brush_maskPR, brush_mask, pixel_region_init_temp_buf (&brush_maskPR, (TempBuf *) brush_mask,
off_x, off_y, off_x, off_y,
paint_core->canvas_buf->width, paint_core->canvas_buf->width,
paint_core->canvas_buf->height); paint_core->canvas_buf->height);
@ -980,10 +958,10 @@ gimp_brush_core_replace_canvas (GimpBrushCore *core,
gdouble dynamic_force, gdouble dynamic_force,
GimpPaintApplicationMode mode) GimpPaintApplicationMode mode)
{ {
TempBuf *brush_mask = gimp_brush_core_get_brush_mask (core, const TempBuf *brush_mask = gimp_brush_core_get_brush_mask (core,
coords, coords,
brush_hardness, brush_hardness,
dynamic_force); dynamic_force);
if (brush_mask) if (brush_mask)
{ {
@ -1000,7 +978,7 @@ gimp_brush_core_replace_canvas (GimpBrushCore *core,
off_x = (x < 0) ? -x : 0; off_x = (x < 0) ? -x : 0;
off_y = (y < 0) ? -y : 0; off_y = (y < 0) ? -y : 0;
pixel_region_init_temp_buf (&brush_maskPR, brush_mask, pixel_region_init_temp_buf (&brush_maskPR, (TempBuf *) brush_mask,
off_x, off_y, off_x, off_y,
paint_core->canvas_buf->width, paint_core->canvas_buf->width,
paint_core->canvas_buf->height); paint_core->canvas_buf->height);
@ -1047,9 +1025,9 @@ rotate_pointers (gulong **p,
p[i] = tmp; p[i] = tmp;
} }
static TempBuf * static const TempBuf *
gimp_brush_core_subsample_mask (GimpBrushCore *core, gimp_brush_core_subsample_mask (GimpBrushCore *core,
TempBuf *mask, const TempBuf *mask,
gdouble x, gdouble x,
gdouble y) gdouble y)
{ {
@ -1181,9 +1159,9 @@ gimp_brush_core_subsample_mask (GimpBrushCore *core,
/* #define FANCY_PRESSURE */ /* #define FANCY_PRESSURE */
static TempBuf * static const TempBuf *
gimp_brush_core_pressurize_mask (GimpBrushCore *core, gimp_brush_core_pressurize_mask (GimpBrushCore *core,
TempBuf *brush_mask, const TempBuf *brush_mask,
gdouble x, gdouble x,
gdouble y, gdouble y,
gdouble pressure) gdouble pressure)
@ -1191,7 +1169,7 @@ gimp_brush_core_pressurize_mask (GimpBrushCore *core,
static guchar mapi[256]; static guchar mapi[256];
const guchar *source; const guchar *source;
guchar *dest; guchar *dest;
TempBuf *subsample_mask; const TempBuf *subsample_mask;
const guchar empty = TRANSPARENT_OPACITY; const guchar empty = TRANSPARENT_OPACITY;
gint i; gint i;
@ -1296,9 +1274,9 @@ gimp_brush_core_pressurize_mask (GimpBrushCore *core,
return core->pressure_brush; return core->pressure_brush;
} }
static TempBuf * static const TempBuf *
gimp_brush_core_solidify_mask (GimpBrushCore *core, gimp_brush_core_solidify_mask (GimpBrushCore *core,
TempBuf *brush_mask, const TempBuf *brush_mask,
gdouble x, gdouble x,
gdouble y) gdouble y)
{ {
@ -1329,7 +1307,7 @@ gimp_brush_core_solidify_mask (GimpBrushCore *core,
} }
if (! core->solid_cache_invalid && if (! core->solid_cache_invalid &&
brush_mask == core->last_solid_brush) brush_mask == core->last_solid_brush_mask)
{ {
if (core->solid_brushes[dest_offset_y][dest_offset_x]) if (core->solid_brushes[dest_offset_y][dest_offset_x])
return core->solid_brushes[dest_offset_y][dest_offset_x]; return core->solid_brushes[dest_offset_y][dest_offset_x];
@ -1344,8 +1322,8 @@ gimp_brush_core_solidify_mask (GimpBrushCore *core,
core->solid_brushes[i][j] = NULL; core->solid_brushes[i][j] = NULL;
} }
core->last_solid_brush = brush_mask; core->last_solid_brush_mask = brush_mask;
core->solid_cache_invalid = FALSE; core->solid_cache_invalid = FALSE;
} }
dest = temp_buf_new (brush_mask->width + 2, dest = temp_buf_new (brush_mask->width + 2,
@ -1370,123 +1348,62 @@ gimp_brush_core_solidify_mask (GimpBrushCore *core,
return dest; return dest;
} }
static TempBuf * static const TempBuf *
gimp_brush_core_transform_mask (GimpBrushCore *core, gimp_brush_core_transform_mask (GimpBrushCore *core,
GimpBrush *brush) GimpBrush *brush)
{ {
gint width; const TempBuf *mask;
gint height;
if (core->scale <= 0.0) if (core->scale <= 0.0)
return NULL; /* Should never happen now, with scale clamping. */ return NULL; /* Should never happen now, with scale clamping. */
if ((core->scale == 1.0) && mask = gimp_brush_transform_mask (brush,
(core->angle == 0.0) && core->scale,
(core->hardness == 1.0) && core->aspect_ratio,
(core->aspect_ratio == 0.0)) core->angle,
return brush->mask; core->hardness);
gimp_brush_transform_size (brush, if (mask == core->transform_brush)
core->scale, core->aspect_ratio, core->angle, return mask;
&width, &height);
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->angle == core->last_angle &&
core->hardness == core->last_hardness &&
core->aspect_ratio == core->last_aspect_ratio)
{
return core->transform_brush;
}
core->last_transform_brush = brush->mask;
core->last_transform_width = width;
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->hardness);
core->transform_brush = mask;
core->cache_invalid = TRUE; core->cache_invalid = TRUE;
core->solid_cache_invalid = TRUE; core->solid_cache_invalid = TRUE;
return core->transform_brush; return core->transform_brush;
} }
static TempBuf * static const TempBuf *
gimp_brush_core_transform_pixmap (GimpBrushCore *core, gimp_brush_core_transform_pixmap (GimpBrushCore *core,
GimpBrush *brush) GimpBrush *brush)
{ {
gint width; const TempBuf *pixmap;
gint height;
if (core->scale <= 0.0) if (core->scale <= 0.0)
return NULL; return NULL;
if ((core->scale == 1.0) && pixmap = gimp_brush_transform_pixmap (brush,
(core->angle == 0.0) && core->scale,
(core->hardness == 1.0) && core->aspect_ratio,
(core->aspect_ratio == 0.0)) core->angle,
return brush->pixmap; core->hardness);
gimp_brush_transform_size (brush, if (pixmap == core->transform_pixmap)
core->scale, core->aspect_ratio, core->angle, return pixmap;
&width, &height);
if (! core->cache_invalid && core->transform_pixmap = pixmap;
core->transform_pixmap && core->cache_invalid = TRUE;
brush->pixmap == core->last_transform_pixmap &&
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;
}
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_hardness = core->hardness;
core->last_aspect_ratio = core->aspect_ratio;
if (core->transform_pixmap)
temp_buf_free (core->transform_pixmap);
core->transform_pixmap = gimp_brush_transform_pixmap (brush,
core->scale,
core->aspect_ratio,
core->angle,
core->hardness);
core->cache_invalid = TRUE;
return core->transform_pixmap; return core->transform_pixmap;
} }
TempBuf * const TempBuf *
gimp_brush_core_get_brush_mask (GimpBrushCore *core, gimp_brush_core_get_brush_mask (GimpBrushCore *core,
const GimpCoords *coords, const GimpCoords *coords,
GimpBrushApplicationMode brush_hardness, GimpBrushApplicationMode brush_hardness,
gdouble dynamic_force) gdouble dynamic_force)
{ {
TempBuf *mask; const TempBuf *mask;
mask = gimp_brush_core_transform_mask (core, core->brush); mask = gimp_brush_core_transform_mask (core, core->brush);
@ -1496,29 +1413,26 @@ gimp_brush_core_get_brush_mask (GimpBrushCore *core,
switch (brush_hardness) switch (brush_hardness)
{ {
case GIMP_BRUSH_SOFT: case GIMP_BRUSH_SOFT:
mask = gimp_brush_core_subsample_mask (core, mask, return gimp_brush_core_subsample_mask (core, mask,
coords->x, coords->x,
coords->y); coords->y);
break; break;
case GIMP_BRUSH_HARD: case GIMP_BRUSH_HARD:
mask = gimp_brush_core_solidify_mask (core, mask, return gimp_brush_core_solidify_mask (core, mask,
coords->x, coords->x,
coords->y); coords->y);
break; break;
case GIMP_BRUSH_PRESSURE: case GIMP_BRUSH_PRESSURE:
mask = gimp_brush_core_pressurize_mask (core, mask, return gimp_brush_core_pressurize_mask (core, mask,
coords->x, coords->x,
coords->y, coords->y,
dynamic_force); dynamic_force);
break; break;
default:
break;
} }
return mask; g_return_val_if_reached (NULL);
} }
void void
@ -1616,17 +1530,17 @@ gimp_brush_core_color_area_with_pixmap (GimpBrushCore *core,
TempBuf *area, TempBuf *area,
GimpBrushApplicationMode mode) GimpBrushApplicationMode mode)
{ {
GimpImage *image; GimpImage *image;
PixelRegion destPR; PixelRegion destPR;
void *pr; void *pr;
guchar *d; guchar *d;
gint ulx; gint ulx;
gint uly; gint uly;
gint offsetx; gint offsetx;
gint offsety; gint offsety;
gint y; gint y;
TempBuf *pixmap_mask; const TempBuf *pixmap_mask;
TempBuf *brush_mask; const TempBuf *brush_mask;
g_return_if_fail (GIMP_IS_BRUSH (core->brush)); g_return_if_fail (GIMP_IS_BRUSH (core->brush));
g_return_if_fail (core->brush->pixmap != NULL); g_return_if_fail (core->brush->pixmap != NULL);
@ -1672,25 +1586,26 @@ gimp_brush_core_color_area_with_pixmap (GimpBrushCore *core,
for (y = 0; y < destPR.h; y++) for (y = 0; y < destPR.h; y++)
{ {
paint_line_pixmap_mask (image, drawable, pixmap_mask, brush_mask, gimp_brush_core_paint_line_pixmap_mask (image, drawable,
d, offsetx, y + offsety, pixmap_mask, brush_mask,
destPR.bytes, destPR.w, mode); d, offsetx, y + offsety,
destPR.bytes, destPR.w, mode);
d += destPR.rowstride; d += destPR.rowstride;
} }
} }
} }
static void static void
paint_line_pixmap_mask (GimpImage *dest, gimp_brush_core_paint_line_pixmap_mask (GimpImage *dest,
GimpDrawable *drawable, GimpDrawable *drawable,
TempBuf *pixmap_mask, const TempBuf *pixmap_mask,
TempBuf *brush_mask, const TempBuf *brush_mask,
guchar *d, guchar *d,
gint x, gint x,
gint y, gint y,
gint bytes, gint bytes,
gint width, gint width,
GimpBrushApplicationMode mode) GimpBrushApplicationMode mode)
{ {
const guchar *mask; const guchar *mask;
guchar *b; guchar *b;

View File

@ -55,26 +55,15 @@ struct _GimpBrushCore
TempBuf *pressure_brush; TempBuf *pressure_brush;
TempBuf *solid_brushes[BRUSH_CORE_SOLID_SUBSAMPLE][BRUSH_CORE_SOLID_SUBSAMPLE]; TempBuf *solid_brushes[BRUSH_CORE_SOLID_SUBSAMPLE][BRUSH_CORE_SOLID_SUBSAMPLE];
TempBuf *last_solid_brush; const TempBuf *last_solid_brush_mask;
gboolean solid_cache_invalid; gboolean solid_cache_invalid;
TempBuf *transform_brush; const TempBuf *transform_brush;
TempBuf *last_transform_brush; const TempBuf *transform_pixmap;
gint last_transform_width;
gint last_transform_height;
gdouble last_scale;
gdouble last_angle;
gdouble last_hardness;
gdouble last_aspect_ratio;
TempBuf *transform_pixmap;
TempBuf *last_transform_pixmap;
gint last_transform_pixmap_width;
gint last_transform_pixmap_height;
TempBuf *kernel_brushes[BRUSH_CORE_SUBSAMPLE + 1][BRUSH_CORE_SUBSAMPLE + 1]; TempBuf *kernel_brushes[BRUSH_CORE_SUBSAMPLE + 1][BRUSH_CORE_SUBSAMPLE + 1];
TempBuf *last_brush_mask; const TempBuf *last_brush_mask;
gboolean cache_invalid; gboolean cache_invalid;
gdouble jitter; gdouble jitter;
@ -93,6 +82,7 @@ struct _GimpBrushCoreClass
/* Set for tools that don't mind if the brush scales while painting */ /* Set for tools that don't mind if the brush scales while painting */
gboolean handles_transforming_brush; gboolean handles_transforming_brush;
/* Set for tools that don't mind if the brush scales mid stroke */ /* Set for tools that don't mind if the brush scales mid stroke */
gboolean handles_dynamic_transforming_brush; gboolean handles_dynamic_transforming_brush;
@ -103,48 +93,50 @@ struct _GimpBrushCoreClass
}; };
GType gimp_brush_core_get_type (void) G_GNUC_CONST; GType gimp_brush_core_get_type (void) G_GNUC_CONST;
void gimp_brush_core_set_brush (GimpBrushCore *core, void gimp_brush_core_set_brush (GimpBrushCore *core,
GimpBrush *brush); GimpBrush *brush);
void gimp_brush_core_set_dynamics (GimpBrushCore *core, void gimp_brush_core_set_dynamics (GimpBrushCore *core,
GimpDynamics *dynamics); GimpDynamics *dynamics);
void gimp_brush_core_paste_canvas (GimpBrushCore *core, void gimp_brush_core_paste_canvas (GimpBrushCore *core,
GimpDrawable *drawable, GimpDrawable *drawable,
const GimpCoords *coords, const GimpCoords *coords,
gdouble brush_opacity, gdouble brush_opacity,
gdouble image_opacity, gdouble image_opacity,
GimpLayerModeEffects paint_mode, GimpLayerModeEffects paint_mode,
GimpBrushApplicationMode brush_hardness, GimpBrushApplicationMode brush_hardness,
gdouble dynamic_hardness, gdouble dynamic_hardness,
GimpPaintApplicationMode mode); GimpPaintApplicationMode mode);
void gimp_brush_core_replace_canvas (GimpBrushCore *core, void gimp_brush_core_replace_canvas (GimpBrushCore *core,
GimpDrawable *drawable, GimpDrawable *drawable,
const GimpCoords *coords, const GimpCoords *coords,
gdouble brush_opacity, gdouble brush_opacity,
gdouble image_opacity, gdouble image_opacity,
GimpBrushApplicationMode brush_hardness, GimpBrushApplicationMode brush_hardness,
gdouble dynamic_hardness, gdouble dynamic_hardness,
GimpPaintApplicationMode mode); GimpPaintApplicationMode mode);
void gimp_brush_core_color_area_with_pixmap void gimp_brush_core_color_area_with_pixmap
(GimpBrushCore *core, (GimpBrushCore *core,
GimpDrawable *drawable, GimpDrawable *drawable,
const GimpCoords *coords, const GimpCoords *coords,
TempBuf *area, TempBuf *area,
GimpBrushApplicationMode mode); GimpBrushApplicationMode mode);
TempBuf * gimp_brush_core_get_brush_mask (GimpBrushCore *core, const TempBuf * gimp_brush_core_get_brush_mask
const GimpCoords *coords, (GimpBrushCore *core,
GimpBrushApplicationMode brush_hardness, const GimpCoords *coords,
gdouble dynamic_hardness); GimpBrushApplicationMode brush_hardness,
gdouble dynamic_hardness);
void gimp_brush_core_eval_transform_dynamics
(GimpPaintCore *paint_core,
GimpDrawable *drawable,
GimpPaintOptions *paint_options,
const GimpCoords *coords);
void gimp_brush_core_eval_transform_dynamics (GimpPaintCore *paint_core,
GimpDrawable *drawable,
GimpPaintOptions *paint_options,
const GimpCoords *coords);
#endif /* __GIMP_BRUSH_CORE_H__ */ #endif /* __GIMP_BRUSH_CORE_H__ */

View File

@ -84,7 +84,7 @@ static void gimp_heal_laplace_loop (gdouble *matrix,
static PixelRegion *gimp_heal_region (PixelRegion *tempPR, static PixelRegion *gimp_heal_region (PixelRegion *tempPR,
PixelRegion *srcPR, PixelRegion *srcPR,
TempBuf *mask_buf); const TempBuf *mask_buf);
static void gimp_heal_motion (GimpSourceCore *source_core, static void gimp_heal_motion (GimpSourceCore *source_core,
GimpDrawable *drawable, GimpDrawable *drawable,
@ -387,9 +387,9 @@ gimp_heal_laplace_loop (gdouble *matrix,
* 2005, http://www.tgeorgiev.net/ * 2005, http://www.tgeorgiev.net/
*/ */
static PixelRegion * static PixelRegion *
gimp_heal_region (PixelRegion *tempPR, gimp_heal_region (PixelRegion *tempPR,
PixelRegion *srcPR, PixelRegion *srcPR,
TempBuf *mask_buf) const TempBuf *mask_buf)
{ {
gdouble *i_1 = g_new (gdouble, tempPR->h * tempPR->bytes * tempPR->w); gdouble *i_1 = g_new (gdouble, tempPR->h * tempPR->bytes * tempPR->w);
gdouble *i_2 = g_new (gdouble, tempPR->h * tempPR->bytes * tempPR->w); gdouble *i_2 = g_new (gdouble, tempPR->h * tempPR->bytes * tempPR->w);
@ -442,7 +442,7 @@ gimp_heal_motion (GimpSourceCore *source_core,
PixelRegion tempPR; PixelRegion tempPR;
PixelRegion destPR; PixelRegion destPR;
GimpImageType src_type; GimpImageType src_type;
TempBuf *mask_buf; const TempBuf *mask_buf;
gdouble fade_point; gdouble fade_point;
gdouble hardness; gdouble hardness;

View File

@ -295,13 +295,13 @@ gimp_brush_tool_draw_brush (GimpBrushTool *brush_tool,
gdouble y, gdouble y,
gboolean draw_fallback) gboolean draw_fallback)
{ {
GimpDrawTool *draw_tool; GimpDrawTool *draw_tool;
GimpBrushCore *brush_core; GimpBrushCore *brush_core;
GimpPaintOptions *options; GimpPaintOptions *options;
GimpDisplayShell *shell; GimpDisplayShell *shell;
GimpBezierDesc *boundary = NULL; const GimpBezierDesc *boundary = NULL;
gint width = 0; gint width = 0;
gint height = 0; gint height = 0;
g_return_if_fail (GIMP_IS_BRUSH_TOOL (brush_tool)); g_return_if_fail (GIMP_IS_BRUSH_TOOL (brush_tool));
@ -353,9 +353,6 @@ gimp_brush_tool_draw_brush (GimpBrushTool *brush_tool,
x, y, x, y,
5, 5, GIMP_HANDLE_ANCHOR_CENTER); 5, 5, GIMP_HANDLE_ANCHOR_CENTER);
} }
if (boundary)
gimp_bezier_desc_free (boundary);
} }
static void static void