Console Library 4.7.0
A header-only library that makes C++ simple
Loading...
Searching...
No Matches
screen.h
Go to the documentation of this file.
1
8
9/*
10Copyright (c) 2026 MrXie1109
11
12Permission is hereby granted, free of charge, to any person obtaining a copy
13of this software and associated documentation files (the "Software"), to deal
14in the Software without restriction, including without limitation the rights
15to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16copies of the Software, and to permit persons to whom the Software is
17furnished to do so, subject to the following conditions:
18
19The above copyright notice and this permission notice shall be included in all
20copies or substantial portions of the Software.
21
22THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28SOFTWARE.
29*/
30
31#pragma once
32#include <string>
33#include <array>
34#include <iostream>
35#include <cstdlib>
36#include <cmath>
37#include <utility>
38
39namespace console
40{
48 template <unsigned COLS, unsigned ROWS>
49 class Screen
50 {
52 static_assert(COLS % 2 == 0, "COLS must be a multiple of 2!");
54 static_assert(ROWS % 4 == 0, "ROWS must be a multiple of 4!");
55
56 std::array<std::array<unsigned char, COLS / 2>, ROWS / 4> masks;
57
58 public:
60 Screen() : masks() {}
61
68 void point(unsigned x, unsigned y, bool on = true)
69 {
70 if (x >= COLS || y >= ROWS)
71 return;
72 unsigned braille_col = x / 2;
73 unsigned braille_row = y / 4;
74 unsigned sub_x = x % 2;
75 unsigned sub_y = y % 4;
76 static const unsigned char mapping[2][4] = {
77 {0, 1, 2, 6},
78 {3, 4, 5, 7}};
79 unsigned char bit = 1 << mapping[sub_x][sub_y];
80 if (on)
81 masks[braille_row][braille_col] |= bit;
82 else
83 masks[braille_row][braille_col] &= ~bit;
84 }
85
95 void line(int x0, int y0, int x1, int y1, bool on = true)
96 {
97 int dx = std::abs(x1 - x0);
98 int dy = -std::abs(y1 - y0);
99 int sx = x0 < x1 ? 1 : -1;
100 int sy = y0 < y1 ? 1 : -1;
101 int err = dx + dy;
102 while (true)
103 {
104 point(x0, y0, on);
105 if (x0 == x1 && y0 == y1)
106 break;
107 int e2 = 2 * err;
108 if (e2 >= dy)
109 err += dy, x0 += sx;
110 if (e2 <= dx)
111 err += dx, y0 += sy;
112 }
113 }
114
124 void rect(int x0, int y0, int x1, int y1, bool on = true)
125 {
126 line(x0, y0, x1, y0, on);
127 line(x1, y0, x1, y1, on);
128 line(x1, y1, x0, y1, on);
129 line(x0, y1, x0, y0, on);
130 }
131
141 void fillRect(int x0, int y0, int x1, int y1, bool on = true)
142 {
143 if (x0 > x1)
144 std::swap(x0, x1);
145 if (y0 > y1)
146 std::swap(y0, y1);
147 for (int y = y0; y <= y1; ++y)
148 for (int x = x0; x <= x1; ++x)
149 point(x, y, on);
150 }
151
160 void circle(int cx, int cy, int r, bool on = true)
161 {
162 int x = 0, y = r;
163 int d = 3 - 2 * r;
164 while (x <= y)
165 {
166 point(cx + x, cy + y, on);
167 point(cx - x, cy + y, on);
168 point(cx + x, cy - y, on);
169 point(cx - x, cy - y, on);
170 point(cx + y, cy + x, on);
171 point(cx - y, cy + x, on);
172 point(cx + y, cy - x, on);
173 point(cx - y, cy - x, on);
174 if (d < 0)
175 d = d + 4 * x + 6;
176 else
177 d = d + 4 * (x - y) + 10, y--;
178 x++;
179 }
180 }
181
190 void fillCircle(int cx, int cy, int r, bool on = true)
191 {
192 int x = 0, y = r;
193 int d = 3 - 2 * r;
194 while (x <= y)
195 {
196 for (int i = cx - x; i <= cx + x; ++i)
197 {
198 point(i, cy + y, on);
199 point(i, cy - y, on);
200 }
201 for (int i = cx - y; i <= cx + y; ++i)
202 {
203 point(i, cy + x, on);
204 point(i, cy - x, on);
205 }
206
207 if (d < 0)
208 {
209 d += 4 * x + 6;
210 }
211 else
212 {
213 d += 4 * (x - y) + 10;
214 y--;
215 }
216 x++;
217 }
218 }
219
221 void clear()
222 {
223 for (auto &row : masks)
224 for (auto &cell : row)
225 cell = 0;
226 }
227
234 void update(std::ostream &os = std::cout, bool clear = false) const
235 {
236 if (clear)
237 {
238 os << "\033[2J";
239 }
240 std::string out;
241 out.reserve((ROWS / 4) * (COLS / 2 * 3 + 1));
242 for (unsigned row = 0; row < ROWS / 4; ++row)
243 {
244 for (unsigned col = 0; col < COLS / 2; ++col)
245 {
246 unsigned int code = 0x2800 + masks[row][col];
247 out += static_cast<char>(0xE0 | (code >> 12));
248 out += static_cast<char>(0x80 | ((code >> 6) & 0x3F));
249 out += static_cast<char>(0x80 | (code & 0x3F));
250 }
251 out += '\n';
252 }
253 os << "\033[H" << out << std::flush;
254 }
255 };
256}
void point(unsigned x, unsigned y, bool on=true)
在屏幕上绘制一个点。
Definition screen.h:68
void circle(int cx, int cy, int r, bool on=true)
在屏幕上绘制空心圆。
Definition screen.h:160
void fillRect(int x0, int y0, int x1, int y1, bool on=true)
在屏幕上绘制实心矩形。
Definition screen.h:141
void rect(int x0, int y0, int x1, int y1, bool on=true)
在屏幕上绘制空心矩形。
Definition screen.h:124
void line(int x0, int y0, int x1, int y1, bool on=true)
在屏幕上绘制一条直线。
Definition screen.h:95
void clear()
清空屏幕。
Definition screen.h:221
void update(std::ostream &os=std::cout, bool clear=false) const
将 Screen 存储的虚拟屏幕输出到指定流。
Definition screen.h:234
Screen()
默认构造函数,构造一个空白的 Screen
Definition screen.h:60
void fillCircle(int cx, int cy, int r, bool on=true)
在屏幕上绘制实心圆。
Definition screen.h:190
本库所有组件所在的顶层命名空间。