[gtk+/wip/cssvalue: 2/3] css: Use GtkCssValues instead of GValue in the css machinery



commit 7603e6e47395b8e1d66522a22255637fa10d3a47
Author: Alexander Larsson <alexl redhat com>
Date:   Tue Mar 6 14:16:32 2012 +0100

    css: Use GtkCssValues instead of GValue in the css machinery
    
    Also, in places where we're computing a new CssValue based on an
    old one, make sure that if nothing changes we're returning a reference
    to the old one, rather than creating a new identical instance.

 gtk/gtkborderimage.c                 |    9 +--
 gtk/gtkcsscomputedvalues.c           |   60 +++++----------
 gtk/gtkcsscomputedvaluesprivate.h    |   11 ++--
 gtk/gtkcsscustomproperty.c           |   37 +++++-----
 gtk/gtkcsslookup.c                   |    8 +-
 gtk/gtkcsslookupprivate.h            |    4 +-
 gtk/gtkcssprovider.c                 |   32 ++++-----
 gtk/gtkcssshorthandproperty.c        |    5 +-
 gtk/gtkcssshorthandpropertyimpl.c    |   54 +++++++-------
 gtk/gtkcssshorthandpropertyprivate.h |    3 +-
 gtk/gtkcssstylefuncs.c               |   94 ++++++++++++-------------
 gtk/gtkcssstylefuncsprivate.h        |    7 +-
 gtk/gtkcssstyleproperty.c            |   90 ++++++++++++------------
 gtk/gtkcssstylepropertyimpl.c        |  130 ++++++++++++++++++----------------
 gtk/gtkcssstylepropertyprivate.h     |   16 ++---
 gtk/gtkcsstypes.c                    |    8 ++-
 gtk/gtkcsstypesprivate.h             |    2 +-
 gtk/gtkstylecontext.c                |   21 +++---
 gtk/gtkstylecontextprivate.h         |    3 +-
 gtk/gtkstyleproperties.c             |   92 ++++++++++--------------
 gtk/gtkstylepropertiesprivate.h      |    4 +-
 gtk/gtkstyleproperty.c               |   12 +--
 gtk/gtkstylepropertyprivate.h        |   11 ++--
 gtk/gtkthemingbackground.c           |    4 +-
 gtk/gtkthemingengine.c               |   10 ++--
 gtk/gtkthemingengineprivate.h        |    3 +-
 26 files changed, 346 insertions(+), 384 deletions(-)
---
diff --git a/gtk/gtkborderimage.c b/gtk/gtkborderimage.c
index e43abc6..a05c9d5 100644
--- a/gtk/gtkborderimage.c
+++ b/gtk/gtkborderimage.c
@@ -39,12 +39,12 @@ _gtk_border_image_init (GtkBorderImage   *image,
 {
   GtkBorder *width;
 
-  image->source = g_value_get_object (_gtk_theming_engine_peek_property (engine, "border-image-source"));
+  image->source = _gtk_css_value_get_object (_gtk_theming_engine_peek_property (engine, "border-image-source"));
   if (image->source == NULL)
     return FALSE;
 
-  image->slice = *(GtkBorder *) g_value_get_boxed (_gtk_theming_engine_peek_property (engine, "border-image-slice"));
-  width = g_value_get_boxed (_gtk_theming_engine_peek_property (engine, "border-image-width"));
+  image->slice = *(GtkBorder *) _gtk_css_value_get_boxed (_gtk_theming_engine_peek_property (engine, "border-image-slice"));
+  width = _gtk_css_value_get_boxed (_gtk_theming_engine_peek_property (engine, "border-image-width"));
   if (width)
     {
       image->width = *width;
@@ -53,8 +53,7 @@ _gtk_border_image_init (GtkBorderImage   *image,
   else
     image->has_width = FALSE;
 
-  image->repeat = *(GtkCssBorderImageRepeat *) g_value_get_boxed (
-      _gtk_theming_engine_peek_property (engine, "border-image-repeat"));
+  image->repeat = *_gtk_css_value_get_border_image_repeat (_gtk_theming_engine_peek_property (engine, "border-image-repeat"));
 
   return TRUE;
 }
diff --git a/gtk/gtkcsscomputedvalues.c b/gtk/gtkcsscomputedvalues.c
index 0eee9b6..305ff4f 100644
--- a/gtk/gtkcsscomputedvalues.c
+++ b/gtk/gtkcsscomputedvalues.c
@@ -34,7 +34,7 @@ gtk_css_computed_values_dispose (GObject *object)
 
   if (values->values)
     {
-      g_array_free (values->values, TRUE);
+      g_ptr_array_unref (values->values);
       values->values = NULL;
     }
   if (values->sections)
@@ -77,7 +77,7 @@ void
 _gtk_css_computed_values_compute_value (GtkCssComputedValues *values,
                                         GtkStyleContext      *context,
                                         guint                 id,
-                                        const GValue         *specified,
+                                        GtkCssValue          *specified,
                                         GtkCssSection        *section)
 {
   GtkCssStyleProperty *prop;
@@ -85,18 +85,14 @@ _gtk_css_computed_values_compute_value (GtkCssComputedValues *values,
 
   g_return_if_fail (GTK_IS_CSS_COMPUTED_VALUES (values));
   g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
-  g_return_if_fail (specified == NULL || G_IS_VALUE (specified));
 
   prop = _gtk_css_style_property_lookup_by_id (id);
   parent = gtk_style_context_get_parent (context);
 
   if (values->values == NULL)
-    {
-      values->values = g_array_new (FALSE, TRUE, sizeof (GValue));
-      g_array_set_clear_func (values->values, (GDestroyNotify) g_value_unset);
-    }
+    values->values = g_ptr_array_new_with_free_func ((GDestroyNotify)_gtk_css_value_unref);
   if (id <= values->values->len)
-   g_array_set_size (values->values, id + 1);
+   g_ptr_array_set_size (values->values, id + 1);
 
   /* http://www.w3.org/TR/css3-cascade/#cascade
    * Then, for every element, the value for each property can be found
@@ -105,9 +101,9 @@ _gtk_css_computed_values_compute_value (GtkCssComputedValues *values,
    */
   if (specified != NULL)
     {
-      if (G_VALUE_HOLDS (specified, GTK_TYPE_CSS_SPECIAL_VALUE))
+      if (_gtk_css_value_is_special (specified))
         {
-          switch (g_value_get_enum (specified))
+          switch (_gtk_css_value_get_special_kind (specified))
             {
             case GTK_CSS_INHERIT:
               /* 3) if the value of the winning declaration is âinheritâ,
@@ -159,20 +155,19 @@ _gtk_css_computed_values_compute_value (GtkCssComputedValues *values,
 
   if (specified)
     {
-      _gtk_css_style_property_compute_value (prop,
-                                             &g_array_index (values->values, GValue, id),
-                                             context,
-                                             specified);
+      g_ptr_array_index (values->values, id) =
+	_gtk_css_style_property_compute_value (prop,
+					       context,
+					       specified);
     }
   else
     {
-      const GValue *parent_value;
-      GValue *value = &g_array_index (values->values, GValue, id);
+      GtkCssValue *parent_value;
       /* Set NULL here and do the inheritance upon lookup? */
       parent_value = _gtk_style_context_peek_property (parent,
                                                        _gtk_style_property_get_name (GTK_STYLE_PROPERTY (prop)));
-      g_value_init (value, G_VALUE_TYPE (parent_value));
-      g_value_copy (parent_value, value);
+
+      g_ptr_array_index (values->values, id) = _gtk_css_value_ref (parent_value);
     }
 
   if (section)
@@ -189,26 +184,17 @@ _gtk_css_computed_values_compute_value (GtkCssComputedValues *values,
 void
 _gtk_css_computed_values_set_value (GtkCssComputedValues *values,
                                     guint                 id,
-                                    const GValue         *value,
+                                    GtkCssValue          *value,
                                     GtkCssSection        *section)
 {
-  GValue *set;
-
   g_return_if_fail (GTK_IS_CSS_COMPUTED_VALUES (values));
-  g_return_if_fail (value == NULL || G_IS_VALUE (value));
 
   if (values->values == NULL)
-    {
-      values->values = g_array_new (FALSE, TRUE, sizeof (GValue));
-      g_array_set_clear_func (values->values, (GDestroyNotify) g_value_unset);
-    }
+    values->values = g_ptr_array_new_with_free_func ((GDestroyNotify)_gtk_css_value_unref);
   if (id <= values->values->len)
-   g_array_set_size (values->values, id + 1);
-
+   g_ptr_array_set_size (values->values, id + 1);
 
-  set = &g_array_index (values->values, GValue, id);
-  g_value_init (set, G_VALUE_TYPE (value));
-  g_value_copy (value, set);
+  g_ptr_array_index (values->values, id) = _gtk_css_value_ref (value);
 
   if (section)
     {
@@ -221,26 +207,20 @@ _gtk_css_computed_values_set_value (GtkCssComputedValues *values,
     }
 }
 
-const GValue *
+GtkCssValue *
 _gtk_css_computed_values_get_value (GtkCssComputedValues *values,
                                     guint                 id)
 {
-  const GValue *v;
-
   g_return_val_if_fail (GTK_IS_CSS_COMPUTED_VALUES (values), NULL);
 
   if (values->values == NULL ||
       id >= values->values->len)
     return NULL;
 
-  v = &g_array_index (values->values, GValue, id);
-  if (!G_IS_VALUE (v))
-    return NULL;
-
-  return v;
+  return g_ptr_array_index (values->values, id);
 }
 
-const GValue *
+GtkCssValue *
 _gtk_css_computed_values_get_value_by_name (GtkCssComputedValues *values,
                                             const char           *name)
 {
diff --git a/gtk/gtkcsscomputedvaluesprivate.h b/gtk/gtkcsscomputedvaluesprivate.h
index f520641..1b4dc132 100644
--- a/gtk/gtkcsscomputedvaluesprivate.h
+++ b/gtk/gtkcsscomputedvaluesprivate.h
@@ -24,6 +24,7 @@
 
 #include "gtk/gtkcsssection.h"
 #include "gtk/gtkstylecontext.h"
+#include "gtk/gtkcssvalueprivate.h"
 
 G_BEGIN_DECLS
 
@@ -41,7 +42,7 @@ struct _GtkCssComputedValues
 {
   GObject parent;
 
-  GArray                *values;
+  GPtrArray              *values;
   GPtrArray             *sections;
 };
 
@@ -57,16 +58,16 @@ GtkCssComputedValues *  _gtk_css_computed_values_new                  (void);
 void                    _gtk_css_computed_values_compute_value        (GtkCssComputedValues     *values,
                                                                        GtkStyleContext          *context,
                                                                        guint                     id,
-                                                                       const GValue             *specified,
+                                                                       GtkCssValue              *specified,
                                                                        GtkCssSection            *section);
 void                    _gtk_css_computed_values_set_value            (GtkCssComputedValues     *values,
                                                                        guint                     id,
-                                                                       const GValue             *value,
+                                                                       GtkCssValue              *value,
                                                                        GtkCssSection            *section);
                                                                         
-const GValue *          _gtk_css_computed_values_get_value            (GtkCssComputedValues     *values,
+GtkCssValue *           _gtk_css_computed_values_get_value            (GtkCssComputedValues     *values,
                                                                        guint                     id);
-const GValue *          _gtk_css_computed_values_get_value_by_name    (GtkCssComputedValues     *values,
+GtkCssValue *           _gtk_css_computed_values_get_value_by_name    (GtkCssComputedValues     *values,
                                                                        const char               *name);
 GtkCssSection *         _gtk_css_computed_values_get_section          (GtkCssComputedValues     *values,
                                                                        guint                     id);
diff --git a/gtk/gtkcsscustomproperty.c b/gtk/gtkcsscustomproperty.c
index a7009f8..179705b 100644
--- a/gtk/gtkcsscustomproperty.c
+++ b/gtk/gtkcsscustomproperty.c
@@ -91,29 +91,32 @@ gtk_css_custom_property_get_specified_type (GParamSpec *pspec)
     return pspec->value_type;
 }
 
-static void
-gtk_css_custom_property_create_initial_value (GParamSpec *pspec,
-                                              GValue     *value)
+static GtkCssValue *
+gtk_css_custom_property_create_initial_value (GParamSpec *pspec)
 {
-  g_value_init (value, gtk_css_custom_property_get_specified_type (pspec));
+  GValue value = G_VALUE_INIT;
+
+  g_value_init (&value, gtk_css_custom_property_get_specified_type (pspec));
 
   if (pspec->value_type == GTK_TYPE_THEMING_ENGINE)
-    g_value_set_object (value, gtk_theming_engine_load (NULL));
+    g_value_set_object (&value, gtk_theming_engine_load (NULL));
   else if (pspec->value_type == PANGO_TYPE_FONT_DESCRIPTION)
-    g_value_take_boxed (value, pango_font_description_from_string ("Sans 10"));
+    g_value_take_boxed (&value, pango_font_description_from_string ("Sans 10"));
   else if (pspec->value_type == GDK_TYPE_RGBA ||
            pspec->value_type == GDK_TYPE_COLOR)
     {
       GdkRGBA color;
       gdk_rgba_parse (&color, "pink");
-      g_value_take_boxed (value, gtk_symbolic_color_new_literal (&color));
+      g_value_take_boxed (&value, gtk_symbolic_color_new_literal (&color));
     }
   else if (pspec->value_type == GTK_TYPE_BORDER)
     {
-      g_value_take_boxed (value, gtk_border_new ());
+      g_value_take_boxed (&value, gtk_border_new ());
     }
   else
-    g_param_value_set_default (pspec, value);
+    g_param_value_set_default (pspec, &value);
+
+  return _gtk_css_value_new_take_gvalue (&value);
 }
 
 /* Property registration functions */
@@ -164,7 +167,7 @@ gtk_theming_engine_register_property (const gchar            *name_space,
                                       GParamSpec             *pspec)
 {
   GtkCssCustomProperty *node;
-  GValue initial = { 0, };
+  GtkCssValue *initial;
   gchar *name;
 
   g_return_if_fail (name_space != NULL);
@@ -172,10 +175,10 @@ gtk_theming_engine_register_property (const gchar            *name_space,
   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
 
   name = g_strdup_printf ("-%s-%s", name_space, pspec->name);
-  gtk_css_custom_property_create_initial_value (pspec, &initial);
+  initial = gtk_css_custom_property_create_initial_value (pspec);
 
   node = g_object_new (GTK_TYPE_CSS_CUSTOM_PROPERTY,
-                       "initial-value", &initial,
+                       "initial-value", initial,
                        "name", name,
                        "computed-type", pspec->value_type,
                        "value-type", pspec->value_type,
@@ -183,7 +186,7 @@ gtk_theming_engine_register_property (const gchar            *name_space,
   node->pspec = pspec;
   node->property_parse_func = parse_func;
 
-  g_value_unset (&initial);
+  _gtk_css_value_unref (initial);
   g_free (name);
 }
 
@@ -204,14 +207,14 @@ gtk_style_properties_register_property (GtkStylePropertyParser  parse_func,
                                         GParamSpec             *pspec)
 {
   GtkCssCustomProperty *node;
-  GValue initial = { 0, };
+  GtkCssValue *initial;
 
   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
 
-  gtk_css_custom_property_create_initial_value (pspec, &initial);
+  initial = gtk_css_custom_property_create_initial_value (pspec);
 
   node = g_object_new (GTK_TYPE_CSS_CUSTOM_PROPERTY,
-                       "initial-value", &initial,
+                       "initial-value", initial,
                        "name", pspec->name,
                        "computed-type", pspec->value_type,
                        "value-type", pspec->value_type,
@@ -219,7 +222,7 @@ gtk_style_properties_register_property (GtkStylePropertyParser  parse_func,
   node->pspec = pspec;
   node->property_parse_func = parse_func;
 
-  g_value_unset (&initial);
+  _gtk_css_value_unref (initial);
 }
 
 /**
diff --git a/gtk/gtkcsslookup.c b/gtk/gtkcsslookup.c
index a40e2df..940f68c 100644
--- a/gtk/gtkcsslookup.c
+++ b/gtk/gtkcsslookup.c
@@ -26,8 +26,8 @@
 
 typedef struct {
   GtkCssSection     *section;
-  const GValue      *value;
-  const GValue      *computed;
+  GtkCssValue       *value;
+  GtkCssValue       *computed;
 } GtkCssLookupValue;
 
 struct _GtkCssLookup {
@@ -91,7 +91,7 @@ void
 _gtk_css_lookup_set (GtkCssLookup  *lookup,
                      guint          id,
                      GtkCssSection *section,
-                     const GValue  *value)
+                     GtkCssValue   *value)
 {
   g_return_if_fail (lookup != NULL);
   g_return_if_fail (_gtk_bitmask_get (lookup->missing, id));
@@ -125,7 +125,7 @@ void
 _gtk_css_lookup_set_computed (GtkCssLookup  *lookup,
                               guint          id,
                               GtkCssSection *section,
-                              const GValue  *value)
+                              GtkCssValue  *value)
 {
   g_return_if_fail (lookup != NULL);
   g_return_if_fail (_gtk_bitmask_get (lookup->missing, id));
diff --git a/gtk/gtkcsslookupprivate.h b/gtk/gtkcsslookupprivate.h
index 99d9467..3e8824c 100644
--- a/gtk/gtkcsslookupprivate.h
+++ b/gtk/gtkcsslookupprivate.h
@@ -38,11 +38,11 @@ gboolean                _gtk_css_lookup_is_missing              (const GtkCssLoo
 void                    _gtk_css_lookup_set                     (GtkCssLookup       *lookup,
                                                                  guint               id,
                                                                  GtkCssSection      *section,
-                                                                 const GValue       *value);
+                                                                 GtkCssValue        *value);
 void                    _gtk_css_lookup_set_computed            (GtkCssLookup       *lookup,
                                                                  guint               id,
                                                                  GtkCssSection      *section,
-                                                                 const GValue       *value);
+                                                                 GtkCssValue        *value);
 void                    _gtk_css_lookup_resolve                 (GtkCssLookup       *lookup,
                                                                  GtkStyleContext    *context,
                                                                  GtkCssComputedValues *values);
diff --git a/gtk/gtkcssprovider.c b/gtk/gtkcssprovider.c
index 250bcb4..1001550 100644
--- a/gtk/gtkcssprovider.c
+++ b/gtk/gtkcssprovider.c
@@ -969,14 +969,14 @@ typedef enum ParserSymbol ParserSymbol;
 
 struct _PropertyValue {
   GtkCssStyleProperty *property;
-  GValue               value;
+  GtkCssValue         *value;
   GtkCssSection       *section;
 };
 
 struct _WidgetPropertyValue {
   char *name;
   WidgetPropertyValue *next;
-  GValue         value;
+  GtkCssValue         *value;
 
   GtkCssSection *section;
 };
@@ -1156,7 +1156,8 @@ gtk_css_ruleset_clear (GtkCssRuleset *ruleset)
 
       for (i = 0; i < ruleset->n_styles; i++)
         {
-          g_value_unset (&ruleset->styles[i].value);
+          _gtk_css_value_unref (ruleset->styles[i].value);
+	  ruleset->styles[i].value = NULL;
           gtk_css_section_unref (ruleset->styles[i].section);
         }
       g_free (ruleset->styles);
@@ -1187,9 +1188,7 @@ widget_property_value_new (char *name, GtkCssSection *section)
 static void
 widget_property_value_free (WidgetPropertyValue *value)
 {
-  if (G_IS_VALUE (&value->value))
-    g_value_unset (&value->value);
-
+  _gtk_css_value_unref (value->value);
   g_free (value->name);
   gtk_css_section_unref (value->section);
 
@@ -1263,7 +1262,8 @@ gtk_css_ruleset_add (GtkCssRuleset       *ruleset,
     {
       if (ruleset->styles[i].property == property)
         {
-          g_value_unset (&ruleset->styles[i].value);
+          _gtk_css_value_unref (ruleset->styles[i].value);
+	  ruleset->styles[i].value = NULL;
           gtk_css_section_unref (ruleset->styles[i].section);
           break;
         }
@@ -1272,12 +1272,11 @@ gtk_css_ruleset_add (GtkCssRuleset       *ruleset,
     {
       ruleset->n_styles++;
       ruleset->styles = g_realloc (ruleset->styles, ruleset->n_styles * sizeof (PropertyValue));
-      memset (&ruleset->styles[i].value, 0, sizeof (GValue));
+      ruleset->styles[i].value = NULL;
       ruleset->styles[i].property = property;
     }
 
-  g_value_init (&ruleset->styles[i].value, G_VALUE_TYPE (value));
-  g_value_copy (value, &ruleset->styles[i].value);
+  ruleset->styles[i].value = _gtk_css_value_new_from_gvalue (value);
   ruleset->styles[i].section = gtk_css_section_ref (section);
 }
 
@@ -1485,7 +1484,7 @@ gtk_css_provider_get_style (GtkStyleProvider *provider,
 	_gtk_style_properties_set_property_by_property (props,
 							GTK_CSS_STYLE_PROPERTY (ruleset->styles[i].property),
 							_gtk_css_selector_get_state_flags (ruleset->selector),
-							&ruleset->styles[i].value);
+							ruleset->styles[i].value);
     }
 
   return props;
@@ -1531,7 +1530,7 @@ gtk_css_provider_get_style_property (GtkStyleProvider *provider,
 					     NULL,
 					     val->section,
 					     gtk_css_section_get_file (val->section),
-					     g_value_get_string (&val->value));
+					     _gtk_css_value_get_string (val->value));
 
 	      found = _gtk_css_style_parse_value (value,
 						  scanner->parser,
@@ -1609,7 +1608,7 @@ gtk_css_style_provider_lookup (GtkStyleProviderPrivate *provider,
           _gtk_css_lookup_set (lookup,
                                id,
                                ruleset->styles[j].section,
-                               &ruleset->styles[j].value);
+                               ruleset->styles[j].value);
         }
     }
 }
@@ -2215,8 +2214,7 @@ parse_declaration (GtkCssScanner *scanner,
           WidgetPropertyValue *val;
 
           val = widget_property_value_new (name, scanner->section);
-          g_value_init (&val->value, G_TYPE_STRING);
-          g_value_take_string (&val->value, value_str);
+	  val->value = _gtk_css_value_new_take_string (value_str);
 
           gtk_css_ruleset_add_style (ruleset, name, val);
         }
@@ -2799,7 +2797,7 @@ gtk_css_ruleset_print (const GtkCssRuleset *ruleset,
           g_string_append (str, "  ");
           g_string_append (str, _gtk_style_property_get_name (GTK_STYLE_PROPERTY (prop->property)));
           g_string_append (str, ": ");
-          _gtk_css_style_property_print_value (prop->property, &prop->value, str);
+          _gtk_css_style_property_print_value (prop->property, prop->value, str);
           g_string_append (str, ";\n");
         }
 
@@ -2822,7 +2820,7 @@ gtk_css_ruleset_print (const GtkCssRuleset *ruleset,
           g_string_append (str, "  ");
           g_string_append (str, widget_value->name);
           g_string_append (str, ": ");
-          g_string_append (str, g_value_get_string (&widget_value->value));
+          g_string_append (str, _gtk_css_value_get_string (widget_value->value));
           g_string_append (str, ";\n");
         }
 
diff --git a/gtk/gtkcssshorthandproperty.c b/gtk/gtkcssshorthandproperty.c
index 157c946..f961791 100644
--- a/gtk/gtkcssshorthandproperty.c
+++ b/gtk/gtkcssshorthandproperty.c
@@ -72,15 +72,14 @@ _gtk_css_shorthand_property_assign (GtkStyleProperty   *property,
   shorthand->assign (shorthand, props, state, value);
 }
 
-static void
+static GtkCssValue *
 _gtk_css_shorthand_property_query (GtkStyleProperty   *property,
-                                   GValue             *value,
                                    GtkStyleQueryFunc   query_func,
                                    gpointer            query_data)
 {
   GtkCssShorthandProperty *shorthand = GTK_CSS_SHORTHAND_PROPERTY (property);
 
-  shorthand->query (shorthand, value, query_func, query_data);
+  return shorthand->query (shorthand, query_func, query_data);
 }
 
 static void
diff --git a/gtk/gtkcssshorthandpropertyimpl.c b/gtk/gtkcssshorthandpropertyimpl.c
index 74e75ff..9684dc4 100644
--- a/gtk/gtkcssshorthandpropertyimpl.c
+++ b/gtk/gtkcssshorthandpropertyimpl.c
@@ -31,6 +31,7 @@
 #include "gtkstylepropertiesprivate.h"
 #include "gtksymboliccolorprivate.h"
 #include "gtktypebuiltins.h"
+#include "gtkcssvalueprivate.h"
 
 /* this is in case round() is not provided by the compiler, 
  * such as in the case of C89 compilers, like MSVC
@@ -608,34 +609,33 @@ unpack_border (GtkCssShorthandProperty *shorthand,
   g_value_unset (&v);
 }
 
-static void
+static GtkCssValue *
 pack_border (GtkCssShorthandProperty *shorthand,
-             GValue                  *value,
              GtkStyleQueryFunc        query_func,
              gpointer                 query_data)
 {
   GtkCssStyleProperty *prop;
   GtkBorder border;
-  const GValue *v;
+  GtkCssValue *v;
 
   prop = _gtk_css_shorthand_property_get_subproperty (shorthand, 0);
   v = (* query_func) (_gtk_css_style_property_get_id (prop), query_data);
   if (v)
-    border.top = g_value_get_int (v);
+    border.top = _gtk_css_value_get_int (v);
   prop = _gtk_css_shorthand_property_get_subproperty (shorthand, 1);
   v = (* query_func) (_gtk_css_style_property_get_id (prop), query_data);
   if (v)
-    border.right = g_value_get_int (v);
+    border.right = _gtk_css_value_get_int (v);
   prop = _gtk_css_shorthand_property_get_subproperty (shorthand, 2);
   v = (* query_func) (_gtk_css_style_property_get_id (prop), query_data);
   if (v)
-    border.bottom = g_value_get_int (v);
+    border.bottom = _gtk_css_value_get_int (v);
   prop = _gtk_css_shorthand_property_get_subproperty (shorthand, 3);
   v = (* query_func) (_gtk_css_style_property_get_id (prop), query_data);
   if (v)
-    border.left = g_value_get_int (v);
+    border.left = _gtk_css_value_get_int (v);
 
-  g_value_set_boxed (value, &border);
+  return _gtk_css_value_new_from_border (&border);
 }
 
 static void
@@ -659,24 +659,26 @@ unpack_border_radius (GtkCssShorthandProperty *shorthand,
   g_value_unset (&v);
 }
 
-static void
+static GtkCssValue *
 pack_border_radius (GtkCssShorthandProperty *shorthand,
-                    GValue                  *value,
                     GtkStyleQueryFunc        query_func,
                     gpointer                 query_data)
 {
   GtkCssBorderCornerRadius *top_left;
   GtkCssStyleProperty *prop;
-  const GValue *v;
+  GtkCssValue *v;
+  int value = 0;
 
   prop = GTK_CSS_STYLE_PROPERTY (_gtk_style_property_lookup ("border-top-left-radius"));
   v = (* query_func) (_gtk_css_style_property_get_id (prop), query_data);
   if (v)
     {
-      top_left = g_value_get_boxed (v);
+      top_left = _gtk_css_value_get_border_corner_radius (v);
       if (top_left)
-        g_value_set_int (value, top_left->horizontal.value);
+        value = top_left->horizontal.value;
     }
+
+  return _gtk_css_value_new_from_int (value);
 }
 
 static void
@@ -759,21 +761,20 @@ unpack_font_description (GtkCssShorthandProperty *shorthand,
     }
 }
 
-static void
+static GtkCssValue *
 pack_font_description (GtkCssShorthandProperty *shorthand,
-                       GValue                  *value,
                        GtkStyleQueryFunc        query_func,
                        gpointer                 query_data)
 {
   PangoFontDescription *description;
-  const GValue *v;
+  GtkCssValue *v;
 
   description = pango_font_description_new ();
 
   v = (* query_func) (_gtk_css_style_property_get_id (GTK_CSS_STYLE_PROPERTY (_gtk_style_property_lookup ("font-family"))), query_data);
   if (v)
     {
-      const char **families = g_value_get_boxed (v);
+      const char **families = _gtk_css_value_get_strv (v);
       /* xxx: Can we set all the families here somehow? */
       if (families)
         pango_font_description_set_family (description, families[0]);
@@ -781,21 +782,21 @@ pack_font_description (GtkCssShorthandProperty *shorthand,
 
   v = (* query_func) (_gtk_css_style_property_get_id (GTK_CSS_STYLE_PROPERTY (_gtk_style_property_lookup ("font-size"))), query_data);
   if (v)
-    pango_font_description_set_size (description, round (g_value_get_double (v) * PANGO_SCALE));
+    pango_font_description_set_size (description, round (_gtk_css_value_get_double (v) * PANGO_SCALE));
 
   v = (* query_func) (_gtk_css_style_property_get_id (GTK_CSS_STYLE_PROPERTY (_gtk_style_property_lookup ("font-style"))), query_data);
   if (v)
-    pango_font_description_set_style (description, g_value_get_enum (v));
+    pango_font_description_set_style (description, _gtk_css_value_get_pango_style (v));
 
   v = (* query_func) (_gtk_css_style_property_get_id (GTK_CSS_STYLE_PROPERTY (_gtk_style_property_lookup ("font-variant"))), query_data);
   if (v)
-    pango_font_description_set_variant (description, g_value_get_enum (v));
+    pango_font_description_set_variant (description, _gtk_css_value_get_pango_variant (v));
 
   v = (* query_func) (_gtk_css_style_property_get_id (GTK_CSS_STYLE_PROPERTY (_gtk_style_property_lookup ("font-weight"))), query_data);
   if (v)
-    pango_font_description_set_weight (description, g_value_get_enum (v));
+    pango_font_description_set_weight (description, _gtk_css_value_get_pango_weight (v));
 
-  g_value_take_boxed (value, description);
+  return _gtk_css_value_new_take_font_description (description);
 }
 
 static void
@@ -816,14 +817,13 @@ unpack_to_everything (GtkCssShorthandProperty *shorthand,
     }
 }
 
-static void
+static GtkCssValue *
 pack_first_element (GtkCssShorthandProperty *shorthand,
-                    GValue                  *value,
                     GtkStyleQueryFunc        query_func,
                     gpointer                 query_data)
 {
   GtkCssStyleProperty *prop;
-  const GValue *v;
+  GtkCssValue *v;
   guint i;
 
   /* NB: This is a fallback for properties that originally were
@@ -837,10 +837,10 @@ pack_first_element (GtkCssShorthandProperty *shorthand,
       v = (* query_func) (_gtk_css_style_property_get_id (prop), query_data);
       if (v)
         {
-          g_value_copy (v, value);
-          return;
+          return _gtk_css_value_ref (v);
         }
     }
+  return NULL;
 }
 
 static void
diff --git a/gtk/gtkcssshorthandpropertyprivate.h b/gtk/gtkcssshorthandpropertyprivate.h
index 4592949..9a79a3d 100644
--- a/gtk/gtkcssshorthandpropertyprivate.h
+++ b/gtk/gtkcssshorthandpropertyprivate.h
@@ -46,8 +46,7 @@ typedef void                  (* GtkCssShorthandPropertyAssignFunc)     (GtkCssS
                                                                          GtkStyleProperties      *props,
                                                                          GtkStateFlags            state,
                                                                          const GValue            *value);
-typedef void                  (* GtkCssShorthandPropertyQueryFunc)      (GtkCssShorthandProperty *shorthand,
-                                                                         GValue                  *value,
+typedef GtkCssValue *         (* GtkCssShorthandPropertyQueryFunc)      (GtkCssShorthandProperty *shorthand,
                                                                          GtkStyleQueryFunc        query_func,
                                                                          gpointer                 query_data);
 
diff --git a/gtk/gtkcssstylefuncs.c b/gtk/gtkcssstylefuncs.c
index e2ccd75..b1e373e 100644
--- a/gtk/gtkcssstylefuncs.c
+++ b/gtk/gtkcssstylefuncs.c
@@ -54,9 +54,8 @@ typedef gboolean         (* GtkStyleParseFunc)             (GtkCssParser
                                                             GValue                 *value);
 typedef void             (* GtkStylePrintFunc)             (const GValue           *value,
                                                             GString                *string);
-typedef void             (* GtkStyleComputeFunc)           (GValue                 *computed,
-                                                            GtkStyleContext        *context,
-                                                            const GValue           *specified);
+typedef GtkCssValue *    (* GtkStyleComputeFunc)           (GtkStyleContext        *context,
+                                                            GtkCssValue            *specified);
 
 static void
 register_conversion_function (GType               type,
@@ -212,31 +211,31 @@ rgba_value_print (const GValue *value,
     }
 }
 
-static void
-rgba_value_compute (GValue          *computed,
-                    GtkStyleContext *context,
-                    const GValue    *specified)
+static GtkCssValue *
+rgba_value_compute (GtkStyleContext *context,
+                    GtkCssValue    *specified)
 {
   GdkRGBA rgba, white = { 1, 1, 1, 1 };
-
-  if (G_VALUE_HOLDS (specified, GTK_TYPE_CSS_SPECIAL_VALUE))
+  
+  if (_gtk_css_value_holds (specified, GTK_TYPE_CSS_SPECIAL_VALUE))
     {
+      return _gtk_css_value_new_from_rgba (NULL);
     }
-  else if (G_VALUE_HOLDS (specified, GTK_TYPE_SYMBOLIC_COLOR))
+  else if (_gtk_css_value_holds (specified, GTK_TYPE_SYMBOLIC_COLOR))
     {
-      GtkSymbolicColor *symbolic = g_value_get_boxed (specified);
-      
+      GtkSymbolicColor *symbolic = _gtk_css_value_get_symbolic_color (specified);
+
       if (symbolic == _gtk_symbolic_color_get_current_color ())
-        g_value_copy (_gtk_style_context_peek_property (context, "color"), computed);
+        return _gtk_css_value_ref (_gtk_style_context_peek_property (context, "color"));
       else if (_gtk_style_context_resolve_color (context,
                                                  symbolic,
                                                  &rgba))
-        g_value_set_boxed (computed, &rgba);
+	return _gtk_css_value_new_from_rgba (&rgba);
       else
-        g_value_set_boxed (computed, &white);
+	return _gtk_css_value_new_from_rgba (&white);
     }
   else
-    g_value_copy (specified, computed);
+    return _gtk_css_value_ref (specified);
 }
 
 static gboolean 
@@ -287,18 +286,17 @@ color_value_print (const GValue *value,
     }
 }
 
-static void
-color_value_compute (GValue          *computed,
-                     GtkStyleContext *context,
-                     const GValue    *specified)
+static GtkCssValue *
+color_value_compute (GtkStyleContext *context,
+                     GtkCssValue    *specified)
 {
   GdkRGBA rgba;
   GdkColor color = { 0, 65535, 65535, 65535 };
 
-  if (G_VALUE_HOLDS (specified, GTK_TYPE_SYMBOLIC_COLOR))
+  if (_gtk_css_value_holds (specified, GTK_TYPE_SYMBOLIC_COLOR))
     {
       if (_gtk_style_context_resolve_color (context,
-                                            g_value_get_boxed (specified),
+                                            _gtk_css_value_get_symbolic_color (specified),
                                             &rgba))
         {
           color.red = rgba.red * 65535. + 0.5;
@@ -306,10 +304,10 @@ color_value_compute (GValue          *computed,
           color.blue = rgba.blue * 65535. + 0.5;
         }
       
-      g_value_set_boxed (computed, &color);
+      return _gtk_css_value_new_from_color (&color);
     }
   else
-    g_value_copy (specified, computed);
+    return _gtk_css_value_ref (specified);
 }
 
 static gboolean
@@ -877,21 +875,20 @@ pattern_value_print (const GValue *value,
     }
 }
 
-static void
-pattern_value_compute (GValue          *computed,
-                       GtkStyleContext *context,
-                       const GValue    *specified)
+static GtkCssValue *
+pattern_value_compute (GtkStyleContext *context,
+                       GtkCssValue     *specified)
 {
-  if (G_VALUE_HOLDS (specified, GTK_TYPE_GRADIENT))
+  if (_gtk_css_value_holds (specified, GTK_TYPE_GRADIENT))
     {
       cairo_pattern_t *gradient;
       
-      gradient = gtk_gradient_resolve_for_context (g_value_get_boxed (specified), context);
+      gradient = gtk_gradient_resolve_for_context (_gtk_css_value_get_gradient (specified), context);
 
-      g_value_take_boxed (computed, gradient);
+      return _gtk_css_value_new_take_pattern (gradient);
     }
   else
-    g_value_copy (specified, computed);
+    return _gtk_css_value_ref (specified);
 }
 
 static gboolean
@@ -996,18 +993,17 @@ shadow_value_print (const GValue *value,
     _gtk_shadow_print (shadow, string);
 }
 
-static void
-shadow_value_compute (GValue          *computed,
-                      GtkStyleContext *context,
-                      const GValue    *specified)
+static GtkCssValue *
+shadow_value_compute (GtkStyleContext *context,
+                      GtkCssValue     *specified)
 {
   GtkShadow *shadow;
-
-  shadow = g_value_get_boxed (specified);
+  
+  shadow = _gtk_css_value_get_shadow (specified);
   if (shadow)
     shadow = _gtk_shadow_resolve (shadow, context);
 
-  g_value_take_boxed (computed, shadow);
+  return _gtk_css_value_new_take_shadow (shadow);
 }
 
 static gboolean
@@ -1337,28 +1333,26 @@ _gtk_css_style_print_value (const GValue *value,
  * @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)
+GtkCssValue *
+_gtk_css_style_compute_value (GtkStyleContext *context,
+			      GType           target_type,
+                              GtkCssValue    *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));
+  g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
 
   gtk_css_style_funcs_init ();
 
   func = g_hash_table_lookup (compute_funcs,
-                              GSIZE_TO_POINTER (G_VALUE_TYPE (computed)));
+                              GSIZE_TO_POINTER (target_type));
   if (func == NULL)
     func = g_hash_table_lookup (compute_funcs,
-                                GSIZE_TO_POINTER (g_type_fundamental (G_VALUE_TYPE (computed))));
+                                GSIZE_TO_POINTER (g_type_fundamental (target_type)));
 
   if (func)
-    func (computed, context, specified);
+    return func (context, specified);
   else
-    g_value_copy (specified, computed);
+    return _gtk_css_value_ref (specified);
 }
 
diff --git a/gtk/gtkcssstylefuncsprivate.h b/gtk/gtkcssstylefuncsprivate.h
index 2728aa9..647a950 100644
--- a/gtk/gtkcssstylefuncsprivate.h
+++ b/gtk/gtkcssstylefuncsprivate.h
@@ -20,6 +20,7 @@
 
 #include "gtkcssparserprivate.h"
 #include "gtkstylecontext.h"
+#include "gtkcssvalueprivate.h"
 
 G_BEGIN_DECLS
 
@@ -28,9 +29,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);
+GtkCssValue *       _gtk_css_style_compute_value           (GtkStyleContext        *context,
+							    GType                   target_type,
+                                                            GtkCssValue            *specified);
 
 G_END_DECLS
 
diff --git a/gtk/gtkcssstyleproperty.c b/gtk/gtkcssstyleproperty.c
index a0873ec..cbbe606 100644
--- a/gtk/gtkcssstyleproperty.c
+++ b/gtk/gtkcssstyleproperty.c
@@ -67,7 +67,6 @@ gtk_css_style_property_set_property (GObject      *object,
                                      GParamSpec   *pspec)
 {
   GtkCssStyleProperty *property = GTK_CSS_STYLE_PROPERTY (object);
-  const GValue *initial;
 
   switch (prop_id)
     {
@@ -75,10 +74,8 @@ gtk_css_style_property_set_property (GObject      *object,
       property->inherit = g_value_get_boolean (value);
       break;
     case PROP_INITIAL:
-      initial = g_value_get_boxed (value);
-      g_assert (initial);
-      g_value_init (&property->initial_value, G_VALUE_TYPE (initial));
-      g_value_copy (initial, &property->initial_value);
+      property->initial_value = g_value_dup_boxed (value);
+      g_assert (property->initial_value != NULL);
       break;
     case PROP_COMPUTED_TYPE:
       property->computed_type = g_value_get_gtype (value);
@@ -113,7 +110,7 @@ gtk_css_style_property_get_property (GObject    *object,
       g_value_set_boolean (value, property->inherit);
       break;
     case PROP_INITIAL:
-      g_value_set_boxed (value, &property->initial_value);
+      g_value_set_boxed (value, property->initial_value);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -127,35 +124,36 @@ _gtk_css_style_property_assign (GtkStyleProperty   *property,
                                 GtkStateFlags       state,
                                 const GValue       *value)
 {
+  GtkCssValue *css_value = _gtk_css_value_new_from_gvalue (value);
   _gtk_style_properties_set_property_by_property (props,
                                                   GTK_CSS_STYLE_PROPERTY (property),
                                                   state,
-                                                  value);
+                                                  css_value);
+  _gtk_css_value_unref (css_value);
 }
 
-static void
+static GtkCssValue *
 _gtk_css_style_property_query (GtkStyleProperty   *property,
-                               GValue             *value,
                                GtkStyleQueryFunc   query_func,
                                gpointer            query_data)
 {
-  const GValue *val;
+  GtkCssValue *css_value;
   
-  val = (* query_func) (GTK_CSS_STYLE_PROPERTY (property)->id, query_data);
-  if (val)
+  css_value = (* query_func) (GTK_CSS_STYLE_PROPERTY (property)->id, query_data);
+  if (css_value)
     {
       /* Somebody make this a vfunc */
-      if (G_VALUE_TYPE (val) == GTK_TYPE_CSS_IMAGE)
+      if (_gtk_css_value_holds (css_value, GTK_TYPE_CSS_IMAGE))
         {
-          GtkCssImage *image = g_value_get_object (val);
+          GtkCssImage *image = _gtk_css_value_get_image (css_value);
           cairo_pattern_t *pattern;
           cairo_surface_t *surface;
           cairo_matrix_t matrix;
           
           if (image == NULL)
-            g_value_set_boxed (value, NULL);
+	    return _gtk_css_value_new_from_pattern (NULL);
           else if (GTK_IS_CSS_IMAGE_GRADIENT (image))
-            g_value_set_boxed (value, GTK_CSS_IMAGE_GRADIENT (image)->pattern);
+	    return _gtk_css_value_new_from_pattern (GTK_CSS_IMAGE_GRADIENT (image)->pattern);
           else
             {
               double width, height;
@@ -167,18 +165,19 @@ _gtk_css_style_property_query (GtkStyleProperty   *property,
               cairo_matrix_init_scale (&matrix, width, height);
               cairo_pattern_set_matrix (pattern, &matrix);
               cairo_surface_destroy (surface);
-              g_value_take_boxed (value, pattern);
+	      return _gtk_css_value_new_take_pattern (pattern);
             }
         }
-      else if (G_VALUE_TYPE (val) == GTK_TYPE_CSS_NUMBER)
+      else if (_gtk_css_value_holds (css_value, GTK_TYPE_CSS_NUMBER))
         {
-          g_value_set_int (value, round (_gtk_css_number_get (g_value_get_boxed (val), 100)));
+	  int v = round (_gtk_css_number_get (_gtk_css_value_get_number (css_value), 100));
+	  return _gtk_css_value_new_from_int (v);
         }
       else
-        g_value_copy (val, value);
+	return _gtk_css_value_ref (css_value);
     }
   else
-    g_value_copy (_gtk_css_style_property_get_initial_value (GTK_CSS_STYLE_PROPERTY (property)), value);
+    return _gtk_css_value_ref (_gtk_css_style_property_get_initial_value (GTK_CSS_STYLE_PROPERTY (property)));
 }
 
 static gboolean
@@ -264,7 +263,7 @@ _gtk_css_style_property_class_init (GtkCssStylePropertyClass *klass)
                                    g_param_spec_boxed ("initial-value",
                                                        P_("Initial value"),
                                                        P_("The initial specified value used for this property"),
-                                                       G_TYPE_VALUE,
+                                                       GTK_TYPE_CSS_VALUE,
                                                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 
   property_class->assign = _gtk_css_style_property_assign;
@@ -291,13 +290,12 @@ gtk_css_style_property_real_print_value (GtkCssStyleProperty *property,
   _gtk_css_style_print_value (value, string);
 }
 
-static void
+static GtkCssValue *
 gtk_css_style_property_real_compute_value (GtkCssStyleProperty *property,
-                                           GValue              *computed,
                                            GtkStyleContext     *context,
-                                           const GValue        *specified)
+                                           GtkCssValue         *specified)
 {
-  _gtk_css_style_compute_value (computed, context, specified);
+  return _gtk_css_style_compute_value (context, _gtk_css_style_property_get_computed_type (property), specified);
 }
 
 static void
@@ -404,12 +402,12 @@ _gtk_css_style_property_get_id (GtkCssStyleProperty *property)
  *
  * Returns: a reference to the initial value. The value will never change.
  **/
-const GValue *
+GtkCssValue *
 _gtk_css_style_property_get_initial_value (GtkCssStyleProperty *property)
 {
   g_return_val_if_fail (GTK_IS_CSS_STYLE_PROPERTY (property), NULL);
 
-  return &property->initial_value;
+  return property->initial_value;
 }
 
 /**
@@ -448,7 +446,7 @@ _gtk_css_style_property_get_specified_type (GtkCssStyleProperty *property)
 {
   g_return_val_if_fail (GTK_IS_CSS_STYLE_PROPERTY (property), G_TYPE_NONE);
 
-  return G_VALUE_TYPE (&property->initial_value);
+  return _gtk_css_value_get_content_type (property->initial_value);
 }
 
 gboolean
@@ -458,7 +456,7 @@ _gtk_css_style_property_is_specified_type (GtkCssStyleProperty *property,
   g_return_val_if_fail (GTK_IS_CSS_STYLE_PROPERTY (property), FALSE);
 
   /* If it's our specified type, of course it's valid */
-  if (type == G_VALUE_TYPE (&property->initial_value))
+  if (type == _gtk_css_value_get_content_type (property->initial_value))
     return TRUE;
 
   /* The special values 'inherit' and 'initial' are always valid */
@@ -466,7 +464,7 @@ _gtk_css_style_property_is_specified_type (GtkCssStyleProperty *property,
     return TRUE;
 
   /* XXX: Someone needs to fix that legacy */
-  if (G_VALUE_TYPE (&property->initial_value) == CAIRO_GOBJECT_TYPE_PATTERN &&
+  if (_gtk_css_value_holds (property->initial_value, CAIRO_GOBJECT_TYPE_PATTERN) &&
       type == GTK_TYPE_GRADIENT)
     return TRUE;
 
@@ -485,20 +483,15 @@ _gtk_css_style_property_is_specified_type (GtkCssStyleProperty *property,
  * <ulink url="http://www.w3.org/TR/css3-cascade/#computed>
  * the CSS documentation</ulink>.
  **/
-void
+GtkCssValue *
 _gtk_css_style_property_compute_value (GtkCssStyleProperty *property,
-                                       GValue              *computed,
                                        GtkStyleContext     *context,
-                                       const GValue        *specified)
+                                       GtkCssValue         *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_css_style_property_get_computed_type (property));
+  g_return_val_if_fail (GTK_IS_CSS_STYLE_PROPERTY (property), NULL);
+  g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
 
-  property->compute_value (property, computed, context, specified);
+  return property->compute_value (property, context, specified);
 }
 
 /**
@@ -513,26 +506,31 @@ _gtk_css_style_property_compute_value (GtkCssStyleProperty *property,
  **/
 void
 _gtk_css_style_property_print_value (GtkCssStyleProperty    *property,
-                                     const GValue           *value,
+                                     GtkCssValue            *css_value,
                                      GString                *string)
 {
   g_return_if_fail (GTK_IS_CSS_STYLE_PROPERTY (property));
-  g_return_if_fail (value != NULL);
+  g_return_if_fail (css_value != NULL);
   g_return_if_fail (string != NULL);
 
-  if (G_VALUE_HOLDS (value, GTK_TYPE_CSS_SPECIAL_VALUE))
+  if (_gtk_css_value_is_special (css_value))
     {
       GEnumClass *enum_class;
       GEnumValue *enum_value;
 
       enum_class = g_type_class_ref (GTK_TYPE_CSS_SPECIAL_VALUE);
-      enum_value = g_enum_get_value (enum_class, g_value_get_enum (value));
+      enum_value = g_enum_get_value (enum_class, _gtk_css_value_get_special_kind (css_value));
 
       g_string_append (string, enum_value->value_nick);
 
       g_type_class_unref (enum_class);
     }
   else
-    property->print_value (property, value, string);
+    {
+      GValue value = G_VALUE_INIT;
+      _gtk_css_value_init_gvalue (css_value, &value);
+      property->print_value (property, &value, string);
+      g_value_unset (&value);
+    }
 }
 
diff --git a/gtk/gtkcssstylepropertyimpl.c b/gtk/gtkcssstylepropertyimpl.c
index e5e8c08..5d206e3 100644
--- a/gtk/gtkcssstylepropertyimpl.c
+++ b/gtk/gtkcssstylepropertyimpl.c
@@ -62,27 +62,30 @@ gtk_css_style_property_register (const char *                   name,
                                  ...)
 {
   GtkCssStyleProperty *node;
-  GValue initial_value = G_VALUE_INIT;
+  GValue initial_gvalue = G_VALUE_INIT;
+  GtkCssValue *initial_value;
   char *error = NULL;
   va_list args;
 
   va_start (args, compute_value);
-  G_VALUE_COLLECT_INIT (&initial_value, specified_type,
+  G_VALUE_COLLECT_INIT (&initial_gvalue, specified_type,
                         args, 0, &error);
   if (error)
     {
       g_error ("property `%s' initial value is broken: %s", name, error);
-      g_value_unset (&initial_value);
+      g_value_unset (&initial_gvalue);
       return;
     }
 
   va_end (args);
 
+  initial_value = _gtk_css_value_new_take_gvalue (&initial_gvalue);
+
   node = g_object_new (GTK_TYPE_CSS_STYLE_PROPERTY,
                        "value-type", value_type,
                        "computed-type", computed_type,
                        "inherit", (flags & GTK_STYLE_PROPERTY_INHERIT) ? TRUE : FALSE,
-                       "initial-value", &initial_value,
+                       "initial-value", initial_value,
                        "name", name,
                        NULL);
   
@@ -93,7 +96,7 @@ gtk_css_style_property_register (const char *                   name,
   if (compute_value)
     node->compute_value = compute_value;
 
-  g_value_unset (&initial_value);
+  _gtk_css_value_unref (initial_value);
 }
 
 /*** HELPERS ***/
@@ -137,13 +140,12 @@ string_append_string (GString    *str,
 
 /*** IMPLEMENTATIONS ***/
 
-static void
+static GtkCssValue *
 color_compute (GtkCssStyleProperty    *property,
-               GValue                 *computed,
                GtkStyleContext        *context,
-               const GValue           *specified)
+               GtkCssValue            *specified)
 {
-  GtkSymbolicColor *symbolic = g_value_get_boxed (specified);
+  GtkSymbolicColor *symbolic = _gtk_css_value_get_symbolic_color (specified);
   GdkRGBA rgba;
 
   if (symbolic == _gtk_symbolic_color_get_current_color ())
@@ -157,29 +159,28 @@ color_compute (GtkCssStyleProperty    *property,
           GtkStyleContext *parent = gtk_style_context_get_parent (context);
 
           if (parent)
-            g_value_copy (_gtk_style_context_peek_property (parent, "color"), computed);
+            return _gtk_css_value_ref (_gtk_style_context_peek_property (parent, "color"));
           else
-            _gtk_css_style_compute_value (computed,
-                                          context,
-                                          _gtk_css_style_property_get_initial_value (property));
+            return _gtk_css_style_compute_value (context,
+						 GDK_TYPE_RGBA,
+						 _gtk_css_style_property_get_initial_value (property));
         }
       else
         {
-          g_value_copy (_gtk_style_context_peek_property (context, "color"), computed);
+          return _gtk_css_value_ref (_gtk_style_context_peek_property (context, "color"));
         }
     }
   else if (_gtk_style_context_resolve_color (context,
                                              symbolic,
                                              &rgba))
     {
-      g_value_set_boxed (computed, &rgba);
+      return _gtk_css_value_new_from_rgba (&rgba);
     }
   else
     {
-      color_compute (property,
-                     computed,
-                     context,
-                     _gtk_css_style_property_get_initial_value (property));
+      return color_compute (property,
+			    context,
+			    _gtk_css_style_property_get_initial_value (property));
     }
 }
 
@@ -395,18 +396,17 @@ css_image_value_print (GtkCssStyleProperty *property,
     g_string_append (string, "none");
 }
 
-static void
+static GtkCssValue *
 css_image_value_compute (GtkCssStyleProperty    *property,
-                         GValue                 *computed,
                          GtkStyleContext        *context,
-                         const GValue           *specified)
+                         GtkCssValue            *specified)
 {
-  GtkCssImage *image = g_value_get_object (specified);
+  GtkCssImage *image = _gtk_css_value_get_image (specified);
 
   if (image)
     image = _gtk_css_image_compute (image, context);
 
-  g_value_take_object (computed, image);
+  return _gtk_css_value_new_take_image (image);
 }
 
 static gboolean 
@@ -427,18 +427,20 @@ parse_margin (GtkCssStyleProperty *property,
   return TRUE;
 }
 
-static void
+static GtkCssValue *
 compute_margin (GtkCssStyleProperty *property,
-                GValue              *computed,
                 GtkStyleContext     *context,
-                const GValue        *specified)
+                GtkCssValue         *specified)
 {
   GtkCssNumber number;
   
-  _gtk_css_number_compute (&number,
-                           g_value_get_boxed (specified),
-                           context);
-  g_value_set_boxed (computed, &number);
+  if (_gtk_css_number_compute (&number,
+			       _gtk_css_value_get_number (specified),
+			       context))
+    {
+      return _gtk_css_value_new_from_number (&number);
+    }
+  return  _gtk_css_value_ref (specified);
 }
 
 static gboolean 
@@ -460,18 +462,18 @@ parse_padding (GtkCssStyleProperty *property,
   return TRUE;
 }
 
-static void
+static GtkCssValue *
 compute_padding (GtkCssStyleProperty *property,
-                 GValue              *computed,
                  GtkStyleContext     *context,
-                 const GValue        *specified)
+                 GtkCssValue         *specified)
 {
   GtkCssNumber number;
-  
-  _gtk_css_number_compute (&number,
-                           g_value_get_boxed (specified),
-                           context);
-  g_value_set_boxed (computed, &number);
+
+  if (_gtk_css_number_compute (&number,
+			       _gtk_css_value_get_number (specified),
+			       context))
+    return _gtk_css_value_new_from_number (&number);
+  return _gtk_css_value_ref (specified);
 }
 
 static gboolean 
@@ -493,33 +495,36 @@ parse_border_width (GtkCssStyleProperty *property,
   return TRUE;
 }
 
-static void
+static GtkCssValue *
 compute_border_width (GtkCssStyleProperty    *property,
-                      GValue                 *computed,
                       GtkStyleContext        *context,
-                      const GValue           *specified)
+                      GtkCssValue            *specified)
 {
   GtkCssStyleProperty *style;
   GtkBorderStyle border_style;
   GtkCssNumber number;
+  int value = 0;
   
   /* The -1 is magic that is only true because we register the style
    * properties directly after the width properties.
    */
   style = _gtk_css_style_property_lookup_by_id (_gtk_css_style_property_get_id (property) - 1);
-  border_style = g_value_get_enum (_gtk_style_context_peek_property (context, _gtk_style_property_get_name (GTK_STYLE_PROPERTY (style))));
+  
+  border_style = _gtk_css_value_get_border_style (_gtk_style_context_peek_property (context, _gtk_style_property_get_name (GTK_STYLE_PROPERTY (style))));
 
   if (border_style == GTK_BORDER_STYLE_NONE ||
       border_style == GTK_BORDER_STYLE_HIDDEN)
     {
-      g_value_set_int (computed, 0);
-      return;
+      value = 0;
     }
-
-  _gtk_css_number_compute (&number,
-                           g_value_get_boxed (specified),
-                           context);
-  g_value_set_int (computed, round (number.value));
+  else
+    {
+      _gtk_css_number_compute (&number,
+			       _gtk_css_value_get_number (specified),
+			       context);
+      value = round (number.value);
+    }
+  return _gtk_css_value_new_from_int (value);
 }
 
 static gboolean
@@ -656,25 +661,26 @@ background_size_print (GtkCssStyleProperty *property,
     }
 }
 
-static void
+static GtkCssValue *
 background_size_compute (GtkCssStyleProperty    *property,
-                         GValue                 *computed,
                          GtkStyleContext        *context,
-                         const GValue           *specified)
+                         GtkCssValue            *specified)
 {
-  GtkCssBackgroundSize *ssize = g_value_get_boxed (specified);
+  GtkCssBackgroundSize *ssize = _gtk_css_value_get_background_size (specified);
   GtkCssBackgroundSize csize;
+  gboolean changed;
 
   csize.cover = ssize->cover;
   csize.contain = ssize->contain;
-  _gtk_css_number_compute (&csize.width,
-                           &ssize->width,
-                           context);
-  _gtk_css_number_compute (&csize.height,
-                           &ssize->height,
-                           context);
-
-  g_value_set_boxed (computed, &csize);
+  changed = _gtk_css_number_compute (&csize.width,
+				     &ssize->width,
+				     context);
+  changed |= _gtk_css_number_compute (&csize.height,
+				      &ssize->height,
+				      context);
+  if (changed)
+    return _gtk_css_value_new_from_background_size (&csize);
+  return _gtk_css_value_ref (specified);
 }
 
 /*** REGISTRATION ***/
diff --git a/gtk/gtkcssstylepropertyprivate.h b/gtk/gtkcssstylepropertyprivate.h
index 2d75827..a51d455 100644
--- a/gtk/gtkcssstylepropertyprivate.h
+++ b/gtk/gtkcssstylepropertyprivate.h
@@ -41,16 +41,15 @@ typedef gboolean         (* GtkCssStylePropertyParseFunc)  (GtkCssStyleProperty
 typedef void             (* GtkCssStylePropertyPrintFunc)  (GtkCssStyleProperty    *property,
                                                             const GValue           *value,
                                                             GString                *string);
-typedef void             (* GtkCssStylePropertyComputeFunc)(GtkCssStyleProperty    *property,
-                                                            GValue                 *computed,
+typedef GtkCssValue  *   (* GtkCssStylePropertyComputeFunc)(GtkCssStyleProperty    *property,
                                                             GtkStyleContext        *context,
-                                                            const GValue           *specified);
+                                                            GtkCssValue            *specified);
 struct _GtkCssStyleProperty
 {
   GtkStyleProperty parent;
 
   GType computed_type;
-  GValue initial_value;
+  GtkCssValue *initial_value;
   guint id;
   guint inherit :1;
 
@@ -75,20 +74,19 @@ GtkCssStyleProperty *   _gtk_css_style_property_lookup_by_id    (guint
 
 gboolean                _gtk_css_style_property_is_inherit      (GtkCssStyleProperty    *property);
 guint                   _gtk_css_style_property_get_id          (GtkCssStyleProperty    *property);
-const GValue *          _gtk_css_style_property_get_initial_value
+GtkCssValue  *          _gtk_css_style_property_get_initial_value
                                                                 (GtkCssStyleProperty    *property);
 GType                   _gtk_css_style_property_get_computed_type (GtkCssStyleProperty *property);
 GType                   _gtk_css_style_property_get_specified_type (GtkCssStyleProperty *property);
 gboolean                _gtk_css_style_property_is_specified_type (GtkCssStyleProperty  *property,
                                                                  GType                   type);
 
-void                    _gtk_css_style_property_compute_value   (GtkCssStyleProperty    *property,
-                                                                 GValue                 *computed,
+GtkCssValue *           _gtk_css_style_property_compute_value   (GtkCssStyleProperty    *property,
                                                                  GtkStyleContext        *context,
-                                                                 const GValue           *specified);
+                                                                 GtkCssValue            *specified);
 
 void                    _gtk_css_style_property_print_value     (GtkCssStyleProperty    *property,
-                                                                 const GValue           *value,
+                                                                 GtkCssValue            *value,
                                                                  GString                *string);
                                                                  
 
diff --git a/gtk/gtkcsstypes.c b/gtk/gtkcsstypes.c
index ffa7a27..c454fea 100644
--- a/gtk/gtkcsstypes.c
+++ b/gtk/gtkcsstypes.c
@@ -62,7 +62,7 @@ _gtk_css_number_get (const GtkCssNumber *number,
     return number->value;
 }
 
-void
+gboolean
 _gtk_css_number_compute (GtkCssNumber       *dest,
                          const GtkCssNumber *src,
                          GtkStyleContext    *context)
@@ -100,12 +100,12 @@ _gtk_css_number_compute (GtkCssNumber       *dest,
       dest->unit = GTK_CSS_PX;
       break;
     case GTK_CSS_EM:
-      dest->value = src->value * g_value_get_double (_gtk_style_context_peek_property (context, "font-size"));
+      dest->value = src->value * _gtk_css_value_get_double (_gtk_style_context_peek_property (context, "font-size"));
       dest->unit = GTK_CSS_PX;
       break;
     case GTK_CSS_EX:
       /* for now we pretend ex is half of em */
-      dest->value = src->value * g_value_get_double (_gtk_style_context_peek_property (context, "font-size"));
+      dest->value = src->value * _gtk_css_value_get_double (_gtk_style_context_peek_property (context, "font-size"));
       dest->unit = GTK_CSS_PX;
       break;
     case GTK_CSS_RAD:
@@ -121,6 +121,8 @@ _gtk_css_number_compute (GtkCssNumber       *dest,
       dest->unit = GTK_CSS_DEG;
       break;
     }
+
+  return !_gtk_css_number_equal (src, dest);
 }
 
 void
diff --git a/gtk/gtkcsstypesprivate.h b/gtk/gtkcsstypesprivate.h
index 1096994..d481427 100644
--- a/gtk/gtkcsstypesprivate.h
+++ b/gtk/gtkcsstypesprivate.h
@@ -142,7 +142,7 @@ gboolean        _gtk_css_number_equal                           (const GtkCssNum
                                                                  const GtkCssNumber *two);
 double          _gtk_css_number_get                             (const GtkCssNumber *number,
                                                                  double              one_hundred_percent);
-void            _gtk_css_number_compute                         (GtkCssNumber       *dest,
+gboolean        _gtk_css_number_compute                         (GtkCssNumber       *dest,
                                                                  const GtkCssNumber *src,
                                                                  GtkStyleContext    *context);
 void            _gtk_css_number_print                           (const GtkCssNumber *number,
diff --git a/gtk/gtkstylecontext.c b/gtk/gtkstylecontext.c
index a46be6f..42673c3 100644
--- a/gtk/gtkstylecontext.c
+++ b/gtk/gtkstylecontext.c
@@ -1072,7 +1072,7 @@ style_data_lookup (GtkStyleContext *context,
   GtkStyleContextPrivate *priv;
   StyleData *data;
   gboolean state_mismatch;
-  const GValue *v;
+  GtkCssValue *v;
 
   priv = context->priv;
   state_mismatch = ((GtkStyleInfo *) priv->info_stack->data)->state_flags != state;
@@ -1116,7 +1116,7 @@ style_data_lookup (GtkStyleContext *context,
 
   v = _gtk_css_computed_values_get_value_by_name (priv->current_data->store, "engine");
   if (v)
-    priv->theming_engine = g_value_dup_object (v);
+    priv->theming_engine = _gtk_css_value_dup_object (v);
   else
     priv->theming_engine = g_object_ref (gtk_theming_engine_load (NULL));
 
@@ -1440,7 +1440,7 @@ gtk_style_context_get_section (GtkStyleContext *context,
   return _gtk_css_computed_values_get_section (data->store, _gtk_css_style_property_get_id (GTK_CSS_STYLE_PROPERTY (prop)));
 }
 
-static const GValue *
+static GtkCssValue *
 gtk_style_context_query_func (guint    id,
                               gpointer values)
 {
@@ -1470,6 +1470,7 @@ gtk_style_context_get_property (GtkStyleContext *context,
   GtkStyleContextPrivate *priv;
   GtkStyleProperty *prop;
   StyleData *data;
+  GtkCssValue *v;
 
   g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
   g_return_if_fail (property != NULL);
@@ -1491,7 +1492,9 @@ gtk_style_context_get_property (GtkStyleContext *context,
     }
 
   data = style_data_lookup (context, state);
-  _gtk_style_property_query (prop, value, gtk_style_context_query_func, data->store);
+  v = _gtk_style_property_query (prop, gtk_style_context_query_func, data->store);
+  _gtk_css_value_init_gvalue (v, value);
+  _gtk_css_value_unref (v);
 }
 
 /**
@@ -2362,7 +2365,7 @@ style_property_values_cmp (gconstpointer bsearch_node1,
   return 0;
 }
 
-const GValue *
+GtkCssValue *
 _gtk_style_context_peek_property (GtkStyleContext *context,
                                   const char      *property_name)
 {
@@ -2376,10 +2379,10 @@ _gtk_style_context_get_number (GtkStyleContext *context,
                                const char      *property_name,
                                double           one_hundred_percent)
 {
-  const GValue *value;
+  GtkCssValue *value;
   
   value = _gtk_style_context_peek_property (context, property_name);
-  return _gtk_css_number_get (g_value_get_boxed (value), one_hundred_percent);
+  return _gtk_css_number_get (_gtk_css_value_get_number (value), one_hundred_percent);
 }
 
 const GValue *
@@ -3023,7 +3026,7 @@ gtk_style_context_notify_state_change (GtkStyleContext *context,
   GtkAnimationDescription *desc;
   AnimationInfo *info;
   GtkStateFlags flags;
-  const GValue *v;
+  GtkCssValue *v;
   StyleData *data;
 
   g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
@@ -3068,7 +3071,7 @@ gtk_style_context_notify_state_change (GtkStyleContext *context,
   v = _gtk_css_computed_values_get_value_by_name (data->store, "transition");
   if (!v)
     return;
-  desc = g_value_get_boxed (v);
+  desc = _gtk_css_value_get_boxed (v);
   if (!desc)
     return;
 
diff --git a/gtk/gtkstylecontextprivate.h b/gtk/gtkstylecontextprivate.h
index a5933c3..06efa0f 100644
--- a/gtk/gtkstylecontextprivate.h
+++ b/gtk/gtkstylecontextprivate.h
@@ -20,10 +20,11 @@
 
 #include "gtkstylecontext.h"
 #include "gtksymboliccolor.h"
+#include "gtkcssvalueprivate.h"
 
 G_BEGIN_DECLS
 
-const GValue * _gtk_style_context_peek_property              (GtkStyleContext *context,
+GtkCssValue   * _gtk_style_context_peek_property              (GtkStyleContext *context,
                                                               const char      *property_name);
 double         _gtk_style_context_get_number                 (GtkStyleContext *context,
                                                               const char      *property_name,
diff --git a/gtk/gtkstyleproperties.c b/gtk/gtkstyleproperties.c
index 362f384..e73e74b 100644
--- a/gtk/gtkstyleproperties.c
+++ b/gtk/gtkstyleproperties.c
@@ -65,7 +65,7 @@ typedef struct ValueData ValueData;
 struct ValueData
 {
   GtkStateFlags state;
-  GValue value;
+  GtkCssValue *value;
 };
 
 struct PropertyData
@@ -122,8 +122,8 @@ property_data_remove_values (PropertyData *data)
 
       value_data = &g_array_index (data->values, ValueData, i);
 
-      if (G_IS_VALUE (&value_data->value))
-        g_value_unset (&value_data->value);
+      _gtk_css_value_unref (value_data->value);
+      value_data->value = NULL;
     }
 
   if (data->values->len > 0)
@@ -188,11 +188,10 @@ property_data_find_position (PropertyData  *data,
   return found;
 }
 
-static GValue *
+static ValueData *
 property_data_get_value (PropertyData  *data,
                          GtkStateFlags  state)
 {
-  ValueData *val_data;
   guint pos;
 
   if (!property_data_find_position (data, state, &pos))
@@ -203,12 +202,10 @@ property_data_get_value (PropertyData  *data,
       g_array_insert_val (data->values, pos, new);
     }
 
-  val_data = &g_array_index (data->values, ValueData, pos);
-
-  return &val_data->value;
+  return &g_array_index (data->values, ValueData, pos);
 }
 
-static GValue *
+static GtkCssValue *
 property_data_match_state (PropertyData  *data,
                            GtkStateFlags  state)
 {
@@ -221,7 +218,7 @@ property_data_match_state (PropertyData  *data,
 
       /* Exact match */
       val_data = &g_array_index (data->values, ValueData, pos);
-      return &val_data->value;
+      return val_data->value;
     }
 
   if (pos >= data->values->len)
@@ -248,7 +245,7 @@ property_data_match_state (PropertyData  *data,
       if (val_data->state == 0 ||
           ((val_data->state & state) != 0 &&
            (val_data->state & ~state) == 0))
-        return &val_data->value;
+        return val_data->value;
     }
 
   return NULL;
@@ -325,7 +322,7 @@ gtk_style_properties_provider_lookup (GtkStyleProviderPrivate *provider,
     {
       GtkCssStyleProperty *prop = key;
       PropertyData *data = value;
-      const GValue *value;
+      GtkCssValue *value;
       guint id;
 
       id = _gtk_css_style_property_get_id (prop);
@@ -431,13 +428,13 @@ void
 _gtk_style_properties_set_property_by_property (GtkStyleProperties  *props,
                                                 GtkCssStyleProperty *style_prop,
                                                 GtkStateFlags        state,
-                                                const GValue        *value)
+                                                GtkCssValue         *value)
 {
   GtkStylePropertiesPrivate *priv;
   PropertyData *prop;
-  GValue *val;
+  ValueData *val;
 
-  g_return_if_fail (G_VALUE_TYPE (value) == _gtk_css_style_property_get_computed_type (style_prop));
+  g_return_if_fail (_gtk_css_value_holds (value, _gtk_css_style_property_get_computed_type (style_prop)));
 
   priv = props->priv;
   prop = g_hash_table_lookup (priv->properties, style_prop);
@@ -450,17 +447,8 @@ _gtk_style_properties_set_property_by_property (GtkStyleProperties  *props,
 
   val = property_data_get_value (prop, state);
 
-  if (G_VALUE_TYPE (val) == G_VALUE_TYPE (value))
-    g_value_reset (val);
-  else
-    {
-      if (G_IS_VALUE (val))
-        g_value_unset (val);
-
-      g_value_init (val, G_VALUE_TYPE (value));
-    }
-
-  g_value_copy (value, val);
+  _gtk_css_value_unref (val->value);
+  val->value = _gtk_css_value_ref (value);
 }
 
 /**
@@ -586,7 +574,7 @@ gtk_style_properties_set (GtkStyleProperties *props,
   va_end (args);
 }
 
-const GValue *
+GtkCssValue *
 _gtk_style_properties_peek_property (GtkStyleProperties  *props,
                                      GtkCssStyleProperty *property,
                                      GtkStateFlags        state)
@@ -610,7 +598,7 @@ typedef struct {
   GtkStateFlags       state;
 } StyleQueryData;
 
-static const GValue *
+static GtkCssValue *
 style_query_func (guint    id,
                   gpointer data)
 {
@@ -643,6 +631,7 @@ gtk_style_properties_get_property (GtkStyleProperties *props,
 {
   StyleQueryData query = { props, state };
   GtkStyleProperty *node;
+  GtkCssValue *v;
 
   g_return_val_if_fail (GTK_IS_STYLE_PROPERTIES (props), FALSE);
   g_return_val_if_fail (property != NULL, FALSE);
@@ -660,10 +649,12 @@ gtk_style_properties_get_property (GtkStyleProperties *props,
       return FALSE;
     }
 
-  _gtk_style_property_query (node,
-                             value,
-                             style_query_func,
-                             &query);
+  v = _gtk_style_property_query (node,
+				 style_query_func,
+				 &query);
+  _gtk_css_value_init_gvalue (v, value);
+  _gtk_css_value_unref (v);
+
   return TRUE;
 }
 
@@ -800,8 +791,8 @@ gtk_style_properties_unset_property (GtkStyleProperties *props,
 
       data = &g_array_index (prop->values, ValueData, pos);
 
-      if (G_IS_VALUE (&data->value))
-        g_value_unset (&data->value);
+      _gtk_css_value_unref (data->value);
+      data->value = NULL;
 
       g_array_remove_index (prop->values, pos);
     }
@@ -893,12 +884,12 @@ gtk_style_properties_merge (GtkStyleProperties       *props,
       for (i = 0; i < prop_to_merge->values->len; i++)
         {
           ValueData *data;
-          GValue *value;
+          ValueData *value;
 
           data = &g_array_index (prop_to_merge->values, ValueData, i);
 
           if (replace && data->state == GTK_STATE_FLAG_NORMAL &&
-              G_VALUE_TYPE (&data->value) != PANGO_TYPE_FONT_DESCRIPTION)
+              _gtk_css_value_holds (data->value, PANGO_TYPE_FONT_DESCRIPTION))
             {
               /* Let normal state override all states
                * previously set in the original set
@@ -908,20 +899,20 @@ gtk_style_properties_merge (GtkStyleProperties       *props,
 
           value = property_data_get_value (prop, data->state);
 
-          if (G_VALUE_TYPE (&data->value) == PANGO_TYPE_FONT_DESCRIPTION &&
-              G_IS_VALUE (value))
+          if (_gtk_css_value_holds (data->value, PANGO_TYPE_FONT_DESCRIPTION) &&
+              value->value != NULL)
             {
               PangoFontDescription *font_desc;
               PangoFontDescription *font_desc_to_merge;
 
               /* Handle merging of font descriptions */
-              font_desc = g_value_get_boxed (value);
-              font_desc_to_merge = g_value_get_boxed (&data->value);
+              font_desc = _gtk_css_value_get_font_description (value->value);
+              font_desc_to_merge = _gtk_css_value_get_font_description (data->value);
 
               pango_font_description_merge (font_desc, font_desc_to_merge, replace);
             }
-          else if (G_VALUE_TYPE (&data->value) == G_TYPE_PTR_ARRAY &&
-                   G_IS_VALUE (value))
+          else if (_gtk_css_value_holds (data->value, G_TYPE_PTR_ARRAY) &&
+                   value->value != NULL)
             {
               GPtrArray *array, *array_to_merge;
               gint i;
@@ -929,23 +920,16 @@ gtk_style_properties_merge (GtkStyleProperties       *props,
               /* Append the array, mainly thought
                * for the gtk-key-bindings property
                */
-              array = g_value_get_boxed (value);
-              array_to_merge = g_value_get_boxed (&data->value);
+              array = _gtk_css_value_get_boxed (value->value);
+              array_to_merge = _gtk_css_value_get_boxed (data->value);
 
               for (i = 0; i < array_to_merge->len; i++)
                 g_ptr_array_add (array, g_ptr_array_index (array_to_merge, i));
             }
-          else if (replace || !G_IS_VALUE (value))
+          else if (replace || value->value == NULL)
             {
-              if (!G_IS_VALUE (value))
-                g_value_init (value, G_VALUE_TYPE (&data->value));
-              else if (G_VALUE_TYPE (value) != G_VALUE_TYPE (&data->value))
-                {
-                  g_value_unset (value);
-                  g_value_init (value, G_VALUE_TYPE (&data->value));
-                }
-
-              g_value_copy (&data->value, value);
+	      _gtk_css_value_unref (value->value);
+	      value->value = _gtk_css_value_ref (data->value);
             }
         }
     }
diff --git a/gtk/gtkstylepropertiesprivate.h b/gtk/gtkstylepropertiesprivate.h
index 1b9caf4..c5b742e 100644
--- a/gtk/gtkstylepropertiesprivate.h
+++ b/gtk/gtkstylepropertiesprivate.h
@@ -25,13 +25,13 @@
 
 G_BEGIN_DECLS
 
-const GValue * _gtk_style_properties_peek_property            (GtkStyleProperties      *props,
+GtkCssValue  * _gtk_style_properties_peek_property            (GtkStyleProperties      *props,
                                                                GtkCssStyleProperty     *property,
                                                                GtkStateFlags            state);
 void           _gtk_style_properties_set_property_by_property (GtkStyleProperties      *props,
                                                                GtkCssStyleProperty     *property,
                                                                GtkStateFlags            state,
-                                                               const GValue            *value);
+                                                               GtkCssValue             *value);
 
 G_END_DECLS
 
diff --git a/gtk/gtkstyleproperty.c b/gtk/gtkstyleproperty.c
index 7cc6cbb..c70c76f 100644
--- a/gtk/gtkstyleproperty.c
+++ b/gtk/gtkstyleproperty.c
@@ -205,23 +205,19 @@ _gtk_style_property_assign (GtkStyleProperty   *property,
  * turn gtk_style_context_get() and similar functions to get the
  * value to return to code using old APIs.
  **/
-void
+GtkCssValue *
 _gtk_style_property_query (GtkStyleProperty  *property,
-                           GValue            *value,
                            GtkStyleQueryFunc  query_func,
                            gpointer           query_data)
 {
   GtkStylePropertyClass *klass;
 
-  g_return_if_fail (GTK_IS_STYLE_PROPERTY (property));
-  g_return_if_fail (value != NULL);
-  g_return_if_fail (query_func != NULL);
+  g_return_val_if_fail (GTK_IS_STYLE_PROPERTY (property), NULL);
+  g_return_val_if_fail (query_func != NULL, NULL);
 
   klass = GTK_STYLE_PROPERTY_GET_CLASS (property);
 
-  g_value_init (value, property->value_type);
-
-  klass->query (property, value, query_func, query_data);
+  return klass->query (property, query_func, query_data);
 }
 
 void
diff --git a/gtk/gtkstylepropertyprivate.h b/gtk/gtkstylepropertyprivate.h
index 936b48a..898b97f 100644
--- a/gtk/gtkstylepropertyprivate.h
+++ b/gtk/gtkstylepropertyprivate.h
@@ -20,6 +20,7 @@
 
 #include "gtkcssparserprivate.h"
 #include "gtkstylecontextprivate.h"
+#include "gtkcssvalueprivate.h"
 
 G_BEGIN_DECLS
 
@@ -37,8 +38,8 @@ typedef enum {
   GTK_STYLE_PROPERTY_INHERIT = (1 << 0)
 } GtkStylePropertyFlags;
 
-typedef const GValue *   (* GtkStyleQueryFunc)             (guint                   id,
-                                                            gpointer                data);
+typedef GtkCssValue *   (* GtkStyleQueryFunc)        (guint                   id,
+						      gpointer                data);
 
 struct _GtkStyleProperty
 {
@@ -56,8 +57,7 @@ struct _GtkStylePropertyClass
                                                             GtkStyleProperties     *props,
                                                             GtkStateFlags           state,
                                                             const GValue           *value);
-  void              (* query)                              (GtkStyleProperty       *property,
-                                                            GValue                 *value,
+  GtkCssValue *     (* query)                              (GtkStyleProperty       *property,
                                                             GtkStyleQueryFunc       query_func,
                                                             gpointer                query_data);
   gboolean          (* parse_value)                        (GtkStyleProperty *      property,
@@ -82,8 +82,7 @@ gboolean                 _gtk_style_property_parse_value   (GtkStyleProperty *
                                                             GFile                  *base);
 
 GType                    _gtk_style_property_get_value_type(GtkStyleProperty *      property);
-void                     _gtk_style_property_query         (GtkStyleProperty *      property,
-                                                            GValue                 *value,
+GtkCssValue *            _gtk_style_property_query         (GtkStyleProperty *      property,
                                                             GtkStyleQueryFunc       query_func,
                                                             gpointer                query_data);
 void                     _gtk_style_property_assign        (GtkStyleProperty       *property,
diff --git a/gtk/gtkthemingbackground.c b/gtk/gtkthemingbackground.c
index 1e21d2d..161cc5a 100644
--- a/gtk/gtkthemingbackground.c
+++ b/gtk/gtkthemingbackground.c
@@ -165,7 +165,7 @@ _gtk_theming_background_paint (GtkThemingBackground *bg,
       double image_width, image_height;
       double width, height;
 
-      size = g_value_get_boxed (_gtk_style_context_peek_property (bg->context, "background-size"));
+      size = _gtk_css_value_get_background_size (_gtk_style_context_peek_property (bg->context, "background-size"));
       gtk_style_context_get (bg->context, bg->flags,
                              "background-repeat", &hrepeat,
                              NULL);
@@ -338,7 +338,7 @@ _gtk_theming_background_init_context (GtkThemingBackground *bg)
   _gtk_theming_background_apply_clip (bg);
   _gtk_theming_background_apply_origin (bg);
 
-  bg->image = g_value_get_object (_gtk_style_context_peek_property (bg->context, "background-image"));
+  bg->image = _gtk_css_value_get_image (_gtk_style_context_peek_property (bg->context, "background-image"));
 }
 
 void
diff --git a/gtk/gtkthemingengine.c b/gtk/gtkthemingengine.c
index 662f1ce..d5eb10b 100644
--- a/gtk/gtkthemingengine.c
+++ b/gtk/gtkthemingengine.c
@@ -338,7 +338,7 @@ _gtk_theming_engine_get_context (GtkThemingEngine *engine)
   return engine->priv->context;
 }
 
-const GValue *
+GtkCssValue *
 _gtk_theming_engine_peek_property (GtkThemingEngine *engine,
                                    const char       *property_name)
 {
@@ -1820,17 +1820,17 @@ render_frame_internal (GtkThemingEngine *engine,
       render_border (cr, &border_box, &border, hidden_side, colors, border_style);
     }
 
-  border_style[0] = g_value_get_enum (_gtk_theming_engine_peek_property (engine, "outline-style"));
+  border_style[0] = _gtk_css_value_get_border_style (_gtk_theming_engine_peek_property (engine, "outline-style"));
   if (border_style[0] != GTK_BORDER_STYLE_NONE)
     {
       int offset;
 
       border_style[1] = border_style[2] = border_style[3] = border_style[0];
-      border.top = g_value_get_int (_gtk_theming_engine_peek_property (engine, "outline-width"));
+      border.top = _gtk_css_value_get_int (_gtk_theming_engine_peek_property (engine, "outline-width"));
       border.left = border.right = border.bottom = border.top;
-      colors[0] = *(GdkRGBA *) g_value_get_boxed (_gtk_theming_engine_peek_property (engine, "outline-color"));
+      colors[0] = *_gtk_css_value_get_rgba (_gtk_theming_engine_peek_property (engine, "outline-color"));
       colors[3] = colors[2] = colors[1] = colors[0];
-      offset = g_value_get_int (_gtk_theming_engine_peek_property (engine, "outline-offset"));
+      offset = _gtk_css_value_get_int (_gtk_theming_engine_peek_property (engine, "outline-offset"));
       
       /* reinit box here - outlines don't have a border radius */
       _gtk_rounded_box_init_rect (&border_box, x, y, width, height);
diff --git a/gtk/gtkthemingengineprivate.h b/gtk/gtkthemingengineprivate.h
index 64dbfaf..63d0cfa 100644
--- a/gtk/gtkthemingengineprivate.h
+++ b/gtk/gtkthemingengineprivate.h
@@ -20,13 +20,14 @@
 
 #include <gdk/gdk.h>
 #include "gtk/gtkthemingengine.h"
+#include "gtk/gtkcssvalueprivate.h"
 
 void _gtk_theming_engine_paint_spinner (cairo_t *cr,
                                         gdouble  radius,
                                         gdouble  progress,
                                         GdkRGBA *color);
 
-const GValue *_gtk_theming_engine_peek_property (GtkThemingEngine *engine,
+GtkCssValue  *_gtk_theming_engine_peek_property (GtkThemingEngine *engine,
                                                  const char       *property_name);
 double        _gtk_theming_engine_get_number    (GtkThemingEngine *engine,
                                                  const char       *property_name,



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