summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2012-11-23 16:08:56 +0100
committerAlexander Larsson <alexl@redhat.com>2012-11-23 16:13:26 +0100
commitfc12246758a3f057dfa654e0d8f836e1898e1802 (patch)
treea1c0691ada8d79301e682ec2d8b89272dd5ed3f6
parentae194d14d18de04a2c44721f8d4ab004b72ca6ab (diff)
downloadgtk+-fc12246758a3f057dfa654e0d8f836e1898e1802.tar.gz
css: Make gtk_css_style_provider_lookup use the new rule tree
-rw-r--r--gtk/gtkcssprovider.c126
1 files changed, 123 insertions, 3 deletions
diff --git a/gtk/gtkcssprovider.c b/gtk/gtkcssprovider.c
index dc33a5ce60..cdd31a4c41 100644
--- a/gtk/gtkcssprovider.c
+++ b/gtk/gtkcssprovider.c
@@ -1596,6 +1596,117 @@ gtk_css_style_provider_get_keyframes (GtkStyleProviderPrivate *provider,
}
static void
+collect_possible_rules (GPtrArray *rules_lists,
+ GtkCssRulesetsTree *tree,
+ const GtkCssMatcher *matcher)
+{
+ if (tree == NULL)
+ return;
+
+ switch (tree->type)
+ {
+ case RULESETS_TREE_TYPE_RULES:
+ g_ptr_array_add (rules_lists, &tree->u.rules);
+ break;
+ case RULESETS_TREE_TYPE_STATE:
+ if ((_gtk_css_matcher_get_state (matcher) & tree->u.state.state) == tree->u.state.state)
+ collect_possible_rules (rules_lists,
+ tree->u.state.matched,
+ matcher);
+ break;
+ case RULESETS_TREE_TYPE_CLASS:
+ if (_gtk_css_matcher_has_class (matcher, tree->u.class.class))
+ collect_possible_rules (rules_lists,
+ tree->u.class.matched,
+ matcher);
+ break;
+ }
+
+ collect_possible_rules (rules_lists,
+ tree->next,
+ matcher);
+}
+
+/* Merged two pre-sorted arrays of uints, assumes enough space in destination to fit a_len + b_len */
+static void
+merge_uints (guint *dest, const guint *a, int a_len, const guint* b, int b_len)
+{
+ const guint *a_end = a + a_len;
+ const guint *b_end = b + b_len;
+
+ while (a != a_end ||
+ b != b_end)
+ {
+ if (a == a_end)
+ {
+ memcpy (dest, b, sizeof (guint) * (b_end - b));
+ break;
+ }
+ else if (b == b_end)
+ {
+ memcpy (dest, a, sizeof (guint) * (a_end - a));
+ break;
+ }
+ else if (*a <= *b)
+ *dest++ = *a++;
+ else
+ *dest++ = *b++;
+ }
+}
+
+static guint *
+find_possible_rules (GtkCssRulesetsTree *tree,
+ const GtkCssMatcher *matcher,
+ guint *num_refs_out)
+{
+ GPtrArray *rules_lists;
+ gint i;
+ guint *merged, *tmp_refs, *swap_ptr;
+ guint merged_size;
+ guint num_refs;
+
+ /* Collect all possible rules from the tree */
+ rules_lists = g_ptr_array_new ();
+ collect_possible_rules (rules_lists, tree, matcher);
+
+ /* Merge the separate sorted lists into one list */
+ num_refs = 0;
+ for (i = 0; i < rules_lists->len; i++)
+ {
+ GtkCssRulesetList *list = (GtkCssRulesetList *)rules_lists->pdata[i];
+ num_refs += list->num_rules;
+ }
+
+ merged = g_new (guint, num_refs);
+ merged_size = 0;
+ tmp_refs = g_new (guint, num_refs);
+
+ /* Merge the already sorted refs list */
+ for (i = 0; i < rules_lists->len; i++)
+ {
+ GtkCssRulesetList *list = (GtkCssRulesetList *)rules_lists->pdata[i];
+
+ if (i == 0)
+ memcpy (merged, list->rules, sizeof (*list->rules) * list->num_rules);
+ else
+ {
+ merge_uints (tmp_refs, merged, merged_size, list->rules, list->num_rules);
+ swap_ptr = merged;
+ merged = tmp_refs;
+ tmp_refs = swap_ptr;
+ }
+
+ merged_size += list->num_rules;
+ }
+
+ g_free (tmp_refs);
+ g_ptr_array_free (rules_lists, TRUE);
+
+ *num_refs_out = num_refs;
+ return merged;
+}
+
+static void
gtk_css_style_provider_lookup (GtkStyleProviderPrivate *provider,
const GtkCssMatcher *matcher,
GtkCssLookup *lookup)
@@ -1604,6 +1715,9 @@ gtk_css_style_provider_lookup (GtkStyleProviderPrivate *provider,
GtkCssProviderPrivate *priv;
GtkCssRuleset *ruleset;
guint j;
+ gint i;
+ guint *refs;
+ guint num_refs;
css_provider = GTK_CSS_PROVIDER (provider);
priv = css_provider->priv;
@@ -1611,10 +1725,14 @@ gtk_css_style_provider_lookup (GtkStyleProviderPrivate *provider,
if (priv->rulesets->len == 0)
return;
- for (ruleset = &g_array_index (priv->rulesets, GtkCssRuleset, priv->rulesets->len - 1);
- ruleset >= &g_array_index (priv->rulesets, GtkCssRuleset, 0);
- ruleset--)
+ refs = find_possible_rules (priv->rulesets_tree, matcher, &num_refs);
+ if (num_refs == 0)
+ return;
+
+ for (i = num_refs - 1; i >= 0; i--)
{
+ ruleset = &g_array_index (priv->rulesets, GtkCssRuleset, refs[i]);
+
if (ruleset->styles == NULL)
continue;
@@ -1642,6 +1760,8 @@ gtk_css_style_provider_lookup (GtkStyleProviderPrivate *provider,
if (_gtk_bitmask_is_empty (_gtk_css_lookup_get_missing (lookup)))
break;
}
+
+ g_free (refs);
}
static GtkCssChange