SkMatrix.cpp revision 363e546ed626b6dbbc42f5db87b3594bc0b5944b
180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2006 The Android Open Source Project
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkMatrix.h"
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "Sk64.h"
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkFloatBits.h"
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkScalarCompare.h"
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkString.h"
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_SCALAR_IS_FLOAT
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define kMatrix22Elem   SK_Scalar1
1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static inline float SkDoubleToFloat(double x) {
2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return static_cast<float>(x);
2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define kMatrix22Elem   SK_Fract1
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*      [scale-x    skew-x      trans-x]   [X]   [X']
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        [skew-y     scale-y     trans-y] * [Y] = [Y']
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        [persp-0    persp-1     persp-2]   [1]   [1 ]
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru*/
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix::reset() {
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMScaleX] = fMat[kMScaleY] = SK_Scalar1;
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMSkewX]  = fMat[kMSkewY] =
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMTransX] = fMat[kMTransY] =
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMPersp0] = fMat[kMPersp1] = 0;
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMPersp2] = kMatrix22Elem;
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->setTypeMask(kIdentity_Mask | kRectStaysRect_Mask);
3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// this guy aligns with the masks, so we can compute a mask from a varaible 0/1
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruenum {
4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    kTranslate_Shift,
4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    kScale_Shift,
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    kAffine_Shift,
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    kPerspective_Shift,
4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    kRectStaysRect_Shift
4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_SCALAR_IS_FLOAT
5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static const int32_t kScalar1Int = 0x3f800000;
5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static const int32_t kPersp1Int  = 0x3f800000;
5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define scalarAsInt(x)  (x)
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static const int32_t kScalar1Int = (1 << 16);
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static const int32_t kPersp1Int  = (1 << 30);
5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruuint8_t SkMatrix::computePerspectiveTypeMask() const {
6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_SCALAR_SLOW_COMPARES
6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (SkScalarAs2sCompliment(fMat[kMPersp0]) |
6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkScalarAs2sCompliment(fMat[kMPersp1]) |
6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            (SkScalarAs2sCompliment(fMat[kMPersp2]) - kPersp1Int)) {
6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return SkToU8(kORableMasks);
6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Benchmarking suggests that replacing this set of SkScalarAs2sCompliment
6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // is a win, but replacing those below is not. We don't yet understand
6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // that result.
7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fMat[kMPersp0] != 0 || fMat[kMPersp1] != 0 ||
7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMat[kMPersp2] != kMatrix22Elem) {
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // If this is a perspective transform, we return true for all other
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // transform flags - this does not disable any optimizations, respects
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // the rule that the type mask must be conservative, and speeds up
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // type mask computation.
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return SkToU8(kORableMasks);
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkToU8(kOnlyPerspectiveValid_Mask | kUnknown_Mask);
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruuint8_t SkMatrix::computeTypeMask() const {
8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    unsigned mask = 0;
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_SCALAR_SLOW_COMPARES
8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (SkScalarAs2sCompliment(fMat[kMPersp0]) |
8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkScalarAs2sCompliment(fMat[kMPersp1]) |
8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            (SkScalarAs2sCompliment(fMat[kMPersp2]) - kPersp1Int)) {
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return SkToU8(kORableMasks);
9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (SkScalarAs2sCompliment(fMat[kMTransX]) |
9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkScalarAs2sCompliment(fMat[kMTransY])) {
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        mask |= kTranslate_Mask;
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fMat[kMPersp0] != 0 || fMat[kMPersp1] != 0 ||
9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMat[kMPersp2] != kMatrix22Elem) {
10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // Once it is determined that that this is a perspective transform,
10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // all other flags are moot as far as optimizations are concerned.
10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return SkToU8(kORableMasks);
10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fMat[kMTransX] != 0 || fMat[kMTransY] != 0) {
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        mask |= kTranslate_Mask;
10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int m00 = SkScalarAs2sCompliment(fMat[SkMatrix::kMScaleX]);
11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int m01 = SkScalarAs2sCompliment(fMat[SkMatrix::kMSkewX]);
11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int m10 = SkScalarAs2sCompliment(fMat[SkMatrix::kMSkewY]);
11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int m11 = SkScalarAs2sCompliment(fMat[SkMatrix::kMScaleY]);
11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (m01 | m10) {
11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // The skew components may be scale-inducing, unless we are dealing
11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // with a pure rotation.  Testing for a pure rotation is expensive,
11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // so we opt for being conservative by always setting the scale bit.
11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // along with affine.
12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // By doing this, we are also ensuring that matrices have the same
12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // type masks as their inverses.
12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        mask |= kAffine_Mask | kScale_Mask;
12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // For rectStaysRect, in the affine case, we only need check that
12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // the primary diagonal is all zeros and that the secondary diagonal
12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // is all non-zero.
12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // map non-zero to 1
12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        m01 = m01 != 0;
13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        m10 = m10 != 0;
13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int dp0 = 0 == (m00 | m11) ;  // true if both are 0
13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int ds1 = m01 & m10;        // true if both are 1
13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        mask |= (dp0 & ds1) << kRectStaysRect_Shift;
13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // Only test for scale explicitly if not affine, since affine sets the
13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // scale bit.
13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if ((m00 - kScalar1Int) | (m11 - kScalar1Int)) {
14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            mask |= kScale_Mask;
14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // Not affine, therefore we already know secondary diagonal is
14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // all zeros, so we just need to check that primary diagonal is
14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // all non-zero.
14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // map non-zero to 1
14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        m00 = m00 != 0;
14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        m11 = m11 != 0;
15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // record if the (p)rimary diagonal is all non-zero
15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        mask |= (m00 & m11) << kRectStaysRect_Shift;
15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
15480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkToU8(mask);
15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_SCALAR_IS_FLOAT
16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool operator==(const SkMatrix& a, const SkMatrix& b) {
16380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const SkScalar* SK_RESTRICT ma = a.fMat;
16480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const SkScalar* SK_RESTRICT mb = b.fMat;
16580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return  ma[0] == mb[0] && ma[1] == mb[1] && ma[2] == mb[2] &&
16780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            ma[3] == mb[3] && ma[4] == mb[4] && ma[5] == mb[5] &&
16880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            ma[6] == mb[6] && ma[7] == mb[7] && ma[8] == mb[8];
16980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
17080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
17180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
17280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
17380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
17480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
17580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix::setTranslate(SkScalar dx, SkScalar dy) {
17680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (SkScalarToCompareType(dx) || SkScalarToCompareType(dy)) {
17780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMat[kMTransX] = dx;
17880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMat[kMTransY] = dy;
17980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
18080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMat[kMScaleX] = fMat[kMScaleY] = SK_Scalar1;
18180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMat[kMSkewX]  = fMat[kMSkewY] =
18280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMat[kMPersp0] = fMat[kMPersp1] = 0;
18380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMat[kMPersp2] = kMatrix22Elem;
18480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
18580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->setTypeMask(kTranslate_Mask | kRectStaysRect_Mask);
18680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
18780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->reset();
18880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
18980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
19080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
19180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkMatrix::preTranslate(SkScalar dx, SkScalar dy) {
19280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (this->hasPerspective()) {
19380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkMatrix    m;
19480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        m.setTranslate(dx, dy);
19580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return this->preConcat(m);
19680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
19780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
19880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (SkScalarToCompareType(dx) || SkScalarToCompareType(dy)) {
19980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMat[kMTransX] += SkScalarMul(fMat[kMScaleX], dx) +
20080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                          SkScalarMul(fMat[kMSkewX], dy);
20180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMat[kMTransY] += SkScalarMul(fMat[kMSkewY], dx) +
20280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                          SkScalarMul(fMat[kMScaleY], dy);
20380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
20480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
20580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
20680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
20780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
20880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
20980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkMatrix::postTranslate(SkScalar dx, SkScalar dy) {
21080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (this->hasPerspective()) {
21180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkMatrix    m;
21280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        m.setTranslate(dx, dy);
21380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return this->postConcat(m);
21480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
21580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
21680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (SkScalarToCompareType(dx) || SkScalarToCompareType(dy)) {
21780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMat[kMTransX] += dx;
21880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMat[kMTransY] += dy;
21980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
22080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
22180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
22280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
22380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
22480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
22580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
22680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix::setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
22780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (SK_Scalar1 == sx && SK_Scalar1 == sy) {
22880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->reset();
22980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
23080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMat[kMScaleX] = sx;
23180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMat[kMScaleY] = sy;
23280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMat[kMTransX] = px - SkScalarMul(sx, px);
23380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMat[kMTransY] = py - SkScalarMul(sy, py);
23480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMat[kMPersp2] = kMatrix22Elem;
23580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
23680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMat[kMSkewX]  = fMat[kMSkewY] =
23780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMat[kMPersp0] = fMat[kMPersp1] = 0;
23880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
23980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->setTypeMask(kScale_Mask | kTranslate_Mask | kRectStaysRect_Mask);
24080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
24180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
24280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
24380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix::setScale(SkScalar sx, SkScalar sy) {
24480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (SK_Scalar1 == sx && SK_Scalar1 == sy) {
24580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->reset();
24680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
24780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMat[kMScaleX] = sx;
24880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMat[kMScaleY] = sy;
24980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMat[kMPersp2] = kMatrix22Elem;
25080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
25180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMat[kMTransX] = fMat[kMTransY] =
25280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMat[kMSkewX]  = fMat[kMSkewY] =
25380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMat[kMPersp0] = fMat[kMPersp1] = 0;
25480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
25580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->setTypeMask(kScale_Mask | kRectStaysRect_Mask);
25680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
25780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
25880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
25980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkMatrix::setIDiv(int divx, int divy) {
26080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!divx || !divy) {
26180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
26280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
26380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->setScale(SK_Scalar1 / divx, SK_Scalar1 / divy);
26480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
26580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
26680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
26780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkMatrix::preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
26880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkMatrix    m;
26980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    m.setScale(sx, sy, px, py);
27080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return this->preConcat(m);
27180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
27280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
27380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkMatrix::preScale(SkScalar sx, SkScalar sy) {
27480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (SK_Scalar1 == sx && SK_Scalar1 == sy) {
27580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
27680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
27780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
27880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_SCALAR_IS_FIXED
27980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkMatrix    m;
28080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    m.setScale(sx, sy);
28180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return this->preConcat(m);
28280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
28380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // the assumption is that these multiplies are very cheap, and that
28480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // a full concat and/or just computing the matrix type is more expensive.
28580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Also, the fixed-point case checks for overflow, but the float doesn't,
28680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // so we can get away with these blind multiplies.
28780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
28880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMScaleX] = SkScalarMul(fMat[kMScaleX], sx);
28980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMSkewY] = SkScalarMul(fMat[kMSkewY],   sx);
29080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMPersp0] = SkScalarMul(fMat[kMPersp0], sx);
29180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
29280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMSkewX] = SkScalarMul(fMat[kMSkewX],   sy);
29380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMScaleY] = SkScalarMul(fMat[kMScaleY], sy);
29480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMPersp1] = SkScalarMul(fMat[kMPersp1], sy);
29580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
29680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->orTypeMask(kScale_Mask);
29780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
29880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
29980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
30080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
30180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkMatrix::postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
30280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (SK_Scalar1 == sx && SK_Scalar1 == sy) {
30380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
30480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
30580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkMatrix    m;
30680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    m.setScale(sx, sy, px, py);
30780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return this->postConcat(m);
30880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
30980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
31080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkMatrix::postScale(SkScalar sx, SkScalar sy) {
31180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (SK_Scalar1 == sx && SK_Scalar1 == sy) {
31280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
31380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
31480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkMatrix    m;
31580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    m.setScale(sx, sy);
31680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return this->postConcat(m);
31780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
31880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
31980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_SCALAR_IS_FIXED
32080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static inline SkFixed roundidiv(SkFixed numer, int denom) {
32180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int ns = numer >> 31;
32280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int ds = denom >> 31;
32380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        numer = (numer ^ ns) - ns;
32480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        denom = (denom ^ ds) - ds;
32580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
32680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkFixed answer = (numer + (denom >> 1)) / denom;
32780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int as = ns ^ ds;
32880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return (answer ^ as) - as;
32980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
33080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
33180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
33280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// this guy perhaps can go away, if we have a fract/high-precision way to
33380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// scale matrices
33480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkMatrix::postIDiv(int divx, int divy) {
33580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (divx == 0 || divy == 0) {
33680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
33780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
33880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
33980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_SCALAR_IS_FIXED
34080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMScaleX] = roundidiv(fMat[kMScaleX], divx);
34180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMSkewX]  = roundidiv(fMat[kMSkewX],  divx);
34280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMTransX] = roundidiv(fMat[kMTransX], divx);
34380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
34480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMScaleY] = roundidiv(fMat[kMScaleY], divy);
34580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMSkewY]  = roundidiv(fMat[kMSkewY],  divy);
34680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMTransY] = roundidiv(fMat[kMTransY], divy);
34780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
34880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const float invX = 1.f / divx;
34980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const float invY = 1.f / divy;
35080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
35180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMScaleX] *= invX;
35280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMSkewX]  *= invX;
35380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMTransX] *= invX;
35480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
35580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMScaleY] *= invY;
35680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMSkewY]  *= invY;
35780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMTransY] *= invY;
35880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
35980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
36080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->setTypeMask(kUnknown_Mask);
36180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
36280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
36380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
36480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru////////////////////////////////////////////////////////////////////////////////////
36580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
36680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix::setSinCos(SkScalar sinV, SkScalar cosV,
36780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                         SkScalar px, SkScalar py) {
36880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const SkScalar oneMinusCosV = SK_Scalar1 - cosV;
36980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
37080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMScaleX]  = cosV;
37180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMSkewX]   = -sinV;
37280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMTransX]  = SkScalarMul(sinV, py) + SkScalarMul(oneMinusCosV, px);
37380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
37480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMSkewY]   = sinV;
37580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMScaleY]  = cosV;
37680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMTransY]  = SkScalarMul(-sinV, px) + SkScalarMul(oneMinusCosV, py);
37780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
37880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMPersp0] = fMat[kMPersp1] = 0;
37980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMPersp2] = kMatrix22Elem;
38080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
38180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
38280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
38380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
38480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix::setSinCos(SkScalar sinV, SkScalar cosV) {
38580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMScaleX]  = cosV;
38680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMSkewX]   = -sinV;
38780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMTransX]  = 0;
38880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
38980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMSkewY]   = sinV;
39080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMScaleY]  = cosV;
39180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMTransY]  = 0;
39280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
39380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMPersp0] = fMat[kMPersp1] = 0;
39480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMPersp2] = kMatrix22Elem;
39580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
39680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
39780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
39880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
39980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix::setRotate(SkScalar degrees, SkScalar px, SkScalar py) {
40080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScalar sinV, cosV;
40180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    sinV = SkScalarSinCos(SkDegreesToRadians(degrees), &cosV);
40280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->setSinCos(sinV, cosV, px, py);
40380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
40480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
40580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix::setRotate(SkScalar degrees) {
40680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScalar sinV, cosV;
40780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    sinV = SkScalarSinCos(SkDegreesToRadians(degrees), &cosV);
40880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->setSinCos(sinV, cosV);
40980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
41080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
41180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkMatrix::preRotate(SkScalar degrees, SkScalar px, SkScalar py) {
41280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkMatrix    m;
41380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    m.setRotate(degrees, px, py);
41480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return this->preConcat(m);
41580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
41680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
41780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkMatrix::preRotate(SkScalar degrees) {
41880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkMatrix    m;
41980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    m.setRotate(degrees);
42080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return this->preConcat(m);
42180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
42280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
42380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkMatrix::postRotate(SkScalar degrees, SkScalar px, SkScalar py) {
42480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkMatrix    m;
42580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    m.setRotate(degrees, px, py);
42680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return this->postConcat(m);
42780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
42880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
42980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkMatrix::postRotate(SkScalar degrees) {
43080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkMatrix    m;
43180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    m.setRotate(degrees);
43280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return this->postConcat(m);
43380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
43480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
43580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru////////////////////////////////////////////////////////////////////////////////////
43680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
43780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix::setSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
43880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMScaleX]  = SK_Scalar1;
43980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMSkewX]   = sx;
44080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMTransX]  = SkScalarMul(-sx, py);
44180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
44280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMSkewY]   = sy;
44380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMScaleY]  = SK_Scalar1;
44480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMTransY]  = SkScalarMul(-sy, px);
44580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
44680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMPersp0] = fMat[kMPersp1] = 0;
44780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMPersp2] = kMatrix22Elem;
44880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
44980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
45080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
45180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
45280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix::setSkew(SkScalar sx, SkScalar sy) {
45380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMScaleX]  = SK_Scalar1;
45480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMSkewX]   = sx;
45580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMTransX]  = 0;
45680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
45780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMSkewY]   = sy;
45880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMScaleY]  = SK_Scalar1;
45980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMTransY]  = 0;
46080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
46180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMPersp0] = fMat[kMPersp1] = 0;
46280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMPersp2] = kMatrix22Elem;
46380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
46480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
46580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
46680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
46780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkMatrix::preSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
46880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkMatrix    m;
46980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    m.setSkew(sx, sy, px, py);
47080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return this->preConcat(m);
47180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
47280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
47380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkMatrix::preSkew(SkScalar sx, SkScalar sy) {
47480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkMatrix    m;
47580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    m.setSkew(sx, sy);
47680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return this->preConcat(m);
47780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
47880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
47980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkMatrix::postSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
48080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkMatrix    m;
48180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    m.setSkew(sx, sy, px, py);
48280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return this->postConcat(m);
48380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
48480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
48580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkMatrix::postSkew(SkScalar sx, SkScalar sy) {
48680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkMatrix    m;
48780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    m.setSkew(sx, sy);
48880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return this->postConcat(m);
48980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
49080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
49180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
49280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
49380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkMatrix::setRectToRect(const SkRect& src, const SkRect& dst,
49480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             ScaleToFit align)
49580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
49680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (src.isEmpty()) {
49780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->reset();
49880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
49980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
50080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
50180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (dst.isEmpty()) {
50280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        sk_bzero(fMat, 8 * sizeof(SkScalar));
50380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->setTypeMask(kScale_Mask | kRectStaysRect_Mask);
50480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
50580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalar    tx, sx = SkScalarDiv(dst.width(), src.width());
50680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalar    ty, sy = SkScalarDiv(dst.height(), src.height());
50780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        bool        xLarger = false;
50880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
50980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (align != kFill_ScaleToFit) {
51080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (sx > sy) {
51180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                xLarger = true;
51280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                sx = sy;
51380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } else {
51480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                sy = sx;
51580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
51680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
51780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
51880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        tx = dst.fLeft - SkScalarMul(src.fLeft, sx);
51980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        ty = dst.fTop - SkScalarMul(src.fTop, sy);
52080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (align == kCenter_ScaleToFit || align == kEnd_ScaleToFit) {
52180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkScalar diff;
52280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
52380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (xLarger) {
52480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                diff = dst.width() - SkScalarMul(src.width(), sy);
52580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } else {
52680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                diff = dst.height() - SkScalarMul(src.height(), sy);
52780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
52880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
52980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (align == kCenter_ScaleToFit) {
53080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                diff = SkScalarHalf(diff);
53180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
53280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
53380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (xLarger) {
53480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                tx += diff;
53580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } else {
53680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                ty += diff;
53780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
53880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
53980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
54080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMat[kMScaleX] = sx;
54180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMat[kMScaleY] = sy;
54280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMat[kMTransX] = tx;
54380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMat[kMTransY] = ty;
54480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMat[kMSkewX]  = fMat[kMSkewY] =
54580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMat[kMPersp0] = fMat[kMPersp1] = 0;
54680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
54780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        unsigned mask = kRectStaysRect_Mask;
54880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (sx != SK_Scalar1 || sy != SK_Scalar1) {
54980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            mask |= kScale_Mask;
55080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
55180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (tx || ty) {
55280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            mask |= kTranslate_Mask;
55380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
55480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->setTypeMask(mask);
55580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
55680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // shared cleanup
55780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[kMPersp2] = kMatrix22Elem;
55880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
55980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
56080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
56180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
56280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
56380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_SCALAR_IS_FLOAT
56480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static inline int fixmuladdmul(float a, float b, float c, float d,
56580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                   float* result) {
56680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *result = SkDoubleToFloat((double)a * b + (double)c * d);
56780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
56880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
56980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
57080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static inline bool rowcol3(const float row[], const float col[],
57180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                               float* result) {
57280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *result = row[0] * col[0] + row[1] * col[3] + row[2] * col[6];
57380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
57480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
57580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
57680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static inline int negifaddoverflows(float& result, float a, float b) {
57780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        result = a + b;
57880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return 0;
57980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
58080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
58180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static inline bool fixmuladdmul(SkFixed a, SkFixed b, SkFixed c, SkFixed d,
58280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                    SkFixed* result) {
58380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        Sk64    tmp1, tmp2;
58480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        tmp1.setMul(a, b);
58580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        tmp2.setMul(c, d);
58680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        tmp1.add(tmp2);
58780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (tmp1.isFixed()) {
58880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *result = tmp1.getFixed();
58980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return true;
59080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
59180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
59280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
59380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
59480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static inline SkFixed fracmuladdmul(SkFixed a, SkFract b, SkFixed c,
59580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                        SkFract d) {
59680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        Sk64 tmp1, tmp2;
59780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        tmp1.setMul(a, b);
59880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        tmp2.setMul(c, d);
59980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        tmp1.add(tmp2);
60080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return tmp1.getFract();
60180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
60280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
60380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static inline bool rowcol3(const SkFixed row[], const SkFixed col[],
60480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                               SkFixed* result) {
60580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        Sk64 tmp1, tmp2;
60680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
60780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        tmp1.setMul(row[0], col[0]);    // N * fixed
60880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        tmp2.setMul(row[1], col[3]);    // N * fixed
60980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        tmp1.add(tmp2);
61080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
61180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        tmp2.setMul(row[2], col[6]);    // N * fract
61280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        tmp2.roundRight(14);            // make it fixed
61380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        tmp1.add(tmp2);
61480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
61580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (tmp1.isFixed()) {
61680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *result = tmp1.getFixed();
61780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return true;
61880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
61980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
62080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
62180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
62280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static inline int negifaddoverflows(SkFixed& result, SkFixed a, SkFixed b) {
62380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkFixed c = a + b;
62480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        result = c;
62580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return (c ^ a) & (c ^ b);
62680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
62780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
62880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
62980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void normalize_perspective(SkScalar mat[9]) {
63080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (SkScalarAbs(mat[SkMatrix::kMPersp2]) > kMatrix22Elem) {
63180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for (int i = 0; i < 9; i++)
63280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            mat[i] = SkScalarHalf(mat[i]);
63380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
63480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
63580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
63680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkMatrix::setConcat(const SkMatrix& a, const SkMatrix& b) {
63780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    TypeMask aType = a.getPerspectiveTypeMaskOnly();
63880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    TypeMask bType = b.getPerspectiveTypeMaskOnly();
63980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
64080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (a.isTriviallyIdentity()) {
64180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *this = b;
64280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else if (b.isTriviallyIdentity()) {
64380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *this = a;
64480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
64580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkMatrix tmp;
64680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
64780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if ((aType | bType) & kPerspective_Mask) {
64880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (!rowcol3(&a.fMat[0], &b.fMat[0], &tmp.fMat[kMScaleX])) {
64980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
65080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
65180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (!rowcol3(&a.fMat[0], &b.fMat[1], &tmp.fMat[kMSkewX])) {
65280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
65380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
65480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (!rowcol3(&a.fMat[0], &b.fMat[2], &tmp.fMat[kMTransX])) {
65580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
65680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
65780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
65880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (!rowcol3(&a.fMat[3], &b.fMat[0], &tmp.fMat[kMSkewY])) {
65980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
66080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
66180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (!rowcol3(&a.fMat[3], &b.fMat[1], &tmp.fMat[kMScaleY])) {
66280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
66380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
66480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (!rowcol3(&a.fMat[3], &b.fMat[2], &tmp.fMat[kMTransY])) {
66580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
66680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
66780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
66880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (!rowcol3(&a.fMat[6], &b.fMat[0], &tmp.fMat[kMPersp0])) {
66980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
67080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
67180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (!rowcol3(&a.fMat[6], &b.fMat[1], &tmp.fMat[kMPersp1])) {
67280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
67380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
67480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (!rowcol3(&a.fMat[6], &b.fMat[2], &tmp.fMat[kMPersp2])) {
67580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
67680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
67780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
67880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            normalize_perspective(tmp.fMat);
67980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            tmp.setTypeMask(kUnknown_Mask);
68080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {    // not perspective
68180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (!fixmuladdmul(a.fMat[kMScaleX], b.fMat[kMScaleX],
68280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    a.fMat[kMSkewX], b.fMat[kMSkewY], &tmp.fMat[kMScaleX])) {
68380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
68480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
68580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (!fixmuladdmul(a.fMat[kMScaleX], b.fMat[kMSkewX],
68680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                      a.fMat[kMSkewX], b.fMat[kMScaleY], &tmp.fMat[kMSkewX])) {
68780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
68880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
68980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (!fixmuladdmul(a.fMat[kMScaleX], b.fMat[kMTransX],
69080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                      a.fMat[kMSkewX], b.fMat[kMTransY], &tmp.fMat[kMTransX])) {
69180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
69280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
69380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (negifaddoverflows(tmp.fMat[kMTransX], tmp.fMat[kMTransX],
69480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                  a.fMat[kMTransX]) < 0) {
69580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
69680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
69780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
69880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (!fixmuladdmul(a.fMat[kMSkewY], b.fMat[kMScaleX],
69980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                      a.fMat[kMScaleY], b.fMat[kMSkewY], &tmp.fMat[kMSkewY])) {
70080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
70180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
70280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (!fixmuladdmul(a.fMat[kMSkewY], b.fMat[kMSkewX],
70380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    a.fMat[kMScaleY], b.fMat[kMScaleY], &tmp.fMat[kMScaleY])) {
70480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
70580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
70680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (!fixmuladdmul(a.fMat[kMSkewY], b.fMat[kMTransX],
70780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                     a.fMat[kMScaleY], b.fMat[kMTransY], &tmp.fMat[kMTransY])) {
70880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
70980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
71080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (negifaddoverflows(tmp.fMat[kMTransY], tmp.fMat[kMTransY],
71180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                  a.fMat[kMTransY]) < 0) {
71280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
71380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
71480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
71580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            tmp.fMat[kMPersp0] = tmp.fMat[kMPersp1] = 0;
71680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            tmp.fMat[kMPersp2] = kMatrix22Elem;
71780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            //SkDebugf("Concat mat non-persp type: %d\n", tmp.getType());
71880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            //SkASSERT(!(tmp.getType() & kPerspective_Mask));
71980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            tmp.setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
72080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
72180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *this = tmp;
72280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
72380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
72480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
72580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
72680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkMatrix::preConcat(const SkMatrix& mat) {
72780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // check for identity first, so we don't do a needless copy of ourselves
72880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // to ourselves inside setConcat()
72980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return mat.isIdentity() || this->setConcat(*this, mat);
73080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
73180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
73280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkMatrix::postConcat(const SkMatrix& mat) {
73380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // check for identity first, so we don't do a needless copy of ourselves
73480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // to ourselves inside setConcat()
73580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return mat.isIdentity() || this->setConcat(mat, *this);
73680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
73780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
73880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
73980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
74080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*  Matrix inversion is very expensive, but also the place where keeping
74180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    precision may be most important (here and matrix concat). Hence to avoid
74280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bitmap blitting artifacts when walking the inverse, we use doubles for
74380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    the intermediate math, even though we know that is more expensive.
74480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    The fixed counter part is us using Sk64 for temp calculations.
74580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
74680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
74780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_SCALAR_IS_FLOAT
74880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    typedef double SkDetScalar;
74980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define SkPerspMul(a, b)            SkScalarMul(a, b)
75080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define SkScalarMulShift(a, b, s)   SkDoubleToFloat((a) * (b))
75180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static double sk_inv_determinant(const float mat[9], int isPerspective,
75280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                    int* /* (only used in Fixed case) */) {
75380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        double det;
75480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
75580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (isPerspective) {
75680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            det =   mat[SkMatrix::kMScaleX] * ((double)mat[SkMatrix::kMScaleY] * mat[SkMatrix::kMPersp2] - (double)mat[SkMatrix::kMTransY] * mat[SkMatrix::kMPersp1]) +
75780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    mat[SkMatrix::kMSkewX] * ((double)mat[SkMatrix::kMTransY] * mat[SkMatrix::kMPersp0] - (double)mat[SkMatrix::kMSkewY] * mat[SkMatrix::kMPersp2]) +
75880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    mat[SkMatrix::kMTransX] * ((double)mat[SkMatrix::kMSkewY] * mat[SkMatrix::kMPersp1] - (double)mat[SkMatrix::kMScaleY] * mat[SkMatrix::kMPersp0]);
75980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
76080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            det =   (double)mat[SkMatrix::kMScaleX] * mat[SkMatrix::kMScaleY] - (double)mat[SkMatrix::kMSkewX] * mat[SkMatrix::kMSkewY];
76180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
76280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
76380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // Since the determinant is on the order of the cube of the matrix members,
76480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // compare to the cube of the default nearly-zero constant (although an
76580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // estimate of the condition number would be better if it wasn't so expensive).
76680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (SkScalarNearlyZero((float)det, SK_ScalarNearlyZero * SK_ScalarNearlyZero * SK_ScalarNearlyZero)) {
76780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return 0;
76880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
76980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return 1.0 / det;
77080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
77180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // we declar a,b,c,d to all be doubles, because we want to perform
77280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // double-precision muls and subtract, even though the original values are
77380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // from the matrix, which are floats.
77480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static float inline mul_diff_scale(double a, double b, double c, double d,
77580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                       double scale) {
77680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return SkDoubleToFloat((a * b - c * d) * scale);
77780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
77880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
77980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    typedef SkFixed SkDetScalar;
78080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define SkPerspMul(a, b)            SkFractMul(a, b)
78180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define SkScalarMulShift(a, b, s)   SkMulShift(a, b, s)
78280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static void set_muladdmul(Sk64* dst, int32_t a, int32_t b, int32_t c,
78380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                              int32_t d) {
78480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        Sk64 tmp;
78580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dst->setMul(a, b);
78680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        tmp.setMul(c, d);
78780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dst->add(tmp);
78880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
78980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
79080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static SkFixed sk_inv_determinant(const SkFixed mat[9], int isPerspective,
79180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                      int* shift) {
79280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        Sk64    tmp1, tmp2;
79380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
79480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (isPerspective) {
79580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            tmp1.setMul(mat[SkMatrix::kMScaleX], fracmuladdmul(mat[SkMatrix::kMScaleY], mat[SkMatrix::kMPersp2], -mat[SkMatrix::kMTransY], mat[SkMatrix::kMPersp1]));
79680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            tmp2.setMul(mat[SkMatrix::kMSkewX], fracmuladdmul(mat[SkMatrix::kMTransY], mat[SkMatrix::kMPersp0], -mat[SkMatrix::kMSkewY], mat[SkMatrix::kMPersp2]));
79780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            tmp1.add(tmp2);
79880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            tmp2.setMul(mat[SkMatrix::kMTransX], fracmuladdmul(mat[SkMatrix::kMSkewY], mat[SkMatrix::kMPersp1], -mat[SkMatrix::kMScaleY], mat[SkMatrix::kMPersp0]));
79980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            tmp1.add(tmp2);
80080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
80180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            tmp1.setMul(mat[SkMatrix::kMScaleX], mat[SkMatrix::kMScaleY]);
80280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            tmp2.setMul(mat[SkMatrix::kMSkewX], mat[SkMatrix::kMSkewY]);
80380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            tmp1.sub(tmp2);
80480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
80580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
80680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int s = tmp1.getClzAbs();
80780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *shift = s;
80880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
80980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkFixed denom;
81080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (s <= 32) {
81180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            denom = tmp1.getShiftRight(33 - s);
81280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
81380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            denom = (int32_t)tmp1.fLo << (s - 33);
81480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
81580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
81680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (denom == 0) {
81780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return 0;
81880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
81980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        /** This could perhaps be a special fractdiv function, since both of its
82080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            arguments are known to have bit 31 clear and bit 30 set (when they
82180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            are made positive), thus eliminating the need for calling clz()
82280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        */
82380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return SkFractDiv(SK_Fract1, denom);
82480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
82580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
82680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
82780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix::SetAffineIdentity(SkScalar affine[6]) {
82880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    affine[kAScaleX] = SK_Scalar1;
82980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    affine[kASkewY] = 0;
83080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    affine[kASkewX] = 0;
83180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    affine[kAScaleY] = SK_Scalar1;
83280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    affine[kATransX] = 0;
83380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    affine[kATransY] = 0;
83480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
83580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
83680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkMatrix::asAffine(SkScalar affine[6]) const {
83780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (this->hasPerspective()) {
83880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
83980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
84080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (affine) {
84180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        affine[kAScaleX] = this->fMat[kMScaleX];
84280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        affine[kASkewY] = this->fMat[kMSkewY];
84380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        affine[kASkewX] = this->fMat[kMSkewX];
84480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        affine[kAScaleY] = this->fMat[kMScaleY];
84580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        affine[kATransX] = this->fMat[kMTransX];
84680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        affine[kATransY] = this->fMat[kMTransY];
84780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
84880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
84980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
85080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
851363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerbool SkMatrix::invertNonIdentity(SkMatrix* inv) const {
852363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkASSERT(!this->isIdentity());
85380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int         isPersp = this->hasPerspective();
85480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int         shift;
85580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDetScalar scale = sk_inv_determinant(fMat, isPersp, &shift);
85680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
85780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (scale == 0) { // underflow
85880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
85980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
86080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
86180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (inv) {
86280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkMatrix tmp;
86380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (inv == this) {
86480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            inv = &tmp;
86580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
86680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
86780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (isPersp) {
86880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            shift = 61 - shift;
86980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            inv->fMat[kMScaleX] = SkScalarMulShift(SkPerspMul(fMat[kMScaleY], fMat[kMPersp2]) - SkPerspMul(fMat[kMTransY], fMat[kMPersp1]), scale, shift);
87080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            inv->fMat[kMSkewX]  = SkScalarMulShift(SkPerspMul(fMat[kMTransX], fMat[kMPersp1]) - SkPerspMul(fMat[kMSkewX],  fMat[kMPersp2]), scale, shift);
87180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            inv->fMat[kMTransX] = SkScalarMulShift(SkScalarMul(fMat[kMSkewX], fMat[kMTransY]) - SkScalarMul(fMat[kMTransX], fMat[kMScaleY]), scale, shift);
87280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
87380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            inv->fMat[kMSkewY]  = SkScalarMulShift(SkPerspMul(fMat[kMTransY], fMat[kMPersp0]) - SkPerspMul(fMat[kMSkewY],   fMat[kMPersp2]), scale, shift);
87480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            inv->fMat[kMScaleY] = SkScalarMulShift(SkPerspMul(fMat[kMScaleX], fMat[kMPersp2]) - SkPerspMul(fMat[kMTransX],  fMat[kMPersp0]), scale, shift);
87580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            inv->fMat[kMTransY] = SkScalarMulShift(SkScalarMul(fMat[kMTransX], fMat[kMSkewY]) - SkScalarMul(fMat[kMScaleX], fMat[kMTransY]), scale, shift);
87680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
87780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            inv->fMat[kMPersp0] = SkScalarMulShift(SkScalarMul(fMat[kMSkewY], fMat[kMPersp1]) - SkScalarMul(fMat[kMScaleY], fMat[kMPersp0]), scale, shift);
87880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            inv->fMat[kMPersp1] = SkScalarMulShift(SkScalarMul(fMat[kMSkewX], fMat[kMPersp0]) - SkScalarMul(fMat[kMScaleX], fMat[kMPersp1]), scale, shift);
87980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            inv->fMat[kMPersp2] = SkScalarMulShift(SkScalarMul(fMat[kMScaleX], fMat[kMScaleY]) - SkScalarMul(fMat[kMSkewX], fMat[kMSkewY]), scale, shift);
88080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_SCALAR_IS_FIXED
88180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (SkAbs32(inv->fMat[kMPersp2]) > SK_Fixed1) {
88280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                Sk64    tmp;
88380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
88480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                tmp.set(SK_Fract1);
88580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                tmp.shiftLeft(16);
88680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                tmp.div(inv->fMat[kMPersp2], Sk64::kRound_DivOption);
88780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
88880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkFract scale = tmp.get32();
88980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
89080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                for (int i = 0; i < 9; i++) {
89180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    inv->fMat[i] = SkFractMul(inv->fMat[i], scale);
89280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
89380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
89480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            inv->fMat[kMPersp2] = SkFixedToFract(inv->fMat[kMPersp2]);
89580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
89680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {   // not perspective
89780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_SCALAR_IS_FIXED
89880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            Sk64    tx, ty;
89980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            int     clzNumer;
90080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
90180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // check the 2x2 for overflow
90280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            {
90380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                int32_t value = SkAbs32(fMat[kMScaleY]);
90480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                value |= SkAbs32(fMat[kMSkewX]);
90580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                value |= SkAbs32(fMat[kMScaleX]);
90680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                value |= SkAbs32(fMat[kMSkewY]);
90780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                clzNumer = SkCLZ(value);
90880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (shift - clzNumer > 31)
90980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    return false;   // overflow
91080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
91180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
91280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            set_muladdmul(&tx, fMat[kMSkewX], fMat[kMTransY], -fMat[kMScaleY], fMat[kMTransX]);
91380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            set_muladdmul(&ty, fMat[kMSkewY], fMat[kMTransX], -fMat[kMScaleX], fMat[kMTransY]);
91480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // check tx,ty for overflow
91580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            clzNumer = SkCLZ(SkAbs32(tx.fHi) | SkAbs32(ty.fHi));
91680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (shift - clzNumer > 14) {
91780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;   // overflow
91880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
91980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
92080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            int fixedShift = 61 - shift;
92180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            int sk64shift = 44 - shift + clzNumer;
92280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
92380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            inv->fMat[kMScaleX] = SkMulShift(fMat[kMScaleY], scale, fixedShift);
92480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            inv->fMat[kMSkewX]  = SkMulShift(-fMat[kMSkewX], scale, fixedShift);
92580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            inv->fMat[kMTransX] = SkMulShift(tx.getShiftRight(33 - clzNumer), scale, sk64shift);
92680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
92780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            inv->fMat[kMSkewY]  = SkMulShift(-fMat[kMSkewY], scale, fixedShift);
92880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            inv->fMat[kMScaleY] = SkMulShift(fMat[kMScaleX], scale, fixedShift);
92980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            inv->fMat[kMTransY] = SkMulShift(ty.getShiftRight(33 - clzNumer), scale, sk64shift);
93080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
93180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            inv->fMat[kMScaleX] = SkDoubleToFloat(fMat[kMScaleY] * scale);
93280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            inv->fMat[kMSkewX] = SkDoubleToFloat(-fMat[kMSkewX] * scale);
93380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            inv->fMat[kMTransX] = mul_diff_scale(fMat[kMSkewX], fMat[kMTransY],
93480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                     fMat[kMScaleY], fMat[kMTransX], scale);
93580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
93680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            inv->fMat[kMSkewY] = SkDoubleToFloat(-fMat[kMSkewY] * scale);
93780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            inv->fMat[kMScaleY] = SkDoubleToFloat(fMat[kMScaleX] * scale);
93880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            inv->fMat[kMTransY] = mul_diff_scale(fMat[kMSkewY], fMat[kMTransX],
93980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                        fMat[kMScaleX], fMat[kMTransY], scale);
94080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
94180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            inv->fMat[kMPersp0] = 0;
94280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            inv->fMat[kMPersp1] = 0;
94380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            inv->fMat[kMPersp2] = kMatrix22Elem;
94480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
94580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
94680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
94780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        inv->setTypeMask(fTypeMask);
94880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
94980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (inv == &tmp) {
95080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *(SkMatrix*)this = tmp;
95180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
95280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
95380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
95480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
95580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
95680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
95780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
95880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix::Identity_pts(const SkMatrix& m, SkPoint dst[],
95980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                            const SkPoint src[], int count) {
96080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(m.getType() == 0);
96180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
96280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (dst != src && count > 0)
96380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        memcpy(dst, src, count * sizeof(SkPoint));
96480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
96580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
96680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix::Trans_pts(const SkMatrix& m, SkPoint dst[],
96780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                         const SkPoint src[], int count) {
96880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(m.getType() == kTranslate_Mask);
96980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
97080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (count > 0) {
97180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalar tx = m.fMat[kMTransX];
97280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalar ty = m.fMat[kMTransY];
97380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        do {
97480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            dst->fY = src->fY + ty;
97580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            dst->fX = src->fX + tx;
97680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            src += 1;
97780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            dst += 1;
97880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } while (--count);
97980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
98080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
98180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
98280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix::Scale_pts(const SkMatrix& m, SkPoint dst[],
98380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                         const SkPoint src[], int count) {
98480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(m.getType() == kScale_Mask);
98580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
98680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (count > 0) {
98780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalar mx = m.fMat[kMScaleX];
98880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalar my = m.fMat[kMScaleY];
98980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        do {
99080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            dst->fY = SkScalarMul(src->fY, my);
99180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            dst->fX = SkScalarMul(src->fX, mx);
99280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            src += 1;
99380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            dst += 1;
99480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } while (--count);
99580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
99680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
99780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
99880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix::ScaleTrans_pts(const SkMatrix& m, SkPoint dst[],
99980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                              const SkPoint src[], int count) {
100080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(m.getType() == (kScale_Mask | kTranslate_Mask));
100180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
100280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (count > 0) {
100380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalar mx = m.fMat[kMScaleX];
100480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalar my = m.fMat[kMScaleY];
100580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalar tx = m.fMat[kMTransX];
100680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalar ty = m.fMat[kMTransY];
100780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        do {
100880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            dst->fY = SkScalarMulAdd(src->fY, my, ty);
100980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            dst->fX = SkScalarMulAdd(src->fX, mx, tx);
101080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            src += 1;
101180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            dst += 1;
101280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } while (--count);
101380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
101480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
101580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
101680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix::Rot_pts(const SkMatrix& m, SkPoint dst[],
101780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                       const SkPoint src[], int count) {
101880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT((m.getType() & (kPerspective_Mask | kTranslate_Mask)) == 0);
101980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
102080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (count > 0) {
102180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalar mx = m.fMat[kMScaleX];
102280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalar my = m.fMat[kMScaleY];
102380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalar kx = m.fMat[kMSkewX];
102480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalar ky = m.fMat[kMSkewY];
102580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        do {
102680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkScalar sy = src->fY;
102780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkScalar sx = src->fX;
102880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            src += 1;
102980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            dst->fY = SkScalarMul(sx, ky) + SkScalarMul(sy, my);
103080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            dst->fX = SkScalarMul(sx, mx) + SkScalarMul(sy, kx);
103180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            dst += 1;
103280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } while (--count);
103380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
103480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
103580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
103680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix::RotTrans_pts(const SkMatrix& m, SkPoint dst[],
103780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                            const SkPoint src[], int count) {
103880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(!m.hasPerspective());
103980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
104080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (count > 0) {
104180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalar mx = m.fMat[kMScaleX];
104280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalar my = m.fMat[kMScaleY];
104380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalar kx = m.fMat[kMSkewX];
104480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalar ky = m.fMat[kMSkewY];
104580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalar tx = m.fMat[kMTransX];
104680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalar ty = m.fMat[kMTransY];
104780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        do {
104880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkScalar sy = src->fY;
104980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkScalar sx = src->fX;
105080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            src += 1;
105180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            dst->fY = SkScalarMul(sx, ky) + SkScalarMulAdd(sy, my, ty);
105280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            dst->fX = SkScalarMul(sx, mx) + SkScalarMulAdd(sy, kx, tx);
105380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            dst += 1;
105480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } while (--count);
105580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
105680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
105780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
105880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix::Persp_pts(const SkMatrix& m, SkPoint dst[],
105980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                         const SkPoint src[], int count) {
106080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(m.hasPerspective());
106180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
106280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_SCALAR_IS_FIXED
106380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkFixed persp2 = SkFractToFixed(m.fMat[kMPersp2]);
106480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
106580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
106680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (count > 0) {
106780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        do {
106880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkScalar sy = src->fY;
106980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkScalar sx = src->fX;
107080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            src += 1;
107180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
107280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkScalar x = SkScalarMul(sx, m.fMat[kMScaleX]) +
107380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                         SkScalarMul(sy, m.fMat[kMSkewX]) + m.fMat[kMTransX];
107480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkScalar y = SkScalarMul(sx, m.fMat[kMSkewY]) +
107580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                         SkScalarMul(sy, m.fMat[kMScaleY]) + m.fMat[kMTransY];
107680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_SCALAR_IS_FIXED
107780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkFixed z = SkFractMul(sx, m.fMat[kMPersp0]) +
107880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        SkFractMul(sy, m.fMat[kMPersp1]) + persp2;
107980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
108080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            float z = SkScalarMul(sx, m.fMat[kMPersp0]) +
108180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                      SkScalarMulAdd(sy, m.fMat[kMPersp1], m.fMat[kMPersp2]);
108280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
108380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (z) {
108480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                z = SkScalarFastInvert(z);
108580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
108680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
108780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            dst->fY = SkScalarMul(y, z);
108880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            dst->fX = SkScalarMul(x, z);
108980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            dst += 1;
109080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } while (--count);
109180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
109280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
109380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
109480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruconst SkMatrix::MapPtsProc SkMatrix::gMapPtsProcs[] = {
109580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkMatrix::Identity_pts, SkMatrix::Trans_pts,
109680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkMatrix::Scale_pts,    SkMatrix::ScaleTrans_pts,
109780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkMatrix::Rot_pts,      SkMatrix::RotTrans_pts,
109880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkMatrix::Rot_pts,      SkMatrix::RotTrans_pts,
109980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // repeat the persp proc 8 times
110080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkMatrix::Persp_pts,    SkMatrix::Persp_pts,
110180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkMatrix::Persp_pts,    SkMatrix::Persp_pts,
110280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkMatrix::Persp_pts,    SkMatrix::Persp_pts,
110380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkMatrix::Persp_pts,    SkMatrix::Persp_pts
110480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
110580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
110680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix::mapPoints(SkPoint dst[], const SkPoint src[], int count) const {
110780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT((dst && src && count > 0) || count == 0);
110880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // no partial overlap
110980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(src == dst || SkAbs32((int32_t)(src - dst)) >= count);
111080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
111180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->getMapPtsProc()(*this, dst, src, count);
111280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
111380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
111480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
111580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
111680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix::mapVectors(SkPoint dst[], const SkPoint src[], int count) const {
111780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (this->hasPerspective()) {
111880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkPoint origin;
111980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
112080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        MapXYProc proc = this->getMapXYProc();
112180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        proc(*this, 0, 0, &origin);
112280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
112380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for (int i = count - 1; i >= 0; --i) {
112480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkPoint tmp;
112580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
112680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            proc(*this, src[i].fX, src[i].fY, &tmp);
112780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            dst[i].set(tmp.fX - origin.fX, tmp.fY - origin.fY);
112880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
112980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
113080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkMatrix tmp = *this;
113180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
113280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        tmp.fMat[kMTransX] = tmp.fMat[kMTransY] = 0;
113380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        tmp.clearTypeMask(kTranslate_Mask);
113480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        tmp.mapPoints(dst, src, count);
113580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
113680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
113780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
113880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkMatrix::mapRect(SkRect* dst, const SkRect& src) const {
113980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(dst && &src);
114080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
114180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (this->rectStaysRect()) {
114280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->mapPoints((SkPoint*)dst, (const SkPoint*)&src, 2);
114380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dst->sort();
114480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
114580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
114680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkPoint quad[4];
114780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
114880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        src.toQuad(quad);
114980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->mapPoints(quad, quad, 4);
115080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dst->set(quad, 4);
115180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
115280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
115380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
115480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
115580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkScalar SkMatrix::mapRadius(SkScalar radius) const {
115680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkVector    vec[2];
115780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
115880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    vec[0].set(radius, 0);
115980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    vec[1].set(0, radius);
116080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->mapVectors(vec, 2);
116180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
116280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScalar d0 = vec[0].length();
116380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScalar d1 = vec[1].length();
116480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
116580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkScalarMean(d0, d1);
116680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
116780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
116880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
116980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
117080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix::Persp_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
117180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        SkPoint* pt) {
117280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(m.hasPerspective());
117380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
117480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScalar x = SkScalarMul(sx, m.fMat[kMScaleX]) +
117580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                 SkScalarMul(sy, m.fMat[kMSkewX]) + m.fMat[kMTransX];
117680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScalar y = SkScalarMul(sx, m.fMat[kMSkewY]) +
117780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                 SkScalarMul(sy, m.fMat[kMScaleY]) + m.fMat[kMTransY];
117880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_SCALAR_IS_FIXED
117980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkFixed z = SkFractMul(sx, m.fMat[kMPersp0]) +
118080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkFractMul(sy, m.fMat[kMPersp1]) +
118180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkFractToFixed(m.fMat[kMPersp2]);
118280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
118380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    float z = SkScalarMul(sx, m.fMat[kMPersp0]) +
118480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru              SkScalarMul(sy, m.fMat[kMPersp1]) + m.fMat[kMPersp2];
118580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
118680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (z) {
118780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        z = SkScalarFastInvert(z);
118880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
118980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    pt->fX = SkScalarMul(x, z);
119080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    pt->fY = SkScalarMul(y, z);
119180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
119280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
119380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_SCALAR_IS_FIXED
119480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic SkFixed fixmuladdmul(SkFixed a, SkFixed b, SkFixed c, SkFixed d) {
119580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Sk64    tmp, tmp1;
119680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
119780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    tmp.setMul(a, b);
119880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    tmp1.setMul(c, d);
119980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return tmp.addGetFixed(tmp1);
120080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//  tmp.add(tmp1);
120180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//  return tmp.getFixed();
120280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
120380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
120480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
120580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix::RotTrans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
120680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                           SkPoint* pt) {
120780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT((m.getType() & (kAffine_Mask | kPerspective_Mask)) == kAffine_Mask);
120880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
120980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_SCALAR_IS_FIXED
121080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    pt->fX = fixmuladdmul(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX]) +
121180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru             m.fMat[kMTransX];
121280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    pt->fY = fixmuladdmul(sx, m.fMat[kMSkewY], sy, m.fMat[kMScaleY]) +
121380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru             m.fMat[kMTransY];
121480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
121580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    pt->fX = SkScalarMul(sx, m.fMat[kMScaleX]) +
121680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru             SkScalarMulAdd(sy, m.fMat[kMSkewX], m.fMat[kMTransX]);
121780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    pt->fY = SkScalarMul(sx, m.fMat[kMSkewY]) +
121880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru             SkScalarMulAdd(sy, m.fMat[kMScaleY], m.fMat[kMTransY]);
121980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
122080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
122180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
122280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix::Rot_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
122380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                      SkPoint* pt) {
122480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT((m.getType() & (kAffine_Mask | kPerspective_Mask))== kAffine_Mask);
122580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(0 == m.fMat[kMTransX]);
122680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(0 == m.fMat[kMTransY]);
122780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
122880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_SCALAR_IS_FIXED
122980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    pt->fX = fixmuladdmul(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX]);
123080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    pt->fY = fixmuladdmul(sx, m.fMat[kMSkewY], sy, m.fMat[kMScaleY]);
123180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
123280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    pt->fX = SkScalarMul(sx, m.fMat[kMScaleX]) +
123380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru             SkScalarMulAdd(sy, m.fMat[kMSkewX], m.fMat[kMTransX]);
123480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    pt->fY = SkScalarMul(sx, m.fMat[kMSkewY]) +
123580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru             SkScalarMulAdd(sy, m.fMat[kMScaleY], m.fMat[kMTransY]);
123680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
123780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
123880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
123980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix::ScaleTrans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
124080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             SkPoint* pt) {
124180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT((m.getType() & (kScale_Mask | kAffine_Mask | kPerspective_Mask))
124280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru             == kScale_Mask);
124380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
124480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    pt->fX = SkScalarMulAdd(sx, m.fMat[kMScaleX], m.fMat[kMTransX]);
124580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    pt->fY = SkScalarMulAdd(sy, m.fMat[kMScaleY], m.fMat[kMTransY]);
124680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
124780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
124880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix::Scale_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
124980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        SkPoint* pt) {
125080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT((m.getType() & (kScale_Mask | kAffine_Mask | kPerspective_Mask))
125180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru             == kScale_Mask);
125280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(0 == m.fMat[kMTransX]);
125380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(0 == m.fMat[kMTransY]);
125480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
125580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    pt->fX = SkScalarMul(sx, m.fMat[kMScaleX]);
125680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    pt->fY = SkScalarMul(sy, m.fMat[kMScaleY]);
125780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
125880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
125980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix::Trans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
126080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        SkPoint* pt) {
126180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(m.getType() == kTranslate_Mask);
126280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
126380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    pt->fX = sx + m.fMat[kMTransX];
126480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    pt->fY = sy + m.fMat[kMTransY];
126580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
126680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
126780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix::Identity_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
126880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                           SkPoint* pt) {
126980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(0 == m.getType());
127080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
127180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    pt->fX = sx;
127280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    pt->fY = sy;
127380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
127480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
127580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruconst SkMatrix::MapXYProc SkMatrix::gMapXYProcs[] = {
127680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkMatrix::Identity_xy, SkMatrix::Trans_xy,
127780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkMatrix::Scale_xy,    SkMatrix::ScaleTrans_xy,
127880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkMatrix::Rot_xy,      SkMatrix::RotTrans_xy,
127980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkMatrix::Rot_xy,      SkMatrix::RotTrans_xy,
128080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // repeat the persp proc 8 times
128180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkMatrix::Persp_xy,    SkMatrix::Persp_xy,
128280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkMatrix::Persp_xy,    SkMatrix::Persp_xy,
128380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkMatrix::Persp_xy,    SkMatrix::Persp_xy,
128480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkMatrix::Persp_xy,    SkMatrix::Persp_xy
128580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
128680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
128780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
128880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
128980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// if its nearly zero (just made up 26, perhaps it should be bigger or smaller)
129080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_SCALAR_IS_FIXED
129180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    typedef SkFract             SkPerspElemType;
129280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define PerspNearlyZero(x)  (SkAbs32(x) < (SK_Fract1 >> 26))
129380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
129480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    typedef float               SkPerspElemType;
129580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define PerspNearlyZero(x)  SkScalarNearlyZero(x, (1.0f / (1 << 26)))
129680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
129780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
129880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkMatrix::fixedStepInX(SkScalar y, SkFixed* stepX, SkFixed* stepY) const {
129980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (PerspNearlyZero(fMat[kMPersp0])) {
130080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (stepX || stepY) {
130180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (PerspNearlyZero(fMat[kMPersp1]) &&
130280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    PerspNearlyZero(fMat[kMPersp2] - kMatrix22Elem)) {
130380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (stepX) {
130480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    *stepX = SkScalarToFixed(fMat[kMScaleX]);
130580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
130680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (stepY) {
130780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    *stepY = SkScalarToFixed(fMat[kMSkewY]);
130880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
130980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } else {
131080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_SCALAR_IS_FIXED
131180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkFixed z = SkFractMul(y, fMat[kMPersp1]) +
131280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                            SkFractToFixed(fMat[kMPersp2]);
131380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
131480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                float z = y * fMat[kMPersp1] + fMat[kMPersp2];
131580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
131680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (stepX) {
131780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    *stepX = SkScalarToFixed(SkScalarDiv(fMat[kMScaleX], z));
131880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
131980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (stepY) {
132080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    *stepY = SkScalarToFixed(SkScalarDiv(fMat[kMSkewY], z));
132180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
132280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
132380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
132480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
132580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
132680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return false;
132780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
132880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
132980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
133080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
133180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkPerspIter.h"
133280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
133380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkPerspIter::SkPerspIter(const SkMatrix& m, SkScalar x0, SkScalar y0, int count)
133480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        : fMatrix(m), fSX(x0), fSY(y0), fCount(count) {
133580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkPoint pt;
133680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
133780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkMatrix::Persp_xy(m, x0, y0, &pt);
133880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fX = SkScalarToFixed(pt.fX);
133980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fY = SkScalarToFixed(pt.fY);
134080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
134180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
134280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint SkPerspIter::next() {
134380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int n = fCount;
134480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
134580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (0 == n) {
134680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return 0;
134780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
134880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkPoint pt;
134980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkFixed x = fX;
135080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkFixed y = fY;
135180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkFixed dx, dy;
135280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
135380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (n >= kCount) {
135480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        n = kCount;
135580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fSX += SkIntToScalar(kCount);
135680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkMatrix::Persp_xy(fMatrix, fSX, fSY, &pt);
135780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fX = SkScalarToFixed(pt.fX);
135880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fY = SkScalarToFixed(pt.fY);
135980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dx = (fX - x) >> kShift;
136080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dy = (fY - y) >> kShift;
136180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
136280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fSX += SkIntToScalar(n);
136380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkMatrix::Persp_xy(fMatrix, fSX, fSY, &pt);
136480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fX = SkScalarToFixed(pt.fX);
136580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fY = SkScalarToFixed(pt.fY);
136680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dx = (fX - x) / n;
136780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dy = (fY - y) / n;
136880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
136980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
137080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkFixed* p = fStorage;
137180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (int i = 0; i < n; i++) {
137280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *p++ = x; x += dx;
137380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *p++ = y; y += dy;
137480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
137580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
137680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fCount -= n;
137780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return n;
137880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
137980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
138080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
138180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
138280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_SCALAR_IS_FIXED
138380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
138480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline bool poly_to_point(SkPoint* pt, const SkPoint poly[], int count) {
138580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkFixed x = SK_Fixed1, y = SK_Fixed1;
138680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkPoint pt1, pt2;
138780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Sk64    w1, w2;
138880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
138980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (count > 1) {
139080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        pt1.fX = poly[1].fX - poly[0].fX;
139180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        pt1.fY = poly[1].fY - poly[0].fY;
139280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        y = SkPoint::Length(pt1.fX, pt1.fY);
139380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (y == 0) {
139480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
139580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
139680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        switch (count) {
139780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            case 2:
139880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
139980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            case 3:
140080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                pt2.fX = poly[0].fY - poly[2].fY;
140180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                pt2.fY = poly[2].fX - poly[0].fX;
140280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                goto CALC_X;
140380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            default:
140480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                pt2.fX = poly[0].fY - poly[3].fY;
140580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                pt2.fY = poly[3].fX - poly[0].fX;
140680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            CALC_X:
140780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                w1.setMul(pt1.fX, pt2.fX);
140880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                w2.setMul(pt1.fY, pt2.fY);
140980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                w1.add(w2);
141080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                w1.div(y, Sk64::kRound_DivOption);
141180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (!w1.is32()) {
141280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    return false;
141380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
141480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                x = w1.get32();
141580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
141680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
141780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
141880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    pt->set(x, y);
141980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
142080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
142180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
142280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkMatrix::Poly2Proc(const SkPoint srcPt[], SkMatrix* dst,
142380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                         const SkPoint& scalePt) {
142480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // need to check if SkFixedDiv overflows...
142580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
142680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const SkFixed scale = scalePt.fY;
142780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMScaleX] = SkFixedDiv(srcPt[1].fY - srcPt[0].fY, scale);
142880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMSkewY]  = SkFixedDiv(srcPt[0].fX - srcPt[1].fX, scale);
142980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMPersp0] = 0;
143080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMSkewX]  = SkFixedDiv(srcPt[1].fX - srcPt[0].fX, scale);
143180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMScaleY] = SkFixedDiv(srcPt[1].fY - srcPt[0].fY, scale);
143280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMPersp1] = 0;
143380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMTransX] = srcPt[0].fX;
143480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMTransY] = srcPt[0].fY;
143580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMPersp2] = SK_Fract1;
143680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->setTypeMask(kUnknown_Mask);
143780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
143880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
143980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
144080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkMatrix::Poly3Proc(const SkPoint srcPt[], SkMatrix* dst,
144180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                         const SkPoint& scale) {
144280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // really, need to check if SkFixedDiv overflow'd
144380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
144480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMScaleX] = SkFixedDiv(srcPt[2].fX - srcPt[0].fX, scale.fX);
144580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMSkewY]  = SkFixedDiv(srcPt[2].fY - srcPt[0].fY, scale.fX);
144680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMPersp0] = 0;
144780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMSkewX]  = SkFixedDiv(srcPt[1].fX - srcPt[0].fX, scale.fY);
144880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMScaleY] = SkFixedDiv(srcPt[1].fY - srcPt[0].fY, scale.fY);
144980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMPersp1] = 0;
145080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMTransX] = srcPt[0].fX;
145180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMTransY] = srcPt[0].fY;
145280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMPersp2] = SK_Fract1;
145380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->setTypeMask(kUnknown_Mask);
145480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
145580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
145680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
145780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkMatrix::Poly4Proc(const SkPoint srcPt[], SkMatrix* dst,
145880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                         const SkPoint& scale) {
145980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkFract a1, a2;
146080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkFixed x0, y0, x1, y1, x2, y2;
146180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
146280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    x0 = srcPt[2].fX - srcPt[0].fX;
146380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    y0 = srcPt[2].fY - srcPt[0].fY;
146480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    x1 = srcPt[2].fX - srcPt[1].fX;
146580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    y1 = srcPt[2].fY - srcPt[1].fY;
146680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    x2 = srcPt[2].fX - srcPt[3].fX;
146780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    y2 = srcPt[2].fY - srcPt[3].fY;
146880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
146980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /* check if abs(x2) > abs(y2) */
147080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if ( x2 > 0 ? y2 > 0 ? x2 > y2 : x2 > -y2 : y2 > 0 ? -x2 > y2 : x2 < y2) {
147180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkFixed denom = SkMulDiv(x1, y2, x2) - y1;
147280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (0 == denom) {
147380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
147480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
147580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        a1 = SkFractDiv(SkMulDiv(x0 - x1, y2, x2) - y0 + y1, denom);
147680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
147780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkFixed denom = x1 - SkMulDiv(y1, x2, y2);
147880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (0 == denom) {
147980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
148080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
148180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        a1 = SkFractDiv(x0 - x1 - SkMulDiv(y0 - y1, x2, y2), denom);
148280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
148380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
148480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /* check if abs(x1) > abs(y1) */
148580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if ( x1 > 0 ? y1 > 0 ? x1 > y1 : x1 > -y1 : y1 > 0 ? -x1 > y1 : x1 < y1) {
148680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkFixed denom = y2 - SkMulDiv(x2, y1, x1);
148780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (0 == denom) {
148880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
148980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
149080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        a2 = SkFractDiv(y0 - y2 - SkMulDiv(x0 - x2, y1, x1), denom);
149180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
149280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkFixed denom = SkMulDiv(y2, x1, y1) - x2;
149380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (0 == denom) {
149480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
149580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
149680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        a2 = SkFractDiv(SkMulDiv(y0 - y2, x1, y1) - x0 + x2, denom);
149780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
149880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
149980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // need to check if SkFixedDiv overflows...
150080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMScaleX] = SkFixedDiv(SkFractMul(a2, srcPt[3].fX) +
150180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                     srcPt[3].fX - srcPt[0].fX, scale.fX);
150280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMSkewY]  = SkFixedDiv(SkFractMul(a2, srcPt[3].fY) +
150380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                     srcPt[3].fY - srcPt[0].fY, scale.fX);
150480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMPersp0] = SkFixedDiv(a2, scale.fX);
150580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMSkewX]  = SkFixedDiv(SkFractMul(a1, srcPt[1].fX) +
150680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                     srcPt[1].fX - srcPt[0].fX, scale.fY);
150780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMScaleY] = SkFixedDiv(SkFractMul(a1, srcPt[1].fY) +
150880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                     srcPt[1].fY - srcPt[0].fY, scale.fY);
150980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMPersp1] = SkFixedDiv(a1, scale.fY);
151080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMTransX] = srcPt[0].fX;
151180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMTransY] = srcPt[0].fY;
151280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMPersp2] = SK_Fract1;
151380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->setTypeMask(kUnknown_Mask);
151480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
151580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
151680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
151780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else   /* Scalar is float */
151880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
151980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline bool checkForZero(float x) {
152080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return x*x == 0;
152180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
152280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
152380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline bool poly_to_point(SkPoint* pt, const SkPoint poly[], int count) {
152480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    float   x = 1, y = 1;
152580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkPoint pt1, pt2;
152680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
152780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (count > 1) {
152880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        pt1.fX = poly[1].fX - poly[0].fX;
152980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        pt1.fY = poly[1].fY - poly[0].fY;
153080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        y = SkPoint::Length(pt1.fX, pt1.fY);
153180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (checkForZero(y)) {
153280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
153380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
153480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        switch (count) {
153580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            case 2:
153680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
153780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            case 3:
153880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                pt2.fX = poly[0].fY - poly[2].fY;
153980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                pt2.fY = poly[2].fX - poly[0].fX;
154080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                goto CALC_X;
154180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            default:
154280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                pt2.fX = poly[0].fY - poly[3].fY;
154380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                pt2.fY = poly[3].fX - poly[0].fX;
154480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            CALC_X:
154580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                x = SkScalarDiv(SkScalarMul(pt1.fX, pt2.fX) +
154680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                SkScalarMul(pt1.fY, pt2.fY), y);
154780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
154880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
154980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
155080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    pt->set(x, y);
155180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
155280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
155380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
155480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkMatrix::Poly2Proc(const SkPoint srcPt[], SkMatrix* dst,
155580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                         const SkPoint& scale) {
155680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    float invScale = 1 / scale.fY;
155780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
155880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMScaleX] = (srcPt[1].fY - srcPt[0].fY) * invScale;
155980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMSkewY] = (srcPt[0].fX - srcPt[1].fX) * invScale;
156080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMPersp0] = 0;
156180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMSkewX] = (srcPt[1].fX - srcPt[0].fX) * invScale;
156280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMScaleY] = (srcPt[1].fY - srcPt[0].fY) * invScale;
156380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMPersp1] = 0;
156480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMTransX] = srcPt[0].fX;
156580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMTransY] = srcPt[0].fY;
156680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMPersp2] = 1;
156780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->setTypeMask(kUnknown_Mask);
156880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
156980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
157080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
157180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkMatrix::Poly3Proc(const SkPoint srcPt[], SkMatrix* dst,
157280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                         const SkPoint& scale) {
157380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    float invScale = 1 / scale.fX;
157480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMScaleX] = (srcPt[2].fX - srcPt[0].fX) * invScale;
157580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMSkewY] = (srcPt[2].fY - srcPt[0].fY) * invScale;
157680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMPersp0] = 0;
157780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
157880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    invScale = 1 / scale.fY;
157980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMSkewX] = (srcPt[1].fX - srcPt[0].fX) * invScale;
158080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMScaleY] = (srcPt[1].fY - srcPt[0].fY) * invScale;
158180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMPersp1] = 0;
158280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
158380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMTransX] = srcPt[0].fX;
158480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMTransY] = srcPt[0].fY;
158580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMPersp2] = 1;
158680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->setTypeMask(kUnknown_Mask);
158780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
158880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
158980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
159080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkMatrix::Poly4Proc(const SkPoint srcPt[], SkMatrix* dst,
159180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                         const SkPoint& scale) {
159280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    float   a1, a2;
159380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    float   x0, y0, x1, y1, x2, y2;
159480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
159580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    x0 = srcPt[2].fX - srcPt[0].fX;
159680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    y0 = srcPt[2].fY - srcPt[0].fY;
159780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    x1 = srcPt[2].fX - srcPt[1].fX;
159880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    y1 = srcPt[2].fY - srcPt[1].fY;
159980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    x2 = srcPt[2].fX - srcPt[3].fX;
160080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    y2 = srcPt[2].fY - srcPt[3].fY;
160180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
160280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /* check if abs(x2) > abs(y2) */
160380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if ( x2 > 0 ? y2 > 0 ? x2 > y2 : x2 > -y2 : y2 > 0 ? -x2 > y2 : x2 < y2) {
160480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        float denom = SkScalarMulDiv(x1, y2, x2) - y1;
160580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (checkForZero(denom)) {
160680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
160780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
160880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        a1 = SkScalarDiv(SkScalarMulDiv(x0 - x1, y2, x2) - y0 + y1, denom);
160980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
161080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        float denom = x1 - SkScalarMulDiv(y1, x2, y2);
161180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (checkForZero(denom)) {
161280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
161380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
161480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        a1 = SkScalarDiv(x0 - x1 - SkScalarMulDiv(y0 - y1, x2, y2), denom);
161580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
161680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
161780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /* check if abs(x1) > abs(y1) */
161880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if ( x1 > 0 ? y1 > 0 ? x1 > y1 : x1 > -y1 : y1 > 0 ? -x1 > y1 : x1 < y1) {
161980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        float denom = y2 - SkScalarMulDiv(x2, y1, x1);
162080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (checkForZero(denom)) {
162180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
162280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
162380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        a2 = SkScalarDiv(y0 - y2 - SkScalarMulDiv(x0 - x2, y1, x1), denom);
162480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
162580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        float denom = SkScalarMulDiv(y2, x1, y1) - x2;
162680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (checkForZero(denom)) {
162780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
162880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
162980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        a2 = SkScalarDiv(SkScalarMulDiv(y0 - y2, x1, y1) - x0 + x2, denom);
163080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
163180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
163280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    float invScale = 1 / scale.fX;
163380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMScaleX] = SkScalarMul(SkScalarMul(a2, srcPt[3].fX) +
163480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                      srcPt[3].fX - srcPt[0].fX, invScale);
163580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMSkewY] = SkScalarMul(SkScalarMul(a2, srcPt[3].fY) +
163680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                     srcPt[3].fY - srcPt[0].fY, invScale);
163780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMPersp0] = SkScalarMul(a2, invScale);
163880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    invScale = 1 / scale.fY;
163980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMSkewX] = SkScalarMul(SkScalarMul(a1, srcPt[1].fX) +
164080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                     srcPt[1].fX - srcPt[0].fX, invScale);
164180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMScaleY] = SkScalarMul(SkScalarMul(a1, srcPt[1].fY) +
164280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                      srcPt[1].fY - srcPt[0].fY, invScale);
164380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMPersp1] = SkScalarMul(a1, invScale);
164480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMTransX] = srcPt[0].fX;
164580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMTransY] = srcPt[0].fY;
164680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fMat[kMPersp2] = 1;
164780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->setTypeMask(kUnknown_Mask);
164880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
164980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
165080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
165180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
165280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
165380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querutypedef bool (*PolyMapProc)(const SkPoint[], SkMatrix*, const SkPoint&);
165480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
165580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*  Taken from Rob Johnson's original sample code in QuickDraw GX
165680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru*/
165780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkMatrix::setPolyToPoly(const SkPoint src[], const SkPoint dst[],
165880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             int count) {
165980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if ((unsigned)count > 4) {
166080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkDebugf("--- SkMatrix::setPolyToPoly count out of range %d\n", count);
166180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
166280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
166380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
166480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (0 == count) {
166580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->reset();
166680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
166780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
166880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (1 == count) {
166980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->setTranslate(dst[0].fX - src[0].fX, dst[0].fY - src[0].fY);
167080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
167180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
167280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
167380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkPoint scale;
167480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!poly_to_point(&scale, src, count) ||
167580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkScalarNearlyZero(scale.fX) ||
167680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkScalarNearlyZero(scale.fY)) {
167780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
167880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
167980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
168080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static const PolyMapProc gPolyMapProcs[] = {
168180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkMatrix::Poly2Proc, SkMatrix::Poly3Proc, SkMatrix::Poly4Proc
168280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    };
168380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    PolyMapProc proc = gPolyMapProcs[count - 2];
168480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
168580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkMatrix tempMap, result;
168680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    tempMap.setTypeMask(kUnknown_Mask);
168780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
168880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!proc(src, &tempMap, scale)) {
168980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
169080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
169180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!tempMap.invert(&result)) {
169280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
169380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
169480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!proc(dst, &tempMap, scale)) {
169580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
169680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
169780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!result.setConcat(tempMap, result)) {
169880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
169980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
170080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    *this = result;
170180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
170280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
170380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
170480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
170580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
170680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkScalar SkMatrix::getMaxStretch() const {
170780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    TypeMask mask = this->getType();
170880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
170980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (this->hasPerspective()) {
171080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return -SK_Scalar1;
171180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
171280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (this->isIdentity()) {
171380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return SK_Scalar1;
171480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
171580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!(mask & kAffine_Mask)) {
171680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return SkMaxScalar(SkScalarAbs(fMat[kMScaleX]),
171780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                           SkScalarAbs(fMat[kMScaleY]));
171880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
171980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // ignore the translation part of the matrix, just look at 2x2 portion.
172080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // compute singular values, take largest abs value.
172180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // [a b; b c] = A^T*A
172280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScalar a = SkScalarMul(fMat[kMScaleX], fMat[kMScaleX]) +
172380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                 SkScalarMul(fMat[kMSkewY],  fMat[kMSkewY]);
172480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScalar b = SkScalarMul(fMat[kMScaleX], fMat[kMSkewX]) +
172580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                 SkScalarMul(fMat[kMScaleY], fMat[kMSkewY]);
172680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScalar c = SkScalarMul(fMat[kMSkewX],  fMat[kMSkewX]) +
172780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                 SkScalarMul(fMat[kMScaleY], fMat[kMScaleY]);
172880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // eigenvalues of A^T*A are the squared singular values of A.
172980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // characteristic equation is det((A^T*A) - l*I) = 0
173080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // l^2 - (a + c)l + (ac-b^2)
173180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // solve using quadratic equation (divisor is non-zero since l^2 has 1 coeff
173280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // and roots are guaraunteed to be pos and real).
173380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScalar largerRoot;
173480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScalar bSqd = SkScalarMul(b,b);
173580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // if upper left 2x2 is orthogonal save some math
173680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (bSqd <= SK_ScalarNearlyZero) {
173780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        largerRoot = SkMaxScalar(a, c);
173880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
173980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalar aminusc = a - c;
174080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalar apluscdiv2 = SkScalarHalf(a + c);
174180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalar x = SkScalarHalf(SkScalarSqrt(SkScalarMul(aminusc, aminusc) + 4 * bSqd));
174280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        largerRoot = apluscdiv2 + x;
174380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
174480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkScalarSqrt(largerRoot);
174580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
174680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
174780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruconst SkMatrix& SkMatrix::I() {
174880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static SkMatrix gIdentity;
174980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static bool gOnce;
175080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!gOnce) {
175180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        gIdentity.reset();
175280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        gOnce = true;
175380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
175480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return gIdentity;
175580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
175680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
175780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruconst SkMatrix& SkMatrix::InvalidMatrix() {
175880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static SkMatrix gInvalid;
175980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static bool gOnce;
176080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!gOnce) {
176180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        gInvalid.setAll(SK_ScalarMax, SK_ScalarMax, SK_ScalarMax,
176280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        SK_ScalarMax, SK_ScalarMax, SK_ScalarMax,
176380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        SK_ScalarMax, SK_ScalarMax, SK_ScalarMax);
176480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        gInvalid.getType(); // force the type to be computed
176580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        gOnce = true;
176680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
176780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return gInvalid;
176880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
176980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
177080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
177180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
177280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruuint32_t SkMatrix::writeToMemory(void* buffer) const {
177380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // TODO write less for simple matrices
177480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (buffer) {
177580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        memcpy(buffer, fMat, 9 * sizeof(SkScalar));
177680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
177780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return 9 * sizeof(SkScalar);
177880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
177980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
178080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruuint32_t SkMatrix::readFromMemory(const void* buffer) {
178180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (buffer) {
178280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        memcpy(fMat, buffer, 9 * sizeof(SkScalar));
178380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->setTypeMask(kUnknown_Mask);
178480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
178580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return 9 * sizeof(SkScalar);
178680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
178780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
178880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix::dump() const {
178980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkString str;
179080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->toDumpString(&str);
179180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDebugf("%s\n", str.c_str());
179280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
179380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
179480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix::toDumpString(SkString* str) const {
179580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    str->printf("[%8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f]",
179680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_SCALAR_IS_FLOAT
179780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru             fMat[0], fMat[1], fMat[2], fMat[3], fMat[4], fMat[5],
179880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru             fMat[6], fMat[7], fMat[8]);
179980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
180080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkFixedToFloat(fMat[0]), SkFixedToFloat(fMat[1]), SkFixedToFloat(fMat[2]),
180180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkFixedToFloat(fMat[3]), SkFixedToFloat(fMat[4]), SkFixedToFloat(fMat[5]),
180280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkFractToFloat(fMat[6]), SkFractToFloat(fMat[7]), SkFractToFloat(fMat[8]));
180380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
180480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
1805