150d3b57c8aaa0f026b981101c45ea30361382940reed/*
250d3b57c8aaa0f026b981101c45ea30361382940reed * Copyright 2011 Google Inc.
350d3b57c8aaa0f026b981101c45ea30361382940reed *
450d3b57c8aaa0f026b981101c45ea30361382940reed * Use of this source code is governed by a BSD-style license that can be
550d3b57c8aaa0f026b981101c45ea30361382940reed * found in the LICENSE file.
650d3b57c8aaa0f026b981101c45ea30361382940reed */
750d3b57c8aaa0f026b981101c45ea30361382940reed
850d3b57c8aaa0f026b981101c45ea30361382940reed#ifndef SkMatrix44_DEFINED
950d3b57c8aaa0f026b981101c45ea30361382940reed#define SkMatrix44_DEFINED
1050d3b57c8aaa0f026b981101c45ea30361382940reed
1150d3b57c8aaa0f026b981101c45ea30361382940reed#include "SkMatrix.h"
1250d3b57c8aaa0f026b981101c45ea30361382940reed#include "SkScalar.h"
1350d3b57c8aaa0f026b981101c45ea30361382940reed
1450d3b57c8aaa0f026b981101c45ea30361382940reed#ifdef SK_MSCALAR_IS_DOUBLE
1550d3b57c8aaa0f026b981101c45ea30361382940reed#ifdef SK_MSCALAR_IS_FLOAT
1650d3b57c8aaa0f026b981101c45ea30361382940reed    #error "can't define MSCALAR both as DOUBLE and FLOAT"
1750d3b57c8aaa0f026b981101c45ea30361382940reed#endif
1850d3b57c8aaa0f026b981101c45ea30361382940reed    typedef double SkMScalar;
1950d3b57c8aaa0f026b981101c45ea30361382940reed
2050d3b57c8aaa0f026b981101c45ea30361382940reed    static inline double SkFloatToMScalar(float x) {
2150d3b57c8aaa0f026b981101c45ea30361382940reed        return static_cast<double>(x);
2250d3b57c8aaa0f026b981101c45ea30361382940reed    }
2350d3b57c8aaa0f026b981101c45ea30361382940reed    static inline float SkMScalarToFloat(double x) {
2450d3b57c8aaa0f026b981101c45ea30361382940reed        return static_cast<float>(x);
2550d3b57c8aaa0f026b981101c45ea30361382940reed    }
2650d3b57c8aaa0f026b981101c45ea30361382940reed    static inline double SkDoubleToMScalar(double x) {
2750d3b57c8aaa0f026b981101c45ea30361382940reed        return x;
2850d3b57c8aaa0f026b981101c45ea30361382940reed    }
2950d3b57c8aaa0f026b981101c45ea30361382940reed    static inline double SkMScalarToDouble(double x) {
3050d3b57c8aaa0f026b981101c45ea30361382940reed        return x;
3150d3b57c8aaa0f026b981101c45ea30361382940reed    }
3250d3b57c8aaa0f026b981101c45ea30361382940reed    static inline double SkMScalarAbs(double x) {
3350d3b57c8aaa0f026b981101c45ea30361382940reed        return fabs(x);
3450d3b57c8aaa0f026b981101c45ea30361382940reed    }
3550d3b57c8aaa0f026b981101c45ea30361382940reed    static const SkMScalar SK_MScalarPI = 3.141592653589793;
3650d3b57c8aaa0f026b981101c45ea30361382940reed
3750d3b57c8aaa0f026b981101c45ea30361382940reed    #define SkMScalarFloor(x)           sk_double_floor(x)
3850d3b57c8aaa0f026b981101c45ea30361382940reed    #define SkMScalarCeil(x)            sk_double_ceil(x)
3950d3b57c8aaa0f026b981101c45ea30361382940reed    #define SkMScalarRound(x)           sk_double_round(x)
4050d3b57c8aaa0f026b981101c45ea30361382940reed
4150d3b57c8aaa0f026b981101c45ea30361382940reed    #define SkMScalarFloorToInt(x)      sk_double_floor2int(x)
4250d3b57c8aaa0f026b981101c45ea30361382940reed    #define SkMScalarCeilToInt(x)       sk_double_ceil2int(x)
4350d3b57c8aaa0f026b981101c45ea30361382940reed    #define SkMScalarRoundToInt(x)      sk_double_round2int(x)
4450d3b57c8aaa0f026b981101c45ea30361382940reed
4550d3b57c8aaa0f026b981101c45ea30361382940reed
4650d3b57c8aaa0f026b981101c45ea30361382940reed#elif defined SK_MSCALAR_IS_FLOAT
4750d3b57c8aaa0f026b981101c45ea30361382940reed#ifdef SK_MSCALAR_IS_DOUBLE
4850d3b57c8aaa0f026b981101c45ea30361382940reed    #error "can't define MSCALAR both as DOUBLE and FLOAT"
4950d3b57c8aaa0f026b981101c45ea30361382940reed#endif
5050d3b57c8aaa0f026b981101c45ea30361382940reed    typedef float SkMScalar;
5150d3b57c8aaa0f026b981101c45ea30361382940reed
5250d3b57c8aaa0f026b981101c45ea30361382940reed    static inline float SkFloatToMScalar(float x) {
5350d3b57c8aaa0f026b981101c45ea30361382940reed        return x;
5450d3b57c8aaa0f026b981101c45ea30361382940reed    }
5550d3b57c8aaa0f026b981101c45ea30361382940reed    static inline float SkMScalarToFloat(float x) {
5650d3b57c8aaa0f026b981101c45ea30361382940reed        return x;
5750d3b57c8aaa0f026b981101c45ea30361382940reed    }
5850d3b57c8aaa0f026b981101c45ea30361382940reed    static inline float SkDoubleToMScalar(double x) {
5950d3b57c8aaa0f026b981101c45ea30361382940reed        return static_cast<float>(x);
6050d3b57c8aaa0f026b981101c45ea30361382940reed    }
6150d3b57c8aaa0f026b981101c45ea30361382940reed    static inline double SkMScalarToDouble(float x) {
6250d3b57c8aaa0f026b981101c45ea30361382940reed        return static_cast<double>(x);
6350d3b57c8aaa0f026b981101c45ea30361382940reed    }
6450d3b57c8aaa0f026b981101c45ea30361382940reed    static inline float SkMScalarAbs(float x) {
6550d3b57c8aaa0f026b981101c45ea30361382940reed        return sk_float_abs(x);
6650d3b57c8aaa0f026b981101c45ea30361382940reed    }
6750d3b57c8aaa0f026b981101c45ea30361382940reed    static const SkMScalar SK_MScalarPI = 3.14159265f;
6850d3b57c8aaa0f026b981101c45ea30361382940reed
6950d3b57c8aaa0f026b981101c45ea30361382940reed    #define SkMScalarFloor(x)           sk_float_floor(x)
7050d3b57c8aaa0f026b981101c45ea30361382940reed    #define SkMScalarCeil(x)            sk_float_ceil(x)
7150d3b57c8aaa0f026b981101c45ea30361382940reed    #define SkMScalarRound(x)           sk_float_round(x)
7250d3b57c8aaa0f026b981101c45ea30361382940reed
7350d3b57c8aaa0f026b981101c45ea30361382940reed    #define SkMScalarFloorToInt(x)      sk_float_floor2int(x)
7450d3b57c8aaa0f026b981101c45ea30361382940reed    #define SkMScalarCeilToInt(x)       sk_float_ceil2int(x)
7550d3b57c8aaa0f026b981101c45ea30361382940reed    #define SkMScalarRoundToInt(x)      sk_float_round2int(x)
7650d3b57c8aaa0f026b981101c45ea30361382940reed
7750d3b57c8aaa0f026b981101c45ea30361382940reed#endif
7850d3b57c8aaa0f026b981101c45ea30361382940reed
7950d3b57c8aaa0f026b981101c45ea30361382940reed#define SkIntToMScalar(n)       static_cast<SkMScalar>(n)
8050d3b57c8aaa0f026b981101c45ea30361382940reed
8150d3b57c8aaa0f026b981101c45ea30361382940reed#define SkMScalarToScalar(x)    SkMScalarToFloat(x)
8250d3b57c8aaa0f026b981101c45ea30361382940reed#define SkScalarToMScalar(x)    SkFloatToMScalar(x)
8350d3b57c8aaa0f026b981101c45ea30361382940reed
8450d3b57c8aaa0f026b981101c45ea30361382940reedstatic const SkMScalar SK_MScalar1 = 1;
8550d3b57c8aaa0f026b981101c45ea30361382940reed
8650d3b57c8aaa0f026b981101c45ea30361382940reed///////////////////////////////////////////////////////////////////////////////
8750d3b57c8aaa0f026b981101c45ea30361382940reed
8850d3b57c8aaa0f026b981101c45ea30361382940reedstruct SkVector4 {
8950d3b57c8aaa0f026b981101c45ea30361382940reed    SkScalar fData[4];
9050d3b57c8aaa0f026b981101c45ea30361382940reed
9150d3b57c8aaa0f026b981101c45ea30361382940reed    SkVector4() {
9250d3b57c8aaa0f026b981101c45ea30361382940reed        this->set(0, 0, 0, 1);
9350d3b57c8aaa0f026b981101c45ea30361382940reed    }
9450d3b57c8aaa0f026b981101c45ea30361382940reed    SkVector4(const SkVector4& src) {
9550d3b57c8aaa0f026b981101c45ea30361382940reed        memcpy(fData, src.fData, sizeof(fData));
9650d3b57c8aaa0f026b981101c45ea30361382940reed    }
9750d3b57c8aaa0f026b981101c45ea30361382940reed    SkVector4(SkScalar x, SkScalar y, SkScalar z, SkScalar w = SK_Scalar1) {
9850d3b57c8aaa0f026b981101c45ea30361382940reed        fData[0] = x;
9950d3b57c8aaa0f026b981101c45ea30361382940reed        fData[1] = y;
10050d3b57c8aaa0f026b981101c45ea30361382940reed        fData[2] = z;
10150d3b57c8aaa0f026b981101c45ea30361382940reed        fData[3] = w;
10250d3b57c8aaa0f026b981101c45ea30361382940reed    }
10350d3b57c8aaa0f026b981101c45ea30361382940reed
10450d3b57c8aaa0f026b981101c45ea30361382940reed    SkVector4& operator=(const SkVector4& src) {
10550d3b57c8aaa0f026b981101c45ea30361382940reed        memcpy(fData, src.fData, sizeof(fData));
10650d3b57c8aaa0f026b981101c45ea30361382940reed        return *this;
10750d3b57c8aaa0f026b981101c45ea30361382940reed    }
10850d3b57c8aaa0f026b981101c45ea30361382940reed
10950d3b57c8aaa0f026b981101c45ea30361382940reed    bool operator==(const SkVector4& v) {
11050d3b57c8aaa0f026b981101c45ea30361382940reed        return fData[0] == v.fData[0] && fData[1] == v.fData[1] &&
11150d3b57c8aaa0f026b981101c45ea30361382940reed               fData[2] == v.fData[2] && fData[3] == v.fData[3];
11250d3b57c8aaa0f026b981101c45ea30361382940reed    }
11350d3b57c8aaa0f026b981101c45ea30361382940reed    bool operator!=(const SkVector4& v) {
11450d3b57c8aaa0f026b981101c45ea30361382940reed        return !(*this == v);
11550d3b57c8aaa0f026b981101c45ea30361382940reed    }
11650d3b57c8aaa0f026b981101c45ea30361382940reed    bool equals(SkScalar x, SkScalar y, SkScalar z, SkScalar w = SK_Scalar1) {
11750d3b57c8aaa0f026b981101c45ea30361382940reed        return fData[0] == x && fData[1] == y &&
11850d3b57c8aaa0f026b981101c45ea30361382940reed               fData[2] == z && fData[3] == w;
11950d3b57c8aaa0f026b981101c45ea30361382940reed    }
12050d3b57c8aaa0f026b981101c45ea30361382940reed
12150d3b57c8aaa0f026b981101c45ea30361382940reed    void set(SkScalar x, SkScalar y, SkScalar z, SkScalar w = SK_Scalar1) {
12250d3b57c8aaa0f026b981101c45ea30361382940reed        fData[0] = x;
12350d3b57c8aaa0f026b981101c45ea30361382940reed        fData[1] = y;
12450d3b57c8aaa0f026b981101c45ea30361382940reed        fData[2] = z;
12550d3b57c8aaa0f026b981101c45ea30361382940reed        fData[3] = w;
12650d3b57c8aaa0f026b981101c45ea30361382940reed    }
12750d3b57c8aaa0f026b981101c45ea30361382940reed};
12850d3b57c8aaa0f026b981101c45ea30361382940reed
129afe7a5f84890b88dbb61a3ba53b3d66d679f92d7Mike Klein/** \class SkMatrix44
130afe7a5f84890b88dbb61a3ba53b3d66d679f92d7Mike Klein
131afe7a5f84890b88dbb61a3ba53b3d66d679f92d7Mike Klein    The SkMatrix44 class holds a 4x4 matrix.
132afe7a5f84890b88dbb61a3ba53b3d66d679f92d7Mike Klein
133afe7a5f84890b88dbb61a3ba53b3d66d679f92d7Mike Klein    SkMatrix44 is not thread safe unless you've first called SkMatrix44::getType().
134afe7a5f84890b88dbb61a3ba53b3d66d679f92d7Mike Klein*/
13550d3b57c8aaa0f026b981101c45ea30361382940reedclass SK_API SkMatrix44 {
13650d3b57c8aaa0f026b981101c45ea30361382940reedpublic:
13750d3b57c8aaa0f026b981101c45ea30361382940reed
13850d3b57c8aaa0f026b981101c45ea30361382940reed    enum Uninitialized_Constructor {
13950d3b57c8aaa0f026b981101c45ea30361382940reed        kUninitialized_Constructor
14050d3b57c8aaa0f026b981101c45ea30361382940reed    };
14150d3b57c8aaa0f026b981101c45ea30361382940reed    enum Identity_Constructor {
14250d3b57c8aaa0f026b981101c45ea30361382940reed        kIdentity_Constructor
14350d3b57c8aaa0f026b981101c45ea30361382940reed    };
14450d3b57c8aaa0f026b981101c45ea30361382940reed
145c1a3e24918f99fc0b975111afb39dca38c50eb5cmsarett    SkMatrix44(Uninitialized_Constructor) {}
146c1a3e24918f99fc0b975111afb39dca38c50eb5cmsarett
147c1a3e24918f99fc0b975111afb39dca38c50eb5cmsarett    constexpr SkMatrix44(Identity_Constructor)
148c1a3e24918f99fc0b975111afb39dca38c50eb5cmsarett        : fMat{{ 1, 0, 0, 0, },
149c1a3e24918f99fc0b975111afb39dca38c50eb5cmsarett               { 0, 1, 0, 0, },
150c1a3e24918f99fc0b975111afb39dca38c50eb5cmsarett               { 0, 0, 1, 0, },
151c1a3e24918f99fc0b975111afb39dca38c50eb5cmsarett               { 0, 0, 0, 1, }}
152c1a3e24918f99fc0b975111afb39dca38c50eb5cmsarett        , fTypeMask(kIdentity_Mask)
153c1a3e24918f99fc0b975111afb39dca38c50eb5cmsarett    {}
15450d3b57c8aaa0f026b981101c45ea30361382940reed
15550d3b57c8aaa0f026b981101c45ea30361382940reed    SK_ATTR_DEPRECATED("use the constructors that take an enum")
15650d3b57c8aaa0f026b981101c45ea30361382940reed    SkMatrix44() { this->setIdentity(); }
15750d3b57c8aaa0f026b981101c45ea30361382940reed
15850d3b57c8aaa0f026b981101c45ea30361382940reed    SkMatrix44(const SkMatrix44& src) {
15950d3b57c8aaa0f026b981101c45ea30361382940reed        memcpy(fMat, src.fMat, sizeof(fMat));
16050d3b57c8aaa0f026b981101c45ea30361382940reed        fTypeMask = src.fTypeMask;
16150d3b57c8aaa0f026b981101c45ea30361382940reed    }
16250d3b57c8aaa0f026b981101c45ea30361382940reed
16350d3b57c8aaa0f026b981101c45ea30361382940reed    SkMatrix44(const SkMatrix44& a, const SkMatrix44& b) {
16450d3b57c8aaa0f026b981101c45ea30361382940reed        this->setConcat(a, b);
16550d3b57c8aaa0f026b981101c45ea30361382940reed    }
16650d3b57c8aaa0f026b981101c45ea30361382940reed
16750d3b57c8aaa0f026b981101c45ea30361382940reed    SkMatrix44& operator=(const SkMatrix44& src) {
16850d3b57c8aaa0f026b981101c45ea30361382940reed        if (&src != this) {
16950d3b57c8aaa0f026b981101c45ea30361382940reed            memcpy(fMat, src.fMat, sizeof(fMat));
17050d3b57c8aaa0f026b981101c45ea30361382940reed            fTypeMask = src.fTypeMask;
17150d3b57c8aaa0f026b981101c45ea30361382940reed        }
17250d3b57c8aaa0f026b981101c45ea30361382940reed        return *this;
17350d3b57c8aaa0f026b981101c45ea30361382940reed    }
17450d3b57c8aaa0f026b981101c45ea30361382940reed
17550d3b57c8aaa0f026b981101c45ea30361382940reed    bool operator==(const SkMatrix44& other) const;
17650d3b57c8aaa0f026b981101c45ea30361382940reed    bool operator!=(const SkMatrix44& other) const {
17750d3b57c8aaa0f026b981101c45ea30361382940reed        return !(other == *this);
17850d3b57c8aaa0f026b981101c45ea30361382940reed    }
17950d3b57c8aaa0f026b981101c45ea30361382940reed
18050d3b57c8aaa0f026b981101c45ea30361382940reed    /* When converting from SkMatrix44 to SkMatrix, the third row and
18150d3b57c8aaa0f026b981101c45ea30361382940reed     * column is dropped.  When converting from SkMatrix to SkMatrix44
18250d3b57c8aaa0f026b981101c45ea30361382940reed     * the third row and column remain as identity:
18350d3b57c8aaa0f026b981101c45ea30361382940reed     * [ a b c ]      [ a b 0 c ]
18450d3b57c8aaa0f026b981101c45ea30361382940reed     * [ d e f ]  ->  [ d e 0 f ]
18550d3b57c8aaa0f026b981101c45ea30361382940reed     * [ g h i ]      [ 0 0 1 0 ]
18650d3b57c8aaa0f026b981101c45ea30361382940reed     *                [ g h 0 i ]
18750d3b57c8aaa0f026b981101c45ea30361382940reed     */
18850d3b57c8aaa0f026b981101c45ea30361382940reed    SkMatrix44(const SkMatrix&);
18950d3b57c8aaa0f026b981101c45ea30361382940reed    SkMatrix44& operator=(const SkMatrix& src);
19050d3b57c8aaa0f026b981101c45ea30361382940reed    operator SkMatrix() const;
19150d3b57c8aaa0f026b981101c45ea30361382940reed
19250d3b57c8aaa0f026b981101c45ea30361382940reed    /**
19350d3b57c8aaa0f026b981101c45ea30361382940reed     *  Return a reference to a const identity matrix
19450d3b57c8aaa0f026b981101c45ea30361382940reed     */
19550d3b57c8aaa0f026b981101c45ea30361382940reed    static const SkMatrix44& I();
19650d3b57c8aaa0f026b981101c45ea30361382940reed
19750d3b57c8aaa0f026b981101c45ea30361382940reed    enum TypeMask {
19850d3b57c8aaa0f026b981101c45ea30361382940reed        kIdentity_Mask      = 0,
19950d3b57c8aaa0f026b981101c45ea30361382940reed        kTranslate_Mask     = 0x01,  //!< set if the matrix has translation
20050d3b57c8aaa0f026b981101c45ea30361382940reed        kScale_Mask         = 0x02,  //!< set if the matrix has any scale != 1
20150d3b57c8aaa0f026b981101c45ea30361382940reed        kAffine_Mask        = 0x04,  //!< set if the matrix skews or rotates
20250d3b57c8aaa0f026b981101c45ea30361382940reed        kPerspective_Mask   = 0x08   //!< set if the matrix is in perspective
20350d3b57c8aaa0f026b981101c45ea30361382940reed    };
20450d3b57c8aaa0f026b981101c45ea30361382940reed
20550d3b57c8aaa0f026b981101c45ea30361382940reed    /**
20650d3b57c8aaa0f026b981101c45ea30361382940reed     *  Returns a bitfield describing the transformations the matrix may
20750d3b57c8aaa0f026b981101c45ea30361382940reed     *  perform. The bitfield is computed conservatively, so it may include
20850d3b57c8aaa0f026b981101c45ea30361382940reed     *  false positives. For example, when kPerspective_Mask is true, all
20950d3b57c8aaa0f026b981101c45ea30361382940reed     *  other bits may be set to true even in the case of a pure perspective
21050d3b57c8aaa0f026b981101c45ea30361382940reed     *  transform.
21150d3b57c8aaa0f026b981101c45ea30361382940reed     */
21250d3b57c8aaa0f026b981101c45ea30361382940reed    inline TypeMask getType() const {
21350d3b57c8aaa0f026b981101c45ea30361382940reed        if (fTypeMask & kUnknown_Mask) {
21450d3b57c8aaa0f026b981101c45ea30361382940reed            fTypeMask = this->computeTypeMask();
21550d3b57c8aaa0f026b981101c45ea30361382940reed        }
21650d3b57c8aaa0f026b981101c45ea30361382940reed        SkASSERT(!(fTypeMask & kUnknown_Mask));
21750d3b57c8aaa0f026b981101c45ea30361382940reed        return (TypeMask)fTypeMask;
21850d3b57c8aaa0f026b981101c45ea30361382940reed    }
21950d3b57c8aaa0f026b981101c45ea30361382940reed
22050d3b57c8aaa0f026b981101c45ea30361382940reed    /**
22150d3b57c8aaa0f026b981101c45ea30361382940reed     *  Return true if the matrix is identity.
22250d3b57c8aaa0f026b981101c45ea30361382940reed     */
22350d3b57c8aaa0f026b981101c45ea30361382940reed    inline bool isIdentity() const {
22450d3b57c8aaa0f026b981101c45ea30361382940reed        return kIdentity_Mask == this->getType();
22550d3b57c8aaa0f026b981101c45ea30361382940reed    }
22650d3b57c8aaa0f026b981101c45ea30361382940reed
22750d3b57c8aaa0f026b981101c45ea30361382940reed    /**
22850d3b57c8aaa0f026b981101c45ea30361382940reed     *  Return true if the matrix contains translate or is identity.
22950d3b57c8aaa0f026b981101c45ea30361382940reed     */
23050d3b57c8aaa0f026b981101c45ea30361382940reed    inline bool isTranslate() const {
23150d3b57c8aaa0f026b981101c45ea30361382940reed        return !(this->getType() & ~kTranslate_Mask);
23250d3b57c8aaa0f026b981101c45ea30361382940reed    }
23350d3b57c8aaa0f026b981101c45ea30361382940reed
23450d3b57c8aaa0f026b981101c45ea30361382940reed    /**
23550d3b57c8aaa0f026b981101c45ea30361382940reed     *  Return true if the matrix only contains scale or translate or is identity.
23650d3b57c8aaa0f026b981101c45ea30361382940reed     */
23750d3b57c8aaa0f026b981101c45ea30361382940reed    inline bool isScaleTranslate() const {
23850d3b57c8aaa0f026b981101c45ea30361382940reed        return !(this->getType() & ~(kScale_Mask | kTranslate_Mask));
23950d3b57c8aaa0f026b981101c45ea30361382940reed    }
24050d3b57c8aaa0f026b981101c45ea30361382940reed
24150d3b57c8aaa0f026b981101c45ea30361382940reed    /**
24250d3b57c8aaa0f026b981101c45ea30361382940reed     *  Returns true if the matrix only contains scale or is identity.
24350d3b57c8aaa0f026b981101c45ea30361382940reed     */
24450d3b57c8aaa0f026b981101c45ea30361382940reed    inline bool isScale() const {
24550d3b57c8aaa0f026b981101c45ea30361382940reed            return !(this->getType() & ~kScale_Mask);
24650d3b57c8aaa0f026b981101c45ea30361382940reed    }
24750d3b57c8aaa0f026b981101c45ea30361382940reed
24850d3b57c8aaa0f026b981101c45ea30361382940reed    inline bool hasPerspective() const {
24950d3b57c8aaa0f026b981101c45ea30361382940reed        return SkToBool(this->getType() & kPerspective_Mask);
25050d3b57c8aaa0f026b981101c45ea30361382940reed    }
25150d3b57c8aaa0f026b981101c45ea30361382940reed
25250d3b57c8aaa0f026b981101c45ea30361382940reed    void setIdentity();
25350d3b57c8aaa0f026b981101c45ea30361382940reed    inline void reset() { this->setIdentity();}
25450d3b57c8aaa0f026b981101c45ea30361382940reed
25550d3b57c8aaa0f026b981101c45ea30361382940reed    /**
25650d3b57c8aaa0f026b981101c45ea30361382940reed     *  get a value from the matrix. The row,col parameters work as follows:
25750d3b57c8aaa0f026b981101c45ea30361382940reed     *  (0, 0)  scale-x
25850d3b57c8aaa0f026b981101c45ea30361382940reed     *  (0, 3)  translate-x
25950d3b57c8aaa0f026b981101c45ea30361382940reed     *  (3, 0)  perspective-x
26050d3b57c8aaa0f026b981101c45ea30361382940reed     */
26150d3b57c8aaa0f026b981101c45ea30361382940reed    inline SkMScalar get(int row, int col) const {
26250d3b57c8aaa0f026b981101c45ea30361382940reed        SkASSERT((unsigned)row <= 3);
26350d3b57c8aaa0f026b981101c45ea30361382940reed        SkASSERT((unsigned)col <= 3);
26450d3b57c8aaa0f026b981101c45ea30361382940reed        return fMat[col][row];
26550d3b57c8aaa0f026b981101c45ea30361382940reed    }
26650d3b57c8aaa0f026b981101c45ea30361382940reed
26750d3b57c8aaa0f026b981101c45ea30361382940reed    /**
26850d3b57c8aaa0f026b981101c45ea30361382940reed     *  set a value in the matrix. The row,col parameters work as follows:
26950d3b57c8aaa0f026b981101c45ea30361382940reed     *  (0, 0)  scale-x
27050d3b57c8aaa0f026b981101c45ea30361382940reed     *  (0, 3)  translate-x
27150d3b57c8aaa0f026b981101c45ea30361382940reed     *  (3, 0)  perspective-x
27250d3b57c8aaa0f026b981101c45ea30361382940reed     */
27350d3b57c8aaa0f026b981101c45ea30361382940reed    inline void set(int row, int col, SkMScalar value) {
27450d3b57c8aaa0f026b981101c45ea30361382940reed        SkASSERT((unsigned)row <= 3);
27550d3b57c8aaa0f026b981101c45ea30361382940reed        SkASSERT((unsigned)col <= 3);
27650d3b57c8aaa0f026b981101c45ea30361382940reed        fMat[col][row] = value;
27750d3b57c8aaa0f026b981101c45ea30361382940reed        this->dirtyTypeMask();
27850d3b57c8aaa0f026b981101c45ea30361382940reed    }
27950d3b57c8aaa0f026b981101c45ea30361382940reed
28050d3b57c8aaa0f026b981101c45ea30361382940reed    inline double getDouble(int row, int col) const {
28150d3b57c8aaa0f026b981101c45ea30361382940reed        return SkMScalarToDouble(this->get(row, col));
28250d3b57c8aaa0f026b981101c45ea30361382940reed    }
28350d3b57c8aaa0f026b981101c45ea30361382940reed    inline void setDouble(int row, int col, double value) {
28450d3b57c8aaa0f026b981101c45ea30361382940reed        this->set(row, col, SkDoubleToMScalar(value));
28550d3b57c8aaa0f026b981101c45ea30361382940reed    }
28650d3b57c8aaa0f026b981101c45ea30361382940reed    inline float getFloat(int row, int col) const {
28750d3b57c8aaa0f026b981101c45ea30361382940reed        return SkMScalarToFloat(this->get(row, col));
28850d3b57c8aaa0f026b981101c45ea30361382940reed    }
28950d3b57c8aaa0f026b981101c45ea30361382940reed    inline void setFloat(int row, int col, float value) {
29050d3b57c8aaa0f026b981101c45ea30361382940reed        this->set(row, col, SkFloatToMScalar(value));
29150d3b57c8aaa0f026b981101c45ea30361382940reed    }
29250d3b57c8aaa0f026b981101c45ea30361382940reed
29350d3b57c8aaa0f026b981101c45ea30361382940reed    /** These methods allow one to efficiently read matrix entries into an
29450d3b57c8aaa0f026b981101c45ea30361382940reed     *  array. The given array must have room for exactly 16 entries. Whenever
29550d3b57c8aaa0f026b981101c45ea30361382940reed     *  possible, they will try to use memcpy rather than an entry-by-entry
29650d3b57c8aaa0f026b981101c45ea30361382940reed     *  copy.
297c1a3e24918f99fc0b975111afb39dca38c50eb5cmsarett     *
298c1a3e24918f99fc0b975111afb39dca38c50eb5cmsarett     *  Col major indicates that consecutive elements of columns will be stored
299c1a3e24918f99fc0b975111afb39dca38c50eb5cmsarett     *  contiguously in memory.  Row major indicates that consecutive elements
300c1a3e24918f99fc0b975111afb39dca38c50eb5cmsarett     *  of rows will be stored contiguously in memory.
30150d3b57c8aaa0f026b981101c45ea30361382940reed     */
30250d3b57c8aaa0f026b981101c45ea30361382940reed    void asColMajorf(float[]) const;
30350d3b57c8aaa0f026b981101c45ea30361382940reed    void asColMajord(double[]) const;
30450d3b57c8aaa0f026b981101c45ea30361382940reed    void asRowMajorf(float[]) const;
30550d3b57c8aaa0f026b981101c45ea30361382940reed    void asRowMajord(double[]) const;
30650d3b57c8aaa0f026b981101c45ea30361382940reed
30750d3b57c8aaa0f026b981101c45ea30361382940reed    /** These methods allow one to efficiently set all matrix entries from an
30850d3b57c8aaa0f026b981101c45ea30361382940reed     *  array. The given array must have room for exactly 16 entries. Whenever
30950d3b57c8aaa0f026b981101c45ea30361382940reed     *  possible, they will try to use memcpy rather than an entry-by-entry
31050d3b57c8aaa0f026b981101c45ea30361382940reed     *  copy.
311c1a3e24918f99fc0b975111afb39dca38c50eb5cmsarett     *
312c1a3e24918f99fc0b975111afb39dca38c50eb5cmsarett     *  Col major indicates that input memory will be treated as if consecutive
313c1a3e24918f99fc0b975111afb39dca38c50eb5cmsarett     *  elements of columns are stored contiguously in memory.  Row major
314c1a3e24918f99fc0b975111afb39dca38c50eb5cmsarett     *  indicates that input memory will be treated as if consecutive elements
315c1a3e24918f99fc0b975111afb39dca38c50eb5cmsarett     *  of rows are stored contiguously in memory.
31650d3b57c8aaa0f026b981101c45ea30361382940reed     */
31750d3b57c8aaa0f026b981101c45ea30361382940reed    void setColMajorf(const float[]);
31850d3b57c8aaa0f026b981101c45ea30361382940reed    void setColMajord(const double[]);
31950d3b57c8aaa0f026b981101c45ea30361382940reed    void setRowMajorf(const float[]);
32050d3b57c8aaa0f026b981101c45ea30361382940reed    void setRowMajord(const double[]);
32150d3b57c8aaa0f026b981101c45ea30361382940reed
32250d3b57c8aaa0f026b981101c45ea30361382940reed#ifdef SK_MSCALAR_IS_FLOAT
32350d3b57c8aaa0f026b981101c45ea30361382940reed    void setColMajor(const SkMScalar data[]) { this->setColMajorf(data); }
32450d3b57c8aaa0f026b981101c45ea30361382940reed    void setRowMajor(const SkMScalar data[]) { this->setRowMajorf(data); }
32550d3b57c8aaa0f026b981101c45ea30361382940reed#else
32650d3b57c8aaa0f026b981101c45ea30361382940reed    void setColMajor(const SkMScalar data[]) { this->setColMajord(data); }
32750d3b57c8aaa0f026b981101c45ea30361382940reed    void setRowMajor(const SkMScalar data[]) { this->setRowMajord(data); }
32850d3b57c8aaa0f026b981101c45ea30361382940reed#endif
32950d3b57c8aaa0f026b981101c45ea30361382940reed
33050d3b57c8aaa0f026b981101c45ea30361382940reed    /* This sets the top-left of the matrix and clears the translation and
331c1a3e24918f99fc0b975111afb39dca38c50eb5cmsarett     * perspective components (with [3][3] set to 1).  mXY is interpreted
332c1a3e24918f99fc0b975111afb39dca38c50eb5cmsarett     * as the matrix entry at col = X, row = Y. */
33350d3b57c8aaa0f026b981101c45ea30361382940reed    void set3x3(SkMScalar m00, SkMScalar m01, SkMScalar m02,
33450d3b57c8aaa0f026b981101c45ea30361382940reed                SkMScalar m10, SkMScalar m11, SkMScalar m12,
33550d3b57c8aaa0f026b981101c45ea30361382940reed                SkMScalar m20, SkMScalar m21, SkMScalar m22);
336c1a3e24918f99fc0b975111afb39dca38c50eb5cmsarett    void set3x3RowMajorf(const float[]);
33750d3b57c8aaa0f026b981101c45ea30361382940reed
33850d3b57c8aaa0f026b981101c45ea30361382940reed    void setTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz);
33950d3b57c8aaa0f026b981101c45ea30361382940reed    void preTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz);
34050d3b57c8aaa0f026b981101c45ea30361382940reed    void postTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz);
34150d3b57c8aaa0f026b981101c45ea30361382940reed
34250d3b57c8aaa0f026b981101c45ea30361382940reed    void setScale(SkMScalar sx, SkMScalar sy, SkMScalar sz);
34350d3b57c8aaa0f026b981101c45ea30361382940reed    void preScale(SkMScalar sx, SkMScalar sy, SkMScalar sz);
34450d3b57c8aaa0f026b981101c45ea30361382940reed    void postScale(SkMScalar sx, SkMScalar sy, SkMScalar sz);
34550d3b57c8aaa0f026b981101c45ea30361382940reed
34650d3b57c8aaa0f026b981101c45ea30361382940reed    inline void setScale(SkMScalar scale) {
34750d3b57c8aaa0f026b981101c45ea30361382940reed        this->setScale(scale, scale, scale);
34850d3b57c8aaa0f026b981101c45ea30361382940reed    }
34950d3b57c8aaa0f026b981101c45ea30361382940reed    inline void preScale(SkMScalar scale) {
35050d3b57c8aaa0f026b981101c45ea30361382940reed        this->preScale(scale, scale, scale);
35150d3b57c8aaa0f026b981101c45ea30361382940reed    }
35250d3b57c8aaa0f026b981101c45ea30361382940reed    inline void postScale(SkMScalar scale) {
35350d3b57c8aaa0f026b981101c45ea30361382940reed        this->postScale(scale, scale, scale);
35450d3b57c8aaa0f026b981101c45ea30361382940reed    }
35550d3b57c8aaa0f026b981101c45ea30361382940reed
35650d3b57c8aaa0f026b981101c45ea30361382940reed    void setRotateDegreesAbout(SkMScalar x, SkMScalar y, SkMScalar z,
35750d3b57c8aaa0f026b981101c45ea30361382940reed                               SkMScalar degrees) {
35850d3b57c8aaa0f026b981101c45ea30361382940reed        this->setRotateAbout(x, y, z, degrees * SK_MScalarPI / 180);
35950d3b57c8aaa0f026b981101c45ea30361382940reed    }
36050d3b57c8aaa0f026b981101c45ea30361382940reed
36150d3b57c8aaa0f026b981101c45ea30361382940reed    /** Rotate about the vector [x,y,z]. If that vector is not unit-length,
36250d3b57c8aaa0f026b981101c45ea30361382940reed        it will be automatically resized.
36350d3b57c8aaa0f026b981101c45ea30361382940reed     */
36450d3b57c8aaa0f026b981101c45ea30361382940reed    void setRotateAbout(SkMScalar x, SkMScalar y, SkMScalar z,
36550d3b57c8aaa0f026b981101c45ea30361382940reed                        SkMScalar radians);
36650d3b57c8aaa0f026b981101c45ea30361382940reed    /** Rotate about the vector [x,y,z]. Does not check the length of the
36750d3b57c8aaa0f026b981101c45ea30361382940reed        vector, assuming it is unit-length.
36850d3b57c8aaa0f026b981101c45ea30361382940reed     */
36950d3b57c8aaa0f026b981101c45ea30361382940reed    void setRotateAboutUnit(SkMScalar x, SkMScalar y, SkMScalar z,
37050d3b57c8aaa0f026b981101c45ea30361382940reed                            SkMScalar radians);
37150d3b57c8aaa0f026b981101c45ea30361382940reed
37250d3b57c8aaa0f026b981101c45ea30361382940reed    void setConcat(const SkMatrix44& a, const SkMatrix44& b);
37350d3b57c8aaa0f026b981101c45ea30361382940reed    inline void preConcat(const SkMatrix44& m) {
37450d3b57c8aaa0f026b981101c45ea30361382940reed        this->setConcat(*this, m);
37550d3b57c8aaa0f026b981101c45ea30361382940reed    }
37650d3b57c8aaa0f026b981101c45ea30361382940reed    inline void postConcat(const SkMatrix44& m) {
37750d3b57c8aaa0f026b981101c45ea30361382940reed        this->setConcat(m, *this);
37850d3b57c8aaa0f026b981101c45ea30361382940reed    }
37950d3b57c8aaa0f026b981101c45ea30361382940reed
38050d3b57c8aaa0f026b981101c45ea30361382940reed    friend SkMatrix44 operator*(const SkMatrix44& a, const SkMatrix44& b) {
38150d3b57c8aaa0f026b981101c45ea30361382940reed        return SkMatrix44(a, b);
38250d3b57c8aaa0f026b981101c45ea30361382940reed    }
38350d3b57c8aaa0f026b981101c45ea30361382940reed
38450d3b57c8aaa0f026b981101c45ea30361382940reed    /** If this is invertible, return that in inverse and return true. If it is
38550d3b57c8aaa0f026b981101c45ea30361382940reed        not invertible, return false and leave the inverse parameter in an
38650d3b57c8aaa0f026b981101c45ea30361382940reed        unspecified state.
38750d3b57c8aaa0f026b981101c45ea30361382940reed     */
38850d3b57c8aaa0f026b981101c45ea30361382940reed    bool invert(SkMatrix44* inverse) const;
38950d3b57c8aaa0f026b981101c45ea30361382940reed
39050d3b57c8aaa0f026b981101c45ea30361382940reed    /** Transpose this matrix in place. */
39150d3b57c8aaa0f026b981101c45ea30361382940reed    void transpose();
39250d3b57c8aaa0f026b981101c45ea30361382940reed
39350d3b57c8aaa0f026b981101c45ea30361382940reed    /** Apply the matrix to the src vector, returning the new vector in dst.
39450d3b57c8aaa0f026b981101c45ea30361382940reed        It is legal for src and dst to point to the same memory.
39550d3b57c8aaa0f026b981101c45ea30361382940reed     */
39650d3b57c8aaa0f026b981101c45ea30361382940reed    void mapScalars(const SkScalar src[4], SkScalar dst[4]) const;
39750d3b57c8aaa0f026b981101c45ea30361382940reed    inline void mapScalars(SkScalar vec[4]) const {
39850d3b57c8aaa0f026b981101c45ea30361382940reed        this->mapScalars(vec, vec);
39950d3b57c8aaa0f026b981101c45ea30361382940reed    }
40050d3b57c8aaa0f026b981101c45ea30361382940reed
40150d3b57c8aaa0f026b981101c45ea30361382940reed    SK_ATTR_DEPRECATED("use mapScalars")
40250d3b57c8aaa0f026b981101c45ea30361382940reed    void map(const SkScalar src[4], SkScalar dst[4]) const {
40350d3b57c8aaa0f026b981101c45ea30361382940reed        this->mapScalars(src, dst);
40450d3b57c8aaa0f026b981101c45ea30361382940reed    }
40550d3b57c8aaa0f026b981101c45ea30361382940reed
40650d3b57c8aaa0f026b981101c45ea30361382940reed    SK_ATTR_DEPRECATED("use mapScalars")
40750d3b57c8aaa0f026b981101c45ea30361382940reed    void map(SkScalar vec[4]) const {
40850d3b57c8aaa0f026b981101c45ea30361382940reed        this->mapScalars(vec, vec);
40950d3b57c8aaa0f026b981101c45ea30361382940reed    }
41050d3b57c8aaa0f026b981101c45ea30361382940reed
41150d3b57c8aaa0f026b981101c45ea30361382940reed#ifdef SK_MSCALAR_IS_DOUBLE
41250d3b57c8aaa0f026b981101c45ea30361382940reed    void mapMScalars(const SkMScalar src[4], SkMScalar dst[4]) const;
41350d3b57c8aaa0f026b981101c45ea30361382940reed#elif defined SK_MSCALAR_IS_FLOAT
41450d3b57c8aaa0f026b981101c45ea30361382940reed    inline void mapMScalars(const SkMScalar src[4], SkMScalar dst[4]) const {
41550d3b57c8aaa0f026b981101c45ea30361382940reed        this->mapScalars(src, dst);
41650d3b57c8aaa0f026b981101c45ea30361382940reed    }
41750d3b57c8aaa0f026b981101c45ea30361382940reed#endif
41850d3b57c8aaa0f026b981101c45ea30361382940reed    inline void mapMScalars(SkMScalar vec[4]) const {
41950d3b57c8aaa0f026b981101c45ea30361382940reed        this->mapMScalars(vec, vec);
42050d3b57c8aaa0f026b981101c45ea30361382940reed    }
42150d3b57c8aaa0f026b981101c45ea30361382940reed
42250d3b57c8aaa0f026b981101c45ea30361382940reed    friend SkVector4 operator*(const SkMatrix44& m, const SkVector4& src) {
42350d3b57c8aaa0f026b981101c45ea30361382940reed        SkVector4 dst;
42450d3b57c8aaa0f026b981101c45ea30361382940reed        m.mapScalars(src.fData, dst.fData);
42550d3b57c8aaa0f026b981101c45ea30361382940reed        return dst;
42650d3b57c8aaa0f026b981101c45ea30361382940reed    }
42750d3b57c8aaa0f026b981101c45ea30361382940reed
42850d3b57c8aaa0f026b981101c45ea30361382940reed    /**
42950d3b57c8aaa0f026b981101c45ea30361382940reed     *  map an array of [x, y, 0, 1] through the matrix, returning an array
43050d3b57c8aaa0f026b981101c45ea30361382940reed     *  of [x', y', z', w'].
43150d3b57c8aaa0f026b981101c45ea30361382940reed     *
43250d3b57c8aaa0f026b981101c45ea30361382940reed     *  @param src2     array of [x, y] pairs, with implied z=0 and w=1
43350d3b57c8aaa0f026b981101c45ea30361382940reed     *  @param count    number of [x, y] pairs in src2
43450d3b57c8aaa0f026b981101c45ea30361382940reed     *  @param dst4     array of [x', y', z', w'] quads as the output.
43550d3b57c8aaa0f026b981101c45ea30361382940reed     */
43650d3b57c8aaa0f026b981101c45ea30361382940reed    void map2(const float src2[], int count, float dst4[]) const;
43750d3b57c8aaa0f026b981101c45ea30361382940reed    void map2(const double src2[], int count, double dst4[]) const;
43850d3b57c8aaa0f026b981101c45ea30361382940reed
43950d3b57c8aaa0f026b981101c45ea30361382940reed    /** Returns true if transformating an axis-aligned square in 2d by this matrix
44050d3b57c8aaa0f026b981101c45ea30361382940reed        will produce another 2d axis-aligned square; typically means the matrix
44150d3b57c8aaa0f026b981101c45ea30361382940reed        is a scale with perhaps a 90-degree rotation. A 3d rotation through 90
44250d3b57c8aaa0f026b981101c45ea30361382940reed        degrees into a perpendicular plane collapses a square to a line, but
44350d3b57c8aaa0f026b981101c45ea30361382940reed        is still considered to be axis-aligned.
44450d3b57c8aaa0f026b981101c45ea30361382940reed
44550d3b57c8aaa0f026b981101c45ea30361382940reed        By default, tolerates very slight error due to float imprecisions;
44650d3b57c8aaa0f026b981101c45ea30361382940reed        a 90-degree rotation can still end up with 10^-17 of
44750d3b57c8aaa0f026b981101c45ea30361382940reed        "non-axis-aligned" result.
44850d3b57c8aaa0f026b981101c45ea30361382940reed     */
44950d3b57c8aaa0f026b981101c45ea30361382940reed    bool preserves2dAxisAlignment(SkMScalar epsilon = SK_ScalarNearlyZero) const;
45050d3b57c8aaa0f026b981101c45ea30361382940reed
45150d3b57c8aaa0f026b981101c45ea30361382940reed    void dump() const;
45250d3b57c8aaa0f026b981101c45ea30361382940reed
45350d3b57c8aaa0f026b981101c45ea30361382940reed    double determinant() const;
45450d3b57c8aaa0f026b981101c45ea30361382940reed
45550d3b57c8aaa0f026b981101c45ea30361382940reedprivate:
456c1a3e24918f99fc0b975111afb39dca38c50eb5cmsarett    /* This is indexed by [col][row]. */
45750d3b57c8aaa0f026b981101c45ea30361382940reed    SkMScalar           fMat[4][4];
45850d3b57c8aaa0f026b981101c45ea30361382940reed    mutable unsigned    fTypeMask;
45950d3b57c8aaa0f026b981101c45ea30361382940reed
46050d3b57c8aaa0f026b981101c45ea30361382940reed    enum {
46150d3b57c8aaa0f026b981101c45ea30361382940reed        kUnknown_Mask = 0x80,
46250d3b57c8aaa0f026b981101c45ea30361382940reed
46350d3b57c8aaa0f026b981101c45ea30361382940reed        kAllPublic_Masks = 0xF
46450d3b57c8aaa0f026b981101c45ea30361382940reed    };
46550d3b57c8aaa0f026b981101c45ea30361382940reed
466de68d6c4616d86621373d88100002ddfdb9c08e3brianosman    void as3x4RowMajorf(float[]) const;
467de68d6c4616d86621373d88100002ddfdb9c08e3brianosman    void set3x4RowMajorf(const float[]);
468111a42d9cebf0bb8844c5d24f67fac57cc619d29msarett
46950d3b57c8aaa0f026b981101c45ea30361382940reed    SkMScalar transX() const { return fMat[3][0]; }
47050d3b57c8aaa0f026b981101c45ea30361382940reed    SkMScalar transY() const { return fMat[3][1]; }
47150d3b57c8aaa0f026b981101c45ea30361382940reed    SkMScalar transZ() const { return fMat[3][2]; }
47250d3b57c8aaa0f026b981101c45ea30361382940reed
47350d3b57c8aaa0f026b981101c45ea30361382940reed    SkMScalar scaleX() const { return fMat[0][0]; }
47450d3b57c8aaa0f026b981101c45ea30361382940reed    SkMScalar scaleY() const { return fMat[1][1]; }
47550d3b57c8aaa0f026b981101c45ea30361382940reed    SkMScalar scaleZ() const { return fMat[2][2]; }
47650d3b57c8aaa0f026b981101c45ea30361382940reed
47750d3b57c8aaa0f026b981101c45ea30361382940reed    SkMScalar perspX() const { return fMat[0][3]; }
47850d3b57c8aaa0f026b981101c45ea30361382940reed    SkMScalar perspY() const { return fMat[1][3]; }
47950d3b57c8aaa0f026b981101c45ea30361382940reed    SkMScalar perspZ() const { return fMat[2][3]; }
48050d3b57c8aaa0f026b981101c45ea30361382940reed
48150d3b57c8aaa0f026b981101c45ea30361382940reed    int computeTypeMask() const;
48250d3b57c8aaa0f026b981101c45ea30361382940reed
48350d3b57c8aaa0f026b981101c45ea30361382940reed    inline void dirtyTypeMask() {
48450d3b57c8aaa0f026b981101c45ea30361382940reed        fTypeMask = kUnknown_Mask;
48550d3b57c8aaa0f026b981101c45ea30361382940reed    }
48650d3b57c8aaa0f026b981101c45ea30361382940reed
48750d3b57c8aaa0f026b981101c45ea30361382940reed    inline void setTypeMask(int mask) {
48850d3b57c8aaa0f026b981101c45ea30361382940reed        SkASSERT(0 == (~(kAllPublic_Masks | kUnknown_Mask) & mask));
48950d3b57c8aaa0f026b981101c45ea30361382940reed        fTypeMask = mask;
49050d3b57c8aaa0f026b981101c45ea30361382940reed    }
49150d3b57c8aaa0f026b981101c45ea30361382940reed
49250d3b57c8aaa0f026b981101c45ea30361382940reed    /**
49350d3b57c8aaa0f026b981101c45ea30361382940reed     *  Does not take the time to 'compute' the typemask. Only returns true if
49450d3b57c8aaa0f026b981101c45ea30361382940reed     *  we already know that this matrix is identity.
49550d3b57c8aaa0f026b981101c45ea30361382940reed     */
49650d3b57c8aaa0f026b981101c45ea30361382940reed    inline bool isTriviallyIdentity() const {
49750d3b57c8aaa0f026b981101c45ea30361382940reed        return 0 == fTypeMask;
49850d3b57c8aaa0f026b981101c45ea30361382940reed    }
499111a42d9cebf0bb8844c5d24f67fac57cc619d29msarett
500e151bdb357c21b833718b369fe8fbd7fd57ae474Matt Sarett    inline const SkMScalar* values() const { return &fMat[0][0]; }
501e151bdb357c21b833718b369fe8fbd7fd57ae474Matt Sarett
502111a42d9cebf0bb8844c5d24f67fac57cc619d29msarett    friend class SkColorSpace;
503e151bdb357c21b833718b369fe8fbd7fd57ae474Matt Sarett    friend class SkColorSpace_XYZ;
50450d3b57c8aaa0f026b981101c45ea30361382940reed};
50550d3b57c8aaa0f026b981101c45ea30361382940reed
50650d3b57c8aaa0f026b981101c45ea30361382940reed#endif
507