Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2006 The Android Open Source Project
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SkMatrix.h"
      9 #include "SkFloatBits.h"
     10 #include "SkRSXform.h"
     11 #include "SkString.h"
     12 #include "SkNx.h"
     13 #include "SkOpts.h"
     14 
     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 || dy) {
    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     if (!dx && !dy) {
    291         return;
    292     }
    293 
    294     if (this->hasPerspective()) {
    295         SkMatrix    m;
    296         m.setTranslate(dx, dy);
    297         this->preConcat(m);
    298     } else {
    299         fMat[kMTransX] += sdot(fMat[kMScaleX], dx, fMat[kMSkewX], dy);
    300         fMat[kMTransY] += sdot(fMat[kMSkewY], dx, fMat[kMScaleY], dy);
    301         this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
    302     }
    303 }
    304 
    305 void SkMatrix::postTranslate(SkScalar dx, SkScalar dy) {
    306     if (!dx && !dy) {
    307         return;
    308     }
    309 
    310     if (this->hasPerspective()) {
    311         SkMatrix    m;
    312         m.setTranslate(dx, dy);
    313         this->postConcat(m);
    314     } else {
    315         fMat[kMTransX] += dx;
    316         fMat[kMTransY] += dy;
    317         this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
    318     }
    319 }
    320 
    321 ///////////////////////////////////////////////////////////////////////////////
    322 
    323 void SkMatrix::setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
    324     if (1 == sx && 1 == sy) {
    325         this->reset();
    326     } else {
    327         this->setScaleTranslate(sx, sy, px - sx * px, py - sy * py);
    328     }
    329 }
    330 
    331 void SkMatrix::setScale(SkScalar sx, SkScalar sy) {
    332     if (1 == sx && 1 == sy) {
    333         this->reset();
    334     } else {
    335         fMat[kMScaleX] = sx;
    336         fMat[kMScaleY] = sy;
    337         fMat[kMPersp2] = 1;
    338 
    339         fMat[kMTransX] = fMat[kMTransY] =
    340         fMat[kMSkewX]  = fMat[kMSkewY] =
    341         fMat[kMPersp0] = fMat[kMPersp1] = 0;
    342 
    343         this->setTypeMask(kScale_Mask | kRectStaysRect_Mask);
    344     }
    345 }
    346 
    347 bool SkMatrix::setIDiv(int divx, int divy) {
    348     if (!divx || !divy) {
    349         return false;
    350     }
    351     this->setScale(SkScalarInvert(divx), SkScalarInvert(divy));
    352     return true;
    353 }
    354 
    355 void SkMatrix::preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
    356     if (1 == sx && 1 == sy) {
    357         return;
    358     }
    359 
    360     SkMatrix    m;
    361     m.setScale(sx, sy, px, py);
    362     this->preConcat(m);
    363 }
    364 
    365 void SkMatrix::preScale(SkScalar sx, SkScalar sy) {
    366     if (1 == sx && 1 == sy) {
    367         return;
    368     }
    369 
    370     // the assumption is that these multiplies are very cheap, and that
    371     // a full concat and/or just computing the matrix type is more expensive.
    372     // Also, the fixed-point case checks for overflow, but the float doesn't,
    373     // so we can get away with these blind multiplies.
    374 
    375     fMat[kMScaleX] *= sx;
    376     fMat[kMSkewY]  *= sx;
    377     fMat[kMPersp0] *= sx;
    378 
    379     fMat[kMSkewX]  *= sy;
    380     fMat[kMScaleY] *= sy;
    381     fMat[kMPersp1] *= sy;
    382 
    383     // Attempt to simplify our type when applying an inverse scale.
    384     // TODO: The persp/affine preconditions are in place to keep the mask consistent with
    385     //       what computeTypeMask() would produce (persp/skew always implies kScale).
    386     //       We should investigate whether these flag dependencies are truly needed.
    387     if (fMat[kMScaleX] == 1 && fMat[kMScaleY] == 1
    388         && !(fTypeMask & (kPerspective_Mask | kAffine_Mask))) {
    389         this->clearTypeMask(kScale_Mask);
    390     } else {
    391         this->orTypeMask(kScale_Mask);
    392     }
    393 }
    394 
    395 void SkMatrix::postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
    396     if (1 == sx && 1 == sy) {
    397         return;
    398     }
    399     SkMatrix    m;
    400     m.setScale(sx, sy, px, py);
    401     this->postConcat(m);
    402 }
    403 
    404 void SkMatrix::postScale(SkScalar sx, SkScalar sy) {
    405     if (1 == sx && 1 == sy) {
    406         return;
    407     }
    408     SkMatrix    m;
    409     m.setScale(sx, sy);
    410     this->postConcat(m);
    411 }
    412 
    413 // this guy perhaps can go away, if we have a fract/high-precision way to
    414 // scale matrices
    415 bool SkMatrix::postIDiv(int divx, int divy) {
    416     if (divx == 0 || divy == 0) {
    417         return false;
    418     }
    419 
    420     const float invX = 1.f / divx;
    421     const float invY = 1.f / divy;
    422 
    423     fMat[kMScaleX] *= invX;
    424     fMat[kMSkewX]  *= invX;
    425     fMat[kMTransX] *= invX;
    426 
    427     fMat[kMScaleY] *= invY;
    428     fMat[kMSkewY]  *= invY;
    429     fMat[kMTransY] *= invY;
    430 
    431     this->setTypeMask(kUnknown_Mask);
    432     return true;
    433 }
    434 
    435 ////////////////////////////////////////////////////////////////////////////////////
    436 
    437 void SkMatrix::setSinCos(SkScalar sinV, SkScalar cosV, SkScalar px, SkScalar py) {
    438     const SkScalar oneMinusCosV = 1 - cosV;
    439 
    440     fMat[kMScaleX]  = cosV;
    441     fMat[kMSkewX]   = -sinV;
    442     fMat[kMTransX]  = sdot(sinV, py, oneMinusCosV, px);
    443 
    444     fMat[kMSkewY]   = sinV;
    445     fMat[kMScaleY]  = cosV;
    446     fMat[kMTransY]  = sdot(-sinV, px, oneMinusCosV, py);
    447 
    448     fMat[kMPersp0] = fMat[kMPersp1] = 0;
    449     fMat[kMPersp2] = 1;
    450 
    451     this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
    452 }
    453 
    454 SkMatrix& SkMatrix::setRSXform(const SkRSXform& xform) {
    455     fMat[kMScaleX]  = xform.fSCos;
    456     fMat[kMSkewX]   = -xform.fSSin;
    457     fMat[kMTransX]  = xform.fTx;
    458 
    459     fMat[kMSkewY]   = xform.fSSin;
    460     fMat[kMScaleY]  = xform.fSCos;
    461     fMat[kMTransY]  = xform.fTy;
    462 
    463     fMat[kMPersp0] = fMat[kMPersp1] = 0;
    464     fMat[kMPersp2] = 1;
    465 
    466     this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
    467     return *this;
    468 }
    469 
    470 void SkMatrix::setSinCos(SkScalar sinV, SkScalar cosV) {
    471     fMat[kMScaleX]  = cosV;
    472     fMat[kMSkewX]   = -sinV;
    473     fMat[kMTransX]  = 0;
    474 
    475     fMat[kMSkewY]   = sinV;
    476     fMat[kMScaleY]  = cosV;
    477     fMat[kMTransY]  = 0;
    478 
    479     fMat[kMPersp0] = fMat[kMPersp1] = 0;
    480     fMat[kMPersp2] = 1;
    481 
    482     this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
    483 }
    484 
    485 void SkMatrix::setRotate(SkScalar degrees, SkScalar px, SkScalar py) {
    486     SkScalar sinV, cosV;
    487     sinV = SkScalarSinCos(SkDegreesToRadians(degrees), &cosV);
    488     this->setSinCos(sinV, cosV, px, py);
    489 }
    490 
    491 void SkMatrix::setRotate(SkScalar degrees) {
    492     SkScalar sinV, cosV;
    493     sinV = SkScalarSinCos(SkDegreesToRadians(degrees), &cosV);
    494     this->setSinCos(sinV, cosV);
    495 }
    496 
    497 void SkMatrix::preRotate(SkScalar degrees, SkScalar px, SkScalar py) {
    498     SkMatrix    m;
    499     m.setRotate(degrees, px, py);
    500     this->preConcat(m);
    501 }
    502 
    503 void SkMatrix::preRotate(SkScalar degrees) {
    504     SkMatrix    m;
    505     m.setRotate(degrees);
    506     this->preConcat(m);
    507 }
    508 
    509 void SkMatrix::postRotate(SkScalar degrees, SkScalar px, SkScalar py) {
    510     SkMatrix    m;
    511     m.setRotate(degrees, px, py);
    512     this->postConcat(m);
    513 }
    514 
    515 void SkMatrix::postRotate(SkScalar degrees) {
    516     SkMatrix    m;
    517     m.setRotate(degrees);
    518     this->postConcat(m);
    519 }
    520 
    521 ////////////////////////////////////////////////////////////////////////////////////
    522 
    523 void SkMatrix::setSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
    524     fMat[kMScaleX]  = 1;
    525     fMat[kMSkewX]   = sx;
    526     fMat[kMTransX]  = -sx * py;
    527 
    528     fMat[kMSkewY]   = sy;
    529     fMat[kMScaleY]  = 1;
    530     fMat[kMTransY]  = -sy * px;
    531 
    532     fMat[kMPersp0] = fMat[kMPersp1] = 0;
    533     fMat[kMPersp2] = 1;
    534 
    535     this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
    536 }
    537 
    538 void SkMatrix::setSkew(SkScalar sx, SkScalar sy) {
    539     fMat[kMScaleX]  = 1;
    540     fMat[kMSkewX]   = sx;
    541     fMat[kMTransX]  = 0;
    542 
    543     fMat[kMSkewY]   = sy;
    544     fMat[kMScaleY]  = 1;
    545     fMat[kMTransY]  = 0;
    546 
    547     fMat[kMPersp0] = fMat[kMPersp1] = 0;
    548     fMat[kMPersp2] = 1;
    549 
    550     this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
    551 }
    552 
    553 void SkMatrix::preSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
    554     SkMatrix    m;
    555     m.setSkew(sx, sy, px, py);
    556     this->preConcat(m);
    557 }
    558 
    559 void SkMatrix::preSkew(SkScalar sx, SkScalar sy) {
    560     SkMatrix    m;
    561     m.setSkew(sx, sy);
    562     this->preConcat(m);
    563 }
    564 
    565 void SkMatrix::postSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
    566     SkMatrix    m;
    567     m.setSkew(sx, sy, px, py);
    568     this->postConcat(m);
    569 }
    570 
    571 void SkMatrix::postSkew(SkScalar sx, SkScalar sy) {
    572     SkMatrix    m;
    573     m.setSkew(sx, sy);
    574     this->postConcat(m);
    575 }
    576 
    577 ///////////////////////////////////////////////////////////////////////////////
    578 
    579 bool SkMatrix::setRectToRect(const SkRect& src, const SkRect& dst, ScaleToFit align) {
    580     if (src.isEmpty()) {
    581         this->reset();
    582         return false;
    583     }
    584 
    585     if (dst.isEmpty()) {
    586         sk_bzero(fMat, 8 * sizeof(SkScalar));
    587         fMat[kMPersp2] = 1;
    588         this->setTypeMask(kScale_Mask | kRectStaysRect_Mask);
    589     } else {
    590         SkScalar    tx, sx = dst.width() / src.width();
    591         SkScalar    ty, sy = dst.height() / src.height();
    592         bool        xLarger = false;
    593 
    594         if (align != kFill_ScaleToFit) {
    595             if (sx > sy) {
    596                 xLarger = true;
    597                 sx = sy;
    598             } else {
    599                 sy = sx;
    600             }
    601         }
    602 
    603         tx = dst.fLeft - src.fLeft * sx;
    604         ty = dst.fTop - src.fTop * sy;
    605         if (align == kCenter_ScaleToFit || align == kEnd_ScaleToFit) {
    606             SkScalar diff;
    607 
    608             if (xLarger) {
    609                 diff = dst.width() - src.width() * sy;
    610             } else {
    611                 diff = dst.height() - src.height() * sy;
    612             }
    613 
    614             if (align == kCenter_ScaleToFit) {
    615                 diff = SkScalarHalf(diff);
    616             }
    617 
    618             if (xLarger) {
    619                 tx += diff;
    620             } else {
    621                 ty += diff;
    622             }
    623         }
    624 
    625         this->setScaleTranslate(sx, sy, tx, ty);
    626     }
    627     return true;
    628 }
    629 
    630 ///////////////////////////////////////////////////////////////////////////////
    631 
    632 static inline float muladdmul(float a, float b, float c, float d) {
    633     return SkDoubleToFloat((double)a * b + (double)c * d);
    634 }
    635 
    636 static inline float rowcol3(const float row[], const float col[]) {
    637     return row[0] * col[0] + row[1] * col[3] + row[2] * col[6];
    638 }
    639 
    640 static bool only_scale_and_translate(unsigned mask) {
    641     return 0 == (mask & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask));
    642 }
    643 
    644 void SkMatrix::setConcat(const SkMatrix& a, const SkMatrix& b) {
    645     TypeMask aType = a.getType();
    646     TypeMask bType = b.getType();
    647 
    648     if (a.isTriviallyIdentity()) {
    649         *this = b;
    650     } else if (b.isTriviallyIdentity()) {
    651         *this = a;
    652     } else if (only_scale_and_translate(aType | bType)) {
    653         this->setScaleTranslate(a.fMat[kMScaleX] * b.fMat[kMScaleX],
    654                                 a.fMat[kMScaleY] * b.fMat[kMScaleY],
    655                                 a.fMat[kMScaleX] * b.fMat[kMTransX] + a.fMat[kMTransX],
    656                                 a.fMat[kMScaleY] * b.fMat[kMTransY] + a.fMat[kMTransY]);
    657     } else {
    658         SkMatrix tmp;
    659 
    660         if ((aType | bType) & kPerspective_Mask) {
    661             tmp.fMat[kMScaleX] = rowcol3(&a.fMat[0], &b.fMat[0]);
    662             tmp.fMat[kMSkewX]  = rowcol3(&a.fMat[0], &b.fMat[1]);
    663             tmp.fMat[kMTransX] = rowcol3(&a.fMat[0], &b.fMat[2]);
    664             tmp.fMat[kMSkewY]  = rowcol3(&a.fMat[3], &b.fMat[0]);
    665             tmp.fMat[kMScaleY] = rowcol3(&a.fMat[3], &b.fMat[1]);
    666             tmp.fMat[kMTransY] = rowcol3(&a.fMat[3], &b.fMat[2]);
    667             tmp.fMat[kMPersp0] = rowcol3(&a.fMat[6], &b.fMat[0]);
    668             tmp.fMat[kMPersp1] = rowcol3(&a.fMat[6], &b.fMat[1]);
    669             tmp.fMat[kMPersp2] = rowcol3(&a.fMat[6], &b.fMat[2]);
    670 
    671             normalize_perspective(tmp.fMat);
    672             tmp.setTypeMask(kUnknown_Mask);
    673         } else {
    674             tmp.fMat[kMScaleX] = muladdmul(a.fMat[kMScaleX],
    675                                            b.fMat[kMScaleX],
    676                                            a.fMat[kMSkewX],
    677                                            b.fMat[kMSkewY]);
    678 
    679             tmp.fMat[kMSkewX]  = muladdmul(a.fMat[kMScaleX],
    680                                            b.fMat[kMSkewX],
    681                                            a.fMat[kMSkewX],
    682                                            b.fMat[kMScaleY]);
    683 
    684             tmp.fMat[kMTransX] = muladdmul(a.fMat[kMScaleX],
    685                                            b.fMat[kMTransX],
    686                                            a.fMat[kMSkewX],
    687                                            b.fMat[kMTransY]) + a.fMat[kMTransX];
    688 
    689             tmp.fMat[kMSkewY]  = muladdmul(a.fMat[kMSkewY],
    690                                            b.fMat[kMScaleX],
    691                                            a.fMat[kMScaleY],
    692                                            b.fMat[kMSkewY]);
    693 
    694             tmp.fMat[kMScaleY] = muladdmul(a.fMat[kMSkewY],
    695                                            b.fMat[kMSkewX],
    696                                            a.fMat[kMScaleY],
    697                                            b.fMat[kMScaleY]);
    698 
    699             tmp.fMat[kMTransY] = muladdmul(a.fMat[kMSkewY],
    700                                            b.fMat[kMTransX],
    701                                            a.fMat[kMScaleY],
    702                                            b.fMat[kMTransY]) + a.fMat[kMTransY];
    703 
    704             tmp.fMat[kMPersp0] = 0;
    705             tmp.fMat[kMPersp1] = 0;
    706             tmp.fMat[kMPersp2] = 1;
    707             //SkDebugf("Concat mat non-persp type: %d\n", tmp.getType());
    708             //SkASSERT(!(tmp.getType() & kPerspective_Mask));
    709             tmp.setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
    710         }
    711         *this = tmp;
    712     }
    713 }
    714 
    715 void SkMatrix::preConcat(const SkMatrix& mat) {
    716     // check for identity first, so we don't do a needless copy of ourselves
    717     // to ourselves inside setConcat()
    718     if(!mat.isIdentity()) {
    719         this->setConcat(*this, mat);
    720     }
    721 }
    722 
    723 void SkMatrix::postConcat(const SkMatrix& mat) {
    724     // check for identity first, so we don't do a needless copy of ourselves
    725     // to ourselves inside setConcat()
    726     if (!mat.isIdentity()) {
    727         this->setConcat(mat, *this);
    728     }
    729 }
    730 
    731 ///////////////////////////////////////////////////////////////////////////////
    732 
    733 /*  Matrix inversion is very expensive, but also the place where keeping
    734     precision may be most important (here and matrix concat). Hence to avoid
    735     bitmap blitting artifacts when walking the inverse, we use doubles for
    736     the intermediate math, even though we know that is more expensive.
    737  */
    738 
    739 static inline SkScalar scross_dscale(SkScalar a, SkScalar b,
    740                                      SkScalar c, SkScalar d, double scale) {
    741     return SkDoubleToScalar(scross(a, b, c, d) * scale);
    742 }
    743 
    744 static inline double dcross(double a, double b, double c, double d) {
    745     return a * b - c * d;
    746 }
    747 
    748 static inline SkScalar dcross_dscale(double a, double b,
    749                                      double c, double d, double scale) {
    750     return SkDoubleToScalar(dcross(a, b, c, d) * scale);
    751 }
    752 
    753 static double sk_inv_determinant(const float mat[9], int isPerspective) {
    754     double det;
    755 
    756     if (isPerspective) {
    757         det = mat[SkMatrix::kMScaleX] *
    758               dcross(mat[SkMatrix::kMScaleY], mat[SkMatrix::kMPersp2],
    759                      mat[SkMatrix::kMTransY], mat[SkMatrix::kMPersp1])
    760               +
    761               mat[SkMatrix::kMSkewX]  *
    762               dcross(mat[SkMatrix::kMTransY], mat[SkMatrix::kMPersp0],
    763                      mat[SkMatrix::kMSkewY],  mat[SkMatrix::kMPersp2])
    764               +
    765               mat[SkMatrix::kMTransX] *
    766               dcross(mat[SkMatrix::kMSkewY],  mat[SkMatrix::kMPersp1],
    767                      mat[SkMatrix::kMScaleY], mat[SkMatrix::kMPersp0]);
    768     } else {
    769         det = dcross(mat[SkMatrix::kMScaleX], mat[SkMatrix::kMScaleY],
    770                      mat[SkMatrix::kMSkewX], mat[SkMatrix::kMSkewY]);
    771     }
    772 
    773     // Since the determinant is on the order of the cube of the matrix members,
    774     // compare to the cube of the default nearly-zero constant (although an
    775     // estimate of the condition number would be better if it wasn't so expensive).
    776     if (SkScalarNearlyZero((float)det, SK_ScalarNearlyZero * SK_ScalarNearlyZero * SK_ScalarNearlyZero)) {
    777         return 0;
    778     }
    779     return 1.0 / det;
    780 }
    781 
    782 void SkMatrix::SetAffineIdentity(SkScalar affine[6]) {
    783     affine[kAScaleX] = 1;
    784     affine[kASkewY] = 0;
    785     affine[kASkewX] = 0;
    786     affine[kAScaleY] = 1;
    787     affine[kATransX] = 0;
    788     affine[kATransY] = 0;
    789 }
    790 
    791 bool SkMatrix::asAffine(SkScalar affine[6]) const {
    792     if (this->hasPerspective()) {
    793         return false;
    794     }
    795     if (affine) {
    796         affine[kAScaleX] = this->fMat[kMScaleX];
    797         affine[kASkewY] = this->fMat[kMSkewY];
    798         affine[kASkewX] = this->fMat[kMSkewX];
    799         affine[kAScaleY] = this->fMat[kMScaleY];
    800         affine[kATransX] = this->fMat[kMTransX];
    801         affine[kATransY] = this->fMat[kMTransY];
    802     }
    803     return true;
    804 }
    805 
    806 void SkMatrix::ComputeInv(SkScalar dst[9], const SkScalar src[9], double invDet, bool isPersp) {
    807     SkASSERT(src != dst);
    808     SkASSERT(src && dst);
    809 
    810     if (isPersp) {
    811         dst[kMScaleX] = scross_dscale(src[kMScaleY], src[kMPersp2], src[kMTransY], src[kMPersp1], invDet);
    812         dst[kMSkewX]  = scross_dscale(src[kMTransX], src[kMPersp1], src[kMSkewX],  src[kMPersp2], invDet);
    813         dst[kMTransX] = scross_dscale(src[kMSkewX],  src[kMTransY], src[kMTransX], src[kMScaleY], invDet);
    814 
    815         dst[kMSkewY]  = scross_dscale(src[kMTransY], src[kMPersp0], src[kMSkewY],  src[kMPersp2], invDet);
    816         dst[kMScaleY] = scross_dscale(src[kMScaleX], src[kMPersp2], src[kMTransX], src[kMPersp0], invDet);
    817         dst[kMTransY] = scross_dscale(src[kMTransX], src[kMSkewY],  src[kMScaleX], src[kMTransY], invDet);
    818 
    819         dst[kMPersp0] = scross_dscale(src[kMSkewY],  src[kMPersp1], src[kMScaleY], src[kMPersp0], invDet);
    820         dst[kMPersp1] = scross_dscale(src[kMSkewX],  src[kMPersp0], src[kMScaleX], src[kMPersp1], invDet);
    821         dst[kMPersp2] = scross_dscale(src[kMScaleX], src[kMScaleY], src[kMSkewX],  src[kMSkewY],  invDet);
    822     } else {   // not perspective
    823         dst[kMScaleX] = SkDoubleToScalar(src[kMScaleY] * invDet);
    824         dst[kMSkewX]  = SkDoubleToScalar(-src[kMSkewX] * invDet);
    825         dst[kMTransX] = dcross_dscale(src[kMSkewX], src[kMTransY], src[kMScaleY], src[kMTransX], invDet);
    826 
    827         dst[kMSkewY]  = SkDoubleToScalar(-src[kMSkewY] * invDet);
    828         dst[kMScaleY] = SkDoubleToScalar(src[kMScaleX] * invDet);
    829         dst[kMTransY] = dcross_dscale(src[kMSkewY], src[kMTransX], src[kMScaleX], src[kMTransY], invDet);
    830 
    831         dst[kMPersp0] = 0;
    832         dst[kMPersp1] = 0;
    833         dst[kMPersp2] = 1;
    834     }
    835 }
    836 
    837 bool SkMatrix::invertNonIdentity(SkMatrix* inv) const {
    838     SkASSERT(!this->isIdentity());
    839 
    840     TypeMask mask = this->getType();
    841 
    842     if (0 == (mask & ~(kScale_Mask | kTranslate_Mask))) {
    843         bool invertible = true;
    844         if (inv) {
    845             if (mask & kScale_Mask) {
    846                 SkScalar invX = fMat[kMScaleX];
    847                 SkScalar invY = fMat[kMScaleY];
    848                 if (0 == invX || 0 == invY) {
    849                     return false;
    850                 }
    851                 invX = SkScalarInvert(invX);
    852                 invY = SkScalarInvert(invY);
    853 
    854                 // Must be careful when writing to inv, since it may be the
    855                 // same memory as this.
    856 
    857                 inv->fMat[kMSkewX] = inv->fMat[kMSkewY] =
    858                 inv->fMat[kMPersp0] = inv->fMat[kMPersp1] = 0;
    859 
    860                 inv->fMat[kMScaleX] = invX;
    861                 inv->fMat[kMScaleY] = invY;
    862                 inv->fMat[kMPersp2] = 1;
    863                 inv->fMat[kMTransX] = -fMat[kMTransX] * invX;
    864                 inv->fMat[kMTransY] = -fMat[kMTransY] * invY;
    865 
    866                 inv->setTypeMask(mask | kRectStaysRect_Mask);
    867             } else {
    868                 // translate only
    869                 inv->setTranslate(-fMat[kMTransX], -fMat[kMTransY]);
    870             }
    871         } else {    // inv is nullptr, just check if we're invertible
    872             if (!fMat[kMScaleX] || !fMat[kMScaleY]) {
    873                 invertible = false;
    874             }
    875         }
    876         return invertible;
    877     }
    878 
    879     int    isPersp = mask & kPerspective_Mask;
    880     double invDet = sk_inv_determinant(fMat, isPersp);
    881 
    882     if (invDet == 0) { // underflow
    883         return false;
    884     }
    885 
    886     bool applyingInPlace = (inv == this);
    887 
    888     SkMatrix* tmp = inv;
    889 
    890     SkMatrix storage;
    891     if (applyingInPlace || nullptr == tmp) {
    892         tmp = &storage;     // we either need to avoid trampling memory or have no memory
    893     }
    894 
    895     ComputeInv(tmp->fMat, fMat, invDet, isPersp);
    896     if (!tmp->isFinite()) {
    897         return false;
    898     }
    899 
    900     tmp->setTypeMask(fTypeMask);
    901 
    902     if (applyingInPlace) {
    903         *inv = storage; // need to copy answer back
    904     }
    905 
    906     return true;
    907 }
    908 
    909 ///////////////////////////////////////////////////////////////////////////////
    910 
    911 void SkMatrix::Identity_pts(const SkMatrix& m, SkPoint dst[], const SkPoint src[], int count) {
    912     SkASSERT(m.getType() == 0);
    913 
    914     if (dst != src && count > 0) {
    915         memcpy(dst, src, count * sizeof(SkPoint));
    916     }
    917 }
    918 
    919 void SkMatrix::Trans_pts(const SkMatrix& m, SkPoint dst[], const SkPoint src[], int count) {
    920     return SkOpts::matrix_translate(m,dst,src,count);
    921 }
    922 
    923 void SkMatrix::Scale_pts(const SkMatrix& m, SkPoint dst[], const SkPoint src[], int count) {
    924     return SkOpts::matrix_scale_translate(m,dst,src,count);
    925 }
    926 
    927 void SkMatrix::Persp_pts(const SkMatrix& m, SkPoint dst[],
    928                          const SkPoint src[], int count) {
    929     SkASSERT(m.hasPerspective());
    930 
    931     if (count > 0) {
    932         do {
    933             SkScalar sy = src->fY;
    934             SkScalar sx = src->fX;
    935             src += 1;
    936 
    937             SkScalar x = sdot(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX])  + m.fMat[kMTransX];
    938             SkScalar y = sdot(sx, m.fMat[kMSkewY],  sy, m.fMat[kMScaleY]) + m.fMat[kMTransY];
    939 #ifdef SK_LEGACY_MATRIX_MATH_ORDER
    940             SkScalar z = sx * m.fMat[kMPersp0] + (sy * m.fMat[kMPersp1] + m.fMat[kMPersp2]);
    941 #else
    942             SkScalar z = sdot(sx, m.fMat[kMPersp0], sy, m.fMat[kMPersp1]) + m.fMat[kMPersp2];
    943 #endif
    944             if (z) {
    945                 z = SkScalarFastInvert(z);
    946             }
    947 
    948             dst->fY = y * z;
    949             dst->fX = x * z;
    950             dst += 1;
    951         } while (--count);
    952     }
    953 }
    954 
    955 void SkMatrix::Affine_vpts(const SkMatrix& m, SkPoint dst[], const SkPoint src[], int count) {
    956     return SkOpts::matrix_affine(m,dst,src,count);
    957 }
    958 
    959 const SkMatrix::MapPtsProc SkMatrix::gMapPtsProcs[] = {
    960     SkMatrix::Identity_pts, SkMatrix::Trans_pts,
    961     SkMatrix::Scale_pts,   SkMatrix::Scale_pts,
    962     SkMatrix::Affine_vpts,  SkMatrix::Affine_vpts,
    963     SkMatrix::Affine_vpts,  SkMatrix::Affine_vpts,
    964     // repeat the persp proc 8 times
    965     SkMatrix::Persp_pts,    SkMatrix::Persp_pts,
    966     SkMatrix::Persp_pts,    SkMatrix::Persp_pts,
    967     SkMatrix::Persp_pts,    SkMatrix::Persp_pts,
    968     SkMatrix::Persp_pts,    SkMatrix::Persp_pts
    969 };
    970 
    971 ///////////////////////////////////////////////////////////////////////////////
    972 
    973 void SkMatrix::mapHomogeneousPoints(SkScalar dst[], const SkScalar src[], int count) const {
    974     SkASSERT((dst && src && count > 0) || 0 == count);
    975     // no partial overlap
    976     SkASSERT(src == dst || &dst[3*count] <= &src[0] || &src[3*count] <= &dst[0]);
    977 
    978     if (count > 0) {
    979         if (this->isIdentity()) {
    980             memcpy(dst, src, 3*count*sizeof(SkScalar));
    981             return;
    982         }
    983         do {
    984             SkScalar sx = src[0];
    985             SkScalar sy = src[1];
    986             SkScalar sw = src[2];
    987             src += 3;
    988 
    989             SkScalar x = sdot(sx, fMat[kMScaleX], sy, fMat[kMSkewX],  sw, fMat[kMTransX]);
    990             SkScalar y = sdot(sx, fMat[kMSkewY],  sy, fMat[kMScaleY], sw, fMat[kMTransY]);
    991             SkScalar w = sdot(sx, fMat[kMPersp0], sy, fMat[kMPersp1], sw, fMat[kMPersp2]);
    992 
    993             dst[0] = x;
    994             dst[1] = y;
    995             dst[2] = w;
    996             dst += 3;
    997         } while (--count);
    998     }
    999 }
   1000 
   1001 ///////////////////////////////////////////////////////////////////////////////
   1002 
   1003 void SkMatrix::mapVectors(SkPoint dst[], const SkPoint src[], int count) const {
   1004     if (this->hasPerspective()) {
   1005         SkPoint origin;
   1006 
   1007         MapXYProc proc = this->getMapXYProc();
   1008         proc(*this, 0, 0, &origin);
   1009 
   1010         for (int i = count - 1; i >= 0; --i) {
   1011             SkPoint tmp;
   1012 
   1013             proc(*this, src[i].fX, src[i].fY, &tmp);
   1014             dst[i].set(tmp.fX - origin.fX, tmp.fY - origin.fY);
   1015         }
   1016     } else {
   1017         SkMatrix tmp = *this;
   1018 
   1019         tmp.fMat[kMTransX] = tmp.fMat[kMTransY] = 0;
   1020         tmp.clearTypeMask(kTranslate_Mask);
   1021         tmp.mapPoints(dst, src, count);
   1022     }
   1023 }
   1024 
   1025 bool SkMatrix::mapRect(SkRect* dst, const SkRect& src) const {
   1026     SkASSERT(dst);
   1027 
   1028     if (this->rectStaysRect()) {
   1029         this->mapPoints((SkPoint*)dst, (const SkPoint*)&src, 2);
   1030         dst->sort();
   1031         return true;
   1032     } else {
   1033         SkPoint quad[4];
   1034 
   1035         src.toQuad(quad);
   1036         this->mapPoints(quad, quad, 4);
   1037         dst->set(quad, 4);
   1038         return false;
   1039     }
   1040 }
   1041 
   1042 SkScalar SkMatrix::mapRadius(SkScalar radius) const {
   1043     SkVector    vec[2];
   1044 
   1045     vec[0].set(radius, 0);
   1046     vec[1].set(0, radius);
   1047     this->mapVectors(vec, 2);
   1048 
   1049     SkScalar d0 = vec[0].length();
   1050     SkScalar d1 = vec[1].length();
   1051 
   1052     // return geometric mean
   1053     return SkScalarSqrt(d0 * d1);
   1054 }
   1055 
   1056 ///////////////////////////////////////////////////////////////////////////////
   1057 
   1058 void SkMatrix::Persp_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
   1059                         SkPoint* pt) {
   1060     SkASSERT(m.hasPerspective());
   1061 
   1062     SkScalar x = sdot(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX])  + m.fMat[kMTransX];
   1063     SkScalar y = sdot(sx, m.fMat[kMSkewY],  sy, m.fMat[kMScaleY]) + m.fMat[kMTransY];
   1064     SkScalar z = sdot(sx, m.fMat[kMPersp0], sy, m.fMat[kMPersp1]) + m.fMat[kMPersp2];
   1065     if (z) {
   1066         z = SkScalarFastInvert(z);
   1067     }
   1068     pt->fX = x * z;
   1069     pt->fY = y * z;
   1070 }
   1071 
   1072 void SkMatrix::RotTrans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
   1073                            SkPoint* pt) {
   1074     SkASSERT((m.getType() & (kAffine_Mask | kPerspective_Mask)) == kAffine_Mask);
   1075 
   1076 #ifdef SK_LEGACY_MATRIX_MATH_ORDER
   1077     pt->fX = sx * m.fMat[kMScaleX] + (sy * m.fMat[kMSkewX]  +  m.fMat[kMTransX]);
   1078     pt->fY = sx * m.fMat[kMSkewY]  + (sy * m.fMat[kMScaleY] + m.fMat[kMTransY]);
   1079 #else
   1080     pt->fX = sdot(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX])  + m.fMat[kMTransX];
   1081     pt->fY = sdot(sx, m.fMat[kMSkewY],  sy, m.fMat[kMScaleY]) + m.fMat[kMTransY];
   1082 #endif
   1083 }
   1084 
   1085 void SkMatrix::Rot_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
   1086                       SkPoint* pt) {
   1087     SkASSERT((m.getType() & (kAffine_Mask | kPerspective_Mask))== kAffine_Mask);
   1088     SkASSERT(0 == m.fMat[kMTransX]);
   1089     SkASSERT(0 == m.fMat[kMTransY]);
   1090 
   1091 #ifdef SK_LEGACY_MATRIX_MATH_ORDER
   1092     pt->fX = sx * m.fMat[kMScaleX] + (sy * m.fMat[kMSkewX]  + m.fMat[kMTransX]);
   1093     pt->fY = sx * m.fMat[kMSkewY]  + (sy * m.fMat[kMScaleY] + m.fMat[kMTransY]);
   1094 #else
   1095     pt->fX = sdot(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX])  + m.fMat[kMTransX];
   1096     pt->fY = sdot(sx, m.fMat[kMSkewY],  sy, m.fMat[kMScaleY]) + m.fMat[kMTransY];
   1097 #endif
   1098 }
   1099 
   1100 void SkMatrix::ScaleTrans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
   1101                              SkPoint* pt) {
   1102     SkASSERT((m.getType() & (kScale_Mask | kAffine_Mask | kPerspective_Mask))
   1103              == kScale_Mask);
   1104 
   1105     pt->fX = sx * m.fMat[kMScaleX] + m.fMat[kMTransX];
   1106     pt->fY = sy * m.fMat[kMScaleY] + m.fMat[kMTransY];
   1107 }
   1108 
   1109 void SkMatrix::Scale_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
   1110                         SkPoint* pt) {
   1111     SkASSERT((m.getType() & (kScale_Mask | kAffine_Mask | kPerspective_Mask))
   1112              == kScale_Mask);
   1113     SkASSERT(0 == m.fMat[kMTransX]);
   1114     SkASSERT(0 == m.fMat[kMTransY]);
   1115 
   1116     pt->fX = sx * m.fMat[kMScaleX];
   1117     pt->fY = sy * m.fMat[kMScaleY];
   1118 }
   1119 
   1120 void SkMatrix::Trans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
   1121                         SkPoint* pt) {
   1122     SkASSERT(m.getType() == kTranslate_Mask);
   1123 
   1124     pt->fX = sx + m.fMat[kMTransX];
   1125     pt->fY = sy + m.fMat[kMTransY];
   1126 }
   1127 
   1128 void SkMatrix::Identity_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
   1129                            SkPoint* pt) {
   1130     SkASSERT(0 == m.getType());
   1131 
   1132     pt->fX = sx;
   1133     pt->fY = sy;
   1134 }
   1135 
   1136 const SkMatrix::MapXYProc SkMatrix::gMapXYProcs[] = {
   1137     SkMatrix::Identity_xy, SkMatrix::Trans_xy,
   1138     SkMatrix::Scale_xy,    SkMatrix::ScaleTrans_xy,
   1139     SkMatrix::Rot_xy,      SkMatrix::RotTrans_xy,
   1140     SkMatrix::Rot_xy,      SkMatrix::RotTrans_xy,
   1141     // repeat the persp proc 8 times
   1142     SkMatrix::Persp_xy,    SkMatrix::Persp_xy,
   1143     SkMatrix::Persp_xy,    SkMatrix::Persp_xy,
   1144     SkMatrix::Persp_xy,    SkMatrix::Persp_xy,
   1145     SkMatrix::Persp_xy,    SkMatrix::Persp_xy
   1146 };
   1147 
   1148 ///////////////////////////////////////////////////////////////////////////////
   1149 
   1150 // if its nearly zero (just made up 26, perhaps it should be bigger or smaller)
   1151 #define PerspNearlyZero(x)  SkScalarNearlyZero(x, (1.0f / (1 << 26)))
   1152 
   1153 bool SkMatrix::isFixedStepInX() const {
   1154   return PerspNearlyZero(fMat[kMPersp0]);
   1155 }
   1156 
   1157 SkVector SkMatrix::fixedStepInX(SkScalar y) const {
   1158     SkASSERT(PerspNearlyZero(fMat[kMPersp0]));
   1159     if (PerspNearlyZero(fMat[kMPersp1]) &&
   1160         PerspNearlyZero(fMat[kMPersp2] - 1)) {
   1161         return SkVector::Make(fMat[kMScaleX], fMat[kMSkewY]);
   1162     } else {
   1163         SkScalar z = y * fMat[kMPersp1] + fMat[kMPersp2];
   1164         return SkVector::Make(fMat[kMScaleX] / z, fMat[kMSkewY] / z);
   1165     }
   1166 }
   1167 
   1168 ///////////////////////////////////////////////////////////////////////////////
   1169 
   1170 #include "SkPerspIter.h"
   1171 
   1172 SkPerspIter::SkPerspIter(const SkMatrix& m, SkScalar x0, SkScalar y0, int count)
   1173         : fMatrix(m), fSX(x0), fSY(y0), fCount(count) {
   1174     SkPoint pt;
   1175 
   1176     SkMatrix::Persp_xy(m, x0, y0, &pt);
   1177     fX = SkScalarToFixed(pt.fX);
   1178     fY = SkScalarToFixed(pt.fY);
   1179 }
   1180 
   1181 int SkPerspIter::next() {
   1182     int n = fCount;
   1183 
   1184     if (0 == n) {
   1185         return 0;
   1186     }
   1187     SkPoint pt;
   1188     SkFixed x = fX;
   1189     SkFixed y = fY;
   1190     SkFixed dx, dy;
   1191 
   1192     if (n >= kCount) {
   1193         n = kCount;
   1194         fSX += SkIntToScalar(kCount);
   1195         SkMatrix::Persp_xy(fMatrix, fSX, fSY, &pt);
   1196         fX = SkScalarToFixed(pt.fX);
   1197         fY = SkScalarToFixed(pt.fY);
   1198         dx = (fX - x) >> kShift;
   1199         dy = (fY - y) >> kShift;
   1200     } else {
   1201         fSX += SkIntToScalar(n);
   1202         SkMatrix::Persp_xy(fMatrix, fSX, fSY, &pt);
   1203         fX = SkScalarToFixed(pt.fX);
   1204         fY = SkScalarToFixed(pt.fY);
   1205         dx = (fX - x) / n;
   1206         dy = (fY - y) / n;
   1207     }
   1208 
   1209     SkFixed* p = fStorage;
   1210     for (int i = 0; i < n; i++) {
   1211         *p++ = x; x += dx;
   1212         *p++ = y; y += dy;
   1213     }
   1214 
   1215     fCount -= n;
   1216     return n;
   1217 }
   1218 
   1219 ///////////////////////////////////////////////////////////////////////////////
   1220 
   1221 static inline bool checkForZero(float x) {
   1222     return x*x == 0;
   1223 }
   1224 
   1225 static inline bool poly_to_point(SkPoint* pt, const SkPoint poly[], int count) {
   1226     float   x = 1, y = 1;
   1227     SkPoint pt1, pt2;
   1228 
   1229     if (count > 1) {
   1230         pt1.fX = poly[1].fX - poly[0].fX;
   1231         pt1.fY = poly[1].fY - poly[0].fY;
   1232         y = SkPoint::Length(pt1.fX, pt1.fY);
   1233         if (checkForZero(y)) {
   1234             return false;
   1235         }
   1236         switch (count) {
   1237             case 2:
   1238                 break;
   1239             case 3:
   1240                 pt2.fX = poly[0].fY - poly[2].fY;
   1241                 pt2.fY = poly[2].fX - poly[0].fX;
   1242                 goto CALC_X;
   1243             default:
   1244                 pt2.fX = poly[0].fY - poly[3].fY;
   1245                 pt2.fY = poly[3].fX - poly[0].fX;
   1246             CALC_X:
   1247                 x = sdot(pt1.fX, pt2.fX, pt1.fY, pt2.fY) / y;
   1248                 break;
   1249         }
   1250     }
   1251     pt->set(x, y);
   1252     return true;
   1253 }
   1254 
   1255 bool SkMatrix::Poly2Proc(const SkPoint srcPt[], SkMatrix* dst,
   1256                          const SkPoint& scale) {
   1257     float invScale = 1 / scale.fY;
   1258 
   1259     dst->fMat[kMScaleX] = (srcPt[1].fY - srcPt[0].fY) * invScale;
   1260     dst->fMat[kMSkewY] = (srcPt[0].fX - srcPt[1].fX) * invScale;
   1261     dst->fMat[kMPersp0] = 0;
   1262     dst->fMat[kMSkewX] = (srcPt[1].fX - srcPt[0].fX) * invScale;
   1263     dst->fMat[kMScaleY] = (srcPt[1].fY - srcPt[0].fY) * invScale;
   1264     dst->fMat[kMPersp1] = 0;
   1265     dst->fMat[kMTransX] = srcPt[0].fX;
   1266     dst->fMat[kMTransY] = srcPt[0].fY;
   1267     dst->fMat[kMPersp2] = 1;
   1268     dst->setTypeMask(kUnknown_Mask);
   1269     return true;
   1270 }
   1271 
   1272 bool SkMatrix::Poly3Proc(const SkPoint srcPt[], SkMatrix* dst,
   1273                          const SkPoint& scale) {
   1274     float invScale = 1 / scale.fX;
   1275     dst->fMat[kMScaleX] = (srcPt[2].fX - srcPt[0].fX) * invScale;
   1276     dst->fMat[kMSkewY] = (srcPt[2].fY - srcPt[0].fY) * invScale;
   1277     dst->fMat[kMPersp0] = 0;
   1278 
   1279     invScale = 1 / scale.fY;
   1280     dst->fMat[kMSkewX] = (srcPt[1].fX - srcPt[0].fX) * invScale;
   1281     dst->fMat[kMScaleY] = (srcPt[1].fY - srcPt[0].fY) * invScale;
   1282     dst->fMat[kMPersp1] = 0;
   1283 
   1284     dst->fMat[kMTransX] = srcPt[0].fX;
   1285     dst->fMat[kMTransY] = srcPt[0].fY;
   1286     dst->fMat[kMPersp2] = 1;
   1287     dst->setTypeMask(kUnknown_Mask);
   1288     return true;
   1289 }
   1290 
   1291 bool SkMatrix::Poly4Proc(const SkPoint srcPt[], SkMatrix* dst,
   1292                          const SkPoint& scale) {
   1293     float   a1, a2;
   1294     float   x0, y0, x1, y1, x2, y2;
   1295 
   1296     x0 = srcPt[2].fX - srcPt[0].fX;
   1297     y0 = srcPt[2].fY - srcPt[0].fY;
   1298     x1 = srcPt[2].fX - srcPt[1].fX;
   1299     y1 = srcPt[2].fY - srcPt[1].fY;
   1300     x2 = srcPt[2].fX - srcPt[3].fX;
   1301     y2 = srcPt[2].fY - srcPt[3].fY;
   1302 
   1303     /* check if abs(x2) > abs(y2) */
   1304     if ( x2 > 0 ? y2 > 0 ? x2 > y2 : x2 > -y2 : y2 > 0 ? -x2 > y2 : x2 < y2) {
   1305         float denom = SkScalarMulDiv(x1, y2, x2) - y1;
   1306         if (checkForZero(denom)) {
   1307             return false;
   1308         }
   1309         a1 = (SkScalarMulDiv(x0 - x1, y2, x2) - y0 + y1) / denom;
   1310     } else {
   1311         float denom = x1 - SkScalarMulDiv(y1, x2, y2);
   1312         if (checkForZero(denom)) {
   1313             return false;
   1314         }
   1315         a1 = (x0 - x1 - SkScalarMulDiv(y0 - y1, x2, y2)) / denom;
   1316     }
   1317 
   1318     /* check if abs(x1) > abs(y1) */
   1319     if ( x1 > 0 ? y1 > 0 ? x1 > y1 : x1 > -y1 : y1 > 0 ? -x1 > y1 : x1 < y1) {
   1320         float denom = y2 - SkScalarMulDiv(x2, y1, x1);
   1321         if (checkForZero(denom)) {
   1322             return false;
   1323         }
   1324         a2 = (y0 - y2 - SkScalarMulDiv(x0 - x2, y1, x1)) / denom;
   1325     } else {
   1326         float denom = SkScalarMulDiv(y2, x1, y1) - x2;
   1327         if (checkForZero(denom)) {
   1328             return false;
   1329         }
   1330         a2 = (SkScalarMulDiv(y0 - y2, x1, y1) - x0 + x2) / denom;
   1331     }
   1332 
   1333     float invScale = SkScalarInvert(scale.fX);
   1334     dst->fMat[kMScaleX] = (a2 * srcPt[3].fX + srcPt[3].fX - srcPt[0].fX) * invScale;
   1335     dst->fMat[kMSkewY]  = (a2 * srcPt[3].fY + srcPt[3].fY - srcPt[0].fY) * invScale;
   1336     dst->fMat[kMPersp0] = a2 * invScale;
   1337 
   1338     invScale = SkScalarInvert(scale.fY);
   1339     dst->fMat[kMSkewX]  = (a1 * srcPt[1].fX + srcPt[1].fX - srcPt[0].fX) * invScale;
   1340     dst->fMat[kMScaleY] = (a1 * srcPt[1].fY + srcPt[1].fY - srcPt[0].fY) * invScale;
   1341     dst->fMat[kMPersp1] = a1 * invScale;
   1342 
   1343     dst->fMat[kMTransX] = srcPt[0].fX;
   1344     dst->fMat[kMTransY] = srcPt[0].fY;
   1345     dst->fMat[kMPersp2] = 1;
   1346     dst->setTypeMask(kUnknown_Mask);
   1347     return true;
   1348 }
   1349 
   1350 typedef bool (*PolyMapProc)(const SkPoint[], SkMatrix*, const SkPoint&);
   1351 
   1352 /*  Taken from Rob Johnson's original sample code in QuickDraw GX
   1353 */
   1354 bool SkMatrix::setPolyToPoly(const SkPoint src[], const SkPoint dst[],
   1355                              int count) {
   1356     if ((unsigned)count > 4) {
   1357         SkDebugf("--- SkMatrix::setPolyToPoly count out of range %d\n", count);
   1358         return false;
   1359     }
   1360 
   1361     if (0 == count) {
   1362         this->reset();
   1363         return true;
   1364     }
   1365     if (1 == count) {
   1366         this->setTranslate(dst[0].fX - src[0].fX, dst[0].fY - src[0].fY);
   1367         return true;
   1368     }
   1369 
   1370     SkPoint scale;
   1371     if (!poly_to_point(&scale, src, count) ||
   1372             SkScalarNearlyZero(scale.fX) ||
   1373             SkScalarNearlyZero(scale.fY)) {
   1374         return false;
   1375     }
   1376 
   1377     static const PolyMapProc gPolyMapProcs[] = {
   1378         SkMatrix::Poly2Proc, SkMatrix::Poly3Proc, SkMatrix::Poly4Proc
   1379     };
   1380     PolyMapProc proc = gPolyMapProcs[count - 2];
   1381 
   1382     SkMatrix tempMap, result;
   1383     tempMap.setTypeMask(kUnknown_Mask);
   1384 
   1385     if (!proc(src, &tempMap, scale)) {
   1386         return false;
   1387     }
   1388     if (!tempMap.invert(&result)) {
   1389         return false;
   1390     }
   1391     if (!proc(dst, &tempMap, scale)) {
   1392         return false;
   1393     }
   1394     this->setConcat(tempMap, result);
   1395     return true;
   1396 }
   1397 
   1398 ///////////////////////////////////////////////////////////////////////////////
   1399 
   1400 enum MinMaxOrBoth {
   1401     kMin_MinMaxOrBoth,
   1402     kMax_MinMaxOrBoth,
   1403     kBoth_MinMaxOrBoth
   1404 };
   1405 
   1406 template <MinMaxOrBoth MIN_MAX_OR_BOTH> bool get_scale_factor(SkMatrix::TypeMask typeMask,
   1407                                                               const SkScalar m[9],
   1408                                                               SkScalar results[/*1 or 2*/]) {
   1409     if (typeMask & SkMatrix::kPerspective_Mask) {
   1410         return false;
   1411     }
   1412     if (SkMatrix::kIdentity_Mask == typeMask) {
   1413         results[0] = SK_Scalar1;
   1414         if (kBoth_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
   1415             results[1] = SK_Scalar1;
   1416         }
   1417         return true;
   1418     }
   1419     if (!(typeMask & SkMatrix::kAffine_Mask)) {
   1420         if (kMin_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
   1421              results[0] = SkMinScalar(SkScalarAbs(m[SkMatrix::kMScaleX]),
   1422                                       SkScalarAbs(m[SkMatrix::kMScaleY]));
   1423         } else if (kMax_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
   1424              results[0] = SkMaxScalar(SkScalarAbs(m[SkMatrix::kMScaleX]),
   1425                                       SkScalarAbs(m[SkMatrix::kMScaleY]));
   1426         } else {
   1427             results[0] = SkScalarAbs(m[SkMatrix::kMScaleX]);
   1428             results[1] = SkScalarAbs(m[SkMatrix::kMScaleY]);
   1429              if (results[0] > results[1]) {
   1430                  SkTSwap(results[0], results[1]);
   1431              }
   1432         }
   1433         return true;
   1434     }
   1435     // ignore the translation part of the matrix, just look at 2x2 portion.
   1436     // compute singular values, take largest or smallest abs value.
   1437     // [a b; b c] = A^T*A
   1438     SkScalar a = sdot(m[SkMatrix::kMScaleX], m[SkMatrix::kMScaleX],
   1439                       m[SkMatrix::kMSkewY],  m[SkMatrix::kMSkewY]);
   1440     SkScalar b = sdot(m[SkMatrix::kMScaleX], m[SkMatrix::kMSkewX],
   1441                       m[SkMatrix::kMScaleY], m[SkMatrix::kMSkewY]);
   1442     SkScalar c = sdot(m[SkMatrix::kMSkewX],  m[SkMatrix::kMSkewX],
   1443                       m[SkMatrix::kMScaleY], m[SkMatrix::kMScaleY]);
   1444     // eigenvalues of A^T*A are the squared singular values of A.
   1445     // characteristic equation is det((A^T*A) - l*I) = 0
   1446     // l^2 - (a + c)l + (ac-b^2)
   1447     // solve using quadratic equation (divisor is non-zero since l^2 has 1 coeff
   1448     // and roots are guaranteed to be pos and real).
   1449     SkScalar bSqd = b * b;
   1450     // if upper left 2x2 is orthogonal save some math
   1451     if (bSqd <= SK_ScalarNearlyZero*SK_ScalarNearlyZero) {
   1452         if (kMin_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
   1453             results[0] = SkMinScalar(a, c);
   1454         } else if (kMax_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
   1455             results[0] = SkMaxScalar(a, c);
   1456         } else {
   1457             results[0] = a;
   1458             results[1] = c;
   1459             if (results[0] > results[1]) {
   1460                 SkTSwap(results[0], results[1]);
   1461             }
   1462         }
   1463     } else {
   1464         SkScalar aminusc = a - c;
   1465         SkScalar apluscdiv2 = SkScalarHalf(a + c);
   1466         SkScalar x = SkScalarHalf(SkScalarSqrt(aminusc * aminusc + 4 * bSqd));
   1467         if (kMin_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
   1468             results[0] = apluscdiv2 - x;
   1469         } else if (kMax_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
   1470             results[0] = apluscdiv2 + x;
   1471         } else {
   1472             results[0] = apluscdiv2 - x;
   1473             results[1] = apluscdiv2 + x;
   1474         }
   1475     }
   1476     if (SkScalarIsNaN(results[0])) {
   1477         return false;
   1478     }
   1479     SkASSERT(results[0] >= 0);
   1480     results[0] = SkScalarSqrt(results[0]);
   1481     if (kBoth_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
   1482         if (SkScalarIsNaN(results[1])) {
   1483             return false;
   1484         }
   1485         SkASSERT(results[1] >= 0);
   1486         results[1] = SkScalarSqrt(results[1]);
   1487     }
   1488     return true;
   1489 }
   1490 
   1491 SkScalar SkMatrix::getMinScale() const {
   1492     SkScalar factor;
   1493     if (get_scale_factor<kMin_MinMaxOrBoth>(this->getType(), fMat, &factor)) {
   1494         return factor;
   1495     } else {
   1496         return -1;
   1497     }
   1498 }
   1499 
   1500 SkScalar SkMatrix::getMaxScale() const {
   1501     SkScalar factor;
   1502     if (get_scale_factor<kMax_MinMaxOrBoth>(this->getType(), fMat, &factor)) {
   1503         return factor;
   1504     } else {
   1505         return -1;
   1506     }
   1507 }
   1508 
   1509 bool SkMatrix::getMinMaxScales(SkScalar scaleFactors[2]) const {
   1510     return get_scale_factor<kBoth_MinMaxOrBoth>(this->getType(), fMat, scaleFactors);
   1511 }
   1512 
   1513 namespace {
   1514 
   1515 // SkMatrix is C++11 POD (trivial and standard-layout), but not aggregate (it has private fields).
   1516 struct AggregateMatrix {
   1517     SkScalar matrix[9];
   1518     uint32_t typemask;
   1519 
   1520     const SkMatrix& asSkMatrix() const { return *reinterpret_cast<const SkMatrix*>(this); }
   1521 };
   1522 static_assert(sizeof(AggregateMatrix) == sizeof(SkMatrix), "AggregateMatrix size mismatch.");
   1523 
   1524 }  // namespace
   1525 
   1526 const SkMatrix& SkMatrix::I() {
   1527     static_assert(offsetof(SkMatrix,fMat)      == offsetof(AggregateMatrix,matrix),   "fMat");
   1528     static_assert(offsetof(SkMatrix,fTypeMask) == offsetof(AggregateMatrix,typemask), "fTypeMask");
   1529 
   1530     static const AggregateMatrix identity = { {SK_Scalar1, 0, 0,
   1531                                                0, SK_Scalar1, 0,
   1532                                                0, 0, SK_Scalar1 },
   1533                                              kIdentity_Mask | kRectStaysRect_Mask};
   1534     SkASSERT(identity.asSkMatrix().isIdentity());
   1535     return identity.asSkMatrix();
   1536 }
   1537 
   1538 const SkMatrix& SkMatrix::InvalidMatrix() {
   1539     static_assert(offsetof(SkMatrix,fMat)      == offsetof(AggregateMatrix,matrix),   "fMat");
   1540     static_assert(offsetof(SkMatrix,fTypeMask) == offsetof(AggregateMatrix,typemask), "fTypeMask");
   1541 
   1542     static const AggregateMatrix invalid =
   1543         { {SK_ScalarMax, SK_ScalarMax, SK_ScalarMax,
   1544            SK_ScalarMax, SK_ScalarMax, SK_ScalarMax,
   1545            SK_ScalarMax, SK_ScalarMax, SK_ScalarMax },
   1546          kTranslate_Mask | kScale_Mask | kAffine_Mask | kPerspective_Mask };
   1547     return invalid.asSkMatrix();
   1548 }
   1549 
   1550 bool SkMatrix::decomposeScale(SkSize* scale, SkMatrix* remaining) const {
   1551     if (this->hasPerspective()) {
   1552         return false;
   1553     }
   1554 
   1555     const SkScalar sx = SkVector::Length(this->getScaleX(), this->getSkewY());
   1556     const SkScalar sy = SkVector::Length(this->getSkewX(), this->getScaleY());
   1557     if (!SkScalarIsFinite(sx) || !SkScalarIsFinite(sy) ||
   1558         SkScalarNearlyZero(sx) || SkScalarNearlyZero(sy)) {
   1559         return false;
   1560     }
   1561 
   1562     if (scale) {
   1563         scale->set(sx, sy);
   1564     }
   1565     if (remaining) {
   1566         *remaining = *this;
   1567         remaining->postScale(SkScalarInvert(sx), SkScalarInvert(sy));
   1568     }
   1569     return true;
   1570 }
   1571 
   1572 ///////////////////////////////////////////////////////////////////////////////
   1573 
   1574 size_t SkMatrix::writeToMemory(void* buffer) const {
   1575     // TODO write less for simple matrices
   1576     static const size_t sizeInMemory = 9 * sizeof(SkScalar);
   1577     if (buffer) {
   1578         memcpy(buffer, fMat, sizeInMemory);
   1579     }
   1580     return sizeInMemory;
   1581 }
   1582 
   1583 size_t SkMatrix::readFromMemory(const void* buffer, size_t length) {
   1584     static const size_t sizeInMemory = 9 * sizeof(SkScalar);
   1585     if (length < sizeInMemory) {
   1586         return 0;
   1587     }
   1588     if (buffer) {
   1589         memcpy(fMat, buffer, sizeInMemory);
   1590         this->setTypeMask(kUnknown_Mask);
   1591     }
   1592     return sizeInMemory;
   1593 }
   1594 
   1595 void SkMatrix::dump() const {
   1596     SkString str;
   1597     this->toString(&str);
   1598     SkDebugf("%s\n", str.c_str());
   1599 }
   1600 
   1601 void SkMatrix::toString(SkString* str) const {
   1602     str->appendf("[%8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f]",
   1603              fMat[0], fMat[1], fMat[2], fMat[3], fMat[4], fMat[5],
   1604              fMat[6], fMat[7], fMat[8]);
   1605 }
   1606 
   1607 ///////////////////////////////////////////////////////////////////////////////
   1608 
   1609 #include "SkMatrixUtils.h"
   1610 
   1611 bool SkTreatAsSprite(const SkMatrix& mat, const SkISize& size, const SkPaint& paint) {
   1612     // Our path aa is 2-bits, and our rect aa is 8, so we could use 8,
   1613     // but in practice 4 seems enough (still looks smooth) and allows
   1614     // more slightly fractional cases to fall into the fast (sprite) case.
   1615     static const unsigned kAntiAliasSubpixelBits = 4;
   1616 
   1617     const unsigned subpixelBits = paint.isAntiAlias() ? kAntiAliasSubpixelBits : 0;
   1618 
   1619     // quick reject on affine or perspective
   1620     if (mat.getType() & ~(SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask)) {
   1621         return false;
   1622     }
   1623 
   1624     // quick success check
   1625     if (!subpixelBits && !(mat.getType() & ~SkMatrix::kTranslate_Mask)) {
   1626         return true;
   1627     }
   1628 
   1629     // mapRect supports negative scales, so we eliminate those first
   1630     if (mat.getScaleX() < 0 || mat.getScaleY() < 0) {
   1631         return false;
   1632     }
   1633 
   1634     SkRect dst;
   1635     SkIRect isrc = SkIRect::MakeSize(size);
   1636 
   1637     {
   1638         SkRect src;
   1639         src.set(isrc);
   1640         mat.mapRect(&dst, src);
   1641     }
   1642 
   1643     // just apply the translate to isrc
   1644     isrc.offset(SkScalarRoundToInt(mat.getTranslateX()),
   1645                 SkScalarRoundToInt(mat.getTranslateY()));
   1646 
   1647     if (subpixelBits) {
   1648         isrc.fLeft = SkLeftShift(isrc.fLeft, subpixelBits);
   1649         isrc.fTop = SkLeftShift(isrc.fTop, subpixelBits);
   1650         isrc.fRight = SkLeftShift(isrc.fRight, subpixelBits);
   1651         isrc.fBottom = SkLeftShift(isrc.fBottom, subpixelBits);
   1652 
   1653         const float scale = 1 << subpixelBits;
   1654         dst.fLeft *= scale;
   1655         dst.fTop *= scale;
   1656         dst.fRight *= scale;
   1657         dst.fBottom *= scale;
   1658     }
   1659 
   1660     SkIRect idst;
   1661     dst.round(&idst);
   1662     return isrc == idst;
   1663 }
   1664 
   1665 // A square matrix M can be decomposed (via polar decomposition) into two matrices --
   1666 // an orthogonal matrix Q and a symmetric matrix S. In turn we can decompose S into U*W*U^T,
   1667 // where U is another orthogonal matrix and W is a scale matrix. These can be recombined
   1668 // to give M = (Q*U)*W*U^T, i.e., the product of two orthogonal matrices and a scale matrix.
   1669 //
   1670 // The one wrinkle is that traditionally Q may contain a reflection -- the
   1671 // calculation has been rejiggered to put that reflection into W.
   1672 bool SkDecomposeUpper2x2(const SkMatrix& matrix,
   1673                          SkPoint* rotation1,
   1674                          SkPoint* scale,
   1675                          SkPoint* rotation2) {
   1676 
   1677     SkScalar A = matrix[SkMatrix::kMScaleX];
   1678     SkScalar B = matrix[SkMatrix::kMSkewX];
   1679     SkScalar C = matrix[SkMatrix::kMSkewY];
   1680     SkScalar D = matrix[SkMatrix::kMScaleY];
   1681 
   1682     if (is_degenerate_2x2(A, B, C, D)) {
   1683         return false;
   1684     }
   1685 
   1686     double w1, w2;
   1687     SkScalar cos1, sin1;
   1688     SkScalar cos2, sin2;
   1689 
   1690     // do polar decomposition (M = Q*S)
   1691     SkScalar cosQ, sinQ;
   1692     double Sa, Sb, Sd;
   1693     // if M is already symmetric (i.e., M = I*S)
   1694     if (SkScalarNearlyEqual(B, C)) {
   1695         cosQ = 1;
   1696         sinQ = 0;
   1697 
   1698         Sa = A;
   1699         Sb = B;
   1700         Sd = D;
   1701     } else {
   1702         cosQ = A + D;
   1703         sinQ = C - B;
   1704         SkScalar reciplen = SkScalarInvert(SkScalarSqrt(cosQ*cosQ + sinQ*sinQ));
   1705         cosQ *= reciplen;
   1706         sinQ *= reciplen;
   1707 
   1708         // S = Q^-1*M
   1709         // we don't calc Sc since it's symmetric
   1710         Sa = A*cosQ + C*sinQ;
   1711         Sb = B*cosQ + D*sinQ;
   1712         Sd = -B*sinQ + D*cosQ;
   1713     }
   1714 
   1715     // Now we need to compute eigenvalues of S (our scale factors)
   1716     // and eigenvectors (bases for our rotation)
   1717     // From this, should be able to reconstruct S as U*W*U^T
   1718     if (SkScalarNearlyZero(SkDoubleToScalar(Sb))) {
   1719         // already diagonalized
   1720         cos1 = 1;
   1721         sin1 = 0;
   1722         w1 = Sa;
   1723         w2 = Sd;
   1724         cos2 = cosQ;
   1725         sin2 = sinQ;
   1726     } else {
   1727         double diff = Sa - Sd;
   1728         double discriminant = sqrt(diff*diff + 4.0*Sb*Sb);
   1729         double trace = Sa + Sd;
   1730         if (diff > 0) {
   1731             w1 = 0.5*(trace + discriminant);
   1732             w2 = 0.5*(trace - discriminant);
   1733         } else {
   1734             w1 = 0.5*(trace - discriminant);
   1735             w2 = 0.5*(trace + discriminant);
   1736         }
   1737 
   1738         cos1 = SkDoubleToScalar(Sb); sin1 = SkDoubleToScalar(w1 - Sa);
   1739         SkScalar reciplen = SkScalarInvert(SkScalarSqrt(cos1*cos1 + sin1*sin1));
   1740         cos1 *= reciplen;
   1741         sin1 *= reciplen;
   1742 
   1743         // rotation 2 is composition of Q and U
   1744         cos2 = cos1*cosQ - sin1*sinQ;
   1745         sin2 = sin1*cosQ + cos1*sinQ;
   1746 
   1747         // rotation 1 is U^T
   1748         sin1 = -sin1;
   1749     }
   1750 
   1751     if (scale) {
   1752         scale->fX = SkDoubleToScalar(w1);
   1753         scale->fY = SkDoubleToScalar(w2);
   1754     }
   1755     if (rotation1) {
   1756         rotation1->fX = cos1;
   1757         rotation1->fY = sin1;
   1758     }
   1759     if (rotation2) {
   1760         rotation2->fX = cos2;
   1761         rotation2->fY = sin2;
   1762     }
   1763 
   1764     return true;
   1765 }
   1766 
   1767 //////////////////////////////////////////////////////////////////////////////////////////////////
   1768 
   1769 void SkRSXform::toQuad(SkScalar width, SkScalar height, SkPoint quad[4]) const {
   1770 #if 0
   1771     // This is the slow way, but it documents what we're doing
   1772     quad[0].set(0, 0);
   1773     quad[1].set(width, 0);
   1774     quad[2].set(width, height);
   1775     quad[3].set(0, height);
   1776     SkMatrix m;
   1777     m.setRSXform(*this).mapPoints(quad, quad, 4);
   1778 #else
   1779     const SkScalar m00 = fSCos;
   1780     const SkScalar m01 = -fSSin;
   1781     const SkScalar m02 = fTx;
   1782     const SkScalar m10 = -m01;
   1783     const SkScalar m11 = m00;
   1784     const SkScalar m12 = fTy;
   1785 
   1786     quad[0].set(m02, m12);
   1787     quad[1].set(m00 * width + m02, m10 * width + m12);
   1788     quad[2].set(m00 * width + m01 * height + m02, m10 * width + m11 * height + m12);
   1789     quad[3].set(m01 * height + m02, m11 * height + m12);
   1790 #endif
   1791 }
   1792