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 |
1886 // and roots are guaraunteed to be pos and real). | 1895 // and roots are guaranteed 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 |