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