[gimp/multi-stroke: 7/31] app: cache more than 1 brush.
- From: Jehan Pagès <jehanp src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp/multi-stroke: 7/31] app: cache more than 1 brush.
- Date: Thu, 8 Oct 2015 19:03:31 +0000 (UTC)
commit 366669416f45a14fd9a712f40bfb0235a8985b19
Author: Jehan <jehan girinstud io>
Date: Sat Mar 21 19:00:59 2015 +0100
app: cache more than 1 brush.
This allows to reuse brush cache after dynamic changes, and also
allows the multi stroke feature to not constantly invalidate its cache
when GEGL operations are used.
app/core/gimpbrushcache.c | 121 ++++++++++++++++++++++++++++++++++-----------
app/core/gimpbrushcache.h | 9 +---
app/paint/gimpmirror.c | 112 +++++++++++++++++++++++++++--------------
app/paint/gimpmirror.h | 7 +++
4 files changed, 173 insertions(+), 76 deletions(-)
---
diff --git a/app/core/gimpbrushcache.c b/app/core/gimpbrushcache.c
index 38c0aba..11c74b8 100644
--- a/app/core/gimpbrushcache.c
+++ b/app/core/gimpbrushcache.c
@@ -29,6 +29,7 @@
#include "gimp-log.h"
#include "gimp-intl.h"
+#define MAX_CACHED_DATA 20
enum
{
@@ -36,6 +37,20 @@ enum
PROP_DATA_DESTROY
};
+typedef struct _GimpBrushCacheUnit GimpBrushCacheUnit;
+
+struct _GimpBrushCacheUnit
+{
+ gpointer data;
+
+ gint width;
+ gint height;
+ gdouble scale;
+ gdouble aspect_ratio;
+ gdouble angle;
+ gdouble hardness;
+ GeglNode *op;
+};
static void gimp_brush_cache_constructed (GObject *object);
static void gimp_brush_cache_finalize (GObject *object);
@@ -91,10 +106,18 @@ gimp_brush_cache_finalize (GObject *object)
{
GimpBrushCache *cache = GIMP_BRUSH_CACHE (object);
- if (cache->last_data)
+ if (cache->cached_units)
{
- cache->data_destroy (cache->last_data);
- cache->last_data = NULL;
+ GList *iter;
+
+ for (iter = cache->cached_units; iter; iter = g_list_next (iter))
+ {
+ GimpBrushCacheUnit *unit = iter->data;
+
+ cache->data_destroy (unit->data);
+ }
+ g_list_free_full (cache->cached_units, g_free);
+ cache->cached_units = NULL;
}
G_OBJECT_CLASS (parent_class)->finalize (object);
@@ -167,10 +190,18 @@ gimp_brush_cache_clear (GimpBrushCache *cache)
{
g_return_if_fail (GIMP_IS_BRUSH_CACHE (cache));
- if (cache->last_data)
+ if (cache->cached_units)
{
- cache->data_destroy (cache->last_data);
- cache->last_data = NULL;
+ GList *iter;
+
+ for (iter = cache->cached_units; iter; iter = g_list_next (iter))
+ {
+ GimpBrushCacheUnit *unit = iter->data;
+
+ cache->data_destroy (unit->data);
+ }
+ g_list_free_full (cache->cached_units, g_free);
+ cache->cached_units = NULL;
}
}
@@ -184,21 +215,34 @@ gimp_brush_cache_get (GimpBrushCache *cache,
gdouble angle,
gdouble hardness)
{
+ GList *iter;
+
g_return_val_if_fail (GIMP_IS_BRUSH_CACHE (cache), NULL);
- if (cache->last_data &&
- cache->last_op == op &&
- 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)
+ for (iter = cache->cached_units; iter; iter = g_list_next (iter))
{
- if (gimp_log_flags & GIMP_LOG_BRUSH_CACHE)
- g_printerr ("%c", cache->debug_hit);
-
- return (gconstpointer) cache->last_data;
+ GimpBrushCacheUnit *unit = iter->data;
+
+ if (unit->data &&
+ unit->width == width &&
+ unit->height == height &&
+ unit->scale == scale &&
+ unit->aspect_ratio == aspect_ratio &&
+ unit->angle == angle &&
+ unit->hardness == hardness &&
+ unit->op == op)
+ {
+ if (gimp_log_flags & GIMP_LOG_BRUSH_CACHE)
+ g_printerr ("%c", cache->debug_hit);
+
+ /* Make the returned cached brush first in the list. */
+ cache->cached_units = g_list_remove_link (cache->cached_units, iter);
+ iter->next = cache->cached_units;
+ if (cache->cached_units)
+ cache->cached_units->prev = iter;
+ cache->cached_units = iter;
+ return (gconstpointer) unit->data;
+ }
}
if (gimp_log_flags & GIMP_LOG_BRUSH_CACHE)
@@ -218,21 +262,38 @@ gimp_brush_cache_add (GimpBrushCache *cache,
gdouble angle,
gdouble hardness)
{
+ GList *iter;
+ GimpBrushCacheUnit *unit;
+
g_return_if_fail (GIMP_IS_BRUSH_CACHE (cache));
g_return_if_fail (data != NULL);
- if (data == cache->last_data)
- return;
+ for (iter = cache->cached_units; iter; iter = g_list_next (iter))
+ {
+ unit = iter->data;
+ if (data == unit->data)
+ return;
+ }
+
+ if (g_list_length (cache->cached_units) > MAX_CACHED_DATA &&
+ (iter = g_list_last (cache->cached_units)))
+ {
+ unit = iter->data;
+
+ cache->data_destroy (unit->data);
+ cache->cached_units = g_list_delete_link (cache->cached_units, iter);
+ }
+
+ unit = g_new (GimpBrushCacheUnit, 1);
- if (cache->last_data)
- cache->data_destroy (cache->last_data);
+ unit->data = data;
+ unit->width = width;
+ unit->height = height;
+ unit->scale = scale;
+ unit->aspect_ratio = aspect_ratio;
+ unit->angle = angle;
+ unit->hardness = hardness;
+ unit->op = op;
- cache->last_data = data;
- cache->last_op = op;
- 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;
+ cache->cached_units = g_list_prepend (cache->cached_units, unit);
}
diff --git a/app/core/gimpbrushcache.h b/app/core/gimpbrushcache.h
index c529388..6fa48ec 100644
--- a/app/core/gimpbrushcache.h
+++ b/app/core/gimpbrushcache.h
@@ -41,14 +41,7 @@ struct _GimpBrushCache
GDestroyNotify data_destroy;
- gpointer last_data;
- GeglNode *last_op;
- gint last_width;
- gint last_height;
- gdouble last_scale;
- gdouble last_aspect_ratio;
- gdouble last_angle;
- gdouble last_hardness;
+ GList *cached_units;
gchar debug_hit;
gchar debug_miss;
diff --git a/app/paint/gimpmirror.c b/app/paint/gimpmirror.c
index b40a019..ce1808d 100644
--- a/app/paint/gimpmirror.c
+++ b/app/paint/gimpmirror.c
@@ -69,6 +69,9 @@ static void gimp_mirror_get_property (GObject *object,
static void gimp_mirror_update_strokes (GimpMultiStroke *mirror,
GimpDrawable *drawable,
GimpCoords *origin);
+static void gimp_mirror_prepare_operations (GimpMirror *mirror,
+ gint paint_width,
+ gint paint_height);
static GeglNode * gimp_mirror_get_operation (GimpMultiStroke *mirror,
gint stroke,
gint paint_width,
@@ -169,6 +172,18 @@ gimp_mirror_finalize (GObject *object)
g_object_unref (mirror->vertical_guide);
mirror->vertical_guide = NULL;
+ if (mirror->horizontal_op)
+ g_object_unref (mirror->horizontal_op);
+ mirror->horizontal_op = NULL;
+
+ if (mirror->vertical_op)
+ g_object_unref (mirror->vertical_op);
+ mirror->vertical_op = NULL;
+
+ if (mirror->central_op)
+ g_object_unref (mirror->central_op);
+ mirror->central_op = NULL;
+
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@@ -286,6 +301,59 @@ gimp_mirror_update_strokes (GimpMultiStroke *mstroke,
g_signal_emit_by_name (mstroke, "strokes-updated", mstroke->image);
}
+static void gimp_mirror_prepare_operations (GimpMirror *mirror,
+ gint paint_width,
+ gint paint_height)
+{
+ if (paint_width == mirror->last_paint_width &&
+ paint_height == mirror->last_paint_height)
+ return;
+
+ mirror->last_paint_width = paint_width;
+ mirror->last_paint_height = paint_height;
+
+ if (mirror->horizontal_op)
+ g_object_unref (mirror->horizontal_op);
+
+ mirror->horizontal_op = gegl_node_new_child (NULL,
+ "operation", "gegl:reflect",
+ "origin-x", 0.0,
+ "origin-y",
+ (gdouble) paint_height / 2.0,
+ "x",
+ 1.0,
+ "y",
+ 0.0,
+ NULL);
+
+ if (mirror->vertical_op)
+ g_object_unref (mirror->vertical_op);
+
+ mirror->vertical_op = gegl_node_new_child (NULL,
+ "operation", "gegl:reflect",
+ "origin-x",
+ (gdouble) paint_width / 2.0,
+ "origin-y", 0.0,
+ "x",
+ 0.0,
+ "y",
+ 1.0,
+ NULL);
+
+ if (mirror->central_op)
+ g_object_unref (mirror->central_op);
+
+ mirror->central_op = gegl_node_new_child (NULL,
+ "operation", "gegl:rotate",
+ "origin-x",
+ (gdouble) paint_width / 2.0,
+ "origin-y",
+ (gdouble) paint_height / 2.0,
+ "degrees",
+ 180.0,
+ NULL);
+}
+
static GeglNode *
gimp_mirror_get_operation (GimpMultiStroke *mstroke,
gint stroke,
@@ -298,52 +366,20 @@ gimp_mirror_get_operation (GimpMultiStroke *mstroke,
g_return_val_if_fail (stroke >= 0 &&
stroke < g_list_length (mstroke->strokes), NULL);
+ gimp_mirror_prepare_operations (mirror, paint_width, paint_height);
+
if (mirror->disable_transformation || stroke == 0 ||
paint_width == 0 || paint_height == 0)
- {
- op = NULL;
- }
+ op = NULL;
else if (stroke == 1 && mirror->horizontal_mirror)
- {
- op = gegl_node_new_child (NULL,
- "operation", "gegl:reflect",
- "origin-x", 0.0,
- "origin-y",
- (gdouble) paint_height / 2.0,
- "x",
- 1.0,
- "y",
- 0.0,
- NULL);
- }
+ op = g_object_ref (mirror->horizontal_op);
else if ((stroke == 2 && mirror->horizontal_mirror &&
mirror->vertical_mirror) ||
(stroke == 1 && mirror->vertical_mirror &&
! mirror->horizontal_mirror))
- {
- op = gegl_node_new_child (NULL,
- "operation", "gegl:reflect",
- "origin-x",
- (gdouble) paint_width / 2.0,
- "origin-y", 0.0,
- "x",
- 0.0,
- "y",
- 1.0,
- NULL);
- }
+ op = g_object_ref (mirror->vertical_op);
else
- {
- op = gegl_node_new_child (NULL,
- "operation", "gegl:rotate",
- "origin-x",
- (gdouble) paint_width / 2.0,
- "origin-y",
- (gdouble) paint_height / 2.0,
- "degrees",
- 180.0,
- NULL);
- }
+ op = g_object_ref (mirror->central_op);
return op;
}
diff --git a/app/paint/gimpmirror.h b/app/paint/gimpmirror.h
index 0ee9537..9e0004c 100644
--- a/app/paint/gimpmirror.h
+++ b/app/paint/gimpmirror.h
@@ -47,6 +47,13 @@ struct _GimpMirror
gdouble vertical_position;
GimpMirrorGuide *horizontal_guide;
GimpMirrorGuide *vertical_guide;
+
+ /* Cached data */
+ gint last_paint_width;
+ gint last_paint_height;
+ GeglNode *horizontal_op;
+ GeglNode *vertical_op;
+ GeglNode *central_op;
};
struct _GimpMirrorClass
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]