struct GtkCssRuleset
{
GtkCssSelector *selector;
+ GtkCssSelectorTree *selector_match;
WidgetPropertyValue *widget_style;
PropertyValue *styles;
GtkBitmask *set_styles;
GHashTable *keyframes;
GArray *rulesets;
+ GtkCssSelectorTree *tree;
GResource *resource;
};
ruleset->styles[i].section = NULL;
}
-static gboolean
-gtk_css_ruleset_matches (GtkCssRuleset *ruleset,
- const GtkCssMatcher *matcher)
-{
- return _gtk_css_selector_matches (ruleset->selector, matcher);
-}
-
-static GtkCssChange
-gtk_css_ruleset_get_change (GtkCssRuleset *ruleset)
-{
- return _gtk_css_selector_get_change (ruleset->selector);
-}
-
static void
gtk_css_scanner_destroy (GtkCssScanner *scanner)
{
(GDestroyNotify) _gtk_css_value_unref);
}
+static void
+verify_tree_match_results (GtkCssProvider *provider,
+ const GtkCssMatcher *matcher,
+ GPtrArray *tree_rules)
+{
+#ifdef VERIFY_TREE
+ GtkCssProviderPrivate *priv = provider->priv;
+ GtkCssRuleset *ruleset;
+ gboolean should_match;
+ int i, j;
+
+ for (i = 0; i < priv->rulesets->len; i++)
+ {
+ gboolean found = FALSE;
+
+ ruleset = &g_array_index (priv->rulesets, GtkCssRuleset, i);
+
+ for (j = 0; j < tree_rules->len; j++)
+ {
+ if (ruleset == tree_rules->pdata[j])
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ should_match = _gtk_css_selector_matches (ruleset->selector, matcher);
+ if (found != !!should_match)
+ {
+ g_error ("expected rule '%s' to %s, but it %s\n",
+ _gtk_css_selector_to_string (ruleset->selector),
+ should_match ? "match" : "not match",
+ found ? "matched" : "didn't match");
+ }
+ }
+#endif
+}
+
+static void
+verify_tree_get_change_results (GtkCssProvider *provider,
+ const GtkCssMatcher *matcher,
+ GtkCssChange change)
+{
+#ifdef VERIFY_TREE
+ {
+ GtkCssChange verify_change = 0;
+ GPtrArray *tree_rules;
+ int i;
+
+ tree_rules = _gtk_css_selector_tree_match_all (provider->priv->tree, matcher);
+ verify_tree_match_results (provider, matcher, tree_rules);
+
+ for (i = tree_rules->len - 1; i >= 0; i--)
+ {
+ GtkCssRuleset *ruleset;
+
+ ruleset = tree_rules->pdata[i];
+
+ verify_change |= _gtk_css_selector_tree_match_get_change (ruleset->selector_match);
+ }
+
+ if (change != verify_change)
+ {
+ GString *s;
+
+ s = g_string_new ("");
+ g_string_append_printf (s, "expected change 0x%x, but it was 0x%x", verify_change, change);
+ if ((change & ~verify_change) != 0)
+ g_string_append_printf (s, ", unexpectedly set: 0x%x", change & ~verify_change);
+ if ((~change & verify_change) != 0)
+ g_string_append_printf (s, ", unexpectedly no set: 0x%x", ~change & verify_change);
+ g_warning (s->str);
+ g_string_free (s, TRUE);
+ }
+
+ g_ptr_array_free (tree_rules, TRUE);
+ }
+#endif
+}
+
+
static gboolean
gtk_css_provider_get_style_property (GtkStyleProvider *provider,
GtkWidgetPath *path,
GtkCssProvider *css_provider = GTK_CSS_PROVIDER (provider);
GtkCssProviderPrivate *priv = css_provider->priv;
WidgetPropertyValue *val;
+ GPtrArray *tree_rules;
GtkCssMatcher matcher;
gboolean found = FALSE;
gchar *prop_name;
if (!_gtk_css_matcher_init (&matcher, path, state))
return FALSE;
+ tree_rules = _gtk_css_selector_tree_match_all (priv->tree, &matcher);
+ verify_tree_match_results (css_provider, &matcher, tree_rules);
+
prop_name = g_strdup_printf ("-%s-%s",
g_type_name (pspec->owner_type),
pspec->name);
- for (i = priv->rulesets->len - 1; i >= 0; i--)
+ for (i = tree_rules->len - 1; i >= 0; i--)
{
- GtkCssRuleset *ruleset;
-
- ruleset = &g_array_index (priv->rulesets, GtkCssRuleset, i);
+ GtkCssRuleset *ruleset = tree_rules->pdata[i];
if (ruleset->widget_style == NULL)
continue;
- if (!gtk_css_ruleset_matches (ruleset, &matcher))
- continue;
-
for (val = ruleset->widget_style; val != NULL; val = val->next)
{
if (strcmp (val->name, prop_name) == 0)
}
g_free (prop_name);
+ g_ptr_array_free (tree_rules, TRUE);
return found;
}
GtkCssProviderPrivate *priv;
GtkCssRuleset *ruleset;
guint j;
+ int i;
+ GPtrArray *tree_rules;
css_provider = GTK_CSS_PROVIDER (provider);
priv = css_provider->priv;
- if (priv->rulesets->len == 0)
- return;
+ tree_rules = _gtk_css_selector_tree_match_all (priv->tree, matcher);
+ verify_tree_match_results (css_provider, matcher, tree_rules);
- for (ruleset = &g_array_index (priv->rulesets, GtkCssRuleset, priv->rulesets->len - 1);
- ruleset >= &g_array_index (priv->rulesets, GtkCssRuleset, 0);
- ruleset--)
+ for (i = tree_rules->len - 1; i >= 0; i--)
{
+ ruleset = tree_rules->pdata[i];
+
if (ruleset->styles == NULL)
continue;
ruleset->set_styles))
continue;
- if (!gtk_css_ruleset_matches (ruleset, matcher))
- continue;
-
for (j = 0; j < ruleset->n_styles; j++)
{
GtkCssStyleProperty *prop = ruleset->styles[j].property;
if (_gtk_bitmask_is_empty (_gtk_css_lookup_get_missing (lookup)))
break;
}
+
+ g_ptr_array_free (tree_rules, TRUE);
}
static GtkCssChange
{
GtkCssProvider *css_provider;
GtkCssProviderPrivate *priv;
- GtkCssChange change = 0;
- int i;
+ GtkCssChange change;
css_provider = GTK_CSS_PROVIDER (provider);
priv = css_provider->priv;
- for (i = priv->rulesets->len - 1; i >= 0; i--)
- {
- GtkCssRuleset *ruleset;
-
- ruleset = &g_array_index (priv->rulesets, GtkCssRuleset, i);
-
- if (ruleset->styles == NULL)
- continue;
-
- if (!gtk_css_ruleset_matches (ruleset, matcher))
- continue;
+ change = _gtk_css_selector_tree_get_change_all (priv->tree, matcher);
- change |= gtk_css_ruleset_get_change (ruleset);
- }
+ verify_tree_get_change_results (css_provider, matcher, change);
return change;
}
gtk_css_ruleset_clear (&g_array_index (priv->rulesets, GtkCssRuleset, i));
g_array_free (priv->rulesets, TRUE);
+ _gtk_css_selector_tree_free (priv->tree);
g_hash_table_destroy (priv->symbolic_colors);
g_hash_table_destroy (priv->keyframes);
for (i = 0; i < priv->rulesets->len; i++)
gtk_css_ruleset_clear (&g_array_index (priv->rulesets, GtkCssRuleset, i));
g_array_set_size (priv->rulesets, 0);
+ _gtk_css_selector_tree_free (priv->tree);
+ priv->tree = NULL;
+
}
static void
gtk_css_provider_postprocess (GtkCssProvider *css_provider)
{
GtkCssProviderPrivate *priv = css_provider->priv;
+ GtkCssSelectorTreeBuilder *builder;
+ guint i;
g_array_sort (priv->rulesets, gtk_css_provider_compare_rule);
+
+ builder = _gtk_css_selector_tree_builder_new ();
+ for (i = 0; i < priv->rulesets->len; i++)
+ {
+ GtkCssRuleset *ruleset;
+
+ ruleset = &g_array_index (priv->rulesets, GtkCssRuleset, i);
+
+ _gtk_css_selector_tree_builder_add (builder,
+ ruleset->selector,
+ &ruleset->selector_match,
+ ruleset);
+ }
+
+ priv->tree = _gtk_css_selector_tree_builder_build (builder);
+ _gtk_css_selector_tree_builder_free (builder);
+
+#ifndef VERIFY_TREE
+ for (i = 0; i < priv->rulesets->len; i++)
+ {
+ GtkCssRuleset *ruleset;
+
+ ruleset = &g_array_index (priv->rulesets, GtkCssRuleset, i);
+
+ _gtk_css_selector_free (ruleset->selector);
+ ruleset->selector = NULL;
+ }
+#endif
}
static gboolean
WidgetPropertyValue *widget_value;
guint i;
- _gtk_css_selector_print (ruleset->selector, str);
+ _gtk_css_selector_tree_match_print (ruleset->selector_match, str);
g_string_append (str, " {\n");