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