1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc.
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
68260a895869beaa4cab9f8b915e457728f41e561reed@google.com */
78260a895869beaa4cab9f8b915e457728f41e561reed@google.com
88260a895869beaa4cab9f8b915e457728f41e561reed@google.com#ifndef SkMatrix44_DEFINED
98260a895869beaa4cab9f8b915e457728f41e561reed@google.com#define SkMatrix44_DEFINED
108260a895869beaa4cab9f8b915e457728f41e561reed@google.com
118260a895869beaa4cab9f8b915e457728f41e561reed@google.com#include "SkMatrix.h"
128260a895869beaa4cab9f8b915e457728f41e561reed@google.com#include "SkScalar.h"
138260a895869beaa4cab9f8b915e457728f41e561reed@google.com
148260a895869beaa4cab9f8b915e457728f41e561reed@google.com#ifdef SK_MSCALAR_IS_DOUBLE
157d68335eb427547606497eb4edea81acce7891f9reed@google.com#ifdef SK_MSCALAR_IS_FLOAT
167d68335eb427547606497eb4edea81acce7891f9reed@google.com    #error "can't define MSCALAR both as DOUBLE and FLOAT"
177d68335eb427547606497eb4edea81acce7891f9reed@google.com#endif
188260a895869beaa4cab9f8b915e457728f41e561reed@google.com    typedef double SkMScalar;
197d68335eb427547606497eb4edea81acce7891f9reed@google.com
208260a895869beaa4cab9f8b915e457728f41e561reed@google.com    static inline double SkFloatToMScalar(float x) {
218260a895869beaa4cab9f8b915e457728f41e561reed@google.com        return static_cast<double>(x);
228260a895869beaa4cab9f8b915e457728f41e561reed@google.com    }
238260a895869beaa4cab9f8b915e457728f41e561reed@google.com    static inline float SkMScalarToFloat(double x) {
248260a895869beaa4cab9f8b915e457728f41e561reed@google.com        return static_cast<float>(x);
258260a895869beaa4cab9f8b915e457728f41e561reed@google.com    }
268260a895869beaa4cab9f8b915e457728f41e561reed@google.com    static inline double SkDoubleToMScalar(double x) {
278260a895869beaa4cab9f8b915e457728f41e561reed@google.com        return x;
288260a895869beaa4cab9f8b915e457728f41e561reed@google.com    }
298260a895869beaa4cab9f8b915e457728f41e561reed@google.com    static inline double SkMScalarToDouble(double x) {
308260a895869beaa4cab9f8b915e457728f41e561reed@google.com        return x;
318260a895869beaa4cab9f8b915e457728f41e561reed@google.com    }
32faccb8eb53f1bc745d3dd530d8df8b40e0dedc23tomhudson    static inline double SkMScalarAbs(double x) {
33faccb8eb53f1bc745d3dd530d8df8b40e0dedc23tomhudson        return fabs(x);
34faccb8eb53f1bc745d3dd530d8df8b40e0dedc23tomhudson    }
358260a895869beaa4cab9f8b915e457728f41e561reed@google.com    static const SkMScalar SK_MScalarPI = 3.141592653589793;
3639393e3ac309d4bedbc18bae98d3ebcb762501ddreed
3739393e3ac309d4bedbc18bae98d3ebcb762501ddreed    #define SkMScalarFloor(x)           sk_double_floor(x)
3839393e3ac309d4bedbc18bae98d3ebcb762501ddreed    #define SkMScalarCeil(x)            sk_double_ceil(x)
3939393e3ac309d4bedbc18bae98d3ebcb762501ddreed    #define SkMScalarRound(x)           sk_double_round(x)
4039393e3ac309d4bedbc18bae98d3ebcb762501ddreed
4139393e3ac309d4bedbc18bae98d3ebcb762501ddreed    #define SkMScalarFloorToInt(x)      sk_double_floor2int(x)
4239393e3ac309d4bedbc18bae98d3ebcb762501ddreed    #define SkMScalarCeilToInt(x)       sk_double_ceil2int(x)
4339393e3ac309d4bedbc18bae98d3ebcb762501ddreed    #define SkMScalarRoundToInt(x)      sk_double_round2int(x)
4439393e3ac309d4bedbc18bae98d3ebcb762501ddreed
4539393e3ac309d4bedbc18bae98d3ebcb762501ddreed
465596a69e9f7884e3042bceba071c468dee52aa7fvollick@chromium.org#elif defined SK_MSCALAR_IS_FLOAT
477d68335eb427547606497eb4edea81acce7891f9reed@google.com#ifdef SK_MSCALAR_IS_DOUBLE
487d68335eb427547606497eb4edea81acce7891f9reed@google.com    #error "can't define MSCALAR both as DOUBLE and FLOAT"
497d68335eb427547606497eb4edea81acce7891f9reed@google.com#endif
508260a895869beaa4cab9f8b915e457728f41e561reed@google.com    typedef float SkMScalar;
510264fb4543b0d8cebe00f1ee32433784f4ceb074skia.committer@gmail.com
528260a895869beaa4cab9f8b915e457728f41e561reed@google.com    static inline float SkFloatToMScalar(float x) {
538260a895869beaa4cab9f8b915e457728f41e561reed@google.com        return x;
548260a895869beaa4cab9f8b915e457728f41e561reed@google.com    }
558260a895869beaa4cab9f8b915e457728f41e561reed@google.com    static inline float SkMScalarToFloat(float x) {
568260a895869beaa4cab9f8b915e457728f41e561reed@google.com        return x;
578260a895869beaa4cab9f8b915e457728f41e561reed@google.com    }
588260a895869beaa4cab9f8b915e457728f41e561reed@google.com    static inline float SkDoubleToMScalar(double x) {
598260a895869beaa4cab9f8b915e457728f41e561reed@google.com        return static_cast<float>(x);
608260a895869beaa4cab9f8b915e457728f41e561reed@google.com    }
618260a895869beaa4cab9f8b915e457728f41e561reed@google.com    static inline double SkMScalarToDouble(float x) {
628260a895869beaa4cab9f8b915e457728f41e561reed@google.com        return static_cast<double>(x);
638260a895869beaa4cab9f8b915e457728f41e561reed@google.com    }
64faccb8eb53f1bc745d3dd530d8df8b40e0dedc23tomhudson    static inline float SkMScalarAbs(float x) {
65faccb8eb53f1bc745d3dd530d8df8b40e0dedc23tomhudson        return sk_float_abs(x);
66faccb8eb53f1bc745d3dd530d8df8b40e0dedc23tomhudson    }
678260a895869beaa4cab9f8b915e457728f41e561reed@google.com    static const SkMScalar SK_MScalarPI = 3.14159265f;
6839393e3ac309d4bedbc18bae98d3ebcb762501ddreed
6939393e3ac309d4bedbc18bae98d3ebcb762501ddreed    #define SkMScalarFloor(x)           sk_float_floor(x)
7039393e3ac309d4bedbc18bae98d3ebcb762501ddreed    #define SkMScalarCeil(x)            sk_float_ceil(x)
7139393e3ac309d4bedbc18bae98d3ebcb762501ddreed    #define SkMScalarRound(x)           sk_float_round(x)
7239393e3ac309d4bedbc18bae98d3ebcb762501ddreed
7339393e3ac309d4bedbc18bae98d3ebcb762501ddreed    #define SkMScalarFloorToInt(x)      sk_float_floor2int(x)
7439393e3ac309d4bedbc18bae98d3ebcb762501ddreed    #define SkMScalarCeilToInt(x)       sk_float_ceil2int(x)
7539393e3ac309d4bedbc18bae98d3ebcb762501ddreed    #define SkMScalarRoundToInt(x)      sk_float_round2int(x)
7639393e3ac309d4bedbc18bae98d3ebcb762501ddreed
778260a895869beaa4cab9f8b915e457728f41e561reed@google.com#endif
788260a895869beaa4cab9f8b915e457728f41e561reed@google.com
7939393e3ac309d4bedbc18bae98d3ebcb762501ddreed#define SkIntToMScalar(n)       static_cast<SkMScalar>(n)
8039393e3ac309d4bedbc18bae98d3ebcb762501ddreed
8139393e3ac309d4bedbc18bae98d3ebcb762501ddreed#define SkMScalarToScalar(x)    SkMScalarToFloat(x)
8239393e3ac309d4bedbc18bae98d3ebcb762501ddreed#define SkScalarToMScalar(x)    SkFloatToMScalar(x)
8372e49b8982586a5d8b0425f16d909c05a36ea8c3bsalomon@google.com
848260a895869beaa4cab9f8b915e457728f41e561reed@google.comstatic const SkMScalar SK_MScalar1 = 1;
858260a895869beaa4cab9f8b915e457728f41e561reed@google.com
868260a895869beaa4cab9f8b915e457728f41e561reed@google.com///////////////////////////////////////////////////////////////////////////////
878260a895869beaa4cab9f8b915e457728f41e561reed@google.com
888260a895869beaa4cab9f8b915e457728f41e561reed@google.comstruct SkVector4 {
898260a895869beaa4cab9f8b915e457728f41e561reed@google.com    SkScalar fData[4];
908260a895869beaa4cab9f8b915e457728f41e561reed@google.com
918260a895869beaa4cab9f8b915e457728f41e561reed@google.com    SkVector4() {
928260a895869beaa4cab9f8b915e457728f41e561reed@google.com        this->set(0, 0, 0, 1);
938260a895869beaa4cab9f8b915e457728f41e561reed@google.com    }
948260a895869beaa4cab9f8b915e457728f41e561reed@google.com    SkVector4(const SkVector4& src) {
958260a895869beaa4cab9f8b915e457728f41e561reed@google.com        memcpy(fData, src.fData, sizeof(fData));
968260a895869beaa4cab9f8b915e457728f41e561reed@google.com    }
978260a895869beaa4cab9f8b915e457728f41e561reed@google.com    SkVector4(SkScalar x, SkScalar y, SkScalar z, SkScalar w = SK_Scalar1) {
988260a895869beaa4cab9f8b915e457728f41e561reed@google.com        fData[0] = x;
998260a895869beaa4cab9f8b915e457728f41e561reed@google.com        fData[1] = y;
1008260a895869beaa4cab9f8b915e457728f41e561reed@google.com        fData[2] = z;
1018260a895869beaa4cab9f8b915e457728f41e561reed@google.com        fData[3] = w;
1028260a895869beaa4cab9f8b915e457728f41e561reed@google.com    }
1038260a895869beaa4cab9f8b915e457728f41e561reed@google.com
1048260a895869beaa4cab9f8b915e457728f41e561reed@google.com    SkVector4& operator=(const SkVector4& src) {
1058260a895869beaa4cab9f8b915e457728f41e561reed@google.com        memcpy(fData, src.fData, sizeof(fData));
1068260a895869beaa4cab9f8b915e457728f41e561reed@google.com        return *this;
1078260a895869beaa4cab9f8b915e457728f41e561reed@google.com    }
1088260a895869beaa4cab9f8b915e457728f41e561reed@google.com
1098260a895869beaa4cab9f8b915e457728f41e561reed@google.com    bool operator==(const SkVector4& v) {
1108260a895869beaa4cab9f8b915e457728f41e561reed@google.com        return fData[0] == v.fData[0] && fData[1] == v.fData[1] &&
1118260a895869beaa4cab9f8b915e457728f41e561reed@google.com               fData[2] == v.fData[2] && fData[3] == v.fData[3];
1128260a895869beaa4cab9f8b915e457728f41e561reed@google.com    }
1138260a895869beaa4cab9f8b915e457728f41e561reed@google.com    bool operator!=(const SkVector4& v) {
1148260a895869beaa4cab9f8b915e457728f41e561reed@google.com        return !(*this == v);
1158260a895869beaa4cab9f8b915e457728f41e561reed@google.com    }
1168260a895869beaa4cab9f8b915e457728f41e561reed@google.com    bool equals(SkScalar x, SkScalar y, SkScalar z, SkScalar w = SK_Scalar1) {
1178260a895869beaa4cab9f8b915e457728f41e561reed@google.com        return fData[0] == x && fData[1] == y &&
1188260a895869beaa4cab9f8b915e457728f41e561reed@google.com               fData[2] == z && fData[3] == w;
1198260a895869beaa4cab9f8b915e457728f41e561reed@google.com    }
1208260a895869beaa4cab9f8b915e457728f41e561reed@google.com
1218260a895869beaa4cab9f8b915e457728f41e561reed@google.com    void set(SkScalar x, SkScalar y, SkScalar z, SkScalar w = SK_Scalar1) {
1228260a895869beaa4cab9f8b915e457728f41e561reed@google.com        fData[0] = x;
1238260a895869beaa4cab9f8b915e457728f41e561reed@google.com        fData[1] = y;
1248260a895869beaa4cab9f8b915e457728f41e561reed@google.com        fData[2] = z;
1258260a895869beaa4cab9f8b915e457728f41e561reed@google.com        fData[3] = w;
1268260a895869beaa4cab9f8b915e457728f41e561reed@google.com    }
1278260a895869beaa4cab9f8b915e457728f41e561reed@google.com};
1288260a895869beaa4cab9f8b915e457728f41e561reed@google.com
1297cfb9c7b6186bf1e42b7d13466eab94470587e7etomhudson@google.comclass SK_API SkMatrix44 {
1308260a895869beaa4cab9f8b915e457728f41e561reed@google.compublic:
13157a54e33cfe771c792b1086ba67484cb95938d5dvollick@chromium.org
13257a54e33cfe771c792b1086ba67484cb95938d5dvollick@chromium.org    enum Uninitialized_Constructor {
13357a54e33cfe771c792b1086ba67484cb95938d5dvollick@chromium.org        kUninitialized_Constructor
13457a54e33cfe771c792b1086ba67484cb95938d5dvollick@chromium.org    };
13557a54e33cfe771c792b1086ba67484cb95938d5dvollick@chromium.org    enum Identity_Constructor {
13657a54e33cfe771c792b1086ba67484cb95938d5dvollick@chromium.org        kIdentity_Constructor
13757a54e33cfe771c792b1086ba67484cb95938d5dvollick@chromium.org    };
13857a54e33cfe771c792b1086ba67484cb95938d5dvollick@chromium.org
13957a54e33cfe771c792b1086ba67484cb95938d5dvollick@chromium.org    SkMatrix44(Uninitialized_Constructor) { }
14057a54e33cfe771c792b1086ba67484cb95938d5dvollick@chromium.org    SkMatrix44(Identity_Constructor) { this->setIdentity(); }
14157a54e33cfe771c792b1086ba67484cb95938d5dvollick@chromium.org
1424469938e92d779dff05e745559e67907bbf21e78reed@google.com    SK_ATTR_DEPRECATED("use the constructors that take an enum")
1437d68335eb427547606497eb4edea81acce7891f9reed@google.com    SkMatrix44() { this->setIdentity(); }
144d53025364a8062b5c72f3f9ed54a613a1ae17958reed@google.com
145d53025364a8062b5c72f3f9ed54a613a1ae17958reed@google.com    SkMatrix44(const SkMatrix44& src) {
146d53025364a8062b5c72f3f9ed54a613a1ae17958reed@google.com        memcpy(fMat, src.fMat, sizeof(fMat));
147d53025364a8062b5c72f3f9ed54a613a1ae17958reed@google.com        fTypeMask = src.fTypeMask;
148d53025364a8062b5c72f3f9ed54a613a1ae17958reed@google.com    }
149d53025364a8062b5c72f3f9ed54a613a1ae17958reed@google.com
150d53025364a8062b5c72f3f9ed54a613a1ae17958reed@google.com    SkMatrix44(const SkMatrix44& a, const SkMatrix44& b) {
151d53025364a8062b5c72f3f9ed54a613a1ae17958reed@google.com        this->setConcat(a, b);
152d53025364a8062b5c72f3f9ed54a613a1ae17958reed@google.com    }
1538260a895869beaa4cab9f8b915e457728f41e561reed@google.com
1548260a895869beaa4cab9f8b915e457728f41e561reed@google.com    SkMatrix44& operator=(const SkMatrix44& src) {
1553fda0eadac18dc3071e2bb2979512bd580b39eadreed@google.com        if (&src != this) {
1563fda0eadac18dc3071e2bb2979512bd580b39eadreed@google.com            memcpy(fMat, src.fMat, sizeof(fMat));
1573fda0eadac18dc3071e2bb2979512bd580b39eadreed@google.com            fTypeMask = src.fTypeMask;
1583fda0eadac18dc3071e2bb2979512bd580b39eadreed@google.com        }
1598260a895869beaa4cab9f8b915e457728f41e561reed@google.com        return *this;
1608260a895869beaa4cab9f8b915e457728f41e561reed@google.com    }
1618260a895869beaa4cab9f8b915e457728f41e561reed@google.com
162631940c8c44e92939fc95d305b87be64eb9b886ereed@google.com    bool operator==(const SkMatrix44& other) const;
1638260a895869beaa4cab9f8b915e457728f41e561reed@google.com    bool operator!=(const SkMatrix44& other) const {
164631940c8c44e92939fc95d305b87be64eb9b886ereed@google.com        return !(other == *this);
1658260a895869beaa4cab9f8b915e457728f41e561reed@google.com    }
1668260a895869beaa4cab9f8b915e457728f41e561reed@google.com
167722555bebbe9128783b8dbe0e897c09c9ccb88cecommit-bot@chromium.org    /* When converting from SkMatrix44 to SkMatrix, the third row and
168722555bebbe9128783b8dbe0e897c09c9ccb88cecommit-bot@chromium.org     * column is dropped.  When converting from SkMatrix to SkMatrix44
169722555bebbe9128783b8dbe0e897c09c9ccb88cecommit-bot@chromium.org     * the third row and column remain as identity:
170722555bebbe9128783b8dbe0e897c09c9ccb88cecommit-bot@chromium.org     * [ a b c ]      [ a b 0 c ]
171722555bebbe9128783b8dbe0e897c09c9ccb88cecommit-bot@chromium.org     * [ d e f ]  ->  [ d e 0 f ]
172722555bebbe9128783b8dbe0e897c09c9ccb88cecommit-bot@chromium.org     * [ g h i ]      [ 0 0 1 0 ]
173722555bebbe9128783b8dbe0e897c09c9ccb88cecommit-bot@chromium.org     *                [ g h 0 i ]
174722555bebbe9128783b8dbe0e897c09c9ccb88cecommit-bot@chromium.org     */
1758260a895869beaa4cab9f8b915e457728f41e561reed@google.com    SkMatrix44(const SkMatrix&);
1768260a895869beaa4cab9f8b915e457728f41e561reed@google.com    SkMatrix44& operator=(const SkMatrix& src);
1778260a895869beaa4cab9f8b915e457728f41e561reed@google.com    operator SkMatrix() const;
1788260a895869beaa4cab9f8b915e457728f41e561reed@google.com
1797d68335eb427547606497eb4edea81acce7891f9reed@google.com    /**
1807d68335eb427547606497eb4edea81acce7891f9reed@google.com     *  Return a reference to a const identity matrix
1817d68335eb427547606497eb4edea81acce7891f9reed@google.com     */
1827d68335eb427547606497eb4edea81acce7891f9reed@google.com    static const SkMatrix44& I();
1837d68335eb427547606497eb4edea81acce7891f9reed@google.com
1847d68335eb427547606497eb4edea81acce7891f9reed@google.com    enum TypeMask {
1857d68335eb427547606497eb4edea81acce7891f9reed@google.com        kIdentity_Mask      = 0,
1867d68335eb427547606497eb4edea81acce7891f9reed@google.com        kTranslate_Mask     = 0x01,  //!< set if the matrix has translation
1877d68335eb427547606497eb4edea81acce7891f9reed@google.com        kScale_Mask         = 0x02,  //!< set if the matrix has any scale != 1
1887d68335eb427547606497eb4edea81acce7891f9reed@google.com        kAffine_Mask        = 0x04,  //!< set if the matrix skews or rotates
1897d68335eb427547606497eb4edea81acce7891f9reed@google.com        kPerspective_Mask   = 0x08   //!< set if the matrix is in perspective
1907d68335eb427547606497eb4edea81acce7891f9reed@google.com    };
1910264fb4543b0d8cebe00f1ee32433784f4ceb074skia.committer@gmail.com
1927d68335eb427547606497eb4edea81acce7891f9reed@google.com    /**
1937d68335eb427547606497eb4edea81acce7891f9reed@google.com     *  Returns a bitfield describing the transformations the matrix may
1947d68335eb427547606497eb4edea81acce7891f9reed@google.com     *  perform. The bitfield is computed conservatively, so it may include
1957d68335eb427547606497eb4edea81acce7891f9reed@google.com     *  false positives. For example, when kPerspective_Mask is true, all
1967d68335eb427547606497eb4edea81acce7891f9reed@google.com     *  other bits may be set to true even in the case of a pure perspective
1977d68335eb427547606497eb4edea81acce7891f9reed@google.com     *  transform.
1987d68335eb427547606497eb4edea81acce7891f9reed@google.com     */
1997d68335eb427547606497eb4edea81acce7891f9reed@google.com    inline TypeMask getType() const {
2007d68335eb427547606497eb4edea81acce7891f9reed@google.com        if (fTypeMask & kUnknown_Mask) {
2017d68335eb427547606497eb4edea81acce7891f9reed@google.com            fTypeMask = this->computeTypeMask();
2027d68335eb427547606497eb4edea81acce7891f9reed@google.com        }
2037d68335eb427547606497eb4edea81acce7891f9reed@google.com        SkASSERT(!(fTypeMask & kUnknown_Mask));
2047d68335eb427547606497eb4edea81acce7891f9reed@google.com        return (TypeMask)fTypeMask;
2057d68335eb427547606497eb4edea81acce7891f9reed@google.com    }
2067d68335eb427547606497eb4edea81acce7891f9reed@google.com
207f8b1ebc35b6872c2805a22481b7c23b85486fb46mike@reedtribe.org    /**
208f8b1ebc35b6872c2805a22481b7c23b85486fb46mike@reedtribe.org     *  Return true if the matrix is identity.
209f8b1ebc35b6872c2805a22481b7c23b85486fb46mike@reedtribe.org     */
2107d68335eb427547606497eb4edea81acce7891f9reed@google.com    inline bool isIdentity() const {
211f8b1ebc35b6872c2805a22481b7c23b85486fb46mike@reedtribe.org        return kIdentity_Mask == this->getType();
212f8b1ebc35b6872c2805a22481b7c23b85486fb46mike@reedtribe.org    }
213f8b1ebc35b6872c2805a22481b7c23b85486fb46mike@reedtribe.org
214f8b1ebc35b6872c2805a22481b7c23b85486fb46mike@reedtribe.org    /**
215f8b1ebc35b6872c2805a22481b7c23b85486fb46mike@reedtribe.org     *  Return true if the matrix contains translate or is identity.
216f8b1ebc35b6872c2805a22481b7c23b85486fb46mike@reedtribe.org     */
217f8b1ebc35b6872c2805a22481b7c23b85486fb46mike@reedtribe.org    inline bool isTranslate() const {
218f8b1ebc35b6872c2805a22481b7c23b85486fb46mike@reedtribe.org        return !(this->getType() & ~kTranslate_Mask);
219f8b1ebc35b6872c2805a22481b7c23b85486fb46mike@reedtribe.org    }
220f8b1ebc35b6872c2805a22481b7c23b85486fb46mike@reedtribe.org
221f8b1ebc35b6872c2805a22481b7c23b85486fb46mike@reedtribe.org    /**
222f8b1ebc35b6872c2805a22481b7c23b85486fb46mike@reedtribe.org     *  Return true if the matrix only contains scale or translate or is identity.
223f8b1ebc35b6872c2805a22481b7c23b85486fb46mike@reedtribe.org     */
224f8b1ebc35b6872c2805a22481b7c23b85486fb46mike@reedtribe.org    inline bool isScaleTranslate() const {
225f8b1ebc35b6872c2805a22481b7c23b85486fb46mike@reedtribe.org        return !(this->getType() & ~(kScale_Mask | kTranslate_Mask));
2267d68335eb427547606497eb4edea81acce7891f9reed@google.com    }
2270264fb4543b0d8cebe00f1ee32433784f4ceb074skia.committer@gmail.com
22820b7960798320e6804ffee78fd92e6c001eba30btfarina    /**
22920b7960798320e6804ffee78fd92e6c001eba30btfarina     *  Returns true if the matrix only contains scale or is identity.
23020b7960798320e6804ffee78fd92e6c001eba30btfarina     */
23120b7960798320e6804ffee78fd92e6c001eba30btfarina    inline bool isScale() const {
23220b7960798320e6804ffee78fd92e6c001eba30btfarina            return !(this->getType() & ~kScale_Mask);
23320b7960798320e6804ffee78fd92e6c001eba30btfarina    }
23420b7960798320e6804ffee78fd92e6c001eba30btfarina
235a32f1758b7ebd889eecfdc67c935e7edcedc5be3tomhudson    inline bool hasPerspective() const {
236a32f1758b7ebd889eecfdc67c935e7edcedc5be3tomhudson        return SkToBool(this->getType() & kPerspective_Mask);
237a32f1758b7ebd889eecfdc67c935e7edcedc5be3tomhudson    }
238a32f1758b7ebd889eecfdc67c935e7edcedc5be3tomhudson
2397d68335eb427547606497eb4edea81acce7891f9reed@google.com    void setIdentity();
2407d68335eb427547606497eb4edea81acce7891f9reed@google.com    inline void reset() { this->setIdentity();}
2417d68335eb427547606497eb4edea81acce7891f9reed@google.com
2427d68335eb427547606497eb4edea81acce7891f9reed@google.com    /**
2437d68335eb427547606497eb4edea81acce7891f9reed@google.com     *  get a value from the matrix. The row,col parameters work as follows:
2447d68335eb427547606497eb4edea81acce7891f9reed@google.com     *  (0, 0)  scale-x
2457d68335eb427547606497eb4edea81acce7891f9reed@google.com     *  (0, 3)  translate-x
2467d68335eb427547606497eb4edea81acce7891f9reed@google.com     *  (3, 0)  perspective-x
2477d68335eb427547606497eb4edea81acce7891f9reed@google.com     */
2487d68335eb427547606497eb4edea81acce7891f9reed@google.com    inline SkMScalar get(int row, int col) const {
249631940c8c44e92939fc95d305b87be64eb9b886ereed@google.com        SkASSERT((unsigned)row <= 3);
250631940c8c44e92939fc95d305b87be64eb9b886ereed@google.com        SkASSERT((unsigned)col <= 3);
251631940c8c44e92939fc95d305b87be64eb9b886ereed@google.com        return fMat[col][row];
252631940c8c44e92939fc95d305b87be64eb9b886ereed@google.com    }
2538260a895869beaa4cab9f8b915e457728f41e561reed@google.com
2547d68335eb427547606497eb4edea81acce7891f9reed@google.com    /**
2557d68335eb427547606497eb4edea81acce7891f9reed@google.com     *  set a value in the matrix. The row,col parameters work as follows:
2567d68335eb427547606497eb4edea81acce7891f9reed@google.com     *  (0, 0)  scale-x
2577d68335eb427547606497eb4edea81acce7891f9reed@google.com     *  (0, 3)  translate-x
2587d68335eb427547606497eb4edea81acce7891f9reed@google.com     *  (3, 0)  perspective-x
2597d68335eb427547606497eb4edea81acce7891f9reed@google.com     */
2607d68335eb427547606497eb4edea81acce7891f9reed@google.com    inline void set(int row, int col, SkMScalar value) {
261631940c8c44e92939fc95d305b87be64eb9b886ereed@google.com        SkASSERT((unsigned)row <= 3);
262631940c8c44e92939fc95d305b87be64eb9b886ereed@google.com        SkASSERT((unsigned)col <= 3);
263631940c8c44e92939fc95d305b87be64eb9b886ereed@google.com        fMat[col][row] = value;
2647d68335eb427547606497eb4edea81acce7891f9reed@google.com        this->dirtyTypeMask();
265631940c8c44e92939fc95d305b87be64eb9b886ereed@google.com    }
266ab38f7acb336c4330af015312e854e990babd3f5skia.committer@gmail.com
2677d68335eb427547606497eb4edea81acce7891f9reed@google.com    inline double getDouble(int row, int col) const {
2689b21c25e742d6a8b69bee8b049e79877f93b5936vollick@chromium.org        return SkMScalarToDouble(this->get(row, col));
2699b21c25e742d6a8b69bee8b049e79877f93b5936vollick@chromium.org    }
2707d68335eb427547606497eb4edea81acce7891f9reed@google.com    inline void setDouble(int row, int col, double value) {
2719b21c25e742d6a8b69bee8b049e79877f93b5936vollick@chromium.org        this->set(row, col, SkDoubleToMScalar(value));
2729b21c25e742d6a8b69bee8b049e79877f93b5936vollick@chromium.org    }
273e2419cc5edbe1a6a7dae81a90ca44673a1fa030fcommit-bot@chromium.org    inline float getFloat(int row, int col) const {
274e2419cc5edbe1a6a7dae81a90ca44673a1fa030fcommit-bot@chromium.org        return SkMScalarToFloat(this->get(row, col));
275e2419cc5edbe1a6a7dae81a90ca44673a1fa030fcommit-bot@chromium.org    }
276e2419cc5edbe1a6a7dae81a90ca44673a1fa030fcommit-bot@chromium.org    inline void setFloat(int row, int col, float value) {
277e2419cc5edbe1a6a7dae81a90ca44673a1fa030fcommit-bot@chromium.org        this->set(row, col, SkFloatToMScalar(value));
278e2419cc5edbe1a6a7dae81a90ca44673a1fa030fcommit-bot@chromium.org    }
2799b21c25e742d6a8b69bee8b049e79877f93b5936vollick@chromium.org
280f11cf9ff885c81e29f55283174ca34ce2fc5fd23vollick@chromium.org    /** These methods allow one to efficiently read matrix entries into an
281f11cf9ff885c81e29f55283174ca34ce2fc5fd23vollick@chromium.org     *  array. The given array must have room for exactly 16 entries. Whenever
282f11cf9ff885c81e29f55283174ca34ce2fc5fd23vollick@chromium.org     *  possible, they will try to use memcpy rather than an entry-by-entry
283f11cf9ff885c81e29f55283174ca34ce2fc5fd23vollick@chromium.org     *  copy.
284f11cf9ff885c81e29f55283174ca34ce2fc5fd23vollick@chromium.org     */
285da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com    void asColMajorf(float[]) const;
286da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com    void asColMajord(double[]) const;
287da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com    void asRowMajorf(float[]) const;
288da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com    void asRowMajord(double[]) const;
289da9fac0aa13d1445f8b58a75d9390638845c814dreed@google.com
290f11cf9ff885c81e29f55283174ca34ce2fc5fd23vollick@chromium.org    /** These methods allow one to efficiently set all matrix entries from an
291f11cf9ff885c81e29f55283174ca34ce2fc5fd23vollick@chromium.org     *  array. The given array must have room for exactly 16 entries. Whenever
292f11cf9ff885c81e29f55283174ca34ce2fc5fd23vollick@chromium.org     *  possible, they will try to use memcpy rather than an entry-by-entry
293f11cf9ff885c81e29f55283174ca34ce2fc5fd23vollick@chromium.org     *  copy.
294f11cf9ff885c81e29f55283174ca34ce2fc5fd23vollick@chromium.org     */
295f11cf9ff885c81e29f55283174ca34ce2fc5fd23vollick@chromium.org    void setColMajorf(const float[]);
296f11cf9ff885c81e29f55283174ca34ce2fc5fd23vollick@chromium.org    void setColMajord(const double[]);
297f11cf9ff885c81e29f55283174ca34ce2fc5fd23vollick@chromium.org    void setRowMajorf(const float[]);
298f11cf9ff885c81e29f55283174ca34ce2fc5fd23vollick@chromium.org    void setRowMajord(const double[]);
299f11cf9ff885c81e29f55283174ca34ce2fc5fd23vollick@chromium.org
3007d68335eb427547606497eb4edea81acce7891f9reed@google.com#ifdef SK_MSCALAR_IS_FLOAT
3017d68335eb427547606497eb4edea81acce7891f9reed@google.com    void setColMajor(const SkMScalar data[]) { this->setColMajorf(data); }
3027d68335eb427547606497eb4edea81acce7891f9reed@google.com    void setRowMajor(const SkMScalar data[]) { this->setRowMajorf(data); }
3037d68335eb427547606497eb4edea81acce7891f9reed@google.com#else
3047d68335eb427547606497eb4edea81acce7891f9reed@google.com    void setColMajor(const SkMScalar data[]) { this->setColMajord(data); }
3057d68335eb427547606497eb4edea81acce7891f9reed@google.com    void setRowMajor(const SkMScalar data[]) { this->setRowMajord(data); }
3067d68335eb427547606497eb4edea81acce7891f9reed@google.com#endif
3078260a895869beaa4cab9f8b915e457728f41e561reed@google.com
308722555bebbe9128783b8dbe0e897c09c9ccb88cecommit-bot@chromium.org    /* This sets the top-left of the matrix and clears the translation and
309722555bebbe9128783b8dbe0e897c09c9ccb88cecommit-bot@chromium.org     * perspective components (with [3][3] set to 1). */
3108260a895869beaa4cab9f8b915e457728f41e561reed@google.com    void set3x3(SkMScalar m00, SkMScalar m01, SkMScalar m02,
3118260a895869beaa4cab9f8b915e457728f41e561reed@google.com                SkMScalar m10, SkMScalar m11, SkMScalar m12,
3128260a895869beaa4cab9f8b915e457728f41e561reed@google.com                SkMScalar m20, SkMScalar m21, SkMScalar m22);
3138260a895869beaa4cab9f8b915e457728f41e561reed@google.com
3148260a895869beaa4cab9f8b915e457728f41e561reed@google.com    void setTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz);
3158260a895869beaa4cab9f8b915e457728f41e561reed@google.com    void preTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz);
3168260a895869beaa4cab9f8b915e457728f41e561reed@google.com    void postTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz);
3178260a895869beaa4cab9f8b915e457728f41e561reed@google.com
3188260a895869beaa4cab9f8b915e457728f41e561reed@google.com    void setScale(SkMScalar sx, SkMScalar sy, SkMScalar sz);
3198260a895869beaa4cab9f8b915e457728f41e561reed@google.com    void preScale(SkMScalar sx, SkMScalar sy, SkMScalar sz);
3208260a895869beaa4cab9f8b915e457728f41e561reed@google.com    void postScale(SkMScalar sx, SkMScalar sy, SkMScalar sz);
3218260a895869beaa4cab9f8b915e457728f41e561reed@google.com
3227d68335eb427547606497eb4edea81acce7891f9reed@google.com    inline void setScale(SkMScalar scale) {
3238260a895869beaa4cab9f8b915e457728f41e561reed@google.com        this->setScale(scale, scale, scale);
3248260a895869beaa4cab9f8b915e457728f41e561reed@google.com    }
3257d68335eb427547606497eb4edea81acce7891f9reed@google.com    inline void preScale(SkMScalar scale) {
3268260a895869beaa4cab9f8b915e457728f41e561reed@google.com        this->preScale(scale, scale, scale);
3278260a895869beaa4cab9f8b915e457728f41e561reed@google.com    }
3287d68335eb427547606497eb4edea81acce7891f9reed@google.com    inline void postScale(SkMScalar scale) {
3298260a895869beaa4cab9f8b915e457728f41e561reed@google.com        this->postScale(scale, scale, scale);
3308260a895869beaa4cab9f8b915e457728f41e561reed@google.com    }
3318260a895869beaa4cab9f8b915e457728f41e561reed@google.com
3328260a895869beaa4cab9f8b915e457728f41e561reed@google.com    void setRotateDegreesAbout(SkMScalar x, SkMScalar y, SkMScalar z,
3338260a895869beaa4cab9f8b915e457728f41e561reed@google.com                               SkMScalar degrees) {
3348260a895869beaa4cab9f8b915e457728f41e561reed@google.com        this->setRotateAbout(x, y, z, degrees * SK_MScalarPI / 180);
3358260a895869beaa4cab9f8b915e457728f41e561reed@google.com    }
3368260a895869beaa4cab9f8b915e457728f41e561reed@google.com
3378260a895869beaa4cab9f8b915e457728f41e561reed@google.com    /** Rotate about the vector [x,y,z]. If that vector is not unit-length,
3388260a895869beaa4cab9f8b915e457728f41e561reed@google.com        it will be automatically resized.
3398260a895869beaa4cab9f8b915e457728f41e561reed@google.com     */
3408260a895869beaa4cab9f8b915e457728f41e561reed@google.com    void setRotateAbout(SkMScalar x, SkMScalar y, SkMScalar z,
3418260a895869beaa4cab9f8b915e457728f41e561reed@google.com                        SkMScalar radians);
3428260a895869beaa4cab9f8b915e457728f41e561reed@google.com    /** Rotate about the vector [x,y,z]. Does not check the length of the
3438260a895869beaa4cab9f8b915e457728f41e561reed@google.com        vector, assuming it is unit-length.
3448260a895869beaa4cab9f8b915e457728f41e561reed@google.com     */
3458260a895869beaa4cab9f8b915e457728f41e561reed@google.com    void setRotateAboutUnit(SkMScalar x, SkMScalar y, SkMScalar z,
3468260a895869beaa4cab9f8b915e457728f41e561reed@google.com                            SkMScalar radians);
3478260a895869beaa4cab9f8b915e457728f41e561reed@google.com
3488260a895869beaa4cab9f8b915e457728f41e561reed@google.com    void setConcat(const SkMatrix44& a, const SkMatrix44& b);
3497d68335eb427547606497eb4edea81acce7891f9reed@google.com    inline void preConcat(const SkMatrix44& m) {
3508260a895869beaa4cab9f8b915e457728f41e561reed@google.com        this->setConcat(*this, m);
3518260a895869beaa4cab9f8b915e457728f41e561reed@google.com    }
3527d68335eb427547606497eb4edea81acce7891f9reed@google.com    inline void postConcat(const SkMatrix44& m) {
3538260a895869beaa4cab9f8b915e457728f41e561reed@google.com        this->setConcat(m, *this);
3548260a895869beaa4cab9f8b915e457728f41e561reed@google.com    }
3558260a895869beaa4cab9f8b915e457728f41e561reed@google.com
3568260a895869beaa4cab9f8b915e457728f41e561reed@google.com    friend SkMatrix44 operator*(const SkMatrix44& a, const SkMatrix44& b) {
3578260a895869beaa4cab9f8b915e457728f41e561reed@google.com        return SkMatrix44(a, b);
3588260a895869beaa4cab9f8b915e457728f41e561reed@google.com    }
3598260a895869beaa4cab9f8b915e457728f41e561reed@google.com
3608260a895869beaa4cab9f8b915e457728f41e561reed@google.com    /** If this is invertible, return that in inverse and return true. If it is
3618260a895869beaa4cab9f8b915e457728f41e561reed@google.com        not invertible, return false and ignore the inverse parameter.
3628260a895869beaa4cab9f8b915e457728f41e561reed@google.com     */
3638260a895869beaa4cab9f8b915e457728f41e561reed@google.com    bool invert(SkMatrix44* inverse) const;
3648260a895869beaa4cab9f8b915e457728f41e561reed@google.com
3659b21c25e742d6a8b69bee8b049e79877f93b5936vollick@chromium.org    /** Transpose this matrix in place. */
3669b21c25e742d6a8b69bee8b049e79877f93b5936vollick@chromium.org    void transpose();
3679b21c25e742d6a8b69bee8b049e79877f93b5936vollick@chromium.org
3688260a895869beaa4cab9f8b915e457728f41e561reed@google.com    /** Apply the matrix to the src vector, returning the new vector in dst.
3698260a895869beaa4cab9f8b915e457728f41e561reed@google.com        It is legal for src and dst to point to the same memory.
3708260a895869beaa4cab9f8b915e457728f41e561reed@google.com     */
3711ea95be560b38a71e3f24749c4e5e3d3564e4c6creed@google.com    void mapScalars(const SkScalar src[4], SkScalar dst[4]) const;
3727d68335eb427547606497eb4edea81acce7891f9reed@google.com    inline void mapScalars(SkScalar vec[4]) const {
3731ea95be560b38a71e3f24749c4e5e3d3564e4c6creed@google.com        this->mapScalars(vec, vec);
3741ea95be560b38a71e3f24749c4e5e3d3564e4c6creed@google.com    }
3751ea95be560b38a71e3f24749c4e5e3d3564e4c6creed@google.com
3764469938e92d779dff05e745559e67907bbf21e78reed@google.com    SK_ATTR_DEPRECATED("use mapScalars")
3771ea95be560b38a71e3f24749c4e5e3d3564e4c6creed@google.com    void map(const SkScalar src[4], SkScalar dst[4]) const {
3781ea95be560b38a71e3f24749c4e5e3d3564e4c6creed@google.com        this->mapScalars(src, dst);
3791ea95be560b38a71e3f24749c4e5e3d3564e4c6creed@google.com    }
3804469938e92d779dff05e745559e67907bbf21e78reed@google.com
3814469938e92d779dff05e745559e67907bbf21e78reed@google.com    SK_ATTR_DEPRECATED("use mapScalars")
3828260a895869beaa4cab9f8b915e457728f41e561reed@google.com    void map(SkScalar vec[4]) const {
3831ea95be560b38a71e3f24749c4e5e3d3564e4c6creed@google.com        this->mapScalars(vec, vec);
3841ea95be560b38a71e3f24749c4e5e3d3564e4c6creed@google.com    }
3851ea95be560b38a71e3f24749c4e5e3d3564e4c6creed@google.com
3861ea95be560b38a71e3f24749c4e5e3d3564e4c6creed@google.com#ifdef SK_MSCALAR_IS_DOUBLE
387dd31131021e2b5ef16b4f3cdec3cf328adcfd6ccreed@google.com    void mapMScalars(const SkMScalar src[4], SkMScalar dst[4]) const;
3885596a69e9f7884e3042bceba071c468dee52aa7fvollick@chromium.org#elif defined SK_MSCALAR_IS_FLOAT
3897d68335eb427547606497eb4edea81acce7891f9reed@google.com    inline void mapMScalars(const SkMScalar src[4], SkMScalar dst[4]) const {
3901ea95be560b38a71e3f24749c4e5e3d3564e4c6creed@google.com        this->mapScalars(src, dst);
3911ea95be560b38a71e3f24749c4e5e3d3564e4c6creed@google.com    }
3921ea95be560b38a71e3f24749c4e5e3d3564e4c6creed@google.com#endif
3937d68335eb427547606497eb4edea81acce7891f9reed@google.com    inline void mapMScalars(SkMScalar vec[4]) const {
3941ea95be560b38a71e3f24749c4e5e3d3564e4c6creed@google.com        this->mapMScalars(vec, vec);
3958260a895869beaa4cab9f8b915e457728f41e561reed@google.com    }
3968260a895869beaa4cab9f8b915e457728f41e561reed@google.com
3978260a895869beaa4cab9f8b915e457728f41e561reed@google.com    friend SkVector4 operator*(const SkMatrix44& m, const SkVector4& src) {
3988260a895869beaa4cab9f8b915e457728f41e561reed@google.com        SkVector4 dst;
3994469938e92d779dff05e745559e67907bbf21e78reed@google.com        m.mapScalars(src.fData, dst.fData);
4008260a895869beaa4cab9f8b915e457728f41e561reed@google.com        return dst;
4018260a895869beaa4cab9f8b915e457728f41e561reed@google.com    }
4028260a895869beaa4cab9f8b915e457728f41e561reed@google.com
40399b5c7f94ba5ef0c9cb464e34834cd5adea37a0ereed@google.com    /**
40499b5c7f94ba5ef0c9cb464e34834cd5adea37a0ereed@google.com     *  map an array of [x, y, 0, 1] through the matrix, returning an array
40599b5c7f94ba5ef0c9cb464e34834cd5adea37a0ereed@google.com     *  of [x', y', z', w'].
40699b5c7f94ba5ef0c9cb464e34834cd5adea37a0ereed@google.com     *
40799b5c7f94ba5ef0c9cb464e34834cd5adea37a0ereed@google.com     *  @param src2     array of [x, y] pairs, with implied z=0 and w=1
40899b5c7f94ba5ef0c9cb464e34834cd5adea37a0ereed@google.com     *  @param count    number of [x, y] pairs in src2
40999b5c7f94ba5ef0c9cb464e34834cd5adea37a0ereed@google.com     *  @param dst4     array of [x', y', z', w'] quads as the output.
41099b5c7f94ba5ef0c9cb464e34834cd5adea37a0ereed@google.com     */
41199b5c7f94ba5ef0c9cb464e34834cd5adea37a0ereed@google.com    void map2(const float src2[], int count, float dst4[]) const;
41299b5c7f94ba5ef0c9cb464e34834cd5adea37a0ereed@google.com    void map2(const double src2[], int count, double dst4[]) const;
41399b5c7f94ba5ef0c9cb464e34834cd5adea37a0ereed@google.com
414faccb8eb53f1bc745d3dd530d8df8b40e0dedc23tomhudson    /** Returns true if transformating an axis-aligned square in 2d by this matrix
415faccb8eb53f1bc745d3dd530d8df8b40e0dedc23tomhudson        will produce another 2d axis-aligned square; typically means the matrix
416faccb8eb53f1bc745d3dd530d8df8b40e0dedc23tomhudson        is a scale with perhaps a 90-degree rotation. A 3d rotation through 90
417faccb8eb53f1bc745d3dd530d8df8b40e0dedc23tomhudson        degrees into a perpendicular plane collapses a square to a line, but
418faccb8eb53f1bc745d3dd530d8df8b40e0dedc23tomhudson        is still considered to be axis-aligned.
419faccb8eb53f1bc745d3dd530d8df8b40e0dedc23tomhudson
420faccb8eb53f1bc745d3dd530d8df8b40e0dedc23tomhudson        By default, tolerates very slight error due to float imprecisions;
421faccb8eb53f1bc745d3dd530d8df8b40e0dedc23tomhudson        a 90-degree rotation can still end up with 10^-17 of
422faccb8eb53f1bc745d3dd530d8df8b40e0dedc23tomhudson        "non-axis-aligned" result.
423faccb8eb53f1bc745d3dd530d8df8b40e0dedc23tomhudson     */
424faccb8eb53f1bc745d3dd530d8df8b40e0dedc23tomhudson    bool preserves2dAxisAlignment(SkMScalar epsilon = SK_ScalarNearlyZero) const;
425faccb8eb53f1bc745d3dd530d8df8b40e0dedc23tomhudson
4268260a895869beaa4cab9f8b915e457728f41e561reed@google.com    void dump() const;
4278260a895869beaa4cab9f8b915e457728f41e561reed@google.com
4283959a76ab086a4adbdb9d48977fa276ce0213cb1vollick@chromium.org    double determinant() const;
4293959a76ab086a4adbdb9d48977fa276ce0213cb1vollick@chromium.org
4308260a895869beaa4cab9f8b915e457728f41e561reed@google.comprivate:
431d53025364a8062b5c72f3f9ed54a613a1ae17958reed@google.com    SkMScalar           fMat[4][4];
432d53025364a8062b5c72f3f9ed54a613a1ae17958reed@google.com    mutable unsigned    fTypeMask;
4330264fb4543b0d8cebe00f1ee32433784f4ceb074skia.committer@gmail.com
4347d68335eb427547606497eb4edea81acce7891f9reed@google.com    enum {
4357d68335eb427547606497eb4edea81acce7891f9reed@google.com        kUnknown_Mask = 0x80,
4367d68335eb427547606497eb4edea81acce7891f9reed@google.com
4377d68335eb427547606497eb4edea81acce7891f9reed@google.com        kAllPublic_Masks = 0xF
4387d68335eb427547606497eb4edea81acce7891f9reed@google.com    };
4397d68335eb427547606497eb4edea81acce7891f9reed@google.com
4407d68335eb427547606497eb4edea81acce7891f9reed@google.com    SkMScalar transX() const { return fMat[3][0]; }
4417d68335eb427547606497eb4edea81acce7891f9reed@google.com    SkMScalar transY() const { return fMat[3][1]; }
4427d68335eb427547606497eb4edea81acce7891f9reed@google.com    SkMScalar transZ() const { return fMat[3][2]; }
4437d68335eb427547606497eb4edea81acce7891f9reed@google.com
4447d68335eb427547606497eb4edea81acce7891f9reed@google.com    SkMScalar scaleX() const { return fMat[0][0]; }
4457d68335eb427547606497eb4edea81acce7891f9reed@google.com    SkMScalar scaleY() const { return fMat[1][1]; }
4467d68335eb427547606497eb4edea81acce7891f9reed@google.com    SkMScalar scaleZ() const { return fMat[2][2]; }
4470264fb4543b0d8cebe00f1ee32433784f4ceb074skia.committer@gmail.com
4487d68335eb427547606497eb4edea81acce7891f9reed@google.com    SkMScalar perspX() const { return fMat[0][3]; }
4497d68335eb427547606497eb4edea81acce7891f9reed@google.com    SkMScalar perspY() const { return fMat[1][3]; }
4507d68335eb427547606497eb4edea81acce7891f9reed@google.com    SkMScalar perspZ() const { return fMat[2][3]; }
451deb4c169690c777acb27ee8ce67d70d3f6eb2a2cjamesr@chromium.org
4527d68335eb427547606497eb4edea81acce7891f9reed@google.com    int computeTypeMask() const;
4537d68335eb427547606497eb4edea81acce7891f9reed@google.com
4547d68335eb427547606497eb4edea81acce7891f9reed@google.com    inline void dirtyTypeMask() {
4557d68335eb427547606497eb4edea81acce7891f9reed@google.com        fTypeMask = kUnknown_Mask;
4567d68335eb427547606497eb4edea81acce7891f9reed@google.com    }
4577d68335eb427547606497eb4edea81acce7891f9reed@google.com
4587d68335eb427547606497eb4edea81acce7891f9reed@google.com    inline void setTypeMask(int mask) {
4597d68335eb427547606497eb4edea81acce7891f9reed@google.com        SkASSERT(0 == (~(kAllPublic_Masks | kUnknown_Mask) & mask));
4607d68335eb427547606497eb4edea81acce7891f9reed@google.com        fTypeMask = mask;
4617d68335eb427547606497eb4edea81acce7891f9reed@google.com    }
4627d68335eb427547606497eb4edea81acce7891f9reed@google.com
4637d68335eb427547606497eb4edea81acce7891f9reed@google.com    /**
4647d68335eb427547606497eb4edea81acce7891f9reed@google.com     *  Does not take the time to 'compute' the typemask. Only returns true if
4657d68335eb427547606497eb4edea81acce7891f9reed@google.com     *  we already know that this matrix is identity.
4667d68335eb427547606497eb4edea81acce7891f9reed@google.com     */
4677d68335eb427547606497eb4edea81acce7891f9reed@google.com    inline bool isTriviallyIdentity() const {
4687d68335eb427547606497eb4edea81acce7891f9reed@google.com        return 0 == fTypeMask;
4697d68335eb427547606497eb4edea81acce7891f9reed@google.com    }
4707cfb9c7b6186bf1e42b7d13466eab94470587e7etomhudson@google.com};
4718260a895869beaa4cab9f8b915e457728f41e561reed@google.com
4728260a895869beaa4cab9f8b915e457728f41e561reed@google.com#endif
473