5#ifndef FLUTTER_IMPELLER_GEOMETRY_RECT_H_
6#define FLUTTER_IMPELLER_GEOMETRY_RECT_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);
146 return MakeXYWH(origin.
x, origin.
y, size.width, size.height);
151 return TRect(0.0, 0.0, size.width, size.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 TRect(left_ * scale,
209 [[nodiscard]]
constexpr TRect Scale(Type scale_x, Type scale_y)
const {
210 return TRect(left_ * scale_x,
217 return Scale(scale.
x, scale.
y);
275 (o.
IsEmpty() || (o.left_ >= left_ &&
277 o.right_ <= right_ &&
278 o.bottom_ <= bottom_));
289 return std::isfinite(left_) &&
290 std::isfinite(top_) &&
291 std::isfinite(right_) &&
292 std::isfinite(bottom_);
297 [[nodiscard]]
constexpr bool IsEmpty()
const {
300 return !(left_ < right_ && top_ < bottom_);
311 return !
IsEmpty() && (right_ - left_) == (bottom_ - top_);
321 return {left_, top_};
333 [[nodiscard]]
constexpr Type
GetX()
const {
return left_; }
337 [[nodiscard]]
constexpr Type
GetY()
const {
return top_; }
342 return saturated::Sub(right_, left_);
348 return saturated::Sub(bottom_, top_);
351 [[nodiscard]]
constexpr auto GetLeft()
const {
return left_; }
353 [[nodiscard]]
constexpr auto GetTop()
const {
return top_; }
355 [[nodiscard]]
constexpr auto GetRight()
const {
return right_; }
357 [[nodiscard]]
constexpr auto GetBottom()
const {
return bottom_; }
360 return {left_, top_};
364 return {right_, top_};
368 return {left_, bottom_};
372 return {right_, bottom_};
376 [[nodiscard]]
constexpr T
Area()
const {
378 return IsEmpty() ? 0 : (right_ - left_) * (bottom_ - top_);
383 return {saturated::AverageScalar(left_, right_),
384 saturated::AverageScalar(top_, bottom_)};
387 [[nodiscard]]
constexpr std::array<T, 4>
GetLTRB()
const {
388 return {left_, top_, right_, bottom_};
393 [[nodiscard]]
constexpr std::array<T, 4>
GetXYWH()
const {
403 std::min(left_, right_),
404 std::min(top_, bottom_),
405 std::max(left_, right_),
406 std::max(top_, bottom_),
414 [[nodiscard]]
constexpr std::array<TPoint<T>, 4>
GetPoints()
const {
429 for (
size_t i = 0;
i <
points.size();
i++) {
448 auto ul =
transform.TransformHomogenous({left_, top_});
449 auto ur =
transform.TransformHomogenous({right_, top_});
450 auto ll =
transform.TransformHomogenous({left_, bottom_});
451 auto lr =
transform.TransformHomogenous({right_, bottom_});
461 index = ClipAndInsert(
points, index, ll, ul, ur);
462 index = ClipAndInsert(
points, index, ul, ur, lr);
463 index = ClipAndInsert(
points, index, ur, lr, ll);
464 index = ClipAndInsert(
points, index, lr, ll, ul);
467 return bounds.value_or(
TRect{});
478 if (bounds.has_value()) {
479 return bounds.value();
499 if (sx != 0.0 && sy != 0.0 && 0.0 * sx * sy * tx * ty == 0.0) {
501 return Matrix( sx, 0.0f, 0.0f, 0.0f,
502 0.0f, sy, 0.0f, 0.0f,
503 0.0f, 0.0f, 1.0f, 0.0f,
521 std::min(left_, o.left_),
522 std::min(top_, o.top_),
523 std::max(right_, o.right_),
524 std::max(bottom_, o.bottom_),
529 const TRect& o)
const {
532 std::max(left_, o.left_),
533 std::max(top_, o.top_),
534 std::min(right_, o.right_),
535 std::min(bottom_, o.bottom_),
557 [[nodiscard]]
constexpr std::optional<TRect<T>>
Cutout(
const TRect& o)
const {
567 const auto& [a_left, a_top, a_right, a_bottom] =
GetLTRB();
568 const auto& [b_left, b_top, b_right, b_bottom] = o.
GetLTRB();
569 if (b_left <= a_left && b_right >= a_right) {
570 if (b_top <= a_top && b_bottom >= a_bottom) {
574 if (b_top <= a_top && b_bottom > a_top) {
578 if (b_bottom >= a_bottom && b_top < a_bottom) {
583 if (b_top <= a_top && b_bottom >= a_bottom) {
584 if (b_left <= a_left && b_right > a_left) {
588 if (b_right >= a_right && b_left < a_right) {
604 saturated::Add(left_, dx),
605 saturated::Add(top_, dy),
606 saturated::Add(right_, dx),
607 saturated::Add(bottom_, dy),
613 return Shift(offset.
x, offset.
y);
623 saturated::Sub(left_, left),
624 saturated::Sub(top_, top),
625 saturated::Add(right_, right),
626 saturated::Add(bottom_, bottom),
634 saturated::Sub(left_, amount),
635 saturated::Sub(top_, amount),
636 saturated::Add(right_, amount),
637 saturated::Add(bottom_, amount),
644 T vertical_amount)
const {
646 saturated::Sub(left_, horizontal_amount),
647 saturated::Sub(top_, vertical_amount),
648 saturated::Add(right_, horizontal_amount),
649 saturated::Add(bottom_, vertical_amount),
673 return source.
Shift(-left_, -top_)
681 saturated::Cast<U, Type>(floor(r.GetTop())),
682 saturated::Cast<U, Type>(ceil(r.GetRight())),
683 saturated::Cast<U, Type>(ceil(r.GetBottom())));
689 saturated::Cast<U, Type>(ceil(r.GetTop())),
690 saturated::Cast<U, Type>(floor(r.GetRight())),
691 saturated::Cast<U, Type>(floor(r.GetBottom())));
697 saturated::Cast<U, Type>(round(r.GetTop())),
698 saturated::Cast<U, Type>(round(r.GetRight())),
699 saturated::Cast<U, Type>(round(r.GetBottom())));
703 const std::optional<TRect> b) {
704 return b.has_value() ? a.
Union(b.value()) : a;
707 [[nodiscard]]
constexpr static TRect Union(
const std::optional<TRect> a,
709 return a.has_value() ? a->
Union(b) : b;
712 [[nodiscard]]
constexpr static std::optional<TRect>
Union(
713 const std::optional<TRect> a,
714 const std::optional<TRect> b) {
715 return a.has_value() ?
Union(a.value(), b) : b;
720 const std::optional<TRect> b) {
725 const std::optional<TRect> a,
727 return a.has_value() ? a->Intersection(b) : b;
731 const std::optional<TRect> a,
732 const std::optional<TRect> b) {
737 constexpr TRect(Type left, Type top, Type right, Type bottom)
738 : left_(left), top_(top), right_(right), bottom_(bottom) {}
745 static constexpr Scalar kMinimumHomogenous = 1.0f / (1 << 14);
756 static constexpr int ClipAndInsert(
Point clipped[],
760 const Vector3& right) {
761 if (p.z >= kMinimumHomogenous) {
762 clipped[index++] = {p.x / p.z, p.y / p.z};
764 index = InterpolateAndInsert(clipped, index, p, left);
765 index = InterpolateAndInsert(clipped, index, p, right);
773 static constexpr int InterpolateAndInsert(
Point clipped[],
776 const Vector3& neighbor) {
777 if (neighbor.z >= kMinimumHomogenous) {
778 auto t = (kMinimumHomogenous - p.z) / (neighbor.z - p.z);
780 (t * p.x + (1.0f - t) * neighbor.x) / kMinimumHomogenous,
781 (t * p.y + (1.0f - t) * neighbor.y) / kMinimumHomogenous,
794#undef ONLY_ON_FLOAT_M
801inline std::ostream&
operator<<(std::ostream& out,
#define FML_UNREACHABLE()
#define ONLY_ON_FLOAT_M(Modifiers, Return)
std::ostream & operator<<(std::ostream &out, const impeller::Arc &a)
A 4x4 matrix using column-major storage.
static constexpr Matrix MakeScale(const Vector3 &s)
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 bool ContainsInclusive(const TPoint< Type > &p) const
Returns true iff the provided point |p| is inside the closed-range interior of this rectangle.
static constexpr TRect MakeWH(Type width, Type height)
static constexpr TRect Union(const TRect &a, const std::optional< TRect > b)
constexpr auto GetTop() 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 std::optional< TRect > Intersection(const TRect &o) const
constexpr TRect< T > Project(TRect< T > source) const
Returns a new rectangle that represents the projection of the source rectangle onto this rectangle....
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 Type GetHeight() const
Returns the height of the rectangle, equivalent to |GetSize().height|.
static constexpr std::optional< TRect > Union(const std::optional< TRect > a, const std::optional< 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 TRect Scale(TPoint< T > scale) const
constexpr bool IsMaximum() 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 bool Contains(const TPoint< Type > &p) const
Returns true iff the provided point |p| is inside the half-open interior of this rectangle.
static constexpr std::optional< TRect > MakePointBounds(const PointIter first, const PointIter last)
constexpr TRect Union(const TRect &o) const
constexpr TRect Scale(Type scale_x, Type scale_y) const
static constexpr std::enable_if_t< std::is_floating_point_v< FT >, TRect > Make(const TRect< U > &rect)
constexpr bool IntersectsWithRect(const TRect &o) const
constexpr auto GetLeft() const
RoundIn(const TRect< U > &r)
constexpr TRect CutoutOrEmpty(const TRect &o) const
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.
constexpr TPoint< T > GetLeftTop() const
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.
static constexpr std::optional< TRect > Intersection(const TRect &a, const std::optional< TRect > b)
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 std::array< T, 4 > GetLTRB() const
static constexpr TRect MakeOriginSize(const TPoint< Type > &origin, const TSize< Type > &size)
constexpr auto GetRight() const
constexpr bool IsSquare() const
Returns true if width and height are equal and neither is NaN.
static constexpr TRect MakeXYWH(Type x, Type y, Type width, Type height)
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 TRect Scale(Type scale) 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 TPoint< T > GetRightBottom() const
static constexpr std::optional< TRect > Intersection(const std::optional< TRect > a, const std::optional< TRect > b)
constexpr TPoint< T > GetLeftBottom() const
static constexpr TRect MakeSize(const TSize< U > &size)
constexpr TRect< T > Shift(TPoint< T > offset) const
Returns a new rectangle translated by the given offset.
constexpr Type GetWidth() const
Returns the width of the rectangle, equivalent to |GetSize().width|.
static constexpr std::optional< TRect > Intersection(const std::optional< TRect > a, const TRect &b)
constexpr TPoint< T > GetRightTop() const
static constexpr std::optional< TRect > MakePointBounds(const U &value)
constexpr TRect< T > Expand(T left, T top, T right, T bottom) const
Returns a rectangle with expanded edges. Negative expansion results in shrinking.
static constexpr TRect MakeMaximum()
constexpr Point GetCenter() const
Get the center point as a |Point|.
constexpr TRect IntersectionOrEmpty(const TRect &o) const
constexpr TRect< T > Expand(TSize< T > amount) const
Returns a rectangle with expanded edges in all directions. Negative expansion results in shrinking.
constexpr bool operator==(const TRect &r) const
constexpr TRect< T > Expand(T amount) const
Returns a rectangle with expanded edges in all directions. Negative expansion results in shrinking.
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 TRect< T > Shift(T dx, T dy) const
Returns a new rectangle translated by the given offset.
constexpr TRect< T > Expand(TPoint< T > amount) const
Returns a rectangle with expanded edges in all directions. Negative expansion results in shrinking.
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...
static constexpr TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
static constexpr TRect Union(const std::optional< TRect > a, const TRect &b)
std::vector< Point > points