[lasem] svg: add circular reference checks.
- From: Emmanuel Pacaud <emmanuel src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [lasem] svg: add circular reference checks.
- Date: Wed, 4 May 2011 07:47:31 +0000 (UTC)
commit 78722595f92ed8e122a9f780b463c27ddbeec8d9
Author: Emmanuel Pacaud <emmanuel gnome org>
Date: Wed May 4 09:46:03 2011 +0200
svg: add circular reference checks.
It still o implemented for <use> elements.
The code in radial, linear gradients and pattern must be factorized.
src/lsmsvglineargradientelement.c | 52 +++++++++++++++++++++++++-----------
src/lsmsvgpatternelement.c | 50 +++++++++++++++++++++++++----------
src/lsmsvgradialgradientelement.c | 52 +++++++++++++++++++++++++-----------
src/lsmsvgview.c | 43 +++++++++++++++++++++++++++---
4 files changed, 146 insertions(+), 51 deletions(-)
---
diff --git a/src/lsmsvglineargradientelement.c b/src/lsmsvglineargradientelement.c
index 8478f08..a6f9c9a 100644
--- a/src/lsmsvglineargradientelement.c
+++ b/src/lsmsvglineargradientelement.c
@@ -61,13 +61,18 @@ lsm_svg_linear_gradient_element_get_node_name (LsmDomNode *node)
static LsmSvgGradientElement *
lsm_svg_linear_gradient_element_inherit_referenced (LsmDomDocument *owner,
LsmSvgGradientElement *gradient,
- LsmSvgLinearGradientElementAttributes *attributes)
+ LsmSvgLinearGradientElementAttributes *attributes,
+ GSList **elements)
{
LsmSvgGradientElement *referenced_gradient = gradient;
LsmDomElement *element;
+ *elements = g_slist_prepend (*elements, gradient);
+
if (lsm_attribute_is_defined (&gradient->href)) {
char *id;
+ GSList *iter;
+ gboolean circular_reference_found = FALSE;
id = gradient->href.value;
if (id == NULL)
@@ -76,21 +81,33 @@ lsm_svg_linear_gradient_element_inherit_referenced (LsmDomDocument *owner,
id++;
element = lsm_dom_document_get_element_by_id (owner, id);
- 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_GRADIENT_ELEMENT (element),
- attributes);
- } else {
- lsm_debug ("render",
- "[LsmSvgLinearGradientElement::inherit_attributes]"
- " Referenced element '%s' not found", id);
+
+ for (iter = *elements; iter != NULL; iter = iter->next)
+ if (iter->data == element) {
+ lsm_debug ("render", "[LsmSvgLinearGradientElement::inherit_attributes] "
+ "Circular reference (id = %s)", id);
+ circular_reference_found = TRUE;
+ }
+
+ if (!circular_reference_found) {
+ 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_GRADIENT_ELEMENT (element),
+ attributes, elements);
+
+ } else {
+ lsm_debug ("render",
+ "[LsmSvgLinearGradientElement::inherit_attributes]"
+ " Referenced element '%s' not found", id);
+ referenced_gradient = NULL;
+ }
+ } else
referenced_gradient = NULL;
- }
}
if (LSM_IS_SVG_LINEAR_GRADIENT_ELEMENT (gradient)) {
@@ -128,11 +145,14 @@ lsm_svg_linear_gradient_element_create_gradient (LsmSvgElement *self,
LsmSvgLinearGradientElementAttributes attributes;
LsmDomDocument *owner;
attributes = default_attributes;
+ GSList *elements = NULL;
owner = lsm_dom_node_get_owner_document (LSM_DOM_NODE (self));
referenced_gradient = lsm_svg_linear_gradient_element_inherit_referenced
- (owner, LSM_SVG_GRADIENT_ELEMENT (gradient), &attributes);
+ (owner, LSM_SVG_GRADIENT_ELEMENT (gradient), &attributes, &elements);
+
+ g_slist_free (elements);
gradient->x1.length = attributes.x1;
gradient->y1.length = attributes.y1;
diff --git a/src/lsmsvgpatternelement.c b/src/lsmsvgpatternelement.c
index a10d737..4cba96d 100644
--- a/src/lsmsvgpatternelement.c
+++ b/src/lsmsvgpatternelement.c
@@ -69,13 +69,18 @@ _pattern_element_get_node_name (LsmDomNode *node)
static LsmSvgPatternElement *
lsm_svg_pattern_element_inherit_referenced (LsmDomDocument *owner,
LsmSvgPatternElement *pattern,
- LsmSvgPatternElementAttributes *attributes)
+ LsmSvgPatternElementAttributes *attributes,
+ GSList **elements)
{
LsmSvgPatternElement *referenced_pattern = pattern;
LsmDomElement *element;
+ *elements = g_slist_prepend (*elements, pattern);
+
if (lsm_attribute_is_defined (&pattern->href)) {
char *id;
+ GSList *iter;
+ gboolean circular_reference_found = FALSE;
id = pattern->href.value;
if (id == NULL)
@@ -84,19 +89,32 @@ lsm_svg_pattern_element_inherit_referenced (LsmDomDocument *owner,
id++;
element = lsm_dom_document_get_element_by_id (owner, id);
- if (LSM_IS_SVG_PATTERN_ELEMENT (element)) {
- lsm_debug ("render",
- "[LsmSvgPatternElement::inherit_attributes] Found referenced element '%s'", id);
-
- referenced_pattern = lsm_svg_pattern_element_inherit_referenced
- (owner,
- LSM_SVG_PATTERN_ELEMENT (element),
- attributes);
- } else {
- lsm_debug ("render",
- "[LsmSvgPatternElement::inherit_attributes] Referenced element '%s' not found", id);
+
+ for (iter = *elements; iter != NULL; iter = iter->next)
+ if (iter->data == element) {
+ lsm_debug ("render", "[LsmSvgPatternElement::inherit_attributes] "
+ "Circular reference (id = %s)", id);
+ circular_reference_found = TRUE;
+ }
+
+ if (!circular_reference_found) {
+ if (LSM_IS_SVG_PATTERN_ELEMENT (element), elements) {
+ lsm_debug ("render",
+ "[LsmSvgPatternElement::inherit_attributes] "
+ "Found referenced element '%s'", id);
+
+ referenced_pattern = lsm_svg_pattern_element_inherit_referenced
+ (owner,
+ LSM_SVG_PATTERN_ELEMENT (element),
+ attributes, elements);
+ } else {
+ lsm_debug ("render",
+ "[LsmSvgPatternElement::inherit_attributes] "
+ "Referenced element '%s' not found", id);
+ referenced_pattern = NULL;
+ }
+ } else
referenced_pattern = NULL;
- }
}
if (lsm_attribute_is_defined (&pattern->x.base))
@@ -144,10 +162,14 @@ lsm_svg_pattern_element_render (LsmSvgElement *self, LsmSvgView *view)
LsmSvgPatternElementAttributes attributes;
LsmDomDocument *owner;
attributes = default_attributes;
+ GSList *elements = NULL;
owner = lsm_dom_node_get_owner_document (LSM_DOM_NODE (self));
- referenced_pattern = lsm_svg_pattern_element_inherit_referenced (owner, pattern, &attributes);
+ referenced_pattern = lsm_svg_pattern_element_inherit_referenced (owner, pattern,
+ &attributes, &elements);
+
+ g_slist_free (elements);
pattern->x.length = attributes.x;
pattern->y.length = attributes.y;
diff --git a/src/lsmsvgradialgradientelement.c b/src/lsmsvgradialgradientelement.c
index 5b8f3a1..b15c537 100644
--- a/src/lsmsvgradialgradientelement.c
+++ b/src/lsmsvgradialgradientelement.c
@@ -68,13 +68,18 @@ lsm_svg_radial_gradient_element_get_node_name (LsmDomNode *node)
LsmSvgGradientElement *
lsm_svg_radial_gradient_element_inherit_referenced (LsmDomDocument *owner,
LsmSvgGradientElement *gradient,
- LsmSvgRadialGradientElementAttributes *attributes)
+ LsmSvgRadialGradientElementAttributes *attributes,
+ GSList **elements)
{
LsmSvgGradientElement *referenced_gradient = gradient;
LsmDomElement *element;
+ *elements = g_slist_prepend (*elements, gradient);
+
if (lsm_attribute_is_defined (&gradient->href)) {
char *id;
+ GSList *iter;
+ gboolean circular_reference_found = FALSE;
id = gradient->href.value;
if (id == NULL)
@@ -83,21 +88,33 @@ lsm_svg_radial_gradient_element_inherit_referenced (LsmDomDocument *owner,
id++;
element = lsm_dom_document_get_element_by_id (owner, id);
- 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_GRADIENT_ELEMENT (element),
- attributes);
- } else {
- lsm_debug ("render",
- "[LsmSvgRadialGradientElement::inherit_attributes]"
- " Referenced element '%s' not found", id);
+
+ for (iter = *elements; iter != NULL; iter = iter->next)
+ if (iter->data == element) {
+ lsm_debug ("render", "[LsmSvgRadialGradientElement::inherit_attributes] "
+ "Circular reference (id = %s)", id);
+ circular_reference_found = TRUE;
+ }
+
+ if (!circular_reference_found) {
+ 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_GRADIENT_ELEMENT (element),
+ attributes, elements);
+ } else {
+ lsm_debug ("render",
+ "[LsmSvgRadialGradientElement::inherit_attributes]"
+ " Referenced element '%s' not found", id);
+ referenced_gradient = NULL;
+ }
+ } else
referenced_gradient = NULL;
- }
+
}
if (LSM_IS_SVG_RADIAL_GRADIENT_ELEMENT (gradient)) {
@@ -145,11 +162,14 @@ lsm_svg_radial_gradient_element_create_gradient (LsmSvgElement *self,
LsmSvgRadialGradientElementAttributes attributes;
LsmDomDocument *owner;
attributes = default_attributes;
+ GSList *elements = NULL;
owner = lsm_dom_node_get_owner_document (LSM_DOM_NODE (self));
referenced_gradient = lsm_svg_radial_gradient_element_inherit_referenced
- (owner, LSM_SVG_GRADIENT_ELEMENT (gradient), &attributes);
+ (owner, LSM_SVG_GRADIENT_ELEMENT (gradient), &attributes, &elements);
+
+ g_slist_free (elements);
gradient->cx.length = attributes.cx;
gradient->cy.length = attributes.cy;
diff --git a/src/lsmsvgview.c b/src/lsmsvgview.c
index d821a6b..f3906af 100644
--- a/src/lsmsvgview.c
+++ b/src/lsmsvgview.c
@@ -40,6 +40,8 @@
#include <math.h>
#include <string.h>
+static gboolean lsm_svg_view_circular_reference_check (LsmSvgView *view, LsmSvgElement *element);
+
static GObjectClass *parent_class;
typedef struct {
@@ -761,9 +763,10 @@ _paint_url (LsmSvgView *view,
LsmBox extents;
element = lsm_svg_document_get_element_by_url (LSM_SVG_DOCUMENT (view->dom_view.document), url);
- if (!LSM_IS_SVG_RADIAL_GRADIENT_ELEMENT (element) &&
- !LSM_IS_SVG_LINEAR_GRADIENT_ELEMENT (element) &&
- !LSM_IS_SVG_PATTERN_ELEMENT (element))
+ if ((!LSM_IS_SVG_RADIAL_GRADIENT_ELEMENT (element) &&
+ !LSM_IS_SVG_LINEAR_GRADIENT_ELEMENT (element) &&
+ !LSM_IS_SVG_PATTERN_ELEMENT (element)) ||
+ lsm_svg_view_circular_reference_check (view, element))
return;
lsm_debug ("render", "[LsmSvgView::_paint_url] Paint using '%s'", url);
@@ -890,6 +893,15 @@ paint_markers (LsmSvgView *view)
stroke_width = lsm_svg_view_normalize_length (view, &view->style->stroke_width->length,
LSM_SVG_LENGTH_DIRECTION_DIAGONAL);
+ if (marker != NULL && lsm_svg_view_circular_reference_check (view, marker))
+ return;
+ if (marker_start != NULL && lsm_svg_view_circular_reference_check (view, marker_start))
+ return;
+ if (marker_mid != NULL && lsm_svg_view_circular_reference_check (view, marker_mid))
+ return;
+ if (marker_end != NULL && lsm_svg_view_circular_reference_check (view, marker_end))
+ return;
+
if (marker_start == NULL)
marker_start = marker;
if (marker_mid == NULL)
@@ -1737,7 +1749,8 @@ lsm_svg_view_push_clip (LsmSvgView *view)
view->clip_extents.height = extents.y2 - extents.y1;
element = lsm_svg_document_get_element_by_url (LSM_SVG_DOCUMENT (view->dom_view.document), url);
- if (LSM_IS_SVG_CLIP_PATH_ELEMENT (element)) {
+ if (LSM_IS_SVG_CLIP_PATH_ELEMENT (element) &&
+ !lsm_svg_view_circular_reference_check (view, element)) {
view->is_clipping = TRUE;
lsm_svg_element_force_render (LSM_SVG_ELEMENT (element), view);
cairo_clip (view->dom_view.cairo);
@@ -1771,7 +1784,8 @@ lsm_svg_view_pop_mask (LsmSvgView *view)
mask_element = lsm_svg_document_get_element_by_url (LSM_SVG_DOCUMENT (view->dom_view.document),
view->style->mask->value);
- if (LSM_IS_SVG_MASK_ELEMENT (mask_element)) {
+ if (LSM_IS_SVG_MASK_ELEMENT (mask_element) &&
+ !lsm_svg_view_circular_reference_check (view, mask_element)) {
LsmExtents extents;
LsmBox mask_extents;
cairo_t *cairo;
@@ -1876,6 +1890,8 @@ lsm_svg_view_pop_filter (LsmSvgView *view)
filter_element = lsm_svg_document_get_element_by_url (LSM_SVG_DOCUMENT (view->dom_view.document),
view->style->filter->value);
+TODO: lsm_svg_view_circular_reference_check
+
cairo = view->pattern_data->old_cairo;
view->filter_surfaces = NULL;
@@ -1936,6 +1952,23 @@ lsm_svg_view_pop_element (LsmSvgView *view)
view->element_stack = g_slist_delete_link (view->element_stack, view->element_stack);
}
+static gboolean
+lsm_svg_view_circular_reference_check (LsmSvgView *view, LsmSvgElement *element)
+{
+ GSList *iter;
+
+ for (iter = view->element_stack; iter != NULL; iter = iter->next)
+ if (iter->data == element) {
+ lsm_debug ("render", "[LsmSvgView::circular_reference_check] "
+ "Circular reference to %s (id = %s)",
+ lsm_dom_element_get_tag_name (LSM_DOM_ELEMENT (element)),
+ lsm_dom_element_get_attribute (LSM_DOM_ELEMENT (element), "id"));
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
void
lsm_svg_view_push_style (LsmSvgView *view, const LsmSvgStyle *style)
{
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]