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.
This commit is contained in:
Christian Hergert 2020-03-18 11:32:46 -07:00
parent 1bc1b82256
commit 6c8d47f585
3 changed files with 43 additions and 8 deletions

View File

@ -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);

View File

@ -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;
}

View File

@ -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