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