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