- did a bit of fine tuning to the character replacement mappings:

* prefer accent-less lower case over uppercase letters if an accented lower case letter cannot be found.
* added accent-less mappings for Latin Extended 1 (0x100-0x17f) and some easy to handle characters between 0x200 and 0x220. This should allow to display all Eastern European text without empty gaps for missing letters.

# Conflicts:
#	src/v_font.cpp
This commit is contained in:
Christoph Oelckers 2019-02-17 13:41:04 +01:00 committed by drfrag
parent b14a48d2dc
commit d51728c7c3

View file

@ -953,52 +953,67 @@ static bool myislower(int code)
return false; return false;
} }
// Returns a character without an accent mark. // Returns a character without an accent mark (or one with a similar looking accent in some cases where direct support is unlikely.
// FIXME: Only valid for CP-1252; we should go Unicode at some point.
static int stripaccent(int code) static int stripaccent(int code)
{ {
if (code < 0x8a) if (code < 0x8a)
return code; return code;
if (code == 0x8a) // Latin capital letter S with caron if (code < 0x100)
return 'S'; {
if (code == 0x8e) // Latin capital letter Z with caron if (code == 0x8a) // Latin capital letter S with caron
return 'Z'; return 'S';
if (code == 0x9a) // Latin small letter S with caron if (code == 0x8e) // Latin capital letter Z with caron
return 's'; return 'Z';
if (code == 0x9e) // Latin small letter Z with caron if (code == 0x9a) // Latin small letter S with caron
return 'z'; return 's';
if (code == 0x9f) // Latin capital letter Y with diaeresis if (code == 0x9e) // Latin small letter Z with caron
return 'Y'; return 'z';
if (code == 0xff) // Latin small letter Y with diaeresis if (code == 0x9f) // Latin capital letter Y with diaeresis
return 'y'; return 'Y';
// Every other accented character has the high two bits set. if (code == 0xff) // Latin small letter Y with diaeresis
if ((code & 0xC0) == 0) return 'y';
return code; // Every other accented character has the high two bits set.
// Make lowercase characters uppercase so there are half as many tests. if ((code & 0xC0) == 0)
int acode = code & 0xDF; return code;
if (acode >= 0xC0 && acode <= 0xC5) // A with accents // Make lowercase characters uppercase so there are half as many tests.
return 'A' + (code & 0x20); int acode = code & 0xDF;
if (acode == 0xC7) // Cedilla if (acode >= 0xC0 && acode <= 0xC5) // A with accents
return 'C' + (acode & 0x20); return 'A' + (code & 0x20);
if (acode >= 0xC8 && acode <= 0xCB) // E with accents if (acode == 0xC7) // Cedilla
return 'E' + (code & 0x20); return 'C' + (acode & 0x20);
if (acode >= 0xCC && acode <= 0xCF) // I with accents if (acode >= 0xC8 && acode <= 0xCB) // E with accents
return 'I' + (code & 0x20); return 'E' + (code & 0x20);
if (acode == 0xD0) // Eth if (acode >= 0xCC && acode <= 0xCF) // I with accents
return 'D' + (code & 0x20); return 'I' + (code & 0x20);
if (acode == 0xD1) // N with tilde if (acode == 0xD0) // Eth
return 'N' + (code & 0x20); return 'D' + (code & 0x20);
if ((acode >= 0xD2 && acode <= 0xD6) || // O with accents if (acode == 0xD1) // N with tilde
acode == 0xD8) // O with stroke return 'N' + (code & 0x20);
return 'O' + (code & 0x20); if ((acode >= 0xD2 && acode <= 0xD6) || // O with accents
if (acode >= 0xD9 && acode <= 0xDC) // U with accents acode == 0xD8) // O with stroke
return 'U' + (code & 0x20); return 'O' + (code & 0x20);
if (acode == 0xDD) // Y with accute if (acode >= 0xD9 && acode <= 0xDC) // U with accents
return 'Y' + (code & 0x20); return 'U' + (code & 0x20);
if (acode == 0xDE) // Thorn if (acode == 0xDD) // Y with accute
return 'P' + (code & 0x20); // well, it sort of looks like a 'P' return 'Y' + (code & 0x20);
// fixme: codes above 0x100 not supported yet! if (acode == 0xDE) // Thorn
return 'P' + (code & 0x20); // well, it sort of looks like a 'P'
}
else if (code >= 0x100 && code < 0x180)
{
static const char accentless[] = "AaAaAaCcCcCcCcDdDdEeEeEeEeEeGgGgGgGgHhHhIiIiIiIiIiIiJjKkkLlLlLlLlLlNnNnNnnNnOoOoOoOoRrRrRrSsSsSsSsTtTtTtUuUuUuUuUuUuWwYyYZzZzZz ";
return accentless[code -0x100];
}
else if (code >= 0x200 && code < 0x21c)
{
// 0x200-0x217 are probably irrelevant but easy to map to other characters more likely to exist. 0x218-0x21b are relevant for Romanian but also have a fallback within ranges that are more likely to be supported.
static const uint16_t u200map[] = {0xc4, 0xe4, 0xc2, 0xe2, 0xcb, 0xeb, 0xca, 0xea, 0xcf, 0xef, 0xce, 0xee, 0xd6, 0xf6, 0xd4, 0xe4, 'R', 'r', 'R', 'r', 0xdc, 0xfc, 0xdb, 0xfb, 0x15e, 0x15f, 0x162, 0x163};
return u200map[code - 0x200];
}
// skip the rest of Latin characters because none of them are relevant for modern languages.
return code; return code;
} }
@ -1475,18 +1490,12 @@ int FFont::GetCharCode(int code, bool needpic) const
{ {
return code; return code;
} }
// Try converting lowercase characters to uppercase.
if (myislower(code)) int originalcode = code;
{ int newcode;
code = upperforlower[code];
if (code >= FirstChar && code <= LastChar && (!needpic || Chars[code - FirstChar].Pic != NULL)) // Try stripping accents from accented characters. This may repeat to allow multi-step fallbacks.
{ while ((newcode = stripaccent(code)) != code)
return code;
}
}
// Try stripping accents from accented characters.
int newcode = stripaccent(code);
if (newcode != code)
{ {
code = newcode; code = newcode;
if (code >= FirstChar && code <= LastChar && (!needpic || Chars[code - FirstChar].Pic != NULL)) if (code >= FirstChar && code <= LastChar && (!needpic || Chars[code - FirstChar].Pic != NULL))
@ -1494,6 +1503,14 @@ int FFont::GetCharCode(int code, bool needpic) const
return code; return code;
} }
} }
if (myislower(code))
{
int upper = upperforlower[code];
// Stripping accents did not help - now try uppercase for lowercase
if (upper != code) return GetCharCode(upper, needpic);
}
return -1; return -1;
} }