From fbedcdaf7d72d4b015deb9e030606322bf5428ea Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Thu, 29 Dec 2011 14:04:33 +0100 Subject: [PATCH] css: Make CSS resolving work according to spec See inline code comments taken from http://dev.w3.org/csswg/css3-cascade/#cascade This now respects the special values "inherit" and "initial" properly. Note that those values cannot be parsed yet. This will be added in a future commit. --- gtk/gtkcsslookup.c | 96 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 90 insertions(+), 6 deletions(-) diff --git a/gtk/gtkcsslookup.c b/gtk/gtkcsslookup.c index c5fd148826..a3e272d108 100644 --- a/gtk/gtkcsslookup.c +++ b/gtk/gtkcsslookup.c @@ -21,6 +21,8 @@ #include "gtkcsslookupprivate.h" +#include "gtkcsstypesprivate.h" +#include "gtkprivatetypebuiltins.h" #include "gtkstylepropertyprivate.h" #include "gtkstylepropertiesprivate.h" @@ -120,13 +122,95 @@ _gtk_css_lookup_resolve (GtkCssLookup *lookup, for (i = 0; i < n; i++) { - if (lookup->values[i] == NULL) - continue; + const GtkStyleProperty *prop = _gtk_style_property_get (i); + const GValue *result; - _gtk_style_properties_set_property_by_property (props, - _gtk_style_property_get (i), - 0, - lookup->values[i]); + /* 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 (lookup->values[i] != NULL) + { + /* 2) If the cascading process (described below) yields a winning + * declaration and the value of the winning declaration is not + * ‘initial’ or ‘inherit’, the value of the winning declaration + * becomes the specified value. + */ + if (!G_VALUE_HOLDS (lookup->values[i], GTK_TYPE_CSS_SPECIAL_VALUE)) + { + result = lookup->values[i]; + } + else + { + switch (g_value_get_enum (lookup->values[i])) + { + case GTK_CSS_INHERIT: + /* 3) if the value of the winning declaration is ‘inherit’, + * the inherited value (see below) becomes the specified value. + */ + result = NULL; + break; + case GTK_CSS_INITIAL: + /* if the value of the winning declaration is ‘initial’, + * the initial value (see below) becomes the specified value. + */ + result = _gtk_style_property_get_initial_value (prop); + break; + default: + /* This is part of (2) above */ + result = lookup->values[i]; + break; + } + } + } + else + { + if (_gtk_style_property_is_inherit (prop)) + { + /* 4) if the property is inherited, the inherited value becomes + * the specified value. + */ + result = NULL; + } + else + { + /* 5) Otherwise, the initial value becomes the specified value. + */ + result = _gtk_style_property_get_initial_value (prop); + } + } + + if (result) + { + _gtk_style_properties_set_property_by_property (props, + prop, + 0, + result); + } + else if (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_style_property_get_initial_value (prop)); + } + else + { + GValue value = { 0, }; + /* Set NULL here and do the inheritance upon lookup? */ + gtk_style_context_get_property (parent, + prop->pspec->name, + gtk_style_context_get_state (parent), + &value); + _gtk_style_properties_set_property_by_property (props, + prop, + 0, + &value); + g_value_unset (&value); + } } return props;