diff --git a/app/core/gimppickable-contiguous-region.c b/app/core/gimppickable-contiguous-region.c index 38a0f2ed0a..0187734616 100644 --- a/app/core/gimppickable-contiguous-region.c +++ b/app/core/gimppickable-contiguous-region.c @@ -31,12 +31,22 @@ #include "gegl/gimp-babl.h" +#include "gimp-parallel.h" #include "gimp-utils.h" /* GIMP_TIMER */ +#include "gimpasync.h" #include "gimplineart.h" #include "gimppickable.h" #include "gimppickable-contiguous-region.h" +typedef struct +{ + GeglBuffer *buffer; + gboolean select_transparent; + gfloat stroke_threshold; +} LineArtData; + + /* local function prototypes */ static const Babl * choose_format (GeglBuffer *buffer, @@ -96,41 +106,52 @@ static void find_contiguous_region (GeglBuffer *src_buffer, gint y, const gfloat *col); +static LineArtData * line_art_data_new (GeglBuffer *buffer, + gboolean select_transparent, + gfloat stroke_threshold); +static void line_art_data_free (LineArtData *data); + /* public functions */ -GeglBuffer * -gimp_pickable_contiguous_region_prepare_line_art (GimpPickable *pickable, - gboolean select_transparent, - gfloat stroke_threshold) +static void +gimp_pickable_contiguous_region_prepare_line_art_async_func (GimpAsync *async, + LineArtData *data) { GeglBuffer *lineart; gboolean has_alpha; + gboolean select_transparent = FALSE; - g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), NULL); + has_alpha = babl_format_has_alpha (gegl_buffer_get_format (data->buffer)); - 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 (has_alpha) { - if (select_transparent) + if (data->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"), + gi = gegl_buffer_iterator_new (data->buffer, 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; + if (gimp_async_is_canceled (async)) + { + gegl_buffer_iterator_stop (gi); + + gimp_async_abort (async); + + line_art_data_free (data); + + return; + } + for (k = 0; k < gi->length; k++) { if (! *p) @@ -147,10 +168,6 @@ gimp_pickable_contiguous_region_prepare_line_art (GimpPickable *pickable, 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 @@ -158,9 +175,9 @@ gimp_pickable_contiguous_region_prepare_line_art (GimpPickable *pickable, */ GIMP_TIMER_START(); - lineart = gimp_lineart_close (lineart, + lineart = gimp_lineart_close (data->buffer, select_transparent, - stroke_threshold, + data->stroke_threshold, /*minimal_lineart_area,*/ 5, /*normal_estimate_mask_size,*/ @@ -188,9 +205,70 @@ gimp_pickable_contiguous_region_prepare_line_art (GimpPickable *pickable, GIMP_TIMER_END("close line-art"); + gimp_async_finish_full (async, lineart, g_object_unref); + + line_art_data_free (data); +} + +GeglBuffer * +gimp_pickable_contiguous_region_prepare_line_art (GimpPickable *pickable, + gboolean select_transparent, + gfloat stroke_threshold) +{ + GimpAsync *async; + LineArtData *data; + GeglBuffer *lineart; + + g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), NULL); + + gimp_pickable_flush (pickable); + + async = gimp_async_new (); + data = line_art_data_new (gimp_pickable_get_buffer (pickable), + select_transparent, + stroke_threshold); + + gimp_pickable_contiguous_region_prepare_line_art_async_func (async, data); + + lineart = g_object_ref (gimp_async_get_result (async)); + + g_object_unref (async); + return lineart; } +GimpAsync * +gimp_pickable_contiguous_region_prepare_line_art_async (GimpPickable *pickable, + gboolean select_transparent, + gfloat stroke_threshold, + gint priority) +{ + GeglBuffer *buffer; + GimpAsync *async; + LineArtData *data; + + g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), NULL); + + gimp_pickable_flush (pickable); + + buffer = gegl_buffer_dup (gimp_pickable_get_buffer (pickable)); + + data = line_art_data_new (buffer, + select_transparent, + stroke_threshold); + + g_object_unref (buffer); + + async = gimp_parallel_run_async_full ( + priority, + (GimpParallelRunAsyncFunc) + gimp_pickable_contiguous_region_prepare_line_art_async_func, + data, + (GDestroyNotify) line_art_data_free); + + return async; +} + GeglBuffer * gimp_pickable_contiguous_region_by_seed (GimpPickable *pickable, GeglBuffer *line_art, @@ -926,3 +1004,25 @@ find_contiguous_region (GeglBuffer *src_buffer, g_free (row); #endif } + +static LineArtData * +line_art_data_new (GeglBuffer *buffer, + gboolean select_transparent, + gfloat stroke_threshold) +{ + LineArtData *data = g_slice_new (LineArtData); + + data->buffer = g_object_ref (buffer); + data->select_transparent = select_transparent; + data->stroke_threshold = stroke_threshold; + + return data; +} + +static void +line_art_data_free (LineArtData *data) +{ + g_object_unref (data->buffer); + + g_slice_free (LineArtData, data); +} diff --git a/app/core/gimppickable-contiguous-region.h b/app/core/gimppickable-contiguous-region.h index b73f9aa1c4..95543a59e5 100644 --- a/app/core/gimppickable-contiguous-region.h +++ b/app/core/gimppickable-contiguous-region.h @@ -19,26 +19,31 @@ #define __GIMP_PICKABLE_CONTIGUOUS_REGION_H__ -GeglBuffer * gimp_pickable_contiguous_region_prepare_line_art (GimpPickable *pickable, - gboolean select_transparent, - gfloat stroke_threshold); -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, - gfloat stroke_threshold, - gint x, - gint y); +GeglBuffer * gimp_pickable_contiguous_region_prepare_line_art (GimpPickable *pickable, + gboolean select_transparent, + gfloat stroke_threshold); +GimpAsync * gimp_pickable_contiguous_region_prepare_line_art_async (GimpPickable *pickable, + gboolean select_transparent, + gfloat stroke_threshold, + gint priority); -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_seed (GimpPickable *pickable, + GeglBuffer *line_art, + gboolean antialias, + gfloat threshold, + gboolean select_transparent, + GimpSelectCriterion select_criterion, + gboolean diagonal_neighbors, + gfloat stroke_threshold, + 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); #endif /* __GIMP_PICKABLE_CONTIGUOUS_REGION_H__ */ diff --git a/app/tools/gimpbucketfilltool.c b/app/tools/gimpbucketfilltool.c index 9ce209c714..829cf87412 100644 --- a/app/tools/gimpbucketfilltool.c +++ b/app/tools/gimpbucketfilltool.c @@ -35,7 +35,6 @@ #include "core/gimpimage.h" #include "core/gimpitem.h" #include "core/gimplineart.h" -#include "core/gimp-parallel.h" #include "core/gimppickable.h" #include "core/gimppickable-contiguous-region.h" #include "core/gimpprogress.h" @@ -689,33 +688,6 @@ gimp_bucket_fill_tool_cursor_update (GimpTool *tool, GIMP_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, display); } -typedef struct -{ - GimpPickable *pickable; - gboolean fill_transparent; - gdouble line_art_threshold; -} PrecomputeData; - -static void -precompute_data_free (PrecomputeData *data) -{ - g_object_unref (data->pickable); - g_slice_free (PrecomputeData, data); -} - -static void -gimp_bucket_fill_compute_line_art_async (GimpAsync *async, - PrecomputeData *data) -{ - GeglBuffer *line_art; - - line_art = gimp_pickable_contiguous_region_prepare_line_art (data->pickable, - data->fill_transparent, - data->line_art_threshold); - precompute_data_free (data); - gimp_async_finish_full (async, line_art, g_object_unref); -} - static void gimp_bucket_fill_compute_line_art_cb (GimpAsync *async, GimpBucketFillTool *tool) @@ -754,36 +726,26 @@ gimp_bucket_fill_compute_line_art (GimpBucketFillTool *tool) GimpDrawable *drawable = g_weak_ref_get (&tool->priv->cached_drawable); if (image && options->sample_merged) - { - pickable = GIMP_PICKABLE (image); - g_clear_object (&drawable); - } + pickable = GIMP_PICKABLE (image); else if (drawable && ! options->sample_merged) - { - pickable = GIMP_PICKABLE (drawable); - g_clear_object (&image); - } - else - { - g_clear_object (&image); - g_clear_object (&drawable); - } + pickable = GIMP_PICKABLE (drawable); if (pickable) { - PrecomputeData *data = g_slice_new (PrecomputeData); + tool->priv->async = + gimp_pickable_contiguous_region_prepare_line_art_async ( + pickable, + options->fill_transparent, + options->line_art_threshold, + +1); - data->pickable = pickable; - data->fill_transparent = options->fill_transparent; - data->line_art_threshold = options->line_art_threshold; - - tool->priv->async = gimp_parallel_run_async_full (1, - (GimpParallelRunAsyncFunc) gimp_bucket_fill_compute_line_art_async, - data, (GDestroyNotify) precompute_data_free); gimp_async_add_callback (tool->priv->async, (GimpAsyncCallback) gimp_bucket_fill_compute_line_art_cb, tool); } + + g_clear_object (&image); + g_clear_object (&drawable); } }