[gtk+] styleproperty: Make _gtk_style_property_parse_value() return a CssValue



commit 9b7640b898c61eb4ff49140880f2bb2b70eb9f0b
Author: Benjamin Otte <otte redhat com>
Date:   Mon Mar 26 17:24:02 2012 +0200

    styleproperty: Make _gtk_style_property_parse_value() return a CssValue
    
    Also split out initial/inherit handling into a custom GtkCssValue class.

 gtk/Makefile.am                      |    4 +
 gtk/gtkcsscomputedvalues.c           |   35 ++---
 gtk/gtkcsscustomproperty.c           |   23 ++-
 gtk/gtkcssinheritvalue.c             |   59 +++++++++
 gtk/gtkcssinheritvalueprivate.h      |   33 +++++
 gtk/gtkcssinitialvalue.c             |   59 +++++++++
 gtk/gtkcssinitialvalueprivate.h      |   33 +++++
 gtk/gtkcssprovider.c                 |   98 +++++++-------
 gtk/gtkcssshorthandproperty.c        |   55 ++++-----
 gtk/gtkcssshorthandpropertyimpl.c    |  234 +++++++++++++++------------------
 gtk/gtkcssshorthandpropertyprivate.h |    2 +-
 gtk/gtkcssstylefuncs.c               |    6 +-
 gtk/gtkcssstyleproperty.c            |   63 ++++-----
 gtk/gtkcssstylepropertyimpl.c        |   77 ++++-------
 gtk/gtkcssstylepropertyprivate.h     |    3 +-
 gtk/gtkcsstypesprivate.h             |    5 -
 gtk/gtkcssvalue.c                    |   82 ++++++++++--
 gtk/gtkcssvalueprivate.h             |    9 +-
 gtk/gtkstyleproperty.c               |   17 +--
 gtk/gtkstylepropertyprivate.h        |    6 +-
 20 files changed, 538 insertions(+), 365 deletions(-)
---
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index 740c155..6209b4d 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -431,6 +431,8 @@ gtk_private_h_sources =		\
 	gtkcssimageprivate.h	\
 	gtkcssimageurlprivate.h	\
 	gtkcssimagewin32private.h	\
+	gtkcssinheritvalueprivate.h	\
+	gtkcssinitialvalueprivate.h	\
 	gtkcsslookupprivate.h	\
 	gtkcssmatcherprivate.h	\
 	gtkcssparserprivate.h	\
@@ -629,6 +631,8 @@ gtk_base_c_sources = 		\
 	gtkcssimagelinear.c	\
 	gtkcssimageurl.c	\
 	gtkcssimagewin32.c	\
+	gtkcssinheritvalue.c	\
+	gtkcssinitialvalue.c	\
 	gtkcsslookup.c		\
 	gtkcssmatcher.c		\
 	gtkcssparser.c		\
diff --git a/gtk/gtkcsscomputedvalues.c b/gtk/gtkcsscomputedvalues.c
index 37ad20b..6b2ca8e 100644
--- a/gtk/gtkcsscomputedvalues.c
+++ b/gtk/gtkcsscomputedvalues.c
@@ -21,9 +21,9 @@
 
 #include "gtkcsscomputedvaluesprivate.h"
 
+#include "gtkcssinheritvalueprivate.h"
+#include "gtkcssinitialvalueprivate.h"
 #include "gtkcssstylepropertyprivate.h"
-#include "gtkcsstypesprivate.h"
-#include "gtkprivatetypebuiltins.h"
 
 G_DEFINE_TYPE (GtkCssComputedValues, _gtk_css_computed_values, G_TYPE_OBJECT)
 
@@ -101,26 +101,19 @@ _gtk_css_computed_values_compute_value (GtkCssComputedValues *values,
    */
   if (specified != NULL)
     {
-      if (_gtk_css_value_is_special (specified))
+      if (_gtk_css_value_is_inherit (specified))
         {
-          switch (_gtk_css_value_get_special_kind (specified))
-            {
-            case GTK_CSS_INHERIT:
-              /* 3) if the value of the winning declaration is âinheritâ,
-               * the inherited value (see below) becomes the specified value.
-               */
-              specified = NULL;
-              break;
-            case GTK_CSS_INITIAL:
-              /* if the value of the winning declaration is âinitialâ,
-               * the initial value (see below) becomes the specified value.
-               */
-              specified = _gtk_css_style_property_get_initial_value (prop);
-              break;
-            default:
-              /* This is part of (2) above */
-              break;
-            }
+          /* 3) if the value of the winning declaration is âinheritâ,
+           * the inherited value (see below) becomes the specified value.
+           */
+          specified = NULL;
+        }
+      else if (_gtk_css_value_is_initial (specified))
+        {
+          /* if the value of the winning declaration is âinitialâ,
+           * the initial value (see below) becomes the specified value.
+           */
+          specified = _gtk_css_style_property_get_initial_value (prop);
         }
 
       /* 2) If the cascading process (described below) yields a winning
diff --git a/gtk/gtkcsscustomproperty.c b/gtk/gtkcsscustomproperty.c
index 4f4e15f..28355dc 100644
--- a/gtk/gtkcsscustomproperty.c
+++ b/gtk/gtkcsscustomproperty.c
@@ -28,13 +28,14 @@
 
 G_DEFINE_TYPE (GtkCssCustomProperty, _gtk_css_custom_property, GTK_TYPE_CSS_STYLE_PROPERTY)
 
-static gboolean
+static GtkCssValue *
 gtk_css_custom_property_parse_value (GtkStyleProperty *property,
-                                     GValue           *value,
                                      GtkCssParser     *parser,
                                      GFile            *base)
 {
   GtkCssCustomProperty *custom = GTK_CSS_CUSTOM_PROPERTY (property);
+  GValue value = G_VALUE_INIT;
+  GtkCssValue *result;
   gboolean success;
 
   if (custom->property_parse_func)
@@ -42,12 +43,12 @@ gtk_css_custom_property_parse_value (GtkStyleProperty *property,
       GError *error = NULL;
       char *value_str;
       
-      g_value_init (value, _gtk_style_property_get_value_type (property));
+      g_value_init (&value, _gtk_style_property_get_value_type (property));
 
       value_str = _gtk_css_parser_read_value (parser);
       if (value_str != NULL)
         {
-          success = (* custom->property_parse_func) (value_str, value, &error);
+          success = (* custom->property_parse_func) (value_str, &value, &error);
           g_free (value_str);
         }
       else
@@ -56,15 +57,21 @@ gtk_css_custom_property_parse_value (GtkStyleProperty *property,
   else
     {
       GtkCssStyleProperty *style = GTK_CSS_STYLE_PROPERTY (property);
-      g_value_init (value, _gtk_css_style_property_get_specified_type (style));
+      g_value_init (&value, _gtk_css_style_property_get_specified_type (style));
 
-      success = _gtk_css_style_parse_value (value, parser, base);
+      success = _gtk_css_style_parse_value (&value, parser, base);
     }
 
   if (!success)
-    g_value_unset (value);
+    {
+      g_value_unset (&value);
+      return NULL;
+    }
 
-  return success;
+  result = _gtk_css_value_new_from_gvalue (&value);
+  g_value_unset (&value);
+
+  return result;
 }
 
 static void
diff --git a/gtk/gtkcssinheritvalue.c b/gtk/gtkcssinheritvalue.c
new file mode 100644
index 0000000..99405bb
--- /dev/null
+++ b/gtk/gtkcssinheritvalue.c
@@ -0,0 +1,59 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "gtkcssinheritvalueprivate.h"
+
+struct _GtkCssValue {
+  GTK_CSS_VALUE_BASE
+};
+
+static void
+gtk_css_value_inherit_free (GtkCssValue *value)
+{
+  /* Can only happen if the unique value gets unreffed too often */
+  g_assert_not_reached ();
+}
+
+static void
+gtk_css_value_inherit_print (const GtkCssValue *value,
+                             GString           *string)
+{
+  g_string_append (string, "inherit");
+}
+
+static const GtkCssValueClass GTK_CSS_VALUE_INHERIT = {
+  gtk_css_value_inherit_free,
+  gtk_css_value_inherit_print
+};
+
+static GtkCssValue inherit = { &GTK_CSS_VALUE_INHERIT, 1 };
+
+GtkCssValue *
+_gtk_css_inherit_value_new (void)
+{
+  return _gtk_css_value_ref (&inherit);
+}
+
+gboolean
+_gtk_css_value_is_inherit (const GtkCssValue *value)
+{
+  g_return_val_if_fail (value != NULL, FALSE);
+
+  return value == &inherit;
+}
diff --git a/gtk/gtkcssinheritvalueprivate.h b/gtk/gtkcssinheritvalueprivate.h
new file mode 100644
index 0000000..768aea2
--- /dev/null
+++ b/gtk/gtkcssinheritvalueprivate.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright  2012 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Alexander Larsson <alexl gnome org>
+ */
+
+#ifndef __GTK_CSS_INHERIT_VALUE_PRIVATE_H__
+#define __GTK_CSS_INHERIT_VALUE_PRIVATE_H__
+
+#include "gtkcssvalueprivate.h"
+
+G_BEGIN_DECLS
+
+GtkCssValue *   _gtk_css_inherit_value_new            (void);
+
+gboolean        _gtk_css_value_is_inherit             (const GtkCssValue          *value);
+
+G_END_DECLS
+
+#endif /* __GTK_CSS_INHERIT_VALUE_PRIVATE_H__ */
diff --git a/gtk/gtkcssinitialvalue.c b/gtk/gtkcssinitialvalue.c
new file mode 100644
index 0000000..32fb1c9
--- /dev/null
+++ b/gtk/gtkcssinitialvalue.c
@@ -0,0 +1,59 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "gtkcssinitialvalueprivate.h"
+
+struct _GtkCssValue {
+  GTK_CSS_VALUE_BASE
+};
+
+static void
+gtk_css_value_initial_free (GtkCssValue *value)
+{
+  /* Can only happen if the unique value gets unreffed too often */
+  g_assert_not_reached ();
+}
+
+static void
+gtk_css_value_initial_print (const GtkCssValue *value,
+                             GString           *string)
+{
+  g_string_append (string, "initial");
+}
+
+static const GtkCssValueClass GTK_CSS_VALUE_INITIAL = {
+  gtk_css_value_initial_free,
+  gtk_css_value_initial_print
+};
+
+static GtkCssValue initial = { &GTK_CSS_VALUE_INITIAL, 1 };
+
+GtkCssValue *
+_gtk_css_initial_value_new (void)
+{
+  return _gtk_css_value_ref (&initial);
+}
+
+gboolean
+_gtk_css_value_is_initial (const GtkCssValue *value)
+{
+  g_return_val_if_fail (value != NULL, FALSE);
+
+  return value == &initial;
+}
diff --git a/gtk/gtkcssinitialvalueprivate.h b/gtk/gtkcssinitialvalueprivate.h
new file mode 100644
index 0000000..19c39ed
--- /dev/null
+++ b/gtk/gtkcssinitialvalueprivate.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright  2012 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Alexander Larsson <alexl gnome org>
+ */
+
+#ifndef __GTK_CSS_INITIAL_VALUE_PRIVATE_H__
+#define __GTK_CSS_INITIAL_VALUE_PRIVATE_H__
+
+#include "gtkcssvalueprivate.h"
+
+G_BEGIN_DECLS
+
+GtkCssValue *   _gtk_css_initial_value_new            (void);
+
+gboolean        _gtk_css_value_is_initial             (const GtkCssValue          *value);
+
+G_END_DECLS
+
+#endif /* __GTK_CSS_INITIAL_VALUE_PRIVATE_H__ */
diff --git a/gtk/gtkcssprovider.c b/gtk/gtkcssprovider.c
index cbd14cd..e91b08e 100644
--- a/gtk/gtkcssprovider.c
+++ b/gtk/gtkcssprovider.c
@@ -26,6 +26,7 @@
 #include "gtkcssproviderprivate.h"
 
 #include "gtkbitmaskprivate.h"
+#include "gtkcssarrayvalueprivate.h"
 #include "gtkcssstylefuncsprivate.h"
 #include "gtkcssparserprivate.h"
 #include "gtkcsssectionprivate.h"
@@ -1249,7 +1250,7 @@ gtk_css_ruleset_add_style (GtkCssRuleset *ruleset,
 static void
 gtk_css_ruleset_add (GtkCssRuleset       *ruleset,
                      GtkCssStyleProperty *property,
-                     const GValue        *value,
+                     GtkCssValue         *value,
                      GtkCssSection       *section)
 {
   guint i;
@@ -1284,7 +1285,7 @@ gtk_css_ruleset_add (GtkCssRuleset       *ruleset,
       ruleset->styles[i].property = property;
     }
 
-  ruleset->styles[i].value = _gtk_css_value_new_from_gvalue (value);
+  ruleset->styles[i].value = value;
   if (gtk_keep_css_sections)
     ruleset->styles[i].section = gtk_css_section_ref (section);
   else
@@ -2190,66 +2191,65 @@ parse_declaration (GtkCssScanner *scanner,
 
   if (property)
     {
-      GValue value = { 0, };
+      GtkCssValue *value;
 
       g_free (name);
 
       gtk_css_scanner_push_section (scanner, GTK_CSS_SECTION_VALUE);
 
-      if (_gtk_style_property_parse_value (property,
-                                           &value,
-                                           scanner->parser,
-                                           gtk_css_scanner_get_base_url (scanner)))
+      value = _gtk_style_property_parse_value (property,
+                                               scanner->parser,
+                                               gtk_css_scanner_get_base_url (scanner));
+
+      if (value == NULL)
         {
-          if (_gtk_css_parser_begins_with (scanner->parser, ';') ||
-              _gtk_css_parser_begins_with (scanner->parser, '}') ||
-              _gtk_css_parser_is_eof (scanner->parser))
-            {
-              if (GTK_IS_CSS_SHORTHAND_PROPERTY (property))
-                {
-                  GtkCssShorthandProperty *shorthand = GTK_CSS_SHORTHAND_PROPERTY (property);
-                  GArray *array = g_value_get_boxed (&value);
-                  guint i;
-
-                  for (i = 0; i < _gtk_css_shorthand_property_get_n_subproperties (shorthand); i++)
-                    {
-                      GtkCssStyleProperty *child = _gtk_css_shorthand_property_get_subproperty (shorthand, i);
-                      const GValue *sub = &g_array_index (array, GValue, i);
-                      
-                      gtk_css_ruleset_add (ruleset, child, sub, scanner->section);
-                    }
-                }
-              else if (GTK_IS_CSS_STYLE_PROPERTY (property))
-                {
-                  gtk_css_ruleset_add (ruleset, GTK_CSS_STYLE_PROPERTY (property), &value, scanner->section);
-                }
-              else
-                {
-                  g_assert_not_reached ();
-                }
-
-              g_value_unset (&value);
-            }
-          else
-            {
-              gtk_css_provider_error_literal (scanner->provider,
-                                              scanner,
-                                              GTK_CSS_PROVIDER_ERROR,
-                                              GTK_CSS_PROVIDER_ERROR_SYNTAX,
-                                              "Junk at end of value");
-              _gtk_css_parser_resync (scanner->parser, TRUE, '}');
-              gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_VALUE);
-              gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_DECLARATION);
-              return;
-            }
+          _gtk_css_parser_resync (scanner->parser, TRUE, '}');
+          gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_VALUE);
+          gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_DECLARATION);
+          return;
         }
-      else
+
+      if (!_gtk_css_parser_begins_with (scanner->parser, ';') &&
+          !_gtk_css_parser_begins_with (scanner->parser, '}') &&
+          !_gtk_css_parser_is_eof (scanner->parser))
         {
+          gtk_css_provider_error_literal (scanner->provider,
+                                          scanner,
+                                          GTK_CSS_PROVIDER_ERROR,
+                                          GTK_CSS_PROVIDER_ERROR_SYNTAX,
+                                          "Junk at end of value");
           _gtk_css_parser_resync (scanner->parser, TRUE, '}');
           gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_VALUE);
           gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_DECLARATION);
           return;
         }
+
+      if (GTK_IS_CSS_SHORTHAND_PROPERTY (property))
+        {
+          GtkCssShorthandProperty *shorthand = GTK_CSS_SHORTHAND_PROPERTY (property);
+          guint i;
+
+          for (i = 0; i < _gtk_css_shorthand_property_get_n_subproperties (shorthand); i++)
+            {
+              GtkCssStyleProperty *child = _gtk_css_shorthand_property_get_subproperty (shorthand, i);
+              GtkCssValue *sub = _gtk_css_array_value_get_nth (value, i);
+              
+              gtk_css_ruleset_add (ruleset, child, _gtk_css_value_ref (sub), scanner->section);
+            }
+          
+            _gtk_css_value_unref (value);
+        }
+      else if (GTK_IS_CSS_STYLE_PROPERTY (property))
+        {
+          gtk_css_ruleset_add (ruleset, GTK_CSS_STYLE_PROPERTY (property), value, scanner->section);
+        }
+      else
+        {
+          g_assert_not_reached ();
+          _gtk_css_value_unref (value);
+        }
+
+
       gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_VALUE);
     }
   else if (name[0] == '-')
diff --git a/gtk/gtkcssshorthandproperty.c b/gtk/gtkcssshorthandproperty.c
index 6905b45..f10201d 100644
--- a/gtk/gtkcssshorthandproperty.c
+++ b/gtk/gtkcssshorthandproperty.c
@@ -21,10 +21,11 @@
 
 #include "gtkcssshorthandpropertyprivate.h"
 
+#include "gtkcssarrayvalueprivate.h"
+#include "gtkcssinheritvalueprivate.h"
+#include "gtkcssinitialvalueprivate.h"
 #include "gtkcssstylefuncsprivate.h"
-#include "gtkcsstypesprivate.h"
 #include "gtkintl.h"
-#include "gtkprivatetypebuiltins.h"
 
 enum {
   PROP_0,
@@ -83,26 +84,17 @@ _gtk_css_shorthand_property_query (GtkStyleProperty   *property,
   return shorthand->query (shorthand, value, query_func, query_data);
 }
 
-static void
-gtk_css_shorthand_property_unset_value (gpointer value)
-{
-  if (G_IS_VALUE (value))
-    g_value_unset (value);
-}
-
-static gboolean
+static GtkCssValue *
 gtk_css_shorthand_property_parse_value (GtkStyleProperty *property,
-                                        GValue           *value,
                                         GtkCssParser     *parser,
                                         GFile            *base)
 {
   GtkCssShorthandProperty *shorthand = GTK_CSS_SHORTHAND_PROPERTY (property);
-  GArray *array;
+  GtkCssValue **data;
+  GtkCssValue *result;
   guint i;
 
-  array = g_array_new (FALSE, TRUE, sizeof (GValue));
-  g_array_set_clear_func (array, gtk_css_shorthand_property_unset_value);
-  g_array_set_size (array, shorthand->subproperties->len);
+  data = g_new0 (GtkCssValue *, shorthand->subproperties->len);
 
   if (_gtk_css_parser_try (parser, "initial", TRUE))
     {
@@ -111,9 +103,7 @@ gtk_css_shorthand_property_parse_value (GtkStyleProperty *property,
        */
       for (i = 0; i < shorthand->subproperties->len; i++)
         {
-          GValue *val = &g_array_index (array, GValue, i);
-          g_value_init (val, GTK_TYPE_CSS_SPECIAL_VALUE);
-          g_value_set_enum (val, GTK_CSS_INITIAL);
+          data[i] = _gtk_css_initial_value_new ();
         }
     }
   else if (_gtk_css_parser_try (parser, "inherit", TRUE))
@@ -126,15 +116,18 @@ gtk_css_shorthand_property_parse_value (GtkStyleProperty *property,
        */
       for (i = 0; i < shorthand->subproperties->len; i++)
         {
-          GValue *val = &g_array_index (array, GValue, i);
-          g_value_init (val, GTK_TYPE_CSS_SPECIAL_VALUE);
-          g_value_set_enum (val, GTK_CSS_INHERIT);
+          data[i] = _gtk_css_inherit_value_new ();
         }
     }
-  else if (!shorthand->parse (shorthand, (GValue *) array->data, parser, base))
+  else if (!shorthand->parse (shorthand, data, parser, base))
     {
-      g_array_free (array, TRUE);
-      return FALSE;
+      for (i = 0; i < shorthand->subproperties->len; i++)
+        {
+          if (data[i] != NULL)
+            _gtk_css_value_unref (data[i]);
+        }
+      g_free (data);
+      return NULL;
     }
 
   /* All values that aren't set by the parse func are set to their
@@ -142,16 +135,14 @@ gtk_css_shorthand_property_parse_value (GtkStyleProperty *property,
    * XXX: Is the default always initial or can it be inherit? */
   for (i = 0; i < shorthand->subproperties->len; i++)
     {
-      GValue *val = &g_array_index (array, GValue, i);
-      if (G_IS_VALUE (val))
-        continue;
-      g_value_init (val, GTK_TYPE_CSS_SPECIAL_VALUE);
-      g_value_set_enum (val, GTK_CSS_INITIAL);
+      if (data[i] == NULL)
+        data[i] = _gtk_css_initial_value_new ();
     }
 
-  g_value_init (value, G_TYPE_ARRAY);
-  g_value_take_boxed (value, array);
-  return TRUE;
+  result = _gtk_css_array_value_new (data, shorthand->subproperties->len);
+  g_free (data);
+  
+  return result;
 }
 
 static void
diff --git a/gtk/gtkcssshorthandpropertyimpl.c b/gtk/gtkcssshorthandpropertyimpl.c
index 19c7895..85f3d28 100644
--- a/gtk/gtkcssshorthandpropertyimpl.c
+++ b/gtk/gtkcssshorthandpropertyimpl.c
@@ -49,10 +49,10 @@ value_is_done_parsing (GtkCssParser *parser)
 }
 
 static gboolean
-parse_four_numbers (GtkCssShorthandProperty *shorthand,
-                    GValue                  *values,
-                    GtkCssParser            *parser,
-                    GtkCssNumberParseFlags   flags)
+parse_four_numbers (GtkCssShorthandProperty  *shorthand,
+                    GtkCssValue             **values,
+                    GtkCssParser             *parser,
+                    GtkCssNumberParseFlags    flags)
 {
   GtkCssNumber numbers[4];
   guint i;
@@ -81,18 +81,17 @@ parse_four_numbers (GtkCssShorthandProperty *shorthand,
 
   for (i = 0; i < 4; i++)
     {
-      g_value_init (&values[i], GTK_TYPE_CSS_NUMBER);
-      g_value_set_boxed (&values[i], &numbers[i]);
+      values[i] = _gtk_css_value_new_from_number (&numbers[i]);
     }
 
   return TRUE;
 }
 
 static gboolean
-parse_margin (GtkCssShorthandProperty *shorthand,
-              GValue                  *values,
-              GtkCssParser            *parser,
-              GFile                   *base)
+parse_margin (GtkCssShorthandProperty  *shorthand,
+              GtkCssValue             **values,
+              GtkCssParser             *parser,
+              GFile                    *base)
 {
   return parse_four_numbers (shorthand,
                              values,
@@ -102,10 +101,10 @@ parse_margin (GtkCssShorthandProperty *shorthand,
 }
 
 static gboolean
-parse_padding (GtkCssShorthandProperty *shorthand,
-               GValue                  *values,
-               GtkCssParser            *parser,
-               GFile                   *base)
+parse_padding (GtkCssShorthandProperty  *shorthand,
+               GtkCssValue             **values,
+               GtkCssParser             *parser,
+               GFile                    *base)
 {
   return parse_four_numbers (shorthand,
                              values,
@@ -116,10 +115,10 @@ parse_padding (GtkCssShorthandProperty *shorthand,
 }
 
 static gboolean
-parse_border_width (GtkCssShorthandProperty *shorthand,
-                    GValue                  *values,
-                    GtkCssParser            *parser,
-                    GFile                   *base)
+parse_border_width (GtkCssShorthandProperty  *shorthand,
+                    GtkCssValue             **values,
+                    GtkCssParser             *parser,
+                    GFile                    *base)
 {
   return parse_four_numbers (shorthand,
                              values,
@@ -130,10 +129,10 @@ parse_border_width (GtkCssShorthandProperty *shorthand,
 }
 
 static gboolean 
-parse_border_radius (GtkCssShorthandProperty *shorthand,
-                     GValue                  *values,
-                     GtkCssParser            *parser,
-                     GFile                   *base)
+parse_border_radius (GtkCssShorthandProperty  *shorthand,
+                     GtkCssValue             **values,
+                     GtkCssParser             *parser,
+                     GFile                    *base)
 {
   GtkCssBorderCornerRadius borders[4];
   guint i;
@@ -195,18 +194,17 @@ parse_border_radius (GtkCssShorthandProperty *shorthand,
 
   for (i = 0; i < G_N_ELEMENTS (borders); i++)
     {
-      g_value_init (&values[i], GTK_TYPE_CSS_BORDER_CORNER_RADIUS);
-      g_value_set_boxed (&values[i], &borders[i]);
+      values[i] = _gtk_css_value_new_from_border_corner_radius (&borders[i]);
     }
 
   return TRUE;
 }
 
 static gboolean 
-parse_border_color (GtkCssShorthandProperty *shorthand,
-                    GValue                  *values,
-                    GtkCssParser            *parser,
-                    GFile                   *base)
+parse_border_color (GtkCssShorthandProperty  *shorthand,
+                    GtkCssValue             **values,
+                    GtkCssParser             *parser,
+                    GFile                    *base)
 {
   GtkSymbolicColor *symbolic;
   guint i;
@@ -224,8 +222,7 @@ parse_border_color (GtkCssShorthandProperty *shorthand,
             return FALSE;
         }
 
-      g_value_init (&values[i], GTK_TYPE_SYMBOLIC_COLOR);
-      g_value_set_boxed (&values[i], symbolic);
+      values[i] = _gtk_css_value_new_take_symbolic_color (symbolic);
 
       if (value_is_done_parsing (parser))
         break;
@@ -233,18 +230,17 @@ parse_border_color (GtkCssShorthandProperty *shorthand,
 
   for (i++; i < 4; i++)
     {
-      g_value_init (&values[i], G_VALUE_TYPE (&values[(i - 1) >> 1]));
-      g_value_copy (&values[(i - 1) >> 1], &values[i]);
+      values[i] = _gtk_css_value_ref (values[(i - 1) >> 1]);
     }
 
   return TRUE;
 }
 
 static gboolean
-parse_border_style (GtkCssShorthandProperty *shorthand,
-                    GValue                  *values,
-                    GtkCssParser            *parser,
-                    GFile                   *base)
+parse_border_style (GtkCssShorthandProperty  *shorthand,
+                    GtkCssValue             **values,
+                    GtkCssParser             *parser,
+                    GFile                    *base)
 {
   GtkBorderStyle styles[4];
   guint i;
@@ -266,19 +262,19 @@ parse_border_style (GtkCssShorthandProperty *shorthand,
 
   for (i = 0; i < G_N_ELEMENTS (styles); i++)
     {
-      g_value_init (&values[i], GTK_TYPE_BORDER_STYLE);
-      g_value_set_enum (&values[i], styles[i]);
+      values[i] = _gtk_css_value_new_from_enum (GTK_TYPE_BORDER_STYLE, styles[i]);
     }
 
   return TRUE;
 }
 
 static gboolean
-parse_border_image (GtkCssShorthandProperty *shorthand,
-                    GValue                  *values,
-                    GtkCssParser            *parser,
-                    GFile                   *base)
+parse_border_image (GtkCssShorthandProperty  *shorthand,
+                    GtkCssValue             **values,
+                    GtkCssParser             *parser,
+                    GFile                    *base)
 {
+  GValue value = G_VALUE_INIT;
   GtkCssImage *image;
   
   if (_gtk_css_parser_try (parser, "none", TRUE))
@@ -289,44 +285,49 @@ parse_border_image (GtkCssShorthandProperty *shorthand,
       if (!image)
         return FALSE;
     }
-  g_value_init (&values[0], GTK_TYPE_CSS_IMAGE);
-  g_value_set_object (&values[0], image);
+  values[0] = _gtk_css_value_new_take_image (image);
 
   if (value_is_done_parsing (parser))
     return TRUE;
 
-  g_value_init (&values[1], GTK_TYPE_BORDER);
-  if (!_gtk_css_style_parse_value (&values[1], parser, base))
+  g_value_init (&value, GTK_TYPE_BORDER);
+  if (!_gtk_css_style_parse_value (&value, parser, base))
     return FALSE;
+  values[1] = _gtk_css_value_new_from_gvalue (&value);
+  g_value_unset (&value);
 
   if (_gtk_css_parser_try (parser, "/", TRUE))
     {
-      g_value_init (&values[2], GTK_TYPE_BORDER);
-      if (!_gtk_css_style_parse_value (&values[2], parser, base))
+      g_value_init (&value, GTK_TYPE_BORDER);
+      if (!_gtk_css_style_parse_value (&value, parser, base))
         return FALSE;
+      values[2] = _gtk_css_value_new_from_gvalue (&value);
+      g_value_unset (&value);
     }
 
   if (value_is_done_parsing (parser))
     return TRUE;
 
-  g_value_init (&values[3], GTK_TYPE_CSS_BORDER_IMAGE_REPEAT);
-  if (!_gtk_css_style_parse_value (&values[3], parser, base))
+  g_value_init (&value, GTK_TYPE_CSS_BORDER_IMAGE_REPEAT);
+  if (!_gtk_css_style_parse_value (&value, parser, base))
     return FALSE;
+  values[3] = _gtk_css_value_new_from_gvalue (&value);
+  g_value_unset (&value);
 
   return TRUE;
 }
 
 static gboolean
-parse_border_side (GtkCssShorthandProperty *shorthand,
-                   GValue                  *values,
-                   GtkCssParser            *parser,
-                   GFile                   *base)
+parse_border_side (GtkCssShorthandProperty  *shorthand,
+                   GtkCssValue             **values,
+                   GtkCssParser             *parser,
+                   GFile                    *base)
 {
   int style;
 
   do
   {
-    if (!G_IS_VALUE (&values[0]) &&
+    if (values[0] == NULL &&
          _gtk_css_parser_has_number (parser))
       {
         GtkCssNumber number;
@@ -337,16 +338,14 @@ parse_border_side (GtkCssShorthandProperty *shorthand,
                                           | GTK_CSS_PARSE_LENGTH))
           return FALSE;
 
-        g_value_init (&values[0], GTK_TYPE_CSS_NUMBER);
-        g_value_set_boxed (&values[0], &number);
+        values[0] = _gtk_css_value_new_from_number (&number);
       }
-    else if (!G_IS_VALUE (&values[1]) &&
+    else if (values[1] == NULL &&
              _gtk_css_parser_try_enum (parser, GTK_TYPE_BORDER_STYLE, &style))
       {
-        g_value_init (&values[1], GTK_TYPE_BORDER_STYLE);
-        g_value_set_enum (&values[1], style);
+        values[1] = _gtk_css_value_new_from_enum (GTK_TYPE_BORDER_STYLE, style);
       }
-    else if (!G_IS_VALUE (&values[2]))
+    else if (values[2] == NULL)
       {
         GtkSymbolicColor *symbolic;
 
@@ -354,8 +353,7 @@ parse_border_side (GtkCssShorthandProperty *shorthand,
         if (symbolic == NULL)
           return FALSE;
 
-        g_value_init (&values[2], GTK_TYPE_SYMBOLIC_COLOR);
-        g_value_take_boxed (&values[2], symbolic);
+        values[2] = _gtk_css_value_new_take_symbolic_color (symbolic);
       }
     else
       {
@@ -371,16 +369,16 @@ parse_border_side (GtkCssShorthandProperty *shorthand,
 }
 
 static gboolean
-parse_border (GtkCssShorthandProperty *shorthand,
-              GValue                  *values,
-              GtkCssParser            *parser,
-              GFile                   *base)
+parse_border (GtkCssShorthandProperty  *shorthand,
+              GtkCssValue             **values,
+              GtkCssParser             *parser,
+              GFile                    *base)
 {
   int style;
 
   do
   {
-    if (!G_IS_VALUE (&values[0]) &&
+    if (values[0] == NULL &&
          _gtk_css_parser_has_number (parser))
       {
         GtkCssNumber number;
@@ -391,26 +389,18 @@ parse_border (GtkCssShorthandProperty *shorthand,
                                           | GTK_CSS_PARSE_LENGTH))
           return FALSE;
 
-        g_value_init (&values[0], GTK_TYPE_CSS_NUMBER);
-        g_value_init (&values[1], GTK_TYPE_CSS_NUMBER);
-        g_value_init (&values[2], GTK_TYPE_CSS_NUMBER);
-        g_value_init (&values[3], GTK_TYPE_CSS_NUMBER);
-        g_value_set_boxed (&values[0], &number);
-        g_value_set_boxed (&values[1], &number);
-        g_value_set_boxed (&values[2], &number);
-        g_value_set_boxed (&values[3], &number);
+        values[0] = _gtk_css_value_new_from_number (&number);
+        values[1] = _gtk_css_value_ref (values[0]);
+        values[2] = _gtk_css_value_ref (values[0]);
+        values[3] = _gtk_css_value_ref (values[0]);
       }
-    else if (!G_IS_VALUE (&values[4]) &&
+    else if (values[4] == NULL &&
              _gtk_css_parser_try_enum (parser, GTK_TYPE_BORDER_STYLE, &style))
       {
-        g_value_init (&values[4], GTK_TYPE_BORDER_STYLE);
-        g_value_init (&values[5], GTK_TYPE_BORDER_STYLE);
-        g_value_init (&values[6], GTK_TYPE_BORDER_STYLE);
-        g_value_init (&values[7], GTK_TYPE_BORDER_STYLE);
-        g_value_set_enum (&values[4], style);
-        g_value_set_enum (&values[5], style);
-        g_value_set_enum (&values[6], style);
-        g_value_set_enum (&values[7], style);
+        values[4] = _gtk_css_value_new_from_enum (GTK_TYPE_BORDER_STYLE, style);
+        values[5] = _gtk_css_value_ref (values[4]);
+        values[6] = _gtk_css_value_ref (values[4]);
+        values[7] = _gtk_css_value_ref (values[4]);
       }
     else if (!G_IS_VALUE (&values[8]))
       {
@@ -420,14 +410,10 @@ parse_border (GtkCssShorthandProperty *shorthand,
         if (symbolic == NULL)
           return FALSE;
 
-        g_value_init (&values[8], GTK_TYPE_SYMBOLIC_COLOR);
-        g_value_init (&values[9], GTK_TYPE_SYMBOLIC_COLOR);
-        g_value_init (&values[10], GTK_TYPE_SYMBOLIC_COLOR);
-        g_value_init (&values[11], GTK_TYPE_SYMBOLIC_COLOR);
-        g_value_set_boxed (&values[8], symbolic);
-        g_value_set_boxed (&values[9], symbolic);
-        g_value_set_boxed (&values[10], symbolic);
-        g_value_take_boxed (&values[11], symbolic);
+        values[8] = _gtk_css_value_new_take_symbolic_color (symbolic);
+        values[9] = _gtk_css_value_ref (values[8]);
+        values[10] = _gtk_css_value_ref (values[8]);
+        values[11] = _gtk_css_value_ref (values[8]);
       }
     else
       {
@@ -446,10 +432,10 @@ parse_border (GtkCssShorthandProperty *shorthand,
 }
 
 static gboolean
-parse_font (GtkCssShorthandProperty *shorthand,
-            GValue                  *values,
-            GtkCssParser            *parser,
-            GFile                   *base)
+parse_font (GtkCssShorthandProperty  *shorthand,
+            GtkCssValue             **values,
+            GtkCssParser             *parser,
+            GFile                    *base)
 {
   PangoFontDescription *desc;
   guint mask;
@@ -466,33 +452,29 @@ parse_font (GtkCssShorthandProperty *shorthand,
 
   if (mask & PANGO_FONT_MASK_FAMILY)
     {
-      GPtrArray *strv = g_ptr_array_new ();
+      char **strv = g_new0 (char *, 2);
 
-      g_ptr_array_add (strv, g_strdup (pango_font_description_get_family (desc)));
-      g_ptr_array_add (strv, NULL);
-      g_value_init (&values[0], G_TYPE_STRV);
-      g_value_take_boxed (&values[0], g_ptr_array_free (strv, FALSE));
+      strv[0] = g_strdup (pango_font_description_get_family (desc));
+      values[0] = _gtk_css_value_new_take_strv (strv);
     }
   if (mask & PANGO_FONT_MASK_STYLE)
     {
-      g_value_init (&values[1], PANGO_TYPE_STYLE);
-      g_value_set_enum (&values[1], pango_font_description_get_style (desc));
+      values[1] = _gtk_css_value_new_from_enum (PANGO_TYPE_STYLE,
+                                                pango_font_description_get_style (desc));
     }
   if (mask & PANGO_FONT_MASK_VARIANT)
     {
-      g_value_init (&values[2], PANGO_TYPE_VARIANT);
-      g_value_set_enum (&values[2], pango_font_description_get_variant (desc));
+      values[2] = _gtk_css_value_new_from_enum (PANGO_TYPE_VARIANT,
+                                                pango_font_description_get_variant (desc));
     }
   if (mask & PANGO_FONT_MASK_WEIGHT)
     {
-      g_value_init (&values[3], PANGO_TYPE_WEIGHT);
-      g_value_set_enum (&values[3], pango_font_description_get_weight (desc));
+      values[3] = _gtk_css_value_new_from_enum (PANGO_TYPE_WEIGHT,
+                                                pango_font_description_get_weight (desc));
     }
   if (mask & PANGO_FONT_MASK_SIZE)
     {
-      g_value_init (&values[4], G_TYPE_DOUBLE);
-      g_value_set_double (&values[4],
-                          (double) pango_font_description_get_size (desc) / PANGO_SCALE);
+      values[4] = _gtk_css_value_new_from_double ((double) pango_font_description_get_size (desc) / PANGO_SCALE);
     }
 
   pango_font_description_free (desc);
@@ -501,17 +483,17 @@ parse_font (GtkCssShorthandProperty *shorthand,
 }
 
 static gboolean
-parse_background (GtkCssShorthandProperty *shorthand,
-                  GValue                  *values,
-                  GtkCssParser            *parser,
-                  GFile                   *base)
+parse_background (GtkCssShorthandProperty  *shorthand,
+                  GtkCssValue             **values,
+                  GtkCssParser             *parser,
+                  GFile                    *base)
 {
   int enum_value;
 
   do
     {
       /* the image part */
-      if (!G_IS_VALUE (&values[0]) &&
+      if (values[0] == NULL &&
           (_gtk_css_parser_has_prefix (parser, "none") ||
            _gtk_css_image_can_parse (parser)))
         {
@@ -526,10 +508,9 @@ parse_background (GtkCssShorthandProperty *shorthand,
                 return FALSE;
             }
 
-          g_value_init (&values[0], GTK_TYPE_CSS_IMAGE);
-          g_value_take_object (&values[0], image);
+          values[0] = _gtk_css_value_new_take_image (image);
         }
-      else if (!G_IS_VALUE (&values[1]) &&
+      else if (values[1] == NULL &&
                _gtk_css_parser_try_enum (parser, GTK_TYPE_CSS_BACKGROUND_REPEAT, &enum_value))
         {
           if (enum_value <= GTK_CSS_BACKGROUND_REPEAT_MASK)
@@ -550,17 +531,15 @@ parse_background (GtkCssShorthandProperty *shorthand,
                 enum_value |= enum_value << GTK_CSS_BACKGROUND_REPEAT_SHIFT;
             }
 
-          g_value_init (&values[1], GTK_TYPE_CSS_BACKGROUND_REPEAT);
-          g_value_set_enum (&values[1], enum_value);
+          values[1] = _gtk_css_value_new_from_enum (GTK_TYPE_CSS_BACKGROUND_REPEAT, enum_value);
         }
-      else if ((!G_IS_VALUE (&values[2]) || !G_IS_VALUE (&values[3])) &&
+      else if ((values[2] == NULL || values[3] == NULL) &&
                _gtk_css_parser_try_enum (parser, GTK_TYPE_CSS_AREA, &enum_value))
         {
-          guint idx = !G_IS_VALUE (&values[2]) ? 2 : 3;
-          g_value_init (&values[idx], GTK_TYPE_CSS_AREA);
-          g_value_set_enum (&values[idx], enum_value);
+          guint idx = values[2] == NULL ? 2 : 3;
+          values[idx] = _gtk_css_value_new_from_enum (GTK_TYPE_CSS_AREA, enum_value);
         }
-      else if (!G_IS_VALUE (&values[4]))
+      else if (values[4] == NULL)
         {
           GtkSymbolicColor *symbolic;
           
@@ -568,8 +547,7 @@ parse_background (GtkCssShorthandProperty *shorthand,
           if (symbolic == NULL)
             return FALSE;
 
-          g_value_init (&values[4], GTK_TYPE_SYMBOLIC_COLOR);
-          g_value_take_boxed (&values[4], symbolic);
+          values[4] = _gtk_css_value_new_take_symbolic_color (symbolic);
         }
       else
         {
diff --git a/gtk/gtkcssshorthandpropertyprivate.h b/gtk/gtkcssshorthandpropertyprivate.h
index 4592949..95ec48c 100644
--- a/gtk/gtkcssshorthandpropertyprivate.h
+++ b/gtk/gtkcssshorthandpropertyprivate.h
@@ -39,7 +39,7 @@ typedef struct _GtkCssShorthandProperty           GtkCssShorthandProperty;
 typedef struct _GtkCssShorthandPropertyClass      GtkCssShorthandPropertyClass;
 
 typedef gboolean              (* GtkCssShorthandPropertyParseFunc)      (GtkCssShorthandProperty *shorthand,
-                                                                         GValue                  *values,
+                                                                         GtkCssValue            **values,
                                                                          GtkCssParser            *parser,
                                                                          GFile                   *base);
 typedef void                  (* GtkCssShorthandPropertyAssignFunc)     (GtkCssShorthandProperty *shorthand,
diff --git a/gtk/gtkcssstylefuncs.c b/gtk/gtkcssstylefuncs.c
index 0693e04..f3b58e5 100644
--- a/gtk/gtkcssstylefuncs.c
+++ b/gtk/gtkcssstylefuncs.c
@@ -218,11 +218,7 @@ rgba_value_compute (GtkStyleContext *context,
   GdkRGBA white = { 1, 1, 1, 1 };
   GtkCssValue *res;
   
-  if (_gtk_css_value_holds (specified, GTK_TYPE_CSS_SPECIAL_VALUE))
-    {
-      return _gtk_css_value_new_from_rgba (NULL);
-    }
-  else if (_gtk_css_value_holds (specified, GTK_TYPE_SYMBOLIC_COLOR))
+  if (_gtk_css_value_holds (specified, GTK_TYPE_SYMBOLIC_COLOR))
     {
       GtkSymbolicColor *symbolic = _gtk_css_value_get_symbolic_color (specified);
 
diff --git a/gtk/gtkcssstyleproperty.c b/gtk/gtkcssstyleproperty.c
index 35d21ca..933dbd4 100644
--- a/gtk/gtkcssstyleproperty.c
+++ b/gtk/gtkcssstyleproperty.c
@@ -21,6 +21,8 @@
 
 #include "gtkcssstylepropertyprivate.h"
 
+#include "gtkcssinheritvalueprivate.h"
+#include "gtkcssinitialvalueprivate.h"
 #include "gtkcssstylefuncsprivate.h"
 #include "gtkcsstypesprivate.h"
 #include "gtkintl.h"
@@ -186,9 +188,8 @@ _gtk_css_style_property_query (GtkStyleProperty   *property,
     }
 }
 
-static gboolean
+static GtkCssValue *
 gtk_css_style_property_parse_value (GtkStyleProperty *property,
-                                    GValue           *value,
                                     GtkCssParser     *parser,
                                     GFile            *base)
 {
@@ -199,9 +200,7 @@ gtk_css_style_property_parse_value (GtkStyleProperty *property,
       /* the initial value can be explicitly specified with the
        * âinitialâ keyword which all properties accept.
        */
-      g_value_init (value, GTK_TYPE_CSS_SPECIAL_VALUE);
-      g_value_set_enum (value, GTK_CSS_INITIAL);
-      return TRUE;
+      return _gtk_css_initial_value_new ();
     }
   else if (_gtk_css_parser_try (parser, "inherit", TRUE))
     {
@@ -211,19 +210,10 @@ gtk_css_style_property_parse_value (GtkStyleProperty *property,
        * strengthen inherited values in the cascade, and it can
        * also be used on properties that are not normally inherited.
        */
-      g_value_init (value, GTK_TYPE_CSS_SPECIAL_VALUE);
-      g_value_set_enum (value, GTK_CSS_INHERIT);
-      return TRUE;
-    }
-
-  g_value_init (value, _gtk_css_style_property_get_specified_type (style_property));
-  if (!(* style_property->parse_value) (style_property, value, parser, base))
-    {
-      g_value_unset (value);
-      return FALSE;
+      return _gtk_css_inherit_value_new ();
     }
 
-  return TRUE;
+  return (* style_property->parse_value) (style_property, parser, base);
 }
 
 static void
@@ -279,13 +269,25 @@ _gtk_css_style_property_class_init (GtkCssStylePropertyClass *klass)
   klass->style_properties = g_ptr_array_new ();
 }
 
-static gboolean
+static GtkCssValue *
 gtk_css_style_property_real_parse_value (GtkCssStyleProperty *property,
-                                         GValue              *value,
                                          GtkCssParser        *parser,
                                          GFile               *base)
 {
-  return _gtk_css_style_parse_value (value, parser, base);
+  GValue value = G_VALUE_INIT;
+  GtkCssValue *result;
+
+  g_value_init (&value, _gtk_css_style_property_get_specified_type (property));
+  if (!_gtk_css_style_parse_value (&value, parser, base))
+    {
+      g_value_unset (&value);
+      return NULL;
+    }
+
+  result = _gtk_css_value_new_from_gvalue (&value);
+  g_value_unset (&value);
+
+  return result;
 }
 
 static void
@@ -499,29 +501,18 @@ _gtk_css_style_property_compute_value (GtkCssStyleProperty *property,
  **/
 void
 _gtk_css_style_property_print_value (GtkCssStyleProperty    *property,
-                                     GtkCssValue            *css_value,
+                                     GtkCssValue            *value,
                                      GString                *string)
 {
   g_return_if_fail (GTK_IS_CSS_STYLE_PROPERTY (property));
-  g_return_if_fail (css_value != NULL);
+  g_return_if_fail (value != NULL);
   g_return_if_fail (string != NULL);
 
-  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, _gtk_css_value_get_special_kind (css_value));
-
-      g_string_append (string, enum_value->value_nick);
-
-      g_type_class_unref (enum_class);
-    }
+  if (_gtk_css_value_is_inherit (value) ||
+      _gtk_css_value_is_initial (value))
+    _gtk_css_value_print (value, string);
   else
-    {
-      property->print_value (property, css_value, string);
-    }
+    property->print_value (property, value, string);
 }
 
 /**
diff --git a/gtk/gtkcssstylepropertyimpl.c b/gtk/gtkcssstylepropertyimpl.c
index dc6af92..4e6836e 100644
--- a/gtk/gtkcssstylepropertyimpl.c
+++ b/gtk/gtkcssstylepropertyimpl.c
@@ -187,9 +187,8 @@ color_compute (GtkCssStyleProperty    *property,
     }
 }
 
-static gboolean
+static GtkCssValue *
 font_family_parse (GtkCssStyleProperty *property,
-                   GValue              *value,
                    GtkCssParser        *parser,
                    GFile               *base)
 {
@@ -230,8 +229,7 @@ font_family_parse (GtkCssStyleProperty *property,
 
   /* NULL-terminate array */
   g_ptr_array_add (names, NULL);
-  g_value_set_boxed (value, g_ptr_array_free (names, FALSE));
-  return TRUE;
+  return _gtk_css_value_new_take_strv ((char **) g_ptr_array_free (names, FALSE));
 }
 
 static void
@@ -257,9 +255,8 @@ font_family_value_print (GtkCssStyleProperty *property,
     }
 }
 
-static gboolean 
+static GtkCssValue *
 bindings_value_parse (GtkCssStyleProperty *property,
-                      GValue              *value,
                       GtkCssParser        *parser,
                       GFile               *base)
 {
@@ -292,9 +289,7 @@ bindings_value_parse (GtkCssStyleProperty *property,
     }
   while (_gtk_css_parser_try (parser, ",", TRUE));
 
-  g_value_take_boxed (value, array);
-
-  return TRUE;
+  return _gtk_css_value_new_take_binding_sets (array);
 }
 
 static void
@@ -317,9 +312,8 @@ bindings_value_print (GtkCssStyleProperty *property,
     }
 }
 
-static gboolean 
+static GtkCssValue *
 border_corner_radius_value_parse (GtkCssStyleProperty *property,
-                                  GValue              *value,
                                   GtkCssParser        *parser,
                                   GFile               *base)
 {
@@ -343,8 +337,7 @@ border_corner_radius_value_parse (GtkCssStyleProperty *property,
                                          | GTK_CSS_PARSE_LENGTH))
     return FALSE;
 
-  g_value_set_boxed (value, &corner);
-  return TRUE;
+  return _gtk_css_value_new_from_border_corner_radius (&corner);
 }
 
 static void
@@ -365,9 +358,8 @@ border_corner_radius_value_print (GtkCssStyleProperty *property,
     }
 }
 
-static gboolean 
+static GtkCssValue *
 css_image_value_parse (GtkCssStyleProperty *property,
-                       GValue              *value,
                        GtkCssParser        *parser,
                        GFile               *base)
 {
@@ -382,8 +374,7 @@ css_image_value_parse (GtkCssStyleProperty *property,
         return FALSE;
     }
 
-  g_value_take_object (value, image);
-  return TRUE;
+  return _gtk_css_value_new_take_image (image);
 }
 
 static void
@@ -422,9 +413,8 @@ css_image_value_compute (GtkCssStyleProperty    *property,
   return _gtk_css_value_new_take_image (computed);
 }
 
-static gboolean 
+static GtkCssValue *
 parse_margin (GtkCssStyleProperty *property,
-              GValue              *value,
               GtkCssParser        *parser,
               GFile               *base)
 {
@@ -434,10 +424,9 @@ parse_margin (GtkCssStyleProperty *property,
                                     &number, 
                                     GTK_CSS_NUMBER_AS_PIXELS
                                     | GTK_CSS_PARSE_LENGTH))
-    return FALSE;
+    return NULL;
 
-  g_value_set_boxed (value, &number);
-  return TRUE;
+  return _gtk_css_value_new_from_number (&number);
 }
 
 static GtkCssValue *
@@ -456,9 +445,8 @@ compute_margin (GtkCssStyleProperty *property,
   return  _gtk_css_value_ref (specified);
 }
 
-static gboolean 
+static GtkCssValue *
 parse_padding (GtkCssStyleProperty *property,
-               GValue              *value,
                GtkCssParser        *parser,
                GFile               *base)
 {
@@ -469,10 +457,9 @@ parse_padding (GtkCssStyleProperty *property,
                                     GTK_CSS_POSITIVE_ONLY
                                     | GTK_CSS_NUMBER_AS_PIXELS
                                     | GTK_CSS_PARSE_LENGTH))
-    return FALSE;
+    return NULL;
 
-  g_value_set_boxed (value, &number);
-  return TRUE;
+  return _gtk_css_value_new_from_number (&number);
 }
 
 static GtkCssValue *
@@ -489,9 +476,8 @@ compute_padding (GtkCssStyleProperty *property,
   return _gtk_css_value_ref (specified);
 }
 
-static gboolean 
+static GtkCssValue *
 parse_border_width (GtkCssStyleProperty *property,
-                    GValue              *value,
                     GtkCssParser        *parser,
                     GFile               *base)
 {
@@ -504,8 +490,7 @@ parse_border_width (GtkCssStyleProperty *property,
                                     | GTK_CSS_PARSE_LENGTH))
     return FALSE;
 
-  g_value_set_boxed (value, &number);
-  return TRUE;
+  return _gtk_css_value_new_from_number (&number);
 }
 
 static GtkCssValue *
@@ -540,9 +525,8 @@ compute_border_width (GtkCssStyleProperty    *property,
   return _gtk_css_value_new_from_int (value);
 }
 
-static gboolean
+static GtkCssValue *
 background_repeat_value_parse (GtkCssStyleProperty *property,
-                               GValue              *value,
                                GtkCssParser        *parser,
                                GFile               *base)
 {
@@ -570,8 +554,7 @@ background_repeat_value_parse (GtkCssStyleProperty *property,
         repeat |= repeat << GTK_CSS_BACKGROUND_REPEAT_SHIFT;
     }
 
-  g_value_set_enum (value, repeat);
-  return TRUE;
+  return _gtk_css_value_new_from_enum (GTK_TYPE_CSS_BACKGROUND_REPEAT, repeat);
 }
 
 static void
@@ -606,9 +589,8 @@ background_repeat_value_print (GtkCssStyleProperty *property,
   g_type_class_unref (enum_class);
 }
 
-static gboolean
+static GtkCssValue *
 background_size_parse (GtkCssStyleProperty *property,
-                       GValue              *value,
                        GtkCssParser        *parser,
                        GFile               *base)
 {
@@ -627,7 +609,7 @@ background_size_parse (GtkCssStyleProperty *property,
                                              GTK_CSS_POSITIVE_ONLY
                                              | GTK_CSS_PARSE_PERCENT
                                              | GTK_CSS_PARSE_LENGTH))
-        return FALSE;
+        return NULL;
 
       if (_gtk_css_parser_try (parser, "auto", TRUE))
         _gtk_css_number_init (&size.height, 0, GTK_CSS_PX);
@@ -638,14 +620,13 @@ background_size_parse (GtkCssStyleProperty *property,
                                             GTK_CSS_POSITIVE_ONLY
                                             | GTK_CSS_PARSE_PERCENT
                                             | GTK_CSS_PARSE_LENGTH))
-            return FALSE;
+            return NULL;
         }
       else
         _gtk_css_number_init (&size.height, 0, GTK_CSS_PX);
     }
 
-  g_value_set_boxed (value, &size);
-  return TRUE;
+  return _gtk_css_value_new_from_background_size (&size);
 }
 
 static void
@@ -696,9 +677,8 @@ background_size_compute (GtkCssStyleProperty    *property,
   return _gtk_css_value_ref (specified);
 }
 
-static gboolean
+static GtkCssValue *
 background_position_parse (GtkCssStyleProperty *property,
-			   GValue              *value,
 			   GtkCssParser        *parser,
 			   GFile               *base)
 {
@@ -744,7 +724,7 @@ background_position_parse (GtkCssStyleProperty *property,
 					&pos.x,
 					GTK_CSS_PARSE_PERCENT
 					| GTK_CSS_PARSE_LENGTH))
-	return FALSE;
+	return NULL;
     }
 
   for (second = 0; names[second].name != NULL; second++)
@@ -763,13 +743,13 @@ background_position_parse (GtkCssStyleProperty *property,
           if (missing != &pos.y)
             {
               _gtk_css_parser_error (parser, "Invalid combination of values");
-              return FALSE;
+              return NULL;
             }
           if (!_gtk_css_parser_read_number (parser,
                                             missing,
                                             GTK_CSS_PARSE_PERCENT
                                             | GTK_CSS_PARSE_LENGTH))
-	    return FALSE;
+	    return NULL;
         }
       else
         {
@@ -783,12 +763,11 @@ background_position_parse (GtkCssStyleProperty *property,
           (!names[first].horizontal && !names[second].horizontal))
         {
           _gtk_css_parser_error (parser, "Invalid combination of values");
-          return FALSE;
+          return NULL;
         }
     }
 
-  g_value_set_boxed (value, &pos);
-  return TRUE;
+  return _gtk_css_value_new_from_background_position (&pos);
 }
 
 static void
diff --git a/gtk/gtkcssstylepropertyprivate.h b/gtk/gtkcssstylepropertyprivate.h
index a10297b..43b0576 100644
--- a/gtk/gtkcssstylepropertyprivate.h
+++ b/gtk/gtkcssstylepropertyprivate.h
@@ -34,8 +34,7 @@ G_BEGIN_DECLS
 typedef struct _GtkCssStyleProperty           GtkCssStyleProperty;
 typedef struct _GtkCssStylePropertyClass      GtkCssStylePropertyClass;
 
-typedef gboolean         (* GtkCssStylePropertyParseFunc)  (GtkCssStyleProperty    *property,
-                                                            GValue                 *value,
+typedef GtkCssValue *    (* GtkCssStylePropertyParseFunc)  (GtkCssStyleProperty    *property,
                                                             GtkCssParser           *parser,
                                                             GFile                  *base);
 typedef void             (* GtkCssStylePropertyPrintFunc)  (GtkCssStyleProperty    *property,
diff --git a/gtk/gtkcsstypesprivate.h b/gtk/gtkcsstypesprivate.h
index c064b86..62bd29d 100644
--- a/gtk/gtkcsstypesprivate.h
+++ b/gtk/gtkcsstypesprivate.h
@@ -54,11 +54,6 @@ typedef enum { /*< skip >*/
                                    GTK_CSS_CHANGE_PARENT_POSITION | GTK_CSS_CHANGE_PARENT_SIBLING_POSITION | \
                                    GTK_CSS_CHANGE_PARENT_STATE | GTK_CSS_CHANGE_PARENT_SIBLING_STATE)
 
-typedef enum {
-  GTK_CSS_INHERIT,
-  GTK_CSS_INITIAL
-} GtkCssSpecialValue;
-
 /* We encode horizontal and vertical repeat in one enum value.
  * This eases parsing and storage, but you need to be aware that
  * you have to "unpack" this value.
diff --git a/gtk/gtkcssvalue.c b/gtk/gtkcssvalue.c
index 7bd1a55..a797f65 100644
--- a/gtk/gtkcssvalue.c
+++ b/gtk/gtkcssvalue.c
@@ -183,6 +183,31 @@ _gtk_css_value_new_from_int (gint val)
 }
 
 GtkCssValue *
+_gtk_css_value_new_from_enum (GType type,
+                              gint  val)
+{
+  GtkCssValue *value;
+
+  g_return_val_if_fail (g_type_is_a (type, G_TYPE_ENUM), NULL);
+
+  value = gtk_css_value_new (type);
+  value->u.gint = val;
+
+  return value;
+}
+
+GtkCssValue *
+_gtk_css_value_new_from_double (double d)
+{
+  GtkCssValue *value;
+
+  value = gtk_css_value_new (G_TYPE_DOUBLE);
+  value->u.dbl = d;
+
+  return value;
+}
+
+GtkCssValue *
 _gtk_css_value_new_take_string (char *string)
 {
   GtkCssValue *value;
@@ -193,6 +218,17 @@ _gtk_css_value_new_take_string (char *string)
   return value;
 }
 
+GtkCssValue *
+_gtk_css_value_new_take_strv (char **strv)
+{
+  GtkCssValue *value;
+
+  value = gtk_css_value_new (G_TYPE_STRV);
+  value->u.ptr = strv;
+
+  return value;
+}
+
 static gpointer
 g_boxed_copy0 (GType         boxed_type,
 	       gconstpointer src_boxed)
@@ -236,6 +272,17 @@ _gtk_css_value_new_take_image (GtkCssImage *v)
 }
 
 GtkCssValue *
+_gtk_css_value_new_take_binding_sets (GPtrArray *array)
+{
+  GtkCssValue *value;
+
+  value = gtk_css_value_new (G_TYPE_PTR_ARRAY);
+  value->u.ptr = array;
+
+  return value;
+}
+
+GtkCssValue *
 _gtk_css_value_new_from_number (const GtkCssNumber *v)
 {
   GtkCssValue *value;
@@ -323,6 +370,28 @@ _gtk_css_value_new_from_background_position (const GtkCssBackgroundPosition *v)
 }
 
 GtkCssValue *
+_gtk_css_value_new_from_border_corner_radius (const GtkCssBorderCornerRadius *v)
+{
+  GtkCssValue *value;
+
+  value = gtk_css_value_new (GTK_TYPE_CSS_BORDER_CORNER_RADIUS);
+  value->u.ptr = g_boxed_copy0 (GTK_TYPE_CSS_BORDER_CORNER_RADIUS, v);
+
+  return value;
+}
+
+GtkCssValue *
+_gtk_css_value_new_from_border_style (GtkBorderStyle style)
+{
+  GtkCssValue *value;
+
+  value = gtk_css_value_new (GTK_TYPE_BORDER_STYLE);
+  value->u.gint = style;
+
+  return value;
+}
+
+GtkCssValue *
 _gtk_css_value_new_take_symbolic_color (GtkSymbolicColor *v)
 {
   GtkCssValue *value;
@@ -434,19 +503,6 @@ _gtk_css_value_init_gvalue (const GtkCssValue *value,
     }
 }
 
-gboolean
-_gtk_css_value_is_special (const GtkCssValue *value)
-{
-  return _gtk_css_value_holds (value, GTK_TYPE_CSS_SPECIAL_VALUE);
-}
-
-GtkCssSpecialValue
-_gtk_css_value_get_special_kind (const GtkCssValue *value)
-{
-  g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_CSS_SPECIAL_VALUE), 0);
-  return value->u.gint;
-}
-
 const GtkCssNumber *
 _gtk_css_value_get_number (const GtkCssValue *value)
 {
diff --git a/gtk/gtkcssvalueprivate.h b/gtk/gtkcssvalueprivate.h
index 39af9b3..90517b5 100644
--- a/gtk/gtkcssvalueprivate.h
+++ b/gtk/gtkcssvalueprivate.h
@@ -69,7 +69,11 @@ gboolean     _gtk_css_value_holds                     (const GtkCssValue
 						       GType                       type);
 GtkCssValue *_gtk_css_value_new_from_gvalue           (const GValue               *g_value);
 GtkCssValue *_gtk_css_value_new_from_int              (gint                        val);
+GtkCssValue *_gtk_css_value_new_from_enum             (GType                       type,
+                                                       gint                        val);
+GtkCssValue *_gtk_css_value_new_from_double           (double                      d);
 GtkCssValue *_gtk_css_value_new_take_string           (char                       *string);
+GtkCssValue *_gtk_css_value_new_take_strv             (char                      **strv);
 GtkCssValue *_gtk_css_value_new_from_rgba             (const GdkRGBA              *v);
 GtkCssValue *_gtk_css_value_new_from_color            (const GdkColor             *v);
 GtkCssValue *_gtk_css_value_new_take_symbolic_color   (GtkSymbolicColor           *v);
@@ -77,13 +81,14 @@ GtkCssValue *_gtk_css_value_new_take_pattern          (cairo_pattern_t
 GtkCssValue *_gtk_css_value_new_take_shadow           (GtkShadow                  *v);
 GtkCssValue *_gtk_css_value_new_take_image            (GtkCssImage                *v);
 GtkCssValue *_gtk_css_value_new_from_number           (const GtkCssNumber         *v);
+GtkCssValue *_gtk_css_value_new_take_binding_sets     (GPtrArray                  *array);
 GtkCssValue *_gtk_css_value_new_from_background_size  (const GtkCssBackgroundSize *v);
 GtkCssValue *_gtk_css_value_new_from_background_position (const GtkCssBackgroundPosition *v);
+GtkCssValue *_gtk_css_value_new_from_border_corner_radius (const GtkCssBorderCornerRadius *v);
+GtkCssValue *_gtk_css_value_new_from_border_style     (GtkBorderStyle              style);
 void         _gtk_css_value_init_gvalue               (const GtkCssValue          *value,
 						       GValue                     *g_value);
 
-gboolean                        _gtk_css_value_is_special                 (const GtkCssValue *value);
-GtkCssSpecialValue              _gtk_css_value_get_special_kind           (const GtkCssValue *value);
 int                             _gtk_css_value_get_int                    (const GtkCssValue *value);
 int                             _gtk_css_value_get_enum                   (const GtkCssValue *value);
 double                          _gtk_css_value_get_double                 (const GtkCssValue *value);
diff --git a/gtk/gtkstyleproperty.c b/gtk/gtkstyleproperty.c
index 7418b93..87234e0 100644
--- a/gtk/gtkstyleproperty.c
+++ b/gtk/gtkstyleproperty.c
@@ -131,7 +131,6 @@ _gtk_style_property_init (GtkStyleProperty *property)
 /**
  * _gtk_style_property_parse_value:
  * @property: the property
- * @value: an uninitialized value
  * @parser: the parser to parse from
  * @base: the base file for @aprser
  *
@@ -142,26 +141,24 @@ _gtk_style_property_init (GtkStyleProperty *property)
  * left uninitialized.
  *
  * Only if @property is a #GtkCssShorthandProperty, the @value will
- * always contain a #GValueArray with the values to be used for
- * the subproperties.
+ * always be a #GtkCssValue whose values can be queried with
+ * _gtk_css_array_value_get_nth().
  *
- * Returns: %TRUE on success
+ * Returns: %NULL on failure or the parsed #GtkCssValue
  **/
-gboolean
+GtkCssValue *
 _gtk_style_property_parse_value (GtkStyleProperty *property,
-                                 GValue           *value,
                                  GtkCssParser     *parser,
                                  GFile            *base)
 {
   GtkStylePropertyClass *klass;
 
-  g_return_val_if_fail (GTK_IS_STYLE_PROPERTY (property), FALSE);
-  g_return_val_if_fail (value != NULL, FALSE);
-  g_return_val_if_fail (parser != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_STYLE_PROPERTY (property), NULL);
+  g_return_val_if_fail (parser != NULL, NULL);
 
   klass = GTK_STYLE_PROPERTY_GET_CLASS (property);
 
-  return klass->parse_value (property, value, parser, base);
+  return klass->parse_value (property, parser, base);
 }
 
 /**
diff --git a/gtk/gtkstylepropertyprivate.h b/gtk/gtkstylepropertyprivate.h
index d169139..1a6b6fb 100644
--- a/gtk/gtkstylepropertyprivate.h
+++ b/gtk/gtkstylepropertyprivate.h
@@ -61,8 +61,7 @@ struct _GtkStylePropertyClass
                                                             GValue                 *value,
                                                             GtkStyleQueryFunc       query_func,
                                                             gpointer                query_data);
-  gboolean          (* parse_value)                        (GtkStyleProperty *      property,
-                                                            GValue                 *value,
+  GtkCssValue *     (* parse_value)                        (GtkStyleProperty *      property,
                                                             GtkCssParser           *parser,
                                                             GFile                  *base);
 
@@ -77,8 +76,7 @@ GtkStyleProperty *       _gtk_style_property_lookup        (const char
 
 const char *             _gtk_style_property_get_name      (GtkStyleProperty       *property);
 
-gboolean                 _gtk_style_property_parse_value   (GtkStyleProperty *      property,
-                                                            GValue                 *value,
+GtkCssValue *            _gtk_style_property_parse_value   (GtkStyleProperty *      property,
                                                             GtkCssParser           *parser,
                                                             GFile                  *base);
 



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