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