[gimp/gimp-2-10] app: compute line art in advance.
- From: Jehan <jehanp src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp/gimp-2-10] app: compute line art in advance.
- Date: Wed, 19 Dec 2018 15:43:03 +0000 (UTC)
commit 32f0a49ecc0f44540ebd4bf99d7ae9c78d9d4d39
Author: Jehan <jehan girinstud io>
Date: Sat Nov 3 18:40:50 2018 +0100
app: compute line art in advance.
Right now, this is mostly meaningless as it is still done sequentially.
But I am mostly preparing the field to pre-compute the line art as
background thread.
(cherry picked from commit f246f404940d7e2e54ea2a863b38970b86e198cc)
app/core/gimpchannel-select.c | 1 +
app/core/gimpdrawable-bucket-fill.c | 2 +
app/core/gimpdrawable-bucket-fill.h | 1 +
app/core/gimppickable-contiguous-region.c | 201 ++++++++++++++--------
app/core/gimppickable-contiguous-region.h | 31 ++--
app/pdb/drawable-edit-cmds.c | 2 +-
app/tools/gimpbucketfilltool.c | 270 ++++++++++++++++++++++++++++--
app/tools/gimpbucketfilltool.h | 5 +-
app/tools/gimpfuzzyselecttool.c | 2 +-
pdb/groups/drawable_edit.pdb | 2 +-
10 files changed, 421 insertions(+), 96 deletions(-)
---
diff --git a/app/core/gimpchannel-select.c b/app/core/gimpchannel-select.c
index e0cfc27354..dd6c433aee 100644
--- a/app/core/gimpchannel-select.c
+++ b/app/core/gimpchannel-select.c
@@ -516,6 +516,7 @@ gimp_channel_select_fuzzy (GimpChannel *channel,
pickable = GIMP_PICKABLE (drawable);
add_on = gimp_pickable_contiguous_region_by_seed (pickable,
+ NULL,
antialias,
threshold,
select_transparent,
diff --git a/app/core/gimpdrawable-bucket-fill.c b/app/core/gimpdrawable-bucket-fill.c
index a1a181eeb9..b5e6d7d484 100644
--- a/app/core/gimpdrawable-bucket-fill.c
+++ b/app/core/gimpdrawable-bucket-fill.c
@@ -49,6 +49,7 @@
void
gimp_drawable_bucket_fill (GimpDrawable *drawable,
+ GeglBuffer *line_art,
GimpFillOptions *options,
gboolean fill_transparent,
GimpSelectCriterion fill_criterion,
@@ -91,6 +92,7 @@ gimp_drawable_bucket_fill (GimpDrawable *drawable,
* contiguous region.
*/
mask_buffer = gimp_pickable_contiguous_region_by_seed (pickable,
+ line_art,
antialias,
threshold,
fill_transparent,
diff --git a/app/core/gimpdrawable-bucket-fill.h b/app/core/gimpdrawable-bucket-fill.h
index f79062a8fb..a614fb727d 100644
--- a/app/core/gimpdrawable-bucket-fill.h
+++ b/app/core/gimpdrawable-bucket-fill.h
@@ -20,6 +20,7 @@
void gimp_drawable_bucket_fill (GimpDrawable *drawable,
+ GeglBuffer *line_art,
GimpFillOptions *options,
gboolean fill_transparent,
GimpSelectCriterion fill_criterion,
diff --git a/app/core/gimppickable-contiguous-region.c b/app/core/gimppickable-contiguous-region.c
index d12878e631..d4c06a75a3 100644
--- a/app/core/gimppickable-contiguous-region.c
+++ b/app/core/gimppickable-contiguous-region.c
@@ -98,8 +98,103 @@ static void find_contiguous_region (GeglBuffer *src_buffer,
/* public functions */
+GeglBuffer *
+gimp_pickable_contiguous_region_prepare_line_art (GimpPickable *pickable,
+ gboolean select_transparent)
+{
+ GeglBuffer *lineart;
+ gboolean has_alpha;
+
+ g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), NULL);
+
+ gimp_pickable_flush (pickable);
+
+ lineart = gimp_pickable_get_buffer (pickable);
+ has_alpha = babl_format_has_alpha (gegl_buffer_get_format (lineart));
+
+ if (! has_alpha)
+ {
+ if (select_transparent)
+ {
+ /* don't select transparent regions if there are no fully
+ * transparent pixels.
+ */
+ GeglBufferIterator *gi;
+
+ select_transparent = FALSE;
+ gi = gegl_buffer_iterator_new (lineart, NULL, 0, babl_format ("A u8"),
+ GEGL_ACCESS_READ, GEGL_ABYSS_NONE, 3);
+ while (gegl_buffer_iterator_next (gi))
+ {
+ guint8 *p = (guint8*) gi->items[0].data;
+ gint k;
+
+ for (k = 0; k < gi->length; k++)
+ {
+ if (! *p)
+ {
+ select_transparent = TRUE;
+ break;
+ }
+ p++;
+ }
+ if (select_transparent)
+ break;
+ }
+ if (select_transparent)
+ gegl_buffer_iterator_stop (gi);
+ }
+ }
+ else
+ {
+ select_transparent = FALSE;
+ }
+
+ /* For smart selection, we generate a binarized image with close
+ * regions, then run a composite selection with no threshold on
+ * this intermediate buffer.
+ */
+ GIMP_TIMER_START();
+
+ lineart = gimp_lineart_close (lineart,
+ select_transparent,
+ /*contour_detection_level,*/
+ 0.92,
+ /* erosion, */
+ -1,
+ /*minimal_lineart_area,*/
+ 5,
+ /*normal_estimate_mask_size,*/
+ 5,
+ /*end_point_rate,*/
+ 0.85,
+ /*spline_max_length,*/
+ 60,
+ /*spline_max_angle,*/
+ 90.0,
+ /*end_point_connectivity,*/
+ 2,
+ /*spline_roundness,*/
+ 1.0,
+ /*allow_self_intersections,*/
+ TRUE,
+ /*created_regions_significant_area,*/
+ 4,
+ /*created_regions_minimum_area,*/
+ 100,
+ /*small_segments_from_spline_sources,*/
+ TRUE,
+ /*segments_max_length*/
+ 20);
+
+ GIMP_TIMER_END("close line-art");
+
+ return lineart;
+}
+
GeglBuffer *
gimp_pickable_contiguous_region_by_seed (GimpPickable *pickable,
+ GeglBuffer *line_art,
gboolean antialias,
gfloat threshold,
gboolean select_transparent,
@@ -115,89 +210,61 @@ gimp_pickable_contiguous_region_by_seed (GimpPickable *pickable,
gint n_components;
gboolean has_alpha;
gfloat start_col[MAX_CHANNELS];
+ gfloat flag = 2.0;
gboolean smart_line_art = FALSE;
- gfloat flag = 2.0;
+ gboolean free_line_art = FALSE;
g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), NULL);
- gimp_pickable_flush (pickable);
-
- src_buffer = gimp_pickable_get_buffer (pickable);
-
- format = choose_format (src_buffer, select_criterion,
- &n_components, &has_alpha);
-
- gegl_buffer_sample (src_buffer, x, y, NULL, start_col, format,
- GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE);
-
- if (has_alpha)
+ if (select_criterion == GIMP_SELECT_CRITERION_LINE_ART)
{
- if (select_transparent)
+ if (line_art == NULL)
{
- /* don't select transparent regions if the start pixel isn't
- * fully transparent
+ /* It is much better experience to pre-compute the line art,
+ * but it may not be always possible (for instance when
+ * selecting/filling through a PDB call).
*/
- if (start_col[n_components - 1] > 0)
- select_transparent = FALSE;
+ line_art = gimp_pickable_contiguous_region_prepare_line_art (pickable, select_transparent);
+ free_line_art = TRUE;
}
- }
- else
- {
- select_transparent = FALSE;
- }
- if (select_criterion == GIMP_SELECT_CRITERION_LINE_ART)
- {
- /* For smart selection, we generate a binarized image with close
- * regions, then run a composite selection with no threshold on
- * this intermediate buffer.
- */
- GIMP_TIMER_START();
- src_buffer = gimp_lineart_close (src_buffer,
- select_transparent,
- /*contour_detection_level,*/
- 0.92,
- /* erosion, */
- -1,
- /*minimal_lineart_area,*/
- 5,
- /*normal_estimate_mask_size,*/
- 5,
- /*end_point_rate,*/
- 0.85,
- /*spline_max_length,*/
- 60,
- /*spline_max_angle,*/
- 90.0,
- /*end_point_connectivity,*/
- 2,
- /*spline_roundness,*/
- 1.0,
- /*allow_self_intersections,*/
- TRUE,
- /*created_regions_significant_area,*/
- 4,
- /*created_regions_minimum_area,*/
- 100,
- /*small_segments_from_spline_sources,*/
- TRUE,
- /*segments_max_length*/
- 20);
+ src_buffer = line_art;
+
smart_line_art = TRUE;
antialias = FALSE;
threshold = 0.0;
select_transparent = FALSE;
select_criterion = GIMP_SELECT_CRITERION_COMPOSITE;
diagonal_neighbors = FALSE;
+ }
+ else
+ {
+ gimp_pickable_flush (pickable);
+ src_buffer = gimp_pickable_get_buffer (pickable);
- format = choose_format (src_buffer, select_criterion,
- &n_components, &has_alpha);
- gegl_buffer_sample (src_buffer, x, y, NULL, start_col, format,
- GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE);
-
- GIMP_TIMER_END("close line-art");
+ if (has_alpha)
+ {
+ if (select_transparent)
+ {
+ /* don't select transparent regions if the start pixel isn't
+ * fully transparent
+ */
+ if (start_col[n_components - 1] > 0)
+ select_transparent = FALSE;
+ }
+ }
+ else
+ {
+ select_transparent = FALSE;
+ }
}
+ format = choose_format (src_buffer, select_criterion,
+ &n_components, &has_alpha);
+
+ gegl_buffer_sample (src_buffer, x, y, NULL, start_col, format,
+ GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE);
+
extent = *gegl_buffer_get_extent (src_buffer);
mask_buffer = gegl_buffer_new (&extent, babl_format ("Y float"));
@@ -271,7 +338,6 @@ gimp_pickable_contiguous_region_by_seed (GimpPickable *pickable,
prio++;
}
}
- g_object_unref (src_buffer);
/* Watershed the line art. */
graph = gegl_node_new ();
@@ -297,6 +363,9 @@ gimp_pickable_contiguous_region_by_seed (GimpPickable *pickable,
g_object_unref (priomap);
GIMP_TIMER_END("watershed line art");
+
+ if (free_line_art)
+ g_object_unref (src_buffer);
}
return mask_buffer;
diff --git a/app/core/gimppickable-contiguous-region.h b/app/core/gimppickable-contiguous-region.h
index 6db86248bb..7f8d693d92 100644
--- a/app/core/gimppickable-contiguous-region.h
+++ b/app/core/gimppickable-contiguous-region.h
@@ -19,21 +19,24 @@
#define __GIMP_PICKABLE_CONTIGUOUS_REGION_H__
-GeglBuffer * gimp_pickable_contiguous_region_by_seed (GimpPickable *pickable,
- gboolean antialias,
- gfloat threshold,
- gboolean select_transparent,
- GimpSelectCriterion select_criterion,
- gboolean diagonal_neighbors,
- gint x,
- gint y);
+GeglBuffer * gimp_pickable_contiguous_region_prepare_line_art (GimpPickable *pickable,
+ gboolean select_transparent);
+GeglBuffer * gimp_pickable_contiguous_region_by_seed (GimpPickable *pickable,
+ GeglBuffer *line_art,
+ gboolean antialias,
+ gfloat threshold,
+ gboolean select_transparent,
+ GimpSelectCriterion select_criterion,
+ gboolean diagonal_neighbors,
+ gint x,
+ gint y);
-GeglBuffer * gimp_pickable_contiguous_region_by_color (GimpPickable *pickable,
- gboolean antialias,
- gfloat threshold,
- gboolean select_transparent,
- GimpSelectCriterion select_criterion,
- const GimpRGB *color);
+GeglBuffer * gimp_pickable_contiguous_region_by_color (GimpPickable *pickable,
+ gboolean antialias,
+ gfloat threshold,
+ gboolean select_transparent,
+ GimpSelectCriterion select_criterion,
+ const GimpRGB *color);
#endif /* __GIMP_PICKABLE_CONTIGUOUS_REGION_H__ */
diff --git a/app/pdb/drawable-edit-cmds.c b/app/pdb/drawable-edit-cmds.c
index 43ac00a7e6..a5212bb1cd 100644
--- a/app/pdb/drawable-edit-cmds.c
+++ b/app/pdb/drawable-edit-cmds.c
@@ -165,7 +165,7 @@ drawable_edit_bucket_fill_invoker (GimpProcedure *procedure,
if (gimp_fill_options_set_by_fill_type (options, context,
fill_type, error))
{
- gimp_drawable_bucket_fill (drawable, options,
+ gimp_drawable_bucket_fill (drawable, NULL, options,
GIMP_PDB_CONTEXT (context)->sample_transparent,
GIMP_PDB_CONTEXT (context)->sample_criterion,
GIMP_PDB_CONTEXT (context)->sample_threshold,
diff --git a/app/tools/gimpbucketfilltool.c b/app/tools/gimpbucketfilltool.c
index ee55344ab6..41a0f95825 100644
--- a/app/tools/gimpbucketfilltool.c
+++ b/app/tools/gimpbucketfilltool.c
@@ -31,6 +31,9 @@
#include "core/gimpfilloptions.h"
#include "core/gimpimage.h"
#include "core/gimpitem.h"
+#include "core/gimplineart.h"
+#include "core/gimppickable.h"
+#include "core/gimppickable-contiguous-region.h"
#include "widgets/gimphelp-ids.h"
#include "widgets/gimpwidgets-utils.h"
@@ -45,8 +48,18 @@
#include "gimp-intl.h"
+struct _GimpBucketFillToolPrivate
+{
+ GeglBuffer *line_art;
+ GWeakRef cached_image;
+ GWeakRef cached_drawable;
+};
+
/* local function prototypes */
+static void gimp_bucket_fill_tool_constructed (GObject *object);
+static void gimp_bucket_fill_tool_finalize (GObject *object);
+
static gboolean gimp_bucket_fill_tool_initialize (GimpTool *tool,
GimpDisplay *display,
GError **error);
@@ -66,8 +79,25 @@ static void gimp_bucket_fill_tool_cursor_update (GimpTool *tool,
GdkModifierType state,
GimpDisplay *display);
-
-G_DEFINE_TYPE (GimpBucketFillTool, gimp_bucket_fill_tool, GIMP_TYPE_TOOL)
+static void gimp_bucket_fill_compute_line_art (GimpBucketFillTool *tool);
+static gboolean gimp_bucket_fill_tool_connect_handlers (gpointer data);
+static void gimp_bucket_fill_tool_options_notified (GimpBucketFillOptions *options,
+ GParamSpec *pspec,
+ GimpBucketFillTool *tool);
+static void gimp_bucket_fill_tool_image_changed (GimpContext *context,
+ GimpImage *image,
+ GimpBucketFillTool *tool);
+static void gimp_bucket_fill_tool_drawable_changed (GimpImage *image,
+ GimpBucketFillTool *tool);
+static void gimp_bucket_fill_tool_drawable_update (GimpDrawable *drawable,
+ gint x,
+ gint y,
+ gint width,
+ gint height,
+ GimpBucketFillTool *tool);
+
+
+G_DEFINE_TYPE_WITH_PRIVATE (GimpBucketFillTool, gimp_bucket_fill_tool, GIMP_TYPE_TOOL)
#define parent_class gimp_bucket_fill_tool_parent_class
@@ -96,7 +126,11 @@ gimp_bucket_fill_tool_register (GimpToolRegisterCallback callback,
static void
gimp_bucket_fill_tool_class_init (GimpBucketFillToolClass *klass)
{
- GimpToolClass *tool_class = GIMP_TOOL_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GimpToolClass *tool_class = GIMP_TOOL_CLASS (klass);
+
+ object_class->constructed = gimp_bucket_fill_tool_constructed;
+ object_class->finalize = gimp_bucket_fill_tool_finalize;
tool_class->initialize = gimp_bucket_fill_tool_initialize;
tool_class->button_release = gimp_bucket_fill_tool_button_release;
@@ -117,6 +151,58 @@ gimp_bucket_fill_tool_init (GimpBucketFillTool *bucket_fill_tool)
"context/context-opacity-set");
gimp_tool_control_set_action_object_1 (tool->control,
"context/context-pattern-select-set");
+
+ bucket_fill_tool->priv = gimp_bucket_fill_tool_get_instance_private (bucket_fill_tool);
+}
+
+static void
+gimp_bucket_fill_tool_constructed (GObject *object)
+{
+ GimpTool *tool = GIMP_TOOL (object);
+ GimpBucketFillOptions *options = GIMP_BUCKET_FILL_TOOL_GET_OPTIONS (object);
+ Gimp *gimp = GIMP_CONTEXT (options)->gimp;
+
+ G_OBJECT_CLASS (parent_class)->constructed (object);
+
+ /* Avoid computing initial line art several times (for every option
+ * property as it gets deserialized) if tool is selected when starting
+ * GIMP with an image.
+ */
+ if (gimp_is_restored (gimp))
+ gimp_bucket_fill_tool_connect_handlers (tool);
+ else
+ g_idle_add (gimp_bucket_fill_tool_connect_handlers, tool);
+}
+
+static void
+gimp_bucket_fill_tool_finalize (GObject *object)
+{
+ GimpBucketFillTool *tool = GIMP_BUCKET_FILL_TOOL (object);
+ GimpBucketFillOptions *options = GIMP_BUCKET_FILL_TOOL_GET_OPTIONS (tool);
+ Gimp *gimp = GIMP_CONTEXT (options)->gimp;
+ GimpContext *context = gimp_get_user_context (gimp);
+ GimpImage *image = g_weak_ref_get (&tool->priv->cached_image);
+ GimpDrawable *drawable = g_weak_ref_get (&tool->priv->cached_drawable);
+
+ g_clear_object (&tool->priv->line_art);
+
+ if (image)
+ {
+ g_signal_handlers_disconnect_by_data (image, tool);
+ g_object_unref (image);
+ }
+ if (drawable)
+ {
+ g_signal_handlers_disconnect_by_data (drawable, tool);
+ g_object_unref (drawable);
+ }
+
+ g_signal_handlers_disconnect_by_func (options,
+ G_CALLBACK (gimp_bucket_fill_tool_options_notified),
+ tool);
+ g_signal_handlers_disconnect_by_data (context, tool);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
}
static gboolean
@@ -124,8 +210,19 @@ gimp_bucket_fill_tool_initialize (GimpTool *tool,
GimpDisplay *display,
GError **error)
{
- GimpImage *image = gimp_display_get_image (display);
- GimpDrawable *drawable = gimp_image_get_active_drawable (image);
+ GimpBucketFillTool *bucket_tool = GIMP_BUCKET_FILL_TOOL (tool);
+ GimpBucketFillOptions *options = GIMP_BUCKET_FILL_TOOL_GET_OPTIONS (bucket_tool);
+ GimpImage *image = gimp_display_get_image (display);
+ GimpDrawable *drawable = gimp_image_get_active_drawable (image);
+
+ if (options->fill_criterion == GIMP_SELECT_CRITERION_LINE_ART)
+ {
+ GimpImage *prev_image = g_weak_ref_get (&bucket_tool->priv->cached_image);
+ GimpDrawable *prev_drawable = g_weak_ref_get (&bucket_tool->priv->cached_drawable);
+ g_return_val_if_fail (image == prev_image && drawable == prev_drawable, FALSE);
+ g_object_unref (prev_drawable);
+ g_object_unref (prev_image);
+ }
if (! GIMP_TOOL_CLASS (parent_class)->initialize (tool, display, error))
{
@@ -139,19 +236,19 @@ gimp_bucket_fill_tool_initialize (GimpTool *tool,
return FALSE;
}
- if (gimp_item_is_content_locked (GIMP_ITEM (drawable)))
+ if (! gimp_item_is_visible (GIMP_ITEM (drawable)))
{
g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
- _("The active layer's pixels are locked."));
- if (error)
- gimp_tools_blink_lock_box (display->gimp, GIMP_ITEM (drawable));
+ _("The active layer is not visible."));
return FALSE;
}
- if (! gimp_item_is_visible (GIMP_ITEM (drawable)))
+ if (gimp_item_is_content_locked (GIMP_ITEM (drawable)))
{
g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
- _("The active layer is not visible."));
+ _("The active layer's pixels are locked."));
+ if (error)
+ gimp_tools_blink_lock_box (display->gimp, GIMP_ITEM (drawable));
return FALSE;
}
@@ -211,7 +308,10 @@ gimp_bucket_fill_tool_button_release (GimpTool *tool,
y -= off_y;
}
- gimp_drawable_bucket_fill (drawable, fill_options,
+
+ gimp_drawable_bucket_fill (drawable,
+ GIMP_BUCKET_FILL_TOOL (tool)->priv->line_art,
+ fill_options,
options->fill_transparent,
options->fill_criterion,
options->threshold / 255.0,
@@ -310,3 +410,149 @@ gimp_bucket_fill_tool_cursor_update (GimpTool *tool,
GIMP_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, display);
}
+
+static void
+gimp_bucket_fill_compute_line_art (GimpBucketFillTool *tool)
+{
+ GimpBucketFillOptions *options = GIMP_BUCKET_FILL_TOOL_GET_OPTIONS (tool);
+
+ g_clear_object (&tool->priv->line_art);
+ if (options->fill_criterion == GIMP_SELECT_CRITERION_LINE_ART)
+ {
+ GimpPickable *pickable = NULL;
+ GimpDrawable *image = g_weak_ref_get (&tool->priv->cached_image);
+ GimpDrawable *drawable = g_weak_ref_get (&tool->priv->cached_drawable);
+
+ if (image && options->sample_merged)
+ pickable = GIMP_PICKABLE (image);
+ else if (drawable && ! options->sample_merged)
+ pickable = GIMP_PICKABLE (drawable);
+
+ if (pickable)
+ tool->priv->line_art = gimp_pickable_contiguous_region_prepare_line_art (pickable,
+ options->fill_transparent);
+ if (image)
+ g_object_unref (image);
+ if (drawable)
+ g_object_unref (drawable);
+ }
+}
+
+static gboolean
+gimp_bucket_fill_tool_connect_handlers (gpointer data)
+{
+ GimpBucketFillTool *tool = GIMP_BUCKET_FILL_TOOL (data);
+ GimpBucketFillOptions *options = GIMP_BUCKET_FILL_TOOL_GET_OPTIONS (tool);
+ Gimp *gimp = GIMP_CONTEXT (options)->gimp;
+
+ if (gimp_is_restored (gimp))
+ {
+ GimpContext *context = gimp_get_user_context (gimp);
+ GimpImage *image = gimp_context_get_image (context);
+
+ g_signal_connect (options, "notify::fill-criterion",
+ G_CALLBACK (gimp_bucket_fill_tool_options_notified),
+ tool);
+ g_signal_connect (options, "notify::sample-merged",
+ G_CALLBACK (gimp_bucket_fill_tool_options_notified),
+ tool);
+ g_signal_connect (options, "notify::fill-transparent",
+ G_CALLBACK (gimp_bucket_fill_tool_options_notified),
+ tool);
+
+ g_signal_connect (context, "image-changed",
+ G_CALLBACK (gimp_bucket_fill_tool_image_changed),
+ tool);
+ gimp_bucket_fill_tool_image_changed (context, image, GIMP_BUCKET_FILL_TOOL (tool));
+
+ return G_SOURCE_REMOVE;
+ }
+ return G_SOURCE_CONTINUE;
+}
+
+static void
+gimp_bucket_fill_tool_options_notified (GimpBucketFillOptions *options,
+ GParamSpec *pspec,
+ GimpBucketFillTool *tool)
+{
+ if ((! strcmp (pspec->name, "fill-criterion") ||
+ ! strcmp (pspec->name, "fill-transparent") ||
+ ! strcmp (pspec->name, "sample-merged")) &&
+ options->fill_criterion == GIMP_SELECT_CRITERION_LINE_ART)
+ {
+ gimp_bucket_fill_compute_line_art (tool);
+ }
+}
+
+static void
+gimp_bucket_fill_tool_image_changed (GimpContext *context,
+ GimpImage *image,
+ GimpBucketFillTool *tool)
+{
+ GimpImage *prev_image = g_weak_ref_get (&tool->priv->cached_image);
+
+ if (image != prev_image)
+ {
+ GimpImage *prev_drawable = g_weak_ref_get (&tool->priv->cached_drawable);
+
+ g_clear_object (&tool->priv->line_art);
+
+ if (prev_image)
+ g_signal_handlers_disconnect_by_data (prev_image, tool);
+ if (prev_drawable)
+ {
+ g_signal_handlers_disconnect_by_data (prev_drawable, tool);
+ g_object_unref (prev_drawable);
+ }
+
+ g_weak_ref_set (&tool->priv->cached_image, image ? image : NULL);
+ g_weak_ref_set (&tool->priv->cached_drawable, NULL);
+ if (image)
+ {
+ g_signal_connect (image, "active-layer-changed",
+ G_CALLBACK (gimp_bucket_fill_tool_drawable_changed),
+ tool);
+ g_signal_connect (image, "active-channel-changed",
+ G_CALLBACK (gimp_bucket_fill_tool_drawable_changed),
+ tool);
+ gimp_bucket_fill_tool_drawable_changed (image, tool);
+ }
+ }
+ if (prev_image)
+ g_object_unref (prev_image);
+}
+
+static void
+gimp_bucket_fill_tool_drawable_changed (GimpImage *image,
+ GimpBucketFillTool *tool)
+{
+ GimpDrawable *drawable = gimp_image_get_active_drawable (image);
+ GimpDrawable *prev_drawable = g_weak_ref_get (&tool->priv->cached_drawable);
+
+ if (drawable != prev_drawable)
+ {
+ if (prev_drawable)
+ g_signal_handlers_disconnect_by_data (prev_drawable, tool);
+
+ g_weak_ref_set (&tool->priv->cached_drawable, drawable ? drawable : NULL);
+ if (drawable)
+ g_signal_connect (drawable, "update",
+ G_CALLBACK (gimp_bucket_fill_tool_drawable_update),
+ tool);
+
+ gimp_bucket_fill_compute_line_art (tool);
+ }
+ if (prev_drawable)
+ g_object_unref (prev_drawable);
+}
+
+static void
+gimp_bucket_fill_tool_drawable_update (GimpDrawable *drawable,
+ gint x,
+ gint y,
+ gint width,
+ gint height,
+ GimpBucketFillTool *tool)
+{
+ gimp_bucket_fill_compute_line_art (tool);
+}
diff --git a/app/tools/gimpbucketfilltool.h b/app/tools/gimpbucketfilltool.h
index 8ce8eb02f1..0b7b8279c0 100644
--- a/app/tools/gimpbucketfilltool.h
+++ b/app/tools/gimpbucketfilltool.h
@@ -34,10 +34,13 @@
typedef struct _GimpBucketFillTool GimpBucketFillTool;
typedef struct _GimpBucketFillToolClass GimpBucketFillToolClass;
+typedef struct _GimpBucketFillToolPrivate GimpBucketFillToolPrivate;
struct _GimpBucketFillTool
{
- GimpTool parent_instance;
+ GimpTool parent_instance;
+
+ GimpBucketFillToolPrivate *priv;
};
struct _GimpBucketFillToolClass
diff --git a/app/tools/gimpfuzzyselecttool.c b/app/tools/gimpfuzzyselecttool.c
index 785804a27b..b3eee7d196 100644
--- a/app/tools/gimpfuzzyselecttool.c
+++ b/app/tools/gimpfuzzyselecttool.c
@@ -122,7 +122,7 @@ gimp_fuzzy_select_tool_get_mask (GimpRegionSelectTool *region_select,
pickable = GIMP_PICKABLE (image);
}
- return gimp_pickable_contiguous_region_by_seed (pickable,
+ return gimp_pickable_contiguous_region_by_seed (pickable, NULL,
sel_options->antialias,
options->threshold / 255.0,
options->select_transparent,
diff --git a/pdb/groups/drawable_edit.pdb b/pdb/groups/drawable_edit.pdb
index 52ab64b6e5..79b8c395c5 100644
--- a/pdb/groups/drawable_edit.pdb
+++ b/pdb/groups/drawable_edit.pdb
@@ -169,7 +169,7 @@ HELP
if (gimp_fill_options_set_by_fill_type (options, context,
fill_type, error))
{
- gimp_drawable_bucket_fill (drawable, options,
+ gimp_drawable_bucket_fill (drawable, NULL, options,
GIMP_PDB_CONTEXT (context)->sample_transparent,
GIMP_PDB_CONTEXT (context)->sample_criterion,
GIMP_PDB_CONTEXT (context)->sample_threshold,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]