diff --git a/radio/src/gui/128x64/lcd.cpp b/radio/src/gui/128x64/lcd.cpp index 47c25b1a5..bcc4b4457 100644 --- a/radio/src/gui/128x64/lcd.cpp +++ b/radio/src/gui/128x64/lcd.cpp @@ -162,70 +162,72 @@ uint8_t getPatternWidth(const PatternData * pattern) LcdFlags getCharPattern(PatternData * pattern, unsigned char c, LcdFlags flags) { #if !defined(BOOT) + static const uint8_t fontWidth[] = { 5, 3, 5, 8, 10, 22, 5 }; + static const uint8_t fontHeight[] = { 7, 5, 6, 12, 16, 38, 7 }; + uint32_t fontsize = FONTSIZE(flags); unsigned char c_remapped = 0; if (fontsize == DBLSIZE || (flags & BOLD)) { // To save space only some DBLSIZE and BOLD chars are available // c has to be remapped. All non existing chars mapped to 0 (space) - if (c>=',' && c<=':') + if (c >= ',' && c <= ':') c_remapped = c - ',' + 1; - else if (c>='A' && c<='Z') + else if (c >= 'A' && c <= 'Z') c_remapped = c - 'A' + 16; - else if (c>='a' && c<='z') + else if (c >= 'a' && c <= 'z') c_remapped = c - 'a' + 42; - else if (c=='_') + else if (c == '_') c_remapped = 4; - else if (c!=' ') - flags &= ~BOLD; + else if (c != ' ') + flags &= ~BOLD; // For BOLD use Standard font if character is not in BOLD } - if (fontsize == DBLSIZE) { - pattern->width = 10; - pattern->height = 16; - if (c >= 0xC0) { - pattern->data = &font_10x14_extra[((uint16_t)(c-0xC0))*20]; - } - else { - if (c >= 128) - c_remapped = c - 81; - pattern->data = &font_10x14[((uint16_t)c_remapped)*20]; - } - } - else if (fontsize == XXLSIZE) { - pattern->width = 22; - pattern->height = 38; - pattern->data = &font_22x38_num[((uint16_t)c-'0'+5)*110]; - } - else if (fontsize == MIDSIZE) { - pattern->width = 8; - pattern->height = 12; - pattern->data = &font_8x10[((uint16_t)c-0x20)*16]; - } - else if (fontsize == SMLSIZE) { - pattern->width = 5; - pattern->height = 6; - pattern->data = (c < 0xc0 ? &font_4x6[(c-0x20)*5] : &font_4x6_extra[(c-0xc0)*5]); - } - else if (fontsize == TINSIZE) { - pattern->width = 3; - pattern->height = 5; - pattern->data = &font_3x5[((uint16_t)c-0x20)*3]; - } - else if (flags & BOLD) { - pattern->width = 5; - pattern->height = 7; - pattern->data = &font_5x7_B[c_remapped*5]; - } - else { - pattern->width = 5; - pattern->height = 7; - pattern->data = &font_5x7[(c - 0x20) * 5]; - } + uint8_t fontIdx = fontsize >> 8; + if (fontIdx == 0 && flags & BOLD) fontIdx = 6; + + pattern->width = fontWidth[fontIdx]; + pattern->height = fontHeight[fontIdx]; + int charSize = (pattern->height + 7) / 8 * pattern->width; + + switch (fontIdx) { + case 0: // Standard + pattern->data = &font_5x7[(c - FONT_BASE_START) * charSize]; + break; + case 1: // TINSIZE + pattern->data = &font_3x5[(c - FONT_BASE_START) * charSize]; + break; + case 2: // SMLSIZE + // Adjust language special characters offset + if (c >= FONT_LANG_START) + c = c - (FONT_SYMS_CNT - FONT_SYMS_CNT_4x6); + pattern->data = &font_4x6[(c - FONT_BASE_START) * charSize]; + break; + case 3: // MDLSIZE + // Adjust language special characters offset + if (c >= FONT_LANG_START) + c = c - FONT_SYMS_CNT; + pattern->data = &font_8x10[(c - FONT_BASE_START) * charSize]; + break; + case 4: // DBLSIZE + // Adjust language special characters offset and symbols offset + if (c >= FONT_LANG_START) + c_remapped = c - (FONT_BASE_CNT - FONT_BASE_CNT_10x14) - (FONT_SYMS_CNT - FONT_SYMS_CNT_10x14) - FONT_BASE_START; + else if (c >= FONT_SYMS_START) + c_remapped = c - (FONT_BASE_CNT - FONT_BASE_CNT_10x14) - FONT_BASE_START; + pattern->data = &font_10x14[(c_remapped) * charSize]; + break; + case 5: // XXLSIZE + pattern->data = &font_22x38_num[(c - '0' + 5) * charSize]; + break; + case 6: // BOLD + pattern->data = &font_5x7_B[c_remapped * charSize]; + break; + }; #else pattern->width = 5; pattern->height = 7; - pattern->data = &font_5x7[(c-0x20)*5]; + pattern->data = &font_5x7[(c - FONT_BASE_START) * 5]; #endif return flags; } @@ -240,14 +242,9 @@ uint8_t getCharWidth(char c, LcdFlags flags) void lcdDrawChar(coord_t x, coord_t y, uint8_t c, LcdFlags flags) { lcdNextPos = x - 1; -#if defined(BOOT) - const uint8_t * data = &font_5x7[(c-0x20)*5]; - lcdPutPattern(x, y, data, 5, 7, flags); -#else PatternData pattern; flags = getCharPattern(&pattern, c, flags); lcdPutPattern(x, y, pattern.data, pattern.width, pattern.height, flags); -#endif } void lcdDrawChar(coord_t x, coord_t y, uint8_t c) @@ -260,12 +257,7 @@ uint8_t getTextWidth(const char * s, uint8_t len, LcdFlags flags) uint8_t width = 0; if (len == 0) len = strlen(s); while (len--) { -#if !defined(BOOT) unsigned char c = map_utf8_char(s, len); - if (c >= 0x95 && FONTSIZE(flags)) c -=21; -#else - unsigned char c = *s; -#endif if (!c) { break; } @@ -306,7 +298,6 @@ void lcdDrawSizedText(coord_t x, coord_t y, const char * s, uint8_t len, LcdFlag else if (c >= 0x20) { // UTF8 detection c = map_utf8_char(s, len); - if (c >= 0x95 && fontsize) c -=21; if (!c) break; lcdDrawChar(x, y, c, flags); diff --git a/radio/src/gui/128x64/lcd.h b/radio/src/gui/128x64/lcd.h index b126f6936..97cda9672 100644 --- a/radio/src/gui/128x64/lcd.h +++ b/radio/src/gui/128x64/lcd.h @@ -19,8 +19,7 @@ * GNU General Public License for more details. */ -#ifndef _LCD_H_ -#define _LCD_H_ +#pragma once #include @@ -94,7 +93,6 @@ extern coord_t lcdNextPos; #define IS_IN_DISPLAY(p) ((p) >= displayBuf && (p) < DISPLAY_END) #define ASSERT_IN_DISPLAY(p) assert((p) >= displayBuf && (p) < DISPLAY_END) - void lcdDrawChar(coord_t x, coord_t y, uint8_t c); void lcdDrawChar(coord_t x, coord_t y, uint8_t c, LcdFlags flags); void lcdDrawCenteredText(coord_t y, const char * s, LcdFlags flags = 0); @@ -190,5 +188,3 @@ inline pixel_t getPixel(uint8_t x, uint8_t y) } uint8_t getTextWidth(const char * s, uint8_t len=0, LcdFlags flags=0); - -#endif // _LCD_H_ diff --git a/radio/src/gui/212x64/lcd.cpp b/radio/src/gui/212x64/lcd.cpp index 318c10358..9b13bdb89 100644 --- a/radio/src/gui/212x64/lcd.cpp +++ b/radio/src/gui/212x64/lcd.cpp @@ -167,6 +167,9 @@ void lcdPutPattern(coord_t x, coord_t y, const uint8_t * pattern, uint8_t width, LcdFlags getCharPattern(PatternData * pattern, unsigned char c, LcdFlags flags) { #if !defined(BOOT) + static const uint8_t fontWidth[] = { 5, 3, 5, 8, 10, 22, 5 }; + static const uint8_t fontHeight[] = { 7, 5, 6, 12, 16, 38, 7 }; + uint32_t fontsize = FONTSIZE(flags); unsigned char c_remapped = 0; @@ -175,62 +178,61 @@ LcdFlags getCharPattern(PatternData * pattern, unsigned char c, LcdFlags flags) // c has to be remapped. All non existing chars mapped to 0 (space) if (c >= ',' && c <= ':') c_remapped = c - ',' + 1; - else if (c>='A' && c<='Z') + else if (c >= 'A' && c <= 'Z') c_remapped = c - 'A' + 16; - else if (c>='a' && c<='z') + else if (c >= 'a' && c <= 'z') c_remapped = c - 'a' + 42; - else if (c=='_') + else if (c == '_') c_remapped = 4; - else if (c!=' ') - flags &= ~BOLD; + else if (c != ' ') + flags &= ~BOLD; // For BOLD use Standard font if character is not in BOLD } - if (fontsize == DBLSIZE) { - pattern->width = 10; - pattern->height = 16; - if (c >= 0x80) { - pattern->data = &font_10x14_extra[((uint16_t) (c - 0x80)) * 20]; - } - else { - if (c >= 0x80) - c_remapped = c - 81; - pattern->data = &font_10x14[((uint16_t) c_remapped) * 20]; - } - } - else if (fontsize == XXLSIZE) { - pattern->width = 22; - pattern->height = 38; - pattern->data = &font_22x38_num[((uint16_t) c - '0' + 5) * 110]; - } - else if (fontsize == MIDSIZE) { - pattern->width = 8; - pattern->height = 12; - pattern->data = &font_8x10[((uint16_t) c - 0x20) * 16]; - } - else if (fontsize == SMLSIZE) { - pattern->width = 5; - pattern->height = 6; - pattern->data = (c < 0x80 ? &font_4x6[(c - 0x20) * 5] : &font_4x6_extra[(c - 0x80) * 5]); - } - else if (fontsize == TINSIZE) { - pattern->width = 3; - pattern->height = 5; - pattern->data = &font_3x5[((uint16_t) c - 0x20) * 3]; - } - else if (flags & BOLD) { - pattern->width = 5; - pattern->height = 7; - pattern->data = &font_5x7_B[c_remapped*5]; - } - else { - pattern->width = 5; - pattern->height = 7; - pattern->data = &font_5x7[(c - 0x20) * 5]; - } + uint8_t fontIdx = fontsize >> 8; + if (fontIdx == 0 && flags & BOLD) fontIdx = 6; + + pattern->width = fontWidth[fontIdx]; + pattern->height = fontHeight[fontIdx]; + int charSize = (pattern->height + 7) / 8 * pattern->width; + + switch (fontIdx) { + case 0: // Standard + pattern->data = &font_5x7[(c - FONT_BASE_START) * charSize]; + break; + case 1: // TINSIZE + pattern->data = &font_3x5[(c - FONT_BASE_START) * charSize]; + break; + case 2: // SMLSIZE + // Adjust language special characters offset + if (c >= FONT_LANG_START) + c = c - (FONT_SYMS_CNT - FONT_SYMS_CNT_4x6); + pattern->data = &font_4x6[(c - FONT_BASE_START) * charSize]; + break; + case 3: // MDLSIZE + // Adjust language special characters offset + if (c >= FONT_LANG_START) + c = c - FONT_SYMS_CNT; + pattern->data = &font_8x10[(c - FONT_BASE_START) * charSize]; + break; + case 4: // DBLSIZE + // Adjust language special characters offset and symbols offset + if (c >= FONT_LANG_START) + c_remapped = c - (FONT_BASE_CNT - FONT_BASE_CNT_10x14) - (FONT_SYMS_CNT - FONT_SYMS_CNT_10x14) - FONT_BASE_START; + else if (c >= FONT_SYMS_START) + c_remapped = c - (FONT_BASE_CNT - FONT_BASE_CNT_10x14) - FONT_BASE_START; + pattern->data = &font_10x14[(c_remapped) * charSize]; + break; + case 5: // XXLSIZE + pattern->data = &font_22x38_num[(c - '0' + 5) * charSize]; + break; + case 6: // BOLD + pattern->data = &font_5x7_B[c_remapped * charSize]; + break; + }; #else pattern->width = 5; pattern->height = 7; - pattern->data = &font_5x7[(c - 0x20) * 5]; + pattern->data = &font_5x7[(c - FONT_BASE_START) * 5]; #endif return flags; } @@ -245,14 +247,9 @@ uint8_t getCharWidth(char c, LcdFlags flags) void lcdDrawChar(coord_t x, coord_t y, uint8_t c, LcdFlags flags) { lcdNextPos = x - 1; -#if defined(BOOT) - const uint8_t * data = &font_5x7[(c-0x20)*5]; - lcdPutPattern(x, y, data, 5, 7, flags); -#else PatternData pattern; flags = getCharPattern(&pattern, c, flags); lcdPutPattern(x, y, pattern.data, pattern.width, pattern.height, flags); -#endif } void lcdDrawChar(coord_t x, coord_t y, uint8_t c) @@ -264,11 +261,7 @@ uint8_t getTextWidth(const char * s, uint8_t len, LcdFlags flags) { uint8_t width = 0; for (int i = 0; len == 0 || i < len; ++i) { -#if !defined(BOOT) - unsigned char c = *s; -#else - unsigned char c = *s; -#endif + unsigned char c = map_utf8_char(s, len); if (!c) { break; } @@ -309,7 +302,6 @@ void lcdDrawSizedText(coord_t x, coord_t y, const char * s, uint8_t len, LcdFlag #if !defined(BOOT) // UTF8 detection c = map_utf8_char(s, len); - if (c >= 0x95 && FONTSIZE(flags)) c -=21; if (!c) break; if (c == 46 && FONTSIZE(flags) == TINSIZE) { // '.' handling diff --git a/radio/src/gui/212x64/lcd.h b/radio/src/gui/212x64/lcd.h index 6d018c4ba..c7d6a3fa2 100644 --- a/radio/src/gui/212x64/lcd.h +++ b/radio/src/gui/212x64/lcd.h @@ -19,8 +19,7 @@ * GNU General Public License for more details. */ -#ifndef _LCD_H_ -#define _LCD_H_ +#pragma once #include @@ -255,6 +254,3 @@ private: coord_t pos; }; - - -#endif // _LCD_H_ diff --git a/radio/src/gui/common/stdlcd/fonts.cpp b/radio/src/gui/common/stdlcd/fonts.cpp index 0fe41b46e..74c3a33ad 100644 --- a/radio/src/gui/common/stdlcd/fonts.cpp +++ b/radio/src/gui/common/stdlcd/fonts.cpp @@ -21,6 +21,32 @@ #include "fonts.h" +/* + Strings in EdgeTX are encoded using UTF8. Latin characters are single byte in the range 32 - 127. + Special characters for language translations and special symbols are encoded as 2-byte or 3-byte + sequences. + The UTF8 encoded characters are mapped to single byte characters before display. + The single byte characters are mapped to the various font sizes as per the table below: + + Char 3x5 4x6 5x7 5x7 BOLD 8x10 10x14 22x38 + Range TINSIZE SMLSIZE Standard BOLD MDLSIZE DBLSIZE XXLSIZE + ----- ------- ------- -------- -------- ------- ------- ------- + 0 - 31 not used not used not used not used not used not used not used + 31 - 127 Latin(1) Latin Latin Latin(2) Latin Latin(2) Latin(3) + 128 - 148 not used extra(4) extra(5) extra(6) not used extra(4) not used + 149 - 255 not used Language Language Language(7) Language Language not used + + Notes: + (1) - reduced character set, contains only space, upper case letters, numbers, '-' and '.'. + (2) - reduced character set, contains only space, alphanumeric, ',', '.', '-', ':' and '_'. + (3) - reduced character set, contains only space, numbers, ',', '.', '-', ':' and '_'. + Note: to display ' ' use '+', to display '_' use '/'. + (4) - arrows + (5) - arrows and symbols (e.g. delta, stick, switch, etc) + (6) - uses the 5x7 arrow and symbol font characters (not bold) + (7) - uses the 5x7 Language font characters (not bold) +*/ + const unsigned char font_5x7[] = { #include "font_05x07.lbm" #include "font_05x07_extra.lbm" @@ -58,31 +84,32 @@ const unsigned char font_5x7_B[] = { const unsigned char font_10x14[] = { #include "font_10x14_compressed.lbm" - #if defined(TRANSLATIONS_DE) - #include "font_de_10x14.lbm" - #elif defined(TRANSLATIONS_DA) - #include "font_da_10x14.lbm" - #elif defined(TRANSLATIONS_CZ) - #include "font_cz_10x14.lbm" - #elif defined(TRANSLATIONS_ES) - #include "font_es_10x14.lbm" - #elif defined(TRANSLATIONS_FI) - #include "font_fi_10x14.lbm" - #elif defined(TRANSLATIONS_FR) - #include "font_fr_10x14.lbm" - #elif defined(TRANSLATIONS_IT) - #include "font_it_10x14.lbm" - #elif defined(TRANSLATIONS_PL) - #include "font_pl_10x14.lbm" - #elif defined(TRANSLATIONS_PT) - #include "font_pt_10x14.lbm" - #elif defined(TRANSLATIONS_RU) - #include "font_ru_10x14.lbm" - #elif defined(TRANSLATIONS_SE) - #include "font_se_10x14.lbm" - #elif defined(TRANSLATIONS_UA) - #include "font_ua_10x14.lbm" - #endif +#include "font_10x14_extra.lbm" +#if defined(TRANSLATIONS_DE) +#include "font_de_10x14.lbm" +#elif defined(TRANSLATIONS_DA) +#include "font_da_10x14.lbm" +#elif defined(TRANSLATIONS_CZ) +#include "font_cz_10x14.lbm" +#elif defined(TRANSLATIONS_ES) +#include "font_es_10x14.lbm" +#elif defined(TRANSLATIONS_FI) +#include "font_fi_10x14.lbm" +#elif defined(TRANSLATIONS_FR) +#include "font_fr_10x14.lbm" +#elif defined(TRANSLATIONS_IT) +#include "font_it_10x14.lbm" +#elif defined(TRANSLATIONS_PL) +#include "font_pl_10x14.lbm" +#elif defined(TRANSLATIONS_PT) +#include "font_pt_10x14.lbm" +#elif defined(TRANSLATIONS_RU) +#include "font_ru_10x14.lbm" +#elif defined(TRANSLATIONS_SE) +#include "font_se_10x14.lbm" +#elif defined(TRANSLATIONS_UA) +#include "font_ua_10x14.lbm" +#endif }; const unsigned char font_3x5[] = { @@ -91,6 +118,7 @@ const unsigned char font_3x5[] = { const unsigned char font_4x6[] = { #include "font_04x06.lbm" +#include "font_04x06_extra.lbm" #if defined(TRANSLATIONS_DE) #include "font_de_04x06.lbm" #elif defined(TRANSLATIONS_DA) @@ -151,12 +179,4 @@ const unsigned char font_22x38_num[] = { #include "font_22x38_num.lbm" }; -const unsigned char font_4x6_extra[] = { -#include "font_04x06_extra.lbm" -}; - -const unsigned char font_10x14_extra[] = { -#include "font_10x14_extra.lbm" -}; - #endif // !defined(BOOT) diff --git a/radio/src/gui/common/stdlcd/fonts.h b/radio/src/gui/common/stdlcd/fonts.h index e4ab192ed..9252bca7a 100644 --- a/radio/src/gui/common/stdlcd/fonts.h +++ b/radio/src/gui/common/stdlcd/fonts.h @@ -19,20 +19,23 @@ * GNU General Public License for more details. */ -#ifndef _FONTS_H_ -#define _FONTS_H_ +#pragma once + +constexpr int FONT_BASE_START = 0x20; +constexpr int FONT_SYMS_START = 0x80; +constexpr int FONT_LANG_START = 0x95; + +constexpr int FONT_BASE_CNT = 96; // Number of characters in standard 5x7 font +constexpr int FONT_BASE_CNT_10x14 = 68; // Number of characters in compressed 10x14 font + +constexpr int FONT_SYMS_CNT = 21; // Max # of extra symbols (based on 5x7 standard font) +constexpr int FONT_SYMS_CNT_4x6 = 8; // # of extra symbols in 4x6 font (adjust if font is changed) +constexpr int FONT_SYMS_CNT_10x14 = 8; // # of extra symbols in 10x14 font (adjust if font is changed) extern const unsigned char font_5x7[]; +extern const unsigned char font_5x7_B[]; +extern const unsigned char font_3x5[]; +extern const unsigned char font_4x6[]; +extern const unsigned char font_8x10[]; extern const unsigned char font_10x14[]; - -#if !defined(BOOT) - extern const unsigned char font_5x7_B[]; - extern const unsigned char font_3x5[]; - extern const unsigned char font_4x6[]; - extern const unsigned char font_8x10[]; - extern const unsigned char font_22x38_num[]; - extern const unsigned char font_10x14_extra[]; - extern const unsigned char font_4x6_extra[]; -#endif - -#endif // _FONTS_H_ +extern const unsigned char font_22x38_num[]; diff --git a/radio/src/gui/common/stdlcd/utf8.cpp b/radio/src/gui/common/stdlcd/utf8.cpp index e7dcb627b..8513c0bcf 100644 --- a/radio/src/gui/common/stdlcd/utf8.cpp +++ b/radio/src/gui/common/stdlcd/utf8.cpp @@ -21,6 +21,7 @@ /* -*- coding: utf-8 -*- */ #include +#include "fonts.h" #include "definitions.h" #include "translations/untranslated.h" @@ -141,7 +142,7 @@ static unsigned char lookup_utf8_mapping(wchar_t w) { for (uint32_t i=0; i < DIM(_utf8_lut); i++) { if (w == _utf8_lut[i]) - return 0x95 + (uint8_t)i; // TODO: use constant + return FONT_LANG_START + (uint8_t)i; } return 0x20; // return 'space' for unknown chars } @@ -177,8 +178,7 @@ unsigned char map_utf8_char(const char*& s, uint8_t& len) len--; s++; c = *s; w |= c & 0x3F; } - // TODO: use constants - if (w >= 0x80 && w <= 0x94) { // extra chars + if (w >= FONT_SYMS_START && w < FONT_LANG_START) { // extra chars return (unsigned char)w; } if(w == L'≥') @@ -187,7 +187,7 @@ unsigned char map_utf8_char(const char*& s, uint8_t& len) return STR_CHAR_BW_DEGREE; #if defined(UTF8_SUBS_LUT) auto w_map = lookup_utf8_substitution(w); - if (w_map> 0x95) + if (w_map> FONT_LANG_START) w_map = lookup_utf8_mapping(w_map); return w_map; #elif !defined(NO_UTF8_LUT)