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 class SkString;
18 
19 /** \class SkMatrix
20     SkMatrix holds a 3x3 matrix for transforming coordinates. This allows mapping
21     SkPoint and vectors with translation, scaling, skewing, rotation, and
22     perspective.
23 
24     SkMatrix elements are in row major order. SkMatrix does not have a constructor,
25     so it must be explicitly initialized. setIdentity() initializes SkMatrix
26     so it has no effect. setTranslate(), setScale(), setSkew(), setRotate(), set9 and setAll()
27     initializes all SkMatrix elements with the corresponding mapping.
28 
29     SkMatrix includes a hidden variable that classifies the type of matrix to
30     improve performance. SkMatrix is not thread safe unless getType() is called first.
31 */
32 SK_BEGIN_REQUIRE_DENSE
33 class SK_API SkMatrix {
34 public:
35 
36     /** Creates an identity SkMatrix:
37 
38             | 1 0 0 |
39             | 0 1 0 |
40             | 0 0 1 |
41     */
SkMatrix()42     constexpr SkMatrix() : SkMatrix(1,0,0, 0,1,0, 0,0,1, kIdentity_Mask | kRectStaysRect_Mask) {}
43 
44     /** Sets SkMatrix to scale by (sx, sy). Returned matrix is:
45 
46             | sx  0  0 |
47             |  0 sy  0 |
48             |  0  0  1 |
49 
50         @param sx  horizontal scale factor
51         @param sy  vertical scale factor
52         @return    SkMatrix with scale
53     */
MakeScale(SkScalar sx,SkScalar sy)54     static SkMatrix SK_WARN_UNUSED_RESULT MakeScale(SkScalar sx, SkScalar sy) {
55         SkMatrix m;
56         m.setScale(sx, sy);
57         return m;
58     }
59 
60     /** Sets SkMatrix to scale by (scale, scale). Returned matrix is:
61 
62             | scale   0   0 |
63             |   0   scale 0 |
64             |   0     0   1 |
65 
66         @param scale  horizontal and vertical scale factor
67         @return       SkMatrix with scale
68     */
MakeScale(SkScalar scale)69     static SkMatrix SK_WARN_UNUSED_RESULT MakeScale(SkScalar scale) {
70         SkMatrix m;
71         m.setScale(scale, scale);
72         return m;
73     }
74 
75     /** Sets SkMatrix to translate by (dx, dy). Returned matrix is:
76 
77             | 1 0 dx |
78             | 0 1 dy |
79             | 0 0  1 |
80 
81         @param dx  horizontal translation
82         @param dy  vertical translation
83         @return    SkMatrix with translation
84     */
MakeTrans(SkScalar dx,SkScalar dy)85     static SkMatrix SK_WARN_UNUSED_RESULT MakeTrans(SkScalar dx, SkScalar dy) {
86         SkMatrix m;
87         m.setTranslate(dx, dy);
88         return m;
89     }
90 
91     /** Sets SkMatrix to:
92 
93             | scaleX  skewX transX |
94             |  skewY scaleY transY |
95             |  pers0  pers1  pers2 |
96 
97         @param scaleX  horizontal scale factor
98         @param skewX   horizontal skew factor
99         @param transX  horizontal translation
100         @param skewY   vertical skew factor
101         @param scaleY  vertical scale factor
102         @param transY  vertical translation
103         @param pers0   input x-axis perspective factor
104         @param pers1   input y-axis perspective factor
105         @param pers2   perspective scale factor
106         @return        SkMatrix constructed from parameters
107     */
MakeAll(SkScalar scaleX,SkScalar skewX,SkScalar transX,SkScalar skewY,SkScalar scaleY,SkScalar transY,SkScalar pers0,SkScalar pers1,SkScalar pers2)108     static SkMatrix SK_WARN_UNUSED_RESULT MakeAll(SkScalar scaleX, SkScalar skewX,  SkScalar transX,
109                                                   SkScalar skewY,  SkScalar scaleY, SkScalar transY,
110                                                   SkScalar pers0, SkScalar pers1, SkScalar pers2) {
111         SkMatrix m;
112         m.setAll(scaleX, skewX, transX, skewY, scaleY, transY, pers0, pers1, pers2);
113         return m;
114     }
115 
116     /** \enum SkMatrix::TypeMask
117         Enum of bit fields for mask returned by getType().
118         Used to identify the complexity of SkMatrix, to optimize performance.
119     */
120     enum TypeMask {
121         kIdentity_Mask    = 0,    //!< identity SkMatrix; all bits clear
122         kTranslate_Mask   = 0x01, //!< translation SkMatrix
123         kScale_Mask       = 0x02, //!< scale SkMatrix
124         kAffine_Mask      = 0x04, //!< skew or rotate SkMatrix
125         kPerspective_Mask = 0x08, //!< perspective SkMatrix
126     };
127 
128     /** Returns a bit field describing the transformations the matrix may
129         perform. The bit field is computed conservatively, so it may include
130         false positives. For example, when kPerspective_Mask is set, all
131         other bits are set.
132 
133         @return  kIdentity_Mask, or combinations of: kTranslate_Mask, kScale_Mask,
134                  kAffine_Mask, kPerspective_Mask
135     */
getType()136     TypeMask getType() const {
137         if (fTypeMask & kUnknown_Mask) {
138             fTypeMask = this->computeTypeMask();
139         }
140         // only return the public masks
141         return (TypeMask)(fTypeMask & 0xF);
142     }
143 
144     /** Returns true if SkMatrix is identity.  Identity matrix is:
145 
146             | 1 0 0 |
147             | 0 1 0 |
148             | 0 0 1 |
149 
150         @return  true if SkMatrix has no effect
151     */
isIdentity()152     bool isIdentity() const {
153         return this->getType() == 0;
154     }
155 
156     /** Returns true if SkMatrix at most scales and translates. SkMatrix may be identity,
157         contain only scale elements, only translate elements, or both. SkMatrix form is:
158 
159             | scale-x    0    translate-x |
160             |    0    scale-y translate-y |
161             |    0       0         1      |
162 
163         @return  true if SkMatrix is identity; or scales, translates, or both
164     */
isScaleTranslate()165     bool isScaleTranslate() const {
166         return !(this->getType() & ~(kScale_Mask | kTranslate_Mask));
167     }
168 
169     /** Returns true if SkMatrix is identity, or translates. SkMatrix form is:
170 
171             | 1 0 translate-x |
172             | 0 1 translate-y |
173             | 0 0      1      |
174 
175         @return  true if SkMatrix is identity, or translates
176     */
isTranslate()177     bool isTranslate() const { return !(this->getType() & ~(kTranslate_Mask)); }
178 
179     /** Returns true SkMatrix maps SkRect to another SkRect. If true, SkMatrix is identity,
180         or scales, or rotates a multiple of 90 degrees, or mirrors on axes. In all
181         cases, SkMatrix may also have translation. SkMatrix form is either:
182 
183             | scale-x    0    translate-x |
184             |    0    scale-y translate-y |
185             |    0       0         1      |
186 
187         or
188 
189             |    0     rotate-x translate-x |
190             | rotate-y    0     translate-y |
191             |    0        0          1      |
192 
193         for non-zero values of scale-x, scale-y, rotate-x, and rotate-y.
194 
195         Also called preservesAxisAlignment(); use the one that provides better inline
196         documentation.
197 
198         @return  true if SkMatrix maps one SkRect into another
199     */
rectStaysRect()200     bool rectStaysRect() const {
201         if (fTypeMask & kUnknown_Mask) {
202             fTypeMask = this->computeTypeMask();
203         }
204         return (fTypeMask & kRectStaysRect_Mask) != 0;
205     }
206 
207     /** Returns true SkMatrix maps SkRect to another SkRect. If true, SkMatrix is identity,
208         or scales, or rotates a multiple of 90 degrees, or mirrors on axes. In all
209         cases, SkMatrix may also have translation. SkMatrix form is either:
210 
211             | scale-x    0    translate-x |
212             |    0    scale-y translate-y |
213             |    0       0         1      |
214 
215         or
216 
217             |    0     rotate-x translate-x |
218             | rotate-y    0     translate-y |
219             |    0        0          1      |
220 
221         for non-zero values of scale-x, scale-y, rotate-x, and rotate-y.
222 
223         Also called rectStaysRect(); use the one that provides better inline
224         documentation.
225 
226         @return  true if SkMatrix maps one SkRect into another
227     */
preservesAxisAlignment()228     bool preservesAxisAlignment() const { return this->rectStaysRect(); }
229 
230     /** Returns true if the matrix contains perspective elements. SkMatrix form is:
231 
232             |       --            --              --          |
233             |       --            --              --          |
234             | perspective-x  perspective-y  perspective-scale |
235 
236         where perspective-x or perspective-y is non-zero, or perspective-scale is
237         not one. All other elements may have any value.
238 
239         @return  true if SkMatrix is in most general form
240     */
hasPerspective()241     bool hasPerspective() const {
242         return SkToBool(this->getPerspectiveTypeMaskOnly() &
243                         kPerspective_Mask);
244     }
245 
246     /** Returns true if SkMatrix contains only translation, rotation, reflection, and
247         uniform scale.
248         Returns false if SkMatrix contains different scales, skewing, perspective, or
249         degenerate forms that collapse to a line or point.
250 
251         Describes that the SkMatrix makes rendering with and without the matrix are
252         visually alike; a transformed circle remains a circle. Mathematically, this is
253         referred to as similarity of a Euclidean space, or a similarity transformation.
254 
255         Preserves right angles, keeping the arms of the angle equal lengths.
256 
257         @param tol  to be deprecated
258         @return     true if SkMatrix only rotates, uniformly scales, translates
259     */
260     bool isSimilarity(SkScalar tol = SK_ScalarNearlyZero) const;
261 
262     /** Returns true if SkMatrix contains only translation, rotation, reflection, and
263         scale. Scale may differ along rotated axes.
264         Returns false if SkMatrix skewing, perspective, or degenerate forms that collapse
265         to a line or point.
266 
267         Preserves right angles, but not requiring that the arms of the angle
268         retain equal lengths.
269 
270         @param tol  to be deprecated
271         @return     true if SkMatrix only rotates, scales, translates
272     */
273     bool preservesRightAngles(SkScalar tol = SK_ScalarNearlyZero) const;
274 
275     /** SkMatrix organizes its values in row order. These members correspond to
276         each value in SkMatrix.
277     */
278     static constexpr int kMScaleX = 0; //!< horizontal scale factor
279     static constexpr int kMSkewX  = 1; //!< horizontal skew factor
280     static constexpr int kMTransX = 2; //!< horizontal translation
281     static constexpr int kMSkewY  = 3; //!< vertical skew factor
282     static constexpr int kMScaleY = 4; //!< vertical scale factor
283     static constexpr int kMTransY = 5; //!< vertical translation
284     static constexpr int kMPersp0 = 6; //!< input x perspective factor
285     static constexpr int kMPersp1 = 7; //!< input y perspective factor
286     static constexpr int kMPersp2 = 8; //!< perspective bias
287 
288     /** Affine arrays are in column major order to match the matrix used by
289         PDF and XPS.
290     */
291     static constexpr int kAScaleX = 0; //!< horizontal scale factor
292     static constexpr int kASkewY  = 1; //!< vertical skew factor
293     static constexpr int kASkewX  = 2; //!< horizontal skew factor
294     static constexpr int kAScaleY = 3; //!< vertical scale factor
295     static constexpr int kATransX = 4; //!< horizontal translation
296     static constexpr int kATransY = 5; //!< vertical translation
297 
298     /** Returns one matrix value. Asserts if index is out of range and SK_DEBUG is
299         defined.
300 
301         @param index  one of: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY,
302                       kMPersp0, kMPersp1, kMPersp2
303         @return       value corresponding to index
304     */
305     SkScalar operator[](int index) const {
306         SkASSERT((unsigned)index < 9);
307         return fMat[index];
308     }
309 
310     /** Returns one matrix value. Asserts if index is out of range and SK_DEBUG is
311         defined.
312 
313         @param index  one of: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY,
314                       kMPersp0, kMPersp1, kMPersp2
315         @return       value corresponding to index
316     */
get(int index)317     SkScalar get(int index) const {
318         SkASSERT((unsigned)index < 9);
319         return fMat[index];
320     }
321 
322     /** Returns scale factor multiplied by x-axis input, contributing to x-axis output.
323         With mapPoints(), scales SkPoint along the x-axis.
324 
325         @return  horizontal scale factor
326     */
getScaleX()327     SkScalar getScaleX() const { return fMat[kMScaleX]; }
328 
329     /** Returns scale factor multiplied by y-axis input, contributing to y-axis output.
330         With mapPoints(), scales SkPoint along the y-axis.
331 
332         @return  vertical scale factor
333     */
getScaleY()334     SkScalar getScaleY() const { return fMat[kMScaleY]; }
335 
336     /** Returns scale factor multiplied by x-axis input, contributing to y-axis output.
337         With mapPoints(), skews SkPoint along the y-axis.
338         Skewing both axes can rotate SkPoint.
339 
340         @return  vertical skew factor
341     */
getSkewY()342     SkScalar getSkewY() const { return fMat[kMSkewY]; }
343 
344     /** Returns scale factor multiplied by y-axis input, contributing to x-axis output.
345         With mapPoints(), skews SkPoint along the x-axis.
346         Skewing both axes can rotate SkPoint.
347 
348         @return  horizontal scale factor
349     */
getSkewX()350     SkScalar getSkewX() const { return fMat[kMSkewX]; }
351 
352     /** Returns translation contributing to x-axis output.
353         With mapPoints(), moves SkPoint along the x-axis.
354 
355         @return  horizontal translation factor
356     */
getTranslateX()357     SkScalar getTranslateX() const { return fMat[kMTransX]; }
358 
359     /** Returns translation contributing to y-axis output.
360         With mapPoints(), moves SkPoint along the y-axis.
361 
362         @return  vertical translation factor
363     */
getTranslateY()364     SkScalar getTranslateY() const { return fMat[kMTransY]; }
365 
366     /** Returns factor scaling input x-axis relative to input y-axis.
367 
368         @return  input x-axis perspective factor
369     */
getPerspX()370     SkScalar getPerspX() const { return fMat[kMPersp0]; }
371 
372     /** Returns factor scaling input y-axis relative to input x-axis.
373 
374         @return  input y-axis perspective factor
375     */
getPerspY()376     SkScalar getPerspY() const { return fMat[kMPersp1]; }
377 
378     /** Returns writable SkMatrix value. Asserts if index is out of range and SK_DEBUG is
379         defined. Clears internal cache anticipating that caller will change SkMatrix value.
380 
381         Next call to read SkMatrix state may recompute cache; subsequent writes to SkMatrix
382         value must be followed by dirtyMatrixTypeCache().
383 
384         @param index  one of: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY,
385                       kMPersp0, kMPersp1, kMPersp2
386         @return       writable value corresponding to index
387     */
388     SkScalar& operator[](int index) {
389         SkASSERT((unsigned)index < 9);
390         this->setTypeMask(kUnknown_Mask);
391         return fMat[index];
392     }
393 
394     /** Sets SkMatrix value. Asserts if index is out of range and SK_DEBUG is
395         defined. Safer than operator[]; internal cache is always maintained.
396 
397         @param index  one of: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY,
398                       kMPersp0, kMPersp1, kMPersp2
399         @param value  scalar to store in SkMatrix
400     */
set(int index,SkScalar value)401     SkMatrix& set(int index, SkScalar value) {
402         SkASSERT((unsigned)index < 9);
403         fMat[index] = value;
404         this->setTypeMask(kUnknown_Mask);
405         return *this;
406     }
407 
408     /** Sets horizontal scale factor.
409 
410         @param v  horizontal scale factor to store
411     */
setScaleX(SkScalar v)412     SkMatrix& setScaleX(SkScalar v) { return this->set(kMScaleX, v); }
413 
414     /** Sets vertical scale factor.
415 
416         @param v  vertical scale factor to store
417     */
setScaleY(SkScalar v)418     SkMatrix& setScaleY(SkScalar v) { return this->set(kMScaleY, v); }
419 
420     /** Sets vertical skew factor.
421 
422         @param v  vertical skew factor to store
423     */
setSkewY(SkScalar v)424     SkMatrix& setSkewY(SkScalar v) { return this->set(kMSkewY, v); }
425 
426     /** Sets horizontal skew factor.
427 
428         @param v  horizontal skew factor to store
429     */
setSkewX(SkScalar v)430     SkMatrix& setSkewX(SkScalar v) { return this->set(kMSkewX, v); }
431 
432     /** Sets horizontal translation.
433 
434         @param v  horizontal translation to store
435     */
setTranslateX(SkScalar v)436     SkMatrix& setTranslateX(SkScalar v) { return this->set(kMTransX, v); }
437 
438     /** Sets vertical translation.
439 
440         @param v  vertical translation to store
441     */
setTranslateY(SkScalar v)442     SkMatrix& setTranslateY(SkScalar v) { return this->set(kMTransY, v); }
443 
444     /** Sets input x-axis perspective factor, which causes mapXY() to vary input x-axis values
445         inversely proportional to input y-axis values.
446 
447         @param v  perspective factor
448     */
setPerspX(SkScalar v)449     SkMatrix& setPerspX(SkScalar v) { return this->set(kMPersp0, v); }
450 
451     /** Sets input y-axis perspective factor, which causes mapXY() to vary input y-axis values
452         inversely proportional to input x-axis values.
453 
454         @param v  perspective factor
455     */
setPerspY(SkScalar v)456     SkMatrix& setPerspY(SkScalar v) { return this->set(kMPersp1, v); }
457 
458     /** Sets all values from parameters. Sets matrix to:
459 
460             | scaleX  skewX transX |
461             |  skewY scaleY transY |
462             | persp0 persp1 persp2 |
463 
464         @param scaleX  horizontal scale factor to store
465         @param skewX   horizontal skew factor to store
466         @param transX  horizontal translation to store
467         @param skewY   vertical skew factor to store
468         @param scaleY  vertical scale factor to store
469         @param transY  vertical translation to store
470         @param persp0  input x-axis values perspective factor to store
471         @param persp1  input y-axis values perspective factor to store
472         @param persp2  perspective scale factor to store
473     */
setAll(SkScalar scaleX,SkScalar skewX,SkScalar transX,SkScalar skewY,SkScalar scaleY,SkScalar transY,SkScalar persp0,SkScalar persp1,SkScalar persp2)474     SkMatrix& setAll(SkScalar scaleX, SkScalar skewX,  SkScalar transX,
475                 SkScalar skewY,  SkScalar scaleY, SkScalar transY,
476                 SkScalar persp0, SkScalar persp1, SkScalar persp2) {
477         fMat[kMScaleX] = scaleX;
478         fMat[kMSkewX]  = skewX;
479         fMat[kMTransX] = transX;
480         fMat[kMSkewY]  = skewY;
481         fMat[kMScaleY] = scaleY;
482         fMat[kMTransY] = transY;
483         fMat[kMPersp0] = persp0;
484         fMat[kMPersp1] = persp1;
485         fMat[kMPersp2] = persp2;
486         this->setTypeMask(kUnknown_Mask);
487         return *this;
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     SkMatrix& 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     SkMatrix& 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     SkMatrix& setIdentity() { return this->reset(); }
539 
540     /** Sets SkMatrix to translate by (dx, dy).
541 
542         @param dx  horizontal translation
543         @param dy  vertical translation
544     */
545     SkMatrix& 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     SkMatrix& setTranslate(const SkVector& v) { return 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     SkMatrix& 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     SkMatrix& 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     SkMatrix& 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     SkMatrix& 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     SkMatrix& 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     SkMatrix& 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     SkMatrix& 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     SkMatrix& 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     SkMatrix& 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     SkMatrix& 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     SkMatrix& 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     SkMatrix& 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     SkMatrix& 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     SkMatrix& 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     SkMatrix& 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     SkMatrix& 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     SkMatrix& 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     SkMatrix& 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     SkMatrix& 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     SkMatrix& 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     SkMatrix& 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     SkMatrix& 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     SkMatrix& 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     SkMatrix& 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     SkMatrix& 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     SkMatrix& 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     */
1228     void mapPoints(SkPoint dst[], const SkPoint src[], int count) const;
1229 
1230     /** Maps pts SkPoint array of length count in place. SkPoint are mapped by multiplying
1231         each SkPoint by SkMatrix. Given:
1232 
1233                      | A B C |        | x |
1234             Matrix = | D E F |,  pt = | y |
1235                      | G H I |        | 1 |
1236 
1237         where
1238 
1239             for (i = 0; i < count; ++i) {
1240                 x = pts[i].fX
1241                 y = pts[i].fY
1242             }
1243 
1244         each resulting pts SkPoint is computed as:
1245 
1246                           |A B C| |x|                               Ax+By+C   Dx+Ey+F
1247             Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------
1248                           |G H I| |1|                               Gx+Hy+I   Gx+Hy+I
1249 
1250         @param pts    storage for mapped SkPoint
1251         @param count  number of SkPoint to transform
1252     */
mapPoints(SkPoint pts[],int count)1253     void mapPoints(SkPoint pts[], int count) const {
1254         this->mapPoints(pts, pts, count);
1255     }
1256 
1257     /** Maps src SkPoint3 array of length count to dst SkPoint3 array, which must of length count or
1258         greater. SkPoint3 array is mapped by multiplying each SkPoint3 by SkMatrix. Given:
1259 
1260                      | A B C |         | x |
1261             Matrix = | D E F |,  src = | y |
1262                      | G H I |         | z |
1263 
1264         each resulting dst SkPoint is computed as:
1265 
1266                            |A B C| |x|
1267             Matrix * src = |D E F| |y| = |Ax+By+Cz Dx+Ey+Fz Gx+Hy+Iz|
1268                            |G H I| |z|
1269 
1270         @param dst    storage for mapped SkPoint3 array
1271         @param src    SkPoint3 array to transform
1272         @param count  items in SkPoint3 array to transform
1273     */
1274     void mapHomogeneousPoints(SkPoint3 dst[], const SkPoint3 src[], int count) const;
1275 
1276     /** Maps SkPoint (x, y) to result. SkPoint is mapped by multiplying by SkMatrix. Given:
1277 
1278                      | A B C |        | x |
1279             Matrix = | D E F |,  pt = | y |
1280                      | G H I |        | 1 |
1281 
1282         result 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         @param x       x-axis value of SkPoint to map
1289         @param y       y-axis value of SkPoint to map
1290         @param result  storage for mapped SkPoint
1291     */
1292     void mapXY(SkScalar x, SkScalar y, SkPoint* result) const;
1293 
1294     /** Returns SkPoint (x, y) multiplied by SkMatrix. Given:
1295 
1296                      | A B C |        | x |
1297             Matrix = | D E F |,  pt = | y |
1298                      | G H I |        | 1 |
1299 
1300         result is computed as:
1301 
1302                           |A B C| |x|                               Ax+By+C   Dx+Ey+F
1303             Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------
1304                           |G H I| |1|                               Gx+Hy+I   Gx+Hy+I
1305 
1306         @param x  x-axis value of SkPoint to map
1307         @param y  y-axis value of SkPoint to map
1308         @return   mapped SkPoint
1309     */
mapXY(SkScalar x,SkScalar y)1310     SkPoint mapXY(SkScalar x, SkScalar y) const {
1311         SkPoint result;
1312         this->mapXY(x,y, &result);
1313         return result;
1314     }
1315 
1316     /** Maps src vector array of length count to vector SkPoint array of equal or greater
1317         length. Vectors are mapped by multiplying each vector by SkMatrix, treating
1318         SkMatrix translation as zero. Given:
1319 
1320                      | A B 0 |         | x |
1321             Matrix = | D E 0 |,  src = | y |
1322                      | G H I |         | 1 |
1323 
1324         where
1325 
1326             for (i = 0; i < count; ++i) {
1327                 x = src[i].fX
1328                 y = src[i].fY
1329             }
1330 
1331         each dst vector is computed as:
1332 
1333                            |A B 0| |x|                            Ax+By     Dx+Ey
1334             Matrix * src = |D E 0| |y| = |Ax+By Dx+Ey Gx+Hy+I| = ------- , -------
1335                            |G H I| |1|                           Gx+Hy+I   Gx+Hy+I
1336 
1337         src and dst may point to the same storage.
1338 
1339         @param dst    storage for mapped vectors
1340         @param src    vectors to transform
1341         @param count  number of vectors to transform
1342     */
1343     void mapVectors(SkVector dst[], const SkVector src[], int count) const;
1344 
1345     /** Maps vecs vector array of length count in place, multiplying each vector by
1346         SkMatrix, treating SkMatrix translation as zero. Given:
1347 
1348                      | A B 0 |         | x |
1349             Matrix = | D E 0 |,  vec = | y |
1350                      | G H I |         | 1 |
1351 
1352         where
1353 
1354             for (i = 0; i < count; ++i) {
1355                 x = vecs[i].fX
1356                 y = vecs[i].fY
1357             }
1358 
1359         each result vector is computed as:
1360 
1361                            |A B 0| |x|                            Ax+By     Dx+Ey
1362             Matrix * vec = |D E 0| |y| = |Ax+By Dx+Ey Gx+Hy+I| = ------- , -------
1363                            |G H I| |1|                           Gx+Hy+I   Gx+Hy+I
1364 
1365         @param vecs   vectors to transform, and storage for mapped vectors
1366         @param count  number of vectors to transform
1367     */
mapVectors(SkVector vecs[],int count)1368     void mapVectors(SkVector vecs[], int count) const {
1369         this->mapVectors(vecs, vecs, count);
1370     }
1371 
1372     /** Maps vector (dx, dy) to result. Vector is mapped by multiplying by SkMatrix,
1373         treating SkMatrix translation as zero. Given:
1374 
1375                      | A B 0 |         | dx |
1376             Matrix = | D E 0 |,  vec = | dy |
1377                      | G H I |         |  1 |
1378 
1379         each result vector is computed as:
1380 
1381                        |A B 0| |dx|                                        A*dx+B*dy     D*dx+E*dy
1382         Matrix * vec = |D E 0| |dy| = |A*dx+B*dy D*dx+E*dy G*dx+H*dy+I| = ----------- , -----------
1383                        |G H I| | 1|                                       G*dx+H*dy+I   G*dx+*dHy+I
1384 
1385         @param dx      x-axis value of vector to map
1386         @param dy      y-axis value of vector to map
1387         @param result  storage for mapped vector
1388     */
mapVector(SkScalar dx,SkScalar dy,SkVector * result)1389     void mapVector(SkScalar dx, SkScalar dy, SkVector* result) const {
1390         SkVector vec = { dx, dy };
1391         this->mapVectors(result, &vec, 1);
1392     }
1393 
1394     /** Returns vector (dx, dy) multiplied by SkMatrix, treating SkMatrix translation as zero.
1395         Given:
1396 
1397                      | A B 0 |         | dx |
1398             Matrix = | D E 0 |,  vec = | dy |
1399                      | G H I |         |  1 |
1400 
1401         each result vector is computed as:
1402 
1403                        |A B 0| |dx|                                        A*dx+B*dy     D*dx+E*dy
1404         Matrix * vec = |D E 0| |dy| = |A*dx+B*dy D*dx+E*dy G*dx+H*dy+I| = ----------- , -----------
1405                        |G H I| | 1|                                       G*dx+H*dy+I   G*dx+*dHy+I
1406 
1407         @param dx  x-axis value of vector to map
1408         @param dy  y-axis value of vector to map
1409         @return    mapped vector
1410     */
mapVector(SkScalar dx,SkScalar dy)1411     SkVector mapVector(SkScalar dx, SkScalar dy) const {
1412         SkVector vec = { dx, dy };
1413         this->mapVectors(&vec, &vec, 1);
1414         return vec;
1415     }
1416 
1417     /** Sets dst to bounds of src corners mapped by SkMatrix.
1418         Returns true if mapped corners are dst corners.
1419 
1420         Returned value is the same as calling rectStaysRect().
1421 
1422         @param dst  storage for bounds of mapped SkPoint
1423         @param src  SkRect to map
1424         @return     true if dst is equivalent to mapped src
1425     */
1426     bool mapRect(SkRect* dst, const SkRect& src) const;
1427 
1428     /** Sets rect to bounds of rect corners mapped by SkMatrix.
1429         Returns true if mapped corners are computed rect corners.
1430 
1431         Returned value is the same as calling rectStaysRect().
1432 
1433         @param rect  rectangle to map, and storage for bounds of mapped corners
1434         @return      true if result is equivalent to mapped rect
1435     */
mapRect(SkRect * rect)1436     bool mapRect(SkRect* rect) const {
1437         return this->mapRect(rect, *rect);
1438     }
1439 
1440     /** Returns bounds of src corners mapped by SkMatrix.
1441 
1442         @param src  rectangle to map
1443         @return     mapped bounds
1444     */
mapRect(const SkRect & src)1445     SkRect mapRect(const SkRect& src) const {
1446         SkRect dst;
1447         (void)this->mapRect(&dst, src);
1448         return dst;
1449     }
1450 
1451     /** Maps four corners of rect to dst. SkPoint are mapped by multiplying each
1452         rect corner by SkMatrix. rect corner is processed in this order:
1453         (rect.fLeft, rect.fTop), (rect.fRight, rect.fTop), (rect.fRight, rect.fBottom),
1454         (rect.fLeft, rect.fBottom).
1455 
1456         rect may be empty: rect.fLeft may be greater than or equal to rect.fRight;
1457         rect.fTop may be greater than or equal to rect.fBottom.
1458 
1459         Given:
1460 
1461                      | A B C |        | x |
1462             Matrix = | D E F |,  pt = | y |
1463                      | G H I |        | 1 |
1464 
1465         where pt is initialized from each of (rect.fLeft, rect.fTop),
1466         (rect.fRight, rect.fTop), (rect.fRight, rect.fBottom), (rect.fLeft, rect.fBottom),
1467         each dst SkPoint is computed as:
1468 
1469                           |A B C| |x|                               Ax+By+C   Dx+Ey+F
1470             Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------
1471                           |G H I| |1|                               Gx+Hy+I   Gx+Hy+I
1472 
1473         @param dst   storage for mapped corner SkPoint
1474         @param rect  SkRect to map
1475     */
mapRectToQuad(SkPoint dst[4],const SkRect & rect)1476     void mapRectToQuad(SkPoint dst[4], const SkRect& rect) const {
1477         // This could potentially be faster if we only transformed each x and y of the rect once.
1478         rect.toQuad(dst);
1479         this->mapPoints(dst, 4);
1480     }
1481 
1482     /** Sets dst to bounds of src corners mapped by SkMatrix. If matrix contains
1483         elements other than scale or translate: asserts if SK_DEBUG is defined;
1484         otherwise, results are undefined.
1485 
1486         @param dst  storage for bounds of mapped SkPoint
1487         @param src  SkRect to map
1488     */
1489     void mapRectScaleTranslate(SkRect* dst, const SkRect& src) const;
1490 
1491     /** Returns geometric mean radius of ellipse formed by constructing circle of
1492         size radius, and mapping constructed circle with SkMatrix. The result squared is
1493         equal to the major axis length times the minor axis length.
1494         Result is not meaningful if SkMatrix contains perspective elements.
1495 
1496         @param radius  circle size to map
1497         @return        average mapped radius
1498     */
1499     SkScalar mapRadius(SkScalar radius) const;
1500 
1501     /** Returns true if a unit step on x-axis at some y-axis value mapped through SkMatrix
1502         can be represented by a constant vector. Returns true if getType() returns
1503         kIdentity_Mask, or combinations of: kTranslate_Mask, kScale_Mask, and kAffine_Mask.
1504 
1505         May return true if getType() returns kPerspective_Mask, but only when SkMatrix
1506         does not include rotation or skewing along the y-axis.
1507 
1508         @return  true if SkMatrix does not have complex perspective
1509     */
1510     bool isFixedStepInX() const;
1511 
1512     /** Returns vector representing a unit step on x-axis at y mapped through SkMatrix.
1513         If isFixedStepInX() is false, returned value is undefined.
1514 
1515         @param y  position of line parallel to x-axis
1516         @return   vector advance of mapped unit step on x-axis
1517     */
1518     SkVector fixedStepInX(SkScalar y) const;
1519 
1520     /** Returns true if SkMatrix equals m, using an efficient comparison.
1521 
1522         Returns false when the sign of zero values is the different; when one
1523         matrix has positive zero value and the other has negative zero value.
1524 
1525         Returns true even when both SkMatrix contain NaN.
1526 
1527         NaN never equals any value, including itself. To improve performance, NaN values
1528         are treated as bit patterns that are equal if their bit patterns are equal.
1529 
1530         @param m  SkMatrix to compare
1531         @return   true if m and SkMatrix are represented by identical bit patterns
1532     */
cheapEqualTo(const SkMatrix & m)1533     bool cheapEqualTo(const SkMatrix& m) const {
1534         return 0 == memcmp(fMat, m.fMat, sizeof(fMat));
1535     }
1536 
1537     /** Compares a and b; returns true if a and b are numerically equal. Returns true
1538         even if sign of zero values are different. Returns false if either SkMatrix
1539         contains NaN, even if the other SkMatrix also contains NaN.
1540 
1541         @param a  SkMatrix to compare
1542         @param b  SkMatrix to compare
1543         @return   true if SkMatrix a and SkMatrix b are numerically equal
1544     */
1545     friend SK_API bool operator==(const SkMatrix& a, const SkMatrix& b);
1546 
1547     /** Compares a and b; returns true if a and b are not numerically equal. Returns false
1548         even if sign of zero values are different. Returns true if either SkMatrix
1549         contains NaN, even if the other SkMatrix also contains NaN.
1550 
1551         @param a  SkMatrix to compare
1552         @param b  SkMatrix to compare
1553         @return   true if SkMatrix a and SkMatrix b are numerically not equal
1554     */
1555     friend SK_API bool operator!=(const SkMatrix& a, const SkMatrix& b) {
1556         return !(a == b);
1557     }
1558 
1559     /** Writes text representation of SkMatrix to standard output. Floating point values
1560         are written with limited precision; it may not be possible to reconstruct
1561         original SkMatrix from output.
1562     */
1563     void dump() const;
1564 
1565     /** Returns the minimum scaling factor of SkMatrix by decomposing the scaling and
1566         skewing elements.
1567         Returns -1 if scale factor overflows or SkMatrix contains perspective.
1568 
1569         @return  minimum scale factor
1570     */
1571     SkScalar getMinScale() const;
1572 
1573     /** Returns the maximum 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  maximum scale factor
1578     */
1579     SkScalar getMaxScale() const;
1580 
1581     /** Sets scaleFactors[0] to the minimum scaling factor, and scaleFactors[1] to the
1582         maximum scaling factor. Scaling factors are computed by decomposing
1583         the SkMatrix scaling and skewing elements.
1584 
1585         Returns true if scaleFactors are found; otherwise, returns false and sets
1586         scaleFactors to undefined values.
1587 
1588         @param scaleFactors  storage for minimum and maximum scale factors
1589         @return              true if scale factors were computed correctly
1590     */
1591     bool SK_WARN_UNUSED_RESULT getMinMaxScales(SkScalar scaleFactors[2]) const;
1592 
1593     /** Decomposes SkMatrix into scale components and whatever remains. Returns false if
1594         SkMatrix could not be decomposed.
1595 
1596         Sets scale to portion of SkMatrix that scale axes. Sets remaining to SkMatrix
1597         with scaling factored out. remaining may be passed as nullptr
1598         to determine if SkMatrix can be decomposed without computing remainder.
1599 
1600         Returns true if scale components are found. scale and remaining are
1601         unchanged if SkMatrix contains perspective; scale factors are not finite, or
1602         are nearly zero.
1603 
1604         On success: Matrix = Remaining * scale.
1605 
1606         @param scale      axes scaling factors; may be nullptr
1607         @param remaining  SkMatrix without scaling; may be nullptr
1608         @return           true if scale can be computed
1609     */
1610     bool decomposeScale(SkSize* scale, SkMatrix* remaining = nullptr) const;
1611 
1612     /** Returns reference to const identity SkMatrix. Returned SkMatrix is set to:
1613 
1614             | 1 0 0 |
1615             | 0 1 0 |
1616             | 0 0 1 |
1617 
1618         @return  const identity SkMatrix
1619     */
1620     static const SkMatrix& I();
1621 
1622     /** Returns reference to a const SkMatrix with invalid values. Returned SkMatrix is set
1623         to:
1624 
1625             | SK_ScalarMax SK_ScalarMax SK_ScalarMax |
1626             | SK_ScalarMax SK_ScalarMax SK_ScalarMax |
1627             | SK_ScalarMax SK_ScalarMax SK_ScalarMax |
1628 
1629         @return  const invalid SkMatrix
1630     */
1631     static const SkMatrix& InvalidMatrix();
1632 
1633     /** Returns SkMatrix a multiplied by SkMatrix b.
1634 
1635         Given:
1636 
1637                 | A B C |      | J K L |
1638             a = | D E F |, b = | M N O |
1639                 | G H I |      | P Q R |
1640 
1641         sets SkMatrix to:
1642 
1643                     | A B C |   | J K L |   | AJ+BM+CP AK+BN+CQ AL+BO+CR |
1644             a * b = | D E F | * | M N O | = | DJ+EM+FP DK+EN+FQ DL+EO+FR |
1645                     | G H I |   | P Q R |   | GJ+HM+IP GK+HN+IQ GL+HO+IR |
1646 
1647         @param a  SkMatrix on left side of multiply expression
1648         @param b  SkMatrix on right side of multiply expression
1649         @return   SkMatrix computed from a times b
1650     */
Concat(const SkMatrix & a,const SkMatrix & b)1651     static SkMatrix Concat(const SkMatrix& a, const SkMatrix& b) {
1652         SkMatrix result;
1653         result.setConcat(a, b);
1654         return result;
1655     }
1656 
1657     /** Sets internal cache to unknown state. Use to force update after repeated
1658         modifications to SkMatrix element reference returned by operator[](int index).
1659     */
dirtyMatrixTypeCache()1660     void dirtyMatrixTypeCache() {
1661         this->setTypeMask(kUnknown_Mask);
1662     }
1663 
1664     /** Initializes SkMatrix with scale and translate elements.
1665 
1666             | sx  0 tx |
1667             |  0 sy ty |
1668             |  0  0  1 |
1669 
1670         @param sx  horizontal scale factor to store
1671         @param sy  vertical scale factor to store
1672         @param tx  horizontal translation to store
1673         @param ty  vertical translation to store
1674     */
setScaleTranslate(SkScalar sx,SkScalar sy,SkScalar tx,SkScalar ty)1675     void setScaleTranslate(SkScalar sx, SkScalar sy, SkScalar tx, SkScalar ty) {
1676         fMat[kMScaleX] = sx;
1677         fMat[kMSkewX]  = 0;
1678         fMat[kMTransX] = tx;
1679 
1680         fMat[kMSkewY]  = 0;
1681         fMat[kMScaleY] = sy;
1682         fMat[kMTransY] = ty;
1683 
1684         fMat[kMPersp0] = 0;
1685         fMat[kMPersp1] = 0;
1686         fMat[kMPersp2] = 1;
1687 
1688         unsigned mask = 0;
1689         if (sx != 1 || sy != 1) {
1690             mask |= kScale_Mask;
1691         }
1692         if (tx || ty) {
1693             mask |= kTranslate_Mask;
1694         }
1695         this->setTypeMask(mask | kRectStaysRect_Mask);
1696     }
1697 
1698     /** Returns true if all elements of the matrix are finite. Returns false if any
1699         element is infinity, or NaN.
1700 
1701         @return  true if matrix has only finite elements
1702     */
isFinite()1703     bool isFinite() const { return SkScalarsAreFinite(fMat, 9); }
1704 
1705 private:
1706     /** Set if the matrix will map a rectangle to another rectangle. This
1707         can be true if the matrix is scale-only, or rotates a multiple of
1708         90 degrees.
1709 
1710         This bit will be set on identity matrices
1711     */
1712     static constexpr int kRectStaysRect_Mask = 0x10;
1713 
1714     /** Set if the perspective bit is valid even though the rest of
1715         the matrix is Unknown.
1716     */
1717     static constexpr int kOnlyPerspectiveValid_Mask = 0x40;
1718 
1719     static constexpr int kUnknown_Mask = 0x80;
1720 
1721     static constexpr int kORableMasks = kTranslate_Mask |
1722                                         kScale_Mask |
1723                                         kAffine_Mask |
1724                                         kPerspective_Mask;
1725 
1726     static constexpr int kAllMasks = kTranslate_Mask |
1727                                      kScale_Mask |
1728                                      kAffine_Mask |
1729                                      kPerspective_Mask |
1730                                      kRectStaysRect_Mask;
1731 
1732     SkScalar         fMat[9];
1733     mutable uint32_t fTypeMask;
1734 
SkMatrix(SkScalar sx,SkScalar kx,SkScalar tx,SkScalar ky,SkScalar sy,SkScalar ty,SkScalar p0,SkScalar p1,SkScalar p2,uint32_t typeMask)1735     constexpr SkMatrix(SkScalar sx, SkScalar kx, SkScalar tx,
1736                        SkScalar ky, SkScalar sy, SkScalar ty,
1737                        SkScalar p0, SkScalar p1, SkScalar p2, uint32_t typeMask)
1738         : fMat{sx, kx, tx,
1739                ky, sy, ty,
1740                p0, p1, p2}
1741         , fTypeMask(typeMask) {}
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