@@ -717,6 +717,16 @@ static double sk_inv_determinant(const float mat[9], int isPerspective) {
717
717
return 1.0 / det;
718
718
}
719
719
720
+ bool SkMatrix::isFinite () const {
721
+ for (int i = 0 ; i < 9 ; ++i) {
722
+ if (!SkScalarIsFinite (fMat [i])) {
723
+ return false ;
724
+ }
725
+ }
726
+
727
+ return true ;
728
+ }
729
+
720
730
void SkMatrix::SetAffineIdentity (SkScalar affine[6 ]) {
721
731
affine[kAScaleX ] = 1 ;
722
732
affine[kASkewY ] = 0 ;
@@ -741,6 +751,37 @@ bool SkMatrix::asAffine(SkScalar affine[6]) const {
741
751
return true ;
742
752
}
743
753
754
+ void SkMatrix::ComputeInv (SkScalar dst[9 ], const SkScalar src[9 ], SkScalar invDet, bool isPersp) {
755
+ SkASSERT (src != dst);
756
+ SkASSERT (src && dst);
757
+
758
+ if (isPersp) {
759
+ dst[kMScaleX ] = scross_dscale (src[kMScaleY ], src[kMPersp2 ], src[kMTransY ], src[kMPersp1 ], invDet);
760
+ dst[kMSkewX ] = scross_dscale (src[kMTransX ], src[kMPersp1 ], src[kMSkewX ], src[kMPersp2 ], invDet);
761
+ dst[kMTransX ] = scross_dscale (src[kMSkewX ], src[kMTransY ], src[kMTransX ], src[kMScaleY ], invDet);
762
+
763
+ dst[kMSkewY ] = scross_dscale (src[kMTransY ], src[kMPersp0 ], src[kMSkewY ], src[kMPersp2 ], invDet);
764
+ dst[kMScaleY ] = scross_dscale (src[kMScaleX ], src[kMPersp2 ], src[kMTransX ], src[kMPersp0 ], invDet);
765
+ dst[kMTransY ] = scross_dscale (src[kMTransX ], src[kMSkewY ], src[kMScaleX ], src[kMTransY ], invDet);
766
+
767
+ dst[kMPersp0 ] = scross_dscale (src[kMSkewY ], src[kMPersp1 ], src[kMScaleY ], src[kMPersp0 ], invDet);
768
+ dst[kMPersp1 ] = scross_dscale (src[kMSkewX ], src[kMPersp0 ], src[kMScaleX ], src[kMPersp1 ], invDet);
769
+ dst[kMPersp2 ] = scross_dscale (src[kMScaleX ], src[kMScaleY ], src[kMSkewX ], src[kMSkewY ], invDet);
770
+ } else { // not perspective
771
+ dst[kMScaleX ] = SkDoubleToScalar (src[kMScaleY ] * invDet);
772
+ dst[kMSkewX ] = SkDoubleToScalar (-src[kMSkewX ] * invDet);
773
+ dst[kMTransX ] = dcross_dscale (src[kMSkewX ], src[kMTransY ], src[kMScaleY ], src[kMTransX ], invDet);
774
+
775
+ dst[kMSkewY ] = SkDoubleToScalar (-src[kMSkewY ] * invDet);
776
+ dst[kMScaleY ] = SkDoubleToScalar (src[kMScaleX ] * invDet);
777
+ dst[kMTransY ] = dcross_dscale (src[kMSkewY ], src[kMTransX ], src[kMScaleX ], src[kMTransY ], invDet);
778
+
779
+ dst[kMPersp0 ] = 0 ;
780
+ dst[kMPersp1 ] = 0 ;
781
+ dst[kMPersp2 ] = 1 ;
782
+ }
783
+ }
784
+
744
785
bool SkMatrix::invertNonIdentity (SkMatrix* inv) const {
745
786
SkASSERT (!this ->isIdentity ());
746
787
@@ -784,50 +825,32 @@ bool SkMatrix::invertNonIdentity(SkMatrix* inv) const {
784
825
}
785
826
786
827
int isPersp = mask & kPerspective_Mask ;
787
- double scale = sk_inv_determinant (fMat , isPersp);
828
+ double invDet = sk_inv_determinant (fMat , isPersp);
788
829
789
- if (scale == 0 ) { // underflow
830
+ if (invDet == 0 ) { // underflow
790
831
return false ;
791
832
}
792
833
793
- if (inv) {
794
- SkMatrix tmp;
795
- if (inv == this ) {
796
- inv = &tmp;
797
- }
834
+ bool applyingInPlace = (inv == this );
798
835
799
- if (isPersp) {
800
- inv->fMat [kMScaleX ] = scross_dscale (fMat [kMScaleY ], fMat [kMPersp2 ], fMat [kMTransY ], fMat [kMPersp1 ], scale);
801
- inv->fMat [kMSkewX ] = scross_dscale (fMat [kMTransX ], fMat [kMPersp1 ], fMat [kMSkewX ], fMat [kMPersp2 ], scale);
802
- inv->fMat [kMTransX ] = scross_dscale (fMat [kMSkewX ], fMat [kMTransY ], fMat [kMTransX ], fMat [kMScaleY ], scale);
803
-
804
- inv->fMat [kMSkewY ] = scross_dscale (fMat [kMTransY ], fMat [kMPersp0 ], fMat [kMSkewY ], fMat [kMPersp2 ], scale);
805
- inv->fMat [kMScaleY ] = scross_dscale (fMat [kMScaleX ], fMat [kMPersp2 ], fMat [kMTransX ], fMat [kMPersp0 ], scale);
806
- inv->fMat [kMTransY ] = scross_dscale (fMat [kMTransX ], fMat [kMSkewY ], fMat [kMScaleX ], fMat [kMTransY ], scale);
807
-
808
- inv->fMat [kMPersp0 ] = scross_dscale (fMat [kMSkewY ], fMat [kMPersp1 ], fMat [kMScaleY ], fMat [kMPersp0 ], scale);
809
- inv->fMat [kMPersp1 ] = scross_dscale (fMat [kMSkewX ], fMat [kMPersp0 ], fMat [kMScaleX ], fMat [kMPersp1 ], scale);
810
- inv->fMat [kMPersp2 ] = scross_dscale (fMat [kMScaleX ], fMat [kMScaleY ], fMat [kMSkewX ], fMat [kMSkewY ], scale);
811
- } else { // not perspective
812
- inv->fMat [kMScaleX ] = SkDoubleToScalar (fMat [kMScaleY ] * scale);
813
- inv->fMat [kMSkewX ] = SkDoubleToScalar (-fMat [kMSkewX ] * scale);
814
- inv->fMat [kMTransX ] = dcross_dscale (fMat [kMSkewX ], fMat [kMTransY ], fMat [kMScaleY ], fMat [kMTransX ], scale);
815
-
816
- inv->fMat [kMSkewY ] = SkDoubleToScalar (-fMat [kMSkewY ] * scale);
817
- inv->fMat [kMScaleY ] = SkDoubleToScalar (fMat [kMScaleX ] * scale);
818
- inv->fMat [kMTransY ] = dcross_dscale (fMat [kMSkewY ], fMat [kMTransX ], fMat [kMScaleX ], fMat [kMTransY ], scale);
819
-
820
- inv->fMat [kMPersp0 ] = 0 ;
821
- inv->fMat [kMPersp1 ] = 0 ;
822
- inv->fMat [kMPersp2 ] = 1 ;
823
- }
836
+ SkMatrix* tmp = inv;
837
+
838
+ SkMatrix storage;
839
+ if (applyingInPlace || NULL == tmp) {
840
+ tmp = &storage; // we either need to avoid trampling memory or have no memory
841
+ }
842
+
843
+ ComputeInv (tmp->fMat , fMat , invDet, isPersp);
844
+ if (!tmp->isFinite ()) {
845
+ return false ;
846
+ }
824
847
825
- inv ->setTypeMask (fTypeMask );
848
+ tmp ->setTypeMask (fTypeMask );
826
849
827
- if (inv == &tmp) {
828
- *(SkMatrix*)this = tmp;
829
- }
850
+ if (applyingInPlace) {
851
+ *inv = storage; // need to copy answer back
830
852
}
853
+
831
854
return true ;
832
855
}
833
856
0 commit comments