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