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