SkMatrix44.cpp revision 9d12f5c11b56ef51ba2c95db721ae7e5bab27023
18260a895869beaa4cab9f8b915e457728f41e561reed@google.com 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc. 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 78260a895869beaa4cab9f8b915e457728f41e561reed@google.com */ 88260a895869beaa4cab9f8b915e457728f41e561reed@google.com 98260a895869beaa4cab9f8b915e457728f41e561reed@google.com 10ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 118260a895869beaa4cab9f8b915e457728f41e561reed@google.com#include "SkMatrix44.h" 128260a895869beaa4cab9f8b915e457728f41e561reed@google.com 138260a895869beaa4cab9f8b915e457728f41e561reed@google.comSkMatrix44::SkMatrix44() { 148260a895869beaa4cab9f8b915e457728f41e561reed@google.com this->setIdentity(); 158260a895869beaa4cab9f8b915e457728f41e561reed@google.com} 168260a895869beaa4cab9f8b915e457728f41e561reed@google.com 178260a895869beaa4cab9f8b915e457728f41e561reed@google.comSkMatrix44::SkMatrix44(const SkMatrix44& src) { 188260a895869beaa4cab9f8b915e457728f41e561reed@google.com memcpy(this, &src, sizeof(src)); 198260a895869beaa4cab9f8b915e457728f41e561reed@google.com} 208260a895869beaa4cab9f8b915e457728f41e561reed@google.com 218260a895869beaa4cab9f8b915e457728f41e561reed@google.comSkMatrix44::SkMatrix44(const SkMatrix44& a, const SkMatrix44& b) { 228260a895869beaa4cab9f8b915e457728f41e561reed@google.com this->setConcat(a, b); 238260a895869beaa4cab9f8b915e457728f41e561reed@google.com} 248260a895869beaa4cab9f8b915e457728f41e561reed@google.com 258260a895869beaa4cab9f8b915e457728f41e561reed@google.comSkMScalar SkMatrix44::get(int row, int col) const { 268260a895869beaa4cab9f8b915e457728f41e561reed@google.com SkASSERT(row <= 3 && row >= 0); 278260a895869beaa4cab9f8b915e457728f41e561reed@google.com SkASSERT(col <= 3 && col >= 0); 288260a895869beaa4cab9f8b915e457728f41e561reed@google.com return fMat[col][row]; 298260a895869beaa4cab9f8b915e457728f41e561reed@google.com} 308260a895869beaa4cab9f8b915e457728f41e561reed@google.com 318260a895869beaa4cab9f8b915e457728f41e561reed@google.comvoid SkMatrix44::set(int row, int col, const SkMScalar& value) { 328260a895869beaa4cab9f8b915e457728f41e561reed@google.com SkASSERT(row <= 3 && row >= 0); 338260a895869beaa4cab9f8b915e457728f41e561reed@google.com SkASSERT(col <= 3 && col >= 0); 348260a895869beaa4cab9f8b915e457728f41e561reed@google.com fMat[col][row] = value; 358260a895869beaa4cab9f8b915e457728f41e561reed@google.com} 368260a895869beaa4cab9f8b915e457728f41e561reed@google.com 378260a895869beaa4cab9f8b915e457728f41e561reed@google.com/////////////////////////////////////////////////////////////////////////////// 388260a895869beaa4cab9f8b915e457728f41e561reed@google.com 39da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.comvoid SkMatrix44::asColMajorf(float dst[]) const { 40da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com const SkMScalar* src = &fMat[0][0]; 41da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com#ifdef SK_MSCALAR_IS_DOUBLE 42da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com for (int i = 0; i < 16; ++i) { 43da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com dst[i] = SkMScalarToFloat(src[i]); 44da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com } 45da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com#else 46da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com memcpy(dst, src, 16 * sizeof(float)); 47da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com#endif 48da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com} 49da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com 50da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.comvoid SkMatrix44::asColMajord(double dst[]) const { 51da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com const SkMScalar* src = &fMat[0][0]; 52da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com#ifdef SK_MSCALAR_IS_DOUBLE 53da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com memcpy(dst, src, 16 * sizeof(double)); 54da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com#else 55da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com for (int i = 0; i < 16; ++i) { 56da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com dst[i] = SkMScalarToDouble(src[i]); 57da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com } 58da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com#endif 59da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com} 60da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com 61da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.comvoid SkMatrix44::asRowMajorf(float dst[]) const { 62da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com const SkMScalar* src = &fMat[0][0]; 63da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com for (int i = 0; i < 4; ++i) { 64da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com dst[0] = SkMScalarToFloat(src[0]); 65da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com dst[4] = SkMScalarToFloat(src[1]); 66da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com dst[8] = SkMScalarToFloat(src[2]); 67da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com dst[12] = SkMScalarToFloat(src[3]); 68da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com src += 4; 69da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com dst += 1; 70da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com } 71da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com} 72da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com 73da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.comvoid SkMatrix44::asRowMajord(double dst[]) const { 74da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com const SkMScalar* src = &fMat[0][0]; 75da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com for (int i = 0; i < 4; ++i) { 76da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com dst[0] = SkMScalarToDouble(src[0]); 77da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com dst[4] = SkMScalarToDouble(src[1]); 78da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com dst[8] = SkMScalarToDouble(src[2]); 79da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com dst[12] = SkMScalarToDouble(src[3]); 80da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com src += 4; 81da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com dst += 1; 82da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com } 83da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com} 84da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com 85da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com/////////////////////////////////////////////////////////////////////////////// 86da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com 878260a895869beaa4cab9f8b915e457728f41e561reed@google.comstatic const SkMatrix44 gIdentity44; 888260a895869beaa4cab9f8b915e457728f41e561reed@google.com 898260a895869beaa4cab9f8b915e457728f41e561reed@google.combool SkMatrix44::isIdentity() const { 908260a895869beaa4cab9f8b915e457728f41e561reed@google.com return *this == gIdentity44; 918260a895869beaa4cab9f8b915e457728f41e561reed@google.com} 928260a895869beaa4cab9f8b915e457728f41e561reed@google.com 938260a895869beaa4cab9f8b915e457728f41e561reed@google.com/////////////////////////////////////////////////////////////////////////////// 948260a895869beaa4cab9f8b915e457728f41e561reed@google.com 958260a895869beaa4cab9f8b915e457728f41e561reed@google.comvoid SkMatrix44::setIdentity() { 968260a895869beaa4cab9f8b915e457728f41e561reed@google.com sk_bzero(fMat, sizeof(fMat)); 978260a895869beaa4cab9f8b915e457728f41e561reed@google.com fMat[0][0] = fMat[1][1] = fMat[2][2] = fMat[3][3] = 1; 988260a895869beaa4cab9f8b915e457728f41e561reed@google.com} 998260a895869beaa4cab9f8b915e457728f41e561reed@google.com 1008260a895869beaa4cab9f8b915e457728f41e561reed@google.comvoid SkMatrix44::set3x3(SkMScalar m00, SkMScalar m01, SkMScalar m02, 1018260a895869beaa4cab9f8b915e457728f41e561reed@google.com SkMScalar m10, SkMScalar m11, SkMScalar m12, 1028260a895869beaa4cab9f8b915e457728f41e561reed@google.com SkMScalar m20, SkMScalar m21, SkMScalar m22) { 1038260a895869beaa4cab9f8b915e457728f41e561reed@google.com sk_bzero(fMat, sizeof(fMat)); 1048260a895869beaa4cab9f8b915e457728f41e561reed@google.com fMat[0][0] = m00; fMat[0][1] = m01; fMat[0][2] = m02; fMat[0][3] = 0; 1058260a895869beaa4cab9f8b915e457728f41e561reed@google.com fMat[1][0] = m10; fMat[1][1] = m11; fMat[1][2] = m12; fMat[1][3] = 0; 1068260a895869beaa4cab9f8b915e457728f41e561reed@google.com fMat[2][0] = m20; fMat[2][1] = m21; fMat[2][2] = m22; fMat[2][3] = 0; 1078260a895869beaa4cab9f8b915e457728f41e561reed@google.com fMat[3][0] = 0; fMat[3][1] = 0; fMat[3][2] = 0; fMat[3][3] = 1; 1088260a895869beaa4cab9f8b915e457728f41e561reed@google.com} 1098260a895869beaa4cab9f8b915e457728f41e561reed@google.com 1108260a895869beaa4cab9f8b915e457728f41e561reed@google.com/////////////////////////////////////////////////////////////////////////////// 1118260a895869beaa4cab9f8b915e457728f41e561reed@google.com 1128260a895869beaa4cab9f8b915e457728f41e561reed@google.comvoid SkMatrix44::setTranslate(SkMScalar tx, SkMScalar ty, SkMScalar tz) { 1138260a895869beaa4cab9f8b915e457728f41e561reed@google.com this->setIdentity(); 1148260a895869beaa4cab9f8b915e457728f41e561reed@google.com fMat[3][0] = tx; 1158260a895869beaa4cab9f8b915e457728f41e561reed@google.com fMat[3][1] = ty; 1168260a895869beaa4cab9f8b915e457728f41e561reed@google.com fMat[3][2] = tz; 1178260a895869beaa4cab9f8b915e457728f41e561reed@google.com fMat[3][3] = 1; 1188260a895869beaa4cab9f8b915e457728f41e561reed@google.com} 1198260a895869beaa4cab9f8b915e457728f41e561reed@google.com 1208260a895869beaa4cab9f8b915e457728f41e561reed@google.comvoid SkMatrix44::preTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz) { 1218260a895869beaa4cab9f8b915e457728f41e561reed@google.com SkMatrix44 mat; 1228260a895869beaa4cab9f8b915e457728f41e561reed@google.com mat.setTranslate(dx, dy, dz); 1238260a895869beaa4cab9f8b915e457728f41e561reed@google.com this->preConcat(mat); 1248260a895869beaa4cab9f8b915e457728f41e561reed@google.com} 1258260a895869beaa4cab9f8b915e457728f41e561reed@google.com 1268260a895869beaa4cab9f8b915e457728f41e561reed@google.comvoid SkMatrix44::postTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz) { 1278260a895869beaa4cab9f8b915e457728f41e561reed@google.com fMat[3][0] += dx; 1288260a895869beaa4cab9f8b915e457728f41e561reed@google.com fMat[3][1] += dy; 1298260a895869beaa4cab9f8b915e457728f41e561reed@google.com fMat[3][2] += dz; 1308260a895869beaa4cab9f8b915e457728f41e561reed@google.com} 1318260a895869beaa4cab9f8b915e457728f41e561reed@google.com 1328260a895869beaa4cab9f8b915e457728f41e561reed@google.com/////////////////////////////////////////////////////////////////////////////// 1338260a895869beaa4cab9f8b915e457728f41e561reed@google.com 1348260a895869beaa4cab9f8b915e457728f41e561reed@google.comvoid SkMatrix44::setScale(SkMScalar sx, SkMScalar sy, SkMScalar sz) { 1358260a895869beaa4cab9f8b915e457728f41e561reed@google.com sk_bzero(fMat, sizeof(fMat)); 1368260a895869beaa4cab9f8b915e457728f41e561reed@google.com fMat[0][0] = sx; 1378260a895869beaa4cab9f8b915e457728f41e561reed@google.com fMat[1][1] = sy; 1388260a895869beaa4cab9f8b915e457728f41e561reed@google.com fMat[2][2] = sz; 1398260a895869beaa4cab9f8b915e457728f41e561reed@google.com fMat[3][3] = 1; 1408260a895869beaa4cab9f8b915e457728f41e561reed@google.com} 1418260a895869beaa4cab9f8b915e457728f41e561reed@google.com 1428260a895869beaa4cab9f8b915e457728f41e561reed@google.comvoid SkMatrix44::preScale(SkMScalar sx, SkMScalar sy, SkMScalar sz) { 1438260a895869beaa4cab9f8b915e457728f41e561reed@google.com SkMatrix44 tmp; 1448260a895869beaa4cab9f8b915e457728f41e561reed@google.com tmp.setScale(sx, sy, sz); 1458260a895869beaa4cab9f8b915e457728f41e561reed@google.com this->preConcat(tmp); 1468260a895869beaa4cab9f8b915e457728f41e561reed@google.com} 1478260a895869beaa4cab9f8b915e457728f41e561reed@google.com 1488260a895869beaa4cab9f8b915e457728f41e561reed@google.comvoid SkMatrix44::postScale(SkMScalar sx, SkMScalar sy, SkMScalar sz) { 1498260a895869beaa4cab9f8b915e457728f41e561reed@google.com for (int i = 0; i < 4; i++) { 1508260a895869beaa4cab9f8b915e457728f41e561reed@google.com fMat[i][0] *= sx; 1518260a895869beaa4cab9f8b915e457728f41e561reed@google.com fMat[i][1] *= sy; 1528260a895869beaa4cab9f8b915e457728f41e561reed@google.com fMat[i][2] *= sz; 1538260a895869beaa4cab9f8b915e457728f41e561reed@google.com } 1548260a895869beaa4cab9f8b915e457728f41e561reed@google.com} 1558260a895869beaa4cab9f8b915e457728f41e561reed@google.com 1568260a895869beaa4cab9f8b915e457728f41e561reed@google.com/////////////////////////////////////////////////////////////////////////////// 1578260a895869beaa4cab9f8b915e457728f41e561reed@google.com 1588260a895869beaa4cab9f8b915e457728f41e561reed@google.comvoid SkMatrix44::setRotateAbout(SkMScalar x, SkMScalar y, SkMScalar z, 1598260a895869beaa4cab9f8b915e457728f41e561reed@google.com SkMScalar radians) { 1608260a895869beaa4cab9f8b915e457728f41e561reed@google.com double len2 = x * x + y * y + z * z; 1618260a895869beaa4cab9f8b915e457728f41e561reed@google.com if (len2 != 1) { 1628260a895869beaa4cab9f8b915e457728f41e561reed@google.com if (len2 == 0) { 1638260a895869beaa4cab9f8b915e457728f41e561reed@google.com this->setIdentity(); 1648260a895869beaa4cab9f8b915e457728f41e561reed@google.com return; 1658260a895869beaa4cab9f8b915e457728f41e561reed@google.com } 1668260a895869beaa4cab9f8b915e457728f41e561reed@google.com double scale = 1 / sqrt(len2); 1679d12f5c11b56ef51ba2c95db721ae7e5bab27023bsalomon@google.com x = SkDoubleToMScalar(x * scale); 1689d12f5c11b56ef51ba2c95db721ae7e5bab27023bsalomon@google.com y = SkDoubleToMScalar(y * scale); 1699d12f5c11b56ef51ba2c95db721ae7e5bab27023bsalomon@google.com z = SkDoubleToMScalar(z * scale); 1708260a895869beaa4cab9f8b915e457728f41e561reed@google.com } 1718260a895869beaa4cab9f8b915e457728f41e561reed@google.com this->setRotateAboutUnit(x, y, z, radians); 1728260a895869beaa4cab9f8b915e457728f41e561reed@google.com} 1738260a895869beaa4cab9f8b915e457728f41e561reed@google.com 1748260a895869beaa4cab9f8b915e457728f41e561reed@google.comvoid SkMatrix44::setRotateAboutUnit(SkMScalar x, SkMScalar y, SkMScalar z, 1758260a895869beaa4cab9f8b915e457728f41e561reed@google.com SkMScalar radians) { 1768260a895869beaa4cab9f8b915e457728f41e561reed@google.com double c = cos(radians); 1778260a895869beaa4cab9f8b915e457728f41e561reed@google.com double s = sin(radians); 1788260a895869beaa4cab9f8b915e457728f41e561reed@google.com double C = 1 - c; 1798260a895869beaa4cab9f8b915e457728f41e561reed@google.com double xs = x * s; 1808260a895869beaa4cab9f8b915e457728f41e561reed@google.com double ys = y * s; 1818260a895869beaa4cab9f8b915e457728f41e561reed@google.com double zs = z * s; 1828260a895869beaa4cab9f8b915e457728f41e561reed@google.com double xC = x * C; 1838260a895869beaa4cab9f8b915e457728f41e561reed@google.com double yC = y * C; 1848260a895869beaa4cab9f8b915e457728f41e561reed@google.com double zC = z * C; 1858260a895869beaa4cab9f8b915e457728f41e561reed@google.com double xyC = x * yC; 1868260a895869beaa4cab9f8b915e457728f41e561reed@google.com double yzC = y * zC; 1878260a895869beaa4cab9f8b915e457728f41e561reed@google.com double zxC = z * xC; 1888260a895869beaa4cab9f8b915e457728f41e561reed@google.com 1898260a895869beaa4cab9f8b915e457728f41e561reed@google.com // if you're looking at wikipedia, remember that we're column major. 1909d12f5c11b56ef51ba2c95db721ae7e5bab27023bsalomon@google.com this->set3x3(SkDoubleToMScalar(x * xC + c), // scale x 1919d12f5c11b56ef51ba2c95db721ae7e5bab27023bsalomon@google.com SkDoubleToMScalar(xyC + zs), // skew x 1929d12f5c11b56ef51ba2c95db721ae7e5bab27023bsalomon@google.com SkDoubleToMScalar(zxC - ys), // trans x 1939d12f5c11b56ef51ba2c95db721ae7e5bab27023bsalomon@google.com 1949d12f5c11b56ef51ba2c95db721ae7e5bab27023bsalomon@google.com SkDoubleToMScalar(xyC - zs), // skew y 1959d12f5c11b56ef51ba2c95db721ae7e5bab27023bsalomon@google.com SkDoubleToMScalar(y * yC + c), // scale y 1969d12f5c11b56ef51ba2c95db721ae7e5bab27023bsalomon@google.com SkDoubleToMScalar(yzC + xs), // trans y 1979d12f5c11b56ef51ba2c95db721ae7e5bab27023bsalomon@google.com 1989d12f5c11b56ef51ba2c95db721ae7e5bab27023bsalomon@google.com SkDoubleToMScalar(zxC + ys), // persp x 1999d12f5c11b56ef51ba2c95db721ae7e5bab27023bsalomon@google.com SkDoubleToMScalar(yzC - xs), // persp y 2009d12f5c11b56ef51ba2c95db721ae7e5bab27023bsalomon@google.com SkDoubleToMScalar(z * zC + c)); // persp 2 2018260a895869beaa4cab9f8b915e457728f41e561reed@google.com} 2028260a895869beaa4cab9f8b915e457728f41e561reed@google.com 2038260a895869beaa4cab9f8b915e457728f41e561reed@google.com/////////////////////////////////////////////////////////////////////////////// 2048260a895869beaa4cab9f8b915e457728f41e561reed@google.com 2058260a895869beaa4cab9f8b915e457728f41e561reed@google.comvoid SkMatrix44::setConcat(const SkMatrix44& a, const SkMatrix44& b) { 2068260a895869beaa4cab9f8b915e457728f41e561reed@google.com SkMScalar result[4][4]; 2078260a895869beaa4cab9f8b915e457728f41e561reed@google.com for (int i = 0; i < 4; i++) { 2088260a895869beaa4cab9f8b915e457728f41e561reed@google.com for (int j = 0; j < 4; j++) { 2098260a895869beaa4cab9f8b915e457728f41e561reed@google.com double value = 0; 2108260a895869beaa4cab9f8b915e457728f41e561reed@google.com for (int k = 0; k < 4; k++) { 2118260a895869beaa4cab9f8b915e457728f41e561reed@google.com value += SkMScalarToDouble(a.fMat[k][i]) * b.fMat[j][k]; 2128260a895869beaa4cab9f8b915e457728f41e561reed@google.com } 2138260a895869beaa4cab9f8b915e457728f41e561reed@google.com result[j][i] = SkDoubleToMScalar(value); 2148260a895869beaa4cab9f8b915e457728f41e561reed@google.com } 2158260a895869beaa4cab9f8b915e457728f41e561reed@google.com } 2168260a895869beaa4cab9f8b915e457728f41e561reed@google.com memcpy(fMat, result, sizeof(result)); 2178260a895869beaa4cab9f8b915e457728f41e561reed@google.com} 2188260a895869beaa4cab9f8b915e457728f41e561reed@google.com 2198260a895869beaa4cab9f8b915e457728f41e561reed@google.com/////////////////////////////////////////////////////////////////////////////// 2208260a895869beaa4cab9f8b915e457728f41e561reed@google.com 2218260a895869beaa4cab9f8b915e457728f41e561reed@google.comstatic inline SkMScalar det2x2(double m00, double m01, double m10, double m11) { 2229d12f5c11b56ef51ba2c95db721ae7e5bab27023bsalomon@google.com return SkDoubleToMScalar(m00 * m11 - m10 * m01); 2238260a895869beaa4cab9f8b915e457728f41e561reed@google.com} 2248260a895869beaa4cab9f8b915e457728f41e561reed@google.com 2258260a895869beaa4cab9f8b915e457728f41e561reed@google.comstatic inline double det3x3(double m00, double m01, double m02, 2268260a895869beaa4cab9f8b915e457728f41e561reed@google.com double m10, double m11, double m12, 2278260a895869beaa4cab9f8b915e457728f41e561reed@google.com double m20, double m21, double m22) { 2288260a895869beaa4cab9f8b915e457728f41e561reed@google.com return m00 * det2x2(m11, m12, m21, m22) - 2298260a895869beaa4cab9f8b915e457728f41e561reed@google.com m10 * det2x2(m01, m02, m21, m22) + 2308260a895869beaa4cab9f8b915e457728f41e561reed@google.com m20 * det2x2(m01, m02, m11, m12); 2318260a895869beaa4cab9f8b915e457728f41e561reed@google.com} 2328260a895869beaa4cab9f8b915e457728f41e561reed@google.com 2338260a895869beaa4cab9f8b915e457728f41e561reed@google.com/** We always perform the calculation in doubles, to avoid prematurely losing 2348260a895869beaa4cab9f8b915e457728f41e561reed@google.com precision along the way. This relies on the compiler automatically 2358260a895869beaa4cab9f8b915e457728f41e561reed@google.com promoting our SkMScalar values to double (if needed). 2368260a895869beaa4cab9f8b915e457728f41e561reed@google.com */ 2378260a895869beaa4cab9f8b915e457728f41e561reed@google.comdouble SkMatrix44::determinant() const { 2388260a895869beaa4cab9f8b915e457728f41e561reed@google.com return fMat[0][0] * det3x3(fMat[1][1], fMat[1][2], fMat[1][3], 2398260a895869beaa4cab9f8b915e457728f41e561reed@google.com fMat[2][1], fMat[2][2], fMat[2][3], 2408260a895869beaa4cab9f8b915e457728f41e561reed@google.com fMat[3][1], fMat[3][2], fMat[3][3]) - 2418260a895869beaa4cab9f8b915e457728f41e561reed@google.com fMat[1][0] * det3x3(fMat[0][1], fMat[0][2], fMat[0][3], 2428260a895869beaa4cab9f8b915e457728f41e561reed@google.com fMat[2][1], fMat[2][2], fMat[2][3], 2438260a895869beaa4cab9f8b915e457728f41e561reed@google.com fMat[3][1], fMat[3][2], fMat[3][3]) + 2448260a895869beaa4cab9f8b915e457728f41e561reed@google.com fMat[2][0] * det3x3(fMat[0][1], fMat[0][2], fMat[0][3], 2458260a895869beaa4cab9f8b915e457728f41e561reed@google.com fMat[1][1], fMat[1][2], fMat[1][3], 2468260a895869beaa4cab9f8b915e457728f41e561reed@google.com fMat[3][1], fMat[3][2], fMat[3][3]) - 2478260a895869beaa4cab9f8b915e457728f41e561reed@google.com fMat[3][0] * det3x3(fMat[0][1], fMat[0][2], fMat[0][3], 2488260a895869beaa4cab9f8b915e457728f41e561reed@google.com fMat[1][1], fMat[1][2], fMat[1][3], 2498260a895869beaa4cab9f8b915e457728f41e561reed@google.com fMat[2][1], fMat[2][2], fMat[2][3]); 2508260a895869beaa4cab9f8b915e457728f41e561reed@google.com} 2518260a895869beaa4cab9f8b915e457728f41e561reed@google.com 2528260a895869beaa4cab9f8b915e457728f41e561reed@google.com/////////////////////////////////////////////////////////////////////////////// 2538260a895869beaa4cab9f8b915e457728f41e561reed@google.com 2548260a895869beaa4cab9f8b915e457728f41e561reed@google.com// just picked a small value. not sure how to pick the "right" one 2558260a895869beaa4cab9f8b915e457728f41e561reed@google.com#define TOO_SMALL_FOR_DETERMINANT (1.e-8) 2568260a895869beaa4cab9f8b915e457728f41e561reed@google.com 2578260a895869beaa4cab9f8b915e457728f41e561reed@google.comstatic inline double dabs(double x) { 2588260a895869beaa4cab9f8b915e457728f41e561reed@google.com if (x < 0) { 2598260a895869beaa4cab9f8b915e457728f41e561reed@google.com x = -x; 2608260a895869beaa4cab9f8b915e457728f41e561reed@google.com } 2618260a895869beaa4cab9f8b915e457728f41e561reed@google.com return x; 2628260a895869beaa4cab9f8b915e457728f41e561reed@google.com} 2638260a895869beaa4cab9f8b915e457728f41e561reed@google.com 2648260a895869beaa4cab9f8b915e457728f41e561reed@google.combool SkMatrix44::invert(SkMatrix44* inverse) const { 2658260a895869beaa4cab9f8b915e457728f41e561reed@google.com double det = this->determinant(); 2668260a895869beaa4cab9f8b915e457728f41e561reed@google.com if (dabs(det) < TOO_SMALL_FOR_DETERMINANT) { 2678260a895869beaa4cab9f8b915e457728f41e561reed@google.com return false; 2688260a895869beaa4cab9f8b915e457728f41e561reed@google.com } 2698260a895869beaa4cab9f8b915e457728f41e561reed@google.com if (NULL == inverse) { 2708260a895869beaa4cab9f8b915e457728f41e561reed@google.com return true; 2718260a895869beaa4cab9f8b915e457728f41e561reed@google.com } 2728260a895869beaa4cab9f8b915e457728f41e561reed@google.com 2738260a895869beaa4cab9f8b915e457728f41e561reed@google.com // we explicitly promote to doubles to keep the intermediate values in 2748260a895869beaa4cab9f8b915e457728f41e561reed@google.com // higher precision (assuming SkMScalar isn't already a double) 2758260a895869beaa4cab9f8b915e457728f41e561reed@google.com double m00 = fMat[0][0]; 2768260a895869beaa4cab9f8b915e457728f41e561reed@google.com double m01 = fMat[0][1]; 2778260a895869beaa4cab9f8b915e457728f41e561reed@google.com double m02 = fMat[0][2]; 2788260a895869beaa4cab9f8b915e457728f41e561reed@google.com double m03 = fMat[0][3]; 2798260a895869beaa4cab9f8b915e457728f41e561reed@google.com double m10 = fMat[1][0]; 2808260a895869beaa4cab9f8b915e457728f41e561reed@google.com double m11 = fMat[1][1]; 2818260a895869beaa4cab9f8b915e457728f41e561reed@google.com double m12 = fMat[1][2]; 2828260a895869beaa4cab9f8b915e457728f41e561reed@google.com double m13 = fMat[1][3]; 2838260a895869beaa4cab9f8b915e457728f41e561reed@google.com double m20 = fMat[2][0]; 2848260a895869beaa4cab9f8b915e457728f41e561reed@google.com double m21 = fMat[2][1]; 2858260a895869beaa4cab9f8b915e457728f41e561reed@google.com double m22 = fMat[2][2]; 2868260a895869beaa4cab9f8b915e457728f41e561reed@google.com double m23 = fMat[2][3]; 2878260a895869beaa4cab9f8b915e457728f41e561reed@google.com double m30 = fMat[3][0]; 2888260a895869beaa4cab9f8b915e457728f41e561reed@google.com double m31 = fMat[3][1]; 2898260a895869beaa4cab9f8b915e457728f41e561reed@google.com double m32 = fMat[3][2]; 2908260a895869beaa4cab9f8b915e457728f41e561reed@google.com double m33 = fMat[3][3]; 2918260a895869beaa4cab9f8b915e457728f41e561reed@google.com 2928260a895869beaa4cab9f8b915e457728f41e561reed@google.com double tmp[4][4]; 2938260a895869beaa4cab9f8b915e457728f41e561reed@google.com 2948260a895869beaa4cab9f8b915e457728f41e561reed@google.com tmp[0][0] = m12*m23*m31 - m13*m22*m31 + m13*m21*m32 - m11*m23*m32 - m12*m21*m33 + m11*m22*m33; 2958260a895869beaa4cab9f8b915e457728f41e561reed@google.com tmp[0][1] = m03*m22*m31 - m02*m23*m31 - m03*m21*m32 + m01*m23*m32 + m02*m21*m33 - m01*m22*m33; 2968260a895869beaa4cab9f8b915e457728f41e561reed@google.com tmp[0][2] = m02*m13*m31 - m03*m12*m31 + m03*m11*m32 - m01*m13*m32 - m02*m11*m33 + m01*m12*m33; 2978260a895869beaa4cab9f8b915e457728f41e561reed@google.com tmp[0][3] = m03*m12*m21 - m02*m13*m21 - m03*m11*m22 + m01*m13*m22 + m02*m11*m23 - m01*m12*m23; 2988260a895869beaa4cab9f8b915e457728f41e561reed@google.com tmp[1][0] = m13*m22*m30 - m12*m23*m30 - m13*m20*m32 + m10*m23*m32 + m12*m20*m33 - m10*m22*m33; 2998260a895869beaa4cab9f8b915e457728f41e561reed@google.com tmp[1][1] = m02*m23*m30 - m03*m22*m30 + m03*m20*m32 - m00*m23*m32 - m02*m20*m33 + m00*m22*m33; 3008260a895869beaa4cab9f8b915e457728f41e561reed@google.com tmp[1][2] = m03*m12*m30 - m02*m13*m30 - m03*m10*m32 + m00*m13*m32 + m02*m10*m33 - m00*m12*m33; 3018260a895869beaa4cab9f8b915e457728f41e561reed@google.com tmp[1][3] = m02*m13*m20 - m03*m12*m20 + m03*m10*m22 - m00*m13*m22 - m02*m10*m23 + m00*m12*m23; 3028260a895869beaa4cab9f8b915e457728f41e561reed@google.com tmp[2][0] = m11*m23*m30 - m13*m21*m30 + m13*m20*m31 - m10*m23*m31 - m11*m20*m33 + m10*m21*m33; 3038260a895869beaa4cab9f8b915e457728f41e561reed@google.com tmp[2][1] = m03*m21*m30 - m01*m23*m30 - m03*m20*m31 + m00*m23*m31 + m01*m20*m33 - m00*m21*m33; 3048260a895869beaa4cab9f8b915e457728f41e561reed@google.com tmp[2][2] = m01*m13*m30 - m03*m11*m30 + m03*m10*m31 - m00*m13*m31 - m01*m10*m33 + m00*m11*m33; 3058260a895869beaa4cab9f8b915e457728f41e561reed@google.com tmp[2][3] = m03*m11*m20 - m01*m13*m20 - m03*m10*m21 + m00*m13*m21 + m01*m10*m23 - m00*m11*m23; 3068260a895869beaa4cab9f8b915e457728f41e561reed@google.com tmp[3][0] = m12*m21*m30 - m11*m22*m30 - m12*m20*m31 + m10*m22*m31 + m11*m20*m32 - m10*m21*m32; 3078260a895869beaa4cab9f8b915e457728f41e561reed@google.com tmp[3][1] = m01*m22*m30 - m02*m21*m30 + m02*m20*m31 - m00*m22*m31 - m01*m20*m32 + m00*m21*m32; 3088260a895869beaa4cab9f8b915e457728f41e561reed@google.com tmp[3][2] = m02*m11*m30 - m01*m12*m30 - m02*m10*m31 + m00*m12*m31 + m01*m10*m32 - m00*m11*m32; 3098260a895869beaa4cab9f8b915e457728f41e561reed@google.com tmp[3][3] = m01*m12*m20 - m02*m11*m20 + m02*m10*m21 - m00*m12*m21 - m01*m10*m22 + m00*m11*m22; 3108260a895869beaa4cab9f8b915e457728f41e561reed@google.com 3118260a895869beaa4cab9f8b915e457728f41e561reed@google.com double invDet = 1.0 / det; 3128260a895869beaa4cab9f8b915e457728f41e561reed@google.com for (int i = 0; i < 4; i++) { 3138260a895869beaa4cab9f8b915e457728f41e561reed@google.com for (int j = 0; j < 4; j++) { 3148260a895869beaa4cab9f8b915e457728f41e561reed@google.com inverse->fMat[i][j] = SkDoubleToMScalar(tmp[i][j] * invDet); 3158260a895869beaa4cab9f8b915e457728f41e561reed@google.com } 3168260a895869beaa4cab9f8b915e457728f41e561reed@google.com } 3178260a895869beaa4cab9f8b915e457728f41e561reed@google.com return true; 3188260a895869beaa4cab9f8b915e457728f41e561reed@google.com} 3198260a895869beaa4cab9f8b915e457728f41e561reed@google.com 3208260a895869beaa4cab9f8b915e457728f41e561reed@google.com/////////////////////////////////////////////////////////////////////////////// 3218260a895869beaa4cab9f8b915e457728f41e561reed@google.com 3228260a895869beaa4cab9f8b915e457728f41e561reed@google.comvoid SkMatrix44::map(const SkScalar src[4], SkScalar dst[4]) const { 3238260a895869beaa4cab9f8b915e457728f41e561reed@google.com SkScalar result[4]; 3248260a895869beaa4cab9f8b915e457728f41e561reed@google.com for (int i = 0; i < 4; i++) { 3258260a895869beaa4cab9f8b915e457728f41e561reed@google.com SkMScalar value = 0; 3268260a895869beaa4cab9f8b915e457728f41e561reed@google.com for (int j = 0; j < 4; j++) { 3278260a895869beaa4cab9f8b915e457728f41e561reed@google.com value += fMat[j][i] * src[j]; 3288260a895869beaa4cab9f8b915e457728f41e561reed@google.com } 3298260a895869beaa4cab9f8b915e457728f41e561reed@google.com result[i] = value; 3308260a895869beaa4cab9f8b915e457728f41e561reed@google.com } 3318260a895869beaa4cab9f8b915e457728f41e561reed@google.com memcpy(dst, result, sizeof(result)); 3328260a895869beaa4cab9f8b915e457728f41e561reed@google.com} 3338260a895869beaa4cab9f8b915e457728f41e561reed@google.com 3348260a895869beaa4cab9f8b915e457728f41e561reed@google.com/////////////////////////////////////////////////////////////////////////////// 3358260a895869beaa4cab9f8b915e457728f41e561reed@google.com 3368260a895869beaa4cab9f8b915e457728f41e561reed@google.comvoid SkMatrix44::dump() const { 3379ac4a89d35df3d581886a84df421161418707fd6tomhudson@google.com static const char* format = 3389ac4a89d35df3d581886a84df421161418707fd6tomhudson@google.com "[%g %g %g %g][%g %g %g %g][%g %g %g %g][%g %g %g %g]\n"; 3398260a895869beaa4cab9f8b915e457728f41e561reed@google.com#if 0 3409ac4a89d35df3d581886a84df421161418707fd6tomhudson@google.com SkDebugf(format, 3418260a895869beaa4cab9f8b915e457728f41e561reed@google.com fMat[0][0], fMat[1][0], fMat[2][0], fMat[3][0], 3428260a895869beaa4cab9f8b915e457728f41e561reed@google.com fMat[0][1], fMat[1][1], fMat[2][1], fMat[3][1], 3438260a895869beaa4cab9f8b915e457728f41e561reed@google.com fMat[0][2], fMat[1][2], fMat[2][2], fMat[3][2], 3448260a895869beaa4cab9f8b915e457728f41e561reed@google.com fMat[0][3], fMat[1][3], fMat[2][3], fMat[3][3]); 3459ac4a89d35df3d581886a84df421161418707fd6tomhudson@google.com#else 3469ac4a89d35df3d581886a84df421161418707fd6tomhudson@google.com SkDebugf(format, 3479ac4a89d35df3d581886a84df421161418707fd6tomhudson@google.com fMat[0][0], fMat[0][1], fMat[0][2], fMat[0][3], 3489ac4a89d35df3d581886a84df421161418707fd6tomhudson@google.com fMat[1][0], fMat[1][1], fMat[1][2], fMat[1][3], 3499ac4a89d35df3d581886a84df421161418707fd6tomhudson@google.com fMat[2][0], fMat[2][1], fMat[2][2], fMat[2][3], 3509ac4a89d35df3d581886a84df421161418707fd6tomhudson@google.com fMat[3][0], fMat[3][1], fMat[3][2], fMat[3][3]); 3518260a895869beaa4cab9f8b915e457728f41e561reed@google.com#endif 3528260a895869beaa4cab9f8b915e457728f41e561reed@google.com} 3538260a895869beaa4cab9f8b915e457728f41e561reed@google.com 3548260a895869beaa4cab9f8b915e457728f41e561reed@google.com/////////////////////////////////////////////////////////////////////////////// 3558260a895869beaa4cab9f8b915e457728f41e561reed@google.com 3568260a895869beaa4cab9f8b915e457728f41e561reed@google.comstatic void initFromMatrix(SkMScalar dst[4][4], const SkMatrix& src) { 3578260a895869beaa4cab9f8b915e457728f41e561reed@google.com sk_bzero(dst, 16 * sizeof(SkMScalar)); 3588260a895869beaa4cab9f8b915e457728f41e561reed@google.com dst[0][0] = src[SkMatrix::kMScaleX]; 3598260a895869beaa4cab9f8b915e457728f41e561reed@google.com dst[1][0] = src[SkMatrix::kMSkewX]; 3608260a895869beaa4cab9f8b915e457728f41e561reed@google.com dst[3][0] = src[SkMatrix::kMTransX]; 3618260a895869beaa4cab9f8b915e457728f41e561reed@google.com dst[0][1] = src[SkMatrix::kMSkewY]; 3628260a895869beaa4cab9f8b915e457728f41e561reed@google.com dst[1][1] = src[SkMatrix::kMScaleY]; 3638260a895869beaa4cab9f8b915e457728f41e561reed@google.com dst[3][1] = src[SkMatrix::kMTransY]; 3648260a895869beaa4cab9f8b915e457728f41e561reed@google.com dst[2][2] = dst[3][3] = 1; 3658260a895869beaa4cab9f8b915e457728f41e561reed@google.com} 3668260a895869beaa4cab9f8b915e457728f41e561reed@google.com 3678260a895869beaa4cab9f8b915e457728f41e561reed@google.comSkMatrix44::SkMatrix44(const SkMatrix& src) { 3688260a895869beaa4cab9f8b915e457728f41e561reed@google.com initFromMatrix(fMat, src); 3698260a895869beaa4cab9f8b915e457728f41e561reed@google.com} 3708260a895869beaa4cab9f8b915e457728f41e561reed@google.com 3718260a895869beaa4cab9f8b915e457728f41e561reed@google.comSkMatrix44& SkMatrix44::operator=(const SkMatrix& src) { 3728260a895869beaa4cab9f8b915e457728f41e561reed@google.com initFromMatrix(fMat, src); 3738260a895869beaa4cab9f8b915e457728f41e561reed@google.com return *this; 3748260a895869beaa4cab9f8b915e457728f41e561reed@google.com} 3758260a895869beaa4cab9f8b915e457728f41e561reed@google.com 3768260a895869beaa4cab9f8b915e457728f41e561reed@google.comSkMatrix44::operator SkMatrix() const { 3778260a895869beaa4cab9f8b915e457728f41e561reed@google.com SkMatrix dst; 3788260a895869beaa4cab9f8b915e457728f41e561reed@google.com dst.reset(); // setup our perspective correctly for identity 3798260a895869beaa4cab9f8b915e457728f41e561reed@google.com 3808260a895869beaa4cab9f8b915e457728f41e561reed@google.com dst[SkMatrix::kMScaleX] = SkMScalarToFloat(fMat[0][0]); 3818260a895869beaa4cab9f8b915e457728f41e561reed@google.com dst[SkMatrix::kMSkewX] = SkMScalarToFloat(fMat[1][0]); 3828260a895869beaa4cab9f8b915e457728f41e561reed@google.com dst[SkMatrix::kMTransX] = SkMScalarToFloat(fMat[3][0]); 3838260a895869beaa4cab9f8b915e457728f41e561reed@google.com 3848260a895869beaa4cab9f8b915e457728f41e561reed@google.com dst[SkMatrix::kMSkewY] = SkMScalarToFloat(fMat[0][1]); 3858260a895869beaa4cab9f8b915e457728f41e561reed@google.com dst[SkMatrix::kMScaleY] = SkMScalarToFloat(fMat[1][1]); 3868260a895869beaa4cab9f8b915e457728f41e561reed@google.com dst[SkMatrix::kMTransY] = SkMScalarToFloat(fMat[3][1]); 3878260a895869beaa4cab9f8b915e457728f41e561reed@google.com 3888260a895869beaa4cab9f8b915e457728f41e561reed@google.com return dst; 3898260a895869beaa4cab9f8b915e457728f41e561reed@google.com} 390