Skia
2DGraphicsLibrary
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
SkRRect.h
1 /*
2  * Copyright 2012 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 SkRRect_DEFINED
9 #define SkRRect_DEFINED
10 
11 #include "SkRect.h"
12 #include "SkPoint.h"
13 
14 class SkPath;
15 class SkMatrix;
16 
17 // Path forward:
18 // core work
19 // add contains(SkRect&) - for clip stack
20 // add contains(SkRRect&) - for clip stack
21 // add heart rect computation (max rect inside RR)
22 // add 9patch rect computation
23 // add growToInclude(SkPath&)
24 // analysis
25 // use growToInclude to fit skp round rects & generate stats (RRs vs. real paths)
26 // check on # of rectorus's the RRs could handle
27 // rendering work
28 // update SkPath.addRRect() to only use quads
29 // add GM and bench
30 // further out
31 // detect and triangulate RRectorii rather than falling back to SW in Ganesh
32 //
33 
47 class SK_API SkRRect {
48 public:
49  SkRRect() { /* unititialized */ }
50  SkRRect(const SkRRect&) = default;
51  SkRRect& operator=(const SkRRect&) = default;
52 
57  enum Type {
58  // !< The RR is empty
59  kEmpty_Type,
60 
63  kRect_Type,
64 
67  kOval_Type,
68 
72  kSimple_Type,
73 
80  kNinePatch_Type,
81 
85  kComplex_Type,
86  };
87 
91  Type getType() const {
92  SkASSERT(this->isValid());
93  return static_cast<Type>(fType);
94  }
95 
96  Type type() const { return this->getType(); }
97 
98  inline bool isEmpty() const { return kEmpty_Type == this->getType(); }
99  inline bool isRect() const { return kRect_Type == this->getType(); }
100  inline bool isOval() const { return kOval_Type == this->getType(); }
101  inline bool isSimple() const { return kSimple_Type == this->getType(); }
102  // TODO: should isSimpleCircular & isCircle take a tolerance? This could help
103  // instances where the mapping to device space is noisy.
104  inline bool isSimpleCircular() const {
105  return this->isSimple() && SkScalarNearlyEqual(fRadii[0].fX, fRadii[0].fY);
106  }
107  inline bool isCircle() const {
108  return this->isOval() && SkScalarNearlyEqual(fRadii[0].fX, fRadii[0].fY);
109  }
110  inline bool isNinePatch() const { return kNinePatch_Type == this->getType(); }
111  inline bool isComplex() const { return kComplex_Type == this->getType(); }
112 
113  bool allCornersCircular(SkScalar tolerance = SK_ScalarNearlyZero) const;
114 
115  SkScalar width() const { return fRect.width(); }
116  SkScalar height() const { return fRect.height(); }
117 
121  void setEmpty() {
122  fRect.setEmpty();
123  memset(fRadii, 0, sizeof(fRadii));
124  fType = kEmpty_Type;
125 
126  SkASSERT(this->isValid());
127  }
128 
132  void setRect(const SkRect& rect) {
133  fRect = rect;
134  fRect.sort();
135 
136  if (fRect.isEmpty()) {
137  this->setEmpty();
138  return;
139  }
140 
141  memset(fRadii, 0, sizeof(fRadii));
142  fType = kRect_Type;
143 
144  SkASSERT(this->isValid());
145  }
146 
147  static SkRRect MakeEmpty() {
148  SkRRect rr;
149  rr.setEmpty();
150  return rr;
151  }
152 
153  static SkRRect MakeRect(const SkRect& r) {
154  SkRRect rr;
155  rr.setRect(r);
156  return rr;
157  }
158 
159  static SkRRect MakeOval(const SkRect& oval) {
160  SkRRect rr;
161  rr.setOval(oval);
162  return rr;
163  }
164 
165  static SkRRect MakeRectXY(const SkRect& rect, SkScalar xRad, SkScalar yRad) {
166  SkRRect rr;
167  rr.setRectXY(rect, xRad, yRad);
168  return rr;
169  }
170 
175  void setOval(const SkRect& oval) {
176  fRect = oval;
177  fRect.sort();
178 
179  if (fRect.isEmpty()) {
180  this->setEmpty();
181  return;
182  }
183 
184  SkScalar xRad = SkScalarHalf(fRect.width());
185  SkScalar yRad = SkScalarHalf(fRect.height());
186 
187  for (int i = 0; i < 4; ++i) {
188  fRadii[i].set(xRad, yRad);
189  }
190  fType = kOval_Type;
191 
192  SkASSERT(this->isValid());
193  }
194 
198  void setRectXY(const SkRect& rect, SkScalar xRad, SkScalar yRad);
199 
203  void setNinePatch(const SkRect& rect, SkScalar leftRad, SkScalar topRad,
204  SkScalar rightRad, SkScalar bottomRad);
205 
209  void setRectRadii(const SkRect& rect, const SkVector radii[4]);
210 
211  // The radii are stored in UL, UR, LR, LL order.
212  enum Corner {
213  kUpperLeft_Corner,
214  kUpperRight_Corner,
215  kLowerRight_Corner,
216  kLowerLeft_Corner
217  };
218 
219  const SkRect& rect() const { return fRect; }
220  const SkVector& radii(Corner corner) const { return fRadii[corner]; }
221  const SkRect& getBounds() const { return fRect; }
222 
227  const SkVector& getSimpleRadii() const {
228  SkASSERT(!this->isComplex());
229  return fRadii[0];
230  }
231 
232  friend bool operator==(const SkRRect& a, const SkRRect& b) {
233  return a.fRect == b.fRect &&
234  SkScalarsEqual(a.fRadii[0].asScalars(),
235  b.fRadii[0].asScalars(), 8);
236  }
237 
238  friend bool operator!=(const SkRRect& a, const SkRRect& b) {
239  return a.fRect != b.fRect ||
240  !SkScalarsEqual(a.fRadii[0].asScalars(),
241  b.fRadii[0].asScalars(), 8);
242  }
243 
252  void inset(SkScalar dx, SkScalar dy, SkRRect* dst) const;
253 
254  void inset(SkScalar dx, SkScalar dy) {
255  this->inset(dx, dy, this);
256  }
257 
266  void outset(SkScalar dx, SkScalar dy, SkRRect* dst) const {
267  this->inset(-dx, -dy, dst);
268  }
269  void outset(SkScalar dx, SkScalar dy) {
270  this->inset(-dx, -dy, this);
271  }
272 
276  void offset(SkScalar dx, SkScalar dy) {
277  fRect.offset(dx, dy);
278  }
279 
280  SkRRect SK_WARN_UNUSED_RESULT makeOffset(SkScalar dx, SkScalar dy) const {
281  return SkRRect(fRect.makeOffset(dx, dy), fRadii, fType);
282  }
283 
288  bool contains(const SkRect& rect) const;
289 
290  bool isValid() const;
291 
292  enum {
293  kSizeInMemory = 12 * sizeof(SkScalar)
294  };
295 
301  size_t writeToMemory(void* buffer) const;
302 
314  size_t readFromMemory(const void* buffer, size_t length);
315 
325  bool transform(const SkMatrix& matrix, SkRRect* dst) const;
326 
327  void dump(bool asHex) const;
328  void dump() const { this->dump(false); }
329  void dumpHex() const { this->dump(true); }
330 
331 private:
332  SkRRect(const SkRect& rect, const SkVector radii[4], int32_t type)
333  : fRect(rect)
334  , fRadii{radii[0], radii[1], radii[2], radii[3]}
335  , fType(type) {}
336 
337  SkRect fRect;
338  // Radii order is UL, UR, LR, LL. Use Corner enum to index into fRadii[]
339  SkVector fRadii[4];
340  // use an explicitly sized type so we're sure the class is dense (no uninitialized bytes)
341  int32_t fType;
342  // TODO: add padding so we can use memcpy for flattening and not copy
343  // uninitialized data
344 
345  void computeType();
346  bool checkCornerContainment(SkScalar x, SkScalar y) const;
347  void scaleRadii();
348 
349  // to access fRadii directly
350  friend class SkPath;
351 };
352 
353 #endif
The SkRRect class represents a rounded rect with a potentially different radii for each corner...
Definition: SkRRect.h:47
The SkPath class encapsulates compound (multiple contour) geometric paths consisting of straight line...
Definition: SkPath.h:25
void sort()
Swap top/bottom or left/right if there are flipped (i.e.
Definition: SkRect.h:900
void setRectXY(const SkRect &rect, SkScalar xRad, SkScalar yRad)
Initialize the RR with the same radii for all four corners.
Type
Enum to capture the various possible subtypes of RR.
Definition: SkRRect.h:57
Definition: SkPoint.h:156
The SkMatrix class holds a 3x3 matrix for transforming coordinates.
Definition: SkMatrix.h:28
const SkScalar * asScalars() const
cast-safe way to treat the point as an array of (2) SkScalars.
Definition: SkPoint.h:547
void offset(SkScalar dx, SkScalar dy)
Translate the rrect by (dx, dy).
Definition: SkRRect.h:276
Type getType() const
Returns the RR's sub type.
Definition: SkRRect.h:91
void outset(SkScalar dx, SkScalar dy, SkRRect *dst) const
Call outset on the bounds, and adjust the radii to reflect what happens in stroking: If the corner is...
Definition: SkRRect.h:266
Definition: SkRect.h:404
const SkVector & getSimpleRadii() const
When a rrect is simple, all of its radii are equal.
Definition: SkRRect.h:227
void setOval(const SkRect &oval)
Set this RR to match the supplied oval.
Definition: SkRRect.h:175
void setEmpty()
Set this RR to the empty rectangle (0,0,0,0) with 0 x & y radii.
Definition: SkRRect.h:121
void setRect(const SkRect &rect)
Set this RR to match the supplied rect.
Definition: SkRRect.h:132