1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/utils/SkMatrix44.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,932 @@ 1.4 +/* 1.5 + * Copyright 2011 Google Inc. 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license that can be 1.8 + * found in the LICENSE file. 1.9 + */ 1.10 + 1.11 +#include "SkMatrix44.h" 1.12 + 1.13 +static inline bool eq4(const SkMScalar* SK_RESTRICT a, 1.14 + const SkMScalar* SK_RESTRICT b) { 1.15 + return (a[0] == b[0]) & (a[1] == b[1]) & (a[2] == b[2]) & (a[3] == b[3]); 1.16 +} 1.17 + 1.18 +bool SkMatrix44::operator==(const SkMatrix44& other) const { 1.19 + if (this == &other) { 1.20 + return true; 1.21 + } 1.22 + 1.23 + if (this->isTriviallyIdentity() && other.isTriviallyIdentity()) { 1.24 + return true; 1.25 + } 1.26 + 1.27 + const SkMScalar* SK_RESTRICT a = &fMat[0][0]; 1.28 + const SkMScalar* SK_RESTRICT b = &other.fMat[0][0]; 1.29 + 1.30 +#if 0 1.31 + for (int i = 0; i < 16; ++i) { 1.32 + if (a[i] != b[i]) { 1.33 + return false; 1.34 + } 1.35 + } 1.36 + return true; 1.37 +#else 1.38 + // to reduce branch instructions, we compare 4 at a time. 1.39 + // see bench/Matrix44Bench.cpp for test. 1.40 + if (!eq4(&a[0], &b[0])) { 1.41 + return false; 1.42 + } 1.43 + if (!eq4(&a[4], &b[4])) { 1.44 + return false; 1.45 + } 1.46 + if (!eq4(&a[8], &b[8])) { 1.47 + return false; 1.48 + } 1.49 + return eq4(&a[12], &b[12]); 1.50 +#endif 1.51 +} 1.52 + 1.53 +/////////////////////////////////////////////////////////////////////////////// 1.54 + 1.55 +int SkMatrix44::computeTypeMask() const { 1.56 + unsigned mask = 0; 1.57 + 1.58 + if (0 != perspX() || 0 != perspY() || 0 != perspZ() || 1 != fMat[3][3]) { 1.59 + return kTranslate_Mask | kScale_Mask | kAffine_Mask | kPerspective_Mask; 1.60 + } 1.61 + 1.62 + if (0 != transX() || 0 != transY() || 0 != transZ()) { 1.63 + mask |= kTranslate_Mask; 1.64 + } 1.65 + 1.66 + if (1 != scaleX() || 1 != scaleY() || 1 != scaleZ()) { 1.67 + mask |= kScale_Mask; 1.68 + } 1.69 + 1.70 + if (0 != fMat[1][0] || 0 != fMat[0][1] || 0 != fMat[0][2] || 1.71 + 0 != fMat[2][0] || 0 != fMat[1][2] || 0 != fMat[2][1]) { 1.72 + mask |= kAffine_Mask; 1.73 + } 1.74 + 1.75 + return mask; 1.76 +} 1.77 + 1.78 +/////////////////////////////////////////////////////////////////////////////// 1.79 + 1.80 +void SkMatrix44::asColMajorf(float dst[]) const { 1.81 + const SkMScalar* src = &fMat[0][0]; 1.82 +#ifdef SK_MSCALAR_IS_DOUBLE 1.83 + for (int i = 0; i < 16; ++i) { 1.84 + dst[i] = SkMScalarToFloat(src[i]); 1.85 + } 1.86 +#elif defined SK_MSCALAR_IS_FLOAT 1.87 + memcpy(dst, src, 16 * sizeof(float)); 1.88 +#endif 1.89 +} 1.90 + 1.91 +void SkMatrix44::asColMajord(double dst[]) const { 1.92 + const SkMScalar* src = &fMat[0][0]; 1.93 +#ifdef SK_MSCALAR_IS_DOUBLE 1.94 + memcpy(dst, src, 16 * sizeof(double)); 1.95 +#elif defined SK_MSCALAR_IS_FLOAT 1.96 + for (int i = 0; i < 16; ++i) { 1.97 + dst[i] = SkMScalarToDouble(src[i]); 1.98 + } 1.99 +#endif 1.100 +} 1.101 + 1.102 +void SkMatrix44::asRowMajorf(float dst[]) const { 1.103 + const SkMScalar* src = &fMat[0][0]; 1.104 + for (int i = 0; i < 4; ++i) { 1.105 + dst[0] = SkMScalarToFloat(src[0]); 1.106 + dst[4] = SkMScalarToFloat(src[1]); 1.107 + dst[8] = SkMScalarToFloat(src[2]); 1.108 + dst[12] = SkMScalarToFloat(src[3]); 1.109 + src += 4; 1.110 + dst += 1; 1.111 + } 1.112 +} 1.113 + 1.114 +void SkMatrix44::asRowMajord(double dst[]) const { 1.115 + const SkMScalar* src = &fMat[0][0]; 1.116 + for (int i = 0; i < 4; ++i) { 1.117 + dst[0] = SkMScalarToDouble(src[0]); 1.118 + dst[4] = SkMScalarToDouble(src[1]); 1.119 + dst[8] = SkMScalarToDouble(src[2]); 1.120 + dst[12] = SkMScalarToDouble(src[3]); 1.121 + src += 4; 1.122 + dst += 1; 1.123 + } 1.124 +} 1.125 + 1.126 +void SkMatrix44::setColMajorf(const float src[]) { 1.127 + SkMScalar* dst = &fMat[0][0]; 1.128 +#ifdef SK_MSCALAR_IS_DOUBLE 1.129 + for (int i = 0; i < 16; ++i) { 1.130 + dst[i] = SkMScalarToFloat(src[i]); 1.131 + } 1.132 +#elif defined SK_MSCALAR_IS_FLOAT 1.133 + memcpy(dst, src, 16 * sizeof(float)); 1.134 +#endif 1.135 + 1.136 + this->dirtyTypeMask(); 1.137 +} 1.138 + 1.139 +void SkMatrix44::setColMajord(const double src[]) { 1.140 + SkMScalar* dst = &fMat[0][0]; 1.141 +#ifdef SK_MSCALAR_IS_DOUBLE 1.142 + memcpy(dst, src, 16 * sizeof(double)); 1.143 +#elif defined SK_MSCALAR_IS_FLOAT 1.144 + for (int i = 0; i < 16; ++i) { 1.145 + dst[i] = SkDoubleToMScalar(src[i]); 1.146 + } 1.147 +#endif 1.148 + 1.149 + this->dirtyTypeMask(); 1.150 +} 1.151 + 1.152 +void SkMatrix44::setRowMajorf(const float src[]) { 1.153 + SkMScalar* dst = &fMat[0][0]; 1.154 + for (int i = 0; i < 4; ++i) { 1.155 + dst[0] = SkMScalarToFloat(src[0]); 1.156 + dst[4] = SkMScalarToFloat(src[1]); 1.157 + dst[8] = SkMScalarToFloat(src[2]); 1.158 + dst[12] = SkMScalarToFloat(src[3]); 1.159 + src += 4; 1.160 + dst += 1; 1.161 + } 1.162 + this->dirtyTypeMask(); 1.163 +} 1.164 + 1.165 +void SkMatrix44::setRowMajord(const double src[]) { 1.166 + SkMScalar* dst = &fMat[0][0]; 1.167 + for (int i = 0; i < 4; ++i) { 1.168 + dst[0] = SkDoubleToMScalar(src[0]); 1.169 + dst[4] = SkDoubleToMScalar(src[1]); 1.170 + dst[8] = SkDoubleToMScalar(src[2]); 1.171 + dst[12] = SkDoubleToMScalar(src[3]); 1.172 + src += 4; 1.173 + dst += 1; 1.174 + } 1.175 + this->dirtyTypeMask(); 1.176 +} 1.177 + 1.178 +/////////////////////////////////////////////////////////////////////////////// 1.179 + 1.180 +const SkMatrix44& SkMatrix44::I() { 1.181 + static const SkMatrix44 gIdentity44(kIdentity_Constructor); 1.182 + return gIdentity44; 1.183 +} 1.184 + 1.185 +void SkMatrix44::setIdentity() { 1.186 + fMat[0][0] = 1; 1.187 + fMat[0][1] = 0; 1.188 + fMat[0][2] = 0; 1.189 + fMat[0][3] = 0; 1.190 + fMat[1][0] = 0; 1.191 + fMat[1][1] = 1; 1.192 + fMat[1][2] = 0; 1.193 + fMat[1][3] = 0; 1.194 + fMat[2][0] = 0; 1.195 + fMat[2][1] = 0; 1.196 + fMat[2][2] = 1; 1.197 + fMat[2][3] = 0; 1.198 + fMat[3][0] = 0; 1.199 + fMat[3][1] = 0; 1.200 + fMat[3][2] = 0; 1.201 + fMat[3][3] = 1; 1.202 + this->setTypeMask(kIdentity_Mask); 1.203 +} 1.204 + 1.205 +void SkMatrix44::set3x3(SkMScalar m00, SkMScalar m01, SkMScalar m02, 1.206 + SkMScalar m10, SkMScalar m11, SkMScalar m12, 1.207 + SkMScalar m20, SkMScalar m21, SkMScalar m22) { 1.208 + fMat[0][0] = m00; fMat[0][1] = m01; fMat[0][2] = m02; fMat[0][3] = 0; 1.209 + fMat[1][0] = m10; fMat[1][1] = m11; fMat[1][2] = m12; fMat[1][3] = 0; 1.210 + fMat[2][0] = m20; fMat[2][1] = m21; fMat[2][2] = m22; fMat[2][3] = 0; 1.211 + fMat[3][0] = 0; fMat[3][1] = 0; fMat[3][2] = 0; fMat[3][3] = 1; 1.212 + this->dirtyTypeMask(); 1.213 +} 1.214 + 1.215 +/////////////////////////////////////////////////////////////////////////////// 1.216 + 1.217 +void SkMatrix44::setTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz) { 1.218 + this->setIdentity(); 1.219 + 1.220 + if (!dx && !dy && !dz) { 1.221 + return; 1.222 + } 1.223 + 1.224 + fMat[3][0] = dx; 1.225 + fMat[3][1] = dy; 1.226 + fMat[3][2] = dz; 1.227 + this->setTypeMask(kTranslate_Mask); 1.228 +} 1.229 + 1.230 +void SkMatrix44::preTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz) { 1.231 + if (!dx && !dy && !dz) { 1.232 + return; 1.233 + } 1.234 + 1.235 + for (int i = 0; i < 4; ++i) { 1.236 + fMat[3][i] = fMat[0][i] * dx + fMat[1][i] * dy + fMat[2][i] * dz + fMat[3][i]; 1.237 + } 1.238 + this->dirtyTypeMask(); 1.239 +} 1.240 + 1.241 +void SkMatrix44::postTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz) { 1.242 + if (!dx && !dy && !dz) { 1.243 + return; 1.244 + } 1.245 + 1.246 + if (this->getType() & kPerspective_Mask) { 1.247 + for (int i = 0; i < 4; ++i) { 1.248 + fMat[i][0] += fMat[i][3] * dx; 1.249 + fMat[i][1] += fMat[i][3] * dy; 1.250 + fMat[i][2] += fMat[i][3] * dz; 1.251 + } 1.252 + } else { 1.253 + fMat[3][0] += dx; 1.254 + fMat[3][1] += dy; 1.255 + fMat[3][2] += dz; 1.256 + this->dirtyTypeMask(); 1.257 + } 1.258 +} 1.259 + 1.260 +/////////////////////////////////////////////////////////////////////////////// 1.261 + 1.262 +void SkMatrix44::setScale(SkMScalar sx, SkMScalar sy, SkMScalar sz) { 1.263 + this->setIdentity(); 1.264 + 1.265 + if (1 == sx && 1 == sy && 1 == sz) { 1.266 + return; 1.267 + } 1.268 + 1.269 + fMat[0][0] = sx; 1.270 + fMat[1][1] = sy; 1.271 + fMat[2][2] = sz; 1.272 + this->setTypeMask(kScale_Mask); 1.273 +} 1.274 + 1.275 +void SkMatrix44::preScale(SkMScalar sx, SkMScalar sy, SkMScalar sz) { 1.276 + if (1 == sx && 1 == sy && 1 == sz) { 1.277 + return; 1.278 + } 1.279 + 1.280 + // The implementation matrix * pureScale can be shortcut 1.281 + // by knowing that pureScale components effectively scale 1.282 + // the columns of the original matrix. 1.283 + for (int i = 0; i < 4; i++) { 1.284 + fMat[0][i] *= sx; 1.285 + fMat[1][i] *= sy; 1.286 + fMat[2][i] *= sz; 1.287 + } 1.288 + this->dirtyTypeMask(); 1.289 +} 1.290 + 1.291 +void SkMatrix44::postScale(SkMScalar sx, SkMScalar sy, SkMScalar sz) { 1.292 + if (1 == sx && 1 == sy && 1 == sz) { 1.293 + return; 1.294 + } 1.295 + 1.296 + for (int i = 0; i < 4; i++) { 1.297 + fMat[i][0] *= sx; 1.298 + fMat[i][1] *= sy; 1.299 + fMat[i][2] *= sz; 1.300 + } 1.301 + this->dirtyTypeMask(); 1.302 +} 1.303 + 1.304 +/////////////////////////////////////////////////////////////////////////////// 1.305 + 1.306 +void SkMatrix44::setRotateAbout(SkMScalar x, SkMScalar y, SkMScalar z, 1.307 + SkMScalar radians) { 1.308 + double len2 = (double)x * x + (double)y * y + (double)z * z; 1.309 + if (1 != len2) { 1.310 + if (0 == len2) { 1.311 + this->setIdentity(); 1.312 + return; 1.313 + } 1.314 + double scale = 1 / sqrt(len2); 1.315 + x = SkDoubleToMScalar(x * scale); 1.316 + y = SkDoubleToMScalar(y * scale); 1.317 + z = SkDoubleToMScalar(z * scale); 1.318 + } 1.319 + this->setRotateAboutUnit(x, y, z, radians); 1.320 +} 1.321 + 1.322 +void SkMatrix44::setRotateAboutUnit(SkMScalar x, SkMScalar y, SkMScalar z, 1.323 + SkMScalar radians) { 1.324 + double c = cos(radians); 1.325 + double s = sin(radians); 1.326 + double C = 1 - c; 1.327 + double xs = x * s; 1.328 + double ys = y * s; 1.329 + double zs = z * s; 1.330 + double xC = x * C; 1.331 + double yC = y * C; 1.332 + double zC = z * C; 1.333 + double xyC = x * yC; 1.334 + double yzC = y * zC; 1.335 + double zxC = z * xC; 1.336 + 1.337 + // if you're looking at wikipedia, remember that we're column major. 1.338 + this->set3x3(SkDoubleToMScalar(x * xC + c), // scale x 1.339 + SkDoubleToMScalar(xyC + zs), // skew x 1.340 + SkDoubleToMScalar(zxC - ys), // trans x 1.341 + 1.342 + SkDoubleToMScalar(xyC - zs), // skew y 1.343 + SkDoubleToMScalar(y * yC + c), // scale y 1.344 + SkDoubleToMScalar(yzC + xs), // trans y 1.345 + 1.346 + SkDoubleToMScalar(zxC + ys), // persp x 1.347 + SkDoubleToMScalar(yzC - xs), // persp y 1.348 + SkDoubleToMScalar(z * zC + c)); // persp 2 1.349 +} 1.350 + 1.351 +/////////////////////////////////////////////////////////////////////////////// 1.352 + 1.353 +static bool bits_isonly(int value, int mask) { 1.354 + return 0 == (value & ~mask); 1.355 +} 1.356 + 1.357 +void SkMatrix44::setConcat(const SkMatrix44& a, const SkMatrix44& b) { 1.358 + const SkMatrix44::TypeMask a_mask = a.getType(); 1.359 + const SkMatrix44::TypeMask b_mask = b.getType(); 1.360 + 1.361 + if (kIdentity_Mask == a_mask) { 1.362 + *this = b; 1.363 + return; 1.364 + } 1.365 + if (kIdentity_Mask == b_mask) { 1.366 + *this = a; 1.367 + return; 1.368 + } 1.369 + 1.370 + bool useStorage = (this == &a || this == &b); 1.371 + SkMScalar storage[16]; 1.372 + SkMScalar* result = useStorage ? storage : &fMat[0][0]; 1.373 + 1.374 + // Both matrices are at most scale+translate 1.375 + if (bits_isonly(a_mask | b_mask, kScale_Mask | kTranslate_Mask)) { 1.376 + result[0] = a.fMat[0][0] * b.fMat[0][0]; 1.377 + result[1] = result[2] = result[3] = result[4] = 0; 1.378 + result[5] = a.fMat[1][1] * b.fMat[1][1]; 1.379 + result[6] = result[7] = result[8] = result[9] = 0; 1.380 + result[10] = a.fMat[2][2] * b.fMat[2][2]; 1.381 + result[11] = 0; 1.382 + result[12] = a.fMat[0][0] * b.fMat[3][0] + a.fMat[3][0]; 1.383 + result[13] = a.fMat[1][1] * b.fMat[3][1] + a.fMat[3][1]; 1.384 + result[14] = a.fMat[2][2] * b.fMat[3][2] + a.fMat[3][2]; 1.385 + result[15] = 1; 1.386 + } else { 1.387 + for (int j = 0; j < 4; j++) { 1.388 + for (int i = 0; i < 4; i++) { 1.389 + double value = 0; 1.390 + for (int k = 0; k < 4; k++) { 1.391 + value += SkMScalarToDouble(a.fMat[k][i]) * b.fMat[j][k]; 1.392 + } 1.393 + *result++ = SkDoubleToMScalar(value); 1.394 + } 1.395 + } 1.396 + } 1.397 + 1.398 + if (useStorage) { 1.399 + memcpy(fMat, storage, sizeof(storage)); 1.400 + } 1.401 + this->dirtyTypeMask(); 1.402 +} 1.403 + 1.404 +/////////////////////////////////////////////////////////////////////////////// 1.405 + 1.406 +/** We always perform the calculation in doubles, to avoid prematurely losing 1.407 + precision along the way. This relies on the compiler automatically 1.408 + promoting our SkMScalar values to double (if needed). 1.409 + */ 1.410 +double SkMatrix44::determinant() const { 1.411 + if (this->isIdentity()) { 1.412 + return 1; 1.413 + } 1.414 + if (this->isScaleTranslate()) { 1.415 + return fMat[0][0] * fMat[1][1] * fMat[2][2] * fMat[3][3]; 1.416 + } 1.417 + 1.418 + double a00 = fMat[0][0]; 1.419 + double a01 = fMat[0][1]; 1.420 + double a02 = fMat[0][2]; 1.421 + double a03 = fMat[0][3]; 1.422 + double a10 = fMat[1][0]; 1.423 + double a11 = fMat[1][1]; 1.424 + double a12 = fMat[1][2]; 1.425 + double a13 = fMat[1][3]; 1.426 + double a20 = fMat[2][0]; 1.427 + double a21 = fMat[2][1]; 1.428 + double a22 = fMat[2][2]; 1.429 + double a23 = fMat[2][3]; 1.430 + double a30 = fMat[3][0]; 1.431 + double a31 = fMat[3][1]; 1.432 + double a32 = fMat[3][2]; 1.433 + double a33 = fMat[3][3]; 1.434 + 1.435 + double b00 = a00 * a11 - a01 * a10; 1.436 + double b01 = a00 * a12 - a02 * a10; 1.437 + double b02 = a00 * a13 - a03 * a10; 1.438 + double b03 = a01 * a12 - a02 * a11; 1.439 + double b04 = a01 * a13 - a03 * a11; 1.440 + double b05 = a02 * a13 - a03 * a12; 1.441 + double b06 = a20 * a31 - a21 * a30; 1.442 + double b07 = a20 * a32 - a22 * a30; 1.443 + double b08 = a20 * a33 - a23 * a30; 1.444 + double b09 = a21 * a32 - a22 * a31; 1.445 + double b10 = a21 * a33 - a23 * a31; 1.446 + double b11 = a22 * a33 - a23 * a32; 1.447 + 1.448 + // Calculate the determinant 1.449 + return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; 1.450 +} 1.451 + 1.452 +/////////////////////////////////////////////////////////////////////////////// 1.453 + 1.454 +bool SkMatrix44::invert(SkMatrix44* inverse) const { 1.455 + if (this->isIdentity()) { 1.456 + if (inverse) { 1.457 + inverse->setIdentity(); 1.458 + } 1.459 + return true; 1.460 + } 1.461 + 1.462 + if (this->isTranslate()) { 1.463 + if (inverse) { 1.464 + inverse->setTranslate(-fMat[3][0], -fMat[3][1], -fMat[3][2]); 1.465 + } 1.466 + return true; 1.467 + } 1.468 + 1.469 + if (this->isScaleTranslate()) { 1.470 + if (0 == fMat[0][0] * fMat[1][1] * fMat[2][2]) { 1.471 + return false; 1.472 + } 1.473 + 1.474 + if (inverse) { 1.475 + double invXScale = 1 / fMat[0][0]; 1.476 + double invYScale = 1 / fMat[1][1]; 1.477 + double invZScale = 1 / fMat[2][2]; 1.478 + 1.479 + inverse->fMat[0][0] = invXScale; 1.480 + inverse->fMat[0][1] = 0; 1.481 + inverse->fMat[0][2] = 0; 1.482 + inverse->fMat[0][3] = 0; 1.483 + 1.484 + inverse->fMat[1][0] = 0; 1.485 + inverse->fMat[1][1] = invYScale; 1.486 + inverse->fMat[1][2] = 0; 1.487 + inverse->fMat[1][3] = 0; 1.488 + 1.489 + inverse->fMat[2][0] = 0; 1.490 + inverse->fMat[2][1] = 0; 1.491 + inverse->fMat[2][2] = invZScale; 1.492 + inverse->fMat[2][3] = 0; 1.493 + 1.494 + inverse->fMat[3][0] = -fMat[3][0] * invXScale; 1.495 + inverse->fMat[3][1] = -fMat[3][1] * invYScale; 1.496 + inverse->fMat[3][2] = -fMat[3][2] * invZScale; 1.497 + inverse->fMat[3][3] = 1; 1.498 + 1.499 + inverse->setTypeMask(this->getType()); 1.500 + } 1.501 + 1.502 + return true; 1.503 + } 1.504 + 1.505 + double a00 = fMat[0][0]; 1.506 + double a01 = fMat[0][1]; 1.507 + double a02 = fMat[0][2]; 1.508 + double a03 = fMat[0][3]; 1.509 + double a10 = fMat[1][0]; 1.510 + double a11 = fMat[1][1]; 1.511 + double a12 = fMat[1][2]; 1.512 + double a13 = fMat[1][3]; 1.513 + double a20 = fMat[2][0]; 1.514 + double a21 = fMat[2][1]; 1.515 + double a22 = fMat[2][2]; 1.516 + double a23 = fMat[2][3]; 1.517 + double a30 = fMat[3][0]; 1.518 + double a31 = fMat[3][1]; 1.519 + double a32 = fMat[3][2]; 1.520 + double a33 = fMat[3][3]; 1.521 + 1.522 + if (!(this->getType() & kPerspective_Mask)) { 1.523 + // If we know the matrix has no perspective, then the perspective 1.524 + // component is (0, 0, 0, 1). We can use this information to save a lot 1.525 + // of arithmetic that would otherwise be spent to compute the inverse 1.526 + // of a general matrix. 1.527 + 1.528 + SkASSERT(a03 == 0); 1.529 + SkASSERT(a13 == 0); 1.530 + SkASSERT(a23 == 0); 1.531 + SkASSERT(a33 == 1); 1.532 + 1.533 + double b00 = a00 * a11 - a01 * a10; 1.534 + double b01 = a00 * a12 - a02 * a10; 1.535 + double b03 = a01 * a12 - a02 * a11; 1.536 + double b06 = a20 * a31 - a21 * a30; 1.537 + double b07 = a20 * a32 - a22 * a30; 1.538 + double b08 = a20; 1.539 + double b09 = a21 * a32 - a22 * a31; 1.540 + double b10 = a21; 1.541 + double b11 = a22; 1.542 + 1.543 + // Calculate the determinant 1.544 + double det = b00 * b11 - b01 * b10 + b03 * b08; 1.545 + 1.546 + double invdet = 1.0 / det; 1.547 + // If det is zero, we want to return false. However, we also want to return false 1.548 + // if 1/det overflows to infinity (i.e. det is denormalized). Both of these are 1.549 + // handled by checking that 1/det is finite. 1.550 + if (!sk_float_isfinite(invdet)) { 1.551 + return false; 1.552 + } 1.553 + if (NULL == inverse) { 1.554 + return true; 1.555 + } 1.556 + 1.557 + b00 *= invdet; 1.558 + b01 *= invdet; 1.559 + b03 *= invdet; 1.560 + b06 *= invdet; 1.561 + b07 *= invdet; 1.562 + b08 *= invdet; 1.563 + b09 *= invdet; 1.564 + b10 *= invdet; 1.565 + b11 *= invdet; 1.566 + 1.567 + inverse->fMat[0][0] = SkDoubleToMScalar(a11 * b11 - a12 * b10); 1.568 + inverse->fMat[0][1] = SkDoubleToMScalar(a02 * b10 - a01 * b11); 1.569 + inverse->fMat[0][2] = SkDoubleToMScalar(b03); 1.570 + inverse->fMat[0][3] = 0; 1.571 + inverse->fMat[1][0] = SkDoubleToMScalar(a12 * b08 - a10 * b11); 1.572 + inverse->fMat[1][1] = SkDoubleToMScalar(a00 * b11 - a02 * b08); 1.573 + inverse->fMat[1][2] = SkDoubleToMScalar(-b01); 1.574 + inverse->fMat[1][3] = 0; 1.575 + inverse->fMat[2][0] = SkDoubleToMScalar(a10 * b10 - a11 * b08); 1.576 + inverse->fMat[2][1] = SkDoubleToMScalar(a01 * b08 - a00 * b10); 1.577 + inverse->fMat[2][2] = SkDoubleToMScalar(b00); 1.578 + inverse->fMat[2][3] = 0; 1.579 + inverse->fMat[3][0] = SkDoubleToMScalar(a11 * b07 - a10 * b09 - a12 * b06); 1.580 + inverse->fMat[3][1] = SkDoubleToMScalar(a00 * b09 - a01 * b07 + a02 * b06); 1.581 + inverse->fMat[3][2] = SkDoubleToMScalar(a31 * b01 - a30 * b03 - a32 * b00); 1.582 + inverse->fMat[3][3] = 1; 1.583 + 1.584 + inverse->setTypeMask(this->getType()); 1.585 + return true; 1.586 + } 1.587 + 1.588 + double b00 = a00 * a11 - a01 * a10; 1.589 + double b01 = a00 * a12 - a02 * a10; 1.590 + double b02 = a00 * a13 - a03 * a10; 1.591 + double b03 = a01 * a12 - a02 * a11; 1.592 + double b04 = a01 * a13 - a03 * a11; 1.593 + double b05 = a02 * a13 - a03 * a12; 1.594 + double b06 = a20 * a31 - a21 * a30; 1.595 + double b07 = a20 * a32 - a22 * a30; 1.596 + double b08 = a20 * a33 - a23 * a30; 1.597 + double b09 = a21 * a32 - a22 * a31; 1.598 + double b10 = a21 * a33 - a23 * a31; 1.599 + double b11 = a22 * a33 - a23 * a32; 1.600 + 1.601 + // Calculate the determinant 1.602 + double det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; 1.603 + 1.604 + double invdet = 1.0 / det; 1.605 + // If det is zero, we want to return false. However, we also want to return false 1.606 + // if 1/det overflows to infinity (i.e. det is denormalized). Both of these are 1.607 + // handled by checking that 1/det is finite. 1.608 + if (!sk_float_isfinite(invdet)) { 1.609 + return false; 1.610 + } 1.611 + if (NULL == inverse) { 1.612 + return true; 1.613 + } 1.614 + 1.615 + b00 *= invdet; 1.616 + b01 *= invdet; 1.617 + b02 *= invdet; 1.618 + b03 *= invdet; 1.619 + b04 *= invdet; 1.620 + b05 *= invdet; 1.621 + b06 *= invdet; 1.622 + b07 *= invdet; 1.623 + b08 *= invdet; 1.624 + b09 *= invdet; 1.625 + b10 *= invdet; 1.626 + b11 *= invdet; 1.627 + 1.628 + inverse->fMat[0][0] = SkDoubleToMScalar(a11 * b11 - a12 * b10 + a13 * b09); 1.629 + inverse->fMat[0][1] = SkDoubleToMScalar(a02 * b10 - a01 * b11 - a03 * b09); 1.630 + inverse->fMat[0][2] = SkDoubleToMScalar(a31 * b05 - a32 * b04 + a33 * b03); 1.631 + inverse->fMat[0][3] = SkDoubleToMScalar(a22 * b04 - a21 * b05 - a23 * b03); 1.632 + inverse->fMat[1][0] = SkDoubleToMScalar(a12 * b08 - a10 * b11 - a13 * b07); 1.633 + inverse->fMat[1][1] = SkDoubleToMScalar(a00 * b11 - a02 * b08 + a03 * b07); 1.634 + inverse->fMat[1][2] = SkDoubleToMScalar(a32 * b02 - a30 * b05 - a33 * b01); 1.635 + inverse->fMat[1][3] = SkDoubleToMScalar(a20 * b05 - a22 * b02 + a23 * b01); 1.636 + inverse->fMat[2][0] = SkDoubleToMScalar(a10 * b10 - a11 * b08 + a13 * b06); 1.637 + inverse->fMat[2][1] = SkDoubleToMScalar(a01 * b08 - a00 * b10 - a03 * b06); 1.638 + inverse->fMat[2][2] = SkDoubleToMScalar(a30 * b04 - a31 * b02 + a33 * b00); 1.639 + inverse->fMat[2][3] = SkDoubleToMScalar(a21 * b02 - a20 * b04 - a23 * b00); 1.640 + inverse->fMat[3][0] = SkDoubleToMScalar(a11 * b07 - a10 * b09 - a12 * b06); 1.641 + inverse->fMat[3][1] = SkDoubleToMScalar(a00 * b09 - a01 * b07 + a02 * b06); 1.642 + inverse->fMat[3][2] = SkDoubleToMScalar(a31 * b01 - a30 * b03 - a32 * b00); 1.643 + inverse->fMat[3][3] = SkDoubleToMScalar(a20 * b03 - a21 * b01 + a22 * b00); 1.644 + inverse->dirtyTypeMask(); 1.645 + 1.646 + return true; 1.647 +} 1.648 + 1.649 +/////////////////////////////////////////////////////////////////////////////// 1.650 + 1.651 +void SkMatrix44::transpose() { 1.652 + SkTSwap(fMat[0][1], fMat[1][0]); 1.653 + SkTSwap(fMat[0][2], fMat[2][0]); 1.654 + SkTSwap(fMat[0][3], fMat[3][0]); 1.655 + SkTSwap(fMat[1][2], fMat[2][1]); 1.656 + SkTSwap(fMat[1][3], fMat[3][1]); 1.657 + SkTSwap(fMat[2][3], fMat[3][2]); 1.658 + 1.659 + if (!this->isTriviallyIdentity()) { 1.660 + this->dirtyTypeMask(); 1.661 + } 1.662 +} 1.663 + 1.664 +/////////////////////////////////////////////////////////////////////////////// 1.665 + 1.666 +void SkMatrix44::mapScalars(const SkScalar src[4], SkScalar dst[4]) const { 1.667 + SkScalar storage[4]; 1.668 + SkScalar* result = (src == dst) ? storage : dst; 1.669 + 1.670 + for (int i = 0; i < 4; i++) { 1.671 + SkMScalar value = 0; 1.672 + for (int j = 0; j < 4; j++) { 1.673 + value += fMat[j][i] * src[j]; 1.674 + } 1.675 + result[i] = SkMScalarToScalar(value); 1.676 + } 1.677 + 1.678 + if (storage == result) { 1.679 + memcpy(dst, storage, sizeof(storage)); 1.680 + } 1.681 +} 1.682 + 1.683 +#ifdef SK_MSCALAR_IS_DOUBLE 1.684 + 1.685 +void SkMatrix44::mapMScalars(const SkMScalar src[4], SkMScalar dst[4]) const { 1.686 + SkMScalar storage[4]; 1.687 + SkMScalar* result = (src == dst) ? storage : dst; 1.688 + 1.689 + for (int i = 0; i < 4; i++) { 1.690 + SkMScalar value = 0; 1.691 + for (int j = 0; j < 4; j++) { 1.692 + value += fMat[j][i] * src[j]; 1.693 + } 1.694 + result[i] = value; 1.695 + } 1.696 + 1.697 + if (storage == result) { 1.698 + memcpy(dst, storage, sizeof(storage)); 1.699 + } 1.700 +} 1.701 + 1.702 +#endif 1.703 + 1.704 +typedef void (*Map2Procf)(const SkMScalar mat[][4], const float src2[], int count, float dst4[]); 1.705 +typedef void (*Map2Procd)(const SkMScalar mat[][4], const double src2[], int count, double dst4[]); 1.706 + 1.707 +static void map2_if(const SkMScalar mat[][4], const float* SK_RESTRICT src2, 1.708 + int count, float* SK_RESTRICT dst4) { 1.709 + for (int i = 0; i < count; ++i) { 1.710 + dst4[0] = src2[0]; 1.711 + dst4[1] = src2[1]; 1.712 + dst4[2] = 0; 1.713 + dst4[3] = 1; 1.714 + src2 += 2; 1.715 + dst4 += 4; 1.716 + } 1.717 +} 1.718 + 1.719 +static void map2_id(const SkMScalar mat[][4], const double* SK_RESTRICT src2, 1.720 + int count, double* SK_RESTRICT dst4) { 1.721 + for (int i = 0; i < count; ++i) { 1.722 + dst4[0] = src2[0]; 1.723 + dst4[1] = src2[1]; 1.724 + dst4[2] = 0; 1.725 + dst4[3] = 1; 1.726 + src2 += 2; 1.727 + dst4 += 4; 1.728 + } 1.729 +} 1.730 + 1.731 +static void map2_tf(const SkMScalar mat[][4], const float* SK_RESTRICT src2, 1.732 + int count, float* SK_RESTRICT dst4) { 1.733 + const float mat30 = SkMScalarToFloat(mat[3][0]); 1.734 + const float mat31 = SkMScalarToFloat(mat[3][1]); 1.735 + const float mat32 = SkMScalarToFloat(mat[3][2]); 1.736 + for (int n = 0; n < count; ++n) { 1.737 + dst4[0] = src2[0] + mat30; 1.738 + dst4[1] = src2[1] + mat31; 1.739 + dst4[2] = mat32; 1.740 + dst4[3] = 1; 1.741 + src2 += 2; 1.742 + dst4 += 4; 1.743 + } 1.744 +} 1.745 + 1.746 +static void map2_td(const SkMScalar mat[][4], const double* SK_RESTRICT src2, 1.747 + int count, double* SK_RESTRICT dst4) { 1.748 + for (int n = 0; n < count; ++n) { 1.749 + dst4[0] = src2[0] + mat[3][0]; 1.750 + dst4[1] = src2[1] + mat[3][1]; 1.751 + dst4[2] = mat[3][2]; 1.752 + dst4[3] = 1; 1.753 + src2 += 2; 1.754 + dst4 += 4; 1.755 + } 1.756 +} 1.757 + 1.758 +static void map2_sf(const SkMScalar mat[][4], const float* SK_RESTRICT src2, 1.759 + int count, float* SK_RESTRICT dst4) { 1.760 + const float mat32 = SkMScalarToFloat(mat[3][2]); 1.761 + for (int n = 0; n < count; ++n) { 1.762 + dst4[0] = SkMScalarToFloat(mat[0][0] * src2[0] + mat[3][0]); 1.763 + dst4[1] = SkMScalarToFloat(mat[1][1] * src2[1] + mat[3][1]); 1.764 + dst4[2] = mat32; 1.765 + dst4[3] = 1; 1.766 + src2 += 2; 1.767 + dst4 += 4; 1.768 + } 1.769 +} 1.770 + 1.771 +static void map2_sd(const SkMScalar mat[][4], const double* SK_RESTRICT src2, 1.772 + int count, double* SK_RESTRICT dst4) { 1.773 + for (int n = 0; n < count; ++n) { 1.774 + dst4[0] = mat[0][0] * src2[0] + mat[3][0]; 1.775 + dst4[1] = mat[1][1] * src2[1] + mat[3][1]; 1.776 + dst4[2] = mat[3][2]; 1.777 + dst4[3] = 1; 1.778 + src2 += 2; 1.779 + dst4 += 4; 1.780 + } 1.781 +} 1.782 + 1.783 +static void map2_af(const SkMScalar mat[][4], const float* SK_RESTRICT src2, 1.784 + int count, float* SK_RESTRICT dst4) { 1.785 + SkMScalar r; 1.786 + for (int n = 0; n < count; ++n) { 1.787 + SkMScalar sx = SkFloatToMScalar(src2[0]); 1.788 + SkMScalar sy = SkFloatToMScalar(src2[1]); 1.789 + r = mat[0][0] * sx + mat[1][0] * sy + mat[3][0]; 1.790 + dst4[0] = SkMScalarToFloat(r); 1.791 + r = mat[0][1] * sx + mat[1][1] * sy + mat[3][1]; 1.792 + dst4[1] = SkMScalarToFloat(r); 1.793 + r = mat[0][2] * sx + mat[1][2] * sy + mat[3][2]; 1.794 + dst4[2] = SkMScalarToFloat(r); 1.795 + dst4[3] = 1; 1.796 + src2 += 2; 1.797 + dst4 += 4; 1.798 + } 1.799 +} 1.800 + 1.801 +static void map2_ad(const SkMScalar mat[][4], const double* SK_RESTRICT src2, 1.802 + int count, double* SK_RESTRICT dst4) { 1.803 + for (int n = 0; n < count; ++n) { 1.804 + double sx = src2[0]; 1.805 + double sy = src2[1]; 1.806 + dst4[0] = mat[0][0] * sx + mat[1][0] * sy + mat[3][0]; 1.807 + dst4[1] = mat[0][1] * sx + mat[1][1] * sy + mat[3][1]; 1.808 + dst4[2] = mat[0][2] * sx + mat[1][2] * sy + mat[3][2]; 1.809 + dst4[3] = 1; 1.810 + src2 += 2; 1.811 + dst4 += 4; 1.812 + } 1.813 +} 1.814 + 1.815 +static void map2_pf(const SkMScalar mat[][4], const float* SK_RESTRICT src2, 1.816 + int count, float* SK_RESTRICT dst4) { 1.817 + SkMScalar r; 1.818 + for (int n = 0; n < count; ++n) { 1.819 + SkMScalar sx = SkFloatToMScalar(src2[0]); 1.820 + SkMScalar sy = SkFloatToMScalar(src2[1]); 1.821 + for (int i = 0; i < 4; i++) { 1.822 + r = mat[0][i] * sx + mat[1][i] * sy + mat[3][i]; 1.823 + dst4[i] = SkMScalarToFloat(r); 1.824 + } 1.825 + src2 += 2; 1.826 + dst4 += 4; 1.827 + } 1.828 +} 1.829 + 1.830 +static void map2_pd(const SkMScalar mat[][4], const double* SK_RESTRICT src2, 1.831 + int count, double* SK_RESTRICT dst4) { 1.832 + for (int n = 0; n < count; ++n) { 1.833 + double sx = src2[0]; 1.834 + double sy = src2[1]; 1.835 + for (int i = 0; i < 4; i++) { 1.836 + dst4[i] = mat[0][i] * sx + mat[1][i] * sy + mat[3][i]; 1.837 + } 1.838 + src2 += 2; 1.839 + dst4 += 4; 1.840 + } 1.841 +} 1.842 + 1.843 +void SkMatrix44::map2(const float src2[], int count, float dst4[]) const { 1.844 + static const Map2Procf gProc[] = { 1.845 + map2_if, map2_tf, map2_sf, map2_sf, map2_af, map2_af, map2_af, map2_af 1.846 + }; 1.847 + 1.848 + TypeMask mask = this->getType(); 1.849 + Map2Procf proc = (mask & kPerspective_Mask) ? map2_pf : gProc[mask]; 1.850 + proc(fMat, src2, count, dst4); 1.851 +} 1.852 + 1.853 +void SkMatrix44::map2(const double src2[], int count, double dst4[]) const { 1.854 + static const Map2Procd gProc[] = { 1.855 + map2_id, map2_td, map2_sd, map2_sd, map2_ad, map2_ad, map2_ad, map2_ad 1.856 + }; 1.857 + 1.858 + TypeMask mask = this->getType(); 1.859 + Map2Procd proc = (mask & kPerspective_Mask) ? map2_pd : gProc[mask]; 1.860 + proc(fMat, src2, count, dst4); 1.861 +} 1.862 + 1.863 +/////////////////////////////////////////////////////////////////////////////// 1.864 + 1.865 +void SkMatrix44::dump() const { 1.866 + static const char* format = 1.867 + "[%g %g %g %g][%g %g %g %g][%g %g %g %g][%g %g %g %g]\n"; 1.868 +#if 0 1.869 + SkDebugf(format, 1.870 + fMat[0][0], fMat[1][0], fMat[2][0], fMat[3][0], 1.871 + fMat[0][1], fMat[1][1], fMat[2][1], fMat[3][1], 1.872 + fMat[0][2], fMat[1][2], fMat[2][2], fMat[3][2], 1.873 + fMat[0][3], fMat[1][3], fMat[2][3], fMat[3][3]); 1.874 +#else 1.875 + SkDebugf(format, 1.876 + fMat[0][0], fMat[0][1], fMat[0][2], fMat[0][3], 1.877 + fMat[1][0], fMat[1][1], fMat[1][2], fMat[1][3], 1.878 + fMat[2][0], fMat[2][1], fMat[2][2], fMat[2][3], 1.879 + fMat[3][0], fMat[3][1], fMat[3][2], fMat[3][3]); 1.880 +#endif 1.881 +} 1.882 + 1.883 +/////////////////////////////////////////////////////////////////////////////// 1.884 + 1.885 +static void initFromMatrix(SkMScalar dst[4][4], const SkMatrix& src) { 1.886 + dst[0][0] = SkScalarToMScalar(src[SkMatrix::kMScaleX]); 1.887 + dst[1][0] = SkScalarToMScalar(src[SkMatrix::kMSkewX]); 1.888 + dst[2][0] = 0; 1.889 + dst[3][0] = SkScalarToMScalar(src[SkMatrix::kMTransX]); 1.890 + dst[0][1] = SkScalarToMScalar(src[SkMatrix::kMSkewY]); 1.891 + dst[1][1] = SkScalarToMScalar(src[SkMatrix::kMScaleY]); 1.892 + dst[2][1] = 0; 1.893 + dst[3][1] = SkScalarToMScalar(src[SkMatrix::kMTransY]); 1.894 + dst[0][2] = 0; 1.895 + dst[1][2] = 0; 1.896 + dst[2][2] = 1; 1.897 + dst[3][2] = 0; 1.898 + dst[0][3] = SkScalarToMScalar(src[SkMatrix::kMPersp0]); 1.899 + dst[1][3] = SkScalarToMScalar(src[SkMatrix::kMPersp1]); 1.900 + dst[2][3] = 0; 1.901 + dst[3][3] = SkScalarToMScalar(src[SkMatrix::kMPersp2]); 1.902 +} 1.903 + 1.904 +SkMatrix44::SkMatrix44(const SkMatrix& src) { 1.905 + initFromMatrix(fMat, src); 1.906 +} 1.907 + 1.908 +SkMatrix44& SkMatrix44::operator=(const SkMatrix& src) { 1.909 + initFromMatrix(fMat, src); 1.910 + 1.911 + if (src.isIdentity()) { 1.912 + this->setTypeMask(kIdentity_Mask); 1.913 + } else { 1.914 + this->dirtyTypeMask(); 1.915 + } 1.916 + return *this; 1.917 +} 1.918 + 1.919 +SkMatrix44::operator SkMatrix() const { 1.920 + SkMatrix dst; 1.921 + 1.922 + dst[SkMatrix::kMScaleX] = SkMScalarToScalar(fMat[0][0]); 1.923 + dst[SkMatrix::kMSkewX] = SkMScalarToScalar(fMat[1][0]); 1.924 + dst[SkMatrix::kMTransX] = SkMScalarToScalar(fMat[3][0]); 1.925 + 1.926 + dst[SkMatrix::kMSkewY] = SkMScalarToScalar(fMat[0][1]); 1.927 + dst[SkMatrix::kMScaleY] = SkMScalarToScalar(fMat[1][1]); 1.928 + dst[SkMatrix::kMTransY] = SkMScalarToScalar(fMat[3][1]); 1.929 + 1.930 + dst[SkMatrix::kMPersp0] = SkMScalarToScalar(fMat[0][3]); 1.931 + dst[SkMatrix::kMPersp1] = SkMScalarToScalar(fMat[1][3]); 1.932 + dst[SkMatrix::kMPersp2] = SkMScalarToScalar(fMat[3][3]); 1.933 + 1.934 + return dst; 1.935 +}