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 "SkFloatBits.h" | 9 #include "SkFloatBits.h" |
10 #include "SkString.h" | 10 #include "SkString.h" |
(...skipping 734 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
745 | 745 |
746 // Since the determinant is on the order of the cube of the matrix members, | 746 // Since the determinant is on the order of the cube of the matrix members, |
747 // compare to the cube of the default nearly-zero constant (although an | 747 // compare to the cube of the default nearly-zero constant (although an |
748 // estimate of the condition number would be better if it wasn't so expensiv
e). | 748 // estimate of the condition number would be better if it wasn't so expensiv
e). |
749 if (SkScalarNearlyZero((float)det, SK_ScalarNearlyZero * SK_ScalarNearlyZero
* SK_ScalarNearlyZero)) { | 749 if (SkScalarNearlyZero((float)det, SK_ScalarNearlyZero * SK_ScalarNearlyZero
* SK_ScalarNearlyZero)) { |
750 return 0; | 750 return 0; |
751 } | 751 } |
752 return 1.0 / det; | 752 return 1.0 / det; |
753 } | 753 } |
754 | 754 |
| 755 bool SkMatrix::isFinite() const { |
| 756 for (int i = 0; i < 9; ++i) { |
| 757 if (!SkScalarIsFinite(fMat[i])) { |
| 758 return false; |
| 759 } |
| 760 } |
| 761 |
| 762 return true; |
| 763 } |
| 764 |
755 void SkMatrix::SetAffineIdentity(SkScalar affine[6]) { | 765 void SkMatrix::SetAffineIdentity(SkScalar affine[6]) { |
756 affine[kAScaleX] = 1; | 766 affine[kAScaleX] = 1; |
757 affine[kASkewY] = 0; | 767 affine[kASkewY] = 0; |
758 affine[kASkewX] = 0; | 768 affine[kASkewX] = 0; |
759 affine[kAScaleY] = 1; | 769 affine[kAScaleY] = 1; |
760 affine[kATransX] = 0; | 770 affine[kATransX] = 0; |
761 affine[kATransY] = 0; | 771 affine[kATransY] = 0; |
762 } | 772 } |
763 | 773 |
764 bool SkMatrix::asAffine(SkScalar affine[6]) const { | 774 bool SkMatrix::asAffine(SkScalar affine[6]) const { |
765 if (this->hasPerspective()) { | 775 if (this->hasPerspective()) { |
766 return false; | 776 return false; |
767 } | 777 } |
768 if (affine) { | 778 if (affine) { |
769 affine[kAScaleX] = this->fMat[kMScaleX]; | 779 affine[kAScaleX] = this->fMat[kMScaleX]; |
770 affine[kASkewY] = this->fMat[kMSkewY]; | 780 affine[kASkewY] = this->fMat[kMSkewY]; |
771 affine[kASkewX] = this->fMat[kMSkewX]; | 781 affine[kASkewX] = this->fMat[kMSkewX]; |
772 affine[kAScaleY] = this->fMat[kMScaleY]; | 782 affine[kAScaleY] = this->fMat[kMScaleY]; |
773 affine[kATransX] = this->fMat[kMTransX]; | 783 affine[kATransX] = this->fMat[kMTransX]; |
774 affine[kATransY] = this->fMat[kMTransY]; | 784 affine[kATransY] = this->fMat[kMTransY]; |
775 } | 785 } |
776 return true; | 786 return true; |
777 } | 787 } |
778 | 788 |
| 789 void SkMatrix::ComputeInv(SkScalar dst[9], const SkScalar src[9], SkScalar invDe
t, bool isPersp) { |
| 790 SkASSERT(src != dst); |
| 791 SkASSERT(src && dst); |
| 792 |
| 793 if (isPersp) { |
| 794 dst[kMScaleX] = scross_dscale(src[kMScaleY], src[kMPersp2], src[kMTransY
], src[kMPersp1], invDet); |
| 795 dst[kMSkewX] = scross_dscale(src[kMTransX], src[kMPersp1], src[kMSkewX]
, src[kMPersp2], invDet); |
| 796 dst[kMTransX] = scross_dscale(src[kMSkewX], src[kMTransY], src[kMTransX
], src[kMScaleY], invDet); |
| 797 |
| 798 dst[kMSkewY] = scross_dscale(src[kMTransY], src[kMPersp0], src[kMSkewY]
, src[kMPersp2], invDet); |
| 799 dst[kMScaleY] = scross_dscale(src[kMScaleX], src[kMPersp2], src[kMTransX
], src[kMPersp0], invDet); |
| 800 dst[kMTransY] = scross_dscale(src[kMTransX], src[kMSkewY], src[kMScaleX
], src[kMTransY], invDet); |
| 801 |
| 802 dst[kMPersp0] = scross_dscale(src[kMSkewY], src[kMPersp1], src[kMScaleY
], src[kMPersp0], invDet); |
| 803 dst[kMPersp1] = scross_dscale(src[kMSkewX], src[kMPersp0], src[kMScaleX
], src[kMPersp1], invDet); |
| 804 dst[kMPersp2] = scross_dscale(src[kMScaleX], src[kMScaleY], src[kMSkewX]
, src[kMSkewY], invDet); |
| 805 } else { // not perspective |
| 806 dst[kMScaleX] = SkDoubleToScalar(src[kMScaleY] * invDet); |
| 807 dst[kMSkewX] = SkDoubleToScalar(-src[kMSkewX] * invDet); |
| 808 dst[kMTransX] = dcross_dscale(src[kMSkewX], src[kMTransY], src[kMScaleY]
, src[kMTransX], invDet); |
| 809 |
| 810 dst[kMSkewY] = SkDoubleToScalar(-src[kMSkewY] * invDet); |
| 811 dst[kMScaleY] = SkDoubleToScalar(src[kMScaleX] * invDet); |
| 812 dst[kMTransY] = dcross_dscale(src[kMSkewY], src[kMTransX], src[kMScaleX]
, src[kMTransY], invDet); |
| 813 |
| 814 dst[kMPersp0] = 0; |
| 815 dst[kMPersp1] = 0; |
| 816 dst[kMPersp2] = 1; |
| 817 } |
| 818 } |
| 819 |
779 bool SkMatrix::invertNonIdentity(SkMatrix* inv) const { | 820 bool SkMatrix::invertNonIdentity(SkMatrix* inv) const { |
780 SkASSERT(!this->isIdentity()); | 821 SkASSERT(!this->isIdentity()); |
781 | 822 |
782 TypeMask mask = this->getType(); | 823 TypeMask mask = this->getType(); |
783 | 824 |
784 if (0 == (mask & ~(kScale_Mask | kTranslate_Mask))) { | 825 if (0 == (mask & ~(kScale_Mask | kTranslate_Mask))) { |
785 bool invertible = true; | 826 bool invertible = true; |
786 if (inv) { | 827 if (inv) { |
787 if (mask & kScale_Mask) { | 828 if (mask & kScale_Mask) { |
788 SkScalar invX = fMat[kMScaleX]; | 829 SkScalar invX = fMat[kMScaleX]; |
(...skipping 23 matching lines...) Expand all Loading... |
812 } | 853 } |
813 } else { // inv is NULL, just check if we're invertible | 854 } else { // inv is NULL, just check if we're invertible |
814 if (!fMat[kMScaleX] || !fMat[kMScaleY]) { | 855 if (!fMat[kMScaleX] || !fMat[kMScaleY]) { |
815 invertible = false; | 856 invertible = false; |
816 } | 857 } |
817 } | 858 } |
818 return invertible; | 859 return invertible; |
819 } | 860 } |
820 | 861 |
821 int isPersp = mask & kPerspective_Mask; | 862 int isPersp = mask & kPerspective_Mask; |
822 double scale = sk_inv_determinant(fMat, isPersp); | 863 double invDet = sk_inv_determinant(fMat, isPersp); |
823 | 864 |
824 if (scale == 0) { // underflow | 865 if (invDet == 0) { // underflow |
825 return false; | 866 return false; |
826 } | 867 } |
827 | 868 |
828 if (inv) { | 869 bool applyingInPlace = (inv == this); |
829 SkMatrix tmp; | |
830 if (inv == this) { | |
831 inv = &tmp; | |
832 } | |
833 | 870 |
834 if (isPersp) { | 871 SkMatrix* tmp = inv; |
835 inv->fMat[kMScaleX] = scross_dscale(fMat[kMScaleY], fMat[kMPersp2],
fMat[kMTransY], fMat[kMPersp1], scale); | |
836 inv->fMat[kMSkewX] = scross_dscale(fMat[kMTransX], fMat[kMPersp1],
fMat[kMSkewX], fMat[kMPersp2], scale); | |
837 inv->fMat[kMTransX] = scross_dscale(fMat[kMSkewX], fMat[kMTransY],
fMat[kMTransX], fMat[kMScaleY], scale); | |
838 | 872 |
839 inv->fMat[kMSkewY] = scross_dscale(fMat[kMTransY], fMat[kMPersp0],
fMat[kMSkewY], fMat[kMPersp2], scale); | 873 SkMatrix storage; |
840 inv->fMat[kMScaleY] = scross_dscale(fMat[kMScaleX], fMat[kMPersp2],
fMat[kMTransX], fMat[kMPersp0], scale); | 874 if (applyingInPlace || NULL == tmp) { |
841 inv->fMat[kMTransY] = scross_dscale(fMat[kMTransX], fMat[kMSkewY],
fMat[kMScaleX], fMat[kMTransY], scale); | 875 tmp = &storage; // we either need to avoid trampling memory or have
no memory |
| 876 } |
842 | 877 |
843 inv->fMat[kMPersp0] = scross_dscale(fMat[kMSkewY], fMat[kMPersp1],
fMat[kMScaleY], fMat[kMPersp0], scale); | 878 ComputeInv(tmp->fMat, fMat, invDet, isPersp); |
844 inv->fMat[kMPersp1] = scross_dscale(fMat[kMSkewX], fMat[kMPersp0],
fMat[kMScaleX], fMat[kMPersp1], scale); | 879 if (!tmp->isFinite()) { |
845 inv->fMat[kMPersp2] = scross_dscale(fMat[kMScaleX], fMat[kMScaleY],
fMat[kMSkewX], fMat[kMSkewY], scale); | 880 return false; |
846 } else { // not perspective | 881 } |
847 inv->fMat[kMScaleX] = SkDoubleToScalar(fMat[kMScaleY] * scale); | |
848 inv->fMat[kMSkewX] = SkDoubleToScalar(-fMat[kMSkewX] * scale); | |
849 inv->fMat[kMTransX] = dcross_dscale(fMat[kMSkewX], fMat[kMTransY], f
Mat[kMScaleY], fMat[kMTransX], scale); | |
850 | 882 |
851 inv->fMat[kMSkewY] = SkDoubleToScalar(-fMat[kMSkewY] * scale); | 883 tmp->setTypeMask(fTypeMask); |
852 inv->fMat[kMScaleY] = SkDoubleToScalar(fMat[kMScaleX] * scale); | |
853 inv->fMat[kMTransY] = dcross_dscale(fMat[kMSkewY], fMat[kMTransX], f
Mat[kMScaleX], fMat[kMTransY], scale); | |
854 | 884 |
855 inv->fMat[kMPersp0] = 0; | 885 if (applyingInPlace) { |
856 inv->fMat[kMPersp1] = 0; | 886 *inv = storage; // need to copy answer back |
857 inv->fMat[kMPersp2] = 1; | 887 } |
858 } | |
859 | 888 |
860 inv->setTypeMask(fTypeMask); | |
861 | |
862 if (inv == &tmp) { | |
863 *(SkMatrix*)this = tmp; | |
864 } | |
865 } | |
866 return true; | 889 return true; |
867 } | 890 } |
868 | 891 |
869 /////////////////////////////////////////////////////////////////////////////// | 892 /////////////////////////////////////////////////////////////////////////////// |
870 | 893 |
871 void SkMatrix::Identity_pts(const SkMatrix& m, SkPoint dst[], const SkPoint src[
], int count) { | 894 void SkMatrix::Identity_pts(const SkMatrix& m, SkPoint dst[], const SkPoint src[
], int count) { |
872 SkASSERT(m.getType() == 0); | 895 SkASSERT(m.getType() == 0); |
873 | 896 |
874 if (dst != src && count > 0) { | 897 if (dst != src && count > 0) { |
875 memcpy(dst, src, count * sizeof(SkPoint)); | 898 memcpy(dst, src, count * sizeof(SkPoint)); |
(...skipping 917 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1793 rotation1->fX = cos1; | 1816 rotation1->fX = cos1; |
1794 rotation1->fY = sin1; | 1817 rotation1->fY = sin1; |
1795 } | 1818 } |
1796 if (rotation2) { | 1819 if (rotation2) { |
1797 rotation2->fX = cos2; | 1820 rotation2->fX = cos2; |
1798 rotation2->fY = sin2; | 1821 rotation2->fY = sin2; |
1799 } | 1822 } |
1800 | 1823 |
1801 return true; | 1824 return true; |
1802 } | 1825 } |
OLD | NEW |