Commit e87cf5d7 authored by Benjamin Otte's avatar Benjamin Otte

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.
parent 29382c13
......@@ -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;
......
......@@ -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);
}
......@@ -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
......
......@@ -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
......
......@@ -63,9 +63,15 @@ 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
......
......@@ -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;
......
......@@ -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,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment