diff options
author | Matthias Clasen <mclasen@redhat.com> | 2020-01-24 22:52:38 -0500 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2020-01-25 01:20:17 -0500 |
commit | 4ab0e7956eb90e9d99ba686117fb1896cfc4f31a (patch) | |
tree | e202d021e0ab270ad528e9610273d9a4926e53e8 /gtk/gtkcssstaticstyle.c | |
parent | 1eec7362b91fe083599890e753e4398673b78994 (diff) | |
download | gtk+-matthiasc/css-value-inner-loop.tar.gz |
css: Reshuffle the inner loop of value computationmatthiasc/css-value-inner-loop
The loop over all properties in gtk_css_static_style_compute_values
is the inner loop of the css value computation, we hit it thousands
of times per frame. Rearrange things to make this faster, by avoiding
function calls, pulling the section handling out of the separate loop,
and handling the border-width special case in a neater way.
Before: 50 runs, min 12.45, max 20.419, avg 15.9414
After: 50 runs, min 12.622, max 21.195, avg 15.0449
Diffstat (limited to 'gtk/gtkcssstaticstyle.c')
-rw-r--r-- | gtk/gtkcssstaticstyle.c | 215 |
1 files changed, 115 insertions, 100 deletions
diff --git a/gtk/gtkcssstaticstyle.c b/gtk/gtkcssstaticstyle.c index 0c6b8da04b..f99f9efbc6 100644 --- a/gtk/gtkcssstaticstyle.c +++ b/gtk/gtkcssstaticstyle.c @@ -115,34 +115,6 @@ maybe_unref_section (gpointer section) gtk_css_section_unref (section); } -static void -gtk_css_static_style_set_value (GtkCssStaticStyle *style, - guint id, - GtkCssValue *value, - GtkCssSection *section) -{ - if (style->values[id]) - _gtk_css_value_unref (style->values[id]); - - style->values[id] = value; - - if (style->sections && style->sections->len > id && g_ptr_array_index (style->sections, id)) - { - gtk_css_section_unref (g_ptr_array_index (style->sections, id)); - g_ptr_array_index (style->sections, id) = NULL; - } - - if (section) - { - if (style->sections == NULL) - style->sections = g_ptr_array_new_with_free_func (maybe_unref_section); - if (style->sections->len <= id) - g_ptr_array_set_size (style->sections, id + 1); - - g_ptr_array_index (style->sections, id) = gtk_css_section_ref (section); - } -} - static GtkCssStyle *default_style; static void @@ -175,6 +147,120 @@ gtk_css_static_style_get_default (void) return default_style; } +G_STATIC_ASSERT (GTK_CSS_PROPERTY_BORDER_TOP_STYLE == GTK_CSS_PROPERTY_BORDER_TOP_WIDTH - 1); +G_STATIC_ASSERT (GTK_CSS_PROPERTY_BORDER_RIGHT_STYLE == GTK_CSS_PROPERTY_BORDER_RIGHT_WIDTH - 1); +G_STATIC_ASSERT (GTK_CSS_PROPERTY_BORDER_BOTTOM_STYLE == GTK_CSS_PROPERTY_BORDER_BOTTOM_WIDTH - 1); +G_STATIC_ASSERT (GTK_CSS_PROPERTY_BORDER_LEFT_STYLE == GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH - 1); +G_STATIC_ASSERT (GTK_CSS_PROPERTY_OUTLINE_STYLE == GTK_CSS_PROPERTY_OUTLINE_WIDTH - 1); + +static inline gboolean +is_border_style_special_case (guint id) +{ + switch (id) + { + case GTK_CSS_PROPERTY_BORDER_TOP_STYLE: + case GTK_CSS_PROPERTY_BORDER_RIGHT_STYLE: + case GTK_CSS_PROPERTY_BORDER_BOTTOM_STYLE: + case GTK_CSS_PROPERTY_BORDER_LEFT_STYLE: + case GTK_CSS_PROPERTY_OUTLINE_STYLE: + return TRUE; + default: + return FALSE; + } +} + +static void +gtk_css_static_style_compute_values (GtkCssStaticStyle *style, + GtkStyleProvider *provider, + GtkCssStyle *parent_style, + GtkCssLookup *lookup) +{ + GtkCssLookupValue *values = lookup->values; + guint id; + GtkCssValue **parent_values; + guint border_prop[] = { + GTK_CSS_PROPERTY_BORDER_TOP_STYLE, + GTK_CSS_PROPERTY_BORDER_LEFT_STYLE, + GTK_CSS_PROPERTY_BORDER_BOTTOM_STYLE, + GTK_CSS_PROPERTY_BORDER_RIGHT_STYLE, + GTK_CSS_PROPERTY_OUTLINE_STYLE, + 0 + }; + int b = 0; + + if (GTK_IS_CSS_STATIC_STYLE (parent_style)) + parent_values = GTK_CSS_STATIC_STYLE (parent_style)->values; + else + parent_values = NULL; + + for (id = 0; id < GTK_CSS_PROPERTY_N_PROPERTIES; id++) + { + GtkCssValue *specified = values[id].value; + + /* http://www.w3.org/TR/css3-cascade/#cascade + * Then, for every element, the value for each property can be found + * by following this pseudo-algorithm: + * 1) Identify all declarations that apply to the element + */ + if (specified) + { + style->values[id] = _gtk_css_value_compute (specified, id, provider, (GtkCssStyle *)style, parent_style); + + /* special case according to http://dev.w3.org/csswg/css-backgrounds/#the-border-width */ + if (id == border_prop[b]) + { + b++; + /* We have them ordered in gtkcssstylepropertyimpl.c accordingly, so the + * border styles are computed before the border widths. + * Note that we rely on ..._WIDTH == ..._STYLE + 1 here. + */ + GtkBorderStyle border_style = _gtk_css_border_style_value_get (style->values[id]); + if (border_style == GTK_BORDER_STYLE_NONE || border_style == GTK_BORDER_STYLE_HIDDEN) + { + id++; + style->values[id] = gtk_css_dimension_value_new (0, GTK_CSS_NUMBER); + } + } + } + else if (parent_values && gtk_css_style_property_is_inherit (id)) + { + style->values[id] = _gtk_css_value_ref (parent_values[id]); + + /* the border properties are not inherit, so no need to check the special case here */ + } + else if (parent_style && gtk_css_style_property_is_inherit (id)) + { + style->values[id] = _gtk_css_value_ref (gtk_css_style_get_value (parent_style, id)); + + /* the border properties are not inherit, so no need to check the special case here */ + } + else + { + style->values[id] = _gtk_css_initial_value_new_compute (id, provider, (GtkCssStyle *)style, parent_style); + + /* special case according to http://dev.w3.org/csswg/css-backgrounds/#the-border-width */ + if (id == border_prop[b]) + { + b++; + /* no need to check the value. The initial value of the border-style properties is none */ + id++; + style->values[id] = gtk_css_dimension_value_new (0, GTK_CSS_NUMBER); + } + } + } + + if (lookup->has_section) + { + style->sections = g_ptr_array_new_full (GTK_CSS_PROPERTY_N_PROPERTIES, maybe_unref_section); + for (id = 0; id < GTK_CSS_PROPERTY_N_PROPERTIES; id++) + { + GtkCssSection *section = values[id].section; + if (section) + g_ptr_array_index (style->sections, id) = gtk_css_section_ref (section); + } + } +} + GtkCssStyle * gtk_css_static_style_new_compute (GtkStyleProvider *provider, const GtkCssMatcher *matcher, @@ -196,84 +282,13 @@ gtk_css_static_style_new_compute (GtkStyleProvider *provider, result->change = change; - _gtk_css_lookup_resolve (&lookup, - provider, - result, - parent); + gtk_css_static_style_compute_values (result, provider, parent, &lookup); _gtk_css_lookup_destroy (&lookup); return GTK_CSS_STYLE (result); } -G_STATIC_ASSERT (GTK_CSS_PROPERTY_BORDER_TOP_STYLE == GTK_CSS_PROPERTY_BORDER_TOP_WIDTH - 1); -G_STATIC_ASSERT (GTK_CSS_PROPERTY_BORDER_RIGHT_STYLE == GTK_CSS_PROPERTY_BORDER_RIGHT_WIDTH - 1); -G_STATIC_ASSERT (GTK_CSS_PROPERTY_BORDER_BOTTOM_STYLE == GTK_CSS_PROPERTY_BORDER_BOTTOM_WIDTH - 1); -G_STATIC_ASSERT (GTK_CSS_PROPERTY_BORDER_LEFT_STYLE == GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH - 1); -G_STATIC_ASSERT (GTK_CSS_PROPERTY_OUTLINE_STYLE == GTK_CSS_PROPERTY_OUTLINE_WIDTH - 1); - -void -gtk_css_static_style_compute_value (GtkCssStaticStyle *style, - GtkStyleProvider *provider, - GtkCssStyle *parent_style, - guint id, - GtkCssValue *specified, - GtkCssSection *section) -{ - GtkCssValue *value; - GtkBorderStyle border_style; - - gtk_internal_return_if_fail (id < GTK_CSS_PROPERTY_N_PROPERTIES); - - /* special case according to http://dev.w3.org/csswg/css-backgrounds/#the-border-width */ - switch (id) - { - /* We have them ordered in gtkcssstylepropertyimpl.c accordingly, so the - * border styles are already computed when we compute the border widths. - * - * Note that we rely on ..._STYLE == ..._WIDTH - 1 here. - */ - case GTK_CSS_PROPERTY_BORDER_TOP_WIDTH: - case GTK_CSS_PROPERTY_BORDER_RIGHT_WIDTH: - case GTK_CSS_PROPERTY_BORDER_BOTTOM_WIDTH: - case GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH: - case GTK_CSS_PROPERTY_OUTLINE_WIDTH: - border_style = _gtk_css_border_style_value_get (gtk_css_style_get_value ((GtkCssStyle *)style, id - 1)); - if (border_style == GTK_BORDER_STYLE_NONE || border_style == GTK_BORDER_STYLE_HIDDEN) - { - gtk_css_static_style_set_value (style, id, gtk_css_dimension_value_new (0, GTK_CSS_NUMBER), section); - return; - } - break; - - default: - /* Go ahead */ - break; - } - - - /* http://www.w3.org/TR/css3-cascade/#cascade - * Then, for every element, the value for each property can be found - * by following this pseudo-algorithm: - * 1) Identify all declarations that apply to the element - */ - if (specified) - { - value = _gtk_css_value_compute (specified, id, provider, (GtkCssStyle *)style, parent_style); - } - else if (parent_style && _gtk_css_style_property_is_inherit (_gtk_css_style_property_lookup_by_id (id))) - { - /* Just take the style from the parent */ - value = _gtk_css_value_ref (gtk_css_style_get_value (parent_style, id)); - } - else - { - value = _gtk_css_initial_value_new_compute (id, provider, (GtkCssStyle *)style, parent_style); - } - - gtk_css_static_style_set_value (style, id, value, section); -} - GtkCssChange gtk_css_static_style_get_change (GtkCssStaticStyle *style) { |