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