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