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 
1271 #include "SkPerspIter.h"
1272 
SkPerspIter(const SkMatrix & m,SkScalar x0,SkScalar y0,int count)1273 SkPerspIter::SkPerspIter(const SkMatrix& m, SkScalar x0, SkScalar y0, int count)
1274         : fMatrix(m), fSX(x0), fSY(y0), fCount(count) {
1275     SkPoint pt;
1276 
1277     SkMatrix::Persp_xy(m, x0, y0, &pt);
1278     fX = SkScalarToFixed(pt.fX);
1279     fY = SkScalarToFixed(pt.fY);
1280 }
1281 
next()1282 int SkPerspIter::next() {
1283     int n = fCount;
1284 
1285     if (0 == n) {
1286         return 0;
1287     }
1288     SkPoint pt;
1289     SkFixed x = fX;
1290     SkFixed y = fY;
1291     SkFixed dx, dy;
1292 
1293     if (n >= kCount) {
1294         n = kCount;
1295         fSX += SkIntToScalar(kCount);
1296         SkMatrix::Persp_xy(fMatrix, fSX, fSY, &pt);
1297         fX = SkScalarToFixed(pt.fX);
1298         fY = SkScalarToFixed(pt.fY);
1299         dx = (fX - x) >> kShift;
1300         dy = (fY - y) >> kShift;
1301     } else {
1302         fSX += SkIntToScalar(n);
1303         SkMatrix::Persp_xy(fMatrix, fSX, fSY, &pt);
1304         fX = SkScalarToFixed(pt.fX);
1305         fY = SkScalarToFixed(pt.fY);
1306         dx = (fX - x) / n;
1307         dy = (fY - y) / n;
1308     }
1309 
1310     SkFixed* p = fStorage;
1311     for (int i = 0; i < n; i++) {
1312         *p++ = x; x += dx;
1313         *p++ = y; y += dy;
1314     }
1315 
1316     fCount -= n;
1317     return n;
1318 }
1319 
1320 ///////////////////////////////////////////////////////////////////////////////
1321 
checkForZero(float x)1322 static inline bool checkForZero(float x) {
1323     return x*x == 0;
1324 }
1325 
poly_to_point(SkPoint * pt,const SkPoint poly[],int count)1326 static inline bool poly_to_point(SkPoint* pt, const SkPoint poly[], int count) {
1327     float   x = 1, y = 1;
1328     SkPoint pt1, pt2;
1329 
1330     if (count > 1) {
1331         pt1.fX = poly[1].fX - poly[0].fX;
1332         pt1.fY = poly[1].fY - poly[0].fY;
1333         y = SkPoint::Length(pt1.fX, pt1.fY);
1334         if (checkForZero(y)) {
1335             return false;
1336         }
1337         switch (count) {
1338             case 2:
1339                 break;
1340             case 3:
1341                 pt2.fX = poly[0].fY - poly[2].fY;
1342                 pt2.fY = poly[2].fX - poly[0].fX;
1343                 goto CALC_X;
1344             default:
1345                 pt2.fX = poly[0].fY - poly[3].fY;
1346                 pt2.fY = poly[3].fX - poly[0].fX;
1347             CALC_X:
1348                 x = sdot(pt1.fX, pt2.fX, pt1.fY, pt2.fY) / y;
1349                 break;
1350         }
1351     }
1352     pt->set(x, y);
1353     return true;
1354 }
1355 
Poly2Proc(const SkPoint srcPt[],SkMatrix * dst,const SkPoint & scale)1356 bool SkMatrix::Poly2Proc(const SkPoint srcPt[], SkMatrix* dst,
1357                          const SkPoint& scale) {
1358     float invScale = 1 / scale.fY;
1359 
1360     dst->fMat[kMScaleX] = (srcPt[1].fY - srcPt[0].fY) * invScale;
1361     dst->fMat[kMSkewY] = (srcPt[0].fX - srcPt[1].fX) * invScale;
1362     dst->fMat[kMPersp0] = 0;
1363     dst->fMat[kMSkewX] = (srcPt[1].fX - srcPt[0].fX) * invScale;
1364     dst->fMat[kMScaleY] = (srcPt[1].fY - srcPt[0].fY) * invScale;
1365     dst->fMat[kMPersp1] = 0;
1366     dst->fMat[kMTransX] = srcPt[0].fX;
1367     dst->fMat[kMTransY] = srcPt[0].fY;
1368     dst->fMat[kMPersp2] = 1;
1369     dst->setTypeMask(kUnknown_Mask);
1370     return true;
1371 }
1372 
Poly3Proc(const SkPoint srcPt[],SkMatrix * dst,const SkPoint & scale)1373 bool SkMatrix::Poly3Proc(const SkPoint srcPt[], SkMatrix* dst,
1374                          const SkPoint& scale) {
1375     float invScale = 1 / scale.fX;
1376     dst->fMat[kMScaleX] = (srcPt[2].fX - srcPt[0].fX) * invScale;
1377     dst->fMat[kMSkewY] = (srcPt[2].fY - srcPt[0].fY) * invScale;
1378     dst->fMat[kMPersp0] = 0;
1379 
1380     invScale = 1 / scale.fY;
1381     dst->fMat[kMSkewX] = (srcPt[1].fX - srcPt[0].fX) * invScale;
1382     dst->fMat[kMScaleY] = (srcPt[1].fY - srcPt[0].fY) * invScale;
1383     dst->fMat[kMPersp1] = 0;
1384 
1385     dst->fMat[kMTransX] = srcPt[0].fX;
1386     dst->fMat[kMTransY] = srcPt[0].fY;
1387     dst->fMat[kMPersp2] = 1;
1388     dst->setTypeMask(kUnknown_Mask);
1389     return true;
1390 }
1391 
Poly4Proc(const SkPoint srcPt[],SkMatrix * dst,const SkPoint & scale)1392 bool SkMatrix::Poly4Proc(const SkPoint srcPt[], SkMatrix* dst,
1393                          const SkPoint& scale) {
1394     float   a1, a2;
1395     float   x0, y0, x1, y1, x2, y2;
1396 
1397     x0 = srcPt[2].fX - srcPt[0].fX;
1398     y0 = srcPt[2].fY - srcPt[0].fY;
1399     x1 = srcPt[2].fX - srcPt[1].fX;
1400     y1 = srcPt[2].fY - srcPt[1].fY;
1401     x2 = srcPt[2].fX - srcPt[3].fX;
1402     y2 = srcPt[2].fY - srcPt[3].fY;
1403 
1404     /* check if abs(x2) > abs(y2) */
1405     if ( x2 > 0 ? y2 > 0 ? x2 > y2 : x2 > -y2 : y2 > 0 ? -x2 > y2 : x2 < y2) {
1406         float denom = (x1 * y2 / x2) - y1;
1407         if (checkForZero(denom)) {
1408             return false;
1409         }
1410         a1 = (((x0 - x1) * y2 / x2) - y0 + y1) / denom;
1411     } else {
1412         float denom = x1 - (y1 * x2 / y2);
1413         if (checkForZero(denom)) {
1414             return false;
1415         }
1416         a1 = (x0 - x1 - ((y0 - y1) * x2 / y2)) / denom;
1417     }
1418 
1419     /* check if abs(x1) > abs(y1) */
1420     if ( x1 > 0 ? y1 > 0 ? x1 > y1 : x1 > -y1 : y1 > 0 ? -x1 > y1 : x1 < y1) {
1421         float denom = y2 - (x2 * y1 / x1);
1422         if (checkForZero(denom)) {
1423             return false;
1424         }
1425         a2 = (y0 - y2 - ((x0 - x2) * y1 / x1)) / denom;
1426     } else {
1427         float denom = (y2 * x1 / y1) - x2;
1428         if (checkForZero(denom)) {
1429             return false;
1430         }
1431         a2 = (((y0 - y2) * x1 / y1) - x0 + x2) / denom;
1432     }
1433 
1434     float invScale = SkScalarInvert(scale.fX);
1435     dst->fMat[kMScaleX] = (a2 * srcPt[3].fX + srcPt[3].fX - srcPt[0].fX) * invScale;
1436     dst->fMat[kMSkewY]  = (a2 * srcPt[3].fY + srcPt[3].fY - srcPt[0].fY) * invScale;
1437     dst->fMat[kMPersp0] = a2 * invScale;
1438 
1439     invScale = SkScalarInvert(scale.fY);
1440     dst->fMat[kMSkewX]  = (a1 * srcPt[1].fX + srcPt[1].fX - srcPt[0].fX) * invScale;
1441     dst->fMat[kMScaleY] = (a1 * srcPt[1].fY + srcPt[1].fY - srcPt[0].fY) * invScale;
1442     dst->fMat[kMPersp1] = a1 * invScale;
1443 
1444     dst->fMat[kMTransX] = srcPt[0].fX;
1445     dst->fMat[kMTransY] = srcPt[0].fY;
1446     dst->fMat[kMPersp2] = 1;
1447     dst->setTypeMask(kUnknown_Mask);
1448     return true;
1449 }
1450 
1451 typedef bool (*PolyMapProc)(const SkPoint[], SkMatrix*, const SkPoint&);
1452 
1453 /*  Taken from Rob Johnson's original sample code in QuickDraw GX
1454 */
setPolyToPoly(const SkPoint src[],const SkPoint dst[],int count)1455 bool SkMatrix::setPolyToPoly(const SkPoint src[], const SkPoint dst[],
1456                              int count) {
1457     if ((unsigned)count > 4) {
1458         SkDebugf("--- SkMatrix::setPolyToPoly count out of range %d\n", count);
1459         return false;
1460     }
1461 
1462     if (0 == count) {
1463         this->reset();
1464         return true;
1465     }
1466     if (1 == count) {
1467         this->setTranslate(dst[0].fX - src[0].fX, dst[0].fY - src[0].fY);
1468         return true;
1469     }
1470 
1471     SkPoint scale;
1472     if (!poly_to_point(&scale, src, count) ||
1473             SkScalarNearlyZero(scale.fX) ||
1474             SkScalarNearlyZero(scale.fY)) {
1475         return false;
1476     }
1477 
1478     static const PolyMapProc gPolyMapProcs[] = {
1479         SkMatrix::Poly2Proc, SkMatrix::Poly3Proc, SkMatrix::Poly4Proc
1480     };
1481     PolyMapProc proc = gPolyMapProcs[count - 2];
1482 
1483     SkMatrix tempMap, result;
1484     tempMap.setTypeMask(kUnknown_Mask);
1485 
1486     if (!proc(src, &tempMap, scale)) {
1487         return false;
1488     }
1489     if (!tempMap.invert(&result)) {
1490         return false;
1491     }
1492     if (!proc(dst, &tempMap, scale)) {
1493         return false;
1494     }
1495     this->setConcat(tempMap, result);
1496     return true;
1497 }
1498 
1499 ///////////////////////////////////////////////////////////////////////////////
1500 
1501 enum MinMaxOrBoth {
1502     kMin_MinMaxOrBoth,
1503     kMax_MinMaxOrBoth,
1504     kBoth_MinMaxOrBoth
1505 };
1506 
get_scale_factor(SkMatrix::TypeMask typeMask,const SkScalar m[9],SkScalar results[])1507 template <MinMaxOrBoth MIN_MAX_OR_BOTH> bool get_scale_factor(SkMatrix::TypeMask typeMask,
1508                                                               const SkScalar m[9],
1509                                                               SkScalar results[/*1 or 2*/]) {
1510     if (typeMask & SkMatrix::kPerspective_Mask) {
1511         return false;
1512     }
1513     if (SkMatrix::kIdentity_Mask == typeMask) {
1514         results[0] = SK_Scalar1;
1515         if (kBoth_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
1516             results[1] = SK_Scalar1;
1517         }
1518         return true;
1519     }
1520     if (!(typeMask & SkMatrix::kAffine_Mask)) {
1521         if (kMin_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
1522              results[0] = SkMinScalar(SkScalarAbs(m[SkMatrix::kMScaleX]),
1523                                       SkScalarAbs(m[SkMatrix::kMScaleY]));
1524         } else if (kMax_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
1525              results[0] = SkMaxScalar(SkScalarAbs(m[SkMatrix::kMScaleX]),
1526                                       SkScalarAbs(m[SkMatrix::kMScaleY]));
1527         } else {
1528             results[0] = SkScalarAbs(m[SkMatrix::kMScaleX]);
1529             results[1] = SkScalarAbs(m[SkMatrix::kMScaleY]);
1530              if (results[0] > results[1]) {
1531                  SkTSwap(results[0], results[1]);
1532              }
1533         }
1534         return true;
1535     }
1536     // ignore the translation part of the matrix, just look at 2x2 portion.
1537     // compute singular values, take largest or smallest abs value.
1538     // [a b; b c] = A^T*A
1539     SkScalar a = sdot(m[SkMatrix::kMScaleX], m[SkMatrix::kMScaleX],
1540                       m[SkMatrix::kMSkewY],  m[SkMatrix::kMSkewY]);
1541     SkScalar b = sdot(m[SkMatrix::kMScaleX], m[SkMatrix::kMSkewX],
1542                       m[SkMatrix::kMScaleY], m[SkMatrix::kMSkewY]);
1543     SkScalar c = sdot(m[SkMatrix::kMSkewX],  m[SkMatrix::kMSkewX],
1544                       m[SkMatrix::kMScaleY], m[SkMatrix::kMScaleY]);
1545     // eigenvalues of A^T*A are the squared singular values of A.
1546     // characteristic equation is det((A^T*A) - l*I) = 0
1547     // l^2 - (a + c)l + (ac-b^2)
1548     // solve using quadratic equation (divisor is non-zero since l^2 has 1 coeff
1549     // and roots are guaranteed to be pos and real).
1550     SkScalar bSqd = b * b;
1551     // if upper left 2x2 is orthogonal save some math
1552     if (bSqd <= SK_ScalarNearlyZero*SK_ScalarNearlyZero) {
1553         if (kMin_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
1554             results[0] = SkMinScalar(a, c);
1555         } else if (kMax_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
1556             results[0] = SkMaxScalar(a, c);
1557         } else {
1558             results[0] = a;
1559             results[1] = c;
1560             if (results[0] > results[1]) {
1561                 SkTSwap(results[0], results[1]);
1562             }
1563         }
1564     } else {
1565         SkScalar aminusc = a - c;
1566         SkScalar apluscdiv2 = SkScalarHalf(a + c);
1567         SkScalar x = SkScalarHalf(SkScalarSqrt(aminusc * aminusc + 4 * bSqd));
1568         if (kMin_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
1569             results[0] = apluscdiv2 - x;
1570         } else if (kMax_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
1571             results[0] = apluscdiv2 + x;
1572         } else {
1573             results[0] = apluscdiv2 - x;
1574             results[1] = apluscdiv2 + x;
1575         }
1576     }
1577     if (!SkScalarIsFinite(results[0])) {
1578         return false;
1579     }
1580     // Due to the floating point inaccuracy, there might be an error in a, b, c
1581     // calculated by sdot, further deepened by subsequent arithmetic operations
1582     // on them. Therefore, we allow and cap the nearly-zero negative values.
1583     SkASSERT(results[0] >= -SK_ScalarNearlyZero);
1584     if (results[0] < 0) {
1585         results[0] = 0;
1586     }
1587     results[0] = SkScalarSqrt(results[0]);
1588     if (kBoth_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
1589         if (!SkScalarIsFinite(results[1])) {
1590             return false;
1591         }
1592         SkASSERT(results[1] >= -SK_ScalarNearlyZero);
1593         if (results[1] < 0) {
1594             results[1] = 0;
1595         }
1596         results[1] = SkScalarSqrt(results[1]);
1597     }
1598     return true;
1599 }
1600 
getMinScale() const1601 SkScalar SkMatrix::getMinScale() const {
1602     SkScalar factor;
1603     if (get_scale_factor<kMin_MinMaxOrBoth>(this->getType(), fMat, &factor)) {
1604         return factor;
1605     } else {
1606         return -1;
1607     }
1608 }
1609 
getMaxScale() const1610 SkScalar SkMatrix::getMaxScale() const {
1611     SkScalar factor;
1612     if (get_scale_factor<kMax_MinMaxOrBoth>(this->getType(), fMat, &factor)) {
1613         return factor;
1614     } else {
1615         return -1;
1616     }
1617 }
1618 
getMinMaxScales(SkScalar scaleFactors[2]) const1619 bool SkMatrix::getMinMaxScales(SkScalar scaleFactors[2]) const {
1620     return get_scale_factor<kBoth_MinMaxOrBoth>(this->getType(), fMat, scaleFactors);
1621 }
1622 
1623 namespace {
1624 
1625 // SkMatrix is C++11 POD (trivial and standard-layout), but not aggregate (it has private fields).
1626 struct AggregateMatrix {
1627     SkScalar matrix[9];
1628     uint32_t typemask;
1629 
asSkMatrix__anon2741cf7b0211::AggregateMatrix1630     const SkMatrix& asSkMatrix() const { return *reinterpret_cast<const SkMatrix*>(this); }
1631 };
1632 static_assert(sizeof(AggregateMatrix) == sizeof(SkMatrix), "AggregateMatrix size mismatch.");
1633 
1634 }  // namespace
1635 
I()1636 const SkMatrix& SkMatrix::I() {
1637     static_assert(offsetof(SkMatrix,fMat)      == offsetof(AggregateMatrix,matrix),   "fMat");
1638     static_assert(offsetof(SkMatrix,fTypeMask) == offsetof(AggregateMatrix,typemask), "fTypeMask");
1639 
1640     static const AggregateMatrix identity = { {SK_Scalar1, 0, 0,
1641                                                0, SK_Scalar1, 0,
1642                                                0, 0, SK_Scalar1 },
1643                                              kIdentity_Mask | kRectStaysRect_Mask};
1644     SkASSERT(identity.asSkMatrix().isIdentity());
1645     return identity.asSkMatrix();
1646 }
1647 
InvalidMatrix()1648 const SkMatrix& SkMatrix::InvalidMatrix() {
1649     static_assert(offsetof(SkMatrix,fMat)      == offsetof(AggregateMatrix,matrix),   "fMat");
1650     static_assert(offsetof(SkMatrix,fTypeMask) == offsetof(AggregateMatrix,typemask), "fTypeMask");
1651 
1652     static const AggregateMatrix invalid =
1653         { {SK_ScalarMax, SK_ScalarMax, SK_ScalarMax,
1654            SK_ScalarMax, SK_ScalarMax, SK_ScalarMax,
1655            SK_ScalarMax, SK_ScalarMax, SK_ScalarMax },
1656          kTranslate_Mask | kScale_Mask | kAffine_Mask | kPerspective_Mask };
1657     return invalid.asSkMatrix();
1658 }
1659 
decomposeScale(SkSize * scale,SkMatrix * remaining) const1660 bool SkMatrix::decomposeScale(SkSize* scale, SkMatrix* remaining) const {
1661     if (this->hasPerspective()) {
1662         return false;
1663     }
1664 
1665     const SkScalar sx = SkVector::Length(this->getScaleX(), this->getSkewY());
1666     const SkScalar sy = SkVector::Length(this->getSkewX(), this->getScaleY());
1667     if (!SkScalarIsFinite(sx) || !SkScalarIsFinite(sy) ||
1668         SkScalarNearlyZero(sx) || SkScalarNearlyZero(sy)) {
1669         return false;
1670     }
1671 
1672     if (scale) {
1673         scale->set(sx, sy);
1674     }
1675     if (remaining) {
1676         *remaining = *this;
1677         remaining->postScale(SkScalarInvert(sx), SkScalarInvert(sy));
1678     }
1679     return true;
1680 }
1681 
1682 ///////////////////////////////////////////////////////////////////////////////
1683 
writeToMemory(void * buffer) const1684 size_t SkMatrix::writeToMemory(void* buffer) const {
1685     // TODO write less for simple matrices
1686     static const size_t sizeInMemory = 9 * sizeof(SkScalar);
1687     if (buffer) {
1688         memcpy(buffer, fMat, sizeInMemory);
1689     }
1690     return sizeInMemory;
1691 }
1692 
readFromMemory(const void * buffer,size_t length)1693 size_t SkMatrix::readFromMemory(const void* buffer, size_t length) {
1694     static const size_t sizeInMemory = 9 * sizeof(SkScalar);
1695     if (length < sizeInMemory) {
1696         return 0;
1697     }
1698     if (buffer) {
1699         memcpy(fMat, buffer, sizeInMemory);
1700         this->setTypeMask(kUnknown_Mask);
1701     }
1702     return sizeInMemory;
1703 }
1704 
dump() const1705 void SkMatrix::dump() const {
1706     SkString str;
1707     this->toString(&str);
1708     SkDebugf("%s\n", str.c_str());
1709 }
1710 
toString(SkString * str) const1711 void SkMatrix::toString(SkString* str) const {
1712     str->appendf("[%8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f]",
1713              fMat[0], fMat[1], fMat[2], fMat[3], fMat[4], fMat[5],
1714              fMat[6], fMat[7], fMat[8]);
1715 }
1716 
1717 ///////////////////////////////////////////////////////////////////////////////
1718 
1719 #include "SkMatrixUtils.h"
1720 
SkTreatAsSprite(const SkMatrix & mat,const SkISize & size,const SkPaint & paint)1721 bool SkTreatAsSprite(const SkMatrix& mat, const SkISize& size, const SkPaint& paint) {
1722     // Our path aa is 2-bits, and our rect aa is 8, so we could use 8,
1723     // but in practice 4 seems enough (still looks smooth) and allows
1724     // more slightly fractional cases to fall into the fast (sprite) case.
1725     static const unsigned kAntiAliasSubpixelBits = 4;
1726 
1727     const unsigned subpixelBits = paint.isAntiAlias() ? kAntiAliasSubpixelBits : 0;
1728 
1729     // quick reject on affine or perspective
1730     if (mat.getType() & ~(SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask)) {
1731         return false;
1732     }
1733 
1734     // quick success check
1735     if (!subpixelBits && !(mat.getType() & ~SkMatrix::kTranslate_Mask)) {
1736         return true;
1737     }
1738 
1739     // mapRect supports negative scales, so we eliminate those first
1740     if (mat.getScaleX() < 0 || mat.getScaleY() < 0) {
1741         return false;
1742     }
1743 
1744     SkRect dst;
1745     SkIRect isrc = SkIRect::MakeSize(size);
1746 
1747     {
1748         SkRect src;
1749         src.set(isrc);
1750         mat.mapRect(&dst, src);
1751     }
1752 
1753     // just apply the translate to isrc
1754     isrc.offset(SkScalarRoundToInt(mat.getTranslateX()),
1755                 SkScalarRoundToInt(mat.getTranslateY()));
1756 
1757     if (subpixelBits) {
1758         isrc.fLeft = SkLeftShift(isrc.fLeft, subpixelBits);
1759         isrc.fTop = SkLeftShift(isrc.fTop, subpixelBits);
1760         isrc.fRight = SkLeftShift(isrc.fRight, subpixelBits);
1761         isrc.fBottom = SkLeftShift(isrc.fBottom, subpixelBits);
1762 
1763         const float scale = 1 << subpixelBits;
1764         dst.fLeft *= scale;
1765         dst.fTop *= scale;
1766         dst.fRight *= scale;
1767         dst.fBottom *= scale;
1768     }
1769 
1770     SkIRect idst;
1771     dst.round(&idst);
1772     return isrc == idst;
1773 }
1774 
1775 // A square matrix M can be decomposed (via polar decomposition) into two matrices --
1776 // an orthogonal matrix Q and a symmetric matrix S. In turn we can decompose S into U*W*U^T,
1777 // where U is another orthogonal matrix and W is a scale matrix. These can be recombined
1778 // to give M = (Q*U)*W*U^T, i.e., the product of two orthogonal matrices and a scale matrix.
1779 //
1780 // The one wrinkle is that traditionally Q may contain a reflection -- the
1781 // calculation has been rejiggered to put that reflection into W.
SkDecomposeUpper2x2(const SkMatrix & matrix,SkPoint * rotation1,SkPoint * scale,SkPoint * rotation2)1782 bool SkDecomposeUpper2x2(const SkMatrix& matrix,
1783                          SkPoint* rotation1,
1784                          SkPoint* scale,
1785                          SkPoint* rotation2) {
1786 
1787     SkScalar A = matrix[SkMatrix::kMScaleX];
1788     SkScalar B = matrix[SkMatrix::kMSkewX];
1789     SkScalar C = matrix[SkMatrix::kMSkewY];
1790     SkScalar D = matrix[SkMatrix::kMScaleY];
1791 
1792     if (is_degenerate_2x2(A, B, C, D)) {
1793         return false;
1794     }
1795 
1796     double w1, w2;
1797     SkScalar cos1, sin1;
1798     SkScalar cos2, sin2;
1799 
1800     // do polar decomposition (M = Q*S)
1801     SkScalar cosQ, sinQ;
1802     double Sa, Sb, Sd;
1803     // if M is already symmetric (i.e., M = I*S)
1804     if (SkScalarNearlyEqual(B, C)) {
1805         cosQ = 1;
1806         sinQ = 0;
1807 
1808         Sa = A;
1809         Sb = B;
1810         Sd = D;
1811     } else {
1812         cosQ = A + D;
1813         sinQ = C - B;
1814         SkScalar reciplen = SkScalarInvert(SkScalarSqrt(cosQ*cosQ + sinQ*sinQ));
1815         cosQ *= reciplen;
1816         sinQ *= reciplen;
1817 
1818         // S = Q^-1*M
1819         // we don't calc Sc since it's symmetric
1820         Sa = A*cosQ + C*sinQ;
1821         Sb = B*cosQ + D*sinQ;
1822         Sd = -B*sinQ + D*cosQ;
1823     }
1824 
1825     // Now we need to compute eigenvalues of S (our scale factors)
1826     // and eigenvectors (bases for our rotation)
1827     // From this, should be able to reconstruct S as U*W*U^T
1828     if (SkScalarNearlyZero(SkDoubleToScalar(Sb))) {
1829         // already diagonalized
1830         cos1 = 1;
1831         sin1 = 0;
1832         w1 = Sa;
1833         w2 = Sd;
1834         cos2 = cosQ;
1835         sin2 = sinQ;
1836     } else {
1837         double diff = Sa - Sd;
1838         double discriminant = sqrt(diff*diff + 4.0*Sb*Sb);
1839         double trace = Sa + Sd;
1840         if (diff > 0) {
1841             w1 = 0.5*(trace + discriminant);
1842             w2 = 0.5*(trace - discriminant);
1843         } else {
1844             w1 = 0.5*(trace - discriminant);
1845             w2 = 0.5*(trace + discriminant);
1846         }
1847 
1848         cos1 = SkDoubleToScalar(Sb); sin1 = SkDoubleToScalar(w1 - Sa);
1849         SkScalar reciplen = SkScalarInvert(SkScalarSqrt(cos1*cos1 + sin1*sin1));
1850         cos1 *= reciplen;
1851         sin1 *= reciplen;
1852 
1853         // rotation 2 is composition of Q and U
1854         cos2 = cos1*cosQ - sin1*sinQ;
1855         sin2 = sin1*cosQ + cos1*sinQ;
1856 
1857         // rotation 1 is U^T
1858         sin1 = -sin1;
1859     }
1860 
1861     if (scale) {
1862         scale->fX = SkDoubleToScalar(w1);
1863         scale->fY = SkDoubleToScalar(w2);
1864     }
1865     if (rotation1) {
1866         rotation1->fX = cos1;
1867         rotation1->fY = sin1;
1868     }
1869     if (rotation2) {
1870         rotation2->fX = cos2;
1871         rotation2->fY = sin2;
1872     }
1873 
1874     return true;
1875 }
1876 
1877 //////////////////////////////////////////////////////////////////////////////////////////////////
1878 
toQuad(SkScalar width,SkScalar height,SkPoint quad[4]) const1879 void SkRSXform::toQuad(SkScalar width, SkScalar height, SkPoint quad[4]) const {
1880 #if 0
1881     // This is the slow way, but it documents what we're doing
1882     quad[0].set(0, 0);
1883     quad[1].set(width, 0);
1884     quad[2].set(width, height);
1885     quad[3].set(0, height);
1886     SkMatrix m;
1887     m.setRSXform(*this).mapPoints(quad, quad, 4);
1888 #else
1889     const SkScalar m00 = fSCos;
1890     const SkScalar m01 = -fSSin;
1891     const SkScalar m02 = fTx;
1892     const SkScalar m10 = -m01;
1893     const SkScalar m11 = m00;
1894     const SkScalar m12 = fTy;
1895 
1896     quad[0].set(m02, m12);
1897     quad[1].set(m00 * width + m02, m10 * width + m12);
1898     quad[2].set(m00 * width + m01 * height + m02, m10 * width + m11 * height + m12);
1899     quad[3].set(m01 * height + m02, m11 * height + m12);
1900 #endif
1901 }
1902