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