diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c index b1fc6b34d..2867243f4 100644 --- a/src/cairo-gstate.c +++ b/src/cairo-gstate.c @@ -1289,6 +1289,9 @@ cairo_status_t _cairo_gstate_set_font_matrix (cairo_gstate_t *gstate, const cairo_matrix_t *matrix) { + if (! _cairo_matrix_is_invertible (matrix)) + return _cairo_error (CAIRO_STATUS_INVALID_MATRIX); + _cairo_gstate_unset_scaled_font (gstate); gstate->font_matrix = *matrix; diff --git a/src/cairo-matrix.c b/src/cairo-matrix.c index cf31c5d4d..00c2d4866 100644 --- a/src/cairo-matrix.c +++ b/src/cairo-matrix.c @@ -486,6 +486,16 @@ cairo_matrix_invert (cairo_matrix_t *matrix) } slim_hidden_def(cairo_matrix_invert); +cairo_bool_t +_cairo_matrix_is_invertible (const cairo_matrix_t *matrix) +{ + double det; + + _cairo_matrix_compute_determinant (matrix, &det); + + return det != 0. && det * det > 0.; +} + void _cairo_matrix_compute_determinant (const cairo_matrix_t *matrix, double *det) diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c index 2da991204..e90591746 100644 --- a/src/cairo-scaled-font.c +++ b/src/cairo-scaled-font.c @@ -603,6 +603,9 @@ cairo_scaled_font_create (cairo_font_face_t *font_face, if (cairo_font_options_status ((cairo_font_options_t *) options)) return (cairo_scaled_font_t *)&_cairo_scaled_font_nil; + if (! _cairo_matrix_is_invertible (font_matrix)) + return (cairo_scaled_font_t *)&_cairo_scaled_font_nil; + font_map = _cairo_scaled_font_map_lock (); if (font_map == NULL) return (cairo_scaled_font_t *)&_cairo_scaled_font_nil; diff --git a/src/cairoint.h b/src/cairoint.h index 80915d770..c5cdf1a5d 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -2104,6 +2104,9 @@ _cairo_matrix_transform_bounding_box (const cairo_matrix_t *matrix, double *x2, double *y2, cairo_bool_t *is_tight); +cairo_private cairo_bool_t +_cairo_matrix_is_invertible (const cairo_matrix_t *matrix); + cairo_private void _cairo_matrix_compute_determinant (const cairo_matrix_t *matrix, double *det);