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