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