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