10#include "flutter/fml/logging.h"
27 skyline_.push_back(SkylineSegment{0, 0,
width()});
37 struct SkylineSegment {
43 std::vector<SkylineSegment> skyline_;
51 bool RectangleFits(
size_t skyline_index,
int width,
int height,
int*
y)
const;
54 void AddSkylineLevel(
size_t skylineIndex,
62 if ((
unsigned)p_width > (
unsigned)
width() ||
63 (
unsigned)p_height > (
unsigned)
height()) {
68 int bestWidth =
width() + 1;
72 for (
auto i = 0u;
i < skyline_.size(); ++
i) {
74 if (RectangleFits(
i, p_width, p_height, &
y)) {
76 if (
y < bestY || (
y == bestY && skyline_[
i].width_ < bestWidth)) {
78 bestWidth = skyline_[
i].width_;
79 bestX = skyline_[
i].x_;
86 if (-1 != bestIndex) {
87 AddSkylineLevel(bestIndex, bestX, bestY, p_width, p_height);
91 area_so_far_ += p_width * p_height;
100bool SkylineRectanglePacker::RectangleFits(
size_t skyline_index,
104 int x = skyline_[skyline_index].x_;
105 if (
x + p_width >
width()) {
109 int widthLeft = p_width;
110 size_t i = skyline_index;
111 int y = skyline_[skyline_index].y_;
112 while (widthLeft > 0) {
117 widthLeft -= skyline_[
i].width_;
119 FML_CHECK(
i < skyline_.size() || widthLeft <= 0);
126void SkylineRectanglePacker::AddSkylineLevel(
size_t skyline_index,
131 SkylineSegment newSegment;
133 newSegment.y_ =
y + p_height;
134 newSegment.width_ = p_width;
135 skyline_.insert(skyline_.begin() + skyline_index, newSegment);
141 for (
auto i = skyline_index + 1;
i < skyline_.size(); ++
i) {
145 if (skyline_[
i].x_ < skyline_[
i - 1].x_ + skyline_[
i - 1].width_) {
146 int shrink = skyline_[
i - 1].x_ + skyline_[
i - 1].width_ - skyline_[
i].x_;
148 skyline_[
i].x_ += shrink;
149 skyline_[
i].width_ -= shrink;
151 if (skyline_[
i].width_ <= 0) {
153 skyline_.erase(skyline_.begin() +
i);
165 for (
auto i = 0u;
i < skyline_.size() - 1; ++
i) {
166 if (skyline_[
i].y_ == skyline_[
i + 1].y_) {
167 skyline_[
i].width_ += skyline_[
i + 1].width_;
168 skyline_.erase(skyline_.begin() +
i + 1);
176 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)
#define FML_CHECK(condition)
#define FML_DCHECK(condition)
static float max(float r, float g, float b)