OXYGENHUB
◆ main openmsx / src / PlotterPaper.hh
2.1 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
1
#ifndef PLOTTER_PAPER_HH
2
#define PLOTTER_PAPER_HH
3
4
#include "GLUtil.hh"
5
#include "MemBuffer.hh"
6
#include "gl_vec.hh"
7
8
#include <algorithm>
9
#include <cassert>
10
#include <span>
11
#include <utility>
12
13
namespace openmsx {
14
15
using GrayPixel = uint8_t;
16
using RgbPixel = gl::vecN<3, uint8_t>;
17
18
template<typename T> class Canvas
19
{
20
public:
21
	Canvas(gl::ivec2 size, T init_value = T{})
22
		: pixels(size_t(size.x) * size.y)
23
		, sz(size)
24
	{
25
		std::ranges::fill(pixels, init_value);
26
	}
27
28
	[[nodiscard]] gl::ivec2 size() const { return sz; }
29
30
	// Access entire scanline (reduces address calculation overhead)
31
	[[nodiscard]] std::span<T> getLine(int y) {
32
		assert(y >= 0 && y < sz.y);
33
		return std::span<T>(pixels.data() + y * sz.x, sz.x);
34
	}
35
	[[nodiscard]] std::span<const T> getLine(int y) const {
36
		assert(y >= 0 && y < sz.y);
37
		return std::span<const T>(pixels.data() + y * sz.x, sz.x);
38
	}
39
40
private:
41
	MemBuffer<T> pixels;
42
	gl::ivec2 sz;
43
};
44
45
struct BoundingBox {
46
	void clear() { tl = gl::ivec2{0}; br = gl::ivec2{0}; }
47
	[[nodiscard]] bool empty() const { return br.x <= tl.x || br.y <= tl.y; }
48
	[[nodiscard]] gl::ivec2 size() const { return br - tl; }
49
50
	[[nodiscard]] static BoundingBox merge(const BoundingBox& a, const BoundingBox& b) {
51
		if (a.empty()) return b;
52
		if (b.empty()) return a;
53
		return {.tl = min(a.tl, b.tl), .br = max(a.br, b.br)};
54
	}
55
56
	gl::ivec2 tl{}; // top-left corner (inclusive)
57
	gl::ivec2 br{}; // bottom-right corner (exclusive)
58
};
59
60
class PlotterPaper
61
{
62
public:
63
	explicit PlotterPaper(gl::ivec2 size);
64
65
	[[nodiscard]] gl::ivec2 size() const { return paper.size(); }
66
	[[nodiscard]] bool empty() const { return !anythingPlotted; }
67
68
	void draw_dot(gl::vec2 pos, float radius, gl::vec3 color);
69
	void draw_motion(gl::vec2 from, gl::vec2 to, float radius, gl::vec3 color);
70
71
	[[nodiscard]] Canvas<RgbPixel> getRGB() const;
72
	gl::Texture& updateTexture(gl::ivec2 targetSize);
73
74
private:
75
	Canvas<gl::vec3> paper;
76
77
	gl::Texture texture{gl::Null{}};
78
	gl::ivec2 texSize;
79
	BoundingBox damage;
80
81
	bool anythingPlotted = false; // Used to avoid saving blank file when nothing was plotted
82
};
83
84
} // namespace openmsx
85
86
#endif