/* * Copyright 2011 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef SkMatrix44_DEFINED #define SkMatrix44_DEFINED #include "SkMatrix.h" #include "SkScalar.h" #ifdef SK_MSCALAR_IS_DOUBLE typedef double SkMScalar; static inline double SkFloatToMScalar(float x) { return static_cast<double>(x); } static inline float SkMScalarToFloat(double x) { return static_cast<float>(x); } static inline double SkDoubleToMScalar(double x) { return x; } static inline double SkMScalarToDouble(double x) { return x; } static const SkMScalar SK_MScalarPI = 3.141592653589793; #else typedef float SkMScalar; static inline float SkFloatToMScalar(float x) { return x; } static inline float SkMScalarToFloat(float x) { return x; } static inline float SkDoubleToMScalar(double x) { return static_cast<float>(x); } static inline double SkMScalarToDouble(float x) { return static_cast<double>(x); } static const SkMScalar SK_MScalarPI = 3.14159265f; #endif #ifdef SK_SCALAR_IS_FLOAT #define SkMScalarToScalar SkMScalarToFloat #define SkScalarToMScalar SkFloatToMScalar #else #if SK_MSCALAR_IS_DOUBLE // we don't have fixed <-> double macros, use double<->scalar macros #define SkMScalarToScalar SkDoubleToScalar #define SkScalarToMScalar SkScalarToDouble #else #define SkMScalarToScalar SkFloatToFixed #define SkScalarToMScalar SkFixedToFloat #endif #endif static const SkMScalar SK_MScalar1 = 1; /////////////////////////////////////////////////////////////////////////////// struct SkVector4 { SkScalar fData[4]; SkVector4() { this->set(0, 0, 0, 1); } SkVector4(const SkVector4& src) { memcpy(fData, src.fData, sizeof(fData)); } SkVector4(SkScalar x, SkScalar y, SkScalar z, SkScalar w = SK_Scalar1) { fData[0] = x; fData[1] = y; fData[2] = z; fData[3] = w; } SkVector4& operator=(const SkVector4& src) { memcpy(fData, src.fData, sizeof(fData)); return *this; } bool operator==(const SkVector4& v) { return fData[0] == v.fData[0] && fData[1] == v.fData[1] && fData[2] == v.fData[2] && fData[3] == v.fData[3]; } bool operator!=(const SkVector4& v) { return !(*this == v); } bool equals(SkScalar x, SkScalar y, SkScalar z, SkScalar w = SK_Scalar1) { return fData[0] == x && fData[1] == y && fData[2] == z && fData[3] == w; } void set(SkScalar x, SkScalar y, SkScalar z, SkScalar w = SK_Scalar1) { fData[0] = x; fData[1] = y; fData[2] = z; fData[3] = w; } }; class SK_API SkMatrix44 { public: SkMatrix44(); SkMatrix44(const SkMatrix44&); SkMatrix44(const SkMatrix44& a, const SkMatrix44& b); SkMatrix44& operator=(const SkMatrix44& src) { memcpy(this, &src, sizeof(*this)); return *this; } bool operator==(const SkMatrix44& other) const { return !memcmp(this, &other, sizeof(*this)); } bool operator!=(const SkMatrix44& other) const { return !!memcmp(this, &other, sizeof(*this)); } SkMatrix44(const SkMatrix&); SkMatrix44& operator=(const SkMatrix& src); operator SkMatrix() const; SkMScalar get(int row, int col) const; void set(int row, int col, const SkMScalar& value); void asColMajorf(float[]) const; void asColMajord(double[]) const; void asRowMajorf(float[]) const; void asRowMajord(double[]) const; bool isIdentity() const; void setIdentity(); void reset() { this->setIdentity();} void set3x3(SkMScalar m00, SkMScalar m01, SkMScalar m02, SkMScalar m10, SkMScalar m11, SkMScalar m12, SkMScalar m20, SkMScalar m21, SkMScalar m22); void setTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz); void preTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz); void postTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz); void setScale(SkMScalar sx, SkMScalar sy, SkMScalar sz); void preScale(SkMScalar sx, SkMScalar sy, SkMScalar sz); void postScale(SkMScalar sx, SkMScalar sy, SkMScalar sz); void setScale(SkMScalar scale) { this->setScale(scale, scale, scale); } void preScale(SkMScalar scale) { this->preScale(scale, scale, scale); } void postScale(SkMScalar scale) { this->postScale(scale, scale, scale); } void setRotateDegreesAbout(SkMScalar x, SkMScalar y, SkMScalar z, SkMScalar degrees) { this->setRotateAbout(x, y, z, degrees * SK_MScalarPI / 180); } /** Rotate about the vector [x,y,z]. If that vector is not unit-length, it will be automatically resized. */ void setRotateAbout(SkMScalar x, SkMScalar y, SkMScalar z, SkMScalar radians); /** Rotate about the vector [x,y,z]. Does not check the length of the vector, assuming it is unit-length. */ void setRotateAboutUnit(SkMScalar x, SkMScalar y, SkMScalar z, SkMScalar radians); void setConcat(const SkMatrix44& a, const SkMatrix44& b); void preConcat(const SkMatrix44& m) { this->setConcat(*this, m); } void postConcat(const SkMatrix44& m) { this->setConcat(m, *this); } friend SkMatrix44 operator*(const SkMatrix44& a, const SkMatrix44& b) { return SkMatrix44(a, b); } /** If this is invertible, return that in inverse and return true. If it is not invertible, return false and ignore the inverse parameter. */ bool invert(SkMatrix44* inverse) const; /** Apply the matrix to the src vector, returning the new vector in dst. It is legal for src and dst to point to the same memory. */ void map(const SkScalar src[4], SkScalar dst[4]) const; void map(SkScalar vec[4]) const { this->map(vec, vec); } friend SkVector4 operator*(const SkMatrix44& m, const SkVector4& src) { SkVector4 dst; m.map(src.fData, dst.fData); return dst; } void dump() const; private: /* Stored in the same order as opengl: [3][0] = tx [3][1] = ty [3][2] = tz */ SkMScalar fMat[4][4]; double determinant() const; }; #endif