[lasem] [SVG] A first try at handling viewport correctly.



commit 9e48a6eb91d6727458b8de84fb3f1311b8b7817a
Author: Emmanuel Pacaud <emmanuel pacaud lapp in2p3 fr>
Date:   Fri May 8 18:05:24 2009 +0200

    [SVG] A first try at handling viewport correctly.
    
    There's still some issues with gradients and pattern, when units are
    the object bounding box.
---
 src/lasemrender.c                 |   26 ++++++---
 src/lasemtest.c                   |   19 ++++---
 src/lsmdomattributes.c            |    2 -
 src/lsmdomdocument.c              |   51 ++++++++++++++++
 src/lsmdomdocument.h              |   30 +++++++---
 src/lsmdomview.c                  |   53 ++++++++++++++---
 src/lsmdomview.h                  |    9 ++-
 src/lsmmathmlview.c               |    8 +--
 src/lsmsvg.h                      |    2 +-
 src/lsmsvgattributebags.c         |   12 ++--
 src/lsmsvgattributes.c            |  118 ++++++++++++++++++++++++-------------
 src/lsmsvgattributes.h            |   20 +++++--
 src/lsmsvgcircleelement.c         |    9 ++-
 src/lsmsvgellipseelement.c        |   12 +++-
 src/lsmsvgenums.h                 |    6 ++
 src/lsmsvggradientelement.c       |   12 +++-
 src/lsmsvggraphic.c               |   20 ++++---
 src/lsmsvglineargradientelement.c |   28 +++++----
 src/lsmsvglineelement.c           |   12 +++-
 src/lsmsvgpatternelement.c        |   12 +++-
 src/lsmsvgradialgradientelement.c |   41 +++++++------
 src/lsmsvgrectelement.c           |   18 ++++--
 src/lsmsvgstopelement.c           |    3 +-
 src/lsmsvgstyle.h                 |   15 ++++-
 src/lsmsvgsvgelement.c            |  100 ++++++++++++++++++++++++-------
 src/lsmsvgtextelement.c           |    6 +-
 src/lsmsvguseelement.c            |   12 +++-
 src/lsmsvgview.c                  |    2 +-
 28 files changed, 464 insertions(+), 194 deletions(-)

diff --git a/src/lasemrender.c b/src/lasemrender.c
index 9b3b21a..af70dda 100644
--- a/src/lasemrender.c
+++ b/src/lasemrender.c
@@ -92,7 +92,8 @@ int main(int argc, char **argv)
 	char *mime;
 	char *buffer = NULL;
 	size_t size;
-	double height, width;
+	double height_pt, width_pt;
+	unsigned int height, width;
 	gboolean success;
 
 	g_type_init ();
@@ -186,28 +187,37 @@ int main(int argc, char **argv)
 
 		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);
 
-				lsm_dom_view_measure (view, &width, &height);
+				width_pt = 2.0;
+				height_pt = 2.0;
+
+				lsm_dom_view_get_size (view, &width_pt, &height_pt);
+				lsm_dom_view_get_size_px (view, &width, &height);
 
 				switch (format) {
 					case FORMAT_PDF:
-						surface = cairo_pdf_surface_create (output_filename, width, height);
+						surface = cairo_pdf_surface_create (output_filename,
+										    width_pt, height_pt);
 						break;
 					case FORMAT_PS:
-						surface = cairo_ps_surface_create (output_filename, width, height);
+						surface = cairo_ps_surface_create (output_filename,
+										   width_pt, height_pt);
 						break;
 					case FORMAT_PNG:
 						surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
-										      width * option_ppi / 72.0 + 0.5,
-										      height * option_ppi / 72.0 + 0.5);
+										      width,
+										      height);
 						break;
 					case FORMAT_SVG:
 					default:
-						surface = cairo_svg_surface_create (output_filename, width, height);
+						surface = cairo_svg_surface_create (output_filename,
+										    width_pt, height_pt);
 						break;
 				}
 
@@ -236,7 +246,7 @@ int main(int argc, char **argv)
 
 				g_object_unref (document);
 
-				lsm_debug ("width = %g pt, height = %g pt",  width, height);
+				lsm_debug ("width = %g pt, height = %g pt",  width_pt, height_pt);
 			} else
 				g_warning ("Can't load %s", input_filename);
 		} else
diff --git a/src/lasemtest.c b/src/lasemtest.c
index 122d4b2..dd8da14 100644
--- a/src/lasemtest.c
+++ b/src/lasemtest.c
@@ -39,7 +39,6 @@
 
 #include <../itex2mml/itex2MML.h>
 
-#define TEST_WIDTH 	480
 #define XML_FILENAME	"lasemtest.xml"
 
 static const char *fail_face = "", *normal_face = "";
@@ -71,7 +70,7 @@ lasem_test_render (char const *filename)
 	char *reference_png_filename;
 	char *test_name;
 	char *mime;
-	double width, height;
+	unsigned int width, height;
 	gboolean is_xml, success;
 	gboolean is_svg;
 	gboolean is_mathml;
@@ -106,9 +105,11 @@ lasem_test_render (char const *filename)
 
 		view = lsm_dom_document_create_view (document);
 
-		lsm_dom_view_measure (LSM_DOM_VIEW (view), &width, &height);
+		lsm_dom_document_set_viewport_px (document, 480.0, 360.0);
+		lsm_dom_document_set_resolution (document, 96.0);
+		lsm_dom_view_get_size_px (LSM_DOM_VIEW (view), &width, &height);
 
-		surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width + 2.5, height + 2.5);
+		surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width + 2, height + 2);
 		cairo = cairo_create (surface);
 		cairo_surface_destroy (surface);
 
@@ -125,6 +126,11 @@ lasem_test_render (char const *filename)
 
 		lasem_test_html ("<table border=\"1\" cellpadding=\"8\">\n");
 		lasem_test_html ("<tr>");
+
+		lasem_test_html ("<td><a href=\"%s\"><img border=\"0\" src=\"%s\"/></a></td>",
+				   filename, png_filename);
+		lasem_test_html ("<td><img src=\"%s\"/></td>", reference_png_filename);
+
 		lasem_test_html ("<td>");
 
 		if (is_mathml) {
@@ -145,13 +151,10 @@ lasem_test_render (char const *filename)
 		if (is_svg) {
 			lasem_test_html ("<object type=\"image/svg+xml\" data=\"");
 			lasem_test_html (filename);
-			lasem_test_html ("\" width=\"320\"/>");
+			lasem_test_html ("\" width=\"480\"/>");
 		}
 
 		lasem_test_html ("</td>");
-		lasem_test_html ("<td><a href=\"%s\"><img border=\"0\" src=\"%s\"/></a></td>",
-				   filename, png_filename);
-		lasem_test_html ("<td><img src=\"%s\"/></td>", reference_png_filename);
 		lasem_test_html ("</tr>\n");
 		lasem_test_html ("</table>\n");
 
diff --git a/src/lsmdomattributes.c b/src/lsmdomattributes.c
index a871c1d..3898164 100644
--- a/src/lsmdomattributes.c
+++ b/src/lsmdomattributes.c
@@ -106,8 +106,6 @@ lsm_dom_attribute_map_add_bag_attribute  (LsmDomAttributeMap *map,
 	attribute_infos->attribute_offset = attribute_offset;
 	attribute_infos->attribute_class = attribute_class;
 
-	lsm_debug ("name = %s - attribute_offset = %d", name, attribute_offset);
-
 	g_hash_table_insert (map->attribute_hash, (char *) name, attribute_infos);
 
 	if (bag_class != NULL) {
diff --git a/src/lsmdomdocument.c b/src/lsmdomdocument.c
index d6e902a..d96a6ba 100644
--- a/src/lsmdomdocument.c
+++ b/src/lsmdomdocument.c
@@ -84,6 +84,54 @@ lsm_dom_document_create_view (LsmDomDocument *self)
 	return LSM_DOM_DOCUMENT_GET_CLASS (self)->create_view (self);
 }
 
+double
+lsm_dom_document_get_resolution (LsmDomDocument *self)
+{
+	g_return_val_if_fail (LSM_IS_DOM_DOCUMENT (self), 0.0);
+
+	return self->resolution_ppi;
+}
+
+void
+lsm_dom_document_set_resolution (LsmDomDocument *self, double ppi)
+{
+	g_return_if_fail (LSM_IS_DOM_DOCUMENT (self));
+
+	if (ppi < 0.0)
+		self->resolution_ppi = LSM_DOM_DOCUMENT_DEFAULT_RESOLUTION;
+	else
+		self->resolution_ppi = ppi;
+}
+
+void
+lsm_dom_document_set_viewport (LsmDomDocument *self, double width, double height)
+{
+	g_return_if_fail (LSM_IS_DOM_DOCUMENT (self));
+
+	self->viewport_width = width;
+	self->viewport_height = height;
+}
+
+void
+lsm_dom_document_set_viewport_px (LsmDomDocument *self, double width, double height)
+{
+	g_return_if_fail (LSM_IS_DOM_DOCUMENT (self));
+
+	self->viewport_width  = width  * 72.0 / self->resolution_ppi;
+	self->viewport_height = height * 72.0 / self->resolution_ppi;
+}
+
+void
+lsm_dom_document_get_viewport (LsmDomDocument *self, double *width, double *height)
+{
+	g_return_if_fail (LSM_IS_DOM_DOCUMENT (self));
+
+	if (width != NULL)
+		*width = self->viewport_width;
+	if (height != NULL)
+		*height = self->viewport_height;
+}
+
 LsmDomElement *
 lsm_dom_document_get_element_by_id (LsmDomDocument *self, const char *id)
 {
@@ -125,6 +173,9 @@ lsm_dom_document_init (LsmDomDocument *document)
 {
 	document->ids = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
 	document->elements = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL);
+	document->resolution_ppi = LSM_DOM_DOCUMENT_DEFAULT_RESOLUTION;
+	document->viewport_width = LSM_DOM_DOCUMENT_DEFAULT_VIEWPORT_WIDTH;
+	document->viewport_height = LSM_DOM_DOCUMENT_DEFAULT_VIEWPORT_HEIGHT;
 }
 
 static void
diff --git a/src/lsmdomdocument.h b/src/lsmdomdocument.h
index 64cb5a8..1ef081b 100644
--- a/src/lsmdomdocument.h
+++ b/src/lsmdomdocument.h
@@ -29,6 +29,10 @@
 
 G_BEGIN_DECLS
 
+#define LSM_DOM_DOCUMENT_DEFAULT_RESOLUTION 		 72.0
+#define LSM_DOM_DOCUMENT_DEFAULT_VIEWPORT_WIDTH		320.0
+#define LSM_DOM_DOCUMENT_DEFAULT_VIEWPORT_HEIGHT 	200.0
+
 #define LSM_TYPE_DOM_DOCUMENT             (lsm_dom_document_get_type ())
 #define LSM_DOM_DOCUMENT(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), LSM_TYPE_DOM_DOCUMENT, LsmDomDocument))
 #define LSM_DOM_DOCUMENT_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), LSM_TYPE_DOM_DOCUMENT, LsmDomDocumentClass))
@@ -43,28 +47,38 @@ struct _GDomDocument {
 
 	GHashTable *		ids;
 	GHashTable *		elements;
+
+	/* Not really a document property, but that simplifies things greatly */
+	double resolution_ppi;
+	double viewport_width;
+	double viewport_height;
 };
 
 struct _GDomDocumentClass {
 	LsmDomNodeClass parent_class;
 
-	LsmDomElement * 	(*get_document_element) (LsmDomDocument* self);
-	LsmDomElement * 	(*create_element) (LsmDomDocument* self, const char *tag_name);
-	LsmDomText * 	(*create_text_node) (LsmDomDocument* self, const char *data);
+	LsmDomElement *	(*get_document_element) (LsmDomDocument* self);
+	LsmDomElement *	(*create_element) 	(LsmDomDocument* self, const char *tag_name);
+	LsmDomText * 	(*create_text_node) 	(LsmDomDocument* self, const char *data);
 
-	LsmDomView*	(*create_view) (LsmDomDocument *self);
+	LsmDomView*	(*create_view) 		(LsmDomDocument *self);
 };
 
 GType lsm_dom_document_get_type (void);
 
 LsmDomElement* 	lsm_dom_document_get_document_element 	(LsmDomDocument* self);
-LsmDomElement* 	lsm_dom_document_create_element 		(LsmDomDocument* self, const char *tag_name);
-LsmDomText* 	lsm_dom_document_create_text_node 		(LsmDomDocument* self, const char *data);
-LsmDomElement * 	lsm_dom_document_get_element_by_id 	(LsmDomDocument *self, const char *id);
+LsmDomElement* 	lsm_dom_document_create_element 	(LsmDomDocument* self, const char *tag_name);
+LsmDomText* 	lsm_dom_document_create_text_node 	(LsmDomDocument* self, const char *data);
+LsmDomElement *	lsm_dom_document_get_element_by_id 	(LsmDomDocument *self, const char *id);
 
-void 		lsm_dom_document_register_element	 	(LsmDomDocument *self, LsmDomElement *element, const char *id);
+void 		lsm_dom_document_register_element 	(LsmDomDocument *self, LsmDomElement *element, const char *id);
 
 LsmDomView*	lsm_dom_document_create_view		(LsmDomDocument *self);
+double		lsm_dom_document_get_resolution		(LsmDomDocument *self);
+void		lsm_dom_document_set_resolution		(LsmDomDocument *self, double ppi);
+void 		lsm_dom_document_set_viewport 		(LsmDomDocument *self, double width, double height);
+void 		lsm_dom_document_get_viewport 		(LsmDomDocument *self, double *width, double *height);
+void 		lsm_dom_document_set_viewport_px 	(LsmDomDocument *self, double width, double height);
 
 G_END_DECLS
 
diff --git a/src/lsmdomview.c b/src/lsmdomview.c
index a524dbf..2a80075 100644
--- a/src/lsmdomview.c
+++ b/src/lsmdomview.c
@@ -26,16 +26,19 @@
 static GObjectClass *parent_class;
 
 void
-lsm_dom_view_measure (LsmDomView *view, double *width, double *height)
+lsm_dom_view_get_size (LsmDomView *view, double *width, double *height)
 {
 	LsmDomViewClass *view_class;
-
-	if (width != NULL)
-		*width = 0.0;
-	if (height != NULL)
-		*height = 0.0;
+	double dummy_width = 0.0;
+	double dummy_height = 0.0;
 
 	g_return_if_fail (LSM_IS_DOM_VIEW (view));
+	g_return_if_fail (view->document != NULL);
+
+	if (width == NULL)
+		width = &dummy_width;
+	if (height == NULL)
+		height = &dummy_height;
 
 	view_class = LSM_DOM_VIEW_GET_CLASS (view);
 	if (view_class->measure != NULL)
@@ -43,16 +46,50 @@ lsm_dom_view_measure (LsmDomView *view, double *width, double *height)
 }
 
 void
+lsm_dom_view_get_size_px (LsmDomView *view, unsigned int *width, unsigned int *height)
+{
+	double resolution_ppi;
+	double width_pt;
+	double height_pt;
+
+	g_return_if_fail (LSM_IS_DOM_VIEW (view));
+	g_return_if_fail (view->document != NULL);
+
+	resolution_ppi = lsm_dom_document_get_resolution (view->document);
+	g_return_if_fail (resolution_ppi > 0.0);
+
+	width_pt =  width  != NULL ? *width  * 72.0 / resolution_ppi : 0.0;
+	height_pt = height != NULL ? *height * 72.0 / resolution_ppi : 0.0;
+
+	lsm_dom_view_get_size (view, &width_pt, &height_pt);
+
+	if (width != NULL)
+		*width =  (double) (0.5 + width_pt  * resolution_ppi / 72.0);
+	if (height != NULL)
+		*height = (double) (0.5 + height_pt * resolution_ppi / 72.0);
+}
+
+void
 lsm_dom_view_render (LsmDomView *view, double x, double y)
 {
 	LsmDomViewClass *view_class;
+	double resolution_ppi;
 
 	g_return_if_fail (LSM_IS_DOM_VIEW (view));
+	g_return_if_fail (LSM_IS_DOM_DOCUMENT (view->document));
 	g_return_if_fail (view->cairo != NULL);
 
+	resolution_ppi = lsm_dom_document_get_resolution (view->document);
+
+	cairo_save (view->cairo);
+
+	cairo_translate (view->cairo, x, y);
+
 	view_class = LSM_DOM_VIEW_GET_CLASS (view);
-	if (view_class->measure != NULL)
-		view_class->render (view, x, y);
+	if (view_class->render != NULL)
+		view_class->render (view);
+
+	cairo_restore (view->cairo);
 }
 
 void
diff --git a/src/lsmdomview.h b/src/lsmdomview.h
index 1aab9e3..dce3d6f 100644
--- a/src/lsmdomview.h
+++ b/src/lsmdomview.h
@@ -56,16 +56,17 @@ struct _GDomViewClass {
 
 	GType document_type;
 
-	void (*measure)		(LsmDomView *view, double *width, double *height);
-	void (*render)		(LsmDomView *view, double x, double y);
+	void (*measure)	(LsmDomView *view, double *width, double *height);
+	void (*render)	(LsmDomView *view);
 };
 
 GType lsm_dom_view_get_type (void);
 
 void 			lsm_dom_view_render 		(LsmDomView *view, double x, double y);
-void			lsm_dom_view_measure 		(LsmDomView *view, double *width, double *height);
+void			lsm_dom_view_get_size		(LsmDomView *view, double *width, double *height);
+void 			lsm_dom_view_get_size_px 	(LsmDomView *view, unsigned int *width, unsigned int *height);
 
-void 			lsm_dom_view_set_document 		(LsmDomView *view, LsmDomDocument *document);
+void 			lsm_dom_view_set_document 	(LsmDomView *view, LsmDomDocument *document);
 void			lsm_dom_view_set_cairo 		(LsmDomView *view, cairo_t *cr);
 
 void			lsm_dom_view_set_debug 		(LsmDomView *view, gboolean debug);
diff --git a/src/lsmmathmlview.c b/src/lsmmathmlview.c
index e94c443..a606977 100644
--- a/src/lsmmathmlview.c
+++ b/src/lsmmathmlview.c
@@ -960,7 +960,7 @@ lsm_mathml_view_measure (LsmDomView *dom_view, double *width, double *height)
 }
 
 static void
-lsm_mathml_view_render (LsmDomView *dom_view, double x, double y)
+lsm_mathml_view_render (LsmDomView *dom_view)
 {
 	LsmMathmlView *view = LSM_MATHML_VIEW (dom_view);
 	LsmMathmlMathElement *math_element;
@@ -977,15 +977,11 @@ lsm_mathml_view_render (LsmDomView *dom_view, double x, double y)
 
 	cairo = view->dom_view.cairo;
 
-	cairo_save (view->dom_view.cairo);
-
-	cairo_translate (cairo, x, y + bbox->height);
+	cairo_translate (cairo, 0, bbox->height);
 
 	lsm_mathml_math_element_render (math_element, view);
 
 	lsm_debug ("[LsmMathmlView::render] cairo status = %s", cairo_status_to_string (cairo_status (cairo)));
-
-	cairo_restore (cairo);
 }
 
 LsmMathmlView *
diff --git a/src/lsmsvg.h b/src/lsmsvg.h
index ee1f513..6bf6b06 100644
--- a/src/lsmsvg.h
+++ b/src/lsmsvg.h
@@ -49,7 +49,7 @@ typedef struct _GSvgStopElement LsmSvgStopElement;
 typedef struct _GSvgPatternElement LsmSvgPatternElement;
 
 typedef struct _GSvgView LsmSvgView;
-typedef struct _GSvgStyle LsmSvgStyle;
+typedef struct _LsmSvgStyle LsmSvgStyle;
 
 G_END_DECLS
 
diff --git a/src/lsmsvgattributebags.c b/src/lsmsvgattributebags.c
index 1dec313..e1f2d15 100644
--- a/src/lsmsvgattributebags.c
+++ b/src/lsmsvgattributebags.c
@@ -184,14 +184,14 @@ void
 lsm_dom_attribute_map_add_text_attribute_bag (LsmDomAttributeMap *map, ptrdiff_t bag_offset)
 {
 	lsm_dom_attribute_map_add_bag_attribute (map, "font-family",
-					      offsetof (LsmSvgTextAttributeBag, font_family),
-					      &lsm_dom_string_attribute_class,
-					      bag_offset, &lsm_svg_text_attribute_bag_class);
+						 offsetof (LsmSvgTextAttributeBag, font_family),
+						 &lsm_dom_string_attribute_class,
+						 bag_offset, &lsm_svg_text_attribute_bag_class);
 
 	lsm_dom_attribute_map_add_bag_attribute (map, "font-size",
-					      offsetof (LsmSvgTextAttributeBag, font_size),
-					      NULL,
-					      bag_offset, &lsm_svg_text_attribute_bag_class);
+						 offsetof (LsmSvgTextAttributeBag, font_size),
+						 NULL,
+						 bag_offset, &lsm_svg_text_attribute_bag_class);
 }
 
 static void *
diff --git a/src/lsmsvgattributes.c b/src/lsmsvgattributes.c
index 99cce39..ba5e4a5 100644
--- a/src/lsmsvgattributes.c
+++ b/src/lsmsvgattributes.c
@@ -22,6 +22,7 @@
 #include <lsmsvgattributes.h>
 #include <lsmsvgcolors.h>
 #include <lsmsvgutils.h>
+#include <lsmsvgstyle.h>
 #include <lsmdebug.h>
 #include <string.h>
 #include <stdlib.h>
@@ -75,6 +76,19 @@ lsm_svg_dash_array_duplicate (const LsmSvgDashArray *origin)
 	return duplicate;
 }
 
+static const char *
+lsm_svg_attribute_get_value (LsmDomAttribute *attribute)
+{
+	const char *string;
+
+	string = lsm_dom_attribute_get_value ((LsmDomAttribute *) attribute);
+
+	if (g_strcmp0 (string, "inherit") == 0)
+		return NULL;
+
+	return string;
+}
+
 const LsmSvgColor lsm_svg_color_null = {0.0, 0.0, 0.0};
 
 void
@@ -86,10 +100,7 @@ lsm_svg_double_attribute_parse (LsmSvgDoubleAttribute *attribute,
 	g_return_if_fail (attribute != NULL);
 	g_return_if_fail (double_value != NULL);
 
-	string = lsm_dom_attribute_get_value ((LsmDomAttribute *) attribute);
-
-	if (g_strcmp0 (string, "inherit") == 0)
-		string = NULL;
+	string = lsm_svg_attribute_get_value ((LsmDomAttribute *) attribute);
 
 	if (string == NULL) {
 		attribute->value = *double_value;
@@ -101,40 +112,67 @@ lsm_svg_double_attribute_parse (LsmSvgDoubleAttribute *attribute,
 }
 
 static double
-lsm_svg_length_compute (const LsmSvgLength *length, double viewbox, double font_size)
+lsm_svg_length_compute (const LsmSvgLength *length,
+			const LsmSvgStyle *style,
+			LsmSvgLengthDirection direction)
 {
+	double viewport;
+	double viewport_scale;
+
 	g_return_val_if_fail (length != NULL, 0.0);
 
+	switch (direction) {
+		case LSM_SVG_LENGTH_DIRECTION_HORIZONTAL:
+			viewport = style->viewport.width;
+			viewport_scale = style->viewport.horizontal_scale;
+			break;
+		case LSM_SVG_LENGTH_DIRECTION_VERTICAL:
+			viewport = style->viewport.height;
+			viewport_scale = style->viewport.vertical_scale;
+			break;
+		case LSM_SVG_LENGTH_DIRECTION_DIAGONAL:
+			viewport = style->viewport.diagonal;
+			viewport_scale = style->viewport.diagonal_scale;
+			break;
+		default:
+			viewport = 0.0;
+			viewport_scale = 0.0;
+	}
+
 	switch (length->type) {
+		case LSM_SVG_LENGTH_TYPE_NUMBER:
+		case LSM_SVG_LENGTH_TYPE_UNKNOWN:
+			return length->value_unit;
+		case LSM_SVG_LENGTH_TYPE_PERCENTAGE:
+			return length->value_unit * viewport / 100.0;
 		case LSM_SVG_LENGTH_TYPE_PX:
+			return length->value_unit * 72.0 * viewport_scale / style->resolution_ppi;
 		case LSM_SVG_LENGTH_TYPE_PT:
-			return length->value_unit;
+			return length->value_unit * viewport_scale;
 		case LSM_SVG_LENGTH_TYPE_PC:
-			return length->value_unit * 72.0 / 6.0;
+			return length->value_unit * 72.0 * viewport_scale / 6.0;
 		case LSM_SVG_LENGTH_TYPE_CM:
-			return length->value_unit * 72.0 / 2.54;
+			return length->value_unit * 72.0 * viewport_scale / 2.54;
 		case LSM_SVG_LENGTH_TYPE_MM:
-			return length->value_unit * 72.0 / 25.4;
+			return length->value_unit * 72.0 * viewport_scale / 25.4;
 		case LSM_SVG_LENGTH_TYPE_IN:
-			return length->value_unit * 72.0;
+			return length->value_unit * 72.0 * viewport_scale;
 		case LSM_SVG_LENGTH_TYPE_EMS:
-			return length->value_unit * font_size;
+			return length->value_unit * style->text.font_size.value;
 		case LSM_SVG_LENGTH_TYPE_EXS:
-			return length->value_unit * font_size * 0.5;
-		case LSM_SVG_LENGTH_TYPE_PERCENTAGE:
-			return viewbox * length->value_unit / 100.0;
-		case LSM_SVG_LENGTH_TYPE_NUMBER:
-		case LSM_SVG_LENGTH_TYPE_UNKNOWN:
-			return length->value_unit;
+			return length->value_unit * style->text.font_size.value * 0.5;
 	}
 
+	g_warning ("[LsmSvgLength::compute] Invalid length property");
+
 	return 0.0;
 }
 
 void
 lsm_svg_length_attribute_parse (LsmSvgLengthAttribute *attribute,
 				LsmSvgLength *default_value,
-				double font_size)
+				const LsmSvgStyle *style,
+				LsmSvgLengthDirection direction)
 {
 	const char *string;
 	char *length_type_str;
@@ -142,6 +180,7 @@ lsm_svg_length_attribute_parse (LsmSvgLengthAttribute *attribute,
 	g_return_if_fail (attribute != NULL);
 
 	string = lsm_dom_attribute_get_value ((LsmDomAttribute *) attribute);
+
 	if (string == NULL) {
 		g_return_if_fail (default_value != NULL);
 
@@ -149,8 +188,7 @@ lsm_svg_length_attribute_parse (LsmSvgLengthAttribute *attribute,
 	} else {
 		attribute->length.value_unit = g_strtod (string, &length_type_str);
 		attribute->length.type = lsm_svg_length_type_from_string (length_type_str);
-		attribute->length.value = lsm_svg_length_compute (&attribute->length,
-								  default_value->value, font_size);
+		attribute->length.value = lsm_svg_length_compute (&attribute->length, style, direction);
 
 		*default_value = attribute->length;
 	}
@@ -159,7 +197,8 @@ lsm_svg_length_attribute_parse (LsmSvgLengthAttribute *attribute,
 void
 lsm_svg_animated_length_attribute_parse (LsmSvgAnimatedLengthAttribute *attribute,
 					 LsmSvgLength *default_value,
-					 double font_size)
+					 const LsmSvgStyle *style,
+					 LsmSvgLengthDirection direction)
 {
 	const char *string;
 	char *length_type_str;
@@ -175,8 +214,7 @@ lsm_svg_animated_length_attribute_parse (LsmSvgAnimatedLengthAttribute *attribut
 	} else {
 		attribute->length.base.value_unit = g_strtod (string, &length_type_str);
 		attribute->length.base.type = lsm_svg_length_type_from_string (length_type_str);
-		attribute->length.base.value = lsm_svg_length_compute (&attribute->length.base,
-								       default_value->value, font_size);
+		attribute->length.base.value = lsm_svg_length_compute (&attribute->length.base, style, direction);
 		attribute->length.animated = attribute->length.base;
 
 		*default_value = attribute->length.base;
@@ -196,15 +234,15 @@ lsm_svg_dash_array_attribute_finalize (void *abstract)
 
 void
 lsm_svg_dash_array_attribute_parse (LsmSvgDashArrayAttribute *attribute,
-				    LsmSvgDashArray **default_value)
+				    LsmSvgDashArray **default_value,
+				    const LsmSvgStyle *style,
+				    LsmSvgLengthDirection direction)
 {
 	const char *string;
 
 	g_return_if_fail (attribute != NULL);
 
-	string = lsm_dom_attribute_get_value ((LsmDomAttribute *) attribute);
-	if (g_strcmp0 (string, "inherit") == 0)
-		string = NULL;
+	string = lsm_svg_attribute_get_value ((LsmDomAttribute *) attribute);
 
 	if (string == NULL) {
 		lsm_svg_dash_array_free (attribute->value);
@@ -236,8 +274,8 @@ lsm_svg_dash_array_attribute_parse (LsmSvgDashArrayAttribute *attribute,
 				for (i = 0; i < n_dashes; i++) {
 					if (lsm_svg_str_parse_double (&iter, &length.value_unit)) {
 						length.type = lsm_svg_length_type_from_string (iter);
-						attribute->value->dashes[i] = lsm_svg_length_compute (&length,
-												      0.0, 0.0);
+						attribute->value->dashes[i] =
+							lsm_svg_length_compute (&length, style, direction);
 						while (*iter != '\0' && *iter != ' ' && *iter != ',')
 							iter ++;
 					} else
@@ -395,7 +433,7 @@ lsm_svg_paint_attribute_parse (LsmSvgPaintAttribute *attribute,
 
 	g_return_if_fail (attribute != NULL);
 
-	string = (char *) lsm_dom_attribute_get_value ((LsmDomAttribute *) attribute);
+	string = (char *) lsm_svg_attribute_get_value ((LsmDomAttribute *) attribute);
 
 	if (string == NULL) {
 		g_free (attribute->paint.uri);
@@ -460,10 +498,7 @@ lsm_svg_color_attribute_parse (LsmSvgColorAttribute *attribute,
 
 	g_return_if_fail (attribute != NULL);
 
-	string = (char *) lsm_dom_attribute_get_value ((LsmDomAttribute *) attribute);
-
-	if (g_strcmp0 (string, "inherit") == 0)
-		string = NULL;
+	string = (char *) lsm_svg_attribute_get_value ((LsmDomAttribute *) attribute);
 
 	if (string == NULL) {
 		attribute->value = *default_value;
@@ -477,19 +512,15 @@ lsm_svg_color_attribute_parse (LsmSvgColorAttribute *attribute,
 }
 
 void
-lsm_svg_view_box_attribute_parse (LsmSvgViewBoxAttribute *attribute,
-				  LsmSvgViewBox *default_value)
+lsm_svg_view_box_attribute_parse (LsmSvgViewBoxAttribute *attribute)
 {
 	char *string;
 
 	g_return_if_fail (attribute != NULL);
 
 	string = (char *) lsm_dom_attribute_get_value ((LsmDomAttribute *) attribute);
-	if (string == NULL) {
-		g_return_if_fail (default_value != NULL);
 
-		attribute->value = *default_value;
-	} else {
+	if (string != NULL) {
 		unsigned int i;
 		double value[4];
 
@@ -511,8 +542,11 @@ lsm_svg_view_box_attribute_parse (LsmSvgViewBoxAttribute *attribute,
 			attribute->value.width = 0;
 			attribute->value.height = 0;
 		}
-
-		*default_value = attribute->value;
+	} else {
+		attribute->value.x = 0;
+		attribute->value.y = 0;
+		attribute->value.width = 0;
+		attribute->value.height = 0;
 	}
 }
 
diff --git a/src/lsmsvgattributes.h b/src/lsmsvgattributes.h
index ca66f49..9cc43eb 100644
--- a/src/lsmsvgattributes.h
+++ b/src/lsmsvgattributes.h
@@ -120,19 +120,27 @@ typedef struct {
 	LsmSvgMatrix matrix;
 } LsmSvgTransformAttribute;
 
+
+/* Properties */
+
 void 		lsm_svg_double_attribute_parse 		(LsmSvgDoubleAttribute *attribute,
 							 double *double_value);
 void		lsm_svg_length_attribute_parse 		(LsmSvgLengthAttribute *attribute,
 							 LsmSvgLength *default_value,
-							 double font_size);
+							 const LsmSvgStyle *style,
+							 LsmSvgLengthDirection direction);
 void 		lsm_svg_animated_length_attribute_parse (LsmSvgAnimatedLengthAttribute *attribute,
 							 LsmSvgLength *default_value,
-							 double font_size);
+							 const LsmSvgStyle *style,
+							 LsmSvgLengthDirection direction);
 
 void 		lsm_svg_dash_array_attribute_finalize 	(void *abstract);
 
 void		lsm_svg_dash_array_attribute_parse	(LsmSvgDashArrayAttribute *attribute,
-							 LsmSvgDashArray **default_value);
+							 LsmSvgDashArray **default_value,
+							 const LsmSvgStyle *style,
+							 LsmSvgLengthDirection direction);
+
 void 		lsm_svg_fill_rule_attribute_parse 	(LsmDomEnumAttribute *attribute,
 							 unsigned int *style_value);
 void 		lsm_svg_line_join_attribute_parse 	(LsmDomEnumAttribute *attribute,
@@ -150,8 +158,10 @@ void 		lsm_svg_paint_attribute_parse 		(LsmSvgPaintAttribute *attribute,
 void 		lsm_svg_color_attribute_parse 		(LsmSvgColorAttribute *attribute,
 							 LsmSvgColor *default_value,
 							 const LsmSvgColor *current_color);
-void		lsm_svg_view_box_attribute_parse	(LsmSvgViewBoxAttribute *attribute,
-							 LsmSvgViewBox *default_value);
+
+/* Attributes */
+
+void		lsm_svg_view_box_attribute_parse	(LsmSvgViewBoxAttribute *attribute);
 void		lsm_svg_transform_attribute_parse	(LsmSvgTransformAttribute *attribute);
 
 G_END_DECLS
diff --git a/src/lsmsvgcircleelement.c b/src/lsmsvgcircleelement.c
index 07a3283..5ac5190 100644
--- a/src/lsmsvgcircleelement.c
+++ b/src/lsmsvgcircleelement.c
@@ -43,17 +43,20 @@ lsm_svg_circle_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 	length.value = 0.0;
 	length.value_unit = 0.0;
 	length.type = LSM_SVG_LENGTH_TYPE_NUMBER;
-	lsm_svg_animated_length_attribute_parse (&circle->cx, &length, 0.0);
+	lsm_svg_animated_length_attribute_parse (&circle->cx, &length, parent_style,
+						 LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
 
 	length.value = 0.0;
 	length.value_unit = 0.0;
 	length.type = LSM_SVG_LENGTH_TYPE_NUMBER;
-	lsm_svg_animated_length_attribute_parse (&circle->cy, &length, 0.0);
+	lsm_svg_animated_length_attribute_parse (&circle->cy, &length, parent_style,
+						 LSM_SVG_LENGTH_DIRECTION_VERTICAL);
 
 	length.value = 0.0;
 	length.value_unit = 0.0;
 	length.type = LSM_SVG_LENGTH_TYPE_NUMBER;
-	lsm_svg_animated_length_attribute_parse (&circle->r, &length, 0.0);
+	lsm_svg_animated_length_attribute_parse (&circle->r, &length, parent_style,
+						 LSM_SVG_LENGTH_DIRECTION_DIAGONAL);
 
 	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
 }
diff --git a/src/lsmsvgellipseelement.c b/src/lsmsvgellipseelement.c
index 17f6c51..a26f37e 100644
--- a/src/lsmsvgellipseelement.c
+++ b/src/lsmsvgellipseelement.c
@@ -43,22 +43,26 @@ lsm_svg_ellipse_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 	length.value = 0.0;
 	length.value_unit = 0.0;
 	length.type = LSM_SVG_LENGTH_TYPE_NUMBER;
-	lsm_svg_animated_length_attribute_parse (&ellipse->cx, &length, 0.0);
+	lsm_svg_animated_length_attribute_parse (&ellipse->cx, &length, parent_style,
+						 LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
 
 	length.value = 0.0;
 	length.value_unit = 0.0;
 	length.type = LSM_SVG_LENGTH_TYPE_NUMBER;
-	lsm_svg_animated_length_attribute_parse (&ellipse->cy, &length, 0.0);
+	lsm_svg_animated_length_attribute_parse (&ellipse->cy, &length, parent_style,
+						 LSM_SVG_LENGTH_DIRECTION_VERTICAL);
 
 	length.value = 0.0;
 	length.value_unit = 0.0;
 	length.type = LSM_SVG_LENGTH_TYPE_NUMBER;
-	lsm_svg_animated_length_attribute_parse (&ellipse->rx, &length, 0.0);
+	lsm_svg_animated_length_attribute_parse (&ellipse->rx, &length, parent_style,
+						 LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
 
 	length.value = 0.0;
 	length.value_unit = 0.0;
 	length.type = LSM_SVG_LENGTH_TYPE_NUMBER;
-	lsm_svg_animated_length_attribute_parse (&ellipse->ry, &length, 0.0);
+	lsm_svg_animated_length_attribute_parse (&ellipse->ry, &length, parent_style,
+						 LSM_SVG_LENGTH_DIRECTION_VERTICAL);
 
 	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
 }
diff --git a/src/lsmsvgenums.h b/src/lsmsvgenums.h
index a061c39..fb42420 100644
--- a/src/lsmsvgenums.h
+++ b/src/lsmsvgenums.h
@@ -40,6 +40,12 @@ typedef enum {
 } LsmSvgPaintType;
 
 typedef enum {
+	LSM_SVG_LENGTH_DIRECTION_HORIZONTAL,
+	LSM_SVG_LENGTH_DIRECTION_VERTICAL,
+	LSM_SVG_LENGTH_DIRECTION_DIAGONAL
+} LsmSvgLengthDirection;
+
+typedef enum {
 	LSM_SVG_LENGTH_TYPE_UNKNOWN,
 	LSM_SVG_LENGTH_TYPE_NUMBER,
 	LSM_SVG_LENGTH_TYPE_PERCENTAGE,
diff --git a/src/lsmsvggradientelement.c b/src/lsmsvggradientelement.c
index 6b891f0..80d4802 100644
--- a/src/lsmsvggradientelement.c
+++ b/src/lsmsvggradientelement.c
@@ -51,6 +51,12 @@ _gradient_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 	lsm_svg_spread_method_attribute_parse (&gradient->spread_method, &method);
 	lsm_svg_transform_attribute_parse (&gradient->transform);
 
+	if (gradient->units.value == LSM_SVG_GRADIENT_UNITS_OBJECT_BOUNDING_BOX) {
+		parent_style->viewport.width = 1.0;
+		parent_style->viewport.height = 1.0;
+		parent_style->viewport.diagonal = 1.0;
+	}
+
 	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
 }
 
@@ -87,9 +93,9 @@ _gradient_element_graphic_render (LsmSvgElement *self, LsmSvgView *view)
 	}
 
 	lsm_svg_view_set_gradient_properties (view,
-					   gradient->spread_method.value,
-					   gradient->units.value,
-					   &gradient->transform.matrix);
+					      gradient->spread_method.value,
+					      gradient->units.value,
+					      &gradient->transform.matrix);
 }
 
 /* LsmSvgGradientElement implementation */
diff --git a/src/lsmsvggraphic.c b/src/lsmsvggraphic.c
index ffd771b..6f48b81 100644
--- a/src/lsmsvggraphic.c
+++ b/src/lsmsvggraphic.c
@@ -95,6 +95,12 @@ lsm_svg_graphic_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 	default_opacity = 1.0;
 	lsm_svg_double_attribute_parse (&graphic->opacity, &default_opacity); /* FIXME handle inherit */
 
+	if (graphic->text != NULL) {
+		lsm_dom_string_attribute_parse (&graphic->text->font_family, &parent_style->text.font_family);
+		lsm_svg_length_attribute_parse (&graphic->text->font_size, &parent_style->text.font_size,
+						parent_style, LSM_SVG_LENGTH_DIRECTION_DIAGONAL);
+	}
+
 	if (graphic->fill != NULL) {
 		lsm_debug ("[LsmSvgGraphic::update] fill");
 
@@ -109,24 +115,22 @@ lsm_svg_graphic_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 
 		lsm_svg_paint_attribute_parse (&graphic->stroke->paint, &parent_style->stroke.paint,
 					       &graphic->color.value);
-		lsm_svg_length_attribute_parse (&graphic->stroke->width, &parent_style->stroke.width, 0.0);
+		lsm_svg_length_attribute_parse (&graphic->stroke->width, &parent_style->stroke.width,
+						parent_style, LSM_SVG_LENGTH_DIRECTION_DIAGONAL);
 		lsm_dom_double_attribute_parse (&graphic->stroke->opacity, &parent_style->stroke.opacity);
 		lsm_svg_line_join_attribute_parse (&graphic->stroke->line_join, &parent_style->stroke.line_join);
 		lsm_svg_line_cap_attribute_parse (&graphic->stroke->line_cap, &parent_style->stroke.line_cap);
 		lsm_svg_double_attribute_parse (&graphic->stroke->miter_limit, &parent_style->stroke.miter_limit);
-		lsm_svg_dash_array_attribute_parse (&graphic->stroke->dash_array, &parent_style->stroke.dash_array);
-		lsm_svg_length_attribute_parse (&graphic->stroke->dash_offset, &parent_style->stroke.dash_offset, 0.0);
+		lsm_svg_dash_array_attribute_parse (&graphic->stroke->dash_array, &parent_style->stroke.dash_array,
+						    parent_style, LSM_SVG_LENGTH_DIRECTION_DIAGONAL);
+		lsm_svg_length_attribute_parse (&graphic->stroke->dash_offset, &parent_style->stroke.dash_offset,
+						    parent_style, LSM_SVG_LENGTH_DIRECTION_DIAGONAL);
 	}
 
 	if (graphic->transform != NULL) {
 		lsm_svg_transform_attribute_parse (&graphic->transform->transform);
 	}
 
-	if (graphic->text != NULL) {
-		lsm_dom_string_attribute_parse (&graphic->text->font_family, &parent_style->text.font_family);
-		lsm_svg_length_attribute_parse (&graphic->text->font_size, &parent_style->text.font_size, 0.0);
-	}
-
 	if (graphic->stop != NULL) {
 		lsm_svg_color_attribute_parse (&graphic->stop->color,
 					       &parent_style->stop.color,
diff --git a/src/lsmsvglineargradientelement.c b/src/lsmsvglineargradientelement.c
index 0cb5a7e..d454eb8 100644
--- a/src/lsmsvglineargradientelement.c
+++ b/src/lsmsvglineargradientelement.c
@@ -42,27 +42,31 @@ _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 = 0.0;
 	length.value_unit = 0.0;
-	length.type = LSM_SVG_LENGTH_TYPE_NUMBER;
-	lsm_svg_animated_length_attribute_parse (&linear->x1, &length, 0.0);
+	length.type = LSM_SVG_LENGTH_TYPE_PERCENTAGE;
+	lsm_svg_animated_length_attribute_parse (&linear->x1, &length, parent_style,
+						 LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
 
 	length.value = 0.0;
 	length.value_unit = 0.0;
-	length.type = LSM_SVG_LENGTH_TYPE_NUMBER;
-	lsm_svg_animated_length_attribute_parse (&linear->y1, &length, 0.0);
+	length.type = LSM_SVG_LENGTH_TYPE_PERCENTAGE;
+	lsm_svg_animated_length_attribute_parse (&linear->y1, &length, parent_style,
+						 LSM_SVG_LENGTH_DIRECTION_VERTICAL);
 
-	length.value = 1.0;
-	length.value_unit = 1.0;
-	length.type = LSM_SVG_LENGTH_TYPE_NUMBER;
-	lsm_svg_animated_length_attribute_parse (&linear->x2, &length, 0.0);
+	length.value = 100.0;
+	length.value_unit = 100.0;
+	length.type = LSM_SVG_LENGTH_TYPE_PERCENTAGE;
+	lsm_svg_animated_length_attribute_parse (&linear->x2, &length, parent_style,
+						 LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
 
 	length.value = 0.0;
 	length.value_unit = 0.0;
-	length.type = LSM_SVG_LENGTH_TYPE_NUMBER;
-	lsm_svg_animated_length_attribute_parse (&linear->y2, &length, 0.0);
-
-	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
+	length.type = LSM_SVG_LENGTH_TYPE_PERCENTAGE;
+	lsm_svg_animated_length_attribute_parse (&linear->y2, &length, parent_style,
+						 LSM_SVG_LENGTH_DIRECTION_VERTICAL);
 }
 
 static void
diff --git a/src/lsmsvglineelement.c b/src/lsmsvglineelement.c
index bbce4a6..14e7ee6 100644
--- a/src/lsmsvglineelement.c
+++ b/src/lsmsvglineelement.c
@@ -43,22 +43,26 @@ lsm_svg_line_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 	length.value = 0.0;
 	length.value_unit = 0.0;
 	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&line->x1, &length, 0.0);
+	lsm_svg_animated_length_attribute_parse (&line->x1, &length, parent_style,
+						 LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
 
 	length.value = 0.0;
 	length.value_unit = 0.0;
 	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&line->y1, &length, 0.0);
+	lsm_svg_animated_length_attribute_parse (&line->y1, &length, parent_style,
+						 LSM_SVG_LENGTH_DIRECTION_VERTICAL);
 
 	length.value = 0.0;
 	length.value_unit = 0.0;
 	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&line->x2, &length, 0.0);
+	lsm_svg_animated_length_attribute_parse (&line->x2, &length, parent_style,
+						 LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
 
 	length.value = 0.0;
 	length.value_unit = 0.0;
 	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&line->y2, &length, 0.0);
+	lsm_svg_animated_length_attribute_parse (&line->y2, &length, parent_style,
+						 LSM_SVG_LENGTH_DIRECTION_VERTICAL);
 
 	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
 }
diff --git a/src/lsmsvgpatternelement.c b/src/lsmsvgpatternelement.c
index 3e230a6..3c06ab2 100644
--- a/src/lsmsvgpatternelement.c
+++ b/src/lsmsvgpatternelement.c
@@ -54,22 +54,26 @@ _pattern_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 	length.value = 0.0;
 	length.value_unit = 0.0;
 	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&pattern->x, &length, 0.0);
+	lsm_svg_animated_length_attribute_parse (&pattern->x, &length, parent_style,
+						 LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
 
 	length.value = 0.0;
 	length.value_unit = 0.0;
 	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&pattern->y, &length, 0.0);
+	lsm_svg_animated_length_attribute_parse (&pattern->y, &length, parent_style,
+						 LSM_SVG_LENGTH_DIRECTION_VERTICAL);
 
 	length.value = 0.0;
 	length.value_unit = 0.0;
 	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&pattern->width, &length, 0.0);
+	lsm_svg_animated_length_attribute_parse (&pattern->width, &length, parent_style,
+						 LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
 
 	length.value = 0.0;
 	length.value_unit = 0.0;
 	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&pattern->height, &length, 0.0);
+	lsm_svg_animated_length_attribute_parse (&pattern->height, &length, parent_style,
+						 LSM_SVG_LENGTH_DIRECTION_VERTICAL);
 
 	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
 }
diff --git a/src/lsmsvgradialgradientelement.c b/src/lsmsvgradialgradientelement.c
index 1d5e8c1..5fec09e 100644
--- a/src/lsmsvgradialgradientelement.c
+++ b/src/lsmsvgradialgradientelement.c
@@ -42,32 +42,33 @@ _radial_gradient_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 	LsmSvgRadialGradientElement *radial = LSM_SVG_RADIAL_GRADIENT_ELEMENT (self);
 	LsmSvgLength length;
 
-	length.value = 0.5;
-	length.value_unit = 0.5;
-	length.type = LSM_SVG_LENGTH_TYPE_NUMBER;
-	lsm_svg_animated_length_attribute_parse (&radial->cx, &length, 0.0);
+	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
 
-	length.value = 0.5;
-	length.value_unit = 0.5;
-	length.type = LSM_SVG_LENGTH_TYPE_NUMBER;
-	lsm_svg_animated_length_attribute_parse (&radial->cy, &length, 0.0);
+	length.value = 50.0;
+	length.value_unit = 50.0;
+	length.type = LSM_SVG_LENGTH_TYPE_PERCENTAGE;
+	lsm_svg_animated_length_attribute_parse (&radial->cx, &length, parent_style,
+						 LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
 
-	length.value = 0.5;
-	length.value_unit = 0.5;
-	length.type = LSM_SVG_LENGTH_TYPE_NUMBER;
-	lsm_svg_animated_length_attribute_parse (&radial->r, &length, 0.0);
+	length.value = 50.0;
+	length.value_unit = 50.0;
+	length.type = LSM_SVG_LENGTH_TYPE_PERCENTAGE;
+	lsm_svg_animated_length_attribute_parse (&radial->cy, &length, parent_style,
+						 LSM_SVG_LENGTH_DIRECTION_VERTICAL);
 
-	length.value = 0.5;
-	length.value_unit = 0.5;
+	length.value = 50.0;
+	length.value_unit = 50.0;
 	length.type = LSM_SVG_LENGTH_TYPE_NUMBER;
-	lsm_svg_animated_length_attribute_parse (&radial->fx, &length, 0.0);
+	lsm_svg_animated_length_attribute_parse (&radial->r, &length, parent_style,
+						 LSM_SVG_LENGTH_DIRECTION_DIAGONAL);
 
-	length.value = 0.5;
-	length.value_unit = 0.5;
-	length.type = LSM_SVG_LENGTH_TYPE_NUMBER;
-	lsm_svg_animated_length_attribute_parse (&radial->fy, &length, 0.0);
+	length = radial->cx.length.base;
+	lsm_svg_animated_length_attribute_parse (&radial->fx, &length, parent_style,
+						 LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
 
-	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
+	length = radial->cy.length.base;
+	lsm_svg_animated_length_attribute_parse (&radial->fy, &length, parent_style,
+						 LSM_SVG_LENGTH_DIRECTION_VERTICAL);
 }
 
 static void
diff --git a/src/lsmsvgrectelement.c b/src/lsmsvgrectelement.c
index 1055d44..fad65c7 100644
--- a/src/lsmsvgrectelement.c
+++ b/src/lsmsvgrectelement.c
@@ -43,32 +43,38 @@ lsm_svg_rect_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 	length.value = 0.0;
 	length.value_unit = 0.0;
 	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&rect->x, &length, 0.0);
+	lsm_svg_animated_length_attribute_parse (&rect->x, &length, parent_style,
+						 LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
 
 	length.value = 0.0;
 	length.value_unit = 0.0;
 	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&rect->y, &length, 0.0);
+	lsm_svg_animated_length_attribute_parse (&rect->y, &length, parent_style,
+						 LSM_SVG_LENGTH_DIRECTION_VERTICAL);
 
 	length.value = 0.0;
 	length.value_unit = 0.0;
 	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&rect->width, &length, 0.0);
+	lsm_svg_animated_length_attribute_parse (&rect->width, &length, parent_style,
+						 LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
 
 	length.value = 0.0;
 	length.value_unit = 0.0;
 	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&rect->height, &length, 0.0);
+	lsm_svg_animated_length_attribute_parse (&rect->height, &length, parent_style,
+						 LSM_SVG_LENGTH_DIRECTION_VERTICAL);
 
 	length.value = 0.0;
 	length.value_unit = 0.0;
 	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&rect->rx, &length, 0.0);
+	lsm_svg_animated_length_attribute_parse (&rect->rx, &length, parent_style,
+						 LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
 
 	length.value = 0.0;
 	length.value_unit = 0.0;
 	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&rect->ry, &length, 0.0);
+	lsm_svg_animated_length_attribute_parse (&rect->ry, &length, parent_style,
+						 LSM_SVG_LENGTH_DIRECTION_VERTICAL);
 
 	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
 }
diff --git a/src/lsmsvgstopelement.c b/src/lsmsvgstopelement.c
index 957b453..c9931f8 100644
--- a/src/lsmsvgstopelement.c
+++ b/src/lsmsvgstopelement.c
@@ -45,7 +45,8 @@ _stop_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 
 	length.value = 1.0;
 	length.type = LSM_SVG_LENGTH_TYPE_NUMBER;
-	lsm_svg_length_attribute_parse (&stop->offset, &length, 0.0);
+	lsm_svg_length_attribute_parse (&stop->offset, &length, parent_style,
+					LSM_SVG_LENGTH_DIRECTION_DIAGONAL);
 
 	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
 }
diff --git a/src/lsmsvgstyle.h b/src/lsmsvgstyle.h
index ce8303d..85bfdcf 100644
--- a/src/lsmsvgstyle.h
+++ b/src/lsmsvgstyle.h
@@ -27,9 +27,20 @@
 
 G_BEGIN_DECLS
 
-struct _GSvgStyle {
+struct _LsmSvgStyle {
 	LsmSvgColor color;
 
+	double resolution_ppi;
+
+	struct {
+		double width;
+		double height;
+		double diagonal;
+		double horizontal_scale;
+		double vertical_scale;
+		double diagonal_scale;
+	} viewport;
+
 	struct {
 		LsmSvgPaint paint;
 		LsmSvgFillRule rule;
@@ -59,7 +70,7 @@ struct _GSvgStyle {
 };
 
 LsmSvgStyle * 	lsm_svg_style_new 		(void);
-void 		lsm_svg_style_free 	(LsmSvgStyle *style);
+void 		lsm_svg_style_free 		(LsmSvgStyle *style);
 LsmSvgStyle *	lsm_svg_style_duplicate 	(const LsmSvgStyle *style);
 
 G_END_DECLS
diff --git a/src/lsmsvgsvgelement.c b/src/lsmsvgsvgelement.c
index 61ed0d8..703dd53 100644
--- a/src/lsmsvgsvgelement.c
+++ b/src/lsmsvgsvgelement.c
@@ -23,6 +23,8 @@
 #include <lsmsvgstyle.h>
 #include <lsmsvgview.h>
 #include <lsmdebug.h>
+#include <lsmdomdocument.h>
+#include <math.h>
 #include <stdio.h>
 
 static GObjectClass *parent_class;
@@ -42,31 +44,40 @@ _svg_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 {
 	LsmSvgSvgElement *svg = LSM_SVG_SVG_ELEMENT (self);
 	LsmSvgLength length;
-	LsmSvgViewBox view_box = {0,0,0,0};
 
-	lsm_svg_view_box_attribute_parse (&svg->view_box, &view_box);
-
-	length.value = svg->view_box.value.x;
-	length.value_unit = svg->view_box.value.x;
+	length.value = 0.0;
+	length.value_unit = 0.0;
 	length.type = LSM_SVG_LENGTH_TYPE_NUMBER;
-	lsm_svg_length_attribute_parse (&svg->x, &length, 0.0);
+	lsm_svg_length_attribute_parse (&svg->x, &length, parent_style, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
 
-	length.value = svg->view_box.value.y;
-	length.value_unit = svg->view_box.value.y;
+	length.value = 0.0;
+	length.value_unit = 0.0;
 	length.type = LSM_SVG_LENGTH_TYPE_NUMBER;
-	lsm_svg_length_attribute_parse (&svg->y, &length, 0.0);
+	lsm_svg_length_attribute_parse (&svg->y, &length, parent_style, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
 
-	length.value = svg->view_box.value.width;
-	length.value_unit = svg->view_box.value.width;
+	length.value = 0.0;
+	length.value_unit = 0.0;
 	length.type = LSM_SVG_LENGTH_TYPE_NUMBER;
-	lsm_svg_length_attribute_parse (&svg->width, &length, 0.0);
+	lsm_svg_length_attribute_parse (&svg->width, &length, parent_style, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
 
-	length.value = svg->view_box.value.height;
-	length.value_unit = svg->view_box.value.height;
+	length.value = 0.0;
+	length.value_unit = 0.0;
 	length.type = LSM_SVG_LENGTH_TYPE_NUMBER;
-	lsm_svg_length_attribute_parse (&svg->height, &length, 0.0);
+	lsm_svg_length_attribute_parse (&svg->height, &length, parent_style, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
+
+	if (svg->width.length.value <= 0.0)
+		svg->width.length.value = parent_style->viewport.width;
+	if (svg->height.length.value <= 0.0)
+		svg->height.length.value = parent_style->viewport.height;
+
+	lsm_svg_view_box_attribute_parse (&svg->view_box);
 
-	lsm_debug ("[LsmSvgSvgElement::update] height = %g, width = %g",
+	if (svg->view_box.value.width <= 0.0)
+		svg->view_box.value.width = svg->width.length.value;
+	if (svg->view_box.value.height <= 0.0)
+		svg->view_box.value.height = svg->height.length.value;
+
+	lsm_debug ("[LsmSvgSvgElement::update] height = %g px, width = %g px",
 		    svg->height.length.value,
 		    svg->width.length.value);
 
@@ -76,18 +87,44 @@ _svg_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 		    svg->view_box.value.width,
 		    svg->view_box.value.height);
 
+	parent_style->viewport.width = svg->view_box.value.width;
+	parent_style->viewport.height = svg->view_box.value.height;
+	parent_style->viewport.diagonal= sqrt (pow (svg->view_box.value.width, 2.0) +
+					       pow (svg->view_box.value.height, 2.0)) / sqrt (2.0);
+
+	parent_style->viewport.horizontal_scale = svg->width.length.value / svg->view_box.value.width;
+	parent_style->viewport.vertical_scale = svg->height.length.value / svg->view_box.value.height;
+	parent_style->viewport.diagonal_scale = sqrt (pow (parent_style->viewport.horizontal_scale, 2.0) +
+						      pow (parent_style->viewport.vertical_scale, 2.0)) / sqrt (2.0);
+	parent_style->viewport.horizontal_scale =
+	parent_style->viewport.vertical_scale =
+	parent_style->viewport.diagonal_scale =  parent_style->resolution_ppi / 72.0;
+
+	lsm_debug ("[LsmSvgSvgElement::update] viewport       = %g, %g",
+		   parent_style->viewport.width, parent_style->viewport.height);
+	lsm_debug ("[LsmSvgSvgElement::update] viewport_scale = %g, %g",
+		   parent_style->viewport.horizontal_scale, parent_style->viewport.vertical_scale);
+
 	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
 }
 
 void
 lsm_svg_svg_element_measure (LsmSvgSvgElement *self, double *width, double *height)
 {
+	LsmDomDocument *document;
+	double resolution_ppi;
+
 	g_return_if_fail (LSM_IS_SVG_SVG_ELEMENT (self));
 
+	document = LSM_DOM_DOCUMENT (LSM_DOM_NODE (self)->parent_node);
+	g_return_if_fail (LSM_IS_DOM_DOCUMENT (document));
+
+	resolution_ppi = lsm_dom_document_get_resolution (document);
+
 	if (width != NULL)
-		*width = self->width.length.value;
+		*width = self->width.length.value * 72.0 / resolution_ppi;
 	if (height != NULL)
-		*height = self->height.length.value;
+		*height = self->height.length.value * 72.0 / resolution_ppi;
 }
 
 /* LsmSvgGraphic implementation */
@@ -103,10 +140,11 @@ lsm_svg_svg_element_graphic_render (LsmSvgElement *self, LsmSvgView *view)
 		return;
 
 	lsm_svg_matrix_init (&matrix,
-			  svg->width.length.value / svg->view_box.value.width,
-			  0, 0,
-			  svg->height.length.value / svg->view_box.value.height,
-			  0, 0);
+			     svg->width.length.value / svg->view_box.value.width,
+			     0, 0,
+			     svg->height.length.value / svg->view_box.value.height,
+			     0, 0);
+
 	lsm_svg_view_push_transform (view, &matrix);
 
 	LSM_SVG_GRAPHIC_CLASS (parent_class)->graphic_render (self, view);
@@ -127,6 +165,24 @@ lsm_svg_svg_element_get_default_style (LsmSvgSvgElement *svg_element)
 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->resolution_ppi = lsm_dom_document_get_resolution (document);
+	lsm_dom_document_get_viewport (document, &style->viewport.width, &style->viewport.height);
+	style->viewport.diagonal = sqrt (pow (style->viewport.width, 2.0) + pow (style->viewport.height, 2.0)) /
+		sqrt (2.0);
+	style->viewport.horizontal_scale =
+	style->viewport.vertical_scale =
+	style->viewport.diagonal_scale = style->resolution_ppi / 72.0;
+
 	lsm_svg_element_update (LSM_SVG_ELEMENT (svg_element),
 			     lsm_svg_svg_element_get_default_style (svg_element));
 }
diff --git a/src/lsmsvgtextelement.c b/src/lsmsvgtextelement.c
index 83a3196..9209afc 100644
--- a/src/lsmsvgtextelement.c
+++ b/src/lsmsvgtextelement.c
@@ -50,12 +50,14 @@ lsm_svg_text_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 	length.value = 0.0;
 	length.value_unit = 0.0;
 	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&text->x, &length, 0.0);
+	lsm_svg_animated_length_attribute_parse (&text->x, &length, parent_style,
+						 LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
 
 	length.value = 0.0;
 	length.value_unit = 0.0;
 	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&text->y, &length, 0.0);
+	lsm_svg_animated_length_attribute_parse (&text->y, &length, parent_style,
+						 LSM_SVG_LENGTH_DIRECTION_VERTICAL);
 
 	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
 }
diff --git a/src/lsmsvguseelement.c b/src/lsmsvguseelement.c
index c884ccb..7c83ab2 100644
--- a/src/lsmsvguseelement.c
+++ b/src/lsmsvguseelement.c
@@ -52,22 +52,26 @@ lsm_svg_use_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 	length.value = 0.0;
 	length.value_unit = 0.0;
 	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&use_element->x, &length, 0.0);
+	lsm_svg_animated_length_attribute_parse (&use_element->x, &length, parent_style,
+						 LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
 
 	length.value = 0.0;
 	length.value_unit = 0.0;
 	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&use_element->y, &length, 0.0);
+	lsm_svg_animated_length_attribute_parse (&use_element->y, &length, parent_style,
+						 LSM_SVG_LENGTH_DIRECTION_VERTICAL);
 
 	length.value = 0.0;
 	length.value_unit = 0.0;
 	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&use_element->width, &length, 0.0);
+	lsm_svg_animated_length_attribute_parse (&use_element->width, &length, parent_style,
+						 LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
 
 	length.value = 0.0;
 	length.value_unit = 0.0;
 	length.type = LSM_SVG_LENGTH_TYPE_PX;
-	lsm_svg_animated_length_attribute_parse (&use_element->height, &length, 0.0);
+	lsm_svg_animated_length_attribute_parse (&use_element->height, &length, parent_style,
+						 LSM_SVG_LENGTH_DIRECTION_VERTICAL);
 
 	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
 }
diff --git a/src/lsmsvgview.c b/src/lsmsvgview.c
index 1e05a20..d96e974 100644
--- a/src/lsmsvgview.c
+++ b/src/lsmsvgview.c
@@ -1051,7 +1051,7 @@ lsm_svg_view_measure (LsmDomView *view, double *width, double *height)
 }
 
 static void
-lsm_svg_view_render (LsmDomView *view, double x, double y)
+lsm_svg_view_render (LsmDomView *view)
 {
 	LsmSvgView *svg_view;
 	LsmSvgSvgElement *svg_element;



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