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 #include "SkPerspIter.h" 1272 1273 SkPerspIter::SkPerspIter(const SkMatrix& m, SkScalar x0, SkScalar y0, int count) 1274 : fMatrix(m), fSX(x0), fSY(y0), fCount(count) { 1275 SkPoint pt; 1276 1277 SkMatrix::Persp_xy(m, x0, y0, &pt); 1278 fX = SkScalarToFixed(pt.fX); 1279 fY = SkScalarToFixed(pt.fY); 1280 } 1281 1282 int SkPerspIter::next() { 1283 int n = fCount; 1284 1285 if (0 == n) { 1286 return 0; 1287 } 1288 SkPoint pt; 1289 SkFixed x = fX; 1290 SkFixed y = fY; 1291 SkFixed dx, dy; 1292 1293 if (n >= kCount) { 1294 n = kCount; 1295 fSX += SkIntToScalar(kCount); 1296 SkMatrix::Persp_xy(fMatrix, fSX, fSY, &pt); 1297 fX = SkScalarToFixed(pt.fX); 1298 fY = SkScalarToFixed(pt.fY); 1299 dx = (fX - x) >> kShift; 1300 dy = (fY - y) >> kShift; 1301 } else { 1302 fSX += SkIntToScalar(n); 1303 SkMatrix::Persp_xy(fMatrix, fSX, fSY, &pt); 1304 fX = SkScalarToFixed(pt.fX); 1305 fY = SkScalarToFixed(pt.fY); 1306 dx = (fX - x) / n; 1307 dy = (fY - y) / n; 1308 } 1309 1310 SkFixed* p = fStorage; 1311 for (int i = 0; i < n; i++) { 1312 *p++ = x; x += dx; 1313 *p++ = y; y += dy; 1314 } 1315 1316 fCount -= n; 1317 return n; 1318 } 1319 1320 /////////////////////////////////////////////////////////////////////////////// 1321 1322 static inline bool checkForZero(float x) { 1323 return x*x == 0; 1324 } 1325 1326 static inline bool poly_to_point(SkPoint* pt, const SkPoint poly[], int count) { 1327 float x = 1, y = 1; 1328 SkPoint pt1, pt2; 1329 1330 if (count > 1) { 1331 pt1.fX = poly[1].fX - poly[0].fX; 1332 pt1.fY = poly[1].fY - poly[0].fY; 1333 y = SkPoint::Length(pt1.fX, pt1.fY); 1334 if (checkForZero(y)) { 1335 return false; 1336 } 1337 switch (count) { 1338 case 2: 1339 break; 1340 case 3: 1341 pt2.fX = poly[0].fY - poly[2].fY; 1342 pt2.fY = poly[2].fX - poly[0].fX; 1343 goto CALC_X; 1344 default: 1345 pt2.fX = poly[0].fY - poly[3].fY; 1346 pt2.fY = poly[3].fX - poly[0].fX; 1347 CALC_X: 1348 x = sdot(pt1.fX, pt2.fX, pt1.fY, pt2.fY) / y; 1349 break; 1350 } 1351 } 1352 pt->set(x, y); 1353 return true; 1354 } 1355 1356 bool SkMatrix::Poly2Proc(const SkPoint srcPt[], SkMatrix* dst, 1357 const SkPoint& scale) { 1358 float invScale = 1 / scale.fY; 1359 1360 dst->fMat[kMScaleX] = (srcPt[1].fY - srcPt[0].fY) * invScale; 1361 dst->fMat[kMSkewY] = (srcPt[0].fX - srcPt[1].fX) * invScale; 1362 dst->fMat[kMPersp0] = 0; 1363 dst->fMat[kMSkewX] = (srcPt[1].fX - srcPt[0].fX) * invScale; 1364 dst->fMat[kMScaleY] = (srcPt[1].fY - srcPt[0].fY) * invScale; 1365 dst->fMat[kMPersp1] = 0; 1366 dst->fMat[kMTransX] = srcPt[0].fX; 1367 dst->fMat[kMTransY] = srcPt[0].fY; 1368 dst->fMat[kMPersp2] = 1; 1369 dst->setTypeMask(kUnknown_Mask); 1370 return true; 1371 } 1372 1373 bool SkMatrix::Poly3Proc(const SkPoint srcPt[], SkMatrix* dst, 1374 const SkPoint& scale) { 1375 float invScale = 1 / scale.fX; 1376 dst->fMat[kMScaleX] = (srcPt[2].fX - srcPt[0].fX) * invScale; 1377 dst->fMat[kMSkewY] = (srcPt[2].fY - srcPt[0].fY) * invScale; 1378 dst->fMat[kMPersp0] = 0; 1379 1380 invScale = 1 / scale.fY; 1381 dst->fMat[kMSkewX] = (srcPt[1].fX - srcPt[0].fX) * invScale; 1382 dst->fMat[kMScaleY] = (srcPt[1].fY - srcPt[0].fY) * invScale; 1383 dst->fMat[kMPersp1] = 0; 1384 1385 dst->fMat[kMTransX] = srcPt[0].fX; 1386 dst->fMat[kMTransY] = srcPt[0].fY; 1387 dst->fMat[kMPersp2] = 1; 1388 dst->setTypeMask(kUnknown_Mask); 1389 return true; 1390 } 1391 1392 bool SkMatrix::Poly4Proc(const SkPoint srcPt[], SkMatrix* dst, 1393 const SkPoint& scale) { 1394 float a1, a2; 1395 float x0, y0, x1, y1, x2, y2; 1396 1397 x0 = srcPt[2].fX - srcPt[0].fX; 1398 y0 = srcPt[2].fY - srcPt[0].fY; 1399 x1 = srcPt[2].fX - srcPt[1].fX; 1400 y1 = srcPt[2].fY - srcPt[1].fY; 1401 x2 = srcPt[2].fX - srcPt[3].fX; 1402 y2 = srcPt[2].fY - srcPt[3].fY; 1403 1404 /* check if abs(x2) > abs(y2) */ 1405 if ( x2 > 0 ? y2 > 0 ? x2 > y2 : x2 > -y2 : y2 > 0 ? -x2 > y2 : x2 < y2) { 1406 float denom = (x1 * y2 / x2) - y1; 1407 if (checkForZero(denom)) { 1408 return false; 1409 } 1410 a1 = (((x0 - x1) * y2 / x2) - y0 + y1) / denom; 1411 } else { 1412 float denom = x1 - (y1 * x2 / y2); 1413 if (checkForZero(denom)) { 1414 return false; 1415 } 1416 a1 = (x0 - x1 - ((y0 - y1) * x2 / y2)) / denom; 1417 } 1418 1419 /* check if abs(x1) > abs(y1) */ 1420 if ( x1 > 0 ? y1 > 0 ? x1 > y1 : x1 > -y1 : y1 > 0 ? -x1 > y1 : x1 < y1) { 1421 float denom = y2 - (x2 * y1 / x1); 1422 if (checkForZero(denom)) { 1423 return false; 1424 } 1425 a2 = (y0 - y2 - ((x0 - x2) * y1 / x1)) / denom; 1426 } else { 1427 float denom = (y2 * x1 / y1) - x2; 1428 if (checkForZero(denom)) { 1429 return false; 1430 } 1431 a2 = (((y0 - y2) * x1 / y1) - x0 + x2) / denom; 1432 } 1433 1434 float invScale = SkScalarInvert(scale.fX); 1435 dst->fMat[kMScaleX] = (a2 * srcPt[3].fX + srcPt[3].fX - srcPt[0].fX) * invScale; 1436 dst->fMat[kMSkewY] = (a2 * srcPt[3].fY + srcPt[3].fY - srcPt[0].fY) * invScale; 1437 dst->fMat[kMPersp0] = a2 * invScale; 1438 1439 invScale = SkScalarInvert(scale.fY); 1440 dst->fMat[kMSkewX] = (a1 * srcPt[1].fX + srcPt[1].fX - srcPt[0].fX) * invScale; 1441 dst->fMat[kMScaleY] = (a1 * srcPt[1].fY + srcPt[1].fY - srcPt[0].fY) * invScale; 1442 dst->fMat[kMPersp1] = a1 * invScale; 1443 1444 dst->fMat[kMTransX] = srcPt[0].fX; 1445 dst->fMat[kMTransY] = srcPt[0].fY; 1446 dst->fMat[kMPersp2] = 1; 1447 dst->setTypeMask(kUnknown_Mask); 1448 return true; 1449 } 1450 1451 typedef bool (*PolyMapProc)(const SkPoint[], SkMatrix*, const SkPoint&); 1452 1453 /* Taken from Rob Johnson's original sample code in QuickDraw GX 1454 */ 1455 bool SkMatrix::setPolyToPoly(const SkPoint src[], const SkPoint dst[], 1456 int count) { 1457 if ((unsigned)count > 4) { 1458 SkDebugf("--- SkMatrix::setPolyToPoly count out of range %d\n", count); 1459 return false; 1460 } 1461 1462 if (0 == count) { 1463 this->reset(); 1464 return true; 1465 } 1466 if (1 == count) { 1467 this->setTranslate(dst[0].fX - src[0].fX, dst[0].fY - src[0].fY); 1468 return true; 1469 } 1470 1471 SkPoint scale; 1472 if (!poly_to_point(&scale, src, count) || 1473 SkScalarNearlyZero(scale.fX) || 1474 SkScalarNearlyZero(scale.fY)) { 1475 return false; 1476 } 1477 1478 static const PolyMapProc gPolyMapProcs[] = { 1479 SkMatrix::Poly2Proc, SkMatrix::Poly3Proc, SkMatrix::Poly4Proc 1480 }; 1481 PolyMapProc proc = gPolyMapProcs[count - 2]; 1482 1483 SkMatrix tempMap, result; 1484 tempMap.setTypeMask(kUnknown_Mask); 1485 1486 if (!proc(src, &tempMap, scale)) { 1487 return false; 1488 } 1489 if (!tempMap.invert(&result)) { 1490 return false; 1491 } 1492 if (!proc(dst, &tempMap, scale)) { 1493 return false; 1494 } 1495 this->setConcat(tempMap, result); 1496 return true; 1497 } 1498 1499 /////////////////////////////////////////////////////////////////////////////// 1500 1501 enum MinMaxOrBoth { 1502 kMin_MinMaxOrBoth, 1503 kMax_MinMaxOrBoth, 1504 kBoth_MinMaxOrBoth 1505 }; 1506 1507 template <MinMaxOrBoth MIN_MAX_OR_BOTH> bool get_scale_factor(SkMatrix::TypeMask typeMask, 1508 const SkScalar m[9], 1509 SkScalar results[/*1 or 2*/]) { 1510 if (typeMask & SkMatrix::kPerspective_Mask) { 1511 return false; 1512 } 1513 if (SkMatrix::kIdentity_Mask == typeMask) { 1514 results[0] = SK_Scalar1; 1515 if (kBoth_MinMaxOrBoth == MIN_MAX_OR_BOTH) { 1516 results[1] = SK_Scalar1; 1517 } 1518 return true; 1519 } 1520 if (!(typeMask & SkMatrix::kAffine_Mask)) { 1521 if (kMin_MinMaxOrBoth == MIN_MAX_OR_BOTH) { 1522 results[0] = SkMinScalar(SkScalarAbs(m[SkMatrix::kMScaleX]), 1523 SkScalarAbs(m[SkMatrix::kMScaleY])); 1524 } else if (kMax_MinMaxOrBoth == MIN_MAX_OR_BOTH) { 1525 results[0] = SkMaxScalar(SkScalarAbs(m[SkMatrix::kMScaleX]), 1526 SkScalarAbs(m[SkMatrix::kMScaleY])); 1527 } else { 1528 results[0] = SkScalarAbs(m[SkMatrix::kMScaleX]); 1529 results[1] = SkScalarAbs(m[SkMatrix::kMScaleY]); 1530 if (results[0] > results[1]) { 1531 SkTSwap(results[0], results[1]); 1532 } 1533 } 1534 return true; 1535 } 1536 // ignore the translation part of the matrix, just look at 2x2 portion. 1537 // compute singular values, take largest or smallest abs value. 1538 // [a b; b c] = A^T*A 1539 SkScalar a = sdot(m[SkMatrix::kMScaleX], m[SkMatrix::kMScaleX], 1540 m[SkMatrix::kMSkewY], m[SkMatrix::kMSkewY]); 1541 SkScalar b = sdot(m[SkMatrix::kMScaleX], m[SkMatrix::kMSkewX], 1542 m[SkMatrix::kMScaleY], m[SkMatrix::kMSkewY]); 1543 SkScalar c = sdot(m[SkMatrix::kMSkewX], m[SkMatrix::kMSkewX], 1544 m[SkMatrix::kMScaleY], m[SkMatrix::kMScaleY]); 1545 // eigenvalues of A^T*A are the squared singular values of A. 1546 // characteristic equation is det((A^T*A) - l*I) = 0 1547 // l^2 - (a + c)l + (ac-b^2) 1548 // solve using quadratic equation (divisor is non-zero since l^2 has 1 coeff 1549 // and roots are guaranteed to be pos and real). 1550 SkScalar bSqd = b * b; 1551 // if upper left 2x2 is orthogonal save some math 1552 if (bSqd <= SK_ScalarNearlyZero*SK_ScalarNearlyZero) { 1553 if (kMin_MinMaxOrBoth == MIN_MAX_OR_BOTH) { 1554 results[0] = SkMinScalar(a, c); 1555 } else if (kMax_MinMaxOrBoth == MIN_MAX_OR_BOTH) { 1556 results[0] = SkMaxScalar(a, c); 1557 } else { 1558 results[0] = a; 1559 results[1] = c; 1560 if (results[0] > results[1]) { 1561 SkTSwap(results[0], results[1]); 1562 } 1563 } 1564 } else { 1565 SkScalar aminusc = a - c; 1566 SkScalar apluscdiv2 = SkScalarHalf(a + c); 1567 SkScalar x = SkScalarHalf(SkScalarSqrt(aminusc * aminusc + 4 * bSqd)); 1568 if (kMin_MinMaxOrBoth == MIN_MAX_OR_BOTH) { 1569 results[0] = apluscdiv2 - x; 1570 } else if (kMax_MinMaxOrBoth == MIN_MAX_OR_BOTH) { 1571 results[0] = apluscdiv2 + x; 1572 } else { 1573 results[0] = apluscdiv2 - x; 1574 results[1] = apluscdiv2 + x; 1575 } 1576 } 1577 if (!SkScalarIsFinite(results[0])) { 1578 return false; 1579 } 1580 // Due to the floating point inaccuracy, there might be an error in a, b, c 1581 // calculated by sdot, further deepened by subsequent arithmetic operations 1582 // on them. Therefore, we allow and cap the nearly-zero negative values. 1583 SkASSERT(results[0] >= -SK_ScalarNearlyZero); 1584 if (results[0] < 0) { 1585 results[0] = 0; 1586 } 1587 results[0] = SkScalarSqrt(results[0]); 1588 if (kBoth_MinMaxOrBoth == MIN_MAX_OR_BOTH) { 1589 if (!SkScalarIsFinite(results[1])) { 1590 return false; 1591 } 1592 SkASSERT(results[1] >= -SK_ScalarNearlyZero); 1593 if (results[1] < 0) { 1594 results[1] = 0; 1595 } 1596 results[1] = SkScalarSqrt(results[1]); 1597 } 1598 return true; 1599 } 1600 1601 SkScalar SkMatrix::getMinScale() const { 1602 SkScalar factor; 1603 if (get_scale_factor<kMin_MinMaxOrBoth>(this->getType(), fMat, &factor)) { 1604 return factor; 1605 } else { 1606 return -1; 1607 } 1608 } 1609 1610 SkScalar SkMatrix::getMaxScale() const { 1611 SkScalar factor; 1612 if (get_scale_factor<kMax_MinMaxOrBoth>(this->getType(), fMat, &factor)) { 1613 return factor; 1614 } else { 1615 return -1; 1616 } 1617 } 1618 1619 bool SkMatrix::getMinMaxScales(SkScalar scaleFactors[2]) const { 1620 return get_scale_factor<kBoth_MinMaxOrBoth>(this->getType(), fMat, scaleFactors); 1621 } 1622 1623 namespace { 1624 1625 // SkMatrix is C++11 POD (trivial and standard-layout), but not aggregate (it has private fields). 1626 struct AggregateMatrix { 1627 SkScalar matrix[9]; 1628 uint32_t typemask; 1629 1630 const SkMatrix& asSkMatrix() const { return *reinterpret_cast<const SkMatrix*>(this); } 1631 }; 1632 static_assert(sizeof(AggregateMatrix) == sizeof(SkMatrix), "AggregateMatrix size mismatch."); 1633 1634 } // namespace 1635 1636 const SkMatrix& SkMatrix::I() { 1637 static_assert(offsetof(SkMatrix,fMat) == offsetof(AggregateMatrix,matrix), "fMat"); 1638 static_assert(offsetof(SkMatrix,fTypeMask) == offsetof(AggregateMatrix,typemask), "fTypeMask"); 1639 1640 static const AggregateMatrix identity = { {SK_Scalar1, 0, 0, 1641 0, SK_Scalar1, 0, 1642 0, 0, SK_Scalar1 }, 1643 kIdentity_Mask | kRectStaysRect_Mask}; 1644 SkASSERT(identity.asSkMatrix().isIdentity()); 1645 return identity.asSkMatrix(); 1646 } 1647 1648 const SkMatrix& SkMatrix::InvalidMatrix() { 1649 static_assert(offsetof(SkMatrix,fMat) == offsetof(AggregateMatrix,matrix), "fMat"); 1650 static_assert(offsetof(SkMatrix,fTypeMask) == offsetof(AggregateMatrix,typemask), "fTypeMask"); 1651 1652 static const AggregateMatrix invalid = 1653 { {SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, 1654 SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, 1655 SK_ScalarMax, SK_ScalarMax, SK_ScalarMax }, 1656 kTranslate_Mask | kScale_Mask | kAffine_Mask | kPerspective_Mask }; 1657 return invalid.asSkMatrix(); 1658 } 1659 1660 bool SkMatrix::decomposeScale(SkSize* scale, SkMatrix* remaining) const { 1661 if (this->hasPerspective()) { 1662 return false; 1663 } 1664 1665 const SkScalar sx = SkVector::Length(this->getScaleX(), this->getSkewY()); 1666 const SkScalar sy = SkVector::Length(this->getSkewX(), this->getScaleY()); 1667 if (!SkScalarIsFinite(sx) || !SkScalarIsFinite(sy) || 1668 SkScalarNearlyZero(sx) || SkScalarNearlyZero(sy)) { 1669 return false; 1670 } 1671 1672 if (scale) { 1673 scale->set(sx, sy); 1674 } 1675 if (remaining) { 1676 *remaining = *this; 1677 remaining->postScale(SkScalarInvert(sx), SkScalarInvert(sy)); 1678 } 1679 return true; 1680 } 1681 1682 /////////////////////////////////////////////////////////////////////////////// 1683 1684 size_t SkMatrix::writeToMemory(void* buffer) const { 1685 // TODO write less for simple matrices 1686 static const size_t sizeInMemory = 9 * sizeof(SkScalar); 1687 if (buffer) { 1688 memcpy(buffer, fMat, sizeInMemory); 1689 } 1690 return sizeInMemory; 1691 } 1692 1693 size_t SkMatrix::readFromMemory(const void* buffer, size_t length) { 1694 static const size_t sizeInMemory = 9 * sizeof(SkScalar); 1695 if (length < sizeInMemory) { 1696 return 0; 1697 } 1698 if (buffer) { 1699 memcpy(fMat, buffer, sizeInMemory); 1700 this->setTypeMask(kUnknown_Mask); 1701 } 1702 return sizeInMemory; 1703 } 1704 1705 void SkMatrix::dump() const { 1706 SkString str; 1707 this->toString(&str); 1708 SkDebugf("%s\n", str.c_str()); 1709 } 1710 1711 void SkMatrix::toString(SkString* str) const { 1712 str->appendf("[%8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f]", 1713 fMat[0], fMat[1], fMat[2], fMat[3], fMat[4], fMat[5], 1714 fMat[6], fMat[7], fMat[8]); 1715 } 1716 1717 /////////////////////////////////////////////////////////////////////////////// 1718 1719 #include "SkMatrixUtils.h" 1720 1721 bool SkTreatAsSprite(const SkMatrix& mat, const SkISize& size, const SkPaint& paint) { 1722 // Our path aa is 2-bits, and our rect aa is 8, so we could use 8, 1723 // but in practice 4 seems enough (still looks smooth) and allows 1724 // more slightly fractional cases to fall into the fast (sprite) case. 1725 static const unsigned kAntiAliasSubpixelBits = 4; 1726 1727 const unsigned subpixelBits = paint.isAntiAlias() ? kAntiAliasSubpixelBits : 0; 1728 1729 // quick reject on affine or perspective 1730 if (mat.getType() & ~(SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask)) { 1731 return false; 1732 } 1733 1734 // quick success check 1735 if (!subpixelBits && !(mat.getType() & ~SkMatrix::kTranslate_Mask)) { 1736 return true; 1737 } 1738 1739 // mapRect supports negative scales, so we eliminate those first 1740 if (mat.getScaleX() < 0 || mat.getScaleY() < 0) { 1741 return false; 1742 } 1743 1744 SkRect dst; 1745 SkIRect isrc = SkIRect::MakeSize(size); 1746 1747 { 1748 SkRect src; 1749 src.set(isrc); 1750 mat.mapRect(&dst, src); 1751 } 1752 1753 // just apply the translate to isrc 1754 isrc.offset(SkScalarRoundToInt(mat.getTranslateX()), 1755 SkScalarRoundToInt(mat.getTranslateY())); 1756 1757 if (subpixelBits) { 1758 isrc.fLeft = SkLeftShift(isrc.fLeft, subpixelBits); 1759 isrc.fTop = SkLeftShift(isrc.fTop, subpixelBits); 1760 isrc.fRight = SkLeftShift(isrc.fRight, subpixelBits); 1761 isrc.fBottom = SkLeftShift(isrc.fBottom, subpixelBits); 1762 1763 const float scale = 1 << subpixelBits; 1764 dst.fLeft *= scale; 1765 dst.fTop *= scale; 1766 dst.fRight *= scale; 1767 dst.fBottom *= scale; 1768 } 1769 1770 SkIRect idst; 1771 dst.round(&idst); 1772 return isrc == idst; 1773 } 1774 1775 // A square matrix M can be decomposed (via polar decomposition) into two matrices -- 1776 // an orthogonal matrix Q and a symmetric matrix S. In turn we can decompose S into U*W*U^T, 1777 // where U is another orthogonal matrix and W is a scale matrix. These can be recombined 1778 // to give M = (Q*U)*W*U^T, i.e., the product of two orthogonal matrices and a scale matrix. 1779 // 1780 // The one wrinkle is that traditionally Q may contain a reflection -- the 1781 // calculation has been rejiggered to put that reflection into W. 1782 bool SkDecomposeUpper2x2(const SkMatrix& matrix, 1783 SkPoint* rotation1, 1784 SkPoint* scale, 1785 SkPoint* rotation2) { 1786 1787 SkScalar A = matrix[SkMatrix::kMScaleX]; 1788 SkScalar B = matrix[SkMatrix::kMSkewX]; 1789 SkScalar C = matrix[SkMatrix::kMSkewY]; 1790 SkScalar D = matrix[SkMatrix::kMScaleY]; 1791 1792 if (is_degenerate_2x2(A, B, C, D)) { 1793 return false; 1794 } 1795 1796 double w1, w2; 1797 SkScalar cos1, sin1; 1798 SkScalar cos2, sin2; 1799 1800 // do polar decomposition (M = Q*S) 1801 SkScalar cosQ, sinQ; 1802 double Sa, Sb, Sd; 1803 // if M is already symmetric (i.e., M = I*S) 1804 if (SkScalarNearlyEqual(B, C)) { 1805 cosQ = 1; 1806 sinQ = 0; 1807 1808 Sa = A; 1809 Sb = B; 1810 Sd = D; 1811 } else { 1812 cosQ = A + D; 1813 sinQ = C - B; 1814 SkScalar reciplen = SkScalarInvert(SkScalarSqrt(cosQ*cosQ + sinQ*sinQ)); 1815 cosQ *= reciplen; 1816 sinQ *= reciplen; 1817 1818 // S = Q^-1*M 1819 // we don't calc Sc since it's symmetric 1820 Sa = A*cosQ + C*sinQ; 1821 Sb = B*cosQ + D*sinQ; 1822 Sd = -B*sinQ + D*cosQ; 1823 } 1824 1825 // Now we need to compute eigenvalues of S (our scale factors) 1826 // and eigenvectors (bases for our rotation) 1827 // From this, should be able to reconstruct S as U*W*U^T 1828 if (SkScalarNearlyZero(SkDoubleToScalar(Sb))) { 1829 // already diagonalized 1830 cos1 = 1; 1831 sin1 = 0; 1832 w1 = Sa; 1833 w2 = Sd; 1834 cos2 = cosQ; 1835 sin2 = sinQ; 1836 } else { 1837 double diff = Sa - Sd; 1838 double discriminant = sqrt(diff*diff + 4.0*Sb*Sb); 1839 double trace = Sa + Sd; 1840 if (diff > 0) { 1841 w1 = 0.5*(trace + discriminant); 1842 w2 = 0.5*(trace - discriminant); 1843 } else { 1844 w1 = 0.5*(trace - discriminant); 1845 w2 = 0.5*(trace + discriminant); 1846 } 1847 1848 cos1 = SkDoubleToScalar(Sb); sin1 = SkDoubleToScalar(w1 - Sa); 1849 SkScalar reciplen = SkScalarInvert(SkScalarSqrt(cos1*cos1 + sin1*sin1)); 1850 cos1 *= reciplen; 1851 sin1 *= reciplen; 1852 1853 // rotation 2 is composition of Q and U 1854 cos2 = cos1*cosQ - sin1*sinQ; 1855 sin2 = sin1*cosQ + cos1*sinQ; 1856 1857 // rotation 1 is U^T 1858 sin1 = -sin1; 1859 } 1860 1861 if (scale) { 1862 scale->fX = SkDoubleToScalar(w1); 1863 scale->fY = SkDoubleToScalar(w2); 1864 } 1865 if (rotation1) { 1866 rotation1->fX = cos1; 1867 rotation1->fY = sin1; 1868 } 1869 if (rotation2) { 1870 rotation2->fX = cos2; 1871 rotation2->fY = sin2; 1872 } 1873 1874 return true; 1875 } 1876 1877 ////////////////////////////////////////////////////////////////////////////////////////////////// 1878 1879 void SkRSXform::toQuad(SkScalar width, SkScalar height, SkPoint quad[4]) const { 1880 #if 0 1881 // This is the slow way, but it documents what we're doing 1882 quad[0].set(0, 0); 1883 quad[1].set(width, 0); 1884 quad[2].set(width, height); 1885 quad[3].set(0, height); 1886 SkMatrix m; 1887 m.setRSXform(*this).mapPoints(quad, quad, 4); 1888 #else 1889 const SkScalar m00 = fSCos; 1890 const SkScalar m01 = -fSSin; 1891 const SkScalar m02 = fTx; 1892 const SkScalar m10 = -m01; 1893 const SkScalar m11 = m00; 1894 const SkScalar m12 = fTy; 1895 1896 quad[0].set(m02, m12); 1897 quad[1].set(m00 * width + m02, m10 * width + m12); 1898 quad[2].set(m00 * width + m01 * height + m02, m10 * width + m11 * height + m12); 1899 quad[3].set(m01 * height + m02, m11 * height + m12); 1900 #endif 1901 } 1902