Skia
2DGraphicsLibrary
 All Classes 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 
129 class SK_API SkMatrix44 {
130 public:
131 
132  enum Uninitialized_Constructor {
133  kUninitialized_Constructor
134  };
135  enum Identity_Constructor {
136  kIdentity_Constructor
137  };
138 
139  SkMatrix44(Uninitialized_Constructor) {}
140 
141  constexpr SkMatrix44(Identity_Constructor)
142  : fMat{{ 1, 0, 0, 0, },
143  { 0, 1, 0, 0, },
144  { 0, 0, 1, 0, },
145  { 0, 0, 0, 1, }}
146  , fTypeMask(kIdentity_Mask)
147  {}
148 
149  SK_ATTR_DEPRECATED("use the constructors that take an enum")
150  SkMatrix44() { this->setIdentity(); }
151 
152  SkMatrix44(const SkMatrix44& src) {
153  memcpy(fMat, src.fMat, sizeof(fMat));
154  fTypeMask = src.fTypeMask;
155  }
156 
157  SkMatrix44(const SkMatrix44& a, const SkMatrix44& b) {
158  this->setConcat(a, b);
159  }
160 
161  SkMatrix44& operator=(const SkMatrix44& src) {
162  if (&src != this) {
163  memcpy(fMat, src.fMat, sizeof(fMat));
164  fTypeMask = src.fTypeMask;
165  }
166  return *this;
167  }
168 
169  bool operator==(const SkMatrix44& other) const;
170  bool operator!=(const SkMatrix44& other) const {
171  return !(other == *this);
172  }
173 
174  /* When converting from SkMatrix44 to SkMatrix, the third row and
175  * column is dropped. When converting from SkMatrix to SkMatrix44
176  * the third row and column remain as identity:
177  * [ a b c ] [ a b 0 c ]
178  * [ d e f ] -> [ d e 0 f ]
179  * [ g h i ] [ 0 0 1 0 ]
180  * [ g h 0 i ]
181  */
182  SkMatrix44(const SkMatrix&);
183  SkMatrix44& operator=(const SkMatrix& src);
184  operator SkMatrix() const;
185 
189  static const SkMatrix44& I();
190 
191  enum TypeMask {
192  kIdentity_Mask = 0,
193  kTranslate_Mask = 0x01,
194  kScale_Mask = 0x02,
195  kAffine_Mask = 0x04,
196  kPerspective_Mask = 0x08
197  };
198 
206  inline TypeMask getType() const {
207  if (fTypeMask & kUnknown_Mask) {
208  fTypeMask = this->computeTypeMask();
209  }
210  SkASSERT(!(fTypeMask & kUnknown_Mask));
211  return (TypeMask)fTypeMask;
212  }
213 
217  inline bool isIdentity() const {
218  return kIdentity_Mask == this->getType();
219  }
220 
224  inline bool isTranslate() const {
225  return !(this->getType() & ~kTranslate_Mask);
226  }
227 
231  inline bool isScaleTranslate() const {
232  return !(this->getType() & ~(kScale_Mask | kTranslate_Mask));
233  }
234 
238  inline bool isScale() const {
239  return !(this->getType() & ~kScale_Mask);
240  }
241 
242  inline bool hasPerspective() const {
243  return SkToBool(this->getType() & kPerspective_Mask);
244  }
245 
246  void setIdentity();
247  inline void reset() { this->setIdentity();}
248 
255  inline SkMScalar get(int row, int col) const {
256  SkASSERT((unsigned)row <= 3);
257  SkASSERT((unsigned)col <= 3);
258  return fMat[col][row];
259  }
260 
267  inline void set(int row, int col, SkMScalar value) {
268  SkASSERT((unsigned)row <= 3);
269  SkASSERT((unsigned)col <= 3);
270  fMat[col][row] = value;
271  this->dirtyTypeMask();
272  }
273 
274  inline double getDouble(int row, int col) const {
275  return SkMScalarToDouble(this->get(row, col));
276  }
277  inline void setDouble(int row, int col, double value) {
278  this->set(row, col, SkDoubleToMScalar(value));
279  }
280  inline float getFloat(int row, int col) const {
281  return SkMScalarToFloat(this->get(row, col));
282  }
283  inline void setFloat(int row, int col, float value) {
284  this->set(row, col, SkFloatToMScalar(value));
285  }
286 
296  void asColMajorf(float[]) const;
297  void asColMajord(double[]) const;
298  void asRowMajorf(float[]) const;
299  void asRowMajord(double[]) const;
300 
311  void setColMajorf(const float[]);
312  void setColMajord(const double[]);
313  void setRowMajorf(const float[]);
314  void setRowMajord(const double[]);
315 
316 #ifdef SK_MSCALAR_IS_FLOAT
317  void setColMajor(const SkMScalar data[]) { this->setColMajorf(data); }
318  void setRowMajor(const SkMScalar data[]) { this->setRowMajorf(data); }
319 #else
320  void setColMajor(const SkMScalar data[]) { this->setColMajord(data); }
321  void setRowMajor(const SkMScalar data[]) { this->setRowMajord(data); }
322 #endif
323 
324  /* This sets the top-left of the matrix and clears the translation and
325  * perspective components (with [3][3] set to 1). mXY is interpreted
326  * as the matrix entry at col = X, row = Y. */
327  void set3x3(SkMScalar m00, SkMScalar m01, SkMScalar m02,
328  SkMScalar m10, SkMScalar m11, SkMScalar m12,
329  SkMScalar m20, SkMScalar m21, SkMScalar m22);
330  void set3x3RowMajorf(const float[]);
331 
332  void setTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz);
333  void preTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz);
334  void postTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz);
335 
336  void setScale(SkMScalar sx, SkMScalar sy, SkMScalar sz);
337  void preScale(SkMScalar sx, SkMScalar sy, SkMScalar sz);
338  void postScale(SkMScalar sx, SkMScalar sy, SkMScalar sz);
339 
340  inline void setScale(SkMScalar scale) {
341  this->setScale(scale, scale, scale);
342  }
343  inline void preScale(SkMScalar scale) {
344  this->preScale(scale, scale, scale);
345  }
346  inline void postScale(SkMScalar scale) {
347  this->postScale(scale, scale, scale);
348  }
349 
350  void setRotateDegreesAbout(SkMScalar x, SkMScalar y, SkMScalar z,
351  SkMScalar degrees) {
352  this->setRotateAbout(x, y, z, degrees * SK_MScalarPI / 180);
353  }
354 
358  void setRotateAbout(SkMScalar x, SkMScalar y, SkMScalar z,
359  SkMScalar radians);
363  void setRotateAboutUnit(SkMScalar x, SkMScalar y, SkMScalar z,
364  SkMScalar radians);
365 
366  void setConcat(const SkMatrix44& a, const SkMatrix44& b);
367  inline void preConcat(const SkMatrix44& m) {
368  this->setConcat(*this, m);
369  }
370  inline void postConcat(const SkMatrix44& m) {
371  this->setConcat(m, *this);
372  }
373 
374  friend SkMatrix44 operator*(const SkMatrix44& a, const SkMatrix44& b) {
375  return SkMatrix44(a, b);
376  }
377 
382  bool invert(SkMatrix44* inverse) const;
383 
385  void transpose();
386 
390  void mapScalars(const SkScalar src[4], SkScalar dst[4]) const;
391  inline void mapScalars(SkScalar vec[4]) const {
392  this->mapScalars(vec, vec);
393  }
394 
395  SK_ATTR_DEPRECATED("use mapScalars")
396  void map(const SkScalar src[4], SkScalar dst[4]) const {
397  this->mapScalars(src, dst);
398  }
399 
400  SK_ATTR_DEPRECATED("use mapScalars")
401  void map(SkScalar vec[4]) const {
402  this->mapScalars(vec, vec);
403  }
404 
405 #ifdef SK_MSCALAR_IS_DOUBLE
406  void mapMScalars(const SkMScalar src[4], SkMScalar dst[4]) const;
407 #elif defined SK_MSCALAR_IS_FLOAT
408  inline void mapMScalars(const SkMScalar src[4], SkMScalar dst[4]) const {
409  this->mapScalars(src, dst);
410  }
411 #endif
412  inline void mapMScalars(SkMScalar vec[4]) const {
413  this->mapMScalars(vec, vec);
414  }
415 
416  friend SkVector4 operator*(const SkMatrix44& m, const SkVector4& src) {
417  SkVector4 dst;
418  m.mapScalars(src.fData, dst.fData);
419  return dst;
420  }
421 
430  void map2(const float src2[], int count, float dst4[]) const;
431  void map2(const double src2[], int count, double dst4[]) const;
432 
443  bool preserves2dAxisAlignment(SkMScalar epsilon = SK_ScalarNearlyZero) const;
444 
445  void dump() const;
446 
447  double determinant() const;
448 
449 private:
450  /* This is indexed by [col][row]. */
451  SkMScalar fMat[4][4];
452  mutable unsigned fTypeMask;
453 
454  enum {
455  kUnknown_Mask = 0x80,
456 
457  kAllPublic_Masks = 0xF
458  };
459 
460  void as4x3ColMajorf(float[]) const;
461  void set4x3ColMajorf(const float[]);
462 
463  SkMScalar transX() const { return fMat[3][0]; }
464  SkMScalar transY() const { return fMat[3][1]; }
465  SkMScalar transZ() const { return fMat[3][2]; }
466 
467  SkMScalar scaleX() const { return fMat[0][0]; }
468  SkMScalar scaleY() const { return fMat[1][1]; }
469  SkMScalar scaleZ() const { return fMat[2][2]; }
470 
471  SkMScalar perspX() const { return fMat[0][3]; }
472  SkMScalar perspY() const { return fMat[1][3]; }
473  SkMScalar perspZ() const { return fMat[2][3]; }
474 
475  int computeTypeMask() const;
476 
477  inline void dirtyTypeMask() {
478  fTypeMask = kUnknown_Mask;
479  }
480 
481  inline void setTypeMask(int mask) {
482  SkASSERT(0 == (~(kAllPublic_Masks | kUnknown_Mask) & mask));
483  fTypeMask = mask;
484  }
485 
490  inline bool isTriviallyIdentity() const {
491  return 0 == fTypeMask;
492  }
493 
494  friend class SkColorSpace;
495 };
496 
497 #endif
bool isScale() const
Returns true if the matrix only contains scale or is identity.
Definition: SkMatrix44.h:238
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:16
TypeMask getType() const
Returns a bitfield describing the transformations the matrix may perform.
Definition: SkMatrix44.h:206
Definition: SkMatrix44.h:88
bool isTranslate() const
Return true if the matrix contains translate or is identity.
Definition: SkMatrix44.h:224
Definition: SkMatrix44.h:129
bool isIdentity() const
Return true if the matrix is identity.
Definition: SkMatrix44.h:217
The SkMatrix class holds a 3x3 matrix for transforming coordinates.
Definition: SkMatrix.h:26
#define SkToBool(cond)
Returns 0 or 1 based on the condition.
Definition: SkTypes.h:287
bool isTriviallyIdentity() const
Does not take the time to 'compute' the typemask.
Definition: SkMatrix44.h:490
bool isScaleTranslate() const
Return true if the matrix only contains scale or translate or is identity.
Definition: SkMatrix44.h:231
TypeMask
Definition: SkMatrix44.h:191
void set(int row, int col, SkMScalar value)
set a value in the matrix.
Definition: SkMatrix44.h:267