[gtk/wip/chergert/speedup-char_is_invisible] textbtree: short-circuit visibility check when possible



commit 6c8d47f5855cfbed8298a65d9d5315a4655468d3
Author: Christian Hergert <chergert redhat com>
Date:   Wed Mar 18 11:32:46 2020 -0700

    textbtree: short-circuit visibility check when possible
    
    If we have never seen a GtkTextTag in the GtkTextTagTable with the
    invisible bit set, then we do not need to go through the process of
    checking the accumulated tags.
    
    Not using invisible tags is overwhelmingly the common case.

 gtk/gtktextbtree.c           |  9 ++++++++-
 gtk/gtktexttagtable.c        | 27 +++++++++++++++++++++++++++
 gtk/gtktexttagtableprivate.h | 15 ++++++++-------
 3 files changed, 43 insertions(+), 8 deletions(-)
---
diff --git a/gtk/gtktextbtree.c b/gtk/gtktextbtree.c
index 1ab7878539..65aae142e1 100644
--- a/gtk/gtktextbtree.c
+++ b/gtk/gtktextbtree.c
@@ -60,7 +60,7 @@
 #include "gtktextbufferprivate.h"
 #include "gtktexttag.h"
 #include "gtktexttagprivate.h"
-#include "gtktexttagtable.h"
+#include "gtktexttagtableprivate.h"
 #include "gtktextlayoutprivate.h"
 #include "gtktextiterprivate.h"
 #include "gtkdebug.h"
@@ -2491,6 +2491,13 @@ _gtk_text_btree_char_is_invisible (const GtkTextIter *iter)
 
   line = _gtk_text_iter_get_text_line (iter);
   tree = _gtk_text_iter_get_btree (iter);
+
+  /* Short-circuit if we've never seen a visibility tag within the
+   * tag table (meaning everything must be visible).
+   */
+  if G_LIKELY (!_gtk_text_tag_table_affects_visibility (tree->table))
+    return FALSE;
+
   byte_index = gtk_text_iter_get_line_index (iter);
 
   numTags = gtk_text_tag_table_get_size (tree->table);
diff --git a/gtk/gtktexttagtable.c b/gtk/gtktexttagtable.c
index 81a852ccc3..c28621edd6 100644
--- a/gtk/gtktexttagtable.c
+++ b/gtk/gtktexttagtable.c
@@ -88,6 +88,8 @@ struct _GtkTextTagTablePrivate
   GSList     *buffers;
 
   gint anon_count;
+
+  guint seen_invisible : 1;
 };
 
 enum {
@@ -180,6 +182,22 @@ gtk_text_tag_table_init (GtkTextTagTable *table)
   table->priv->hash = g_hash_table_new (g_str_hash, g_str_equal);
 }
 
+static void
+check_visible (GtkTextTagTable *table,
+               GtkTextTag      *tag)
+{
+  if (table->priv->seen_invisible)
+    return;
+
+  if (tag->priv->invisible_set)
+    {
+      gboolean invisible;
+
+      g_object_get (tag, "invisible", &invisible, NULL);
+      table->priv->seen_invisible = invisible;
+    }
+}
+
 /**
  * gtk_text_tag_table_new:
  * 
@@ -301,6 +319,8 @@ gtk_text_tag_table_add (GtkTextTagTable *table,
   g_assert (size > 0);
   tag->priv->priority = size - 1;
 
+  check_visible (table, tag);
+
   g_signal_emit (table, signals[TAG_ADDED], 0, tag);
   return TRUE;
 }
@@ -490,5 +510,12 @@ _gtk_text_tag_table_tag_changed (GtkTextTagTable *table,
                                  GtkTextTag      *tag,
                                  gboolean         size_changed)
 {
+  check_visible (table, tag);
   g_signal_emit (table, signals[TAG_CHANGED], 0, tag, size_changed);
 }
+
+gboolean
+_gtk_text_tag_table_affects_visibility (GtkTextTagTable *table)
+{
+  return table->priv->seen_invisible;
+}
diff --git a/gtk/gtktexttagtableprivate.h b/gtk/gtktexttagtableprivate.h
index 0a8401e695..4bf0d5773c 100644
--- a/gtk/gtktexttagtableprivate.h
+++ b/gtk/gtktexttagtableprivate.h
@@ -29,13 +29,14 @@
 
 G_BEGIN_DECLS
 
-void _gtk_text_tag_table_add_buffer    (GtkTextTagTable *table,
-                                        gpointer         buffer);
-void _gtk_text_tag_table_remove_buffer (GtkTextTagTable *table,
-                                        gpointer         buffer);
-void _gtk_text_tag_table_tag_changed   (GtkTextTagTable *table,
-                                        GtkTextTag      *tag,
-                                        gboolean         size_changed);
+void     _gtk_text_tag_table_add_buffer         (GtkTextTagTable *table,
+                                                 gpointer         buffer);
+void     _gtk_text_tag_table_remove_buffer      (GtkTextTagTable *table,
+                                                 gpointer         buffer);
+void     _gtk_text_tag_table_tag_changed        (GtkTextTagTable *table,
+                                                 GtkTextTag      *tag,
+                                                 gboolean         size_changed);
+gboolean _gtk_text_tag_table_affects_visibility (GtkTextTagTable *table);
 
 G_END_DECLS
 


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