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