SkMatrix44.cpp revision 631940c8c44e92939fc95d305b87be64eb9b886e
1a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin
2a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin/*
3a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin * Copyright 2011 Google Inc.
4a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin *
5a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin * Use of this source code is governed by a BSD-style license that can be
6a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin * found in the LICENSE file.
7a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin */
8a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin
9a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin
10a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin
11a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin#include "SkMatrix44.h"
12a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin
13a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen LinSkMatrix44::SkMatrix44() {
14a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    this->setIdentity();
15a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin}
16a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin
17a4eae1abb4f2547dfbda84301ee764ce35464881John ReckSkMatrix44::SkMatrix44(const SkMatrix44& src) {
18a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    memcpy(this, &src, sizeof(src));
19a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin}
20a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin
21a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen LinSkMatrix44::SkMatrix44(const SkMatrix44& a, const SkMatrix44& b) {
22a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    this->setConcat(a, b);
23a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin}
24a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin
25a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Linbool SkMatrix44::operator==(const SkMatrix44& other) const {
26a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    const SkMScalar* a = &fMat[0][0];
27d71a718afe02282153d86b78f6a44c4783203d54Owen Lin    const SkMScalar* b = &other.fMat[0][0];
28a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    for (int i = 0; i < 16; ++i) {
29a4eae1abb4f2547dfbda84301ee764ce35464881John Reck        if (a[i] != b[i]) {
30a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin            return false;
31a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        }
32a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    }
33a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    return true;
34a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin}
35a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin
36a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin///////////////////////////////////////////////////////////////////////////////
37a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin
38a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Linvoid SkMatrix44::asColMajorf(float dst[]) const {
39adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin    const SkMScalar* src = &fMat[0][0];
4004d324e313b8ee36ce878f5e8c92949b32de33c0Owen Lin#ifdef SK_MSCALAR_IS_DOUBLE
4104d324e313b8ee36ce878f5e8c92949b32de33c0Owen Lin    for (int i = 0; i < 16; ++i) {
42a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        dst[i] = SkMScalarToFloat(src[i]);
43a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    }
44a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin#elif defined SK_MSCALAR_IS_FLOAT
45d71a718afe02282153d86b78f6a44c4783203d54Owen Lin    memcpy(dst, src, 16 * sizeof(float));
46d71a718afe02282153d86b78f6a44c4783203d54Owen Lin#endif
47d71a718afe02282153d86b78f6a44c4783203d54Owen Lin}
48d71a718afe02282153d86b78f6a44c4783203d54Owen Lin
49a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Linvoid SkMatrix44::asColMajord(double dst[]) const {
50a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    const SkMScalar* src = &fMat[0][0];
51a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin#ifdef SK_MSCALAR_IS_DOUBLE
52a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    memcpy(dst, src, 16 * sizeof(double));
53a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin#elif defined SK_MSCALAR_IS_FLOAT
5404d324e313b8ee36ce878f5e8c92949b32de33c0Owen Lin    for (int i = 0; i < 16; ++i) {
55a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        dst[i] = SkMScalarToDouble(src[i]);
56a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    }
57a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin#endif
58a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin}
5918b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong
6018b388839ed9858a3b35cec9a636e5cde58a528aAngus Kongvoid SkMatrix44::asRowMajorf(float dst[]) const {
61a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    const SkMScalar* src = &fMat[0][0];
62a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    for (int i = 0; i < 4; ++i) {
63a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        dst[0] = SkMScalarToFloat(src[0]);
64a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        dst[4] = SkMScalarToFloat(src[1]);
65a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        dst[8] = SkMScalarToFloat(src[2]);
66a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        dst[12] = SkMScalarToFloat(src[3]);
67a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        src += 4;
68a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        dst += 1;
69a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    }
70a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin}
71a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin
72a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Linvoid SkMatrix44::asRowMajord(double dst[]) const {
73a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    const SkMScalar* src = &fMat[0][0];
74a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    for (int i = 0; i < 4; ++i) {
75a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        dst[0] = SkMScalarToDouble(src[0]);
76a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        dst[4] = SkMScalarToDouble(src[1]);
77a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        dst[8] = SkMScalarToDouble(src[2]);
78a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        dst[12] = SkMScalarToDouble(src[3]);
79a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        src += 4;
80a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        dst += 1;
81a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    }
82a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin}
83a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin
84a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Linvoid SkMatrix44::setColMajorf(const float src[]) {
85a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    SkMScalar* dst = &fMat[0][0];
86a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin#ifdef SK_MSCALAR_IS_DOUBLE
87a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    for (int i = 0; i < 16; ++i) {
88a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        dst[i] = SkMScalarToFloat(src[i]);
89a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    }
90a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin#elif defined SK_MSCALAR_IS_FLOAT
91a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    memcpy(dst, src, 16 * sizeof(float));
92a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin#endif
93a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin}
94d71a718afe02282153d86b78f6a44c4783203d54Owen Lin
95d71a718afe02282153d86b78f6a44c4783203d54Owen Linvoid SkMatrix44::setColMajord(const double src[]) {
9618b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong    SkMScalar* dst = &fMat[0][0];
97a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin#ifdef SK_MSCALAR_IS_DOUBLE
98a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    memcpy(dst, src, 16 * sizeof(double));
99a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin#elif defined SK_MSCALAR_IS_FLOAT
100a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    for (int i = 0; i < 16; ++i) {
101a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        dst[i] = SkMScalarToDouble(src[i]);
102d71a718afe02282153d86b78f6a44c4783203d54Owen Lin    }
103a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin#endif
104a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin}
105a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin
106a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Linvoid SkMatrix44::setRowMajorf(const float src[]) {
107a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    SkMScalar* dst = &fMat[0][0];
108a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    for (int i = 0; i < 4; ++i) {
109a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        dst[0] = SkMScalarToFloat(src[0]);
110a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        dst[4] = SkMScalarToFloat(src[1]);
111a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        dst[8] = SkMScalarToFloat(src[2]);
112a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        dst[12] = SkMScalarToFloat(src[3]);
113a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        src += 4;
114a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        dst += 1;
115a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    }
116a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin}
117a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin
118a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Linvoid SkMatrix44::setRowMajord(const double src[]) {
119a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    SkMScalar* dst = &fMat[0][0];
120a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    for (int i = 0; i < 4; ++i) {
121a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        dst[0] = SkMScalarToDouble(src[0]);
122a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        dst[4] = SkMScalarToDouble(src[1]);
123a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        dst[8] = SkMScalarToDouble(src[2]);
124a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        dst[12] = SkMScalarToDouble(src[3]);
125a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        src += 4;
126a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        dst += 1;
127a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    }
128a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin}
129a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin
130a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin///////////////////////////////////////////////////////////////////////////////
131a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin
132da713ad257719520234fc071c3d11deea8125ed6Mangesh Ghiwarebool SkMatrix44::isIdentity() const {
133da713ad257719520234fc071c3d11deea8125ed6Mangesh Ghiware    static const SkMScalar  sIdentityMat[4][4] = {
134da713ad257719520234fc071c3d11deea8125ed6Mangesh Ghiware        { 1, 0, 0, 0 },
135a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        { 0, 1, 0, 0 },
136a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        { 0, 0, 1, 0 },
137da713ad257719520234fc071c3d11deea8125ed6Mangesh Ghiware        { 0, 0, 0, 1 },
138da713ad257719520234fc071c3d11deea8125ed6Mangesh Ghiware    };
139da713ad257719520234fc071c3d11deea8125ed6Mangesh Ghiware    return !memcmp(fMat, sIdentityMat, sizeof(fMat));
140da713ad257719520234fc071c3d11deea8125ed6Mangesh Ghiware}
141da713ad257719520234fc071c3d11deea8125ed6Mangesh Ghiware
142da713ad257719520234fc071c3d11deea8125ed6Mangesh Ghiware///////////////////////////////////////////////////////////////////////////////
143da713ad257719520234fc071c3d11deea8125ed6Mangesh Ghiware
144da713ad257719520234fc071c3d11deea8125ed6Mangesh Ghiwarevoid SkMatrix44::setIdentity() {
145da713ad257719520234fc071c3d11deea8125ed6Mangesh Ghiware    sk_bzero(fMat, sizeof(fMat));
146da713ad257719520234fc071c3d11deea8125ed6Mangesh Ghiware    fMat[0][0] = fMat[1][1] = fMat[2][2] = fMat[3][3] = 1;
147da713ad257719520234fc071c3d11deea8125ed6Mangesh Ghiware}
148da713ad257719520234fc071c3d11deea8125ed6Mangesh Ghiware
149da713ad257719520234fc071c3d11deea8125ed6Mangesh Ghiwarevoid SkMatrix44::set3x3(SkMScalar m00, SkMScalar m01, SkMScalar m02,
150da713ad257719520234fc071c3d11deea8125ed6Mangesh Ghiware                        SkMScalar m10, SkMScalar m11, SkMScalar m12,
151a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin                        SkMScalar m20, SkMScalar m21, SkMScalar m22) {
152a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    sk_bzero(fMat, sizeof(fMat));
153a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    fMat[0][0] = m00; fMat[0][1] = m01; fMat[0][2] = m02; fMat[0][3] = 0;
154a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    fMat[1][0] = m10; fMat[1][1] = m11; fMat[1][2] = m12; fMat[1][3] = 0;
155a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    fMat[2][0] = m20; fMat[2][1] = m21; fMat[2][2] = m22; fMat[2][3] = 0;
156a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    fMat[3][0] = 0;   fMat[3][1] = 0;   fMat[3][2] = 0;   fMat[3][3] = 1;
157a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin}
158a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin
159a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin///////////////////////////////////////////////////////////////////////////////
160a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin
161a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Linvoid SkMatrix44::setTranslate(SkMScalar tx, SkMScalar ty, SkMScalar tz) {
162a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    this->setIdentity();
163a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    fMat[3][0] = tx;
164a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    fMat[3][1] = ty;
165a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    fMat[3][2] = tz;
166a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    fMat[3][3] = 1;
167a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin}
168a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin
169a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Linvoid SkMatrix44::preTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz) {
170a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    SkMatrix44 mat;
171a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    mat.setTranslate(dx, dy, dz);
172a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    this->preConcat(mat);
173a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin}
174a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin
175a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Linvoid SkMatrix44::postTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz) {
176a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    fMat[3][0] += dx;
177a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    fMat[3][1] += dy;
178a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    fMat[3][2] += dz;
179a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin}
180a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin
181a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin///////////////////////////////////////////////////////////////////////////////
182adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin
18318b388839ed9858a3b35cec9a636e5cde58a528aAngus Kongvoid SkMatrix44::setScale(SkMScalar sx, SkMScalar sy, SkMScalar sz) {
18418b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong    sk_bzero(fMat, sizeof(fMat));
185d54825d1cad2ab586b6d32853acc09dc6df5945fBobby Georgescu    fMat[0][0] = sx;
18618b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong    fMat[1][1] = sy;
18718b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong    fMat[2][2] = sz;
18818b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong    fMat[3][3] = 1;
18918b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong}
19018b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong
191d54825d1cad2ab586b6d32853acc09dc6df5945fBobby Georgescuvoid SkMatrix44::preScale(SkMScalar sx, SkMScalar sy, SkMScalar sz) {
19218b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong    SkMatrix44 tmp;
19318b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong    tmp.setScale(sx, sy, sz);
19418b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong    this->preConcat(tmp);
19518b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong}
19618b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong
19718b388839ed9858a3b35cec9a636e5cde58a528aAngus Kongvoid SkMatrix44::postScale(SkMScalar sx, SkMScalar sy, SkMScalar sz) {
198d54825d1cad2ab586b6d32853acc09dc6df5945fBobby Georgescu    for (int i = 0; i < 4; i++) {
199a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        fMat[i][0] *= sx;
200a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        fMat[i][1] *= sy;
201a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        fMat[i][2] *= sz;
202a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    }
203a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin}
204a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin
205a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin///////////////////////////////////////////////////////////////////////////////
206a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin
207a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Linvoid SkMatrix44::setRotateAbout(SkMScalar x, SkMScalar y, SkMScalar z,
208a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin                                SkMScalar radians) {
209a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    double len2 = x * x + y * y + z * z;
210a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    if (len2 != 1) {
211a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        if (len2 == 0) {
212a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin            this->setIdentity();
213a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin            return;
214a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        }
215a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        double scale = 1 / sqrt(len2);
216a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        x = SkDoubleToMScalar(x * scale);
217a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        y = SkDoubleToMScalar(y * scale);
218a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        z = SkDoubleToMScalar(z * scale);
219a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    }
220a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    this->setRotateAboutUnit(x, y, z, radians);
221a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin}
222a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin
223a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Linvoid SkMatrix44::setRotateAboutUnit(SkMScalar x, SkMScalar y, SkMScalar z,
224a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin                                    SkMScalar radians) {
225a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    double c = cos(radians);
22618b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong    double s = sin(radians);
227a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    double C = 1 - c;
22818b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong    double xs = x * s;
22918b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong    double ys = y * s;
23018b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong    double zs = z * s;
23118b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong    double xC = x * C;
232a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    double yC = y * C;
233a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    double zC = z * C;
234a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    double xyC = x * yC;
235a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    double yzC = y * zC;
236a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    double zxC = z * xC;
237a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin
23804d324e313b8ee36ce878f5e8c92949b32de33c0Owen Lin    // if you're looking at wikipedia, remember that we're column major.
239a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    this->set3x3(SkDoubleToMScalar(x * xC + c),     // scale x
240a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin                 SkDoubleToMScalar(xyC + zs),       // skew x
241a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin                 SkDoubleToMScalar(zxC - ys),       // trans x
242a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin
243a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin                 SkDoubleToMScalar(xyC - zs),       // skew y
244a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin                 SkDoubleToMScalar(y * yC + c),     // scale y
24504d324e313b8ee36ce878f5e8c92949b32de33c0Owen Lin                 SkDoubleToMScalar(yzC + xs),       // trans y
24604d324e313b8ee36ce878f5e8c92949b32de33c0Owen Lin
24704d324e313b8ee36ce878f5e8c92949b32de33c0Owen Lin                 SkDoubleToMScalar(zxC + ys),       // persp x
24804d324e313b8ee36ce878f5e8c92949b32de33c0Owen Lin                 SkDoubleToMScalar(yzC - xs),       // persp y
249a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin                 SkDoubleToMScalar(z * zC + c));    // persp 2
250a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin}
251a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin
252a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin///////////////////////////////////////////////////////////////////////////////
253a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin
254a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Linvoid SkMatrix44::setConcat(const SkMatrix44& a, const SkMatrix44& b) {
255a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    SkMScalar result[4][4];
256a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    for (int i = 0; i < 4; i++) {
257a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        for (int j = 0; j < 4; j++) {
258a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin            double value = 0;
259a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin            for (int k = 0; k < 4; k++) {
260a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin                value += SkMScalarToDouble(a.fMat[k][i]) * b.fMat[j][k];
261a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin            }
262a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin            result[j][i] = SkDoubleToMScalar(value);
263a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        }
264a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    }
265a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    memcpy(fMat, result, sizeof(result));
266a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin}
267a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin
268a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin///////////////////////////////////////////////////////////////////////////////
269a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin
270a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Linstatic inline SkMScalar det2x2(double m00, double m01, double m10, double m11) {
271a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    return SkDoubleToMScalar(m00 * m11 - m10 * m01);
272a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin}
273a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin
274a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Linstatic inline double det3x3(double m00, double m01, double m02,
275a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin                            double m10, double m11, double m12,
276a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin                            double m20, double m21, double m22) {
277a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    return  m00 * det2x2(m11, m12, m21, m22) -
278a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    m10 * det2x2(m01, m02, m21, m22) +
279a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    m20 * det2x2(m01, m02, m11, m12);
28018b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong}
281a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin
28218b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong/** We always perform the calculation in doubles, to avoid prematurely losing
28318b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong    precision along the way. This relies on the compiler automatically
28418b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong    promoting our SkMScalar values to double (if needed).
28518b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong */
28618b388839ed9858a3b35cec9a636e5cde58a528aAngus Kongdouble SkMatrix44::determinant() const {
28718b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong    return  fMat[0][0] * det3x3(fMat[1][1], fMat[1][2], fMat[1][3],
28818b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong                                fMat[2][1], fMat[2][2], fMat[2][3],
28918b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong                                fMat[3][1], fMat[3][2], fMat[3][3]) -
29018b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong    fMat[1][0] * det3x3(fMat[0][1], fMat[0][2], fMat[0][3],
291a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin                        fMat[2][1], fMat[2][2], fMat[2][3],
292a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin                        fMat[3][1], fMat[3][2], fMat[3][3]) +
293a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    fMat[2][0] * det3x3(fMat[0][1], fMat[0][2], fMat[0][3],
294a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin                        fMat[1][1], fMat[1][2], fMat[1][3],
295adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin                        fMat[3][1], fMat[3][2], fMat[3][3]) -
296a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    fMat[3][0] * det3x3(fMat[0][1], fMat[0][2], fMat[0][3],
297a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin                        fMat[1][1], fMat[1][2], fMat[1][3],
298a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin                        fMat[2][1], fMat[2][2], fMat[2][3]);
29918b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong}
300a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin
30118b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong///////////////////////////////////////////////////////////////////////////////
30218b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong
30318b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong// just picked a small value. not sure how to pick the "right" one
30418b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong#define TOO_SMALL_FOR_DETERMINANT   (1.e-8)
30518b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong
30618b388839ed9858a3b35cec9a636e5cde58a528aAngus Kongstatic inline double dabs(double x) {
30718b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong    if (x < 0) {
30818b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong        x = -x;
30918b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong    }
310a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    return x;
311a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin}
312a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin
313a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Linbool SkMatrix44::invert(SkMatrix44* inverse) const {
314a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    double det = this->determinant();
315a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    if (dabs(det) < TOO_SMALL_FOR_DETERMINANT) {
316a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        return false;
317a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    }
318a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    if (NULL == inverse) {
319a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin        return true;
320a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    }
321a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin
322a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    // we explicitly promote to doubles to keep the intermediate values in
323a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    // higher precision (assuming SkMScalar isn't already a double)
32418b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong    double m00 = fMat[0][0];
32518b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong    double m01 = fMat[0][1];
32618b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong    double m02 = fMat[0][2];
32718b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong    double m03 = fMat[0][3];
32818b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong    double m10 = fMat[1][0];
32918b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong    double m11 = fMat[1][1];
33018b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong    double m12 = fMat[1][2];
33118b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong    double m13 = fMat[1][3];
33218b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong    double m20 = fMat[2][0];
33318b388839ed9858a3b35cec9a636e5cde58a528aAngus Kong    double m21 = fMat[2][1];
334a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    double m22 = fMat[2][2];
335a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    double m23 = fMat[2][3];
336adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin    double m30 = fMat[3][0];
337adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin    double m31 = fMat[3][1];
338adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin    double m32 = fMat[3][2];
339adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin    double m33 = fMat[3][3];
340adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin
341adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin    double tmp[4][4];
342adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin
343adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin    tmp[0][0] = m12*m23*m31 - m13*m22*m31 + m13*m21*m32 - m11*m23*m32 - m12*m21*m33 + m11*m22*m33;
344adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin    tmp[0][1] = m03*m22*m31 - m02*m23*m31 - m03*m21*m32 + m01*m23*m32 + m02*m21*m33 - m01*m22*m33;
345adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin    tmp[0][2] = m02*m13*m31 - m03*m12*m31 + m03*m11*m32 - m01*m13*m32 - m02*m11*m33 + m01*m12*m33;
346adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin    tmp[0][3] = m03*m12*m21 - m02*m13*m21 - m03*m11*m22 + m01*m13*m22 + m02*m11*m23 - m01*m12*m23;
347adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin    tmp[1][0] = m13*m22*m30 - m12*m23*m30 - m13*m20*m32 + m10*m23*m32 + m12*m20*m33 - m10*m22*m33;
348adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin    tmp[1][1] = m02*m23*m30 - m03*m22*m30 + m03*m20*m32 - m00*m23*m32 - m02*m20*m33 + m00*m22*m33;
349adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin    tmp[1][2] = m03*m12*m30 - m02*m13*m30 - m03*m10*m32 + m00*m13*m32 + m02*m10*m33 - m00*m12*m33;
350adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin    tmp[1][3] = m02*m13*m20 - m03*m12*m20 + m03*m10*m22 - m00*m13*m22 - m02*m10*m23 + m00*m12*m23;
351adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin    tmp[2][0] = m11*m23*m30 - m13*m21*m30 + m13*m20*m31 - m10*m23*m31 - m11*m20*m33 + m10*m21*m33;
352adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin    tmp[2][1] = m03*m21*m30 - m01*m23*m30 - m03*m20*m31 + m00*m23*m31 + m01*m20*m33 - m00*m21*m33;
353adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin    tmp[2][2] = m01*m13*m30 - m03*m11*m30 + m03*m10*m31 - m00*m13*m31 - m01*m10*m33 + m00*m11*m33;
354adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin    tmp[2][3] = m03*m11*m20 - m01*m13*m20 - m03*m10*m21 + m00*m13*m21 + m01*m10*m23 - m00*m11*m23;
355adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin    tmp[3][0] = m12*m21*m30 - m11*m22*m30 - m12*m20*m31 + m10*m22*m31 + m11*m20*m32 - m10*m21*m32;
356a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin    tmp[3][1] = m01*m22*m30 - m02*m21*m30 + m02*m20*m31 - m00*m22*m31 - m01*m20*m32 + m00*m21*m32;
357    tmp[3][2] = m02*m11*m30 - m01*m12*m30 - m02*m10*m31 + m00*m12*m31 + m01*m10*m32 - m00*m11*m32;
358    tmp[3][3] = m01*m12*m20 - m02*m11*m20 + m02*m10*m21 - m00*m12*m21 - m01*m10*m22 + m00*m11*m22;
359
360    double invDet = 1.0 / det;
361    for (int i = 0; i < 4; i++) {
362        for (int j = 0; j < 4; j++) {
363            inverse->fMat[i][j] = SkDoubleToMScalar(tmp[i][j] * invDet);
364        }
365    }
366    return true;
367}
368
369///////////////////////////////////////////////////////////////////////////////
370
371void SkMatrix44::transpose() {
372    SkTSwap(fMat[0][1], fMat[1][0]);
373    SkTSwap(fMat[0][2], fMat[2][0]);
374    SkTSwap(fMat[0][3], fMat[3][0]);
375    SkTSwap(fMat[1][2], fMat[2][1]);
376    SkTSwap(fMat[1][3], fMat[3][1]);
377    SkTSwap(fMat[2][3], fMat[3][2]);
378}
379
380///////////////////////////////////////////////////////////////////////////////
381
382void SkMatrix44::mapScalars(const SkScalar src[4], SkScalar dst[4]) const {
383    SkScalar result[4];
384    for (int i = 0; i < 4; i++) {
385        SkMScalar value = 0;
386        for (int j = 0; j < 4; j++) {
387            value += fMat[j][i] * src[j];
388        }
389        result[i] = SkMScalarToScalar(value);
390    }
391    memcpy(dst, result, sizeof(result));
392}
393
394#ifdef SK_MSCALAR_IS_DOUBLE
395void SkMatrix44::mapMScalars(const SkMScalar src[4], SkMScalar dst[4]) const {
396    SkMScalar result[4];
397    for (int i = 0; i < 4; i++) {
398        SkMScalar value = 0;
399        for (int j = 0; j < 4; j++) {
400            value += fMat[j][i] * src[j];
401        }
402        result[i] = SkMScalarToScalar(value);
403    }
404    memcpy(dst, result, sizeof(result));
405}
406#endif
407
408///////////////////////////////////////////////////////////////////////////////
409
410void SkMatrix44::dump() const {
411    static const char* format =
412        "[%g %g %g %g][%g %g %g %g][%g %g %g %g][%g %g %g %g]\n";
413#if 0
414    SkDebugf(format,
415             fMat[0][0], fMat[1][0], fMat[2][0], fMat[3][0],
416             fMat[0][1], fMat[1][1], fMat[2][1], fMat[3][1],
417             fMat[0][2], fMat[1][2], fMat[2][2], fMat[3][2],
418             fMat[0][3], fMat[1][3], fMat[2][3], fMat[3][3]);
419#else
420    SkDebugf(format,
421             fMat[0][0], fMat[0][1], fMat[0][2], fMat[0][3],
422             fMat[1][0], fMat[1][1], fMat[1][2], fMat[1][3],
423             fMat[2][0], fMat[2][1], fMat[2][2], fMat[2][3],
424             fMat[3][0], fMat[3][1], fMat[3][2], fMat[3][3]);
425#endif
426}
427
428///////////////////////////////////////////////////////////////////////////////
429
430static void initFromMatrix(SkMScalar dst[4][4], const SkMatrix& src) {
431    sk_bzero(dst, 16 * sizeof(SkMScalar));
432    dst[0][0] = SkScalarToMScalar(src[SkMatrix::kMScaleX]);
433    dst[1][0] = SkScalarToMScalar(src[SkMatrix::kMSkewX]);
434    dst[3][0] = SkScalarToMScalar(src[SkMatrix::kMTransX]);
435    dst[0][1] = SkScalarToMScalar(src[SkMatrix::kMSkewY]);
436    dst[1][1] = SkScalarToMScalar(src[SkMatrix::kMScaleY]);
437    dst[3][1] = SkScalarToMScalar(src[SkMatrix::kMTransY]);
438    dst[2][2] = dst[3][3] = 1;
439}
440
441SkMatrix44::SkMatrix44(const SkMatrix& src) {
442    initFromMatrix(fMat, src);
443}
444
445SkMatrix44& SkMatrix44::operator=(const SkMatrix& src) {
446    initFromMatrix(fMat, src);
447    return *this;
448}
449
450SkMatrix44::operator SkMatrix() const {
451    SkMatrix dst;
452    dst.reset();    // setup our perspective correctly for identity
453
454    dst[SkMatrix::kMScaleX]  = SkMScalarToScalar(fMat[0][0]);
455    dst[SkMatrix::kMSkewX]  = SkMScalarToScalar(fMat[1][0]);
456    dst[SkMatrix::kMTransX] = SkMScalarToScalar(fMat[3][0]);
457
458    dst[SkMatrix::kMSkewY]  = SkMScalarToScalar(fMat[0][1]);
459    dst[SkMatrix::kMScaleY] = SkMScalarToScalar(fMat[1][1]);
460    dst[SkMatrix::kMTransY] = SkMScalarToScalar(fMat[3][1]);
461
462    return dst;
463}
464