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