mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-19 09:50:06 +00:00
cssprovider: Refactor handling of rulesets
Keep rulesets as an on-stack/heap structure instead of allocating all instances separately. Also, pass a ruleset to the ruleset parser, so we can make the ruleset parser do lots of fancy things that might be useful for performance.
This commit is contained in:
parent
151294576d
commit
0318ab2ce1
@ -764,7 +764,7 @@ struct _GtkCssProviderPrivate
|
|||||||
|
|
||||||
GHashTable *symbolic_colors;
|
GHashTable *symbolic_colors;
|
||||||
|
|
||||||
GPtrArray *rulesets;
|
GArray *rulesets;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ParserScope {
|
enum ParserScope {
|
||||||
@ -908,19 +908,20 @@ gtk_css_provider_take_error_full (GtkCssProvider *provider,
|
|||||||
g_error_free (error);
|
g_error_free (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GtkCssRuleset *
|
static void
|
||||||
gtk_css_ruleset_new (GtkCssSelector *selector)
|
gtk_css_ruleset_init_copy (GtkCssRuleset *new,
|
||||||
|
const GtkCssRuleset *ruleset,
|
||||||
|
GtkCssSelector *selector)
|
||||||
{
|
{
|
||||||
GtkCssRuleset *ruleset;
|
memcpy (new, ruleset, sizeof (GtkCssRuleset));
|
||||||
|
|
||||||
ruleset = g_slice_new0 (GtkCssRuleset);
|
new->selector = selector;
|
||||||
ruleset->selector = selector;
|
if (new->style)
|
||||||
|
g_hash_table_ref (new->style);
|
||||||
return ruleset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_css_ruleset_free (GtkCssRuleset *ruleset)
|
gtk_css_ruleset_clear (GtkCssRuleset *ruleset)
|
||||||
{
|
{
|
||||||
if (ruleset->style)
|
if (ruleset->style)
|
||||||
g_hash_table_unref (ruleset->style);
|
g_hash_table_unref (ruleset->style);
|
||||||
@ -928,28 +929,7 @@ gtk_css_ruleset_free (GtkCssRuleset *ruleset)
|
|||||||
if (ruleset->selector)
|
if (ruleset->selector)
|
||||||
_gtk_css_selector_free (ruleset->selector);
|
_gtk_css_selector_free (ruleset->selector);
|
||||||
|
|
||||||
g_slice_free (GtkCssRuleset, ruleset);
|
memset (ruleset, 0, sizeof (GtkCssRuleset));
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gtk_css_ruleset_set_style (GtkCssRuleset *ruleset,
|
|
||||||
GHashTable *style)
|
|
||||||
{
|
|
||||||
if (ruleset->style)
|
|
||||||
g_hash_table_unref (ruleset->style);
|
|
||||||
|
|
||||||
if (style)
|
|
||||||
ruleset->style = g_hash_table_ref (style);
|
|
||||||
else
|
|
||||||
ruleset->style = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
gtk_css_ruleset_matches (GtkCssRuleset *ruleset,
|
|
||||||
GtkWidgetPath *path,
|
|
||||||
guint length)
|
|
||||||
{
|
|
||||||
return _gtk_css_selector_matches (ruleset->selector, path, length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -961,6 +941,28 @@ property_value_free (GValue *value)
|
|||||||
g_slice_free (GValue, value);
|
g_slice_free (GValue, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_css_ruleset_add_style (GtkCssRuleset *ruleset,
|
||||||
|
char *name,
|
||||||
|
GValue *value)
|
||||||
|
{
|
||||||
|
if (ruleset->style == NULL)
|
||||||
|
ruleset->style = g_hash_table_new_full (g_str_hash,
|
||||||
|
g_str_equal,
|
||||||
|
(GDestroyNotify) g_free,
|
||||||
|
(GDestroyNotify) property_value_free);
|
||||||
|
|
||||||
|
g_hash_table_insert (ruleset->style, name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gtk_css_ruleset_matches (GtkCssRuleset *ruleset,
|
||||||
|
GtkWidgetPath *path,
|
||||||
|
guint length)
|
||||||
|
{
|
||||||
|
return _gtk_css_selector_matches (ruleset->selector, path, length);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_css_scanner_reset (GtkCssScanner *scanner)
|
gtk_css_scanner_reset (GtkCssScanner *scanner)
|
||||||
{
|
{
|
||||||
@ -1079,7 +1081,7 @@ gtk_css_provider_init (GtkCssProvider *css_provider)
|
|||||||
GTK_TYPE_CSS_PROVIDER,
|
GTK_TYPE_CSS_PROVIDER,
|
||||||
GtkCssProviderPrivate);
|
GtkCssProviderPrivate);
|
||||||
|
|
||||||
priv->rulesets = g_ptr_array_new_with_free_func ((GDestroyNotify) gtk_css_ruleset_free);
|
priv->rulesets = g_array_new (FALSE, FALSE, sizeof (GtkCssRuleset));
|
||||||
|
|
||||||
priv->symbolic_colors = g_hash_table_new_full (g_str_hash, g_str_equal,
|
priv->symbolic_colors = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||||
(GDestroyNotify) g_free,
|
(GDestroyNotify) g_free,
|
||||||
@ -1133,7 +1135,7 @@ gtk_css_provider_get_style (GtkStyleProvider *provider,
|
|||||||
GHashTableIter iter;
|
GHashTableIter iter;
|
||||||
gpointer key, value;
|
gpointer key, value;
|
||||||
|
|
||||||
ruleset = g_ptr_array_index (priv->rulesets, i);
|
ruleset = &g_array_index (priv->rulesets, GtkCssRuleset, i);
|
||||||
|
|
||||||
if (l < length && _gtk_css_selector_get_state_flags (ruleset->selector))
|
if (l < length && _gtk_css_selector_get_state_flags (ruleset->selector))
|
||||||
continue;
|
continue;
|
||||||
@ -1187,7 +1189,7 @@ gtk_css_provider_get_style_property (GtkStyleProvider *provider,
|
|||||||
GtkCssRuleset *ruleset;
|
GtkCssRuleset *ruleset;
|
||||||
GtkStateFlags selector_state;
|
GtkStateFlags selector_state;
|
||||||
|
|
||||||
ruleset = g_ptr_array_index (priv->rulesets, i);
|
ruleset = &g_array_index (priv->rulesets, GtkCssRuleset, i);
|
||||||
|
|
||||||
if (!gtk_css_ruleset_matches (ruleset, path, gtk_widget_path_length (path)))
|
if (!gtk_css_ruleset_matches (ruleset, path, gtk_widget_path_length (path)))
|
||||||
continue;
|
continue;
|
||||||
@ -1240,7 +1242,7 @@ gtk_css_provider_finalize (GObject *object)
|
|||||||
css_provider = GTK_CSS_PROVIDER (object);
|
css_provider = GTK_CSS_PROVIDER (object);
|
||||||
priv = css_provider->priv;
|
priv = css_provider->priv;
|
||||||
|
|
||||||
g_ptr_array_free (priv->rulesets, TRUE);
|
g_array_free (priv->rulesets, TRUE);
|
||||||
|
|
||||||
if (priv->symbolic_colors)
|
if (priv->symbolic_colors)
|
||||||
g_hash_table_destroy (priv->symbolic_colors);
|
g_hash_table_destroy (priv->symbolic_colors);
|
||||||
@ -1325,32 +1327,29 @@ gtk_css_provider_invalid_token (GtkCssProvider *provider,
|
|||||||
static void
|
static void
|
||||||
css_provider_commit (GtkCssProvider *css_provider,
|
css_provider_commit (GtkCssProvider *css_provider,
|
||||||
GSList *selectors,
|
GSList *selectors,
|
||||||
GHashTable *properties)
|
GtkCssRuleset *ruleset)
|
||||||
{
|
{
|
||||||
GtkCssProviderPrivate *priv;
|
GtkCssProviderPrivate *priv;
|
||||||
GSList *l;
|
GSList *l;
|
||||||
|
|
||||||
priv = css_provider->priv;
|
priv = css_provider->priv;
|
||||||
|
|
||||||
if (g_hash_table_size (properties) == 0)
|
if (ruleset->style == NULL)
|
||||||
{
|
{
|
||||||
g_slist_free_full (selectors, (GDestroyNotify) _gtk_css_selector_free);
|
g_slist_free_full (selectors, (GDestroyNotify) _gtk_css_selector_free);
|
||||||
g_hash_table_unref (properties);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (l = selectors; l; l = l->next)
|
for (l = selectors; l; l = l->next)
|
||||||
{
|
{
|
||||||
GtkCssSelector *selector = l->data;
|
GtkCssRuleset new;
|
||||||
GtkCssRuleset *ruleset;
|
|
||||||
|
|
||||||
ruleset = gtk_css_ruleset_new (selector);
|
gtk_css_ruleset_init_copy (&new, ruleset, l->data);
|
||||||
gtk_css_ruleset_set_style (ruleset, properties);
|
|
||||||
|
|
||||||
g_ptr_array_add (priv->rulesets, ruleset);
|
g_array_append_val (priv->rulesets, new);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_hash_table_unref (properties);
|
g_slist_free (selectors);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1383,11 +1382,13 @@ static void
|
|||||||
gtk_css_provider_reset (GtkCssProvider *css_provider)
|
gtk_css_provider_reset (GtkCssProvider *css_provider)
|
||||||
{
|
{
|
||||||
GtkCssProviderPrivate *priv;
|
GtkCssProviderPrivate *priv;
|
||||||
|
guint i;
|
||||||
|
|
||||||
priv = css_provider->priv;
|
priv = css_provider->priv;
|
||||||
|
|
||||||
if (priv->rulesets->len > 0)
|
for (i = 0; i < priv->rulesets->len; i++)
|
||||||
g_ptr_array_remove_range (priv->rulesets, 0, priv->rulesets->len);
|
gtk_css_ruleset_clear (&g_array_index (priv->rulesets, GtkCssRuleset, i));
|
||||||
|
g_array_set_size (priv->rulesets, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1898,7 +1899,8 @@ parse_selector_list (GtkCssScanner *scanner)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
parse_declaration (GtkCssScanner *scanner, GHashTable *properties)
|
parse_declaration (GtkCssScanner *scanner,
|
||||||
|
GtkCssRuleset *ruleset)
|
||||||
{
|
{
|
||||||
GtkStylePropertyParser parse_func = NULL;
|
GtkStylePropertyParser parse_func = NULL;
|
||||||
GParamSpec *pspec = NULL;
|
GParamSpec *pspec = NULL;
|
||||||
@ -1951,20 +1953,20 @@ parse_declaration (GtkCssScanner *scanner, GHashTable *properties)
|
|||||||
* to override other style providers when merged
|
* to override other style providers when merged
|
||||||
*/
|
*/
|
||||||
g_param_value_set_default (pspec, val);
|
g_param_value_set_default (pspec, val);
|
||||||
g_hash_table_insert (properties, name, val);
|
gtk_css_ruleset_add_style (ruleset, name, val);
|
||||||
}
|
}
|
||||||
else if (strcmp (name, "gtk-key-bindings") == 0)
|
else if (strcmp (name, "gtk-key-bindings") == 0)
|
||||||
{
|
{
|
||||||
/* Private property holding the binding sets */
|
/* Private property holding the binding sets */
|
||||||
resolve_binding_sets (value_str, val);
|
resolve_binding_sets (value_str, val);
|
||||||
g_hash_table_insert (properties, name, val);
|
gtk_css_ruleset_add_style (ruleset, name, val);
|
||||||
}
|
}
|
||||||
else if (parse_func)
|
else if (parse_func)
|
||||||
{
|
{
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
|
|
||||||
if ((*parse_func) (value_str, val, &error))
|
if ((*parse_func) (value_str, val, &error))
|
||||||
g_hash_table_insert (properties, name, val);
|
gtk_css_ruleset_add_style (ruleset, name, val);
|
||||||
else
|
else
|
||||||
gtk_css_provider_take_error (scanner->provider, scanner, error);
|
gtk_css_provider_take_error (scanner->provider, scanner, error);
|
||||||
}
|
}
|
||||||
@ -1977,7 +1979,7 @@ parse_declaration (GtkCssScanner *scanner, GHashTable *properties)
|
|||||||
value_str,
|
value_str,
|
||||||
&error))
|
&error))
|
||||||
{
|
{
|
||||||
g_hash_table_insert (properties, name, val);
|
gtk_css_ruleset_add_style (ruleset, name, val);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1997,7 +1999,7 @@ parse_declaration (GtkCssScanner *scanner, GHashTable *properties)
|
|||||||
g_value_init (val, G_TYPE_STRING);
|
g_value_init (val, G_TYPE_STRING);
|
||||||
g_value_set_string (val, value_str);
|
g_value_set_string (val, value_str);
|
||||||
|
|
||||||
g_hash_table_insert (properties, name, val);
|
gtk_css_ruleset_add_style (ruleset, name, val);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
g_free (name);
|
g_free (name);
|
||||||
@ -2020,30 +2022,22 @@ check_for_semicolon:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static GHashTable *
|
static void
|
||||||
parse_declarations (GtkCssScanner *scanner)
|
parse_declarations (GtkCssScanner *scanner,
|
||||||
|
GtkCssRuleset *ruleset)
|
||||||
{
|
{
|
||||||
GHashTable *properties;
|
|
||||||
|
|
||||||
properties = g_hash_table_new_full (g_str_hash,
|
|
||||||
g_str_equal,
|
|
||||||
(GDestroyNotify) g_free,
|
|
||||||
(GDestroyNotify) property_value_free);
|
|
||||||
|
|
||||||
while (!_gtk_css_parser_is_eof (scanner->parser) &&
|
while (!_gtk_css_parser_is_eof (scanner->parser) &&
|
||||||
!_gtk_css_parser_begins_with (scanner->parser, '}'))
|
!_gtk_css_parser_begins_with (scanner->parser, '}'))
|
||||||
{
|
{
|
||||||
parse_declaration (scanner, properties);
|
parse_declaration (scanner, ruleset);
|
||||||
}
|
}
|
||||||
|
|
||||||
return properties;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
parse_ruleset (GtkCssScanner *scanner)
|
parse_ruleset (GtkCssScanner *scanner)
|
||||||
{
|
{
|
||||||
GSList *selectors;
|
GSList *selectors;
|
||||||
GHashTable *properties;
|
GtkCssRuleset ruleset = { 0, };
|
||||||
|
|
||||||
selectors = parse_selector_list (scanner);
|
selectors = parse_selector_list (scanner);
|
||||||
if (selectors == NULL)
|
if (selectors == NULL)
|
||||||
@ -2061,7 +2055,7 @@ parse_ruleset (GtkCssScanner *scanner)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
properties = parse_declarations (scanner);
|
parse_declarations (scanner, &ruleset);
|
||||||
|
|
||||||
if (!_gtk_css_parser_try (scanner->parser, "}", TRUE))
|
if (!_gtk_css_parser_try (scanner->parser, "}", TRUE))
|
||||||
{
|
{
|
||||||
@ -2074,16 +2068,13 @@ parse_ruleset (GtkCssScanner *scanner)
|
|||||||
{
|
{
|
||||||
_gtk_css_parser_resync (scanner->parser, FALSE, 0);
|
_gtk_css_parser_resync (scanner->parser, FALSE, 0);
|
||||||
g_slist_free_full (selectors, (GDestroyNotify) _gtk_css_selector_free);
|
g_slist_free_full (selectors, (GDestroyNotify) _gtk_css_selector_free);
|
||||||
if (properties)
|
gtk_css_ruleset_clear (&ruleset);
|
||||||
g_hash_table_unref (properties);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (properties)
|
css_provider_commit (scanner->provider, selectors, &ruleset);
|
||||||
css_provider_commit (scanner->provider, selectors, properties);
|
gtk_css_ruleset_clear (&ruleset);
|
||||||
else
|
|
||||||
g_slist_free_full (selectors, (GDestroyNotify) _gtk_css_selector_free);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -2114,8 +2105,8 @@ static int
|
|||||||
gtk_css_provider_compare_rule (gconstpointer a_,
|
gtk_css_provider_compare_rule (gconstpointer a_,
|
||||||
gconstpointer b_)
|
gconstpointer b_)
|
||||||
{
|
{
|
||||||
const GtkCssRuleset *a = *(const GtkCssRuleset **) a_;
|
const GtkCssRuleset *a = (const GtkCssRuleset *) a_;
|
||||||
const GtkCssRuleset *b = *(const GtkCssRuleset **) b_;
|
const GtkCssRuleset *b = (const GtkCssRuleset *) b_;
|
||||||
int compare;
|
int compare;
|
||||||
|
|
||||||
compare = _gtk_css_selector_compare (a->selector, b->selector);
|
compare = _gtk_css_selector_compare (a->selector, b->selector);
|
||||||
@ -2137,7 +2128,7 @@ gtk_css_provider_postprocess (GtkCssProvider *css_provider)
|
|||||||
{
|
{
|
||||||
GtkCssProviderPrivate *priv = css_provider->priv;
|
GtkCssProviderPrivate *priv = css_provider->priv;
|
||||||
|
|
||||||
g_ptr_array_sort (priv->rulesets, gtk_css_provider_compare_rule);
|
g_array_sort (priv->rulesets, gtk_css_provider_compare_rule);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -2903,7 +2894,7 @@ gtk_css_provider_to_string (GtkCssProvider *provider)
|
|||||||
{
|
{
|
||||||
if (i > 0)
|
if (i > 0)
|
||||||
g_string_append (str, "\n");
|
g_string_append (str, "\n");
|
||||||
gtk_css_ruleset_print (g_ptr_array_index (priv->rulesets, i), str);
|
gtk_css_ruleset_print (&g_array_index (priv->rulesets, GtkCssRuleset, i), str);
|
||||||
}
|
}
|
||||||
|
|
||||||
return g_string_free (str, FALSE);
|
return g_string_free (str, FALSE);
|
||||||
|
Loading…
Reference in New Issue
Block a user