[lasem] <svg;marker> Start to render something.



commit e1639c3462fc1b5463dd717463785d51a6c05c09
Author: Emmanuel Pacaud <emmanuel pacaud lapp in2p3 fr>
Date:   Wed Aug 12 23:22:40 2009 +0200

    <svg;marker> Start to render something.

 src/lsmsvgdocument.c       |   23 ++++
 src/lsmsvgdocument.h       |    1 +
 src/lsmsvgelement.c        |    4 +-
 src/lsmsvgmarkerelement.c  |  125 +++++++++++++++++++++-
 src/lsmsvgmarkerelement.h  |   12 ++
 src/lsmsvgpatternelement.c |    1 -
 src/lsmsvgstyle.c          |   11 ++
 src/lsmsvgstyle.h          |    1 +
 src/lsmsvgtraits.c         |   22 ++--
 src/lsmsvgtraits.h         |    2 +-
 src/lsmsvguseelement.c     |    1 -
 src/lsmsvgview.c           |  253 ++++++++++++++++++++++++++-----------------
 12 files changed, 337 insertions(+), 119 deletions(-)
---
diff --git a/src/lsmsvgdocument.c b/src/lsmsvgdocument.c
index 9adbf61..3354a68 100644
--- a/src/lsmsvgdocument.c
+++ b/src/lsmsvgdocument.c
@@ -55,6 +55,29 @@ lsm_svg_document_can_append_child (LsmDomNode *self, LsmDomNode *child)
 
 /* LsmDomDocument implementation */
 
+LsmSvgElement *
+lsm_svg_document_get_element_by_url (LsmSvgDocument *document, const char *url)
+{
+	LsmDomElement *element;
+	char *end;
+	char *id;
+
+	g_return_val_if_fail (LSM_IS_SVG_DOCUMENT (document), NULL);
+
+	if (url == NULL || strncmp (url, "url(#", 5) != 0)
+		return NULL;
+
+	id = g_strdup (url + 5);
+	for (end = id; *end != '\0' && *end != ')'; end++);
+	*end = '\0';
+
+	element = lsm_dom_document_get_element_by_id (LSM_DOM_DOCUMENT (document), id);
+
+	g_free (id);
+
+	return LSM_SVG_ELEMENT (element);
+}
+
 static LsmDomElement *
 lsm_svg_document_create_element (LsmDomDocument *document, const char *tag_name)
 {
diff --git a/src/lsmsvgdocument.h b/src/lsmsvgdocument.h
index ba173a9..3df022b 100644
--- a/src/lsmsvgdocument.h
+++ b/src/lsmsvgdocument.h
@@ -48,6 +48,7 @@ GType lsm_svg_document_get_type (void);
 
 LsmSvgDocument *	lsm_svg_document_new 			(void);
 LsmSvgSvgElement * 	lsm_svg_document_get_root_element 	(const LsmSvgDocument *document);
+LsmSvgElement * 	lsm_svg_document_get_element_by_url 	(LsmSvgDocument *document, const char *url);
 
 G_END_DECLS
 
diff --git a/src/lsmsvgelement.c b/src/lsmsvgelement.c
index 8c5ab53..331cd09 100644
--- a/src/lsmsvgelement.c
+++ b/src/lsmsvgelement.c
@@ -27,6 +27,7 @@
 #include <lsmsvgpatternelement.h>
 #include <lsmsvggradientelement.h>
 #include <lsmsvgclippathelement.h>
+#include <lsmsvgmarkerelement.h>
 #include <lsmsvgmaskelement.h>
 #include <lsmsvgview.h>
 #include <string.h>
@@ -161,7 +162,8 @@ lsm_svg_element_force_render (LsmSvgElement *element, LsmSvgView *view)
 	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));
+			  LSM_IS_SVG_CLIP_PATH_ELEMENT (element) ||
+			  LSM_IS_SVG_MARKER_ELEMENT (element));
 
 	lsm_svg_element_enable_rendering (element);
 	lsm_svg_element_render (element, view);
diff --git a/src/lsmsvgmarkerelement.c b/src/lsmsvgmarkerelement.c
index f373d23..a918049 100644
--- a/src/lsmsvgmarkerelement.c
+++ b/src/lsmsvgmarkerelement.c
@@ -40,12 +40,94 @@ lsm_svg_marker_element_get_node_name (LsmDomNode *node)
 /* LsmSvgGraphic implementation */
 
 static void
-lsm_svg_marker_element_render (LsmSvgElement *self, LsmSvgView *view)
+_marker_element_render (LsmSvgElement *self, LsmSvgView *view)
 {
+	LsmSvgMarkerElement *marker = LSM_SVG_MARKER_ELEMENT (self);
+	LsmSvgStyle *style;
+	LsmSvgMatrix matrix;
+	LsmBox viewbox = {.x = 0.0, .y = .0, .width = 1.0, .height = 1.0};
+	LsmBox viewport;
+	double ref_x, ref_y;
+
+	if (!marker->enable_rendering) {
+		if (marker->style)
+			lsm_svg_style_free (marker->style);
+		/* FIXME Use reference counting for LsmSvgStyle */
+		marker->style = lsm_svg_style_duplicate (lsm_svg_view_get_current_style (view));
+
+		lsm_debug ("[LsmSvgMarkerElement::render] Direct rendering not allowed");
+		return;
+	} else {
+		marker->enable_rendering = FALSE;
+	}
+
+	style = lsm_svg_style_new_inherited (marker->style, &self->property_bag);
+	lsm_svg_view_push_style (view, style);
+
+	viewport.x = 0.0;
+	viewport.y = 0.0;
+
+	viewport.width = lsm_svg_view_normalize_length (view, &marker->width.length,
+							LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
+	viewport.height = lsm_svg_view_normalize_length (view, &marker->height.length,
+							 LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
+
+	ref_x = lsm_svg_view_normalize_length (view, &marker->ref_x.length,
+					       LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
+	ref_y = lsm_svg_view_normalize_length (view, &marker->ref_y.length,
+					       LSM_SVG_LENGTH_DIRECTION_VERTICAL);
+
+	lsm_svg_matrix_init_translate (&matrix, -ref_x, -ref_y);
+
+	if (marker->units.value == LSM_SVG_MARKER_UNITS_STROKE_WIDTH) {
+		lsm_svg_matrix_scale (&matrix, marker->stroke_width, marker->stroke_width);
+	}
+
+	lsm_svg_view_push_viewbox (view, &viewbox);
+	lsm_svg_view_push_matrix (view, &matrix);
+
+	lsm_debug ("[LsmSvgMarkerElement::render] stroke_width scale = %g",
+		   marker->stroke_width);
+
+	lsm_svg_view_push_viewport (view, &viewport, &marker->viewbox.value,
+				    &marker->preserve_aspect_ratio.value);
+
+	lsm_svg_matrix_init_rotate (&matrix, marker->vertex_angle);
+	lsm_svg_view_push_matrix (view, &matrix);
+
+	LSM_SVG_ELEMENT_CLASS (parent_class)->render (self, view);
+
+	lsm_svg_view_pop_matrix (view);
+
+	lsm_svg_view_pop_viewport (view);
+
+	lsm_svg_view_pop_matrix (view);
+	lsm_svg_view_pop_viewbox (view);
+
+	lsm_svg_view_pop_style (view);
+	lsm_svg_style_free (style);
 }
 
 /* LsmSvgMarkerElement implementation */
 
+void
+lsm_svg_marker_element_render (LsmSvgMarkerElement *marker, LsmSvgView *view,
+			       double stroke_width, double vertex_angle)
+{
+	g_return_if_fail (LSM_IS_SVG_MARKER_ELEMENT (marker));
+
+	marker->stroke_width = stroke_width;
+	marker->vertex_angle = vertex_angle;
+
+	lsm_svg_element_force_render (LSM_SVG_ELEMENT (marker), view);
+}
+
+static void
+lsm_svg_marker_element_enable_rendering (LsmSvgElement *element)
+{
+	LSM_SVG_MARKER_ELEMENT (element)->enable_rendering  = TRUE;
+}
+
 LsmDomNode *
 lsm_svg_marker_element_new (void)
 {
@@ -56,14 +138,33 @@ static const LsmSvgMarkerUnits units_default =   LSM_SVG_MARKER_UNITS_STROKE_WID
 static const LsmSvgLength length_default = 	 { .value_unit =   0.0, .type = LSM_SVG_LENGTH_TYPE_NUMBER};
 static const LsmSvgLength width_default = 	 { .value_unit =   3.0, .type = LSM_SVG_LENGTH_TYPE_NUMBER};
 static const LsmSvgAngle orientation_default =	 { .angle =        0.0, .type = LSM_SVG_ANGLE_TYPE_FIXED};
+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_marker_element_init (LsmSvgMarkerElement *self)
 {
+	self->enable_rendering = FALSE;
 	self->ref_x.length = length_default;
 	self->ref_y.length = length_default;
 	self->width.length = width_default;
 	self->height.length = width_default;
+	self->preserve_aspect_ratio.value = preserve_aspect_ratio_default;
+}
+
+static void
+lsm_svg_marker_element_finalize (GObject *object)
+{
+	LsmSvgMarkerElement *marker = LSM_SVG_MARKER_ELEMENT (object);
+
+	if (marker->style)
+		lsm_svg_style_free (marker->style);
+
+	parent_class->finalize (object);
 }
 
 /* LsmSvgMarkerElement class */
@@ -88,13 +189,13 @@ static const LsmAttributeInfos lsm_svg_marker_element_attribute_infos[] = {
 		.trait_default = &length_default
 	},
 	{
-		.name = "width",
+		.name = "markerWidth",
 		.attribute_offset = offsetof (LsmSvgMarkerElement, width),
 		.trait_class = &lsm_svg_length_trait_class,
 		.trait_default = &width_default
 	},
 	{
-		.name = "height",
+		.name = "markerHeight",
 		.attribute_offset = offsetof (LsmSvgMarkerElement, height),
 		.trait_class = &lsm_svg_length_trait_class,
 		.trait_default = &width_default
@@ -104,20 +205,36 @@ static const LsmAttributeInfos lsm_svg_marker_element_attribute_infos[] = {
 		.attribute_offset = offsetof (LsmSvgMarkerElement, orientation),
 		.trait_class = &lsm_svg_angle_trait_class,
 		.trait_default = &orientation_default
+	},
+	{
+		.name = "viewBox",
+		.attribute_offset = offsetof (LsmSvgMarkerElement, viewbox),
+		.trait_class = &lsm_box_trait_class,
+		.trait_default = &viewbox_default
+	},
+	{
+		.name = "preserveAspectRatio",
+		.attribute_offset = offsetof (LsmSvgMarkerElement, preserve_aspect_ratio),
+		.trait_class = &lsm_svg_preserve_aspect_ratio_trait_class,
+		.trait_default = &preserve_aspect_ratio_default
 	}
 };
 
 static void
 lsm_svg_marker_element_class_init (LsmSvgMarkerElementClass *klass)
 {
+	GObjectClass *object_class = G_OBJECT_CLASS (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);
 
+	object_class->finalize = lsm_svg_marker_element_finalize;
+
 	d_node_class->get_node_name = lsm_svg_marker_element_get_node_name;
 
-	s_element_class->render = lsm_svg_marker_element_render;
+	s_element_class->render = _marker_element_render;
+	s_element_class->enable_rendering = lsm_svg_marker_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,
diff --git a/src/lsmsvgmarkerelement.h b/src/lsmsvgmarkerelement.h
index 7c444ee..3c911f1 100644
--- a/src/lsmsvgmarkerelement.h
+++ b/src/lsmsvgmarkerelement.h
@@ -45,6 +45,16 @@ struct _LsmSvgMarkerElement {
 	LsmSvgLengthAttribute width;
 	LsmSvgLengthAttribute height;
 	LsmSvgAngleAttribute orientation;
+
+	LsmSvgViewboxAttribute	viewbox;
+	LsmSvgPreserveAspectRatioAttribute	preserve_aspect_ratio;
+
+	gboolean enable_rendering;
+
+	double stroke_width;
+	double vertex_angle;
+
+	LsmSvgStyle *style;
 };
 
 struct _LsmSvgMarkerElementClass {
@@ -54,6 +64,8 @@ struct _LsmSvgMarkerElementClass {
 GType lsm_svg_marker_element_get_type (void);
 
 LsmDomNode *		lsm_svg_marker_element_new 		(void);
+void 			lsm_svg_marker_element_render 		(LsmSvgMarkerElement *marker, LsmSvgView *view,
+								 double stroke_width, double vertex_angle);
 
 G_END_DECLS
 
diff --git a/src/lsmsvgpatternelement.c b/src/lsmsvgpatternelement.c
index 79dea55..471023b 100644
--- a/src/lsmsvgpatternelement.c
+++ b/src/lsmsvgpatternelement.c
@@ -54,7 +54,6 @@ lsm_svg_pattern_element_render (LsmSvgElement *self, LsmSvgView *view)
 		pattern->enable_rendering = FALSE;
 	}
 
-
 	style = lsm_svg_style_new_inherited (NULL, &self->property_bag);
 	lsm_svg_view_push_style (view, style);
 
diff --git a/src/lsmsvgstyle.c b/src/lsmsvgstyle.c
index 438aa26..f28f45b 100644
--- a/src/lsmsvgstyle.c
+++ b/src/lsmsvgstyle.c
@@ -500,3 +500,14 @@ lsm_svg_style_new_inherited (const LsmSvgStyle *parent_style, LsmPropertyBag *pr
 	return style;
 }
 
+LsmSvgStyle *
+lsm_svg_style_duplicate (const LsmSvgStyle *origin)
+{
+	LsmSvgStyle *style;
+
+	style = g_new (LsmSvgStyle, 1);
+
+	memcpy (style, origin, sizeof (LsmSvgStyle));
+
+	return style;
+}
diff --git a/src/lsmsvgstyle.h b/src/lsmsvgstyle.h
index cbb1cc7..a57ee60 100644
--- a/src/lsmsvgstyle.h
+++ b/src/lsmsvgstyle.h
@@ -152,6 +152,7 @@ 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);
+LsmSvgStyle * 		lsm_svg_style_duplicate 		(const LsmSvgStyle *origin);
 
 G_END_DECLS
 
diff --git a/src/lsmsvgtraits.c b/src/lsmsvgtraits.c
index db07b94..313f7d0 100644
--- a/src/lsmsvgtraits.c
+++ b/src/lsmsvgtraits.c
@@ -300,30 +300,29 @@ lsm_svg_paint_trait_from_string (LsmTrait *abstract_trait, char *string)
 	LsmSvgPaint *paint = (LsmSvgPaint *) abstract_trait;
 	LsmSvgPaintType paint_type;
 
-	g_free (paint->uri);
+	g_free (paint->url);
 
 	if (strncmp (string, "url(#", 5) == 0) {
 		unsigned int length;
 
-		string += 5;
-		length = 0;
+		length = 5;
 		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';
+		paint->url = g_new (char, length);
+		if (paint->url != NULL) {
+			memcpy (paint->url, string, length - 1);
+			paint->url[length - 1] = '\0';
 		}
 		string += length;
 	} else {
-		paint->uri = NULL;
+		paint->url = NULL;
 	}
 
 	string = _parse_color (string, &paint->color, &paint_type);
 
-	if (paint->uri != NULL)
+	if (paint->url != NULL)
 		switch (paint_type) {
 			case LSM_SVG_PAINT_TYPE_RGB_COLOR:
 				paint_type = LSM_SVG_PAINT_TYPE_URI_RGB_COLOR;
@@ -353,8 +352,9 @@ lsm_svg_paint_trait_to_string (LsmTrait *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);
+	/* FIXME */
+	if (paint->url != NULL)
+		return g_strdup (paint->url);
 
 	return g_strdup_printf ("rgb(%g%%,%g%%,%g%%)",
 				100.0 * paint->color.red,
diff --git a/src/lsmsvgtraits.h b/src/lsmsvgtraits.h
index 21ba491..e51d19a 100644
--- a/src/lsmsvgtraits.h
+++ b/src/lsmsvgtraits.h
@@ -50,7 +50,7 @@ void			lsm_svg_dash_array_copy		(LsmSvgDashArray *to, const LsmSvgDashArray *fro
 
 typedef struct {
 	LsmSvgPaintType type;
-	char *uri;
+	char *url;
 	LsmSvgColor color;
 } LsmSvgPaint;
 
diff --git a/src/lsmsvguseelement.c b/src/lsmsvguseelement.c
index 5fcb2ee..d54bf33 100644
--- a/src/lsmsvguseelement.c
+++ b/src/lsmsvguseelement.c
@@ -67,7 +67,6 @@ lsm_svg_use_element_render (LsmSvgElement *self, LsmSvgView *view)
 	if (id == NULL)
 		return;
 
-	/* TODO Ugly hack */
 	if (*id == '#')
 		id++;
 
diff --git a/src/lsmsvgview.c b/src/lsmsvgview.c
index 58845fc..463c2bd 100644
--- a/src/lsmsvgview.c
+++ b/src/lsmsvgview.c
@@ -26,6 +26,7 @@
 #include <lsmsvgsvgelement.h>
 #include <lsmsvggradientelement.h>
 #include <lsmsvgpatternelement.h>
+#include <lsmsvgmarkerelement.h>
 #include <lsmsvgclippathelement.h>
 #include <lsmsvgmaskelement.h>
 #include <lsmstr.h>
@@ -686,14 +687,14 @@ typedef enum {
 } LsmSvgViewPaintOperation;
 
 static void
-_paint_uri (LsmSvgView *view, LsmSvgViewPaintOperation operation, const char *uri)
+_paint_url (LsmSvgView *view, LsmSvgViewPaintOperation operation, const char *url)
 {
 	cairo_t *cairo;
-	LsmDomElement *element;
+	LsmSvgElement *element;
 	LsmBox extents;
 	double x1, x2, y1, y2;
 
-	element = lsm_dom_document_get_element_by_id (view->dom_view.document, uri);
+	element = lsm_svg_document_get_element_by_url (LSM_SVG_DOCUMENT (view->dom_view.document), url);
 	if (!LSM_IS_SVG_GRADIENT_ELEMENT (element) &&
 	    !LSM_IS_SVG_PATTERN_ELEMENT (element))
 		return;
@@ -789,7 +790,7 @@ _set_color (LsmSvgView *view, LsmSvgViewPaintOperation operation,
 		case LSM_SVG_PAINT_TYPE_URI_RGB_COLOR:
 		case LSM_SVG_PAINT_TYPE_URI_CURRENT_COLOR:
 		case LSM_SVG_PAINT_TYPE_URI_NONE:
-			_paint_uri (view, operation, paint->uri);
+			_paint_url (view, operation, paint->url);
 			break;
 		default:
 			return FALSE;
@@ -890,10 +891,80 @@ paint (LsmSvgView *view)
 		} else
 			cairo_set_dash (cairo, NULL, 0, 0.0);
 
-		cairo_stroke (cairo);
+		cairo_stroke_preserve (cairo);
 	}
 
-	cairo_new_path (cairo);
+	if ((style->marker->value != NULL && strcmp (style->marker->value, "none") != 0) ||
+	    (style->marker_mid->value != NULL && strcmp (style->marker_mid->value, "none") != 0) ||
+	    (style->marker_end->value != NULL && strcmp (style->marker_end->value, "none") != 0) ||
+	    (style->marker_start->value != NULL && strcmp (style->marker_start->value, "none") != 0)) {
+		LsmSvgElement *marker;
+		LsmSvgElement *marker_start;
+		LsmSvgElement *marker_mid;
+		LsmSvgElement *marker_end;
+		cairo_path_t *path;
+		cairo_path_data_t *data;
+		double stroke_width;
+		int i;
+
+		marker = lsm_svg_document_get_element_by_url (LSM_SVG_DOCUMENT (view->dom_view.document),
+							      style->marker->value);
+		marker_start = lsm_svg_document_get_element_by_url (LSM_SVG_DOCUMENT (view->dom_view.document),
+								    style->marker_start->value);
+		marker_mid = lsm_svg_document_get_element_by_url (LSM_SVG_DOCUMENT (view->dom_view.document),
+								  style->marker_mid->value);
+		marker_end = lsm_svg_document_get_element_by_url (LSM_SVG_DOCUMENT (view->dom_view.document),
+								  style->marker_end->value);
+		stroke_width = lsm_svg_view_normalize_length (view, &view->style->stroke_width->length,
+							      LSM_SVG_LENGTH_DIRECTION_DIAGONAL);
+
+		if (marker_start == NULL)
+			marker_start = marker;
+		if (marker_mid == NULL)
+			marker_mid = marker;
+		if (marker_end == NULL)
+			marker_end = marker;
+
+		path = cairo_copy_path (cairo);
+		cairo_new_path (cairo);
+
+		for (i = 0; i < path->num_data; i += path->data[i].header.length) {
+			data = &path->data[i];
+#if 0
+			switch (data->header.type) {
+				case CAIRO_PATH_MOVE_TO:
+					break;
+				case CAIRO_PATH_LINE_TO:
+					break;
+				case CAIRO_PATH_CURVE_TO:
+					break;
+				case CAIRO_PATH_CLOSE_PATH:
+					break;
+			}
+#endif
+			if (i == 0)
+				marker = marker_start;
+			else if (i + path->data[i].header.length >= path->num_data)
+				marker = marker_end;
+			else
+				marker = marker_mid;
+
+			if (marker != NULL) {
+				double x, y;
+				cairo_save (cairo);
+
+				x = data[1].point.x;
+				y = data[1].point.y;
+				cairo_translate (cairo, x, y);
+				lsm_svg_marker_element_render (LSM_SVG_MARKER_ELEMENT (marker), view,
+							       stroke_width, 0.0);
+				cairo_restore (cairo);
+			}
+		}
+
+		cairo_path_destroy (path);
+	} else
+		cairo_new_path (cairo);
 
 	if (use_group) {
 		cairo_pop_group_to_source (cairo);
@@ -1004,6 +1075,7 @@ lsm_svg_view_show_path (LsmSvgView *view,
 	_emit_svg_path (view->dom_view.cairo, d);
 
 	process_path (view);
+
 }
 
 void
@@ -1017,8 +1089,8 @@ lsm_svg_view_show_line (LsmSvgView *view, double x1, double y1, double x2, doubl
 	process_path (view);
 }
 
-void
-lsm_svg_view_show_polyline (LsmSvgView *view, const char *points)
+static void
+_show_points (LsmSvgView *view, const char *points, gboolean close_path)
 {
 	char *str;
 	double values[2];
@@ -1033,28 +1105,22 @@ lsm_svg_view_show_polyline (LsmSvgView *view, const char *points)
 			cairo_line_to (view->dom_view.cairo, values[0], values[1]);
 	}
 
+	if (close_path)
+		cairo_close_path (view->dom_view.cairo);
+
 	process_path (view);
 }
 
 void
-lsm_svg_view_show_polygon (LsmSvgView *view, const char *points)
+lsm_svg_view_show_polyline (LsmSvgView *view, const char *points)
 {
-	char *str;
-	double values[2];
-
-	g_return_if_fail (LSM_IS_SVG_VIEW (view));
-
-	str = (char *) points;
-
-	if (lsm_str_parse_double_list (&str, 2, values)) {
-		cairo_move_to (view->dom_view.cairo, values[0], values[1]);
-		while (lsm_str_parse_double_list (&str, 2, values))
-			cairo_line_to (view->dom_view.cairo, values[0], values[1]);
-	}
-
-	cairo_close_path (view->dom_view.cairo);
+	_show_points (view, points, FALSE);
+}
 
-	process_path (view);
+void
+lsm_svg_view_show_polygon (LsmSvgView *view, const char *points)
+{
+	_show_points (view, points, TRUE);
 }
 
 void
@@ -1221,6 +1287,14 @@ lsm_svg_view_push_viewport (LsmSvgView *view, const LsmBox *viewport, const LsmB
 	cairo = view->dom_view.cairo;
 
 	cairo_save (cairo);
+	if (view->dom_view.debug) {
+		cairo_save (cairo);
+		cairo_set_line_width (cairo, 1.0);
+		cairo_set_source_rgb (cairo, 0.0, 0.0, 0.0);
+		cairo_rectangle (cairo, viewport->x, viewport->y, viewport->width, viewport->height);
+		cairo_stroke (cairo);
+		cairo_restore (cairo);
+	}
 	cairo_rectangle (cairo, viewport->x, viewport->y, viewport->width, viewport->height);
 	cairo_clip (cairo);
 	cairo_translate (cairo, x, y);
@@ -1306,18 +1380,18 @@ lsm_svg_view_pop_group_opacity (LsmSvgView *view)
 static void
 lsm_svg_view_push_clip (LsmSvgView *view)
 {
-	LsmDomElement *element;
+	LsmSvgElement *element;
 	LsmExtents extents;
-	char *uri;
+	char *url;
 
 	g_return_if_fail (LSM_IS_SVG_VIEW (view));
 	g_return_if_fail (!view->is_clipping);
 
 	lsm_svg_element_get_extents (view->element_stack->data, view, &extents);
 
-	uri = view->style->clip_path->value;
+	url = view->style->clip_path->value;
 
-	lsm_debug ("[LsmSvgView::push_clip] Using '%s'", uri);
+	lsm_debug ("[LsmSvgView::push_clip] Using '%s'", url);
 
 	cairo_save (view->dom_view.cairo);
 
@@ -1326,23 +1400,12 @@ lsm_svg_view_push_clip (LsmSvgView *view)
 	view->clip_extents.width  = extents.x2 - extents.x1;
 	view->clip_extents.height = extents.y2 - extents.y1;
 
-	if (strncmp (uri, "url(#", 5) ==0) {
-		char *end;
-
-		uri = g_strdup (uri + 5);
-		for (end = uri; *end != '\0' && *end != ')'; end++);
-		*end = '\0';
-
-		element = lsm_dom_document_get_element_by_id (view->dom_view.document, uri);
-
-		g_free (uri);
-
-		if (element != NULL && LSM_IS_SVG_CLIP_PATH_ELEMENT (element)) {
-			view->is_clipping = TRUE;
-			lsm_svg_element_force_render (LSM_SVG_ELEMENT (element), view);
-			cairo_clip (view->dom_view.cairo);
-			view->is_clipping = FALSE;
-		}
+	element = lsm_svg_document_get_element_by_url (LSM_SVG_DOCUMENT (view->dom_view.document), url);
+	if (element != NULL && LSM_IS_SVG_CLIP_PATH_ELEMENT (element)) {
+		view->is_clipping = TRUE;
+		lsm_svg_element_force_render (LSM_SVG_ELEMENT (element), view);
+		cairo_clip (view->dom_view.cairo);
+		view->is_clipping = FALSE;
 	}
 }
 
@@ -1365,76 +1428,66 @@ lsm_svg_view_push_mask (LsmSvgView *view)
 static void
 lsm_svg_view_pop_mask (LsmSvgView *view)
 {
-	g_return_if_fail (LSM_IS_SVG_VIEW (view));
-
-	if (strncmp (view->style->mask->value, "url(#", 5) == 0) {
-		LsmDomElement *mask_element;
-		char *end;
-		char *uri;
-
-		uri = g_strdup (view->style->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);
+	LsmSvgElement *mask_element;
 
-		if (LSM_IS_SVG_MASK_ELEMENT (mask_element)) {
-			LsmExtents extents;
-			LsmBox mask_extents;
-			cairo_t *cairo;
+	g_return_if_fail (LSM_IS_SVG_VIEW (view));
 
-			lsm_svg_element_get_extents (view->element_stack->data, view, &extents);
+	mask_element = lsm_svg_document_get_element_by_url (LSM_SVG_DOCUMENT (view->dom_view.document),
+							    view->style->mask->value);
 
-			mask_extents.x = extents.x1;
-			mask_extents.y = extents.y1;
-			mask_extents.width = extents.x2 - extents.x1;
-			mask_extents.height = extents.y2 - extents.y1;
+	if (LSM_IS_SVG_MASK_ELEMENT (mask_element)) {
+		LsmExtents extents;
+		LsmBox mask_extents;
+		cairo_t *cairo;
 
-			cairo = view->dom_view.cairo;
+		lsm_svg_element_get_extents (view->element_stack->data, view, &extents);
 
-			_start_pattern (view, &mask_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;
 
-			lsm_svg_element_force_render (LSM_SVG_ELEMENT (mask_element), view);
+		cairo = view->dom_view.cairo;
 
-			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;
+		_start_pattern (view, &mask_extents);
 
-				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);
+		lsm_svg_element_force_render (LSM_SVG_ELEMENT (mask_element), view);
 
-				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_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 */);
 				}
+			}
 
-				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);



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