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