Actually we had half of the fix already with my recent change to source
tools giving the ability to clone from multiple source drawables where I
moved the source drawables from GimpSourceCore to GimpSourceOptions (see
commit 6ad00cdbba). The problem is that gimp_vectors_stroke() is using
the context paint options, but it is creating a brand new paint core
just to stroke the path. Hence with my recent changes, the drawable
sources were finally available to the path stroke, yet not the source
position. So stroking with clone was always starting on position (0, 0)
on the source.
This is now fixed by moving also the position properties "src-x" and
"src-y" on the GimpSourceOptions. This makes this info finally
accessible to the core when running the source tools this way.
Thanks to Eneko Castresana Vara for their initial contribution.
Unfortunately the code had diverged too much for it to be usable because
of our much too late review so a different fix had to be done.
293 lines
9.7 KiB
C
293 lines
9.7 KiB
C
/* GIMP - The GNU Image Manipulation Program
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
* (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
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <gdk-pixbuf/gdk-pixbuf.h>
|
|
#include <gegl.h>
|
|
|
|
#include "libgimpbase/gimpbase.h"
|
|
#include "libgimpconfig/gimpconfig.h"
|
|
|
|
#include "paint-types.h"
|
|
|
|
#include "core/gimp.h"
|
|
#include "core/gimpcontainer.h"
|
|
#include "core/gimpimage.h"
|
|
#include "core/gimpimage-new.h"
|
|
#include "core/gimpitem.h"
|
|
#include "core/gimppickable.h"
|
|
|
|
#include "gimpsourceoptions.h"
|
|
|
|
#include "gimp-intl.h"
|
|
|
|
|
|
enum
|
|
{
|
|
PROP_0,
|
|
PROP_SRC_DRAWABLES,
|
|
PROP_SRC_X,
|
|
PROP_SRC_Y,
|
|
PROP_ALIGN_MODE,
|
|
PROP_SAMPLE_MERGED
|
|
};
|
|
|
|
|
|
static void gimp_source_options_finalize (GObject *object);
|
|
static void gimp_source_options_set_property (GObject *object,
|
|
guint property_id,
|
|
const GValue *value,
|
|
GParamSpec *pspec);
|
|
static void gimp_source_options_get_property (GObject *object,
|
|
guint property_id,
|
|
GValue *value,
|
|
GParamSpec *pspec);
|
|
|
|
static void
|
|
gimp_source_options_set_src_drawables (GimpSourceOptions *options,
|
|
GList *drawables);
|
|
static void
|
|
gimp_source_options_src_drawable_removed (GimpDrawable *drawable,
|
|
GimpSourceOptions *options);
|
|
static void gimp_source_options_make_pickable (GimpSourceOptions *options);
|
|
|
|
|
|
G_DEFINE_TYPE (GimpSourceOptions, gimp_source_options, GIMP_TYPE_PAINT_OPTIONS)
|
|
|
|
#define parent_class gimp_source_options_parent_class
|
|
|
|
|
|
static void
|
|
gimp_source_options_class_init (GimpSourceOptionsClass *klass)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
object_class->finalize = gimp_source_options_finalize;
|
|
object_class->set_property = gimp_source_options_set_property;
|
|
object_class->get_property = gimp_source_options_get_property;
|
|
|
|
g_object_class_install_property (object_class, PROP_SRC_DRAWABLES,
|
|
g_param_spec_pointer ("src-drawables",
|
|
NULL, NULL,
|
|
GIMP_PARAM_READWRITE));
|
|
|
|
g_object_class_install_property (object_class, PROP_SRC_X,
|
|
g_param_spec_int ("src-x",
|
|
NULL, NULL,
|
|
G_MININT, G_MAXINT, 0,
|
|
GIMP_PARAM_READWRITE));
|
|
g_object_class_install_property (object_class, PROP_SRC_Y,
|
|
g_param_spec_int ("src-y",
|
|
NULL, NULL,
|
|
G_MININT, G_MAXINT, 0,
|
|
GIMP_PARAM_READWRITE));
|
|
|
|
GIMP_CONFIG_PROP_ENUM (object_class, PROP_ALIGN_MODE,
|
|
"align-mode",
|
|
_("Alignment"),
|
|
NULL,
|
|
GIMP_TYPE_SOURCE_ALIGN_MODE,
|
|
GIMP_SOURCE_ALIGN_NO,
|
|
GIMP_PARAM_STATIC_STRINGS);
|
|
|
|
GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_SAMPLE_MERGED,
|
|
"sample-merged",
|
|
_("Sample merged"),
|
|
NULL,
|
|
FALSE,
|
|
GIMP_PARAM_STATIC_STRINGS);
|
|
}
|
|
|
|
static void
|
|
gimp_source_options_init (GimpSourceOptions *options)
|
|
{
|
|
options->src_drawables = NULL;
|
|
}
|
|
|
|
static void
|
|
gimp_source_options_finalize (GObject *object)
|
|
{
|
|
GimpSourceOptions *options = GIMP_SOURCE_OPTIONS (object);
|
|
|
|
gimp_source_options_set_src_drawables (options, NULL);
|
|
g_clear_object (&options->src_image);
|
|
|
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
gimp_source_options_set_property (GObject *object,
|
|
guint property_id,
|
|
const GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
GimpSourceOptions *options = GIMP_SOURCE_OPTIONS (object);
|
|
|
|
switch (property_id)
|
|
{
|
|
case PROP_SRC_DRAWABLES:
|
|
gimp_source_options_set_src_drawables (options,
|
|
g_value_get_pointer (value));
|
|
break;
|
|
case PROP_SRC_X:
|
|
options->src_x = g_value_get_int (value);
|
|
break;
|
|
case PROP_SRC_Y:
|
|
options->src_y = g_value_get_int (value);
|
|
break;
|
|
case PROP_ALIGN_MODE:
|
|
options->align_mode = g_value_get_enum (value);
|
|
break;
|
|
case PROP_SAMPLE_MERGED:
|
|
options->sample_merged = g_value_get_boolean (value);
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gimp_source_options_get_property (GObject *object,
|
|
guint property_id,
|
|
GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
GimpSourceOptions *options = GIMP_SOURCE_OPTIONS (object);
|
|
|
|
switch (property_id)
|
|
{
|
|
case PROP_SRC_DRAWABLES:
|
|
g_value_set_pointer (value, options->src_drawables);
|
|
break;
|
|
case PROP_SRC_X:
|
|
g_value_set_int (value, options->src_x);
|
|
break;
|
|
case PROP_SRC_Y:
|
|
g_value_set_int (value, options->src_y);
|
|
break;
|
|
case PROP_ALIGN_MODE:
|
|
g_value_set_enum (value, options->align_mode);
|
|
break;
|
|
case PROP_SAMPLE_MERGED:
|
|
g_value_set_boolean (value, options->sample_merged);
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gimp_source_options_set_src_drawables (GimpSourceOptions *options,
|
|
GList *drawables)
|
|
{
|
|
GimpImage *image = NULL;
|
|
GList *iter;
|
|
|
|
if (g_list_length (options->src_drawables) == g_list_length (drawables))
|
|
{
|
|
GList *iter2;
|
|
|
|
for (iter = options->src_drawables, iter2 = drawables;
|
|
iter; iter = iter->next, iter2 = iter2->next)
|
|
{
|
|
if (iter->data != iter2->data)
|
|
break;
|
|
}
|
|
if (iter == NULL)
|
|
return;
|
|
}
|
|
for (GList *iter = drawables; iter; iter = iter->next)
|
|
{
|
|
/* Make sure all drawables are from the same image. */
|
|
if (image == NULL)
|
|
image = gimp_item_get_image (GIMP_ITEM (iter->data));
|
|
else
|
|
g_return_if_fail (image == gimp_item_get_image (GIMP_ITEM (iter->data)));
|
|
}
|
|
|
|
if (options->src_drawables)
|
|
{
|
|
for (GList *iter = options->src_drawables; iter; iter = iter->next)
|
|
g_signal_handlers_disconnect_by_func (iter->data,
|
|
gimp_source_options_src_drawable_removed,
|
|
options);
|
|
|
|
g_list_free (options->src_drawables);
|
|
}
|
|
|
|
options->src_drawables = g_list_copy (drawables);
|
|
|
|
if (options->src_drawables)
|
|
{
|
|
for (GList *iter = options->src_drawables; iter; iter = iter->next)
|
|
g_signal_connect (iter->data, "removed",
|
|
G_CALLBACK (gimp_source_options_src_drawable_removed),
|
|
options);
|
|
}
|
|
|
|
gimp_source_options_make_pickable (options);
|
|
g_object_notify (G_OBJECT (options), "src-drawables");
|
|
}
|
|
|
|
static void
|
|
gimp_source_options_src_drawable_removed (GimpDrawable *drawable,
|
|
GimpSourceOptions *options)
|
|
{
|
|
options->src_drawables = g_list_remove (options->src_drawables, drawable);
|
|
|
|
g_signal_handlers_disconnect_by_func (drawable,
|
|
gimp_source_options_src_drawable_removed,
|
|
options);
|
|
|
|
gimp_source_options_make_pickable (options);
|
|
g_object_notify (G_OBJECT (options), "src-drawables");
|
|
}
|
|
|
|
static void
|
|
gimp_source_options_make_pickable (GimpSourceOptions *options)
|
|
{
|
|
g_clear_object (&options->src_image);
|
|
options->src_pickable = NULL;
|
|
|
|
if (options->src_drawables)
|
|
{
|
|
GimpImage *image;
|
|
|
|
image = gimp_item_get_image (GIMP_ITEM (options->src_drawables->data));
|
|
|
|
if (g_list_length (options->src_drawables) > 1)
|
|
{
|
|
/* A composited projection of src_drawables as if they were on
|
|
* their own in the image. Some kind of sample_merged limited
|
|
* to these drawables.
|
|
*/
|
|
options->src_image = gimp_image_new_from_drawables (image->gimp, options->src_drawables,
|
|
FALSE);
|
|
gimp_container_remove (image->gimp->images, GIMP_OBJECT (options->src_image));
|
|
|
|
options->src_pickable = GIMP_PICKABLE (options->src_image);
|
|
gimp_pickable_flush (options->src_pickable);
|
|
}
|
|
else
|
|
{
|
|
options->src_pickable = GIMP_PICKABLE (options->src_drawables->data);
|
|
}
|
|
}
|
|
}
|