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