css: Redo value resolving

Instead of on-demand resolvage, we now resolve during lookup. The step
is done via
  _gtk_css_style_property_compute_value()
which currently calls into
  _gtk_css_style_compute_value()
That function has all the old resolving machinery.

The only part missing for now is the handling of win32 code. It will be
added back later.
This commit is contained in:
Benjamin Otte
2012-01-02 15:44:45 +01:00
parent 29382c1305
commit e87cf5d789
7 changed files with 227 additions and 233 deletions

View File

@ -135,6 +135,7 @@ _gtk_css_lookup_resolve (GtkCssLookup *lookup,
{
GtkCssStyleProperty *prop = _gtk_css_style_property_lookup_by_id (i);
const GValue *result;
GValue value = { 0, };
/* http://www.w3.org/TR/css3-cascade/#cascade
* Then, for every element, the value for each property can be found
@ -192,36 +193,31 @@ _gtk_css_lookup_resolve (GtkCssLookup *lookup,
}
}
if (result)
{
_gtk_style_properties_set_property_by_property (props,
prop,
0,
result);
}
else if (parent == NULL)
if (result == NULL && parent == NULL)
{
/* If the inherit value is set on the root element, the property is
* assigned its initial value. */
_gtk_style_properties_set_property_by_property (props,
prop,
0,
_gtk_css_style_property_get_initial_value (prop));
result = _gtk_css_style_property_get_initial_value (prop);
}
if (result)
{
_gtk_css_style_property_compute_value (prop, &value, context, result);
}
else
{
GValue value = { 0, };
/* Set NULL here and do the inheritance upon lookup? */
gtk_style_context_get_property (parent,
_gtk_style_property_get_name (GTK_STYLE_PROPERTY (prop)),
gtk_style_context_get_state (parent),
&value);
_gtk_style_properties_set_property_by_property (props,
prop,
0,
&value);
g_value_unset (&value);
}
_gtk_style_properties_set_property_by_property (props,
prop,
0,
&value);
g_value_unset (&value);
}
return props;

View File

@ -35,6 +35,7 @@
#include "gtkgradient.h"
#include "gtkprivatetypebuiltins.h"
#include "gtkshadowprivate.h"
#include "gtkstylecontextprivate.h"
#include "gtkthemingengine.h"
#include "gtktypebuiltins.h"
#include "gtkwin32themeprivate.h"
@ -46,22 +47,31 @@
static GHashTable *parse_funcs = NULL;
static GHashTable *print_funcs = NULL;
static GHashTable *compute_funcs = NULL;
typedef gboolean (* GtkStyleParseFunc) (GtkCssParser *parser,
GFile *base,
GValue *value);
typedef void (* GtkStylePrintFunc) (const GValue *value,
GString *string);
typedef void (* GtkStylePrintFunc) (const GValue *value,
GString *string);
typedef void (* GtkStyleComputeFunc) (GValue *computed,
GtkStyleContext *context,
const GValue *specified);
static void
register_conversion_function (GType type,
GtkStyleParseFunc parse,
GtkStylePrintFunc print)
register_conversion_function (GType type,
GtkStyleParseFunc parse,
GtkStylePrintFunc print,
GtkStyleComputeFunc compute)
{
if (parse)
g_hash_table_insert (parse_funcs, GSIZE_TO_POINTER (type), parse);
if (print)
g_hash_table_insert (print_funcs, GSIZE_TO_POINTER (type), print);
if (compute)
g_hash_table_insert (compute_funcs, GSIZE_TO_POINTER (type), compute);
}
static void
@ -197,6 +207,26 @@ rgba_value_print (const GValue *value,
}
}
static void
rgba_value_compute (GValue *computed,
GtkStyleContext *context,
const GValue *specified)
{
GdkRGBA rgba, white = { 1, 1, 1, 1 };
if (G_VALUE_HOLDS (specified, GTK_TYPE_SYMBOLIC_COLOR))
{
if (_gtk_style_context_resolve_color (context,
g_value_get_boxed (specified),
&rgba))
g_value_set_boxed (computed, &rgba);
else
g_value_set_boxed (computed, &white);
}
else
g_value_copy (specified, computed);
}
static gboolean
color_value_parse (GtkCssParser *parser,
GFile *base,
@ -245,6 +275,31 @@ color_value_print (const GValue *value,
}
}
static void
color_value_compute (GValue *computed,
GtkStyleContext *context,
const GValue *specified)
{
GdkRGBA rgba;
GdkColor color = { 0, 65535, 65535, 65535 };
if (G_VALUE_HOLDS (specified, GTK_TYPE_SYMBOLIC_COLOR))
{
if (_gtk_style_context_resolve_color (context,
g_value_get_boxed (specified),
&rgba))
{
color.red = rgba.red * 65535. + 0.5;
color.green = rgba.green * 65535. + 0.5;
color.blue = rgba.blue * 65535. + 0.5;
}
g_value_set_boxed (computed, &color);
}
else
g_value_copy (specified, computed);
}
static gboolean
symbolic_color_value_parse (GtkCssParser *parser,
GFile *base,
@ -1044,6 +1099,23 @@ pattern_value_print (const GValue *value,
}
}
static void
pattern_value_compute (GValue *computed,
GtkStyleContext *context,
const GValue *specified)
{
if (G_VALUE_HOLDS (specified, GTK_TYPE_GRADIENT))
{
cairo_pattern_t *gradient;
gradient = gtk_gradient_resolve_for_context (g_value_get_boxed (specified), context);
g_value_take_boxed (computed, gradient);
}
else
g_value_copy (specified, computed);
}
static gboolean
shadow_value_parse (GtkCssParser *parser,
GFile *base,
@ -1146,6 +1218,20 @@ shadow_value_print (const GValue *value,
_gtk_shadow_print (shadow, string);
}
static void
shadow_value_compute (GValue *computed,
GtkStyleContext *context,
const GValue *specified)
{
GtkShadow *shadow;
shadow = g_value_get_boxed (specified);
if (shadow)
shadow = _gtk_shadow_resolve (shadow, context);
g_value_take_boxed (computed, shadow);
}
static gboolean
background_repeat_value_parse (GtkCssParser *parser,
GFile *file,
@ -1326,67 +1412,88 @@ gtk_css_style_funcs_init (void)
parse_funcs = g_hash_table_new (NULL, NULL);
print_funcs = g_hash_table_new (NULL, NULL);
compute_funcs = g_hash_table_new (NULL, NULL);
register_conversion_function (GDK_TYPE_RGBA,
rgba_value_parse,
rgba_value_print);
rgba_value_print,
rgba_value_compute);
register_conversion_function (GDK_TYPE_COLOR,
color_value_parse,
color_value_print);
color_value_print,
color_value_compute);
register_conversion_function (GTK_TYPE_SYMBOLIC_COLOR,
symbolic_color_value_parse,
symbolic_color_value_print);
symbolic_color_value_print,
NULL);
register_conversion_function (PANGO_TYPE_FONT_DESCRIPTION,
font_description_value_parse,
font_description_value_print);
font_description_value_print,
NULL);
register_conversion_function (G_TYPE_BOOLEAN,
boolean_value_parse,
boolean_value_print);
boolean_value_print,
NULL);
register_conversion_function (G_TYPE_INT,
int_value_parse,
int_value_print);
int_value_print,
NULL);
register_conversion_function (G_TYPE_UINT,
uint_value_parse,
uint_value_print);
uint_value_print,
NULL);
register_conversion_function (G_TYPE_DOUBLE,
double_value_parse,
double_value_print);
double_value_print,
NULL);
register_conversion_function (G_TYPE_FLOAT,
float_value_parse,
float_value_print);
float_value_print,
NULL);
register_conversion_function (G_TYPE_STRING,
string_value_parse,
string_value_print);
string_value_print,
NULL);
register_conversion_function (GTK_TYPE_THEMING_ENGINE,
theming_engine_value_parse,
theming_engine_value_print);
theming_engine_value_print,
NULL);
register_conversion_function (GTK_TYPE_ANIMATION_DESCRIPTION,
animation_description_value_parse,
animation_description_value_print);
animation_description_value_print,
NULL);
register_conversion_function (GTK_TYPE_BORDER,
border_value_parse,
border_value_print);
border_value_print,
NULL);
register_conversion_function (GTK_TYPE_GRADIENT,
gradient_value_parse,
gradient_value_print);
gradient_value_print,
NULL);
register_conversion_function (CAIRO_GOBJECT_TYPE_PATTERN,
pattern_value_parse,
pattern_value_print);
pattern_value_print,
pattern_value_compute);
register_conversion_function (GTK_TYPE_CSS_BORDER_IMAGE_REPEAT,
border_image_repeat_value_parse,
border_image_repeat_value_print);
border_image_repeat_value_print,
NULL);
register_conversion_function (GTK_TYPE_SHADOW,
shadow_value_parse,
shadow_value_print);
shadow_value_print,
shadow_value_compute);
register_conversion_function (G_TYPE_ENUM,
enum_value_parse,
enum_value_print);
enum_value_print,
NULL);
register_conversion_function (G_TYPE_FLAGS,
flags_value_parse,
flags_value_print);
flags_value_print,
NULL);
register_conversion_function (GTK_TYPE_CSS_BACKGROUND_REPEAT,
background_repeat_value_parse,
background_repeat_value_print);
background_repeat_value_print,
NULL);
}
/**
@ -1463,3 +1570,39 @@ _gtk_css_style_print_value (const GValue *value,
func (value, string);
}
/**
* _gtk_css_style_compute_value:
* @computed: (out): a value to be filled with the result
* @context: the context to use for computing the value
* @specified: the value to use for the computation
*
* Converts the @specified value into the @computed value using the
* information in @context. The values must have matching types, ie
* @specified must be a result of a call to
* _gtk_css_style_parse_value() with the same type as @computed.
**/
void
_gtk_css_style_compute_value (GValue *computed,
GtkStyleContext *context,
const GValue *specified)
{
GtkStyleComputeFunc func;
g_return_if_fail (G_IS_VALUE (computed));
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (G_IS_VALUE (specified));
gtk_css_style_funcs_init ();
func = g_hash_table_lookup (compute_funcs,
GSIZE_TO_POINTER (G_VALUE_TYPE (computed)));
if (func == NULL)
func = g_hash_table_lookup (compute_funcs,
GSIZE_TO_POINTER (g_type_fundamental (G_VALUE_TYPE (computed))));
if (func)
func (computed, context, specified);
else
g_value_copy (specified, computed);
}

View File

@ -21,6 +21,7 @@
#define __GTK_CSS_STYLE_FUNCS_PRIVATE_H__
#include "gtkcssparserprivate.h"
#include "gtkstylecontext.h"
G_BEGIN_DECLS
@ -29,6 +30,9 @@ gboolean _gtk_css_style_parse_value (GValue
GFile *base);
void _gtk_css_style_print_value (const GValue *value,
GString *string);
void _gtk_css_style_compute_value (GValue *computed,
GtkStyleContext *context,
const GValue *specified);
G_END_DECLS

View File

@ -28,13 +28,6 @@
#include "gtkprivatetypebuiltins.h"
#include "gtkstylepropertiesprivate.h"
/* for resolvage */
#include <cairo-gobject.h>
#include "gtkgradient.h"
#include "gtkshadowprivate.h"
#include "gtkwin32themeprivate.h"
enum {
PROP_0,
PROP_ID,
@ -128,180 +121,6 @@ _gtk_style_property_default_value (GtkStyleProperty *property,
g_value_copy (_gtk_css_style_property_get_initial_value (GTK_CSS_STYLE_PROPERTY (property)), value);
}
static gboolean
resolve_color (GtkStyleProperties *props,
GValue *value)
{
GdkRGBA color;
/* Resolve symbolic color to GdkRGBA */
if (!gtk_symbolic_color_resolve (g_value_get_boxed (value), props, &color))
return FALSE;
/* Store it back, this is where GdkRGBA caching happens */
g_value_unset (value);
g_value_init (value, GDK_TYPE_RGBA);
g_value_set_boxed (value, &color);
return TRUE;
}
static gboolean
resolve_color_rgb (GtkStyleProperties *props,
GValue *value)
{
GdkColor color = { 0 };
GdkRGBA rgba;
if (!gtk_symbolic_color_resolve (g_value_get_boxed (value), props, &rgba))
return FALSE;
color.red = rgba.red * 65535. + 0.5;
color.green = rgba.green * 65535. + 0.5;
color.blue = rgba.blue * 65535. + 0.5;
g_value_unset (value);
g_value_init (value, GDK_TYPE_COLOR);
g_value_set_boxed (value, &color);
return TRUE;
}
static gboolean
resolve_win32_theme_part (GtkStyleProperties *props,
GValue *value,
GValue *value_out,
GtkStylePropertyContext *context)
{
GtkWin32ThemePart *part;
cairo_pattern_t *pattern;
part = g_value_get_boxed (value);
if (part == NULL)
return FALSE;
pattern = _gtk_win32_theme_part_render (part, context->width, context->height);
g_value_take_boxed (value_out, pattern);
return TRUE;
}
static gboolean
resolve_gradient (GtkStyleProperties *props,
GValue *value)
{
cairo_pattern_t *gradient;
if (!gtk_gradient_resolve (g_value_get_boxed (value), props, &gradient))
return FALSE;
/* Store it back, this is where cairo_pattern_t caching happens */
g_value_unset (value);
g_value_init (value, CAIRO_GOBJECT_TYPE_PATTERN);
g_value_take_boxed (value, gradient);
return TRUE;
}
static gboolean
resolve_shadow (GtkStyleProperties *props,
GValue *value)
{
GtkShadow *resolved, *base;
base = g_value_get_boxed (value);
if (base == NULL)
return TRUE;
if (_gtk_shadow_get_resolved (base))
return TRUE;
resolved = _gtk_shadow_resolve (base, props);
if (resolved == NULL)
return FALSE;
g_value_take_boxed (value, resolved);
return TRUE;
}
static void
_gtk_style_property_resolve (GtkStyleProperty *property,
GtkStyleProperties *props,
GtkStateFlags state,
GtkStylePropertyContext *context,
GValue *val,
GValue *val_out)
{
if (G_VALUE_TYPE (val) == GTK_TYPE_CSS_SPECIAL_VALUE)
{
GtkCssSpecialValue special = g_value_get_enum (val);
g_value_unset (val);
switch (special)
{
case GTK_CSS_CURRENT_COLOR:
g_assert (_gtk_style_property_get_value_type (property) == GDK_TYPE_RGBA);
gtk_style_properties_get_property (props, "color", state, val);
break;
case GTK_CSS_INHERIT:
case GTK_CSS_INITIAL:
default:
g_assert_not_reached ();
}
}
else if (G_VALUE_TYPE (val) == GTK_TYPE_SYMBOLIC_COLOR)
{
if (_gtk_style_property_get_value_type (property) == GDK_TYPE_RGBA)
{
if (resolve_color (props, val))
goto out;
}
else if (_gtk_style_property_get_value_type (property) == GDK_TYPE_COLOR)
{
if (resolve_color_rgb (props, val))
goto out;
}
g_value_unset (val);
g_value_init (val, _gtk_style_property_get_value_type (property));
_gtk_style_property_default_value (property, props, state, val);
}
else if (G_VALUE_TYPE (val) == GDK_TYPE_RGBA)
{
if (g_value_get_boxed (val) == NULL)
_gtk_style_property_default_value (property, props, state, val);
}
else if (G_VALUE_TYPE (val) == GTK_TYPE_GRADIENT)
{
g_return_if_fail (_gtk_style_property_get_value_type (property) == CAIRO_GOBJECT_TYPE_PATTERN);
if (!resolve_gradient (props, val))
{
g_value_unset (val);
g_value_init (val, CAIRO_GOBJECT_TYPE_PATTERN);
_gtk_style_property_default_value (property, props, state, val);
}
}
else if (G_VALUE_TYPE (val) == GTK_TYPE_SHADOW)
{
if (!resolve_shadow (props, val))
_gtk_style_property_default_value (property, props, state, val);
}
else if (G_VALUE_TYPE (val) == GTK_TYPE_WIN32_THEME_PART)
{
if (resolve_win32_theme_part (props, val, val_out, context))
return; /* Don't copy val, this sets val_out */
_gtk_style_property_default_value (property, props, state, val);
}
out:
g_value_copy (val, val_out);
}
static void
_gtk_css_style_property_query (GtkStyleProperty *property,
GtkStyleProperties *props,
@ -313,7 +132,7 @@ _gtk_css_style_property_query (GtkStyleProperty *property,
val = _gtk_style_properties_peek_property (props, GTK_CSS_STYLE_PROPERTY (property), state);
if (val)
_gtk_style_property_resolve (property, props, state, context, (GValue *) val, value);
g_value_copy (val, value);
else
_gtk_style_property_default_value (property, props, state, value);
}
@ -496,6 +315,33 @@ _gtk_css_style_property_get_initial_value (GtkCssStyleProperty *property)
return &property->initial_value;
}
/**
* _gtk_css_style_property_compute_value:
* @property: the property
* @computed: (out): an uninitialized value to be filled with the result
* @context: the context to use for resolving
* @specified: the value to compute from
*
* Converts the @specified value into the @computed value using the
* information in @context. This step is explained in detail in
* <ulink url="http://www.w3.org/TR/css3-cascade/#computed>
* the CSS documentation</ulink>.
**/
void
_gtk_css_style_property_compute_value (GtkCssStyleProperty *property,
GValue *computed,
GtkStyleContext *context,
const GValue *specified)
{
g_return_if_fail (GTK_IS_CSS_STYLE_PROPERTY (property));
g_return_if_fail (computed != NULL && !G_IS_VALUE (computed));
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (G_IS_VALUE (specified));
g_value_init (computed, _gtk_style_property_get_value_type (GTK_STYLE_PROPERTY (property)));
_gtk_css_style_compute_value (computed, context, specified);
}
/**
* _gtk_css_style_property_print_value:
* @property: the property

View File

@ -63,10 +63,16 @@ guint _gtk_css_style_property_get_id (GtkCssStyleProp
const GValue * _gtk_css_style_property_get_initial_value
(GtkCssStyleProperty *property);
void _gtk_css_style_property_compute_value (GtkCssStyleProperty *property,
GValue *computed,
GtkStyleContext *context,
const GValue *specified);
void _gtk_css_style_property_print_value (GtkCssStyleProperty *property,
const GValue *value,
GString *string);
G_END_DECLS
#endif /* __GTK_CSS_STYLE_PROPERTY_PRIVATE_H__ */

View File

@ -22,11 +22,10 @@
#include "config.h"
#include "gtkshadowprivate.h"
#include "gtkstylecontext.h"
#include "gtkstylecontextprivate.h"
#include "gtkthemingengineprivate.h"
#include "gtkthemingengine.h"
#include "gtkpango.h"
#include "gtkthemingengineprivate.h"
typedef struct _GtkShadowElement GtkShadowElement;
@ -186,8 +185,8 @@ _gtk_shadow_append (GtkShadow *shadow,
}
GtkShadow *
_gtk_shadow_resolve (GtkShadow *shadow,
GtkStyleProperties *props)
_gtk_shadow_resolve (GtkShadow *shadow,
GtkStyleContext *context)
{
GtkShadow *resolved_shadow;
GtkShadowElement *element, *resolved_element;
@ -203,9 +202,9 @@ _gtk_shadow_resolve (GtkShadow *shadow,
{
element = l->data;
if (!gtk_symbolic_color_resolve (element->symbolic_color,
props,
&color))
if (!_gtk_style_context_resolve_color (context,
element->symbolic_color,
&color))
{
_gtk_shadow_unref (resolved_shadow);
return NULL;

View File

@ -24,7 +24,7 @@
#include <glib-object.h>
#include "gtkstyleproperties.h"
#include "gtkstylecontext.h"
#include "gtksymboliccolor.h"
#include "gtkicontheme.h"
#include "gtkcsstypesprivate.h"
@ -54,7 +54,7 @@ void _gtk_shadow_print (GtkShadow *shadow,
GString *string);
GtkShadow *_gtk_shadow_resolve (GtkShadow *shadow,
GtkStyleProperties *props);
GtkStyleContext *context);
gboolean _gtk_shadow_get_resolved (GtkShadow *shadow);
void _gtk_text_shadow_paint_layout (GtkShadow *shadow,