[lasem] svg_gradient: allow referencing of radial from linear and vice-versa.



commit 6798e1c29a435af3567f804dcafb6d556c94bbea
Author: Emmanuel Pacaud <emmanuel gnome org>
Date:   Fri Aug 13 23:11:23 2010 +0200

    svg_gradient: allow referencing of radial from linear and vice-versa.

 configure.ac                      |    2 +-
 src/Makefile.am                   |    2 +
 src/lsmsvg.h                      |    1 +
 src/lsmsvggradientelement.c       |  150 +++++++++++++++++++++++++++++++++++++
 src/lsmsvggradientelement.h       |   67 ++++++++++++++++
 src/lsmsvglineargradientelement.c |  139 ++++++++++++----------------------
 src/lsmsvglineargradientelement.h |   12 +--
 src/lsmsvgradialgradientelement.c |  149 +++++++++++++------------------------
 src/lsmsvgradialgradientelement.h |   12 +--
 9 files changed, 329 insertions(+), 205 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 591a30c..9aeed9a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -7,7 +7,7 @@ m4_define([lasem_version], [lasem_version_major.lasem_version_minor.lasem_versio
 
 m4_define([lasem_libtool_current], m4_eval(100 * lasem_version_major + lasem_version_minor))
 
-AC_INIT([lasem],[lasem_version],[http://bugzilla.gnome.org/enter_bug.cgi?product=lasem],[lasem])
+AC_INIT([lasem], [lasem_version], [http://bugzilla.gnome.org/], [lasem])
 
 AM_INIT_AUTOMAKE([-Wno-portability])
 AM_MAINTAINER_MODE
diff --git a/src/Makefile.am b/src/Makefile.am
index 3669113..b0b198c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -99,6 +99,7 @@ liblasem_ LASEM_API_VERSION@_la_SOURCES =				\
 	lsmsvgpathelement.c			\
 	lsmsvgtextelement.c			\
 	lsmsvgtspanelement.c			\
+	lsmsvggradientelement.c			\
 	lsmsvglineargradientelement.c		\
 	lsmsvgradialgradientelement.c		\
 	lsmsvgstopelement.c			\
@@ -186,6 +187,7 @@ LASEM_HDRS = \
 	lsmsvgpolygonelement.h			\
 	lsmsvgtextelement.h			\
 	lsmsvgtspanelement.h			\
+	lsmsvggradientelement.h			\
 	lsmsvglineargradientelement.h		\
 	lsmsvgradialgradientelement.h		\
 	lsmsvgstopelement.h			\
diff --git a/src/lsmsvg.h b/src/lsmsvg.h
index d9c1639..a6b61d5 100644
--- a/src/lsmsvg.h
+++ b/src/lsmsvg.h
@@ -47,6 +47,7 @@ typedef struct _LsmSvgPolygonElement LsmSvgPolygonElement;
 typedef struct _LsmSvgPathElement LsmSvgPathElement;
 typedef struct _LsmSvgTextElement LsmSvgTextElement;
 typedef struct _LsmSvgTspanElement LsmSvgTspanElement;
+typedef struct _LsmSvgGradientElement LsmSvgGradientElement;
 typedef struct _LsmSvgLinearGradientElement LsmSvgLinearGradientElement;
 typedef struct _LsmSvgRadialGradientElement LsmSvgRadialGradientElement;
 typedef struct _LsmSvgStopElement LsmSvgStopElement;
diff --git a/src/lsmsvggradientelement.c b/src/lsmsvggradientelement.c
new file mode 100644
index 0000000..e0e9b44
--- /dev/null
+++ b/src/lsmsvggradientelement.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright © 2009 Emmanuel Pacaud
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author:
+ * 	Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+#include <lsmsvggradientelement.h>
+#include <lsmsvgstopelement.h>
+#include <lsmsvgview.h>
+#include <lsmdomdocument.h>
+#include <lsmdebug.h>
+#include <stdio.h>
+
+static const LsmSvgGradientElementAttributes default_attributes = {
+	.transform = {1.0, 0.0, 0.0, 1.0, 0.0, 0.0, LSM_SVG_MATRIX_FLAGS_IDENTITY},
+	.units = LSM_SVG_PATTERN_UNITS_OBJECT_BOUNDING_BOX,
+	.spread_method = LSM_SVG_SPREAD_METHOD_PAD,
+};
+
+static GObjectClass *parent_class;
+
+/* GdomNode implementation */
+
+static gboolean
+lsm_svg_gradient_element_can_append_child (LsmDomNode *parent, LsmDomNode *child)
+{
+	return LSM_IS_SVG_STOP_ELEMENT (child);
+}
+
+/* LsmSvgElement implementation */
+
+static void
+lsm_svg_gradient_element_render (LsmSvgElement *self, LsmSvgView *view)
+{
+	LsmSvgGradientElement *gradient = LSM_SVG_GRADIENT_ELEMENT (self);
+	LsmSvgGradientElement *referenced_gradient;
+	LsmSvgGradientElementClass *gradient_class = LSM_SVG_GRADIENT_ELEMENT_GET_CLASS (self);
+	LsmDomNode *node;
+
+	if (!gradient->enable_rendering)
+		return;
+
+	gradient->enable_rendering = FALSE;
+
+	referenced_gradient = gradient_class->create_gradient (self, view);
+
+	if (referenced_gradient == NULL)
+		return;
+
+	lsm_debug ("render", "[LsmSvgElement::render] transform %g, %g, %g, %g, %g, %g",
+		   gradient->transform.matrix.a,
+		   gradient->transform.matrix.b,
+		   gradient->transform.matrix.c,
+		   gradient->transform.matrix.d,
+		   gradient->transform.matrix.e,
+		   gradient->transform.matrix.f);
+
+	lsm_svg_view_set_gradient_properties (view,
+					      gradient->spread_method.value,
+					      gradient->units.value,
+					      &gradient->transform.matrix);
+
+	for (node = LSM_DOM_NODE (referenced_gradient)->first_child; node != NULL; node = node->next_sibling)
+		if (LSM_IS_SVG_ELEMENT (node))
+		    lsm_svg_element_render (LSM_SVG_ELEMENT (node), view);
+}
+
+static void
+lsm_svg_gradient_element_enable_rendering (LsmSvgElement *element)
+{
+	LSM_SVG_GRADIENT_ELEMENT (element)->enable_rendering = TRUE;
+}
+
+/* LsmSvgGradientElement implementation */
+
+
+static void
+lsm_svg_gradient_element_init (LsmSvgGradientElement *self)
+{
+	self->enable_rendering = FALSE;
+
+	self->units.value = default_attributes.units;
+	self->spread_method.value = default_attributes.spread_method;
+	self->transform.matrix = default_attributes.transform;
+}
+
+/* LsmSvgGradientElement class */
+
+static const LsmAttributeInfos lsm_svg_gradient_element_attribute_infos[] = {
+	{
+		.name = "gradientTransform",
+		.attribute_offset = offsetof (LsmSvgGradientElement, transform),
+		.trait_class = &lsm_svg_matrix_trait_class,
+		.trait_default = &default_attributes.transform
+	},
+	{
+		.name = "gradientUnits",
+		.attribute_offset = offsetof (LsmSvgGradientElement, units),
+		.trait_class = &lsm_svg_pattern_units_trait_class,
+		.trait_default = &default_attributes.units
+	},
+	{
+		.name = "spreadMethod",
+		.attribute_offset = offsetof (LsmSvgGradientElement, spread_method),
+		.trait_class = &lsm_svg_spread_method_trait_class,
+		.trait_default = &default_attributes.spread_method
+	},
+	{
+		.name = "xlink:href",
+		.attribute_offset = offsetof (LsmSvgGradientElement, href),
+		.trait_class = &lsm_null_trait_class
+	}
+};
+
+static void
+lsm_svg_gradient_element_class_init (LsmSvgGradientElementClass *klass)
+{
+	LsmDomNodeClass *d_node_class = LSM_DOM_NODE_CLASS (klass);
+	LsmSvgElementClass *s_element_class = LSM_SVG_ELEMENT_CLASS (klass);
+
+	parent_class = g_type_class_peek_parent (klass);
+
+	d_node_class->can_append_child = lsm_svg_gradient_element_can_append_child;
+
+	s_element_class->render = lsm_svg_gradient_element_render;
+	s_element_class->enable_rendering = lsm_svg_gradient_element_enable_rendering;
+	s_element_class->attribute_manager = lsm_attribute_manager_duplicate (s_element_class->attribute_manager);
+
+	lsm_attribute_manager_add_attributes (s_element_class->attribute_manager,
+					      G_N_ELEMENTS (lsm_svg_gradient_element_attribute_infos),
+					      lsm_svg_gradient_element_attribute_infos);
+}
+
+G_DEFINE_ABSTRACT_TYPE (LsmSvgGradientElement, lsm_svg_gradient_element, LSM_TYPE_SVG_ELEMENT)
diff --git a/src/lsmsvggradientelement.h b/src/lsmsvggradientelement.h
new file mode 100644
index 0000000..bb811cd
--- /dev/null
+++ b/src/lsmsvggradientelement.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright © 2009 Emmanuel Pacaud
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author:
+ * 	Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+#ifndef LSM_SVG_GRADIENT_ELEMENT_H
+#define LSM_SVG_GRADIENT_ELEMENT_H
+
+#include <lsmsvg.h>
+#include <lsmsvgelement.h>
+
+G_BEGIN_DECLS
+
+typedef struct {
+	LsmSvgMatrix transform;
+	LsmSvgPatternUnits units;
+	LsmSvgSpreadMethod spread_method;
+} LsmSvgGradientElementAttributes;
+
+#define LSM_TYPE_SVG_GRADIENT_ELEMENT             (lsm_svg_gradient_element_get_type ())
+#define LSM_SVG_GRADIENT_ELEMENT(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), LSM_TYPE_SVG_GRADIENT_ELEMENT, LsmSvgGradientElement))
+#define LSM_SVG_GRADIENT_ELEMENT_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), LSM_TYPE_SVG_GRADIENT_ELEMENT, LsmSvgGradientElementClass))
+#define LSM_IS_SVG_GRADIENT_ELEMENT(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LSM_TYPE_SVG_GRADIENT_ELEMENT))
+#define LSM_IS_SVG_GRADIENT_ELEMENT_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), LSM_TYPE_SVG_GRADIENT_ELEMENT))
+#define LSM_SVG_GRADIENT_ELEMENT_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS((obj), LSM_TYPE_SVG_GRADIENT_ELEMENT, LsmSvgGradientElementClass))
+
+typedef struct _LsmSvgGradientElementClass LsmSvgGradientElementClass;
+
+struct _LsmSvgGradientElement {
+	LsmSvgElement element;
+
+	LsmSvgTransformAttribute transform;
+	LsmSvgPatternUnitsAttribute units;
+	LsmSvgSpreadMethodAtttribute spread_method;
+	LsmAttribute href;
+
+	gboolean enable_rendering;
+};
+
+struct _LsmSvgGradientElementClass {
+	LsmSvgElementClass  element_class;
+
+	LsmSvgGradientElement * (*create_gradient)	(LsmSvgElement *self, LsmSvgView *view);
+};
+
+GType lsm_svg_gradient_element_get_type (void);
+
+G_END_DECLS
+
+#endif
diff --git a/src/lsmsvglineargradientelement.c b/src/lsmsvglineargradientelement.c
index d11fa97..8478f08 100644
--- a/src/lsmsvglineargradientelement.c
+++ b/src/lsmsvglineargradientelement.c
@@ -27,23 +27,23 @@
 #include <stdio.h>
 
 typedef struct {
+	LsmSvgGradientElementAttributes base;
 	LsmSvgLength x1;
 	LsmSvgLength y1;
 	LsmSvgLength x2;
 	LsmSvgLength y2;
-	LsmSvgMatrix transform;
-	LsmSvgPatternUnits units;
-	LsmSvgSpreadMethod spread_method;
 } LsmSvgLinearGradientElementAttributes;
 
 static const LsmSvgLinearGradientElementAttributes default_attributes = {
+	.base = {
+		.transform = {1.0, 0.0, 0.0, 1.0, 0.0, 0.0, LSM_SVG_MATRIX_FLAGS_IDENTITY},
+		.units = LSM_SVG_PATTERN_UNITS_OBJECT_BOUNDING_BOX,
+		.spread_method = LSM_SVG_SPREAD_METHOD_PAD
+	},
 	.x1 = { .value_unit =   0.0, .type = LSM_SVG_LENGTH_TYPE_PERCENTAGE},
 	.y1 = { .value_unit =   0.0, .type = LSM_SVG_LENGTH_TYPE_PERCENTAGE},
 	.x2 = { .value_unit = 100.0, .type = LSM_SVG_LENGTH_TYPE_PERCENTAGE},
-	.y1 = { .value_unit =   0.0, .type = LSM_SVG_LENGTH_TYPE_PERCENTAGE},
-	.transform = {1.0, 0.0, 0.0, 1.0, 0.0, 0.0, LSM_SVG_MATRIX_FLAGS_IDENTITY},
-	.units = LSM_SVG_PATTERN_UNITS_OBJECT_BOUNDING_BOX,
-	.spread_method = LSM_SVG_SPREAD_METHOD_PAD
+	.y1 = { .value_unit =   0.0, .type = LSM_SVG_LENGTH_TYPE_PERCENTAGE}
 };
 
 static GObjectClass *parent_class;
@@ -58,12 +58,12 @@ lsm_svg_linear_gradient_element_get_node_name (LsmDomNode *node)
 
 /* LsmSvgElement implementation */
 
-static LsmSvgLinearGradientElement *
+static LsmSvgGradientElement *
 lsm_svg_linear_gradient_element_inherit_referenced (LsmDomDocument *owner,
-					    LsmSvgLinearGradientElement *gradient,
-					    LsmSvgLinearGradientElementAttributes *attributes)
+						    LsmSvgGradientElement *gradient,
+						    LsmSvgLinearGradientElementAttributes *attributes)
 {
-	LsmSvgLinearGradientElement *referenced_gradient = gradient;
+	LsmSvgGradientElement *referenced_gradient = gradient;
 	LsmDomElement *element;
 
 	if (lsm_attribute_is_defined (&gradient->href)) {
@@ -76,14 +76,14 @@ lsm_svg_linear_gradient_element_inherit_referenced (LsmDomDocument *owner,
 			id++;
 
 		element = lsm_dom_document_get_element_by_id (owner, id);
-		if (LSM_IS_SVG_LINEAR_GRADIENT_ELEMENT (element)) {
+		if (LSM_IS_SVG_GRADIENT_ELEMENT (element)) {
 			lsm_debug ("render",
 				   "[LsmSvgLinearGradientElement::inherit_attributes]"
 				   " Found referenced element '%s'", id);
 
 			referenced_gradient = lsm_svg_linear_gradient_element_inherit_referenced
 				(owner,
-				 LSM_SVG_LINEAR_GRADIENT_ELEMENT (element),
+				 LSM_SVG_GRADIENT_ELEMENT (element),
 				 attributes);
 		} else {
 			lsm_debug ("render",
@@ -93,61 +93,62 @@ lsm_svg_linear_gradient_element_inherit_referenced (LsmDomDocument *owner,
 		}
 	}
 
-	if (lsm_attribute_is_defined (&gradient->x1.base))
-		attributes->x1 = gradient->x1.length;
-	if (lsm_attribute_is_defined (&gradient->y1.base))
-		attributes->y1 = gradient->y1.length;
-	if (lsm_attribute_is_defined (&gradient->x1.base))
-		attributes->x2 = gradient->x2.length;
-	if (lsm_attribute_is_defined (&gradient->y2.base))
-		attributes->y2 = gradient->y2.length;
+	if (LSM_IS_SVG_LINEAR_GRADIENT_ELEMENT (gradient)) {
+		LsmSvgLinearGradientElement *linear = LSM_SVG_LINEAR_GRADIENT_ELEMENT (gradient);
+		if (lsm_attribute_is_defined (&linear->x1.base))
+			attributes->x1 = linear->x1.length;
+		if (lsm_attribute_is_defined (&linear->y1.base))
+			attributes->y1 = linear->y1.length;
+		if (lsm_attribute_is_defined (&linear->x1.base))
+			attributes->x2 = linear->x2.length;
+		if (lsm_attribute_is_defined (&linear->y2.base))
+			attributes->y2 = linear->y2.length;
+	}
+
 	if (lsm_attribute_is_defined (&gradient->transform.base))
-		attributes->transform = gradient->transform.matrix;
+		attributes->base.transform = gradient->transform.matrix;
 	if (lsm_attribute_is_defined (&gradient->units.base))
-		attributes->units = gradient->units.value;
+		attributes->base.units = gradient->units.value;
 	if (lsm_attribute_is_defined (&gradient->spread_method.base))
-		attributes->spread_method = gradient->spread_method.value;
+		attributes->base.spread_method = gradient->spread_method.value;
 
 	return referenced_gradient;
 }
 
-static void
-lsm_svg_linear_gradient_element_render (LsmSvgElement *self, LsmSvgView *view)
+static LsmSvgGradientElement *
+lsm_svg_linear_gradient_element_create_gradient (LsmSvgElement *self,
+						 LsmSvgView *view)
 {
 	LsmSvgLinearGradientElement *gradient = LSM_SVG_LINEAR_GRADIENT_ELEMENT (self);
-	LsmSvgLinearGradientElement *referenced_gradient;
-	LsmDomNode *node;
+	LsmSvgGradientElement *referenced_gradient;
 	gboolean is_object_bounding_box;
 	double x1, x2, y1, y2;
 
-	if (!gradient->enable_rendering)
-		return;
-
-	gradient->enable_rendering = FALSE;
-
-	if (lsm_attribute_is_defined (&gradient->href)) {
+	if (lsm_attribute_is_defined (&gradient->base.href)) {
 		LsmSvgLinearGradientElementAttributes attributes;
 		LsmDomDocument *owner;
 		attributes = default_attributes;
 
 		owner = lsm_dom_node_get_owner_document (LSM_DOM_NODE (self));
 
-		referenced_gradient = lsm_svg_linear_gradient_element_inherit_referenced (owner, gradient, &attributes);
+		referenced_gradient = lsm_svg_linear_gradient_element_inherit_referenced
+			(owner, LSM_SVG_GRADIENT_ELEMENT (gradient), &attributes);
 
 		gradient->x1.length = attributes.x1;
 		gradient->y1.length = attributes.y1;
 		gradient->x2.length = attributes.x2;
 		gradient->y2.length = attributes.y2;
-		gradient->transform.matrix = attributes.transform;
-		gradient->units.value = attributes.units;
-		gradient->spread_method.value = attributes.spread_method;
+
+		gradient->base.transform.matrix = attributes.base.transform;
+		gradient->base.units.value = attributes.base.units;
+		gradient->base.spread_method.value = attributes.base.spread_method;
 	} else
-		referenced_gradient = gradient;
+		referenced_gradient = LSM_SVG_GRADIENT_ELEMENT (gradient);
 
 	if (referenced_gradient == NULL)
-		return;
+		return NULL;
 
-	is_object_bounding_box = (gradient->units.value == LSM_SVG_PATTERN_UNITS_OBJECT_BOUNDING_BOX);
+	is_object_bounding_box = (gradient->base.units.value == LSM_SVG_PATTERN_UNITS_OBJECT_BOUNDING_BOX);
 
 	if (is_object_bounding_box) {
 		LsmBox viewbox = {.x = 0.0, .y = .0, .width = 1.0, .height = 1.0};
@@ -160,28 +161,15 @@ lsm_svg_linear_gradient_element_render (LsmSvgElement *self, LsmSvgView *view)
 	x2 = lsm_svg_view_normalize_length (view, &gradient->x2.length, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
 	y2 = lsm_svg_view_normalize_length (view, &gradient->y2.length, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
 
-	lsm_debug ("render", "[LsmSvgLinearGradientElement::render] Create linear %g, %g, %g, %g",
-		    x1, y1, x2, y2);
-
 	if (is_object_bounding_box)
 		lsm_svg_view_pop_viewbox (view);
 
-	lsm_svg_view_create_linear_gradient (view, x1, y1, x2, y2);
-
-	lsm_svg_view_set_gradient_properties (view,
-					      gradient->spread_method.value,
-					      gradient->units.value,
-					      &gradient->transform.matrix);
+	lsm_debug ("render", "[LsmSvgLinearGradientElement::render] Create linear %g, %g, %g, %g",
+		    x1, y1, x2, y2);
 
-	for (node = LSM_DOM_NODE (referenced_gradient)->first_child; node != NULL; node = node->next_sibling)
-		if (LSM_IS_SVG_ELEMENT (node))
-		    lsm_svg_element_render (LSM_SVG_ELEMENT (node), view);
-}
+	lsm_svg_view_create_linear_gradient (view, x1, y1, x2, y2);
 
-static void
-lsm_svg_linear_gradient_element_enable_rendering (LsmSvgElement *element)
-{
-	LSM_SVG_LINEAR_GRADIENT_ELEMENT (element)->enable_rendering = TRUE;
+	return referenced_gradient;
 }
 
 /* LsmSvgLinearGradientElement implementation */
@@ -195,15 +183,10 @@ lsm_svg_linear_gradient_element_new (void)
 static void
 lsm_svg_linear_gradient_element_init (LsmSvgLinearGradientElement *self)
 {
-	self->enable_rendering = FALSE;
-
 	self->x1.length = default_attributes.x1;
 	self->y1.length = default_attributes.y1;
 	self->x2.length = default_attributes.x2;
 	self->y2.length = default_attributes.y2;
-	self->transform.matrix = default_attributes.transform;
-	self->units.value = default_attributes.units;
-	self->spread_method.value = default_attributes.spread_method;
 }
 
 static void
@@ -238,29 +221,6 @@ static const LsmAttributeInfos lsm_svg_linear_gradient_element_attribute_infos[]
 		.attribute_offset = offsetof (LsmSvgLinearGradientElement, y2),
 		.trait_class = &lsm_svg_length_trait_class,
 		.trait_default = &default_attributes.y2
-	},
-	{
-		.name = "gradientTransform",
-		.attribute_offset = offsetof (LsmSvgLinearGradientElement, transform),
-		.trait_class = &lsm_svg_matrix_trait_class,
-		.trait_default = &default_attributes.transform
-	},
-	{
-		.name = "gradientUnits",
-		.attribute_offset = offsetof (LsmSvgLinearGradientElement, units),
-		.trait_class = &lsm_svg_pattern_units_trait_class,
-		.trait_default = &default_attributes.units
-	},
-	{
-		.name = "spreadMethod",
-		.attribute_offset = offsetof (LsmSvgLinearGradientElement, spread_method),
-		.trait_class = &lsm_svg_spread_method_trait_class,
-		.trait_default = &default_attributes.spread_method
-	},
-	{
-		.name = "xlink:href",
-		.attribute_offset = offsetof (LsmSvgLinearGradientElement, href),
-		.trait_class = &lsm_null_trait_class
 	}
 };
 
@@ -270,6 +230,7 @@ lsm_svg_linear_gradient_element_class_init (LsmSvgLinearGradientElementClass *s_
 	GObjectClass *object_class = G_OBJECT_CLASS (s_svg_class);
 	LsmDomNodeClass *d_node_class = LSM_DOM_NODE_CLASS (s_svg_class);
 	LsmSvgElementClass *s_element_class = LSM_SVG_ELEMENT_CLASS (s_svg_class);
+	LsmSvgGradientElementClass *s_gradient_class = LSM_SVG_GRADIENT_ELEMENT_CLASS (s_svg_class);
 
 	parent_class = g_type_class_peek_parent (s_svg_class);
 
@@ -279,13 +240,13 @@ lsm_svg_linear_gradient_element_class_init (LsmSvgLinearGradientElementClass *s_
 
 	s_element_class->category = LSM_SVG_ELEMENT_CATEGORY_GRADIENT;
 
-	s_element_class->render = lsm_svg_linear_gradient_element_render;
-	s_element_class->enable_rendering = lsm_svg_linear_gradient_element_enable_rendering;
 	s_element_class->attribute_manager = lsm_attribute_manager_duplicate (s_element_class->attribute_manager);
 
 	lsm_attribute_manager_add_attributes (s_element_class->attribute_manager,
 					      G_N_ELEMENTS (lsm_svg_linear_gradient_element_attribute_infos),
 					      lsm_svg_linear_gradient_element_attribute_infos);
+
+	s_gradient_class->create_gradient = lsm_svg_linear_gradient_element_create_gradient;
 }
 
-G_DEFINE_TYPE (LsmSvgLinearGradientElement, lsm_svg_linear_gradient_element, LSM_TYPE_SVG_ELEMENT)
+G_DEFINE_TYPE (LsmSvgLinearGradientElement, lsm_svg_linear_gradient_element, LSM_TYPE_SVG_GRADIENT_ELEMENT)
diff --git a/src/lsmsvglineargradientelement.h b/src/lsmsvglineargradientelement.h
index 202eb6e..4be14ae 100644
--- a/src/lsmsvglineargradientelement.h
+++ b/src/lsmsvglineargradientelement.h
@@ -24,7 +24,7 @@
 #define LSM_SVG_LINEAR_GRADIENT_ELEMENT_H
 
 #include <lsmsvg.h>
-#include <lsmsvgelement.h>
+#include <lsmsvggradientelement.h>
 
 G_BEGIN_DECLS
 
@@ -38,22 +38,16 @@ G_BEGIN_DECLS
 typedef struct _LsmSvgLinearGradientElementClass LsmSvgLinearGradientElementClass;
 
 struct _LsmSvgLinearGradientElement {
-	LsmSvgElement element;
+	LsmSvgGradientElement base;
 
 	LsmSvgLengthAttribute x1;
 	LsmSvgLengthAttribute y1;
 	LsmSvgLengthAttribute x2;
 	LsmSvgLengthAttribute y2;
-	LsmSvgTransformAttribute transform;
-	LsmSvgPatternUnitsAttribute units;
-	LsmSvgSpreadMethodAtttribute spread_method;
-	LsmAttribute href;
-
-	gboolean enable_rendering;
 };
 
 struct _LsmSvgLinearGradientElementClass {
-	LsmSvgElementClass  parent_class;
+	LsmSvgGradientElementClass  parent_class;
 };
 
 GType lsm_svg_linear_gradient_element_get_type (void);
diff --git a/src/lsmsvgradialgradientelement.c b/src/lsmsvgradialgradientelement.c
index 8c1ffcb..5b8f3a1 100644
--- a/src/lsmsvgradialgradientelement.c
+++ b/src/lsmsvgradialgradientelement.c
@@ -28,27 +28,27 @@
 #include <math.h>
 
 typedef struct {
+	LsmSvgGradientElementAttributes base;
 	LsmSvgLength cx;
 	LsmSvgLength cy;
 	LsmSvgLength r;
 	LsmSvgLength fx;
 	LsmSvgLength fy;
-	LsmSvgMatrix transform;
-	LsmSvgPatternUnits units;
-	LsmSvgSpreadMethod spread_method;
 	gboolean is_fx_defined;
 	gboolean is_fy_defined;
 } LsmSvgRadialGradientElementAttributes;
 
 static const LsmSvgRadialGradientElementAttributes default_attributes = {
+	.base = {
+		.transform = {1.0, 0.0, 0.0, 1.0, 0.0, 0.0, LSM_SVG_MATRIX_FLAGS_IDENTITY},
+		.units = LSM_SVG_PATTERN_UNITS_OBJECT_BOUNDING_BOX,
+		.spread_method = LSM_SVG_SPREAD_METHOD_PAD,
+	},
 	.cx = {.value_unit = 50.0, .type = LSM_SVG_LENGTH_TYPE_PERCENTAGE},
 	.cy = {.value_unit = 50.0, .type = LSM_SVG_LENGTH_TYPE_PERCENTAGE},
 	.r  = {.value_unit = 50.0, .type = LSM_SVG_LENGTH_TYPE_PERCENTAGE},
 	.fx = {.value_unit =  0.0, .type = LSM_SVG_LENGTH_TYPE_ERROR},
 	.fy = {.value_unit =  0.0, .type = LSM_SVG_LENGTH_TYPE_ERROR},
-	.transform = {1.0, 0.0, 0.0, 1.0, 0.0, 0.0, LSM_SVG_MATRIX_FLAGS_IDENTITY},
-	.units = LSM_SVG_PATTERN_UNITS_OBJECT_BOUNDING_BOX,
-	.spread_method = LSM_SVG_SPREAD_METHOD_PAD,
 	.is_fx_defined = FALSE,
 	.is_fy_defined = FALSE
 };
@@ -63,14 +63,14 @@ lsm_svg_radial_gradient_element_get_node_name (LsmDomNode *node)
 	return "radialGradient";
 }
 
-/* LsmSvgRadialGradientElement implementation */
+/* LsmSvgGradientElement implementation */
 
-static LsmSvgRadialGradientElement *
+LsmSvgGradientElement *
 lsm_svg_radial_gradient_element_inherit_referenced (LsmDomDocument *owner,
-						    LsmSvgRadialGradientElement *gradient,
+						    LsmSvgGradientElement *gradient,
 						    LsmSvgRadialGradientElementAttributes *attributes)
 {
-	LsmSvgRadialGradientElement *referenced_gradient = gradient;
+	LsmSvgGradientElement *referenced_gradient = gradient;
 	LsmDomElement *element;
 
 	if (lsm_attribute_is_defined (&gradient->href)) {
@@ -83,14 +83,14 @@ lsm_svg_radial_gradient_element_inherit_referenced (LsmDomDocument *owner,
 			id++;
 
 		element = lsm_dom_document_get_element_by_id (owner, id);
-		if (LSM_IS_SVG_RADIAL_GRADIENT_ELEMENT (element)) {
+		if (LSM_IS_SVG_GRADIENT_ELEMENT (element)) {
 			lsm_debug ("render",
 				   "[LsmSvgRadialGradientElement::inherit_attributes]"
 				   " Found referenced element '%s'", id);
 
 			referenced_gradient = lsm_svg_radial_gradient_element_inherit_referenced
 				(owner,
-				 LSM_SVG_RADIAL_GRADIENT_ELEMENT (element),
+				 LSM_SVG_GRADIENT_ELEMENT (element),
 				 attributes);
 		} else {
 			lsm_debug ("render",
@@ -100,78 +100,80 @@ lsm_svg_radial_gradient_element_inherit_referenced (LsmDomDocument *owner,
 		}
 	}
 
-	if (lsm_attribute_is_defined (&gradient->cx.base))
-		attributes->cx = gradient->cx.length;
-	if (lsm_attribute_is_defined (&gradient->cy.base))
-		attributes->cy = gradient->cy.length;
-	if (lsm_attribute_is_defined (&gradient->r.base))
-		attributes->r = gradient->r.length;
-	if (lsm_attribute_is_defined (&gradient->fx.base)) {
-		attributes->fx = gradient->fx.length;
-		attributes->is_fx_defined = TRUE;
-	}
-	if (lsm_attribute_is_defined (&gradient->fy.base)) {
-		attributes->fy = gradient->fy.length;
-		attributes->is_fy_defined = TRUE;
+	if (LSM_IS_SVG_RADIAL_GRADIENT_ELEMENT (gradient)) {
+		LsmSvgRadialGradientElement *radial = LSM_SVG_RADIAL_GRADIENT_ELEMENT (gradient);
+
+		if (lsm_attribute_is_defined (&radial->cx.base))
+			attributes->cx = radial->cx.length;
+		if (lsm_attribute_is_defined (&radial->cy.base))
+			attributes->cy = radial->cy.length;
+		if (lsm_attribute_is_defined (&radial->r.base))
+			attributes->r = radial->r.length;
+		if (lsm_attribute_is_defined (&radial->fx.base)) {
+			attributes->fx = radial->fx.length;
+			attributes->is_fx_defined = TRUE;
+		}
+		if (lsm_attribute_is_defined (&radial->fy.base)) {
+			attributes->fy = radial->fy.length;
+			attributes->is_fy_defined = TRUE;
+		}
 	}
+
 	if (lsm_attribute_is_defined (&gradient->transform.base))
-		attributes->transform = gradient->transform.matrix;
+		attributes->base.transform = gradient->transform.matrix;
 	if (lsm_attribute_is_defined (&gradient->units.base))
-		attributes->units = gradient->units.value;
+		attributes->base.units = gradient->units.value;
 	if (lsm_attribute_is_defined (&gradient->spread_method.base))
-		attributes->spread_method = gradient->spread_method.value;
+		attributes->base.spread_method = gradient->spread_method.value;
 
 	return referenced_gradient;
 }
 
-static void
-lsm_svg_radial_gradient_element_render (LsmSvgElement *self, LsmSvgView *view)
+static LsmSvgGradientElement *
+lsm_svg_radial_gradient_element_create_gradient (LsmSvgElement *self,
+						 LsmSvgView *view)
 {
 	LsmSvgRadialGradientElement *gradient = LSM_SVG_RADIAL_GRADIENT_ELEMENT (self);
-	LsmSvgRadialGradientElement *referenced_gradient;
-	LsmDomNode *node;
+	LsmSvgGradientElement *referenced_gradient;
 	gboolean is_object_bounding_box;
 	double cx, cy, fx, fy, r;
 	double gradient_radius;
 	gboolean is_fx_defined;
 	gboolean is_fy_defined;
 
-	if (!gradient->enable_rendering)
-		return;
-
-	gradient->enable_rendering = FALSE;
-
-	if (lsm_attribute_is_defined (&gradient->href)) {
+	if (lsm_attribute_is_defined (&gradient->base.href)) {
 		LsmSvgRadialGradientElementAttributes attributes;
 		LsmDomDocument *owner;
 		attributes = default_attributes;
 
 		owner = lsm_dom_node_get_owner_document (LSM_DOM_NODE (self));
 
-		referenced_gradient = lsm_svg_radial_gradient_element_inherit_referenced (owner, gradient, &attributes);
+		referenced_gradient = lsm_svg_radial_gradient_element_inherit_referenced
+			(owner, LSM_SVG_GRADIENT_ELEMENT (gradient), &attributes);
 
 		gradient->cx.length = attributes.cx;
 		gradient->cy.length = attributes.cy;
 		gradient->r.length = attributes.r;
 		gradient->fx.length = attributes.fx;
 		gradient->fy.length = attributes.fy;
-		gradient->transform.matrix = attributes.transform;
-		gradient->units.value = attributes.units;
-		gradient->spread_method.value = attributes.spread_method;
 
 		is_fx_defined = attributes.is_fx_defined;
 		is_fy_defined = attributes.is_fy_defined;
+
+		gradient->base.transform.matrix = attributes.base.transform;
+		gradient->base.units.value = attributes.base.units;
+		gradient->base.spread_method.value = attributes.base.spread_method;
 	} else {
-		referenced_gradient = gradient;
+		referenced_gradient = LSM_SVG_GRADIENT_ELEMENT (gradient);
 
 		is_fx_defined = lsm_attribute_is_defined (&gradient->fx.base);
 		is_fy_defined = lsm_attribute_is_defined (&gradient->fy.base);
 	}
 
 	if (referenced_gradient == NULL)
-		return;
+		return NULL;
 
-	is_object_bounding_box = (gradient->units.value == LSM_SVG_PATTERN_UNITS_OBJECT_BOUNDING_BOX);
+	is_object_bounding_box = (gradient->base.units.value == LSM_SVG_PATTERN_UNITS_OBJECT_BOUNDING_BOX);
 
 	if (is_object_bounding_box) {
 		LsmBox viewbox = {.x = 0.0, .y = .0, .width = 1.0, .height = 1.0};
@@ -209,30 +211,10 @@ lsm_svg_radial_gradient_element_render (LsmSvgElement *self, LsmSvgView *view)
 
 	lsm_debug ("render", "[LsmSvgRadialElement::render] cx = %g, cy = %g, r = %g, fx = %g, fy = %g",
 		    cx, cy, r, fx, fy);
-	lsm_debug ("render", "[LsmSvgRadialElement::render] transform %g, %g, %g, %g, %g, %g",
-		   gradient->transform.matrix.a,
-		   gradient->transform.matrix.b,
-		   gradient->transform.matrix.c,
-		   gradient->transform.matrix.d,
-		   gradient->transform.matrix.e,
-		   gradient->transform.matrix.f);
 
 	lsm_svg_view_create_radial_gradient (view, cx, cy, r, fx, fy);
 
-	lsm_svg_view_set_gradient_properties (view,
-					      gradient->spread_method.value,
-					      gradient->units.value,
-					      &gradient->transform.matrix);
-
-	for (node = LSM_DOM_NODE (referenced_gradient)->first_child; node != NULL; node = node->next_sibling)
-		if (LSM_IS_SVG_ELEMENT (node))
-		    lsm_svg_element_render (LSM_SVG_ELEMENT (node), view);
-}
-
-static void
-lsm_svg_radial_gradient_element_enable_rendering (LsmSvgElement *element)
-{
-	LSM_SVG_RADIAL_GRADIENT_ELEMENT (element)->enable_rendering = TRUE;
+	return referenced_gradient;
 }
 
 /* LsmSvgRadialGradientElement implementation */
@@ -246,16 +228,11 @@ lsm_svg_radial_gradient_element_new (void)
 static void
 lsm_svg_radial_gradient_element_init (LsmSvgRadialGradientElement *self)
 {
-	self->enable_rendering = FALSE;
-
 	self->cx.length = default_attributes.cx;
 	self->cy.length = default_attributes.cy;
 	self->r.length = default_attributes.r;
 	self->fx.length = default_attributes.fx;
 	self->fy.length = default_attributes.fy;
-	self->transform.matrix = default_attributes.transform;
-	self->units.value = default_attributes.units;
-	self->spread_method.value = default_attributes.spread_method;
 }
 
 static void
@@ -296,29 +273,6 @@ static const LsmAttributeInfos lsm_svg_radial_gradient_element_attribute_infos[]
 		.attribute_offset = offsetof (LsmSvgRadialGradientElement, fy),
 		.trait_class = &lsm_svg_length_trait_class,
 		.trait_default = &default_attributes.fy
-	},
-	{
-		.name = "gradientTransform",
-		.attribute_offset = offsetof (LsmSvgRadialGradientElement, transform),
-		.trait_class = &lsm_svg_matrix_trait_class,
-		.trait_default = &default_attributes.transform
-	},
-	{
-		.name = "gradientUnits",
-		.attribute_offset = offsetof (LsmSvgRadialGradientElement, units),
-		.trait_class = &lsm_svg_pattern_units_trait_class,
-		.trait_default = &default_attributes.units
-	},
-	{
-		.name = "spreadMethod",
-		.attribute_offset = offsetof (LsmSvgRadialGradientElement, spread_method),
-		.trait_class = &lsm_svg_spread_method_trait_class,
-		.trait_default = &default_attributes.spread_method
-	},
-	{
-		.name = "xlink:href",
-		.attribute_offset = offsetof (LsmSvgRadialGradientElement, href),
-		.trait_class = &lsm_null_trait_class
 	}
 };
 
@@ -328,6 +282,7 @@ lsm_svg_radial_gradient_element_class_init (LsmSvgRadialGradientElementClass *s_
 	GObjectClass *object_class = G_OBJECT_CLASS (s_svg_class);
 	LsmDomNodeClass *d_node_class = LSM_DOM_NODE_CLASS (s_svg_class);
 	LsmSvgElementClass *s_element_class = LSM_SVG_ELEMENT_CLASS (s_svg_class);
+	LsmSvgGradientElementClass *s_gradient_class = LSM_SVG_GRADIENT_ELEMENT_CLASS (s_svg_class);
 
 	parent_class = g_type_class_peek_parent (s_svg_class);
 
@@ -337,13 +292,13 @@ lsm_svg_radial_gradient_element_class_init (LsmSvgRadialGradientElementClass *s_
 
 	s_element_class->category = LSM_SVG_ELEMENT_CATEGORY_GRADIENT;
 
-	s_element_class->render = lsm_svg_radial_gradient_element_render;
-	s_element_class->enable_rendering = lsm_svg_radial_gradient_element_enable_rendering;
 	s_element_class->attribute_manager = lsm_attribute_manager_duplicate (s_element_class->attribute_manager);
 
 	lsm_attribute_manager_add_attributes (s_element_class->attribute_manager,
 					      G_N_ELEMENTS (lsm_svg_radial_gradient_element_attribute_infos),
 					      lsm_svg_radial_gradient_element_attribute_infos);
+
+	s_gradient_class->create_gradient = lsm_svg_radial_gradient_element_create_gradient;
 }
 
-G_DEFINE_TYPE (LsmSvgRadialGradientElement, lsm_svg_radial_gradient_element, LSM_TYPE_SVG_ELEMENT)
+G_DEFINE_TYPE (LsmSvgRadialGradientElement, lsm_svg_radial_gradient_element, LSM_TYPE_SVG_GRADIENT_ELEMENT)
diff --git a/src/lsmsvgradialgradientelement.h b/src/lsmsvgradialgradientelement.h
index 85bd60c..450b833 100644
--- a/src/lsmsvgradialgradientelement.h
+++ b/src/lsmsvgradialgradientelement.h
@@ -24,7 +24,7 @@
 #define LSM_SVG_RADIAL_GRADIENT_ELEMENT_H
 
 #include <lsmsvg.h>
-#include <lsmsvgelement.h>
+#include <lsmsvggradientelement.h>
 
 G_BEGIN_DECLS
 
@@ -38,23 +38,17 @@ G_BEGIN_DECLS
 typedef struct _LsmSvgRadialGradientElementClass LsmSvgRadialGradientElementClass;
 
 struct _LsmSvgRadialGradientElement {
-	LsmSvgElement element;
+	LsmSvgGradientElement base;
 
 	LsmSvgLengthAttribute	cx;
 	LsmSvgLengthAttribute	cy;
 	LsmSvgLengthAttribute	r;
 	LsmSvgLengthAttribute	fx;
 	LsmSvgLengthAttribute	fy;
-	LsmSvgTransformAttribute transform;
-	LsmSvgPatternUnitsAttribute units;
-	LsmSvgSpreadMethodAtttribute spread_method;
-	LsmAttribute href;
-
-	gboolean enable_rendering;
 };
 
 struct _LsmSvgRadialGradientElementClass {
-	LsmSvgElementClass  parent_class;
+	LsmSvgGradientElementClass  parent_class;
 };
 
 GType lsm_svg_radial_gradient_element_get_type (void);



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