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