diff --git a/gtk/gtkcsslookup.c b/gtk/gtkcsslookup.c index dc43005287..af4eddfd41 100644 --- a/gtk/gtkcsslookup.c +++ b/gtk/gtkcsslookup.c @@ -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; diff --git a/gtk/gtkcssstylefuncs.c b/gtk/gtkcssstylefuncs.c index 5ba366c0c9..a7b31f1cab 100644 --- a/gtk/gtkcssstylefuncs.c +++ b/gtk/gtkcssstylefuncs.c @@ -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); +} + diff --git a/gtk/gtkcssstylefuncsprivate.h b/gtk/gtkcssstylefuncsprivate.h index d4d2932b39..a3a564174c 100644 --- a/gtk/gtkcssstylefuncsprivate.h +++ b/gtk/gtkcssstylefuncsprivate.h @@ -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 diff --git a/gtk/gtkcssstyleproperty.c b/gtk/gtkcssstyleproperty.c index 76021dc8ef..2f542449f9 100644 --- a/gtk/gtkcssstyleproperty.c +++ b/gtk/gtkcssstyleproperty.c @@ -28,13 +28,6 @@ #include "gtkprivatetypebuiltins.h" #include "gtkstylepropertiesprivate.h" -/* for resolvage */ -#include -#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 + * 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; diff --git a/gtk/gtkshadowprivate.h b/gtk/gtkshadowprivate.h index 5b9bad5f0c..6537ba92e4 100644 --- a/gtk/gtkshadowprivate.h +++ b/gtk/gtkshadowprivate.h @@ -24,7 +24,7 @@ #include -#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,