diff --git a/common/unicode_sorta.hpp b/common/unicode_sorta.hpp index a75e4c76..3a6856e9 100644 --- a/common/unicode_sorta.hpp +++ b/common/unicode_sorta.hpp @@ -11,6 +11,16 @@ table to map anything prefixed with 0xc3 to its non-accented equivilent. namespace unicode_sorta { +const char PAGE_194_START = 194; +const char PAGE_195_START = 195; + +// Codepage is probably completely the wrong terminology here +// but character pairs come in the form 0xc2 0x00 and 0xc3 0x00. +enum codepage_t : uint8_t { + PAGE_194, + PAGE_195 +}; + const uint8_t UNICODE_PREFIX = 0xc3; enum accents : uint8_t { @@ -92,7 +102,46 @@ static const accents char_accent[] = { ACCENT_DIAERESIS }; -static const char char_base[] = { +// Codepage 194. Starts at 0x80 but the first 32 are non-printable +// Since we're already implementing LUTs for various accented characters, +// it makes sense for us poor brits to grab a usable £, too! +static const char char_base_194[] = { + ' ', // - c2 a0 - NO-BREAK SPACE + 'i', // ¡ - c2 a1 - INVERTED EXCLAMATION MARK + ' ', // ¢ - c2 a2 - CENT SIGN + '\x85', // £ - c2 a3 - POUND SIGN + ' ', // ¤ - c2 a4 - CURRENCY SIGN + '\x86', // ¥ - c2 a5 - YEN SIGN + ' ', // ¦ - c2 a6 - BROKEN BAR + 'S', // § - c2 a7 - SECTION SIGN + ' ', // ¨ - c2 a8 - DIAERESIS + '\x87', // © - c2 a9 - COPYRIGHT SIGN + 'a', // ª - c2 aa - FEMININE ORDINAL INDICATOR + '<', // « - c2 ab - LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + ' ', // ¬ - c2 ac - NOT SIGN + ' ', // ­ - c2 ad - SOFT HYPHEN + 'R', // ® - c2 ae - REGISTERED SIGN + ' ', // ¯ - c2 af - MACRON + '\x88', // ° - c2 b0 - DEGREE SIGN + ' ', // ± - c2 b1 - PLUS-MINUS SIGN + '2', // ² - c2 b2 - SUPERSCRIPT TWO + '3', // ³ - c2 b3 - SUPERSCRIPT THREE + ' ', // ´ - c2 b4 - ACUTE ACCENT + ' ', // µ - c2 b5 - MICRO SIGN + ' ', // ¶ - c2 b6 - PILCROW SIGN + ' ', // · - c2 b7 - MIDDLE DOT + ' ', // ¸ - c2 b8 - CEDILLA + ' ', // ¹ - c2 b9 - SUPERSCRIPT ONE + ' ', // º - c2 ba - MASCULINE ORDINAL INDICATOR + ' ', // » - c2 bb - RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + ' ', // ¼ - c2 bc - VULGAR FRACTION ONE QUARTER + ' ', // ½ - c2 bd - VULGAR FRACTION ONE HALF + ' ', // ¾ - c2 be - VULGAR FRACTION THREE QUARTERS + ' ', // ¿ - c2 bf - INVERTED QUESTION MARK +}; + +// Codepage 195. Starts at 0x80 +static const char char_base_195[] = { 'A', // À - c3 80 - A + GRAVE 'A', // Á - c3 81 - A + ACUTE 'A', // Â - c3 82 - A + CIRCUMFLEX diff --git a/libraries/bitmap_fonts/bitmap_fonts.cpp b/libraries/bitmap_fonts/bitmap_fonts.cpp index fcfbe3c1..9866bdc8 100644 --- a/libraries/bitmap_fonts/bitmap_fonts.cpp +++ b/libraries/bitmap_fonts/bitmap_fonts.cpp @@ -1,8 +1,7 @@ #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) { + int32_t measure_character(const font_t *font, const char c, const uint8_t scale, unicode_sorta::codepage_t codepage) { if(c < 32 || c > 127 + 64) { // + 64 char remappings defined in unicode_sorta.hpp return 0; } @@ -10,7 +9,11 @@ namespace bitmap { uint8_t char_index = c; if(char_index > 127) { - char_index = unicode_sorta::char_base[c - 128]; + if(codepage == unicode_sorta::PAGE_195) { + char_index = unicode_sorta::char_base_195[c - 128]; + } else { + char_index = unicode_sorta::char_base_194[c - 128 - 32]; + } } char_index -= 32; @@ -20,13 +23,22 @@ namespace bitmap { int32_t measure_text(const font_t *font, const std::string &t, const uint8_t scale) { int32_t text_width = 0; + unicode_sorta::codepage_t codepage = unicode_sorta::PAGE_195; for(auto c : t) { - text_width += measure_character(font, c, scale); + if(c == unicode_sorta::PAGE_194_START) { + codepage = unicode_sorta::PAGE_194; + continue; + } else if (c == unicode_sorta::PAGE_195_START) { + continue; + } + text_width += measure_character(font, c, scale, codepage); + text_width += 1 * scale; + codepage = unicode_sorta::PAGE_195; // Reset back to default } return text_width; } - void character(const font_t *font, rect_func rectangle, const char c, const int32_t x, const int32_t y, const uint8_t scale) { + void character(const font_t *font, rect_func rectangle, const char c, const int32_t x, const int32_t y, const uint8_t scale, unicode_sorta::codepage_t codepage) { if(c < 32 || c > 127 + 64) { // + 64 char remappings defined in unicode_sorta.hpp return; } @@ -37,8 +49,13 @@ namespace bitmap { // Remap any chars that fall outside of the 7-bit ASCII range // using our unicode fudge lookup table. if(char_index > 127) { - char_index = unicode_sorta::char_base[c - 128]; - char_accent = unicode_sorta::char_accent[c - 128]; + if(codepage == unicode_sorta::PAGE_195) { + char_index = unicode_sorta::char_base_195[c - 128]; + char_accent = unicode_sorta::char_accent[c - 128]; + } else { + char_index = unicode_sorta::char_base_194[c - 128 - 32]; + char_accent = unicode_sorta::ACCENT_NONE; + } } // We don't map font data for the first 32 non-printable ASCII chars @@ -55,7 +72,7 @@ namespace bitmap { // Accents can be up to 8 pixels tall on both 8bit and 16bit fonts // Each accent's data is font->max_width bytes + 2 offset bytes long - const uint8_t *a = &font->data[101 * bytes_per_char + char_accent * (font->max_width + 2)]; + const uint8_t *a = &font->data[(base_chars + extra_chars) * bytes_per_char + char_accent * (font->max_width + 2)]; // Effectively shift off the first two bytes of accent data- // these are the lower and uppercase accent offsets @@ -104,6 +121,7 @@ namespace bitmap { void text(const font_t *font, rect_func rectangle, const std::string &t, const int32_t x, const int32_t y, const int32_t wrap, const uint8_t scale) { uint32_t co = 0, lo = 0; // character and line (if wrapping) offset + unicode_sorta::codepage_t codepage = unicode_sorta::PAGE_195; size_t i = 0; while(i < t.length()) { @@ -116,7 +134,14 @@ namespace bitmap { uint16_t word_width = 0; for(size_t j = i; j < next_space; j++) { - word_width += measure_character(font, t[j], scale); + if (t[j] == unicode_sorta::PAGE_194_START) { + codepage = unicode_sorta::PAGE_194; + continue; + } else if (t[j] == unicode_sorta::PAGE_195_START) { + continue; + } + word_width += measure_character(font, t[j], scale, codepage); + codepage = unicode_sorta::PAGE_195; } // if this word would exceed the wrap limit then @@ -128,8 +153,16 @@ namespace bitmap { // draw word for(size_t j = i; j < next_space; j++) { - character(font, rectangle, t[j], x + co, y + lo, scale); - co += measure_character(font, t[j], scale); + if (t[j] == unicode_sorta::PAGE_194_START) { + codepage = unicode_sorta::PAGE_194; + continue; + } else if (t[j] == unicode_sorta::PAGE_195_START) { + continue; + } + character(font, rectangle, t[j], x + co, y + lo, scale, codepage); + co += measure_character(font, t[j], scale, codepage); + co += 1 * scale; + codepage = unicode_sorta::PAGE_195; } // move character offset to end of word and add a space diff --git a/libraries/bitmap_fonts/bitmap_fonts.hpp b/libraries/bitmap_fonts/bitmap_fonts.hpp index 2dc596a0..5de76d49 100644 --- a/libraries/bitmap_fonts/bitmap_fonts.hpp +++ b/libraries/bitmap_fonts/bitmap_fonts.hpp @@ -3,20 +3,24 @@ #include #include #include +#include "common/unicode_sorta.hpp" namespace bitmap { + const int base_chars = 96; // 96 printable ASCII chars + const int extra_chars = 9; // Extra chars we've rempped that aren't just an ASCII char plus an accent + struct font_t { const uint8_t height; const uint8_t max_width; - const uint8_t widths[96 + 5]; // 96 printable ASCII chars plus 5 exta we can't easily remap and decorate with accents + const uint8_t widths[base_chars + extra_chars]; const uint8_t data[]; }; typedef std::function rect_func; - int32_t measure_character(const font_t *font, const char c, const uint8_t scale); + int32_t measure_character(const font_t *font, const char c, const uint8_t scale, unicode_sorta::codepage_t codepage = unicode_sorta::PAGE_195); int32_t measure_text(const font_t *font, const std::string &t, const uint8_t scale); - void character(const font_t *font, rect_func rectangle, const char c, const int32_t x, const int32_t y, const uint8_t scale = 2); + void character(const font_t *font, rect_func rectangle, const char c, const int32_t x, const int32_t y, const uint8_t scale = 2, unicode_sorta::codepage_t codepage = unicode_sorta::PAGE_195); void text(const font_t *font, rect_func rectangle, const std::string &t, const int32_t x, const int32_t y, const int32_t wrap, const uint8_t scale = 2); } \ No newline at end of file diff --git a/libraries/bitmap_fonts/font14_outline_data.hpp b/libraries/bitmap_fonts/font14_outline_data.hpp index 14df4089..41b14d6b 100644 --- a/libraries/bitmap_fonts/font14_outline_data.hpp +++ b/libraries/bitmap_fonts/font14_outline_data.hpp @@ -12,7 +12,9 @@ const bitmap::font_t font14_outline { 6, 9, 6, 6, 7, 7, 7, 9, 7, 7, 7, 5, 7, 5, 7, 8, 5, 8, 6, 5, 6, 6, 5, 7, 6, 3, 5, 6, 5, 9, 6, 7, 6, 7, 5, 5, 6, 6, 7, 9, 7, 7, 7, 5, 3, 5, 8, 5, - 9, 6, 6, 10, 6 // Extra +// Extra +// Æ Þ ß æ þ £ ¥ © ° + 9, 6, 6, 10, 6, 6, 6, 6, 5 }, .data = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // @@ -122,6 +124,10 @@ const bitmap::font_t font14_outline { 0x0f, 0xfc, 0x08, 0x04, 0x0f, 0xb4, 0x0b, 0xb4, 0x0c, 0x4c, 0x07, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ß 0x07, 0xc0, 0x0c, 0x60, 0x0b, 0xa0, 0x0a, 0xa0, 0x0b, 0xa0, 0x0c, 0x60, 0x0a, 0xa0, 0x0a, 0xa0, 0x0b, 0x60, 0x0f, 0xc0, // æ 0x3f, 0xe0, 0x20, 0x20, 0x3d, 0xa0, 0x05, 0xa0, 0x06, 0x60, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // þ + 0x00, 0xe0, 0x0f, 0xb8, 0x08, 0x04, 0x0b, 0xb4, 0x0a, 0xb4, 0x0e, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // £ + 0x00, 0x3c, 0x00, 0xe4, 0x0f, 0x9c, 0x08, 0x70, 0x0f, 0x9c, 0x00, 0xe4, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ¥ + 0x07, 0xc0, 0x0c, 0x60, 0x0b, 0xa0, 0x0a, 0xa0, 0x0e, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // © + 0x00, 0x38, 0x00, 0x44, 0x00, 0x54, 0x00, 0x44, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ° // Accents + Offsets // All chars are shifted 8px down into a 32 pixel canvas for combining with accents. // Accent shift values (the first two numbers in each line below) move the accent down to meet them. diff --git a/libraries/bitmap_fonts/font6_data.hpp b/libraries/bitmap_fonts/font6_data.hpp index 020486b5..f334d977 100644 --- a/libraries/bitmap_fonts/font6_data.hpp +++ b/libraries/bitmap_fonts/font6_data.hpp @@ -6,13 +6,15 @@ const bitmap::font_t font6 { .height = 6, .max_width = 6, .widths = { - 3, 2, 4, 6, 6, 6, 7, 2, 3, 3, 4, 4, 2, 4, 2, 4, - 6, 3, 5, 5, 6, 5, 6, 6, 6, 6, 2, 2, 4, 4, 4, 5, - 7, 6, 6, 5, 6, 5, 5, 6, 5, 4, 5, 5, 5, 6, 6, 6, - 6, 6, 6, 5, 6, 6, 6, 6, 5, 5, 5, 3, 4, 3, 4, 4, - 3, 6, 6, 5, 6, 5, 5, 6, 5, 4, 5, 5, 5, 6, 6, 6, - 6, 6, 6, 5, 6, 6, 6, 6, 5, 5, 5, 4, 2, 4, 4, 2, - 6, 5, 5, 6, 5 // Extra + 3, 1, 3, 5, 5, 5, 6, 1, 2, 2, 3, 3, 1, 3, 1, 3, + 5, 2, 4, 4, 5, 4, 5, 5, 5, 5, 1, 1, 3, 3, 3, 4, + 6, 5, 5, 4, 5, 4, 4, 5, 4, 3, 4, 4, 4, 5, 5, 5, + 5, 5, 5, 4, 5, 5, 5, 5, 4, 4, 4, 2, 3, 2, 3, 3, + 2, 5, 5, 4, 5, 4, 4, 5, 4, 3, 4, 4, 4, 5, 5, 5, + 5, 5, 5, 4, 5, 5, 5, 5, 4, 4, 4, 3, 1, 3, 3, 1, +// Extra +// Æ Þ ß æ þ £ ¥ © ° + 5, 5, 4, 5, 5, 4, 4, 4, 3 }, .data = { 0x00,0x00,0x00,0x00,0x00,0x00, // @@ -117,6 +119,10 @@ const bitmap::font_t font6 { 0x3e,0x0a,0x2a,0x34,0x00,0x00, // ß 0x3c,0x12,0x3c,0x2a,0x2a,0x00, // æ 0x3f,0x12,0x12,0x12,0x0e,0x00, // þ + 0x08,0x3c,0x2a,0x2a,0x00,0x00, // £ + 0x26,0x28,0x28,0x1e,0x00,0x00, // ¥s + 0x1c,0x22,0x22,0x22,0x00,0x00, // © + 0x02,0x05,0x02,0x00,0x00,0x00, // ° // Accents + Offsets // All chars are shifted 8px down into a 32 pixel canvas for combining with accents. // Accent shift values (the first two numbers in each line below) move the accent down to meet them. diff --git a/libraries/bitmap_fonts/font8_data.hpp b/libraries/bitmap_fonts/font8_data.hpp index f5732640..358c894b 100644 --- a/libraries/bitmap_fonts/font8_data.hpp +++ b/libraries/bitmap_fonts/font8_data.hpp @@ -6,13 +6,15 @@ const bitmap::font_t font8 { .height = 8, .max_width = 6, .widths = { - 2, 2, 4, 6, 5, 5, 5, 2, 4, 4, 4, 4, 3, 4, 3, 5, - 5, 4, 5, 5, 5, 5, 5, 5, 5, 5, 2, 3, 4, 4, 4, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 5, 5, 5, 6, 5, 5, - 5, 5, 5, 5, 6, 5, 5, 6, 5, 5, 5, 3, 5, 3, 4, 4, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 5, 5, 4, 6, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 4, 2, 4, 5, 2, - 6, 5, 5, 6, 5 // Extra + 3, 1, 3, 5, 4, 4, 4, 1, 3, 3, 3, 3, 2, 3, 2, 4, + 4, 3, 4, 4, 4, 4, 4, 4, 4, 4, 1, 2, 3, 3, 3, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 4, 4, 4, 5, 4, 4, + 4, 4, 4, 4, 5, 4, 4, 5, 4, 4, 4, 2, 4, 2, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 4, 4, 3, 5, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 5, 4, 4, 4, 3, 1, 3, 4, 1, +// Extra +// Æ Þ ß æ þ £ ¥ © ° + 5, 4, 4, 5, 4, 4, 4, 4, 3 }, .data = { 0x00,0x00,0x00,0x00,0x00,0x00, // @@ -117,6 +119,10 @@ const bitmap::font_t font8 { 0x7e,0x09,0x49,0x36,0x00,0x00, // ß 0x20,0x54,0x78,0x54,0x58,0x00, // æ 0x7f,0x24,0x24,0x18,0x00,0x00, // þ + 0x08,0x7e,0x49,0x41,0x00,0x00, // £ + 0x47,0x48,0x48,0x3f,0x00,0x00, // ¥ + 0x38,0x44,0x44,0x28,0x00,0x00, // © + 0x02,0x05,0x02,0x00,0x00,0x00, // ° // Accents + Offsets // All chars are shifted 8px down into a 32 pixel canvas for combining with accents. // Accent shift values (the first two numbers in each line below) move the accent down to meet them. diff --git a/libraries/hershey_fonts/hershey_fonts.cpp b/libraries/hershey_fonts/hershey_fonts.cpp index 7136ba1f..7234488c 100644 --- a/libraries/hershey_fonts/hershey_fonts.cpp +++ b/libraries/hershey_fonts/hershey_fonts.cpp @@ -24,7 +24,7 @@ namespace hershey { } if(c > 127) { - c = unicode_sorta::char_base[c - 128]; + c = unicode_sorta::char_base_195[c - 128]; } return &font->chars[c - 32]; diff --git a/micropython/modules/badger2040/badger2040.cpp b/micropython/modules/badger2040/badger2040.cpp index 1f444b6e..69747fd4 100644 --- a/micropython/modules/badger2040/badger2040.cpp +++ b/micropython/modules/badger2040/badger2040.cpp @@ -444,7 +444,7 @@ mp_obj_t Badger2040_glyph(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ enum { ARG_self, ARG_char, ARG_x, ARG_y, ARG_scale, ARG_rotation }; static const mp_arg_t allowed_args[] = { { MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_char, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_char, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT }, { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT }, { MP_QSTR_scale, MP_ARG_OBJ, {.u_obj = mp_const_none} }, @@ -455,7 +455,8 @@ mp_obj_t Badger2040_glyph(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - int c = args[ARG_char].u_int; + int c = 0; + int x = args[ARG_x].u_int; int y = args[ARG_y].u_int; float scale = 1.0f; @@ -468,7 +469,16 @@ mp_obj_t Badger2040_glyph(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ } _Badger2040_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self].u_obj, _Badger2040_obj_t); - self->badger2040->glyph(c, x, y, scale, rotation); + + if (mp_obj_is_int(args[ARG_char].u_obj)) { + c = (uint8_t)mp_obj_get_int(args[ARG_char].u_obj); + self->badger2040->glyph(c, x, y, scale, rotation); + } else if (mp_obj_is_str_or_bytes(args[ARG_char].u_obj)) { + std::string message = mp_obj_to_string_r(args[ARG_char].u_obj); + self->badger2040->text(message, x, y, scale, rotation); + } else { + mp_raise_TypeError("glyph: expected char or string."); + } return mp_const_none; }