LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/core - SkMatrix44.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 16 641 2.5 %
Date: 2017-07-14 16:53:18 Functions: 2 50 4.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2011 Google Inc.
       3             :  *
       4             :  * Use of this source code is governed by a BSD-style license that can be
       5             :  * found in the LICENSE file.
       6             :  */
       7             : 
       8             : #include "SkMatrix44.h"
       9             : 
      10           0 : static inline bool eq4(const SkMScalar* SK_RESTRICT a,
      11             :                       const SkMScalar* SK_RESTRICT b) {
      12           0 :     return (a[0] == b[0]) & (a[1] == b[1]) & (a[2] == b[2]) & (a[3] == b[3]);
      13             : }
      14             : 
      15           0 : bool SkMatrix44::operator==(const SkMatrix44& other) const {
      16           0 :     if (this == &other) {
      17           0 :         return true;
      18             :     }
      19             : 
      20           0 :     if (this->isTriviallyIdentity() && other.isTriviallyIdentity()) {
      21           0 :         return true;
      22             :     }
      23             : 
      24           0 :     const SkMScalar* SK_RESTRICT a = &fMat[0][0];
      25           0 :     const SkMScalar* SK_RESTRICT b = &other.fMat[0][0];
      26             : 
      27             : #if 0
      28             :     for (int i = 0; i < 16; ++i) {
      29             :         if (a[i] != b[i]) {
      30             :             return false;
      31             :         }
      32             :     }
      33             :     return true;
      34             : #else
      35             :     // to reduce branch instructions, we compare 4 at a time.
      36             :     // see bench/Matrix44Bench.cpp for test.
      37           0 :     if (!eq4(&a[0], &b[0])) {
      38           0 :         return false;
      39             :     }
      40           0 :     if (!eq4(&a[4], &b[4])) {
      41           0 :         return false;
      42             :     }
      43           0 :     if (!eq4(&a[8], &b[8])) {
      44           0 :         return false;
      45             :     }
      46           0 :     return eq4(&a[12], &b[12]);
      47             : #endif
      48             : }
      49             : 
      50             : ///////////////////////////////////////////////////////////////////////////////
      51             : 
      52           1 : int SkMatrix44::computeTypeMask() const {
      53           1 :     unsigned mask = 0;
      54             : 
      55           1 :     if (0 != perspX() || 0 != perspY() || 0 != perspZ() || 1 != fMat[3][3]) {
      56           0 :         return kTranslate_Mask | kScale_Mask | kAffine_Mask | kPerspective_Mask;
      57             :     }
      58             : 
      59           1 :     if (0 != transX() || 0 != transY() || 0 != transZ()) {
      60           0 :         mask |= kTranslate_Mask;
      61             :     }
      62             : 
      63           1 :     if (1 != scaleX() || 1 != scaleY() || 1 != scaleZ()) {
      64           1 :         mask |= kScale_Mask;
      65             :     }
      66             : 
      67           1 :     if (0 != fMat[1][0] || 0 != fMat[0][1] || 0 != fMat[0][2] ||
      68           0 :         0 != fMat[2][0] || 0 != fMat[1][2] || 0 != fMat[2][1]) {
      69           1 :             mask |= kAffine_Mask;
      70             :     }
      71             : 
      72           1 :     return mask;
      73             : }
      74             : 
      75             : ///////////////////////////////////////////////////////////////////////////////
      76             : 
      77           0 : void SkMatrix44::asColMajorf(float dst[]) const {
      78           0 :     const SkMScalar* src = &fMat[0][0];
      79             : #ifdef SK_MSCALAR_IS_DOUBLE
      80             :     for (int i = 0; i < 16; ++i) {
      81             :         dst[i] = SkMScalarToFloat(src[i]);
      82             :     }
      83             : #elif defined SK_MSCALAR_IS_FLOAT
      84           0 :     memcpy(dst, src, 16 * sizeof(float));
      85             : #endif
      86           0 : }
      87             : 
      88           0 : void SkMatrix44::as3x4RowMajorf(float dst[]) const {
      89           0 :     dst[0] = fMat[0][0]; dst[1] = fMat[1][0]; dst[2]  = fMat[2][0]; dst[3]  = fMat[3][0];
      90           0 :     dst[4] = fMat[0][1]; dst[5] = fMat[1][1]; dst[6]  = fMat[2][1]; dst[7]  = fMat[3][1];
      91           0 :     dst[8] = fMat[0][2]; dst[9] = fMat[1][2]; dst[10] = fMat[2][2]; dst[11] = fMat[3][2];
      92           0 : }
      93             : 
      94           0 : void SkMatrix44::asColMajord(double dst[]) const {
      95           0 :     const SkMScalar* src = &fMat[0][0];
      96             : #ifdef SK_MSCALAR_IS_DOUBLE
      97             :     memcpy(dst, src, 16 * sizeof(double));
      98             : #elif defined SK_MSCALAR_IS_FLOAT
      99           0 :     for (int i = 0; i < 16; ++i) {
     100           0 :         dst[i] = SkMScalarToDouble(src[i]);
     101             :     }
     102             : #endif
     103           0 : }
     104             : 
     105           0 : void SkMatrix44::asRowMajorf(float dst[]) const {
     106           0 :     const SkMScalar* src = &fMat[0][0];
     107           0 :     for (int i = 0; i < 4; ++i) {
     108           0 :         dst[0] = SkMScalarToFloat(src[0]);
     109           0 :         dst[4] = SkMScalarToFloat(src[1]);
     110           0 :         dst[8] = SkMScalarToFloat(src[2]);
     111           0 :         dst[12] = SkMScalarToFloat(src[3]);
     112           0 :         src += 4;
     113           0 :         dst += 1;
     114             :     }
     115           0 : }
     116             : 
     117           0 : void SkMatrix44::asRowMajord(double dst[]) const {
     118           0 :     const SkMScalar* src = &fMat[0][0];
     119           0 :     for (int i = 0; i < 4; ++i) {
     120           0 :         dst[0] = SkMScalarToDouble(src[0]);
     121           0 :         dst[4] = SkMScalarToDouble(src[1]);
     122           0 :         dst[8] = SkMScalarToDouble(src[2]);
     123           0 :         dst[12] = SkMScalarToDouble(src[3]);
     124           0 :         src += 4;
     125           0 :         dst += 1;
     126             :     }
     127           0 : }
     128             : 
     129           0 : void SkMatrix44::setColMajorf(const float src[]) {
     130           0 :     SkMScalar* dst = &fMat[0][0];
     131             : #ifdef SK_MSCALAR_IS_DOUBLE
     132             :     for (int i = 0; i < 16; ++i) {
     133             :         dst[i] = SkMScalarToFloat(src[i]);
     134             :     }
     135             : #elif defined SK_MSCALAR_IS_FLOAT
     136           0 :     memcpy(dst, src, 16 * sizeof(float));
     137             : #endif
     138             : 
     139           0 :     this->dirtyTypeMask();
     140           0 : }
     141             : 
     142           0 : void SkMatrix44::setColMajord(const double src[]) {
     143           0 :     SkMScalar* dst = &fMat[0][0];
     144             : #ifdef SK_MSCALAR_IS_DOUBLE
     145             :     memcpy(dst, src, 16 * sizeof(double));
     146             : #elif defined SK_MSCALAR_IS_FLOAT
     147           0 :     for (int i = 0; i < 16; ++i) {
     148           0 :         dst[i] = SkDoubleToMScalar(src[i]);
     149             :     }
     150             : #endif
     151             : 
     152           0 :     this->dirtyTypeMask();
     153           0 : }
     154             : 
     155           0 : void SkMatrix44::setRowMajorf(const float src[]) {
     156           0 :     SkMScalar* dst = &fMat[0][0];
     157           0 :     for (int i = 0; i < 4; ++i) {
     158           0 :         dst[0] = SkMScalarToFloat(src[0]);
     159           0 :         dst[4] = SkMScalarToFloat(src[1]);
     160           0 :         dst[8] = SkMScalarToFloat(src[2]);
     161           0 :         dst[12] = SkMScalarToFloat(src[3]);
     162           0 :         src += 4;
     163           0 :         dst += 1;
     164             :     }
     165           0 :     this->dirtyTypeMask();
     166           0 : }
     167             : 
     168           0 : void SkMatrix44::setRowMajord(const double src[]) {
     169           0 :     SkMScalar* dst = &fMat[0][0];
     170           0 :     for (int i = 0; i < 4; ++i) {
     171           0 :         dst[0] = SkDoubleToMScalar(src[0]);
     172           0 :         dst[4] = SkDoubleToMScalar(src[1]);
     173           0 :         dst[8] = SkDoubleToMScalar(src[2]);
     174           0 :         dst[12] = SkDoubleToMScalar(src[3]);
     175           0 :         src += 4;
     176           0 :         dst += 1;
     177             :     }
     178           0 :     this->dirtyTypeMask();
     179           0 : }
     180             : 
     181             : ///////////////////////////////////////////////////////////////////////////////
     182             : 
     183           0 : const SkMatrix44& SkMatrix44::I() {
     184             :     static constexpr SkMatrix44 gIdentity44(kIdentity_Constructor);
     185           0 :     return gIdentity44;
     186             : }
     187             : 
     188           0 : void SkMatrix44::setIdentity() {
     189           0 :     fMat[0][0] = 1;
     190           0 :     fMat[0][1] = 0;
     191           0 :     fMat[0][2] = 0;
     192           0 :     fMat[0][3] = 0;
     193           0 :     fMat[1][0] = 0;
     194           0 :     fMat[1][1] = 1;
     195           0 :     fMat[1][2] = 0;
     196           0 :     fMat[1][3] = 0;
     197           0 :     fMat[2][0] = 0;
     198           0 :     fMat[2][1] = 0;
     199           0 :     fMat[2][2] = 1;
     200           0 :     fMat[2][3] = 0;
     201           0 :     fMat[3][0] = 0;
     202           0 :     fMat[3][1] = 0;
     203           0 :     fMat[3][2] = 0;
     204           0 :     fMat[3][3] = 1;
     205           0 :     this->setTypeMask(kIdentity_Mask);
     206           0 : }
     207             : 
     208           0 : void SkMatrix44::set3x3(SkMScalar m00, SkMScalar m01, SkMScalar m02,
     209             :                         SkMScalar m10, SkMScalar m11, SkMScalar m12,
     210             :                         SkMScalar m20, SkMScalar m21, SkMScalar m22) {
     211           0 :     fMat[0][0] = m00; fMat[0][1] = m01; fMat[0][2] = m02; fMat[0][3] = 0;
     212           0 :     fMat[1][0] = m10; fMat[1][1] = m11; fMat[1][2] = m12; fMat[1][3] = 0;
     213           0 :     fMat[2][0] = m20; fMat[2][1] = m21; fMat[2][2] = m22; fMat[2][3] = 0;
     214           0 :     fMat[3][0] = 0;   fMat[3][1] = 0;   fMat[3][2] = 0;   fMat[3][3] = 1;
     215           0 :     this->dirtyTypeMask();
     216           0 : }
     217             : 
     218           1 : void SkMatrix44::set3x3RowMajorf(const float src[]) {
     219           1 :     fMat[0][0] = src[0]; fMat[0][1] = src[3]; fMat[0][2] = src[6]; fMat[0][3] = 0;
     220           1 :     fMat[1][0] = src[1]; fMat[1][1] = src[4]; fMat[1][2] = src[7]; fMat[1][3] = 0;
     221           1 :     fMat[2][0] = src[2]; fMat[2][1] = src[5]; fMat[2][2] = src[8]; fMat[2][3] = 0;
     222           1 :     fMat[3][0] = 0;      fMat[3][1] = 0;      fMat[3][2] = 0;      fMat[3][3] = 1;
     223           1 :     this->dirtyTypeMask();
     224           1 : }
     225             : 
     226           0 : void SkMatrix44::set3x4RowMajorf(const float src[]) {
     227           0 :     fMat[0][0] = src[0]; fMat[1][0] = src[1]; fMat[2][0] = src[2];  fMat[3][0] = src[3];
     228           0 :     fMat[0][1] = src[4]; fMat[1][1] = src[5]; fMat[2][1] = src[6];  fMat[3][1] = src[7];
     229           0 :     fMat[0][2] = src[8]; fMat[1][2] = src[9]; fMat[2][2] = src[10]; fMat[3][2] = src[11];
     230           0 :     fMat[0][3] = 0;      fMat[1][3] = 0;      fMat[2][3] = 0;       fMat[3][3] = 1;
     231           0 :     this->dirtyTypeMask();
     232           0 : }
     233             : 
     234             : ///////////////////////////////////////////////////////////////////////////////
     235             : 
     236           0 : void SkMatrix44::setTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz) {
     237           0 :     this->setIdentity();
     238             : 
     239           0 :     if (!dx && !dy && !dz) {
     240           0 :         return;
     241             :     }
     242             : 
     243           0 :     fMat[3][0] = dx;
     244           0 :     fMat[3][1] = dy;
     245           0 :     fMat[3][2] = dz;
     246           0 :     this->setTypeMask(kTranslate_Mask);
     247             : }
     248             : 
     249           0 : void SkMatrix44::preTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz) {
     250           0 :     if (!dx && !dy && !dz) {
     251           0 :         return;
     252             :     }
     253             : 
     254           0 :     for (int i = 0; i < 4; ++i) {
     255           0 :         fMat[3][i] = fMat[0][i] * dx + fMat[1][i] * dy + fMat[2][i] * dz + fMat[3][i];
     256             :     }
     257           0 :     this->dirtyTypeMask();
     258             : }
     259             : 
     260           0 : void SkMatrix44::postTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz) {
     261           0 :     if (!dx && !dy && !dz) {
     262           0 :         return;
     263             :     }
     264             : 
     265           0 :     if (this->getType() & kPerspective_Mask) {
     266           0 :         for (int i = 0; i < 4; ++i) {
     267           0 :             fMat[i][0] += fMat[i][3] * dx;
     268           0 :             fMat[i][1] += fMat[i][3] * dy;
     269           0 :             fMat[i][2] += fMat[i][3] * dz;
     270             :         }
     271             :     } else {
     272           0 :         fMat[3][0] += dx;
     273           0 :         fMat[3][1] += dy;
     274           0 :         fMat[3][2] += dz;
     275           0 :         this->dirtyTypeMask();
     276             :     }
     277             : }
     278             : 
     279             : ///////////////////////////////////////////////////////////////////////////////
     280             : 
     281           0 : void SkMatrix44::setScale(SkMScalar sx, SkMScalar sy, SkMScalar sz) {
     282           0 :     this->setIdentity();
     283             : 
     284           0 :     if (1 == sx && 1 == sy && 1 == sz) {
     285           0 :         return;
     286             :     }
     287             : 
     288           0 :     fMat[0][0] = sx;
     289           0 :     fMat[1][1] = sy;
     290           0 :     fMat[2][2] = sz;
     291           0 :     this->setTypeMask(kScale_Mask);
     292             : }
     293             : 
     294           0 : void SkMatrix44::preScale(SkMScalar sx, SkMScalar sy, SkMScalar sz) {
     295           0 :     if (1 == sx && 1 == sy && 1 == sz) {
     296           0 :         return;
     297             :     }
     298             : 
     299             :     // The implementation matrix * pureScale can be shortcut
     300             :     // by knowing that pureScale components effectively scale
     301             :     // the columns of the original matrix.
     302           0 :     for (int i = 0; i < 4; i++) {
     303           0 :         fMat[0][i] *= sx;
     304           0 :         fMat[1][i] *= sy;
     305           0 :         fMat[2][i] *= sz;
     306             :     }
     307           0 :     this->dirtyTypeMask();
     308             : }
     309             : 
     310           0 : void SkMatrix44::postScale(SkMScalar sx, SkMScalar sy, SkMScalar sz) {
     311           0 :     if (1 == sx && 1 == sy && 1 == sz) {
     312           0 :         return;
     313             :     }
     314             : 
     315           0 :     for (int i = 0; i < 4; i++) {
     316           0 :         fMat[i][0] *= sx;
     317           0 :         fMat[i][1] *= sy;
     318           0 :         fMat[i][2] *= sz;
     319             :     }
     320           0 :     this->dirtyTypeMask();
     321             : }
     322             : 
     323             : ///////////////////////////////////////////////////////////////////////////////
     324             : 
     325           0 : void SkMatrix44::setRotateAbout(SkMScalar x, SkMScalar y, SkMScalar z,
     326             :                                 SkMScalar radians) {
     327           0 :     double len2 = (double)x * x + (double)y * y + (double)z * z;
     328           0 :     if (1 != len2) {
     329           0 :         if (0 == len2) {
     330           0 :             this->setIdentity();
     331           0 :             return;
     332             :         }
     333           0 :         double scale = 1 / sqrt(len2);
     334           0 :         x = SkDoubleToMScalar(x * scale);
     335           0 :         y = SkDoubleToMScalar(y * scale);
     336           0 :         z = SkDoubleToMScalar(z * scale);
     337             :     }
     338           0 :     this->setRotateAboutUnit(x, y, z, radians);
     339             : }
     340             : 
     341           0 : void SkMatrix44::setRotateAboutUnit(SkMScalar x, SkMScalar y, SkMScalar z,
     342             :                                     SkMScalar radians) {
     343           0 :     double c = cos(radians);
     344           0 :     double s = sin(radians);
     345           0 :     double C = 1 - c;
     346           0 :     double xs = x * s;
     347           0 :     double ys = y * s;
     348           0 :     double zs = z * s;
     349           0 :     double xC = x * C;
     350           0 :     double yC = y * C;
     351           0 :     double zC = z * C;
     352           0 :     double xyC = x * yC;
     353           0 :     double yzC = y * zC;
     354           0 :     double zxC = z * xC;
     355             : 
     356             :     // if you're looking at wikipedia, remember that we're column major.
     357           0 :     this->set3x3(SkDoubleToMScalar(x * xC + c),     // scale x
     358             :                  SkDoubleToMScalar(xyC + zs),       // skew x
     359             :                  SkDoubleToMScalar(zxC - ys),       // trans x
     360             : 
     361             :                  SkDoubleToMScalar(xyC - zs),       // skew y
     362           0 :                  SkDoubleToMScalar(y * yC + c),     // scale y
     363             :                  SkDoubleToMScalar(yzC + xs),       // trans y
     364             : 
     365             :                  SkDoubleToMScalar(zxC + ys),       // persp x
     366             :                  SkDoubleToMScalar(yzC - xs),       // persp y
     367           0 :                  SkDoubleToMScalar(z * zC + c));    // persp 2
     368           0 : }
     369             : 
     370             : ///////////////////////////////////////////////////////////////////////////////
     371             : 
     372           0 : static bool bits_isonly(int value, int mask) {
     373           0 :     return 0 == (value & ~mask);
     374             : }
     375             : 
     376           0 : void SkMatrix44::setConcat(const SkMatrix44& a, const SkMatrix44& b) {
     377           0 :     const SkMatrix44::TypeMask a_mask = a.getType();
     378           0 :     const SkMatrix44::TypeMask b_mask = b.getType();
     379             : 
     380           0 :     if (kIdentity_Mask == a_mask) {
     381           0 :         *this = b;
     382           0 :         return;
     383             :     }
     384           0 :     if (kIdentity_Mask == b_mask) {
     385           0 :         *this = a;
     386           0 :         return;
     387             :     }
     388             : 
     389           0 :     bool useStorage = (this == &a || this == &b);
     390             :     SkMScalar storage[16];
     391           0 :     SkMScalar* result = useStorage ? storage : &fMat[0][0];
     392             : 
     393             :     // Both matrices are at most scale+translate
     394           0 :     if (bits_isonly(a_mask | b_mask, kScale_Mask | kTranslate_Mask)) {
     395           0 :         result[0] = a.fMat[0][0] * b.fMat[0][0];
     396           0 :         result[1] = result[2] = result[3] = result[4] = 0;
     397           0 :         result[5] = a.fMat[1][1] * b.fMat[1][1];
     398           0 :         result[6] = result[7] = result[8] = result[9] = 0;
     399           0 :         result[10] = a.fMat[2][2] * b.fMat[2][2];
     400           0 :         result[11] = 0;
     401           0 :         result[12] = a.fMat[0][0] * b.fMat[3][0] + a.fMat[3][0];
     402           0 :         result[13] = a.fMat[1][1] * b.fMat[3][1] + a.fMat[3][1];
     403           0 :         result[14] = a.fMat[2][2] * b.fMat[3][2] + a.fMat[3][2];
     404           0 :         result[15] = 1;
     405             :     } else {
     406           0 :         for (int j = 0; j < 4; j++) {
     407           0 :             for (int i = 0; i < 4; i++) {
     408           0 :                 double value = 0;
     409           0 :                 for (int k = 0; k < 4; k++) {
     410           0 :                     value += SkMScalarToDouble(a.fMat[k][i]) * b.fMat[j][k];
     411             :                 }
     412           0 :                 *result++ = SkDoubleToMScalar(value);
     413             :             }
     414             :         }
     415             :     }
     416             : 
     417           0 :     if (useStorage) {
     418           0 :         memcpy(fMat, storage, sizeof(storage));
     419             :     }
     420           0 :     this->dirtyTypeMask();
     421             : }
     422             : 
     423             : ///////////////////////////////////////////////////////////////////////////////
     424             : 
     425             : /** We always perform the calculation in doubles, to avoid prematurely losing
     426             :     precision along the way. This relies on the compiler automatically
     427             :     promoting our SkMScalar values to double (if needed).
     428             :  */
     429           0 : double SkMatrix44::determinant() const {
     430           0 :     if (this->isIdentity()) {
     431           0 :         return 1;
     432             :     }
     433           0 :     if (this->isScaleTranslate()) {
     434           0 :         return fMat[0][0] * fMat[1][1] * fMat[2][2] * fMat[3][3];
     435             :     }
     436             : 
     437           0 :     double a00 = fMat[0][0];
     438           0 :     double a01 = fMat[0][1];
     439           0 :     double a02 = fMat[0][2];
     440           0 :     double a03 = fMat[0][3];
     441           0 :     double a10 = fMat[1][0];
     442           0 :     double a11 = fMat[1][1];
     443           0 :     double a12 = fMat[1][2];
     444           0 :     double a13 = fMat[1][3];
     445           0 :     double a20 = fMat[2][0];
     446           0 :     double a21 = fMat[2][1];
     447           0 :     double a22 = fMat[2][2];
     448           0 :     double a23 = fMat[2][3];
     449           0 :     double a30 = fMat[3][0];
     450           0 :     double a31 = fMat[3][1];
     451           0 :     double a32 = fMat[3][2];
     452           0 :     double a33 = fMat[3][3];
     453             : 
     454           0 :     double b00 = a00 * a11 - a01 * a10;
     455           0 :     double b01 = a00 * a12 - a02 * a10;
     456           0 :     double b02 = a00 * a13 - a03 * a10;
     457           0 :     double b03 = a01 * a12 - a02 * a11;
     458           0 :     double b04 = a01 * a13 - a03 * a11;
     459           0 :     double b05 = a02 * a13 - a03 * a12;
     460           0 :     double b06 = a20 * a31 - a21 * a30;
     461           0 :     double b07 = a20 * a32 - a22 * a30;
     462           0 :     double b08 = a20 * a33 - a23 * a30;
     463           0 :     double b09 = a21 * a32 - a22 * a31;
     464           0 :     double b10 = a21 * a33 - a23 * a31;
     465           0 :     double b11 = a22 * a33 - a23 * a32;
     466             : 
     467             :     // Calculate the determinant
     468           0 :     return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
     469             : }
     470             : 
     471             : ///////////////////////////////////////////////////////////////////////////////
     472             : 
     473           0 : static bool is_matrix_finite(const SkMatrix44& matrix) {
     474           0 :     SkMScalar accumulator = 0;
     475           0 :     for (int row = 0; row < 4; ++row) {
     476           0 :         for (int col = 0; col < 4; ++col) {
     477           0 :             accumulator *= matrix.get(row, col);
     478             :         }
     479             :     }
     480           0 :     return accumulator == 0;
     481             : }
     482             : 
     483           0 : bool SkMatrix44::invert(SkMatrix44* storage) const {
     484           0 :     if (this->isIdentity()) {
     485           0 :         if (storage) {
     486           0 :             storage->setIdentity();
     487             :         }
     488           0 :         return true;
     489             :     }
     490             : 
     491           0 :     if (this->isTranslate()) {
     492           0 :         if (storage) {
     493           0 :             storage->setTranslate(-fMat[3][0], -fMat[3][1], -fMat[3][2]);
     494             :         }
     495           0 :         return true;
     496             :     }
     497             : 
     498           0 :     SkMatrix44 tmp(kUninitialized_Constructor);
     499             :     // Use storage if it's available and distinct from this matrix.
     500           0 :     SkMatrix44* inverse = (storage && storage != this) ? storage : &tmp;
     501           0 :     if (this->isScaleTranslate()) {
     502           0 :         if (0 == fMat[0][0] * fMat[1][1] * fMat[2][2]) {
     503           0 :             return false;
     504             :         }
     505             : 
     506           0 :         double invXScale = 1 / fMat[0][0];
     507           0 :         double invYScale = 1 / fMat[1][1];
     508           0 :         double invZScale = 1 / fMat[2][2];
     509             : 
     510           0 :         inverse->fMat[0][0] = SkDoubleToMScalar(invXScale);
     511           0 :         inverse->fMat[0][1] = 0;
     512           0 :         inverse->fMat[0][2] = 0;
     513           0 :         inverse->fMat[0][3] = 0;
     514             : 
     515           0 :         inverse->fMat[1][0] = 0;
     516           0 :         inverse->fMat[1][1] = SkDoubleToMScalar(invYScale);
     517           0 :         inverse->fMat[1][2] = 0;
     518           0 :         inverse->fMat[1][3] = 0;
     519             : 
     520           0 :         inverse->fMat[2][0] = 0;
     521           0 :         inverse->fMat[2][1] = 0;
     522           0 :         inverse->fMat[2][2] = SkDoubleToMScalar(invZScale);
     523           0 :         inverse->fMat[2][3] = 0;
     524             : 
     525           0 :         inverse->fMat[3][0] = SkDoubleToMScalar(-fMat[3][0] * invXScale);
     526           0 :         inverse->fMat[3][1] = SkDoubleToMScalar(-fMat[3][1] * invYScale);
     527           0 :         inverse->fMat[3][2] = SkDoubleToMScalar(-fMat[3][2] * invZScale);
     528           0 :         inverse->fMat[3][3] = 1;
     529             : 
     530           0 :         inverse->setTypeMask(this->getType());
     531             : 
     532           0 :         if (!is_matrix_finite(*inverse)) {
     533           0 :             return false;
     534             :         }
     535           0 :         if (storage && inverse != storage) {
     536           0 :             *storage = *inverse;
     537             :         }
     538           0 :         return true;
     539             :     }
     540             : 
     541           0 :     double a00 = fMat[0][0];
     542           0 :     double a01 = fMat[0][1];
     543           0 :     double a02 = fMat[0][2];
     544           0 :     double a03 = fMat[0][3];
     545           0 :     double a10 = fMat[1][0];
     546           0 :     double a11 = fMat[1][1];
     547           0 :     double a12 = fMat[1][2];
     548           0 :     double a13 = fMat[1][3];
     549           0 :     double a20 = fMat[2][0];
     550           0 :     double a21 = fMat[2][1];
     551           0 :     double a22 = fMat[2][2];
     552           0 :     double a23 = fMat[2][3];
     553           0 :     double a30 = fMat[3][0];
     554           0 :     double a31 = fMat[3][1];
     555           0 :     double a32 = fMat[3][2];
     556           0 :     double a33 = fMat[3][3];
     557             : 
     558           0 :     if (!(this->getType() & kPerspective_Mask)) {
     559             :         // If we know the matrix has no perspective, then the perspective
     560             :         // component is (0, 0, 0, 1). We can use this information to save a lot
     561             :         // of arithmetic that would otherwise be spent to compute the inverse
     562             :         // of a general matrix.
     563             : 
     564           0 :         SkASSERT(a03 == 0);
     565           0 :         SkASSERT(a13 == 0);
     566           0 :         SkASSERT(a23 == 0);
     567           0 :         SkASSERT(a33 == 1);
     568             : 
     569           0 :         double b00 = a00 * a11 - a01 * a10;
     570           0 :         double b01 = a00 * a12 - a02 * a10;
     571           0 :         double b03 = a01 * a12 - a02 * a11;
     572           0 :         double b06 = a20 * a31 - a21 * a30;
     573           0 :         double b07 = a20 * a32 - a22 * a30;
     574           0 :         double b08 = a20;
     575           0 :         double b09 = a21 * a32 - a22 * a31;
     576           0 :         double b10 = a21;
     577           0 :         double b11 = a22;
     578             : 
     579             :         // Calculate the determinant
     580           0 :         double det = b00 * b11 - b01 * b10 + b03 * b08;
     581             : 
     582           0 :         double invdet = 1.0 / det;
     583             :         // If det is zero, we want to return false. However, we also want to return false
     584             :         // if 1/det overflows to infinity (i.e. det is denormalized). Both of these are
     585             :         // handled by checking that 1/det is finite.
     586           0 :         if (!sk_float_isfinite(invdet)) {
     587           0 :             return false;
     588             :         }
     589             : 
     590           0 :         b00 *= invdet;
     591           0 :         b01 *= invdet;
     592           0 :         b03 *= invdet;
     593           0 :         b06 *= invdet;
     594           0 :         b07 *= invdet;
     595           0 :         b08 *= invdet;
     596           0 :         b09 *= invdet;
     597           0 :         b10 *= invdet;
     598           0 :         b11 *= invdet;
     599             : 
     600           0 :         inverse->fMat[0][0] = SkDoubleToMScalar(a11 * b11 - a12 * b10);
     601           0 :         inverse->fMat[0][1] = SkDoubleToMScalar(a02 * b10 - a01 * b11);
     602           0 :         inverse->fMat[0][2] = SkDoubleToMScalar(b03);
     603           0 :         inverse->fMat[0][3] = 0;
     604           0 :         inverse->fMat[1][0] = SkDoubleToMScalar(a12 * b08 - a10 * b11);
     605           0 :         inverse->fMat[1][1] = SkDoubleToMScalar(a00 * b11 - a02 * b08);
     606           0 :         inverse->fMat[1][2] = SkDoubleToMScalar(-b01);
     607           0 :         inverse->fMat[1][3] = 0;
     608           0 :         inverse->fMat[2][0] = SkDoubleToMScalar(a10 * b10 - a11 * b08);
     609           0 :         inverse->fMat[2][1] = SkDoubleToMScalar(a01 * b08 - a00 * b10);
     610           0 :         inverse->fMat[2][2] = SkDoubleToMScalar(b00);
     611           0 :         inverse->fMat[2][3] = 0;
     612           0 :         inverse->fMat[3][0] = SkDoubleToMScalar(a11 * b07 - a10 * b09 - a12 * b06);
     613           0 :         inverse->fMat[3][1] = SkDoubleToMScalar(a00 * b09 - a01 * b07 + a02 * b06);
     614           0 :         inverse->fMat[3][2] = SkDoubleToMScalar(a31 * b01 - a30 * b03 - a32 * b00);
     615           0 :         inverse->fMat[3][3] = 1;
     616             : 
     617           0 :         inverse->setTypeMask(this->getType());
     618           0 :         if (!is_matrix_finite(*inverse)) {
     619           0 :             return false;
     620             :         }
     621           0 :         if (storage && inverse != storage) {
     622           0 :             *storage = *inverse;
     623             :         }
     624           0 :         return true;
     625             :     }
     626             : 
     627           0 :     double b00 = a00 * a11 - a01 * a10;
     628           0 :     double b01 = a00 * a12 - a02 * a10;
     629           0 :     double b02 = a00 * a13 - a03 * a10;
     630           0 :     double b03 = a01 * a12 - a02 * a11;
     631           0 :     double b04 = a01 * a13 - a03 * a11;
     632           0 :     double b05 = a02 * a13 - a03 * a12;
     633           0 :     double b06 = a20 * a31 - a21 * a30;
     634           0 :     double b07 = a20 * a32 - a22 * a30;
     635           0 :     double b08 = a20 * a33 - a23 * a30;
     636           0 :     double b09 = a21 * a32 - a22 * a31;
     637           0 :     double b10 = a21 * a33 - a23 * a31;
     638           0 :     double b11 = a22 * a33 - a23 * a32;
     639             : 
     640             :     // Calculate the determinant
     641           0 :     double det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
     642             : 
     643           0 :     double invdet = 1.0 / det;
     644             :     // If det is zero, we want to return false. However, we also want to return false
     645             :     // if 1/det overflows to infinity (i.e. det is denormalized). Both of these are
     646             :     // handled by checking that 1/det is finite.
     647           0 :     if (!sk_float_isfinite(invdet)) {
     648           0 :         return false;
     649             :     }
     650             : 
     651           0 :     b00 *= invdet;
     652           0 :     b01 *= invdet;
     653           0 :     b02 *= invdet;
     654           0 :     b03 *= invdet;
     655           0 :     b04 *= invdet;
     656           0 :     b05 *= invdet;
     657           0 :     b06 *= invdet;
     658           0 :     b07 *= invdet;
     659           0 :     b08 *= invdet;
     660           0 :     b09 *= invdet;
     661           0 :     b10 *= invdet;
     662           0 :     b11 *= invdet;
     663             : 
     664           0 :     inverse->fMat[0][0] = SkDoubleToMScalar(a11 * b11 - a12 * b10 + a13 * b09);
     665           0 :     inverse->fMat[0][1] = SkDoubleToMScalar(a02 * b10 - a01 * b11 - a03 * b09);
     666           0 :     inverse->fMat[0][2] = SkDoubleToMScalar(a31 * b05 - a32 * b04 + a33 * b03);
     667           0 :     inverse->fMat[0][3] = SkDoubleToMScalar(a22 * b04 - a21 * b05 - a23 * b03);
     668           0 :     inverse->fMat[1][0] = SkDoubleToMScalar(a12 * b08 - a10 * b11 - a13 * b07);
     669           0 :     inverse->fMat[1][1] = SkDoubleToMScalar(a00 * b11 - a02 * b08 + a03 * b07);
     670           0 :     inverse->fMat[1][2] = SkDoubleToMScalar(a32 * b02 - a30 * b05 - a33 * b01);
     671           0 :     inverse->fMat[1][3] = SkDoubleToMScalar(a20 * b05 - a22 * b02 + a23 * b01);
     672           0 :     inverse->fMat[2][0] = SkDoubleToMScalar(a10 * b10 - a11 * b08 + a13 * b06);
     673           0 :     inverse->fMat[2][1] = SkDoubleToMScalar(a01 * b08 - a00 * b10 - a03 * b06);
     674           0 :     inverse->fMat[2][2] = SkDoubleToMScalar(a30 * b04 - a31 * b02 + a33 * b00);
     675           0 :     inverse->fMat[2][3] = SkDoubleToMScalar(a21 * b02 - a20 * b04 - a23 * b00);
     676           0 :     inverse->fMat[3][0] = SkDoubleToMScalar(a11 * b07 - a10 * b09 - a12 * b06);
     677           0 :     inverse->fMat[3][1] = SkDoubleToMScalar(a00 * b09 - a01 * b07 + a02 * b06);
     678           0 :     inverse->fMat[3][2] = SkDoubleToMScalar(a31 * b01 - a30 * b03 - a32 * b00);
     679           0 :     inverse->fMat[3][3] = SkDoubleToMScalar(a20 * b03 - a21 * b01 + a22 * b00);
     680           0 :     inverse->dirtyTypeMask();
     681             : 
     682           0 :     inverse->setTypeMask(this->getType());
     683           0 :     if (!is_matrix_finite(*inverse)) {
     684           0 :         return false;
     685             :     }
     686           0 :     if (storage && inverse != storage) {
     687           0 :         *storage = *inverse;
     688             :     }
     689           0 :     return true;
     690             : }
     691             : 
     692             : ///////////////////////////////////////////////////////////////////////////////
     693             : 
     694           0 : void SkMatrix44::transpose() {
     695           0 :     SkTSwap(fMat[0][1], fMat[1][0]);
     696           0 :     SkTSwap(fMat[0][2], fMat[2][0]);
     697           0 :     SkTSwap(fMat[0][3], fMat[3][0]);
     698           0 :     SkTSwap(fMat[1][2], fMat[2][1]);
     699           0 :     SkTSwap(fMat[1][3], fMat[3][1]);
     700           0 :     SkTSwap(fMat[2][3], fMat[3][2]);
     701             : 
     702           0 :     if (!this->isTriviallyIdentity()) {
     703           0 :         this->dirtyTypeMask();
     704             :     }
     705           0 : }
     706             : 
     707             : ///////////////////////////////////////////////////////////////////////////////
     708             : 
     709           0 : void SkMatrix44::mapScalars(const SkScalar src[4], SkScalar dst[4]) const {
     710             :     SkScalar storage[4];
     711           0 :     SkScalar* result = (src == dst) ? storage : dst;
     712             : 
     713           0 :     for (int i = 0; i < 4; i++) {
     714           0 :         SkMScalar value = 0;
     715           0 :         for (int j = 0; j < 4; j++) {
     716           0 :             value += fMat[j][i] * src[j];
     717             :         }
     718           0 :         result[i] = SkMScalarToScalar(value);
     719             :     }
     720             : 
     721           0 :     if (storage == result) {
     722           0 :         memcpy(dst, storage, sizeof(storage));
     723             :     }
     724           0 : }
     725             : 
     726             : #ifdef SK_MSCALAR_IS_DOUBLE
     727             : 
     728             : void SkMatrix44::mapMScalars(const SkMScalar src[4], SkMScalar dst[4]) const {
     729             :     SkMScalar storage[4];
     730             :     SkMScalar* result = (src == dst) ? storage : dst;
     731             : 
     732             :     for (int i = 0; i < 4; i++) {
     733             :         SkMScalar value = 0;
     734             :         for (int j = 0; j < 4; j++) {
     735             :             value += fMat[j][i] * src[j];
     736             :         }
     737             :         result[i] = value;
     738             :     }
     739             : 
     740             :     if (storage == result) {
     741             :         memcpy(dst, storage, sizeof(storage));
     742             :     }
     743             : }
     744             : 
     745             : #endif
     746             : 
     747             : typedef void (*Map2Procf)(const SkMScalar mat[][4], const float src2[], int count, float dst4[]);
     748             : typedef void (*Map2Procd)(const SkMScalar mat[][4], const double src2[], int count, double dst4[]);
     749             : 
     750           0 : static void map2_if(const SkMScalar mat[][4], const float* SK_RESTRICT src2,
     751             :                     int count, float* SK_RESTRICT dst4) {
     752           0 :     for (int i = 0; i < count; ++i) {
     753           0 :         dst4[0] = src2[0];
     754           0 :         dst4[1] = src2[1];
     755           0 :         dst4[2] = 0;
     756           0 :         dst4[3] = 1;
     757           0 :         src2 += 2;
     758           0 :         dst4 += 4;
     759             :     }
     760           0 : }
     761             : 
     762           0 : static void map2_id(const SkMScalar mat[][4], const double* SK_RESTRICT src2,
     763             :                     int count, double* SK_RESTRICT dst4) {
     764           0 :     for (int i = 0; i < count; ++i) {
     765           0 :         dst4[0] = src2[0];
     766           0 :         dst4[1] = src2[1];
     767           0 :         dst4[2] = 0;
     768           0 :         dst4[3] = 1;
     769           0 :         src2 += 2;
     770           0 :         dst4 += 4;
     771             :     }
     772           0 : }
     773             : 
     774           0 : static void map2_tf(const SkMScalar mat[][4], const float* SK_RESTRICT src2,
     775             :                     int count, float* SK_RESTRICT dst4) {
     776           0 :     const float mat30 = SkMScalarToFloat(mat[3][0]);
     777           0 :     const float mat31 = SkMScalarToFloat(mat[3][1]);
     778           0 :     const float mat32 = SkMScalarToFloat(mat[3][2]);
     779           0 :     for (int n = 0; n < count; ++n) {
     780           0 :         dst4[0] = src2[0] + mat30;
     781           0 :         dst4[1] = src2[1] + mat31;
     782           0 :         dst4[2] = mat32;
     783           0 :         dst4[3] = 1;
     784           0 :         src2 += 2;
     785           0 :         dst4 += 4;
     786             :     }
     787           0 : }
     788             : 
     789           0 : static void map2_td(const SkMScalar mat[][4], const double* SK_RESTRICT src2,
     790             :                     int count, double* SK_RESTRICT dst4) {
     791           0 :     for (int n = 0; n < count; ++n) {
     792           0 :         dst4[0] = src2[0] + mat[3][0];
     793           0 :         dst4[1] = src2[1] + mat[3][1];
     794           0 :         dst4[2] = mat[3][2];
     795           0 :         dst4[3] = 1;
     796           0 :         src2 += 2;
     797           0 :         dst4 += 4;
     798             :     }
     799           0 : }
     800             : 
     801           0 : static void map2_sf(const SkMScalar mat[][4], const float* SK_RESTRICT src2,
     802             :                     int count, float* SK_RESTRICT dst4) {
     803           0 :     const float mat32 = SkMScalarToFloat(mat[3][2]);
     804           0 :     for (int n = 0; n < count; ++n) {
     805           0 :         dst4[0] = SkMScalarToFloat(mat[0][0] * src2[0] + mat[3][0]);
     806           0 :         dst4[1] = SkMScalarToFloat(mat[1][1] * src2[1] + mat[3][1]);
     807           0 :         dst4[2] = mat32;
     808           0 :         dst4[3] = 1;
     809           0 :         src2 += 2;
     810           0 :         dst4 += 4;
     811             :     }
     812           0 : }
     813             : 
     814           0 : static void map2_sd(const SkMScalar mat[][4], const double* SK_RESTRICT src2,
     815             :                     int count, double* SK_RESTRICT dst4) {
     816           0 :     for (int n = 0; n < count; ++n) {
     817           0 :         dst4[0] = mat[0][0] * src2[0] + mat[3][0];
     818           0 :         dst4[1] = mat[1][1] * src2[1] + mat[3][1];
     819           0 :         dst4[2] = mat[3][2];
     820           0 :         dst4[3] = 1;
     821           0 :         src2 += 2;
     822           0 :         dst4 += 4;
     823             :     }
     824           0 : }
     825             : 
     826           0 : static void map2_af(const SkMScalar mat[][4], const float* SK_RESTRICT src2,
     827             :                     int count, float* SK_RESTRICT dst4) {
     828             :     SkMScalar r;
     829           0 :     for (int n = 0; n < count; ++n) {
     830           0 :         SkMScalar sx = SkFloatToMScalar(src2[0]);
     831           0 :         SkMScalar sy = SkFloatToMScalar(src2[1]);
     832           0 :         r = mat[0][0] * sx + mat[1][0] * sy + mat[3][0];
     833           0 :         dst4[0] = SkMScalarToFloat(r);
     834           0 :         r = mat[0][1] * sx + mat[1][1] * sy + mat[3][1];
     835           0 :         dst4[1] = SkMScalarToFloat(r);
     836           0 :         r = mat[0][2] * sx + mat[1][2] * sy + mat[3][2];
     837           0 :         dst4[2] = SkMScalarToFloat(r);
     838           0 :         dst4[3] = 1;
     839           0 :         src2 += 2;
     840           0 :         dst4 += 4;
     841             :     }
     842           0 : }
     843             : 
     844           0 : static void map2_ad(const SkMScalar mat[][4], const double* SK_RESTRICT src2,
     845             :                     int count, double* SK_RESTRICT dst4) {
     846           0 :     for (int n = 0; n < count; ++n) {
     847           0 :         double sx = src2[0];
     848           0 :         double sy = src2[1];
     849           0 :         dst4[0] = mat[0][0] * sx + mat[1][0] * sy + mat[3][0];
     850           0 :         dst4[1] = mat[0][1] * sx + mat[1][1] * sy + mat[3][1];
     851           0 :         dst4[2] = mat[0][2] * sx + mat[1][2] * sy + mat[3][2];
     852           0 :         dst4[3] = 1;
     853           0 :         src2 += 2;
     854           0 :         dst4 += 4;
     855             :     }
     856           0 : }
     857             : 
     858           0 : static void map2_pf(const SkMScalar mat[][4], const float* SK_RESTRICT src2,
     859             :                     int count, float* SK_RESTRICT dst4) {
     860             :     SkMScalar r;
     861           0 :     for (int n = 0; n < count; ++n) {
     862           0 :         SkMScalar sx = SkFloatToMScalar(src2[0]);
     863           0 :         SkMScalar sy = SkFloatToMScalar(src2[1]);
     864           0 :         for (int i = 0; i < 4; i++) {
     865           0 :             r = mat[0][i] * sx + mat[1][i] * sy + mat[3][i];
     866           0 :             dst4[i] = SkMScalarToFloat(r);
     867             :         }
     868           0 :         src2 += 2;
     869           0 :         dst4 += 4;
     870             :     }
     871           0 : }
     872             : 
     873           0 : static void map2_pd(const SkMScalar mat[][4], const double* SK_RESTRICT src2,
     874             :                     int count, double* SK_RESTRICT dst4) {
     875           0 :     for (int n = 0; n < count; ++n) {
     876           0 :         double sx = src2[0];
     877           0 :         double sy = src2[1];
     878           0 :         for (int i = 0; i < 4; i++) {
     879           0 :             dst4[i] = mat[0][i] * sx + mat[1][i] * sy + mat[3][i];
     880             :         }
     881           0 :         src2 += 2;
     882           0 :         dst4 += 4;
     883             :     }
     884           0 : }
     885             : 
     886           0 : void SkMatrix44::map2(const float src2[], int count, float dst4[]) const {
     887             :     static const Map2Procf gProc[] = {
     888             :         map2_if, map2_tf, map2_sf, map2_sf, map2_af, map2_af, map2_af, map2_af
     889             :     };
     890             : 
     891           0 :     TypeMask mask = this->getType();
     892           0 :     Map2Procf proc = (mask & kPerspective_Mask) ? map2_pf : gProc[mask];
     893           0 :     proc(fMat, src2, count, dst4);
     894           0 : }
     895             : 
     896           0 : void SkMatrix44::map2(const double src2[], int count, double dst4[]) const {
     897             :     static const Map2Procd gProc[] = {
     898             :         map2_id, map2_td, map2_sd, map2_sd, map2_ad, map2_ad, map2_ad, map2_ad
     899             :     };
     900             : 
     901           0 :     TypeMask mask = this->getType();
     902           0 :     Map2Procd proc = (mask & kPerspective_Mask) ? map2_pd : gProc[mask];
     903           0 :     proc(fMat, src2, count, dst4);
     904           0 : }
     905             : 
     906           0 : bool SkMatrix44::preserves2dAxisAlignment (SkMScalar epsilon) const {
     907             : 
     908             :     // Can't check (mask & kPerspective_Mask) because Z isn't relevant here.
     909           0 :     if (0 != perspX() || 0 != perspY()) return false;
     910             : 
     911             :     // A matrix with two non-zeroish values in any of the upper right
     912             :     // rows or columns will skew.  If only one value in each row or
     913             :     // column is non-zeroish, we get a scale plus perhaps a 90-degree
     914             :     // rotation.
     915           0 :     int col0 = 0;
     916           0 :     int col1 = 0;
     917           0 :     int row0 = 0;
     918           0 :     int row1 = 0;
     919             : 
     920             :     // Must test against epsilon, not 0, because we can get values
     921             :     // around 6e-17 in the matrix that "should" be 0.
     922             : 
     923           0 :     if (SkMScalarAbs(fMat[0][0]) > epsilon) {
     924           0 :         col0++;
     925           0 :         row0++;
     926             :     }
     927           0 :     if (SkMScalarAbs(fMat[0][1]) > epsilon) {
     928           0 :         col1++;
     929           0 :         row0++;
     930             :     }
     931           0 :     if (SkMScalarAbs(fMat[1][0]) > epsilon) {
     932           0 :         col0++;
     933           0 :         row1++;
     934             :     }
     935           0 :     if (SkMScalarAbs(fMat[1][1]) > epsilon) {
     936           0 :         col1++;
     937           0 :         row1++;
     938             :     }
     939           0 :     if (col0 > 1 || col1 > 1 || row0 > 1 || row1 > 1) {
     940           0 :         return false;
     941             :     }
     942             : 
     943           0 :     return true;
     944             : }
     945             : 
     946             : ///////////////////////////////////////////////////////////////////////////////
     947             : 
     948           0 : void SkMatrix44::dump() const {
     949             :     static const char* format = "|%g %g %g %g|\n"
     950             :                                 "|%g %g %g %g|\n"
     951             :                                 "|%g %g %g %g|\n"
     952             :                                 "|%g %g %g %g|\n";
     953           0 :     SkDebugf(format,
     954           0 :              fMat[0][0], fMat[1][0], fMat[2][0], fMat[3][0],
     955           0 :              fMat[0][1], fMat[1][1], fMat[2][1], fMat[3][1],
     956           0 :              fMat[0][2], fMat[1][2], fMat[2][2], fMat[3][2],
     957           0 :              fMat[0][3], fMat[1][3], fMat[2][3], fMat[3][3]);
     958           0 : }
     959             : 
     960             : ///////////////////////////////////////////////////////////////////////////////
     961             : 
     962           0 : static void initFromMatrix(SkMScalar dst[4][4], const SkMatrix& src) {
     963           0 :     dst[0][0] = SkScalarToMScalar(src[SkMatrix::kMScaleX]);
     964           0 :     dst[1][0] = SkScalarToMScalar(src[SkMatrix::kMSkewX]);
     965           0 :     dst[2][0] = 0;
     966           0 :     dst[3][0] = SkScalarToMScalar(src[SkMatrix::kMTransX]);
     967           0 :     dst[0][1] = SkScalarToMScalar(src[SkMatrix::kMSkewY]);
     968           0 :     dst[1][1] = SkScalarToMScalar(src[SkMatrix::kMScaleY]);
     969           0 :     dst[2][1] = 0;
     970           0 :     dst[3][1] = SkScalarToMScalar(src[SkMatrix::kMTransY]);
     971           0 :     dst[0][2] = 0;
     972           0 :     dst[1][2] = 0;
     973           0 :     dst[2][2] = 1;
     974           0 :     dst[3][2] = 0;
     975           0 :     dst[0][3] = SkScalarToMScalar(src[SkMatrix::kMPersp0]);
     976           0 :     dst[1][3] = SkScalarToMScalar(src[SkMatrix::kMPersp1]);
     977           0 :     dst[2][3] = 0;
     978           0 :     dst[3][3] = SkScalarToMScalar(src[SkMatrix::kMPersp2]);
     979           0 : }
     980             : 
     981           0 : SkMatrix44::SkMatrix44(const SkMatrix& src) {
     982           0 :     this->operator=(src);
     983           0 : }
     984             : 
     985           0 : SkMatrix44& SkMatrix44::operator=(const SkMatrix& src) {
     986           0 :     initFromMatrix(fMat, src);
     987             : 
     988           0 :     if (src.isIdentity()) {
     989           0 :         this->setTypeMask(kIdentity_Mask);
     990             :     } else {
     991           0 :         this->dirtyTypeMask();
     992             :     }
     993           0 :     return *this;
     994             : }
     995             : 
     996           0 : SkMatrix44::operator SkMatrix() const {
     997             :     SkMatrix dst;
     998             : 
     999           0 :     dst[SkMatrix::kMScaleX]  = SkMScalarToScalar(fMat[0][0]);
    1000           0 :     dst[SkMatrix::kMSkewX]  = SkMScalarToScalar(fMat[1][0]);
    1001           0 :     dst[SkMatrix::kMTransX] = SkMScalarToScalar(fMat[3][0]);
    1002             : 
    1003           0 :     dst[SkMatrix::kMSkewY]  = SkMScalarToScalar(fMat[0][1]);
    1004           0 :     dst[SkMatrix::kMScaleY] = SkMScalarToScalar(fMat[1][1]);
    1005           0 :     dst[SkMatrix::kMTransY] = SkMScalarToScalar(fMat[3][1]);
    1006             : 
    1007           0 :     dst[SkMatrix::kMPersp0] = SkMScalarToScalar(fMat[0][3]);
    1008           0 :     dst[SkMatrix::kMPersp1] = SkMScalarToScalar(fMat[1][3]);
    1009           0 :     dst[SkMatrix::kMPersp2] = SkMScalarToScalar(fMat[3][3]);
    1010             : 
    1011           0 :     return dst;
    1012             : }

Generated by: LCOV version 1.13