[gimp] app: fix symmetry transform in Clone/Heal tools when brush is cropped



commit a701032b4ea9e3588aea38de5d447db5091e3ccf
Author: Ell <ell_se yahoo com>
Date:   Wed May 29 04:58:17 2019 -0400

    app: fix symmetry transform in Clone/Heal tools when brush is cropped
    
    In GimpSourceCore, when applying a symmetry transform to the source
    content, combine the transform op with translation to the paint-
    buffer coordinates, so that subclasses (namely, GimpClone and
    GimpHeal) can use the op to apply the transformation directly from
    the source buffer to the paint buffer in a single step.  This is
    both more efficient, and avoids incorrect symmetry transforms when
    the paint buffer is cropped to the bounds of the drawable.

 app/paint/gimpclone.c      | 35 ++++++++++++++++++------------
 app/paint/gimpheal.c       | 30 ++++++++++++--------------
 app/paint/gimpsourcecore.c | 54 +++++++++++++++++++++++++++++++++++++++++-----
 3 files changed, 84 insertions(+), 35 deletions(-)
---
diff --git a/app/paint/gimpclone.c b/app/paint/gimpclone.c
index 464a3a4ba4..9c807f43ff 100644
--- a/app/paint/gimpclone.c
+++ b/app/paint/gimpclone.c
@@ -169,21 +169,28 @@ gimp_clone_motion (GimpSourceCore   *source_core,
 
   if (gimp_source_core_use_source (source_core, source_options))
     {
-      gimp_gegl_buffer_copy (src_buffer,
-                             GEGL_RECTANGLE (src_rect->x,
-                                             src_rect->y,
-                                             paint_area_width,
-                                             paint_area_height),
-                             GEGL_ABYSS_NONE,
-                             paint_buffer,
-                             GEGL_RECTANGLE (paint_area_offset_x,
-                                             paint_area_offset_y,
-                                             0, 0));
-
-      if (op)
+      if (! op)
         {
-          gimp_gegl_apply_operation (paint_buffer, NULL, NULL, op,
-                                     paint_buffer, NULL, FALSE);
+          gimp_gegl_buffer_copy (src_buffer,
+                                 GEGL_RECTANGLE (src_rect->x,
+                                                 src_rect->y,
+                                                 paint_area_width,
+                                                 paint_area_height),
+                                 GEGL_ABYSS_NONE,
+                                 paint_buffer,
+                                 GEGL_RECTANGLE (paint_area_offset_x,
+                                                 paint_area_offset_y,
+                                                 0, 0));
+        }
+      else
+        {
+          gimp_gegl_apply_operation (src_buffer, NULL, NULL, op,
+                                     paint_buffer,
+                                     GEGL_RECTANGLE (paint_area_offset_x,
+                                                     paint_area_offset_y,
+                                                     paint_area_width,
+                                                     paint_area_height),
+                                     FALSE);
         }
     }
   else if (options->clone_type == GIMP_CLONE_PATTERN)
diff --git a/app/paint/gimpheal.c b/app/paint/gimpheal.c
index 2901df3315..8f7451a3b2 100644
--- a/app/paint/gimpheal.c
+++ b/app/paint/gimpheal.c
@@ -560,16 +560,23 @@ gimp_heal_motion (GimpSourceCore   *source_core,
     }
 
   /*  heal should work in perceptual space, use R'G'B' instead of RGB  */
-  src_copy = gegl_buffer_new (GEGL_RECTANGLE (0, 0,
+  src_copy = gegl_buffer_new (GEGL_RECTANGLE (paint_area_offset_x,
+                                              paint_area_offset_y,
                                               src_rect->width,
                                               src_rect->height),
                               babl_format ("R'G'B'A float"));
 
-  gimp_gegl_buffer_copy (src_buffer, src_rect, GEGL_ABYSS_NONE,
-                         src_copy,
-                         GEGL_RECTANGLE (0, 0,
-                                         src_rect->width,
-                                         src_rect->height));
+  if (! op)
+    {
+      gimp_gegl_buffer_copy (src_buffer, src_rect, GEGL_ABYSS_NONE,
+                             src_copy, gegl_buffer_get_extent (src_copy));
+    }
+  else
+    {
+      gimp_gegl_apply_operation (src_buffer, NULL, NULL, op,
+                                 src_copy, gegl_buffer_get_extent (src_copy),
+                                 FALSE);
+    }
 
   if (src_options->sample_merged)
     {
@@ -610,16 +617,7 @@ gimp_heal_motion (GimpSourceCore   *source_core,
     mask_off_y = (y < 0) ? -y : 0;
   }
 
-  if (op)
-    {
-      gimp_gegl_apply_operation (src_copy, NULL, NULL, op,
-                                 src_copy, NULL, FALSE);
-    }
-
-  gimp_heal (src_copy,
-             GEGL_RECTANGLE (0, 0,
-                             gegl_buffer_get_width  (src_copy),
-                             gegl_buffer_get_height (src_copy)),
+  gimp_heal (src_copy, gegl_buffer_get_extent (src_copy),
              paint_buffer,
              GEGL_RECTANGLE (paint_area_offset_x,
                              paint_area_offset_y,
diff --git a/app/paint/gimpsourcecore.c b/app/paint/gimpsourcecore.c
index bfa81d20ed..02db2186f6 100644
--- a/app/paint/gimpsourcecore.c
+++ b/app/paint/gimpsourcecore.c
@@ -480,9 +480,52 @@ gimp_source_core_motion (GimpSourceCore   *source_core,
       /*  Set the paint buffer to transparent  */
       gegl_buffer_clear (paint_buffer, NULL);
 
-      op = gimp_symmetry_get_operation (sym, i,
-                                        gegl_buffer_get_width (paint_buffer),
-                                        gegl_buffer_get_height (paint_buffer));
+      op = gimp_symmetry_get_operation (sym, i);
+
+      if (op)
+        {
+          GeglNode *node;
+          GeglNode *input;
+          GeglNode *translate_before;
+          GeglNode *translate_after;
+          GeglNode *output;
+
+          node = gegl_node_new ();
+
+          input = gegl_node_get_input_proxy (node, "input");
+
+          translate_before = gegl_node_new_child (
+            node,
+            "operation", "gegl:translate",
+            "x",         -(source_core->src_x + 0.5),
+            "y",         -(source_core->src_y + 0.5),
+            NULL);
+
+          gegl_node_add_child (node, op);
+
+          translate_after = gegl_node_new_child (
+            node,
+            "operation", "gegl:translate",
+            "x",         (source_core->src_x + 0.5) +
+                         (paint_area_offset_x - src_rect.x),
+            "y",         (source_core->src_y + 0.5) +
+                         (paint_area_offset_y - src_rect.y),
+            NULL);
+
+          output = gegl_node_get_output_proxy (node, "output");
+
+          gegl_node_link_many (input,
+                               translate_before,
+                               op,
+                               translate_after,
+                               output,
+                               NULL);
+
+          g_object_unref (op);
+
+          op = node;
+        }
+
       GIMP_SOURCE_CORE_GET_CLASS (source_core)->motion (source_core,
                                                         drawable,
                                                         paint_options,
@@ -502,8 +545,9 @@ gimp_source_core_motion (GimpSourceCore   *source_core,
                                                         paint_area_width,
                                                         paint_area_height);
 
-      if (src_buffer)
-        g_object_unref (src_buffer);
+      g_clear_object (&op);
+
+      g_clear_object (&src_buffer);
     }
 }
 


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