[gegl] Bug 793690 - gegl_buffer_{copy, clear}() don't emit "changed" signal ...



commit 914490f152d96f99465000cfa1b0f4a698779291
Author: Ell <ell_se yahoo com>
Date:   Wed Feb 21 08:13:33 2018 -0500

    Bug 793690 - gegl_buffer_{copy,clear}() don't emit "changed" signal ...
    
    ... when only affecting whole tiles
    
    gegl_buffer_copy() and gegl_buffer_clear() don't emit a "changed"
    signal themselves, so the signal is only emitted for the affected
    regions that don't span an entire tile, which use an iterator.
    
    Add internal gegl_buffer_{block,unblock}_changed_signal()
    functions, which temporarily prevent the "changed" signal from
    being emitted.  Surround the body of gegl_buffer_{copy,clear}()
    with these functions, to avoid emitting superfluous "changed"
    signals, and emit a single "changed" signal for the entire dst_rect
    at the end of the function.
    
    Do the same for gegl_buffer_set_color(), which always uses an
    iterator and isn't affected by this bug, to avoid emitting multiple
    "changed" signals.

 gegl/buffer/gegl-buffer-access.c  |   17 +++++++++++++++++
 gegl/buffer/gegl-buffer-private.h |    8 ++++++--
 gegl/buffer/gegl-buffer.c         |   17 ++++++++++++++++-
 3 files changed, 39 insertions(+), 3 deletions(-)
---
diff --git a/gegl/buffer/gegl-buffer-access.c b/gegl/buffer/gegl-buffer-access.c
index e613d76..f31b593 100644
--- a/gegl/buffer/gegl-buffer-access.c
+++ b/gegl/buffer/gegl-buffer-access.c
@@ -2251,6 +2251,7 @@ gegl_buffer_copy (GeglBuffer          *src,
       dst_rect = src_rect;
     }
 
+  gegl_buffer_block_changed_signal (dst);
 
   if (src->soft_format == dst->soft_format &&
       src_rect->width >= src->tile_width &&
@@ -2399,6 +2400,10 @@ gegl_buffer_copy (GeglBuffer          *src,
     {
       gegl_buffer_copy2 (src, src_rect, repeat_mode, dst, dst_rect);
     }
+
+  gegl_buffer_unblock_changed_signal (dst);
+
+  gegl_buffer_emit_changed_signal (dst, dst_rect);
 }
 
 static void
@@ -2445,6 +2450,8 @@ gegl_buffer_clear (GeglBuffer          *dst,
       dst_rect = gegl_buffer_get_extent (dst);
     }
 
+  gegl_buffer_block_changed_signal (dst);
+
 #if 1
   /* cow for clearing is currently broken */
   if (!g_object_get_data (G_OBJECT (dst), "is-linear"))
@@ -2543,6 +2550,10 @@ gegl_buffer_clear (GeglBuffer          *dst,
     {
       gegl_buffer_clear2 (dst, dst_rect);
     }
+
+  gegl_buffer_unblock_changed_signal (dst);
+
+  gegl_buffer_emit_changed_signal (dst, dst_rect);
 }
 
 void
@@ -2671,6 +2682,8 @@ gegl_buffer_set_color (GeglBuffer          *dst,
 
   bpp = babl_format_get_bytes_per_pixel (dst->soft_format);
 
+  gegl_buffer_block_changed_signal (dst);
+
   /* FIXME: this can be even further optimized by special casing it so
    * that fully filled tiles are shared.
    */
@@ -2680,6 +2693,10 @@ gegl_buffer_set_color (GeglBuffer          *dst,
     {
       gegl_memset_pattern (i->data[0], pixel, bpp, i->length);
     }
+
+  gegl_buffer_unblock_changed_signal (dst);
+
+  gegl_buffer_emit_changed_signal (dst, dst_rect);
 }
 
 GeglBuffer *
diff --git a/gegl/buffer/gegl-buffer-private.h b/gegl/buffer/gegl-buffer-private.h
index 9df62bf..5662cb6 100644
--- a/gegl/buffer/gegl-buffer-private.h
+++ b/gegl/buffer/gegl-buffer-private.h
@@ -74,6 +74,8 @@ struct _GeglBuffer
 
   gint              changed_signal_connections; /* to avoid firing changed signals
                                                    with no listeners */
+  gint              changed_signal_block_count; /* temporarily block changed
+                                                   signal */
 
   GeglTileBackend  *backend;
 };
@@ -138,8 +140,10 @@ void              gegl_buffer_get_unlocked (GeglBuffer          *buffer,
 GeglBuffer *      gegl_buffer_new_ram     (const GeglRectangle *extent,
                                            const Babl          *format);
 
-void              gegl_buffer_emit_changed_signal (GeglBuffer *buffer,
-                                                   const GeglRectangle *rect);
+void              gegl_buffer_emit_changed_signal    (GeglBuffer *buffer,
+                                                      const GeglRectangle *rect);
+void              gegl_buffer_block_changed_signal   (GeglBuffer *buffer);
+void              gegl_buffer_unblock_changed_signal (GeglBuffer *buffer);
 
 /* the instance size of a GeglTile is a bit large, and should if possible be
  * trimmed down
diff --git a/gegl/buffer/gegl-buffer.c b/gegl/buffer/gegl-buffer.c
index a2480cf..cb84da3 100644
--- a/gegl/buffer/gegl-buffer.c
+++ b/gegl/buffer/gegl-buffer.c
@@ -1190,7 +1190,8 @@ void
 gegl_buffer_emit_changed_signal (GeglBuffer          *buffer,
                                  const GeglRectangle *rect)
 {
-  if (buffer->changed_signal_connections)
+  if (buffer->changed_signal_connections &&
+      buffer->changed_signal_block_count == 0)
   {
     GeglRectangle copy;
 
@@ -1203,6 +1204,20 @@ gegl_buffer_emit_changed_signal (GeglBuffer          *buffer,
   }
 }
 
+void
+gegl_buffer_block_changed_signal (GeglBuffer *buffer)
+{
+  buffer->changed_signal_block_count++;
+}
+
+void
+gegl_buffer_unblock_changed_signal (GeglBuffer *buffer)
+{
+  g_return_if_fail (buffer->changed_signal_block_count > 0);
+
+  buffer->changed_signal_block_count--;
+}
+
 glong gegl_buffer_signal_connect (GeglBuffer *buffer,
                                   const char *detailed_signal,
                                   GCallback   c_handler,


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