gfx/skia/trunk/include/utils/SkMatrix44.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/skia/trunk/include/utils/SkMatrix44.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,422 @@
     1.4 +/*
     1.5 + * Copyright 2011 Google Inc.
     1.6 + *
     1.7 + * Use of this source code is governed by a BSD-style license that can be
     1.8 + * found in the LICENSE file.
     1.9 + */
    1.10 +
    1.11 +#ifndef SkMatrix44_DEFINED
    1.12 +#define SkMatrix44_DEFINED
    1.13 +
    1.14 +#include "SkMatrix.h"
    1.15 +#include "SkScalar.h"
    1.16 +
    1.17 +#ifdef SK_MSCALAR_IS_DOUBLE
    1.18 +#ifdef SK_MSCALAR_IS_FLOAT
    1.19 +    #error "can't define MSCALAR both as DOUBLE and FLOAT"
    1.20 +#endif
    1.21 +    typedef double SkMScalar;
    1.22 +
    1.23 +    static inline double SkFloatToMScalar(float x) {
    1.24 +        return static_cast<double>(x);
    1.25 +    }
    1.26 +    static inline float SkMScalarToFloat(double x) {
    1.27 +        return static_cast<float>(x);
    1.28 +    }
    1.29 +    static inline double SkDoubleToMScalar(double x) {
    1.30 +        return x;
    1.31 +    }
    1.32 +    static inline double SkMScalarToDouble(double x) {
    1.33 +        return x;
    1.34 +    }
    1.35 +    static const SkMScalar SK_MScalarPI = 3.141592653589793;
    1.36 +#elif defined SK_MSCALAR_IS_FLOAT
    1.37 +#ifdef SK_MSCALAR_IS_DOUBLE
    1.38 +    #error "can't define MSCALAR both as DOUBLE and FLOAT"
    1.39 +#endif
    1.40 +    typedef float SkMScalar;
    1.41 +
    1.42 +    static inline float SkFloatToMScalar(float x) {
    1.43 +        return x;
    1.44 +    }
    1.45 +    static inline float SkMScalarToFloat(float x) {
    1.46 +        return x;
    1.47 +    }
    1.48 +    static inline float SkDoubleToMScalar(double x) {
    1.49 +        return static_cast<float>(x);
    1.50 +    }
    1.51 +    static inline double SkMScalarToDouble(float x) {
    1.52 +        return static_cast<double>(x);
    1.53 +    }
    1.54 +    static const SkMScalar SK_MScalarPI = 3.14159265f;
    1.55 +#endif
    1.56 +
    1.57 +#define SkMScalarToScalar SkMScalarToFloat
    1.58 +#define SkScalarToMScalar SkFloatToMScalar
    1.59 +
    1.60 +static const SkMScalar SK_MScalar1 = 1;
    1.61 +
    1.62 +///////////////////////////////////////////////////////////////////////////////
    1.63 +
    1.64 +struct SkVector4 {
    1.65 +    SkScalar fData[4];
    1.66 +
    1.67 +    SkVector4() {
    1.68 +        this->set(0, 0, 0, 1);
    1.69 +    }
    1.70 +    SkVector4(const SkVector4& src) {
    1.71 +        memcpy(fData, src.fData, sizeof(fData));
    1.72 +    }
    1.73 +    SkVector4(SkScalar x, SkScalar y, SkScalar z, SkScalar w = SK_Scalar1) {
    1.74 +        fData[0] = x;
    1.75 +        fData[1] = y;
    1.76 +        fData[2] = z;
    1.77 +        fData[3] = w;
    1.78 +    }
    1.79 +
    1.80 +    SkVector4& operator=(const SkVector4& src) {
    1.81 +        memcpy(fData, src.fData, sizeof(fData));
    1.82 +        return *this;
    1.83 +    }
    1.84 +
    1.85 +    bool operator==(const SkVector4& v) {
    1.86 +        return fData[0] == v.fData[0] && fData[1] == v.fData[1] &&
    1.87 +               fData[2] == v.fData[2] && fData[3] == v.fData[3];
    1.88 +    }
    1.89 +    bool operator!=(const SkVector4& v) {
    1.90 +        return !(*this == v);
    1.91 +    }
    1.92 +    bool equals(SkScalar x, SkScalar y, SkScalar z, SkScalar w = SK_Scalar1) {
    1.93 +        return fData[0] == x && fData[1] == y &&
    1.94 +               fData[2] == z && fData[3] == w;
    1.95 +    }
    1.96 +
    1.97 +    void set(SkScalar x, SkScalar y, SkScalar z, SkScalar w = SK_Scalar1) {
    1.98 +        fData[0] = x;
    1.99 +        fData[1] = y;
   1.100 +        fData[2] = z;
   1.101 +        fData[3] = w;
   1.102 +    }
   1.103 +};
   1.104 +
   1.105 +class SK_API SkMatrix44 {
   1.106 +public:
   1.107 +
   1.108 +    enum Uninitialized_Constructor {
   1.109 +        kUninitialized_Constructor
   1.110 +    };
   1.111 +    enum Identity_Constructor {
   1.112 +        kIdentity_Constructor
   1.113 +    };
   1.114 +
   1.115 +    SkMatrix44(Uninitialized_Constructor) { }
   1.116 +    SkMatrix44(Identity_Constructor) { this->setIdentity(); }
   1.117 +
   1.118 +    SK_ATTR_DEPRECATED("use the constructors that take an enum")
   1.119 +    SkMatrix44() { this->setIdentity(); }
   1.120 +
   1.121 +    SkMatrix44(const SkMatrix44& src) {
   1.122 +        memcpy(fMat, src.fMat, sizeof(fMat));
   1.123 +        fTypeMask = src.fTypeMask;
   1.124 +    }
   1.125 +
   1.126 +    SkMatrix44(const SkMatrix44& a, const SkMatrix44& b) {
   1.127 +        this->setConcat(a, b);
   1.128 +    }
   1.129 +
   1.130 +    SkMatrix44& operator=(const SkMatrix44& src) {
   1.131 +        if (&src != this) {
   1.132 +            memcpy(fMat, src.fMat, sizeof(fMat));
   1.133 +            fTypeMask = src.fTypeMask;
   1.134 +        }
   1.135 +        return *this;
   1.136 +    }
   1.137 +
   1.138 +    bool operator==(const SkMatrix44& other) const;
   1.139 +    bool operator!=(const SkMatrix44& other) const {
   1.140 +        return !(other == *this);
   1.141 +    }
   1.142 +
   1.143 +    /* When converting from SkMatrix44 to SkMatrix, the third row and
   1.144 +     * column is dropped.  When converting from SkMatrix to SkMatrix44
   1.145 +     * the third row and column remain as identity:
   1.146 +     * [ a b c ]      [ a b 0 c ]
   1.147 +     * [ d e f ]  ->  [ d e 0 f ]
   1.148 +     * [ g h i ]      [ 0 0 1 0 ]
   1.149 +     *                [ g h 0 i ]
   1.150 +     */
   1.151 +    SkMatrix44(const SkMatrix&);
   1.152 +    SkMatrix44& operator=(const SkMatrix& src);
   1.153 +    operator SkMatrix() const;
   1.154 +
   1.155 +    /**
   1.156 +     *  Return a reference to a const identity matrix
   1.157 +     */
   1.158 +    static const SkMatrix44& I();
   1.159 +
   1.160 +    enum TypeMask {
   1.161 +        kIdentity_Mask      = 0,
   1.162 +        kTranslate_Mask     = 0x01,  //!< set if the matrix has translation
   1.163 +        kScale_Mask         = 0x02,  //!< set if the matrix has any scale != 1
   1.164 +        kAffine_Mask        = 0x04,  //!< set if the matrix skews or rotates
   1.165 +        kPerspective_Mask   = 0x08   //!< set if the matrix is in perspective
   1.166 +    };
   1.167 +
   1.168 +    /**
   1.169 +     *  Returns a bitfield describing the transformations the matrix may
   1.170 +     *  perform. The bitfield is computed conservatively, so it may include
   1.171 +     *  false positives. For example, when kPerspective_Mask is true, all
   1.172 +     *  other bits may be set to true even in the case of a pure perspective
   1.173 +     *  transform.
   1.174 +     */
   1.175 +    inline TypeMask getType() const {
   1.176 +        if (fTypeMask & kUnknown_Mask) {
   1.177 +            fTypeMask = this->computeTypeMask();
   1.178 +        }
   1.179 +        SkASSERT(!(fTypeMask & kUnknown_Mask));
   1.180 +        return (TypeMask)fTypeMask;
   1.181 +    }
   1.182 +
   1.183 +    /**
   1.184 +     *  Return true if the matrix is identity.
   1.185 +     */
   1.186 +    inline bool isIdentity() const {
   1.187 +        return kIdentity_Mask == this->getType();
   1.188 +    }
   1.189 +
   1.190 +    /**
   1.191 +     *  Return true if the matrix contains translate or is identity.
   1.192 +     */
   1.193 +    inline bool isTranslate() const {
   1.194 +        return !(this->getType() & ~kTranslate_Mask);
   1.195 +    }
   1.196 +
   1.197 +    /**
   1.198 +     *  Return true if the matrix only contains scale or translate or is identity.
   1.199 +     */
   1.200 +    inline bool isScaleTranslate() const {
   1.201 +        return !(this->getType() & ~(kScale_Mask | kTranslate_Mask));
   1.202 +    }
   1.203 +
   1.204 +    void setIdentity();
   1.205 +    inline void reset() { this->setIdentity();}
   1.206 +
   1.207 +    /**
   1.208 +     *  get a value from the matrix. The row,col parameters work as follows:
   1.209 +     *  (0, 0)  scale-x
   1.210 +     *  (0, 3)  translate-x
   1.211 +     *  (3, 0)  perspective-x
   1.212 +     */
   1.213 +    inline SkMScalar get(int row, int col) const {
   1.214 +        SkASSERT((unsigned)row <= 3);
   1.215 +        SkASSERT((unsigned)col <= 3);
   1.216 +        return fMat[col][row];
   1.217 +    }
   1.218 +
   1.219 +    /**
   1.220 +     *  set a value in the matrix. The row,col parameters work as follows:
   1.221 +     *  (0, 0)  scale-x
   1.222 +     *  (0, 3)  translate-x
   1.223 +     *  (3, 0)  perspective-x
   1.224 +     */
   1.225 +    inline void set(int row, int col, SkMScalar value) {
   1.226 +        SkASSERT((unsigned)row <= 3);
   1.227 +        SkASSERT((unsigned)col <= 3);
   1.228 +        fMat[col][row] = value;
   1.229 +        this->dirtyTypeMask();
   1.230 +    }
   1.231 +
   1.232 +    inline double getDouble(int row, int col) const {
   1.233 +        return SkMScalarToDouble(this->get(row, col));
   1.234 +    }
   1.235 +    inline void setDouble(int row, int col, double value) {
   1.236 +        this->set(row, col, SkDoubleToMScalar(value));
   1.237 +    }
   1.238 +    inline float getFloat(int row, int col) const {
   1.239 +        return SkMScalarToFloat(this->get(row, col));
   1.240 +    }
   1.241 +    inline void setFloat(int row, int col, float value) {
   1.242 +        this->set(row, col, SkFloatToMScalar(value));
   1.243 +    }
   1.244 +
   1.245 +    /** These methods allow one to efficiently read matrix entries into an
   1.246 +     *  array. The given array must have room for exactly 16 entries. Whenever
   1.247 +     *  possible, they will try to use memcpy rather than an entry-by-entry
   1.248 +     *  copy.
   1.249 +     */
   1.250 +    void asColMajorf(float[]) const;
   1.251 +    void asColMajord(double[]) const;
   1.252 +    void asRowMajorf(float[]) const;
   1.253 +    void asRowMajord(double[]) const;
   1.254 +
   1.255 +    /** These methods allow one to efficiently set all matrix entries from an
   1.256 +     *  array. The given array must have room for exactly 16 entries. Whenever
   1.257 +     *  possible, they will try to use memcpy rather than an entry-by-entry
   1.258 +     *  copy.
   1.259 +     */
   1.260 +    void setColMajorf(const float[]);
   1.261 +    void setColMajord(const double[]);
   1.262 +    void setRowMajorf(const float[]);
   1.263 +    void setRowMajord(const double[]);
   1.264 +
   1.265 +#ifdef SK_MSCALAR_IS_FLOAT
   1.266 +    void setColMajor(const SkMScalar data[]) { this->setColMajorf(data); }
   1.267 +    void setRowMajor(const SkMScalar data[]) { this->setRowMajorf(data); }
   1.268 +#else
   1.269 +    void setColMajor(const SkMScalar data[]) { this->setColMajord(data); }
   1.270 +    void setRowMajor(const SkMScalar data[]) { this->setRowMajord(data); }
   1.271 +#endif
   1.272 +
   1.273 +    /* This sets the top-left of the matrix and clears the translation and
   1.274 +     * perspective components (with [3][3] set to 1). */
   1.275 +    void set3x3(SkMScalar m00, SkMScalar m01, SkMScalar m02,
   1.276 +                SkMScalar m10, SkMScalar m11, SkMScalar m12,
   1.277 +                SkMScalar m20, SkMScalar m21, SkMScalar m22);
   1.278 +
   1.279 +    void setTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz);
   1.280 +    void preTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz);
   1.281 +    void postTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz);
   1.282 +
   1.283 +    void setScale(SkMScalar sx, SkMScalar sy, SkMScalar sz);
   1.284 +    void preScale(SkMScalar sx, SkMScalar sy, SkMScalar sz);
   1.285 +    void postScale(SkMScalar sx, SkMScalar sy, SkMScalar sz);
   1.286 +
   1.287 +    inline void setScale(SkMScalar scale) {
   1.288 +        this->setScale(scale, scale, scale);
   1.289 +    }
   1.290 +    inline void preScale(SkMScalar scale) {
   1.291 +        this->preScale(scale, scale, scale);
   1.292 +    }
   1.293 +    inline void postScale(SkMScalar scale) {
   1.294 +        this->postScale(scale, scale, scale);
   1.295 +    }
   1.296 +
   1.297 +    void setRotateDegreesAbout(SkMScalar x, SkMScalar y, SkMScalar z,
   1.298 +                               SkMScalar degrees) {
   1.299 +        this->setRotateAbout(x, y, z, degrees * SK_MScalarPI / 180);
   1.300 +    }
   1.301 +
   1.302 +    /** Rotate about the vector [x,y,z]. If that vector is not unit-length,
   1.303 +        it will be automatically resized.
   1.304 +     */
   1.305 +    void setRotateAbout(SkMScalar x, SkMScalar y, SkMScalar z,
   1.306 +                        SkMScalar radians);
   1.307 +    /** Rotate about the vector [x,y,z]. Does not check the length of the
   1.308 +        vector, assuming it is unit-length.
   1.309 +     */
   1.310 +    void setRotateAboutUnit(SkMScalar x, SkMScalar y, SkMScalar z,
   1.311 +                            SkMScalar radians);
   1.312 +
   1.313 +    void setConcat(const SkMatrix44& a, const SkMatrix44& b);
   1.314 +    inline void preConcat(const SkMatrix44& m) {
   1.315 +        this->setConcat(*this, m);
   1.316 +    }
   1.317 +    inline void postConcat(const SkMatrix44& m) {
   1.318 +        this->setConcat(m, *this);
   1.319 +    }
   1.320 +
   1.321 +    friend SkMatrix44 operator*(const SkMatrix44& a, const SkMatrix44& b) {
   1.322 +        return SkMatrix44(a, b);
   1.323 +    }
   1.324 +
   1.325 +    /** If this is invertible, return that in inverse and return true. If it is
   1.326 +        not invertible, return false and ignore the inverse parameter.
   1.327 +     */
   1.328 +    bool invert(SkMatrix44* inverse) const;
   1.329 +
   1.330 +    /** Transpose this matrix in place. */
   1.331 +    void transpose();
   1.332 +
   1.333 +    /** Apply the matrix to the src vector, returning the new vector in dst.
   1.334 +        It is legal for src and dst to point to the same memory.
   1.335 +     */
   1.336 +    void mapScalars(const SkScalar src[4], SkScalar dst[4]) const;
   1.337 +    inline void mapScalars(SkScalar vec[4]) const {
   1.338 +        this->mapScalars(vec, vec);
   1.339 +    }
   1.340 +
   1.341 +    SK_ATTR_DEPRECATED("use mapScalars")
   1.342 +    void map(const SkScalar src[4], SkScalar dst[4]) const {
   1.343 +        this->mapScalars(src, dst);
   1.344 +    }
   1.345 +
   1.346 +    SK_ATTR_DEPRECATED("use mapScalars")
   1.347 +    void map(SkScalar vec[4]) const {
   1.348 +        this->mapScalars(vec, vec);
   1.349 +    }
   1.350 +
   1.351 +#ifdef SK_MSCALAR_IS_DOUBLE
   1.352 +    void mapMScalars(const SkMScalar src[4], SkMScalar dst[4]) const;
   1.353 +#elif defined SK_MSCALAR_IS_FLOAT
   1.354 +    inline void mapMScalars(const SkMScalar src[4], SkMScalar dst[4]) const {
   1.355 +        this->mapScalars(src, dst);
   1.356 +    }
   1.357 +#endif
   1.358 +    inline void mapMScalars(SkMScalar vec[4]) const {
   1.359 +        this->mapMScalars(vec, vec);
   1.360 +    }
   1.361 +
   1.362 +    friend SkVector4 operator*(const SkMatrix44& m, const SkVector4& src) {
   1.363 +        SkVector4 dst;
   1.364 +        m.mapScalars(src.fData, dst.fData);
   1.365 +        return dst;
   1.366 +    }
   1.367 +
   1.368 +    /**
   1.369 +     *  map an array of [x, y, 0, 1] through the matrix, returning an array
   1.370 +     *  of [x', y', z', w'].
   1.371 +     *
   1.372 +     *  @param src2     array of [x, y] pairs, with implied z=0 and w=1
   1.373 +     *  @param count    number of [x, y] pairs in src2
   1.374 +     *  @param dst4     array of [x', y', z', w'] quads as the output.
   1.375 +     */
   1.376 +    void map2(const float src2[], int count, float dst4[]) const;
   1.377 +    void map2(const double src2[], int count, double dst4[]) const;
   1.378 +
   1.379 +    void dump() const;
   1.380 +
   1.381 +    double determinant() const;
   1.382 +
   1.383 +private:
   1.384 +    SkMScalar           fMat[4][4];
   1.385 +    mutable unsigned    fTypeMask;
   1.386 +
   1.387 +    enum {
   1.388 +        kUnknown_Mask = 0x80,
   1.389 +
   1.390 +        kAllPublic_Masks = 0xF
   1.391 +    };
   1.392 +
   1.393 +    SkMScalar transX() const { return fMat[3][0]; }
   1.394 +    SkMScalar transY() const { return fMat[3][1]; }
   1.395 +    SkMScalar transZ() const { return fMat[3][2]; }
   1.396 +
   1.397 +    SkMScalar scaleX() const { return fMat[0][0]; }
   1.398 +    SkMScalar scaleY() const { return fMat[1][1]; }
   1.399 +    SkMScalar scaleZ() const { return fMat[2][2]; }
   1.400 +
   1.401 +    SkMScalar perspX() const { return fMat[0][3]; }
   1.402 +    SkMScalar perspY() const { return fMat[1][3]; }
   1.403 +    SkMScalar perspZ() const { return fMat[2][3]; }
   1.404 +
   1.405 +    int computeTypeMask() const;
   1.406 +
   1.407 +    inline void dirtyTypeMask() {
   1.408 +        fTypeMask = kUnknown_Mask;
   1.409 +    }
   1.410 +
   1.411 +    inline void setTypeMask(int mask) {
   1.412 +        SkASSERT(0 == (~(kAllPublic_Masks | kUnknown_Mask) & mask));
   1.413 +        fTypeMask = mask;
   1.414 +    }
   1.415 +
   1.416 +    /**
   1.417 +     *  Does not take the time to 'compute' the typemask. Only returns true if
   1.418 +     *  we already know that this matrix is identity.
   1.419 +     */
   1.420 +    inline bool isTriviallyIdentity() const {
   1.421 +        return 0 == fTypeMask;
   1.422 +    }
   1.423 +};
   1.424 +
   1.425 +#endif

mercurial