#include "font.h" #include "utf8.h" #include "progmem.h" #include #define FONT_EXTRAS_START (0x7e - 0x20 + 1) union utf_lookup { const char symbol[4]; /// symbol as uint, but not decoded - just for matching! const uint32_t uint; }; struct utf_glyph5x { union utf_lookup utf; font5x_bitmap_t graphic; }; struct utf_glyph4x { union utf_lookup utf; font4x_bitmap_t graphic; }; struct utf_glyph3x { union utf_lookup utf; font3x_bitmap_t graphic; }; #define F57_NUM_ASCII 95 #define F57_ASCII_START 0x20 #define F57_ASCII_END 0x7e // ASCII symbols are stored as bare graphic to reduce ROM size static const font5x_bitmap_t PROGMEM font57_ascii[F57_NUM_ASCII] = { {{0x00, 0x00, 0x00, 0x00, 0x00}}, // 0x20 {{0x00, 0x00, 0x5f, 0x00, 0x00}}, // ! 0x21 {{0x00, 0x07, 0x00, 0x07, 0x00}}, // \" 0x22 {{0x14, 0x7f, 0x14, 0x7f, 0x14}}, // # 0x23 {{0x24, 0x2a, 0x7f, 0x2a, 0x12}}, // $ 0x24 {{0x23, 0x13, 0x08, 0x64, 0x62}}, // % 0x25 {{0x36, 0x49, 0x55, 0x22, 0x50}}, // & 0x26 {{0x00, 0x05, 0x03, 0x00, 0x00}}, // ' 0x27 {{0x00, 0x1c, 0x22, 0x41, 0x00}}, // ( 0x28 {{0x00, 0x41, 0x22, 0x1c, 0x00}}, // ) 0x29 {{0x14, 0x08, 0x3e, 0x08, 0x14}}, // * 0x2a {{0x08, 0x08, 0x3e, 0x08, 0x08}}, // + 0x2b {{0x00, 0x50, 0x30, 0x00, 0x00}}, // , 0x2c {{0x08, 0x08, 0x08, 0x08, 0x08}}, // - 0x2d {{0x00, 0x60, 0x60, 0x00, 0x00}}, // . 0x2e {{0x20, 0x10, 0x08, 0x04, 0x02}}, // / 0x2f {{0x3e, 0x51, 0x49, 0x45, 0x3e}}, // 0 0x30 {{0x00, 0x42, 0x7f, 0x40, 0x00}}, // 1 0x31 {{0x42, 0x61, 0x51, 0x49, 0x46}}, // 2 0x32 {{0x21, 0x41, 0x45, 0x4b, 0x31}}, // 3 0x33 {{0x18, 0x14, 0x12, 0x7f, 0x10}}, // 4 0x34 {{0x27, 0x45, 0x45, 0x45, 0x39}}, // 5 0x35 {{0x3c, 0x4a, 0x49, 0x49, 0x30}}, // 6 0x36 {{0x01, 0x71, 0x09, 0x05, 0x03}}, // 7 0x37 {{0x36, 0x49, 0x49, 0x49, 0x36}}, // 8 0x38 {{0x06, 0x49, 0x49, 0x29, 0x1e}}, // 9 0x39 {{0x00, 0x36, 0x36, 0x00, 0x00}}, // : 0x3a {{0x00, 0x56, 0x36, 0x00, 0x00}}, // ; 0x3b {{0x08, 0x14, 0x22, 0x41, 0x00}}, // < 0x3c {{0x14, 0x14, 0x14, 0x14, 0x14}}, // = 0x3d {{0x00, 0x41, 0x22, 0x14, 0x08}}, // > 0x3e {{0x02, 0x01, 0x51, 0x09, 0x06}}, // ? 0x3f {{0x32, 0x49, 0x79, 0x41, 0x3e}}, // @ 0x40 {{0x7e, 0x11, 0x11, 0x11, 0x7e}}, // A 0x41 {{0x7f, 0x49, 0x49, 0x49, 0x36}}, // B 0x42 {{0x3e, 0x41, 0x41, 0x41, 0x22}}, // C 0x43 {{0x7f, 0x41, 0x41, 0x22, 0x1c}}, // D 0x44 {{0x7f, 0x49, 0x49, 0x49, 0x41}}, // E 0x45 {{0x7f, 0x09, 0x09, 0x09, 0x01}}, // F 0x46 {{0x3e, 0x41, 0x49, 0x49, 0x7a}}, // G 0x47 {{0x7f, 0x08, 0x08, 0x08, 0x7f}}, // H 0x48 {{0x00, 0x41, 0x7f, 0x41, 0x00}}, // I 0x49 {{0x20, 0x40, 0x41, 0x3f, 0x01}}, // J 0x4a {{0x7f, 0x08, 0x14, 0x22, 0x41}}, // K 0x4b {{0x7f, 0x40, 0x40, 0x40, 0x40}}, // L 0x4c {{0x7f, 0x02, 0x0c, 0x02, 0x7f}}, // M 0x4d {{0x7f, 0x04, 0x08, 0x10, 0x7f}}, // N 0x4e {{0x3e, 0x41, 0x41, 0x41, 0x3e}}, // O 0x4f {{0x7f, 0x09, 0x09, 0x09, 0x06}}, // P 0x50 {{0x3e, 0x41, 0x51, 0x21, 0x5e}}, // Q 0x51 {{0x7f, 0x09, 0x19, 0x29, 0x46}}, // R 0x52 {{0x46, 0x49, 0x49, 0x49, 0x31}}, // S 0x53 {{0x01, 0x01, 0x7f, 0x01, 0x01}}, // T 0x54 {{0x3f, 0x40, 0x40, 0x40, 0x3f}}, // U 0x55 {{0x1f, 0x20, 0x40, 0x20, 0x1f}}, // V 0x56 {{0x3f, 0x40, 0x38, 0x40, 0x3f}}, // W 0x57 {{0x63, 0x14, 0x08, 0x14, 0x63}}, // X 0x58 {{0x07, 0x08, 0x70, 0x08, 0x07}}, // Y 0x59 {{0x61, 0x51, 0x49, 0x45, 0x43}}, // Z 0x5a {{0x00, 0x7f, 0x41, 0x41, 0x00}}, // [ 0x5b {{0x02, 0x04, 0x08, 0x10, 0x20}}, // \\ 0x5c {{0x00, 0x41, 0x41, 0x7f, 0x00}}, // ] 0x5d {{0x04, 0x02, 0x01, 0x02, 0x04}}, // ^ 0x5e {{0x40, 0x40, 0x40, 0x40, 0x40}}, // _ 0x5f {{0x00, 0x01, 0x02, 0x04, 0x00}}, // ` 0x60 {{0x20, 0x54, 0x54, 0x54, 0x78}}, // a 0x61 {{0x7f, 0x48, 0x44, 0x44, 0x38}}, // b 0x62 {{0x38, 0x44, 0x44, 0x44, 0x20}}, // c 0x63 {{0x38, 0x44, 0x44, 0x48, 0x7f}}, // d 0x64 {{0x38, 0x54, 0x54, 0x54, 0x18}}, // e 0x65 {{0x08, 0x7e, 0x09, 0x01, 0x02}}, // f 0x66 {{0x0c, 0x52, 0x52, 0x52, 0x3e}}, // g 0x67 {{0x7f, 0x08, 0x04, 0x04, 0x78}}, // h 0x68 {{0x00, 0x44, 0x7d, 0x40, 0x00}}, // i 0x69 {{0x20, 0x40, 0x44, 0x3d, 0x00}}, // j 0x6a {{0x7f, 0x10, 0x28, 0x44, 0x00}}, // k 0x6b {{0x00, 0x41, 0x7f, 0x40, 0x00}}, // l 0x6c {{0x7c, 0x04, 0x18, 0x04, 0x78}}, // m 0x6d {{0x7c, 0x08, 0x04, 0x04, 0x78}}, // n 0x6e {{0x38, 0x44, 0x44, 0x44, 0x38}}, // o 0x6f {{0x7c, 0x14, 0x14, 0x14, 0x08}}, // p 0x70 {{0x08, 0x14, 0x14, 0x18, 0x7c}}, // q 0x71 {{0x7c, 0x08, 0x04, 0x04, 0x08}}, // r 0x72 {{0x48, 0x54, 0x54, 0x54, 0x20}}, // s 0x73 {{0x04, 0x3f, 0x44, 0x40, 0x20}}, // t 0x74 {{0x3c, 0x40, 0x40, 0x20, 0x7c}}, // u 0x75 {{0x1c, 0x20, 0x40, 0x20, 0x1c}}, // v 0x76 {{0x3c, 0x40, 0x30, 0x40, 0x3c}}, // w 0x77 {{0x44, 0x28, 0x10, 0x28, 0x44}}, // x 0x78 {{0x0c, 0x50, 0x50, 0x50, 0x3c}}, // y 0x79 {{0x44, 0x64, 0x54, 0x4c, 0x44}}, // z 0x7a {{0x00, 0x08, 0x36, 0x41, 0x00}}, // { 0x7b {{0x00, 0x00, 0x7f, 0x00, 0x00}}, // | 0x7c {{0x00, 0x41, 0x36, 0x08, 0x00}}, // } 0x7d {{0x10, 0x08, 0x08, 0x10, 0x08}}, // ~ 0x7e }; #define F57_NUM_EXTRA 16 // utf8 characters list ending with empty struct static const struct utf_glyph5x PROGMEM font57_extra[F57_NUM_EXTRA] = { {.symbol="�", {{0xFE, 0x82, 0x82, 0x82, 0xFE}}}, // box - error code {.symbol="×", {{0x22, 0x14, 0x08, 0x14, 0x22}}}, // cross {.symbol="↑", {{0x08, 0x04, 0x3e, 0x04, 0x08}}}, // arrow_up {.symbol="↓", {{0x08, 0x10, 0x3e, 0x10, 0x08}}}, // arrow_down {.symbol="←", {{0x08, 0x1c, 0x2a, 0x08, 0x08}}}, // arrow_left {.symbol="→", {{0x08, 0x08, 0x2a, 0x1c, 0x08}}}, // arrow_right {.symbol="⏰", {{0x1c, 0x22, 0x2e, 0x2a, 0x1c}}}, // clock {.symbol="⌛", {{0x63, 0x55, 0x4d, 0x55, 0x63}}}, // hourglass {.symbol="☸", {{0x1c, 0x22, 0x2a, 0x22, 0x1c}}}, // wheel {.symbol="⏎", {{0x10, 0x38, 0x54, 0x10, 0x1e}}}, // return {.symbol="🌡", {{0x60, 0x9e, 0x81, 0x9e, 0x6a}}}, // thermometer {.symbol="°", {{0x00, 0x07, 0x05, 0x07, 0x00}}}, // degree {.symbol="μ", {{0x7C, 0x20, 0x20, 0x10, 0x3C}}}, // micro {.symbol="🔙", {{0x04, 0x4e, 0x55, 0x44, 0x38}}}, // back {.symbol="▶", {{0x7f, 0x3e, 0x1c, 0x08, 0x00}}}, // tri_right {.symbol="◀", {{0x00, 0x08, 0x1c, 0x3e, 0x7f}}}, // tri_left }; #define F45_NUM_ASCII static const font4x_bitmap_t PROGMEM font45_ascii[F45_NUM_ASCII] = { {{0x0e, 0x11, 0x11, 0x0e}}, // 0 {{0x04, 0x12, 0x1f, 0x10}}, // 1 {{0x12, 0x19, 0x15, 0x12}}, // 2 {{0x0a, 0x11, 0x15, 0x0a}}, // 3 {{0x07, 0x04, 0x1e, 0x04}}, // 4 {{0x17, 0x15, 0x15, 0x09}}, // 5 {{0x0e, 0x15, 0x15, 0x09}}, // 6 {{0x11, 0x09, 0x05, 0x03}}, // 7 {{0x0a, 0x15, 0x15, 0x0a}}, // 8 {{0x12, 0x15, 0x15, 0x0a}}, // 9 {{0x00, 0x00, 0x00, 0x00}}, // ' ' }; #define F45_NUM_EXTRA 7 static const struct utf_glyph4x PROGMEM font45_extra[F45_NUM_EXTRA] = { {.symbol="�", {{0x1f, 0x11, 0x11, 0x1f}}}, // box - error code {.symbol="°", {{0x02, 0x05, 0x02, 0x00}}}, {.symbol="-", {{0x00, 0x04, 0x04, 0x04}}}, {.symbol="C", {{0x0e, 0x11, 0x11, 0x0a}}}, {.symbol="P", {{0x1f, 0x05, 0x05, 0x02}}}, {.symbol="M", {{0x1f, 0x01, 0x02, 0x1f}}}, {.symbol=".", {{0x00, 0x18, 0x18, 0x00}}}, }; const font5x_bitmap_t *font57_getsym(const struct Utf8Char *ch) { const uint8_t byte0 = ch->bytes[0]; if (byte0 < F57_ASCII_START) { // low ASCII is not supported. goto fail; } if (byte0 <= F57_ASCII_END) { // valid ASCII at hard positions. // In this case only the first byte is significant. return &font57_ascii[byte0 - F57_ASCII_START]; } // search UTF8 for (uint8_t i = 0; i < F57_NUM_EXTRA; i++) { const struct utf_glyph5x *sym = &font57_extra[i]; const uint32_t table_ch = pgm_read_dword(&sym->uint); if (table_ch == ch->uint) { return &sym->graphic; } } fail: return &font57_extra[0].graphic; // replacement character } const font4x_bitmap_t *font45_getsym(const struct Utf8Char *ch) { const uint8_t byte0 = ch->bytes[0]; if (byte0 == ' ') { return &font45_ascii[10]; } if (byte0 >= '0' && byte0 <= '9') { return &font45_ascii[byte0 - '0']; } // search UTF8 for (uint8_t i = 0; i < F45_NUM_EXTRA; i++) { const struct utf_glyph4x *sym = &font45_extra[i]; const uint32_t table_ch = pgm_read_dword(&sym->uint); if (table_ch == ch->uint) { return &sym->graphic; } } fail: return &font45_extra[0].graphic; // replacement character }