summaryrefslogtreecommitdiff
path: root/gtk/gtkcssselector.c
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2014-12-09 05:26:52 +0100
committerBenjamin Otte <otte@redhat.com>2014-12-10 03:49:40 +0100
commit14f5ce710856708dc80fcc98cb5eb2ba257f34ad (patch)
treefd96d636efb12081c66de539e860091f2b59d7e1 /gtk/gtkcssselector.c
parente2dddd62cf28edefddb5d2d2585d16a75e392c56 (diff)
downloadgtk+-14f5ce710856708dc80fcc98cb5eb2ba257f34ad.tar.gz
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.
Diffstat (limited to 'gtk/gtkcssselector.c')
-rw-r--r--gtk/gtkcssselector.c256
1 files changed, 41 insertions, 215 deletions
diff --git a/gtk/gtkcssselector.c b/gtk/gtkcssselector.c
index fb2b7c29f4..ec49884c8f 100644
--- a/gtk/gtkcssselector.c
+++ b/gtk/gtkcssselector.c
@@ -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
@@ -328,33 +290,6 @@ gtk_css_selector_descendant_foreach_matcher (const GtkCssSelector *selector
}
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)
{
return _gtk_css_change_for_child (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,
@@ -413,35 +347,6 @@ gtk_css_selector_descendant_for_region_foreach_matcher (const GtkCssSelector
}
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)
{
return previous_change | _gtk_css_change_for_child (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,
@@ -484,26 +388,6 @@ gtk_css_selector_child_foreach_matcher (const GtkCssSelector *selector,
}
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)
{
return _gtk_css_change_for_child (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,
@@ -556,34 +439,6 @@ gtk_css_selector_sibling_foreach_matcher (const GtkCssSelector *selector,
}
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)
{
return _gtk_css_change_for_sibling (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,
@@ -626,26 +480,6 @@ gtk_css_selector_adjacent_foreach_matcher (const GtkCssSelector *selector,
}
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)
{
return _gtk_css_change_for_sibling (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, \
@@ -911,28 +720,6 @@ gtk_css_selector_region_match_one (const GtkCssSelector *selector,
}
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)
{
return previous_change | GTK_CSS_CHANGE_REGION;
@@ -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