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