Line data Source code
1 : /*
2 : * Copyright (C) 2025 aeml
3 : *
4 : * This program is free software: you can redistribute it and/or modify
5 : * it under the terms of the GNU General Public License as published by
6 : * the Free Software Foundation, either version 3 of the License, or
7 : * (at your option) any later version.
8 : *
9 : * This program is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : * GNU General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU General Public License
15 : * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 : */
17 :
18 : #pragma once
19 :
20 : #include <vector>
21 : #include <ostream>
22 : #include <cstddef>
23 : #include <algorithm>
24 :
25 : namespace ascii
26 : {
27 : enum class Color { Default, White, Red, Green, Blue, Yellow, Cyan, Magenta };
28 :
29 : struct Cell
30 : {
31 : char ch;
32 : Color color{Color::Default};
33 :
34 2247448 : bool operator==(const Cell& other) const {
35 2247448 : return ch == other.ch && color == other.color;
36 : }
37 2247448 : bool operator!=(const Cell& other) const {
38 2247448 : return !(*this == other);
39 : }
40 : };
41 :
42 : class TextSurface
43 : {
44 : public:
45 : TextSurface(int width, int height);
46 : void Clear(char fill = ' ', Color color = Color::Default);
47 : void Put(int x, int y, char ch, Color color = Color::Default);
48 761 : int Width() const { return m_width; }
49 761 : int Height() const { return m_height; }
50 14 : const Cell* Data() const { return m_cells.data(); }
51 1508 : Cell* Data() { return m_cells.data(); }
52 : private:
53 : int m_width;
54 : int m_height;
55 : std::vector<Cell> m_cells;
56 : };
57 :
58 : class TextRenderer
59 : {
60 : public:
61 : TextRenderer(int width, int height);
62 : void Clear(char fill = ' ', Color color = Color::Default);
63 : void Put(int x, int y, char ch, Color color = Color::Default);
64 :
65 : // Primitives
66 : void DrawLine(int x0, int y0, int x1, int y1, char ch, Color color = Color::Default);
67 : void DrawRect(int x, int y, int w, int h, char ch, Color color = Color::Default);
68 : void DrawCircle(int xc, int yc, int r, char ch, Color color = Color::Default);
69 : void DrawEllipse(int xc, int yc, int rx, int ry, char ch, Color color = Color::Default);
70 : void FillEllipse(int xc, int yc, int rx, int ry, char ch, Color color = Color::Default);
71 :
72 : // Compute number of changed cells vs previous frame (no output side effects).
73 : std::size_t ComputeDiff() const;
74 : // Present diff to stream and update previous buffer; returns changed cell count.
75 : std::size_t PresentDiff(std::ostream& out);
76 :
77 : // Present full frame regardless of diff state (does not alter headless flag logic).
78 : // Returns number of changed cells vs previous (same metric as ComputeDiff) and updates previous.
79 : std::size_t PresentFull(std::ostream& out);
80 :
81 748 : void SetHeadless(bool headless) { m_headless = headless; }
82 : bool IsHeadless() const noexcept { return m_headless; }
83 :
84 : private:
85 : TextSurface m_current;
86 : TextSurface m_previous;
87 : bool m_headless{false};
88 : };
89 : }
|