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