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.
This commit is contained in:
Alexander Larsson 2012-03-08 14:52:10 +01:00
parent 3cfd1d93dc
commit 616cc5b96d
6 changed files with 158 additions and 85 deletions

View File

@ -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);

View File

@ -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
{

View File

@ -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;
}
/**

View File

@ -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);

View File

@ -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);

View File

@ -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);