mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
101 lines
3.1 KiB
C++
101 lines
3.1 KiB
C++
// 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 "rtree.h"
|
|
|
|
#include <list>
|
|
|
|
#include "flutter/fml/logging.h"
|
|
#include "third_party/skia/include/core/SkBBHFactory.h"
|
|
|
|
namespace flutter {
|
|
|
|
RTree::RTree() : bbh_{SkRTreeFactory{}()}, all_ops_count_(0) {}
|
|
|
|
void RTree::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 RTree::insert(const SkRect boundsArray[], int N) {
|
|
insert(boundsArray, nullptr, N);
|
|
}
|
|
|
|
void RTree::search(const SkRect& query, std::vector<int>* results) const {
|
|
bbh_->search(query, results);
|
|
}
|
|
|
|
std::list<SkRect> RTree::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 RTree::bytesUsed() const {
|
|
return bbh_->bytesUsed();
|
|
}
|
|
|
|
RTreeFactory::RTreeFactory() {
|
|
r_tree_ = sk_make_sp<RTree>();
|
|
}
|
|
|
|
sk_sp<RTree> RTreeFactory::getInstance() {
|
|
return r_tree_;
|
|
}
|
|
|
|
sk_sp<SkBBoxHierarchy> RTreeFactory::operator()() const {
|
|
return r_tree_;
|
|
}
|
|
|
|
} // namespace flutter
|