1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 2011 Benjamin Otte <otte@gnome.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
22 #include "gtkcsslookupprivate.h"
24 #include "gtkcsstypesprivate.h"
25 #include "gtkprivatetypebuiltins.h"
26 #include "gtkcssstylepropertyprivate.h"
27 #include "gtkstylepropertiesprivate.h"
30 GtkCssSection *section;
34 struct _GtkCssLookup {
36 GtkCssLookupValue values[1];
40 _gtk_css_lookup_new (void)
43 guint n = _gtk_css_style_property_get_n_properties ();
45 lookup = g_malloc0 (sizeof (GtkCssLookup) + sizeof (GtkCssLookupValue) * n);
46 lookup->missing = _gtk_bitmask_new ();
47 _gtk_bitmask_invert_range (lookup->missing, 0, n);
53 _gtk_css_lookup_free (GtkCssLookup *lookup)
55 g_return_if_fail (lookup != NULL);
57 _gtk_bitmask_free (lookup->missing);
62 _gtk_css_lookup_get_missing (const GtkCssLookup *lookup)
64 g_return_val_if_fail (lookup != NULL, NULL);
66 return lookup->missing;
70 _gtk_css_lookup_is_missing (const GtkCssLookup *lookup,
73 g_return_val_if_fail (lookup != NULL, FALSE);
75 return lookup->values[id].value == NULL;
79 * _gtk_css_lookup_set:
81 * @id: id of the property to set, see _gtk_style_property_get_id()
82 * @section: (allow-none): The @section the value was defined in or %NULL
83 * @value: the "cascading value" to use
85 * Sets the @value for a given @id. No value may have been set for @id
86 * before. See _gtk_css_lookup_is_missing(). This function is used to
87 * set the "winning declaration" of a lookup. Note that for performance
88 * reasons @value and @section are not copied. It is your responsibility
89 * to ensure they are kept alive until _gtk_css_lookup_free() is called.
92 _gtk_css_lookup_set (GtkCssLookup *lookup,
94 GtkCssSection *section,
97 g_return_if_fail (lookup != NULL);
98 g_return_if_fail (_gtk_bitmask_get (lookup->missing, id));
99 g_return_if_fail (value != NULL);
101 _gtk_bitmask_set (lookup->missing, id, FALSE);
102 lookup->values[id].value = value;
103 lookup->values[id].section = section;
107 * _gtk_css_lookup_resolve:
108 * @lookup: the lookup
109 * @context: the context the values are resolved for
111 * Resolves the current lookup into a styleproperties object. This is done
112 * by converting from the "winning declaration" to the "computed value".
114 * XXX: This bypasses the notion of "specified value". If this ever becomes
115 * an issue, go fix it.
117 * Returns: a new #GtkStyleProperties
120 _gtk_css_lookup_resolve (GtkCssLookup *lookup,
121 GtkStyleContext *context)
123 GtkStyleProperties *props;
124 GtkStyleContext *parent;
127 g_return_val_if_fail (lookup != NULL, NULL);
128 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
130 parent = gtk_style_context_get_parent (context);
131 n = _gtk_css_style_property_get_n_properties ();
132 props = gtk_style_properties_new ();
134 for (i = 0; i < n; i++)
136 GtkCssStyleProperty *prop = _gtk_css_style_property_lookup_by_id (i);
137 const GValue *result;
138 GValue value = { 0, };
140 /* http://www.w3.org/TR/css3-cascade/#cascade
141 * Then, for every element, the value for each property can be found
142 * by following this pseudo-algorithm:
143 * 1) Identify all declarations that apply to the element
145 if (lookup->values[i].value != NULL)
147 /* 2) If the cascading process (described below) yields a winning
148 * declaration and the value of the winning declaration is not
149 * ‘initial’ or ‘inherit’, the value of the winning declaration
150 * becomes the specified value.
152 if (!G_VALUE_HOLDS (lookup->values[i].value, GTK_TYPE_CSS_SPECIAL_VALUE))
154 result = lookup->values[i].value;
158 switch (g_value_get_enum (lookup->values[i].value))
160 case GTK_CSS_INHERIT:
161 /* 3) if the value of the winning declaration is ‘inherit’,
162 * the inherited value (see below) becomes the specified value.
166 case GTK_CSS_INITIAL:
167 /* if the value of the winning declaration is ‘initial’,
168 * the initial value (see below) becomes the specified value.
170 result = _gtk_css_style_property_get_initial_value (prop);
173 /* This is part of (2) above */
174 result = lookup->values[i].value;
181 if (_gtk_css_style_property_is_inherit (prop))
183 /* 4) if the property is inherited, the inherited value becomes
184 * the specified value.
190 /* 5) Otherwise, the initial value becomes the specified value.
192 result = _gtk_css_style_property_get_initial_value (prop);
196 if (result == NULL && parent == NULL)
198 /* If the ‘inherit’ value is set on the root element, the property is
199 * assigned its initial value. */
200 result = _gtk_css_style_property_get_initial_value (prop);
205 _gtk_css_style_property_compute_value (prop, &value, context, result);
209 /* Set NULL here and do the inheritance upon lookup? */
210 result = _gtk_style_context_peek_property (parent,
211 _gtk_style_property_get_name (GTK_STYLE_PROPERTY (prop)));
212 g_value_init (&value, G_VALUE_TYPE (result));
213 g_value_copy (result, &value);
216 _gtk_style_properties_set_property_by_property (props,
220 g_value_unset (&value);