• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#Topic Matrix
2#Alias Matrices
3#Alias Matrix_Reference
4
5#Subtopic Overview
6    #Subtopic Subtopics
7    #Populate
8    ##
9##
10
11#Class SkMatrix
12
13Matrix holds a 3x3 matrix for transforming coordinates. This allows mapping
14Points and Vectors with translation, scaling, skewing, rotation, and
15perspective.
16
17Matrix elements are in row major order. Matrix does not have a constructor,
18so it must be explicitly initialized. setIdentity initializes Matrix
19so it has no effect. setTranslate, setScale, setSkew, setRotate, set9 and setAll
20initializes all Matrix elements with the corresponding mapping.
21
22Matrix includes a hidden variable that classifies the type of matrix to
23improve performance. Matrix is not thread safe unless getType is called first.
24
25#Subtopic Constructors
26#Populate
27##
28
29#Subtopic Operators
30#Populate
31##
32
33#Subtopic Member_Functions
34#Populate
35##
36
37# ------------------------------------------------------------------------------
38
39#Method static SkMatrix SK_WARN_UNUSED_RESULT MakeScale(SkScalar sx, SkScalar sy)
40
41#Line # constructs from scale in x and y ##
42Sets Matrix to scale by (sx, sy). Returned matrix is:
43
44#Code
45#Literal
46| sx  0  0 |
47|  0 sy  0 |
48|  0  0  1 |
49##
50
51#Param sx  horizontal scale factor ##
52#Param sy  vertical scale factor ##
53
54#Return  Matrix with scale ##
55
56#Example
57#Image 4
58canvas->concat(SkMatrix::MakeScale(4, 3));
59canvas->drawBitmap(source, 0, 0);
60##
61
62#SeeAlso setScale postScale preScale
63
64##
65
66# ------------------------------------------------------------------------------
67
68#Method static SkMatrix SK_WARN_UNUSED_RESULT MakeScale(SkScalar scale)
69
70Sets Matrix to scale by (scale, scale). Returned matrix is:
71
72#Code
73#Literal
74| scale   0   0 |
75|   0   scale 0 |
76|   0     0   1 |
77##
78
79#Param scale  horizontal and vertical scale factor ##
80
81#Return  Matrix with scale ##
82
83#Example
84#Image 4
85canvas->concat(SkMatrix::MakeScale(4));
86canvas->drawBitmap(source, 0, 0);
87##
88
89#SeeAlso setScale postScale preScale
90
91##
92
93# ------------------------------------------------------------------------------
94
95#Method static SkMatrix SK_WARN_UNUSED_RESULT MakeTrans(SkScalar dx, SkScalar dy)
96
97#Line # constructs from translate in x and y ##
98Sets Matrix to translate by (dx, dy). Returned matrix is:
99
100#Code
101#Literal
102| 1 0 dx |
103| 0 1 dy |
104| 0 0  1 |
105##
106
107#Param dx  horizontal translation ##
108#Param dy  vertical translation ##
109
110#Return  Matrix with translation ##
111
112#Example
113#Image 4
114SkMatrix matrix = SkMatrix::MakeTrans(64, 48);
115for (int i = 0; i < 4; ++i) {
116    canvas->drawBitmap(source, 0, 0);
117    canvas->concat(matrix);
118}
119##
120
121#SeeAlso setTranslate postTranslate preTranslate
122
123##
124
125# ------------------------------------------------------------------------------
126
127#Method static SkMatrix SK_WARN_UNUSED_RESULT MakeAll(SkScalar scaleX, SkScalar skewX,  SkScalar transX,
128                                                      SkScalar skewY,  SkScalar scaleY, SkScalar transY,
129                                                      SkScalar pers0, SkScalar pers1, SkScalar pers2)
130#Line # constructs all nine values ##
131
132
133Sets Matrix to:
134
135#Code
136#Literal
137| scaleX  skewX transX |
138|  skewY scaleY transY |
139|  pers0  pers1  pers2 |
140##
141
142#Param scaleX  horizontal scale factor ##
143#Param skewX   horizontal skew factor ##
144#Param transX  horizontal translation ##
145#Param skewY   vertical skew factor ##
146#Param scaleY  vertical scale factor ##
147#Param transY  vertical translation ##
148#Param pers0   input x perspective factor ##
149#Param pers1   input y perspective factor ##
150#Param pers2   perspective scale factor ##
151
152#Return  Matrix constructed from parameters ##
153
154#Example
155    SkPaint p;
156    p.setAntiAlias(true);
157    p.setTextSize(64);
158    for (SkScalar sx : { -1, 1 } ) {
159        for (SkScalar sy : { -1, 1 } ) {
160            SkAutoCanvasRestore autoRestore(canvas, true);
161            SkMatrix m = SkMatrix::MakeAll(sx, 1, 128,    0, sy, 128,   0, 0, 1);
162            canvas->concat(m);
163            canvas->drawString("K", 0, 0, p);
164        }
165    }
166##
167
168#SeeAlso setAll set9 postConcat preConcat
169
170##
171
172
173# ------------------------------------------------------------------------------
174
175#Enum TypeMask
176
177#Code
178    enum TypeMask {
179        kIdentity_Mask = 0,
180        kTranslate_Mask = 0x01,
181        kScale_Mask = 0x02,
182        kAffine_Mask = 0x04,
183        kPerspective_Mask = 0x08,
184    };
185##
186
187Enum of bit fields for mask returned by getType.
188Used to identify the complexity of Matrix, to optimize performance.
189
190#Const kIdentity_Mask 0
191all bits clear if Matrix is identity
192##
193#Const kTranslate_Mask 1
194set if Matrix has translation
195##
196#Const kScale_Mask 2
197set if Matrix has x or y scale
198##
199#Const kAffine_Mask 4
200set if Matrix skews or rotates
201##
202#Const kPerspective_Mask 8
203set if Matrix has perspective
204##
205
206#Example
207    auto debugster = [](const char* prefix, const SkMatrix& matrix) -> void {
208        SkString typeMask;
209        typeMask += SkMatrix::kIdentity_Mask == matrix.getType() ? "kIdentity_Mask " : "";
210        typeMask += SkMatrix::kTranslate_Mask & matrix.getType() ? "kTranslate_Mask " : "";
211        typeMask += SkMatrix::kScale_Mask & matrix.getType() ? "kScale_Mask " : "";
212        typeMask += SkMatrix::kAffine_Mask & matrix.getType() ? "kAffine_Mask " : "";
213        typeMask += SkMatrix::kPerspective_Mask & matrix.getType() ? "kPerspective_Mask" : "";
214        SkDebugf("after %s: %s\n", prefix, typeMask.c_str());
215    };
216SkMatrix matrix;
217matrix.reset();
218debugster("reset", matrix);
219matrix.postTranslate(1, 0);
220debugster("postTranslate", matrix);
221matrix.postScale(2, 1);
222debugster("postScale", matrix);
223matrix.postRotate(45);
224debugster("postScale", matrix);
225SkPoint polys[][4] = {{{0, 0}, {0, 1}, {1, 1}, {1, 0}}, {{0, 0}, {0, 1}, {2, 1}, {1, 0}}};
226matrix.setPolyToPoly(polys[0], polys[1], 4);
227debugster("setPolyToPoly", matrix);
228#StdOut
229after reset: kIdentity_Mask
230after postTranslate: kTranslate_Mask
231after postScale: kTranslate_Mask kScale_Mask
232after postScale: kTranslate_Mask kScale_Mask kAffine_Mask
233after setPolyToPoly: kTranslate_Mask kScale_Mask kAffine_Mask kPerspective_Mask
234##
235##
236
237#SeeAlso getType
238
239##
240
241# ------------------------------------------------------------------------------
242
243#Method TypeMask getType() const
244
245#Line # returns transform complexity ##
246Returns a bit field describing the transformations the matrix may
247perform. The bit field is computed conservatively, so it may include
248false positives. For example, when kPerspective_Mask is set, all
249other bits are set.
250
251#Return  kIdentity_Mask, or combinations of: kTranslate_Mask, kScale_Mask,
252         kAffine_Mask, kPerspective_Mask
253##
254
255#Example
256SkMatrix matrix;
257matrix.setAll(1, 0, 0,   0, 1, 0,    0, 0, 1);
258SkDebugf("identity flags hex: %0x decimal: %d\n", matrix.getType(), matrix.getType());
259matrix.setAll(1, 0, 0,   0, 1, 0,    0, 0, .5f);
260SkDebugf("set all  flags hex: %0x decimal: %d\n", matrix.getType(), matrix.getType());
261#StdOut
262identity flags hex: 0 decimal: 0
263set all  flags hex: f decimal: 15
264##
265##
266
267#SeeAlso TypeMask
268
269##
270
271# ------------------------------------------------------------------------------
272
273#Method bool isIdentity() const
274
275#Line # returns if matrix equals the identity Matrix  ##
276Returns true if Matrix is identity.  Identity matrix is:
277
278#Code
279#Literal
280| 1 0 0 |
281| 0 1 0 |
282| 0 0 1 |
283##
284
285#Return  true if Matrix has no effect ##
286
287#Example
288SkMatrix matrix;
289matrix.setAll(1, 0, 0,   0, 1, 0,    0, 0, 1);
290SkDebugf("is identity: %s\n", matrix.isIdentity() ? "true" : "false");
291matrix.setAll(1, 0, 0,   0, 1, 0,    0, 0, 2);
292SkDebugf("is identity: %s\n", matrix.isIdentity() ? "true" : "false");
293#StdOut
294is identity: true
295is identity: false
296##
297##
298
299#SeeAlso reset() setIdentity getType
300
301##
302
303# ------------------------------------------------------------------------------
304
305#Method bool isScaleTranslate() const
306
307#Line # returns if transform is limited to scale and translate ##
308Returns true if Matrix at most scales and translates. Matrix may be identity,
309contain only scale elements, only translate elements, or both. Matrix form is:
310
311#Code
312#Literal
313| scale-x    0    translate-x |
314|    0    scale-y translate-y |
315|    0       0         1      |
316##
317
318#Return  true if Matrix is identity; or scales, translates, or both ##
319
320#Example
321SkMatrix matrix;
322for (SkScalar scaleX : { 1, 2 } ) {
323    for (SkScalar translateX : { 0, 20 } ) {
324        matrix.setAll(scaleX, 0, translateX,   0, 1, 0,    0, 0, 1);
325        SkDebugf("is scale-translate: %s\n", matrix.isScaleTranslate() ? "true" : "false");
326    }
327}
328#StdOut
329is scale-translate: true
330is scale-translate: true
331is scale-translate: true
332is scale-translate: true
333##
334##
335
336#SeeAlso setScale isTranslate setTranslate getType
337
338##
339
340# ------------------------------------------------------------------------------
341
342#Method bool isTranslate() const
343
344#Line # returns if transform is limited to translate ##
345Returns true if Matrix is identity, or translates. Matrix form is:
346
347#Code
348#Literal
349| 1 0 translate-x |
350| 0 1 translate-y |
351| 0 0      1      |
352##
353
354#Return  true if Matrix is identity, or translates ##
355
356#Example
357SkMatrix matrix;
358for (SkScalar scaleX : { 1, 2 } ) {
359    for (SkScalar translateX : { 0, 20 } ) {
360        matrix.setAll(scaleX, 0, translateX,   0, 1, 0,    0, 0, 1);
361        SkDebugf("is translate: %s\n", matrix.isTranslate() ? "true" : "false");
362    }
363}
364#StdOut
365is translate: true
366is translate: true
367is translate: false
368is translate: false
369##
370##
371
372#SeeAlso setTranslate getType
373
374##
375
376# ------------------------------------------------------------------------------
377
378#Method bool rectStaysRect() const
379
380#Line # returns if mapped Rect can be represented by another Rect ##
381Returns true Matrix maps Rect to another Rect. If true, Matrix is identity,
382or scales, or rotates a multiple of 90 degrees, or mirrors in x or y. In all
383cases, Matrix may also have translation. Matrix form is either:
384
385#Code
386#Literal
387| scale-x    0    translate-x |
388|    0    scale-y translate-y |
389|    0       0         1      |
390##
391
392or
393
394#Code
395#Literal
396|    0     rotate-x translate-x |
397| rotate-y    0     translate-y |
398|    0        0          1      |
399##
400
401for non-zero values of scale-x, scale-y, rotate-x, and rotate-y.
402
403Also called preservesAxisAlignment; use the one that provides better inline
404documentation.
405
406#Return  true if Matrix maps one Rect into another  ##
407
408#Example
409SkMatrix matrix;
410for (SkScalar angle: { 0, 90, 180, 270 } ) {
411    matrix.setRotate(angle);
412    SkDebugf("rectStaysRect: %s\n", matrix.rectStaysRect() ? "true" : "false");
413}
414#StdOut
415rectStaysRect: true
416rectStaysRect: true
417rectStaysRect: true
418rectStaysRect: true
419##
420##
421
422#SeeAlso preservesAxisAlignment preservesRightAngles
423
424##
425
426# ------------------------------------------------------------------------------
427
428#Method bool preservesAxisAlignment() const
429
430#Line # returns if mapping restricts to 90 degree multiples and mirroring ##
431
432Returns true Matrix maps Rect to another Rect. If true, Matrix is identity,
433or scales, or rotates a multiple of 90 degrees, or mirrors in x or y. In all
434cases, Matrix may also have translation. Matrix form is either:
435
436#Code
437#Literal
438| scale-x    0    translate-x |
439|    0    scale-y translate-y |
440|    0       0         1      |
441##
442
443or
444
445#Code
446#Literal
447|    0     rotate-x translate-x |
448| rotate-y    0     translate-y |
449|    0        0          1      |
450##
451
452for non-zero values of scale-x, scale-y, rotate-x, and rotate-y.
453
454Also called rectStaysRect; use the one that provides better inline
455documentation.
456
457#Return  true if Matrix maps one Rect into another  ##
458
459#Example
460SkMatrix matrix;
461for (SkScalar angle: { 0, 90, 180, 270 } ) {
462    matrix.setRotate(angle);
463    SkDebugf("preservesAxisAlignment: %s\n", matrix.preservesAxisAlignment() ? "true" : "false");
464}
465#StdOut
466preservesAxisAlignment: true
467preservesAxisAlignment: true
468preservesAxisAlignment: true
469preservesAxisAlignment: true
470##
471##
472
473#SeeAlso rectStaysRect preservesRightAngles
474
475##
476
477# ------------------------------------------------------------------------------
478
479#Method bool hasPerspective() const
480
481#Line # returns if transform includes perspective ##
482Returns true if the matrix contains perspective elements. Matrix form is:
483
484#Code
485#Literal
486|       --            --              --          |
487|       --            --              --          |
488| perspective-x  perspective-y  perspective-scale |
489##
490
491where perspective-x or perspective-y is non-zero, or perspective-scale is
492not one. All other elements may have any value.
493
494#Return  true if Matrix is in most general form ##
495
496#Example
497#Image 4
498SkMatrix matrix;
499SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
500SkRect::Make(source.bounds()).toQuad(bitmapBounds);
501matrix.setPolyToPoly(bitmapBounds, perspect, 4);
502canvas->concat(matrix);
503SkString string;
504string.printf("hasPerspective %s", matrix.hasPerspective() ? "true" : "false");
505canvas->drawBitmap(source, 0, 0);
506SkPaint paint;
507paint.setAntiAlias(true);
508paint.setTextSize(48);
509canvas->drawString(string, 0, source.bounds().height() + 48, paint);
510##
511
512#SeeAlso setAll set9 MakeAll
513
514##
515
516# ------------------------------------------------------------------------------
517
518#Method bool isSimilarity(SkScalar tol = SK_ScalarNearlyZero) const
519
520#Line # returns if transform is limited to square scale and rotation ##
521Returns true if Matrix contains only translation, rotation, reflection, and
522uniform scale.
523Returns false if Matrix contains different scales, skewing, perspective, or
524degenerate forms that collapse to a line or point.
525
526Describes that the Matrix makes rendering with and without the matrix are
527visually alike; a transformed circle remains a circle. Mathematically, this is
528referred to as similarity of a Euclidean_Space, or a similarity transformation.
529
530Preserves right angles, keeping the arms of the angle equal lengths.
531
532#Param tol  to be deprecated ##
533
534#Return  true if Matrix only rotates, uniformly scales, translates ##
535
536#Example
537#Description
538String is drawn four times through but only two are visible. Drawing the pair
539with isSimilarity false reveals the pair not visible through the matrix.
540##
541    SkPaint p;
542    p.setAntiAlias(true);
543    SkMatrix m;
544    int below = 175;
545    for (SkScalar sx : { -1, 1 } ) {
546        for (SkScalar sy : { -1, 1 } ) {
547            m.setAll(sx, 1, 128,    1, sy, 32,   0, 0, 1);
548            bool isSimilarity = m.isSimilarity();
549            SkString str;
550            str.printf("sx: %g sy: %g sim: %s", sx, sy, isSimilarity ? "true" : "false");
551            {
552                SkAutoCanvasRestore autoRestore(canvas, true);
553                canvas->concat(m);
554                canvas->drawString(str, 0, 0, p);
555            }
556            if (!isSimilarity) {
557                canvas->drawString(str, 40, below, p);
558                below += 20;
559            }
560        }
561    }
562##
563
564#SeeAlso isScaleTranslate preservesRightAngles rectStaysRect isFixedStepInX
565
566##
567
568# ------------------------------------------------------------------------------
569
570#Method bool preservesRightAngles(SkScalar tol = SK_ScalarNearlyZero) const
571
572#Line # returns if mapped 90 angle remains 90 degrees ##
573Returns true if Matrix contains only translation, rotation, reflection, and
574scale. Scale may differ along rotated axes.
575Returns false if Matrix skewing, perspective, or degenerate forms that collapse
576to a line or point.
577
578Preserves right angles, but not requiring that the arms of the angle
579retain equal lengths.
580
581#Param tol  to be deprecated ##
582
583#Return  true if Matrix only rotates, scales, translates ##
584
585#Example
586#Height 128
587#Description
588Equal scale is both similar and preserves right angles.
589Unequal scale is not similar but preserves right angles.
590Skews are not similar and do not preserve right angles.
591##
592SkPaint p;
593p.setAntiAlias(true);
594SkMatrix m;
595int pos = 0;
596for (SkScalar sx : { 1, 2 } ) {
597    for (SkScalar kx : { 0, 1 } ) {
598        m.setAll(sx, kx, 16,    0, 1, 32,   0, 0, 1);
599        bool isSimilarity = m.isSimilarity();
600        bool preservesRightAngles = m.preservesRightAngles();
601        SkString str;
602        str.printf("sx: %g kx: %g %s %s", sx, kx, isSimilarity ? "sim" : "",
603                    preservesRightAngles ? "right" : "");
604        SkAutoCanvasRestore autoRestore(canvas, true);
605        canvas->concat(m);
606        canvas->drawString(str, 0, pos, p);
607        pos += 20;
608    }
609}
610##
611
612#SeeAlso isScaleTranslate isSimilarity rectStaysRect isFixedStepInX
613
614##
615
616# ------------------------------------------------------------------------------
617
618#Enum
619
620#Code
621    enum {
622        kMScaleX,
623        kMSkewX,
624        kMTransX,
625        kMSkewY,
626        kMScaleY,
627        kMTransY,
628        kMPersp0,
629        kMPersp1,
630        kMPersp2,
631    };
632##
633
634Matrix organizes its values in row order. These members correspond to
635each value in Matrix.
636
637#Const kMScaleX 0
638horizontal scale factor
639##
640#Const kMSkewX 1
641horizontal skew factor
642##
643#Const kMTransX 2
644horizontal translation
645##
646#Const kMSkewY 3
647vertical skew factor
648##
649#Const kMScaleY 4
650vertical scale factor
651##
652#Const kMTransY 5
653vertical translation
654##
655#Const kMPersp0 6
656input x perspective factor
657##
658#Const kMPersp1 7
659input y perspective factor
660##
661#Const kMPersp2 8
662perspective bias
663##
664
665#Example
666SkPaint black;
667black.setAntiAlias(true);
668black.setTextSize(48);
669SkPaint gray = black;
670gray.setColor(0xFF9f9f9f);
671SkScalar offset[] = { 1.5f, 1.5f, 20,   1.5f, 1.5f, 20,   .03f, .01f, 2 };
672for (int i : { SkMatrix::kMScaleX, SkMatrix::kMSkewX,  SkMatrix::kMTransX,
673               SkMatrix::kMSkewY,  SkMatrix::kMScaleY, SkMatrix::kMTransY,
674               SkMatrix::kMPersp0, SkMatrix::kMPersp1, SkMatrix::kMPersp2 } ) {
675    SkMatrix m;
676    m.setIdentity();
677    m.set(i, offset[i]);
678    SkAutoCanvasRestore autoRestore(canvas, true);
679    canvas->translate(22 + (i % 3) * 88, 44 + (i / 3) * 88);
680    canvas->drawString("&", 0, 0, gray);
681    canvas->concat(m);
682    canvas->drawString("&", 0, 0, black);
683}
684##
685
686#SeeAlso get() set()
687
688##
689
690# ------------------------------------------------------------------------------
691
692#Enum
693
694#Code
695    enum {
696        kAScaleX,
697        kASkewY,
698        kASkewX,
699        kAScaleY,
700        kATransX,
701        kATransY,
702    };
703##
704
705Affine arrays are in column major order to match the matrix used by
706PDF and XPS.
707
708#Const kAScaleX 0
709horizontal scale factor
710##
711#Const kASkewY 1
712vertical skew factor
713##
714#Const kASkewX 2
715horizontal skew factor
716##
717#Const kAScaleY 3
718vertical scale factor
719##
720#Const kATransX 4
721horizontal translation
722##
723#Const kATransY 5
724vertical translation
725##
726
727#NoExample
728##
729
730#SeeAlso SetAffineIdentity asAffine setAffine
731
732##
733
734# ------------------------------------------------------------------------------
735
736#Method SkScalar operator[](int index)_const
737
738#Line # returns Matrix value ##
739Returns one matrix value. Asserts if index is out of range and SK_DEBUG is
740defined.
741
742#Param index  one of: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY,
743                      kMPersp0, kMPersp1, kMPersp2
744##
745
746#Return  value corresponding to index ##
747
748#Example
749SkMatrix matrix;
750matrix.setScale(42, 24);
751SkDebugf("matrix[SkMatrix::kMScaleX] %c= 42\n", matrix[SkMatrix::kMScaleX] == 42 ? '=' : '!');
752SkDebugf("matrix[SkMatrix::kMScaleY] %c= 24\n", matrix[SkMatrix::kMScaleY] == 24 ? '=' : '!');
753#StdOut
754matrix[SkMatrix::kMScaleX] == 42
755matrix[SkMatrix::kMScaleY] == 24
756##
757##
758
759#SeeAlso get set
760
761##
762
763# ------------------------------------------------------------------------------
764
765#Method SkScalar get(int index) const
766
767#Line # returns one of nine Matrix values ##
768Returns one matrix value. Asserts if index is out of range and SK_DEBUG is
769defined.
770
771#Param index  one of: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY,
772                      kMPersp0, kMPersp1, kMPersp2
773##
774
775#Return  value corresponding to index ##
776
777#Example
778SkMatrix matrix;
779matrix.setSkew(42, 24);
780SkDebugf("matrix.get(SkMatrix::kMSkewX) %c= 42\n",
781         matrix.get(SkMatrix::kMSkewX) == 42 ? '=' : '!');
782SkDebugf("matrix.get(SkMatrix::kMSkewY) %c= 24\n",
783         matrix.get(SkMatrix::kMSkewY) == 24 ? '=' : '!');
784#StdOut
785matrix.get(SkMatrix::kMSkewX) == 42
786matrix.get(SkMatrix::kMSkewY) == 24
787##
788##
789
790#SeeAlso operator[](int index) set
791
792##
793
794# ------------------------------------------------------------------------------
795
796#Method SkScalar getScaleX() const
797
798#Line # returns horizontal scale factor ##
799Returns scale factor multiplied by x input, contributing to x output.
800With mapPoints, scales Points along the x-axis.
801
802#Return  horizontal scale factor ##
803
804#Example
805SkMatrix matrix;
806matrix.setScale(42, 24);
807SkDebugf("matrix.getScaleX() %c= 42\n", matrix.getScaleX() == 42 ? '=' : '!');
808#StdOut
809matrix.getScaleX() == 42
810##
811##
812
813#SeeAlso get getScaleY setScaleX setScale
814
815##
816
817# ------------------------------------------------------------------------------
818
819#Method SkScalar getScaleY() const
820
821#Line # returns vertical scale factor ##
822Returns scale factor multiplied by y input, contributing to y output.
823With mapPoints, scales Points along the y-axis.
824
825#Return  vertical scale factor ##
826
827#Example
828SkMatrix matrix;
829matrix.setScale(42, 24);
830SkDebugf("matrix.getScaleY() %c= 24\n", matrix.getScaleY() == 24 ? '=' : '!');
831#StdOut
832matrix.getScaleY() == 24
833##
834##
835
836#SeeAlso get getScaleX setScaleY setScale
837
838##
839
840# ------------------------------------------------------------------------------
841
842#Method SkScalar getSkewY() const
843
844#Line # returns vertical skew factor ##
845Returns scale factor multiplied by x input, contributing to y output.
846With mapPoints, skews Points along the y-axis.
847Skew x and y together can rotate Points.
848
849#Return  vertical skew factor ##
850
851#Example
852SkMatrix matrix;
853matrix.setSkew(42, 24);
854SkDebugf("matrix.getSkewY() %c= 24\n", matrix.getSkewY() == 24 ? '=' : '!');
855#StdOut
856matrix.getSkewY() == 24
857##
858##
859
860#SeeAlso get getSkewX setSkewY setSkew
861
862##
863
864# ------------------------------------------------------------------------------
865
866#Method SkScalar getSkewX() const
867
868#Line # returns horizontal skew factor ##
869Returns scale factor multiplied by y input, contributing to x output.
870With mapPoints, skews Points along the x-axis.
871Skew x and y together can rotate Points.
872
873#Return  horizontal scale factor ##
874
875#Example
876SkMatrix matrix;
877matrix.setSkew(42, 24);
878SkDebugf("matrix.getSkewX() %c= 42\n", matrix.getSkewX() == 42 ? '=' : '!');
879#StdOut
880matrix.getSkewX() == 42
881##
882##
883
884#SeeAlso get getSkewY setSkewX setSkew
885
886##
887
888# ------------------------------------------------------------------------------
889
890#Method SkScalar getTranslateX() const
891
892#Line # returns horizontal translation ##
893Returns translation contributing to x output.
894With mapPoints, moves Points along the x-axis.
895
896#Return  horizontal translation factor ##
897
898#Example
899SkMatrix matrix;
900matrix.setTranslate(42, 24);
901SkDebugf("matrix.getTranslateX() %c= 42\n", matrix.getTranslateX() == 42 ? '=' : '!');
902#StdOut
903matrix.getTranslateX() == 42
904##
905##
906
907#SeeAlso get getTranslateY setTranslateX setTranslate
908
909##
910
911# ------------------------------------------------------------------------------
912
913#Method SkScalar getTranslateY() const
914
915#Line # returns vertical translation ##
916Returns translation contributing to y output.
917With mapPoints, moves Points along the y-axis.
918
919#Return  vertical translation factor ##
920
921#Example
922SkMatrix matrix;
923matrix.setTranslate(42, 24);
924SkDebugf("matrix.getTranslateY() %c= 24\n", matrix.getTranslateY() == 24 ? '=' : '!');
925#StdOut
926matrix.getTranslateY() == 24
927##
928##
929
930#SeeAlso get getTranslateX setTranslateY setTranslate
931
932##
933
934# ------------------------------------------------------------------------------
935
936#Method SkScalar getPerspX() const
937
938#Line # returns input x perspective factor ##
939Returns factor scaling input x relative to input y.
940
941#Return  input x perspective factor ##
942
943#Example
944    SkMatrix m;
945    m.setIdentity();
946    m.set(SkMatrix::kMPersp0, -0.004f);
947    SkAutoCanvasRestore autoRestore(canvas, true);
948    canvas->translate(22, 144);
949    SkPaint black;
950    black.setAntiAlias(true);
951    black.setTextSize(24);
952    SkPaint gray = black;
953    gray.setColor(0xFF9f9f9f);
954    SkString string;
955    string.appendScalar(m.getPerspX());
956    canvas->drawString(string, 0, -72, gray);
957    canvas->concat(m);
958    canvas->drawString(string, 0, 0, black);
959##
960
961#SeeAlso kMPersp0 getPerspY
962
963##
964
965# ------------------------------------------------------------------------------
966
967#Method SkScalar getPerspY() const
968
969#Line # returns input y perspective factor ##
970
971Returns factor scaling input y relative to input x.
972
973#Return  input y perspective factor ##
974
975#Example
976    SkMatrix m;
977    m.setIdentity();
978    m.set(SkMatrix::kMPersp1, -0.004f);
979    SkAutoCanvasRestore autoRestore(canvas, true);
980    canvas->translate(22, 144);
981    SkPaint black;
982    black.setAntiAlias(true);
983    black.setTextSize(24);
984    SkPaint gray = black;
985    gray.setColor(0xFF9f9f9f);
986    SkString string;
987    string.appendScalar(m.getPerspY());
988    canvas->drawString(string, 0, -72, gray);
989    canvas->concat(m);
990    canvas->drawString(string, 0, 0, black);
991##
992
993#SeeAlso kMPersp1 getPerspX
994
995##
996
997# ------------------------------------------------------------------------------
998
999#Method SkScalar& operator[](int index)
1000
1001#Line # returns writable reference to Matrix value ##
1002Returns writable Matrix value. Asserts if index is out of range and SK_DEBUG is
1003defined. Clears internal cache anticipating that caller will change Matrix value.
1004
1005Next call to read Matrix state may recompute cache; subsequent writes to Matrix
1006value must be followed by dirtyMatrixTypeCache.
1007
1008#Param index  one of: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY,
1009                      kMPersp0, kMPersp1, kMPersp2
1010##
1011
1012#Return  writable value corresponding to index ##
1013
1014#Example
1015SkMatrix matrix;
1016matrix.setIdentity();
1017SkDebugf("with identity matrix: x = %g\n", matrix.mapXY(24, 42).fX);
1018SkScalar& skewRef = matrix[SkMatrix::kMSkewX];
1019skewRef = 0;
1020SkDebugf("after skew x mod:     x = %g\n", matrix.mapXY(24, 42).fX);
1021skewRef = 1;
1022SkDebugf("after 2nd skew x mod: x = %g\n", matrix.mapXY(24, 42).fX);
1023matrix.dirtyMatrixTypeCache();
1024SkDebugf("after dirty cache:    x = %g\n", matrix.mapXY(24, 42).fX);
1025#StdOut
1026with identity matrix: x = 24
1027after skew x mod:     x = 24
1028after 2nd skew x mod: x = 24
1029after dirty cache:    x = 66
1030##
1031##
1032
1033#SeeAlso get dirtyMatrixTypeCache set
1034
1035##
1036
1037# ------------------------------------------------------------------------------
1038
1039#Method void set(int index, SkScalar value)
1040
1041#Line # sets one value ##
1042Sets Matrix value. Asserts if index is out of range and SK_DEBUG is
1043defined. Safer than operator[]; internal cache is always maintained.
1044
1045#Param index  one of: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY,
1046                      kMPersp0, kMPersp1, kMPersp2
1047##
1048#Param value  Scalar to store in Matrix ##
1049
1050#Example
1051SkMatrix matrix;
1052matrix.setIdentity();
1053SkDebugf("with identity matrix: x = %g\n", matrix.mapXY(24, 42).fX);
1054matrix.set(SkMatrix::kMSkewX, 0);
1055SkDebugf("after skew x mod:     x = %g\n", matrix.mapXY(24, 42).fX);
1056matrix.set(SkMatrix::kMSkewX, 1);
1057SkDebugf("after 2nd skew x mod: x = %g\n", matrix.mapXY(24, 42).fX);
1058#StdOut
1059with identity matrix: x = 24
1060after skew x mod:     x = 24
1061after 2nd skew x mod: x = 66
1062##
1063##
1064
1065#SeeAlso operator[] get
1066
1067#Method ##
1068
1069# ------------------------------------------------------------------------------
1070
1071#Method void setScaleX(SkScalar v)
1072
1073#Line # sets horizontal scale factor ##
1074Sets horizontal scale factor.
1075
1076#Param v  horizontal scale factor to store ##
1077
1078#Example
1079#Height 64
1080SkPaint paint;
1081paint.setAntiAlias(true);
1082paint.setTextSize(24);
1083canvas->drawString("normal", 12, 24, paint);
1084SkMatrix matrix;
1085matrix.setIdentity();
1086matrix.setScaleX(3);
1087canvas->concat(matrix);
1088canvas->drawString("x scale", 0, 48, paint);
1089##
1090
1091#SeeAlso set setScale setScaleY
1092
1093#Method ##
1094
1095# ------------------------------------------------------------------------------
1096
1097#Method void setScaleY(SkScalar v)
1098
1099#Line # sets vertical scale factor ##
1100Sets vertical scale factor.
1101
1102#Param v  vertical scale factor to store ##
1103
1104#Example
1105#Height 192
1106SkPaint paint;
1107paint.setAntiAlias(true);
1108paint.setTextSize(24);
1109canvas->drawString("normal", 12, 24, paint);
1110SkMatrix matrix;
1111matrix.setIdentity();
1112matrix.setScaleY(3);
1113canvas->concat(matrix);
1114canvas->drawString("y scale", 12, 48, paint);
1115##
1116
1117#SeeAlso set setScale setScaleX
1118
1119#Method ##
1120
1121# ------------------------------------------------------------------------------
1122
1123#Method void setSkewY(SkScalar v)
1124
1125#Line # sets vertical skew factor ##
1126Sets vertical skew factor.
1127
1128#Param v  vertical skew factor to store ##
1129
1130#Example
1131#Height 96
1132SkPaint paint;
1133paint.setAntiAlias(true);
1134paint.setTextSize(24);
1135canvas->drawString("normal", 12, 24, paint);
1136SkMatrix matrix;
1137matrix.setIdentity();
1138matrix.setSkewY(.3f);
1139canvas->concat(matrix);
1140canvas->drawString("y skew", 12, 48, paint);
1141##
1142
1143#SeeAlso set setSkew setSkewX
1144
1145#Method ##
1146
1147# ------------------------------------------------------------------------------
1148
1149#Method void setSkewX(SkScalar v)
1150
1151#Line # sets horizontal skew factor ##
1152Sets horizontal skew factor.
1153
1154#Param v  horizontal skew factor to store ##
1155
1156#Example
1157#Height 64
1158SkPaint paint;
1159paint.setAntiAlias(true);
1160paint.setTextSize(24);
1161canvas->drawString("normal", 12, 24, paint);
1162SkMatrix matrix;
1163matrix.setIdentity();
1164matrix.setSkewX(-.7f);
1165canvas->concat(matrix);
1166canvas->drawString("x skew", 36, 48, paint);
1167##
1168
1169#SeeAlso set setSkew setSkewX
1170
1171#Method ##
1172
1173# ------------------------------------------------------------------------------
1174
1175#Method void setTranslateX(SkScalar v)
1176
1177#Line # sets horizontal translation ##
1178Sets horizontal translation.
1179
1180#Param v  horizontal translation to store ##
1181
1182#Example
1183#Height 48
1184SkPaint paint;
1185paint.setAntiAlias(true);
1186paint.setTextSize(24);
1187canvas->drawString("normal", 8, 24, paint);
1188SkMatrix matrix;
1189matrix.setIdentity();
1190matrix.setTranslateX(96);
1191canvas->concat(matrix);
1192canvas->drawString("x translate", 8, 24, paint);
1193##
1194
1195#SeeAlso set setTranslate setTranslateY
1196
1197#Method ##
1198
1199# ------------------------------------------------------------------------------
1200
1201#Method void setTranslateY(SkScalar v)
1202
1203#Line # sets vertical translation ##
1204Sets vertical translation.
1205
1206#Param v  vertical translation to store ##
1207
1208#Example
1209#Height 64
1210SkPaint paint;
1211paint.setAntiAlias(true);
1212paint.setTextSize(24);
1213canvas->drawString("normal", 8, 24, paint);
1214SkMatrix matrix;
1215matrix.setIdentity();
1216matrix.setTranslateY(24);
1217canvas->concat(matrix);
1218canvas->drawString("y translate", 8, 24, paint);
1219##
1220
1221#SeeAlso set setTranslate setTranslateX
1222
1223#Method ##
1224
1225# ------------------------------------------------------------------------------
1226
1227#Method void setPerspX(SkScalar v)
1228
1229#Line # sets input x perspective factor ##
1230Sets input x perspective factor, which causes mapXY to vary input x inversely
1231proportional to input y.
1232
1233#Param v  perspective factor ##
1234
1235#Example
1236#Image 4
1237for (SkScalar perspX : { -.003f, 0.f, .003f, .012f } ) {
1238    SkMatrix matrix;
1239    matrix.setIdentity();
1240    matrix.setPerspX(perspX);
1241    canvas->save();
1242    canvas->concat(matrix);
1243    canvas->drawBitmap(source, 0, 0);
1244    canvas->restore();
1245    canvas->translate(64, 64);
1246}
1247##
1248
1249#SeeAlso getPerspX set setAll set9 MakeAll
1250
1251#Method ##
1252
1253# ------------------------------------------------------------------------------
1254
1255#Method void setPerspY(SkScalar v)
1256
1257#Line # sets input y perspective factor ##
1258Sets input y perspective factor, which causes mapXY to vary input y inversely
1259proportional to input x.
1260
1261#Param v  perspective factor ##
1262
1263#Example
1264#Image 4
1265for (SkScalar perspX : { -.003f, 0.f, .003f, .012f } ) {
1266    SkMatrix matrix;
1267    matrix.setIdentity();
1268    matrix.setPerspY(perspX);
1269    canvas->save();
1270    canvas->concat(matrix);
1271    canvas->drawBitmap(source, 0, 0);
1272    canvas->restore();
1273    canvas->translate(64, 64);
1274}
1275##
1276
1277#SeeAlso getPerspY set setAll set9 MakeAll
1278
1279#Method ##
1280
1281# ------------------------------------------------------------------------------
1282
1283#Method void setAll(SkScalar scaleX, SkScalar skewX,  SkScalar transX,
1284                SkScalar skewY,  SkScalar scaleY, SkScalar transY,
1285                SkScalar persp0, SkScalar persp1, SkScalar persp2)
1286#Line # sets all values from parameters ##
1287
1288Sets all values from parameters. Sets matrix to:
1289
1290#Code
1291#Literal
1292| scaleX  skewX transX |
1293|  skewY scaleY transY |
1294| persp0 persp1 persp2 |
1295##
1296
1297#Param scaleX  horizontal scale factor to store ##
1298#Param skewX  horizontal skew factor to store ##
1299#Param transX  horizontal translation to store ##
1300#Param skewY  vertical skew factor to store ##
1301#Param scaleY  vertical scale factor to store ##
1302#Param transY  vertical translation to store ##
1303#Param persp0  input x perspective factor to store ##
1304#Param persp1  input y perspective factor to store ##
1305#Param persp2  perspective scale factor to store ##
1306
1307#Example
1308#Height 128
1309    SkPaint p;
1310    p.setAntiAlias(true);
1311    p.setTextSize(64);
1312    SkMatrix m;
1313    for (SkScalar sx : { -1, 1 } ) {
1314        for (SkScalar sy : { -1, 1 } ) {
1315            SkAutoCanvasRestore autoRestore(canvas, true);
1316            m.setAll(sx, 1, 128,    0, sy, 64,   0, 0, 1);
1317            canvas->concat(m);
1318            canvas->drawString("K", 0, 0, p);
1319        }
1320    }
1321##
1322
1323#SeeAlso set9 MakeAll
1324
1325#Method ##
1326
1327# ------------------------------------------------------------------------------
1328
1329#Method void get9(SkScalar buffer[9]) const
1330
1331#Line # returns all nine Matrix values ##
1332Copies nine Scalar values contained by Matrix into buffer, in member value
1333ascending order: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY,
1334kMPersp0, kMPersp1, kMPersp2.
1335
1336#Param buffer  storage for nine Scalar values ##
1337
1338#Example
1339SkMatrix matrix = SkMatrix::MakeRectToRect({0, 0, 1, 1}, {3, 4, 7, 9},
1340                                           SkMatrix::kFill_ScaleToFit);
1341SkScalar b[9];
1342matrix.get9(b);
1343SkDebugf("{%g, %g, %g},\n{%g, %g, %g},\n{%g, %g, %g}\n", b[0], b[1], b[2],
1344         b[3], b[4], b[5], b[6], b[7], b[8]);
1345#StdOut
1346{4, 0, 3},
1347{0, 5, 4},
1348{0, 0, 1}
1349##
1350##
1351
1352#SeeAlso set9
1353
1354#Method ##
1355
1356# ------------------------------------------------------------------------------
1357
1358#Method void set9(const SkScalar buffer[9])
1359
1360#Line # sets all values from Scalar array ##
1361Sets Matrix to nine Scalar values in buffer, in member value ascending order:
1362kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY, kMPersp0, kMPersp1,
1363kMPersp2.
1364
1365Sets matrix to:
1366
1367#Code
1368#Literal
1369| buffer[0] buffer[1] buffer[2] |
1370| buffer[3] buffer[4] buffer[5] |
1371| buffer[6] buffer[7] buffer[8] |
1372##
1373
1374In the future, set9 followed by get9 may not return the same values. Since Matrix
1375maps non-homogeneous coordinates, scaling all nine values produces an equivalent
1376transformation, possibly improving precision.
1377
1378#Param buffer  nine Scalar values ##
1379
1380#Example
1381#Image 4
1382SkMatrix m;
1383SkScalar buffer[9] = {4, 0, 3,    0, 5, 4,     0, 0, 1};
1384m.set9(buffer);
1385canvas->concat(m);
1386canvas->drawBitmap(source, 0, 0);
1387##
1388
1389#SeeAlso setAll get9 MakeAll
1390
1391#Method ##
1392
1393# ------------------------------------------------------------------------------
1394
1395#Method void reset()
1396
1397#Line # sets Matrix to identity ##
1398Sets Matrix to identity; which has no effect on mapped Points. Sets Matrix to:
1399
1400#Code
1401#Literal
1402| 1 0 0 |
1403| 0 1 0 |
1404| 0 0 1 |
1405##
1406
1407Also called setIdentity(); use the one that provides better inline
1408documentation.
1409
1410#Example
1411SkMatrix m;
1412m.reset();
1413SkDebugf("m.isIdentity(): %s\n", m.isIdentity() ? "true" : "false");
1414#StdOut
1415m.isIdentity(): true
1416##
1417##
1418
1419#SeeAlso isIdentity setIdentity
1420
1421#Method ##
1422
1423# ------------------------------------------------------------------------------
1424
1425#Method void setIdentity()
1426
1427#Line # sets Matrix to identity ##
1428Sets Matrix to identity; which has no effect on mapped Points. Sets Matrix to:
1429
1430#Code
1431#Literal
1432| 1 0 0 |
1433| 0 1 0 |
1434| 0 0 1 |
1435##
1436
1437Also called reset(); use the one that provides better inline
1438documentation.
1439
1440#Example
1441SkMatrix m;
1442m.setIdentity();
1443SkDebugf("m.isIdentity(): %s\n", m.isIdentity() ? "true" : "false");
1444#StdOut
1445m.isIdentity(): true
1446##
1447##
1448
1449#SeeAlso isIdentity reset
1450
1451#Method ##
1452
1453# ------------------------------------------------------------------------------
1454
1455#Method void setTranslate(SkScalar dx, SkScalar dy)
1456
1457#Line # sets to translate in x and y ##
1458Sets Matrix to translate by (dx, dy).
1459
1460#Param dx  horizontal translation ##
1461#Param dy  vertical translation ##
1462
1463#Example
1464#Height 64
1465SkPaint paint;
1466paint.setAntiAlias(true);
1467paint.setTextSize(24);
1468canvas->drawString("normal", 8, 24, paint);
1469SkMatrix matrix;
1470matrix.setTranslate(96, 24);
1471canvas->concat(matrix);
1472canvas->drawString("translate", 8, 24, paint);
1473##
1474
1475#SeeAlso setTranslateX setTranslateY
1476
1477#Method ##
1478
1479# ------------------------------------------------------------------------------
1480
1481#Method void setTranslate(const SkVector& v)
1482
1483Sets Matrix to translate by (v.fX, v.fY).
1484
1485#Param v  Vector containing horizontal and vertical translation ##
1486
1487#Example
1488#Height 64
1489SkPaint paint;
1490paint.setAntiAlias(true);
1491paint.setTextSize(24);
1492canvas->drawString("normal", 8, 24, paint);
1493SkMatrix matrix;
1494matrix.setTranslate({96, 24});
1495canvas->concat(matrix);
1496canvas->drawString("translate", 8, 24, paint);
1497##
1498
1499#SeeAlso setTranslateX setTranslateY MakeTrans
1500
1501#Method ##
1502
1503# ------------------------------------------------------------------------------
1504
1505#Method void setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py)
1506
1507#Line # sets to scale about a point ##
1508Sets Matrix to scale by sx and sy, about a pivot point at (px, py).
1509The pivot point is unchanged when mapped with Matrix.
1510
1511#Param sx  horizontal scale factor ##
1512#Param sy  vertical scale factor ##
1513#Param px  pivot x ##
1514#Param py  pivot y ##
1515
1516#Example
1517#Height 128
1518    SkPaint p;
1519    p.setAntiAlias(true);
1520    p.setTextSize(64);
1521    SkMatrix m;
1522    for (SkScalar sx : { -1, 1 } ) {
1523        for (SkScalar sy : { -1, 1 } ) {
1524            SkAutoCanvasRestore autoRestore(canvas, true);
1525            m.setScale(sx, sy, 128, 64);
1526            canvas->concat(m);
1527            canvas->drawString("%", 128, 64, p);
1528        }
1529    }
1530##
1531
1532#SeeAlso setScaleX setScaleY MakeScale preScale postScale
1533
1534#Method ##
1535
1536# ------------------------------------------------------------------------------
1537
1538#Method void setScale(SkScalar sx, SkScalar sy)
1539
1540Sets Matrix to scale by sx and sy about at pivot point at (0, 0).
1541
1542#Param sx  horizontal scale factor ##
1543#Param sy  vertical scale factor ##
1544
1545#Example
1546#Height 128
1547    SkPaint p;
1548    p.setAntiAlias(true);
1549    p.setTextSize(64);
1550    SkMatrix m;
1551    for (SkScalar sx : { -1, 1 } ) {
1552        for (SkScalar sy : { -1, 1 } ) {
1553            SkAutoCanvasRestore autoRestore(canvas, true);
1554            m.setScale(sx, sy);
1555            m.postTranslate(128, 64);
1556            canvas->concat(m);
1557            canvas->drawString("@", 0, 0, p);
1558        }
1559    }
1560##
1561
1562#SeeAlso setScaleX setScaleY MakeScale preScale postScale
1563
1564#Method ##
1565
1566# ------------------------------------------------------------------------------
1567
1568#Method void setRotate(SkScalar degrees, SkScalar px, SkScalar py)
1569
1570#Line # sets to rotate about a point ##
1571Sets Matrix to rotate by degrees about a pivot point at (px, py).
1572The pivot point is unchanged when mapped with Matrix.
1573
1574Positive degrees rotates clockwise.
1575
1576#Param degrees  angle of axes relative to upright axes ##
1577#Param px  pivot x ##
1578#Param py  pivot y ##
1579
1580#Example
1581#Height 128
1582    SkPaint paint;
1583    paint.setColor(SK_ColorGRAY);
1584    paint.setAntiAlias(true);
1585    SkRect rect = {20, 20, 100, 100};
1586    canvas->drawRect(rect, paint);
1587    paint.setColor(SK_ColorRED);
1588    SkMatrix matrix;
1589    matrix.setRotate(25, rect.centerX(), rect.centerY());
1590    canvas->concat(matrix);
1591    canvas->drawRect(rect, paint);
1592##
1593
1594#SeeAlso setSinCos preRotate postRotate
1595
1596#Method ##
1597
1598# ------------------------------------------------------------------------------
1599
1600#Method void setRotate(SkScalar degrees)
1601
1602Sets Matrix to rotate by degrees about a pivot point at (0, 0).
1603Positive degrees rotates clockwise.
1604
1605#Param degrees  angle of axes relative to upright axes ##
1606
1607#Example
1608#Height 128
1609    SkPaint paint;
1610    paint.setColor(SK_ColorGRAY);
1611    paint.setAntiAlias(true);
1612    SkRect rect = {20, 20, 100, 100};
1613    canvas->drawRect(rect, paint);
1614    paint.setColor(SK_ColorRED);
1615    SkMatrix matrix;
1616    matrix.setRotate(25);
1617    canvas->translate(rect.centerX(), rect.centerY());
1618    canvas->concat(matrix);
1619    canvas->translate(-rect.centerX(), -rect.centerY());
1620    canvas->drawRect(rect, paint);
1621##
1622
1623#SeeAlso setSinCos preRotate postRotate
1624
1625#Method ##
1626
1627# ------------------------------------------------------------------------------
1628
1629#Method void setSinCos(SkScalar sinValue, SkScalar cosValue,
1630                   SkScalar px, SkScalar py)
1631#Line # sets to rotate and scale about a point ##
1632
1633Sets Matrix to rotate by sinValue and cosValue, about a pivot point at (px, py).
1634The pivot point is unchanged when mapped with Matrix.
1635
1636Vector (sinValue, cosValue) describes the angle of rotation relative to (0, 1).
1637Vector length specifies scale.
1638
1639#Param sinValue  rotation vector x component ##
1640#Param cosValue  rotation vector y component ##
1641#Param px  pivot x ##
1642#Param py  pivot y ##
1643
1644#Example
1645#Height 128
1646    SkPaint paint;
1647    paint.setColor(SK_ColorGRAY);
1648    paint.setAntiAlias(true);
1649    SkRect rect = {20, 20, 100, 100};
1650    canvas->drawRect(rect, paint);
1651    paint.setColor(SK_ColorRED);
1652    SkMatrix matrix;
1653    matrix.setSinCos(.25f, .85f, rect.centerX(), rect.centerY());
1654    canvas->concat(matrix);
1655    canvas->drawRect(rect, paint);
1656##
1657
1658#SeeAlso setRotate setScale setRSXform
1659
1660#Method ##
1661
1662# ------------------------------------------------------------------------------
1663
1664#Method void setSinCos(SkScalar sinValue, SkScalar cosValue)
1665
1666Sets Matrix to rotate by sinValue and cosValue, about a pivot point at (0, 0).
1667
1668Vector (sinValue, cosValue) describes the angle of rotation relative to (0, 1).
1669Vector length specifies scale.
1670
1671#Param sinValue  rotation vector x component ##
1672#Param cosValue  rotation vector y component ##
1673
1674#Example
1675#Description
1676Canvas needs offset after applying Matrix to pivot about Rect center.
1677##
1678#Height 128
1679    SkPaint paint;
1680    paint.setColor(SK_ColorGRAY);
1681    paint.setAntiAlias(true);
1682    SkRect rect = {20, 20, 100, 100};
1683    canvas->drawRect(rect, paint);
1684    paint.setColor(SK_ColorRED);
1685    SkMatrix matrix;
1686    matrix.setSinCos(.25f, .85f);
1687    matrix.postTranslate(rect.centerX(), rect.centerY());
1688    canvas->concat(matrix);
1689    canvas->translate(-rect.centerX(), -rect.centerY());
1690    canvas->drawRect(rect, paint);
1691##
1692
1693#SeeAlso setRotate setScale setRSXform
1694
1695#Method ##
1696
1697# ------------------------------------------------------------------------------
1698
1699#Method SkMatrix& setRSXform(const SkRSXform& rsxForm)
1700
1701#Line # sets to rotate, scale, and translate ##
1702Sets Matrix to rotate, scale, and translate using a compressed matrix form.
1703
1704Vector (rsxForm.fSSin, rsxForm.fSCos) describes the angle of rotation relative
1705to (0, 1). Vector length specifies scale. Mapped point is rotated and scaled
1706by Vector, then translated by (rsxForm.fTx, rsxForm.fTy).
1707
1708#Param rsxForm  compressed RSXform matrix ##
1709
1710#Return  reference to Matrix ##
1711
1712#Example
1713#Description
1714Canvas needs offset after applying Matrix to pivot about Rect center.
1715##
1716#Height 128
1717    SkPaint paint;
1718    paint.setColor(SK_ColorGRAY);
1719    paint.setAntiAlias(true);
1720    SkRect rect = {20, 20, 100, 100};
1721    canvas->drawRect(rect, paint);
1722    paint.setColor(SK_ColorRED);
1723    SkMatrix matrix;
1724    matrix.setRSXform(SkRSXform::Make(.85f, .25f, rect.centerX(), rect.centerY()));
1725    canvas->concat(matrix);
1726    canvas->translate(-rect.centerX(), -rect.centerY());
1727    canvas->drawRect(rect, paint);
1728##
1729
1730#SeeAlso setSinCos setScale setTranslate
1731
1732#Method ##
1733
1734# ------------------------------------------------------------------------------
1735
1736#Method void setSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py)
1737
1738#Line # sets to skew about a point ##
1739Sets Matrix to skew by kx and ky, about a pivot point at (px, py).
1740The pivot point is unchanged when mapped with Matrix.
1741
1742#Param kx  horizontal skew factor ##
1743#Param ky  vertical skew factor ##
1744#Param px  pivot x ##
1745#Param py  pivot y ##
1746
1747#Example
1748    SkPaint p;
1749    p.setAntiAlias(true);
1750    p.setTextSize(48);
1751    SkMatrix m;
1752    for (SkScalar sx : { -1, 0, 1 } ) {
1753        for (SkScalar sy : { -1, 0, 1 } ) {
1754            SkAutoCanvasRestore autoRestore(canvas, true);
1755            m.setSkew(sx, sy, 96 + 64 * sx, 128 + 48 * sy);
1756            canvas->concat(m);
1757            canvas->drawString("K", 96 + 64 * sx, 128 + 48 * sy, p);
1758        }
1759    }
1760##
1761
1762#SeeAlso setSkewX setSkewY preSkew postSkew
1763
1764#Method ##
1765
1766# ------------------------------------------------------------------------------
1767
1768#Method void setSkew(SkScalar kx, SkScalar ky)
1769
1770Sets Matrix to skew by kx and ky, about a pivot point at (0, 0).
1771
1772#Param kx  horizontal skew factor ##
1773#Param ky  vertical skew factor ##
1774
1775#Example
1776    SkPaint p;
1777    p.setAntiAlias(true);
1778    p.setTextSize(48);
1779    SkMatrix m;
1780    for (SkScalar sx : { -1, 0, 1 } ) {
1781        for (SkScalar sy : { -1, 0, 1 } ) {
1782            SkAutoCanvasRestore autoRestore(canvas, true);
1783            m.setSkew(sx, sy);
1784            m.postTranslate(96 + 64 * sx, 128 + 48 * sy);
1785            canvas->concat(m);
1786            canvas->drawString("K", 0, 0, p);
1787        }
1788    }
1789##
1790
1791#SeeAlso setSkewX setSkewY preSkew postSkew
1792
1793#Method ##
1794
1795# ------------------------------------------------------------------------------
1796
1797#Method void setConcat(const SkMatrix& a, const SkMatrix& b)
1798
1799#Line # sets to Matrix parameter multiplied by Matrix parameter ##
1800Sets Matrix to Matrix a multiplied by Matrix b. Either a or b may be this.
1801
1802Given:
1803
1804#Code
1805#Literal
1806    | A B C |      | J K L |
1807a = | D E F |, b = | M N O |
1808    | G H I |      | P Q R |
1809##
1810
1811sets Matrix to:
1812
1813#Code
1814#Literal
1815        | A B C |   | J K L |   | AJ+BM+CP AK+BN+CQ AL+BO+CR |
1816a * b = | D E F | * | M N O | = | DJ+EM+FP DK+EN+FQ DL+EO+FR |
1817        | G H I |   | P Q R |   | GJ+HM+IP GK+HN+IQ GL+HO+IR |
1818##
1819
1820#Param a  Matrix on left side of multiply expression ##
1821#Param b  Matrix on right side of multiply expression ##
1822
1823#Example
1824#Image 3
1825#Description
1826setPolyToPoly creates perspective matrices, one the inverse of the other.
1827Multiplying the matrix by its inverse turns into an identity matrix.
1828##
1829SkMatrix matrix, matrix2;
1830SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
1831SkRect::Make(source.bounds()).toQuad(bitmapBounds);
1832matrix.setPolyToPoly(bitmapBounds, perspect, 4);
1833matrix2.setPolyToPoly(perspect, bitmapBounds, 4);
1834matrix.setConcat(matrix, matrix2);
1835canvas->concat(matrix);
1836canvas->drawBitmap(source, 0, 0);
1837##
1838
1839#SeeAlso Concat preConcat postConcat SkCanvas::concat
1840
1841#Method ##
1842
1843# ------------------------------------------------------------------------------
1844
1845#Method void preTranslate(SkScalar dx, SkScalar dy)
1846
1847#Line # pre-multiplies Matrix by translation ##
1848Sets Matrix to Matrix multiplied by Matrix constructed from translation (dx, dy).
1849This can be thought of as moving the point to be mapped before applying Matrix.
1850
1851Given:
1852
1853#Code
1854#Literal
1855         | A B C |               | 1 0 dx |
1856Matrix = | D E F |,  T(dx, dy) = | 0 1 dy |
1857         | G H I |               | 0 0  1 |
1858##
1859
1860sets Matrix to:
1861
1862#Code
1863#Literal
1864                     | A B C | | 1 0 dx |   | A B A*dx+B*dy+C |
1865Matrix * T(dx, dy) = | D E F | | 0 1 dy | = | D E D*dx+E*dy+F |
1866                     | G H I | | 0 0  1 |   | G H G*dx+H*dy+I |
1867##
1868
1869#Param dx  x translation before applying Matrix ##
1870#Param dy  y translation before applying Matrix ##
1871
1872#Example
1873#Height 160
1874    SkPaint paint;
1875    paint.setAntiAlias(true);
1876    SkRect rect = {20, 20, 100, 100};
1877    for (int i = 0; i < 2; ++i ) {
1878        SkMatrix matrix;
1879        i == 0 ? matrix.reset(): matrix.setRotate(25, rect.centerX(), 320);
1880        {
1881            SkAutoCanvasRestore acr(canvas, true);
1882            canvas->concat(matrix);
1883            paint.setColor(SK_ColorGRAY);
1884            canvas->drawRect(rect, paint);
1885        }
1886        paint.setColor(SK_ColorRED);
1887        for (int j = 0; j < 2; ++j ) {
1888            SkAutoCanvasRestore acr(canvas, true);
1889            matrix.preTranslate(40, 40);
1890            canvas->concat(matrix);
1891            canvas->drawCircle(0, 0, 3, paint);
1892        }
1893    }
1894##
1895
1896#SeeAlso postTranslate setTranslate MakeTrans
1897
1898#Method ##
1899
1900# ------------------------------------------------------------------------------
1901
1902#Method void preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py)
1903
1904#Line # pre-multiplies Matrix by scale ##
1905Sets Matrix to Matrix multiplied by Matrix constructed from scaling by (sx, sy)
1906about pivot point (px, py).
1907This can be thought of as scaling about a pivot point before applying Matrix.
1908
1909Given:
1910
1911#Code
1912#Literal
1913         | A B C |                       | sx  0 dx |
1914Matrix = | D E F |,  S(sx, sy, px, py) = |  0 sy dy |
1915         | G H I |                       |  0  0  1 |
1916##
1917
1918where
1919
1920#Code
1921#Literal
1922dx = px - sx * px
1923dy = py - sy * py
1924##
1925
1926sets Matrix to:
1927
1928#Code
1929#Literal
1930                             | A B C | | sx  0 dx |   | A*sx B*sy A*dx+B*dy+C |
1931Matrix * S(sx, sy, px, py) = | D E F | |  0 sy dy | = | D*sx E*sy D*dx+E*dy+F |
1932                             | G H I | |  0  0  1 |   | G*sx H*sy G*dx+H*dy+I |
1933##
1934
1935#Param sx  horizontal scale factor ##
1936#Param sy  vertical scale factor ##
1937#Param px  pivot x ##
1938#Param py  pivot y ##
1939
1940#Example
1941#Image 3
1942SkMatrix matrix;
1943SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
1944SkRect::Make(source.bounds()).toQuad(bitmapBounds);
1945matrix.setPolyToPoly(bitmapBounds, perspect, 4);
1946matrix.preScale(.75f, 1.5f, source.width() / 2, source.height() / 2);
1947canvas->concat(matrix);
1948canvas->drawBitmap(source, 0, 0);
1949##
1950
1951#SeeAlso postScale setScale MakeScale
1952
1953#Method ##
1954
1955# ------------------------------------------------------------------------------
1956
1957#Method void preScale(SkScalar sx, SkScalar sy)
1958
1959Sets Matrix to Matrix multiplied by Matrix constructed from scaling by (sx, sy)
1960about pivot point (0, 0).
1961This can be thought of as scaling about the origin before applying Matrix.
1962
1963Given:
1964
1965#Code
1966#Literal
1967         | A B C |               | sx  0  0 |
1968Matrix = | D E F |,  S(sx, sy) = |  0 sy  0 |
1969         | G H I |               |  0  0  1 |
1970##
1971
1972sets Matrix to:
1973
1974#Code
1975#Literal
1976                     | A B C | | sx  0  0 |   | A*sx B*sy C |
1977Matrix * S(sx, sy) = | D E F | |  0 sy  0 | = | D*sx E*sy F |
1978                     | G H I | |  0  0  1 |   | G*sx H*sy I |
1979##
1980
1981#Param sx  horizontal scale factor ##
1982#Param sy  vertical scale factor ##
1983
1984#Example
1985#Image 3
1986SkMatrix matrix;
1987SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
1988SkRect::Make(source.bounds()).toQuad(bitmapBounds);
1989matrix.setPolyToPoly(bitmapBounds, perspect, 4);
1990matrix.preScale(.75f, 1.5f);
1991canvas->concat(matrix);
1992canvas->drawBitmap(source, 0, 0);
1993##
1994
1995#SeeAlso postScale setScale MakeScale
1996
1997#Method ##
1998
1999# ------------------------------------------------------------------------------
2000
2001#Method void preRotate(SkScalar degrees, SkScalar px, SkScalar py)
2002
2003#Line # pre-multiplies Matrix by rotation ##
2004Sets Matrix to Matrix multiplied by Matrix constructed from rotating by degrees
2005about pivot point (px, py).
2006This can be thought of as rotating about a pivot point before applying Matrix.
2007
2008Positive degrees rotates clockwise.
2009
2010Given:
2011
2012#Code
2013#Literal
2014         | A B C |                        | c -s dx |
2015Matrix = | D E F |,  R(degrees, px, py) = | s  c dy |
2016         | G H I |                        | 0  0  1 |
2017##
2018
2019where
2020
2021#Code
2022#Literal
2023c  = cos(degrees)
2024s  = sin(degrees)
2025dx =  s * py + (1 - c) * px
2026dy = -s * px + (1 - c) * py
2027##
2028
2029sets Matrix to:
2030
2031#Code
2032#Literal
2033                              | A B C | | c -s dx |   | Ac+Bs -As+Bc A*dx+B*dy+C |
2034Matrix * R(degrees, px, py) = | D E F | | s  c dy | = | Dc+Es -Ds+Ec D*dx+E*dy+F |
2035                              | G H I | | 0  0  1 |   | Gc+Hs -Gs+Hc G*dx+H*dy+I |
2036##
2037
2038#Param degrees  angle of axes relative to upright axes ##
2039#Param px  pivot x ##
2040#Param py  pivot y ##
2041
2042#Example
2043#Image 3
2044SkMatrix matrix;
2045SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
2046SkRect::Make(source.bounds()).toQuad(bitmapBounds);
2047matrix.setPolyToPoly(bitmapBounds, perspect, 4);
2048matrix.preRotate(45, source.width() / 2, source.height() / 2);
2049canvas->concat(matrix);
2050canvas->drawBitmap(source, 0, 0);
2051##
2052
2053#SeeAlso postRotate setRotate
2054
2055#Method ##
2056
2057# ------------------------------------------------------------------------------
2058
2059#Method void preRotate(SkScalar degrees)
2060
2061Sets Matrix to Matrix multiplied by Matrix constructed from rotating by degrees
2062about pivot point (0, 0).
2063This can be thought of as rotating about the origin before applying Matrix.
2064
2065Positive degrees rotates clockwise.
2066
2067Given:
2068
2069#Code
2070#Literal
2071         | A B C |                        | c -s 0 |
2072Matrix = | D E F |,  R(degrees, px, py) = | s  c 0 |
2073         | G H I |                        | 0  0 1 |
2074##
2075
2076where
2077
2078#Code
2079#Literal
2080c  = cos(degrees)
2081s  = sin(degrees)
2082##
2083
2084sets Matrix to:
2085
2086#Code
2087#Literal
2088                              | A B C | | c -s 0 |   | Ac+Bs -As+Bc C |
2089Matrix * R(degrees, px, py) = | D E F | | s  c 0 | = | Dc+Es -Ds+Ec F |
2090                              | G H I | | 0  0 1 |   | Gc+Hs -Gs+Hc I |
2091##
2092
2093#Param degrees  angle of axes relative to upright axes ##
2094
2095#Example
2096#Image 3
2097SkMatrix matrix;
2098SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
2099SkRect::Make(source.bounds()).toQuad(bitmapBounds);
2100matrix.setPolyToPoly(bitmapBounds, perspect, 4);
2101matrix.preRotate(45);
2102canvas->concat(matrix);
2103canvas->drawBitmap(source, 0, 0);
2104##
2105
2106#SeeAlso postRotate setRotate
2107
2108#Method ##
2109
2110# ------------------------------------------------------------------------------
2111
2112#Method void preSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py)
2113
2114#Line # pre-multiplies Matrix by skew ##
2115Sets Matrix to Matrix multiplied by Matrix constructed from skewing by (kx, ky)
2116about pivot point (px, py).
2117This can be thought of as skewing about a pivot point before applying Matrix.
2118
2119Given:
2120
2121#Code
2122#Literal
2123         | A B C |                       |  1 kx dx |
2124Matrix = | D E F |,  K(kx, ky, px, py) = | ky  1 dy |
2125         | G H I |                       |  0  0  1 |
2126##
2127
2128where
2129
2130#Code
2131#Literal
2132dx = -kx * py
2133dy = -ky * px
2134##
2135
2136sets Matrix to:
2137
2138#Code
2139#Literal
2140                             | A B C | |  1 kx dx |   | A+B*ky A*kx+B A*dx+B*dy+C |
2141Matrix * K(kx, ky, px, py) = | D E F | | ky  1 dy | = | D+E*ky D*kx+E D*dx+E*dy+F |
2142                             | G H I | |  0  0  1 |   | G+H*ky G*kx+H G*dx+H*dy+I |
2143##
2144
2145#Param kx  horizontal skew factor ##
2146#Param ky  vertical skew factor ##
2147#Param px  pivot x ##
2148#Param py  pivot y ##
2149
2150#Example
2151#Image 3
2152SkMatrix matrix;
2153SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
2154SkRect::Make(source.bounds()).toQuad(bitmapBounds);
2155matrix.setPolyToPoly(bitmapBounds, perspect, 4);
2156matrix.preSkew(.5f, 0, source.width() / 2, source.height() / 2);
2157canvas->concat(matrix);
2158canvas->drawBitmap(source, 0, 0);
2159##
2160
2161#SeeAlso postSkew setSkew
2162
2163#Method ##
2164
2165# ------------------------------------------------------------------------------
2166
2167#Method void preSkew(SkScalar kx, SkScalar ky)
2168
2169Sets Matrix to Matrix multiplied by Matrix constructed from skewing by (kx, ky)
2170about pivot point (0, 0).
2171This can be thought of as skewing about the origin before applying Matrix.
2172
2173Given:
2174
2175#Code
2176#Literal
2177         | A B C |               |  1 kx 0 |
2178Matrix = | D E F |,  K(kx, ky) = | ky  1 0 |
2179         | G H I |               |  0  0 1 |
2180##
2181
2182sets Matrix to:
2183
2184#Code
2185#Literal
2186                     | A B C | |  1 kx 0 |   | A+B*ky A*kx+B C |
2187Matrix * K(kx, ky) = | D E F | | ky  1 0 | = | D+E*ky D*kx+E F |
2188                     | G H I | |  0  0 1 |   | G+H*ky G*kx+H I |
2189##
2190
2191#Param kx  horizontal skew factor ##
2192#Param ky  vertical skew factor ##
2193
2194#Example
2195#Image 3
2196SkMatrix matrix;
2197SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
2198SkRect::Make(source.bounds()).toQuad(bitmapBounds);
2199matrix.setPolyToPoly(bitmapBounds, perspect, 4);
2200matrix.preSkew(.5f, 0);
2201canvas->concat(matrix);
2202canvas->drawBitmap(source, 0, 0);
2203##
2204
2205#SeeAlso postSkew setSkew
2206
2207#Method ##
2208
2209# ------------------------------------------------------------------------------
2210
2211#Method void preConcat(const SkMatrix& other)
2212
2213#Line # pre-multiplies Matrix by Matrix parameter ##
2214Sets Matrix to Matrix multiplied by Matrix other.
2215This can be thought of mapping by other before applying Matrix.
2216
2217Given:
2218
2219#Code
2220#Literal
2221         | A B C |          | J K L |
2222Matrix = | D E F |, other = | M N O |
2223         | G H I |          | P Q R |
2224##
2225
2226sets Matrix to:
2227
2228#Code
2229#Literal
2230                 | A B C |   | J K L |   | AJ+BM+CP AK+BN+CQ AL+BO+CR |
2231Matrix * other = | D E F | * | M N O | = | DJ+EM+FP DK+EN+FQ DL+EO+FR |
2232                 | G H I |   | P Q R |   | GJ+HM+IP GK+HN+IQ GL+HO+IR |
2233##
2234
2235#Param other  Matrix on right side of multiply expression ##
2236
2237#Example
2238#Image 3
2239#Description
2240setPolyToPoly creates perspective matrices, one the inverse of the other.
2241Multiplying the matrix by its inverse turns into an identity matrix.
2242##
2243SkMatrix matrix, matrix2;
2244SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
2245SkRect::Make(source.bounds()).toQuad(bitmapBounds);
2246matrix.setPolyToPoly(bitmapBounds, perspect, 4);
2247matrix2.setPolyToPoly(perspect, bitmapBounds, 4);
2248matrix.preConcat(matrix2);
2249canvas->concat(matrix);
2250canvas->drawBitmap(source, 0, 0);
2251##
2252
2253#SeeAlso postConcat setConcat Concat
2254
2255#Method ##
2256
2257# ------------------------------------------------------------------------------
2258
2259#Method void postTranslate(SkScalar dx, SkScalar dy)
2260
2261#Line # post-multiplies Matrix by translation ##
2262Sets Matrix to Matrix constructed from translation (dx, dy) multiplied by Matrix.
2263This can be thought of as moving the point to be mapped after applying Matrix.
2264
2265Given:
2266
2267#Code
2268#Literal
2269         | J K L |               | 1 0 dx |
2270Matrix = | M N O |,  T(dx, dy) = | 0 1 dy |
2271         | P Q R |               | 0 0  1 |
2272##
2273
2274sets Matrix to:
2275
2276#Code
2277#Literal
2278                     | 1 0 dx | | J K L |   | J+dx*P K+dx*Q L+dx*R |
2279T(dx, dy) * Matrix = | 0 1 dy | | M N O | = | M+dy*P N+dy*Q O+dy*R |
2280                     | 0 0  1 | | P Q R |   |      P      Q      R |
2281##
2282
2283#Param dx  x translation after applying Matrix ##
2284#Param dy  y translation after applying Matrix ##
2285
2286#Example
2287#Height 160
2288#Description
2289Compare with preTranslate example.
2290##
2291    SkPaint paint;
2292    paint.setAntiAlias(true);
2293    SkRect rect = {20, 20, 100, 100};
2294    for (int i = 0; i < 2; ++i ) {
2295        SkMatrix matrix;
2296        i == 0 ? matrix.reset(): matrix.setRotate(25, rect.centerX(), 320);
2297        {
2298            SkAutoCanvasRestore acr(canvas, true);
2299            canvas->concat(matrix);
2300            paint.setColor(SK_ColorGRAY);
2301            canvas->drawRect(rect, paint);
2302        }
2303        paint.setColor(SK_ColorRED);
2304        for (int j = 0; j < 2; ++j ) {
2305            SkAutoCanvasRestore acr(canvas, true);
2306            matrix.postTranslate(40, 40);
2307            canvas->concat(matrix);
2308            canvas->drawCircle(0, 0, 3, paint);
2309        }
2310    }
2311##
2312
2313#SeeAlso preTranslate setTranslate MakeTrans
2314
2315#Method ##
2316
2317# ------------------------------------------------------------------------------
2318
2319#Method void postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py)
2320
2321#Line # post-multiplies Matrix by scale ##
2322Sets Matrix to Matrix constructed from scaling by (sx, sy) about pivot point
2323(px, py), multiplied by Matrix.
2324This can be thought of as scaling about a pivot point after applying Matrix.
2325
2326Given:
2327
2328#Code
2329#Literal
2330         | J K L |                       | sx  0 dx |
2331Matrix = | M N O |,  S(sx, sy, px, py) = |  0 sy dy |
2332         | P Q R |                       |  0  0  1 |
2333##
2334
2335where
2336
2337#Code
2338#Literal
2339dx = px - sx * px
2340dy = py - sy * py
2341##
2342
2343sets Matrix to:
2344
2345#Code
2346#Literal
2347                             | sx  0 dx | | J K L |   | sx*J+dx*P sx*K+dx*Q sx*L+dx+R |
2348S(sx, sy, px, py) * Matrix = |  0 sy dy | | M N O | = | sy*M+dy*P sy*N+dy*Q sy*O+dy*R |
2349                             |  0  0  1 | | P Q R |   |         P         Q         R |
2350##
2351
2352#Param sx  horizontal scale factor ##
2353#Param sy  vertical scale factor ##
2354#Param px  pivot x ##
2355#Param py  pivot y ##
2356
2357#Example
2358#Image 3
2359SkMatrix matrix;
2360SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
2361SkRect::Make(source.bounds()).toQuad(bitmapBounds);
2362matrix.setPolyToPoly(bitmapBounds, perspect, 4);
2363matrix.postScale(.75f, 1.5f, source.width() / 2, source.height() / 2);
2364canvas->concat(matrix);
2365canvas->drawBitmap(source, 0, 0);
2366##
2367
2368#SeeAlso preScale setScale MakeScale
2369
2370##
2371
2372# ------------------------------------------------------------------------------
2373
2374#Method void postScale(SkScalar sx, SkScalar sy)
2375
2376Sets Matrix to Matrix constructed from scaling by (sx, sy) about pivot point
2377(0, 0), multiplied by Matrix.
2378This can be thought of as scaling about the origin after applying Matrix.
2379
2380Given:
2381
2382#Code
2383#Literal
2384         | J K L |               | sx  0  0 |
2385Matrix = | M N O |,  S(sx, sy) = |  0 sy  0 |
2386         | P Q R |               |  0  0  1 |
2387##
2388
2389sets Matrix to:
2390
2391#Code
2392#Literal
2393                     | sx  0  0 | | J K L |   | sx*J sx*K sx*L |
2394S(sx, sy) * Matrix = |  0 sy  0 | | M N O | = | sy*M sy*N sy*O |
2395                     |  0  0  1 | | P Q R |   |    P    Q    R |
2396##
2397
2398#Param sx  horizontal scale factor ##
2399#Param sy  vertical scale factor ##
2400
2401#Example
2402#Image 3
2403SkMatrix matrix;
2404SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
2405SkRect::Make(source.bounds()).toQuad(bitmapBounds);
2406matrix.setPolyToPoly(bitmapBounds, perspect, 4);
2407matrix.postScale(.75f, 1.5f);
2408canvas->concat(matrix);
2409canvas->drawBitmap(source, 0, 0);
2410##
2411
2412#SeeAlso preScale setScale MakeScale
2413
2414##
2415
2416# ------------------------------------------------------------------------------
2417
2418#Method bool postIDiv(int divx, int divy)
2419
2420#Line # post-multiplies Matrix by inverse scale ##
2421Sets Matrix to Matrix constructed from scaling by
2422#Formula
2423(1/divx, 1/divy)
2424##
2425about pivot point (px, py), multiplied by Matrix.
2426
2427Returns false if either divx or divy is zero.
2428
2429Given:
2430
2431#Code
2432#Literal
2433         | J K L |                   | sx  0  0 |
2434Matrix = | M N O |,  I(divx, divy) = |  0 sy  0 |
2435         | P Q R |                   |  0  0  1 |
2436##
2437
2438where
2439
2440#Code
2441#Literal
2442sx = 1 / divx
2443sy = 1 / divy
2444##
2445
2446sets Matrix to:
2447
2448#Code
2449#Literal
2450                         | sx  0  0 | | J K L |   | sx*J sx*K sx*L |
2451I(divx, divy) * Matrix = |  0 sy  0 | | M N O | = | sy*M sy*N sy*O |
2452                         |  0  0  1 | | P Q R |   |    P    Q    R |
2453##
2454
2455#Param divx  integer divisor for inverse scale in x ##
2456#Param divy  integer divisor for inverse scale in y ##
2457
2458#Return  true on successful scale ##
2459
2460#Example
2461#Image 3
2462SkMatrix matrix, matrix2;
2463SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
2464SkRect::Make(source.bounds()).toQuad(bitmapBounds);
2465matrix.setPolyToPoly(bitmapBounds, perspect, 4);
2466matrix.postIDiv(1, 2);
2467canvas->concat(matrix);
2468canvas->drawBitmap(source, 0, 0);
2469##
2470
2471#SeeAlso postScale MakeScale
2472
2473##
2474
2475# ------------------------------------------------------------------------------
2476
2477#Method void postRotate(SkScalar degrees, SkScalar px, SkScalar py)
2478
2479#Line # post-multiplies Matrix by rotation ##
2480Sets Matrix to Matrix constructed from rotating by degrees about pivot point
2481(px, py), multiplied by Matrix.
2482This can be thought of as rotating about a pivot point after applying Matrix.
2483
2484Positive degrees rotates clockwise.
2485
2486Given:
2487
2488#Code
2489#Literal
2490         | J K L |                        | c -s dx |
2491Matrix = | M N O |,  R(degrees, px, py) = | s  c dy |
2492         | P Q R |                        | 0  0  1 |
2493##
2494
2495where
2496
2497#Code
2498#Literal
2499c  = cos(degrees)
2500s  = sin(degrees)
2501dx =  s * py + (1 - c) * px
2502dy = -s * px + (1 - c) * py
2503##
2504
2505sets Matrix to:
2506
2507#Code
2508#Literal
2509                              |c -s dx| |J K L|   |cJ-sM+dx*P cK-sN+dx*Q cL-sO+dx+R|
2510R(degrees, px, py) * Matrix = |s  c dy| |M N O| = |sJ+cM+dy*P sK+cN+dy*Q sL+cO+dy*R|
2511                              |0  0  1| |P Q R|   |         P          Q          R|
2512##
2513
2514#Param degrees  angle of axes relative to upright axes ##
2515#Param px  pivot x ##
2516#Param py  pivot y ##
2517
2518#Example
2519#Image 3
2520SkMatrix matrix;
2521SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
2522SkRect::Make(source.bounds()).toQuad(bitmapBounds);
2523matrix.setPolyToPoly(bitmapBounds, perspect, 4);
2524matrix.postRotate(45, source.width() / 2, source.height() / 2);
2525canvas->concat(matrix);
2526canvas->drawBitmap(source, 0, 0);
2527##
2528
2529#SeeAlso preRotate setRotate
2530
2531##
2532
2533# ------------------------------------------------------------------------------
2534
2535#Method void postRotate(SkScalar degrees)
2536
2537Sets Matrix to Matrix constructed from rotating by degrees about pivot point
2538(0, 0), multiplied by Matrix.
2539This can be thought of as rotating about the origin after applying Matrix.
2540
2541Positive degrees rotates clockwise.
2542
2543Given:
2544
2545#Code
2546#Literal
2547         | J K L |                        | c -s 0 |
2548Matrix = | M N O |,  R(degrees, px, py) = | s  c 0 |
2549         | P Q R |                        | 0  0 1 |
2550##
2551
2552where
2553
2554#Code
2555#Literal
2556c  = cos(degrees)
2557s  = sin(degrees)
2558##
2559
2560sets Matrix to:
2561
2562#Code
2563#Literal
2564                              | c -s dx | | J K L |   | cJ-sM cK-sN cL-sO |
2565R(degrees, px, py) * Matrix = | s  c dy | | M N O | = | sJ+cM sK+cN sL+cO |
2566                              | 0  0  1 | | P Q R |   |     P     Q     R |
2567##
2568
2569#Param degrees  angle of axes relative to upright axes ##
2570
2571#Example
2572#Image 3
2573SkMatrix matrix;
2574SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
2575SkRect::Make(source.bounds()).toQuad(bitmapBounds);
2576matrix.setPolyToPoly(bitmapBounds, perspect, 4);
2577matrix.postRotate(45);
2578canvas->concat(matrix);
2579canvas->drawBitmap(source, 0, 0);
2580##
2581
2582#SeeAlso preRotate setRotate
2583
2584##
2585
2586# ------------------------------------------------------------------------------
2587
2588#Method void postSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py)
2589
2590#Line # post-multiplies Matrix by skew ##
2591Sets Matrix to Matrix constructed from skewing by (kx, ky) about pivot point
2592(px, py), multiplied by Matrix.
2593This can be thought of as skewing about a pivot point after applying Matrix.
2594
2595Given:
2596
2597#Code
2598#Literal
2599         | J K L |                       |  1 kx dx |
2600Matrix = | M N O |,  K(kx, ky, px, py) = | ky  1 dy |
2601         | P Q R |                       |  0  0  1 |
2602##
2603
2604where
2605
2606#Code
2607#Literal
2608dx = -kx * py
2609dy = -ky * px
2610##
2611
2612sets Matrix to:
2613
2614#Code
2615#Literal
2616                             | 1 kx dx| |J K L|   |J+kx*M+dx*P K+kx*N+dx*Q L+kx*O+dx+R|
2617K(kx, ky, px, py) * Matrix = |ky  1 dy| |M N O| = |ky*J+M+dy*P ky*K+N+dy*Q ky*L+O+dy*R|
2618                             | 0  0  1| |P Q R|   |          P           Q           R|
2619##
2620
2621#Param kx  horizontal skew factor ##
2622#Param ky  vertical skew factor ##
2623#Param px  pivot x ##
2624#Param py  pivot y ##
2625
2626#Example
2627#Image 3
2628SkMatrix matrix;
2629SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
2630SkRect::Make(source.bounds()).toQuad(bitmapBounds);
2631matrix.setPolyToPoly(bitmapBounds, perspect, 4);
2632matrix.postSkew(.5f, 0, source.width() / 2, source.height() / 2);
2633canvas->concat(matrix);
2634canvas->drawBitmap(source, 0, 0);
2635##
2636
2637#SeeAlso preSkew setSkew
2638
2639##
2640
2641# ------------------------------------------------------------------------------
2642
2643#Method void postSkew(SkScalar kx, SkScalar ky)
2644
2645Sets Matrix to Matrix constructed from skewing by (kx, ky) about pivot point
2646(0, 0), multiplied by Matrix.
2647This can be thought of as skewing about the origin after applying Matrix.
2648
2649Given:
2650
2651#Code
2652#Literal
2653         | J K L |               |  1 kx 0 |
2654Matrix = | M N O |,  K(kx, ky) = | ky  1 0 |
2655         | P Q R |               |  0  0 1 |
2656##
2657
2658sets Matrix to:
2659
2660#Code
2661#Literal
2662                     |  1 kx 0 | | J K L |   | J+kx*M K+kx*N L+kx*O |
2663K(kx, ky) * Matrix = | ky  1 0 | | M N O | = | ky*J+M ky*K+N ky*L+O |
2664                     |  0  0 1 | | P Q R |   |      P      Q      R |
2665##
2666
2667#Param kx  horizontal skew factor ##
2668#Param ky  vertical skew factor ##
2669
2670#Example
2671#Image 3
2672SkMatrix matrix;
2673SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
2674SkRect::Make(source.bounds()).toQuad(bitmapBounds);
2675matrix.setPolyToPoly(bitmapBounds, perspect, 4);
2676matrix.postSkew(.5f, 0);
2677canvas->concat(matrix);
2678canvas->drawBitmap(source, 0, 0);
2679##
2680
2681#SeeAlso preSkew setSkew
2682
2683##
2684
2685# ------------------------------------------------------------------------------
2686
2687#Method void postConcat(const SkMatrix& other)
2688
2689#Line # post-multiplies Matrix by Matrix parameter ##
2690Sets Matrix to Matrix other multiplied by Matrix.
2691This can be thought of mapping by other after applying Matrix.
2692
2693Given:
2694
2695#Code
2696#Literal
2697         | J K L |           | A B C |
2698Matrix = | M N O |,  other = | D E F |
2699         | P Q R |           | G H I |
2700##
2701
2702sets Matrix to:
2703
2704#Code
2705#Literal
2706                 | A B C |   | J K L |   | AJ+BM+CP AK+BN+CQ AL+BO+CR |
2707other * Matrix = | D E F | * | M N O | = | DJ+EM+FP DK+EN+FQ DL+EO+FR |
2708                 | G H I |   | P Q R |   | GJ+HM+IP GK+HN+IQ GL+HO+IR |
2709##
2710
2711#Param other  Matrix on left side of multiply expression ##
2712
2713#Example
2714#Image 3
2715#Height 64
2716SkMatrix matrix, matrix2;
2717SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
2718SkRect::Make(source.bounds()).toQuad(bitmapBounds);
2719matrix.setPolyToPoly(bitmapBounds, perspect, 4);
2720matrix.postConcat(matrix);
2721canvas->concat(matrix);
2722canvas->drawBitmap(source, 0, 0);
2723##
2724
2725#SeeAlso preConcat setConcat Concat
2726
2727##
2728
2729# ------------------------------------------------------------------------------
2730
2731#Enum ScaleToFit
2732
2733#Code
2734    enum ScaleToFit {
2735        kFill_ScaleToFit,
2736        kStart_ScaleToFit,
2737        kCenter_ScaleToFit,
2738        kEnd_ScaleToFit,
2739    };
2740##
2741
2742ScaleToFit describes how Matrix is constructed to map one Rect to another.
2743ScaleToFit may allow Matrix to have unequal horizontal and vertical scaling,
2744or may restrict Matrix to square scaling. If restricted, ScaleToFit specifies
2745how Matrix maps to the side or center of the destination Rect.
2746
2747#Const kFill_ScaleToFit 0
2748    Computes Matrix that scales in x and y independently, so that source Rect is
2749    mapped to completely fill destination Rect. The aspect ratio of source Rect
2750    may change.
2751##
2752#Const kStart_ScaleToFit 1
2753    Computes Matrix that maintains source Rect aspect ratio, mapping source Rect
2754    width or height to destination Rect. Aligns mapping to left and top edges
2755    of destination Rect.
2756##
2757#Const kCenter_ScaleToFit 2
2758    Computes Matrix that maintains source Rect aspect ratio, mapping source Rect
2759    width or height to destination Rect. Aligns mapping to center of destination
2760    Rect.
2761##
2762#Const kEnd_ScaleToFit 3
2763    Computes Matrix that maintains source Rect aspect ratio, mapping source Rect
2764    width or height to destination Rect. Aligns mapping to right and bottom
2765    edges of destination Rect.
2766##
2767
2768#Example
2769   const char* labels[] = { "Fill", "Start", "Center", "End" };
2770   SkRect rects[] = {{5, 5, 59, 59}, {5, 74, 59, 108}, {10, 123, 44, 172}, {10, 187, 54, 231}};
2771   SkRect bounds;
2772   source.getBounds(&bounds);
2773   SkPaint paint;
2774   paint.setAntiAlias(true);
2775   for (auto fit : { SkMatrix::kFill_ScaleToFit, SkMatrix::kStart_ScaleToFit,
2776                     SkMatrix::kCenter_ScaleToFit, SkMatrix::kEnd_ScaleToFit } ) {
2777       for (auto rect : rects ) {
2778           canvas->drawRect(rect, paint);
2779           SkMatrix matrix;
2780           if (!matrix.setRectToRect(bounds, rect, fit)) {
2781               continue;
2782           }
2783           SkAutoCanvasRestore acr(canvas, true);
2784           canvas->concat(matrix);
2785           canvas->drawBitmap(source, 0, 0);
2786       }
2787       canvas->drawString(labels[fit], 10, 255, paint);
2788       canvas->translate(64, 0);
2789   }
2790##
2791
2792#SeeAlso setRectToRect MakeRectToRect setPolyToPoly
2793
2794##
2795
2796# ------------------------------------------------------------------------------
2797
2798#Method bool setRectToRect(const SkRect& src, const SkRect& dst, ScaleToFit stf)
2799
2800#Line # sets to map one Rect to another ##
2801Sets Matrix to scale and translate src Rect to dst Rect. stf selects whether
2802mapping completely fills dst or preserves the aspect ratio, and how to align
2803src within dst. Returns false if src is empty, and sets Matrix to identity.
2804Returns true if dst is empty, and sets Matrix to:
2805
2806#Code
2807#Literal
2808| 0 0 0 |
2809| 0 0 0 |
2810| 0 0 1 |
2811##
2812
2813#Param src  Rect to map from ##
2814#Param dst  Rect to map to ##
2815#Param stf  one of: kFill_ScaleToFit, kStart_ScaleToFit,
2816                    kCenter_ScaleToFit, kEnd_ScaleToFit
2817##
2818
2819#Return  true if Matrix can represent Rect mapping ##
2820
2821#Example
2822    const SkRect srcs[] = { {0, 0, 0, 0}, {1, 2, 3, 4} };
2823    const SkRect dsts[] = { {0, 0, 0, 0}, {5, 6, 8, 9} };
2824    for (auto src : srcs) {
2825        for (auto dst : dsts) {
2826             SkMatrix matrix;
2827             matrix.setAll(-1, -1, -1, -1, -1, -1, -1, -1, -1);
2828             bool success = matrix.setRectToRect(src, dst, SkMatrix::kFill_ScaleToFit);
2829             SkDebugf("src: %g, %g, %g, %g  dst: %g, %g, %g, %g  success: %s\n",
2830                      src.fLeft, src.fTop, src.fRight, src.fBottom,
2831                      dst.fLeft, dst.fTop, dst.fRight, dst.fBottom, success ? "true" : "false");
2832             matrix.dump();
2833        }
2834    }
2835#StdOut
2836src: 0, 0, 0, 0  dst: 0, 0, 0, 0  success: false
2837[  1.0000   0.0000   0.0000][  0.0000   1.0000   0.0000][  0.0000   0.0000   1.0000]
2838src: 0, 0, 0, 0  dst: 5, 6, 8, 9  success: false
2839[  1.0000   0.0000   0.0000][  0.0000   1.0000   0.0000][  0.0000   0.0000   1.0000]
2840src: 1, 2, 3, 4  dst: 0, 0, 0, 0  success: true
2841[  0.0000   0.0000   0.0000][  0.0000   0.0000   0.0000][  0.0000   0.0000   1.0000]
2842src: 1, 2, 3, 4  dst: 5, 6, 8, 9  success: true
2843[  1.5000   0.0000   3.5000][  0.0000   1.5000   3.0000][  0.0000   0.0000   1.0000]
2844##
2845##
2846
2847#SeeAlso MakeRectToRect ScaleToFit setPolyToPoly SkRect::isEmpty
2848
2849##
2850
2851# ------------------------------------------------------------------------------
2852
2853#Method static SkMatrix MakeRectToRect(const SkRect& src, const SkRect& dst, ScaleToFit stf)
2854
2855#Line # constructs from source Rect to destination Rect ##
2856Returns Matrix set to scale and translate src Rect to dst Rect. stf selects
2857whether mapping completely fills dst or preserves the aspect ratio, and how to
2858align src within dst. Returns the identity Matrix if src is empty. If dst is
2859empty, returns Matrix set to:
2860
2861#Code
2862#Literal
2863| 0 0 0 |
2864| 0 0 0 |
2865| 0 0 1 |
2866##
2867
2868#Param src  Rect to map from ##
2869#Param dst  Rect to map to ##
2870#Param stf  one of: kFill_ScaleToFit, kStart_ScaleToFit,
2871                    kCenter_ScaleToFit, kEnd_ScaleToFit
2872##
2873
2874#Return  Matrix mapping src to dst ##
2875
2876#Example
2877    const SkRect srcs[] = { {0, 0, 0, 0}, {1, 2, 3, 4} };
2878    const SkRect dsts[] = { {0, 0, 0, 0}, {5, 6, 8, 9} };
2879    for (auto src : srcs) {
2880        for (auto dst : dsts) {
2881             SkMatrix matrix = SkMatrix::MakeRectToRect(src, dst, SkMatrix::kFill_ScaleToFit);
2882             SkDebugf("src: %g, %g, %g, %g  dst: %g, %g, %g, %g\n",
2883                      src.fLeft, src.fTop, src.fRight, src.fBottom,
2884                      dst.fLeft, dst.fTop, dst.fRight, dst.fBottom);
2885             matrix.dump();
2886        }
2887    }
2888#StdOut
2889src: 0, 0, 0, 0  dst: 0, 0, 0, 0
2890[  1.0000   0.0000   0.0000][  0.0000   1.0000   0.0000][  0.0000   0.0000   1.0000]
2891src: 0, 0, 0, 0  dst: 5, 6, 8, 9
2892[  1.0000   0.0000   0.0000][  0.0000   1.0000   0.0000][  0.0000   0.0000   1.0000]
2893src: 1, 2, 3, 4  dst: 0, 0, 0, 0
2894[  0.0000   0.0000   0.0000][  0.0000   0.0000   0.0000][  0.0000   0.0000   1.0000]
2895src: 1, 2, 3, 4  dst: 5, 6, 8, 9
2896[  1.5000   0.0000   3.5000][  0.0000   1.5000   3.0000][  0.0000   0.0000   1.0000]
2897##
2898##
2899
2900#SeeAlso setRectToRect ScaleToFit setPolyToPoly SkRect::isEmpty
2901
2902##
2903
2904# ------------------------------------------------------------------------------
2905
2906#Method bool setPolyToPoly(const SkPoint src[], const SkPoint dst[], int count)
2907
2908#Line # sets to map one to four points to an equal array of points ##
2909Sets Matrix to map src to dst. count must be zero or greater, and four or less.
2910
2911If count is zero, sets Matrix to identity and returns true.
2912If count is one, sets Matrix to translate and returns true.
2913If count is two or more, sets Matrix to map Points if possible; returns false
2914if Matrix cannot be constructed. If count is four, Matrix may include
2915perspective.
2916
2917#Param src  Points to map from ##
2918#Param dst  Points to map to ##
2919#Param count  number of Points in src and dst ##
2920
2921#Return  true if Matrix was constructed successfully
2922##
2923
2924#Example
2925    const SkPoint src[] = { { 0, 0}, {30,   0}, {30, -30}, { 0, -30} };
2926    const SkPoint dst[] = { {50, 0}, {80, -10}, {90, -30}, {60, -40} };
2927    SkPaint blackPaint;
2928    blackPaint.setAntiAlias(true);
2929    blackPaint.setTextSize(42);
2930    SkPaint redPaint = blackPaint;
2931    redPaint.setColor(SK_ColorRED);
2932    for (int count : { 1, 2, 3, 4 } ) {
2933        canvas->translate(35, 55);
2934        for (int index = 0; index < count; ++index) {
2935            canvas->drawCircle(src[index], 3, blackPaint);
2936            canvas->drawCircle(dst[index], 3, blackPaint);
2937            if (index > 0) {
2938                canvas->drawLine(src[index], src[index - 1], blackPaint);
2939                canvas->drawLine(dst[index], dst[index - 1], blackPaint);
2940            }
2941        }
2942        SkMatrix matrix;
2943        matrix.setPolyToPoly(src, dst, count);
2944        canvas->drawString("A", src[0].fX, src[0].fY, redPaint);
2945        SkAutoCanvasRestore acr(canvas, true);
2946        canvas->concat(matrix);
2947        canvas->drawString("A", src[0].fX, src[0].fY, redPaint);
2948    }
2949##
2950
2951#SeeAlso setRectToRect MakeRectToRect
2952
2953##
2954
2955# ------------------------------------------------------------------------------
2956
2957#Method bool SK_WARN_UNUSED_RESULT invert(SkMatrix* inverse) const
2958
2959#Line # returns inverse, if possible ##
2960Sets inverse to reciprocal matrix, returning true if Matrix can be inverted.
2961Geometrically, if Matrix maps from source to destination, inverse Matrix
2962maps from destination to source. If Matrix can not be inverted, inverse is
2963unchanged.
2964
2965#Param inverse  storage for inverted Matrix; may be nullptr ##
2966
2967#Return  true if Matrix can be inverted ##
2968
2969#Example
2970#Height 128
2971    const SkPoint src[] = { { 10, 120}, {120, 120}, {120, 10}, {  10, 10} };
2972    const SkPoint dst[] = { {150, 120}, {200, 100}, {240, 30}, { 130, 40} };
2973    SkPaint paint;
2974    paint.setAntiAlias(true);
2975    SkMatrix matrix;
2976    matrix.setPolyToPoly(src, dst, 4);
2977    canvas->drawPoints(SkCanvas::kPolygon_PointMode, 4, src, paint);
2978    canvas->drawPoints(SkCanvas::kPolygon_PointMode, 4, dst, paint);
2979    paint.setColor(SK_ColorBLUE);
2980    paint.setStrokeWidth(3);
2981    paint.setStrokeCap(SkPaint::kRound_Cap);
2982    canvas->drawPoints(SkCanvas::kPoints_PointMode, 4, dst, paint);
2983    matrix.invert(&matrix);
2984    canvas->concat(matrix);
2985    canvas->drawPoints(SkCanvas::kPoints_PointMode, 4, dst, paint);
2986##
2987
2988#SeeAlso Concat
2989
2990##
2991
2992# ------------------------------------------------------------------------------
2993
2994#Method static void SetAffineIdentity(SkScalar affine[6])
2995
2996#Line # sets 3x2 array to identity ##
2997Fills affine with identity values in column major order.
2998Sets affine to:
2999
3000#Code
3001#Literal
3002| 1 0 0 |
3003| 0 1 0 |
3004##
3005
3006Affine 3x2 matrices in column major order are used by OpenGL and XPS.
3007
3008#Param affine  storage for 3x2 affine matrix ##
3009
3010#Example
3011    SkScalar affine[6];
3012    SkMatrix::SetAffineIdentity(affine);
3013    const char* names[] = { "ScaleX", "SkewY", "SkewX", "ScaleY", "TransX", "TransY" };
3014    for (int i = 0; i < 6; ++i) {
3015        SkDebugf("%s: %g ", names[i], affine[i]);
3016    }
3017    SkDebugf("\n");
3018#StdOut
3019ScaleX: 1 SkewY: 0 SkewX: 0 ScaleY: 1 TransX: 0 TransY: 0
3020##
3021##
3022
3023#SeeAlso setAffine asAffine
3024
3025##
3026
3027# ------------------------------------------------------------------------------
3028
3029#Method bool SK_WARN_UNUSED_RESULT asAffine(SkScalar affine[6]) const
3030
3031#Line # copies to 3x2 array ##
3032Fills affine in column major order. Sets affine to:
3033
3034#Code
3035#Literal
3036| scale-x  skew-x translate-x |
3037| skew-y  scale-y translate-y |
3038##
3039
3040If Matrix contains perspective, returns false and leaves affine unchanged.
3041
3042#Param affine  storage for 3x2 affine matrix; may be nullptr ##
3043
3044#Return  true if Matrix does not contain perspective ##
3045
3046#Example
3047SkMatrix matrix;
3048matrix.setAll(2, 3, 4, 5, 6, 7, 0, 0, 1);
3049SkScalar affine[6];
3050matrix.asAffine(affine);
3051const char* names[] = { "ScaleX", "SkewY", "SkewX", "ScaleY", "TransX", "TransY" };
3052for (int i = 0; i < 6; ++i) {
3053    SkDebugf("%s: %g ", names[i], affine[i]);
3054}
3055SkDebugf("\n");
3056#StdOut
3057ScaleX: 2 SkewY: 5 SkewX: 3 ScaleY: 6 TransX: 4 TransY: 7
3058##
3059##
3060
3061#SeeAlso setAffine SetAffineIdentity
3062
3063##
3064
3065# ------------------------------------------------------------------------------
3066
3067#Method void setAffine(const SkScalar affine[6])
3068
3069#Line # sets left two columns ##
3070Sets Matrix to affine values, passed in column major order. Given affine,
3071column, then row, as:
3072
3073#Code
3074#Literal
3075| scale-x  skew-x translate-x |
3076|  skew-y scale-y translate-y |
3077##
3078
3079Matrix is set, row, then column, to:
3080
3081#Code
3082#Literal
3083| scale-x  skew-x translate-x |
3084|  skew-y scale-y translate-y |
3085|       0       0           1 |
3086##
3087
3088#Param affine  3x2 affine matrix ##
3089
3090#Example
3091SkMatrix matrix;
3092matrix.setAll(2, 3, 4, 5, 6, 7, 0, 0, 1);
3093SkScalar affine[6];
3094matrix.asAffine(affine);
3095const char* names[] = { "ScaleX", "SkewY", "SkewX", "ScaleY", "TransX", "TransY" };
3096for (int i = 0; i < 6; ++i) {
3097    SkDebugf("%s: %g ", names[i], affine[i]);
3098}
3099SkDebugf("\n");
3100matrix.reset();
3101matrix.setAffine(affine);
3102matrix.dump();
3103#StdOut
3104ScaleX: 2 SkewY: 5 SkewX: 3 ScaleY: 6 TransX: 4 TransY: 7
3105[  2.0000   3.0000   4.0000][  5.0000   6.0000   7.0000][  0.0000   0.0000   1.0000]
3106##
3107##
3108
3109#SeeAlso asAffine SetAffineIdentity
3110
3111##
3112
3113# ------------------------------------------------------------------------------
3114
3115#Method void mapPoints(SkPoint dst[], const SkPoint src[], int count) const
3116
3117#Line # maps Point array ##
3118Maps src Point array of length count to dst Point array of equal or greater
3119length. Points are mapped by multiplying each Point by Matrix. Given:
3120
3121#Code
3122#Literal
3123         | A B C |        | x |
3124Matrix = | D E F |,  pt = | y |
3125         | G H I |        | 1 |
3126##
3127
3128where
3129
3130#Code
3131#Literal
3132for (i = 0; i < count; ++i) {
3133    x = src[i].fX
3134    y = src[i].fY
3135}
3136##
3137
3138each dst Point is computed as:
3139
3140#Code
3141#Literal
3142              |A B C| |x|                               Ax+By+C   Dx+Ey+F
3143Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------
3144              |G H I| |1|                               Gx+Hy+I   Gx+Hy+I
3145##
3146
3147src and dst may point to the same storage.
3148
3149#Param dst  storage for mapped Points ##
3150#Param src  Points to transform ##
3151#Param count  number of Points to transform ##
3152
3153#Example
3154    SkMatrix matrix;
3155    matrix.reset();
3156    const int count = 4;
3157    SkPoint src[count];
3158    matrix.mapRectToQuad(src, {40, 70, 180, 220} );
3159    SkPaint paint;
3160    paint.setARGB(77, 23, 99, 154);
3161    for (int i = 0; i < 5; ++i) {
3162        SkPoint dst[count];
3163        matrix.mapPoints(dst, src, count);
3164        canvas->drawPoints(SkCanvas::kPolygon_PointMode, count, dst, paint);
3165        matrix.preRotate(35, 128, 128);
3166    }
3167##
3168
3169#SeeAlso mapXY mapHomogeneousPoints mapVectors
3170
3171##
3172
3173# ------------------------------------------------------------------------------
3174
3175#Method void mapPoints(SkPoint pts[], int count) const
3176
3177Maps pts Point array of length count in place. Points are mapped by multiplying
3178each Point by Matrix. Given:
3179
3180#Code
3181#Literal
3182         | A B C |        | x |
3183Matrix = | D E F |,  pt = | y |
3184         | G H I |        | 1 |
3185##
3186
3187where
3188
3189#Code
3190#Literal
3191for (i = 0; i < count; ++i) {
3192    x = pts[i].fX
3193    y = pts[i].fY
3194}
3195##
3196
3197each resulting pts Point is computed as:
3198
3199#Code
3200#Literal
3201              |A B C| |x|                               Ax+By+C   Dx+Ey+F
3202Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------
3203              |G H I| |1|                               Gx+Hy+I   Gx+Hy+I
3204##
3205
3206#Param pts  storage for mapped Points ##
3207#Param count  number of Points to transform ##
3208
3209#Example
3210    SkMatrix matrix;
3211    matrix.setRotate(35, 128, 128);
3212    const int count = 4;
3213    SkPoint pts[count];
3214    matrix.mapRectToQuad(pts, {40, 70, 180, 220} );
3215    SkPaint paint;
3216    paint.setARGB(77, 23, 99, 154);
3217    for (int i = 0; i < 5; ++i) {
3218        canvas->drawPoints(SkCanvas::kPolygon_PointMode, count, pts, paint);
3219        matrix.mapPoints(pts, count);
3220    }
3221##
3222
3223#SeeAlso mapXY mapHomogeneousPoints mapVectors
3224
3225##
3226
3227# ------------------------------------------------------------------------------
3228
3229#Method void mapHomogeneousPoints(SkPoint3 dst[], const SkPoint3 src[], int count) const
3230
3231#Line # maps Point3 array ##
3232Maps src Point3 array of length count to dst Point3 array, which must of length count or
3233greater. Point3 array is mapped by multiplying each Point3 by Matrix. Given:
3234
3235#Code
3236#Literal
3237         | A B C |         | x |
3238Matrix = | D E F |,  src = | y |
3239         | G H I |         | z |
3240##
3241
3242each resulting dst Point is computed as:
3243
3244#Code
3245#Literal
3246               |A B C| |x|
3247Matrix * src = |D E F| |y| = |Ax+By+Cz Dx+Ey+Fz Gx+Hy+Iz|
3248               |G H I| |z|
3249##
3250
3251#Param dst  storage for mapped Point3 array ##
3252#Param src  Point3 array to transform ##
3253#Param count  items in Point3 array to transform ##
3254
3255#Example
3256    SkPoint3 src[] = {{3, 3, 1}, {8, 2, 2}, {5, 0, 4}, {0, 1, 3},
3257                      {3, 7, 1}, {8, 6, 2}, {5, 4, 4}, {0, 5, 3}};
3258    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 };
3259    constexpr int count = SK_ARRAY_COUNT(src);
3260    auto debugster = [=](SkPoint3 src[]) -> void {
3261    for (size_t i = 0; i < SK_ARRAY_COUNT(lines); i += 2) {
3262        const SkPoint3& s = src[lines[i]];
3263        const SkPoint3& e = src[lines[i + 1]];
3264        SkPaint paint;
3265        paint.setARGB(77, 23, 99, 154);
3266        canvas->drawLine(s.fX / s.fZ, s.fY / s.fZ, e.fX / e.fZ, e.fY / e.fZ, paint);
3267    }
3268    };
3269    canvas->save();
3270    canvas->translate(5, 5);
3271    canvas->scale(15, 15);
3272    debugster(src);
3273    canvas->restore();
3274    canvas->translate(128, 128);
3275    SkMatrix matrix;
3276    matrix.setAll(15, 0, 0, 0, 15, 0, -0.08, 0.04, 1);
3277    matrix.mapHomogeneousPoints(src, src, count);
3278    debugster(src);
3279##
3280
3281#SeeAlso mapPoints mapXY mapVectors
3282
3283##
3284
3285# ------------------------------------------------------------------------------
3286
3287#Method void mapXY(SkScalar x, SkScalar y, SkPoint* result) const
3288
3289#Line # maps Point ##
3290Maps Point (x, y) to result. Point is mapped by multiplying by Matrix. Given:
3291
3292#Code
3293#Literal
3294         | A B C |        | x |
3295Matrix = | D E F |,  pt = | y |
3296         | G H I |        | 1 |
3297##
3298
3299result is computed as:
3300
3301#Code
3302#Literal
3303              |A B C| |x|                               Ax+By+C   Dx+Ey+F
3304Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------
3305              |G H I| |1|                               Gx+Hy+I   Gx+Hy+I
3306##
3307
3308#Param x  x-coordinate of Point to map ##
3309#Param y  y-coordinate of Point to map ##
3310#Param result  storage for mapped Point ##
3311
3312#Example
3313    SkPaint paint;
3314    paint.setAntiAlias(true);
3315    SkMatrix matrix;
3316    matrix.setRotate(60, 128, 128);
3317    SkPoint lines[] = {{50, 50}, {150, 50}, {150, 150}};
3318    for (size_t i = 0; i < SK_ARRAY_COUNT(lines); ++i) {
3319        SkPoint pt;
3320        matrix.mapXY(lines[i].fX, lines[i].fY, &pt);
3321        canvas->drawCircle(pt.fX, pt.fY, 3, paint);
3322    }
3323    canvas->concat(matrix);
3324    canvas->drawPoints(SkCanvas::kPolygon_PointMode, SK_ARRAY_COUNT(lines), lines, paint);
3325##
3326
3327#SeeAlso mapPoints mapVectors
3328
3329##
3330
3331# ------------------------------------------------------------------------------
3332
3333#Method SkPoint mapXY(SkScalar x, SkScalar y) const
3334
3335Returns Point (x, y) multiplied by Matrix. Given:
3336
3337#Code
3338#Literal
3339         | A B C |        | x |
3340Matrix = | D E F |,  pt = | y |
3341         | G H I |        | 1 |
3342##
3343
3344result is computed as:
3345
3346#Code
3347#Literal
3348              |A B C| |x|                               Ax+By+C   Dx+Ey+F
3349Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------
3350              |G H I| |1|                               Gx+Hy+I   Gx+Hy+I
3351##
3352
3353#Param x  x-coordinate of Point to map ##
3354#Param y  y-coordinate of Point to map ##
3355
3356#Return  mapped Point ##
3357
3358#Example
3359#Image 4
3360SkMatrix matrix;
3361SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {30, 206}};
3362SkRect::Make(source.bounds()).toQuad(bitmapBounds);
3363matrix.setPolyToPoly(bitmapBounds, perspect, 4);
3364SkPaint paint;
3365paint.setAntiAlias(true);
3366paint.setStrokeWidth(3);
3367for (int x : { 0, source.width() } ) {
3368    for (int y : { 0, source.height() } ) {
3369        canvas->drawPoint(matrix.mapXY(x, y), paint);
3370    }
3371}
3372canvas->concat(matrix);
3373canvas->drawBitmap(source, 0, 0);
3374##
3375
3376#SeeAlso mapPoints mapVectors
3377
3378##
3379
3380# ------------------------------------------------------------------------------
3381
3382#Method void mapVectors(SkVector dst[], const SkVector src[], int count) const
3383
3384#Line # maps Vector array ##
3385Maps src Vector array of length count to Vector Point array of equal or greater
3386length. Vectors are mapped by multiplying each Vector by Matrix, treating
3387Matrix translation as zero. Given:
3388
3389#Code
3390#Literal
3391         | A B 0 |         | x |
3392Matrix = | D E 0 |,  src = | y |
3393         | G H I |         | 1 |
3394##
3395
3396where
3397
3398#Code
3399#Literal
3400for (i = 0; i < count; ++i) {
3401    x = src[i].fX
3402    y = src[i].fY
3403}
3404##
3405
3406each dst Vector is computed as:
3407
3408#Code
3409#Literal
3410               |A B 0| |x|                            Ax+By     Dx+Ey
3411Matrix * src = |D E 0| |y| = |Ax+By Dx+Ey Gx+Hy+I| = ------- , -------
3412               |G H I| |1|                           Gx+Hy+I   Gx+Hy+I
3413##
3414
3415src and dst may point to the same storage.
3416
3417#Param dst  storage for mapped Vectors ##
3418#Param src  Vectors to transform ##
3419#Param count  number of Vectors to transform ##
3420
3421#Example
3422    SkPaint paint;
3423    paint.setAntiAlias(true);
3424    paint.setStyle(SkPaint::kStroke_Style);
3425    SkMatrix matrix;
3426    matrix.reset();
3427    const SkVector radii[] = {{8, 4}, {9, 1}, {6, 2}, {7, 3}};
3428    for (int i = 0; i < 4; ++i) {
3429        SkVector rScaled[4];
3430        matrix.preScale(1.5f, 2.f);
3431        matrix.mapVectors(rScaled, radii, SK_ARRAY_COUNT(radii));
3432        SkRRect rrect;
3433        rrect.setRectRadii({20, 20, 180, 70}, rScaled);
3434        canvas->drawRRect(rrect, paint);
3435        canvas->translate(0, 60);
3436    }
3437##
3438
3439#SeeAlso mapVector mapPoints mapXY
3440
3441##
3442
3443# ------------------------------------------------------------------------------
3444
3445#Method void mapVectors(SkVector vecs[], int count) const
3446
3447Maps vecs Vector array of length count in place, multiplying each Vector by
3448Matrix, treating Matrix translation as zero. Given:
3449
3450#Code
3451#Literal
3452         | A B 0 |         | x |
3453Matrix = | D E 0 |,  vec = | y |
3454         | G H I |         | 1 |
3455##
3456
3457where
3458
3459#Code
3460#Literal
3461for (i = 0; i < count; ++i) {
3462    x = vecs[i].fX
3463    y = vecs[i].fY
3464}
3465##
3466
3467each result Vector is computed as:
3468
3469#Code
3470#Literal
3471               |A B 0| |x|                            Ax+By     Dx+Ey
3472Matrix * vec = |D E 0| |y| = |Ax+By Dx+Ey Gx+Hy+I| = ------- , -------
3473               |G H I| |1|                           Gx+Hy+I   Gx+Hy+I
3474##
3475
3476#Param vecs  Vectors to transform, and storage for mapped Vectors ##
3477#Param count  number of Vectors to transform ##
3478
3479#Example
3480    SkPaint paint;
3481    paint.setAntiAlias(true);
3482    paint.setStyle(SkPaint::kStroke_Style);
3483    SkMatrix matrix;
3484    matrix.setScale(2, 3);
3485    SkVector radii[] = {{7, 7}, {3, 3}, {2, 2}, {4, 0}};
3486    for (int i = 0; i < 4; ++i) {
3487        SkRRect rrect;
3488        rrect.setRectRadii({20, 20, 180, 70}, radii);
3489        canvas->drawRRect(rrect, paint);
3490        canvas->translate(0, 60);
3491        matrix.mapVectors(radii, SK_ARRAY_COUNT(radii));
3492    }
3493##
3494
3495#SeeAlso mapVector mapPoints mapXY
3496
3497##
3498
3499# ------------------------------------------------------------------------------
3500
3501#Method void mapVector(SkScalar dx, SkScalar dy, SkVector* result) const
3502
3503#Line # maps Vector ##
3504Maps Vector (x, y) to result. Vector is mapped by multiplying by Matrix,
3505treating Matrix translation as zero. Given:
3506
3507#Code
3508#Literal
3509         | A B 0 |         | dx |
3510Matrix = | D E 0 |,  vec = | dy |
3511         | G H I |         |  1 |
3512##
3513
3514each result Vector is computed as:
3515
3516#Code
3517#Literal
3518#Outdent
3519               |A B 0| |dx|                                        A*dx+B*dy     D*dx+E*dy
3520Matrix * vec = |D E 0| |dy| = |A*dx+B*dy D*dx+E*dy G*dx+H*dy+I| = ----------- , -----------
3521               |G H I| | 1|                                       G*dx+H*dy+I   G*dx+*dHy+I
3522##
3523
3524#Param dx  x-coordinate of Vector to map ##
3525#Param dy  y-coordinate of Vector to map ##
3526#Param result  storage for mapped Vector ##
3527
3528#Example
3529    SkPaint paint;
3530    paint.setColor(SK_ColorGREEN);
3531    paint.setAntiAlias(true);
3532    paint.setTextSize(48);
3533    SkMatrix matrix;
3534    matrix.setRotate(90);
3535    SkVector offset = { 7, 7 };
3536    for (int i = 0; i < 4; ++i) {
3537        paint.setImageFilter(SkDropShadowImageFilter::Make(offset.fX, offset.fY, 3, 3,
3538              SK_ColorBLUE, SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMode, nullptr));
3539        matrix.mapVector(offset.fX, offset.fY, &offset);
3540        canvas->translate(0, 60);
3541        canvas->drawString("Text", 50, 0, paint);
3542    }
3543##
3544
3545#SeeAlso mapVectors mapPoints mapXY
3546
3547##
3548
3549# ------------------------------------------------------------------------------
3550
3551#Method SkVector mapVector(SkScalar dx, SkScalar dy) const
3552
3553Returns Vector (x, y) multiplied by Matrix, treating Matrix translation as zero.
3554Given:
3555
3556#Code
3557#Literal
3558         | A B 0 |         | dx |
3559Matrix = | D E 0 |,  vec = | dy |
3560         | G H I |         |  1 |
3561##
3562
3563each result Vector is computed as:
3564
3565#Code
3566#Literal
3567#Outdent
3568               |A B 0| |dx|                                        A*dx+B*dy     D*dx+E*dy
3569Matrix * vec = |D E 0| |dy| = |A*dx+B*dy D*dx+E*dy G*dx+H*dy+I| = ----------- , -----------
3570               |G H I| | 1|                                       G*dx+H*dy+I   G*dx+*dHy+I
3571##
3572
3573#Param dx  x-coordinate of Vector to map ##
3574#Param dy  y-coordinate of Vector to map ##
3575
3576#Return  mapped Vector ##
3577
3578#Example
3579    SkPaint paint;
3580    paint.setColor(SK_ColorGREEN);
3581    paint.setAntiAlias(true);
3582    paint.setTextSize(48);
3583    SkMatrix matrix;
3584    matrix.setRotate(90);
3585    SkVector offset = { 7, 7 };
3586    for (int i = 0; i < 4; ++i) {
3587        paint.setImageFilter(SkDropShadowImageFilter::Make(offset.fX, offset.fY, 3, 3,
3588              SK_ColorBLUE, SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMode, nullptr));
3589        offset = matrix.mapVector(offset.fX, offset.fY);
3590        canvas->translate(0, 60);
3591        canvas->drawString("Text", 50, 0, paint);
3592    }
3593##
3594
3595#SeeAlso mapVectors mapPoints mapXY
3596
3597##
3598
3599# ------------------------------------------------------------------------------
3600
3601#Method bool mapRect(SkRect* dst, const SkRect& src) const
3602
3603#Line # returns bounds of mapped Rect ##
3604Sets dst to bounds of src corners mapped by Matrix.
3605Returns true if mapped corners are dst corners.
3606
3607Returned value is the same as calling rectStaysRect.
3608
3609#Param dst  storage for bounds of mapped Points ##
3610#Param src  Rect to map ##
3611
3612#Return  true if dst is equivalent to mapped src ##
3613
3614#Example
3615    SkPaint paint;
3616    paint.setAntiAlias(true);
3617    SkMatrix matrix;
3618    matrix.setRotate(45, 128, 128);
3619    SkRect rotatedBounds, bounds = {40, 50, 190, 200};
3620    matrix.mapRect(&rotatedBounds, bounds );
3621    paint.setColor(SK_ColorGRAY);
3622    canvas->drawRect(rotatedBounds, paint);
3623    canvas->concat(matrix);
3624    paint.setColor(SK_ColorRED);
3625    canvas->drawRect(bounds, paint);
3626##
3627
3628#SeeAlso mapPoints rectStaysRect
3629
3630##
3631
3632# ------------------------------------------------------------------------------
3633
3634#Method bool mapRect(SkRect* rect) const
3635
3636Sets rect to bounds of rect corners mapped by Matrix.
3637Returns true if mapped corners are computed rect corners.
3638
3639Returned value is the same as calling rectStaysRect.
3640
3641#Param rect  rectangle to map, and storage for bounds of mapped corners ##
3642
3643#Return  true if result is equivalent to mapped src ##
3644
3645#Example
3646    SkPaint paint;
3647    paint.setAntiAlias(true);
3648    SkMatrix matrix;
3649    matrix.setRotate(45, 128, 128);
3650    SkRect bounds = {40, 50, 190, 200};
3651    matrix.mapRect(&bounds);
3652    paint.setColor(SK_ColorGRAY);
3653    canvas->drawRect(bounds, paint);
3654    canvas->concat(matrix);
3655    paint.setColor(SK_ColorRED);
3656    canvas->drawRect({40, 50, 190, 200}, paint);
3657##
3658
3659#SeeAlso mapRectScaleTranslate mapPoints rectStaysRect
3660
3661##
3662
3663# ------------------------------------------------------------------------------
3664
3665#Method void mapRectToQuad(SkPoint dst[4], const SkRect& rect) const
3666
3667#Line # maps Rect to Point array ##
3668Maps four corners of rect to dst. Points are mapped by multiplying each
3669rect corner by Matrix. rect corner is processed in this order:
3670(rect.fLeft, rect.fTop), (rect.fRight, rect.fTop), (rect.fRight, rect.fBottom),
3671(rect.fLeft, rect.fBottom).
3672
3673rect may be empty: rect.fLeft may be greater than or equal to rect.fRight;
3674rect.fTop may be greater than or equal to rect.fBottom.
3675
3676Given:
3677
3678#Code
3679#Literal
3680         | A B C |        | x |
3681Matrix = | D E F |,  pt = | y |
3682         | G H I |        | 1 |
3683##
3684
3685where pt is initialized from each of (rect.fLeft, rect.fTop),
3686(rect.fRight, rect.fTop), (rect.fRight, rect.fBottom), (rect.fLeft, rect.fBottom),
3687each dst Point is computed as:
3688
3689#Code
3690#Literal
3691              |A B C| |x|                               Ax+By+C   Dx+Ey+F
3692Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------
3693              |G H I| |1|                               Gx+Hy+I   Gx+Hy+I
3694##
3695
3696#Param dst  storage for mapped corner Points ##
3697#Param rect  Rect to map ##
3698
3699#Example
3700#Height 192
3701    SkPaint paint;
3702    paint.setAntiAlias(true);
3703    SkMatrix matrix;
3704    matrix.setRotate(60, 128, 128);
3705    SkRect rect = {50, 50, 150, 150};
3706    SkPoint pts[4];
3707    matrix.mapRectToQuad(pts, rect);
3708    for (int i = 0; i < 4; ++i) {
3709        canvas->drawCircle(pts[i].fX, pts[i].fY, 3, paint);
3710    }
3711    canvas->concat(matrix);
3712    paint.setStyle(SkPaint::kStroke_Style);
3713    canvas->drawRect(rect, paint);
3714##
3715
3716#SeeAlso mapRect mapRectScaleTranslate
3717
3718##
3719
3720# ------------------------------------------------------------------------------
3721
3722#Method void mapRectScaleTranslate(SkRect* dst, const SkRect& src) const
3723
3724#Line # returns bounds of mapped Rect ##
3725Sets dst to bounds of src corners mapped by Matrix. If matrix contains
3726elements other than scale or translate: asserts if SK_DEBUG is defined;
3727otherwise, results are undefined.
3728
3729#Param dst  storage for bounds of mapped Points ##
3730#Param src  Rect to map ##
3731
3732#Example
3733    SkPaint paint;
3734    SkMatrix matrix;
3735    SkRect rect = {100, 50, 150, 180};
3736    matrix.setScale(2, .5f, rect.centerX(), rect.centerY());
3737    SkRect rotated;
3738    matrix.mapRectScaleTranslate(&rotated, rect);
3739    paint.setStyle(SkPaint::kStroke_Style);
3740    canvas->drawRect(rect, paint);
3741    paint.setColor(SK_ColorRED);
3742    canvas->drawRect(rotated, paint);
3743##
3744
3745#SeeAlso mapRect mapRectToQuad isScaleTranslate rectStaysRect
3746
3747##
3748
3749# ------------------------------------------------------------------------------
3750
3751#Method SkScalar mapRadius(SkScalar radius) const
3752
3753#Line # returns mean radius of mapped Circle ##
3754Returns geometric mean radius of ellipse formed by constructing Circle of
3755size radius, and mapping constructed Circle with Matrix. The result squared is
3756equal to the major axis length times the minor axis length.
3757Result is not meaningful if Matrix contains perspective elements.
3758
3759#Param radius  Circle size to map ##
3760
3761#Return  average mapped radius ##
3762
3763#Example
3764#Description
3765The area enclosed by a square with sides equal to mappedRadius is the same as
3766the area enclosed by the ellipse major and minor axes.
3767##
3768  SkPaint paint;
3769  paint.setAntiAlias(true);
3770  SkMatrix matrix;
3771  const SkPoint center = {108, 93};
3772  matrix.setScale(2, .5f, center.fX, center.fY);
3773  matrix.postRotate(45, center.fX, center.fY);
3774  const SkScalar circleRadius = 50;
3775  SkScalar mappedRadius = matrix.mapRadius(circleRadius);
3776  SkVector minorAxis, majorAxis;
3777  matrix.mapVector(0, circleRadius, &minorAxis);
3778  matrix.mapVector(circleRadius, 0, &majorAxis);
3779  SkString mappedArea;
3780  mappedArea.printf("area = %g", mappedRadius * mappedRadius);
3781  canvas->drawString(mappedArea, 145, 250, paint);
3782  canvas->drawString("mappedRadius", center.fX + mappedRadius + 3, center.fY, paint);
3783  paint.setColor(SK_ColorRED);
3784  SkString axArea;
3785  axArea.printf("area = %g", majorAxis.length() * minorAxis.length());
3786  paint.setStyle(SkPaint::kFill_Style);
3787  canvas->drawString(axArea, 15, 250, paint);
3788  paint.setStyle(SkPaint::kStroke_Style);
3789  canvas->drawRect({10, 200, 10 + majorAxis.length(), 200 + minorAxis.length()}, paint);
3790  paint.setColor(SK_ColorBLACK);
3791  canvas->drawLine(center.fX, center.fY, center.fX + mappedRadius, center.fY, paint);
3792  canvas->drawLine(center.fX, center.fY, center.fX, center.fY + mappedRadius, paint);
3793  canvas->drawRect({140, 180, 140 + mappedRadius, 180 + mappedRadius}, paint);
3794  canvas->concat(matrix);
3795  canvas->drawCircle(center.fX, center.fY, circleRadius, paint);
3796  paint.setColor(SK_ColorRED);
3797  canvas->drawLine(center.fX, center.fY, center.fX + circleRadius, center.fY, paint);
3798  canvas->drawLine(center.fX, center.fY, center.fX, center.fY + circleRadius, paint);
3799##
3800
3801#SeeAlso mapVector
3802
3803##
3804
3805# ------------------------------------------------------------------------------
3806
3807#Method bool isFixedStepInX() const
3808
3809#Line # returns if transformation supports fixed step in x ##
3810Returns true if a unit step in x at some y mapped through Matrix can be
3811represented by a constant Vector. Returns true if getType returns kIdentity_Mask,
3812or combinations of: kTranslate_Mask, kScale_Mask, and kAffine_Mask.
3813
3814May return true if getType returns kPerspective_Mask, but only when Matrix
3815does not include rotation or skewing along the y-axis.
3816
3817#Return  true if Matrix does not have complex perspective ##
3818
3819#Example
3820    SkMatrix matrix;
3821    for (SkScalar px : { 0.0f, 0.1f } ) {
3822        for (SkScalar py : { 0.0f, 0.1f } ) {
3823            for (SkScalar sy : { 1, 2 } ) {
3824                matrix.setAll(1, 0, 0,   0, sy, 0,   px, py, 1);
3825                matrix.dump();
3826                SkDebugf("isFixedStepInX: %s\n", matrix.isFixedStepInX() ? "true" : "false");
3827            }
3828        }
3829    }
3830#StdOut
3831[  1.0000   0.0000   0.0000][  0.0000   1.0000   0.0000][  0.0000   0.0000   1.0000]
3832isFixedStepInX: true
3833[  1.0000   0.0000   0.0000][  0.0000   2.0000   0.0000][  0.0000   0.0000   1.0000]
3834isFixedStepInX: true
3835[  1.0000   0.0000   0.0000][  0.0000   1.0000   0.0000][  0.0000   0.1000   1.0000]
3836isFixedStepInX: true
3837[  1.0000   0.0000   0.0000][  0.0000   2.0000   0.0000][  0.0000   0.1000   1.0000]
3838isFixedStepInX: true
3839[  1.0000   0.0000   0.0000][  0.0000   1.0000   0.0000][  0.1000   0.0000   1.0000]
3840isFixedStepInX: false
3841[  1.0000   0.0000   0.0000][  0.0000   2.0000   0.0000][  0.1000   0.0000   1.0000]
3842isFixedStepInX: false
3843[  1.0000   0.0000   0.0000][  0.0000   1.0000   0.0000][  0.1000   0.1000   1.0000]
3844isFixedStepInX: false
3845[  1.0000   0.0000   0.0000][  0.0000   2.0000   0.0000][  0.1000   0.1000   1.0000]
3846isFixedStepInX: false
3847##
3848##
3849
3850#SeeAlso fixedStepInX getType
3851
3852##
3853
3854# ------------------------------------------------------------------------------
3855
3856#Method SkVector fixedStepInX(SkScalar y) const
3857
3858#Line # returns step in x for a position in y ##
3859Returns Vector representing a unit step in x at y mapped through Matrix.
3860If isFixedStepInX is false, returned value is undefined.
3861
3862#Param y  position of line parallel to x-axis ##
3863
3864#Return  Vector advance of mapped unit step in x ##
3865
3866#Example
3867#Image 3
3868    SkMatrix matrix;
3869    const SkPoint center = { 128, 128 };
3870    matrix.setScale(20, 25, center.fX, center.fY);
3871    matrix.postRotate(75, center.fX, center.fY);
3872    {
3873       SkAutoCanvasRestore acr(canvas, true);
3874       canvas->concat(matrix);
3875       canvas->drawBitmap(source, 0, 0);
3876    }
3877    if (matrix.isFixedStepInX()) {
3878       SkPaint paint;
3879       paint.setAntiAlias(true);
3880       SkVector step = matrix.fixedStepInX(128);
3881       SkVector end = center + step;
3882       canvas->drawLine(center, end, paint);
3883       SkVector arrow = { step.fX + step.fY, step.fY - step.fX};
3884       arrow = arrow * .25f;
3885       canvas->drawLine(end, end - arrow, paint);
3886       canvas->drawLine(end, {end.fX + arrow.fY, end.fY - arrow.fX}, paint);
3887    }
3888##
3889
3890#SeeAlso isFixedStepInX getType
3891
3892##
3893
3894# ------------------------------------------------------------------------------
3895
3896#Method bool cheapEqualTo(const SkMatrix& m) const
3897
3898#Line # compares Matrix pair using memcmp() ##
3899Returns true if Matrix equals m, using an efficient comparison.
3900
3901Returns false when the sign of zero values is the different; when one
3902matrix has positive zero value and the other has negative zero value.
3903
3904Returns true even when both Matrices contain NaN.
3905
3906NaN never equals any value, including itself. To improve performance, NaN values
3907are treated as bit patterns that are equal if their bit patterns are equal.
3908
3909#Param m  Matrix to compare ##
3910
3911#Return  true if m and Matrix are represented by identical bit patterns ##
3912
3913#Example
3914    auto debugster = [](const char* prefix, const SkMatrix& a, const SkMatrix& b) -> void {
3915        SkDebugf("%s: a %c= b a.cheapEqualTo(b): %s\n", prefix,
3916                 a == b ? '=' : '!', a.cheapEqualTo(b) ? "true" : "false");
3917    };
3918    SkMatrix a, b;
3919    a.setAll(1, 0, 0,   0, 1, 0,  0, 0, 1);
3920    b.setIdentity();
3921    debugster("identity", a, b);
3922    a.setAll(1, -0.0f, 0,   0, 1, 0,  0, 0, 1);
3923    debugster("neg zero", a, b);
3924    a.setAll(1, SK_ScalarNaN, 0,   0, 1, 0,  0, 0, 1);
3925    debugster(" one NaN", a, b);
3926    b.setAll(1, SK_ScalarNaN, 0,   0, 1, 0,  0, 0, 1);
3927    debugster("both NaN", a, b);
3928#StdOut
3929identity: a == b a.cheapEqualTo(b): true
3930neg zero: a == b a.cheapEqualTo(b): false
3931 one NaN: a != b a.cheapEqualTo(b): false
3932both NaN: a != b a.cheapEqualTo(b): true
3933##
3934##
3935
3936#SeeAlso operator==(const SkMatrix& a, const SkMatrix& b)
3937
3938##
3939
3940# ------------------------------------------------------------------------------
3941
3942#Method bool operator==(const SkMatrix& a, const SkMatrix& b)
3943
3944#Line # returns true if members are equal ##
3945Compares a and b; returns true if a and b are numerically equal. Returns true
3946even if sign of zero values are different. Returns false if either Matrix
3947contains NaN, even if the other Matrix also contains NaN.
3948
3949#Param a  Matrix to compare ##
3950#Param b  Matrix to compare ##
3951
3952#Return  true if m and Matrix are numerically equal ##
3953
3954#Example
3955    auto debugster = [](const char* prefix, const SkMatrix& a, const SkMatrix& b) -> void {
3956        SkDebugf("%s: a %c= b a.cheapEqualTo(b): %s\n", prefix,
3957                 a == b ? '=' : '!', a.cheapEqualTo(b) ? "true" : "false");
3958    };
3959    SkMatrix a, b;
3960    a.setAll(1, 0, 0,   0, 1, 0,  0, 0, 1);
3961    b.setScale(2, 4);
3962    b.postScale(0.5f, 0.25f);
3963    debugster("identity", a, b);
3964#StdOut
3965identity: a == b a.cheapEqualTo(b): true
3966##
3967##
3968
3969#SeeAlso  cheapEqualTo operator!=(const SkMatrix& a, const SkMatrix& b)
3970
3971##
3972
3973# ------------------------------------------------------------------------------
3974
3975#Method bool operator!=(const SkMatrix& a, const SkMatrix& b)
3976
3977#Line # returns true if members are unequal ##
3978Compares a and b; returns true if a and b are not numerically equal. Returns false
3979even if sign of zero values are different. Returns true if either Matrix
3980contains NaN, even if the other Matrix also contains NaN.
3981
3982#Param a  Matrix to compare ##
3983#Param b  Matrix to compare ##
3984
3985#Return  true if m and Matrix are numerically not equal ##
3986
3987#Example
3988    auto debugster = [](const char* prefix, const SkMatrix& a, const SkMatrix& b) -> void {
3989        SkDebugf("%s: a %c= b a.cheapEqualTo(b): %s\n", prefix,
3990                 a != b ? '!' : '=', a.cheapEqualTo(b) ? "true" : "false");
3991    };
3992    SkMatrix a, b;
3993    a.setAll(1, 0, 0,   0, 1, 0,  1, 0, 1);
3994    a.invert(&b);
3995    debugster("identity", a, b);
3996##
3997
3998#SeeAlso cheapEqualTo operator==(const SkMatrix& a, const SkMatrix& b)
3999
4000##
4001
4002# ------------------------------------------------------------------------------
4003
4004#Method void dump() const
4005
4006#Line # sends text representation using floats to standard output ##
4007Writes text representation of Matrix to standard output. Floating point values
4008are written with limited precision; it may not be possible to reconstruct
4009original Matrix from output.
4010
4011#Example
4012    SkMatrix matrix;
4013    matrix.setRotate(45);
4014    matrix.dump();
4015    SkMatrix nearlyEqual;
4016    nearlyEqual.setAll(0.7071f, -0.7071f, 0,   0.7071f, 0.7071f, 0,   0, 0, 1);
4017    nearlyEqual.dump();
4018    SkDebugf("matrix %c= nearlyEqual\n", matrix == nearlyEqual ? '=' : '!');
4019#StdOut
4020[  0.7071  -0.7071   0.0000][  0.7071   0.7071   0.0000][  0.0000   0.0000   1.0000]
4021[  0.7071  -0.7071   0.0000][  0.7071   0.7071   0.0000][  0.0000   0.0000   1.0000]
4022matrix != nearlyEqual
4023##
4024##
4025
4026#SeeAlso toString
4027
4028##
4029
4030# ------------------------------------------------------------------------------
4031
4032#Method void toString(SkString* str) const
4033
4034#Line # converts Matrix to machine readable form ##
4035Creates string representation of Matrix. Floating point values
4036are written with limited precision; it may not be possible to reconstruct
4037original Matrix from output.
4038
4039#Param str  storage for string representation of Matrix ##
4040
4041#Example
4042    SkMatrix matrix;
4043    matrix.setRotate(45);
4044    SkString mStr, neStr;
4045    matrix.toString(&mStr);
4046    SkMatrix nearlyEqual;
4047    nearlyEqual.setAll(0.7071f, -0.7071f, 0,   0.7071f, 0.7071f, 0,   0, 0, 1);
4048    nearlyEqual.toString(&neStr);
4049    SkDebugf("mStr  %s\n", mStr.c_str());
4050    SkDebugf("neStr %s\n", neStr.c_str());
4051    SkDebugf("matrix %c= nearlyEqual\n", matrix == nearlyEqual ? '=' : '!');
4052#StdOut
4053mStr  [  0.7071  -0.7071   0.0000][  0.7071   0.7071   0.0000][  0.0000   0.0000   1.0000]
4054neStr [  0.7071  -0.7071   0.0000][  0.7071   0.7071   0.0000][  0.0000   0.0000   1.0000]
4055matrix != nearlyEqual
4056##
4057##
4058
4059#SeeAlso dump
4060
4061##
4062
4063# ------------------------------------------------------------------------------
4064
4065#Method SkScalar getMinScale() const
4066
4067#Line # returns minimum scaling, if possible ##
4068Returns the minimum scaling factor of Matrix by decomposing the scaling and
4069skewing elements.
4070Returns -1 if scale factor overflows or Matrix contains perspective.
4071
4072#Return  minimum scale factor
4073##
4074
4075#Example
4076    SkMatrix matrix;
4077    matrix.setScale(42, 24);
4078    SkDebugf("matrix.getMinScale() %g\n", matrix.getMinScale());
4079#StdOut
4080matrix.getMinScale() 24
4081##
4082##
4083
4084#SeeAlso getMaxScale getMinMaxScales
4085
4086##
4087
4088# ------------------------------------------------------------------------------
4089
4090#Method SkScalar getMaxScale() const
4091
4092#Line # returns maximum scaling, if possible ##
4093Returns the maximum scaling factor of Matrix by decomposing the scaling and
4094skewing elements.
4095Returns -1 if scale factor overflows or Matrix contains perspective.
4096
4097#Return  maximum scale factor
4098##
4099
4100#Example
4101    SkMatrix matrix;
4102    matrix.setScale(42, 24);
4103    SkDebugf("matrix.getMaxScale() %g\n", matrix.getMaxScale());
4104#StdOut
4105matrix.getMaxScale() 42
4106##
4107##
4108
4109#SeeAlso getMinScale getMinMaxScales
4110
4111##
4112
4113# ------------------------------------------------------------------------------
4114
4115#Method bool SK_WARN_UNUSED_RESULT getMinMaxScales(SkScalar scaleFactors[2]) const
4116
4117#Line # returns minimum and maximum scaling, if possible ##
4118Sets scaleFactors[0] to the minimum scaling factor, and scaleFactors[1] to the
4119maximum scaling factor. Scaling factors are computed by decomposing
4120the Matrix scaling and skewing elements.
4121
4122Returns true if scaleFactors are found; otherwise, returns false and sets
4123scaleFactors to undefined values.
4124
4125#Param scaleFactors  storage for minimum and maximum scale factors ##
4126
4127#Return  true if scale factors were computed correctly ##
4128
4129#Example
4130    SkMatrix matrix;
4131    matrix.setAll(1, 0, 0,  0, 1, 0,   0, 0, 0);
4132    matrix.invert(&matrix);
4133    SkScalar factor[2] = {2, 2};
4134    bool result = matrix.getMinMaxScales(factor);
4135    SkDebugf("matrix.getMinMaxScales() %s %g %g\n", result ? "true" : "false", factor[0], factor[1]);
4136#StdOut
4137matrix.getMinMaxScales() false 2 2
4138##
4139##
4140
4141#SeeAlso getMinScale getMaxScale
4142
4143##
4144
4145# ------------------------------------------------------------------------------
4146
4147#Method bool decomposeScale(SkSize* scale, SkMatrix* remaining = nullptr) const
4148
4149#Line # separates scale if possible ##
4150Decomposes Matrix into scale components and whatever remains. Returns false if
4151Matrix could not be decomposed.
4152
4153Sets scale to portion of Matrix that scales in x and y. Sets remaining to Matrix
4154with x and y scaling factored out. remaining may be passed as nullptr
4155to determine if Matrix can be decomposed without computing remainder.
4156
4157Returns true if scale components are found. scale and remaining are
4158unchanged if Matrix contains perspective; scale factors are not finite, or
4159are nearly zero.
4160
4161On success
4162
4163#Formula
4164Matrix = scale * Remaining
4165##
4166
4167#Param scale  x and y scaling factors; may be nullptr  ##
4168#Param remaining  Matrix without scaling; may be nullptr ##
4169
4170#Return  true if scale can be computed ##
4171
4172#Example
4173    SkMatrix matrix;
4174    matrix.setRotate(90 * SK_Scalar1);
4175    matrix.postScale(1.f / 4, 1.f / 2);
4176    matrix.dump();
4177    SkSize scale = {SK_ScalarNaN, SK_ScalarNaN};
4178    SkMatrix remaining;
4179    remaining.reset();
4180    bool success = matrix.decomposeScale(&scale, &remaining);
4181    SkDebugf("success: %s  ", success ? "true" : "false");
4182    SkDebugf("scale: %g, %g\n", scale.width(), scale.height());
4183    remaining.dump();
4184    SkMatrix scaleMatrix = SkMatrix::MakeScale(scale.width(), scale.height());
4185    SkMatrix combined = SkMatrix::Concat(scaleMatrix, remaining);
4186    combined.dump();
4187#StdOut
4188[  0.0000  -0.2500   0.0000][  0.5000   0.0000   0.0000][  0.0000   0.0000   1.0000]
4189success: true  scale: 0.5, 0.25
4190[  0.0000  -0.5000   0.0000][  2.0000   0.0000   0.0000][  0.0000   0.0000   1.0000]
4191[  0.0000  -0.2500   0.0000][  0.5000   0.0000   0.0000][  0.0000   0.0000   1.0000]
4192##
4193##
4194
4195#SeeAlso setScale MakeScale
4196
4197##
4198
4199# ------------------------------------------------------------------------------
4200
4201#Method static const SkMatrix& I()
4202
4203#Line # returns a reference to a const identity Matrix ##
4204Returns reference to const identity Matrix. Returned Matrix is set to:
4205
4206#Code
4207#Literal
4208| 1 0 0 |
4209| 0 1 0 |
4210| 0 0 1 |
4211##
4212
4213#Return  const identity Matrix ##
4214
4215#Example
4216    SkMatrix m1, m2, m3;
4217    m1.reset();
4218    m2.setIdentity();
4219    m3 = SkMatrix::I();
4220    SkDebugf("m1 %c= m2\n", m1 == m2 ? '=' : '!');
4221    SkDebugf("m2 %c= m3\n", m1 == m2 ? '=' : '!');
4222#StdOut
4223m1 == m2
4224m2 == m3
4225##
4226##
4227
4228#SeeAlso reset() setIdentity
4229
4230##
4231
4232# ------------------------------------------------------------------------------
4233
4234#Method static const SkMatrix& InvalidMatrix()
4235
4236#Line # returns a reference to a const invalid Matrix ##
4237Returns reference to a const Matrix with invalid values. Returned Matrix is set
4238to:
4239
4240#Code
4241#Literal
4242| SK_ScalarMax SK_ScalarMax SK_ScalarMax |
4243| SK_ScalarMax SK_ScalarMax SK_ScalarMax |
4244| SK_ScalarMax SK_ScalarMax SK_ScalarMax |
4245##
4246
4247#Return  const invalid Matrix ##
4248
4249#Example
4250    SkDebugf("scaleX %g\n", SkMatrix::InvalidMatrix().getScaleX());
4251#StdOut
4252scaleX 3.40282e+38
4253##
4254##
4255
4256#SeeAlso SeeAlso getType
4257
4258##
4259
4260# ------------------------------------------------------------------------------
4261
4262#Method static SkMatrix Concat(const SkMatrix& a, const SkMatrix& b)
4263
4264#Line # returns the concatenation of Matrix pair ##
4265Returns Matrix a multiplied by Matrix b.
4266
4267Given:
4268
4269#Code
4270#Literal
4271    | A B C |      | J K L |
4272a = | D E F |, b = | M N O |
4273    | G H I |      | P Q R |
4274##
4275
4276sets Matrix to:
4277
4278#Code
4279#Literal
4280        | A B C |   | J K L |   | AJ+BM+CP AK+BN+CQ AL+BO+CR |
4281a * b = | D E F | * | M N O | = | DJ+EM+FP DK+EN+FQ DL+EO+FR |
4282        | G H I |   | P Q R |   | GJ+HM+IP GK+HN+IQ GL+HO+IR |
4283##
4284
4285#Param a  Matrix on left side of multiply expression ##
4286#Param b  Matrix on right side of multiply expression ##
4287
4288#Return  Matrix computed from a times b ##
4289
4290#Example
4291#Height 64
4292#Image 4
4293#Description
4294setPolyToPoly creates perspective matrices, one the inverse of the other.
4295Multiplying the matrix by its inverse turns into an identity matrix.
4296##
4297SkMatrix matrix, matrix2;
4298SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
4299SkRect::Make(source.bounds()).toQuad(bitmapBounds);
4300matrix.setPolyToPoly(bitmapBounds, perspect, 4);
4301matrix2.setPolyToPoly(perspect, bitmapBounds, 4);
4302SkMatrix concat = SkMatrix::Concat(matrix, matrix2);
4303canvas->concat(concat);
4304canvas->drawBitmap(source, 0, 0);
4305##
4306
4307#SeeAlso preConcat postConcat
4308
4309##
4310
4311# ------------------------------------------------------------------------------
4312
4313#Method void dirtyMatrixTypeCache()
4314
4315#Line # sets internal cache to unknown state ##
4316Sets internal cache to unknown state. Use to force update after repeated
4317modifications to Matrix element reference returned by operator[](int index).
4318
4319#Example
4320SkMatrix matrix;
4321matrix.setIdentity();
4322SkDebugf("with identity matrix: x = %g\n", matrix.mapXY(24, 42).fX);
4323SkScalar& skewRef = matrix[SkMatrix::kMSkewX];
4324skewRef = 0;
4325SkDebugf("after skew x mod:     x = %g\n", matrix.mapXY(24, 42).fX);
4326skewRef = 1;
4327SkDebugf("after 2nd skew x mod: x = %g\n", matrix.mapXY(24, 42).fX);
4328matrix.dirtyMatrixTypeCache();
4329SkDebugf("after dirty cache:    x = %g\n", matrix.mapXY(24, 42).fX);
4330#StdOut
4331with identity matrix: x = 24
4332after skew x mod:     x = 24
4333after 2nd skew x mod: x = 24
4334after dirty cache:    x = 66
4335##
4336##
4337
4338#SeeAlso operator[](int index) getType
4339
4340##
4341
4342# ------------------------------------------------------------------------------
4343
4344#Method void setScaleTranslate(SkScalar sx, SkScalar sy, SkScalar tx, SkScalar ty)
4345
4346#Line # sets to scale and translate ##
4347Initializes Matrix with scale and translate elements.
4348
4349#Code
4350#Literal
4351| sx  0 tx |
4352|  0 sy ty |
4353|  0  0  1 |
4354##
4355
4356#Param sx  horizontal scale factor to store ##
4357#Param sy  vertical scale factor to store ##
4358#Param tx  horizontal translation to store ##
4359#Param ty  vertical translation to store ##
4360
4361#Example
4362SkMatrix matrix;
4363matrix.setScaleTranslate(1, 2, 3, 4);
4364matrix.dump();
4365#StdOut
4366[  1.0000   0.0000   3.0000][  0.0000   2.0000   4.0000][  0.0000   0.0000   1.0000]
4367##
4368##
4369
4370#SeeAlso setScale preTranslate postTranslate
4371
4372##
4373
4374# ------------------------------------------------------------------------------
4375
4376#Method bool isFinite() const
4377
4378#Line # returns if all Matrix values are not infinity, NaN ##
4379Returns true if all elements of the matrix are finite. Returns false if any
4380element is infinity, or NaN.
4381
4382#Return  true if matrix has only finite elements ##
4383
4384#Example
4385SkMatrix matrix = SkMatrix::MakeTrans(SK_ScalarNaN, 0);
4386matrix.dump();
4387SkDebugf("matrix is finite: %s\n", matrix.isFinite() ? "true" : "false");
4388SkDebugf("matrix %c= matrix\n", matrix == matrix ? '=' : '!');
4389#StdOut
4390[  1.0000   0.0000      nan][  0.0000   1.0000   0.0000][  0.0000   0.0000   1.0000]
4391matrix is finite: false
4392matrix != matrix
4393##
4394##
4395
4396#SeeAlso operator==
4397
4398##
4399
4400#Class SkMatrix ##
4401
4402#Topic Matrix ##
4403