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