From 616cc5b96dc6d04ec0dcb43fe1024dc5473bfc9b Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Thu, 8 Mar 2012 14:52:10 +0100 Subject: [PATCH] Use GtkCssValue in symbolic color resolving We now store the symbolic colors as a GtkCssValue which means that we can reuse the color when resolving and storing the color in the computed values in the style context. Additionally we keep a last_resolved GtkCssValue cache in the GtkSymbolicColor, and if resolving the color returns the same as last time we reuse the old value. This further increases sharing of Css Values. --- gtk/gtkcssstylefuncs.c | 14 +-- gtk/gtkcssstylepropertyimpl.c | 9 +- gtk/gtkstylecontext.c | 28 +++++- gtk/gtkstylecontextprivate.h | 2 + gtk/gtksymboliccolor.c | 184 +++++++++++++++++++++------------- gtk/gtksymboliccolorprivate.h | 6 +- 6 files changed, 158 insertions(+), 85 deletions(-) diff --git a/gtk/gtkcssstylefuncs.c b/gtk/gtkcssstylefuncs.c index b1e373e82a..0693e04487 100644 --- a/gtk/gtkcssstylefuncs.c +++ b/gtk/gtkcssstylefuncs.c @@ -215,7 +215,8 @@ static GtkCssValue * rgba_value_compute (GtkStyleContext *context, GtkCssValue *specified) { - GdkRGBA rgba, white = { 1, 1, 1, 1 }; + GdkRGBA white = { 1, 1, 1, 1 }; + GtkCssValue *res; if (_gtk_css_value_holds (specified, GTK_TYPE_CSS_SPECIAL_VALUE)) { @@ -227,12 +228,13 @@ rgba_value_compute (GtkStyleContext *context, if (symbolic == _gtk_symbolic_color_get_current_color ()) return _gtk_css_value_ref (_gtk_style_context_peek_property (context, "color")); - else if (_gtk_style_context_resolve_color (context, - symbolic, - &rgba)) - return _gtk_css_value_new_from_rgba (&rgba); - else + else { + res = _gtk_style_context_resolve_color_value (context, symbolic); + if (res != NULL) + return res; + return _gtk_css_value_new_from_rgba (&white); + } } else return _gtk_css_value_ref (specified); diff --git a/gtk/gtkcssstylepropertyimpl.c b/gtk/gtkcssstylepropertyimpl.c index 5d206e3be3..f6d4b491f3 100644 --- a/gtk/gtkcssstylepropertyimpl.c +++ b/gtk/gtkcssstylepropertyimpl.c @@ -146,7 +146,7 @@ color_compute (GtkCssStyleProperty *property, GtkCssValue *specified) { GtkSymbolicColor *symbolic = _gtk_css_value_get_symbolic_color (specified); - GdkRGBA rgba; + GtkCssValue *resolved; if (symbolic == _gtk_symbolic_color_get_current_color ()) { @@ -170,11 +170,10 @@ color_compute (GtkCssStyleProperty *property, return _gtk_css_value_ref (_gtk_style_context_peek_property (context, "color")); } } - else if (_gtk_style_context_resolve_color (context, - symbolic, - &rgba)) + else if ((resolved = _gtk_style_context_resolve_color_value (context, + symbolic)) != NULL) { - return _gtk_css_value_new_from_rgba (&rgba); + return resolved; } else { diff --git a/gtk/gtkstylecontext.c b/gtk/gtkstylecontext.c index 42673c3dea..e04e03b452 100644 --- a/gtk/gtkstylecontext.c +++ b/gtk/gtkstylecontext.c @@ -2919,19 +2919,39 @@ gtk_style_context_color_lookup_func (gpointer contextp, return sym_color; } +GtkCssValue * +_gtk_style_context_resolve_color_value (GtkStyleContext *context, + GtkSymbolicColor *color) +{ + g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), FALSE); + g_return_val_if_fail (color != NULL, FALSE); + + return _gtk_symbolic_color_resolve_full (color, + gtk_style_context_color_lookup_func, + context); +} + + gboolean _gtk_style_context_resolve_color (GtkStyleContext *context, GtkSymbolicColor *color, GdkRGBA *result) { + GtkCssValue *val; + g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), FALSE); g_return_val_if_fail (color != NULL, FALSE); g_return_val_if_fail (result != NULL, FALSE); - return _gtk_symbolic_color_resolve_full (color, - gtk_style_context_color_lookup_func, - context, - result); + val = _gtk_symbolic_color_resolve_full (color, + gtk_style_context_color_lookup_func, + context); + if (val == NULL) + return FALSE; + + *result = *_gtk_css_value_get_rgba (val); + _gtk_css_value_unref (val); + return TRUE; } /** diff --git a/gtk/gtkstylecontextprivate.h b/gtk/gtkstylecontextprivate.h index 06efa0f83b..dbec998443 100644 --- a/gtk/gtkstylecontextprivate.h +++ b/gtk/gtkstylecontextprivate.h @@ -41,6 +41,8 @@ gboolean _gtk_style_context_check_region_name (const gchar *s gboolean _gtk_style_context_resolve_color (GtkStyleContext *context, GtkSymbolicColor *color, GdkRGBA *result); +GtkCssValue * _gtk_style_context_resolve_color_value (GtkStyleContext *context, + GtkSymbolicColor *color); void _gtk_style_context_get_cursor_color (GtkStyleContext *context, GdkRGBA *primary_color, GdkRGBA *secondary_color); diff --git a/gtk/gtksymboliccolor.c b/gtk/gtksymboliccolor.c index bb4c2b8e89..b96a2348fd 100644 --- a/gtk/gtksymboliccolor.c +++ b/gtk/gtksymboliccolor.c @@ -58,10 +58,10 @@ struct _GtkSymbolicColor { ColorType type; guint ref_count; + GtkCssValue *last_value; union { - GdkRGBA color; gchar *name; struct @@ -104,7 +104,7 @@ gtk_symbolic_color_new_literal (const GdkRGBA *color) symbolic_color = g_slice_new0 (GtkSymbolicColor); symbolic_color->type = COLOR_TYPE_LITERAL; - symbolic_color->color = *color; + symbolic_color->last_value = _gtk_css_value_new_from_rgba (color); symbolic_color->ref_count = 1; return symbolic_color; @@ -328,27 +328,28 @@ gtk_symbolic_color_unref (GtkSymbolicColor *color) if (color->ref_count == 0) { + _gtk_css_value_unref (color->last_value); switch (color->type) - { - case COLOR_TYPE_NAME: - g_free (color->name); - break; - case COLOR_TYPE_SHADE: - gtk_symbolic_color_unref (color->shade.color); - break; - case COLOR_TYPE_ALPHA: - gtk_symbolic_color_unref (color->alpha.color); - break; - case COLOR_TYPE_MIX: - gtk_symbolic_color_unref (color->mix.color1); - gtk_symbolic_color_unref (color->mix.color2); - break; - case COLOR_TYPE_WIN32: - g_free (color->win32.theme_class); - break; - default: - break; - } + { + case COLOR_TYPE_NAME: + g_free (color->name); + break; + case COLOR_TYPE_SHADE: + gtk_symbolic_color_unref (color->shade.color); + break; + case COLOR_TYPE_ALPHA: + gtk_symbolic_color_unref (color->alpha.color); + break; + case COLOR_TYPE_MIX: + gtk_symbolic_color_unref (color->mix.color1); + gtk_symbolic_color_unref (color->mix.color2); + break; + case COLOR_TYPE_WIN32: + g_free (color->win32.theme_class); + break; + default: + break; + } g_slice_free (GtkSymbolicColor, color); } @@ -560,106 +561,155 @@ resolve_lookup_color (gpointer data, const char *name) **/ gboolean gtk_symbolic_color_resolve (GtkSymbolicColor *color, - GtkStyleProperties *props, - GdkRGBA *resolved_color) + GtkStyleProperties *props, + GdkRGBA *resolved_color) { + GtkCssValue *v; + g_return_val_if_fail (color != NULL, FALSE); g_return_val_if_fail (resolved_color != NULL, FALSE); g_return_val_if_fail (props == NULL || GTK_IS_STYLE_PROPERTIES (props), FALSE); - return _gtk_symbolic_color_resolve_full (color, - resolve_lookup_color, - props, - resolved_color); + v =_gtk_symbolic_color_resolve_full (color, + resolve_lookup_color, + props); + if (v == NULL) + return FALSE; + + *resolved_color = *_gtk_css_value_get_rgba (v); + _gtk_css_value_unref (v); + return TRUE; } -gboolean +GtkCssValue * _gtk_symbolic_color_resolve_full (GtkSymbolicColor *color, - GtkSymbolicColorLookupFunc func, - gpointer data, - GdkRGBA *resolved_color) + GtkSymbolicColorLookupFunc func, + gpointer data) { + GtkCssValue *value; + g_return_val_if_fail (color != NULL, FALSE); - g_return_val_if_fail (resolved_color != NULL, FALSE); g_return_val_if_fail (func != NULL, FALSE); + value = NULL; switch (color->type) { case COLOR_TYPE_LITERAL: - *resolved_color = color->color; - return TRUE; + return _gtk_css_value_ref (color->last_value); case COLOR_TYPE_NAME: { - GtkSymbolicColor *named_color; + GtkSymbolicColor *named_color; - named_color = func (data, color->name); + named_color = func (data, color->name); - if (!named_color) - return FALSE; + if (!named_color) + return NULL; - return _gtk_symbolic_color_resolve_full (named_color, func, data, resolved_color); + return _gtk_symbolic_color_resolve_full (named_color, func, data); } break; case COLOR_TYPE_SHADE: { - GdkRGBA shade; + GtkCssValue *val; + GdkRGBA shade; - if (!_gtk_symbolic_color_resolve_full (color->shade.color, func, data, &shade)) - return FALSE; + val = _gtk_symbolic_color_resolve_full (color->shade.color, func, data); + if (val == NULL) + return NULL; - _shade_color (&shade, color->shade.factor); - *resolved_color = shade; + shade = *_gtk_css_value_get_rgba (val); + _shade_color (&shade, color->shade.factor); - return TRUE; + _gtk_css_value_unref (val); + + value = _gtk_css_value_new_from_rgba (&shade); } break; case COLOR_TYPE_ALPHA: { - GdkRGBA alpha; + GtkCssValue *val; + GdkRGBA alpha; - if (!_gtk_symbolic_color_resolve_full (color->alpha.color, func, data, &alpha)) - return FALSE; + val = _gtk_symbolic_color_resolve_full (color->alpha.color, func, data); + if (val == NULL) + return NULL; - *resolved_color = alpha; - resolved_color->alpha = CLAMP (alpha.alpha * color->alpha.factor, 0, 1); + alpha = *_gtk_css_value_get_rgba (val); + alpha.alpha = CLAMP (alpha.alpha * color->alpha.factor, 0, 1); - return TRUE; + _gtk_css_value_unref (val); + + value = _gtk_css_value_new_from_rgba (&alpha); } + break; + case COLOR_TYPE_MIX: { - GdkRGBA color1, color2; + GtkCssValue *val; + GdkRGBA color1, color2, res; - if (!_gtk_symbolic_color_resolve_full (color->mix.color1, func, data, &color1)) - return FALSE; + val = _gtk_symbolic_color_resolve_full (color->mix.color1, func, data); + if (val == NULL) + return NULL; + color1 = *_gtk_css_value_get_rgba (val); + _gtk_css_value_unref (val); - if (!_gtk_symbolic_color_resolve_full (color->mix.color2, func, data, &color2)) - return FALSE; + val = _gtk_symbolic_color_resolve_full (color->mix.color2, func, data); + if (val == NULL) + return NULL; + color2 = *_gtk_css_value_get_rgba (val); + _gtk_css_value_unref (val); - resolved_color->red = CLAMP (color1.red + ((color2.red - color1.red) * color->mix.factor), 0, 1); - resolved_color->green = CLAMP (color1.green + ((color2.green - color1.green) * color->mix.factor), 0, 1); - resolved_color->blue = CLAMP (color1.blue + ((color2.blue - color1.blue) * color->mix.factor), 0, 1); - resolved_color->alpha = CLAMP (color1.alpha + ((color2.alpha - color1.alpha) * color->mix.factor), 0, 1); - return TRUE; + res.red = CLAMP (color1.red + ((color2.red - color1.red) * color->mix.factor), 0, 1); + res.green = CLAMP (color1.green + ((color2.green - color1.green) * color->mix.factor), 0, 1); + res.blue = CLAMP (color1.blue + ((color2.blue - color1.blue) * color->mix.factor), 0, 1); + res.alpha = CLAMP (color1.alpha + ((color2.alpha - color1.alpha) * color->mix.factor), 0, 1); + + value =_gtk_css_value_new_from_rgba (&res); } break; case COLOR_TYPE_WIN32: - return _gtk_win32_theme_color_resolve (color->win32.theme_class, + { + GdkRGBA res; + + if (!_gtk_win32_theme_color_resolve (color->win32.theme_class, color->win32.id, - resolved_color); + &res)) + return NULL; + + value = _gtk_css_value_new_from_rgba (&res); + } break; case COLOR_TYPE_CURRENT_COLOR: - return FALSE; + return NULL; break; default: g_assert_not_reached (); } - return FALSE; + if (value != NULL) + { + if (color->last_value != NULL && + gdk_rgba_equal (_gtk_css_value_get_rgba (color->last_value), + _gtk_css_value_get_rgba (value))) + { + _gtk_css_value_unref (value); + value = _gtk_css_value_ref (color->last_value); + } + else + { + if (color->last_value != NULL) + _gtk_css_value_unref (color->last_value); + color->last_value = _gtk_css_value_ref (value); + } + } + + return value; } /** @@ -684,7 +734,7 @@ gtk_symbolic_color_to_string (GtkSymbolicColor *color) switch (color->type) { case COLOR_TYPE_LITERAL: - s = gdk_rgba_to_string (&color->color); + s = gdk_rgba_to_string (_gtk_css_value_get_rgba (color->last_value)); break; case COLOR_TYPE_NAME: s = g_strconcat ("@", color->name, NULL); diff --git a/gtk/gtksymboliccolorprivate.h b/gtk/gtksymboliccolorprivate.h index a469626cc9..869af698a9 100644 --- a/gtk/gtksymboliccolorprivate.h +++ b/gtk/gtksymboliccolorprivate.h @@ -19,15 +19,15 @@ #define __GTK_SYMBOLIC_COLOR_PRIVATE_H__ #include "gtk/gtksymboliccolor.h" +#include "gtk/gtkcssvalueprivate.h" G_BEGIN_DECLS typedef GtkSymbolicColor * (* GtkSymbolicColorLookupFunc) (gpointer data, const char *name); -gboolean _gtk_symbolic_color_resolve_full (GtkSymbolicColor *color, +GtkCssValue * _gtk_symbolic_color_resolve_full (GtkSymbolicColor *color, GtkSymbolicColorLookupFunc func, - gpointer data, - GdkRGBA *resolved_color); + gpointer data); GtkSymbolicColor * _gtk_symbolic_color_get_current_color (void);