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);
158 return MakeLTRB(center.
x - radius, center.
y - radius,
159 center.
x + radius, center.
y + radius);
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),
708 FML_DCHECK(!
transform.HasPerspective2D());
711 if (transform_scaling.
x == 0.0f || transform_scaling.
y == 0.0f) {
715 Size min_local_size =
716 Size(min_transformed_size.
width / transform_scaling.
x,
717 min_transformed_size.
height / transform_scaling.
y);
723 if (current_size.
width >= min_local_size.
width &&
729 Size expanded_size = current_size.
Max(min_local_size);
731 expanded_size.
height * 0.5f));
742 return source.
Shift(-left_, -top_)
750 saturated::Cast<U, Type>(floor(r.GetTop())),
751 saturated::Cast<U, Type>(ceil(r.GetRight())),
752 saturated::Cast<U, Type>(ceil(r.GetBottom())));
758 saturated::Cast<U, Type>(ceil(r.GetTop())),
759 saturated::Cast<U, Type>(floor(r.GetRight())),
760 saturated::Cast<U, Type>(floor(r.GetBottom())));
766 saturated::Cast<U, Type>(round(r.GetTop())),
767 saturated::Cast<U, Type>(round(r.GetRight())),
768 saturated::Cast<U, Type>(round(r.GetBottom())));
772 const std::optional<TRect>
b) {
773 return b.has_value() ? a.
Union(
b.value()) : a;
776 [[nodiscard]] constexpr
static TRect Union(
const std::optional<TRect> a,
778 return a.has_value() ? a->
Union(
b) :
b;
781 [[nodiscard]] constexpr
static std::optional<TRect>
Union(
782 const std::optional<TRect> a,
783 const std::optional<TRect>
b) {
784 return a.has_value() ?
Union(a.value(),
b) :
b;
789 const std::optional<TRect>
b) {
794 const std::optional<TRect> a,
796 return a.has_value() ? a->Intersection(
b) :
b;
800 const std::optional<TRect> a,
801 const std::optional<TRect>
b) {
806 constexpr
TRect(Type left, Type top, Type right, Type bottom)
807 : left_(left), top_(top), right_(right), bottom_(bottom) {}
814 static constexpr
Scalar kMinimumHomogenous = 1.0f / (1 << 14);
825 static constexpr
int ClipAndInsert(
Point clipped[],
829 const Vector3& right) {
830 if (p.z >= kMinimumHomogenous) {
831 clipped[index++] = {p.x / p.z, p.y / p.z};
833 index = InterpolateAndInsert(clipped, index, p, left);
834 index = InterpolateAndInsert(clipped, index, p, right);
842 static constexpr
int InterpolateAndInsert(
Point clipped[],
845 const Vector3& neighbor) {
846 if (neighbor.z >= kMinimumHomogenous) {
847 auto t = (kMinimumHomogenous - p.z) / (neighbor.z - p.z);
849 ((1.0f - t) * p.x + t * neighbor.x) / kMinimumHomogenous,
850 ((1.0f - t) * p.y + t * neighbor.y) / kMinimumHomogenous,
863 #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 std::optional< TRect< T > > ExpandToMinTransformedSize(TSize< T > min_transformed_size, const Matrix &transform) const
Returns a rectangle with edges expanded to satisfy a minimum size in a 2D-transformed coordinate spac...
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 static TRect MakeCircleBounds(const TPoint< Type > ¢er, Type radius)
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 TRect Scale(Type scale) const
constexpr static TRect MakeXYWH(Type x, Type y, Type width, Type height)
constexpr std::enable_if_t< std::is_floating_point_v< FT >, bool > Contains(const TRect< U > &o) const
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 TRect MakeEllipseBounds(const TPoint< Type > ¢er, const TPoint< Type > &radii)
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 static TRect MakeEllipseBounds(const TPoint< Type > ¢er, const TSize< Type > &radii)
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()
constexpr TSize Max(const TSize &o) const
std::vector< Point > points