cssselector: Rewrite change computation

We know that non-simple selectors cause a transition to the all matcher,
so just assume the all matcher from that point on.
This commit is contained in:
Benjamin Otte
2014-12-09 05:26:52 +01:00
parent e2dddd62cf
commit 14f5ce7108

View File

@ -25,17 +25,6 @@
#include "gtkcssprovider.h"
#include "gtkstylecontextprivate.h"
/* 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 a match like *.class:active we'll
get a tree that first checks :active, if that matches we continue down
to the tree, and if we get a match we add CHANGE_CLASS. However, the
end of the tree where we have a match is an ANY which doesn't actually
modify the change, so we don't know if we have a match or not. We fix
this by setting GTK_CSS_CHANGE_GOT_MATCH which lets us guarantee
that change != 0 on any match. */
#define GTK_CSS_CHANGE_GOT_MATCH GTK_CSS_CHANGE_RESERVED_BIT
typedef struct _GtkCssSelectorClass GtkCssSelectorClass;
typedef gboolean (* GtkCssSelectorForeachFunc) (const GtkCssSelector *selector,
const GtkCssMatcher *matcher,
@ -60,8 +49,6 @@ struct _GtkCssSelectorClass {
const GtkCssMatcher *matcher);
GtkCssChange (* get_change) (const GtkCssSelector *selector,
GtkCssChange previous_change);
GtkCssChange (* tree_get_change) (const GtkCssSelectorTree *tree,
const GtkCssMatcher *matcher);
void (* add_specificity) (const GtkCssSelector *selector,
guint *ids,
guint *classes,
@ -168,16 +155,6 @@ gtk_css_selector_tree_found_match (const GtkCssSelectorTree *tree,
}
}
static GtkCssChange
gtk_css_selector_tree_get_change (const GtkCssSelectorTree *tree,
const GtkCssMatcher *matcher)
{
if (tree == NULL)
return 0;
return tree->selector.class->tree_get_change (tree, matcher);
}
static gboolean
gtk_css_selector_match (const GtkCssSelector *selector,
const GtkCssMatcher *matcher)
@ -239,21 +216,6 @@ gtk_css_selector_tree_get_sibling (const GtkCssSelectorTree *tree)
return gtk_css_selector_tree_at_offset (tree, tree->sibling_offset);
}
static GtkCssChange
gtk_css_selector_tree_get_previous_change (const GtkCssSelectorTree *tree,
const GtkCssMatcher *matcher)
{
GtkCssChange previous_change = 0;
const GtkCssSelectorTree *prev;
for (prev = gtk_css_selector_tree_get_previous (tree);
prev != NULL;
prev = gtk_css_selector_tree_get_sibling (prev))
previous_change |= gtk_css_selector_tree_get_change (prev, matcher);
return previous_change;
}
/* DEFAULTS */
static void
@ -327,33 +289,6 @@ gtk_css_selector_descendant_foreach_matcher (const GtkCssSelector *selector
return FALSE;
}
static GtkCssChange
gtk_css_selector_descendant_tree_get_change (const GtkCssSelectorTree *tree,
const GtkCssMatcher *matcher)
{
GtkCssMatcher ancestor;
GtkCssChange change, previous_change;
change = 0;
previous_change = 0;
while (_gtk_css_matcher_get_parent (&ancestor, matcher))
{
matcher = &ancestor;
previous_change |= gtk_css_selector_tree_get_previous_change (tree, matcher);
/* any matchers are dangerous here, as we may loop forever, but
we can terminate now as all possible matches have already been added */
if (_gtk_css_matcher_matches_any (matcher))
break;
}
if (previous_change != 0)
change |= _gtk_css_change_for_child (previous_change) | GTK_CSS_CHANGE_GOT_MATCH;
return change;
}
static GtkCssChange
gtk_css_selector_descendant_get_change (const GtkCssSelector *selector, GtkCssChange previous_change)
{
@ -366,7 +301,6 @@ static const GtkCssSelectorClass GTK_CSS_SELECTOR_DESCENDANT = {
gtk_css_selector_descendant_foreach_matcher,
gtk_css_selector_default_match_one,
gtk_css_selector_descendant_get_change,
gtk_css_selector_descendant_tree_get_change,
gtk_css_selector_default_add_specificity,
gtk_css_selector_default_hash_one,
gtk_css_selector_default_compare_one,
@ -412,35 +346,6 @@ gtk_css_selector_descendant_for_region_foreach_matcher (const GtkCssSelector
return FALSE;
}
static GtkCssChange
gtk_css_selector_descendant_for_region_tree_get_change (const GtkCssSelectorTree *tree,
const GtkCssMatcher *matcher)
{
GtkCssMatcher ancestor;
GtkCssChange change, previous_change;
previous_change = gtk_css_selector_tree_get_previous_change (tree, matcher);
change = 0;
while (_gtk_css_matcher_get_parent (&ancestor, matcher))
{
matcher = &ancestor;
previous_change |= _gtk_css_change_for_child (gtk_css_selector_tree_get_previous_change (tree, matcher));
/* any matchers are dangerous here, as we may loop forever, but
we can terminate now as all possible matches have already been added */
if (_gtk_css_matcher_matches_any (matcher))
break;
}
if (previous_change != 0)
change |= previous_change | GTK_CSS_CHANGE_GOT_MATCH;
return change;
}
static GtkCssChange
gtk_css_selector_descendant_for_region_get_change (const GtkCssSelector *selector, GtkCssChange previous_change)
{
@ -453,7 +358,6 @@ static const GtkCssSelectorClass GTK_CSS_SELECTOR_DESCENDANT_FOR_REGION = {
gtk_css_selector_descendant_for_region_foreach_matcher,
gtk_css_selector_default_match_one,
gtk_css_selector_descendant_for_region_get_change,
gtk_css_selector_descendant_for_region_tree_get_change,
gtk_css_selector_default_add_specificity,
gtk_css_selector_default_hash_one,
gtk_css_selector_default_compare_one,
@ -483,26 +387,6 @@ gtk_css_selector_child_foreach_matcher (const GtkCssSelector *selector,
return func (selector, &parent, data);
}
static GtkCssChange
gtk_css_selector_child_tree_get_change (const GtkCssSelectorTree *tree,
const GtkCssMatcher *matcher)
{
GtkCssMatcher parent;
GtkCssChange change, previous_change;
if (!_gtk_css_matcher_get_parent (&parent, matcher))
return 0;
change = 0;
previous_change = gtk_css_selector_tree_get_previous_change (tree, &parent);
if (previous_change != 0)
change |= _gtk_css_change_for_child (previous_change) | GTK_CSS_CHANGE_GOT_MATCH;
return change;
}
static GtkCssChange
gtk_css_selector_child_get_change (const GtkCssSelector *selector, GtkCssChange previous_change)
{
@ -515,7 +399,6 @@ static const GtkCssSelectorClass GTK_CSS_SELECTOR_CHILD = {
gtk_css_selector_child_foreach_matcher,
gtk_css_selector_default_match_one,
gtk_css_selector_child_get_change,
gtk_css_selector_child_tree_get_change,
gtk_css_selector_default_add_specificity,
gtk_css_selector_default_hash_one,
gtk_css_selector_default_compare_one,
@ -555,34 +438,6 @@ gtk_css_selector_sibling_foreach_matcher (const GtkCssSelector *selector,
return FALSE;
}
static GtkCssChange
gtk_css_selector_sibling_tree_get_change (const GtkCssSelectorTree *tree,
const GtkCssMatcher *matcher)
{
GtkCssMatcher previous;
GtkCssChange change, previous_change;
change = 0;
previous_change = 0;
while (_gtk_css_matcher_get_previous (&previous, matcher))
{
matcher = &previous;
previous_change |= gtk_css_selector_tree_get_previous_change (tree, matcher);
/* any matchers are dangerous here, as we may loop forever, but
we can terminate now as all possible matches have already been added */
if (_gtk_css_matcher_matches_any (matcher))
break;
}
if (previous_change != 0)
change |= _gtk_css_change_for_sibling (previous_change) | GTK_CSS_CHANGE_GOT_MATCH;
return change;
}
static GtkCssChange
gtk_css_selector_sibling_get_change (const GtkCssSelector *selector, GtkCssChange previous_change)
{
@ -595,7 +450,6 @@ static const GtkCssSelectorClass GTK_CSS_SELECTOR_SIBLING = {
gtk_css_selector_sibling_foreach_matcher,
gtk_css_selector_default_match_one,
gtk_css_selector_sibling_get_change,
gtk_css_selector_sibling_tree_get_change,
gtk_css_selector_default_add_specificity,
gtk_css_selector_default_hash_one,
gtk_css_selector_default_compare_one,
@ -625,26 +479,6 @@ gtk_css_selector_adjacent_foreach_matcher (const GtkCssSelector *selector,
return func (selector, &previous, data);
}
static GtkCssChange
gtk_css_selector_adjacent_tree_get_change (const GtkCssSelectorTree *tree,
const GtkCssMatcher *matcher)
{
GtkCssMatcher previous;
GtkCssChange change, previous_change;
if (!_gtk_css_matcher_get_previous (&previous, matcher))
return 0;
change = 0;
previous_change = gtk_css_selector_tree_get_previous_change (tree, &previous);
if (previous_change != 0)
change |= _gtk_css_change_for_sibling (previous_change) | GTK_CSS_CHANGE_GOT_MATCH;
return change;
}
static GtkCssChange
gtk_css_selector_adjacent_get_change (const GtkCssSelector *selector, GtkCssChange previous_change)
{
@ -657,7 +491,6 @@ static const GtkCssSelectorClass GTK_CSS_SELECTOR_ADJACENT = {
gtk_css_selector_adjacent_foreach_matcher,
gtk_css_selector_default_match_one,
gtk_css_selector_adjacent_get_change,
gtk_css_selector_adjacent_tree_get_change,
gtk_css_selector_default_add_specificity,
gtk_css_selector_default_hash_one,
gtk_css_selector_default_compare_one,
@ -699,28 +532,6 @@ gtk_css_selector_not_ ## n ## _match_one (const GtkCssSelector *selector, \
} \
\
static GtkCssChange \
gtk_css_selector_ ## n ##_tree_get_change (const GtkCssSelectorTree *tree, \
const GtkCssMatcher *matcher) \
{ \
GtkCssChange change, previous_change; \
\
if (!match_func (&tree->selector, matcher)) \
return 0; \
\
change = 0; \
\
if (tree->matches_offset != GTK_CSS_SELECTOR_TREE_EMPTY_OFFSET) \
change |= GTK_CSS_CHANGE_ ## c | GTK_CSS_CHANGE_GOT_MATCH; \
\
previous_change = gtk_css_selector_tree_get_previous_change (tree, matcher); \
\
if (previous_change) \
change |= previous_change | GTK_CSS_CHANGE_ ## c | GTK_CSS_CHANGE_GOT_MATCH; \
\
return change; \
} \
\
static GtkCssChange \
gtk_css_selector_ ## n ## _get_change (const GtkCssSelector *selector, GtkCssChange previous_change) \
{ \
return previous_change | GTK_CSS_CHANGE_ ## c; \
@ -746,7 +557,6 @@ static const GtkCssSelectorClass GTK_CSS_SELECTOR_ ## c = { \
gtk_css_selector_default_foreach_matcher, \
match_func, \
gtk_css_selector_ ## n ## _get_change, \
gtk_css_selector_ ## n ## _tree_get_change, \
gtk_css_selector_ ## n ## _add_specificity, \
hash_func, \
comp_func, \
@ -759,7 +569,6 @@ static const GtkCssSelectorClass GTK_CSS_SELECTOR_NOT_ ## c = { \
gtk_css_selector_default_foreach_matcher, \
gtk_css_selector_not_ ## n ## _match_one, \
gtk_css_selector_ ## n ## _get_change, \
gtk_css_selector_ ## n ## _tree_get_change, \
gtk_css_selector_ ## n ## _add_specificity, \
hash_func, \
comp_func, \
@ -910,28 +719,6 @@ gtk_css_selector_region_match_one (const GtkCssSelector *selector,
return _gtk_css_matcher_has_region (matcher, selector->region.name, selector->region.flags);
}
static GtkCssChange
gtk_css_selector_region_tree_get_change (const GtkCssSelectorTree *tree,
const GtkCssMatcher *matcher)
{
GtkCssChange change, previous_change;
if (!_gtk_css_matcher_has_region (matcher, tree->selector.region.name, tree->selector.region.flags))
return 0;
change = 0;
if (tree->matches_offset != GTK_CSS_SELECTOR_TREE_EMPTY_OFFSET)
change |= GTK_CSS_CHANGE_REGION | GTK_CSS_CHANGE_GOT_MATCH;
previous_change = gtk_css_selector_tree_get_previous_change (tree, matcher);
if (previous_change != 0)
change |= previous_change | GTK_CSS_CHANGE_REGION | GTK_CSS_CHANGE_GOT_MATCH;
return change;
}
static GtkCssChange
gtk_css_selector_region_get_change (const GtkCssSelector *selector, GtkCssChange previous_change)
{
@ -985,7 +772,6 @@ static const GtkCssSelectorClass GTK_CSS_SELECTOR_REGION = {
gtk_css_selector_default_foreach_matcher,
gtk_css_selector_region_match_one,
gtk_css_selector_region_get_change,
gtk_css_selector_region_tree_get_change,
gtk_css_selector_region_add_specificity,
gtk_css_selector_region_hash_one,
gtk_css_selector_region_compare_one,
@ -1968,6 +1754,45 @@ _gtk_css_selector_tree_match_all (const GtkCssSelectorTree *tree,
return array;
}
static GtkCssChange
gtk_css_selector_tree_collect_change (const GtkCssSelectorTree *tree)
{
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,
const GtkCssMatcher *matcher)
{
GtkCssChange change = 0;
const GtkCssSelectorTree *prev;
if (!gtk_css_selector_match (&tree->selector, matcher))
return 0;
if (tree->selector.class->is_simple)
return gtk_css_selector_tree_collect_change (tree);
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, matcher);
change = tree->selector.class->get_change (&tree->selector, change);
return change;
}
GtkCssChange
_gtk_css_selector_tree_get_change_all (const GtkCssSelectorTree *tree,
const GtkCssMatcher *matcher)
@ -1976,12 +1801,13 @@ _gtk_css_selector_tree_get_change_all (const GtkCssSelectorTree *tree,
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, matcher);
/* Never return reserved bit set */
return change & ~GTK_CSS_CHANGE_RESERVED_BIT;
return change;
}
#ifdef PRINT_TREE