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