forked from flutter/engine
-
Notifications
You must be signed in to change notification settings - Fork 0
/
display_list_rtree.cc
97 lines (83 loc) · 3.12 KB
/
display_list_rtree.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "flutter/display_list/display_list_rtree.h"
#include "flutter/fml/logging.h"
namespace flutter {
DlRTree::DlRTree() : bbh_{SkRTreeFactory{}()}, all_ops_count_(0) {}
void DlRTree::insert(const SkRect boundsArray[],
const SkBBoxHierarchy::Metadata metadata[],
int N) {
FML_DCHECK(0 == all_ops_count_);
bbh_->insert(boundsArray, metadata, N);
for (int i = 0; i < N; i++) {
if (metadata == nullptr || metadata[i].isDraw) {
draw_op_[i] = boundsArray[i];
}
}
all_ops_count_ = N;
}
void DlRTree::insert(const SkRect boundsArray[], int N) {
insert(boundsArray, nullptr, N);
}
void DlRTree::search(const SkRect& query, std::vector<int>* results) const {
bbh_->search(query, results);
}
std::list<SkRect> DlRTree::searchNonOverlappingDrawnRects(
const SkRect& query) const {
// Get the indexes for the operations that intersect with the query rect.
std::vector<int> intermediary_results;
search(query, &intermediary_results);
std::list<SkRect> final_results;
for (int index : intermediary_results) {
auto draw_op = draw_op_.find(index);
// Ignore records that don't draw anything.
if (draw_op == draw_op_.end()) {
continue;
}
auto current_record_rect = draw_op->second;
auto replaced_existing_rect = false;
// // If the current record rect intersects with any of the rects in the
// // result list, then join them, and update the rect in final_results.
std::list<SkRect>::iterator curr_rect_itr = final_results.begin();
std::list<SkRect>::iterator first_intersecting_rect_itr;
while (!replaced_existing_rect && curr_rect_itr != final_results.end()) {
if (SkRect::Intersects(*curr_rect_itr, current_record_rect)) {
replaced_existing_rect = true;
first_intersecting_rect_itr = curr_rect_itr;
curr_rect_itr->join(current_record_rect);
}
curr_rect_itr++;
}
// It's possible that the result contains duplicated rects at this point.
// For example, consider a result list that contains rects A, B. If a
// new rect C is a superset of A and B, then A and B are the same set after
// the merge. As a result, find such cases and remove them from the result
// list.
while (replaced_existing_rect && curr_rect_itr != final_results.end()) {
if (SkRect::Intersects(*curr_rect_itr, *first_intersecting_rect_itr)) {
first_intersecting_rect_itr->join(*curr_rect_itr);
curr_rect_itr = final_results.erase(curr_rect_itr);
} else {
curr_rect_itr++;
}
}
if (!replaced_existing_rect) {
final_results.push_back(current_record_rect);
}
}
return final_results;
}
size_t DlRTree::bytesUsed() const {
return bbh_->bytesUsed();
}
DlRTreeFactory::DlRTreeFactory() {
r_tree_ = sk_make_sp<DlRTree>();
}
sk_sp<DlRTree> DlRTreeFactory::getInstance() {
return r_tree_;
}
sk_sp<SkBBoxHierarchy> DlRTreeFactory::operator()() const {
return r_tree_;
}
} // namespace flutter