[gimp] app: optimize away redundant and expensive text layer re-rendering



commit 9c4864e789b05b294e5d56e59eb1e9f610150658
Author: Michael Natterer <mitch gimp org>
Date:   Tue Mar 2 17:44:31 2010 +0100

    app: optimize away redundant and expensive text layer re-rendering
    
    - Add signal GimpText::changed() and emit it from
      GObject::dispatch_properties_changed() after all notifications have
      been emitted, so "changed" is emitted only once for any number of
      properties set within a g_object_freeze/thaw_notify() pair.
    - Connect GimpTextLayer to "changed" instead of "notify" so we aviod
      lots of expensive re-rendering when multiple properties are set
      at once.
    - Connect GimpTextTool to "notify" *and* "changed", and move some
      common code to the "changed" callback (e.g. we don't need to
      re-frame the item for each set property).

 app/text/gimptext.c      |   63 +++++++++++++++++++++++++++++++++++-----------
 app/text/gimptext.h      |    2 +
 app/text/gimptextlayer.c |   14 ++++++---
 app/tools/gimptexttool.c |   36 ++++++++++++++++++++++----
 4 files changed, 89 insertions(+), 26 deletions(-)
---
diff --git a/app/text/gimptext.c b/app/text/gimptext.c
index 78843db..117ed94 100644
--- a/app/text/gimptext.c
+++ b/app/text/gimptext.c
@@ -32,6 +32,7 @@
 
 #include "text-types.h"
 
+#include "core/gimpmarshal.h"
 #include "core/gimpstrokeoptions.h"
 #include "core/gimp-utils.h"
 
@@ -69,18 +70,27 @@ enum
   PROP_HINTING
 };
 
+enum
+{
+  CHANGED,
+  LAST_SIGNAL
+};
 
-static void     gimp_text_finalize     (GObject      *object);
-static void     gimp_text_get_property (GObject      *object,
-                                        guint         property_id,
-                                        GValue       *value,
-                                        GParamSpec   *pspec);
-static void     gimp_text_set_property (GObject      *object,
-                                        guint         property_id,
-                                        const GValue *value,
-                                        GParamSpec   *pspec);
-static gint64   gimp_text_get_memsize  (GimpObject   *object,
-                                        gint64       *gui_size);
+
+static void     gimp_text_finalize                    (GObject      *object);
+static void     gimp_text_get_property                (GObject      *object,
+                                                       guint         property_id,
+                                                       GValue       *value,
+                                                       GParamSpec   *pspec);
+static void     gimp_text_set_property                (GObject      *object,
+                                                       guint         property_id,
+                                                       const GValue *value,
+                                                       GParamSpec   *pspec);
+static void     gimp_text_dispatch_properties_changed (GObject      *object,
+                                                       guint         n_pspecs,
+                                                       GParamSpec  **pspecs);
+static gint64   gimp_text_get_memsize                 (GimpObject   *object,
+                                                       gint64       *gui_size);
 
 
 G_DEFINE_TYPE_WITH_CODE (GimpText, gimp_text, GIMP_TYPE_OBJECT,
@@ -88,6 +98,8 @@ G_DEFINE_TYPE_WITH_CODE (GimpText, gimp_text, GIMP_TYPE_OBJECT,
 
 #define parent_class gimp_text_parent_class
 
+static guint text_signals[LAST_SIGNAL] = { 0 };
+
 
 static void
 gimp_text_class_init (GimpTextClass *klass)
@@ -98,11 +110,21 @@ gimp_text_class_init (GimpTextClass *klass)
   GimpMatrix2      identity;
   gchar           *language;
 
-  object_class->finalize         = gimp_text_finalize;
-  object_class->get_property     = gimp_text_get_property;
-  object_class->set_property     = gimp_text_set_property;
+  text_signals[CHANGED] =
+    g_signal_new ("changed",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_FIRST,
+                  G_STRUCT_OFFSET (GimpTextClass, changed),
+                  NULL, NULL,
+                  gimp_marshal_VOID__VOID,
+                  G_TYPE_NONE, 0);
+
+  object_class->finalize                    = gimp_text_finalize;
+  object_class->get_property                = gimp_text_get_property;
+  object_class->set_property                = gimp_text_set_property;
+  object_class->dispatch_properties_changed = gimp_text_dispatch_properties_changed;
 
-  gimp_object_class->get_memsize = gimp_text_get_memsize;
+  gimp_object_class->get_memsize            = gimp_text_get_memsize;
 
   gimp_rgba_set (&black, 0.0, 0.0, 0.0, GIMP_OPACITY_OPAQUE);
   gimp_matrix2_identity (&identity);
@@ -480,6 +502,17 @@ gimp_text_set_property (GObject      *object,
     }
 }
 
+static void
+gimp_text_dispatch_properties_changed (GObject     *object,
+                                       guint        n_pspecs,
+                                       GParamSpec **pspecs)
+{
+  G_OBJECT_CLASS (parent_class)->dispatch_properties_changed (object,
+                                                              n_pspecs, pspecs);
+
+  g_signal_emit (object, text_signals[CHANGED], 0);
+}
+
 static gint64
 gimp_text_get_memsize (GimpObject *object,
                        gint64     *gui_size)
diff --git a/app/text/gimptext.h b/app/text/gimptext.h
index 27048ac..466f825 100644
--- a/app/text/gimptext.h
+++ b/app/text/gimptext.h
@@ -70,6 +70,8 @@ struct _GimpText
 struct _GimpTextClass
 {
   GimpObjectClass        parent_class;
+
+  void (* changed) (GimpText *text);
 };
 
 
diff --git a/app/text/gimptextlayer.c b/app/text/gimptextlayer.c
index a988c4d..e1edb1a 100644
--- a/app/text/gimptextlayer.c
+++ b/app/text/gimptextlayer.c
@@ -97,7 +97,7 @@ static void       gimp_text_layer_push_undo      (GimpDrawable    *drawable,
                                                   gint             width,
                                                   gint             height);
 
-static void       gimp_text_layer_text_notify    (GimpTextLayer   *layer);
+static void       gimp_text_layer_text_changed   (GimpTextLayer   *layer);
 static gboolean   gimp_text_layer_render         (GimpTextLayer   *layer);
 static void       gimp_text_layer_render_layout  (GimpTextLayer   *layer,
                                                   GimpTextLayout  *layout);
@@ -351,6 +351,8 @@ gimp_text_layer_push_undo (GimpDrawable *drawable,
 }
 
 
+/*  public functions  */
+
 /**
  * gimp_text_layer_new:
  * @image: the #GimpImage the layer should belong to
@@ -404,7 +406,7 @@ gimp_text_layer_set_text (GimpTextLayer *layer,
   if (layer->text)
     {
       g_signal_handlers_disconnect_by_func (layer->text,
-                                            G_CALLBACK (gimp_text_layer_text_notify),
+                                            G_CALLBACK (gimp_text_layer_text_changed),
                                             layer);
 
       g_object_unref (layer->text);
@@ -415,8 +417,8 @@ gimp_text_layer_set_text (GimpTextLayer *layer,
     {
       layer->text = g_object_ref (text);
 
-      g_signal_connect_object (text, "notify",
-                               G_CALLBACK (gimp_text_layer_text_notify),
+      g_signal_connect_object (text, "changed",
+                               G_CALLBACK (gimp_text_layer_text_changed),
                                layer, G_CONNECT_SWAPPED);
     }
 
@@ -511,8 +513,10 @@ gimp_drawable_is_text_layer (GimpDrawable *drawable)
 }
 
 
+/*  private functions  */
+
 static void
-gimp_text_layer_text_notify (GimpTextLayer *layer)
+gimp_text_layer_text_changed (GimpTextLayer *layer)
 {
   /*   If the text layer was created from a parasite, it's time to
    *   remove that parasite now.
diff --git a/app/tools/gimptexttool.c b/app/tools/gimptexttool.c
index a82d1cd..f90fdc2 100644
--- a/app/tools/gimptexttool.c
+++ b/app/tools/gimptexttool.c
@@ -143,9 +143,13 @@ static void      gimp_text_tool_layer_notify    (GimpTextLayer     *layer,
 static void      gimp_text_tool_proxy_notify    (GimpText          *text,
                                                  GParamSpec        *pspec,
                                                  GimpTextTool      *text_tool);
+
 static void      gimp_text_tool_text_notify     (GimpText          *text,
                                                  GParamSpec        *pspec,
                                                  GimpTextTool      *text_tool);
+static void      gimp_text_tool_text_changed    (GimpText          *text,
+                                                 GimpTextTool      *text_tool);
+
 static gboolean  gimp_text_tool_idle_apply      (GimpTextTool      *text_tool);
 static void      gimp_text_tool_apply           (GimpTextTool      *text_tool);
 
@@ -738,7 +742,6 @@ gimp_text_tool_draw (GimpDrawTool *draw_tool)
 
       gimp_text_tool_draw_selection (draw_tool,
                                      logical_offset_x, logical_offset_y);
-
     }
   else
     {
@@ -930,6 +933,9 @@ gimp_text_tool_connect (GimpTextTool  *text_tool,
           g_signal_handlers_disconnect_by_func (text_tool->text,
                                                 gimp_text_tool_text_notify,
                                                 text_tool);
+          g_signal_handlers_disconnect_by_func (text_tool->text,
+                                                gimp_text_tool_text_changed,
+                                                text_tool);
 
           if (text_tool->pending)
             gimp_text_tool_apply (text_tool);
@@ -963,6 +969,9 @@ gimp_text_tool_connect (GimpTextTool  *text_tool,
           g_signal_connect (text, "notify",
                             G_CALLBACK (gimp_text_tool_text_notify),
                             text_tool);
+          g_signal_connect (text, "changed",
+                            G_CALLBACK (gimp_text_tool_text_changed),
+                            text_tool);
         }
 
       g_signal_handlers_unblock_by_func (text_tool->buffer,
@@ -1048,11 +1057,6 @@ gimp_text_tool_text_notify (GimpText     *text,
       g_value_unset (&value);
     }
 
-  /* we need to redraw the rectangle in any case because whatever
-   * changes to the text can change its size
-   */
-  gimp_text_tool_frame_item (text_tool);
-
   /* if the text has changed, (probably because of an undo), we put
    * the new text into the text buffer
    */
@@ -1073,6 +1077,20 @@ gimp_text_tool_text_notify (GimpText     *text,
                                          text_tool);
     }
 
+  gimp_draw_tool_resume (GIMP_DRAW_TOOL (text_tool));
+}
+
+static void
+gimp_text_tool_text_changed (GimpText     *text,
+                             GimpTextTool *text_tool)
+{
+  gimp_draw_tool_pause (GIMP_DRAW_TOOL (text_tool));
+
+  /* we need to redraw the rectangle in any case because whatever
+   * changes to the text can change its size
+   */
+  gimp_text_tool_frame_item (text_tool);
+
   gimp_text_tool_clear_layout (text_tool);
 
   gimp_draw_tool_resume (GIMP_DRAW_TOOL (text_tool));
@@ -1184,6 +1202,9 @@ gimp_text_tool_apply (GimpTextTool *text_tool)
   g_signal_handlers_block_by_func (dest,
                                    gimp_text_tool_text_notify,
                                    text_tool);
+  g_signal_handlers_block_by_func (dest,
+                                   gimp_text_tool_text_changed,
+                                   text_tool);
 
   g_object_freeze_notify (dest);
 
@@ -1213,6 +1234,9 @@ gimp_text_tool_apply (GimpTextTool *text_tool)
   g_signal_handlers_unblock_by_func (dest,
                                      gimp_text_tool_text_notify,
                                      text_tool);
+  g_signal_handlers_unblock_by_func (dest,
+                                     gimp_text_tool_text_changed,
+                                     text_tool);
 
   if (push_undo)
     {



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