diff --git a/common/unicode_sorta.hpp b/common/unicode_sorta.hpp new file mode 100644 index 00000000..7dc77e0f --- /dev/null +++ b/common/unicode_sorta.hpp @@ -0,0 +1,158 @@ +#pragma once + +#include + +/* +This file exists to allow space-efficient rendering of accented characters. + +It permits rudimentary support for unicode characters by providing a lookup +table to map anything prefixed with 0xc3 to its non-accented equivilent. +*/ + +const uint8_t UNICODE_PREFIX = 0xc3; + +enum accents : uint8_t { + ACCENT_GRAVE, + ACCENT_ACUTE, + ACCENT_CIRCUMFLEX, + ACCENT_TILDE, + ACCENT_DIAERESIS, + ACCENT_RING_ABOVE, + ACCENT_STROKE, + ACCENT_CEDILLA, + ACCENT_NONE, +}; + +static const accents char_accent[] = { + ACCENT_GRAVE, + ACCENT_ACUTE, + ACCENT_CIRCUMFLEX, + ACCENT_TILDE, + ACCENT_DIAERESIS, + ACCENT_RING_ABOVE, + ACCENT_NONE, + ACCENT_CEDILLA, + ACCENT_GRAVE, + ACCENT_ACUTE, + ACCENT_CIRCUMFLEX, + ACCENT_DIAERESIS, + ACCENT_GRAVE, + ACCENT_ACUTE, + ACCENT_CIRCUMFLEX, + ACCENT_DIAERESIS, + ACCENT_NONE, + ACCENT_TILDE, + ACCENT_GRAVE, + ACCENT_ACUTE, + ACCENT_CIRCUMFLEX, + ACCENT_TILDE, + ACCENT_DIAERESIS, + ACCENT_NONE, + ACCENT_STROKE, + ACCENT_GRAVE, + ACCENT_ACUTE, + ACCENT_CIRCUMFLEX, + ACCENT_DIAERESIS, + ACCENT_ACUTE, + ACCENT_NONE, + ACCENT_NONE, + ACCENT_GRAVE, + ACCENT_ACUTE, + ACCENT_CIRCUMFLEX, + ACCENT_TILDE, + ACCENT_DIAERESIS, + ACCENT_RING_ABOVE, + ACCENT_NONE, + ACCENT_CEDILLA, + ACCENT_GRAVE, + ACCENT_ACUTE, + ACCENT_CIRCUMFLEX, + ACCENT_DIAERESIS, + ACCENT_GRAVE, + ACCENT_ACUTE, + ACCENT_CIRCUMFLEX, + ACCENT_DIAERESIS, + ACCENT_NONE, + ACCENT_TILDE, + ACCENT_GRAVE, + ACCENT_ACUTE, + ACCENT_CIRCUMFLEX, + ACCENT_TILDE, + ACCENT_DIAERESIS, + ACCENT_NONE, + ACCENT_STROKE, + ACCENT_GRAVE, + ACCENT_ACUTE, + ACCENT_CIRCUMFLEX, + ACCENT_DIAERESIS, + ACCENT_ACUTE, + ACCENT_NONE, + ACCENT_DIAERESIS +}; + +static const char char_base[] = { + 'A', // À - c3 80 - A + GRAVE + 'A', // Á - c3 81 - A + ACUTE + 'A', // Â - c3 82 - A + CIRCUMFLEX + 'A', // Ã - c3 83 - A + TILDE + 'A', // Ä - c3 84 - A + DIAERESIS + 'A', // Å - c3 85 - A + RING ABOVE + ' ', // Æ - c3 86 - AE + 'C', // Ç - c3 87 - C + CEDILLA + 'E', // È - c3 88 - E + GRAVE + 'E', // É - c3 89 - E + ACUTE + 'E', // Ê - c3 8a - E + CIRCUMFLEX + 'E', // Ë - c3 8b - E + DIAERESIS + 'I', // Ì - c3 8c - I + GRAVE + 'I', // Í - c3 8d - I + ACUTE + 'I', // Î - c3 8e - I + CIRCUMFLEX + 'I', // Ï - c3 8f - I + DIAERESIS + 'D', // Ð - c3 90 - ETH + 'N', // Ñ - c3 91 - N + TILDE + 'O', // Ò - c3 92 - O + GRAVE + 'O', // Ó - c3 93 - O + ACUTE + 'O', // Ô - c3 94 - O + CIRCUMFLEX + 'O', // Õ - c3 95 - O + TILDE + 'O', // Ö - c3 96 - O + DIAERESIS + 'x', // × - c3 97 - MULTIPLICATION SIGN + 'O', // Ø - c3 98 - O + STROKE + 'U', // Ù - c3 99 - U + GRAVE + 'U', // Ú - c3 9a - U + ACUTE + 'U', // Û - c3 9b - U + CIRCUMFLEX + 'U', // Ü - c3 9c - U + DIAERESIS + 'Y', // Ý - c3 9d - Y + ACUTE + ' ', // Þ - c3 9e - THORN + ' ', // ß - c3 9f - SHARP S + 'a', // à - c3 a0 - A + GRAVE + 'a', // á - c3 a1 - A + ACUTE + 'a', // â - c3 a2 - A + CIRCUMFLEX + 'a', // ã - c3 a3 - A + TILDE + 'a', // ä - c3 a4 - A + DIAERESIS + 'a', // å - c3 a5 - A + RING ABOVE + ' ', // æ - c3 a6 - AE + 'c', // ç - c3 a7 - C + CEDILLA + 'e', // è - c3 a8 - E + GRAVE + 'e', // é - c3 a9 - E + ACUTE + 'e', // ê - c3 aa - E + CIRCUMFLEX + 'e', // ë - c3 ab - E + DIAERESIS + 'i', // ì - c3 ac - I + GRAVE + 'i', // í - c3 ad - I + ACUTE + 'i', // î - c3 ae - I + CIRCUMFLEX + 'i', // ï - c3 af - I + DIAERESIS + 'o', // ð - c3 b0 - ETH + 'n', // ñ - c3 b1 - N + TILDE + 'o', // ò - c3 b2 - O + GRAVE + 'o', // ó - c3 b3 - O + ACUTE + 'o', // ô - c3 b4 - O + CIRCUMFLEX + 'o', // õ - c3 b5 - O + TILDE + 'o', // ö - c3 b6 - O + DIAERESIS + '/', // ÷ - c3 b7 - DIVISION SIGN + 'o', // ø - c3 b8 - O + STROKE + 'u', // ù - c3 b9 - U + GRAVE + 'u', // ú - c3 ba - U + ACUTE + 'u', // û - c3 bb - U + CIRCUMFLEX + 'u', // ü - c3 bc - U + DIAERESIS + 'y', // ý - c3 bd - Y + ACUTE + ' ', // þ - c3 be - THORN + 'y', // ÿ - c3 bf - Y + DIAERESIS +}; \ No newline at end of file diff --git a/libraries/bitmap_fonts/bitmap_fonts.cpp b/libraries/bitmap_fonts/bitmap_fonts.cpp index 72c71fd6..e20d93a0 100644 --- a/libraries/bitmap_fonts/bitmap_fonts.cpp +++ b/libraries/bitmap_fonts/bitmap_fonts.cpp @@ -1,8 +1,20 @@ #include "bitmap_fonts.hpp" +#include "common/unicode_sorta.hpp" namespace bitmap { int32_t measure_character(const font_t *font, const char c, const uint8_t scale) { - uint8_t char_index = c - 32; + if(c < 32 || c > 127 + 64) { // + 64 char remappings defined in unicode_sorta.hpp + return 0; + } + + uint8_t char_index = c; + + if(char_index > 127) { + char_index = char_base[c - 128]; + } + + char_index -= 32; + return font->widths[char_index] * scale; } @@ -15,7 +27,17 @@ namespace bitmap { } void character(const font_t *font, rect_func rectangle, const char c, const int32_t x, const int32_t y, const uint8_t scale) { - uint8_t char_index = c - 32; + if(c < 32 || c > 127 + 64) { // + 64 char remappings defined in unicode_sorta.hpp + return; + } + + uint8_t char_index = c; + + if(char_index > 127) { + char_index = char_base[c - 128]; + } + + char_index -= 32; const uint8_t *d = &font->data[char_index * font->max_width]; for(uint8_t cx = 0; cx < font->widths[char_index]; cx++) { @@ -43,7 +65,7 @@ namespace bitmap { uint16_t word_width = 0; for(size_t j = i; j < next_space; j++) { - word_width += font->widths[t[j] - 32] * scale; + word_width += measure_character(font, t[j], scale); } // if this word would exceed the wrap limit then @@ -56,7 +78,7 @@ namespace bitmap { // draw word for(size_t j = i; j < next_space; j++) { character(font, rectangle, t[j], x + co, y + lo, scale); - co += font->widths[t[j] - 32] * scale; + co += measure_character(font, t[j], scale); } // move character offset to end of word and add a space diff --git a/libraries/hershey_fonts/hershey_fonts.cpp b/libraries/hershey_fonts/hershey_fonts.cpp index cd9df968..56c0d8c1 100644 --- a/libraries/hershey_fonts/hershey_fonts.cpp +++ b/libraries/hershey_fonts/hershey_fonts.cpp @@ -1,4 +1,5 @@ #include "hershey_fonts.hpp" +#include "common/unicode_sorta.hpp" #include namespace hershey { @@ -18,10 +19,14 @@ namespace hershey { } const font_glyph_t* glyph_data(const font_t* font, unsigned char c) { - if(c < 32 || c > 127) { + if(c < 32 || c > 127 + 64) { // + 64 char remappings defined in unicode_sorta.hpp return nullptr; } + if(c > 127) { + c = char_base[c - 128]; + } + return &font->chars[c - 32]; } @@ -45,6 +50,9 @@ namespace hershey { } int32_t glyph(const font_t* font, line_func line, unsigned char c, int32_t x, int32_t y, float s, float a) { + if (c == UNICODE_PREFIX) { + return 0; + } const font_glyph_t *gd = glyph_data(font, c); // if glyph data not found (id too great) then skip