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