From a8aec7875aaf6c8d8d4ed37ce74705988b73e9c1 Mon Sep 17 00:00:00 2001 From: Robin Watts Date: Mon, 30 Sep 2013 16:45:15 +0100 Subject: Bug 694526: Spot non-invertable matrices and bale before stroking The bug fix added in the previous commit fails to work in this case (hang-9527.pdf) because the matrix is not invertible and hence the clipping rectangle ends up infinite. Spot this case here and return early. --- include/mupdf/fitz/math.h | 14 ++++++++++++++ source/fitz/draw-path.c | 3 ++- source/fitz/geometry.c | 19 +++++++++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/include/mupdf/fitz/math.h b/include/mupdf/fitz/math.h index 1d542964..387f73a4 100644 --- a/include/mupdf/fitz/math.h +++ b/include/mupdf/fitz/math.h @@ -399,6 +399,20 @@ fz_matrix *fz_pre_translate(fz_matrix *m, float tx, float ty); */ fz_matrix *fz_invert_matrix(fz_matrix *inverse, const fz_matrix *matrix); +/* + fz_try_invert_matrix: Attempt to create an inverse matrix. + + inverse: Place to store inverse matrix. + + matrix: Matrix to invert. A degenerate matrix, where the + determinant is equal to zero, can not be inverted. + + Returns 1 if matrix is degenerate (singular), or 0 otherwise. + + Does not throw exceptions. +*/ + int fz_try_invert_matrix(fz_matrix *inverse, const fz_matrix *matrix); + /* fz_is_rectilinear: Check if a transformation is rectilinear. diff --git a/source/fitz/draw-path.c b/source/fitz/draw-path.c index 6fa6191d..b33ea8b4 100644 --- a/source/fitz/draw-path.c +++ b/source/fitz/draw-path.c @@ -971,7 +971,8 @@ fz_flatten_dash_path(fz_gel *gel, fz_path *path, const fz_stroke_state *stroke, for (i = 0; i < stroke->dash_len; i++) phase_len += stroke->dash_list[i]; fz_gel_scissor(gel, &s.rect); - fz_invert_matrix(&inv, ctm); + if (fz_try_invert_matrix(&inv, ctm)) + return; fz_transform_rect(&s.rect, &inv); s.rect.x0 -= linewidth; s.rect.x1 += linewidth; diff --git a/source/fitz/geometry.c b/source/fitz/geometry.c index 81450246..c7c3d198 100644 --- a/source/fitz/geometry.c +++ b/source/fitz/geometry.c @@ -213,6 +213,25 @@ fz_invert_matrix(fz_matrix *dst, const fz_matrix *src) return dst; } +int +fz_try_invert_matrix(fz_matrix *dst, const fz_matrix *src) +{ + /* Be careful to cope with dst == src */ + float a = src->a; + float det = a * src->d - src->b * src->c; + if (det >= -FLT_EPSILON && det <= FLT_EPSILON) + return 1; + det = 1 / det; + dst->a = src->d * det; + dst->b = -src->b * det; + dst->c = -src->c * det; + dst->d = a * det; + a = -src->e * dst->a - src->f * dst->c; + dst->f = -src->e * dst->b - src->f * dst->d; + dst->e = a; + return 0; +} + int fz_is_rectilinear(const fz_matrix *m) { -- cgit v1.2.3