kopia lustrzana https://github.com/pimoroni/pimoroni-pico
Bitmap Fonts: Refactor and support for pound/degrees.
rodzic
b2ff46b516
commit
0d43973326
|
@ -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
|
||||
|
|
|
@ -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];
|
||||
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
|
||||
|
|
|
@ -3,20 +3,24 @@
|
|||
#include <functional>
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
#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<void(int32_t x, int32_t y, int32_t w, int32_t h)> 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);
|
||||
}
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue