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