mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-26 21:51:08 +00:00
css: Use the bloom filter for change matching
Instead of just doing radical change matching on the node itself, also consider the parent nodes via the bloom filter. This means a radical change is now also one where the parent name/id/classes change, but since that's considered a radical change on the parent already, those things are slow anyway. Improves the benchmark times for CSS validation during backdrop transitions in widget-factory from 45ms to 35ms on my machine.
This commit is contained in:
parent
ccdc3ee406
commit
495eaf31d4
@ -87,7 +87,9 @@
|
||||
|
||||
/* When these change we do a full restyling. Otherwise we try to figure out
|
||||
* if we need to change things. */
|
||||
#define GTK_CSS_RADICAL_CHANGE (GTK_CSS_CHANGE_ID | GTK_CSS_CHANGE_NAME | GTK_CSS_CHANGE_CLASS | GTK_CSS_CHANGE_SOURCE | GTK_CSS_CHANGE_PARENT_STYLE)
|
||||
#define GTK_CSS_RADICAL_CHANGE (GTK_CSS_CHANGE_ID | GTK_CSS_CHANGE_NAME | GTK_CSS_CHANGE_CLASS | \
|
||||
GTK_CSS_CHANGE_PARENT_ID | GTK_CSS_CHANGE_PARENT_NAME | GTK_CSS_CHANGE_PARENT_CLASS | \
|
||||
GTK_CSS_CHANGE_SOURCE | GTK_CSS_CHANGE_PARENT_STYLE)
|
||||
|
||||
/* When these change, we need to recompute the change flags for the new style
|
||||
* since they may have changed.
|
||||
|
@ -498,7 +498,7 @@ gtk_css_style_provider_lookup (GtkStyleProvider *provider,
|
||||
}
|
||||
|
||||
if (change)
|
||||
*change = _gtk_css_selector_tree_get_change_all (priv->tree, node);
|
||||
*change = gtk_css_selector_tree_get_change_all (priv->tree, filter, node);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1957,21 +1957,6 @@ _gtk_css_selector_tree_match_all (const GtkCssSelectorTree *tree,
|
||||
return tm.results;
|
||||
}
|
||||
|
||||
/* The code for collecting matches assumes that the name, id and classes
|
||||
* of a node remain unchanged, and anything else can change. This needs to
|
||||
* be kept in sync with the definition of 'radical change' in gtkcssnode.c.
|
||||
*/
|
||||
|
||||
static gboolean
|
||||
gtk_css_selector_match_for_change (const GtkCssSelector *selector,
|
||||
GtkCssNode *node)
|
||||
{
|
||||
if (selector->class->category != GTK_CSS_SELECTOR_CATEGORY_SIMPLE_RADICAL)
|
||||
return TRUE;
|
||||
|
||||
return selector->class->match_one (selector, node);
|
||||
}
|
||||
|
||||
/* When checking for changes via the tree we need to know if a rule further
|
||||
down the tree matched, because if so we need to add "our bit" to the
|
||||
Change. For instance in a match like *.class:active we'll
|
||||
@ -1983,39 +1968,56 @@ gtk_css_selector_match_for_change (const GtkCssSelector *selector,
|
||||
that change != 0 on any match. */
|
||||
#define GTK_CSS_CHANGE_GOT_MATCH GTK_CSS_CHANGE_RESERVED_BIT
|
||||
|
||||
/* The code for collecting matches assumes that the name, id and classes
|
||||
* of a node remain unchanged, and anything else can change. This needs to
|
||||
* be kept in sync with the definition of 'radical change' in gtkcssnode.c.
|
||||
*/
|
||||
|
||||
static GtkCssChange
|
||||
gtk_css_selector_tree_collect_change (const GtkCssSelectorTree *tree)
|
||||
gtk_css_selector_tree_get_change (const GtkCssSelectorTree *tree,
|
||||
const GtkCountingBloomFilter *filter,
|
||||
GtkCssNode *node,
|
||||
gboolean skipping)
|
||||
{
|
||||
GtkCssChange change = 0;
|
||||
const GtkCssSelectorTree *prev;
|
||||
|
||||
for (prev = gtk_css_selector_tree_get_previous (tree);
|
||||
prev != NULL;
|
||||
prev = gtk_css_selector_tree_get_sibling (prev))
|
||||
change |= gtk_css_selector_tree_collect_change (prev);
|
||||
|
||||
change = tree->selector.class->get_change (&tree->selector, change);
|
||||
|
||||
return change;
|
||||
}
|
||||
|
||||
static GtkCssChange
|
||||
gtk_css_selector_tree_get_change (const GtkCssSelectorTree *tree,
|
||||
GtkCssNode *node)
|
||||
{
|
||||
GtkCssChange change = 0;
|
||||
const GtkCssSelectorTree *prev;
|
||||
|
||||
if (!gtk_css_selector_match_for_change (&tree->selector, node))
|
||||
return 0;
|
||||
|
||||
if (!gtk_css_selector_is_simple (&tree->selector))
|
||||
return gtk_css_selector_tree_collect_change (tree) | GTK_CSS_CHANGE_GOT_MATCH;
|
||||
switch (tree->selector.class->category)
|
||||
{
|
||||
case GTK_CSS_SELECTOR_CATEGORY_SIMPLE:
|
||||
break;
|
||||
case GTK_CSS_SELECTOR_CATEGORY_SIMPLE_RADICAL:
|
||||
if (skipping)
|
||||
break;
|
||||
if (node)
|
||||
{
|
||||
if (!tree->selector.class->match_one (&tree->selector, node))
|
||||
return 0;
|
||||
}
|
||||
else if (filter)
|
||||
{
|
||||
if (!gtk_counting_bloom_filter_may_contain (filter,
|
||||
gtk_css_selector_hash_one (&tree->selector)))
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case GTK_CSS_SELECTOR_CATEGORY_PARENT:
|
||||
skipping = FALSE;
|
||||
node = NULL;
|
||||
break;
|
||||
case GTK_CSS_SELECTOR_CATEGORY_SIBLING:
|
||||
skipping = TRUE;
|
||||
node = NULL;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (prev = gtk_css_selector_tree_get_previous (tree);
|
||||
prev != NULL;
|
||||
prev = gtk_css_selector_tree_get_sibling (prev))
|
||||
change |= gtk_css_selector_tree_get_change (prev, node);
|
||||
change |= gtk_css_selector_tree_get_change (prev, filter, node, skipping);
|
||||
|
||||
if (change || gtk_css_selector_tree_get_matches (tree))
|
||||
change = tree->selector.class->get_change (&tree->selector, change & ~GTK_CSS_CHANGE_GOT_MATCH) | GTK_CSS_CHANGE_GOT_MATCH;
|
||||
@ -2030,17 +2032,15 @@ _gtk_css_selector_tree_is_empty (const GtkCssSelectorTree *tree)
|
||||
}
|
||||
|
||||
GtkCssChange
|
||||
_gtk_css_selector_tree_get_change_all (const GtkCssSelectorTree *tree,
|
||||
GtkCssNode *node)
|
||||
gtk_css_selector_tree_get_change_all (const GtkCssSelectorTree *tree,
|
||||
const GtkCountingBloomFilter *filter,
|
||||
GtkCssNode *node)
|
||||
{
|
||||
GtkCssChange change;
|
||||
GtkCssChange change = 0;
|
||||
|
||||
change = 0;
|
||||
|
||||
/* no need to foreach here because we abort for non-simple selectors */
|
||||
for (; tree != NULL;
|
||||
tree = gtk_css_selector_tree_get_sibling (tree))
|
||||
change |= gtk_css_selector_tree_get_change (tree, node);
|
||||
change |= gtk_css_selector_tree_get_change (tree, filter, node, FALSE);
|
||||
|
||||
/* Never return reserved bit set */
|
||||
return change & ~GTK_CSS_CHANGE_RESERVED_BIT;
|
||||
|
@ -45,7 +45,8 @@ void _gtk_css_selector_tree_free (GtkCssSelectorTree *
|
||||
GPtrArray * _gtk_css_selector_tree_match_all (const GtkCssSelectorTree *tree,
|
||||
const GtkCountingBloomFilter *filter,
|
||||
GtkCssNode *node);
|
||||
GtkCssChange _gtk_css_selector_tree_get_change_all (const GtkCssSelectorTree *tree,
|
||||
GtkCssChange gtk_css_selector_tree_get_change_all (const GtkCssSelectorTree *tree,
|
||||
const GtkCountingBloomFilter *filter,
|
||||
GtkCssNode *node);
|
||||
void _gtk_css_selector_tree_match_print (const GtkCssSelectorTree *tree,
|
||||
GString *str);
|
||||
|
@ -1,9 +1,9 @@
|
||||
window.background:dir(ltr)
|
||||
decoration:dir(ltr)
|
||||
grid.horizontal:dir(ltr)
|
||||
label:dir(ltr) name|sibling-name|parent-name|parent-sibling-name
|
||||
label:dir(ltr)
|
||||
box.horizontal:dir(ltr)
|
||||
label:dir(ltr) name|sibling-name|parent-name|parent-sibling-name
|
||||
label:dir(ltr)
|
||||
button:dir(ltr)
|
||||
box.horizontal:dir(ltr)
|
||||
checkbutton:dir(ltr)
|
||||
|
Loading…
Reference in New Issue
Block a user