#include "gtkbitmaskprivate.h"
#include "gtkcssarrayvalueprivate.h"
+#include "gtkcsscolorvalueprivate.h"
#include "gtkcsskeyframesprivate.h"
#include "gtkcssparserprivate.h"
#include "gtkcsssectionprivate.h"
#include "gtkcssselectorprivate.h"
#include "gtkcssshorthandpropertyprivate.h"
#include "gtkcssstylefuncsprivate.h"
-#include "gtksymboliccolor.h"
#include "gtkstyleprovider.h"
#include "gtkstylecontextprivate.h"
#include "gtkstylepropertiesprivate.h"
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)
{
priv->symbolic_colors = g_hash_table_new_full (g_str_hash, g_str_equal,
(GDestroyNotify) g_free,
- (GDestroyNotify) gtk_symbolic_color_unref);
+ (GDestroyNotify) _gtk_css_value_unref);
priv->keyframes = g_hash_table_new_full (g_str_hash, g_str_equal,
(GDestroyNotify) g_free,
(GDestroyNotify) _gtk_css_value_unref);
}
static void
-css_provider_dump_symbolic_colors (GtkCssProvider *css_provider,
- GtkStyleProperties *props)
+verify_tree_match_results (GtkCssProvider *provider,
+ const GtkCssMatcher *matcher,
+ GPtrArray *tree_rules)
{
- GtkCssProviderPrivate *priv;
- GHashTableIter iter;
- gpointer key, value;
+#ifdef VERIFY_TREE
+ GtkCssProviderPrivate *priv = provider->priv;
+ GtkCssRuleset *ruleset;
+ gboolean should_match;
+ int i, j;
- priv = css_provider->priv;
- g_hash_table_iter_init (&iter, priv->symbolic_colors);
-
- while (g_hash_table_iter_next (&iter, &key, &value))
+ for (i = 0; i < priv->rulesets->len; i++)
{
- const gchar *name;
- GtkSymbolicColor *color;
+ gboolean found = FALSE;
- name = key;
- color = value;
+ ruleset = &g_array_index (priv->rulesets, GtkCssRuleset, i);
- gtk_style_properties_map_color (props, name, color);
+ 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 GtkStyleProperties *
-gtk_css_provider_get_style (GtkStyleProvider *provider,
- GtkWidgetPath *path)
+static void
+verify_tree_get_change_results (GtkCssProvider *provider,
+ const GtkCssMatcher *matcher,
+ GtkCssChange change)
{
- GtkCssMatcher matcher;
- GtkCssProvider *css_provider;
- GtkCssProviderPrivate *priv;
- GtkStyleProperties *props;
- guint i, j;
+#ifdef VERIFY_TREE
+ {
+ GtkCssChange verify_change = 0;
+ GPtrArray *tree_rules;
+ int i;
- css_provider = GTK_CSS_PROVIDER (provider);
- priv = css_provider->priv;
- props = gtk_style_properties_new ();
+ tree_rules = _gtk_css_selector_tree_match_all (provider->priv->tree, matcher);
+ verify_tree_match_results (provider, matcher, tree_rules);
- css_provider_dump_symbolic_colors (css_provider, props);
- if (_gtk_css_matcher_init (&matcher, path, 0))
- {
- for (i = 0; i < priv->rulesets->len; i++)
- {
- GtkCssRuleset *ruleset;
+ for (i = tree_rules->len - 1; i >= 0; i--)
+ {
+ GtkCssRuleset *ruleset;
- ruleset = &g_array_index (priv->rulesets, GtkCssRuleset, i);
+ ruleset = tree_rules->pdata[i];
- if (ruleset->styles == NULL)
- continue;
+ verify_change |= _gtk_css_selector_tree_match_get_change (ruleset->selector_match);
+ }
- if (!gtk_css_ruleset_matches (ruleset, &matcher))
- continue;
+ if (change != verify_change)
+ {
+ GString *s;
- for (j = 0; j < ruleset->n_styles; j++)
- _gtk_style_properties_set_property_by_property (props,
- GTK_CSS_STYLE_PROPERTY (ruleset->styles[i].property),
- _gtk_css_selector_get_state_flags (ruleset->selector),
- ruleset->styles[i].value);
- }
- }
+ 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);
+ }
- return props;
+ 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;
}
static void
gtk_css_style_provider_iface_init (GtkStyleProviderIface *iface)
{
- iface->get_style = gtk_css_provider_get_style;
iface->get_style_property = gtk_css_provider_get_style_property;
}
-static GtkSymbolicColor *
+static GtkCssValue *
gtk_css_style_provider_get_color (GtkStyleProviderPrivate *provider,
const char *name)
{
{
GtkCssProvider *css_provider;
GtkCssProviderPrivate *priv;
- int i;
+ GtkCssRuleset *ruleset;
guint j;
+ int i;
+ GPtrArray *tree_rules;
css_provider = GTK_CSS_PROVIDER (provider);
priv = css_provider->priv;
- for (i = priv->rulesets->len - 1; i >= 0; i--)
- {
- GtkCssRuleset *ruleset;
+ tree_rules = _gtk_css_selector_tree_match_all (priv->tree, matcher);
+ verify_tree_match_results (css_provider, matcher, tree_rules);
- ruleset = &g_array_index (priv->rulesets, GtkCssRuleset, i);
+ 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;
ruleset->styles[j].section,
ruleset->styles[j].value);
}
+
+ 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
return;
*propagate_to = g_error_copy (error);
- s = _gtk_css_section_to_string (section);
- g_prefix_error (propagate_to, "%s", s);
- g_free (s);
+ if (section)
+ {
+ s = _gtk_css_section_to_string (section);
+ g_prefix_error (propagate_to, "%s", s);
+ g_free (s);
+ }
}
static gboolean
static gboolean
parse_color_definition (GtkCssScanner *scanner)
{
- GtkCssValue *symbolic;
+ GtkCssValue *color;
char *name;
gtk_css_scanner_push_section (scanner, GTK_CSS_SECTION_COLOR_DEFINITION);
return TRUE;
}
- symbolic = _gtk_css_symbolic_value_new (scanner->parser);
- if (symbolic == NULL)
+ color = _gtk_css_color_value_parse (scanner->parser);
+ if (color == NULL)
{
g_free (name);
_gtk_css_parser_resync (scanner->parser, TRUE, 0);
if (!_gtk_css_parser_try (scanner->parser, ";", TRUE))
{
g_free (name);
- _gtk_css_value_unref (symbolic);
+ _gtk_css_value_unref (color);
gtk_css_provider_error_literal (scanner->provider,
scanner,
GTK_CSS_PROVIDER_ERROR,
return TRUE;
}
- g_hash_table_insert (scanner->provider->priv->symbolic_colors, name, symbolic);
+ g_hash_table_insert (scanner->provider->priv->symbolic_colors, name, color);
gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_COLOR_DEFINITION);
return TRUE;
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
g_free (path);
g_free (dir);
}
+ else
+ {
+ /* Things failed! Fall back! Fall back! */
+
+ if (variant)
+ {
+ /* If there was a variant, try without */
+ _gtk_css_provider_load_named (provider, name, NULL);
+ }
+ else
+ {
+ /* Worst case, fall back to Raleigh */
+ g_return_if_fail (!g_str_equal (name, "Raleigh")); /* infloop protection */
+ _gtk_css_provider_load_named (provider, "Raleigh", NULL);
+ }
+ }
}
/**
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");
GString *str)
{
GList *keys, *walk;
- char *s;
keys = g_hash_table_get_keys (colors);
/* so the output is identical for identical styles */
for (walk = keys; walk; walk = walk->next)
{
const char *name = walk->data;
- GtkSymbolicColor *symbolic = g_hash_table_lookup (colors, (gpointer) name);
+ GtkCssValue *color = g_hash_table_lookup (colors, (gpointer) name);
g_string_append (str, "@define-color ");
g_string_append (str, name);
g_string_append (str, " ");
- s = gtk_symbolic_color_to_string (symbolic);
- g_string_append (str, s);
- g_free (s);
+ _gtk_css_value_print (color, str);
g_string_append (str, ";\n");
}