5 #ifndef FLUTTER_IMPELLER_GEOMETRY_RECT_H_
6 #define FLUTTER_IMPELLER_GEOMETRY_RECT_H_
13 #include "fml/logging.h"
22 #define ONLY_ON_FLOAT_M(Modifiers, Return) \
23 template <typename U = T> \
24 Modifiers std::enable_if_t<std::is_floating_point_v<U>, Return>
25 #define ONLY_ON_FLOAT(Return) DL_ONLY_ON_FLOAT_M(, Return)
127 constexpr
TRect() : left_(0), top_(0), right_(0), bottom_(0) {}
133 return TRect(left, top, right, bottom);
137 return TRect(
x, y, saturated::Add(
x, width), saturated::Add(y, height));
141 return TRect(0, 0, width, height);
156 template <
class U,
class FT = T>
157 constexpr
static std::enable_if_t<std::is_floating_point_v<FT>,
TRect>
Make(
160 static_cast<FT
>(rect.
GetLeft()),
static_cast<FT
>(rect.
GetTop()),
164 template <
typename U>
169 template <
typename Po
intIter>
171 const PointIter last) {
175 auto left = first->x;
177 auto right = first->x;
178 auto bottom = first->y;
179 for (
auto it = first + 1; it < last; ++it) {
180 left = std::min(left, it->x);
181 top = std::min(top, it->y);
182 right = std::max(right, it->x);
183 bottom = std::max(bottom, it->y);
190 std::numeric_limits<Type>::lowest(),
191 std::numeric_limits<Type>::max(),
192 std::numeric_limits<Type>::max());
196 return left_ == r.left_ &&
198 right_ == r.right_ &&
199 bottom_ == r.bottom_;
203 return !(*
this == r);
207 return TRect(left_ * scale,
213 [[nodiscard]] constexpr
TRect Scale(Type scale_x, Type scale_y)
const {
214 return TRect(left_ * scale_x,
221 return Scale(scale.
x, scale.
y);
279 (o.
IsEmpty() || (o.left_ >= left_ &&
281 o.right_ <= right_ &&
282 o.bottom_ <= bottom_));
293 return std::isfinite(left_) &&
294 std::isfinite(top_) &&
295 std::isfinite(right_) &&
296 std::isfinite(bottom_);
301 [[nodiscard]] constexpr
bool IsEmpty()
const {
304 return !(left_ < right_ && top_ < bottom_);
315 return !
IsEmpty() && (right_ - left_) == (bottom_ - top_);
325 return {left_, top_};
337 [[nodiscard]] constexpr Type
GetX()
const {
return left_; }
341 [[nodiscard]] constexpr Type
GetY()
const {
return top_; }
346 return saturated::Sub(right_, left_);
352 return saturated::Sub(bottom_, top_);
355 [[nodiscard]] constexpr
auto GetLeft()
const {
return left_; }
357 [[nodiscard]] constexpr
auto GetTop()
const {
return top_; }
359 [[nodiscard]] constexpr
auto GetRight()
const {
return right_; }
361 [[nodiscard]] constexpr
auto GetBottom()
const {
return bottom_; }
364 return {left_, top_};
368 return {right_, top_};
372 return {left_, bottom_};
376 return {right_, bottom_};
380 [[nodiscard]] constexpr T
Area()
const {
382 return IsEmpty() ? 0 : (right_ - left_) * (bottom_ - top_);
387 return {saturated::AverageScalar(left_, right_),
388 saturated::AverageScalar(top_, bottom_)};
391 [[nodiscard]] constexpr std::array<T, 4>
GetLTRB()
const {
392 return {left_, top_, right_, bottom_};
397 [[nodiscard]] constexpr std::array<T, 4>
GetXYWH()
const {
407 std::min(left_, right_),
408 std::min(top_, bottom_),
409 std::max(left_, right_),
410 std::max(top_, bottom_),
418 [[nodiscard]] constexpr std::array<TPoint<T>, 4>
GetPoints()
const {
433 for (
size_t i = 0; i <
points.size(); i++) {
452 auto ul =
transform.TransformHomogenous({left_, top_});
453 auto ur =
transform.TransformHomogenous({right_, top_});
454 auto ll =
transform.TransformHomogenous({left_, bottom_});
455 auto lr =
transform.TransformHomogenous({right_, bottom_});
465 index = ClipAndInsert(
points, index, ll, ul, ur);
466 index = ClipAndInsert(
points, index, ul, ur, lr);
467 index = ClipAndInsert(
points, index, ur, lr, ll);
468 index = ClipAndInsert(
points, index, lr, ll, ul);
471 return bounds.value_or(
TRect{});
482 if (bounds.has_value()) {
483 return bounds.value();
503 if (sx != 0.0 && sy != 0.0 && 0.0 * sx * sy * tx * ty == 0.0) {
505 return Matrix( sx, 0.0f, 0.0f, 0.0f,
506 0.0f, sy, 0.0f, 0.0f,
507 0.0f, 0.0f, 1.0f, 0.0f,
525 std::min(left_, o.left_),
526 std::min(top_, o.top_),
527 std::max(right_, o.right_),
528 std::max(bottom_, o.bottom_),
533 const TRect& o)
const {
536 std::max(left_, o.left_),
537 std::max(top_, o.top_),
538 std::min(right_, o.right_),
539 std::min(bottom_, o.bottom_),
561 [[nodiscard]] constexpr std::optional<TRect<T>>
Cutout(
const TRect& o)
const {
571 const auto& [a_left, a_top, a_right, a_bottom] =
GetLTRB();
572 const auto& [b_left, b_top, b_right, b_bottom] = o.
GetLTRB();
573 if (b_left <= a_left && b_right >= a_right) {
574 if (b_top <= a_top && b_bottom >= a_bottom) {
578 if (b_top <= a_top && b_bottom > a_top) {
582 if (b_bottom >= a_bottom && b_top < a_bottom) {
587 if (b_top <= a_top && b_bottom >= a_bottom) {
588 if (b_left <= a_left && b_right > a_left) {
592 if (b_right >= a_right && b_left < a_right) {
608 saturated::Add(left_, dx),
609 saturated::Add(top_, dy),
610 saturated::Add(right_, dx),
611 saturated::Add(bottom_, dy),
617 return Shift(offset.
x, offset.
y);
627 saturated::Sub(left_, left),
628 saturated::Sub(top_, top),
629 saturated::Add(right_, right),
630 saturated::Add(bottom_, bottom),
638 saturated::Sub(left_, amount),
639 saturated::Sub(top_, amount),
640 saturated::Add(right_, amount),
641 saturated::Add(bottom_, amount),
648 T vertical_amount)
const {
650 saturated::Sub(left_, horizontal_amount),
651 saturated::Sub(top_, vertical_amount),
652 saturated::Add(right_, horizontal_amount),
653 saturated::Add(bottom_, vertical_amount),
677 return source.
Shift(-left_, -top_)
685 saturated::Cast<U, Type>(floor(r.GetTop())),
686 saturated::Cast<U, Type>(ceil(r.GetRight())),
687 saturated::Cast<U, Type>(ceil(r.GetBottom())));
693 saturated::Cast<U, Type>(ceil(r.GetTop())),
694 saturated::Cast<U, Type>(floor(r.GetRight())),
695 saturated::Cast<U, Type>(floor(r.GetBottom())));
701 saturated::Cast<U, Type>(round(r.GetTop())),
702 saturated::Cast<U, Type>(round(r.GetRight())),
703 saturated::Cast<U, Type>(round(r.GetBottom())));
707 const std::optional<TRect>
b) {
708 return b.has_value() ? a.
Union(
b.value()) : a;
711 [[nodiscard]] constexpr
static TRect Union(
const std::optional<TRect> a,
713 return a.has_value() ? a->
Union(
b) :
b;
716 [[nodiscard]] constexpr
static std::optional<TRect>
Union(
717 const std::optional<TRect> a,
718 const std::optional<TRect>
b) {
719 return a.has_value() ?
Union(a.value(),
b) :
b;
724 const std::optional<TRect>
b) {
729 const std::optional<TRect> a,
731 return a.has_value() ? a->Intersection(
b) :
b;
735 const std::optional<TRect> a,
736 const std::optional<TRect>
b) {
741 constexpr
TRect(Type left, Type top, Type right, Type bottom)
742 : left_(left), top_(top), right_(right), bottom_(bottom) {}
749 static constexpr
Scalar kMinimumHomogenous = 1.0f / (1 << 14);
760 static constexpr
int ClipAndInsert(
Point clipped[],
764 const Vector3& right) {
765 if (p.z >= kMinimumHomogenous) {
766 clipped[index++] = {p.x / p.z, p.y / p.z};
768 index = InterpolateAndInsert(clipped, index, p, left);
769 index = InterpolateAndInsert(clipped, index, p, right);
777 static constexpr
int InterpolateAndInsert(
Point clipped[],
780 const Vector3& neighbor) {
781 if (neighbor.z >= kMinimumHomogenous) {
782 auto t = (kMinimumHomogenous - p.z) / (neighbor.z - p.z);
784 (t * p.x + (1.0f - t) * neighbor.x) / kMinimumHomogenous,
785 (t * p.y + (1.0f - t) * neighbor.y) / kMinimumHomogenous,
798 #undef ONLY_ON_FLOAT_M
std::ostream & operator<<(std::ostream &out, const impeller::Arc &a)
#define ONLY_ON_FLOAT_M(Modifiers, Return)
A 4x4 matrix using column-major storage.
static constexpr Matrix MakeScale(const Vector3 &s)
constexpr TRect< T > Expand(T left, T top, T right, T bottom) const
Returns a rectangle with expanded edges. Negative expansion results in shrinking.
constexpr auto GetBottom() const
constexpr Type GetY() const
Returns the Y coordinate of the upper left corner, equivalent to |GetOrigin().y|.
constexpr TRect TransformBounds(const Matrix &transform) const
Creates a new bounding box that contains this transformed rectangle.
constexpr TRect< T > Project(TRect< T > source) const
Returns a new rectangle that represents the projection of the source rectangle onto this rectangle....
constexpr bool ContainsInclusive(const TPoint< Type > &p) const
Returns true iff the provided point |p| is inside the closed-range interior of this rectangle.
constexpr auto GetTop() const
constexpr Type GetHeight() const
Returns the height of the rectangle, equivalent to |GetSize().height|.
constexpr TPoint< Type > GetOrigin() const
Returns the upper left corner of the rectangle as specified by the left/top or x/y values when it was...
constexpr TRect Scale(TPoint< T > scale) const
constexpr TRect< T > Expand(TPoint< T > amount) const
Returns a rectangle with expanded edges in all directions. Negative expansion results in shrinking.
constexpr bool IsMaximum() const
constexpr std::optional< TRect > Intersection(const TRect &o) const
constexpr bool IsEmpty() const
Returns true if either of the width or height are 0, negative, or NaN.
constexpr T Area() const
Get the area of the rectangle, equivalent to |GetSize().Area()|.
constexpr static TRect MakeOriginSize(const TPoint< Type > &origin, const TSize< Type > &size)
constexpr bool Contains(const TPoint< Type > &p) const
Returns true iff the provided point |p| is inside the half-open interior of this rectangle.
constexpr static TRect Union(const TRect &a, const std::optional< TRect > b)
constexpr TRect Union(const TRect &o) const
constexpr TRect Scale(Type scale_x, Type scale_y) const
constexpr std::array< TPoint< T >, 4 > GetPoints() const
Get the points that represent the 4 corners of this rectangle in a Z order that is compatible with tr...
constexpr bool IntersectsWithRect(const TRect &o) const
constexpr auto GetLeft() const
RoundIn(const TRect< U > &r)
constexpr TRect CutoutOrEmpty(const TRect &o) const
constexpr static TRect MakeWH(Type width, Type height)
constexpr static std::optional< TRect > MakePointBounds(const U &value)
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...
constexpr TRect< T > Expand(T horizontal_amount, T vertical_amount) const
Returns a rectangle with expanded edges in all directions. Negative expansion results in shrinking.
Round(const TRect< U > &r)
RoundOut(const TRect< U > &r)
constexpr TRect GetPositive() const
Get a version of this rectangle that has a non-negative size.
constexpr TRect Scale(TSize< T > scale) const
constexpr Type GetX() const
Returns the X coordinate of the upper left corner, equivalent to |GetOrigin().x|.
constexpr auto GetRight() const
constexpr bool IsSquare() const
Returns true if width and height are equal and neither is NaN.
constexpr static std::optional< TRect > Intersection(const std::optional< TRect > a, const std::optional< TRect > b)
constexpr bool Contains(const TRect &o) const
Returns true iff this rectangle is not empty and it also contains every point considered inside the p...
IsFinite() const
Returns true if all of the fields of this floating point rectangle are finite.
constexpr Matrix GetNormalizingTransform() const
Constructs a Matrix that will map all points in the coordinate space of the rectangle into a new norm...
constexpr static std::optional< TRect > Union(const std::optional< TRect > a, const std::optional< TRect > b)
constexpr bool operator!=(const TRect &r) const
constexpr TRect Scale(Type scale) const
constexpr static TRect MakeXYWH(Type x, Type y, Type width, Type height)
constexpr TPoint< T > GetLeftBottom() const
constexpr std::array< TPoint< T >, 4 > GetTransformedPoints(const Matrix &transform) const
constexpr TRect TransformAndClipBounds(const Matrix &transform) const
Creates a new bounding box that contains this transformed rectangle, clipped against the near clippin...
constexpr static TRect Union(const std::optional< TRect > a, const TRect &b)
constexpr TRect< T > Shift(TPoint< T > offset) const
Returns a new rectangle translated by the given offset.
constexpr TPoint< T > GetRightTop() const
constexpr TRect< T > Expand(T amount) const
Returns a rectangle with expanded edges in all directions. Negative expansion results in shrinking.
constexpr static std::optional< TRect > MakePointBounds(const PointIter first, const PointIter last)
constexpr TRect< T > Shift(T dx, T dy) const
Returns a new rectangle translated by the given offset.
constexpr static TRect MakeSize(const TSize< U > &size)
constexpr Type GetWidth() const
Returns the width of the rectangle, equivalent to |GetSize().width|.
constexpr TPoint< T > GetRightBottom() const
constexpr std::array< T, 4 > GetLTRB() const
constexpr static std::enable_if_t< std::is_floating_point_v< FT >, TRect > Make(const TRect< U > &rect)
constexpr TRect< T > Expand(TSize< T > amount) const
Returns a rectangle with expanded edges in all directions. Negative expansion results in shrinking.
constexpr static std::optional< TRect > Intersection(const TRect &a, const std::optional< TRect > b)
constexpr Point GetCenter() const
Get the center point as a |Point|.
constexpr TRect IntersectionOrEmpty(const TRect &o) const
constexpr static std::optional< TRect > Intersection(const std::optional< TRect > a, const TRect &b)
constexpr std::optional< TRect< T > > Cutout(const TRect &o) const
Returns the new boundary rectangle that would result from this rectangle being cut out by the specifi...
constexpr TPoint< T > GetLeftTop() const
constexpr bool operator==(const TRect &r) const
constexpr std::array< T, 4 > GetXYWH() const
Get the x, y coordinates of the origin and the width and height of the rectangle in an array.
constexpr static TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
constexpr static TRect MakeMaximum()
std::vector< Point > points