Flutter Impeller
round_superellipse.h
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef FLUTTER_IMPELLER_GEOMETRY_ROUND_SUPERELLIPSE_H_
6 #define FLUTTER_IMPELLER_GEOMETRY_ROUND_SUPERELLIPSE_H_
7 
13 
14 namespace impeller {
15 
16 struct RoundRect;
17 
19  RoundSuperellipse() = default;
20 
21  inline static RoundSuperellipse MakeRect(const Rect& rect) {
22  return MakeRectRadii(rect, RoundingRadii());
23  }
24 
25  inline static RoundSuperellipse MakeOval(const Rect& rect) {
26  return MakeRectRadii(rect, RoundingRadii::MakeRadii(rect.GetSize() * 0.5f));
27  }
28 
29  inline static RoundSuperellipse MakeRectRadius(const Rect& rect,
30  Scalar radius) {
31  return MakeRectRadii(rect, RoundingRadii::MakeRadius(radius));
32  }
33 
34  inline static RoundSuperellipse MakeRectXY(const Rect& rect,
35  Scalar x_radius,
36  Scalar y_radius) {
37  return MakeRectRadii(rect,
38  RoundingRadii::MakeRadii(Size(x_radius, y_radius)));
39  }
40 
41  inline static RoundSuperellipse MakeRectXY(const Rect& rect,
42  Size corner_radii) {
43  return MakeRectRadii(rect, RoundingRadii::MakeRadii(corner_radii));
44  }
45 
46  static RoundSuperellipse MakeRectRadii(const Rect& rect,
47  const RoundingRadii& radii);
48 
49  constexpr const Rect& GetBounds() const { return bounds_; }
50  constexpr const RoundingRadii& GetRadii() const { return radii_; }
51 
52  [[nodiscard]] constexpr bool IsFinite() const {
53  return bounds_.IsFinite() && //
54  radii_.top_left.IsFinite() && //
55  radii_.top_right.IsFinite() && //
56  radii_.bottom_left.IsFinite() && //
57  radii_.bottom_right.IsFinite();
58  }
59 
60  [[nodiscard]] constexpr bool IsEmpty() const { return bounds_.IsEmpty(); }
61 
62  [[nodiscard]] constexpr bool IsRect() const {
63  return !bounds_.IsEmpty() && radii_.AreAllCornersEmpty();
64  }
65 
66  [[nodiscard]] constexpr bool IsOval() const {
67  return !bounds_.IsEmpty() && radii_.AreAllCornersSame() &&
69  bounds_.GetWidth() * 0.5f) &&
71  bounds_.GetHeight() * 0.5f);
72  }
73 
74  /// @brief Returns true iff the provided point |p| is inside the
75  /// half-open interior of this rectangle.
76  ///
77  /// For purposes of containment, a rectangle contains points
78  /// along the top and left edges but not points along the
79  /// right and bottom edges so that a point is only ever
80  /// considered inside one of two abutting rectangles.
81  [[nodiscard]] bool Contains(const Point& p) const;
82 
83  /// @brief Returns a new round rectangle translated by the given offset.
84  [[nodiscard]] inline RoundSuperellipse Shift(Scalar dx, Scalar dy) const {
85  // Just in case, use the factory rather than the internal constructor
86  // as shifting the rectangle may increase/decrease its bit precision
87  // so we should re-validate the radii to the newly located rectangle.
88  return MakeRectRadii(bounds_.Shift(dx, dy), radii_);
89  }
90 
91  /// @brief Returns a round rectangle with expanded edges. Negative expansion
92  /// results in shrinking.
93  [[nodiscard]] inline RoundSuperellipse Expand(Scalar left,
94  Scalar top,
95  Scalar right,
96  Scalar bottom) const {
97  // Use the factory rather than the internal constructor as the changing
98  // size of the rectangle requires that we re-validate the radii to the
99  // newly sized rectangle.
100  return MakeRectRadii(bounds_.Expand(left, top, right, bottom), radii_);
101  }
102 
103  /// @brief Returns a round rectangle with expanded edges. Negative expansion
104  /// results in shrinking.
105  [[nodiscard]] inline RoundSuperellipse Expand(Scalar horizontal,
106  Scalar vertical) const {
107  // Use the factory rather than the internal constructor as the changing
108  // size of the rectangle requires that we re-validate the radii to the
109  // newly sized rectangle.
110  return MakeRectRadii(bounds_.Expand(horizontal, vertical), radii_);
111  }
112 
113  /// @brief Returns a round rectangle with expanded edges. Negative expansion
114  /// results in shrinking.
115  [[nodiscard]] inline RoundSuperellipse Expand(Scalar amount) const {
116  // Use the factory rather than the internal constructor as the changing
117  // size of the rectangle requires that we re-validate the radii to the
118  // newly sized rectangle.
119  return MakeRectRadii(bounds_.Expand(amount), radii_);
120  }
121 
122  [[nodiscard]] constexpr bool operator==(const RoundSuperellipse& rr) const {
123  return bounds_ == rr.bounds_ && radii_ == rr.radii_;
124  }
125 
126  [[nodiscard]] constexpr bool operator!=(const RoundSuperellipse& r) const {
127  return !(*this == r);
128  }
129 
130  // Approximates a rounded superellipse with a round rectangle to the
131  // best practical accuracy.
132  //
133  // This is used for Skia backends, which does not support rounded
134  // superellipses directly, so rendering rounded superellipses
135  // falls back to RRect.
136  [[nodiscard]] RoundRect ToApproximateRoundRect() const;
137 
138  private:
139  constexpr RoundSuperellipse(const Rect& bounds, const RoundingRadii& radii)
140  : bounds_(bounds), radii_(radii) {}
141 
142  Rect bounds_;
143  RoundingRadii radii_;
144 };
145 
147  public:
149  const RoundSuperellipse& round_superellipse);
150 
152 
154  return round_superellipse_;
155  }
156 
157  // |PathSource|
158  FillType GetFillType() const override;
159 
160  // |PathSource|
161  Rect GetBounds() const override;
162 
163  // |PathSource|
164  bool IsConvex() const override;
165 
166  // |PathSource|
167  void Dispatch(PathReceiver& receiver) const override;
168 
169  private:
170  const RoundSuperellipse round_superellipse_;
171 };
172 
173 } // namespace impeller
174 
175 namespace std {
176 
177 inline std::ostream& operator<<(std::ostream& out,
178  const impeller::RoundSuperellipse& rr) {
179  out << "(" //
180  << "rect: " << rr.GetBounds() << ", " //
181  << "radii: " << rr.GetRadii();
182  out << ")";
183  return out;
184 }
185 
186 } // namespace std
187 
188 #endif // FLUTTER_IMPELLER_GEOMETRY_ROUND_SUPERELLIPSE_H_
Collection of functions to receive path segments from the underlying path representation via the DlPa...
Definition: path_source.h:42
const RoundSuperellipse & GetRoundSuperellipse() const
RoundSuperellipsePathSource(const RoundSuperellipse &round_superellipse)
void Dispatch(PathReceiver &receiver) const override
float Scalar
Definition: scalar.h:19
TRect< Scalar > Rect
Definition: rect.h:792
TSize< Scalar > Size
Definition: size.h:159
constexpr bool ScalarNearlyEqual(Scalar x, Scalar y, Scalar tolerance=kEhCloseEnough)
Definition: scalar.h:36
Definition: comparable.h:95
std::ostream & operator<<(std::ostream &out, const impeller::Arc &a)
Definition: arc.h:141
RoundSuperellipse Expand(Scalar amount) const
Returns a round rectangle with expanded edges. Negative expansion results in shrinking.
constexpr const RoundingRadii & GetRadii() const
static RoundSuperellipse MakeRectRadii(const Rect &rect, const RoundingRadii &radii)
constexpr bool IsOval() const
constexpr bool IsFinite() const
constexpr bool IsEmpty() const
RoundSuperellipse Expand(Scalar left, Scalar top, Scalar right, Scalar bottom) const
Returns a round rectangle with expanded edges. Negative expansion results in shrinking.
constexpr bool IsRect() const
static RoundSuperellipse MakeOval(const Rect &rect)
RoundRect ToApproximateRoundRect() const
RoundSuperellipse Expand(Scalar horizontal, Scalar vertical) const
Returns a round rectangle with expanded edges. Negative expansion results in shrinking.
RoundSuperellipse Shift(Scalar dx, Scalar dy) const
Returns a new round rectangle translated by the given offset.
static RoundSuperellipse MakeRect(const Rect &rect)
static RoundSuperellipse MakeRectRadius(const Rect &rect, Scalar radius)
constexpr const Rect & GetBounds() const
constexpr bool operator==(const RoundSuperellipse &rr) const
constexpr bool operator!=(const RoundSuperellipse &r) const
bool Contains(const Point &p) const
Returns true iff the provided point |p| is inside the half-open interior of this rectangle.
static RoundSuperellipse MakeRectXY(const Rect &rect, Size corner_radii)
static RoundSuperellipse MakeRectXY(const Rect &rect, Scalar x_radius, Scalar y_radius)
constexpr bool AreAllCornersEmpty() const
constexpr static RoundingRadii MakeRadii(Size radii)
constexpr bool AreAllCornersSame(Scalar tolerance=kEhCloseEnough) const
constexpr static RoundingRadii MakeRadius(Scalar radius)
constexpr TRect< T > Expand(T left, T top, T right, T bottom) const
Returns a rectangle with expanded edges. Negative expansion results in shrinking.
Definition: rect.h:622
constexpr Type GetHeight() const
Returns the height of the rectangle, equivalent to |GetSize().height|.
Definition: rect.h:351
constexpr bool IsEmpty() const
Returns true if either of the width or height are 0, negative, or NaN.
Definition: rect.h:301
constexpr TSize< Type > GetSize() const
Returns the size of the rectangle which may be negative in either width or height and may have been c...
Definition: rect.h:331
IsFinite() const
Returns true if all of the fields of this floating point rectangle are finite.
Definition: rect.h:292
constexpr TRect< T > Shift(T dx, T dy) const
Returns a new rectangle translated by the given offset.
Definition: rect.h:606
constexpr Type GetWidth() const
Returns the width of the rectangle, equivalent to |GetSize().width|.
Definition: rect.h:345
Type height
Definition: size.h:29
Type width
Definition: size.h:28
IsFinite() const
Definition: size.h:126