Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(89)

Unified Diff: src/core/SkMatrix.cpp

Issue 19569007: Add basic SVD support to SkMatrix. Allows you to pull out the x- and y-scale factors, sandwiched by… (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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) {
« include/core/SkMatrix.h ('K') | « include/core/SkMatrix.h ('k') | tests/MatrixTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698