Skia
2DGraphicsLibrary
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
SkMatrix.h
1 
2 /*
3  * Copyright 2006 The Android Open Source Project
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 
9 
10 #ifndef SkMatrix_DEFINED
11 #define SkMatrix_DEFINED
12 
13 #include "SkRect.h"
14 
15 struct SkRSXform;
16 class SkString;
17 
25 SK_BEGIN_REQUIRE_DENSE
26 class SK_API SkMatrix {
27 public:
28  static SkMatrix SK_WARN_UNUSED_RESULT MakeScale(SkScalar sx, SkScalar sy) {
29  SkMatrix m;
30  m.setScale(sx, sy);
31  return m;
32  }
33 
34  static SkMatrix SK_WARN_UNUSED_RESULT MakeScale(SkScalar scale) {
35  SkMatrix m;
36  m.setScale(scale, scale);
37  return m;
38  }
39 
40  static SkMatrix SK_WARN_UNUSED_RESULT MakeTrans(SkScalar dx, SkScalar dy) {
41  SkMatrix m;
42  m.setTranslate(dx, dy);
43  return m;
44  }
45 
49  enum TypeMask {
50  kIdentity_Mask = 0,
51  kTranslate_Mask = 0x01,
52  kScale_Mask = 0x02,
53  kAffine_Mask = 0x04,
54  kPerspective_Mask = 0x08
55  };
56 
63  TypeMask getType() const {
64  if (fTypeMask & kUnknown_Mask) {
65  fTypeMask = this->computeTypeMask();
66  }
67  // only return the public masks
68  return (TypeMask)(fTypeMask & 0xF);
69  }
70 
73  bool isIdentity() const {
74  return this->getType() == 0;
75  }
76 
77  bool isScaleTranslate() const {
78  return !(this->getType() & ~(kScale_Mask | kTranslate_Mask));
79  }
80 
85  bool rectStaysRect() const {
86  if (fTypeMask & kUnknown_Mask) {
87  fTypeMask = this->computeTypeMask();
88  }
89  return (fTypeMask & kRectStaysRect_Mask) != 0;
90  }
91  // alias for rectStaysRect()
92  bool preservesAxisAlignment() const { return this->rectStaysRect(); }
93 
97  bool hasPerspective() const {
98  return SkToBool(this->getPerspectiveTypeMaskOnly() &
99  kPerspective_Mask);
100  }
101 
105  bool isSimilarity(SkScalar tol = SK_ScalarNearlyZero) const;
106 
111  bool preservesRightAngles(SkScalar tol = SK_ScalarNearlyZero) const;
112 
113  enum {
114  kMScaleX,
115  kMSkewX,
116  kMTransX,
117  kMSkewY,
118  kMScaleY,
119  kMTransY,
120  kMPersp0,
121  kMPersp1,
122  kMPersp2
123  };
124 
128  enum {
129  kAScaleX,
130  kASkewY,
131  kASkewX,
132  kAScaleY,
133  kATransX,
134  kATransY
135  };
136 
137  SkScalar operator[](int index) const {
138  SkASSERT((unsigned)index < 9);
139  return fMat[index];
140  }
141 
142  SkScalar get(int index) const {
143  SkASSERT((unsigned)index < 9);
144  return fMat[index];
145  }
146 
147  SkScalar getScaleX() const { return fMat[kMScaleX]; }
148  SkScalar getScaleY() const { return fMat[kMScaleY]; }
149  SkScalar getSkewY() const { return fMat[kMSkewY]; }
150  SkScalar getSkewX() const { return fMat[kMSkewX]; }
151  SkScalar getTranslateX() const { return fMat[kMTransX]; }
152  SkScalar getTranslateY() const { return fMat[kMTransY]; }
153  SkScalar getPerspX() const { return fMat[kMPersp0]; }
154  SkScalar getPerspY() const { return fMat[kMPersp1]; }
155 
156  SkScalar& operator[](int index) {
157  SkASSERT((unsigned)index < 9);
158  this->setTypeMask(kUnknown_Mask);
159  return fMat[index];
160  }
161 
162  void set(int index, SkScalar value) {
163  SkASSERT((unsigned)index < 9);
164  fMat[index] = value;
165  this->setTypeMask(kUnknown_Mask);
166  }
167 
168  void setScaleX(SkScalar v) { this->set(kMScaleX, v); }
169  void setScaleY(SkScalar v) { this->set(kMScaleY, v); }
170  void setSkewY(SkScalar v) { this->set(kMSkewY, v); }
171  void setSkewX(SkScalar v) { this->set(kMSkewX, v); }
172  void setTranslateX(SkScalar v) { this->set(kMTransX, v); }
173  void setTranslateY(SkScalar v) { this->set(kMTransY, v); }
174  void setPerspX(SkScalar v) { this->set(kMPersp0, v); }
175  void setPerspY(SkScalar v) { this->set(kMPersp1, v); }
176 
177  void setAll(SkScalar scaleX, SkScalar skewX, SkScalar transX,
178  SkScalar skewY, SkScalar scaleY, SkScalar transY,
179  SkScalar persp0, SkScalar persp1, SkScalar persp2) {
180  fMat[kMScaleX] = scaleX;
181  fMat[kMSkewX] = skewX;
182  fMat[kMTransX] = transX;
183  fMat[kMSkewY] = skewY;
184  fMat[kMScaleY] = scaleY;
185  fMat[kMTransY] = transY;
186  fMat[kMPersp0] = persp0;
187  fMat[kMPersp1] = persp1;
188  fMat[kMPersp2] = persp2;
189  this->setTypeMask(kUnknown_Mask);
190  }
191 
196  void get9(SkScalar buffer[9]) const {
197  memcpy(buffer, fMat, 9 * sizeof(SkScalar));
198  }
199 
207  void set9(const SkScalar buffer[9]);
208 
211  void reset();
212  // alias for reset()
213  void setIdentity() { this->reset(); }
214 
217  void setTranslate(SkScalar dx, SkScalar dy);
218  void setTranslate(const SkVector& v) { this->setTranslate(v.fX, v.fY); }
219 
224  void setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py);
227  void setScale(SkScalar sx, SkScalar sy);
231  bool setIDiv(int divx, int divy);
236  void setRotate(SkScalar degrees, SkScalar px, SkScalar py);
239  void setRotate(SkScalar degrees);
244  void setSinCos(SkScalar sinValue, SkScalar cosValue,
245  SkScalar px, SkScalar py);
248  void setSinCos(SkScalar sinValue, SkScalar cosValue);
249 
250  SkMatrix& setRSXform(const SkRSXform&);
251 
256  void setSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py);
259  void setSkew(SkScalar kx, SkScalar ky);
264  void setConcat(const SkMatrix& a, const SkMatrix& b);
265 
269  void preTranslate(SkScalar dx, SkScalar dy);
273  void preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py);
277  void preScale(SkScalar sx, SkScalar sy);
281  void preRotate(SkScalar degrees, SkScalar px, SkScalar py);
285  void preRotate(SkScalar degrees);
289  void preSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py);
293  void preSkew(SkScalar kx, SkScalar ky);
297  void preConcat(const SkMatrix& other);
298 
302  void postTranslate(SkScalar dx, SkScalar dy);
306  void postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py);
310  void postScale(SkScalar sx, SkScalar sy);
314  bool postIDiv(int divx, int divy);
318  void postRotate(SkScalar degrees, SkScalar px, SkScalar py);
322  void postRotate(SkScalar degrees);
326  void postSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py);
330  void postSkew(SkScalar kx, SkScalar ky);
334  void postConcat(const SkMatrix& other);
335 
336  enum ScaleToFit {
361  kEnd_ScaleToFit
362  };
363 
372  bool setRectToRect(const SkRect& src, const SkRect& dst, ScaleToFit stf);
373  static SkMatrix MakeRectToRect(const SkRect& src, const SkRect& dst, ScaleToFit stf) {
374  SkMatrix m;
375  m.setRectToRect(src, dst, stf);
376  return m;
377  }
378 
386  bool setPolyToPoly(const SkPoint src[], const SkPoint dst[], int count);
387 
392  bool SK_WARN_UNUSED_RESULT invert(SkMatrix* inverse) const {
393  // Allow the trivial case to be inlined.
394  if (this->isIdentity()) {
395  if (inverse) {
396  inverse->reset();
397  }
398  return true;
399  }
400  return this->invertNonIdentity(inverse);
401  }
402 
408  static void SetAffineIdentity(SkScalar affine[6]);
409 
415  bool SK_WARN_UNUSED_RESULT asAffine(SkScalar affine[6]) const;
416 
420  void setAffine(const SkScalar affine[6]);
421 
432  void mapPoints(SkPoint dst[], const SkPoint src[], int count) const {
433  SkASSERT((dst && src && count > 0) || 0 == count);
434  // no partial overlap
435  SkASSERT(src == dst || &dst[count] <= &src[0] || &src[count] <= &dst[0]);
436  this->getMapPtsProc()(*this, dst, src, count);
437  }
438 
446  void mapPoints(SkPoint pts[], int count) const {
447  this->mapPoints(pts, pts, count);
448  }
449 
453  void mapPointsWithStride(SkPoint pts[], size_t stride, int count) const {
454  SkASSERT(stride >= sizeof(SkPoint));
455  SkASSERT(0 == stride % sizeof(SkScalar));
456  for (int i = 0; i < count; ++i) {
457  this->mapPoints(pts, pts, 1);
458  pts = (SkPoint*)((intptr_t)pts + stride);
459  }
460  }
461 
465  size_t stride, int count) const {
466  SkASSERT(stride >= sizeof(SkPoint));
467  SkASSERT(0 == stride % sizeof(SkScalar));
468  for (int i = 0; i < count; ++i) {
469  this->mapPoints(dst, src, 1);
470  src = (SkPoint*)((intptr_t)src + stride);
471  dst = (SkPoint*)((intptr_t)dst + stride);
472  }
473  }
474 
486  void mapHomogeneousPoints(SkScalar dst[], const SkScalar src[], int count) const;
487 
488  void mapXY(SkScalar x, SkScalar y, SkPoint* result) const {
489  SkASSERT(result);
490  this->getMapXYProc()(*this, x, y, result);
491  }
492 
493  SkPoint mapXY(SkScalar x, SkScalar y) const {
494  SkPoint result;
495  this->getMapXYProc()(*this, x, y, &result);
496  return result;
497  }
498 
509  void mapVectors(SkVector dst[], const SkVector src[], int count) const;
510 
518  void mapVectors(SkVector vecs[], int count) const {
519  this->mapVectors(vecs, vecs, count);
520  }
521 
522  void mapVector(SkScalar dx, SkScalar dy, SkVector* result) const {
523  SkVector vec = { dx, dy };
524  this->mapVectors(result, &vec, 1);
525  }
526 
527  SkVector mapVector(SkScalar dx, SkScalar dy) const {
528  SkVector vec = { dx, dy };
529  this->mapVectors(&vec, &vec, 1);
530  return vec;
531  }
532 
540  bool mapRect(SkRect* dst, const SkRect& src) const;
541 
548  bool mapRect(SkRect* rect) const {
549  return this->mapRect(rect, *rect);
550  }
551 
558  void mapRectToQuad(SkPoint dst[4], const SkRect& rect) const {
559  // This could potentially be faster if we only transformed each x and y of the rect once.
560  rect.toQuad(dst);
561  this->mapPoints(dst, 4);
562  }
563 
568  void mapRectScaleTranslate(SkRect* dst, const SkRect& src) const;
569 
574  SkScalar mapRadius(SkScalar radius) const;
575 
576  typedef void (*MapXYProc)(const SkMatrix& mat, SkScalar x, SkScalar y,
577  SkPoint* result);
578 
579  static MapXYProc GetMapXYProc(TypeMask mask) {
580  SkASSERT((mask & ~kAllMasks) == 0);
581  return gMapXYProcs[mask & kAllMasks];
582  }
583 
584  MapXYProc getMapXYProc() const {
585  return GetMapXYProc(this->getType());
586  }
587 
588  typedef void (*MapPtsProc)(const SkMatrix& mat, SkPoint dst[],
589  const SkPoint src[], int count);
590 
591  static MapPtsProc GetMapPtsProc(TypeMask mask) {
592  SkASSERT((mask & ~kAllMasks) == 0);
593  return gMapPtsProcs[mask & kAllMasks];
594  }
595 
596  MapPtsProc getMapPtsProc() const {
597  return GetMapPtsProc(this->getType());
598  }
599 
603  bool isFixedStepInX() const;
604 
609  SkVector fixedStepInX(SkScalar y) const;
610 
619  bool cheapEqualTo(const SkMatrix& m) const {
620  return 0 == memcmp(fMat, m.fMat, sizeof(fMat));
621  }
622 
623  friend SK_API bool operator==(const SkMatrix& a, const SkMatrix& b);
624  friend SK_API bool operator!=(const SkMatrix& a, const SkMatrix& b) {
625  return !(a == b);
626  }
627 
628  enum {
629  // writeTo/readFromMemory will never return a value larger than this
630  kMaxFlattenSize = 9 * sizeof(SkScalar) + sizeof(uint32_t)
631  };
632  // return the number of bytes written, whether or not buffer is null
633  size_t writeToMemory(void* buffer) const;
642  size_t readFromMemory(const void* buffer, size_t length);
643 
644  void dump() const;
645  void toString(SkString*) const;
646 
654  SkScalar getMinScale() const;
655 
663  SkScalar getMaxScale() const;
664 
670  bool SK_WARN_UNUSED_RESULT getMinMaxScales(SkScalar scaleFactors[2]) const;
671 
683  bool decomposeScale(SkSize* scale, SkMatrix* remaining = NULL) const;
684 
688  static const SkMatrix& I();
689 
694  static const SkMatrix& InvalidMatrix();
695 
699  static SkMatrix Concat(const SkMatrix& a, const SkMatrix& b) {
700  SkMatrix result;
701  result.setConcat(a, b);
702  return result;
703  }
704 
710  this->setTypeMask(kUnknown_Mask);
711  }
712 
716  void setScaleTranslate(SkScalar sx, SkScalar sy, SkScalar tx, SkScalar ty) {
717  fMat[kMScaleX] = sx;
718  fMat[kMSkewX] = 0;
719  fMat[kMTransX] = tx;
720 
721  fMat[kMSkewY] = 0;
722  fMat[kMScaleY] = sy;
723  fMat[kMTransY] = ty;
724 
725  fMat[kMPersp0] = 0;
726  fMat[kMPersp1] = 0;
727  fMat[kMPersp2] = 1;
728 
729  unsigned mask = 0;
730  if (sx != 1 || sy != 1) {
731  mask |= kScale_Mask;
732  }
733  if (tx || ty) {
734  mask |= kTranslate_Mask;
735  }
736  this->setTypeMask(mask | kRectStaysRect_Mask);
737  }
738 
739 private:
740  enum {
747  kRectStaysRect_Mask = 0x10,
748 
752  kOnlyPerspectiveValid_Mask = 0x40,
753 
754  kUnknown_Mask = 0x80,
755 
756  kORableMasks = kTranslate_Mask |
757  kScale_Mask |
758  kAffine_Mask |
759  kPerspective_Mask,
760 
761  kAllMasks = kTranslate_Mask |
762  kScale_Mask |
763  kAffine_Mask |
764  kPerspective_Mask |
765  kRectStaysRect_Mask
766  };
767 
768  SkScalar fMat[9];
769  mutable uint32_t fTypeMask;
770 
773  bool isFinite() const { return SkScalarsAreFinite(fMat, 9); }
774 
775  static void ComputeInv(SkScalar dst[9], const SkScalar src[9], double invDet, bool isPersp);
776 
777  uint8_t computeTypeMask() const;
778  uint8_t computePerspectiveTypeMask() const;
779 
780  void setTypeMask(int mask) {
781  // allow kUnknown or a valid mask
782  SkASSERT(kUnknown_Mask == mask || (mask & kAllMasks) == mask ||
783  ((kUnknown_Mask | kOnlyPerspectiveValid_Mask) & mask)
784  == (kUnknown_Mask | kOnlyPerspectiveValid_Mask));
785  fTypeMask = SkToU8(mask);
786  }
787 
788  void orTypeMask(int mask) {
789  SkASSERT((mask & kORableMasks) == mask);
790  fTypeMask = SkToU8(fTypeMask | mask);
791  }
792 
793  void clearTypeMask(int mask) {
794  // only allow a valid mask
795  SkASSERT((mask & kAllMasks) == mask);
796  fTypeMask = fTypeMask & ~mask;
797  }
798 
799  TypeMask getPerspectiveTypeMaskOnly() const {
800  if ((fTypeMask & kUnknown_Mask) &&
801  !(fTypeMask & kOnlyPerspectiveValid_Mask)) {
802  fTypeMask = this->computePerspectiveTypeMask();
803  }
804  return (TypeMask)(fTypeMask & 0xF);
805  }
806 
810  bool isTriviallyIdentity() const {
811  if (fTypeMask & kUnknown_Mask) {
812  return false;
813  }
814  return ((fTypeMask & 0xF) == 0);
815  }
816 
817  bool SK_WARN_UNUSED_RESULT invertNonIdentity(SkMatrix* inverse) const;
818 
819  static bool Poly2Proc(const SkPoint[], SkMatrix*, const SkPoint& scale);
820  static bool Poly3Proc(const SkPoint[], SkMatrix*, const SkPoint& scale);
821  static bool Poly4Proc(const SkPoint[], SkMatrix*, const SkPoint& scale);
822 
823  static void Identity_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
824  static void Trans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
825  static void Scale_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
826  static void ScaleTrans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
827  static void Rot_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
828  static void RotTrans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
829  static void Persp_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
830 
831  static const MapXYProc gMapXYProcs[];
832 
833  static void Identity_pts(const SkMatrix&, SkPoint[], const SkPoint[], int);
834  static void Trans_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
835  static void Scale_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
836  static void ScaleTrans_pts(const SkMatrix&, SkPoint dst[], const SkPoint[],
837  int count);
838  static void Persp_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
839 
840  static void Affine_vpts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
841 
842  static const MapPtsProc gMapPtsProcs[];
843 
844  friend class SkPerspIter;
845  friend class SkMatrixPriv;
846 };
847 SK_END_REQUIRE_DENSE
848 
849 #endif
TypeMask
Enum of bit fields for the mask return by getType().
Definition: SkMatrix.h:49
bool isFinite() const
Are all elements of the matrix finite?
Definition: SkMatrix.h:773
ScaleToFit
Definition: SkMatrix.h:336
bool isIdentity() const
Returns true if the matrix is identity.
Definition: SkMatrix.h:73
void get9(SkScalar buffer[9]) const
Copy the 9 scalars for this matrix into buffer, in the same order as the kMScaleX enum...
Definition: SkMatrix.h:196
void setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py)
Set the matrix to scale by sx and sy, with a pivot point at (px, py).
void mapPoints(SkPoint dst[], const SkPoint src[], int count) const
Apply this matrix to the array of points specified by src, and write the transformed points into the ...
Definition: SkMatrix.h:432
void setConcat(const SkMatrix &a, const SkMatrix &b)
Set the matrix to the concatenation of the two specified matrices.
Definition: SkPoint.h:156
void dirtyMatrixTypeCache()
Testing routine; the matrix's type cache should never need to be manually invalidated during normal u...
Definition: SkMatrix.h:709
bool setRectToRect(const SkRect &src, const SkRect &dst, ScaleToFit stf)
Set the matrix to the scale and translate values that map the source rectangle to the destination rec...
void mapVectors(SkVector vecs[], int count) const
Apply this matrix to the array of vectors specified by src, and write the transformed vectors into th...
Definition: SkMatrix.h:518
The SkMatrix class holds a 3x3 matrix for transforming coordinates.
Definition: SkMatrix.h:26
void setTranslate(SkScalar dx, SkScalar dy)
Set the matrix to translate by (dx, dy).
bool SK_WARN_UNUSED_RESULT invert(SkMatrix *inverse) const
If this matrix can be inverted, return true and if inverse is not null, set inverse to be the inverse...
Definition: SkMatrix.h:392
#define SkToBool(cond)
Returns 0 or 1 based on the condition.
Definition: SkTypes.h:287
A compressed form of a rotation+scale matrix.
Definition: SkRSXform.h:20
Compute a scale that will maintain the original src aspect ratio, but will also ensure that src fits ...
Definition: SkMatrix.h:354
void mapPoints(SkPoint pts[], int count) const
Apply this matrix to the array of points, overwriting it with the transformed values.
Definition: SkMatrix.h:446
Scale in X and Y independently, so that src matches dst exactly.
Definition: SkMatrix.h:341
TypeMask getType() const
Returns a bitfield describing the transformations the matrix may perform.
Definition: SkMatrix.h:63
bool mapRect(SkRect *rect) const
Apply this matrix to the rectangle, and write the transformed rectangle back into it...
Definition: SkMatrix.h:548
static SkMatrix Concat(const SkMatrix &a, const SkMatrix &b)
Return the concatenation of two matrices, a * b.
Definition: SkMatrix.h:699
void toQuad(SkPoint quad[4]) const
return the 4 points that enclose the rectangle (top-left, top-right, bottom-right, bottom-left).
void reset()
Set the matrix to identity.
bool isTriviallyIdentity() const
Returns true if we already know that the matrix is identity; false otherwise.
Definition: SkMatrix.h:810
void mapPointsWithStride(SkPoint dst[], SkPoint src[], size_t stride, int count) const
Like mapPoints but with custom byte stride between the points.
Definition: SkMatrix.h:464
bool hasPerspective() const
Returns true if the matrix contains perspective elements.
Definition: SkMatrix.h:97
void mapRectToQuad(SkPoint dst[4], const SkRect &rect) const
Apply this matrix to the src rectangle, and write the four transformed points into dst...
Definition: SkMatrix.h:558
bool cheapEqualTo(const SkMatrix &m) const
Efficient comparison of two matrices.
Definition: SkMatrix.h:619
Definition: SkRect.h:390
void setScaleTranslate(SkScalar sx, SkScalar sy, SkScalar tx, SkScalar ty)
Initialize the matrix to be scale + post-translate.
Definition: SkMatrix.h:716
Compute a scale that will maintain the original src aspect ratio, but will also ensure that src fits ...
Definition: SkMatrix.h:348
void mapPointsWithStride(SkPoint pts[], size_t stride, int count) const
Like mapPoints but with custom byte stride between the points.
Definition: SkMatrix.h:453
Definition: SkSize.h:77
Light weight class for managing strings.
Definition: SkString.h:121
bool rectStaysRect() const
Returns true if will map a rectangle to another rectangle.
Definition: SkMatrix.h:85