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