summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/mupdf/fitz/math.h14
-rw-r--r--source/fitz/draw-path.c3
-rw-r--r--source/fitz/geometry.c19
3 files changed, 35 insertions, 1 deletions
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
@@ -400,6 +400,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.
Rectilinear means that no shearing is present and that any
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
@@ -214,6 +214,25 @@ fz_invert_matrix(fz_matrix *dst, const fz_matrix *src)
}
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)
{
return (fabsf(m->b) < FLT_EPSILON && fabsf(m->c) < FLT_EPSILON) ||