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