122 {
123 private:
125
126 public:
127 constexpr TRect() : left_(0), top_(0), right_(0), bottom_(0) {}
128
129 constexpr static TRect MakeLTRB(
Type left,
134 }
135
137 return TRect(
x,
y, saturated::Add(
x,
width), saturated::Add(
y,
height));
138 }
139
140 constexpr static TRect MakeOriginSize(const TPoint<Type>& origin,
141 const TSize<Type>& size) {
142 return MakeXYWH(origin.x, origin.y,
size.width,
size.height);
143 }
144
145 template <class U>
146 constexpr static TRect MakeSize(const TSize<U>& size) {
147 return TRect(0.0, 0.0,
size.width,
size.height);
148 }
149
150 template <typename U>
151 constexpr static std::optional<TRect> MakePointBounds(const U& value) {
152 return MakePointBounds(
value.begin(),
value.end());
153 }
154
155 template <typename PointIter>
156 constexpr static std::optional<TRect> MakePointBounds(const PointIter first,
157 const PointIter last) {
158 if (first == last) {
159 return std::nullopt;
160 }
161 auto left = first->x;
162 auto top = first->y;
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);
170 }
171 return TRect::MakeLTRB(
left, top,
right, bottom);
172 }
173
174 [[nodiscard]] constexpr static TRect MakeMaximum() {
175 return TRect::MakeLTRB(std::numeric_limits<Type>::lowest(),
176 std::numeric_limits<Type>::lowest(),
177 std::numeric_limits<Type>::max(),
178 std::numeric_limits<Type>::max());
179 }
180
181 [[nodiscard]]
constexpr bool operator==(
const TRect& r)
const {
182 return left_ == r.left_ &&
183 top_ == r.top_ &&
184 right_ == r.right_ &&
185 bottom_ == r.bottom_;
186 }
187
189 return TRect(left_ *
scale,
193 }
194
195 [[nodiscard]]
constexpr TRect
Scale(
Type scale_x,
Type scale_y)
const {
196 return TRect(left_ * scale_x,
197 top_ * scale_y,
198 right_ * scale_x,
199 bottom_ * scale_y);
200 }
201
202 [[nodiscard]]
constexpr TRect
Scale(TPoint<T>
scale)
const {
204 }
205
206 [[nodiscard]]
constexpr TRect
Scale(TSize<T>
scale)
const {
208 }
209
210
211
212
213
214
215
216
217 [[nodiscard]]
constexpr bool Contains(
const TPoint<Type>& p)
const {
218 return !this->IsEmpty() &&
223 }
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240 [[nodiscard]]
constexpr bool Contains(
const TRect& o)
const {
241 return !this->IsEmpty() &&
242 (o.IsEmpty() || (o.left_ >= left_ &&
243 o.top_ >= top_ &&
244 o.right_ <= right_ &&
245 o.bottom_ <= bottom_));
246 }
247
248
249
250
251
252
253
255 IsFinite() const {
256 return std::isfinite(left_) &&
257 std::isfinite(top_) &&
258 std::isfinite(right_) &&
259 std::isfinite(bottom_);
260 }
261
262
263
264 [[nodiscard]] constexpr bool IsEmpty() const {
265
266
267 return !(left_ < right_ && top_ < bottom_);
268 }
269
270
271 [[nodiscard]] constexpr bool IsSquare() const {
272
273
274
275
276
277
278 return !IsEmpty() && (right_ - left_) == (bottom_ - top_);
279 }
280
281 [[nodiscard]] constexpr bool IsMaximum() const {
282 return *this == MakeMaximum();
283 }
284
285
286
287 [[nodiscard]] constexpr TPoint<Type> GetOrigin() const {
288 return {left_, top_};
289 }
290
291
292
293
294 [[nodiscard]] constexpr TSize<Type> GetSize() const {
295 return {GetWidth(), GetHeight()};
296 }
297
298
299
300 [[nodiscard]]
constexpr Type GetX()
const {
return left_; }
301
302
303
304 [[nodiscard]]
constexpr Type GetY()
const {
return top_; }
305
306
307
308 [[nodiscard]]
constexpr Type GetWidth()
const {
309 return saturated::Sub(right_, left_);
310 }
311
312
313
314 [[nodiscard]]
constexpr Type GetHeight()
const {
315 return saturated::Sub(bottom_, top_);
316 }
317
318 [[nodiscard]] constexpr auto GetLeft() const { return left_; }
319
320 [[nodiscard]] constexpr auto GetTop() const { return top_; }
321
322 [[nodiscard]] constexpr auto GetRight() const { return right_; }
323
324 [[nodiscard]] constexpr auto GetBottom() const { return bottom_; }
325
326 [[nodiscard]] constexpr TPoint<T> GetLeftTop() const {
327 return {left_, top_};
328 }
329
330 [[nodiscard]] constexpr TPoint<T> GetRightTop() const {
331 return {right_, top_};
332 }
333
334 [[nodiscard]] constexpr TPoint<T> GetLeftBottom() const {
335 return {left_, bottom_};
336 }
337
338 [[nodiscard]] constexpr TPoint<T> GetRightBottom() const {
339 return {right_, bottom_};
340 }
341
342
343 [[nodiscard]]
constexpr T Area()
const {
344
345
346 return IsEmpty() ? 0 : (right_ - left_) * (bottom_ - top_);
347 }
348
349
350 [[nodiscard]]
constexpr Point GetCenter()
const {
351 return {saturated::AverageScalar(left_, right_),
352 saturated::AverageScalar(top_, bottom_)};
353 }
354
355 [[nodiscard]] constexpr std::array<T, 4> GetLTRB() const {
356 return {left_, top_, right_, bottom_};
357 }
358
359
360
361 [[nodiscard]] constexpr std::array<T, 4> GetXYWH() const {
362 return {left_, top_, GetWidth(), GetHeight()};
363 }
364
365
366 [[nodiscard]] constexpr TRect GetPositive() const {
367 if (!IsEmpty()) {
368 return *this;
369 }
370 return {
371 std::min(left_, right_),
372 std::min(top_, bottom_),
373 std::max(left_, right_),
374 std::max(top_, bottom_),
375 };
376 }
377
378
379
380
381
382 [[nodiscard]] constexpr std::array<TPoint<T>, 4> GetPoints() const {
383 if (IsEmpty()) {
384 return {};
385 }
386 return {
387 TPoint{left_, top_},
388 TPoint{right_, top_},
389 TPoint{left_, bottom_},
390 TPoint{right_, bottom_},
391 };
392 }
393
394 [[nodiscard]] constexpr std::array<TPoint<T>, 4> GetTransformedPoints(
396 auto points = GetPoints();
397 for (
size_t i = 0; i <
points.size(); i++) {
399 }
401 }
402
403
404
405
406 [[nodiscard]] constexpr TRect TransformAndClipBounds(
410 }
411
412 if (IsEmpty()) {
413 return {};
414 }
415
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_});
420
421
422
423
425 int index = 0;
426
427
428
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);
433
435 return bounds.value_or(TRect{});
436 }
437
438
439
440 [[nodiscard]]
constexpr TRect TransformBounds(
const Matrix&
transform)
const {
441 if (IsEmpty()) {
442 return {};
443 }
448 }
450 }
451
452
453
454
455
456
457
458
459 [[nodiscard]] constexpr Matrix GetNormalizingTransform() const {
460 if (!IsEmpty()) {
461 Scalar sx = 1.0 / GetWidth();
462 Scalar sy = 1.0 / GetHeight();
465
466
467 if (sx != 0.0 && sy != 0.0 && 0.0 * sx * sy * tx * ty == 0.0) {
468
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,
472 tx, ty, 0.0f, 1.0f);
473
474 }
475 }
476
477
478 return Matrix::MakeScale({0.0f, 0.0f, 1.0f});
479 }
480
481 [[nodiscard]]
constexpr TRect
Union(
const TRect& o)
const {
482 if (IsEmpty()) {
483 return o;
484 }
485 if (o.IsEmpty()) {
486 return *this;
487 }
488 return {
489 std::min(left_, o.left_),
490 std::min(top_, o.top_),
491 std::max(right_, o.right_),
492 std::max(bottom_, o.bottom_),
493 };
494 }
495
496 [[nodiscard]] constexpr std::optional<TRect> Intersection(
497 const TRect& o) const {
498 if (IntersectsWithRect(o)) {
499 return TRect{
500 std::max(left_, o.left_),
501 std::max(top_, o.top_),
502 std::min(right_, o.right_),
503 std::min(bottom_, o.bottom_),
504 };
505 } else {
506 return std::nullopt;
507 }
508 }
509
510 [[nodiscard]] constexpr bool IntersectsWithRect(const TRect& o) const {
511 return !IsEmpty() &&
512 !o.IsEmpty() &&
513 left_ < o.right_ &&
514 top_ < o.bottom_ &&
515 right_ > o.left_ &&
516 bottom_ > o.top_;
517 }
518
519
520
521 [[nodiscard]] constexpr std::optional<TRect<T>> Cutout(const TRect& o) const {
522 if (IsEmpty()) {
523
524
525
526
527
528 return std::nullopt;
529 }
530
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) {
535
536 return std::nullopt;
537 }
538 if (b_top <= a_top && b_bottom > a_top) {
539
540 return TRect::MakeLTRB(a_left, b_bottom, a_right, a_bottom);
541 }
542 if (b_bottom >= a_bottom && b_top < a_bottom) {
543
544 return TRect::MakeLTRB(a_left, a_top, a_right, b_top);
545 }
546 }
547 if (b_top <= a_top && b_bottom >= a_bottom) {
548 if (b_left <= a_left && b_right > a_left) {
549
550 return TRect::MakeLTRB(b_right, a_top, a_right, a_bottom);
551 }
552 if (b_right >= a_right && b_left < a_right) {
553
554 return TRect::MakeLTRB(a_left, a_top, b_left, a_bottom);
555 }
556 }
557
558 return *this;
559 }
560
561 [[nodiscard]] constexpr TRect CutoutOrEmpty(const TRect& o) const {
562 return Cutout(o).value_or(TRect());
563 }
564
565
566 [[nodiscard]]
constexpr TRect<T>
Shift(
T dx,
T dy)
const {
567 return {
568 saturated::Add(left_, dx),
569 saturated::Add(top_, dy),
570 saturated::Add(right_, dx),
571 saturated::Add(bottom_, dy),
572 };
573 }
574
575
576 [[nodiscard]]
constexpr TRect<T>
Shift(TPoint<T>
offset)
const {
578 }
579
580
581
582 [[nodiscard]]
constexpr TRect<T> Expand(
T left,
586 return {
587 saturated::Sub(left_,
left),
588 saturated::Sub(top_, top),
589 saturated::Add(right_,
right),
590 saturated::Add(bottom_, bottom),
591 };
592 }
593
594
595
596 [[nodiscard]]
constexpr TRect<T> Expand(
T amount)
const {
597 return {
598 saturated::Sub(left_, amount),
599 saturated::Sub(top_, amount),
600 saturated::Add(right_, amount),
601 saturated::Add(bottom_, amount),
602 };
603 }
604
605
606
607 [[nodiscard]]
constexpr TRect<T> Expand(
T horizontal_amount,
608 T vertical_amount)
const {
609 return {
610 saturated::Sub(left_, horizontal_amount),
611 saturated::Sub(top_, vertical_amount),
612 saturated::Add(right_, horizontal_amount),
613 saturated::Add(bottom_, vertical_amount),
614 };
615 }
616
617
618
619 [[nodiscard]] constexpr TRect<T> Expand(TPoint<T> amount) const {
620 return Expand(amount.x, amount.y);
621 }
622
623
624
625 [[nodiscard]] constexpr TRect<T> Expand(TSize<T> amount) const {
626 return Expand(amount.width, amount.height);
627 }
628
629
630
631
632
633 [[nodiscard]]
constexpr TRect<T> Project(TRect<T>
source)
const {
634 if (IsEmpty()) {
635 return {};
636 }
637 return source.Shift(-left_, -top_)
638 .Scale(1.0 /
static_cast<Scalar>(GetWidth()),
639 1.0 /
static_cast<Scalar>(GetHeight()));
640 }
641
644 return TRect::MakeLTRB(saturated::Cast<U, Type>(
floor(r.GetLeft())),
645 saturated::Cast<U, Type>(
floor(r.GetTop())),
646 saturated::Cast<U, Type>(
ceil(r.GetRight())),
647 saturated::Cast<U, Type>(
ceil(r.GetBottom())));
648 }
649
651 Round(const TRect<U>& r) {
652 return TRect::MakeLTRB(saturated::Cast<U, Type>(
round(r.GetLeft())),
653 saturated::Cast<U, Type>(
round(r.GetTop())),
654 saturated::Cast<U, Type>(
round(r.GetRight())),
655 saturated::Cast<U, Type>(
round(r.GetBottom())));
656 }
657
658 [[nodiscard]]
constexpr static std::optional<TRect>
Union(
660 const std::optional<TRect>
b) {
661 return b.has_value() ?
a.Union(
b.value()) :
a;
662 }
663
664 [[nodiscard]]
constexpr static std::optional<TRect>
Union(
665 const std::optional<TRect>
a,
667 return a.has_value() ?
a->Union(
b) :
b;
668 }
669
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;
674 }
675
676 [[nodiscard]] constexpr static std::optional<TRect> Intersection(
678 const std::optional<TRect>
b) {
679 return b.has_value() ?
a.Intersection(
b.value()) :
a;
680 }
681
682 [[nodiscard]] constexpr static std::optional<TRect> Intersection(
683 const std::optional<TRect>
a,
685 return a.has_value() ?
a->Intersection(
b) :
b;
686 }
687
688 [[nodiscard]] constexpr static std::optional<TRect> Intersection(
689 const std::optional<TRect>
a,
690 const std::optional<TRect>
b) {
691 return a.has_value() ? Intersection(
a.value(),
b) :
b;
692 }
693
694 private:
696 : left_(
left), top_(top), right_(
right), bottom_(bottom) {}
697
702
703 static constexpr Scalar kMinimumHomogenous = 1.0f / (1 << 14);
704
705
706
707
708
709
710
711
712
713
714 static constexpr int ClipAndInsert(Point clipped[],
715 int index,
717 const Vector3& p,
718 const Vector3&
right) {
719 if (
p.z >= kMinimumHomogenous) {
720 clipped[index++] = {
p.x /
p.z,
p.y /
p.z};
721 } else {
722 index = InterpolateAndInsert(clipped, index, p,
left);
723 index = InterpolateAndInsert(clipped, index, p,
right);
724 }
725 return index;
726 }
727
728
729
730
731 static constexpr int InterpolateAndInsert(Point clipped[],
732 int index,
733 const Vector3& p,
734 const Vector3& neighbor) {
735 if (neighbor.z >= kMinimumHomogenous) {
736 auto t = (kMinimumHomogenous -
p.z) / (neighbor.z -
p.z);
737 clipped[index++] = {
738 (t *
p.x + (1.0f - t) * neighbor.x) / kMinimumHomogenous,
739 (t *
p.y + (1.0f - t) * neighbor.y) / kMinimumHomogenous,
740 };
741 }
742 return index;
743 }
744};
745
746using Rect = TRect<Scalar>;
747using IRect = TRect<int64_t>;
748
749#undef ONLY_ON_FLOAT
750#undef ONLY_ON_FLOAT_M
751
752}
753
755
756template <class T>
757inline std::ostream&
operator<<(std::ostream& out,
761}
762
763}
764
765#endif
static void round(SkPoint *p)
static const int points[]
static void Union(SkRegion *rgn, const SkIRect &rect)
static bool left(const SkPoint &p0, const SkPoint &p1)
static bool right(const SkPoint &p0, const SkPoint &p1)
bool operator==(const FlutterPoint &a, const FlutterPoint &b)
#define FML_UNREACHABLE()
#define ONLY_ON_FLOAT_M(Modifiers, Return)
Optional< SkRect > bounds
bool Contains(const Container &container, const Value &value)
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
SkIRect RoundOut(SkRect r)
SIN Vec< N, float > floor(const Vec< N, float > &x)
SIN Vec< N, float > ceil(const Vec< N, float > &x)
std::ostream & operator<<(std::ostream &out, const impeller::Color &c)
static SkColor4f transform(SkColor4f c, SkColorSpace *src, SkColorSpace *dst)
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 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...