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