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