180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2011 Google Inc.
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkMatrix44.h"
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerstatic inline bool eq4(const SkMScalar* SK_RESTRICT a,
11363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                      const SkMScalar* SK_RESTRICT b) {
12363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    return (a[0] == b[0]) & (a[1] == b[1]) & (a[2] == b[2]) & (a[3] == b[3]);
13363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
14363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
15363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerbool SkMatrix44::operator==(const SkMatrix44& other) const {
16363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (this == &other) {
17363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        return true;
18363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
19363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
20363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (this->isTriviallyIdentity() && other.isTriviallyIdentity()) {
21363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        return true;
22363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
23363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
24363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    const SkMScalar* SK_RESTRICT a = &fMat[0][0];
25363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    const SkMScalar* SK_RESTRICT b = &other.fMat[0][0];
26363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
27363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#if 0
28363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    for (int i = 0; i < 16; ++i) {
29363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        if (a[i] != b[i]) {
30363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            return false;
31363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
32363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
33363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    return true;
34363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#else
35363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // to reduce branch instructions, we compare 4 at a time.
36363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // see bench/Matrix44Bench.cpp for test.
37363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (!eq4(&a[0], &b[0])) {
38363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        return false;
39363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
40363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (!eq4(&a[4], &b[4])) {
41363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        return false;
42363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
43363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (!eq4(&a[8], &b[8])) {
44363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        return false;
45363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
46363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    return eq4(&a[12], &b[12]);
47363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#endif
4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
50363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger///////////////////////////////////////////////////////////////////////////////
51363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
52363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerint SkMatrix44::computeTypeMask() const {
53363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    unsigned mask = 0;
54363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
55363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (0 != perspX() || 0 != perspY() || 0 != perspZ() || 1 != fMat[3][3]) {
56363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        return kTranslate_Mask | kScale_Mask | kAffine_Mask | kPerspective_Mask;
57363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
58363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
59363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (0 != transX() || 0 != transY() || 0 != transZ()) {
60363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        mask |= kTranslate_Mask;
61363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
62363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
63363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (1 != scaleX() || 1 != scaleY() || 1 != scaleZ()) {
64363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        mask |= kScale_Mask;
65363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
66363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
67363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (0 != fMat[1][0] || 0 != fMat[0][1] || 0 != fMat[0][2] ||
68363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        0 != fMat[2][0] || 0 != fMat[1][2] || 0 != fMat[2][1]) {
69363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            mask |= kAffine_Mask;
70363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
71363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
72363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    return mask;
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix44::asColMajorf(float dst[]) const {
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const SkMScalar* src = &fMat[0][0];
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_MSCALAR_IS_DOUBLE
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (int i = 0; i < 16; ++i) {
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dst[i] = SkMScalarToFloat(src[i]);
8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
83363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#elif defined SK_MSCALAR_IS_FLOAT
8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    memcpy(dst, src, 16 * sizeof(float));
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix44::asColMajord(double dst[]) const {
8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const SkMScalar* src = &fMat[0][0];
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_MSCALAR_IS_DOUBLE
9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    memcpy(dst, src, 16 * sizeof(double));
92363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#elif defined SK_MSCALAR_IS_FLOAT
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (int i = 0; i < 16; ++i) {
9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dst[i] = SkMScalarToDouble(src[i]);
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix44::asRowMajorf(float dst[]) const {
10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const SkMScalar* src = &fMat[0][0];
10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (int i = 0; i < 4; ++i) {
10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dst[0] = SkMScalarToFloat(src[0]);
10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dst[4] = SkMScalarToFloat(src[1]);
10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dst[8] = SkMScalarToFloat(src[2]);
10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dst[12] = SkMScalarToFloat(src[3]);
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        src += 4;
10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dst += 1;
10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix44::asRowMajord(double dst[]) const {
11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const SkMScalar* src = &fMat[0][0];
11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (int i = 0; i < 4; ++i) {
11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dst[0] = SkMScalarToDouble(src[0]);
11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dst[4] = SkMScalarToDouble(src[1]);
11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dst[8] = SkMScalarToDouble(src[2]);
11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dst[12] = SkMScalarToDouble(src[3]);
11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        src += 4;
11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dst += 1;
12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
123363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergervoid SkMatrix44::setColMajorf(const float src[]) {
124363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkMScalar* dst = &fMat[0][0];
125363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#ifdef SK_MSCALAR_IS_DOUBLE
126363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    for (int i = 0; i < 16; ++i) {
127363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst[i] = SkMScalarToFloat(src[i]);
128363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
129363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#elif defined SK_MSCALAR_IS_FLOAT
130363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    memcpy(dst, src, 16 * sizeof(float));
131363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#endif
13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
133363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    this->dirtyTypeMask();
134363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
135363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
136363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergervoid SkMatrix44::setColMajord(const double src[]) {
137363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkMScalar* dst = &fMat[0][0];
138363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#ifdef SK_MSCALAR_IS_DOUBLE
139363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    memcpy(dst, src, 16 * sizeof(double));
140363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#elif defined SK_MSCALAR_IS_FLOAT
141363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    for (int i = 0; i < 16; ++i) {
142363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst[i] = SkDoubleToMScalar(src[i]);
143363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
144363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#endif
145363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
146363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    this->dirtyTypeMask();
147363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
148363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
149363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergervoid SkMatrix44::setRowMajorf(const float src[]) {
150363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkMScalar* dst = &fMat[0][0];
151363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    for (int i = 0; i < 4; ++i) {
152363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst[0] = SkMScalarToFloat(src[0]);
153363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst[4] = SkMScalarToFloat(src[1]);
154363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst[8] = SkMScalarToFloat(src[2]);
155363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst[12] = SkMScalarToFloat(src[3]);
156363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        src += 4;
157363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst += 1;
158363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
159363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    this->dirtyTypeMask();
160363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
161363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
162363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergervoid SkMatrix44::setRowMajord(const double src[]) {
163363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkMScalar* dst = &fMat[0][0];
164363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    for (int i = 0; i < 4; ++i) {
165363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst[0] = SkDoubleToMScalar(src[0]);
166363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst[4] = SkDoubleToMScalar(src[1]);
167363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst[8] = SkDoubleToMScalar(src[2]);
168363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst[12] = SkDoubleToMScalar(src[3]);
169363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        src += 4;
170363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst += 1;
171363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
172363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    this->dirtyTypeMask();
17380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
17480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
17580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
17680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
177363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerconst SkMatrix44& SkMatrix44::I() {
178363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    static const SkMatrix44 gIdentity44(kIdentity_Constructor);
179363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    return gIdentity44;
180363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
181363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
18280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix44::setIdentity() {
1830a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    fMat[0][0] = 1;
1840a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    fMat[0][1] = 0;
1850a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    fMat[0][2] = 0;
1860a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    fMat[0][3] = 0;
1870a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    fMat[1][0] = 0;
1880a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    fMat[1][1] = 1;
1890a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    fMat[1][2] = 0;
1900a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    fMat[1][3] = 0;
1910a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    fMat[2][0] = 0;
1920a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    fMat[2][1] = 0;
1930a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    fMat[2][2] = 1;
1940a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    fMat[2][3] = 0;
1950a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    fMat[3][0] = 0;
1960a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    fMat[3][1] = 0;
1970a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    fMat[3][2] = 0;
1980a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    fMat[3][3] = 1;
199363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    this->setTypeMask(kIdentity_Mask);
20080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
20180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
20280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix44::set3x3(SkMScalar m00, SkMScalar m01, SkMScalar m02,
20380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        SkMScalar m10, SkMScalar m11, SkMScalar m12,
20480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        SkMScalar m20, SkMScalar m21, SkMScalar m22) {
20580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[0][0] = m00; fMat[0][1] = m01; fMat[0][2] = m02; fMat[0][3] = 0;
20680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[1][0] = m10; fMat[1][1] = m11; fMat[1][2] = m12; fMat[1][3] = 0;
20780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[2][0] = m20; fMat[2][1] = m21; fMat[2][2] = m22; fMat[2][3] = 0;
20880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[3][0] = 0;   fMat[3][1] = 0;   fMat[3][2] = 0;   fMat[3][3] = 1;
209363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    this->dirtyTypeMask();
21080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
21180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
21280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
21380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
214363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergervoid SkMatrix44::setTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz) {
21580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->setIdentity();
216363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
217363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (!dx && !dy && !dz) {
218363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        return;
219363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
220363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
221363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    fMat[3][0] = dx;
222363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    fMat[3][1] = dy;
223363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    fMat[3][2] = dz;
224363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    this->setTypeMask(kTranslate_Mask);
22580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
22680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
22780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix44::preTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz) {
228363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (!dx && !dy && !dz) {
229363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        return;
230363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
231363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
232363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    for (int i = 0; i < 4; ++i) {
2330a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        fMat[3][i] = fMat[0][i] * dx + fMat[1][i] * dy + fMat[2][i] * dz + fMat[3][i];
234363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
235363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    this->dirtyTypeMask();
23680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
23780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
23880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix44::postTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz) {
239363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (!dx && !dy && !dz) {
240363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        return;
241363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
242363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
243363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (this->getType() & kPerspective_Mask) {
244363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        for (int i = 0; i < 4; ++i) {
245363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fMat[i][0] += fMat[i][3] * dx;
246363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fMat[i][1] += fMat[i][3] * dy;
247363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fMat[i][2] += fMat[i][3] * dz;
248363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
249363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    } else {
250363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        fMat[3][0] += dx;
251363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        fMat[3][1] += dy;
252363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        fMat[3][2] += dz;
253363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        this->dirtyTypeMask();
254363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
25580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
25680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
25780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
25880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
25980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix44::setScale(SkMScalar sx, SkMScalar sy, SkMScalar sz) {
260363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    this->setIdentity();
261363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
262363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (1 == sx && 1 == sy && 1 == sz) {
263363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        return;
264363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
265363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
26680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[0][0] = sx;
26780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[1][1] = sy;
26880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMat[2][2] = sz;
269363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    this->setTypeMask(kScale_Mask);
27080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
27180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
27280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix44::preScale(SkMScalar sx, SkMScalar sy, SkMScalar sz) {
273363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (1 == sx && 1 == sy && 1 == sz) {
274363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        return;
275363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
276363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
277363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // The implementation matrix * pureScale can be shortcut
278363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // by knowing that pureScale components effectively scale
279363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // the columns of the original matrix.
280363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    for (int i = 0; i < 4; i++) {
281363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        fMat[0][i] *= sx;
282363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        fMat[1][i] *= sy;
283363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        fMat[2][i] *= sz;
284363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
285363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    this->dirtyTypeMask();
28680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
28780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
28880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix44::postScale(SkMScalar sx, SkMScalar sy, SkMScalar sz) {
289363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (1 == sx && 1 == sy && 1 == sz) {
290363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        return;
291363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
292363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
29380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (int i = 0; i < 4; i++) {
29480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMat[i][0] *= sx;
29580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMat[i][1] *= sy;
29680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMat[i][2] *= sz;
29780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
298363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    this->dirtyTypeMask();
29980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
30080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
30180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
30280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
30380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix44::setRotateAbout(SkMScalar x, SkMScalar y, SkMScalar z,
30480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                SkMScalar radians) {
305363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double len2 = (double)x * x + (double)y * y + (double)z * z;
306363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (1 != len2) {
307363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        if (0 == len2) {
30880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            this->setIdentity();
30980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return;
31080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
31180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        double scale = 1 / sqrt(len2);
31280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        x = SkDoubleToMScalar(x * scale);
31380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        y = SkDoubleToMScalar(y * scale);
31480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        z = SkDoubleToMScalar(z * scale);
31580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
31680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->setRotateAboutUnit(x, y, z, radians);
31780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
31880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
31980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix44::setRotateAboutUnit(SkMScalar x, SkMScalar y, SkMScalar z,
32080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                    SkMScalar radians) {
32180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    double c = cos(radians);
32280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    double s = sin(radians);
32380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    double C = 1 - c;
32480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    double xs = x * s;
32580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    double ys = y * s;
32680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    double zs = z * s;
32780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    double xC = x * C;
32880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    double yC = y * C;
32980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    double zC = z * C;
33080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    double xyC = x * yC;
33180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    double yzC = y * zC;
33280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    double zxC = z * xC;
33380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
33480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // if you're looking at wikipedia, remember that we're column major.
33580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->set3x3(SkDoubleToMScalar(x * xC + c),     // scale x
33680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                 SkDoubleToMScalar(xyC + zs),       // skew x
33780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                 SkDoubleToMScalar(zxC - ys),       // trans x
33880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
33980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                 SkDoubleToMScalar(xyC - zs),       // skew y
34080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                 SkDoubleToMScalar(y * yC + c),     // scale y
34180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                 SkDoubleToMScalar(yzC + xs),       // trans y
34280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
34380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                 SkDoubleToMScalar(zxC + ys),       // persp x
34480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                 SkDoubleToMScalar(yzC - xs),       // persp y
34580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                 SkDoubleToMScalar(z * zC + c));    // persp 2
34680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
34780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
34880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
34980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
350363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerstatic bool bits_isonly(int value, int mask) {
351363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    return 0 == (value & ~mask);
352363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
353363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
35480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix44::setConcat(const SkMatrix44& a, const SkMatrix44& b) {
355363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    const SkMatrix44::TypeMask a_mask = a.getType();
356363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    const SkMatrix44::TypeMask b_mask = b.getType();
357363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
358363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (kIdentity_Mask == a_mask) {
359363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        *this = b;
360363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        return;
361363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
362363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (kIdentity_Mask == b_mask) {
363363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        *this = a;
364363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        return;
365363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
366363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
367363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    bool useStorage = (this == &a || this == &b);
368363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkMScalar storage[16];
369363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkMScalar* result = useStorage ? storage : &fMat[0][0];
370363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
371d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    // Both matrices are at most scale+translate
372363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (bits_isonly(a_mask | b_mask, kScale_Mask | kTranslate_Mask)) {
373363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        result[0] = a.fMat[0][0] * b.fMat[0][0];
374d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        result[1] = result[2] = result[3] = result[4] = 0;
375363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        result[5] = a.fMat[1][1] * b.fMat[1][1];
376d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        result[6] = result[7] = result[8] = result[9] = 0;
377363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        result[10] = a.fMat[2][2] * b.fMat[2][2];
378d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        result[11] = 0;
379363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        result[12] = a.fMat[0][0] * b.fMat[3][0] + a.fMat[3][0];
380363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        result[13] = a.fMat[1][1] * b.fMat[3][1] + a.fMat[3][1];
381363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        result[14] = a.fMat[2][2] * b.fMat[3][2] + a.fMat[3][2];
382363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        result[15] = 1;
383363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    } else {
38480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for (int j = 0; j < 4; j++) {
385363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            for (int i = 0; i < 4; i++) {
386363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                double value = 0;
387363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                for (int k = 0; k < 4; k++) {
388363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    value += SkMScalarToDouble(a.fMat[k][i]) * b.fMat[j][k];
389363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                }
390363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                *result++ = SkDoubleToMScalar(value);
39180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
39280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
39380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
394363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
395363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (useStorage) {
396363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        memcpy(fMat, storage, sizeof(storage));
397363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
398363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    this->dirtyTypeMask();
39980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
40080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
40180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
40280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
40380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/** We always perform the calculation in doubles, to avoid prematurely losing
40480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    precision along the way. This relies on the compiler automatically
40580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    promoting our SkMScalar values to double (if needed).
40680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
40780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querudouble SkMatrix44::determinant() const {
408363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (this->isIdentity()) {
409363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        return 1;
410363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
411363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (this->isScaleTranslate()) {
412363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        return fMat[0][0] * fMat[1][1] * fMat[2][2] * fMat[3][3];
413363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
414363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
415363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double a00 = fMat[0][0];
416363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double a01 = fMat[0][1];
417363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double a02 = fMat[0][2];
418363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double a03 = fMat[0][3];
419363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double a10 = fMat[1][0];
420363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double a11 = fMat[1][1];
421363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double a12 = fMat[1][2];
422363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double a13 = fMat[1][3];
423363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double a20 = fMat[2][0];
424363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double a21 = fMat[2][1];
425363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double a22 = fMat[2][2];
426363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double a23 = fMat[2][3];
427363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double a30 = fMat[3][0];
428363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double a31 = fMat[3][1];
429363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double a32 = fMat[3][2];
430363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double a33 = fMat[3][3];
431363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
432363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double b00 = a00 * a11 - a01 * a10;
433363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double b01 = a00 * a12 - a02 * a10;
434363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double b02 = a00 * a13 - a03 * a10;
435363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double b03 = a01 * a12 - a02 * a11;
436363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double b04 = a01 * a13 - a03 * a11;
437363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double b05 = a02 * a13 - a03 * a12;
438363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double b06 = a20 * a31 - a21 * a30;
439363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double b07 = a20 * a32 - a22 * a30;
440363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double b08 = a20 * a33 - a23 * a30;
441363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double b09 = a21 * a32 - a22 * a31;
442363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double b10 = a21 * a33 - a23 * a31;
443363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double b11 = a22 * a33 - a23 * a32;
444363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
445363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // Calculate the determinant
446363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
44780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
44880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
44980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
45080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
45180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkMatrix44::invert(SkMatrix44* inverse) const {
452363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (this->isIdentity()) {
453363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        if (inverse) {
4540a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger            inverse->setIdentity();
455363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
456910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        return true;
457363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
458910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger
459363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (this->isTranslate()) {
460363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        if (inverse) {
461363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            inverse->setTranslate(-fMat[3][0], -fMat[3][1], -fMat[3][2]);
462363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
463363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        return true;
464363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
465910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger
466363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (this->isScaleTranslate()) {
467363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        if (0 == fMat[0][0] * fMat[1][1] * fMat[2][2]) {
468363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            return false;
469363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
470363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
471910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        if (inverse) {
472910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            double invXScale = 1 / fMat[0][0];
473910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            double invYScale = 1 / fMat[1][1];
474910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            double invZScale = 1 / fMat[2][2];
4750a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
4760a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger            inverse->fMat[0][0] = invXScale;
477910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            inverse->fMat[0][1] = 0;
478910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            inverse->fMat[0][2] = 0;
479910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            inverse->fMat[0][3] = 0;
4800a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
481910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            inverse->fMat[1][0] = 0;
482910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            inverse->fMat[1][1] = invYScale;
483910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            inverse->fMat[1][2] = 0;
484910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            inverse->fMat[1][3] = 0;
4850a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
486910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            inverse->fMat[2][0] = 0;
4870a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger            inverse->fMat[2][1] = 0;
488910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            inverse->fMat[2][2] = invZScale;
489910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            inverse->fMat[2][3] = 0;
4900a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
4910a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger            inverse->fMat[3][0] = -fMat[3][0] * invXScale;
4920a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger            inverse->fMat[3][1] = -fMat[3][1] * invYScale;
4930a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger            inverse->fMat[3][2] = -fMat[3][2] * invZScale;
494363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            inverse->fMat[3][3] = 1;
495363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
496363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            inverse->setTypeMask(this->getType());
497363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
4980a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
499363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        return true;
500363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
501363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
502363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double a00 = fMat[0][0];
503363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double a01 = fMat[0][1];
504363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double a02 = fMat[0][2];
505363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double a03 = fMat[0][3];
506363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double a10 = fMat[1][0];
507363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double a11 = fMat[1][1];
508363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double a12 = fMat[1][2];
509363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double a13 = fMat[1][3];
510363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double a20 = fMat[2][0];
511363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double a21 = fMat[2][1];
512363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double a22 = fMat[2][2];
513363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double a23 = fMat[2][3];
514363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double a30 = fMat[3][0];
515363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double a31 = fMat[3][1];
516363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double a32 = fMat[3][2];
517363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double a33 = fMat[3][3];
518363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
5190a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    if (!(this->getType() & kPerspective_Mask)) {
5200a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        // If we know the matrix has no perspective, then the perspective
5210a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        // component is (0, 0, 0, 1). We can use this information to save a lot
5220a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        // of arithmetic that would otherwise be spent to compute the inverse
5230a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        // of a general matrix.
5240a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
5250a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        SkASSERT(a03 == 0);
5260a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        SkASSERT(a13 == 0);
5270a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        SkASSERT(a23 == 0);
5280a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        SkASSERT(a33 == 1);
5290a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
5300a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        double b00 = a00 * a11 - a01 * a10;
5310a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        double b01 = a00 * a12 - a02 * a10;
5320a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        double b03 = a01 * a12 - a02 * a11;
5330a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        double b06 = a20 * a31 - a21 * a30;
5340a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        double b07 = a20 * a32 - a22 * a30;
5350a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        double b08 = a20;
5360a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        double b09 = a21 * a32 - a22 * a31;
5370a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        double b10 = a21;
5380a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        double b11 = a22;
5390a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
5400a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        // Calculate the determinant
5410a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        double det = b00 * b11 - b01 * b10 + b03 * b08;
5420a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
5430a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        double invdet = 1.0 / det;
5440a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        // If det is zero, we want to return false. However, we also want to return false
5450a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        // if 1/det overflows to infinity (i.e. det is denormalized). Both of these are
5460a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        // handled by checking that 1/det is finite.
5470a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        if (!sk_float_isfinite(invdet)) {
5480a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger            return false;
5490a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        }
5500a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        if (NULL == inverse) {
5510a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger            return true;
5520a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        }
5530a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
5540a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        b00 *= invdet;
5550a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        b01 *= invdet;
5560a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        b03 *= invdet;
5570a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        b06 *= invdet;
5580a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        b07 *= invdet;
5590a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        b08 *= invdet;
5600a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        b09 *= invdet;
5610a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        b10 *= invdet;
5620a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        b11 *= invdet;
5630a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
5640a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        inverse->fMat[0][0] = SkDoubleToMScalar(a11 * b11 - a12 * b10);
5650a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        inverse->fMat[0][1] = SkDoubleToMScalar(a02 * b10 - a01 * b11);
5660a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        inverse->fMat[0][2] = SkDoubleToMScalar(b03);
5670a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        inverse->fMat[0][3] = 0;
5680a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        inverse->fMat[1][0] = SkDoubleToMScalar(a12 * b08 - a10 * b11);
5690a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        inverse->fMat[1][1] = SkDoubleToMScalar(a00 * b11 - a02 * b08);
5700a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        inverse->fMat[1][2] = SkDoubleToMScalar(-b01);
5710a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        inverse->fMat[1][3] = 0;
5720a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        inverse->fMat[2][0] = SkDoubleToMScalar(a10 * b10 - a11 * b08);
5730a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        inverse->fMat[2][1] = SkDoubleToMScalar(a01 * b08 - a00 * b10);
5740a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        inverse->fMat[2][2] = SkDoubleToMScalar(b00);
5750a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        inverse->fMat[2][3] = 0;
5760a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        inverse->fMat[3][0] = SkDoubleToMScalar(a11 * b07 - a10 * b09 - a12 * b06);
5770a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        inverse->fMat[3][1] = SkDoubleToMScalar(a00 * b09 - a01 * b07 + a02 * b06);
5780a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        inverse->fMat[3][2] = SkDoubleToMScalar(a31 * b01 - a30 * b03 - a32 * b00);
5790a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        inverse->fMat[3][3] = 1;
5800a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
5810a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        inverse->setTypeMask(this->getType());
5820a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        return true;
5830a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    }
5840a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
585363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double b00 = a00 * a11 - a01 * a10;
586363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double b01 = a00 * a12 - a02 * a10;
587363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double b02 = a00 * a13 - a03 * a10;
588363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double b03 = a01 * a12 - a02 * a11;
589363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double b04 = a01 * a13 - a03 * a11;
590363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double b05 = a02 * a13 - a03 * a12;
591363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double b06 = a20 * a31 - a21 * a30;
592363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double b07 = a20 * a32 - a22 * a30;
593363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double b08 = a20 * a33 - a23 * a30;
594363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double b09 = a21 * a32 - a22 * a31;
595363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double b10 = a21 * a33 - a23 * a31;
596363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double b11 = a22 * a33 - a23 * a32;
597363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
598363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // Calculate the determinant
599363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    double det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
600363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
6010a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    double invdet = 1.0 / det;
6020a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    // If det is zero, we want to return false. However, we also want to return false
6030a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    // if 1/det overflows to infinity (i.e. det is denormalized). Both of these are
6040a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    // handled by checking that 1/det is finite.
6050a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    if (!sk_float_isfinite(invdet)) {
60680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
60780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
60880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == inverse) {
60980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
61080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
611363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
612363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    b00 *= invdet;
613363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    b01 *= invdet;
614363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    b02 *= invdet;
615363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    b03 *= invdet;
616363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    b04 *= invdet;
617363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    b05 *= invdet;
618363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    b06 *= invdet;
619363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    b07 *= invdet;
620363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    b08 *= invdet;
621363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    b09 *= invdet;
622363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    b10 *= invdet;
623363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    b11 *= invdet;
624363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
625363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    inverse->fMat[0][0] = SkDoubleToMScalar(a11 * b11 - a12 * b10 + a13 * b09);
626363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    inverse->fMat[0][1] = SkDoubleToMScalar(a02 * b10 - a01 * b11 - a03 * b09);
627363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    inverse->fMat[0][2] = SkDoubleToMScalar(a31 * b05 - a32 * b04 + a33 * b03);
628363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    inverse->fMat[0][3] = SkDoubleToMScalar(a22 * b04 - a21 * b05 - a23 * b03);
629363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    inverse->fMat[1][0] = SkDoubleToMScalar(a12 * b08 - a10 * b11 - a13 * b07);
630363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    inverse->fMat[1][1] = SkDoubleToMScalar(a00 * b11 - a02 * b08 + a03 * b07);
631363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    inverse->fMat[1][2] = SkDoubleToMScalar(a32 * b02 - a30 * b05 - a33 * b01);
632363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    inverse->fMat[1][3] = SkDoubleToMScalar(a20 * b05 - a22 * b02 + a23 * b01);
633363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    inverse->fMat[2][0] = SkDoubleToMScalar(a10 * b10 - a11 * b08 + a13 * b06);
634363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    inverse->fMat[2][1] = SkDoubleToMScalar(a01 * b08 - a00 * b10 - a03 * b06);
635363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    inverse->fMat[2][2] = SkDoubleToMScalar(a30 * b04 - a31 * b02 + a33 * b00);
636363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    inverse->fMat[2][3] = SkDoubleToMScalar(a21 * b02 - a20 * b04 - a23 * b00);
637363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    inverse->fMat[3][0] = SkDoubleToMScalar(a11 * b07 - a10 * b09 - a12 * b06);
638363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    inverse->fMat[3][1] = SkDoubleToMScalar(a00 * b09 - a01 * b07 + a02 * b06);
639363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    inverse->fMat[3][2] = SkDoubleToMScalar(a31 * b01 - a30 * b03 - a32 * b00);
640363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    inverse->fMat[3][3] = SkDoubleToMScalar(a20 * b03 - a21 * b01 + a22 * b00);
641363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    inverse->dirtyTypeMask();
642363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
643363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    return true;
644363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
645363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
646363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger///////////////////////////////////////////////////////////////////////////////
647363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
648363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergervoid SkMatrix44::transpose() {
649363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkTSwap(fMat[0][1], fMat[1][0]);
650363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkTSwap(fMat[0][2], fMat[2][0]);
651363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkTSwap(fMat[0][3], fMat[3][0]);
652363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkTSwap(fMat[1][2], fMat[2][1]);
653363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkTSwap(fMat[1][3], fMat[3][1]);
654363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkTSwap(fMat[2][3], fMat[3][2]);
655363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
656363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (!this->isTriviallyIdentity()) {
657363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        this->dirtyTypeMask();
658363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
659363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
660363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
661363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger///////////////////////////////////////////////////////////////////////////////
662363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
663363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergervoid SkMatrix44::mapScalars(const SkScalar src[4], SkScalar dst[4]) const {
664363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkScalar storage[4];
665363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkScalar* result = (src == dst) ? storage : dst;
66680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
66780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (int i = 0; i < 4; i++) {
668363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        SkMScalar value = 0;
66980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for (int j = 0; j < 4; j++) {
670363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            value += fMat[j][i] * src[j];
67180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
672363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        result[i] = SkMScalarToScalar(value);
673363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
674363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
675363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (storage == result) {
676363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        memcpy(dst, storage, sizeof(storage));
67780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
67880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
67980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
680363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#ifdef SK_MSCALAR_IS_DOUBLE
681363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
682363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergervoid SkMatrix44::mapMScalars(const SkMScalar src[4], SkMScalar dst[4]) const {
683363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkMScalar storage[4];
684363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkMScalar* result = (src == dst) ? storage : dst;
68580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
68680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (int i = 0; i < 4; i++) {
68780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkMScalar value = 0;
68880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for (int j = 0; j < 4; j++) {
68980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            value += fMat[j][i] * src[j];
69080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
691363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        result[i] = value;
692363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
693363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
694363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (storage == result) {
695363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        memcpy(dst, storage, sizeof(storage));
696363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
697363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
698363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
699363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#endif
700363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
701363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergertypedef void (*Map2Procf)(const SkMScalar mat[][4], const float src2[], int count, float dst4[]);
702363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergertypedef void (*Map2Procd)(const SkMScalar mat[][4], const double src2[], int count, double dst4[]);
703363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
704363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerstatic void map2_if(const SkMScalar mat[][4], const float* SK_RESTRICT src2,
705363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    int count, float* SK_RESTRICT dst4) {
706363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    for (int i = 0; i < count; ++i) {
707363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4[0] = src2[0];
708363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4[1] = src2[1];
709363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4[2] = 0;
710363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4[3] = 1;
711363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        src2 += 2;
712363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4 += 4;
713363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
714363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
715363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
716363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerstatic void map2_id(const SkMScalar mat[][4], const double* SK_RESTRICT src2,
717363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    int count, double* SK_RESTRICT dst4) {
718363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    for (int i = 0; i < count; ++i) {
719363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4[0] = src2[0];
720363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4[1] = src2[1];
721363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4[2] = 0;
722363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4[3] = 1;
723363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        src2 += 2;
724363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4 += 4;
725363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
726363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
727363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
728363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerstatic void map2_tf(const SkMScalar mat[][4], const float* SK_RESTRICT src2,
729363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    int count, float* SK_RESTRICT dst4) {
730363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    const float mat30 = SkMScalarToFloat(mat[3][0]);
731363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    const float mat31 = SkMScalarToFloat(mat[3][1]);
732363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    const float mat32 = SkMScalarToFloat(mat[3][2]);
733363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    for (int n = 0; n < count; ++n) {
734363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4[0] = src2[0] + mat30;
735363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4[1] = src2[1] + mat31;
736363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4[2] = mat32;
737363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4[3] = 1;
738363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        src2 += 2;
739363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4 += 4;
740363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
741363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
742363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
743363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerstatic void map2_td(const SkMScalar mat[][4], const double* SK_RESTRICT src2,
744363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    int count, double* SK_RESTRICT dst4) {
745363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    for (int n = 0; n < count; ++n) {
746363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4[0] = src2[0] + mat[3][0];
747363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4[1] = src2[1] + mat[3][1];
748363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4[2] = mat[3][2];
749363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4[3] = 1;
750363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        src2 += 2;
751363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4 += 4;
752363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
753363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
754363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
755363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerstatic void map2_sf(const SkMScalar mat[][4], const float* SK_RESTRICT src2,
756363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    int count, float* SK_RESTRICT dst4) {
757363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    const float mat32 = SkMScalarToFloat(mat[3][2]);
758363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    for (int n = 0; n < count; ++n) {
759363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4[0] = SkMScalarToFloat(mat[0][0] * src2[0] + mat[3][0]);
760363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4[1] = SkMScalarToFloat(mat[1][1] * src2[1] + mat[3][1]);
761363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4[2] = mat32;
762363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4[3] = 1;
763363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        src2 += 2;
764363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4 += 4;
765363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
766363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
767363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
768363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerstatic void map2_sd(const SkMScalar mat[][4], const double* SK_RESTRICT src2,
769363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    int count, double* SK_RESTRICT dst4) {
770363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    for (int n = 0; n < count; ++n) {
771363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4[0] = mat[0][0] * src2[0] + mat[3][0];
772363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4[1] = mat[1][1] * src2[1] + mat[3][1];
773363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4[2] = mat[3][2];
774363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4[3] = 1;
775363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        src2 += 2;
776363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4 += 4;
77780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
778363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
779363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
780363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerstatic void map2_af(const SkMScalar mat[][4], const float* SK_RESTRICT src2,
781363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    int count, float* SK_RESTRICT dst4) {
7820a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    SkMScalar r;
783363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    for (int n = 0; n < count; ++n) {
7840a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        SkMScalar sx = SkFloatToMScalar(src2[0]);
7850a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        SkMScalar sy = SkFloatToMScalar(src2[1]);
786363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        r = mat[0][0] * sx + mat[1][0] * sy + mat[3][0];
787363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4[0] = SkMScalarToFloat(r);
788363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        r = mat[0][1] * sx + mat[1][1] * sy + mat[3][1];
789363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4[1] = SkMScalarToFloat(r);
790363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        r = mat[0][2] * sx + mat[1][2] * sy + mat[3][2];
791363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4[2] = SkMScalarToFloat(r);
792363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4[3] = 1;
793363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        src2 += 2;
794363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4 += 4;
795363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
796363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
797363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
798363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerstatic void map2_ad(const SkMScalar mat[][4], const double* SK_RESTRICT src2,
799363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    int count, double* SK_RESTRICT dst4) {
800363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    for (int n = 0; n < count; ++n) {
801363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        double sx = src2[0];
802363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        double sy = src2[1];
803363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4[0] = mat[0][0] * sx + mat[1][0] * sy + mat[3][0];
804363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4[1] = mat[0][1] * sx + mat[1][1] * sy + mat[3][1];
805363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4[2] = mat[0][2] * sx + mat[1][2] * sy + mat[3][2];
806363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4[3] = 1;
807363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        src2 += 2;
808363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4 += 4;
809363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
810363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
811363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
812363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerstatic void map2_pf(const SkMScalar mat[][4], const float* SK_RESTRICT src2,
813363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    int count, float* SK_RESTRICT dst4) {
8140a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    SkMScalar r;
815363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    for (int n = 0; n < count; ++n) {
8160a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        SkMScalar sx = SkFloatToMScalar(src2[0]);
8170a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        SkMScalar sy = SkFloatToMScalar(src2[1]);
818363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        for (int i = 0; i < 4; i++) {
819363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            r = mat[0][i] * sx + mat[1][i] * sy + mat[3][i];
820363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            dst4[i] = SkMScalarToFloat(r);
821363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
822363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        src2 += 2;
823363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4 += 4;
824363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
825363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
826363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
827363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerstatic void map2_pd(const SkMScalar mat[][4], const double* SK_RESTRICT src2,
828363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    int count, double* SK_RESTRICT dst4) {
829363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    for (int n = 0; n < count; ++n) {
830363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        double sx = src2[0];
831363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        double sy = src2[1];
832363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        for (int i = 0; i < 4; i++) {
833363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            dst4[i] = mat[0][i] * sx + mat[1][i] * sy + mat[3][i];
834363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
835363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        src2 += 2;
836363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        dst4 += 4;
837363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
838363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
839363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
840363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergervoid SkMatrix44::map2(const float src2[], int count, float dst4[]) const {
841363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    static const Map2Procf gProc[] = {
842363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        map2_if, map2_tf, map2_sf, map2_sf, map2_af, map2_af, map2_af, map2_af
843363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    };
844363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
845363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    TypeMask mask = this->getType();
846363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    Map2Procf proc = (mask & kPerspective_Mask) ? map2_pf : gProc[mask];
847363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    proc(fMat, src2, count, dst4);
848363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
849363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
850363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergervoid SkMatrix44::map2(const double src2[], int count, double dst4[]) const {
851363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    static const Map2Procd gProc[] = {
852363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        map2_id, map2_td, map2_sd, map2_sd, map2_ad, map2_ad, map2_ad, map2_ad
853363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    };
854363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
855363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    TypeMask mask = this->getType();
856363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    Map2Procd proc = (mask & kPerspective_Mask) ? map2_pd : gProc[mask];
857363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    proc(fMat, src2, count, dst4);
85880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
85980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
86080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
86180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
86280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMatrix44::dump() const {
86380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static const char* format =
86480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        "[%g %g %g %g][%g %g %g %g][%g %g %g %g][%g %g %g %g]\n";
86580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if 0
86680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDebugf(format,
86780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru             fMat[0][0], fMat[1][0], fMat[2][0], fMat[3][0],
86880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru             fMat[0][1], fMat[1][1], fMat[2][1], fMat[3][1],
86980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru             fMat[0][2], fMat[1][2], fMat[2][2], fMat[3][2],
87080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru             fMat[0][3], fMat[1][3], fMat[2][3], fMat[3][3]);
87180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
87280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDebugf(format,
87380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru             fMat[0][0], fMat[0][1], fMat[0][2], fMat[0][3],
87480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru             fMat[1][0], fMat[1][1], fMat[1][2], fMat[1][3],
87580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru             fMat[2][0], fMat[2][1], fMat[2][2], fMat[2][3],
87680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru             fMat[3][0], fMat[3][1], fMat[3][2], fMat[3][3]);
87780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
87880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
87980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
88080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
88180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
88280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void initFromMatrix(SkMScalar dst[4][4], const SkMatrix& src) {
88380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst[0][0] = SkScalarToMScalar(src[SkMatrix::kMScaleX]);
88480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst[1][0] = SkScalarToMScalar(src[SkMatrix::kMSkewX]);
8850a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    dst[2][0] = 0;
88680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst[3][0] = SkScalarToMScalar(src[SkMatrix::kMTransX]);
88780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst[0][1] = SkScalarToMScalar(src[SkMatrix::kMSkewY]);
88880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst[1][1] = SkScalarToMScalar(src[SkMatrix::kMScaleY]);
8890a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    dst[2][1] = 0;
89080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst[3][1] = SkScalarToMScalar(src[SkMatrix::kMTransY]);
8910a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    dst[0][2] = 0;
8920a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    dst[1][2] = 0;
8930a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    dst[2][2] = 1;
8940a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    dst[3][2] = 0;
8950a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    dst[0][3] = SkScalarToMScalar(src[SkMatrix::kMPersp0]);
8960a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    dst[1][3] = SkScalarToMScalar(src[SkMatrix::kMPersp1]);
8970a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    dst[2][3] = 0;
8980a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    dst[3][3] = SkScalarToMScalar(src[SkMatrix::kMPersp2]);
89980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
90080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
90180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkMatrix44::SkMatrix44(const SkMatrix& src) {
90280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    initFromMatrix(fMat, src);
90380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
90480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
90580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkMatrix44& SkMatrix44::operator=(const SkMatrix& src) {
90680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    initFromMatrix(fMat, src);
907363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
908363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (src.isIdentity()) {
909363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        this->setTypeMask(kIdentity_Mask);
910363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    } else {
911363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        this->dirtyTypeMask();
912363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
91380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return *this;
91480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
91580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
91680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkMatrix44::operator SkMatrix() const {
91780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkMatrix dst;
91880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
91980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst[SkMatrix::kMScaleX]  = SkMScalarToScalar(fMat[0][0]);
92080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst[SkMatrix::kMSkewX]  = SkMScalarToScalar(fMat[1][0]);
92180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst[SkMatrix::kMTransX] = SkMScalarToScalar(fMat[3][0]);
92280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
92380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst[SkMatrix::kMSkewY]  = SkMScalarToScalar(fMat[0][1]);
92480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst[SkMatrix::kMScaleY] = SkMScalarToScalar(fMat[1][1]);
92580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst[SkMatrix::kMTransY] = SkMScalarToScalar(fMat[3][1]);
92680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9270a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    dst[SkMatrix::kMPersp0] = SkMScalarToScalar(fMat[0][3]);
9280a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    dst[SkMatrix::kMPersp1] = SkMScalarToScalar(fMat[1][3]);
9290a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    dst[SkMatrix::kMPersp2] = SkMScalarToScalar(fMat[3][3]);
9300a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
93180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return dst;
93280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
933