From f1ca75d1812f95690f2bba7445ad6803b58d4780 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Wed, 26 Aug 2015 18:01:39 +0200 Subject: [PATCH] cssnode: Loosen requirements for style caching We can actually share :first-child/:last-child related things now, because we special case them. So the only positions we cannot cache are nth-child/nth-last-child. This should take care of a lot of Adwaita's styling. --- gtk/gtkcssnode.c | 45 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 6 deletions(-) diff --git a/gtk/gtkcssnode.c b/gtk/gtkcssnode.c index 9d76f2ae31..3cc7e16188 100644 --- a/gtk/gtkcssnode.c +++ b/gtk/gtkcssnode.c @@ -181,6 +181,10 @@ gtk_css_node_finalize (GObject *object) G_OBJECT_CLASS (gtk_css_node_parent_class)->finalize (object); } +#define UNPACK_DECLARATION(packed) ((GtkCssNodeDeclaration *) (GPOINTER_TO_SIZE (packed) & ~0x3)) +#define UNPACK_FLAGS(packed) (GPOINTER_TO_SIZE (packed) & 0x3) +#define PACK(decl, first_child, last_child) GSIZE_TO_POINTER (GPOINTER_TO_SIZE (decl) | ((first_child) ? 0x2 : 0) | ((last_child) ? 0x1 : 0)) + static gboolean may_use_global_parent_cache (GtkCssNode *node) { @@ -214,7 +218,10 @@ lookup_in_global_parent_cache (GtkCssNode *node, if (cache == NULL) return NULL; - style = g_hash_table_lookup (cache, decl); + style = g_hash_table_lookup (cache, + PACK (decl, + gtk_css_node_get_previous_sibling (node) == NULL, + gtk_css_node_get_next_sibling (node) == NULL)); return style; } @@ -235,12 +242,36 @@ may_be_stored_in_parent_cache (GtkCssStyle *style) /* Again, the cache is shared between all children of the parent. * If the position is relevant, no child has the same style. */ - if (change & GTK_CSS_CHANGE_POSITION) + if (change & (GTK_CSS_CHANGE_NTH_CHILD | GTK_CSS_CHANGE_NTH_LAST_CHILD)) return FALSE; return TRUE; } +static guint +gtk_global_parent_cache_hash (gconstpointer item) +{ + return gtk_css_node_declaration_hash (UNPACK_DECLARATION (item)) << 2 + || UNPACK_FLAGS (item); +} + +static gboolean +gtk_global_parent_cache_equal (gconstpointer item1, + gconstpointer item2) +{ + if (UNPACK_FLAGS (item1) != UNPACK_FLAGS (item2)) + return FALSE; + + return gtk_css_node_declaration_equal (UNPACK_DECLARATION (item1), + UNPACK_DECLARATION (item2)); +} + +static void +gtk_global_parent_cache_free (gpointer item) +{ + gtk_css_node_declaration_unref (UNPACK_DECLARATION (item)); +} + static void store_in_global_parent_cache (GtkCssNode *node, GtkCssStyle *parent, @@ -261,15 +292,17 @@ store_in_global_parent_cache (GtkCssNode *node, cache = g_object_get_data (G_OBJECT (parent), "gtk-global-cache"); if (cache == NULL) { - cache = g_hash_table_new_full (gtk_css_node_declaration_hash, - gtk_css_node_declaration_equal, - (GDestroyNotify) gtk_css_node_declaration_unref, + cache = g_hash_table_new_full (gtk_global_parent_cache_hash, + gtk_global_parent_cache_equal, + gtk_global_parent_cache_free, g_object_unref); g_object_set_data_full (G_OBJECT (parent), "gtk-global-cache", cache, (GDestroyNotify) g_hash_table_destroy); } g_hash_table_insert (cache, - gtk_css_node_declaration_ref ((GtkCssNodeDeclaration *) decl), + PACK (gtk_css_node_declaration_ref ((GtkCssNodeDeclaration *) decl), + gtk_css_node_get_previous_sibling (node) == NULL, + gtk_css_node_get_next_sibling (node) == NULL), g_object_ref (style)); }