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 
12 
13 namespace impeller {
14 
15 struct RoundRect;
16 
18  RoundSuperellipse() = default;
19 
20  constexpr static RoundSuperellipse MakeRect(const Rect& rect) {
21  return MakeRectRadii(rect, RoundingRadii());
22  }
23 
24  constexpr static RoundSuperellipse MakeOval(const Rect& rect) {
25  return MakeRectRadii(rect, RoundingRadii::MakeRadii(rect.GetSize() * 0.5f));
26  }
27 
28  constexpr static RoundSuperellipse MakeRectRadius(const Rect& rect,
29  Scalar radius) {
30  return MakeRectRadii(rect, RoundingRadii::MakeRadius(radius));
31  }
32 
33  constexpr static RoundSuperellipse MakeRectXY(const Rect& rect,
34  Scalar x_radius,
35  Scalar y_radius) {
36  return MakeRectRadii(rect,
37  RoundingRadii::MakeRadii(Size(x_radius, y_radius)));
38  }
39 
40  constexpr static RoundSuperellipse MakeRectXY(const Rect& rect,
41  Size corner_radii) {
42  return MakeRectRadii(rect, RoundingRadii::MakeRadii(corner_radii));
43  }
44 
45  static RoundSuperellipse MakeRectRadii(const Rect& rect,
46  const RoundingRadii& radii);
47 
48  constexpr const Rect& GetBounds() const { return bounds_; }
49  constexpr const RoundingRadii& GetRadii() const { return radii_; }
50 
51  [[nodiscard]] constexpr bool IsFinite() const {
52  return bounds_.IsFinite() && //
53  radii_.top_left.IsFinite() && //
54  radii_.top_right.IsFinite() && //
55  radii_.bottom_left.IsFinite() && //
56  radii_.bottom_right.IsFinite();
57  }
58 
59  [[nodiscard]] constexpr bool IsEmpty() const { return bounds_.IsEmpty(); }
60 
61  [[nodiscard]] constexpr bool IsRect() const {
62  return !bounds_.IsEmpty() && radii_.AreAllCornersEmpty();
63  }
64 
65  [[nodiscard]] constexpr bool IsOval() const {
66  return !bounds_.IsEmpty() && radii_.AreAllCornersSame() &&
68  bounds_.GetWidth() * 0.5f) &&
70  bounds_.GetHeight() * 0.5f);
71  }
72 
73  /// @brief Returns true iff the provided point |p| is inside the
74  /// half-open interior of this rectangle.
75  ///
76  /// For purposes of containment, a rectangle contains points
77  /// along the top and left edges but not points along the
78  /// right and bottom edges so that a point is only ever
79  /// considered inside one of two abutting rectangles.
80  [[nodiscard]] bool Contains(const Point& p) const;
81 
82  /// @brief Returns a new round rectangle translated by the given offset.
83  [[nodiscard]] constexpr RoundSuperellipse Shift(Scalar dx, Scalar dy) const {
84  // Just in case, use the factory rather than the internal constructor
85  // as shifting the rectangle may increase/decrease its bit precision
86  // so we should re-validate the radii to the newly located rectangle.
87  return MakeRectRadii(bounds_.Shift(dx, dy), radii_);
88  }
89 
90  /// @brief Returns a round rectangle with expanded edges. Negative expansion
91  /// results in shrinking.
92  [[nodiscard]] constexpr RoundSuperellipse Expand(Scalar left,
93  Scalar top,
94  Scalar right,
95  Scalar bottom) const {
96  // Use the factory rather than the internal constructor as the changing
97  // size of the rectangle requires that we re-validate the radii to the
98  // newly sized rectangle.
99  return MakeRectRadii(bounds_.Expand(left, top, right, bottom), radii_);
100  }
101 
102  /// @brief Returns a round rectangle with expanded edges. Negative expansion
103  /// results in shrinking.
104  [[nodiscard]] constexpr RoundSuperellipse Expand(Scalar horizontal,
105  Scalar vertical) const {
106  // Use the factory rather than the internal constructor as the changing
107  // size of the rectangle requires that we re-validate the radii to the
108  // newly sized rectangle.
109  return MakeRectRadii(bounds_.Expand(horizontal, vertical), radii_);
110  }
111 
112  /// @brief Returns a round rectangle with expanded edges. Negative expansion
113  /// results in shrinking.
114  [[nodiscard]] constexpr RoundSuperellipse Expand(Scalar amount) const {
115  // Use the factory rather than the internal constructor as the changing
116  // size of the rectangle requires that we re-validate the radii to the
117  // newly sized rectangle.
118  return MakeRectRadii(bounds_.Expand(amount), radii_);
119  }
120 
121  [[nodiscard]] constexpr bool operator==(const RoundSuperellipse& rr) const {
122  return bounds_ == rr.bounds_ && radii_ == rr.radii_;
123  }
124 
125  [[nodiscard]] constexpr bool operator!=(const RoundSuperellipse& r) const {
126  return !(*this == r);
127  }
128 
129  // Approximates a rounded superellipse with a round rectangle to the
130  // best practical accuracy.
131  //
132  // This is used for Skia backends, which does not support rounded
133  // superellipses directly, so rendering rounded superellipses
134  // falls back to RRect.
135  [[nodiscard]] RoundRect ToApproximateRoundRect() const;
136 
137  private:
138  constexpr RoundSuperellipse(const Rect& bounds, const RoundingRadii& radii)
139  : bounds_(bounds), radii_(radii) {}
140 
141  Rect bounds_;
142  RoundingRadii radii_;
143 };
144 
145 } // namespace impeller
146 
147 namespace std {
148 
149 inline std::ostream& operator<<(std::ostream& out,
150  const impeller::RoundSuperellipse& rr) {
151  out << "(" //
152  << "rect: " << rr.GetBounds() << ", " //
153  << "radii: " << rr.GetRadii();
154  out << ")";
155  return out;
156 }
157 
158 } // namespace std
159 
160 #endif // FLUTTER_IMPELLER_GEOMETRY_ROUND_SUPERELLIPSE_H_
float Scalar
Definition: scalar.h:18
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:35
Definition: comparable.h:95
std::ostream & operator<<(std::ostream &out, const impeller::Color &c)
Definition: color.h:927
constexpr RoundSuperellipse Expand(Scalar left, Scalar top, Scalar right, Scalar bottom) const
Returns a round rectangle with expanded edges. Negative expansion results in shrinking.
constexpr RoundSuperellipse Expand(Scalar horizontal, Scalar vertical) const
Returns a round rectangle with expanded edges. Negative expansion results in shrinking.
constexpr static RoundSuperellipse MakeRectXY(const Rect &rect, Size corner_radii)
constexpr static RoundSuperellipse MakeOval(const Rect &rect)
constexpr const RoundingRadii & GetRadii() const
static RoundSuperellipse MakeRectRadii(const Rect &rect, const RoundingRadii &radii)
constexpr bool IsOval() const
constexpr static RoundSuperellipse MakeRect(const Rect &rect)
constexpr bool IsFinite() const
constexpr bool IsEmpty() const
constexpr RoundSuperellipse Expand(Scalar amount) const
Returns a round rectangle with expanded edges. Negative expansion results in shrinking.
constexpr bool IsRect() const
constexpr RoundSuperellipse Shift(Scalar dx, Scalar dy) const
Returns a new round rectangle translated by the given offset.
constexpr static RoundSuperellipse MakeRectRadius(const Rect &rect, Scalar radius)
RoundRect ToApproximateRoundRect() const
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.
constexpr 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