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