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);
158 return MakeLTRB(center.x - radius, center.y - radius,
159 center.x + radius, center.y + radius);
174 return MakeLTRB(center.x - radii.
x, center.y - radii.
y,
175 center.x + radii.
x, center.y + radii.
y);
180 template <
class U,
class FT = T>
181 constexpr static std::enable_if_t<std::is_floating_point_v<FT>,
TRect>
Make(
184 static_cast<FT
>(rect.
GetLeft()),
static_cast<FT
>(rect.
GetTop()),
188 template <
typename U>
193 template <
typename Po
intIter>
195 const PointIter last) {
199 auto left = first->x;
201 auto right = first->x;
202 auto bottom = first->y;
203 for (
auto it = first + 1; it < last; ++it) {
204 left = std::min(left, it->x);
205 top = std::min(top, it->y);
206 right = std::max(right, it->x);
207 bottom = std::max(bottom, it->y);
214 std::numeric_limits<Type>::lowest(),
215 std::numeric_limits<Type>::max(),
216 std::numeric_limits<Type>::max());
220 return left_ == r.left_ &&
222 right_ == r.right_ &&
223 bottom_ == r.bottom_;
227 return TRect(left_ * scale,
233 [[nodiscard]]
constexpr TRect Scale(Type scale_x, Type scale_y)
const {
234 return TRect(left_ * scale_x,
241 return Scale(scale.
x, scale.
y);
299 (o.
IsEmpty() || (o.left_ >= left_ &&
301 o.right_ <= right_ &&
302 o.bottom_ <= bottom_));
305 template <
class U,
class FT = T>
306 [[nodiscard]]
constexpr std::enable_if_t<std::is_floating_point_v<FT>,
bool>
323 return std::isfinite(left_) &&
324 std::isfinite(top_) &&
325 std::isfinite(right_) &&
326 std::isfinite(bottom_);
331 [[nodiscard]]
constexpr bool IsEmpty()
const {
334 return !(left_ < right_ && top_ < bottom_);
345 return !
IsEmpty() && (right_ - left_) == (bottom_ - top_);
355 return {left_, top_};
367 [[nodiscard]]
constexpr Type
GetX()
const {
return left_; }
371 [[nodiscard]]
constexpr Type
GetY()
const {
return top_; }
376 return saturated::Sub(right_, left_);
382 return saturated::Sub(bottom_, top_);
385 [[nodiscard]]
constexpr auto GetLeft()
const {
return left_; }
387 [[nodiscard]]
constexpr auto GetTop()
const {
return top_; }
389 [[nodiscard]]
constexpr auto GetRight()
const {
return right_; }
391 [[nodiscard]]
constexpr auto GetBottom()
const {
return bottom_; }
394 return {left_, top_};
398 return {right_, top_};
402 return {left_, bottom_};
406 return {right_, bottom_};
410 [[nodiscard]]
constexpr T
Area()
const {
412 return IsEmpty() ? 0 : (right_ - left_) * (bottom_ - top_);
417 return {saturated::AverageScalar(left_, right_),
418 saturated::AverageScalar(top_, bottom_)};
421 [[nodiscard]]
constexpr std::array<T, 4>
GetLTRB()
const {
422 return {left_, top_, right_, bottom_};
427 [[nodiscard]]
constexpr std::array<T, 4>
GetXYWH()
const {
437 std::min(left_, right_),
438 std::min(top_, bottom_),
439 std::max(left_, right_),
440 std::max(top_, bottom_),
448 [[nodiscard]]
constexpr std::array<TPoint<T>, 4>
GetPoints()
const {
463 for (
size_t i = 0;
i <
points.size();
i++) {
482 auto ul =
transform.TransformHomogenous({left_, top_});
483 auto ur =
transform.TransformHomogenous({right_, top_});
484 auto ll =
transform.TransformHomogenous({left_, bottom_});
485 auto lr =
transform.TransformHomogenous({right_, bottom_});
495 index = ClipAndInsert(
points, index, ll, ul, ur);
496 index = ClipAndInsert(
points, index, ul, ur, lr);
497 index = ClipAndInsert(
points, index, ur, lr, ll);
498 index = ClipAndInsert(
points, index, lr, ll, ul);
501 return bounds.value_or(
TRect{});
512 if (bounds.has_value()) {
513 return bounds.value();
533 if (sx != 0.0 && sy != 0.0 && 0.0 * sx * sy * tx * ty == 0.0) {
535 return Matrix( sx, 0.0f, 0.0f, 0.0f,
536 0.0f, sy, 0.0f, 0.0f,
537 0.0f, 0.0f, 1.0f, 0.0f,
555 std::min(left_, o.left_),
556 std::min(top_, o.top_),
557 std::max(right_, o.right_),
558 std::max(bottom_, o.bottom_),
563 const TRect& o)
const {
566 std::max(left_, o.left_),
567 std::max(top_, o.top_),
568 std::min(right_, o.right_),
569 std::min(bottom_, o.bottom_),
591 [[nodiscard]]
constexpr std::optional<TRect<T>>
Cutout(
const TRect& o)
const {
601 const auto& [a_left, a_top, a_right, a_bottom] =
GetLTRB();
602 const auto& [b_left, b_top, b_right, b_bottom] = o.
GetLTRB();
603 if (b_left <= a_left && b_right >= a_right) {
604 if (b_top <= a_top && b_bottom >= a_bottom) {
608 if (b_top <= a_top && b_bottom > a_top) {
612 if (b_bottom >= a_bottom && b_top < a_bottom) {
617 if (b_top <= a_top && b_bottom >= a_bottom) {
618 if (b_left <= a_left && b_right > a_left) {
622 if (b_right >= a_right && b_left < a_right) {
638 saturated::Add(left_, dx),
639 saturated::Add(top_, dy),
640 saturated::Add(right_, dx),
641 saturated::Add(bottom_, dy),
647 return Shift(offset.
x, offset.
y);
657 saturated::Sub(left_, left),
658 saturated::Sub(top_, top),
659 saturated::Add(right_, right),
660 saturated::Add(bottom_, bottom),
668 saturated::Sub(left_, amount),
669 saturated::Sub(top_, amount),
670 saturated::Add(right_, amount),
671 saturated::Add(bottom_, amount),
678 T vertical_amount)
const {
680 saturated::Sub(left_, horizontal_amount),
681 saturated::Sub(top_, vertical_amount),
682 saturated::Add(right_, horizontal_amount),
683 saturated::Add(bottom_, vertical_amount),
707 return source.
Shift(-left_, -top_)
715 saturated::Cast<U, Type>(floor(r.GetTop())),
716 saturated::Cast<U, Type>(ceil(r.GetRight())),
717 saturated::Cast<U, Type>(ceil(r.GetBottom())));
723 saturated::Cast<U, Type>(ceil(r.GetTop())),
724 saturated::Cast<U, Type>(floor(r.GetRight())),
725 saturated::Cast<U, Type>(floor(r.GetBottom())));
731 saturated::Cast<U, Type>(round(r.GetTop())),
732 saturated::Cast<U, Type>(round(r.GetRight())),
733 saturated::Cast<U, Type>(round(r.GetBottom())));
737 const std::optional<TRect> b) {
738 return b.has_value() ? a.
Union(b.value()) : a;
741 [[nodiscard]]
constexpr static TRect Union(
const std::optional<TRect> a,
743 return a.has_value() ? a->
Union(b) : b;
746 [[nodiscard]]
constexpr static std::optional<TRect>
Union(
747 const std::optional<TRect> a,
748 const std::optional<TRect> b) {
749 return a.has_value() ?
Union(a.value(), b) : b;
754 const std::optional<TRect> b) {
759 const std::optional<TRect> a,
761 return a.has_value() ? a->Intersection(b) : b;
765 const std::optional<TRect> a,
766 const std::optional<TRect> b) {
771 constexpr TRect(Type left, Type top, Type right, Type bottom)
772 : left_(left), top_(top), right_(right), bottom_(bottom) {}
779 static constexpr Scalar kMinimumHomogenous = 1.0f / (1 << 14);
790 static constexpr int ClipAndInsert(
Point clipped[],
794 const Vector3& right) {
795 if (p.z >= kMinimumHomogenous) {
796 clipped[index++] = {p.x / p.z, p.y / p.z};
798 index = InterpolateAndInsert(clipped, index, p, left);
799 index = InterpolateAndInsert(clipped, index, p, right);
807 static constexpr int InterpolateAndInsert(
Point clipped[],
810 const Vector3& neighbor) {
811 if (neighbor.z >= kMinimumHomogenous) {
812 auto t = (kMinimumHomogenous - p.z) / (neighbor.z - p.z);
814 ((1.0f - t) * p.x + t * neighbor.x) / kMinimumHomogenous,
815 ((1.0f - t) * p.y + t * neighbor.y) / kMinimumHomogenous,
828#undef ONLY_ON_FLOAT_M
835inline 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 MakeEllipseBounds(const TPoint< Type > ¢er, const TSize< Type > &radii)
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...
static constexpr TRect MakeCircleBounds(const TPoint< Type > ¢er, Type radius)
constexpr TRect Scale(Type scale) const
constexpr std::array< TPoint< T >, 4 > GetTransformedPoints(const Matrix &transform) const
static constexpr TRect MakeEllipseBounds(const TPoint< Type > ¢er, const TPoint< Type > &radii)
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 std::enable_if_t< std::is_floating_point_v< FT >, bool > Contains(const TRect< U > &o) const
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