2006-12-10 05:33:38 +08:00
|
|
|
/* GIMP - The GNU Image Manipulation Program
|
1997-11-25 06:05:25 +08:00
|
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
|
|
*
|
2009-01-18 06:28:01 +08:00
|
|
|
* This program is free software: you can redistribute it and/or modify
|
1997-11-25 06:05:25 +08:00
|
|
|
* it under the terms of the GNU General Public License as published by
|
2009-01-18 06:28:01 +08:00
|
|
|
* the Free Software Foundation; either version 3 of the License, or
|
1997-11-25 06:05:25 +08:00
|
|
|
* (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
|
2018-07-12 05:27:07 +08:00
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
1997-11-25 06:05:25 +08:00
|
|
|
*/
|
2000-12-17 05:37:03 +08:00
|
|
|
|
2000-04-28 01:27:28 +08:00
|
|
|
#include "config.h"
|
2000-01-14 20:41:00 +08:00
|
|
|
|
2008-10-10 04:24:04 +08:00
|
|
|
#include <gegl.h>
|
2000-12-17 05:37:03 +08:00
|
|
|
#include <gtk/gtk.h>
|
2000-01-14 20:41:00 +08:00
|
|
|
|
2001-01-25 06:36:18 +08:00
|
|
|
#include "libgimpwidgets/gimpwidgets.h"
|
|
|
|
|
2002-05-03 20:45:22 +08:00
|
|
|
#include "tools-types.h"
|
2000-12-17 05:37:03 +08:00
|
|
|
|
2007-12-07 03:07:11 +08:00
|
|
|
#include "core/gimp.h"
|
2018-11-04 21:29:16 +08:00
|
|
|
#include "core/gimpasync.h"
|
|
|
|
#include "core/gimpcancelable.h"
|
2001-11-09 03:14:51 +08:00
|
|
|
#include "core/gimpdrawable-bucket-fill.h"
|
2018-04-19 05:44:34 +08:00
|
|
|
#include "core/gimpdrawable-edit.h"
|
2018-11-04 23:22:56 +08:00
|
|
|
#include "core/gimpdrawablefilter.h"
|
2009-08-20 23:05:23 +08:00
|
|
|
#include "core/gimperror.h"
|
2016-03-12 02:52:36 +08:00
|
|
|
#include "core/gimpfilloptions.h"
|
2001-05-09 10:32:03 +08:00
|
|
|
#include "core/gimpimage.h"
|
2007-03-08 23:32:58 +08:00
|
|
|
#include "core/gimpitem.h"
|
2018-11-04 01:40:50 +08:00
|
|
|
#include "core/gimplineart.h"
|
|
|
|
#include "core/gimppickable.h"
|
|
|
|
#include "core/gimppickable-contiguous-region.h"
|
2018-11-04 23:22:56 +08:00
|
|
|
#include "core/gimpprogress.h"
|
|
|
|
#include "core/gimpprojection.h"
|
2018-11-28 00:25:05 +08:00
|
|
|
#include "core/gimptoolinfo.h"
|
2018-11-04 21:29:16 +08:00
|
|
|
#include "core/gimpwaitable.h"
|
2001-05-09 10:32:03 +08:00
|
|
|
|
2018-11-04 23:22:56 +08:00
|
|
|
#include "gegl/gimp-gegl-nodes.h"
|
|
|
|
|
|
|
|
#include "operations/layer-modes/gimp-layer-modes.h"
|
|
|
|
|
2003-08-22 09:42:57 +08:00
|
|
|
#include "widgets/gimphelp-ids.h"
|
2011-10-07 03:59:07 +08:00
|
|
|
#include "widgets/gimpwidgets-utils.h"
|
2003-08-22 09:42:57 +08:00
|
|
|
|
2001-09-26 07:23:09 +08:00
|
|
|
#include "display/gimpdisplay.h"
|
|
|
|
|
2003-02-05 22:39:40 +08:00
|
|
|
#include "gimpbucketfilloptions.h"
|
2001-03-08 09:07:03 +08:00
|
|
|
#include "gimpbucketfilltool.h"
|
2018-11-28 00:25:05 +08:00
|
|
|
#include "gimpcoloroptions.h"
|
2003-04-16 00:05:52 +08:00
|
|
|
#include "gimptoolcontrol.h"
|
2018-12-10 21:22:50 +08:00
|
|
|
#include "gimptools-utils.h"
|
2001-01-25 06:36:18 +08:00
|
|
|
|
2003-03-26 00:38:19 +08:00
|
|
|
#include "gimp-intl.h"
|
Lots of ii8n stuff here and some additions to the de.po. Applied
Wed Oct 14 17:46:15 EDT 1998 Adrian Likins <adrian@gimp.org>
* app/*, po/de.po, de/POTFILES.in, libgimp/gimpintl.h:
Lots of ii8n stuff here and some additions to the de.po.
Applied gimp-egger-981005-1 ,gimp-egger-981006-1,
gimp-egger-981007-1, gimp-egger-981008-1,
gimp-egger-981009-1.patch, gimp-egger-981010-1.patch
* plug-in/guillotine/guillotine.c: added the coordinates
of the split images from the original image to the title.
ie foo.jpg (0,0) for the image in the topleft.
* plug-in/script-fu/scripts/neon-logo.scm,
perspective-shadow.scm, predator.scm,rendermap.scm,
ripply-anim.scm, select_to_image.scm,swirltile.scm,
xach-effect.scm: updated scripts to use new script-fu stuff
wooo boy! a big un!
in testing this, it looks like some of the po files are busted.
but the code stuff seems okay.
-adrian
1998-10-15 07:23:52 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2018-11-04 01:40:50 +08:00
|
|
|
struct _GimpBucketFillToolPrivate
|
|
|
|
{
|
2018-12-02 01:33:51 +08:00
|
|
|
GimpLineArt *line_art;
|
2018-11-04 23:22:56 +08:00
|
|
|
GWeakRef cached_image;
|
|
|
|
GWeakRef cached_drawable;
|
|
|
|
|
|
|
|
/* For preview */
|
|
|
|
GeglNode *graph;
|
|
|
|
GeglNode *fill_node;
|
|
|
|
GeglNode *offset_node;
|
|
|
|
|
2018-12-08 17:54:38 +08:00
|
|
|
GeglBuffer *fill_mask;
|
|
|
|
|
2018-11-04 23:22:56 +08:00
|
|
|
GimpDrawableFilter *filter;
|
2018-12-08 17:54:38 +08:00
|
|
|
|
|
|
|
/* Temp property save */
|
|
|
|
GimpBucketFillMode fill_mode;
|
app: do not make line art bucket fill a GimpSelectCriterion anymore.
This was my initial choice, but the more I think about it, the less I am
sure this was the right choice. There was some common code (as I was
making a common composite bucket fill once the line art was generated),
but there is also a lot of different code and the functions were filled
of exception when we were doing a line art fill. Also though there is a
bit of color works (the way we decide whether a pixel is part of a
stroke or not, though currently this is basic grayscale threshold), this
is really not the same as other criterions. In particular this was made
obvious on the Select by Color tool where the line art criterion was
completely meaningless and would have had to be opted-out!
This commit split a bit the code. Instead of finding the line art in the
criterion list, I add a third choice to the "Fill whole selection"/"Fill
similar colors" radio. In turn I create a new GimpBucketFillArea type
with the 3 choices, and remove line art value from GimpSelectCriterion.
I am not fully happy yet of this code, as it creates a bit of duplicate
code, and I would appreciate to move some code away from gimpdrawable-*
and gimppickable-* files. This may happen later. I break the work in
pieces to not get too messy.
Also this removes access to the smart colorization from the API, but
that's probably ok as I prefer to not freeze options too early in the
process since API needs to be stable. Probably we should get a concept
of experimental API.
2018-12-12 01:05:12 +08:00
|
|
|
GimpBucketFillArea fill_area;
|
2018-11-04 01:40:50 +08:00
|
|
|
};
|
|
|
|
|
2005-12-13 17:13:50 +08:00
|
|
|
/* local function prototypes */
|
2001-02-28 09:05:22 +08:00
|
|
|
|
2018-11-04 23:22:56 +08:00
|
|
|
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);
|
|
|
|
|
|
|
|
static void gimp_bucket_fill_tool_start (GimpBucketFillTool *tool,
|
|
|
|
const GimpCoords *coords,
|
|
|
|
GimpDisplay *display);
|
|
|
|
static void gimp_bucket_fill_tool_preview (GimpBucketFillTool *tool,
|
|
|
|
const GimpCoords *coords,
|
|
|
|
GimpDisplay *display,
|
|
|
|
GimpFillOptions *fill_options);
|
|
|
|
static void gimp_bucket_fill_tool_commit (GimpBucketFillTool *tool);
|
|
|
|
static void gimp_bucket_fill_tool_halt (GimpBucketFillTool *tool);
|
|
|
|
static void gimp_bucket_fill_tool_filter_flush (GimpDrawableFilter *filter,
|
|
|
|
GimpTool *tool);
|
|
|
|
static void gimp_bucket_fill_tool_create_graph (GimpBucketFillTool *tool);
|
|
|
|
|
|
|
|
static void gimp_bucket_fill_tool_button_press (GimpTool *tool,
|
|
|
|
const GimpCoords *coords,
|
|
|
|
guint32 time,
|
|
|
|
GdkModifierType state,
|
|
|
|
GimpButtonPressType press_type,
|
|
|
|
GimpDisplay *display);
|
|
|
|
static void gimp_bucket_fill_tool_motion (GimpTool *tool,
|
|
|
|
const GimpCoords *coords,
|
|
|
|
guint32 time,
|
|
|
|
GdkModifierType state,
|
|
|
|
GimpDisplay *display);
|
|
|
|
static void gimp_bucket_fill_tool_button_release (GimpTool *tool,
|
|
|
|
const GimpCoords *coords,
|
|
|
|
guint32 time,
|
|
|
|
GdkModifierType state,
|
|
|
|
GimpButtonReleaseType release_type,
|
|
|
|
GimpDisplay *display);
|
|
|
|
static void gimp_bucket_fill_tool_modifier_key (GimpTool *tool,
|
|
|
|
GdkModifierType key,
|
|
|
|
gboolean press,
|
|
|
|
GdkModifierType state,
|
|
|
|
GimpDisplay *display);
|
|
|
|
static void gimp_bucket_fill_tool_cursor_update (GimpTool *tool,
|
|
|
|
const GimpCoords *coords,
|
|
|
|
GdkModifierType state,
|
|
|
|
GimpDisplay *display);
|
1999-04-09 06:25:54 +08:00
|
|
|
|
2018-11-04 01:40:50 +08:00
|
|
|
static void gimp_bucket_fill_tool_options_notified (GimpBucketFillOptions *options,
|
|
|
|
GParamSpec *pspec,
|
|
|
|
GimpBucketFillTool *tool);
|
2018-12-02 01:33:51 +08:00
|
|
|
static void gimp_bucket_fill_reset_line_art (GimpBucketFillTool *tool,
|
|
|
|
GimpBucketFillOptions *options);
|
2018-11-04 01:40:50 +08:00
|
|
|
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);
|
|
|
|
|
|
|
|
|
2018-11-28 00:25:05 +08:00
|
|
|
G_DEFINE_TYPE_WITH_PRIVATE (GimpBucketFillTool, gimp_bucket_fill_tool, GIMP_TYPE_COLOR_TOOL)
|
2005-12-13 17:13:50 +08:00
|
|
|
|
|
|
|
#define parent_class gimp_bucket_fill_tool_parent_class
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-02-28 09:05:22 +08:00
|
|
|
void
|
2002-03-29 11:50:29 +08:00
|
|
|
gimp_bucket_fill_tool_register (GimpToolRegisterCallback callback,
|
2003-08-22 09:42:57 +08:00
|
|
|
gpointer data)
|
2001-02-28 09:05:22 +08:00
|
|
|
{
|
2002-03-29 11:50:29 +08:00
|
|
|
(* callback) (GIMP_TYPE_BUCKET_FILL_TOOL,
|
2003-02-05 22:39:40 +08:00
|
|
|
GIMP_TYPE_BUCKET_FILL_OPTIONS,
|
|
|
|
gimp_bucket_fill_options_gui,
|
2015-09-09 03:18:49 +08:00
|
|
|
GIMP_CONTEXT_PROP_MASK_FOREGROUND |
|
|
|
|
GIMP_CONTEXT_PROP_MASK_BACKGROUND |
|
|
|
|
GIMP_CONTEXT_PROP_MASK_OPACITY |
|
|
|
|
GIMP_CONTEXT_PROP_MASK_PAINT_MODE |
|
|
|
|
GIMP_CONTEXT_PROP_MASK_PATTERN,
|
2002-03-21 20:17:17 +08:00
|
|
|
"gimp-bucket-fill-tool",
|
2001-11-21 07:00:47 +08:00
|
|
|
_("Bucket Fill"),
|
2006-09-19 02:00:22 +08:00
|
|
|
_("Bucket Fill Tool: Fill selected area with a color or pattern"),
|
2004-04-29 21:19:28 +08:00
|
|
|
N_("_Bucket Fill"), "<shift>B",
|
2003-08-22 09:42:57 +08:00
|
|
|
NULL, GIMP_HELP_TOOL_BUCKET_FILL,
|
2017-03-05 23:01:59 +08:00
|
|
|
GIMP_ICON_TOOL_BUCKET_FILL,
|
2002-05-03 19:31:08 +08:00
|
|
|
data);
|
2001-02-28 09:05:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_bucket_fill_tool_class_init (GimpBucketFillToolClass *klass)
|
|
|
|
{
|
2018-11-04 01:40:50 +08:00
|
|
|
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;
|
2001-02-28 09:05:22 +08:00
|
|
|
|
2009-08-20 23:05:23 +08:00
|
|
|
tool_class->initialize = gimp_bucket_fill_tool_initialize;
|
2018-11-04 23:22:56 +08:00
|
|
|
tool_class->button_press = gimp_bucket_fill_tool_button_press;
|
|
|
|
tool_class->motion = gimp_bucket_fill_tool_motion;
|
2001-02-28 09:05:22 +08:00
|
|
|
tool_class->button_release = gimp_bucket_fill_tool_button_release;
|
|
|
|
tool_class->modifier_key = gimp_bucket_fill_tool_modifier_key;
|
|
|
|
tool_class->cursor_update = gimp_bucket_fill_tool_cursor_update;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_bucket_fill_tool_init (GimpBucketFillTool *bucket_fill_tool)
|
|
|
|
{
|
2005-03-04 19:42:46 +08:00
|
|
|
GimpTool *tool = GIMP_TOOL (bucket_fill_tool);
|
2001-02-28 09:05:22 +08:00
|
|
|
|
2005-03-05 03:05:40 +08:00
|
|
|
gimp_tool_control_set_scroll_lock (tool->control, TRUE);
|
2007-03-08 23:32:58 +08:00
|
|
|
gimp_tool_control_set_wants_click (tool->control, TRUE);
|
2005-03-05 03:05:40 +08:00
|
|
|
gimp_tool_control_set_tool_cursor (tool->control,
|
|
|
|
GIMP_TOOL_CURSOR_BUCKET_FILL);
|
2014-04-20 02:09:39 +08:00
|
|
|
gimp_tool_control_set_action_opacity (tool->control,
|
2005-03-05 03:05:40 +08:00
|
|
|
"context/context-opacity-set");
|
|
|
|
gimp_tool_control_set_action_object_1 (tool->control,
|
|
|
|
"context/context-pattern-select-set");
|
2018-11-04 01:40:50 +08:00
|
|
|
|
|
|
|
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;
|
app: do not make line art bucket fill a GimpSelectCriterion anymore.
This was my initial choice, but the more I think about it, the less I am
sure this was the right choice. There was some common code (as I was
making a common composite bucket fill once the line art was generated),
but there is also a lot of different code and the functions were filled
of exception when we were doing a line art fill. Also though there is a
bit of color works (the way we decide whether a pixel is part of a
stroke or not, though currently this is basic grayscale threshold), this
is really not the same as other criterions. In particular this was made
obvious on the Select by Color tool where the line art criterion was
completely meaningless and would have had to be opted-out!
This commit split a bit the code. Instead of finding the line art in the
criterion list, I add a third choice to the "Fill whole selection"/"Fill
similar colors" radio. In turn I create a new GimpBucketFillArea type
with the 3 choices, and remove line art value from GimpSelectCriterion.
I am not fully happy yet of this code, as it creates a bit of duplicate
code, and I would appreciate to move some code away from gimpdrawable-*
and gimppickable-* files. This may happen later. I break the work in
pieces to not get too messy.
Also this removes access to the smart colorization from the API, but
that's probably ok as I prefer to not freeze options too early in the
process since API needs to be stable. Probably we should get a concept
of experimental API.
2018-12-12 01:05:12 +08:00
|
|
|
GimpContext *context = gimp_get_user_context (gimp);
|
|
|
|
GimpImage *image = gimp_context_get_image (context);
|
2018-12-02 01:33:51 +08:00
|
|
|
GimpLineArt *line_art;
|
2018-11-04 01:40:50 +08:00
|
|
|
|
|
|
|
G_OBJECT_CLASS (parent_class)->constructed (object);
|
|
|
|
|
2018-12-02 01:33:51 +08:00
|
|
|
line_art = gimp_line_art_new ();
|
|
|
|
g_object_bind_property (options, "fill-transparent",
|
|
|
|
line_art, "select-transparent",
|
|
|
|
G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
|
|
|
|
g_object_bind_property (options, "line-art-threshold",
|
|
|
|
line_art, "threshold",
|
|
|
|
G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
|
|
|
|
g_object_bind_property (options, "line-art-max-grow",
|
|
|
|
line_art, "max-grow",
|
|
|
|
G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
|
|
|
|
g_object_bind_property (options, "line-art-spline-max-len",
|
|
|
|
line_art, "spline-max-length",
|
|
|
|
G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
|
|
|
|
g_object_bind_property (options, "line-art-segment-max-len",
|
|
|
|
line_art, "segment-max-length",
|
|
|
|
G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
|
|
|
|
GIMP_BUCKET_FILL_TOOL (tool)->priv->line_art = line_art;
|
|
|
|
|
app: do not make line art bucket fill a GimpSelectCriterion anymore.
This was my initial choice, but the more I think about it, the less I am
sure this was the right choice. There was some common code (as I was
making a common composite bucket fill once the line art was generated),
but there is also a lot of different code and the functions were filled
of exception when we were doing a line art fill. Also though there is a
bit of color works (the way we decide whether a pixel is part of a
stroke or not, though currently this is basic grayscale threshold), this
is really not the same as other criterions. In particular this was made
obvious on the Select by Color tool where the line art criterion was
completely meaningless and would have had to be opted-out!
This commit split a bit the code. Instead of finding the line art in the
criterion list, I add a third choice to the "Fill whole selection"/"Fill
similar colors" radio. In turn I create a new GimpBucketFillArea type
with the 3 choices, and remove line art value from GimpSelectCriterion.
I am not fully happy yet of this code, as it creates a bit of duplicate
code, and I would appreciate to move some code away from gimpdrawable-*
and gimppickable-* files. This may happen later. I break the work in
pieces to not get too messy.
Also this removes access to the smart colorization from the API, but
that's probably ok as I prefer to not freeze options too early in the
process since API needs to be stable. Probably we should get a concept
of experimental API.
2018-12-12 01:05:12 +08:00
|
|
|
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-mode",
|
|
|
|
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));
|
2018-11-28 00:25:05 +08:00
|
|
|
|
|
|
|
GIMP_COLOR_TOOL (tool)->pick_target = (options->fill_mode == GIMP_BUCKET_FILL_BG) ?
|
|
|
|
GIMP_COLOR_PICK_TARGET_BACKGROUND : GIMP_COLOR_PICK_TARGET_FOREGROUND;
|
2018-11-04 01:40:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
2018-11-20 03:25:51 +08:00
|
|
|
|
2018-11-04 01:40:50 +08:00
|
|
|
g_clear_object (&tool->priv->line_art);
|
|
|
|
|
|
|
|
if (image)
|
|
|
|
{
|
|
|
|
g_signal_handlers_disconnect_by_data (image, tool);
|
|
|
|
g_object_unref (image);
|
|
|
|
}
|
|
|
|
|
2018-12-02 01:33:51 +08:00
|
|
|
g_signal_handlers_disconnect_by_data (options, tool);
|
2018-11-04 01:40:50 +08:00
|
|
|
g_signal_handlers_disconnect_by_data (context, tool);
|
|
|
|
|
|
|
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
2001-02-28 09:05:22 +08:00
|
|
|
}
|
|
|
|
|
2009-08-20 23:05:23 +08:00
|
|
|
static gboolean
|
|
|
|
gimp_bucket_fill_tool_initialize (GimpTool *tool,
|
|
|
|
GimpDisplay *display,
|
|
|
|
GError **error)
|
|
|
|
{
|
2018-11-04 23:22:56 +08:00
|
|
|
GimpImage *image = gimp_display_get_image (display);
|
|
|
|
GimpDrawable *drawable = gimp_image_get_active_drawable (image);
|
2009-08-20 23:05:23 +08:00
|
|
|
|
|
|
|
if (! GIMP_TOOL_CLASS (parent_class)->initialize (tool, display, error))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2009-08-29 02:07:14 +08:00
|
|
|
if (gimp_viewable_get_children (GIMP_VIEWABLE (drawable)))
|
|
|
|
{
|
|
|
|
g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
|
2016-12-21 11:05:32 +08:00
|
|
|
_("Cannot modify the pixels of layer groups."));
|
2009-08-29 02:07:14 +08:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2018-11-04 01:40:50 +08:00
|
|
|
if (! gimp_item_is_visible (GIMP_ITEM (drawable)))
|
2009-08-20 23:05:23 +08:00
|
|
|
{
|
|
|
|
g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
|
2018-11-04 01:40:50 +08:00
|
|
|
_("The active layer is not visible."));
|
2009-08-20 23:05:23 +08:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2018-11-04 01:40:50 +08:00
|
|
|
if (gimp_item_is_content_locked (GIMP_ITEM (drawable)))
|
2013-04-24 22:27:12 +08:00
|
|
|
{
|
|
|
|
g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
|
2018-11-04 01:40:50 +08:00
|
|
|
_("The active layer's pixels are locked."));
|
2018-12-10 21:22:50 +08:00
|
|
|
if (error)
|
|
|
|
gimp_tools_blink_lock_box (display->gimp, GIMP_ITEM (drawable));
|
2013-04-24 22:27:12 +08:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2009-08-20 23:05:23 +08:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
1998-03-19 06:35:31 +08:00
|
|
|
static void
|
2018-11-04 23:22:56 +08:00
|
|
|
gimp_bucket_fill_tool_start (GimpBucketFillTool *tool,
|
|
|
|
const GimpCoords *coords,
|
|
|
|
GimpDisplay *display)
|
|
|
|
{
|
|
|
|
GimpBucketFillOptions *options = GIMP_BUCKET_FILL_TOOL_GET_OPTIONS (tool);
|
|
|
|
GimpContext *context = GIMP_CONTEXT (options);
|
|
|
|
GimpImage *image = gimp_display_get_image (display);
|
|
|
|
GimpDrawable *drawable = gimp_image_get_active_drawable (image);
|
|
|
|
|
|
|
|
g_return_if_fail (! tool->priv->filter);
|
|
|
|
|
2018-12-02 01:33:51 +08:00
|
|
|
gimp_line_art_freeze (tool->priv->line_art);
|
2018-11-04 23:22:56 +08:00
|
|
|
|
|
|
|
GIMP_TOOL (tool)->display = display;
|
|
|
|
GIMP_TOOL (tool)->drawable = drawable;
|
|
|
|
|
|
|
|
gimp_bucket_fill_tool_create_graph (tool);
|
|
|
|
|
|
|
|
tool->priv->filter = gimp_drawable_filter_new (drawable, _("Bucket fill"),
|
|
|
|
tool->priv->graph,
|
|
|
|
GIMP_ICON_TOOL_BUCKET_FILL);
|
|
|
|
|
|
|
|
gimp_drawable_filter_set_region (tool->priv->filter, GIMP_FILTER_REGION_DRAWABLE);
|
|
|
|
|
|
|
|
/* We only set these here, and don't need to update it since we assume
|
|
|
|
* the settings can't change while the fill started.
|
|
|
|
*/
|
|
|
|
gimp_drawable_filter_set_mode (tool->priv->filter,
|
|
|
|
gimp_context_get_paint_mode (context),
|
|
|
|
GIMP_LAYER_COLOR_SPACE_AUTO,
|
|
|
|
GIMP_LAYER_COLOR_SPACE_AUTO,
|
|
|
|
gimp_layer_mode_get_paint_composite_mode (gimp_context_get_paint_mode (context)));
|
|
|
|
gimp_drawable_filter_set_opacity (tool->priv->filter,
|
|
|
|
gimp_context_get_opacity (context));
|
|
|
|
|
|
|
|
g_signal_connect (tool->priv->filter, "flush",
|
|
|
|
G_CALLBACK (gimp_bucket_fill_tool_filter_flush),
|
|
|
|
tool);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_bucket_fill_tool_preview (GimpBucketFillTool *tool,
|
|
|
|
const GimpCoords *coords,
|
|
|
|
GimpDisplay *display,
|
|
|
|
GimpFillOptions *fill_options)
|
|
|
|
{
|
|
|
|
GimpBucketFillOptions *options = GIMP_BUCKET_FILL_TOOL_GET_OPTIONS (tool);
|
|
|
|
GimpImage *image = gimp_display_get_image (display);
|
|
|
|
GimpDrawable *drawable = gimp_image_get_active_drawable (image);
|
|
|
|
|
|
|
|
if (tool->priv->filter)
|
|
|
|
{
|
|
|
|
GeglBuffer *fill = NULL;
|
|
|
|
gdouble x = coords->x;
|
|
|
|
gdouble y = coords->y;
|
|
|
|
|
|
|
|
if (! options->sample_merged)
|
|
|
|
{
|
|
|
|
gint off_x, off_y;
|
|
|
|
|
|
|
|
gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);
|
|
|
|
|
|
|
|
x -= (gdouble) off_x;
|
|
|
|
y -= (gdouble) off_y;
|
|
|
|
}
|
|
|
|
|
app: do not make line art bucket fill a GimpSelectCriterion anymore.
This was my initial choice, but the more I think about it, the less I am
sure this was the right choice. There was some common code (as I was
making a common composite bucket fill once the line art was generated),
but there is also a lot of different code and the functions were filled
of exception when we were doing a line art fill. Also though there is a
bit of color works (the way we decide whether a pixel is part of a
stroke or not, though currently this is basic grayscale threshold), this
is really not the same as other criterions. In particular this was made
obvious on the Select by Color tool where the line art criterion was
completely meaningless and would have had to be opted-out!
This commit split a bit the code. Instead of finding the line art in the
criterion list, I add a third choice to the "Fill whole selection"/"Fill
similar colors" radio. In turn I create a new GimpBucketFillArea type
with the 3 choices, and remove line art value from GimpSelectCriterion.
I am not fully happy yet of this code, as it creates a bit of duplicate
code, and I would appreciate to move some code away from gimpdrawable-*
and gimppickable-* files. This may happen later. I break the work in
pieces to not get too messy.
Also this removes access to the smart colorization from the API, but
that's probably ok as I prefer to not freeze options too early in the
process since API needs to be stable. Probably we should get a concept
of experimental API.
2018-12-12 01:05:12 +08:00
|
|
|
if (options->fill_area == GIMP_BUCKET_FILL_SIMILAR_COLORS)
|
|
|
|
{
|
|
|
|
fill = gimp_drawable_get_bucket_fill_buffer (drawable,
|
|
|
|
fill_options,
|
|
|
|
options->fill_transparent,
|
|
|
|
options->fill_criterion,
|
|
|
|
options->threshold / 255.0,
|
|
|
|
options->sample_merged,
|
|
|
|
options->diagonal_neighbors,
|
|
|
|
x, y, &tool->priv->fill_mask,
|
|
|
|
&x, &y, NULL, NULL);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fill = gimp_drawable_get_line_art_fill_buffer (drawable,
|
|
|
|
tool->priv->line_art,
|
|
|
|
fill_options,
|
|
|
|
options->sample_merged,
|
|
|
|
x, y, &tool->priv->fill_mask,
|
|
|
|
&x, &y, NULL, NULL);
|
|
|
|
}
|
2018-11-04 23:22:56 +08:00
|
|
|
if (fill)
|
|
|
|
{
|
|
|
|
gegl_node_set (tool->priv->fill_node,
|
|
|
|
"buffer", fill,
|
|
|
|
NULL);
|
|
|
|
gegl_node_set (tool->priv->offset_node,
|
|
|
|
"x", x,
|
|
|
|
"y", y,
|
|
|
|
NULL);
|
|
|
|
gimp_drawable_filter_apply (tool->priv->filter, NULL);
|
|
|
|
g_object_unref (fill);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_bucket_fill_tool_commit (GimpBucketFillTool *tool)
|
|
|
|
{
|
|
|
|
if (tool->priv->filter)
|
|
|
|
{
|
|
|
|
gimp_drawable_filter_commit (tool->priv->filter,
|
|
|
|
GIMP_PROGRESS (tool), FALSE);
|
|
|
|
gimp_image_flush (gimp_display_get_image (GIMP_TOOL (tool)->display));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_bucket_fill_tool_halt (GimpBucketFillTool *tool)
|
|
|
|
{
|
|
|
|
if (tool->priv->graph)
|
|
|
|
{
|
|
|
|
g_clear_object (&tool->priv->graph);
|
|
|
|
tool->priv->fill_node = NULL;
|
|
|
|
tool->priv->offset_node = NULL;
|
|
|
|
}
|
|
|
|
if (tool->priv->filter)
|
|
|
|
{
|
|
|
|
gimp_drawable_filter_abort (tool->priv->filter);
|
|
|
|
g_clear_object (&tool->priv->filter);
|
|
|
|
}
|
|
|
|
g_clear_object (&tool->priv->fill_mask);
|
|
|
|
|
2018-12-02 01:33:51 +08:00
|
|
|
gimp_line_art_thaw (tool->priv->line_art);
|
2018-11-04 23:22:56 +08:00
|
|
|
|
|
|
|
GIMP_TOOL (tool)->display = NULL;
|
|
|
|
GIMP_TOOL (tool)->drawable = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_bucket_fill_tool_filter_flush (GimpDrawableFilter *filter,
|
|
|
|
GimpTool *tool)
|
|
|
|
{
|
|
|
|
GimpImage *image = gimp_display_get_image (tool->display);
|
|
|
|
|
|
|
|
gimp_projection_flush (gimp_image_get_projection (image));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_bucket_fill_tool_create_graph (GimpBucketFillTool *tool)
|
|
|
|
{
|
|
|
|
GeglNode *graph;
|
|
|
|
GeglNode *output;
|
|
|
|
GeglNode *fill_node;
|
|
|
|
GeglNode *offset_node;
|
|
|
|
|
|
|
|
g_return_if_fail (! tool->priv->graph &&
|
|
|
|
! tool->priv->fill_node &&
|
|
|
|
! tool->priv->offset_node);
|
|
|
|
|
|
|
|
graph = gegl_node_new ();
|
|
|
|
|
|
|
|
fill_node = gegl_node_new_child (graph,
|
|
|
|
"operation", "gegl:buffer-source",
|
|
|
|
NULL);
|
|
|
|
offset_node = gegl_node_new_child (graph,
|
|
|
|
"operation", "gegl:translate",
|
|
|
|
NULL);
|
|
|
|
output = gegl_node_get_output_proxy (graph, "output");
|
|
|
|
gegl_node_link_many (fill_node, offset_node, output, NULL);
|
|
|
|
|
|
|
|
tool->priv->graph = graph;
|
|
|
|
tool->priv->fill_node = fill_node;
|
|
|
|
tool->priv->offset_node = offset_node;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_bucket_fill_tool_button_press (GimpTool *tool,
|
|
|
|
const GimpCoords *coords,
|
|
|
|
guint32 time,
|
|
|
|
GdkModifierType state,
|
|
|
|
GimpButtonPressType press_type,
|
|
|
|
GimpDisplay *display)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2018-11-04 21:29:16 +08:00
|
|
|
GimpBucketFillTool *bucket_tool = GIMP_BUCKET_FILL_TOOL (tool);
|
|
|
|
GimpBucketFillOptions *options = GIMP_BUCKET_FILL_TOOL_GET_OPTIONS (tool);
|
|
|
|
GimpImage *image = gimp_display_get_image (display);
|
2001-11-20 21:53:21 +08:00
|
|
|
|
2018-11-28 00:25:05 +08:00
|
|
|
if (gimp_color_tool_is_enabled (GIMP_COLOR_TOOL (tool)))
|
|
|
|
{
|
|
|
|
GIMP_TOOL_CLASS (parent_class)->button_press (tool, coords, time, state,
|
|
|
|
press_type, display);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-11-04 23:22:56 +08:00
|
|
|
if (press_type == GIMP_BUTTON_PRESS_NORMAL &&
|
2009-10-08 01:00:42 +08:00
|
|
|
gimp_image_coords_in_active_pickable (image, coords,
|
2007-03-08 23:32:58 +08:00
|
|
|
options->sample_merged, TRUE))
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2016-03-12 05:03:32 +08:00
|
|
|
GimpDrawable *drawable = gimp_image_get_active_drawable (image);
|
|
|
|
GimpContext *context = GIMP_CONTEXT (options);
|
|
|
|
GimpFillOptions *fill_options;
|
|
|
|
GError *error = NULL;
|
2007-03-08 23:32:58 +08:00
|
|
|
|
2016-03-16 03:10:16 +08:00
|
|
|
fill_options = gimp_fill_options_new (image->gimp, NULL, FALSE);
|
2007-03-08 23:32:58 +08:00
|
|
|
|
2016-03-12 05:41:25 +08:00
|
|
|
if (gimp_fill_options_set_by_fill_mode (fill_options, context,
|
|
|
|
options->fill_mode,
|
|
|
|
&error))
|
2014-06-03 20:00:01 +08:00
|
|
|
{
|
2016-09-15 18:24:37 +08:00
|
|
|
gimp_fill_options_set_antialias (fill_options, options->antialias);
|
|
|
|
|
2016-03-12 05:03:32 +08:00
|
|
|
gimp_context_set_opacity (GIMP_CONTEXT (fill_options),
|
|
|
|
gimp_context_get_opacity (context));
|
|
|
|
gimp_context_set_paint_mode (GIMP_CONTEXT (fill_options),
|
|
|
|
gimp_context_get_paint_mode (context));
|
2016-03-12 02:52:36 +08:00
|
|
|
|
app: do not make line art bucket fill a GimpSelectCriterion anymore.
This was my initial choice, but the more I think about it, the less I am
sure this was the right choice. There was some common code (as I was
making a common composite bucket fill once the line art was generated),
but there is also a lot of different code and the functions were filled
of exception when we were doing a line art fill. Also though there is a
bit of color works (the way we decide whether a pixel is part of a
stroke or not, though currently this is basic grayscale threshold), this
is really not the same as other criterions. In particular this was made
obvious on the Select by Color tool where the line art criterion was
completely meaningless and would have had to be opted-out!
This commit split a bit the code. Instead of finding the line art in the
criterion list, I add a third choice to the "Fill whole selection"/"Fill
similar colors" radio. In turn I create a new GimpBucketFillArea type
with the 3 choices, and remove line art value from GimpSelectCriterion.
I am not fully happy yet of this code, as it creates a bit of duplicate
code, and I would appreciate to move some code away from gimpdrawable-*
and gimppickable-* files. This may happen later. I break the work in
pieces to not get too messy.
Also this removes access to the smart colorization from the API, but
that's probably ok as I prefer to not freeze options too early in the
process since API needs to be stable. Probably we should get a concept
of experimental API.
2018-12-12 01:05:12 +08:00
|
|
|
if (options->fill_area == GIMP_BUCKET_FILL_SELECTION)
|
2016-03-12 02:52:36 +08:00
|
|
|
{
|
2018-04-19 05:44:34 +08:00
|
|
|
gimp_drawable_edit_fill (drawable, fill_options, NULL);
|
2018-11-16 20:41:12 +08:00
|
|
|
gimp_image_flush (image);
|
2016-03-12 02:52:36 +08:00
|
|
|
}
|
app: do not make line art bucket fill a GimpSelectCriterion anymore.
This was my initial choice, but the more I think about it, the less I am
sure this was the right choice. There was some common code (as I was
making a common composite bucket fill once the line art was generated),
but there is also a lot of different code and the functions were filled
of exception when we were doing a line art fill. Also though there is a
bit of color works (the way we decide whether a pixel is part of a
stroke or not, though currently this is basic grayscale threshold), this
is really not the same as other criterions. In particular this was made
obvious on the Select by Color tool where the line art criterion was
completely meaningless and would have had to be opted-out!
This commit split a bit the code. Instead of finding the line art in the
criterion list, I add a third choice to the "Fill whole selection"/"Fill
similar colors" radio. In turn I create a new GimpBucketFillArea type
with the 3 choices, and remove line art value from GimpSelectCriterion.
I am not fully happy yet of this code, as it creates a bit of duplicate
code, and I would appreciate to move some code away from gimpdrawable-*
and gimppickable-* files. This may happen later. I break the work in
pieces to not get too messy.
Also this removes access to the smart colorization from the API, but
that's probably ok as I prefer to not freeze options too early in the
process since API needs to be stable. Probably we should get a concept
of experimental API.
2018-12-12 01:05:12 +08:00
|
|
|
else /* GIMP_BUCKET_FILL_SIMILAR_COLORS or GIMP_BUCKET_FILL_LINE_ART */
|
2016-03-12 02:52:36 +08:00
|
|
|
{
|
2018-11-04 23:22:56 +08:00
|
|
|
gimp_bucket_fill_tool_start (bucket_tool, coords, display);
|
|
|
|
gimp_bucket_fill_tool_preview (bucket_tool, coords, display, fill_options);
|
2016-03-12 02:52:36 +08:00
|
|
|
}
|
2018-11-04 23:22:56 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gimp_message_literal (display->gimp, G_OBJECT (display),
|
|
|
|
GIMP_MESSAGE_WARNING, error->message);
|
|
|
|
g_clear_error (&error);
|
|
|
|
}
|
2016-03-12 05:03:32 +08:00
|
|
|
|
2018-11-04 23:22:56 +08:00
|
|
|
g_object_unref (fill_options);
|
|
|
|
}
|
|
|
|
|
|
|
|
GIMP_TOOL_CLASS (parent_class)->button_press (tool, coords, time, state,
|
|
|
|
press_type, display);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_bucket_fill_tool_motion (GimpTool *tool,
|
|
|
|
const GimpCoords *coords,
|
|
|
|
guint32 time,
|
|
|
|
GdkModifierType state,
|
|
|
|
GimpDisplay *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);
|
|
|
|
|
|
|
|
GIMP_TOOL_CLASS (parent_class)->motion (tool, coords, time, state, display);
|
|
|
|
|
2018-11-28 00:25:05 +08:00
|
|
|
if (gimp_color_tool_is_enabled (GIMP_COLOR_TOOL (tool)))
|
|
|
|
return;
|
|
|
|
|
2018-11-04 23:22:56 +08:00
|
|
|
if (gimp_image_coords_in_active_pickable (image, coords,
|
|
|
|
options->sample_merged, TRUE) &&
|
|
|
|
/* Fill selection only needs to happen once. */
|
app: do not make line art bucket fill a GimpSelectCriterion anymore.
This was my initial choice, but the more I think about it, the less I am
sure this was the right choice. There was some common code (as I was
making a common composite bucket fill once the line art was generated),
but there is also a lot of different code and the functions were filled
of exception when we were doing a line art fill. Also though there is a
bit of color works (the way we decide whether a pixel is part of a
stroke or not, though currently this is basic grayscale threshold), this
is really not the same as other criterions. In particular this was made
obvious on the Select by Color tool where the line art criterion was
completely meaningless and would have had to be opted-out!
This commit split a bit the code. Instead of finding the line art in the
criterion list, I add a third choice to the "Fill whole selection"/"Fill
similar colors" radio. In turn I create a new GimpBucketFillArea type
with the 3 choices, and remove line art value from GimpSelectCriterion.
I am not fully happy yet of this code, as it creates a bit of duplicate
code, and I would appreciate to move some code away from gimpdrawable-*
and gimppickable-* files. This may happen later. I break the work in
pieces to not get too messy.
Also this removes access to the smart colorization from the API, but
that's probably ok as I prefer to not freeze options too early in the
process since API needs to be stable. Probably we should get a concept
of experimental API.
2018-12-12 01:05:12 +08:00
|
|
|
options->fill_area != GIMP_BUCKET_FILL_SELECTION)
|
2018-11-04 23:22:56 +08:00
|
|
|
{
|
|
|
|
GimpContext *context = GIMP_CONTEXT (options);
|
|
|
|
GimpFillOptions *fill_options;
|
|
|
|
GError *error = NULL;
|
|
|
|
|
|
|
|
fill_options = gimp_fill_options_new (image->gimp, NULL, FALSE);
|
|
|
|
|
|
|
|
if (gimp_fill_options_set_by_fill_mode (fill_options, context,
|
|
|
|
options->fill_mode,
|
|
|
|
&error))
|
|
|
|
{
|
|
|
|
gimp_fill_options_set_antialias (fill_options, options->antialias);
|
|
|
|
|
|
|
|
gimp_context_set_opacity (GIMP_CONTEXT (fill_options),
|
|
|
|
gimp_context_get_opacity (context));
|
|
|
|
gimp_context_set_paint_mode (GIMP_CONTEXT (fill_options),
|
|
|
|
gimp_context_get_paint_mode (context));
|
|
|
|
|
|
|
|
gimp_bucket_fill_tool_preview (bucket_tool, coords, display, fill_options);
|
2007-12-07 03:07:11 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-06-03 20:00:01 +08:00
|
|
|
gimp_message_literal (display->gimp, G_OBJECT (display),
|
|
|
|
GIMP_MESSAGE_WARNING, error->message);
|
|
|
|
g_clear_error (&error);
|
2007-12-07 03:07:11 +08:00
|
|
|
}
|
2016-03-12 05:41:25 +08:00
|
|
|
|
|
|
|
g_object_unref (fill_options);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
2018-11-04 23:22:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_bucket_fill_tool_button_release (GimpTool *tool,
|
|
|
|
const GimpCoords *coords,
|
|
|
|
guint32 time,
|
|
|
|
GdkModifierType state,
|
|
|
|
GimpButtonReleaseType release_type,
|
|
|
|
GimpDisplay *display)
|
|
|
|
{
|
app: do not make line art bucket fill a GimpSelectCriterion anymore.
This was my initial choice, but the more I think about it, the less I am
sure this was the right choice. There was some common code (as I was
making a common composite bucket fill once the line art was generated),
but there is also a lot of different code and the functions were filled
of exception when we were doing a line art fill. Also though there is a
bit of color works (the way we decide whether a pixel is part of a
stroke or not, though currently this is basic grayscale threshold), this
is really not the same as other criterions. In particular this was made
obvious on the Select by Color tool where the line art criterion was
completely meaningless and would have had to be opted-out!
This commit split a bit the code. Instead of finding the line art in the
criterion list, I add a third choice to the "Fill whole selection"/"Fill
similar colors" radio. In turn I create a new GimpBucketFillArea type
with the 3 choices, and remove line art value from GimpSelectCriterion.
I am not fully happy yet of this code, as it creates a bit of duplicate
code, and I would appreciate to move some code away from gimpdrawable-*
and gimppickable-* files. This may happen later. I break the work in
pieces to not get too messy.
Also this removes access to the smart colorization from the API, but
that's probably ok as I prefer to not freeze options too early in the
process since API needs to be stable. Probably we should get a concept
of experimental API.
2018-12-12 01:05:12 +08:00
|
|
|
GimpBucketFillTool *bucket_tool = GIMP_BUCKET_FILL_TOOL (tool);
|
|
|
|
GimpBucketFillOptions *options = GIMP_BUCKET_FILL_TOOL_GET_OPTIONS (tool);
|
2018-11-04 23:22:56 +08:00
|
|
|
|
2018-11-28 00:25:05 +08:00
|
|
|
if (gimp_color_tool_is_enabled (GIMP_COLOR_TOOL (tool)))
|
|
|
|
{
|
|
|
|
GIMP_TOOL_CLASS (parent_class)->button_release (tool, coords, time,
|
|
|
|
state, release_type,
|
|
|
|
display);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
app: do not make line art bucket fill a GimpSelectCriterion anymore.
This was my initial choice, but the more I think about it, the less I am
sure this was the right choice. There was some common code (as I was
making a common composite bucket fill once the line art was generated),
but there is also a lot of different code and the functions were filled
of exception when we were doing a line art fill. Also though there is a
bit of color works (the way we decide whether a pixel is part of a
stroke or not, though currently this is basic grayscale threshold), this
is really not the same as other criterions. In particular this was made
obvious on the Select by Color tool where the line art criterion was
completely meaningless and would have had to be opted-out!
This commit split a bit the code. Instead of finding the line art in the
criterion list, I add a third choice to the "Fill whole selection"/"Fill
similar colors" radio. In turn I create a new GimpBucketFillArea type
with the 3 choices, and remove line art value from GimpSelectCriterion.
I am not fully happy yet of this code, as it creates a bit of duplicate
code, and I would appreciate to move some code away from gimpdrawable-*
and gimppickable-* files. This may happen later. I break the work in
pieces to not get too messy.
Also this removes access to the smart colorization from the API, but
that's probably ok as I prefer to not freeze options too early in the
process since API needs to be stable. Probably we should get a concept
of experimental API.
2018-12-12 01:05:12 +08:00
|
|
|
if (release_type != GIMP_BUTTON_RELEASE_CANCEL)
|
2018-11-04 23:22:56 +08:00
|
|
|
gimp_bucket_fill_tool_commit (bucket_tool);
|
|
|
|
|
app: do not make line art bucket fill a GimpSelectCriterion anymore.
This was my initial choice, but the more I think about it, the less I am
sure this was the right choice. There was some common code (as I was
making a common composite bucket fill once the line art was generated),
but there is also a lot of different code and the functions were filled
of exception when we were doing a line art fill. Also though there is a
bit of color works (the way we decide whether a pixel is part of a
stroke or not, though currently this is basic grayscale threshold), this
is really not the same as other criterions. In particular this was made
obvious on the Select by Color tool where the line art criterion was
completely meaningless and would have had to be opted-out!
This commit split a bit the code. Instead of finding the line art in the
criterion list, I add a third choice to the "Fill whole selection"/"Fill
similar colors" radio. In turn I create a new GimpBucketFillArea type
with the 3 choices, and remove line art value from GimpSelectCriterion.
I am not fully happy yet of this code, as it creates a bit of duplicate
code, and I would appreciate to move some code away from gimpdrawable-*
and gimppickable-* files. This may happen later. I break the work in
pieces to not get too messy.
Also this removes access to the smart colorization from the API, but
that's probably ok as I prefer to not freeze options too early in the
process since API needs to be stable. Probably we should get a concept
of experimental API.
2018-12-12 01:05:12 +08:00
|
|
|
if (options->fill_area != GIMP_BUCKET_FILL_SELECTION)
|
|
|
|
gimp_bucket_fill_tool_halt (bucket_tool);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2007-03-08 23:32:58 +08:00
|
|
|
GIMP_TOOL_CLASS (parent_class)->button_release (tool, coords, time, state,
|
|
|
|
release_type, display);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2001-11-09 03:14:51 +08:00
|
|
|
gimp_bucket_fill_tool_modifier_key (GimpTool *tool,
|
|
|
|
GdkModifierType key,
|
|
|
|
gboolean press,
|
|
|
|
GdkModifierType state,
|
2006-03-29 01:55:52 +08:00
|
|
|
GimpDisplay *display)
|
2001-11-09 03:14:51 +08:00
|
|
|
{
|
2006-09-06 02:25:31 +08:00
|
|
|
GimpBucketFillOptions *options = GIMP_BUCKET_FILL_TOOL_GET_OPTIONS (tool);
|
2001-11-20 21:53:21 +08:00
|
|
|
|
2018-11-28 00:25:05 +08:00
|
|
|
if (key == GDK_MOD1_MASK)
|
2001-11-09 03:14:51 +08:00
|
|
|
{
|
2018-12-08 17:54:38 +08:00
|
|
|
if (press)
|
2001-11-09 03:14:51 +08:00
|
|
|
{
|
2018-12-08 17:54:38 +08:00
|
|
|
GIMP_BUCKET_FILL_TOOL (tool)->priv->fill_mode = options->fill_mode;
|
|
|
|
switch (options->fill_mode)
|
|
|
|
{
|
|
|
|
case GIMP_BUCKET_FILL_FG:
|
|
|
|
g_object_set (options, "fill-mode", GIMP_BUCKET_FILL_BG, NULL);
|
|
|
|
break;
|
2003-02-08 01:12:21 +08:00
|
|
|
|
2018-12-08 17:54:38 +08:00
|
|
|
default: /* GIMP_BUCKET_FILL_BG && GIMP_BUCKET_FILL_PATTERN */
|
|
|
|
g_object_set (options, "fill-mode", GIMP_BUCKET_FILL_FG, NULL);
|
|
|
|
break;
|
2003-02-08 01:12:21 +08:00
|
|
|
|
2018-12-08 17:54:38 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else /* release */
|
|
|
|
{
|
|
|
|
g_object_set (options, "fill-mode",
|
|
|
|
GIMP_BUCKET_FILL_TOOL (tool)->priv->fill_mode,
|
|
|
|
NULL);
|
2001-11-09 03:14:51 +08:00
|
|
|
}
|
|
|
|
}
|
2018-11-28 00:25:05 +08:00
|
|
|
else if (key == gimp_get_toggle_behavior_mask ())
|
|
|
|
{
|
|
|
|
GimpToolInfo *info = gimp_get_tool_info (display->gimp,
|
|
|
|
"gimp-color-picker-tool");
|
|
|
|
if (! gimp_color_tool_is_enabled (GIMP_COLOR_TOOL (tool)))
|
|
|
|
{
|
|
|
|
switch (GIMP_COLOR_TOOL (tool)->pick_target)
|
|
|
|
{
|
|
|
|
case GIMP_COLOR_PICK_TARGET_BACKGROUND:
|
|
|
|
gimp_tool_push_status (tool, display,
|
|
|
|
_("Click in any image to pick the "
|
|
|
|
"background color"));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_COLOR_PICK_TARGET_FOREGROUND:
|
|
|
|
default:
|
|
|
|
gimp_tool_push_status (tool, display,
|
|
|
|
_("Click in any image to pick the "
|
|
|
|
"foreground color"));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
GIMP_TOOL (tool)->display = display;
|
|
|
|
gimp_color_tool_enable (GIMP_COLOR_TOOL (tool),
|
|
|
|
GIMP_COLOR_OPTIONS (info->tool_options));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gimp_tool_pop_status (tool, display);
|
|
|
|
gimp_color_tool_disable (GIMP_COLOR_TOOL (tool));
|
|
|
|
GIMP_TOOL (tool)->display = NULL;
|
|
|
|
}
|
|
|
|
}
|
2015-10-17 21:31:08 +08:00
|
|
|
else if (key == gimp_get_extend_selection_mask ())
|
2004-01-27 23:26:11 +08:00
|
|
|
{
|
app: do not make line art bucket fill a GimpSelectCriterion anymore.
This was my initial choice, but the more I think about it, the less I am
sure this was the right choice. There was some common code (as I was
making a common composite bucket fill once the line art was generated),
but there is also a lot of different code and the functions were filled
of exception when we were doing a line art fill. Also though there is a
bit of color works (the way we decide whether a pixel is part of a
stroke or not, though currently this is basic grayscale threshold), this
is really not the same as other criterions. In particular this was made
obvious on the Select by Color tool where the line art criterion was
completely meaningless and would have had to be opted-out!
This commit split a bit the code. Instead of finding the line art in the
criterion list, I add a third choice to the "Fill whole selection"/"Fill
similar colors" radio. In turn I create a new GimpBucketFillArea type
with the 3 choices, and remove line art value from GimpSelectCriterion.
I am not fully happy yet of this code, as it creates a bit of duplicate
code, and I would appreciate to move some code away from gimpdrawable-*
and gimppickable-* files. This may happen later. I break the work in
pieces to not get too messy.
Also this removes access to the smart colorization from the API, but
that's probably ok as I prefer to not freeze options too early in the
process since API needs to be stable. Probably we should get a concept
of experimental API.
2018-12-12 01:05:12 +08:00
|
|
|
if (press)
|
|
|
|
{
|
|
|
|
GIMP_BUCKET_FILL_TOOL (tool)->priv->fill_area = options->fill_area;
|
|
|
|
switch (options->fill_area)
|
|
|
|
{
|
|
|
|
case GIMP_BUCKET_FILL_SIMILAR_COLORS:
|
|
|
|
g_object_set (options, "fill-area", GIMP_BUCKET_FILL_SELECTION, NULL);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default: /* GIMP_BUCKET_FILL_SELECTION && GIMP_BUCKET_FILL_LINE_ART */
|
|
|
|
g_object_set (options, "fill-area", GIMP_BUCKET_FILL_SIMILAR_COLORS, NULL);
|
|
|
|
break;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else /* release */
|
|
|
|
{
|
|
|
|
g_object_set (options, "fill-area",
|
|
|
|
GIMP_BUCKET_FILL_TOOL (tool)->priv->fill_area,
|
|
|
|
NULL);
|
|
|
|
}
|
2004-01-27 23:26:11 +08:00
|
|
|
}
|
2001-11-09 03:14:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2008-11-01 23:17:36 +08:00
|
|
|
gimp_bucket_fill_tool_cursor_update (GimpTool *tool,
|
|
|
|
const GimpCoords *coords,
|
|
|
|
GdkModifierType state,
|
|
|
|
GimpDisplay *display)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2006-09-06 02:25:31 +08:00
|
|
|
GimpBucketFillOptions *options = GIMP_BUCKET_FILL_TOOL_GET_OPTIONS (tool);
|
2006-06-03 23:41:40 +08:00
|
|
|
GimpCursorModifier modifier = GIMP_CURSOR_MODIFIER_BAD;
|
2009-10-08 01:00:42 +08:00
|
|
|
GimpImage *image = gimp_display_get_image (display);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2009-10-08 01:00:42 +08:00
|
|
|
if (gimp_image_coords_in_active_pickable (image, coords,
|
2006-06-03 23:41:40 +08:00
|
|
|
options->sample_merged, TRUE))
|
1998-01-22 15:02:57 +08:00
|
|
|
{
|
2009-10-08 01:00:42 +08:00
|
|
|
GimpDrawable *drawable = gimp_image_get_active_drawable (image);
|
2006-06-03 23:41:40 +08:00
|
|
|
|
2009-08-29 02:07:14 +08:00
|
|
|
if (! gimp_viewable_get_children (GIMP_VIEWABLE (drawable)) &&
|
2013-04-24 22:27:12 +08:00
|
|
|
! gimp_item_is_content_locked (GIMP_ITEM (drawable)) &&
|
|
|
|
gimp_item_is_visible (GIMP_ITEM (drawable)))
|
2009-08-22 01:34:59 +08:00
|
|
|
{
|
|
|
|
switch (options->fill_mode)
|
|
|
|
{
|
2014-04-30 02:55:08 +08:00
|
|
|
case GIMP_BUCKET_FILL_FG:
|
2009-08-22 01:34:59 +08:00
|
|
|
modifier = GIMP_CURSOR_MODIFIER_FOREGROUND;
|
|
|
|
break;
|
|
|
|
|
2014-04-30 02:55:08 +08:00
|
|
|
case GIMP_BUCKET_FILL_BG:
|
2009-08-22 01:34:59 +08:00
|
|
|
modifier = GIMP_CURSOR_MODIFIER_BACKGROUND;
|
|
|
|
break;
|
|
|
|
|
2014-04-30 02:55:08 +08:00
|
|
|
case GIMP_BUCKET_FILL_PATTERN:
|
2009-08-22 01:34:59 +08:00
|
|
|
modifier = GIMP_CURSOR_MODIFIER_PATTERN;
|
|
|
|
break;
|
|
|
|
}
|
2003-05-08 22:06:03 +08:00
|
|
|
}
|
1998-01-22 15:02:57 +08:00
|
|
|
}
|
2000-07-30 00:12:40 +08:00
|
|
|
|
2006-06-03 23:41:40 +08:00
|
|
|
gimp_tool_control_set_cursor_modifier (tool->control, modifier);
|
2002-02-05 01:43:01 +08:00
|
|
|
|
2006-03-29 01:55:52 +08:00
|
|
|
GIMP_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, display);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
2018-11-04 01:40:50 +08:00
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_bucket_fill_tool_options_notified (GimpBucketFillOptions *options,
|
|
|
|
GParamSpec *pspec,
|
|
|
|
GimpBucketFillTool *tool)
|
|
|
|
{
|
2018-12-02 01:33:51 +08:00
|
|
|
if (! strcmp (pspec->name, "fill-criterion") ||
|
|
|
|
! strcmp (pspec->name, "sample-merged"))
|
2018-11-04 01:40:50 +08:00
|
|
|
{
|
2018-12-02 01:33:51 +08:00
|
|
|
gimp_bucket_fill_reset_line_art (tool, options);
|
2018-11-04 01:40:50 +08:00
|
|
|
}
|
2018-11-28 00:25:05 +08:00
|
|
|
else if (! strcmp (pspec->name, "fill-mode"))
|
|
|
|
{
|
|
|
|
if (gimp_color_tool_is_enabled (GIMP_COLOR_TOOL (tool)))
|
|
|
|
gimp_tool_pop_status (GIMP_TOOL (tool), GIMP_TOOL (tool)->display);
|
|
|
|
|
|
|
|
switch (options->fill_mode)
|
|
|
|
{
|
|
|
|
case GIMP_BUCKET_FILL_BG:
|
|
|
|
GIMP_COLOR_TOOL (tool)->pick_target = GIMP_COLOR_PICK_TARGET_BACKGROUND;
|
|
|
|
if (gimp_color_tool_is_enabled (GIMP_COLOR_TOOL (tool)))
|
|
|
|
gimp_tool_push_status (GIMP_TOOL (tool), GIMP_TOOL (tool)->display,
|
|
|
|
_("Click in any image to pick the "
|
|
|
|
"background color"));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_BUCKET_FILL_FG:
|
|
|
|
default:
|
|
|
|
GIMP_COLOR_TOOL (tool)->pick_target = GIMP_COLOR_PICK_TARGET_FOREGROUND;
|
|
|
|
if (gimp_color_tool_is_enabled (GIMP_COLOR_TOOL (tool)))
|
|
|
|
gimp_tool_push_status (GIMP_TOOL (tool), GIMP_TOOL (tool)->display,
|
|
|
|
_("Click in any image to pick the "
|
|
|
|
"foreground color"));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2018-11-04 01:40:50 +08:00
|
|
|
}
|
|
|
|
|
2018-12-02 01:33:51 +08:00
|
|
|
static void
|
|
|
|
gimp_bucket_fill_reset_line_art (GimpBucketFillTool *tool,
|
|
|
|
GimpBucketFillOptions *options)
|
|
|
|
{
|
|
|
|
GimpImage *prev_image = g_weak_ref_get (&tool->priv->cached_image);
|
|
|
|
GimpContext *context = gimp_get_user_context (GIMP_CONTEXT (options)->gimp);
|
|
|
|
GimpImage *image = gimp_context_get_image (context);
|
|
|
|
|
|
|
|
if (prev_image)
|
|
|
|
{
|
|
|
|
g_signal_handlers_disconnect_by_data (prev_image, tool);
|
|
|
|
g_object_unref (prev_image);
|
|
|
|
}
|
|
|
|
g_weak_ref_set (&tool->priv->cached_image, image ? image : NULL);
|
|
|
|
g_weak_ref_set (&tool->priv->cached_drawable, NULL);
|
|
|
|
|
app: do not make line art bucket fill a GimpSelectCriterion anymore.
This was my initial choice, but the more I think about it, the less I am
sure this was the right choice. There was some common code (as I was
making a common composite bucket fill once the line art was generated),
but there is also a lot of different code and the functions were filled
of exception when we were doing a line art fill. Also though there is a
bit of color works (the way we decide whether a pixel is part of a
stroke or not, though currently this is basic grayscale threshold), this
is really not the same as other criterions. In particular this was made
obvious on the Select by Color tool where the line art criterion was
completely meaningless and would have had to be opted-out!
This commit split a bit the code. Instead of finding the line art in the
criterion list, I add a third choice to the "Fill whole selection"/"Fill
similar colors" radio. In turn I create a new GimpBucketFillArea type
with the 3 choices, and remove line art value from GimpSelectCriterion.
I am not fully happy yet of this code, as it creates a bit of duplicate
code, and I would appreciate to move some code away from gimpdrawable-*
and gimppickable-* files. This may happen later. I break the work in
pieces to not get too messy.
Also this removes access to the smart colorization from the API, but
that's probably ok as I prefer to not freeze options too early in the
process since API needs to be stable. Probably we should get a concept
of experimental API.
2018-12-12 01:05:12 +08:00
|
|
|
if (image && options->fill_area == GIMP_BUCKET_FILL_LINE_ART)
|
2018-12-02 01:33:51 +08:00
|
|
|
{
|
|
|
|
GimpBucketFillOptions *options = GIMP_BUCKET_FILL_TOOL_GET_OPTIONS (tool);
|
|
|
|
GimpDrawable *drawable = gimp_image_get_active_drawable (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);
|
|
|
|
|
|
|
|
g_weak_ref_set (&tool->priv->cached_drawable, drawable ? drawable : NULL);
|
|
|
|
|
|
|
|
if (options->sample_merged)
|
|
|
|
gimp_line_art_set_input (tool->priv->line_art, GIMP_PICKABLE (image));
|
|
|
|
else if (drawable)
|
|
|
|
gimp_line_art_set_input (tool->priv->line_art, GIMP_PICKABLE (drawable));
|
|
|
|
else
|
|
|
|
gimp_line_art_set_input (tool->priv->line_art, NULL);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gimp_line_art_set_input (tool->priv->line_art, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-04 01:40:50 +08:00
|
|
|
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)
|
|
|
|
{
|
|
|
|
if (prev_image)
|
2018-11-19 21:13:03 +08:00
|
|
|
{
|
|
|
|
g_signal_handlers_disconnect_by_data (prev_image, tool);
|
2018-11-04 01:40:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
g_weak_ref_set (&tool->priv->cached_image, image ? image : NULL);
|
|
|
|
g_weak_ref_set (&tool->priv->cached_drawable, NULL);
|
|
|
|
if (image)
|
|
|
|
{
|
2018-12-02 01:33:51 +08:00
|
|
|
GimpBucketFillOptions *options = GIMP_BUCKET_FILL_TOOL_GET_OPTIONS (tool);
|
|
|
|
|
2018-11-04 01:40:50 +08:00
|
|
|
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);
|
2018-12-02 01:33:51 +08:00
|
|
|
|
|
|
|
if (options->sample_merged)
|
|
|
|
gimp_line_art_set_input (tool->priv->line_art,
|
|
|
|
GIMP_PICKABLE (image));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gimp_line_art_set_input (tool->priv->line_art, NULL);
|
2018-11-04 01:40:50 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
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)
|
|
|
|
{
|
2018-12-02 01:33:51 +08:00
|
|
|
GimpBucketFillOptions *options = GIMP_BUCKET_FILL_TOOL_GET_OPTIONS (tool);
|
2018-11-04 01:40:50 +08:00
|
|
|
|
|
|
|
g_weak_ref_set (&tool->priv->cached_drawable, drawable ? drawable : NULL);
|
2018-12-02 01:33:51 +08:00
|
|
|
if (! options->sample_merged)
|
|
|
|
gimp_line_art_set_input (tool->priv->line_art,
|
|
|
|
drawable ? GIMP_PICKABLE (drawable) : NULL);
|
2018-11-04 01:40:50 +08:00
|
|
|
}
|
|
|
|
if (prev_drawable)
|
|
|
|
g_object_unref (prev_drawable);
|
|
|
|
}
|