[gimp] app: invalidate channel boundary upon buffer "changed" signal



commit d0ae244fe85a502446fe9c7b82afdf1b89498966
Author: Ell <ell_se yahoo com>
Date:   Sat Feb 10 05:26:26 2018 -0500

    app: invalidate channel boundary upon buffer "changed" signal
    
    Have GimpChannel connect to the drawable buffer's "changed" signal,
    so that we can invalidate the channel's boundary whenever the
    buffer contents change.  Currently, the calls to
    gimp_drawable_invalidate_boundary() dispersed throughout the code
    are not enough.
    
    Moreover, invalidate both the boundary and the bounds in
    gimp_channel_invalidate_boundary(), since both are necessary when
    the buffer changes.

 app/core/gimpchannel.c  |  165 ++++++++--------------------------------------
 app/core/gimpdrawable.c |   31 +++++----
 app/core/gimplayer.c    |    8 ++-
 3 files changed, 53 insertions(+), 151 deletions(-)
---
diff --git a/app/core/gimpchannel.c b/app/core/gimpchannel.c
index b6947b3..956a80a 100644
--- a/app/core/gimpchannel.c
+++ b/app/core/gimpchannel.c
@@ -157,39 +157,12 @@ static void gimp_channel_get_active_components (GimpDrawable       *drawable,
 static GimpComponentMask
                   gimp_channel_get_active_mask (GimpDrawable      *drawable);
 
-static void      gimp_channel_apply_buffer   (GimpDrawable        *drawable,
-                                              GeglBuffer          *buffer,
-                                              const GeglRectangle *buffer_region,
-                                              gboolean             push_undo,
-                                              const gchar         *undo_desc,
-                                              gdouble              opacity,
-                                              GimpLayerMode        mode,
-                                              GimpLayerColorSpace  blend_space,
-                                              GimpLayerColorSpace  composite_space,
-                                              GimpLayerCompositeMode composite_mode,
-                                              GeglBuffer          *base_buffer,
-                                              gint                 base_x,
-                                              gint                 base_y);
-static void      gimp_channel_replace_buffer (GimpDrawable        *drawable,
-                                              GeglBuffer          *buffer,
-                                              const GeglRectangle *buffer_region,
-                                              gboolean             push_undo,
-                                              const gchar         *undo_desc,
-                                              gdouble              opacity,
-                                              GeglBuffer          *mask,
-                                              const GeglRectangle *mask_region,
-                                              gint                 x,
-                                              gint                 y);
 static void      gimp_channel_set_buffer     (GimpDrawable        *drawable,
                                               gboolean             push_undo,
                                               const gchar         *undo_desc,
                                               GeglBuffer          *buffer,
                                               gint                 offset_x,
                                               gint                 offset_y);
-static void      gimp_channel_swap_pixels    (GimpDrawable        *drawable,
-                                              GeglBuffer          *buffer,
-                                              gint                 x,
-                                              gint                 y);
 
 static gdouble   gimp_channel_get_opacity_at (GimpPickable        *pickable,
                                               gint                 x,
@@ -237,6 +210,11 @@ static void       gimp_channel_real_flood    (GimpChannel         *channel,
                                               gboolean             push_undo);
 
 
+static void      gimp_channel_buffer_changed (GeglBuffer          *buffer,
+                                              const GeglRectangle *rect,
+                                              GimpChannel         *channel);
+
+
 G_DEFINE_TYPE_WITH_CODE (GimpChannel, gimp_channel, GIMP_TYPE_DRAWABLE,
                          G_IMPLEMENT_INTERFACE (GIMP_TYPE_PICKABLE,
                                                 gimp_channel_pickable_iface_init))
@@ -311,10 +289,7 @@ gimp_channel_class_init (GimpChannelClass *klass)
   drawable_class->invalidate_boundary   = gimp_channel_invalidate_boundary;
   drawable_class->get_active_components = gimp_channel_get_active_components;
   drawable_class->get_active_mask       = gimp_channel_get_active_mask;
-  drawable_class->apply_buffer          = gimp_channel_apply_buffer;
-  drawable_class->replace_buffer        = gimp_channel_replace_buffer;
   drawable_class->set_buffer            = gimp_channel_set_buffer;
-  drawable_class->swap_pixels           = gimp_channel_swap_pixels;
 
   klass->boundary       = gimp_channel_real_boundary;
   klass->is_empty       = gimp_channel_real_is_empty;
@@ -645,8 +620,6 @@ gimp_channel_translate (GimpItem *item,
 
   if (push_undo)
     gimp_channel_push_undo (channel, NULL);
-  else
-    gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (channel));
 
   x1 = CLAMP ((x1 + off_x), 0, gimp_item_get_width  (GIMP_ITEM (channel)));
   y1 = CLAMP ((y1 + off_y), 0, gimp_item_get_height (GIMP_ITEM (channel)));
@@ -991,7 +964,10 @@ gimp_channel_convert_type (GimpDrawable     *drawable,
 static void
 gimp_channel_invalidate_boundary (GimpDrawable *drawable)
 {
-  GIMP_CHANNEL (drawable)->boundary_known = FALSE;
+  GimpChannel *channel = GIMP_CHANNEL (drawable);
+
+  channel->boundary_known = FALSE;
+  channel->bounds_known   = FALSE;
 }
 
 static void
@@ -1011,60 +987,6 @@ gimp_channel_get_active_mask (GimpDrawable *drawable)
 }
 
 static void
-gimp_channel_apply_buffer (GimpDrawable           *drawable,
-                           GeglBuffer             *buffer,
-                           const GeglRectangle    *buffer_region,
-                           gboolean                push_undo,
-                           const gchar            *undo_desc,
-                           gdouble                 opacity,
-                           GimpLayerMode           mode,
-                           GimpLayerColorSpace     blend_space,
-                           GimpLayerColorSpace     composite_space,
-                           GimpLayerCompositeMode  composite_mode,
-                           GeglBuffer             *base_buffer,
-                           gint                    base_x,
-                           gint                    base_y)
-{
-  gimp_drawable_invalidate_boundary (drawable);
-
-  GIMP_DRAWABLE_CLASS (parent_class)->apply_buffer (drawable, buffer,
-                                                    buffer_region,
-                                                    push_undo, undo_desc,
-                                                    opacity, mode,
-                                                    blend_space,
-                                                    composite_space,
-                                                    composite_mode,
-                                                    base_buffer,
-                                                    base_x, base_y);
-
-  GIMP_CHANNEL (drawable)->bounds_known = FALSE;
-}
-
-static void
-gimp_channel_replace_buffer (GimpDrawable        *drawable,
-                             GeglBuffer          *buffer,
-                             const GeglRectangle *buffer_region,
-                             gboolean             push_undo,
-                             const gchar         *undo_desc,
-                             gdouble              opacity,
-                             GeglBuffer          *mask,
-                             const GeglRectangle *mask_region,
-                             gint                 x,
-                             gint                 y)
-{
-  gimp_drawable_invalidate_boundary (drawable);
-
-  GIMP_DRAWABLE_CLASS (parent_class)->replace_buffer (drawable, buffer,
-                                                      buffer_region,
-                                                      push_undo, undo_desc,
-                                                      opacity,
-                                                      mask, mask_region,
-                                                      x, y);
-
-  GIMP_CHANNEL (drawable)->bounds_known = FALSE;
-}
-
-static void
 gimp_channel_set_buffer (GimpDrawable *drawable,
                          gboolean      push_undo,
                          const gchar  *undo_desc,
@@ -1072,14 +994,24 @@ gimp_channel_set_buffer (GimpDrawable *drawable,
                          gint          offset_x,
                          gint          offset_y)
 {
-  GimpChannel *channel = GIMP_CHANNEL (drawable);
+  GimpChannel *channel    = GIMP_CHANNEL (drawable);
+  GeglBuffer  *old_buffer = gimp_drawable_get_buffer (drawable);
+
+  if (old_buffer)
+    {
+      g_signal_handlers_disconnect_by_func (old_buffer,
+                                            gimp_channel_buffer_changed,
+                                            channel);
+    }
 
   GIMP_DRAWABLE_CLASS (parent_class)->set_buffer (drawable,
                                                   push_undo, undo_desc,
                                                   buffer,
                                                   offset_x, offset_y);
 
-  channel->bounds_known = FALSE;
+  gegl_buffer_signal_connect (buffer, "changed",
+                              G_CALLBACK (gimp_channel_buffer_changed),
+                              channel);
 
   if (gimp_filter_peek_node (GIMP_FILTER (channel)))
     {
@@ -1096,19 +1028,6 @@ gimp_channel_set_buffer (GimpDrawable *drawable,
     }
 }
 
-static void
-gimp_channel_swap_pixels (GimpDrawable *drawable,
-                          GeglBuffer   *buffer,
-                          gint          x,
-                          gint          y)
-{
-  gimp_drawable_invalidate_boundary (drawable);
-
-  GIMP_DRAWABLE_CLASS (parent_class)->swap_pixels (drawable, buffer, x, y);
-
-  GIMP_CHANNEL (drawable)->bounds_known = FALSE;
-}
-
 static gdouble
 gimp_channel_get_opacity_at (GimpPickable *pickable,
                              gint          x,
@@ -1273,8 +1192,6 @@ gimp_channel_real_feather (GimpChannel *channel,
   if (push_undo)
     gimp_channel_push_undo (channel,
                             GIMP_CHANNEL_GET_CLASS (channel)->feather_desc);
-  else
-    gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (channel));
 
   gimp_gegl_apply_feather (gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)),
                            NULL, NULL,
@@ -1283,8 +1200,6 @@ gimp_channel_real_feather (GimpChannel *channel,
                            radius_x,
                            radius_y);
 
-  channel->bounds_known = FALSE;
-
   gimp_drawable_update (GIMP_DRAWABLE (channel), 0, 0, -1, -1);
 }
 
@@ -1297,16 +1212,12 @@ gimp_channel_real_sharpen (GimpChannel *channel,
   if (push_undo)
     gimp_channel_push_undo (channel,
                             GIMP_CHANNEL_GET_CLASS (channel)->sharpen_desc);
-  else
-    gimp_drawable_invalidate_boundary (drawable);
 
   gimp_gegl_apply_threshold (gimp_drawable_get_buffer (drawable),
                              NULL, NULL,
                              gimp_drawable_get_buffer (drawable),
                              0.5);
 
-  channel->bounds_known = FALSE;
-
   gimp_drawable_update (GIMP_DRAWABLE (channel), 0, 0, -1, -1);
 }
 
@@ -1322,10 +1233,6 @@ gimp_channel_real_clear (GimpChannel *channel,
 
       gimp_channel_push_undo (channel, undo_desc);
     }
-  else
-    {
-      gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (channel));
-    }
 
   if (channel->bounds_known && ! channel->empty)
     {
@@ -1360,8 +1267,6 @@ gimp_channel_real_all (GimpChannel *channel,
   if (push_undo)
     gimp_channel_push_undo (channel,
                             GIMP_CHANNEL_GET_CLASS (channel)->all_desc);
-  else
-    gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (channel));
 
   /*  clear the channel  */
   color = gegl_color_new ("#fff");
@@ -1389,8 +1294,6 @@ gimp_channel_real_invert (GimpChannel *channel,
   if (push_undo)
     gimp_channel_push_undo (channel,
                             GIMP_CHANNEL_GET_CLASS (channel)->invert_desc);
-  else
-    gimp_drawable_invalidate_boundary (drawable);
 
   if (channel->bounds_known && channel->empty)
     {
@@ -1402,8 +1305,6 @@ gimp_channel_real_invert (GimpChannel *channel,
                                      NULL, NULL,
                                      gimp_drawable_get_buffer (drawable));
 
-      channel->bounds_known = FALSE;
-
       gimp_drawable_update (GIMP_DRAWABLE (channel), 0, 0, -1, -1);
     }
 }
@@ -1469,8 +1370,6 @@ gimp_channel_real_border (GimpChannel            *channel,
   if (push_undo)
     gimp_channel_push_undo (channel,
                             GIMP_CHANNEL_GET_CLASS (channel)->border_desc);
-  else
-    gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (channel));
 
   gimp_gegl_apply_border (gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)),
                           NULL, NULL,
@@ -1478,8 +1377,6 @@ gimp_channel_real_border (GimpChannel            *channel,
                           GEGL_RECTANGLE (x1, y1, x2 - x1, y2 - y1),
                           radius_x, radius_y, style, edge_lock);
 
-  channel->bounds_known = FALSE;
-
   gimp_drawable_update (GIMP_DRAWABLE (channel), 0, 0, -1, -1);
 }
 
@@ -1535,8 +1432,6 @@ gimp_channel_real_grow (GimpChannel *channel,
   if (push_undo)
     gimp_channel_push_undo (channel,
                             GIMP_CHANNEL_GET_CLASS (channel)->grow_desc);
-  else
-    gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (channel));
 
   gimp_gegl_apply_grow (gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)),
                         NULL, NULL,
@@ -1544,8 +1439,6 @@ gimp_channel_real_grow (GimpChannel *channel,
                         GEGL_RECTANGLE (x1, y1, x2 - x1, y2 - y1),
                         radius_x, radius_y);
 
-  channel->bounds_known = FALSE;
-
   gimp_drawable_update (GIMP_DRAWABLE (channel), 0, 0, -1, -1);
 }
 
@@ -1591,8 +1484,6 @@ gimp_channel_real_shrink (GimpChannel *channel,
   if (push_undo)
     gimp_channel_push_undo (channel,
                             GIMP_CHANNEL_GET_CLASS (channel)->shrink_desc);
-  else
-    gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (channel));
 
   gimp_gegl_apply_shrink (gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)),
                           NULL, NULL,
@@ -1600,8 +1491,6 @@ gimp_channel_real_shrink (GimpChannel *channel,
                           GEGL_RECTANGLE (x1, y1, x2 - x1, y2 - y1),
                           radius_x, radius_y, edge_lock);
 
-  channel->bounds_known = FALSE;
-
   gimp_drawable_update (GIMP_DRAWABLE (channel), 0, 0, -1, -1);
 }
 
@@ -1629,6 +1518,14 @@ gimp_channel_real_flood (GimpChannel *channel,
   gimp_drawable_update (GIMP_DRAWABLE (channel), x, y, width, height);
 }
 
+static void
+gimp_channel_buffer_changed (GeglBuffer          *buffer,
+                             const GeglRectangle *rect,
+                             GimpChannel         *channel)
+{
+  gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (channel));
+}
+
 
 /*  public functions  */
 
@@ -1716,8 +1613,6 @@ gimp_channel_new_from_alpha (GimpImage     *image,
                     dest_buffer, NULL);
   gegl_buffer_set_format (dest_buffer, NULL);
 
-  channel->bounds_known = FALSE;
-
   return channel;
 }
 
@@ -1901,8 +1796,6 @@ gimp_channel_push_undo (GimpChannel *channel,
 
   gimp_image_undo_push_mask (gimp_item_get_image (GIMP_ITEM (channel)),
                              undo_desc, channel);
-
-  gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (channel));
 }
 
 
diff --git a/app/core/gimpdrawable.c b/app/core/gimpdrawable.c
index 95c44d7..7a5c71e 100644
--- a/app/core/gimpdrawable.c
+++ b/app/core/gimpdrawable.c
@@ -438,12 +438,12 @@ gimp_drawable_duplicate (GimpItem *item,
     {
       GimpDrawable  *drawable     = GIMP_DRAWABLE (item);
       GimpDrawable  *new_drawable = GIMP_DRAWABLE (new_item);
+      GeglBuffer    *new_buffer;
 
-      if (new_drawable->private->buffer)
-        g_object_unref (new_drawable->private->buffer);
+      new_buffer = gegl_buffer_dup (gimp_drawable_get_buffer (drawable));
 
-      new_drawable->private->buffer =
-        gegl_buffer_dup (gimp_drawable_get_buffer (drawable));
+      gimp_drawable_set_buffer (new_drawable, FALSE, NULL, new_buffer);
+      g_object_unref (new_buffer);
     }
 
   return new_item;
@@ -770,10 +770,8 @@ gimp_drawable_real_set_buffer (GimpDrawable *drawable,
                                gint          offset_x,
                                gint          offset_y)
 {
-  GimpItem *item = GIMP_ITEM (drawable);
-  gboolean  old_has_alpha;
-
-  old_has_alpha = gimp_drawable_has_alpha (drawable);
+  GimpItem *item          = GIMP_ITEM (drawable);
+  gint      old_has_alpha = -1;
 
   g_object_freeze_notify (G_OBJECT (drawable));
 
@@ -787,7 +785,11 @@ gimp_drawable_real_set_buffer (GimpDrawable *drawable,
   g_object_ref (buffer);
 
   if (drawable->private->buffer)
-    g_object_unref (drawable->private->buffer);
+    {
+      old_has_alpha = gimp_drawable_has_alpha (drawable);
+
+      g_object_unref (drawable->private->buffer);
+    }
 
   drawable->private->buffer = buffer;
 
@@ -801,7 +803,8 @@ gimp_drawable_real_set_buffer (GimpDrawable *drawable,
                       gegl_buffer_get_width  (buffer),
                       gegl_buffer_get_height (buffer));
 
-  if (old_has_alpha != gimp_drawable_has_alpha (drawable))
+  if (old_has_alpha >= 0 &&
+      old_has_alpha != gimp_drawable_has_alpha (drawable))
     gimp_drawable_alpha_changed (drawable);
 
   g_object_notify (G_OBJECT (drawable), "buffer");
@@ -894,6 +897,7 @@ gimp_drawable_new (GType          type,
                    const Babl    *format)
 {
   GimpDrawable *drawable;
+  GeglBuffer   *buffer;
 
   g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
   g_return_val_if_fail (g_type_is_a (type, GIMP_TYPE_DRAWABLE), NULL);
@@ -905,9 +909,10 @@ gimp_drawable_new (GType          type,
                                            offset_x, offset_y,
                                            width, height));
 
-  drawable->private->buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0,
-                                                               width, height),
-                                               format);
+  buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, width, height), format);
+
+  gimp_drawable_set_buffer (drawable, FALSE, NULL, buffer);
+  g_object_unref (buffer);
 
   return drawable;
 }
diff --git a/app/core/gimplayer.c b/app/core/gimplayer.c
index a7455a9..9939169 100644
--- a/app/core/gimplayer.c
+++ b/app/core/gimplayer.c
@@ -1382,14 +1382,18 @@ gimp_layer_set_buffer (GimpDrawable *drawable,
                        gint          offset_x,
                        gint          offset_y)
 {
-  gboolean old_linear = gimp_drawable_get_linear (drawable);
+  GeglBuffer *old_buffer = gimp_drawable_get_buffer (drawable);
+  gint        old_linear = -1;
+
+  if (old_buffer)
+    old_linear = gimp_drawable_get_linear (drawable);
 
   GIMP_DRAWABLE_CLASS (parent_class)->set_buffer (drawable,
                                                   push_undo, undo_desc,
                                                   buffer,
                                                   offset_x, offset_y);
 
-  if (gimp_filter_peek_node (GIMP_FILTER (drawable)))
+  if (old_linear >= 0 && gimp_filter_peek_node (GIMP_FILTER (drawable)))
     {
       gboolean new_linear = gimp_drawable_get_linear (drawable);
 


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