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