LCOV - code coverage report
Current view: top level - gfx/skia/skia/include/core - SkMatrix44.h (source / functions) Hit Total Coverage
Test: output.info Lines: 21 73 28.8 %
Date: 2017-07-14 16:53:18 Functions: 12 32 37.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2011 Google Inc.
       3             :  *
       4             :  * Use of this source code is governed by a BSD-style license that can be
       5             :  * found in the LICENSE file.
       6             :  */
       7             : 
       8             : #ifndef SkMatrix44_DEFINED
       9             : #define SkMatrix44_DEFINED
      10             : 
      11             : #include "SkMatrix.h"
      12             : #include "SkScalar.h"
      13             : 
      14             : #ifdef SK_MSCALAR_IS_DOUBLE
      15             : #ifdef SK_MSCALAR_IS_FLOAT
      16             :     #error "can't define MSCALAR both as DOUBLE and FLOAT"
      17             : #endif
      18             :     typedef double SkMScalar;
      19             : 
      20             :     static inline double SkFloatToMScalar(float x) {
      21             :         return static_cast<double>(x);
      22             :     }
      23             :     static inline float SkMScalarToFloat(double x) {
      24             :         return static_cast<float>(x);
      25             :     }
      26             :     static inline double SkDoubleToMScalar(double x) {
      27             :         return x;
      28             :     }
      29             :     static inline double SkMScalarToDouble(double x) {
      30             :         return x;
      31             :     }
      32             :     static inline double SkMScalarAbs(double x) {
      33             :         return fabs(x);
      34             :     }
      35             :     static const SkMScalar SK_MScalarPI = 3.141592653589793;
      36             : 
      37             :     #define SkMScalarFloor(x)           sk_double_floor(x)
      38             :     #define SkMScalarCeil(x)            sk_double_ceil(x)
      39             :     #define SkMScalarRound(x)           sk_double_round(x)
      40             : 
      41             :     #define SkMScalarFloorToInt(x)      sk_double_floor2int(x)
      42             :     #define SkMScalarCeilToInt(x)       sk_double_ceil2int(x)
      43             :     #define SkMScalarRoundToInt(x)      sk_double_round2int(x)
      44             : 
      45             : 
      46             : #elif defined SK_MSCALAR_IS_FLOAT
      47             : #ifdef SK_MSCALAR_IS_DOUBLE
      48             :     #error "can't define MSCALAR both as DOUBLE and FLOAT"
      49             : #endif
      50             :     typedef float SkMScalar;
      51             : 
      52           0 :     static inline float SkFloatToMScalar(float x) {
      53           0 :         return x;
      54             :     }
      55           0 :     static inline float SkMScalarToFloat(float x) {
      56           0 :         return x;
      57             :     }
      58           0 :     static inline float SkDoubleToMScalar(double x) {
      59           0 :         return static_cast<float>(x);
      60             :     }
      61           0 :     static inline double SkMScalarToDouble(float x) {
      62           0 :         return static_cast<double>(x);
      63             :     }
      64           0 :     static inline float SkMScalarAbs(float x) {
      65           0 :         return sk_float_abs(x);
      66             :     }
      67             :     static const SkMScalar SK_MScalarPI = 3.14159265f;
      68             : 
      69             :     #define SkMScalarFloor(x)           sk_float_floor(x)
      70             :     #define SkMScalarCeil(x)            sk_float_ceil(x)
      71             :     #define SkMScalarRound(x)           sk_float_round(x)
      72             : 
      73             :     #define SkMScalarFloorToInt(x)      sk_float_floor2int(x)
      74             :     #define SkMScalarCeilToInt(x)       sk_float_ceil2int(x)
      75             :     #define SkMScalarRoundToInt(x)      sk_float_round2int(x)
      76             : 
      77             : #endif
      78             : 
      79             : #define SkIntToMScalar(n)       static_cast<SkMScalar>(n)
      80             : 
      81             : #define SkMScalarToScalar(x)    SkMScalarToFloat(x)
      82             : #define SkScalarToMScalar(x)    SkFloatToMScalar(x)
      83             : 
      84             : static const SkMScalar SK_MScalar1 = 1;
      85             : 
      86             : ///////////////////////////////////////////////////////////////////////////////
      87             : 
      88             : struct SkVector4 {
      89             :     SkScalar fData[4];
      90             : 
      91             :     SkVector4() {
      92             :         this->set(0, 0, 0, 1);
      93             :     }
      94             :     SkVector4(const SkVector4& src) {
      95             :         memcpy(fData, src.fData, sizeof(fData));
      96             :     }
      97             :     SkVector4(SkScalar x, SkScalar y, SkScalar z, SkScalar w = SK_Scalar1) {
      98             :         fData[0] = x;
      99             :         fData[1] = y;
     100             :         fData[2] = z;
     101             :         fData[3] = w;
     102             :     }
     103             : 
     104             :     SkVector4& operator=(const SkVector4& src) {
     105             :         memcpy(fData, src.fData, sizeof(fData));
     106             :         return *this;
     107             :     }
     108             : 
     109             :     bool operator==(const SkVector4& v) {
     110             :         return fData[0] == v.fData[0] && fData[1] == v.fData[1] &&
     111             :                fData[2] == v.fData[2] && fData[3] == v.fData[3];
     112             :     }
     113             :     bool operator!=(const SkVector4& v) {
     114             :         return !(*this == v);
     115             :     }
     116             :     bool equals(SkScalar x, SkScalar y, SkScalar z, SkScalar w = SK_Scalar1) {
     117             :         return fData[0] == x && fData[1] == y &&
     118             :                fData[2] == z && fData[3] == w;
     119             :     }
     120             : 
     121             :     void set(SkScalar x, SkScalar y, SkScalar z, SkScalar w = SK_Scalar1) {
     122             :         fData[0] = x;
     123             :         fData[1] = y;
     124             :         fData[2] = z;
     125             :         fData[3] = w;
     126             :     }
     127             : };
     128             : 
     129             : /** \class SkMatrix44
     130             : 
     131             :     The SkMatrix44 class holds a 4x4 matrix.
     132             : 
     133             :     SkMatrix44 is not thread safe unless you've first called SkMatrix44::getType().
     134             : */
     135             : class SK_API SkMatrix44 {
     136             : public:
     137             : 
     138             :     enum Uninitialized_Constructor {
     139             :         kUninitialized_Constructor
     140             :     };
     141             :     enum Identity_Constructor {
     142             :         kIdentity_Constructor
     143             :     };
     144             : 
     145           2 :     SkMatrix44(Uninitialized_Constructor) {}
     146             : 
     147             :     constexpr SkMatrix44(Identity_Constructor)
     148             :         : fMat{{ 1, 0, 0, 0, },
     149             :                { 0, 1, 0, 0, },
     150             :                { 0, 0, 1, 0, },
     151             :                { 0, 0, 0, 1, }}
     152             :         , fTypeMask(kIdentity_Mask)
     153             :     {}
     154             : 
     155             :     SK_ATTR_DEPRECATED("use the constructors that take an enum")
     156             :     SkMatrix44() { this->setIdentity(); }
     157             : 
     158           1 :     SkMatrix44(const SkMatrix44& src) {
     159           1 :         memcpy(fMat, src.fMat, sizeof(fMat));
     160           1 :         fTypeMask = src.fTypeMask;
     161           1 :     }
     162             : 
     163           0 :     SkMatrix44(const SkMatrix44& a, const SkMatrix44& b) {
     164           0 :         this->setConcat(a, b);
     165           0 :     }
     166             : 
     167           0 :     SkMatrix44& operator=(const SkMatrix44& src) {
     168           0 :         if (&src != this) {
     169           0 :             memcpy(fMat, src.fMat, sizeof(fMat));
     170           0 :             fTypeMask = src.fTypeMask;
     171             :         }
     172           0 :         return *this;
     173             :     }
     174             : 
     175             :     bool operator==(const SkMatrix44& other) const;
     176           0 :     bool operator!=(const SkMatrix44& other) const {
     177           0 :         return !(other == *this);
     178             :     }
     179             : 
     180             :     /* When converting from SkMatrix44 to SkMatrix, the third row and
     181             :      * column is dropped.  When converting from SkMatrix to SkMatrix44
     182             :      * the third row and column remain as identity:
     183             :      * [ a b c ]      [ a b 0 c ]
     184             :      * [ d e f ]  ->  [ d e 0 f ]
     185             :      * [ g h i ]      [ 0 0 1 0 ]
     186             :      *                [ g h 0 i ]
     187             :      */
     188             :     SkMatrix44(const SkMatrix&);
     189             :     SkMatrix44& operator=(const SkMatrix& src);
     190             :     operator SkMatrix() const;
     191             : 
     192             :     /**
     193             :      *  Return a reference to a const identity matrix
     194             :      */
     195             :     static const SkMatrix44& I();
     196             : 
     197             :     enum TypeMask {
     198             :         kIdentity_Mask      = 0,
     199             :         kTranslate_Mask     = 0x01,  //!< set if the matrix has translation
     200             :         kScale_Mask         = 0x02,  //!< set if the matrix has any scale != 1
     201             :         kAffine_Mask        = 0x04,  //!< set if the matrix skews or rotates
     202             :         kPerspective_Mask   = 0x08   //!< set if the matrix is in perspective
     203             :     };
     204             : 
     205             :     /**
     206             :      *  Returns a bitfield describing the transformations the matrix may
     207             :      *  perform. The bitfield is computed conservatively, so it may include
     208             :      *  false positives. For example, when kPerspective_Mask is true, all
     209             :      *  other bits may be set to true even in the case of a pure perspective
     210             :      *  transform.
     211             :      */
     212           1 :     inline TypeMask getType() const {
     213           1 :         if (fTypeMask & kUnknown_Mask) {
     214           1 :             fTypeMask = this->computeTypeMask();
     215             :         }
     216           1 :         SkASSERT(!(fTypeMask & kUnknown_Mask));
     217           1 :         return (TypeMask)fTypeMask;
     218             :     }
     219             : 
     220             :     /**
     221             :      *  Return true if the matrix is identity.
     222             :      */
     223           0 :     inline bool isIdentity() const {
     224           0 :         return kIdentity_Mask == this->getType();
     225             :     }
     226             : 
     227             :     /**
     228             :      *  Return true if the matrix contains translate or is identity.
     229             :      */
     230           0 :     inline bool isTranslate() const {
     231           0 :         return !(this->getType() & ~kTranslate_Mask);
     232             :     }
     233             : 
     234             :     /**
     235             :      *  Return true if the matrix only contains scale or translate or is identity.
     236             :      */
     237           0 :     inline bool isScaleTranslate() const {
     238           0 :         return !(this->getType() & ~(kScale_Mask | kTranslate_Mask));
     239             :     }
     240             : 
     241             :     /**
     242             :      *  Returns true if the matrix only contains scale or is identity.
     243             :      */
     244             :     inline bool isScale() const {
     245             :             return !(this->getType() & ~kScale_Mask);
     246             :     }
     247             : 
     248             :     inline bool hasPerspective() const {
     249             :         return SkToBool(this->getType() & kPerspective_Mask);
     250             :     }
     251             : 
     252             :     void setIdentity();
     253             :     inline void reset() { this->setIdentity();}
     254             : 
     255             :     /**
     256             :      *  get a value from the matrix. The row,col parameters work as follows:
     257             :      *  (0, 0)  scale-x
     258             :      *  (0, 3)  translate-x
     259             :      *  (3, 0)  perspective-x
     260             :      */
     261           0 :     inline SkMScalar get(int row, int col) const {
     262           0 :         SkASSERT((unsigned)row <= 3);
     263           0 :         SkASSERT((unsigned)col <= 3);
     264           0 :         return fMat[col][row];
     265             :     }
     266             : 
     267             :     /**
     268             :      *  set a value in the matrix. The row,col parameters work as follows:
     269             :      *  (0, 0)  scale-x
     270             :      *  (0, 3)  translate-x
     271             :      *  (3, 0)  perspective-x
     272             :      */
     273           0 :     inline void set(int row, int col, SkMScalar value) {
     274           0 :         SkASSERT((unsigned)row <= 3);
     275           0 :         SkASSERT((unsigned)col <= 3);
     276           0 :         fMat[col][row] = value;
     277           0 :         this->dirtyTypeMask();
     278           0 :     }
     279             : 
     280             :     inline double getDouble(int row, int col) const {
     281             :         return SkMScalarToDouble(this->get(row, col));
     282             :     }
     283             :     inline void setDouble(int row, int col, double value) {
     284             :         this->set(row, col, SkDoubleToMScalar(value));
     285             :     }
     286           0 :     inline float getFloat(int row, int col) const {
     287           0 :         return SkMScalarToFloat(this->get(row, col));
     288             :     }
     289           0 :     inline void setFloat(int row, int col, float value) {
     290           0 :         this->set(row, col, SkFloatToMScalar(value));
     291           0 :     }
     292             : 
     293             :     /** These methods allow one to efficiently read matrix entries into an
     294             :      *  array. The given array must have room for exactly 16 entries. Whenever
     295             :      *  possible, they will try to use memcpy rather than an entry-by-entry
     296             :      *  copy.
     297             :      *
     298             :      *  Col major indicates that consecutive elements of columns will be stored
     299             :      *  contiguously in memory.  Row major indicates that consecutive elements
     300             :      *  of rows will be stored contiguously in memory.
     301             :      */
     302             :     void asColMajorf(float[]) const;
     303             :     void asColMajord(double[]) const;
     304             :     void asRowMajorf(float[]) const;
     305             :     void asRowMajord(double[]) const;
     306             : 
     307             :     /** These methods allow one to efficiently set all matrix entries from an
     308             :      *  array. The given array must have room for exactly 16 entries. Whenever
     309             :      *  possible, they will try to use memcpy rather than an entry-by-entry
     310             :      *  copy.
     311             :      *
     312             :      *  Col major indicates that input memory will be treated as if consecutive
     313             :      *  elements of columns are stored contiguously in memory.  Row major
     314             :      *  indicates that input memory will be treated as if consecutive elements
     315             :      *  of rows are stored contiguously in memory.
     316             :      */
     317             :     void setColMajorf(const float[]);
     318             :     void setColMajord(const double[]);
     319             :     void setRowMajorf(const float[]);
     320             :     void setRowMajord(const double[]);
     321             : 
     322             : #ifdef SK_MSCALAR_IS_FLOAT
     323             :     void setColMajor(const SkMScalar data[]) { this->setColMajorf(data); }
     324             :     void setRowMajor(const SkMScalar data[]) { this->setRowMajorf(data); }
     325             : #else
     326             :     void setColMajor(const SkMScalar data[]) { this->setColMajord(data); }
     327             :     void setRowMajor(const SkMScalar data[]) { this->setRowMajord(data); }
     328             : #endif
     329             : 
     330             :     /* This sets the top-left of the matrix and clears the translation and
     331             :      * perspective components (with [3][3] set to 1).  mXY is interpreted
     332             :      * as the matrix entry at col = X, row = Y. */
     333             :     void set3x3(SkMScalar m00, SkMScalar m01, SkMScalar m02,
     334             :                 SkMScalar m10, SkMScalar m11, SkMScalar m12,
     335             :                 SkMScalar m20, SkMScalar m21, SkMScalar m22);
     336             :     void set3x3RowMajorf(const float[]);
     337             : 
     338             :     void setTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz);
     339             :     void preTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz);
     340             :     void postTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz);
     341             : 
     342             :     void setScale(SkMScalar sx, SkMScalar sy, SkMScalar sz);
     343             :     void preScale(SkMScalar sx, SkMScalar sy, SkMScalar sz);
     344             :     void postScale(SkMScalar sx, SkMScalar sy, SkMScalar sz);
     345             : 
     346             :     inline void setScale(SkMScalar scale) {
     347             :         this->setScale(scale, scale, scale);
     348             :     }
     349             :     inline void preScale(SkMScalar scale) {
     350             :         this->preScale(scale, scale, scale);
     351             :     }
     352             :     inline void postScale(SkMScalar scale) {
     353             :         this->postScale(scale, scale, scale);
     354             :     }
     355             : 
     356             :     void setRotateDegreesAbout(SkMScalar x, SkMScalar y, SkMScalar z,
     357             :                                SkMScalar degrees) {
     358             :         this->setRotateAbout(x, y, z, degrees * SK_MScalarPI / 180);
     359             :     }
     360             : 
     361             :     /** Rotate about the vector [x,y,z]. If that vector is not unit-length,
     362             :         it will be automatically resized.
     363             :      */
     364             :     void setRotateAbout(SkMScalar x, SkMScalar y, SkMScalar z,
     365             :                         SkMScalar radians);
     366             :     /** Rotate about the vector [x,y,z]. Does not check the length of the
     367             :         vector, assuming it is unit-length.
     368             :      */
     369             :     void setRotateAboutUnit(SkMScalar x, SkMScalar y, SkMScalar z,
     370             :                             SkMScalar radians);
     371             : 
     372             :     void setConcat(const SkMatrix44& a, const SkMatrix44& b);
     373             :     inline void preConcat(const SkMatrix44& m) {
     374             :         this->setConcat(*this, m);
     375             :     }
     376             :     inline void postConcat(const SkMatrix44& m) {
     377             :         this->setConcat(m, *this);
     378             :     }
     379             : 
     380             :     friend SkMatrix44 operator*(const SkMatrix44& a, const SkMatrix44& b) {
     381             :         return SkMatrix44(a, b);
     382             :     }
     383             : 
     384             :     /** If this is invertible, return that in inverse and return true. If it is
     385             :         not invertible, return false and leave the inverse parameter in an
     386             :         unspecified state.
     387             :      */
     388             :     bool invert(SkMatrix44* inverse) const;
     389             : 
     390             :     /** Transpose this matrix in place. */
     391             :     void transpose();
     392             : 
     393             :     /** Apply the matrix to the src vector, returning the new vector in dst.
     394             :         It is legal for src and dst to point to the same memory.
     395             :      */
     396             :     void mapScalars(const SkScalar src[4], SkScalar dst[4]) const;
     397           0 :     inline void mapScalars(SkScalar vec[4]) const {
     398           0 :         this->mapScalars(vec, vec);
     399           0 :     }
     400             : 
     401             :     SK_ATTR_DEPRECATED("use mapScalars")
     402             :     void map(const SkScalar src[4], SkScalar dst[4]) const {
     403             :         this->mapScalars(src, dst);
     404             :     }
     405             : 
     406             :     SK_ATTR_DEPRECATED("use mapScalars")
     407             :     void map(SkScalar vec[4]) const {
     408             :         this->mapScalars(vec, vec);
     409             :     }
     410             : 
     411             : #ifdef SK_MSCALAR_IS_DOUBLE
     412             :     void mapMScalars(const SkMScalar src[4], SkMScalar dst[4]) const;
     413             : #elif defined SK_MSCALAR_IS_FLOAT
     414             :     inline void mapMScalars(const SkMScalar src[4], SkMScalar dst[4]) const {
     415             :         this->mapScalars(src, dst);
     416             :     }
     417             : #endif
     418             :     inline void mapMScalars(SkMScalar vec[4]) const {
     419             :         this->mapMScalars(vec, vec);
     420             :     }
     421             : 
     422             :     friend SkVector4 operator*(const SkMatrix44& m, const SkVector4& src) {
     423             :         SkVector4 dst;
     424             :         m.mapScalars(src.fData, dst.fData);
     425             :         return dst;
     426             :     }
     427             : 
     428             :     /**
     429             :      *  map an array of [x, y, 0, 1] through the matrix, returning an array
     430             :      *  of [x', y', z', w'].
     431             :      *
     432             :      *  @param src2     array of [x, y] pairs, with implied z=0 and w=1
     433             :      *  @param count    number of [x, y] pairs in src2
     434             :      *  @param dst4     array of [x', y', z', w'] quads as the output.
     435             :      */
     436             :     void map2(const float src2[], int count, float dst4[]) const;
     437             :     void map2(const double src2[], int count, double dst4[]) const;
     438             : 
     439             :     /** Returns true if transformating an axis-aligned square in 2d by this matrix
     440             :         will produce another 2d axis-aligned square; typically means the matrix
     441             :         is a scale with perhaps a 90-degree rotation. A 3d rotation through 90
     442             :         degrees into a perpendicular plane collapses a square to a line, but
     443             :         is still considered to be axis-aligned.
     444             : 
     445             :         By default, tolerates very slight error due to float imprecisions;
     446             :         a 90-degree rotation can still end up with 10^-17 of
     447             :         "non-axis-aligned" result.
     448             :      */
     449             :     bool preserves2dAxisAlignment(SkMScalar epsilon = SK_ScalarNearlyZero) const;
     450             : 
     451             :     void dump() const;
     452             : 
     453             :     double determinant() const;
     454             : 
     455             : private:
     456             :     /* This is indexed by [col][row]. */
     457             :     SkMScalar           fMat[4][4];
     458             :     mutable unsigned    fTypeMask;
     459             : 
     460             :     enum {
     461             :         kUnknown_Mask = 0x80,
     462             : 
     463             :         kAllPublic_Masks = 0xF
     464             :     };
     465             : 
     466             :     void as3x4RowMajorf(float[]) const;
     467             :     void set3x4RowMajorf(const float[]);
     468             : 
     469           1 :     SkMScalar transX() const { return fMat[3][0]; }
     470           1 :     SkMScalar transY() const { return fMat[3][1]; }
     471           1 :     SkMScalar transZ() const { return fMat[3][2]; }
     472             : 
     473           1 :     SkMScalar scaleX() const { return fMat[0][0]; }
     474           0 :     SkMScalar scaleY() const { return fMat[1][1]; }
     475           0 :     SkMScalar scaleZ() const { return fMat[2][2]; }
     476             : 
     477           1 :     SkMScalar perspX() const { return fMat[0][3]; }
     478           1 :     SkMScalar perspY() const { return fMat[1][3]; }
     479           1 :     SkMScalar perspZ() const { return fMat[2][3]; }
     480             : 
     481             :     int computeTypeMask() const;
     482             : 
     483           1 :     inline void dirtyTypeMask() {
     484           1 :         fTypeMask = kUnknown_Mask;
     485           1 :     }
     486             : 
     487           0 :     inline void setTypeMask(int mask) {
     488           0 :         SkASSERT(0 == (~(kAllPublic_Masks | kUnknown_Mask) & mask));
     489           0 :         fTypeMask = mask;
     490           0 :     }
     491             : 
     492             :     /**
     493             :      *  Does not take the time to 'compute' the typemask. Only returns true if
     494             :      *  we already know that this matrix is identity.
     495             :      */
     496           0 :     inline bool isTriviallyIdentity() const {
     497           0 :         return 0 == fTypeMask;
     498             :     }
     499             : 
     500           1 :     inline const SkMScalar* values() const { return &fMat[0][0]; }
     501             : 
     502             :     friend class SkColorSpace;
     503             :     friend class SkColorSpace_XYZ;
     504             : };
     505             : 
     506             : #endif

Generated by: LCOV version 1.13