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