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     */
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 = scale * Remaining.
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 
1735     static void ComputeInv(SkScalar dst[9], const SkScalar src[9], double invDet, bool isPersp);
1736 
1737     uint8_t computeTypeMask() const;
1738     uint8_t computePerspectiveTypeMask() const;
1739 
setTypeMask(int mask)1740     void setTypeMask(int mask) {
1741         // allow kUnknown or a valid mask
1742         SkASSERT(kUnknown_Mask == mask || (mask & kAllMasks) == mask ||
1743                  ((kUnknown_Mask | kOnlyPerspectiveValid_Mask) & mask)
1744                  == (kUnknown_Mask | kOnlyPerspectiveValid_Mask));
1745         fTypeMask = SkToU8(mask);
1746     }
1747 
orTypeMask(int mask)1748     void orTypeMask(int mask) {
1749         SkASSERT((mask & kORableMasks) == mask);
1750         fTypeMask = SkToU8(fTypeMask | mask);
1751     }
1752 
clearTypeMask(int mask)1753     void clearTypeMask(int mask) {
1754         // only allow a valid mask
1755         SkASSERT((mask & kAllMasks) == mask);
1756         fTypeMask = fTypeMask & ~mask;
1757     }
1758 
getPerspectiveTypeMaskOnly()1759     TypeMask getPerspectiveTypeMaskOnly() const {
1760         if ((fTypeMask & kUnknown_Mask) &&
1761             !(fTypeMask & kOnlyPerspectiveValid_Mask)) {
1762             fTypeMask = this->computePerspectiveTypeMask();
1763         }
1764         return (TypeMask)(fTypeMask & 0xF);
1765     }
1766 
1767     /** Returns true if we already know that the matrix is identity;
1768         false otherwise.
1769     */
isTriviallyIdentity()1770     bool isTriviallyIdentity() const {
1771         if (fTypeMask & kUnknown_Mask) {
1772             return false;
1773         }
1774         return ((fTypeMask & 0xF) == 0);
1775     }
1776 
updateTranslateMask()1777     inline void updateTranslateMask() {
1778         if ((fMat[kMTransX] != 0) | (fMat[kMTransY] != 0)) {
1779             fTypeMask |= kTranslate_Mask;
1780         } else {
1781             fTypeMask &= ~kTranslate_Mask;
1782         }
1783     }
1784 
1785     typedef void (*MapXYProc)(const SkMatrix& mat, SkScalar x, SkScalar y,
1786                                  SkPoint* result);
1787 
GetMapXYProc(TypeMask mask)1788     static MapXYProc GetMapXYProc(TypeMask mask) {
1789         SkASSERT((mask & ~kAllMasks) == 0);
1790         return gMapXYProcs[mask & kAllMasks];
1791     }
1792 
getMapXYProc()1793     MapXYProc getMapXYProc() const {
1794         return GetMapXYProc(this->getType());
1795     }
1796 
1797     typedef void (*MapPtsProc)(const SkMatrix& mat, SkPoint dst[],
1798                                   const SkPoint src[], int count);
1799 
GetMapPtsProc(TypeMask mask)1800     static MapPtsProc GetMapPtsProc(TypeMask mask) {
1801         SkASSERT((mask & ~kAllMasks) == 0);
1802         return gMapPtsProcs[mask & kAllMasks];
1803     }
1804 
getMapPtsProc()1805     MapPtsProc getMapPtsProc() const {
1806         return GetMapPtsProc(this->getType());
1807     }
1808 
1809     bool SK_WARN_UNUSED_RESULT invertNonIdentity(SkMatrix* inverse) const;
1810 
1811     static bool Poly2Proc(const SkPoint[], SkMatrix*);
1812     static bool Poly3Proc(const SkPoint[], SkMatrix*);
1813     static bool Poly4Proc(const SkPoint[], SkMatrix*);
1814 
1815     static void Identity_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
1816     static void Trans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
1817     static void Scale_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
1818     static void ScaleTrans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
1819     static void Rot_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
1820     static void RotTrans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
1821     static void Persp_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
1822 
1823     static const MapXYProc gMapXYProcs[];
1824 
1825     static void Identity_pts(const SkMatrix&, SkPoint[], const SkPoint[], int);
1826     static void Trans_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
1827     static void Scale_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
1828     static void ScaleTrans_pts(const SkMatrix&, SkPoint dst[], const SkPoint[],
1829                                int count);
1830     static void Persp_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
1831 
1832     static void Affine_vpts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
1833 
1834     static const MapPtsProc gMapPtsProcs[];
1835 
1836     // return the number of bytes written, whether or not buffer is null
1837     size_t writeToMemory(void* buffer) const;
1838     /**
1839      * Reads data from the buffer parameter
1840      *
1841      * @param buffer Memory to read from
1842      * @param length Amount of memory available in the buffer
1843      * @return number of bytes read (must be a multiple of 4) or
1844      *         0 if there was not enough memory available
1845      */
1846     size_t readFromMemory(const void* buffer, size_t length);
1847 
1848     friend class SkPerspIter;
1849     friend class SkMatrixPriv;
1850     friend class SkReader32;
1851     friend class SerializationTest;
1852 };
1853 SK_END_REQUIRE_DENSE
1854 
1855 #endif
1856