fix(bw): language special characters not working for 10x14 font size (#4816)

Also cleans up the font handling to make the different font sizes more consistent.
It will now allow more than 64 special characters for language translation (if it is ever required).
This commit is contained in:
philmoz
2024-03-30 10:57:30 +10:00
committed by GitHub
parent 2d4c1acbfb
commit d73d88a10b
7 changed files with 178 additions and 180 deletions
+51 -60
View File
@@ -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);
+1 -5
View File
@@ -19,8 +19,7 @@
* GNU General Public License for more details.
*/
#ifndef _LCD_H_
#define _LCD_H_
#pragma once
#include <inttypes.h>
@@ -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_
+51 -59
View File
@@ -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
+1 -5
View File
@@ -19,8 +19,7 @@
* GNU General Public License for more details.
*/
#ifndef _LCD_H_
#define _LCD_H_
#pragma once
#include <inttypes.h>
@@ -255,6 +254,3 @@ private:
coord_t pos;
};
#endif // _LCD_H_
+53 -33
View File
@@ -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)
+17 -14
View File
@@ -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[];
+4 -4
View File
@@ -21,6 +21,7 @@
/* -*- coding: utf-8 -*- */
#include <stdint.h>
#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)