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