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