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 static inline bool checkForZero(float x) {
   1272     return x*x == 0;
   1273 }
   1274 
   1275 static inline bool poly_to_point(SkPoint* pt, const SkPoint poly[], int count) {
   1276     float   x = 1, y = 1;
   1277     SkPoint pt1, pt2;
   1278 
   1279     if (count > 1) {
   1280         pt1.fX = poly[1].fX - poly[0].fX;
   1281         pt1.fY = poly[1].fY - poly[0].fY;
   1282         y = SkPoint::Length(pt1.fX, pt1.fY);
   1283         if (checkForZero(y)) {
   1284             return false;
   1285         }
   1286         switch (count) {
   1287             case 2:
   1288                 break;
   1289             case 3:
   1290                 pt2.fX = poly[0].fY - poly[2].fY;
   1291                 pt2.fY = poly[2].fX - poly[0].fX;
   1292                 goto CALC_X;
   1293             default:
   1294                 pt2.fX = poly[0].fY - poly[3].fY;
   1295                 pt2.fY = poly[3].fX - poly[0].fX;
   1296             CALC_X:
   1297                 x = sdot(pt1.fX, pt2.fX, pt1.fY, pt2.fY) / y;
   1298                 break;
   1299         }
   1300     }
   1301     pt->set(x, y);
   1302     return true;
   1303 }
   1304 
   1305 bool SkMatrix::Poly2Proc(const SkPoint srcPt[], SkMatrix* dst,
   1306                          const SkPoint& scale) {
   1307     float invScale = 1 / scale.fY;
   1308 
   1309     dst->fMat[kMScaleX] = (srcPt[1].fY - srcPt[0].fY) * invScale;
   1310     dst->fMat[kMSkewY] = (srcPt[0].fX - srcPt[1].fX) * invScale;
   1311     dst->fMat[kMPersp0] = 0;
   1312     dst->fMat[kMSkewX] = (srcPt[1].fX - srcPt[0].fX) * invScale;
   1313     dst->fMat[kMScaleY] = (srcPt[1].fY - srcPt[0].fY) * invScale;
   1314     dst->fMat[kMPersp1] = 0;
   1315     dst->fMat[kMTransX] = srcPt[0].fX;
   1316     dst->fMat[kMTransY] = srcPt[0].fY;
   1317     dst->fMat[kMPersp2] = 1;
   1318     dst->setTypeMask(kUnknown_Mask);
   1319     return true;
   1320 }
   1321 
   1322 bool SkMatrix::Poly3Proc(const SkPoint srcPt[], SkMatrix* dst,
   1323                          const SkPoint& scale) {
   1324     float invScale = 1 / scale.fX;
   1325     dst->fMat[kMScaleX] = (srcPt[2].fX - srcPt[0].fX) * invScale;
   1326     dst->fMat[kMSkewY] = (srcPt[2].fY - srcPt[0].fY) * invScale;
   1327     dst->fMat[kMPersp0] = 0;
   1328 
   1329     invScale = 1 / scale.fY;
   1330     dst->fMat[kMSkewX] = (srcPt[1].fX - srcPt[0].fX) * invScale;
   1331     dst->fMat[kMScaleY] = (srcPt[1].fY - srcPt[0].fY) * invScale;
   1332     dst->fMat[kMPersp1] = 0;
   1333 
   1334     dst->fMat[kMTransX] = srcPt[0].fX;
   1335     dst->fMat[kMTransY] = srcPt[0].fY;
   1336     dst->fMat[kMPersp2] = 1;
   1337     dst->setTypeMask(kUnknown_Mask);
   1338     return true;
   1339 }
   1340 
   1341 bool SkMatrix::Poly4Proc(const SkPoint srcPt[], SkMatrix* dst,
   1342                          const SkPoint& scale) {
   1343     float   a1, a2;
   1344     float   x0, y0, x1, y1, x2, y2;
   1345 
   1346     x0 = srcPt[2].fX - srcPt[0].fX;
   1347     y0 = srcPt[2].fY - srcPt[0].fY;
   1348     x1 = srcPt[2].fX - srcPt[1].fX;
   1349     y1 = srcPt[2].fY - srcPt[1].fY;
   1350     x2 = srcPt[2].fX - srcPt[3].fX;
   1351     y2 = srcPt[2].fY - srcPt[3].fY;
   1352 
   1353     /* check if abs(x2) > abs(y2) */
   1354     if ( x2 > 0 ? y2 > 0 ? x2 > y2 : x2 > -y2 : y2 > 0 ? -x2 > y2 : x2 < y2) {
   1355         float denom = (x1 * y2 / x2) - y1;
   1356         if (checkForZero(denom)) {
   1357             return false;
   1358         }
   1359         a1 = (((x0 - x1) * y2 / x2) - y0 + y1) / denom;
   1360     } else {
   1361         float denom = x1 - (y1 * x2 / y2);
   1362         if (checkForZero(denom)) {
   1363             return false;
   1364         }
   1365         a1 = (x0 - x1 - ((y0 - y1) * x2 / y2)) / denom;
   1366     }
   1367 
   1368     /* check if abs(x1) > abs(y1) */
   1369     if ( x1 > 0 ? y1 > 0 ? x1 > y1 : x1 > -y1 : y1 > 0 ? -x1 > y1 : x1 < y1) {
   1370         float denom = y2 - (x2 * y1 / x1);
   1371         if (checkForZero(denom)) {
   1372             return false;
   1373         }
   1374         a2 = (y0 - y2 - ((x0 - x2) * y1 / x1)) / denom;
   1375     } else {
   1376         float denom = (y2 * x1 / y1) - x2;
   1377         if (checkForZero(denom)) {
   1378             return false;
   1379         }
   1380         a2 = (((y0 - y2) * x1 / y1) - x0 + x2) / denom;
   1381     }
   1382 
   1383     float invScale = SkScalarInvert(scale.fX);
   1384     dst->fMat[kMScaleX] = (a2 * srcPt[3].fX + srcPt[3].fX - srcPt[0].fX) * invScale;
   1385     dst->fMat[kMSkewY]  = (a2 * srcPt[3].fY + srcPt[3].fY - srcPt[0].fY) * invScale;
   1386     dst->fMat[kMPersp0] = a2 * invScale;
   1387 
   1388     invScale = SkScalarInvert(scale.fY);
   1389     dst->fMat[kMSkewX]  = (a1 * srcPt[1].fX + srcPt[1].fX - srcPt[0].fX) * invScale;
   1390     dst->fMat[kMScaleY] = (a1 * srcPt[1].fY + srcPt[1].fY - srcPt[0].fY) * invScale;
   1391     dst->fMat[kMPersp1] = a1 * invScale;
   1392 
   1393     dst->fMat[kMTransX] = srcPt[0].fX;
   1394     dst->fMat[kMTransY] = srcPt[0].fY;
   1395     dst->fMat[kMPersp2] = 1;
   1396     dst->setTypeMask(kUnknown_Mask);
   1397     return true;
   1398 }
   1399 
   1400 typedef bool (*PolyMapProc)(const SkPoint[], SkMatrix*, const SkPoint&);
   1401 
   1402 /*  Taken from Rob Johnson's original sample code in QuickDraw GX
   1403 */
   1404 bool SkMatrix::setPolyToPoly(const SkPoint src[], const SkPoint dst[],
   1405                              int count) {
   1406     if ((unsigned)count > 4) {
   1407         SkDebugf("--- SkMatrix::setPolyToPoly count out of range %d\n", count);
   1408         return false;
   1409     }
   1410 
   1411     if (0 == count) {
   1412         this->reset();
   1413         return true;
   1414     }
   1415     if (1 == count) {
   1416         this->setTranslate(dst[0].fX - src[0].fX, dst[0].fY - src[0].fY);
   1417         return true;
   1418     }
   1419 
   1420     SkPoint scale;
   1421     if (!poly_to_point(&scale, src, count) ||
   1422             SkScalarNearlyZero(scale.fX) ||
   1423             SkScalarNearlyZero(scale.fY)) {
   1424         return false;
   1425     }
   1426 
   1427     static const PolyMapProc gPolyMapProcs[] = {
   1428         SkMatrix::Poly2Proc, SkMatrix::Poly3Proc, SkMatrix::Poly4Proc
   1429     };
   1430     PolyMapProc proc = gPolyMapProcs[count - 2];
   1431 
   1432     SkMatrix tempMap, result;
   1433     tempMap.setTypeMask(kUnknown_Mask);
   1434 
   1435     if (!proc(src, &tempMap, scale)) {
   1436         return false;
   1437     }
   1438     if (!tempMap.invert(&result)) {
   1439         return false;
   1440     }
   1441     if (!proc(dst, &tempMap, scale)) {
   1442         return false;
   1443     }
   1444     this->setConcat(tempMap, result);
   1445     return true;
   1446 }
   1447 
   1448 ///////////////////////////////////////////////////////////////////////////////
   1449 
   1450 enum MinMaxOrBoth {
   1451     kMin_MinMaxOrBoth,
   1452     kMax_MinMaxOrBoth,
   1453     kBoth_MinMaxOrBoth
   1454 };
   1455 
   1456 template <MinMaxOrBoth MIN_MAX_OR_BOTH> bool get_scale_factor(SkMatrix::TypeMask typeMask,
   1457                                                               const SkScalar m[9],
   1458                                                               SkScalar results[/*1 or 2*/]) {
   1459     if (typeMask & SkMatrix::kPerspective_Mask) {
   1460         return false;
   1461     }
   1462     if (SkMatrix::kIdentity_Mask == typeMask) {
   1463         results[0] = SK_Scalar1;
   1464         if (kBoth_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
   1465             results[1] = SK_Scalar1;
   1466         }
   1467         return true;
   1468     }
   1469     if (!(typeMask & SkMatrix::kAffine_Mask)) {
   1470         if (kMin_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
   1471              results[0] = SkMinScalar(SkScalarAbs(m[SkMatrix::kMScaleX]),
   1472                                       SkScalarAbs(m[SkMatrix::kMScaleY]));
   1473         } else if (kMax_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
   1474              results[0] = SkMaxScalar(SkScalarAbs(m[SkMatrix::kMScaleX]),
   1475                                       SkScalarAbs(m[SkMatrix::kMScaleY]));
   1476         } else {
   1477             results[0] = SkScalarAbs(m[SkMatrix::kMScaleX]);
   1478             results[1] = SkScalarAbs(m[SkMatrix::kMScaleY]);
   1479              if (results[0] > results[1]) {
   1480                  SkTSwap(results[0], results[1]);
   1481              }
   1482         }
   1483         return true;
   1484     }
   1485     // ignore the translation part of the matrix, just look at 2x2 portion.
   1486     // compute singular values, take largest or smallest abs value.
   1487     // [a b; b c] = A^T*A
   1488     SkScalar a = sdot(m[SkMatrix::kMScaleX], m[SkMatrix::kMScaleX],
   1489                       m[SkMatrix::kMSkewY],  m[SkMatrix::kMSkewY]);
   1490     SkScalar b = sdot(m[SkMatrix::kMScaleX], m[SkMatrix::kMSkewX],
   1491                       m[SkMatrix::kMScaleY], m[SkMatrix::kMSkewY]);
   1492     SkScalar c = sdot(m[SkMatrix::kMSkewX],  m[SkMatrix::kMSkewX],
   1493                       m[SkMatrix::kMScaleY], m[SkMatrix::kMScaleY]);
   1494     // eigenvalues of A^T*A are the squared singular values of A.
   1495     // characteristic equation is det((A^T*A) - l*I) = 0
   1496     // l^2 - (a + c)l + (ac-b^2)
   1497     // solve using quadratic equation (divisor is non-zero since l^2 has 1 coeff
   1498     // and roots are guaranteed to be pos and real).
   1499     SkScalar bSqd = b * b;
   1500     // if upper left 2x2 is orthogonal save some math
   1501     if (bSqd <= SK_ScalarNearlyZero*SK_ScalarNearlyZero) {
   1502         if (kMin_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
   1503             results[0] = SkMinScalar(a, c);
   1504         } else if (kMax_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
   1505             results[0] = SkMaxScalar(a, c);
   1506         } else {
   1507             results[0] = a;
   1508             results[1] = c;
   1509             if (results[0] > results[1]) {
   1510                 SkTSwap(results[0], results[1]);
   1511             }
   1512         }
   1513     } else {
   1514         SkScalar aminusc = a - c;
   1515         SkScalar apluscdiv2 = SkScalarHalf(a + c);
   1516         SkScalar x = SkScalarHalf(SkScalarSqrt(aminusc * aminusc + 4 * bSqd));
   1517         if (kMin_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
   1518             results[0] = apluscdiv2 - x;
   1519         } else if (kMax_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
   1520             results[0] = apluscdiv2 + x;
   1521         } else {
   1522             results[0] = apluscdiv2 - x;
   1523             results[1] = apluscdiv2 + x;
   1524         }
   1525     }
   1526     if (!SkScalarIsFinite(results[0])) {
   1527         return false;
   1528     }
   1529     // Due to the floating point inaccuracy, there might be an error in a, b, c
   1530     // calculated by sdot, further deepened by subsequent arithmetic operations
   1531     // on them. Therefore, we allow and cap the nearly-zero negative values.
   1532     SkASSERT(results[0] >= -SK_ScalarNearlyZero);
   1533     if (results[0] < 0) {
   1534         results[0] = 0;
   1535     }
   1536     results[0] = SkScalarSqrt(results[0]);
   1537     if (kBoth_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
   1538         if (!SkScalarIsFinite(results[1])) {
   1539             return false;
   1540         }
   1541         SkASSERT(results[1] >= -SK_ScalarNearlyZero);
   1542         if (results[1] < 0) {
   1543             results[1] = 0;
   1544         }
   1545         results[1] = SkScalarSqrt(results[1]);
   1546     }
   1547     return true;
   1548 }
   1549 
   1550 SkScalar SkMatrix::getMinScale() const {
   1551     SkScalar factor;
   1552     if (get_scale_factor<kMin_MinMaxOrBoth>(this->getType(), fMat, &factor)) {
   1553         return factor;
   1554     } else {
   1555         return -1;
   1556     }
   1557 }
   1558 
   1559 SkScalar SkMatrix::getMaxScale() const {
   1560     SkScalar factor;
   1561     if (get_scale_factor<kMax_MinMaxOrBoth>(this->getType(), fMat, &factor)) {
   1562         return factor;
   1563     } else {
   1564         return -1;
   1565     }
   1566 }
   1567 
   1568 bool SkMatrix::getMinMaxScales(SkScalar scaleFactors[2]) const {
   1569     return get_scale_factor<kBoth_MinMaxOrBoth>(this->getType(), fMat, scaleFactors);
   1570 }
   1571 
   1572 namespace {
   1573 
   1574 // SkMatrix is C++11 POD (trivial and standard-layout), but not aggregate (it has private fields).
   1575 struct AggregateMatrix {
   1576     SkScalar matrix[9];
   1577     uint32_t typemask;
   1578 
   1579     const SkMatrix& asSkMatrix() const { return *reinterpret_cast<const SkMatrix*>(this); }
   1580 };
   1581 static_assert(sizeof(AggregateMatrix) == sizeof(SkMatrix), "AggregateMatrix size mismatch.");
   1582 
   1583 }  // namespace
   1584 
   1585 const SkMatrix& SkMatrix::I() {
   1586     static_assert(offsetof(SkMatrix,fMat)      == offsetof(AggregateMatrix,matrix),   "fMat");
   1587     static_assert(offsetof(SkMatrix,fTypeMask) == offsetof(AggregateMatrix,typemask), "fTypeMask");
   1588 
   1589     static const AggregateMatrix identity = { {SK_Scalar1, 0, 0,
   1590                                                0, SK_Scalar1, 0,
   1591                                                0, 0, SK_Scalar1 },
   1592                                              kIdentity_Mask | kRectStaysRect_Mask};
   1593     SkASSERT(identity.asSkMatrix().isIdentity());
   1594     return identity.asSkMatrix();
   1595 }
   1596 
   1597 const SkMatrix& SkMatrix::InvalidMatrix() {
   1598     static_assert(offsetof(SkMatrix,fMat)      == offsetof(AggregateMatrix,matrix),   "fMat");
   1599     static_assert(offsetof(SkMatrix,fTypeMask) == offsetof(AggregateMatrix,typemask), "fTypeMask");
   1600 
   1601     static const AggregateMatrix invalid =
   1602         { {SK_ScalarMax, SK_ScalarMax, SK_ScalarMax,
   1603            SK_ScalarMax, SK_ScalarMax, SK_ScalarMax,
   1604            SK_ScalarMax, SK_ScalarMax, SK_ScalarMax },
   1605          kTranslate_Mask | kScale_Mask | kAffine_Mask | kPerspective_Mask };
   1606     return invalid.asSkMatrix();
   1607 }
   1608 
   1609 bool SkMatrix::decomposeScale(SkSize* scale, SkMatrix* remaining) const {
   1610     if (this->hasPerspective()) {
   1611         return false;
   1612     }
   1613 
   1614     const SkScalar sx = SkVector::Length(this->getScaleX(), this->getSkewY());
   1615     const SkScalar sy = SkVector::Length(this->getSkewX(), this->getScaleY());
   1616     if (!SkScalarIsFinite(sx) || !SkScalarIsFinite(sy) ||
   1617         SkScalarNearlyZero(sx) || SkScalarNearlyZero(sy)) {
   1618         return false;
   1619     }
   1620 
   1621     if (scale) {
   1622         scale->set(sx, sy);
   1623     }
   1624     if (remaining) {
   1625         *remaining = *this;
   1626         remaining->postScale(SkScalarInvert(sx), SkScalarInvert(sy));
   1627     }
   1628     return true;
   1629 }
   1630 
   1631 ///////////////////////////////////////////////////////////////////////////////
   1632 
   1633 size_t SkMatrix::writeToMemory(void* buffer) const {
   1634     // TODO write less for simple matrices
   1635     static const size_t sizeInMemory = 9 * sizeof(SkScalar);
   1636     if (buffer) {
   1637         memcpy(buffer, fMat, sizeInMemory);
   1638     }
   1639     return sizeInMemory;
   1640 }
   1641 
   1642 size_t SkMatrix::readFromMemory(const void* buffer, size_t length) {
   1643     static const size_t sizeInMemory = 9 * sizeof(SkScalar);
   1644     if (length < sizeInMemory) {
   1645         return 0;
   1646     }
   1647     if (buffer) {
   1648         memcpy(fMat, buffer, sizeInMemory);
   1649         this->setTypeMask(kUnknown_Mask);
   1650     }
   1651     return sizeInMemory;
   1652 }
   1653 
   1654 void SkMatrix::dump() const {
   1655     SkString str;
   1656     this->toString(&str);
   1657     SkDebugf("%s\n", str.c_str());
   1658 }
   1659 
   1660 void SkMatrix::toString(SkString* str) const {
   1661     str->appendf("[%8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f]",
   1662              fMat[0], fMat[1], fMat[2], fMat[3], fMat[4], fMat[5],
   1663              fMat[6], fMat[7], fMat[8]);
   1664 }
   1665 
   1666 ///////////////////////////////////////////////////////////////////////////////
   1667 
   1668 #include "SkMatrixUtils.h"
   1669 
   1670 bool SkTreatAsSprite(const SkMatrix& mat, const SkISize& size, const SkPaint& paint) {
   1671     // Our path aa is 2-bits, and our rect aa is 8, so we could use 8,
   1672     // but in practice 4 seems enough (still looks smooth) and allows
   1673     // more slightly fractional cases to fall into the fast (sprite) case.
   1674     static const unsigned kAntiAliasSubpixelBits = 4;
   1675 
   1676     const unsigned subpixelBits = paint.isAntiAlias() ? kAntiAliasSubpixelBits : 0;
   1677 
   1678     // quick reject on affine or perspective
   1679     if (mat.getType() & ~(SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask)) {
   1680         return false;
   1681     }
   1682 
   1683     // quick success check
   1684     if (!subpixelBits && !(mat.getType() & ~SkMatrix::kTranslate_Mask)) {
   1685         return true;
   1686     }
   1687 
   1688     // mapRect supports negative scales, so we eliminate those first
   1689     if (mat.getScaleX() < 0 || mat.getScaleY() < 0) {
   1690         return false;
   1691     }
   1692 
   1693     SkRect dst;
   1694     SkIRect isrc = SkIRect::MakeSize(size);
   1695 
   1696     {
   1697         SkRect src;
   1698         src.set(isrc);
   1699         mat.mapRect(&dst, src);
   1700     }
   1701 
   1702     // just apply the translate to isrc
   1703     isrc.offset(SkScalarRoundToInt(mat.getTranslateX()),
   1704                 SkScalarRoundToInt(mat.getTranslateY()));
   1705 
   1706     if (subpixelBits) {
   1707         isrc.fLeft = SkLeftShift(isrc.fLeft, subpixelBits);
   1708         isrc.fTop = SkLeftShift(isrc.fTop, subpixelBits);
   1709         isrc.fRight = SkLeftShift(isrc.fRight, subpixelBits);
   1710         isrc.fBottom = SkLeftShift(isrc.fBottom, subpixelBits);
   1711 
   1712         const float scale = 1 << subpixelBits;
   1713         dst.fLeft *= scale;
   1714         dst.fTop *= scale;
   1715         dst.fRight *= scale;
   1716         dst.fBottom *= scale;
   1717     }
   1718 
   1719     SkIRect idst;
   1720     dst.round(&idst);
   1721     return isrc == idst;
   1722 }
   1723 
   1724 // A square matrix M can be decomposed (via polar decomposition) into two matrices --
   1725 // an orthogonal matrix Q and a symmetric matrix S. In turn we can decompose S into U*W*U^T,
   1726 // where U is another orthogonal matrix and W is a scale matrix. These can be recombined
   1727 // to give M = (Q*U)*W*U^T, i.e., the product of two orthogonal matrices and a scale matrix.
   1728 //
   1729 // The one wrinkle is that traditionally Q may contain a reflection -- the
   1730 // calculation has been rejiggered to put that reflection into W.
   1731 bool SkDecomposeUpper2x2(const SkMatrix& matrix,
   1732                          SkPoint* rotation1,
   1733                          SkPoint* scale,
   1734                          SkPoint* rotation2) {
   1735 
   1736     SkScalar A = matrix[SkMatrix::kMScaleX];
   1737     SkScalar B = matrix[SkMatrix::kMSkewX];
   1738     SkScalar C = matrix[SkMatrix::kMSkewY];
   1739     SkScalar D = matrix[SkMatrix::kMScaleY];
   1740 
   1741     if (is_degenerate_2x2(A, B, C, D)) {
   1742         return false;
   1743     }
   1744 
   1745     double w1, w2;
   1746     SkScalar cos1, sin1;
   1747     SkScalar cos2, sin2;
   1748 
   1749     // do polar decomposition (M = Q*S)
   1750     SkScalar cosQ, sinQ;
   1751     double Sa, Sb, Sd;
   1752     // if M is already symmetric (i.e., M = I*S)
   1753     if (SkScalarNearlyEqual(B, C)) {
   1754         cosQ = 1;
   1755         sinQ = 0;
   1756 
   1757         Sa = A;
   1758         Sb = B;
   1759         Sd = D;
   1760     } else {
   1761         cosQ = A + D;
   1762         sinQ = C - B;
   1763         SkScalar reciplen = SkScalarInvert(SkScalarSqrt(cosQ*cosQ + sinQ*sinQ));
   1764         cosQ *= reciplen;
   1765         sinQ *= reciplen;
   1766 
   1767         // S = Q^-1*M
   1768         // we don't calc Sc since it's symmetric
   1769         Sa = A*cosQ + C*sinQ;
   1770         Sb = B*cosQ + D*sinQ;
   1771         Sd = -B*sinQ + D*cosQ;
   1772     }
   1773 
   1774     // Now we need to compute eigenvalues of S (our scale factors)
   1775     // and eigenvectors (bases for our rotation)
   1776     // From this, should be able to reconstruct S as U*W*U^T
   1777     if (SkScalarNearlyZero(SkDoubleToScalar(Sb))) {
   1778         // already diagonalized
   1779         cos1 = 1;
   1780         sin1 = 0;
   1781         w1 = Sa;
   1782         w2 = Sd;
   1783         cos2 = cosQ;
   1784         sin2 = sinQ;
   1785     } else {
   1786         double diff = Sa - Sd;
   1787         double discriminant = sqrt(diff*diff + 4.0*Sb*Sb);
   1788         double trace = Sa + Sd;
   1789         if (diff > 0) {
   1790             w1 = 0.5*(trace + discriminant);
   1791             w2 = 0.5*(trace - discriminant);
   1792         } else {
   1793             w1 = 0.5*(trace - discriminant);
   1794             w2 = 0.5*(trace + discriminant);
   1795         }
   1796 
   1797         cos1 = SkDoubleToScalar(Sb); sin1 = SkDoubleToScalar(w1 - Sa);
   1798         SkScalar reciplen = SkScalarInvert(SkScalarSqrt(cos1*cos1 + sin1*sin1));
   1799         cos1 *= reciplen;
   1800         sin1 *= reciplen;
   1801 
   1802         // rotation 2 is composition of Q and U
   1803         cos2 = cos1*cosQ - sin1*sinQ;
   1804         sin2 = sin1*cosQ + cos1*sinQ;
   1805 
   1806         // rotation 1 is U^T
   1807         sin1 = -sin1;
   1808     }
   1809 
   1810     if (scale) {
   1811         scale->fX = SkDoubleToScalar(w1);
   1812         scale->fY = SkDoubleToScalar(w2);
   1813     }
   1814     if (rotation1) {
   1815         rotation1->fX = cos1;
   1816         rotation1->fY = sin1;
   1817     }
   1818     if (rotation2) {
   1819         rotation2->fX = cos2;
   1820         rotation2->fY = sin2;
   1821     }
   1822 
   1823     return true;
   1824 }
   1825 
   1826 //////////////////////////////////////////////////////////////////////////////////////////////////
   1827 
   1828 void SkRSXform::toQuad(SkScalar width, SkScalar height, SkPoint quad[4]) const {
   1829 #if 0
   1830     // This is the slow way, but it documents what we're doing
   1831     quad[0].set(0, 0);
   1832     quad[1].set(width, 0);
   1833     quad[2].set(width, height);
   1834     quad[3].set(0, height);
   1835     SkMatrix m;
   1836     m.setRSXform(*this).mapPoints(quad, quad, 4);
   1837 #else
   1838     const SkScalar m00 = fSCos;
   1839     const SkScalar m01 = -fSSin;
   1840     const SkScalar m02 = fTx;
   1841     const SkScalar m10 = -m01;
   1842     const SkScalar m11 = m00;
   1843     const SkScalar m12 = fTy;
   1844 
   1845     quad[0].set(m02, m12);
   1846     quad[1].set(m00 * width + m02, m10 * width + m12);
   1847     quad[2].set(m00 * width + m01 * height + m02, m10 * width + m11 * height + m12);
   1848     quad[3].set(m01 * height + m02, m11 * height + m12);
   1849 #endif
   1850 }
   1851