Clone Tool Source Cursor

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

 



Hi, all

To address bug #2184: [gimp-bug] Clone tool samples "sample from"
cursor,
creating artifacts, I'd like to change the cursor behavior in
(what I think) is an unobtrusive way.

When the sampling cursor and destination cursor are within one brush
width
of one another, I'd like to supress the generation of the sample cursor.

Currently the sampling cursor is displayed at all times between button
presses and
releases, even when the two cursors are in close proximity to one
another.
#2184 reports that when this is the case, artifacts are generated.

1. The artifacts arise from the original design of the sampling cursor.
It is not
a hardware cursor, but generated through gdk_draw_lines() writing
directly to
the window. These lines simply invert the hardware colormap, so that
subsequently
overwriting these lines is the same as not writing them at all.

2. The original design  depended on maintaining a correct phase among
(a) overwriting
the sampling cursor to make it "disappear" (b) writing clone pixels,
then (c) writing
the sampling cursor in its new location, making it "reappear"  (a), (b),
and (c) would
then repeat on each mouse motion event.

3. Extensive modifiations and improvements to gdisplay_flush() and
related functions
have effectively changed this sequence to (a)(c)(b), the actual writing
of clone
pixels are buffered and their writing to screen are deferred. This does
not give rise
to artifacts when clone pixels writes are quite far from the sample
points. The erasing
(a) and rewriting (c) strokes flash the sampling cursor off, then on, in
a pointless
but unobtrusive way. But when clone pixels write very near to the sample
point,
(b) partially overwrites the image created by (c), a partial
"untoggling" of inverted
pixels occurs. The next, so-called "erasing" step (a) properly reverts
uncloned pixels,
but improperly inverts cloned pixels. This leaves a partially written
sampling cursor
behind, an artifact.

4. Since artifact generation occurs when the sampling and "real" cursor
almost coincide,
It seems to me that simply supressing the generating of the sampling
cursor is a more
effective means of dealing with bug #2184 than attempting to restore a
delicate phase
relationship through gdisplay buffering code. This alteration does
change user
interface semantics, so I wanted to query the group before committing
the change.

The attached patch is a not-fully-tested implementation that illustrates
the approach.
It is intended to be applied to gimp/app/clone.c, CVS version 1.34
[1999, Nov 17 04:37]

Awaiting opinions, or suggestions to alternate approaches.

Be good, be well

Garry Osgood

--- gimp/app/clone.c       Wed Nov 17 04:37:39 1999
+++ gimp/app/clone.c-patch Fri Dec 17 20:37:08 1999
@@ -287,7 +287,6 @@
            {
              offset_x = src_x - dest_x;
              offset_y = src_y - dest_y;
-             first = FALSE;
            }

          src_x = dest_x + offset_x;
@@ -299,6 +298,8 @@
        }

       draw_core_pause (paint_core->core, active_tool);
+      if (!(paint_core->state & GDK_CONTROL_MASK) && first == TRUE)
+        first = FALSE;
       break;

     case INIT_PAINT :
@@ -324,10 +325,15 @@
     case FINISH_PAINT :
       draw_core_stop (paint_core->core, active_tool);
       if (clone_options->aligned == AlignNo && !first)
-      {
-       src_x = orig_src_x;
-       src_y = orig_src_y;
-      }
+        {
+         src_x = orig_src_x;
+         src_y = orig_src_y;
+        }
+      if (clone_options->aligned == AlignNo)
+        {
+          offset_x = 0;
+          offset_y = 0;
+        }
       return NULL;
       break;

@@ -437,6 +443,27 @@
   paint_core_free (tool);
 }

+gboolean
+clone_proximity_check(PaintCore *paint_core)
+{
+  /* Render clone tool source-of-copy cursor   */
+  /* unless its position is within the greater */
+  /* of x or y brush mask extent.              */
+  /* Address bug 2184 <gosgood@xxxxxxx>        */
+
+  if(first) return TRUE;
+  else
+  {
+    int dx2 = offset_x*offset_x;
+    int dy2 = offset_y*offset_y;
+    int pr  = ((paint_core->brush->mask->width >
paint_core->brush->mask->height)?
+               paint_core->brush->mask->width :
paint_core->brush->mask->height) + 2;
+
+    pr *= pr;
+    return (dx2 + dy2) > pr;
+  }
+}
+
 static void
 clone_draw (Tool *tool)
 {
@@ -446,12 +473,15 @@

   if (paint_core->core->gc != NULL && clone_options->type ==
IMAGE_CLONE)
     {
-      gdk_draw_line (paint_core->core->win, paint_core->core->gc,
-                    trans_tx - (TARGET_WIDTH >> 1), trans_ty,
-                    trans_tx + (TARGET_WIDTH >> 1), trans_ty);
-      gdk_draw_line (paint_core->core->win, paint_core->core->gc,
-                    trans_tx, trans_ty - (TARGET_HEIGHT >> 1),
-                    trans_tx, trans_ty + (TARGET_HEIGHT >> 1));
+      if (clone_proximity_check(paint_core))
+        {
+          gdk_draw_line (paint_core->core->win, paint_core->core->gc,
+                        trans_tx - (TARGET_WIDTH >> 1), trans_ty,
+                        trans_tx + (TARGET_WIDTH >> 1), trans_ty);
+          gdk_draw_line (paint_core->core->win, paint_core->core->gc,
+                        trans_tx, trans_ty - (TARGET_HEIGHT >> 1),
+                        trans_tx, trans_ty + (TARGET_HEIGHT >> 1));
+        }
     }
 }




[Index of Archives]     [Video For Linux]     [Photo]     [Yosemite News]     [gtk]     [GIMP for Windows]     [KDE]     [GEGL]     [Gimp's Home]     [Gimp on GUI]     [Gimp on Windows]     [Steve's Art]

  Powered by Linux