forked from AuroraMiddleware/gtk
cssnode: Implement the style cache
This essentially copies the previous cache implementation. With one caveat: It is now attached to and maintained by the CssNode, not by the CssStyle. And this is important because styles may be reused in incompatible situations which would cause cache collisions and lead to broken CSS in weird situations.
This commit is contained in:
parent
5d562b6a2a
commit
024429f76f
@ -19,12 +19,18 @@
|
||||
|
||||
#include "gtkcssnodestylecacheprivate.h"
|
||||
|
||||
#include "gtkcssstaticstyleprivate.h"
|
||||
|
||||
struct _GtkCssNodeStyleCache {
|
||||
guint ref_count;
|
||||
GtkCssStyle *style;
|
||||
GHashTable *children;
|
||||
};
|
||||
|
||||
#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))
|
||||
|
||||
GtkCssNodeStyleCache *
|
||||
gtk_css_node_style_cache_new (GtkCssStyle *style)
|
||||
{
|
||||
@ -38,6 +44,14 @@ gtk_css_node_style_cache_new (GtkCssStyle *style)
|
||||
return result;
|
||||
}
|
||||
|
||||
GtkCssNodeStyleCache *
|
||||
gtk_css_node_style_cache_ref (GtkCssNodeStyleCache *cache)
|
||||
{
|
||||
cache->ref_count++;
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
||||
void
|
||||
gtk_css_node_style_cache_unref (GtkCssNodeStyleCache *cache)
|
||||
{
|
||||
@ -47,6 +61,10 @@ gtk_css_node_style_cache_unref (GtkCssNodeStyleCache *cache)
|
||||
return;
|
||||
|
||||
g_object_unref (cache->style);
|
||||
if (cache->children)
|
||||
g_hash_table_unref (cache->children);
|
||||
|
||||
g_slice_free (GtkCssNodeStyleCache, cache);
|
||||
}
|
||||
|
||||
GtkCssStyle *
|
||||
@ -55,6 +73,55 @@ gtk_css_node_style_cache_get_style (GtkCssNodeStyleCache *cache)
|
||||
return cache->style;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
may_be_stored_in_cache (GtkCssStyle *style)
|
||||
{
|
||||
GtkCssChange change;
|
||||
|
||||
if (!GTK_IS_CSS_STATIC_STYLE (style))
|
||||
return FALSE;
|
||||
|
||||
change = gtk_css_static_style_get_change (GTK_CSS_STATIC_STYLE (style));
|
||||
|
||||
/* The cache is shared between all children of the parent, so if a
|
||||
* style depends on a sibling it is not independant of the child.
|
||||
*/
|
||||
if (change & GTK_CSS_CHANGE_ANY_SIBLING)
|
||||
return FALSE;
|
||||
|
||||
/* 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_NTH_CHILD | GTK_CSS_CHANGE_NTH_LAST_CHILD))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static guint
|
||||
gtk_css_node_style_cache_decl_hash (gconstpointer item)
|
||||
{
|
||||
return gtk_css_node_declaration_hash (UNPACK_DECLARATION (item)) << 2
|
||||
| UNPACK_FLAGS (item);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_css_node_style_cache_decl_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_css_node_style_cache_decl_free (gpointer item)
|
||||
{
|
||||
gtk_css_node_declaration_unref (UNPACK_DECLARATION (item));
|
||||
}
|
||||
|
||||
GtkCssNodeStyleCache *
|
||||
gtk_css_node_style_cache_insert (GtkCssNodeStyleCache *parent,
|
||||
GtkCssNodeDeclaration *decl,
|
||||
@ -62,7 +129,24 @@ gtk_css_node_style_cache_insert (GtkCssNodeStyleCache *parent,
|
||||
gboolean is_last,
|
||||
GtkCssStyle *style)
|
||||
{
|
||||
return gtk_css_node_style_cache_new (style);
|
||||
GtkCssNodeStyleCache *result;
|
||||
|
||||
if (!may_be_stored_in_cache (style))
|
||||
return NULL;
|
||||
|
||||
if (parent->children == NULL)
|
||||
parent->children = g_hash_table_new_full (gtk_css_node_style_cache_decl_hash,
|
||||
gtk_css_node_style_cache_decl_equal,
|
||||
gtk_css_node_style_cache_decl_free,
|
||||
(GDestroyNotify) gtk_css_node_style_cache_unref);
|
||||
|
||||
result = gtk_css_node_style_cache_new (style);
|
||||
|
||||
g_hash_table_insert (parent->children,
|
||||
PACK (gtk_css_node_declaration_ref (decl), is_first, is_last),
|
||||
gtk_css_node_style_cache_ref (result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
GtkCssNodeStyleCache *
|
||||
@ -71,6 +155,15 @@ gtk_css_node_style_cache_lookup (GtkCssNodeStyleCache *parent,
|
||||
gboolean is_first,
|
||||
gboolean is_last)
|
||||
{
|
||||
return NULL;
|
||||
GtkCssNodeStyleCache *result;
|
||||
|
||||
if (parent->children == NULL)
|
||||
return NULL;
|
||||
|
||||
result = g_hash_table_lookup (parent->children, PACK (decl, is_first, is_last));
|
||||
if (result == NULL)
|
||||
return NULL;
|
||||
|
||||
return gtk_css_node_style_cache_ref (result);
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
#ifndef __GTK_CSS_NODE_STYLE_CACHE_PRIVATE_H__
|
||||
#define __GTK_CSS_NODE_STYLE_CACHE_PRIVATE_H__
|
||||
|
||||
#include "gtkcssnodedeclarationprivate.h"
|
||||
#include "gtkcssstyleprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
@ -25,6 +26,7 @@ G_BEGIN_DECLS
|
||||
typedef struct _GtkCssNodeStyleCache GtkCssNodeStyleCache;
|
||||
|
||||
GtkCssNodeStyleCache * gtk_css_node_style_cache_new (GtkCssStyle *style);
|
||||
GtkCssNodeStyleCache * gtk_css_node_style_cache_ref (GtkCssNodeStyleCache *cache);
|
||||
void gtk_css_node_style_cache_unref (GtkCssNodeStyleCache *cache);
|
||||
|
||||
GtkCssStyle * gtk_css_node_style_cache_get_style (GtkCssNodeStyleCache *cache);
|
||||
|
Loading…
Reference in New Issue
Block a user