mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-06 12:48:04 +02:00
[matrix] Optimise invert for simple scaling|translation matrices.
Peter Hercek reported, and provided a very useful test case for, a bug that caused his applications to crash with Cairo detecting an non-invertible pattern matrix and thus asserting the impossible happened. Bisecting revealed that the bug first appeared with3c18d95and disappeared with0d0c6a1. Since neither of these explain the crash, further investigation revealed a compiler bug (gcc 4.3.3 20081130, earlier versions have different bugs!) that caused the matrix inversion to be invalid iff _cairo_matrix_scalar_multiply() was inlined (i.e. -O0, or an explicit noinline atttribute on that function prevented the bug, as did -msse.) So we apply this workaround to hide the bug in the stable series... The matrix is quite often just a simple scale and translate (or even identity!). For this class of matrix, we can skip the full adjoint rearrangement and determinant calculation and just compute the inverse directly. (cherry picked from commit0d0c6a199c)
This commit is contained in:
parent
f5634818f1
commit
540de34453
1 changed files with 25 additions and 1 deletions
|
|
@ -485,9 +485,33 @@ _cairo_matrix_compute_adjoint (cairo_matrix_t *matrix)
|
|||
cairo_status_t
|
||||
cairo_matrix_invert (cairo_matrix_t *matrix)
|
||||
{
|
||||
/* inv (A) = 1/det (A) * adj (A) */
|
||||
double det;
|
||||
|
||||
/* Simple scaling|translation matrices are quite common... */
|
||||
if (matrix->xy == 0. && matrix->yx == 0.) {
|
||||
matrix->x0 = -matrix->x0;
|
||||
matrix->y0 = -matrix->y0;
|
||||
|
||||
if (matrix->xx != 1.) {
|
||||
if (matrix->xx == 0.)
|
||||
return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
|
||||
|
||||
matrix->xx = 1. / matrix->xx;
|
||||
matrix->x0 *= matrix->xx;
|
||||
}
|
||||
|
||||
if (matrix->yy != 1.) {
|
||||
if (matrix->yy == 0.)
|
||||
return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
|
||||
|
||||
matrix->yy = 1. / matrix->yy;
|
||||
matrix->y0 *= matrix->yy;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* inv (A) = 1/det (A) * adj (A) */
|
||||
det = _cairo_matrix_compute_determinant (matrix);
|
||||
|
||||
if (! ISFINITE (det))
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue