Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ FILE: ../../../flutter/flow/raster_cache.h
FILE: ../../../flutter/flow/raster_cache_key.cc
FILE: ../../../flutter/flow/raster_cache_key.h
FILE: ../../../flutter/flow/raster_cache_unittests.cc
FILE: ../../../flutter/flow/rtree.cc
FILE: ../../../flutter/flow/rtree.h
FILE: ../../../flutter/flow/rtree_unittests.cc
FILE: ../../../flutter/flow/scene_update_context.cc
FILE: ../../../flutter/flow/scene_update_context.h
FILE: ../../../flutter/flow/skia_gpu_object.cc
Expand Down
3 changes: 3 additions & 0 deletions flow/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ source_set("flow") {
"raster_cache.h",
"raster_cache_key.cc",
"raster_cache_key.h",
"rtree.cc",
"rtree.h",
"skia_gpu_object.cc",
"skia_gpu_object.h",
"texture.cc",
Expand Down Expand Up @@ -150,6 +152,7 @@ executable("flow_unittests") {
"matrix_decomposition_unittests.cc",
"mutators_stack_unittests.cc",
"raster_cache_unittests.cc",
"rtree_unittests.cc",
"skia_gpu_object_unittests.cc",
"testing/mock_layer_unittests.cc",
"testing/mock_texture_unittests.cc",
Expand Down
100 changes: 100 additions & 0 deletions flow/rtree.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// 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
65 changes: 65 additions & 0 deletions flow/rtree.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// 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.

#ifndef FLUTTER_FLOW_RTREE_H_
#define FLUTTER_FLOW_RTREE_H_

#include <list>
#include <map>

#include "third_party/skia/include/core/SkBBHFactory.h"
#include "third_party/skia/include/core/SkTypes.h"

namespace flutter {
/**
* An R-Tree implementation that forwards calls to an SkRTree.
*
* This implementation provides a searchNonOverlappingDrawnRects method,
* which can be used to query the rects for the operations recorded in the tree.
*/
class RTree : public SkBBoxHierarchy {
public:
RTree();

void insert(const SkRect[],
const SkBBoxHierarchy::Metadata[],
int N) override;
void insert(const SkRect[], int N) override;
void search(const SkRect& query, std::vector<int>* results) const override;
size_t bytesUsed() const override;

// Finds the rects in the tree that represent drawing operations and intersect
// with the query rect.
//
// When two rects intersect with each other, they are joined into a single
// rect which also intersects with the query rect. In other words, the bounds
// of each rect in the result list are mutually exclusive.
std::list<SkRect> searchNonOverlappingDrawnRects(const SkRect& query) const;

// Insertion count (not overall node count, which may be greater).
int getCount() const { return all_ops_count_; }

private:
// A map containing the draw operation rects keyed off the operation index
// in the insert call.
std::map<int, SkRect> draw_op_;
sk_sp<SkBBoxHierarchy> bbh_;
int all_ops_count_;
};

class RTreeFactory : public SkBBHFactory {
public:
RTreeFactory();

// Gets the instance to the R-tree.
sk_sp<RTree> getInstance();
sk_sp<SkBBoxHierarchy> operator()() const override;

private:
sk_sp<RTree> r_tree_;
};

} // namespace flutter

#endif // FLUTTER_FLOW_RTREE_H_
Loading