1 /* 2 * Copyright 2006 The Android Open Source Project 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef SkMatrix_DEFINED 9 #define SkMatrix_DEFINED 10 11 #include "include/core/SkRect.h" 12 #include "include/private/SkMacros.h" 13 #include "include/private/SkTo.h" 14 15 struct SkRSXform; 16 struct SkPoint3; 17 18 /** 19 * When we transform points through a matrix containing perspective (the bottom row is something 20 * other than 0,0,1), the bruteforce math can produce confusing results (since we might divide 21 * by 0, or a negative w value). By default, methods that map rects and paths will apply 22 * perspective clipping, but this can be changed by specifying kYes to those methods. 23 */ 24 enum class SkApplyPerspectiveClip { 25 kNo, //!< Don't pre-clip the geometry before applying the (perspective) matrix 26 kYes, //!< Do pre-clip the geometry before applying the (perspective) matrix 27 }; 28 29 /** \class SkMatrix 30 SkMatrix holds a 3x3 matrix for transforming coordinates. This allows mapping 31 SkPoint and vectors with translation, scaling, skewing, rotation, and 32 perspective. 33 34 SkMatrix elements are in row major order. SkMatrix does not have a constructor, 35 so it must be explicitly initialized. setIdentity() initializes SkMatrix 36 so it has no effect. setTranslate(), setScale(), setSkew(), setRotate(), set9 and setAll() 37 initializes all SkMatrix elements with the corresponding mapping. 38 39 SkMatrix includes a hidden variable that classifies the type of matrix to 40 improve performance. SkMatrix is not thread safe unless getType() is called first. 41 42 example: https://fiddle.skia.org/c/@Matrix_063 43 */ 44 SK_BEGIN_REQUIRE_DENSE 45 class SK_API SkMatrix { 46 public: 47 48 /** Creates an identity SkMatrix: 49 50 | 1 0 0 | 51 | 0 1 0 | 52 | 0 0 1 | 53 */ SkMatrix()54 constexpr SkMatrix() : SkMatrix(1,0,0, 0,1,0, 0,0,1, kIdentity_Mask | kRectStaysRect_Mask) {} 55 56 /** Sets SkMatrix to scale by (sx, sy). Returned matrix is: 57 58 | sx 0 0 | 59 | 0 sy 0 | 60 | 0 0 1 | 61 62 @param sx horizontal scale factor 63 @param sy vertical scale factor 64 @return SkMatrix with scale 65 */ MakeScale(SkScalar sx,SkScalar sy)66 static SkMatrix SK_WARN_UNUSED_RESULT MakeScale(SkScalar sx, SkScalar sy) { 67 SkMatrix m; 68 m.setScale(sx, sy); 69 return m; 70 } 71 72 /** Sets SkMatrix to scale by (scale, scale). Returned matrix is: 73 74 | scale 0 0 | 75 | 0 scale 0 | 76 | 0 0 1 | 77 78 @param scale horizontal and vertical scale factor 79 @return SkMatrix with scale 80 */ MakeScale(SkScalar scale)81 static SkMatrix SK_WARN_UNUSED_RESULT MakeScale(SkScalar scale) { 82 SkMatrix m; 83 m.setScale(scale, scale); 84 return m; 85 } 86 87 /** Sets SkMatrix to translate by (dx, dy). Returned matrix is: 88 89 | 1 0 dx | 90 | 0 1 dy | 91 | 0 0 1 | 92 93 @param dx horizontal translation 94 @param dy vertical translation 95 @return SkMatrix with translation 96 */ MakeTrans(SkScalar dx,SkScalar dy)97 static SkMatrix SK_WARN_UNUSED_RESULT MakeTrans(SkScalar dx, SkScalar dy) { 98 SkMatrix m; 99 m.setTranslate(dx, dy); 100 return m; 101 } 102 103 /** Sets SkMatrix to translate by (t.x(), t.y()). Returned matrix is: 104 105 | 1 0 t.x() | 106 | 0 1 t.y() | 107 | 0 0 1 | 108 109 @param t translation vector 110 @return SkMatrix with translation 111 */ MakeTrans(SkVector t)112 static SkMatrix SK_WARN_UNUSED_RESULT MakeTrans(SkVector t) { return MakeTrans(t.x(), t.y()); } MakeTrans(SkIVector t)113 static SkMatrix SK_WARN_UNUSED_RESULT MakeTrans(SkIVector t) { return MakeTrans(t.x(), t.y()); } 114 115 /** Sets SkMatrix to: 116 117 | scaleX skewX transX | 118 | skewY scaleY transY | 119 | pers0 pers1 pers2 | 120 121 @param scaleX horizontal scale factor 122 @param skewX horizontal skew factor 123 @param transX horizontal translation 124 @param skewY vertical skew factor 125 @param scaleY vertical scale factor 126 @param transY vertical translation 127 @param pers0 input x-axis perspective factor 128 @param pers1 input y-axis perspective factor 129 @param pers2 perspective scale factor 130 @return SkMatrix constructed from parameters 131 */ MakeAll(SkScalar scaleX,SkScalar skewX,SkScalar transX,SkScalar skewY,SkScalar scaleY,SkScalar transY,SkScalar pers0,SkScalar pers1,SkScalar pers2)132 static SkMatrix SK_WARN_UNUSED_RESULT MakeAll(SkScalar scaleX, SkScalar skewX, SkScalar transX, 133 SkScalar skewY, SkScalar scaleY, SkScalar transY, 134 SkScalar pers0, SkScalar pers1, SkScalar pers2) { 135 SkMatrix m; 136 m.setAll(scaleX, skewX, transX, skewY, scaleY, transY, pers0, pers1, pers2); 137 return m; 138 } 139 140 /** \enum SkMatrix::TypeMask 141 Enum of bit fields for mask returned by getType(). 142 Used to identify the complexity of SkMatrix, to optimize performance. 143 */ 144 enum TypeMask { 145 kIdentity_Mask = 0, //!< identity SkMatrix; all bits clear 146 kTranslate_Mask = 0x01, //!< translation SkMatrix 147 kScale_Mask = 0x02, //!< scale SkMatrix 148 kAffine_Mask = 0x04, //!< skew or rotate SkMatrix 149 kPerspective_Mask = 0x08, //!< perspective SkMatrix 150 }; 151 152 /** Returns a bit field describing the transformations the matrix may 153 perform. The bit field is computed conservatively, so it may include 154 false positives. For example, when kPerspective_Mask is set, all 155 other bits are set. 156 157 @return kIdentity_Mask, or combinations of: kTranslate_Mask, kScale_Mask, 158 kAffine_Mask, kPerspective_Mask 159 */ getType()160 TypeMask getType() const { 161 if (fTypeMask & kUnknown_Mask) { 162 fTypeMask = this->computeTypeMask(); 163 } 164 // only return the public masks 165 return (TypeMask)(fTypeMask & 0xF); 166 } 167 168 /** Returns true if SkMatrix is identity. Identity matrix is: 169 170 | 1 0 0 | 171 | 0 1 0 | 172 | 0 0 1 | 173 174 @return true if SkMatrix has no effect 175 */ isIdentity()176 bool isIdentity() const { 177 return this->getType() == 0; 178 } 179 180 /** Returns true if SkMatrix at most scales and translates. SkMatrix may be identity, 181 contain only scale elements, only translate elements, or both. SkMatrix form is: 182 183 | scale-x 0 translate-x | 184 | 0 scale-y translate-y | 185 | 0 0 1 | 186 187 @return true if SkMatrix is identity; or scales, translates, or both 188 */ isScaleTranslate()189 bool isScaleTranslate() const { 190 return !(this->getType() & ~(kScale_Mask | kTranslate_Mask)); 191 } 192 193 /** Returns true if SkMatrix is identity, or translates. SkMatrix form is: 194 195 | 1 0 translate-x | 196 | 0 1 translate-y | 197 | 0 0 1 | 198 199 @return true if SkMatrix is identity, or translates 200 */ isTranslate()201 bool isTranslate() const { return !(this->getType() & ~(kTranslate_Mask)); } 202 203 /** Returns true SkMatrix maps SkRect to another SkRect. If true, SkMatrix is identity, 204 or scales, or rotates a multiple of 90 degrees, or mirrors on axes. In all 205 cases, SkMatrix may also have translation. SkMatrix form is either: 206 207 | scale-x 0 translate-x | 208 | 0 scale-y translate-y | 209 | 0 0 1 | 210 211 or 212 213 | 0 rotate-x translate-x | 214 | rotate-y 0 translate-y | 215 | 0 0 1 | 216 217 for non-zero values of scale-x, scale-y, rotate-x, and rotate-y. 218 219 Also called preservesAxisAlignment(); use the one that provides better inline 220 documentation. 221 222 @return true if SkMatrix maps one SkRect into another 223 */ rectStaysRect()224 bool rectStaysRect() const { 225 if (fTypeMask & kUnknown_Mask) { 226 fTypeMask = this->computeTypeMask(); 227 } 228 return (fTypeMask & kRectStaysRect_Mask) != 0; 229 } 230 231 /** Returns true SkMatrix maps SkRect to another SkRect. If true, SkMatrix is identity, 232 or scales, or rotates a multiple of 90 degrees, or mirrors on axes. In all 233 cases, SkMatrix may also have translation. SkMatrix form is either: 234 235 | scale-x 0 translate-x | 236 | 0 scale-y translate-y | 237 | 0 0 1 | 238 239 or 240 241 | 0 rotate-x translate-x | 242 | rotate-y 0 translate-y | 243 | 0 0 1 | 244 245 for non-zero values of scale-x, scale-y, rotate-x, and rotate-y. 246 247 Also called rectStaysRect(); use the one that provides better inline 248 documentation. 249 250 @return true if SkMatrix maps one SkRect into another 251 */ preservesAxisAlignment()252 bool preservesAxisAlignment() const { return this->rectStaysRect(); } 253 254 /** Returns true if the matrix contains perspective elements. SkMatrix form is: 255 256 | -- -- -- | 257 | -- -- -- | 258 | perspective-x perspective-y perspective-scale | 259 260 where perspective-x or perspective-y is non-zero, or perspective-scale is 261 not one. All other elements may have any value. 262 263 @return true if SkMatrix is in most general form 264 */ hasPerspective()265 bool hasPerspective() const { 266 return SkToBool(this->getPerspectiveTypeMaskOnly() & 267 kPerspective_Mask); 268 } 269 270 /** Returns true if SkMatrix contains only translation, rotation, reflection, and 271 uniform scale. 272 Returns false if SkMatrix contains different scales, skewing, perspective, or 273 degenerate forms that collapse to a line or point. 274 275 Describes that the SkMatrix makes rendering with and without the matrix are 276 visually alike; a transformed circle remains a circle. Mathematically, this is 277 referred to as similarity of a Euclidean space, or a similarity transformation. 278 279 Preserves right angles, keeping the arms of the angle equal lengths. 280 281 @param tol to be deprecated 282 @return true if SkMatrix only rotates, uniformly scales, translates 283 284 example: https://fiddle.skia.org/c/@Matrix_isSimilarity 285 */ 286 bool isSimilarity(SkScalar tol = SK_ScalarNearlyZero) const; 287 288 /** Returns true if SkMatrix contains only translation, rotation, reflection, and 289 scale. Scale may differ along rotated axes. 290 Returns false if SkMatrix skewing, perspective, or degenerate forms that collapse 291 to a line or point. 292 293 Preserves right angles, but not requiring that the arms of the angle 294 retain equal lengths. 295 296 @param tol to be deprecated 297 @return true if SkMatrix only rotates, scales, translates 298 299 example: https://fiddle.skia.org/c/@Matrix_preservesRightAngles 300 */ 301 bool preservesRightAngles(SkScalar tol = SK_ScalarNearlyZero) const; 302 303 /** SkMatrix organizes its values in row order. These members correspond to 304 each value in SkMatrix. 305 */ 306 static constexpr int kMScaleX = 0; //!< horizontal scale factor 307 static constexpr int kMSkewX = 1; //!< horizontal skew factor 308 static constexpr int kMTransX = 2; //!< horizontal translation 309 static constexpr int kMSkewY = 3; //!< vertical skew factor 310 static constexpr int kMScaleY = 4; //!< vertical scale factor 311 static constexpr int kMTransY = 5; //!< vertical translation 312 static constexpr int kMPersp0 = 6; //!< input x perspective factor 313 static constexpr int kMPersp1 = 7; //!< input y perspective factor 314 static constexpr int kMPersp2 = 8; //!< perspective bias 315 316 /** Affine arrays are in column major order to match the matrix used by 317 PDF and XPS. 318 */ 319 static constexpr int kAScaleX = 0; //!< horizontal scale factor 320 static constexpr int kASkewY = 1; //!< vertical skew factor 321 static constexpr int kASkewX = 2; //!< horizontal skew factor 322 static constexpr int kAScaleY = 3; //!< vertical scale factor 323 static constexpr int kATransX = 4; //!< horizontal translation 324 static constexpr int kATransY = 5; //!< vertical translation 325 326 /** Returns one matrix value. Asserts if index is out of range and SK_DEBUG is 327 defined. 328 329 @param index one of: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY, 330 kMPersp0, kMPersp1, kMPersp2 331 @return value corresponding to index 332 */ 333 SkScalar operator[](int index) const { 334 SkASSERT((unsigned)index < 9); 335 return fMat[index]; 336 } 337 338 /** Returns one matrix value. Asserts if index is out of range and SK_DEBUG is 339 defined. 340 341 @param index one of: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY, 342 kMPersp0, kMPersp1, kMPersp2 343 @return value corresponding to index 344 */ get(int index)345 SkScalar get(int index) const { 346 SkASSERT((unsigned)index < 9); 347 return fMat[index]; 348 } 349 350 /** Returns scale factor multiplied by x-axis input, contributing to x-axis output. 351 With mapPoints(), scales SkPoint along the x-axis. 352 353 @return horizontal scale factor 354 */ getScaleX()355 SkScalar getScaleX() const { return fMat[kMScaleX]; } 356 357 /** Returns scale factor multiplied by y-axis input, contributing to y-axis output. 358 With mapPoints(), scales SkPoint along the y-axis. 359 360 @return vertical scale factor 361 */ getScaleY()362 SkScalar getScaleY() const { return fMat[kMScaleY]; } 363 364 /** Returns scale factor multiplied by x-axis input, contributing to y-axis output. 365 With mapPoints(), skews SkPoint along the y-axis. 366 Skewing both axes can rotate SkPoint. 367 368 @return vertical skew factor 369 */ getSkewY()370 SkScalar getSkewY() const { return fMat[kMSkewY]; } 371 372 /** Returns scale factor multiplied by y-axis input, contributing to x-axis output. 373 With mapPoints(), skews SkPoint along the x-axis. 374 Skewing both axes can rotate SkPoint. 375 376 @return horizontal scale factor 377 */ getSkewX()378 SkScalar getSkewX() const { return fMat[kMSkewX]; } 379 380 /** Returns translation contributing to x-axis output. 381 With mapPoints(), moves SkPoint along the x-axis. 382 383 @return horizontal translation factor 384 */ getTranslateX()385 SkScalar getTranslateX() const { return fMat[kMTransX]; } 386 387 /** Returns translation contributing to y-axis output. 388 With mapPoints(), moves SkPoint along the y-axis. 389 390 @return vertical translation factor 391 */ getTranslateY()392 SkScalar getTranslateY() const { return fMat[kMTransY]; } 393 394 /** Returns factor scaling input x-axis relative to input y-axis. 395 396 @return input x-axis perspective factor 397 */ getPerspX()398 SkScalar getPerspX() const { return fMat[kMPersp0]; } 399 400 /** Returns factor scaling input y-axis relative to input x-axis. 401 402 @return input y-axis perspective factor 403 */ getPerspY()404 SkScalar getPerspY() const { return fMat[kMPersp1]; } 405 406 /** Returns writable SkMatrix value. Asserts if index is out of range and SK_DEBUG is 407 defined. Clears internal cache anticipating that caller will change SkMatrix value. 408 409 Next call to read SkMatrix state may recompute cache; subsequent writes to SkMatrix 410 value must be followed by dirtyMatrixTypeCache(). 411 412 @param index one of: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY, 413 kMPersp0, kMPersp1, kMPersp2 414 @return writable value corresponding to index 415 */ 416 SkScalar& operator[](int index) { 417 SkASSERT((unsigned)index < 9); 418 this->setTypeMask(kUnknown_Mask); 419 return fMat[index]; 420 } 421 422 /** Sets SkMatrix value. Asserts if index is out of range and SK_DEBUG is 423 defined. Safer than operator[]; internal cache is always maintained. 424 425 @param index one of: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY, 426 kMPersp0, kMPersp1, kMPersp2 427 @param value scalar to store in SkMatrix 428 */ set(int index,SkScalar value)429 SkMatrix& set(int index, SkScalar value) { 430 SkASSERT((unsigned)index < 9); 431 fMat[index] = value; 432 this->setTypeMask(kUnknown_Mask); 433 return *this; 434 } 435 436 /** Sets horizontal scale factor. 437 438 @param v horizontal scale factor to store 439 */ setScaleX(SkScalar v)440 SkMatrix& setScaleX(SkScalar v) { return this->set(kMScaleX, v); } 441 442 /** Sets vertical scale factor. 443 444 @param v vertical scale factor to store 445 */ setScaleY(SkScalar v)446 SkMatrix& setScaleY(SkScalar v) { return this->set(kMScaleY, v); } 447 448 /** Sets vertical skew factor. 449 450 @param v vertical skew factor to store 451 */ setSkewY(SkScalar v)452 SkMatrix& setSkewY(SkScalar v) { return this->set(kMSkewY, v); } 453 454 /** Sets horizontal skew factor. 455 456 @param v horizontal skew factor to store 457 */ setSkewX(SkScalar v)458 SkMatrix& setSkewX(SkScalar v) { return this->set(kMSkewX, v); } 459 460 /** Sets horizontal translation. 461 462 @param v horizontal translation to store 463 */ setTranslateX(SkScalar v)464 SkMatrix& setTranslateX(SkScalar v) { return this->set(kMTransX, v); } 465 466 /** Sets vertical translation. 467 468 @param v vertical translation to store 469 */ setTranslateY(SkScalar v)470 SkMatrix& setTranslateY(SkScalar v) { return this->set(kMTransY, v); } 471 472 /** Sets input x-axis perspective factor, which causes mapXY() to vary input x-axis values 473 inversely proportional to input y-axis values. 474 475 @param v perspective factor 476 */ setPerspX(SkScalar v)477 SkMatrix& setPerspX(SkScalar v) { return this->set(kMPersp0, v); } 478 479 /** Sets input y-axis perspective factor, which causes mapXY() to vary input y-axis values 480 inversely proportional to input x-axis values. 481 482 @param v perspective factor 483 */ setPerspY(SkScalar v)484 SkMatrix& setPerspY(SkScalar v) { return this->set(kMPersp1, v); } 485 486 /** Sets all values from parameters. Sets matrix to: 487 488 | scaleX skewX transX | 489 | skewY scaleY transY | 490 | persp0 persp1 persp2 | 491 492 @param scaleX horizontal scale factor to store 493 @param skewX horizontal skew factor to store 494 @param transX horizontal translation to store 495 @param skewY vertical skew factor to store 496 @param scaleY vertical scale factor to store 497 @param transY vertical translation to store 498 @param persp0 input x-axis values perspective factor to store 499 @param persp1 input y-axis values perspective factor to store 500 @param persp2 perspective scale factor to store 501 */ setAll(SkScalar scaleX,SkScalar skewX,SkScalar transX,SkScalar skewY,SkScalar scaleY,SkScalar transY,SkScalar persp0,SkScalar persp1,SkScalar persp2)502 SkMatrix& setAll(SkScalar scaleX, SkScalar skewX, SkScalar transX, 503 SkScalar skewY, SkScalar scaleY, SkScalar transY, 504 SkScalar persp0, SkScalar persp1, SkScalar persp2) { 505 fMat[kMScaleX] = scaleX; 506 fMat[kMSkewX] = skewX; 507 fMat[kMTransX] = transX; 508 fMat[kMSkewY] = skewY; 509 fMat[kMScaleY] = scaleY; 510 fMat[kMTransY] = transY; 511 fMat[kMPersp0] = persp0; 512 fMat[kMPersp1] = persp1; 513 fMat[kMPersp2] = persp2; 514 this->setTypeMask(kUnknown_Mask); 515 return *this; 516 } 517 518 /** Copies nine scalar values contained by SkMatrix into buffer, in member value 519 ascending order: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY, 520 kMPersp0, kMPersp1, kMPersp2. 521 522 @param buffer storage for nine scalar values 523 */ get9(SkScalar buffer[9])524 void get9(SkScalar buffer[9]) const { 525 memcpy(buffer, fMat, 9 * sizeof(SkScalar)); 526 } 527 528 /** Sets SkMatrix to nine scalar values in buffer, in member value ascending order: 529 kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY, kMPersp0, kMPersp1, 530 kMPersp2. 531 532 Sets matrix to: 533 534 | buffer[0] buffer[1] buffer[2] | 535 | buffer[3] buffer[4] buffer[5] | 536 | buffer[6] buffer[7] buffer[8] | 537 538 In the future, set9 followed by get9 may not return the same values. Since SkMatrix 539 maps non-homogeneous coordinates, scaling all nine values produces an equivalent 540 transformation, possibly improving precision. 541 542 @param buffer nine scalar values 543 */ 544 SkMatrix& set9(const SkScalar buffer[9]); 545 546 /** Sets SkMatrix to identity; which has no effect on mapped SkPoint. Sets SkMatrix to: 547 548 | 1 0 0 | 549 | 0 1 0 | 550 | 0 0 1 | 551 552 Also called setIdentity(); use the one that provides better inline 553 documentation. 554 */ 555 SkMatrix& reset(); 556 557 /** Sets SkMatrix to identity; which has no effect on mapped SkPoint. Sets SkMatrix to: 558 559 | 1 0 0 | 560 | 0 1 0 | 561 | 0 0 1 | 562 563 Also called reset(); use the one that provides better inline 564 documentation. 565 */ setIdentity()566 SkMatrix& setIdentity() { return this->reset(); } 567 568 /** Sets SkMatrix to translate by (dx, dy). 569 570 @param dx horizontal translation 571 @param dy vertical translation 572 */ 573 SkMatrix& setTranslate(SkScalar dx, SkScalar dy); 574 575 /** Sets SkMatrix to translate by (v.fX, v.fY). 576 577 @param v vector containing horizontal and vertical translation 578 */ setTranslate(const SkVector & v)579 SkMatrix& setTranslate(const SkVector& v) { return this->setTranslate(v.fX, v.fY); } 580 581 /** Sets SkMatrix to scale by sx and sy, about a pivot point at (px, py). 582 The pivot point is unchanged when mapped with SkMatrix. 583 584 @param sx horizontal scale factor 585 @param sy vertical scale factor 586 @param px pivot on x-axis 587 @param py pivot on y-axis 588 */ 589 SkMatrix& setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py); 590 591 /** Sets SkMatrix to scale by sx and sy about at pivot point at (0, 0). 592 593 @param sx horizontal scale factor 594 @param sy vertical scale factor 595 */ 596 SkMatrix& setScale(SkScalar sx, SkScalar sy); 597 598 /** Sets SkMatrix to rotate by degrees about a pivot point at (px, py). 599 The pivot point is unchanged when mapped with SkMatrix. 600 601 Positive degrees rotates clockwise. 602 603 @param degrees angle of axes relative to upright axes 604 @param px pivot on x-axis 605 @param py pivot on y-axis 606 */ 607 SkMatrix& setRotate(SkScalar degrees, SkScalar px, SkScalar py); 608 609 /** Sets SkMatrix to rotate by degrees about a pivot point at (0, 0). 610 Positive degrees rotates clockwise. 611 612 @param degrees angle of axes relative to upright axes 613 */ 614 SkMatrix& setRotate(SkScalar degrees); 615 616 /** Sets SkMatrix to rotate by sinValue and cosValue, about a pivot point at (px, py). 617 The pivot point is unchanged when mapped with SkMatrix. 618 619 Vector (sinValue, cosValue) describes the angle of rotation relative to (0, 1). 620 Vector length specifies scale. 621 622 @param sinValue rotation vector x-axis component 623 @param cosValue rotation vector y-axis component 624 @param px pivot on x-axis 625 @param py pivot on y-axis 626 */ 627 SkMatrix& setSinCos(SkScalar sinValue, SkScalar cosValue, 628 SkScalar px, SkScalar py); 629 630 /** Sets SkMatrix to rotate by sinValue and cosValue, about a pivot point at (0, 0). 631 632 Vector (sinValue, cosValue) describes the angle of rotation relative to (0, 1). 633 Vector length specifies scale. 634 635 @param sinValue rotation vector x-axis component 636 @param cosValue rotation vector y-axis component 637 */ 638 SkMatrix& setSinCos(SkScalar sinValue, SkScalar cosValue); 639 640 /** Sets SkMatrix to rotate, scale, and translate using a compressed matrix form. 641 642 Vector (rsxForm.fSSin, rsxForm.fSCos) describes the angle of rotation relative 643 to (0, 1). Vector length specifies scale. Mapped point is rotated and scaled 644 by vector, then translated by (rsxForm.fTx, rsxForm.fTy). 645 646 @param rsxForm compressed SkRSXform matrix 647 @return reference to SkMatrix 648 649 example: https://fiddle.skia.org/c/@Matrix_setRSXform 650 */ 651 SkMatrix& setRSXform(const SkRSXform& rsxForm); 652 653 /** Sets SkMatrix to skew by kx and ky, about a pivot point at (px, py). 654 The pivot point is unchanged when mapped with SkMatrix. 655 656 @param kx horizontal skew factor 657 @param ky vertical skew factor 658 @param px pivot on x-axis 659 @param py pivot on y-axis 660 */ 661 SkMatrix& setSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py); 662 663 /** Sets SkMatrix to skew by kx and ky, about a pivot point at (0, 0). 664 665 @param kx horizontal skew factor 666 @param ky vertical skew factor 667 */ 668 SkMatrix& setSkew(SkScalar kx, SkScalar ky); 669 670 /** Sets SkMatrix to SkMatrix a multiplied by SkMatrix b. Either a or b may be this. 671 672 Given: 673 674 | A B C | | J K L | 675 a = | D E F |, b = | M N O | 676 | G H I | | P Q R | 677 678 sets SkMatrix to: 679 680 | A B C | | J K L | | AJ+BM+CP AK+BN+CQ AL+BO+CR | 681 a * b = | D E F | * | M N O | = | DJ+EM+FP DK+EN+FQ DL+EO+FR | 682 | G H I | | P Q R | | GJ+HM+IP GK+HN+IQ GL+HO+IR | 683 684 @param a SkMatrix on left side of multiply expression 685 @param b SkMatrix on right side of multiply expression 686 */ 687 SkMatrix& setConcat(const SkMatrix& a, const SkMatrix& b); 688 689 /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from translation (dx, dy). 690 This can be thought of as moving the point to be mapped before applying SkMatrix. 691 692 Given: 693 694 | A B C | | 1 0 dx | 695 Matrix = | D E F |, T(dx, dy) = | 0 1 dy | 696 | G H I | | 0 0 1 | 697 698 sets SkMatrix to: 699 700 | A B C | | 1 0 dx | | A B A*dx+B*dy+C | 701 Matrix * T(dx, dy) = | D E F | | 0 1 dy | = | D E D*dx+E*dy+F | 702 | G H I | | 0 0 1 | | G H G*dx+H*dy+I | 703 704 @param dx x-axis translation before applying SkMatrix 705 @param dy y-axis translation before applying SkMatrix 706 */ 707 SkMatrix& preTranslate(SkScalar dx, SkScalar dy); 708 709 /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from scaling by (sx, sy) 710 about pivot point (px, py). 711 This can be thought of as scaling about a pivot point before applying SkMatrix. 712 713 Given: 714 715 | A B C | | sx 0 dx | 716 Matrix = | D E F |, S(sx, sy, px, py) = | 0 sy dy | 717 | G H I | | 0 0 1 | 718 719 where 720 721 dx = px - sx * px 722 dy = py - sy * py 723 724 sets SkMatrix to: 725 726 | A B C | | sx 0 dx | | A*sx B*sy A*dx+B*dy+C | 727 Matrix * S(sx, sy, px, py) = | D E F | | 0 sy dy | = | D*sx E*sy D*dx+E*dy+F | 728 | G H I | | 0 0 1 | | G*sx H*sy G*dx+H*dy+I | 729 730 @param sx horizontal scale factor 731 @param sy vertical scale factor 732 @param px pivot on x-axis 733 @param py pivot on y-axis 734 */ 735 SkMatrix& preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py); 736 737 /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from scaling by (sx, sy) 738 about pivot point (0, 0). 739 This can be thought of as scaling about the origin before applying SkMatrix. 740 741 Given: 742 743 | A B C | | sx 0 0 | 744 Matrix = | D E F |, S(sx, sy) = | 0 sy 0 | 745 | G H I | | 0 0 1 | 746 747 sets SkMatrix to: 748 749 | A B C | | sx 0 0 | | A*sx B*sy C | 750 Matrix * S(sx, sy) = | D E F | | 0 sy 0 | = | D*sx E*sy F | 751 | G H I | | 0 0 1 | | G*sx H*sy I | 752 753 @param sx horizontal scale factor 754 @param sy vertical scale factor 755 */ 756 SkMatrix& preScale(SkScalar sx, SkScalar sy); 757 758 /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from rotating by degrees 759 about pivot point (px, py). 760 This can be thought of as rotating about a pivot point before applying SkMatrix. 761 762 Positive degrees rotates clockwise. 763 764 Given: 765 766 | A B C | | c -s dx | 767 Matrix = | D E F |, R(degrees, px, py) = | s c dy | 768 | G H I | | 0 0 1 | 769 770 where 771 772 c = cos(degrees) 773 s = sin(degrees) 774 dx = s * py + (1 - c) * px 775 dy = -s * px + (1 - c) * py 776 777 sets SkMatrix to: 778 779 | A B C | | c -s dx | | Ac+Bs -As+Bc A*dx+B*dy+C | 780 Matrix * R(degrees, px, py) = | D E F | | s c dy | = | Dc+Es -Ds+Ec D*dx+E*dy+F | 781 | G H I | | 0 0 1 | | Gc+Hs -Gs+Hc G*dx+H*dy+I | 782 783 @param degrees angle of axes relative to upright axes 784 @param px pivot on x-axis 785 @param py pivot on y-axis 786 */ 787 SkMatrix& preRotate(SkScalar degrees, SkScalar px, SkScalar py); 788 789 /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from rotating by degrees 790 about pivot point (0, 0). 791 This can be thought of as rotating about the origin before applying SkMatrix. 792 793 Positive degrees rotates clockwise. 794 795 Given: 796 797 | A B C | | c -s 0 | 798 Matrix = | D E F |, R(degrees, px, py) = | s c 0 | 799 | G H I | | 0 0 1 | 800 801 where 802 803 c = cos(degrees) 804 s = sin(degrees) 805 806 sets SkMatrix to: 807 808 | A B C | | c -s 0 | | Ac+Bs -As+Bc C | 809 Matrix * R(degrees, px, py) = | D E F | | s c 0 | = | Dc+Es -Ds+Ec F | 810 | G H I | | 0 0 1 | | Gc+Hs -Gs+Hc I | 811 812 @param degrees angle of axes relative to upright axes 813 */ 814 SkMatrix& preRotate(SkScalar degrees); 815 816 /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from skewing by (kx, ky) 817 about pivot point (px, py). 818 This can be thought of as skewing about a pivot point before applying SkMatrix. 819 820 Given: 821 822 | A B C | | 1 kx dx | 823 Matrix = | D E F |, K(kx, ky, px, py) = | ky 1 dy | 824 | G H I | | 0 0 1 | 825 826 where 827 828 dx = -kx * py 829 dy = -ky * px 830 831 sets SkMatrix to: 832 833 | A B C | | 1 kx dx | | A+B*ky A*kx+B A*dx+B*dy+C | 834 Matrix * K(kx, ky, px, py) = | D E F | | ky 1 dy | = | D+E*ky D*kx+E D*dx+E*dy+F | 835 | G H I | | 0 0 1 | | G+H*ky G*kx+H G*dx+H*dy+I | 836 837 @param kx horizontal skew factor 838 @param ky vertical skew factor 839 @param px pivot on x-axis 840 @param py pivot on y-axis 841 */ 842 SkMatrix& preSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py); 843 844 /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from skewing by (kx, ky) 845 about pivot point (0, 0). 846 This can be thought of as skewing about the origin before applying SkMatrix. 847 848 Given: 849 850 | A B C | | 1 kx 0 | 851 Matrix = | D E F |, K(kx, ky) = | ky 1 0 | 852 | G H I | | 0 0 1 | 853 854 sets SkMatrix to: 855 856 | A B C | | 1 kx 0 | | A+B*ky A*kx+B C | 857 Matrix * K(kx, ky) = | D E F | | ky 1 0 | = | D+E*ky D*kx+E F | 858 | G H I | | 0 0 1 | | G+H*ky G*kx+H I | 859 860 @param kx horizontal skew factor 861 @param ky vertical skew factor 862 */ 863 SkMatrix& preSkew(SkScalar kx, SkScalar ky); 864 865 /** Sets SkMatrix to SkMatrix multiplied by SkMatrix other. 866 This can be thought of mapping by other before applying SkMatrix. 867 868 Given: 869 870 | A B C | | J K L | 871 Matrix = | D E F |, other = | M N O | 872 | G H I | | P Q R | 873 874 sets SkMatrix to: 875 876 | A B C | | J K L | | AJ+BM+CP AK+BN+CQ AL+BO+CR | 877 Matrix * other = | D E F | * | M N O | = | DJ+EM+FP DK+EN+FQ DL+EO+FR | 878 | G H I | | P Q R | | GJ+HM+IP GK+HN+IQ GL+HO+IR | 879 880 @param other SkMatrix on right side of multiply expression 881 */ 882 SkMatrix& preConcat(const SkMatrix& other); 883 884 /** Sets SkMatrix to SkMatrix constructed from translation (dx, dy) multiplied by SkMatrix. 885 This can be thought of as moving the point to be mapped after applying SkMatrix. 886 887 Given: 888 889 | J K L | | 1 0 dx | 890 Matrix = | M N O |, T(dx, dy) = | 0 1 dy | 891 | P Q R | | 0 0 1 | 892 893 sets SkMatrix to: 894 895 | 1 0 dx | | J K L | | J+dx*P K+dx*Q L+dx*R | 896 T(dx, dy) * Matrix = | 0 1 dy | | M N O | = | M+dy*P N+dy*Q O+dy*R | 897 | 0 0 1 | | P Q R | | P Q R | 898 899 @param dx x-axis translation after applying SkMatrix 900 @param dy y-axis translation after applying SkMatrix 901 */ 902 SkMatrix& postTranslate(SkScalar dx, SkScalar dy); 903 904 /** Sets SkMatrix to SkMatrix constructed from scaling by (sx, sy) about pivot point 905 (px, py), multiplied by SkMatrix. 906 This can be thought of as scaling about a pivot point after applying SkMatrix. 907 908 Given: 909 910 | J K L | | sx 0 dx | 911 Matrix = | M N O |, S(sx, sy, px, py) = | 0 sy dy | 912 | P Q R | | 0 0 1 | 913 914 where 915 916 dx = px - sx * px 917 dy = py - sy * py 918 919 sets SkMatrix to: 920 921 | sx 0 dx | | J K L | | sx*J+dx*P sx*K+dx*Q sx*L+dx+R | 922 S(sx, sy, px, py) * Matrix = | 0 sy dy | | M N O | = | sy*M+dy*P sy*N+dy*Q sy*O+dy*R | 923 | 0 0 1 | | P Q R | | P Q R | 924 925 @param sx horizontal scale factor 926 @param sy vertical scale factor 927 @param px pivot on x-axis 928 @param py pivot on y-axis 929 */ 930 SkMatrix& postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py); 931 932 /** Sets SkMatrix to SkMatrix constructed from scaling by (sx, sy) about pivot point 933 (0, 0), multiplied by SkMatrix. 934 This can be thought of as scaling about the origin after applying SkMatrix. 935 936 Given: 937 938 | J K L | | sx 0 0 | 939 Matrix = | M N O |, S(sx, sy) = | 0 sy 0 | 940 | P Q R | | 0 0 1 | 941 942 sets SkMatrix to: 943 944 | sx 0 0 | | J K L | | sx*J sx*K sx*L | 945 S(sx, sy) * Matrix = | 0 sy 0 | | M N O | = | sy*M sy*N sy*O | 946 | 0 0 1 | | P Q R | | P Q R | 947 948 @param sx horizontal scale factor 949 @param sy vertical scale factor 950 */ 951 SkMatrix& postScale(SkScalar sx, SkScalar sy); 952 953 /** Sets SkMatrix to SkMatrix constructed from rotating by degrees about pivot point 954 (px, py), multiplied by SkMatrix. 955 This can be thought of as rotating about a pivot point after applying SkMatrix. 956 957 Positive degrees rotates clockwise. 958 959 Given: 960 961 | J K L | | c -s dx | 962 Matrix = | M N O |, R(degrees, px, py) = | s c dy | 963 | P Q R | | 0 0 1 | 964 965 where 966 967 c = cos(degrees) 968 s = sin(degrees) 969 dx = s * py + (1 - c) * px 970 dy = -s * px + (1 - c) * py 971 972 sets SkMatrix to: 973 974 |c -s dx| |J K L| |cJ-sM+dx*P cK-sN+dx*Q cL-sO+dx+R| 975 R(degrees, px, py) * Matrix = |s c dy| |M N O| = |sJ+cM+dy*P sK+cN+dy*Q sL+cO+dy*R| 976 |0 0 1| |P Q R| | P Q R| 977 978 @param degrees angle of axes relative to upright axes 979 @param px pivot on x-axis 980 @param py pivot on y-axis 981 */ 982 SkMatrix& postRotate(SkScalar degrees, SkScalar px, SkScalar py); 983 984 /** Sets SkMatrix to SkMatrix constructed from rotating by degrees about pivot point 985 (0, 0), multiplied by SkMatrix. 986 This can be thought of as rotating about the origin after applying SkMatrix. 987 988 Positive degrees rotates clockwise. 989 990 Given: 991 992 | J K L | | c -s 0 | 993 Matrix = | M N O |, R(degrees, px, py) = | s c 0 | 994 | P Q R | | 0 0 1 | 995 996 where 997 998 c = cos(degrees) 999 s = sin(degrees) 1000 1001 sets SkMatrix to: 1002 1003 | c -s dx | | J K L | | cJ-sM cK-sN cL-sO | 1004 R(degrees, px, py) * Matrix = | s c dy | | M N O | = | sJ+cM sK+cN sL+cO | 1005 | 0 0 1 | | P Q R | | P Q R | 1006 1007 @param degrees angle of axes relative to upright axes 1008 */ 1009 SkMatrix& postRotate(SkScalar degrees); 1010 1011 /** Sets SkMatrix to SkMatrix constructed from skewing by (kx, ky) about pivot point 1012 (px, py), multiplied by SkMatrix. 1013 This can be thought of as skewing about a pivot point after applying SkMatrix. 1014 1015 Given: 1016 1017 | J K L | | 1 kx dx | 1018 Matrix = | M N O |, K(kx, ky, px, py) = | ky 1 dy | 1019 | P Q R | | 0 0 1 | 1020 1021 where 1022 1023 dx = -kx * py 1024 dy = -ky * px 1025 1026 sets SkMatrix to: 1027 1028 | 1 kx dx| |J K L| |J+kx*M+dx*P K+kx*N+dx*Q L+kx*O+dx+R| 1029 K(kx, ky, px, py) * Matrix = |ky 1 dy| |M N O| = |ky*J+M+dy*P ky*K+N+dy*Q ky*L+O+dy*R| 1030 | 0 0 1| |P Q R| | P Q R| 1031 1032 @param kx horizontal skew factor 1033 @param ky vertical skew factor 1034 @param px pivot on x-axis 1035 @param py pivot on y-axis 1036 */ 1037 SkMatrix& postSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py); 1038 1039 /** Sets SkMatrix to SkMatrix constructed from skewing by (kx, ky) about pivot point 1040 (0, 0), multiplied by SkMatrix. 1041 This can be thought of as skewing about the origin after applying SkMatrix. 1042 1043 Given: 1044 1045 | J K L | | 1 kx 0 | 1046 Matrix = | M N O |, K(kx, ky) = | ky 1 0 | 1047 | P Q R | | 0 0 1 | 1048 1049 sets SkMatrix to: 1050 1051 | 1 kx 0 | | J K L | | J+kx*M K+kx*N L+kx*O | 1052 K(kx, ky) * Matrix = | ky 1 0 | | M N O | = | ky*J+M ky*K+N ky*L+O | 1053 | 0 0 1 | | P Q R | | P Q R | 1054 1055 @param kx horizontal skew factor 1056 @param ky vertical skew factor 1057 */ 1058 SkMatrix& postSkew(SkScalar kx, SkScalar ky); 1059 1060 /** Sets SkMatrix to SkMatrix other multiplied by SkMatrix. 1061 This can be thought of mapping by other after applying SkMatrix. 1062 1063 Given: 1064 1065 | J K L | | A B C | 1066 Matrix = | M N O |, other = | D E F | 1067 | P Q R | | G H I | 1068 1069 sets SkMatrix to: 1070 1071 | A B C | | J K L | | AJ+BM+CP AK+BN+CQ AL+BO+CR | 1072 other * Matrix = | D E F | * | M N O | = | DJ+EM+FP DK+EN+FQ DL+EO+FR | 1073 | G H I | | P Q R | | GJ+HM+IP GK+HN+IQ GL+HO+IR | 1074 1075 @param other SkMatrix on left side of multiply expression 1076 */ 1077 SkMatrix& postConcat(const SkMatrix& other); 1078 1079 /** \enum SkMatrix::ScaleToFit 1080 ScaleToFit describes how SkMatrix is constructed to map one SkRect to another. 1081 ScaleToFit may allow SkMatrix to have unequal horizontal and vertical scaling, 1082 or may restrict SkMatrix to square scaling. If restricted, ScaleToFit specifies 1083 how SkMatrix maps to the side or center of the destination SkRect. 1084 */ 1085 enum ScaleToFit { 1086 kFill_ScaleToFit, //!< scales in x and y to fill destination SkRect 1087 kStart_ScaleToFit, //!< scales and aligns to left and top 1088 kCenter_ScaleToFit, //!< scales and aligns to center 1089 kEnd_ScaleToFit, //!< scales and aligns to right and bottom 1090 }; 1091 1092 /** Sets SkMatrix to scale and translate src SkRect to dst SkRect. stf selects whether 1093 mapping completely fills dst or preserves the aspect ratio, and how to align 1094 src within dst. Returns false if src is empty, and sets SkMatrix to identity. 1095 Returns true if dst is empty, and sets SkMatrix to: 1096 1097 | 0 0 0 | 1098 | 0 0 0 | 1099 | 0 0 1 | 1100 1101 @param src SkRect to map from 1102 @param dst SkRect to map to 1103 @return true if SkMatrix can represent SkRect mapping 1104 1105 example: https://fiddle.skia.org/c/@Matrix_setRectToRect 1106 */ 1107 bool setRectToRect(const SkRect& src, const SkRect& dst, ScaleToFit stf); 1108 1109 /** Returns SkMatrix set to scale and translate src SkRect to dst SkRect. stf selects 1110 whether mapping completely fills dst or preserves the aspect ratio, and how to 1111 align src within dst. Returns the identity SkMatrix if src is empty. If dst is 1112 empty, returns SkMatrix set to: 1113 1114 | 0 0 0 | 1115 | 0 0 0 | 1116 | 0 0 1 | 1117 1118 @param src SkRect to map from 1119 @param dst SkRect to map to 1120 @return SkMatrix mapping src to dst 1121 */ MakeRectToRect(const SkRect & src,const SkRect & dst,ScaleToFit stf)1122 static SkMatrix MakeRectToRect(const SkRect& src, const SkRect& dst, ScaleToFit stf) { 1123 SkMatrix m; 1124 m.setRectToRect(src, dst, stf); 1125 return m; 1126 } 1127 1128 /** Sets SkMatrix to map src to dst. count must be zero or greater, and four or less. 1129 1130 If count is zero, sets SkMatrix to identity and returns true. 1131 If count is one, sets SkMatrix to translate and returns true. 1132 If count is two or more, sets SkMatrix to map SkPoint if possible; returns false 1133 if SkMatrix cannot be constructed. If count is four, SkMatrix may include 1134 perspective. 1135 1136 @param src SkPoint to map from 1137 @param dst SkPoint to map to 1138 @param count number of SkPoint in src and dst 1139 @return true if SkMatrix was constructed successfully 1140 1141 example: https://fiddle.skia.org/c/@Matrix_setPolyToPoly 1142 */ 1143 bool setPolyToPoly(const SkPoint src[], const SkPoint dst[], int count); 1144 1145 /** Sets inverse to reciprocal matrix, returning true if SkMatrix can be inverted. 1146 Geometrically, if SkMatrix maps from source to destination, inverse SkMatrix 1147 maps from destination to source. If SkMatrix can not be inverted, inverse is 1148 unchanged. 1149 1150 @param inverse storage for inverted SkMatrix; may be nullptr 1151 @return true if SkMatrix can be inverted 1152 */ invert(SkMatrix * inverse)1153 bool SK_WARN_UNUSED_RESULT invert(SkMatrix* inverse) const { 1154 // Allow the trivial case to be inlined. 1155 if (this->isIdentity()) { 1156 if (inverse) { 1157 inverse->reset(); 1158 } 1159 return true; 1160 } 1161 return this->invertNonIdentity(inverse); 1162 } 1163 1164 /** Fills affine with identity values in column major order. 1165 Sets affine to: 1166 1167 | 1 0 0 | 1168 | 0 1 0 | 1169 1170 Affine 3 by 2 matrices in column major order are used by OpenGL and XPS. 1171 1172 @param affine storage for 3 by 2 affine matrix 1173 1174 example: https://fiddle.skia.org/c/@Matrix_SetAffineIdentity 1175 */ 1176 static void SetAffineIdentity(SkScalar affine[6]); 1177 1178 /** Fills affine in column major order. Sets affine to: 1179 1180 | scale-x skew-x translate-x | 1181 | skew-y scale-y translate-y | 1182 1183 If SkMatrix contains perspective, returns false and leaves affine unchanged. 1184 1185 @param affine storage for 3 by 2 affine matrix; may be nullptr 1186 @return true if SkMatrix does not contain perspective 1187 */ 1188 bool SK_WARN_UNUSED_RESULT asAffine(SkScalar affine[6]) const; 1189 1190 /** Sets SkMatrix to affine values, passed in column major order. Given affine, 1191 column, then row, as: 1192 1193 | scale-x skew-x translate-x | 1194 | skew-y scale-y translate-y | 1195 1196 SkMatrix is set, row, then column, to: 1197 1198 | scale-x skew-x translate-x | 1199 | skew-y scale-y translate-y | 1200 | 0 0 1 | 1201 1202 @param affine 3 by 2 affine matrix 1203 */ 1204 SkMatrix& setAffine(const SkScalar affine[6]); 1205 1206 /** 1207 * A matrix is categorized as 'perspective' if the bottom row is not [0, 0, 1]. 1208 * However, for most uses (e.g. mapPoints) a bottom row of [0, 0, X] behaves like a 1209 * non-perspective matrix, though it will be categorized as perspective. Calling 1210 * normalizePerspective() will change the matrix such that, if its bottom row was [0, 0, X], 1211 * it will be changed to [0, 0, 1] by scaling the rest of the matrix by 1/X. 1212 * 1213 * | A B C | | A/X B/X C/X | 1214 * | D E F | -> | D/X E/X F/X | for X != 0 1215 * | 0 0 X | | 0 0 1 | 1216 */ normalizePerspective()1217 void normalizePerspective() { 1218 if (fMat[8] != 1) { 1219 this->doNormalizePerspective(); 1220 } 1221 } 1222 1223 /** Maps src SkPoint array of length count to dst SkPoint array of equal or greater 1224 length. SkPoint are mapped by multiplying each SkPoint by SkMatrix. Given: 1225 1226 | A B C | | x | 1227 Matrix = | D E F |, pt = | y | 1228 | G H I | | 1 | 1229 1230 where 1231 1232 for (i = 0; i < count; ++i) { 1233 x = src[i].fX 1234 y = src[i].fY 1235 } 1236 1237 each dst SkPoint is computed as: 1238 1239 |A B C| |x| Ax+By+C Dx+Ey+F 1240 Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , ------- 1241 |G H I| |1| Gx+Hy+I Gx+Hy+I 1242 1243 src and dst may point to the same storage. 1244 1245 @param dst storage for mapped SkPoint 1246 @param src SkPoint to transform 1247 @param count number of SkPoint to transform 1248 1249 example: https://fiddle.skia.org/c/@Matrix_mapPoints 1250 */ 1251 void mapPoints(SkPoint dst[], const SkPoint src[], int count) const; 1252 1253 /** Maps pts SkPoint array of length count in place. SkPoint are mapped by multiplying 1254 each SkPoint by SkMatrix. Given: 1255 1256 | A B C | | x | 1257 Matrix = | D E F |, pt = | y | 1258 | G H I | | 1 | 1259 1260 where 1261 1262 for (i = 0; i < count; ++i) { 1263 x = pts[i].fX 1264 y = pts[i].fY 1265 } 1266 1267 each resulting pts SkPoint is computed as: 1268 1269 |A B C| |x| Ax+By+C Dx+Ey+F 1270 Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , ------- 1271 |G H I| |1| Gx+Hy+I Gx+Hy+I 1272 1273 @param pts storage for mapped SkPoint 1274 @param count number of SkPoint to transform 1275 */ mapPoints(SkPoint pts[],int count)1276 void mapPoints(SkPoint pts[], int count) const { 1277 this->mapPoints(pts, pts, count); 1278 } 1279 1280 /** Maps src SkPoint3 array of length count to dst SkPoint3 array, which must of length count or 1281 greater. SkPoint3 array is mapped by multiplying each SkPoint3 by SkMatrix. Given: 1282 1283 | A B C | | x | 1284 Matrix = | D E F |, src = | y | 1285 | G H I | | z | 1286 1287 each resulting dst SkPoint is computed as: 1288 1289 |A B C| |x| 1290 Matrix * src = |D E F| |y| = |Ax+By+Cz Dx+Ey+Fz Gx+Hy+Iz| 1291 |G H I| |z| 1292 1293 @param dst storage for mapped SkPoint3 array 1294 @param src SkPoint3 array to transform 1295 @param count items in SkPoint3 array to transform 1296 1297 example: https://fiddle.skia.org/c/@Matrix_mapHomogeneousPoints 1298 */ 1299 void mapHomogeneousPoints(SkPoint3 dst[], const SkPoint3 src[], int count) const; 1300 1301 /** 1302 * Returns homogeneous points, starting with 2D src points (with implied w = 1). 1303 */ 1304 void mapHomogeneousPoints(SkPoint3 dst[], const SkPoint src[], int count) const; 1305 1306 /** Maps SkPoint (x, y) to result. SkPoint is mapped by multiplying by SkMatrix. Given: 1307 1308 | A B C | | x | 1309 Matrix = | D E F |, pt = | y | 1310 | G H I | | 1 | 1311 1312 result is computed as: 1313 1314 |A B C| |x| Ax+By+C Dx+Ey+F 1315 Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , ------- 1316 |G H I| |1| Gx+Hy+I Gx+Hy+I 1317 1318 @param x x-axis value of SkPoint to map 1319 @param y y-axis value of SkPoint to map 1320 @param result storage for mapped SkPoint 1321 1322 example: https://fiddle.skia.org/c/@Matrix_mapXY 1323 */ 1324 void mapXY(SkScalar x, SkScalar y, SkPoint* result) const; 1325 1326 /** Returns SkPoint (x, y) multiplied by SkMatrix. Given: 1327 1328 | A B C | | x | 1329 Matrix = | D E F |, pt = | y | 1330 | G H I | | 1 | 1331 1332 result is computed as: 1333 1334 |A B C| |x| Ax+By+C Dx+Ey+F 1335 Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , ------- 1336 |G H I| |1| Gx+Hy+I Gx+Hy+I 1337 1338 @param x x-axis value of SkPoint to map 1339 @param y y-axis value of SkPoint to map 1340 @return mapped SkPoint 1341 */ mapXY(SkScalar x,SkScalar y)1342 SkPoint mapXY(SkScalar x, SkScalar y) const { 1343 SkPoint result; 1344 this->mapXY(x,y, &result); 1345 return result; 1346 } 1347 1348 /** Maps src vector array of length count to vector SkPoint array of equal or greater 1349 length. Vectors are mapped by multiplying each vector by SkMatrix, treating 1350 SkMatrix translation as zero. Given: 1351 1352 | A B 0 | | x | 1353 Matrix = | D E 0 |, src = | y | 1354 | G H I | | 1 | 1355 1356 where 1357 1358 for (i = 0; i < count; ++i) { 1359 x = src[i].fX 1360 y = src[i].fY 1361 } 1362 1363 each dst vector is computed as: 1364 1365 |A B 0| |x| Ax+By Dx+Ey 1366 Matrix * src = |D E 0| |y| = |Ax+By Dx+Ey Gx+Hy+I| = ------- , ------- 1367 |G H I| |1| Gx+Hy+I Gx+Hy+I 1368 1369 src and dst may point to the same storage. 1370 1371 @param dst storage for mapped vectors 1372 @param src vectors to transform 1373 @param count number of vectors to transform 1374 1375 example: https://fiddle.skia.org/c/@Matrix_mapVectors 1376 */ 1377 void mapVectors(SkVector dst[], const SkVector src[], int count) const; 1378 1379 /** Maps vecs vector array of length count in place, multiplying each vector by 1380 SkMatrix, treating SkMatrix translation as zero. Given: 1381 1382 | A B 0 | | x | 1383 Matrix = | D E 0 |, vec = | y | 1384 | G H I | | 1 | 1385 1386 where 1387 1388 for (i = 0; i < count; ++i) { 1389 x = vecs[i].fX 1390 y = vecs[i].fY 1391 } 1392 1393 each result vector is computed as: 1394 1395 |A B 0| |x| Ax+By Dx+Ey 1396 Matrix * vec = |D E 0| |y| = |Ax+By Dx+Ey Gx+Hy+I| = ------- , ------- 1397 |G H I| |1| Gx+Hy+I Gx+Hy+I 1398 1399 @param vecs vectors to transform, and storage for mapped vectors 1400 @param count number of vectors to transform 1401 */ mapVectors(SkVector vecs[],int count)1402 void mapVectors(SkVector vecs[], int count) const { 1403 this->mapVectors(vecs, vecs, count); 1404 } 1405 1406 /** Maps vector (dx, dy) to result. Vector is mapped by multiplying by SkMatrix, 1407 treating SkMatrix translation as zero. Given: 1408 1409 | A B 0 | | dx | 1410 Matrix = | D E 0 |, vec = | dy | 1411 | G H I | | 1 | 1412 1413 each result vector is computed as: 1414 1415 |A B 0| |dx| A*dx+B*dy D*dx+E*dy 1416 Matrix * vec = |D E 0| |dy| = |A*dx+B*dy D*dx+E*dy G*dx+H*dy+I| = ----------- , ----------- 1417 |G H I| | 1| G*dx+H*dy+I G*dx+*dHy+I 1418 1419 @param dx x-axis value of vector to map 1420 @param dy y-axis value of vector to map 1421 @param result storage for mapped vector 1422 */ mapVector(SkScalar dx,SkScalar dy,SkVector * result)1423 void mapVector(SkScalar dx, SkScalar dy, SkVector* result) const { 1424 SkVector vec = { dx, dy }; 1425 this->mapVectors(result, &vec, 1); 1426 } 1427 1428 /** Returns vector (dx, dy) multiplied by SkMatrix, treating SkMatrix translation as zero. 1429 Given: 1430 1431 | A B 0 | | dx | 1432 Matrix = | D E 0 |, vec = | dy | 1433 | G H I | | 1 | 1434 1435 each result vector is computed as: 1436 1437 |A B 0| |dx| A*dx+B*dy D*dx+E*dy 1438 Matrix * vec = |D E 0| |dy| = |A*dx+B*dy D*dx+E*dy G*dx+H*dy+I| = ----------- , ----------- 1439 |G H I| | 1| G*dx+H*dy+I G*dx+*dHy+I 1440 1441 @param dx x-axis value of vector to map 1442 @param dy y-axis value of vector to map 1443 @return mapped vector 1444 */ mapVector(SkScalar dx,SkScalar dy)1445 SkVector mapVector(SkScalar dx, SkScalar dy) const { 1446 SkVector vec = { dx, dy }; 1447 this->mapVectors(&vec, &vec, 1); 1448 return vec; 1449 } 1450 1451 /** Sets dst to bounds of src corners mapped by SkMatrix. 1452 Returns true if mapped corners are dst corners. 1453 1454 Returned value is the same as calling rectStaysRect(). 1455 1456 @param dst storage for bounds of mapped SkPoint 1457 @param src SkRect to map 1458 @param pc whether to apply perspective clipping 1459 @return true if dst is equivalent to mapped src 1460 1461 example: https://fiddle.skia.org/c/@Matrix_mapRect 1462 */ 1463 bool mapRect(SkRect* dst, const SkRect& src, 1464 SkApplyPerspectiveClip pc = SkApplyPerspectiveClip::kYes) const; 1465 1466 /** Sets rect to bounds of rect corners mapped by SkMatrix. 1467 Returns true if mapped corners are computed rect corners. 1468 1469 Returned value is the same as calling rectStaysRect(). 1470 1471 @param rect rectangle to map, and storage for bounds of mapped corners 1472 @param pc whether to apply perspective clipping 1473 @return true if result is equivalent to mapped rect 1474 */ 1475 bool mapRect(SkRect* rect, SkApplyPerspectiveClip pc = SkApplyPerspectiveClip::kYes) const { 1476 return this->mapRect(rect, *rect, pc); 1477 } 1478 1479 /** Returns bounds of src corners mapped by SkMatrix. 1480 1481 @param src rectangle to map 1482 @return mapped bounds 1483 */ 1484 SkRect mapRect(const SkRect& src, 1485 SkApplyPerspectiveClip pc = SkApplyPerspectiveClip::kYes) const { 1486 SkRect dst; 1487 (void)this->mapRect(&dst, src, pc); 1488 return dst; 1489 } 1490 1491 /** Maps four corners of rect to dst. SkPoint are mapped by multiplying each 1492 rect corner by SkMatrix. rect corner is processed in this order: 1493 (rect.fLeft, rect.fTop), (rect.fRight, rect.fTop), (rect.fRight, rect.fBottom), 1494 (rect.fLeft, rect.fBottom). 1495 1496 rect may be empty: rect.fLeft may be greater than or equal to rect.fRight; 1497 rect.fTop may be greater than or equal to rect.fBottom. 1498 1499 Given: 1500 1501 | A B C | | x | 1502 Matrix = | D E F |, pt = | y | 1503 | G H I | | 1 | 1504 1505 where pt is initialized from each of (rect.fLeft, rect.fTop), 1506 (rect.fRight, rect.fTop), (rect.fRight, rect.fBottom), (rect.fLeft, rect.fBottom), 1507 each dst SkPoint is computed as: 1508 1509 |A B C| |x| Ax+By+C Dx+Ey+F 1510 Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , ------- 1511 |G H I| |1| Gx+Hy+I Gx+Hy+I 1512 1513 @param dst storage for mapped corner SkPoint 1514 @param rect SkRect to map 1515 1516 Note: this does not perform perspective clipping (as that might result in more than 1517 4 points, so results are suspect if the matrix contains perspective. 1518 */ mapRectToQuad(SkPoint dst[4],const SkRect & rect)1519 void mapRectToQuad(SkPoint dst[4], const SkRect& rect) const { 1520 // This could potentially be faster if we only transformed each x and y of the rect once. 1521 rect.toQuad(dst); 1522 this->mapPoints(dst, 4); 1523 } 1524 1525 /** Sets dst to bounds of src corners mapped by SkMatrix. If matrix contains 1526 elements other than scale or translate: asserts if SK_DEBUG is defined; 1527 otherwise, results are undefined. 1528 1529 @param dst storage for bounds of mapped SkPoint 1530 @param src SkRect to map 1531 1532 example: https://fiddle.skia.org/c/@Matrix_mapRectScaleTranslate 1533 */ 1534 void mapRectScaleTranslate(SkRect* dst, const SkRect& src) const; 1535 1536 /** Returns geometric mean radius of ellipse formed by constructing circle of 1537 size radius, and mapping constructed circle with SkMatrix. The result squared is 1538 equal to the major axis length times the minor axis length. 1539 Result is not meaningful if SkMatrix contains perspective elements. 1540 1541 @param radius circle size to map 1542 @return average mapped radius 1543 1544 example: https://fiddle.skia.org/c/@Matrix_mapRadius 1545 */ 1546 SkScalar mapRadius(SkScalar radius) const; 1547 1548 /** Compares a and b; returns true if a and b are numerically equal. Returns true 1549 even if sign of zero values are different. Returns false if either SkMatrix 1550 contains NaN, even if the other SkMatrix also contains NaN. 1551 1552 @param a SkMatrix to compare 1553 @param b SkMatrix to compare 1554 @return true if SkMatrix a and SkMatrix b are numerically equal 1555 */ 1556 friend SK_API bool operator==(const SkMatrix& a, const SkMatrix& b); 1557 1558 /** Compares a and b; returns true if a and b are not numerically equal. Returns false 1559 even if sign of zero values are different. Returns true if either SkMatrix 1560 contains NaN, even if the other SkMatrix also contains NaN. 1561 1562 @param a SkMatrix to compare 1563 @param b SkMatrix to compare 1564 @return true if SkMatrix a and SkMatrix b are numerically not equal 1565 */ 1566 friend SK_API bool operator!=(const SkMatrix& a, const SkMatrix& b) { 1567 return !(a == b); 1568 } 1569 1570 /** Writes text representation of SkMatrix to standard output. Floating point values 1571 are written with limited precision; it may not be possible to reconstruct 1572 original SkMatrix from output. 1573 1574 example: https://fiddle.skia.org/c/@Matrix_dump 1575 */ 1576 void dump() const; 1577 1578 /** Returns the minimum scaling factor of SkMatrix by decomposing the scaling and 1579 skewing elements. 1580 Returns -1 if scale factor overflows or SkMatrix contains perspective. 1581 1582 @return minimum scale factor 1583 1584 example: https://fiddle.skia.org/c/@Matrix_getMinScale 1585 */ 1586 SkScalar getMinScale() const; 1587 1588 /** Returns the maximum scaling factor of SkMatrix by decomposing the scaling and 1589 skewing elements. 1590 Returns -1 if scale factor overflows or SkMatrix contains perspective. 1591 1592 @return maximum scale factor 1593 1594 example: https://fiddle.skia.org/c/@Matrix_getMaxScale 1595 */ 1596 SkScalar getMaxScale() const; 1597 1598 /** Sets scaleFactors[0] to the minimum scaling factor, and scaleFactors[1] to the 1599 maximum scaling factor. Scaling factors are computed by decomposing 1600 the SkMatrix scaling and skewing elements. 1601 1602 Returns true if scaleFactors are found; otherwise, returns false and sets 1603 scaleFactors to undefined values. 1604 1605 @param scaleFactors storage for minimum and maximum scale factors 1606 @return true if scale factors were computed correctly 1607 */ 1608 bool SK_WARN_UNUSED_RESULT getMinMaxScales(SkScalar scaleFactors[2]) const; 1609 1610 /** Decomposes SkMatrix into scale components and whatever remains. Returns false if 1611 SkMatrix could not be decomposed. 1612 1613 Sets scale to portion of SkMatrix that scale axes. Sets remaining to SkMatrix 1614 with scaling factored out. remaining may be passed as nullptr 1615 to determine if SkMatrix can be decomposed without computing remainder. 1616 1617 Returns true if scale components are found. scale and remaining are 1618 unchanged if SkMatrix contains perspective; scale factors are not finite, or 1619 are nearly zero. 1620 1621 On success: Matrix = Remaining * scale. 1622 1623 @param scale axes scaling factors; may be nullptr 1624 @param remaining SkMatrix without scaling; may be nullptr 1625 @return true if scale can be computed 1626 1627 example: https://fiddle.skia.org/c/@Matrix_decomposeScale 1628 */ 1629 bool decomposeScale(SkSize* scale, SkMatrix* remaining = nullptr) const; 1630 1631 /** Returns reference to const identity SkMatrix. Returned SkMatrix is set to: 1632 1633 | 1 0 0 | 1634 | 0 1 0 | 1635 | 0 0 1 | 1636 1637 @return const identity SkMatrix 1638 1639 example: https://fiddle.skia.org/c/@Matrix_I 1640 */ 1641 static const SkMatrix& I(); 1642 1643 /** Returns reference to a const SkMatrix with invalid values. Returned SkMatrix is set 1644 to: 1645 1646 | SK_ScalarMax SK_ScalarMax SK_ScalarMax | 1647 | SK_ScalarMax SK_ScalarMax SK_ScalarMax | 1648 | SK_ScalarMax SK_ScalarMax SK_ScalarMax | 1649 1650 @return const invalid SkMatrix 1651 1652 example: https://fiddle.skia.org/c/@Matrix_InvalidMatrix 1653 */ 1654 static const SkMatrix& InvalidMatrix(); 1655 1656 /** Returns SkMatrix a multiplied by SkMatrix b. 1657 1658 Given: 1659 1660 | A B C | | J K L | 1661 a = | D E F |, b = | M N O | 1662 | G H I | | P Q R | 1663 1664 sets SkMatrix to: 1665 1666 | A B C | | J K L | | AJ+BM+CP AK+BN+CQ AL+BO+CR | 1667 a * b = | D E F | * | M N O | = | DJ+EM+FP DK+EN+FQ DL+EO+FR | 1668 | G H I | | P Q R | | GJ+HM+IP GK+HN+IQ GL+HO+IR | 1669 1670 @param a SkMatrix on left side of multiply expression 1671 @param b SkMatrix on right side of multiply expression 1672 @return SkMatrix computed from a times b 1673 */ Concat(const SkMatrix & a,const SkMatrix & b)1674 static SkMatrix Concat(const SkMatrix& a, const SkMatrix& b) { 1675 SkMatrix result; 1676 result.setConcat(a, b); 1677 return result; 1678 } 1679 1680 /** Sets internal cache to unknown state. Use to force update after repeated 1681 modifications to SkMatrix element reference returned by operator[](int index). 1682 */ dirtyMatrixTypeCache()1683 void dirtyMatrixTypeCache() { 1684 this->setTypeMask(kUnknown_Mask); 1685 } 1686 1687 /** Initializes SkMatrix with scale and translate elements. 1688 1689 | sx 0 tx | 1690 | 0 sy ty | 1691 | 0 0 1 | 1692 1693 @param sx horizontal scale factor to store 1694 @param sy vertical scale factor to store 1695 @param tx horizontal translation to store 1696 @param ty vertical translation to store 1697 */ setScaleTranslate(SkScalar sx,SkScalar sy,SkScalar tx,SkScalar ty)1698 void setScaleTranslate(SkScalar sx, SkScalar sy, SkScalar tx, SkScalar ty) { 1699 fMat[kMScaleX] = sx; 1700 fMat[kMSkewX] = 0; 1701 fMat[kMTransX] = tx; 1702 1703 fMat[kMSkewY] = 0; 1704 fMat[kMScaleY] = sy; 1705 fMat[kMTransY] = ty; 1706 1707 fMat[kMPersp0] = 0; 1708 fMat[kMPersp1] = 0; 1709 fMat[kMPersp2] = 1; 1710 1711 unsigned mask = 0; 1712 if (sx != 1 || sy != 1) { 1713 mask |= kScale_Mask; 1714 } 1715 if (tx || ty) { 1716 mask |= kTranslate_Mask; 1717 } 1718 this->setTypeMask(mask | kRectStaysRect_Mask); 1719 } 1720 1721 /** Returns true if all elements of the matrix are finite. Returns false if any 1722 element is infinity, or NaN. 1723 1724 @return true if matrix has only finite elements 1725 */ isFinite()1726 bool isFinite() const { return SkScalarsAreFinite(fMat, 9); } 1727 1728 private: 1729 /** Set if the matrix will map a rectangle to another rectangle. This 1730 can be true if the matrix is scale-only, or rotates a multiple of 1731 90 degrees. 1732 1733 This bit will be set on identity matrices 1734 */ 1735 static constexpr int kRectStaysRect_Mask = 0x10; 1736 1737 /** Set if the perspective bit is valid even though the rest of 1738 the matrix is Unknown. 1739 */ 1740 static constexpr int kOnlyPerspectiveValid_Mask = 0x40; 1741 1742 static constexpr int kUnknown_Mask = 0x80; 1743 1744 static constexpr int kORableMasks = kTranslate_Mask | 1745 kScale_Mask | 1746 kAffine_Mask | 1747 kPerspective_Mask; 1748 1749 static constexpr int kAllMasks = kTranslate_Mask | 1750 kScale_Mask | 1751 kAffine_Mask | 1752 kPerspective_Mask | 1753 kRectStaysRect_Mask; 1754 1755 SkScalar fMat[9]; 1756 mutable uint32_t fTypeMask; 1757 SkMatrix(SkScalar sx,SkScalar kx,SkScalar tx,SkScalar ky,SkScalar sy,SkScalar ty,SkScalar p0,SkScalar p1,SkScalar p2,uint32_t typeMask)1758 constexpr SkMatrix(SkScalar sx, SkScalar kx, SkScalar tx, 1759 SkScalar ky, SkScalar sy, SkScalar ty, 1760 SkScalar p0, SkScalar p1, SkScalar p2, uint32_t typeMask) 1761 : fMat{sx, kx, tx, 1762 ky, sy, ty, 1763 p0, p1, p2} 1764 , fTypeMask(typeMask) {} 1765 1766 static void ComputeInv(SkScalar dst[9], const SkScalar src[9], double invDet, bool isPersp); 1767 1768 uint8_t computeTypeMask() const; 1769 uint8_t computePerspectiveTypeMask() const; 1770 setTypeMask(int mask)1771 void setTypeMask(int mask) { 1772 // allow kUnknown or a valid mask 1773 SkASSERT(kUnknown_Mask == mask || (mask & kAllMasks) == mask || 1774 ((kUnknown_Mask | kOnlyPerspectiveValid_Mask) & mask) 1775 == (kUnknown_Mask | kOnlyPerspectiveValid_Mask)); 1776 fTypeMask = SkToU8(mask); 1777 } 1778 orTypeMask(int mask)1779 void orTypeMask(int mask) { 1780 SkASSERT((mask & kORableMasks) == mask); 1781 fTypeMask = SkToU8(fTypeMask | mask); 1782 } 1783 clearTypeMask(int mask)1784 void clearTypeMask(int mask) { 1785 // only allow a valid mask 1786 SkASSERT((mask & kAllMasks) == mask); 1787 fTypeMask = fTypeMask & ~mask; 1788 } 1789 getPerspectiveTypeMaskOnly()1790 TypeMask getPerspectiveTypeMaskOnly() const { 1791 if ((fTypeMask & kUnknown_Mask) && 1792 !(fTypeMask & kOnlyPerspectiveValid_Mask)) { 1793 fTypeMask = this->computePerspectiveTypeMask(); 1794 } 1795 return (TypeMask)(fTypeMask & 0xF); 1796 } 1797 1798 /** Returns true if we already know that the matrix is identity; 1799 false otherwise. 1800 */ isTriviallyIdentity()1801 bool isTriviallyIdentity() const { 1802 if (fTypeMask & kUnknown_Mask) { 1803 return false; 1804 } 1805 return ((fTypeMask & 0xF) == 0); 1806 } 1807 updateTranslateMask()1808 inline void updateTranslateMask() { 1809 if ((fMat[kMTransX] != 0) | (fMat[kMTransY] != 0)) { 1810 fTypeMask |= kTranslate_Mask; 1811 } else { 1812 fTypeMask &= ~kTranslate_Mask; 1813 } 1814 } 1815 1816 typedef void (*MapXYProc)(const SkMatrix& mat, SkScalar x, SkScalar y, 1817 SkPoint* result); 1818 GetMapXYProc(TypeMask mask)1819 static MapXYProc GetMapXYProc(TypeMask mask) { 1820 SkASSERT((mask & ~kAllMasks) == 0); 1821 return gMapXYProcs[mask & kAllMasks]; 1822 } 1823 getMapXYProc()1824 MapXYProc getMapXYProc() const { 1825 return GetMapXYProc(this->getType()); 1826 } 1827 1828 typedef void (*MapPtsProc)(const SkMatrix& mat, SkPoint dst[], 1829 const SkPoint src[], int count); 1830 GetMapPtsProc(TypeMask mask)1831 static MapPtsProc GetMapPtsProc(TypeMask mask) { 1832 SkASSERT((mask & ~kAllMasks) == 0); 1833 return gMapPtsProcs[mask & kAllMasks]; 1834 } 1835 getMapPtsProc()1836 MapPtsProc getMapPtsProc() const { 1837 return GetMapPtsProc(this->getType()); 1838 } 1839 1840 bool SK_WARN_UNUSED_RESULT invertNonIdentity(SkMatrix* inverse) const; 1841 1842 static bool Poly2Proc(const SkPoint[], SkMatrix*); 1843 static bool Poly3Proc(const SkPoint[], SkMatrix*); 1844 static bool Poly4Proc(const SkPoint[], SkMatrix*); 1845 1846 static void Identity_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*); 1847 static void Trans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*); 1848 static void Scale_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*); 1849 static void ScaleTrans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*); 1850 static void Rot_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*); 1851 static void RotTrans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*); 1852 static void Persp_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*); 1853 1854 static const MapXYProc gMapXYProcs[]; 1855 1856 static void Identity_pts(const SkMatrix&, SkPoint[], const SkPoint[], int); 1857 static void Trans_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int); 1858 static void Scale_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int); 1859 static void ScaleTrans_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], 1860 int count); 1861 static void Persp_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int); 1862 1863 static void Affine_vpts(const SkMatrix&, SkPoint dst[], const SkPoint[], int); 1864 1865 static const MapPtsProc gMapPtsProcs[]; 1866 1867 // return the number of bytes written, whether or not buffer is null 1868 size_t writeToMemory(void* buffer) const; 1869 /** 1870 * Reads data from the buffer parameter 1871 * 1872 * @param buffer Memory to read from 1873 * @param length Amount of memory available in the buffer 1874 * @return number of bytes read (must be a multiple of 4) or 1875 * 0 if there was not enough memory available 1876 */ 1877 size_t readFromMemory(const void* buffer, size_t length); 1878 1879 // legacy method -- still needed? why not just postScale(1/divx, ...)? 1880 bool postIDiv(int divx, int divy); 1881 void doNormalizePerspective(); 1882 1883 friend class SkPerspIter; 1884 friend class SkMatrixPriv; 1885 friend class SkReader32; 1886 friend class SerializationTest; 1887 }; 1888 SK_END_REQUIRE_DENSE 1889 1890 #endif 1891