diff --git a/src/demo/NodeTest.h b/src/demo/NodeTest.h index 8e1019f..caa7f21 100644 --- a/src/demo/NodeTest.h +++ b/src/demo/NodeTest.h @@ -22,7 +22,7 @@ public: display.setup(); display.setBrightness(6); display.clear(); - display.printf(1, 1, Blue, "Test"); + display.printf(1, 1, LEFT, Blue, "Test"); display.drawLine(0, 7, 32, 0, 1, Red); } diff --git a/src/patrix/display/Display.h b/src/patrix/display/Display.h index 99a766a..e4dc305 100644 --- a/src/patrix/display/Display.h +++ b/src/patrix/display/Display.h @@ -9,6 +9,8 @@ #include "DisplayMatrix_FontSpecial.h" #include "DisplayMatrix_FontUpper.h" +#include + inline void fixRect(int& x0, int& y0, int& w, int& h) { if (w < 0) { x0 += w; @@ -20,6 +22,10 @@ inline void fixRect(int& x0, int& y0, int& w, int& h) { } } +enum Align { + LEFT, CENTER, RIGHT +}; + class Display { Adafruit_NeoPixel leds; @@ -140,45 +146,73 @@ public: // print ---------------------------------------------------------------------------------------- - void printf(const int x, const int y, const RGBA color, const char *format, ...) { + void printf(const int x, const int y, const Align align, const RGBA color, const char *format, ...) { va_list args; va_start(args, format); - printf(x, y, color, format, args); + printf(x, y, align, color, format, args); va_end(args); } - void printf(const int x, const int y, const RGBA color, const char *format, const va_list args) { + void printf(const int x, const int y, const Align align, const RGBA color, const char *format, const va_list args) { char buffer[64]; vsnprintf(buffer, sizeof buffer, format, args); - print(x, y, color, buffer); + print(x, y, align, color, buffer); } - void print(int x, int y, const RGBA color, const char *message) { - while (*message != '\0') { - print(&x, &y, color, &message); - x += 1; // space between characters + void print(const int x0, const int y0, const Align align, const RGBA color, const char *message) { + auto x = x0; + auto y = y0; + doAlign(x, align, message); + print(x, y, color, message, true); + } + + void doAlign(int& x, const Align align, const char *message) { + if (align != LEFT) { + auto w = 0; + auto h = 0; + measure(message, w, h); + if (align == RIGHT) { + x = x - w; + } else if (align == CENTER) { + x = x - w / 2; + } + } else { } } - void print(int *x, int *y, const RGBA color, const char **cPP) { + void measure(const char *message, int& w, int& h) { + w = 0; + h = 0; + print(w, h, White, message, false); + } + + void print(int& x, int& y, const RGBA color, const char *message, const bool doDraw) { + auto character = message; + while (*character != '\0') { + print(x, x, y, color, &character, doDraw); + x++; // separate characters + } + } + + void print(const int x0, int& x, int& y, const RGBA color, const char **cPP, const bool doDraw) { const auto character = *(*cPP)++; if ('0' <= character && character <= '9') { - return print(x, y, reinterpret_cast(FONT_NUMBER_SEGMENTS[character - '0']), countof(FONT_NUMBER_SEGMENTS[character - '0'][0]), countof(FONT_NUMBER_SEGMENTS[character - '0']), color); + return print(x, y, reinterpret_cast(FONT_NUMBER_SEGMENTS[character - '0']), countof(FONT_NUMBER_SEGMENTS[character - '0'][0]), countof(FONT_NUMBER_SEGMENTS[character - '0']), color, doDraw); } if ('A' <= character && character <= 'Z') { - return print(x, y, reinterpret_cast(FONT_UPPER[character - 'A']), countof(FONT_UPPER[character - 'A'][0]), countof(FONT_UPPER[character - 'A']), color); + return print(x, y, reinterpret_cast(FONT_UPPER[character - 'A']), countof(FONT_UPPER[character - 'A'][0]), countof(FONT_UPPER[character - 'A']), color, doDraw); } if ('a' <= character && character <= 'z') { - return print(x, y, reinterpret_cast(FONT_LOWER[character - 'a']), countof(FONT_LOWER[character - 'a'][0]), countof(FONT_LOWER[character - 'a']), color); + return print(x, y, reinterpret_cast(FONT_LOWER[character - 'a']), countof(FONT_LOWER[character - 'a'][0]), countof(FONT_LOWER[character - 'a']), color, doDraw); } if (character == 0xC2) { const auto secondCharacter = *(*cPP)++; if (secondCharacter == 0xB0) { - return print(x, y, reinterpret_cast(FONT_CHAR_DEGREE), countof(FONT_CHAR_DEGREE[0]), countof(FONT_CHAR_DEGREE), color); + return print(x, y, reinterpret_cast(FONT_CHAR_DEGREE), countof(FONT_CHAR_DEGREE[0]), countof(FONT_CHAR_DEGREE), color, doDraw); } - return printERROR(x, y, color); + return printERROR(x, y, color, doDraw); } if (character == 0xE2) { @@ -186,90 +220,92 @@ public: if (secondCharacter == 0x82) { const auto thirdCharacter = *(*cPP)++; if (thirdCharacter == 0xAC) { - return print(x, y, reinterpret_cast(FONT_CHAR_EURO), countof(FONT_CHAR_EURO[0]), countof(FONT_CHAR_EURO), color); + return print(x, y, reinterpret_cast(FONT_CHAR_EURO), countof(FONT_CHAR_EURO[0]), countof(FONT_CHAR_EURO), color, doDraw); } - return printERROR(x, y, color); + return printERROR(x, y, color, doDraw); } - return printERROR(x, y, color); + return printERROR(x, y, color, doDraw); } if (character == ' ') { - *x += 1; - return; + x += 3; } if (character == '\n') { - *y += 6; + x = x0; + y += 6; return; } switch (character) { - case '-': return print(x, y, reinterpret_cast(FONT_CHAR_MINUS), countof(FONT_CHAR_MINUS[0]), countof(FONT_CHAR_MINUS), color); - case '+': return print(x, y, reinterpret_cast(FONT_CHAR_PLUS), countof(FONT_CHAR_PLUS[0]), countof(FONT_CHAR_PLUS), color); - case '_': return print(x, y, reinterpret_cast(FONT_CHAR_UNDERLINE), countof(FONT_CHAR_UNDERLINE[0]), countof(FONT_CHAR_UNDERLINE), color); - case '%': return print(x, y, reinterpret_cast(FONT_CHAR_PERCENT), countof(FONT_CHAR_PERCENT[0]), countof(FONT_CHAR_PERCENT), color); - case '?': return print(x, y, reinterpret_cast(FONT_CHAR_QUESTION), countof(FONT_CHAR_QUESTION[0]), countof(FONT_CHAR_QUESTION), color); - case '!': return print(x, y, reinterpret_cast(FONT_CHAR_EXCLAMATION), countof(FONT_CHAR_EXCLAMATION[0]), countof(FONT_CHAR_EXCLAMATION), color); - case '.': return print(x, y, reinterpret_cast(FONT_CHAR_POINT), countof(FONT_CHAR_POINT[0]), countof(FONT_CHAR_POINT), color); - case ',': return print(x, y, reinterpret_cast(FONT_CHAR_COMMA), countof(FONT_CHAR_COMMA[0]), countof(FONT_CHAR_COMMA), color); - case ';': return print(x, y, reinterpret_cast(FONT_CHAR_SEMICOLON), countof(FONT_CHAR_SEMICOLON[0]), countof(FONT_CHAR_SEMICOLON), color); - case ':': return print(x, y, reinterpret_cast(FONT_CHAR_COLON), countof(FONT_CHAR_COLON[0]), countof(FONT_CHAR_COLON), color); - case '#': return print(x, y, reinterpret_cast(FONT_CHAR_SHARP), countof(FONT_CHAR_SHARP[0]), countof(FONT_CHAR_SHARP), color); - case '~': return print(x, y, reinterpret_cast(FONT_CHAR_TILDE), countof(FONT_CHAR_TILDE[0]), countof(FONT_CHAR_TILDE), color); - case '*': return print(x, y, reinterpret_cast(FONT_CHAR_ASTERISK), countof(FONT_CHAR_ASTERISK[0]), countof(FONT_CHAR_ASTERISK), color); - case '"': return print(x, y, reinterpret_cast(FONT_CHAR_QUOTE_DOUBLE), countof(FONT_CHAR_QUOTE_DOUBLE[0]), countof(FONT_CHAR_QUOTE_DOUBLE), color); - case '\'': return print(x, y, reinterpret_cast(FONT_CHAR_QUOTE_SINGLE), countof(FONT_CHAR_QUOTE_SINGLE[0]), countof(FONT_CHAR_QUOTE_SINGLE), color); - case '=': return print(x, y, reinterpret_cast(FONT_CHAR_EQUALS), countof(FONT_CHAR_EQUALS[0]), countof(FONT_CHAR_EQUALS), color); - case '(': return print(x, y, reinterpret_cast(FONT_CHAR_PAR_L), countof(FONT_CHAR_PAR_L[0]), countof(FONT_CHAR_PAR_L), color); - case ')': return print(x, y, reinterpret_cast(FONT_CHAR_PAR_R), countof(FONT_CHAR_PAR_R[0]), countof(FONT_CHAR_PAR_R), color); - case '[': return print(x, y, reinterpret_cast(FONT_CHAR_BRACKET_L), countof(FONT_CHAR_BRACKET_L[0]), countof(FONT_CHAR_BRACKET_L), color); - case ']': return print(x, y, reinterpret_cast(FONT_CHAR_BRACKET_R), countof(FONT_CHAR_BRACKET_R[0]), countof(FONT_CHAR_BRACKET_R), color); - case '{': return print(x, y, reinterpret_cast(FONT_CHAR_CURL_L), countof(FONT_CHAR_CURL_L[0]), countof(FONT_CHAR_CURL_L), color); - case '}': return print(x, y, reinterpret_cast(FONT_CHAR_CURL_R), countof(FONT_CHAR_CURL_R[0]), countof(FONT_CHAR_CURL_R), color); - case '/': return print(x, y, reinterpret_cast(FONT_CHAR_SLASH), countof(FONT_CHAR_SLASH[0]), countof(FONT_CHAR_SLASH), color); - case '\\': return print(x, y, reinterpret_cast(FONT_CHAR_BACKSLASH), countof(FONT_CHAR_BACKSLASH[0]), countof(FONT_CHAR_BACKSLASH), color); - case '&': return print(x, y, reinterpret_cast(FONT_CHAR_AND), countof(FONT_CHAR_AND[0]), countof(FONT_CHAR_AND), color); - case '|': return print(x, y, reinterpret_cast(FONT_CHAR_PIPE), countof(FONT_CHAR_PIPE[0]), countof(FONT_CHAR_PIPE), color); - case '$': return print(x, y, reinterpret_cast(FONT_CHAR_DOLLAR), countof(FONT_CHAR_DOLLAR[0]), countof(FONT_CHAR_DOLLAR), color); - case '@': return print(x, y, reinterpret_cast(FONT_CHAR_AT), countof(FONT_CHAR_AT[0]), countof(FONT_CHAR_AT), color); - case '<': return print(x, y, reinterpret_cast(FONT_CHAR_LT), countof(FONT_CHAR_LT[0]), countof(FONT_CHAR_LT), color); - case '>': return print(x, y, reinterpret_cast(FONT_CHAR_GT), countof(FONT_CHAR_GT[0]), countof(FONT_CHAR_GT), color); - default: return printERROR(x, y, color); + case '-': return print(x, y, reinterpret_cast(FONT_CHAR_MINUS), countof(FONT_CHAR_MINUS[0]), countof(FONT_CHAR_MINUS), color, doDraw); + case '+': return print(x, y, reinterpret_cast(FONT_CHAR_PLUS), countof(FONT_CHAR_PLUS[0]), countof(FONT_CHAR_PLUS), color, doDraw); + case '_': return print(x, y, reinterpret_cast(FONT_CHAR_UNDERLINE), countof(FONT_CHAR_UNDERLINE[0]), countof(FONT_CHAR_UNDERLINE), color, doDraw); + case '%': return print(x, y, reinterpret_cast(FONT_CHAR_PERCENT), countof(FONT_CHAR_PERCENT[0]), countof(FONT_CHAR_PERCENT), color, doDraw); + case '?': return print(x, y, reinterpret_cast(FONT_CHAR_QUESTION), countof(FONT_CHAR_QUESTION[0]), countof(FONT_CHAR_QUESTION), color, doDraw); + case '!': return print(x, y, reinterpret_cast(FONT_CHAR_EXCLAMATION), countof(FONT_CHAR_EXCLAMATION[0]), countof(FONT_CHAR_EXCLAMATION), color, doDraw); + case '.': return print(x, y, reinterpret_cast(FONT_CHAR_POINT), countof(FONT_CHAR_POINT[0]), countof(FONT_CHAR_POINT), color, doDraw); + case ',': return print(x, y, reinterpret_cast(FONT_CHAR_COMMA), countof(FONT_CHAR_COMMA[0]), countof(FONT_CHAR_COMMA), color, doDraw); + case ';': return print(x, y, reinterpret_cast(FONT_CHAR_SEMICOLON), countof(FONT_CHAR_SEMICOLON[0]), countof(FONT_CHAR_SEMICOLON), color, doDraw); + case ':': return print(x, y, reinterpret_cast(FONT_CHAR_COLON), countof(FONT_CHAR_COLON[0]), countof(FONT_CHAR_COLON), color, doDraw); + case '#': return print(x, y, reinterpret_cast(FONT_CHAR_SHARP), countof(FONT_CHAR_SHARP[0]), countof(FONT_CHAR_SHARP), color, doDraw); + case '~': return print(x, y, reinterpret_cast(FONT_CHAR_TILDE), countof(FONT_CHAR_TILDE[0]), countof(FONT_CHAR_TILDE), color, doDraw); + case '*': return print(x, y, reinterpret_cast(FONT_CHAR_ASTERISK), countof(FONT_CHAR_ASTERISK[0]), countof(FONT_CHAR_ASTERISK), color, doDraw); + case '"': return print(x, y, reinterpret_cast(FONT_CHAR_QUOTE_DOUBLE), countof(FONT_CHAR_QUOTE_DOUBLE[0]), countof(FONT_CHAR_QUOTE_DOUBLE), color, doDraw); + case '\'': return print(x, y, reinterpret_cast(FONT_CHAR_QUOTE_SINGLE), countof(FONT_CHAR_QUOTE_SINGLE[0]), countof(FONT_CHAR_QUOTE_SINGLE), color, doDraw); + case '=': return print(x, y, reinterpret_cast(FONT_CHAR_EQUALS), countof(FONT_CHAR_EQUALS[0]), countof(FONT_CHAR_EQUALS), color, doDraw); + case '(': return print(x, y, reinterpret_cast(FONT_CHAR_PAR_L), countof(FONT_CHAR_PAR_L[0]), countof(FONT_CHAR_PAR_L), color, doDraw); + case ')': return print(x, y, reinterpret_cast(FONT_CHAR_PAR_R), countof(FONT_CHAR_PAR_R[0]), countof(FONT_CHAR_PAR_R), color, doDraw); + case '[': return print(x, y, reinterpret_cast(FONT_CHAR_BRACKET_L), countof(FONT_CHAR_BRACKET_L[0]), countof(FONT_CHAR_BRACKET_L), color, doDraw); + case ']': return print(x, y, reinterpret_cast(FONT_CHAR_BRACKET_R), countof(FONT_CHAR_BRACKET_R[0]), countof(FONT_CHAR_BRACKET_R), color, doDraw); + case '{': return print(x, y, reinterpret_cast(FONT_CHAR_CURL_L), countof(FONT_CHAR_CURL_L[0]), countof(FONT_CHAR_CURL_L), color, doDraw); + case '}': return print(x, y, reinterpret_cast(FONT_CHAR_CURL_R), countof(FONT_CHAR_CURL_R[0]), countof(FONT_CHAR_CURL_R), color, doDraw); + case '/': return print(x, y, reinterpret_cast(FONT_CHAR_SLASH), countof(FONT_CHAR_SLASH[0]), countof(FONT_CHAR_SLASH), color, doDraw); + case '\\': return print(x, y, reinterpret_cast(FONT_CHAR_BACKSLASH), countof(FONT_CHAR_BACKSLASH[0]), countof(FONT_CHAR_BACKSLASH), color, doDraw); + case '&': return print(x, y, reinterpret_cast(FONT_CHAR_AND), countof(FONT_CHAR_AND[0]), countof(FONT_CHAR_AND), color, doDraw); + case '|': return print(x, y, reinterpret_cast(FONT_CHAR_PIPE), countof(FONT_CHAR_PIPE[0]), countof(FONT_CHAR_PIPE), color, doDraw); + case '$': return print(x, y, reinterpret_cast(FONT_CHAR_DOLLAR), countof(FONT_CHAR_DOLLAR[0]), countof(FONT_CHAR_DOLLAR), color, doDraw); + case '@': return print(x, y, reinterpret_cast(FONT_CHAR_AT), countof(FONT_CHAR_AT[0]), countof(FONT_CHAR_AT), color, doDraw); + case '<': return print(x, y, reinterpret_cast(FONT_CHAR_LT), countof(FONT_CHAR_LT[0]), countof(FONT_CHAR_LT), color, doDraw); + case '>': return print(x, y, reinterpret_cast(FONT_CHAR_GT), countof(FONT_CHAR_GT[0]), countof(FONT_CHAR_GT), color, doDraw); + default: return printERROR(x, y, color, doDraw); } } - void printERROR(int *x, const int *y, const RGBA color) { - return print(x, y, reinterpret_cast(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) { + void print(int& x0, const int& y0, const bool *s, const int w, const int h, const RGBA color, const bool doDraw) { 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 + 1, maxWidth); + const auto pixelX = x0 + x; + const auto pixelY = y0 + y; + if (doDraw) { + setPixel(pixelX, pixelY, color); + } } } } - *x0 += maxWidth; + x0 += maxWidth; } - void print(int *x0, const int *y0, const RGBA *s, const int w, const int h) { + 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; + const auto pixelX = x0 + x; + const auto pixelY = y0 + y; setPixel(pixelX, pixelY, color); } } - *x0 += w; + x0 += w; + } + + void printERROR(int& x, const int& y, const RGBA color, const bool doDraw) { + return print(x, y, reinterpret_cast(FONT_ERROR_), countof(FONT_ERROR_[0]), countof(FONT_ERROR_), color, doDraw); } }; diff --git a/src/patrix/display/DisplayMatrix_FontSpecial.cpp b/src/patrix/display/DisplayMatrix_FontSpecial.cpp index 6d5b151..2f374db 100644 --- a/src/patrix/display/DisplayMatrix_FontSpecial.cpp +++ b/src/patrix/display/DisplayMatrix_FontSpecial.cpp @@ -229,11 +229,11 @@ Symbol4 FONT_ERROR_ = { }; Symbol5 FONT_CHAR_PERCENT = { - {X,_,_,_,X}, - {_,_,_,X,_}, - {_,_,X,_,_}, - {_,X,_,_,_}, - {X,_,_,_,X}, + {X,_,_}, + {_,_,X}, + {_,X,_}, + {X,_,_}, + {_,_,X}, }; //@formatter:off