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