Commit a3cda4ab authored by Jehan's avatar Jehan

app: make line art pre-computation in threads.

This makes the speed sensation of the tool much faster as line art can
be computed in dead time when you start the tool or when you move the
pointer.
parent f246f404
......@@ -25,6 +25,8 @@
#include "tools-types.h"
#include "core/gimp.h"
#include "core/gimpasync.h"
#include "core/gimpcancelable.h"
#include "core/gimpdrawable-bucket-fill.h"
#include "core/gimpdrawable-edit.h"
#include "core/gimperror.h"
......@@ -32,8 +34,10 @@
#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/gimpwaitable.h"
#include "widgets/gimphelp-ids.h"
#include "widgets/gimpwidgets-utils.h"
......@@ -49,6 +53,7 @@
struct _GimpBucketFillToolPrivate
{
GimpAsync *async;
GeglBuffer *line_art;
GWeakRef cached_image;
GWeakRef cached_drawable;
......@@ -260,8 +265,9 @@ gimp_bucket_fill_tool_button_release (GimpTool *tool,
GimpButtonReleaseType release_type,
GimpDisplay *display)
{
GimpBucketFillOptions *options = GIMP_BUCKET_FILL_TOOL_GET_OPTIONS (tool);
GimpImage *image = gimp_display_get_image (display);
GimpBucketFillTool *bucket_tool = GIMP_BUCKET_FILL_TOOL (tool);
GimpBucketFillOptions *options = GIMP_BUCKET_FILL_TOOL_GET_OPTIONS (tool);
GimpImage *image = gimp_display_get_image (display);
if ((release_type == GIMP_BUTTON_RELEASE_CLICK ||
release_type == GIMP_BUTTON_RELEASE_NO_MOTION) &&
......@@ -292,8 +298,9 @@ gimp_bucket_fill_tool_button_release (GimpTool *tool,
}
else
{
gint x = coords->x;
gint y = coords->y;
GeglBuffer *line_art;
gint x = coords->x;
gint y = coords->y;
if (! options->sample_merged)
{
......@@ -305,9 +312,13 @@ gimp_bucket_fill_tool_button_release (GimpTool *tool,
y -= off_y;
}
gimp_waitable_wait (GIMP_WAITABLE (bucket_tool->priv->async));
line_art = g_object_ref (bucket_tool->priv->line_art);
g_object_unref (bucket_tool->priv->async);
bucket_tool->priv->async = NULL;
gimp_drawable_bucket_fill (drawable,
GIMP_BUCKET_FILL_TOOL (tool)->priv->line_art,
line_art,
fill_options,
options->fill_transparent,
options->fill_criterion,
......@@ -315,6 +326,7 @@ gimp_bucket_fill_tool_button_release (GimpTool *tool,
options->sample_merged,
options->diagonal_neighbors,
x, y);
g_object_unref (line_art);
}
gimp_image_flush (image);
......@@ -408,6 +420,50 @@ gimp_bucket_fill_tool_cursor_update (GimpTool *tool,
GIMP_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, display);
}
typedef struct
{
GimpBucketFillTool *tool;
GimpPickable *pickable;
gboolean fill_transparent;
} PrecomputeData;
static void
precompute_data_free (PrecomputeData *data)
{
g_object_unref (data->pickable);
g_object_unref (data->tool);
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);
precompute_data_free (data);
if (gimp_async_is_canceled (async))
{
g_object_unref (line_art);
gimp_async_abort (async);
return;
}
gimp_async_finish (async, line_art);
}
static void
gimp_bucket_fill_compute_line_art_cb (GimpAsync *async,
GimpBucketFillTool *tool)
{
if (gimp_async_is_canceled (async))
return;
if (gimp_async_is_finished (async))
tool->priv->line_art = gimp_async_get_result (async);
}
static void
gimp_bucket_fill_compute_line_art (GimpBucketFillTool *tool)
{
......@@ -421,17 +477,43 @@ 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);
{
pickable = GIMP_PICKABLE (image);
g_object_unref (drawable);
}
else if (drawable && ! options->sample_merged)
pickable = GIMP_PICKABLE (drawable);
{
pickable = GIMP_PICKABLE (drawable);
g_object_unref (image);
}
else
{
g_object_unref (image);
g_object_unref (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);
{
PrecomputeData *data = g_slice_new (PrecomputeData);
data->tool = g_object_ref (tool);
data->pickable = pickable;
data->fill_transparent = options->fill_transparent;
if (tool->priv->async)
{
gimp_cancelable_cancel (GIMP_CANCELABLE (tool->priv->async));
g_object_unref (tool->priv->async);
}
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);
}
else
g_object_unref (pickable);
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment