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