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