diff options
-rw-r--r-- | src/utils/SkMatrix44.cpp | 8 | ||||
-rw-r--r-- | tests/Matrix44Test.cpp | 27 |
2 files changed, 32 insertions, 3 deletions
diff --git a/src/utils/SkMatrix44.cpp b/src/utils/SkMatrix44.cpp index 92c8715faa..9ceecbdf2a 100644 --- a/src/utils/SkMatrix44.cpp +++ b/src/utils/SkMatrix44.cpp @@ -529,13 +529,16 @@ bool SkMatrix44::invert(SkMatrix44* inverse) const { // Calculate the determinant double det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; - if (dabs(det) < TOO_SMALL_FOR_DETERMINANT) { + double invdet = 1.0 / det; + // If det is zero, we want to return false. However, we also want to return false + // if 1/det overflows to infinity (i.e. det is denormalized). Both of these are + // handled by checking that 1/det is finite. + if (!sk_float_isfinite(invdet)) { return false; } if (NULL == inverse) { return true; } - double invdet = 1.0 / det; b00 *= invdet; b01 *= invdet; @@ -568,7 +571,6 @@ bool SkMatrix44::invert(SkMatrix44* inverse) const { inverse->fMat[3][3] = SkDoubleToMScalar(a20 * b03 - a21 * b01 + a22 * b00); inverse->dirtyTypeMask(); - inverse->dirtyTypeMask(); return true; } diff --git a/tests/Matrix44Test.cpp b/tests/Matrix44Test.cpp index b2c7071b79..7e31840144 100644 --- a/tests/Matrix44Test.cpp +++ b/tests/Matrix44Test.cpp @@ -403,6 +403,33 @@ static void TestMatrix44(skiatest::Reporter* reporter) { iden2.setConcat(inverse, mat); REPORTER_ASSERT(reporter, is_identity(iden2)); + // test tiny-valued matrix inverse + mat.reset(); + mat.setScale(1.0e-12, 1.0e-12, 1.0e-12); + rot.setRotateDegreesAbout(0, 0, -1, 90); + mat.postConcat(rot); + mat.postTranslate(1.0e-12, 1.0e-12, 1.0e-12); + REPORTER_ASSERT(reporter, mat.invert(NULL)); + mat.invert(&inverse); + iden1.setConcat(mat, inverse); + REPORTER_ASSERT(reporter, is_identity(iden1)); + + // test mixed-valued matrix inverse + mat.reset(); + mat.setScale(1.0e-11, 3.0, 1.0e+11); + rot.setRotateDegreesAbout(0, 0, -1, 90); + mat.postConcat(rot); + mat.postTranslate(1.0e+11, 3.0, 1.0e-11); + REPORTER_ASSERT(reporter, mat.invert(NULL)); + mat.invert(&inverse); + iden1.setConcat(mat, inverse); + REPORTER_ASSERT(reporter, is_identity(iden1)); + + // test degenerate matrix + mat.reset(); + mat.set3x3(1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0); + REPORTER_ASSERT(reporter, !mat.invert(NULL)); + // test rol/col Major getters { mat.setTranslate(2, 3, 4); |