Home | History | Annotate | Download | only in docs
      1 #Topic Matrix
      2 #Alias Matrices ##
      3 #Alias Matrix_Reference ##
      4 
      5 #Class SkMatrix
      6 
      7 #Code
      8 #Populate
      9 ##
     10 
     11 Matrix holds a 3 by 3 matrix for transforming coordinates. This allows mapping
     12 Points and Vectors with translation, scaling, skewing, rotation, and
     13 perspective.
     14 
     15 Matrix elements are in row major order. Matrix does not have a constructor,
     16 so it must be explicitly initialized. setIdentity initializes Matrix
     17 so it has no effect. setTranslate, setScale, setSkew, setRotate, set9 and setAll
     18 initializes all Matrix elements with the corresponding mapping.
     19 
     20 Matrix includes a hidden variable that classifies the type of matrix to
     21 improve performance. Matrix is not thread safe unless getType is called first.
     22 
     23 # ------------------------------------------------------------------------------
     24 
     25 #Method static SkMatrix MakeScale(SkScalar sx, SkScalar sy)
     26 #In Constructors
     27 #Line # constructs from scale on x-axis and y-axis ##
     28 #Populate
     29 
     30 #Example
     31 #Image 4
     32 canvas->concat(SkMatrix::MakeScale(4, 3));
     33 canvas->drawBitmap(source, 0, 0);
     34 ##
     35 
     36 #SeeAlso setScale postScale preScale
     37 
     38 ##
     39 
     40 # ------------------------------------------------------------------------------
     41 
     42 #Method static SkMatrix MakeScale(SkScalar scale)
     43 #Populate
     44 
     45 #Example
     46 #Image 4
     47 canvas->concat(SkMatrix::MakeScale(4));
     48 canvas->drawBitmap(source, 0, 0);
     49 ##
     50 
     51 #SeeAlso setScale postScale preScale
     52 
     53 ##
     54 
     55 # ------------------------------------------------------------------------------
     56 
     57 #Method static SkMatrix MakeTrans(SkScalar dx, SkScalar dy)
     58 #In Constructors
     59 #Line # constructs from translate on x-axis and y-axis ##
     60 #Populate
     61 
     62 #Example
     63 #Image 4
     64 SkMatrix matrix = SkMatrix::MakeTrans(64, 48);
     65 for (int i = 0; i < 4; ++i) {
     66     canvas->drawBitmap(source, 0, 0);
     67     canvas->concat(matrix);
     68 }
     69 ##
     70 
     71 #SeeAlso setTranslate postTranslate preTranslate
     72 
     73 ##
     74 
     75 # ------------------------------------------------------------------------------
     76 
     77 #Method static SkMatrix MakeAll(SkScalar scaleX, SkScalar skewX,  SkScalar transX,
     78                                                       SkScalar skewY,  SkScalar scaleY, SkScalar transY,
     79                                                       SkScalar pers0, SkScalar pers1, SkScalar pers2)
     80 #In Constructors
     81 #Line # constructs all nine values ##
     82 #Populate
     83 
     84 #Example
     85     SkPaint p;
     86     p.setAntiAlias(true);
     87     p.setTextSize(64);
     88     for (SkScalar sx : { -1, 1 } ) {
     89         for (SkScalar sy : { -1, 1 } ) {
     90             SkAutoCanvasRestore autoRestore(canvas, true);
     91             SkMatrix m = SkMatrix::MakeAll(sx, 1, 128,    0, sy, 128,   0, 0, 1);
     92             canvas->concat(m);
     93             canvas->drawString("K", 0, 0, p);
     94         }
     95     }
     96 ##
     97 
     98 #SeeAlso setAll set9 postConcat preConcat
     99 
    100 ##
    101 
    102 
    103 # ------------------------------------------------------------------------------
    104 
    105 #Enum TypeMask
    106 #Line # bit field for Matrix complexity ##
    107 #Code
    108 #Populate
    109 ##
    110 
    111 Enumeration of bit fields for mask returned by getType.
    112 Used to identify the complexity of Matrix, to optimize performance.
    113 
    114 #Const kIdentity_Mask 0
    115 #Line # identity Matrix; all bits clear ##
    116 all bits clear if Matrix is identity
    117 ##
    118 #Const kTranslate_Mask 1
    119 #Line # translation Matrix ##
    120 set if Matrix has translation
    121 ##
    122 #Const kScale_Mask 2
    123 #Line # scale Matrix ##
    124 set if Matrix scales x-axis or y-axis
    125 ##
    126 #Const kAffine_Mask 4
    127 #Line # skew or rotate Matrix ##
    128 set if Matrix skews or rotates
    129 ##
    130 #Const kPerspective_Mask 8
    131 #Line # perspective Matrix ##
    132 set if Matrix has perspective
    133 ##
    134 
    135 #Example
    136     auto debugster = [](const char* prefix, const SkMatrix& matrix) -> void {
    137         SkString typeMask;
    138         typeMask += SkMatrix::kIdentity_Mask == matrix.getType() ? "kIdentity_Mask " : "";
    139         typeMask += SkMatrix::kTranslate_Mask & matrix.getType() ? "kTranslate_Mask " : "";
    140         typeMask += SkMatrix::kScale_Mask & matrix.getType() ? "kScale_Mask " : "";
    141         typeMask += SkMatrix::kAffine_Mask & matrix.getType() ? "kAffine_Mask " : "";
    142         typeMask += SkMatrix::kPerspective_Mask & matrix.getType() ? "kPerspective_Mask" : "";
    143         SkDebugf("after %s: %s\n", prefix, typeMask.c_str());
    144     };
    145 SkMatrix matrix;
    146 matrix.reset();
    147 debugster("reset", matrix);
    148 matrix.postTranslate(1, 0);
    149 debugster("postTranslate", matrix);
    150 matrix.postScale(2, 1);
    151 debugster("postScale", matrix);
    152 matrix.postRotate(45);
    153 debugster("postScale", matrix);
    154 SkPoint polys[][4] = {{{0, 0}, {0, 1}, {1, 1}, {1, 0}}, {{0, 0}, {0, 1}, {2, 1}, {1, 0}}};
    155 matrix.setPolyToPoly(polys[0], polys[1], 4);
    156 debugster("setPolyToPoly", matrix);
    157 #StdOut
    158 after reset: kIdentity_Mask
    159 after postTranslate: kTranslate_Mask
    160 after postScale: kTranslate_Mask kScale_Mask
    161 after postScale: kTranslate_Mask kScale_Mask kAffine_Mask
    162 after setPolyToPoly: kTranslate_Mask kScale_Mask kAffine_Mask kPerspective_Mask
    163 ##
    164 ##
    165 
    166 #SeeAlso getType
    167 
    168 ##
    169 
    170 # ------------------------------------------------------------------------------
    171 #Subtopic Property
    172 #Line # values and attributes ##
    173 ##
    174 
    175 #Method TypeMask getType() const
    176 #In Property
    177 #Line # returns transform complexity ##
    178 #Populate
    179 
    180 #Example
    181 SkMatrix matrix;
    182 matrix.setAll(1, 0, 0,   0, 1, 0,    0, 0, 1);
    183 SkDebugf("identity flags hex: %0x decimal: %d\n", matrix.getType(), matrix.getType());
    184 matrix.setAll(1, 0, 0,   0, 1, 0,    0, 0, .5f);
    185 SkDebugf("set all  flags hex: %0x decimal: %d\n", matrix.getType(), matrix.getType());
    186 #StdOut
    187 identity flags hex: 0 decimal: 0
    188 set all  flags hex: f decimal: 15
    189 ##
    190 ##
    191 
    192 #SeeAlso TypeMask
    193 
    194 ##
    195 
    196 # ------------------------------------------------------------------------------
    197 
    198 #Method bool isIdentity() const
    199 #In Property
    200 #Line # returns if matrix equals the identity Matrix  ##
    201 #Populate
    202 
    203 #Example
    204 SkMatrix matrix;
    205 matrix.setAll(1, 0, 0,   0, 1, 0,    0, 0, 1);
    206 SkDebugf("is identity: %s\n", matrix.isIdentity() ? "true" : "false");
    207 matrix.setAll(1, 0, 0,   0, 1, 0,    0, 0, 2);
    208 SkDebugf("is identity: %s\n", matrix.isIdentity() ? "true" : "false");
    209 #StdOut
    210 is identity: true
    211 is identity: false
    212 ##
    213 ##
    214 
    215 #SeeAlso reset() setIdentity getType
    216 
    217 ##
    218 
    219 # ------------------------------------------------------------------------------
    220 
    221 #Method bool isScaleTranslate() const
    222 #In Property
    223 #Line # returns if transform is limited to scale and translate ##
    224 #Populate
    225 
    226 #Example
    227 SkMatrix matrix;
    228 for (SkScalar scaleX : { 1, 2 } ) {
    229     for (SkScalar translateX : { 0, 20 } ) {
    230         matrix.setAll(scaleX, 0, translateX,   0, 1, 0,    0, 0, 1);
    231         SkDebugf("is scale-translate: %s\n", matrix.isScaleTranslate() ? "true" : "false");
    232     }
    233 }
    234 #StdOut
    235 is scale-translate: true
    236 is scale-translate: true
    237 is scale-translate: true
    238 is scale-translate: true
    239 ##
    240 ##
    241 
    242 #SeeAlso setScale isTranslate setTranslate getType
    243 
    244 ##
    245 
    246 # ------------------------------------------------------------------------------
    247 
    248 #Method bool isTranslate() const
    249 #In Property
    250 #Line # returns if transform is limited to translate ##
    251 #Populate
    252 
    253 #Example
    254 SkMatrix matrix;
    255 for (SkScalar scaleX : { 1, 2 } ) {
    256     for (SkScalar translateX : { 0, 20 } ) {
    257         matrix.setAll(scaleX, 0, translateX,   0, 1, 0,    0, 0, 1);
    258         SkDebugf("is translate: %s\n", matrix.isTranslate() ? "true" : "false");
    259     }
    260 }
    261 #StdOut
    262 is translate: true
    263 is translate: true
    264 is translate: false
    265 is translate: false
    266 ##
    267 ##
    268 
    269 #SeeAlso setTranslate getType
    270 
    271 ##
    272 
    273 # ------------------------------------------------------------------------------
    274 
    275 #Method bool rectStaysRect() const
    276 #In Property
    277 #Line # returns if mapped Rect can be represented by another Rect ##
    278 #Populate
    279 
    280 #Example
    281 SkMatrix matrix;
    282 for (SkScalar angle: { 0, 90, 180, 270 } ) {
    283     matrix.setRotate(angle);
    284     SkDebugf("rectStaysRect: %s\n", matrix.rectStaysRect() ? "true" : "false");
    285 }
    286 #StdOut
    287 rectStaysRect: true
    288 rectStaysRect: true
    289 rectStaysRect: true
    290 rectStaysRect: true
    291 ##
    292 ##
    293 
    294 #SeeAlso preservesAxisAlignment preservesRightAngles
    295 
    296 ##
    297 
    298 # ------------------------------------------------------------------------------
    299 
    300 #Method bool preservesAxisAlignment() const
    301 #In Property
    302 #Line # returns if mapping restricts to 90 degree multiples and mirroring ##
    303 #Populate
    304 
    305 #Example
    306 SkMatrix matrix;
    307 for (SkScalar angle: { 0, 90, 180, 270 } ) {
    308     matrix.setRotate(angle);
    309     SkDebugf("preservesAxisAlignment: %s\n", matrix.preservesAxisAlignment() ? "true" : "false");
    310 }
    311 #StdOut
    312 preservesAxisAlignment: true
    313 preservesAxisAlignment: true
    314 preservesAxisAlignment: true
    315 preservesAxisAlignment: true
    316 ##
    317 ##
    318 
    319 #SeeAlso rectStaysRect preservesRightAngles
    320 
    321 ##
    322 
    323 # ------------------------------------------------------------------------------
    324 
    325 #Method bool hasPerspective() const
    326 #In Property
    327 #Line # returns if transform includes perspective ##
    328 #Populate
    329 
    330 #Example
    331 #Image 4
    332 SkMatrix matrix;
    333 SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
    334 SkRect::Make(source.bounds()).toQuad(bitmapBounds);
    335 matrix.setPolyToPoly(bitmapBounds, perspect, 4);
    336 canvas->concat(matrix);
    337 SkString string;
    338 string.printf("hasPerspective %s", matrix.hasPerspective() ? "true" : "false");
    339 canvas->drawBitmap(source, 0, 0);
    340 SkPaint paint;
    341 paint.setAntiAlias(true);
    342 paint.setTextSize(48);
    343 canvas->drawString(string, 0, source.bounds().height() + 48, paint);
    344 ##
    345 
    346 #SeeAlso setAll set9 MakeAll
    347 
    348 ##
    349 
    350 # ------------------------------------------------------------------------------
    351 
    352 #Method bool isSimilarity(SkScalar tol = SK_ScalarNearlyZero) const
    353 #In Property
    354 #Line # returns if transform is limited to square scale and rotation ##
    355 #Populate
    356 
    357 #Example
    358 #Description
    359 String is drawn four times through but only two are visible. Drawing the pair
    360 with isSimilarity false reveals the pair not visible through the matrix.
    361 ##
    362     SkPaint p;
    363     p.setAntiAlias(true);
    364     SkMatrix m;
    365     int below = 175;
    366     for (SkScalar sx : { -1, 1 } ) {
    367         for (SkScalar sy : { -1, 1 } ) {
    368             m.setAll(sx, 1, 128,    1, sy, 32,   0, 0, 1);
    369             bool isSimilarity = m.isSimilarity();
    370             SkString str;
    371             str.printf("sx: %g sy: %g sim: %s", sx, sy, isSimilarity ? "true" : "false");
    372             {
    373                 SkAutoCanvasRestore autoRestore(canvas, true);
    374                 canvas->concat(m);
    375                 canvas->drawString(str, 0, 0, p);
    376             }
    377             if (!isSimilarity) {
    378                 canvas->drawString(str, 40, below, p);
    379                 below += 20;
    380             }
    381         }
    382     }
    383 ##
    384 
    385 #SeeAlso isScaleTranslate preservesRightAngles rectStaysRect isFixedStepInX
    386 
    387 ##
    388 
    389 # ------------------------------------------------------------------------------
    390 
    391 #Method bool preservesRightAngles(SkScalar tol = SK_ScalarNearlyZero) const
    392 #In Property
    393 #Line # returns if mapped 90 angle remains 90 degrees ##
    394 #Populate
    395 
    396 #Example
    397 #Height 128
    398 #Description
    399 Equal scale is both similar and preserves right angles.
    400 Unequal scale is not similar but preserves right angles.
    401 Skews are not similar and do not preserve right angles.
    402 ##
    403 SkPaint p;
    404 p.setAntiAlias(true);
    405 SkMatrix m;
    406 int pos = 0;
    407 for (SkScalar sx : { 1, 2 } ) {
    408     for (SkScalar kx : { 0, 1 } ) {
    409         m.setAll(sx, kx, 16,    0, 1, 32,   0, 0, 1);
    410         bool isSimilarity = m.isSimilarity();
    411         bool preservesRightAngles = m.preservesRightAngles();
    412         SkString str;
    413         str.printf("sx: %g kx: %g %s %s", sx, kx, isSimilarity ? "sim" : "",
    414                     preservesRightAngles ? "right" : "");
    415         SkAutoCanvasRestore autoRestore(canvas, true);
    416         canvas->concat(m);
    417         canvas->drawString(str, 0, pos, p);
    418         pos += 20;
    419     }
    420 }
    421 ##
    422 
    423 #SeeAlso isScaleTranslate isSimilarity rectStaysRect isFixedStepInX
    424 
    425 ##
    426 
    427 # ------------------------------------------------------------------------------
    428 
    429 #Subtopic MemberIndex
    430 #In Constant
    431 #Line # member indices ##
    432 #Filter kM
    433 #Code
    434 #Populate
    435 ##
    436 
    437 Matrix organizes its values in row order. These members correspond to
    438 each value in Matrix.
    439 
    440 #Const kMScaleX 0
    441 #Line # horizontal scale factor ##
    442 ##
    443 #Const kMSkewX 1
    444 #Line # horizontal skew factor ##
    445 ##
    446 #Const kMTransX 2
    447 #Line # horizontal translation ##
    448 ##
    449 #Const kMSkewY 3
    450 #Line # vertical skew factor ##
    451 ##
    452 #Const kMScaleY 4
    453 #Line # vertical scale factor ##
    454 ##
    455 #Const kMTransY 5
    456 #Line # vertical translation ##
    457 ##
    458 #Const kMPersp0 6
    459 #Line # input x perspective factor ##
    460 ##
    461 #Const kMPersp1 7
    462 #Line # input y perspective factor ##
    463 ##
    464 #Const kMPersp2 8
    465 #Line # perspective bias ##
    466 ##
    467 
    468 #Example
    469 SkPaint black;
    470 black.setAntiAlias(true);
    471 black.setTextSize(48);
    472 SkPaint gray = black;
    473 gray.setColor(0xFF9f9f9f);
    474 SkScalar offset[] = { 1.5f, 1.5f, 20,   1.5f, 1.5f, 20,   .03f, .01f, 2 };
    475 for (int i : { SkMatrix::kMScaleX, SkMatrix::kMSkewX,  SkMatrix::kMTransX,
    476                SkMatrix::kMSkewY,  SkMatrix::kMScaleY, SkMatrix::kMTransY,
    477                SkMatrix::kMPersp0, SkMatrix::kMPersp1, SkMatrix::kMPersp2 } ) {
    478     SkMatrix m;
    479     m.setIdentity();
    480     m.set(i, offset[i]);
    481     SkAutoCanvasRestore autoRestore(canvas, true);
    482     canvas->translate(22 + (i % 3) * 88, 44 + (i / 3) * 88);
    483     canvas->drawString("&", 0, 0, gray);
    484     canvas->concat(m);
    485     canvas->drawString("&", 0, 0, black);
    486 }
    487 ##
    488 
    489 #SeeAlso get() set()
    490 
    491 ##
    492 
    493 # ------------------------------------------------------------------------------
    494 
    495 #Subtopic AffineIndex
    496 #In Constant
    497 #Line # affine member indices ##
    498 #Filter KA
    499 
    500 #Code
    501 #Populate
    502 ##
    503 
    504 Affine arrays are in column major order to match the matrix used by
    505 PDF and XPS.
    506 
    507 #Const kAScaleX 0
    508 #Line # horizontal scale factor ##
    509 ##
    510 #Const kASkewY 1
    511 #Line # vertical skew factor ##
    512 ##
    513 #Const kASkewX 2
    514 #Line # horizontal skew factor ##
    515 ##
    516 #Const kAScaleY 3
    517 #Line # vertical scale factor ##
    518 ##
    519 #Const kATransX 4
    520 #Line # horizontal translation ##
    521 ##
    522 #Const kATransY 5
    523 #Line # vertical translation ##
    524 ##
    525 
    526 #NoExample
    527 ##
    528 
    529 #SeeAlso SetAffineIdentity asAffine setAffine
    530 
    531 ##
    532 
    533 # ------------------------------------------------------------------------------
    534 
    535 #Method SkScalar operator[](int index) const
    536 
    537 #Line # returns Matrix value ##
    538 #Populate
    539 
    540 #Example
    541 SkMatrix matrix;
    542 matrix.setScale(42, 24);
    543 SkDebugf("matrix[SkMatrix::kMScaleX] %c= 42\n", matrix[SkMatrix::kMScaleX] == 42 ? '=' : '!');
    544 SkDebugf("matrix[SkMatrix::kMScaleY] %c= 24\n", matrix[SkMatrix::kMScaleY] == 24 ? '=' : '!');
    545 #StdOut
    546 matrix[SkMatrix::kMScaleX] == 42
    547 matrix[SkMatrix::kMScaleY] == 24
    548 ##
    549 ##
    550 
    551 #SeeAlso get set
    552 
    553 ##
    554 
    555 # ------------------------------------------------------------------------------
    556 
    557 #Method SkScalar get(int index) const
    558 #In Property
    559 #Line # returns one of nine Matrix values ##
    560 #Populate
    561 
    562 #Example
    563 SkMatrix matrix;
    564 matrix.setSkew(42, 24);
    565 SkDebugf("matrix.get(SkMatrix::kMSkewX) %c= 42\n",
    566          matrix.get(SkMatrix::kMSkewX) == 42 ? '=' : '!');
    567 SkDebugf("matrix.get(SkMatrix::kMSkewY) %c= 24\n",
    568          matrix.get(SkMatrix::kMSkewY) == 24 ? '=' : '!');
    569 #StdOut
    570 matrix.get(SkMatrix::kMSkewX) == 42
    571 matrix.get(SkMatrix::kMSkewY) == 24
    572 ##
    573 ##
    574 
    575 #SeeAlso operator[](int index) set
    576 
    577 ##
    578 
    579 # ------------------------------------------------------------------------------
    580 
    581 #Method SkScalar getScaleX() const
    582 #In Property
    583 #Line # returns horizontal scale factor ##
    584 #Populate
    585 
    586 #Example
    587 SkMatrix matrix;
    588 matrix.setScale(42, 24);
    589 SkDebugf("matrix.getScaleX() %c= 42\n", matrix.getScaleX() == 42 ? '=' : '!');
    590 #StdOut
    591 matrix.getScaleX() == 42
    592 ##
    593 ##
    594 
    595 #SeeAlso get getScaleY setScaleX setScale
    596 
    597 ##
    598 
    599 # ------------------------------------------------------------------------------
    600 
    601 #Method SkScalar getScaleY() const
    602 #In Property
    603 #Line # returns vertical scale factor ##
    604 #Populate
    605 
    606 #Example
    607 SkMatrix matrix;
    608 matrix.setScale(42, 24);
    609 SkDebugf("matrix.getScaleY() %c= 24\n", matrix.getScaleY() == 24 ? '=' : '!');
    610 #StdOut
    611 matrix.getScaleY() == 24
    612 ##
    613 ##
    614 
    615 #SeeAlso get getScaleX setScaleY setScale
    616 
    617 ##
    618 
    619 # ------------------------------------------------------------------------------
    620 
    621 #Method SkScalar getSkewY() const
    622 #In Property
    623 #Line # returns vertical skew factor ##
    624 #Populate
    625 
    626 #Example
    627 SkMatrix matrix;
    628 matrix.setSkew(42, 24);
    629 SkDebugf("matrix.getSkewY() %c= 24\n", matrix.getSkewY() == 24 ? '=' : '!');
    630 #StdOut
    631 matrix.getSkewY() == 24
    632 ##
    633 ##
    634 
    635 #SeeAlso get getSkewX setSkewY setSkew
    636 
    637 ##
    638 
    639 # ------------------------------------------------------------------------------
    640 
    641 #Method SkScalar getSkewX() const
    642 #In Property
    643 #Line # returns horizontal skew factor ##
    644 #Populate
    645 
    646 #Example
    647 SkMatrix matrix;
    648 matrix.setSkew(42, 24);
    649 SkDebugf("matrix.getSkewX() %c= 42\n", matrix.getSkewX() == 42 ? '=' : '!');
    650 #StdOut
    651 matrix.getSkewX() == 42
    652 ##
    653 ##
    654 
    655 #SeeAlso get getSkewY setSkewX setSkew
    656 
    657 ##
    658 
    659 # ------------------------------------------------------------------------------
    660 
    661 #Method SkScalar getTranslateX() const
    662 #In Property
    663 #Line # returns horizontal translation ##
    664 #Populate
    665 
    666 #Example
    667 SkMatrix matrix;
    668 matrix.setTranslate(42, 24);
    669 SkDebugf("matrix.getTranslateX() %c= 42\n", matrix.getTranslateX() == 42 ? '=' : '!');
    670 #StdOut
    671 matrix.getTranslateX() == 42
    672 ##
    673 ##
    674 
    675 #SeeAlso get getTranslateY setTranslateX setTranslate
    676 
    677 ##
    678 
    679 # ------------------------------------------------------------------------------
    680 
    681 #Method SkScalar getTranslateY() const
    682 #In Property
    683 #Line # returns vertical translation ##
    684 #Populate
    685 
    686 #Example
    687 SkMatrix matrix;
    688 matrix.setTranslate(42, 24);
    689 SkDebugf("matrix.getTranslateY() %c= 24\n", matrix.getTranslateY() == 24 ? '=' : '!');
    690 #StdOut
    691 matrix.getTranslateY() == 24
    692 ##
    693 ##
    694 
    695 #SeeAlso get getTranslateX setTranslateY setTranslate
    696 
    697 ##
    698 
    699 # ------------------------------------------------------------------------------
    700 
    701 #Method SkScalar getPerspX() const
    702 #In Property
    703 #Line # returns input x perspective factor ##
    704 #Populate
    705 
    706 #Example
    707     SkMatrix m;
    708     m.setIdentity();
    709     m.set(SkMatrix::kMPersp0, -0.004f);
    710     SkAutoCanvasRestore autoRestore(canvas, true);
    711     canvas->translate(22, 144);
    712     SkPaint black;
    713     black.setAntiAlias(true);
    714     black.setTextSize(24);
    715     SkPaint gray = black;
    716     gray.setColor(0xFF9f9f9f);
    717     SkString string;
    718     string.appendScalar(m.getPerspX());
    719     canvas->drawString(string, 0, -72, gray);
    720     canvas->concat(m);
    721     canvas->drawString(string, 0, 0, black);
    722 ##
    723 
    724 #SeeAlso kMPersp0 getPerspY
    725 
    726 ##
    727 
    728 # ------------------------------------------------------------------------------
    729 
    730 #Method SkScalar getPerspY() const
    731 #In Property
    732 #Line # returns input y perspective factor ##
    733 #Populate
    734 
    735 #Example
    736     SkMatrix m;
    737     m.setIdentity();
    738     m.set(SkMatrix::kMPersp1, -0.004f);
    739     SkAutoCanvasRestore autoRestore(canvas, true);
    740     canvas->translate(22, 144);
    741     SkPaint black;
    742     black.setAntiAlias(true);
    743     black.setTextSize(24);
    744     SkPaint gray = black;
    745     gray.setColor(0xFF9f9f9f);
    746     SkString string;
    747     string.appendScalar(m.getPerspY());
    748     canvas->drawString(string, 0, -72, gray);
    749     canvas->concat(m);
    750     canvas->drawString(string, 0, 0, black);
    751 ##
    752 
    753 #SeeAlso kMPersp1 getPerspX
    754 
    755 ##
    756 
    757 # ------------------------------------------------------------------------------
    758 
    759 #Method SkScalar& operator[](int index)
    760 
    761 #Line # returns writable reference to Matrix value ##
    762 #Populate
    763 
    764 #Example
    765 SkMatrix matrix;
    766 matrix.setIdentity();
    767 SkDebugf("with identity matrix: x = %g\n", matrix.mapXY(24, 42).fX);
    768 SkScalar& skewRef = matrix[SkMatrix::kMSkewX];
    769 skewRef = 0;
    770 SkDebugf("after skew x mod:     x = %g\n", matrix.mapXY(24, 42).fX);
    771 skewRef = 1;
    772 SkDebugf("after 2nd skew x mod: x = %g\n", matrix.mapXY(24, 42).fX);
    773 matrix.dirtyMatrixTypeCache();
    774 SkDebugf("after dirty cache:    x = %g\n", matrix.mapXY(24, 42).fX);
    775 #StdOut
    776 with identity matrix: x = 24
    777 after skew x mod:     x = 24
    778 after 2nd skew x mod: x = 24
    779 after dirty cache:    x = 66
    780 ##
    781 ##
    782 
    783 #SeeAlso get dirtyMatrixTypeCache set
    784 
    785 ##
    786 
    787 # ------------------------------------------------------------------------------
    788 #Subtopic Set
    789 #Line # sets one or more matrix values ##
    790 ##
    791 
    792 #Method void set(int index, SkScalar value)
    793 #In Set
    794 #Line # sets one value ##
    795 #Populate
    796 
    797 #Example
    798 SkMatrix matrix;
    799 matrix.setIdentity();
    800 SkDebugf("with identity matrix: x = %g\n", matrix.mapXY(24, 42).fX);
    801 matrix.set(SkMatrix::kMSkewX, 0);
    802 SkDebugf("after skew x mod:     x = %g\n", matrix.mapXY(24, 42).fX);
    803 matrix.set(SkMatrix::kMSkewX, 1);
    804 SkDebugf("after 2nd skew x mod: x = %g\n", matrix.mapXY(24, 42).fX);
    805 #StdOut
    806 with identity matrix: x = 24
    807 after skew x mod:     x = 24
    808 after 2nd skew x mod: x = 66
    809 ##
    810 ##
    811 
    812 #SeeAlso operator[] get
    813 
    814 #Method ##
    815 
    816 # ------------------------------------------------------------------------------
    817 
    818 #Method void setScaleX(SkScalar v)
    819 #In Set
    820 #Line # sets horizontal scale factor ##
    821 #Populate
    822 
    823 #Example
    824 #Height 64
    825 SkPaint paint;
    826 paint.setAntiAlias(true);
    827 paint.setTextSize(24);
    828 canvas->drawString("normal", 12, 24, paint);
    829 SkMatrix matrix;
    830 matrix.setIdentity();
    831 matrix.setScaleX(3);
    832 canvas->concat(matrix);
    833 canvas->drawString("x scale", 0, 48, paint);
    834 ##
    835 
    836 #SeeAlso set setScale setScaleY
    837 
    838 #Method ##
    839 
    840 # ------------------------------------------------------------------------------
    841 
    842 #Method void setScaleY(SkScalar v)
    843 #In Set
    844 #Line # sets vertical scale factor ##
    845 #Populate
    846 
    847 #Example
    848 #Height 192
    849 SkPaint paint;
    850 paint.setAntiAlias(true);
    851 paint.setTextSize(24);
    852 canvas->drawString("normal", 12, 24, paint);
    853 SkMatrix matrix;
    854 matrix.setIdentity();
    855 matrix.setScaleY(3);
    856 canvas->concat(matrix);
    857 canvas->drawString("y scale", 12, 48, paint);
    858 ##
    859 
    860 #SeeAlso set setScale setScaleX
    861 
    862 #Method ##
    863 
    864 # ------------------------------------------------------------------------------
    865 
    866 #Method void setSkewY(SkScalar v)
    867 #In Set
    868 #Line # sets vertical skew factor ##
    869 #Populate
    870 
    871 #Example
    872 #Height 96
    873 SkPaint paint;
    874 paint.setAntiAlias(true);
    875 paint.setTextSize(24);
    876 canvas->drawString("normal", 12, 24, paint);
    877 SkMatrix matrix;
    878 matrix.setIdentity();
    879 matrix.setSkewY(.3f);
    880 canvas->concat(matrix);
    881 canvas->drawString("y skew", 12, 48, paint);
    882 ##
    883 
    884 #SeeAlso set setSkew setSkewX
    885 
    886 #Method ##
    887 
    888 # ------------------------------------------------------------------------------
    889 
    890 #Method void setSkewX(SkScalar v)
    891 #In Set
    892 #Line # sets horizontal skew factor ##
    893 #Populate
    894 
    895 #Example
    896 #Height 64
    897 SkPaint paint;
    898 paint.setAntiAlias(true);
    899 paint.setTextSize(24);
    900 canvas->drawString("normal", 12, 24, paint);
    901 SkMatrix matrix;
    902 matrix.setIdentity();
    903 matrix.setSkewX(-.7f);
    904 canvas->concat(matrix);
    905 canvas->drawString("x skew", 36, 48, paint);
    906 ##
    907 
    908 #SeeAlso set setSkew setSkewX
    909 
    910 #Method ##
    911 
    912 # ------------------------------------------------------------------------------
    913 
    914 #Method void setTranslateX(SkScalar v)
    915 #In Set
    916 #Line # sets horizontal translation ##
    917 #Populate
    918 
    919 #Example
    920 #Height 48
    921 SkPaint paint;
    922 paint.setAntiAlias(true);
    923 paint.setTextSize(24);
    924 canvas->drawString("normal", 8, 24, paint);
    925 SkMatrix matrix;
    926 matrix.setIdentity();
    927 matrix.setTranslateX(96);
    928 canvas->concat(matrix);
    929 canvas->drawString("x translate", 8, 24, paint);
    930 ##
    931 
    932 #SeeAlso set setTranslate setTranslateY
    933 
    934 #Method ##
    935 
    936 # ------------------------------------------------------------------------------
    937 
    938 #Method void setTranslateY(SkScalar v)
    939 #In Set
    940 #Line # sets vertical translation ##
    941 #Populate
    942 
    943 #Example
    944 #Height 64
    945 SkPaint paint;
    946 paint.setAntiAlias(true);
    947 paint.setTextSize(24);
    948 canvas->drawString("normal", 8, 24, paint);
    949 SkMatrix matrix;
    950 matrix.setIdentity();
    951 matrix.setTranslateY(24);
    952 canvas->concat(matrix);
    953 canvas->drawString("y translate", 8, 24, paint);
    954 ##
    955 
    956 #SeeAlso set setTranslate setTranslateX
    957 
    958 #Method ##
    959 
    960 # ------------------------------------------------------------------------------
    961 
    962 #Method void setPerspX(SkScalar v)
    963 #In Set
    964 #Line # sets input x perspective factor ##
    965 #Populate
    966 
    967 #Example
    968 #Image 4
    969 for (SkScalar perspX : { -.003f, 0.f, .003f, .012f } ) {
    970     SkMatrix matrix;
    971     matrix.setIdentity();
    972     matrix.setPerspX(perspX);
    973     canvas->save();
    974     canvas->concat(matrix);
    975     canvas->drawBitmap(source, 0, 0);
    976     canvas->restore();
    977     canvas->translate(64, 64);
    978 }
    979 ##
    980 
    981 #SeeAlso getPerspX set setAll set9 MakeAll
    982 
    983 #Method ##
    984 
    985 # ------------------------------------------------------------------------------
    986 
    987 #Method void setPerspY(SkScalar v)
    988 #In Set
    989 #Line # sets input y perspective factor ##
    990 #Populate
    991 
    992 #Example
    993 #Image 4
    994 for (SkScalar perspX : { -.003f, 0.f, .003f, .012f } ) {
    995     SkMatrix matrix;
    996     matrix.setIdentity();
    997     matrix.setPerspY(perspX);
    998     canvas->save();
    999     canvas->concat(matrix);
   1000     canvas->drawBitmap(source, 0, 0);
   1001     canvas->restore();
   1002     canvas->translate(64, 64);
   1003 }
   1004 ##
   1005 
   1006 #SeeAlso getPerspY set setAll set9 MakeAll
   1007 
   1008 #Method ##
   1009 
   1010 # ------------------------------------------------------------------------------
   1011 
   1012 #Method void setAll(SkScalar scaleX, SkScalar skewX,  SkScalar transX,
   1013                 SkScalar skewY,  SkScalar scaleY, SkScalar transY,
   1014                 SkScalar persp0, SkScalar persp1, SkScalar persp2)
   1015 #In Set
   1016 #Line # sets all values from parameters ##
   1017 #Populate
   1018 
   1019 #Example
   1020 #Height 128
   1021     SkPaint p;
   1022     p.setAntiAlias(true);
   1023     p.setTextSize(64);
   1024     SkMatrix m;
   1025     for (SkScalar sx : { -1, 1 } ) {
   1026         for (SkScalar sy : { -1, 1 } ) {
   1027             SkAutoCanvasRestore autoRestore(canvas, true);
   1028             m.setAll(sx, 1, 128,    0, sy, 64,   0, 0, 1);
   1029             canvas->concat(m);
   1030             canvas->drawString("K", 0, 0, p);
   1031         }
   1032     }
   1033 ##
   1034 
   1035 #SeeAlso set9 MakeAll
   1036 
   1037 #Method ##
   1038 
   1039 # ------------------------------------------------------------------------------
   1040 
   1041 #Method void get9(SkScalar buffer[9]) const
   1042 #In Property
   1043 #Line # returns all nine Matrix values ##
   1044 #Populate
   1045 
   1046 #Example
   1047 SkMatrix matrix = SkMatrix::MakeRectToRect({0, 0, 1, 1}, {3, 4, 7, 9},
   1048                                            SkMatrix::kFill_ScaleToFit);
   1049 SkScalar b[9];
   1050 matrix.get9(b);
   1051 SkDebugf("{%g, %g, %g},\n{%g, %g, %g},\n{%g, %g, %g}\n", b[0], b[1], b[2],
   1052          b[3], b[4], b[5], b[6], b[7], b[8]);
   1053 #StdOut
   1054 {4, 0, 3},
   1055 {0, 5, 4},
   1056 {0, 0, 1}
   1057 ##
   1058 ##
   1059 
   1060 #SeeAlso set9
   1061 
   1062 #Method ##
   1063 
   1064 # ------------------------------------------------------------------------------
   1065 
   1066 #Method void set9(const SkScalar buffer[9])
   1067 #In Set
   1068 #In Constructors
   1069 #Line # sets all values from Scalar array ##
   1070 #Populate
   1071 
   1072 #Example
   1073 #Image 4
   1074 SkMatrix m;
   1075 SkScalar buffer[9] = {4, 0, 3,    0, 5, 4,     0, 0, 1};
   1076 m.set9(buffer);
   1077 canvas->concat(m);
   1078 canvas->drawBitmap(source, 0, 0);
   1079 ##
   1080 
   1081 #SeeAlso setAll get9 MakeAll
   1082 
   1083 #Method ##
   1084 
   1085 # ------------------------------------------------------------------------------
   1086 
   1087 #Method void reset()
   1088 #In Constructors
   1089 #In Set
   1090 #Line # sets Matrix to identity ##
   1091 #Populate
   1092 
   1093 #Example
   1094 SkMatrix m;
   1095 m.reset();
   1096 SkDebugf("m.isIdentity(): %s\n", m.isIdentity() ? "true" : "false");
   1097 #StdOut
   1098 m.isIdentity(): true
   1099 ##
   1100 ##
   1101 
   1102 #SeeAlso isIdentity setIdentity
   1103 
   1104 #Method ##
   1105 
   1106 # ------------------------------------------------------------------------------
   1107 
   1108 #Method void setIdentity()
   1109 #In Constructors
   1110 #In Set
   1111 #Line # sets Matrix to identity ##
   1112 #Populate
   1113 
   1114 #Example
   1115 SkMatrix m;
   1116 m.setIdentity();
   1117 SkDebugf("m.isIdentity(): %s\n", m.isIdentity() ? "true" : "false");
   1118 #StdOut
   1119 m.isIdentity(): true
   1120 ##
   1121 ##
   1122 
   1123 #SeeAlso isIdentity reset
   1124 
   1125 #Method ##
   1126 
   1127 # ------------------------------------------------------------------------------
   1128 
   1129 #Method void setTranslate(SkScalar dx, SkScalar dy)
   1130 #In Constructors
   1131 #In Set
   1132 #Line # sets to translate on x-axis and y-axis ##
   1133 #Populate
   1134 
   1135 #Example
   1136 #Height 64
   1137 SkPaint paint;
   1138 paint.setAntiAlias(true);
   1139 paint.setTextSize(24);
   1140 canvas->drawString("normal", 8, 24, paint);
   1141 SkMatrix matrix;
   1142 matrix.setTranslate(96, 24);
   1143 canvas->concat(matrix);
   1144 canvas->drawString("translate", 8, 24, paint);
   1145 ##
   1146 
   1147 #SeeAlso setTranslateX setTranslateY
   1148 
   1149 #Method ##
   1150 
   1151 # ------------------------------------------------------------------------------
   1152 
   1153 #Method void setTranslate(const SkVector& v)
   1154 #Populate
   1155 
   1156 #Example
   1157 #Height 64
   1158 SkPaint paint;
   1159 paint.setAntiAlias(true);
   1160 paint.setTextSize(24);
   1161 canvas->drawString("normal", 8, 24, paint);
   1162 SkMatrix matrix;
   1163 matrix.setTranslate({96, 24});
   1164 canvas->concat(matrix);
   1165 canvas->drawString("translate", 8, 24, paint);
   1166 ##
   1167 
   1168 #SeeAlso setTranslateX setTranslateY MakeTrans
   1169 
   1170 #Method ##
   1171 
   1172 # ------------------------------------------------------------------------------
   1173 
   1174 #Method void setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py)
   1175 #In Constructors
   1176 #In Set
   1177 #Line # sets to scale about a point ##
   1178 #Populate
   1179 
   1180 #Example
   1181 #Height 128
   1182     SkPaint p;
   1183     p.setAntiAlias(true);
   1184     p.setTextSize(64);
   1185     SkMatrix m;
   1186     for (SkScalar sx : { -1, 1 } ) {
   1187         for (SkScalar sy : { -1, 1 } ) {
   1188             SkAutoCanvasRestore autoRestore(canvas, true);
   1189             m.setScale(sx, sy, 128, 64);
   1190             canvas->concat(m);
   1191             canvas->drawString("%", 128, 64, p);
   1192         }
   1193     }
   1194 ##
   1195 
   1196 #SeeAlso setScaleX setScaleY MakeScale preScale postScale
   1197 
   1198 #Method ##
   1199 
   1200 # ------------------------------------------------------------------------------
   1201 
   1202 #Method void setScale(SkScalar sx, SkScalar sy)
   1203 #Populate
   1204 
   1205 #Example
   1206 #Height 128
   1207     SkPaint p;
   1208     p.setAntiAlias(true);
   1209     p.setTextSize(64);
   1210     SkMatrix m;
   1211     for (SkScalar sx : { -1, 1 } ) {
   1212         for (SkScalar sy : { -1, 1 } ) {
   1213             SkAutoCanvasRestore autoRestore(canvas, true);
   1214             m.setScale(sx, sy);
   1215             m.postTranslate(128, 64);
   1216             canvas->concat(m);
   1217             canvas->drawString("@", 0, 0, p);
   1218         }
   1219     }
   1220 ##
   1221 
   1222 #SeeAlso setScaleX setScaleY MakeScale preScale postScale
   1223 
   1224 #Method ##
   1225 
   1226 # ------------------------------------------------------------------------------
   1227 
   1228 #Method void setRotate(SkScalar degrees, SkScalar px, SkScalar py)
   1229 #In Constructors
   1230 #In Set
   1231 #Line # sets to rotate about a point ##
   1232 #Populate
   1233 
   1234 #Example
   1235 #Height 128
   1236     SkPaint paint;
   1237     paint.setColor(SK_ColorGRAY);
   1238     paint.setAntiAlias(true);
   1239     SkRect rect = {20, 20, 100, 100};
   1240     canvas->drawRect(rect, paint);
   1241     paint.setColor(SK_ColorRED);
   1242     SkMatrix matrix;
   1243     matrix.setRotate(25, rect.centerX(), rect.centerY());
   1244     canvas->concat(matrix);
   1245     canvas->drawRect(rect, paint);
   1246 ##
   1247 
   1248 #SeeAlso setSinCos preRotate postRotate
   1249 
   1250 #Method ##
   1251 
   1252 # ------------------------------------------------------------------------------
   1253 
   1254 #Method void setRotate(SkScalar degrees)
   1255 #Populate
   1256 
   1257 #Example
   1258 #Height 128
   1259     SkPaint paint;
   1260     paint.setColor(SK_ColorGRAY);
   1261     paint.setAntiAlias(true);
   1262     SkRect rect = {20, 20, 100, 100};
   1263     canvas->drawRect(rect, paint);
   1264     paint.setColor(SK_ColorRED);
   1265     SkMatrix matrix;
   1266     matrix.setRotate(25);
   1267     canvas->translate(rect.centerX(), rect.centerY());
   1268     canvas->concat(matrix);
   1269     canvas->translate(-rect.centerX(), -rect.centerY());
   1270     canvas->drawRect(rect, paint);
   1271 ##
   1272 
   1273 #SeeAlso setSinCos preRotate postRotate
   1274 
   1275 #Method ##
   1276 
   1277 # ------------------------------------------------------------------------------
   1278 
   1279 #Method void setSinCos(SkScalar sinValue, SkScalar cosValue,
   1280                    SkScalar px, SkScalar py)
   1281 #In Constructors
   1282 #In Set
   1283 #Line # sets to rotate and scale about a point ##
   1284 #Populate
   1285 
   1286 #Example
   1287 #Height 128
   1288     SkPaint paint;
   1289     paint.setColor(SK_ColorGRAY);
   1290     paint.setAntiAlias(true);
   1291     SkRect rect = {20, 20, 100, 100};
   1292     canvas->drawRect(rect, paint);
   1293     paint.setColor(SK_ColorRED);
   1294     SkMatrix matrix;
   1295     matrix.setSinCos(.25f, .85f, rect.centerX(), rect.centerY());
   1296     canvas->concat(matrix);
   1297     canvas->drawRect(rect, paint);
   1298 ##
   1299 
   1300 #SeeAlso setRotate setScale setRSXform
   1301 
   1302 #Method ##
   1303 
   1304 # ------------------------------------------------------------------------------
   1305 
   1306 #Method void setSinCos(SkScalar sinValue, SkScalar cosValue)
   1307 #Populate
   1308 
   1309 #Example
   1310 #Description
   1311 Canvas needs offset after applying Matrix to pivot about Rect center.
   1312 ##
   1313 #Height 128
   1314     SkPaint paint;
   1315     paint.setColor(SK_ColorGRAY);
   1316     paint.setAntiAlias(true);
   1317     SkRect rect = {20, 20, 100, 100};
   1318     canvas->drawRect(rect, paint);
   1319     paint.setColor(SK_ColorRED);
   1320     SkMatrix matrix;
   1321     matrix.setSinCos(.25f, .85f);
   1322     matrix.postTranslate(rect.centerX(), rect.centerY());
   1323     canvas->concat(matrix);
   1324     canvas->translate(-rect.centerX(), -rect.centerY());
   1325     canvas->drawRect(rect, paint);
   1326 ##
   1327 
   1328 #SeeAlso setRotate setScale setRSXform
   1329 
   1330 #Method ##
   1331 
   1332 # ------------------------------------------------------------------------------
   1333 
   1334 #Method SkMatrix& setRSXform(const SkRSXform& rsxForm)
   1335 #In Constructors
   1336 #In Set
   1337 #Line # sets to rotate, scale, and translate ##
   1338 #Populate
   1339 
   1340 #Example
   1341 #Description
   1342 Canvas needs offset after applying Matrix to pivot about Rect center.
   1343 ##
   1344 #Height 128
   1345     SkPaint paint;
   1346     paint.setColor(SK_ColorGRAY);
   1347     paint.setAntiAlias(true);
   1348     SkRect rect = {20, 20, 100, 100};
   1349     canvas->drawRect(rect, paint);
   1350     paint.setColor(SK_ColorRED);
   1351     SkMatrix matrix;
   1352     matrix.setRSXform(SkRSXform::Make(.85f, .25f, rect.centerX(), rect.centerY()));
   1353     canvas->concat(matrix);
   1354     canvas->translate(-rect.centerX(), -rect.centerY());
   1355     canvas->drawRect(rect, paint);
   1356 ##
   1357 
   1358 #SeeAlso setSinCos setScale setTranslate
   1359 
   1360 #Method ##
   1361 
   1362 # ------------------------------------------------------------------------------
   1363 
   1364 #Method void setSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py)
   1365 #In Constructors
   1366 #In Set
   1367 #Line # sets to skew about a point ##
   1368 #Populate
   1369 
   1370 #Example
   1371     SkPaint p;
   1372     p.setAntiAlias(true);
   1373     p.setTextSize(48);
   1374     SkMatrix m;
   1375     for (SkScalar sx : { -1, 0, 1 } ) {
   1376         for (SkScalar sy : { -1, 0, 1 } ) {
   1377             SkAutoCanvasRestore autoRestore(canvas, true);
   1378             m.setSkew(sx, sy, 96 + 64 * sx, 128 + 48 * sy);
   1379             canvas->concat(m);
   1380             canvas->drawString("K", 96 + 64 * sx, 128 + 48 * sy, p);
   1381         }
   1382     }
   1383 ##
   1384 
   1385 #SeeAlso setSkewX setSkewY preSkew postSkew
   1386 
   1387 #Method ##
   1388 
   1389 # ------------------------------------------------------------------------------
   1390 
   1391 #Method void setSkew(SkScalar kx, SkScalar ky)
   1392 #Populate
   1393 
   1394 #Example
   1395     SkPaint p;
   1396     p.setAntiAlias(true);
   1397     p.setTextSize(48);
   1398     SkMatrix m;
   1399     for (SkScalar sx : { -1, 0, 1 } ) {
   1400         for (SkScalar sy : { -1, 0, 1 } ) {
   1401             SkAutoCanvasRestore autoRestore(canvas, true);
   1402             m.setSkew(sx, sy);
   1403             m.postTranslate(96 + 64 * sx, 128 + 48 * sy);
   1404             canvas->concat(m);
   1405             canvas->drawString("K", 0, 0, p);
   1406         }
   1407     }
   1408 ##
   1409 
   1410 #SeeAlso setSkewX setSkewY preSkew postSkew
   1411 
   1412 #Method ##
   1413 
   1414 # ------------------------------------------------------------------------------
   1415 
   1416 #Method void setConcat(const SkMatrix& a, const SkMatrix& b)
   1417 #In Constructors
   1418 #In Set
   1419 #Line # sets to Matrix parameter multiplied by Matrix parameter ##
   1420 #Populate
   1421 
   1422 #Example
   1423 #Image 3
   1424 #Description
   1425 setPolyToPoly creates perspective matrices, one the inverse of the other.
   1426 Multiplying the matrix by its inverse turns into an identity matrix.
   1427 ##
   1428 SkMatrix matrix, matrix2;
   1429 SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
   1430 SkRect::Make(source.bounds()).toQuad(bitmapBounds);
   1431 matrix.setPolyToPoly(bitmapBounds, perspect, 4);
   1432 matrix2.setPolyToPoly(perspect, bitmapBounds, 4);
   1433 matrix.setConcat(matrix, matrix2);
   1434 canvas->concat(matrix);
   1435 canvas->drawBitmap(source, 0, 0);
   1436 ##
   1437 
   1438 #SeeAlso Concat preConcat postConcat SkCanvas::concat
   1439 
   1440 #Method ##
   1441 
   1442 # ------------------------------------------------------------------------------
   1443 
   1444 #Method void preTranslate(SkScalar dx, SkScalar dy)
   1445 #In Set
   1446 #In Operators
   1447 #Line # pre-multiplies Matrix by translation ##
   1448 #Populate
   1449 
   1450 #Example
   1451 #Height 160
   1452     SkPaint paint;
   1453     paint.setAntiAlias(true);
   1454     SkRect rect = {20, 20, 100, 100};
   1455     for (int i = 0; i < 2; ++i ) {
   1456         SkMatrix matrix;
   1457         i == 0 ? matrix.reset(): matrix.setRotate(25, rect.centerX(), 320);
   1458         {
   1459             SkAutoCanvasRestore acr(canvas, true);
   1460             canvas->concat(matrix);
   1461             paint.setColor(SK_ColorGRAY);
   1462             canvas->drawRect(rect, paint);
   1463         }
   1464         paint.setColor(SK_ColorRED);
   1465         for (int j = 0; j < 2; ++j ) {
   1466             SkAutoCanvasRestore acr(canvas, true);
   1467             matrix.preTranslate(40, 40);
   1468             canvas->concat(matrix);
   1469             canvas->drawCircle(0, 0, 3, paint);
   1470         }
   1471     }
   1472 ##
   1473 
   1474 #SeeAlso postTranslate setTranslate MakeTrans
   1475 
   1476 #Method ##
   1477 
   1478 # ------------------------------------------------------------------------------
   1479 
   1480 #Method void preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py)
   1481 #In Set
   1482 #In Operators
   1483 #Line # pre-multiplies Matrix by scale ##
   1484 #Populate
   1485 
   1486 #Example
   1487 #Image 3
   1488 SkMatrix matrix;
   1489 SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
   1490 SkRect::Make(source.bounds()).toQuad(bitmapBounds);
   1491 matrix.setPolyToPoly(bitmapBounds, perspect, 4);
   1492 matrix.preScale(.75f, 1.5f, source.width() / 2, source.height() / 2);
   1493 canvas->concat(matrix);
   1494 canvas->drawBitmap(source, 0, 0);
   1495 ##
   1496 
   1497 #SeeAlso postScale setScale MakeScale
   1498 
   1499 #Method ##
   1500 
   1501 # ------------------------------------------------------------------------------
   1502 
   1503 #Method void preScale(SkScalar sx, SkScalar sy)
   1504 #In Set
   1505 #In Operators
   1506 #Populate
   1507 
   1508 #Example
   1509 #Image 3
   1510 SkMatrix matrix;
   1511 SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
   1512 SkRect::Make(source.bounds()).toQuad(bitmapBounds);
   1513 matrix.setPolyToPoly(bitmapBounds, perspect, 4);
   1514 matrix.preScale(.75f, 1.5f);
   1515 canvas->concat(matrix);
   1516 canvas->drawBitmap(source, 0, 0);
   1517 ##
   1518 
   1519 #SeeAlso postScale setScale MakeScale
   1520 
   1521 #Method ##
   1522 
   1523 # ------------------------------------------------------------------------------
   1524 
   1525 #Method void preRotate(SkScalar degrees, SkScalar px, SkScalar py)
   1526 #In Set
   1527 #In Operators
   1528 #Line # pre-multiplies Matrix by rotation ##
   1529 #Populate
   1530 
   1531 #Example
   1532 #Image 3
   1533 SkMatrix matrix;
   1534 SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
   1535 SkRect::Make(source.bounds()).toQuad(bitmapBounds);
   1536 matrix.setPolyToPoly(bitmapBounds, perspect, 4);
   1537 matrix.preRotate(45, source.width() / 2, source.height() / 2);
   1538 canvas->concat(matrix);
   1539 canvas->drawBitmap(source, 0, 0);
   1540 ##
   1541 
   1542 #SeeAlso postRotate setRotate
   1543 
   1544 #Method ##
   1545 
   1546 # ------------------------------------------------------------------------------
   1547 
   1548 #Method void preRotate(SkScalar degrees)
   1549 #Populate
   1550 
   1551 #Example
   1552 #Image 3
   1553 SkMatrix matrix;
   1554 SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
   1555 SkRect::Make(source.bounds()).toQuad(bitmapBounds);
   1556 matrix.setPolyToPoly(bitmapBounds, perspect, 4);
   1557 matrix.preRotate(45);
   1558 canvas->concat(matrix);
   1559 canvas->drawBitmap(source, 0, 0);
   1560 ##
   1561 
   1562 #SeeAlso postRotate setRotate
   1563 
   1564 #Method ##
   1565 
   1566 # ------------------------------------------------------------------------------
   1567 
   1568 #Method void preSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py)
   1569 #In Set
   1570 #In Operators
   1571 #Line # pre-multiplies Matrix by skew ##
   1572 #Populate
   1573 
   1574 #Example
   1575 #Image 3
   1576 SkMatrix matrix;
   1577 SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
   1578 SkRect::Make(source.bounds()).toQuad(bitmapBounds);
   1579 matrix.setPolyToPoly(bitmapBounds, perspect, 4);
   1580 matrix.preSkew(.5f, 0, source.width() / 2, source.height() / 2);
   1581 canvas->concat(matrix);
   1582 canvas->drawBitmap(source, 0, 0);
   1583 ##
   1584 
   1585 #SeeAlso postSkew setSkew
   1586 
   1587 #Method ##
   1588 
   1589 # ------------------------------------------------------------------------------
   1590 
   1591 #Method void preSkew(SkScalar kx, SkScalar ky)
   1592 #Populate
   1593 
   1594 #Example
   1595 #Image 3
   1596 SkMatrix matrix;
   1597 SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
   1598 SkRect::Make(source.bounds()).toQuad(bitmapBounds);
   1599 matrix.setPolyToPoly(bitmapBounds, perspect, 4);
   1600 matrix.preSkew(.5f, 0);
   1601 canvas->concat(matrix);
   1602 canvas->drawBitmap(source, 0, 0);
   1603 ##
   1604 
   1605 #SeeAlso postSkew setSkew
   1606 
   1607 #Method ##
   1608 
   1609 # ------------------------------------------------------------------------------
   1610 
   1611 #Method void preConcat(const SkMatrix& other)
   1612 #In Set
   1613 #In Operators
   1614 #Line # pre-multiplies Matrix by Matrix parameter ##
   1615 #Populate
   1616 
   1617 #Example
   1618 #Image 3
   1619 #Description
   1620 setPolyToPoly creates perspective matrices, one the inverse of the other.
   1621 Multiplying the matrix by its inverse turns into an identity matrix.
   1622 ##
   1623 SkMatrix matrix, matrix2;
   1624 SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
   1625 SkRect::Make(source.bounds()).toQuad(bitmapBounds);
   1626 matrix.setPolyToPoly(bitmapBounds, perspect, 4);
   1627 matrix2.setPolyToPoly(perspect, bitmapBounds, 4);
   1628 matrix.preConcat(matrix2);
   1629 canvas->concat(matrix);
   1630 canvas->drawBitmap(source, 0, 0);
   1631 ##
   1632 
   1633 #SeeAlso postConcat setConcat Concat
   1634 
   1635 #Method ##
   1636 
   1637 # ------------------------------------------------------------------------------
   1638 
   1639 #Method void postTranslate(SkScalar dx, SkScalar dy)
   1640 #In Set
   1641 #In Operators
   1642 #Line # post-multiplies Matrix by translation ##
   1643 #Populate
   1644 
   1645 #Example
   1646 #Height 160
   1647 #Description
   1648 Compare with preTranslate example.
   1649 ##
   1650     SkPaint paint;
   1651     paint.setAntiAlias(true);
   1652     SkRect rect = {20, 20, 100, 100};
   1653     for (int i = 0; i < 2; ++i ) {
   1654         SkMatrix matrix;
   1655         i == 0 ? matrix.reset(): matrix.setRotate(25, rect.centerX(), 320);
   1656         {
   1657             SkAutoCanvasRestore acr(canvas, true);
   1658             canvas->concat(matrix);
   1659             paint.setColor(SK_ColorGRAY);
   1660             canvas->drawRect(rect, paint);
   1661         }
   1662         paint.setColor(SK_ColorRED);
   1663         for (int j = 0; j < 2; ++j ) {
   1664             SkAutoCanvasRestore acr(canvas, true);
   1665             matrix.postTranslate(40, 40);
   1666             canvas->concat(matrix);
   1667             canvas->drawCircle(0, 0, 3, paint);
   1668         }
   1669     }
   1670 ##
   1671 
   1672 #SeeAlso preTranslate setTranslate MakeTrans
   1673 
   1674 #Method ##
   1675 
   1676 # ------------------------------------------------------------------------------
   1677 
   1678 #Method void postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py)
   1679 #In Set
   1680 #In Operators
   1681 #Line # post-multiplies Matrix by scale ##
   1682 #Populate
   1683 
   1684 #Example
   1685 #Image 3
   1686 SkMatrix matrix;
   1687 SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
   1688 SkRect::Make(source.bounds()).toQuad(bitmapBounds);
   1689 matrix.setPolyToPoly(bitmapBounds, perspect, 4);
   1690 matrix.postScale(.75f, 1.5f, source.width() / 2, source.height() / 2);
   1691 canvas->concat(matrix);
   1692 canvas->drawBitmap(source, 0, 0);
   1693 ##
   1694 
   1695 #SeeAlso preScale setScale MakeScale
   1696 
   1697 ##
   1698 
   1699 # ------------------------------------------------------------------------------
   1700 
   1701 #Method void postScale(SkScalar sx, SkScalar sy)
   1702 #Populate
   1703 
   1704 #Example
   1705 #Image 3
   1706 SkMatrix matrix;
   1707 SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
   1708 SkRect::Make(source.bounds()).toQuad(bitmapBounds);
   1709 matrix.setPolyToPoly(bitmapBounds, perspect, 4);
   1710 matrix.postScale(.75f, 1.5f);
   1711 canvas->concat(matrix);
   1712 canvas->drawBitmap(source, 0, 0);
   1713 ##
   1714 
   1715 #SeeAlso preScale setScale MakeScale
   1716 
   1717 ##
   1718 
   1719 # ------------------------------------------------------------------------------
   1720 
   1721 #Method bool postIDiv(int divx, int divy)
   1722 #In Set
   1723 #In Operators
   1724 #Line # post-multiplies Matrix by inverse scale ##
   1725 Sets Matrix to Matrix constructed from scaling by (1/divx, 1/divy),
   1726 multiplied by Matrix.
   1727 
   1728 Returns false if either divx or divy is zero.
   1729 
   1730 Given:
   1731 
   1732 #Code
   1733 #Literal
   1734          | J K L |                   | sx  0  0 |
   1735 Matrix = | M N O |,  I(divx, divy) = |  0 sy  0 |
   1736          | P Q R |                   |  0  0  1 |
   1737 ##
   1738 
   1739 where
   1740 
   1741 #Code
   1742 #Literal
   1743 sx = 1 / divx
   1744 sy = 1 / divy
   1745 ##
   1746 
   1747 sets Matrix to:
   1748 
   1749 #Code
   1750 #Literal
   1751                          | sx  0  0 | | J K L |   | sx*J sx*K sx*L |
   1752 I(divx, divy) * Matrix = |  0 sy  0 | | M N O | = | sy*M sy*N sy*O |
   1753                          |  0  0  1 | | P Q R |   |    P    Q    R |
   1754 ##
   1755 
   1756 #Param divx  integer divisor for inverse scale on x-axis ##
   1757 #Param divy  integer divisor for inverse scale on y-axis ##
   1758 
   1759 #Return  true on successful scale ##
   1760 
   1761 #Example
   1762 #Image 3
   1763 SkMatrix matrix;
   1764 SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
   1765 SkRect::Make(source.bounds()).toQuad(bitmapBounds);
   1766 matrix.setPolyToPoly(bitmapBounds, perspect, 4);
   1767 matrix.postIDiv(1, 2);
   1768 canvas->concat(matrix);
   1769 canvas->drawBitmap(source, 0, 0);
   1770 ##
   1771 
   1772 #SeeAlso postScale MakeScale
   1773 
   1774 ##
   1775 
   1776 # ------------------------------------------------------------------------------
   1777 
   1778 #Method void postRotate(SkScalar degrees, SkScalar px, SkScalar py)
   1779 #In Set
   1780 #In Operators
   1781 #Line # post-multiplies Matrix by rotation ##
   1782 #Populate
   1783 
   1784 #Example
   1785 #Image 3
   1786 SkMatrix matrix;
   1787 SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
   1788 SkRect::Make(source.bounds()).toQuad(bitmapBounds);
   1789 matrix.setPolyToPoly(bitmapBounds, perspect, 4);
   1790 matrix.postRotate(45, source.width() / 2, source.height() / 2);
   1791 canvas->concat(matrix);
   1792 canvas->drawBitmap(source, 0, 0);
   1793 ##
   1794 
   1795 #SeeAlso preRotate setRotate
   1796 
   1797 ##
   1798 
   1799 # ------------------------------------------------------------------------------
   1800 
   1801 #Method void postRotate(SkScalar degrees)
   1802 #Populate
   1803 
   1804 #Example
   1805 #Image 3
   1806 SkMatrix matrix;
   1807 SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
   1808 SkRect::Make(source.bounds()).toQuad(bitmapBounds);
   1809 matrix.setPolyToPoly(bitmapBounds, perspect, 4);
   1810 matrix.postRotate(45);
   1811 canvas->concat(matrix);
   1812 canvas->drawBitmap(source, 0, 0);
   1813 ##
   1814 
   1815 #SeeAlso preRotate setRotate
   1816 
   1817 ##
   1818 
   1819 # ------------------------------------------------------------------------------
   1820 
   1821 #Method void postSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py)
   1822 #In Set
   1823 #In Operators
   1824 #Line # post-multiplies Matrix by skew ##
   1825 #Populate
   1826 
   1827 #Example
   1828 #Image 3
   1829 SkMatrix matrix;
   1830 SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
   1831 SkRect::Make(source.bounds()).toQuad(bitmapBounds);
   1832 matrix.setPolyToPoly(bitmapBounds, perspect, 4);
   1833 matrix.postSkew(.5f, 0, source.width() / 2, source.height() / 2);
   1834 canvas->concat(matrix);
   1835 canvas->drawBitmap(source, 0, 0);
   1836 ##
   1837 
   1838 #SeeAlso preSkew setSkew
   1839 
   1840 ##
   1841 
   1842 # ------------------------------------------------------------------------------
   1843 
   1844 #Method void postSkew(SkScalar kx, SkScalar ky)
   1845 #Populate
   1846 
   1847 #Example
   1848 #Image 3
   1849 SkMatrix matrix;
   1850 SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
   1851 SkRect::Make(source.bounds()).toQuad(bitmapBounds);
   1852 matrix.setPolyToPoly(bitmapBounds, perspect, 4);
   1853 matrix.postSkew(.5f, 0);
   1854 canvas->concat(matrix);
   1855 canvas->drawBitmap(source, 0, 0);
   1856 ##
   1857 
   1858 #SeeAlso preSkew setSkew
   1859 
   1860 ##
   1861 
   1862 # ------------------------------------------------------------------------------
   1863 
   1864 #Method void postConcat(const SkMatrix& other)
   1865 #In Set
   1866 #In Operators
   1867 #Line # post-multiplies Matrix by Matrix parameter ##
   1868 #Populate
   1869 
   1870 #Example
   1871 #Image 3
   1872 #Height 64
   1873 SkMatrix matrix;
   1874 SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
   1875 SkRect::Make(source.bounds()).toQuad(bitmapBounds);
   1876 matrix.setPolyToPoly(bitmapBounds, perspect, 4);
   1877 matrix.postConcat(matrix);
   1878 canvas->concat(matrix);
   1879 canvas->drawBitmap(source, 0, 0);
   1880 ##
   1881 
   1882 #SeeAlso preConcat setConcat Concat
   1883 
   1884 ##
   1885 
   1886 # ------------------------------------------------------------------------------
   1887 
   1888 #Enum ScaleToFit
   1889 #Line # options to map Rects ##
   1890 #Code
   1891     enum ScaleToFit {
   1892         kFill_ScaleToFit,
   1893         kStart_ScaleToFit,
   1894         kCenter_ScaleToFit,
   1895         kEnd_ScaleToFit,
   1896     };
   1897 ##
   1898 
   1899 ScaleToFit describes how Matrix is constructed to map one Rect to another.
   1900 ScaleToFit may allow Matrix to have unequal horizontal and vertical scaling,
   1901 or may restrict Matrix to square scaling. If restricted, ScaleToFit specifies
   1902 how Matrix maps to the side or center of the destination Rect.
   1903 
   1904 #Const kFill_ScaleToFit 0
   1905 #Line # scales about x-axis and y-axis to fill destination Rect ##
   1906     Computes Matrix that scales about x-axis and y-axis independently, so that
   1907     source Rect is mapped to completely fill destination Rect. The aspect ratio
   1908     of source Rect may change.
   1909 ##
   1910 #Const kStart_ScaleToFit 1
   1911 #Line # scales and aligns to left and top ##
   1912     Computes Matrix that maintains source Rect aspect ratio, mapping source Rect
   1913     width or height to destination Rect. Aligns mapping to left and top edges
   1914     of destination Rect.
   1915 ##
   1916 #Const kCenter_ScaleToFit 2
   1917 #Line # scales and aligns to center ##
   1918     Computes Matrix that maintains source Rect aspect ratio, mapping source Rect
   1919     width or height to destination Rect. Aligns mapping to center of destination
   1920     Rect.
   1921 ##
   1922 #Const kEnd_ScaleToFit 3
   1923 #Line # scales and aligns to right and bottom ##
   1924     Computes Matrix that maintains source Rect aspect ratio, mapping source Rect
   1925     width or height to destination Rect. Aligns mapping to right and bottom
   1926     edges of destination Rect.
   1927 ##
   1928 
   1929 #Example
   1930    const char* labels[] = { "Fill", "Start", "Center", "End" };
   1931    SkRect rects[] = {{5, 5, 59, 59}, {5, 74, 59, 108}, {10, 123, 44, 172}, {10, 187, 54, 231}};
   1932    SkRect bounds;
   1933    source.getBounds(&bounds);
   1934    SkPaint paint;
   1935    paint.setAntiAlias(true);
   1936    for (auto fit : { SkMatrix::kFill_ScaleToFit, SkMatrix::kStart_ScaleToFit,
   1937                      SkMatrix::kCenter_ScaleToFit, SkMatrix::kEnd_ScaleToFit } ) {
   1938        for (auto rect : rects ) {
   1939            canvas->drawRect(rect, paint);
   1940            SkMatrix matrix;
   1941            if (!matrix.setRectToRect(bounds, rect, fit)) {
   1942                continue;
   1943            }
   1944            SkAutoCanvasRestore acr(canvas, true);
   1945            canvas->concat(matrix);
   1946            canvas->drawBitmap(source, 0, 0);
   1947        }
   1948        canvas->drawString(labels[fit], 10, 255, paint);
   1949        canvas->translate(64, 0);
   1950    }
   1951 ##
   1952 
   1953 #SeeAlso setRectToRect MakeRectToRect setPolyToPoly
   1954 
   1955 ##
   1956 
   1957 # ------------------------------------------------------------------------------
   1958 
   1959 #Method bool setRectToRect(const SkRect& src, const SkRect& dst, ScaleToFit stf)
   1960 #In Set
   1961 #Line # sets to map one Rect to another ##
   1962 #Populate
   1963 
   1964 #Example
   1965     const SkRect srcs[] = { {0, 0, 0, 0}, {1, 2, 3, 4} };
   1966     const SkRect dsts[] = { {0, 0, 0, 0}, {5, 6, 8, 9} };
   1967     for (auto src : srcs) {
   1968         for (auto dst : dsts) {
   1969              SkMatrix matrix;
   1970              matrix.setAll(-1, -1, -1, -1, -1, -1, -1, -1, -1);
   1971              bool success = matrix.setRectToRect(src, dst, SkMatrix::kFill_ScaleToFit);
   1972              SkDebugf("src: %g, %g, %g, %g  dst: %g, %g, %g, %g  success: %s\n",
   1973                       src.fLeft, src.fTop, src.fRight, src.fBottom,
   1974                       dst.fLeft, dst.fTop, dst.fRight, dst.fBottom, success ? "true" : "false");
   1975              matrix.dump();
   1976         }
   1977     }
   1978 #StdOut
   1979 src: 0, 0, 0, 0  dst: 0, 0, 0, 0  success: false
   1980 [  1.0000   0.0000   0.0000][  0.0000   1.0000   0.0000][  0.0000   0.0000   1.0000]
   1981 src: 0, 0, 0, 0  dst: 5, 6, 8, 9  success: false
   1982 [  1.0000   0.0000   0.0000][  0.0000   1.0000   0.0000][  0.0000   0.0000   1.0000]
   1983 src: 1, 2, 3, 4  dst: 0, 0, 0, 0  success: true
   1984 [  0.0000   0.0000   0.0000][  0.0000   0.0000   0.0000][  0.0000   0.0000   1.0000]
   1985 src: 1, 2, 3, 4  dst: 5, 6, 8, 9  success: true
   1986 [  1.5000   0.0000   3.5000][  0.0000   1.5000   3.0000][  0.0000   0.0000   1.0000]
   1987 ##
   1988 ##
   1989 
   1990 #SeeAlso MakeRectToRect ScaleToFit setPolyToPoly SkRect::isEmpty
   1991 
   1992 ##
   1993 
   1994 # ------------------------------------------------------------------------------
   1995 
   1996 #Method static SkMatrix MakeRectToRect(const SkRect& src, const SkRect& dst, ScaleToFit stf)
   1997 #In Constructors
   1998 #Line # constructs from source Rect to destination Rect ##
   1999 #Populate
   2000 
   2001 #Example
   2002     const SkRect srcs[] = { {0, 0, 0, 0}, {1, 2, 3, 4} };
   2003     const SkRect dsts[] = { {0, 0, 0, 0}, {5, 6, 8, 9} };
   2004     for (auto src : srcs) {
   2005         for (auto dst : dsts) {
   2006              SkMatrix matrix = SkMatrix::MakeRectToRect(src, dst, SkMatrix::kFill_ScaleToFit);
   2007              SkDebugf("src: %g, %g, %g, %g  dst: %g, %g, %g, %g\n",
   2008                       src.fLeft, src.fTop, src.fRight, src.fBottom,
   2009                       dst.fLeft, dst.fTop, dst.fRight, dst.fBottom);
   2010              matrix.dump();
   2011         }
   2012     }
   2013 #StdOut
   2014 src: 0, 0, 0, 0  dst: 0, 0, 0, 0
   2015 [  1.0000   0.0000   0.0000][  0.0000   1.0000   0.0000][  0.0000   0.0000   1.0000]
   2016 src: 0, 0, 0, 0  dst: 5, 6, 8, 9
   2017 [  1.0000   0.0000   0.0000][  0.0000   1.0000   0.0000][  0.0000   0.0000   1.0000]
   2018 src: 1, 2, 3, 4  dst: 0, 0, 0, 0
   2019 [  0.0000   0.0000   0.0000][  0.0000   0.0000   0.0000][  0.0000   0.0000   1.0000]
   2020 src: 1, 2, 3, 4  dst: 5, 6, 8, 9
   2021 [  1.5000   0.0000   3.5000][  0.0000   1.5000   3.0000][  0.0000   0.0000   1.0000]
   2022 ##
   2023 ##
   2024 
   2025 #SeeAlso setRectToRect ScaleToFit setPolyToPoly SkRect::isEmpty
   2026 
   2027 ##
   2028 
   2029 # ------------------------------------------------------------------------------
   2030 
   2031 #Method bool setPolyToPoly(const SkPoint src[], const SkPoint dst[], int count)
   2032 #In Set
   2033 #Line # sets to map one to four points to an equal array of points ##
   2034 #Populate
   2035 
   2036 #Example
   2037     const SkPoint src[] = { { 0, 0}, {30,   0}, {30, -30}, { 0, -30} };
   2038     const SkPoint dst[] = { {50, 0}, {80, -10}, {90, -30}, {60, -40} };
   2039     SkPaint blackPaint;
   2040     blackPaint.setAntiAlias(true);
   2041     blackPaint.setTextSize(42);
   2042     SkPaint redPaint = blackPaint;
   2043     redPaint.setColor(SK_ColorRED);
   2044     for (int count : { 1, 2, 3, 4 } ) {
   2045         canvas->translate(35, 55);
   2046         for (int index = 0; index < count; ++index) {
   2047             canvas->drawCircle(src[index], 3, blackPaint);
   2048             canvas->drawCircle(dst[index], 3, blackPaint);
   2049             if (index > 0) {
   2050                 canvas->drawLine(src[index], src[index - 1], blackPaint);
   2051                 canvas->drawLine(dst[index], dst[index - 1], blackPaint);
   2052             }
   2053         }
   2054         SkMatrix matrix;
   2055         matrix.setPolyToPoly(src, dst, count);
   2056         canvas->drawString("A", src[0].fX, src[0].fY, redPaint);
   2057         SkAutoCanvasRestore acr(canvas, true);
   2058         canvas->concat(matrix);
   2059         canvas->drawString("A", src[0].fX, src[0].fY, redPaint);
   2060     }
   2061 ##
   2062 
   2063 #SeeAlso setRectToRect MakeRectToRect
   2064 
   2065 ##
   2066 
   2067 # ------------------------------------------------------------------------------
   2068 
   2069 #Method bool invert(SkMatrix* inverse) const
   2070 #In Operators
   2071 #Line # returns inverse, if possible ##
   2072 #Populate
   2073 
   2074 #Example
   2075 #Height 128
   2076     const SkPoint src[] = { { 10, 120}, {120, 120}, {120, 10}, {  10, 10} };
   2077     const SkPoint dst[] = { {150, 120}, {200, 100}, {240, 30}, { 130, 40} };
   2078     SkPaint paint;
   2079     paint.setAntiAlias(true);
   2080     SkMatrix matrix;
   2081     matrix.setPolyToPoly(src, dst, 4);
   2082     canvas->drawPoints(SkCanvas::kPolygon_PointMode, 4, src, paint);
   2083     canvas->drawPoints(SkCanvas::kPolygon_PointMode, 4, dst, paint);
   2084     paint.setColor(SK_ColorBLUE);
   2085     paint.setStrokeWidth(3);
   2086     paint.setStrokeCap(SkPaint::kRound_Cap);
   2087     canvas->drawPoints(SkCanvas::kPoints_PointMode, 4, dst, paint);
   2088     if (matrix.invert(&matrix)) {
   2089         canvas->concat(matrix);
   2090         canvas->drawPoints(SkCanvas::kPoints_PointMode, 4, dst, paint);
   2091     }
   2092 ##
   2093 
   2094 #SeeAlso Concat
   2095 
   2096 ##
   2097 
   2098 # ------------------------------------------------------------------------------
   2099 
   2100 #Method static void SetAffineIdentity(SkScalar affine[6])
   2101 #In Constructors
   2102 #Line # sets 3x2 array to identity ##
   2103 #Populate
   2104 
   2105 #Example
   2106     SkScalar affine[6];
   2107     SkMatrix::SetAffineIdentity(affine);
   2108     const char* names[] = { "ScaleX", "SkewY", "SkewX", "ScaleY", "TransX", "TransY" };
   2109     for (int i = 0; i < 6; ++i) {
   2110         SkDebugf("%s: %g ", names[i], affine[i]);
   2111     }
   2112     SkDebugf("\n");
   2113 #StdOut
   2114 ScaleX: 1 SkewY: 0 SkewX: 0 ScaleY: 1 TransX: 0 TransY: 0
   2115 ##
   2116 ##
   2117 
   2118 #SeeAlso setAffine asAffine
   2119 
   2120 ##
   2121 
   2122 # ------------------------------------------------------------------------------
   2123 
   2124 #Method bool asAffine(SkScalar affine[6]) const
   2125 #In Constructors
   2126 #Line # copies to 3x2 array ##
   2127 #Populate
   2128 
   2129 #Example
   2130 SkMatrix matrix;
   2131 matrix.setAll(2, 3, 4, 5, 6, 7, 0, 0, 1);
   2132 SkScalar affine[6];
   2133 if (matrix.asAffine(affine)) {
   2134     const char* names[] = { "ScaleX", "SkewY", "SkewX", "ScaleY", "TransX", "TransY" };
   2135     for (int i = 0; i < 6; ++i) {
   2136         SkDebugf("%s: %g ", names[i], affine[i]);
   2137     }
   2138     SkDebugf("\n");
   2139 }
   2140 #StdOut
   2141 ScaleX: 2 SkewY: 5 SkewX: 3 ScaleY: 6 TransX: 4 TransY: 7
   2142 ##
   2143 ##
   2144 
   2145 #SeeAlso setAffine SetAffineIdentity
   2146 
   2147 ##
   2148 
   2149 # ------------------------------------------------------------------------------
   2150 
   2151 #Method void setAffine(const SkScalar affine[6])
   2152 #In Constructors
   2153 #In Set
   2154 #Line # sets left two columns ##
   2155 #Populate
   2156 
   2157 #Example
   2158 SkMatrix matrix;
   2159 matrix.setAll(2, 3, 4, 5, 6, 7, 0, 0, 1);
   2160 SkScalar affine[6];
   2161 if (matrix.asAffine(affine)) {
   2162     const char* names[] = { "ScaleX", "SkewY", "SkewX", "ScaleY", "TransX", "TransY" };
   2163     for (int i = 0; i < 6; ++i) {
   2164         SkDebugf("%s: %g ", names[i], affine[i]);
   2165     }
   2166     SkDebugf("\n");
   2167     matrix.reset();
   2168     matrix.setAffine(affine);
   2169     matrix.dump();
   2170 }
   2171 #StdOut
   2172 ScaleX: 2 SkewY: 5 SkewX: 3 ScaleY: 6 TransX: 4 TransY: 7
   2173 [  2.0000   3.0000   4.0000][  5.0000   6.0000   7.0000][  0.0000   0.0000   1.0000]
   2174 ##
   2175 ##
   2176 
   2177 #SeeAlso asAffine SetAffineIdentity
   2178 
   2179 ##
   2180 
   2181 # ------------------------------------------------------------------------------
   2182 #Subtopic Transform
   2183 #Line # map points with Matrix ##
   2184 ##
   2185 
   2186 #Method void mapPoints(SkPoint dst[], const SkPoint src[], int count) const
   2187 #In Transform
   2188 #Line # maps Point array ##
   2189 #Populate
   2190 
   2191 #Example
   2192     SkMatrix matrix;
   2193     matrix.reset();
   2194     const int count = 4;
   2195     SkPoint src[count];
   2196     matrix.mapRectToQuad(src, {40, 70, 180, 220} );
   2197     SkPaint paint;
   2198     paint.setARGB(77, 23, 99, 154);
   2199     for (int i = 0; i < 5; ++i) {
   2200         SkPoint dst[count];
   2201         matrix.mapPoints(dst, src, count);
   2202         canvas->drawPoints(SkCanvas::kPolygon_PointMode, count, dst, paint);
   2203         matrix.preRotate(35, 128, 128);
   2204     }
   2205 ##
   2206 
   2207 #SeeAlso mapXY mapHomogeneousPoints mapVectors
   2208 
   2209 ##
   2210 
   2211 # ------------------------------------------------------------------------------
   2212 
   2213 #Method void mapPoints(SkPoint pts[], int count) const
   2214 #Populate
   2215 
   2216 #Example
   2217     SkMatrix matrix;
   2218     matrix.setRotate(35, 128, 128);
   2219     const int count = 4;
   2220     SkPoint pts[count];
   2221     matrix.mapRectToQuad(pts, {40, 70, 180, 220} );
   2222     SkPaint paint;
   2223     paint.setARGB(77, 23, 99, 154);
   2224     for (int i = 0; i < 5; ++i) {
   2225         canvas->drawPoints(SkCanvas::kPolygon_PointMode, count, pts, paint);
   2226         matrix.mapPoints(pts, count);
   2227     }
   2228 ##
   2229 
   2230 #SeeAlso mapXY mapHomogeneousPoints mapVectors
   2231 
   2232 ##
   2233 
   2234 # ------------------------------------------------------------------------------
   2235 
   2236 #Method void mapHomogeneousPoints(SkPoint3 dst[], const SkPoint3 src[], int count) const
   2237 #In Transform
   2238 #Line # maps Point3 array ##
   2239 #Populate
   2240 
   2241 #Example
   2242     SkPoint3 src[] = {{3, 3, 1}, {8, 2, 2}, {5, 0, 4}, {0, 1, 3},
   2243                       {3, 7, 1}, {8, 6, 2}, {5, 4, 4}, {0, 5, 3}};
   2244     int lines[] = { 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7 };
   2245     constexpr int count = SK_ARRAY_COUNT(src);
   2246     auto debugster = [=](SkPoint3 src[]) -> void {
   2247     for (size_t i = 0; i < SK_ARRAY_COUNT(lines); i += 2) {
   2248         const SkPoint3& s = src[lines[i]];
   2249         const SkPoint3& e = src[lines[i + 1]];
   2250         SkPaint paint;
   2251         paint.setARGB(77, 23, 99, 154);
   2252         canvas->drawLine(s.fX / s.fZ, s.fY / s.fZ, e.fX / e.fZ, e.fY / e.fZ, paint);
   2253     }
   2254     };
   2255     canvas->save();
   2256     canvas->translate(5, 5);
   2257     canvas->scale(15, 15);
   2258     debugster(src);
   2259     canvas->restore();
   2260     canvas->translate(128, 128);
   2261     SkMatrix matrix;
   2262     matrix.setAll(15, 0, 0, 0, 15, 0, -0.08, 0.04, 1);
   2263     matrix.mapHomogeneousPoints(src, src, count);
   2264     debugster(src);
   2265 ##
   2266 
   2267 #SeeAlso mapPoints mapXY mapVectors
   2268 
   2269 ##
   2270 
   2271 # ------------------------------------------------------------------------------
   2272 
   2273 #Method void mapXY(SkScalar x, SkScalar y, SkPoint* result) const
   2274 #In Transform
   2275 #Line # maps Point ##
   2276 #Populate
   2277 
   2278 #Example
   2279     SkPaint paint;
   2280     paint.setAntiAlias(true);
   2281     SkMatrix matrix;
   2282     matrix.setRotate(60, 128, 128);
   2283     SkPoint lines[] = {{50, 50}, {150, 50}, {150, 150}};
   2284     for (size_t i = 0; i < SK_ARRAY_COUNT(lines); ++i) {
   2285         SkPoint pt;
   2286         matrix.mapXY(lines[i].fX, lines[i].fY, &pt);
   2287         canvas->drawCircle(pt.fX, pt.fY, 3, paint);
   2288     }
   2289     canvas->concat(matrix);
   2290     canvas->drawPoints(SkCanvas::kPolygon_PointMode, SK_ARRAY_COUNT(lines), lines, paint);
   2291 ##
   2292 
   2293 #SeeAlso mapPoints mapVectors
   2294 
   2295 ##
   2296 
   2297 # ------------------------------------------------------------------------------
   2298 
   2299 #Method SkPoint mapXY(SkScalar x, SkScalar y) const
   2300 #Populate
   2301 
   2302 #Example
   2303 #Image 4
   2304 SkMatrix matrix;
   2305 SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {30, 206}};
   2306 SkRect::Make(source.bounds()).toQuad(bitmapBounds);
   2307 matrix.setPolyToPoly(bitmapBounds, perspect, 4);
   2308 SkPaint paint;
   2309 paint.setAntiAlias(true);
   2310 paint.setStrokeWidth(3);
   2311 for (int x : { 0, source.width() } ) {
   2312     for (int y : { 0, source.height() } ) {
   2313         canvas->drawPoint(matrix.mapXY(x, y), paint);
   2314     }
   2315 }
   2316 canvas->concat(matrix);
   2317 canvas->drawBitmap(source, 0, 0);
   2318 ##
   2319 
   2320 #SeeAlso mapPoints mapVectors
   2321 
   2322 ##
   2323 
   2324 # ------------------------------------------------------------------------------
   2325 
   2326 #Method void mapVectors(SkVector dst[], const SkVector src[], int count) const
   2327 #In Transform
   2328 #Line # maps Vector array ##
   2329 #Populate
   2330 
   2331 #Example
   2332     SkPaint paint;
   2333     paint.setAntiAlias(true);
   2334     paint.setStyle(SkPaint::kStroke_Style);
   2335     SkMatrix matrix;
   2336     matrix.reset();
   2337     const SkVector radii[] = {{8, 4}, {9, 1}, {6, 2}, {7, 3}};
   2338     for (int i = 0; i < 4; ++i) {
   2339         SkVector rScaled[4];
   2340         matrix.preScale(1.5f, 2.f);
   2341         matrix.mapVectors(rScaled, radii, SK_ARRAY_COUNT(radii));
   2342         SkRRect rrect;
   2343         rrect.setRectRadii({20, 20, 180, 70}, rScaled);
   2344         canvas->drawRRect(rrect, paint);
   2345         canvas->translate(0, 60);
   2346     }
   2347 ##
   2348 
   2349 #SeeAlso mapVector mapPoints mapXY
   2350 
   2351 ##
   2352 
   2353 # ------------------------------------------------------------------------------
   2354 
   2355 #Method void mapVectors(SkVector vecs[], int count) const
   2356 #Populate
   2357 
   2358 #Example
   2359     SkPaint paint;
   2360     paint.setAntiAlias(true);
   2361     paint.setStyle(SkPaint::kStroke_Style);
   2362     SkMatrix matrix;
   2363     matrix.setScale(2, 3);
   2364     SkVector radii[] = {{7, 7}, {3, 3}, {2, 2}, {4, 0}};
   2365     for (int i = 0; i < 4; ++i) {
   2366         SkRRect rrect;
   2367         rrect.setRectRadii({20, 20, 180, 70}, radii);
   2368         canvas->drawRRect(rrect, paint);
   2369         canvas->translate(0, 60);
   2370         matrix.mapVectors(radii, SK_ARRAY_COUNT(radii));
   2371     }
   2372 ##
   2373 
   2374 #SeeAlso mapVector mapPoints mapXY
   2375 
   2376 ##
   2377 
   2378 # ------------------------------------------------------------------------------
   2379 
   2380 #Method void mapVector(SkScalar dx, SkScalar dy, SkVector* result) const
   2381 #In Transform
   2382 #Line # maps Vector ##
   2383 #Populate
   2384 
   2385 #Example
   2386     SkPaint paint;
   2387     paint.setColor(SK_ColorGREEN);
   2388     paint.setAntiAlias(true);
   2389     paint.setTextSize(48);
   2390     SkMatrix matrix;
   2391     matrix.setRotate(90);
   2392     SkVector offset = { 7, 7 };
   2393     for (int i = 0; i < 4; ++i) {
   2394         paint.setImageFilter(SkDropShadowImageFilter::Make(offset.fX, offset.fY, 3, 3,
   2395               SK_ColorBLUE, SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMode, nullptr));
   2396         matrix.mapVector(offset.fX, offset.fY, &offset);
   2397         canvas->translate(0, 60);
   2398         canvas->drawString("Text", 50, 0, paint);
   2399     }
   2400 ##
   2401 
   2402 #SeeAlso mapVectors mapPoints mapXY
   2403 
   2404 ##
   2405 
   2406 # ------------------------------------------------------------------------------
   2407 
   2408 #Method SkVector mapVector(SkScalar dx, SkScalar dy) const
   2409 #Populate
   2410 
   2411 #Example
   2412     SkPaint paint;
   2413     paint.setColor(SK_ColorGREEN);
   2414     paint.setAntiAlias(true);
   2415     paint.setTextSize(48);
   2416     SkMatrix matrix;
   2417     matrix.setRotate(90);
   2418     SkVector offset = { 7, 7 };
   2419     for (int i = 0; i < 4; ++i) {
   2420         paint.setImageFilter(SkDropShadowImageFilter::Make(offset.fX, offset.fY, 3, 3,
   2421               SK_ColorBLUE, SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMode, nullptr));
   2422         offset = matrix.mapVector(offset.fX, offset.fY);
   2423         canvas->translate(0, 60);
   2424         canvas->drawString("Text", 50, 0, paint);
   2425     }
   2426 ##
   2427 
   2428 #SeeAlso mapVectors mapPoints mapXY
   2429 
   2430 ##
   2431 
   2432 # ------------------------------------------------------------------------------
   2433 
   2434 #Method bool mapRect(SkRect* dst, const SkRect& src) const
   2435 #In Transform
   2436 #Line # returns bounds of mapped Rect ##
   2437 #Populate
   2438 
   2439 #Example
   2440     SkPaint paint;
   2441     paint.setAntiAlias(true);
   2442     SkMatrix matrix;
   2443     matrix.setRotate(45, 128, 128);
   2444     SkRect rotatedBounds, bounds = {40, 50, 190, 200};
   2445     matrix.mapRect(&rotatedBounds, bounds );
   2446     paint.setColor(SK_ColorGRAY);
   2447     canvas->drawRect(rotatedBounds, paint);
   2448     canvas->concat(matrix);
   2449     paint.setColor(SK_ColorRED);
   2450     canvas->drawRect(bounds, paint);
   2451 ##
   2452 
   2453 #SeeAlso mapPoints rectStaysRect
   2454 
   2455 ##
   2456 
   2457 # ------------------------------------------------------------------------------
   2458 
   2459 #Method bool mapRect(SkRect* rect) const
   2460 #Populate
   2461 
   2462 #Example
   2463     SkPaint paint;
   2464     paint.setAntiAlias(true);
   2465     SkMatrix matrix;
   2466     matrix.setRotate(45, 128, 128);
   2467     SkRect bounds = {40, 50, 190, 200};
   2468     matrix.mapRect(&bounds);
   2469     paint.setColor(SK_ColorGRAY);
   2470     canvas->drawRect(bounds, paint);
   2471     canvas->concat(matrix);
   2472     paint.setColor(SK_ColorRED);
   2473     canvas->drawRect({40, 50, 190, 200}, paint);
   2474 ##
   2475 
   2476 #SeeAlso mapRectScaleTranslate mapPoints rectStaysRect
   2477 
   2478 ##
   2479 
   2480 # ------------------------------------------------------------------------------
   2481 
   2482 #Method SkRect mapRect(const SkRect& src) const
   2483 #Populate
   2484 
   2485 #Example
   2486   SkRect rect{110, 50, 180, 100};
   2487   SkMatrix matrix;
   2488   matrix.setRotate(50, 28, 28);
   2489   SkRect mapped = matrix.mapRect(rect);
   2490   SkPaint paint;
   2491   paint.setAntiAlias(true);
   2492   paint.setStyle(SkPaint::kStroke_Style);
   2493   canvas->drawRect(rect, paint);
   2494   canvas->drawRect(mapped, paint);
   2495   canvas->concat(matrix);
   2496   canvas->drawRect(rect, paint);
   2497 ##
   2498 
   2499 #SeeAlso mapRectToQuad mapRectScaleTranslate
   2500 #Method ##
   2501 
   2502 # ------------------------------------------------------------------------------
   2503 
   2504 #Method void mapRectToQuad(SkPoint dst[4], const SkRect& rect) const
   2505 #In Transform
   2506 #Line # maps Rect to Point array ##
   2507 #Populate
   2508 
   2509 #Example
   2510 #Height 192
   2511     SkPaint paint;
   2512     paint.setAntiAlias(true);
   2513     SkMatrix matrix;
   2514     matrix.setRotate(60, 128, 128);
   2515     SkRect rect = {50, 50, 150, 150};
   2516     SkPoint pts[4];
   2517     matrix.mapRectToQuad(pts, rect);
   2518     for (int i = 0; i < 4; ++i) {
   2519         canvas->drawCircle(pts[i].fX, pts[i].fY, 3, paint);
   2520     }
   2521     canvas->concat(matrix);
   2522     paint.setStyle(SkPaint::kStroke_Style);
   2523     canvas->drawRect(rect, paint);
   2524 ##
   2525 
   2526 #SeeAlso mapRect mapRectScaleTranslate
   2527 
   2528 ##
   2529 
   2530 # ------------------------------------------------------------------------------
   2531 
   2532 #Method void mapRectScaleTranslate(SkRect* dst, const SkRect& src) const
   2533 #In Transform
   2534 #Line # returns bounds of mapped Rect ##
   2535 #Populate
   2536 
   2537 #Example
   2538     SkPaint paint;
   2539     SkMatrix matrix;
   2540     SkRect rect = {100, 50, 150, 180};
   2541     matrix.setScale(2, .5f, rect.centerX(), rect.centerY());
   2542     SkRect rotated;
   2543     matrix.mapRectScaleTranslate(&rotated, rect);
   2544     paint.setStyle(SkPaint::kStroke_Style);
   2545     canvas->drawRect(rect, paint);
   2546     paint.setColor(SK_ColorRED);
   2547     canvas->drawRect(rotated, paint);
   2548 ##
   2549 
   2550 #SeeAlso mapRect mapRectToQuad isScaleTranslate rectStaysRect
   2551 
   2552 ##
   2553 
   2554 # ------------------------------------------------------------------------------
   2555 
   2556 #Method SkScalar mapRadius(SkScalar radius) const
   2557 #In Transform
   2558 #Line # returns mean radius of mapped Circle ##
   2559 #Populate
   2560 
   2561 #Example
   2562 #Description
   2563 The area enclosed by a square with sides equal to mappedRadius is the same as
   2564 the area enclosed by the ellipse major and minor axes.
   2565 ##
   2566   SkPaint paint;
   2567   paint.setAntiAlias(true);
   2568   SkMatrix matrix;
   2569   const SkPoint center = {108, 93};
   2570   matrix.setScale(2, .5f, center.fX, center.fY);
   2571   matrix.postRotate(45, center.fX, center.fY);
   2572   const SkScalar circleRadius = 50;
   2573   SkScalar mappedRadius = matrix.mapRadius(circleRadius);
   2574   SkVector minorAxis, majorAxis;
   2575   matrix.mapVector(0, circleRadius, &minorAxis);
   2576   matrix.mapVector(circleRadius, 0, &majorAxis);
   2577   SkString mappedArea;
   2578   mappedArea.printf("area = %g", mappedRadius * mappedRadius);
   2579   canvas->drawString(mappedArea, 145, 250, paint);
   2580   canvas->drawString("mappedRadius", center.fX + mappedRadius + 3, center.fY, paint);
   2581   paint.setColor(SK_ColorRED);
   2582   SkString axArea;
   2583   axArea.printf("area = %g", majorAxis.length() * minorAxis.length());
   2584   paint.setStyle(SkPaint::kFill_Style);
   2585   canvas->drawString(axArea, 15, 250, paint);
   2586   paint.setStyle(SkPaint::kStroke_Style);
   2587   canvas->drawRect({10, 200, 10 + majorAxis.length(), 200 + minorAxis.length()}, paint);
   2588   paint.setColor(SK_ColorBLACK);
   2589   canvas->drawLine(center.fX, center.fY, center.fX + mappedRadius, center.fY, paint);
   2590   canvas->drawLine(center.fX, center.fY, center.fX, center.fY + mappedRadius, paint);
   2591   canvas->drawRect({140, 180, 140 + mappedRadius, 180 + mappedRadius}, paint);
   2592   canvas->concat(matrix);
   2593   canvas->drawCircle(center.fX, center.fY, circleRadius, paint);
   2594   paint.setColor(SK_ColorRED);
   2595   canvas->drawLine(center.fX, center.fY, center.fX + circleRadius, center.fY, paint);
   2596   canvas->drawLine(center.fX, center.fY, center.fX, center.fY + circleRadius, paint);
   2597 ##
   2598 
   2599 #SeeAlso mapVector
   2600 
   2601 ##
   2602 
   2603 # ------------------------------------------------------------------------------
   2604 #Method bool isFixedStepInX() const
   2605 #In Property
   2606 #Line # returns if transformation supports fixed step on x-axis ##
   2607 #Populate
   2608 
   2609 #Example
   2610     SkMatrix matrix;
   2611     for (SkScalar px : { 0.0f, 0.1f } ) {
   2612         for (SkScalar py : { 0.0f, 0.1f } ) {
   2613             for (SkScalar sy : { 1, 2 } ) {
   2614                 matrix.setAll(1, 0, 0,   0, sy, 0,   px, py, 1);
   2615                 matrix.dump();
   2616                 SkDebugf("isFixedStepInX: %s\n", matrix.isFixedStepInX() ? "true" : "false");
   2617             }
   2618         }
   2619     }
   2620 #StdOut
   2621 [  1.0000   0.0000   0.0000][  0.0000   1.0000   0.0000][  0.0000   0.0000   1.0000]
   2622 isFixedStepInX: true
   2623 [  1.0000   0.0000   0.0000][  0.0000   2.0000   0.0000][  0.0000   0.0000   1.0000]
   2624 isFixedStepInX: true
   2625 [  1.0000   0.0000   0.0000][  0.0000   1.0000   0.0000][  0.0000   0.1000   1.0000]
   2626 isFixedStepInX: true
   2627 [  1.0000   0.0000   0.0000][  0.0000   2.0000   0.0000][  0.0000   0.1000   1.0000]
   2628 isFixedStepInX: true
   2629 [  1.0000   0.0000   0.0000][  0.0000   1.0000   0.0000][  0.1000   0.0000   1.0000]
   2630 isFixedStepInX: false
   2631 [  1.0000   0.0000   0.0000][  0.0000   2.0000   0.0000][  0.1000   0.0000   1.0000]
   2632 isFixedStepInX: false
   2633 [  1.0000   0.0000   0.0000][  0.0000   1.0000   0.0000][  0.1000   0.1000   1.0000]
   2634 isFixedStepInX: false
   2635 [  1.0000   0.0000   0.0000][  0.0000   2.0000   0.0000][  0.1000   0.1000   1.0000]
   2636 isFixedStepInX: false
   2637 ##
   2638 ##
   2639 
   2640 #SeeAlso fixedStepInX getType
   2641 
   2642 ##
   2643 
   2644 # ------------------------------------------------------------------------------
   2645 
   2646 #Method SkVector fixedStepInX(SkScalar y) const
   2647 #In Property
   2648 #Line # returns step on x-axis for a position on y-axis ##
   2649 #Populate
   2650 
   2651 #Example
   2652 #Image 3
   2653     SkMatrix matrix;
   2654     const SkPoint center = { 128, 128 };
   2655     matrix.setScale(20, 25, center.fX, center.fY);
   2656     matrix.postRotate(75, center.fX, center.fY);
   2657     {
   2658        SkAutoCanvasRestore acr(canvas, true);
   2659        canvas->concat(matrix);
   2660        canvas->drawBitmap(source, 0, 0);
   2661     }
   2662     if (matrix.isFixedStepInX()) {
   2663        SkPaint paint;
   2664        paint.setAntiAlias(true);
   2665        SkVector step = matrix.fixedStepInX(128);
   2666        SkVector end = center + step;
   2667        canvas->drawLine(center, end, paint);
   2668        SkVector arrow = { step.fX + step.fY, step.fY - step.fX};
   2669        arrow = arrow * .25f;
   2670        canvas->drawLine(end, end - arrow, paint);
   2671        canvas->drawLine(end, {end.fX + arrow.fY, end.fY - arrow.fX}, paint);
   2672     }
   2673 ##
   2674 
   2675 #SeeAlso isFixedStepInX getType
   2676 
   2677 ##
   2678 
   2679 # ------------------------------------------------------------------------------
   2680 
   2681 #Method bool cheapEqualTo(const SkMatrix& m) const
   2682 #In Operators
   2683 #Line # compares Matrix pair using memcmp() ##
   2684 #Populate
   2685 
   2686 #Example
   2687     auto debugster = [](const char* prefix, const SkMatrix& a, const SkMatrix& b) -> void {
   2688         SkDebugf("%s: a %c= b a.cheapEqualTo(b): %s\n", prefix,
   2689                  a == b ? '=' : '!', a.cheapEqualTo(b) ? "true" : "false");
   2690     };
   2691     SkMatrix a, b;
   2692     a.setAll(1, 0, 0,   0, 1, 0,  0, 0, 1);
   2693     b.setIdentity();
   2694     debugster("identity", a, b);
   2695     a.setAll(1, -0.0f, 0,   0, 1, 0,  0, 0, 1);
   2696     debugster("neg zero", a, b);
   2697     a.setAll(1, SK_ScalarNaN, 0,   0, 1, 0,  0, 0, 1);
   2698     debugster(" one NaN", a, b);
   2699     b.setAll(1, SK_ScalarNaN, 0,   0, 1, 0,  0, 0, 1);
   2700     debugster("both NaN", a, b);
   2701 #StdOut
   2702 identity: a == b a.cheapEqualTo(b): true
   2703 neg zero: a == b a.cheapEqualTo(b): false
   2704  one NaN: a != b a.cheapEqualTo(b): false
   2705 both NaN: a != b a.cheapEqualTo(b): true
   2706 ##
   2707 ##
   2708 
   2709 #SeeAlso operator==(const SkMatrix& a, const SkMatrix& b)
   2710 
   2711 ##
   2712 
   2713 # ------------------------------------------------------------------------------
   2714 
   2715 #Method bool operator==(const SkMatrix& a, const SkMatrix& b)
   2716 
   2717 #Line # returns true if members are equal ##
   2718 #Populate
   2719 
   2720 #Example
   2721     auto debugster = [](const char* prefix, const SkMatrix& a, const SkMatrix& b) -> void {
   2722         SkDebugf("%s: a %c= b a.cheapEqualTo(b): %s\n", prefix,
   2723                  a == b ? '=' : '!', a.cheapEqualTo(b) ? "true" : "false");
   2724     };
   2725     SkMatrix a, b;
   2726     a.setAll(1, 0, 0,   0, 1, 0,  0, 0, 1);
   2727     b.setScale(2, 4);
   2728     b.postScale(0.5f, 0.25f);
   2729     debugster("identity", a, b);
   2730 #StdOut
   2731 identity: a == b a.cheapEqualTo(b): true
   2732 ##
   2733 ##
   2734 
   2735 #SeeAlso  cheapEqualTo operator!=(const SkMatrix& a, const SkMatrix& b)
   2736 
   2737 ##
   2738 
   2739 # ------------------------------------------------------------------------------
   2740 
   2741 #Method bool operator!=(const SkMatrix& a, const SkMatrix& b)
   2742 
   2743 #Line # returns true if members are unequal ##
   2744 #Populate
   2745 
   2746 #Example
   2747     auto debugster = [](const char* prefix, const SkMatrix& a, const SkMatrix& b) -> void {
   2748         SkDebugf("%s: a %c= b a.cheapEqualTo(b): %s\n", prefix,
   2749                  a != b ? '!' : '=', a.cheapEqualTo(b) ? "true" : "false");
   2750     };
   2751     SkMatrix a, b;
   2752     a.setAll(1, 0, 0,   0, 1, 0,  1, 0, 1);
   2753     if (a.invert(&b)) {
   2754         debugster("identity", a, b);
   2755     }
   2756 ##
   2757 
   2758 #SeeAlso cheapEqualTo operator==(const SkMatrix& a, const SkMatrix& b)
   2759 
   2760 ##
   2761 
   2762 # ------------------------------------------------------------------------------
   2763 #Subtopic Utility
   2764 #Line # rarely called management functions ##
   2765 ##
   2766 
   2767 #Method void dump() const
   2768 #In Utility
   2769 #Line # sends text representation using floats to standard output ##
   2770 #Populate
   2771 
   2772 #Example
   2773     SkMatrix matrix;
   2774     matrix.setRotate(45);
   2775     matrix.dump();
   2776     SkMatrix nearlyEqual;
   2777     nearlyEqual.setAll(0.7071f, -0.7071f, 0,   0.7071f, 0.7071f, 0,   0, 0, 1);
   2778     nearlyEqual.dump();
   2779     SkDebugf("matrix %c= nearlyEqual\n", matrix == nearlyEqual ? '=' : '!');
   2780 #StdOut
   2781 [  0.7071  -0.7071   0.0000][  0.7071   0.7071   0.0000][  0.0000   0.0000   1.0000]
   2782 [  0.7071  -0.7071   0.0000][  0.7071   0.7071   0.0000][  0.0000   0.0000   1.0000]
   2783 matrix != nearlyEqual
   2784 ##
   2785 ##
   2786 
   2787 #SeeAlso SkPath::dump
   2788 
   2789 ##
   2790 
   2791 # ------------------------------------------------------------------------------
   2792 
   2793 #Method SkScalar getMinScale() const
   2794 #In Property
   2795 #Line # returns minimum scaling, if possible ##
   2796 #Populate
   2797 
   2798 #Example
   2799     SkMatrix matrix;
   2800     matrix.setScale(42, 24);
   2801     SkDebugf("matrix.getMinScale() %g\n", matrix.getMinScale());
   2802 #StdOut
   2803 matrix.getMinScale() 24
   2804 ##
   2805 ##
   2806 
   2807 #SeeAlso getMaxScale getMinMaxScales
   2808 
   2809 ##
   2810 
   2811 # ------------------------------------------------------------------------------
   2812 
   2813 #Method SkScalar getMaxScale() const
   2814 #In Property
   2815 #Line # returns maximum scaling, if possible ##
   2816 #Populate
   2817 
   2818 #Example
   2819     SkMatrix matrix;
   2820     matrix.setScale(42, 24);
   2821     SkDebugf("matrix.getMaxScale() %g\n", matrix.getMaxScale());
   2822 #StdOut
   2823 matrix.getMaxScale() 42
   2824 ##
   2825 ##
   2826 
   2827 #SeeAlso getMinScale getMinMaxScales
   2828 
   2829 ##
   2830 
   2831 # ------------------------------------------------------------------------------
   2832 
   2833 #Method bool getMinMaxScales(SkScalar scaleFactors[2]) const
   2834 #In Property
   2835 #Line # returns minimum and maximum scaling, if possible ##
   2836 #Populate
   2837 
   2838 #Example
   2839     SkMatrix matrix;
   2840     matrix.setAll(1, 0, 0,  0, 1, 0,   0, 0, 0);
   2841     if (matrix.invert(&matrix)) {
   2842         SkScalar factor[2] = {2, 2};
   2843         bool result = matrix.getMinMaxScales(factor);
   2844         SkDebugf("matrix.getMinMaxScales() %s %g %g\n",
   2845                 result ? "true" : "false", factor[0], factor[1]);
   2846     }
   2847 #StdOut
   2848 matrix.getMinMaxScales() false 2 2
   2849 ##
   2850 ##
   2851 
   2852 #SeeAlso getMinScale getMaxScale
   2853 
   2854 ##
   2855 
   2856 # ------------------------------------------------------------------------------
   2857 
   2858 #Method bool decomposeScale(SkSize* scale, SkMatrix* remaining = nullptr) const
   2859 #In Property
   2860 #Line # separates scale if possible ##
   2861 Decomposes Matrix into scale components and whatever remains. Returns false if
   2862 Matrix could not be decomposed.
   2863 
   2864 Sets scale to portion of Matrix that scale axes. Sets remaining to Matrix
   2865 with scaling factored out. remaining may be passed as nullptr
   2866 to determine if Matrix can be decomposed without computing remainder.
   2867 
   2868 Returns true if scale components are found. scale and remaining are
   2869 unchanged if Matrix contains perspective; scale factors are not finite, or
   2870 are nearly zero.
   2871 
   2872 On success: #Formula # Matrix = scale * Remaining ##.
   2873 
   2874 #Param scale  axes scaling factors; may be nullptr ##
   2875 #Param remaining  Matrix without scaling; may be nullptr ##
   2876 
   2877 #Return  true if scale can be computed ##
   2878 
   2879 #Example
   2880     SkMatrix matrix;
   2881     matrix.setRotate(90 * SK_Scalar1);
   2882     matrix.postScale(1.f / 4, 1.f / 2);
   2883     matrix.dump();
   2884     SkSize scale = {SK_ScalarNaN, SK_ScalarNaN};
   2885     SkMatrix remaining;
   2886     remaining.reset();
   2887     bool success = matrix.decomposeScale(&scale, &remaining);
   2888     SkDebugf("success: %s  ", success ? "true" : "false");
   2889     SkDebugf("scale: %g, %g\n", scale.width(), scale.height());
   2890     remaining.dump();
   2891     SkMatrix scaleMatrix = SkMatrix::MakeScale(scale.width(), scale.height());
   2892     SkMatrix combined = SkMatrix::Concat(scaleMatrix, remaining);
   2893     combined.dump();
   2894 #StdOut
   2895 [  0.0000  -0.2500   0.0000][  0.5000   0.0000   0.0000][  0.0000   0.0000   1.0000]
   2896 success: true  scale: 0.5, 0.25
   2897 [  0.0000  -0.5000   0.0000][  2.0000   0.0000   0.0000][  0.0000   0.0000   1.0000]
   2898 [  0.0000  -0.2500   0.0000][  0.5000   0.0000   0.0000][  0.0000   0.0000   1.0000]
   2899 ##
   2900 ##
   2901 
   2902 #SeeAlso setScale MakeScale
   2903 
   2904 ##
   2905 
   2906 # ------------------------------------------------------------------------------
   2907 
   2908 #Method static const SkMatrix& I()
   2909 #In Constructors
   2910 #Line # returns a reference to a const identity Matrix ##
   2911 #Populate
   2912 
   2913 #Example
   2914     SkMatrix m1, m2, m3;
   2915     m1.reset();
   2916     m2.setIdentity();
   2917     m3 = SkMatrix::I();
   2918     SkDebugf("m1 %c= m2\n", m1 == m2 ? '=' : '!');
   2919     SkDebugf("m2 %c= m3\n", m1 == m2 ? '=' : '!');
   2920 #StdOut
   2921 m1 == m2
   2922 m2 == m3
   2923 ##
   2924 ##
   2925 
   2926 #SeeAlso reset() setIdentity
   2927 
   2928 ##
   2929 
   2930 # ------------------------------------------------------------------------------
   2931 
   2932 #Method static const SkMatrix& InvalidMatrix()
   2933 #In Constructors
   2934 #Line # returns a reference to a const invalid Matrix ##
   2935 #Populate
   2936 
   2937 #Example
   2938     SkDebugf("scaleX %g\n", SkMatrix::InvalidMatrix().getScaleX());
   2939 #StdOut
   2940 scaleX 3.40282e+38
   2941 ##
   2942 ##
   2943 
   2944 #SeeAlso getType
   2945 
   2946 ##
   2947 
   2948 # ------------------------------------------------------------------------------
   2949 
   2950 #Method static SkMatrix Concat(const SkMatrix& a, const SkMatrix& b)
   2951 #In Operators
   2952 #Line # returns the concatenation of Matrix pair ##
   2953 #Populate
   2954 
   2955 #Example
   2956 #Height 64
   2957 #Image 4
   2958 #Description
   2959 setPolyToPoly creates perspective matrices, one the inverse of the other.
   2960 Multiplying the matrix by its inverse turns into an identity matrix.
   2961 ##
   2962 SkMatrix matrix, matrix2;
   2963 SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
   2964 SkRect::Make(source.bounds()).toQuad(bitmapBounds);
   2965 matrix.setPolyToPoly(bitmapBounds, perspect, 4);
   2966 matrix2.setPolyToPoly(perspect, bitmapBounds, 4);
   2967 SkMatrix concat = SkMatrix::Concat(matrix, matrix2);
   2968 canvas->concat(concat);
   2969 canvas->drawBitmap(source, 0, 0);
   2970 ##
   2971 
   2972 #SeeAlso preConcat postConcat
   2973 
   2974 ##
   2975 
   2976 # ------------------------------------------------------------------------------
   2977 
   2978 #Method void dirtyMatrixTypeCache()
   2979 #In Utility
   2980 #Line # sets internal cache to unknown state ##
   2981 #Populate
   2982 
   2983 #Example
   2984 SkMatrix matrix;
   2985 matrix.setIdentity();
   2986 SkDebugf("with identity matrix: x = %g\n", matrix.mapXY(24, 42).fX);
   2987 SkScalar& skewRef = matrix[SkMatrix::kMSkewX];
   2988 skewRef = 0;
   2989 SkDebugf("after skew x mod:     x = %g\n", matrix.mapXY(24, 42).fX);
   2990 skewRef = 1;
   2991 SkDebugf("after 2nd skew x mod: x = %g\n", matrix.mapXY(24, 42).fX);
   2992 matrix.dirtyMatrixTypeCache();
   2993 SkDebugf("after dirty cache:    x = %g\n", matrix.mapXY(24, 42).fX);
   2994 #StdOut
   2995 with identity matrix: x = 24
   2996 after skew x mod:     x = 24
   2997 after 2nd skew x mod: x = 24
   2998 after dirty cache:    x = 66
   2999 ##
   3000 ##
   3001 
   3002 #SeeAlso operator[](int index) getType
   3003 
   3004 ##
   3005 
   3006 # ------------------------------------------------------------------------------
   3007 
   3008 #Method void setScaleTranslate(SkScalar sx, SkScalar sy, SkScalar tx, SkScalar ty)
   3009 #In Constructors
   3010 #In Set
   3011 #Line # sets to scale and translate ##
   3012 #Populate
   3013 
   3014 #Example
   3015 SkMatrix matrix;
   3016 matrix.setScaleTranslate(1, 2, 3, 4);
   3017 matrix.dump();
   3018 #StdOut
   3019 [  1.0000   0.0000   3.0000][  0.0000   2.0000   4.0000][  0.0000   0.0000   1.0000]
   3020 ##
   3021 ##
   3022 
   3023 #SeeAlso setScale preTranslate postTranslate
   3024 
   3025 ##
   3026 
   3027 # ------------------------------------------------------------------------------
   3028 
   3029 #Method bool isFinite() const
   3030 #In Property
   3031 #Line # returns if all Matrix values are not infinity, NaN ##
   3032 #Populate
   3033 
   3034 #Example
   3035 SkMatrix matrix = SkMatrix::MakeTrans(SK_ScalarNaN, 0);
   3036 matrix.dump();
   3037 SkDebugf("matrix is finite: %s\n", matrix.isFinite() ? "true" : "false");
   3038 SkDebugf("matrix %c= matrix\n", matrix == matrix ? '=' : '!');
   3039 #StdOut
   3040 [  1.0000   0.0000      nan][  0.0000   1.0000   0.0000][  0.0000   0.0000   1.0000]
   3041 matrix is finite: false
   3042 matrix != matrix
   3043 ##
   3044 ##
   3045 
   3046 #SeeAlso operator==
   3047 
   3048 ##
   3049 
   3050 #Class SkMatrix ##
   3051 
   3052 #Topic Matrix ##
   3053