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