From 7e1982fa65f154f5f99f9c39659a926bdc712434 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 31 Mar 2023 17:40:19 +0200 Subject: [PATCH] - adapted font system to properly handle Turkish. Those i's are really messy, especially when dealing with allcaps or pure lowercase fonts. --- src/common/engine/i_interface.h | 1 + src/common/fonts/font.cpp | 30 ++++++++++++++---- src/common/fonts/v_text.cpp | 14 ++++++++ src/common/utility/utf8.cpp | 13 +++++--- .../filter/doom.id/fonts/bigupper/0131.lmp | Bin 0 -> 134 bytes .../fonts/defbigfont/{0081.lmp => 0131.lmp} | Bin .../fonts/defsmallfont/{0081.lmp => 0131.lmp} | Bin .../fonts/defbigfont/{0081.lmp => 0131.lmp} | Bin .../fonts/defsmallfont/{0081.lmp => 0131.lmp} | Bin 9 files changed, 46 insertions(+), 12 deletions(-) create mode 100644 wadsrc_extra/static/filter/doom.id/fonts/bigupper/0131.lmp rename wadsrc_extra/static/filter/game-heretic/fonts/defbigfont/{0081.lmp => 0131.lmp} (100%) rename wadsrc_extra/static/filter/game-heretic/fonts/defsmallfont/{0081.lmp => 0131.lmp} (100%) rename wadsrc_extra/static/filter/game-hexen/fonts/defbigfont/{0081.lmp => 0131.lmp} (100%) rename wadsrc_extra/static/filter/game-hexen/fonts/defsmallfont/{0081.lmp => 0131.lmp} (100%) diff --git a/src/common/engine/i_interface.h b/src/common/engine/i_interface.h index 48cd2b95d5..bdc05198ed 100644 --- a/src/common/engine/i_interface.h +++ b/src/common/engine/i_interface.h @@ -62,6 +62,7 @@ extern FString endoomName; extern bool batchrun; extern float menuBlurAmount; extern bool generic_ui; +extern bool special_i; extern int paused; extern bool pauseext; diff --git a/src/common/fonts/font.cpp b/src/common/fonts/font.cpp index f78985b436..7028ee33d8 100644 --- a/src/common/fonts/font.cpp +++ b/src/common/fonts/font.cpp @@ -752,7 +752,23 @@ int FFont::GetCharCode(int code, bool needpic) const // regular chars turn negative when the 8th bit is set. code &= 255; } - if (code >= FirstChar && code <= LastChar && (!needpic || Chars[code - FirstChar].OriginalPic != nullptr)) + if (special_i && needpic) + { + // We need one special case for Turkish: If we have a lowercase-only font (like Raven's) and want to print the capital I, it must map to the dotless ı, because its own glyph will be the dotted i. + // This checks if the font has no small i, but does define the small dotless ı. + if (!MixedCase && code == 'I' && LastChar >= 0x131 && Chars['i' - FirstChar].OriginalPic == nullptr && Chars[0x131 - FirstChar].OriginalPic != nullptr) + { + return 0x131; + } + // a similar check is needed for the small i in allcaps fonts. Here we cannot simply remap to an existing character, so the small dotted i must be placed at code point 0080. + if (code == 'i' && LastChar >= 0x80 && Chars[0x80 - FirstChar].OriginalPic != nullptr) + { + return 0x131; + } + } + + + if (code >= FirstChar && code <= LastChar && Chars[code - FirstChar].OriginalPic != nullptr) { return code; } @@ -766,7 +782,7 @@ int FFont::GetCharCode(int code, bool needpic) const if (myislower(code)) { code = upperforlower[code]; - if (code >= FirstChar && code <= LastChar && (!needpic || Chars[code - FirstChar].OriginalPic != nullptr)) + if (code >= FirstChar && code <= LastChar && Chars[code - FirstChar].OriginalPic != nullptr) { return code; } @@ -775,7 +791,7 @@ int FFont::GetCharCode(int code, bool needpic) const while ((newcode = stripaccent(code)) != code) { code = newcode; - if (code >= FirstChar && code <= LastChar && (!needpic || Chars[code - FirstChar].OriginalPic != nullptr)) + if (code >= FirstChar && code <= LastChar && Chars[code - FirstChar].OriginalPic != nullptr) { return code; } @@ -789,7 +805,7 @@ int FFont::GetCharCode(int code, bool needpic) const while ((newcode = stripaccent(code)) != code) { code = newcode; - if (code >= FirstChar && code <= LastChar && (!needpic || Chars[code - FirstChar].OriginalPic != nullptr)) + if (code >= FirstChar && code <= LastChar && Chars[code - FirstChar].OriginalPic != nullptr) { return code; } @@ -800,14 +816,14 @@ int FFont::GetCharCode(int code, bool needpic) const { int upper = upperforlower[code]; // Stripping accents did not help - now try uppercase for lowercase - if (upper != code) return GetCharCode(upper, needpic); + if (upper != code) return GetCharCode(upper, true); } // Same for the uppercase character. Since we restart at the accented version this must go through the entire thing again. while ((newcode = stripaccent(code)) != code) { code = newcode; - if (code >= FirstChar && code <= LastChar && (!needpic || Chars[code - FirstChar].OriginalPic != nullptr)) + if (code >= FirstChar && code <= LastChar && Chars[code - FirstChar].OriginalPic != nullptr) { return code; } @@ -907,7 +923,7 @@ bool FFont::CanPrint(const uint8_t *string) const } else if (chr != '\n') { - int cc = GetCharCode(chr, true); + int cc = GetCharCode(chr, false); if (chr != cc && myiswalpha(chr) && cc != getAlternative(chr)) { return false; diff --git a/src/common/fonts/v_text.cpp b/src/common/fonts/v_text.cpp index b7467a8abd..164d9086de 100644 --- a/src/common/fonts/v_text.cpp +++ b/src/common/fonts/v_text.cpp @@ -265,6 +265,7 @@ DEFINE_ACTION_FUNCTION(FFont, BreakLines) bool generic_ui; +bool special_i; bool CheckFontComplete(FFont* font) { @@ -309,6 +310,19 @@ void UpdateGenericUI(bool cvar) AlternativeBigFont = NewSmallFont; } } + // Turkish i crap. What a mess, just to save two code points... :( + switchstr = GStrings["REQUIRED_CHARACTERS"]; + special_i = strstr(switchstr, "\xc4\xb0") != nullptr; // capital dotted i (İ). + if (special_i) + { + upperforlower['i'] = 0x130; + lowerforupper['I'] = 0x131; + } + else + { + upperforlower['i'] = 'I'; + lowerforupper['I'] = 'i'; + } } CUSTOM_CVAR(Bool, ui_generic, false, CVAR_NOINITCALL) // This is for allowing to test the generic font system with all languages diff --git a/src/common/utility/utf8.cpp b/src/common/utility/utf8.cpp index 5ca3506ef6..e5b52347b7 100644 --- a/src/common/utility/utf8.cpp +++ b/src/common/utility/utf8.cpp @@ -332,11 +332,11 @@ int stripaccent(int code) return accentless[code - 0x100]; } } - else if (code >= 0x200 && code < 0x218) + else if (code >= 0x1fc && code < 0x218) { // 0x200-0x217 are irrelevant but easy to map to other characters more likely to exist. - 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}; - return u200map[code - 0x200]; + static const uint16_t u200map[] = {0xc6, 0xe6, 0xd8, 0xf8, 0xc4, 0xe4, 0xc2, 0xe2, 0xcb, 0xeb, 0xca, 0xea, 0xcf, 0xef, 0xce, 0xee, 0xd6, 0xf6, 0xd4, 0xe4, 'R', 'r', 'R', 'r', 0xdc, 0xfc, 0xdb, 0xfb}; + return u200map[code - 0x1fc]; } return getAlternative(code); } @@ -527,7 +527,6 @@ static const uint16_t loweruppercase[] = { 0x012B,0x012A, 0x012D,0x012C, 0x012F,0x012E, -0x0131,0x0049, 0x0133,0x0132, 0x0135,0x0134, 0x0137,0x0136, @@ -1112,6 +1111,7 @@ static const uint16_t loweruppercase[] = { 0xFF58, 0xFF38, 0xFF59, 0xFF39, 0xFF5A, 0xFF3A, + 0, 0 }; @@ -1128,13 +1128,16 @@ struct InitLowerUpper { auto lower = loweruppercase[i]; auto upper = loweruppercase[i + 1]; - if (lowerforupper[upper] == upper) lowerforupper[upper] = lower; // This mapping is ambiguous (see 0x0131 -> 0x0049, (small Turkish 'i' without dot.) so only pick the first match. + if (lowerforupper[upper] == upper) lowerforupper[upper] = lower; // This mapping is ambiguous so only pick the first match. if (upperforlower[lower] == lower) upperforlower[lower] = upper; isuppermap[upper] = islowermap[lower] = true; } // Special treatment for the two variants of the small sigma in Greek. islowermap[0x3c2] = true; upperforlower[0x3c2] = 0x3a3; + // Turkish 'I's. + upperforlower[0x131] = 'I'; + lowerforupper[0x130] = 'i'; } }; diff --git a/wadsrc_extra/static/filter/doom.id/fonts/bigupper/0131.lmp b/wadsrc_extra/static/filter/doom.id/fonts/bigupper/0131.lmp new file mode 100644 index 0000000000000000000000000000000000000000..4a6c9ed19378e797f09f83f31c9ff1cdd959e05b GIT binary patch literal 134 zcmZQ$;9+23`1@Z0NE!mM6A%XjaS9NZ0x<(m77F+e5{QnEiI0zuiHS+f$^r`n$0sHx gCdEgG$HN4Ga`Ev=@o*I}Ngx$TiSaNk$fo`W0B;s61poj5 literal 0 HcmV?d00001 diff --git a/wadsrc_extra/static/filter/game-heretic/fonts/defbigfont/0081.lmp b/wadsrc_extra/static/filter/game-heretic/fonts/defbigfont/0131.lmp similarity index 100% rename from wadsrc_extra/static/filter/game-heretic/fonts/defbigfont/0081.lmp rename to wadsrc_extra/static/filter/game-heretic/fonts/defbigfont/0131.lmp diff --git a/wadsrc_extra/static/filter/game-heretic/fonts/defsmallfont/0081.lmp b/wadsrc_extra/static/filter/game-heretic/fonts/defsmallfont/0131.lmp similarity index 100% rename from wadsrc_extra/static/filter/game-heretic/fonts/defsmallfont/0081.lmp rename to wadsrc_extra/static/filter/game-heretic/fonts/defsmallfont/0131.lmp diff --git a/wadsrc_extra/static/filter/game-hexen/fonts/defbigfont/0081.lmp b/wadsrc_extra/static/filter/game-hexen/fonts/defbigfont/0131.lmp similarity index 100% rename from wadsrc_extra/static/filter/game-hexen/fonts/defbigfont/0081.lmp rename to wadsrc_extra/static/filter/game-hexen/fonts/defbigfont/0131.lmp diff --git a/wadsrc_extra/static/filter/game-hexen/fonts/defsmallfont/0081.lmp b/wadsrc_extra/static/filter/game-hexen/fonts/defsmallfont/0131.lmp similarity index 100% rename from wadsrc_extra/static/filter/game-hexen/fonts/defsmallfont/0081.lmp rename to wadsrc_extra/static/filter/game-hexen/fonts/defsmallfont/0131.lmp