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));
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) {
166 left = std::min(left, it->x);
167 top = std::min(top, it->y);
168 right = std::max(right, it->x);
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_;
195 [[nodiscard]] constexpr
TRect Scale(Type scale_x, Type scale_y)
const {
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 {
395 const Matrix& transform)
const {
397 for (
size_t i = 0; i < points.size(); i++) {
398 points[i] = transform * points[i];
411 if (bounds.has_value()) {
412 return bounds.value();
432 if (sx != 0.0 && sy != 0.0 && 0.0 * sx * sy * tx * ty == 0.0) {
434 return Matrix( sx, 0.0f, 0.0f, 0.0f,
435 0.0f, sy, 0.0f, 0.0f,
436 0.0f, 0.0f, 1.0f, 0.0f,
454 std::min(left_, o.left_),
455 std::min(top_, o.top_),
456 std::max(right_, o.right_),
457 std::max(bottom_, o.bottom_),
462 const TRect& o)
const {
465 std::max(left_, o.left_),
466 std::max(top_, o.top_),
467 std::min(right_, o.right_),
468 std::min(bottom_, o.bottom_),
486 [[nodiscard]] constexpr std::optional<TRect<T>>
Cutout(
const TRect& o)
const {
496 const auto& [a_left, a_top, a_right, a_bottom] =
GetLTRB();
497 const auto& [b_left, b_top, b_right, b_bottom] = o.
GetLTRB();
498 if (b_left <= a_left && b_right >= a_right) {
499 if (b_top <= a_top && b_bottom >= a_bottom) {
503 if (b_top <= a_top && b_bottom > a_top) {
507 if (b_bottom >= a_bottom && b_top < a_bottom) {
512 if (b_top <= a_top && b_bottom >= a_bottom) {
513 if (b_left <= a_left && b_right > a_left) {
517 if (b_right >= a_right && b_left < a_right) {
533 saturated::Add(left_, dx),
534 saturated::Add(top_, dy),
535 saturated::Add(right_, dx),
536 saturated::Add(bottom_, dy),
552 saturated::Sub(left_, left),
553 saturated::Sub(top_, top),
554 saturated::Add(right_, right),
555 saturated::Add(bottom_, bottom),
563 saturated::Sub(left_, amount),
564 saturated::Sub(top_, amount),
565 saturated::Add(right_, amount),
566 saturated::Add(bottom_, amount),
573 T vertical_amount)
const {
575 saturated::Sub(left_, horizontal_amount),
576 saturated::Sub(top_, vertical_amount),
577 saturated::Add(right_, horizontal_amount),
578 saturated::Add(bottom_, vertical_amount),
602 return source.
Shift(-left_, -top_)
610 saturated::Cast<U, Type>(floor(r.GetTop())),
611 saturated::Cast<U, Type>(ceil(r.GetRight())),
612 saturated::Cast<U, Type>(ceil(r.GetBottom())));
615 [[nodiscard]] constexpr
static std::optional<TRect>
Union(
617 const std::optional<TRect>
b) {
618 return b.has_value() ? a.
Union(
b.value()) : a;
621 [[nodiscard]] constexpr
static std::optional<TRect>
Union(
622 const std::optional<TRect> a,
624 return a.has_value() ? a->Union(
b) :
b;
627 [[nodiscard]] constexpr
static std::optional<TRect>
Union(
628 const std::optional<TRect> a,
629 const std::optional<TRect>
b) {
630 return a.has_value() ?
Union(a.value(),
b) :
b;
635 const std::optional<TRect>
b) {
640 const std::optional<TRect> a,
642 return a.has_value() ? a->Intersection(
b) :
b;
646 const std::optional<TRect> a,
647 const std::optional<TRect>
b) {
652 constexpr
TRect(Type left, Type top, Type right, Type bottom)
653 : left_(left), top_(top), right_(right), bottom_(bottom) {}
665 #undef ONLY_ON_FLOAT_M
680 #endif // FLUTTER_IMPELLER_GEOMETRY_RECT_H_