diff --git a/src/core/SkMatrix.cpp b/src/core/SkMatrix.cpp index 5c9547e8a7..6cccc39ece 100644 --- a/src/core/SkMatrix.cpp +++ b/src/core/SkMatrix.cpp @@ -850,7 +850,42 @@ bool SkMatrix::asAffine(SkScalar affine[6]) const { bool SkMatrix::invertNonIdentity(SkMatrix* inv) const { SkASSERT(!this->isIdentity()); - int isPersp = this->hasPerspective(); + + TypeMask mask = this->getType(); + + if (0 == (mask & ~(kScale_Mask | kTranslate_Mask))) { + if (inv) { + if (mask & kScale_Mask) { + SkScalar invX = fMat[kMScaleX]; + SkScalar invY = fMat[kMScaleY]; + if (0 == invX || 0 == invY) { + return false; + } + invX = SkScalarInvert(invX); + invY = SkScalarInvert(invY); + + // Must be careful when writing to inv, since it may be the + // same memory as this. + + inv->fMat[kMSkewX] = inv->fMat[kMSkewY] = + inv->fMat[kMPersp0] = inv->fMat[kMPersp1] = 0; + + inv->fMat[kMScaleX] = invX; + inv->fMat[kMScaleY] = invY; + inv->fMat[kMPersp2] = kMatrix22Elem; + inv->fMat[kMTransX] = -SkScalarMul(fMat[kMTransX], invX); + inv->fMat[kMTransY] = -SkScalarMul(fMat[kMTransY], invY); + + inv->setTypeMask(mask | kRectStaysRect_Mask); + } else { + // translate only + inv->setTranslate(-fMat[kMTransX], -fMat[kMTransY]); + } + } + return true; + } + + int isPersp = mask & kPerspective_Mask; int shift; SkDetScalar scale = sk_inv_determinant(fMat, isPersp, &shift); diff --git a/tests/MatrixTest.cpp b/tests/MatrixTest.cpp index 894278e84b..bba2e08683 100644 --- a/tests/MatrixTest.cpp +++ b/tests/MatrixTest.cpp @@ -384,13 +384,13 @@ static void TestMatrix(skiatest::Reporter* reporter) { iden1.setConcat(mat, inverse); REPORTER_ASSERT(reporter, is_identity(iden1)); - mat.setScale(SkIntToScalar(2), SkIntToScalar(2)); + mat.setScale(SkIntToScalar(2), SkIntToScalar(4)); REPORTER_ASSERT(reporter, mat.invert(&inverse)); iden1.setConcat(mat, inverse); REPORTER_ASSERT(reporter, is_identity(iden1)); test_flatten(reporter, mat); - mat.setScale(SK_Scalar1/2, SK_Scalar1/2); + mat.setScale(SK_Scalar1/2, SkIntToScalar(2)); REPORTER_ASSERT(reporter, mat.invert(&inverse)); iden1.setConcat(mat, inverse); REPORTER_ASSERT(reporter, is_identity(iden1)); @@ -407,6 +407,11 @@ static void TestMatrix(skiatest::Reporter* reporter) { test_flatten(reporter, mat); test_flatten(reporter, iden2); + mat.setScale(0, SK_Scalar1); + REPORTER_ASSERT(reporter, !mat.invert(&inverse)); + mat.setScale(SK_Scalar1, 0); + REPORTER_ASSERT(reporter, !mat.invert(&inverse)); + // rectStaysRect test { static const struct {