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