Index: src/core/SkMatrix.cpp |
diff --git a/src/core/SkMatrix.cpp b/src/core/SkMatrix.cpp |
index 13ec7ae322d0a3ff177a372557ace12382479ab1..7334b5bc552ac48a71557f981c6af5909515e93a 100644 |
--- a/src/core/SkMatrix.cpp |
+++ b/src/core/SkMatrix.cpp |
@@ -240,6 +240,71 @@ bool SkMatrix::preservesRightAngles(SkScalar tol) const { |
SkScalarSquare(tol)); |
} |
+bool SkMatrix::decomposeUpper2x2(SkScalar* rotation0, |
+ SkScalar* xScale, SkScalar* yScale, |
+ SkScalar* rotation1) const { |
+ |
+ // borrowed from Jim Blinn's article "Consider the Lowly 2x2 Matrix" |
+ // Note: he uses row vectors, so we have to do some swapping of terms |
+ SkScalar A = fMat[kMScaleX]; |
+ SkScalar B = fMat[kMSkewX]; |
+ SkScalar C = fMat[kMSkewY]; |
+ SkScalar D = fMat[kMScaleY]; |
+ |
+ SkScalar E = SK_ScalarHalf*(A + D); |
+ SkScalar F = SK_ScalarHalf*(A - D); |
+ SkScalar G = SK_ScalarHalf*(C + B); |
+ SkScalar H = SK_ScalarHalf*(C - B); |
+ |
+ SkScalar sqrt0 = SkScalarSqrt(E*E + H*H); |
+ SkScalar sqrt1 = SkScalarSqrt(F*F + G*G); |
+ |
+ // can't have zero yScale, must be degenerate |
+ if (SkScalarNearlyEqual(sqrt0, sqrt1)) { |
+ return false; |
+ } |
+ if (NULL != xScale) { |
+ *xScale = sqrt0 + sqrt1; |
+ } |
+ if (NULL != yScale) { |
+ *yScale = sqrt0 - sqrt1; |
+ } |
+ |
+ // uniformly scaled rotation |
+ if (SkScalarNearlyZero(F) && SkScalarNearlyZero(G)) { |
+ SkASSERT(!SkScalarNearlyZero(E)); |
+ if (NULL != rotation0) { |
+ *rotation0 = SkScalarATan2(H, E); |
+ } |
+ if (NULL != rotation1) { |
+ *rotation1 = 0; |
+ } |
+ // uniformly scaled reflection |
+ } else if (SkScalarNearlyZero(E) && SkScalarNearlyZero(H)) { |
+ SkASSERT(!SkScalarNearlyZero(F)); |
+ if (NULL != rotation0) { |
+ *rotation0 = -SkScalarATan2(G, F); |
+ } |
+ if (NULL != rotation1) { |
+ *rotation1 = 0; |
+ } |
+ } else { |
+ SkASSERT(!SkScalarNearlyZero(E)); |
+ SkASSERT(!SkScalarNearlyZero(F)); |
+ |
+ SkScalar arctan0 = SkScalarATan2(H, E); |
+ SkScalar arctan1 = SkScalarATan2(G, F); |
+ if (NULL != rotation0) { |
+ *rotation0 = SK_ScalarHalf*(arctan0 - arctan1); |
+ } |
+ if (NULL != rotation1) { |
+ *rotation1 = SK_ScalarHalf*(arctan0 + arctan1); |
+ } |
+ } |
+ |
+ return true; |
+} |
+ |
/////////////////////////////////////////////////////////////////////////////// |
void SkMatrix::setTranslate(SkScalar dx, SkScalar dy) { |