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