summaryrefslogtreecommitdiff
path: root/libraries/pake/source/dirtiable-image.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/pake/source/dirtiable-image.cpp')
-rw-r--r--libraries/pake/source/dirtiable-image.cpp80
1 files changed, 80 insertions, 0 deletions
diff --git a/libraries/pake/source/dirtiable-image.cpp b/libraries/pake/source/dirtiable-image.cpp
new file mode 100644
index 0000000..9e5c979
--- /dev/null
+++ b/libraries/pake/source/dirtiable-image.cpp
@@ -0,0 +1,80 @@
+#include <pake/dirtiable-image.hpp>
+
+namespace pake {
+
+ struct dirty_region_builder {
+
+ std::vector<region> regions_not_on_bottom;
+ std::list<region> regions_on_bottom;
+
+ void add_row(const std::vector<region> &row) {
+
+ std::list<region> 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<region> dirtiable_image::get_dirty_regions() {
+
+ dirty_region_builder builder;
+
+ std::vector<region> 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);
+ }
+
+}