• 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/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 
doNormalizePerspective()24 void 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 
reset()63 SkMatrix& SkMatrix::reset() { *this = SkMatrix(); return *this; }
64 
set9(const SkScalar buffer[])65 SkMatrix& SkMatrix::set9(const SkScalar buffer[]) {
66     memcpy(fMat, buffer, 9 * sizeof(SkScalar));
67     this->setTypeMask(kUnknown_Mask);
68     return *this;
69 }
70 
setAffine(const SkScalar buffer[])71 SkMatrix& 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
86 enum {
87     kTranslate_Shift,
88     kScale_Shift,
89     kAffine_Shift,
90     kPerspective_Shift,
91     kRectStaysRect_Shift
92 };
93 
94 static const int32_t kScalar1Int = 0x3f800000;
95 
computePerspectiveTypeMask() const96 uint8_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 
computeTypeMask() const111 uint8_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 
operator ==(const SkMatrix & a,const SkMatrix & b)174 bool 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
is_degenerate_2x2(SkScalar scaleX,SkScalar skewX,SkScalar skewY,SkScalar scaleY)186 static 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 
isSimilarity(SkScalar tol) const194 bool 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 
preservesRightAngles(SkScalar tol) const223 bool 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 
sdot(SkScalar a,SkScalar b,SkScalar c,SkScalar d)255 static inline SkScalar sdot(SkScalar a, SkScalar b, SkScalar c, SkScalar d) {
256     return a * b + c * d;
257 }
258 
sdot(SkScalar a,SkScalar b,SkScalar c,SkScalar d,SkScalar e,SkScalar f)259 static 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 
scross(SkScalar a,SkScalar b,SkScalar c,SkScalar d)264 static inline SkScalar scross(SkScalar a, SkScalar b, SkScalar c, SkScalar d) {
265     return a * b - c * d;
266 }
267 
setTranslate(SkScalar dx,SkScalar dy)268 SkMatrix& 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 
preTranslate(SkScalar dx,SkScalar dy)277 SkMatrix& 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 
postTranslate(SkScalar dx,SkScalar dy)295 SkMatrix& 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 
setScale(SkScalar sx,SkScalar sy,SkScalar px,SkScalar py)310 SkMatrix& 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 
setScale(SkScalar sx,SkScalar sy)319 SkMatrix& 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 
preScale(SkScalar sx,SkScalar sy,SkScalar px,SkScalar py)328 SkMatrix& 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 
preScale(SkScalar sx,SkScalar sy)338 SkMatrix& 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 
postScale(SkScalar sx,SkScalar sy,SkScalar px,SkScalar py)369 SkMatrix& 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 
postScale(SkScalar sx,SkScalar sy)378 SkMatrix& 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
postIDiv(int divx,int divy)389 bool 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 
setSinCos(SkScalar sinV,SkScalar cosV,SkScalar px,SkScalar py)411 SkMatrix& 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 
setRSXform(const SkRSXform & xform)429 SkMatrix& 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 
setSinCos(SkScalar sinV,SkScalar cosV)445 SkMatrix& 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 
setRotate(SkScalar degrees,SkScalar px,SkScalar py)461 SkMatrix& 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 
setRotate(SkScalar degrees)466 SkMatrix& SkMatrix::setRotate(SkScalar degrees) {
467     SkScalar rad = SkDegreesToRadians(degrees);
468     return this->setSinCos(SkScalarSinSnapToZero(rad), SkScalarCosSnapToZero(rad));
469 }
470 
preRotate(SkScalar degrees,SkScalar px,SkScalar py)471 SkMatrix& SkMatrix::preRotate(SkScalar degrees, SkScalar px, SkScalar py) {
472     SkMatrix    m;
473     m.setRotate(degrees, px, py);
474     return this->preConcat(m);
475 }
476 
preRotate(SkScalar degrees)477 SkMatrix& SkMatrix::preRotate(SkScalar degrees) {
478     SkMatrix    m;
479     m.setRotate(degrees);
480     return this->preConcat(m);
481 }
482 
postRotate(SkScalar degrees,SkScalar px,SkScalar py)483 SkMatrix& SkMatrix::postRotate(SkScalar degrees, SkScalar px, SkScalar py) {
484     SkMatrix    m;
485     m.setRotate(degrees, px, py);
486     return this->postConcat(m);
487 }
488 
postRotate(SkScalar degrees)489 SkMatrix& SkMatrix::postRotate(SkScalar degrees) {
490     SkMatrix    m;
491     m.setRotate(degrees);
492     return this->postConcat(m);
493 }
494 
495 ////////////////////////////////////////////////////////////////////////////////////
496 
setSkew(SkScalar sx,SkScalar sy,SkScalar px,SkScalar py)497 SkMatrix& 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 
setSkew(SkScalar sx,SkScalar sy)505 SkMatrix& 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 
preSkew(SkScalar sx,SkScalar sy,SkScalar px,SkScalar py)521 SkMatrix& 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 
preSkew(SkScalar sx,SkScalar sy)527 SkMatrix& SkMatrix::preSkew(SkScalar sx, SkScalar sy) {
528     SkMatrix    m;
529     m.setSkew(sx, sy);
530     return this->preConcat(m);
531 }
532 
postSkew(SkScalar sx,SkScalar sy,SkScalar px,SkScalar py)533 SkMatrix& 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 
postSkew(SkScalar sx,SkScalar sy)539 SkMatrix& SkMatrix::postSkew(SkScalar sx, SkScalar sy) {
540     SkMatrix    m;
541     m.setSkew(sx, sy);
542     return this->postConcat(m);
543 }
544 
545 ///////////////////////////////////////////////////////////////////////////////
546 
setRectToRect(const SkRect & src,const SkRect & dst,ScaleToFit align)547 bool 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 
muladdmul(float a,float b,float c,float d)600 static 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 
rowcol3(const float row[],const float col[])604 static 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 
only_scale_and_translate(unsigned mask)608 static bool only_scale_and_translate(unsigned mask) {
609     return 0 == (mask & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask));
610 }
611 
setConcat(const SkMatrix & a,const SkMatrix & b)612 SkMatrix& 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 
preConcat(const SkMatrix & mat)683 SkMatrix& 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 
postConcat(const SkMatrix & mat)692 SkMatrix& 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 
scross_dscale(SkScalar a,SkScalar b,SkScalar c,SkScalar d,double scale)709 static 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 
dcross(double a,double b,double c,double d)714 static inline double dcross(double a, double b, double c, double d) {
715     return a * b - c * d;
716 }
717 
dcross_dscale(double a,double b,double c,double d,double scale)718 static 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 
sk_determinant(const float mat[9],int isPerspective)723 static 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 
sk_inv_determinant(const float mat[9],int isPerspective)742 static 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 
SetAffineIdentity(SkScalar affine[6])755 void 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 
asAffine(SkScalar affine[6]) const764 bool 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 
mapPoints(SkPoint dst[],const SkPoint src[],int count) const779 void 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 
mapXY(SkScalar x,SkScalar y,SkPoint * result) const786 void SkMatrix::mapXY(SkScalar x, SkScalar y, SkPoint* result) const {
787     SkASSERT(result);
788     this->getMapXYProc()(*this, x, y, result);
789 }
790 
ComputeInv(SkScalar dst[9],const SkScalar src[9],double invDet,bool isPersp)791 void 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 
invertNonIdentity(SkMatrix * inv) const822 bool 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 
Identity_pts(const SkMatrix & m,SkPoint dst[],const SkPoint src[],int count)896 void 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 
Trans_pts(const SkMatrix & m,SkPoint dst[],const SkPoint src[],int count)904 void 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 
Scale_pts(const SkMatrix & m,SkPoint dst[],const SkPoint src[],int count)932 void 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         Sk4s trans4(tx, ty, tx, ty);
940         Sk4s scale4(sx, sy, sx, sy);
941         if (count & 1) {
942             Sk4s p(src->fX, src->fY, 0, 0);
943             p = p * scale4 + trans4;
944             dst->fX = p[0];
945             dst->fY = p[1];
946             src += 1;
947             dst += 1;
948         }
949         count >>= 1;
950         if (count & 1) {
951             (Sk4s::Load(src) * scale4 + trans4).store(dst);
952             src += 2;
953             dst += 2;
954         }
955         count >>= 1;
956         for (int i = 0; i < count; ++i) {
957             (Sk4s::Load(src+0) * scale4 + trans4).store(dst+0);
958             (Sk4s::Load(src+2) * scale4 + trans4).store(dst+2);
959             src += 4;
960             dst += 4;
961         }
962     }
963 }
964 
Persp_pts(const SkMatrix & m,SkPoint dst[],const SkPoint src[],int count)965 void SkMatrix::Persp_pts(const SkMatrix& m, SkPoint dst[],
966                          const SkPoint src[], int count) {
967     SkASSERT(m.hasPerspective());
968 
969     if (count > 0) {
970         do {
971             SkScalar sy = src->fY;
972             SkScalar sx = src->fX;
973             src += 1;
974 
975             SkScalar x = sdot(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX])  + m.fMat[kMTransX];
976             SkScalar y = sdot(sx, m.fMat[kMSkewY],  sy, m.fMat[kMScaleY]) + m.fMat[kMTransY];
977 #ifdef SK_LEGACY_MATRIX_MATH_ORDER
978             SkScalar z = sx * m.fMat[kMPersp0] + (sy * m.fMat[kMPersp1] + m.fMat[kMPersp2]);
979 #else
980             SkScalar z = sdot(sx, m.fMat[kMPersp0], sy, m.fMat[kMPersp1]) + m.fMat[kMPersp2];
981 #endif
982             if (z) {
983                 z = 1 / z;
984             }
985 
986             dst->fY = y * z;
987             dst->fX = x * z;
988             dst += 1;
989         } while (--count);
990     }
991 }
992 
Affine_vpts(const SkMatrix & m,SkPoint dst[],const SkPoint src[],int count)993 void SkMatrix::Affine_vpts(const SkMatrix& m, SkPoint dst[], const SkPoint src[], int count) {
994     SkASSERT(m.getType() != SkMatrix::kPerspective_Mask);
995     if (count > 0) {
996         SkScalar tx = m.getTranslateX();
997         SkScalar ty = m.getTranslateY();
998         SkScalar sx = m.getScaleX();
999         SkScalar sy = m.getScaleY();
1000         SkScalar kx = m.getSkewX();
1001         SkScalar ky = m.getSkewY();
1002         if (count & 1) {
1003             dst->set(src->fX * sx + src->fY * kx + tx,
1004                      src->fX * ky + src->fY * sy + ty);
1005             src += 1;
1006             dst += 1;
1007         }
1008         Sk4s trans4(tx, ty, tx, ty);
1009         Sk4s scale4(sx, sy, sx, sy);
1010         Sk4s  skew4(kx, ky, kx, ky);    // applied to swizzle of src4
1011         count >>= 1;
1012         for (int i = 0; i < count; ++i) {
1013             Sk4s src4 = Sk4s::Load(src);
1014             Sk4s swz4 = SkNx_shuffle<1,0,3,2>(src4);  // y0 x0, y1 x1
1015             (src4 * scale4 + swz4 * skew4 + trans4).store(dst);
1016             src += 2;
1017             dst += 2;
1018         }
1019     }
1020 }
1021 
1022 const SkMatrix::MapPtsProc SkMatrix::gMapPtsProcs[] = {
1023     SkMatrix::Identity_pts, SkMatrix::Trans_pts,
1024     SkMatrix::Scale_pts,    SkMatrix::Scale_pts,
1025     SkMatrix::Affine_vpts,  SkMatrix::Affine_vpts,
1026     SkMatrix::Affine_vpts,  SkMatrix::Affine_vpts,
1027     // repeat the persp proc 8 times
1028     SkMatrix::Persp_pts,    SkMatrix::Persp_pts,
1029     SkMatrix::Persp_pts,    SkMatrix::Persp_pts,
1030     SkMatrix::Persp_pts,    SkMatrix::Persp_pts,
1031     SkMatrix::Persp_pts,    SkMatrix::Persp_pts
1032 };
1033 
1034 ///////////////////////////////////////////////////////////////////////////////
1035 
MapHomogeneousPointsWithStride(const SkMatrix & mx,SkPoint3 dst[],size_t dstStride,const SkPoint3 src[],size_t srcStride,int count)1036 void SkMatrixPriv::MapHomogeneousPointsWithStride(const SkMatrix& mx, SkPoint3 dst[],
1037                                                   size_t dstStride, const SkPoint3 src[],
1038                                                   size_t srcStride, int count) {
1039     SkASSERT((dst && src && count > 0) || 0 == count);
1040     // no partial overlap
1041     SkASSERT(src == dst || &dst[count] <= &src[0] || &src[count] <= &dst[0]);
1042 
1043     if (count > 0) {
1044         if (mx.isIdentity()) {
1045             if (src != dst) {
1046                 if (srcStride == sizeof(SkPoint3) && dstStride == sizeof(SkPoint3)) {
1047                     memcpy(dst, src, count * sizeof(SkPoint3));
1048                 } else {
1049                     for (int i = 0; i < count; ++i) {
1050                         *dst = *src;
1051                         dst = reinterpret_cast<SkPoint3*>(reinterpret_cast<char*>(dst) + dstStride);
1052                         src = reinterpret_cast<const SkPoint3*>(reinterpret_cast<const char*>(src) +
1053                                                                 srcStride);
1054                     }
1055                 }
1056             }
1057             return;
1058         }
1059         do {
1060             SkScalar sx = src->fX;
1061             SkScalar sy = src->fY;
1062             SkScalar sw = src->fZ;
1063             src = reinterpret_cast<const SkPoint3*>(reinterpret_cast<const char*>(src) + srcStride);
1064             const SkScalar* mat = mx.fMat;
1065             typedef SkMatrix M;
1066             SkScalar x = sdot(sx, mat[M::kMScaleX], sy, mat[M::kMSkewX],  sw, mat[M::kMTransX]);
1067             SkScalar y = sdot(sx, mat[M::kMSkewY],  sy, mat[M::kMScaleY], sw, mat[M::kMTransY]);
1068             SkScalar w = sdot(sx, mat[M::kMPersp0], sy, mat[M::kMPersp1], sw, mat[M::kMPersp2]);
1069 
1070             dst->set(x, y, w);
1071             dst = reinterpret_cast<SkPoint3*>(reinterpret_cast<char*>(dst) + dstStride);
1072         } while (--count);
1073     }
1074 }
1075 
mapHomogeneousPoints(SkPoint3 dst[],const SkPoint3 src[],int count) const1076 void SkMatrix::mapHomogeneousPoints(SkPoint3 dst[], const SkPoint3 src[], int count) const {
1077     SkMatrixPriv::MapHomogeneousPointsWithStride(*this, dst, sizeof(SkPoint3), src,
1078                                                  sizeof(SkPoint3), count);
1079 }
1080 
mapHomogeneousPoints(SkPoint3 dst[],const SkPoint src[],int count) const1081 void SkMatrix::mapHomogeneousPoints(SkPoint3 dst[], const SkPoint src[], int count) const {
1082     if (this->isIdentity()) {
1083         for (int i = 0; i < count; ++i) {
1084             dst[i] = { src[i].fX, src[i].fY, 1 };
1085         }
1086     } else if (this->hasPerspective()) {
1087         for (int i = 0; i < count; ++i) {
1088             dst[i] = {
1089                 fMat[0] * src[i].fX + fMat[1] * src[i].fY + fMat[2],
1090                 fMat[3] * src[i].fX + fMat[4] * src[i].fY + fMat[5],
1091                 fMat[6] * src[i].fX + fMat[7] * src[i].fY + fMat[8],
1092             };
1093         }
1094     } else {    // affine
1095         for (int i = 0; i < count; ++i) {
1096             dst[i] = {
1097                 fMat[0] * src[i].fX + fMat[1] * src[i].fY + fMat[2],
1098                 fMat[3] * src[i].fX + fMat[4] * src[i].fY + fMat[5],
1099                 1,
1100             };
1101         }
1102     }
1103 }
1104 
1105 ///////////////////////////////////////////////////////////////////////////////
1106 
mapVectors(SkPoint dst[],const SkPoint src[],int count) const1107 void SkMatrix::mapVectors(SkPoint dst[], const SkPoint src[], int count) const {
1108     if (this->hasPerspective()) {
1109         SkPoint origin;
1110 
1111         MapXYProc proc = this->getMapXYProc();
1112         proc(*this, 0, 0, &origin);
1113 
1114         for (int i = count - 1; i >= 0; --i) {
1115             SkPoint tmp;
1116 
1117             proc(*this, src[i].fX, src[i].fY, &tmp);
1118             dst[i].set(tmp.fX - origin.fX, tmp.fY - origin.fY);
1119         }
1120     } else {
1121         SkMatrix tmp = *this;
1122 
1123         tmp.fMat[kMTransX] = tmp.fMat[kMTransY] = 0;
1124         tmp.clearTypeMask(kTranslate_Mask);
1125         tmp.mapPoints(dst, src, count);
1126     }
1127 }
1128 
sort_as_rect(const Sk4f & ltrb)1129 static Sk4f sort_as_rect(const Sk4f& ltrb) {
1130     Sk4f rblt(ltrb[2], ltrb[3], ltrb[0], ltrb[1]);
1131     Sk4f min = Sk4f::Min(ltrb, rblt);
1132     Sk4f max = Sk4f::Max(ltrb, rblt);
1133     // We can extract either pair [0,1] or [2,3] from min and max and be correct, but on
1134     // ARM this sequence generates the fastest (a single instruction).
1135     return Sk4f(min[2], min[3], max[0], max[1]);
1136 }
1137 
mapRectScaleTranslate(SkRect * dst,const SkRect & src) const1138 void SkMatrix::mapRectScaleTranslate(SkRect* dst, const SkRect& src) const {
1139     SkASSERT(dst);
1140     SkASSERT(this->isScaleTranslate());
1141 
1142     SkScalar sx = fMat[kMScaleX];
1143     SkScalar sy = fMat[kMScaleY];
1144     SkScalar tx = fMat[kMTransX];
1145     SkScalar ty = fMat[kMTransY];
1146     Sk4f scale(sx, sy, sx, sy);
1147     Sk4f trans(tx, ty, tx, ty);
1148     sort_as_rect(Sk4f::Load(&src.fLeft) * scale + trans).store(&dst->fLeft);
1149 }
1150 
mapRect(SkRect * dst,const SkRect & src,SkApplyPerspectiveClip pc) const1151 bool SkMatrix::mapRect(SkRect* dst, const SkRect& src, SkApplyPerspectiveClip pc) const {
1152     SkASSERT(dst);
1153 
1154     if (this->getType() <= kTranslate_Mask) {
1155         SkScalar tx = fMat[kMTransX];
1156         SkScalar ty = fMat[kMTransY];
1157         Sk4f trans(tx, ty, tx, ty);
1158         sort_as_rect(Sk4f::Load(&src.fLeft) + trans).store(&dst->fLeft);
1159         return true;
1160     }
1161     if (this->isScaleTranslate()) {
1162         this->mapRectScaleTranslate(dst, src);
1163         return true;
1164     } else if (pc == SkApplyPerspectiveClip::kYes && this->hasPerspective()) {
1165         SkPath path;
1166         path.addRect(src);
1167         path.transform(*this);
1168         *dst = path.getBounds();
1169         return false;
1170     } else {
1171         SkPoint quad[4];
1172 
1173         src.toQuad(quad);
1174         this->mapPoints(quad, quad, 4);
1175         dst->setBoundsNoCheck(quad, 4);
1176         return this->rectStaysRect();   // might still return true if rotated by 90, etc.
1177     }
1178 }
1179 
mapRadius(SkScalar radius) const1180 SkScalar SkMatrix::mapRadius(SkScalar radius) const {
1181     SkVector    vec[2];
1182 
1183     vec[0].set(radius, 0);
1184     vec[1].set(0, radius);
1185     this->mapVectors(vec, 2);
1186 
1187     SkScalar d0 = vec[0].length();
1188     SkScalar d1 = vec[1].length();
1189 
1190     // return geometric mean
1191     return SkScalarSqrt(d0 * d1);
1192 }
1193 
1194 ///////////////////////////////////////////////////////////////////////////////
1195 
Persp_xy(const SkMatrix & m,SkScalar sx,SkScalar sy,SkPoint * pt)1196 void SkMatrix::Persp_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
1197                         SkPoint* pt) {
1198     SkASSERT(m.hasPerspective());
1199 
1200     SkScalar x = sdot(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX])  + m.fMat[kMTransX];
1201     SkScalar y = sdot(sx, m.fMat[kMSkewY],  sy, m.fMat[kMScaleY]) + m.fMat[kMTransY];
1202     SkScalar z = sdot(sx, m.fMat[kMPersp0], sy, m.fMat[kMPersp1]) + m.fMat[kMPersp2];
1203     if (z) {
1204         z = 1 / z;
1205     }
1206     pt->fX = x * z;
1207     pt->fY = y * z;
1208 }
1209 
RotTrans_xy(const SkMatrix & m,SkScalar sx,SkScalar sy,SkPoint * pt)1210 void SkMatrix::RotTrans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
1211                            SkPoint* pt) {
1212     SkASSERT((m.getType() & (kAffine_Mask | kPerspective_Mask)) == kAffine_Mask);
1213 
1214 #ifdef SK_LEGACY_MATRIX_MATH_ORDER
1215     pt->fX = sx * m.fMat[kMScaleX] + (sy * m.fMat[kMSkewX]  +  m.fMat[kMTransX]);
1216     pt->fY = sx * m.fMat[kMSkewY]  + (sy * m.fMat[kMScaleY] + m.fMat[kMTransY]);
1217 #else
1218     pt->fX = sdot(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX])  + m.fMat[kMTransX];
1219     pt->fY = sdot(sx, m.fMat[kMSkewY],  sy, m.fMat[kMScaleY]) + m.fMat[kMTransY];
1220 #endif
1221 }
1222 
Rot_xy(const SkMatrix & m,SkScalar sx,SkScalar sy,SkPoint * pt)1223 void SkMatrix::Rot_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
1224                       SkPoint* pt) {
1225     SkASSERT((m.getType() & (kAffine_Mask | kPerspective_Mask))== kAffine_Mask);
1226     SkASSERT(0 == m.fMat[kMTransX]);
1227     SkASSERT(0 == m.fMat[kMTransY]);
1228 
1229 #ifdef SK_LEGACY_MATRIX_MATH_ORDER
1230     pt->fX = sx * m.fMat[kMScaleX] + (sy * m.fMat[kMSkewX]  + m.fMat[kMTransX]);
1231     pt->fY = sx * m.fMat[kMSkewY]  + (sy * m.fMat[kMScaleY] + m.fMat[kMTransY]);
1232 #else
1233     pt->fX = sdot(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX])  + m.fMat[kMTransX];
1234     pt->fY = sdot(sx, m.fMat[kMSkewY],  sy, m.fMat[kMScaleY]) + m.fMat[kMTransY];
1235 #endif
1236 }
1237 
ScaleTrans_xy(const SkMatrix & m,SkScalar sx,SkScalar sy,SkPoint * pt)1238 void SkMatrix::ScaleTrans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
1239                              SkPoint* pt) {
1240     SkASSERT((m.getType() & (kScale_Mask | kAffine_Mask | kPerspective_Mask))
1241              == kScale_Mask);
1242 
1243     pt->fX = sx * m.fMat[kMScaleX] + m.fMat[kMTransX];
1244     pt->fY = sy * m.fMat[kMScaleY] + m.fMat[kMTransY];
1245 }
1246 
Scale_xy(const SkMatrix & m,SkScalar sx,SkScalar sy,SkPoint * pt)1247 void SkMatrix::Scale_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
1248                         SkPoint* pt) {
1249     SkASSERT((m.getType() & (kScale_Mask | kAffine_Mask | kPerspective_Mask))
1250              == kScale_Mask);
1251     SkASSERT(0 == m.fMat[kMTransX]);
1252     SkASSERT(0 == m.fMat[kMTransY]);
1253 
1254     pt->fX = sx * m.fMat[kMScaleX];
1255     pt->fY = sy * m.fMat[kMScaleY];
1256 }
1257 
Trans_xy(const SkMatrix & m,SkScalar sx,SkScalar sy,SkPoint * pt)1258 void SkMatrix::Trans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
1259                         SkPoint* pt) {
1260     SkASSERT(m.getType() == kTranslate_Mask);
1261 
1262     pt->fX = sx + m.fMat[kMTransX];
1263     pt->fY = sy + m.fMat[kMTransY];
1264 }
1265 
Identity_xy(const SkMatrix & m,SkScalar sx,SkScalar sy,SkPoint * pt)1266 void SkMatrix::Identity_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
1267                            SkPoint* pt) {
1268     SkASSERT(0 == m.getType());
1269 
1270     pt->fX = sx;
1271     pt->fY = sy;
1272 }
1273 
1274 const SkMatrix::MapXYProc SkMatrix::gMapXYProcs[] = {
1275     SkMatrix::Identity_xy, SkMatrix::Trans_xy,
1276     SkMatrix::Scale_xy,    SkMatrix::ScaleTrans_xy,
1277     SkMatrix::Rot_xy,      SkMatrix::RotTrans_xy,
1278     SkMatrix::Rot_xy,      SkMatrix::RotTrans_xy,
1279     // repeat the persp proc 8 times
1280     SkMatrix::Persp_xy,    SkMatrix::Persp_xy,
1281     SkMatrix::Persp_xy,    SkMatrix::Persp_xy,
1282     SkMatrix::Persp_xy,    SkMatrix::Persp_xy,
1283     SkMatrix::Persp_xy,    SkMatrix::Persp_xy
1284 };
1285 
1286 ///////////////////////////////////////////////////////////////////////////////
1287 #if 0
1288 // if its nearly zero (just made up 26, perhaps it should be bigger or smaller)
1289 #define PerspNearlyZero(x)  SkScalarNearlyZero(x, (1.0f / (1 << 26)))
1290 
1291 bool SkMatrix::isFixedStepInX() const {
1292   return PerspNearlyZero(fMat[kMPersp0]);
1293 }
1294 
1295 SkVector SkMatrix::fixedStepInX(SkScalar y) const {
1296     SkASSERT(PerspNearlyZero(fMat[kMPersp0]));
1297     if (PerspNearlyZero(fMat[kMPersp1]) &&
1298         PerspNearlyZero(fMat[kMPersp2] - 1)) {
1299         return SkVector::Make(fMat[kMScaleX], fMat[kMSkewY]);
1300     } else {
1301         SkScalar z = y * fMat[kMPersp1] + fMat[kMPersp2];
1302         return SkVector::Make(fMat[kMScaleX] / z, fMat[kMSkewY] / z);
1303     }
1304 }
1305 #endif
1306 
1307 ///////////////////////////////////////////////////////////////////////////////
1308 
checkForZero(float x)1309 static inline bool checkForZero(float x) {
1310     return x*x == 0;
1311 }
1312 
Poly2Proc(const SkPoint srcPt[],SkMatrix * dst)1313 bool SkMatrix::Poly2Proc(const SkPoint srcPt[], SkMatrix* dst) {
1314     dst->fMat[kMScaleX] = srcPt[1].fY - srcPt[0].fY;
1315     dst->fMat[kMSkewY]  = srcPt[0].fX - srcPt[1].fX;
1316     dst->fMat[kMPersp0] = 0;
1317 
1318     dst->fMat[kMSkewX]  = srcPt[1].fX - srcPt[0].fX;
1319     dst->fMat[kMScaleY] = srcPt[1].fY - srcPt[0].fY;
1320     dst->fMat[kMPersp1] = 0;
1321 
1322     dst->fMat[kMTransX] = srcPt[0].fX;
1323     dst->fMat[kMTransY] = srcPt[0].fY;
1324     dst->fMat[kMPersp2] = 1;
1325     dst->setTypeMask(kUnknown_Mask);
1326     return true;
1327 }
1328 
Poly3Proc(const SkPoint srcPt[],SkMatrix * dst)1329 bool SkMatrix::Poly3Proc(const SkPoint srcPt[], SkMatrix* dst) {
1330     dst->fMat[kMScaleX] = srcPt[2].fX - srcPt[0].fX;
1331     dst->fMat[kMSkewY]  = srcPt[2].fY - srcPt[0].fY;
1332     dst->fMat[kMPersp0] = 0;
1333 
1334     dst->fMat[kMSkewX]  = srcPt[1].fX - srcPt[0].fX;
1335     dst->fMat[kMScaleY] = srcPt[1].fY - srcPt[0].fY;
1336     dst->fMat[kMPersp1] = 0;
1337 
1338     dst->fMat[kMTransX] = srcPt[0].fX;
1339     dst->fMat[kMTransY] = srcPt[0].fY;
1340     dst->fMat[kMPersp2] = 1;
1341     dst->setTypeMask(kUnknown_Mask);
1342     return true;
1343 }
1344 
Poly4Proc(const SkPoint srcPt[],SkMatrix * dst)1345 bool SkMatrix::Poly4Proc(const SkPoint srcPt[], SkMatrix* dst) {
1346     float   a1, a2;
1347     float   x0, y0, x1, y1, x2, y2;
1348 
1349     x0 = srcPt[2].fX - srcPt[0].fX;
1350     y0 = srcPt[2].fY - srcPt[0].fY;
1351     x1 = srcPt[2].fX - srcPt[1].fX;
1352     y1 = srcPt[2].fY - srcPt[1].fY;
1353     x2 = srcPt[2].fX - srcPt[3].fX;
1354     y2 = srcPt[2].fY - srcPt[3].fY;
1355 
1356     /* check if abs(x2) > abs(y2) */
1357     if ( x2 > 0 ? y2 > 0 ? x2 > y2 : x2 > -y2 : y2 > 0 ? -x2 > y2 : x2 < y2) {
1358         float denom = sk_ieee_float_divide(x1 * y2, x2) - y1;
1359         if (checkForZero(denom)) {
1360             return false;
1361         }
1362         a1 = (((x0 - x1) * y2 / x2) - y0 + y1) / denom;
1363     } else {
1364         float denom = x1 - sk_ieee_float_divide(y1 * x2, y2);
1365         if (checkForZero(denom)) {
1366             return false;
1367         }
1368         a1 = (x0 - x1 - sk_ieee_float_divide((y0 - y1) * x2, y2)) / denom;
1369     }
1370 
1371     /* check if abs(x1) > abs(y1) */
1372     if ( x1 > 0 ? y1 > 0 ? x1 > y1 : x1 > -y1 : y1 > 0 ? -x1 > y1 : x1 < y1) {
1373         float denom = y2 - sk_ieee_float_divide(x2 * y1, x1);
1374         if (checkForZero(denom)) {
1375             return false;
1376         }
1377         a2 = (y0 - y2 - sk_ieee_float_divide((x0 - x2) * y1, x1)) / denom;
1378     } else {
1379         float denom = sk_ieee_float_divide(y2 * x1, y1) - x2;
1380         if (checkForZero(denom)) {
1381             return false;
1382         }
1383         a2 = (sk_ieee_float_divide((y0 - y2) * x1, y1) - x0 + x2) / denom;
1384     }
1385 
1386     dst->fMat[kMScaleX] = a2 * srcPt[3].fX + srcPt[3].fX - srcPt[0].fX;
1387     dst->fMat[kMSkewY]  = a2 * srcPt[3].fY + srcPt[3].fY - srcPt[0].fY;
1388     dst->fMat[kMPersp0] = a2;
1389 
1390     dst->fMat[kMSkewX]  = a1 * srcPt[1].fX + srcPt[1].fX - srcPt[0].fX;
1391     dst->fMat[kMScaleY] = a1 * srcPt[1].fY + srcPt[1].fY - srcPt[0].fY;
1392     dst->fMat[kMPersp1] = a1;
1393 
1394     dst->fMat[kMTransX] = srcPt[0].fX;
1395     dst->fMat[kMTransY] = srcPt[0].fY;
1396     dst->fMat[kMPersp2] = 1;
1397     dst->setTypeMask(kUnknown_Mask);
1398     return true;
1399 }
1400 
1401 typedef bool (*PolyMapProc)(const SkPoint[], SkMatrix*);
1402 
1403 /*  Adapted from Rob Johnson's original sample code in QuickDraw GX
1404 */
setPolyToPoly(const SkPoint src[],const SkPoint dst[],int count)1405 bool SkMatrix::setPolyToPoly(const SkPoint src[], const SkPoint dst[], int count) {
1406     if ((unsigned)count > 4) {
1407         SkDebugf("--- SkMatrix::setPolyToPoly count out of range %d\n", count);
1408         return false;
1409     }
1410 
1411     if (0 == count) {
1412         this->reset();
1413         return true;
1414     }
1415     if (1 == count) {
1416         this->setTranslate(dst[0].fX - src[0].fX, dst[0].fY - src[0].fY);
1417         return true;
1418     }
1419 
1420     const PolyMapProc gPolyMapProcs[] = {
1421         SkMatrix::Poly2Proc, SkMatrix::Poly3Proc, SkMatrix::Poly4Proc
1422     };
1423     PolyMapProc proc = gPolyMapProcs[count - 2];
1424 
1425     SkMatrix tempMap, result;
1426 
1427     if (!proc(src, &tempMap)) {
1428         return false;
1429     }
1430     if (!tempMap.invert(&result)) {
1431         return false;
1432     }
1433     if (!proc(dst, &tempMap)) {
1434         return false;
1435     }
1436     this->setConcat(tempMap, result);
1437     return true;
1438 }
1439 
1440 ///////////////////////////////////////////////////////////////////////////////
1441 
1442 enum MinMaxOrBoth {
1443     kMin_MinMaxOrBoth,
1444     kMax_MinMaxOrBoth,
1445     kBoth_MinMaxOrBoth
1446 };
1447 
get_scale_factor(SkMatrix::TypeMask typeMask,const SkScalar m[9],SkScalar results[])1448 template <MinMaxOrBoth MIN_MAX_OR_BOTH> bool get_scale_factor(SkMatrix::TypeMask typeMask,
1449                                                               const SkScalar m[9],
1450                                                               SkScalar results[/*1 or 2*/]) {
1451     if (typeMask & SkMatrix::kPerspective_Mask) {
1452         return false;
1453     }
1454     if (SkMatrix::kIdentity_Mask == typeMask) {
1455         results[0] = SK_Scalar1;
1456         if (kBoth_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
1457             results[1] = SK_Scalar1;
1458         }
1459         return true;
1460     }
1461     if (!(typeMask & SkMatrix::kAffine_Mask)) {
1462         if (kMin_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
1463              results[0] = std::min(SkScalarAbs(m[SkMatrix::kMScaleX]),
1464                                    SkScalarAbs(m[SkMatrix::kMScaleY]));
1465         } else if (kMax_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
1466              results[0] = std::max(SkScalarAbs(m[SkMatrix::kMScaleX]),
1467                                    SkScalarAbs(m[SkMatrix::kMScaleY]));
1468         } else {
1469             results[0] = SkScalarAbs(m[SkMatrix::kMScaleX]);
1470             results[1] = SkScalarAbs(m[SkMatrix::kMScaleY]);
1471              if (results[0] > results[1]) {
1472                  using std::swap;
1473                  swap(results[0], results[1]);
1474              }
1475         }
1476         return true;
1477     }
1478     // ignore the translation part of the matrix, just look at 2x2 portion.
1479     // compute singular values, take largest or smallest abs value.
1480     // [a b; b c] = A^T*A
1481     SkScalar a = sdot(m[SkMatrix::kMScaleX], m[SkMatrix::kMScaleX],
1482                       m[SkMatrix::kMSkewY],  m[SkMatrix::kMSkewY]);
1483     SkScalar b = sdot(m[SkMatrix::kMScaleX], m[SkMatrix::kMSkewX],
1484                       m[SkMatrix::kMScaleY], m[SkMatrix::kMSkewY]);
1485     SkScalar c = sdot(m[SkMatrix::kMSkewX],  m[SkMatrix::kMSkewX],
1486                       m[SkMatrix::kMScaleY], m[SkMatrix::kMScaleY]);
1487     // eigenvalues of A^T*A are the squared singular values of A.
1488     // characteristic equation is det((A^T*A) - l*I) = 0
1489     // l^2 - (a + c)l + (ac-b^2)
1490     // solve using quadratic equation (divisor is non-zero since l^2 has 1 coeff
1491     // and roots are guaranteed to be pos and real).
1492     SkScalar bSqd = b * b;
1493     // if upper left 2x2 is orthogonal save some math
1494     if (bSqd <= SK_ScalarNearlyZero*SK_ScalarNearlyZero) {
1495         if (kMin_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
1496             results[0] = std::min(a, c);
1497         } else if (kMax_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
1498             results[0] = std::max(a, c);
1499         } else {
1500             results[0] = a;
1501             results[1] = c;
1502             if (results[0] > results[1]) {
1503                 using std::swap;
1504                 swap(results[0], results[1]);
1505             }
1506         }
1507     } else {
1508         SkScalar aminusc = a - c;
1509         SkScalar apluscdiv2 = SkScalarHalf(a + c);
1510         SkScalar x = SkScalarHalf(SkScalarSqrt(aminusc * aminusc + 4 * bSqd));
1511         if (kMin_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
1512             results[0] = apluscdiv2 - x;
1513         } else if (kMax_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
1514             results[0] = apluscdiv2 + x;
1515         } else {
1516             results[0] = apluscdiv2 - x;
1517             results[1] = apluscdiv2 + x;
1518         }
1519     }
1520     if (!SkScalarIsFinite(results[0])) {
1521         return false;
1522     }
1523     // Due to the floating point inaccuracy, there might be an error in a, b, c
1524     // calculated by sdot, further deepened by subsequent arithmetic operations
1525     // on them. Therefore, we allow and cap the nearly-zero negative values.
1526     if (results[0] < 0) {
1527         results[0] = 0;
1528     }
1529     results[0] = SkScalarSqrt(results[0]);
1530     if (kBoth_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
1531         if (!SkScalarIsFinite(results[1])) {
1532             return false;
1533         }
1534         if (results[1] < 0) {
1535             results[1] = 0;
1536         }
1537         results[1] = SkScalarSqrt(results[1]);
1538     }
1539     return true;
1540 }
1541 
getMinScale() const1542 SkScalar SkMatrix::getMinScale() const {
1543     SkScalar factor;
1544     if (get_scale_factor<kMin_MinMaxOrBoth>(this->getType(), fMat, &factor)) {
1545         return factor;
1546     } else {
1547         return -1;
1548     }
1549 }
1550 
getMaxScale() const1551 SkScalar SkMatrix::getMaxScale() const {
1552     SkScalar factor;
1553     if (get_scale_factor<kMax_MinMaxOrBoth>(this->getType(), fMat, &factor)) {
1554         return factor;
1555     } else {
1556         return -1;
1557     }
1558 }
1559 
getMinMaxScales(SkScalar scaleFactors[2]) const1560 bool SkMatrix::getMinMaxScales(SkScalar scaleFactors[2]) const {
1561     return get_scale_factor<kBoth_MinMaxOrBoth>(this->getType(), fMat, scaleFactors);
1562 }
1563 
I()1564 const SkMatrix& SkMatrix::I() {
1565     static constexpr SkMatrix identity;
1566     SkASSERT(identity.isIdentity());
1567     return identity;
1568 }
1569 
InvalidMatrix()1570 const SkMatrix& SkMatrix::InvalidMatrix() {
1571     static constexpr SkMatrix invalid(SK_ScalarMax, SK_ScalarMax, SK_ScalarMax,
1572                                       SK_ScalarMax, SK_ScalarMax, SK_ScalarMax,
1573                                       SK_ScalarMax, SK_ScalarMax, SK_ScalarMax,
1574                                       kTranslate_Mask | kScale_Mask |
1575                                       kAffine_Mask | kPerspective_Mask);
1576     return invalid;
1577 }
1578 
decomposeScale(SkSize * scale,SkMatrix * remaining) const1579 bool SkMatrix::decomposeScale(SkSize* scale, SkMatrix* remaining) const {
1580     if (this->hasPerspective()) {
1581         return false;
1582     }
1583 
1584     const SkScalar sx = SkVector::Length(this->getScaleX(), this->getSkewY());
1585     const SkScalar sy = SkVector::Length(this->getSkewX(), this->getScaleY());
1586     if (!SkScalarIsFinite(sx) || !SkScalarIsFinite(sy) ||
1587         SkScalarNearlyZero(sx) || SkScalarNearlyZero(sy)) {
1588         return false;
1589     }
1590 
1591     if (scale) {
1592         scale->set(sx, sy);
1593     }
1594     if (remaining) {
1595         *remaining = *this;
1596         remaining->preScale(SkScalarInvert(sx), SkScalarInvert(sy));
1597     }
1598     return true;
1599 }
1600 
1601 ///////////////////////////////////////////////////////////////////////////////
1602 
writeToMemory(void * buffer) const1603 size_t SkMatrix::writeToMemory(void* buffer) const {
1604     // TODO write less for simple matrices
1605     static const size_t sizeInMemory = 9 * sizeof(SkScalar);
1606     if (buffer) {
1607         memcpy(buffer, fMat, sizeInMemory);
1608     }
1609     return sizeInMemory;
1610 }
1611 
readFromMemory(const void * buffer,size_t length)1612 size_t SkMatrix::readFromMemory(const void* buffer, size_t length) {
1613     static const size_t sizeInMemory = 9 * sizeof(SkScalar);
1614     if (length < sizeInMemory) {
1615         return 0;
1616     }
1617     memcpy(fMat, buffer, sizeInMemory);
1618     this->setTypeMask(kUnknown_Mask);
1619     // Figure out the type now so that we're thread-safe
1620     (void)this->getType();
1621     return sizeInMemory;
1622 }
1623 
dump() const1624 void SkMatrix::dump() const {
1625     SkString str;
1626     str.appendf("[%8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f]",
1627              fMat[0], fMat[1], fMat[2], fMat[3], fMat[4], fMat[5],
1628              fMat[6], fMat[7], fMat[8]);
1629     SkDebugf("%s\n", str.c_str());
1630 }
1631 
1632 ///////////////////////////////////////////////////////////////////////////////
1633 
1634 #include "src/core/SkMatrixUtils.h"
1635 #include "src/core/SkSamplingPriv.h"
1636 
SkTreatAsSprite(const SkMatrix & mat,const SkISize & size,const SkSamplingOptions & sampling,const SkPaint & paint)1637 bool SkTreatAsSprite(const SkMatrix& mat, const SkISize& size, const SkSamplingOptions& sampling,
1638                      const SkPaint& paint) {
1639     if (!SkSamplingPriv::NoChangeWithIdentityMatrix(sampling)) {
1640         return false;
1641     }
1642 
1643     // Our path aa is 2-bits, and our rect aa is 8, so we could use 8,
1644     // but in practice 4 seems enough (still looks smooth) and allows
1645     // more slightly fractional cases to fall into the fast (sprite) case.
1646     static const unsigned kAntiAliasSubpixelBits = 4;
1647 
1648     const unsigned subpixelBits = paint.isAntiAlias() ? kAntiAliasSubpixelBits : 0;
1649 
1650     // quick reject on affine or perspective
1651     if (mat.getType() & ~(SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask)) {
1652         return false;
1653     }
1654 
1655     // quick success check
1656     if (!subpixelBits && !(mat.getType() & ~SkMatrix::kTranslate_Mask)) {
1657         return true;
1658     }
1659 
1660     // mapRect supports negative scales, so we eliminate those first
1661     if (mat.getScaleX() < 0 || mat.getScaleY() < 0) {
1662         return false;
1663     }
1664 
1665     SkRect dst;
1666     SkIRect isrc = SkIRect::MakeSize(size);
1667 
1668     {
1669         SkRect src;
1670         src.set(isrc);
1671         mat.mapRect(&dst, src);
1672     }
1673 
1674     // just apply the translate to isrc
1675     isrc.offset(SkScalarRoundToInt(mat.getTranslateX()),
1676                 SkScalarRoundToInt(mat.getTranslateY()));
1677 
1678     if (subpixelBits) {
1679         isrc.fLeft = SkLeftShift(isrc.fLeft, subpixelBits);
1680         isrc.fTop = SkLeftShift(isrc.fTop, subpixelBits);
1681         isrc.fRight = SkLeftShift(isrc.fRight, subpixelBits);
1682         isrc.fBottom = SkLeftShift(isrc.fBottom, subpixelBits);
1683 
1684         const float scale = 1 << subpixelBits;
1685         dst.fLeft *= scale;
1686         dst.fTop *= scale;
1687         dst.fRight *= scale;
1688         dst.fBottom *= scale;
1689     }
1690 
1691     SkIRect idst;
1692     dst.round(&idst);
1693     return isrc == idst;
1694 }
1695 
1696 // A square matrix M can be decomposed (via polar decomposition) into two matrices --
1697 // an orthogonal matrix Q and a symmetric matrix S. In turn we can decompose S into U*W*U^T,
1698 // where U is another orthogonal matrix and W is a scale matrix. These can be recombined
1699 // to give M = (Q*U)*W*U^T, i.e., the product of two orthogonal matrices and a scale matrix.
1700 //
1701 // The one wrinkle is that traditionally Q may contain a reflection -- the
1702 // calculation has been rejiggered to put that reflection into W.
SkDecomposeUpper2x2(const SkMatrix & matrix,SkPoint * rotation1,SkPoint * scale,SkPoint * rotation2)1703 bool SkDecomposeUpper2x2(const SkMatrix& matrix,
1704                          SkPoint* rotation1,
1705                          SkPoint* scale,
1706                          SkPoint* rotation2) {
1707 
1708     SkScalar A = matrix[SkMatrix::kMScaleX];
1709     SkScalar B = matrix[SkMatrix::kMSkewX];
1710     SkScalar C = matrix[SkMatrix::kMSkewY];
1711     SkScalar D = matrix[SkMatrix::kMScaleY];
1712 
1713     if (is_degenerate_2x2(A, B, C, D)) {
1714         return false;
1715     }
1716 
1717     double w1, w2;
1718     SkScalar cos1, sin1;
1719     SkScalar cos2, sin2;
1720 
1721     // do polar decomposition (M = Q*S)
1722     SkScalar cosQ, sinQ;
1723     double Sa, Sb, Sd;
1724     // if M is already symmetric (i.e., M = I*S)
1725     if (SkScalarNearlyEqual(B, C)) {
1726         cosQ = 1;
1727         sinQ = 0;
1728 
1729         Sa = A;
1730         Sb = B;
1731         Sd = D;
1732     } else {
1733         cosQ = A + D;
1734         sinQ = C - B;
1735         SkScalar reciplen = SkScalarInvert(SkScalarSqrt(cosQ*cosQ + sinQ*sinQ));
1736         cosQ *= reciplen;
1737         sinQ *= reciplen;
1738 
1739         // S = Q^-1*M
1740         // we don't calc Sc since it's symmetric
1741         Sa = A*cosQ + C*sinQ;
1742         Sb = B*cosQ + D*sinQ;
1743         Sd = -B*sinQ + D*cosQ;
1744     }
1745 
1746     // Now we need to compute eigenvalues of S (our scale factors)
1747     // and eigenvectors (bases for our rotation)
1748     // From this, should be able to reconstruct S as U*W*U^T
1749     if (SkScalarNearlyZero(SkDoubleToScalar(Sb))) {
1750         // already diagonalized
1751         cos1 = 1;
1752         sin1 = 0;
1753         w1 = Sa;
1754         w2 = Sd;
1755         cos2 = cosQ;
1756         sin2 = sinQ;
1757     } else {
1758         double diff = Sa - Sd;
1759         double discriminant = sqrt(diff*diff + 4.0*Sb*Sb);
1760         double trace = Sa + Sd;
1761         if (diff > 0) {
1762             w1 = 0.5*(trace + discriminant);
1763             w2 = 0.5*(trace - discriminant);
1764         } else {
1765             w1 = 0.5*(trace - discriminant);
1766             w2 = 0.5*(trace + discriminant);
1767         }
1768 
1769         cos1 = SkDoubleToScalar(Sb); sin1 = SkDoubleToScalar(w1 - Sa);
1770         SkScalar reciplen = SkScalarInvert(SkScalarSqrt(cos1*cos1 + sin1*sin1));
1771         cos1 *= reciplen;
1772         sin1 *= reciplen;
1773 
1774         // rotation 2 is composition of Q and U
1775         cos2 = cos1*cosQ - sin1*sinQ;
1776         sin2 = sin1*cosQ + cos1*sinQ;
1777 
1778         // rotation 1 is U^T
1779         sin1 = -sin1;
1780     }
1781 
1782     if (scale) {
1783         scale->fX = SkDoubleToScalar(w1);
1784         scale->fY = SkDoubleToScalar(w2);
1785     }
1786     if (rotation1) {
1787         rotation1->fX = cos1;
1788         rotation1->fY = sin1;
1789     }
1790     if (rotation2) {
1791         rotation2->fX = cos2;
1792         rotation2->fY = sin2;
1793     }
1794 
1795     return true;
1796 }
1797 
1798 //////////////////////////////////////////////////////////////////////////////////////////////////
1799 
toQuad(SkScalar width,SkScalar height,SkPoint quad[4]) const1800 void SkRSXform::toQuad(SkScalar width, SkScalar height, SkPoint quad[4]) const {
1801 #if 0
1802     // This is the slow way, but it documents what we're doing
1803     quad[0].set(0, 0);
1804     quad[1].set(width, 0);
1805     quad[2].set(width, height);
1806     quad[3].set(0, height);
1807     SkMatrix m;
1808     m.setRSXform(*this).mapPoints(quad, quad, 4);
1809 #else
1810     const SkScalar m00 = fSCos;
1811     const SkScalar m01 = -fSSin;
1812     const SkScalar m02 = fTx;
1813     const SkScalar m10 = -m01;
1814     const SkScalar m11 = m00;
1815     const SkScalar m12 = fTy;
1816 
1817     quad[0].set(m02, m12);
1818     quad[1].set(m00 * width + m02, m10 * width + m12);
1819     quad[2].set(m00 * width + m01 * height + m02, m10 * width + m11 * height + m12);
1820     quad[3].set(m01 * height + m02, m11 * height + m12);
1821 #endif
1822 }
1823 
toTriStrip(SkScalar width,SkScalar height,SkPoint strip[4]) const1824 void SkRSXform::toTriStrip(SkScalar width, SkScalar height, SkPoint strip[4]) const {
1825     const SkScalar m00 = fSCos;
1826     const SkScalar m01 = -fSSin;
1827     const SkScalar m02 = fTx;
1828     const SkScalar m10 = -m01;
1829     const SkScalar m11 = m00;
1830     const SkScalar m12 = fTy;
1831 
1832     strip[0].set(m02, m12);
1833     strip[1].set(m01 * height + m02, m11 * height + m12);
1834     strip[2].set(m00 * width + m02, m10 * width + m12);
1835     strip[3].set(m00 * width + m01 * height + m02, m10 * width + m11 * height + m12);
1836 }
1837 
1838 ///////////////////////////////////////////////////////////////////////////////////////////////////
1839 
DifferentialAreaScale(const SkMatrix & m,const SkPoint & p)1840 SkScalar SkMatrixPriv::DifferentialAreaScale(const SkMatrix& m, const SkPoint& p) {
1841     //              [m00 m01 m02]                                 [f(u,v)]
1842     // Assuming M = [m10 m11 m12], define the projected p'(u,v) = [g(u,v)] where
1843     //              [m20 m12 m22]
1844     //                                                        [x]     [u]
1845     // f(u,v) = x(u,v) / w(u,v), g(u,v) = y(u,v) / w(u,v) and [y] = M*[v]
1846     //                                                        [w]     [1]
1847     //
1848     // Then the differential scale factor between p = (u,v) and p' is |det J|,
1849     // where J is the Jacobian for p': [df/du dg/du]
1850     //                                 [df/dv dg/dv]
1851     // and df/du = (w*dx/du - x*dw/du)/w^2,   dg/du = (w*dy/du - y*dw/du)/w^2
1852     //     df/dv = (w*dx/dv - x*dw/dv)/w^2,   dg/dv = (w*dy/dv - y*dw/dv)/w^2
1853     //
1854     // From here, |det J| can be rewritten as |det J'/w^3|, where
1855     //      [x     y     w    ]   [x   y   w  ]
1856     // J' = [dx/du dy/du dw/du] = [m00 m10 m20]
1857     //      [dx/dv dy/dv dw/dv]   [m01 m11 m21]
1858     SkPoint3 xyw;
1859     m.mapHomogeneousPoints(&xyw, &p, 1);
1860 
1861     if (xyw.fZ < SK_ScalarNearlyZero) {
1862         // Reaching the discontinuity of xy/w and where the point would clip to w >= 0
1863         return SK_ScalarInfinity;
1864     }
1865     SkMatrix jacobian = SkMatrix::MakeAll(xyw.fX, xyw.fY, xyw.fZ,
1866                                           m.getScaleX(), m.getSkewY(), m.getPerspX(),
1867                                           m.getSkewX(), m.getScaleY(), m.getPerspY());
1868 
1869     double denom = 1.0 / xyw.fZ;   // 1/w
1870     denom = denom * denom * denom; // 1/w^3
1871     return SkScalarAbs(SkDoubleToScalar(sk_determinant(jacobian.fMat, true) * denom));
1872 }
1873