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

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: Remove trailing white space; replace fabs() with SkScalarAbs() 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
« no previous file with comments | « no previous file | src/core/SkMatrixUtils.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/core/SkMatrix.cpp
diff --git a/src/core/SkMatrix.cpp b/src/core/SkMatrix.cpp
index 13ec7ae322d0a3ff177a372557ace12382479ab1..488bff7287905bdff6169eaeec9267f736545f33 100644
--- a/src/core/SkMatrix.cpp
+++ b/src/core/SkMatrix.cpp
@@ -1966,3 +1966,86 @@ bool SkTreatAsSprite(const SkMatrix& mat, int width, int height,
dst.round(&idst);
return isrc == idst;
}
+
+bool SkDecomposeUpper2x2(const SkMatrix& matrix,
+ SkScalar* rotation0,
+ SkScalar* xScale, SkScalar* yScale,
+ SkScalar* rotation1) {
+
+ // 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 = matrix[SkMatrix::kMScaleX];
+ SkScalar B = matrix[SkMatrix::kMSkewX];
+ SkScalar C = matrix[SkMatrix::kMSkewY];
+ SkScalar D = matrix[SkMatrix::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);
+
+ SkScalar xs, ys, r0, r1;
+
+ // can't have zero yScale, must be degenerate
+ if (SkScalarNearlyEqual(sqrt0, sqrt1)) {
+ return false;
+ }
+ xs = sqrt0 + sqrt1;
+ ys = sqrt0 - sqrt1;
+
+ // uniformly scaled rotation
+ if (SkScalarNearlyZero(F) && SkScalarNearlyZero(G)) {
+ SkASSERT(!SkScalarNearlyZero(E));
+ r0 = SkScalarATan2(H, E);
+ r1 = 0;
+ // uniformly scaled reflection
+ } else if (SkScalarNearlyZero(E) && SkScalarNearlyZero(H)) {
+ SkASSERT(!SkScalarNearlyZero(F));
+ r0 = -SkScalarATan2(G, F);
+ r1 = 0;
+ } else {
+ SkASSERT(!SkScalarNearlyZero(E));
+ SkASSERT(!SkScalarNearlyZero(F));
+
+ SkScalar arctan0 = SkScalarATan2(H, E);
+ SkScalar arctan1 = SkScalarATan2(G, F);
+ r0 = SK_ScalarHalf*(arctan0 - arctan1);
+ r1 = SK_ScalarHalf*(arctan0 + arctan1);
+
+ // simplify the results
+ const SkScalar kHalfPI = SK_ScalarHalf*SK_ScalarPI;
+ if (SkScalarNearlyEqual(SkScalarAbs(r0), kHalfPI)) {
+ SkScalar tmp = xs;
+ xs = ys;
+ ys = tmp;
+
+ r1 += r0;
+ r0 = 0;
+ } else if (SkScalarNearlyEqual(SkScalarAbs(r1), kHalfPI)) {
+ SkScalar tmp = xs;
+ xs = ys;
+ ys = tmp;
+
+ r0 += r1;
+ r1 = 0;
+ }
+ }
+
+ if (NULL != xScale) {
+ *xScale = xs;
+ }
+ if (NULL != yScale) {
+ *yScale = ys;
+ }
+ if (NULL != rotation0) {
+ *rotation0 = r0;
+ }
+ if (NULL != rotation1) {
+ *rotation1 = r1;
+ }
+
+ return true;
+}
« no previous file with comments | « no previous file | src/core/SkMatrixUtils.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698