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