REFACTOR: removed Display members: cursorX, cursorY, foreground, background

This commit is contained in:
Patrick Haßel 2025-01-25 20:49:29 +01:00
parent 8bbddc3bb8
commit d57ef636f2
8 changed files with 243 additions and 436 deletions

View File

@ -21,16 +21,9 @@ public:
config.read(); config.read();
display.setup(); display.setup();
display.setBrightness(6); display.setBrightness(6);
display.clear(); display.clear();
display.printf(1, 1, Blue, "Test");
display.foreground = Blue; display.drawLine(0, 7, 32, 0, 1, Red);
display.printf("Test");
display.foreground = Red;
display.cursorX = 0;
display.cursorY = 7;
display.drawLineWH(32, 0, 1);
} }
void loop() override { void loop() override {

View File

@ -1,10 +1,37 @@
#ifndef PATRIX_DISPLAY_H #ifndef PATRIX_DISPLAY_height
#define PATRIX_DISPLAY_H #define PATRIX_DISPLAY_height
#include <Adafruit_NeoPixel.h>
#include "DisplayMatrix_FontCommon.h" #include "DisplayMatrix_FontCommon.h"
#include "DisplayMatrix_FontLower.h"
#include "DisplayMatrix_FontNumberSegments.h"
#include "DisplayMatrix_FontSpecial.h"
#include "DisplayMatrix_FontUpper.h"
inline void fixRect(int& x0, int& y0, int& w, int& h) {
if (w < 0) {
x0 += w;
w = -w;
}
if (h < 0) {
y0 += h;
h = -h;
}
}
class Display { class Display {
Adafruit_NeoPixel leds;
bool dirty = true;
protected:
virtual RGB _read_pixel_(int x, int y) = 0;
virtual void _write_pixel_(int x, int y, RGBA color) = 0;
public: public:
const uint8_t width; const uint8_t width;
@ -13,15 +40,11 @@ public:
const uint16_t pixelCount; const uint16_t pixelCount;
RGBA foreground = White; Display(const int16_t pin, const uint8_t width, const uint8_t height)
: leds(width * height, pin),
RGBA background = Transparent; width(width),
height(height),
int cursorX = 0; pixelCount(width * height) {
int cursorY = 0;
Display(const uint8_t width, const uint8_t height): width(width), height(height), pixelCount(width * height) {
// //
} }
@ -29,45 +52,220 @@ public:
// basic ---------------------------------------------------------------------------------------- // basic ----------------------------------------------------------------------------------------
virtual void setup() {} void setup() {
leds.begin();
leds.setBrightness(10);
clear();
}
virtual void loop() {} void loop() {
if (dirty) {
for (auto y = 0; y < height; y++) {
for (auto x = 0; x < width; x++) {
const auto rgb = _read_pixel_(x, y);
const auto index = y * width + (y % 2 == 0 ? x : width - x - 1);
leds.setPixelColor(index, rgb.r, rgb.g, rgb.b);
}
}
leds.show();
dirty = false;
}
}
virtual void setBrightness(uint8_t brightness) {} void setBrightness(const uint8_t brightness) {
if (leds.getBrightness() != brightness) {
leds.setBrightness(brightness);
dirty = true;
}
}
virtual uint8_t getBrightness(); uint8_t getBrightness() const {
return leds.getBrightness();
}
// draw ----------------------------------------------------------------------------------------- // draw -----------------------------------------------------------------------------------------
virtual void clear() {} void clear() {
fillRect(0, 0, width, height, Black);
}
virtual void setPixel(int x, int y, RGBA color) {} void setPixel(const int x, const int y, const RGBA color) {
if (x < 0 || x >= width || y < 0 || y >= height) {
return;
}
_write_pixel_(x, y, color);
dirty = true;
}
virtual void setPixel(int x, int y) {} void fillRect(int x0, int y0, int w, int h, const RGBA color) {
fixRect(x0, y0, w, h);
for (auto y = y0; y < y0 + h; ++y) {
for (auto x = x0; x < x0 + w; ++x) {
setPixel(x, y, color);
}
}
}
virtual void fillRect(int w, int h) {} void drawLine(int x0, int y0, int w, int h, const int thickness, const RGBA color) {
fixRect(x0, y0, w, h);
virtual void drawLineWH(int x, int y, int w, int h, int thickness) {} if (h == 0) {
for (auto x = x0; x < x0 + w; ++x) {
virtual void drawLineWH(int w, int h, int thickness) {} setPixel(x, y0, color);
}
} else if (w == 0) {
for (auto y = y0; y < y0 + w; ++y) {
setPixel(x0, y, color);
}
} else if (w >= h) {
const auto m = static_cast<double>(h) / w;
for (auto t = 0; t < thickness; ++t) {
const auto offset = t % 2 == 0 ? t / 2 : -t / 2;
for (auto x = x0; x < x0 + w; ++x) {
const auto y = static_cast<int>(round(offset + x * m));
setPixel(x, y, color);
}
}
} else {
const auto m = static_cast<double>(w) / h;
for (auto t = 0; t < thickness; ++t) {
const auto offset = t % 2 == 0 ? t / 2 : -t / 2;
for (auto y = y0; y < y0 + w; ++y) {
const auto x = static_cast<int>(round(offset + y * m));
setPixel(x, y, color);
}
}
}
}
// print ---------------------------------------------------------------------------------------- // print ----------------------------------------------------------------------------------------
virtual void printf(const char *format, ...) {} void printf(const int x, const int y, const RGBA color, const char *format, ...) {
va_list args;
va_start(args, format);
printf(x, y, color, format, args);
va_end(args);
}
virtual void printf(const bool segments, const char *format, ...) {} void printf(const int x, const int y, const RGBA color, const char *format, const va_list args) {
char buffer[64];
vsnprintf(buffer, sizeof buffer, format, args);
print(x, y, color, buffer);
}
virtual void printf(bool segments, const char *format, const va_list args) {} void print(int x, int y, const RGBA color, const char *message) {
while (*message != '\0') {
print(&x, &y, color, &message);
x += 2; // space between characters
}
}
virtual void print(const char *str) {} void print(int *x, int *y, const RGBA color, const char **cPP) {
const auto character = *(*cPP)++;
virtual void print(const bool segments, const char *str) {} if ('0' <= character && character <= '9') {
return print(x, y, reinterpret_cast<bool *>(FONT_NUMBER_SEGMENTS[character - '0']), countof(FONT_NUMBER_SEGMENTS[character - '0'][0]), countof(FONT_NUMBER_SEGMENTS[character - '0']), color);
}
if ('A' <= character && character <= 'Z') {
return print(x, y, reinterpret_cast<bool *>(FONT_UPPER[character - 'A']), countof(FONT_UPPER[character - 'A'][0]), countof(FONT_UPPER[character - 'A']), color);
}
if ('a' <= character && character <= 'z') {
return print(x, y, reinterpret_cast<bool *>(FONT_LOWER[character - 'a']), countof(FONT_LOWER[character - 'a'][0]), countof(FONT_LOWER[character - 'a']), color);
}
virtual void print(const bool segments, const char **cPP) {} if (character == 0xC2) {
const auto secondCharacter = *(*cPP)++;
if (secondCharacter == 0xB0) {
return print(x, y, reinterpret_cast<bool *>(FONT_CHAR_DEGREE), countof(FONT_CHAR_DEGREE[0]), countof(FONT_CHAR_DEGREE), color);
}
return printERROR(x, y, color);
}
virtual void print(bool *s, size_t w, size_t h) {} if (character == 0xE2) {
const auto secondCharacter = *(*cPP)++;
if (secondCharacter == 0x82) {
const auto thirdCharacter = *(*cPP)++;
if (thirdCharacter == 0xAC) {
return print(x, y, reinterpret_cast<bool *>(FONT_CHAR_EURO), countof(FONT_CHAR_EURO[0]), countof(FONT_CHAR_EURO), color);
}
return printERROR(x, y, color);
}
return printERROR(x, y, color);
}
virtual void print(RGBA *s, size_t w, size_t h) {} if (character == '\n') {
*y += 6;
return;
}
switch (character) {
case ' ': return print(x, y, reinterpret_cast<bool *>(FONT_CHAR_SPACE), countof(FONT_CHAR_SPACE[0]), countof(FONT_CHAR_SPACE), color);
case '-': return print(x, y, reinterpret_cast<bool *>(FONT_CHAR_MINUS), countof(FONT_CHAR_MINUS[0]), countof(FONT_CHAR_MINUS), color);
case '+': return print(x, y, reinterpret_cast<bool *>(FONT_CHAR_PLUS), countof(FONT_CHAR_PLUS[0]), countof(FONT_CHAR_PLUS), color);
case '_': return print(x, y, reinterpret_cast<bool *>(FONT_CHAR_UNDERLINE), countof(FONT_CHAR_UNDERLINE[0]), countof(FONT_CHAR_UNDERLINE), color);
case '%': return print(x, y, reinterpret_cast<bool *>(FONT_CHAR_PERCENT), countof(FONT_CHAR_PERCENT[0]), countof(FONT_CHAR_PERCENT), color);
case '?': return print(x, y, reinterpret_cast<bool *>(FONT_CHAR_QUESTION), countof(FONT_CHAR_QUESTION[0]), countof(FONT_CHAR_QUESTION), color);
case '!': return print(x, y, reinterpret_cast<bool *>(FONT_CHAR_EXCLAMATION), countof(FONT_CHAR_EXCLAMATION[0]), countof(FONT_CHAR_EXCLAMATION), color);
case '.': return print(x, y, reinterpret_cast<bool *>(FONT_CHAR_POINT), countof(FONT_CHAR_POINT[0]), countof(FONT_CHAR_POINT), color);
case ',': return print(x, y, reinterpret_cast<bool *>(FONT_CHAR_COMMA), countof(FONT_CHAR_COMMA[0]), countof(FONT_CHAR_COMMA), color);
case ';': return print(x, y, reinterpret_cast<bool *>(FONT_CHAR_SEMICOLON), countof(FONT_CHAR_SEMICOLON[0]), countof(FONT_CHAR_SEMICOLON), color);
case ':': return print(x, y, reinterpret_cast<bool *>(FONT_CHAR_COLON), countof(FONT_CHAR_COLON[0]), countof(FONT_CHAR_COLON), color);
case '#': return print(x, y, reinterpret_cast<bool *>(FONT_CHAR_SHARP), countof(FONT_CHAR_SHARP[0]), countof(FONT_CHAR_SHARP), color);
case '~': return print(x, y, reinterpret_cast<bool *>(FONT_CHAR_TILDE), countof(FONT_CHAR_TILDE[0]), countof(FONT_CHAR_TILDE), color);
case '*': return print(x, y, reinterpret_cast<bool *>(FONT_CHAR_ASTERISK), countof(FONT_CHAR_ASTERISK[0]), countof(FONT_CHAR_ASTERISK), color);
case '"': return print(x, y, reinterpret_cast<bool *>(FONT_CHAR_QUOTE_DOUBLE), countof(FONT_CHAR_QUOTE_DOUBLE[0]), countof(FONT_CHAR_QUOTE_DOUBLE), color);
case '\'': return print(x, y, reinterpret_cast<bool *>(FONT_CHAR_QUOTE_SINGLE), countof(FONT_CHAR_QUOTE_SINGLE[0]), countof(FONT_CHAR_QUOTE_SINGLE), color);
case '=': return print(x, y, reinterpret_cast<bool *>(FONT_CHAR_EQUALS), countof(FONT_CHAR_EQUALS[0]), countof(FONT_CHAR_EQUALS), color);
case '(': return print(x, y, reinterpret_cast<bool *>(FONT_CHAR_PAR_L), countof(FONT_CHAR_PAR_L[0]), countof(FONT_CHAR_PAR_L), color);
case ')': return print(x, y, reinterpret_cast<bool *>(FONT_CHAR_PAR_R), countof(FONT_CHAR_PAR_R[0]), countof(FONT_CHAR_PAR_R), color);
case '[': return print(x, y, reinterpret_cast<bool *>(FONT_CHAR_BRACKET_L), countof(FONT_CHAR_BRACKET_L[0]), countof(FONT_CHAR_BRACKET_L), color);
case ']': return print(x, y, reinterpret_cast<bool *>(FONT_CHAR_BRACKET_R), countof(FONT_CHAR_BRACKET_R[0]), countof(FONT_CHAR_BRACKET_R), color);
case '{': return print(x, y, reinterpret_cast<bool *>(FONT_CHAR_CURL_L), countof(FONT_CHAR_CURL_L[0]), countof(FONT_CHAR_CURL_L), color);
case '}': return print(x, y, reinterpret_cast<bool *>(FONT_CHAR_CURL_R), countof(FONT_CHAR_CURL_R[0]), countof(FONT_CHAR_CURL_R), color);
case '/': return print(x, y, reinterpret_cast<bool *>(FONT_CHAR_SLASH), countof(FONT_CHAR_SLASH[0]), countof(FONT_CHAR_SLASH), color);
case '\\': return print(x, y, reinterpret_cast<bool *>(FONT_CHAR_BACKSLASH), countof(FONT_CHAR_BACKSLASH[0]), countof(FONT_CHAR_BACKSLASH), color);
case '&': return print(x, y, reinterpret_cast<bool *>(FONT_CHAR_AND), countof(FONT_CHAR_AND[0]), countof(FONT_CHAR_AND), color);
case '|': return print(x, y, reinterpret_cast<bool *>(FONT_CHAR_PIPE), countof(FONT_CHAR_PIPE[0]), countof(FONT_CHAR_PIPE), color);
case '$': return print(x, y, reinterpret_cast<bool *>(FONT_CHAR_DOLLAR), countof(FONT_CHAR_DOLLAR[0]), countof(FONT_CHAR_DOLLAR), color);
case '@': return print(x, y, reinterpret_cast<bool *>(FONT_CHAR_AT), countof(FONT_CHAR_AT[0]), countof(FONT_CHAR_AT), color);
case '<': return print(x, y, reinterpret_cast<bool *>(FONT_CHAR_LT), countof(FONT_CHAR_LT[0]), countof(FONT_CHAR_LT), color);
case '>': return print(x, y, reinterpret_cast<bool *>(FONT_CHAR_GT), countof(FONT_CHAR_GT[0]), countof(FONT_CHAR_GT), color);
default: return printERROR(x, y, color);
}
}
void printERROR(int *x, const int *y, const RGBA color) {
return print(x, y, reinterpret_cast<bool *>(FONT_ERROR_), countof(FONT_ERROR_[0]), countof(FONT_ERROR_), color);
}
void print(int *x0, const int *y0, const bool *s, const int w, const int h, const RGBA color) {
auto maxWidth = 0;
for (auto y = 0; y < h; y++) {
for (auto x = 0; x < w; x++) {
const auto symbolIndex = y * w + x;
const auto active = *(s + symbolIndex);
const auto pixelX = *x0 + x;
const auto pixelY = *y0 + y;
if (active) {
setPixel(pixelX, pixelY, color);
maxWidth = max(x, maxWidth);
}
}
}
*x0 += maxWidth;
}
void print(int *x0, const int *y0, const RGBA *s, const int w, const int h) {
for (auto y = 0; y < h; y++) {
for (auto x = 0; x < w; x++) {
const auto symbolIndex = y * w + x;
const auto color = *(s + symbolIndex);
const auto pixelX = *x0 + x;
const auto pixelY = *y0 + y;
setPixel(pixelX, pixelY, color);
}
}
*x0 += w;
}
}; };

View File

@ -1,98 +1,32 @@
#ifndef DISPLAY_MATRIX_H #ifndef DISPLAY_MATRIX_H
#define DISPLAY_MATRIX_H #define DISPLAY_MATRIX_H
#include <Adafruit_NeoPixel.h>
#include "Display.h" #include "Display.h"
template<int W, int H> template<int W, int H>
class DisplayMatrix final : public Display { class DisplayMatrix final : public Display {
Adafruit_NeoPixel leds;
RGB matrix[H][W] = {}; RGB matrix[H][W] = {};
bool dirty = true; protected:
RGB _read_pixel_(int x, int y) override {
return matrix[y][x];
}
void _write_pixel_(const int x, const int y, const RGBA color) override {
matrix[y][x] = color;
}
public: public:
explicit DisplayMatrix(const int16_t pin): Display(W, H), leds(W * H, pin) { explicit DisplayMatrix(const int16_t pin)
: Display(pin, W, H) {
// //
} }
~DisplayMatrix() override = default; ~DisplayMatrix() override = default;
// basic ----------------------------------------------------------------------------------------
void setup() override {
leds.begin();
leds.setBrightness(10);
clear();
}
void loop() override {
if (dirty) {
for (auto y = 0; y < H; y++) {
for (auto x = 0; x < W; x++) {
auto rgb = matrix[y][x];
const auto index = y * W + (y % 2 == 0 ? x : W - x - 1);
leds.setPixelColor(index, rgb.r, rgb.g, rgb.b);
}
}
leds.show();
dirty = false;
}
}
void setBrightness(const uint8_t brightness) override {
if (leds.getBrightness() != brightness) {
leds.setBrightness(brightness);
dirty = true;
}
}
uint8_t getBrightness() override {
return leds.getBrightness();
}
// draw -----------------------------------------------------------------------------------------
void clear() override;
void setPixel(int x, int y) override;
void setPixel(int x, int y, RGBA color) override;
void fillRect(int w, int h) override;
void drawLineWH(int x, int y, int w, int h, int thickness) override;
void drawLineWH(int w, int h, int thickness) override;
// print ----------------------------------------------------------------------------------------
void printf(const char *format, ...) override;
void printf(bool segments, const char *format, ...) override;
void printf(bool segments, const char *format, va_list args) override;
void print(const char *message) override;
void print(bool segments, const char *message) override;
void print(bool segments, const char **cPP) override;
void print(bool *s, size_t w, size_t h) override;
void print(RGBA *s, size_t w, size_t h) override;
}; };
// ReSharper disable once CppUnusedIncludeDirective
#include <patrix/display/DisplayMatrix_draw.h>
// ReSharper disable once CppUnusedIncludeDirective
#include <patrix/display/DisplayMatrix_print.h>
#endif #endif

View File

@ -1,74 +0,0 @@
#include "DisplayMatrix_FontNumber.h"
Symbol4 FONT_NUMBER[] = {
{
{_,X,X,_},
{X,_,_,X},
{X,_,_,X},
{X,_,_,X},
{_,X,X,_},
},
{
{_,_,X,_},
{_,X,X,_},
{X,_,X,_},
{_,_,X,_},
{_,_,X,_},
},
{
{_,X,X,_},
{X,_,_,X},
{_,_,X,_},
{_,X,_,_},
{X,X,X,X},
},
{
{_,X,X,_},
{X,_,_,X},
{_,_,X,_},
{X,_,_,X},
{_,X,X,_},
},
{
{X,_,_,X},
{X,_,_,X},
{X,X,X,X},
{_,_,_,X},
{_,_,_,X},
},
{
{X,X,X,X},
{X,_,_,_},
{X,X,X,_},
{_,_,_,X},
{X,X,X,_},
},
{
{_,X,X,_},
{X,_,_,_},
{X,X,X,_},
{X,_,_,X},
{_,X,X,_},
},
{
{X,X,X,X},
{_,_,_,X},
{_,_,X,_},
{_,X,_,_},
{X,_,_,_},
},
{
{_,X,X,_},
{X,_,_,X},
{_,X,X,_},
{X,_,_,X},
{_,X,X,_},
},
{
{_,X,X,_},
{X,_,_,X},
{_,X,X,X},
{_,_,_,X},
{_,X,X,_},
},
};

View File

@ -1,8 +0,0 @@
#ifndef DISPLAY_MATRIX_FONT_NUMBER_H
#define DISPLAY_MATRIX_FONT_NUMBER_H
#include "DisplayMatrix_FontCommon.h"
extern Symbol4 FONT_NUMBER[];
#endif

View File

@ -1,4 +1,4 @@
#include "DisplayMatrix_FontNumber.h" #include "DisplayMatrix_FontCommon.h"
Symbol4 FONT_NUMBER_SEGMENTS[] = { Symbol4 FONT_NUMBER_SEGMENTS[] = {
{ {

View File

@ -1,83 +0,0 @@
#ifndef DISPLAY_MATRIX_DRAW_H
#define DISPLAY_MATRIX_DRAW_H
template<int W, int H>
void DisplayMatrix<W, H>::clear() {
const auto backup = foreground;
foreground = Black;
cursorX = 0;
cursorY = 0;
fillRect(W, H);
foreground = backup;
}
template<int W, int H>
void DisplayMatrix<W, H>::setPixel(const int x, const int y) {
setPixel(x, y, foreground);
}
template<int W, int H>
void DisplayMatrix<W, H>::setPixel(int x, int y, RGBA color) {
if (x < 0 || x >= W || y < 0 || y >= H) {
return;
}
matrix[y][x] = color;
dirty = true;
}
template<int W, int H>
void DisplayMatrix<W, H>::fillRect(const int w, const int h) {
if (w < 1 || h < 1) {
return;
}
for (auto y = cursorY; y < cursorY + h; ++y) {
for (auto x = cursorX; x < cursorX + w; ++x) {
setPixel(x, y);
}
}
dirty = true;
}
template<int W, int H>
void DisplayMatrix<W, H>::drawLineWH(int x, int y, int w, int h, const int thickness) {
if (w < 0) {
x -= w;
w = -w;
}
if (h < 0) {
y -= h;
h = -h;
}
cursorX = x;
cursorY = y;
drawLineWH(w, h, thickness);
}
template<int W, int H>
void DisplayMatrix<W, H>::drawLineWH(const int w, const int h, const int thickness) {
if (w < 1 && h < 1) {
return;
}
if (w >= h) {
const auto m = static_cast<double>(h) / w;
for (auto t = 0; t < thickness; ++t) {
const auto offset = t % 2 == 0 ? t / 2 : -t / 2;
for (auto x = 0; x < w; ++x) {
const auto y = static_cast<int>(round(offset + x * m));
setPixel(cursorY + y, cursorX + x);
}
}
} else {
const auto m = static_cast<double>(w) / h;
for (auto t = 0; t < thickness; ++t) {
const auto offset = t % 2 == 0 ? t / 2 : -t / 2;
for (auto y = 0; y < w; ++y) {
const auto x = static_cast<int>(round(offset + y * m));
setPixel(cursorY + y, cursorX + x);
}
}
}
dirty = true;
}
#endif

View File

@ -1,153 +0,0 @@
#ifndef DISPLAYMATRIX_PRINT_H
#define DISPLAYMATRIX_PRINT_H
#include "DisplayMatrix_FontLower.h"
#include "DisplayMatrix_FontNumber.h"
#include "DisplayMatrix_FontNumberSegments.h"
#include "DisplayMatrix_FontSpecial.h"
#include "DisplayMatrix_FontUpper.h"
template<int W, int H>
void DisplayMatrix<W, H>::printf(const char *format, ...) {
va_list args;
va_start(args, format);
printf(false, format, args);
va_end(args);
}
template<int W, int H>
void DisplayMatrix<W, H>::printf(const bool segments, const char *format, ...) {
va_list args;
va_start(args, format);
printf(segments, format, args);
va_end(args);
}
template<int W, int H>
void DisplayMatrix<W, H>::printf(const bool segments, const char *format, const va_list args) {
char buffer[64];
vsnprintf(buffer, sizeof buffer, format, args);
print(segments, buffer);
}
template<int W, int H>
void DisplayMatrix<W, H>::print(const char *message) {
print(false, message);
}
template<int W, int H>
void DisplayMatrix<W, H>::print(const bool segments, const char *message) {
while (*message != '\0') {
print(segments, &message);
cursorX += 2; // space between characters
}
}
template<int W, int H>
void DisplayMatrix<W, H>::print(const bool segments, const char **cPP) {
const auto a = *(*cPP)++;
auto b = '\0';
if (a == 0xC2) {
b = *(*cPP)++;
switch (b) { // NOLINT(*-multiway-paths-covered)
case 0xB0: return print(reinterpret_cast<bool *>(FONT_CHAR_DEGREE), countof(FONT_CHAR_DEGREE[0]), countof(FONT_CHAR_DEGREE));
default: return print(reinterpret_cast<bool *>(FONT_ERROR_), countof(FONT_ERROR_[0]), countof(FONT_ERROR_));
}
}
if (a == 0xE2) {
auto c = '\0';
b = *(*cPP)++;
switch (b) { // NOLINT(*-multiway-paths-covered)
case 0x82:
c = *(*cPP)++;
switch (c) { // NOLINT(*-multiway-paths-covered)
case 0xAC: return print(reinterpret_cast<bool *>(FONT_CHAR_EURO), countof(FONT_CHAR_EURO[0]), countof(FONT_CHAR_EURO));
default: return print(reinterpret_cast<bool *>(FONT_ERROR_), countof(FONT_ERROR_[0]), countof(FONT_ERROR_));
}
default: return print(reinterpret_cast<bool *>(FONT_ERROR_), countof(FONT_ERROR_[0]), countof(FONT_ERROR_));
}
}
if ('a' <= a && a <= 'z') {
return print(reinterpret_cast<bool *>(FONT_LOWER[a - 'a']), countof(FONT_LOWER[a - 'a'][0]), countof(FONT_LOWER[a - 'a']));
}
if ('A' <= a && a <= 'Z') {
return print(reinterpret_cast<bool *>(FONT_UPPER[a - 'A']), countof(FONT_UPPER[a - 'A'][0]), countof(FONT_UPPER[a - 'A']));
}
if ('0' <= a && a <= '9') {
if (segments){
return print(reinterpret_cast<bool *>(FONT_NUMBER[a - '0']), countof(FONT_NUMBER[a - '0'][0]), countof(FONT_NUMBER[a - '0']));
}
return print(reinterpret_cast<bool *>(FONT_NUMBER_SEGMENTS[a - '0']), countof(FONT_NUMBER_SEGMENTS[a - '0'][0]), countof(FONT_NUMBER_SEGMENTS[a - '0']));
}
switch (a) {
case ' ': return print(reinterpret_cast<bool *>(FONT_CHAR_SPACE), countof(FONT_CHAR_SPACE[0]), countof(FONT_CHAR_SPACE));
case '-': return print(reinterpret_cast<bool *>(FONT_CHAR_MINUS), countof(FONT_CHAR_MINUS[0]), countof(FONT_CHAR_MINUS));
case '+': return print(reinterpret_cast<bool *>(FONT_CHAR_PLUS), countof(FONT_CHAR_PLUS[0]), countof(FONT_CHAR_PLUS));
case '_': return print(reinterpret_cast<bool *>(FONT_CHAR_UNDERLINE), countof(FONT_CHAR_UNDERLINE[0]), countof(FONT_CHAR_UNDERLINE));
case '%': return print(reinterpret_cast<bool *>(FONT_CHAR_PERCENT), countof(FONT_CHAR_PERCENT[0]), countof(FONT_CHAR_PERCENT));
case '?': return print(reinterpret_cast<bool *>(FONT_CHAR_QUESTION), countof(FONT_CHAR_QUESTION[0]), countof(FONT_CHAR_QUESTION));
case '!': return print(reinterpret_cast<bool *>(FONT_CHAR_EXCLAMATION), countof(FONT_CHAR_EXCLAMATION[0]), countof(FONT_CHAR_EXCLAMATION));
case '.': return print(reinterpret_cast<bool *>(FONT_CHAR_POINT), countof(FONT_CHAR_POINT[0]), countof(FONT_CHAR_POINT));
case ',': return print(reinterpret_cast<bool *>(FONT_CHAR_COMMA), countof(FONT_CHAR_COMMA[0]), countof(FONT_CHAR_COMMA));
case ';': return print(reinterpret_cast<bool *>(FONT_CHAR_SEMICOLON), countof(FONT_CHAR_SEMICOLON[0]), countof(FONT_CHAR_SEMICOLON));
case ':': return print(reinterpret_cast<bool *>(FONT_CHAR_COLON), countof(FONT_CHAR_COLON[0]), countof(FONT_CHAR_COLON));
case '#': return print(reinterpret_cast<bool *>(FONT_CHAR_SHARP), countof(FONT_CHAR_SHARP[0]), countof(FONT_CHAR_SHARP));
case '~': return print(reinterpret_cast<bool *>(FONT_CHAR_TILDE), countof(FONT_CHAR_TILDE[0]), countof(FONT_CHAR_TILDE));
case '*': return print(reinterpret_cast<bool *>(FONT_CHAR_ASTERISK), countof(FONT_CHAR_ASTERISK[0]), countof(FONT_CHAR_ASTERISK));
case '"': return print(reinterpret_cast<bool *>(FONT_CHAR_QUOTE_DOUBLE), countof(FONT_CHAR_QUOTE_DOUBLE[0]), countof(FONT_CHAR_QUOTE_DOUBLE));
case '\'': return print(reinterpret_cast<bool *>(FONT_CHAR_QUOTE_SINGLE), countof(FONT_CHAR_QUOTE_SINGLE[0]), countof(FONT_CHAR_QUOTE_SINGLE));
case '=': return print(reinterpret_cast<bool *>(FONT_CHAR_EQUALS), countof(FONT_CHAR_EQUALS[0]), countof(FONT_CHAR_EQUALS));
case '(': return print(reinterpret_cast<bool *>(FONT_CHAR_PAR_L), countof(FONT_CHAR_PAR_L[0]), countof(FONT_CHAR_PAR_L));
case ')': return print(reinterpret_cast<bool *>(FONT_CHAR_PAR_R), countof(FONT_CHAR_PAR_R[0]), countof(FONT_CHAR_PAR_R));
case '[': return print(reinterpret_cast<bool *>(FONT_CHAR_BRACKET_L), countof(FONT_CHAR_BRACKET_L[0]), countof(FONT_CHAR_BRACKET_L));
case ']': return print(reinterpret_cast<bool *>(FONT_CHAR_BRACKET_R), countof(FONT_CHAR_BRACKET_R[0]), countof(FONT_CHAR_BRACKET_R));
case '{': return print(reinterpret_cast<bool *>(FONT_CHAR_CURL_L), countof(FONT_CHAR_CURL_L[0]), countof(FONT_CHAR_CURL_L));
case '}': return print(reinterpret_cast<bool *>(FONT_CHAR_CURL_R), countof(FONT_CHAR_CURL_R[0]), countof(FONT_CHAR_CURL_R));
case '/': return print(reinterpret_cast<bool *>(FONT_CHAR_SLASH), countof(FONT_CHAR_SLASH[0]), countof(FONT_CHAR_SLASH));
case '\\': return print(reinterpret_cast<bool *>(FONT_CHAR_BACKSLASH), countof(FONT_CHAR_BACKSLASH[0]), countof(FONT_CHAR_BACKSLASH));
case '&': return print(reinterpret_cast<bool *>(FONT_CHAR_AND), countof(FONT_CHAR_AND[0]), countof(FONT_CHAR_AND));
case '|': return print(reinterpret_cast<bool *>(FONT_CHAR_PIPE), countof(FONT_CHAR_PIPE[0]), countof(FONT_CHAR_PIPE));
case '$': return print(reinterpret_cast<bool *>(FONT_CHAR_DOLLAR), countof(FONT_CHAR_DOLLAR[0]), countof(FONT_CHAR_DOLLAR));
case '@': return print(reinterpret_cast<bool *>(FONT_CHAR_AT), countof(FONT_CHAR_AT[0]), countof(FONT_CHAR_AT));
case '<': return print(reinterpret_cast<bool *>(FONT_CHAR_LT), countof(FONT_CHAR_LT[0]), countof(FONT_CHAR_LT));
case '>': return print(reinterpret_cast<bool *>(FONT_CHAR_GT), countof(FONT_CHAR_GT[0]), countof(FONT_CHAR_GT));
default: return print(reinterpret_cast<bool *>(FONT_ERROR_), countof(FONT_ERROR_[0]), countof(FONT_ERROR_));
}
}
template<int W, int H>
void DisplayMatrix<W, H>::print(bool *s, const size_t w, const size_t h) {
auto symbolMaxX = 0;
for (auto symbolY = 0; symbolY < h; symbolY++) {
for (auto symbolX = 0; symbolX < w; symbolX++) {
const auto symbolIndex = symbolY * w + symbolX;
const auto active = *(s + symbolIndex);
const auto pixelX = cursorX + symbolX;
const auto pixelY = cursorY + symbolY;
if (active) {
setPixel(pixelX, pixelY);
symbolMaxX = max(symbolX, symbolMaxX);
} else {
setPixel(pixelX, pixelY, background);
}
}
}
cursorX += symbolMaxX;
}
template<int W, int H>
void DisplayMatrix<W, H>::print(RGBA *s, const size_t w, const size_t h) {
for (auto symbolY = 0; symbolY < h; symbolY++) {
for (auto symbolX = 0; symbolX < w; symbolX++) {
const auto symbolIndex = symbolY * w + symbolX;
const auto color = *(s + symbolIndex);
const auto pixelX = cursorX + symbolX;
const auto pixelY = cursorY + symbolY;
setPixel(pixelX, pixelY, color);
}
}
cursorX += w;
}
#endif