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