diff options
author | reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-01-04 17:02:33 +0000 |
---|---|---|
committer | reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-01-04 17:02:33 +0000 |
commit | 2fb96cc5d713451216bd63d5dc8d19abc8550730 (patch) | |
tree | d97411a5a61648e62f2e23e6139982681b9fa6d1 | |
parent | be61c05d897bef024fde7a9f9d7b6c35855bb982 (diff) |
special-case matrix invert for translate and scale
update unittest to use diff scale-x and scale-y values, and tests for non-invertible scale matrices
Review URL: https://codereview.appspot.com/7027055
git-svn-id: http://skia.googlecode.com/svn/trunk@7019 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r-- | src/core/SkMatrix.cpp | 37 | ||||
-rw-r--r-- | tests/MatrixTest.cpp | 9 |
2 files changed, 43 insertions, 3 deletions
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 { |