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