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