Index: src/utils/SkMatrix44.cpp |
diff --git a/src/utils/SkMatrix44.cpp b/src/utils/SkMatrix44.cpp |
index c2c9ee4336b08fb0330112b32d49c171fd4f545e..71cd74002b87450e23662f2efc82d6594007901b 100644 |
--- a/src/utils/SkMatrix44.cpp |
+++ b/src/utils/SkMatrix44.cpp |
@@ -448,54 +448,71 @@ double SkMatrix44::determinant() const { |
/////////////////////////////////////////////////////////////////////////////// |
-bool SkMatrix44::invert(SkMatrix44* inverse) const { |
+static bool is_matrix_finite(const SkMatrix44& matrix) { |
+ SkMScalar accumulator = 0; |
+ for (int row = 0; row < 4; ++row) { |
+ for (int col = 0; col < 4; ++col) { |
+ accumulator *= matrix.get(row, col); |
+ } |
+ } |
+ return accumulator == 0; |
+} |
+ |
+bool SkMatrix44::invert(SkMatrix44* storage) const { |
if (this->isIdentity()) { |
- if (inverse) { |
- inverse->setIdentity(); |
+ if (storage) { |
+ storage->setIdentity(); |
} |
return true; |
} |
if (this->isTranslate()) { |
- if (inverse) { |
- inverse->setTranslate(-fMat[3][0], -fMat[3][1], -fMat[3][2]); |
+ if (storage) { |
+ storage->setTranslate(-fMat[3][0], -fMat[3][1], -fMat[3][2]); |
} |
return true; |
} |
+ SkMatrix44 tmp(kUninitialized_Constructor); |
+ // Use storage if it's available and distinct from this matrix. |
+ SkMatrix44* inverse = (storage && storage != this) ? storage : &tmp; |
if (this->isScaleTranslate()) { |
if (0 == fMat[0][0] * fMat[1][1] * fMat[2][2]) { |
return false; |
} |
- if (inverse) { |
- double invXScale = 1 / fMat[0][0]; |
- double invYScale = 1 / fMat[1][1]; |
- double invZScale = 1 / fMat[2][2]; |
+ double invXScale = 1 / fMat[0][0]; |
+ double invYScale = 1 / fMat[1][1]; |
+ double invZScale = 1 / fMat[2][2]; |
- inverse->fMat[0][0] = SkDoubleToMScalar(invXScale); |
- inverse->fMat[0][1] = 0; |
- inverse->fMat[0][2] = 0; |
- inverse->fMat[0][3] = 0; |
+ inverse->fMat[0][0] = SkDoubleToMScalar(invXScale); |
+ inverse->fMat[0][1] = 0; |
+ inverse->fMat[0][2] = 0; |
+ inverse->fMat[0][3] = 0; |
- inverse->fMat[1][0] = 0; |
- inverse->fMat[1][1] = SkDoubleToMScalar(invYScale); |
- inverse->fMat[1][2] = 0; |
- inverse->fMat[1][3] = 0; |
+ inverse->fMat[1][0] = 0; |
+ inverse->fMat[1][1] = SkDoubleToMScalar(invYScale); |
+ inverse->fMat[1][2] = 0; |
+ inverse->fMat[1][3] = 0; |
- inverse->fMat[2][0] = 0; |
- inverse->fMat[2][1] = 0; |
- inverse->fMat[2][2] = SkDoubleToMScalar(invZScale); |
- inverse->fMat[2][3] = 0; |
+ inverse->fMat[2][0] = 0; |
+ inverse->fMat[2][1] = 0; |
+ inverse->fMat[2][2] = SkDoubleToMScalar(invZScale); |
+ inverse->fMat[2][3] = 0; |
- inverse->fMat[3][0] = SkDoubleToMScalar(-fMat[3][0] * invXScale); |
- inverse->fMat[3][1] = SkDoubleToMScalar(-fMat[3][1] * invYScale); |
- inverse->fMat[3][2] = SkDoubleToMScalar(-fMat[3][2] * invZScale); |
- inverse->fMat[3][3] = 1; |
+ inverse->fMat[3][0] = SkDoubleToMScalar(-fMat[3][0] * invXScale); |
+ inverse->fMat[3][1] = SkDoubleToMScalar(-fMat[3][1] * invYScale); |
+ inverse->fMat[3][2] = SkDoubleToMScalar(-fMat[3][2] * invZScale); |
+ inverse->fMat[3][3] = 1; |
- inverse->setTypeMask(this->getType()); |
- } |
+ inverse->setTypeMask(this->getType()); |
+ if (!is_matrix_finite(*inverse)) { |
+ return false; |
+ } |
+ if (storage && inverse != storage) { |
+ *storage = *inverse; |
+ } |
return true; |
} |
@@ -547,9 +564,6 @@ bool SkMatrix44::invert(SkMatrix44* inverse) const { |
if (!sk_float_isfinite(invdet)) { |
return false; |
} |
- if (NULL == inverse) { |
- return true; |
- } |
b00 *= invdet; |
b01 *= invdet; |
@@ -579,6 +593,12 @@ bool SkMatrix44::invert(SkMatrix44* inverse) const { |
inverse->fMat[3][3] = 1; |
inverse->setTypeMask(this->getType()); |
+ if (!is_matrix_finite(*inverse)) { |
+ return false; |
+ } |
+ if (storage && inverse != storage) { |
+ *storage = *inverse; |
+ } |
return true; |
} |
@@ -605,9 +625,6 @@ bool SkMatrix44::invert(SkMatrix44* inverse) const { |
if (!sk_float_isfinite(invdet)) { |
return false; |
} |
- if (NULL == inverse) { |
- return true; |
- } |
b00 *= invdet; |
b01 *= invdet; |
@@ -640,6 +657,13 @@ bool SkMatrix44::invert(SkMatrix44* inverse) const { |
inverse->fMat[3][3] = SkDoubleToMScalar(a20 * b03 - a21 * b01 + a22 * b00); |
inverse->dirtyTypeMask(); |
+ inverse->setTypeMask(this->getType()); |
+ if (!is_matrix_finite(*inverse)) { |
+ return false; |
+ } |
+ if (storage && inverse != storage) { |
+ *storage = *inverse; |
+ } |
return true; |
} |