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(const SkScalar* src, SkScalar* dst, SkScalar scale, bo ol 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], scale); | |
795 dst[kMSkewX] = scross_dscale(src[kMTransX], src[kMPersp1], src[kMSkewX] , src[kMPersp2], scale); | |
796 dst[kMTransX] = scross_dscale(src[kMSkewX], src[kMTransY], src[kMTransX ], src[kMScaleY], scale); | |
797 | |
798 dst[kMSkewY] = scross_dscale(src[kMTransY], src[kMPersp0], src[kMSkewY] , src[kMPersp2], scale); | |
799 dst[kMScaleY] = scross_dscale(src[kMScaleX], src[kMPersp2], src[kMTransX ], src[kMPersp0], scale); | |
800 dst[kMTransY] = scross_dscale(src[kMTransX], src[kMSkewY], src[kMScaleX ], src[kMTransY], scale); | |
801 | |
802 dst[kMPersp0] = scross_dscale(src[kMSkewY], src[kMPersp1], src[kMScaleY ], src[kMPersp0], scale); | |
803 dst[kMPersp1] = scross_dscale(src[kMSkewX], src[kMPersp0], src[kMScaleX ], src[kMPersp1], scale); | |
804 dst[kMPersp2] = scross_dscale(src[kMScaleX], src[kMScaleY], src[kMSkewX] , src[kMSkewY], scale); | |
805 } else { // not perspective | |
806 dst[kMScaleX] = SkDoubleToScalar(src[kMScaleY] * scale); | |
807 dst[kMSkewX] = SkDoubleToScalar(-src[kMSkewX] * scale); | |
808 dst[kMTransX] = dcross_dscale(src[kMSkewX], src[kMTransY], src[kMScaleY] , src[kMTransX], scale); | |
809 | |
810 dst[kMSkewY] = SkDoubleToScalar(-src[kMSkewY] * scale); | |
811 dst[kMScaleY] = SkDoubleToScalar(src[kMScaleX] * scale); | |
812 dst[kMTransY] = dcross_dscale(src[kMSkewY], src[kMTransX], src[kMScaleX] , src[kMTransY], scale); | |
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 29 matching lines...) Expand all Loading... | |
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 scale = sk_inv_determinant(fMat, isPersp); |
823 | 864 |
824 if (scale == 0) { // underflow | 865 if (scale == 0) { // underflow |
825 return false; | 866 return false; |
826 } | 867 } |
827 | 868 |
828 if (inv) { | 869 // If the scale is close to the float min check the validity of the |
829 SkMatrix tmp; | 870 // inverse result regardless of if the actual result is requested |
830 if (inv == this) { | 871 bool checkInv = abs(scale) <= SK_ScalarSmallest; |
831 inv = &tmp; | |
832 } | |
833 | 872 |
834 if (isPersp) { | 873 if (!inv && !checkInv) { |
835 inv->fMat[kMScaleX] = scross_dscale(fMat[kMScaleY], fMat[kMPersp2], fMat[kMTransY], fMat[kMPersp1], scale); | 874 return true; // no reason to actually compute the inverse |
836 inv->fMat[kMSkewX] = scross_dscale(fMat[kMTransX], fMat[kMPersp1], fMat[kMSkewX], fMat[kMPersp2], scale); | 875 } |
837 inv->fMat[kMTransX] = scross_dscale(fMat[kMSkewX], fMat[kMTransY], fMat[kMTransX], fMat[kMScaleY], scale); | |
838 | 876 |
839 inv->fMat[kMSkewY] = scross_dscale(fMat[kMTransY], fMat[kMPersp0], fMat[kMSkewY], fMat[kMPersp2], scale); | 877 bool applyingInPlace = (inv == this); |
840 inv->fMat[kMScaleY] = scross_dscale(fMat[kMScaleX], fMat[kMPersp2], fMat[kMTransX], fMat[kMPersp0], scale); | |
841 inv->fMat[kMTransY] = scross_dscale(fMat[kMTransX], fMat[kMSkewY], fMat[kMScaleX], fMat[kMTransY], scale); | |
842 | 878 |
843 inv->fMat[kMPersp0] = scross_dscale(fMat[kMSkewY], fMat[kMPersp1], fMat[kMScaleY], fMat[kMPersp0], scale); | 879 SkMatrix* tmp = inv; |
844 inv->fMat[kMPersp1] = scross_dscale(fMat[kMSkewX], fMat[kMPersp0], fMat[kMScaleX], fMat[kMPersp1], scale); | |
845 inv->fMat[kMPersp2] = scross_dscale(fMat[kMScaleX], fMat[kMScaleY], fMat[kMSkewX], fMat[kMSkewY], scale); | |
846 } else { // not perspective | |
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 | 880 |
851 inv->fMat[kMSkewY] = SkDoubleToScalar(-fMat[kMSkewY] * scale); | 881 SkMatrix storage; |
852 inv->fMat[kMScaleY] = SkDoubleToScalar(fMat[kMScaleX] * scale); | 882 if (applyingInPlace || NULL == tmp) { |
853 inv->fMat[kMTransY] = dcross_dscale(fMat[kMSkewY], fMat[kMTransX], f Mat[kMScaleX], fMat[kMTransY], scale); | 883 tmp = &storage; // we either need to avoid trampling memory or have no memory |
884 } | |
854 | 885 |
855 inv->fMat[kMPersp0] = 0; | 886 ComputeInv(fMat, tmp->fMat, scale, isPersp); |
856 inv->fMat[kMPersp1] = 0; | 887 if (!tmp->isFinite()) { |
857 inv->fMat[kMPersp2] = 1; | 888 return false; |
858 } | 889 } |
859 | 890 |
860 inv->setTypeMask(fTypeMask); | 891 tmp->setTypeMask(fTypeMask); |
861 | 892 |
862 if (inv == &tmp) { | 893 if (applyingInPlace) { |
863 *(SkMatrix*)this = tmp; | 894 *(SkMatrix*)this = storage; // need to copy answer back |
reed1
2015/06/17 19:27:56
why the cast? why not
if (applyingInPlace) {
robertphillips
2015/06/17 19:44:46
Done. It was left over from the prior code.
| |
864 } | |
865 } | 895 } |
896 | |
866 return true; | 897 return true; |
867 } | 898 } |
868 | 899 |
869 /////////////////////////////////////////////////////////////////////////////// | 900 /////////////////////////////////////////////////////////////////////////////// |
870 | 901 |
871 void SkMatrix::Identity_pts(const SkMatrix& m, SkPoint dst[], const SkPoint src[ ], int count) { | 902 void SkMatrix::Identity_pts(const SkMatrix& m, SkPoint dst[], const SkPoint src[ ], int count) { |
872 SkASSERT(m.getType() == 0); | 903 SkASSERT(m.getType() == 0); |
873 | 904 |
874 if (dst != src && count > 0) { | 905 if (dst != src && count > 0) { |
875 memcpy(dst, src, count * sizeof(SkPoint)); | 906 memcpy(dst, src, count * sizeof(SkPoint)); |
(...skipping 917 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1793 rotation1->fX = cos1; | 1824 rotation1->fX = cos1; |
1794 rotation1->fY = sin1; | 1825 rotation1->fY = sin1; |
1795 } | 1826 } |
1796 if (rotation2) { | 1827 if (rotation2) { |
1797 rotation2->fX = cos2; | 1828 rotation2->fX = cos2; |
1798 rotation2->fY = sin2; | 1829 rotation2->fY = sin2; |
1799 } | 1830 } |
1800 | 1831 |
1801 return true; | 1832 return true; |
1802 } | 1833 } |
OLD | NEW |