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::asColMajord(double dst[]) const { 89 const SkMScalar* src = &fMat[0][0]; 90 #ifdef SK_MSCALAR_IS_DOUBLE 91 memcpy(dst, src, 16 * sizeof(double)); 92 #elif defined SK_MSCALAR_IS_FLOAT 93 for (int i = 0; i < 16; ++i) { 94 dst[i] = SkMScalarToDouble(src[i]); 95 } 96 #endif 97 } 98 99 void SkMatrix44::asRowMajorf(float dst[]) const { 100 const SkMScalar* src = &fMat[0][0]; 101 for (int i = 0; i < 4; ++i) { 102 dst[0] = SkMScalarToFloat(src[0]); 103 dst[4] = SkMScalarToFloat(src[1]); 104 dst[8] = SkMScalarToFloat(src[2]); 105 dst[12] = SkMScalarToFloat(src[3]); 106 src += 4; 107 dst += 1; 108 } 109 } 110 111 void SkMatrix44::asRowMajord(double dst[]) const { 112 const SkMScalar* src = &fMat[0][0]; 113 for (int i = 0; i < 4; ++i) { 114 dst[0] = SkMScalarToDouble(src[0]); 115 dst[4] = SkMScalarToDouble(src[1]); 116 dst[8] = SkMScalarToDouble(src[2]); 117 dst[12] = SkMScalarToDouble(src[3]); 118 src += 4; 119 dst += 1; 120 } 121 } 122 123 void SkMatrix44::setColMajorf(const float src[]) { 124 SkMScalar* dst = &fMat[0][0]; 125 #ifdef SK_MSCALAR_IS_DOUBLE 126 for (int i = 0; i < 16; ++i) { 127 dst[i] = SkMScalarToFloat(src[i]); 128 } 129 #elif defined SK_MSCALAR_IS_FLOAT 130 memcpy(dst, src, 16 * sizeof(float)); 131 #endif 132 133 this->dirtyTypeMask(); 134 } 135 136 void SkMatrix44::setColMajord(const double src[]) { 137 SkMScalar* dst = &fMat[0][0]; 138 #ifdef SK_MSCALAR_IS_DOUBLE 139 memcpy(dst, src, 16 * sizeof(double)); 140 #elif defined SK_MSCALAR_IS_FLOAT 141 for (int i = 0; i < 16; ++i) { 142 dst[i] = SkDoubleToMScalar(src[i]); 143 } 144 #endif 145 146 this->dirtyTypeMask(); 147 } 148 149 void SkMatrix44::setRowMajorf(const float src[]) { 150 SkMScalar* dst = &fMat[0][0]; 151 for (int i = 0; i < 4; ++i) { 152 dst[0] = SkMScalarToFloat(src[0]); 153 dst[4] = SkMScalarToFloat(src[1]); 154 dst[8] = SkMScalarToFloat(src[2]); 155 dst[12] = SkMScalarToFloat(src[3]); 156 src += 4; 157 dst += 1; 158 } 159 this->dirtyTypeMask(); 160 } 161 162 void SkMatrix44::setRowMajord(const double src[]) { 163 SkMScalar* dst = &fMat[0][0]; 164 for (int i = 0; i < 4; ++i) { 165 dst[0] = SkDoubleToMScalar(src[0]); 166 dst[4] = SkDoubleToMScalar(src[1]); 167 dst[8] = SkDoubleToMScalar(src[2]); 168 dst[12] = SkDoubleToMScalar(src[3]); 169 src += 4; 170 dst += 1; 171 } 172 this->dirtyTypeMask(); 173 } 174 175 /////////////////////////////////////////////////////////////////////////////// 176 177 const SkMatrix44& SkMatrix44::I() { 178 static const SkMatrix44 gIdentity44(kIdentity_Constructor); 179 return gIdentity44; 180 } 181 182 void SkMatrix44::setIdentity() { 183 sk_bzero(fMat, sizeof(fMat)); 184 fMat[0][0] = fMat[1][1] = fMat[2][2] = fMat[3][3] = 1; 185 this->setTypeMask(kIdentity_Mask); 186 } 187 188 void SkMatrix44::set3x3(SkMScalar m00, SkMScalar m01, SkMScalar m02, 189 SkMScalar m10, SkMScalar m11, SkMScalar m12, 190 SkMScalar m20, SkMScalar m21, SkMScalar m22) { 191 fMat[0][0] = m00; fMat[0][1] = m01; fMat[0][2] = m02; fMat[0][3] = 0; 192 fMat[1][0] = m10; fMat[1][1] = m11; fMat[1][2] = m12; fMat[1][3] = 0; 193 fMat[2][0] = m20; fMat[2][1] = m21; fMat[2][2] = m22; fMat[2][3] = 0; 194 fMat[3][0] = 0; fMat[3][1] = 0; fMat[3][2] = 0; fMat[3][3] = 1; 195 this->dirtyTypeMask(); 196 } 197 198 /////////////////////////////////////////////////////////////////////////////// 199 200 void SkMatrix44::setTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz) { 201 this->setIdentity(); 202 203 if (!dx && !dy && !dz) { 204 return; 205 } 206 207 fMat[3][0] = dx; 208 fMat[3][1] = dy; 209 fMat[3][2] = dz; 210 this->setTypeMask(kTranslate_Mask); 211 } 212 213 void SkMatrix44::preTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz) { 214 if (!dx && !dy && !dz) { 215 return; 216 } 217 218 const double X = SkMScalarToDouble(dx); 219 const double Y = SkMScalarToDouble(dy); 220 const double Z = SkMScalarToDouble(dz); 221 222 double tmp; 223 for (int i = 0; i < 4; ++i) { 224 tmp = fMat[0][i] * X + fMat[1][i] * Y + fMat[2][i] * Z + fMat[3][i]; 225 fMat[3][i] = SkDoubleToMScalar(tmp); 226 } 227 this->dirtyTypeMask(); 228 } 229 230 void SkMatrix44::postTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz) { 231 if (!dx && !dy && !dz) { 232 return; 233 } 234 235 if (this->getType() & kPerspective_Mask) { 236 for (int i = 0; i < 4; ++i) { 237 fMat[i][0] += fMat[i][3] * dx; 238 fMat[i][1] += fMat[i][3] * dy; 239 fMat[i][2] += fMat[i][3] * dz; 240 } 241 } else { 242 fMat[3][0] += dx; 243 fMat[3][1] += dy; 244 fMat[3][2] += dz; 245 this->dirtyTypeMask(); 246 } 247 } 248 249 /////////////////////////////////////////////////////////////////////////////// 250 251 void SkMatrix44::setScale(SkMScalar sx, SkMScalar sy, SkMScalar sz) { 252 this->setIdentity(); 253 254 if (1 == sx && 1 == sy && 1 == sz) { 255 return; 256 } 257 258 fMat[0][0] = sx; 259 fMat[1][1] = sy; 260 fMat[2][2] = sz; 261 this->setTypeMask(kScale_Mask); 262 } 263 264 void SkMatrix44::preScale(SkMScalar sx, SkMScalar sy, SkMScalar sz) { 265 if (1 == sx && 1 == sy && 1 == sz) { 266 return; 267 } 268 269 // The implementation matrix * pureScale can be shortcut 270 // by knowing that pureScale components effectively scale 271 // the columns of the original matrix. 272 for (int i = 0; i < 4; i++) { 273 fMat[0][i] *= sx; 274 fMat[1][i] *= sy; 275 fMat[2][i] *= sz; 276 } 277 this->dirtyTypeMask(); 278 } 279 280 void SkMatrix44::postScale(SkMScalar sx, SkMScalar sy, SkMScalar sz) { 281 if (1 == sx && 1 == sy && 1 == sz) { 282 return; 283 } 284 285 for (int i = 0; i < 4; i++) { 286 fMat[i][0] *= sx; 287 fMat[i][1] *= sy; 288 fMat[i][2] *= sz; 289 } 290 this->dirtyTypeMask(); 291 } 292 293 /////////////////////////////////////////////////////////////////////////////// 294 295 void SkMatrix44::setRotateAbout(SkMScalar x, SkMScalar y, SkMScalar z, 296 SkMScalar radians) { 297 double len2 = (double)x * x + (double)y * y + (double)z * z; 298 if (1 != len2) { 299 if (0 == len2) { 300 this->setIdentity(); 301 return; 302 } 303 double scale = 1 / sqrt(len2); 304 x = SkDoubleToMScalar(x * scale); 305 y = SkDoubleToMScalar(y * scale); 306 z = SkDoubleToMScalar(z * scale); 307 } 308 this->setRotateAboutUnit(x, y, z, radians); 309 } 310 311 void SkMatrix44::setRotateAboutUnit(SkMScalar x, SkMScalar y, SkMScalar z, 312 SkMScalar radians) { 313 double c = cos(radians); 314 double s = sin(radians); 315 double C = 1 - c; 316 double xs = x * s; 317 double ys = y * s; 318 double zs = z * s; 319 double xC = x * C; 320 double yC = y * C; 321 double zC = z * C; 322 double xyC = x * yC; 323 double yzC = y * zC; 324 double zxC = z * xC; 325 326 // if you're looking at wikipedia, remember that we're column major. 327 this->set3x3(SkDoubleToMScalar(x * xC + c), // scale x 328 SkDoubleToMScalar(xyC + zs), // skew x 329 SkDoubleToMScalar(zxC - ys), // trans x 330 331 SkDoubleToMScalar(xyC - zs), // skew y 332 SkDoubleToMScalar(y * yC + c), // scale y 333 SkDoubleToMScalar(yzC + xs), // trans y 334 335 SkDoubleToMScalar(zxC + ys), // persp x 336 SkDoubleToMScalar(yzC - xs), // persp y 337 SkDoubleToMScalar(z * zC + c)); // persp 2 338 } 339 340 /////////////////////////////////////////////////////////////////////////////// 341 342 static bool bits_isonly(int value, int mask) { 343 return 0 == (value & ~mask); 344 } 345 346 void SkMatrix44::setConcat(const SkMatrix44& a, const SkMatrix44& b) { 347 const SkMatrix44::TypeMask a_mask = a.getType(); 348 const SkMatrix44::TypeMask b_mask = b.getType(); 349 350 if (kIdentity_Mask == a_mask) { 351 *this = b; 352 return; 353 } 354 if (kIdentity_Mask == b_mask) { 355 *this = a; 356 return; 357 } 358 359 bool useStorage = (this == &a || this == &b); 360 SkMScalar storage[16]; 361 SkMScalar* result = useStorage ? storage : &fMat[0][0]; 362 363 // Both matrices are at most scale+translate 364 if (bits_isonly(a_mask | b_mask, kScale_Mask | kTranslate_Mask)) { 365 result[0] = a.fMat[0][0] * b.fMat[0][0]; 366 result[1] = result[2] = result[3] = result[4] = 0; 367 result[5] = a.fMat[1][1] * b.fMat[1][1]; 368 result[6] = result[7] = result[8] = result[9] = 0; 369 result[10] = a.fMat[2][2] * b.fMat[2][2]; 370 result[11] = 0; 371 result[12] = a.fMat[0][0] * b.fMat[3][0] + a.fMat[3][0]; 372 result[13] = a.fMat[1][1] * b.fMat[3][1] + a.fMat[3][1]; 373 result[14] = a.fMat[2][2] * b.fMat[3][2] + a.fMat[3][2]; 374 result[15] = 1; 375 } else { 376 for (int j = 0; j < 4; j++) { 377 for (int i = 0; i < 4; i++) { 378 double value = 0; 379 for (int k = 0; k < 4; k++) { 380 value += SkMScalarToDouble(a.fMat[k][i]) * b.fMat[j][k]; 381 } 382 *result++ = SkDoubleToMScalar(value); 383 } 384 } 385 } 386 387 if (useStorage) { 388 memcpy(fMat, storage, sizeof(storage)); 389 } 390 this->dirtyTypeMask(); 391 } 392 393 /////////////////////////////////////////////////////////////////////////////// 394 395 static inline SkMScalar det2x2(double m00, double m01, double m10, double m11) { 396 return SkDoubleToMScalar(m00 * m11 - m10 * m01); 397 } 398 399 static inline double det3x3(double m00, double m01, double m02, 400 double m10, double m11, double m12, 401 double m20, double m21, double m22) { 402 return m00 * det2x2(m11, m12, m21, m22) - 403 m10 * det2x2(m01, m02, m21, m22) + 404 m20 * det2x2(m01, m02, m11, m12); 405 } 406 407 /** We always perform the calculation in doubles, to avoid prematurely losing 408 precision along the way. This relies on the compiler automatically 409 promoting our SkMScalar values to double (if needed). 410 */ 411 double SkMatrix44::determinant() const { 412 if (this->isIdentity()) { 413 return 1; 414 } 415 if (this->isScaleTranslate()) { 416 return fMat[0][0] * fMat[1][1] * fMat[2][2] * fMat[3][3]; 417 } 418 419 double a00 = fMat[0][0]; 420 double a01 = fMat[0][1]; 421 double a02 = fMat[0][2]; 422 double a03 = fMat[0][3]; 423 double a10 = fMat[1][0]; 424 double a11 = fMat[1][1]; 425 double a12 = fMat[1][2]; 426 double a13 = fMat[1][3]; 427 double a20 = fMat[2][0]; 428 double a21 = fMat[2][1]; 429 double a22 = fMat[2][2]; 430 double a23 = fMat[2][3]; 431 double a30 = fMat[3][0]; 432 double a31 = fMat[3][1]; 433 double a32 = fMat[3][2]; 434 double a33 = fMat[3][3]; 435 436 double b00 = a00 * a11 - a01 * a10; 437 double b01 = a00 * a12 - a02 * a10; 438 double b02 = a00 * a13 - a03 * a10; 439 double b03 = a01 * a12 - a02 * a11; 440 double b04 = a01 * a13 - a03 * a11; 441 double b05 = a02 * a13 - a03 * a12; 442 double b06 = a20 * a31 - a21 * a30; 443 double b07 = a20 * a32 - a22 * a30; 444 double b08 = a20 * a33 - a23 * a30; 445 double b09 = a21 * a32 - a22 * a31; 446 double b10 = a21 * a33 - a23 * a31; 447 double b11 = a22 * a33 - a23 * a32; 448 449 // Calculate the determinant 450 return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; 451 } 452 453 /////////////////////////////////////////////////////////////////////////////// 454 455 // just picked a small value. not sure how to pick the "right" one 456 #define TOO_SMALL_FOR_DETERMINANT (1.e-8) 457 458 static inline double dabs(double x) { 459 if (x < 0) { 460 x = -x; 461 } 462 return x; 463 } 464 465 bool SkMatrix44::invert(SkMatrix44* inverse) const { 466 if (this->isIdentity()) { 467 if (inverse) { 468 *inverse = *this; 469 return true; 470 } 471 } 472 if (this->isTranslate()) { 473 if (inverse) { 474 inverse->setTranslate(-fMat[3][0], -fMat[3][1], -fMat[3][2]); 475 } 476 return true; 477 } 478 if (this->isScaleTranslate()) { 479 if (0 == fMat[0][0] * fMat[1][1] * fMat[2][2]) { 480 return false; 481 } 482 if (inverse) { 483 sk_bzero(inverse->fMat, sizeof(inverse->fMat)); 484 485 inverse->fMat[3][0] = -fMat[3][0] / fMat[0][0]; 486 inverse->fMat[3][1] = -fMat[3][1] / fMat[1][1]; 487 inverse->fMat[3][2] = -fMat[3][2] / fMat[2][2]; 488 489 inverse->fMat[0][0] = 1 / fMat[0][0]; 490 inverse->fMat[1][1] = 1 / fMat[1][1]; 491 inverse->fMat[2][2] = 1 / fMat[2][2]; 492 inverse->fMat[3][3] = 1; 493 494 inverse->setTypeMask(this->getType()); 495 } 496 return true; 497 } 498 499 double a00 = fMat[0][0]; 500 double a01 = fMat[0][1]; 501 double a02 = fMat[0][2]; 502 double a03 = fMat[0][3]; 503 double a10 = fMat[1][0]; 504 double a11 = fMat[1][1]; 505 double a12 = fMat[1][2]; 506 double a13 = fMat[1][3]; 507 double a20 = fMat[2][0]; 508 double a21 = fMat[2][1]; 509 double a22 = fMat[2][2]; 510 double a23 = fMat[2][3]; 511 double a30 = fMat[3][0]; 512 double a31 = fMat[3][1]; 513 double a32 = fMat[3][2]; 514 double a33 = fMat[3][3]; 515 516 double b00 = a00 * a11 - a01 * a10; 517 double b01 = a00 * a12 - a02 * a10; 518 double b02 = a00 * a13 - a03 * a10; 519 double b03 = a01 * a12 - a02 * a11; 520 double b04 = a01 * a13 - a03 * a11; 521 double b05 = a02 * a13 - a03 * a12; 522 double b06 = a20 * a31 - a21 * a30; 523 double b07 = a20 * a32 - a22 * a30; 524 double b08 = a20 * a33 - a23 * a30; 525 double b09 = a21 * a32 - a22 * a31; 526 double b10 = a21 * a33 - a23 * a31; 527 double b11 = a22 * a33 - a23 * a32; 528 529 // Calculate the determinant 530 double det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; 531 532 if (dabs(det) < TOO_SMALL_FOR_DETERMINANT) { 533 return false; 534 } 535 if (NULL == inverse) { 536 return true; 537 } 538 double invdet = 1.0 / det; 539 540 b00 *= invdet; 541 b01 *= invdet; 542 b02 *= invdet; 543 b03 *= invdet; 544 b04 *= invdet; 545 b05 *= invdet; 546 b06 *= invdet; 547 b07 *= invdet; 548 b08 *= invdet; 549 b09 *= invdet; 550 b10 *= invdet; 551 b11 *= invdet; 552 553 inverse->fMat[0][0] = SkDoubleToMScalar(a11 * b11 - a12 * b10 + a13 * b09); 554 inverse->fMat[0][1] = SkDoubleToMScalar(a02 * b10 - a01 * b11 - a03 * b09); 555 inverse->fMat[0][2] = SkDoubleToMScalar(a31 * b05 - a32 * b04 + a33 * b03); 556 inverse->fMat[0][3] = SkDoubleToMScalar(a22 * b04 - a21 * b05 - a23 * b03); 557 inverse->fMat[1][0] = SkDoubleToMScalar(a12 * b08 - a10 * b11 - a13 * b07); 558 inverse->fMat[1][1] = SkDoubleToMScalar(a00 * b11 - a02 * b08 + a03 * b07); 559 inverse->fMat[1][2] = SkDoubleToMScalar(a32 * b02 - a30 * b05 - a33 * b01); 560 inverse->fMat[1][3] = SkDoubleToMScalar(a20 * b05 - a22 * b02 + a23 * b01); 561 inverse->fMat[2][0] = SkDoubleToMScalar(a10 * b10 - a11 * b08 + a13 * b06); 562 inverse->fMat[2][1] = SkDoubleToMScalar(a01 * b08 - a00 * b10 - a03 * b06); 563 inverse->fMat[2][2] = SkDoubleToMScalar(a30 * b04 - a31 * b02 + a33 * b00); 564 inverse->fMat[2][3] = SkDoubleToMScalar(a21 * b02 - a20 * b04 - a23 * b00); 565 inverse->fMat[3][0] = SkDoubleToMScalar(a11 * b07 - a10 * b09 - a12 * b06); 566 inverse->fMat[3][1] = SkDoubleToMScalar(a00 * b09 - a01 * b07 + a02 * b06); 567 inverse->fMat[3][2] = SkDoubleToMScalar(a31 * b01 - a30 * b03 - a32 * b00); 568 inverse->fMat[3][3] = SkDoubleToMScalar(a20 * b03 - a21 * b01 + a22 * b00); 569 inverse->dirtyTypeMask(); 570 571 inverse->dirtyTypeMask(); 572 return true; 573 } 574 575 /////////////////////////////////////////////////////////////////////////////// 576 577 void SkMatrix44::transpose() { 578 SkTSwap(fMat[0][1], fMat[1][0]); 579 SkTSwap(fMat[0][2], fMat[2][0]); 580 SkTSwap(fMat[0][3], fMat[3][0]); 581 SkTSwap(fMat[1][2], fMat[2][1]); 582 SkTSwap(fMat[1][3], fMat[3][1]); 583 SkTSwap(fMat[2][3], fMat[3][2]); 584 585 if (!this->isTriviallyIdentity()) { 586 this->dirtyTypeMask(); 587 } 588 } 589 590 /////////////////////////////////////////////////////////////////////////////// 591 592 void SkMatrix44::mapScalars(const SkScalar src[4], SkScalar dst[4]) const { 593 SkScalar storage[4]; 594 SkScalar* result = (src == dst) ? storage : dst; 595 596 for (int i = 0; i < 4; i++) { 597 SkMScalar value = 0; 598 for (int j = 0; j < 4; j++) { 599 value += fMat[j][i] * src[j]; 600 } 601 result[i] = SkMScalarToScalar(value); 602 } 603 604 if (storage == result) { 605 memcpy(dst, storage, sizeof(storage)); 606 } 607 } 608 609 #ifdef SK_MSCALAR_IS_DOUBLE 610 611 void SkMatrix44::mapMScalars(const SkMScalar src[4], SkMScalar dst[4]) const { 612 SkMScalar storage[4]; 613 SkMScalar* result = (src == dst) ? storage : dst; 614 615 for (int i = 0; i < 4; i++) { 616 SkMScalar value = 0; 617 for (int j = 0; j < 4; j++) { 618 value += fMat[j][i] * src[j]; 619 } 620 result[i] = value; 621 } 622 623 if (storage == result) { 624 memcpy(dst, storage, sizeof(storage)); 625 } 626 } 627 628 #endif 629 630 typedef void (*Map2Procf)(const SkMScalar mat[][4], const float src2[], int count, float dst4[]); 631 typedef void (*Map2Procd)(const SkMScalar mat[][4], const double src2[], int count, double dst4[]); 632 633 static void map2_if(const SkMScalar mat[][4], const float* SK_RESTRICT src2, 634 int count, float* SK_RESTRICT dst4) { 635 for (int i = 0; i < count; ++i) { 636 dst4[0] = src2[0]; 637 dst4[1] = src2[1]; 638 dst4[2] = 0; 639 dst4[3] = 1; 640 src2 += 2; 641 dst4 += 4; 642 } 643 } 644 645 static void map2_id(const SkMScalar mat[][4], const double* SK_RESTRICT src2, 646 int count, double* SK_RESTRICT dst4) { 647 for (int i = 0; i < count; ++i) { 648 dst4[0] = src2[0]; 649 dst4[1] = src2[1]; 650 dst4[2] = 0; 651 dst4[3] = 1; 652 src2 += 2; 653 dst4 += 4; 654 } 655 } 656 657 static void map2_tf(const SkMScalar mat[][4], const float* SK_RESTRICT src2, 658 int count, float* SK_RESTRICT dst4) { 659 const float mat30 = SkMScalarToFloat(mat[3][0]); 660 const float mat31 = SkMScalarToFloat(mat[3][1]); 661 const float mat32 = SkMScalarToFloat(mat[3][2]); 662 for (int n = 0; n < count; ++n) { 663 dst4[0] = src2[0] + mat30; 664 dst4[1] = src2[1] + mat31; 665 dst4[2] = mat32; 666 dst4[3] = 1; 667 src2 += 2; 668 dst4 += 4; 669 } 670 } 671 672 static void map2_td(const SkMScalar mat[][4], const double* SK_RESTRICT src2, 673 int count, double* SK_RESTRICT dst4) { 674 for (int n = 0; n < count; ++n) { 675 dst4[0] = src2[0] + mat[3][0]; 676 dst4[1] = src2[1] + mat[3][1]; 677 dst4[2] = mat[3][2]; 678 dst4[3] = 1; 679 src2 += 2; 680 dst4 += 4; 681 } 682 } 683 684 static void map2_sf(const SkMScalar mat[][4], const float* SK_RESTRICT src2, 685 int count, float* SK_RESTRICT dst4) { 686 const float mat32 = SkMScalarToFloat(mat[3][2]); 687 for (int n = 0; n < count; ++n) { 688 dst4[0] = SkMScalarToFloat(mat[0][0] * src2[0] + mat[3][0]); 689 dst4[1] = SkMScalarToFloat(mat[1][1] * src2[1] + mat[3][1]); 690 dst4[2] = mat32; 691 dst4[3] = 1; 692 src2 += 2; 693 dst4 += 4; 694 } 695 } 696 697 static void map2_sd(const SkMScalar mat[][4], const double* SK_RESTRICT src2, 698 int count, double* SK_RESTRICT dst4) { 699 for (int n = 0; n < count; ++n) { 700 dst4[0] = mat[0][0] * src2[0] + mat[3][0]; 701 dst4[1] = mat[1][1] * src2[1] + mat[3][1]; 702 dst4[2] = mat[3][2]; 703 dst4[3] = 1; 704 src2 += 2; 705 dst4 += 4; 706 } 707 } 708 709 static void map2_af(const SkMScalar mat[][4], const float* SK_RESTRICT src2, 710 int count, float* SK_RESTRICT dst4) { 711 double r; 712 for (int n = 0; n < count; ++n) { 713 double sx = src2[0]; 714 double sy = src2[1]; 715 r = mat[0][0] * sx + mat[1][0] * sy + mat[3][0]; 716 dst4[0] = SkMScalarToFloat(r); 717 r = mat[0][1] * sx + mat[1][1] * sy + mat[3][1]; 718 dst4[1] = SkMScalarToFloat(r); 719 r = mat[0][2] * sx + mat[1][2] * sy + mat[3][2]; 720 dst4[2] = SkMScalarToFloat(r); 721 dst4[3] = 1; 722 src2 += 2; 723 dst4 += 4; 724 } 725 } 726 727 static void map2_ad(const SkMScalar mat[][4], const double* SK_RESTRICT src2, 728 int count, double* SK_RESTRICT dst4) { 729 for (int n = 0; n < count; ++n) { 730 double sx = src2[0]; 731 double sy = src2[1]; 732 dst4[0] = mat[0][0] * sx + mat[1][0] * sy + mat[3][0]; 733 dst4[1] = mat[0][1] * sx + mat[1][1] * sy + mat[3][1]; 734 dst4[2] = mat[0][2] * sx + mat[1][2] * sy + mat[3][2]; 735 dst4[3] = 1; 736 src2 += 2; 737 dst4 += 4; 738 } 739 } 740 741 static void map2_pf(const SkMScalar mat[][4], const float* SK_RESTRICT src2, 742 int count, float* SK_RESTRICT dst4) { 743 double r; 744 for (int n = 0; n < count; ++n) { 745 double sx = src2[0]; 746 double sy = src2[1]; 747 for (int i = 0; i < 4; i++) { 748 r = mat[0][i] * sx + mat[1][i] * sy + mat[3][i]; 749 dst4[i] = SkMScalarToFloat(r); 750 } 751 src2 += 2; 752 dst4 += 4; 753 } 754 } 755 756 static void map2_pd(const SkMScalar mat[][4], const double* SK_RESTRICT src2, 757 int count, double* SK_RESTRICT dst4) { 758 for (int n = 0; n < count; ++n) { 759 double sx = src2[0]; 760 double sy = src2[1]; 761 for (int i = 0; i < 4; i++) { 762 dst4[i] = mat[0][i] * sx + mat[1][i] * sy + mat[3][i]; 763 } 764 src2 += 2; 765 dst4 += 4; 766 } 767 } 768 769 void SkMatrix44::map2(const float src2[], int count, float dst4[]) const { 770 static const Map2Procf gProc[] = { 771 map2_if, map2_tf, map2_sf, map2_sf, map2_af, map2_af, map2_af, map2_af 772 }; 773 774 TypeMask mask = this->getType(); 775 Map2Procf proc = (mask & kPerspective_Mask) ? map2_pf : gProc[mask]; 776 proc(fMat, src2, count, dst4); 777 } 778 779 void SkMatrix44::map2(const double src2[], int count, double dst4[]) const { 780 static const Map2Procd gProc[] = { 781 map2_id, map2_td, map2_sd, map2_sd, map2_ad, map2_ad, map2_ad, map2_ad 782 }; 783 784 TypeMask mask = this->getType(); 785 Map2Procd proc = (mask & kPerspective_Mask) ? map2_pd : gProc[mask]; 786 proc(fMat, src2, count, dst4); 787 } 788 789 /////////////////////////////////////////////////////////////////////////////// 790 791 void SkMatrix44::dump() const { 792 static const char* format = 793 "[%g %g %g %g][%g %g %g %g][%g %g %g %g][%g %g %g %g]\n"; 794 #if 0 795 SkDebugf(format, 796 fMat[0][0], fMat[1][0], fMat[2][0], fMat[3][0], 797 fMat[0][1], fMat[1][1], fMat[2][1], fMat[3][1], 798 fMat[0][2], fMat[1][2], fMat[2][2], fMat[3][2], 799 fMat[0][3], fMat[1][3], fMat[2][3], fMat[3][3]); 800 #else 801 SkDebugf(format, 802 fMat[0][0], fMat[0][1], fMat[0][2], fMat[0][3], 803 fMat[1][0], fMat[1][1], fMat[1][2], fMat[1][3], 804 fMat[2][0], fMat[2][1], fMat[2][2], fMat[2][3], 805 fMat[3][0], fMat[3][1], fMat[3][2], fMat[3][3]); 806 #endif 807 } 808 809 /////////////////////////////////////////////////////////////////////////////// 810 811 // TODO: make this support src' perspective elements 812 // 813 static void initFromMatrix(SkMScalar dst[4][4], const SkMatrix& src) { 814 sk_bzero(dst, 16 * sizeof(SkMScalar)); 815 dst[0][0] = SkScalarToMScalar(src[SkMatrix::kMScaleX]); 816 dst[1][0] = SkScalarToMScalar(src[SkMatrix::kMSkewX]); 817 dst[3][0] = SkScalarToMScalar(src[SkMatrix::kMTransX]); 818 dst[0][1] = SkScalarToMScalar(src[SkMatrix::kMSkewY]); 819 dst[1][1] = SkScalarToMScalar(src[SkMatrix::kMScaleY]); 820 dst[3][1] = SkScalarToMScalar(src[SkMatrix::kMTransY]); 821 dst[2][2] = dst[3][3] = 1; 822 } 823 824 SkMatrix44::SkMatrix44(const SkMatrix& src) { 825 initFromMatrix(fMat, src); 826 } 827 828 SkMatrix44& SkMatrix44::operator=(const SkMatrix& src) { 829 initFromMatrix(fMat, src); 830 831 if (src.isIdentity()) { 832 this->setTypeMask(kIdentity_Mask); 833 } else { 834 this->dirtyTypeMask(); 835 } 836 return *this; 837 } 838 839 // TODO: make this support our perspective elements 840 // 841 SkMatrix44::operator SkMatrix() const { 842 SkMatrix dst; 843 dst.reset(); // setup our perspective correctly for identity 844 845 dst[SkMatrix::kMScaleX] = SkMScalarToScalar(fMat[0][0]); 846 dst[SkMatrix::kMSkewX] = SkMScalarToScalar(fMat[1][0]); 847 dst[SkMatrix::kMTransX] = SkMScalarToScalar(fMat[3][0]); 848 849 dst[SkMatrix::kMSkewY] = SkMScalarToScalar(fMat[0][1]); 850 dst[SkMatrix::kMScaleY] = SkMScalarToScalar(fMat[1][1]); 851 dst[SkMatrix::kMTransY] = SkMScalarToScalar(fMat[3][1]); 852 853 return dst; 854 } 855