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