Home | History | Annotate | Download | only in utils
      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::asColMajord(double dst[]) const {
     89     const SkMScalar* src = &fMat[0][0];
     90 #ifdef SK_MSCALAR_IS_DOUBLE
     91     memcpy(dst, src, 16 * sizeof(double));
     92 #elif defined SK_MSCALAR_IS_FLOAT
     93     for (int i = 0; i < 16; ++i) {
     94         dst[i] = SkMScalarToDouble(src[i]);
     95     }
     96 #endif
     97 }
     98 
     99 void SkMatrix44::asRowMajorf(float dst[]) const {
    100     const SkMScalar* src = &fMat[0][0];
    101     for (int i = 0; i < 4; ++i) {
    102         dst[0] = SkMScalarToFloat(src[0]);
    103         dst[4] = SkMScalarToFloat(src[1]);
    104         dst[8] = SkMScalarToFloat(src[2]);
    105         dst[12] = SkMScalarToFloat(src[3]);
    106         src += 4;
    107         dst += 1;
    108     }
    109 }
    110 
    111 void SkMatrix44::asRowMajord(double dst[]) const {
    112     const SkMScalar* src = &fMat[0][0];
    113     for (int i = 0; i < 4; ++i) {
    114         dst[0] = SkMScalarToDouble(src[0]);
    115         dst[4] = SkMScalarToDouble(src[1]);
    116         dst[8] = SkMScalarToDouble(src[2]);
    117         dst[12] = SkMScalarToDouble(src[3]);
    118         src += 4;
    119         dst += 1;
    120     }
    121 }
    122 
    123 void SkMatrix44::setColMajorf(const float src[]) {
    124     SkMScalar* dst = &fMat[0][0];
    125 #ifdef SK_MSCALAR_IS_DOUBLE
    126     for (int i = 0; i < 16; ++i) {
    127         dst[i] = SkMScalarToFloat(src[i]);
    128     }
    129 #elif defined SK_MSCALAR_IS_FLOAT
    130     memcpy(dst, src, 16 * sizeof(float));
    131 #endif
    132 
    133     this->dirtyTypeMask();
    134 }
    135 
    136 void SkMatrix44::setColMajord(const double src[]) {
    137     SkMScalar* dst = &fMat[0][0];
    138 #ifdef SK_MSCALAR_IS_DOUBLE
    139     memcpy(dst, src, 16 * sizeof(double));
    140 #elif defined SK_MSCALAR_IS_FLOAT
    141     for (int i = 0; i < 16; ++i) {
    142         dst[i] = SkDoubleToMScalar(src[i]);
    143     }
    144 #endif
    145 
    146     this->dirtyTypeMask();
    147 }
    148 
    149 void SkMatrix44::setRowMajorf(const float src[]) {
    150     SkMScalar* dst = &fMat[0][0];
    151     for (int i = 0; i < 4; ++i) {
    152         dst[0] = SkMScalarToFloat(src[0]);
    153         dst[4] = SkMScalarToFloat(src[1]);
    154         dst[8] = SkMScalarToFloat(src[2]);
    155         dst[12] = SkMScalarToFloat(src[3]);
    156         src += 4;
    157         dst += 1;
    158     }
    159     this->dirtyTypeMask();
    160 }
    161 
    162 void SkMatrix44::setRowMajord(const double src[]) {
    163     SkMScalar* dst = &fMat[0][0];
    164     for (int i = 0; i < 4; ++i) {
    165         dst[0] = SkDoubleToMScalar(src[0]);
    166         dst[4] = SkDoubleToMScalar(src[1]);
    167         dst[8] = SkDoubleToMScalar(src[2]);
    168         dst[12] = SkDoubleToMScalar(src[3]);
    169         src += 4;
    170         dst += 1;
    171     }
    172     this->dirtyTypeMask();
    173 }
    174 
    175 ///////////////////////////////////////////////////////////////////////////////
    176 
    177 const SkMatrix44& SkMatrix44::I() {
    178     static const SkMatrix44 gIdentity44(kIdentity_Constructor);
    179     return gIdentity44;
    180 }
    181 
    182 void SkMatrix44::setIdentity() {
    183     sk_bzero(fMat, sizeof(fMat));
    184     fMat[0][0] = fMat[1][1] = fMat[2][2] = fMat[3][3] = 1;
    185     this->setTypeMask(kIdentity_Mask);
    186 }
    187 
    188 void SkMatrix44::set3x3(SkMScalar m00, SkMScalar m01, SkMScalar m02,
    189                         SkMScalar m10, SkMScalar m11, SkMScalar m12,
    190                         SkMScalar m20, SkMScalar m21, SkMScalar m22) {
    191     fMat[0][0] = m00; fMat[0][1] = m01; fMat[0][2] = m02; fMat[0][3] = 0;
    192     fMat[1][0] = m10; fMat[1][1] = m11; fMat[1][2] = m12; fMat[1][3] = 0;
    193     fMat[2][0] = m20; fMat[2][1] = m21; fMat[2][2] = m22; fMat[2][3] = 0;
    194     fMat[3][0] = 0;   fMat[3][1] = 0;   fMat[3][2] = 0;   fMat[3][3] = 1;
    195     this->dirtyTypeMask();
    196 }
    197 
    198 ///////////////////////////////////////////////////////////////////////////////
    199 
    200 void SkMatrix44::setTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz) {
    201     this->setIdentity();
    202 
    203     if (!dx && !dy && !dz) {
    204         return;
    205     }
    206 
    207     fMat[3][0] = dx;
    208     fMat[3][1] = dy;
    209     fMat[3][2] = dz;
    210     this->setTypeMask(kTranslate_Mask);
    211 }
    212 
    213 void SkMatrix44::preTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz) {
    214     if (!dx && !dy && !dz) {
    215         return;
    216     }
    217 
    218     const double X = SkMScalarToDouble(dx);
    219     const double Y = SkMScalarToDouble(dy);
    220     const double Z = SkMScalarToDouble(dz);
    221 
    222     double tmp;
    223     for (int i = 0; i < 4; ++i) {
    224         tmp = fMat[0][i] * X + fMat[1][i] * Y + fMat[2][i] * Z + fMat[3][i];
    225         fMat[3][i] = SkDoubleToMScalar(tmp);
    226     }
    227     this->dirtyTypeMask();
    228 }
    229 
    230 void SkMatrix44::postTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz) {
    231     if (!dx && !dy && !dz) {
    232         return;
    233     }
    234 
    235     if (this->getType() & kPerspective_Mask) {
    236         for (int i = 0; i < 4; ++i) {
    237             fMat[i][0] += fMat[i][3] * dx;
    238             fMat[i][1] += fMat[i][3] * dy;
    239             fMat[i][2] += fMat[i][3] * dz;
    240         }
    241     } else {
    242         fMat[3][0] += dx;
    243         fMat[3][1] += dy;
    244         fMat[3][2] += dz;
    245         this->dirtyTypeMask();
    246     }
    247 }
    248 
    249 ///////////////////////////////////////////////////////////////////////////////
    250 
    251 void SkMatrix44::setScale(SkMScalar sx, SkMScalar sy, SkMScalar sz) {
    252     this->setIdentity();
    253 
    254     if (1 == sx && 1 == sy && 1 == sz) {
    255         return;
    256     }
    257 
    258     fMat[0][0] = sx;
    259     fMat[1][1] = sy;
    260     fMat[2][2] = sz;
    261     this->setTypeMask(kScale_Mask);
    262 }
    263 
    264 void SkMatrix44::preScale(SkMScalar sx, SkMScalar sy, SkMScalar sz) {
    265     if (1 == sx && 1 == sy && 1 == sz) {
    266         return;
    267     }
    268 
    269     // The implementation matrix * pureScale can be shortcut
    270     // by knowing that pureScale components effectively scale
    271     // the columns of the original matrix.
    272     for (int i = 0; i < 4; i++) {
    273         fMat[0][i] *= sx;
    274         fMat[1][i] *= sy;
    275         fMat[2][i] *= sz;
    276     }
    277     this->dirtyTypeMask();
    278 }
    279 
    280 void SkMatrix44::postScale(SkMScalar sx, SkMScalar sy, SkMScalar sz) {
    281     if (1 == sx && 1 == sy && 1 == sz) {
    282         return;
    283     }
    284 
    285     for (int i = 0; i < 4; i++) {
    286         fMat[i][0] *= sx;
    287         fMat[i][1] *= sy;
    288         fMat[i][2] *= sz;
    289     }
    290     this->dirtyTypeMask();
    291 }
    292 
    293 ///////////////////////////////////////////////////////////////////////////////
    294 
    295 void SkMatrix44::setRotateAbout(SkMScalar x, SkMScalar y, SkMScalar z,
    296                                 SkMScalar radians) {
    297     double len2 = (double)x * x + (double)y * y + (double)z * z;
    298     if (1 != len2) {
    299         if (0 == len2) {
    300             this->setIdentity();
    301             return;
    302         }
    303         double scale = 1 / sqrt(len2);
    304         x = SkDoubleToMScalar(x * scale);
    305         y = SkDoubleToMScalar(y * scale);
    306         z = SkDoubleToMScalar(z * scale);
    307     }
    308     this->setRotateAboutUnit(x, y, z, radians);
    309 }
    310 
    311 void SkMatrix44::setRotateAboutUnit(SkMScalar x, SkMScalar y, SkMScalar z,
    312                                     SkMScalar radians) {
    313     double c = cos(radians);
    314     double s = sin(radians);
    315     double C = 1 - c;
    316     double xs = x * s;
    317     double ys = y * s;
    318     double zs = z * s;
    319     double xC = x * C;
    320     double yC = y * C;
    321     double zC = z * C;
    322     double xyC = x * yC;
    323     double yzC = y * zC;
    324     double zxC = z * xC;
    325 
    326     // if you're looking at wikipedia, remember that we're column major.
    327     this->set3x3(SkDoubleToMScalar(x * xC + c),     // scale x
    328                  SkDoubleToMScalar(xyC + zs),       // skew x
    329                  SkDoubleToMScalar(zxC - ys),       // trans x
    330 
    331                  SkDoubleToMScalar(xyC - zs),       // skew y
    332                  SkDoubleToMScalar(y * yC + c),     // scale y
    333                  SkDoubleToMScalar(yzC + xs),       // trans y
    334 
    335                  SkDoubleToMScalar(zxC + ys),       // persp x
    336                  SkDoubleToMScalar(yzC - xs),       // persp y
    337                  SkDoubleToMScalar(z * zC + c));    // persp 2
    338 }
    339 
    340 ///////////////////////////////////////////////////////////////////////////////
    341 
    342 static bool bits_isonly(int value, int mask) {
    343     return 0 == (value & ~mask);
    344 }
    345 
    346 void SkMatrix44::setConcat(const SkMatrix44& a, const SkMatrix44& b) {
    347     const SkMatrix44::TypeMask a_mask = a.getType();
    348     const SkMatrix44::TypeMask b_mask = b.getType();
    349 
    350     if (kIdentity_Mask == a_mask) {
    351         *this = b;
    352         return;
    353     }
    354     if (kIdentity_Mask == b_mask) {
    355         *this = a;
    356         return;
    357     }
    358 
    359     bool useStorage = (this == &a || this == &b);
    360     SkMScalar storage[16];
    361     SkMScalar* result = useStorage ? storage : &fMat[0][0];
    362 
    363     // Both matrices are at most scale+translate
    364     if (bits_isonly(a_mask | b_mask, kScale_Mask | kTranslate_Mask)) {
    365         result[0] = a.fMat[0][0] * b.fMat[0][0];
    366         result[1] = result[2] = result[3] = result[4] = 0;
    367         result[5] = a.fMat[1][1] * b.fMat[1][1];
    368         result[6] = result[7] = result[8] = result[9] = 0;
    369         result[10] = a.fMat[2][2] * b.fMat[2][2];
    370         result[11] = 0;
    371         result[12] = a.fMat[0][0] * b.fMat[3][0] + a.fMat[3][0];
    372         result[13] = a.fMat[1][1] * b.fMat[3][1] + a.fMat[3][1];
    373         result[14] = a.fMat[2][2] * b.fMat[3][2] + a.fMat[3][2];
    374         result[15] = 1;
    375     } else {
    376         for (int j = 0; j < 4; j++) {
    377             for (int i = 0; i < 4; i++) {
    378                 double value = 0;
    379                 for (int k = 0; k < 4; k++) {
    380                     value += SkMScalarToDouble(a.fMat[k][i]) * b.fMat[j][k];
    381                 }
    382                 *result++ = SkDoubleToMScalar(value);
    383             }
    384         }
    385     }
    386 
    387     if (useStorage) {
    388         memcpy(fMat, storage, sizeof(storage));
    389     }
    390     this->dirtyTypeMask();
    391 }
    392 
    393 ///////////////////////////////////////////////////////////////////////////////
    394 
    395 static inline SkMScalar det2x2(double m00, double m01, double m10, double m11) {
    396     return SkDoubleToMScalar(m00 * m11 - m10 * m01);
    397 }
    398 
    399 static inline double det3x3(double m00, double m01, double m02,
    400                             double m10, double m11, double m12,
    401                             double m20, double m21, double m22) {
    402     return  m00 * det2x2(m11, m12, m21, m22) -
    403     m10 * det2x2(m01, m02, m21, m22) +
    404     m20 * det2x2(m01, m02, m11, m12);
    405 }
    406 
    407 /** We always perform the calculation in doubles, to avoid prematurely losing
    408     precision along the way. This relies on the compiler automatically
    409     promoting our SkMScalar values to double (if needed).
    410  */
    411 double SkMatrix44::determinant() const {
    412     if (this->isIdentity()) {
    413         return 1;
    414     }
    415     if (this->isScaleTranslate()) {
    416         return fMat[0][0] * fMat[1][1] * fMat[2][2] * fMat[3][3];
    417     }
    418 
    419     double a00 = fMat[0][0];
    420     double a01 = fMat[0][1];
    421     double a02 = fMat[0][2];
    422     double a03 = fMat[0][3];
    423     double a10 = fMat[1][0];
    424     double a11 = fMat[1][1];
    425     double a12 = fMat[1][2];
    426     double a13 = fMat[1][3];
    427     double a20 = fMat[2][0];
    428     double a21 = fMat[2][1];
    429     double a22 = fMat[2][2];
    430     double a23 = fMat[2][3];
    431     double a30 = fMat[3][0];
    432     double a31 = fMat[3][1];
    433     double a32 = fMat[3][2];
    434     double a33 = fMat[3][3];
    435 
    436     double b00 = a00 * a11 - a01 * a10;
    437     double b01 = a00 * a12 - a02 * a10;
    438     double b02 = a00 * a13 - a03 * a10;
    439     double b03 = a01 * a12 - a02 * a11;
    440     double b04 = a01 * a13 - a03 * a11;
    441     double b05 = a02 * a13 - a03 * a12;
    442     double b06 = a20 * a31 - a21 * a30;
    443     double b07 = a20 * a32 - a22 * a30;
    444     double b08 = a20 * a33 - a23 * a30;
    445     double b09 = a21 * a32 - a22 * a31;
    446     double b10 = a21 * a33 - a23 * a31;
    447     double b11 = a22 * a33 - a23 * a32;
    448 
    449     // Calculate the determinant
    450     return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
    451 }
    452 
    453 ///////////////////////////////////////////////////////////////////////////////
    454 
    455 // just picked a small value. not sure how to pick the "right" one
    456 #define TOO_SMALL_FOR_DETERMINANT   (1.e-8)
    457 
    458 static inline double dabs(double x) {
    459     if (x < 0) {
    460         x = -x;
    461     }
    462     return x;
    463 }
    464 
    465 bool SkMatrix44::invert(SkMatrix44* inverse) const {
    466     if (this->isIdentity()) {
    467         if (inverse) {
    468             *inverse = *this;
    469             return true;
    470         }
    471     }
    472     if (this->isTranslate()) {
    473         if (inverse) {
    474             inverse->setTranslate(-fMat[3][0], -fMat[3][1], -fMat[3][2]);
    475         }
    476         return true;
    477     }
    478     if (this->isScaleTranslate()) {
    479         if (0 == fMat[0][0] * fMat[1][1] * fMat[2][2]) {
    480             return false;
    481         }
    482         if (inverse) {
    483             sk_bzero(inverse->fMat, sizeof(inverse->fMat));
    484 
    485             inverse->fMat[3][0] = -fMat[3][0] / fMat[0][0];
    486             inverse->fMat[3][1] = -fMat[3][1] / fMat[1][1];
    487             inverse->fMat[3][2] = -fMat[3][2] / fMat[2][2];
    488 
    489             inverse->fMat[0][0] = 1 / fMat[0][0];
    490             inverse->fMat[1][1] = 1 / fMat[1][1];
    491             inverse->fMat[2][2] = 1 / fMat[2][2];
    492             inverse->fMat[3][3] = 1;
    493 
    494             inverse->setTypeMask(this->getType());
    495         }
    496         return true;
    497     }
    498 
    499     double a00 = fMat[0][0];
    500     double a01 = fMat[0][1];
    501     double a02 = fMat[0][2];
    502     double a03 = fMat[0][3];
    503     double a10 = fMat[1][0];
    504     double a11 = fMat[1][1];
    505     double a12 = fMat[1][2];
    506     double a13 = fMat[1][3];
    507     double a20 = fMat[2][0];
    508     double a21 = fMat[2][1];
    509     double a22 = fMat[2][2];
    510     double a23 = fMat[2][3];
    511     double a30 = fMat[3][0];
    512     double a31 = fMat[3][1];
    513     double a32 = fMat[3][2];
    514     double a33 = fMat[3][3];
    515 
    516     double b00 = a00 * a11 - a01 * a10;
    517     double b01 = a00 * a12 - a02 * a10;
    518     double b02 = a00 * a13 - a03 * a10;
    519     double b03 = a01 * a12 - a02 * a11;
    520     double b04 = a01 * a13 - a03 * a11;
    521     double b05 = a02 * a13 - a03 * a12;
    522     double b06 = a20 * a31 - a21 * a30;
    523     double b07 = a20 * a32 - a22 * a30;
    524     double b08 = a20 * a33 - a23 * a30;
    525     double b09 = a21 * a32 - a22 * a31;
    526     double b10 = a21 * a33 - a23 * a31;
    527     double b11 = a22 * a33 - a23 * a32;
    528 
    529     // Calculate the determinant
    530     double det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
    531 
    532     if (dabs(det) < TOO_SMALL_FOR_DETERMINANT) {
    533         return false;
    534     }
    535     if (NULL == inverse) {
    536         return true;
    537     }
    538     double invdet = 1.0 / det;
    539 
    540     b00 *= invdet;
    541     b01 *= invdet;
    542     b02 *= invdet;
    543     b03 *= invdet;
    544     b04 *= invdet;
    545     b05 *= invdet;
    546     b06 *= invdet;
    547     b07 *= invdet;
    548     b08 *= invdet;
    549     b09 *= invdet;
    550     b10 *= invdet;
    551     b11 *= invdet;
    552 
    553     inverse->fMat[0][0] = SkDoubleToMScalar(a11 * b11 - a12 * b10 + a13 * b09);
    554     inverse->fMat[0][1] = SkDoubleToMScalar(a02 * b10 - a01 * b11 - a03 * b09);
    555     inverse->fMat[0][2] = SkDoubleToMScalar(a31 * b05 - a32 * b04 + a33 * b03);
    556     inverse->fMat[0][3] = SkDoubleToMScalar(a22 * b04 - a21 * b05 - a23 * b03);
    557     inverse->fMat[1][0] = SkDoubleToMScalar(a12 * b08 - a10 * b11 - a13 * b07);
    558     inverse->fMat[1][1] = SkDoubleToMScalar(a00 * b11 - a02 * b08 + a03 * b07);
    559     inverse->fMat[1][2] = SkDoubleToMScalar(a32 * b02 - a30 * b05 - a33 * b01);
    560     inverse->fMat[1][3] = SkDoubleToMScalar(a20 * b05 - a22 * b02 + a23 * b01);
    561     inverse->fMat[2][0] = SkDoubleToMScalar(a10 * b10 - a11 * b08 + a13 * b06);
    562     inverse->fMat[2][1] = SkDoubleToMScalar(a01 * b08 - a00 * b10 - a03 * b06);
    563     inverse->fMat[2][2] = SkDoubleToMScalar(a30 * b04 - a31 * b02 + a33 * b00);
    564     inverse->fMat[2][3] = SkDoubleToMScalar(a21 * b02 - a20 * b04 - a23 * b00);
    565     inverse->fMat[3][0] = SkDoubleToMScalar(a11 * b07 - a10 * b09 - a12 * b06);
    566     inverse->fMat[3][1] = SkDoubleToMScalar(a00 * b09 - a01 * b07 + a02 * b06);
    567     inverse->fMat[3][2] = SkDoubleToMScalar(a31 * b01 - a30 * b03 - a32 * b00);
    568     inverse->fMat[3][3] = SkDoubleToMScalar(a20 * b03 - a21 * b01 + a22 * b00);
    569     inverse->dirtyTypeMask();
    570 
    571     inverse->dirtyTypeMask();
    572     return true;
    573 }
    574 
    575 ///////////////////////////////////////////////////////////////////////////////
    576 
    577 void SkMatrix44::transpose() {
    578     SkTSwap(fMat[0][1], fMat[1][0]);
    579     SkTSwap(fMat[0][2], fMat[2][0]);
    580     SkTSwap(fMat[0][3], fMat[3][0]);
    581     SkTSwap(fMat[1][2], fMat[2][1]);
    582     SkTSwap(fMat[1][3], fMat[3][1]);
    583     SkTSwap(fMat[2][3], fMat[3][2]);
    584 
    585     if (!this->isTriviallyIdentity()) {
    586         this->dirtyTypeMask();
    587     }
    588 }
    589 
    590 ///////////////////////////////////////////////////////////////////////////////
    591 
    592 void SkMatrix44::mapScalars(const SkScalar src[4], SkScalar dst[4]) const {
    593     SkScalar storage[4];
    594     SkScalar* result = (src == dst) ? storage : dst;
    595 
    596     for (int i = 0; i < 4; i++) {
    597         SkMScalar value = 0;
    598         for (int j = 0; j < 4; j++) {
    599             value += fMat[j][i] * src[j];
    600         }
    601         result[i] = SkMScalarToScalar(value);
    602     }
    603 
    604     if (storage == result) {
    605         memcpy(dst, storage, sizeof(storage));
    606     }
    607 }
    608 
    609 #ifdef SK_MSCALAR_IS_DOUBLE
    610 
    611 void SkMatrix44::mapMScalars(const SkMScalar src[4], SkMScalar dst[4]) const {
    612     SkMScalar storage[4];
    613     SkMScalar* result = (src == dst) ? storage : dst;
    614 
    615     for (int i = 0; i < 4; i++) {
    616         SkMScalar value = 0;
    617         for (int j = 0; j < 4; j++) {
    618             value += fMat[j][i] * src[j];
    619         }
    620         result[i] = value;
    621     }
    622 
    623     if (storage == result) {
    624         memcpy(dst, storage, sizeof(storage));
    625     }
    626 }
    627 
    628 #endif
    629 
    630 typedef void (*Map2Procf)(const SkMScalar mat[][4], const float src2[], int count, float dst4[]);
    631 typedef void (*Map2Procd)(const SkMScalar mat[][4], const double src2[], int count, double dst4[]);
    632 
    633 static void map2_if(const SkMScalar mat[][4], const float* SK_RESTRICT src2,
    634                     int count, float* SK_RESTRICT dst4) {
    635     for (int i = 0; i < count; ++i) {
    636         dst4[0] = src2[0];
    637         dst4[1] = src2[1];
    638         dst4[2] = 0;
    639         dst4[3] = 1;
    640         src2 += 2;
    641         dst4 += 4;
    642     }
    643 }
    644 
    645 static void map2_id(const SkMScalar mat[][4], const double* SK_RESTRICT src2,
    646                     int count, double* SK_RESTRICT dst4) {
    647     for (int i = 0; i < count; ++i) {
    648         dst4[0] = src2[0];
    649         dst4[1] = src2[1];
    650         dst4[2] = 0;
    651         dst4[3] = 1;
    652         src2 += 2;
    653         dst4 += 4;
    654     }
    655 }
    656 
    657 static void map2_tf(const SkMScalar mat[][4], const float* SK_RESTRICT src2,
    658                     int count, float* SK_RESTRICT dst4) {
    659     const float mat30 = SkMScalarToFloat(mat[3][0]);
    660     const float mat31 = SkMScalarToFloat(mat[3][1]);
    661     const float mat32 = SkMScalarToFloat(mat[3][2]);
    662     for (int n = 0; n < count; ++n) {
    663         dst4[0] = src2[0] + mat30;
    664         dst4[1] = src2[1] + mat31;
    665         dst4[2] = mat32;
    666         dst4[3] = 1;
    667         src2 += 2;
    668         dst4 += 4;
    669     }
    670 }
    671 
    672 static void map2_td(const SkMScalar mat[][4], const double* SK_RESTRICT src2,
    673                     int count, double* SK_RESTRICT dst4) {
    674     for (int n = 0; n < count; ++n) {
    675         dst4[0] = src2[0] + mat[3][0];
    676         dst4[1] = src2[1] + mat[3][1];
    677         dst4[2] = mat[3][2];
    678         dst4[3] = 1;
    679         src2 += 2;
    680         dst4 += 4;
    681     }
    682 }
    683 
    684 static void map2_sf(const SkMScalar mat[][4], const float* SK_RESTRICT src2,
    685                     int count, float* SK_RESTRICT dst4) {
    686     const float mat32 = SkMScalarToFloat(mat[3][2]);
    687     for (int n = 0; n < count; ++n) {
    688         dst4[0] = SkMScalarToFloat(mat[0][0] * src2[0] + mat[3][0]);
    689         dst4[1] = SkMScalarToFloat(mat[1][1] * src2[1] + mat[3][1]);
    690         dst4[2] = mat32;
    691         dst4[3] = 1;
    692         src2 += 2;
    693         dst4 += 4;
    694     }
    695 }
    696 
    697 static void map2_sd(const SkMScalar mat[][4], const double* SK_RESTRICT src2,
    698                     int count, double* SK_RESTRICT dst4) {
    699     for (int n = 0; n < count; ++n) {
    700         dst4[0] = mat[0][0] * src2[0] + mat[3][0];
    701         dst4[1] = mat[1][1] * src2[1] + mat[3][1];
    702         dst4[2] = mat[3][2];
    703         dst4[3] = 1;
    704         src2 += 2;
    705         dst4 += 4;
    706     }
    707 }
    708 
    709 static void map2_af(const SkMScalar mat[][4], const float* SK_RESTRICT src2,
    710                     int count, float* SK_RESTRICT dst4) {
    711     double r;
    712     for (int n = 0; n < count; ++n) {
    713         double sx = src2[0];
    714         double sy = src2[1];
    715         r = mat[0][0] * sx + mat[1][0] * sy + mat[3][0];
    716         dst4[0] = SkMScalarToFloat(r);
    717         r = mat[0][1] * sx + mat[1][1] * sy + mat[3][1];
    718         dst4[1] = SkMScalarToFloat(r);
    719         r = mat[0][2] * sx + mat[1][2] * sy + mat[3][2];
    720         dst4[2] = SkMScalarToFloat(r);
    721         dst4[3] = 1;
    722         src2 += 2;
    723         dst4 += 4;
    724     }
    725 }
    726 
    727 static void map2_ad(const SkMScalar mat[][4], const double* SK_RESTRICT src2,
    728                     int count, double* SK_RESTRICT dst4) {
    729     for (int n = 0; n < count; ++n) {
    730         double sx = src2[0];
    731         double sy = src2[1];
    732         dst4[0] = mat[0][0] * sx + mat[1][0] * sy + mat[3][0];
    733         dst4[1] = mat[0][1] * sx + mat[1][1] * sy + mat[3][1];
    734         dst4[2] = mat[0][2] * sx + mat[1][2] * sy + mat[3][2];
    735         dst4[3] = 1;
    736         src2 += 2;
    737         dst4 += 4;
    738     }
    739 }
    740 
    741 static void map2_pf(const SkMScalar mat[][4], const float* SK_RESTRICT src2,
    742                     int count, float* SK_RESTRICT dst4) {
    743     double r;
    744     for (int n = 0; n < count; ++n) {
    745         double sx = src2[0];
    746         double sy = src2[1];
    747         for (int i = 0; i < 4; i++) {
    748             r = mat[0][i] * sx + mat[1][i] * sy + mat[3][i];
    749             dst4[i] = SkMScalarToFloat(r);
    750         }
    751         src2 += 2;
    752         dst4 += 4;
    753     }
    754 }
    755 
    756 static void map2_pd(const SkMScalar mat[][4], const double* SK_RESTRICT src2,
    757                     int count, double* SK_RESTRICT dst4) {
    758     for (int n = 0; n < count; ++n) {
    759         double sx = src2[0];
    760         double sy = src2[1];
    761         for (int i = 0; i < 4; i++) {
    762             dst4[i] = mat[0][i] * sx + mat[1][i] * sy + mat[3][i];
    763         }
    764         src2 += 2;
    765         dst4 += 4;
    766     }
    767 }
    768 
    769 void SkMatrix44::map2(const float src2[], int count, float dst4[]) const {
    770     static const Map2Procf gProc[] = {
    771         map2_if, map2_tf, map2_sf, map2_sf, map2_af, map2_af, map2_af, map2_af
    772     };
    773 
    774     TypeMask mask = this->getType();
    775     Map2Procf proc = (mask & kPerspective_Mask) ? map2_pf : gProc[mask];
    776     proc(fMat, src2, count, dst4);
    777 }
    778 
    779 void SkMatrix44::map2(const double src2[], int count, double dst4[]) const {
    780     static const Map2Procd gProc[] = {
    781         map2_id, map2_td, map2_sd, map2_sd, map2_ad, map2_ad, map2_ad, map2_ad
    782     };
    783 
    784     TypeMask mask = this->getType();
    785     Map2Procd proc = (mask & kPerspective_Mask) ? map2_pd : gProc[mask];
    786     proc(fMat, src2, count, dst4);
    787 }
    788 
    789 ///////////////////////////////////////////////////////////////////////////////
    790 
    791 void SkMatrix44::dump() const {
    792     static const char* format =
    793         "[%g %g %g %g][%g %g %g %g][%g %g %g %g][%g %g %g %g]\n";
    794 #if 0
    795     SkDebugf(format,
    796              fMat[0][0], fMat[1][0], fMat[2][0], fMat[3][0],
    797              fMat[0][1], fMat[1][1], fMat[2][1], fMat[3][1],
    798              fMat[0][2], fMat[1][2], fMat[2][2], fMat[3][2],
    799              fMat[0][3], fMat[1][3], fMat[2][3], fMat[3][3]);
    800 #else
    801     SkDebugf(format,
    802              fMat[0][0], fMat[0][1], fMat[0][2], fMat[0][3],
    803              fMat[1][0], fMat[1][1], fMat[1][2], fMat[1][3],
    804              fMat[2][0], fMat[2][1], fMat[2][2], fMat[2][3],
    805              fMat[3][0], fMat[3][1], fMat[3][2], fMat[3][3]);
    806 #endif
    807 }
    808 
    809 ///////////////////////////////////////////////////////////////////////////////
    810 
    811 // TODO: make this support src' perspective elements
    812 //
    813 static void initFromMatrix(SkMScalar dst[4][4], const SkMatrix& src) {
    814     sk_bzero(dst, 16 * sizeof(SkMScalar));
    815     dst[0][0] = SkScalarToMScalar(src[SkMatrix::kMScaleX]);
    816     dst[1][0] = SkScalarToMScalar(src[SkMatrix::kMSkewX]);
    817     dst[3][0] = SkScalarToMScalar(src[SkMatrix::kMTransX]);
    818     dst[0][1] = SkScalarToMScalar(src[SkMatrix::kMSkewY]);
    819     dst[1][1] = SkScalarToMScalar(src[SkMatrix::kMScaleY]);
    820     dst[3][1] = SkScalarToMScalar(src[SkMatrix::kMTransY]);
    821     dst[2][2] = dst[3][3] = 1;
    822 }
    823 
    824 SkMatrix44::SkMatrix44(const SkMatrix& src) {
    825     initFromMatrix(fMat, src);
    826 }
    827 
    828 SkMatrix44& SkMatrix44::operator=(const SkMatrix& src) {
    829     initFromMatrix(fMat, src);
    830 
    831     if (src.isIdentity()) {
    832         this->setTypeMask(kIdentity_Mask);
    833     } else {
    834         this->dirtyTypeMask();
    835     }
    836     return *this;
    837 }
    838 
    839 // TODO: make this support our perspective elements
    840 //
    841 SkMatrix44::operator SkMatrix() const {
    842     SkMatrix dst;
    843     dst.reset();    // setup our perspective correctly for identity
    844 
    845     dst[SkMatrix::kMScaleX]  = SkMScalarToScalar(fMat[0][0]);
    846     dst[SkMatrix::kMSkewX]  = SkMScalarToScalar(fMat[1][0]);
    847     dst[SkMatrix::kMTransX] = SkMScalarToScalar(fMat[3][0]);
    848 
    849     dst[SkMatrix::kMSkewY]  = SkMScalarToScalar(fMat[0][1]);
    850     dst[SkMatrix::kMScaleY] = SkMScalarToScalar(fMat[1][1]);
    851     dst[SkMatrix::kMTransY] = SkMScalarToScalar(fMat[3][1]);
    852 
    853     return dst;
    854 }
    855