Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Classes | Namespaces | Macros | Typedefs
rect.h File Reference
#include <array>
#include <optional>
#include <ostream>
#include <vector>
#include "fml/logging.h"
#include "impeller/geometry/matrix.h"
#include "impeller/geometry/point.h"
#include "impeller/geometry/saturated_math.h"
#include "impeller/geometry/scalar.h"
#include "impeller/geometry/size.h"

Go to the source code of this file.

Classes

struct  impeller::TRect< T >
 

Namespaces

namespace  impeller
 
namespace  std
 

Macros

#define ONLY_ON_FLOAT_M(Modifiers, Return)
 
#define ONLY_ON_FLOAT(Return)   DL_ONLY_ON_FLOAT_M(, Return)
 

Typedefs

using impeller::Rect = TRect< Scalar >
 
using impeller::IRect = TRect< int64_t >
 

Macro Definition Documentation

◆ ONLY_ON_FLOAT

#define ONLY_ON_FLOAT (   Return)    DL_ONLY_ON_FLOAT_M(, Return)

Definition at line 25 of file rect.h.

◆ ONLY_ON_FLOAT_M

#define ONLY_ON_FLOAT_M (   Modifiers,
  Return 
)
Value:
template <typename U = T> \
Modifiers std::enable_if_t<std::is_floating_point_v<U>, Return>

Definition at line 22 of file rect.h.

122 {
123 private:
124 using Type = T;
125
126 public:
127 constexpr TRect() : left_(0), top_(0), right_(0), bottom_(0) {}
128
129 constexpr static TRect MakeLTRB(Type left,
130 Type top,
131 Type right,
132 Type bottom) {
133 return TRect(left, top, right, bottom);
134 }
135
136 constexpr static TRect MakeXYWH(Type x, Type y, Type width, Type height) {
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) {
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);
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
188 [[nodiscard]] constexpr TRect Scale(Type scale) const {
189 return TRect(left_ * scale, //
190 top_ * scale, //
191 right_ * scale, //
192 bottom_ * 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 {
203 return Scale(scale.x, scale.y);
204 }
205
206 [[nodiscard]] constexpr TRect Scale(TSize<T> scale) const {
207 return Scale(scale.width, scale.height);
208 }
209
210 /// @brief Returns true iff the provided point |p| is inside the
211 /// half-open interior of this rectangle.
212 ///
213 /// For purposes of containment, a rectangle contains points
214 /// along the top and left edges but not points along the
215 /// right and bottom edges so that a point is only ever
216 /// considered inside one of two abutting rectangles.
217 [[nodiscard]] constexpr bool Contains(const TPoint<Type>& p) const {
218 return !this->IsEmpty() && //
219 p.x >= left_ && //
220 p.y >= top_ && //
221 p.x < right_ && //
222 p.y < bottom_;
223 }
224
225 /// @brief Returns true iff this rectangle is not empty and it also
226 /// contains every point considered inside the provided
227 /// rectangle |o| (as determined by |Contains(TPoint)|).
228 ///
229 /// This is similar to a definition where the result is true iff
230 /// the union of the two rectangles is equal to this rectangle,
231 /// ignoring precision issues with performing those operations
232 /// and assuming that empty rectangles are never equal.
233 ///
234 /// An empty rectangle can contain no other rectangle.
235 ///
236 /// An empty rectangle is, however, contained within any
237 /// other non-empy rectangle as the set of points it contains
238 /// is an empty set and so there are no points to fail the
239 /// containment criteria.
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 /// @brief Returns true if all of the fields of this floating point
249 /// rectangle are finite.
250 ///
251 /// Note that the results of |GetWidth()| and |GetHeight()| may
252 /// still be infinite due to overflow even if the fields themselves
253 /// are finite.
254 ONLY_ON_FLOAT_M([[nodiscard]] constexpr, bool)
255 IsFinite() const {
256 return std::isfinite(left_) && //
257 std::isfinite(top_) && //
258 std::isfinite(right_) && //
259 std::isfinite(bottom_);
260 }
261
262 /// @brief Returns true if either of the width or height are 0, negative,
263 /// or NaN.
264 [[nodiscard]] constexpr bool IsEmpty() const {
265 // Computing the non-empty condition and negating the result causes any
266 // NaN value to return true - i.e. is considered empty.
267 return !(left_ < right_ && top_ < bottom_);
268 }
269
270 /// @brief Returns true if width and height are equal and neither is NaN.
271 [[nodiscard]] constexpr bool IsSquare() const {
272 // empty rectangles can technically be "square", but would be
273 // misleading to most callers. Using |IsEmpty| also prevents
274 // "non-empty and non-overflowing" computations from happening
275 // to be equal to "empty and overflowing" results.
276 // (Consider LTRB(10, 15, MAX-2, MIN+2) which is empty, but both
277 // w/h subtractions equal "5").
278 return !IsEmpty() && (right_ - left_) == (bottom_ - top_);
279 }
280
281 [[nodiscard]] constexpr bool IsMaximum() const {
282 return *this == MakeMaximum();
283 }
284
285 /// @brief Returns the upper left corner of the rectangle as specified
286 /// by the left/top or x/y values when it was constructed.
287 [[nodiscard]] constexpr TPoint<Type> GetOrigin() const {
288 return {left_, top_};
289 }
290
291 /// @brief Returns the size of the rectangle which may be negative in
292 /// either width or height and may have been clipped to the
293 /// maximum integer values for integer rects whose size overflows.
294 [[nodiscard]] constexpr TSize<Type> GetSize() const {
295 return {GetWidth(), GetHeight()};
296 }
297
298 /// @brief Returns the X coordinate of the upper left corner, equivalent
299 /// to |GetOrigin().x|
300 [[nodiscard]] constexpr Type GetX() const { return left_; }
301
302 /// @brief Returns the Y coordinate of the upper left corner, equivalent
303 /// to |GetOrigin().y|
304 [[nodiscard]] constexpr Type GetY() const { return top_; }
305
306 /// @brief Returns the width of the rectangle, equivalent to
307 /// |GetSize().width|
308 [[nodiscard]] constexpr Type GetWidth() const {
309 return saturated::Sub(right_, left_);
310 }
311
312 /// @brief Returns the height of the rectangle, equivalent to
313 /// |GetSize().height|
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 /// @brief Get the area of the rectangle, equivalent to |GetSize().Area()|
343 [[nodiscard]] constexpr T Area() const {
344 // TODO(flutter/flutter#141710) - Use saturated math to avoid overflow
345 // https://github.com/flutter/flutter/issues/141710
346 return IsEmpty() ? 0 : (right_ - left_) * (bottom_ - top_);
347 }
348
349 /// @brief Get the center point as a |Point|.
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 /// @brief Get the x, y coordinates of the origin and the width and
360 /// height of the rectangle in an array.
361 [[nodiscard]] constexpr std::array<T, 4> GetXYWH() const {
362 return {left_, top_, GetWidth(), GetHeight()};
363 }
364
365 /// @brief Get a version of this rectangle that has a non-negative size.
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 /// @brief Get the points that represent the 4 corners of this rectangle
379 /// in a Z order that is compatible with triangle strips or a set
380 /// of all zero points if the rectangle is empty.
381 /// The order is: Top left, top right, bottom left, bottom right.
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(
395 const Matrix& transform) const {
396 auto points = GetPoints();
397 for (size_t i = 0; i < points.size(); i++) {
398 points[i] = transform * points[i];
399 }
400 return points;
401 }
402
403 /// @brief Creates a new bounding box that contains this transformed
404 /// rectangle, clipped against the near clipping plane if
405 /// necessary.
406 [[nodiscard]] constexpr TRect TransformAndClipBounds(
407 const Matrix& transform) const {
408 if (!transform.HasPerspective2D()) {
409 return TransformBounds(transform);
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 // It can probably be proven that we only ever have 5 points at most
422 // which happens when only 1 corner is clipped and we get 2 points
423 // in return for it as we interpolate against its neighbors.
424 Point points[8];
425 int index = 0;
426
427 // Process (clip and interpolate) each point against its 2 neighbors:
428 // left, pt, right
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
434 auto bounds = TRect::MakePointBounds(points, points + index);
435 return bounds.value_or(TRect{});
436 }
437
438 /// @brief Creates a new bounding box that contains this transformed
439 /// rectangle.
440 [[nodiscard]] constexpr TRect TransformBounds(const Matrix& transform) const {
441 if (IsEmpty()) {
442 return {};
443 }
444 auto points = GetTransformedPoints(transform);
445 auto bounds = TRect::MakePointBounds(points.begin(), points.end());
446 if (bounds.has_value()) {
447 return bounds.value();
448 }
450 }
451
452 /// @brief Constructs a Matrix that will map all points in the coordinate
453 /// space of the rectangle into a new normalized coordinate space
454 /// where the upper left corner of the rectangle maps to (0, 0)
455 /// and the lower right corner of the rectangle maps to (1, 1).
456 ///
457 /// Empty and non-finite rectangles will return a zero-scaling
458 /// transform that maps all points to (0, 0).
459 [[nodiscard]] constexpr Matrix GetNormalizingTransform() const {
460 if (!IsEmpty()) {
461 Scalar sx = 1.0 / GetWidth();
462 Scalar sy = 1.0 / GetHeight();
463 Scalar tx = left_ * -sx;
464 Scalar ty = top_ * -sy;
465
466 // Exclude NaN and infinities and either scale underflowing to zero
467 if (sx != 0.0 && sy != 0.0 && 0.0 * sx * sy * tx * ty == 0.0) {
468 // clang-format off
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 // clang-format on
474 }
475 }
476
477 // Map all coordinates to the origin.
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 /// @brief Returns the new boundary rectangle that would result from this
520 /// rectangle being cut out by the specified rectangle.
521 [[nodiscard]] constexpr std::optional<TRect<T>> Cutout(const TRect& o) const {
522 if (IsEmpty()) {
523 // This test isn't just a short-circuit, it also prevents the concise
524 // math below from returning the wrong answer on empty rects.
525 // Once we know that this rectangle is not empty, the math below can
526 // only succeed in computing a value if o is also non-empty and non-nan.
527 // Otherwise, the method returns *this by default.
528 return std::nullopt;
529 }
530
531 const auto& [a_left, a_top, a_right, a_bottom] = GetLTRB(); // Source rect.
532 const auto& [b_left, b_top, b_right, b_bottom] = o.GetLTRB(); // Cutout.
533 if (b_left <= a_left && b_right >= a_right) {
534 if (b_top <= a_top && b_bottom >= a_bottom) {
535 // Full cutout.
536 return std::nullopt;
537 }
538 if (b_top <= a_top && b_bottom > a_top) {
539 // Cuts off the top.
540 return TRect::MakeLTRB(a_left, b_bottom, a_right, a_bottom);
541 }
542 if (b_bottom >= a_bottom && b_top < a_bottom) {
543 // Cuts off the bottom.
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 // Cuts off the left.
550 return TRect::MakeLTRB(b_right, a_top, a_right, a_bottom);
551 }
552 if (b_right >= a_right && b_left < a_right) {
553 // Cuts off the right.
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 /// @brief Returns a new rectangle translated by the given offset.
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 /// @brief Returns a new rectangle translated by the given offset.
576 [[nodiscard]] constexpr TRect<T> Shift(TPoint<T> offset) const {
577 return Shift(offset.x, offset.y);
578 }
579
580 /// @brief Returns a rectangle with expanded edges. Negative expansion
581 /// results in shrinking.
582 [[nodiscard]] constexpr TRect<T> Expand(T left,
583 T top,
584 T right,
585 T bottom) const {
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 /// @brief Returns a rectangle with expanded edges in all directions.
595 /// Negative expansion results in shrinking.
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 /// @brief Returns a rectangle with expanded edges in all directions.
606 /// Negative expansion results in shrinking.
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 /// @brief Returns a rectangle with expanded edges in all directions.
618 /// Negative expansion results in shrinking.
619 [[nodiscard]] constexpr TRect<T> Expand(TPoint<T> amount) const {
620 return Expand(amount.x, amount.y);
621 }
622
623 /// @brief Returns a rectangle with expanded edges in all directions.
624 /// Negative expansion results in shrinking.
625 [[nodiscard]] constexpr TRect<T> Expand(TSize<T> amount) const {
626 return Expand(amount.width, amount.height);
627 }
628
629 /// @brief Returns a new rectangle that represents the projection of the
630 /// source rectangle onto this rectangle. In other words, the source
631 /// rectangle is redefined in terms of the coordinate space of this
632 /// rectangle.
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
642 ONLY_ON_FLOAT_M([[nodiscard]] constexpr static, TRect)
643 RoundOut(const TRect<U>& r) {
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
650 ONLY_ON_FLOAT_M([[nodiscard]] constexpr static, TRect)
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(
659 const TRect& a,
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,
666 const TRect& b) {
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(
677 const TRect& a,
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,
684 const TRect& b) {
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:
695 constexpr TRect(Type left, Type top, Type right, Type bottom)
696 : left_(left), top_(top), right_(right), bottom_(bottom) {}
697
698 Type left_;
699 Type top_;
700 Type right_;
701 Type bottom_;
702
703 static constexpr Scalar kMinimumHomogenous = 1.0f / (1 << 14);
704
705 // Clip p against the near clipping plane (W = kMinimumHomogenous)
706 // and interpolate a crossing point against the nearby neighbors
707 // left and right if p is clipped and either of them is not.
708 // This method can produce 0, 1, or 2 points per call depending on
709 // how many of the points are clipped.
710 // 0 - all points are clipped
711 // 1 - p is unclipped OR
712 // p is clipped and exactly one of the neighbors is not
713 // 2 - p is clipped and both neighbors are not
714 static constexpr int ClipAndInsert(Point clipped[],
715 int index,
716 const Vector3& left,
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 // Interpolate (a clipped) point p against one of its neighbors
729 // and insert the point into the array where the line between them
730 // veers from clipped space to unclipped, if such a point exists.
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} // namespace impeller
753
754namespace std {
755
756template <class T>
757inline std::ostream& operator<<(std::ostream& out,
758 const impeller::TRect<T>& r) {
759 out << "(" << r.GetOrigin() << ", " << r.GetSize() << ")";
760 return out;
761}
762
763} // namespace std
764
765#endif // FLUTTER_IMPELLER_GEOMETRY_RECT_H_
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)
SkBitmap source
Definition examples.cpp:28
static bool b
struct MyStruct a[10]
uint8_t value
#define FML_UNREACHABLE()
Definition logging.h:109
#define ONLY_ON_FLOAT_M(Modifiers, Return)
Definition rect.h:22
double y
double x
Optional< SkRect > bounds
Definition SkRecords.h:189
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
Definition switches.h:259
float Scalar
Definition scalar.h:18
TRect< Scalar > Rect
Definition rect.h:746
TPoint< Scalar > Point
Definition point.h:316
TRect< int64_t > IRect
Definition rect.h:747
SkIRect RoundOut(SkRect r)
SIN Vec< N, float > floor(const Vec< N, float > &x)
Definition SkVx.h:703
SIN Vec< N, float > ceil(const Vec< N, float > &x)
Definition SkVx.h:702
Definition ref_ptr.h:256
std::ostream & operator<<(std::ostream &out, const impeller::Color &c)
Definition color.h:951
static SkColor4f transform(SkColor4f c, SkColorSpace *src, SkColorSpace *dst)
Definition p3.cpp:47
#define T
int32_t height
int32_t width
const Scalar scale
Point offset
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...
Definition rect.h:294
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...
Definition rect.h:287