[lasem] svg: avoid cairo errors when matrix is not invertible.



commit 3950427b7c4442b644260111864f7ad72a52e840
Author: Emmanuel Pacaud <emmanuel gnome org>
Date:   Tue Jun 12 16:01:45 2012 +0200

    svg: avoid cairo errors when matrix is not invertible.

 src/lsmsvgelement.c        |   32 ++++++++++++++++++++------------
 src/lsmsvgmarkerelement.c  |   14 +++++++++-----
 src/lsmsvgmaskelement.c    |    8 ++++++--
 src/lsmsvgpatternelement.c |   23 ++++++++++++++---------
 src/lsmsvguseelement.c     |   15 ++++++++-------
 src/lsmsvgview.c           |   17 +++++++++++++++--
 src/lsmsvgview.h           |    2 +-
 7 files changed, 73 insertions(+), 38 deletions(-)
---
diff --git a/src/lsmsvgelement.c b/src/lsmsvgelement.c
index dc0c0f7..d6ba4c6 100644
--- a/src/lsmsvgelement.c
+++ b/src/lsmsvgelement.c
@@ -159,6 +159,7 @@ lsm_svg_element_render (LsmSvgElement *element, LsmSvgView *view)
 	const LsmSvgStyle *parent_style;
 	LsmSvgStyle *style;
 	gboolean is_identity_transform;
+	gboolean is_matrix_invertible = TRUE;
 
 	g_return_if_fail (LSM_IS_SVG_ELEMENT (element));
 
@@ -172,23 +173,30 @@ lsm_svg_element_render (LsmSvgElement *element, LsmSvgView *view)
 	style = lsm_svg_style_new_inherited (parent_style, &element->property_bag);
 
 	if (!is_identity_transform)
-		lsm_svg_view_push_matrix (view, &element->transform.matrix);
+		is_matrix_invertible = lsm_svg_view_push_matrix (view, &element->transform.matrix);
 
-	lsm_svg_view_push_element (view, element);
-	lsm_svg_view_push_style (view, style);
+	if (!is_matrix_invertible & !is_matrix_invertible)
+		lsm_debug_render ("[LsmSvgElement::render] Not invertibale matrix for %s (%s)",
+				  lsm_dom_node_get_node_name (LSM_DOM_NODE (element)),
+				  element->id.value != NULL ? element->id.value : "no id");
 
+	if (is_identity_transform || is_matrix_invertible) {
+		lsm_svg_view_push_element (view, element);
+		lsm_svg_view_push_style (view, style);
 
-	if (style->visibility->value == LSM_SVG_VISIBILITY_VISIBLE &&
-	    style->display->value != LSM_SVG_DISPLAY_NONE) {
-		lsm_debug_render ("[LsmSvgElement::render] Render %s (%s)",
-			   lsm_dom_node_get_node_name (LSM_DOM_NODE (element)),
-			   element->id.value != NULL ? element->id.value : "no id");
 
-		element_class->render (element, view);
-	}
+		if (style->visibility->value == LSM_SVG_VISIBILITY_VISIBLE &&
+		    style->display->value != LSM_SVG_DISPLAY_NONE) {
+			lsm_debug_render ("[LsmSvgElement::render] Render %s (%s)",
+					  lsm_dom_node_get_node_name (LSM_DOM_NODE (element)),
+					  element->id.value != NULL ? element->id.value : "no id");
+
+			element_class->render (element, view);
+		}
 
-	lsm_svg_view_pop_style (view);
-	lsm_svg_view_pop_element (view);
+		lsm_svg_view_pop_style (view);
+		lsm_svg_view_pop_element (view);
+	}
 
 	if (!is_identity_transform)
 		lsm_svg_view_pop_matrix (view);
diff --git a/src/lsmsvgmarkerelement.c b/src/lsmsvgmarkerelement.c
index 783536d..3711f61 100644
--- a/src/lsmsvgmarkerelement.c
+++ b/src/lsmsvgmarkerelement.c
@@ -96,17 +96,21 @@ _marker_element_render (LsmSvgElement *self, LsmSvgView *view)
 		lsm_debug_render ("[LsmSvgMarkerElement::render] auto angle = %g", marker->vertex_angle);
 	}
 	lsm_svg_matrix_translate (&matrix, -ref_x, -ref_y);
-	lsm_svg_view_push_matrix (view, &matrix);
 
-	lsm_svg_view_push_viewport (view, &viewport, &marker->viewbox.value,
-				    &marker->preserve_aspect_ratio.value);
+	if (lsm_svg_view_push_matrix (view, &matrix)) {
 
-	LSM_SVG_ELEMENT_CLASS (parent_class)->render (self, view);
+		lsm_svg_view_push_viewport (view, &viewport, &marker->viewbox.value,
+					    &marker->preserve_aspect_ratio.value);
 
-	lsm_svg_view_pop_viewport (view);
+		LSM_SVG_ELEMENT_CLASS (parent_class)->render (self, view);
+
+		lsm_svg_view_pop_viewport (view);
+	} else
+		lsm_debug_render ("[LsmSvgMarkerElement::render] Not invertible matrix");
 
 	lsm_svg_view_pop_matrix (view);
 
+
 	lsm_svg_view_pop_style (view);
 	lsm_svg_style_unref (style);
 }
diff --git a/src/lsmsvgmaskelement.c b/src/lsmsvgmaskelement.c
index 8e1b325..56a77e0 100644
--- a/src/lsmsvgmaskelement.c
+++ b/src/lsmsvgmaskelement.c
@@ -46,6 +46,7 @@ lsm_svg_mask_element_render (LsmSvgElement *self, LsmSvgView *view)
 	LsmBox viewport;
 	const LsmBox *mask_extents;
 	LsmSvgStyle *style;
+	gboolean is_matrix_invertible = TRUE;
 
 	if (!mask->enable_rendering) {
 		lsm_debug_render ("[LsmSvgMaskElement::render] Direct rendering not allowed");
@@ -114,7 +115,7 @@ lsm_svg_mask_element_render (LsmSvgElement *self, LsmSvgView *view)
 		lsm_svg_matrix_init_translate (&matrix, +mask_extents->x, +mask_extents->y);
 		lsm_svg_matrix_scale (&matrix, mask_extents->width, mask_extents->height);
 		lsm_svg_view_push_viewbox (view, &viewbox);
-		lsm_svg_view_push_matrix (view, &matrix);
+		is_matrix_invertible = lsm_svg_view_push_matrix (view, &matrix);
 
 		lsm_debug_render ("[LsmSvgMaskElement::render] object_bounding_box"
 			   " x_scale = %g, y_scale = %g, x_offset = %g, y_offset = %g",
@@ -122,7 +123,10 @@ lsm_svg_mask_element_render (LsmSvgElement *self, LsmSvgView *view)
 			   mask_extents->x, mask_extents->y);
 	}
 
-	LSM_SVG_ELEMENT_CLASS (parent_class)->render (self, view);
+	if (is_matrix_invertible)
+		LSM_SVG_ELEMENT_CLASS (parent_class)->render (self, view);
+	else
+		lsm_debug_render ("[LsmSvgMaskElement::render] Not invertibale matrix");
 
 	if (is_object_bounding_box) {
 		lsm_svg_view_pop_matrix (view);
diff --git a/src/lsmsvgpatternelement.c b/src/lsmsvgpatternelement.c
index 2a4585e..ee289c2 100644
--- a/src/lsmsvgpatternelement.c
+++ b/src/lsmsvgpatternelement.c
@@ -149,6 +149,7 @@ lsm_svg_pattern_element_render (LsmSvgElement *self, LsmSvgView *view)
 	LsmBox image_box;
 	const LsmBox *pattern_extents;
 	LsmSvgStyle *style;
+	gboolean is_matrix_invertible = TRUE;
 
 	if (!pattern->enable_rendering) {
 		lsm_debug_render ("[LsmSvgPatternElement::render] Direct rendering not allowed");
@@ -247,7 +248,7 @@ lsm_svg_pattern_element_render (LsmSvgElement *self, LsmSvgView *view)
 		lsm_svg_matrix_init_scale (&matrix, pattern_extents->width, pattern_extents->height);
 		lsm_svg_matrix_translate (&matrix, -pattern_extents->x, -pattern_extents->y);
 		lsm_svg_view_push_viewbox (view, &viewbox);
-		lsm_svg_view_push_matrix (view, &matrix);
+		is_matrix_invertible = lsm_svg_view_push_matrix (view, &matrix);
 
 		lsm_debug_render ("[LsmSvgPatternElement::render] object_bounding_box"
 			   " x_scale = %g, y_scale = %g, x_offset = %g, y_offset = %g",
@@ -255,18 +256,22 @@ lsm_svg_pattern_element_render (LsmSvgElement *self, LsmSvgView *view)
 			   pattern_extents->x,     pattern_extents->y);
 	}
 
-	is_viewbox_defined = lsm_attribute_is_defined (&pattern->viewbox.base);
+	if (is_matrix_invertible) {
 
-	if (!(is_viewbox_defined) ||
-	    (is_viewbox_defined && pattern->viewbox.value.width > 0.0 && pattern->viewbox.value.height > 0.0)) {
+		is_viewbox_defined = lsm_attribute_is_defined (&pattern->viewbox.base);
 
-		lsm_svg_view_push_viewport (view, &viewport, is_viewbox_defined ? &pattern->viewbox.value : NULL,
-					    &pattern->preserve_aspect_ratio.value);
+		if (!(is_viewbox_defined) ||
+		    (is_viewbox_defined && pattern->viewbox.value.width > 0.0 && pattern->viewbox.value.height > 0.0)) {
 
-		LSM_SVG_ELEMENT_CLASS (parent_class)->render (LSM_SVG_ELEMENT (referenced_pattern), view);
+			lsm_svg_view_push_viewport (view, &viewport, is_viewbox_defined ? &pattern->viewbox.value : NULL,
+						    &pattern->preserve_aspect_ratio.value);
 
-		lsm_svg_view_pop_viewport (view);
-	}
+			LSM_SVG_ELEMENT_CLASS (parent_class)->render (LSM_SVG_ELEMENT (referenced_pattern), view);
+
+			lsm_svg_view_pop_viewport (view);
+		}
+	} else
+		lsm_debug_render ("[LsmSvgPatternElement::render] Not invertiblae matrix");
 
 	if (is_object_bounding_box) {
 		lsm_svg_view_pop_matrix (view);
diff --git a/src/lsmsvguseelement.c b/src/lsmsvguseelement.c
index c150777..0689771 100644
--- a/src/lsmsvguseelement.c
+++ b/src/lsmsvguseelement.c
@@ -101,9 +101,11 @@ lsm_svg_use_element_render (LsmSvgElement *self, LsmSvgView *view)
 					   LSM_SVG_LENGTH_DIRECTION_VERTICAL);
 
 	lsm_svg_matrix_init_translate (&matrix, x, y);
-	lsm_svg_view_push_matrix (view, &matrix);
 
-	lsm_svg_element_render (LSM_SVG_ELEMENT (element), view);
+	if (lsm_svg_view_push_matrix (view, &matrix))
+		lsm_svg_element_render (LSM_SVG_ELEMENT (element), view);
+	else
+		lsm_debug_render ("[LsmSvgUseElement::render] Not invertibale matrix");
 
 	lsm_svg_view_pop_matrix (view);
 
@@ -151,12 +153,11 @@ lsm_svg_use_element_get_extents (LsmSvgElement *self, LsmSvgView *view, LsmExten
 						       &extents->x2, &extents->y2);
 
 	lsm_svg_matrix_init_translate (&matrix, x, y);
-	lsm_svg_view_push_matrix (view, &matrix);
-
-	lsm_svg_matrix_transform_bounding_box (&matrix,
-					       &extents->x1, &extents->y1,
-					       &extents->x2, &extents->y2);
 
+	if (lsm_svg_view_push_matrix (view, &matrix))
+		lsm_svg_matrix_transform_bounding_box (&matrix,
+						       &extents->x1, &extents->y1,
+						       &extents->x2, &extents->y2);
 	lsm_svg_view_pop_matrix (view);
 
 	use_element->flags &= ~LSM_SVG_USE_ELEMENT_FLAGS_IN_USE_FOR_GET_EXTENTS;
diff --git a/src/lsmsvgview.c b/src/lsmsvgview.c
index 431d0da..95a10a8 100644
--- a/src/lsmsvgview.c
+++ b/src/lsmsvgview.c
@@ -1656,13 +1656,15 @@ lsm_svg_view_viewbox_to_viewport (LsmSvgView *view, const LsmBox *viewport, cons
 		*y = *y * y_scale + y_offset;
 }
 
-void
+gboolean
 lsm_svg_view_push_matrix (LsmSvgView *view, const LsmSvgMatrix *matrix)
 {
 	cairo_matrix_t cr_matrix;
+	cairo_matrix_t cr_inv_matrix;
 	cairo_matrix_t *ctm;
+	cairo_status_t status;
 
-	g_return_if_fail (LSM_IS_SVG_VIEW (view));
+	g_return_val_if_fail (LSM_IS_SVG_VIEW (view), FALSE);
 
 	ctm = g_new (cairo_matrix_t, 1);
 	cairo_get_matrix (view->dom_view.cairo, ctm);
@@ -1673,6 +1675,12 @@ lsm_svg_view_push_matrix (LsmSvgView *view, const LsmSvgMatrix *matrix)
 		   matrix->a, matrix->b, matrix->c, matrix->d, matrix->e, matrix->f);
 
 	cairo_matrix_init (&cr_matrix, matrix->a, matrix->b, matrix->c, matrix->d, matrix->e, matrix->f);
+	cr_inv_matrix = cr_matrix;
+	status = cairo_matrix_invert (&cr_inv_matrix) == CAIRO_STATUS_SUCCESS;
+
+	if (status == CAIRO_STATUS_SUCCESS)
+       		return FALSE;
+
 	cairo_transform (view->dom_view.cairo, &cr_matrix);
 
 	{
@@ -1683,6 +1691,8 @@ lsm_svg_view_push_matrix (LsmSvgView *view, const LsmSvgMatrix *matrix)
 			   current_ctm.xx, current_ctm.xy, current_ctm.yx, current_ctm.yy,
 			   current_ctm.x0, current_ctm.y0);
 	}
+
+	return TRUE;
 }
 
 void
@@ -2118,6 +2128,9 @@ lsm_svg_view_render (LsmDomView *view)
 		g_slist_free (svg_view->style_stack);
 		svg_view->style_stack = NULL;
 	}
+
+	if (cairo_status (view->cairo) != CAIRO_STATUS_SUCCESS)
+		printf ("Cairo error ! %s\n", cairo_status_to_string (cairo_status (view->cairo)));
 }
 
 LsmSvgView *
diff --git a/src/lsmsvgview.h b/src/lsmsvgview.h
index a44464f..0bb7140 100644
--- a/src/lsmsvgview.h
+++ b/src/lsmsvgview.h
@@ -130,7 +130,7 @@ void 		lsm_svg_view_viewbox_to_viewport 	(LsmSvgView *view,
 							 const LsmBox *viewport, const LsmBox *viewbox,
 							 const LsmSvgPreserveAspectRatio *aspect_ratio,
 							 double *x, double *y);
-void 		lsm_svg_view_push_matrix		(LsmSvgView *view, const LsmSvgMatrix *matrix);
+gboolean	lsm_svg_view_push_matrix		(LsmSvgView *view, const LsmSvgMatrix *matrix);
 void 		lsm_svg_view_pop_matrix			(LsmSvgView *view);
 
 void		lsm_svg_view_push_element		(LsmSvgView *view, const LsmSvgElement *element);



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