[lasem] svg: avoid cairo errors when matrix is not invertible.
- From: Emmanuel Pacaud <emmanuel src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [lasem] svg: avoid cairo errors when matrix is not invertible.
- Date: Tue, 12 Jun 2012 14:02:27 +0000 (UTC)
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]