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