1 /* 2 * Copyright 2006 The Android Open Source Project 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 "SkMatrix.h" 9 #include "SkFloatBits.h" 10 #include "SkRSXform.h" 11 #include "SkString.h" 12 #include "SkNx.h" 13 #include "SkOpts.h" 14 15 #include <stddef.h> 16 17 static void normalize_perspective(SkScalar mat[9]) { 18 // If it was interesting to never store the last element, we could divide all 8 other 19 // elements here by the 9th, making it 1.0... 20 // 21 // When SkScalar was SkFixed, we would sometimes rescale the entire matrix to keep its 22 // component values from getting too large. This is not a concern when using floats/doubles, 23 // so we do nothing now. 24 25 // Disable this for now, but it could be enabled. 26 #if 0 27 if (0 == mat[SkMatrix::kMPersp0] && 0 == mat[SkMatrix::kMPersp1]) { 28 SkScalar p2 = mat[SkMatrix::kMPersp2]; 29 if (p2 != 0 && p2 != 1) { 30 double inv = 1.0 / p2; 31 for (int i = 0; i < 6; ++i) { 32 mat[i] = SkDoubleToScalar(mat[i] * inv); 33 } 34 mat[SkMatrix::kMPersp2] = 1; 35 } 36 } 37 #endif 38 } 39 40 // In a few places, we performed the following 41 // a * b + c * d + e 42 // as 43 // a * b + (c * d + e) 44 // 45 // sdot and scross are indended to capture these compound operations into a 46 // function, with an eye toward considering upscaling the intermediates to 47 // doubles for more precision (as we do in concat and invert). 48 // 49 // However, these few lines that performed the last add before the "dot", cause 50 // tiny image differences, so we guard that change until we see the impact on 51 // chrome's layouttests. 52 // 53 #define SK_LEGACY_MATRIX_MATH_ORDER 54 55 static inline float SkDoubleToFloat(double x) { 56 return static_cast<float>(x); 57 } 58 59 /* [scale-x skew-x trans-x] [X] [X'] 60 [skew-y scale-y trans-y] * [Y] = [Y'] 61 [persp-0 persp-1 persp-2] [1] [1 ] 62 */ 63 64 void SkMatrix::reset() { 65 fMat[kMScaleX] = fMat[kMScaleY] = fMat[kMPersp2] = 1; 66 fMat[kMSkewX] = fMat[kMSkewY] = 67 fMat[kMTransX] = fMat[kMTransY] = 68 fMat[kMPersp0] = fMat[kMPersp1] = 0; 69 this->setTypeMask(kIdentity_Mask | kRectStaysRect_Mask); 70 } 71 72 void SkMatrix::set9(const SkScalar buffer[]) { 73 memcpy(fMat, buffer, 9 * sizeof(SkScalar)); 74 normalize_perspective(fMat); 75 this->setTypeMask(kUnknown_Mask); 76 } 77 78 void SkMatrix::setAffine(const SkScalar buffer[]) { 79 fMat[kMScaleX] = buffer[kAScaleX]; 80 fMat[kMSkewX] = buffer[kASkewX]; 81 fMat[kMTransX] = buffer[kATransX]; 82 fMat[kMSkewY] = buffer[kASkewY]; 83 fMat[kMScaleY] = buffer[kAScaleY]; 84 fMat[kMTransY] = buffer[kATransY]; 85 fMat[kMPersp0] = 0; 86 fMat[kMPersp1] = 0; 87 fMat[kMPersp2] = 1; 88 this->setTypeMask(kUnknown_Mask); 89 } 90 91 // this guy aligns with the masks, so we can compute a mask from a varaible 0/1 92 enum { 93 kTranslate_Shift, 94 kScale_Shift, 95 kAffine_Shift, 96 kPerspective_Shift, 97 kRectStaysRect_Shift 98 }; 99 100 static const int32_t kScalar1Int = 0x3f800000; 101 102 uint8_t SkMatrix::computePerspectiveTypeMask() const { 103 // Benchmarking suggests that replacing this set of SkScalarAs2sCompliment 104 // is a win, but replacing those below is not. We don't yet understand 105 // that result. 106 if (fMat[kMPersp0] != 0 || fMat[kMPersp1] != 0 || fMat[kMPersp2] != 1) { 107 // If this is a perspective transform, we return true for all other 108 // transform flags - this does not disable any optimizations, respects 109 // the rule that the type mask must be conservative, and speeds up 110 // type mask computation. 111 return SkToU8(kORableMasks); 112 } 113 114 return SkToU8(kOnlyPerspectiveValid_Mask | kUnknown_Mask); 115 } 116 117 uint8_t SkMatrix::computeTypeMask() const { 118 unsigned mask = 0; 119 120 if (fMat[kMPersp0] != 0 || fMat[kMPersp1] != 0 || fMat[kMPersp2] != 1) { 121 // Once it is determined that that this is a perspective transform, 122 // all other flags are moot as far as optimizations are concerned. 123 return SkToU8(kORableMasks); 124 } 125 126 if (fMat[kMTransX] != 0 || fMat[kMTransY] != 0) { 127 mask |= kTranslate_Mask; 128 } 129 130 int m00 = SkScalarAs2sCompliment(fMat[SkMatrix::kMScaleX]); 131 int m01 = SkScalarAs2sCompliment(fMat[SkMatrix::kMSkewX]); 132 int m10 = SkScalarAs2sCompliment(fMat[SkMatrix::kMSkewY]); 133 int m11 = SkScalarAs2sCompliment(fMat[SkMatrix::kMScaleY]); 134 135 if (m01 | m10) { 136 // The skew components may be scale-inducing, unless we are dealing 137 // with a pure rotation. Testing for a pure rotation is expensive, 138 // so we opt for being conservative by always setting the scale bit. 139 // along with affine. 140 // By doing this, we are also ensuring that matrices have the same 141 // type masks as their inverses. 142 mask |= kAffine_Mask | kScale_Mask; 143 144 // For rectStaysRect, in the affine case, we only need check that 145 // the primary diagonal is all zeros and that the secondary diagonal 146 // is all non-zero. 147 148 // map non-zero to 1 149 m01 = m01 != 0; 150 m10 = m10 != 0; 151 152 int dp0 = 0 == (m00 | m11) ; // true if both are 0 153 int ds1 = m01 & m10; // true if both are 1 154 155 mask |= (dp0 & ds1) << kRectStaysRect_Shift; 156 } else { 157 // Only test for scale explicitly if not affine, since affine sets the 158 // scale bit. 159 if ((m00 ^ kScalar1Int) | (m11 ^ kScalar1Int)) { 160 mask |= kScale_Mask; 161 } 162 163 // Not affine, therefore we already know secondary diagonal is 164 // all zeros, so we just need to check that primary diagonal is 165 // all non-zero. 166 167 // map non-zero to 1 168 m00 = m00 != 0; 169 m11 = m11 != 0; 170 171 // record if the (p)rimary diagonal is all non-zero 172 mask |= (m00 & m11) << kRectStaysRect_Shift; 173 } 174 175 return SkToU8(mask); 176 } 177 178 /////////////////////////////////////////////////////////////////////////////// 179 180 bool operator==(const SkMatrix& a, const SkMatrix& b) { 181 const SkScalar* SK_RESTRICT ma = a.fMat; 182 const SkScalar* SK_RESTRICT mb = b.fMat; 183 184 return ma[0] == mb[0] && ma[1] == mb[1] && ma[2] == mb[2] && 185 ma[3] == mb[3] && ma[4] == mb[4] && ma[5] == mb[5] && 186 ma[6] == mb[6] && ma[7] == mb[7] && ma[8] == mb[8]; 187 } 188 189 /////////////////////////////////////////////////////////////////////////////// 190 191 // helper function to determine if upper-left 2x2 of matrix is degenerate 192 static inline bool is_degenerate_2x2(SkScalar scaleX, SkScalar skewX, 193 SkScalar skewY, SkScalar scaleY) { 194 SkScalar perp_dot = scaleX*scaleY - skewX*skewY; 195 return SkScalarNearlyZero(perp_dot, SK_ScalarNearlyZero*SK_ScalarNearlyZero); 196 } 197 198 /////////////////////////////////////////////////////////////////////////////// 199 200 bool SkMatrix::isSimilarity(SkScalar tol) const { 201 // if identity or translate matrix 202 TypeMask mask = this->getType(); 203 if (mask <= kTranslate_Mask) { 204 return true; 205 } 206 if (mask & kPerspective_Mask) { 207 return false; 208 } 209 210 SkScalar mx = fMat[kMScaleX]; 211 SkScalar my = fMat[kMScaleY]; 212 // if no skew, can just compare scale factors 213 if (!(mask & kAffine_Mask)) { 214 return !SkScalarNearlyZero(mx) && SkScalarNearlyEqual(SkScalarAbs(mx), SkScalarAbs(my)); 215 } 216 SkScalar sx = fMat[kMSkewX]; 217 SkScalar sy = fMat[kMSkewY]; 218 219 if (is_degenerate_2x2(mx, sx, sy, my)) { 220 return false; 221 } 222 223 // upper 2x2 is rotation/reflection + uniform scale if basis vectors 224 // are 90 degree rotations of each other 225 return (SkScalarNearlyEqual(mx, my, tol) && SkScalarNearlyEqual(sx, -sy, tol)) 226 || (SkScalarNearlyEqual(mx, -my, tol) && SkScalarNearlyEqual(sx, sy, tol)); 227 } 228 229 bool SkMatrix::preservesRightAngles(SkScalar tol) const { 230 TypeMask mask = this->getType(); 231 232 if (mask <= kTranslate_Mask) { 233 // identity, translate and/or scale 234 return true; 235 } 236 if (mask & kPerspective_Mask) { 237 return false; 238 } 239 240 SkASSERT(mask & (kAffine_Mask | kScale_Mask)); 241 242 SkScalar mx = fMat[kMScaleX]; 243 SkScalar my = fMat[kMScaleY]; 244 SkScalar sx = fMat[kMSkewX]; 245 SkScalar sy = fMat[kMSkewY]; 246 247 if (is_degenerate_2x2(mx, sx, sy, my)) { 248 return false; 249 } 250 251 // upper 2x2 is scale + rotation/reflection if basis vectors are orthogonal 252 SkVector vec[2]; 253 vec[0].set(mx, sy); 254 vec[1].set(sx, my); 255 256 return SkScalarNearlyZero(vec[0].dot(vec[1]), SkScalarSquare(tol)); 257 } 258 259 /////////////////////////////////////////////////////////////////////////////// 260 261 static inline SkScalar sdot(SkScalar a, SkScalar b, SkScalar c, SkScalar d) { 262 return a * b + c * d; 263 } 264 265 static inline SkScalar sdot(SkScalar a, SkScalar b, SkScalar c, SkScalar d, 266 SkScalar e, SkScalar f) { 267 return a * b + c * d + e * f; 268 } 269 270 static inline SkScalar scross(SkScalar a, SkScalar b, SkScalar c, SkScalar d) { 271 return a * b - c * d; 272 } 273 274 void SkMatrix::setTranslate(SkScalar dx, SkScalar dy) { 275 if (dx || dy) { 276 fMat[kMTransX] = dx; 277 fMat[kMTransY] = dy; 278 279 fMat[kMScaleX] = fMat[kMScaleY] = fMat[kMPersp2] = 1; 280 fMat[kMSkewX] = fMat[kMSkewY] = 281 fMat[kMPersp0] = fMat[kMPersp1] = 0; 282 283 this->setTypeMask(kTranslate_Mask | kRectStaysRect_Mask); 284 } else { 285 this->reset(); 286 } 287 } 288 289 void SkMatrix::preTranslate(SkScalar dx, SkScalar dy) { 290 if (!dx && !dy) { 291 return; 292 } 293 294 if (this->hasPerspective()) { 295 SkMatrix m; 296 m.setTranslate(dx, dy); 297 this->preConcat(m); 298 } else { 299 fMat[kMTransX] += sdot(fMat[kMScaleX], dx, fMat[kMSkewX], dy); 300 fMat[kMTransY] += sdot(fMat[kMSkewY], dx, fMat[kMScaleY], dy); 301 this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); 302 } 303 } 304 305 void SkMatrix::postTranslate(SkScalar dx, SkScalar dy) { 306 if (!dx && !dy) { 307 return; 308 } 309 310 if (this->hasPerspective()) { 311 SkMatrix m; 312 m.setTranslate(dx, dy); 313 this->postConcat(m); 314 } else { 315 fMat[kMTransX] += dx; 316 fMat[kMTransY] += dy; 317 this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); 318 } 319 } 320 321 /////////////////////////////////////////////////////////////////////////////// 322 323 void SkMatrix::setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) { 324 if (1 == sx && 1 == sy) { 325 this->reset(); 326 } else { 327 this->setScaleTranslate(sx, sy, px - sx * px, py - sy * py); 328 } 329 } 330 331 void SkMatrix::setScale(SkScalar sx, SkScalar sy) { 332 if (1 == sx && 1 == sy) { 333 this->reset(); 334 } else { 335 fMat[kMScaleX] = sx; 336 fMat[kMScaleY] = sy; 337 fMat[kMPersp2] = 1; 338 339 fMat[kMTransX] = fMat[kMTransY] = 340 fMat[kMSkewX] = fMat[kMSkewY] = 341 fMat[kMPersp0] = fMat[kMPersp1] = 0; 342 343 this->setTypeMask(kScale_Mask | kRectStaysRect_Mask); 344 } 345 } 346 347 bool SkMatrix::setIDiv(int divx, int divy) { 348 if (!divx || !divy) { 349 return false; 350 } 351 this->setScale(SkScalarInvert(divx), SkScalarInvert(divy)); 352 return true; 353 } 354 355 void SkMatrix::preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) { 356 if (1 == sx && 1 == sy) { 357 return; 358 } 359 360 SkMatrix m; 361 m.setScale(sx, sy, px, py); 362 this->preConcat(m); 363 } 364 365 void SkMatrix::preScale(SkScalar sx, SkScalar sy) { 366 if (1 == sx && 1 == sy) { 367 return; 368 } 369 370 // the assumption is that these multiplies are very cheap, and that 371 // a full concat and/or just computing the matrix type is more expensive. 372 // Also, the fixed-point case checks for overflow, but the float doesn't, 373 // so we can get away with these blind multiplies. 374 375 fMat[kMScaleX] *= sx; 376 fMat[kMSkewY] *= sx; 377 fMat[kMPersp0] *= sx; 378 379 fMat[kMSkewX] *= sy; 380 fMat[kMScaleY] *= sy; 381 fMat[kMPersp1] *= sy; 382 383 // Attempt to simplify our type when applying an inverse scale. 384 // TODO: The persp/affine preconditions are in place to keep the mask consistent with 385 // what computeTypeMask() would produce (persp/skew always implies kScale). 386 // We should investigate whether these flag dependencies are truly needed. 387 if (fMat[kMScaleX] == 1 && fMat[kMScaleY] == 1 388 && !(fTypeMask & (kPerspective_Mask | kAffine_Mask))) { 389 this->clearTypeMask(kScale_Mask); 390 } else { 391 this->orTypeMask(kScale_Mask); 392 } 393 } 394 395 void SkMatrix::postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) { 396 if (1 == sx && 1 == sy) { 397 return; 398 } 399 SkMatrix m; 400 m.setScale(sx, sy, px, py); 401 this->postConcat(m); 402 } 403 404 void SkMatrix::postScale(SkScalar sx, SkScalar sy) { 405 if (1 == sx && 1 == sy) { 406 return; 407 } 408 SkMatrix m; 409 m.setScale(sx, sy); 410 this->postConcat(m); 411 } 412 413 // this guy perhaps can go away, if we have a fract/high-precision way to 414 // scale matrices 415 bool SkMatrix::postIDiv(int divx, int divy) { 416 if (divx == 0 || divy == 0) { 417 return false; 418 } 419 420 const float invX = 1.f / divx; 421 const float invY = 1.f / divy; 422 423 fMat[kMScaleX] *= invX; 424 fMat[kMSkewX] *= invX; 425 fMat[kMTransX] *= invX; 426 427 fMat[kMScaleY] *= invY; 428 fMat[kMSkewY] *= invY; 429 fMat[kMTransY] *= invY; 430 431 this->setTypeMask(kUnknown_Mask); 432 return true; 433 } 434 435 //////////////////////////////////////////////////////////////////////////////////// 436 437 void SkMatrix::setSinCos(SkScalar sinV, SkScalar cosV, SkScalar px, SkScalar py) { 438 const SkScalar oneMinusCosV = 1 - cosV; 439 440 fMat[kMScaleX] = cosV; 441 fMat[kMSkewX] = -sinV; 442 fMat[kMTransX] = sdot(sinV, py, oneMinusCosV, px); 443 444 fMat[kMSkewY] = sinV; 445 fMat[kMScaleY] = cosV; 446 fMat[kMTransY] = sdot(-sinV, px, oneMinusCosV, py); 447 448 fMat[kMPersp0] = fMat[kMPersp1] = 0; 449 fMat[kMPersp2] = 1; 450 451 this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); 452 } 453 454 SkMatrix& SkMatrix::setRSXform(const SkRSXform& xform) { 455 fMat[kMScaleX] = xform.fSCos; 456 fMat[kMSkewX] = -xform.fSSin; 457 fMat[kMTransX] = xform.fTx; 458 459 fMat[kMSkewY] = xform.fSSin; 460 fMat[kMScaleY] = xform.fSCos; 461 fMat[kMTransY] = xform.fTy; 462 463 fMat[kMPersp0] = fMat[kMPersp1] = 0; 464 fMat[kMPersp2] = 1; 465 466 this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); 467 return *this; 468 } 469 470 void SkMatrix::setSinCos(SkScalar sinV, SkScalar cosV) { 471 fMat[kMScaleX] = cosV; 472 fMat[kMSkewX] = -sinV; 473 fMat[kMTransX] = 0; 474 475 fMat[kMSkewY] = sinV; 476 fMat[kMScaleY] = cosV; 477 fMat[kMTransY] = 0; 478 479 fMat[kMPersp0] = fMat[kMPersp1] = 0; 480 fMat[kMPersp2] = 1; 481 482 this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); 483 } 484 485 void SkMatrix::setRotate(SkScalar degrees, SkScalar px, SkScalar py) { 486 SkScalar sinV, cosV; 487 sinV = SkScalarSinCos(SkDegreesToRadians(degrees), &cosV); 488 this->setSinCos(sinV, cosV, px, py); 489 } 490 491 void SkMatrix::setRotate(SkScalar degrees) { 492 SkScalar sinV, cosV; 493 sinV = SkScalarSinCos(SkDegreesToRadians(degrees), &cosV); 494 this->setSinCos(sinV, cosV); 495 } 496 497 void SkMatrix::preRotate(SkScalar degrees, SkScalar px, SkScalar py) { 498 SkMatrix m; 499 m.setRotate(degrees, px, py); 500 this->preConcat(m); 501 } 502 503 void SkMatrix::preRotate(SkScalar degrees) { 504 SkMatrix m; 505 m.setRotate(degrees); 506 this->preConcat(m); 507 } 508 509 void SkMatrix::postRotate(SkScalar degrees, SkScalar px, SkScalar py) { 510 SkMatrix m; 511 m.setRotate(degrees, px, py); 512 this->postConcat(m); 513 } 514 515 void SkMatrix::postRotate(SkScalar degrees) { 516 SkMatrix m; 517 m.setRotate(degrees); 518 this->postConcat(m); 519 } 520 521 //////////////////////////////////////////////////////////////////////////////////// 522 523 void SkMatrix::setSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) { 524 fMat[kMScaleX] = 1; 525 fMat[kMSkewX] = sx; 526 fMat[kMTransX] = -sx * py; 527 528 fMat[kMSkewY] = sy; 529 fMat[kMScaleY] = 1; 530 fMat[kMTransY] = -sy * px; 531 532 fMat[kMPersp0] = fMat[kMPersp1] = 0; 533 fMat[kMPersp2] = 1; 534 535 this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); 536 } 537 538 void SkMatrix::setSkew(SkScalar sx, SkScalar sy) { 539 fMat[kMScaleX] = 1; 540 fMat[kMSkewX] = sx; 541 fMat[kMTransX] = 0; 542 543 fMat[kMSkewY] = sy; 544 fMat[kMScaleY] = 1; 545 fMat[kMTransY] = 0; 546 547 fMat[kMPersp0] = fMat[kMPersp1] = 0; 548 fMat[kMPersp2] = 1; 549 550 this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); 551 } 552 553 void SkMatrix::preSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) { 554 SkMatrix m; 555 m.setSkew(sx, sy, px, py); 556 this->preConcat(m); 557 } 558 559 void SkMatrix::preSkew(SkScalar sx, SkScalar sy) { 560 SkMatrix m; 561 m.setSkew(sx, sy); 562 this->preConcat(m); 563 } 564 565 void SkMatrix::postSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) { 566 SkMatrix m; 567 m.setSkew(sx, sy, px, py); 568 this->postConcat(m); 569 } 570 571 void SkMatrix::postSkew(SkScalar sx, SkScalar sy) { 572 SkMatrix m; 573 m.setSkew(sx, sy); 574 this->postConcat(m); 575 } 576 577 /////////////////////////////////////////////////////////////////////////////// 578 579 bool SkMatrix::setRectToRect(const SkRect& src, const SkRect& dst, ScaleToFit align) { 580 if (src.isEmpty()) { 581 this->reset(); 582 return false; 583 } 584 585 if (dst.isEmpty()) { 586 sk_bzero(fMat, 8 * sizeof(SkScalar)); 587 fMat[kMPersp2] = 1; 588 this->setTypeMask(kScale_Mask | kRectStaysRect_Mask); 589 } else { 590 SkScalar tx, sx = dst.width() / src.width(); 591 SkScalar ty, sy = dst.height() / src.height(); 592 bool xLarger = false; 593 594 if (align != kFill_ScaleToFit) { 595 if (sx > sy) { 596 xLarger = true; 597 sx = sy; 598 } else { 599 sy = sx; 600 } 601 } 602 603 tx = dst.fLeft - src.fLeft * sx; 604 ty = dst.fTop - src.fTop * sy; 605 if (align == kCenter_ScaleToFit || align == kEnd_ScaleToFit) { 606 SkScalar diff; 607 608 if (xLarger) { 609 diff = dst.width() - src.width() * sy; 610 } else { 611 diff = dst.height() - src.height() * sy; 612 } 613 614 if (align == kCenter_ScaleToFit) { 615 diff = SkScalarHalf(diff); 616 } 617 618 if (xLarger) { 619 tx += diff; 620 } else { 621 ty += diff; 622 } 623 } 624 625 this->setScaleTranslate(sx, sy, tx, ty); 626 } 627 return true; 628 } 629 630 /////////////////////////////////////////////////////////////////////////////// 631 632 static inline float muladdmul(float a, float b, float c, float d) { 633 return SkDoubleToFloat((double)a * b + (double)c * d); 634 } 635 636 static inline float rowcol3(const float row[], const float col[]) { 637 return row[0] * col[0] + row[1] * col[3] + row[2] * col[6]; 638 } 639 640 static bool only_scale_and_translate(unsigned mask) { 641 return 0 == (mask & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)); 642 } 643 644 void SkMatrix::setConcat(const SkMatrix& a, const SkMatrix& b) { 645 TypeMask aType = a.getType(); 646 TypeMask bType = b.getType(); 647 648 if (a.isTriviallyIdentity()) { 649 *this = b; 650 } else if (b.isTriviallyIdentity()) { 651 *this = a; 652 } else if (only_scale_and_translate(aType | bType)) { 653 this->setScaleTranslate(a.fMat[kMScaleX] * b.fMat[kMScaleX], 654 a.fMat[kMScaleY] * b.fMat[kMScaleY], 655 a.fMat[kMScaleX] * b.fMat[kMTransX] + a.fMat[kMTransX], 656 a.fMat[kMScaleY] * b.fMat[kMTransY] + a.fMat[kMTransY]); 657 } else { 658 SkMatrix tmp; 659 660 if ((aType | bType) & kPerspective_Mask) { 661 tmp.fMat[kMScaleX] = rowcol3(&a.fMat[0], &b.fMat[0]); 662 tmp.fMat[kMSkewX] = rowcol3(&a.fMat[0], &b.fMat[1]); 663 tmp.fMat[kMTransX] = rowcol3(&a.fMat[0], &b.fMat[2]); 664 tmp.fMat[kMSkewY] = rowcol3(&a.fMat[3], &b.fMat[0]); 665 tmp.fMat[kMScaleY] = rowcol3(&a.fMat[3], &b.fMat[1]); 666 tmp.fMat[kMTransY] = rowcol3(&a.fMat[3], &b.fMat[2]); 667 tmp.fMat[kMPersp0] = rowcol3(&a.fMat[6], &b.fMat[0]); 668 tmp.fMat[kMPersp1] = rowcol3(&a.fMat[6], &b.fMat[1]); 669 tmp.fMat[kMPersp2] = rowcol3(&a.fMat[6], &b.fMat[2]); 670 671 normalize_perspective(tmp.fMat); 672 tmp.setTypeMask(kUnknown_Mask); 673 } else { 674 tmp.fMat[kMScaleX] = muladdmul(a.fMat[kMScaleX], 675 b.fMat[kMScaleX], 676 a.fMat[kMSkewX], 677 b.fMat[kMSkewY]); 678 679 tmp.fMat[kMSkewX] = muladdmul(a.fMat[kMScaleX], 680 b.fMat[kMSkewX], 681 a.fMat[kMSkewX], 682 b.fMat[kMScaleY]); 683 684 tmp.fMat[kMTransX] = muladdmul(a.fMat[kMScaleX], 685 b.fMat[kMTransX], 686 a.fMat[kMSkewX], 687 b.fMat[kMTransY]) + a.fMat[kMTransX]; 688 689 tmp.fMat[kMSkewY] = muladdmul(a.fMat[kMSkewY], 690 b.fMat[kMScaleX], 691 a.fMat[kMScaleY], 692 b.fMat[kMSkewY]); 693 694 tmp.fMat[kMScaleY] = muladdmul(a.fMat[kMSkewY], 695 b.fMat[kMSkewX], 696 a.fMat[kMScaleY], 697 b.fMat[kMScaleY]); 698 699 tmp.fMat[kMTransY] = muladdmul(a.fMat[kMSkewY], 700 b.fMat[kMTransX], 701 a.fMat[kMScaleY], 702 b.fMat[kMTransY]) + a.fMat[kMTransY]; 703 704 tmp.fMat[kMPersp0] = 0; 705 tmp.fMat[kMPersp1] = 0; 706 tmp.fMat[kMPersp2] = 1; 707 //SkDebugf("Concat mat non-persp type: %d\n", tmp.getType()); 708 //SkASSERT(!(tmp.getType() & kPerspective_Mask)); 709 tmp.setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); 710 } 711 *this = tmp; 712 } 713 } 714 715 void SkMatrix::preConcat(const SkMatrix& mat) { 716 // check for identity first, so we don't do a needless copy of ourselves 717 // to ourselves inside setConcat() 718 if(!mat.isIdentity()) { 719 this->setConcat(*this, mat); 720 } 721 } 722 723 void SkMatrix::postConcat(const SkMatrix& mat) { 724 // check for identity first, so we don't do a needless copy of ourselves 725 // to ourselves inside setConcat() 726 if (!mat.isIdentity()) { 727 this->setConcat(mat, *this); 728 } 729 } 730 731 /////////////////////////////////////////////////////////////////////////////// 732 733 /* Matrix inversion is very expensive, but also the place where keeping 734 precision may be most important (here and matrix concat). Hence to avoid 735 bitmap blitting artifacts when walking the inverse, we use doubles for 736 the intermediate math, even though we know that is more expensive. 737 */ 738 739 static inline SkScalar scross_dscale(SkScalar a, SkScalar b, 740 SkScalar c, SkScalar d, double scale) { 741 return SkDoubleToScalar(scross(a, b, c, d) * scale); 742 } 743 744 static inline double dcross(double a, double b, double c, double d) { 745 return a * b - c * d; 746 } 747 748 static inline SkScalar dcross_dscale(double a, double b, 749 double c, double d, double scale) { 750 return SkDoubleToScalar(dcross(a, b, c, d) * scale); 751 } 752 753 static double sk_inv_determinant(const float mat[9], int isPerspective) { 754 double det; 755 756 if (isPerspective) { 757 det = mat[SkMatrix::kMScaleX] * 758 dcross(mat[SkMatrix::kMScaleY], mat[SkMatrix::kMPersp2], 759 mat[SkMatrix::kMTransY], mat[SkMatrix::kMPersp1]) 760 + 761 mat[SkMatrix::kMSkewX] * 762 dcross(mat[SkMatrix::kMTransY], mat[SkMatrix::kMPersp0], 763 mat[SkMatrix::kMSkewY], mat[SkMatrix::kMPersp2]) 764 + 765 mat[SkMatrix::kMTransX] * 766 dcross(mat[SkMatrix::kMSkewY], mat[SkMatrix::kMPersp1], 767 mat[SkMatrix::kMScaleY], mat[SkMatrix::kMPersp0]); 768 } else { 769 det = dcross(mat[SkMatrix::kMScaleX], mat[SkMatrix::kMScaleY], 770 mat[SkMatrix::kMSkewX], mat[SkMatrix::kMSkewY]); 771 } 772 773 // Since the determinant is on the order of the cube of the matrix members, 774 // compare to the cube of the default nearly-zero constant (although an 775 // estimate of the condition number would be better if it wasn't so expensive). 776 if (SkScalarNearlyZero((float)det, SK_ScalarNearlyZero * SK_ScalarNearlyZero * SK_ScalarNearlyZero)) { 777 return 0; 778 } 779 return 1.0 / det; 780 } 781 782 void SkMatrix::SetAffineIdentity(SkScalar affine[6]) { 783 affine[kAScaleX] = 1; 784 affine[kASkewY] = 0; 785 affine[kASkewX] = 0; 786 affine[kAScaleY] = 1; 787 affine[kATransX] = 0; 788 affine[kATransY] = 0; 789 } 790 791 bool SkMatrix::asAffine(SkScalar affine[6]) const { 792 if (this->hasPerspective()) { 793 return false; 794 } 795 if (affine) { 796 affine[kAScaleX] = this->fMat[kMScaleX]; 797 affine[kASkewY] = this->fMat[kMSkewY]; 798 affine[kASkewX] = this->fMat[kMSkewX]; 799 affine[kAScaleY] = this->fMat[kMScaleY]; 800 affine[kATransX] = this->fMat[kMTransX]; 801 affine[kATransY] = this->fMat[kMTransY]; 802 } 803 return true; 804 } 805 806 void SkMatrix::ComputeInv(SkScalar dst[9], const SkScalar src[9], double invDet, bool isPersp) { 807 SkASSERT(src != dst); 808 SkASSERT(src && dst); 809 810 if (isPersp) { 811 dst[kMScaleX] = scross_dscale(src[kMScaleY], src[kMPersp2], src[kMTransY], src[kMPersp1], invDet); 812 dst[kMSkewX] = scross_dscale(src[kMTransX], src[kMPersp1], src[kMSkewX], src[kMPersp2], invDet); 813 dst[kMTransX] = scross_dscale(src[kMSkewX], src[kMTransY], src[kMTransX], src[kMScaleY], invDet); 814 815 dst[kMSkewY] = scross_dscale(src[kMTransY], src[kMPersp0], src[kMSkewY], src[kMPersp2], invDet); 816 dst[kMScaleY] = scross_dscale(src[kMScaleX], src[kMPersp2], src[kMTransX], src[kMPersp0], invDet); 817 dst[kMTransY] = scross_dscale(src[kMTransX], src[kMSkewY], src[kMScaleX], src[kMTransY], invDet); 818 819 dst[kMPersp0] = scross_dscale(src[kMSkewY], src[kMPersp1], src[kMScaleY], src[kMPersp0], invDet); 820 dst[kMPersp1] = scross_dscale(src[kMSkewX], src[kMPersp0], src[kMScaleX], src[kMPersp1], invDet); 821 dst[kMPersp2] = scross_dscale(src[kMScaleX], src[kMScaleY], src[kMSkewX], src[kMSkewY], invDet); 822 } else { // not perspective 823 dst[kMScaleX] = SkDoubleToScalar(src[kMScaleY] * invDet); 824 dst[kMSkewX] = SkDoubleToScalar(-src[kMSkewX] * invDet); 825 dst[kMTransX] = dcross_dscale(src[kMSkewX], src[kMTransY], src[kMScaleY], src[kMTransX], invDet); 826 827 dst[kMSkewY] = SkDoubleToScalar(-src[kMSkewY] * invDet); 828 dst[kMScaleY] = SkDoubleToScalar(src[kMScaleX] * invDet); 829 dst[kMTransY] = dcross_dscale(src[kMSkewY], src[kMTransX], src[kMScaleX], src[kMTransY], invDet); 830 831 dst[kMPersp0] = 0; 832 dst[kMPersp1] = 0; 833 dst[kMPersp2] = 1; 834 } 835 } 836 837 bool SkMatrix::invertNonIdentity(SkMatrix* inv) const { 838 SkASSERT(!this->isIdentity()); 839 840 TypeMask mask = this->getType(); 841 842 if (0 == (mask & ~(kScale_Mask | kTranslate_Mask))) { 843 bool invertible = true; 844 if (inv) { 845 if (mask & kScale_Mask) { 846 SkScalar invX = fMat[kMScaleX]; 847 SkScalar invY = fMat[kMScaleY]; 848 if (0 == invX || 0 == invY) { 849 return false; 850 } 851 invX = SkScalarInvert(invX); 852 invY = SkScalarInvert(invY); 853 854 // Must be careful when writing to inv, since it may be the 855 // same memory as this. 856 857 inv->fMat[kMSkewX] = inv->fMat[kMSkewY] = 858 inv->fMat[kMPersp0] = inv->fMat[kMPersp1] = 0; 859 860 inv->fMat[kMScaleX] = invX; 861 inv->fMat[kMScaleY] = invY; 862 inv->fMat[kMPersp2] = 1; 863 inv->fMat[kMTransX] = -fMat[kMTransX] * invX; 864 inv->fMat[kMTransY] = -fMat[kMTransY] * invY; 865 866 inv->setTypeMask(mask | kRectStaysRect_Mask); 867 } else { 868 // translate only 869 inv->setTranslate(-fMat[kMTransX], -fMat[kMTransY]); 870 } 871 } else { // inv is nullptr, just check if we're invertible 872 if (!fMat[kMScaleX] || !fMat[kMScaleY]) { 873 invertible = false; 874 } 875 } 876 return invertible; 877 } 878 879 int isPersp = mask & kPerspective_Mask; 880 double invDet = sk_inv_determinant(fMat, isPersp); 881 882 if (invDet == 0) { // underflow 883 return false; 884 } 885 886 bool applyingInPlace = (inv == this); 887 888 SkMatrix* tmp = inv; 889 890 SkMatrix storage; 891 if (applyingInPlace || nullptr == tmp) { 892 tmp = &storage; // we either need to avoid trampling memory or have no memory 893 } 894 895 ComputeInv(tmp->fMat, fMat, invDet, isPersp); 896 if (!tmp->isFinite()) { 897 return false; 898 } 899 900 tmp->setTypeMask(fTypeMask); 901 902 if (applyingInPlace) { 903 *inv = storage; // need to copy answer back 904 } 905 906 return true; 907 } 908 909 /////////////////////////////////////////////////////////////////////////////// 910 911 void SkMatrix::Identity_pts(const SkMatrix& m, SkPoint dst[], const SkPoint src[], int count) { 912 SkASSERT(m.getType() == 0); 913 914 if (dst != src && count > 0) { 915 memcpy(dst, src, count * sizeof(SkPoint)); 916 } 917 } 918 919 void SkMatrix::Trans_pts(const SkMatrix& m, SkPoint dst[], const SkPoint src[], int count) { 920 return SkOpts::matrix_translate(m,dst,src,count); 921 } 922 923 void SkMatrix::Scale_pts(const SkMatrix& m, SkPoint dst[], const SkPoint src[], int count) { 924 return SkOpts::matrix_scale_translate(m,dst,src,count); 925 } 926 927 void SkMatrix::Persp_pts(const SkMatrix& m, SkPoint dst[], 928 const SkPoint src[], int count) { 929 SkASSERT(m.hasPerspective()); 930 931 if (count > 0) { 932 do { 933 SkScalar sy = src->fY; 934 SkScalar sx = src->fX; 935 src += 1; 936 937 SkScalar x = sdot(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX]) + m.fMat[kMTransX]; 938 SkScalar y = sdot(sx, m.fMat[kMSkewY], sy, m.fMat[kMScaleY]) + m.fMat[kMTransY]; 939 #ifdef SK_LEGACY_MATRIX_MATH_ORDER 940 SkScalar z = sx * m.fMat[kMPersp0] + (sy * m.fMat[kMPersp1] + m.fMat[kMPersp2]); 941 #else 942 SkScalar z = sdot(sx, m.fMat[kMPersp0], sy, m.fMat[kMPersp1]) + m.fMat[kMPersp2]; 943 #endif 944 if (z) { 945 z = SkScalarFastInvert(z); 946 } 947 948 dst->fY = y * z; 949 dst->fX = x * z; 950 dst += 1; 951 } while (--count); 952 } 953 } 954 955 void SkMatrix::Affine_vpts(const SkMatrix& m, SkPoint dst[], const SkPoint src[], int count) { 956 return SkOpts::matrix_affine(m,dst,src,count); 957 } 958 959 const SkMatrix::MapPtsProc SkMatrix::gMapPtsProcs[] = { 960 SkMatrix::Identity_pts, SkMatrix::Trans_pts, 961 SkMatrix::Scale_pts, SkMatrix::Scale_pts, 962 SkMatrix::Affine_vpts, SkMatrix::Affine_vpts, 963 SkMatrix::Affine_vpts, SkMatrix::Affine_vpts, 964 // repeat the persp proc 8 times 965 SkMatrix::Persp_pts, SkMatrix::Persp_pts, 966 SkMatrix::Persp_pts, SkMatrix::Persp_pts, 967 SkMatrix::Persp_pts, SkMatrix::Persp_pts, 968 SkMatrix::Persp_pts, SkMatrix::Persp_pts 969 }; 970 971 /////////////////////////////////////////////////////////////////////////////// 972 973 void SkMatrix::mapHomogeneousPoints(SkScalar dst[], const SkScalar src[], int count) const { 974 SkASSERT((dst && src && count > 0) || 0 == count); 975 // no partial overlap 976 SkASSERT(src == dst || &dst[3*count] <= &src[0] || &src[3*count] <= &dst[0]); 977 978 if (count > 0) { 979 if (this->isIdentity()) { 980 memcpy(dst, src, 3*count*sizeof(SkScalar)); 981 return; 982 } 983 do { 984 SkScalar sx = src[0]; 985 SkScalar sy = src[1]; 986 SkScalar sw = src[2]; 987 src += 3; 988 989 SkScalar x = sdot(sx, fMat[kMScaleX], sy, fMat[kMSkewX], sw, fMat[kMTransX]); 990 SkScalar y = sdot(sx, fMat[kMSkewY], sy, fMat[kMScaleY], sw, fMat[kMTransY]); 991 SkScalar w = sdot(sx, fMat[kMPersp0], sy, fMat[kMPersp1], sw, fMat[kMPersp2]); 992 993 dst[0] = x; 994 dst[1] = y; 995 dst[2] = w; 996 dst += 3; 997 } while (--count); 998 } 999 } 1000 1001 /////////////////////////////////////////////////////////////////////////////// 1002 1003 void SkMatrix::mapVectors(SkPoint dst[], const SkPoint src[], int count) const { 1004 if (this->hasPerspective()) { 1005 SkPoint origin; 1006 1007 MapXYProc proc = this->getMapXYProc(); 1008 proc(*this, 0, 0, &origin); 1009 1010 for (int i = count - 1; i >= 0; --i) { 1011 SkPoint tmp; 1012 1013 proc(*this, src[i].fX, src[i].fY, &tmp); 1014 dst[i].set(tmp.fX - origin.fX, tmp.fY - origin.fY); 1015 } 1016 } else { 1017 SkMatrix tmp = *this; 1018 1019 tmp.fMat[kMTransX] = tmp.fMat[kMTransY] = 0; 1020 tmp.clearTypeMask(kTranslate_Mask); 1021 tmp.mapPoints(dst, src, count); 1022 } 1023 } 1024 1025 bool SkMatrix::mapRect(SkRect* dst, const SkRect& src) const { 1026 SkASSERT(dst); 1027 1028 if (this->rectStaysRect()) { 1029 this->mapPoints((SkPoint*)dst, (const SkPoint*)&src, 2); 1030 dst->sort(); 1031 return true; 1032 } else { 1033 SkPoint quad[4]; 1034 1035 src.toQuad(quad); 1036 this->mapPoints(quad, quad, 4); 1037 dst->set(quad, 4); 1038 return false; 1039 } 1040 } 1041 1042 SkScalar SkMatrix::mapRadius(SkScalar radius) const { 1043 SkVector vec[2]; 1044 1045 vec[0].set(radius, 0); 1046 vec[1].set(0, radius); 1047 this->mapVectors(vec, 2); 1048 1049 SkScalar d0 = vec[0].length(); 1050 SkScalar d1 = vec[1].length(); 1051 1052 // return geometric mean 1053 return SkScalarSqrt(d0 * d1); 1054 } 1055 1056 /////////////////////////////////////////////////////////////////////////////// 1057 1058 void SkMatrix::Persp_xy(const SkMatrix& m, SkScalar sx, SkScalar sy, 1059 SkPoint* pt) { 1060 SkASSERT(m.hasPerspective()); 1061 1062 SkScalar x = sdot(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX]) + m.fMat[kMTransX]; 1063 SkScalar y = sdot(sx, m.fMat[kMSkewY], sy, m.fMat[kMScaleY]) + m.fMat[kMTransY]; 1064 SkScalar z = sdot(sx, m.fMat[kMPersp0], sy, m.fMat[kMPersp1]) + m.fMat[kMPersp2]; 1065 if (z) { 1066 z = SkScalarFastInvert(z); 1067 } 1068 pt->fX = x * z; 1069 pt->fY = y * z; 1070 } 1071 1072 void SkMatrix::RotTrans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy, 1073 SkPoint* pt) { 1074 SkASSERT((m.getType() & (kAffine_Mask | kPerspective_Mask)) == kAffine_Mask); 1075 1076 #ifdef SK_LEGACY_MATRIX_MATH_ORDER 1077 pt->fX = sx * m.fMat[kMScaleX] + (sy * m.fMat[kMSkewX] + m.fMat[kMTransX]); 1078 pt->fY = sx * m.fMat[kMSkewY] + (sy * m.fMat[kMScaleY] + m.fMat[kMTransY]); 1079 #else 1080 pt->fX = sdot(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX]) + m.fMat[kMTransX]; 1081 pt->fY = sdot(sx, m.fMat[kMSkewY], sy, m.fMat[kMScaleY]) + m.fMat[kMTransY]; 1082 #endif 1083 } 1084 1085 void SkMatrix::Rot_xy(const SkMatrix& m, SkScalar sx, SkScalar sy, 1086 SkPoint* pt) { 1087 SkASSERT((m.getType() & (kAffine_Mask | kPerspective_Mask))== kAffine_Mask); 1088 SkASSERT(0 == m.fMat[kMTransX]); 1089 SkASSERT(0 == m.fMat[kMTransY]); 1090 1091 #ifdef SK_LEGACY_MATRIX_MATH_ORDER 1092 pt->fX = sx * m.fMat[kMScaleX] + (sy * m.fMat[kMSkewX] + m.fMat[kMTransX]); 1093 pt->fY = sx * m.fMat[kMSkewY] + (sy * m.fMat[kMScaleY] + m.fMat[kMTransY]); 1094 #else 1095 pt->fX = sdot(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX]) + m.fMat[kMTransX]; 1096 pt->fY = sdot(sx, m.fMat[kMSkewY], sy, m.fMat[kMScaleY]) + m.fMat[kMTransY]; 1097 #endif 1098 } 1099 1100 void SkMatrix::ScaleTrans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy, 1101 SkPoint* pt) { 1102 SkASSERT((m.getType() & (kScale_Mask | kAffine_Mask | kPerspective_Mask)) 1103 == kScale_Mask); 1104 1105 pt->fX = sx * m.fMat[kMScaleX] + m.fMat[kMTransX]; 1106 pt->fY = sy * m.fMat[kMScaleY] + m.fMat[kMTransY]; 1107 } 1108 1109 void SkMatrix::Scale_xy(const SkMatrix& m, SkScalar sx, SkScalar sy, 1110 SkPoint* pt) { 1111 SkASSERT((m.getType() & (kScale_Mask | kAffine_Mask | kPerspective_Mask)) 1112 == kScale_Mask); 1113 SkASSERT(0 == m.fMat[kMTransX]); 1114 SkASSERT(0 == m.fMat[kMTransY]); 1115 1116 pt->fX = sx * m.fMat[kMScaleX]; 1117 pt->fY = sy * m.fMat[kMScaleY]; 1118 } 1119 1120 void SkMatrix::Trans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy, 1121 SkPoint* pt) { 1122 SkASSERT(m.getType() == kTranslate_Mask); 1123 1124 pt->fX = sx + m.fMat[kMTransX]; 1125 pt->fY = sy + m.fMat[kMTransY]; 1126 } 1127 1128 void SkMatrix::Identity_xy(const SkMatrix& m, SkScalar sx, SkScalar sy, 1129 SkPoint* pt) { 1130 SkASSERT(0 == m.getType()); 1131 1132 pt->fX = sx; 1133 pt->fY = sy; 1134 } 1135 1136 const SkMatrix::MapXYProc SkMatrix::gMapXYProcs[] = { 1137 SkMatrix::Identity_xy, SkMatrix::Trans_xy, 1138 SkMatrix::Scale_xy, SkMatrix::ScaleTrans_xy, 1139 SkMatrix::Rot_xy, SkMatrix::RotTrans_xy, 1140 SkMatrix::Rot_xy, SkMatrix::RotTrans_xy, 1141 // repeat the persp proc 8 times 1142 SkMatrix::Persp_xy, SkMatrix::Persp_xy, 1143 SkMatrix::Persp_xy, SkMatrix::Persp_xy, 1144 SkMatrix::Persp_xy, SkMatrix::Persp_xy, 1145 SkMatrix::Persp_xy, SkMatrix::Persp_xy 1146 }; 1147 1148 /////////////////////////////////////////////////////////////////////////////// 1149 1150 // if its nearly zero (just made up 26, perhaps it should be bigger or smaller) 1151 #define PerspNearlyZero(x) SkScalarNearlyZero(x, (1.0f / (1 << 26))) 1152 1153 bool SkMatrix::isFixedStepInX() const { 1154 return PerspNearlyZero(fMat[kMPersp0]); 1155 } 1156 1157 SkVector SkMatrix::fixedStepInX(SkScalar y) const { 1158 SkASSERT(PerspNearlyZero(fMat[kMPersp0])); 1159 if (PerspNearlyZero(fMat[kMPersp1]) && 1160 PerspNearlyZero(fMat[kMPersp2] - 1)) { 1161 return SkVector::Make(fMat[kMScaleX], fMat[kMSkewY]); 1162 } else { 1163 SkScalar z = y * fMat[kMPersp1] + fMat[kMPersp2]; 1164 return SkVector::Make(fMat[kMScaleX] / z, fMat[kMSkewY] / z); 1165 } 1166 } 1167 1168 /////////////////////////////////////////////////////////////////////////////// 1169 1170 #include "SkPerspIter.h" 1171 1172 SkPerspIter::SkPerspIter(const SkMatrix& m, SkScalar x0, SkScalar y0, int count) 1173 : fMatrix(m), fSX(x0), fSY(y0), fCount(count) { 1174 SkPoint pt; 1175 1176 SkMatrix::Persp_xy(m, x0, y0, &pt); 1177 fX = SkScalarToFixed(pt.fX); 1178 fY = SkScalarToFixed(pt.fY); 1179 } 1180 1181 int SkPerspIter::next() { 1182 int n = fCount; 1183 1184 if (0 == n) { 1185 return 0; 1186 } 1187 SkPoint pt; 1188 SkFixed x = fX; 1189 SkFixed y = fY; 1190 SkFixed dx, dy; 1191 1192 if (n >= kCount) { 1193 n = kCount; 1194 fSX += SkIntToScalar(kCount); 1195 SkMatrix::Persp_xy(fMatrix, fSX, fSY, &pt); 1196 fX = SkScalarToFixed(pt.fX); 1197 fY = SkScalarToFixed(pt.fY); 1198 dx = (fX - x) >> kShift; 1199 dy = (fY - y) >> kShift; 1200 } else { 1201 fSX += SkIntToScalar(n); 1202 SkMatrix::Persp_xy(fMatrix, fSX, fSY, &pt); 1203 fX = SkScalarToFixed(pt.fX); 1204 fY = SkScalarToFixed(pt.fY); 1205 dx = (fX - x) / n; 1206 dy = (fY - y) / n; 1207 } 1208 1209 SkFixed* p = fStorage; 1210 for (int i = 0; i < n; i++) { 1211 *p++ = x; x += dx; 1212 *p++ = y; y += dy; 1213 } 1214 1215 fCount -= n; 1216 return n; 1217 } 1218 1219 /////////////////////////////////////////////////////////////////////////////// 1220 1221 static inline bool checkForZero(float x) { 1222 return x*x == 0; 1223 } 1224 1225 static inline bool poly_to_point(SkPoint* pt, const SkPoint poly[], int count) { 1226 float x = 1, y = 1; 1227 SkPoint pt1, pt2; 1228 1229 if (count > 1) { 1230 pt1.fX = poly[1].fX - poly[0].fX; 1231 pt1.fY = poly[1].fY - poly[0].fY; 1232 y = SkPoint::Length(pt1.fX, pt1.fY); 1233 if (checkForZero(y)) { 1234 return false; 1235 } 1236 switch (count) { 1237 case 2: 1238 break; 1239 case 3: 1240 pt2.fX = poly[0].fY - poly[2].fY; 1241 pt2.fY = poly[2].fX - poly[0].fX; 1242 goto CALC_X; 1243 default: 1244 pt2.fX = poly[0].fY - poly[3].fY; 1245 pt2.fY = poly[3].fX - poly[0].fX; 1246 CALC_X: 1247 x = sdot(pt1.fX, pt2.fX, pt1.fY, pt2.fY) / y; 1248 break; 1249 } 1250 } 1251 pt->set(x, y); 1252 return true; 1253 } 1254 1255 bool SkMatrix::Poly2Proc(const SkPoint srcPt[], SkMatrix* dst, 1256 const SkPoint& scale) { 1257 float invScale = 1 / scale.fY; 1258 1259 dst->fMat[kMScaleX] = (srcPt[1].fY - srcPt[0].fY) * invScale; 1260 dst->fMat[kMSkewY] = (srcPt[0].fX - srcPt[1].fX) * invScale; 1261 dst->fMat[kMPersp0] = 0; 1262 dst->fMat[kMSkewX] = (srcPt[1].fX - srcPt[0].fX) * invScale; 1263 dst->fMat[kMScaleY] = (srcPt[1].fY - srcPt[0].fY) * invScale; 1264 dst->fMat[kMPersp1] = 0; 1265 dst->fMat[kMTransX] = srcPt[0].fX; 1266 dst->fMat[kMTransY] = srcPt[0].fY; 1267 dst->fMat[kMPersp2] = 1; 1268 dst->setTypeMask(kUnknown_Mask); 1269 return true; 1270 } 1271 1272 bool SkMatrix::Poly3Proc(const SkPoint srcPt[], SkMatrix* dst, 1273 const SkPoint& scale) { 1274 float invScale = 1 / scale.fX; 1275 dst->fMat[kMScaleX] = (srcPt[2].fX - srcPt[0].fX) * invScale; 1276 dst->fMat[kMSkewY] = (srcPt[2].fY - srcPt[0].fY) * invScale; 1277 dst->fMat[kMPersp0] = 0; 1278 1279 invScale = 1 / scale.fY; 1280 dst->fMat[kMSkewX] = (srcPt[1].fX - srcPt[0].fX) * invScale; 1281 dst->fMat[kMScaleY] = (srcPt[1].fY - srcPt[0].fY) * invScale; 1282 dst->fMat[kMPersp1] = 0; 1283 1284 dst->fMat[kMTransX] = srcPt[0].fX; 1285 dst->fMat[kMTransY] = srcPt[0].fY; 1286 dst->fMat[kMPersp2] = 1; 1287 dst->setTypeMask(kUnknown_Mask); 1288 return true; 1289 } 1290 1291 bool SkMatrix::Poly4Proc(const SkPoint srcPt[], SkMatrix* dst, 1292 const SkPoint& scale) { 1293 float a1, a2; 1294 float x0, y0, x1, y1, x2, y2; 1295 1296 x0 = srcPt[2].fX - srcPt[0].fX; 1297 y0 = srcPt[2].fY - srcPt[0].fY; 1298 x1 = srcPt[2].fX - srcPt[1].fX; 1299 y1 = srcPt[2].fY - srcPt[1].fY; 1300 x2 = srcPt[2].fX - srcPt[3].fX; 1301 y2 = srcPt[2].fY - srcPt[3].fY; 1302 1303 /* check if abs(x2) > abs(y2) */ 1304 if ( x2 > 0 ? y2 > 0 ? x2 > y2 : x2 > -y2 : y2 > 0 ? -x2 > y2 : x2 < y2) { 1305 float denom = SkScalarMulDiv(x1, y2, x2) - y1; 1306 if (checkForZero(denom)) { 1307 return false; 1308 } 1309 a1 = (SkScalarMulDiv(x0 - x1, y2, x2) - y0 + y1) / denom; 1310 } else { 1311 float denom = x1 - SkScalarMulDiv(y1, x2, y2); 1312 if (checkForZero(denom)) { 1313 return false; 1314 } 1315 a1 = (x0 - x1 - SkScalarMulDiv(y0 - y1, x2, y2)) / denom; 1316 } 1317 1318 /* check if abs(x1) > abs(y1) */ 1319 if ( x1 > 0 ? y1 > 0 ? x1 > y1 : x1 > -y1 : y1 > 0 ? -x1 > y1 : x1 < y1) { 1320 float denom = y2 - SkScalarMulDiv(x2, y1, x1); 1321 if (checkForZero(denom)) { 1322 return false; 1323 } 1324 a2 = (y0 - y2 - SkScalarMulDiv(x0 - x2, y1, x1)) / denom; 1325 } else { 1326 float denom = SkScalarMulDiv(y2, x1, y1) - x2; 1327 if (checkForZero(denom)) { 1328 return false; 1329 } 1330 a2 = (SkScalarMulDiv(y0 - y2, x1, y1) - x0 + x2) / denom; 1331 } 1332 1333 float invScale = SkScalarInvert(scale.fX); 1334 dst->fMat[kMScaleX] = (a2 * srcPt[3].fX + srcPt[3].fX - srcPt[0].fX) * invScale; 1335 dst->fMat[kMSkewY] = (a2 * srcPt[3].fY + srcPt[3].fY - srcPt[0].fY) * invScale; 1336 dst->fMat[kMPersp0] = a2 * invScale; 1337 1338 invScale = SkScalarInvert(scale.fY); 1339 dst->fMat[kMSkewX] = (a1 * srcPt[1].fX + srcPt[1].fX - srcPt[0].fX) * invScale; 1340 dst->fMat[kMScaleY] = (a1 * srcPt[1].fY + srcPt[1].fY - srcPt[0].fY) * invScale; 1341 dst->fMat[kMPersp1] = a1 * invScale; 1342 1343 dst->fMat[kMTransX] = srcPt[0].fX; 1344 dst->fMat[kMTransY] = srcPt[0].fY; 1345 dst->fMat[kMPersp2] = 1; 1346 dst->setTypeMask(kUnknown_Mask); 1347 return true; 1348 } 1349 1350 typedef bool (*PolyMapProc)(const SkPoint[], SkMatrix*, const SkPoint&); 1351 1352 /* Taken from Rob Johnson's original sample code in QuickDraw GX 1353 */ 1354 bool SkMatrix::setPolyToPoly(const SkPoint src[], const SkPoint dst[], 1355 int count) { 1356 if ((unsigned)count > 4) { 1357 SkDebugf("--- SkMatrix::setPolyToPoly count out of range %d\n", count); 1358 return false; 1359 } 1360 1361 if (0 == count) { 1362 this->reset(); 1363 return true; 1364 } 1365 if (1 == count) { 1366 this->setTranslate(dst[0].fX - src[0].fX, dst[0].fY - src[0].fY); 1367 return true; 1368 } 1369 1370 SkPoint scale; 1371 if (!poly_to_point(&scale, src, count) || 1372 SkScalarNearlyZero(scale.fX) || 1373 SkScalarNearlyZero(scale.fY)) { 1374 return false; 1375 } 1376 1377 static const PolyMapProc gPolyMapProcs[] = { 1378 SkMatrix::Poly2Proc, SkMatrix::Poly3Proc, SkMatrix::Poly4Proc 1379 }; 1380 PolyMapProc proc = gPolyMapProcs[count - 2]; 1381 1382 SkMatrix tempMap, result; 1383 tempMap.setTypeMask(kUnknown_Mask); 1384 1385 if (!proc(src, &tempMap, scale)) { 1386 return false; 1387 } 1388 if (!tempMap.invert(&result)) { 1389 return false; 1390 } 1391 if (!proc(dst, &tempMap, scale)) { 1392 return false; 1393 } 1394 this->setConcat(tempMap, result); 1395 return true; 1396 } 1397 1398 /////////////////////////////////////////////////////////////////////////////// 1399 1400 enum MinMaxOrBoth { 1401 kMin_MinMaxOrBoth, 1402 kMax_MinMaxOrBoth, 1403 kBoth_MinMaxOrBoth 1404 }; 1405 1406 template <MinMaxOrBoth MIN_MAX_OR_BOTH> bool get_scale_factor(SkMatrix::TypeMask typeMask, 1407 const SkScalar m[9], 1408 SkScalar results[/*1 or 2*/]) { 1409 if (typeMask & SkMatrix::kPerspective_Mask) { 1410 return false; 1411 } 1412 if (SkMatrix::kIdentity_Mask == typeMask) { 1413 results[0] = SK_Scalar1; 1414 if (kBoth_MinMaxOrBoth == MIN_MAX_OR_BOTH) { 1415 results[1] = SK_Scalar1; 1416 } 1417 return true; 1418 } 1419 if (!(typeMask & SkMatrix::kAffine_Mask)) { 1420 if (kMin_MinMaxOrBoth == MIN_MAX_OR_BOTH) { 1421 results[0] = SkMinScalar(SkScalarAbs(m[SkMatrix::kMScaleX]), 1422 SkScalarAbs(m[SkMatrix::kMScaleY])); 1423 } else if (kMax_MinMaxOrBoth == MIN_MAX_OR_BOTH) { 1424 results[0] = SkMaxScalar(SkScalarAbs(m[SkMatrix::kMScaleX]), 1425 SkScalarAbs(m[SkMatrix::kMScaleY])); 1426 } else { 1427 results[0] = SkScalarAbs(m[SkMatrix::kMScaleX]); 1428 results[1] = SkScalarAbs(m[SkMatrix::kMScaleY]); 1429 if (results[0] > results[1]) { 1430 SkTSwap(results[0], results[1]); 1431 } 1432 } 1433 return true; 1434 } 1435 // ignore the translation part of the matrix, just look at 2x2 portion. 1436 // compute singular values, take largest or smallest abs value. 1437 // [a b; b c] = A^T*A 1438 SkScalar a = sdot(m[SkMatrix::kMScaleX], m[SkMatrix::kMScaleX], 1439 m[SkMatrix::kMSkewY], m[SkMatrix::kMSkewY]); 1440 SkScalar b = sdot(m[SkMatrix::kMScaleX], m[SkMatrix::kMSkewX], 1441 m[SkMatrix::kMScaleY], m[SkMatrix::kMSkewY]); 1442 SkScalar c = sdot(m[SkMatrix::kMSkewX], m[SkMatrix::kMSkewX], 1443 m[SkMatrix::kMScaleY], m[SkMatrix::kMScaleY]); 1444 // eigenvalues of A^T*A are the squared singular values of A. 1445 // characteristic equation is det((A^T*A) - l*I) = 0 1446 // l^2 - (a + c)l + (ac-b^2) 1447 // solve using quadratic equation (divisor is non-zero since l^2 has 1 coeff 1448 // and roots are guaranteed to be pos and real). 1449 SkScalar bSqd = b * b; 1450 // if upper left 2x2 is orthogonal save some math 1451 if (bSqd <= SK_ScalarNearlyZero*SK_ScalarNearlyZero) { 1452 if (kMin_MinMaxOrBoth == MIN_MAX_OR_BOTH) { 1453 results[0] = SkMinScalar(a, c); 1454 } else if (kMax_MinMaxOrBoth == MIN_MAX_OR_BOTH) { 1455 results[0] = SkMaxScalar(a, c); 1456 } else { 1457 results[0] = a; 1458 results[1] = c; 1459 if (results[0] > results[1]) { 1460 SkTSwap(results[0], results[1]); 1461 } 1462 } 1463 } else { 1464 SkScalar aminusc = a - c; 1465 SkScalar apluscdiv2 = SkScalarHalf(a + c); 1466 SkScalar x = SkScalarHalf(SkScalarSqrt(aminusc * aminusc + 4 * bSqd)); 1467 if (kMin_MinMaxOrBoth == MIN_MAX_OR_BOTH) { 1468 results[0] = apluscdiv2 - x; 1469 } else if (kMax_MinMaxOrBoth == MIN_MAX_OR_BOTH) { 1470 results[0] = apluscdiv2 + x; 1471 } else { 1472 results[0] = apluscdiv2 - x; 1473 results[1] = apluscdiv2 + x; 1474 } 1475 } 1476 if (SkScalarIsNaN(results[0])) { 1477 return false; 1478 } 1479 SkASSERT(results[0] >= 0); 1480 results[0] = SkScalarSqrt(results[0]); 1481 if (kBoth_MinMaxOrBoth == MIN_MAX_OR_BOTH) { 1482 if (SkScalarIsNaN(results[1])) { 1483 return false; 1484 } 1485 SkASSERT(results[1] >= 0); 1486 results[1] = SkScalarSqrt(results[1]); 1487 } 1488 return true; 1489 } 1490 1491 SkScalar SkMatrix::getMinScale() const { 1492 SkScalar factor; 1493 if (get_scale_factor<kMin_MinMaxOrBoth>(this->getType(), fMat, &factor)) { 1494 return factor; 1495 } else { 1496 return -1; 1497 } 1498 } 1499 1500 SkScalar SkMatrix::getMaxScale() const { 1501 SkScalar factor; 1502 if (get_scale_factor<kMax_MinMaxOrBoth>(this->getType(), fMat, &factor)) { 1503 return factor; 1504 } else { 1505 return -1; 1506 } 1507 } 1508 1509 bool SkMatrix::getMinMaxScales(SkScalar scaleFactors[2]) const { 1510 return get_scale_factor<kBoth_MinMaxOrBoth>(this->getType(), fMat, scaleFactors); 1511 } 1512 1513 namespace { 1514 1515 // SkMatrix is C++11 POD (trivial and standard-layout), but not aggregate (it has private fields). 1516 struct AggregateMatrix { 1517 SkScalar matrix[9]; 1518 uint32_t typemask; 1519 1520 const SkMatrix& asSkMatrix() const { return *reinterpret_cast<const SkMatrix*>(this); } 1521 }; 1522 static_assert(sizeof(AggregateMatrix) == sizeof(SkMatrix), "AggregateMatrix size mismatch."); 1523 1524 } // namespace 1525 1526 const SkMatrix& SkMatrix::I() { 1527 static_assert(offsetof(SkMatrix,fMat) == offsetof(AggregateMatrix,matrix), "fMat"); 1528 static_assert(offsetof(SkMatrix,fTypeMask) == offsetof(AggregateMatrix,typemask), "fTypeMask"); 1529 1530 static const AggregateMatrix identity = { {SK_Scalar1, 0, 0, 1531 0, SK_Scalar1, 0, 1532 0, 0, SK_Scalar1 }, 1533 kIdentity_Mask | kRectStaysRect_Mask}; 1534 SkASSERT(identity.asSkMatrix().isIdentity()); 1535 return identity.asSkMatrix(); 1536 } 1537 1538 const SkMatrix& SkMatrix::InvalidMatrix() { 1539 static_assert(offsetof(SkMatrix,fMat) == offsetof(AggregateMatrix,matrix), "fMat"); 1540 static_assert(offsetof(SkMatrix,fTypeMask) == offsetof(AggregateMatrix,typemask), "fTypeMask"); 1541 1542 static const AggregateMatrix invalid = 1543 { {SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, 1544 SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, 1545 SK_ScalarMax, SK_ScalarMax, SK_ScalarMax }, 1546 kTranslate_Mask | kScale_Mask | kAffine_Mask | kPerspective_Mask }; 1547 return invalid.asSkMatrix(); 1548 } 1549 1550 bool SkMatrix::decomposeScale(SkSize* scale, SkMatrix* remaining) const { 1551 if (this->hasPerspective()) { 1552 return false; 1553 } 1554 1555 const SkScalar sx = SkVector::Length(this->getScaleX(), this->getSkewY()); 1556 const SkScalar sy = SkVector::Length(this->getSkewX(), this->getScaleY()); 1557 if (!SkScalarIsFinite(sx) || !SkScalarIsFinite(sy) || 1558 SkScalarNearlyZero(sx) || SkScalarNearlyZero(sy)) { 1559 return false; 1560 } 1561 1562 if (scale) { 1563 scale->set(sx, sy); 1564 } 1565 if (remaining) { 1566 *remaining = *this; 1567 remaining->postScale(SkScalarInvert(sx), SkScalarInvert(sy)); 1568 } 1569 return true; 1570 } 1571 1572 /////////////////////////////////////////////////////////////////////////////// 1573 1574 size_t SkMatrix::writeToMemory(void* buffer) const { 1575 // TODO write less for simple matrices 1576 static const size_t sizeInMemory = 9 * sizeof(SkScalar); 1577 if (buffer) { 1578 memcpy(buffer, fMat, sizeInMemory); 1579 } 1580 return sizeInMemory; 1581 } 1582 1583 size_t SkMatrix::readFromMemory(const void* buffer, size_t length) { 1584 static const size_t sizeInMemory = 9 * sizeof(SkScalar); 1585 if (length < sizeInMemory) { 1586 return 0; 1587 } 1588 if (buffer) { 1589 memcpy(fMat, buffer, sizeInMemory); 1590 this->setTypeMask(kUnknown_Mask); 1591 } 1592 return sizeInMemory; 1593 } 1594 1595 void SkMatrix::dump() const { 1596 SkString str; 1597 this->toString(&str); 1598 SkDebugf("%s\n", str.c_str()); 1599 } 1600 1601 void SkMatrix::toString(SkString* str) const { 1602 str->appendf("[%8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f]", 1603 fMat[0], fMat[1], fMat[2], fMat[3], fMat[4], fMat[5], 1604 fMat[6], fMat[7], fMat[8]); 1605 } 1606 1607 /////////////////////////////////////////////////////////////////////////////// 1608 1609 #include "SkMatrixUtils.h" 1610 1611 bool SkTreatAsSprite(const SkMatrix& mat, const SkISize& size, const SkPaint& paint) { 1612 // Our path aa is 2-bits, and our rect aa is 8, so we could use 8, 1613 // but in practice 4 seems enough (still looks smooth) and allows 1614 // more slightly fractional cases to fall into the fast (sprite) case. 1615 static const unsigned kAntiAliasSubpixelBits = 4; 1616 1617 const unsigned subpixelBits = paint.isAntiAlias() ? kAntiAliasSubpixelBits : 0; 1618 1619 // quick reject on affine or perspective 1620 if (mat.getType() & ~(SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask)) { 1621 return false; 1622 } 1623 1624 // quick success check 1625 if (!subpixelBits && !(mat.getType() & ~SkMatrix::kTranslate_Mask)) { 1626 return true; 1627 } 1628 1629 // mapRect supports negative scales, so we eliminate those first 1630 if (mat.getScaleX() < 0 || mat.getScaleY() < 0) { 1631 return false; 1632 } 1633 1634 SkRect dst; 1635 SkIRect isrc = SkIRect::MakeSize(size); 1636 1637 { 1638 SkRect src; 1639 src.set(isrc); 1640 mat.mapRect(&dst, src); 1641 } 1642 1643 // just apply the translate to isrc 1644 isrc.offset(SkScalarRoundToInt(mat.getTranslateX()), 1645 SkScalarRoundToInt(mat.getTranslateY())); 1646 1647 if (subpixelBits) { 1648 isrc.fLeft = SkLeftShift(isrc.fLeft, subpixelBits); 1649 isrc.fTop = SkLeftShift(isrc.fTop, subpixelBits); 1650 isrc.fRight = SkLeftShift(isrc.fRight, subpixelBits); 1651 isrc.fBottom = SkLeftShift(isrc.fBottom, subpixelBits); 1652 1653 const float scale = 1 << subpixelBits; 1654 dst.fLeft *= scale; 1655 dst.fTop *= scale; 1656 dst.fRight *= scale; 1657 dst.fBottom *= scale; 1658 } 1659 1660 SkIRect idst; 1661 dst.round(&idst); 1662 return isrc == idst; 1663 } 1664 1665 // A square matrix M can be decomposed (via polar decomposition) into two matrices -- 1666 // an orthogonal matrix Q and a symmetric matrix S. In turn we can decompose S into U*W*U^T, 1667 // where U is another orthogonal matrix and W is a scale matrix. These can be recombined 1668 // to give M = (Q*U)*W*U^T, i.e., the product of two orthogonal matrices and a scale matrix. 1669 // 1670 // The one wrinkle is that traditionally Q may contain a reflection -- the 1671 // calculation has been rejiggered to put that reflection into W. 1672 bool SkDecomposeUpper2x2(const SkMatrix& matrix, 1673 SkPoint* rotation1, 1674 SkPoint* scale, 1675 SkPoint* rotation2) { 1676 1677 SkScalar A = matrix[SkMatrix::kMScaleX]; 1678 SkScalar B = matrix[SkMatrix::kMSkewX]; 1679 SkScalar C = matrix[SkMatrix::kMSkewY]; 1680 SkScalar D = matrix[SkMatrix::kMScaleY]; 1681 1682 if (is_degenerate_2x2(A, B, C, D)) { 1683 return false; 1684 } 1685 1686 double w1, w2; 1687 SkScalar cos1, sin1; 1688 SkScalar cos2, sin2; 1689 1690 // do polar decomposition (M = Q*S) 1691 SkScalar cosQ, sinQ; 1692 double Sa, Sb, Sd; 1693 // if M is already symmetric (i.e., M = I*S) 1694 if (SkScalarNearlyEqual(B, C)) { 1695 cosQ = 1; 1696 sinQ = 0; 1697 1698 Sa = A; 1699 Sb = B; 1700 Sd = D; 1701 } else { 1702 cosQ = A + D; 1703 sinQ = C - B; 1704 SkScalar reciplen = SkScalarInvert(SkScalarSqrt(cosQ*cosQ + sinQ*sinQ)); 1705 cosQ *= reciplen; 1706 sinQ *= reciplen; 1707 1708 // S = Q^-1*M 1709 // we don't calc Sc since it's symmetric 1710 Sa = A*cosQ + C*sinQ; 1711 Sb = B*cosQ + D*sinQ; 1712 Sd = -B*sinQ + D*cosQ; 1713 } 1714 1715 // Now we need to compute eigenvalues of S (our scale factors) 1716 // and eigenvectors (bases for our rotation) 1717 // From this, should be able to reconstruct S as U*W*U^T 1718 if (SkScalarNearlyZero(SkDoubleToScalar(Sb))) { 1719 // already diagonalized 1720 cos1 = 1; 1721 sin1 = 0; 1722 w1 = Sa; 1723 w2 = Sd; 1724 cos2 = cosQ; 1725 sin2 = sinQ; 1726 } else { 1727 double diff = Sa - Sd; 1728 double discriminant = sqrt(diff*diff + 4.0*Sb*Sb); 1729 double trace = Sa + Sd; 1730 if (diff > 0) { 1731 w1 = 0.5*(trace + discriminant); 1732 w2 = 0.5*(trace - discriminant); 1733 } else { 1734 w1 = 0.5*(trace - discriminant); 1735 w2 = 0.5*(trace + discriminant); 1736 } 1737 1738 cos1 = SkDoubleToScalar(Sb); sin1 = SkDoubleToScalar(w1 - Sa); 1739 SkScalar reciplen = SkScalarInvert(SkScalarSqrt(cos1*cos1 + sin1*sin1)); 1740 cos1 *= reciplen; 1741 sin1 *= reciplen; 1742 1743 // rotation 2 is composition of Q and U 1744 cos2 = cos1*cosQ - sin1*sinQ; 1745 sin2 = sin1*cosQ + cos1*sinQ; 1746 1747 // rotation 1 is U^T 1748 sin1 = -sin1; 1749 } 1750 1751 if (scale) { 1752 scale->fX = SkDoubleToScalar(w1); 1753 scale->fY = SkDoubleToScalar(w2); 1754 } 1755 if (rotation1) { 1756 rotation1->fX = cos1; 1757 rotation1->fY = sin1; 1758 } 1759 if (rotation2) { 1760 rotation2->fX = cos2; 1761 rotation2->fY = sin2; 1762 } 1763 1764 return true; 1765 } 1766 1767 ////////////////////////////////////////////////////////////////////////////////////////////////// 1768 1769 void SkRSXform::toQuad(SkScalar width, SkScalar height, SkPoint quad[4]) const { 1770 #if 0 1771 // This is the slow way, but it documents what we're doing 1772 quad[0].set(0, 0); 1773 quad[1].set(width, 0); 1774 quad[2].set(width, height); 1775 quad[3].set(0, height); 1776 SkMatrix m; 1777 m.setRSXform(*this).mapPoints(quad, quad, 4); 1778 #else 1779 const SkScalar m00 = fSCos; 1780 const SkScalar m01 = -fSSin; 1781 const SkScalar m02 = fTx; 1782 const SkScalar m10 = -m01; 1783 const SkScalar m11 = m00; 1784 const SkScalar m12 = fTy; 1785 1786 quad[0].set(m02, m12); 1787 quad[1].set(m00 * width + m02, m10 * width + m12); 1788 quad[2].set(m00 * width + m01 * height + m02, m10 * width + m11 * height + m12); 1789 quad[3].set(m01 * height + m02, m11 * height + m12); 1790 #endif 1791 } 1792