[lasem] Rework of property handling. Use for SVG.



commit c417ea79a4a791e2ab441da714a8b1ac854e0805
Author: Emmanuel Pacaud <emmanuel pacaud lapp in2p3 fr>
Date:   Fri Aug 7 11:37:17 2009 +0200

    Rework of property handling. Use for SVG.

 .gitignore                        |    1 +
 src/Makefile.am                   |   51 ++--
 src/lasemrender.c                 |  150 +++------
 src/lasemtest.c                   |    7 +-
 src/lsmdom.h                      |   17 +-
 src/lsmdomdocument.c              |   81 +++++
 src/lsmdomdocument.h              |   12 +-
 src/lsmdomnode.h                  |   24 +-
 src/lsmdomparser.c                |  134 +++++++-
 src/lsmdomparser.h                |    9 +-
 src/lsmdomview.c                  |    3 +
 src/lsmmathmldocument.c           |    2 +
 src/lsmmathmldocument.h           |    2 +
 src/lsmmathmlmathelement.c        |    2 +
 src/lsmmathmltableelement.c       |    2 +
 src/lsmsvgattributebags.c         |  272 ---------------
 src/lsmsvgattributebags.h         |   77 -----
 src/lsmsvgattributes.c            |  659 ------------------------------------
 src/lsmsvgattributes.h            |  105 ++-----
 src/lsmsvgcircleelement.c         |   77 +++---
 src/lsmsvgcircleelement.h         |   12 +-
 src/lsmsvgclippathelement.c       |   70 +++--
 src/lsmsvgclippathelement.h       |   10 +-
 src/lsmsvgdefselement.c           |    2 +-
 src/lsmsvgdefselement.h           |    6 +-
 src/lsmsvgdocument.h              |    2 +-
 src/lsmsvgelement.c               |  199 +++++++-----
 src/lsmsvgelement.h               |   21 +-
 src/lsmsvgellipseelement.c        |   90 +++---
 src/lsmsvgellipseelement.h        |   14 +-
 src/lsmsvgenums.c                 |    2 +-
 src/lsmsvggelement.c              |    5 +-
 src/lsmsvggelement.h              |    6 +-
 src/lsmsvggradientelement.c       |  115 ++++----
 src/lsmsvggradientelement.h       |   16 +-
 src/lsmsvggraphic.c               |  296 ----------------
 src/lsmsvggraphic.h               |   67 ----
 src/lsmsvgimageelement.c          |  181 ++++++-----
 src/lsmsvgimageelement.h          |   16 +-
 src/lsmsvglineargradientelement.c |   90 +++---
 src/lsmsvglineargradientelement.h |    8 +-
 src/lsmsvglineelement.c           |   91 +++---
 src/lsmsvglineelement.h           |   14 +-
 src/lsmsvgmaskelement.c           |  153 +++++----
 src/lsmsvgmaskelement.h           |   22 +-
 src/lsmsvgmatrix.c                |   25 ++
 src/lsmsvgmatrix.h                |    7 +
 src/lsmsvgpathelement.c           |   28 +-
 src/lsmsvgpathelement.h           |   10 +-
 src/lsmsvgpatternelement.c        |  200 +++++++-----
 src/lsmsvgpatternelement.h        |   22 +-
 src/lsmsvgpolygonelement.c        |   23 +-
 src/lsmsvgpolygonelement.h        |    8 +-
 src/lsmsvgpolylineelement.c       |   23 +-
 src/lsmsvgpolylineelement.h       |    8 +-
 src/lsmsvgradialgradientelement.c |  117 ++++---
 src/lsmsvgradialgradientelement.h |   10 +-
 src/lsmsvgrectelement.c           |  139 ++++----
 src/lsmsvgrectelement.h           |   20 +-
 src/lsmsvgstopelement.c           |   70 ++---
 src/lsmsvgstopelement.h           |   10 +-
 src/lsmsvgstyle.c                 |  463 +++++++++++++++++++++++++-
 src/lsmsvgstyle.h                 |  162 +++++++---
 src/lsmsvgsvgelement.c            |  205 +++++-------
 src/lsmsvgsvgelement.h            |   10 +-
 src/lsmsvgsymbolelement.c         |   13 +-
 src/lsmsvgsymbolelement.h         |    6 +-
 src/lsmsvgtextelement.c           |   70 ++--
 src/lsmsvgtextelement.h           |   10 +-
 src/lsmsvgtraits.c                |  666 +++++++++++++++++++++++++++++++++++++
 src/lsmsvgtraits.h                |   77 +++++
 src/lsmsvguseelement.c            |  104 +++---
 src/lsmsvguseelement.h            |   16 +-
 src/lsmsvgutils.c                 |  132 --------
 src/lsmsvgutils.h                 |   70 ----
 src/lsmsvgview.c                  |  443 +++++++++++--------------
 src/lsmsvgview.h                  |   26 +-
 test/.gitignore                   |    1 -
 78 files changed, 3125 insertions(+), 3264 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index ba0eeca..1832f85 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,4 +24,5 @@ tags
 *.swp
 lasem.svg
 lasem.pc
+lasemtest.xml
 manugen
diff --git a/src/Makefile.am b/src/Makefile.am
index dc76bd8..0d989f6 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -7,7 +7,8 @@ INCLUDES = \
 AM_CFLAGS =\
 	 -Wall\
 	 -Werror \
-	 -g
+	 -g \
+	 -O0
 
 lib_LTLIBRARIES = liblasem.la
 
@@ -17,6 +18,10 @@ liblasem_la_LIBADD = 				\
 
 liblasem_la_SOURCES =				\
 	lsmdebug.c				\
+	lsmstr.c				\
+	lsmtraits.c				\
+	lsmproperties.c				\
+	lsmattributes.c				\
 	lsmdomnode.c				\
 	lsmdomnodelist.c			\
 	lsmdomdocument.c			\
@@ -60,9 +65,15 @@ liblasem_la_SOURCES =				\
 	lsmmathmlaligngroupelement.c		\
 	lsmmathmlutils.c			\
 	lsmmathmllayoututils.c			\
+	lsmsvgenums.c				\
+	lsmsvgtraits.c				\
+	lsmsvgstyle.c				\
+	lsmsvgcolors.c				\
+	lsmsvglength.c				\
+	lsmsvgview.c				\
+	lsmsvgmatrix.c				\
 	lsmsvgdocument.c			\
 	lsmsvgelement.c				\
-	lsmsvggraphic.c				\
 	lsmsvgclippathelement.c			\
 	lsmsvgsvgelement.c			\
 	lsmsvguseelement.c			\
@@ -83,20 +94,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			\
@@ -143,9 +150,16 @@ liblasem_la_HEADERS = \
 	lsmmathmlutils.h			\
 	lsmmathmllayoututils.h			\
 	lsmsvg.h				\
+	lsmsvgenums.h				\
+	lsmsvgtraits.h				\
+	lsmsvgattributes.h			\
+	lsmsvgstyle.h				\
+	lsmsvgcolors.h				\
+	lsmsvglength.h				\
+	lsmsvgview.h				\
+	lsmsvgmatrix.h				\
 	lsmsvgdocument.h			\
 	lsmsvgelement.h				\
-	lsmsvggraphic.h				\
 	lsmsvgclippathelement.h			\
 	lsmsvgsvgelement.h			\
 	lsmsvggelement.h			\
@@ -166,16 +180,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/lasemrender.c b/src/lasemrender.c
index 32c89ab..b93cc01 100644
--- a/src/lasemrender.c
+++ b/src/lasemrender.c
@@ -85,16 +85,11 @@ int main(int argc, char **argv)
 	cairo_surface_t *surface;
 	GError *error = NULL;
 	GOptionContext *context;
-	GFile *file;
 	FileFormat format;
 	char *output_filename;
 	char *input_filename;
-	char *mime;
-	char *buffer = NULL;
-	size_t size;
 	double height_pt, width_pt;
 	unsigned int height, width;
-	gboolean success;
 
 	g_type_init ();
 
@@ -164,102 +159,69 @@ int main(int argc, char **argv)
 		g_free (directory);
 	}
 
-	mime = g_content_type_guess (input_filename, NULL, 0, NULL);
-	file = g_file_new_for_path (input_filename);
+	document = lsm_dom_document_new_from_path (input_filename, NULL);
+	if (document == NULL)
+		document = lsm_dom_document_new_from_url (input_filename, NULL);
 
-	success = g_file_load_contents (file, NULL, &buffer, &size, NULL, NULL);
-	if (!success) {
-		g_object_unref (file);
-		file = g_file_new_for_uri (input_filename);
-		success = g_file_load_contents (file, NULL, &buffer, &size, NULL, NULL);
-	}
+	if (document != NULL) {
+		lsm_dom_document_set_resolution (document, option_ppi);
+
+		view = lsm_dom_document_create_view (document);
+
+		lsm_dom_view_set_debug (view, option_debug);
 
-	if (success) {
-		char *mathml;
+		width_pt = 2.0;
+		height_pt = 2.0;
 
-		if (strcmp (mime, "text/mathml") == 0 ||
-		    strcmp (mime, "image/svg+xml") == 0)
-			mathml = buffer;
-		else {
-			mathml = itex2MML_parse (buffer, size);
-			g_free (buffer);
-			buffer = NULL;
+		lsm_dom_view_get_size (view, &width_pt, &height_pt);
+		lsm_dom_view_get_size_pixels (view, &width, &height);
+
+		switch (format) {
+			case FORMAT_PDF:
+				surface = cairo_pdf_surface_create (output_filename,
+								    width_pt, height_pt);
+				break;
+			case FORMAT_PS:
+				surface = cairo_ps_surface_create (output_filename,
+								   width_pt, height_pt);
+				break;
+			case FORMAT_PNG:
+				surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+								      width,
+								      height);
+				break;
+			case FORMAT_SVG:
+			default:
+				surface = cairo_svg_surface_create (output_filename,
+								    width_pt, height_pt);
+				break;
 		}
 
-		if (mathml != NULL) {
-			document = lsm_dom_document_new_from_memory (mathml);
-			lsm_dom_document_set_resolution (document, option_ppi);
-
-			if (document != NULL) {
-				view = lsm_dom_document_create_view (document);
-
-				lsm_dom_view_set_debug (view, option_debug);
-
-				width_pt = 2.0;
-				height_pt = 2.0;
-
-				lsm_dom_view_get_size (view, &width_pt, &height_pt);
-				lsm_dom_view_get_size_pixels (view, &width, &height);
-
-				switch (format) {
-					case FORMAT_PDF:
-						surface = cairo_pdf_surface_create (output_filename,
-										    width_pt, height_pt);
-						break;
-					case FORMAT_PS:
-						surface = cairo_ps_surface_create (output_filename,
-										   width_pt, height_pt);
-						break;
-					case FORMAT_PNG:
-						surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
-										      width,
-										      height);
-						break;
-					case FORMAT_SVG:
-					default:
-						surface = cairo_svg_surface_create (output_filename,
-										    width_pt, height_pt);
-						break;
-				}
-
-				cairo = cairo_create (surface);
-				cairo_surface_destroy (surface);
-
-				lsm_dom_view_set_cairo (view, cairo);
-
-				lsm_dom_view_render (view, 0, 0);
-
-				switch (format) {
-					case FORMAT_PNG:
-						cairo_surface_write_to_png (cairo_get_target (cairo),
-									    output_filename);
-						break;
-					default:
-						break;
-				}
-
-				cairo_destroy (cairo);
-
-				g_object_unref (view);
-
-				g_object_unref (document);
-
-				lsm_debug ("width = %g pt, height = %g pt",  width_pt, height_pt);
-			} else
-				g_warning ("Can't load %s", input_filename);
-		} else
-			g_warning ("Invalid document");
-
-		if (mathml == buffer)
-			g_free (mathml);
-		else
-			itex2MML_free_string (mathml);
-
-		g_object_unref (file);
+		cairo = cairo_create (surface);
+		cairo_surface_destroy (surface);
+
+		lsm_dom_view_set_cairo (view, cairo);
+
+		lsm_dom_view_render (view, 0, 0);
+
+		switch (format) {
+			case FORMAT_PNG:
+				cairo_surface_write_to_png (cairo_get_target (cairo),
+							    output_filename);
+				break;
+			default:
+				break;
+		}
+
+		cairo_destroy (cairo);
+
+		g_object_unref (view);
+
+		g_object_unref (document);
+
+		lsm_debug ("width = %g pt, height = %g pt",  width_pt, height_pt);
 	} else
 		g_warning ("Can't load %s", input_filename);
 
-	g_free (mime);
-
 	return (0);
 }
diff --git a/src/lasemtest.c b/src/lasemtest.c
index 4a3a16e..bf385f6 100644
--- a/src/lasemtest.c
+++ b/src/lasemtest.c
@@ -115,10 +115,13 @@ lasem_test_render (char const *filename)
 
 		if (is_xml)
 			xml = buffer;
-		else
+		else {
 			xml = itex2MML_parse (buffer, size);
+			size = 0;
+		}
 
-		document = lsm_dom_document_new_from_memory (xml);
+		document = lsm_dom_document_new_from_memory (xml, size, NULL);
+		lsm_dom_document_set_path (document, filename);
 
 		view = lsm_dom_document_create_view (document);
 
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/lsmdomdocument.c b/src/lsmdomdocument.c
index 8dd9879..c8062f1 100644
--- a/src/lsmdomdocument.c
+++ b/src/lsmdomdocument.c
@@ -21,8 +21,13 @@
 
 #include <lsmdomdocument.h>
 #include <lsmdomelement.h>
+#include <lsmstr.h>
 #include <lsmdebug.h>
 #include <lsmdomtext.h>
+#include <gio/gio.h>
+#include <string.h>
+
+static GObjectClass *parent_class;
 
 /* LsmDomNode implementation */
 
@@ -185,6 +190,76 @@ lsm_dom_document_register_element (LsmDomDocument *self, LsmDomElement *element,
 	}
 }
 
+const char *
+lsm_dom_document_get_url (LsmDomDocument *self)
+{
+	g_return_val_if_fail (LSM_IS_DOM_DOCUMENT (self), NULL);
+
+	return self->url;
+}
+
+void
+lsm_dom_document_set_path (LsmDomDocument *self, const char *path)
+{
+	g_return_if_fail (LSM_IS_DOM_DOCUMENT (self));
+
+	g_free (self->url);
+
+	if (path == NULL) {
+		self->url = NULL;
+		return;
+	}
+
+	self->url = lsm_str_to_uri (path);
+}
+
+void
+lsm_dom_document_set_url (LsmDomDocument *self, const char *url)
+{
+	g_return_if_fail (LSM_IS_DOM_DOCUMENT (self));
+	g_return_if_fail (url == NULL || lsm_str_is_uri (url));
+
+	g_free (self->url);
+	self->url = g_strdup (url);
+}
+
+void *
+lsm_dom_document_get_href_data (LsmDomDocument *self, const char *href, gsize *size)
+{
+	GFile *file;
+	char *data = NULL;
+
+	g_return_val_if_fail (LSM_IS_DOM_DOCUMENT (self), NULL);
+	g_return_val_if_fail (href != NULL, NULL);
+
+	if (strncmp (href, "data:", 5) == 0) {
+		while (*href != '\0' && *href != ',')
+			href++;
+		return g_base64_decode (href, size);
+	}
+
+	file = g_file_new_for_uri (href);
+
+	if (!g_file_load_contents (file, NULL, &data, size, NULL, NULL) && self->url != NULL) {
+		GFile *document_file;
+		GFile *parent_file;
+
+		g_object_unref (file);
+
+		document_file = g_file_new_for_uri (self->url);
+		parent_file = g_file_get_parent (document_file);
+		file = g_file_resolve_relative_path (parent_file, href);
+		g_object_unref (document_file);
+		g_object_unref (parent_file);
+
+		g_file_load_contents (file, NULL, &data, size, NULL, NULL);
+	}
+
+	g_object_unref (file);
+
+	return data;
+}
+
 static void
 lsm_dom_document_init (LsmDomDocument *document)
 {
@@ -205,6 +280,10 @@ lsm_dom_document_finalize (GObject *object)
 
 	g_hash_table_unref (document->elements);
 	g_hash_table_unref (document->ids);
+
+	g_free (document->url);
+
+	parent_class->finalize (object);
 }
 
 /* LsmDomDocument class */
@@ -215,6 +294,8 @@ lsm_dom_document_class_init (LsmDomDocumentClass *klass)
 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 	LsmDomNodeClass *node_class = LSM_DOM_NODE_CLASS (klass);
 
+	parent_class = g_type_class_peek_parent (klass);
+
 	object_class->finalize = lsm_dom_document_finalize;
 
 	node_class->get_node_name = lsm_dom_document_get_node_name;
diff --git a/src/lsmdomdocument.h b/src/lsmdomdocument.h
index 3321d36..78697ec 100644
--- a/src/lsmdomdocument.h
+++ b/src/lsmdomdocument.h
@@ -45,8 +45,10 @@ typedef struct _LsmDomDocumentClass LsmDomDocumentClass;
 struct _LsmDomDocument {
 	LsmDomNode node;
 
-	GHashTable *		ids;
-	GHashTable *		elements;
+	GHashTable *	ids;
+	GHashTable *	elements;
+
+	char *		url;
 
 	/* Not really a document property, but that simplifies things greatly */
 	double resolution_ppi;
@@ -82,6 +84,12 @@ void 		lsm_dom_document_set_viewport_px 	(LsmDomDocument *self, const LsmBox *vi
 LsmBox 		lsm_dom_document_get_viewport 		(LsmDomDocument *self);
 LsmBox 		lsm_dom_document_get_viewport_px 	(LsmDomDocument *self);
 
+const char * 	lsm_dom_document_get_url 		(LsmDomDocument *self);
+void		lsm_dom_document_set_url		(LsmDomDocument *self, const char *url);
+void 		lsm_dom_document_set_path 		(LsmDomDocument *self, const char *path);
+
+void * 		lsm_dom_document_get_href_data 		(LsmDomDocument *self, const char *href, gsize *size);
+
 G_END_DECLS
 
 #endif
diff --git a/src/lsmdomnode.h b/src/lsmdomnode.h
index 86cae17..8305525 100644
--- a/src/lsmdomnode.h
+++ b/src/lsmdomnode.h
@@ -89,30 +89,30 @@ struct _LsmDomNodeClass {
 
 GType lsm_dom_node_get_type (void);
 
-const char* 		lsm_dom_node_get_node_name 	(LsmDomNode* self);
-const char* 		lsm_dom_node_get_node_value 	(LsmDomNode* self);
-void 			lsm_dom_node_set_node_value 	(LsmDomNode* self, const char* new_value);
-LsmDomNodeType 		lsm_dom_node_get_node_type 	(LsmDomNode* self);
-LsmDomNode* 		lsm_dom_node_get_parent_node 	(LsmDomNode* self);
+const char* 		lsm_dom_node_get_node_name 		(LsmDomNode* self);
+const char* 		lsm_dom_node_get_node_value 		(LsmDomNode* self);
+void 			lsm_dom_node_set_node_value 		(LsmDomNode* self, const char* new_value);
+LsmDomNodeType 		lsm_dom_node_get_node_type 		(LsmDomNode* self);
+LsmDomNode* 		lsm_dom_node_get_parent_node 		(LsmDomNode* self);
 #if 0
 LsmDomNodeList* 		lsm_dom_node_get_child_nodes 	(LsmDomNode* self);
 #endif
-LsmDomNode* 		lsm_dom_node_get_first_child 	(LsmDomNode* self);
-LsmDomNode* 		lsm_dom_node_get_last_child 	(LsmDomNode* self);
+LsmDomNode* 		lsm_dom_node_get_first_child 		(LsmDomNode* self);
+LsmDomNode* 		lsm_dom_node_get_last_child 		(LsmDomNode* self);
 LsmDomNode* 		lsm_dom_node_get_previous_sibling 	(LsmDomNode* self);
-LsmDomNode* 		lsm_dom_node_get_next_sibling 	(LsmDomNode* self);
+LsmDomNode* 		lsm_dom_node_get_next_sibling 		(LsmDomNode* self);
 #if 0
 LsmDomNamedNodeMap* 	lsm_dom_node_get_attributes 	(LsmDomNode* self);
 #endif
 LsmDomNode* 		lsm_dom_node_insert_before		(LsmDomNode* self, LsmDomNode* new_child, LsmDomNode* ref_child);
-LsmDomNode* 		lsm_dom_node_replace_child 	(LsmDomNode* self, LsmDomNode* new_child, LsmDomNode* old_child);
+LsmDomNode* 		lsm_dom_node_replace_child 		(LsmDomNode* self, LsmDomNode* new_child, LsmDomNode* old_child);
 LsmDomNode* 		lsm_dom_node_append_child 		(LsmDomNode* self, LsmDomNode* new_child);
 LsmDomNode* 		lsm_dom_node_remove_child 		(LsmDomNode* self, LsmDomNode* old_child);
-gboolean 		lsm_dom_node_has_child_nodes 	(LsmDomNode* self);
+gboolean 		lsm_dom_node_has_child_nodes 		(LsmDomNode* self);
 
-void 			lsm_dom_node_changed 		(LsmDomNode *self);
+void 			lsm_dom_node_changed 			(LsmDomNode *self);
 
-LsmDomDocument* 		lsm_dom_node_get_owner_document 	(LsmDomNode* self);
+LsmDomDocument*		lsm_dom_node_get_owner_document 	(LsmDomNode* self);
 
 void 			lsm_dom_node_dump 			(LsmDomNode *self);
 
diff --git a/src/lsmdomparser.c b/src/lsmdomparser.c
index 8d3bbef..66024f4 100644
--- a/src/lsmdomparser.c
+++ b/src/lsmdomparser.c
@@ -24,8 +24,11 @@
 #include <lsmmathmlpresentationtoken.h>
 #include <lsmmathmlentitydictionary.h>
 #include <lsmsvgtextelement.h>
+#include <lsmstr.h>
 #include <libxml/parser.h>
+#include <gio/gio.h>
 #include <string.h>
+#include <../itex2mml/itex2MML.h>
 
 typedef enum {
 	STATE
@@ -256,37 +259,134 @@ static xmlSAXHandler sax_handler = {
 	.entityDecl = lsm_dom_parser_declare_entity
 };
 
-LsmDomDocument *
-lsm_dom_document_new_from_file (const char *filename)
+static GQuark
+lsm_dom_document_error_quark (void)
+{
+	static GQuark q = 0;
+
+        if (q == 0) {
+                q = g_quark_from_static_string ("mrp-error-quark");
+        }
+
+        return q;
+}
+
+#define LSM_DOM_DOCUMENT_ERROR lsm_dom_document_error_quark ()
+
+typedef enum {
+	LSM_DOM_DOCUMENT_ERROR_INVALID_XML
+} LsmDomDocumentError;
+
+static void
+_dummy_error (const char *msg)
+{
+}
+
+static LsmDomDocument *
+lsm_dom_document_new_from_contents (const char *contents, gsize size, GError **error)
 {
 	static LsmDomSaxParserState state;
+	char *mime;
+	char *xml;
+
+	state.document = NULL;
 
-	if (xmlSAXUserParseFile (&sax_handler, &state, filename) < 0) {
+	mime = g_content_type_guess (NULL, (guchar *) contents, size, NULL);
+	lsm_debug ("[LsmDomDocument::new_from_contents] mime = '%s'", mime);
+	if (g_strcmp0 (mime, "image/svg+xml") == 0 ||
+	    g_strcmp0 (mime, "text/mathml") == 0 ||
+	    g_strcmp0 (mime, "application/xml") == 0) {
+		xml = (char *) contents;
+	} else {
+		itex2MML_error = _dummy_error;
+
+		xml = itex2MML_parse (contents, size);
+		size = strlen (contents);
+	}
+
+	if (xmlSAXUserParseMemory (&sax_handler, &state, xml, size) < 0) {
 		if (state.document !=  NULL)
 			g_object_unref (state.document);
-		g_warning ("[LsmDomParser::from_file] invalid document");
-		return NULL;
+		state.document = NULL;
+
+		lsm_debug ("[LsmDomParser::from_memory] invalid document");
+
+		g_set_error (error,
+			     LSM_DOM_DOCUMENT_ERROR,
+			     LSM_DOM_DOCUMENT_ERROR_INVALID_XML,
+			     "Invalid document.");
 	}
 
-	return LSM_DOM_DOCUMENT (state.document);
+	if (xml != contents)
+		itex2MML_free_string (xml);
+
+	return state.document;
 }
 
 LsmDomDocument *
-lsm_dom_document_new_from_memory (const char *buffer)
+lsm_dom_document_new_from_memory (const char *buffer, gsize size, GError **error)
 {
-	static LsmDomSaxParserState state;
+	g_return_val_if_fail (buffer != NULL, NULL);
 
-	if (buffer == NULL)
-		return NULL;
+	if (size < 1)
+		size = strlen (buffer);
 
-	state.document = NULL;
+	return lsm_dom_document_new_from_contents (buffer, size, error);
+}
 
-	if (xmlSAXUserParseMemory (&sax_handler, &state, buffer, strlen (buffer)) < 0) {
-		if (state.document !=  NULL)
-			g_object_unref (state.document);
-		g_warning ("[LsmDomParser::from_memory] invalid document");
+static LsmDomDocument *
+lsm_dom_document_new_from_file (GFile *file, GError **error)
+{
+	LsmDomDocument *document;
+	gsize size = 0;
+	char *contents = NULL;
+
+	if (!g_file_load_contents (file, NULL, &contents, &size, NULL, error))
 		return NULL;
-	}
 
-	return LSM_DOM_DOCUMENT (state.document);
+	document = lsm_dom_document_new_from_contents (contents, size, error);
+
+	g_free (contents);
+
+	return document;
+}
+
+LsmDomDocument *
+lsm_dom_document_new_from_path (const char *path, GError **error)
+{
+	LsmDomDocument *document;
+	GFile *file;
+
+	g_return_val_if_fail (path != NULL, NULL);
+
+	file = g_file_new_for_path (path);
+
+	document = lsm_dom_document_new_from_file (file, error);
+
+	g_object_unref (file);
+
+	if (document != NULL)
+		lsm_dom_document_set_path (document, path);
+
+	return document;
+}
+
+LsmDomDocument *
+lsm_dom_document_new_from_url (const char *url, GError **error)
+{
+	LsmDomDocument *document;
+	GFile *file;
+
+	g_return_val_if_fail (url != NULL, NULL);
+
+	file = g_file_new_for_uri (url);
+
+	document = lsm_dom_document_new_from_file (file, error);
+
+	g_object_unref (file);
+
+	if (document != NULL)
+		lsm_dom_document_set_url (document, url);
+
+	return document;
 }
diff --git a/src/lsmdomparser.h b/src/lsmdomparser.h
index 1af26b8..51e6a78 100644
--- a/src/lsmdomparser.h
+++ b/src/lsmdomparser.h
@@ -26,8 +26,13 @@
 
 G_BEGIN_DECLS
 
-LsmDomDocument * 	lsm_dom_document_new_from_file 	(const char *filename);
-LsmDomDocument * 	lsm_dom_document_new_from_memory 	(const char *buffer);
+typedef enum {
+	LSM_DOM_DOCUMENT_ERROR_INVALID_XML
+} LsmDomDocumentError;
+
+LsmDomDocument * 	lsm_dom_document_new_from_memory 	(const char *buffer, gsize size, GError *error);
+LsmDomDocument * 	lsm_dom_document_new_from_path 		(const char *path, GError *error);
+LsmDomDocument * 	lsm_dom_document_new_from_url 		(const char *url, GError *error);
 
 G_END_DECLS
 
diff --git a/src/lsmdomview.c b/src/lsmdomview.c
index 1b7cbb1..0f9c4c8 100644
--- a/src/lsmdomview.c
+++ b/src/lsmdomview.c
@@ -90,6 +90,9 @@ lsm_dom_view_render (LsmDomView *view, double x, double y)
 		view_class->render (view);
 
 	cairo_restore (view->cairo);
+
+	lsm_debug ("[LsmDomView::render] cairo status = %s",
+		   cairo_status_to_string (cairo_status (view->cairo)));
 }
 
 void
diff --git a/src/lsmmathmldocument.c b/src/lsmmathmldocument.c
index 83d7d3a..2532456 100644
--- a/src/lsmmathmldocument.c
+++ b/src/lsmmathmldocument.c
@@ -168,6 +168,7 @@ lsm_mathml_document_class_init (LsmMathmlDocumentClass *m_document_class)
 
 G_DEFINE_TYPE (LsmMathmlDocument, lsm_mathml_document, LSM_TYPE_DOM_DOCUMENT)
 
+#if 0
 static void
 _dummy_error (const char *msg)
 {
@@ -194,3 +195,4 @@ lsm_mathml_document_new_from_itex (const char *itex)
 
 	return document;
 }
+#endif
diff --git a/src/lsmmathmldocument.h b/src/lsmmathmldocument.h
index 59a2046..e8c47e9 100644
--- a/src/lsmmathmldocument.h
+++ b/src/lsmmathmldocument.h
@@ -50,7 +50,9 @@ GType lsm_mathml_document_get_type (void);
 LsmMathmlDocument *	lsm_mathml_document_new 		(void);
 LsmMathmlMathElement * 	lsm_mathml_document_get_root_element 	(const LsmMathmlDocument *document);
 
+#if 0
 LsmMathmlDocument * 	lsm_mathml_document_new_from_itex	(const char *itex);
+#endif
 
 G_END_DECLS
 
diff --git a/src/lsmmathmlmathelement.c b/src/lsmmathmlmathelement.c
index 2ae7673..e494c65 100644
--- a/src/lsmmathmlmathelement.c
+++ b/src/lsmmathmlmathelement.c
@@ -181,6 +181,8 @@ lsm_mathml_math_element_finalize (GObject *object)
 	LsmMathmlMathElement *math_element = LSM_MATHML_MATH_ELEMENT (object);
 
 	lsm_mathml_style_free (math_element->default_style);
+
+	parent_class->finalize (object);
 }
 
 /* LsmMathmlMathElement class */
diff --git a/src/lsmmathmltableelement.c b/src/lsmmathmltableelement.c
index c4fa903..31c869a 100644
--- a/src/lsmmathmltableelement.c
+++ b/src/lsmmathmltableelement.c
@@ -457,6 +457,8 @@ lsm_mathml_table_element_finalize (GObject *object)
 	table->widths = NULL;
 	table->heights = NULL;
 	table->depths = NULL;
+
+	parent_class->finalize (object);
 }
 
 /* LsmMathmlTableElement class */
diff --git a/src/lsmsvgattributes.h b/src/lsmsvgattributes.h
index 4db88ad..806ac81 100644
--- a/src/lsmsvgattributes.h
+++ b/src/lsmsvgattributes.h
@@ -23,135 +23,70 @@
 #ifndef LSM_SVG_ATTRIBUTES_H
 #define LSM_SVG_ATTRIBUTES_H
 
-#include <lsmdomattributes.h>
+#include <lsmattributes.h>
 #include <lsmdomview.h>
 #include <lsmsvg.h>
 #include <lsmsvgenums.h>
+#include <lsmsvgtraits.h>
 #include <lsmsvglength.h>
 #include <lsmsvgmatrix.h>
 
 G_BEGIN_DECLS
 
 typedef struct {
-	LsmDomAttribute attr;
+	LsmAttribute base;
 	double value;
 } 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;
+	LsmAttribute base;
 	LsmSvgDashArray *value;
 } LsmSvgDashArrayAttribute;
 
 typedef struct {
-	LsmSvgPaintType type;
-	char *uri;
-	LsmSvgColor color;
-} LsmSvgPaint;
-
-typedef struct {
-	LsmDomAttribute attr;
+	LsmAttribute base;
 	LsmSvgLength length;
-	double value;
 } LsmSvgLengthAttribute;
 
 typedef struct {
-	LsmDomAttribute attr;
-	LsmSvgAnimatedLength length;
-	double value;
-} LsmSvgAnimatedLengthAttribute;
-
-typedef struct {
-	LsmDomAttribute attr;
+	LsmAttribute base;
 	LsmSvgPaint paint;
 } LsmSvgPaintAttribute;
 
 typedef struct {
-	LsmDomAttribute attr;
+	LsmAttribute base;
 	char *value;
 } LsmSvgStringAttribute;
 
 typedef struct {
-	LsmDomAttribute attr;
+	LsmAttribute base;
 	LsmSvgColor value;
 } LsmSvgColorAttribute;
 
 typedef struct {
-	LsmDomAttribute attr;
+	LsmAttribute base;
 	LsmBox value;
 } LsmSvgViewboxAttribute;
 
 typedef struct {
-	LsmDomAttribute attr;
+	LsmAttribute base;
 	LsmSvgMatrix matrix;
 } LsmSvgTransformAttribute;
 
 typedef struct {
-	gboolean defer;
-	LsmSvgAlign align;
-	LsmSvgMeetOrSlice meet_or_slice;
-} LsmSvgPreserveAspectRatio;
-
-typedef struct {
-	LsmDomAttribute attr;
+	LsmAttribute base;
 	LsmSvgPreserveAspectRatio value;
 } LsmSvgPreserveAspectRatioAttribute;
 
-/* Properties */
-
-void 		lsm_svg_double_attribute_parse 		(LsmSvgDoubleAttribute *attribute,
-							 double *double_value);
-void		lsm_svg_length_attribute_parse 		(LsmSvgLengthAttribute *attribute,
-							 LsmSvgLength *default_value);
-void 		lsm_svg_animated_length_attribute_parse (LsmSvgAnimatedLengthAttribute *attribute,
-							 LsmSvgLength *default_value);
-
-void 		lsm_svg_dash_array_attribute_finalize 	(void *abstract);
-
-void		lsm_svg_dash_array_attribute_parse	(LsmSvgDashArrayAttribute *attribute,
-							 LsmSvgDashArray **default_value);
-
-void 		lsm_svg_fill_rule_attribute_parse 	(LsmDomEnumAttribute *attribute,
-							 unsigned int *style_value);
-void 		lsm_svg_line_join_attribute_parse 	(LsmDomEnumAttribute *attribute,
-							 unsigned int *style_value);
-void 		lsm_svg_line_cap_attribute_parse 	(LsmDomEnumAttribute *attribute,
-							 unsigned int *style_value);
-void 		lsm_svg_pattern_units_attribute_parse 	(LsmDomEnumAttribute *attribute,
-							 unsigned int *style_value);
-void 		lsm_svg_spread_method_attribute_parse 	(LsmDomEnumAttribute *attribute,
-							 unsigned int *style_value);
-void 		lsm_svg_paint_attribute_finalize 	(void *abstract);
-void 		lsm_svg_paint_attribute_parse 		(LsmSvgPaintAttribute *attribute,
-							 LsmSvgPaint *default_value,
-							 const LsmSvgColor *current_color);
-void 		lsm_svg_color_attribute_parse 		(LsmSvgColorAttribute *attribute,
-							 LsmSvgColor *default_value,
-							 const LsmSvgColor *current_color);
-
-/* Attributes */
-
-void		lsm_svg_viewbox_attribute_parse			(LsmSvgViewboxAttribute *attribute);
-void		lsm_svg_transform_attribute_parse		(LsmSvgTransformAttribute *attribute);
-void 		lsm_svg_preserve_aspect_ratio_attribute_parse 	(LsmSvgPreserveAspectRatioAttribute *attribute);
+typedef struct {
+	LsmAttribute base;
+	LsmSvgSpreadMethod value;
+} LsmSvgSpreadMethodAtttribute;
+
+typedef struct {
+	LsmAttribute base;
+	LsmSvgPatternUnits value;
+} LsmSvgPatternUnitsAttribute;
 
 G_END_DECLS
 
diff --git a/src/lsmsvgcircleelement.c b/src/lsmsvgcircleelement.c
index 5371a7d..8407424 100644
--- a/src/lsmsvgcircleelement.c
+++ b/src/lsmsvgcircleelement.c
@@ -35,40 +35,19 @@ lsm_svg_circle_element_get_node_name (LsmDomNode *node)
 
 /* LsmSvgElement implementation */
 
-static void
-lsm_svg_circle_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
-{
-	LsmSvgCircleElement *circle = LSM_SVG_CIRCLE_ELEMENT (self);
-	LsmSvgLength length;
-
-	length.value_unit = 0.0;
-	length.type = LSM_SVG_LENGTH_TYPE_NUMBER;
-	lsm_svg_animated_length_attribute_parse (&circle->cx, &length);
-
-	length.value_unit = 0.0;
-	length.type = LSM_SVG_LENGTH_TYPE_NUMBER;
-	lsm_svg_animated_length_attribute_parse (&circle->cy, &length);
-
-	length.value_unit = 0.0;
-	length.type = LSM_SVG_LENGTH_TYPE_NUMBER;
-	lsm_svg_animated_length_attribute_parse (&circle->r, &length);
-
-	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
-}
-
 /* LsmSvgGraphic implementation */
 
 static void
-lsm_svg_circle_element_graphic_render (LsmSvgElement *self, LsmSvgView *view)
+lsm_svg_circle_element_render (LsmSvgElement *self, LsmSvgView *view)
 {
 	LsmSvgCircleElement *circle = LSM_SVG_CIRCLE_ELEMENT (self);
 	double cx, cy, r;
 
-	cx = lsm_svg_view_normalize_length (view, &circle->cx.length.base, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
-	cy = lsm_svg_view_normalize_length (view, &circle->cy.length.base, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
-	r  = lsm_svg_view_normalize_length (view, &circle->r.length.base,  LSM_SVG_LENGTH_DIRECTION_DIAGONAL);
+	cx = lsm_svg_view_normalize_length (view, &circle->cx.length, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
+	cy = lsm_svg_view_normalize_length (view, &circle->cy.length, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
+	r  = lsm_svg_view_normalize_length (view, &circle->r.length,  LSM_SVG_LENGTH_DIRECTION_DIAGONAL);
 
-	lsm_debug ("[LsmSvgCircleElement::graphic_render] cx = %g, cy = %g, r = %g",
+	lsm_debug ("[LsmSvgCircleElement::render] cx = %g, cy = %g, r = %g",
 		   cx, cy, r);
 
 	lsm_svg_view_show_circle (view, cx, cy, r);
@@ -82,25 +61,51 @@ lsm_svg_circle_element_new (void)
 	return g_object_new (LSM_TYPE_SVG_CIRCLE_ELEMENT, NULL);
 }
 
+static const LsmSvgLength length_default = 	 { .value_unit =   0.0, .type = LSM_SVG_LENGTH_TYPE_PX};
+
 static void
 lsm_svg_circle_element_init (LsmSvgCircleElement *self)
 {
+	self->cx.length = length_default;
+	self->cy.length = length_default;
+	self->r.length = length_default;
 }
 
 static void
 lsm_svg_circle_element_finalize (GObject *object)
 {
+	parent_class->finalize (object);
 }
 
 /* LsmSvgCircleElement class */
 
+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)
 {
 	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);
 
 	parent_class = g_type_class_peek_parent (s_rect_class);
 
@@ -108,18 +113,12 @@ 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_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->render = lsm_svg_circle_element_render;
+	s_element_class->attribute_manager = lsm_attribute_manager_duplicate (s_element_class->attribute_manager);
 
-	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_attribute_manager_add_attributes (s_element_class->attribute_manager,
+					      G_N_ELEMENTS (lsm_svg_circle_element_attribute_infos),
+					      lsm_svg_circle_element_attribute_infos);
 }
 
-G_DEFINE_TYPE (LsmSvgCircleElement, lsm_svg_circle_element, LSM_TYPE_SVG_GRAPHIC)
+G_DEFINE_TYPE (LsmSvgCircleElement, lsm_svg_circle_element, LSM_TYPE_SVG_ELEMENT)
diff --git a/src/lsmsvgcircleelement.h b/src/lsmsvgcircleelement.h
index 83541b7..b8696b8 100644
--- a/src/lsmsvgcircleelement.h
+++ b/src/lsmsvgcircleelement.h
@@ -23,7 +23,7 @@
 #define LSM_SVG_CIRCLE_ELEMENT_H
 
 #include <lsmsvg.h>
-#include <lsmsvggraphic.h>
+#include <lsmsvgelement.h>
 
 G_BEGIN_DECLS
 
@@ -37,15 +37,15 @@ G_BEGIN_DECLS
 typedef struct _LsmSvgCircleElementClass LsmSvgCircleElementClass;
 
 struct _LsmSvgCircleElement {
-	LsmSvgGraphic graphic;
+	LsmSvgElement element;
 
-	LsmSvgAnimatedLengthAttribute	cx;
-	LsmSvgAnimatedLengthAttribute	cy;
-	LsmSvgAnimatedLengthAttribute	r;
+	LsmSvgLengthAttribute	cx;
+	LsmSvgLengthAttribute	cy;
+	LsmSvgLengthAttribute	r;
 };
 
 struct _LsmSvgCircleElementClass {
-	LsmSvgGraphicClass  parent_class;
+	LsmSvgElementClass  element_class;
 };
 
 GType lsm_svg_circle_element_get_type (void);
diff --git a/src/lsmsvgclippathelement.c b/src/lsmsvgclippathelement.c
index 0bbdcdf..9409733 100644
--- a/src/lsmsvgclippathelement.c
+++ b/src/lsmsvgclippathelement.c
@@ -37,22 +37,21 @@ _clip_path_element_get_node_name (LsmDomNode *node)
 /* LsmSvgElement implementation */
 
 static void
-_clip_path_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
-{
-	LsmSvgClipPathElement *pattern = LSM_SVG_CLIP_PATH_ELEMENT (self);
-	LsmSvgPatternUnits units;
-
-	units = LSM_SVG_PATTERN_UNITS_USER_SPACE_ON_USE;
-	lsm_svg_pattern_units_attribute_parse (&pattern->units, &units);
-
-	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
-}
-
-static void
-_clip_path_element_render_clip (LsmSvgElement *self, LsmSvgView *view)
+lsm_svg_clip_path_element_render (LsmSvgElement *self, LsmSvgView *view)
 {
 	LsmSvgClipPathElement *clip = LSM_SVG_CLIP_PATH_ELEMENT (self);
 	gboolean is_object_bounding_box;
+	LsmSvgStyle *style;
+
+	if (!clip->enable_rendering) {
+		lsm_debug ("[LsmSvgClipPathElement::render] Direct rendering not allowed");
+		return;
+	} else {
+		clip->enable_rendering = FALSE;
+	}
+
+	style = lsm_svg_style_new_inherited (NULL, &self->property_bag);
+	lsm_svg_view_push_style (view, style);
 
 	is_object_bounding_box = (clip->units.value == LSM_SVG_PATTERN_UNITS_OBJECT_BOUNDING_BOX);
 
@@ -73,6 +72,15 @@ _clip_path_element_render_clip (LsmSvgElement *self, LsmSvgView *view)
 		lsm_svg_view_pop_matrix (view);
 		lsm_svg_view_pop_viewbox (view);
 	}
+
+	lsm_svg_view_pop_style (view);
+	lsm_svg_style_free (style);
+}
+
+static void
+lsm_svg_clip_path_element_enable_rendering (LsmSvgElement *element)
+{
+	LSM_SVG_CLIP_PATH_ELEMENT (element)->enable_rendering  = TRUE;
 }
 
 LsmDomNode *
@@ -81,22 +89,26 @@ lsm_svg_clip_path_element_new (void)
 	return g_object_new (LSM_TYPE_SVG_CLIP_PATH_ELEMENT, NULL);
 }
 
+static const LsmSvgPatternUnits units_default = LSM_SVG_PATTERN_UNITS_USER_SPACE_ON_USE;
+
 static void
 lsm_svg_clip_path_element_init (LsmSvgClipPathElement *self)
 {
-	/* Hack - Force the creation of the attribute bags,
-	   making sure the properties will be inherited from the
-	   pattern element ancestor, not the referencing one. */
-
-	lsm_dom_element_set_attribute (LSM_DOM_ELEMENT (self), "fill", NULL);
-	lsm_dom_element_set_attribute (LSM_DOM_ELEMENT (self), "stroke", NULL);
-	lsm_dom_element_set_attribute (LSM_DOM_ELEMENT (self), "transform", NULL);
-	lsm_dom_element_set_attribute (LSM_DOM_ELEMENT (self), "font-family", NULL);
-	lsm_dom_element_set_attribute (LSM_DOM_ELEMENT (self), "stop-color", NULL);
+	self->enable_rendering = FALSE;
+	self->units.value = units_default;
 }
 
 /* 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),
+		.trait_default = &units_default
+	}
+};
+
 static void
 lsm_svg_clip_path_element_class_init (LsmSvgClipPathElementClass *klass)
 {
@@ -107,14 +119,14 @@ 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->render_clip = _clip_path_element_render_clip;
-	s_element_class->render = NULL;
+	s_element_class->render = lsm_svg_clip_path_element_render;
+	s_element_class->enable_rendering = lsm_svg_clip_path_element_enable_rendering;
 
-	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_dom_attribute_map_add_attribute (s_element_class->attributes, "clipPathUnits",
-					     offsetof (LsmSvgClipPathElement, units));
+	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);
 }
 
-G_DEFINE_TYPE (LsmSvgClipPathElement, lsm_svg_clip_path_element, LSM_TYPE_SVG_GRAPHIC)
+G_DEFINE_TYPE (LsmSvgClipPathElement, lsm_svg_clip_path_element, LSM_TYPE_SVG_ELEMENT)
diff --git a/src/lsmsvgclippathelement.h b/src/lsmsvgclippathelement.h
index 9959a1e..5794396 100644
--- a/src/lsmsvgclippathelement.h
+++ b/src/lsmsvgclippathelement.h
@@ -23,7 +23,7 @@
 #define LSM_SVG_CLIP_PATH_ELEMENT_H
 
 #include <lsmsvg.h>
-#include <lsmsvggraphic.h>
+#include <lsmsvgelement.h>
 
 G_BEGIN_DECLS
 
@@ -37,13 +37,15 @@ G_BEGIN_DECLS
 typedef struct _LsmSvgClipPathElementClass LsmSvgClipPathElementClass;
 
 struct _LsmSvgClipPathElement {
-	LsmSvgGraphic graphic;
+	LsmSvgElement element;
 
-	LsmDomEnumAttribute 		units;
+	LsmSvgPatternUnitsAttribute units;
+
+	gboolean enable_rendering;
 };
 
 struct _LsmSvgClipPathElementClass {
-	LsmSvgGraphicClass  parent_class;
+	LsmSvgElementClass  element_class;
 };
 
 GType lsm_svg_clip_path_element_get_type (void);
diff --git a/src/lsmsvgdefselement.c b/src/lsmsvgdefselement.c
index 957816e..fbde796 100644
--- a/src/lsmsvgdefselement.c
+++ b/src/lsmsvgdefselement.c
@@ -65,4 +65,4 @@ lsm_svg_defs_element_class_init (LsmSvgDefsElementClass *s_g_class)
 	s_element_class->render = NULL;
 }
 
-G_DEFINE_TYPE (LsmSvgDefsElement, lsm_svg_defs_element, LSM_TYPE_SVG_GRAPHIC)
+G_DEFINE_TYPE (LsmSvgDefsElement, lsm_svg_defs_element, LSM_TYPE_SVG_ELEMENT)
diff --git a/src/lsmsvgdefselement.h b/src/lsmsvgdefselement.h
index 21c84fd..3c0c3f3 100644
--- a/src/lsmsvgdefselement.h
+++ b/src/lsmsvgdefselement.h
@@ -23,7 +23,7 @@
 #define LSM_SVG_DEFS_ELEMENT_H
 
 #include <lsmsvg.h>
-#include <lsmsvggraphic.h>
+#include <lsmsvgelement.h>
 
 G_BEGIN_DECLS
 
@@ -37,11 +37,11 @@ G_BEGIN_DECLS
 typedef struct _LsmSvgDefsElementClass LsmSvgDefsElementClass;
 
 struct _LsmSvgDefsElement {
-	LsmSvgGraphic graphic;
+	LsmSvgElement element;
 };
 
 struct _LsmSvgDefsElementClass {
-	LsmSvgGraphicClass  parent_class;
+	LsmSvgElementClass  element_class;
 };
 
 GType lsm_svg_defs_element_get_type (void);
diff --git a/src/lsmsvgdocument.h b/src/lsmsvgdocument.h
index 17de642..ba173a9 100644
--- a/src/lsmsvgdocument.h
+++ b/src/lsmsvgdocument.h
@@ -46,7 +46,7 @@ struct _LsmSvgDocumentClass {
 
 GType lsm_svg_document_get_type (void);
 
-LsmSvgDocument *		lsm_svg_document_new 		(void);
+LsmSvgDocument *	lsm_svg_document_new 			(void);
 LsmSvgSvgElement * 	lsm_svg_document_get_root_element 	(const LsmSvgDocument *document);
 
 G_END_DECLS
diff --git a/src/lsmsvgelement.c b/src/lsmsvgelement.c
index 26299b2..8c5ab53 100644
--- a/src/lsmsvgelement.c
+++ b/src/lsmsvgelement.c
@@ -20,8 +20,14 @@
  */
 
 #include <lsmdebug.h>
+#include <lsmattributes.h>
+#include <lsmproperties.h>
 #include <lsmdomdocument.h>
 #include <lsmsvgelement.h>
+#include <lsmsvgpatternelement.h>
+#include <lsmsvggradientelement.h>
+#include <lsmsvgclippathelement.h>
+#include <lsmsvgmaskelement.h>
 #include <lsmsvgview.h>
 #include <string.h>
 
@@ -38,13 +44,6 @@ lsm_svg_element_can_append_child (LsmDomNode *self, LsmDomNode *child)
 static gboolean
 lsm_svg_element_child_changed (LsmDomNode *parent, LsmDomNode *child)
 {
-	LsmSvgElement *element = LSM_SVG_ELEMENT (parent);
-
-	if (element->need_children_update)
-		return FALSE;
-
-	element->need_children_update = TRUE;
-
 	return TRUE;
 }
 
@@ -53,68 +52,40 @@ lsm_svg_element_child_changed (LsmDomNode *parent, LsmDomNode *child)
 static void
 lsm_svg_element_set_attribute (LsmDomElement *self, const char* name, const char *value)
 {
-	LsmSvgElementClass *s_element_class = LSM_SVG_ELEMENT_GET_CLASS(self);
+	LsmSvgElementClass *s_element_class = LSM_SVG_ELEMENT_GET_CLASS (self);
+	LsmSvgElement *s_element = LSM_SVG_ELEMENT (self);
 
 	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);
+	/* 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);
+
+	if (g_strcmp0 (name, "id") == 0) {
+		LsmDomDocument *document;
+
+		document = lsm_dom_node_get_owner_document (LSM_DOM_NODE (self));
+		if (document != NULL)
+			lsm_dom_document_register_element (document, LSM_DOM_ELEMENT (self), 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;
 
-	return lsm_dom_attribute_map_get_attribute (s_element_class->attributes, self, name);
-}
-
-/* LsmSvgElement implementation */
-
-void
-lsm_svg_element_update (LsmSvgElement *self, const LsmSvgStyle *parent_style)
-{
-	LsmSvgElementClass *element_class;
-	LsmSvgStyle *style;
-	LsmDomDocument *document;
-	LsmDomNode *node;
-
-	g_return_if_fail (LSM_IS_SVG_ELEMENT (self));
-	g_return_if_fail (parent_style != NULL);
-
-	if (!self->need_update && !self->need_children_update) {
-		lsm_debug ("[Element::update] %s already up to date",
-			    lsm_dom_node_get_node_name (LSM_DOM_NODE (self)));
-		return;
-	}
-
-	document = lsm_dom_node_get_owner_document (LSM_DOM_NODE (self));
-	if (document != NULL)
-		lsm_dom_document_register_element (document, LSM_DOM_ELEMENT (self), self->id.value);
-
-	element_class = LSM_SVG_ELEMENT_GET_CLASS (self);
-
-	style = lsm_svg_style_duplicate (parent_style);
-	g_return_if_fail (style != NULL);
-
-	lsm_debug ("[Element::update] update %s",
-		    lsm_dom_node_get_node_name (LSM_DOM_NODE (self)));
+	/* TODO Avoid double hash table lookup */
+	value = lsm_attribute_manager_get_attribute (s_element_class->attribute_manager,
+						     self, name);
+	if (value != NULL)
+		return value;
 
-	if (element_class->update != NULL)
-		element_class->update (self, style);
-
-	for (node = LSM_DOM_NODE (self)->first_child; node != NULL; node = node->next_sibling)
-		if (LSM_IS_SVG_ELEMENT (node)) {
-			if (self->need_update)
-				LSM_SVG_ELEMENT (node)->need_update = TRUE;
-			lsm_svg_element_update (LSM_SVG_ELEMENT (node), style);
-		}
-
-	lsm_svg_style_free (style);
-
-	self->need_update = FALSE;
-	self->need_children_update = FALSE;
+	return lsm_svg_property_bag_get_property (&s_element->property_bag, name);
 }
 
 /* LsmSvgElement implementation */
@@ -126,20 +97,32 @@ _render (LsmSvgElement *element, LsmSvgView *view)
 
 	lsm_debug ("[LsmSvgElement::_render");
 
+	lsm_svg_view_push_group_opacity (view);
+
 	for (node = LSM_DOM_NODE (element)->first_child; node != NULL; node = node->next_sibling)
 		if (LSM_IS_SVG_ELEMENT (node))
 		    lsm_svg_element_render (LSM_SVG_ELEMENT (node), view);
+
+	lsm_svg_view_pop_group_opacity (view);
 }
 
 void
 lsm_svg_element_render (LsmSvgElement *element, LsmSvgView *view)
 {
 	LsmSvgElementClass *element_class;
+	const LsmSvgStyle *parent_style;
+	LsmSvgStyle *style;
 
 	g_return_if_fail (LSM_IS_SVG_ELEMENT (element));
 
+	parent_style = lsm_svg_view_get_current_style (view);
+	style = lsm_svg_style_new_inherited (parent_style, &element->property_bag);
+
+	if (!lsm_svg_matrix_is_identity (&element->transform.matrix))
+		lsm_svg_view_push_matrix (view, &element->transform.matrix);
 
 	lsm_svg_view_push_element (view, element);
+	lsm_svg_view_push_style (view, style);
 
 	element_class = LSM_SVG_ELEMENT_GET_CLASS (element);
 	if (element_class->render != NULL) {
@@ -150,41 +133,72 @@ lsm_svg_element_render (LsmSvgElement *element, LsmSvgView *view)
 		element_class->render (element, view);
 	}
 
+	lsm_svg_view_pop_style (view);
 	lsm_svg_view_pop_element (view);
+
+	if (!lsm_svg_matrix_is_identity (&element->transform.matrix))
+		lsm_svg_view_pop_matrix (view);
+
+	lsm_svg_style_free (style);
 }
 
-void
-lsm_svg_element_render_paint (LsmSvgElement *element, LsmSvgView *view)
+static void
+lsm_svg_element_enable_rendering (LsmSvgElement *element)
 {
 	LsmSvgElementClass *element_class;
 
 	g_return_if_fail (LSM_IS_SVG_ELEMENT (element));
 
 	element_class = LSM_SVG_ELEMENT_GET_CLASS (element);
-	if (element_class->render_paint != NULL) {
-		lsm_debug ("[LsmSvgElement::render_paint] Render %s (%s)",
-			    lsm_dom_node_get_node_name (LSM_DOM_NODE (element)),
-			    element->id.value != NULL ? element->id.value : "no id");
+	g_return_if_fail (element_class->enable_rendering != NULL);
 
-		element_class->render_paint (element, view);
-	}
+	element_class->enable_rendering (element);
 }
 
 void
-lsm_svg_element_render_clip (LsmSvgElement *element, LsmSvgView *view)
+lsm_svg_element_force_render (LsmSvgElement *element, LsmSvgView *view)
 {
-	LsmSvgElementClass *element_class;
+	g_return_if_fail (LSM_IS_SVG_PATTERN_ELEMENT (element) ||
+			  LSM_IS_SVG_GRADIENT_ELEMENT (element) ||
+			  LSM_IS_SVG_MASK_ELEMENT (element) ||
+			  LSM_IS_SVG_CLIP_PATH_ELEMENT (element));
 
-	g_return_if_fail (LSM_IS_SVG_ELEMENT (element));
+	lsm_svg_element_enable_rendering (element);
+	lsm_svg_element_render (element, view);
+}
 
-	element_class = LSM_SVG_ELEMENT_GET_CLASS (element);
-	if (element_class->render_clip != NULL) {
-		lsm_debug ("[LsmSvgElement::render_clip] Render %s (%s)",
-			    lsm_dom_node_get_node_name (LSM_DOM_NODE (element)),
-			    element->id.value != NULL ? element->id.value : "no id");
+static void
+_get_extents (LsmSvgElement *self, LsmSvgView *view, LsmExtents *extents)
+{
+	LsmDomNode *node;
+	gboolean first_child = TRUE;
+	LsmExtents element_extents = {0.0, 0.0, 0.0, 0.0};
+
+	lsm_debug ("[LsmSvgGraphic::_graphic_get_extents]");
 
-		element_class->render_clip (element, view);
+	for (node = LSM_DOM_NODE (self)->first_child; node != NULL; node = node->next_sibling) {
+		if (LSM_IS_SVG_ELEMENT (node)) {
+			LsmExtents child_extents;
+
+			lsm_svg_element_get_extents (LSM_SVG_ELEMENT (node), view, &child_extents);
+
+			if (!lsm_svg_matrix_is_identity (&self->transform.matrix))
+				lsm_svg_matrix_transform_bounding_box (&self->transform.matrix,
+								       &child_extents.x1, &child_extents.y1,
+								       &child_extents.x2, &child_extents.y2);
+			if (first_child) {
+				element_extents = child_extents;
+				first_child = FALSE;
+			} else {
+				element_extents.x1 = MIN (element_extents.x1, child_extents.x1);
+				element_extents.y1 = MIN (element_extents.y1, child_extents.y1);
+				element_extents.x2 = MAX (element_extents.x2, child_extents.x2);
+				element_extents.y2 = MAX (element_extents.y2, child_extents.y2);
+			}
+		}
 	}
+
+	*extents = element_extents;
 }
 
 void
@@ -214,17 +228,42 @@ lsm_svg_element_get_extents (LsmSvgElement *element, LsmSvgView *view, LsmExtent
 static void
 lsm_svg_element_init (LsmSvgElement *element)
 {
-	element->need_update = TRUE;
+	lsm_svg_matrix_init_identity (&element->transform.matrix);
 }
 
 static void
 lsm_svg_element_finalize (GObject *object)
 {
+	LsmSvgElement *svg_element = LSM_SVG_ELEMENT (object);
+
+	lsm_svg_property_bag_clean (&svg_element->property_bag);
+
 	parent_class->finalize (object);
 }
 
 /* LsmSvgElement class */
 
+static const LsmSvgMatrix matrix_default =	 { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, LSM_SVG_MATRIX_FLAGS_IDENTITY};
+
+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 = "transform",
+		.attribute_offset = offsetof (LsmSvgElement, transform),
+		.trait_class = &lsm_svg_matrix_trait_class,
+		.trait_default = &matrix_default
+	}
+};
+
 static void
 lsm_svg_element_class_init (LsmSvgElementClass *s_element_class)
 {
@@ -242,14 +281,10 @@ lsm_svg_element_class_init (LsmSvgElementClass *s_element_class)
 	d_element_class->get_attribute = lsm_svg_element_get_attribute;
 	d_element_class->set_attribute = lsm_svg_element_set_attribute;
 
-	s_element_class->update = NULL;
 	s_element_class->render = _render;
-	s_element_class->render_paint = NULL;
-
-	s_element_class->attributes = lsm_dom_attribute_map_new ();
-
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "id",
-					  offsetof (LsmSvgElement, id));
+	s_element_class->get_extents = _get_extents;
+	s_element_class->attribute_manager = lsm_attribute_manager_new (G_N_ELEMENTS (lsm_svg_attribute_infos),
+									lsm_svg_attribute_infos);
 }
 
 G_DEFINE_ABSTRACT_TYPE (LsmSvgElement, lsm_svg_element, LSM_TYPE_DOM_ELEMENT)
diff --git a/src/lsmsvgelement.h b/src/lsmsvgelement.h
index 0a877c3..4138219 100644
--- a/src/lsmsvgelement.h
+++ b/src/lsmsvgelement.h
@@ -24,8 +24,8 @@
 #define LSM_SVG_ELEMENT_H
 
 #include <lsmsvg.h>
+#include <lsmattributes.h>
 #include <lsmsvgattributes.h>
-#include <lsmsvgattributebags.h>
 #include <lsmsvgstyle.h>
 #include <lsmdomelement.h>
 #include <cairo.h>
@@ -44,32 +44,27 @@ typedef struct _LsmSvgElementClass LsmSvgElementClass;
 struct _LsmSvgElement {
 	LsmDomElement	element;
 
-	LsmDomAttribute	id;
+	LsmPropertyBag property_bag;
 
-	/* View */
-
-	gboolean need_update;
-	gboolean need_children_update;
+	LsmAttribute			id;
+	LsmAttribute			class_name;
+	LsmSvgTransformAttribute 	transform;
 };
 
 struct _LsmSvgElementClass {
 	LsmDomElementClass  parent_class;
 
-	LsmDomAttributeMap *attributes;
+	LsmAttributeManager *attribute_manager;
 
-	void		(*update)		(LsmSvgElement *element, LsmSvgStyle *style);
+	void		(*enable_rendering)	(LsmSvgElement *element);
 	void 		(*render)		(LsmSvgElement *element, LsmSvgView *view);
-	void 		(*render_paint)		(LsmSvgElement *element, LsmSvgView *view);
-	void 		(*render_clip)		(LsmSvgElement *element, LsmSvgView *view);
 	void 		(*get_extents)		(LsmSvgElement *element, LsmSvgView *view, LsmExtents *extents);
 };
 
 GType lsm_svg_element_get_type (void);
 
-void		lsm_svg_element_update 		(LsmSvgElement *element, const LsmSvgStyle *style);
 void 		lsm_svg_element_render 		(LsmSvgElement *element, LsmSvgView *view);
-void 		lsm_svg_element_render_paint 	(LsmSvgElement *element, LsmSvgView *view);
-void 		lsm_svg_element_render_clip 	(LsmSvgElement *element, LsmSvgView *view);
+void 		lsm_svg_element_force_render 	(LsmSvgElement *element, LsmSvgView *view);
 void		lsm_svg_element_get_extents	(LsmSvgElement *element, LsmSvgView *view, LsmExtents *extents);
 
 G_END_DECLS
diff --git a/src/lsmsvgellipseelement.c b/src/lsmsvgellipseelement.c
index 17f7783..f394a77 100644
--- a/src/lsmsvgellipseelement.c
+++ b/src/lsmsvgellipseelement.c
@@ -34,43 +34,18 @@ lsm_svg_ellipse_element_get_node_name (LsmDomNode *node)
 
 /* LsmSvgElement implementation */
 
-static void
-lsm_svg_ellipse_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
-{
-	LsmSvgEllipseElement *ellipse = LSM_SVG_ELLIPSE_ELEMENT (self);
-	LsmSvgLength length;
-
-	length.value_unit = 0.0;
-	length.type = LSM_SVG_LENGTH_TYPE_NUMBER;
-	lsm_svg_animated_length_attribute_parse (&ellipse->cx, &length);
-
-	length.value_unit = 0.0;
-	length.type = LSM_SVG_LENGTH_TYPE_NUMBER;
-	lsm_svg_animated_length_attribute_parse (&ellipse->cy, &length);
-
-	length.value_unit = 0.0;
-	length.type = LSM_SVG_LENGTH_TYPE_NUMBER;
-	lsm_svg_animated_length_attribute_parse (&ellipse->rx, &length);
-
-	length.value_unit = 0.0;
-	length.type = LSM_SVG_LENGTH_TYPE_NUMBER;
-	lsm_svg_animated_length_attribute_parse (&ellipse->ry, &length);
-
-	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
-}
-
 /* LsmSvgGraphic implementation */
 
 static void
-lsm_svg_ellipse_element_graphic_render (LsmSvgElement *self, LsmSvgView *view)
+lsm_svg_ellipse_element_render (LsmSvgElement *self, LsmSvgView *view)
 {
 	LsmSvgEllipseElement *ellipse = LSM_SVG_ELLIPSE_ELEMENT (self);
 	double cx, cy, rx, ry;
 
-	cx = lsm_svg_view_normalize_length (view, &ellipse->cx.length.base, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
-	cy = lsm_svg_view_normalize_length (view, &ellipse->cy.length.base, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
-	rx = lsm_svg_view_normalize_length (view, &ellipse->rx.length.base, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
-	ry = lsm_svg_view_normalize_length (view, &ellipse->ry.length.base, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
+	cx = lsm_svg_view_normalize_length (view, &ellipse->cx.length, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
+	cy = lsm_svg_view_normalize_length (view, &ellipse->cy.length, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
+	rx = lsm_svg_view_normalize_length (view, &ellipse->rx.length, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
+	ry = lsm_svg_view_normalize_length (view, &ellipse->ry.length, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
 
 	lsm_svg_view_show_ellipse (view, cx, cy, rx, ry);
 }
@@ -83,25 +58,58 @@ lsm_svg_ellipse_element_new (void)
 	return g_object_new (LSM_TYPE_SVG_ELLIPSE_ELEMENT, NULL);
 }
 
+static const LsmSvgLength length_default = 	 { .value_unit =   0.0, .type = LSM_SVG_LENGTH_TYPE_PX};
+
 static void
 lsm_svg_ellipse_element_init (LsmSvgEllipseElement *self)
 {
+	self->cx.length = length_default;
+	self->cy.length = length_default;
+	self->rx.length = length_default;
+	self->ry.length = length_default;
 }
 
 static void
 lsm_svg_ellipse_element_finalize (GObject *object)
 {
+	parent_class->finalize (object);
 }
 
 /* LsmSvgEllipseElement class */
 
+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)
 {
 	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);
 
 	parent_class = g_type_class_peek_parent (s_rect_class);
 
@@ -109,20 +117,12 @@ 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_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->render = lsm_svg_ellipse_element_render;
+	s_element_class->attribute_manager = lsm_attribute_manager_duplicate (s_element_class->attribute_manager);
 
-	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_attribute_manager_add_attributes (s_element_class->attribute_manager,
+					      G_N_ELEMENTS (lsm_svg_ellipse_element_attribute_infos),
+					      lsm_svg_ellipse_element_attribute_infos);
 }
 
-G_DEFINE_TYPE (LsmSvgEllipseElement, lsm_svg_ellipse_element, LSM_TYPE_SVG_GRAPHIC)
+G_DEFINE_TYPE (LsmSvgEllipseElement, lsm_svg_ellipse_element, LSM_TYPE_SVG_ELEMENT)
diff --git a/src/lsmsvgellipseelement.h b/src/lsmsvgellipseelement.h
index d5e6d74..87a6760 100644
--- a/src/lsmsvgellipseelement.h
+++ b/src/lsmsvgellipseelement.h
@@ -23,7 +23,7 @@
 #define LSM_SVG_ELLIPSE_ELEMENT_H
 
 #include <lsmsvg.h>
-#include <lsmsvggraphic.h>
+#include <lsmsvgelement.h>
 
 G_BEGIN_DECLS
 
@@ -37,16 +37,16 @@ G_BEGIN_DECLS
 typedef struct _LsmSvgEllipseElementClass LsmSvgEllipseElementClass;
 
 struct _LsmSvgEllipseElement {
-	LsmSvgGraphic graphic;
+	LsmSvgElement element;
 
-	LsmSvgAnimatedLengthAttribute	cx;
-	LsmSvgAnimatedLengthAttribute	cy;
-	LsmSvgAnimatedLengthAttribute	rx;
-	LsmSvgAnimatedLengthAttribute	ry;
+	LsmSvgLengthAttribute	cx;
+	LsmSvgLengthAttribute	cy;
+	LsmSvgLengthAttribute	rx;
+	LsmSvgLengthAttribute	ry;
 };
 
 struct _LsmSvgEllipseElementClass {
-	LsmSvgGraphicClass  parent_class;
+	LsmSvgElementClass  element_class;
 };
 
 GType lsm_svg_ellipse_element_get_type (void);
diff --git a/src/lsmsvgenums.c b/src/lsmsvgenums.c
index 1247354..ce02e1d 100644
--- a/src/lsmsvgenums.c
+++ b/src/lsmsvgenums.c
@@ -38,7 +38,7 @@ lsm_svg_value_from_string (const char *string, const char **strings, unsigned in
 }
 
 static const char *lsm_svg_length_type_strings[] = {
-	"",
+	"?",
 	"",
 	"%",
 	"em",
diff --git a/src/lsmsvggelement.c b/src/lsmsvggelement.c
index fb2a8c8..f3565ad 100644
--- a/src/lsmsvggelement.c
+++ b/src/lsmsvggelement.c
@@ -35,7 +35,7 @@ lsm_svg_g_element_get_node_name (LsmDomNode *node)
 
 /* GGElement implementation */
 
-/* LsmSvgGraphic implementation */
+/* LsmSvgElement implementation */
 
 /* LsmSvgGElement implementation */
 
@@ -52,6 +52,7 @@ lsm_svg_g_element_init (LsmSvgGElement *self)
 
 /* LsmSvgGElement class */
 
+
 static void
 lsm_svg_g_element_class_init (LsmSvgGElementClass *s_g_class)
 {
@@ -62,4 +63,4 @@ lsm_svg_g_element_class_init (LsmSvgGElementClass *s_g_class)
 	d_node_class->get_node_name = lsm_svg_g_element_get_node_name;
 }
 
-G_DEFINE_TYPE (LsmSvgGElement, lsm_svg_g_element, LSM_TYPE_SVG_GRAPHIC)
+G_DEFINE_TYPE (LsmSvgGElement, lsm_svg_g_element, LSM_TYPE_SVG_ELEMENT)
diff --git a/src/lsmsvggelement.h b/src/lsmsvggelement.h
index f44e05a..cbb1ae1 100644
--- a/src/lsmsvggelement.h
+++ b/src/lsmsvggelement.h
@@ -23,7 +23,7 @@
 #define LSM_SVG_G_ELEMENT_H
 
 #include <lsmsvg.h>
-#include <lsmsvggraphic.h>
+#include <lsmsvgelement.h>
 
 G_BEGIN_DECLS
 
@@ -37,11 +37,11 @@ G_BEGIN_DECLS
 typedef struct _LsmSvgGElementClass LsmSvgGElementClass;
 
 struct _LsmSvgGElement {
-	LsmSvgGraphic graphic;
+	LsmSvgElement element;
 };
 
 struct _LsmSvgGElementClass {
-	LsmSvgGraphicClass  parent_class;
+	LsmSvgElementClass  element_class;
 };
 
 GType lsm_svg_g_element_get_type (void);
diff --git a/src/lsmsvggradientelement.c b/src/lsmsvggradientelement.c
index 2b441b7..d7d1ef7 100644
--- a/src/lsmsvggradientelement.c
+++ b/src/lsmsvggradientelement.c
@@ -38,95 +38,94 @@ lsm_svg_gradient_element_can_append_child (LsmDomNode *parent, LsmDomNode *child
 /* LsmSvgElement implementation */
 
 static void
-_gradient_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
+lsm_svg_gradient_element_render (LsmSvgElement *self, LsmSvgView *view)
 {
 	LsmSvgGradientElement *gradient = LSM_SVG_GRADIENT_ELEMENT (self);
-	LsmSvgPatternUnits units;
-	LsmSvgSpreadMethod method;
+	LsmSvgGradientElementClass *gradient_class = LSM_SVG_GRADIENT_ELEMENT_GET_CLASS (self);
 
-	units = LSM_SVG_PATTERN_UNITS_OBJECT_BOUNDING_BOX;
-	method = LSM_SVG_SPREAD_METHOD_PAD;
+	if (!gradient->enable_rendering)
+		return;
 
-	lsm_svg_pattern_units_attribute_parse (&gradient->units, &units);
-	lsm_svg_spread_method_attribute_parse (&gradient->spread_method, &method);
-	lsm_svg_transform_attribute_parse (&gradient->transform);
+	gradient->enable_rendering = FALSE;
 
-	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
-}
-
-static void
-_gradient_element_graphic_render (LsmSvgElement *self, LsmSvgView *view)
-{
-	LsmSvgGradientElement *gradient = LSM_SVG_GRADIENT_ELEMENT (self);
-	LsmDomNode *iter;
-	double last_offset = 0.0;
-
-	for (iter = LSM_DOM_NODE (self)->first_child; iter != NULL; iter = iter->next_sibling) {
-		if (LSM_IS_SVG_STOP_ELEMENT (iter)) {
-			LsmSvgStopElement *stop;
-			const LsmSvgColor *color;
-			double offset;
-			double opacity;
-
-			stop = LSM_SVG_STOP_ELEMENT (iter);
-
-			offset = lsm_svg_stop_element_get_offset (stop);
-			color = lsm_svg_stop_element_get_color (stop);
-			opacity = lsm_svg_stop_element_get_opacity (stop);
-
-			if (offset < last_offset)
-				offset = last_offset;
-			else
-				last_offset = offset;
-
-			lsm_debug ("[LsmSvgGradientElement::render] Add stop at %g (%g,%g,%g,%g)",
-				    offset, color->red, color->green, color->blue, opacity);
+	g_return_if_fail (gradient_class->create_gradient != NULL);
 
-			lsm_svg_view_add_gradient_color_stop (view, offset, color, opacity);
-		}
-	}
+	gradient_class->create_gradient (self, view);
 
 	lsm_svg_view_set_gradient_properties (view,
 					      gradient->spread_method.value,
 					      gradient->units.value,
 					      &gradient->transform.matrix);
+
+	LSM_SVG_ELEMENT_CLASS (parent_class)->render (self, view);
+}
+
+static void
+lsm_svg_gradient_element_enable_rendering (LsmSvgElement *element)
+{
+	LSM_SVG_GRADIENT_ELEMENT (element)->enable_rendering = TRUE;
 }
 
 /* LsmSvgGradientElement implementation */
 
+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, LSM_SVG_MATRIX_FLAGS_IDENTITY};
+
 static void
 lsm_svg_gradient_element_init (LsmSvgGradientElement *self)
 {
+	self->enable_rendering = FALSE;
+	self->units.value = units_default;
+	self->spread_method.value = spread_method_default;
+	lsm_svg_matrix_init_identity (&self->transform.matrix);
 }
 
 /* LsmSvgGradientElement class */
 
+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)
 {
 	LsmDomNodeClass *d_node_class = LSM_DOM_NODE_CLASS (klass);
 	LsmSvgElementClass *s_element_class = LSM_SVG_ELEMENT_CLASS (klass);
-	LsmSvgGraphicClass *s_graphic_class = LSM_SVG_GRAPHIC_CLASS (klass);
 
 	parent_class = g_type_class_peek_parent (klass);
 
 	d_node_class->can_append_child = lsm_svg_gradient_element_can_append_child;
 
-	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);
-
-	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));
+	s_element_class->render = lsm_svg_gradient_element_render;
+	s_element_class->enable_rendering = lsm_svg_gradient_element_enable_rendering;
+	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);
 }
 
-G_DEFINE_ABSTRACT_TYPE (LsmSvgGradientElement, lsm_svg_gradient_element, LSM_TYPE_SVG_GRAPHIC)
+G_DEFINE_ABSTRACT_TYPE (LsmSvgGradientElement, lsm_svg_gradient_element, LSM_TYPE_SVG_ELEMENT)
diff --git a/src/lsmsvggradientelement.h b/src/lsmsvggradientelement.h
index cad2a35..6bb0c3a 100644
--- a/src/lsmsvggradientelement.h
+++ b/src/lsmsvggradientelement.h
@@ -23,7 +23,7 @@
 #define LSM_SVG_GRADIENT_ELEMENT_H
 
 #include <lsmsvg.h>
-#include <lsmsvggraphic.h>
+#include <lsmsvgelement.h>
 
 G_BEGIN_DECLS
 
@@ -37,16 +37,20 @@ G_BEGIN_DECLS
 typedef struct _LsmSvgGradientElementClass LsmSvgGradientElementClass;
 
 struct _LsmSvgGradientElement {
-	LsmSvgGraphic graphic;
+	LsmSvgElement element;
 
 	LsmSvgTransformAttribute transform;
-	LsmDomEnumAttribute units;
-	LsmDomEnumAttribute spread_method;
-	LsmDomAttribute href;
+	LsmSvgPatternUnitsAttribute units;
+	LsmSvgSpreadMethodAtttribute spread_method;
+	LsmAttribute href;
+
+	gboolean enable_rendering;
 };
 
 struct _LsmSvgGradientElementClass {
-	LsmSvgGraphicClass  parent_class;
+	LsmSvgElementClass  element_class;
+
+	void (*create_gradient)	(LsmSvgElement *self, LsmSvgView *view);
 };
 
 GType lsm_svg_gradient_element_get_type (void);
diff --git a/src/lsmsvgimageelement.c b/src/lsmsvgimageelement.c
index 61057fd..9ae0451 100644
--- a/src/lsmsvgimageelement.c
+++ b/src/lsmsvgimageelement.c
@@ -36,104 +36,75 @@ lsm_svg_image_element_get_node_name (LsmDomNode *node)
 	return "image";
 }
 
-static gboolean
-lsm_svg_use_can_append_child (LsmDomNode *node, LsmDomNode *child)
-{
-	return FALSE;
-}
-
-/* LsmSvgElement implementation */
-
 static void
-lsm_svg_image_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
+lsm_svg_image_element_set_attribute (LsmDomElement *self, const char *name, const char *value)
 {
 	LsmSvgImageElement *image_element = LSM_SVG_IMAGE_ELEMENT (self);
-	LsmSvgLength length;
-	const char *href;
-
-	length.value_unit = 0.0;
-	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&image_element->x, &length);
-
-	length.value_unit = 0.0;
-	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&image_element->y, &length);
-
-	length.value_unit = 0.0;
-	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&image_element->width, &length);
-
-	length.value_unit = 0.0;
-	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&image_element->height, &length);
 
-	lsm_svg_preserve_aspect_ratio_attribute_parse (&image_element->preserve_aspect_ratio);
+	LSM_DOM_ELEMENT_CLASS (parent_class)->set_attribute (self, name, value);
 
-	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
-
-	if (image_element->pixbuf != NULL) {
+	if (g_strcmp0 (name, "xlink:href") == 0 && image_element->pixbuf != NULL) {
 		g_object_unref (image_element->pixbuf);
 		image_element->pixbuf = NULL;
 	}
+}
 
-	href = image_element->href.value;
+static gboolean
+lsm_svg_use_can_append_child (LsmDomNode *node, LsmDomNode *child)
+{
+	return FALSE;
+}
 
-	if (href != NULL) {
-		GdkPixbufLoader *loader;
-		void *image_data;
-		gsize data_size;
-		int result;
+/* LsmSvgElement implementation */
 
-		if (strncmp (href, "data:", 5) == 0) {
+/* LsmSvgGraphic implementation */
 
-			lsm_debug ("[LsmSvgImageElement::update] Found inlined image");
+static void
+lsm_svg_image_element_render (LsmSvgElement *self, LsmSvgView *view)
+{
+	LsmSvgImageElement *image;
+	LsmBox viewport;
+	LsmBox viewbox;
 
-			while (*href != '\0' && *href != ',')
-				href++;
+	image = LSM_SVG_IMAGE_ELEMENT (self);
 
-			image_data = g_base64_decode (href, &data_size);
-		} else {
-			image_data = NULL;
-			data_size = 0;
-		}
+	if (image->pixbuf == NULL) {
+		LsmDomDocument *document;
+		char *data;
+		gsize size;
+
+		document = lsm_dom_node_get_owner_document (LSM_DOM_NODE (self));
+		data = lsm_dom_document_get_href_data (document, image->href.value, &size);
+
+		if (data != NULL) {
+			GdkPixbufLoader *loader;
+			int result;
 
-		if (image_data != NULL) {
 			loader = gdk_pixbuf_loader_new ();
 
-			result = gdk_pixbuf_loader_write (loader, image_data, data_size, NULL);
+			result = gdk_pixbuf_loader_write (loader, (guchar *) data, size, NULL);
 
-			g_free (image_data);
+			g_free (data);
 
 			gdk_pixbuf_loader_close (loader, NULL);
 
-			image_element->pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
-			g_object_ref (image_element->pixbuf);
+			image->pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
+			g_object_ref (image->pixbuf);
 
 			g_object_unref (loader);
 		}
 	}
-}
-
-/* LsmSvgGraphic implementation */
-
-static void
-lsm_svg_image_element_graphic_render (LsmSvgElement *self, LsmSvgView *view)
-{
-	LsmSvgImageElement *image;
-	LsmBox viewport;
-	LsmBox viewbox;
 
-	image = LSM_SVG_IMAGE_ELEMENT (self);
 	if (image->pixbuf == NULL)
 		return;
 
-	viewport.x      = lsm_svg_view_normalize_length (view, &image->x.length.base,
+	viewport.x      = lsm_svg_view_normalize_length (view, &image->x.length,
 							 LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
-	viewport.y      = lsm_svg_view_normalize_length (view, &image->y.length.base,
+	viewport.y      = lsm_svg_view_normalize_length (view, &image->y.length,
 							 LSM_SVG_LENGTH_DIRECTION_VERTICAL);
-	viewport.width  = lsm_svg_view_normalize_length (view, &image->width.length.base,
+	viewport.width  = lsm_svg_view_normalize_length (view, &image->width.length,
 							 LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
-	viewport.height = lsm_svg_view_normalize_length (view, &image->height.length.base,
+	viewport.height = lsm_svg_view_normalize_length (view, &image->height.length,
 							 LSM_SVG_LENGTH_DIRECTION_VERTICAL);
 
 	lsm_debug ("[LsmSvgImageElement::graphic_render] viewport %g, %g, %g, %g",
@@ -159,10 +130,22 @@ lsm_svg_image_element_new (void)
 	return g_object_new (LSM_TYPE_SVG_IMAGE_ELEMENT, NULL);
 }
 
+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 void
 lsm_svg_image_element_init (LsmSvgImageElement *self)
 {
 	self->pixbuf = NULL;
+	self->x.length = length_default;
+	self->y.length = length_default;
+	self->width.length = length_default;
+	self->height.length = length_default;
+	self->preserve_aspect_ratio.value = preserve_aspect_ratio_default;
 }
 
 static void
@@ -172,17 +155,57 @@ lsm_svg_image_element_finalize (GObject *gobject)
 
 	if (image->pixbuf != NULL)
 		g_object_unref (image->pixbuf);
+
+	parent_class->finalize (gobject);
 }
 
 /* LsmSvgImageElement class */
 
+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)
 {
 	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 	LsmDomNodeClass *d_node_class = LSM_DOM_NODE_CLASS (klass);
+	LsmDomElementClass *d_element_class = LSM_DOM_ELEMENT_CLASS (klass);
 	LsmSvgElementClass *s_element_class = LSM_SVG_ELEMENT_CLASS (klass);
-	LsmSvgGraphicClass *s_graphic_class = LSM_SVG_GRAPHIC_CLASS (klass);
 
 	parent_class = g_type_class_peek_parent (klass);
 
@@ -191,24 +214,14 @@ lsm_svg_image_element_class_init (LsmSvgImageElementClass *klass)
 	d_node_class->get_node_name = lsm_svg_image_element_get_node_name;
 	d_node_class->can_append_child = lsm_svg_use_can_append_child;
 
-	s_element_class->update = lsm_svg_image_element_update;
-
-	s_graphic_class->graphic_render = lsm_svg_image_element_graphic_render;
+	d_element_class->set_attribute = lsm_svg_image_element_set_attribute;
 
-	s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
+	s_element_class->render = lsm_svg_image_element_render;
+	s_element_class->attribute_manager = lsm_attribute_manager_duplicate (s_element_class->attribute_manager);
 
-	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));
+	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);
 }
 
-G_DEFINE_TYPE (LsmSvgImageElement, lsm_svg_image_element, LSM_TYPE_SVG_GRAPHIC)
+G_DEFINE_TYPE (LsmSvgImageElement, lsm_svg_image_element, LSM_TYPE_SVG_ELEMENT)
diff --git a/src/lsmsvgimageelement.h b/src/lsmsvgimageelement.h
index d2d63d2..fc637cf 100644
--- a/src/lsmsvgimageelement.h
+++ b/src/lsmsvgimageelement.h
@@ -23,7 +23,7 @@
 #define LSM_SVG_IMAGE_ELEMENT_H
 
 #include <lsmsvg.h>
-#include <lsmsvggraphic.h>
+#include <lsmsvgelement.h>
 #include <gdk-pixbuf/gdk-pixbuf.h>
 
 G_BEGIN_DECLS
@@ -38,14 +38,14 @@ G_BEGIN_DECLS
 typedef struct _LsmSvgImageElementClass LsmSvgImageElementClass;
 
 struct _LsmSvgImageElement {
-	LsmSvgGraphic graphic;
+	LsmSvgElement element;
 
-	LsmSvgAnimatedLengthAttribute	x;
-	LsmSvgAnimatedLengthAttribute	y;
-	LsmSvgAnimatedLengthAttribute	width;
-	LsmSvgAnimatedLengthAttribute	height;
+	LsmSvgLengthAttribute	x;
+	LsmSvgLengthAttribute	y;
+	LsmSvgLengthAttribute	width;
+	LsmSvgLengthAttribute	height;
 
-	LsmDomAttribute		href;
+	LsmAttribute		href;
 
 	LsmSvgPreserveAspectRatioAttribute	preserve_aspect_ratio;
 
@@ -53,7 +53,7 @@ struct _LsmSvgImageElement {
 };
 
 struct _LsmSvgImageElementClass {
-	LsmSvgGraphicClass  parent_class;
+	LsmSvgElementClass  element_class;
 };
 
 GType lsm_svg_image_element_get_type (void);
diff --git a/src/lsmsvglineargradientelement.c b/src/lsmsvglineargradientelement.c
index 2fd37cf..c27f650 100644
--- a/src/lsmsvglineargradientelement.c
+++ b/src/lsmsvglineargradientelement.c
@@ -37,32 +37,7 @@ lsm_svg_linear_gradient_element_get_node_name (LsmDomNode *node)
 /* GLinearGradientElement implementation */
 
 static void
-_linear_gradient_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
-{
-	LsmSvgLinearGradientElement *linear = LSM_SVG_LINEAR_GRADIENT_ELEMENT (self);
-	LsmSvgLength length;
-
-	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
-
-	length.value_unit = 0.0;
-	length.type = LSM_SVG_LENGTH_TYPE_PERCENTAGE;
-	lsm_svg_animated_length_attribute_parse (&linear->x1, &length);
-
-	length.value_unit = 0.0;
-	length.type = LSM_SVG_LENGTH_TYPE_PERCENTAGE;
-	lsm_svg_animated_length_attribute_parse (&linear->y1, &length);
-
-	length.value_unit = 100.0;
-	length.type = LSM_SVG_LENGTH_TYPE_PERCENTAGE;
-	lsm_svg_animated_length_attribute_parse (&linear->x2, &length);
-
-	length.value_unit = 0.0;
-	length.type = LSM_SVG_LENGTH_TYPE_PERCENTAGE;
-	lsm_svg_animated_length_attribute_parse (&linear->y2, &length);
-}
-
-static void
-_linear_gradient_element_render_paint (LsmSvgElement *self, LsmSvgView *view)
+lsm_svg_linear_gradient_element_create_gradient (LsmSvgElement *self, LsmSvgView *view)
 {
 	LsmSvgLinearGradientElement *linear = LSM_SVG_LINEAR_GRADIENT_ELEMENT (self);
 	gboolean is_object_bounding_box;
@@ -77,10 +52,10 @@ _linear_gradient_element_render_paint (LsmSvgElement *self, LsmSvgView *view)
 		lsm_svg_view_push_viewbox (view, &viewbox);
 	}
 
-	x1 = lsm_svg_view_normalize_length (view, &linear->x1.length.base, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
-	y1 = lsm_svg_view_normalize_length (view, &linear->y1.length.base, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
-	x2 = lsm_svg_view_normalize_length (view, &linear->x2.length.base, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
-	y2 = lsm_svg_view_normalize_length (view, &linear->y2.length.base, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
+	x1 = lsm_svg_view_normalize_length (view, &linear->x1.length, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
+	y1 = lsm_svg_view_normalize_length (view, &linear->y1.length, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
+	x2 = lsm_svg_view_normalize_length (view, &linear->x2.length, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
+	y2 = lsm_svg_view_normalize_length (view, &linear->y2.length, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
 
 	lsm_debug ("[LsmSvgLinearGradientElement::render] Create linear %g, %g, %g, %g",
 		    x1, y1, x2, y2);
@@ -89,8 +64,6 @@ _linear_gradient_element_render_paint (LsmSvgElement *self, LsmSvgView *view)
 		lsm_svg_view_pop_viewbox (view);
 
 	lsm_svg_view_create_linear_gradient (view, x1, y1, x2, y2);
-
-	LSM_SVG_ELEMENT_CLASS (parent_class)->render_paint (self, view);
 }
 
 /* LsmSvgLinearGradientElement implementation */
@@ -101,25 +74,60 @@ lsm_svg_linear_gradient_element_new (void)
 	return g_object_new (LSM_TYPE_SVG_LINEAR_GRADIENT_ELEMENT, NULL);
 }
 
+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 void
 lsm_svg_linear_gradient_element_init (LsmSvgLinearGradientElement *self)
 {
-
+	self->x1.length = x1_y1_y2_default;
+	self->y1.length = x1_y1_y2_default;
+	self->x2.length = x2_default;
+	self->y2.length = x1_y1_y2_default;
 }
 
 static void
 lsm_svg_linear_gradient_element_finalize (GObject *object)
 {
+	parent_class->finalize (object);
 }
 
 /* LsmSvgLinearGradientElement class */
 
+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)
 {
 	GObjectClass *object_class = G_OBJECT_CLASS (s_svg_class);
 	LsmDomNodeClass *d_node_class = LSM_DOM_NODE_CLASS (s_svg_class);
 	LsmSvgElementClass *s_element_class = LSM_SVG_ELEMENT_CLASS (s_svg_class);
+	LsmSvgGradientElementClass *s_gradient_class = LSM_SVG_GRADIENT_ELEMENT_CLASS (s_svg_class);
 
 	parent_class = g_type_class_peek_parent (s_svg_class);
 
@@ -127,19 +135,13 @@ 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->render_paint = _linear_gradient_element_render_paint;
+	s_element_class->attribute_manager = lsm_attribute_manager_duplicate (s_element_class->attribute_manager);
 
-	s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
+	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);
 
-	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));
+	s_gradient_class->create_gradient = lsm_svg_linear_gradient_element_create_gradient;
 }
 
 G_DEFINE_TYPE (LsmSvgLinearGradientElement, lsm_svg_linear_gradient_element, LSM_TYPE_SVG_GRADIENT_ELEMENT)
diff --git a/src/lsmsvglineargradientelement.h b/src/lsmsvglineargradientelement.h
index 4a5127e..7797355 100644
--- a/src/lsmsvglineargradientelement.h
+++ b/src/lsmsvglineargradientelement.h
@@ -39,10 +39,10 @@ typedef struct _LsmSvgLinearGradientElementClass LsmSvgLinearGradientElementClas
 struct _LsmSvgLinearGradientElement {
 	LsmSvgGradientElement gradient;
 
-	LsmSvgAnimatedLengthAttribute	x1;
-	LsmSvgAnimatedLengthAttribute	y1;
-	LsmSvgAnimatedLengthAttribute	x2;
-	LsmSvgAnimatedLengthAttribute	y2;
+	LsmSvgLengthAttribute	x1;
+	LsmSvgLengthAttribute	y1;
+	LsmSvgLengthAttribute	x2;
+	LsmSvgLengthAttribute	y2;
 };
 
 struct _LsmSvgLinearGradientElementClass {
diff --git a/src/lsmsvglineelement.c b/src/lsmsvglineelement.c
index a272bb3..c7f5b70 100644
--- a/src/lsmsvglineelement.c
+++ b/src/lsmsvglineelement.c
@@ -35,45 +35,20 @@ lsm_svg_line_element_get_node_name (LsmDomNode *node)
 
 /* LsmSvgElement implementation */
 
-static void
-lsm_svg_line_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
-{
-	LsmSvgLineElement *line = LSM_SVG_LINE_ELEMENT (self);
-	LsmSvgLength length;
-
-	length.value_unit = 0.0;
-	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&line->x1, &length);
-
-	length.value_unit = 0.0;
-	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&line->y1, &length);
-
-	length.value_unit = 0.0;
-	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&line->x2, &length);
-
-	length.value_unit = 0.0;
-	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&line->y2, &length);
-
-	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
-}
-
 /* LsmSvgGraphic implementation */
 
 static void
-lsm_svg_line_element_graphic_render (LsmSvgElement *self, LsmSvgView *view)
+lsm_svg_line_element_render (LsmSvgElement *self, LsmSvgView *view)
 {
 	LsmSvgLineElement *line = LSM_SVG_LINE_ELEMENT (self);
 	double x1, y1, x2, y2;
 
-	x1 = lsm_svg_view_normalize_length (view, &line->x1.length.base, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
-	y1 = lsm_svg_view_normalize_length (view, &line->y1.length.base, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
-	x2 = lsm_svg_view_normalize_length (view, &line->x2.length.base, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
-	y2 = lsm_svg_view_normalize_length (view, &line->y2.length.base, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
+	x1 = lsm_svg_view_normalize_length (view, &line->x1.length, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
+	y1 = lsm_svg_view_normalize_length (view, &line->y1.length, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
+	x2 = lsm_svg_view_normalize_length (view, &line->x2.length, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
+	y2 = lsm_svg_view_normalize_length (view, &line->y2.length, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
 
-	lsm_debug ("[LsmSvgLineElement::graphic_render] %g, %g, %g, %g", x1, y1, x2, y2);
+	lsm_debug ("[LsmSvgLineElement::render] %g, %g, %g, %g", x1, y1, x2, y2);
 
 	lsm_svg_view_show_line (view, x1, y1, x2, y2);
 }
@@ -86,38 +61,62 @@ lsm_svg_line_element_new (void)
 	return g_object_new (LSM_TYPE_SVG_LINE_ELEMENT, NULL);
 }
 
+static const LsmSvgLength length_default = 	 { .value_unit =   0.0, .type = LSM_SVG_LENGTH_TYPE_PX};
+
 static void
 lsm_svg_line_element_init (LsmSvgLineElement *self)
 {
+	self->x1.length = length_default;
+	self->x2.length = length_default;
+	self->y1.length = length_default;
+	self->y2.length = length_default;
 }
 
 /* LsmSvgLineElement class */
 
+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)
 {
 	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);
 
 	parent_class = g_type_class_peek_parent (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_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->render = lsm_svg_line_element_render;
+	s_element_class->attribute_manager = lsm_attribute_manager_duplicate (s_element_class->attribute_manager);
 
-	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_attribute_manager_add_attributes (s_element_class->attribute_manager,
+					      G_N_ELEMENTS (lsm_svg_line_element_attribute_infos),
+					      lsm_svg_line_element_attribute_infos);
 }
 
-G_DEFINE_TYPE (LsmSvgLineElement, lsm_svg_line_element, LSM_TYPE_SVG_GRAPHIC)
+G_DEFINE_TYPE (LsmSvgLineElement, lsm_svg_line_element, LSM_TYPE_SVG_ELEMENT)
diff --git a/src/lsmsvglineelement.h b/src/lsmsvglineelement.h
index deeff47..45b9234 100644
--- a/src/lsmsvglineelement.h
+++ b/src/lsmsvglineelement.h
@@ -23,7 +23,7 @@
 #define LSM_SVG_LINE_ELEMENT_H
 
 #include <lsmsvg.h>
-#include <lsmsvggraphic.h>
+#include <lsmsvgelement.h>
 
 G_BEGIN_DECLS
 
@@ -37,16 +37,16 @@ G_BEGIN_DECLS
 typedef struct _LsmSvgLineElementClass LsmSvgLineElementClass;
 
 struct _LsmSvgLineElement {
-	LsmSvgGraphic graphic;
+	LsmSvgElement element;
 
-	LsmSvgAnimatedLengthAttribute	x1;
-	LsmSvgAnimatedLengthAttribute	y1;
-	LsmSvgAnimatedLengthAttribute	x2;
-	LsmSvgAnimatedLengthAttribute	y2;
+	LsmSvgLengthAttribute	x1;
+	LsmSvgLengthAttribute	y1;
+	LsmSvgLengthAttribute	x2;
+	LsmSvgLengthAttribute	y2;
 };
 
 struct _LsmSvgLineElementClass {
-	LsmSvgGraphicClass  parent_class;
+	LsmSvgElementClass  element_class;
 };
 
 GType lsm_svg_line_element_get_type (void);
diff --git a/src/lsmsvgmaskelement.c b/src/lsmsvgmaskelement.c
index c65541d..16cd1d9 100644
--- a/src/lsmsvgmaskelement.c
+++ b/src/lsmsvgmaskelement.c
@@ -37,44 +37,23 @@ _mask_element_get_node_name (LsmDomNode *node)
 /* LsmSvgElement implementation */
 
 static void
-_mask_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
-{
-	LsmSvgMaskElement *mask = LSM_SVG_MASK_ELEMENT (self);
-	LsmSvgPatternUnits units;
-	LsmSvgLength length;
-
-	units = LSM_SVG_PATTERN_UNITS_OBJECT_BOUNDING_BOX;
-	lsm_svg_pattern_units_attribute_parse (&mask->units, &units);
-
-	units = LSM_SVG_PATTERN_UNITS_USER_SPACE_ON_USE;
-	lsm_svg_pattern_units_attribute_parse (&mask->content_units, &units);
-
-	length.value_unit = -10.0;
-	length.type = LSM_SVG_LENGTH_TYPE_PERCENTAGE;
-	lsm_svg_animated_length_attribute_parse (&mask->x, &length);
-
-	length.value_unit = -10.0;
-	length.type = LSM_SVG_LENGTH_TYPE_PERCENTAGE;
-	lsm_svg_animated_length_attribute_parse (&mask->y, &length);
-
-	length.value_unit = 120.0;
-	length.type = LSM_SVG_LENGTH_TYPE_PERCENTAGE;
-	lsm_svg_animated_length_attribute_parse (&mask->width, &length);
-
-	length.value_unit = 120.0;
-	length.type = LSM_SVG_LENGTH_TYPE_PERCENTAGE;
-	lsm_svg_animated_length_attribute_parse (&mask->height, &length);
-
-	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
-}
-
-static void
-_mask_element_render_paint (LsmSvgElement *self, LsmSvgView *view)
+lsm_svg_mask_element_render (LsmSvgElement *self, LsmSvgView *view)
 {
 	LsmSvgMaskElement *mask = LSM_SVG_MASK_ELEMENT (self);
 	gboolean is_object_bounding_box;
 	LsmBox viewport;
 	const LsmBox *mask_extents;
+	LsmSvgStyle *style;
+
+	if (!mask->enable_rendering) {
+		lsm_debug ("[LsmSvgMaskElement::render] Direct rendering not allowed");
+		return;
+	} else {
+		mask->enable_rendering = FALSE;
+	}
+
+	style = lsm_svg_style_new_inherited (NULL, &self->property_bag);
+	lsm_svg_view_push_style (view, style);
 
 	mask_extents = lsm_svg_view_get_pattern_extents (view);
 
@@ -86,13 +65,13 @@ _mask_element_render_paint (LsmSvgElement *self, LsmSvgView *view)
 		lsm_svg_view_push_viewbox (view, &viewbox);
 	}
 
-	viewport.x      = lsm_svg_view_normalize_length (view, &mask->x.length.base,
+	viewport.x      = lsm_svg_view_normalize_length (view, &mask->x.length,
 							 LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
-	viewport.y      = lsm_svg_view_normalize_length (view, &mask->y.length.base,
+	viewport.y      = lsm_svg_view_normalize_length (view, &mask->y.length,
 							 LSM_SVG_LENGTH_DIRECTION_VERTICAL);
-	viewport.width  = lsm_svg_view_normalize_length (view, &mask->width.length.base,
+	viewport.width  = lsm_svg_view_normalize_length (view, &mask->width.length,
 							 LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
-	viewport.height = lsm_svg_view_normalize_length (view, &mask->height.length.base,
+	viewport.height = lsm_svg_view_normalize_length (view, &mask->height.length,
 							 LSM_SVG_LENGTH_DIRECTION_VERTICAL);
 
 	if (is_object_bounding_box) {
@@ -107,7 +86,7 @@ _mask_element_render_paint (LsmSvgElement *self, LsmSvgView *view)
 	if (viewport.width <= 0.0 || viewport.height <= 0.0)
 		return;
 
-	lsm_debug ("[LsmSvgMaskElement::render_paint] Create mask x = %g, y = %g, w = %g, h = %g",
+	lsm_debug ("[LsmSvgMaskElement::render] Create mask x = %g, y = %g, w = %g, h = %g",
 		   viewport.x, viewport.y, viewport.width, viewport.height);
 
 	lsm_svg_view_create_surface_pattern (view, &viewport,
@@ -126,7 +105,7 @@ _mask_element_render_paint (LsmSvgElement *self, LsmSvgView *view)
 		lsm_svg_view_push_viewbox (view, &viewbox);
 		lsm_svg_view_push_matrix (view, &matrix);
 
-		lsm_debug ("[LsmSvgMaskElement::render_paint] object_bounding_box"
+		lsm_debug ("[LsmSvgMaskElement::render] object_bounding_box"
 			   " x_scale = %g, y_scale = %g, x_offset = %g, y_offset = %g",
 			   mask_extents->width, mask_extents->height,
 			   mask_extents->x, mask_extents->y);
@@ -138,6 +117,15 @@ _mask_element_render_paint (LsmSvgElement *self, LsmSvgView *view)
 		lsm_svg_view_pop_matrix (view);
 		lsm_svg_view_pop_viewbox (view);
 	}
+
+	lsm_svg_view_pop_style (view);
+	lsm_svg_style_free (style);
+}
+
+static void
+lsm_svg_mask_element_enable_rendering (LsmSvgElement *element)
+{
+	LSM_SVG_MASK_ELEMENT (element)->enable_rendering  = TRUE;
 }
 
 /* LsmSvgMaskElement implementation */
@@ -148,22 +136,64 @@ lsm_svg_mask_element_new (void)
 	return g_object_new (LSM_TYPE_SVG_MASK_ELEMENT, NULL);
 }
 
+static const LsmSvgLength x_y_default = 	{ .value_unit = -10.0, .type = LSM_SVG_LENGTH_TYPE_PERCENTAGE};
+static const LsmSvgLength width_height_default ={ .value_unit = 120.0, .type = LSM_SVG_LENGTH_TYPE_PERCENTAGE};
+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 void
 lsm_svg_mask_element_init (LsmSvgMaskElement *self)
 {
-	/* Hack - Force the creation of the attribute bags,
-	   making sure the properties will be inherited from the
-	   mask element ancestor, not the referencing one. */
-
-	lsm_dom_element_set_attribute (LSM_DOM_ELEMENT (self), "fill", NULL);
-	lsm_dom_element_set_attribute (LSM_DOM_ELEMENT (self), "stroke", NULL);
-	lsm_dom_element_set_attribute (LSM_DOM_ELEMENT (self), "transform", NULL);
-	lsm_dom_element_set_attribute (LSM_DOM_ELEMENT (self), "font-family", NULL);
-	lsm_dom_element_set_attribute (LSM_DOM_ELEMENT (self), "stop-color", NULL);
+	self->enable_rendering = FALSE;
+	self->x.length = x_y_default;
+	self->y.length = x_y_default;
+	self->width.length = width_height_default;
+	self->height.length = width_height_default;
+	self->units.value = units_default;
+	self->content_units.value = content_units_default;
 }
 
 /* LsmSvgMaskElement class */
 
+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 = &x_y_default
+	},
+	{
+		.name = "y",
+		.attribute_offset = offsetof (LsmSvgMaskElement, y),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &x_y_default
+	},
+	{
+		.name = "width",
+		.attribute_offset = offsetof (LsmSvgMaskElement, width),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &width_height_default
+	},
+	{
+		.name = "height",
+		.attribute_offset = offsetof (LsmSvgMaskElement, height),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &width_height_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 +204,13 @@ 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->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->render = lsm_svg_mask_element_render;
+	s_element_class->enable_rendering = lsm_svg_mask_element_enable_rendering;
+	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);
 }
 
-G_DEFINE_TYPE (LsmSvgMaskElement, lsm_svg_mask_element, LSM_TYPE_SVG_GRAPHIC)
+G_DEFINE_TYPE (LsmSvgMaskElement, lsm_svg_mask_element, LSM_TYPE_SVG_ELEMENT)
diff --git a/src/lsmsvgmaskelement.h b/src/lsmsvgmaskelement.h
index c51338a..fe6a81e 100644
--- a/src/lsmsvgmaskelement.h
+++ b/src/lsmsvgmaskelement.h
@@ -23,7 +23,7 @@
 #define LSM_SVG_MASK_ELEMENT_H
 
 #include <lsmsvg.h>
-#include <lsmsvggraphic.h>
+#include <lsmsvgelement.h>
 
 G_BEGIN_DECLS
 
@@ -37,18 +37,20 @@ G_BEGIN_DECLS
 typedef struct _LsmSvgMaskElementClass LsmSvgMaskElementClass;
 
 struct _LsmSvgMaskElement {
-	LsmSvgGraphic graphic;
-
-	LsmSvgAnimatedLengthAttribute	x;
-	LsmSvgAnimatedLengthAttribute	y;
-	LsmSvgAnimatedLengthAttribute	width;
-	LsmSvgAnimatedLengthAttribute	height;
-	LsmDomEnumAttribute 		units;
-	LsmDomEnumAttribute 		content_units;
+	LsmSvgElement element;
+
+	LsmSvgLengthAttribute		x;
+	LsmSvgLengthAttribute		y;
+	LsmSvgLengthAttribute		width;
+	LsmSvgLengthAttribute		height;
+	LsmSvgPatternUnitsAttribute	units;
+	LsmSvgPatternUnitsAttribute	content_units;
+
+	gboolean enable_rendering;
 };
 
 struct _LsmSvgMaskElementClass {
-	LsmSvgGraphicClass  parent_class;
+	LsmSvgElementClass  element_class;
 };
 
 GType lsm_svg_mask_element_get_type (void);
diff --git a/src/lsmsvgmatrix.c b/src/lsmsvgmatrix.c
index 99edea5..214544e 100644
--- a/src/lsmsvgmatrix.c
+++ b/src/lsmsvgmatrix.c
@@ -22,6 +22,12 @@
 #include <lsmsvgmatrix.h>
 #include <math.h>
 
+gboolean
+lsm_svg_matrix_is_identity (const LsmSvgMatrix *matrix)
+{
+	return ((matrix->flags & LSM_SVG_MATRIX_FLAGS_IDENTITY) != 0);
+}
+
 void
 lsm_svg_matrix_init (LsmSvgMatrix *matrix, double a, double b, double c, double d, double e, double f)
 {
@@ -31,12 +37,14 @@ lsm_svg_matrix_init (LsmSvgMatrix *matrix, double a, double b, double c, double
 	matrix->d = d;
 	matrix->e = e;
 	matrix->f = f;
+	matrix->flags = 0;
 }
 
 void
 lsm_svg_matrix_init_identity (LsmSvgMatrix *matrix)
 {
 	lsm_svg_matrix_init (matrix, 1, 0, 0, 1, 0, 0);
+	matrix->flags |= LSM_SVG_MATRIX_FLAGS_IDENTITY;
 }
 
 void
@@ -125,6 +133,15 @@ lsm_svg_matrix_multiply (LsmSvgMatrix *result, const LsmSvgMatrix *a, const LsmS
 {
 	LsmSvgMatrix r;
 
+	if ((a->flags & LSM_SVG_MATRIX_FLAGS_IDENTITY) != 0) {
+		*result = *b;
+		return;
+	}
+	if ((b->flags & LSM_SVG_MATRIX_FLAGS_IDENTITY) != 0) {
+		*result = *a;
+		return;
+	}
+
 	r.a = a->a * b->a + a->b * b->c;
 	r.b = a->a * b->b + a->b * b->d;
 
@@ -134,6 +151,8 @@ lsm_svg_matrix_multiply (LsmSvgMatrix *result, const LsmSvgMatrix *a, const LsmS
 	r.e = a->e * b->a + a->f * b->c + b->e;
 	r.f = a->e * b->b + a->f * b->d + b->f;
 
+	r.flags = 0;
+
 	*result = r;
 }
 
@@ -143,6 +162,9 @@ lsm_svg_matrix_transform_point (const LsmSvgMatrix *matrix, double *x, double *y
 	double new_x;
 	double new_y;
 
+	if ((matrix->flags & LSM_SVG_MATRIX_FLAGS_IDENTITY) != 0)
+		return;
+
 	new_x = (matrix->a * *x + matrix->c * *y) + matrix->e;
 	new_y = (matrix->b * *x + matrix->d * *y) + matrix->f;
 
@@ -156,6 +178,9 @@ lsm_svg_matrix_transform_bounding_box (const LsmSvgMatrix *matrix, double *x1, d
 	double x12, y12, x21, y21;
 	double x_min, y_min, x_max, y_max;
 
+	if ((matrix->flags & LSM_SVG_MATRIX_FLAGS_IDENTITY) != 0)
+		return;
+
 	x12 = *x1;
 	y12 = *y2;
 	x21 = *x2;
diff --git a/src/lsmsvgmatrix.h b/src/lsmsvgmatrix.h
index 3a4cc5a..2fad642 100644
--- a/src/lsmsvgmatrix.h
+++ b/src/lsmsvgmatrix.h
@@ -24,10 +24,17 @@
 
 #include <lsmsvg.h>
 
+typedef enum {
+	LSM_SVG_MATRIX_FLAGS_IDENTITY = 1 << 0
+} LsmSvgMatrixFlags;
+
 typedef struct {
 	double a, b, c, d, e, f;
+	LsmSvgMatrixFlags flags;
 } LsmSvgMatrix;
 
+gboolean lsm_svg_matrix_is_identity (const LsmSvgMatrix *matrix);
+
 void 	lsm_svg_matrix_init 			(LsmSvgMatrix *matrix, double a, double b,
 					                               double c, double d,
 								       double e, double f);
diff --git a/src/lsmsvgpathelement.c b/src/lsmsvgpathelement.c
index e7e55d1..eb1d540 100644
--- a/src/lsmsvgpathelement.c
+++ b/src/lsmsvgpathelement.c
@@ -36,15 +36,15 @@ lsm_svg_path_element_get_node_name (LsmDomNode *node)
 /* LsmSvgGraphic implementation */
 
 static void
-lsm_svg_path_element_graphic_render (LsmSvgElement *self, LsmSvgView *view)
+lsm_svg_path_element_render (LsmSvgElement *self, LsmSvgView *view)
 {
 	LsmSvgPathElement *path;
 
 	path = LSM_SVG_PATH_ELEMENT (self);
 
-	lsm_debug ("[LsmSvgPathElement::graphic_render]");
+	lsm_debug ("[LsmSvgPathElement::render]");
 
-	lsm_svg_view_show_path (view, lsm_dom_attribute_get_value (&path->d));
+	lsm_svg_view_show_path (view, path->d.value);
 }
 
 /* LsmSvgPathElement implementation */
@@ -63,17 +63,25 @@ lsm_svg_path_element_init (LsmSvgPathElement *self)
 static void
 lsm_svg_path_element_finalize (GObject *object)
 {
+	parent_class->finalize (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)
 {
 	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);
 
 	parent_class = g_type_class_peek_parent (s_rect_class);
 
@@ -81,12 +89,12 @@ lsm_svg_path_element_class_init (LsmSvgPathElementClass *s_rect_class)
 
 	d_node_class->get_node_name = lsm_svg_path_element_get_node_name;
 
-	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->render = lsm_svg_path_element_render;
+	s_element_class->attribute_manager = lsm_attribute_manager_duplicate (s_element_class->attribute_manager);
 
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "d",
-					  offsetof (LsmSvgPathElement, d));
+	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);
 }
 
-G_DEFINE_TYPE (LsmSvgPathElement, lsm_svg_path_element, LSM_TYPE_SVG_GRAPHIC)
+G_DEFINE_TYPE (LsmSvgPathElement, lsm_svg_path_element, LSM_TYPE_SVG_ELEMENT)
diff --git a/src/lsmsvgpathelement.h b/src/lsmsvgpathelement.h
index 0e9afa0..cf34419 100644
--- a/src/lsmsvgpathelement.h
+++ b/src/lsmsvgpathelement.h
@@ -23,7 +23,7 @@
 #define LSM_SVG_PATH_ELEMENT_H
 
 #include <lsmsvg.h>
-#include <lsmsvggraphic.h>
+#include <lsmsvgelement.h>
 
 G_BEGIN_DECLS
 
@@ -37,14 +37,14 @@ G_BEGIN_DECLS
 typedef struct _LsmSvgPathElementClass LsmSvgPathElementClass;
 
 struct _LsmSvgPathElement {
-	LsmSvgGraphic graphic;
+	LsmSvgElement element;
 
-	LsmDomAttribute d;
-	LsmDomDoubleAttribute path_length;
+	LsmAttribute 		d;
+	LsmSvgDoubleAttribute 	path_length;
 };
 
 struct _LsmSvgPathElementClass {
-	LsmSvgGraphicClass  parent_class;
+	LsmSvgElementClass  element_class;
 };
 
 GType lsm_svg_path_element_get_type (void);
diff --git a/src/lsmsvgpatternelement.c b/src/lsmsvgpatternelement.c
index 551da38..4999c01 100644
--- a/src/lsmsvgpatternelement.c
+++ b/src/lsmsvgpatternelement.c
@@ -37,50 +37,25 @@ _pattern_element_get_node_name (LsmDomNode *node)
 /* LsmSvgElement implementation */
 
 static void
-_pattern_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
-{
-	LsmSvgPatternElement *pattern = LSM_SVG_PATTERN_ELEMENT (self);
-	LsmSvgPatternUnits units;
-	LsmSvgLength length;
-
-	units = LSM_SVG_PATTERN_UNITS_OBJECT_BOUNDING_BOX;
-	lsm_svg_pattern_units_attribute_parse (&pattern->units, &units);
-
-	units = LSM_SVG_PATTERN_UNITS_USER_SPACE_ON_USE;
-	lsm_svg_pattern_units_attribute_parse (&pattern->content_units, &units);
-
-	lsm_svg_transform_attribute_parse (&pattern->transform);
-
-	length.value_unit = 0.0;
-	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&pattern->x, &length);
-
-	length.value_unit = 0.0;
-	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&pattern->y, &length);
-
-	length.value_unit = 0.0;
-	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&pattern->width, &length);
-
-	length.value_unit = 0.0;
-	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&pattern->height, &length);
-
-	lsm_svg_viewbox_attribute_parse (&pattern->viewbox);
-	lsm_svg_preserve_aspect_ratio_attribute_parse (&pattern->preserve_aspect_ratio);
-
-	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
-}
-
-static void
-_pattern_element_render_paint (LsmSvgElement *self, LsmSvgView *view)
+lsm_svg_pattern_element_render (LsmSvgElement *self, LsmSvgView *view)
 {
 	LsmSvgPatternElement *pattern = LSM_SVG_PATTERN_ELEMENT (self);
 	gboolean is_object_bounding_box;
 	gboolean is_viewbox_defined;
 	LsmBox viewport;
 	const LsmBox *pattern_extents;
+	LsmSvgStyle *style;
+
+	if (!pattern->enable_rendering) {
+		lsm_debug ("[LsmSvgPatternElement::render] Direct rendering not allowed");
+		return;
+	} else {
+		pattern->enable_rendering = FALSE;
+	}
+
+
+	style = lsm_svg_style_new_inherited (NULL, &self->property_bag);
+	lsm_svg_view_push_style (view, style);
 
 	pattern_extents = lsm_svg_view_get_pattern_extents (view);
 
@@ -92,13 +67,13 @@ _pattern_element_render_paint (LsmSvgElement *self, LsmSvgView *view)
 		lsm_svg_view_push_viewbox (view, &viewbox);
 	}
 
-	viewport.x      = lsm_svg_view_normalize_length (view, &pattern->x.length.base,
+	viewport.x      = lsm_svg_view_normalize_length (view, &pattern->x.length,
 							 LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
-	viewport.y      = lsm_svg_view_normalize_length (view, &pattern->y.length.base,
+	viewport.y      = lsm_svg_view_normalize_length (view, &pattern->y.length,
 							 LSM_SVG_LENGTH_DIRECTION_VERTICAL);
-	viewport.width  = lsm_svg_view_normalize_length (view, &pattern->width.length.base,
+	viewport.width  = lsm_svg_view_normalize_length (view, &pattern->width.length,
 							 LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
-	viewport.height = lsm_svg_view_normalize_length (view, &pattern->height.length.base,
+	viewport.height = lsm_svg_view_normalize_length (view, &pattern->height.length,
 							 LSM_SVG_LENGTH_DIRECTION_VERTICAL);
 
 	if (is_object_bounding_box) {
@@ -113,7 +88,7 @@ _pattern_element_render_paint (LsmSvgElement *self, LsmSvgView *view)
 	if (viewport.width <= 0.0 || viewport.height <= 0.0)
 		return;
 
-	lsm_debug ("[LsmSvgPatternElement::render_paint] Create pattern x = %g, y = %g, w = %g, h = %g",
+	lsm_debug ("[LsmSvgPatternElement::render] Create pattern x = %g, y = %g, w = %g, h = %g",
 		   viewport.x, viewport.y, viewport.width, viewport.height);
 
 	lsm_svg_view_create_surface_pattern (view, &viewport,
@@ -133,13 +108,13 @@ _pattern_element_render_paint (LsmSvgElement *self, LsmSvgView *view)
 		lsm_svg_view_push_viewbox (view, &viewbox);
 		lsm_svg_view_push_matrix (view, &matrix);
 
-		lsm_debug ("[LsmSvgPatternElement::render_paint] object_bounding_box"
+		lsm_debug ("[LsmSvgPatternElement::render] object_bounding_box"
 			   " x_scale = %g, y_scale = %g, x_offset = %g, y_offset = %g",
 			   pattern_extents->width, pattern_extents->height,
 			   pattern_extents->x,     pattern_extents->y);
 	}
 
-	is_viewbox_defined = lsm_dom_attribute_is_defined ((LsmDomAttribute *) &pattern->viewbox);
+	is_viewbox_defined = lsm_attribute_is_defined (&pattern->viewbox.base);
 
 	if (!(is_viewbox_defined) ||
 	    (is_viewbox_defined && pattern->viewbox.value.width > 0.0 && pattern->viewbox.value.height > 0.0)) {
@@ -156,6 +131,15 @@ _pattern_element_render_paint (LsmSvgElement *self, LsmSvgView *view)
 		lsm_svg_view_pop_matrix (view);
 		lsm_svg_view_pop_viewbox (view);
 	}
+
+	lsm_svg_view_pop_style (view);
+	lsm_svg_style_free (style);
+}
+
+static void
+lsm_svg_pattern_element_enable_rendering (LsmSvgElement *element)
+{
+	LSM_SVG_PATTERN_ELEMENT (element)->enable_rendering  = TRUE;
 }
 
 /* LsmSvgPatternElement implementation */
@@ -166,22 +150,95 @@ lsm_svg_pattern_element_new (void)
 	return g_object_new (LSM_TYPE_SVG_PATTERN_ELEMENT, NULL);
 }
 
+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, LSM_SVG_MATRIX_FLAGS_IDENTITY};
+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 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 void
 lsm_svg_pattern_element_init (LsmSvgPatternElement *self)
 {
-	/* Hack - Force the creation of the attribute bags,
-	   making sure the properties will be inherited from the
-	   pattern element ancestor, not the referencing one. */
-
-	lsm_dom_element_set_attribute (LSM_DOM_ELEMENT (self), "fill", NULL);
-	lsm_dom_element_set_attribute (LSM_DOM_ELEMENT (self), "stroke", NULL);
-	lsm_dom_element_set_attribute (LSM_DOM_ELEMENT (self), "transform", NULL);
-	lsm_dom_element_set_attribute (LSM_DOM_ELEMENT (self), "font-family", NULL);
-	lsm_dom_element_set_attribute (LSM_DOM_ELEMENT (self), "stop-color", NULL);
+	self->enable_rendering = FALSE;
+	self->x.length = length_default;
+	self->y.length = length_default;
+	self->width.length = length_default;
+	self->height.length = length_default;
+	self->transform.matrix = matrix_default;
+	self->units.value = units_default;
+	self->content_units.value = content_units_default;
+	self->preserve_aspect_ratio.value = preserve_aspect_ratio_default;
 }
 
 /* LsmSvgPatternElement class */
 
+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)
 {
@@ -192,32 +249,13 @@ lsm_svg_pattern_element_class_init (LsmSvgPatternElementClass *klass)
 
 	d_node_class->get_node_name = _pattern_element_get_node_name;
 
-	s_element_class->update = _pattern_element_update;
-	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->render = lsm_svg_pattern_element_render;
+	s_element_class->enable_rendering = lsm_svg_pattern_element_enable_rendering;
+	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);
 }
 
-G_DEFINE_TYPE (LsmSvgPatternElement, lsm_svg_pattern_element, LSM_TYPE_SVG_GRAPHIC)
+G_DEFINE_TYPE (LsmSvgPatternElement, lsm_svg_pattern_element, LSM_TYPE_SVG_ELEMENT)
diff --git a/src/lsmsvgpatternelement.h b/src/lsmsvgpatternelement.h
index b2c17bd..6c717a4 100644
--- a/src/lsmsvgpatternelement.h
+++ b/src/lsmsvgpatternelement.h
@@ -23,7 +23,7 @@
 #define LSM_SVG_PATTERN_ELEMENT_H
 
 #include <lsmsvg.h>
-#include <lsmsvggraphic.h>
+#include <lsmsvgelement.h>
 
 G_BEGIN_DECLS
 
@@ -37,23 +37,25 @@ G_BEGIN_DECLS
 typedef struct _LsmSvgPatternElementClass LsmSvgPatternElementClass;
 
 struct _LsmSvgPatternElement {
-	LsmSvgGraphic graphic;
+	LsmSvgElement element;
 
-	LsmSvgAnimatedLengthAttribute	x;
-	LsmSvgAnimatedLengthAttribute	y;
-	LsmSvgAnimatedLengthAttribute	width;
-	LsmSvgAnimatedLengthAttribute	height;
+	LsmSvgLengthAttribute		x;
+	LsmSvgLengthAttribute		y;
+	LsmSvgLengthAttribute		width;
+	LsmSvgLengthAttribute		height;
 	LsmSvgTransformAttribute 	transform;
-	LsmDomEnumAttribute 		units;
-	LsmDomEnumAttribute 		content_units;
-	LsmDomAttribute 		href;
+	LsmSvgPatternUnitsAttribute	units;
+	LsmSvgPatternUnitsAttribute	content_units;
+	LsmAttribute 			href;
 
 	LsmSvgViewboxAttribute	viewbox;
 	LsmSvgPreserveAspectRatioAttribute	preserve_aspect_ratio;
+
+	gboolean enable_rendering;
 };
 
 struct _LsmSvgPatternElementClass {
-	LsmSvgGraphicClass  parent_class;
+	LsmSvgElementClass  element_class;
 };
 
 GType lsm_svg_pattern_element_get_type (void);
diff --git a/src/lsmsvgpolygonelement.c b/src/lsmsvgpolygonelement.c
index a560e6f..fde87d0 100644
--- a/src/lsmsvgpolygonelement.c
+++ b/src/lsmsvgpolygonelement.c
@@ -37,7 +37,7 @@ lsm_svg_polygon_element_get_node_name (LsmDomNode *node)
 /* LsmSvgGraphic implementation */
 
 static void
-lsm_svg_polygon_element_graphic_render (LsmSvgElement *self, LsmSvgView *view)
+lsm_svg_polygon_element_render (LsmSvgElement *self, LsmSvgView *view)
 {
 	LsmSvgPolygonElement *polygon = LSM_SVG_POLYGON_ELEMENT (self);
 
@@ -59,23 +59,30 @@ 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)
 {
 	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);
 
 	parent_class = g_type_class_peek_parent (s_rect_class);
 
 	d_node_class->get_node_name = lsm_svg_polygon_element_get_node_name;
 
-	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->render = lsm_svg_polygon_element_render;
+	s_element_class->attribute_manager = lsm_attribute_manager_duplicate (s_element_class->attribute_manager);
 
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "points",
-					  offsetof (LsmSvgPolygonElement, points));
+	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);
 }
 
-G_DEFINE_TYPE (LsmSvgPolygonElement, lsm_svg_polygon_element, LSM_TYPE_SVG_GRAPHIC)
+G_DEFINE_TYPE (LsmSvgPolygonElement, lsm_svg_polygon_element, LSM_TYPE_SVG_ELEMENT)
diff --git a/src/lsmsvgpolygonelement.h b/src/lsmsvgpolygonelement.h
index e9bb558..90db664 100644
--- a/src/lsmsvgpolygonelement.h
+++ b/src/lsmsvgpolygonelement.h
@@ -23,7 +23,7 @@
 #define LSM_SVG_POLYGON_ELEMENT_H
 
 #include <lsmsvg.h>
-#include <lsmsvggraphic.h>
+#include <lsmsvgelement.h>
 
 G_BEGIN_DECLS
 
@@ -37,13 +37,13 @@ G_BEGIN_DECLS
 typedef struct _LsmSvgPolygonElementClass LsmSvgPolygonElementClass;
 
 struct _LsmSvgPolygonElement {
-	LsmSvgGraphic graphic;
+	LsmSvgElement element;
 
-	LsmDomAttribute	points;
+	LsmAttribute	points;
 };
 
 struct _LsmSvgPolygonElementClass {
-	LsmSvgGraphicClass  parent_class;
+	LsmSvgElementClass  element_class;
 };
 
 GType lsm_svg_polygon_element_get_type (void);
diff --git a/src/lsmsvgpolylineelement.c b/src/lsmsvgpolylineelement.c
index 0facb9a..821e7b0 100644
--- a/src/lsmsvgpolylineelement.c
+++ b/src/lsmsvgpolylineelement.c
@@ -37,7 +37,7 @@ lsm_svg_polyline_element_get_node_name (LsmDomNode *node)
 /* LsmSvgGraphic implementation */
 
 static void
-lsm_svg_polyline_element_graphic_render (LsmSvgElement *self, LsmSvgView *view)
+lsm_svg_polyline_element_render (LsmSvgElement *self, LsmSvgView *view)
 {
 	LsmSvgPolylineElement *polyline = LSM_SVG_POLYLINE_ELEMENT (self);
 
@@ -59,23 +59,30 @@ 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)
 {
 	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);
 
 	parent_class = g_type_class_peek_parent (s_rect_class);
 
 	d_node_class->get_node_name = lsm_svg_polyline_element_get_node_name;
 
-	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->render = lsm_svg_polyline_element_render;
+	s_element_class->attribute_manager = lsm_attribute_manager_duplicate (s_element_class->attribute_manager);
 
-	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "points",
-					  offsetof (LsmSvgPolylineElement, points));
+	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);
 }
 
-G_DEFINE_TYPE (LsmSvgPolylineElement, lsm_svg_polyline_element, LSM_TYPE_SVG_GRAPHIC)
+G_DEFINE_TYPE (LsmSvgPolylineElement, lsm_svg_polyline_element, LSM_TYPE_SVG_ELEMENT)
diff --git a/src/lsmsvgpolylineelement.h b/src/lsmsvgpolylineelement.h
index c4c15f2..a96fc6a 100644
--- a/src/lsmsvgpolylineelement.h
+++ b/src/lsmsvgpolylineelement.h
@@ -23,7 +23,7 @@
 #define LSM_SVG_POLYLINE_ELEMENT_H
 
 #include <lsmsvg.h>
-#include <lsmsvggraphic.h>
+#include <lsmsvgelement.h>
 
 G_BEGIN_DECLS
 
@@ -37,13 +37,13 @@ G_BEGIN_DECLS
 typedef struct _LsmSvgPolylineElementClass LsmSvgPolylineElementClass;
 
 struct _LsmSvgPolylineElement {
-	LsmSvgGraphic graphic;
+	LsmSvgElement element;
 
-	LsmDomAttribute	points;
+	LsmAttribute	points;
 };
 
 struct _LsmSvgPolylineElementClass {
-	LsmSvgGraphicClass  parent_class;
+	LsmSvgElementClass  element_class;
 };
 
 GType lsm_svg_polyline_element_get_type (void);
diff --git a/src/lsmsvgradialgradientelement.c b/src/lsmsvgradialgradientelement.c
index a219369..daa569c 100644
--- a/src/lsmsvgradialgradientelement.c
+++ b/src/lsmsvgradialgradientelement.c
@@ -35,37 +35,10 @@ lsm_svg_radial_gradient_element_get_node_name (LsmDomNode *node)
 	return "radialGradient";
 }
 
-/* GRadialGradientElement implementation */
-
-static void
-_radial_gradient_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
-{
-	LsmSvgRadialGradientElement *radial = LSM_SVG_RADIAL_GRADIENT_ELEMENT (self);
-	LsmSvgLength length;
-
-	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
-
-	length.value_unit = 50.0;
-	length.type = LSM_SVG_LENGTH_TYPE_PERCENTAGE;
-	lsm_svg_animated_length_attribute_parse (&radial->cx, &length);
-
-	length.value_unit = 50.0;
-	length.type = LSM_SVG_LENGTH_TYPE_PERCENTAGE;
-	lsm_svg_animated_length_attribute_parse (&radial->cy, &length);
-
-	length.value_unit = 50.0;
-	length.type = LSM_SVG_LENGTH_TYPE_PERCENTAGE;
-	lsm_svg_animated_length_attribute_parse (&radial->r, &length);
-
-	length = radial->cx.length.base;
-	lsm_svg_animated_length_attribute_parse (&radial->fx, &length);
-
-	length = radial->cy.length.base;
-	lsm_svg_animated_length_attribute_parse (&radial->fy, &length);
-}
+/* LsmSvgRadialGradientElement implementation */
 
 static void
-_radial_gradient_element_render_paint (LsmSvgElement *self, LsmSvgView *view)
+lsm_svg_radial_gradient_element_create_gradient (LsmSvgElement *self, LsmSvgView *view)
 {
 	LsmSvgRadialGradientElement *radial = LSM_SVG_RADIAL_GRADIENT_ELEMENT (self);
 	gboolean is_object_bounding_box;
@@ -81,11 +54,19 @@ _radial_gradient_element_render_paint (LsmSvgElement *self, LsmSvgView *view)
 		lsm_svg_view_push_viewbox (view, &viewbox);
 	}
 
-	cx = lsm_svg_view_normalize_length (view, &radial->cx.length.base, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
-	cy = lsm_svg_view_normalize_length (view, &radial->cy.length.base, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
-	r  = lsm_svg_view_normalize_length (view, &radial->r.length.base,  LSM_SVG_LENGTH_DIRECTION_DIAGONAL);
-	fx = lsm_svg_view_normalize_length (view, &radial->fx.length.base, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
-	fy = lsm_svg_view_normalize_length (view, &radial->fy.length.base, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
+	cx = lsm_svg_view_normalize_length (view, &radial->cx.length, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
+	cy = lsm_svg_view_normalize_length (view, &radial->cy.length, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
+	r  = lsm_svg_view_normalize_length (view, &radial->r.length,  LSM_SVG_LENGTH_DIRECTION_DIAGONAL);
+
+	if (lsm_attribute_is_defined (&radial->fx.base))
+		fx = lsm_svg_view_normalize_length (view, &radial->fx.length, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
+	else
+		fx = cx;
+
+	if (lsm_attribute_is_defined (&radial->fy.base))
+		fy = lsm_svg_view_normalize_length (view, &radial->fy.length, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
+	else
+		fy = cy;
 
 	gradient_radius = sqrt ((fx - cx) * (fx - cx) + (fy - cy) * (fy - cy));
 	if (gradient_radius > r) {
@@ -105,8 +86,6 @@ _radial_gradient_element_render_paint (LsmSvgElement *self, LsmSvgView *view)
 		    cx, cy, r, fx, fy);
 
 	lsm_svg_view_create_radial_gradient (view, cx, cy, r, fx, fy);
-
-	LSM_SVG_ELEMENT_CLASS (parent_class)->render_paint (self, view);
 }
 
 /* LsmSvgRadialGradientElement implementation */
@@ -117,25 +96,67 @@ lsm_svg_radial_gradient_element_new (void)
 	return g_object_new (LSM_TYPE_SVG_RADIAL_GRADIENT_ELEMENT, NULL);
 }
 
+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 void
 lsm_svg_radial_gradient_element_init (LsmSvgRadialGradientElement *self)
 {
-
+	self->cx.length = length_default;
+	self->cy.length = length_default;
+	self->r.length = length_default;
+	self->fx.length = unset_default;
+	self->fy.length = unset_default;
 }
 
 static void
 lsm_svg_radial_gradient_element_finalize (GObject *object)
 {
+	parent_class->finalize (object);
 }
 
 /* LsmSvgRadialGradientElement class */
 
+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)
 {
 	GObjectClass *object_class = G_OBJECT_CLASS (s_svg_class);
 	LsmDomNodeClass *d_node_class = LSM_DOM_NODE_CLASS (s_svg_class);
 	LsmSvgElementClass *s_element_class = LSM_SVG_ELEMENT_CLASS (s_svg_class);
+	LsmSvgGradientElementClass *s_gradient_class = LSM_SVG_GRADIENT_ELEMENT_CLASS (s_svg_class);
 
 	parent_class = g_type_class_peek_parent (s_svg_class);
 
@@ -143,21 +164,13 @@ 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->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_gradient_class->create_gradient = lsm_svg_radial_gradient_element_create_gradient;
 }
 
 G_DEFINE_TYPE (LsmSvgRadialGradientElement, lsm_svg_radial_gradient_element, LSM_TYPE_SVG_GRADIENT_ELEMENT)
diff --git a/src/lsmsvgradialgradientelement.h b/src/lsmsvgradialgradientelement.h
index 6be6a7c..47ae183 100644
--- a/src/lsmsvgradialgradientelement.h
+++ b/src/lsmsvgradialgradientelement.h
@@ -39,11 +39,11 @@ typedef struct _LsmSvgRadialGradientElementClass LsmSvgRadialGradientElementClas
 struct _LsmSvgRadialGradientElement {
 	LsmSvgGradientElement gradient;
 
-	LsmSvgAnimatedLengthAttribute	cx;
-	LsmSvgAnimatedLengthAttribute	cy;
-	LsmSvgAnimatedLengthAttribute	r;
-	LsmSvgAnimatedLengthAttribute	fx;
-	LsmSvgAnimatedLengthAttribute	fy;
+	LsmSvgLengthAttribute	cx;
+	LsmSvgLengthAttribute	cy;
+	LsmSvgLengthAttribute	r;
+	LsmSvgLengthAttribute	fx;
+	LsmSvgLengthAttribute	fy;
 };
 
 struct _LsmSvgRadialGradientElementClass {
diff --git a/src/lsmsvgrectelement.c b/src/lsmsvgrectelement.c
index b039e9c..c743fb1 100644
--- a/src/lsmsvgrectelement.c
+++ b/src/lsmsvgrectelement.c
@@ -34,79 +34,46 @@ lsm_svg_rect_element_get_node_name (LsmDomNode *node)
 
 /* LsmSvgElement implementation */
 
-static void
-lsm_svg_rect_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
-{
-	LsmSvgRectElement *rect = LSM_SVG_RECT_ELEMENT (self);
-	LsmSvgLength length;
-
-	length.value_unit = 0.0;
-	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&rect->x, &length);
-
-	length.value_unit = 0.0;
-	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&rect->y, &length);
-
-	length.value_unit = 0.0;
-	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&rect->width, &length);
-
-	length.value_unit = 0.0;
-	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&rect->height, &length);
-
-	length.value_unit = 0.0;
-	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&rect->rx, &length);
-
-	length.value_unit = 0.0;
-	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&rect->ry, &length);
-
-	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
-}
-
 /* LsmSvgGraphic implementation */
 
 static void
-lsm_svg_rect_element_graphic_render (LsmSvgElement *self, LsmSvgView *view)
+lsm_svg_rect_element_render (LsmSvgElement *self, LsmSvgView *view)
 {
 	LsmSvgRectElement *rect = LSM_SVG_RECT_ELEMENT (self);
 	double x, y;
 	double rx, ry;
 	double w, h;
 
-	x = lsm_svg_view_normalize_length (view, &rect->x.length.base, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
-	y = lsm_svg_view_normalize_length (view, &rect->y.length.base, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
-	rx = lsm_svg_view_normalize_length (view, &rect->rx.length.base, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
-	ry = lsm_svg_view_normalize_length (view, &rect->ry.length.base, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
-	w = lsm_svg_view_normalize_length (view, &rect->width.length.base, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
-	h = lsm_svg_view_normalize_length (view, &rect->height.length.base, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
+	x = lsm_svg_view_normalize_length (view, &rect->x.length, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
+	y = lsm_svg_view_normalize_length (view, &rect->y.length, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
+	rx = lsm_svg_view_normalize_length (view, &rect->rx.length, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
+	ry = lsm_svg_view_normalize_length (view, &rect->ry.length, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
+	w = lsm_svg_view_normalize_length (view, &rect->width.length, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
+	h = lsm_svg_view_normalize_length (view, &rect->height.length, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
 
 	/* SVG specification is so weird sometimes ... */
 	if (w == 0.0 || h == 0.0)
 		return;
 
-	if (!lsm_dom_attribute_is_defined (&rect->rx.attr))
+	if (!lsm_attribute_is_defined (&rect->rx.base))
 		rx = ry;
-	else if (!lsm_dom_attribute_is_defined (&rect->ry.attr))
+	else if (!lsm_attribute_is_defined (&rect->ry.base))
 		ry = rx;
 
 	lsm_svg_view_show_rectangle (view, x, y, w, h, rx, ry);
 }
 
 static void
-lsm_svg_rect_element_graphic_get_extents (LsmSvgElement *self, LsmSvgView *view, LsmExtents *extents)
+lsm_svg_rect_element_get_extents (LsmSvgElement *self, LsmSvgView *view, LsmExtents *extents)
 {
 	LsmSvgRectElement *rect = LSM_SVG_RECT_ELEMENT (self);
 	double x, y;
 	double w, h;
 
-	x = lsm_svg_view_normalize_length (view, &rect->x.length.base, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
-	y = lsm_svg_view_normalize_length (view, &rect->y.length.base, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
-	w = lsm_svg_view_normalize_length (view, &rect->width.length.base, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
-	h = lsm_svg_view_normalize_length (view, &rect->height.length.base, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
+	x = lsm_svg_view_normalize_length (view, &rect->x.length, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
+	y = lsm_svg_view_normalize_length (view, &rect->y.length, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
+	w = lsm_svg_view_normalize_length (view, &rect->width.length, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
+	h = lsm_svg_view_normalize_length (view, &rect->height.length, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
 
 	extents->x1 = x;
 	extents->y1 = y;
@@ -122,25 +89,73 @@ lsm_svg_rect_element_new (void)
 	return g_object_new (LSM_TYPE_SVG_RECT_ELEMENT, NULL);
 }
 
+static const LsmSvgLength length_default = 	 { .value_unit =   0.0, .type = LSM_SVG_LENGTH_TYPE_PX};
+static const LsmSvgLength unset_length_default = { .value_unit =   0.0, .type = LSM_SVG_LENGTH_TYPE_UNKNOWN};
+
 static void
 lsm_svg_rect_element_init (LsmSvgRectElement *self)
 {
+	self->x.length = length_default;
+	self->y.length = length_default;
+	self->width.length = length_default;
+	self->height.length = length_default;
+	self->rx.length = unset_length_default;
+	self->ry.length = unset_length_default;
 }
 
 static void
 lsm_svg_rect_element_finalize (GObject *object)
 {
+	parent_class->finalize (object);
 }
 
 /* LsmSvgRectElement class */
 
+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 = &unset_length_default
+	},
+	{
+		.name = "ry",
+		.attribute_offset = offsetof (LsmSvgRectElement, ry),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = &unset_length_default
+	}
+};
+
 static void
 lsm_svg_rect_element_class_init (LsmSvgRectElementClass *s_rect_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);
 
 	parent_class = g_type_class_peek_parent (s_rect_class);
 
@@ -148,25 +163,13 @@ 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_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->render = lsm_svg_rect_element_render;
+	s_element_class->get_extents = lsm_svg_rect_element_get_extents;
+	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);
 }
 
-G_DEFINE_TYPE (LsmSvgRectElement, lsm_svg_rect_element, LSM_TYPE_SVG_GRAPHIC)
+G_DEFINE_TYPE (LsmSvgRectElement, lsm_svg_rect_element, LSM_TYPE_SVG_ELEMENT)
diff --git a/src/lsmsvgrectelement.h b/src/lsmsvgrectelement.h
index 9bf874a..0ec6552 100644
--- a/src/lsmsvgrectelement.h
+++ b/src/lsmsvgrectelement.h
@@ -23,7 +23,7 @@
 #define LSM_SVG_RECT_ELEMENT_H
 
 #include <lsmsvg.h>
-#include <lsmsvggraphic.h>
+#include <lsmsvgelement.h>
 
 G_BEGIN_DECLS
 
@@ -37,18 +37,18 @@ G_BEGIN_DECLS
 typedef struct _LsmSvgRectElementClass LsmSvgRectElementClass;
 
 struct _LsmSvgRectElement {
-	LsmSvgGraphic graphic;
-
-	LsmSvgAnimatedLengthAttribute	x;
-	LsmSvgAnimatedLengthAttribute	y;
-	LsmSvgAnimatedLengthAttribute	width;
-	LsmSvgAnimatedLengthAttribute	height;
-	LsmSvgAnimatedLengthAttribute	rx;
-	LsmSvgAnimatedLengthAttribute	ry;
+	LsmSvgElement element;
+
+	LsmSvgLengthAttribute	x;
+	LsmSvgLengthAttribute	y;
+	LsmSvgLengthAttribute	width;
+	LsmSvgLengthAttribute	height;
+	LsmSvgLengthAttribute	rx;
+	LsmSvgLengthAttribute	ry;
 };
 
 struct _LsmSvgRectElementClass {
-	LsmSvgGraphicClass  parent_class;
+	LsmSvgElementClass  element_class;
 };
 
 GType lsm_svg_rect_element_get_type (void);
diff --git a/src/lsmsvgstopelement.c b/src/lsmsvgstopelement.c
index efdd129..e50b7f3 100644
--- a/src/lsmsvgstopelement.c
+++ b/src/lsmsvgstopelement.c
@@ -38,51 +38,22 @@ lsm_svg_stop_element_get_node_name (LsmDomNode *node)
 /* LsmSvgElement implementation */
 
 static void
-_stop_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
+lsm_svg_stop_element_render (LsmSvgElement *element, LsmSvgView *view)
 {
-	LsmSvgStopElement *stop = LSM_SVG_STOP_ELEMENT (self);
-	LsmSvgLength length;
+	LsmSvgStopElement *stop = LSM_SVG_STOP_ELEMENT (element);
+	double offset;
 
-	length.type = LSM_SVG_LENGTH_TYPE_NUMBER;
-	lsm_svg_length_attribute_parse (&stop->offset, &length);
-
-	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
-}
-
-/* LsmSvgStopElement implementation */
-
-double
-lsm_svg_stop_element_get_offset (LsmSvgStopElement *self)
-{
-	g_return_val_if_fail (LSM_IS_SVG_STOP_ELEMENT (self), 0.0);
-
-	if (self->offset.length.type == LSM_SVG_LENGTH_TYPE_PERCENTAGE)
-		return self->offset.length.value_unit / 100.0;
+	if (stop->offset.length.type == LSM_SVG_LENGTH_TYPE_PERCENTAGE)
+		offset = stop->offset.length.value_unit / 100.0;
 	else
-		return self->offset.length.value_unit;
-}
+		offset = stop->offset.length.value_unit;
 
-const LsmSvgColor *
-lsm_svg_stop_element_get_color (LsmSvgStopElement *self)
-{
-	g_return_val_if_fail (LSM_IS_SVG_STOP_ELEMENT (self), &lsm_svg_color_null);
+	lsm_debug ("[LsmSvgStopElement::render] Add stop at %g", offset);
 
-	if (LSM_SVG_GRAPHIC(self)->stop != NULL)
-		return &(LSM_SVG_GRAPHIC (self)->stop->color.value);
-	else
-		return &lsm_svg_color_null;
+	lsm_svg_view_add_gradient_color_stop (view, offset);
 }
 
-double
-lsm_svg_stop_element_get_opacity (LsmSvgStopElement *self)
-{
-	g_return_val_if_fail (LSM_IS_SVG_STOP_ELEMENT (self), 1.0);
-
-	if (LSM_SVG_GRAPHIC(self)->stop != NULL)
-		return LSM_SVG_GRAPHIC (self)->stop->opacity.value;
-	else
-		return 1.0;
-}
+/* LsmSvgStopElement implementation */
 
 LsmDomNode *
 lsm_svg_stop_element_new (void)
@@ -90,13 +61,25 @@ lsm_svg_stop_element_new (void)
 	return g_object_new (LSM_TYPE_SVG_STOP_ELEMENT, NULL);
 }
 
+static const LsmSvgLength length_default = 	{ .value_unit =   0.0, .type = LSM_SVG_LENGTH_TYPE_NUMBER};
+
 static void
 lsm_svg_stop_element_init (LsmSvgStopElement *self)
 {
+	self->offset.length = length_default;
 }
 
 /* LsmSvgStopElement class */
 
+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 +90,13 @@ 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->render = lsm_svg_stop_element_render;
+	s_element_class->attribute_manager = lsm_attribute_manager_duplicate (s_element_class->attribute_manager);
 
-	s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
+	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);
 
-	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)
+G_DEFINE_TYPE (LsmSvgStopElement, lsm_svg_stop_element, LSM_TYPE_SVG_ELEMENT)
diff --git a/src/lsmsvgstopelement.h b/src/lsmsvgstopelement.h
index 0187c9c..7b17be4 100644
--- a/src/lsmsvgstopelement.h
+++ b/src/lsmsvgstopelement.h
@@ -23,7 +23,7 @@
 #define LSM_SVG_STOP_ELEMENT_H
 
 #include <lsmsvg.h>
-#include <lsmsvggraphic.h>
+#include <lsmsvgelement.h>
 
 G_BEGIN_DECLS
 
@@ -37,23 +37,19 @@ G_BEGIN_DECLS
 typedef struct _LsmSvgStopElementClass LsmSvgStopElementClass;
 
 struct _LsmSvgStopElement {
-	LsmSvgGraphic graphic;
+	LsmSvgElement element;
 
 	LsmSvgLengthAttribute offset;
 };
 
 struct _LsmSvgStopElementClass {
-	LsmSvgGraphicClass  parent_class;
+	LsmSvgElementClass  element_class;
 };
 
 GType lsm_svg_stop_element_get_type (void);
 
 LsmDomNode * lsm_svg_stop_element_new (void);
 
-double 			lsm_svg_stop_element_get_offset 	(LsmSvgStopElement *self);
-const LsmSvgColor *	lsm_svg_stop_element_get_color 		(LsmSvgStopElement *self);
-double 			lsm_svg_stop_element_get_opacity 	(LsmSvgStopElement *self);
-
 G_END_DECLS
 
 #endif
diff --git a/src/lsmsvgstyle.c b/src/lsmsvgstyle.c
index 8e98709..438aa26 100644
--- a/src/lsmsvgstyle.c
+++ b/src/lsmsvgstyle.c
@@ -20,7 +20,442 @@
  */
 
 #include <lsmsvgstyle.h>
+#include <lsmsvgcolors.h>
+#include <lsmsvgtraits.h>
+#include <lsmstr.h>
 #include <string.h>
+#include <math.h>
+
+static const LsmPropertyInfos lsm_svg_property_infos[] = {
+	{
+		.name = "alignment-baseline",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, alignment_baseline),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "auto" /* FIXME specification says "see property description" */
+	},
+	{
+		.name = "baseline-shift",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, baseline_shift),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "baseline"
+	},
+	{
+		.name = "clip",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, clip),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "auto"
+	},
+	{
+		.name = "clip-path",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, clip_path),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "none"
+	},
+	{
+		.name = "dominant-baseline",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, dominant_baseline),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "auto"
+	},
+	{
+		.name = "enable-background",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, enable_background),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "accumulate"
+	},
+	{
+		.name = "filter",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, filter),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "none"
+	},
+	{
+		.name = "flood-color",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, flood_color),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "black"
+	},
+	{
+		.name = "flood-opacity",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, flood_opacity),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "1"
+	},
+	{
+		.name = "lighting-color",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, lighting_color),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "white"
+	},
+	{
+		.name = "mask",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, mask),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "none"
+	},
+	{
+		.name = "opacity",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, opacity),
+		.trait_class = &lsm_double_trait_class,
+		.trait_default = "1"
+	},
+	{
+		.name = "overflow",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, overflow),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = ""
+	},
+	{
+		.name = "stop-color",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, stop_color),
+		.trait_class = &lsm_svg_color_trait_class,
+		.trait_default = "black"
+	},
+	{
+		.name = "stop-opacity",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, stop_opacity),
+		.trait_class = &lsm_double_trait_class,
+		.trait_default = "1"
+	},
+	{
+		.name = "text-decoration",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, text_decoration),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "none"
+	},
+	{
+		.name = "unicode-bidi",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, unicode_bidi),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "normal"
+	},
+	/* Inherited properties */
+	{
+		.name = "clip-rule",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, clip_rule),
+		.trait_class = &lsm_svg_fill_rule_trait_class,
+		.trait_default = "nonzero"
+	},
+	{
+		.name = "color",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, color),
+		.trait_class = &lsm_svg_color_trait_class,
+		.trait_default = "black" /* Depends on user agent */
+	},
+	{
+		.name = "color-interpolation",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, color_interpolation),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "sRGB"
+	},
+	{
+		.name = "color-interpolation-filters",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, color_interpolation_filters),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "linearRGB"
+	},
+	{
+		.name = "color-profile",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, color_profile),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "auto"
+	},
+	{
+		.name = "color-rendering",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, color_rendering),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "auto"
+	},
+	{
+		.name = "cursor",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, cursor),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "auto"
+	},
+	{
+		.name = "direction",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, direction),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "ltr"
+	},
+	{
+		.name = "display",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, display),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "inline"
+	},
+	{
+		.name = "fill",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, fill),
+		.trait_class = &lsm_svg_paint_trait_class,
+		.trait_default = "black"
+	},
+	{
+		.name = "fill-opacity",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, fill_opacity),
+		.trait_class = &lsm_double_trait_class,
+		.trait_default = "1"
+	},
+	{
+		.name = "fill-rule",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, fill_rule),
+		.trait_class = &lsm_svg_fill_rule_trait_class,
+		.trait_default = "nonzero"
+	},
+	{
+		.name = "font",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, font),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = NULL /* specification says "See individual properties" */
+	},
+	{
+		.name = "font-family",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, font_family),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "Sans" /* Depends on user agent */
+	},
+	{
+		.name = "font-size",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, font_size),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = "10pt" /* FIXME Specification says "medium" */
+	},
+	{
+		.name = "font-size-adjust",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, font_size_adjust),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "none"
+	},
+	{
+		.name = "font-stretch",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, font_stretch),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "normal"
+	},
+	{
+		.name = "font-style",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, font_style),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "normal"
+	},
+	{
+		.name = "font-variant",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, font_variant),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "normal"
+	},
+	{
+		.name = "font-weight",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, font_weight),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "normal"
+	},
+	{
+		.name = "glyph-orientation-horizontal",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, glyph_orientation_horizontal),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "0deg"
+	},
+	{
+		.name = "glyph-orientation-vertical",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, glyph_orientation_vertical),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "auto"
+	},
+	{
+		.name = "image-rendering",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, image_rendering),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "auto"
+	},
+	{
+		.name = "kerning",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, kerning),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "auto"
+	},
+	{
+		.name = "letter-spacing",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, letter_spacing),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "normal"
+	},
+	{
+		.name = "marker",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, marker),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "none"
+	},
+	{
+		.name = "marker-end",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, marker_end),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "none"
+	},
+	{
+		.name = "marker-mid",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, marker_mid),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "none"
+	},
+	{
+		.name = "marker-start",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, marker_start),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "none"
+	},
+	{
+		.name = "pointer-events",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, pointer_events),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "visiblePainted"
+	},
+	{
+		.name = "shape-rendering",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, shape_rendering),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "auto"
+	},
+	{
+		.name = "stroke",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, stroke),
+		.trait_class = &lsm_svg_paint_trait_class,
+		.trait_default = "none"
+	},
+	{
+		.name = "stroke-dasharray",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, stroke_dash_array),
+		.trait_class = &lsm_svg_dash_array_trait_class,
+		.trait_default = "none"
+	},
+	{
+		.name = "stroke-dashoffset",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, stroke_dash_offset),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = "0"
+	},
+	{
+		.name = "stroke-linecap",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, stroke_line_cap),
+		.trait_class = &lsm_svg_line_cap_trait_class,
+		.trait_default = "butt"
+	},
+	{
+		.name = "stroke-linejoin",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, stroke_line_join),
+		.trait_class = &lsm_svg_line_join_trait_class,
+		.trait_default = "miter"
+	},
+	{
+		.name = "stroke-miterlimit",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, stroke_miter_limit),
+		.trait_class = &lsm_double_trait_class,
+		.trait_default = "4"
+	},
+	{
+		.name = "stroke-opacity",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, stroke_opacity),
+		.trait_class = &lsm_double_trait_class,
+		.trait_default = "1"
+	},
+	{
+		.name = "stroke-width",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, stroke_width),
+		.trait_class = &lsm_svg_length_trait_class,
+		.trait_default = "1"
+	},
+	{
+		.name = "text-anchor",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, text_anchor),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "start"
+	},
+	{
+		.name = "text-rendering",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, text_rendering),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "auto"
+	},
+	{
+		.name = "visibility",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, visibility),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "visible"
+	},
+	{
+		.name = "word-spacing",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, word_spacing),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "normal"
+	},
+	{
+		.name = "writing-mode",
+		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, writing_mode),
+		.trait_class = &lsm_null_trait_class,
+		.trait_default = "lr-tb"
+	}
+};
+
+static LsmPropertyManager *
+lsm_svg_get_property_manager (void)
+{
+	static LsmPropertyManager *manager = NULL;
+
+	if (G_LIKELY (manager != NULL))
+		return manager;
+
+	manager = lsm_property_manager_new (G_N_ELEMENTS (lsm_svg_property_infos), lsm_svg_property_infos);
+
+	return manager;
+}
+
+void
+lsm_svg_property_bag_set_property (LsmPropertyBag *property_bag, const char *name, const char *value)
+{
+	LsmPropertyManager *property_manager = lsm_svg_get_property_manager ();
+
+	lsm_property_manager_set_property (property_manager, property_bag, name, value);
+}
+
+const char *
+lsm_svg_property_bag_get_property (LsmPropertyBag *property_bag, const char *name)
+{
+	LsmPropertyManager *property_manager = lsm_svg_get_property_manager ();
+
+	return lsm_property_manager_get_property (property_manager, property_bag, name);
+}
+
+void
+lsm_svg_property_bag_clean (LsmPropertyBag *property_bag)
+{
+	LsmPropertyManager *property_manager = lsm_svg_get_property_manager ();
+
+	lsm_property_manager_clean_properties (property_manager, property_bag);
+}
+
+char *
+lsm_svg_property_bag_serialize (LsmPropertyBag *property_bag)
+{
+	LsmPropertyManager *property_manager = lsm_svg_get_property_manager ();
+
+	return lsm_property_manager_serialize (property_manager, property_bag);
+}
+
+static const LsmSvgStyle *
+lsm_svg_get_default_style (void)
+{
+	static LsmSvgStyle *style = NULL;
+	LsmPropertyManager *property_manager = lsm_svg_get_property_manager ();
+
+	if (style != NULL)
+		return style;
+
+	style = g_new (LsmSvgStyle, 1);
+
+	lsm_property_manager_init_default_style (property_manager, style);
+
+	return style;
+}
 
 LsmSvgStyle *
 lsm_svg_style_new (void)
@@ -28,9 +463,6 @@ lsm_svg_style_new (void)
 	LsmSvgStyle *style;
 
 	style = g_new0 (LsmSvgStyle, 1);
-	g_return_val_if_fail (style != NULL, NULL);
-
-	style->text.font_family = g_strdup ("sans");
 
 	return style;
 }
@@ -40,26 +472,31 @@ lsm_svg_style_free (LsmSvgStyle *style)
 {
 	g_return_if_fail (style != NULL);
 
-	lsm_svg_dash_array_free (style->stroke.dash_array);
-
-	g_free (style->text.font_family);
 	g_free (style);
 }
 
 LsmSvgStyle *
-lsm_svg_style_duplicate (const LsmSvgStyle *from)
+lsm_svg_style_new_inherited (const LsmSvgStyle *parent_style, LsmPropertyBag *property_bag)
 {
 	LsmSvgStyle *style;
+	const LsmSvgStyle *default_style;
 
-	g_return_val_if_fail (from != NULL, NULL);
+	default_style = lsm_svg_get_default_style ();
 
-	style = lsm_svg_style_new ();
-	g_return_val_if_fail (style != NULL, NULL);
+	style = g_new (LsmSvgStyle, 1);
 
-	memcpy (style, from, sizeof (LsmSvgStyle));
+	if (parent_style != NULL) {
+		LsmPropertyManager *property_manager = lsm_svg_get_property_manager ();
 
-	style->stroke.dash_array = lsm_svg_dash_array_duplicate (from->stroke.dash_array);
-	style->text.font_family = g_strdup (from->text.font_family);
+		memcpy (style, default_style, offsetof (LsmSvgStyle, clip_rule));
+		memcpy (&style->clip_rule, &parent_style->clip_rule,
+			sizeof (LsmSvgStyle) - offsetof (LsmSvgStyle, clip_rule));
+
+		lsm_property_manager_apply_property_bag (property_manager, property_bag, style, parent_style);
+	} else {
+		memcpy (style, default_style, sizeof (LsmSvgStyle));
+	}
 
 	return style;
 }
+
diff --git a/src/lsmsvgstyle.h b/src/lsmsvgstyle.h
index ccd0c37..cbb1cc7 100644
--- a/src/lsmsvgstyle.h
+++ b/src/lsmsvgstyle.h
@@ -22,50 +22,136 @@
 #ifndef LSM_SVG_STYLE_H
 #define LSM_SVG_STYLE_H
 
-#include <lsmsvg.h>
-#include <lsmsvgattributebags.h>
+#include <lsmsvgtraits.h>
+#include <lsmproperties.h>
 
 G_BEGIN_DECLS
 
+typedef struct {
+	LsmProperty base;
+	double value;
+} LsmSvgDoubleProperty;
+
+typedef struct {
+	LsmProperty base;
+	LsmSvgLength length;
+} LsmSvgLengthProperty;
+
+typedef struct {
+	LsmProperty base;
+	LsmSvgPaint paint;
+} LsmSvgPaintProperty;
+
+typedef struct {
+	LsmProperty base;
+	LsmSvgColor value;
+} LsmSvgColorProperty;
+
+typedef struct {
+	LsmProperty base;
+	LsmSvgMatrix matrix;
+} LsmSvgTransformProperty;
+
+typedef struct {
+	LsmProperty base;
+	LsmSvgFillRule value;
+} LsmSvgFillRuleProperty;
+
+typedef struct {
+	LsmProperty base;
+	LsmSvgLineJoin value;
+} LsmSvgLineJoinProperty;
+
+typedef struct {
+	LsmProperty base;
+	LsmSvgLineCap value;
+} LsmSvgLineCapProperty;
+
+typedef struct {
+	LsmProperty base;
+	LsmSvgDashArray value;
+} LsmSvgDashArrayProperty;
+
 struct _LsmSvgStyle {
-	LsmBox viewport;
-	LsmSvgColor color;
-
-	struct {
-		LsmSvgPaint paint;
-		LsmSvgFillRule rule;
-		double opacity;
-	} fill;
-
-	struct {
-		LsmSvgPaint paint;
-		LsmSvgLength width;
-		LsmSvgLineJoin line_join;
-		LsmSvgLineCap line_cap;
-		double opacity;
-		double miter_limit;
-		LsmSvgDashArray *dash_array;
-		LsmSvgLength dash_offset;
-	} stroke;
-
-	struct {
-		LsmSvgFillRule rule;
-	} clip;
-
-	struct {
-		char *font_family;
-		LsmSvgLength font_size;
-	} text;
-
-	struct {
-		LsmSvgColor color;
-		double opacity;
-	} stop;
+	/* Not inherited */
+
+	LsmProperty *			alignment_baseline;
+	LsmProperty *			baseline_shift;
+	LsmProperty *	 		clip;
+	LsmProperty *	 		clip_path;
+	LsmProperty *	 		dominant_baseline;
+	LsmProperty *	 		enable_background;
+	LsmProperty *	 		filter;
+	LsmProperty *	 		flood_color;
+	LsmProperty *	 		flood_opacity;
+	LsmProperty *			lighting_color;
+	LsmProperty *			mask;
+	LsmSvgDoubleProperty *		opacity;
+	LsmProperty *			overflow;
+	LsmSvgColorProperty *		stop_color;
+	LsmSvgDoubleProperty *		stop_opacity;
+	LsmProperty *			text_decoration;
+	LsmProperty *			unicode_bidi;
+
+	/* Inherited */
+
+	LsmSvgFillRuleProperty * 	clip_rule;
+	LsmSvgColorProperty *		color;
+	LsmProperty *			color_interpolation;
+	LsmProperty *			color_interpolation_filters;
+	LsmProperty *			color_profile;
+	LsmProperty *			color_rendering;
+	LsmProperty *			cursor;
+	LsmProperty *			direction;
+	LsmProperty *			display;
+	LsmSvgPaintProperty *		fill;
+	LsmSvgDoubleProperty *		fill_opacity;
+	LsmSvgFillRuleProperty *	fill_rule;
+	LsmProperty *			font;
+	LsmProperty *			font_family;
+	LsmSvgLengthProperty *		font_size;
+	LsmProperty *			font_size_adjust;
+	LsmProperty *			font_stretch;
+	LsmProperty *			font_style;
+	LsmProperty *			font_variant;
+	LsmProperty *			font_weight;
+	LsmProperty *			glyph_orientation_horizontal;
+	LsmProperty *			glyph_orientation_vertical;
+	LsmProperty *			image_rendering;
+	LsmProperty *			kerning;
+	LsmProperty *			letter_spacing;
+	LsmProperty *			marker;
+	LsmProperty *			marker_end;
+	LsmProperty *			marker_mid;
+	LsmProperty *			marker_start;
+	LsmProperty *			pointer_events;
+	LsmProperty *			shape_rendering;
+	LsmSvgPaintProperty *	 	stroke;
+	LsmSvgDashArrayProperty	*	stroke_dash_array;
+	LsmSvgLengthProperty *		stroke_dash_offset;
+	LsmSvgLineCapProperty *		stroke_line_cap;
+	LsmSvgLineJoinProperty *	stroke_line_join;
+	LsmSvgDoubleProperty *		stroke_miter_limit;
+	LsmSvgDoubleProperty *		stroke_opacity;
+	LsmSvgLengthProperty *		stroke_width;
+	LsmProperty *			text_anchor;
+	LsmProperty *			text_rendering;
+	LsmProperty *			visibility;
+	LsmProperty *			word_spacing;
+	LsmProperty *			writing_mode;
 };
 
-LsmSvgStyle * 	lsm_svg_style_new 		(void);
-void 		lsm_svg_style_free 		(LsmSvgStyle *style);
-LsmSvgStyle *	lsm_svg_style_duplicate 	(const LsmSvgStyle *style);
+void 		lsm_svg_property_bag_set_property 	(LsmPropertyBag *property_bag,
+							 const char *name, const char *value);
+const char *	lsm_svg_property_bag_get_property	(LsmPropertyBag *property_bag,
+							 const char *name);
+void 		lsm_svg_property_bag_clean 		(LsmPropertyBag *property_bag);
+char * 		lsm_svg_property_bag_serialize 		(LsmPropertyBag *property_bag);
+
+LsmSvgStyle * 		lsm_svg_style_new 			(void);
+void 			lsm_svg_style_free 			(LsmSvgStyle *style);
+LsmSvgStyle *		lsm_svg_style_new_inherited 		(const LsmSvgStyle *parent_style,
+								 LsmPropertyBag *property_bag);
 
 G_END_DECLS
 
diff --git a/src/lsmsvgsvgelement.c b/src/lsmsvgsvgelement.c
index be01e75..9537697 100644
--- a/src/lsmsvgsvgelement.c
+++ b/src/lsmsvgsvgelement.c
@@ -39,42 +39,6 @@ lsm_svg_svg_element_get_node_name (LsmDomNode *node)
 
 /* LsmSvgElement implementation */
 
-static void
-_svg_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
-{
-	LsmSvgSvgElement *svg = LSM_SVG_SVG_ELEMENT (self);
-	LsmSvgLength length;
-
-	length.value_unit = 0;
-	length.type = LSM_SVG_LENGTH_TYPE_NUMBER;
-	lsm_svg_length_attribute_parse (&svg->x, &length);
-
-	length.value_unit = 0;
-	length.type = LSM_SVG_LENGTH_TYPE_NUMBER;
-	lsm_svg_length_attribute_parse (&svg->y, &length);
-
-	length.value_unit = parent_style->viewport.width;
-	length.type = LSM_SVG_LENGTH_TYPE_NUMBER;
-	lsm_svg_length_attribute_parse (&svg->width, &length);
-
-	length.value_unit = parent_style->viewport.height;
-	length.type = LSM_SVG_LENGTH_TYPE_NUMBER;
-	lsm_svg_length_attribute_parse (&svg->height, &length);
-
-	lsm_svg_viewbox_attribute_parse (&svg->viewbox);
-	lsm_svg_preserve_aspect_ratio_attribute_parse (&svg->preserve_aspect_ratio);
-
-	lsm_debug ("[LsmSvgSvgElement::update] view_bbox = %g, %g, %g, %g\n",
-		    svg->viewbox.value.x,
-		    svg->viewbox.value.y,
-		    svg->viewbox.value.width,
-		    svg->viewbox.value.height);
-
-	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
-
-	parent_style->viewport = svg->viewbox.value;
-}
-
 void
 lsm_svg_svg_element_measure (LsmSvgSvgElement *self, double *width, double *height)
 {
@@ -99,14 +63,29 @@ lsm_svg_svg_element_measure (LsmSvgSvgElement *self, double *width, double *heig
 	svg_viewbox = lsm_svg_viewbox_new (resolution_ppi, &viewport);
 	font_size = 10 * resolution_ppi / 72.0;
 
-	svg_x      = lsm_svg_length_normalize (&self->x.length, svg_viewbox,
-					       font_size, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
-	svg_y      = lsm_svg_length_normalize (&self->y.length, svg_viewbox,
-					       font_size, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
-	svg_width  = lsm_svg_length_normalize (&self->width.length, svg_viewbox,
-					       font_size, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
-	svg_height = lsm_svg_length_normalize (&self->height.length, svg_viewbox,
-					       font_size, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
+	if (lsm_attribute_is_defined (&self->x.base))
+		svg_x = lsm_svg_length_normalize (&self->x.length, svg_viewbox,
+						  font_size, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
+	else
+		svg_x = viewport.x;
+
+	if (lsm_attribute_is_defined (&self->y.base))
+		svg_y = lsm_svg_length_normalize (&self->y.length, svg_viewbox,
+						  font_size, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
+	else
+		svg_y = viewport.y;
+
+	if (lsm_attribute_is_defined (&self->width.base))
+		svg_width = lsm_svg_length_normalize (&self->width.length, svg_viewbox,
+						       font_size, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
+	else
+		svg_width = viewport.width;
+
+	if (lsm_attribute_is_defined (&self->height.base))
+		svg_height = lsm_svg_length_normalize (&self->height.length, svg_viewbox,
+						       font_size, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
+	else
+		svg_height = viewport.height;
 
 	if (width != NULL)
 		*width = svg_width * 72.0 / resolution_ppi;
@@ -127,7 +106,7 @@ lsm_svg_svg_element_measure (LsmSvgSvgElement *self, double *width, double *heig
 /* LsmSvgGraphic implementation */
 
 static void
-lsm_svg_svg_element_graphic_render (LsmSvgElement *self, LsmSvgView *view)
+_svg_element_render (LsmSvgElement *self, LsmSvgView *view)
 {
 	LsmSvgSvgElement *svg = LSM_SVG_SVG_ELEMENT (self);
 	gboolean is_viewbox_defined;
@@ -138,51 +117,25 @@ lsm_svg_svg_element_graphic_render (LsmSvgElement *self, LsmSvgView *view)
 	viewport.width  = lsm_svg_view_normalize_length (view, &svg->width.length, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
 	viewport.height = lsm_svg_view_normalize_length (view, &svg->height.length, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
 
-	is_viewbox_defined = lsm_dom_attribute_is_defined ((LsmDomAttribute *) &svg->viewbox);
+	is_viewbox_defined = lsm_attribute_is_defined ((LsmAttribute *) &svg->viewbox);
 
 	if (is_viewbox_defined && (svg->viewbox.value.width <= 0.0 ||
 				   svg->viewbox.value.height <= 0.0))
 		return;
 
-	lsm_debug ("[LsmSvgSvgElement::graphic_render] viewport %g, %g, %g, %g",
+	lsm_debug ("[LsmSvgSvgElement::render] viewport %g, %g, %g, %g",
 		   viewport.x, viewport.y, viewport.width, viewport.height);
 
 	lsm_svg_view_push_viewport (view, &viewport, is_viewbox_defined ? &svg->viewbox.value : NULL,
 				    &svg->preserve_aspect_ratio.value);
 
-	LSM_SVG_GRAPHIC_CLASS (parent_class)->graphic_render (self, view);
+	LSM_SVG_ELEMENT_CLASS (parent_class)->render (self, view);
 
 	lsm_svg_view_pop_viewport (view);
 }
 
 /* LsmSvgSvgElement implementation */
 
-LsmSvgStyle *
-lsm_svg_svg_element_get_default_style (LsmSvgSvgElement *svg_element)
-{
-	g_return_val_if_fail (LSM_IS_SVG_SVG_ELEMENT (svg_element), NULL);
-
-	return svg_element->default_style;
-}
-
-void
-lsm_svg_svg_element_update (LsmSvgSvgElement *svg_element)
-{
-	LsmDomDocument *document;
-	LsmSvgStyle *style;
-
-	g_return_if_fail (LSM_IS_SVG_SVG_ELEMENT (svg_element));
-
-	document = LSM_DOM_DOCUMENT (LSM_DOM_NODE (svg_element)->parent_node);
-	g_return_if_fail (LSM_IS_DOM_DOCUMENT (document));
-
-	style = lsm_svg_svg_element_get_default_style (svg_element);
-
-	style->viewport = lsm_dom_document_get_viewport_px (document);
-
-	lsm_svg_element_update (LSM_SVG_ELEMENT (svg_element), style);
-}
-
 void
 lsm_svg_svg_element_render (LsmSvgSvgElement *svg, LsmSvgView *view)
 {
@@ -197,49 +150,79 @@ lsm_svg_svg_element_new (void)
 	return g_object_new (LSM_TYPE_SVG_SVG_ELEMENT, NULL);
 }
 
+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 void
 lsm_svg_svg_element_init (LsmSvgSvgElement *self)
 {
-	LsmSvgStyle *style;
-
-	style = lsm_svg_style_new ();
-	self->default_style = style;
-	g_return_if_fail (style != NULL);
-
-	lsm_dom_element_set_attribute (LSM_DOM_ELEMENT (self), "opacity", 		"1.0");
-	lsm_dom_element_set_attribute (LSM_DOM_ELEMENT (self), "fill", 			"black");
-	lsm_dom_element_set_attribute (LSM_DOM_ELEMENT (self), "fill-opacity", 		"1");
-	lsm_dom_element_set_attribute (LSM_DOM_ELEMENT (self), "fill-rule",		"nonzero");
-	lsm_dom_element_set_attribute (LSM_DOM_ELEMENT (self), "stroke", 		"none");
-	lsm_dom_element_set_attribute (LSM_DOM_ELEMENT (self), "stroke-width", 		"1px");
-	lsm_dom_element_set_attribute (LSM_DOM_ELEMENT (self), "stroke-opacity", 	"1");
-	lsm_dom_element_set_attribute (LSM_DOM_ELEMENT (self), "stroke-linejoin", 	"miter");
-	lsm_dom_element_set_attribute (LSM_DOM_ELEMENT (self), "stroke-linecap", 	"butt");
-	lsm_dom_element_set_attribute (LSM_DOM_ELEMENT (self), "stroke-miterlimit", 	"4");
-	lsm_dom_element_set_attribute (LSM_DOM_ELEMENT (self), "font-family", 		"sans");
-	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");
-
+	self->x.length = x_y_default;
+	self->y.length = x_y_default;
+	self->width.length = width_height_default;
+	self->height.length = width_height_default;
+	self->viewbox.value = viewbox_default;
+	self->preserve_aspect_ratio.value = preserve_aspect_ratio_default;
 }
 
 static void
 lsm_svg_svg_element_finalize (GObject *object)
 {
-	LsmSvgSvgElement *svg_element = LSM_SVG_SVG_ELEMENT (object);
-
-	lsm_svg_style_free (svg_element->default_style);
+	parent_class->finalize (object);
 }
 
 /* LsmSvgSvgElement class */
 
+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)
 {
 	GObjectClass *object_class = G_OBJECT_CLASS (s_svg_class);
 	LsmDomNodeClass *d_node_class = LSM_DOM_NODE_CLASS (s_svg_class);
 	LsmSvgElementClass *s_element_class = LSM_SVG_ELEMENT_CLASS (s_svg_class);
-	LsmSvgGraphicClass *s_graphic_class = LSM_SVG_GRAPHIC_CLASS (s_svg_class);
 
 	parent_class = g_type_class_peek_parent (s_svg_class);
 
@@ -247,24 +230,12 @@ 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_graphic_class->graphic_render = lsm_svg_svg_element_graphic_render;
-
-	s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
+	s_element_class->render = _svg_element_render;
+	s_element_class->attribute_manager = lsm_attribute_manager_duplicate (s_element_class->attribute_manager);
 
-	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));
+	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);
 }
 
-G_DEFINE_TYPE (LsmSvgSvgElement, lsm_svg_svg_element, LSM_TYPE_SVG_GRAPHIC)
+G_DEFINE_TYPE (LsmSvgSvgElement, lsm_svg_svg_element, LSM_TYPE_SVG_ELEMENT)
diff --git a/src/lsmsvgsvgelement.h b/src/lsmsvgsvgelement.h
index bfb9f75..fca6269 100644
--- a/src/lsmsvgsvgelement.h
+++ b/src/lsmsvgsvgelement.h
@@ -23,7 +23,7 @@
 #define LSM_SVG_SVG_ELEMENT_H
 
 #include <lsmsvg.h>
-#include <lsmsvggraphic.h>
+#include <lsmsvgelement.h>
 
 G_BEGIN_DECLS
 
@@ -37,9 +37,9 @@ G_BEGIN_DECLS
 typedef struct _LsmSvgSvgElementClass LsmSvgSvgElementClass;
 
 struct _LsmSvgSvgElement {
-	LsmSvgGraphic graphic;
+	LsmSvgElement element;
 
-	LsmSvgStyle *default_style;
+//        LsmSvgStyle *default_style;
 
 	LsmSvgLengthAttribute	x;
 	LsmSvgLengthAttribute	y;
@@ -53,15 +53,13 @@ struct _LsmSvgSvgElement {
 };
 
 struct _LsmSvgSvgElementClass {
-	LsmSvgGraphicClass  parent_class;
+	LsmSvgElementClass  element_class;
 };
 
 GType lsm_svg_svg_element_get_type (void);
 
 LsmDomNode *		lsm_svg_svg_element_new 		(void);
 
-LsmSvgStyle * 		lsm_svg_svg_element_get_default_style 	(LsmSvgSvgElement *svg_element);
-void 			lsm_svg_svg_element_update 		(LsmSvgSvgElement *svg_element);
 void 			lsm_svg_svg_element_measure 		(LsmSvgSvgElement *self, double *width, double *height);
 void 			lsm_svg_svg_element_render 		(LsmSvgSvgElement *svg_element, LsmSvgView *view);
 
diff --git a/src/lsmsvgsymbolelement.c b/src/lsmsvgsymbolelement.c
index 410a8ad..1f8b641 100644
--- a/src/lsmsvgsymbolelement.c
+++ b/src/lsmsvgsymbolelement.c
@@ -37,12 +37,6 @@ lsm_svg_symbol_element_get_node_name (LsmDomNode *node)
 
 /* LsmSvgElement implementation */
 
-static void
-lsm_svg_symbol_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
-{
-	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
-}
-
 /* LsmSvgGraphic implementation */
 
 /* LsmSvgSymbolElement implementation */
@@ -64,15 +58,10 @@ 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);
 
 	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->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
 }
 
-G_DEFINE_TYPE (LsmSvgSymbolElement, lsm_svg_symbol_element, LSM_TYPE_SVG_GRAPHIC)
+G_DEFINE_TYPE (LsmSvgSymbolElement, lsm_svg_symbol_element, LSM_TYPE_SVG_ELEMENT)
diff --git a/src/lsmsvgsymbolelement.h b/src/lsmsvgsymbolelement.h
index c3ea1b1..40ea9e3 100644
--- a/src/lsmsvgsymbolelement.h
+++ b/src/lsmsvgsymbolelement.h
@@ -23,7 +23,7 @@
 #define LSM_SVG_SYMBOL_ELEMENT_H
 
 #include <lsmsvg.h>
-#include <lsmsvggraphic.h>
+#include <lsmsvgelement.h>
 
 G_BEGIN_DECLS
 
@@ -37,11 +37,11 @@ G_BEGIN_DECLS
 typedef struct _LsmSvgSymbolElementClass LsmSvgSymbolElementClass;
 
 struct _LsmSvgSymbolElement {
-	LsmSvgGraphic graphic;
+	LsmSvgElement element;
 };
 
 struct _LsmSvgSymbolElementClass {
-	LsmSvgGraphicClass  parent_class;
+	LsmSvgElementClass  element_class;
 };
 
 GType lsm_svg_symbol_element_get_type (void);
diff --git a/src/lsmsvgtextelement.c b/src/lsmsvgtextelement.c
index f89c44e..c891343 100644
--- a/src/lsmsvgtextelement.c
+++ b/src/lsmsvgtextelement.c
@@ -41,27 +41,10 @@ lsm_svg_text_element_can_append_child (LsmDomNode *self, LsmDomNode *child)
 
 /* LsmSvgElement implementation */
 
-static void
-lsm_svg_text_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
-{
-	LsmSvgTextElement *text = LSM_SVG_TEXT_ELEMENT (self);
-	LsmSvgLength length;
-
-	length.value_unit = 0.0;
-	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&text->x, &length);
-
-	length.value_unit = 0.0;
-	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&text->y, &length);
-
-	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
-}
-
 /* LsmSvgGraphic implementation */
 
 static void
-lsm_svg_text_element_graphic_render (LsmSvgElement *self, LsmSvgView *view)
+lsm_svg_text_element_render (LsmSvgElement *self, LsmSvgView *view)
 {
 	LsmSvgTextElement *text = LSM_SVG_TEXT_ELEMENT (self);
 	LsmDomNode *node = LSM_DOM_NODE (self);
@@ -78,8 +61,8 @@ lsm_svg_text_element_graphic_render (LsmSvgElement *self, LsmSvgView *view)
 		}
 	}
 
-	x = lsm_svg_view_normalize_length (view, &text->x.length.base, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
-	y = lsm_svg_view_normalize_length (view, &text->y.length.base, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
+	x = lsm_svg_view_normalize_length (view, &text->x.length, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
+	y = lsm_svg_view_normalize_length (view, &text->y.length, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
 
 	lsm_svg_view_show_text (view, g_strstrip (string->str), x, y);
 
@@ -94,43 +77,58 @@ lsm_svg_text_element_new (void)
 	return g_object_new (LSM_TYPE_SVG_TEXT_ELEMENT, NULL);
 }
 
+static const LsmSvgLength length_default = 	 { .value_unit =   0.0, .type = LSM_SVG_LENGTH_TYPE_PX};
+
 static void
 lsm_svg_text_element_init (LsmSvgTextElement *self)
 {
+	self->x.length = length_default;
+	self->y.length = length_default;
 }
 
 static void
 lsm_svg_text_element_finalize (GObject *object)
 {
+	parent_class->finalize (object);
 }
 
 /* LsmSvgTextElement class */
 
+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);
 
-	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_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->render = lsm_svg_text_element_render;
+	s_element_class->attribute_manager = lsm_attribute_manager_duplicate (s_element_class->attribute_manager);
 
-	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_attribute_manager_add_attributes (s_element_class->attribute_manager,
+					      G_N_ELEMENTS (lsm_svg_text_element_attribute_infos),
+					      lsm_svg_text_element_attribute_infos);
 }
 
-G_DEFINE_TYPE (LsmSvgTextElement, lsm_svg_text_element, LSM_TYPE_SVG_GRAPHIC)
+G_DEFINE_TYPE (LsmSvgTextElement, lsm_svg_text_element, LSM_TYPE_SVG_ELEMENT)
diff --git a/src/lsmsvgtextelement.h b/src/lsmsvgtextelement.h
index c3017ed..8e0a28f 100644
--- a/src/lsmsvgtextelement.h
+++ b/src/lsmsvgtextelement.h
@@ -23,7 +23,7 @@
 #define LSM_SVG_TEXT_ELEMENT_H
 
 #include <lsmsvg.h>
-#include <lsmsvggraphic.h>
+#include <lsmsvgelement.h>
 
 G_BEGIN_DECLS
 
@@ -37,14 +37,14 @@ G_BEGIN_DECLS
 typedef struct _LsmSvgTextElementClass LsmSvgTextElementClass;
 
 struct _LsmSvgTextElement {
-	LsmSvgGraphic graphic;
+	LsmSvgElement element;
 
-	LsmSvgAnimatedLengthAttribute	x;
-	LsmSvgAnimatedLengthAttribute	y;
+	LsmSvgLengthAttribute	x;
+	LsmSvgLengthAttribute	y;
 };
 
 struct _LsmSvgTextElementClass {
-	LsmSvgGraphicClass  parent_class;
+	LsmSvgElementClass  element_class;
 };
 
 GType lsm_svg_text_element_get_type (void);
diff --git a/src/lsmsvgtraits.c b/src/lsmsvgtraits.c
new file mode 100644
index 0000000..8eb4c49
--- /dev/null
+++ b/src/lsmsvgtraits.c
@@ -0,0 +1,666 @@
+/* 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,
+	      LsmSvgPaintType *paint_type)
+{
+	unsigned int color = 0;
+
+	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;
+
+		*paint_type = LSM_SVG_PAINT_TYPE_CURRENT_COLOR;
+
+		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;
+
+		*paint_type = LSM_SVG_PAINT_TYPE_RGB_COLOR;
+	} 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;
+
+		*paint_type = LSM_SVG_PAINT_TYPE_RGB_COLOR;
+	} else if (g_strcmp0 (string, "none") != 0) {
+		color = lsm_svg_color_from_string (string);
+
+		*paint_type = LSM_SVG_PAINT_TYPE_RGB_COLOR;
+	} else {
+		*paint_type = LSM_SVG_PAINT_TYPE_NONE;
+	}
+
+	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;
+	LsmSvgPaintType paint_type;
+
+	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, &paint_type);
+
+	if (paint->uri != NULL)
+		switch (paint_type) {
+			case LSM_SVG_PAINT_TYPE_RGB_COLOR:
+				paint_type = LSM_SVG_PAINT_TYPE_URI_RGB_COLOR;
+				break;
+			case LSM_SVG_PAINT_TYPE_CURRENT_COLOR:
+				paint_type = LSM_SVG_PAINT_TYPE_URI_CURRENT_COLOR;
+				break;
+			case LSM_SVG_PAINT_TYPE_NONE:
+				paint_type = LSM_SVG_PAINT_TYPE_URI;
+				break;
+			case LSM_SVG_PAINT_TYPE_RGB_COLOR_ICC_COLOR:
+				paint_type = LSM_SVG_PAINT_TYPE_URI_RGB_COLOR_ICC_COLOR;
+				break;
+			default:
+				paint_type = LSM_SVG_PAINT_TYPE_URI;
+				break;
+		}
+
+	paint->type = paint_type;
+}
+
+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;
+	LsmSvgPaintType paint_type;
+
+	_parse_color (string, color, &paint_type);
+}
+
+static char *
+lsm_svg_color_trait_to_string (LsmTrait *abstract_trait)
+{
+	LsmSvgColor *color = (LsmSvgColor *) abstract_trait;
+
+	if (color->red < 0.0 || color->green < 0.0 || color->blue < 0.0)
+		return g_strdup ("currentColor");
+
+	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..5fcb2ee 100644
--- a/src/lsmsvguseelement.c
+++ b/src/lsmsvguseelement.c
@@ -43,35 +43,10 @@ lsm_svg_use_can_append_child (LsmDomNode *node, LsmDomNode *child)
 
 /* LsmSvgElement implementation */
 
-static void
-lsm_svg_use_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
-{
-	LsmSvgUseElement *use_element = LSM_SVG_USE_ELEMENT (self);
-	LsmSvgLength length;
-
-	length.value_unit = 0.0;
-	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&use_element->x, &length);
-
-	length.value_unit = 0.0;
-	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&use_element->y, &length);
-
-	length.value_unit = 0.0;
-	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&use_element->width, &length);
-
-	length.value_unit = 0.0;
-	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&use_element->height, &length);
-
-	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
-}
-
 /* LsmSvgGraphic implementation */
 
 static void
-lsm_svg_use_element_graphic_render (LsmSvgElement *self, LsmSvgView *view)
+lsm_svg_use_element_render (LsmSvgElement *self, LsmSvgView *view)
 {
 	LsmSvgUseElement *use_element;
 	LsmDomDocument *document;
@@ -82,7 +57,7 @@ lsm_svg_use_element_graphic_render (LsmSvgElement *self, LsmSvgView *view)
 
 	document = lsm_dom_node_get_owner_document (LSM_DOM_NODE (self));
 	if (document == NULL) {
-		lsm_debug ("[LsmSvgUseElement::graphic_render] Owner document not found");
+		lsm_debug ("[LsmSvgUseElement::render] Owner document not found");
 		return;
 	}
 
@@ -98,22 +73,20 @@ lsm_svg_use_element_graphic_render (LsmSvgElement *self, LsmSvgView *view)
 
 	element = lsm_dom_document_get_element_by_id (document, id);
 	if (!LSM_IS_SVG_ELEMENT (element)) {
-		lsm_debug ("[LsmSvgUseElement::graphic_render] Target '%s' not found", id);
+		lsm_debug ("[LsmSvgUseElement::render] Target '%s' not found", id);
 		return;
 	}
 
-	width = lsm_svg_view_normalize_length (view, &use_element->width.length.base,
+	width = lsm_svg_view_normalize_length (view, &use_element->width.length,
 					       LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
-	height = lsm_svg_view_normalize_length (view, &use_element->height.length.base,
+	height = lsm_svg_view_normalize_length (view, &use_element->height.length,
 						LSM_SVG_LENGTH_DIRECTION_VERTICAL);
-/*        if (width <= 0.0 || height <= 0.0)*/
-/*                return;*/
 
-	lsm_debug ("[LsmSvgUseElement::graphic_render] Use '%s'", id);
+	lsm_debug ("[LsmSvgUseElement::render] Use '%s'", id);
 
-	x = lsm_svg_view_normalize_length (view, &use_element->x.length.base,
+	x = lsm_svg_view_normalize_length (view, &use_element->x.length,
 					   LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
-	y = lsm_svg_view_normalize_length (view, &use_element->y.length.base,
+	y = lsm_svg_view_normalize_length (view, &use_element->y.length,
 					   LSM_SVG_LENGTH_DIRECTION_VERTICAL);
 
 	lsm_svg_matrix_init_translate (&matrix, x, y);
@@ -132,41 +105,68 @@ lsm_svg_use_element_new (void)
 	return g_object_new (LSM_TYPE_SVG_USE_ELEMENT, NULL);
 }
 
+static const LsmSvgLength length_default = 	 { .value_unit =   0.0, .type = LSM_SVG_LENGTH_TYPE_PX};
+
 static void
 lsm_svg_use_element_init (LsmSvgUseElement *self)
 {
+	self->x.length = length_default;
+	self->y.length = length_default;
+	self->width.length = length_default;
+	self->height.length = length_default;
 }
 
 /* LsmSvgUseElement class */
 
+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)
 {
 	LsmDomNodeClass *d_node_class = LSM_DOM_NODE_CLASS (klass);
 	LsmSvgElementClass *s_element_class = LSM_SVG_ELEMENT_CLASS (klass);
-	LsmSvgGraphicClass *s_graphic_class = LSM_SVG_GRAPHIC_CLASS (klass);
 
 	parent_class = g_type_class_peek_parent (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_graphic_class->graphic_render = lsm_svg_use_element_graphic_render;
-
-	s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
+	s_element_class->render = lsm_svg_use_element_render;
+	s_element_class->attribute_manager = lsm_attribute_manager_duplicate (s_element_class->attribute_manager);
 
-	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));
+	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);
 }
 
-G_DEFINE_TYPE (LsmSvgUseElement, lsm_svg_use_element, LSM_TYPE_SVG_GRAPHIC)
+G_DEFINE_TYPE (LsmSvgUseElement, lsm_svg_use_element, LSM_TYPE_SVG_ELEMENT)
diff --git a/src/lsmsvguseelement.h b/src/lsmsvguseelement.h
index 285d7e8..3645d90 100644
--- a/src/lsmsvguseelement.h
+++ b/src/lsmsvguseelement.h
@@ -23,7 +23,7 @@
 #define LSM_SVG_USE_ELEMENT_H
 
 #include <lsmsvg.h>
-#include <lsmsvggraphic.h>
+#include <lsmsvgelement.h>
 
 G_BEGIN_DECLS
 
@@ -37,18 +37,18 @@ G_BEGIN_DECLS
 typedef struct _LsmSvgUseElementClass LsmSvgUseElementClass;
 
 struct _LsmSvgUseElement {
-	LsmSvgGraphic graphic;
+	LsmSvgElement element;
 
-	LsmSvgAnimatedLengthAttribute	x;
-	LsmSvgAnimatedLengthAttribute	y;
-	LsmSvgAnimatedLengthAttribute	width;
-	LsmSvgAnimatedLengthAttribute	height;
+	LsmSvgLengthAttribute	x;
+	LsmSvgLengthAttribute	y;
+	LsmSvgLengthAttribute	width;
+	LsmSvgLengthAttribute	height;
 
-	LsmDomAttribute		href;
+	LsmAttribute		href;
 };
 
 struct _LsmSvgUseElementClass {
-	LsmSvgGraphicClass  parent_class;
+	LsmSvgElementClass  element_class;
 };
 
 GType lsm_svg_use_element_get_type (void);
diff --git a/src/lsmsvgview.c b/src/lsmsvgview.c
index 0aaed98..58845fc 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>
 
@@ -58,11 +58,8 @@ lsm_svg_view_normalize_length (LsmSvgView *view, const LsmSvgLength *length, Lsm
 	g_return_val_if_fail (LSM_IS_SVG_VIEW (view), 0.0);
 
 	/* TODO cache font size */
-	if (view->text_stack != NULL && view->viewbox_stack != NULL) {
-		LsmSvgTextAttributeBag *text;
-
-		text = view->text_stack->data;
-		font_size = lsm_svg_length_normalize (&text->font_size.length, view->viewbox_stack->data,
+	if (view->viewbox_stack != NULL && view->style != NULL) {
+		font_size = lsm_svg_length_normalize (&view->style->font_size->length, view->viewbox_stack->data,
 						      0.0, LSM_SVG_LENGTH_DIRECTION_DIAGONAL);
 	} else
 		font_size = 0.0;
@@ -120,6 +117,7 @@ _set_pattern (LsmSvgView *view, cairo_pattern_t *pattern)
 	g_return_if_fail (view->pattern_data->pattern == NULL);
 
 	view->pattern_data->pattern = pattern;
+	view->last_stop_offset = 0.0;
 }
 
 void
@@ -144,15 +142,37 @@ lsm_svg_view_create_linear_gradient (LsmSvgView *view,
 }
 
 void
-lsm_svg_view_add_gradient_color_stop (LsmSvgView *view, double offset, const LsmSvgColor *color, double opacity)
+lsm_svg_view_add_gradient_color_stop (LsmSvgView *view, double offset)
 {
+	const LsmSvgStyle *style;
+	const LsmSvgColor *color;
+
 	g_return_if_fail (LSM_IS_SVG_VIEW (view));
 	g_return_if_fail (view->pattern_data != NULL);
 	g_return_if_fail (view->pattern_data->pattern != NULL);
-	g_return_if_fail (color != NULL);
+
+	if (offset > 1.0)
+		offset = 1.0;
+
+	if (offset < view->last_stop_offset)
+		offset = view->last_stop_offset;
+	else
+		view->last_stop_offset = offset;
+
+	style = view->style;
+
+	lsm_debug ("[LsmSvgView::add_gradient_color_stop] opacity = %g", style->stop_opacity->value);
+
+	color = &style->stop_color->value;
+
+	if (color->red < 0.0 || color->blue < 0.0 || color->green < 0.0)
+		color = &style->color->value;
 
 	cairo_pattern_add_color_stop_rgba (view->pattern_data->pattern, offset,
-					   color->red, color->green, color->blue, opacity);
+					   color->red,
+					   color->green,
+					   color->blue,
+					   style->stop_opacity->value);
 }
 
 void
@@ -199,13 +219,6 @@ lsm_svg_view_create_surface_pattern (LsmSvgView *view,
 	width = viewport->width;
 	height = viewport->height;
 
-/*        if (units == LSM_SVG_PATTERN_UNITS_OBJECT_BOUNDING_BOX) {*/
-/*                x *= view->pattern_data->extents.width;*/
-/*                y *= view->pattern_data->extents.height;*/
-/*                width *= view->pattern_data->extents.width;*/
-/*                height *= view->pattern_data->extents.height;*/
-/*        }*/
-
 	lsm_debug ("[LsmSvgView::create_pattern] pattern size = %g ,%g at %g, %g",
 		   width, height, x, y);
 
@@ -474,7 +487,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 +497,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 +511,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 +543,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 +584,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 +603,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 +612,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 +637,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);
@@ -694,7 +707,7 @@ _paint_uri (LsmSvgView *view, LsmSvgViewPaintOperation operation, const char *ur
 
 	_start_pattern (view, &extents);
 
-	lsm_svg_element_render_paint (LSM_SVG_ELEMENT (element), view);
+	lsm_svg_element_force_render (LSM_SVG_ELEMENT (element), view);
 
 	cairo = view->pattern_data->old_cairo;
 
@@ -765,6 +778,13 @@ _set_color (LsmSvgView *view, LsmSvgViewPaintOperation operation,
 					       paint->color.blue,
 					       opacity);
 			break;
+		case LSM_SVG_PAINT_TYPE_CURRENT_COLOR:
+			cairo_set_source_rgba (cairo,
+					       view->style->color->value.red,
+					       view->style->color->value.green,
+					       view->style->color->value.blue,
+					       opacity);
+			break;
 		case LSM_SVG_PAINT_TYPE_URI:
 		case LSM_SVG_PAINT_TYPE_URI_RGB_COLOR:
 		case LSM_SVG_PAINT_TYPE_URI_CURRENT_COLOR:
@@ -781,33 +801,24 @@ _set_color (LsmSvgView *view, LsmSvgViewPaintOperation operation,
 static void
 paint (LsmSvgView *view)
 {
-	LsmSvgFillAttributeBag *fill;
-	LsmSvgStrokeAttributeBag *stroke;
-	LsmSvgGraphic *graphic;
+	LsmSvgElement *element;
+	const LsmSvgStyle *style;
 	cairo_t *cairo;
 	gboolean use_group;
 	double group_opacity;
 
-	g_return_if_fail (view->fill_stack != NULL);
-	g_return_if_fail (view->stroke_stack != NULL);
-	g_return_if_fail (view->element_stack != NULL);
-
-	graphic = view->element_stack->data;
+	element = view->element_stack->data;
 
-	g_return_if_fail (LSM_IS_SVG_GRAPHIC (graphic));
+	g_return_if_fail (LSM_IS_SVG_ELEMENT (element));
 
 	cairo = view->dom_view.cairo;
-	fill = view->fill_stack->data;
-	stroke = view->stroke_stack->data;
-
-	if (view->mask_stack != NULL && view->mask_stack->data == graphic->mask) {
-		LsmSvgMaskAttributeBag *mask;
+	style = view->style;
 
-		mask = view->mask_stack->data;
-		group_opacity = mask->opacity.value;
+	if (style->opacity != NULL) {
+		group_opacity = style->opacity->value;
 
-		use_group = fill->paint.paint.type != LSM_SVG_PAINT_TYPE_NONE &&
-			stroke->paint.paint.type != LSM_SVG_PAINT_TYPE_NONE &&
+		use_group = style->fill->paint.type != LSM_SVG_PAINT_TYPE_NONE &&
+			style->stroke->paint.type != LSM_SVG_PAINT_TYPE_NONE &&
 			group_opacity < 1.0;
 	} else {
 		use_group = FALSE;
@@ -818,18 +829,22 @@ paint (LsmSvgView *view)
 	if (use_group)
 		cairo_push_group (cairo);
 
-	if (_set_color (view, LSM_SVG_VIEW_PAINT_OPERATION_FILL,
-			&fill->paint.paint, fill->opacity.value * (use_group ? 1.0 : group_opacity))) {
-		cairo_set_fill_rule (cairo, fill->rule.value == LSM_SVG_FILL_RULE_EVEN_ODD ?
+	if (_set_color (view,
+			LSM_SVG_VIEW_PAINT_OPERATION_FILL,
+			&style->fill->paint,
+			style->fill_opacity->value * (use_group ? 1.0 : group_opacity))) {
+		cairo_set_fill_rule (cairo, style->fill_rule->value == LSM_SVG_FILL_RULE_EVEN_ODD ?
 				     CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING);
 		cairo_fill_preserve (cairo);
 	}
 
-	if (_set_color (view, LSM_SVG_VIEW_PAINT_OPERATION_STROKE,
-			&stroke->paint.paint, stroke->opacity.value * (use_group ? 1.0 : group_opacity))) {
+	if (_set_color (view,
+			LSM_SVG_VIEW_PAINT_OPERATION_STROKE,
+			&style->stroke->paint,
+			style->stroke_opacity->value * (use_group ? 1.0 : group_opacity))) {
 		double line_width;
 
-		switch (stroke->line_join.value) {
+		switch (style->stroke_line_join->value) {
 			case LSM_SVG_LINE_JOIN_MITER:
 				cairo_set_line_join (cairo, CAIRO_LINE_JOIN_MITER);
 				break;
@@ -840,7 +855,7 @@ paint (LsmSvgView *view)
 				cairo_set_line_join (cairo,CAIRO_LINE_JOIN_BEVEL);
 		}
 
-		switch (stroke->line_cap.value) {
+		switch (style->stroke_line_cap->value) {
 			case LSM_SVG_LINE_CAP_BUTT:
 				cairo_set_line_cap (cairo, CAIRO_LINE_CAP_BUTT);
 				break;
@@ -851,31 +866,26 @@ paint (LsmSvgView *view)
 				cairo_set_line_cap (cairo, CAIRO_LINE_CAP_SQUARE);
 		}
 
-		line_width = lsm_svg_view_normalize_length (view, &stroke->width.length,
+		line_width = lsm_svg_view_normalize_length (view, &style->stroke_width->length,
 							    LSM_SVG_LENGTH_DIRECTION_DIAGONAL);
 
-		cairo_set_miter_limit (cairo, stroke->miter_limit.value);
+		cairo_set_miter_limit (cairo, style->stroke_miter_limit->value);
 		cairo_set_line_width (cairo, line_width);
 
-		if (stroke->dash_array.value != NULL &&
-		    stroke->dash_array.value->n_dashes > 0) {
+		if (style->stroke_dash_array->value.n_dashes > 0) {
 			double dash_offset;
 			double *dashes;
 			unsigned int i;
 
-			dash_offset = lsm_svg_view_normalize_length (view, &stroke->dash_offset.length,
+			dash_offset = lsm_svg_view_normalize_length (view, &style->stroke_dash_offset->length,
 								     LSM_SVG_LENGTH_DIRECTION_DIAGONAL);
-			dashes = g_new(double, stroke->dash_array.value->n_dashes);
-			for (i = 0; i < stroke->dash_array.value->n_dashes; i++)
+			dashes = g_new (double, style->stroke_dash_array->value.n_dashes);
+			for (i = 0; i < style->stroke_dash_array->value.n_dashes; i++)
 				dashes[i] = lsm_svg_view_normalize_length (view,
-									   &stroke->dash_array.value->dashes[i],
+									   &style->stroke_dash_array->value.dashes[i],
 									   LSM_SVG_LENGTH_DIRECTION_DIAGONAL);
 
-			cairo_set_dash (cairo,
-					dashes,
-					stroke->dash_array.value->n_dashes,
-					dash_offset);
-
+			cairo_set_dash (cairo, dashes, style->stroke_dash_array->value.n_dashes, dash_offset);
 			g_free (dashes);
 		} else
 			cairo_set_dash (cairo, NULL, 0, 0.0);
@@ -894,11 +904,10 @@ paint (LsmSvgView *view)
 static void
 process_path (LsmSvgView *view)
 {
-	if (view->is_clipping) {
-		LsmSvgMaskAttributeBag *mask;
+	g_return_if_fail (view->style != NULL);
 
-		mask = view->mask_stack->data;
-		cairo_set_fill_rule (view->dom_view.cairo, mask->clip_rule.value);
+	if (view->is_clipping) {
+		cairo_set_fill_rule (view->dom_view.cairo, view->style->clip_rule->value);
 	} else
 		paint (view);
 }
@@ -1018,9 +1027,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 +1046,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]);
 	}
 
@@ -1051,11 +1060,11 @@ lsm_svg_view_show_polygon (LsmSvgView *view, const char *points)
 void
 lsm_svg_view_show_text (LsmSvgView *view, char const *string, double x, double y)
 {
+	const LsmSvgStyle *style;
 	PangoLayout *pango_layout;
 	PangoFontDescription *font_description;
 	PangoLayoutIter *iter;
 	PangoRectangle ink_rect;
-	LsmSvgTextAttributeBag *text;
 	double font_size;
 	int baseline;
 
@@ -1064,15 +1073,15 @@ lsm_svg_view_show_text (LsmSvgView *view, char const *string, double x, double y
 
 	g_return_if_fail (LSM_IS_SVG_VIEW (view));
 
-	text = view->text_stack->data;
-	g_return_if_fail (text != NULL);
+	style = view->style;
 
 	pango_layout = view->dom_view.pango_layout;
 	font_description = view->dom_view.font_description;
 
-	font_size = lsm_svg_view_normalize_length (view, &text->font_size.length, LSM_SVG_LENGTH_DIRECTION_DIAGONAL);
+	font_size = lsm_svg_view_normalize_length (view, &style->font_size->length,
+						   LSM_SVG_LENGTH_DIRECTION_DIAGONAL);
 
-	pango_font_description_set_family (font_description, text->font_family.value);
+	pango_font_description_set_family (font_description, style->font_family->value);
 	pango_font_description_set_size (font_description, font_size * PANGO_SCALE);
 
 	pango_layout_set_text (pango_layout, string, -1);
@@ -1227,7 +1236,7 @@ lsm_svg_view_pop_viewport (LsmSvgView *view)
 }
 
 void
-lsm_svg_view_push_matrix (LsmSvgView *view, LsmSvgMatrix *matrix)
+lsm_svg_view_push_matrix (LsmSvgView *view, const LsmSvgMatrix *matrix)
 {
 	cairo_matrix_t cr_matrix;
 	cairo_matrix_t *ctm;
@@ -1273,25 +1282,29 @@ lsm_svg_view_pop_matrix (LsmSvgView *view)
 }
 
 void
-lsm_svg_view_push_element (LsmSvgView *view, const LsmSvgElement *element)
+lsm_svg_view_push_group_opacity (LsmSvgView *view)
 {
 	g_return_if_fail (LSM_IS_SVG_VIEW (view));
-	g_return_if_fail (LSM_IS_SVG_ELEMENT (element));
+	g_return_if_fail (view->style != NULL);
 
-	view->element_stack = g_slist_prepend (view->element_stack, (void *) element);
+	if (view->style->opacity->value < 1.0)
+		cairo_push_group (view->dom_view.cairo);
 }
 
 void
-lsm_svg_view_pop_element (LsmSvgView *view)
+lsm_svg_view_pop_group_opacity (LsmSvgView *view)
 {
 	g_return_if_fail (LSM_IS_SVG_VIEW (view));
-	g_return_if_fail (view->element_stack != NULL);
+	g_return_if_fail (view->style != NULL);
 
-	view->element_stack = g_slist_delete_link (view->element_stack, view->element_stack);
+	if (view->style->opacity->value < 1.0) {
+		cairo_pop_group_to_source (view->dom_view.cairo);
+		cairo_paint_with_alpha (view->dom_view.cairo, view->style->opacity->value);
+	}
 }
 
 static void
-lsm_svg_view_push_clip (LsmSvgView *view, char *clip_path, LsmSvgFillRule clip_rule)
+lsm_svg_view_push_clip (LsmSvgView *view)
 {
 	LsmDomElement *element;
 	LsmExtents extents;
@@ -1302,9 +1315,9 @@ lsm_svg_view_push_clip (LsmSvgView *view, char *clip_path, LsmSvgFillRule clip_r
 
 	lsm_svg_element_get_extents (view->element_stack->data, view, &extents);
 
-	uri = clip_path;
+	uri = view->style->clip_path->value;
 
-	lsm_debug ("[LsmSvgView::push_clip] Using '%s'", clip_path);
+	lsm_debug ("[LsmSvgView::push_clip] Using '%s'", uri);
 
 	cairo_save (view->dom_view.cairo);
 
@@ -1326,7 +1339,7 @@ lsm_svg_view_push_clip (LsmSvgView *view, char *clip_path, LsmSvgFillRule clip_r
 
 		if (element != NULL && LSM_IS_SVG_CLIP_PATH_ELEMENT (element)) {
 			view->is_clipping = TRUE;
-			lsm_svg_element_render_clip (LSM_SVG_ELEMENT (element), view);
+			lsm_svg_element_force_render (LSM_SVG_ELEMENT (element), view);
 			cairo_clip (view->dom_view.cairo);
 			view->is_clipping = FALSE;
 		}
@@ -1341,194 +1354,152 @@ lsm_svg_view_pop_clip (LsmSvgView *view)
 	cairo_restore (view->dom_view.cairo);
 }
 
-void
-lsm_svg_view_push_group_opacity (LsmSvgView *view)
+static void
+lsm_svg_view_push_mask (LsmSvgView *view)
 {
-	LsmSvgMaskAttributeBag *mask;
-
 	g_return_if_fail (LSM_IS_SVG_VIEW (view));
-	g_return_if_fail (view->mask_stack != NULL);
-
-	mask = view->mask_stack->data;
 
-	if (mask->opacity.value < 1.0)
-		cairo_push_group (view->dom_view.cairo);
+	cairo_push_group (view->dom_view.cairo);
 }
 
-void
-lsm_svg_view_pop_group_opacity (LsmSvgView *view)
+static void
+lsm_svg_view_pop_mask (LsmSvgView *view)
 {
-	LsmSvgMaskAttributeBag *mask;
-
 	g_return_if_fail (LSM_IS_SVG_VIEW (view));
-	g_return_if_fail (view->mask_stack != NULL);
 
-	mask = view->mask_stack->data;
+	if (strncmp (view->style->mask->value, "url(#", 5) == 0) {
+		LsmDomElement *mask_element;
+		char *end;
+		char *uri;
 
-	if (mask->opacity.value < 1.0) {
-		cairo_pop_group_to_source (view->dom_view.cairo);
-		cairo_paint_with_alpha (view->dom_view.cairo, mask->opacity.value);
-	}
-}
+		uri = g_strdup (view->style->mask->value + 5);
+		for (end = uri; *end != '\0' && *end != ')'; end++);
+		*end = '\0';
 
-void
-lsm_svg_view_push_mask_attributes (LsmSvgView *view, const LsmSvgMaskAttributeBag *mask)
-{
-	g_return_if_fail (LSM_IS_SVG_VIEW (view));
-	g_return_if_fail (mask != NULL);
+		mask_element = lsm_dom_document_get_element_by_id (view->dom_view.document, uri);
 
-	view->mask_stack = g_slist_prepend (view->mask_stack, (void *) mask);
+		if (LSM_IS_SVG_MASK_ELEMENT (mask_element)) {
+			LsmExtents extents;
+			LsmBox mask_extents;
+			cairo_t *cairo;
 
-	if (mask->clip_path.value != NULL)
-		lsm_svg_view_push_clip (view, mask->clip_path.value, mask->clip_rule.value);
+			lsm_svg_element_get_extents (view->element_stack->data, view, &extents);
 
-	if (mask->mask.value != NULL)
-		cairo_push_group (view->dom_view.cairo);
-}
+			mask_extents.x = extents.x1;
+			mask_extents.y = extents.y1;
+			mask_extents.width = extents.x2 - extents.x1;
+			mask_extents.height = extents.y2 - extents.y1;
 
-void
-lsm_svg_view_pop_mask_attributes (LsmSvgView *view)
-{
-	LsmSvgMaskAttributeBag *mask;
+			cairo = view->dom_view.cairo;
 
-	g_return_if_fail (LSM_IS_SVG_VIEW (view));
-	g_return_if_fail (view->mask_stack != NULL);
+			_start_pattern (view, &mask_extents);
 
-	mask = view->mask_stack->data;
+			lsm_svg_element_force_render (LSM_SVG_ELEMENT (mask_element), view);
 
-	if (mask->clip_path.value != NULL)
-		lsm_svg_view_pop_clip (view);
+			cairo_pop_group_to_source (cairo);
+			if (view->pattern_data->pattern != NULL) {
+				cairo_surface_t *surface;
+				int width, height, row, i, stride;
+				unsigned char *pixels;
+
+				cairo_pattern_get_surface (view->pattern_data->pattern, &surface);
+				pixels = cairo_image_surface_get_data (surface);
+				height = cairo_image_surface_get_height (surface);
+				width = cairo_image_surface_get_width (surface);
+				stride = cairo_image_surface_get_stride (surface);
 
-	if (mask->mask.value != NULL) {
-		if (strncmp (mask->mask.value, "url(#", 5) == 0) {
-			LsmDomElement *mask_element;
-			char *end;
-			char *uri;
-
-			uri = g_strdup (mask->mask.value + 5);
-			for (end = uri; *end != '\0' && *end != ')'; end++);
-			*end = '\0';
-
-			mask_element = lsm_dom_document_get_element_by_id (view->dom_view.document, uri);
-
-			if (LSM_IS_SVG_MASK_ELEMENT (mask_element)) {
-				LsmExtents extents;
-				LsmBox mask_extents;
-				cairo_t *cairo;
-
-				lsm_svg_element_get_extents (view->element_stack->data, view, &extents);
-
-				mask_extents.x = extents.x1;
-				mask_extents.y = extents.y1;
-				mask_extents.width = extents.x2 - extents.x1;
-				mask_extents.height = extents.y2 - extents.y1;
-
-				cairo = view->dom_view.cairo;
-
-				_start_pattern (view, &mask_extents);
-
-				lsm_svg_element_render_paint (LSM_SVG_ELEMENT (mask_element), view);
-
-				cairo_pop_group_to_source (cairo);
-				if (view->pattern_data->pattern != NULL) {
-					cairo_surface_t *surface;
-					int width, height, row, i, stride;
-					unsigned char *pixels;
-
-					cairo_pattern_get_surface (view->pattern_data->pattern, &surface);
-					pixels = cairo_image_surface_get_data (surface);
-					height = cairo_image_surface_get_height (surface);
-					width = cairo_image_surface_get_width (surface);
-					stride = cairo_image_surface_get_stride (surface);
-
-					for (row = 0; row < height; row++) {
-						guint8 *row_data = (pixels + (row * stride));
-						for (i = 0; i < width; i++) {
-							guint32 *pixel = (guint32 *) row_data + i;
-							*pixel = ((((*pixel & 0x00ff0000) >> 16) * 13817 +
-								   ((*pixel & 0x0000ff00) >> 8) * 46518 +
-								   ((*pixel & 0x000000ff)) * 4688) * 0xff
-								  /* * opacity */);
-						}
+				for (row = 0; row < height; row++) {
+					guint8 *row_data = (pixels + (row * stride));
+					for (i = 0; i < width; i++) {
+						guint32 *pixel = (guint32 *) row_data + i;
+						*pixel = ((((*pixel & 0x00ff0000) >> 16) * 13817 +
+							   ((*pixel & 0x0000ff00) >> 8) * 46518 +
+							   ((*pixel & 0x000000ff)) * 4688) * 0xff
+							  /* * opacity */);
 					}
+				}
 
-					cairo_pattern_set_matrix (view->pattern_data->pattern,
-								  &view->pattern_data->matrix);
-					cairo_pattern_set_extend (view->pattern_data->pattern, CAIRO_EXTEND_NONE);
+				cairo_pattern_set_matrix (view->pattern_data->pattern,
+							  &view->pattern_data->matrix);
+				cairo_pattern_set_extend (view->pattern_data->pattern, CAIRO_EXTEND_NONE);
 #if 0
-					cairo_surface_write_to_png (surface, "mask.png");
+				cairo_surface_write_to_png (surface, "mask.png");
 #endif
-					cairo_mask (cairo, view->pattern_data->pattern);
-				} else {
-					cairo_paint (cairo);
-				}
-
-				_end_pattern (view);
+				cairo_mask (cairo, view->pattern_data->pattern);
 			} else {
-				cairo_pop_group_to_source (view->dom_view.cairo);
-				cairo_paint (view->dom_view.cairo);
+				cairo_paint (cairo);
 			}
+
+			_end_pattern (view);
 		} else {
 			cairo_pop_group_to_source (view->dom_view.cairo);
 			cairo_paint (view->dom_view.cairo);
 		}
+	} else {
+		cairo_pop_group_to_source (view->dom_view.cairo);
+		cairo_paint (view->dom_view.cairo);
 	}
-
-	view->mask_stack = g_slist_delete_link (view->mask_stack, view->mask_stack);
 }
 
 void
-lsm_svg_view_push_fill_attributes (LsmSvgView *view, const LsmSvgFillAttributeBag *fill)
+lsm_svg_view_push_element (LsmSvgView *view, const LsmSvgElement *element)
 {
 	g_return_if_fail (LSM_IS_SVG_VIEW (view));
-	g_return_if_fail (fill != NULL);
+	g_return_if_fail (LSM_IS_SVG_ELEMENT (element));
 
-	view->fill_stack = g_slist_prepend (view->fill_stack, (void *) fill);
+	view->element_stack = g_slist_prepend (view->element_stack, (void *) element);
 }
 
 void
-lsm_svg_view_pop_fill_attributes (LsmSvgView *view)
+lsm_svg_view_pop_element (LsmSvgView *view)
 {
 	g_return_if_fail (LSM_IS_SVG_VIEW (view));
-	g_return_if_fail (view->fill_stack != NULL);
+	g_return_if_fail (view->element_stack != NULL);
 
-	view->fill_stack = g_slist_delete_link (view->fill_stack, view->fill_stack);
+	view->element_stack = g_slist_delete_link (view->element_stack, view->element_stack);
 }
 
 void
-lsm_svg_view_push_stroke_attributes (LsmSvgView *view, const LsmSvgStrokeAttributeBag *stroke)
+lsm_svg_view_push_style	(LsmSvgView *view, const LsmSvgStyle *style)
 {
 	g_return_if_fail (LSM_IS_SVG_VIEW (view));
-	g_return_if_fail (stroke != NULL);
+	g_return_if_fail (style != NULL);
 
-	view->stroke_stack = g_slist_prepend (view->stroke_stack, (void *) stroke);
-}
+	view->style_stack = g_slist_prepend (view->style_stack, (void *) style);
+	view->style = style;
 
-void
-lsm_svg_view_pop_stroke_attributes (LsmSvgView *view)
-{
-	g_return_if_fail (LSM_IS_SVG_VIEW (view));
-	g_return_if_fail (view->stroke_stack != NULL);
+	if (g_strcmp0 (style->clip_path->value, "none") != 0) {
+		lsm_debug ("[LsmSvgView::push_style] Start clip '%s'", style->clip_path->value);
+		lsm_svg_view_push_clip (view);
+	}
 
-	view->stroke_stack = g_slist_delete_link (view->stroke_stack, view->stroke_stack);
+	if (g_strcmp0 (style->mask->value, "none") != 0) {
+		lsm_debug ("[LsmSvgView::push_style] Start mask '%s'", style->mask->value);
+		lsm_svg_view_push_mask (view);
+	}
 }
 
-void
-lsm_svg_view_push_text_attributes (LsmSvgView *view, const LsmSvgTextAttributeBag *text)
+void lsm_svg_view_pop_style (LsmSvgView *view)
 {
 	g_return_if_fail (LSM_IS_SVG_VIEW (view));
-	g_return_if_fail (text != NULL);
+	g_return_if_fail (view->style_stack != NULL);
+
+	if (g_strcmp0 (view->style->mask->value, "none") != 0)
+		lsm_svg_view_pop_mask (view);
 
-	view->text_stack = g_slist_prepend (view->text_stack, (void *) text);
+	if (g_strcmp0 (view->style->clip_path->value, "none") != 0)
+		lsm_svg_view_pop_clip (view);
+
+	view->style_stack = g_slist_delete_link (view->style_stack, view->style_stack);
+	view->style = view->style_stack != NULL ? view->style_stack->data : NULL;
 }
 
-void
-lsm_svg_view_pop_text_attributes (LsmSvgView *view)
+const LsmSvgStyle *
+lsm_svg_view_get_current_style (LsmSvgView *view)
 {
-	g_return_if_fail (LSM_IS_SVG_VIEW (view));
-	g_return_if_fail (view->text_stack != NULL);
+	g_return_val_if_fail (LSM_IS_SVG_VIEW (view), NULL);
 
-	view->text_stack = g_slist_delete_link (view->text_stack, view->text_stack);
+	return view->style;
 }
 
 const LsmBox *
@@ -1562,8 +1533,6 @@ lsm_svg_view_measure (LsmDomView *view, double *width, double *height)
 	if (svg_element == NULL)
 		return;
 
-	lsm_svg_svg_element_update (svg_element);
-
 	lsm_svg_svg_element_measure (svg_element, width, height);
 }
 
@@ -1579,14 +1548,9 @@ lsm_svg_view_render (LsmDomView *view)
 	if (svg_element == NULL)
 		return;
 
-	lsm_svg_svg_element_update (svg_element);
-
+	svg_view->style_stack = NULL;
 	svg_view->element_stack = NULL;
 	svg_view->viewbox_stack = NULL;
-	svg_view->mask_stack = NULL;
-	svg_view->fill_stack = NULL;
-	svg_view->stroke_stack = NULL;
-	svg_view->text_stack = NULL;
 	svg_view->matrix_stack = NULL;
 
 	svg_view->is_clipping = FALSE;
@@ -1608,31 +1572,16 @@ lsm_svg_view_render (LsmDomView *view)
 		g_slist_free (svg_view->viewbox_stack);
 		svg_view->viewbox_stack = NULL;
 	}
-	if (svg_view->fill_stack != NULL) {
-		g_warning ("[LsmSvgView::render] Dangling fill attributes in stack");
-		g_slist_free (svg_view->fill_stack);
-		svg_view->fill_stack = NULL;
-	}
-	if (svg_view->stroke_stack != NULL) {
-		g_warning ("[LsmSvgView::render] Dangling stroke attributes in stack");
-		g_slist_free (svg_view->stroke_stack);
-		svg_view->stroke_stack = NULL;
-	}
-	if (svg_view->mask_stack != NULL) {
-		g_warning ("[LsmSvgView::render] Dangling mask attributes in stack");
-		g_slist_free (svg_view->mask_stack);
-		svg_view->mask_stack = NULL;
-	}
-	if (svg_view->text_stack != NULL) {
-		g_warning ("[LsmSvgView::render] Dangling text attribute in stack");
-		g_slist_free (svg_view->text_stack);
-		svg_view->text_stack = NULL;
-	}
 	if (svg_view->element_stack != NULL) {
 		g_warning ("[LsmSvgView::render] Dangling element in stack");
 		g_slist_free (svg_view->element_stack);
 		svg_view->element_stack = NULL;
 	}
+	if (svg_view->style_stack != NULL) {
+		g_warning ("[LsmSvgView::render] Dangling style in stack");
+		g_slist_free (svg_view->style_stack);
+		svg_view->style_stack = NULL;
+	}
 }
 
 LsmSvgView *
diff --git a/src/lsmsvgview.h b/src/lsmsvgview.h
index d295ffe..b960b05 100644
--- a/src/lsmsvgview.h
+++ b/src/lsmsvgview.h
@@ -51,12 +51,11 @@ struct _LsmSvgView {
 
 	double resolution_ppi;
 
+	const LsmSvgStyle *style;
+
+	GSList *style_stack;
 	GSList *element_stack;
 	GSList *viewbox_stack;
-	GSList *mask_stack;
-	GSList *fill_stack;
-	GSList *stroke_stack;
-	GSList *text_stack;
 	GSList *matrix_stack;
 
 	LsmSvgViewPatternData *pattern_data;
@@ -65,6 +64,8 @@ struct _LsmSvgView {
 
 	gboolean is_clipping;
 	LsmBox clip_extents;
+
+	double last_stop_offset;
 };
 
 struct _LsmSvgViewClass {
@@ -85,8 +86,7 @@ void 		lsm_svg_view_create_radial_gradient 	(LsmSvgView *view, double cx, double
 							                   double r, double fx, double fy);
 void 		lsm_svg_view_create_linear_gradient 	(LsmSvgView *view, double x1, double y1,
 							                   double x2, double y2);
-void 		lsm_svg_view_add_gradient_color_stop	(LsmSvgView *view, double offset,
-							 const LsmSvgColor *color, double opacity);
+void 		lsm_svg_view_add_gradient_color_stop	(LsmSvgView *view, double offset);
 void 		lsm_svg_view_set_gradient_properties	(LsmSvgView *view,
 							 LsmSvgSpreadMethod method,
 							 LsmSvgPatternUnits units,
@@ -116,7 +116,7 @@ void 		lsm_svg_view_push_viewport 		(LsmSvgView *view, const LsmBox *viewport,
 							 const LsmBox *viewbox,
 							 const LsmSvgPreserveAspectRatio *aspect_ratio);
 void 		lsm_svg_view_pop_viewport 		(LsmSvgView *view);
-void 		lsm_svg_view_push_matrix		(LsmSvgView *view, LsmSvgMatrix *matrix);
+void 		lsm_svg_view_push_matrix		(LsmSvgView *view, const LsmSvgMatrix *matrix);
 void 		lsm_svg_view_pop_matrix			(LsmSvgView *view);
 
 void		lsm_svg_view_push_element		(LsmSvgView *view, const LsmSvgElement *element);
@@ -125,14 +125,10 @@ void		lsm_svg_view_pop_element		(LsmSvgView *view);
 void 		lsm_svg_view_push_group_opacity 	(LsmSvgView *view);
 void 		lsm_svg_view_pop_group_opacity 		(LsmSvgView *view);
 
-void		lsm_svg_view_push_mask_attributes	(LsmSvgView *view, const LsmSvgMaskAttributeBag *mask);
-void		lsm_svg_view_pop_mask_attributes	(LsmSvgView *view);
-void 		lsm_svg_view_push_fill_attributes 	(LsmSvgView *view, const LsmSvgFillAttributeBag *fill);
-void 		lsm_svg_view_pop_fill_attributes 	(LsmSvgView *view);
-void 		lsm_svg_view_push_stroke_attributes 	(LsmSvgView *view, const LsmSvgStrokeAttributeBag *stroke);
-void 		lsm_svg_view_pop_stroke_attributes 	(LsmSvgView *view);
-void 		lsm_svg_view_push_text_attributes 	(LsmSvgView *view, const LsmSvgTextAttributeBag *text);
-void 		lsm_svg_view_pop_text_attributes 	(LsmSvgView *view);
+void		lsm_svg_view_push_style			(LsmSvgView *view, const LsmSvgStyle *style);
+void		lsm_svg_view_pop_style			(LsmSvgView *view);
+
+const LsmSvgStyle *	lsm_svg_view_get_current_style	(LsmSvgView *view);
 
 G_END_DECLS
 
diff --git a/test/.gitignore b/test/.gitignore
index d109f53..b4dc037 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -1,3 +1,2 @@
-lasemtest.xml
 log
 *-out.png



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