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) {}
142 return MakeXYWH(origin.
x, origin.
y, size.width, size.height);
147 return TRect(0.0, 0.0, size.width, size.height);
150 template <
typename U>
155 template <
typename Po
intIter>
157 const PointIter last) {
161 auto left = first->x;
163 auto right = first->x;
164 auto bottom = first->y;
165 for (
auto it = first + 1; it < last; ++it) {
167 top = std::min(top, it->y);
169 bottom = std::max(bottom, it->y);
176 std::numeric_limits<Type>::lowest(),
177 std::numeric_limits<Type>::max(),
178 std::numeric_limits<Type>::max());
182 return left_ == r.left_ &&
184 right_ == r.right_ &&
185 bottom_ == r.bottom_;
196 return TRect(left_ * scale_x,
242 (o.
IsEmpty() || (o.left_ >= left_ &&
244 o.right_ <= right_ &&
245 o.bottom_ <= bottom_));
256 return std::isfinite(left_) &&
257 std::isfinite(top_) &&
258 std::isfinite(right_) &&
259 std::isfinite(bottom_);
264 [[nodiscard]]
constexpr bool IsEmpty()
const {
267 return !(left_ < right_ && top_ < bottom_);
278 return !
IsEmpty() && (right_ - left_) == (bottom_ - top_);
288 return {left_, top_};
300 [[nodiscard]]
constexpr Type GetX()
const {
return left_; }
304 [[nodiscard]]
constexpr Type GetY()
const {
return top_; }
309 return saturated::Sub(right_, left_);
315 return saturated::Sub(bottom_, top_);
318 [[nodiscard]]
constexpr auto GetLeft()
const {
return left_; }
320 [[nodiscard]]
constexpr auto GetTop()
const {
return top_; }
322 [[nodiscard]]
constexpr auto GetRight()
const {
return right_; }
324 [[nodiscard]]
constexpr auto GetBottom()
const {
return bottom_; }
327 return {left_, top_};
331 return {right_, top_};
335 return {left_, bottom_};
339 return {right_, bottom_};
343 [[nodiscard]]
constexpr T Area()
const {
346 return IsEmpty() ? 0 : (right_ - left_) * (bottom_ - top_);
351 return {saturated::AverageScalar(left_, right_),
352 saturated::AverageScalar(top_, bottom_)};
355 [[nodiscard]]
constexpr std::array<T, 4>
GetLTRB()
const {
356 return {left_, top_, right_, bottom_};
361 [[nodiscard]]
constexpr std::array<T, 4>
GetXYWH()
const {
371 std::min(left_, right_),
372 std::min(top_, bottom_),
373 std::max(left_, right_),
374 std::max(top_, bottom_),
382 [[nodiscard]]
constexpr std::array<TPoint<T>, 4>
GetPoints()
const {
397 for (
size_t i = 0; i <
points.size(); i++) {
416 auto ul =
transform.TransformHomogenous({left_, top_});
417 auto ur =
transform.TransformHomogenous({right_, top_});
418 auto ll =
transform.TransformHomogenous({left_, bottom_});
419 auto lr =
transform.TransformHomogenous({right_, bottom_});
429 index = ClipAndInsert(
points, index, ll, ul, ur);
430 index = ClipAndInsert(
points, index, ul, ur, lr);
431 index = ClipAndInsert(
points, index, ur, lr, ll);
432 index = ClipAndInsert(
points, index, lr, ll, ul);
435 return bounds.value_or(
TRect{});
446 if (bounds.has_value()) {
447 return bounds.value();
467 if (sx != 0.0 && sy != 0.0 && 0.0 * sx * sy * tx * ty == 0.0) {
469 return Matrix( sx, 0.0f, 0.0f, 0.0f,
470 0.0f, sy, 0.0f, 0.0f,
471 0.0f, 0.0f, 1.0f, 0.0f,
489 std::min(left_, o.left_),
490 std::min(top_, o.top_),
491 std::max(right_, o.right_),
492 std::max(bottom_, o.bottom_),
497 const TRect& o)
const {
500 std::max(left_, o.left_),
501 std::max(top_, o.top_),
502 std::min(right_, o.right_),
503 std::min(bottom_, o.bottom_),
521 [[nodiscard]]
constexpr std::optional<TRect<T>>
Cutout(
const TRect& o)
const {
531 const auto& [a_left, a_top, a_right, a_bottom] =
GetLTRB();
532 const auto& [b_left, b_top, b_right, b_bottom] = o.
GetLTRB();
533 if (b_left <= a_left && b_right >= a_right) {
534 if (b_top <= a_top && b_bottom >= a_bottom) {
538 if (b_top <= a_top && b_bottom > a_top) {
542 if (b_bottom >= a_bottom && b_top < a_bottom) {
547 if (b_top <= a_top && b_bottom >= a_bottom) {
548 if (b_left <= a_left && b_right > a_left) {
552 if (b_right >= a_right && b_left < a_right) {
568 saturated::Add(left_, dx),
569 saturated::Add(top_, dy),
570 saturated::Add(right_, dx),
571 saturated::Add(bottom_, dy),
587 saturated::Sub(left_,
left),
588 saturated::Sub(top_, top),
589 saturated::Add(right_,
right),
590 saturated::Add(bottom_, bottom),
598 saturated::Sub(left_, amount),
599 saturated::Sub(top_, amount),
600 saturated::Add(right_, amount),
601 saturated::Add(bottom_, amount),
608 T vertical_amount)
const {
610 saturated::Sub(left_, horizontal_amount),
611 saturated::Sub(top_, vertical_amount),
612 saturated::Add(right_, horizontal_amount),
613 saturated::Add(bottom_, vertical_amount),
637 return source.Shift(-left_, -top_)
645 saturated::Cast<U, Type>(floor(r.GetTop())),
646 saturated::Cast<U, Type>(ceil(r.GetRight())),
647 saturated::Cast<U, Type>(ceil(r.GetBottom())));
653 saturated::Cast<U, Type>(
round(r.GetTop())),
654 saturated::Cast<U, Type>(
round(r.GetRight())),
655 saturated::Cast<U, Type>(
round(r.GetBottom())));
658 [[nodiscard]]
constexpr static std::optional<TRect>
Union(
660 const std::optional<TRect>
b) {
661 return b.has_value() ?
a.Union(
b.value()) :
a;
664 [[nodiscard]]
constexpr static std::optional<TRect>
Union(
665 const std::optional<TRect>
a,
667 return a.has_value() ?
a->Union(
b) :
b;
670 [[nodiscard]]
constexpr static std::optional<TRect>
Union(
671 const std::optional<TRect>
a,
672 const std::optional<TRect>
b) {
673 return a.has_value() ?
Union(
a.value(),
b) :
b;
678 const std::optional<TRect>
b) {
679 return b.has_value() ?
a.Intersection(
b.value()) :
a;
683 const std::optional<TRect>
a,
685 return a.has_value() ?
a->Intersection(
b) :
b;
689 const std::optional<TRect>
a,
690 const std::optional<TRect>
b) {
696 : left_(
left), top_(top), right_(
right), bottom_(bottom) {}
703 static constexpr Scalar kMinimumHomogenous = 1.0f / (1 << 14);
714 static constexpr int ClipAndInsert(
Point clipped[],
718 const Vector3&
right) {
719 if (p.z >= kMinimumHomogenous) {
720 clipped[index++] = {p.x / p.z, p.y / p.z};
722 index = InterpolateAndInsert(clipped, index, p,
left);
723 index = InterpolateAndInsert(clipped, index, p,
right);
731 static constexpr int InterpolateAndInsert(
Point clipped[],
734 const Vector3& neighbor) {
735 if (neighbor.z >= kMinimumHomogenous) {
736 auto t = (kMinimumHomogenous -
p.z) / (neighbor.z -
p.z);
738 (t *
p.x + (1.0f - t) * neighbor.x) / kMinimumHomogenous,
739 (t *
p.y + (1.0f - t) * neighbor.y) / kMinimumHomogenous,
750#undef ONLY_ON_FLOAT_M
757inline std::ostream&
operator<<(std::ostream& out,
static void round(SkPoint *p)
static const int points[]
static bool left(const SkPoint &p0, const SkPoint &p1)
static bool right(const SkPoint &p0, const SkPoint &p1)
#define FML_UNREACHABLE()
#define ONLY_ON_FLOAT_M(Modifiers, Return)
std::ostream & operator<<(std::ostream &out, const impeller::Color &c)
static SkColor4f transform(SkColor4f c, SkColorSpace *src, SkColorSpace *dst)
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 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
constexpr bool IntersectsWithRect(const TRect &o) const
constexpr auto GetLeft() const
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
static constexpr std::optional< TRect > Union(const TRect &a, const std::optional< TRect > b)
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)
static constexpr std::optional< 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 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< 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)