Flutter Engine
The Flutter Engine
Classes | Public Member Functions | Static Public Member Functions | List of all members
flutter::DlRegion Class Reference

#include <dl_region.h>

Public Member Functions

 DlRegion ()=default
 Creates an empty region. More...
 
 DlRegion (const std::vector< SkIRect > &rects)
 
 DlRegion (const SkIRect &rect)
 Creates region covering area of a rectangle. More...
 
 DlRegion (const DlRegion &)=default
 
 DlRegion (DlRegion &&)=default
 
DlRegionoperator= (const DlRegion &)=default
 
DlRegionoperator= (DlRegion &&)=default
 
std::vector< SkIRectgetRects (bool deband=true) const
 
const SkIRectbounds () const
 
bool intersects (const SkIRect &rect) const
 Returns whether this region intersects with a rectangle. More...
 
bool intersects (const DlRegion &region) const
 Returns whether this region intersects with another region. More...
 
bool isEmpty () const
 Returns true if region is empty (contains no rectangles). More...
 
bool isComplex () const
 Returns true if region is not empty and contains more than one rectangle. More...
 
bool isSimple () const
 

Static Public Member Functions

static DlRegion MakeUnion (const DlRegion &a, const DlRegion &b)
 
static DlRegion MakeIntersection (const DlRegion &a, const DlRegion &b)
 

Detailed Description

Represents a region as a collection of non-overlapping rectangles. Implements a subset of SkRegion functionality optimized for quickly converting set of overlapping rectangles to non-overlapping rectangles.

Definition at line 18 of file dl_region.h.

Constructor & Destructor Documentation

◆ DlRegion() [1/5]

flutter::DlRegion::DlRegion ( )
default

Creates an empty region.

◆ DlRegion() [2/5]

flutter::DlRegion::DlRegion ( const std::vector< SkIRect > &  rects)
explicit

Creates region by bulk adding the rectangles. Matches SkRegion::op(rect, SkRegion::kUnion_Op) behavior.

Definition at line 97 of file dl_region.cc.

97 {
98 setRects(rects);
99}

◆ DlRegion() [3/5]

flutter::DlRegion::DlRegion ( const SkIRect rect)
explicit

Creates region covering area of a rectangle.

Definition at line 101 of file dl_region.cc.

101 : bounds_(rect) {
102 Span span{rect.left(), rect.right()};
103 lines_.push_back(makeLine(rect.top(), rect.bottom(), &span, &span + 1));
104}
sk_sp< SkBlender > blender SkRect rect
Definition: SkRecords.h:350

◆ DlRegion() [4/5]

flutter::DlRegion::DlRegion ( const DlRegion )
default

◆ DlRegion() [5/5]

flutter::DlRegion::DlRegion ( DlRegion &&  )
default

Member Function Documentation

◆ bounds()

const SkIRect & flutter::DlRegion::bounds ( ) const
inline

Returns maximum and minimum axis values of rectangles in this region. If region is empty returns SKIRect::MakeEmpty().

Definition at line 53 of file dl_region.h.

53{ return bounds_; }

◆ getRects()

std::vector< SkIRect > flutter::DlRegion::getRects ( bool  deband = true) const

Returns list of non-overlapping rectangles that cover current region. If |deband| is false, each span line will result in separate rectangles, closely matching SkRegion::Iterator behavior. If |deband| is true, matching rectangles from adjacent span lines will be merged into single rectangle.

Definition at line 563 of file dl_region.cc.

563 {
564 std::vector<SkIRect> rects;
565 if (isEmpty()) {
566 return rects;
567 } else if (isSimple()) {
568 rects.push_back(bounds_);
569 return rects;
570 }
571
572 size_t rect_count = 0;
573 size_t previous_span_end = 0;
574 for (const auto& line : lines_) {
575 rect_count += span_buffer_.getChunkSize(line.chunk_handle);
576 }
577 rects.reserve(rect_count);
578
579 for (const auto& line : lines_) {
580 const Span *span_begin, *span_end;
581 span_buffer_.getSpans(line.chunk_handle, span_begin, span_end);
582 for (const auto* span = span_begin; span < span_end; ++span) {
583 SkIRect rect{span->left, line.top, span->right, line.bottom};
584 if (deband) {
585 auto iter = rects.begin() + previous_span_end;
586 // If there is rectangle previously in rects on which this one is a
587 // vertical continuation, remove the previous rectangle and expand
588 // this one vertically to cover the area.
589 while (iter != rects.begin()) {
590 --iter;
591 if (iter->bottom() < rect.top()) {
592 // Went all the way to previous span line.
593 break;
594 } else if (iter->left() == rect.left() &&
595 iter->right() == rect.right()) {
596 FML_DCHECK(iter->bottom() == rect.top());
597 rect.fTop = iter->fTop;
598 rects.erase(iter);
599 --previous_span_end;
600 break;
601 }
602 }
603 }
604 rects.push_back(rect);
605 }
606 previous_span_end = rects.size();
607 }
608 return rects;
609}
bool isEmpty() const
Returns true if region is empty (contains no rectangles).
Definition: dl_region.h:62
bool isSimple() const
Definition: dl_region.h:69
#define FML_DCHECK(condition)
Definition: logging.h:103
Definition: SkRect.h:32

◆ intersects() [1/2]

bool flutter::DlRegion::intersects ( const DlRegion region) const

Returns whether this region intersects with another region.

Definition at line 705 of file dl_region.cc.

705 {
706 if (isEmpty() || region.isEmpty()) {
707 return false;
708 }
709
710 auto our_complex = isComplex();
711 auto their_complex = region.isComplex();
712 auto bounds_intersect = SkIRect::Intersects(bounds_, region.bounds_);
713
714 if (!our_complex && !their_complex) {
715 return bounds_intersect;
716 }
717
718 if (!bounds_intersect) {
719 return false;
720 }
721
722 if (!our_complex) {
723 return region.intersects(bounds_);
724 }
725
726 if (!their_complex) {
727 return intersects(region.bounds_);
728 }
729
730 std::vector<SpanLine>::const_iterator ours, theirs;
731 getIntersectionIterators(lines_, region.lines_, ours, theirs);
732 auto ours_end = lines_.end();
733 auto theirs_end = region.lines_.end();
734
735 while (ours != ours_end && theirs != theirs_end) {
736 if (ours->bottom <= theirs->top) {
737 ++ours;
738 } else if (theirs->bottom <= ours->top) {
739 ++theirs;
740 } else {
741 FML_DCHECK(ours->top < theirs->bottom && theirs->top < ours->bottom);
742 const Span *ours_begin, *ours_end;
743 span_buffer_.getSpans(ours->chunk_handle, ours_begin, ours_end);
744 const Span *theirs_begin, *theirs_end;
745 region.span_buffer_.getSpans(theirs->chunk_handle, theirs_begin,
746 theirs_end);
747 if (spansIntersect(ours_begin, ours_end, theirs_begin, theirs_end)) {
748 return true;
749 }
750 if (ours->bottom < theirs->bottom) {
751 ++ours;
752 } else {
753 ++theirs;
754 }
755 }
756 }
757 return false;
758}
bool isComplex() const
Definition: SkRegion.h:158
bool isEmpty() const
Definition: SkRegion.h:146
bool intersects(const SkIRect &rect) const
Definition: SkRegion.cpp:502
bool intersects(const SkIRect &rect) const
Returns whether this region intersects with a rectangle.
Definition: dl_region.cc:617
bool isComplex() const
Returns true if region is not empty and contains more than one rectangle.
Definition: dl_region.cc:611
ClipOpAndAA opAA SkRegion region
Definition: SkRecords.h:238
static bool Intersects(const SkIRect &a, const SkIRect &b)
Definition: SkRect.h:535

◆ intersects() [2/2]

bool flutter::DlRegion::intersects ( const SkIRect rect) const

Returns whether this region intersects with a rectangle.

Definition at line 617 of file dl_region.cc.

617 {
618 if (isEmpty()) {
619 return false;
620 }
621
622 auto bounds_intersect = SkIRect::Intersects(bounds_, rect);
623
624 if (isSimple()) {
625 return bounds_intersect;
626 }
627
628 if (!bounds_intersect) {
629 return false;
630 }
631
632 auto it = lines_.begin();
633 auto end = lines_.end();
634 if (lines_.size() > kBinarySearchThreshold &&
635 it[kBinarySearchThreshold].bottom <= rect.fTop) {
636 it = std::lower_bound(
637 lines_.begin() + kBinarySearchThreshold + 1, lines_.end(), rect.fTop,
638 [](const SpanLine& line, int32_t top) { return line.bottom <= top; });
639 } else {
640 while (it != end && it->bottom <= rect.fTop) {
641 ++it;
642 continue;
643 }
644 }
645 while (it != end && it->top < rect.fBottom) {
646 FML_DCHECK(rect.fTop < it->bottom && it->top < rect.fBottom);
647 const Span *begin, *end;
648 span_buffer_.getSpans(it->chunk_handle, begin, end);
649 while (begin != end && begin->left < rect.fRight) {
650 if (begin->right > rect.fLeft) {
651 return true;
652 }
653 ++begin;
654 }
655 ++it;
656 }
657
658 return false;
659}
static const char * begin(const StringSlice &s)
Definition: editor.cpp:252
glong glong end
const int kBinarySearchThreshold
Definition: dl_region.cc:13

◆ isComplex()

bool flutter::DlRegion::isComplex ( ) const

Returns true if region is not empty and contains more than one rectangle.

Definition at line 611 of file dl_region.cc.

611 {
612 return lines_.size() > 1 ||
613 (lines_.size() == 1 &&
614 span_buffer_.getChunkSize(lines_.front().chunk_handle) > 1);
615}

◆ isEmpty()

bool flutter::DlRegion::isEmpty ( ) const
inline

Returns true if region is empty (contains no rectangles).

Definition at line 62 of file dl_region.h.

62{ return lines_.empty(); }

◆ isSimple()

bool flutter::DlRegion::isSimple ( ) const
inline

Returns true if region can be represented by single rectangle or is empty.

Definition at line 69 of file dl_region.h.

69{ return !isComplex(); }

◆ MakeIntersection()

DlRegion flutter::DlRegion::MakeIntersection ( const DlRegion a,
const DlRegion b 
)
static

Creates intersection region of region a and b. Matches SkRegion a; a.op(b, SkRegion::kIntersect_Op) behavior.

Definition at line 497 of file dl_region.cc.

497 {
498 if (!SkIRect::Intersects(a.bounds_, b.bounds_)) {
499 return DlRegion();
500 } else if (a.isSimple() && b.isSimple()) {
501 SkIRect r(a.bounds_);
502 auto res = r.intersect(b.bounds_);
503 (void)res; // Suppress unused variable warning in release builds.
504 FML_DCHECK(res);
505 return DlRegion(r);
506 } else if (a.isSimple() && a.bounds_.contains(b.bounds_)) {
507 return b;
508 } else if (b.isSimple() && b.bounds_.contains(a.bounds_)) {
509 return a;
510 }
511
512 DlRegion res;
513 res.span_buffer_.reserve(
514 std::max(a.span_buffer_.capacity(), b.span_buffer_.capacity()));
515
516 auto& lines = res.lines_;
517 lines.reserve(std::min(a.lines_.size(), b.lines_.size()));
518
519 std::vector<SpanLine>::const_iterator a_it, b_it;
520 getIntersectionIterators(a.lines_, b.lines_, a_it, b_it);
521
522 auto a_end = a.lines_.end();
523 auto b_end = b.lines_.end();
524
525 auto& a_buffer = a.span_buffer_;
526 auto& b_buffer = b.span_buffer_;
527
528 std::vector<Span> tmp;
529
530 int32_t cur_top = std::numeric_limits<int32_t>::min();
531
532 while (a_it != a_end && b_it != b_end) {
533 auto a_top = std::max(cur_top, a_it->top);
534 auto b_top = std::max(cur_top, b_it->top);
535 if (a_it->bottom <= b_top) {
536 ++a_it;
537 } else if (b_it->bottom <= a_top) {
538 ++b_it;
539 } else {
540 auto top = std::max(a_top, b_top);
541 auto bottom = std::min(a_it->bottom, b_it->bottom);
542 FML_DCHECK(top < bottom);
543 auto size = intersectLineSpans(tmp, a_buffer, a_it->chunk_handle,
544 b_buffer, b_it->chunk_handle);
545 if (size > 0) {
546 res.appendLine(top, bottom, tmp.data(), tmp.data() + size);
547 res.bounds_.join(SkIRect::MakeLTRB(
548 tmp.data()->left, top, (tmp.data() + size - 1)->right, bottom));
549 }
550 cur_top = bottom;
551 if (cur_top == a_it->bottom) {
552 ++a_it;
553 }
554 if (cur_top == b_it->bottom) {
555 ++b_it;
556 }
557 }
558 }
559 FML_DCHECK(a_it == a_end || b_it == b_end);
560 return res;
561}
DlRegion()=default
Creates an empty region.
static bool b
struct MyStruct a[10]
static float max(float r, float g, float b)
Definition: hsl.cpp:49
static float min(float r, float g, float b)
Definition: hsl.cpp:48
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
static constexpr SkIRect MakeLTRB(int32_t l, int32_t t, int32_t r, int32_t b)
Definition: SkRect.h:91

◆ MakeUnion()

DlRegion flutter::DlRegion::MakeUnion ( const DlRegion a,
const DlRegion b 
)
static

Creates union region of region a and b. Matches SkRegion a; a.op(b, SkRegion::kUnion_Op) behavior.

Definition at line 405 of file dl_region.cc.

405 {
406 if (a.isEmpty()) {
407 return b;
408 } else if (b.isEmpty()) {
409 return a;
410 } else if (a.isSimple() && a.bounds_.contains(b.bounds_)) {
411 return a;
412 } else if (b.isSimple() && b.bounds_.contains(a.bounds_)) {
413 return b;
414 }
415
416 DlRegion res;
417 res.bounds_ = a.bounds_;
418 res.bounds_.join(b.bounds_);
419 res.span_buffer_.reserve(a.span_buffer_.capacity() +
420 b.span_buffer_.capacity());
421
422 auto& lines = res.lines_;
423 lines.reserve(a.lines_.size() + b.lines_.size());
424
425 auto a_it = a.lines_.begin();
426 auto b_it = b.lines_.begin();
427 auto a_end = a.lines_.end();
428 auto b_end = b.lines_.end();
429
430 FML_DCHECK(a_it != a_end && b_it != b_end);
431
432 auto& a_buffer = a.span_buffer_;
433 auto& b_buffer = b.span_buffer_;
434
435 std::vector<Span> tmp;
436
437 int32_t cur_top = std::numeric_limits<int32_t>::min();
438
439 while (a_it != a_end && b_it != b_end) {
440 auto a_top = std::max(cur_top, a_it->top);
441 auto b_top = std::max(cur_top, b_it->top);
442 if (a_it->bottom <= b_top) {
443 res.appendLine(a_top, a_it->bottom, a_buffer, a_it->chunk_handle);
444 ++a_it;
445 } else if (b_it->bottom <= a_top) {
446 res.appendLine(b_top, b_it->bottom, b_buffer, b_it->chunk_handle);
447 ++b_it;
448 } else {
449 if (a_top < b_top) {
450 res.appendLine(a_top, b_top, a_buffer, a_it->chunk_handle);
451 cur_top = b_top;
452 if (cur_top == a_it->bottom) {
453 ++a_it;
454 }
455 } else if (b_top < a_top) {
456 res.appendLine(b_top, a_top, b_buffer, b_it->chunk_handle);
457 cur_top = a_top;
458 if (cur_top == b_it->bottom) {
459 ++b_it;
460 }
461 } else {
462 auto new_bottom = std::min(a_it->bottom, b_it->bottom);
463 FML_DCHECK(a_top == b_top);
464 FML_DCHECK(new_bottom > a_top);
465 FML_DCHECK(new_bottom > b_top);
466 auto size = unionLineSpans(tmp, a_buffer, a_it->chunk_handle, b_buffer,
467 b_it->chunk_handle);
468 res.appendLine(a_top, new_bottom, tmp.data(), tmp.data() + size);
469 cur_top = new_bottom;
470 if (cur_top == a_it->bottom) {
471 ++a_it;
472 }
473 if (cur_top == b_it->bottom) {
474 ++b_it;
475 }
476 }
477 }
478 }
479
480 FML_DCHECK(a_it == a_end || b_it == b_end);
481
482 while (a_it != a_end) {
483 auto a_top = std::max(cur_top, a_it->top);
484 res.appendLine(a_top, a_it->bottom, a_buffer, a_it->chunk_handle);
485 ++a_it;
486 }
487
488 while (b_it != b_end) {
489 auto b_top = std::max(cur_top, b_it->top);
490 res.appendLine(b_top, b_it->bottom, b_buffer, b_it->chunk_handle);
491 ++b_it;
492 }
493
494 return res;
495}

◆ operator=() [1/2]

DlRegion & flutter::DlRegion::operator= ( const DlRegion )
default

◆ operator=() [2/2]

DlRegion & flutter::DlRegion::operator= ( DlRegion &&  )
default

The documentation for this class was generated from the following files: