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