Skia
2DGraphicsLibrary
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
SkMatrix44.h
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  static inline float SkFloatToMScalar(float x) {
53  return x;
54  }
55  static inline float SkMScalarToFloat(float x) {
56  return x;
57  }
58  static inline float SkDoubleToMScalar(double x) {
59  return static_cast<float>(x);
60  }
61  static inline double SkMScalarToDouble(float x) {
62  return static_cast<double>(x);
63  }
64  static inline float SkMScalarAbs(float x) {
65  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 
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 
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  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  SkMatrix44(const SkMatrix44& src) {
159  memcpy(fMat, src.fMat, sizeof(fMat));
160  fTypeMask = src.fTypeMask;
161  }
162 
163  SkMatrix44(const SkMatrix44& a, const SkMatrix44& b) {
164  this->setConcat(a, b);
165  }
166 
167  SkMatrix44& operator=(const SkMatrix44& src) {
168  if (&src != this) {
169  memcpy(fMat, src.fMat, sizeof(fMat));
170  fTypeMask = src.fTypeMask;
171  }
172  return *this;
173  }
174 
175  bool operator==(const SkMatrix44& other) const;
176  bool operator!=(const SkMatrix44& other) const {
177  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 
195  static const SkMatrix44& I();
196 
197  enum TypeMask {
198  kIdentity_Mask = 0,
199  kTranslate_Mask = 0x01,
200  kScale_Mask = 0x02,
201  kAffine_Mask = 0x04,
202  kPerspective_Mask = 0x08
203  };
204 
212  inline TypeMask getType() const {
213  if (fTypeMask & kUnknown_Mask) {
214  fTypeMask = this->computeTypeMask();
215  }
216  SkASSERT(!(fTypeMask & kUnknown_Mask));
217  return (TypeMask)fTypeMask;
218  }
219 
223  inline bool isIdentity() const {
224  return kIdentity_Mask == this->getType();
225  }
226 
230  inline bool isTranslate() const {
231  return !(this->getType() & ~kTranslate_Mask);
232  }
233 
237  inline bool isScaleTranslate() const {
238  return !(this->getType() & ~(kScale_Mask | kTranslate_Mask));
239  }
240 
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 
261  inline SkMScalar get(int row, int col) const {
262  SkASSERT((unsigned)row <= 3);
263  SkASSERT((unsigned)col <= 3);
264  return fMat[col][row];
265  }
266 
273  inline void set(int row, int col, SkMScalar value) {
274  SkASSERT((unsigned)row <= 3);
275  SkASSERT((unsigned)col <= 3);
276  fMat[col][row] = value;
277  this->dirtyTypeMask();
278  }
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  inline float getFloat(int row, int col) const {
287  return SkMScalarToFloat(this->get(row, col));
288  }
289  inline void setFloat(int row, int col, float value) {
290  this->set(row, col, SkFloatToMScalar(value));
291  }
292 
302  void asColMajorf(float[]) const;
303  void asColMajord(double[]) const;
304  void asRowMajorf(float[]) const;
305  void asRowMajord(double[]) const;
306 
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 
364  void setRotateAbout(SkMScalar x, SkMScalar y, SkMScalar z,
365  SkMScalar radians);
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 
388  bool invert(SkMatrix44* inverse) const;
389 
391  void transpose();
392 
396  void mapScalars(const SkScalar src[4], SkScalar dst[4]) const;
397  inline void mapScalars(SkScalar vec[4]) const {
398  this->mapScalars(vec, vec);
399  }
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 
436  void map2(const float src2[], int count, float dst4[]) const;
437  void map2(const double src2[], int count, double dst4[]) const;
438 
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  SkMScalar transX() const { return fMat[3][0]; }
470  SkMScalar transY() const { return fMat[3][1]; }
471  SkMScalar transZ() const { return fMat[3][2]; }
472 
473  SkMScalar scaleX() const { return fMat[0][0]; }
474  SkMScalar scaleY() const { return fMat[1][1]; }
475  SkMScalar scaleZ() const { return fMat[2][2]; }
476 
477  SkMScalar perspX() const { return fMat[0][3]; }
478  SkMScalar perspY() const { return fMat[1][3]; }
479  SkMScalar perspZ() const { return fMat[2][3]; }
480 
481  int computeTypeMask() const;
482 
483  inline void dirtyTypeMask() {
484  fTypeMask = kUnknown_Mask;
485  }
486 
487  inline void setTypeMask(int mask) {
488  SkASSERT(0 == (~(kAllPublic_Masks | kUnknown_Mask) & mask));
489  fTypeMask = mask;
490  }
491 
496  inline bool isTriviallyIdentity() const {
497  return 0 == fTypeMask;
498  }
499 
500  inline const SkMScalar* values() const { return &fMat[0][0]; }
501 
502  friend class SkColorSpace;
503  friend class SkColorSpace_XYZ;
504 };
505 
506 #endif
bool isScale() const
Returns true if the matrix only contains scale or is identity.
Definition: SkMatrix44.h:244
void mapScalars(const SkScalar src[4], SkScalar dst[4]) const
Apply the matrix to the src vector, returning the new vector in dst.
Definition: SkColorSpace.h:59
TypeMask getType() const
Returns a bitfield describing the transformations the matrix may perform.
Definition: SkMatrix44.h:212
Definition: SkMatrix44.h:88
bool isTranslate() const
Return true if the matrix contains translate or is identity.
Definition: SkMatrix44.h:230
The SkMatrix44 class holds a 4x4 matrix.
Definition: SkMatrix44.h:135
bool isIdentity() const
Return true if the matrix is identity.
Definition: SkMatrix44.h:223
The SkMatrix class holds a 3x3 matrix for transforming coordinates.
Definition: SkMatrix.h:28
#define SkToBool(cond)
Returns 0 or 1 based on the condition.
Definition: SkTypes.h:227
bool isTriviallyIdentity() const
Does not take the time to 'compute' the typemask.
Definition: SkMatrix44.h:496
bool isScaleTranslate() const
Return true if the matrix only contains scale or translate or is identity.
Definition: SkMatrix44.h:237
TypeMask
Definition: SkMatrix44.h:197
void set(int row, int col, SkMScalar value)
set a value in the matrix.
Definition: SkMatrix44.h:273