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 1839 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1850 } | 1850 } |
1851 if (!result.setConcat(tempMap, result)) { | 1851 if (!result.setConcat(tempMap, result)) { |
1852 return false; | 1852 return false; |
1853 } | 1853 } |
1854 *this = result; | 1854 *this = result; |
1855 return true; | 1855 return true; |
1856 } | 1856 } |
1857 | 1857 |
1858 /////////////////////////////////////////////////////////////////////////////// | 1858 /////////////////////////////////////////////////////////////////////////////// |
1859 | 1859 |
1860 SkScalar SkMatrix::getMaxStretch() const { | 1860 enum MinOrMax { |
1861 TypeMask mask = this->getType(); | 1861 kMin_MinOrMax, |
1862 kMax_MinOrMax | |
1863 }; | |
1862 | 1864 |
1863 if (this->hasPerspective()) { | 1865 template <MinOrMax MIN_OR_MAX> SkScalar get_stretch_factor(SkMatrix::TypeMask ty peMask, |
1866 const SkScalar m[9]) { | |
1867 if (typeMask & SkMatrix::kPerspective_Mask) { | |
1864 return -SK_Scalar1; | 1868 return -SK_Scalar1; |
1865 } | 1869 } |
1866 if (this->isIdentity()) { | 1870 if (SkMatrix::kIdentity_Mask == typeMask) { |
1867 return SK_Scalar1; | 1871 return SK_Scalar1; |
1868 } | 1872 } |
1869 if (!(mask & kAffine_Mask)) { | 1873 if (!(typeMask & SkMatrix::kAffine_Mask)) { |
1870 return SkMaxScalar(SkScalarAbs(fMat[kMScaleX]), | 1874 if (kMin_MinOrMax == MIN_OR_MAX) { |
1871 SkScalarAbs(fMat[kMScaleY])); | 1875 return SkMinScalar(SkScalarAbs(m[SkMatrix::kMScaleX]), |
1876 SkScalarAbs(m[SkMatrix::kMScaleY])); | |
1877 } else { | |
1878 return SkMaxScalar(SkScalarAbs(m[SkMatrix::kMScaleX]), | |
1879 SkScalarAbs(m[SkMatrix::kMScaleY])); | |
1880 } | |
1872 } | 1881 } |
1873 // ignore the translation part of the matrix, just look at 2x2 portion. | 1882 // ignore the translation part of the matrix, just look at 2x2 portion. |
1874 // compute singular values, take largest abs value. | 1883 // compute singular values, take largest or smallest abs value. |
1875 // [a b; b c] = A^T*A | 1884 // [a b; b c] = A^T*A |
1876 SkScalar a = SkScalarMul(fMat[kMScaleX], fMat[kMScaleX]) + | 1885 SkScalar a = SkScalarMul(m[SkMatrix::kMScaleX], m[SkMatrix::kMScaleX]) + |
1877 SkScalarMul(fMat[kMSkewY], fMat[kMSkewY]); | 1886 SkScalarMul(m[SkMatrix::kMSkewY], m[SkMatrix::kMSkewY]); |
1878 SkScalar b = SkScalarMul(fMat[kMScaleX], fMat[kMSkewX]) + | 1887 SkScalar b = SkScalarMul(m[SkMatrix::kMScaleX], m[SkMatrix::kMSkewX]) + |
1879 SkScalarMul(fMat[kMScaleY], fMat[kMSkewY]); | 1888 SkScalarMul(m[SkMatrix::kMScaleY], m[SkMatrix::kMSkewY]); |
1880 SkScalar c = SkScalarMul(fMat[kMSkewX], fMat[kMSkewX]) + | 1889 SkScalar c = SkScalarMul(m[SkMatrix::kMSkewX], m[SkMatrix::kMSkewX]) + |
1881 SkScalarMul(fMat[kMScaleY], fMat[kMScaleY]); | 1890 SkScalarMul(m[SkMatrix::kMScaleY], m[SkMatrix::kMScaleY]); |
1882 // eigenvalues of A^T*A are the squared singular values of A. | 1891 // eigenvalues of A^T*A are the squared singular values of A. |
1883 // characteristic equation is det((A^T*A) - l*I) = 0 | 1892 // characteristic equation is det((A^T*A) - l*I) = 0 |
1884 // l^2 - (a + c)l + (ac-b^2) | 1893 // l^2 - (a + c)l + (ac-b^2) |
1885 // solve using quadratic equation (divisor is non-zero since l^2 has 1 coeff | 1894 // solve using quadratic equation (divisor is non-zero since l^2 has 1 coeff |
robertphillips
2013/12/04 23:31:55
guaranteed
bsalomon
2013/12/09 18:44:31
Done.
| |
1886 // and roots are guaraunteed to be pos and real). | 1895 // and roots are guaraunteed to be pos and real). |
1887 SkScalar largerRoot; | 1896 SkScalar chosenRoot; |
1888 SkScalar bSqd = SkScalarMul(b,b); | 1897 SkScalar bSqd = SkScalarMul(b,b); |
1889 // if upper left 2x2 is orthogonal save some math | 1898 // if upper left 2x2 is orthogonal save some math |
1890 if (bSqd <= SK_ScalarNearlyZero*SK_ScalarNearlyZero) { | 1899 if (bSqd <= SK_ScalarNearlyZero*SK_ScalarNearlyZero) { |
1891 largerRoot = SkMaxScalar(a, c); | 1900 if (kMin_MinOrMax == MIN_OR_MAX) { |
1901 chosenRoot = SkMinScalar(a, c); | |
1902 } else { | |
1903 chosenRoot = SkMaxScalar(a, c); | |
1904 } | |
1892 } else { | 1905 } else { |
1893 SkScalar aminusc = a - c; | 1906 SkScalar aminusc = a - c; |
1894 SkScalar apluscdiv2 = SkScalarHalf(a + c); | 1907 SkScalar apluscdiv2 = SkScalarHalf(a + c); |
1895 SkScalar x = SkScalarHalf(SkScalarSqrt(SkScalarMul(aminusc, aminusc) + 4 * bSqd)); | 1908 SkScalar x = SkScalarHalf(SkScalarSqrt(SkScalarMul(aminusc, aminusc) + 4 * bSqd)); |
1896 largerRoot = apluscdiv2 + x; | 1909 if (kMin_MinOrMax == MIN_OR_MAX) { |
1910 chosenRoot = apluscdiv2 - x; | |
1911 } else { | |
1912 chosenRoot = apluscdiv2 + x; | |
1913 } | |
1897 } | 1914 } |
1898 return SkScalarSqrt(largerRoot); | 1915 SkASSERT(chosenRoot >= 0); |
1916 return SkScalarSqrt(chosenRoot); | |
1917 } | |
1918 | |
1919 SkScalar SkMatrix::getMinStretch() const { | |
1920 return get_stretch_factor<kMin_MinOrMax>(this->getType(), fMat); | |
1921 } | |
1922 | |
1923 SkScalar SkMatrix::getMaxStretch() const { | |
1924 return get_stretch_factor<kMax_MinOrMax>(this->getType(), fMat); | |
1899 } | 1925 } |
1900 | 1926 |
1901 static void reset_identity_matrix(SkMatrix* identity) { | 1927 static void reset_identity_matrix(SkMatrix* identity) { |
1902 identity->reset(); | 1928 identity->reset(); |
1903 } | 1929 } |
1904 | 1930 |
1905 const SkMatrix& SkMatrix::I() { | 1931 const SkMatrix& SkMatrix::I() { |
1906 // If you can use C++11 now, you might consider replacing this with a conste xpr constructor. | 1932 // If you can use C++11 now, you might consider replacing this with a conste xpr constructor. |
1907 static SkMatrix gIdentity; | 1933 static SkMatrix gIdentity; |
1908 SK_DECLARE_STATIC_ONCE(once); | 1934 SK_DECLARE_STATIC_ONCE(once); |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2112 rotation1->fX = cos1; | 2138 rotation1->fX = cos1; |
2113 rotation1->fY = sin1; | 2139 rotation1->fY = sin1; |
2114 } | 2140 } |
2115 if (NULL != rotation2) { | 2141 if (NULL != rotation2) { |
2116 rotation2->fX = cos2; | 2142 rotation2->fX = cos2; |
2117 rotation2->fY = sin2; | 2143 rotation2->fY = sin2; |
2118 } | 2144 } |
2119 | 2145 |
2120 return true; | 2146 return true; |
2121 } | 2147 } |
OLD | NEW |