Bitmap Fonts: Add accent rendering.

Render accents above and below the 64 characters > 127.

Different offsets for upper/lower case characters.
This commit is contained in:
Phil Howard 2022-03-31 18:09:50 +01:00
parent ef940cc5ea
commit 6a9bc8688f
6 changed files with 67 additions and 12 deletions

View File

@ -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
};
};
}

View File

@ -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++;
}
}

View File

@ -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[];
};

View File

@ -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
}
};

View File

@ -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
}
};

View File

@ -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