SkMatrix44.cpp revision c1a3e24918f99fc0b975111afb39dca38c50eb5c
1/* 2 * Copyright 2011 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "SkMatrix44.h" 9 10static inline bool eq4(const SkMScalar* SK_RESTRICT a, 11 const SkMScalar* SK_RESTRICT b) { 12 return (a[0] == b[0]) & (a[1] == b[1]) & (a[2] == b[2]) & (a[3] == b[3]); 13} 14 15bool SkMatrix44::operator==(const SkMatrix44& other) const { 16 if (this == &other) { 17 return true; 18 } 19 20 if (this->isTriviallyIdentity() && other.isTriviallyIdentity()) { 21 return true; 22 } 23 24 const SkMScalar* SK_RESTRICT a = &fMat[0][0]; 25 const SkMScalar* SK_RESTRICT b = &other.fMat[0][0]; 26 27#if 0 28 for (int i = 0; i < 16; ++i) { 29 if (a[i] != b[i]) { 30 return false; 31 } 32 } 33 return true; 34#else 35 // to reduce branch instructions, we compare 4 at a time. 36 // see bench/Matrix44Bench.cpp for test. 37 if (!eq4(&a[0], &b[0])) { 38 return false; 39 } 40 if (!eq4(&a[4], &b[4])) { 41 return false; 42 } 43 if (!eq4(&a[8], &b[8])) { 44 return false; 45 } 46 return eq4(&a[12], &b[12]); 47#endif 48} 49 50/////////////////////////////////////////////////////////////////////////////// 51 52int SkMatrix44::computeTypeMask() const { 53 unsigned mask = 0; 54 55 if (0 != perspX() || 0 != perspY() || 0 != perspZ() || 1 != fMat[3][3]) { 56 return kTranslate_Mask | kScale_Mask | kAffine_Mask | kPerspective_Mask; 57 } 58 59 if (0 != transX() || 0 != transY() || 0 != transZ()) { 60 mask |= kTranslate_Mask; 61 } 62 63 if (1 != scaleX() || 1 != scaleY() || 1 != scaleZ()) { 64 mask |= kScale_Mask; 65 } 66 67 if (0 != fMat[1][0] || 0 != fMat[0][1] || 0 != fMat[0][2] || 68 0 != fMat[2][0] || 0 != fMat[1][2] || 0 != fMat[2][1]) { 69 mask |= kAffine_Mask; 70 } 71 72 return mask; 73} 74 75/////////////////////////////////////////////////////////////////////////////// 76 77void SkMatrix44::asColMajorf(float dst[]) const { 78 const SkMScalar* src = &fMat[0][0]; 79#ifdef SK_MSCALAR_IS_DOUBLE 80 for (int i = 0; i < 16; ++i) { 81 dst[i] = SkMScalarToFloat(src[i]); 82 } 83#elif defined SK_MSCALAR_IS_FLOAT 84 memcpy(dst, src, 16 * sizeof(float)); 85#endif 86} 87 88void SkMatrix44::as4x3ColMajorf(float dst[]) const { 89 const SkMScalar* src = &fMat[0][0]; 90#ifdef SK_MSCALAR_IS_DOUBLE 91 for (int i = 0; i < 12; ++i) { 92 dst[i] = SkMScalarToFloat(src[i]); 93 } 94#elif defined SK_MSCALAR_IS_FLOAT 95 memcpy(dst, src, 12 * sizeof(float)); 96#endif 97} 98 99void SkMatrix44::asColMajord(double dst[]) const { 100 const SkMScalar* src = &fMat[0][0]; 101#ifdef SK_MSCALAR_IS_DOUBLE 102 memcpy(dst, src, 16 * sizeof(double)); 103#elif defined SK_MSCALAR_IS_FLOAT 104 for (int i = 0; i < 16; ++i) { 105 dst[i] = SkMScalarToDouble(src[i]); 106 } 107#endif 108} 109 110void SkMatrix44::asRowMajorf(float dst[]) const { 111 const SkMScalar* src = &fMat[0][0]; 112 for (int i = 0; i < 4; ++i) { 113 dst[0] = SkMScalarToFloat(src[0]); 114 dst[4] = SkMScalarToFloat(src[1]); 115 dst[8] = SkMScalarToFloat(src[2]); 116 dst[12] = SkMScalarToFloat(src[3]); 117 src += 4; 118 dst += 1; 119 } 120} 121 122void SkMatrix44::asRowMajord(double dst[]) const { 123 const SkMScalar* src = &fMat[0][0]; 124 for (int i = 0; i < 4; ++i) { 125 dst[0] = SkMScalarToDouble(src[0]); 126 dst[4] = SkMScalarToDouble(src[1]); 127 dst[8] = SkMScalarToDouble(src[2]); 128 dst[12] = SkMScalarToDouble(src[3]); 129 src += 4; 130 dst += 1; 131 } 132} 133 134void SkMatrix44::setColMajorf(const float src[]) { 135 SkMScalar* dst = &fMat[0][0]; 136#ifdef SK_MSCALAR_IS_DOUBLE 137 for (int i = 0; i < 16; ++i) { 138 dst[i] = SkMScalarToFloat(src[i]); 139 } 140#elif defined SK_MSCALAR_IS_FLOAT 141 memcpy(dst, src, 16 * sizeof(float)); 142#endif 143 144 this->dirtyTypeMask(); 145} 146 147void SkMatrix44::setColMajord(const double src[]) { 148 SkMScalar* dst = &fMat[0][0]; 149#ifdef SK_MSCALAR_IS_DOUBLE 150 memcpy(dst, src, 16 * sizeof(double)); 151#elif defined SK_MSCALAR_IS_FLOAT 152 for (int i = 0; i < 16; ++i) { 153 dst[i] = SkDoubleToMScalar(src[i]); 154 } 155#endif 156 157 this->dirtyTypeMask(); 158} 159 160void SkMatrix44::setRowMajorf(const float src[]) { 161 SkMScalar* dst = &fMat[0][0]; 162 for (int i = 0; i < 4; ++i) { 163 dst[0] = SkMScalarToFloat(src[0]); 164 dst[4] = SkMScalarToFloat(src[1]); 165 dst[8] = SkMScalarToFloat(src[2]); 166 dst[12] = SkMScalarToFloat(src[3]); 167 src += 4; 168 dst += 1; 169 } 170 this->dirtyTypeMask(); 171} 172 173void SkMatrix44::setRowMajord(const double src[]) { 174 SkMScalar* dst = &fMat[0][0]; 175 for (int i = 0; i < 4; ++i) { 176 dst[0] = SkDoubleToMScalar(src[0]); 177 dst[4] = SkDoubleToMScalar(src[1]); 178 dst[8] = SkDoubleToMScalar(src[2]); 179 dst[12] = SkDoubleToMScalar(src[3]); 180 src += 4; 181 dst += 1; 182 } 183 this->dirtyTypeMask(); 184} 185 186/////////////////////////////////////////////////////////////////////////////// 187 188const SkMatrix44& SkMatrix44::I() { 189 static constexpr SkMatrix44 gIdentity44(kIdentity_Constructor); 190 return gIdentity44; 191} 192 193void SkMatrix44::setIdentity() { 194 fMat[0][0] = 1; 195 fMat[0][1] = 0; 196 fMat[0][2] = 0; 197 fMat[0][3] = 0; 198 fMat[1][0] = 0; 199 fMat[1][1] = 1; 200 fMat[1][2] = 0; 201 fMat[1][3] = 0; 202 fMat[2][0] = 0; 203 fMat[2][1] = 0; 204 fMat[2][2] = 1; 205 fMat[2][3] = 0; 206 fMat[3][0] = 0; 207 fMat[3][1] = 0; 208 fMat[3][2] = 0; 209 fMat[3][3] = 1; 210 this->setTypeMask(kIdentity_Mask); 211} 212 213void SkMatrix44::set3x3(SkMScalar m00, SkMScalar m01, SkMScalar m02, 214 SkMScalar m10, SkMScalar m11, SkMScalar m12, 215 SkMScalar m20, SkMScalar m21, SkMScalar m22) { 216 fMat[0][0] = m00; fMat[0][1] = m01; fMat[0][2] = m02; fMat[0][3] = 0; 217 fMat[1][0] = m10; fMat[1][1] = m11; fMat[1][2] = m12; fMat[1][3] = 0; 218 fMat[2][0] = m20; fMat[2][1] = m21; fMat[2][2] = m22; fMat[2][3] = 0; 219 fMat[3][0] = 0; fMat[3][1] = 0; fMat[3][2] = 0; fMat[3][3] = 1; 220 this->dirtyTypeMask(); 221} 222 223void SkMatrix44::set3x3RowMajorf(const float src[]) { 224 fMat[0][0] = src[0]; fMat[0][1] = src[3]; fMat[0][2] = src[6]; fMat[0][3] = 0; 225 fMat[1][0] = src[1]; fMat[1][1] = src[4]; fMat[1][2] = src[7]; fMat[1][3] = 0; 226 fMat[2][0] = src[2]; fMat[2][1] = src[5]; fMat[2][2] = src[8]; fMat[2][3] = 0; 227 fMat[3][0] = 0; fMat[3][1] = 0; fMat[3][2] = 0; fMat[3][3] = 1; 228 this->dirtyTypeMask(); 229} 230 231void SkMatrix44::set4x3ColMajorf(const float src[]) { 232 fMat[0][0] = src[0]; fMat[0][1] = src[1]; fMat[0][2] = src[2]; fMat[0][3] = src[3]; 233 fMat[1][0] = src[4]; fMat[1][1] = src[5]; fMat[1][2] = src[6]; fMat[1][3] = src[7]; 234 fMat[2][0] = src[8]; fMat[2][1] = src[9]; fMat[2][2] = src[10]; fMat[2][3] = src[11]; 235 fMat[3][0] = 0; fMat[3][1] = 0; fMat[3][2] = 0; fMat[3][3] = 1; 236 this->dirtyTypeMask(); 237} 238 239/////////////////////////////////////////////////////////////////////////////// 240 241void SkMatrix44::setTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz) { 242 this->setIdentity(); 243 244 if (!dx && !dy && !dz) { 245 return; 246 } 247 248 fMat[3][0] = dx; 249 fMat[3][1] = dy; 250 fMat[3][2] = dz; 251 this->setTypeMask(kTranslate_Mask); 252} 253 254void SkMatrix44::preTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz) { 255 if (!dx && !dy && !dz) { 256 return; 257 } 258 259 for (int i = 0; i < 4; ++i) { 260 fMat[3][i] = fMat[0][i] * dx + fMat[1][i] * dy + fMat[2][i] * dz + fMat[3][i]; 261 } 262 this->dirtyTypeMask(); 263} 264 265void SkMatrix44::postTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz) { 266 if (!dx && !dy && !dz) { 267 return; 268 } 269 270 if (this->getType() & kPerspective_Mask) { 271 for (int i = 0; i < 4; ++i) { 272 fMat[i][0] += fMat[i][3] * dx; 273 fMat[i][1] += fMat[i][3] * dy; 274 fMat[i][2] += fMat[i][3] * dz; 275 } 276 } else { 277 fMat[3][0] += dx; 278 fMat[3][1] += dy; 279 fMat[3][2] += dz; 280 this->dirtyTypeMask(); 281 } 282} 283 284/////////////////////////////////////////////////////////////////////////////// 285 286void SkMatrix44::setScale(SkMScalar sx, SkMScalar sy, SkMScalar sz) { 287 this->setIdentity(); 288 289 if (1 == sx && 1 == sy && 1 == sz) { 290 return; 291 } 292 293 fMat[0][0] = sx; 294 fMat[1][1] = sy; 295 fMat[2][2] = sz; 296 this->setTypeMask(kScale_Mask); 297} 298 299void SkMatrix44::preScale(SkMScalar sx, SkMScalar sy, SkMScalar sz) { 300 if (1 == sx && 1 == sy && 1 == sz) { 301 return; 302 } 303 304 // The implementation matrix * pureScale can be shortcut 305 // by knowing that pureScale components effectively scale 306 // the columns of the original matrix. 307 for (int i = 0; i < 4; i++) { 308 fMat[0][i] *= sx; 309 fMat[1][i] *= sy; 310 fMat[2][i] *= sz; 311 } 312 this->dirtyTypeMask(); 313} 314 315void SkMatrix44::postScale(SkMScalar sx, SkMScalar sy, SkMScalar sz) { 316 if (1 == sx && 1 == sy && 1 == sz) { 317 return; 318 } 319 320 for (int i = 0; i < 4; i++) { 321 fMat[i][0] *= sx; 322 fMat[i][1] *= sy; 323 fMat[i][2] *= sz; 324 } 325 this->dirtyTypeMask(); 326} 327 328/////////////////////////////////////////////////////////////////////////////// 329 330void SkMatrix44::setRotateAbout(SkMScalar x, SkMScalar y, SkMScalar z, 331 SkMScalar radians) { 332 double len2 = (double)x * x + (double)y * y + (double)z * z; 333 if (1 != len2) { 334 if (0 == len2) { 335 this->setIdentity(); 336 return; 337 } 338 double scale = 1 / sqrt(len2); 339 x = SkDoubleToMScalar(x * scale); 340 y = SkDoubleToMScalar(y * scale); 341 z = SkDoubleToMScalar(z * scale); 342 } 343 this->setRotateAboutUnit(x, y, z, radians); 344} 345 346void SkMatrix44::setRotateAboutUnit(SkMScalar x, SkMScalar y, SkMScalar z, 347 SkMScalar radians) { 348 double c = cos(radians); 349 double s = sin(radians); 350 double C = 1 - c; 351 double xs = x * s; 352 double ys = y * s; 353 double zs = z * s; 354 double xC = x * C; 355 double yC = y * C; 356 double zC = z * C; 357 double xyC = x * yC; 358 double yzC = y * zC; 359 double zxC = z * xC; 360 361 // if you're looking at wikipedia, remember that we're column major. 362 this->set3x3(SkDoubleToMScalar(x * xC + c), // scale x 363 SkDoubleToMScalar(xyC + zs), // skew x 364 SkDoubleToMScalar(zxC - ys), // trans x 365 366 SkDoubleToMScalar(xyC - zs), // skew y 367 SkDoubleToMScalar(y * yC + c), // scale y 368 SkDoubleToMScalar(yzC + xs), // trans y 369 370 SkDoubleToMScalar(zxC + ys), // persp x 371 SkDoubleToMScalar(yzC - xs), // persp y 372 SkDoubleToMScalar(z * zC + c)); // persp 2 373} 374 375/////////////////////////////////////////////////////////////////////////////// 376 377static bool bits_isonly(int value, int mask) { 378 return 0 == (value & ~mask); 379} 380 381void SkMatrix44::setConcat(const SkMatrix44& a, const SkMatrix44& b) { 382 const SkMatrix44::TypeMask a_mask = a.getType(); 383 const SkMatrix44::TypeMask b_mask = b.getType(); 384 385 if (kIdentity_Mask == a_mask) { 386 *this = b; 387 return; 388 } 389 if (kIdentity_Mask == b_mask) { 390 *this = a; 391 return; 392 } 393 394 bool useStorage = (this == &a || this == &b); 395 SkMScalar storage[16]; 396 SkMScalar* result = useStorage ? storage : &fMat[0][0]; 397 398 // Both matrices are at most scale+translate 399 if (bits_isonly(a_mask | b_mask, kScale_Mask | kTranslate_Mask)) { 400 result[0] = a.fMat[0][0] * b.fMat[0][0]; 401 result[1] = result[2] = result[3] = result[4] = 0; 402 result[5] = a.fMat[1][1] * b.fMat[1][1]; 403 result[6] = result[7] = result[8] = result[9] = 0; 404 result[10] = a.fMat[2][2] * b.fMat[2][2]; 405 result[11] = 0; 406 result[12] = a.fMat[0][0] * b.fMat[3][0] + a.fMat[3][0]; 407 result[13] = a.fMat[1][1] * b.fMat[3][1] + a.fMat[3][1]; 408 result[14] = a.fMat[2][2] * b.fMat[3][2] + a.fMat[3][2]; 409 result[15] = 1; 410 } else { 411 for (int j = 0; j < 4; j++) { 412 for (int i = 0; i < 4; i++) { 413 double value = 0; 414 for (int k = 0; k < 4; k++) { 415 value += SkMScalarToDouble(a.fMat[k][i]) * b.fMat[j][k]; 416 } 417 *result++ = SkDoubleToMScalar(value); 418 } 419 } 420 } 421 422 if (useStorage) { 423 memcpy(fMat, storage, sizeof(storage)); 424 } 425 this->dirtyTypeMask(); 426} 427 428/////////////////////////////////////////////////////////////////////////////// 429 430/** We always perform the calculation in doubles, to avoid prematurely losing 431 precision along the way. This relies on the compiler automatically 432 promoting our SkMScalar values to double (if needed). 433 */ 434double SkMatrix44::determinant() const { 435 if (this->isIdentity()) { 436 return 1; 437 } 438 if (this->isScaleTranslate()) { 439 return fMat[0][0] * fMat[1][1] * fMat[2][2] * fMat[3][3]; 440 } 441 442 double a00 = fMat[0][0]; 443 double a01 = fMat[0][1]; 444 double a02 = fMat[0][2]; 445 double a03 = fMat[0][3]; 446 double a10 = fMat[1][0]; 447 double a11 = fMat[1][1]; 448 double a12 = fMat[1][2]; 449 double a13 = fMat[1][3]; 450 double a20 = fMat[2][0]; 451 double a21 = fMat[2][1]; 452 double a22 = fMat[2][2]; 453 double a23 = fMat[2][3]; 454 double a30 = fMat[3][0]; 455 double a31 = fMat[3][1]; 456 double a32 = fMat[3][2]; 457 double a33 = fMat[3][3]; 458 459 double b00 = a00 * a11 - a01 * a10; 460 double b01 = a00 * a12 - a02 * a10; 461 double b02 = a00 * a13 - a03 * a10; 462 double b03 = a01 * a12 - a02 * a11; 463 double b04 = a01 * a13 - a03 * a11; 464 double b05 = a02 * a13 - a03 * a12; 465 double b06 = a20 * a31 - a21 * a30; 466 double b07 = a20 * a32 - a22 * a30; 467 double b08 = a20 * a33 - a23 * a30; 468 double b09 = a21 * a32 - a22 * a31; 469 double b10 = a21 * a33 - a23 * a31; 470 double b11 = a22 * a33 - a23 * a32; 471 472 // Calculate the determinant 473 return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; 474} 475 476/////////////////////////////////////////////////////////////////////////////// 477 478static bool is_matrix_finite(const SkMatrix44& matrix) { 479 SkMScalar accumulator = 0; 480 for (int row = 0; row < 4; ++row) { 481 for (int col = 0; col < 4; ++col) { 482 accumulator *= matrix.get(row, col); 483 } 484 } 485 return accumulator == 0; 486} 487 488bool SkMatrix44::invert(SkMatrix44* storage) const { 489 if (this->isIdentity()) { 490 if (storage) { 491 storage->setIdentity(); 492 } 493 return true; 494 } 495 496 if (this->isTranslate()) { 497 if (storage) { 498 storage->setTranslate(-fMat[3][0], -fMat[3][1], -fMat[3][2]); 499 } 500 return true; 501 } 502 503 SkMatrix44 tmp(kUninitialized_Constructor); 504 // Use storage if it's available and distinct from this matrix. 505 SkMatrix44* inverse = (storage && storage != this) ? storage : &tmp; 506 if (this->isScaleTranslate()) { 507 if (0 == fMat[0][0] * fMat[1][1] * fMat[2][2]) { 508 return false; 509 } 510 511 double invXScale = 1 / fMat[0][0]; 512 double invYScale = 1 / fMat[1][1]; 513 double invZScale = 1 / fMat[2][2]; 514 515 inverse->fMat[0][0] = SkDoubleToMScalar(invXScale); 516 inverse->fMat[0][1] = 0; 517 inverse->fMat[0][2] = 0; 518 inverse->fMat[0][3] = 0; 519 520 inverse->fMat[1][0] = 0; 521 inverse->fMat[1][1] = SkDoubleToMScalar(invYScale); 522 inverse->fMat[1][2] = 0; 523 inverse->fMat[1][3] = 0; 524 525 inverse->fMat[2][0] = 0; 526 inverse->fMat[2][1] = 0; 527 inverse->fMat[2][2] = SkDoubleToMScalar(invZScale); 528 inverse->fMat[2][3] = 0; 529 530 inverse->fMat[3][0] = SkDoubleToMScalar(-fMat[3][0] * invXScale); 531 inverse->fMat[3][1] = SkDoubleToMScalar(-fMat[3][1] * invYScale); 532 inverse->fMat[3][2] = SkDoubleToMScalar(-fMat[3][2] * invZScale); 533 inverse->fMat[3][3] = 1; 534 535 inverse->setTypeMask(this->getType()); 536 537 if (!is_matrix_finite(*inverse)) { 538 return false; 539 } 540 if (storage && inverse != storage) { 541 *storage = *inverse; 542 } 543 return true; 544 } 545 546 double a00 = fMat[0][0]; 547 double a01 = fMat[0][1]; 548 double a02 = fMat[0][2]; 549 double a03 = fMat[0][3]; 550 double a10 = fMat[1][0]; 551 double a11 = fMat[1][1]; 552 double a12 = fMat[1][2]; 553 double a13 = fMat[1][3]; 554 double a20 = fMat[2][0]; 555 double a21 = fMat[2][1]; 556 double a22 = fMat[2][2]; 557 double a23 = fMat[2][3]; 558 double a30 = fMat[3][0]; 559 double a31 = fMat[3][1]; 560 double a32 = fMat[3][2]; 561 double a33 = fMat[3][3]; 562 563 if (!(this->getType() & kPerspective_Mask)) { 564 // If we know the matrix has no perspective, then the perspective 565 // component is (0, 0, 0, 1). We can use this information to save a lot 566 // of arithmetic that would otherwise be spent to compute the inverse 567 // of a general matrix. 568 569 SkASSERT(a03 == 0); 570 SkASSERT(a13 == 0); 571 SkASSERT(a23 == 0); 572 SkASSERT(a33 == 1); 573 574 double b00 = a00 * a11 - a01 * a10; 575 double b01 = a00 * a12 - a02 * a10; 576 double b03 = a01 * a12 - a02 * a11; 577 double b06 = a20 * a31 - a21 * a30; 578 double b07 = a20 * a32 - a22 * a30; 579 double b08 = a20; 580 double b09 = a21 * a32 - a22 * a31; 581 double b10 = a21; 582 double b11 = a22; 583 584 // Calculate the determinant 585 double det = b00 * b11 - b01 * b10 + b03 * b08; 586 587 double invdet = 1.0 / det; 588 // If det is zero, we want to return false. However, we also want to return false 589 // if 1/det overflows to infinity (i.e. det is denormalized). Both of these are 590 // handled by checking that 1/det is finite. 591 if (!sk_float_isfinite(invdet)) { 592 return false; 593 } 594 595 b00 *= invdet; 596 b01 *= invdet; 597 b03 *= invdet; 598 b06 *= invdet; 599 b07 *= invdet; 600 b08 *= invdet; 601 b09 *= invdet; 602 b10 *= invdet; 603 b11 *= invdet; 604 605 inverse->fMat[0][0] = SkDoubleToMScalar(a11 * b11 - a12 * b10); 606 inverse->fMat[0][1] = SkDoubleToMScalar(a02 * b10 - a01 * b11); 607 inverse->fMat[0][2] = SkDoubleToMScalar(b03); 608 inverse->fMat[0][3] = 0; 609 inverse->fMat[1][0] = SkDoubleToMScalar(a12 * b08 - a10 * b11); 610 inverse->fMat[1][1] = SkDoubleToMScalar(a00 * b11 - a02 * b08); 611 inverse->fMat[1][2] = SkDoubleToMScalar(-b01); 612 inverse->fMat[1][3] = 0; 613 inverse->fMat[2][0] = SkDoubleToMScalar(a10 * b10 - a11 * b08); 614 inverse->fMat[2][1] = SkDoubleToMScalar(a01 * b08 - a00 * b10); 615 inverse->fMat[2][2] = SkDoubleToMScalar(b00); 616 inverse->fMat[2][3] = 0; 617 inverse->fMat[3][0] = SkDoubleToMScalar(a11 * b07 - a10 * b09 - a12 * b06); 618 inverse->fMat[3][1] = SkDoubleToMScalar(a00 * b09 - a01 * b07 + a02 * b06); 619 inverse->fMat[3][2] = SkDoubleToMScalar(a31 * b01 - a30 * b03 - a32 * b00); 620 inverse->fMat[3][3] = 1; 621 622 inverse->setTypeMask(this->getType()); 623 if (!is_matrix_finite(*inverse)) { 624 return false; 625 } 626 if (storage && inverse != storage) { 627 *storage = *inverse; 628 } 629 return true; 630 } 631 632 double b00 = a00 * a11 - a01 * a10; 633 double b01 = a00 * a12 - a02 * a10; 634 double b02 = a00 * a13 - a03 * a10; 635 double b03 = a01 * a12 - a02 * a11; 636 double b04 = a01 * a13 - a03 * a11; 637 double b05 = a02 * a13 - a03 * a12; 638 double b06 = a20 * a31 - a21 * a30; 639 double b07 = a20 * a32 - a22 * a30; 640 double b08 = a20 * a33 - a23 * a30; 641 double b09 = a21 * a32 - a22 * a31; 642 double b10 = a21 * a33 - a23 * a31; 643 double b11 = a22 * a33 - a23 * a32; 644 645 // Calculate the determinant 646 double det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; 647 648 double invdet = 1.0 / det; 649 // If det is zero, we want to return false. However, we also want to return false 650 // if 1/det overflows to infinity (i.e. det is denormalized). Both of these are 651 // handled by checking that 1/det is finite. 652 if (!sk_float_isfinite(invdet)) { 653 return false; 654 } 655 656 b00 *= invdet; 657 b01 *= invdet; 658 b02 *= invdet; 659 b03 *= invdet; 660 b04 *= invdet; 661 b05 *= invdet; 662 b06 *= invdet; 663 b07 *= invdet; 664 b08 *= invdet; 665 b09 *= invdet; 666 b10 *= invdet; 667 b11 *= invdet; 668 669 inverse->fMat[0][0] = SkDoubleToMScalar(a11 * b11 - a12 * b10 + a13 * b09); 670 inverse->fMat[0][1] = SkDoubleToMScalar(a02 * b10 - a01 * b11 - a03 * b09); 671 inverse->fMat[0][2] = SkDoubleToMScalar(a31 * b05 - a32 * b04 + a33 * b03); 672 inverse->fMat[0][3] = SkDoubleToMScalar(a22 * b04 - a21 * b05 - a23 * b03); 673 inverse->fMat[1][0] = SkDoubleToMScalar(a12 * b08 - a10 * b11 - a13 * b07); 674 inverse->fMat[1][1] = SkDoubleToMScalar(a00 * b11 - a02 * b08 + a03 * b07); 675 inverse->fMat[1][2] = SkDoubleToMScalar(a32 * b02 - a30 * b05 - a33 * b01); 676 inverse->fMat[1][3] = SkDoubleToMScalar(a20 * b05 - a22 * b02 + a23 * b01); 677 inverse->fMat[2][0] = SkDoubleToMScalar(a10 * b10 - a11 * b08 + a13 * b06); 678 inverse->fMat[2][1] = SkDoubleToMScalar(a01 * b08 - a00 * b10 - a03 * b06); 679 inverse->fMat[2][2] = SkDoubleToMScalar(a30 * b04 - a31 * b02 + a33 * b00); 680 inverse->fMat[2][3] = SkDoubleToMScalar(a21 * b02 - a20 * b04 - a23 * b00); 681 inverse->fMat[3][0] = SkDoubleToMScalar(a11 * b07 - a10 * b09 - a12 * b06); 682 inverse->fMat[3][1] = SkDoubleToMScalar(a00 * b09 - a01 * b07 + a02 * b06); 683 inverse->fMat[3][2] = SkDoubleToMScalar(a31 * b01 - a30 * b03 - a32 * b00); 684 inverse->fMat[3][3] = SkDoubleToMScalar(a20 * b03 - a21 * b01 + a22 * b00); 685 inverse->dirtyTypeMask(); 686 687 inverse->setTypeMask(this->getType()); 688 if (!is_matrix_finite(*inverse)) { 689 return false; 690 } 691 if (storage && inverse != storage) { 692 *storage = *inverse; 693 } 694 return true; 695} 696 697/////////////////////////////////////////////////////////////////////////////// 698 699void SkMatrix44::transpose() { 700 SkTSwap(fMat[0][1], fMat[1][0]); 701 SkTSwap(fMat[0][2], fMat[2][0]); 702 SkTSwap(fMat[0][3], fMat[3][0]); 703 SkTSwap(fMat[1][2], fMat[2][1]); 704 SkTSwap(fMat[1][3], fMat[3][1]); 705 SkTSwap(fMat[2][3], fMat[3][2]); 706 707 if (!this->isTriviallyIdentity()) { 708 this->dirtyTypeMask(); 709 } 710} 711 712/////////////////////////////////////////////////////////////////////////////// 713 714void SkMatrix44::mapScalars(const SkScalar src[4], SkScalar dst[4]) const { 715 SkScalar storage[4]; 716 SkScalar* result = (src == dst) ? storage : dst; 717 718 for (int i = 0; i < 4; i++) { 719 SkMScalar value = 0; 720 for (int j = 0; j < 4; j++) { 721 value += fMat[j][i] * src[j]; 722 } 723 result[i] = SkMScalarToScalar(value); 724 } 725 726 if (storage == result) { 727 memcpy(dst, storage, sizeof(storage)); 728 } 729} 730 731#ifdef SK_MSCALAR_IS_DOUBLE 732 733void SkMatrix44::mapMScalars(const SkMScalar src[4], SkMScalar dst[4]) const { 734 SkMScalar storage[4]; 735 SkMScalar* result = (src == dst) ? storage : dst; 736 737 for (int i = 0; i < 4; i++) { 738 SkMScalar value = 0; 739 for (int j = 0; j < 4; j++) { 740 value += fMat[j][i] * src[j]; 741 } 742 result[i] = value; 743 } 744 745 if (storage == result) { 746 memcpy(dst, storage, sizeof(storage)); 747 } 748} 749 750#endif 751 752typedef void (*Map2Procf)(const SkMScalar mat[][4], const float src2[], int count, float dst4[]); 753typedef void (*Map2Procd)(const SkMScalar mat[][4], const double src2[], int count, double dst4[]); 754 755static void map2_if(const SkMScalar mat[][4], const float* SK_RESTRICT src2, 756 int count, float* SK_RESTRICT dst4) { 757 for (int i = 0; i < count; ++i) { 758 dst4[0] = src2[0]; 759 dst4[1] = src2[1]; 760 dst4[2] = 0; 761 dst4[3] = 1; 762 src2 += 2; 763 dst4 += 4; 764 } 765} 766 767static void map2_id(const SkMScalar mat[][4], const double* SK_RESTRICT src2, 768 int count, double* SK_RESTRICT dst4) { 769 for (int i = 0; i < count; ++i) { 770 dst4[0] = src2[0]; 771 dst4[1] = src2[1]; 772 dst4[2] = 0; 773 dst4[3] = 1; 774 src2 += 2; 775 dst4 += 4; 776 } 777} 778 779static void map2_tf(const SkMScalar mat[][4], const float* SK_RESTRICT src2, 780 int count, float* SK_RESTRICT dst4) { 781 const float mat30 = SkMScalarToFloat(mat[3][0]); 782 const float mat31 = SkMScalarToFloat(mat[3][1]); 783 const float mat32 = SkMScalarToFloat(mat[3][2]); 784 for (int n = 0; n < count; ++n) { 785 dst4[0] = src2[0] + mat30; 786 dst4[1] = src2[1] + mat31; 787 dst4[2] = mat32; 788 dst4[3] = 1; 789 src2 += 2; 790 dst4 += 4; 791 } 792} 793 794static void map2_td(const SkMScalar mat[][4], const double* SK_RESTRICT src2, 795 int count, double* SK_RESTRICT dst4) { 796 for (int n = 0; n < count; ++n) { 797 dst4[0] = src2[0] + mat[3][0]; 798 dst4[1] = src2[1] + mat[3][1]; 799 dst4[2] = mat[3][2]; 800 dst4[3] = 1; 801 src2 += 2; 802 dst4 += 4; 803 } 804} 805 806static void map2_sf(const SkMScalar mat[][4], const float* SK_RESTRICT src2, 807 int count, float* SK_RESTRICT dst4) { 808 const float mat32 = SkMScalarToFloat(mat[3][2]); 809 for (int n = 0; n < count; ++n) { 810 dst4[0] = SkMScalarToFloat(mat[0][0] * src2[0] + mat[3][0]); 811 dst4[1] = SkMScalarToFloat(mat[1][1] * src2[1] + mat[3][1]); 812 dst4[2] = mat32; 813 dst4[3] = 1; 814 src2 += 2; 815 dst4 += 4; 816 } 817} 818 819static void map2_sd(const SkMScalar mat[][4], const double* SK_RESTRICT src2, 820 int count, double* SK_RESTRICT dst4) { 821 for (int n = 0; n < count; ++n) { 822 dst4[0] = mat[0][0] * src2[0] + mat[3][0]; 823 dst4[1] = mat[1][1] * src2[1] + mat[3][1]; 824 dst4[2] = mat[3][2]; 825 dst4[3] = 1; 826 src2 += 2; 827 dst4 += 4; 828 } 829} 830 831static void map2_af(const SkMScalar mat[][4], const float* SK_RESTRICT src2, 832 int count, float* SK_RESTRICT dst4) { 833 SkMScalar r; 834 for (int n = 0; n < count; ++n) { 835 SkMScalar sx = SkFloatToMScalar(src2[0]); 836 SkMScalar sy = SkFloatToMScalar(src2[1]); 837 r = mat[0][0] * sx + mat[1][0] * sy + mat[3][0]; 838 dst4[0] = SkMScalarToFloat(r); 839 r = mat[0][1] * sx + mat[1][1] * sy + mat[3][1]; 840 dst4[1] = SkMScalarToFloat(r); 841 r = mat[0][2] * sx + mat[1][2] * sy + mat[3][2]; 842 dst4[2] = SkMScalarToFloat(r); 843 dst4[3] = 1; 844 src2 += 2; 845 dst4 += 4; 846 } 847} 848 849static void map2_ad(const SkMScalar mat[][4], const double* SK_RESTRICT src2, 850 int count, double* SK_RESTRICT dst4) { 851 for (int n = 0; n < count; ++n) { 852 double sx = src2[0]; 853 double sy = src2[1]; 854 dst4[0] = mat[0][0] * sx + mat[1][0] * sy + mat[3][0]; 855 dst4[1] = mat[0][1] * sx + mat[1][1] * sy + mat[3][1]; 856 dst4[2] = mat[0][2] * sx + mat[1][2] * sy + mat[3][2]; 857 dst4[3] = 1; 858 src2 += 2; 859 dst4 += 4; 860 } 861} 862 863static void map2_pf(const SkMScalar mat[][4], const float* SK_RESTRICT src2, 864 int count, float* SK_RESTRICT dst4) { 865 SkMScalar r; 866 for (int n = 0; n < count; ++n) { 867 SkMScalar sx = SkFloatToMScalar(src2[0]); 868 SkMScalar sy = SkFloatToMScalar(src2[1]); 869 for (int i = 0; i < 4; i++) { 870 r = mat[0][i] * sx + mat[1][i] * sy + mat[3][i]; 871 dst4[i] = SkMScalarToFloat(r); 872 } 873 src2 += 2; 874 dst4 += 4; 875 } 876} 877 878static void map2_pd(const SkMScalar mat[][4], const double* SK_RESTRICT src2, 879 int count, double* SK_RESTRICT dst4) { 880 for (int n = 0; n < count; ++n) { 881 double sx = src2[0]; 882 double sy = src2[1]; 883 for (int i = 0; i < 4; i++) { 884 dst4[i] = mat[0][i] * sx + mat[1][i] * sy + mat[3][i]; 885 } 886 src2 += 2; 887 dst4 += 4; 888 } 889} 890 891void SkMatrix44::map2(const float src2[], int count, float dst4[]) const { 892 static const Map2Procf gProc[] = { 893 map2_if, map2_tf, map2_sf, map2_sf, map2_af, map2_af, map2_af, map2_af 894 }; 895 896 TypeMask mask = this->getType(); 897 Map2Procf proc = (mask & kPerspective_Mask) ? map2_pf : gProc[mask]; 898 proc(fMat, src2, count, dst4); 899} 900 901void SkMatrix44::map2(const double src2[], int count, double dst4[]) const { 902 static const Map2Procd gProc[] = { 903 map2_id, map2_td, map2_sd, map2_sd, map2_ad, map2_ad, map2_ad, map2_ad 904 }; 905 906 TypeMask mask = this->getType(); 907 Map2Procd proc = (mask & kPerspective_Mask) ? map2_pd : gProc[mask]; 908 proc(fMat, src2, count, dst4); 909} 910 911bool SkMatrix44::preserves2dAxisAlignment (SkMScalar epsilon) const { 912 913 // Can't check (mask & kPerspective_Mask) because Z isn't relevant here. 914 if (0 != perspX() || 0 != perspY()) return false; 915 916 // A matrix with two non-zeroish values in any of the upper right 917 // rows or columns will skew. If only one value in each row or 918 // column is non-zeroish, we get a scale plus perhaps a 90-degree 919 // rotation. 920 int col0 = 0; 921 int col1 = 0; 922 int row0 = 0; 923 int row1 = 0; 924 925 // Must test against epsilon, not 0, because we can get values 926 // around 6e-17 in the matrix that "should" be 0. 927 928 if (SkMScalarAbs(fMat[0][0]) > epsilon) { 929 col0++; 930 row0++; 931 } 932 if (SkMScalarAbs(fMat[0][1]) > epsilon) { 933 col1++; 934 row0++; 935 } 936 if (SkMScalarAbs(fMat[1][0]) > epsilon) { 937 col0++; 938 row1++; 939 } 940 if (SkMScalarAbs(fMat[1][1]) > epsilon) { 941 col1++; 942 row1++; 943 } 944 if (col0 > 1 || col1 > 1 || row0 > 1 || row1 > 1) { 945 return false; 946 } 947 948 return true; 949} 950 951/////////////////////////////////////////////////////////////////////////////// 952 953void SkMatrix44::dump() const { 954 static const char* format = 955 "[%g %g %g %g][%g %g %g %g][%g %g %g %g][%g %g %g %g]\n"; 956#if 0 957 SkDebugf(format, 958 fMat[0][0], fMat[1][0], fMat[2][0], fMat[3][0], 959 fMat[0][1], fMat[1][1], fMat[2][1], fMat[3][1], 960 fMat[0][2], fMat[1][2], fMat[2][2], fMat[3][2], 961 fMat[0][3], fMat[1][3], fMat[2][3], fMat[3][3]); 962#else 963 SkDebugf(format, 964 fMat[0][0], fMat[0][1], fMat[0][2], fMat[0][3], 965 fMat[1][0], fMat[1][1], fMat[1][2], fMat[1][3], 966 fMat[2][0], fMat[2][1], fMat[2][2], fMat[2][3], 967 fMat[3][0], fMat[3][1], fMat[3][2], fMat[3][3]); 968#endif 969} 970 971/////////////////////////////////////////////////////////////////////////////// 972 973static void initFromMatrix(SkMScalar dst[4][4], const SkMatrix& src) { 974 dst[0][0] = SkScalarToMScalar(src[SkMatrix::kMScaleX]); 975 dst[1][0] = SkScalarToMScalar(src[SkMatrix::kMSkewX]); 976 dst[2][0] = 0; 977 dst[3][0] = SkScalarToMScalar(src[SkMatrix::kMTransX]); 978 dst[0][1] = SkScalarToMScalar(src[SkMatrix::kMSkewY]); 979 dst[1][1] = SkScalarToMScalar(src[SkMatrix::kMScaleY]); 980 dst[2][1] = 0; 981 dst[3][1] = SkScalarToMScalar(src[SkMatrix::kMTransY]); 982 dst[0][2] = 0; 983 dst[1][2] = 0; 984 dst[2][2] = 1; 985 dst[3][2] = 0; 986 dst[0][3] = SkScalarToMScalar(src[SkMatrix::kMPersp0]); 987 dst[1][3] = SkScalarToMScalar(src[SkMatrix::kMPersp1]); 988 dst[2][3] = 0; 989 dst[3][3] = SkScalarToMScalar(src[SkMatrix::kMPersp2]); 990} 991 992SkMatrix44::SkMatrix44(const SkMatrix& src) { 993 this->operator=(src); 994} 995 996SkMatrix44& SkMatrix44::operator=(const SkMatrix& src) { 997 initFromMatrix(fMat, src); 998 999 if (src.isIdentity()) { 1000 this->setTypeMask(kIdentity_Mask); 1001 } else { 1002 this->dirtyTypeMask(); 1003 } 1004 return *this; 1005} 1006 1007SkMatrix44::operator SkMatrix() const { 1008 SkMatrix dst; 1009 1010 dst[SkMatrix::kMScaleX] = SkMScalarToScalar(fMat[0][0]); 1011 dst[SkMatrix::kMSkewX] = SkMScalarToScalar(fMat[1][0]); 1012 dst[SkMatrix::kMTransX] = SkMScalarToScalar(fMat[3][0]); 1013 1014 dst[SkMatrix::kMSkewY] = SkMScalarToScalar(fMat[0][1]); 1015 dst[SkMatrix::kMScaleY] = SkMScalarToScalar(fMat[1][1]); 1016 dst[SkMatrix::kMTransY] = SkMScalarToScalar(fMat[3][1]); 1017 1018 dst[SkMatrix::kMPersp0] = SkMScalarToScalar(fMat[0][3]); 1019 dst[SkMatrix::kMPersp1] = SkMScalarToScalar(fMat[1][3]); 1020 dst[SkMatrix::kMPersp2] = SkMScalarToScalar(fMat[3][3]); 1021 1022 return dst; 1023} 1024