From 6a9bc8688fcbbd294c3b711867dc7c3264831f52 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Thu, 31 Mar 2022 18:09:50 +0100 Subject: [PATCH] Bitmap Fonts: Add accent rendering. Render accents above and below the 64 characters > 127. Different offsets for upper/lower case characters. --- common/unicode_sorta.hpp | 6 +++- libraries/bitmap_fonts/bitmap_fonts.cpp | 37 ++++++++++++++++++++--- libraries/bitmap_fonts/bitmap_fonts.hpp | 3 ++ libraries/bitmap_fonts/font6_data.hpp | 14 ++++++++- libraries/bitmap_fonts/font8_data.hpp | 14 ++++++++- libraries/hershey_fonts/hershey_fonts.cpp | 5 +-- 6 files changed, 67 insertions(+), 12 deletions(-) diff --git a/common/unicode_sorta.hpp b/common/unicode_sorta.hpp index 7dc77e0f..0022e2d8 100644 --- a/common/unicode_sorta.hpp +++ b/common/unicode_sorta.hpp @@ -9,6 +9,8 @@ It permits rudimentary support for unicode characters by providing a lookup table to map anything prefixed with 0xc3 to its non-accented equivilent. */ +namespace unicode_sorta { + const uint8_t UNICODE_PREFIX = 0xc3; enum accents : uint8_t { @@ -155,4 +157,6 @@ static const char char_base[] = { 'y', // ý - c3 bd - Y + ACUTE ' ', // þ - c3 be - THORN 'y', // ÿ - c3 bf - Y + DIAERESIS -}; \ No newline at end of file +}; + +} \ No newline at end of file diff --git a/libraries/bitmap_fonts/bitmap_fonts.cpp b/libraries/bitmap_fonts/bitmap_fonts.cpp index e20d93a0..da509e9d 100644 --- a/libraries/bitmap_fonts/bitmap_fonts.cpp +++ b/libraries/bitmap_fonts/bitmap_fonts.cpp @@ -10,7 +10,7 @@ namespace bitmap { uint8_t char_index = c; if(char_index > 127) { - char_index = char_base[c - 128]; + char_index = unicode_sorta::char_base[c - 128]; } char_index -= 32; @@ -32,22 +32,49 @@ namespace bitmap { } uint8_t char_index = c; + unicode_sorta::accents char_accent = unicode_sorta::ACCENT_NONE; if(char_index > 127) { - char_index = char_base[c - 128]; + char_index = unicode_sorta::char_base[c - 128]; + char_accent = unicode_sorta::char_accent[c - 128]; } + bool upper = char_index < 97; // Only valid for A-Z and a-z char_index -= 32; const uint8_t *d = &font->data[char_index * font->max_width]; + const uint8_t *a = &font->data[96 * font->max_width + char_accent * font->max_width]; + + // Vertical offset of our char within the 32 pixel column canvas + // At 16 pixels this gives us 8 pixels above and below the char for accents and spacing. + uint8_t offset = (32 - font->height) / 2; + for(uint8_t cx = 0; cx < font->widths[char_index]; cx++) { - for(uint8_t cy = 0; cy < font->height; cy++) { - if((1U << cy) & *d) { - rectangle(x + (cx * scale), y + (cy * scale), scale, scale); + // Our maximum bitmap font height will be 16 pixels + // give ourselves a 32 pixel high canvas in which to plot the char and accent. + uint32_t data = *d << offset; + if(char_accent != unicode_sorta::ACCENT_NONE) { + uint32_t accent = *a; + accent <<= offset; // Shift the char to the middle of the canvas + if(char_accent == unicode_sorta::ACCENT_CEDILLA) { + // Special case handling for the Cedilla- that little upside-down question mark that goes beneath characters + accent <<= font->accent_offset_below; + } else { + accent >>= upper ? font->accent_offset_upper : font->accent_offset_lower; // Shift the accent above the char + } + data |= accent; // Merge the accent data into the canvas + } + // Offset our y position to account for our column canvas being 32 pixels + int y_offset = y - (offset * scale); + // Dra the 32 pixel high column + for(uint8_t cy = 0; cy < 32; cy++) { + if((1U << cy) & data) { + rectangle(x + (cx * scale), y_offset + (cy * scale), scale, scale); } } d++; + a++; } } diff --git a/libraries/bitmap_fonts/bitmap_fonts.hpp b/libraries/bitmap_fonts/bitmap_fonts.hpp index 432cafd7..c175eb1c 100644 --- a/libraries/bitmap_fonts/bitmap_fonts.hpp +++ b/libraries/bitmap_fonts/bitmap_fonts.hpp @@ -8,6 +8,9 @@ namespace bitmap { struct font_t { const uint8_t height; const uint8_t max_width; + const uint8_t accent_offset_upper; // Number of pixels to shift accents UP above uppercase letters + const uint8_t accent_offset_lower; // Number of pixels to shift accents UP above lowercase letters + const uint8_t accent_offset_below; // Number of pixels to shift accents DOWN below lowercase letters (height of the cedilla accent) const uint8_t widths[96]; const uint8_t data[]; }; diff --git a/libraries/bitmap_fonts/font6_data.hpp b/libraries/bitmap_fonts/font6_data.hpp index 7b199476..c270c5f5 100644 --- a/libraries/bitmap_fonts/font6_data.hpp +++ b/libraries/bitmap_fonts/font6_data.hpp @@ -5,6 +5,9 @@ const bitmap::font_t font6 { .height = 6, .max_width = 6, + .accent_offset_upper = 2, + .accent_offset_lower = 2, + .accent_offset_below = 2, .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, @@ -109,6 +112,15 @@ const bitmap::font_t font6 { 0x3e,0x00,0x00,0x00,0x00,0x00, // | 0x22,0x3e,0x08,0x00,0x00,0x00, // } 0x04,0x02,0x02,0x00,0x00,0x00, // ~ - 0x00,0x00,0x00,0x00,0x00,0x00 + 0x00,0x00,0x00,0x00,0x00,0x00, + // Accents + 0x00,0x00,0x01,0x02,0x00,0x00, // Grave + 0x00,0x00,0x02,0x01,0x00,0x00, // Acute + 0x00,0x02,0x01,0x02,0x00,0x00, // Circumflex + 0x00,0x01,0x02,0x01,0x02,0x00, // Tilde + 0x00,0x01,0x00,0x01,0x00,0x00, // Diaresis + 0x00,0x06,0x09,0x06,0x00,0x00, // Ring Above + 0x00,0x40,0x20,0x10,0x00,0x00, // Stroke + 0x00,0x00,0x28,0x10,0x00,0x00 // Cedilla } }; \ No newline at end of file diff --git a/libraries/bitmap_fonts/font8_data.hpp b/libraries/bitmap_fonts/font8_data.hpp index ad9601dc..e0a6212f 100644 --- a/libraries/bitmap_fonts/font8_data.hpp +++ b/libraries/bitmap_fonts/font8_data.hpp @@ -5,6 +5,9 @@ const bitmap::font_t font8 { .height = 8, .max_width = 6, + .accent_offset_upper = 2, + .accent_offset_lower = 1, + .accent_offset_below = 1, .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, @@ -109,6 +112,15 @@ const bitmap::font_t font8 { 0x7f,0x00,0x00,0x00,0x00,0x00, // | 0x41,0x3e,0x08,0x00,0x00,0x00, // } 0x08,0x04,0x08,0x04,0x00,0x00, // ~ - 0x00,0x00,0x00,0x00,0x00,0x00 + 0x00,0x00,0x00,0x00,0x00,0x00, + // Accents + 0x00,0x00,0x01,0x02,0x00,0x00, // Grave + 0x00,0x00,0x02,0x01,0x00,0x00, // Acute + 0x00,0x02,0x01,0x02,0x00,0x00, // Circumflex + 0x00,0x01,0x02,0x01,0x02,0x00, // Tilde + 0x00,0x01,0x00,0x01,0x00,0x00, // Diaresis + 0x00,0x06,0x09,0x06,0x00,0x00, // Ring Above + 0x00,0x40,0x20,0x00,0x00,0x00, // Stroke + 0x00,0x00,0xa0,0x40,0x00,0x00 // Cedilla } }; \ No newline at end of file diff --git a/libraries/hershey_fonts/hershey_fonts.cpp b/libraries/hershey_fonts/hershey_fonts.cpp index 56c0d8c1..7136ba1f 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 = char_base[c - 128]; + c = unicode_sorta::char_base[c - 128]; } return &font->chars[c - 32]; @@ -50,9 +50,6 @@ 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