[cairo-gstate] Check that the matrix remains invertible.

Ensure that the ctm remains invertible after multiplying the user
supplied matrices. Although the arguments are checked so that they are
valid per se, we double check that the result after multiplication is
still a valid invertible matrix. This should catch pathological cases
where the user concatenates a long series of matrix operations, which
either exceed our numerical limits or become degenerate through rounding
errors.
This commit is contained in:
Chris Wilson 2008-01-13 11:10:28 +00:00
parent 2f600affaa
commit 5e32dcf863

View file

@ -642,6 +642,10 @@ _cairo_gstate_translate (cairo_gstate_t *gstate, double tx, double ty)
cairo_matrix_init_translate (&tmp, tx, ty);
cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm);
/* paranoid check against gradual numerical instability */
if (! _cairo_matrix_is_invertible (&gstate->ctm))
return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
cairo_matrix_init_translate (&tmp, -tx, -ty);
cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp);
@ -668,6 +672,10 @@ _cairo_gstate_scale (cairo_gstate_t *gstate, double sx, double sy)
cairo_matrix_init_scale (&tmp, sx, sy);
cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm);
/* paranoid check against gradual numerical instability */
if (! _cairo_matrix_is_invertible (&gstate->ctm))
return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
cairo_matrix_init_scale (&tmp, 1/sx, 1/sy);
cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp);
@ -695,6 +703,10 @@ _cairo_gstate_rotate (cairo_gstate_t *gstate, double angle)
cairo_matrix_init_rotate (&tmp, angle);
cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm);
/* paranoid check against gradual numerical instability */
if (! _cairo_matrix_is_invertible (&gstate->ctm))
return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
cairo_matrix_init_rotate (&tmp, -angle);
cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp);
@ -718,6 +730,10 @@ _cairo_gstate_transform (cairo_gstate_t *gstate,
cairo_matrix_multiply (&gstate->ctm, matrix, &gstate->ctm);
cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp);
/* paranoid check against gradual numerical instability */
if (! _cairo_matrix_is_invertible (&gstate->ctm))
return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
return CAIRO_STATUS_SUCCESS;
}