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