#include namespace pake { struct dirty_region_builder { std::vector regions_not_on_bottom; std::list regions_on_bottom; void add_row(const std::vector &row) { std::list new_regions_on_bottom; for (auto i = row.begin(); i < row.end(); ++i) { bool expanded = false; for (auto j = regions_on_bottom.begin(); j != regions_on_bottom.end(); ++j) if (i->start_x == j->start_x && i->width == j->width) { j->height += i->height; new_regions_on_bottom.push_back(*j); regions_on_bottom.erase(j); expanded = true; break; } if (!expanded) new_regions_on_bottom.push_back(*i); } for (auto i = regions_on_bottom.begin(); i != regions_on_bottom.end(); ++i) regions_not_on_bottom.push_back(*i); regions_on_bottom = std::move(new_regions_on_bottom); } }; std::vector dirtiable_image::get_dirty_regions() { dirty_region_builder builder; std::vector row; for (int y = 0; y < dirty.height; ++y) { int r = 0; for (int x = 0; x < dirty.width; ++x) if (!dirty.at(x, y)) { if (r != x) row.push_back({ .start_x = r, .start_y = y, .width = x - r, .height = 1 }); r = x + 1; } if (r != dirty.width) row.push_back({ .start_x = r, .start_y = y, .width = dirty.width - r, .height = 1 }); builder.add_row(row); row.clear(); } builder.add_row(row); return builder.regions_not_on_bottom; } void dirtiable_image::clear_dirty() { dirty.fill(false); } dirtiable_image::dirtiable_image(int width, int height) : image(width, height), dirty(width, height) { dirty.fill(false); } }