1 /* 2 * Copyright 2006 The Android Open Source Project 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkMatrix.h" 9 #include "Sk64.h" 10 #include "SkFloatBits.h" 11 #include "SkOnce.h" 12 #include "SkString.h" 13 14 #ifdef SK_SCALAR_IS_FLOAT 15 #define kMatrix22Elem SK_Scalar1 16 17 static inline float SkDoubleToFloat(double x) { 18 return static_cast<float>(x); 19 } 20 #else 21 #define kMatrix22Elem SK_Fract1 22 #endif 23 24 /* [scale-x skew-x trans-x] [X] [X'] 25 [skew-y scale-y trans-y] * [Y] = [Y'] 26 [persp-0 persp-1 persp-2] [1] [1 ] 27 */ 28 29 void SkMatrix::reset() { 30 fMat[kMScaleX] = fMat[kMScaleY] = SK_Scalar1; 31 fMat[kMSkewX] = fMat[kMSkewY] = 32 fMat[kMTransX] = fMat[kMTransY] = 33 fMat[kMPersp0] = fMat[kMPersp1] = 0; 34 fMat[kMPersp2] = kMatrix22Elem; 35 36 this->setTypeMask(kIdentity_Mask | kRectStaysRect_Mask); 37 } 38 39 // this guy aligns with the masks, so we can compute a mask from a varaible 0/1 40 enum { 41 kTranslate_Shift, 42 kScale_Shift, 43 kAffine_Shift, 44 kPerspective_Shift, 45 kRectStaysRect_Shift 46 }; 47 48 #ifdef SK_SCALAR_IS_FLOAT 49 static const int32_t kScalar1Int = 0x3f800000; 50 #else 51 #define scalarAsInt(x) (x) 52 static const int32_t kScalar1Int = (1 << 16); 53 static const int32_t kPersp1Int = (1 << 30); 54 #endif 55 56 #ifdef SK_SCALAR_SLOW_COMPARES 57 static const int32_t kPersp1Int = 0x3f800000; 58 #endif 59 60 uint8_t SkMatrix::computePerspectiveTypeMask() const { 61 #ifdef SK_SCALAR_SLOW_COMPARES 62 if (SkScalarAs2sCompliment(fMat[kMPersp0]) | 63 SkScalarAs2sCompliment(fMat[kMPersp1]) | 64 (SkScalarAs2sCompliment(fMat[kMPersp2]) - kPersp1Int)) { 65 return SkToU8(kORableMasks); 66 } 67 #else 68 // Benchmarking suggests that replacing this set of SkScalarAs2sCompliment 69 // is a win, but replacing those below is not. We don't yet understand 70 // that result. 71 if (fMat[kMPersp0] != 0 || fMat[kMPersp1] != 0 || 72 fMat[kMPersp2] != kMatrix22Elem) { 73 // If this is a perspective transform, we return true for all other 74 // transform flags - this does not disable any optimizations, respects 75 // the rule that the type mask must be conservative, and speeds up 76 // type mask computation. 77 return SkToU8(kORableMasks); 78 } 79 #endif 80 81 return SkToU8(kOnlyPerspectiveValid_Mask | kUnknown_Mask); 82 } 83 84 uint8_t SkMatrix::computeTypeMask() const { 85 unsigned mask = 0; 86 87 #ifdef SK_SCALAR_SLOW_COMPARES 88 if (SkScalarAs2sCompliment(fMat[kMPersp0]) | 89 SkScalarAs2sCompliment(fMat[kMPersp1]) | 90 (SkScalarAs2sCompliment(fMat[kMPersp2]) - kPersp1Int)) { 91 return SkToU8(kORableMasks); 92 } 93 94 if (SkScalarAs2sCompliment(fMat[kMTransX]) | 95 SkScalarAs2sCompliment(fMat[kMTransY])) { 96 mask |= kTranslate_Mask; 97 } 98 #else 99 if (fMat[kMPersp0] != 0 || fMat[kMPersp1] != 0 || 100 fMat[kMPersp2] != kMatrix22Elem) { 101 // Once it is determined that that this is a perspective transform, 102 // all other flags are moot as far as optimizations are concerned. 103 return SkToU8(kORableMasks); 104 } 105 106 if (fMat[kMTransX] != 0 || fMat[kMTransY] != 0) { 107 mask |= kTranslate_Mask; 108 } 109 #endif 110 111 int m00 = SkScalarAs2sCompliment(fMat[SkMatrix::kMScaleX]); 112 int m01 = SkScalarAs2sCompliment(fMat[SkMatrix::kMSkewX]); 113 int m10 = SkScalarAs2sCompliment(fMat[SkMatrix::kMSkewY]); 114 int m11 = SkScalarAs2sCompliment(fMat[SkMatrix::kMScaleY]); 115 116 if (m01 | m10) { 117 // The skew components may be scale-inducing, unless we are dealing 118 // with a pure rotation. Testing for a pure rotation is expensive, 119 // so we opt for being conservative by always setting the scale bit. 120 // along with affine. 121 // By doing this, we are also ensuring that matrices have the same 122 // type masks as their inverses. 123 mask |= kAffine_Mask | kScale_Mask; 124 125 // For rectStaysRect, in the affine case, we only need check that 126 // the primary diagonal is all zeros and that the secondary diagonal 127 // is all non-zero. 128 129 // map non-zero to 1 130 m01 = m01 != 0; 131 m10 = m10 != 0; 132 133 int dp0 = 0 == (m00 | m11) ; // true if both are 0 134 int ds1 = m01 & m10; // true if both are 1 135 136 mask |= (dp0 & ds1) << kRectStaysRect_Shift; 137 } else { 138 // Only test for scale explicitly if not affine, since affine sets the 139 // scale bit. 140 if ((m00 - kScalar1Int) | (m11 - kScalar1Int)) { 141 mask |= kScale_Mask; 142 } 143 144 // Not affine, therefore we already know secondary diagonal is 145 // all zeros, so we just need to check that primary diagonal is 146 // all non-zero. 147 148 // map non-zero to 1 149 m00 = m00 != 0; 150 m11 = m11 != 0; 151 152 // record if the (p)rimary diagonal is all non-zero 153 mask |= (m00 & m11) << kRectStaysRect_Shift; 154 } 155 156 return SkToU8(mask); 157 } 158 159 /////////////////////////////////////////////////////////////////////////////// 160 161 #ifdef SK_SCALAR_IS_FLOAT 162 163 bool operator==(const SkMatrix& a, const SkMatrix& b) { 164 const SkScalar* SK_RESTRICT ma = a.fMat; 165 const SkScalar* SK_RESTRICT mb = b.fMat; 166 167 return ma[0] == mb[0] && ma[1] == mb[1] && ma[2] == mb[2] && 168 ma[3] == mb[3] && ma[4] == mb[4] && ma[5] == mb[5] && 169 ma[6] == mb[6] && ma[7] == mb[7] && ma[8] == mb[8]; 170 } 171 172 #endif 173 174 /////////////////////////////////////////////////////////////////////////////// 175 176 // helper function to determine if upper-left 2x2 of matrix is degenerate 177 static inline bool is_degenerate_2x2(SkScalar scaleX, SkScalar skewX, 178 SkScalar skewY, SkScalar scaleY) { 179 SkScalar perp_dot = scaleX*scaleY - skewX*skewY; 180 return SkScalarNearlyZero(perp_dot, SK_ScalarNearlyZero*SK_ScalarNearlyZero); 181 } 182 183 /////////////////////////////////////////////////////////////////////////////// 184 185 bool SkMatrix::isSimilarity(SkScalar tol) const { 186 // if identity or translate matrix 187 TypeMask mask = this->getType(); 188 if (mask <= kTranslate_Mask) { 189 return true; 190 } 191 if (mask & kPerspective_Mask) { 192 return false; 193 } 194 195 SkScalar mx = fMat[kMScaleX]; 196 SkScalar my = fMat[kMScaleY]; 197 // if no skew, can just compare scale factors 198 if (!(mask & kAffine_Mask)) { 199 return !SkScalarNearlyZero(mx) && SkScalarNearlyEqual(SkScalarAbs(mx), SkScalarAbs(my)); 200 } 201 SkScalar sx = fMat[kMSkewX]; 202 SkScalar sy = fMat[kMSkewY]; 203 204 if (is_degenerate_2x2(mx, sx, sy, my)) { 205 return false; 206 } 207 208 // it has scales and skews, but it could also be rotation, check it out. 209 SkVector vec[2]; 210 vec[0].set(mx, sx); 211 vec[1].set(sy, my); 212 213 return SkScalarNearlyZero(vec[0].dot(vec[1]), SkScalarSquare(tol)) && 214 SkScalarNearlyEqual(vec[0].lengthSqd(), vec[1].lengthSqd(), 215 SkScalarSquare(tol)); 216 } 217 218 bool SkMatrix::preservesRightAngles(SkScalar tol) const { 219 TypeMask mask = this->getType(); 220 221 if (mask <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { 222 // identity, translate and/or scale 223 return true; 224 } 225 if (mask & kPerspective_Mask) { 226 return false; 227 } 228 229 SkASSERT(mask & kAffine_Mask); 230 231 SkScalar mx = fMat[kMScaleX]; 232 SkScalar my = fMat[kMScaleY]; 233 SkScalar sx = fMat[kMSkewX]; 234 SkScalar sy = fMat[kMSkewY]; 235 236 if (is_degenerate_2x2(mx, sx, sy, my)) { 237 return false; 238 } 239 240 // it has scales and skews, but it could also be rotation, check it out. 241 SkVector vec[2]; 242 vec[0].set(mx, sx); 243 vec[1].set(sy, my); 244 245 return SkScalarNearlyZero(vec[0].dot(vec[1]), SkScalarSquare(tol)) && 246 SkScalarNearlyEqual(vec[0].lengthSqd(), vec[1].lengthSqd(), 247 SkScalarSquare(tol)); 248 } 249 250 /////////////////////////////////////////////////////////////////////////////// 251 252 void SkMatrix::setTranslate(SkScalar dx, SkScalar dy) { 253 if (dx || dy) { 254 fMat[kMTransX] = dx; 255 fMat[kMTransY] = dy; 256 257 fMat[kMScaleX] = fMat[kMScaleY] = SK_Scalar1; 258 fMat[kMSkewX] = fMat[kMSkewY] = 259 fMat[kMPersp0] = fMat[kMPersp1] = 0; 260 fMat[kMPersp2] = kMatrix22Elem; 261 262 this->setTypeMask(kTranslate_Mask | kRectStaysRect_Mask); 263 } else { 264 this->reset(); 265 } 266 } 267 268 bool SkMatrix::preTranslate(SkScalar dx, SkScalar dy) { 269 if (this->hasPerspective()) { 270 SkMatrix m; 271 m.setTranslate(dx, dy); 272 return this->preConcat(m); 273 } 274 275 if (dx || dy) { 276 fMat[kMTransX] += SkScalarMul(fMat[kMScaleX], dx) + 277 SkScalarMul(fMat[kMSkewX], dy); 278 fMat[kMTransY] += SkScalarMul(fMat[kMSkewY], dx) + 279 SkScalarMul(fMat[kMScaleY], dy); 280 281 this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); 282 } 283 return true; 284 } 285 286 bool SkMatrix::postTranslate(SkScalar dx, SkScalar dy) { 287 if (this->hasPerspective()) { 288 SkMatrix m; 289 m.setTranslate(dx, dy); 290 return this->postConcat(m); 291 } 292 293 if (dx || dy) { 294 fMat[kMTransX] += dx; 295 fMat[kMTransY] += dy; 296 this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); 297 } 298 return true; 299 } 300 301 /////////////////////////////////////////////////////////////////////////////// 302 303 void SkMatrix::setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) { 304 if (SK_Scalar1 == sx && SK_Scalar1 == sy) { 305 this->reset(); 306 } else { 307 fMat[kMScaleX] = sx; 308 fMat[kMScaleY] = sy; 309 fMat[kMTransX] = px - SkScalarMul(sx, px); 310 fMat[kMTransY] = py - SkScalarMul(sy, py); 311 fMat[kMPersp2] = kMatrix22Elem; 312 313 fMat[kMSkewX] = fMat[kMSkewY] = 314 fMat[kMPersp0] = fMat[kMPersp1] = 0; 315 316 this->setTypeMask(kScale_Mask | kTranslate_Mask | kRectStaysRect_Mask); 317 } 318 } 319 320 void SkMatrix::setScale(SkScalar sx, SkScalar sy) { 321 if (SK_Scalar1 == sx && SK_Scalar1 == sy) { 322 this->reset(); 323 } else { 324 fMat[kMScaleX] = sx; 325 fMat[kMScaleY] = sy; 326 fMat[kMPersp2] = kMatrix22Elem; 327 328 fMat[kMTransX] = fMat[kMTransY] = 329 fMat[kMSkewX] = fMat[kMSkewY] = 330 fMat[kMPersp0] = fMat[kMPersp1] = 0; 331 332 this->setTypeMask(kScale_Mask | kRectStaysRect_Mask); 333 } 334 } 335 336 bool SkMatrix::setIDiv(int divx, int divy) { 337 if (!divx || !divy) { 338 return false; 339 } 340 this->setScale(SK_Scalar1 / divx, SK_Scalar1 / divy); 341 return true; 342 } 343 344 bool SkMatrix::preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) { 345 SkMatrix m; 346 m.setScale(sx, sy, px, py); 347 return this->preConcat(m); 348 } 349 350 bool SkMatrix::preScale(SkScalar sx, SkScalar sy) { 351 if (SK_Scalar1 == sx && SK_Scalar1 == sy) { 352 return true; 353 } 354 355 #ifdef SK_SCALAR_IS_FIXED 356 SkMatrix m; 357 m.setScale(sx, sy); 358 return this->preConcat(m); 359 #else 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] = SkScalarMul(fMat[kMScaleX], sx); 366 fMat[kMSkewY] = SkScalarMul(fMat[kMSkewY], sx); 367 fMat[kMPersp0] = SkScalarMul(fMat[kMPersp0], sx); 368 369 fMat[kMSkewX] = SkScalarMul(fMat[kMSkewX], sy); 370 fMat[kMScaleY] = SkScalarMul(fMat[kMScaleY], sy); 371 fMat[kMPersp1] = SkScalarMul(fMat[kMPersp1], sy); 372 373 this->orTypeMask(kScale_Mask); 374 return true; 375 #endif 376 } 377 378 bool SkMatrix::postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) { 379 if (SK_Scalar1 == sx && SK_Scalar1 == sy) { 380 return true; 381 } 382 SkMatrix m; 383 m.setScale(sx, sy, px, py); 384 return this->postConcat(m); 385 } 386 387 bool SkMatrix::postScale(SkScalar sx, SkScalar sy) { 388 if (SK_Scalar1 == sx && SK_Scalar1 == sy) { 389 return true; 390 } 391 SkMatrix m; 392 m.setScale(sx, sy); 393 return this->postConcat(m); 394 } 395 396 #ifdef SK_SCALAR_IS_FIXED 397 static inline SkFixed roundidiv(SkFixed numer, int denom) { 398 int ns = numer >> 31; 399 int ds = denom >> 31; 400 numer = (numer ^ ns) - ns; 401 denom = (denom ^ ds) - ds; 402 403 SkFixed answer = (numer + (denom >> 1)) / denom; 404 int as = ns ^ ds; 405 return (answer ^ as) - as; 406 } 407 #endif 408 409 // this guy perhaps can go away, if we have a fract/high-precision way to 410 // scale matrices 411 bool SkMatrix::postIDiv(int divx, int divy) { 412 if (divx == 0 || divy == 0) { 413 return false; 414 } 415 416 #ifdef SK_SCALAR_IS_FIXED 417 fMat[kMScaleX] = roundidiv(fMat[kMScaleX], divx); 418 fMat[kMSkewX] = roundidiv(fMat[kMSkewX], divx); 419 fMat[kMTransX] = roundidiv(fMat[kMTransX], divx); 420 421 fMat[kMScaleY] = roundidiv(fMat[kMScaleY], divy); 422 fMat[kMSkewY] = roundidiv(fMat[kMSkewY], divy); 423 fMat[kMTransY] = roundidiv(fMat[kMTransY], divy); 424 #else 425 const float invX = 1.f / divx; 426 const float invY = 1.f / divy; 427 428 fMat[kMScaleX] *= invX; 429 fMat[kMSkewX] *= invX; 430 fMat[kMTransX] *= invX; 431 432 fMat[kMScaleY] *= invY; 433 fMat[kMSkewY] *= invY; 434 fMat[kMTransY] *= invY; 435 #endif 436 437 this->setTypeMask(kUnknown_Mask); 438 return true; 439 } 440 441 //////////////////////////////////////////////////////////////////////////////////// 442 443 void SkMatrix::setSinCos(SkScalar sinV, SkScalar cosV, 444 SkScalar px, SkScalar py) { 445 const SkScalar oneMinusCosV = SK_Scalar1 - cosV; 446 447 fMat[kMScaleX] = cosV; 448 fMat[kMSkewX] = -sinV; 449 fMat[kMTransX] = SkScalarMul(sinV, py) + SkScalarMul(oneMinusCosV, px); 450 451 fMat[kMSkewY] = sinV; 452 fMat[kMScaleY] = cosV; 453 fMat[kMTransY] = SkScalarMul(-sinV, px) + SkScalarMul(oneMinusCosV, py); 454 455 fMat[kMPersp0] = fMat[kMPersp1] = 0; 456 fMat[kMPersp2] = kMatrix22Elem; 457 458 this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); 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] = kMatrix22Elem; 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 bool SkMatrix::preRotate(SkScalar degrees, SkScalar px, SkScalar py) { 489 SkMatrix m; 490 m.setRotate(degrees, px, py); 491 return this->preConcat(m); 492 } 493 494 bool SkMatrix::preRotate(SkScalar degrees) { 495 SkMatrix m; 496 m.setRotate(degrees); 497 return this->preConcat(m); 498 } 499 500 bool SkMatrix::postRotate(SkScalar degrees, SkScalar px, SkScalar py) { 501 SkMatrix m; 502 m.setRotate(degrees, px, py); 503 return this->postConcat(m); 504 } 505 506 bool SkMatrix::postRotate(SkScalar degrees) { 507 SkMatrix m; 508 m.setRotate(degrees); 509 return this->postConcat(m); 510 } 511 512 //////////////////////////////////////////////////////////////////////////////////// 513 514 void SkMatrix::setSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) { 515 fMat[kMScaleX] = SK_Scalar1; 516 fMat[kMSkewX] = sx; 517 fMat[kMTransX] = SkScalarMul(-sx, py); 518 519 fMat[kMSkewY] = sy; 520 fMat[kMScaleY] = SK_Scalar1; 521 fMat[kMTransY] = SkScalarMul(-sy, px); 522 523 fMat[kMPersp0] = fMat[kMPersp1] = 0; 524 fMat[kMPersp2] = kMatrix22Elem; 525 526 this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); 527 } 528 529 void SkMatrix::setSkew(SkScalar sx, SkScalar sy) { 530 fMat[kMScaleX] = SK_Scalar1; 531 fMat[kMSkewX] = sx; 532 fMat[kMTransX] = 0; 533 534 fMat[kMSkewY] = sy; 535 fMat[kMScaleY] = SK_Scalar1; 536 fMat[kMTransY] = 0; 537 538 fMat[kMPersp0] = fMat[kMPersp1] = 0; 539 fMat[kMPersp2] = kMatrix22Elem; 540 541 this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); 542 } 543 544 bool SkMatrix::preSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) { 545 SkMatrix m; 546 m.setSkew(sx, sy, px, py); 547 return this->preConcat(m); 548 } 549 550 bool SkMatrix::preSkew(SkScalar sx, SkScalar sy) { 551 SkMatrix m; 552 m.setSkew(sx, sy); 553 return this->preConcat(m); 554 } 555 556 bool SkMatrix::postSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) { 557 SkMatrix m; 558 m.setSkew(sx, sy, px, py); 559 return this->postConcat(m); 560 } 561 562 bool SkMatrix::postSkew(SkScalar sx, SkScalar sy) { 563 SkMatrix m; 564 m.setSkew(sx, sy); 565 return this->postConcat(m); 566 } 567 568 /////////////////////////////////////////////////////////////////////////////// 569 570 bool SkMatrix::setRectToRect(const SkRect& src, const SkRect& dst, 571 ScaleToFit align) 572 { 573 if (src.isEmpty()) { 574 this->reset(); 575 return false; 576 } 577 578 if (dst.isEmpty()) { 579 sk_bzero(fMat, 8 * sizeof(SkScalar)); 580 this->setTypeMask(kScale_Mask | kRectStaysRect_Mask); 581 } else { 582 SkScalar tx, sx = SkScalarDiv(dst.width(), src.width()); 583 SkScalar ty, sy = SkScalarDiv(dst.height(), src.height()); 584 bool xLarger = false; 585 586 if (align != kFill_ScaleToFit) { 587 if (sx > sy) { 588 xLarger = true; 589 sx = sy; 590 } else { 591 sy = sx; 592 } 593 } 594 595 tx = dst.fLeft - SkScalarMul(src.fLeft, sx); 596 ty = dst.fTop - SkScalarMul(src.fTop, sy); 597 if (align == kCenter_ScaleToFit || align == kEnd_ScaleToFit) { 598 SkScalar diff; 599 600 if (xLarger) { 601 diff = dst.width() - SkScalarMul(src.width(), sy); 602 } else { 603 diff = dst.height() - SkScalarMul(src.height(), sy); 604 } 605 606 if (align == kCenter_ScaleToFit) { 607 diff = SkScalarHalf(diff); 608 } 609 610 if (xLarger) { 611 tx += diff; 612 } else { 613 ty += diff; 614 } 615 } 616 617 fMat[kMScaleX] = sx; 618 fMat[kMScaleY] = sy; 619 fMat[kMTransX] = tx; 620 fMat[kMTransY] = ty; 621 fMat[kMSkewX] = fMat[kMSkewY] = 622 fMat[kMPersp0] = fMat[kMPersp1] = 0; 623 624 unsigned mask = kRectStaysRect_Mask; 625 if (sx != SK_Scalar1 || sy != SK_Scalar1) { 626 mask |= kScale_Mask; 627 } 628 if (tx || ty) { 629 mask |= kTranslate_Mask; 630 } 631 this->setTypeMask(mask); 632 } 633 // shared cleanup 634 fMat[kMPersp2] = kMatrix22Elem; 635 return true; 636 } 637 638 /////////////////////////////////////////////////////////////////////////////// 639 640 #ifdef SK_SCALAR_IS_FLOAT 641 static inline int fixmuladdmul(float a, float b, float c, float d, 642 float* result) { 643 *result = SkDoubleToFloat((double)a * b + (double)c * d); 644 return true; 645 } 646 647 static inline bool rowcol3(const float row[], const float col[], 648 float* result) { 649 *result = row[0] * col[0] + row[1] * col[3] + row[2] * col[6]; 650 return true; 651 } 652 653 static inline int negifaddoverflows(float& result, float a, float b) { 654 result = a + b; 655 return 0; 656 } 657 #else 658 static inline bool fixmuladdmul(SkFixed a, SkFixed b, SkFixed c, SkFixed d, 659 SkFixed* result) { 660 Sk64 tmp1, tmp2; 661 tmp1.setMul(a, b); 662 tmp2.setMul(c, d); 663 tmp1.add(tmp2); 664 if (tmp1.isFixed()) { 665 *result = tmp1.getFixed(); 666 return true; 667 } 668 return false; 669 } 670 671 static inline SkFixed fracmuladdmul(SkFixed a, SkFract b, SkFixed c, 672 SkFract d) { 673 Sk64 tmp1, tmp2; 674 tmp1.setMul(a, b); 675 tmp2.setMul(c, d); 676 tmp1.add(tmp2); 677 return tmp1.getFract(); 678 } 679 680 static inline bool rowcol3(const SkFixed row[], const SkFixed col[], 681 SkFixed* result) { 682 Sk64 tmp1, tmp2; 683 684 tmp1.setMul(row[0], col[0]); // N * fixed 685 tmp2.setMul(row[1], col[3]); // N * fixed 686 tmp1.add(tmp2); 687 688 tmp2.setMul(row[2], col[6]); // N * fract 689 tmp2.roundRight(14); // make it fixed 690 tmp1.add(tmp2); 691 692 if (tmp1.isFixed()) { 693 *result = tmp1.getFixed(); 694 return true; 695 } 696 return false; 697 } 698 699 static inline int negifaddoverflows(SkFixed& result, SkFixed a, SkFixed b) { 700 SkFixed c = a + b; 701 result = c; 702 return (c ^ a) & (c ^ b); 703 } 704 #endif 705 706 static void normalize_perspective(SkScalar mat[9]) { 707 if (SkScalarAbs(mat[SkMatrix::kMPersp2]) > kMatrix22Elem) { 708 for (int i = 0; i < 9; i++) 709 mat[i] = SkScalarHalf(mat[i]); 710 } 711 } 712 713 bool SkMatrix::setConcat(const SkMatrix& a, const SkMatrix& b) { 714 TypeMask aType = a.getPerspectiveTypeMaskOnly(); 715 TypeMask bType = b.getPerspectiveTypeMaskOnly(); 716 717 if (a.isTriviallyIdentity()) { 718 *this = b; 719 } else if (b.isTriviallyIdentity()) { 720 *this = a; 721 } else { 722 SkMatrix tmp; 723 724 if ((aType | bType) & kPerspective_Mask) { 725 if (!rowcol3(&a.fMat[0], &b.fMat[0], &tmp.fMat[kMScaleX])) { 726 return false; 727 } 728 if (!rowcol3(&a.fMat[0], &b.fMat[1], &tmp.fMat[kMSkewX])) { 729 return false; 730 } 731 if (!rowcol3(&a.fMat[0], &b.fMat[2], &tmp.fMat[kMTransX])) { 732 return false; 733 } 734 735 if (!rowcol3(&a.fMat[3], &b.fMat[0], &tmp.fMat[kMSkewY])) { 736 return false; 737 } 738 if (!rowcol3(&a.fMat[3], &b.fMat[1], &tmp.fMat[kMScaleY])) { 739 return false; 740 } 741 if (!rowcol3(&a.fMat[3], &b.fMat[2], &tmp.fMat[kMTransY])) { 742 return false; 743 } 744 745 if (!rowcol3(&a.fMat[6], &b.fMat[0], &tmp.fMat[kMPersp0])) { 746 return false; 747 } 748 if (!rowcol3(&a.fMat[6], &b.fMat[1], &tmp.fMat[kMPersp1])) { 749 return false; 750 } 751 if (!rowcol3(&a.fMat[6], &b.fMat[2], &tmp.fMat[kMPersp2])) { 752 return false; 753 } 754 755 normalize_perspective(tmp.fMat); 756 tmp.setTypeMask(kUnknown_Mask); 757 } else { // not perspective 758 if (!fixmuladdmul(a.fMat[kMScaleX], b.fMat[kMScaleX], 759 a.fMat[kMSkewX], b.fMat[kMSkewY], &tmp.fMat[kMScaleX])) { 760 return false; 761 } 762 if (!fixmuladdmul(a.fMat[kMScaleX], b.fMat[kMSkewX], 763 a.fMat[kMSkewX], b.fMat[kMScaleY], &tmp.fMat[kMSkewX])) { 764 return false; 765 } 766 if (!fixmuladdmul(a.fMat[kMScaleX], b.fMat[kMTransX], 767 a.fMat[kMSkewX], b.fMat[kMTransY], &tmp.fMat[kMTransX])) { 768 return false; 769 } 770 if (negifaddoverflows(tmp.fMat[kMTransX], tmp.fMat[kMTransX], 771 a.fMat[kMTransX]) < 0) { 772 return false; 773 } 774 775 if (!fixmuladdmul(a.fMat[kMSkewY], b.fMat[kMScaleX], 776 a.fMat[kMScaleY], b.fMat[kMSkewY], &tmp.fMat[kMSkewY])) { 777 return false; 778 } 779 if (!fixmuladdmul(a.fMat[kMSkewY], b.fMat[kMSkewX], 780 a.fMat[kMScaleY], b.fMat[kMScaleY], &tmp.fMat[kMScaleY])) { 781 return false; 782 } 783 if (!fixmuladdmul(a.fMat[kMSkewY], b.fMat[kMTransX], 784 a.fMat[kMScaleY], b.fMat[kMTransY], &tmp.fMat[kMTransY])) { 785 return false; 786 } 787 if (negifaddoverflows(tmp.fMat[kMTransY], tmp.fMat[kMTransY], 788 a.fMat[kMTransY]) < 0) { 789 return false; 790 } 791 792 tmp.fMat[kMPersp0] = tmp.fMat[kMPersp1] = 0; 793 tmp.fMat[kMPersp2] = kMatrix22Elem; 794 //SkDebugf("Concat mat non-persp type: %d\n", tmp.getType()); 795 //SkASSERT(!(tmp.getType() & kPerspective_Mask)); 796 tmp.setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); 797 } 798 *this = tmp; 799 } 800 return true; 801 } 802 803 bool SkMatrix::preConcat(const SkMatrix& mat) { 804 // check for identity first, so we don't do a needless copy of ourselves 805 // to ourselves inside setConcat() 806 return mat.isIdentity() || this->setConcat(*this, mat); 807 } 808 809 bool SkMatrix::postConcat(const SkMatrix& mat) { 810 // check for identity first, so we don't do a needless copy of ourselves 811 // to ourselves inside setConcat() 812 return mat.isIdentity() || this->setConcat(mat, *this); 813 } 814 815 /////////////////////////////////////////////////////////////////////////////// 816 817 /* Matrix inversion is very expensive, but also the place where keeping 818 precision may be most important (here and matrix concat). Hence to avoid 819 bitmap blitting artifacts when walking the inverse, we use doubles for 820 the intermediate math, even though we know that is more expensive. 821 The fixed counter part is us using Sk64 for temp calculations. 822 */ 823 824 #ifdef SK_SCALAR_IS_FLOAT 825 typedef double SkDetScalar; 826 #define SkPerspMul(a, b) SkScalarMul(a, b) 827 #define SkScalarMulShift(a, b, s) SkDoubleToFloat((a) * (b)) 828 static double sk_inv_determinant(const float mat[9], int isPerspective, 829 int* /* (only used in Fixed case) */) { 830 double det; 831 832 if (isPerspective) { 833 det = mat[SkMatrix::kMScaleX] * ((double)mat[SkMatrix::kMScaleY] * mat[SkMatrix::kMPersp2] - (double)mat[SkMatrix::kMTransY] * mat[SkMatrix::kMPersp1]) + 834 mat[SkMatrix::kMSkewX] * ((double)mat[SkMatrix::kMTransY] * mat[SkMatrix::kMPersp0] - (double)mat[SkMatrix::kMSkewY] * mat[SkMatrix::kMPersp2]) + 835 mat[SkMatrix::kMTransX] * ((double)mat[SkMatrix::kMSkewY] * mat[SkMatrix::kMPersp1] - (double)mat[SkMatrix::kMScaleY] * mat[SkMatrix::kMPersp0]); 836 } else { 837 det = (double)mat[SkMatrix::kMScaleX] * mat[SkMatrix::kMScaleY] - (double)mat[SkMatrix::kMSkewX] * mat[SkMatrix::kMSkewY]; 838 } 839 840 // Since the determinant is on the order of the cube of the matrix members, 841 // compare to the cube of the default nearly-zero constant (although an 842 // estimate of the condition number would be better if it wasn't so expensive). 843 if (SkScalarNearlyZero((float)det, SK_ScalarNearlyZero * SK_ScalarNearlyZero * SK_ScalarNearlyZero)) { 844 return 0; 845 } 846 return 1.0 / det; 847 } 848 // we declar a,b,c,d to all be doubles, because we want to perform 849 // double-precision muls and subtract, even though the original values are 850 // from the matrix, which are floats. 851 static float inline mul_diff_scale(double a, double b, double c, double d, 852 double scale) { 853 return SkDoubleToFloat((a * b - c * d) * scale); 854 } 855 #else 856 typedef SkFixed SkDetScalar; 857 #define SkPerspMul(a, b) SkFractMul(a, b) 858 #define SkScalarMulShift(a, b, s) SkMulShift(a, b, s) 859 static void set_muladdmul(Sk64* dst, int32_t a, int32_t b, int32_t c, 860 int32_t d) { 861 Sk64 tmp; 862 dst->setMul(a, b); 863 tmp.setMul(c, d); 864 dst->add(tmp); 865 } 866 867 static SkFixed sk_inv_determinant(const SkFixed mat[9], int isPerspective, 868 int* shift) { 869 Sk64 tmp1, tmp2; 870 871 if (isPerspective) { 872 tmp1.setMul(mat[SkMatrix::kMScaleX], fracmuladdmul(mat[SkMatrix::kMScaleY], mat[SkMatrix::kMPersp2], -mat[SkMatrix::kMTransY], mat[SkMatrix::kMPersp1])); 873 tmp2.setMul(mat[SkMatrix::kMSkewX], fracmuladdmul(mat[SkMatrix::kMTransY], mat[SkMatrix::kMPersp0], -mat[SkMatrix::kMSkewY], mat[SkMatrix::kMPersp2])); 874 tmp1.add(tmp2); 875 tmp2.setMul(mat[SkMatrix::kMTransX], fracmuladdmul(mat[SkMatrix::kMSkewY], mat[SkMatrix::kMPersp1], -mat[SkMatrix::kMScaleY], mat[SkMatrix::kMPersp0])); 876 tmp1.add(tmp2); 877 } else { 878 tmp1.setMul(mat[SkMatrix::kMScaleX], mat[SkMatrix::kMScaleY]); 879 tmp2.setMul(mat[SkMatrix::kMSkewX], mat[SkMatrix::kMSkewY]); 880 tmp1.sub(tmp2); 881 } 882 883 int s = tmp1.getClzAbs(); 884 *shift = s; 885 886 SkFixed denom; 887 if (s <= 32) { 888 denom = tmp1.getShiftRight(33 - s); 889 } else { 890 denom = (int32_t)tmp1.fLo << (s - 33); 891 } 892 893 if (denom == 0) { 894 return 0; 895 } 896 /** This could perhaps be a special fractdiv function, since both of its 897 arguments are known to have bit 31 clear and bit 30 set (when they 898 are made positive), thus eliminating the need for calling clz() 899 */ 900 return SkFractDiv(SK_Fract1, denom); 901 } 902 #endif 903 904 void SkMatrix::SetAffineIdentity(SkScalar affine[6]) { 905 affine[kAScaleX] = SK_Scalar1; 906 affine[kASkewY] = 0; 907 affine[kASkewX] = 0; 908 affine[kAScaleY] = SK_Scalar1; 909 affine[kATransX] = 0; 910 affine[kATransY] = 0; 911 } 912 913 bool SkMatrix::asAffine(SkScalar affine[6]) const { 914 if (this->hasPerspective()) { 915 return false; 916 } 917 if (affine) { 918 affine[kAScaleX] = this->fMat[kMScaleX]; 919 affine[kASkewY] = this->fMat[kMSkewY]; 920 affine[kASkewX] = this->fMat[kMSkewX]; 921 affine[kAScaleY] = this->fMat[kMScaleY]; 922 affine[kATransX] = this->fMat[kMTransX]; 923 affine[kATransY] = this->fMat[kMTransY]; 924 } 925 return true; 926 } 927 928 bool SkMatrix::invertNonIdentity(SkMatrix* inv) const { 929 SkASSERT(!this->isIdentity()); 930 931 TypeMask mask = this->getType(); 932 933 if (0 == (mask & ~(kScale_Mask | kTranslate_Mask))) { 934 bool invertible = true; 935 if (inv) { 936 if (mask & kScale_Mask) { 937 SkScalar invX = fMat[kMScaleX]; 938 SkScalar invY = fMat[kMScaleY]; 939 if (0 == invX || 0 == invY) { 940 return false; 941 } 942 invX = SkScalarInvert(invX); 943 invY = SkScalarInvert(invY); 944 945 // Must be careful when writing to inv, since it may be the 946 // same memory as this. 947 948 inv->fMat[kMSkewX] = inv->fMat[kMSkewY] = 949 inv->fMat[kMPersp0] = inv->fMat[kMPersp1] = 0; 950 951 inv->fMat[kMScaleX] = invX; 952 inv->fMat[kMScaleY] = invY; 953 inv->fMat[kMPersp2] = kMatrix22Elem; 954 inv->fMat[kMTransX] = -SkScalarMul(fMat[kMTransX], invX); 955 inv->fMat[kMTransY] = -SkScalarMul(fMat[kMTransY], invY); 956 957 inv->setTypeMask(mask | kRectStaysRect_Mask); 958 } else { 959 // translate only 960 inv->setTranslate(-fMat[kMTransX], -fMat[kMTransY]); 961 } 962 } else { // inv is NULL, just check if we're invertible 963 if (!fMat[kMScaleX] || !fMat[kMScaleY]) { 964 invertible = false; 965 } 966 } 967 return invertible; 968 } 969 970 int isPersp = mask & kPerspective_Mask; 971 int shift; 972 SkDetScalar scale = sk_inv_determinant(fMat, isPersp, &shift); 973 974 if (scale == 0) { // underflow 975 return false; 976 } 977 978 if (inv) { 979 SkMatrix tmp; 980 if (inv == this) { 981 inv = &tmp; 982 } 983 984 if (isPersp) { 985 shift = 61 - shift; 986 inv->fMat[kMScaleX] = SkScalarMulShift(SkPerspMul(fMat[kMScaleY], fMat[kMPersp2]) - SkPerspMul(fMat[kMTransY], fMat[kMPersp1]), scale, shift); 987 inv->fMat[kMSkewX] = SkScalarMulShift(SkPerspMul(fMat[kMTransX], fMat[kMPersp1]) - SkPerspMul(fMat[kMSkewX], fMat[kMPersp2]), scale, shift); 988 inv->fMat[kMTransX] = SkScalarMulShift(SkScalarMul(fMat[kMSkewX], fMat[kMTransY]) - SkScalarMul(fMat[kMTransX], fMat[kMScaleY]), scale, shift); 989 990 inv->fMat[kMSkewY] = SkScalarMulShift(SkPerspMul(fMat[kMTransY], fMat[kMPersp0]) - SkPerspMul(fMat[kMSkewY], fMat[kMPersp2]), scale, shift); 991 inv->fMat[kMScaleY] = SkScalarMulShift(SkPerspMul(fMat[kMScaleX], fMat[kMPersp2]) - SkPerspMul(fMat[kMTransX], fMat[kMPersp0]), scale, shift); 992 inv->fMat[kMTransY] = SkScalarMulShift(SkScalarMul(fMat[kMTransX], fMat[kMSkewY]) - SkScalarMul(fMat[kMScaleX], fMat[kMTransY]), scale, shift); 993 994 inv->fMat[kMPersp0] = SkScalarMulShift(SkScalarMul(fMat[kMSkewY], fMat[kMPersp1]) - SkScalarMul(fMat[kMScaleY], fMat[kMPersp0]), scale, shift); 995 inv->fMat[kMPersp1] = SkScalarMulShift(SkScalarMul(fMat[kMSkewX], fMat[kMPersp0]) - SkScalarMul(fMat[kMScaleX], fMat[kMPersp1]), scale, shift); 996 inv->fMat[kMPersp2] = SkScalarMulShift(SkScalarMul(fMat[kMScaleX], fMat[kMScaleY]) - SkScalarMul(fMat[kMSkewX], fMat[kMSkewY]), scale, shift); 997 #ifdef SK_SCALAR_IS_FIXED 998 if (SkAbs32(inv->fMat[kMPersp2]) > SK_Fixed1) { 999 Sk64 tmp; 1000 1001 tmp.set(SK_Fract1); 1002 tmp.shiftLeft(16); 1003 tmp.div(inv->fMat[kMPersp2], Sk64::kRound_DivOption); 1004 1005 SkFract scale = tmp.get32(); 1006 1007 for (int i = 0; i < 9; i++) { 1008 inv->fMat[i] = SkFractMul(inv->fMat[i], scale); 1009 } 1010 } 1011 inv->fMat[kMPersp2] = SkFixedToFract(inv->fMat[kMPersp2]); 1012 #endif 1013 } else { // not perspective 1014 #ifdef SK_SCALAR_IS_FIXED 1015 Sk64 tx, ty; 1016 int clzNumer; 1017 1018 // check the 2x2 for overflow 1019 { 1020 int32_t value = SkAbs32(fMat[kMScaleY]); 1021 value |= SkAbs32(fMat[kMSkewX]); 1022 value |= SkAbs32(fMat[kMScaleX]); 1023 value |= SkAbs32(fMat[kMSkewY]); 1024 clzNumer = SkCLZ(value); 1025 if (shift - clzNumer > 31) 1026 return false; // overflow 1027 } 1028 1029 set_muladdmul(&tx, fMat[kMSkewX], fMat[kMTransY], -fMat[kMScaleY], fMat[kMTransX]); 1030 set_muladdmul(&ty, fMat[kMSkewY], fMat[kMTransX], -fMat[kMScaleX], fMat[kMTransY]); 1031 // check tx,ty for overflow 1032 clzNumer = SkCLZ(SkAbs32(tx.fHi) | SkAbs32(ty.fHi)); 1033 if (shift - clzNumer > 14) { 1034 return false; // overflow 1035 } 1036 1037 int fixedShift = 61 - shift; 1038 int sk64shift = 44 - shift + clzNumer; 1039 1040 inv->fMat[kMScaleX] = SkMulShift(fMat[kMScaleY], scale, fixedShift); 1041 inv->fMat[kMSkewX] = SkMulShift(-fMat[kMSkewX], scale, fixedShift); 1042 inv->fMat[kMTransX] = SkMulShift(tx.getShiftRight(33 - clzNumer), scale, sk64shift); 1043 1044 inv->fMat[kMSkewY] = SkMulShift(-fMat[kMSkewY], scale, fixedShift); 1045 inv->fMat[kMScaleY] = SkMulShift(fMat[kMScaleX], scale, fixedShift); 1046 inv->fMat[kMTransY] = SkMulShift(ty.getShiftRight(33 - clzNumer), scale, sk64shift); 1047 #else 1048 inv->fMat[kMScaleX] = SkDoubleToFloat(fMat[kMScaleY] * scale); 1049 inv->fMat[kMSkewX] = SkDoubleToFloat(-fMat[kMSkewX] * scale); 1050 inv->fMat[kMTransX] = mul_diff_scale(fMat[kMSkewX], fMat[kMTransY], 1051 fMat[kMScaleY], fMat[kMTransX], scale); 1052 1053 inv->fMat[kMSkewY] = SkDoubleToFloat(-fMat[kMSkewY] * scale); 1054 inv->fMat[kMScaleY] = SkDoubleToFloat(fMat[kMScaleX] * scale); 1055 inv->fMat[kMTransY] = mul_diff_scale(fMat[kMSkewY], fMat[kMTransX], 1056 fMat[kMScaleX], fMat[kMTransY], scale); 1057 #endif 1058 inv->fMat[kMPersp0] = 0; 1059 inv->fMat[kMPersp1] = 0; 1060 inv->fMat[kMPersp2] = kMatrix22Elem; 1061 1062 } 1063 1064 inv->setTypeMask(fTypeMask); 1065 1066 if (inv == &tmp) { 1067 *(SkMatrix*)this = tmp; 1068 } 1069 } 1070 return true; 1071 } 1072 1073 /////////////////////////////////////////////////////////////////////////////// 1074 1075 void SkMatrix::Identity_pts(const SkMatrix& m, SkPoint dst[], 1076 const SkPoint src[], int count) { 1077 SkASSERT(m.getType() == 0); 1078 1079 if (dst != src && count > 0) 1080 memcpy(dst, src, count * sizeof(SkPoint)); 1081 } 1082 1083 void SkMatrix::Trans_pts(const SkMatrix& m, SkPoint dst[], 1084 const SkPoint src[], int count) { 1085 SkASSERT(m.getType() == kTranslate_Mask); 1086 1087 if (count > 0) { 1088 SkScalar tx = m.fMat[kMTransX]; 1089 SkScalar ty = m.fMat[kMTransY]; 1090 do { 1091 dst->fY = src->fY + ty; 1092 dst->fX = src->fX + tx; 1093 src += 1; 1094 dst += 1; 1095 } while (--count); 1096 } 1097 } 1098 1099 void SkMatrix::Scale_pts(const SkMatrix& m, SkPoint dst[], 1100 const SkPoint src[], int count) { 1101 SkASSERT(m.getType() == kScale_Mask); 1102 1103 if (count > 0) { 1104 SkScalar mx = m.fMat[kMScaleX]; 1105 SkScalar my = m.fMat[kMScaleY]; 1106 do { 1107 dst->fY = SkScalarMul(src->fY, my); 1108 dst->fX = SkScalarMul(src->fX, mx); 1109 src += 1; 1110 dst += 1; 1111 } while (--count); 1112 } 1113 } 1114 1115 void SkMatrix::ScaleTrans_pts(const SkMatrix& m, SkPoint dst[], 1116 const SkPoint src[], int count) { 1117 SkASSERT(m.getType() == (kScale_Mask | kTranslate_Mask)); 1118 1119 if (count > 0) { 1120 SkScalar mx = m.fMat[kMScaleX]; 1121 SkScalar my = m.fMat[kMScaleY]; 1122 SkScalar tx = m.fMat[kMTransX]; 1123 SkScalar ty = m.fMat[kMTransY]; 1124 do { 1125 dst->fY = SkScalarMulAdd(src->fY, my, ty); 1126 dst->fX = SkScalarMulAdd(src->fX, mx, tx); 1127 src += 1; 1128 dst += 1; 1129 } while (--count); 1130 } 1131 } 1132 1133 void SkMatrix::Rot_pts(const SkMatrix& m, SkPoint dst[], 1134 const SkPoint src[], int count) { 1135 SkASSERT((m.getType() & (kPerspective_Mask | kTranslate_Mask)) == 0); 1136 1137 if (count > 0) { 1138 SkScalar mx = m.fMat[kMScaleX]; 1139 SkScalar my = m.fMat[kMScaleY]; 1140 SkScalar kx = m.fMat[kMSkewX]; 1141 SkScalar ky = m.fMat[kMSkewY]; 1142 do { 1143 SkScalar sy = src->fY; 1144 SkScalar sx = src->fX; 1145 src += 1; 1146 dst->fY = SkScalarMul(sx, ky) + SkScalarMul(sy, my); 1147 dst->fX = SkScalarMul(sx, mx) + SkScalarMul(sy, kx); 1148 dst += 1; 1149 } while (--count); 1150 } 1151 } 1152 1153 void SkMatrix::RotTrans_pts(const SkMatrix& m, SkPoint dst[], 1154 const SkPoint src[], int count) { 1155 SkASSERT(!m.hasPerspective()); 1156 1157 if (count > 0) { 1158 SkScalar mx = m.fMat[kMScaleX]; 1159 SkScalar my = m.fMat[kMScaleY]; 1160 SkScalar kx = m.fMat[kMSkewX]; 1161 SkScalar ky = m.fMat[kMSkewY]; 1162 SkScalar tx = m.fMat[kMTransX]; 1163 SkScalar ty = m.fMat[kMTransY]; 1164 do { 1165 SkScalar sy = src->fY; 1166 SkScalar sx = src->fX; 1167 src += 1; 1168 dst->fY = SkScalarMul(sx, ky) + SkScalarMulAdd(sy, my, ty); 1169 dst->fX = SkScalarMul(sx, mx) + SkScalarMulAdd(sy, kx, tx); 1170 dst += 1; 1171 } while (--count); 1172 } 1173 } 1174 1175 void SkMatrix::Persp_pts(const SkMatrix& m, SkPoint dst[], 1176 const SkPoint src[], int count) { 1177 SkASSERT(m.hasPerspective()); 1178 1179 #ifdef SK_SCALAR_IS_FIXED 1180 SkFixed persp2 = SkFractToFixed(m.fMat[kMPersp2]); 1181 #endif 1182 1183 if (count > 0) { 1184 do { 1185 SkScalar sy = src->fY; 1186 SkScalar sx = src->fX; 1187 src += 1; 1188 1189 SkScalar x = SkScalarMul(sx, m.fMat[kMScaleX]) + 1190 SkScalarMul(sy, m.fMat[kMSkewX]) + m.fMat[kMTransX]; 1191 SkScalar y = SkScalarMul(sx, m.fMat[kMSkewY]) + 1192 SkScalarMul(sy, m.fMat[kMScaleY]) + m.fMat[kMTransY]; 1193 #ifdef SK_SCALAR_IS_FIXED 1194 SkFixed z = SkFractMul(sx, m.fMat[kMPersp0]) + 1195 SkFractMul(sy, m.fMat[kMPersp1]) + persp2; 1196 #else 1197 float z = SkScalarMul(sx, m.fMat[kMPersp0]) + 1198 SkScalarMulAdd(sy, m.fMat[kMPersp1], m.fMat[kMPersp2]); 1199 #endif 1200 if (z) { 1201 z = SkScalarFastInvert(z); 1202 } 1203 1204 dst->fY = SkScalarMul(y, z); 1205 dst->fX = SkScalarMul(x, z); 1206 dst += 1; 1207 } while (--count); 1208 } 1209 } 1210 1211 const SkMatrix::MapPtsProc SkMatrix::gMapPtsProcs[] = { 1212 SkMatrix::Identity_pts, SkMatrix::Trans_pts, 1213 SkMatrix::Scale_pts, SkMatrix::ScaleTrans_pts, 1214 SkMatrix::Rot_pts, SkMatrix::RotTrans_pts, 1215 SkMatrix::Rot_pts, SkMatrix::RotTrans_pts, 1216 // repeat the persp proc 8 times 1217 SkMatrix::Persp_pts, SkMatrix::Persp_pts, 1218 SkMatrix::Persp_pts, SkMatrix::Persp_pts, 1219 SkMatrix::Persp_pts, SkMatrix::Persp_pts, 1220 SkMatrix::Persp_pts, SkMatrix::Persp_pts 1221 }; 1222 1223 void SkMatrix::mapPoints(SkPoint dst[], const SkPoint src[], int count) const { 1224 SkASSERT((dst && src && count > 0) || 0 == count); 1225 // no partial overlap 1226 SkASSERT(src == dst || &dst[count] <= &src[0] || &src[count] <= &dst[0]); 1227 1228 this->getMapPtsProc()(*this, dst, src, count); 1229 } 1230 1231 /////////////////////////////////////////////////////////////////////////////// 1232 1233 void SkMatrix::mapHomogeneousPoints(SkScalar dst[], const SkScalar src[], int count) const { 1234 SkASSERT((dst && src && count > 0) || 0 == count); 1235 // no partial overlap 1236 SkASSERT(src == dst || SkAbs32((int32_t)(src - dst)) >= 3*count); 1237 1238 if (count > 0) { 1239 if (this->isIdentity()) { 1240 memcpy(dst, src, 3*count*sizeof(SkScalar)); 1241 return; 1242 } 1243 do { 1244 SkScalar sx = src[0]; 1245 SkScalar sy = src[1]; 1246 SkScalar sw = src[2]; 1247 src += 3; 1248 1249 SkScalar x = SkScalarMul(sx, fMat[kMScaleX]) + 1250 SkScalarMul(sy, fMat[kMSkewX]) + 1251 SkScalarMul(sw, fMat[kMTransX]); 1252 SkScalar y = SkScalarMul(sx, fMat[kMSkewY]) + 1253 SkScalarMul(sy, fMat[kMScaleY]) + 1254 SkScalarMul(sw, fMat[kMTransY]); 1255 SkScalar w = SkScalarMul(sx, fMat[kMPersp0]) + 1256 SkScalarMul(sy, fMat[kMPersp1]) + 1257 SkScalarMul(sw, fMat[kMPersp2]); 1258 1259 dst[0] = x; 1260 dst[1] = y; 1261 dst[2] = w; 1262 dst += 3; 1263 } while (--count); 1264 } 1265 } 1266 1267 /////////////////////////////////////////////////////////////////////////////// 1268 1269 void SkMatrix::mapVectors(SkPoint dst[], const SkPoint src[], int count) const { 1270 if (this->hasPerspective()) { 1271 SkPoint origin; 1272 1273 MapXYProc proc = this->getMapXYProc(); 1274 proc(*this, 0, 0, &origin); 1275 1276 for (int i = count - 1; i >= 0; --i) { 1277 SkPoint tmp; 1278 1279 proc(*this, src[i].fX, src[i].fY, &tmp); 1280 dst[i].set(tmp.fX - origin.fX, tmp.fY - origin.fY); 1281 } 1282 } else { 1283 SkMatrix tmp = *this; 1284 1285 tmp.fMat[kMTransX] = tmp.fMat[kMTransY] = 0; 1286 tmp.clearTypeMask(kTranslate_Mask); 1287 tmp.mapPoints(dst, src, count); 1288 } 1289 } 1290 1291 bool SkMatrix::mapRect(SkRect* dst, const SkRect& src) const { 1292 SkASSERT(dst && &src); 1293 1294 if (this->rectStaysRect()) { 1295 this->mapPoints((SkPoint*)dst, (const SkPoint*)&src, 2); 1296 dst->sort(); 1297 return true; 1298 } else { 1299 SkPoint quad[4]; 1300 1301 src.toQuad(quad); 1302 this->mapPoints(quad, quad, 4); 1303 dst->set(quad, 4); 1304 return false; 1305 } 1306 } 1307 1308 SkScalar SkMatrix::mapRadius(SkScalar radius) const { 1309 SkVector vec[2]; 1310 1311 vec[0].set(radius, 0); 1312 vec[1].set(0, radius); 1313 this->mapVectors(vec, 2); 1314 1315 SkScalar d0 = vec[0].length(); 1316 SkScalar d1 = vec[1].length(); 1317 1318 return SkScalarMean(d0, d1); 1319 } 1320 1321 /////////////////////////////////////////////////////////////////////////////// 1322 1323 void SkMatrix::Persp_xy(const SkMatrix& m, SkScalar sx, SkScalar sy, 1324 SkPoint* pt) { 1325 SkASSERT(m.hasPerspective()); 1326 1327 SkScalar x = SkScalarMul(sx, m.fMat[kMScaleX]) + 1328 SkScalarMul(sy, m.fMat[kMSkewX]) + m.fMat[kMTransX]; 1329 SkScalar y = SkScalarMul(sx, m.fMat[kMSkewY]) + 1330 SkScalarMul(sy, m.fMat[kMScaleY]) + m.fMat[kMTransY]; 1331 #ifdef SK_SCALAR_IS_FIXED 1332 SkFixed z = SkFractMul(sx, m.fMat[kMPersp0]) + 1333 SkFractMul(sy, m.fMat[kMPersp1]) + 1334 SkFractToFixed(m.fMat[kMPersp2]); 1335 #else 1336 float z = SkScalarMul(sx, m.fMat[kMPersp0]) + 1337 SkScalarMul(sy, m.fMat[kMPersp1]) + m.fMat[kMPersp2]; 1338 #endif 1339 if (z) { 1340 z = SkScalarFastInvert(z); 1341 } 1342 pt->fX = SkScalarMul(x, z); 1343 pt->fY = SkScalarMul(y, z); 1344 } 1345 1346 #ifdef SK_SCALAR_IS_FIXED 1347 static SkFixed fixmuladdmul(SkFixed a, SkFixed b, SkFixed c, SkFixed d) { 1348 Sk64 tmp, tmp1; 1349 1350 tmp.setMul(a, b); 1351 tmp1.setMul(c, d); 1352 return tmp.addGetFixed(tmp1); 1353 // tmp.add(tmp1); 1354 // return tmp.getFixed(); 1355 } 1356 #endif 1357 1358 void SkMatrix::RotTrans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy, 1359 SkPoint* pt) { 1360 SkASSERT((m.getType() & (kAffine_Mask | kPerspective_Mask)) == kAffine_Mask); 1361 1362 #ifdef SK_SCALAR_IS_FIXED 1363 pt->fX = fixmuladdmul(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX]) + 1364 m.fMat[kMTransX]; 1365 pt->fY = fixmuladdmul(sx, m.fMat[kMSkewY], sy, m.fMat[kMScaleY]) + 1366 m.fMat[kMTransY]; 1367 #else 1368 pt->fX = SkScalarMul(sx, m.fMat[kMScaleX]) + 1369 SkScalarMulAdd(sy, m.fMat[kMSkewX], m.fMat[kMTransX]); 1370 pt->fY = SkScalarMul(sx, m.fMat[kMSkewY]) + 1371 SkScalarMulAdd(sy, m.fMat[kMScaleY], m.fMat[kMTransY]); 1372 #endif 1373 } 1374 1375 void SkMatrix::Rot_xy(const SkMatrix& m, SkScalar sx, SkScalar sy, 1376 SkPoint* pt) { 1377 SkASSERT((m.getType() & (kAffine_Mask | kPerspective_Mask))== kAffine_Mask); 1378 SkASSERT(0 == m.fMat[kMTransX]); 1379 SkASSERT(0 == m.fMat[kMTransY]); 1380 1381 #ifdef SK_SCALAR_IS_FIXED 1382 pt->fX = fixmuladdmul(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX]); 1383 pt->fY = fixmuladdmul(sx, m.fMat[kMSkewY], sy, m.fMat[kMScaleY]); 1384 #else 1385 pt->fX = SkScalarMul(sx, m.fMat[kMScaleX]) + 1386 SkScalarMulAdd(sy, m.fMat[kMSkewX], m.fMat[kMTransX]); 1387 pt->fY = SkScalarMul(sx, m.fMat[kMSkewY]) + 1388 SkScalarMulAdd(sy, m.fMat[kMScaleY], m.fMat[kMTransY]); 1389 #endif 1390 } 1391 1392 void SkMatrix::ScaleTrans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy, 1393 SkPoint* pt) { 1394 SkASSERT((m.getType() & (kScale_Mask | kAffine_Mask | kPerspective_Mask)) 1395 == kScale_Mask); 1396 1397 pt->fX = SkScalarMulAdd(sx, m.fMat[kMScaleX], m.fMat[kMTransX]); 1398 pt->fY = SkScalarMulAdd(sy, m.fMat[kMScaleY], m.fMat[kMTransY]); 1399 } 1400 1401 void SkMatrix::Scale_xy(const SkMatrix& m, SkScalar sx, SkScalar sy, 1402 SkPoint* pt) { 1403 SkASSERT((m.getType() & (kScale_Mask | kAffine_Mask | kPerspective_Mask)) 1404 == kScale_Mask); 1405 SkASSERT(0 == m.fMat[kMTransX]); 1406 SkASSERT(0 == m.fMat[kMTransY]); 1407 1408 pt->fX = SkScalarMul(sx, m.fMat[kMScaleX]); 1409 pt->fY = SkScalarMul(sy, m.fMat[kMScaleY]); 1410 } 1411 1412 void SkMatrix::Trans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy, 1413 SkPoint* pt) { 1414 SkASSERT(m.getType() == kTranslate_Mask); 1415 1416 pt->fX = sx + m.fMat[kMTransX]; 1417 pt->fY = sy + m.fMat[kMTransY]; 1418 } 1419 1420 void SkMatrix::Identity_xy(const SkMatrix& m, SkScalar sx, SkScalar sy, 1421 SkPoint* pt) { 1422 SkASSERT(0 == m.getType()); 1423 1424 pt->fX = sx; 1425 pt->fY = sy; 1426 } 1427 1428 const SkMatrix::MapXYProc SkMatrix::gMapXYProcs[] = { 1429 SkMatrix::Identity_xy, SkMatrix::Trans_xy, 1430 SkMatrix::Scale_xy, SkMatrix::ScaleTrans_xy, 1431 SkMatrix::Rot_xy, SkMatrix::RotTrans_xy, 1432 SkMatrix::Rot_xy, SkMatrix::RotTrans_xy, 1433 // repeat the persp proc 8 times 1434 SkMatrix::Persp_xy, SkMatrix::Persp_xy, 1435 SkMatrix::Persp_xy, SkMatrix::Persp_xy, 1436 SkMatrix::Persp_xy, SkMatrix::Persp_xy, 1437 SkMatrix::Persp_xy, SkMatrix::Persp_xy 1438 }; 1439 1440 /////////////////////////////////////////////////////////////////////////////// 1441 1442 // if its nearly zero (just made up 26, perhaps it should be bigger or smaller) 1443 #ifdef SK_SCALAR_IS_FIXED 1444 typedef SkFract SkPerspElemType; 1445 #define PerspNearlyZero(x) (SkAbs32(x) < (SK_Fract1 >> 26)) 1446 #else 1447 typedef float SkPerspElemType; 1448 #define PerspNearlyZero(x) SkScalarNearlyZero(x, (1.0f / (1 << 26))) 1449 #endif 1450 1451 bool SkMatrix::fixedStepInX(SkScalar y, SkFixed* stepX, SkFixed* stepY) const { 1452 if (PerspNearlyZero(fMat[kMPersp0])) { 1453 if (stepX || stepY) { 1454 if (PerspNearlyZero(fMat[kMPersp1]) && 1455 PerspNearlyZero(fMat[kMPersp2] - kMatrix22Elem)) { 1456 if (stepX) { 1457 *stepX = SkScalarToFixed(fMat[kMScaleX]); 1458 } 1459 if (stepY) { 1460 *stepY = SkScalarToFixed(fMat[kMSkewY]); 1461 } 1462 } else { 1463 #ifdef SK_SCALAR_IS_FIXED 1464 SkFixed z = SkFractMul(y, fMat[kMPersp1]) + 1465 SkFractToFixed(fMat[kMPersp2]); 1466 #else 1467 float z = y * fMat[kMPersp1] + fMat[kMPersp2]; 1468 #endif 1469 if (stepX) { 1470 *stepX = SkScalarToFixed(SkScalarDiv(fMat[kMScaleX], z)); 1471 } 1472 if (stepY) { 1473 *stepY = SkScalarToFixed(SkScalarDiv(fMat[kMSkewY], z)); 1474 } 1475 } 1476 } 1477 return true; 1478 } 1479 return false; 1480 } 1481 1482 /////////////////////////////////////////////////////////////////////////////// 1483 1484 #include "SkPerspIter.h" 1485 1486 SkPerspIter::SkPerspIter(const SkMatrix& m, SkScalar x0, SkScalar y0, int count) 1487 : fMatrix(m), fSX(x0), fSY(y0), fCount(count) { 1488 SkPoint pt; 1489 1490 SkMatrix::Persp_xy(m, x0, y0, &pt); 1491 fX = SkScalarToFixed(pt.fX); 1492 fY = SkScalarToFixed(pt.fY); 1493 } 1494 1495 int SkPerspIter::next() { 1496 int n = fCount; 1497 1498 if (0 == n) { 1499 return 0; 1500 } 1501 SkPoint pt; 1502 SkFixed x = fX; 1503 SkFixed y = fY; 1504 SkFixed dx, dy; 1505 1506 if (n >= kCount) { 1507 n = kCount; 1508 fSX += SkIntToScalar(kCount); 1509 SkMatrix::Persp_xy(fMatrix, fSX, fSY, &pt); 1510 fX = SkScalarToFixed(pt.fX); 1511 fY = SkScalarToFixed(pt.fY); 1512 dx = (fX - x) >> kShift; 1513 dy = (fY - y) >> kShift; 1514 } else { 1515 fSX += SkIntToScalar(n); 1516 SkMatrix::Persp_xy(fMatrix, fSX, fSY, &pt); 1517 fX = SkScalarToFixed(pt.fX); 1518 fY = SkScalarToFixed(pt.fY); 1519 dx = (fX - x) / n; 1520 dy = (fY - y) / n; 1521 } 1522 1523 SkFixed* p = fStorage; 1524 for (int i = 0; i < n; i++) { 1525 *p++ = x; x += dx; 1526 *p++ = y; y += dy; 1527 } 1528 1529 fCount -= n; 1530 return n; 1531 } 1532 1533 /////////////////////////////////////////////////////////////////////////////// 1534 1535 #ifdef SK_SCALAR_IS_FIXED 1536 1537 static inline bool poly_to_point(SkPoint* pt, const SkPoint poly[], int count) { 1538 SkFixed x = SK_Fixed1, y = SK_Fixed1; 1539 SkPoint pt1, pt2; 1540 Sk64 w1, w2; 1541 1542 if (count > 1) { 1543 pt1.fX = poly[1].fX - poly[0].fX; 1544 pt1.fY = poly[1].fY - poly[0].fY; 1545 y = SkPoint::Length(pt1.fX, pt1.fY); 1546 if (y == 0) { 1547 return false; 1548 } 1549 switch (count) { 1550 case 2: 1551 break; 1552 case 3: 1553 pt2.fX = poly[0].fY - poly[2].fY; 1554 pt2.fY = poly[2].fX - poly[0].fX; 1555 goto CALC_X; 1556 default: 1557 pt2.fX = poly[0].fY - poly[3].fY; 1558 pt2.fY = poly[3].fX - poly[0].fX; 1559 CALC_X: 1560 w1.setMul(pt1.fX, pt2.fX); 1561 w2.setMul(pt1.fY, pt2.fY); 1562 w1.add(w2); 1563 w1.div(y, Sk64::kRound_DivOption); 1564 if (!w1.is32()) { 1565 return false; 1566 } 1567 x = w1.get32(); 1568 break; 1569 } 1570 } 1571 pt->set(x, y); 1572 return true; 1573 } 1574 1575 bool SkMatrix::Poly2Proc(const SkPoint srcPt[], SkMatrix* dst, 1576 const SkPoint& scalePt) { 1577 // need to check if SkFixedDiv overflows... 1578 1579 const SkFixed scale = scalePt.fY; 1580 dst->fMat[kMScaleX] = SkFixedDiv(srcPt[1].fY - srcPt[0].fY, scale); 1581 dst->fMat[kMSkewY] = SkFixedDiv(srcPt[0].fX - srcPt[1].fX, scale); 1582 dst->fMat[kMPersp0] = 0; 1583 dst->fMat[kMSkewX] = SkFixedDiv(srcPt[1].fX - srcPt[0].fX, scale); 1584 dst->fMat[kMScaleY] = SkFixedDiv(srcPt[1].fY - srcPt[0].fY, scale); 1585 dst->fMat[kMPersp1] = 0; 1586 dst->fMat[kMTransX] = srcPt[0].fX; 1587 dst->fMat[kMTransY] = srcPt[0].fY; 1588 dst->fMat[kMPersp2] = SK_Fract1; 1589 dst->setTypeMask(kUnknown_Mask); 1590 return true; 1591 } 1592 1593 bool SkMatrix::Poly3Proc(const SkPoint srcPt[], SkMatrix* dst, 1594 const SkPoint& scale) { 1595 // really, need to check if SkFixedDiv overflow'd 1596 1597 dst->fMat[kMScaleX] = SkFixedDiv(srcPt[2].fX - srcPt[0].fX, scale.fX); 1598 dst->fMat[kMSkewY] = SkFixedDiv(srcPt[2].fY - srcPt[0].fY, scale.fX); 1599 dst->fMat[kMPersp0] = 0; 1600 dst->fMat[kMSkewX] = SkFixedDiv(srcPt[1].fX - srcPt[0].fX, scale.fY); 1601 dst->fMat[kMScaleY] = SkFixedDiv(srcPt[1].fY - srcPt[0].fY, scale.fY); 1602 dst->fMat[kMPersp1] = 0; 1603 dst->fMat[kMTransX] = srcPt[0].fX; 1604 dst->fMat[kMTransY] = srcPt[0].fY; 1605 dst->fMat[kMPersp2] = SK_Fract1; 1606 dst->setTypeMask(kUnknown_Mask); 1607 return true; 1608 } 1609 1610 bool SkMatrix::Poly4Proc(const SkPoint srcPt[], SkMatrix* dst, 1611 const SkPoint& scale) { 1612 SkFract a1, a2; 1613 SkFixed x0, y0, x1, y1, x2, y2; 1614 1615 x0 = srcPt[2].fX - srcPt[0].fX; 1616 y0 = srcPt[2].fY - srcPt[0].fY; 1617 x1 = srcPt[2].fX - srcPt[1].fX; 1618 y1 = srcPt[2].fY - srcPt[1].fY; 1619 x2 = srcPt[2].fX - srcPt[3].fX; 1620 y2 = srcPt[2].fY - srcPt[3].fY; 1621 1622 /* check if abs(x2) > abs(y2) */ 1623 if ( x2 > 0 ? y2 > 0 ? x2 > y2 : x2 > -y2 : y2 > 0 ? -x2 > y2 : x2 < y2) { 1624 SkFixed denom = SkMulDiv(x1, y2, x2) - y1; 1625 if (0 == denom) { 1626 return false; 1627 } 1628 a1 = SkFractDiv(SkMulDiv(x0 - x1, y2, x2) - y0 + y1, denom); 1629 } else { 1630 SkFixed denom = x1 - SkMulDiv(y1, x2, y2); 1631 if (0 == denom) { 1632 return false; 1633 } 1634 a1 = SkFractDiv(x0 - x1 - SkMulDiv(y0 - y1, x2, y2), denom); 1635 } 1636 1637 /* check if abs(x1) > abs(y1) */ 1638 if ( x1 > 0 ? y1 > 0 ? x1 > y1 : x1 > -y1 : y1 > 0 ? -x1 > y1 : x1 < y1) { 1639 SkFixed denom = y2 - SkMulDiv(x2, y1, x1); 1640 if (0 == denom) { 1641 return false; 1642 } 1643 a2 = SkFractDiv(y0 - y2 - SkMulDiv(x0 - x2, y1, x1), denom); 1644 } else { 1645 SkFixed denom = SkMulDiv(y2, x1, y1) - x2; 1646 if (0 == denom) { 1647 return false; 1648 } 1649 a2 = SkFractDiv(SkMulDiv(y0 - y2, x1, y1) - x0 + x2, denom); 1650 } 1651 1652 // need to check if SkFixedDiv overflows... 1653 dst->fMat[kMScaleX] = SkFixedDiv(SkFractMul(a2, srcPt[3].fX) + 1654 srcPt[3].fX - srcPt[0].fX, scale.fX); 1655 dst->fMat[kMSkewY] = SkFixedDiv(SkFractMul(a2, srcPt[3].fY) + 1656 srcPt[3].fY - srcPt[0].fY, scale.fX); 1657 dst->fMat[kMPersp0] = SkFixedDiv(a2, scale.fX); 1658 dst->fMat[kMSkewX] = SkFixedDiv(SkFractMul(a1, srcPt[1].fX) + 1659 srcPt[1].fX - srcPt[0].fX, scale.fY); 1660 dst->fMat[kMScaleY] = SkFixedDiv(SkFractMul(a1, srcPt[1].fY) + 1661 srcPt[1].fY - srcPt[0].fY, scale.fY); 1662 dst->fMat[kMPersp1] = SkFixedDiv(a1, scale.fY); 1663 dst->fMat[kMTransX] = srcPt[0].fX; 1664 dst->fMat[kMTransY] = srcPt[0].fY; 1665 dst->fMat[kMPersp2] = SK_Fract1; 1666 dst->setTypeMask(kUnknown_Mask); 1667 return true; 1668 } 1669 1670 #else /* Scalar is float */ 1671 1672 static inline bool checkForZero(float x) { 1673 return x*x == 0; 1674 } 1675 1676 static inline bool poly_to_point(SkPoint* pt, const SkPoint poly[], int count) { 1677 float x = 1, y = 1; 1678 SkPoint pt1, pt2; 1679 1680 if (count > 1) { 1681 pt1.fX = poly[1].fX - poly[0].fX; 1682 pt1.fY = poly[1].fY - poly[0].fY; 1683 y = SkPoint::Length(pt1.fX, pt1.fY); 1684 if (checkForZero(y)) { 1685 return false; 1686 } 1687 switch (count) { 1688 case 2: 1689 break; 1690 case 3: 1691 pt2.fX = poly[0].fY - poly[2].fY; 1692 pt2.fY = poly[2].fX - poly[0].fX; 1693 goto CALC_X; 1694 default: 1695 pt2.fX = poly[0].fY - poly[3].fY; 1696 pt2.fY = poly[3].fX - poly[0].fX; 1697 CALC_X: 1698 x = SkScalarDiv(SkScalarMul(pt1.fX, pt2.fX) + 1699 SkScalarMul(pt1.fY, pt2.fY), y); 1700 break; 1701 } 1702 } 1703 pt->set(x, y); 1704 return true; 1705 } 1706 1707 bool SkMatrix::Poly2Proc(const SkPoint srcPt[], SkMatrix* dst, 1708 const SkPoint& scale) { 1709 float invScale = 1 / scale.fY; 1710 1711 dst->fMat[kMScaleX] = (srcPt[1].fY - srcPt[0].fY) * invScale; 1712 dst->fMat[kMSkewY] = (srcPt[0].fX - srcPt[1].fX) * invScale; 1713 dst->fMat[kMPersp0] = 0; 1714 dst->fMat[kMSkewX] = (srcPt[1].fX - srcPt[0].fX) * invScale; 1715 dst->fMat[kMScaleY] = (srcPt[1].fY - srcPt[0].fY) * invScale; 1716 dst->fMat[kMPersp1] = 0; 1717 dst->fMat[kMTransX] = srcPt[0].fX; 1718 dst->fMat[kMTransY] = srcPt[0].fY; 1719 dst->fMat[kMPersp2] = 1; 1720 dst->setTypeMask(kUnknown_Mask); 1721 return true; 1722 } 1723 1724 bool SkMatrix::Poly3Proc(const SkPoint srcPt[], SkMatrix* dst, 1725 const SkPoint& scale) { 1726 float invScale = 1 / scale.fX; 1727 dst->fMat[kMScaleX] = (srcPt[2].fX - srcPt[0].fX) * invScale; 1728 dst->fMat[kMSkewY] = (srcPt[2].fY - srcPt[0].fY) * invScale; 1729 dst->fMat[kMPersp0] = 0; 1730 1731 invScale = 1 / scale.fY; 1732 dst->fMat[kMSkewX] = (srcPt[1].fX - srcPt[0].fX) * invScale; 1733 dst->fMat[kMScaleY] = (srcPt[1].fY - srcPt[0].fY) * invScale; 1734 dst->fMat[kMPersp1] = 0; 1735 1736 dst->fMat[kMTransX] = srcPt[0].fX; 1737 dst->fMat[kMTransY] = srcPt[0].fY; 1738 dst->fMat[kMPersp2] = 1; 1739 dst->setTypeMask(kUnknown_Mask); 1740 return true; 1741 } 1742 1743 bool SkMatrix::Poly4Proc(const SkPoint srcPt[], SkMatrix* dst, 1744 const SkPoint& scale) { 1745 float a1, a2; 1746 float x0, y0, x1, y1, x2, y2; 1747 1748 x0 = srcPt[2].fX - srcPt[0].fX; 1749 y0 = srcPt[2].fY - srcPt[0].fY; 1750 x1 = srcPt[2].fX - srcPt[1].fX; 1751 y1 = srcPt[2].fY - srcPt[1].fY; 1752 x2 = srcPt[2].fX - srcPt[3].fX; 1753 y2 = srcPt[2].fY - srcPt[3].fY; 1754 1755 /* check if abs(x2) > abs(y2) */ 1756 if ( x2 > 0 ? y2 > 0 ? x2 > y2 : x2 > -y2 : y2 > 0 ? -x2 > y2 : x2 < y2) { 1757 float denom = SkScalarMulDiv(x1, y2, x2) - y1; 1758 if (checkForZero(denom)) { 1759 return false; 1760 } 1761 a1 = SkScalarDiv(SkScalarMulDiv(x0 - x1, y2, x2) - y0 + y1, denom); 1762 } else { 1763 float denom = x1 - SkScalarMulDiv(y1, x2, y2); 1764 if (checkForZero(denom)) { 1765 return false; 1766 } 1767 a1 = SkScalarDiv(x0 - x1 - SkScalarMulDiv(y0 - y1, x2, y2), denom); 1768 } 1769 1770 /* check if abs(x1) > abs(y1) */ 1771 if ( x1 > 0 ? y1 > 0 ? x1 > y1 : x1 > -y1 : y1 > 0 ? -x1 > y1 : x1 < y1) { 1772 float denom = y2 - SkScalarMulDiv(x2, y1, x1); 1773 if (checkForZero(denom)) { 1774 return false; 1775 } 1776 a2 = SkScalarDiv(y0 - y2 - SkScalarMulDiv(x0 - x2, y1, x1), denom); 1777 } else { 1778 float denom = SkScalarMulDiv(y2, x1, y1) - x2; 1779 if (checkForZero(denom)) { 1780 return false; 1781 } 1782 a2 = SkScalarDiv(SkScalarMulDiv(y0 - y2, x1, y1) - x0 + x2, denom); 1783 } 1784 1785 float invScale = 1 / scale.fX; 1786 dst->fMat[kMScaleX] = SkScalarMul(SkScalarMul(a2, srcPt[3].fX) + 1787 srcPt[3].fX - srcPt[0].fX, invScale); 1788 dst->fMat[kMSkewY] = SkScalarMul(SkScalarMul(a2, srcPt[3].fY) + 1789 srcPt[3].fY - srcPt[0].fY, invScale); 1790 dst->fMat[kMPersp0] = SkScalarMul(a2, invScale); 1791 invScale = 1 / scale.fY; 1792 dst->fMat[kMSkewX] = SkScalarMul(SkScalarMul(a1, srcPt[1].fX) + 1793 srcPt[1].fX - srcPt[0].fX, invScale); 1794 dst->fMat[kMScaleY] = SkScalarMul(SkScalarMul(a1, srcPt[1].fY) + 1795 srcPt[1].fY - srcPt[0].fY, invScale); 1796 dst->fMat[kMPersp1] = SkScalarMul(a1, invScale); 1797 dst->fMat[kMTransX] = srcPt[0].fX; 1798 dst->fMat[kMTransY] = srcPt[0].fY; 1799 dst->fMat[kMPersp2] = 1; 1800 dst->setTypeMask(kUnknown_Mask); 1801 return true; 1802 } 1803 1804 #endif 1805 1806 typedef bool (*PolyMapProc)(const SkPoint[], SkMatrix*, const SkPoint&); 1807 1808 /* Taken from Rob Johnson's original sample code in QuickDraw GX 1809 */ 1810 bool SkMatrix::setPolyToPoly(const SkPoint src[], const SkPoint dst[], 1811 int count) { 1812 if ((unsigned)count > 4) { 1813 SkDebugf("--- SkMatrix::setPolyToPoly count out of range %d\n", count); 1814 return false; 1815 } 1816 1817 if (0 == count) { 1818 this->reset(); 1819 return true; 1820 } 1821 if (1 == count) { 1822 this->setTranslate(dst[0].fX - src[0].fX, dst[0].fY - src[0].fY); 1823 return true; 1824 } 1825 1826 SkPoint scale; 1827 if (!poly_to_point(&scale, src, count) || 1828 SkScalarNearlyZero(scale.fX) || 1829 SkScalarNearlyZero(scale.fY)) { 1830 return false; 1831 } 1832 1833 static const PolyMapProc gPolyMapProcs[] = { 1834 SkMatrix::Poly2Proc, SkMatrix::Poly3Proc, SkMatrix::Poly4Proc 1835 }; 1836 PolyMapProc proc = gPolyMapProcs[count - 2]; 1837 1838 SkMatrix tempMap, result; 1839 tempMap.setTypeMask(kUnknown_Mask); 1840 1841 if (!proc(src, &tempMap, scale)) { 1842 return false; 1843 } 1844 if (!tempMap.invert(&result)) { 1845 return false; 1846 } 1847 if (!proc(dst, &tempMap, scale)) { 1848 return false; 1849 } 1850 if (!result.setConcat(tempMap, result)) { 1851 return false; 1852 } 1853 *this = result; 1854 return true; 1855 } 1856 1857 /////////////////////////////////////////////////////////////////////////////// 1858 1859 enum MinOrMax { 1860 kMin_MinOrMax, 1861 kMax_MinOrMax 1862 }; 1863 1864 template <MinOrMax MIN_OR_MAX> SkScalar get_stretch_factor(SkMatrix::TypeMask typeMask, 1865 const SkScalar m[9]) { 1866 if (typeMask & SkMatrix::kPerspective_Mask) { 1867 return -SK_Scalar1; 1868 } 1869 if (SkMatrix::kIdentity_Mask == typeMask) { 1870 return SK_Scalar1; 1871 } 1872 if (!(typeMask & SkMatrix::kAffine_Mask)) { 1873 if (kMin_MinOrMax == MIN_OR_MAX) { 1874 return SkMinScalar(SkScalarAbs(m[SkMatrix::kMScaleX]), 1875 SkScalarAbs(m[SkMatrix::kMScaleY])); 1876 } else { 1877 return SkMaxScalar(SkScalarAbs(m[SkMatrix::kMScaleX]), 1878 SkScalarAbs(m[SkMatrix::kMScaleY])); 1879 } 1880 } 1881 // ignore the translation part of the matrix, just look at 2x2 portion. 1882 // compute singular values, take largest or smallest abs value. 1883 // [a b; b c] = A^T*A 1884 SkScalar a = SkScalarMul(m[SkMatrix::kMScaleX], m[SkMatrix::kMScaleX]) + 1885 SkScalarMul(m[SkMatrix::kMSkewY], m[SkMatrix::kMSkewY]); 1886 SkScalar b = SkScalarMul(m[SkMatrix::kMScaleX], m[SkMatrix::kMSkewX]) + 1887 SkScalarMul(m[SkMatrix::kMScaleY], m[SkMatrix::kMSkewY]); 1888 SkScalar c = SkScalarMul(m[SkMatrix::kMSkewX], m[SkMatrix::kMSkewX]) + 1889 SkScalarMul(m[SkMatrix::kMScaleY], m[SkMatrix::kMScaleY]); 1890 // eigenvalues of A^T*A are the squared singular values of A. 1891 // characteristic equation is det((A^T*A) - l*I) = 0 1892 // l^2 - (a + c)l + (ac-b^2) 1893 // solve using quadratic equation (divisor is non-zero since l^2 has 1 coeff 1894 // and roots are guaranteed to be pos and real). 1895 SkScalar chosenRoot; 1896 SkScalar bSqd = SkScalarMul(b,b); 1897 // if upper left 2x2 is orthogonal save some math 1898 if (bSqd <= SK_ScalarNearlyZero*SK_ScalarNearlyZero) { 1899 if (kMin_MinOrMax == MIN_OR_MAX) { 1900 chosenRoot = SkMinScalar(a, c); 1901 } else { 1902 chosenRoot = SkMaxScalar(a, c); 1903 } 1904 } else { 1905 SkScalar aminusc = a - c; 1906 SkScalar apluscdiv2 = SkScalarHalf(a + c); 1907 SkScalar x = SkScalarHalf(SkScalarSqrt(SkScalarMul(aminusc, aminusc) + 4 * bSqd)); 1908 if (kMin_MinOrMax == MIN_OR_MAX) { 1909 chosenRoot = apluscdiv2 - x; 1910 } else { 1911 chosenRoot = apluscdiv2 + x; 1912 } 1913 } 1914 SkASSERT(chosenRoot >= 0); 1915 return SkScalarSqrt(chosenRoot); 1916 } 1917 1918 SkScalar SkMatrix::getMinStretch() const { 1919 return get_stretch_factor<kMin_MinOrMax>(this->getType(), fMat); 1920 } 1921 1922 SkScalar SkMatrix::getMaxStretch() const { 1923 return get_stretch_factor<kMax_MinOrMax>(this->getType(), fMat); 1924 } 1925 1926 static void reset_identity_matrix(SkMatrix* identity) { 1927 identity->reset(); 1928 } 1929 1930 const SkMatrix& SkMatrix::I() { 1931 // If you can use C++11 now, you might consider replacing this with a constexpr constructor. 1932 static SkMatrix gIdentity; 1933 SK_DECLARE_STATIC_ONCE(once); 1934 SkOnce(&once, reset_identity_matrix, &gIdentity); 1935 return gIdentity; 1936 } 1937 1938 const SkMatrix& SkMatrix::InvalidMatrix() { 1939 static SkMatrix gInvalid; 1940 static bool gOnce; 1941 if (!gOnce) { 1942 gInvalid.setAll(SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, 1943 SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, 1944 SK_ScalarMax, SK_ScalarMax, SK_ScalarMax); 1945 gInvalid.getType(); // force the type to be computed 1946 gOnce = true; 1947 } 1948 return gInvalid; 1949 } 1950 1951 /////////////////////////////////////////////////////////////////////////////// 1952 1953 size_t SkMatrix::writeToMemory(void* buffer) const { 1954 // TODO write less for simple matrices 1955 static const size_t sizeInMemory = 9 * sizeof(SkScalar); 1956 if (buffer) { 1957 memcpy(buffer, fMat, sizeInMemory); 1958 } 1959 return sizeInMemory; 1960 } 1961 1962 size_t SkMatrix::readFromMemory(const void* buffer, size_t length) { 1963 static const size_t sizeInMemory = 9 * sizeof(SkScalar); 1964 if (length < sizeInMemory) { 1965 return 0; 1966 } 1967 if (buffer) { 1968 memcpy(fMat, buffer, sizeInMemory); 1969 this->setTypeMask(kUnknown_Mask); 1970 } 1971 return sizeInMemory; 1972 } 1973 1974 #ifdef SK_DEVELOPER 1975 void SkMatrix::dump() const { 1976 SkString str; 1977 this->toString(&str); 1978 SkDebugf("%s\n", str.c_str()); 1979 } 1980 1981 void SkMatrix::toString(SkString* str) const { 1982 str->appendf("[%8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f]", 1983 #ifdef SK_SCALAR_IS_FLOAT 1984 fMat[0], fMat[1], fMat[2], fMat[3], fMat[4], fMat[5], 1985 fMat[6], fMat[7], fMat[8]); 1986 #else 1987 SkFixedToFloat(fMat[0]), SkFixedToFloat(fMat[1]), SkFixedToFloat(fMat[2]), 1988 SkFixedToFloat(fMat[3]), SkFixedToFloat(fMat[4]), SkFixedToFloat(fMat[5]), 1989 SkFractToFloat(fMat[6]), SkFractToFloat(fMat[7]), SkFractToFloat(fMat[8])); 1990 #endif 1991 } 1992 #endif 1993 1994 /////////////////////////////////////////////////////////////////////////////// 1995 1996 #include "SkMatrixUtils.h" 1997 1998 bool SkTreatAsSprite(const SkMatrix& mat, int width, int height, 1999 unsigned subpixelBits) { 2000 // quick reject on affine or perspective 2001 if (mat.getType() & ~(SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask)) { 2002 return false; 2003 } 2004 2005 // quick success check 2006 if (!subpixelBits && !(mat.getType() & ~SkMatrix::kTranslate_Mask)) { 2007 return true; 2008 } 2009 2010 // mapRect supports negative scales, so we eliminate those first 2011 if (mat.getScaleX() < 0 || mat.getScaleY() < 0) { 2012 return false; 2013 } 2014 2015 SkRect dst; 2016 SkIRect isrc = { 0, 0, width, height }; 2017 2018 { 2019 SkRect src; 2020 src.set(isrc); 2021 mat.mapRect(&dst, src); 2022 } 2023 2024 // just apply the translate to isrc 2025 isrc.offset(SkScalarRoundToInt(mat.getTranslateX()), 2026 SkScalarRoundToInt(mat.getTranslateY())); 2027 2028 if (subpixelBits) { 2029 isrc.fLeft <<= subpixelBits; 2030 isrc.fTop <<= subpixelBits; 2031 isrc.fRight <<= subpixelBits; 2032 isrc.fBottom <<= subpixelBits; 2033 2034 const float scale = 1 << subpixelBits; 2035 dst.fLeft *= scale; 2036 dst.fTop *= scale; 2037 dst.fRight *= scale; 2038 dst.fBottom *= scale; 2039 } 2040 2041 SkIRect idst; 2042 dst.round(&idst); 2043 return isrc == idst; 2044 } 2045 2046 // A square matrix M can be decomposed (via polar decomposition) into two matrices -- 2047 // an orthogonal matrix Q and a symmetric matrix S. In turn we can decompose S into U*W*U^T, 2048 // where U is another orthogonal matrix and W is a scale matrix. These can be recombined 2049 // to give M = (Q*U)*W*U^T, i.e., the product of two orthogonal matrices and a scale matrix. 2050 // 2051 // The one wrinkle is that traditionally Q may contain a reflection -- the 2052 // calculation has been rejiggered to put that reflection into W. 2053 bool SkDecomposeUpper2x2(const SkMatrix& matrix, 2054 SkPoint* rotation1, 2055 SkPoint* scale, 2056 SkPoint* rotation2) { 2057 2058 SkScalar A = matrix[SkMatrix::kMScaleX]; 2059 SkScalar B = matrix[SkMatrix::kMSkewX]; 2060 SkScalar C = matrix[SkMatrix::kMSkewY]; 2061 SkScalar D = matrix[SkMatrix::kMScaleY]; 2062 2063 if (is_degenerate_2x2(A, B, C, D)) { 2064 return false; 2065 } 2066 2067 double w1, w2; 2068 SkScalar cos1, sin1; 2069 SkScalar cos2, sin2; 2070 2071 // do polar decomposition (M = Q*S) 2072 SkScalar cosQ, sinQ; 2073 double Sa, Sb, Sd; 2074 // if M is already symmetric (i.e., M = I*S) 2075 if (SkScalarNearlyEqual(B, C)) { 2076 cosQ = SK_Scalar1; 2077 sinQ = 0; 2078 2079 Sa = A; 2080 Sb = B; 2081 Sd = D; 2082 } else { 2083 cosQ = A + D; 2084 sinQ = C - B; 2085 SkScalar reciplen = SK_Scalar1/SkScalarSqrt(cosQ*cosQ + sinQ*sinQ); 2086 cosQ *= reciplen; 2087 sinQ *= reciplen; 2088 2089 // S = Q^-1*M 2090 // we don't calc Sc since it's symmetric 2091 Sa = A*cosQ + C*sinQ; 2092 Sb = B*cosQ + D*sinQ; 2093 Sd = -B*sinQ + D*cosQ; 2094 } 2095 2096 // Now we need to compute eigenvalues of S (our scale factors) 2097 // and eigenvectors (bases for our rotation) 2098 // From this, should be able to reconstruct S as U*W*U^T 2099 if (SkScalarNearlyZero(SkDoubleToScalar(Sb))) { 2100 // already diagonalized 2101 cos1 = SK_Scalar1; 2102 sin1 = 0; 2103 w1 = Sa; 2104 w2 = Sd; 2105 cos2 = cosQ; 2106 sin2 = sinQ; 2107 } else { 2108 double diff = Sa - Sd; 2109 double discriminant = sqrt(diff*diff + 4.0*Sb*Sb); 2110 double trace = Sa + Sd; 2111 if (diff > 0) { 2112 w1 = 0.5*(trace + discriminant); 2113 w2 = 0.5*(trace - discriminant); 2114 } else { 2115 w1 = 0.5*(trace - discriminant); 2116 w2 = 0.5*(trace + discriminant); 2117 } 2118 2119 cos1 = SkDoubleToScalar(Sb); sin1 = SkDoubleToScalar(w1 - Sa); 2120 SkScalar reciplen = SK_Scalar1/SkScalarSqrt(cos1*cos1 + sin1*sin1); 2121 cos1 *= reciplen; 2122 sin1 *= reciplen; 2123 2124 // rotation 2 is composition of Q and U 2125 cos2 = cos1*cosQ - sin1*sinQ; 2126 sin2 = sin1*cosQ + cos1*sinQ; 2127 2128 // rotation 1 is U^T 2129 sin1 = -sin1; 2130 } 2131 2132 if (NULL != scale) { 2133 scale->fX = SkDoubleToScalar(w1); 2134 scale->fY = SkDoubleToScalar(w2); 2135 } 2136 if (NULL != rotation1) { 2137 rotation1->fX = cos1; 2138 rotation1->fY = sin1; 2139 } 2140 if (NULL != rotation2) { 2141 rotation2->fX = cos2; 2142 rotation2->fY = sin2; 2143 } 2144 2145 return true; 2146 } 2147