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