// 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 #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* results) const { bbh_->search(query, results); } std::list RTree::searchNonOverlappingDrawnRects( const SkRect& query) const { // Get the indexes for the operations that intersect with the query rect. std::vector intermediary_results; search(query, &intermediary_results); std::list 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::iterator curr_rect_itr = final_results.begin(); std::list::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(); } sk_sp RTreeFactory::getInstance() { return r_tree_; } sk_sp RTreeFactory::operator()() const { return r_tree_; } } // namespace flutter