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