11 #include "flutter/fml/logging.h"
28 skyline_.push_back(SkylineSegment{0, 0,
width()});
34 return area_so_far_ / (
static_cast<float>(
width()) *
height());
38 struct SkylineSegment {
44 std::vector<SkylineSegment> skyline_;
52 bool RectangleFits(
size_t skyline_index,
int width,
int height,
int* y)
const;
55 void AddSkylineLevel(
size_t skylineIndex,
63 if (
static_cast<unsigned>(p_width) >
static_cast<unsigned>(
width()) ||
64 static_cast<unsigned>(p_height) >
static_cast<unsigned>(
height())) {
69 int bestWidth =
width() + 1;
73 for (
auto i = 0u; i < skyline_.size(); ++i) {
75 if (RectangleFits(i, p_width, p_height, &y)) {
77 if (y < bestY || (y == bestY && skyline_[i].width_ < bestWidth)) {
79 bestWidth = skyline_[i].width_;
80 bestX = skyline_[i].x_;
87 if (-1 != bestIndex) {
88 AddSkylineLevel(bestIndex, bestX, bestY, p_width, p_height);
92 area_so_far_ += p_width * p_height;
101 bool SkylineRectanglePacker::RectangleFits(
size_t skyline_index,
105 int x = skyline_[skyline_index].x_;
106 if (
x + p_width >
width()) {
110 int widthLeft = p_width;
111 size_t i = skyline_index;
112 int y = skyline_[skyline_index].y_;
113 while (widthLeft > 0) {
114 y = std::max(y, skyline_[i].y_);
115 if (y + p_height >
height()) {
118 widthLeft -= skyline_[i].width_;
120 FML_CHECK(i < skyline_.size() || widthLeft <= 0);
127 void SkylineRectanglePacker::AddSkylineLevel(
size_t skyline_index,
132 SkylineSegment newSegment;
134 newSegment.y_ = y + p_height;
135 newSegment.width_ = p_width;
136 skyline_.insert(skyline_.begin() + skyline_index, newSegment);
138 FML_DCHECK(newSegment.x_ + newSegment.width_ <=
width());
139 FML_DCHECK(newSegment.y_ <=
height());
142 for (
auto i = skyline_index + 1; i < skyline_.size(); ++i) {
144 FML_DCHECK(skyline_[i - 1].x_ <= skyline_[i].x_);
146 if (skyline_[i].x_ < skyline_[i - 1].x_ + skyline_[i - 1].width_) {
147 int shrink = skyline_[i - 1].x_ + skyline_[i - 1].width_ - skyline_[i].x_;
149 skyline_[i].x_ += shrink;
150 skyline_[i].width_ -= shrink;
152 if (skyline_[i].width_ <= 0) {
154 skyline_.erase(skyline_.begin() + i);
166 for (
auto i = 0u; i < skyline_.size() - 1; ++i) {
167 if (skyline_[i].y_ == skyline_[i + 1].y_) {
168 skyline_[i].width_ += skyline_[i + 1].width_;
169 skyline_.erase(skyline_.begin() + i + 1);
177 return std::make_shared<SkylineRectanglePacker>(
width,
height);
Packs rectangles into a specified area without rotating them.
static std::shared_ptr< RectanglePacker > Factory(int width, int height)
Return an empty packer with area specified by width and height.
void Reset() final
Empty out all previously added rectangles.
bool AddRect(int w, int h, IPoint16 *loc) final
Attempt to add a rect without moving already placed rectangles.
Scalar PercentFull() const final
Returns how much area has been filled with rectangles.
~SkylineRectanglePacker() final
SkylineRectanglePacker(int w, int h)