[gimp] Issue #287: Impossible to stroke a path with the clone tool.



commit 4c8f50cb23c7795bed35af9116731ebe6a7ac52c
Author: Jehan <jehan girinstud io>
Date:   Fri Feb 4 22:44:54 2022 +0100

    Issue #287: Impossible to stroke a path with the clone tool.
    
    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 6ad00cdbba7). 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.

 app/paint/gimpperspectiveclone.c     | 53 +++++++++++++-------
 app/paint/gimpsourcecore.c           | 97 +++++++++++++++++-------------------
 app/paint/gimpsourcecore.h           |  3 --
 app/paint/gimpsourceoptions.c        | 25 ++++++++++
 app/paint/gimpsourceoptions.h        |  2 +
 app/tools/gimpperspectiveclonetool.c |  6 ++-
 app/tools/gimpsourcetool.c           | 42 ++++++++++------
 7 files changed, 138 insertions(+), 90 deletions(-)
---
diff --git a/app/paint/gimpperspectiveclone.c b/app/paint/gimpperspectiveclone.c
index aa1b49c51b..b8432e7a36 100644
--- a/app/paint/gimpperspectiveclone.c
+++ b/app/paint/gimpperspectiveclone.c
@@ -146,15 +146,19 @@ gimp_perspective_clone_paint (GimpPaintCore    *paint_core,
     case GIMP_PAINT_STATE_INIT:
       if (source_core->set_source)
         {
-          g_object_set (options, "src-drawables", drawables, NULL);
+          gint src_x = floor (coords->x);
+          gint src_y = floor (coords->y);
 
-          source_core->src_x = floor (coords->x);
-          source_core->src_y = floor (coords->y);
+          g_object_set (options,
+                        "src-drawables", drawables,
+                        "src-x",         src_x,
+                        "src-y",         src_y,
+                        NULL);
 
           /* get source coordinates in front view perspective */
           gimp_matrix3_transform_point (&clone->transform_inv,
-                                        source_core->src_x,
-                                        source_core->src_y,
+                                        src_x,
+                                        src_y,
                                         &clone->src_x_fv,
                                         &clone->src_y_fv);
 
@@ -168,8 +172,10 @@ gimp_perspective_clone_paint (GimpPaintCore    *paint_core,
 
           if (options->align_mode == GIMP_SOURCE_ALIGN_NO)
             {
-              source_core->orig_src_x = source_core->src_x;
-              source_core->orig_src_y = source_core->src_y;
+              g_object_get (options,
+                            "src-x", &source_core->orig_src_x,
+                            "src-y", &source_core->orig_src_y,
+                            NULL);
 
               source_core->first_stroke = TRUE;
             }
@@ -294,15 +300,21 @@ gimp_perspective_clone_paint (GimpPaintCore    *paint_core,
     case GIMP_PAINT_STATE_MOTION:
       if (source_core->set_source)
         {
+          gint src_x = floor (coords->x);
+          gint src_y = floor (coords->y);
+
           /*  If the control key is down, move the src target and return */
 
-          source_core->src_x = floor (coords->x);
-          source_core->src_y = floor (coords->y);
+          g_object_set (options,
+                        "src-drawables", drawables,
+                        "src-x",         src_x,
+                        "src-y",         src_y,
+                        NULL);
 
           /* get source coordinates in front view perspective */
           gimp_matrix3_transform_point (&clone->transform_inv,
-                                        source_core->src_x,
-                                        source_core->src_y,
+                                        src_x,
+                                        src_y,
                                         &clone->src_x_fv,
                                         &clone->src_y_fv);
 
@@ -312,11 +324,19 @@ gimp_perspective_clone_paint (GimpPaintCore    *paint_core,
         {
           /*  otherwise, update the target  */
 
+          gint src_x;
+          gint src_y;
+
           gint dest_x;
           gint dest_y;
           gint n_strokes;
           gint i;
 
+          g_object_get (options,
+                        "src-x", &src_x,
+                        "src-y", &src_y,
+                        NULL);
+
           n_strokes = gimp_symmetry_get_size (sym);
           for (i = 0; i < n_strokes; i++)
             {
@@ -332,13 +352,13 @@ gimp_perspective_clone_paint (GimpPaintCore    *paint_core,
                 }
               else if (options->align_mode == GIMP_SOURCE_ALIGN_FIXED)
                 {
-                  source_core->offset_x = source_core->src_x - dest_x;
-                  source_core->offset_y = source_core->src_y - dest_y;
+                  source_core->offset_x = src_x - dest_x;
+                  source_core->offset_y = src_y - dest_y;
                 }
               else if (source_core->first_stroke)
                 {
-                  source_core->offset_x = source_core->src_x - dest_x;
-                  source_core->offset_y = source_core->src_y - dest_y;
+                  source_core->offset_x = src_x - dest_x;
+                  source_core->offset_y = src_y - dest_y;
 
                   /* get destination coordinates in front view perspective */
                   gimp_matrix3_transform_point (&clone->transform_inv,
@@ -367,9 +387,6 @@ gimp_perspective_clone_paint (GimpPaintCore    *paint_core,
     default:
       break;
     }
-
-  g_object_notify (G_OBJECT (clone), "src-x");
-  g_object_notify (G_OBJECT (clone), "src-y");
 }
 
 static gboolean
diff --git a/app/paint/gimpsourcecore.c b/app/paint/gimpsourcecore.c
index 4d07e0a1d9..87be4dab77 100644
--- a/app/paint/gimpsourcecore.c
+++ b/app/paint/gimpsourcecore.c
@@ -46,8 +46,6 @@
 enum
 {
   PROP_0,
-  PROP_SRC_X,
-  PROP_SRC_Y
 };
 
 
@@ -123,18 +121,6 @@ gimp_source_core_class_init (GimpSourceCoreClass *klass)
   klass->use_source                        = gimp_source_core_real_use_source;
   klass->get_source                        = gimp_source_core_real_get_source;
   klass->motion                            = NULL;
-
-  g_object_class_install_property (object_class, PROP_SRC_X,
-                                   g_param_spec_int ("src-x", NULL, NULL,
-                                                     0, GIMP_MAX_IMAGE_SIZE,
-                                                     0,
-                                                     GIMP_PARAM_READWRITE));
-
-  g_object_class_install_property (object_class, PROP_SRC_Y,
-                                   g_param_spec_int ("src-y", NULL, NULL,
-                                                     0, GIMP_MAX_IMAGE_SIZE,
-                                                     0,
-                                                     GIMP_PARAM_READWRITE));
 }
 
 static void
@@ -142,9 +128,6 @@ gimp_source_core_init (GimpSourceCore *source_core)
 {
   source_core->set_source    = FALSE;
 
-  source_core->src_x         = 0;
-  source_core->src_y         = 0;
-
   source_core->orig_src_x    = 0;
   source_core->orig_src_y    = 0;
 
@@ -163,12 +146,6 @@ gimp_source_core_set_property (GObject      *object,
 
   switch (property_id)
     {
-    case PROP_SRC_X:
-      source_core->src_x = g_value_get_int (value);
-      break;
-    case PROP_SRC_Y:
-      source_core->src_y = g_value_get_int (value);
-      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
       break;
@@ -185,12 +162,6 @@ gimp_source_core_get_property (GObject    *object,
 
   switch (property_id)
     {
-    case PROP_SRC_X:
-      g_value_set_int (value, source_core->src_x);
-      break;
-    case PROP_SRC_Y:
-      g_value_set_int (value, source_core->src_y);
-      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
       break;
@@ -265,18 +236,22 @@ gimp_source_core_paint (GimpPaintCore    *paint_core,
     case GIMP_PAINT_STATE_INIT:
       if (source_core->set_source)
         {
-          g_object_set (options, "src-drawables", drawables, NULL);
+          g_object_set (options,
+                        "src-drawables", drawables,
+                        "src-x",         (gint) floor (coords->x),
+                        "src-y",         (gint) floor (coords->y),
+                        NULL);
 
           /* FIXME(?): subpixel source sampling */
-          source_core->src_x = floor (coords->x);
-          source_core->src_y = floor (coords->y);
 
           source_core->first_stroke = TRUE;
         }
       else if (options->align_mode == GIMP_SOURCE_ALIGN_NO)
         {
-          source_core->orig_src_x = source_core->src_x;
-          source_core->orig_src_y = source_core->src_y;
+          g_object_get (options,
+                        "src-x", &source_core->orig_src_x,
+                        "src-y", &source_core->orig_src_y,
+                        NULL);
 
           source_core->first_stroke = TRUE;
         }
@@ -287,8 +262,11 @@ gimp_source_core_paint (GimpPaintCore    *paint_core,
         {
           /*  If the control key is down, move the src target and return */
 
-          source_core->src_x = floor (coords->x);
-          source_core->src_y = floor (coords->y);
+          g_object_set (options,
+                        "src-drawables", drawables,
+                        "src-x",         (gint) floor (coords->x),
+                        "src-y",         (gint) floor (coords->y),
+                        NULL);
 
           source_core->first_stroke = TRUE;
         }
@@ -296,12 +274,20 @@ gimp_source_core_paint (GimpPaintCore    *paint_core,
         {
           /*  otherwise, update the target  */
 
+          gint src_x;
+          gint src_y;
+
           gint dest_x;
           gint dest_y;
 
           dest_x = floor (coords->x);
           dest_y = floor (coords->y);
 
+          g_object_get (options,
+                        "src-x", &src_x,
+                        "src-y", &src_y,
+                        NULL);
+
           if (options->align_mode == GIMP_SOURCE_ALIGN_REGISTERED)
             {
               source_core->offset_x = 0;
@@ -309,19 +295,22 @@ gimp_source_core_paint (GimpPaintCore    *paint_core,
             }
           else if (options->align_mode == GIMP_SOURCE_ALIGN_FIXED)
             {
-              source_core->offset_x = source_core->src_x - dest_x;
-              source_core->offset_y = source_core->src_y - dest_y;
+              source_core->offset_x = src_x - dest_x;
+              source_core->offset_y = src_y - dest_y;
             }
           else if (source_core->first_stroke)
             {
-              source_core->offset_x = source_core->src_x - dest_x;
-              source_core->offset_y = source_core->src_y - dest_y;
+              source_core->offset_x = src_x - dest_x;
+              source_core->offset_y = src_y - dest_y;
 
               source_core->first_stroke = FALSE;
             }
 
-          source_core->src_x = dest_x + source_core->offset_x;
-          source_core->src_y = dest_y + source_core->offset_y;
+          g_object_set (options,
+                        "src-x", dest_x + source_core->offset_x,
+                        "src-y", dest_y + source_core->offset_y,
+                        NULL);
+
 
           for (GList *iter = drawables; iter; iter = iter->next)
             gimp_source_core_motion (source_core, iter->data,
@@ -335,17 +324,17 @@ gimp_source_core_paint (GimpPaintCore    *paint_core,
       if (options->align_mode == GIMP_SOURCE_ALIGN_NO &&
           ! source_core->first_stroke)
         {
-          source_core->src_x = source_core->orig_src_x;
-          source_core->src_y = source_core->orig_src_y;
+          g_object_set (options,
+                        "src-x", source_core->orig_src_x,
+                        "src-y", source_core->orig_src_y,
+                        NULL);
+
         }
       break;
 
     default:
       break;
     }
-
-  g_object_notify (G_OBJECT (source_core), "src-x");
-  g_object_notify (G_OBJECT (source_core), "src-y");
 }
 
 void
@@ -383,6 +372,7 @@ gimp_source_core_motion (GimpSourceCore   *source_core,
   GimpCoords         coords;
   gint               src_off_x = 0;
   gint               src_off_y = 0;
+  gint               src_x, src_y;
   gint               off_x, off_y;
   gint               n_strokes;
   gint               i;
@@ -437,6 +427,11 @@ gimp_source_core_motion (GimpSourceCore   *source_core,
                               &src_off_x, &src_off_y);
     }
 
+  g_object_get (options,
+                "src-x", &src_x,
+                "src-y", &src_y,
+                NULL);
+
   gimp_brush_core_eval_transform_dynamics (brush_core,
                                            image,
                                            paint_options,
@@ -516,8 +511,8 @@ gimp_source_core_motion (GimpSourceCore   *source_core,
           translate_before = gegl_node_new_child (
             node,
             "operation", "gegl:translate",
-            "x",         -(source_core->src_x + 0.5),
-            "y",         -(source_core->src_y + 0.5),
+            "x",         -((gdouble) src_x + 0.5),
+            "y",         -((gdouble) src_y + 0.5),
             NULL);
 
           gegl_node_add_child (node, op);
@@ -525,9 +520,9 @@ gimp_source_core_motion (GimpSourceCore   *source_core,
           translate_after = gegl_node_new_child (
             node,
             "operation", "gegl:translate",
-            "x",         (source_core->src_x + 0.5) +
+            "x",         ((gdouble) src_x + 0.5) +
                          (paint_area_offset_x - src_rect.x),
-            "y",         (source_core->src_y + 0.5) +
+            "y",         ((gdouble) src_y + 0.5) +
                          (paint_area_offset_y - src_rect.y),
             NULL);
 
diff --git a/app/paint/gimpsourcecore.h b/app/paint/gimpsourcecore.h
index 9db8032dfe..178de3b5f1 100644
--- a/app/paint/gimpsourcecore.h
+++ b/app/paint/gimpsourcecore.h
@@ -38,9 +38,6 @@ struct _GimpSourceCore
 
   gboolean       set_source;
 
-  gint           src_x;
-  gint           src_y;
-
   gint           orig_src_x;
   gint           orig_src_y;
 
diff --git a/app/paint/gimpsourceoptions.c b/app/paint/gimpsourceoptions.c
index db119156ae..8f4653293e 100644
--- a/app/paint/gimpsourceoptions.c
+++ b/app/paint/gimpsourceoptions.c
@@ -41,6 +41,8 @@ enum
 {
   PROP_0,
   PROP_SRC_DRAWABLES,
+  PROP_SRC_X,
+  PROP_SRC_Y,
   PROP_ALIGN_MODE,
   PROP_SAMPLE_MERGED
 };
@@ -84,6 +86,17 @@ gimp_source_options_class_init (GimpSourceOptionsClass *klass)
                                                          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"),
@@ -131,6 +144,12 @@ gimp_source_options_set_property (GObject      *object,
       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;
@@ -156,6 +175,12 @@ gimp_source_options_get_property (GObject    *object,
     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;
diff --git a/app/paint/gimpsourceoptions.h b/app/paint/gimpsourceoptions.h
index a5417b9663..1426c4233f 100644
--- a/app/paint/gimpsourceoptions.h
+++ b/app/paint/gimpsourceoptions.h
@@ -37,6 +37,8 @@ struct _GimpSourceOptions
   GimpPaintOptions     parent_instance;
 
   GList               *src_drawables;
+  gint                 src_x;
+  gint                 src_y;
 
   /* The pickable to use when not in sample merged mode. */
   GimpPickable        *src_pickable;
diff --git a/app/tools/gimpperspectiveclonetool.c b/app/tools/gimpperspectiveclonetool.c
index 00c6132b0f..48eec83ef9 100644
--- a/app/tools/gimpperspectiveclonetool.c
+++ b/app/tools/gimpperspectiveclonetool.c
@@ -630,8 +630,10 @@ gimp_perspective_clone_tool_oper_update (GimpTool         *tool,
             {
               gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));
 
-              clone_tool->src_x = source_core->src_x;
-              clone_tool->src_y = source_core->src_y;
+              g_object_get (options,
+                            "src-x", &clone_tool->src_x,
+                            "src-y", &clone_tool->src_y,
+                            NULL);
 
               if (! source_core->first_stroke)
                 {
diff --git a/app/tools/gimpsourcetool.c b/app/tools/gimpsourcetool.c
index d27252462c..ee7ff4d591 100644
--- a/app/tools/gimpsourcetool.c
+++ b/app/tools/gimpsourcetool.c
@@ -170,6 +170,8 @@ gimp_source_tool_control (GimpTool       *tool,
       gimp_source_tool_set_src_display (source_tool, NULL);
       g_object_set (options,
                     "src-drawables", NULL,
+                    "src-x",         0,
+                    "src-y",         0,
                     NULL);
       break;
 
@@ -188,11 +190,12 @@ gimp_source_tool_button_press (GimpTool            *tool,
                                GimpButtonPressType  press_type,
                                GimpDisplay         *display)
 {
-  GimpPaintTool  *paint_tool  = GIMP_PAINT_TOOL (tool);
-  GimpSourceTool *source_tool = GIMP_SOURCE_TOOL (tool);
-  GimpSourceCore *source      = GIMP_SOURCE_CORE (paint_tool->core);
-  GdkModifierType extend_mask = gimp_get_extend_selection_mask ();
-  GdkModifierType toggle_mask = gimp_get_toggle_behavior_mask ();
+  GimpPaintTool     *paint_tool  = GIMP_PAINT_TOOL (tool);
+  GimpSourceTool    *source_tool = GIMP_SOURCE_TOOL (tool);
+  GimpSourceCore    *source      = GIMP_SOURCE_CORE (paint_tool->core);
+  GimpSourceOptions *options     = GIMP_SOURCE_TOOL_GET_OPTIONS (tool);
+  GdkModifierType    extend_mask = gimp_get_extend_selection_mask ();
+  GdkModifierType    toggle_mask = gimp_get_toggle_behavior_mask ();
 
   gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));
 
@@ -210,8 +213,10 @@ gimp_source_tool_button_press (GimpTool            *tool,
   GIMP_TOOL_CLASS (parent_class)->button_press (tool, coords, time, state,
                                                 press_type, display);
 
-  source_tool->src_x = source->src_x;
-  source_tool->src_y = source->src_y;
+  g_object_get (options,
+                "src-x", &source_tool->src_x,
+                "src-y", &source_tool->src_y,
+                NULL);
 
   gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
 }
@@ -223,16 +228,19 @@ gimp_source_tool_motion (GimpTool         *tool,
                          GdkModifierType   state,
                          GimpDisplay      *display)
 {
-  GimpSourceTool *source_tool = GIMP_SOURCE_TOOL (tool);
-  GimpPaintTool  *paint_tool  = GIMP_PAINT_TOOL (tool);
-  GimpSourceCore *source      = GIMP_SOURCE_CORE (paint_tool->core);
+  GimpSourceTool    *source_tool = GIMP_SOURCE_TOOL (tool);
+  GimpPaintTool     *paint_tool  = GIMP_PAINT_TOOL (tool);
+  GimpSourceCore    *source      = GIMP_SOURCE_CORE (paint_tool->core);
+  GimpSourceOptions *options     = GIMP_SOURCE_TOOL_GET_OPTIONS (tool);
 
   gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));
 
   GIMP_TOOL_CLASS (parent_class)->motion (tool, coords, time, state, display);
 
-  source_tool->src_x = source->src_x;
-  source_tool->src_y = source->src_y;
+  g_object_get (options,
+                "src-x", &source_tool->src_x,
+                "src-y", &source_tool->src_y,
+                NULL);
 
   gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
 }
@@ -362,8 +370,10 @@ gimp_source_tool_oper_update (GimpTool         *tool,
         {
           gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));
 
-          source_tool->src_x = source->src_x;
-          source_tool->src_y = source->src_y;
+          g_object_get (options,
+                        "src-x", &source_tool->src_x,
+                        "src-y", &source_tool->src_y,
+                        NULL);
 
           if (! source->first_stroke)
             {
@@ -409,8 +419,8 @@ gimp_source_tool_draw (GimpDrawTool *draw_tool)
 
       src_shell = gimp_display_get_shell (source_tool->src_display);
 
-      src_x = source_tool->src_x + 0.5;
-      src_y = source_tool->src_y + 0.5;
+      src_x = (gdouble) source_tool->src_x + 0.5;
+      src_y = (gdouble) source_tool->src_y + 0.5;
 
       if (source_tool->src_outline)
         {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]