[gtk/css-style-split-2: 14/16] css: Split styles into groups



commit 5776d0dd992e8a68a06164b9a96f5aceca483fd1
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat Jan 25 23:16:06 2020 -0500

    css: Split styles into groups
    
    Introduce refcounted structs for groups of related css properties,
    and use them to store the style values. Both GtkCssStaticStyle and
    GtkCssAnimatedStyle fill in the structs in GtkCssStyle, and we
    can avoid vfuncs for value access, which should be much faster.
    We can even start accessing style->core->color directly.

 gtk/gtkcssanimatedstyle.c        | 483 ++++++++++++++++++++--
 gtk/gtkcssanimatedstyleprivate.h |   1 -
 gtk/gtkcsslookup.c               |  42 +-
 gtk/gtkcsslookupprivate.h        |  11 +-
 gtk/gtkcssstaticstyle.c          | 872 +++++++++++++++++++++++++++++++++++++--
 gtk/gtkcssstaticstyleprivate.h   |  10 +-
 gtk/gtkcssstyle.c                | 301 +++++++++++++-
 gtk/gtkcssstyleprivate.h         | 194 ++++++++-
 8 files changed, 1791 insertions(+), 123 deletions(-)
---
diff --git a/gtk/gtkcssanimatedstyle.c b/gtk/gtkcssanimatedstyle.c
index 12a1dc79ec..28ccf7326e 100644
--- a/gtk/gtkcssanimatedstyle.c
+++ b/gtk/gtkcssanimatedstyle.c
@@ -40,20 +40,6 @@
 
 G_DEFINE_TYPE (GtkCssAnimatedStyle, gtk_css_animated_style, GTK_TYPE_CSS_STYLE)
 
-static GtkCssValue *
-gtk_css_animated_style_get_value (GtkCssStyle *style,
-                                  guint        id)
-{
-  /* This is called a lot, so we avoid a dynamic type check here */
-  GtkCssAnimatedStyle *animated = (GtkCssAnimatedStyle *) style;
-
-  if (animated->animated_values &&
-      id < animated->animated_values->len &&
-      g_ptr_array_index (animated->animated_values, id))
-    return g_ptr_array_index (animated->animated_values, id);
-
-  return gtk_css_animated_style_get_intrinsic_value (animated, id);
-}
 
 static GtkCssSection *
 gtk_css_animated_style_get_section (GtkCssStyle *style,
@@ -94,12 +80,6 @@ gtk_css_animated_style_dispose (GObject *object)
   GtkCssAnimatedStyle *style = GTK_CSS_ANIMATED_STYLE (object);
   guint i;
 
-  if (style->animated_values)
-    {
-      g_ptr_array_unref (style->animated_values);
-      style->animated_values = NULL;
-    }
-
   for (i = 0; i < style->n_animations; i ++)
     g_object_unref (style->animations[i]);
 
@@ -129,7 +109,6 @@ gtk_css_animated_style_class_init (GtkCssAnimatedStyleClass *klass)
   object_class->dispose = gtk_css_animated_style_dispose;
   object_class->finalize = gtk_css_animated_style_finalize;
 
-  style_class->get_value = gtk_css_animated_style_get_value;
   style_class->get_section = gtk_css_animated_style_get_section;
   style_class->is_static = gtk_css_animated_style_is_static;
   style_class->get_static_style = gtk_css_animated_style_get_static_style;
@@ -140,24 +119,432 @@ gtk_css_animated_style_init (GtkCssAnimatedStyle *style)
 {
 }
 
+#define DEFINE_UNSHARE(TYPE, NAME) \
+static inline void \
+unshare_ ## NAME (GtkCssAnimatedStyle *animated) \
+{ \
+  GtkCssStyle *style = (GtkCssStyle *)animated; \
+  if (style->NAME == animated->style->NAME) \
+    { \
+      gtk_css_values_unref ((GtkCssValues *)style->NAME); \
+      style->NAME = (TYPE *)gtk_css_values_copy ((GtkCssValues *)animated->style->NAME); \
+    } \
+}
+
+DEFINE_UNSHARE (GtkCssCoreValues, core)
+DEFINE_UNSHARE (GtkCssBackgroundValues, background)
+DEFINE_UNSHARE (GtkCssBorderValues, border)
+DEFINE_UNSHARE (GtkCssIconValues, icon)
+DEFINE_UNSHARE (GtkCssOutlineValues, outline)
+DEFINE_UNSHARE (GtkCssFontValues, font)
+DEFINE_UNSHARE (GtkCssFontVariantValues, font_variant)
+DEFINE_UNSHARE (GtkCssAnimationValues, animation)
+DEFINE_UNSHARE (GtkCssTransitionValues, transition)
+DEFINE_UNSHARE (GtkCssSizeValues, size)
+DEFINE_UNSHARE (GtkCssOtherValues, other)
+
+static inline void
+gtk_css_take_value (GtkCssValue **variable,
+                    GtkCssValue  *value)
+{
+  if (*variable)
+    gtk_css_value_unref (*variable);
+  *variable = value;
+}
+
 void
-gtk_css_animated_style_set_animated_value (GtkCssAnimatedStyle *style,
+gtk_css_animated_style_set_animated_value (GtkCssAnimatedStyle *animated,
                                            guint                id,
                                            GtkCssValue         *value)
 {
+  GtkCssStyle *style = (GtkCssStyle *)animated;
+
   gtk_internal_return_if_fail (GTK_IS_CSS_ANIMATED_STYLE (style));
   gtk_internal_return_if_fail (value != NULL);
 
-  if (style->animated_values == NULL)
-    style->animated_values = g_ptr_array_new_with_free_func ((GDestroyNotify)_gtk_css_value_unref);
-  if (id >= style->animated_values->len)
-    g_ptr_array_set_size (style->animated_values, id + 1);
-
-  if (g_ptr_array_index (style->animated_values, id))
-    _gtk_css_value_unref (g_ptr_array_index (style->animated_values, id));
-
-  g_ptr_array_index (style->animated_values, id) = value;
-
+  switch (id)
+    {
+    case GTK_CSS_PROPERTY_COLOR:
+      unshare_core (animated);
+      gtk_css_take_value (&style->core->color, value);
+      break;
+    case GTK_CSS_PROPERTY_DPI:
+      unshare_core (animated);
+      gtk_css_take_value (&style->core->dpi, value);
+      break;
+    case GTK_CSS_PROPERTY_FONT_SIZE:
+      unshare_core (animated);
+      gtk_css_take_value (&style->core->font_size, value);
+      break;
+    case GTK_CSS_PROPERTY_ICON_THEME:
+      unshare_core (animated);
+      gtk_css_take_value (&style->core->icon_theme, value);
+      break;
+    case GTK_CSS_PROPERTY_ICON_PALETTE:
+      unshare_core (animated);
+      gtk_css_take_value (&style->core->icon_palette, value);
+      break;
+    case GTK_CSS_PROPERTY_BACKGROUND_COLOR:
+      unshare_background (animated);
+      gtk_css_take_value (&style->background->background_color, value);
+      break;
+    case GTK_CSS_PROPERTY_FONT_FAMILY:
+      unshare_font (animated);
+      gtk_css_take_value (&style->font->font_family, value);
+      break;
+    case GTK_CSS_PROPERTY_FONT_STYLE:
+      unshare_font (animated);
+      gtk_css_take_value (&style->font->font_style, value);
+      break;
+    case GTK_CSS_PROPERTY_FONT_WEIGHT:
+      unshare_font (animated);
+      gtk_css_take_value (&style->font->font_weight, value);
+      break;
+    case GTK_CSS_PROPERTY_FONT_STRETCH:
+      unshare_font (animated);
+      gtk_css_take_value (&style->font->font_stretch, value);
+      break;
+    case GTK_CSS_PROPERTY_LETTER_SPACING:
+      unshare_font (animated);
+      gtk_css_take_value (&style->font->letter_spacing, value);
+      break;
+    case GTK_CSS_PROPERTY_TEXT_DECORATION_LINE:
+      unshare_font_variant (animated);
+      gtk_css_take_value (&style->font_variant->text_decoration_line, value);
+      break;
+    case GTK_CSS_PROPERTY_TEXT_DECORATION_COLOR:
+      unshare_font_variant (animated);
+      gtk_css_take_value (&style->font_variant->text_decoration_color, value);
+      break;
+    case GTK_CSS_PROPERTY_TEXT_DECORATION_STYLE:
+      unshare_font_variant (animated);
+      gtk_css_take_value (&style->font_variant->text_decoration_style, value);
+      break;
+    case GTK_CSS_PROPERTY_FONT_KERNING:
+      unshare_font_variant (animated);
+      gtk_css_take_value (&style->font_variant->font_kerning, value);
+      break;
+    case GTK_CSS_PROPERTY_FONT_VARIANT_LIGATURES:
+      unshare_font_variant (animated);
+      gtk_css_take_value (&style->font_variant->font_variant_ligatures, value);
+      break;
+    case GTK_CSS_PROPERTY_FONT_VARIANT_POSITION:
+      unshare_font_variant (animated);
+      gtk_css_take_value (&style->font_variant->font_variant_position, value);
+      break;
+    case GTK_CSS_PROPERTY_FONT_VARIANT_CAPS:
+      unshare_font_variant (animated);
+      gtk_css_take_value (&style->font_variant->font_variant_caps, value);
+      break;
+    case GTK_CSS_PROPERTY_FONT_VARIANT_NUMERIC:
+      unshare_font_variant (animated);
+      gtk_css_take_value (&style->font_variant->font_variant_numeric, value);
+      break;
+    case GTK_CSS_PROPERTY_FONT_VARIANT_ALTERNATES:
+      unshare_font_variant (animated);
+      gtk_css_take_value (&style->font_variant->font_variant_alternates, value);
+      break;
+    case GTK_CSS_PROPERTY_FONT_VARIANT_EAST_ASIAN:
+      unshare_font_variant (animated);
+      gtk_css_take_value (&style->font_variant->font_variant_east_asian, value);
+      break;
+    case GTK_CSS_PROPERTY_TEXT_SHADOW:
+      unshare_font (animated);
+      gtk_css_take_value (&style->font->text_shadow, value);
+      break;
+    case GTK_CSS_PROPERTY_BOX_SHADOW:
+      unshare_background (animated);
+      gtk_css_take_value (&style->background->box_shadow, value);
+      break;
+    case GTK_CSS_PROPERTY_MARGIN_TOP:
+      unshare_size (animated);
+      gtk_css_take_value (&style->size->margin_top, value);
+      break;
+    case GTK_CSS_PROPERTY_MARGIN_LEFT:
+      unshare_size (animated);
+      gtk_css_take_value (&style->size->margin_left, value);
+      break;
+    case GTK_CSS_PROPERTY_MARGIN_BOTTOM:
+      unshare_size (animated);
+      gtk_css_take_value (&style->size->margin_bottom, value);
+      break;
+    case GTK_CSS_PROPERTY_MARGIN_RIGHT:
+      unshare_size (animated);
+      gtk_css_take_value (&style->size->margin_right, value);
+      break;
+    case GTK_CSS_PROPERTY_PADDING_TOP:
+      unshare_size (animated);
+      gtk_css_take_value (&style->size->padding_top, value);
+      break;
+    case GTK_CSS_PROPERTY_PADDING_LEFT:
+      unshare_size (animated);
+      gtk_css_take_value (&style->size->padding_left, value);
+      break;
+    case GTK_CSS_PROPERTY_PADDING_BOTTOM:
+      unshare_size (animated);
+      gtk_css_take_value (&style->size->padding_bottom, value);
+      break;
+    case GTK_CSS_PROPERTY_PADDING_RIGHT:
+      unshare_size (animated);
+      gtk_css_take_value (&style->size->padding_right, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_TOP_STYLE:
+      unshare_border (animated);
+      gtk_css_take_value (&style->border->border_top_style, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_TOP_WIDTH:
+      unshare_border (animated);
+      gtk_css_take_value (&style->border->border_top_width, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_LEFT_STYLE:
+      unshare_border (animated);
+      gtk_css_take_value (&style->border->border_left_style, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH:
+      unshare_border (animated);
+      gtk_css_take_value (&style->border->border_left_width, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_BOTTOM_STYLE:
+      unshare_border (animated);
+      gtk_css_take_value (&style->border->border_bottom_style, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_BOTTOM_WIDTH:
+      unshare_border (animated);
+      gtk_css_take_value (&style->border->border_bottom_width, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_RIGHT_STYLE:
+      unshare_border (animated);
+      gtk_css_take_value (&style->border->border_right_style, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_RIGHT_WIDTH:
+      unshare_border (animated);
+      gtk_css_take_value (&style->border->border_right_width, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_TOP_LEFT_RADIUS:
+      unshare_border (animated);
+      gtk_css_take_value (&style->border->border_top_left_radius, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_TOP_RIGHT_RADIUS:
+      unshare_border (animated);
+      gtk_css_take_value (&style->border->border_top_right_radius, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_BOTTOM_RIGHT_RADIUS:
+      unshare_border (animated);
+      gtk_css_take_value (&style->border->border_bottom_right_radius, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_BOTTOM_LEFT_RADIUS:
+      unshare_border (animated);
+      gtk_css_take_value (&style->border->border_bottom_left_radius, value);
+      break;
+    case GTK_CSS_PROPERTY_OUTLINE_STYLE:
+      unshare_outline (animated);
+      gtk_css_take_value (&style->outline->outline_style, value);
+      break;
+    case GTK_CSS_PROPERTY_OUTLINE_WIDTH:
+      unshare_outline (animated);
+      gtk_css_take_value (&style->outline->outline_width, value);
+      break;
+    case GTK_CSS_PROPERTY_OUTLINE_OFFSET:
+      unshare_outline (animated);
+      gtk_css_take_value (&style->outline->outline_offset, value);
+      break;
+    case GTK_CSS_PROPERTY_OUTLINE_TOP_LEFT_RADIUS:
+      unshare_outline (animated);
+      gtk_css_take_value (&style->outline->outline_top_left_radius, value);
+      break;
+    case GTK_CSS_PROPERTY_OUTLINE_TOP_RIGHT_RADIUS:
+      unshare_outline (animated);
+      gtk_css_take_value (&style->outline->outline_top_right_radius, value);
+      break;
+    case GTK_CSS_PROPERTY_OUTLINE_BOTTOM_RIGHT_RADIUS:
+      unshare_outline (animated);
+      gtk_css_take_value (&style->outline->outline_bottom_right_radius, value);
+      break;
+    case GTK_CSS_PROPERTY_OUTLINE_BOTTOM_LEFT_RADIUS:
+      unshare_outline (animated);
+      gtk_css_take_value (&style->outline->outline_bottom_left_radius, value);
+      break;
+    case GTK_CSS_PROPERTY_BACKGROUND_CLIP:
+      unshare_background (animated);
+      gtk_css_take_value (&style->background->background_clip, value);
+      break;
+    case GTK_CSS_PROPERTY_BACKGROUND_ORIGIN:
+      unshare_background (animated);
+      gtk_css_take_value (&style->background->background_origin, value);
+      break;
+    case GTK_CSS_PROPERTY_BACKGROUND_SIZE:
+      unshare_background (animated);
+      gtk_css_take_value (&style->background->background_size, value);
+      break;
+    case GTK_CSS_PROPERTY_BACKGROUND_POSITION:
+      unshare_background (animated);
+      gtk_css_take_value (&style->background->background_position, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_TOP_COLOR:
+      unshare_border (animated);
+      gtk_css_take_value (&style->border->border_top_color, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_RIGHT_COLOR:
+      unshare_border (animated);
+      gtk_css_take_value (&style->border->border_right_color, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_BOTTOM_COLOR:
+      unshare_border (animated);
+      gtk_css_take_value (&style->border->border_bottom_color, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_LEFT_COLOR:
+      unshare_border (animated);
+      gtk_css_take_value (&style->border->border_left_color, value);
+      break;
+    case GTK_CSS_PROPERTY_OUTLINE_COLOR:
+      unshare_outline (animated);
+      gtk_css_take_value (&style->outline->outline_color, value);
+      break;
+    case GTK_CSS_PROPERTY_BACKGROUND_REPEAT:
+      unshare_background (animated);
+      gtk_css_take_value (&style->background->background_repeat, value);
+      break;
+    case GTK_CSS_PROPERTY_BACKGROUND_IMAGE:
+      unshare_background (animated);
+      gtk_css_take_value (&style->background->background_image, value);
+      break;
+    case GTK_CSS_PROPERTY_BACKGROUND_BLEND_MODE:
+      unshare_background (animated);
+      gtk_css_take_value (&style->background->background_blend_mode, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_IMAGE_SOURCE:
+      unshare_border (animated);
+      gtk_css_take_value (&style->border->border_image_source, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_IMAGE_REPEAT:
+      unshare_border (animated);
+      gtk_css_take_value (&style->border->border_image_repeat, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_IMAGE_SLICE:
+      unshare_border (animated);
+      gtk_css_take_value (&style->border->border_image_slice, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_IMAGE_WIDTH:
+      unshare_border (animated);
+      gtk_css_take_value (&style->border->border_image_width, value);
+      break;
+    case GTK_CSS_PROPERTY_ICON_SOURCE:
+      unshare_other (animated);
+      gtk_css_take_value (&style->other->icon_source, value);
+      break;
+    case GTK_CSS_PROPERTY_ICON_SIZE:
+      unshare_icon (animated);
+      gtk_css_take_value (&style->icon->icon_size, value);
+      break;
+    case GTK_CSS_PROPERTY_ICON_SHADOW:
+      unshare_icon (animated);
+      gtk_css_take_value (&style->icon->icon_shadow, value);
+      break;
+    case GTK_CSS_PROPERTY_ICON_STYLE:
+      unshare_icon (animated);
+      gtk_css_take_value (&style->icon->icon_style, value);
+      break;
+    case GTK_CSS_PROPERTY_ICON_TRANSFORM:
+      unshare_other (animated);
+      gtk_css_take_value (&style->other->icon_transform, value);
+      break;
+    case GTK_CSS_PROPERTY_ICON_FILTER:
+      unshare_other (animated);
+      gtk_css_take_value (&style->other->icon_filter, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_SPACING:
+      unshare_size (animated);
+      gtk_css_take_value (&style->size->border_spacing, value);
+      break;
+    case GTK_CSS_PROPERTY_TRANSFORM:
+      unshare_other (animated);
+      gtk_css_take_value (&style->other->transform, value);
+      break;
+    case GTK_CSS_PROPERTY_MIN_WIDTH:
+      unshare_size (animated);
+      gtk_css_take_value (&style->size->min_width, value);
+      break;
+    case GTK_CSS_PROPERTY_MIN_HEIGHT:
+      unshare_size (animated);
+      gtk_css_take_value (&style->size->min_height, value);
+      break;
+    case GTK_CSS_PROPERTY_TRANSITION_PROPERTY:
+      unshare_transition (animated);
+      gtk_css_take_value (&style->transition->transition_property, value);
+      break;
+    case GTK_CSS_PROPERTY_TRANSITION_DURATION:
+      unshare_transition (animated);
+      gtk_css_take_value (&style->transition->transition_duration, value);
+      break;
+    case GTK_CSS_PROPERTY_TRANSITION_TIMING_FUNCTION:
+      unshare_transition (animated);
+      gtk_css_take_value (&style->transition->transition_timing_function, value);
+      break;
+    case GTK_CSS_PROPERTY_TRANSITION_DELAY:
+      unshare_transition (animated);
+      gtk_css_take_value (&style->transition->transition_delay, value);
+      break;
+    case GTK_CSS_PROPERTY_ANIMATION_NAME:
+      unshare_animation (animated);
+      gtk_css_take_value (&style->animation->animation_name, value);
+      break;
+    case GTK_CSS_PROPERTY_ANIMATION_DURATION:
+      unshare_animation (animated);
+      gtk_css_take_value (&style->animation->animation_duration, value);
+      break;
+    case GTK_CSS_PROPERTY_ANIMATION_TIMING_FUNCTION:
+      unshare_animation (animated);
+      gtk_css_take_value (&style->animation->animation_timing_function, value);
+      break;
+    case GTK_CSS_PROPERTY_ANIMATION_ITERATION_COUNT:
+      unshare_animation (animated);
+      gtk_css_take_value (&style->animation->animation_iteration_count, value);
+      break;
+    case GTK_CSS_PROPERTY_ANIMATION_DIRECTION:
+      unshare_animation (animated);
+      gtk_css_take_value (&style->animation->animation_direction, value);
+      break;
+    case GTK_CSS_PROPERTY_ANIMATION_PLAY_STATE:
+      unshare_animation (animated);
+      gtk_css_take_value (&style->animation->animation_play_state, value);
+      break;
+    case GTK_CSS_PROPERTY_ANIMATION_DELAY:
+      unshare_animation (animated);
+      gtk_css_take_value (&style->animation->animation_delay, value);
+      break;
+    case GTK_CSS_PROPERTY_ANIMATION_FILL_MODE:
+      unshare_animation (animated);
+      gtk_css_take_value (&style->animation->animation_fill_mode, value);
+      break;
+    case GTK_CSS_PROPERTY_OPACITY:
+      unshare_other (animated);
+      gtk_css_take_value (&style->other->opacity, value);
+      break;
+    case GTK_CSS_PROPERTY_FILTER:
+      unshare_other (animated);
+      gtk_css_take_value (&style->other->filter, value);
+      break;
+    case GTK_CSS_PROPERTY_CARET_COLOR:
+      unshare_font (animated);
+      gtk_css_take_value (&style->font->caret_color, value);
+      break;
+    case GTK_CSS_PROPERTY_SECONDARY_CARET_COLOR:
+      unshare_font (animated);
+      gtk_css_take_value (&style->font->secondary_caret_color, value);
+      break;
+    case GTK_CSS_PROPERTY_FONT_FEATURE_SETTINGS:
+      unshare_font (animated);
+      gtk_css_take_value (&style->font->font_feature_settings, value);
+      break;
+    case GTK_CSS_PROPERTY_FONT_VARIATION_SETTINGS:
+      unshare_font (animated);
+      gtk_css_take_value (&style->font->font_variation_settings, value);
+      break;
+
+    default:
+      g_assert_not_reached ();
+      break;
+    }
 }
 
 GtkCssValue *
@@ -489,6 +876,7 @@ gtk_css_animated_style_new (GtkCssStyle      *base_style,
                             GtkCssStyle      *previous_style)
 {
   GtkCssAnimatedStyle *result;
+  GtkCssStyle *style;
   GPtrArray *animations = NULL;
 
   gtk_internal_return_val_if_fail (GTK_IS_CSS_STYLE (base_style), NULL);
@@ -515,6 +903,19 @@ gtk_css_animated_style_new (GtkCssStyle      *base_style,
   result->n_animations = animations->len;
   result->animations = g_ptr_array_free (animations, FALSE);
 
+  style = (GtkCssStyle *)result;
+  style->core = (GtkCssCoreValues *)gtk_css_values_ref ((GtkCssValues *)base_style->core);
+  style->background = (GtkCssBackgroundValues *)gtk_css_values_ref ((GtkCssValues *)base_style->background);
+  style->border = (GtkCssBorderValues *)gtk_css_values_ref ((GtkCssValues *)base_style->border);
+  style->icon = (GtkCssIconValues *)gtk_css_values_ref ((GtkCssValues *)base_style->icon);
+  style->outline = (GtkCssOutlineValues *)gtk_css_values_ref ((GtkCssValues *)base_style->outline);
+  style->font = (GtkCssFontValues *)gtk_css_values_ref ((GtkCssValues *)base_style->font);
+  style->font_variant = (GtkCssFontVariantValues *)gtk_css_values_ref ((GtkCssValues 
*)base_style->font_variant);
+  style->animation = (GtkCssAnimationValues *)gtk_css_values_ref ((GtkCssValues *)base_style->animation);
+  style->transition = (GtkCssTransitionValues *)gtk_css_values_ref ((GtkCssValues *)base_style->transition);
+  style->size = (GtkCssSizeValues *)gtk_css_values_ref ((GtkCssValues *)base_style->size);
+  style->other = (GtkCssOtherValues *)gtk_css_values_ref ((GtkCssValues *)base_style->other);
+
   gtk_css_animated_style_apply_animations (result);
 
   return GTK_CSS_STYLE (result);
@@ -522,10 +923,11 @@ gtk_css_animated_style_new (GtkCssStyle      *base_style,
 
 GtkCssStyle *
 gtk_css_animated_style_new_advance (GtkCssAnimatedStyle *source,
-                                    GtkCssStyle         *base,
+                                    GtkCssStyle         *base_style,
                                     gint64               timestamp)
 {
   GtkCssAnimatedStyle *result;
+  GtkCssStyle *style;
   GPtrArray *animations;
   guint i;
 
@@ -557,11 +959,24 @@ gtk_css_animated_style_new_advance (GtkCssAnimatedStyle *source,
 
   result = g_object_new (GTK_TYPE_CSS_ANIMATED_STYLE, NULL);
 
-  result->style = g_object_ref (base);
+  result->style = g_object_ref (base_style);
   result->current_time = timestamp;
   result->n_animations = animations->len;
   result->animations = g_ptr_array_free (animations, FALSE);
 
+  style = (GtkCssStyle *)result;
+  style->core = (GtkCssCoreValues *)gtk_css_values_ref ((GtkCssValues *)base_style->core);
+  style->background = (GtkCssBackgroundValues *)gtk_css_values_ref ((GtkCssValues *)base_style->background);
+  style->border = (GtkCssBorderValues *)gtk_css_values_ref ((GtkCssValues *)base_style->border);
+  style->icon = (GtkCssIconValues *)gtk_css_values_ref ((GtkCssValues *)base_style->icon);
+  style->outline = (GtkCssOutlineValues *)gtk_css_values_ref ((GtkCssValues *)base_style->outline);
+  style->font = (GtkCssFontValues *)gtk_css_values_ref ((GtkCssValues *)base_style->font);
+  style->font_variant = (GtkCssFontVariantValues *)gtk_css_values_ref ((GtkCssValues 
*)base_style->font_variant);
+  style->animation = (GtkCssAnimationValues *)gtk_css_values_ref ((GtkCssValues *)base_style->animation);
+  style->transition = (GtkCssTransitionValues *)gtk_css_values_ref ((GtkCssValues *)base_style->transition);
+  style->size = (GtkCssSizeValues *)gtk_css_values_ref ((GtkCssValues *)base_style->size);
+  style->other = (GtkCssOtherValues *)gtk_css_values_ref ((GtkCssValues *)base_style->other);
+
   gtk_css_animated_style_apply_animations (result);
 
   return GTK_CSS_STYLE (result);
diff --git a/gtk/gtkcssanimatedstyleprivate.h b/gtk/gtkcssanimatedstyleprivate.h
index 7ce2210a27..90e1af83bf 100644
--- a/gtk/gtkcssanimatedstyleprivate.h
+++ b/gtk/gtkcssanimatedstyleprivate.h
@@ -40,7 +40,6 @@ struct _GtkCssAnimatedStyle
 
   GtkCssStyle           *style;                /* the style if we weren't animating */
 
-  GPtrArray             *animated_values;      /* NULL or array of animated values/NULL if not animated */
   gint64                 current_time;         /* the current time in our world */
   gpointer              *animations;           /* GtkStyleAnimation**, least important one first */
   guint                  n_animations;
diff --git a/gtk/gtkcsslookup.c b/gtk/gtkcsslookup.c
index 8b0c33b0df..704de1560b 100644
--- a/gtk/gtkcsslookup.c
+++ b/gtk/gtkcsslookup.c
@@ -28,11 +28,14 @@ void
 _gtk_css_lookup_init (GtkCssLookup     *lookup)
 {
   memset (lookup, 0, sizeof (*lookup));
+
+  lookup->set_values = _gtk_bitmask_new ();
 }
 
 void
 _gtk_css_lookup_destroy (GtkCssLookup *lookup)
 {
+  _gtk_bitmask_free (lookup->set_values);
 }
 
 gboolean
@@ -41,7 +44,7 @@ _gtk_css_lookup_is_missing (const GtkCssLookup *lookup,
 {
   gtk_internal_return_val_if_fail (lookup != NULL, FALSE);
 
-  return lookup->values[id].value == NULL;
+  return !_gtk_bitmask_get (lookup->set_values, id);
 }
 
 /**
@@ -69,40 +72,5 @@ _gtk_css_lookup_set (GtkCssLookup  *lookup,
 
   lookup->values[id].value = value;
   lookup->values[id].section = section;
-}
-
-/**
- * _gtk_css_lookup_resolve:
- * @lookup: the lookup
- * @context: the context the values are resolved for
- * @values: a new #GtkCssStyle to be filled with the new properties
- *
- * Resolves the current lookup into a styleproperties object. This is done
- * by converting from the “winning declaration” to the “computed value”.
- *
- * XXX: This bypasses the notion of “specified value”. If this ever becomes
- * an issue, go fix it.
- **/
-void
-_gtk_css_lookup_resolve (GtkCssLookup      *lookup,
-                         GtkStyleProvider  *provider,
-                         GtkCssStaticStyle *style,
-                         GtkCssStyle       *parent_style)
-{
-  guint i;
-
-  gtk_internal_return_if_fail (lookup != NULL);
-  gtk_internal_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
-  gtk_internal_return_if_fail (GTK_IS_CSS_STATIC_STYLE (style));
-  gtk_internal_return_if_fail (parent_style == NULL || GTK_IS_CSS_STYLE (parent_style));
-
-  for (i = 0; i < GTK_CSS_PROPERTY_N_PROPERTIES; i++)
-    {
-      gtk_css_static_style_compute_value (style,
-                                          provider,
-                                          parent_style,
-                                          i,
-                                          lookup->values[i].value,
-                                          lookup->values[i].section);
-    }
+  lookup->set_values = _gtk_bitmask_set (lookup->set_values, id, TRUE);
 }
diff --git a/gtk/gtkcsslookupprivate.h b/gtk/gtkcsslookupprivate.h
index ef29c4e9b3..b433264c55 100644
--- a/gtk/gtkcsslookupprivate.h
+++ b/gtk/gtkcsslookupprivate.h
@@ -36,6 +36,7 @@ typedef struct {
 } GtkCssLookupValue;
 
 struct _GtkCssLookup {
+  GtkBitmask *set_values;
   GtkCssLookupValue  values[GTK_CSS_PROPERTY_N_PROPERTIES];
 };
 
@@ -47,10 +48,12 @@ void                    _gtk_css_lookup_set                     (GtkCssLookup
                                                                  guint                       id,
                                                                  GtkCssSection              *section,
                                                                  GtkCssValue                *value);
-void                    _gtk_css_lookup_resolve                 (GtkCssLookup               *lookup,
-                                                                 GtkStyleProvider           *provider,
-                                                                 GtkCssStaticStyle          *style,
-                                                                 GtkCssStyle                *parent_style);
+
+static inline const GtkBitmask *
+_gtk_css_lookup_get_set_values (const GtkCssLookup *lookup)
+{
+  return lookup->set_values;
+}
 
 G_END_DECLS
 
diff --git a/gtk/gtkcssstaticstyle.c b/gtk/gtkcssstaticstyle.c
index 6666128036..da349e0534 100644
--- a/gtk/gtkcssstaticstyle.c
+++ b/gtk/gtkcssstaticstyle.c
@@ -39,18 +39,245 @@
 #include "gtkstyleproviderprivate.h"
 #include "gtkcssdimensionvalueprivate.h"
 
-G_DEFINE_TYPE (GtkCssStaticStyle, gtk_css_static_style, GTK_TYPE_CSS_STYLE)
+static void gtk_css_static_style_compute_value (GtkCssStaticStyle *style,
+                                                GtkStyleProvider  *provider,
+                                                GtkCssStyle       *parent_style,
+                                                guint              id,
+                                                GtkCssValue       *specified,
+                                                GtkCssSection     *section);
+
+static int core_props[] = {
+  GTK_CSS_PROPERTY_COLOR,
+  GTK_CSS_PROPERTY_DPI,
+  GTK_CSS_PROPERTY_FONT_SIZE,
+  GTK_CSS_PROPERTY_ICON_THEME,
+  GTK_CSS_PROPERTY_ICON_PALETTE
+};
+
+static int background_props[] = {
+  GTK_CSS_PROPERTY_BACKGROUND_COLOR,
+  GTK_CSS_PROPERTY_BOX_SHADOW,
+  GTK_CSS_PROPERTY_BACKGROUND_CLIP,
+  GTK_CSS_PROPERTY_BACKGROUND_ORIGIN,
+  GTK_CSS_PROPERTY_BACKGROUND_SIZE,
+  GTK_CSS_PROPERTY_BACKGROUND_POSITION,
+  GTK_CSS_PROPERTY_BACKGROUND_REPEAT,
+  GTK_CSS_PROPERTY_BACKGROUND_IMAGE,
+  GTK_CSS_PROPERTY_BACKGROUND_BLEND_MODE
+};
+
+static int border_props[] = {
+  GTK_CSS_PROPERTY_BORDER_TOP_STYLE,
+  GTK_CSS_PROPERTY_BORDER_TOP_WIDTH,
+  GTK_CSS_PROPERTY_BORDER_LEFT_STYLE,
+  GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH,
+  GTK_CSS_PROPERTY_BORDER_BOTTOM_STYLE,
+  GTK_CSS_PROPERTY_BORDER_BOTTOM_WIDTH,
+  GTK_CSS_PROPERTY_BORDER_RIGHT_STYLE,
+  GTK_CSS_PROPERTY_BORDER_RIGHT_WIDTH,
+  GTK_CSS_PROPERTY_BORDER_TOP_LEFT_RADIUS,
+  GTK_CSS_PROPERTY_BORDER_TOP_RIGHT_RADIUS,
+  GTK_CSS_PROPERTY_BORDER_BOTTOM_RIGHT_RADIUS,
+  GTK_CSS_PROPERTY_BORDER_BOTTOM_LEFT_RADIUS,
+  GTK_CSS_PROPERTY_BORDER_TOP_COLOR,
+  GTK_CSS_PROPERTY_BORDER_RIGHT_COLOR,
+  GTK_CSS_PROPERTY_BORDER_BOTTOM_COLOR,
+  GTK_CSS_PROPERTY_BORDER_LEFT_COLOR,
+  GTK_CSS_PROPERTY_BORDER_IMAGE_SOURCE,
+  GTK_CSS_PROPERTY_BORDER_IMAGE_REPEAT,
+  GTK_CSS_PROPERTY_BORDER_IMAGE_SLICE,
+  GTK_CSS_PROPERTY_BORDER_IMAGE_WIDTH
+};
+
+static int icon_props[] = {
+  GTK_CSS_PROPERTY_ICON_SIZE,
+  GTK_CSS_PROPERTY_ICON_SHADOW,
+  GTK_CSS_PROPERTY_ICON_STYLE,
+};
+
+static int outline_props[] = {
+  GTK_CSS_PROPERTY_OUTLINE_STYLE,
+  GTK_CSS_PROPERTY_OUTLINE_WIDTH,
+  GTK_CSS_PROPERTY_OUTLINE_OFFSET,
+  GTK_CSS_PROPERTY_OUTLINE_TOP_LEFT_RADIUS,
+  GTK_CSS_PROPERTY_OUTLINE_TOP_RIGHT_RADIUS,
+  GTK_CSS_PROPERTY_OUTLINE_BOTTOM_RIGHT_RADIUS,
+  GTK_CSS_PROPERTY_OUTLINE_BOTTOM_LEFT_RADIUS,
+  GTK_CSS_PROPERTY_OUTLINE_COLOR,
+};
+
+static int font_props[] = {
+  GTK_CSS_PROPERTY_FONT_FAMILY,
+  GTK_CSS_PROPERTY_FONT_STYLE,
+  GTK_CSS_PROPERTY_FONT_WEIGHT,
+  GTK_CSS_PROPERTY_FONT_STRETCH,
+  GTK_CSS_PROPERTY_LETTER_SPACING,
+  GTK_CSS_PROPERTY_TEXT_SHADOW,  
+  GTK_CSS_PROPERTY_CARET_COLOR,
+  GTK_CSS_PROPERTY_SECONDARY_CARET_COLOR,
+  GTK_CSS_PROPERTY_FONT_FEATURE_SETTINGS,
+  GTK_CSS_PROPERTY_FONT_VARIATION_SETTINGS,
+};
+static int font_variant_props[] = {
+  GTK_CSS_PROPERTY_TEXT_DECORATION_LINE,
+  GTK_CSS_PROPERTY_TEXT_DECORATION_COLOR,
+  GTK_CSS_PROPERTY_TEXT_DECORATION_STYLE,
+  GTK_CSS_PROPERTY_FONT_KERNING,
+  GTK_CSS_PROPERTY_FONT_VARIANT_LIGATURES,
+  GTK_CSS_PROPERTY_FONT_VARIANT_POSITION,
+  GTK_CSS_PROPERTY_FONT_VARIANT_CAPS,
+  GTK_CSS_PROPERTY_FONT_VARIANT_NUMERIC,
+  GTK_CSS_PROPERTY_FONT_VARIANT_ALTERNATES,
+  GTK_CSS_PROPERTY_FONT_VARIANT_EAST_ASIAN,
+};
+
+static int animation_props[] = {
+  GTK_CSS_PROPERTY_ANIMATION_NAME,
+  GTK_CSS_PROPERTY_ANIMATION_DURATION,
+  GTK_CSS_PROPERTY_ANIMATION_TIMING_FUNCTION,
+  GTK_CSS_PROPERTY_ANIMATION_ITERATION_COUNT,
+  GTK_CSS_PROPERTY_ANIMATION_DIRECTION,
+  GTK_CSS_PROPERTY_ANIMATION_PLAY_STATE,
+  GTK_CSS_PROPERTY_ANIMATION_DELAY,
+  GTK_CSS_PROPERTY_ANIMATION_FILL_MODE,
+};
 
-static GtkCssValue *
-gtk_css_static_style_get_value (GtkCssStyle *style,
-                                guint        id)
+static int transition_props[] = {
+  GTK_CSS_PROPERTY_TRANSITION_PROPERTY,
+  GTK_CSS_PROPERTY_TRANSITION_DURATION,
+  GTK_CSS_PROPERTY_TRANSITION_TIMING_FUNCTION,
+  GTK_CSS_PROPERTY_TRANSITION_DELAY,
+};
+
+static int size_props[] = {
+  GTK_CSS_PROPERTY_MARGIN_TOP,
+  GTK_CSS_PROPERTY_MARGIN_LEFT,
+  GTK_CSS_PROPERTY_MARGIN_BOTTOM,
+  GTK_CSS_PROPERTY_MARGIN_RIGHT,
+  GTK_CSS_PROPERTY_PADDING_TOP,
+  GTK_CSS_PROPERTY_PADDING_LEFT,
+  GTK_CSS_PROPERTY_PADDING_BOTTOM,
+  GTK_CSS_PROPERTY_PADDING_RIGHT,
+  GTK_CSS_PROPERTY_BORDER_SPACING,
+  GTK_CSS_PROPERTY_MIN_WIDTH,
+  GTK_CSS_PROPERTY_MIN_HEIGHT,
+};
+
+static int other_props[] = {
+  GTK_CSS_PROPERTY_ICON_SOURCE,
+  GTK_CSS_PROPERTY_ICON_TRANSFORM,
+  GTK_CSS_PROPERTY_ICON_FILTER,
+  GTK_CSS_PROPERTY_TRANSFORM,
+  GTK_CSS_PROPERTY_OPACITY,
+  GTK_CSS_PROPERTY_FILTER,
+};
+
+#define DEFINE_VALUES(ENUM, TYPE, NAME) \
+static inline void \
+gtk_css_ ## NAME ## _values_new_compute (GtkCssStaticStyle *sstyle, \
+                                         GtkStyleProvider *provider, \
+                                         GtkCssStyle *parent_style, \
+                                         GtkCssLookup *lookup) \
+{ \
+  GtkCssStyle *style = (GtkCssStyle *)sstyle; \
+  int i; \
+\
+  style->NAME = (GtkCss ## TYPE ## Values *)gtk_css_values_new (GTK_CSS_ ## ENUM ## _VALUES); \
+\
+  for (i = 0; i < G_N_ELEMENTS (NAME ## _props); i++) \
+    { \
+      guint id = NAME ## _props[i]; \
+      gtk_css_static_style_compute_value (sstyle, \
+                                          provider, \
+                                          parent_style, \
+                                          id, \
+                                          lookup->values[id].value, \
+                                          lookup->values[id].section); \
+    } \
+} \
+\
+static GtkBitmask * gtk_css_ ## NAME ## _values_mask; \
+static GtkCssValues * gtk_css_ ## NAME ## _initial_values; \
+\
+static GtkCssValues * gtk_css_ ## NAME ## _create_initial_values (void); \
+\
+static void \
+gtk_css_ ## NAME ## _values_init (void) \
+{ \
+  int i; \
+  gtk_css_ ## NAME ## _values_mask = _gtk_bitmask_new (); \
+  for (i = 0; i < G_N_ELEMENTS(NAME ## _props); i++) \
+    { \
+      guint id = NAME ## _props[i]; \
+      gtk_css_ ## NAME ## _values_mask = _gtk_bitmask_set (gtk_css_ ## NAME ## _values_mask, id, TRUE); \
+    } \
+\
+  gtk_css_ ## NAME ## _initial_values = gtk_css_ ## NAME ## _create_initial_values (); \
+} \
+\
+static inline gboolean \
+gtk_css_ ## NAME ## _values_unset (const GtkCssLookup *lookup) \
+{ \
+  const GtkBitmask *set_values = _gtk_css_lookup_get_set_values (lookup); \
+  return !_gtk_bitmask_intersects (set_values, gtk_css_ ## NAME ## _values_mask); \
+}
+
+DEFINE_VALUES (CORE, Core, core)
+DEFINE_VALUES (BACKGROUND, Background, background)
+DEFINE_VALUES (BORDER, Border, border)
+DEFINE_VALUES (ICON, Icon, icon)
+DEFINE_VALUES (OUTLINE, Outline, outline)
+DEFINE_VALUES (FONT, Font, font)
+DEFINE_VALUES (FONT_VARIANT, FontVariant, font_variant)
+DEFINE_VALUES (ANIMATION, Animation, animation)
+DEFINE_VALUES (TRANSITION, Transition, transition)
+DEFINE_VALUES (SIZE, Size, size)
+DEFINE_VALUES (OTHER, Other, other)
+
+#define VERIFY_MASK(NAME) \
+  { \
+    GtkBitmask *copy; \
+    copy = _gtk_bitmask_intersect (_gtk_bitmask_copy (gtk_css_ ## NAME ## _values_mask), all); \
+    g_assert (_gtk_bitmask_equals (copy, gtk_css_ ## NAME ## _values_mask)); \
+    _gtk_bitmask_free (copy); \
+  } \
+ all = _gtk_bitmask_subtract (all, gtk_css_ ## NAME ## _values_mask);
+  
+/* Verify that every style property is present in one group, and none
+ * is present in more than one group.
+ */
+static void
+verify_style_groups (void)
 {
-  /* This is called a lot, so we avoid a dynamic type check here */
-  GtkCssStaticStyle *sstyle = (GtkCssStaticStyle *) style;
+  GtkBitmask *all;
+  guint id;
 
-  return sstyle->values[id];
+  all = _gtk_bitmask_new ();
+
+  for (id = 0; id < GTK_CSS_PROPERTY_N_PROPERTIES; id++)
+    all = _gtk_bitmask_set (all, id, TRUE);
+
+  VERIFY_MASK (core);
+  VERIFY_MASK (background);
+  VERIFY_MASK (border);
+  VERIFY_MASK (icon);
+  VERIFY_MASK (outline);
+  VERIFY_MASK (font);
+  VERIFY_MASK (font_variant);
+  VERIFY_MASK (animation);
+  VERIFY_MASK (transition);
+  VERIFY_MASK (size);
+  VERIFY_MASK (other);
+
+  g_assert (_gtk_bitmask_is_empty (all));
+
+  _gtk_bitmask_free (all);
 }
 
+#undef VERIFY_MASK
+
+G_DEFINE_TYPE (GtkCssStaticStyle, gtk_css_static_style, GTK_TYPE_CSS_STYLE)
+
 static GtkCssSection *
 gtk_css_static_style_get_section (GtkCssStyle *style,
                                     guint        id)
@@ -68,13 +295,7 @@ static void
 gtk_css_static_style_dispose (GObject *object)
 {
   GtkCssStaticStyle *style = GTK_CSS_STATIC_STYLE (object);
-  guint i;
 
-  for (i = 0; i < GTK_CSS_PROPERTY_N_PROPERTIES; i++)
-    {
-      if (style->values[i])
-        _gtk_css_value_unref (style->values[i]);
-    }
   if (style->sections)
     {
       g_ptr_array_unref (style->sections);
@@ -98,9 +319,22 @@ gtk_css_static_style_class_init (GtkCssStaticStyleClass *klass)
 
   object_class->dispose = gtk_css_static_style_dispose;
 
-  style_class->get_value = gtk_css_static_style_get_value;
   style_class->get_section = gtk_css_static_style_get_section;
   style_class->get_static_style = gtk_css_static_style_get_static_style;
+
+  gtk_css_core_values_init ();
+  gtk_css_background_values_init ();
+  gtk_css_border_values_init ();
+  gtk_css_icon_values_init ();
+  gtk_css_outline_values_init ();
+  gtk_css_font_values_init ();
+  gtk_css_font_variant_values_init ();
+  gtk_css_animation_values_init ();
+  gtk_css_transition_values_init ();
+  gtk_css_size_values_init ();
+  gtk_css_other_values_init ();
+
+  verify_style_groups ();
 }
 
 static void
@@ -115,31 +349,326 @@ maybe_unref_section (gpointer section)
     gtk_css_section_unref (section);
 }
 
+static inline void
+gtk_css_take_value (GtkCssValue **variable,
+                    GtkCssValue  *value)
+{
+  if (*variable)
+    gtk_css_value_unref (*variable);
+  *variable = value;
+}
+
 static void
-gtk_css_static_style_set_value (GtkCssStaticStyle *style,
+gtk_css_static_style_set_value (GtkCssStaticStyle *sstyle,
                                 guint              id,
                                 GtkCssValue       *value,
                                 GtkCssSection     *section)
 {
-  if (style->values[id])
-    _gtk_css_value_unref (style->values[id]);
+  GtkCssStyle *style = (GtkCssStyle *)sstyle;
 
-  style->values[id] = value;
+  switch (id)
+    {
+    case GTK_CSS_PROPERTY_COLOR:
+      gtk_css_take_value (&style->core->color, value);
+      break;
+    case GTK_CSS_PROPERTY_DPI:
+      gtk_css_take_value (&style->core->dpi, value);
+      break;
+    case GTK_CSS_PROPERTY_FONT_SIZE:
+      gtk_css_take_value (&style->core->font_size, value);
+      break;
+    case GTK_CSS_PROPERTY_ICON_THEME:
+      gtk_css_take_value (&style->core->icon_theme, value);
+      break;
+    case GTK_CSS_PROPERTY_ICON_PALETTE:
+      gtk_css_take_value (&style->core->icon_palette, value);
+      break;
+    case GTK_CSS_PROPERTY_BACKGROUND_COLOR:
+      gtk_css_take_value (&style->background->background_color, value);
+      break;
+    case GTK_CSS_PROPERTY_FONT_FAMILY:
+      gtk_css_take_value (&style->font->font_family, value);
+      break;
+    case GTK_CSS_PROPERTY_FONT_STYLE:
+      gtk_css_take_value (&style->font->font_style, value);
+      break;
+    case GTK_CSS_PROPERTY_FONT_WEIGHT:
+      gtk_css_take_value (&style->font->font_weight, value);
+      break;
+    case GTK_CSS_PROPERTY_FONT_STRETCH:
+      gtk_css_take_value (&style->font->font_stretch, value);
+      break;
+    case GTK_CSS_PROPERTY_LETTER_SPACING:
+      gtk_css_take_value (&style->font->letter_spacing, value);
+      break;
+    case GTK_CSS_PROPERTY_TEXT_DECORATION_LINE:
+      gtk_css_take_value (&style->font_variant->text_decoration_line, value);
+      break;
+    case GTK_CSS_PROPERTY_TEXT_DECORATION_COLOR:
+      gtk_css_take_value (&style->font_variant->text_decoration_color, value);
+      break;
+    case GTK_CSS_PROPERTY_TEXT_DECORATION_STYLE:
+      gtk_css_take_value (&style->font_variant->text_decoration_style, value);
+      break;
+    case GTK_CSS_PROPERTY_FONT_KERNING:
+      gtk_css_take_value (&style->font_variant->font_kerning, value);
+      break;
+    case GTK_CSS_PROPERTY_FONT_VARIANT_LIGATURES:
+      gtk_css_take_value (&style->font_variant->font_variant_ligatures, value);
+      break;
+    case GTK_CSS_PROPERTY_FONT_VARIANT_POSITION:
+      gtk_css_take_value (&style->font_variant->font_variant_position, value);
+      break;
+    case GTK_CSS_PROPERTY_FONT_VARIANT_CAPS:
+      gtk_css_take_value (&style->font_variant->font_variant_caps, value);
+      break;
+    case GTK_CSS_PROPERTY_FONT_VARIANT_NUMERIC:
+      gtk_css_take_value (&style->font_variant->font_variant_numeric, value);
+      break;
+    case GTK_CSS_PROPERTY_FONT_VARIANT_ALTERNATES:
+      gtk_css_take_value (&style->font_variant->font_variant_alternates, value);
+      break;
+    case GTK_CSS_PROPERTY_FONT_VARIANT_EAST_ASIAN:
+      gtk_css_take_value (&style->font_variant->font_variant_east_asian, value);
+      break;
+    case GTK_CSS_PROPERTY_TEXT_SHADOW:
+      gtk_css_take_value (&style->font->text_shadow, value);
+      break;
+    case GTK_CSS_PROPERTY_BOX_SHADOW:
+      gtk_css_take_value (&style->background->box_shadow, value);
+      break;
+    case GTK_CSS_PROPERTY_MARGIN_TOP:
+      gtk_css_take_value (&style->size->margin_top, value);
+      break;
+    case GTK_CSS_PROPERTY_MARGIN_LEFT:
+      gtk_css_take_value (&style->size->margin_left, value);
+      break;
+    case GTK_CSS_PROPERTY_MARGIN_BOTTOM:
+      gtk_css_take_value (&style->size->margin_bottom, value);
+      break;
+    case GTK_CSS_PROPERTY_MARGIN_RIGHT:
+      gtk_css_take_value (&style->size->margin_right, value);
+      break;
+    case GTK_CSS_PROPERTY_PADDING_TOP:
+      gtk_css_take_value (&style->size->padding_top, value);
+      break;
+    case GTK_CSS_PROPERTY_PADDING_LEFT:
+      gtk_css_take_value (&style->size->padding_left, value);
+      break;
+    case GTK_CSS_PROPERTY_PADDING_BOTTOM:
+      gtk_css_take_value (&style->size->padding_bottom, value);
+      break;
+    case GTK_CSS_PROPERTY_PADDING_RIGHT:
+      gtk_css_take_value (&style->size->padding_right, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_TOP_STYLE:
+      gtk_css_take_value (&style->border->border_top_style, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_TOP_WIDTH:
+      gtk_css_take_value (&style->border->border_top_width, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_LEFT_STYLE:
+      gtk_css_take_value (&style->border->border_left_style, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH:
+      gtk_css_take_value (&style->border->border_left_width, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_BOTTOM_STYLE:
+      gtk_css_take_value (&style->border->border_bottom_style, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_BOTTOM_WIDTH:
+      gtk_css_take_value (&style->border->border_bottom_width, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_RIGHT_STYLE:
+      gtk_css_take_value (&style->border->border_right_style, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_RIGHT_WIDTH:
+      gtk_css_take_value (&style->border->border_right_width, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_TOP_LEFT_RADIUS:
+      gtk_css_take_value (&style->border->border_top_left_radius, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_TOP_RIGHT_RADIUS:
+      gtk_css_take_value (&style->border->border_top_right_radius, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_BOTTOM_RIGHT_RADIUS:
+      gtk_css_take_value (&style->border->border_bottom_right_radius, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_BOTTOM_LEFT_RADIUS:
+      gtk_css_take_value (&style->border->border_bottom_left_radius, value);
+      break;
+    case GTK_CSS_PROPERTY_OUTLINE_STYLE:
+      gtk_css_take_value (&style->outline->outline_style, value);
+      break;
+    case GTK_CSS_PROPERTY_OUTLINE_WIDTH:
+      gtk_css_take_value (&style->outline->outline_width, value);
+      break;
+    case GTK_CSS_PROPERTY_OUTLINE_OFFSET:
+      gtk_css_take_value (&style->outline->outline_offset, value);
+      break;
+    case GTK_CSS_PROPERTY_OUTLINE_TOP_LEFT_RADIUS:
+      gtk_css_take_value (&style->outline->outline_top_left_radius, value);
+      break;
+    case GTK_CSS_PROPERTY_OUTLINE_TOP_RIGHT_RADIUS:
+      gtk_css_take_value (&style->outline->outline_top_right_radius, value);
+      break;
+    case GTK_CSS_PROPERTY_OUTLINE_BOTTOM_RIGHT_RADIUS:
+      gtk_css_take_value (&style->outline->outline_bottom_right_radius, value);
+      break;
+    case GTK_CSS_PROPERTY_OUTLINE_BOTTOM_LEFT_RADIUS:
+      gtk_css_take_value (&style->outline->outline_bottom_left_radius, value);
+      break;
+    case GTK_CSS_PROPERTY_BACKGROUND_CLIP:
+      gtk_css_take_value (&style->background->background_clip, value);
+      break;
+    case GTK_CSS_PROPERTY_BACKGROUND_ORIGIN:
+      gtk_css_take_value (&style->background->background_origin, value);
+      break;
+    case GTK_CSS_PROPERTY_BACKGROUND_SIZE:
+      gtk_css_take_value (&style->background->background_size, value);
+      break;
+    case GTK_CSS_PROPERTY_BACKGROUND_POSITION:
+      gtk_css_take_value (&style->background->background_position, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_TOP_COLOR:
+      gtk_css_take_value (&style->border->border_top_color, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_RIGHT_COLOR:
+      gtk_css_take_value (&style->border->border_right_color, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_BOTTOM_COLOR:
+      gtk_css_take_value (&style->border->border_bottom_color, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_LEFT_COLOR:
+      gtk_css_take_value (&style->border->border_left_color, value);
+      break;
+    case GTK_CSS_PROPERTY_OUTLINE_COLOR:
+      gtk_css_take_value (&style->outline->outline_color, value);
+      break;
+    case GTK_CSS_PROPERTY_BACKGROUND_REPEAT:
+      gtk_css_take_value (&style->background->background_repeat, value);
+      break;
+    case GTK_CSS_PROPERTY_BACKGROUND_IMAGE:
+      gtk_css_take_value (&style->background->background_image, value);
+      break;
+    case GTK_CSS_PROPERTY_BACKGROUND_BLEND_MODE:
+      gtk_css_take_value (&style->background->background_blend_mode, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_IMAGE_SOURCE:
+      gtk_css_take_value (&style->border->border_image_source, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_IMAGE_REPEAT:
+      gtk_css_take_value (&style->border->border_image_repeat, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_IMAGE_SLICE:
+      gtk_css_take_value (&style->border->border_image_slice, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_IMAGE_WIDTH:
+      gtk_css_take_value (&style->border->border_image_width, value);
+      break;
+    case GTK_CSS_PROPERTY_ICON_SOURCE:
+      gtk_css_take_value (&style->other->icon_source, value);
+      break;
+    case GTK_CSS_PROPERTY_ICON_SIZE:
+      gtk_css_take_value (&style->icon->icon_size, value);
+      break;
+    case GTK_CSS_PROPERTY_ICON_SHADOW:
+      gtk_css_take_value (&style->icon->icon_shadow, value);
+      break;
+    case GTK_CSS_PROPERTY_ICON_STYLE:
+      gtk_css_take_value (&style->icon->icon_style, value);
+      break;
+    case GTK_CSS_PROPERTY_ICON_TRANSFORM:
+      gtk_css_take_value (&style->other->icon_transform, value);
+      break;
+    case GTK_CSS_PROPERTY_ICON_FILTER:
+      gtk_css_take_value (&style->other->icon_filter, value);
+      break;
+    case GTK_CSS_PROPERTY_BORDER_SPACING:
+      gtk_css_take_value (&style->size->border_spacing, value);
+      break;
+    case GTK_CSS_PROPERTY_TRANSFORM:
+      gtk_css_take_value (&style->other->transform, value);
+      break;
+    case GTK_CSS_PROPERTY_MIN_WIDTH:
+      gtk_css_take_value (&style->size->min_width, value);
+      break;
+    case GTK_CSS_PROPERTY_MIN_HEIGHT:
+      gtk_css_take_value (&style->size->min_height, value);
+      break;
+    case GTK_CSS_PROPERTY_TRANSITION_PROPERTY:
+      gtk_css_take_value (&style->transition->transition_property, value);
+      break;
+    case GTK_CSS_PROPERTY_TRANSITION_DURATION:
+      gtk_css_take_value (&style->transition->transition_duration, value);
+      break;
+    case GTK_CSS_PROPERTY_TRANSITION_TIMING_FUNCTION:
+      gtk_css_take_value (&style->transition->transition_timing_function, value);
+      break;
+    case GTK_CSS_PROPERTY_TRANSITION_DELAY:
+      gtk_css_take_value (&style->transition->transition_delay, value);
+      break;
+    case GTK_CSS_PROPERTY_ANIMATION_NAME:
+      gtk_css_take_value (&style->animation->animation_name, value);
+      break;
+    case GTK_CSS_PROPERTY_ANIMATION_DURATION:
+      gtk_css_take_value (&style->animation->animation_duration, value);
+      break;
+    case GTK_CSS_PROPERTY_ANIMATION_TIMING_FUNCTION:
+      gtk_css_take_value (&style->animation->animation_timing_function, value);
+      break;
+    case GTK_CSS_PROPERTY_ANIMATION_ITERATION_COUNT:
+      gtk_css_take_value (&style->animation->animation_iteration_count, value);
+      break;
+    case GTK_CSS_PROPERTY_ANIMATION_DIRECTION:
+      gtk_css_take_value (&style->animation->animation_direction, value);
+      break;
+    case GTK_CSS_PROPERTY_ANIMATION_PLAY_STATE:
+      gtk_css_take_value (&style->animation->animation_play_state, value);
+      break;
+    case GTK_CSS_PROPERTY_ANIMATION_DELAY:
+      gtk_css_take_value (&style->animation->animation_delay, value);
+      break;
+    case GTK_CSS_PROPERTY_ANIMATION_FILL_MODE:
+      gtk_css_take_value (&style->animation->animation_fill_mode, value);
+      break;
+    case GTK_CSS_PROPERTY_OPACITY:
+      gtk_css_take_value (&style->other->opacity, value);
+      break;
+    case GTK_CSS_PROPERTY_FILTER:
+      gtk_css_take_value (&style->other->filter, value);
+      break;
+    case GTK_CSS_PROPERTY_CARET_COLOR:
+      gtk_css_take_value (&style->font->caret_color, value);
+      break;
+    case GTK_CSS_PROPERTY_SECONDARY_CARET_COLOR:
+      gtk_css_take_value (&style->font->secondary_caret_color, value);
+      break;
+    case GTK_CSS_PROPERTY_FONT_FEATURE_SETTINGS:
+      gtk_css_take_value (&style->font->font_feature_settings, value);
+      break;
+    case GTK_CSS_PROPERTY_FONT_VARIATION_SETTINGS:
+      gtk_css_take_value (&style->font->font_variation_settings, value);
+      break;
 
-  if (style->sections && style->sections->len > id && g_ptr_array_index (style->sections, id))
+    default:
+      g_assert_not_reached ();
+      break;
+    }
+
+  if (sstyle->sections && sstyle->sections->len > id && g_ptr_array_index (sstyle->sections, id))
     {
-      gtk_css_section_unref (g_ptr_array_index (style->sections, id));
-      g_ptr_array_index (style->sections, id) = NULL;
+      gtk_css_section_unref (g_ptr_array_index (sstyle->sections, id));
+      g_ptr_array_index (sstyle->sections, id) = NULL;
     }
 
   if (section)
     {
-      if (style->sections == NULL)
-        style->sections = g_ptr_array_new_with_free_func (maybe_unref_section);
-      if (style->sections->len <= id)
-        g_ptr_array_set_size (style->sections, id + 1);
-
-      g_ptr_array_index (style->sections, id) = gtk_css_section_ref (section);
+      if (sstyle->sections == NULL)
+        sstyle->sections = g_ptr_array_new_with_free_func (maybe_unref_section);
+      if (sstyle->sections->len <= id)
+        g_ptr_array_set_size (sstyle->sections, id + 1);
+      g_ptr_array_index (sstyle->sections, id) = gtk_css_section_ref (section);
     }
 }
 
@@ -176,6 +705,284 @@ gtk_css_static_style_get_default (void)
   return default_style;
 }
 
+static GtkCssValues *
+gtk_css_core_create_initial_values (void)
+{
+  return NULL;
+
+}
+static GtkCssValues *
+gtk_css_background_create_initial_values (void)
+{
+  GtkCssBackgroundValues *values;
+
+  values = (GtkCssBackgroundValues *)gtk_css_values_new (GTK_CSS_BACKGROUND_VALUES);
+
+  values->background_color = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_BACKGROUND_COLOR, NULL, 
NULL, NULL);
+  values->box_shadow = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_BOX_SHADOW, NULL, NULL, NULL);
+  values->background_clip = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_BACKGROUND_CLIP, NULL, 
NULL, NULL);
+  values->background_origin = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_BACKGROUND_ORIGIN, NULL, 
NULL, NULL);
+  values->background_size = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_BACKGROUND_SIZE, NULL, 
NULL, NULL);
+  values->background_position = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_BACKGROUND_POSITION, 
NULL, NULL, NULL);
+  values->background_repeat = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_BACKGROUND_REPEAT, NULL, 
NULL, NULL);
+  values->background_image = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_BACKGROUND_IMAGE, NULL, 
NULL, NULL);
+  values->background_blend_mode = _gtk_css_initial_value_new_compute 
(GTK_CSS_PROPERTY_BACKGROUND_BLEND_MODE, NULL, NULL, NULL);
+
+  return (GtkCssValues *)values;
+}
+
+static GtkCssValues *
+gtk_css_border_create_initial_values (void)
+{
+  GtkCssBorderValues *values;
+
+  values = (GtkCssBorderValues *)gtk_css_values_new (GTK_CSS_BORDER_VALUES);
+
+  values->border_top_style = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_BORDER_TOP_STYLE, NULL, 
NULL, NULL);
+  values->border_top_width = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_BORDER_TOP_WIDTH, NULL, 
NULL, NULL);
+  values->border_left_style = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_BORDER_LEFT_STYLE, NULL, 
NULL, NULL);
+  values->border_left_width = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH, NULL, 
NULL, NULL);
+  values->border_bottom_style = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_BORDER_BOTTOM_STYLE, 
NULL, NULL, NULL);
+  values->border_bottom_width = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_BORDER_BOTTOM_WIDTH, 
NULL, NULL, NULL);
+  values->border_right_style = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_BORDER_RIGHT_STYLE, 
NULL, NULL, NULL);
+  values->border_right_width = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_BORDER_RIGHT_WIDTH, 
NULL, NULL, NULL);
+  values->border_top_left_radius = _gtk_css_initial_value_new_compute 
(GTK_CSS_PROPERTY_BORDER_TOP_LEFT_RADIUS, NULL, NULL, NULL);
+  values->border_top_right_radius = _gtk_css_initial_value_new_compute 
(GTK_CSS_PROPERTY_BORDER_TOP_RIGHT_RADIUS, NULL, NULL, NULL);
+  values->border_bottom_left_radius = _gtk_css_initial_value_new_compute 
(GTK_CSS_PROPERTY_BORDER_BOTTOM_LEFT_RADIUS, NULL, NULL, NULL);
+  values->border_bottom_right_radius = _gtk_css_initial_value_new_compute 
(GTK_CSS_PROPERTY_BORDER_BOTTOM_RIGHT_RADIUS, NULL, NULL, NULL);
+  values->border_top_color = NULL;
+  values->border_right_color = NULL;
+  values->border_bottom_color = NULL;
+  values->border_left_color = NULL;
+  values->border_image_source = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_BORDER_IMAGE_SOURCE, 
NULL, NULL, NULL);
+  values->border_image_repeat = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_BORDER_IMAGE_REPEAT, 
NULL, NULL, NULL);
+  values->border_image_slice = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_BORDER_IMAGE_SLICE, 
NULL, NULL, NULL);
+  values->border_image_width = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_BORDER_IMAGE_WIDTH, 
NULL, NULL, NULL);
+
+  return (GtkCssValues *)values;
+}
+
+static GtkCssValues *
+gtk_css_outline_create_initial_values (void)
+{
+  GtkCssOutlineValues *values;
+
+  values = (GtkCssOutlineValues *)gtk_css_values_new (GTK_CSS_OUTLINE_VALUES);
+
+  values->outline_style = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_OUTLINE_STYLE, NULL, NULL, 
NULL);
+  values->outline_width = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_OUTLINE_WIDTH, NULL, NULL, 
NULL);
+  values->outline_offset = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_OUTLINE_OFFSET, NULL, NULL, 
NULL);
+  values->outline_top_left_radius = _gtk_css_initial_value_new_compute 
(GTK_CSS_PROPERTY_OUTLINE_TOP_LEFT_RADIUS, NULL, NULL, NULL);
+  values->outline_top_right_radius = _gtk_css_initial_value_new_compute 
(GTK_CSS_PROPERTY_OUTLINE_TOP_RIGHT_RADIUS, NULL, NULL, NULL);
+  values->outline_bottom_right_radius = _gtk_css_initial_value_new_compute 
(GTK_CSS_PROPERTY_OUTLINE_BOTTOM_RIGHT_RADIUS, NULL, NULL, NULL);
+  values->outline_bottom_left_radius = _gtk_css_initial_value_new_compute 
(GTK_CSS_PROPERTY_OUTLINE_BOTTOM_LEFT_RADIUS, NULL, NULL, NULL);
+  values->outline_color = NULL;
+
+  return (GtkCssValues *)values;
+}
+
+static GtkCssValues *
+gtk_css_icon_create_initial_values (void)
+{
+  return NULL;
+}
+
+static GtkCssValues *
+gtk_css_font_create_initial_values (void)
+{
+  return NULL;
+}
+
+static GtkCssValues *
+gtk_css_font_variant_create_initial_values (void)
+{
+  GtkCssFontVariantValues *values;
+
+  values = (GtkCssFontVariantValues *)gtk_css_values_new (GTK_CSS_FONT_VARIANT_VALUES);
+
+  values->text_decoration_line = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_TEXT_DECORATION_LINE, 
NULL, NULL, NULL);
+  values->text_decoration_color = NULL;
+  values->text_decoration_style = _gtk_css_initial_value_new_compute 
(GTK_CSS_PROPERTY_TEXT_DECORATION_STYLE, NULL, NULL, NULL);
+  values->font_kerning = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_FONT_KERNING, NULL, NULL, 
NULL);
+  values->font_variant_ligatures = _gtk_css_initial_value_new_compute 
(GTK_CSS_PROPERTY_FONT_VARIANT_LIGATURES, NULL, NULL, NULL);
+  values->font_variant_position = _gtk_css_initial_value_new_compute 
(GTK_CSS_PROPERTY_FONT_VARIANT_POSITION, NULL, NULL, NULL);
+  values->font_variant_caps = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_FONT_VARIANT_CAPS, NULL, 
NULL, NULL);
+  values->font_variant_numeric = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_FONT_VARIANT_NUMERIC, 
NULL, NULL, NULL);
+  values->font_variant_alternates = _gtk_css_initial_value_new_compute 
(GTK_CSS_PROPERTY_FONT_VARIANT_ALTERNATES, NULL, NULL, NULL);
+  values->font_variant_east_asian = _gtk_css_initial_value_new_compute 
(GTK_CSS_PROPERTY_FONT_VARIANT_EAST_ASIAN, NULL, NULL, NULL);
+
+  return (GtkCssValues *)values;
+}
+
+static GtkCssValues *
+gtk_css_animation_create_initial_values (void)
+{
+  GtkCssAnimationValues *values;
+
+  values = (GtkCssAnimationValues *)gtk_css_values_new (GTK_CSS_ANIMATION_VALUES);
+
+  values->animation_name = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_ANIMATION_NAME, NULL, NULL, 
NULL);
+  values->animation_duration = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_ANIMATION_DURATION, 
NULL, NULL, NULL);
+  values->animation_timing_function = _gtk_css_initial_value_new_compute 
(GTK_CSS_PROPERTY_ANIMATION_TIMING_FUNCTION, NULL, NULL, NULL);
+  values->animation_iteration_count = _gtk_css_initial_value_new_compute 
(GTK_CSS_PROPERTY_ANIMATION_ITERATION_COUNT, NULL, NULL, NULL);
+  values->animation_direction = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_ANIMATION_DIRECTION, 
NULL, NULL, NULL);
+  values->animation_play_state = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_ANIMATION_PLAY_STATE, 
NULL, NULL, NULL);
+  values->animation_delay = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_ANIMATION_DELAY, NULL, 
NULL, NULL);
+  values->animation_fill_mode = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_ANIMATION_FILL_MODE, 
NULL, NULL, NULL);
+
+  return (GtkCssValues *)values;
+}
+
+static GtkCssValues *
+gtk_css_transition_create_initial_values (void)
+{
+  GtkCssTransitionValues *values;
+
+  values = (GtkCssTransitionValues *)gtk_css_values_new (GTK_CSS_TRANSITION_VALUES);
+
+  values->transition_property = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_TRANSITION_PROPERTY, 
NULL, NULL, NULL);
+  values->transition_duration = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_TRANSITION_DURATION, 
NULL, NULL, NULL);
+  values->transition_timing_function = _gtk_css_initial_value_new_compute 
(GTK_CSS_PROPERTY_TRANSITION_TIMING_FUNCTION, NULL, NULL, NULL);
+  values->transition_delay = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_TRANSITION_DELAY, NULL, 
NULL, NULL);
+
+  return (GtkCssValues *)values;
+}
+
+static GtkCssValues *
+gtk_css_size_create_initial_values (void)
+{
+  GtkCssSizeValues *values;
+
+  values = (GtkCssSizeValues *)gtk_css_values_new (GTK_CSS_SIZE_VALUES);
+
+  values->margin_top = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_MARGIN_TOP, NULL, NULL, NULL);
+  values->margin_left = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_MARGIN_LEFT, NULL, NULL, NULL);
+  values->margin_bottom = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_MARGIN_BOTTOM, NULL, NULL, 
NULL);
+  values->margin_right = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_MARGIN_RIGHT, NULL, NULL, 
NULL);
+  values->padding_top = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_PADDING_TOP, NULL, NULL, NULL);
+  values->padding_left = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_PADDING_LEFT, NULL, NULL, 
NULL);
+  values->padding_bottom = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_PADDING_BOTTOM, NULL, NULL, 
NULL);
+  values->padding_right = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_PADDING_RIGHT, NULL, NULL, 
NULL);
+  values->border_spacing = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_BORDER_SPACING, NULL, NULL, 
NULL);
+  values->min_width = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_MIN_WIDTH, NULL, NULL, NULL);
+  values->min_height = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_MIN_HEIGHT, NULL, NULL, NULL);
+
+  return (GtkCssValues *)values;
+}
+
+static GtkCssValues *
+gtk_css_other_create_initial_values (void)
+{
+  GtkCssOtherValues *values;
+
+  values = (GtkCssOtherValues *)gtk_css_values_new (GTK_CSS_OTHER_VALUES);
+
+  values->icon_source = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_ICON_SOURCE, NULL, NULL, NULL);
+  values->icon_transform = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_ICON_TRANSFORM, NULL, NULL, 
NULL);
+  values->icon_filter = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_ICON_FILTER, NULL, NULL, NULL);
+  values->transform = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_TRANSFORM, NULL, NULL, NULL);
+  values->opacity = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_OPACITY, NULL, NULL, NULL);
+  values->filter = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_FILTER, NULL, NULL, NULL);
+
+  return (GtkCssValues *)values;
+}
+
+static void
+gtk_css_lookup_resolve (GtkCssLookup      *lookup,
+                        GtkStyleProvider  *provider,
+                        GtkCssStaticStyle *sstyle,
+                        GtkCssStyle       *parent_style)
+{
+  GtkCssStyle *style = (GtkCssStyle *)sstyle;
+
+  gtk_internal_return_if_fail (lookup != NULL);
+  gtk_internal_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
+  gtk_internal_return_if_fail (GTK_IS_CSS_STATIC_STYLE (style));
+  gtk_internal_return_if_fail (parent_style == NULL || GTK_IS_CSS_STYLE (parent_style));
+
+  if (_gtk_bitmask_is_empty (_gtk_css_lookup_get_set_values (lookup)))
+    {
+      style->background = (GtkCssBackgroundValues *)gtk_css_values_ref (gtk_css_background_initial_values);
+      style->border = (GtkCssBorderValues *)gtk_css_values_ref (gtk_css_border_initial_values);
+      style->outline = (GtkCssOutlineValues *)gtk_css_values_ref (gtk_css_outline_initial_values);
+      style->font_variant = (GtkCssFontVariantValues *)gtk_css_values_ref 
(gtk_css_font_variant_initial_values);
+      style->animation = (GtkCssAnimationValues *)gtk_css_values_ref (gtk_css_animation_initial_values);
+      style->transition = (GtkCssTransitionValues *)gtk_css_values_ref (gtk_css_transition_initial_values);
+      style->size = (GtkCssSizeValues *)gtk_css_values_ref (gtk_css_size_initial_values);
+      style->other = (GtkCssOtherValues *)gtk_css_values_ref (gtk_css_other_initial_values);
+
+      if (parent_style)
+        {
+          style->core = (GtkCssCoreValues *)gtk_css_values_ref ((GtkCssValues *)parent_style->core);
+          style->icon = (GtkCssIconValues *)gtk_css_values_ref ((GtkCssValues *)parent_style->icon);
+          style->font = (GtkCssFontValues *)gtk_css_values_ref ((GtkCssValues *)parent_style->font);
+        }
+      else
+        {
+          gtk_css_core_values_new_compute (sstyle, provider, parent_style, lookup);
+          gtk_css_icon_values_new_compute (sstyle, provider, parent_style, lookup);
+          gtk_css_font_values_new_compute (sstyle, provider, parent_style, lookup);
+        }
+
+      return;
+    }
+
+  if (parent_style && gtk_css_core_values_unset (lookup))
+    style->core = (GtkCssCoreValues *)gtk_css_values_ref ((GtkCssValues *)parent_style->core);
+  else
+    gtk_css_core_values_new_compute (sstyle, provider, parent_style, lookup);
+
+  if (gtk_css_background_values_unset (lookup))
+    style->background = (GtkCssBackgroundValues *)gtk_css_values_ref (gtk_css_background_initial_values);
+  else
+    gtk_css_background_values_new_compute (sstyle, provider, parent_style, lookup);
+
+  if (gtk_css_border_values_unset (lookup))
+    style->border = (GtkCssBorderValues *)gtk_css_values_ref (gtk_css_border_initial_values);
+  else
+    gtk_css_border_values_new_compute (sstyle, provider, parent_style, lookup);
+
+  if (parent_style && gtk_css_icon_values_unset (lookup))
+    style->icon = (GtkCssIconValues *)gtk_css_values_ref ((GtkCssValues *)parent_style->icon);
+  else
+    gtk_css_icon_values_new_compute (sstyle, provider, parent_style, lookup);
+
+  if (gtk_css_outline_values_unset (lookup))
+    style->outline = (GtkCssOutlineValues *)gtk_css_values_ref (gtk_css_outline_initial_values);
+  else
+    gtk_css_outline_values_new_compute (sstyle, provider, parent_style, lookup);
+
+  if (parent_style && gtk_css_font_values_unset (lookup))
+    style->font = (GtkCssFontValues *)gtk_css_values_ref ((GtkCssValues *)parent_style->font);
+  else
+    gtk_css_font_values_new_compute (sstyle, provider, parent_style, lookup);
+
+  if (gtk_css_font_variant_values_unset (lookup))
+    style->font_variant = (GtkCssFontVariantValues *)gtk_css_values_ref 
(gtk_css_font_variant_initial_values);
+  else
+    gtk_css_font_variant_values_new_compute (sstyle, provider, parent_style, lookup);
+
+  if (gtk_css_animation_values_unset (lookup))
+    style->animation = (GtkCssAnimationValues *)gtk_css_values_ref (gtk_css_animation_initial_values);
+  else
+    gtk_css_animation_values_new_compute (sstyle, provider, parent_style, lookup);
+
+  if (gtk_css_transition_values_unset (lookup))
+    style->transition = (GtkCssTransitionValues *)gtk_css_values_ref (gtk_css_transition_initial_values);
+  else
+    gtk_css_transition_values_new_compute (sstyle, provider, parent_style, lookup);
+
+  if (gtk_css_size_values_unset (lookup))
+    style->size = (GtkCssSizeValues *)gtk_css_values_ref (gtk_css_size_initial_values);
+  else
+    gtk_css_size_values_new_compute (sstyle, provider, parent_style, lookup);
+
+  if (gtk_css_other_values_unset (lookup))
+    style->other = (GtkCssOtherValues *)gtk_css_values_ref (gtk_css_other_initial_values);
+  else
+    gtk_css_other_values_new_compute (sstyle, provider, parent_style, lookup);
+}
+
 GtkCssStyle *
 gtk_css_static_style_new_compute (GtkStyleProvider             *provider,
                                   const GtkCountingBloomFilter *filter,
@@ -204,10 +1011,10 @@ gtk_css_static_style_new_compute (GtkStyleProvider             *provider,
   else
     parent = NULL;
 
-  _gtk_css_lookup_resolve (&lookup,
-                           provider,
-                           result,
-                           parent ? gtk_css_node_get_style (parent) : NULL);
+  gtk_css_lookup_resolve (&lookup,
+                          provider,
+                          result,
+                          parent ? gtk_css_node_get_style (parent) : NULL);
 
   _gtk_css_lookup_destroy (&lookup);
 
@@ -220,7 +1027,7 @@ G_STATIC_ASSERT (GTK_CSS_PROPERTY_BORDER_BOTTOM_STYLE == GTK_CSS_PROPERTY_BORDER
 G_STATIC_ASSERT (GTK_CSS_PROPERTY_BORDER_LEFT_STYLE == GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH - 1);
 G_STATIC_ASSERT (GTK_CSS_PROPERTY_OUTLINE_STYLE == GTK_CSS_PROPERTY_OUTLINE_WIDTH - 1);
 
-void
+static void
 gtk_css_static_style_compute_value (GtkCssStaticStyle *style,
                                     GtkStyleProvider  *provider,
                                     GtkCssStyle       *parent_style,
@@ -259,7 +1066,6 @@ gtk_css_static_style_compute_value (GtkCssStaticStyle *style,
         break;
     }
 
-
   /* 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:
diff --git a/gtk/gtkcssstaticstyleprivate.h b/gtk/gtkcssstaticstyleprivate.h
index 8c1acf11b2..04654ac070 100644
--- a/gtk/gtkcssstaticstyleprivate.h
+++ b/gtk/gtkcssstaticstyleprivate.h
@@ -35,11 +35,11 @@ G_BEGIN_DECLS
 
 typedef struct _GtkCssStaticStyleClass      GtkCssStaticStyleClass;
 
+
 struct _GtkCssStaticStyle
 {
   GtkCssStyle parent;
 
-  GtkCssValue           *values[GTK_CSS_PROPERTY_N_PROPERTIES]; /* the values */
   GPtrArray             *sections;             /* sections the values are defined in */
 
   GtkCssChange           change;               /* change as returned by value lookup */
@@ -57,14 +57,6 @@ GtkCssStyle *           gtk_css_static_style_new_compute        (GtkStyleProvide
                                                                  const GtkCountingBloomFilter   *filter,
                                                                  GtkCssNode                     *node,
                                                                  GtkCssChange                    change);
-
-void                    gtk_css_static_style_compute_value      (GtkCssStaticStyle              *style,
-                                                                 GtkStyleProvider               *provider,
-                                                                 GtkCssStyle                    
*parent_style,
-                                                                 guint                           id,
-                                                                 GtkCssValue                    *specified,
-                                                                 GtkCssSection                  *section);
-
 GtkCssChange            gtk_css_static_style_get_change         (GtkCssStaticStyle              *style);
 
 G_END_DECLS
diff --git a/gtk/gtkcssstyle.c b/gtk/gtkcssstyle.c
index 48c241d9ca..b05ccc0d20 100644
--- a/gtk/gtkcssstyle.c
+++ b/gtk/gtkcssstyle.c
@@ -54,9 +54,34 @@ gtk_css_style_real_is_static (GtkCssStyle *style)
   return TRUE;
 }
 
+
+static void
+gtk_css_style_finalize (GObject *object)
+{
+  GtkCssStyle *style = GTK_CSS_STYLE (object);
+
+  gtk_css_values_unref ((GtkCssValues *)style->core);
+  gtk_css_values_unref ((GtkCssValues *)style->background);
+  gtk_css_values_unref ((GtkCssValues *)style->border);
+  gtk_css_values_unref ((GtkCssValues *)style->icon);
+  gtk_css_values_unref ((GtkCssValues *)style->outline);
+  gtk_css_values_unref ((GtkCssValues *)style->font);
+  gtk_css_values_unref ((GtkCssValues *)style->font_variant);
+  gtk_css_values_unref ((GtkCssValues *)style->animation);
+  gtk_css_values_unref ((GtkCssValues *)style->transition);
+  gtk_css_values_unref ((GtkCssValues *)style->size);
+  gtk_css_values_unref ((GtkCssValues *)style->other);
+
+  G_OBJECT_CLASS (gtk_css_style_parent_class)->finalize (object);
+}
+
 static void
 gtk_css_style_class_init (GtkCssStyleClass *klass)
 {
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = gtk_css_style_finalize;
+
   klass->get_section = gtk_css_style_real_get_section;
   klass->is_static = gtk_css_style_real_is_static;
 }
@@ -68,9 +93,202 @@ gtk_css_style_init (GtkCssStyle *style)
 
 GtkCssValue *
 gtk_css_style_get_value (GtkCssStyle *style,
-                          guint        id)
+                         guint        id)
 {
-  return GTK_CSS_STYLE_GET_CLASS (style)->get_value (style, id);
+  switch (id)
+    {
+    case GTK_CSS_PROPERTY_COLOR:
+      return style->core->color;
+    case GTK_CSS_PROPERTY_DPI:
+      return style->core->dpi;
+    case GTK_CSS_PROPERTY_FONT_SIZE:
+      return style->core->font_size;
+    case GTK_CSS_PROPERTY_ICON_THEME:
+      return style->core->icon_theme;
+    case GTK_CSS_PROPERTY_ICON_PALETTE:
+      return style->core->icon_palette;
+    case GTK_CSS_PROPERTY_BACKGROUND_COLOR:
+      return style->background->background_color;
+    case GTK_CSS_PROPERTY_FONT_FAMILY:
+      return style->font->font_family;
+    case GTK_CSS_PROPERTY_FONT_STYLE:
+      return style->font->font_style;
+    case GTK_CSS_PROPERTY_FONT_WEIGHT:
+      return style->font->font_weight;
+    case GTK_CSS_PROPERTY_FONT_STRETCH:
+      return style->font->font_stretch;
+    case GTK_CSS_PROPERTY_LETTER_SPACING:
+      return style->font->letter_spacing;
+    case GTK_CSS_PROPERTY_TEXT_DECORATION_LINE:
+      return style->font_variant->text_decoration_line;
+    case GTK_CSS_PROPERTY_TEXT_DECORATION_COLOR:
+      return style->font_variant->text_decoration_color ? style->font_variant->text_decoration_color : 
style->core->color;
+    case GTK_CSS_PROPERTY_TEXT_DECORATION_STYLE:
+      return style->font_variant->text_decoration_style;
+    case GTK_CSS_PROPERTY_FONT_KERNING:
+      return style->font_variant->font_kerning;
+    case GTK_CSS_PROPERTY_FONT_VARIANT_LIGATURES:
+      return style->font_variant->font_variant_ligatures;
+    case GTK_CSS_PROPERTY_FONT_VARIANT_POSITION:
+      return style->font_variant->font_variant_position;
+    case GTK_CSS_PROPERTY_FONT_VARIANT_CAPS:
+      return style->font_variant->font_variant_caps;
+    case GTK_CSS_PROPERTY_FONT_VARIANT_NUMERIC:
+      return style->font_variant->font_variant_numeric;
+    case GTK_CSS_PROPERTY_FONT_VARIANT_ALTERNATES:
+      return style->font_variant->font_variant_alternates;
+    case GTK_CSS_PROPERTY_FONT_VARIANT_EAST_ASIAN:
+      return style->font_variant->font_variant_east_asian;
+    case GTK_CSS_PROPERTY_TEXT_SHADOW:
+      return style->font->text_shadow;
+    case GTK_CSS_PROPERTY_BOX_SHADOW:
+      return style->background->box_shadow;
+    case GTK_CSS_PROPERTY_MARGIN_TOP:
+      return style->size->margin_top;
+    case GTK_CSS_PROPERTY_MARGIN_LEFT:
+      return style->size->margin_left;
+    case GTK_CSS_PROPERTY_MARGIN_BOTTOM:
+      return style->size->margin_bottom;
+    case GTK_CSS_PROPERTY_MARGIN_RIGHT:
+      return style->size->margin_right;
+    case GTK_CSS_PROPERTY_PADDING_TOP:
+      return style->size->padding_top;
+    case GTK_CSS_PROPERTY_PADDING_LEFT:
+      return style->size->padding_left;
+    case GTK_CSS_PROPERTY_PADDING_BOTTOM:
+      return style->size->padding_bottom;
+    case GTK_CSS_PROPERTY_PADDING_RIGHT:
+      return style->size->padding_right;
+    case GTK_CSS_PROPERTY_BORDER_TOP_STYLE:
+      return style->border->border_top_style;
+    case GTK_CSS_PROPERTY_BORDER_TOP_WIDTH:
+      return style->border->border_top_width;
+    case GTK_CSS_PROPERTY_BORDER_LEFT_STYLE:
+      return style->border->border_left_style;
+    case GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH:
+      return style->border->border_left_width;
+    case GTK_CSS_PROPERTY_BORDER_BOTTOM_STYLE:
+      return style->border->border_bottom_style;
+    case GTK_CSS_PROPERTY_BORDER_BOTTOM_WIDTH:
+      return style->border->border_bottom_width;
+    case GTK_CSS_PROPERTY_BORDER_RIGHT_STYLE:
+      return style->border->border_right_style;
+    case GTK_CSS_PROPERTY_BORDER_RIGHT_WIDTH:
+      return style->border->border_right_width;
+    case GTK_CSS_PROPERTY_BORDER_TOP_LEFT_RADIUS:
+      return style->border->border_top_left_radius;
+    case GTK_CSS_PROPERTY_BORDER_TOP_RIGHT_RADIUS:
+      return style->border->border_top_right_radius;
+    case GTK_CSS_PROPERTY_BORDER_BOTTOM_RIGHT_RADIUS:
+      return style->border->border_bottom_right_radius;
+    case GTK_CSS_PROPERTY_BORDER_BOTTOM_LEFT_RADIUS:
+      return style->border->border_bottom_left_radius;
+    case GTK_CSS_PROPERTY_OUTLINE_STYLE:
+      return style->outline->outline_style;
+    case GTK_CSS_PROPERTY_OUTLINE_WIDTH:
+      return style->outline->outline_width;
+    case GTK_CSS_PROPERTY_OUTLINE_OFFSET:
+      return style->outline->outline_offset;
+    case GTK_CSS_PROPERTY_OUTLINE_TOP_LEFT_RADIUS:
+      return style->outline->outline_top_left_radius;
+    case GTK_CSS_PROPERTY_OUTLINE_TOP_RIGHT_RADIUS:
+      return style->outline->outline_top_right_radius;
+    case GTK_CSS_PROPERTY_OUTLINE_BOTTOM_RIGHT_RADIUS:
+      return style->outline->outline_bottom_right_radius;
+    case GTK_CSS_PROPERTY_OUTLINE_BOTTOM_LEFT_RADIUS:
+      return style->outline->outline_bottom_left_radius;
+    case GTK_CSS_PROPERTY_BACKGROUND_CLIP:
+      return style->background->background_clip;
+    case GTK_CSS_PROPERTY_BACKGROUND_ORIGIN:
+      return style->background->background_origin;
+    case GTK_CSS_PROPERTY_BACKGROUND_SIZE:
+      return style->background->background_size;
+    case GTK_CSS_PROPERTY_BACKGROUND_POSITION:
+      return style->background->background_position;
+    case GTK_CSS_PROPERTY_BORDER_TOP_COLOR:
+      return style->border->border_top_color ? style->border->border_top_color : style->core->color;
+    case GTK_CSS_PROPERTY_BORDER_RIGHT_COLOR:
+      return style->border->border_right_color ? style->border->border_right_color : style->core->color;
+    case GTK_CSS_PROPERTY_BORDER_BOTTOM_COLOR:
+      return style->border->border_bottom_color ? style->border->border_bottom_color : style->core->color;
+    case GTK_CSS_PROPERTY_BORDER_LEFT_COLOR:
+      return style->border->border_left_color ? style->border->border_left_color: style->core->color;
+    case GTK_CSS_PROPERTY_OUTLINE_COLOR:
+      return style->outline->outline_color ? style->outline->outline_color : style->core->color;
+    case GTK_CSS_PROPERTY_BACKGROUND_REPEAT:
+      return style->background->background_repeat;
+    case GTK_CSS_PROPERTY_BACKGROUND_IMAGE:
+      return style->background->background_image;
+    case GTK_CSS_PROPERTY_BACKGROUND_BLEND_MODE:
+      return style->background->background_blend_mode;
+    case GTK_CSS_PROPERTY_BORDER_IMAGE_SOURCE:
+      return style->border->border_image_source;
+    case GTK_CSS_PROPERTY_BORDER_IMAGE_REPEAT:
+      return style->border->border_image_repeat;
+    case GTK_CSS_PROPERTY_BORDER_IMAGE_SLICE:
+      return style->border->border_image_slice;
+    case GTK_CSS_PROPERTY_BORDER_IMAGE_WIDTH:
+      return style->border->border_image_width;
+    case GTK_CSS_PROPERTY_ICON_SOURCE:
+      return style->other->icon_source;
+    case GTK_CSS_PROPERTY_ICON_SIZE:
+      return style->icon->icon_size;
+    case GTK_CSS_PROPERTY_ICON_SHADOW:
+      return style->icon->icon_shadow;
+    case GTK_CSS_PROPERTY_ICON_STYLE:
+      return style->icon->icon_style;
+    case GTK_CSS_PROPERTY_ICON_TRANSFORM:
+      return style->other->icon_transform;
+    case GTK_CSS_PROPERTY_ICON_FILTER:
+      return style->other->icon_filter;
+    case GTK_CSS_PROPERTY_BORDER_SPACING:
+      return style->size->border_spacing;
+    case GTK_CSS_PROPERTY_TRANSFORM:
+      return style->other->transform;
+    case GTK_CSS_PROPERTY_MIN_WIDTH:
+      return style->size->min_width;
+    case GTK_CSS_PROPERTY_MIN_HEIGHT:
+      return style->size->min_height;
+    case GTK_CSS_PROPERTY_TRANSITION_PROPERTY:
+      return style->transition->transition_property;
+    case GTK_CSS_PROPERTY_TRANSITION_DURATION:
+      return style->transition->transition_duration;
+    case GTK_CSS_PROPERTY_TRANSITION_TIMING_FUNCTION:
+      return style->transition->transition_timing_function;
+    case GTK_CSS_PROPERTY_TRANSITION_DELAY:
+      return style->transition->transition_delay;
+    case GTK_CSS_PROPERTY_ANIMATION_NAME:
+      return style->animation->animation_name;
+    case GTK_CSS_PROPERTY_ANIMATION_DURATION:
+      return style->animation->animation_duration;
+    case GTK_CSS_PROPERTY_ANIMATION_TIMING_FUNCTION:
+      return style->animation->animation_timing_function;
+    case GTK_CSS_PROPERTY_ANIMATION_ITERATION_COUNT:
+      return style->animation->animation_iteration_count;
+    case GTK_CSS_PROPERTY_ANIMATION_DIRECTION:
+      return style->animation->animation_direction;
+    case GTK_CSS_PROPERTY_ANIMATION_PLAY_STATE:
+      return style->animation->animation_play_state;
+    case GTK_CSS_PROPERTY_ANIMATION_DELAY:
+      return style->animation->animation_delay;
+    case GTK_CSS_PROPERTY_ANIMATION_FILL_MODE:
+      return style->animation->animation_fill_mode;
+    case GTK_CSS_PROPERTY_OPACITY:
+      return style->other->opacity;
+    case GTK_CSS_PROPERTY_FILTER:
+      return style->other->filter;
+    case GTK_CSS_PROPERTY_CARET_COLOR:
+      return style->font->caret_color ? style->font->caret_color : style->core->color;
+    case GTK_CSS_PROPERTY_SECONDARY_CARET_COLOR:
+      return style->font->secondary_caret_color ? style->font->secondary_caret_color : style->core->color;
+    case GTK_CSS_PROPERTY_FONT_FEATURE_SETTINGS:
+      return style->font->font_feature_settings;
+    case GTK_CSS_PROPERTY_FONT_VARIATION_SETTINGS:
+      return style->font->font_variation_settings;
+
+    default:
+      g_assert_not_reached ();
+    }
 }
 
 GtkCssSection *
@@ -474,3 +692,82 @@ gtk_css_style_get_pango_font (GtkCssStyle *style)
 
   return description;
 }
+
+/* Refcounted value structs */
+
+static int values_size[] = {
+  sizeof (GtkCssCoreValues),
+  sizeof (GtkCssBackgroundValues),
+  sizeof (GtkCssBorderValues),
+  sizeof (GtkCssIconValues),
+  sizeof (GtkCssOutlineValues),
+  sizeof (GtkCssFontValues),
+  sizeof (GtkCssFontVariantValues),
+  sizeof (GtkCssAnimationValues),
+  sizeof (GtkCssTransitionValues),
+  sizeof (GtkCssSizeValues),
+  sizeof (GtkCssOtherValues)
+};
+
+#define N_VALUES(type) ((values_size[type] - sizeof (GtkCssValues)) / sizeof (GtkCssValue *))
+
+GtkCssValues *gtk_css_values_ref (GtkCssValues *values)
+{
+  values->ref_count++;
+
+  return values;
+}
+
+static void
+gtk_css_values_free (GtkCssValues *values)
+{
+  int i;
+
+  for (i = 0; i < N_VALUES (values->type); i++)
+    {
+      if (values->values[i])
+        gtk_css_value_unref (values->values[i]);
+    }
+
+  g_free (values);
+}
+
+void gtk_css_values_unref (GtkCssValues *values)
+{
+  if (!values)
+    return;
+
+  values->ref_count--;
+
+  if (values->ref_count == 0)
+    gtk_css_values_free (values);
+}
+
+GtkCssValues *
+gtk_css_values_copy (GtkCssValues *values)
+{
+  GtkCssValues *copy;
+  int i;
+
+  copy = gtk_css_values_new (values->type);
+
+  for (i = 0; i < N_VALUES (values->type); i++)
+    {
+      if (values->values[i])
+        copy->values[i] = gtk_css_value_ref (values->values[i]);
+    }
+
+  return copy;
+}
+
+GtkCssValues *
+gtk_css_values_new (GtkCssValuesType type)
+{
+  GtkCssValues *values;
+
+  values = (GtkCssValues *)g_malloc0 (values_size[type]);
+  values->ref_count = 1;
+  values->type = type;
+
+  return values;  
+}
diff --git a/gtk/gtkcssstyleprivate.h b/gtk/gtkcssstyleprivate.h
index ef54fd9be0..d70b638939 100644
--- a/gtk/gtkcssstyleprivate.h
+++ b/gtk/gtkcssstyleprivate.h
@@ -35,21 +35,202 @@ G_BEGIN_DECLS
 #define GTK_IS_CSS_STYLE_CLASS(obj)  (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_CSS_STYLE))
 #define GTK_CSS_STYLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CSS_STYLE, 
GtkCssStyleClass))
 
+typedef enum {
+  GTK_CSS_CORE_VALUES,
+  GTK_CSS_BACKGROUND_VALUES,
+  GTK_CSS_BORDER_VALUES,
+  GTK_CSS_ICON_VALUES,
+  GTK_CSS_OUTLINE_VALUES,
+  GTK_CSS_FONT_VALUES,
+  GTK_CSS_FONT_VARIANT_VALUES,
+  GTK_CSS_ANIMATION_VALUES,
+  GTK_CSS_TRANSITION_VALUES,
+  GTK_CSS_SIZE_VALUES,
+  GTK_CSS_OTHER_VALUES
+} GtkCssValuesType;
+
+typedef struct _GtkCssValues GtkCssValues;
+typedef struct _GtkCssCoreValues GtkCssCoreValues;
+typedef struct _GtkCssBackgroundValues GtkCssBackgroundValues;
+typedef struct _GtkCssBorderValues GtkCssBorderValues;
+typedef struct _GtkCssIconValues GtkCssIconValues;
+typedef struct _GtkCssOutlineValues GtkCssOutlineValues;
+typedef struct _GtkCssFontValues GtkCssFontValues;
+typedef struct _GtkCssFontVariantValues GtkCssFontVariantValues;
+typedef struct _GtkCssAnimationValues GtkCssAnimationValues;
+typedef struct _GtkCssTransitionValues GtkCssTransitionValues;
+typedef struct _GtkCssSizeValues GtkCssSizeValues;
+typedef struct _GtkCssOtherValues GtkCssOtherValues;
+
+struct _GtkCssValues {
+  int ref_count;
+  GtkCssValuesType type;
+  GtkCssValue *values[];
+};
+
+struct _GtkCssCoreValues {
+  GtkCssValues base;
+  GtkCssValue *color;
+  GtkCssValue *dpi;
+  GtkCssValue *font_size;
+  GtkCssValue *icon_theme;
+  GtkCssValue *icon_palette;
+};
+
+struct _GtkCssBackgroundValues {
+  GtkCssValues base;
+  GtkCssValue *background_color;
+  GtkCssValue *box_shadow;
+  GtkCssValue *background_clip;
+  GtkCssValue *background_origin;
+  GtkCssValue *background_size;
+  GtkCssValue *background_position;
+  GtkCssValue *background_repeat;
+  GtkCssValue *background_image;
+  GtkCssValue *background_blend_mode;
+};
+
+struct _GtkCssBorderValues {
+  GtkCssValues base;
+  GtkCssValue *border_top_style;
+  GtkCssValue *border_top_width;
+  GtkCssValue *border_left_style;
+  GtkCssValue *border_left_width;
+  GtkCssValue *border_bottom_style;
+  GtkCssValue *border_bottom_width;
+  GtkCssValue *border_right_style;
+  GtkCssValue *border_right_width;
+  GtkCssValue *border_top_left_radius;
+  GtkCssValue *border_top_right_radius;
+  GtkCssValue *border_bottom_right_radius;
+  GtkCssValue *border_bottom_left_radius;
+  GtkCssValue *border_top_color; // NULL if currentColor
+  GtkCssValue *border_right_color; // NULL if currentColor
+  GtkCssValue *border_bottom_color; // NULL if currentColor
+  GtkCssValue *border_left_color; // NULL if currentColor
+  GtkCssValue *border_image_source;
+  GtkCssValue *border_image_repeat;
+  GtkCssValue *border_image_slice;
+  GtkCssValue *border_image_width;
+};
+
+struct _GtkCssIconValues {
+  GtkCssValues base;
+  GtkCssValue *icon_size;
+  GtkCssValue *icon_shadow;
+  GtkCssValue *icon_style;
+};
+
+
+struct _GtkCssOutlineValues {
+  GtkCssValues base;
+  GtkCssValue *outline_style;
+  GtkCssValue *outline_width;
+  GtkCssValue *outline_offset;
+  GtkCssValue *outline_top_left_radius;
+  GtkCssValue *outline_top_right_radius;
+  GtkCssValue *outline_bottom_right_radius;
+  GtkCssValue *outline_bottom_left_radius;
+  GtkCssValue *outline_color;
+};
+
+struct _GtkCssFontValues {
+  GtkCssValues base;
+  GtkCssValue *font_family;
+  GtkCssValue *font_style;
+  GtkCssValue *font_weight;
+  GtkCssValue *font_stretch;
+  GtkCssValue *letter_spacing;
+  GtkCssValue *text_shadow;
+  GtkCssValue *caret_color; // NULL if currentColor
+  GtkCssValue *secondary_caret_color; // NULL if currentColor
+  GtkCssValue *font_feature_settings;
+  GtkCssValue *font_variation_settings;
+};
+
+struct _GtkCssFontVariantValues {
+  GtkCssValues base;
+  GtkCssValue *text_decoration_line;
+  GtkCssValue *text_decoration_color; // NULL if currentColor
+  GtkCssValue *text_decoration_style;
+  GtkCssValue *font_kerning;
+  GtkCssValue *font_variant_ligatures;
+  GtkCssValue *font_variant_position;
+  GtkCssValue *font_variant_caps;
+  GtkCssValue *font_variant_numeric;
+  GtkCssValue *font_variant_alternates;
+  GtkCssValue *font_variant_east_asian;
+};
+
+struct _GtkCssAnimationValues {
+  GtkCssValues base;
+  GtkCssValue *animation_name;
+  GtkCssValue *animation_duration;
+  GtkCssValue *animation_timing_function;
+  GtkCssValue *animation_iteration_count;
+  GtkCssValue *animation_direction;
+  GtkCssValue *animation_play_state;
+  GtkCssValue *animation_delay;
+  GtkCssValue *animation_fill_mode;
+};
+
+struct _GtkCssTransitionValues {
+  GtkCssValues base;
+  GtkCssValue *transition_property;
+  GtkCssValue *transition_duration;
+  GtkCssValue *transition_timing_function;
+  GtkCssValue *transition_delay;
+};
+
+struct _GtkCssSizeValues {
+  GtkCssValues base;
+  GtkCssValue *margin_top;
+  GtkCssValue *margin_left;
+  GtkCssValue *margin_bottom;
+  GtkCssValue *margin_right;
+  GtkCssValue *padding_top;
+  GtkCssValue *padding_left;
+  GtkCssValue *padding_bottom;
+  GtkCssValue *padding_right;
+  GtkCssValue *border_spacing;
+  GtkCssValue *min_width;
+  GtkCssValue *min_height;
+};
+
+struct _GtkCssOtherValues {
+  GtkCssValues base;
+  GtkCssValue *icon_source;
+  GtkCssValue *icon_transform;
+  GtkCssValue *icon_filter;
+  GtkCssValue *transform;
+  GtkCssValue *opacity;
+  GtkCssValue *filter;
+};
+
 /* typedef struct _GtkCssStyle           GtkCssStyle; */
 typedef struct _GtkCssStyleClass      GtkCssStyleClass;
 
 struct _GtkCssStyle
 {
   GObject parent;
+
+  GtkCssCoreValues        *core;
+  GtkCssBackgroundValues  *background;
+  GtkCssBorderValues      *border;
+  GtkCssIconValues        *icon;
+  GtkCssOutlineValues     *outline;
+  GtkCssFontValues        *font;
+  GtkCssFontVariantValues *font_variant;
+  GtkCssAnimationValues   *animation;
+  GtkCssTransitionValues  *transition;
+  GtkCssSizeValues        *size;
+  GtkCssOtherValues       *other;
 };
 
 struct _GtkCssStyleClass
 {
   GObjectClass parent_class;
 
-  /* Get the value for the given property id. This needs to be FAST. */
-  GtkCssValue *         (* get_value)                           (GtkCssStyle            *style,
-                                                                 guint                   id);
   /* Get the section the value at the given id was declared at or NULL if unavailable.
    * Optional: default impl will just return NULL */
   GtkCssSection *       (* get_section)                         (GtkCssStyle            *style,
@@ -78,6 +259,13 @@ PangoAttrList *         gtk_css_style_get_pango_attributes      (GtkCssStyle
 PangoFontDescription *  gtk_css_style_get_pango_font            (GtkCssStyle            *style);
 GtkCssStaticStyle *     gtk_css_style_get_static_style          (GtkCssStyle            *style);
 
+
+GtkCssValues *gtk_css_values_new   (GtkCssValuesType  type);
+GtkCssValues *gtk_css_values_ref   (GtkCssValues     *values);
+void          gtk_css_values_unref (GtkCssValues     *values);
+GtkCssValues *gtk_css_values_copy  (GtkCssValues     *values);
+
+
 G_END_DECLS
 
 #endif /* __GTK_CSS_STYLE_PRIVATE_H__ */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]