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