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