[lasem] [SVG] stroke-dasharray and stroke-dashoffset support.



commit 7d50eabaa4385335399012befb71b821cd786bea
Author: Emmanuel Pacaud <emmanuel pacaud lapp in2p3 fr>
Date:   Sun May 3 11:11:21 2009 +0200

    [SVG] stroke-dasharray and stroke-dashoffset support.
---
 src/lsmdomattributes.h    |   30 +++++-----
 src/lsmsvgattributebags.c |   12 ++++
 src/lsmsvgattributebags.h |    3 +-
 src/lsmsvgattributes.c    |  134 +++++++++++++++++++++++++++++++++++++++++++--
 src/lsmsvgattributes.h    |   21 +++++++
 src/lsmsvggraphic.c       |    2 +
 src/lsmsvgstyle.c         |    3 +
 src/lsmsvgstyle.h         |    2 +
 src/lsmsvgutils.h         |    2 +-
 src/lsmsvgview.c          |    9 +++
 10 files changed, 195 insertions(+), 23 deletions(-)

diff --git a/src/lsmdomattributes.h b/src/lsmdomattributes.h
index 7bf56b9..164079b 100644
--- a/src/lsmdomattributes.h
+++ b/src/lsmdomattributes.h
@@ -58,45 +58,45 @@ typedef struct {
 
 typedef void (*LsmDomAttributeFinalizeFunc) (void *);
 
-LsmDomAttributeMap *	lsm_dom_attribute_map_new 			(void);
+LsmDomAttributeMap *	lsm_dom_attribute_map_new 		(void);
 LsmDomAttributeMap *	lsm_dom_attribute_map_duplicate		(const LsmDomAttributeMap *from);
-void			lsm_dom_attribute_map_free			(LsmDomAttributeMap *map);
+void			lsm_dom_attribute_map_free		(LsmDomAttributeMap *map);
 
-void 			lsm_dom_attribute_map_add_bag_attribute  	(LsmDomAttributeMap *map,
+void 		lsm_dom_attribute_map_add_bag_attribute  	(LsmDomAttributeMap *map,
 								 const char *name,
 								 ptrdiff_t attribute_offset,
 								 const LsmDomAttributeClass *attribute_class,
 								 ptrdiff_t bag_offset,
 								 const LsmDomAttributeBagClass *bag_class);
-void			lsm_dom_attribute_map_add_attribute_full	(LsmDomAttributeMap *map,
+void		lsm_dom_attribute_map_add_attribute_full	(LsmDomAttributeMap *map,
 								 char const *name,
 								 ptrdiff_t offset,
 								 const LsmDomAttributeClass *attribute_class);
-void			lsm_dom_attribute_map_add_attribute 	(LsmDomAttributeMap *map,
+void		lsm_dom_attribute_map_add_attribute 		(LsmDomAttributeMap *map,
 								 char const *name,
 								 ptrdiff_t offset);
 
-void			lsm_dom_attribute_map_free_attributes 	(LsmDomAttributeMap *map,
+void		lsm_dom_attribute_map_free_attributes 		(LsmDomAttributeMap *map,
 								 void *instance);
 
-gboolean		lsm_dom_attribute_map_set_attribute	(LsmDomAttributeMap *map,
+gboolean	lsm_dom_attribute_map_set_attribute		(LsmDomAttributeMap *map,
 								 void *instance,
 								 char const *name,
 								 char const *value);
-char const *		lsm_dom_attribute_map_get_attribute	(LsmDomAttributeMap *map,
+char const *	lsm_dom_attribute_map_get_attribute		(LsmDomAttributeMap *map,
 								 void *instance,
 								 char const *name);
-gboolean		lsm_dom_attribute_map_set_css_attribute	(LsmDomAttributeMap *map,
+gboolean	lsm_dom_attribute_map_set_css_attribute		(LsmDomAttributeMap *map,
 								 void *instance,
 								 char const *name,
 								 char const *value,
 								 LsmDomCssType css_type);
-gboolean		lsm_dom_attribute_map_is_attribute_defined	(LsmDomAttributeMap *map,
+gboolean	lsm_dom_attribute_map_is_attribute_defined	(LsmDomAttributeMap *map,
 								 void *instance,
 								 char const *name);
 
-gboolean 		lsm_dom_attribute_is_defined 		(const LsmDomAttribute *attribute);
-char const * 		lsm_dom_attribute_get_value 		(const LsmDomAttribute *attribute);
+gboolean 	lsm_dom_attribute_is_defined 			(const LsmDomAttribute *attribute);
+char const * 	lsm_dom_attribute_get_value 			(const LsmDomAttribute *attribute);
 
 typedef struct {
 	LsmDomAttribute attr;
@@ -138,7 +138,7 @@ typedef unsigned int (*LsmDomNamedConvert) (const char *string);
 
 void 	lsm_dom_boolean_attribute_parse		(LsmDomBooleanAttribute *attribute,
 						 gboolean *default_value);
-void 	lsm_dom_unsigned_attribute_parse		(LsmDomUnsignedAttribute *attribute,
+void 	lsm_dom_unsigned_attribute_parse	(LsmDomUnsignedAttribute *attribute,
 						 unsigned *default_value);
 void 	lsm_dom_double_attribute_parse		(LsmDomDoubleAttribute *attribute,
 						 double *default_value);
@@ -151,11 +151,11 @@ void 	lsm_dom_enum_list_attribute_parse 	(LsmDomEnumListAttribute *attribute,
 						 LsmDomEnumList *style_value,
 						 LsmDomNamedConvert convert);
 
-void	lsm_dom_string_attribute_finalize		(void *abstract);
+void	lsm_dom_string_attribute_finalize	(void *abstract);
 void 	lsm_dom_enum_list_attribute_finalize 	(void *abstract);
 
 
-void 	lsm_dom_attribute_map_add_string 		(LsmDomAttributeMap *map,
+void 	lsm_dom_attribute_map_add_string 	(LsmDomAttributeMap *map,
 						 char const *name,
 						 ptrdiff_t offset);
 void 	lsm_dom_attribute_map_add_enum_list 	(LsmDomAttributeMap *map,
diff --git a/src/lsmsvgattributebags.c b/src/lsmsvgattributebags.c
index 49f9e0d..1dec313 100644
--- a/src/lsmsvgattributebags.c
+++ b/src/lsmsvgattributebags.c
@@ -84,6 +84,10 @@ static const LsmDomAttributeBagClass lsm_svg_stroke_attribute_bag_class =
 	.finalize = lsm_svg_stroke_attribute_bag_finalize
 };
 
+static const LsmDomAttributeClass lsm_svg_dash_array_attribute_class = {
+	.finalize = lsm_svg_dash_array_attribute_finalize
+};
+
 void
 lsm_dom_attribute_map_add_stroke_attribute_bag (LsmDomAttributeMap *map, ptrdiff_t bag_offset)
 {
@@ -111,6 +115,14 @@ lsm_dom_attribute_map_add_stroke_attribute_bag (LsmDomAttributeMap *map, ptrdiff
 						 offsetof (LsmSvgStrokeAttributeBag, miter_limit),
 						 NULL,
 						 bag_offset, &lsm_svg_stroke_attribute_bag_class);
+	lsm_dom_attribute_map_add_bag_attribute (map, "stroke-dasharray",
+						 offsetof (LsmSvgStrokeAttributeBag, dash_array),
+						 &lsm_svg_dash_array_attribute_class,
+						 bag_offset, &lsm_svg_stroke_attribute_bag_class);
+	lsm_dom_attribute_map_add_bag_attribute (map, "stroke-dashoffset",
+						 offsetof (LsmSvgStrokeAttributeBag, dash_offset),
+						 NULL,
+						 bag_offset, &lsm_svg_stroke_attribute_bag_class);
 }
 
 static void *
diff --git a/src/lsmsvgattributebags.h b/src/lsmsvgattributebags.h
index f72395a..9fe4ab7 100644
--- a/src/lsmsvgattributebags.h
+++ b/src/lsmsvgattributebags.h
@@ -39,8 +39,9 @@ typedef struct {
 	LsmDomEnumAttribute line_join;
 	LsmDomEnumAttribute line_cap;
 	LsmSvgDoubleAttribute miter_limit;
-	LsmSvgLengthAttribute dash_offset;
 	LsmDomDoubleAttribute opacity;
+	LsmSvgLengthAttribute dash_offset;
+	LsmSvgDashArrayAttribute dash_array;
 } LsmSvgStrokeAttributeBag;
 
 typedef struct {
diff --git a/src/lsmsvgattributes.c b/src/lsmsvgattributes.c
index f25cffc..074248a 100644
--- a/src/lsmsvgattributes.c
+++ b/src/lsmsvgattributes.c
@@ -28,6 +28,53 @@
 #include <stdio.h>
 #include <math.h>
 
+const LsmSvgDashArray lsm_svg_dash_array_null = {0, NULL};
+
+LsmSvgDashArray *
+lsm_svg_dash_array_new (unsigned int n_dashes)
+{
+	LsmSvgDashArray *array;
+
+	g_return_val_if_fail (n_dashes > 0, (LsmSvgDashArray *) &lsm_svg_dash_array_null);
+
+	array = g_new (LsmSvgDashArray, 1);
+	if (array != NULL) {
+		array->n_dashes = n_dashes;
+		array->dashes = g_new (double, 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 (double) * origin->n_dashes);
+
+	return duplicate;
+}
+
 const LsmSvgColor lsm_svg_color_null = {0.0, 0.0, 0.0};
 
 void
@@ -86,8 +133,8 @@ lsm_svg_length_compute (const LsmSvgLength *length, double viewbox, double font_
 
 void
 lsm_svg_length_attribute_parse (LsmSvgLengthAttribute *attribute,
-			     LsmSvgLength *default_value,
-			     double font_size)
+				LsmSvgLength *default_value,
+				double font_size)
 {
 	const char *string;
 	char *length_type_str;
@@ -103,7 +150,7 @@ lsm_svg_length_attribute_parse (LsmSvgLengthAttribute *attribute,
 		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);
+								  default_value->value, font_size);
 
 		*default_value = attribute->length;
 	}
@@ -111,8 +158,8 @@ lsm_svg_length_attribute_parse (LsmSvgLengthAttribute *attribute,
 
 void
 lsm_svg_animated_length_attribute_parse (LsmSvgAnimatedLengthAttribute *attribute,
-				      LsmSvgLength *default_value,
-				      double font_size)
+					 LsmSvgLength *default_value,
+					 double font_size)
 {
 	const char *string;
 	char *length_type_str;
@@ -129,7 +176,7 @@ lsm_svg_animated_length_attribute_parse (LsmSvgAnimatedLengthAttribute *attribut
 		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);
+								       default_value->value, font_size);
 		attribute->length.animated = attribute->length.base;
 
 		*default_value = attribute->length.base;
@@ -137,6 +184,81 @@ lsm_svg_animated_length_attribute_parse (LsmSvgAnimatedLengthAttribute *attribut
 }
 
 void
+lsm_svg_dash_array_attribute_finalize (void *abstract)
+{
+	LsmSvgDashArrayAttribute *attribute = abstract;
+
+	g_return_if_fail (attribute != NULL);
+
+	lsm_svg_dash_array_free (attribute->value);
+	attribute->value = NULL;
+}
+
+void
+lsm_svg_dash_array_attribute_parse (LsmSvgDashArrayAttribute *attribute,
+				    LsmSvgDashArray **default_value)
+{
+	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;
+
+	if (string == NULL) {
+		lsm_svg_dash_array_free (attribute->value);
+		attribute->value = lsm_svg_dash_array_duplicate (*default_value);
+	} else {
+		unsigned int n_dashes = 1;
+
+		lsm_svg_dash_array_free (attribute->value);
+
+		if (strcmp (string, "none") == 0) {
+			attribute->value = (LsmSvgDashArray *) &lsm_svg_dash_array_null;
+		} else {
+			char *iter = (char *) string;
+			unsigned int i;
+
+			while (*iter != '\0') {
+				if (*iter == ',')
+					n_dashes++;
+				iter++;
+			}
+
+			g_message ("n_dashes = %d", n_dashes);
+
+			attribute->value = lsm_svg_dash_array_new (n_dashes);
+			if (attribute->value != &lsm_svg_dash_array_null) {
+				LsmSvgLength length;
+
+				iter = (char *)string;
+				lsm_svg_str_skip_spaces (&iter);
+
+				for (i = 0; i < n_dashes; i++) {
+					g_message ("iter = %s", iter);
+					if (lsm_svg_str_parse_double (&iter, &length.value_unit)) {
+						g_message ("iter for length = %s", iter);
+						length.type = lsm_svg_length_type_from_string (iter);
+						attribute->value->dashes[i] = lsm_svg_length_compute (&length,
+												      0.0, 0.0);
+						g_message ("length.value = %g", length.value_unit);
+						while (*iter != '\0' && *iter != ' ' && *iter != ',')
+							iter ++;
+					} else
+						attribute->value->dashes[i] = 0.0;
+					g_message ("dashes[%d] = %g", i, attribute->value->dashes[i]);
+					lsm_svg_str_skip_comma_and_spaces (&iter);
+				}
+			}
+		}
+
+		lsm_svg_dash_array_free (*default_value);
+		*default_value = lsm_svg_dash_array_duplicate (attribute->value);
+	}
+}
+
+void
 lsm_svg_fill_rule_attribute_parse (LsmDomEnumAttribute *attribute,
 				   unsigned int *style_value)
 {
diff --git a/src/lsmsvgattributes.h b/src/lsmsvgattributes.h
index f46fdab..ca66f49 100644
--- a/src/lsmsvgattributes.h
+++ b/src/lsmsvgattributes.h
@@ -44,6 +44,22 @@ typedef struct {
 extern const LsmSvgColor lsm_svg_color_null;
 
 typedef struct {
+	unsigned int n_dashes;
+	double *dashes;
+} LsmSvgDashArray;
+
+extern const LsmSvgDashArray lsm_svg_dash_array_null;
+
+LsmSvgDashArray * 	lsm_svg_dash_array_new 		(unsigned int n_dashes);
+void 			lsm_svg_dash_array_free 	(LsmSvgDashArray *array);
+LsmSvgDashArray * 	lsm_svg_dash_array_duplicate 	(const LsmSvgDashArray *origin);
+
+typedef struct {
+	LsmDomAttribute attr;
+	LsmSvgDashArray *value;
+} LsmSvgDashArrayAttribute;
+
+typedef struct {
 	double value;
 	double value_unit;
 	LsmSvgLengthType type;
@@ -112,6 +128,11 @@ void		lsm_svg_length_attribute_parse 		(LsmSvgLengthAttribute *attribute,
 void 		lsm_svg_animated_length_attribute_parse (LsmSvgAnimatedLengthAttribute *attribute,
 							 LsmSvgLength *default_value,
 							 double font_size);
+
+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,
diff --git a/src/lsmsvggraphic.c b/src/lsmsvggraphic.c
index 41f0b6d..ffd771b 100644
--- a/src/lsmsvggraphic.c
+++ b/src/lsmsvggraphic.c
@@ -114,6 +114,8 @@ lsm_svg_graphic_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 		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);
 	}
 
 	if (graphic->transform != NULL) {
diff --git a/src/lsmsvgstyle.c b/src/lsmsvgstyle.c
index 38acda6..8e98709 100644
--- a/src/lsmsvgstyle.c
+++ b/src/lsmsvgstyle.c
@@ -40,6 +40,8 @@ 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);
 }
@@ -56,6 +58,7 @@ lsm_svg_style_duplicate (const LsmSvgStyle *from)
 
 	memcpy (style, from, sizeof (LsmSvgStyle));
 
+	style->stroke.dash_array = lsm_svg_dash_array_duplicate (from->stroke.dash_array);
 	style->text.font_family = g_strdup (from->text.font_family);
 
 	return style;
diff --git a/src/lsmsvgstyle.h b/src/lsmsvgstyle.h
index 8321e6e..ce8303d 100644
--- a/src/lsmsvgstyle.h
+++ b/src/lsmsvgstyle.h
@@ -43,6 +43,8 @@ struct _GSvgStyle {
 		LsmSvgLineCap line_cap;
 		double opacity;
 		double miter_limit;
+		LsmSvgDashArray *dash_array;
+		LsmSvgLength dash_offset;
 	} stroke;
 
 	struct {
diff --git a/src/lsmsvgutils.h b/src/lsmsvgutils.h
index 19bc589..828772d 100644
--- a/src/lsmsvgutils.h
+++ b/src/lsmsvgutils.h
@@ -27,7 +27,7 @@
 
 G_BEGIN_DECLS
 
-gboolean lsm_svg_str_parse_double 		(char **str, double *x);
+gboolean lsm_svg_str_parse_double 	(char **str, double *x);
 gboolean lsm_svg_str_parse_double_list 	(char **str, unsigned int n_values, double *values);
 
 static inline void
diff --git a/src/lsmsvgview.c b/src/lsmsvgview.c
index dff7815..1e05a20 100644
--- a/src/lsmsvgview.c
+++ b/src/lsmsvgview.c
@@ -819,6 +819,15 @@ _paint (LsmSvgView *view)
 
 		cairo_set_miter_limit (cairo, stroke->miter_limit.value);
 		cairo_set_line_width (cairo, stroke->width.length.value);
+
+		if (stroke->dash_array.value != NULL)
+			cairo_set_dash (cairo,
+					stroke->dash_array.value->dashes,
+					stroke->dash_array.value->n_dashes,
+					stroke->dash_offset.length.value);
+		else
+			cairo_set_dash (cairo, NULL, 0, 0.0);
+
 		cairo_stroke (cairo);
 	}
 



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