blob: 440bf36b62e8cefec9fed415673b48a1be03ae71 [file] [log] [blame]
reed@google.com8260a892011-06-13 14:02:52 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * 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.
reed@google.com8260a892011-06-13 14:02:52 +00006 */
7
reed@google.com8260a892011-06-13 14:02:52 +00008#include "SkMatrix44.h"
9
reed@google.com7d683352012-12-03 21:19:52 +000010static 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}
jamesr@chromium.orgdeb4c162012-11-29 21:17:16 +000014
reed@google.com7d683352012-12-03 21:19:52 +000015bool 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
reed@google.com631940c2012-11-27 13:13:22 +000028 for (int i = 0; i < 16; ++i) {
29 if (a[i] != b[i]) {
30 return false;
31 }
32 }
33 return true;
reed@google.com7d683352012-12-03 21:19:52 +000034#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
52int SkMatrix44::computeTypeMask() const {
53 unsigned mask = 0;
skia.committer@gmail.com0264fb42012-12-06 02:01:25 +000054
reed@google.com7d683352012-12-03 21:19:52 +000055 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;
reed@google.com8260a892011-06-13 14:02:52 +000073}
74
75///////////////////////////////////////////////////////////////////////////////
76
reed@google.comda9fac02011-06-13 14:46:52 +000077void 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 }
vollick@chromium.org5596a692012-11-13 20:12:00 +000083#elif defined SK_MSCALAR_IS_FLOAT
reed@google.comda9fac02011-06-13 14:46:52 +000084 memcpy(dst, src, 16 * sizeof(float));
85#endif
86}
87
88void SkMatrix44::asColMajord(double dst[]) const {
89 const SkMScalar* src = &fMat[0][0];
90#ifdef SK_MSCALAR_IS_DOUBLE
91 memcpy(dst, src, 16 * sizeof(double));
vollick@chromium.org5596a692012-11-13 20:12:00 +000092#elif defined SK_MSCALAR_IS_FLOAT
reed@google.comda9fac02011-06-13 14:46:52 +000093 for (int i = 0; i < 16; ++i) {
94 dst[i] = SkMScalarToDouble(src[i]);
95 }
96#endif
97}
98
99void SkMatrix44::asRowMajorf(float dst[]) const {
100 const SkMScalar* src = &fMat[0][0];
101 for (int i = 0; i < 4; ++i) {
102 dst[0] = SkMScalarToFloat(src[0]);
103 dst[4] = SkMScalarToFloat(src[1]);
104 dst[8] = SkMScalarToFloat(src[2]);
105 dst[12] = SkMScalarToFloat(src[3]);
106 src += 4;
107 dst += 1;
108 }
109}
110
111void SkMatrix44::asRowMajord(double dst[]) const {
112 const SkMScalar* src = &fMat[0][0];
113 for (int i = 0; i < 4; ++i) {
114 dst[0] = SkMScalarToDouble(src[0]);
115 dst[4] = SkMScalarToDouble(src[1]);
116 dst[8] = SkMScalarToDouble(src[2]);
117 dst[12] = SkMScalarToDouble(src[3]);
118 src += 4;
119 dst += 1;
120 }
121}
122
vollick@chromium.orgf11cf9f2012-11-19 21:02:06 +0000123void SkMatrix44::setColMajorf(const float src[]) {
124 SkMScalar* dst = &fMat[0][0];
125#ifdef SK_MSCALAR_IS_DOUBLE
126 for (int i = 0; i < 16; ++i) {
127 dst[i] = SkMScalarToFloat(src[i]);
128 }
129#elif defined SK_MSCALAR_IS_FLOAT
130 memcpy(dst, src, 16 * sizeof(float));
131#endif
reed@google.com7d683352012-12-03 21:19:52 +0000132
133 this->dirtyTypeMask();
vollick@chromium.orgf11cf9f2012-11-19 21:02:06 +0000134}
135
136void SkMatrix44::setColMajord(const double src[]) {
137 SkMScalar* dst = &fMat[0][0];
138#ifdef SK_MSCALAR_IS_DOUBLE
139 memcpy(dst, src, 16 * sizeof(double));
140#elif defined SK_MSCALAR_IS_FLOAT
141 for (int i = 0; i < 16; ++i) {
robertphillips@google.com93f03322012-12-03 17:35:19 +0000142 dst[i] = SkDoubleToMScalar(src[i]);
vollick@chromium.orgf11cf9f2012-11-19 21:02:06 +0000143 }
144#endif
reed@google.com7d683352012-12-03 21:19:52 +0000145
146 this->dirtyTypeMask();
vollick@chromium.orgf11cf9f2012-11-19 21:02:06 +0000147}
148
149void SkMatrix44::setRowMajorf(const float src[]) {
150 SkMScalar* dst = &fMat[0][0];
151 for (int i = 0; i < 4; ++i) {
152 dst[0] = SkMScalarToFloat(src[0]);
153 dst[4] = SkMScalarToFloat(src[1]);
154 dst[8] = SkMScalarToFloat(src[2]);
155 dst[12] = SkMScalarToFloat(src[3]);
156 src += 4;
157 dst += 1;
158 }
reed@google.com7d683352012-12-03 21:19:52 +0000159 this->dirtyTypeMask();
vollick@chromium.orgf11cf9f2012-11-19 21:02:06 +0000160}
161
162void SkMatrix44::setRowMajord(const double src[]) {
163 SkMScalar* dst = &fMat[0][0];
164 for (int i = 0; i < 4; ++i) {
robertphillips@google.com93f03322012-12-03 17:35:19 +0000165 dst[0] = SkDoubleToMScalar(src[0]);
166 dst[4] = SkDoubleToMScalar(src[1]);
167 dst[8] = SkDoubleToMScalar(src[2]);
168 dst[12] = SkDoubleToMScalar(src[3]);
vollick@chromium.orgf11cf9f2012-11-19 21:02:06 +0000169 src += 4;
170 dst += 1;
171 }
reed@google.com7d683352012-12-03 21:19:52 +0000172 this->dirtyTypeMask();
vollick@chromium.orgf11cf9f2012-11-19 21:02:06 +0000173}
174
reed@google.comda9fac02011-06-13 14:46:52 +0000175///////////////////////////////////////////////////////////////////////////////
176
reed@google.com7d683352012-12-03 21:19:52 +0000177const SkMatrix44& SkMatrix44::I() {
reed@google.com1adad342012-12-10 21:21:27 +0000178 static const SkMatrix44 gIdentity44(kIdentity_Constructor);
179 return gIdentity44;
reed@google.com8260a892011-06-13 14:02:52 +0000180}
181
reed@google.com8260a892011-06-13 14:02:52 +0000182void SkMatrix44::setIdentity() {
shawnsingh@chromium.org5a6cd352013-08-28 18:55:25 +0000183 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;
reed@google.com7d683352012-12-03 21:19:52 +0000199 this->setTypeMask(kIdentity_Mask);
reed@google.com8260a892011-06-13 14:02:52 +0000200}
201
202void SkMatrix44::set3x3(SkMScalar m00, SkMScalar m01, SkMScalar m02,
203 SkMScalar m10, SkMScalar m11, SkMScalar m12,
204 SkMScalar m20, SkMScalar m21, SkMScalar m22) {
reed@google.com8260a892011-06-13 14:02:52 +0000205 fMat[0][0] = m00; fMat[0][1] = m01; fMat[0][2] = m02; fMat[0][3] = 0;
206 fMat[1][0] = m10; fMat[1][1] = m11; fMat[1][2] = m12; fMat[1][3] = 0;
207 fMat[2][0] = m20; fMat[2][1] = m21; fMat[2][2] = m22; fMat[2][3] = 0;
208 fMat[3][0] = 0; fMat[3][1] = 0; fMat[3][2] = 0; fMat[3][3] = 1;
reed@google.com7d683352012-12-03 21:19:52 +0000209 this->dirtyTypeMask();
reed@google.com8260a892011-06-13 14:02:52 +0000210}
211
212///////////////////////////////////////////////////////////////////////////////
213
reed@google.com99b5c7f2012-12-05 22:13:59 +0000214void SkMatrix44::setTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz) {
reed@google.com8260a892011-06-13 14:02:52 +0000215 this->setIdentity();
skia.committer@gmail.come659c2e2012-12-04 02:01:25 +0000216
reed@google.com99b5c7f2012-12-05 22:13:59 +0000217 if (!dx && !dy && !dz) {
218 return;
reed@google.com7d683352012-12-03 21:19:52 +0000219 }
skia.committer@gmail.com0264fb42012-12-06 02:01:25 +0000220
reed@google.com99b5c7f2012-12-05 22:13:59 +0000221 fMat[3][0] = dx;
222 fMat[3][1] = dy;
223 fMat[3][2] = dz;
224 this->setTypeMask(kTranslate_Mask);
reed@google.com8260a892011-06-13 14:02:52 +0000225}
226
227void SkMatrix44::preTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz) {
reed@google.com99b5c7f2012-12-05 22:13:59 +0000228 if (!dx && !dy && !dz) {
229 return;
230 }
231
reed@google.com99b5c7f2012-12-05 22:13:59 +0000232 for (int i = 0; i < 4; ++i) {
commit-bot@chromium.org658e28b2013-10-29 21:08:51 +0000233 fMat[3][i] = fMat[0][i] * dx + fMat[1][i] * dy + fMat[2][i] * dz + fMat[3][i];
reed@google.com99b5c7f2012-12-05 22:13:59 +0000234 }
235 this->dirtyTypeMask();
reed@google.com8260a892011-06-13 14:02:52 +0000236}
237
238void SkMatrix44::postTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz) {
reed@google.com99b5c7f2012-12-05 22:13:59 +0000239 if (!dx && !dy && !dz) {
240 return;
241 }
242
243 if (this->getType() & kPerspective_Mask) {
244 for (int i = 0; i < 4; ++i) {
245 fMat[i][0] += fMat[i][3] * dx;
246 fMat[i][1] += fMat[i][3] * dy;
247 fMat[i][2] += fMat[i][3] * dz;
248 }
249 } else {
250 fMat[3][0] += dx;
251 fMat[3][1] += dy;
252 fMat[3][2] += dz;
253 this->dirtyTypeMask();
254 }
reed@google.com8260a892011-06-13 14:02:52 +0000255}
256
257///////////////////////////////////////////////////////////////////////////////
258
259void SkMatrix44::setScale(SkMScalar sx, SkMScalar sy, SkMScalar sz) {
reed@google.com99b5c7f2012-12-05 22:13:59 +0000260 this->setIdentity();
261
262 if (1 == sx && 1 == sy && 1 == sz) {
263 return;
264 }
265
reed@google.com8260a892011-06-13 14:02:52 +0000266 fMat[0][0] = sx;
267 fMat[1][1] = sy;
268 fMat[2][2] = sz;
reed@google.com99b5c7f2012-12-05 22:13:59 +0000269 this->setTypeMask(kScale_Mask);
reed@google.com8260a892011-06-13 14:02:52 +0000270}
271
272void SkMatrix44::preScale(SkMScalar sx, SkMScalar sy, SkMScalar sz) {
reed@google.com99b5c7f2012-12-05 22:13:59 +0000273 if (1 == sx && 1 == sy && 1 == sz) {
274 return;
275 }
skia.committer@gmail.com0264fb42012-12-06 02:01:25 +0000276
shawnsingh@chromium.orgf81f97e2012-12-13 22:21:36 +0000277 // The implementation matrix * pureScale can be shortcut
278 // by knowing that pureScale components effectively scale
279 // the columns of the original matrix.
280 for (int i = 0; i < 4; i++) {
281 fMat[0][i] *= sx;
282 fMat[1][i] *= sy;
283 fMat[2][i] *= sz;
284 }
285 this->dirtyTypeMask();
reed@google.com8260a892011-06-13 14:02:52 +0000286}
287
288void SkMatrix44::postScale(SkMScalar sx, SkMScalar sy, SkMScalar sz) {
reed@google.com99b5c7f2012-12-05 22:13:59 +0000289 if (1 == sx && 1 == sy && 1 == sz) {
290 return;
291 }
skia.committer@gmail.com0264fb42012-12-06 02:01:25 +0000292
reed@google.com8260a892011-06-13 14:02:52 +0000293 for (int i = 0; i < 4; i++) {
294 fMat[i][0] *= sx;
295 fMat[i][1] *= sy;
296 fMat[i][2] *= sz;
297 }
reed@google.com7d683352012-12-03 21:19:52 +0000298 this->dirtyTypeMask();
reed@google.com8260a892011-06-13 14:02:52 +0000299}
300
301///////////////////////////////////////////////////////////////////////////////
302
303void SkMatrix44::setRotateAbout(SkMScalar x, SkMScalar y, SkMScalar z,
304 SkMScalar radians) {
reed@google.com7d683352012-12-03 21:19:52 +0000305 double len2 = (double)x * x + (double)y * y + (double)z * z;
306 if (1 != len2) {
307 if (0 == len2) {
reed@google.com8260a892011-06-13 14:02:52 +0000308 this->setIdentity();
309 return;
310 }
311 double scale = 1 / sqrt(len2);
bsalomon@google.com9d12f5c2011-09-29 18:08:18 +0000312 x = SkDoubleToMScalar(x * scale);
313 y = SkDoubleToMScalar(y * scale);
314 z = SkDoubleToMScalar(z * scale);
reed@google.com8260a892011-06-13 14:02:52 +0000315 }
316 this->setRotateAboutUnit(x, y, z, radians);
317}
318
319void SkMatrix44::setRotateAboutUnit(SkMScalar x, SkMScalar y, SkMScalar z,
320 SkMScalar radians) {
321 double c = cos(radians);
322 double s = sin(radians);
323 double C = 1 - c;
324 double xs = x * s;
325 double ys = y * s;
326 double zs = z * s;
327 double xC = x * C;
328 double yC = y * C;
329 double zC = z * C;
330 double xyC = x * yC;
331 double yzC = y * zC;
332 double zxC = z * xC;
333
334 // if you're looking at wikipedia, remember that we're column major.
bsalomon@google.com9d12f5c2011-09-29 18:08:18 +0000335 this->set3x3(SkDoubleToMScalar(x * xC + c), // scale x
336 SkDoubleToMScalar(xyC + zs), // skew x
337 SkDoubleToMScalar(zxC - ys), // trans x
338
339 SkDoubleToMScalar(xyC - zs), // skew y
340 SkDoubleToMScalar(y * yC + c), // scale y
341 SkDoubleToMScalar(yzC + xs), // trans y
342
343 SkDoubleToMScalar(zxC + ys), // persp x
344 SkDoubleToMScalar(yzC - xs), // persp y
345 SkDoubleToMScalar(z * zC + c)); // persp 2
reed@google.com8260a892011-06-13 14:02:52 +0000346}
347
348///////////////////////////////////////////////////////////////////////////////
349
reed@google.com99b5c7f2012-12-05 22:13:59 +0000350static bool bits_isonly(int value, int mask) {
351 return 0 == (value & ~mask);
352}
353
reed@google.com8260a892011-06-13 14:02:52 +0000354void SkMatrix44::setConcat(const SkMatrix44& a, const SkMatrix44& b) {
reed@google.com99b5c7f2012-12-05 22:13:59 +0000355 const SkMatrix44::TypeMask a_mask = a.getType();
356 const SkMatrix44::TypeMask b_mask = b.getType();
357
358 if (kIdentity_Mask == a_mask) {
reed@google.com7d683352012-12-03 21:19:52 +0000359 *this = b;
360 return;
361 }
reed@google.com99b5c7f2012-12-05 22:13:59 +0000362 if (kIdentity_Mask == b_mask) {
reed@google.com7d683352012-12-03 21:19:52 +0000363 *this = a;
364 return;
365 }
366
367 bool useStorage = (this == &a || this == &b);
368 SkMScalar storage[16];
369 SkMScalar* result = useStorage ? storage : &fMat[0][0];
370
reed@google.com2b165702013-01-17 16:01:19 +0000371 // Both matrices are at most scale+translate
reed@google.com99b5c7f2012-12-05 22:13:59 +0000372 if (bits_isonly(a_mask | b_mask, kScale_Mask | kTranslate_Mask)) {
reed@google.com99b5c7f2012-12-05 22:13:59 +0000373 result[0] = a.fMat[0][0] * b.fMat[0][0];
reed@google.com2b165702013-01-17 16:01:19 +0000374 result[1] = result[2] = result[3] = result[4] = 0;
reed@google.com99b5c7f2012-12-05 22:13:59 +0000375 result[5] = a.fMat[1][1] * b.fMat[1][1];
reed@google.com2b165702013-01-17 16:01:19 +0000376 result[6] = result[7] = result[8] = result[9] = 0;
reed@google.com99b5c7f2012-12-05 22:13:59 +0000377 result[10] = a.fMat[2][2] * b.fMat[2][2];
reed@google.com2b165702013-01-17 16:01:19 +0000378 result[11] = 0;
reed@google.com99b5c7f2012-12-05 22:13:59 +0000379 result[12] = a.fMat[0][0] * b.fMat[3][0] + a.fMat[3][0];
380 result[13] = a.fMat[1][1] * b.fMat[3][1] + a.fMat[3][1];
381 result[14] = a.fMat[2][2] * b.fMat[3][2] + a.fMat[3][2];
382 result[15] = 1;
383 } else {
384 for (int j = 0; j < 4; j++) {
385 for (int i = 0; i < 4; i++) {
386 double value = 0;
387 for (int k = 0; k < 4; k++) {
388 value += SkMScalarToDouble(a.fMat[k][i]) * b.fMat[j][k];
389 }
390 *result++ = SkDoubleToMScalar(value);
reed@google.com8260a892011-06-13 14:02:52 +0000391 }
reed@google.com8260a892011-06-13 14:02:52 +0000392 }
393 }
reed@google.com99b5c7f2012-12-05 22:13:59 +0000394
reed@google.com7d683352012-12-03 21:19:52 +0000395 if (useStorage) {
tomhudson@google.com7cfb9c72013-01-17 13:29:35 +0000396 memcpy(fMat, storage, sizeof(storage));
reed@google.com7d683352012-12-03 21:19:52 +0000397 }
reed@google.com7d683352012-12-03 21:19:52 +0000398 this->dirtyTypeMask();
reed@google.com8260a892011-06-13 14:02:52 +0000399}
400
401///////////////////////////////////////////////////////////////////////////////
402
reed@google.com8260a892011-06-13 14:02:52 +0000403/** We always perform the calculation in doubles, to avoid prematurely losing
404 precision along the way. This relies on the compiler automatically
405 promoting our SkMScalar values to double (if needed).
406 */
407double SkMatrix44::determinant() const {
mike@reedtribe.orgf8b1ebc2012-12-10 03:27:47 +0000408 if (this->isIdentity()) {
409 return 1;
410 }
411 if (this->isScaleTranslate()) {
412 return fMat[0][0] * fMat[1][1] * fMat[2][2] * fMat[3][3];
413 }
414
tomhudson@google.com9973a8a2012-12-13 09:55:42 +0000415 double a00 = fMat[0][0];
416 double a01 = fMat[0][1];
417 double a02 = fMat[0][2];
418 double a03 = fMat[0][3];
419 double a10 = fMat[1][0];
420 double a11 = fMat[1][1];
421 double a12 = fMat[1][2];
422 double a13 = fMat[1][3];
423 double a20 = fMat[2][0];
424 double a21 = fMat[2][1];
425 double a22 = fMat[2][2];
426 double a23 = fMat[2][3];
427 double a30 = fMat[3][0];
428 double a31 = fMat[3][1];
429 double a32 = fMat[3][2];
430 double a33 = fMat[3][3];
431
432 double b00 = a00 * a11 - a01 * a10;
433 double b01 = a00 * a12 - a02 * a10;
434 double b02 = a00 * a13 - a03 * a10;
435 double b03 = a01 * a12 - a02 * a11;
436 double b04 = a01 * a13 - a03 * a11;
437 double b05 = a02 * a13 - a03 * a12;
438 double b06 = a20 * a31 - a21 * a30;
439 double b07 = a20 * a32 - a22 * a30;
440 double b08 = a20 * a33 - a23 * a30;
441 double b09 = a21 * a32 - a22 * a31;
442 double b10 = a21 * a33 - a23 * a31;
443 double b11 = a22 * a33 - a23 * a32;
444
445 // Calculate the determinant
446 return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
reed@google.com8260a892011-06-13 14:02:52 +0000447}
448
449///////////////////////////////////////////////////////////////////////////////
450
reed@google.com8260a892011-06-13 14:02:52 +0000451bool SkMatrix44::invert(SkMatrix44* inverse) const {
mike@reedtribe.orgf8b1ebc2012-12-10 03:27:47 +0000452 if (this->isIdentity()) {
reed@google.com7d683352012-12-03 21:19:52 +0000453 if (inverse) {
shawnsingh@chromium.org5a6cd352013-08-28 18:55:25 +0000454 inverse->setIdentity();
reed@google.com7d683352012-12-03 21:19:52 +0000455 return true;
456 }
457 }
mike@reedtribe.orgf8b1ebc2012-12-10 03:27:47 +0000458 if (this->isTranslate()) {
reed@google.com99b5c7f2012-12-05 22:13:59 +0000459 if (inverse) {
460 inverse->setTranslate(-fMat[3][0], -fMat[3][1], -fMat[3][2]);
461 }
462 return true;
463 }
mike@reedtribe.orgf8b1ebc2012-12-10 03:27:47 +0000464 if (this->isScaleTranslate()) {
reed@google.com99b5c7f2012-12-05 22:13:59 +0000465 if (0 == fMat[0][0] * fMat[1][1] * fMat[2][2]) {
466 return false;
467 }
reed@google.com99b5c7f2012-12-05 22:13:59 +0000468
skia.committer@gmail.com772c4e62013-08-30 07:01:34 +0000469 if (inverse) {
470 double invXScale = 1 / fMat[0][0];
471 double invYScale = 1 / fMat[1][1];
472 double invZScale = 1 / fMat[2][2];
reed@google.com99b5c7f2012-12-05 22:13:59 +0000473
skia.committer@gmail.com772c4e62013-08-30 07:01:34 +0000474 inverse->fMat[0][0] = invXScale;
475 inverse->fMat[0][1] = 0;
476 inverse->fMat[0][2] = 0;
477 inverse->fMat[0][3] = 0;
478
479 inverse->fMat[1][0] = 0;
480 inverse->fMat[1][1] = invYScale;
481 inverse->fMat[1][2] = 0;
482 inverse->fMat[1][3] = 0;
483
484 inverse->fMat[2][0] = 0;
commit-bot@chromium.orgc33d6212013-08-29 15:34:50 +0000485 inverse->fMat[2][1] = 0;
skia.committer@gmail.com772c4e62013-08-30 07:01:34 +0000486 inverse->fMat[2][2] = invZScale;
487 inverse->fMat[2][3] = 0;
488
commit-bot@chromium.orgc33d6212013-08-29 15:34:50 +0000489 inverse->fMat[3][0] = -fMat[3][0] * invXScale;
490 inverse->fMat[3][1] = -fMat[3][1] * invYScale;
491 inverse->fMat[3][2] = -fMat[3][2] * invZScale;
492 inverse->fMat[3][3] = 1;
shawnsingh@chromium.orgb6823c12013-08-22 20:24:21 +0000493
commit-bot@chromium.orgc33d6212013-08-29 15:34:50 +0000494 inverse->setTypeMask(this->getType());
shawnsingh@chromium.org5a6cd352013-08-28 18:55:25 +0000495 }
496
reed@google.com99b5c7f2012-12-05 22:13:59 +0000497 return true;
498 }
499
tomhudson@google.com9973a8a2012-12-13 09:55:42 +0000500 double a00 = fMat[0][0];
501 double a01 = fMat[0][1];
502 double a02 = fMat[0][2];
503 double a03 = fMat[0][3];
504 double a10 = fMat[1][0];
505 double a11 = fMat[1][1];
506 double a12 = fMat[1][2];
507 double a13 = fMat[1][3];
508 double a20 = fMat[2][0];
509 double a21 = fMat[2][1];
510 double a22 = fMat[2][2];
511 double a23 = fMat[2][3];
512 double a30 = fMat[3][0];
513 double a31 = fMat[3][1];
514 double a32 = fMat[3][2];
515 double a33 = fMat[3][3];
516
shawnsingh@chromium.orgb6823c12013-08-22 20:24:21 +0000517 if (!(this->getType() & kPerspective_Mask)) {
518 // If we know the matrix has no perspective, then the perspective
519 // component is (0, 0, 0, 1). We can use this information to save a lot
520 // of arithmetic that would otherwise be spent to compute the inverse
521 // of a general matrix.
522
523 SkASSERT(a03 == 0);
524 SkASSERT(a13 == 0);
525 SkASSERT(a23 == 0);
526 SkASSERT(a33 == 1);
527
528 double b00 = a00 * a11 - a01 * a10;
529 double b01 = a00 * a12 - a02 * a10;
530 double b03 = a01 * a12 - a02 * a11;
531 double b06 = a20 * a31 - a21 * a30;
532 double b07 = a20 * a32 - a22 * a30;
533 double b08 = a20;
534 double b09 = a21 * a32 - a22 * a31;
535 double b10 = a21;
536 double b11 = a22;
537
538 // Calculate the determinant
539 double det = b00 * b11 - b01 * b10 + b03 * b08;
540
541 double invdet = 1.0 / det;
542 // If det is zero, we want to return false. However, we also want to return false
543 // if 1/det overflows to infinity (i.e. det is denormalized). Both of these are
544 // handled by checking that 1/det is finite.
545 if (!sk_float_isfinite(invdet)) {
546 return false;
547 }
548 if (NULL == inverse) {
549 return true;
550 }
551
552 b00 *= invdet;
553 b01 *= invdet;
554 b03 *= invdet;
555 b06 *= invdet;
556 b07 *= invdet;
557 b08 *= invdet;
558 b09 *= invdet;
559 b10 *= invdet;
560 b11 *= invdet;
561
562 inverse->fMat[0][0] = SkDoubleToMScalar(a11 * b11 - a12 * b10);
563 inverse->fMat[0][1] = SkDoubleToMScalar(a02 * b10 - a01 * b11);
564 inverse->fMat[0][2] = SkDoubleToMScalar(b03);
565 inverse->fMat[0][3] = 0;
566 inverse->fMat[1][0] = SkDoubleToMScalar(a12 * b08 - a10 * b11);
567 inverse->fMat[1][1] = SkDoubleToMScalar(a00 * b11 - a02 * b08);
568 inverse->fMat[1][2] = SkDoubleToMScalar(-b01);
569 inverse->fMat[1][3] = 0;
570 inverse->fMat[2][0] = SkDoubleToMScalar(a10 * b10 - a11 * b08);
571 inverse->fMat[2][1] = SkDoubleToMScalar(a01 * b08 - a00 * b10);
572 inverse->fMat[2][2] = SkDoubleToMScalar(b00);
573 inverse->fMat[2][3] = 0;
574 inverse->fMat[3][0] = SkDoubleToMScalar(a11 * b07 - a10 * b09 - a12 * b06);
575 inverse->fMat[3][1] = SkDoubleToMScalar(a00 * b09 - a01 * b07 + a02 * b06);
576 inverse->fMat[3][2] = SkDoubleToMScalar(a31 * b01 - a30 * b03 - a32 * b00);
577 inverse->fMat[3][3] = 1;
578
579 inverse->setTypeMask(this->getType());
580 return true;
581 }
582
tomhudson@google.com9973a8a2012-12-13 09:55:42 +0000583 double b00 = a00 * a11 - a01 * a10;
584 double b01 = a00 * a12 - a02 * a10;
585 double b02 = a00 * a13 - a03 * a10;
586 double b03 = a01 * a12 - a02 * a11;
587 double b04 = a01 * a13 - a03 * a11;
588 double b05 = a02 * a13 - a03 * a12;
589 double b06 = a20 * a31 - a21 * a30;
590 double b07 = a20 * a32 - a22 * a30;
591 double b08 = a20 * a33 - a23 * a30;
592 double b09 = a21 * a32 - a22 * a31;
593 double b10 = a21 * a33 - a23 * a31;
594 double b11 = a22 * a33 - a23 * a32;
595
596 // Calculate the determinant
597 double det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
598
commit-bot@chromium.orgf02f0782013-08-20 15:25:04 +0000599 double invdet = 1.0 / det;
600 // If det is zero, we want to return false. However, we also want to return false
601 // if 1/det overflows to infinity (i.e. det is denormalized). Both of these are
602 // handled by checking that 1/det is finite.
603 if (!sk_float_isfinite(invdet)) {
reed@google.com8260a892011-06-13 14:02:52 +0000604 return false;
605 }
606 if (NULL == inverse) {
607 return true;
608 }
609
tomhudson@google.com9973a8a2012-12-13 09:55:42 +0000610 b00 *= invdet;
611 b01 *= invdet;
612 b02 *= invdet;
613 b03 *= invdet;
614 b04 *= invdet;
615 b05 *= invdet;
616 b06 *= invdet;
617 b07 *= invdet;
618 b08 *= invdet;
619 b09 *= invdet;
620 b10 *= invdet;
621 b11 *= invdet;
reed@google.com8260a892011-06-13 14:02:52 +0000622
tomhudson@google.com9973a8a2012-12-13 09:55:42 +0000623 inverse->fMat[0][0] = SkDoubleToMScalar(a11 * b11 - a12 * b10 + a13 * b09);
624 inverse->fMat[0][1] = SkDoubleToMScalar(a02 * b10 - a01 * b11 - a03 * b09);
625 inverse->fMat[0][2] = SkDoubleToMScalar(a31 * b05 - a32 * b04 + a33 * b03);
626 inverse->fMat[0][3] = SkDoubleToMScalar(a22 * b04 - a21 * b05 - a23 * b03);
627 inverse->fMat[1][0] = SkDoubleToMScalar(a12 * b08 - a10 * b11 - a13 * b07);
628 inverse->fMat[1][1] = SkDoubleToMScalar(a00 * b11 - a02 * b08 + a03 * b07);
629 inverse->fMat[1][2] = SkDoubleToMScalar(a32 * b02 - a30 * b05 - a33 * b01);
630 inverse->fMat[1][3] = SkDoubleToMScalar(a20 * b05 - a22 * b02 + a23 * b01);
631 inverse->fMat[2][0] = SkDoubleToMScalar(a10 * b10 - a11 * b08 + a13 * b06);
632 inverse->fMat[2][1] = SkDoubleToMScalar(a01 * b08 - a00 * b10 - a03 * b06);
633 inverse->fMat[2][2] = SkDoubleToMScalar(a30 * b04 - a31 * b02 + a33 * b00);
634 inverse->fMat[2][3] = SkDoubleToMScalar(a21 * b02 - a20 * b04 - a23 * b00);
635 inverse->fMat[3][0] = SkDoubleToMScalar(a11 * b07 - a10 * b09 - a12 * b06);
636 inverse->fMat[3][1] = SkDoubleToMScalar(a00 * b09 - a01 * b07 + a02 * b06);
637 inverse->fMat[3][2] = SkDoubleToMScalar(a31 * b01 - a30 * b03 - a32 * b00);
638 inverse->fMat[3][3] = SkDoubleToMScalar(a20 * b03 - a21 * b01 + a22 * b00);
639 inverse->dirtyTypeMask();
reed@google.com8260a892011-06-13 14:02:52 +0000640
reed@google.com8260a892011-06-13 14:02:52 +0000641 return true;
642}
643
644///////////////////////////////////////////////////////////////////////////////
645
vollick@chromium.org9b21c252012-11-14 21:33:55 +0000646void SkMatrix44::transpose() {
647 SkTSwap(fMat[0][1], fMat[1][0]);
648 SkTSwap(fMat[0][2], fMat[2][0]);
649 SkTSwap(fMat[0][3], fMat[3][0]);
650 SkTSwap(fMat[1][2], fMat[2][1]);
651 SkTSwap(fMat[1][3], fMat[3][1]);
652 SkTSwap(fMat[2][3], fMat[3][2]);
reed@google.com7d683352012-12-03 21:19:52 +0000653
654 if (!this->isTriviallyIdentity()) {
655 this->dirtyTypeMask();
656 }
vollick@chromium.org9b21c252012-11-14 21:33:55 +0000657}
658
659///////////////////////////////////////////////////////////////////////////////
660
reed@google.com1ea95be2012-11-09 21:39:48 +0000661void SkMatrix44::mapScalars(const SkScalar src[4], SkScalar dst[4]) const {
reed@google.com7d683352012-12-03 21:19:52 +0000662 SkScalar storage[4];
663 SkScalar* result = (src == dst) ? storage : dst;
664
reed@google.com8260a892011-06-13 14:02:52 +0000665 for (int i = 0; i < 4; i++) {
666 SkMScalar value = 0;
667 for (int j = 0; j < 4; j++) {
668 value += fMat[j][i] * src[j];
669 }
bsalomon@google.com72e49b82011-10-27 21:47:03 +0000670 result[i] = SkMScalarToScalar(value);
reed@google.com8260a892011-06-13 14:02:52 +0000671 }
skia.committer@gmail.com0264fb42012-12-06 02:01:25 +0000672
reed@google.com7d683352012-12-03 21:19:52 +0000673 if (storage == result) {
674 memcpy(dst, storage, sizeof(storage));
675 }
reed@google.com8260a892011-06-13 14:02:52 +0000676}
677
reed@google.com1ea95be2012-11-09 21:39:48 +0000678#ifdef SK_MSCALAR_IS_DOUBLE
reed@google.com7d683352012-12-03 21:19:52 +0000679
reed@google.com1ea95be2012-11-09 21:39:48 +0000680void SkMatrix44::mapMScalars(const SkMScalar src[4], SkMScalar dst[4]) const {
reed@google.com7d683352012-12-03 21:19:52 +0000681 SkMScalar storage[4];
682 SkMScalar* result = (src == dst) ? storage : dst;
skia.committer@gmail.com0264fb42012-12-06 02:01:25 +0000683
reed@google.com1ea95be2012-11-09 21:39:48 +0000684 for (int i = 0; i < 4; i++) {
685 SkMScalar value = 0;
686 for (int j = 0; j < 4; j++) {
687 value += fMat[j][i] * src[j];
688 }
reed@google.com7d683352012-12-03 21:19:52 +0000689 result[i] = value;
reed@google.com1ea95be2012-11-09 21:39:48 +0000690 }
skia.committer@gmail.com0264fb42012-12-06 02:01:25 +0000691
reed@google.com7d683352012-12-03 21:19:52 +0000692 if (storage == result) {
693 memcpy(dst, storage, sizeof(storage));
694 }
reed@google.com1ea95be2012-11-09 21:39:48 +0000695}
reed@google.com7d683352012-12-03 21:19:52 +0000696
reed@google.com1ea95be2012-11-09 21:39:48 +0000697#endif
698
reed@google.com99b5c7f2012-12-05 22:13:59 +0000699typedef void (*Map2Procf)(const SkMScalar mat[][4], const float src2[], int count, float dst4[]);
700typedef void (*Map2Procd)(const SkMScalar mat[][4], const double src2[], int count, double dst4[]);
701
702static void map2_if(const SkMScalar mat[][4], const float* SK_RESTRICT src2,
703 int count, float* SK_RESTRICT dst4) {
704 for (int i = 0; i < count; ++i) {
705 dst4[0] = src2[0];
706 dst4[1] = src2[1];
707 dst4[2] = 0;
708 dst4[3] = 1;
709 src2 += 2;
710 dst4 += 4;
711 }
712}
713
714static void map2_id(const SkMScalar mat[][4], const double* SK_RESTRICT src2,
715 int count, double* SK_RESTRICT dst4) {
716 for (int i = 0; i < count; ++i) {
717 dst4[0] = src2[0];
718 dst4[1] = src2[1];
719 dst4[2] = 0;
720 dst4[3] = 1;
721 src2 += 2;
722 dst4 += 4;
723 }
724}
725
726static void map2_tf(const SkMScalar mat[][4], const float* SK_RESTRICT src2,
727 int count, float* SK_RESTRICT dst4) {
728 const float mat30 = SkMScalarToFloat(mat[3][0]);
729 const float mat31 = SkMScalarToFloat(mat[3][1]);
730 const float mat32 = SkMScalarToFloat(mat[3][2]);
731 for (int n = 0; n < count; ++n) {
732 dst4[0] = src2[0] + mat30;
733 dst4[1] = src2[1] + mat31;
734 dst4[2] = mat32;
735 dst4[3] = 1;
736 src2 += 2;
737 dst4 += 4;
738 }
739}
740
741static void map2_td(const SkMScalar mat[][4], const double* SK_RESTRICT src2,
742 int count, double* SK_RESTRICT dst4) {
743 for (int n = 0; n < count; ++n) {
744 dst4[0] = src2[0] + mat[3][0];
745 dst4[1] = src2[1] + mat[3][1];
746 dst4[2] = mat[3][2];
747 dst4[3] = 1;
748 src2 += 2;
749 dst4 += 4;
750 }
751}
752
753static void map2_sf(const SkMScalar mat[][4], const float* SK_RESTRICT src2,
754 int count, float* SK_RESTRICT dst4) {
755 const float mat32 = SkMScalarToFloat(mat[3][2]);
756 for (int n = 0; n < count; ++n) {
757 dst4[0] = SkMScalarToFloat(mat[0][0] * src2[0] + mat[3][0]);
758 dst4[1] = SkMScalarToFloat(mat[1][1] * src2[1] + mat[3][1]);
759 dst4[2] = mat32;
760 dst4[3] = 1;
761 src2 += 2;
762 dst4 += 4;
763 }
764}
765
766static void map2_sd(const SkMScalar mat[][4], const double* SK_RESTRICT src2,
767 int count, double* SK_RESTRICT dst4) {
768 for (int n = 0; n < count; ++n) {
769 dst4[0] = mat[0][0] * src2[0] + mat[3][0];
770 dst4[1] = mat[1][1] * src2[1] + mat[3][1];
771 dst4[2] = mat[3][2];
772 dst4[3] = 1;
773 src2 += 2;
774 dst4 += 4;
775 }
776}
777
778static void map2_af(const SkMScalar mat[][4], const float* SK_RESTRICT src2,
779 int count, float* SK_RESTRICT dst4) {
commit-bot@chromium.org658e28b2013-10-29 21:08:51 +0000780 SkMScalar r;
reed@google.com99b5c7f2012-12-05 22:13:59 +0000781 for (int n = 0; n < count; ++n) {
commit-bot@chromium.org658e28b2013-10-29 21:08:51 +0000782 SkMScalar sx = SkFloatToMScalar(src2[0]);
783 SkMScalar sy = SkFloatToMScalar(src2[1]);
reed@google.com99b5c7f2012-12-05 22:13:59 +0000784 r = mat[0][0] * sx + mat[1][0] * sy + mat[3][0];
785 dst4[0] = SkMScalarToFloat(r);
786 r = mat[0][1] * sx + mat[1][1] * sy + mat[3][1];
787 dst4[1] = SkMScalarToFloat(r);
788 r = mat[0][2] * sx + mat[1][2] * sy + mat[3][2];
789 dst4[2] = SkMScalarToFloat(r);
790 dst4[3] = 1;
791 src2 += 2;
792 dst4 += 4;
793 }
794}
795
796static void map2_ad(const SkMScalar mat[][4], const double* SK_RESTRICT src2,
797 int count, double* SK_RESTRICT dst4) {
798 for (int n = 0; n < count; ++n) {
799 double sx = src2[0];
800 double sy = src2[1];
801 dst4[0] = mat[0][0] * sx + mat[1][0] * sy + mat[3][0];
802 dst4[1] = mat[0][1] * sx + mat[1][1] * sy + mat[3][1];
803 dst4[2] = mat[0][2] * sx + mat[1][2] * sy + mat[3][2];
804 dst4[3] = 1;
805 src2 += 2;
806 dst4 += 4;
807 }
808}
809
810static void map2_pf(const SkMScalar mat[][4], const float* SK_RESTRICT src2,
811 int count, float* SK_RESTRICT dst4) {
commit-bot@chromium.org658e28b2013-10-29 21:08:51 +0000812 SkMScalar r;
reed@google.com99b5c7f2012-12-05 22:13:59 +0000813 for (int n = 0; n < count; ++n) {
commit-bot@chromium.org658e28b2013-10-29 21:08:51 +0000814 SkMScalar sx = SkFloatToMScalar(src2[0]);
815 SkMScalar sy = SkFloatToMScalar(src2[1]);
reed@google.com99b5c7f2012-12-05 22:13:59 +0000816 for (int i = 0; i < 4; i++) {
commit-bot@chromium.org658e28b2013-10-29 21:08:51 +0000817 r = mat[0][i] * sx + mat[1][i] * sy + mat[3][i];
818 dst4[i] = SkMScalarToFloat(r);
reed@google.com99b5c7f2012-12-05 22:13:59 +0000819 }
820 src2 += 2;
821 dst4 += 4;
822 }
823}
824
825static void map2_pd(const SkMScalar mat[][4], const double* SK_RESTRICT src2,
826 int count, double* SK_RESTRICT dst4) {
827 for (int n = 0; n < count; ++n) {
828 double sx = src2[0];
829 double sy = src2[1];
830 for (int i = 0; i < 4; i++) {
831 dst4[i] = mat[0][i] * sx + mat[1][i] * sy + mat[3][i];
832 }
833 src2 += 2;
834 dst4 += 4;
835 }
836}
837
838void SkMatrix44::map2(const float src2[], int count, float dst4[]) const {
839 static const Map2Procf gProc[] = {
840 map2_if, map2_tf, map2_sf, map2_sf, map2_af, map2_af, map2_af, map2_af
841 };
842
843 TypeMask mask = this->getType();
844 Map2Procf proc = (mask & kPerspective_Mask) ? map2_pf : gProc[mask];
845 proc(fMat, src2, count, dst4);
846}
847
848void SkMatrix44::map2(const double src2[], int count, double dst4[]) const {
849 static const Map2Procd gProc[] = {
850 map2_id, map2_td, map2_sd, map2_sd, map2_ad, map2_ad, map2_ad, map2_ad
851 };
skia.committer@gmail.com0264fb42012-12-06 02:01:25 +0000852
reed@google.com99b5c7f2012-12-05 22:13:59 +0000853 TypeMask mask = this->getType();
854 Map2Procd proc = (mask & kPerspective_Mask) ? map2_pd : gProc[mask];
855 proc(fMat, src2, count, dst4);
856}
857
reed@google.com8260a892011-06-13 14:02:52 +0000858///////////////////////////////////////////////////////////////////////////////
859
860void SkMatrix44::dump() const {
tomhudson@google.com9ac4a892011-06-28 13:53:13 +0000861 static const char* format =
862 "[%g %g %g %g][%g %g %g %g][%g %g %g %g][%g %g %g %g]\n";
reed@google.com8260a892011-06-13 14:02:52 +0000863#if 0
tomhudson@google.com9ac4a892011-06-28 13:53:13 +0000864 SkDebugf(format,
reed@google.com8260a892011-06-13 14:02:52 +0000865 fMat[0][0], fMat[1][0], fMat[2][0], fMat[3][0],
866 fMat[0][1], fMat[1][1], fMat[2][1], fMat[3][1],
867 fMat[0][2], fMat[1][2], fMat[2][2], fMat[3][2],
868 fMat[0][3], fMat[1][3], fMat[2][3], fMat[3][3]);
tomhudson@google.com9ac4a892011-06-28 13:53:13 +0000869#else
870 SkDebugf(format,
871 fMat[0][0], fMat[0][1], fMat[0][2], fMat[0][3],
872 fMat[1][0], fMat[1][1], fMat[1][2], fMat[1][3],
873 fMat[2][0], fMat[2][1], fMat[2][2], fMat[2][3],
874 fMat[3][0], fMat[3][1], fMat[3][2], fMat[3][3]);
reed@google.com8260a892011-06-13 14:02:52 +0000875#endif
876}
877
878///////////////////////////////////////////////////////////////////////////////
879
880static void initFromMatrix(SkMScalar dst[4][4], const SkMatrix& src) {
bsalomon@google.com72e49b82011-10-27 21:47:03 +0000881 dst[0][0] = SkScalarToMScalar(src[SkMatrix::kMScaleX]);
882 dst[1][0] = SkScalarToMScalar(src[SkMatrix::kMSkewX]);
shawnsingh@chromium.org5a6cd352013-08-28 18:55:25 +0000883 dst[2][0] = 0;
bsalomon@google.com72e49b82011-10-27 21:47:03 +0000884 dst[3][0] = SkScalarToMScalar(src[SkMatrix::kMTransX]);
885 dst[0][1] = SkScalarToMScalar(src[SkMatrix::kMSkewY]);
886 dst[1][1] = SkScalarToMScalar(src[SkMatrix::kMScaleY]);
shawnsingh@chromium.org5a6cd352013-08-28 18:55:25 +0000887 dst[2][1] = 0;
bsalomon@google.com72e49b82011-10-27 21:47:03 +0000888 dst[3][1] = SkScalarToMScalar(src[SkMatrix::kMTransY]);
shawnsingh@chromium.org5a6cd352013-08-28 18:55:25 +0000889 dst[0][2] = 0;
890 dst[1][2] = 0;
891 dst[2][2] = 1;
892 dst[3][2] = 0;
commit-bot@chromium.org722555b2013-10-05 01:16:30 +0000893 dst[0][3] = SkScalarToMScalar(src[SkMatrix::kMPersp0]);
894 dst[1][3] = SkScalarToMScalar(src[SkMatrix::kMPersp1]);
shawnsingh@chromium.org5a6cd352013-08-28 18:55:25 +0000895 dst[2][3] = 0;
commit-bot@chromium.org722555b2013-10-05 01:16:30 +0000896 dst[3][3] = SkScalarToMScalar(src[SkMatrix::kMPersp2]);
reed@google.com8260a892011-06-13 14:02:52 +0000897}
898
899SkMatrix44::SkMatrix44(const SkMatrix& src) {
900 initFromMatrix(fMat, src);
901}
902
903SkMatrix44& SkMatrix44::operator=(const SkMatrix& src) {
904 initFromMatrix(fMat, src);
reed@google.com7d683352012-12-03 21:19:52 +0000905
906 if (src.isIdentity()) {
907 this->setTypeMask(kIdentity_Mask);
908 } else {
909 this->dirtyTypeMask();
910 }
reed@google.com8260a892011-06-13 14:02:52 +0000911 return *this;
912}
913
914SkMatrix44::operator SkMatrix() const {
915 SkMatrix dst;
reed@google.com8260a892011-06-13 14:02:52 +0000916
bsalomon@google.com72e49b82011-10-27 21:47:03 +0000917 dst[SkMatrix::kMScaleX] = SkMScalarToScalar(fMat[0][0]);
918 dst[SkMatrix::kMSkewX] = SkMScalarToScalar(fMat[1][0]);
919 dst[SkMatrix::kMTransX] = SkMScalarToScalar(fMat[3][0]);
reed@google.com8260a892011-06-13 14:02:52 +0000920
bsalomon@google.com72e49b82011-10-27 21:47:03 +0000921 dst[SkMatrix::kMSkewY] = SkMScalarToScalar(fMat[0][1]);
922 dst[SkMatrix::kMScaleY] = SkMScalarToScalar(fMat[1][1]);
923 dst[SkMatrix::kMTransY] = SkMScalarToScalar(fMat[3][1]);
reed@google.com8260a892011-06-13 14:02:52 +0000924
commit-bot@chromium.org722555b2013-10-05 01:16:30 +0000925 dst[SkMatrix::kMPersp0] = SkMScalarToScalar(fMat[0][3]);
926 dst[SkMatrix::kMPersp1] = SkMScalarToScalar(fMat[1][3]);
927 dst[SkMatrix::kMPersp2] = SkMScalarToScalar(fMat[3][3]);
928
reed@google.com8260a892011-06-13 14:02:52 +0000929 return dst;
930}