1 /*
2 * Copyright 2011 Google Inc.
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 "SkMatrix44.h"
9
eq4(const SkMScalar * SK_RESTRICT a,const SkMScalar * SK_RESTRICT b)10 static inline bool eq4(const SkMScalar* SK_RESTRICT a,
11 const SkMScalar* SK_RESTRICT b) {
12 return (a[0] == b[0]) & (a[1] == b[1]) & (a[2] == b[2]) & (a[3] == b[3]);
13 }
14
operator ==(const SkMatrix44 & other) const15 bool SkMatrix44::operator==(const SkMatrix44& other) const {
16 if (this == &other) {
17 return true;
18 }
19
20 if (this->isTriviallyIdentity() && other.isTriviallyIdentity()) {
21 return true;
22 }
23
24 const SkMScalar* SK_RESTRICT a = &fMat[0][0];
25 const SkMScalar* SK_RESTRICT b = &other.fMat[0][0];
26
27 #if 0
28 for (int i = 0; i < 16; ++i) {
29 if (a[i] != b[i]) {
30 return false;
31 }
32 }
33 return true;
34 #else
35 // to reduce branch instructions, we compare 4 at a time.
36 // see bench/Matrix44Bench.cpp for test.
37 if (!eq4(&a[0], &b[0])) {
38 return false;
39 }
40 if (!eq4(&a[4], &b[4])) {
41 return false;
42 }
43 if (!eq4(&a[8], &b[8])) {
44 return false;
45 }
46 return eq4(&a[12], &b[12]);
47 #endif
48 }
49
50 ///////////////////////////////////////////////////////////////////////////////
51
computeTypeMask() const52 int SkMatrix44::computeTypeMask() const {
53 unsigned mask = 0;
54
55 if (0 != perspX() || 0 != perspY() || 0 != perspZ() || 1 != fMat[3][3]) {
56 return kTranslate_Mask | kScale_Mask | kAffine_Mask | kPerspective_Mask;
57 }
58
59 if (0 != transX() || 0 != transY() || 0 != transZ()) {
60 mask |= kTranslate_Mask;
61 }
62
63 if (1 != scaleX() || 1 != scaleY() || 1 != scaleZ()) {
64 mask |= kScale_Mask;
65 }
66
67 if (0 != fMat[1][0] || 0 != fMat[0][1] || 0 != fMat[0][2] ||
68 0 != fMat[2][0] || 0 != fMat[1][2] || 0 != fMat[2][1]) {
69 mask |= kAffine_Mask;
70 }
71
72 return mask;
73 }
74
75 ///////////////////////////////////////////////////////////////////////////////
76
asColMajorf(float dst[]) const77 void SkMatrix44::asColMajorf(float dst[]) const {
78 const SkMScalar* src = &fMat[0][0];
79 #ifdef SK_MSCALAR_IS_DOUBLE
80 for (int i = 0; i < 16; ++i) {
81 dst[i] = SkMScalarToFloat(src[i]);
82 }
83 #elif defined SK_MSCALAR_IS_FLOAT
84 memcpy(dst, src, 16 * sizeof(float));
85 #endif
86 }
87
asColMajord(double dst[]) const88 void SkMatrix44::asColMajord(double dst[]) const {
89 const SkMScalar* src = &fMat[0][0];
90 #ifdef SK_MSCALAR_IS_DOUBLE
91 memcpy(dst, src, 16 * sizeof(double));
92 #elif defined SK_MSCALAR_IS_FLOAT
93 for (int i = 0; i < 16; ++i) {
94 dst[i] = SkMScalarToDouble(src[i]);
95 }
96 #endif
97 }
98
asRowMajorf(float dst[]) const99 void SkMatrix44::asRowMajorf(float dst[]) const {
100 const SkMScalar* src = &fMat[0][0];
101 for (int i = 0; i < 4; ++i) {
102 dst[0] = SkMScalarToFloat(src[0]);
103 dst[4] = SkMScalarToFloat(src[1]);
104 dst[8] = SkMScalarToFloat(src[2]);
105 dst[12] = SkMScalarToFloat(src[3]);
106 src += 4;
107 dst += 1;
108 }
109 }
110
asRowMajord(double dst[]) const111 void SkMatrix44::asRowMajord(double dst[]) const {
112 const SkMScalar* src = &fMat[0][0];
113 for (int i = 0; i < 4; ++i) {
114 dst[0] = SkMScalarToDouble(src[0]);
115 dst[4] = SkMScalarToDouble(src[1]);
116 dst[8] = SkMScalarToDouble(src[2]);
117 dst[12] = SkMScalarToDouble(src[3]);
118 src += 4;
119 dst += 1;
120 }
121 }
122
setColMajorf(const float src[])123 void SkMatrix44::setColMajorf(const float src[]) {
124 SkMScalar* dst = &fMat[0][0];
125 #ifdef SK_MSCALAR_IS_DOUBLE
126 for (int i = 0; i < 16; ++i) {
127 dst[i] = SkMScalarToFloat(src[i]);
128 }
129 #elif defined SK_MSCALAR_IS_FLOAT
130 memcpy(dst, src, 16 * sizeof(float));
131 #endif
132
133 this->dirtyTypeMask();
134 }
135
setColMajord(const double src[])136 void SkMatrix44::setColMajord(const double src[]) {
137 SkMScalar* dst = &fMat[0][0];
138 #ifdef SK_MSCALAR_IS_DOUBLE
139 memcpy(dst, src, 16 * sizeof(double));
140 #elif defined SK_MSCALAR_IS_FLOAT
141 for (int i = 0; i < 16; ++i) {
142 dst[i] = SkDoubleToMScalar(src[i]);
143 }
144 #endif
145
146 this->dirtyTypeMask();
147 }
148
setRowMajorf(const float src[])149 void SkMatrix44::setRowMajorf(const float src[]) {
150 SkMScalar* dst = &fMat[0][0];
151 for (int i = 0; i < 4; ++i) {
152 dst[0] = SkMScalarToFloat(src[0]);
153 dst[4] = SkMScalarToFloat(src[1]);
154 dst[8] = SkMScalarToFloat(src[2]);
155 dst[12] = SkMScalarToFloat(src[3]);
156 src += 4;
157 dst += 1;
158 }
159 this->dirtyTypeMask();
160 }
161
setRowMajord(const double src[])162 void SkMatrix44::setRowMajord(const double src[]) {
163 SkMScalar* dst = &fMat[0][0];
164 for (int i = 0; i < 4; ++i) {
165 dst[0] = SkDoubleToMScalar(src[0]);
166 dst[4] = SkDoubleToMScalar(src[1]);
167 dst[8] = SkDoubleToMScalar(src[2]);
168 dst[12] = SkDoubleToMScalar(src[3]);
169 src += 4;
170 dst += 1;
171 }
172 this->dirtyTypeMask();
173 }
174
175 ///////////////////////////////////////////////////////////////////////////////
176
I()177 const SkMatrix44& SkMatrix44::I() {
178 static const SkMatrix44 gIdentity44(kIdentity_Constructor);
179 return gIdentity44;
180 }
181
setIdentity()182 void SkMatrix44::setIdentity() {
183 fMat[0][0] = 1;
184 fMat[0][1] = 0;
185 fMat[0][2] = 0;
186 fMat[0][3] = 0;
187 fMat[1][0] = 0;
188 fMat[1][1] = 1;
189 fMat[1][2] = 0;
190 fMat[1][3] = 0;
191 fMat[2][0] = 0;
192 fMat[2][1] = 0;
193 fMat[2][2] = 1;
194 fMat[2][3] = 0;
195 fMat[3][0] = 0;
196 fMat[3][1] = 0;
197 fMat[3][2] = 0;
198 fMat[3][3] = 1;
199 this->setTypeMask(kIdentity_Mask);
200 }
201
set3x3(SkMScalar m00,SkMScalar m01,SkMScalar m02,SkMScalar m10,SkMScalar m11,SkMScalar m12,SkMScalar m20,SkMScalar m21,SkMScalar m22)202 void SkMatrix44::set3x3(SkMScalar m00, SkMScalar m01, SkMScalar m02,
203 SkMScalar m10, SkMScalar m11, SkMScalar m12,
204 SkMScalar m20, SkMScalar m21, SkMScalar m22) {
205 fMat[0][0] = m00; fMat[0][1] = m01; fMat[0][2] = m02; fMat[0][3] = 0;
206 fMat[1][0] = m10; fMat[1][1] = m11; fMat[1][2] = m12; fMat[1][3] = 0;
207 fMat[2][0] = m20; fMat[2][1] = m21; fMat[2][2] = m22; fMat[2][3] = 0;
208 fMat[3][0] = 0; fMat[3][1] = 0; fMat[3][2] = 0; fMat[3][3] = 1;
209 this->dirtyTypeMask();
210 }
211
212 ///////////////////////////////////////////////////////////////////////////////
213
setTranslate(SkMScalar dx,SkMScalar dy,SkMScalar dz)214 void SkMatrix44::setTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz) {
215 this->setIdentity();
216
217 if (!dx && !dy && !dz) {
218 return;
219 }
220
221 fMat[3][0] = dx;
222 fMat[3][1] = dy;
223 fMat[3][2] = dz;
224 this->setTypeMask(kTranslate_Mask);
225 }
226
preTranslate(SkMScalar dx,SkMScalar dy,SkMScalar dz)227 void SkMatrix44::preTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz) {
228 if (!dx && !dy && !dz) {
229 return;
230 }
231
232 for (int i = 0; i < 4; ++i) {
233 fMat[3][i] = fMat[0][i] * dx + fMat[1][i] * dy + fMat[2][i] * dz + fMat[3][i];
234 }
235 this->dirtyTypeMask();
236 }
237
postTranslate(SkMScalar dx,SkMScalar dy,SkMScalar dz)238 void SkMatrix44::postTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz) {
239 if (!dx && !dy && !dz) {
240 return;
241 }
242
243 if (this->getType() & kPerspective_Mask) {
244 for (int i = 0; i < 4; ++i) {
245 fMat[i][0] += fMat[i][3] * dx;
246 fMat[i][1] += fMat[i][3] * dy;
247 fMat[i][2] += fMat[i][3] * dz;
248 }
249 } else {
250 fMat[3][0] += dx;
251 fMat[3][1] += dy;
252 fMat[3][2] += dz;
253 this->dirtyTypeMask();
254 }
255 }
256
257 ///////////////////////////////////////////////////////////////////////////////
258
setScale(SkMScalar sx,SkMScalar sy,SkMScalar sz)259 void SkMatrix44::setScale(SkMScalar sx, SkMScalar sy, SkMScalar sz) {
260 this->setIdentity();
261
262 if (1 == sx && 1 == sy && 1 == sz) {
263 return;
264 }
265
266 fMat[0][0] = sx;
267 fMat[1][1] = sy;
268 fMat[2][2] = sz;
269 this->setTypeMask(kScale_Mask);
270 }
271
preScale(SkMScalar sx,SkMScalar sy,SkMScalar sz)272 void SkMatrix44::preScale(SkMScalar sx, SkMScalar sy, SkMScalar sz) {
273 if (1 == sx && 1 == sy && 1 == sz) {
274 return;
275 }
276
277 // The implementation matrix * pureScale can be shortcut
278 // by knowing that pureScale components effectively scale
279 // the columns of the original matrix.
280 for (int i = 0; i < 4; i++) {
281 fMat[0][i] *= sx;
282 fMat[1][i] *= sy;
283 fMat[2][i] *= sz;
284 }
285 this->dirtyTypeMask();
286 }
287
postScale(SkMScalar sx,SkMScalar sy,SkMScalar sz)288 void SkMatrix44::postScale(SkMScalar sx, SkMScalar sy, SkMScalar sz) {
289 if (1 == sx && 1 == sy && 1 == sz) {
290 return;
291 }
292
293 for (int i = 0; i < 4; i++) {
294 fMat[i][0] *= sx;
295 fMat[i][1] *= sy;
296 fMat[i][2] *= sz;
297 }
298 this->dirtyTypeMask();
299 }
300
301 ///////////////////////////////////////////////////////////////////////////////
302
setRotateAbout(SkMScalar x,SkMScalar y,SkMScalar z,SkMScalar radians)303 void SkMatrix44::setRotateAbout(SkMScalar x, SkMScalar y, SkMScalar z,
304 SkMScalar radians) {
305 double len2 = (double)x * x + (double)y * y + (double)z * z;
306 if (1 != len2) {
307 if (0 == len2) {
308 this->setIdentity();
309 return;
310 }
311 double scale = 1 / sqrt(len2);
312 x = SkDoubleToMScalar(x * scale);
313 y = SkDoubleToMScalar(y * scale);
314 z = SkDoubleToMScalar(z * scale);
315 }
316 this->setRotateAboutUnit(x, y, z, radians);
317 }
318
setRotateAboutUnit(SkMScalar x,SkMScalar y,SkMScalar z,SkMScalar radians)319 void SkMatrix44::setRotateAboutUnit(SkMScalar x, SkMScalar y, SkMScalar z,
320 SkMScalar radians) {
321 double c = cos(radians);
322 double s = sin(radians);
323 double C = 1 - c;
324 double xs = x * s;
325 double ys = y * s;
326 double zs = z * s;
327 double xC = x * C;
328 double yC = y * C;
329 double zC = z * C;
330 double xyC = x * yC;
331 double yzC = y * zC;
332 double zxC = z * xC;
333
334 // if you're looking at wikipedia, remember that we're column major.
335 this->set3x3(SkDoubleToMScalar(x * xC + c), // scale x
336 SkDoubleToMScalar(xyC + zs), // skew x
337 SkDoubleToMScalar(zxC - ys), // trans x
338
339 SkDoubleToMScalar(xyC - zs), // skew y
340 SkDoubleToMScalar(y * yC + c), // scale y
341 SkDoubleToMScalar(yzC + xs), // trans y
342
343 SkDoubleToMScalar(zxC + ys), // persp x
344 SkDoubleToMScalar(yzC - xs), // persp y
345 SkDoubleToMScalar(z * zC + c)); // persp 2
346 }
347
348 ///////////////////////////////////////////////////////////////////////////////
349
bits_isonly(int value,int mask)350 static bool bits_isonly(int value, int mask) {
351 return 0 == (value & ~mask);
352 }
353
setConcat(const SkMatrix44 & a,const SkMatrix44 & b)354 void SkMatrix44::setConcat(const SkMatrix44& a, const SkMatrix44& b) {
355 const SkMatrix44::TypeMask a_mask = a.getType();
356 const SkMatrix44::TypeMask b_mask = b.getType();
357
358 if (kIdentity_Mask == a_mask) {
359 *this = b;
360 return;
361 }
362 if (kIdentity_Mask == b_mask) {
363 *this = a;
364 return;
365 }
366
367 bool useStorage = (this == &a || this == &b);
368 SkMScalar storage[16];
369 SkMScalar* result = useStorage ? storage : &fMat[0][0];
370
371 // Both matrices are at most scale+translate
372 if (bits_isonly(a_mask | b_mask, kScale_Mask | kTranslate_Mask)) {
373 result[0] = a.fMat[0][0] * b.fMat[0][0];
374 result[1] = result[2] = result[3] = result[4] = 0;
375 result[5] = a.fMat[1][1] * b.fMat[1][1];
376 result[6] = result[7] = result[8] = result[9] = 0;
377 result[10] = a.fMat[2][2] * b.fMat[2][2];
378 result[11] = 0;
379 result[12] = a.fMat[0][0] * b.fMat[3][0] + a.fMat[3][0];
380 result[13] = a.fMat[1][1] * b.fMat[3][1] + a.fMat[3][1];
381 result[14] = a.fMat[2][2] * b.fMat[3][2] + a.fMat[3][2];
382 result[15] = 1;
383 } else {
384 for (int j = 0; j < 4; j++) {
385 for (int i = 0; i < 4; i++) {
386 double value = 0;
387 for (int k = 0; k < 4; k++) {
388 value += SkMScalarToDouble(a.fMat[k][i]) * b.fMat[j][k];
389 }
390 *result++ = SkDoubleToMScalar(value);
391 }
392 }
393 }
394
395 if (useStorage) {
396 memcpy(fMat, storage, sizeof(storage));
397 }
398 this->dirtyTypeMask();
399 }
400
401 ///////////////////////////////////////////////////////////////////////////////
402
403 /** We always perform the calculation in doubles, to avoid prematurely losing
404 precision along the way. This relies on the compiler automatically
405 promoting our SkMScalar values to double (if needed).
406 */
determinant() const407 double SkMatrix44::determinant() const {
408 if (this->isIdentity()) {
409 return 1;
410 }
411 if (this->isScaleTranslate()) {
412 return fMat[0][0] * fMat[1][1] * fMat[2][2] * fMat[3][3];
413 }
414
415 double a00 = fMat[0][0];
416 double a01 = fMat[0][1];
417 double a02 = fMat[0][2];
418 double a03 = fMat[0][3];
419 double a10 = fMat[1][0];
420 double a11 = fMat[1][1];
421 double a12 = fMat[1][2];
422 double a13 = fMat[1][3];
423 double a20 = fMat[2][0];
424 double a21 = fMat[2][1];
425 double a22 = fMat[2][2];
426 double a23 = fMat[2][3];
427 double a30 = fMat[3][0];
428 double a31 = fMat[3][1];
429 double a32 = fMat[3][2];
430 double a33 = fMat[3][3];
431
432 double b00 = a00 * a11 - a01 * a10;
433 double b01 = a00 * a12 - a02 * a10;
434 double b02 = a00 * a13 - a03 * a10;
435 double b03 = a01 * a12 - a02 * a11;
436 double b04 = a01 * a13 - a03 * a11;
437 double b05 = a02 * a13 - a03 * a12;
438 double b06 = a20 * a31 - a21 * a30;
439 double b07 = a20 * a32 - a22 * a30;
440 double b08 = a20 * a33 - a23 * a30;
441 double b09 = a21 * a32 - a22 * a31;
442 double b10 = a21 * a33 - a23 * a31;
443 double b11 = a22 * a33 - a23 * a32;
444
445 // Calculate the determinant
446 return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
447 }
448
449 ///////////////////////////////////////////////////////////////////////////////
450
invert(SkMatrix44 * inverse) const451 bool SkMatrix44::invert(SkMatrix44* inverse) const {
452 if (this->isIdentity()) {
453 if (inverse) {
454 inverse->setIdentity();
455 }
456 return true;
457 }
458
459 if (this->isTranslate()) {
460 if (inverse) {
461 inverse->setTranslate(-fMat[3][0], -fMat[3][1], -fMat[3][2]);
462 }
463 return true;
464 }
465
466 if (this->isScaleTranslate()) {
467 if (0 == fMat[0][0] * fMat[1][1] * fMat[2][2]) {
468 return false;
469 }
470
471 if (inverse) {
472 double invXScale = 1 / fMat[0][0];
473 double invYScale = 1 / fMat[1][1];
474 double invZScale = 1 / fMat[2][2];
475
476 inverse->fMat[0][0] = invXScale;
477 inverse->fMat[0][1] = 0;
478 inverse->fMat[0][2] = 0;
479 inverse->fMat[0][3] = 0;
480
481 inverse->fMat[1][0] = 0;
482 inverse->fMat[1][1] = invYScale;
483 inverse->fMat[1][2] = 0;
484 inverse->fMat[1][3] = 0;
485
486 inverse->fMat[2][0] = 0;
487 inverse->fMat[2][1] = 0;
488 inverse->fMat[2][2] = invZScale;
489 inverse->fMat[2][3] = 0;
490
491 inverse->fMat[3][0] = -fMat[3][0] * invXScale;
492 inverse->fMat[3][1] = -fMat[3][1] * invYScale;
493 inverse->fMat[3][2] = -fMat[3][2] * invZScale;
494 inverse->fMat[3][3] = 1;
495
496 inverse->setTypeMask(this->getType());
497 }
498
499 return true;
500 }
501
502 double a00 = fMat[0][0];
503 double a01 = fMat[0][1];
504 double a02 = fMat[0][2];
505 double a03 = fMat[0][3];
506 double a10 = fMat[1][0];
507 double a11 = fMat[1][1];
508 double a12 = fMat[1][2];
509 double a13 = fMat[1][3];
510 double a20 = fMat[2][0];
511 double a21 = fMat[2][1];
512 double a22 = fMat[2][2];
513 double a23 = fMat[2][3];
514 double a30 = fMat[3][0];
515 double a31 = fMat[3][1];
516 double a32 = fMat[3][2];
517 double a33 = fMat[3][3];
518
519 if (!(this->getType() & kPerspective_Mask)) {
520 // If we know the matrix has no perspective, then the perspective
521 // component is (0, 0, 0, 1). We can use this information to save a lot
522 // of arithmetic that would otherwise be spent to compute the inverse
523 // of a general matrix.
524
525 SkASSERT(a03 == 0);
526 SkASSERT(a13 == 0);
527 SkASSERT(a23 == 0);
528 SkASSERT(a33 == 1);
529
530 double b00 = a00 * a11 - a01 * a10;
531 double b01 = a00 * a12 - a02 * a10;
532 double b03 = a01 * a12 - a02 * a11;
533 double b06 = a20 * a31 - a21 * a30;
534 double b07 = a20 * a32 - a22 * a30;
535 double b08 = a20;
536 double b09 = a21 * a32 - a22 * a31;
537 double b10 = a21;
538 double b11 = a22;
539
540 // Calculate the determinant
541 double det = b00 * b11 - b01 * b10 + b03 * b08;
542
543 double invdet = 1.0 / det;
544 // If det is zero, we want to return false. However, we also want to return false
545 // if 1/det overflows to infinity (i.e. det is denormalized). Both of these are
546 // handled by checking that 1/det is finite.
547 if (!sk_float_isfinite(invdet)) {
548 return false;
549 }
550 if (NULL == inverse) {
551 return true;
552 }
553
554 b00 *= invdet;
555 b01 *= invdet;
556 b03 *= invdet;
557 b06 *= invdet;
558 b07 *= invdet;
559 b08 *= invdet;
560 b09 *= invdet;
561 b10 *= invdet;
562 b11 *= invdet;
563
564 inverse->fMat[0][0] = SkDoubleToMScalar(a11 * b11 - a12 * b10);
565 inverse->fMat[0][1] = SkDoubleToMScalar(a02 * b10 - a01 * b11);
566 inverse->fMat[0][2] = SkDoubleToMScalar(b03);
567 inverse->fMat[0][3] = 0;
568 inverse->fMat[1][0] = SkDoubleToMScalar(a12 * b08 - a10 * b11);
569 inverse->fMat[1][1] = SkDoubleToMScalar(a00 * b11 - a02 * b08);
570 inverse->fMat[1][2] = SkDoubleToMScalar(-b01);
571 inverse->fMat[1][3] = 0;
572 inverse->fMat[2][0] = SkDoubleToMScalar(a10 * b10 - a11 * b08);
573 inverse->fMat[2][1] = SkDoubleToMScalar(a01 * b08 - a00 * b10);
574 inverse->fMat[2][2] = SkDoubleToMScalar(b00);
575 inverse->fMat[2][3] = 0;
576 inverse->fMat[3][0] = SkDoubleToMScalar(a11 * b07 - a10 * b09 - a12 * b06);
577 inverse->fMat[3][1] = SkDoubleToMScalar(a00 * b09 - a01 * b07 + a02 * b06);
578 inverse->fMat[3][2] = SkDoubleToMScalar(a31 * b01 - a30 * b03 - a32 * b00);
579 inverse->fMat[3][3] = 1;
580
581 inverse->setTypeMask(this->getType());
582 return true;
583 }
584
585 double b00 = a00 * a11 - a01 * a10;
586 double b01 = a00 * a12 - a02 * a10;
587 double b02 = a00 * a13 - a03 * a10;
588 double b03 = a01 * a12 - a02 * a11;
589 double b04 = a01 * a13 - a03 * a11;
590 double b05 = a02 * a13 - a03 * a12;
591 double b06 = a20 * a31 - a21 * a30;
592 double b07 = a20 * a32 - a22 * a30;
593 double b08 = a20 * a33 - a23 * a30;
594 double b09 = a21 * a32 - a22 * a31;
595 double b10 = a21 * a33 - a23 * a31;
596 double b11 = a22 * a33 - a23 * a32;
597
598 // Calculate the determinant
599 double det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
600
601 double invdet = 1.0 / det;
602 // If det is zero, we want to return false. However, we also want to return false
603 // if 1/det overflows to infinity (i.e. det is denormalized). Both of these are
604 // handled by checking that 1/det is finite.
605 if (!sk_float_isfinite(invdet)) {
606 return false;
607 }
608 if (NULL == inverse) {
609 return true;
610 }
611
612 b00 *= invdet;
613 b01 *= invdet;
614 b02 *= invdet;
615 b03 *= invdet;
616 b04 *= invdet;
617 b05 *= invdet;
618 b06 *= invdet;
619 b07 *= invdet;
620 b08 *= invdet;
621 b09 *= invdet;
622 b10 *= invdet;
623 b11 *= invdet;
624
625 inverse->fMat[0][0] = SkDoubleToMScalar(a11 * b11 - a12 * b10 + a13 * b09);
626 inverse->fMat[0][1] = SkDoubleToMScalar(a02 * b10 - a01 * b11 - a03 * b09);
627 inverse->fMat[0][2] = SkDoubleToMScalar(a31 * b05 - a32 * b04 + a33 * b03);
628 inverse->fMat[0][3] = SkDoubleToMScalar(a22 * b04 - a21 * b05 - a23 * b03);
629 inverse->fMat[1][0] = SkDoubleToMScalar(a12 * b08 - a10 * b11 - a13 * b07);
630 inverse->fMat[1][1] = SkDoubleToMScalar(a00 * b11 - a02 * b08 + a03 * b07);
631 inverse->fMat[1][2] = SkDoubleToMScalar(a32 * b02 - a30 * b05 - a33 * b01);
632 inverse->fMat[1][3] = SkDoubleToMScalar(a20 * b05 - a22 * b02 + a23 * b01);
633 inverse->fMat[2][0] = SkDoubleToMScalar(a10 * b10 - a11 * b08 + a13 * b06);
634 inverse->fMat[2][1] = SkDoubleToMScalar(a01 * b08 - a00 * b10 - a03 * b06);
635 inverse->fMat[2][2] = SkDoubleToMScalar(a30 * b04 - a31 * b02 + a33 * b00);
636 inverse->fMat[2][3] = SkDoubleToMScalar(a21 * b02 - a20 * b04 - a23 * b00);
637 inverse->fMat[3][0] = SkDoubleToMScalar(a11 * b07 - a10 * b09 - a12 * b06);
638 inverse->fMat[3][1] = SkDoubleToMScalar(a00 * b09 - a01 * b07 + a02 * b06);
639 inverse->fMat[3][2] = SkDoubleToMScalar(a31 * b01 - a30 * b03 - a32 * b00);
640 inverse->fMat[3][3] = SkDoubleToMScalar(a20 * b03 - a21 * b01 + a22 * b00);
641 inverse->dirtyTypeMask();
642
643 return true;
644 }
645
646 ///////////////////////////////////////////////////////////////////////////////
647
transpose()648 void SkMatrix44::transpose() {
649 SkTSwap(fMat[0][1], fMat[1][0]);
650 SkTSwap(fMat[0][2], fMat[2][0]);
651 SkTSwap(fMat[0][3], fMat[3][0]);
652 SkTSwap(fMat[1][2], fMat[2][1]);
653 SkTSwap(fMat[1][3], fMat[3][1]);
654 SkTSwap(fMat[2][3], fMat[3][2]);
655
656 if (!this->isTriviallyIdentity()) {
657 this->dirtyTypeMask();
658 }
659 }
660
661 ///////////////////////////////////////////////////////////////////////////////
662
mapScalars(const SkScalar src[4],SkScalar dst[4]) const663 void SkMatrix44::mapScalars(const SkScalar src[4], SkScalar dst[4]) const {
664 SkScalar storage[4];
665 SkScalar* result = (src == dst) ? storage : dst;
666
667 for (int i = 0; i < 4; i++) {
668 SkMScalar value = 0;
669 for (int j = 0; j < 4; j++) {
670 value += fMat[j][i] * src[j];
671 }
672 result[i] = SkMScalarToScalar(value);
673 }
674
675 if (storage == result) {
676 memcpy(dst, storage, sizeof(storage));
677 }
678 }
679
680 #ifdef SK_MSCALAR_IS_DOUBLE
681
mapMScalars(const SkMScalar src[4],SkMScalar dst[4]) const682 void SkMatrix44::mapMScalars(const SkMScalar src[4], SkMScalar dst[4]) const {
683 SkMScalar storage[4];
684 SkMScalar* result = (src == dst) ? storage : dst;
685
686 for (int i = 0; i < 4; i++) {
687 SkMScalar value = 0;
688 for (int j = 0; j < 4; j++) {
689 value += fMat[j][i] * src[j];
690 }
691 result[i] = value;
692 }
693
694 if (storage == result) {
695 memcpy(dst, storage, sizeof(storage));
696 }
697 }
698
699 #endif
700
701 typedef void (*Map2Procf)(const SkMScalar mat[][4], const float src2[], int count, float dst4[]);
702 typedef void (*Map2Procd)(const SkMScalar mat[][4], const double src2[], int count, double dst4[]);
703
map2_if(const SkMScalar mat[][4],const float * SK_RESTRICT src2,int count,float * SK_RESTRICT dst4)704 static void map2_if(const SkMScalar mat[][4], const float* SK_RESTRICT src2,
705 int count, float* SK_RESTRICT dst4) {
706 for (int i = 0; i < count; ++i) {
707 dst4[0] = src2[0];
708 dst4[1] = src2[1];
709 dst4[2] = 0;
710 dst4[3] = 1;
711 src2 += 2;
712 dst4 += 4;
713 }
714 }
715
map2_id(const SkMScalar mat[][4],const double * SK_RESTRICT src2,int count,double * SK_RESTRICT dst4)716 static void map2_id(const SkMScalar mat[][4], const double* SK_RESTRICT src2,
717 int count, double* SK_RESTRICT dst4) {
718 for (int i = 0; i < count; ++i) {
719 dst4[0] = src2[0];
720 dst4[1] = src2[1];
721 dst4[2] = 0;
722 dst4[3] = 1;
723 src2 += 2;
724 dst4 += 4;
725 }
726 }
727
map2_tf(const SkMScalar mat[][4],const float * SK_RESTRICT src2,int count,float * SK_RESTRICT dst4)728 static void map2_tf(const SkMScalar mat[][4], const float* SK_RESTRICT src2,
729 int count, float* SK_RESTRICT dst4) {
730 const float mat30 = SkMScalarToFloat(mat[3][0]);
731 const float mat31 = SkMScalarToFloat(mat[3][1]);
732 const float mat32 = SkMScalarToFloat(mat[3][2]);
733 for (int n = 0; n < count; ++n) {
734 dst4[0] = src2[0] + mat30;
735 dst4[1] = src2[1] + mat31;
736 dst4[2] = mat32;
737 dst4[3] = 1;
738 src2 += 2;
739 dst4 += 4;
740 }
741 }
742
map2_td(const SkMScalar mat[][4],const double * SK_RESTRICT src2,int count,double * SK_RESTRICT dst4)743 static void map2_td(const SkMScalar mat[][4], const double* SK_RESTRICT src2,
744 int count, double* SK_RESTRICT dst4) {
745 for (int n = 0; n < count; ++n) {
746 dst4[0] = src2[0] + mat[3][0];
747 dst4[1] = src2[1] + mat[3][1];
748 dst4[2] = mat[3][2];
749 dst4[3] = 1;
750 src2 += 2;
751 dst4 += 4;
752 }
753 }
754
map2_sf(const SkMScalar mat[][4],const float * SK_RESTRICT src2,int count,float * SK_RESTRICT dst4)755 static void map2_sf(const SkMScalar mat[][4], const float* SK_RESTRICT src2,
756 int count, float* SK_RESTRICT dst4) {
757 const float mat32 = SkMScalarToFloat(mat[3][2]);
758 for (int n = 0; n < count; ++n) {
759 dst4[0] = SkMScalarToFloat(mat[0][0] * src2[0] + mat[3][0]);
760 dst4[1] = SkMScalarToFloat(mat[1][1] * src2[1] + mat[3][1]);
761 dst4[2] = mat32;
762 dst4[3] = 1;
763 src2 += 2;
764 dst4 += 4;
765 }
766 }
767
map2_sd(const SkMScalar mat[][4],const double * SK_RESTRICT src2,int count,double * SK_RESTRICT dst4)768 static void map2_sd(const SkMScalar mat[][4], const double* SK_RESTRICT src2,
769 int count, double* SK_RESTRICT dst4) {
770 for (int n = 0; n < count; ++n) {
771 dst4[0] = mat[0][0] * src2[0] + mat[3][0];
772 dst4[1] = mat[1][1] * src2[1] + mat[3][1];
773 dst4[2] = mat[3][2];
774 dst4[3] = 1;
775 src2 += 2;
776 dst4 += 4;
777 }
778 }
779
map2_af(const SkMScalar mat[][4],const float * SK_RESTRICT src2,int count,float * SK_RESTRICT dst4)780 static void map2_af(const SkMScalar mat[][4], const float* SK_RESTRICT src2,
781 int count, float* SK_RESTRICT dst4) {
782 SkMScalar r;
783 for (int n = 0; n < count; ++n) {
784 SkMScalar sx = SkFloatToMScalar(src2[0]);
785 SkMScalar sy = SkFloatToMScalar(src2[1]);
786 r = mat[0][0] * sx + mat[1][0] * sy + mat[3][0];
787 dst4[0] = SkMScalarToFloat(r);
788 r = mat[0][1] * sx + mat[1][1] * sy + mat[3][1];
789 dst4[1] = SkMScalarToFloat(r);
790 r = mat[0][2] * sx + mat[1][2] * sy + mat[3][2];
791 dst4[2] = SkMScalarToFloat(r);
792 dst4[3] = 1;
793 src2 += 2;
794 dst4 += 4;
795 }
796 }
797
map2_ad(const SkMScalar mat[][4],const double * SK_RESTRICT src2,int count,double * SK_RESTRICT dst4)798 static void map2_ad(const SkMScalar mat[][4], const double* SK_RESTRICT src2,
799 int count, double* SK_RESTRICT dst4) {
800 for (int n = 0; n < count; ++n) {
801 double sx = src2[0];
802 double sy = src2[1];
803 dst4[0] = mat[0][0] * sx + mat[1][0] * sy + mat[3][0];
804 dst4[1] = mat[0][1] * sx + mat[1][1] * sy + mat[3][1];
805 dst4[2] = mat[0][2] * sx + mat[1][2] * sy + mat[3][2];
806 dst4[3] = 1;
807 src2 += 2;
808 dst4 += 4;
809 }
810 }
811
map2_pf(const SkMScalar mat[][4],const float * SK_RESTRICT src2,int count,float * SK_RESTRICT dst4)812 static void map2_pf(const SkMScalar mat[][4], const float* SK_RESTRICT src2,
813 int count, float* SK_RESTRICT dst4) {
814 SkMScalar r;
815 for (int n = 0; n < count; ++n) {
816 SkMScalar sx = SkFloatToMScalar(src2[0]);
817 SkMScalar sy = SkFloatToMScalar(src2[1]);
818 for (int i = 0; i < 4; i++) {
819 r = mat[0][i] * sx + mat[1][i] * sy + mat[3][i];
820 dst4[i] = SkMScalarToFloat(r);
821 }
822 src2 += 2;
823 dst4 += 4;
824 }
825 }
826
map2_pd(const SkMScalar mat[][4],const double * SK_RESTRICT src2,int count,double * SK_RESTRICT dst4)827 static void map2_pd(const SkMScalar mat[][4], const double* SK_RESTRICT src2,
828 int count, double* SK_RESTRICT dst4) {
829 for (int n = 0; n < count; ++n) {
830 double sx = src2[0];
831 double sy = src2[1];
832 for (int i = 0; i < 4; i++) {
833 dst4[i] = mat[0][i] * sx + mat[1][i] * sy + mat[3][i];
834 }
835 src2 += 2;
836 dst4 += 4;
837 }
838 }
839
map2(const float src2[],int count,float dst4[]) const840 void SkMatrix44::map2(const float src2[], int count, float dst4[]) const {
841 static const Map2Procf gProc[] = {
842 map2_if, map2_tf, map2_sf, map2_sf, map2_af, map2_af, map2_af, map2_af
843 };
844
845 TypeMask mask = this->getType();
846 Map2Procf proc = (mask & kPerspective_Mask) ? map2_pf : gProc[mask];
847 proc(fMat, src2, count, dst4);
848 }
849
map2(const double src2[],int count,double dst4[]) const850 void SkMatrix44::map2(const double src2[], int count, double dst4[]) const {
851 static const Map2Procd gProc[] = {
852 map2_id, map2_td, map2_sd, map2_sd, map2_ad, map2_ad, map2_ad, map2_ad
853 };
854
855 TypeMask mask = this->getType();
856 Map2Procd proc = (mask & kPerspective_Mask) ? map2_pd : gProc[mask];
857 proc(fMat, src2, count, dst4);
858 }
859
preserves2dAxisAlignment(SkMScalar epsilon) const860 bool SkMatrix44::preserves2dAxisAlignment (SkMScalar epsilon) const {
861
862 // Can't check (mask & kPerspective_Mask) because Z isn't relevant here.
863 if (0 != perspX() || 0 != perspY()) return false;
864
865 // A matrix with two non-zeroish values in any of the upper right
866 // rows or columns will skew. If only one value in each row or
867 // column is non-zeroish, we get a scale plus perhaps a 90-degree
868 // rotation.
869 int col0 = 0;
870 int col1 = 0;
871 int row0 = 0;
872 int row1 = 0;
873
874 // Must test against epsilon, not 0, because we can get values
875 // around 6e-17 in the matrix that "should" be 0.
876
877 if (SkMScalarAbs(fMat[0][0]) > epsilon) {
878 col0++;
879 row0++;
880 }
881 if (SkMScalarAbs(fMat[0][1]) > epsilon) {
882 col1++;
883 row0++;
884 }
885 if (SkMScalarAbs(fMat[1][0]) > epsilon) {
886 col0++;
887 row1++;
888 }
889 if (SkMScalarAbs(fMat[1][1]) > epsilon) {
890 col1++;
891 row1++;
892 }
893 if (col0 > 1 || col1 > 1 || row0 > 1 || row1 > 1) {
894 return false;
895 }
896
897 return true;
898 }
899
900 ///////////////////////////////////////////////////////////////////////////////
901
dump() const902 void SkMatrix44::dump() const {
903 static const char* format =
904 "[%g %g %g %g][%g %g %g %g][%g %g %g %g][%g %g %g %g]\n";
905 #if 0
906 SkDebugf(format,
907 fMat[0][0], fMat[1][0], fMat[2][0], fMat[3][0],
908 fMat[0][1], fMat[1][1], fMat[2][1], fMat[3][1],
909 fMat[0][2], fMat[1][2], fMat[2][2], fMat[3][2],
910 fMat[0][3], fMat[1][3], fMat[2][3], fMat[3][3]);
911 #else
912 SkDebugf(format,
913 fMat[0][0], fMat[0][1], fMat[0][2], fMat[0][3],
914 fMat[1][0], fMat[1][1], fMat[1][2], fMat[1][3],
915 fMat[2][0], fMat[2][1], fMat[2][2], fMat[2][3],
916 fMat[3][0], fMat[3][1], fMat[3][2], fMat[3][3]);
917 #endif
918 }
919
920 ///////////////////////////////////////////////////////////////////////////////
921
initFromMatrix(SkMScalar dst[4][4],const SkMatrix & src)922 static void initFromMatrix(SkMScalar dst[4][4], const SkMatrix& src) {
923 dst[0][0] = SkScalarToMScalar(src[SkMatrix::kMScaleX]);
924 dst[1][0] = SkScalarToMScalar(src[SkMatrix::kMSkewX]);
925 dst[2][0] = 0;
926 dst[3][0] = SkScalarToMScalar(src[SkMatrix::kMTransX]);
927 dst[0][1] = SkScalarToMScalar(src[SkMatrix::kMSkewY]);
928 dst[1][1] = SkScalarToMScalar(src[SkMatrix::kMScaleY]);
929 dst[2][1] = 0;
930 dst[3][1] = SkScalarToMScalar(src[SkMatrix::kMTransY]);
931 dst[0][2] = 0;
932 dst[1][2] = 0;
933 dst[2][2] = 1;
934 dst[3][2] = 0;
935 dst[0][3] = SkScalarToMScalar(src[SkMatrix::kMPersp0]);
936 dst[1][3] = SkScalarToMScalar(src[SkMatrix::kMPersp1]);
937 dst[2][3] = 0;
938 dst[3][3] = SkScalarToMScalar(src[SkMatrix::kMPersp2]);
939 }
940
SkMatrix44(const SkMatrix & src)941 SkMatrix44::SkMatrix44(const SkMatrix& src) {
942 this->operator=(src);
943 }
944
operator =(const SkMatrix & src)945 SkMatrix44& SkMatrix44::operator=(const SkMatrix& src) {
946 initFromMatrix(fMat, src);
947
948 if (src.isIdentity()) {
949 this->setTypeMask(kIdentity_Mask);
950 } else {
951 this->dirtyTypeMask();
952 }
953 return *this;
954 }
955
operator SkMatrix() const956 SkMatrix44::operator SkMatrix() const {
957 SkMatrix dst;
958
959 dst[SkMatrix::kMScaleX] = SkMScalarToScalar(fMat[0][0]);
960 dst[SkMatrix::kMSkewX] = SkMScalarToScalar(fMat[1][0]);
961 dst[SkMatrix::kMTransX] = SkMScalarToScalar(fMat[3][0]);
962
963 dst[SkMatrix::kMSkewY] = SkMScalarToScalar(fMat[0][1]);
964 dst[SkMatrix::kMScaleY] = SkMScalarToScalar(fMat[1][1]);
965 dst[SkMatrix::kMTransY] = SkMScalarToScalar(fMat[3][1]);
966
967 dst[SkMatrix::kMPersp0] = SkMScalarToScalar(fMat[0][3]);
968 dst[SkMatrix::kMPersp1] = SkMScalarToScalar(fMat[1][3]);
969 dst[SkMatrix::kMPersp2] = SkMScalarToScalar(fMat[3][3]);
970
971 return dst;
972 }
973