OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2006 The Android Open Source Project | 2 * Copyright 2006 The Android Open Source Project |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkMatrix.h" | 8 #include "SkMatrix.h" |
9 #include "Sk64.h" | 9 #include "Sk64.h" |
10 #include "SkFloatBits.h" | 10 #include "SkFloatBits.h" |
(...skipping 1989 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2000 dst.fTop *= scale; | 2000 dst.fTop *= scale; |
2001 dst.fRight *= scale; | 2001 dst.fRight *= scale; |
2002 dst.fBottom *= scale; | 2002 dst.fBottom *= scale; |
2003 } | 2003 } |
2004 | 2004 |
2005 SkIRect idst; | 2005 SkIRect idst; |
2006 dst.round(&idst); | 2006 dst.round(&idst); |
2007 return isrc == idst; | 2007 return isrc == idst; |
2008 } | 2008 } |
2009 | 2009 |
| 2010 // A square matrix M can be decomposed (via polar decomposition) into two matric
es -- |
| 2011 // an orthogonal matrix Q and a symmetric matrix S. In turn we can decompose S i
nto U*W*U^T, |
| 2012 // where U is another orthogonal matrix and W is a scale matrix. These can be re
combined |
| 2013 // to give M = (Q*U)*W*U^T, i.e., the product of two orthogonal matrices and a s
cale matrix. |
| 2014 // |
| 2015 // The one wrinkle is that traditionally Q may contain a reflection -- the |
| 2016 // calculation has been rejiggered to put that reflection into W. |
2010 bool SkDecomposeUpper2x2(const SkMatrix& matrix, | 2017 bool SkDecomposeUpper2x2(const SkMatrix& matrix, |
2011 SkScalar* rotation0, | 2018 SkPoint* rotation1, |
2012 SkScalar* xScale, SkScalar* yScale, | 2019 SkPoint* scale, |
2013 SkScalar* rotation1) { | 2020 SkPoint* rotation2) { |
2014 | 2021 |
2015 // borrowed from Jim Blinn's article "Consider the Lowly 2x2 Matrix" | |
2016 // Note: he uses row vectors, so we have to do some swapping of terms | |
2017 SkScalar A = matrix[SkMatrix::kMScaleX]; | 2022 SkScalar A = matrix[SkMatrix::kMScaleX]; |
2018 SkScalar B = matrix[SkMatrix::kMSkewX]; | 2023 SkScalar B = matrix[SkMatrix::kMSkewX]; |
2019 SkScalar C = matrix[SkMatrix::kMSkewY]; | 2024 SkScalar C = matrix[SkMatrix::kMSkewY]; |
2020 SkScalar D = matrix[SkMatrix::kMScaleY]; | 2025 SkScalar D = matrix[SkMatrix::kMScaleY]; |
2021 | 2026 |
2022 if (is_degenerate_2x2(A, B, C, D)) { | 2027 if (is_degenerate_2x2(A, B, C, D)) { |
2023 return false; | 2028 return false; |
2024 } | 2029 } |
2025 | 2030 |
2026 SkScalar E = SK_ScalarHalf*(A + D); | 2031 double w1, w2; |
2027 SkScalar F = SK_ScalarHalf*(A - D); | 2032 SkScalar cos1, sin1; |
2028 SkScalar G = SK_ScalarHalf*(C + B); | 2033 SkScalar cos2, sin2; |
2029 SkScalar H = SK_ScalarHalf*(C - B); | |
2030 | 2034 |
2031 SkScalar sqrt0 = SkScalarSqrt(E*E + H*H); | 2035 // do polar decomposition (M = Q*S) |
2032 SkScalar sqrt1 = SkScalarSqrt(F*F + G*G); | 2036 SkScalar cosQ, sinQ; |
| 2037 double Sa, Sb, Sd; |
| 2038 // if M is already symmetric (i.e., M = I*S) |
| 2039 if (SkScalarNearlyEqual(B, C)) { |
| 2040 cosQ = SK_Scalar1; |
| 2041 sinQ = 0; |
2033 | 2042 |
2034 SkScalar xs, ys, r0, r1; | 2043 Sa = A; |
| 2044 Sb = B; |
| 2045 Sd = D; |
| 2046 } else { |
| 2047 cosQ = A + D; |
| 2048 sinQ = C - B; |
| 2049 SkScalar reciplen = SK_Scalar1/SkScalarSqrt(cosQ*cosQ + sinQ*sinQ); |
| 2050 cosQ *= reciplen; |
| 2051 sinQ *= reciplen; |
2035 | 2052 |
2036 xs = sqrt0 + sqrt1; | 2053 // S = Q^-1*M |
2037 ys = sqrt0 - sqrt1; | 2054 // we don't calc Sc since it's symmetric |
2038 // can't have zero yScale, must be degenerate | 2055 Sa = A*cosQ + C*sinQ; |
2039 SkASSERT(!SkScalarNearlyZero(ys)); | 2056 Sb = B*cosQ + D*sinQ; |
2040 | 2057 Sd = -B*sinQ + D*cosQ; |
2041 // uniformly scaled rotation | |
2042 if (SkScalarNearlyZero(F) && SkScalarNearlyZero(G)) { | |
2043 SkASSERT(!SkScalarNearlyZero(E) || !SkScalarNearlyZero(H)); | |
2044 r0 = SkScalarATan2(H, E); | |
2045 r1 = 0; | |
2046 // uniformly scaled reflection | |
2047 } else if (SkScalarNearlyZero(E) && SkScalarNearlyZero(H)) { | |
2048 SkASSERT(!SkScalarNearlyZero(F) || !SkScalarNearlyZero(G)); | |
2049 r0 = -SkScalarATan2(G, F); | |
2050 r1 = 0; | |
2051 } else { | |
2052 SkASSERT(!SkScalarNearlyZero(E) || !SkScalarNearlyZero(H)); | |
2053 SkASSERT(!SkScalarNearlyZero(F) || !SkScalarNearlyZero(G)); | |
2054 | |
2055 SkScalar arctan0 = SkScalarATan2(H, E); | |
2056 SkScalar arctan1 = SkScalarATan2(G, F); | |
2057 r0 = SK_ScalarHalf*(arctan0 - arctan1); | |
2058 r1 = SK_ScalarHalf*(arctan0 + arctan1); | |
2059 | |
2060 // simplify the results | |
2061 const SkScalar kHalfPI = SK_ScalarHalf*SK_ScalarPI; | |
2062 if (SkScalarNearlyEqual(SkScalarAbs(r0), kHalfPI)) { | |
2063 SkScalar tmp = xs; | |
2064 xs = ys; | |
2065 ys = tmp; | |
2066 | |
2067 r1 += r0; | |
2068 r0 = 0; | |
2069 } else if (SkScalarNearlyEqual(SkScalarAbs(r1), kHalfPI)) { | |
2070 SkScalar tmp = xs; | |
2071 xs = ys; | |
2072 ys = tmp; | |
2073 | |
2074 r0 += r1; | |
2075 r1 = 0; | |
2076 } | |
2077 } | 2058 } |
2078 | 2059 |
2079 if (NULL != xScale) { | 2060 // Now we need to compute eigenvalues of S (our scale factors) |
2080 *xScale = xs; | 2061 // and eigenvectors (bases for our rotation) |
| 2062 // From this, should be able to reconstruct S as U*W*U^T |
| 2063 if (SkScalarNearlyZero(Sb)) { |
| 2064 // already diagonalized |
| 2065 cos1 = SK_Scalar1; |
| 2066 sin1 = 0; |
| 2067 w1 = Sa; |
| 2068 w2 = Sd; |
| 2069 cos2 = cosQ; |
| 2070 sin2 = sinQ; |
| 2071 } else { |
| 2072 double diff = Sa - Sd; |
| 2073 double discriminant = sqrt(diff*diff + 4.0*Sb*Sb); |
| 2074 double trace = Sa + Sd; |
| 2075 if (diff > 0) { |
| 2076 w1 = 0.5*(trace + discriminant); |
| 2077 w2 = 0.5*(trace - discriminant); |
| 2078 } else { |
| 2079 w1 = 0.5*(trace - discriminant); |
| 2080 w2 = 0.5*(trace + discriminant); |
| 2081 } |
| 2082 |
| 2083 cos1 = Sb; sin1 = w1 - Sa; |
| 2084 SkScalar reciplen = SK_Scalar1/SkScalarSqrt(cos1*cos1 + sin1*sin1); |
| 2085 cos1 *= reciplen; |
| 2086 sin1 *= reciplen; |
| 2087 |
| 2088 // rotation 2 is composition of Q and U |
| 2089 cos2 = cos1*cosQ - sin1*sinQ; |
| 2090 sin2 = sin1*cosQ + cos1*sinQ; |
| 2091 |
| 2092 // rotation 1 is U^T |
| 2093 sin1 = -sin1; |
2081 } | 2094 } |
2082 if (NULL != yScale) { | 2095 |
2083 *yScale = ys; | 2096 if (NULL != scale) { |
2084 } | 2097 scale->fX = w1; |
2085 if (NULL != rotation0) { | 2098 scale->fY = w2; |
2086 *rotation0 = r0; | |
2087 } | 2099 } |
2088 if (NULL != rotation1) { | 2100 if (NULL != rotation1) { |
2089 *rotation1 = r1; | 2101 rotation1->fX = cos1; |
| 2102 rotation1->fY = sin1; |
| 2103 } |
| 2104 if (NULL != rotation2) { |
| 2105 rotation2->fX = cos2; |
| 2106 rotation2->fY = sin2; |
2090 } | 2107 } |
2091 | 2108 |
2092 return true; | 2109 return true; |
2093 } | 2110 } |
OLD | NEW |