Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2006 The Android Open Source Project
      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 "SkMatrix.h"
      9 #include "SkFloatBits.h"
     10 #include "SkString.h"
     11 
     12 #include <stddef.h>
     13 
     14 // In a few places, we performed the following
     15 //      a * b + c * d + e
     16 // as
     17 //      a * b + (c * d + e)
     18 //
     19 // sdot and scross are indended to capture these compound operations into a
     20 // function, with an eye toward considering upscaling the intermediates to
     21 // doubles for more precision (as we do in concat and invert).
     22 //
     23 // However, these few lines that performed the last add before the "dot", cause
     24 // tiny image differences, so we guard that change until we see the impact on
     25 // chrome's layouttests.
     26 //
     27 #define SK_LEGACY_MATRIX_MATH_ORDER
     28 
     29 static inline float SkDoubleToFloat(double x) {
     30     return static_cast<float>(x);
     31 }
     32 
     33 /*      [scale-x    skew-x      trans-x]   [X]   [X']
     34         [skew-y     scale-y     trans-y] * [Y] = [Y']
     35         [persp-0    persp-1     persp-2]   [1]   [1 ]
     36 */
     37 
     38 void SkMatrix::reset() {
     39     fMat[kMScaleX] = fMat[kMScaleY] = fMat[kMPersp2] = 1;
     40     fMat[kMSkewX]  = fMat[kMSkewY] =
     41     fMat[kMTransX] = fMat[kMTransY] =
     42     fMat[kMPersp0] = fMat[kMPersp1] = 0;
     43 
     44     this->setTypeMask(kIdentity_Mask | kRectStaysRect_Mask);
     45 }
     46 
     47 // this guy aligns with the masks, so we can compute a mask from a varaible 0/1
     48 enum {
     49     kTranslate_Shift,
     50     kScale_Shift,
     51     kAffine_Shift,
     52     kPerspective_Shift,
     53     kRectStaysRect_Shift
     54 };
     55 
     56 static const int32_t kScalar1Int = 0x3f800000;
     57 
     58 uint8_t SkMatrix::computePerspectiveTypeMask() const {
     59     // Benchmarking suggests that replacing this set of SkScalarAs2sCompliment
     60     // is a win, but replacing those below is not. We don't yet understand
     61     // that result.
     62     if (fMat[kMPersp0] != 0 || fMat[kMPersp1] != 0 || fMat[kMPersp2] != 1) {
     63         // If this is a perspective transform, we return true for all other
     64         // transform flags - this does not disable any optimizations, respects
     65         // the rule that the type mask must be conservative, and speeds up
     66         // type mask computation.
     67         return SkToU8(kORableMasks);
     68     }
     69 
     70     return SkToU8(kOnlyPerspectiveValid_Mask | kUnknown_Mask);
     71 }
     72 
     73 uint8_t SkMatrix::computeTypeMask() const {
     74     unsigned mask = 0;
     75 
     76     if (fMat[kMPersp0] != 0 || fMat[kMPersp1] != 0 || fMat[kMPersp2] != 1) {
     77         // Once it is determined that that this is a perspective transform,
     78         // all other flags are moot as far as optimizations are concerned.
     79         return SkToU8(kORableMasks);
     80     }
     81 
     82     if (fMat[kMTransX] != 0 || fMat[kMTransY] != 0) {
     83         mask |= kTranslate_Mask;
     84     }
     85 
     86     int m00 = SkScalarAs2sCompliment(fMat[SkMatrix::kMScaleX]);
     87     int m01 = SkScalarAs2sCompliment(fMat[SkMatrix::kMSkewX]);
     88     int m10 = SkScalarAs2sCompliment(fMat[SkMatrix::kMSkewY]);
     89     int m11 = SkScalarAs2sCompliment(fMat[SkMatrix::kMScaleY]);
     90 
     91     if (m01 | m10) {
     92         // The skew components may be scale-inducing, unless we are dealing
     93         // with a pure rotation.  Testing for a pure rotation is expensive,
     94         // so we opt for being conservative by always setting the scale bit.
     95         // along with affine.
     96         // By doing this, we are also ensuring that matrices have the same
     97         // type masks as their inverses.
     98         mask |= kAffine_Mask | kScale_Mask;
     99 
    100         // For rectStaysRect, in the affine case, we only need check that
    101         // the primary diagonal is all zeros and that the secondary diagonal
    102         // is all non-zero.
    103 
    104         // map non-zero to 1
    105         m01 = m01 != 0;
    106         m10 = m10 != 0;
    107 
    108         int dp0 = 0 == (m00 | m11) ;  // true if both are 0
    109         int ds1 = m01 & m10;        // true if both are 1
    110 
    111         mask |= (dp0 & ds1) << kRectStaysRect_Shift;
    112     } else {
    113         // Only test for scale explicitly if not affine, since affine sets the
    114         // scale bit.
    115         if ((m00 - kScalar1Int) | (m11 - kScalar1Int)) {
    116             mask |= kScale_Mask;
    117         }
    118 
    119         // Not affine, therefore we already know secondary diagonal is
    120         // all zeros, so we just need to check that primary diagonal is
    121         // all non-zero.
    122 
    123         // map non-zero to 1
    124         m00 = m00 != 0;
    125         m11 = m11 != 0;
    126 
    127         // record if the (p)rimary diagonal is all non-zero
    128         mask |= (m00 & m11) << kRectStaysRect_Shift;
    129     }
    130 
    131     return SkToU8(mask);
    132 }
    133 
    134 ///////////////////////////////////////////////////////////////////////////////
    135 
    136 bool operator==(const SkMatrix& a, const SkMatrix& b) {
    137     const SkScalar* SK_RESTRICT ma = a.fMat;
    138     const SkScalar* SK_RESTRICT mb = b.fMat;
    139 
    140     return  ma[0] == mb[0] && ma[1] == mb[1] && ma[2] == mb[2] &&
    141             ma[3] == mb[3] && ma[4] == mb[4] && ma[5] == mb[5] &&
    142             ma[6] == mb[6] && ma[7] == mb[7] && ma[8] == mb[8];
    143 }
    144 
    145 ///////////////////////////////////////////////////////////////////////////////
    146 
    147 // helper function to determine if upper-left 2x2 of matrix is degenerate
    148 static inline bool is_degenerate_2x2(SkScalar scaleX, SkScalar skewX,
    149                                      SkScalar skewY,  SkScalar scaleY) {
    150     SkScalar perp_dot = scaleX*scaleY - skewX*skewY;
    151     return SkScalarNearlyZero(perp_dot, SK_ScalarNearlyZero*SK_ScalarNearlyZero);
    152 }
    153 
    154 ///////////////////////////////////////////////////////////////////////////////
    155 
    156 bool SkMatrix::isSimilarity(SkScalar tol) const {
    157     // if identity or translate matrix
    158     TypeMask mask = this->getType();
    159     if (mask <= kTranslate_Mask) {
    160         return true;
    161     }
    162     if (mask & kPerspective_Mask) {
    163         return false;
    164     }
    165 
    166     SkScalar mx = fMat[kMScaleX];
    167     SkScalar my = fMat[kMScaleY];
    168     // if no skew, can just compare scale factors
    169     if (!(mask & kAffine_Mask)) {
    170         return !SkScalarNearlyZero(mx) && SkScalarNearlyEqual(SkScalarAbs(mx), SkScalarAbs(my));
    171     }
    172     SkScalar sx = fMat[kMSkewX];
    173     SkScalar sy = fMat[kMSkewY];
    174 
    175     if (is_degenerate_2x2(mx, sx, sy, my)) {
    176         return false;
    177     }
    178 
    179     // upper 2x2 is rotation/reflection + uniform scale if basis vectors
    180     // are 90 degree rotations of each other
    181     return (SkScalarNearlyEqual(mx, my, tol) && SkScalarNearlyEqual(sx, -sy, tol))
    182         || (SkScalarNearlyEqual(mx, -my, tol) && SkScalarNearlyEqual(sx, sy, tol));
    183 }
    184 
    185 bool SkMatrix::preservesRightAngles(SkScalar tol) const {
    186     TypeMask mask = this->getType();
    187 
    188     if (mask <= kTranslate_Mask) {
    189         // identity, translate and/or scale
    190         return true;
    191     }
    192     if (mask & kPerspective_Mask) {
    193         return false;
    194     }
    195 
    196     SkASSERT(mask & (kAffine_Mask | kScale_Mask));
    197 
    198     SkScalar mx = fMat[kMScaleX];
    199     SkScalar my = fMat[kMScaleY];
    200     SkScalar sx = fMat[kMSkewX];
    201     SkScalar sy = fMat[kMSkewY];
    202 
    203     if (is_degenerate_2x2(mx, sx, sy, my)) {
    204         return false;
    205     }
    206 
    207     // upper 2x2 is scale + rotation/reflection if basis vectors are orthogonal
    208     SkVector vec[2];
    209     vec[0].set(mx, sy);
    210     vec[1].set(sx, my);
    211 
    212     return SkScalarNearlyZero(vec[0].dot(vec[1]), SkScalarSquare(tol));
    213 }
    214 
    215 ///////////////////////////////////////////////////////////////////////////////
    216 
    217 static inline SkScalar sdot(SkScalar a, SkScalar b, SkScalar c, SkScalar d) {
    218     return a * b + c * d;
    219 }
    220 
    221 static inline SkScalar sdot(SkScalar a, SkScalar b, SkScalar c, SkScalar d,
    222                              SkScalar e, SkScalar f) {
    223     return a * b + c * d + e * f;
    224 }
    225 
    226 static inline SkScalar scross(SkScalar a, SkScalar b, SkScalar c, SkScalar d) {
    227     return a * b - c * d;
    228 }
    229 
    230 void SkMatrix::setTranslate(SkScalar dx, SkScalar dy) {
    231     if (dx || dy) {
    232         fMat[kMTransX] = dx;
    233         fMat[kMTransY] = dy;
    234 
    235         fMat[kMScaleX] = fMat[kMScaleY] = fMat[kMPersp2] = 1;
    236         fMat[kMSkewX]  = fMat[kMSkewY] =
    237         fMat[kMPersp0] = fMat[kMPersp1] = 0;
    238 
    239         this->setTypeMask(kTranslate_Mask | kRectStaysRect_Mask);
    240     } else {
    241         this->reset();
    242     }
    243 }
    244 
    245 void SkMatrix::preTranslate(SkScalar dx, SkScalar dy) {
    246     if (!dx && !dy) {
    247         return;
    248     }
    249 
    250     if (this->hasPerspective()) {
    251         SkMatrix    m;
    252         m.setTranslate(dx, dy);
    253         this->preConcat(m);
    254     } else {
    255         fMat[kMTransX] += sdot(fMat[kMScaleX], dx, fMat[kMSkewX], dy);
    256         fMat[kMTransY] += sdot(fMat[kMSkewY], dx, fMat[kMScaleY], dy);
    257         this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
    258     }
    259 }
    260 
    261 void SkMatrix::postTranslate(SkScalar dx, SkScalar dy) {
    262     if (!dx && !dy) {
    263         return;
    264     }
    265 
    266     if (this->hasPerspective()) {
    267         SkMatrix    m;
    268         m.setTranslate(dx, dy);
    269         this->postConcat(m);
    270     } else {
    271         fMat[kMTransX] += dx;
    272         fMat[kMTransY] += dy;
    273         this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
    274     }
    275 }
    276 
    277 ///////////////////////////////////////////////////////////////////////////////
    278 
    279 void SkMatrix::setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
    280     if (1 == sx && 1 == sy) {
    281         this->reset();
    282     } else {
    283         fMat[kMScaleX] = sx;
    284         fMat[kMScaleY] = sy;
    285         fMat[kMTransX] = px - sx * px;
    286         fMat[kMTransY] = py - sy * py;
    287         fMat[kMPersp2] = 1;
    288 
    289         fMat[kMSkewX]  = fMat[kMSkewY] =
    290         fMat[kMPersp0] = fMat[kMPersp1] = 0;
    291 
    292         this->setTypeMask(kScale_Mask | kTranslate_Mask | kRectStaysRect_Mask);
    293     }
    294 }
    295 
    296 void SkMatrix::setScale(SkScalar sx, SkScalar sy) {
    297     if (1 == sx && 1 == sy) {
    298         this->reset();
    299     } else {
    300         fMat[kMScaleX] = sx;
    301         fMat[kMScaleY] = sy;
    302         fMat[kMPersp2] = 1;
    303 
    304         fMat[kMTransX] = fMat[kMTransY] =
    305         fMat[kMSkewX]  = fMat[kMSkewY] =
    306         fMat[kMPersp0] = fMat[kMPersp1] = 0;
    307 
    308         this->setTypeMask(kScale_Mask | kRectStaysRect_Mask);
    309     }
    310 }
    311 
    312 bool SkMatrix::setIDiv(int divx, int divy) {
    313     if (!divx || !divy) {
    314         return false;
    315     }
    316     this->setScale(SkScalarInvert(divx), SkScalarInvert(divy));
    317     return true;
    318 }
    319 
    320 void SkMatrix::preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
    321     if (1 == sx && 1 == sy) {
    322         return;
    323     }
    324 
    325     SkMatrix    m;
    326     m.setScale(sx, sy, px, py);
    327     this->preConcat(m);
    328 }
    329 
    330 void SkMatrix::preScale(SkScalar sx, SkScalar sy) {
    331     if (1 == sx && 1 == sy) {
    332         return;
    333     }
    334 
    335     // the assumption is that these multiplies are very cheap, and that
    336     // a full concat and/or just computing the matrix type is more expensive.
    337     // Also, the fixed-point case checks for overflow, but the float doesn't,
    338     // so we can get away with these blind multiplies.
    339 
    340     fMat[kMScaleX] *= sx;
    341     fMat[kMSkewY]  *= sx;
    342     fMat[kMPersp0] *= sx;
    343 
    344     fMat[kMSkewX]  *= sy;
    345     fMat[kMScaleY] *= sy;
    346     fMat[kMPersp1] *= sy;
    347 
    348     this->orTypeMask(kScale_Mask);
    349 }
    350 
    351 void SkMatrix::postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
    352     if (1 == sx && 1 == sy) {
    353         return;
    354     }
    355     SkMatrix    m;
    356     m.setScale(sx, sy, px, py);
    357     this->postConcat(m);
    358 }
    359 
    360 void SkMatrix::postScale(SkScalar sx, SkScalar sy) {
    361     if (1 == sx && 1 == sy) {
    362         return;
    363     }
    364     SkMatrix    m;
    365     m.setScale(sx, sy);
    366     this->postConcat(m);
    367 }
    368 
    369 // this guy perhaps can go away, if we have a fract/high-precision way to
    370 // scale matrices
    371 bool SkMatrix::postIDiv(int divx, int divy) {
    372     if (divx == 0 || divy == 0) {
    373         return false;
    374     }
    375 
    376     const float invX = 1.f / divx;
    377     const float invY = 1.f / divy;
    378 
    379     fMat[kMScaleX] *= invX;
    380     fMat[kMSkewX]  *= invX;
    381     fMat[kMTransX] *= invX;
    382 
    383     fMat[kMScaleY] *= invY;
    384     fMat[kMSkewY]  *= invY;
    385     fMat[kMTransY] *= invY;
    386 
    387     this->setTypeMask(kUnknown_Mask);
    388     return true;
    389 }
    390 
    391 ////////////////////////////////////////////////////////////////////////////////////
    392 
    393 void SkMatrix::setSinCos(SkScalar sinV, SkScalar cosV,
    394                          SkScalar px, SkScalar py) {
    395     const SkScalar oneMinusCosV = 1 - cosV;
    396 
    397     fMat[kMScaleX]  = cosV;
    398     fMat[kMSkewX]   = -sinV;
    399     fMat[kMTransX]  = sdot(sinV, py, oneMinusCosV, px);
    400 
    401     fMat[kMSkewY]   = sinV;
    402     fMat[kMScaleY]  = cosV;
    403     fMat[kMTransY]  = sdot(-sinV, px, oneMinusCosV, py);
    404 
    405     fMat[kMPersp0] = fMat[kMPersp1] = 0;
    406     fMat[kMPersp2] = 1;
    407 
    408     this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
    409 }
    410 
    411 void SkMatrix::setSinCos(SkScalar sinV, SkScalar cosV) {
    412     fMat[kMScaleX]  = cosV;
    413     fMat[kMSkewX]   = -sinV;
    414     fMat[kMTransX]  = 0;
    415 
    416     fMat[kMSkewY]   = sinV;
    417     fMat[kMScaleY]  = cosV;
    418     fMat[kMTransY]  = 0;
    419 
    420     fMat[kMPersp0] = fMat[kMPersp1] = 0;
    421     fMat[kMPersp2] = 1;
    422 
    423     this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
    424 }
    425 
    426 void SkMatrix::setRotate(SkScalar degrees, SkScalar px, SkScalar py) {
    427     SkScalar sinV, cosV;
    428     sinV = SkScalarSinCos(SkDegreesToRadians(degrees), &cosV);
    429     this->setSinCos(sinV, cosV, px, py);
    430 }
    431 
    432 void SkMatrix::setRotate(SkScalar degrees) {
    433     SkScalar sinV, cosV;
    434     sinV = SkScalarSinCos(SkDegreesToRadians(degrees), &cosV);
    435     this->setSinCos(sinV, cosV);
    436 }
    437 
    438 void SkMatrix::preRotate(SkScalar degrees, SkScalar px, SkScalar py) {
    439     SkMatrix    m;
    440     m.setRotate(degrees, px, py);
    441     this->preConcat(m);
    442 }
    443 
    444 void SkMatrix::preRotate(SkScalar degrees) {
    445     SkMatrix    m;
    446     m.setRotate(degrees);
    447     this->preConcat(m);
    448 }
    449 
    450 void SkMatrix::postRotate(SkScalar degrees, SkScalar px, SkScalar py) {
    451     SkMatrix    m;
    452     m.setRotate(degrees, px, py);
    453     this->postConcat(m);
    454 }
    455 
    456 void SkMatrix::postRotate(SkScalar degrees) {
    457     SkMatrix    m;
    458     m.setRotate(degrees);
    459     this->postConcat(m);
    460 }
    461 
    462 ////////////////////////////////////////////////////////////////////////////////////
    463 
    464 void SkMatrix::setSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
    465     fMat[kMScaleX]  = 1;
    466     fMat[kMSkewX]   = sx;
    467     fMat[kMTransX]  = -sx * py;
    468 
    469     fMat[kMSkewY]   = sy;
    470     fMat[kMScaleY]  = 1;
    471     fMat[kMTransY]  = -sy * px;
    472 
    473     fMat[kMPersp0] = fMat[kMPersp1] = 0;
    474     fMat[kMPersp2] = 1;
    475 
    476     this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
    477 }
    478 
    479 void SkMatrix::setSkew(SkScalar sx, SkScalar sy) {
    480     fMat[kMScaleX]  = 1;
    481     fMat[kMSkewX]   = sx;
    482     fMat[kMTransX]  = 0;
    483 
    484     fMat[kMSkewY]   = sy;
    485     fMat[kMScaleY]  = 1;
    486     fMat[kMTransY]  = 0;
    487 
    488     fMat[kMPersp0] = fMat[kMPersp1] = 0;
    489     fMat[kMPersp2] = 1;
    490 
    491     this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
    492 }
    493 
    494 void SkMatrix::preSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
    495     SkMatrix    m;
    496     m.setSkew(sx, sy, px, py);
    497     this->preConcat(m);
    498 }
    499 
    500 void SkMatrix::preSkew(SkScalar sx, SkScalar sy) {
    501     SkMatrix    m;
    502     m.setSkew(sx, sy);
    503     this->preConcat(m);
    504 }
    505 
    506 void SkMatrix::postSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
    507     SkMatrix    m;
    508     m.setSkew(sx, sy, px, py);
    509     this->postConcat(m);
    510 }
    511 
    512 void SkMatrix::postSkew(SkScalar sx, SkScalar sy) {
    513     SkMatrix    m;
    514     m.setSkew(sx, sy);
    515     this->postConcat(m);
    516 }
    517 
    518 ///////////////////////////////////////////////////////////////////////////////
    519 
    520 bool SkMatrix::setRectToRect(const SkRect& src, const SkRect& dst,
    521                              ScaleToFit align)
    522 {
    523     if (src.isEmpty()) {
    524         this->reset();
    525         return false;
    526     }
    527 
    528     if (dst.isEmpty()) {
    529         sk_bzero(fMat, 8 * sizeof(SkScalar));
    530         this->setTypeMask(kScale_Mask | kRectStaysRect_Mask);
    531     } else {
    532         SkScalar    tx, sx = dst.width() / src.width();
    533         SkScalar    ty, sy = dst.height() / src.height();
    534         bool        xLarger = false;
    535 
    536         if (align != kFill_ScaleToFit) {
    537             if (sx > sy) {
    538                 xLarger = true;
    539                 sx = sy;
    540             } else {
    541                 sy = sx;
    542             }
    543         }
    544 
    545         tx = dst.fLeft - src.fLeft * sx;
    546         ty = dst.fTop - src.fTop * sy;
    547         if (align == kCenter_ScaleToFit || align == kEnd_ScaleToFit) {
    548             SkScalar diff;
    549 
    550             if (xLarger) {
    551                 diff = dst.width() - src.width() * sy;
    552             } else {
    553                 diff = dst.height() - src.height() * sy;
    554             }
    555 
    556             if (align == kCenter_ScaleToFit) {
    557                 diff = SkScalarHalf(diff);
    558             }
    559 
    560             if (xLarger) {
    561                 tx += diff;
    562             } else {
    563                 ty += diff;
    564             }
    565         }
    566 
    567         fMat[kMScaleX] = sx;
    568         fMat[kMScaleY] = sy;
    569         fMat[kMTransX] = tx;
    570         fMat[kMTransY] = ty;
    571         fMat[kMSkewX]  = fMat[kMSkewY] =
    572         fMat[kMPersp0] = fMat[kMPersp1] = 0;
    573 
    574         unsigned mask = kRectStaysRect_Mask;
    575         if (sx != 1 || sy != 1) {
    576             mask |= kScale_Mask;
    577         }
    578         if (tx || ty) {
    579             mask |= kTranslate_Mask;
    580         }
    581         this->setTypeMask(mask);
    582     }
    583     // shared cleanup
    584     fMat[kMPersp2] = 1;
    585     return true;
    586 }
    587 
    588 ///////////////////////////////////////////////////////////////////////////////
    589 
    590 static inline float muladdmul(float a, float b, float c, float d) {
    591     return SkDoubleToFloat((double)a * b + (double)c * d);
    592 }
    593 
    594 static inline float rowcol3(const float row[], const float col[]) {
    595     return row[0] * col[0] + row[1] * col[3] + row[2] * col[6];
    596 }
    597 
    598 static void normalize_perspective(SkScalar mat[9]) {
    599     if (SkScalarAbs(mat[SkMatrix::kMPersp2]) > 1) {
    600         for (int i = 0; i < 9; i++)
    601             mat[i] = SkScalarHalf(mat[i]);
    602     }
    603 }
    604 
    605 void SkMatrix::setConcat(const SkMatrix& a, const SkMatrix& b) {
    606     TypeMask aType = a.getPerspectiveTypeMaskOnly();
    607     TypeMask bType = b.getPerspectiveTypeMaskOnly();
    608 
    609     if (a.isTriviallyIdentity()) {
    610         *this = b;
    611     } else if (b.isTriviallyIdentity()) {
    612         *this = a;
    613     } else {
    614         SkMatrix tmp;
    615 
    616         if ((aType | bType) & kPerspective_Mask) {
    617             tmp.fMat[kMScaleX] = rowcol3(&a.fMat[0], &b.fMat[0]);
    618             tmp.fMat[kMSkewX]  = rowcol3(&a.fMat[0], &b.fMat[1]);
    619             tmp.fMat[kMTransX] = rowcol3(&a.fMat[0], &b.fMat[2]);
    620             tmp.fMat[kMSkewY]  = rowcol3(&a.fMat[3], &b.fMat[0]);
    621             tmp.fMat[kMScaleY] = rowcol3(&a.fMat[3], &b.fMat[1]);
    622             tmp.fMat[kMTransY] = rowcol3(&a.fMat[3], &b.fMat[2]);
    623             tmp.fMat[kMPersp0] = rowcol3(&a.fMat[6], &b.fMat[0]);
    624             tmp.fMat[kMPersp1] = rowcol3(&a.fMat[6], &b.fMat[1]);
    625             tmp.fMat[kMPersp2] = rowcol3(&a.fMat[6], &b.fMat[2]);
    626 
    627             normalize_perspective(tmp.fMat);
    628             tmp.setTypeMask(kUnknown_Mask);
    629         } else {    // not perspective
    630             tmp.fMat[kMScaleX] = muladdmul(a.fMat[kMScaleX],
    631                                            b.fMat[kMScaleX],
    632                                            a.fMat[kMSkewX],
    633                                            b.fMat[kMSkewY]);
    634 
    635             tmp.fMat[kMSkewX]  = muladdmul(a.fMat[kMScaleX],
    636                                            b.fMat[kMSkewX],
    637                                            a.fMat[kMSkewX],
    638                                            b.fMat[kMScaleY]);
    639 
    640             tmp.fMat[kMTransX] = muladdmul(a.fMat[kMScaleX],
    641                                            b.fMat[kMTransX],
    642                                            a.fMat[kMSkewX],
    643                                            b.fMat[kMTransY]);
    644 
    645             tmp.fMat[kMTransX] += a.fMat[kMTransX];
    646 
    647             tmp.fMat[kMSkewY]  = muladdmul(a.fMat[kMSkewY],
    648                                            b.fMat[kMScaleX],
    649                                            a.fMat[kMScaleY],
    650                                            b.fMat[kMSkewY]);
    651 
    652             tmp.fMat[kMScaleY] = muladdmul(a.fMat[kMSkewY],
    653                                            b.fMat[kMSkewX],
    654                                            a.fMat[kMScaleY],
    655                                            b.fMat[kMScaleY]);
    656 
    657             tmp.fMat[kMTransY] = muladdmul(a.fMat[kMSkewY],
    658                                            b.fMat[kMTransX],
    659                                            a.fMat[kMScaleY],
    660                                            b.fMat[kMTransY]);
    661 
    662             tmp.fMat[kMTransY] += a.fMat[kMTransY];
    663             tmp.fMat[kMPersp0] = tmp.fMat[kMPersp1] = 0;
    664             tmp.fMat[kMPersp2] = 1;
    665             //SkDebugf("Concat mat non-persp type: %d\n", tmp.getType());
    666             //SkASSERT(!(tmp.getType() & kPerspective_Mask));
    667             tmp.setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
    668         }
    669         *this = tmp;
    670     }
    671 }
    672 
    673 void SkMatrix::preConcat(const SkMatrix& mat) {
    674     // check for identity first, so we don't do a needless copy of ourselves
    675     // to ourselves inside setConcat()
    676     if(!mat.isIdentity()) {
    677         this->setConcat(*this, mat);
    678     }
    679 }
    680 
    681 void SkMatrix::postConcat(const SkMatrix& mat) {
    682     // check for identity first, so we don't do a needless copy of ourselves
    683     // to ourselves inside setConcat()
    684     if (!mat.isIdentity()) {
    685         this->setConcat(mat, *this);
    686     }
    687 }
    688 
    689 ///////////////////////////////////////////////////////////////////////////////
    690 
    691 /*  Matrix inversion is very expensive, but also the place where keeping
    692     precision may be most important (here and matrix concat). Hence to avoid
    693     bitmap blitting artifacts when walking the inverse, we use doubles for
    694     the intermediate math, even though we know that is more expensive.
    695  */
    696 
    697 static inline SkScalar scross_dscale(SkScalar a, SkScalar b,
    698                                      SkScalar c, SkScalar d, double scale) {
    699     return SkDoubleToScalar(scross(a, b, c, d) * scale);
    700 }
    701 
    702 static inline double dcross(double a, double b, double c, double d) {
    703     return a * b - c * d;
    704 }
    705 
    706 static inline SkScalar dcross_dscale(double a, double b,
    707                                      double c, double d, double scale) {
    708     return SkDoubleToScalar(dcross(a, b, c, d) * scale);
    709 }
    710 
    711 static double sk_inv_determinant(const float mat[9], int isPerspective) {
    712     double det;
    713 
    714     if (isPerspective) {
    715         det = mat[SkMatrix::kMScaleX] *
    716               dcross(mat[SkMatrix::kMScaleY], mat[SkMatrix::kMPersp2],
    717                      mat[SkMatrix::kMTransY], mat[SkMatrix::kMPersp1])
    718               +
    719               mat[SkMatrix::kMSkewX]  *
    720               dcross(mat[SkMatrix::kMTransY], mat[SkMatrix::kMPersp0],
    721                      mat[SkMatrix::kMSkewY],  mat[SkMatrix::kMPersp2])
    722               +
    723               mat[SkMatrix::kMTransX] *
    724               dcross(mat[SkMatrix::kMSkewY],  mat[SkMatrix::kMPersp1],
    725                      mat[SkMatrix::kMScaleY], mat[SkMatrix::kMPersp0]);
    726     } else {
    727         det = dcross(mat[SkMatrix::kMScaleX], mat[SkMatrix::kMScaleY],
    728                      mat[SkMatrix::kMSkewX], mat[SkMatrix::kMSkewY]);
    729     }
    730 
    731     // Since the determinant is on the order of the cube of the matrix members,
    732     // compare to the cube of the default nearly-zero constant (although an
    733     // estimate of the condition number would be better if it wasn't so expensive).
    734     if (SkScalarNearlyZero((float)det, SK_ScalarNearlyZero * SK_ScalarNearlyZero * SK_ScalarNearlyZero)) {
    735         return 0;
    736     }
    737     return 1.0 / det;
    738 }
    739 
    740 void SkMatrix::SetAffineIdentity(SkScalar affine[6]) {
    741     affine[kAScaleX] = 1;
    742     affine[kASkewY] = 0;
    743     affine[kASkewX] = 0;
    744     affine[kAScaleY] = 1;
    745     affine[kATransX] = 0;
    746     affine[kATransY] = 0;
    747 }
    748 
    749 bool SkMatrix::asAffine(SkScalar affine[6]) const {
    750     if (this->hasPerspective()) {
    751         return false;
    752     }
    753     if (affine) {
    754         affine[kAScaleX] = this->fMat[kMScaleX];
    755         affine[kASkewY] = this->fMat[kMSkewY];
    756         affine[kASkewX] = this->fMat[kMSkewX];
    757         affine[kAScaleY] = this->fMat[kMScaleY];
    758         affine[kATransX] = this->fMat[kMTransX];
    759         affine[kATransY] = this->fMat[kMTransY];
    760     }
    761     return true;
    762 }
    763 
    764 bool SkMatrix::invertNonIdentity(SkMatrix* inv) const {
    765     SkASSERT(!this->isIdentity());
    766 
    767     TypeMask mask = this->getType();
    768 
    769     if (0 == (mask & ~(kScale_Mask | kTranslate_Mask))) {
    770         bool invertible = true;
    771         if (inv) {
    772             if (mask & kScale_Mask) {
    773                 SkScalar invX = fMat[kMScaleX];
    774                 SkScalar invY = fMat[kMScaleY];
    775                 if (0 == invX || 0 == invY) {
    776                     return false;
    777                 }
    778                 invX = SkScalarInvert(invX);
    779                 invY = SkScalarInvert(invY);
    780 
    781                 // Must be careful when writing to inv, since it may be the
    782                 // same memory as this.
    783 
    784                 inv->fMat[kMSkewX] = inv->fMat[kMSkewY] =
    785                 inv->fMat[kMPersp0] = inv->fMat[kMPersp1] = 0;
    786 
    787                 inv->fMat[kMScaleX] = invX;
    788                 inv->fMat[kMScaleY] = invY;
    789                 inv->fMat[kMPersp2] = 1;
    790                 inv->fMat[kMTransX] = -fMat[kMTransX] * invX;
    791                 inv->fMat[kMTransY] = -fMat[kMTransY] * invY;
    792 
    793                 inv->setTypeMask(mask | kRectStaysRect_Mask);
    794             } else {
    795                 // translate only
    796                 inv->setTranslate(-fMat[kMTransX], -fMat[kMTransY]);
    797             }
    798         } else {    // inv is NULL, just check if we're invertible
    799             if (!fMat[kMScaleX] || !fMat[kMScaleY]) {
    800                 invertible = false;
    801             }
    802         }
    803         return invertible;
    804     }
    805 
    806     int    isPersp = mask & kPerspective_Mask;
    807     double scale = sk_inv_determinant(fMat, isPersp);
    808 
    809     if (scale == 0) { // underflow
    810         return false;
    811     }
    812 
    813     if (inv) {
    814         SkMatrix tmp;
    815         if (inv == this) {
    816             inv = &tmp;
    817         }
    818 
    819         if (isPersp) {
    820             inv->fMat[kMScaleX] = scross_dscale(fMat[kMScaleY], fMat[kMPersp2], fMat[kMTransY], fMat[kMPersp1], scale);
    821             inv->fMat[kMSkewX]  = scross_dscale(fMat[kMTransX], fMat[kMPersp1], fMat[kMSkewX],  fMat[kMPersp2], scale);
    822             inv->fMat[kMTransX] = scross_dscale(fMat[kMSkewX],  fMat[kMTransY], fMat[kMTransX], fMat[kMScaleY], scale);
    823 
    824             inv->fMat[kMSkewY]  = scross_dscale(fMat[kMTransY], fMat[kMPersp0], fMat[kMSkewY],  fMat[kMPersp2], scale);
    825             inv->fMat[kMScaleY] = scross_dscale(fMat[kMScaleX], fMat[kMPersp2], fMat[kMTransX], fMat[kMPersp0], scale);
    826             inv->fMat[kMTransY] = scross_dscale(fMat[kMTransX], fMat[kMSkewY],  fMat[kMScaleX], fMat[kMTransY], scale);
    827 
    828             inv->fMat[kMPersp0] = scross_dscale(fMat[kMSkewY],  fMat[kMPersp1], fMat[kMScaleY], fMat[kMPersp0], scale);
    829             inv->fMat[kMPersp1] = scross_dscale(fMat[kMSkewX],  fMat[kMPersp0], fMat[kMScaleX], fMat[kMPersp1], scale);
    830             inv->fMat[kMPersp2] = scross_dscale(fMat[kMScaleX], fMat[kMScaleY], fMat[kMSkewX],  fMat[kMSkewY],  scale);
    831         } else {   // not perspective
    832             inv->fMat[kMScaleX] = SkDoubleToScalar(fMat[kMScaleY] * scale);
    833             inv->fMat[kMSkewX]  = SkDoubleToScalar(-fMat[kMSkewX] * scale);
    834             inv->fMat[kMTransX] = dcross_dscale(fMat[kMSkewX], fMat[kMTransY], fMat[kMScaleY], fMat[kMTransX], scale);
    835 
    836             inv->fMat[kMSkewY]  = SkDoubleToScalar(-fMat[kMSkewY] * scale);
    837             inv->fMat[kMScaleY] = SkDoubleToScalar(fMat[kMScaleX] * scale);
    838             inv->fMat[kMTransY] = dcross_dscale(fMat[kMSkewY], fMat[kMTransX], fMat[kMScaleX], fMat[kMTransY], scale);
    839 
    840             inv->fMat[kMPersp0] = 0;
    841             inv->fMat[kMPersp1] = 0;
    842             inv->fMat[kMPersp2] = 1;
    843         }
    844 
    845         inv->setTypeMask(fTypeMask);
    846 
    847         if (inv == &tmp) {
    848             *(SkMatrix*)this = tmp;
    849         }
    850     }
    851     return true;
    852 }
    853 
    854 ///////////////////////////////////////////////////////////////////////////////
    855 
    856 void SkMatrix::Identity_pts(const SkMatrix& m, SkPoint dst[],
    857                             const SkPoint src[], int count) {
    858     SkASSERT(m.getType() == 0);
    859 
    860     if (dst != src && count > 0)
    861         memcpy(dst, src, count * sizeof(SkPoint));
    862 }
    863 
    864 void SkMatrix::Trans_pts(const SkMatrix& m, SkPoint dst[],
    865                          const SkPoint src[], int count) {
    866     SkASSERT(m.getType() == kTranslate_Mask);
    867 
    868     if (count > 0) {
    869         SkScalar tx = m.fMat[kMTransX];
    870         SkScalar ty = m.fMat[kMTransY];
    871         do {
    872             dst->fY = src->fY + ty;
    873             dst->fX = src->fX + tx;
    874             src += 1;
    875             dst += 1;
    876         } while (--count);
    877     }
    878 }
    879 
    880 void SkMatrix::Scale_pts(const SkMatrix& m, SkPoint dst[],
    881                          const SkPoint src[], int count) {
    882     SkASSERT(m.getType() == kScale_Mask);
    883 
    884     if (count > 0) {
    885         SkScalar mx = m.fMat[kMScaleX];
    886         SkScalar my = m.fMat[kMScaleY];
    887         do {
    888             dst->fY = src->fY * my;
    889             dst->fX = src->fX * mx;
    890             src += 1;
    891             dst += 1;
    892         } while (--count);
    893     }
    894 }
    895 
    896 void SkMatrix::ScaleTrans_pts(const SkMatrix& m, SkPoint dst[],
    897                               const SkPoint src[], int count) {
    898     SkASSERT(m.getType() == (kScale_Mask | kTranslate_Mask));
    899 
    900     if (count > 0) {
    901         SkScalar mx = m.fMat[kMScaleX];
    902         SkScalar my = m.fMat[kMScaleY];
    903         SkScalar tx = m.fMat[kMTransX];
    904         SkScalar ty = m.fMat[kMTransY];
    905         do {
    906             dst->fY = src->fY * my + ty;
    907             dst->fX = src->fX * mx + tx;
    908             src += 1;
    909             dst += 1;
    910         } while (--count);
    911     }
    912 }
    913 
    914 void SkMatrix::Rot_pts(const SkMatrix& m, SkPoint dst[],
    915                        const SkPoint src[], int count) {
    916     SkASSERT((m.getType() & (kPerspective_Mask | kTranslate_Mask)) == 0);
    917 
    918     if (count > 0) {
    919         SkScalar mx = m.fMat[kMScaleX];
    920         SkScalar my = m.fMat[kMScaleY];
    921         SkScalar kx = m.fMat[kMSkewX];
    922         SkScalar ky = m.fMat[kMSkewY];
    923         do {
    924             SkScalar sy = src->fY;
    925             SkScalar sx = src->fX;
    926             src += 1;
    927             dst->fY = sdot(sx, ky, sy, my);
    928             dst->fX = sdot(sx, mx, sy, kx);
    929             dst += 1;
    930         } while (--count);
    931     }
    932 }
    933 
    934 void SkMatrix::RotTrans_pts(const SkMatrix& m, SkPoint dst[],
    935                             const SkPoint src[], int count) {
    936     SkASSERT(!m.hasPerspective());
    937 
    938     if (count > 0) {
    939         SkScalar mx = m.fMat[kMScaleX];
    940         SkScalar my = m.fMat[kMScaleY];
    941         SkScalar kx = m.fMat[kMSkewX];
    942         SkScalar ky = m.fMat[kMSkewY];
    943         SkScalar tx = m.fMat[kMTransX];
    944         SkScalar ty = m.fMat[kMTransY];
    945         do {
    946             SkScalar sy = src->fY;
    947             SkScalar sx = src->fX;
    948             src += 1;
    949 #ifdef SK_LEGACY_MATRIX_MATH_ORDER
    950             dst->fY = sx * ky + (sy * my + ty);
    951             dst->fX = sx * mx + (sy * kx + tx);
    952 #else
    953             dst->fY = sdot(sx, ky, sy, my) + ty;
    954             dst->fX = sdot(sx, mx, sy, kx) + tx;
    955 #endif
    956             dst += 1;
    957         } while (--count);
    958     }
    959 }
    960 
    961 void SkMatrix::Persp_pts(const SkMatrix& m, SkPoint dst[],
    962                          const SkPoint src[], int count) {
    963     SkASSERT(m.hasPerspective());
    964 
    965     if (count > 0) {
    966         do {
    967             SkScalar sy = src->fY;
    968             SkScalar sx = src->fX;
    969             src += 1;
    970 
    971             SkScalar x = sdot(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX])  + m.fMat[kMTransX];
    972             SkScalar y = sdot(sx, m.fMat[kMSkewY],  sy, m.fMat[kMScaleY]) + m.fMat[kMTransY];
    973 #ifdef SK_LEGACY_MATRIX_MATH_ORDER
    974             SkScalar z = sx * m.fMat[kMPersp0] + (sy * m.fMat[kMPersp1] + m.fMat[kMPersp2]);
    975 #else
    976             SkScalar z = sdot(sx, m.fMat[kMPersp0], sy, m.fMat[kMPersp1]) + m.fMat[kMPersp2];
    977 #endif
    978             if (z) {
    979                 z = SkScalarFastInvert(z);
    980             }
    981 
    982             dst->fY = y * z;
    983             dst->fX = x * z;
    984             dst += 1;
    985         } while (--count);
    986     }
    987 }
    988 
    989 const SkMatrix::MapPtsProc SkMatrix::gMapPtsProcs[] = {
    990     SkMatrix::Identity_pts, SkMatrix::Trans_pts,
    991     SkMatrix::Scale_pts,    SkMatrix::ScaleTrans_pts,
    992     SkMatrix::Rot_pts,      SkMatrix::RotTrans_pts,
    993     SkMatrix::Rot_pts,      SkMatrix::RotTrans_pts,
    994     // repeat the persp proc 8 times
    995     SkMatrix::Persp_pts,    SkMatrix::Persp_pts,
    996     SkMatrix::Persp_pts,    SkMatrix::Persp_pts,
    997     SkMatrix::Persp_pts,    SkMatrix::Persp_pts,
    998     SkMatrix::Persp_pts,    SkMatrix::Persp_pts
    999 };
   1000 
   1001 void SkMatrix::mapPoints(SkPoint dst[], const SkPoint src[], int count) const {
   1002     SkASSERT((dst && src && count > 0) || 0 == count);
   1003     // no partial overlap
   1004     SkASSERT(src == dst || &dst[count] <= &src[0] || &src[count] <= &dst[0]);
   1005 
   1006     this->getMapPtsProc()(*this, dst, src, count);
   1007 }
   1008 
   1009 ///////////////////////////////////////////////////////////////////////////////
   1010 
   1011 void SkMatrix::mapHomogeneousPoints(SkScalar dst[], const SkScalar src[], int count) const {
   1012     SkASSERT((dst && src && count > 0) || 0 == count);
   1013     // no partial overlap
   1014     SkASSERT(src == dst || SkAbs32((int32_t)(src - dst)) >= 3*count);
   1015 
   1016     if (count > 0) {
   1017         if (this->isIdentity()) {
   1018             memcpy(dst, src, 3*count*sizeof(SkScalar));
   1019             return;
   1020         }
   1021         do {
   1022             SkScalar sx = src[0];
   1023             SkScalar sy = src[1];
   1024             SkScalar sw = src[2];
   1025             src += 3;
   1026 
   1027             SkScalar x = sdot(sx, fMat[kMScaleX], sy, fMat[kMSkewX],  sw, fMat[kMTransX]);
   1028             SkScalar y = sdot(sx, fMat[kMSkewY],  sy, fMat[kMScaleY], sw, fMat[kMTransY]);
   1029             SkScalar w = sdot(sx, fMat[kMPersp0], sy, fMat[kMPersp1], sw, fMat[kMPersp2]);
   1030 
   1031             dst[0] = x;
   1032             dst[1] = y;
   1033             dst[2] = w;
   1034             dst += 3;
   1035         } while (--count);
   1036     }
   1037 }
   1038 
   1039 ///////////////////////////////////////////////////////////////////////////////
   1040 
   1041 void SkMatrix::mapVectors(SkPoint dst[], const SkPoint src[], int count) const {
   1042     if (this->hasPerspective()) {
   1043         SkPoint origin;
   1044 
   1045         MapXYProc proc = this->getMapXYProc();
   1046         proc(*this, 0, 0, &origin);
   1047 
   1048         for (int i = count - 1; i >= 0; --i) {
   1049             SkPoint tmp;
   1050 
   1051             proc(*this, src[i].fX, src[i].fY, &tmp);
   1052             dst[i].set(tmp.fX - origin.fX, tmp.fY - origin.fY);
   1053         }
   1054     } else {
   1055         SkMatrix tmp = *this;
   1056 
   1057         tmp.fMat[kMTransX] = tmp.fMat[kMTransY] = 0;
   1058         tmp.clearTypeMask(kTranslate_Mask);
   1059         tmp.mapPoints(dst, src, count);
   1060     }
   1061 }
   1062 
   1063 bool SkMatrix::mapRect(SkRect* dst, const SkRect& src) const {
   1064     SkASSERT(dst);
   1065 
   1066     if (this->rectStaysRect()) {
   1067         this->mapPoints((SkPoint*)dst, (const SkPoint*)&src, 2);
   1068         dst->sort();
   1069         return true;
   1070     } else {
   1071         SkPoint quad[4];
   1072 
   1073         src.toQuad(quad);
   1074         this->mapPoints(quad, quad, 4);
   1075         dst->set(quad, 4);
   1076         return false;
   1077     }
   1078 }
   1079 
   1080 SkScalar SkMatrix::mapRadius(SkScalar radius) const {
   1081     SkVector    vec[2];
   1082 
   1083     vec[0].set(radius, 0);
   1084     vec[1].set(0, radius);
   1085     this->mapVectors(vec, 2);
   1086 
   1087     SkScalar d0 = vec[0].length();
   1088     SkScalar d1 = vec[1].length();
   1089 
   1090     // return geometric mean
   1091     return SkScalarSqrt(d0 * d1);
   1092 }
   1093 
   1094 ///////////////////////////////////////////////////////////////////////////////
   1095 
   1096 void SkMatrix::Persp_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
   1097                         SkPoint* pt) {
   1098     SkASSERT(m.hasPerspective());
   1099 
   1100     SkScalar x = sdot(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX])  + m.fMat[kMTransX];
   1101     SkScalar y = sdot(sx, m.fMat[kMSkewY],  sy, m.fMat[kMScaleY]) + m.fMat[kMTransY];
   1102     SkScalar z = sdot(sx, m.fMat[kMPersp0], sy, m.fMat[kMPersp1]) + m.fMat[kMPersp2];
   1103     if (z) {
   1104         z = SkScalarFastInvert(z);
   1105     }
   1106     pt->fX = x * z;
   1107     pt->fY = y * z;
   1108 }
   1109 
   1110 void SkMatrix::RotTrans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
   1111                            SkPoint* pt) {
   1112     SkASSERT((m.getType() & (kAffine_Mask | kPerspective_Mask)) == kAffine_Mask);
   1113 
   1114 #ifdef SK_LEGACY_MATRIX_MATH_ORDER
   1115     pt->fX = sx * m.fMat[kMScaleX] + (sy * m.fMat[kMSkewX]  +  m.fMat[kMTransX]);
   1116     pt->fY = sx * m.fMat[kMSkewY]  + (sy * m.fMat[kMScaleY] + m.fMat[kMTransY]);
   1117 #else
   1118     pt->fX = sdot(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX])  + m.fMat[kMTransX];
   1119     pt->fY = sdot(sx, m.fMat[kMSkewY],  sy, m.fMat[kMScaleY]) + m.fMat[kMTransY];
   1120 #endif
   1121 }
   1122 
   1123 void SkMatrix::Rot_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
   1124                       SkPoint* pt) {
   1125     SkASSERT((m.getType() & (kAffine_Mask | kPerspective_Mask))== kAffine_Mask);
   1126     SkASSERT(0 == m.fMat[kMTransX]);
   1127     SkASSERT(0 == m.fMat[kMTransY]);
   1128 
   1129 #ifdef SK_LEGACY_MATRIX_MATH_ORDER
   1130     pt->fX = sx * m.fMat[kMScaleX] + (sy * m.fMat[kMSkewX]  + m.fMat[kMTransX]);
   1131     pt->fY = sx * m.fMat[kMSkewY]  + (sy * m.fMat[kMScaleY] + m.fMat[kMTransY]);
   1132 #else
   1133     pt->fX = sdot(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX])  + m.fMat[kMTransX];
   1134     pt->fY = sdot(sx, m.fMat[kMSkewY],  sy, m.fMat[kMScaleY]) + m.fMat[kMTransY];
   1135 #endif
   1136 }
   1137 
   1138 void SkMatrix::ScaleTrans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
   1139                              SkPoint* pt) {
   1140     SkASSERT((m.getType() & (kScale_Mask | kAffine_Mask | kPerspective_Mask))
   1141              == kScale_Mask);
   1142 
   1143     pt->fX = sx * m.fMat[kMScaleX] + m.fMat[kMTransX];
   1144     pt->fY = sy * m.fMat[kMScaleY] + m.fMat[kMTransY];
   1145 }
   1146 
   1147 void SkMatrix::Scale_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
   1148                         SkPoint* pt) {
   1149     SkASSERT((m.getType() & (kScale_Mask | kAffine_Mask | kPerspective_Mask))
   1150              == kScale_Mask);
   1151     SkASSERT(0 == m.fMat[kMTransX]);
   1152     SkASSERT(0 == m.fMat[kMTransY]);
   1153 
   1154     pt->fX = sx * m.fMat[kMScaleX];
   1155     pt->fY = sy * m.fMat[kMScaleY];
   1156 }
   1157 
   1158 void SkMatrix::Trans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
   1159                         SkPoint* pt) {
   1160     SkASSERT(m.getType() == kTranslate_Mask);
   1161 
   1162     pt->fX = sx + m.fMat[kMTransX];
   1163     pt->fY = sy + m.fMat[kMTransY];
   1164 }
   1165 
   1166 void SkMatrix::Identity_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
   1167                            SkPoint* pt) {
   1168     SkASSERT(0 == m.getType());
   1169 
   1170     pt->fX = sx;
   1171     pt->fY = sy;
   1172 }
   1173 
   1174 const SkMatrix::MapXYProc SkMatrix::gMapXYProcs[] = {
   1175     SkMatrix::Identity_xy, SkMatrix::Trans_xy,
   1176     SkMatrix::Scale_xy,    SkMatrix::ScaleTrans_xy,
   1177     SkMatrix::Rot_xy,      SkMatrix::RotTrans_xy,
   1178     SkMatrix::Rot_xy,      SkMatrix::RotTrans_xy,
   1179     // repeat the persp proc 8 times
   1180     SkMatrix::Persp_xy,    SkMatrix::Persp_xy,
   1181     SkMatrix::Persp_xy,    SkMatrix::Persp_xy,
   1182     SkMatrix::Persp_xy,    SkMatrix::Persp_xy,
   1183     SkMatrix::Persp_xy,    SkMatrix::Persp_xy
   1184 };
   1185 
   1186 ///////////////////////////////////////////////////////////////////////////////
   1187 
   1188 // if its nearly zero (just made up 26, perhaps it should be bigger or smaller)
   1189 #define PerspNearlyZero(x)  SkScalarNearlyZero(x, (1.0f / (1 << 26)))
   1190 
   1191 bool SkMatrix::fixedStepInX(SkScalar y, SkFixed* stepX, SkFixed* stepY) const {
   1192     if (PerspNearlyZero(fMat[kMPersp0])) {
   1193         if (stepX || stepY) {
   1194             if (PerspNearlyZero(fMat[kMPersp1]) &&
   1195                     PerspNearlyZero(fMat[kMPersp2] - 1)) {
   1196                 if (stepX) {
   1197                     *stepX = SkScalarToFixed(fMat[kMScaleX]);
   1198                 }
   1199                 if (stepY) {
   1200                     *stepY = SkScalarToFixed(fMat[kMSkewY]);
   1201                 }
   1202             } else {
   1203                 SkScalar z = y * fMat[kMPersp1] + fMat[kMPersp2];
   1204                 if (stepX) {
   1205                     *stepX = SkScalarToFixed(fMat[kMScaleX] / z);
   1206                 }
   1207                 if (stepY) {
   1208                     *stepY = SkScalarToFixed(fMat[kMSkewY] / z);
   1209                 }
   1210             }
   1211         }
   1212         return true;
   1213     }
   1214     return false;
   1215 }
   1216 
   1217 ///////////////////////////////////////////////////////////////////////////////
   1218 
   1219 #include "SkPerspIter.h"
   1220 
   1221 SkPerspIter::SkPerspIter(const SkMatrix& m, SkScalar x0, SkScalar y0, int count)
   1222         : fMatrix(m), fSX(x0), fSY(y0), fCount(count) {
   1223     SkPoint pt;
   1224 
   1225     SkMatrix::Persp_xy(m, x0, y0, &pt);
   1226     fX = SkScalarToFixed(pt.fX);
   1227     fY = SkScalarToFixed(pt.fY);
   1228 }
   1229 
   1230 int SkPerspIter::next() {
   1231     int n = fCount;
   1232 
   1233     if (0 == n) {
   1234         return 0;
   1235     }
   1236     SkPoint pt;
   1237     SkFixed x = fX;
   1238     SkFixed y = fY;
   1239     SkFixed dx, dy;
   1240 
   1241     if (n >= kCount) {
   1242         n = kCount;
   1243         fSX += SkIntToScalar(kCount);
   1244         SkMatrix::Persp_xy(fMatrix, fSX, fSY, &pt);
   1245         fX = SkScalarToFixed(pt.fX);
   1246         fY = SkScalarToFixed(pt.fY);
   1247         dx = (fX - x) >> kShift;
   1248         dy = (fY - y) >> kShift;
   1249     } else {
   1250         fSX += SkIntToScalar(n);
   1251         SkMatrix::Persp_xy(fMatrix, fSX, fSY, &pt);
   1252         fX = SkScalarToFixed(pt.fX);
   1253         fY = SkScalarToFixed(pt.fY);
   1254         dx = (fX - x) / n;
   1255         dy = (fY - y) / n;
   1256     }
   1257 
   1258     SkFixed* p = fStorage;
   1259     for (int i = 0; i < n; i++) {
   1260         *p++ = x; x += dx;
   1261         *p++ = y; y += dy;
   1262     }
   1263 
   1264     fCount -= n;
   1265     return n;
   1266 }
   1267 
   1268 ///////////////////////////////////////////////////////////////////////////////
   1269 
   1270 static inline bool checkForZero(float x) {
   1271     return x*x == 0;
   1272 }
   1273 
   1274 static inline bool poly_to_point(SkPoint* pt, const SkPoint poly[], int count) {
   1275     float   x = 1, y = 1;
   1276     SkPoint pt1, pt2;
   1277 
   1278     if (count > 1) {
   1279         pt1.fX = poly[1].fX - poly[0].fX;
   1280         pt1.fY = poly[1].fY - poly[0].fY;
   1281         y = SkPoint::Length(pt1.fX, pt1.fY);
   1282         if (checkForZero(y)) {
   1283             return false;
   1284         }
   1285         switch (count) {
   1286             case 2:
   1287                 break;
   1288             case 3:
   1289                 pt2.fX = poly[0].fY - poly[2].fY;
   1290                 pt2.fY = poly[2].fX - poly[0].fX;
   1291                 goto CALC_X;
   1292             default:
   1293                 pt2.fX = poly[0].fY - poly[3].fY;
   1294                 pt2.fY = poly[3].fX - poly[0].fX;
   1295             CALC_X:
   1296                 x = sdot(pt1.fX, pt2.fX, pt1.fY, pt2.fY) / y;
   1297                 break;
   1298         }
   1299     }
   1300     pt->set(x, y);
   1301     return true;
   1302 }
   1303 
   1304 bool SkMatrix::Poly2Proc(const SkPoint srcPt[], SkMatrix* dst,
   1305                          const SkPoint& scale) {
   1306     float invScale = 1 / scale.fY;
   1307 
   1308     dst->fMat[kMScaleX] = (srcPt[1].fY - srcPt[0].fY) * invScale;
   1309     dst->fMat[kMSkewY] = (srcPt[0].fX - srcPt[1].fX) * invScale;
   1310     dst->fMat[kMPersp0] = 0;
   1311     dst->fMat[kMSkewX] = (srcPt[1].fX - srcPt[0].fX) * invScale;
   1312     dst->fMat[kMScaleY] = (srcPt[1].fY - srcPt[0].fY) * invScale;
   1313     dst->fMat[kMPersp1] = 0;
   1314     dst->fMat[kMTransX] = srcPt[0].fX;
   1315     dst->fMat[kMTransY] = srcPt[0].fY;
   1316     dst->fMat[kMPersp2] = 1;
   1317     dst->setTypeMask(kUnknown_Mask);
   1318     return true;
   1319 }
   1320 
   1321 bool SkMatrix::Poly3Proc(const SkPoint srcPt[], SkMatrix* dst,
   1322                          const SkPoint& scale) {
   1323     float invScale = 1 / scale.fX;
   1324     dst->fMat[kMScaleX] = (srcPt[2].fX - srcPt[0].fX) * invScale;
   1325     dst->fMat[kMSkewY] = (srcPt[2].fY - srcPt[0].fY) * invScale;
   1326     dst->fMat[kMPersp0] = 0;
   1327 
   1328     invScale = 1 / scale.fY;
   1329     dst->fMat[kMSkewX] = (srcPt[1].fX - srcPt[0].fX) * invScale;
   1330     dst->fMat[kMScaleY] = (srcPt[1].fY - srcPt[0].fY) * invScale;
   1331     dst->fMat[kMPersp1] = 0;
   1332 
   1333     dst->fMat[kMTransX] = srcPt[0].fX;
   1334     dst->fMat[kMTransY] = srcPt[0].fY;
   1335     dst->fMat[kMPersp2] = 1;
   1336     dst->setTypeMask(kUnknown_Mask);
   1337     return true;
   1338 }
   1339 
   1340 bool SkMatrix::Poly4Proc(const SkPoint srcPt[], SkMatrix* dst,
   1341                          const SkPoint& scale) {
   1342     float   a1, a2;
   1343     float   x0, y0, x1, y1, x2, y2;
   1344 
   1345     x0 = srcPt[2].fX - srcPt[0].fX;
   1346     y0 = srcPt[2].fY - srcPt[0].fY;
   1347     x1 = srcPt[2].fX - srcPt[1].fX;
   1348     y1 = srcPt[2].fY - srcPt[1].fY;
   1349     x2 = srcPt[2].fX - srcPt[3].fX;
   1350     y2 = srcPt[2].fY - srcPt[3].fY;
   1351 
   1352     /* check if abs(x2) > abs(y2) */
   1353     if ( x2 > 0 ? y2 > 0 ? x2 > y2 : x2 > -y2 : y2 > 0 ? -x2 > y2 : x2 < y2) {
   1354         float denom = SkScalarMulDiv(x1, y2, x2) - y1;
   1355         if (checkForZero(denom)) {
   1356             return false;
   1357         }
   1358         a1 = (SkScalarMulDiv(x0 - x1, y2, x2) - y0 + y1) / denom;
   1359     } else {
   1360         float denom = x1 - SkScalarMulDiv(y1, x2, y2);
   1361         if (checkForZero(denom)) {
   1362             return false;
   1363         }
   1364         a1 = (x0 - x1 - SkScalarMulDiv(y0 - y1, x2, y2)) / denom;
   1365     }
   1366 
   1367     /* check if abs(x1) > abs(y1) */
   1368     if ( x1 > 0 ? y1 > 0 ? x1 > y1 : x1 > -y1 : y1 > 0 ? -x1 > y1 : x1 < y1) {
   1369         float denom = y2 - SkScalarMulDiv(x2, y1, x1);
   1370         if (checkForZero(denom)) {
   1371             return false;
   1372         }
   1373         a2 = (y0 - y2 - SkScalarMulDiv(x0 - x2, y1, x1)) / denom;
   1374     } else {
   1375         float denom = SkScalarMulDiv(y2, x1, y1) - x2;
   1376         if (checkForZero(denom)) {
   1377             return false;
   1378         }
   1379         a2 = (SkScalarMulDiv(y0 - y2, x1, y1) - x0 + x2) / denom;
   1380     }
   1381 
   1382     float invScale = SkScalarInvert(scale.fX);
   1383     dst->fMat[kMScaleX] = (a2 * srcPt[3].fX + srcPt[3].fX - srcPt[0].fX) * invScale;
   1384     dst->fMat[kMSkewY]  = (a2 * srcPt[3].fY + srcPt[3].fY - srcPt[0].fY) * invScale;
   1385     dst->fMat[kMPersp0] = a2 * invScale;
   1386 
   1387     invScale = SkScalarInvert(scale.fY);
   1388     dst->fMat[kMSkewX]  = (a1 * srcPt[1].fX + srcPt[1].fX - srcPt[0].fX) * invScale;
   1389     dst->fMat[kMScaleY] = (a1 * srcPt[1].fY + srcPt[1].fY - srcPt[0].fY) * invScale;
   1390     dst->fMat[kMPersp1] = a1 * invScale;
   1391 
   1392     dst->fMat[kMTransX] = srcPt[0].fX;
   1393     dst->fMat[kMTransY] = srcPt[0].fY;
   1394     dst->fMat[kMPersp2] = 1;
   1395     dst->setTypeMask(kUnknown_Mask);
   1396     return true;
   1397 }
   1398 
   1399 typedef bool (*PolyMapProc)(const SkPoint[], SkMatrix*, const SkPoint&);
   1400 
   1401 /*  Taken from Rob Johnson's original sample code in QuickDraw GX
   1402 */
   1403 bool SkMatrix::setPolyToPoly(const SkPoint src[], const SkPoint dst[],
   1404                              int count) {
   1405     if ((unsigned)count > 4) {
   1406         SkDebugf("--- SkMatrix::setPolyToPoly count out of range %d\n", count);
   1407         return false;
   1408     }
   1409 
   1410     if (0 == count) {
   1411         this->reset();
   1412         return true;
   1413     }
   1414     if (1 == count) {
   1415         this->setTranslate(dst[0].fX - src[0].fX, dst[0].fY - src[0].fY);
   1416         return true;
   1417     }
   1418 
   1419     SkPoint scale;
   1420     if (!poly_to_point(&scale, src, count) ||
   1421             SkScalarNearlyZero(scale.fX) ||
   1422             SkScalarNearlyZero(scale.fY)) {
   1423         return false;
   1424     }
   1425 
   1426     static const PolyMapProc gPolyMapProcs[] = {
   1427         SkMatrix::Poly2Proc, SkMatrix::Poly3Proc, SkMatrix::Poly4Proc
   1428     };
   1429     PolyMapProc proc = gPolyMapProcs[count - 2];
   1430 
   1431     SkMatrix tempMap, result;
   1432     tempMap.setTypeMask(kUnknown_Mask);
   1433 
   1434     if (!proc(src, &tempMap, scale)) {
   1435         return false;
   1436     }
   1437     if (!tempMap.invert(&result)) {
   1438         return false;
   1439     }
   1440     if (!proc(dst, &tempMap, scale)) {
   1441         return false;
   1442     }
   1443     this->setConcat(tempMap, result);
   1444     return true;
   1445 }
   1446 
   1447 ///////////////////////////////////////////////////////////////////////////////
   1448 
   1449 enum MinMaxOrBoth {
   1450     kMin_MinMaxOrBoth,
   1451     kMax_MinMaxOrBoth,
   1452     kBoth_MinMaxOrBoth
   1453 };
   1454 
   1455 template <MinMaxOrBoth MIN_MAX_OR_BOTH> bool get_scale_factor(SkMatrix::TypeMask typeMask,
   1456                                                               const SkScalar m[9],
   1457                                                               SkScalar results[/*1 or 2*/]) {
   1458     if (typeMask & SkMatrix::kPerspective_Mask) {
   1459         return false;
   1460     }
   1461     if (SkMatrix::kIdentity_Mask == typeMask) {
   1462         results[0] = SK_Scalar1;
   1463         if (kBoth_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
   1464             results[1] = SK_Scalar1;
   1465         }
   1466         return true;
   1467     }
   1468     if (!(typeMask & SkMatrix::kAffine_Mask)) {
   1469         if (kMin_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
   1470              results[0] = SkMinScalar(SkScalarAbs(m[SkMatrix::kMScaleX]),
   1471                                       SkScalarAbs(m[SkMatrix::kMScaleY]));
   1472         } else if (kMax_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
   1473              results[0] = SkMaxScalar(SkScalarAbs(m[SkMatrix::kMScaleX]),
   1474                                       SkScalarAbs(m[SkMatrix::kMScaleY]));
   1475         } else {
   1476             results[0] = SkScalarAbs(m[SkMatrix::kMScaleX]);
   1477             results[1] = SkScalarAbs(m[SkMatrix::kMScaleY]);
   1478              if (results[0] > results[1]) {
   1479                  SkTSwap(results[0], results[1]);
   1480              }
   1481         }
   1482         return true;
   1483     }
   1484     // ignore the translation part of the matrix, just look at 2x2 portion.
   1485     // compute singular values, take largest or smallest abs value.
   1486     // [a b; b c] = A^T*A
   1487     SkScalar a = sdot(m[SkMatrix::kMScaleX], m[SkMatrix::kMScaleX],
   1488                       m[SkMatrix::kMSkewY],  m[SkMatrix::kMSkewY]);
   1489     SkScalar b = sdot(m[SkMatrix::kMScaleX], m[SkMatrix::kMSkewX],
   1490                       m[SkMatrix::kMScaleY], m[SkMatrix::kMSkewY]);
   1491     SkScalar c = sdot(m[SkMatrix::kMSkewX],  m[SkMatrix::kMSkewX],
   1492                       m[SkMatrix::kMScaleY], m[SkMatrix::kMScaleY]);
   1493     // eigenvalues of A^T*A are the squared singular values of A.
   1494     // characteristic equation is det((A^T*A) - l*I) = 0
   1495     // l^2 - (a + c)l + (ac-b^2)
   1496     // solve using quadratic equation (divisor is non-zero since l^2 has 1 coeff
   1497     // and roots are guaranteed to be pos and real).
   1498     SkScalar bSqd = b * b;
   1499     // if upper left 2x2 is orthogonal save some math
   1500     if (bSqd <= SK_ScalarNearlyZero*SK_ScalarNearlyZero) {
   1501         if (kMin_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
   1502             results[0] = SkMinScalar(a, c);
   1503         } else if (kMax_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
   1504             results[0] = SkMaxScalar(a, c);
   1505         } else {
   1506             results[0] = a;
   1507             results[1] = c;
   1508             if (results[0] > results[1]) {
   1509                 SkTSwap(results[0], results[1]);
   1510             }
   1511         }
   1512     } else {
   1513         SkScalar aminusc = a - c;
   1514         SkScalar apluscdiv2 = SkScalarHalf(a + c);
   1515         SkScalar x = SkScalarHalf(SkScalarSqrt(aminusc * aminusc + 4 * bSqd));
   1516         if (kMin_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
   1517             results[0] = apluscdiv2 - x;
   1518         } else if (kMax_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
   1519             results[0] = apluscdiv2 + x;
   1520         } else {
   1521             results[0] = apluscdiv2 - x;
   1522             results[1] = apluscdiv2 + x;
   1523         }
   1524     }
   1525     SkASSERT(results[0] >= 0);
   1526     results[0] = SkScalarSqrt(results[0]);
   1527     if (kBoth_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
   1528         SkASSERT(results[1] >= 0);
   1529         results[1] = SkScalarSqrt(results[1]);
   1530     }
   1531     return true;
   1532 }
   1533 
   1534 SkScalar SkMatrix::getMinScale() const {
   1535     SkScalar factor;
   1536     if (get_scale_factor<kMin_MinMaxOrBoth>(this->getType(), fMat, &factor)) {
   1537         return factor;
   1538     } else {
   1539         return -1;
   1540     }
   1541 }
   1542 
   1543 SkScalar SkMatrix::getMaxScale() const {
   1544     SkScalar factor;
   1545     if (get_scale_factor<kMax_MinMaxOrBoth>(this->getType(), fMat, &factor)) {
   1546         return factor;
   1547     } else {
   1548         return -1;
   1549     }
   1550 }
   1551 
   1552 bool SkMatrix::getMinMaxScales(SkScalar scaleFactors[2]) const {
   1553     return get_scale_factor<kBoth_MinMaxOrBoth>(this->getType(), fMat, scaleFactors);
   1554 }
   1555 
   1556 namespace {
   1557 
   1558 struct PODMatrix {
   1559     SkScalar matrix[9];
   1560     uint32_t typemask;
   1561 
   1562     const SkMatrix& asSkMatrix() const { return *reinterpret_cast<const SkMatrix*>(this); }
   1563 };
   1564 SK_COMPILE_ASSERT(sizeof(PODMatrix) == sizeof(SkMatrix), PODMatrixSizeMismatch);
   1565 
   1566 }  // namespace
   1567 
   1568 const SkMatrix& SkMatrix::I() {
   1569     SK_COMPILE_ASSERT(offsetof(SkMatrix, fMat)      == offsetof(PODMatrix, matrix),   BadfMat);
   1570     SK_COMPILE_ASSERT(offsetof(SkMatrix, fTypeMask) == offsetof(PODMatrix, typemask), BadfTypeMask);
   1571 
   1572     static const PODMatrix identity = { {SK_Scalar1, 0, 0,
   1573                                          0, SK_Scalar1, 0,
   1574                                          0, 0, SK_Scalar1 },
   1575                                        kIdentity_Mask | kRectStaysRect_Mask};
   1576     SkASSERT(identity.asSkMatrix().isIdentity());
   1577     return identity.asSkMatrix();
   1578 }
   1579 
   1580 const SkMatrix& SkMatrix::InvalidMatrix() {
   1581     SK_COMPILE_ASSERT(offsetof(SkMatrix, fMat)      == offsetof(PODMatrix, matrix),   BadfMat);
   1582     SK_COMPILE_ASSERT(offsetof(SkMatrix, fTypeMask) == offsetof(PODMatrix, typemask), BadfTypeMask);
   1583 
   1584     static const PODMatrix invalid =
   1585         { {SK_ScalarMax, SK_ScalarMax, SK_ScalarMax,
   1586            SK_ScalarMax, SK_ScalarMax, SK_ScalarMax,
   1587            SK_ScalarMax, SK_ScalarMax, SK_ScalarMax },
   1588          kTranslate_Mask | kScale_Mask | kAffine_Mask | kPerspective_Mask };
   1589     return invalid.asSkMatrix();
   1590 }
   1591 
   1592 ///////////////////////////////////////////////////////////////////////////////
   1593 
   1594 size_t SkMatrix::writeToMemory(void* buffer) const {
   1595     // TODO write less for simple matrices
   1596     static const size_t sizeInMemory = 9 * sizeof(SkScalar);
   1597     if (buffer) {
   1598         memcpy(buffer, fMat, sizeInMemory);
   1599     }
   1600     return sizeInMemory;
   1601 }
   1602 
   1603 size_t SkMatrix::readFromMemory(const void* buffer, size_t length) {
   1604     static const size_t sizeInMemory = 9 * sizeof(SkScalar);
   1605     if (length < sizeInMemory) {
   1606         return 0;
   1607     }
   1608     if (buffer) {
   1609         memcpy(fMat, buffer, sizeInMemory);
   1610         this->setTypeMask(kUnknown_Mask);
   1611     }
   1612     return sizeInMemory;
   1613 }
   1614 
   1615 #ifdef SK_DEVELOPER
   1616 void SkMatrix::dump() const {
   1617     SkString str;
   1618     this->toString(&str);
   1619     SkDebugf("%s\n", str.c_str());
   1620 }
   1621 #endif
   1622 
   1623 #ifndef SK_IGNORE_TO_STRING
   1624 void SkMatrix::toString(SkString* str) const {
   1625     str->appendf("[%8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f]",
   1626              fMat[0], fMat[1], fMat[2], fMat[3], fMat[4], fMat[5],
   1627              fMat[6], fMat[7], fMat[8]);
   1628 }
   1629 #endif
   1630 
   1631 ///////////////////////////////////////////////////////////////////////////////
   1632 
   1633 #include "SkMatrixUtils.h"
   1634 
   1635 bool SkTreatAsSprite(const SkMatrix& mat, int width, int height,
   1636                      unsigned subpixelBits) {
   1637     // quick reject on affine or perspective
   1638     if (mat.getType() & ~(SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask)) {
   1639         return false;
   1640     }
   1641 
   1642     // quick success check
   1643     if (!subpixelBits && !(mat.getType() & ~SkMatrix::kTranslate_Mask)) {
   1644         return true;
   1645     }
   1646 
   1647     // mapRect supports negative scales, so we eliminate those first
   1648     if (mat.getScaleX() < 0 || mat.getScaleY() < 0) {
   1649         return false;
   1650     }
   1651 
   1652     SkRect dst;
   1653     SkIRect isrc = { 0, 0, width, height };
   1654 
   1655     {
   1656         SkRect src;
   1657         src.set(isrc);
   1658         mat.mapRect(&dst, src);
   1659     }
   1660 
   1661     // just apply the translate to isrc
   1662     isrc.offset(SkScalarRoundToInt(mat.getTranslateX()),
   1663                 SkScalarRoundToInt(mat.getTranslateY()));
   1664 
   1665     if (subpixelBits) {
   1666         isrc.fLeft <<= subpixelBits;
   1667         isrc.fTop <<= subpixelBits;
   1668         isrc.fRight <<= subpixelBits;
   1669         isrc.fBottom <<= subpixelBits;
   1670 
   1671         const float scale = 1 << subpixelBits;
   1672         dst.fLeft *= scale;
   1673         dst.fTop *= scale;
   1674         dst.fRight *= scale;
   1675         dst.fBottom *= scale;
   1676     }
   1677 
   1678     SkIRect idst;
   1679     dst.round(&idst);
   1680     return isrc == idst;
   1681 }
   1682 
   1683 // A square matrix M can be decomposed (via polar decomposition) into two matrices --
   1684 // an orthogonal matrix Q and a symmetric matrix S. In turn we can decompose S into U*W*U^T,
   1685 // where U is another orthogonal matrix and W is a scale matrix. These can be recombined
   1686 // to give M = (Q*U)*W*U^T, i.e., the product of two orthogonal matrices and a scale matrix.
   1687 //
   1688 // The one wrinkle is that traditionally Q may contain a reflection -- the
   1689 // calculation has been rejiggered to put that reflection into W.
   1690 bool SkDecomposeUpper2x2(const SkMatrix& matrix,
   1691                          SkPoint* rotation1,
   1692                          SkPoint* scale,
   1693                          SkPoint* rotation2) {
   1694 
   1695     SkScalar A = matrix[SkMatrix::kMScaleX];
   1696     SkScalar B = matrix[SkMatrix::kMSkewX];
   1697     SkScalar C = matrix[SkMatrix::kMSkewY];
   1698     SkScalar D = matrix[SkMatrix::kMScaleY];
   1699 
   1700     if (is_degenerate_2x2(A, B, C, D)) {
   1701         return false;
   1702     }
   1703 
   1704     double w1, w2;
   1705     SkScalar cos1, sin1;
   1706     SkScalar cos2, sin2;
   1707 
   1708     // do polar decomposition (M = Q*S)
   1709     SkScalar cosQ, sinQ;
   1710     double Sa, Sb, Sd;
   1711     // if M is already symmetric (i.e., M = I*S)
   1712     if (SkScalarNearlyEqual(B, C)) {
   1713         cosQ = 1;
   1714         sinQ = 0;
   1715 
   1716         Sa = A;
   1717         Sb = B;
   1718         Sd = D;
   1719     } else {
   1720         cosQ = A + D;
   1721         sinQ = C - B;
   1722         SkScalar reciplen = SkScalarInvert(SkScalarSqrt(cosQ*cosQ + sinQ*sinQ));
   1723         cosQ *= reciplen;
   1724         sinQ *= reciplen;
   1725 
   1726         // S = Q^-1*M
   1727         // we don't calc Sc since it's symmetric
   1728         Sa = A*cosQ + C*sinQ;
   1729         Sb = B*cosQ + D*sinQ;
   1730         Sd = -B*sinQ + D*cosQ;
   1731     }
   1732 
   1733     // Now we need to compute eigenvalues of S (our scale factors)
   1734     // and eigenvectors (bases for our rotation)
   1735     // From this, should be able to reconstruct S as U*W*U^T
   1736     if (SkScalarNearlyZero(SkDoubleToScalar(Sb))) {
   1737         // already diagonalized
   1738         cos1 = 1;
   1739         sin1 = 0;
   1740         w1 = Sa;
   1741         w2 = Sd;
   1742         cos2 = cosQ;
   1743         sin2 = sinQ;
   1744     } else {
   1745         double diff = Sa - Sd;
   1746         double discriminant = sqrt(diff*diff + 4.0*Sb*Sb);
   1747         double trace = Sa + Sd;
   1748         if (diff > 0) {
   1749             w1 = 0.5*(trace + discriminant);
   1750             w2 = 0.5*(trace - discriminant);
   1751         } else {
   1752             w1 = 0.5*(trace - discriminant);
   1753             w2 = 0.5*(trace + discriminant);
   1754         }
   1755 
   1756         cos1 = SkDoubleToScalar(Sb); sin1 = SkDoubleToScalar(w1 - Sa);
   1757         SkScalar reciplen = SkScalarInvert(SkScalarSqrt(cos1*cos1 + sin1*sin1));
   1758         cos1 *= reciplen;
   1759         sin1 *= reciplen;
   1760 
   1761         // rotation 2 is composition of Q and U
   1762         cos2 = cos1*cosQ - sin1*sinQ;
   1763         sin2 = sin1*cosQ + cos1*sinQ;
   1764 
   1765         // rotation 1 is U^T
   1766         sin1 = -sin1;
   1767     }
   1768 
   1769     if (scale) {
   1770         scale->fX = SkDoubleToScalar(w1);
   1771         scale->fY = SkDoubleToScalar(w2);
   1772     }
   1773     if (rotation1) {
   1774         rotation1->fX = cos1;
   1775         rotation1->fY = sin1;
   1776     }
   1777     if (rotation2) {
   1778         rotation2->fX = cos2;
   1779         rotation2->fY = sin2;
   1780     }
   1781 
   1782     return true;
   1783 }
   1784