11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
21cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/*
31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2011 Google Inc.
41cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger *
51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file.
71cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */
81cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
91cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "SkMatrix44.h"
121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
131cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerSkMatrix44::SkMatrix44() {
141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    this->setIdentity();
151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
171cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerSkMatrix44::SkMatrix44(const SkMatrix44& src) {
181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    memcpy(this, &src, sizeof(src));
191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
211cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerSkMatrix44::SkMatrix44(const SkMatrix44& a, const SkMatrix44& b) {
221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    this->setConcat(a, b);
231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
251cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerSkMScalar SkMatrix44::get(int row, int col) const {
261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkASSERT(row <= 3 && row >= 0);
271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkASSERT(col <= 3 && col >= 0);
281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return fMat[col][row];
291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkMatrix44::set(int row, int col, const SkMScalar& value) {
321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkASSERT(row <= 3 && row >= 0);
331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkASSERT(col <= 3 && col >= 0);
341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    fMat[col][row] = value;
351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger///////////////////////////////////////////////////////////////////////////////
381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkMatrix44::asColMajorf(float dst[]) const {
401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const SkMScalar* src = &fMat[0][0];
411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_MSCALAR_IS_DOUBLE
421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    for (int i = 0; i < 16; ++i) {
431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        dst[i] = SkMScalarToFloat(src[i]);
441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#else
461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    memcpy(dst, src, 16 * sizeof(float));
471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkMatrix44::asColMajord(double dst[]) const {
511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const SkMScalar* src = &fMat[0][0];
521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_MSCALAR_IS_DOUBLE
531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    memcpy(dst, src, 16 * sizeof(double));
541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#else
551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    for (int i = 0; i < 16; ++i) {
561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        dst[i] = SkMScalarToDouble(src[i]);
571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkMatrix44::asRowMajorf(float dst[]) const {
621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const SkMScalar* src = &fMat[0][0];
631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    for (int i = 0; i < 4; ++i) {
641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        dst[0] = SkMScalarToFloat(src[0]);
651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        dst[4] = SkMScalarToFloat(src[1]);
661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        dst[8] = SkMScalarToFloat(src[2]);
671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        dst[12] = SkMScalarToFloat(src[3]);
681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        src += 4;
691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        dst += 1;
701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkMatrix44::asRowMajord(double dst[]) const {
741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const SkMScalar* src = &fMat[0][0];
751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    for (int i = 0; i < 4; ++i) {
761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        dst[0] = SkMScalarToDouble(src[0]);
771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        dst[4] = SkMScalarToDouble(src[1]);
781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        dst[8] = SkMScalarToDouble(src[2]);
791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        dst[12] = SkMScalarToDouble(src[3]);
801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        src += 4;
811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        dst += 1;
821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger///////////////////////////////////////////////////////////////////////////////
861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerbool SkMatrix44::isIdentity() const {
881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    static const SkMScalar  sIdentityMat[4][4] = {
891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        { 1, 0, 0, 0 },
901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        { 0, 1, 0, 0 },
911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        { 0, 0, 1, 0 },
921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        { 0, 0, 0, 1 },
931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    };
941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return !memcmp(fMat, sIdentityMat, sizeof(fMat));
951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger///////////////////////////////////////////////////////////////////////////////
981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkMatrix44::setIdentity() {
1001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    sk_bzero(fMat, sizeof(fMat));
1011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    fMat[0][0] = fMat[1][1] = fMat[2][2] = fMat[3][3] = 1;
1021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
1031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkMatrix44::set3x3(SkMScalar m00, SkMScalar m01, SkMScalar m02,
1051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        SkMScalar m10, SkMScalar m11, SkMScalar m12,
1061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        SkMScalar m20, SkMScalar m21, SkMScalar m22) {
1071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    sk_bzero(fMat, sizeof(fMat));
1081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    fMat[0][0] = m00; fMat[0][1] = m01; fMat[0][2] = m02; fMat[0][3] = 0;
1091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    fMat[1][0] = m10; fMat[1][1] = m11; fMat[1][2] = m12; fMat[1][3] = 0;
1101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    fMat[2][0] = m20; fMat[2][1] = m21; fMat[2][2] = m22; fMat[2][3] = 0;
1111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    fMat[3][0] = 0;   fMat[3][1] = 0;   fMat[3][2] = 0;   fMat[3][3] = 1;
1121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
1131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger///////////////////////////////////////////////////////////////////////////////
1151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkMatrix44::setTranslate(SkMScalar tx, SkMScalar ty, SkMScalar tz) {
1171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    this->setIdentity();
1181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    fMat[3][0] = tx;
1191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    fMat[3][1] = ty;
1201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    fMat[3][2] = tz;
1211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    fMat[3][3] = 1;
1221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
1231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkMatrix44::preTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz) {
1251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkMatrix44 mat;
1261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    mat.setTranslate(dx, dy, dz);
1271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    this->preConcat(mat);
1281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
1291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkMatrix44::postTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz) {
1311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    fMat[3][0] += dx;
1321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    fMat[3][1] += dy;
1331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    fMat[3][2] += dz;
1341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
1351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger///////////////////////////////////////////////////////////////////////////////
1371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkMatrix44::setScale(SkMScalar sx, SkMScalar sy, SkMScalar sz) {
1391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    sk_bzero(fMat, sizeof(fMat));
1401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    fMat[0][0] = sx;
1411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    fMat[1][1] = sy;
1421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    fMat[2][2] = sz;
1431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    fMat[3][3] = 1;
1441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
1451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkMatrix44::preScale(SkMScalar sx, SkMScalar sy, SkMScalar sz) {
1471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkMatrix44 tmp;
1481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    tmp.setScale(sx, sy, sz);
1491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    this->preConcat(tmp);
1501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
1511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkMatrix44::postScale(SkMScalar sx, SkMScalar sy, SkMScalar sz) {
1531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    for (int i = 0; i < 4; i++) {
1541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        fMat[i][0] *= sx;
1551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        fMat[i][1] *= sy;
1561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        fMat[i][2] *= sz;
1571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
1581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
1591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger///////////////////////////////////////////////////////////////////////////////
1611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkMatrix44::setRotateAbout(SkMScalar x, SkMScalar y, SkMScalar z,
1631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                SkMScalar radians) {
1641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    double len2 = x * x + y * y + z * z;
1651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (len2 != 1) {
1661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (len2 == 0) {
1671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            this->setIdentity();
1681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            return;
1691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
1701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        double scale = 1 / sqrt(len2);
1711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        x = SkDoubleToMScalar(x * scale);
1721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        y = SkDoubleToMScalar(y * scale);
1731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        z = SkDoubleToMScalar(z * scale);
1741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
1751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    this->setRotateAboutUnit(x, y, z, radians);
1761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
1771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkMatrix44::setRotateAboutUnit(SkMScalar x, SkMScalar y, SkMScalar z,
1791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                    SkMScalar radians) {
1801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    double c = cos(radians);
1811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    double s = sin(radians);
1821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    double C = 1 - c;
1831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    double xs = x * s;
1841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    double ys = y * s;
1851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    double zs = z * s;
1861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    double xC = x * C;
1871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    double yC = y * C;
1881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    double zC = z * C;
1891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    double xyC = x * yC;
1901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    double yzC = y * zC;
1911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    double zxC = z * xC;
1921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // if you're looking at wikipedia, remember that we're column major.
1941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    this->set3x3(SkDoubleToMScalar(x * xC + c),     // scale x
1951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                 SkDoubleToMScalar(xyC + zs),       // skew x
1961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                 SkDoubleToMScalar(zxC - ys),       // trans x
1971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                 SkDoubleToMScalar(xyC - zs),       // skew y
1991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                 SkDoubleToMScalar(y * yC + c),     // scale y
2001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                 SkDoubleToMScalar(yzC + xs),       // trans y
2011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
2021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                 SkDoubleToMScalar(zxC + ys),       // persp x
2031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                 SkDoubleToMScalar(yzC - xs),       // persp y
2041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                 SkDoubleToMScalar(z * zC + c));    // persp 2
2051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
2061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
2071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger///////////////////////////////////////////////////////////////////////////////
2081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
2091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkMatrix44::setConcat(const SkMatrix44& a, const SkMatrix44& b) {
2101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkMScalar result[4][4];
2111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    for (int i = 0; i < 4; i++) {
2121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        for (int j = 0; j < 4; j++) {
2131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            double value = 0;
2141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            for (int k = 0; k < 4; k++) {
2151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                value += SkMScalarToDouble(a.fMat[k][i]) * b.fMat[j][k];
2161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            }
2171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            result[j][i] = SkDoubleToMScalar(value);
2181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
2191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
2201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    memcpy(fMat, result, sizeof(result));
2211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
2221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
2231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger///////////////////////////////////////////////////////////////////////////////
2241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
2251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic inline SkMScalar det2x2(double m00, double m01, double m10, double m11) {
2261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return SkDoubleToMScalar(m00 * m11 - m10 * m01);
2271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
2281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
2291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic inline double det3x3(double m00, double m01, double m02,
2301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                            double m10, double m11, double m12,
2311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                            double m20, double m21, double m22) {
2321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return  m00 * det2x2(m11, m12, m21, m22) -
2331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    m10 * det2x2(m01, m02, m21, m22) +
2341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    m20 * det2x2(m01, m02, m11, m12);
2351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
2361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
2371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/** We always perform the calculation in doubles, to avoid prematurely losing
2381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    precision along the way. This relies on the compiler automatically
2391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    promoting our SkMScalar values to double (if needed).
2401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */
2411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerdouble SkMatrix44::determinant() const {
2421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return  fMat[0][0] * det3x3(fMat[1][1], fMat[1][2], fMat[1][3],
2431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                fMat[2][1], fMat[2][2], fMat[2][3],
2441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                fMat[3][1], fMat[3][2], fMat[3][3]) -
2451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    fMat[1][0] * det3x3(fMat[0][1], fMat[0][2], fMat[0][3],
2461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        fMat[2][1], fMat[2][2], fMat[2][3],
2471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        fMat[3][1], fMat[3][2], fMat[3][3]) +
2481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    fMat[2][0] * det3x3(fMat[0][1], fMat[0][2], fMat[0][3],
2491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        fMat[1][1], fMat[1][2], fMat[1][3],
2501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        fMat[3][1], fMat[3][2], fMat[3][3]) -
2511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    fMat[3][0] * det3x3(fMat[0][1], fMat[0][2], fMat[0][3],
2521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        fMat[1][1], fMat[1][2], fMat[1][3],
2531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        fMat[2][1], fMat[2][2], fMat[2][3]);
2541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
2551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
2561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger///////////////////////////////////////////////////////////////////////////////
2571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
2581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// just picked a small value. not sure how to pick the "right" one
2591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#define TOO_SMALL_FOR_DETERMINANT   (1.e-8)
2601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
2611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic inline double dabs(double x) {
2621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (x < 0) {
2631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        x = -x;
2641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
2651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return x;
2661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
2671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
2681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerbool SkMatrix44::invert(SkMatrix44* inverse) const {
2691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    double det = this->determinant();
2701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (dabs(det) < TOO_SMALL_FOR_DETERMINANT) {
2711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return false;
2721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
2731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (NULL == inverse) {
2741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return true;
2751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
2761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
2771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // we explicitly promote to doubles to keep the intermediate values in
2781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // higher precision (assuming SkMScalar isn't already a double)
2791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    double m00 = fMat[0][0];
2801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    double m01 = fMat[0][1];
2811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    double m02 = fMat[0][2];
2821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    double m03 = fMat[0][3];
2831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    double m10 = fMat[1][0];
2841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    double m11 = fMat[1][1];
2851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    double m12 = fMat[1][2];
2861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    double m13 = fMat[1][3];
2871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    double m20 = fMat[2][0];
2881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    double m21 = fMat[2][1];
2891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    double m22 = fMat[2][2];
2901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    double m23 = fMat[2][3];
2911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    double m30 = fMat[3][0];
2921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    double m31 = fMat[3][1];
2931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    double m32 = fMat[3][2];
2941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    double m33 = fMat[3][3];
2951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
2961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    double tmp[4][4];
2971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
2981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    tmp[0][0] = m12*m23*m31 - m13*m22*m31 + m13*m21*m32 - m11*m23*m32 - m12*m21*m33 + m11*m22*m33;
2991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    tmp[0][1] = m03*m22*m31 - m02*m23*m31 - m03*m21*m32 + m01*m23*m32 + m02*m21*m33 - m01*m22*m33;
3001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    tmp[0][2] = m02*m13*m31 - m03*m12*m31 + m03*m11*m32 - m01*m13*m32 - m02*m11*m33 + m01*m12*m33;
3011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    tmp[0][3] = m03*m12*m21 - m02*m13*m21 - m03*m11*m22 + m01*m13*m22 + m02*m11*m23 - m01*m12*m23;
3021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    tmp[1][0] = m13*m22*m30 - m12*m23*m30 - m13*m20*m32 + m10*m23*m32 + m12*m20*m33 - m10*m22*m33;
3031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    tmp[1][1] = m02*m23*m30 - m03*m22*m30 + m03*m20*m32 - m00*m23*m32 - m02*m20*m33 + m00*m22*m33;
3041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    tmp[1][2] = m03*m12*m30 - m02*m13*m30 - m03*m10*m32 + m00*m13*m32 + m02*m10*m33 - m00*m12*m33;
3051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    tmp[1][3] = m02*m13*m20 - m03*m12*m20 + m03*m10*m22 - m00*m13*m22 - m02*m10*m23 + m00*m12*m23;
3061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    tmp[2][0] = m11*m23*m30 - m13*m21*m30 + m13*m20*m31 - m10*m23*m31 - m11*m20*m33 + m10*m21*m33;
3071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    tmp[2][1] = m03*m21*m30 - m01*m23*m30 - m03*m20*m31 + m00*m23*m31 + m01*m20*m33 - m00*m21*m33;
3081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    tmp[2][2] = m01*m13*m30 - m03*m11*m30 + m03*m10*m31 - m00*m13*m31 - m01*m10*m33 + m00*m11*m33;
3091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    tmp[2][3] = m03*m11*m20 - m01*m13*m20 - m03*m10*m21 + m00*m13*m21 + m01*m10*m23 - m00*m11*m23;
3101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    tmp[3][0] = m12*m21*m30 - m11*m22*m30 - m12*m20*m31 + m10*m22*m31 + m11*m20*m32 - m10*m21*m32;
3111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    tmp[3][1] = m01*m22*m30 - m02*m21*m30 + m02*m20*m31 - m00*m22*m31 - m01*m20*m32 + m00*m21*m32;
3121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    tmp[3][2] = m02*m11*m30 - m01*m12*m30 - m02*m10*m31 + m00*m12*m31 + m01*m10*m32 - m00*m11*m32;
3131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    tmp[3][3] = m01*m12*m20 - m02*m11*m20 + m02*m10*m21 - m00*m12*m21 - m01*m10*m22 + m00*m11*m22;
3141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    double invDet = 1.0 / det;
3161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    for (int i = 0; i < 4; i++) {
3171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        for (int j = 0; j < 4; j++) {
3181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            inverse->fMat[i][j] = SkDoubleToMScalar(tmp[i][j] * invDet);
3191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
3201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
3211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return true;
3221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
3231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger///////////////////////////////////////////////////////////////////////////////
3251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkMatrix44::map(const SkScalar src[4], SkScalar dst[4]) const {
3271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkScalar result[4];
3281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    for (int i = 0; i < 4; i++) {
3291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkMScalar value = 0;
3301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        for (int j = 0; j < 4; j++) {
3311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            value += fMat[j][i] * src[j];
3321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
3331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        result[i] = SkMScalarToScalar(value);
3341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
3351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    memcpy(dst, result, sizeof(result));
3361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
3371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger///////////////////////////////////////////////////////////////////////////////
3391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkMatrix44::dump() const {
3411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    static const char* format =
3421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        "[%g %g %g %g][%g %g %g %g][%g %g %g %g][%g %g %g %g]\n";
3431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#if 0
3441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkDebugf(format,
3451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger             fMat[0][0], fMat[1][0], fMat[2][0], fMat[3][0],
3461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger             fMat[0][1], fMat[1][1], fMat[2][1], fMat[3][1],
3471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger             fMat[0][2], fMat[1][2], fMat[2][2], fMat[3][2],
3481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger             fMat[0][3], fMat[1][3], fMat[2][3], fMat[3][3]);
3491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#else
3501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkDebugf(format,
3511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger             fMat[0][0], fMat[0][1], fMat[0][2], fMat[0][3],
3521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger             fMat[1][0], fMat[1][1], fMat[1][2], fMat[1][3],
3531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger             fMat[2][0], fMat[2][1], fMat[2][2], fMat[2][3],
3541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger             fMat[3][0], fMat[3][1], fMat[3][2], fMat[3][3]);
3551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
3561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
3571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger///////////////////////////////////////////////////////////////////////////////
3591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic void initFromMatrix(SkMScalar dst[4][4], const SkMatrix& src) {
3611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    sk_bzero(dst, 16 * sizeof(SkMScalar));
3621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    dst[0][0] = SkScalarToMScalar(src[SkMatrix::kMScaleX]);
3631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    dst[1][0] = SkScalarToMScalar(src[SkMatrix::kMSkewX]);
3641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    dst[3][0] = SkScalarToMScalar(src[SkMatrix::kMTransX]);
3651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    dst[0][1] = SkScalarToMScalar(src[SkMatrix::kMSkewY]);
3661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    dst[1][1] = SkScalarToMScalar(src[SkMatrix::kMScaleY]);
3671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    dst[3][1] = SkScalarToMScalar(src[SkMatrix::kMTransY]);
3681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    dst[2][2] = dst[3][3] = 1;
3691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
3701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3711cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerSkMatrix44::SkMatrix44(const SkMatrix& src) {
3721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    initFromMatrix(fMat, src);
3731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
3741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3751cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerSkMatrix44& SkMatrix44::operator=(const SkMatrix& src) {
3761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    initFromMatrix(fMat, src);
3771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return *this;
3781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
3791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3801cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerSkMatrix44::operator SkMatrix() const {
3811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkMatrix dst;
3821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    dst.reset();    // setup our perspective correctly for identity
3831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    dst[SkMatrix::kMScaleX]  = SkMScalarToScalar(fMat[0][0]);
3851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    dst[SkMatrix::kMSkewX]  = SkMScalarToScalar(fMat[1][0]);
3861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    dst[SkMatrix::kMTransX] = SkMScalarToScalar(fMat[3][0]);
3871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    dst[SkMatrix::kMSkewY]  = SkMScalarToScalar(fMat[0][1]);
3891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    dst[SkMatrix::kMScaleY] = SkMScalarToScalar(fMat[1][1]);
3901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    dst[SkMatrix::kMTransY] = SkMScalarToScalar(fMat[3][1]);
3911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return dst;
3931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
394