[lasem/properties] Uncompilable WIP of the property list work.



commit 66e7c805e14a8a9acc64d8a609e9c5a22b95ea8b
Author: Emmanuel Pacaud <emmanuel pacaud lapp in2p3 fr>
Date:   Wed Jul 29 14:25:16 2009 +0200

    Uncompilable WIP of the property list work.

 src/Makefile.am                    |   47 ++--
 src/lsm.h                          |   45 +++
 src/lsmattributes.c                |  229 +++++++++++++
 src/lsmattributes.h                |   65 ++++
 src/lsmdom.h                       |   17 +-
 src/lsmproperties.c                |  112 +++----
 src/lsmproperties.h                |   40 +--
 src/{lsmsvgutils.c => lsmstr.c}    |   12 +-
 src/{lsmsvgutils.h => lsmstr.h}    |   20 +-
 src/lsmsvgattributes.c             |   79 +----
 src/lsmsvgattributes.h             |   32 +--
 src/lsmsvgcircleelement.c          |   47 +++-
 src/lsmsvgclippathelement.c        |   24 ++-
 src/lsmsvgelement.c                |   48 +++-
 src/lsmsvgelement.h                |    8 +-
 src/lsmsvgellipseelement.c         |   57 +++-
 src/lsmsvggradientelement.c        |   58 +++-
 src/lsmsvggraphic.c                |   43 ++-
 src/lsmsvggraphic.h                |    7 +-
 src/lsmsvgimageelement.c           |   84 ++++-
 src/lsmsvglineargradientelement.c  |   58 +++-
 src/lsmsvglineelement.c            |   57 +++-
 src/lsmsvgmaskelement.c            |   81 ++++-
 src/lsmsvgpathelement.c            |   20 +-
 src/lsmsvgpatternelement.c         |  124 ++++++--
 src/lsmsvgpolygonelement.c         |   20 +-
 src/lsmsvgpolylineelement.c        |   20 +-
 src/lsmsvgradialgradientelement.c  |   70 ++++-
 src/lsmsvgrectelement.c            |   79 ++++-
 src/lsmsvgstopelement.c            |   27 ++-
 src/lsmsvgstyle.c                  |  629 +++-------------------------------
 src/lsmsvgstyle.h                  |   14 +-
 src/lsmsvgsvgelement.c             |   87 ++++-
 src/lsmsvgsymbolelement.c          |    8 +-
 src/lsmsvgtextelement.c            |   49 ++-
 src/lsmsvgtraits.c                 |  654 ++++++++++++++++++++++++++++++++++++
 src/lsmsvgtraits.h                 |   77 +++++
 src/lsmsvguseelement.c             |   68 +++-
 src/lsmsvgview.c                   |   30 +-
 src/lsmtraits.c                    |   74 ++++
 src/{lsmsvgutils.h => lsmtraits.h} |   53 +---
 41 files changed, 2287 insertions(+), 1086 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 948c13d..647c8bf 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -18,7 +18,10 @@ liblasem_la_LIBADD = 				\
 
 liblasem_la_SOURCES =				\
 	lsmdebug.c				\
+	lsmstr.c				\
+	lsmtraits.c				\
 	lsmproperties.c				\
+	lsmattributes.c				\
 	lsmdomnode.c				\
 	lsmdomnodelist.c			\
 	lsmdomdocument.c			\
@@ -62,6 +65,15 @@ liblasem_la_SOURCES =				\
 	lsmmathmlaligngroupelement.c		\
 	lsmmathmlutils.c			\
 	lsmmathmllayoututils.c			\
+	lsmsvgenums.c				\
+	lsmsvgtraits.c				\
+	lsmsvgattributes.c			\
+	lsmsvgattributebags.c			\
+	lsmsvgstyle.c				\
+	lsmsvgcolors.c				\
+	lsmsvglength.c				\
+	lsmsvgview.c				\
+	lsmsvgmatrix.c				\
 	lsmsvgdocument.c			\
 	lsmsvgelement.c				\
 	lsmsvggraphic.c				\
@@ -85,21 +97,16 @@ liblasem_la_SOURCES =				\
 	lsmsvgradialgradientelement.c		\
 	lsmsvgstopelement.c			\
 	lsmsvgpatternelement.c			\
-	lsmsvgmaskelement.c			\
-	lsmsvgenums.c				\
-	lsmsvgattributes.c			\
-	lsmsvgattributebags.c			\
-	lsmsvgstyle.c				\
-	lsmsvgcolors.c				\
-	lsmsvglength.c				\
-	lsmsvgutils.c				\
-	lsmsvgview.c				\
-	lsmsvgmatrix.c
+	lsmsvgmaskelement.c
 
 liblasem_ladir = $(includedir)/lasem
 liblasem_la_HEADERS = \
+	lsm.h					\
+	lsmstr.h				\
 	lsmdebug.h				\
+	lsmtraits.h				\
 	lsmproperties.h				\
+	lsmattributes.h				\
 	lsmdom.h				\
 	lsmdomnode.h				\
 	lsmdomnodelist.h			\
@@ -146,6 +153,15 @@ liblasem_la_HEADERS = \
 	lsmmathmlutils.h			\
 	lsmmathmllayoututils.h			\
 	lsmsvg.h				\
+	lsmsvgenums.h				\
+	lsmsvgtraits.h				\
+	lsmsvgattributes.h			\
+	lsmsvgattributebags.h			\
+	lsmsvgstyle.h				\
+	lsmsvgcolors.h				\
+	lsmsvglength.h				\
+	lsmsvgview.h				\
+	lsmsvgmatrix.h				\
 	lsmsvgdocument.h			\
 	lsmsvgelement.h				\
 	lsmsvggraphic.h				\
@@ -169,16 +185,7 @@ liblasem_la_HEADERS = \
 	lsmsvgradialgradientelement.h		\
 	lsmsvgstopelement.h			\
 	lsmsvgpatternelement.h			\
-	lsmsvgmaskelement.h			\
-	lsmsvgenums.h				\
-	lsmsvgattributes.h			\
-	lsmsvgattributebags.h			\
-	lsmsvgstyle.h				\
-	lsmsvgcolors.h				\
-	lsmsvglength.h				\
-	lsmsvgutils.h				\
-	lsmsvgview.h				\
-	lsmsvgmatrix.h
+	lsmsvgmaskelement.h
 
 bin_PROGRAMS = lasemtest lasemrender
 
diff --git a/src/lsm.h b/src/lsm.h
new file mode 100644
index 0000000..71a93db
--- /dev/null
+++ b/src/lsm.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright © 2009 Emmanuel Pacaud
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ * 	Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+#ifndef LSM_H
+#define LSM_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+typedef struct {
+	double x1;
+	double y1;
+	double x2;
+	double y2;
+} LsmExtents;
+
+typedef struct {
+	double x;
+	double y;
+	double width;
+	double height;
+} LsmBox;
+
+G_END_DECLS
+
+#endif
diff --git a/src/lsmattributes.c b/src/lsmattributes.c
new file mode 100644
index 0000000..109efd5
--- /dev/null
+++ b/src/lsmattributes.c
@@ -0,0 +1,229 @@
+/*
+ * Copyright © 2007-2009  Emmanuel Pacaud
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ * 	Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+#include <lsmattributes.h>
+#include <lsmdebug.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+
+#define ATTRIBUTE_TRAIT(attribute) ((void *) (((void *) attribute) + sizeof (LsmAttribute)))
+
+struct _LsmAttributeManager {
+	GHashTable *			hash_by_name;
+};
+
+static LsmAttributeManager *
+lsm_attribute_manager_create (void)
+{
+	LsmAttributeManager *manager;
+
+	manager = g_new0 (LsmAttributeManager, 1);
+	manager->hash_by_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
+
+	return manager;
+}
+
+LsmAttributeManager *
+lsm_attribute_manager_new (unsigned int n_attributes, const LsmAttributeInfos *attribute_infos)
+{
+	LsmAttributeManager *manager;
+
+	manager = lsm_attribute_manager_create ();
+
+	lsm_attribute_manager_add_attributes (manager, n_attributes, attribute_infos);
+
+	return manager;
+}
+
+LsmAttributeManager *
+lsm_attribute_manager_duplicate (const LsmAttributeManager *origin)
+{
+	LsmAttributeManager *manager;
+	GHashTableIter iter;
+	gpointer key, value;
+
+	g_return_val_if_fail (origin != NULL, NULL);
+
+	manager = lsm_attribute_manager_create ();
+
+	g_hash_table_iter_init (&iter, origin->hash_by_name);
+	while (g_hash_table_iter_next (&iter, &key, &value))
+		g_hash_table_insert (manager->hash_by_name, key, value);
+
+	return manager;
+}
+
+void
+lsm_attribute_manager_add_attributes (LsmAttributeManager *manager,
+				      unsigned int n_attributes,
+				      const LsmAttributeInfos *attribute_infos)
+{
+	unsigned int i;
+
+	g_return_if_fail (n_attributes > 0);
+	g_return_if_fail (attribute_infos != NULL);
+
+	for (i = 0; i < n_attributes; i++) {
+		g_assert (attribute_infos[i].name != NULL);
+		g_assert (attribute_infos[i].attribute_offset >= 0);
+		g_assert (attribute_infos[i].trait_class != NULL);
+
+		g_hash_table_insert (manager->hash_by_name,
+				     (void *) attribute_infos[i].name,
+				     (void *) &attribute_infos[i]);
+	}
+
+}
+
+void
+lsm_attribute_manager_free (LsmAttributeManager *manager)
+{
+	g_return_if_fail (manager != NULL);
+
+	g_hash_table_unref (manager->hash_by_name);
+	g_free (manager);
+}
+
+gboolean
+lsm_attribute_manager_set_attribute (LsmAttributeManager *manager,
+				     void *instance,
+				     const char *name,
+				     const char *value)
+{
+	LsmAttribute *attribute;
+	LsmAttributeInfos *attribute_infos;
+	const LsmTraitClass *trait_class;
+
+	g_return_val_if_fail (manager != NULL, FALSE);
+
+	attribute_infos = g_hash_table_lookup (manager->hash_by_name, name);
+	if (attribute_infos == NULL)
+		return FALSE;
+
+	attribute = (void *)(instance + attribute_infos->attribute_offset);
+	g_return_val_if_fail (attribute != NULL, FALSE);
+
+	trait_class = attribute_infos->trait_class;
+
+	g_free (attribute->value);
+	attribute->value = g_strdup (value);
+
+	if (attribute->value != NULL) {
+		if (trait_class->from_string)
+			trait_class->from_string (ATTRIBUTE_TRAIT (attribute), (char *) value);
+	} else {
+		if (trait_class->init)
+			trait_class->init (ATTRIBUTE_TRAIT (attribute), attribute_infos->trait_default);
+		else
+			/* Simple memcpy for default init implementation, discarde by a NULL default value. */
+			if (attribute_infos->trait_default != NULL)
+				memcpy (ATTRIBUTE_TRAIT (attribute),
+					attribute_infos->trait_default,
+					trait_class->size);
+	}
+
+	return TRUE;
+}
+
+char const *
+lsm_attribute_manager_get_attribute (LsmAttributeManager *manager,
+				     void *instance,
+				     const char *name)
+{
+	LsmAttributeInfos *attribute_infos;
+	LsmAttribute *attribute;
+
+	g_return_val_if_fail (manager != NULL, NULL);
+
+	attribute_infos = g_hash_table_lookup (manager->hash_by_name, name);
+	if (attribute_infos == NULL)
+		return NULL;
+
+	attribute = (void *)(instance + attribute_infos->attribute_offset);
+	g_return_val_if_fail (attribute != NULL, NULL);
+
+	return attribute->value;
+}
+
+void
+lsm_attribute_manager_clean_attributes (LsmAttributeManager *manager,
+					void *instance)
+{
+	LsmAttributeInfos *attribute_infos;
+	LsmAttribute *attribute;
+	const LsmTraitClass *trait_class;
+	GHashTableIter iter;
+	gpointer key, value;
+
+	g_return_if_fail (manager != NULL);
+
+	g_hash_table_iter_init (&iter, manager->hash_by_name);
+	while (g_hash_table_iter_next (&iter, &key, &value)) {
+		attribute_infos = value;
+		trait_class = attribute_infos->trait_class;
+
+		if (trait_class->finalize) {
+			attribute = (void *)(instance + attribute_infos->attribute_offset);
+			trait_class->finalize (ATTRIBUTE_TRAIT (attribute));
+		}
+	}
+}
+
+char *
+lsm_attribute_manager_serialize	(LsmAttributeManager *manager,
+				 void *instance)
+{
+	LsmAttributeInfos *attribute_infos;
+	LsmAttribute *attribute;
+	GString *string;
+	GHashTableIter iter;
+	char *c_string;
+	gpointer key, value;
+	gboolean is_first = TRUE;
+
+	g_return_val_if_fail (manager != NULL, NULL);
+
+	string = g_string_new ("");
+
+	g_hash_table_iter_init (&iter, manager->hash_by_name);
+	while (g_hash_table_iter_next (&iter, &key, &value)) {
+		attribute_infos = value;
+		attribute = (void *)(instance + attribute_infos->attribute_offset);
+
+		if (is_first) {
+			g_string_append_printf (string, "%s=\"%s\"",
+						attribute_infos->name,
+						attribute->value);
+			is_first = FALSE;
+		} else {
+			g_string_append_printf (string, " %s=\"%s\"",
+						attribute_infos->name,
+						attribute->value);
+		}
+	}
+
+	c_string = string->str;
+
+	g_string_free (string, FALSE);
+
+	return c_string;
+}
diff --git a/src/lsmattributes.h b/src/lsmattributes.h
new file mode 100644
index 0000000..26c0fb4
--- /dev/null
+++ b/src/lsmattributes.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright © 2007-2009 Emmanuel Pacaud
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ * 	Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+#ifndef LSM_ATTRIBUTES_H
+#define LSM_ATTRIBUTES_H
+
+#include <lsm.h>
+#include <lsmtraits.h>
+
+G_BEGIN_DECLS
+
+typedef struct {
+	char *value;
+} LsmAttribute;
+
+typedef struct {
+	char const *		name;
+	ptrdiff_t 		attribute_offset;
+	const LsmTraitClass *	trait_class;
+	const void *		trait_default;
+} LsmAttributeInfos;
+
+typedef struct _LsmAttributeManager LsmAttributeManager;
+
+LsmAttributeManager *	lsm_attribute_manager_new 		(unsigned int n_attributes,
+								 const LsmAttributeInfos *attribute_infos);
+void			lsm_attribute_manager_free		(LsmAttributeManager *manager);
+void 			lsm_attribute_manager_add_attributes 	(LsmAttributeManager *manager,
+								 unsigned int n_attributes,
+								 const LsmAttributeInfos *attribute_infos);
+LsmAttributeManager * 	lsm_attribute_manager_duplicate 	(const LsmAttributeManager *origin);
+
+gboolean	lsm_attribute_manager_set_attribute		(LsmAttributeManager *manager,
+								 void *instance,
+								 char const *name,
+								 char const *value);
+char const *	lsm_attribute_manager_get_attribute		(LsmAttributeManager *manager,
+								 void *instance,
+								 char const *name);
+void		lsm_attribute_manager_clean_attributes 		(LsmAttributeManager *manager,
+								 void *instance);
+char *		lsm_attribute_manager_serialize			(LsmAttributeManager *manager,
+								 void *instance);
+
+G_END_DECLS
+
+#endif
diff --git a/src/lsmdom.h b/src/lsmdom.h
index d9a131c..ac4d61d 100644
--- a/src/lsmdom.h
+++ b/src/lsmdom.h
@@ -20,28 +20,13 @@
  * 	Emmanuel Pacaud <emmanuel gnome org>
  */
 
-
 #ifndef LSM_DOM_H
 #define LSM_DOM_H
 
-#include <glib-object.h>
+#include <lsm.h>
 
 G_BEGIN_DECLS
 
-typedef struct {
-	double x1;
-	double y1;
-	double x2;
-	double y2;
-} LsmExtents;
-
-typedef struct {
-	double x;
-	double y;
-	double width;
-	double height;
-} LsmBox;
-
 typedef struct _LsmDomNode LsmDomNode;
 typedef struct _LsmDomElement LsmDomElement;
 typedef struct _LsmDomDocument LsmDomDocument;
diff --git a/src/lsmproperties.c b/src/lsmproperties.c
index a17a46c..68fbf3f 100644
--- a/src/lsmproperties.c
+++ b/src/lsmproperties.c
@@ -20,11 +20,15 @@
  */
 
 #include <lsmproperties.h>
+#include <lsmdebug.h>
+
+#define PROPERTY_TRAIT(property) ((void *) (((void *) property) + sizeof (LsmProperty)))
+#define PROPERTY_SIZE(trait_class) (trait_class->size + sizeof (LsmProperty))
 
 struct _LsmPropertyManager {
 	unsigned int		n_properties;
 	const LsmPropertyInfos *property_infos;
-	GHashTable *		hash_by_names;
+	GHashTable *		hash_by_name;
 };
 
 LsmPropertyManager *
@@ -37,17 +41,16 @@ lsm_property_manager_new (unsigned int n_properties, const LsmPropertyInfos *pro
 	g_return_val_if_fail (property_infos != NULL, NULL);
 
 	manager = g_new (LsmPropertyManager, 1);
-	manager->hash_by_names = g_hash_table_new (g_str_hash, g_str_equal);
+	manager->hash_by_name = g_hash_table_new (g_str_hash, g_str_equal);
 	manager->n_properties = n_properties;
 	manager->property_infos = property_infos;
 
 	for (i = 0; i < n_properties; i++) {
 
 		g_assert (property_infos[i].name != NULL);
-		g_assert (property_infos[i].property_class != NULL);
-		g_assert (property_infos[i].property_class->size > 0);
+		g_assert (property_infos[i].trait_class != NULL);
 
-		g_hash_table_insert (manager->hash_by_names,
+		g_hash_table_insert (manager->hash_by_name,
 				     (void *) property_infos[i].name,
 				     (void *) &property_infos[i]);
 	}
@@ -60,74 +63,59 @@ lsm_property_manager_free (LsmPropertyManager *manager)
 {
 	g_return_if_fail (manager != NULL);
 
-	g_hash_table_unref (manager->hash_by_names);
+	g_hash_table_unref (manager->hash_by_name);
 	g_free (manager);
 }
 
-const LsmPropertyInfos *
-lsm_property_manager_find_infos (LsmPropertyManager *manager, const char *name)
-{
-	g_return_val_if_fail (manager != NULL, NULL);
-
-	return g_hash_table_lookup (manager->hash_by_names, name);
-}
-
-const LsmPropertyInfos *
-lsm_property_manager_find_infos_by_id (LsmPropertyManager *manager, guint16 id)
-{
-	g_return_val_if_fail (manager != NULL, NULL);
-	g_return_val_if_fail (id < manager->n_properties, NULL);
-
-	return &manager->property_infos[id];
-}
-
 static void
-property_free (LsmProperty *property, const LsmPropertyClass *property_class)
+property_free (LsmProperty *property, const LsmTraitClass *trait_class)
 {
-	if (property_class != NULL && property_class->finalize != NULL)
-		property_class->finalize (property);
+	if (trait_class != NULL && trait_class->finalize != NULL)
+		trait_class->finalize (PROPERTY_TRAIT (property));
 
 	g_free (property->value);
-	g_slice_free1 (property_class->size, property);
+	g_slice_free1 (PROPERTY_SIZE (trait_class), property);
 }
 
-void
-lsm_property_bag_set_property (LsmPropertyBag *property_bag,
-				LsmPropertyManager *manager,
-				const char *name, const char *value)
+gboolean
+lsm_property_manager_set_property (LsmPropertyManager *manager,
+				   LsmPropertyBag *property_bag,
+				   const char *name, const char *value)
 {
 	LsmProperty *property;
 	const LsmPropertyInfos *property_infos;
-	const LsmPropertyClass *property_class;
+	const LsmTraitClass *trait_class;
 
-	g_return_if_fail (property_bag != NULL);
-	g_return_if_fail (manager != NULL);
+	g_return_val_if_fail (property_bag != NULL, FALSE);
+	g_return_val_if_fail (manager != NULL, FALSE);
 
-	property_infos = lsm_property_manager_find_infos (manager, name);
+	property_infos = g_hash_table_lookup (manager->hash_by_name, name);
 	if (property_infos == NULL)
-		return;
+		return FALSE;
 
-	property_class = property_infos->property_class;
+	trait_class = property_infos->trait_class;
 
 	/* We don't check for existing property in the list. The cleanup will be done later. */
 
-	property = g_slice_alloc0 (property_class->size);
+	property = g_slice_alloc0 (PROPERTY_SIZE (trait_class));
 	property->id = property_infos->id;
 	property->value = g_strdup (value);
 
-	if (property_class->init)
-		property_class->init (property);
+	if (trait_class->init)
+		trait_class->init (PROPERTY_TRAIT (property), NULL);
 
-	if (property->value != NULL && property_class->from_text)
-		property_class->from_text (property, value);
+	if (property->value != NULL && trait_class->from_string)
+		trait_class->from_string (PROPERTY_TRAIT (property), (char *) value);
 
 	property_bag->properties = g_slist_prepend (property_bag->properties, property);
+
+	return TRUE;
 }
 
 const char *
-lsm_property_bag_get_property (LsmPropertyBag *property_bag,
-			       LsmPropertyManager *manager,
-			       const char *name)
+lsm_property_manager_get_property (LsmPropertyManager *manager,
+				   LsmPropertyBag *property_bag,
+				   const char *name)
 {
 	LsmProperty *property = NULL;
 	const LsmPropertyInfos *property_infos;
@@ -136,7 +124,7 @@ lsm_property_bag_get_property (LsmPropertyBag *property_bag,
 	g_return_val_if_fail (property_bag != NULL, NULL);
 	g_return_val_if_fail (manager != NULL, NULL);
 
-	property_infos = lsm_property_manager_find_infos (manager, name);
+	property_infos = g_hash_table_lookup (manager->hash_by_name, name);
 	if (property_infos == NULL)
 		return NULL;
 
@@ -155,11 +143,10 @@ lsm_property_bag_get_property (LsmPropertyBag *property_bag,
 }
 
 void
-lsm_property_bag_clean (LsmPropertyBag *property_bag,
-			LsmPropertyManager *manager)
+lsm_property_manager_clean_properties (LsmPropertyManager *manager,
+				       LsmPropertyBag *property_bag)
 {
 	LsmProperty *property;
-	const LsmPropertyInfos *property_infos;
 	GSList *iter;
 
 	g_return_if_fail (property_bag != NULL);
@@ -168,9 +155,12 @@ lsm_property_bag_clean (LsmPropertyBag *property_bag,
 	for (iter = property_bag->properties; iter != NULL; iter = iter->next) {
 		property = iter->data;
 
-		property_infos = lsm_property_manager_find_infos_by_id (manager, property->id);
+		if (property->id < manager->n_properties) {
+			const LsmPropertyInfos *property_infos;
 
-		property_free (property, property_infos->property_class);
+			property_infos = &manager->property_infos[property->id];
+			property_free (property, property_infos->trait_class);
+		}
 	}
 
 	g_slist_free (property_bag->properties);
@@ -178,29 +168,31 @@ lsm_property_bag_clean (LsmPropertyBag *property_bag,
 }
 
 char *
-lsm_property_bag_serialize (LsmPropertyBag *property_bag,
-			    LsmPropertyManager *property_manager)
+lsm_property_manager_serialize (LsmPropertyManager *manager,
+				LsmPropertyBag *property_bag)
 {
 	LsmProperty *property;
-	const LsmPropertyInfos *property_infos;
 	GSList *iter;
 	GString *string;
 	char *c_string;
 
 	g_return_val_if_fail (property_bag != NULL, NULL);
-	g_return_val_if_fail (property_manager != NULL, NULL);
+	g_return_val_if_fail (manager != NULL, NULL);
 
 	string = g_string_new ("");
 
 	for (iter = property_bag->properties; iter != NULL; iter = iter->next) {
 		property = iter->data;
 
-		property_infos = lsm_property_manager_find_infos_by_id (property_manager, property->id);
+		if (property->id < manager->n_properties) {
+			const LsmPropertyInfos *property_infos;
 
-		g_string_append_printf (string, "%s=\"%s\"%s",
-					property_infos->name,
-					property->value,
-					iter->next != NULL ? " ": "");
+			property_infos = &manager->property_infos[property->id];
+			g_string_append_printf (string, "%s=\"%s\"%s",
+						property_infos->name,
+						property->value,
+						iter->next != NULL ? " ": "");
+		}
 	}
 
 
diff --git a/src/lsmproperties.h b/src/lsmproperties.h
index 8d1d789..a705bb1 100644
--- a/src/lsmproperties.h
+++ b/src/lsmproperties.h
@@ -18,8 +18,11 @@
  * Author:
  * 	Emmanuel Pacaud <emmanuel gnome org>
  */
+#ifndef LSM_PROPERTIES_H
+#define LSM_PROPERTIES_H
 
-#include <glib.h>
+#include <lsm.h>
+#include <lsmtraits.h>
 
 G_BEGIN_DECLS
 
@@ -33,17 +36,9 @@ typedef struct {
 } LsmProperty;
 
 typedef struct {
-	size_t		size;
-	void 		(*init)			(LsmProperty *property);
-	void 		(*finalize)		(LsmProperty *property);
-	void		(*from_text)		(LsmProperty *property, const char *value);
-	char * 		(*to_text)		(LsmProperty *property);
-} LsmPropertyClass;
-
-typedef struct {
-	char const *			name;
-	guint16				id;
-	const LsmPropertyClass *	property_class;
+	char const *		name;
+	guint16			id;
+	const LsmTraitClass *	trait_class;
 } LsmPropertyInfos;
 
 typedef struct {
@@ -56,15 +51,18 @@ LsmPropertyManager *	lsm_property_manager_new	(unsigned int n_properties,
 							 const LsmPropertyInfos *property_infos);
 void			lsm_property_manager_free	(LsmPropertyManager *manager);
 
-void 		lsm_property_bag_set_property 		(LsmPropertyBag *property_bag,
-							 LsmPropertyManager *manager,
-							 const char *name, const char *value);
-const char *	lsm_property_bag_get_property 		(LsmPropertyBag *property_bag,
-							 LsmPropertyManager *manager,
+gboolean 	lsm_property_manager_set_property 	(LsmPropertyManager *manager,
+							 LsmPropertyBag *property_bag,
+							 const char *name,
+							 const char *value);
+const char *	lsm_property_manager_get_property 	(LsmPropertyManager *manager,
+							 LsmPropertyBag *property_bag,
 							 const char *name);
-void		lsm_property_bag_clean			(LsmPropertyBag *property_bag,
-							 LsmPropertyManager *manager);
-char * 		lsm_property_bag_serialize 		(LsmPropertyBag *property_bag,
-							 LsmPropertyManager *property_manager);
+void		lsm_property_manager_clean_properties	(LsmPropertyManager *manager,
+							 LsmPropertyBag *property_bag);
+char * 		lsm_property_manager_serialize 		(LsmPropertyManager *property_manager,
+							 LsmPropertyBag *property_bag);
 
 G_END_DECLS
+
+#endif
diff --git a/src/lsmsvgutils.c b/src/lsmstr.c
similarity index 88%
rename from src/lsmsvgutils.c
rename to src/lsmstr.c
index dd7a02e..486af43 100644
--- a/src/lsmsvgutils.c
+++ b/src/lsmstr.c
@@ -19,12 +19,12 @@
  * 	Emmanuel Pacaud <emmanuel gnome org>
  */
 
-#include <lsmsvgutils.h>
+#include <lsmstr.h>
 #include <stdio.h>
 #include <math.h>
 
 gboolean
-lsm_svg_str_parse_double (char **str, double *x)
+lsm_str_parse_double (char **str, double *x)
 {
 	char *end, *c;
 	gboolean integer_part = FALSE;
@@ -112,19 +112,19 @@ lsm_svg_str_parse_double (char **str, double *x)
 }
 
 gboolean
-lsm_svg_str_parse_double_list (char **str, unsigned int n_values, double *values)
+lsm_str_parse_double_list (char **str, unsigned int n_values, double *values)
 {
 	char *ptr = *str;
 	unsigned int i;
 
-	lsm_svg_str_skip_comma_and_spaces (str);
+	lsm_str_skip_comma_and_spaces (str);
 
 	for (i = 0; i < n_values; i++) {
-		if (!lsm_svg_str_parse_double (str, &values[i])) {
+		if (!lsm_str_parse_double (str, &values[i])) {
 			*str = ptr;
 			return FALSE;
 		}
-		lsm_svg_str_skip_comma_and_spaces (str);
+		lsm_str_skip_comma_and_spaces (str);
 	}
 
 	return TRUE;
diff --git a/src/lsmsvgutils.h b/src/lsmstr.h
similarity index 73%
copy from src/lsmsvgutils.h
copy to src/lsmstr.h
index 828772d..e091128 100644
--- a/src/lsmsvgutils.h
+++ b/src/lsmstr.h
@@ -20,46 +20,46 @@
  */
 
 
-#ifndef GSGV_UTILS_H
-#define GSGV_UTILS_H
+#ifndef LSM_STR_H
+#define LSM_STR_H
 
-#include <lsmsvg.h>
+#include <lsm.h>
 
 G_BEGIN_DECLS
 
-gboolean lsm_svg_str_parse_double 	(char **str, double *x);
-gboolean lsm_svg_str_parse_double_list 	(char **str, unsigned int n_values, double *values);
+gboolean lsm_str_parse_double 		(char **str, double *x);
+gboolean lsm_str_parse_double_list 	(char **str, unsigned int n_values, double *values);
 
 static inline void
-lsm_svg_str_skip_spaces (char **str)
+lsm_str_skip_spaces (char **str)
 {
 	while (g_ascii_isspace (**str))
 		(*str)++;
 }
 
 static inline void
-lsm_svg_str_skip_char (char **str, char c)
+lsm_str_skip_char (char **str, char c)
 {
 	while (**str == c)
 		(*str)++;
 }
 
 static inline void
-lsm_svg_str_skip_comma_and_spaces (char **str)
+lsm_str_skip_comma_and_spaces (char **str)
 {
 	while (g_ascii_isspace (**str) || **str == ',')
 		(*str)++;
 }
 
 static inline void
-lsm_svg_str_skip_semicolon_and_spaces (char **str)
+lsm_str_skip_semicolon_and_spaces (char **str)
 {
 	while (g_ascii_isspace (**str) || **str == ';')
 		(*str)++;
 }
 
 static inline void
-lsm_svg_str_skip_colon_and_spaces (char **str)
+lsm_str_skip_colon_and_spaces (char **str)
 {
 	while (g_ascii_isspace (**str) || **str == ':')
 		(*str)++;
diff --git a/src/lsmsvgattributes.c b/src/lsmsvgattributes.c
index c213fc5..d5f1928 100644
--- a/src/lsmsvgattributes.c
+++ b/src/lsmsvgattributes.c
@@ -21,61 +21,14 @@
 
 #include <lsmsvgattributes.h>
 #include <lsmsvgcolors.h>
-#include <lsmsvgutils.h>
 #include <lsmsvgstyle.h>
+#include <lsmstr.h>
 #include <lsmdebug.h>
 #include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <math.h>
 
-const LsmSvgDashArray lsm_svg_dash_array_null = {0, NULL};
-
-LsmSvgDashArray *
-lsm_svg_dash_array_new (unsigned int n_dashes)
-{
-	LsmSvgDashArray *array;
-
-	g_return_val_if_fail (n_dashes > 0, (LsmSvgDashArray *) &lsm_svg_dash_array_null);
-
-	array = g_new (LsmSvgDashArray, 1);
-	if (array != NULL) {
-		array->n_dashes = n_dashes;
-		array->dashes = g_new (LsmSvgLength, n_dashes);
-		if (array->dashes != NULL)
-			return array;
-		g_free (array);
-	}
-
-	return (LsmSvgDashArray *) &lsm_svg_dash_array_null;
-}
-
-void
-lsm_svg_dash_array_free (LsmSvgDashArray *array)
-{
-	if (array == NULL || array == &lsm_svg_dash_array_null)
-		return;
-
-	g_free (array->dashes);
-	g_free (array);
-}
-
-LsmSvgDashArray *
-lsm_svg_dash_array_duplicate (const LsmSvgDashArray *origin)
-{
-	LsmSvgDashArray *duplicate;
-
-	if (origin == NULL || origin == &lsm_svg_dash_array_null)
-		return (LsmSvgDashArray *) &lsm_svg_dash_array_null;
-
-	duplicate = lsm_svg_dash_array_new (origin->n_dashes);
-
-	if (duplicate != &lsm_svg_dash_array_null)
-		memcpy (duplicate->dashes, origin->dashes, sizeof (LsmSvgLength) * origin->n_dashes);
-
-	return duplicate;
-}
-
 static const char *
 lsm_svg_attribute_get_value (LsmDomAttribute *attribute)
 {
@@ -89,8 +42,6 @@ lsm_svg_attribute_get_value (LsmDomAttribute *attribute)
 	return string;
 }
 
-const LsmSvgColor lsm_svg_color_null = {0.0, 0.0, 0.0};
-
 void
 lsm_svg_double_attribute_parse (LsmSvgDoubleAttribute *attribute,
 				double *double_value)
@@ -204,10 +155,10 @@ lsm_svg_dash_array_attribute_parse (LsmSvgDashArrayAttribute *attribute,
 				LsmSvgLength length;
 
 				iter = (char *)string;
-				lsm_svg_str_skip_spaces (&iter);
+				lsm_str_skip_spaces (&iter);
 
 				for (i = 0; i < n_dashes; i++) {
-					if (lsm_svg_str_parse_double (&iter, &length.value_unit)) {
+					if (lsm_str_parse_double (&iter, &length.value_unit)) {
 						length.type = lsm_svg_length_type_from_string (iter);
 						attribute->value->dashes[i] = length;
 						while (*iter != '\0' && *iter != ' ' && *iter != ',')
@@ -216,7 +167,7 @@ lsm_svg_dash_array_attribute_parse (LsmSvgDashArrayAttribute *attribute,
 						attribute->value->dashes[i].value_unit = 0.0;
 						attribute->value->dashes[i].value_unit = LSM_SVG_LENGTH_TYPE_NUMBER;
 					}
-					lsm_svg_str_skip_comma_and_spaces (&iter);
+					lsm_str_skip_comma_and_spaces (&iter);
 				}
 			}
 		}
@@ -270,7 +221,7 @@ _parse_color (char *string,
 	unsigned int color = 0;
 	*color_set = FALSE;
 
-	lsm_svg_str_skip_spaces (&string);
+	lsm_str_skip_spaces (&string);
 
 	if (g_strcmp0 (string, "currentColor") == 0) {
 		*svg_color = *current_color;
@@ -314,7 +265,7 @@ _parse_color (char *string,
 		string += 4; /* strlen ("rgb(") */
 
 		for (i = 0; i < 3; i++) {
-			if (!lsm_svg_str_parse_double (&string, &value))
+			if (!lsm_str_parse_double (&string, &value))
 				break;
 
 			if (*string == '%') {
@@ -323,12 +274,12 @@ _parse_color (char *string,
 			}
 
 			if (i < 2)
-				lsm_svg_str_skip_comma_and_spaces (&string);
+				lsm_str_skip_comma_and_spaces (&string);
 
 			color = (color << 8) + (int) (0.5 + CLAMP (value, 0.0, 255.0));
 		}
 
-		lsm_svg_str_skip_spaces (&string);
+		lsm_str_skip_spaces (&string);
 
 		if (*string != ')' || i != 3)
 			color = 0;
@@ -461,9 +412,9 @@ lsm_svg_viewbox_attribute_parse (LsmSvgViewboxAttribute *attribute)
 		double value[4];
 
 		for (i = 0; i < 4 && *string != '\0'; i++) {
-			lsm_svg_str_skip_semicolon_and_spaces (&string);
+			lsm_str_skip_semicolon_and_spaces (&string);
 
-			if (!lsm_svg_str_parse_double (&string, &value[i]))
+			if (!lsm_str_parse_double (&string, &value[i]))
 				break;
 		}
 
@@ -565,7 +516,7 @@ lsm_svg_transform_attribute_parse (LsmSvgTransformAttribute *attribute)
 			LsmSvgTransformType transform;
 			double values[6];
 
-			lsm_svg_str_skip_spaces (&string);
+			lsm_str_skip_spaces (&string);
 
 			if (strncmp (string, "translate", 9) == 0) {
 				transform = LSM_SVG_TRANSFORM_TYPE_TRANSLATE;
@@ -588,7 +539,7 @@ lsm_svg_transform_attribute_parse (LsmSvgTransformAttribute *attribute)
 			} else
 				break;
 
-			lsm_svg_str_skip_spaces (&string);
+			lsm_str_skip_spaces (&string);
 
 			if (*string == '(') {
 				unsigned int n_values = 0;
@@ -596,15 +547,15 @@ lsm_svg_transform_attribute_parse (LsmSvgTransformAttribute *attribute)
 				string++;
 
 				while (*string != ')' && *string != '\0' && n_values < 6) {
-					lsm_svg_str_skip_comma_and_spaces (&string);
+					lsm_str_skip_comma_and_spaces (&string);
 
-					if (!lsm_svg_str_parse_double (&string, &values[n_values]))
+					if (!lsm_str_parse_double (&string, &values[n_values]))
 						break;
 
 					n_values++;
 				}
 
-				lsm_svg_str_skip_comma_and_spaces (&string);
+				lsm_str_skip_comma_and_spaces (&string);
 
 				if (*string == ')') {
 					LsmSvgMatrix matrix;
diff --git a/src/lsmsvgattributes.h b/src/lsmsvgattributes.h
index 4db88ad..9027064 100644
--- a/src/lsmsvgattributes.h
+++ b/src/lsmsvgattributes.h
@@ -27,6 +27,7 @@
 #include <lsmdomview.h>
 #include <lsmsvg.h>
 #include <lsmsvgenums.h>
+#include <lsmsvgtraits.h>
 #include <lsmsvglength.h>
 #include <lsmsvgmatrix.h>
 
@@ -38,36 +39,11 @@ typedef struct {
 } LsmSvgDoubleAttribute;
 
 typedef struct {
-	double red;
-	double green;
-	double blue;
-} LsmSvgColor;
-
-extern const LsmSvgColor lsm_svg_color_null;
-
-typedef struct {
-	unsigned int n_dashes;
-	LsmSvgLength *dashes;
-} LsmSvgDashArray;
-
-extern const LsmSvgDashArray lsm_svg_dash_array_null;
-
-LsmSvgDashArray * 	lsm_svg_dash_array_new 		(unsigned int n_dashes);
-void 			lsm_svg_dash_array_free 	(LsmSvgDashArray *array);
-LsmSvgDashArray * 	lsm_svg_dash_array_duplicate 	(const LsmSvgDashArray *origin);
-
-typedef struct {
 	LsmDomAttribute attr;
 	LsmSvgDashArray *value;
 } LsmSvgDashArrayAttribute;
 
 typedef struct {
-	LsmSvgPaintType type;
-	char *uri;
-	LsmSvgColor color;
-} LsmSvgPaint;
-
-typedef struct {
 	LsmDomAttribute attr;
 	LsmSvgLength length;
 	double value;
@@ -105,12 +81,6 @@ typedef struct {
 } LsmSvgTransformAttribute;
 
 typedef struct {
-	gboolean defer;
-	LsmSvgAlign align;
-	LsmSvgMeetOrSlice meet_or_slice;
-} LsmSvgPreserveAspectRatio;
-
-typedef struct {
 	LsmDomAttribute attr;
 	LsmSvgPreserveAspectRatio value;
 } LsmSvgPreserveAspectRatioAttribute;
diff --git a/src/lsmsvgcircleelement.c b/src/lsmsvgcircleelement.c
index ac85261..3750f7d 100644
--- a/src/lsmsvgcircleelement.c
+++ b/src/lsmsvgcircleelement.c
@@ -35,6 +35,7 @@ lsm_svg_circle_element_get_node_name (LsmDomNode *node)
 
 /* LsmSvgElement implementation */
 
+#if 0
 static void
 lsm_svg_circle_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 {
@@ -55,6 +56,7 @@ lsm_svg_circle_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 
 	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
 }
+#endif
 
 /* LsmSvgGraphic implementation */
 
@@ -95,6 +97,29 @@ lsm_svg_circle_element_finalize (GObject *object)
 
 /* LsmSvgCircleElement class */
 
+static const LsmSvgLength length_default = 	 { .value_unit =   0.0, .type = LSM_SVG_LENGTH_TYPE_PX};
+
+static const LsmAttributeInfos lsm_svg_circle_element_attribute_infos[] = {
+	{
+		.name = "cx",
+		.attribute_offset = offsetof (LsmSvgCircleElement, cx),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &length_default
+	},
+	{
+		.name = "cy",
+		.attribute_offset = offsetof (LsmSvgCircleElement, cy),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &length_default
+	},
+	{
+		.name = "r",
+		.attribute_offset = offsetof (LsmSvgCircleElement, r),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &length_default
+	}
+};
+
 static void
 lsm_svg_circle_element_class_init (LsmSvgCircleElementClass *s_rect_class)
 {
@@ -109,18 +134,24 @@ lsm_svg_circle_element_class_init (LsmSvgCircleElementClass *s_rect_class)
 
 	d_node_class->get_node_name = lsm_svg_circle_element_get_node_name;
 
-	s_element_class->update = lsm_svg_circle_element_update;
+/*        s_element_class->update = lsm_svg_circle_element_update;*/
 
 	s_graphic_class->graphic_render = lsm_svg_circle_element_graphic_render;
 
-	s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
+	s_element_class->attribute_manager = lsm_attribute_manager_duplicate (s_element_class->attribute_manager);
+
+	lsm_attribute_manager_add_attributes (s_element_class->attribute_manager,
+					      G_N_ELEMENTS (lsm_svg_circle_element_attribute_infos),
+					      lsm_svg_circle_element_attribute_infos);
+
+/*        s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);*/
 
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "cx",
-					  offsetof (LsmSvgCircleElement, cx));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "cy",
-					  offsetof (LsmSvgCircleElement, cy));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "r",
-					  offsetof (LsmSvgCircleElement, r));
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "cx",*/
+/*                                          offsetof (LsmSvgCircleElement, cx));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "cy",*/
+/*                                          offsetof (LsmSvgCircleElement, cy));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "r",*/
+/*                                          offsetof (LsmSvgCircleElement, r));*/
 }
 
 G_DEFINE_TYPE (LsmSvgCircleElement, lsm_svg_circle_element, LSM_TYPE_SVG_GRAPHIC)
diff --git a/src/lsmsvgclippathelement.c b/src/lsmsvgclippathelement.c
index 0bbdcdf..2e35276 100644
--- a/src/lsmsvgclippathelement.c
+++ b/src/lsmsvgclippathelement.c
@@ -36,6 +36,7 @@ _clip_path_element_get_node_name (LsmDomNode *node)
 
 /* LsmSvgElement implementation */
 
+#if 0
 static void
 _clip_path_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 {
@@ -47,6 +48,7 @@ _clip_path_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 
 	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
 }
+#endif
 
 static void
 _clip_path_element_render_clip (LsmSvgElement *self, LsmSvgView *view)
@@ -97,6 +99,14 @@ lsm_svg_clip_path_element_init (LsmSvgClipPathElement *self)
 
 /* LsmSvgClipPathElement class */
 
+static const LsmAttributeInfos lsm_svg_clip_path_element_attribute_infos[] = {
+	{
+		.name = "clipPathUnits",
+		.trait_class = &lsm_svg_pattern_units_trait_class,
+		.attribute_offset = offsetof (LsmSvgClipPathElement, units)
+	}
+};
+
 static void
 lsm_svg_clip_path_element_class_init (LsmSvgClipPathElementClass *klass)
 {
@@ -107,14 +117,20 @@ lsm_svg_clip_path_element_class_init (LsmSvgClipPathElementClass *klass)
 
 	d_node_class->get_node_name = _clip_path_element_get_node_name;
 
-	s_element_class->update = _clip_path_element_update;
+/*        s_element_class->update = _clip_path_element_update;*/
 	s_element_class->render_clip = _clip_path_element_render_clip;
 	s_element_class->render = NULL;
 
-	s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
+	s_element_class->attribute_manager = lsm_attribute_manager_duplicate (s_element_class->attribute_manager);
+
+	lsm_attribute_manager_add_attributes (s_element_class->attribute_manager,
+					      G_N_ELEMENTS (lsm_svg_clip_path_element_attribute_infos),
+					      lsm_svg_clip_path_element_attribute_infos);
+
+/*        s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);*/
 
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "clipPathUnits",
-					     offsetof (LsmSvgClipPathElement, units));
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "clipPathUnits",*/
+/*                                             offsetof (LsmSvgClipPathElement, units));*/
 }
 
 G_DEFINE_TYPE (LsmSvgClipPathElement, lsm_svg_clip_path_element, LSM_TYPE_SVG_GRAPHIC)
diff --git a/src/lsmsvgelement.c b/src/lsmsvgelement.c
index cdb37a4..478d34e 100644
--- a/src/lsmsvgelement.c
+++ b/src/lsmsvgelement.c
@@ -20,6 +20,8 @@
  */
 
 #include <lsmdebug.h>
+#include <lsmattributes.h>
+#include <lsmproperties.h>
 #include <lsmdomdocument.h>
 #include <lsmsvgelement.h>
 #include <lsmsvgview.h>
@@ -59,18 +61,30 @@ lsm_svg_element_set_attribute (LsmDomElement *self, const char* name, const char
 	lsm_debug ("[LsmSvgElement::set_attribute] node = %s, name = %s, value = %s",
 		    lsm_dom_node_get_node_name (LSM_DOM_NODE (self)), name, value);
 
-	lsm_dom_attribute_map_set_attribute (s_element_class->attributes, self,
-					     name, value);
+/*        lsm_dom_attribute_map_set_attribute (s_element_class->attributes, self,*/
+/*                                             name, value);*/
 
-	lsm_svg_property_bag_set_property (&s_element->property_bag, name, value);
+	/* TODO Avoid double hash table lookup */
+	if (!lsm_attribute_manager_set_attribute (s_element_class->attribute_manager,
+						  self, name, value))
+		lsm_svg_property_bag_set_property (&s_element->property_bag, name, value);
 }
 
 const char *
 lsm_svg_element_get_attribute (LsmDomElement *self, const char *name)
 {
 	LsmSvgElementClass *s_element_class = LSM_SVG_ELEMENT_GET_CLASS(self);
+	LsmSvgElement *s_element = LSM_SVG_ELEMENT (self);
+	const char *value;
+
+	/* TODO Avoid double hash table lookup */
+	value = lsm_attribute_manager_get_attribute (s_element_class->attribute_manager,
+						     self, name);
+	if (value != NULL)
+		return value;
 
-	return lsm_dom_attribute_map_get_attribute (s_element_class->attributes, self, name);
+	return lsm_svg_property_bag_get_property (&s_element->property_bag, name);
+/*        return lsm_dom_attribute_map_get_attribute (s_element_class->attributes, self, name);*/
 }
 
 /* LsmSvgElement implementation */
@@ -237,6 +251,24 @@ lsm_svg_element_finalize (GObject *object)
 
 /* LsmSvgElement class */
 
+static const LsmAttributeInfos lsm_svg_attribute_infos[] = {
+	{
+		.name = "id",
+		.trait_class = &lsm_null_trait_class,
+		.attribute_offset = offsetof (LsmSvgElement, id)
+	},
+	{
+		.name = "class",
+		.trait_class = &lsm_null_trait_class,
+		.attribute_offset = offsetof (LsmSvgElement, class_name)
+	},
+	{
+		.name = "style",
+		.trait_class = &lsm_null_trait_class,
+		.attribute_offset = offsetof (LsmSvgElement, style)
+	}
+};
+
 static void
 lsm_svg_element_class_init (LsmSvgElementClass *s_element_class)
 {
@@ -258,10 +290,12 @@ lsm_svg_element_class_init (LsmSvgElementClass *s_element_class)
 	s_element_class->render = _render;
 	s_element_class->render_paint = NULL;
 
-	s_element_class->attributes = lsm_dom_attribute_map_new ();
+	s_element_class->attribute_manager = lsm_attribute_manager_new (G_N_ELEMENTS (lsm_svg_attribute_infos),
+									lsm_svg_attribute_infos);
+/*        s_element_class->attributes = lsm_dom_attribute_map_new ();*/
 
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "id",
-					  offsetof (LsmSvgElement, id));
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "id",*/
+/*                                          offsetof (LsmSvgElement, id));*/
 }
 
 G_DEFINE_ABSTRACT_TYPE (LsmSvgElement, lsm_svg_element, LSM_TYPE_DOM_ELEMENT)
diff --git a/src/lsmsvgelement.h b/src/lsmsvgelement.h
index 42fc3a1..18f654c 100644
--- a/src/lsmsvgelement.h
+++ b/src/lsmsvgelement.h
@@ -24,6 +24,7 @@
 #define LSM_SVG_ELEMENT_H
 
 #include <lsmsvg.h>
+#include <lsmattributes.h>
 #include <lsmsvgattributes.h>
 #include <lsmsvgattributebags.h>
 #include <lsmsvgstyle.h>
@@ -46,7 +47,9 @@ struct _LsmSvgElement {
 
 	LsmPropertyBag property_bag;
 
-	LsmDomAttribute	id;
+	LsmAttribute	id;
+	LsmAttribute	class_name;
+	LsmAttribute	style;
 
 	/* View */
 
@@ -57,7 +60,8 @@ struct _LsmSvgElement {
 struct _LsmSvgElementClass {
 	LsmDomElementClass  parent_class;
 
-	LsmDomAttributeMap *attributes;
+//        LsmDomAttributeMap *attributes;
+	LsmAttributeManager *attribute_manager;
 
 	void		(*update)		(LsmSvgElement *element, LsmSvgStyle *style);
 	void 		(*render)		(LsmSvgElement *element, LsmSvgView *view);
diff --git a/src/lsmsvgellipseelement.c b/src/lsmsvgellipseelement.c
index 233b539..f6bccac 100644
--- a/src/lsmsvgellipseelement.c
+++ b/src/lsmsvgellipseelement.c
@@ -34,6 +34,7 @@ lsm_svg_ellipse_element_get_node_name (LsmDomNode *node)
 
 /* LsmSvgElement implementation */
 
+#if 0
 static void
 lsm_svg_ellipse_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 {
@@ -58,6 +59,7 @@ lsm_svg_ellipse_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 
 	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
 }
+#endif
 
 /* LsmSvgGraphic implementation */
 
@@ -96,6 +98,35 @@ lsm_svg_ellipse_element_finalize (GObject *object)
 
 /* LsmSvgEllipseElement class */
 
+static const LsmSvgLength length_default = 	 { .value_unit =   0.0, .type = LSM_SVG_LENGTH_TYPE_PX};
+
+static const LsmAttributeInfos lsm_svg_ellipse_element_attribute_infos[] = {
+	{
+		.name = "cx",
+		.attribute_offset = offsetof (LsmSvgEllipseElement, cx),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &length_default
+	},
+	{
+		.name = "cy",
+		.attribute_offset = offsetof (LsmSvgEllipseElement, cy),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &length_default
+	},
+	{
+		.name = "rx",
+		.attribute_offset = offsetof (LsmSvgEllipseElement, rx),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &length_default
+	},
+	{
+		.name = "ry",
+		.attribute_offset = offsetof (LsmSvgEllipseElement, ry),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &length_default
+	}
+};
+
 static void
 lsm_svg_ellipse_element_class_init (LsmSvgEllipseElementClass *s_rect_class)
 {
@@ -110,20 +141,26 @@ lsm_svg_ellipse_element_class_init (LsmSvgEllipseElementClass *s_rect_class)
 
 	d_node_class->get_node_name = lsm_svg_ellipse_element_get_node_name;
 
-	s_element_class->update = lsm_svg_ellipse_element_update;
+/*        s_element_class->update = lsm_svg_ellipse_element_update;*/
 
 	s_graphic_class->graphic_render = lsm_svg_ellipse_element_graphic_render;
 
-	s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
+	s_element_class->attribute_manager = lsm_attribute_manager_duplicate (s_element_class->attribute_manager);
+
+	lsm_attribute_manager_add_attributes (s_element_class->attribute_manager,
+					      G_N_ELEMENTS (lsm_svg_ellipse_element_attribute_infos),
+					      lsm_svg_ellipse_element_attribute_infos);
+
+/*        s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);*/
 
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "cx",
-					  offsetof (LsmSvgEllipseElement, cx));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "cy",
-					  offsetof (LsmSvgEllipseElement, cy));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "rx",
-					  offsetof (LsmSvgEllipseElement, rx));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "ry",
-					  offsetof (LsmSvgEllipseElement, ry));
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "cx",*/
+/*                                          offsetof (LsmSvgEllipseElement, cx));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "cy",*/
+/*                                          offsetof (LsmSvgEllipseElement, cy));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "rx",*/
+/*                                          offsetof (LsmSvgEllipseElement, rx));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "ry",*/
+/*                                          offsetof (LsmSvgEllipseElement, ry));*/
 }
 
 G_DEFINE_TYPE (LsmSvgEllipseElement, lsm_svg_ellipse_element, LSM_TYPE_SVG_GRAPHIC)
diff --git a/src/lsmsvggradientelement.c b/src/lsmsvggradientelement.c
index 2b441b7..3487ccf 100644
--- a/src/lsmsvggradientelement.c
+++ b/src/lsmsvggradientelement.c
@@ -37,6 +37,7 @@ lsm_svg_gradient_element_can_append_child (LsmDomNode *parent, LsmDomNode *child
 
 /* LsmSvgElement implementation */
 
+#if 0
 static void
 _gradient_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 {
@@ -53,6 +54,7 @@ _gradient_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 
 	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
 }
+#endif
 
 static void
 _gradient_element_graphic_render (LsmSvgElement *self, LsmSvgView *view)
@@ -101,6 +103,36 @@ lsm_svg_gradient_element_init (LsmSvgGradientElement *self)
 
 /* LsmSvgGradientElement class */
 
+static const LsmSvgPatternUnits units_default = LSM_SVG_PATTERN_UNITS_OBJECT_BOUNDING_BOX;
+static const LsmSvgSpreadMethod spread_method_default = LSM_SVG_SPREAD_METHOD_PAD;
+static const LsmSvgMatrix matrix_default = {1.0, 0.0, 0.0, 1.0, 0.0, 0.0};
+
+static const LsmAttributeInfos lsm_svg_gradient_element_attribute_infos[] = {
+	{
+		.name = "gradientUnits",
+		.attribute_offset = offsetof (LsmSvgGradientElement, units),
+		.trait_class = &lsm_svg_pattern_units_trait_class,
+		.trait_default = &units_default
+	},
+	{
+		.name = "gradientTransform",
+		.attribute_offset = offsetof (LsmSvgGradientElement, transform),
+		.trait_class = &lsm_svg_matrix_trait_class,
+		.trait_default = &matrix_default
+	},
+	{
+		.name = "spreadMethod",
+		.attribute_offset = offsetof (LsmSvgGradientElement, spread_method),
+		.trait_class = &lsm_svg_spread_method_trait_class,
+		.trait_default = &spread_method_default
+	},
+	{
+		.name = "xlink:href",
+		.attribute_offset = offsetof (LsmSvgGradientElement, href),
+		.trait_class = &lsm_null_trait_class
+	}
+};
+
 static void
 lsm_svg_gradient_element_class_init (LsmSvgGradientElementClass *klass)
 {
@@ -112,21 +144,27 @@ lsm_svg_gradient_element_class_init (LsmSvgGradientElementClass *klass)
 
 	d_node_class->can_append_child = lsm_svg_gradient_element_can_append_child;
 
-	s_element_class->update = _gradient_element_update;
+/*        s_element_class->update = _gradient_element_update;*/
 	s_element_class->render_paint = s_element_class->render;
 	s_element_class->render = NULL;
 	s_graphic_class->graphic_render = _gradient_element_graphic_render;
 
-	s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
+	s_element_class->attribute_manager = lsm_attribute_manager_duplicate (s_element_class->attribute_manager);
+
+	lsm_attribute_manager_add_attributes (s_element_class->attribute_manager,
+					      G_N_ELEMENTS (lsm_svg_gradient_element_attribute_infos),
+					      lsm_svg_gradient_element_attribute_infos);
+
+/*        s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);*/
 
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "gradientUnits",
-					  offsetof (LsmSvgGradientElement, units));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "gradientTransform",
-					  offsetof (LsmSvgGradientElement, transform));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "spreadMethod",
-					  offsetof (LsmSvgGradientElement, spread_method));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "xlink:href",
-					  offsetof (LsmSvgGradientElement, href));
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "gradientUnits",*/
+/*                                          offsetof (LsmSvgGradientElement, units));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "gradientTransform",*/
+/*                                          offsetof (LsmSvgGradientElement, transform));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "spreadMethod",*/
+/*                                          offsetof (LsmSvgGradientElement, spread_method));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "xlink:href",*/
+/*                                          offsetof (LsmSvgGradientElement, href));*/
 }
 
 G_DEFINE_ABSTRACT_TYPE (LsmSvgGradientElement, lsm_svg_gradient_element, LSM_TYPE_SVG_GRAPHIC)
diff --git a/src/lsmsvggraphic.c b/src/lsmsvggraphic.c
index 4974377..3cf12c7 100644
--- a/src/lsmsvggraphic.c
+++ b/src/lsmsvggraphic.c
@@ -21,7 +21,7 @@
 
 #include <lsmsvggraphic.h>
 #include <lsmsvgview.h>
-#include <lsmsvgutils.h>
+#include <lsmstr.h>
 #include <lsmdebug.h>
 
 static GObjectClass *parent_class;
@@ -29,11 +29,12 @@ static GObjectClass *parent_class;
 static void
 lsm_svg_graphic_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 {
+	/* Handle inline style here for now. This should move to the CSS handling part. */
+
+	/*
 	LsmSvgGraphic *graphic = LSM_SVG_GRAPHIC (self);
 	double default_opacity;
 
-	/* Handle inline style here for now. This should move to the CSS handling part. */
-
 	if (graphic->style.value != NULL) {
 		LsmSvgElementClass *s_element_class = LSM_SVG_ELEMENT_GET_CLASS (self);
 		char *inline_style;
@@ -89,7 +90,10 @@ lsm_svg_graphic_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 			g_free (inline_style);
 		}
 	}
+	*/
 
+	/* TODO */
+#if 0
 	lsm_svg_color_attribute_parse (&graphic->color, &parent_style->color, &parent_style->color);
 
 
@@ -140,6 +144,7 @@ lsm_svg_graphic_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 					       &graphic->color.value);
 		lsm_svg_double_attribute_parse (&graphic->stop->opacity, &parent_style->stop.opacity);
 	}
+#endif
 }
 
 static void
@@ -275,22 +280,22 @@ lsm_svg_graphic_class_init (LsmSvgGraphicClass *s_graphic_class)
 	s_graphic_class->graphic_render = _graphic_render;
 	s_graphic_class->graphic_get_extents = _graphic_get_extents;
 
-	s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
-
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "class",
-					     offsetof (LsmSvgGraphic, class_name));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "style",
-					     offsetof (LsmSvgGraphic, style));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "color",
-					     offsetof (LsmSvgGraphic, color));
-
-	lsm_dom_attribute_map_add_mask_attribute_bag (s_element_class->attributes, offsetof (LsmSvgGraphic, mask));
-	lsm_dom_attribute_map_add_fill_attribute_bag (s_element_class->attributes, offsetof (LsmSvgGraphic, fill));
-	lsm_dom_attribute_map_add_stroke_attribute_bag (s_element_class->attributes, offsetof (LsmSvgGraphic, stroke));
-	lsm_dom_attribute_map_add_transform_attribute_bag (s_element_class->attributes,
-							   offsetof (LsmSvgGraphic, transform));
-	lsm_dom_attribute_map_add_text_attribute_bag (s_element_class->attributes, offsetof (LsmSvgGraphic, text));
-	lsm_dom_attribute_map_add_stop_attribute_bag (s_element_class->attributes, offsetof (LsmSvgGraphic, stop));
+/*        s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);*/
+
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "class",*/
+/*                                             offsetof (LsmSvgGraphic, class_name));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "style",*/
+/*                                             offsetof (LsmSvgGraphic, style));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "color",*/
+/*                                             offsetof (LsmSvgGraphic, color));*/
+
+/*        lsm_dom_attribute_map_add_mask_attribute_bag (s_element_class->attributes, offsetof (LsmSvgGraphic, mask));*/
+/*        lsm_dom_attribute_map_add_fill_attribute_bag (s_element_class->attributes, offsetof (LsmSvgGraphic, fill));*/
+/*        lsm_dom_attribute_map_add_stroke_attribute_bag (s_element_class->attributes, offsetof (LsmSvgGraphic, stroke));*/
+/*        lsm_dom_attribute_map_add_transform_attribute_bag (s_element_class->attributes,*/
+/*                                                           offsetof (LsmSvgGraphic, transform));*/
+/*        lsm_dom_attribute_map_add_text_attribute_bag (s_element_class->attributes, offsetof (LsmSvgGraphic, text));*/
+/*        lsm_dom_attribute_map_add_stop_attribute_bag (s_element_class->attributes, offsetof (LsmSvgGraphic, stop));*/
 }
 
 G_DEFINE_ABSTRACT_TYPE (LsmSvgGraphic, lsm_svg_graphic, LSM_TYPE_SVG_ELEMENT)
diff --git a/src/lsmsvggraphic.h b/src/lsmsvggraphic.h
index 5750845..d17e768 100644
--- a/src/lsmsvggraphic.h
+++ b/src/lsmsvggraphic.h
@@ -39,11 +39,12 @@ typedef struct _LsmSvgGraphicClass LsmSvgGraphicClass;
 struct _LsmSvgGraphic {
 	LsmSvgElement	element;
 
-	LsmDomAttribute	class_name;
-	LsmDomAttribute	style;
+//        LsmDomAttribute	class_name;
+//        LsmDomAttribute	style;
 
-	LsmSvgColorAttribute color;
+//        LsmSvgColorAttribute color;
 
+	/* FIXME kill kill kill ! */
 	LsmSvgMaskAttributeBag *mask;
 	LsmSvgFillAttributeBag *fill;
 	LsmSvgStrokeAttributeBag *stroke;
diff --git a/src/lsmsvgimageelement.c b/src/lsmsvgimageelement.c
index 0b4b2db..3aeb1ed 100644
--- a/src/lsmsvgimageelement.c
+++ b/src/lsmsvgimageelement.c
@@ -48,8 +48,9 @@ static void
 lsm_svg_image_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 {
 	LsmSvgImageElement *image_element = LSM_SVG_IMAGE_ELEMENT (self);
-	LsmSvgLength length;
 	const char *href;
+#if 0
+	LsmSvgLength length;
 
 	length.value_unit = 0.0;
 	length.type = LSM_SVG_LENGTH_TYPE_PX;
@@ -68,7 +69,7 @@ lsm_svg_image_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 	lsm_svg_animated_length_attribute_parse (&image_element->height, &length);
 
 	lsm_svg_preserve_aspect_ratio_attribute_parse (&image_element->preserve_aspect_ratio);
-
+#endif
 	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
 
 	if (image_element->pixbuf != NULL) {
@@ -178,6 +179,51 @@ lsm_svg_image_element_finalize (GObject *gobject)
 
 /* LsmSvgImageElement class */
 
+static const LsmSvgLength length_default = 	 { .value_unit =   0.0, .type = LSM_SVG_LENGTH_TYPE_PX};
+static const LsmSvgPreserveAspectRatio preserve_aspect_ratio_default = {
+	.defer = FALSE,
+	.align = LSM_SVG_ALIGN_X_MID_Y_MID,
+	.meet_or_slice = LSM_SVG_MEET_OR_SLICE_MEET
+};
+
+static const LsmAttributeInfos lsm_svg_image_element_attribute_infos[] = {
+	{
+		.name = "x",
+		.attribute_offset = offsetof (LsmSvgImageElement, x),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &length_default
+	},
+	{
+		.name = "y",
+		.attribute_offset = offsetof (LsmSvgImageElement, y),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &length_default
+	},
+	{
+		.name = "width",
+		.attribute_offset = offsetof (LsmSvgImageElement, width),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &length_default
+	},
+	{
+		.name = "height",
+		.attribute_offset = offsetof (LsmSvgImageElement, height),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &length_default
+	},
+	{
+		.name = "xlink:href",
+		.attribute_offset = offsetof (LsmSvgImageElement, href),
+		.trait_class = &lsm_null_trait_class
+	},
+	{
+		.name = "preserveAspectRatio",
+		.attribute_offset = offsetof (LsmSvgImageElement, preserve_aspect_ratio),
+		.trait_class = &lsm_svg_preserve_aspect_ratio_trait_class,
+		.trait_default = &preserve_aspect_ratio_default
+	}
+};
+
 static void
 lsm_svg_image_element_class_init (LsmSvgImageElementClass *klass)
 {
@@ -197,20 +243,26 @@ lsm_svg_image_element_class_init (LsmSvgImageElementClass *klass)
 
 	s_graphic_class->graphic_render = lsm_svg_image_element_graphic_render;
 
-	s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
-
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "x",
-					     offsetof (LsmSvgImageElement, x));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "y",
-					     offsetof (LsmSvgImageElement, y));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "width",
-					     offsetof (LsmSvgImageElement, width));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "height",
-					     offsetof (LsmSvgImageElement, height));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "xlink:href",
-					     offsetof (LsmSvgImageElement, href));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "preserveAspectRatio",
-					     offsetof (LsmSvgImageElement, preserve_aspect_ratio));
+	s_element_class->attribute_manager = lsm_attribute_manager_duplicate (s_element_class->attribute_manager);
+
+	lsm_attribute_manager_add_attributes (s_element_class->attribute_manager,
+					      G_N_ELEMENTS (lsm_svg_image_element_attribute_infos),
+					      lsm_svg_image_element_attribute_infos);
+
+/*        s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);*/
+
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "x",*/
+/*                                             offsetof (LsmSvgImageElement, x));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "y",*/
+/*                                             offsetof (LsmSvgImageElement, y));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "width",*/
+/*                                             offsetof (LsmSvgImageElement, width));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "height",*/
+/*                                             offsetof (LsmSvgImageElement, height));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "xlink:href",*/
+/*                                             offsetof (LsmSvgImageElement, href));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "preserveAspectRatio",*/
+/*                                             offsetof (LsmSvgImageElement, preserve_aspect_ratio));*/
 }
 
 G_DEFINE_TYPE (LsmSvgImageElement, lsm_svg_image_element, LSM_TYPE_SVG_GRAPHIC)
diff --git a/src/lsmsvglineargradientelement.c b/src/lsmsvglineargradientelement.c
index 9301706..9b227b4 100644
--- a/src/lsmsvglineargradientelement.c
+++ b/src/lsmsvglineargradientelement.c
@@ -36,6 +36,7 @@ lsm_svg_linear_gradient_element_get_node_name (LsmDomNode *node)
 
 /* GLinearGradientElement implementation */
 
+#if 0
 static void
 _linear_gradient_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 {
@@ -60,6 +61,7 @@ _linear_gradient_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 	length.type = LSM_SVG_LENGTH_TYPE_PERCENTAGE;
 	lsm_svg_animated_length_attribute_parse (&linear->y2, &length);
 }
+#endif
 
 static void
 _linear_gradient_element_render_paint (LsmSvgElement *self, LsmSvgView *view)
@@ -115,6 +117,36 @@ lsm_svg_linear_gradient_element_finalize (GObject *object)
 
 /* LsmSvgLinearGradientElement class */
 
+static const LsmSvgLength x1_y1_y2_default = 	{ .value_unit =   0.0, .type = LSM_SVG_LENGTH_TYPE_PERCENTAGE};
+static const LsmSvgLength x2_default =		{ .value_unit = 100.0, .type = LSM_SVG_LENGTH_TYPE_PERCENTAGE};
+
+static const LsmAttributeInfos lsm_svg_linear_gradient_element_attribute_infos[] = {
+	{
+		.name = "x1",
+		.attribute_offset = offsetof (LsmSvgLinearGradientElement, x1),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &x1_y1_y2_default
+	},
+	{
+		.name = "y1",
+		.attribute_offset = offsetof (LsmSvgLinearGradientElement, y1),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &x1_y1_y2_default
+	},
+	{
+		.name = "x2",
+		.attribute_offset = offsetof (LsmSvgLinearGradientElement, x2),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &x2_default
+	},
+	{
+		.name = "y2",
+		.attribute_offset = offsetof (LsmSvgLinearGradientElement, y2),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &x1_y1_y2_default
+	}
+};
+
 static void
 lsm_svg_linear_gradient_element_class_init (LsmSvgLinearGradientElementClass *s_svg_class)
 {
@@ -128,19 +160,25 @@ lsm_svg_linear_gradient_element_class_init (LsmSvgLinearGradientElementClass *s_
 
 	d_node_class->get_node_name = lsm_svg_linear_gradient_element_get_node_name;
 
-	s_element_class->update = _linear_gradient_element_update;
+/*        s_element_class->update = _linear_gradient_element_update;*/
 	s_element_class->render_paint = _linear_gradient_element_render_paint;
 
-	s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
+	s_element_class->attribute_manager = lsm_attribute_manager_duplicate (s_element_class->attribute_manager);
+
+	lsm_attribute_manager_add_attributes (s_element_class->attribute_manager,
+					      G_N_ELEMENTS (lsm_svg_linear_gradient_element_attribute_infos),
+					      lsm_svg_linear_gradient_element_attribute_infos);
+
+/*        s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);*/
 
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "x1",
-					  offsetof (LsmSvgLinearGradientElement, x1));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "y1",
-					  offsetof (LsmSvgLinearGradientElement, y1));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "x2",
-					  offsetof (LsmSvgLinearGradientElement, x2));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "y2",
-					  offsetof (LsmSvgLinearGradientElement, y2));
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "x1",*/
+/*                                          offsetof (LsmSvgLinearGradientElement, x1));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "y1",*/
+/*                                          offsetof (LsmSvgLinearGradientElement, y1));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "x2",*/
+/*                                          offsetof (LsmSvgLinearGradientElement, x2));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "y2",*/
+/*                                          offsetof (LsmSvgLinearGradientElement, y2));*/
 }
 
 G_DEFINE_TYPE (LsmSvgLinearGradientElement, lsm_svg_linear_gradient_element, LSM_TYPE_SVG_GRADIENT_ELEMENT)
diff --git a/src/lsmsvglineelement.c b/src/lsmsvglineelement.c
index a272bb3..b85026e 100644
--- a/src/lsmsvglineelement.c
+++ b/src/lsmsvglineelement.c
@@ -35,6 +35,7 @@ lsm_svg_line_element_get_node_name (LsmDomNode *node)
 
 /* LsmSvgElement implementation */
 
+#if 0
 static void
 lsm_svg_line_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 {
@@ -59,6 +60,7 @@ lsm_svg_line_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 
 	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
 }
+#endif
 
 /* LsmSvgGraphic implementation */
 
@@ -93,6 +95,35 @@ lsm_svg_line_element_init (LsmSvgLineElement *self)
 
 /* LsmSvgLineElement class */
 
+static const LsmSvgLength length_default = 	 { .value_unit =   0.0, .type = LSM_SVG_LENGTH_TYPE_PX};
+
+static const LsmAttributeInfos lsm_svg_line_element_attribute_infos[] = {
+	{
+		.name = "x1",
+		.attribute_offset = offsetof (LsmSvgLineElement, x1),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &length_default
+	},
+	{
+		.name = "y1",
+		.attribute_offset = offsetof (LsmSvgLineElement, y1),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &length_default
+	},
+	{
+		.name = "x2",
+		.attribute_offset = offsetof (LsmSvgLineElement, x2),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &length_default
+	},
+	{
+		.name = "y2",
+		.attribute_offset = offsetof (LsmSvgLineElement, y2),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &length_default
+	}
+};
+
 static void
 lsm_svg_line_element_class_init (LsmSvgLineElementClass *s_rect_class)
 {
@@ -104,20 +135,26 @@ lsm_svg_line_element_class_init (LsmSvgLineElementClass *s_rect_class)
 
 	d_node_class->get_node_name = lsm_svg_line_element_get_node_name;
 
-	s_element_class->update = lsm_svg_line_element_update;
+/*        s_element_class->update = lsm_svg_line_element_update;*/
 
 	s_graphic_class->graphic_render = lsm_svg_line_element_graphic_render;
 
-	s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
+	s_element_class->attribute_manager = lsm_attribute_manager_duplicate (s_element_class->attribute_manager);
+
+	lsm_attribute_manager_add_attributes (s_element_class->attribute_manager,
+					      G_N_ELEMENTS (lsm_svg_line_element_attribute_infos),
+					      lsm_svg_line_element_attribute_infos);
+
+/*        s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);*/
 
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "x1",
-					  offsetof (LsmSvgLineElement, x1));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "y1",
-					  offsetof (LsmSvgLineElement, y1));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "x2",
-					  offsetof (LsmSvgLineElement, x2));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "y2",
-					  offsetof (LsmSvgLineElement, y2));
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "x1",*/
+/*                                          offsetof (LsmSvgLineElement, x1));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "y1",*/
+/*                                          offsetof (LsmSvgLineElement, y1));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "x2",*/
+/*                                          offsetof (LsmSvgLineElement, x2));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "y2",*/
+/*                                          offsetof (LsmSvgLineElement, y2));*/
 }
 
 G_DEFINE_TYPE (LsmSvgLineElement, lsm_svg_line_element, LSM_TYPE_SVG_GRAPHIC)
diff --git a/src/lsmsvgmaskelement.c b/src/lsmsvgmaskelement.c
index c65541d..b8d673d 100644
--- a/src/lsmsvgmaskelement.c
+++ b/src/lsmsvgmaskelement.c
@@ -36,6 +36,7 @@ _mask_element_get_node_name (LsmDomNode *node)
 
 /* LsmSvgElement implementation */
 
+#if 0
 static void
 _mask_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 {
@@ -67,6 +68,7 @@ _mask_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 
 	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
 }
+#endif
 
 static void
 _mask_element_render_paint (LsmSvgElement *self, LsmSvgView *view)
@@ -164,6 +166,49 @@ lsm_svg_mask_element_init (LsmSvgMaskElement *self)
 
 /* LsmSvgMaskElement class */
 
+static const LsmSvgLength length_default = 	{ .value_unit =   0.0, .type = LSM_SVG_LENGTH_TYPE_PX};
+static const LsmSvgPatternUnits units_default =  	LSM_SVG_PATTERN_UNITS_OBJECT_BOUNDING_BOX;
+static const LsmSvgPatternUnits content_units_default = LSM_SVG_PATTERN_UNITS_USER_SPACE_ON_USE;
+
+static const LsmAttributeInfos lsm_svg_mask_element_attribute_infos[] = {
+	{
+		.name = "x",
+		.attribute_offset = offsetof (LsmSvgMaskElement, x),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &length_default
+	},
+	{
+		.name = "y",
+		.attribute_offset = offsetof (LsmSvgMaskElement, y),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &length_default
+	},
+	{
+		.name = "width",
+		.attribute_offset = offsetof (LsmSvgMaskElement, width),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &length_default
+	},
+	{
+		.name = "height",
+		.attribute_offset = offsetof (LsmSvgMaskElement, height),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &length_default
+	},
+	{
+		.name = "maskUnits",
+		.attribute_offset = offsetof (LsmSvgMaskElement, units),
+		.trait_class = &lsm_svg_pattern_units_trait_class,
+		.trait_default = &units_default
+	},
+	{
+		.name = "maskContentUnits",
+		.attribute_offset = offsetof (LsmSvgMaskElement, content_units),
+		.trait_class = &lsm_svg_pattern_units_trait_class,
+		.trait_default = &content_units_default
+	}
+};
+
 static void
 lsm_svg_mask_element_class_init (LsmSvgMaskElementClass *klass)
 {
@@ -174,24 +219,30 @@ lsm_svg_mask_element_class_init (LsmSvgMaskElementClass *klass)
 
 	d_node_class->get_node_name = _mask_element_get_node_name;
 
-	s_element_class->update = _mask_element_update;
+/*        s_element_class->update = _mask_element_update;*/
 	s_element_class->render_paint = _mask_element_render_paint;
 	s_element_class->render = NULL;
 
-	s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
-
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "x",
-					     offsetof (LsmSvgMaskElement, x));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "y",
-					     offsetof (LsmSvgMaskElement, y));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "width",
-					     offsetof (LsmSvgMaskElement, width));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "height",
-					     offsetof (LsmSvgMaskElement, height));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "maskUnits",
-					     offsetof (LsmSvgMaskElement, units));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "maskContentUnits",
-					     offsetof (LsmSvgMaskElement, content_units));
+	s_element_class->attribute_manager = lsm_attribute_manager_duplicate (s_element_class->attribute_manager);
+
+	lsm_attribute_manager_add_attributes (s_element_class->attribute_manager,
+					      G_N_ELEMENTS (lsm_svg_mask_element_attribute_infos),
+					      lsm_svg_mask_element_attribute_infos);
+
+/*        s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);*/
+
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "x",*/
+/*                                             offsetof (LsmSvgMaskElement, x));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "y",*/
+/*                                             offsetof (LsmSvgMaskElement, y));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "width",*/
+/*                                             offsetof (LsmSvgMaskElement, width));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "height",*/
+/*                                             offsetof (LsmSvgMaskElement, height));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "maskUnits",*/
+/*                                             offsetof (LsmSvgMaskElement, units));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "maskContentUnits",*/
+/*                                             offsetof (LsmSvgMaskElement, content_units));*/
 }
 
 G_DEFINE_TYPE (LsmSvgMaskElement, lsm_svg_mask_element, LSM_TYPE_SVG_GRAPHIC)
diff --git a/src/lsmsvgpathelement.c b/src/lsmsvgpathelement.c
index 7514e5f..d39add4 100644
--- a/src/lsmsvgpathelement.c
+++ b/src/lsmsvgpathelement.c
@@ -68,6 +68,14 @@ lsm_svg_path_element_finalize (GObject *object)
 
 /* LsmSvgPathElement class */
 
+static const LsmAttributeInfos lsm_svg_path_element_attribute_infos[] = {
+	{
+		.name = "d",
+		.attribute_offset = offsetof (LsmSvgPathElement, d),
+		.trait_class = &lsm_null_trait_class
+	}
+};
+
 static void
 lsm_svg_path_element_class_init (LsmSvgPathElementClass *s_rect_class)
 {
@@ -84,10 +92,16 @@ lsm_svg_path_element_class_init (LsmSvgPathElementClass *s_rect_class)
 
 	s_graphic_class->graphic_render = lsm_svg_path_element_graphic_render;
 
-	s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
+	s_element_class->attribute_manager = lsm_attribute_manager_duplicate (s_element_class->attribute_manager);
+
+	lsm_attribute_manager_add_attributes (s_element_class->attribute_manager,
+					      G_N_ELEMENTS (lsm_svg_path_element_attribute_infos),
+					      lsm_svg_path_element_attribute_infos);
+
+/*        s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);*/
 
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "d",
-					  offsetof (LsmSvgPathElement, d));
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "d",*/
+/*                                          offsetof (LsmSvgPathElement, d));*/
 }
 
 G_DEFINE_TYPE (LsmSvgPathElement, lsm_svg_path_element, LSM_TYPE_SVG_GRAPHIC)
diff --git a/src/lsmsvgpatternelement.c b/src/lsmsvgpatternelement.c
index 551da38..80d64e3 100644
--- a/src/lsmsvgpatternelement.c
+++ b/src/lsmsvgpatternelement.c
@@ -182,6 +182,80 @@ lsm_svg_pattern_element_init (LsmSvgPatternElement *self)
 
 /* LsmSvgPatternElement class */
 
+static const LsmSvgLength length_default = 	{ .value_unit =   0.0, .type = LSM_SVG_LENGTH_TYPE_PX};
+static const LsmSvgMatrix matrix_default = 	{1.0, 0.0, 0.0, 1.0, 0.0, 0.0};
+static const LsmBox viewbox_default =		{0.0, 0.0, 0.0, 0.0};
+static const LsmSvgPatternUnits units_default =  	LSM_SVG_PATTERN_UNITS_OBJECT_BOUNDING_BOX;
+static const LsmSvgPatternUnits content_units_default = LSM_SVG_PATTERN_UNITS_USER_SPACE_ON_USE;
+static const LsmSvgSpreadMethod spread_method_default = LSM_SVG_SPREAD_METHOD_PAD;
+static const LsmSvgPreserveAspectRatio preserve_aspect_ratio_default = {
+	.defer = FALSE,
+	.align = LSM_SVG_ALIGN_X_MID_Y_MID,
+	.meet_or_slice = LSM_SVG_MEET_OR_SLICE_MEET
+};
+
+static const LsmAttributeInfos lsm_svg_pattern_element_attribute_infos[] = {
+	{
+		.name = "x",
+		.attribute_offset = offsetof (LsmSvgPatternElement, x),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &length_default
+	},
+	{
+		.name = "y",
+		.attribute_offset = offsetof (LsmSvgPatternElement, y),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &length_default
+	},
+	{
+		.name = "width",
+		.attribute_offset = offsetof (LsmSvgPatternElement, width),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &length_default
+	},
+	{
+		.name = "height",
+		.attribute_offset = offsetof (LsmSvgPatternElement, height),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &length_default
+	},
+	{
+		.name = "patternUnits",
+		.attribute_offset = offsetof (LsmSvgPatternElement, units),
+		.trait_class = &lsm_svg_pattern_units_trait_class,
+		.trait_default = &units_default
+	},
+	{
+		.name = "patternContentUnits",
+		.attribute_offset = offsetof (LsmSvgPatternElement, content_units),
+		.trait_class = &lsm_svg_pattern_units_trait_class,
+		.trait_default = &content_units_default
+	},
+	{
+		.name = "patternTransform",
+		.attribute_offset = offsetof (LsmSvgPatternElement, transform),
+		.trait_class = &lsm_svg_matrix_trait_class,
+		.trait_default = &matrix_default
+	},
+	{
+		.name = "xlink:href",
+		.attribute_offset = offsetof (LsmSvgPatternElement, href),
+		.trait_class = &lsm_null_trait_class
+	},
+	{
+		.name = "viewBox",
+		.attribute_offset = offsetof (LsmSvgPatternElement, viewbox),
+		.trait_class = &lsm_box_trait_class,
+		.trait_default = &viewbox_default
+	},
+	{
+		.name = "preserveAspectRatio",
+		.attribute_offset = offsetof (LsmSvgPatternElement, preserve_aspect_ratio),
+		.trait_class = &lsm_svg_preserve_aspect_ratio_trait_class,
+		.trait_default = &preserve_aspect_ratio_default
+	}
+};
+
 static void
 lsm_svg_pattern_element_class_init (LsmSvgPatternElementClass *klass)
 {
@@ -196,28 +270,34 @@ lsm_svg_pattern_element_class_init (LsmSvgPatternElementClass *klass)
 	s_element_class->render_paint = _pattern_element_render_paint;
 	s_element_class->render = NULL;
 
-	s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
-
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "x",
-					     offsetof (LsmSvgPatternElement, x));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "y",
-					     offsetof (LsmSvgPatternElement, y));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "width",
-					     offsetof (LsmSvgPatternElement, width));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "height",
-					     offsetof (LsmSvgPatternElement, height));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "patternUnits",
-					     offsetof (LsmSvgPatternElement, units));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "patternContentUnits",
-					     offsetof (LsmSvgPatternElement, content_units));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "patternTransform",
-					     offsetof (LsmSvgPatternElement, transform));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "xlink:href",
-					     offsetof (LsmSvgPatternElement, href));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "viewBox",
-					     offsetof (LsmSvgPatternElement, viewbox));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "preserveAspectRatio",
-					     offsetof (LsmSvgPatternElement, preserve_aspect_ratio));
+	s_element_class->attribute_manager = lsm_attribute_manager_duplicate (s_element_class->attribute_manager);
+
+	lsm_attribute_manager_add_attributes (s_element_class->attribute_manager,
+					      G_N_ELEMENTS (lsm_svg_pattern_element_attribute_infos),
+					      lsm_svg_pattern_element_attribute_infos);
+
+/*        s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);*/
+
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "x",*/
+/*                                             offsetof (LsmSvgPatternElement, x));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "y",*/
+/*                                             offsetof (LsmSvgPatternElement, y));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "width",*/
+/*                                             offsetof (LsmSvgPatternElement, width));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "height",*/
+/*                                             offsetof (LsmSvgPatternElement, height));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "patternUnits",*/
+/*                                             offsetof (LsmSvgPatternElement, units));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "patternContentUnits",*/
+/*                                             offsetof (LsmSvgPatternElement, content_units));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "patternTransform",*/
+/*                                             offsetof (LsmSvgPatternElement, transform));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "xlink:href",*/
+/*                                             offsetof (LsmSvgPatternElement, href));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "viewBox",*/
+/*                                             offsetof (LsmSvgPatternElement, viewbox));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "preserveAspectRatio",*/
+/*                                             offsetof (LsmSvgPatternElement, preserve_aspect_ratio));*/
 }
 
 G_DEFINE_TYPE (LsmSvgPatternElement, lsm_svg_pattern_element, LSM_TYPE_SVG_GRAPHIC)
diff --git a/src/lsmsvgpolygonelement.c b/src/lsmsvgpolygonelement.c
index a560e6f..aa3186c 100644
--- a/src/lsmsvgpolygonelement.c
+++ b/src/lsmsvgpolygonelement.c
@@ -59,6 +59,14 @@ lsm_svg_polygon_element_init (LsmSvgPolygonElement *self)
 
 /* LsmSvgPolygonElement class */
 
+static const LsmAttributeInfos lsm_svg_polygon_element_attribute_infos[] = {
+	{
+		.name = "points",
+		.attribute_offset = offsetof (LsmSvgPolygonElement, points),
+		.trait_class = &lsm_null_trait_class
+	}
+};
+
 static void
 lsm_svg_polygon_element_class_init (LsmSvgPolygonElementClass *s_rect_class)
 {
@@ -72,10 +80,16 @@ lsm_svg_polygon_element_class_init (LsmSvgPolygonElementClass *s_rect_class)
 
 	s_graphic_class->graphic_render = lsm_svg_polygon_element_graphic_render;
 
-	s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
+	s_element_class->attribute_manager = lsm_attribute_manager_duplicate (s_element_class->attribute_manager);
+
+	lsm_attribute_manager_add_attributes (s_element_class->attribute_manager,
+					      G_N_ELEMENTS (lsm_svg_polygon_element_attribute_infos),
+					      lsm_svg_polygon_element_attribute_infos);
+
+/*        s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);*/
 
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "points",
-					  offsetof (LsmSvgPolygonElement, points));
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "points",*/
+/*                                          offsetof (LsmSvgPolygonElement, points));*/
 }
 
 G_DEFINE_TYPE (LsmSvgPolygonElement, lsm_svg_polygon_element, LSM_TYPE_SVG_GRAPHIC)
diff --git a/src/lsmsvgpolylineelement.c b/src/lsmsvgpolylineelement.c
index 0facb9a..bcd60b1 100644
--- a/src/lsmsvgpolylineelement.c
+++ b/src/lsmsvgpolylineelement.c
@@ -59,6 +59,14 @@ lsm_svg_polyline_element_init (LsmSvgPolylineElement *self)
 
 /* LsmSvgPolylineElement class */
 
+static const LsmAttributeInfos lsm_svg_polyline_element_attribute_infos[] = {
+	{
+		.name = "points",
+		.attribute_offset = offsetof (LsmSvgPolylineElement, points),
+		.trait_class = &lsm_null_trait_class
+	}
+};
+
 static void
 lsm_svg_polyline_element_class_init (LsmSvgPolylineElementClass *s_rect_class)
 {
@@ -72,10 +80,16 @@ lsm_svg_polyline_element_class_init (LsmSvgPolylineElementClass *s_rect_class)
 
 	s_graphic_class->graphic_render = lsm_svg_polyline_element_graphic_render;
 
-	s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
+	s_element_class->attribute_manager = lsm_attribute_manager_duplicate (s_element_class->attribute_manager);
+
+	lsm_attribute_manager_add_attributes (s_element_class->attribute_manager,
+					      G_N_ELEMENTS (lsm_svg_polyline_element_attribute_infos),
+					      lsm_svg_polyline_element_attribute_infos);
+
+/*        s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);*/
 
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "points",
-					  offsetof (LsmSvgPolylineElement, points));
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "points",*/
+/*                                          offsetof (LsmSvgPolylineElement, points));*/
 }
 
 G_DEFINE_TYPE (LsmSvgPolylineElement, lsm_svg_polyline_element, LSM_TYPE_SVG_GRAPHIC)
diff --git a/src/lsmsvgradialgradientelement.c b/src/lsmsvgradialgradientelement.c
index 7c3279a..1269670 100644
--- a/src/lsmsvgradialgradientelement.c
+++ b/src/lsmsvgradialgradientelement.c
@@ -37,6 +37,7 @@ lsm_svg_radial_gradient_element_get_node_name (LsmDomNode *node)
 
 /* GRadialGradientElement implementation */
 
+#if 0
 static void
 _radial_gradient_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 {
@@ -63,6 +64,7 @@ _radial_gradient_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 	length = radial->cy.length.base;
 	lsm_svg_animated_length_attribute_parse (&radial->fy, &length);
 }
+#endif
 
 static void
 _radial_gradient_element_render_paint (LsmSvgElement *self, LsmSvgView *view)
@@ -131,6 +133,42 @@ lsm_svg_radial_gradient_element_finalize (GObject *object)
 
 /* LsmSvgRadialGradientElement class */
 
+static const LsmSvgLength length_default = {.value_unit = 50.0, .type = LSM_SVG_LENGTH_TYPE_PERCENTAGE};
+static const LsmSvgLength unset_default  = {.value_unit =  0.0, .type = LSM_SVG_LENGTH_TYPE_UNKNOWN};
+
+static const LsmAttributeInfos lsm_svg_radial_gradient_element_attribute_infos[] = {
+	{
+		.name = "cx",
+		.attribute_offset = offsetof (LsmSvgRadialGradientElement, cx),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &length_default
+	},
+	{
+		.name = "cy",
+		.attribute_offset = offsetof (LsmSvgRadialGradientElement, cy),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &length_default
+	},
+	{
+		.name = "r",
+		.attribute_offset = offsetof (LsmSvgRadialGradientElement, r),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &length_default
+	},
+	{
+		.name = "fx",
+		.attribute_offset = offsetof (LsmSvgRadialGradientElement, fx),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &unset_default
+	},
+	{
+		.name = "fy",
+		.attribute_offset = offsetof (LsmSvgRadialGradientElement, fy),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &unset_default
+	}
+};
+
 static void
 lsm_svg_radial_gradient_element_class_init (LsmSvgRadialGradientElementClass *s_svg_class)
 {
@@ -144,21 +182,27 @@ lsm_svg_radial_gradient_element_class_init (LsmSvgRadialGradientElementClass *s_
 
 	d_node_class->get_node_name = lsm_svg_radial_gradient_element_get_node_name;
 
-	s_element_class->update = _radial_gradient_element_update;
+/*        s_element_class->update = _radial_gradient_element_update;*/
 	s_element_class->render_paint = _radial_gradient_element_render_paint;
 
-	s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
-
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "cx",
-					  offsetof (LsmSvgRadialGradientElement, cx));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "cy",
-					  offsetof (LsmSvgRadialGradientElement, cy));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "r",
-					  offsetof (LsmSvgRadialGradientElement, r));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "fx",
-					  offsetof (LsmSvgRadialGradientElement, fx));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "fy",
-					  offsetof (LsmSvgRadialGradientElement, fy));
+	s_element_class->attribute_manager = lsm_attribute_manager_duplicate (s_element_class->attribute_manager);
+
+	lsm_attribute_manager_add_attributes (s_element_class->attribute_manager,
+					      G_N_ELEMENTS (lsm_svg_radial_gradient_element_attribute_infos),
+					      lsm_svg_radial_gradient_element_attribute_infos);
+
+/*        s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);*/
+
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "cx",*/
+/*                                          offsetof (LsmSvgRadialGradientElement, cx));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "cy",*/
+/*                                          offsetof (LsmSvgRadialGradientElement, cy));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "r",*/
+/*                                          offsetof (LsmSvgRadialGradientElement, r));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "fx",*/
+/*                                          offsetof (LsmSvgRadialGradientElement, fx));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "fy",*/
+/*                                          offsetof (LsmSvgRadialGradientElement, fy));*/
 }
 
 G_DEFINE_TYPE (LsmSvgRadialGradientElement, lsm_svg_radial_gradient_element, LSM_TYPE_SVG_GRADIENT_ELEMENT)
diff --git a/src/lsmsvgrectelement.c b/src/lsmsvgrectelement.c
index 53a30b3..4306edd 100644
--- a/src/lsmsvgrectelement.c
+++ b/src/lsmsvgrectelement.c
@@ -34,6 +34,7 @@ lsm_svg_rect_element_get_node_name (LsmDomNode *node)
 
 /* LsmSvgElement implementation */
 
+#if 0
 static void
 lsm_svg_rect_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 {
@@ -66,6 +67,7 @@ lsm_svg_rect_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 
 	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
 }
+#endif
 
 /* LsmSvgGraphic implementation */
 
@@ -135,6 +137,47 @@ lsm_svg_rect_element_finalize (GObject *object)
 
 /* LsmSvgRectElement class */
 
+static const LsmSvgLength length_default = 	 { .value_unit =   0.0, .type = LSM_SVG_LENGTH_TYPE_PX};
+
+static const LsmAttributeInfos lsm_svg_rect_element_attribute_infos[] = {
+	{
+		.name = "x",
+		.attribute_offset = offsetof (LsmSvgRectElement, x),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &length_default
+	},
+	{
+		.name = "y",
+		.attribute_offset = offsetof (LsmSvgRectElement, y),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &length_default
+	},
+	{
+		.name = "width",
+		.attribute_offset = offsetof (LsmSvgRectElement, width),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &length_default
+	},
+	{
+		.name = "height",
+		.attribute_offset = offsetof (LsmSvgRectElement, height),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &length_default
+	},
+	{
+		.name = "rx",
+		.attribute_offset = offsetof (LsmSvgRectElement, rx),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &length_default
+	},
+	{
+		.name = "ry",
+		.attribute_offset = offsetof (LsmSvgRectElement, ry),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &length_default
+	}
+};
+
 static void
 lsm_svg_rect_element_class_init (LsmSvgRectElementClass *s_rect_class)
 {
@@ -149,25 +192,31 @@ lsm_svg_rect_element_class_init (LsmSvgRectElementClass *s_rect_class)
 
 	d_node_class->get_node_name = lsm_svg_rect_element_get_node_name;
 
-	s_element_class->update = lsm_svg_rect_element_update;
+/*        s_element_class->update = lsm_svg_rect_element_update;*/
 
 	s_graphic_class->graphic_render = lsm_svg_rect_element_graphic_render;
 	s_graphic_class->graphic_get_extents = lsm_svg_rect_element_graphic_get_extents;
 
-	s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
-
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "x",
-					  offsetof (LsmSvgRectElement, x));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "y",
-					  offsetof (LsmSvgRectElement, y));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "width",
-					  offsetof (LsmSvgRectElement, width));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "height",
-					  offsetof (LsmSvgRectElement, height));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "rx",
-					  offsetof (LsmSvgRectElement, rx));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "ry",
-					  offsetof (LsmSvgRectElement, ry));
+	s_element_class->attribute_manager = lsm_attribute_manager_duplicate (s_element_class->attribute_manager);
+
+	lsm_attribute_manager_add_attributes (s_element_class->attribute_manager,
+					      G_N_ELEMENTS (lsm_svg_rect_element_attribute_infos),
+					      lsm_svg_rect_element_attribute_infos);
+
+/*        s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);*/
+
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "x",*/
+/*                                          offsetof (LsmSvgRectElement, x));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "y",*/
+/*                                          offsetof (LsmSvgRectElement, y));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "width",*/
+/*                                          offsetof (LsmSvgRectElement, width));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "height",*/
+/*                                          offsetof (LsmSvgRectElement, height));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "rx",*/
+/*                                          offsetof (LsmSvgRectElement, rx));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "ry",*/
+/*                                          offsetof (LsmSvgRectElement, ry));*/
 }
 
 G_DEFINE_TYPE (LsmSvgRectElement, lsm_svg_rect_element, LSM_TYPE_SVG_GRAPHIC)
diff --git a/src/lsmsvgstopelement.c b/src/lsmsvgstopelement.c
index efdd129..e77bd11 100644
--- a/src/lsmsvgstopelement.c
+++ b/src/lsmsvgstopelement.c
@@ -37,6 +37,7 @@ lsm_svg_stop_element_get_node_name (LsmDomNode *node)
 
 /* LsmSvgElement implementation */
 
+#if 0
 static void
 _stop_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 {
@@ -48,6 +49,7 @@ _stop_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 
 	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
 }
+#endif
 
 /* LsmSvgStopElement implementation */
 
@@ -97,6 +99,17 @@ lsm_svg_stop_element_init (LsmSvgStopElement *self)
 
 /* LsmSvgStopElement class */
 
+static const LsmSvgLength length_default = 	{ .value_unit =   0.0, .type = LSM_SVG_LENGTH_TYPE_NUMBER};
+
+static const LsmAttributeInfos lsm_svg_stop_element_attribute_infos[] = {
+	{
+		.name = "offset",
+		.attribute_offset = offsetof (LsmSvgStopElement, offset),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &length_default
+	}
+};
+
 static void
 lsm_svg_stop_element_class_init (LsmSvgStopElementClass *klass)
 {
@@ -107,12 +120,18 @@ lsm_svg_stop_element_class_init (LsmSvgStopElementClass *klass)
 
 	d_node_class->get_node_name = lsm_svg_stop_element_get_node_name;
 
-	s_element_class->update = _stop_element_update;
+/*        s_element_class->update = _stop_element_update;*/
+
+	s_element_class->attribute_manager = lsm_attribute_manager_duplicate (s_element_class->attribute_manager);
+
+	lsm_attribute_manager_add_attributes (s_element_class->attribute_manager,
+					      G_N_ELEMENTS (lsm_svg_stop_element_attribute_infos),
+					      lsm_svg_stop_element_attribute_infos);
 
-	s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
+/*        s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);*/
 
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "offset",
-					  offsetof (LsmSvgStopElement, offset));
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "offset",*/
+/*                                          offsetof (LsmSvgStopElement, offset));*/
 }
 
 G_DEFINE_TYPE (LsmSvgStopElement, lsm_svg_stop_element, LSM_TYPE_SVG_GRAPHIC)
diff --git a/src/lsmsvgstyle.c b/src/lsmsvgstyle.c
index 09a3717..b8a265f 100644
--- a/src/lsmsvgstyle.c
+++ b/src/lsmsvgstyle.c
@@ -21,645 +21,116 @@
 
 #include <lsmsvgstyle.h>
 #include <lsmsvgcolors.h>
-#include <lsmsvgutils.h>
+#include <lsmsvgtraits.h>
+#include <lsmstr.h>
 #include <string.h>
 #include <math.h>
 
-static const LsmPropertyClass lsm_svg_property_class = {
-	.size = sizeof (LsmProperty)
-};
-
-static void
-lsm_svg_double_property_from_text (LsmProperty *property, const char *value)
-{
-	LsmSvgDoubleProperty *svg_double = (LsmSvgDoubleProperty *) property;
-
-	svg_double->value = g_strtod (value, NULL);
-}
-
-char *
-lsm_svg_double_property_to_text (LsmProperty *property)
-{
-	LsmSvgDoubleProperty *svg_double = (LsmSvgDoubleProperty *) property;
-
-	return g_strdup_printf ("%g", svg_double->value);
-}
-
-static const LsmPropertyClass lsm_svg_double_property_class = {
-	.size = sizeof (LsmSvgDoubleProperty),
-	.from_text = lsm_svg_double_property_from_text,
-	.to_text = lsm_svg_double_property_to_text
-};
-
-static void
-lsm_svg_length_property_from_text (LsmProperty *property, const char *value)
-{
-	LsmSvgLengthProperty *svg_length = (LsmSvgLengthProperty *) property;
-	char *length_type_str;
-
-	svg_length->length.value_unit = g_strtod (value, &length_type_str);
-	svg_length->length.type = lsm_svg_length_type_from_string (length_type_str);
-}
-
-char *
-lsm_svg_length_property_to_text (LsmProperty *property)
-{
-	LsmSvgLengthProperty *svg_length = (LsmSvgLengthProperty *) property;
-
-	return g_strdup_printf ("%g%s",
-				svg_length->length.value_unit,
-				lsm_svg_length_type_to_string (svg_length->length.type));
-}
-
-static const LsmPropertyClass lsm_svg_length_property_class = {
-	.size = sizeof (LsmSvgLengthProperty),
-	.from_text = lsm_svg_length_property_from_text,
-	.to_text = lsm_svg_length_property_to_text
-};
-
-static void
-_init_matrix (LsmSvgMatrix *matrix, LsmSvgTransformType transform, unsigned int n_values, double values[])
-{
-	switch (transform) {
-		case LSM_SVG_TRANSFORM_TYPE_SCALE:
-			if (n_values == 1) {
-				lsm_svg_matrix_init_scale (matrix, values[0], values[0]);
-				return;
-			} else if (n_values == 2) {
-				lsm_svg_matrix_init_scale (matrix, values[0], values[1]);
-				return;
-			}
-			break;
-		case LSM_SVG_TRANSFORM_TYPE_TRANSLATE:
-			if (n_values == 1) {
-				lsm_svg_matrix_init_translate (matrix, values[0], values[0]);
-				return;
-			} else if (n_values == 2) {
-				lsm_svg_matrix_init_translate (matrix, values[0], values[1]);
-				return;
-			}
-			break;
-		case LSM_SVG_TRANSFORM_TYPE_MATRIX:
-			if (n_values == 6) {
-				lsm_svg_matrix_init (matrix,
-						  values[0], values[1],
-						  values[2], values[3],
-						  values[4], values[5]);
-				return;
-			}
-			break;
-		case LSM_SVG_TRANSFORM_TYPE_ROTATE:
-			if (n_values == 1) {
-				lsm_svg_matrix_init_rotate (matrix, values[0] * M_PI / 180.0);
-				return;
-			} else if (n_values == 3) {
-				LsmSvgMatrix matrix_b;
-
-				lsm_svg_matrix_init_translate (matrix, values[1], values[2]);
-				lsm_svg_matrix_init_rotate (&matrix_b, values[0] * M_PI / 180.0);
-				lsm_svg_matrix_multiply (matrix, &matrix_b, matrix);
-				lsm_svg_matrix_init_translate (&matrix_b, -values[1], -values[2]);
-				lsm_svg_matrix_multiply (matrix, &matrix_b, matrix);
-				return;
-			}
-			break;
-		case LSM_SVG_TRANSFORM_TYPE_SKEW_X:
-			if (n_values == 1) {
-				lsm_svg_matrix_init_skew_x (matrix, values[0] * M_PI / 180.0);
-				return;
-			}
-			break;
-		case LSM_SVG_TRANSFORM_TYPE_SKEW_Y:
-			if (n_values == 1) {
-				lsm_svg_matrix_init_skew_y (matrix, values[0] * M_PI / 180.0);
-				return;
-			}
-		default:
-			break;
-	}
-
-	lsm_svg_matrix_init_identity (matrix);
-}
-
-static void
-lsm_svg_transform_property_from_text (LsmProperty *property, const char *value)
-{
-	LsmSvgTransformProperty *svg_transform = (LsmSvgTransformProperty *) property;
-	char *string;
-
-	string = (char *) value;
-
-	lsm_svg_matrix_init_identity (&svg_transform->matrix);
-
-	while (*string != '\0') {
-		LsmSvgTransformType transform;
-		double values[6];
-
-		lsm_svg_str_skip_spaces (&string);
-
-		if (strncmp (string, "translate", 9) == 0) {
-			transform = LSM_SVG_TRANSFORM_TYPE_TRANSLATE;
-			string += 9;
-		} else if (strncmp (string, "scale", 5) == 0) {
-			transform = LSM_SVG_TRANSFORM_TYPE_SCALE;
-			string += 5;
-		} else if (strncmp (string, "rotate", 6) == 0) {
-			transform = LSM_SVG_TRANSFORM_TYPE_ROTATE;
-			string += 6;
-		} else if (strncmp (string, "matrix", 6) == 0) {
-			transform = LSM_SVG_TRANSFORM_TYPE_MATRIX;
-			string += 6;
-		} else if (strncmp (string, "skewX", 5) == 0) {
-			transform = LSM_SVG_TRANSFORM_TYPE_SKEW_X;
-			string += 5;
-		} else if (strncmp (string, "skewY", 5) == 0) {
-			transform = LSM_SVG_TRANSFORM_TYPE_SKEW_Y;
-			string += 5;
-		} else
-			break;
-
-		lsm_svg_str_skip_spaces (&string);
-
-		if (*string == '(') {
-			unsigned int n_values = 0;
-
-			string++;
-
-			while (*string != ')' && *string != '\0' && n_values < 6) {
-				lsm_svg_str_skip_comma_and_spaces (&string);
-
-				if (!lsm_svg_str_parse_double (&string, &values[n_values]))
-					break;
-
-				n_values++;
-			}
-
-			lsm_svg_str_skip_comma_and_spaces (&string);
-
-			if (*string == ')') {
-				LsmSvgMatrix matrix;
-
-				string++;
-
-				_init_matrix (&matrix, transform, n_values, values);
-
-				lsm_svg_matrix_multiply (&svg_transform->matrix, &matrix, &svg_transform->matrix);
-			}
-		}
-	}
-}
-
-char *
-lsm_svg_transform_property_to_text (LsmProperty *property)
-{
-	LsmSvgTransformProperty *svg_transform = (LsmSvgTransformProperty *) property;
-
-	/* TODO smarter serialization, checking for zeros */
-	return g_strdup_printf ("matrix(%g,%g,%g,%g,%g,%g)",
-				svg_transform->matrix.a,
-				svg_transform->matrix.b,
-				svg_transform->matrix.c,
-				svg_transform->matrix.d,
-				svg_transform->matrix.e,
-				svg_transform->matrix.f);
-}
-
-static const LsmPropertyClass lsm_svg_transform_property_class = {
-	.size = sizeof (LsmSvgTransformProperty),
-	.from_text = lsm_svg_transform_property_from_text,
-	.to_text = lsm_svg_transform_property_to_text
-};
-
-static char *
-_parse_color (char *string,
-	      LsmSvgColor *svg_color,
-	      gboolean *is_color_set)
-{
-	unsigned int color = 0;
-	*is_color_set = FALSE;
-
-	lsm_svg_str_skip_spaces (&string);
-
-	if (g_strcmp0 (string, "currentColor") == 0) {
-		svg_color->red = -1.0;
-		svg_color->green = 1.0;
-		svg_color->blue = 1.0;
-
-		*is_color_set = TRUE;
-
-		string += 12; /* strlen ("current_color") */
-
-		return string;
-	}
-
-	if (*string == '#') {
-		int value, i;
-		string++;
-
-		for (i = 0; i < 6; i++) {
-			if (*string >= '0' && *string <= '9')
-				value = *string - '0';
-			else if (*string >= 'A' && *string <= 'F')
-				value = *string - 'A' + 10;
-			else if (*string >= 'a' && *string <= 'f')
-				value = *string - 'a' + 10;
-			else
-				break;
-
-			color = (color << 4) + value;
-			string++;
-		}
-
-		if (i == 3) {
-			color = ((color & 0xf00) << 8) | ((color & 0x0f0) << 4) | (color & 0x00f);
-			color |= color << 4;
-		} else if (i != 6)
-			color = 0;
-
-		*is_color_set = TRUE;
-	} else if (strncmp (string, "rgb(", 4) == 0) {
-		int i;
-		double value;
-
-
-		string += 4; /* strlen ("rgb(") */
-
-		for (i = 0; i < 3; i++) {
-			if (!lsm_svg_str_parse_double (&string, &value))
-				break;
-
-			if (*string == '%') {
-				value = value * 255.0 / 100.0;
-				string++;
-			}
-
-			if (i < 2)
-				lsm_svg_str_skip_comma_and_spaces (&string);
-
-			color = (color << 8) + (int) (0.5 + CLAMP (value, 0.0, 255.0));
-		}
-
-		lsm_svg_str_skip_spaces (&string);
-
-		if (*string != ')' || i != 3)
-			color = 0;
-
-		*is_color_set  = TRUE;
-	} else if (g_strcmp0 (string, "none") == 0) {
-		*is_color_set = FALSE;
-	} else {
-		color = lsm_svg_color_from_string (string);
-
-		*is_color_set = TRUE;
-	}
-
-	svg_color->red = (double) ((color & 0xff0000) >> 16) / 255.0;
-	svg_color->green = (double) ((color & 0x00ff00) >> 8) / 255.0;
-	svg_color->blue = (double) (color & 0x0000ff) / 255.0;
-
-	return string;
-}
-
-static void
-lsm_svg_paint_property_from_text (LsmProperty *abstract_property, const char *value)
-{
-	LsmSvgPaintProperty *property = (LsmSvgPaintProperty *) abstract_property;
-	char *string;
-	gboolean is_color_set;
-
-	g_free (property->paint.uri);
-
-	string = (char *) value;
-
-	if (strncmp (string, "url(#", 5) == 0) {
-		unsigned int length;
-
-		string += 5;
-		length = 0;
-		while (string[length] != ')')
-			length++;
-		length++;
-
-		property->paint.uri = g_new (char, length);
-		if (property->paint.uri != NULL) {
-			memcpy (property->paint.uri, string, length - 1);
-			property->paint.uri[length - 1] = '\0';
-		}
-		string += length;
-	} else {
-		property->paint.uri = NULL;
-	}
-
-	string = _parse_color (string, &property->paint.color, &is_color_set);
-
-	if (is_color_set)
-		property->paint.type = property->paint.uri != NULL ?
-			LSM_SVG_PAINT_TYPE_URI_RGB_COLOR :
-			LSM_SVG_PAINT_TYPE_RGB_COLOR;
-	else
-		property->paint.type = property->paint.uri != NULL ?
-			LSM_SVG_PAINT_TYPE_URI :
-			LSM_SVG_PAINT_TYPE_NONE;
-}
-
-char *
-lsm_svg_paint_property_to_text (LsmProperty *abstract_property)
-{
-	LsmSvgPaintProperty *property = (LsmSvgPaintProperty *) abstract_property;
-
-	if (property->paint.color.red < 0.0 ||
-	    property->paint.color.green < 0.0 ||
-	    property->paint.color.blue < 0.0)
-		return g_strdup ("currentColor");
-
-	if (property->paint.uri != NULL)
-		g_strdup_printf ("url(#%s)", property->paint.uri);
-
-	return g_strdup_printf ("rgb(%g%%,%g%%,%g%%)",
-				100.0 * property->paint.color.red,
-				100.0 * property->paint.color.green,
-				100.0 * property->paint.color.blue);
-}
-
-static const LsmPropertyClass lsm_svg_paint_property_class = {
-	.size = sizeof (LsmSvgPaintProperty),
-	.from_text = lsm_svg_paint_property_from_text,
-	.to_text = lsm_svg_paint_property_to_text
-};
-
-static void
-lsm_svg_fill_rule_property_from_text (LsmProperty *abstract_property, const char *value)
-{
-	LsmSvgFillRuleProperty *property = (LsmSvgFillRuleProperty *) abstract_property;
-
-	property->value = lsm_svg_fill_rule_from_string (value);
-}
-
-char *
-lsm_svg_fill_rule_property_to_text (LsmProperty *abstract_property)
-{
-	LsmSvgFillRuleProperty *property = (LsmSvgFillRuleProperty *) abstract_property;
-
-	return g_strdup (lsm_svg_fill_rule_to_string (property->value));
-}
-
-static const LsmPropertyClass lsm_svg_fill_rule_property_class = {
-	.size = sizeof (LsmSvgFillRuleProperty),
-	.from_text = lsm_svg_fill_rule_property_from_text,
-	.to_text = lsm_svg_fill_rule_property_to_text
-};
-
-static void
-lsm_svg_line_join_property_from_text (LsmProperty *abstract_property, const char *value)
-{
-	LsmSvgLineJoinProperty *property = (LsmSvgLineJoinProperty *) abstract_property;
-
-	property->value = lsm_svg_line_join_from_string (value);
-}
-
-char *
-lsm_svg_line_join_property_to_text (LsmProperty *abstract_property)
-{
-	LsmSvgLineJoinProperty *property = (LsmSvgLineJoinProperty *) abstract_property;
-
-	return g_strdup (lsm_svg_line_join_to_string (property->value));
-}
-
-static const LsmPropertyClass lsm_svg_line_join_property_class = {
-	.size = sizeof (LsmSvgLineJoinProperty),
-	.from_text = lsm_svg_line_join_property_from_text,
-	.to_text = lsm_svg_line_join_property_to_text
-};
-
-static void
-lsm_svg_line_cap_property_from_text (LsmProperty *abstract_property, const char *value)
-{
-	LsmSvgLineCapProperty *property = (LsmSvgLineCapProperty *) abstract_property;
-
-	property->value = lsm_svg_line_cap_from_string (value);
-}
-
-static char *
-lsm_svg_line_cap_property_to_text (LsmProperty *abstract_property)
-{
-	LsmSvgLineCapProperty *property = (LsmSvgLineCapProperty *) abstract_property;
-
-	return g_strdup (lsm_svg_line_cap_to_string (property->value));
-}
-
-static const LsmPropertyClass lsm_svg_line_cap_property_class = {
-	.size = sizeof (LsmSvgLineCapProperty),
-	.from_text = lsm_svg_line_cap_property_from_text,
-	.to_text = lsm_svg_line_cap_property_to_text
-};
-
-static void
-lsm_svg_dash_array_property_from_text (LsmProperty *abstract_property, const char *value)
-{
-	LsmSvgDashArrayProperty *property = (LsmSvgDashArrayProperty *) abstract_property;
-	char *string;
-	unsigned int n_dashes = 1;
-
-	string = (char *) value;
-
-	lsm_svg_dash_array_free (property->value);
-
-	if (strcmp (string, "none") == 0) {
-		property->value = (LsmSvgDashArray *) &lsm_svg_dash_array_null;
-	} else {
-		char *iter = (char *) string;
-		unsigned int i;
-
-		while (*iter != '\0') {
-			if (*iter == ',')
-				n_dashes++;
-			iter++;
-		}
-
-		property->value = lsm_svg_dash_array_new (n_dashes);
-		if (property->value != &lsm_svg_dash_array_null) {
-			LsmSvgLength length;
-
-			iter = (char *)string;
-			lsm_svg_str_skip_spaces (&iter);
-
-			for (i = 0; i < n_dashes; i++) {
-				if (lsm_svg_str_parse_double (&iter, &length.value_unit)) {
-					length.type = lsm_svg_length_type_from_string (iter);
-					property->value->dashes[i] = length;
-					while (*iter != '\0' && *iter != ' ' && *iter != ',')
-						iter ++;
-				} else {
-					property->value->dashes[i].value_unit = 0.0;
-					property->value->dashes[i].value_unit = LSM_SVG_LENGTH_TYPE_NUMBER;
-				}
-				lsm_svg_str_skip_comma_and_spaces (&iter);
-			}
-		}
-	}
-}
-
-static char *
-lsm_svg_dash_array_property_to_text (LsmProperty *abstract_property)
-{
-	g_assert_not_reached ();
-}
-
-static void
-lsm_svg_dash_array_property_finalize (LsmProperty *abstract_property)
-{
-	LsmSvgDashArrayProperty *property = (LsmSvgDashArrayProperty *) abstract_property;
-
-	lsm_svg_dash_array_free (property->value);
-	property->value = NULL;
-}
-
-static const LsmPropertyClass lsm_svg_dash_array_property_class = {
-	.size = sizeof (LsmSvgDashArrayProperty),
-	.from_text = lsm_svg_dash_array_property_from_text,
-	.to_text = lsm_svg_dash_array_property_to_text,
-	.finalize = lsm_svg_dash_array_property_finalize
-};
-
-static void
-lsm_svg_color_property_from_text (LsmProperty *abstract_property, const char *value)
-{
-	LsmSvgColorProperty *property = (LsmSvgColorProperty *) abstract_property;
-	char *string;
-	gboolean is_color_set;
-
-	string = (char *) value;
-
-	_parse_color (string, &property->value, &is_color_set);
-}
-
-char *
-lsm_svg_color_property_to_text (LsmProperty *abstract_property)
-{
-	LsmSvgColorProperty *property = (LsmSvgColorProperty *) abstract_property;
-
-	return g_strdup_printf ("rgb(%g%%,%g%%,%g%%)",
-				100.0 * property->value.red,
-				100.0 * property->value.green,
-				100.0 * property->value.blue);
-}
-
-static const LsmPropertyClass lsm_svg_color_property_class = {
-	.size = sizeof (LsmSvgColorProperty),
-	.from_text = lsm_svg_color_property_from_text,
-	.to_text = lsm_svg_color_property_to_text
-};
-
 static const LsmPropertyInfos lsm_svg_property_infos[] = {
 	{
-		.name = "x",
-		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyleNew, x),
-		.property_class = &lsm_svg_length_property_class
-	},
-	{
-		.name = "y",
-		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyleNew, y),
-		.property_class = &lsm_svg_length_property_class
+		.name = "color",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, color),
+		.trait_class = &lsm_svg_color_trait_class
 	},
 	{
 		.name = "opacity",
-		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyleNew, group_opacity),
-		.property_class = &lsm_svg_double_property_class
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, group_opacity),
+		.trait_class = &lsm_double_trait_class
 	},
 	{
 		.name = "transform",
-		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyleNew, transform),
-		.property_class = &lsm_svg_transform_property_class
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, transform),
+		.trait_class = &lsm_svg_matrix_trait_class
 	},
 	{
 		.name = "fill",
-		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyleNew, fill.paint),
-		.property_class = &lsm_svg_paint_property_class
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, fill.paint),
+		.trait_class = &lsm_svg_paint_trait_class
 	},
 	{
 		.name = "fill-opacity",
-		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyleNew, fill.opacity),
-		.property_class = &lsm_svg_double_property_class
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, fill.opacity),
+		.trait_class = &lsm_double_trait_class
 	},
 	{
 		.name = "fill-rule",
-		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyleNew, fill.rule),
-		.property_class = &lsm_svg_fill_rule_property_class
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, fill.rule),
+		.trait_class = &lsm_svg_fill_rule_trait_class
 	},
 	{
 		.name = "stroke",
-		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyleNew, stroke.paint),
-		.property_class = &lsm_svg_paint_property_class
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, stroke.paint),
+		.trait_class = &lsm_svg_paint_trait_class
 	},
 	{
 		.name = "stroke-opacity",
-		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyleNew, stroke.opacity),
-		.property_class = &lsm_svg_double_property_class
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, stroke.opacity),
+		.trait_class = &lsm_double_trait_class
 	},
 	{
 		.name = "stroke-width",
-		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyleNew, stroke.width),
-		.property_class = &lsm_svg_length_property_class
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, stroke.width),
+		.trait_class = &lsm_svg_length_trait_class
 	},
 	{
 		.name = "stroke-linejoin",
-		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyleNew, stroke.line_join),
-		.property_class = &lsm_svg_line_join_property_class
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, stroke.line_join),
+		.trait_class = &lsm_svg_line_join_trait_class
 	},
 	{
 		.name = "stroke-linecap",
-		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyleNew, stroke.line_cap),
-		.property_class = &lsm_svg_line_cap_property_class
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, stroke.line_cap),
+		.trait_class = &lsm_svg_line_cap_trait_class
 	},
 	{
 		.name = "stroke-miterlimit",
-		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyleNew, stroke.miter_limit),
-		.property_class = &lsm_svg_double_property_class
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, stroke.miter_limit),
+		.trait_class = &lsm_double_trait_class
 	},
 	{
 		.name = "stroke-dashoffset",
-		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyleNew, stroke.dash_offset),
-		.property_class = &lsm_svg_length_property_class
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, stroke.dash_offset),
+		.trait_class = &lsm_svg_length_trait_class
 	},
 	{
 		.name = "stroke-dasharray",
-		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyleNew, stroke.dash_array),
-		.property_class = &lsm_svg_dash_array_property_class
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, stroke.dash_array),
+		.trait_class = &lsm_svg_dash_array_trait_class
 	},
 	{
 		.name = "font-family",
-		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyleNew, text.font_family),
-		.property_class = &lsm_svg_property_class
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, text.font_family),
+		.trait_class = &lsm_null_trait_class
 	},
 	{
 		.name = "font-size",
-		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyleNew, text.font_size),
-		.property_class = &lsm_svg_length_property_class
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, text.font_size),
+		.trait_class = &lsm_svg_length_trait_class
 	},
 	{
 		.name = "clip-path",
-		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyleNew, clip.url),
-		.property_class = &lsm_svg_property_class
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, clip.url),
+		.trait_class = &lsm_null_trait_class
 	},
 	{
 		.name = "clip-rule",
-		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyleNew, clip.rule),
-		.property_class = &lsm_svg_fill_rule_property_class
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, clip.rule),
+		.trait_class = &lsm_svg_fill_rule_trait_class
 	},
 	{
 		.name = "mask",
-		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyleNew, mask.url),
-		.property_class = &lsm_svg_property_class
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, mask.url),
+		.trait_class = &lsm_null_trait_class
 	},
 	{
 		.name = "stop-color",
-		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyleNew, gradient_stop.color),
-		.property_class = &lsm_svg_color_property_class
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, gradient_stop.color),
+		.trait_class = &lsm_svg_color_trait_class
 	},
 	{
 		.name = "stop-opacity",
-		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyleNew, gradient_stop.opacity),
-		.property_class = &lsm_svg_double_property_class
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, gradient_stop.opacity),
+		.trait_class = &lsm_double_trait_class
 	}
 };
 
@@ -681,7 +152,7 @@ lsm_svg_property_bag_set_property (LsmPropertyBag *property_bag, const char *nam
 {
 	LsmPropertyManager *property_manager = lsm_svg_get_property_manager ();
 
-	lsm_property_bag_set_property (property_bag, property_manager, name, value);
+	lsm_property_manager_set_property (property_manager, property_bag, name, value);
 }
 
 const char *
@@ -689,7 +160,7 @@ lsm_svg_property_bag_get_property (LsmPropertyBag *property_bag, const char *nam
 {
 	LsmPropertyManager *property_manager = lsm_svg_get_property_manager ();
 
-	return lsm_property_bag_get_property (property_bag, property_manager, name);
+	return lsm_property_manager_get_property (property_manager, property_bag, name);
 }
 
 void
@@ -697,7 +168,7 @@ lsm_svg_property_bag_clean (LsmPropertyBag *property_bag)
 {
 	LsmPropertyManager *property_manager = lsm_svg_get_property_manager ();
 
-	lsm_property_bag_clean (property_bag, property_manager);
+	lsm_property_manager_clean_properties (property_manager, property_bag);
 }
 
 char *
@@ -705,9 +176,10 @@ lsm_svg_property_bag_serialize (LsmPropertyBag *property_bag)
 {
 	LsmPropertyManager *property_manager = lsm_svg_get_property_manager ();
 
-	return lsm_property_bag_serialize (property_bag, property_manager);
+	return lsm_property_manager_serialize (property_manager, property_bag);
 }
 
+#if 0
 LsmSvgStyle *
 lsm_svg_style_new (void)
 {
@@ -749,3 +221,4 @@ lsm_svg_style_duplicate (const LsmSvgStyle *from)
 
 	return style;
 }
+#endif
diff --git a/src/lsmsvgstyle.h b/src/lsmsvgstyle.h
index da8ff92..87d8238 100644
--- a/src/lsmsvgstyle.h
+++ b/src/lsmsvgstyle.h
@@ -73,10 +73,8 @@ typedef struct {
 	LsmSvgDashArray *value;
 } LsmSvgDashArrayProperty;
 
-typedef struct _LsmSvgStyleNew {
-	LsmSvgLengthProperty *		x;
-	LsmSvgLengthProperty *		y;
-
+struct _LsmSvgStyle {
+	LsmSvgColorProperty *		color;
 	LsmSvgDoubleProperty *		group_opacity;
 	LsmSvgTransformProperty * 	transform;
 
@@ -112,10 +110,14 @@ typedef struct _LsmSvgStyleNew {
 	} mask;
 
 	struct {
+		LsmSvgTransformProperty	*	tranform;
+	} gradient;
+
+	struct {
 		LsmSvgColorProperty *	 	color;
 		LsmSvgDoubleProperty *		opacity;
 	} gradient_stop;
-} LsmSvgStyleNew;
+};
 
 void 		lsm_svg_property_bag_set_property 	(LsmPropertyBag *property_bag,
 							 const char *name, const char *value);
@@ -124,6 +126,7 @@ const char *	lsm_svg_property_bag_get_property	(LsmPropertyBag *property_bag,
 void 		lsm_svg_property_bag_clean 		(LsmPropertyBag *property_bag);
 char * 		lsm_svg_property_bag_serialize 		(LsmPropertyBag *property_bag);
 
+#if 0
 struct _LsmSvgStyle {
 	LsmBox viewport;
 	LsmSvgColor color;
@@ -163,6 +166,7 @@ struct _LsmSvgStyle {
 LsmSvgStyle * 	lsm_svg_style_new 		(void);
 void 		lsm_svg_style_free 		(LsmSvgStyle *style);
 LsmSvgStyle *	lsm_svg_style_duplicate 	(const LsmSvgStyle *style);
+#endif
 
 G_END_DECLS
 
diff --git a/src/lsmsvgsvgelement.c b/src/lsmsvgsvgelement.c
index f009949..007cdaa 100644
--- a/src/lsmsvgsvgelement.c
+++ b/src/lsmsvgsvgelement.c
@@ -39,6 +39,7 @@ lsm_svg_svg_element_get_node_name (LsmDomNode *node)
 
 /* LsmSvgElement implementation */
 
+#if 0
 static void
 _svg_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 {
@@ -74,6 +75,7 @@ _svg_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 
 	parent_style->viewport = svg->viewbox.value;
 }
+#endif
 
 void
 lsm_svg_svg_element_measure (LsmSvgSvgElement *self, double *width, double *height)
@@ -220,7 +222,6 @@ lsm_svg_svg_element_init (LsmSvgSvgElement *self)
 	lsm_dom_element_set_attribute (LSM_DOM_ELEMENT (self), "font-size", 		"10pt");
 	lsm_dom_element_set_attribute (LSM_DOM_ELEMENT (self), "stop-color", 		"black");
 	lsm_dom_element_set_attribute (LSM_DOM_ELEMENT (self), "stop-opacity", 		"1");
-
 }
 
 static void
@@ -235,6 +236,54 @@ lsm_svg_svg_element_finalize (GObject *object)
 
 /* LsmSvgSvgElement class */
 
+static const LsmSvgLength x_y_default = 	 { .value_unit =   0.0, .type = LSM_SVG_LENGTH_TYPE_PERCENTAGE};
+static const LsmSvgLength width_height_default = { .value_unit = 100.0, .type = LSM_SVG_LENGTH_TYPE_PERCENTAGE};
+static const LsmBox viewbox_default =		 {0.0, 0.0, 0.0, 0.0};
+static const LsmSvgPreserveAspectRatio preserve_aspect_ratio_default = {
+	.defer = FALSE,
+	.align = LSM_SVG_ALIGN_X_MID_Y_MID,
+	.meet_or_slice = LSM_SVG_MEET_OR_SLICE_MEET
+};
+
+static const LsmAttributeInfos lsm_svg_svg_element_attribute_infos[] = {
+	{
+		.name = "x",
+		.attribute_offset = offsetof (LsmSvgSvgElement, x),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &x_y_default
+	},
+	{
+		.name = "y",
+		.attribute_offset = offsetof (LsmSvgSvgElement, y),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &x_y_default
+	},
+	{
+		.name = "width",
+		.attribute_offset = offsetof (LsmSvgSvgElement, width),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &width_height_default
+	},
+	{
+		.name = "height",
+		.attribute_offset = offsetof (LsmSvgSvgElement, height),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &width_height_default
+	},
+	{
+		.name = "viewBox",
+		.attribute_offset = offsetof (LsmSvgSvgElement, viewbox),
+		.trait_class = &lsm_box_trait_class,
+		.trait_default = &viewbox_default
+	},
+	{
+		.name = "preserveAspectRatio",
+		.attribute_offset = offsetof (LsmSvgSvgElement, preserve_aspect_ratio),
+		.trait_class = &lsm_svg_preserve_aspect_ratio_trait_class,
+		.trait_default = &preserve_aspect_ratio_default
+	}
+};
+
 static void
 lsm_svg_svg_element_class_init (LsmSvgSvgElementClass *s_svg_class)
 {
@@ -249,24 +298,30 @@ lsm_svg_svg_element_class_init (LsmSvgSvgElementClass *s_svg_class)
 
 	d_node_class->get_node_name = lsm_svg_svg_element_get_node_name;
 
-	s_element_class->update = _svg_element_update;
+/*        s_element_class->update = _svg_element_update;*/
 
 	s_graphic_class->graphic_render = lsm_svg_svg_element_graphic_render;
 
-	s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
-
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "x",
-					     offsetof (LsmSvgSvgElement, x));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "y",
-					     offsetof (LsmSvgSvgElement, y));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "width",
-					     offsetof (LsmSvgSvgElement, width));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "height",
-					     offsetof (LsmSvgSvgElement, height));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "viewBox",
-					     offsetof (LsmSvgSvgElement, viewbox));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "preserveAspectRatio",
-					     offsetof (LsmSvgSvgElement, preserve_aspect_ratio));
+	s_element_class->attribute_manager = lsm_attribute_manager_duplicate (s_element_class->attribute_manager);
+
+	lsm_attribute_manager_add_attributes (s_element_class->attribute_manager,
+					      G_N_ELEMENTS (lsm_svg_svg_element_attribute_infos),
+					      lsm_svg_svg_element_attribute_infos);
+
+/*        s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);*/
+
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "x",*/
+/*                                             offsetof (LsmSvgSvgElement, x));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "y",*/
+/*                                             offsetof (LsmSvgSvgElement, y));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "width",*/
+/*                                             offsetof (LsmSvgSvgElement, width));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "height",*/
+/*                                             offsetof (LsmSvgSvgElement, height));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "viewBox",*/
+/*                                             offsetof (LsmSvgSvgElement, viewbox));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "preserveAspectRatio",*/
+/*                                             offsetof (LsmSvgSvgElement, preserve_aspect_ratio));*/
 }
 
 G_DEFINE_TYPE (LsmSvgSvgElement, lsm_svg_svg_element, LSM_TYPE_SVG_GRAPHIC)
diff --git a/src/lsmsvgsymbolelement.c b/src/lsmsvgsymbolelement.c
index 410a8ad..89c90a2 100644
--- a/src/lsmsvgsymbolelement.c
+++ b/src/lsmsvgsymbolelement.c
@@ -37,11 +37,13 @@ lsm_svg_symbol_element_get_node_name (LsmDomNode *node)
 
 /* LsmSvgElement implementation */
 
+#if 0
 static void
 lsm_svg_symbol_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 {
 	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
 }
+#endif
 
 /* LsmSvgGraphic implementation */
 
@@ -64,15 +66,15 @@ static void
 lsm_svg_symbol_element_class_init (LsmSvgSymbolElementClass *klass)
 {
 	LsmDomNodeClass *d_node_class = LSM_DOM_NODE_CLASS (klass);
-	LsmSvgElementClass *s_element_class = LSM_SVG_ELEMENT_CLASS (klass);
+/*        LsmSvgElementClass *s_element_class = LSM_SVG_ELEMENT_CLASS (klass);*/
 
 	parent_class = g_type_class_peek_parent (klass);
 
 	d_node_class->get_node_name = lsm_svg_symbol_element_get_node_name;
 
-	s_element_class->update = lsm_svg_symbol_element_update;
+/*        s_element_class->update = lsm_svg_symbol_element_update;*/
 
-	s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
+/*        s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);*/
 }
 
 G_DEFINE_TYPE (LsmSvgSymbolElement, lsm_svg_symbol_element, LSM_TYPE_SVG_GRAPHIC)
diff --git a/src/lsmsvgtextelement.c b/src/lsmsvgtextelement.c
index 4bfe73b..46713c9 100644
--- a/src/lsmsvgtextelement.c
+++ b/src/lsmsvgtextelement.c
@@ -41,6 +41,7 @@ lsm_svg_text_element_can_append_child (LsmDomNode *self, LsmDomNode *child)
 
 /* LsmSvgElement implementation */
 
+#if 0
 static void
 lsm_svg_text_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 {
@@ -57,6 +58,7 @@ lsm_svg_text_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 
 	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
 }
+#endif
 
 /* LsmSvgGraphic implementation */
 
@@ -107,31 +109,54 @@ lsm_svg_text_element_finalize (GObject *object)
 
 /* LsmSvgTextElement class */
 
+static const LsmSvgLength length_default = 	 { .value_unit =   0.0, .type = LSM_SVG_LENGTH_TYPE_PX};
+
+static const LsmAttributeInfos lsm_svg_text_element_attribute_infos[] = {
+	{
+		.name = "x",
+		.attribute_offset = offsetof (LsmSvgTextElement, x),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &length_default
+	},
+	{
+		.name = "y",
+		.attribute_offset = offsetof (LsmSvgTextElement, y),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &length_default
+	}
+};
+
 static void
-lsm_svg_text_element_class_init (LsmSvgTextElementClass *s_rect_class)
+lsm_svg_text_element_class_init (LsmSvgTextElementClass *s_text_class)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (s_rect_class);
-	LsmDomNodeClass *d_node_class = LSM_DOM_NODE_CLASS (s_rect_class);
-	LsmSvgElementClass *s_element_class = LSM_SVG_ELEMENT_CLASS (s_rect_class);
-	LsmSvgGraphicClass *s_graphic_class = LSM_SVG_GRAPHIC_CLASS (s_rect_class);
+	GObjectClass *object_class = G_OBJECT_CLASS (s_text_class);
+	LsmDomNodeClass *d_node_class = LSM_DOM_NODE_CLASS (s_text_class);
+	LsmSvgElementClass *s_element_class = LSM_SVG_ELEMENT_CLASS (s_text_class);
+	LsmSvgGraphicClass *s_graphic_class = LSM_SVG_GRAPHIC_CLASS (s_text_class);
 
-	parent_class = g_type_class_peek_parent (s_rect_class);
+	parent_class = g_type_class_peek_parent (s_text_class);
 
 	object_class->finalize = lsm_svg_text_element_finalize;
 
 	d_node_class->get_node_name = lsm_svg_text_element_get_node_name;
 	d_node_class->can_append_child = lsm_svg_text_element_can_append_child;
 
-	s_element_class->update = lsm_svg_text_element_update;
+/*        s_element_class->update = lsm_svg_text_element_update;*/
 
 	s_graphic_class->graphic_render = lsm_svg_text_element_graphic_render;
 
-	s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
+	s_element_class->attribute_manager = lsm_attribute_manager_duplicate (s_element_class->attribute_manager);
+
+	lsm_attribute_manager_add_attributes (s_element_class->attribute_manager,
+					      G_N_ELEMENTS (lsm_svg_text_element_attribute_infos),
+					      lsm_svg_text_element_attribute_infos);
+
+/*        s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);*/
 
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "x",
-					  offsetof (LsmSvgTextElement, x));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "y",
-					  offsetof (LsmSvgTextElement, y));
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "x",*/
+/*                                          offsetof (LsmSvgTextElement, x));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "y",*/
+/*                                          offsetof (LsmSvgTextElement, y));*/
 }
 
 G_DEFINE_TYPE (LsmSvgTextElement, lsm_svg_text_element, LSM_TYPE_SVG_GRAPHIC)
diff --git a/src/lsmsvgtraits.c b/src/lsmsvgtraits.c
new file mode 100644
index 0000000..93e4f91
--- /dev/null
+++ b/src/lsmsvgtraits.c
@@ -0,0 +1,654 @@
+/* lsmdom.h
+ *
+ * Copyright © 2009 Emmanuel Pacaud
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ * 	Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+#include <lsmsvgtraits.h>
+#include <lsmstr.h>
+#include <lsmsvgcolors.h>
+#include <math.h>
+#include <string.h>
+
+const LsmSvgColor lsm_svg_color_null = {0.0, 0.0, 0.0};
+const LsmSvgDashArray lsm_svg_dash_array_null = {0, NULL};
+
+static void
+lsm_svg_length_trait_from_string (LsmTrait *abstract_trait, char *string)
+{
+	LsmSvgLength *svg_length = (LsmSvgLength *) abstract_trait;
+	char *length_type_str;
+
+	svg_length->value_unit = g_strtod (string, &length_type_str);
+	svg_length->type = lsm_svg_length_type_from_string (length_type_str);
+}
+
+static char *
+lsm_svg_length_trait_to_string (LsmTrait *abstract_trait)
+{
+	LsmSvgLength *svg_length = (LsmSvgLength *) abstract_trait;
+
+	return g_strdup_printf ("%g%s",
+				svg_length->value_unit,
+				lsm_svg_length_type_to_string (svg_length->type));
+}
+
+const LsmTraitClass lsm_svg_length_trait_class = {
+	.size = sizeof (LsmSvgLength),
+	.from_string = lsm_svg_length_trait_from_string,
+	.to_string = lsm_svg_length_trait_to_string
+};
+
+static void
+_init_matrix (LsmSvgMatrix *matrix, LsmSvgTransformType transform, unsigned int n_values, double values[])
+{
+	switch (transform) {
+		case LSM_SVG_TRANSFORM_TYPE_SCALE:
+			if (n_values == 1) {
+				lsm_svg_matrix_init_scale (matrix, values[0], values[0]);
+				return;
+			} else if (n_values == 2) {
+				lsm_svg_matrix_init_scale (matrix, values[0], values[1]);
+				return;
+			}
+			break;
+		case LSM_SVG_TRANSFORM_TYPE_TRANSLATE:
+			if (n_values == 1) {
+				lsm_svg_matrix_init_translate (matrix, values[0], values[0]);
+				return;
+			} else if (n_values == 2) {
+				lsm_svg_matrix_init_translate (matrix, values[0], values[1]);
+				return;
+			}
+			break;
+		case LSM_SVG_TRANSFORM_TYPE_MATRIX:
+			if (n_values == 6) {
+				lsm_svg_matrix_init (matrix,
+						  values[0], values[1],
+						  values[2], values[3],
+						  values[4], values[5]);
+				return;
+			}
+			break;
+		case LSM_SVG_TRANSFORM_TYPE_ROTATE:
+			if (n_values == 1) {
+				lsm_svg_matrix_init_rotate (matrix, values[0] * M_PI / 180.0);
+				return;
+			} else if (n_values == 3) {
+				LsmSvgMatrix matrix_b;
+
+				lsm_svg_matrix_init_translate (matrix, values[1], values[2]);
+				lsm_svg_matrix_init_rotate (&matrix_b, values[0] * M_PI / 180.0);
+				lsm_svg_matrix_multiply (matrix, &matrix_b, matrix);
+				lsm_svg_matrix_init_translate (&matrix_b, -values[1], -values[2]);
+				lsm_svg_matrix_multiply (matrix, &matrix_b, matrix);
+				return;
+			}
+			break;
+		case LSM_SVG_TRANSFORM_TYPE_SKEW_X:
+			if (n_values == 1) {
+				lsm_svg_matrix_init_skew_x (matrix, values[0] * M_PI / 180.0);
+				return;
+			}
+			break;
+		case LSM_SVG_TRANSFORM_TYPE_SKEW_Y:
+			if (n_values == 1) {
+				lsm_svg_matrix_init_skew_y (matrix, values[0] * M_PI / 180.0);
+				return;
+			}
+		default:
+			break;
+	}
+
+	lsm_svg_matrix_init_identity (matrix);
+}
+
+static void
+lsm_svg_matrix_trait_from_string (LsmTrait *abstract_trait, char *string)
+{
+	LsmSvgMatrix *matrix = (LsmSvgMatrix *) abstract_trait;
+
+	lsm_svg_matrix_init_identity (matrix);
+
+	while (*string != '\0') {
+		LsmSvgTransformType transform;
+		double values[6];
+
+		lsm_str_skip_spaces (&string);
+
+		if (strncmp (string, "translate", 9) == 0) {
+			transform = LSM_SVG_TRANSFORM_TYPE_TRANSLATE;
+			string += 9;
+		} else if (strncmp (string, "scale", 5) == 0) {
+			transform = LSM_SVG_TRANSFORM_TYPE_SCALE;
+			string += 5;
+		} else if (strncmp (string, "rotate", 6) == 0) {
+			transform = LSM_SVG_TRANSFORM_TYPE_ROTATE;
+			string += 6;
+		} else if (strncmp (string, "matrix", 6) == 0) {
+			transform = LSM_SVG_TRANSFORM_TYPE_MATRIX;
+			string += 6;
+		} else if (strncmp (string, "skewX", 5) == 0) {
+			transform = LSM_SVG_TRANSFORM_TYPE_SKEW_X;
+			string += 5;
+		} else if (strncmp (string, "skewY", 5) == 0) {
+			transform = LSM_SVG_TRANSFORM_TYPE_SKEW_Y;
+			string += 5;
+		} else
+			break;
+
+		lsm_str_skip_spaces (&string);
+
+		if (*string == '(') {
+			unsigned int n_values = 0;
+
+			string++;
+
+			while (*string != ')' && *string != '\0' && n_values < 6) {
+				lsm_str_skip_comma_and_spaces (&string);
+
+				if (!lsm_str_parse_double (&string, &values[n_values]))
+					break;
+
+				n_values++;
+			}
+
+			lsm_str_skip_comma_and_spaces (&string);
+
+			if (*string == ')') {
+				LsmSvgMatrix new_matrix;
+
+				string++;
+
+				_init_matrix (&new_matrix, transform, n_values, values);
+
+				lsm_svg_matrix_multiply (matrix, &new_matrix, matrix);
+			}
+		}
+	}
+}
+
+static char *
+lsm_svg_matrix_trait_to_string (LsmTrait *abstract_trait)
+{
+	LsmSvgMatrix *matrix = (LsmSvgMatrix *) abstract_trait;
+
+	/* TODO smarter serialization, checking for zeros */
+	return g_strdup_printf ("matrix(%g,%g,%g,%g,%g,%g)",
+				matrix->a,
+				matrix->b,
+				matrix->c,
+				matrix->d,
+				matrix->e,
+				matrix->f);
+}
+
+const LsmTraitClass lsm_svg_matrix_trait_class = {
+	.size = sizeof (LsmSvgMatrix),
+	.from_string = lsm_svg_matrix_trait_from_string,
+	.to_string = lsm_svg_matrix_trait_to_string
+};
+
+static char *
+_parse_color (char *string,
+	      LsmSvgColor *svg_color,
+	      gboolean *is_color_set)
+{
+	unsigned int color = 0;
+	*is_color_set = FALSE;
+
+	lsm_str_skip_spaces (&string);
+
+	if (g_strcmp0 (string, "currentColor") == 0) {
+		svg_color->red = -1.0;
+		svg_color->green = 1.0;
+		svg_color->blue = 1.0;
+
+		*is_color_set = TRUE;
+
+		string += 12; /* strlen ("current_color") */
+
+		return string;
+	}
+
+	if (*string == '#') {
+		int value, i;
+		string++;
+
+		for (i = 0; i < 6; i++) {
+			if (*string >= '0' && *string <= '9')
+				value = *string - '0';
+			else if (*string >= 'A' && *string <= 'F')
+				value = *string - 'A' + 10;
+			else if (*string >= 'a' && *string <= 'f')
+				value = *string - 'a' + 10;
+			else
+				break;
+
+			color = (color << 4) + value;
+			string++;
+		}
+
+		if (i == 3) {
+			color = ((color & 0xf00) << 8) | ((color & 0x0f0) << 4) | (color & 0x00f);
+			color |= color << 4;
+		} else if (i != 6)
+			color = 0;
+
+		*is_color_set = TRUE;
+	} else if (strncmp (string, "rgb(", 4) == 0) {
+		int i;
+		double value;
+
+
+		string += 4; /* strlen ("rgb(") */
+
+		for (i = 0; i < 3; i++) {
+			if (!lsm_str_parse_double (&string, &value))
+				break;
+
+			if (*string == '%') {
+				value = value * 255.0 / 100.0;
+				string++;
+			}
+
+			if (i < 2)
+				lsm_str_skip_comma_and_spaces (&string);
+
+			color = (color << 8) + (int) (0.5 + CLAMP (value, 0.0, 255.0));
+		}
+
+		lsm_str_skip_spaces (&string);
+
+		if (*string != ')' || i != 3)
+			color = 0;
+
+		*is_color_set  = TRUE;
+	} else if (g_strcmp0 (string, "none") == 0) {
+		*is_color_set = FALSE;
+	} else {
+		color = lsm_svg_color_from_string (string);
+
+		*is_color_set = TRUE;
+	}
+
+	svg_color->red = (double) ((color & 0xff0000) >> 16) / 255.0;
+	svg_color->green = (double) ((color & 0x00ff00) >> 8) / 255.0;
+	svg_color->blue = (double) (color & 0x0000ff) / 255.0;
+
+	return string;
+}
+
+static void
+lsm_svg_paint_trait_from_string (LsmTrait *abstract_trait, char *string)
+{
+	LsmSvgPaint *paint = (LsmSvgPaint *) abstract_trait;
+	gboolean is_color_set;
+
+	g_free (paint->uri);
+
+	if (strncmp (string, "url(#", 5) == 0) {
+		unsigned int length;
+
+		string += 5;
+		length = 0;
+		while (string[length] != ')')
+			length++;
+		length++;
+
+		paint->uri = g_new (char, length);
+		if (paint->uri != NULL) {
+			memcpy (paint->uri, string, length - 1);
+			paint->uri[length - 1] = '\0';
+		}
+		string += length;
+	} else {
+		paint->uri = NULL;
+	}
+
+	string = _parse_color (string, &paint->color, &is_color_set);
+
+	if (is_color_set)
+		paint->type = paint->uri != NULL ?
+			LSM_SVG_PAINT_TYPE_URI_RGB_COLOR :
+			LSM_SVG_PAINT_TYPE_RGB_COLOR;
+	else
+		paint->type = paint->uri != NULL ?
+			LSM_SVG_PAINT_TYPE_URI :
+			LSM_SVG_PAINT_TYPE_NONE;
+}
+
+char *
+lsm_svg_paint_trait_to_string (LsmTrait *abstract_trait)
+{
+	LsmSvgPaint *paint = (LsmSvgPaint *) abstract_trait;
+
+	if (paint->color.red < 0.0 ||
+	    paint->color.green < 0.0 ||
+	    paint->color.blue < 0.0)
+		return g_strdup ("currentColor");
+
+	if (paint->uri != NULL)
+		g_strdup_printf ("url(#%s)", paint->uri);
+
+	return g_strdup_printf ("rgb(%g%%,%g%%,%g%%)",
+				100.0 * paint->color.red,
+				100.0 * paint->color.green,
+				100.0 * paint->color.blue);
+}
+
+const LsmTraitClass lsm_svg_paint_trait_class = {
+	.size = sizeof (LsmSvgPaint),
+	.from_string = lsm_svg_paint_trait_from_string,
+	.to_string = lsm_svg_paint_trait_to_string
+};
+
+static void
+lsm_svg_fill_rule_trait_from_string (LsmTrait *abstract_trait, char *string)
+{
+	LsmSvgFillRule *trait = (LsmSvgFillRule *) abstract_trait;
+
+	*trait = lsm_svg_fill_rule_from_string (string);
+}
+
+char *
+lsm_svg_fill_rule_trait_to_string (LsmTrait *abstract_trait)
+{
+	LsmSvgFillRule *trait = (LsmSvgFillRule *) abstract_trait;
+
+	return g_strdup (lsm_svg_fill_rule_to_string (*trait));
+}
+
+const LsmTraitClass lsm_svg_fill_rule_trait_class = {
+	.size = sizeof (LsmSvgFillRule),
+	.from_string = lsm_svg_fill_rule_trait_from_string,
+	.to_string = lsm_svg_fill_rule_trait_to_string
+};
+
+static void
+lsm_svg_line_join_trait_from_string (LsmTrait *abstract_trait, char *string)
+{
+	LsmSvgLineJoin *trait = (LsmSvgLineJoin *) abstract_trait;
+
+	*trait = lsm_svg_line_join_from_string (string);
+}
+
+char *
+lsm_svg_line_join_trait_to_string (LsmTrait *abstract_trait)
+{
+	LsmSvgLineJoin *trait = (LsmSvgLineJoin *) abstract_trait;
+
+	return g_strdup (lsm_svg_line_join_to_string (*trait));
+}
+
+const LsmTraitClass lsm_svg_line_join_trait_class = {
+	.size = sizeof (LsmSvgLineJoin),
+	.from_string = lsm_svg_line_join_trait_from_string,
+	.to_string = lsm_svg_line_join_trait_to_string
+};
+
+static void
+lsm_svg_line_cap_trait_from_string (LsmTrait *abstract_trait, char *string)
+{
+	LsmSvgLineCap *trait = (LsmSvgLineCap *) abstract_trait;
+
+	*trait = lsm_svg_line_cap_from_string (string);
+}
+
+static char *
+lsm_svg_line_cap_trait_to_string (LsmTrait *abstract_trait)
+{
+	LsmSvgLineCap *trait = (LsmSvgLineCap *) abstract_trait;
+
+	return g_strdup (lsm_svg_line_cap_to_string (*trait));
+}
+
+const LsmTraitClass lsm_svg_line_cap_trait_class = {
+	.size = sizeof (LsmSvgLineCap),
+	.from_string = lsm_svg_line_cap_trait_from_string,
+	.to_string = lsm_svg_line_cap_trait_to_string
+};
+
+LsmSvgDashArray *
+lsm_svg_dash_array_new (unsigned int n_dashes)
+{
+	LsmSvgDashArray *array;
+
+	g_return_val_if_fail (n_dashes > 0, (LsmSvgDashArray *) &lsm_svg_dash_array_null);
+
+	array = g_new (LsmSvgDashArray, 1);
+	if (array != NULL) {
+		array->n_dashes = n_dashes;
+		array->dashes = g_new (LsmSvgLength, n_dashes);
+		if (array->dashes != NULL)
+			return array;
+		g_free (array);
+	}
+
+	return (LsmSvgDashArray *) &lsm_svg_dash_array_null;
+}
+
+void
+lsm_svg_dash_array_free (LsmSvgDashArray *array)
+{
+	if (array == NULL || array == &lsm_svg_dash_array_null)
+		return;
+
+	g_free (array->dashes);
+	g_free (array);
+}
+
+LsmSvgDashArray *
+lsm_svg_dash_array_duplicate (const LsmSvgDashArray *origin)
+{
+	LsmSvgDashArray *duplicate;
+
+	if (origin == NULL || origin == &lsm_svg_dash_array_null)
+		return (LsmSvgDashArray *) &lsm_svg_dash_array_null;
+
+	duplicate = lsm_svg_dash_array_new (origin->n_dashes);
+
+	if (duplicate != &lsm_svg_dash_array_null)
+		memcpy (duplicate->dashes, origin->dashes, sizeof (LsmSvgLength) * origin->n_dashes);
+
+	return duplicate;
+}
+
+static void
+lsm_svg_dash_array_trait_from_string (LsmTrait *abstract_trait, char *string)
+{
+	LsmSvgDashArray *dash_array = (LsmSvgDashArray *) abstract_trait;
+	unsigned int n_dashes = 1;
+
+	g_free (dash_array->dashes);
+	dash_array->n_dashes = 0;
+	dash_array->dashes = NULL;
+
+	if (strcmp (string, "none") != 0) {
+		char *iter = (char *) string;
+		unsigned int i;
+
+		while (*iter != '\0') {
+			if (*iter == ',')
+				n_dashes++;
+			iter++;
+		}
+
+		if (n_dashes > 0) {
+			LsmSvgLength length;
+
+			dash_array->n_dashes = n_dashes;
+			dash_array->dashes = g_new (LsmSvgLength, n_dashes);
+
+			iter = (char *)string;
+			lsm_str_skip_spaces (&iter);
+
+			for (i = 0; i < n_dashes; i++) {
+				if (lsm_str_parse_double (&iter, &length.value_unit)) {
+					length.type = lsm_svg_length_type_from_string (iter);
+					dash_array->dashes[i] = length;
+					while (*iter != '\0' && *iter != ' ' && *iter != ',')
+						iter ++;
+				} else {
+					dash_array->dashes[i].value_unit = 0.0;
+					dash_array->dashes[i].value_unit = LSM_SVG_LENGTH_TYPE_NUMBER;
+				}
+				lsm_str_skip_comma_and_spaces (&iter);
+			}
+		}
+	}
+}
+
+static char *
+lsm_svg_dash_array_trait_to_string (LsmTrait *abstract_trait)
+{
+	g_assert_not_reached ();
+}
+
+static void
+lsm_svg_dash_array_trait_finalize (LsmTrait *abstract_trait)
+{
+	LsmSvgDashArray *dash_array = (LsmSvgDashArray *) abstract_trait;
+
+	g_free (dash_array->dashes);
+	dash_array->n_dashes = 0;
+	dash_array->dashes = NULL;
+}
+
+const LsmTraitClass lsm_svg_dash_array_trait_class = {
+	.size = sizeof (LsmSvgDashArray),
+	.from_string = lsm_svg_dash_array_trait_from_string,
+	.to_string = lsm_svg_dash_array_trait_to_string,
+	.finalize = lsm_svg_dash_array_trait_finalize
+};
+
+static void
+lsm_svg_color_trait_from_string (LsmTrait *abstract_trait, char *string)
+{
+	LsmSvgColor *color = (LsmSvgColor *) abstract_trait;
+	gboolean is_color_set;
+
+	_parse_color (string, color, &is_color_set);
+}
+
+static char *
+lsm_svg_color_trait_to_string (LsmTrait *abstract_trait)
+{
+	LsmSvgColor *color = (LsmSvgColor *) abstract_trait;
+
+	return g_strdup_printf ("rgb(%g%%,%g%%,%g%%)",
+				100.0 * color->red,
+				100.0 * color->green,
+				100.0 * color->blue);
+}
+
+const LsmTraitClass lsm_svg_color_trait_class = {
+	.size = sizeof (LsmSvgColor),
+	.from_string = lsm_svg_color_trait_from_string,
+	.to_string = lsm_svg_color_trait_to_string
+};
+
+static void
+lsm_svg_pattern_units_trait_from_string (LsmTrait *abstract_trait, char *string)
+{
+	LsmSvgPatternUnits *trait = (LsmSvgPatternUnits *) abstract_trait;
+
+	*trait = lsm_svg_pattern_units_from_string (string);
+}
+
+char *
+lsm_svg_pattern_units_trait_to_string (LsmTrait *abstract_trait)
+{
+	LsmSvgPatternUnits *trait = (LsmSvgPatternUnits *) abstract_trait;
+
+	return g_strdup (lsm_svg_pattern_units_to_string (*trait));
+}
+
+const LsmTraitClass lsm_svg_pattern_units_trait_class = {
+	.size = sizeof (LsmSvgPatternUnits),
+	.from_string = lsm_svg_pattern_units_trait_from_string,
+	.to_string = lsm_svg_pattern_units_trait_to_string
+};
+
+static void
+lsm_svg_preserve_aspect_ratio_trait_from_string (LsmTrait *abstract_trait, char *string)
+{
+	LsmSvgPreserveAspectRatio *trait = (LsmSvgPreserveAspectRatio *) abstract_trait;
+
+	char **tokens;
+	unsigned int i = 0;
+
+	tokens = g_strsplit (string, " ", -1);
+
+	if (tokens[i] != NULL && strcmp (tokens[i], "defer") == 0) {
+		trait->defer = TRUE;
+		i++;
+	} else
+		trait->defer = FALSE;
+
+	if (tokens[i] != NULL) {
+		trait->align = lsm_svg_align_from_string (tokens[i]);
+		i++;
+		if (tokens[i] != NULL)
+			trait->meet_or_slice = lsm_svg_meet_or_slice_from_string (tokens[i]);
+		else
+			trait->meet_or_slice = LSM_SVG_MEET_OR_SLICE_MEET;
+	} else trait->align = LSM_SVG_ALIGN_X_MID_Y_MID;
+
+	g_strfreev (tokens);
+}
+
+char *
+lsm_svg_preserve_aspect_ratio_trait_to_string (LsmTrait *abstract_trait)
+{
+	LsmSvgPreserveAspectRatio *trait = (LsmSvgPreserveAspectRatio *) abstract_trait;
+
+	return g_strdup_printf ("%s%s %s", trait->defer ? "defer " : "",
+				lsm_svg_align_to_string (trait->align),
+				lsm_svg_meet_or_slice_to_string (trait->meet_or_slice));
+}
+
+const LsmTraitClass lsm_svg_preserve_aspect_ratio_trait_class = {
+	.size = sizeof (LsmSvgPreserveAspectRatio),
+	.from_string = lsm_svg_preserve_aspect_ratio_trait_from_string,
+	.to_string = lsm_svg_preserve_aspect_ratio_trait_to_string
+};
+
+static void
+lsm_svg_spread_method_trait_from_string (LsmTrait *abstract_trait, char *string)
+{
+	LsmSvgSpreadMethod *trait = (LsmSvgSpreadMethod *) abstract_trait;
+
+	*trait = lsm_svg_spread_method_from_string (string);
+}
+
+static char *
+lsm_svg_spread_method_trait_to_string (LsmTrait *abstract_trait)
+{
+	LsmSvgSpreadMethod *trait = (LsmSvgSpreadMethod *) abstract_trait;
+
+	return g_strdup (lsm_svg_spread_method_to_string (*trait));
+}
+
+const LsmTraitClass lsm_svg_spread_method_trait_class = {
+	.size = sizeof (LsmSvgSpreadMethod),
+	.from_string = lsm_svg_spread_method_trait_from_string,
+	.to_string = lsm_svg_spread_method_trait_to_string
+};
+
diff --git a/src/lsmsvgtraits.h b/src/lsmsvgtraits.h
new file mode 100644
index 0000000..e33c474
--- /dev/null
+++ b/src/lsmsvgtraits.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright © 2009 Emmanuel Pacaud
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ * 	Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+#ifndef LSM_SVG_TRAITS_H
+#define LSM_SVG_TRAITS_H
+
+#include <lsmtraits.h>
+#include <lsmsvglength.h>
+#include <lsmsvgmatrix.h>
+
+G_BEGIN_DECLS
+
+typedef struct {
+	double red;
+	double green;
+	double blue;
+} LsmSvgColor;
+
+extern const LsmSvgColor lsm_svg_color_null;
+
+typedef struct {
+	unsigned int n_dashes;
+	LsmSvgLength *dashes;
+} LsmSvgDashArray;
+
+extern const LsmSvgDashArray lsm_svg_dash_array_null;
+
+LsmSvgDashArray * 	lsm_svg_dash_array_new 		(unsigned int n_dashes);
+void 			lsm_svg_dash_array_free 	(LsmSvgDashArray *array);
+LsmSvgDashArray * 	lsm_svg_dash_array_duplicate 	(const LsmSvgDashArray *origin);
+void			lsm_svg_dash_array_copy		(LsmSvgDashArray *to, const LsmSvgDashArray *from);
+
+typedef struct {
+	LsmSvgPaintType type;
+	char *uri;
+	LsmSvgColor color;
+} LsmSvgPaint;
+
+typedef struct {
+	gboolean defer;
+	LsmSvgAlign align;
+	LsmSvgMeetOrSlice meet_or_slice;
+} LsmSvgPreserveAspectRatio;
+
+extern const LsmTraitClass lsm_svg_length_trait_class;
+extern const LsmTraitClass lsm_svg_matrix_trait_class;
+extern const LsmTraitClass lsm_svg_paint_trait_class;
+extern const LsmTraitClass lsm_svg_fill_rule_trait_class;
+extern const LsmTraitClass lsm_svg_line_join_trait_class;
+extern const LsmTraitClass lsm_svg_line_cap_trait_class;
+extern const LsmTraitClass lsm_svg_dash_array_trait_class;
+extern const LsmTraitClass lsm_svg_color_trait_class;
+extern const LsmTraitClass lsm_svg_pattern_units_trait_class;
+extern const LsmTraitClass lsm_svg_preserve_aspect_ratio_trait_class;
+extern const LsmTraitClass lsm_svg_spread_method_trait_class;
+
+G_END_DECLS
+
+#endif
diff --git a/src/lsmsvguseelement.c b/src/lsmsvguseelement.c
index 819ecea..27bdc56 100644
--- a/src/lsmsvguseelement.c
+++ b/src/lsmsvguseelement.c
@@ -43,6 +43,7 @@ lsm_svg_use_can_append_child (LsmDomNode *node, LsmDomNode *child)
 
 /* LsmSvgElement implementation */
 
+#if 0
 static void
 lsm_svg_use_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 {
@@ -67,6 +68,7 @@ lsm_svg_use_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 
 	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
 }
+#endif
 
 /* LsmSvgGraphic implementation */
 
@@ -139,6 +141,40 @@ lsm_svg_use_element_init (LsmSvgUseElement *self)
 
 /* LsmSvgUseElement class */
 
+static const LsmSvgLength length_default = 	 { .value_unit =   0.0, .type = LSM_SVG_LENGTH_TYPE_PX};
+
+static const LsmAttributeInfos lsm_svg_use_element_attribute_infos[] = {
+	{
+		.name = "x",
+		.attribute_offset = offsetof (LsmSvgUseElement, x),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &length_default
+	},
+	{
+		.name = "y",
+		.attribute_offset = offsetof (LsmSvgUseElement, y),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &length_default
+	},
+	{
+		.name = "width",
+		.attribute_offset = offsetof (LsmSvgUseElement, width),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &length_default
+	},
+	{
+		.name = "height",
+		.attribute_offset = offsetof (LsmSvgUseElement, height),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &length_default
+	},
+	{
+		.name = "xlink:href",
+		.attribute_offset = offsetof (LsmSvgUseElement, href),
+		.trait_class = &lsm_null_trait_class
+	}
+};
+
 static void
 lsm_svg_use_element_class_init (LsmSvgUseElementClass *klass)
 {
@@ -151,22 +187,28 @@ lsm_svg_use_element_class_init (LsmSvgUseElementClass *klass)
 	d_node_class->get_node_name = lsm_svg_use_element_get_node_name;
 	d_node_class->can_append_child = lsm_svg_use_can_append_child;
 
-	s_element_class->update = lsm_svg_use_element_update;
+/*        s_element_class->update = lsm_svg_use_element_update;*/
 
 	s_graphic_class->graphic_render = lsm_svg_use_element_graphic_render;
 
-	s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
-
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "x",
-					  offsetof (LsmSvgUseElement, x));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "y",
-					  offsetof (LsmSvgUseElement, y));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "width",
-					  offsetof (LsmSvgUseElement, width));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "height",
-					  offsetof (LsmSvgUseElement, height));
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "xlink:href",
-					  offsetof (LsmSvgUseElement, href));
+	s_element_class->attribute_manager = lsm_attribute_manager_duplicate (s_element_class->attribute_manager);
+
+	lsm_attribute_manager_add_attributes (s_element_class->attribute_manager,
+					      G_N_ELEMENTS (lsm_svg_use_element_attribute_infos),
+					      lsm_svg_use_element_attribute_infos);
+
+/*        s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);*/
+
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "x",*/
+/*                                          offsetof (LsmSvgUseElement, x));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "y",*/
+/*                                          offsetof (LsmSvgUseElement, y));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "width",*/
+/*                                          offsetof (LsmSvgUseElement, width));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "height",*/
+/*                                          offsetof (LsmSvgUseElement, height));*/
+/*        lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "xlink:href",*/
+/*                                          offsetof (LsmSvgUseElement, href));*/
 }
 
 G_DEFINE_TYPE (LsmSvgUseElement, lsm_svg_use_element, LSM_TYPE_SVG_GRAPHIC)
diff --git a/src/lsmsvgview.c b/src/lsmsvgview.c
index 0aaed98..598a135 100644
--- a/src/lsmsvgview.c
+++ b/src/lsmsvgview.c
@@ -28,7 +28,7 @@
 #include <lsmsvgpatternelement.h>
 #include <lsmsvgclippathelement.h>
 #include <lsmsvgmaskelement.h>
-#include <lsmsvgutils.h>
+#include <lsmstr.h>
 #include <gdk/gdk.h>
 #include <glib/gprintf.h>
 
@@ -474,7 +474,7 @@ static void
 _emit_function_1 (LsmSvgPathContext *ctxt,
 		  void (*cairo_func) (cairo_t *, double))
 {
-	while (lsm_svg_str_parse_double_list (&ctxt->ptr, 1, ctxt->values))
+	while (lsm_str_parse_double_list (&ctxt->ptr, 1, ctxt->values))
 		cairo_func (ctxt->cr, ctxt->values[0]);
 }
 
@@ -484,12 +484,12 @@ _emit_function_2 (LsmSvgPathContext *ctxt,
 		  void (*cairo_func_b) (cairo_t *, double, double))
 {
 
-	if (lsm_svg_str_parse_double_list (&ctxt->ptr, 2, ctxt->values)) {
+	if (lsm_str_parse_double_list (&ctxt->ptr, 2, ctxt->values)) {
 		cairo_func_a (ctxt->cr, ctxt->values[0], ctxt->values[1]);
 
 		/* Why oh why does the specification say Line is implied here ? */
 
-		while (lsm_svg_str_parse_double_list (&ctxt->ptr, 2, ctxt->values))
+		while (lsm_str_parse_double_list (&ctxt->ptr, 2, ctxt->values))
 			cairo_func_b (ctxt->cr, ctxt->values[0], ctxt->values[1]);
 	}
 }
@@ -498,7 +498,7 @@ static void
 _emit_function_4 (LsmSvgPathContext *ctxt,
 		  void (*cairo_func) (cairo_t *, double, double, double, double))
 {
-	while (lsm_svg_str_parse_double_list (&ctxt->ptr, 4, ctxt->values))
+	while (lsm_str_parse_double_list (&ctxt->ptr, 4, ctxt->values))
 		cairo_func (ctxt->cr, ctxt->values[0], ctxt->values[1], ctxt->values[2], ctxt->values[3]);
 }
 
@@ -530,7 +530,7 @@ _emit_smooth_curve (LsmSvgPathContext *ctxt, gboolean relative)
 		default: x = x0; y = y0; break;
 	}
 
-	while (lsm_svg_str_parse_double_list (&ctxt->ptr, 4, ctxt->values)) {
+	while (lsm_str_parse_double_list (&ctxt->ptr, 4, ctxt->values)) {
 		if (relative) {
 			cairo_get_current_point (ctxt->cr, &x0, &y0);
 			cairo_curve_to (ctxt->cr,
@@ -571,7 +571,7 @@ _emit_smooth_quadratic_curve (LsmSvgPathContext *ctxt, gboolean relative)
 		default: ctxt->last_cp_x = x0; ctxt->last_cp_y = y0; break;
 	}
 
-	while (lsm_svg_str_parse_double_list (&ctxt->ptr, 2, ctxt->values)) {
+	while (lsm_str_parse_double_list (&ctxt->ptr, 2, ctxt->values)) {
 		x = 2 * x0 - ctxt->last_cp_x;
 		y = 2 * y0 - ctxt->last_cp_y;
 		if (relative) {
@@ -590,7 +590,7 @@ static void
 _emit_function_6 (LsmSvgPathContext *ctxt,
 		  void (*cairo_func) (cairo_t *, double, double, double ,double, double, double))
 {
-	while (lsm_svg_str_parse_double_list (&ctxt->ptr, 6, ctxt->values))
+	while (lsm_str_parse_double_list (&ctxt->ptr, 6, ctxt->values))
 		cairo_func (ctxt->cr, ctxt->values[0], ctxt->values[1], ctxt->values[2],
 			              ctxt->values[3], ctxt->values[4], ctxt->values[5]);
 }
@@ -599,7 +599,7 @@ static void
 _emit_function_7 (LsmSvgPathContext *ctxt,
 		  void (*cairo_func) (cairo_t *, double, double, double ,gboolean, gboolean, double, double))
 {
-	while (lsm_svg_str_parse_double_list (&ctxt->ptr, 7, ctxt->values))
+	while (lsm_str_parse_double_list (&ctxt->ptr, 7, ctxt->values))
 		cairo_func (ctxt->cr, ctxt->values[0], ctxt->values[1], ctxt->values[2],
 			              ctxt->values[3], ctxt->values[4], ctxt->values[5],
 				      ctxt->values[6]);
@@ -624,14 +624,14 @@ _emit_svg_path (cairo_t *cr, char const *path)
 	ctxt.values[2] = ctxt.values[4] = ctxt.values[0];
 	ctxt.values[3] = ctxt.values[5] = ctxt.values[1];
 
-	lsm_svg_str_skip_spaces (&ctxt.ptr);
+	lsm_str_skip_spaces (&ctxt.ptr);
 
 	while (*ctxt.ptr != '\0') {
 		char command;
 
 		command = *ctxt.ptr;
 		ctxt.ptr++;
-		lsm_svg_str_skip_spaces (&ctxt.ptr);
+		lsm_str_skip_spaces (&ctxt.ptr);
 
 		if (!cairo_has_current_point (cr)) {
 			cairo_move_to (cr, 0, 0);
@@ -1018,9 +1018,9 @@ lsm_svg_view_show_polyline (LsmSvgView *view, const char *points)
 
 	str = (char *) points;
 
-	if (lsm_svg_str_parse_double_list (&str, 2, values)) {
+	if (lsm_str_parse_double_list (&str, 2, values)) {
 		cairo_move_to (view->dom_view.cairo, values[0], values[1]);
-		while (lsm_svg_str_parse_double_list (&str, 2, values))
+		while (lsm_str_parse_double_list (&str, 2, values))
 			cairo_line_to (view->dom_view.cairo, values[0], values[1]);
 	}
 
@@ -1037,9 +1037,9 @@ lsm_svg_view_show_polygon (LsmSvgView *view, const char *points)
 
 	str = (char *) points;
 
-	if (lsm_svg_str_parse_double_list (&str, 2, values)) {
+	if (lsm_str_parse_double_list (&str, 2, values)) {
 		cairo_move_to (view->dom_view.cairo, values[0], values[1]);
-		while (lsm_svg_str_parse_double_list (&str, 2, values))
+		while (lsm_str_parse_double_list (&str, 2, values))
 			cairo_line_to (view->dom_view.cairo, values[0], values[1]);
 	}
 
diff --git a/src/lsmtraits.c b/src/lsmtraits.c
new file mode 100644
index 0000000..36b217c
--- /dev/null
+++ b/src/lsmtraits.c
@@ -0,0 +1,74 @@
+#include <lsmtraits.h>
+#include <lsmstr.h>
+
+const LsmTraitClass lsm_null_trait_class = {
+	.size = 0
+};
+
+static void
+lsm_double_trait_from_string (LsmTrait *abstract_trait, char *string)
+{
+	double *trait = (double *) abstract_trait;
+
+	*trait = g_strtod (string, NULL);
+}
+
+static char *
+lsm_double_trait_to_string (LsmTrait *abstract_trait)
+{
+	double *trait = (double *) abstract_trait;
+
+	return g_strdup_printf ("%g", *trait);
+}
+
+const LsmTraitClass lsm_double_trait_class = {
+	.size = sizeof (double),
+	.from_string = lsm_double_trait_from_string,
+	.to_string = lsm_double_trait_to_string
+};
+
+static void
+lsm_box_trait_from_string (LsmTrait *abstract_trait, char *string)
+{
+	LsmBox *trait = (LsmBox *) abstract_trait;
+	unsigned int i;
+	double value[4];
+
+	for (i = 0; i < 4 && *string != '\0'; i++) {
+		lsm_str_skip_semicolon_and_spaces (&string);
+
+		if (!lsm_str_parse_double (&string, &value[i]))
+			break;
+	}
+
+	if (i == 4) {
+		trait->x = value[0];
+		trait->y = value[1];
+		trait->width = value[2];
+		trait->height = value[3];
+
+		return;
+	}
+
+	trait->x =
+	trait->y =
+	trait->width =
+	trait->height = 0.0;
+}
+
+char *
+lsm_box_trait_to_string (LsmTrait *abstract_trait)
+{
+	LsmBox *trait = (LsmBox *) abstract_trait;
+
+	return g_strdup_printf ("%g %g %g %g",
+				trait->x, trait->y,
+				trait->width, trait->height);
+}
+
+const LsmTraitClass lsm_box_trait_class = {
+	.size = sizeof (LsmBox),
+	.from_string = lsm_box_trait_from_string,
+	.to_string = lsm_box_trait_to_string
+};
+
diff --git a/src/lsmsvgutils.h b/src/lsmtraits.h
similarity index 51%
rename from src/lsmsvgutils.h
rename to src/lsmtraits.h
index 828772d..e7f5d3e 100644
--- a/src/lsmsvgutils.h
+++ b/src/lsmtraits.h
@@ -19,51 +19,26 @@
  * 	Emmanuel Pacaud <emmanuel gnome org>
  */
 
+#ifndef LSM_TRAITS_H
+#define LSM_TRAITS_H
 
-#ifndef GSGV_UTILS_H
-#define GSGV_UTILS_H
-
-#include <lsmsvg.h>
+#include <lsm.h>
 
 G_BEGIN_DECLS
 
-gboolean lsm_svg_str_parse_double 	(char **str, double *x);
-gboolean lsm_svg_str_parse_double_list 	(char **str, unsigned int n_values, double *values);
-
-static inline void
-lsm_svg_str_skip_spaces (char **str)
-{
-	while (g_ascii_isspace (**str))
-		(*str)++;
-}
-
-static inline void
-lsm_svg_str_skip_char (char **str, char c)
-{
-	while (**str == c)
-		(*str)++;
-}
-
-static inline void
-lsm_svg_str_skip_comma_and_spaces (char **str)
-{
-	while (g_ascii_isspace (**str) || **str == ',')
-		(*str)++;
-}
+typedef void * LsmTrait;
 
-static inline void
-lsm_svg_str_skip_semicolon_and_spaces (char **str)
-{
-	while (g_ascii_isspace (**str) || **str == ';')
-		(*str)++;
-}
+typedef struct {
+	size_t		size;
+	void 		(*init)			(LsmTrait *abstract_trait, const void *trait_default);
+	void 		(*finalize)		(LsmTrait *abstract_trait);
+	void		(*from_string)		(LsmTrait *abstract_trait, char *string);
+	char * 		(*to_string)		(LsmTrait *abstract_trait);
+} LsmTraitClass;
 
-static inline void
-lsm_svg_str_skip_colon_and_spaces (char **str)
-{
-	while (g_ascii_isspace (**str) || **str == ':')
-		(*str)++;
-}
+extern const LsmTraitClass lsm_null_trait_class;
+extern const LsmTraitClass lsm_double_trait_class;
+extern const LsmTraitClass lsm_box_trait_class;
 
 G_END_DECLS
 



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