diff --git a/Assets/Cryville/Common/Font/FontManager.cs b/Assets/Cryville/Common/Font/FontManager.cs index b43512f..c302f1d 100644 --- a/Assets/Cryville/Common/Font/FontManager.cs +++ b/Assets/Cryville/Common/Font/FontManager.cs @@ -1,6 +1,4 @@ -using Cryville.Common.Culture; -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; using System.Linq; @@ -20,15 +18,13 @@ namespace Cryville.Common.Font { List set2; if (!map2.TryGetValue(f.FamilyName, out set2)) { map2.Add(f.FamilyName, set2 = new List()); - } + } set2.Add(f); } MapFullNameToTypeface = map1.ToDictionary(i => i.Key, i => (IReadOnlyCollection)i.Value); MapNameToTypefaces = map2.ToDictionary(i => i.Key, i => (IReadOnlyCollection)i.Value); } protected abstract IEnumerable EnumerateAllTypefaces(); - public abstract IEnumerable MatchScript(string script = null); - public abstract IEnumerable MatchFamily(string[] candidates); protected static IEnumerable ScanDirectoryForTypefaces(string dir) { foreach (var f in new DirectoryInfo(dir).EnumerateFiles()) { FontFile file; @@ -58,195 +54,10 @@ namespace Cryville.Common.Font { protected override IEnumerable EnumerateAllTypefaces() { return ScanDirectoryForTypefaces("/system/fonts"); } - - public override IEnumerable MatchScript(string script = null) { - throw new NotImplementedException(); - } - - public override IEnumerable MatchFamily(string[] candidates) { - throw new NotImplementedException(); - } } public class FontManagerWindows : FontManager { - public static Dictionary> MapScriptToTypefaces = new Dictionary>(); - - static FontManagerWindows() { - if (Environment.OSVersion.Platform != PlatformID.Win32NT) return; - ScriptUtils.FillKeysWithScripts(MapScriptToTypefaces, () => new List()); - // Reference: https://github.com/chromium/chromium/blob/main/third_party/blink/renderer/platform/fonts/win/font_fallback_win.cc - MapScriptToTypefaces["zyyy"].Insert(0, "SimSun"); // Custom - MapScriptToTypefaces["zyyy"].Insert(0, "SimHei"); // Custom - MapScriptToTypefaces["zyyy"].Insert(0, "Arial"); - MapScriptToTypefaces["zyyy"].Insert(0, "Times New Roman"); - MapScriptToTypefaces["zyyy"].Insert(0, "Segoe UI"); // Custom - MapScriptToTypefaces["arab"].Insert(0, "Tahoma"); - MapScriptToTypefaces["cyrl"].Insert(0, "Times New Roman"); - MapScriptToTypefaces["grek"].Insert(0, "Times New Roman"); - MapScriptToTypefaces["hebr"].Insert(0, "David"); - MapScriptToTypefaces["jpan"].Insert(0, "MS PGothic"); - MapScriptToTypefaces["latn"].Insert(0, "Times New Roman"); - MapScriptToTypefaces["hans"].Insert(0, "SimSun"); - MapScriptToTypefaces["hans"].Insert(0, "SimHei"); // Custom - MapScriptToTypefaces["thai"].Insert(0, "Tahoma"); - MapScriptToTypefaces["hans"].Insert(0, "PMingLiU"); - // Reference: https://learn.microsoft.com/en-us/globalization/input/font-support - var ver = Environment.OSVersion.Version; - if (ver >= new Version(5, 0)) { // Windows 2000 - MapScriptToTypefaces["armn"].Insert(0, "Sylfaen"); - MapScriptToTypefaces["deva"].Insert(0, "Mangal"); - MapScriptToTypefaces["geor"].Insert(0, "Sylfaen"); - MapScriptToTypefaces["taml"].Insert(0, "Latha"); - } - if (ver >= new Version(5, 1)) { // Windows XP - MapScriptToTypefaces["gujr"].Insert(0, "Shruti"); - MapScriptToTypefaces["guru"].Insert(0, "Raavi"); - MapScriptToTypefaces["knda"].Insert(0, "Tunga"); - MapScriptToTypefaces["syrc"].Insert(0, "Estrangelo Edessa"); - MapScriptToTypefaces["telu"].Insert(0, "Gautami"); - MapScriptToTypefaces["thaa"].Insert(0, "MV Boli"); - // SP2 - MapScriptToTypefaces["beng"].Insert(0, "Vrinda"); - MapScriptToTypefaces["mlym"].Insert(0, "Kartika"); - } - if (ver >= new Version(6, 0)) { // Windows Vista - MapScriptToTypefaces["cans"].Insert(0, "Euphemia"); - MapScriptToTypefaces["cher"].Insert(0, "Plantagenet"); - MapScriptToTypefaces["ethi"].Insert(0, "Nyala"); - MapScriptToTypefaces["khmr"].Insert(0, "DaunPenh MoolBoran"); - MapScriptToTypefaces["laoo"].Insert(0, "DokChampa"); - MapScriptToTypefaces["mong"].Insert(0, "Mongolian Baiti"); - MapScriptToTypefaces["orya"].Insert(0, "Kalinga"); - MapScriptToTypefaces["sinh"].Insert(0, "Iskoola Pota"); - MapScriptToTypefaces["tibt"].Insert(0, "Microsoft Himalaya"); - MapScriptToTypefaces["yiii"].Insert(0, "Microsoft Yi Baiti"); - MapScriptToTypefaces["arab"].Insert(0, "Segoe UI"); - MapScriptToTypefaces["cyrl"].Insert(0, "Segoe UI"); - MapScriptToTypefaces["grek"].Insert(0, "Segoe UI"); - MapScriptToTypefaces["latn"].Insert(0, "Segoe UI"); - MapScriptToTypefaces["hans"].Add("SimSun-ExtB"); - MapScriptToTypefaces["hant"].Add("MingLiU-ExtB"); - MapScriptToTypefaces["hant"].Add("MingLiU_HKSCS-ExtB"); - MapScriptToTypefaces["arab"].Add("Microsoft Uighur"); - MapScriptToTypefaces["zmth"].Insert(0, "Cambria Math"); - // Reference: https://en.wikipedia.org/wiki/List_of_CJK_fonts - MapScriptToTypefaces["jpan"].Insert(0, "Meiryo"); - MapScriptToTypefaces["hans"].Insert(0, "Microsoft YaHei"); - } - if (ver >= new Version(6, 1)) { // Windows 7 - MapScriptToTypefaces["brai"].Insert(0, "Segoe UI Symbol"); - MapScriptToTypefaces["dsrt"].Insert(0, "Segoe UI Symbol"); - MapScriptToTypefaces["talu"].Insert(0, "Microsoft New Tai Lue"); - MapScriptToTypefaces["ogam"].Insert(0, "Segoe UI Symbol"); - MapScriptToTypefaces["osma"].Insert(0, "Ebrima"); - MapScriptToTypefaces["phag"].Insert(0, "Microsoft PhagsPa"); - MapScriptToTypefaces["runr"].Insert(0, "Segoe UI Symbol"); - MapScriptToTypefaces["zsym"].Insert(0, "Segoe UI Symbol"); - MapScriptToTypefaces["tale"].Insert(0, "Microsoft Tai Le"); - MapScriptToTypefaces["tfng"].Insert(0, "Ebrima"); - MapScriptToTypefaces["vaii"].Insert(0, "Ebrima"); - } - if (ver >= new Version(6, 2)) { // Windows 8 - MapScriptToTypefaces["glag"].Insert(0, "Segoe UI Symbol"); - MapScriptToTypefaces["goth"].Insert(0, "Segoe UI Symbol"); - MapScriptToTypefaces["hang"].Add("Malgun Gothic"); - MapScriptToTypefaces["ital"].Insert(0, "Segoe UI Symbol"); - MapScriptToTypefaces["lisu"].Insert(0, "Segoe UI"); - MapScriptToTypefaces["mymr"].Insert(0, "Myanmar Text"); - MapScriptToTypefaces["nkoo"].Insert(0, "Ebrima"); - MapScriptToTypefaces["orkh"].Insert(0, "Segoe UI Symbol"); - MapScriptToTypefaces["ethi"].Insert(0, "Ebrima"); - MapScriptToTypefaces["cans"].Insert(0, "Gadugi"); - MapScriptToTypefaces["hant"].Insert(0, "Microsoft JhengHei UI"); - MapScriptToTypefaces["hans"].Insert(0, "Microsoft YaHei UI"); - MapScriptToTypefaces["beng"].Insert(0, "Nirmala UI"); - MapScriptToTypefaces["deva"].Insert(0, "Nirmala UI"); - MapScriptToTypefaces["gujr"].Insert(0, "Nirmala UI"); - MapScriptToTypefaces["guru"].Insert(0, "Nirmala UI"); // NOT DOCUMENTED, UNVERIFIED - MapScriptToTypefaces["knda"].Insert(0, "Nirmala UI"); // NOT DOCUMENTED, UNVERIFIED - MapScriptToTypefaces["mlym"].Insert(0, "Nirmala UI"); - MapScriptToTypefaces["orya"].Insert(0, "Nirmala UI"); - MapScriptToTypefaces["sinh"].Insert(0, "Nirmala UI"); // NOT DOCUMENTED, UNVERIFIED - MapScriptToTypefaces["taml"].Insert(0, "Nirmala UI"); // NOT DOCUMENTED, UNVERIFIED - MapScriptToTypefaces["telu"].Insert(0, "Nirmala UI"); - MapScriptToTypefaces["armn"].Insert(0, "Segoe UI"); - MapScriptToTypefaces["geor"].Insert(0, "Segoe UI"); - MapScriptToTypefaces["hebr"].Insert(0, "Segoe UI"); - } - if (ver >= new Version(6, 3)) { // Windows 8.1 - MapScriptToTypefaces["bugi"].Insert(0, "Leelawadee UI"); - MapScriptToTypefaces["copt"].Insert(0, "Segoe UI Symbol"); - MapScriptToTypefaces["java"].Insert(0, "Javanese Text"); - MapScriptToTypefaces["merc"].Insert(0, "Segoe UI Symbol"); - MapScriptToTypefaces["olck"].Insert(0, "Nirmala UI"); - MapScriptToTypefaces["sora"].Insert(0, "Nirmala UI"); - MapScriptToTypefaces["khmr"].Insert(0, "Leelawadee UI"); - MapScriptToTypefaces["laoo"].Insert(0, "Leelawadee UI"); - MapScriptToTypefaces["thai"].Insert(0, "Leelawadee UI"); - MapScriptToTypefaces["zsye"].Insert(0, "Segoe UI Emoji"); - } - if (ver >= new Version(10, 0)) { // Windows 10 - MapScriptToTypefaces["brah"].Insert(0, "Segoe UI Historic"); - MapScriptToTypefaces["cari"].Insert(0, "Segoe UI Historic"); - MapScriptToTypefaces["cprt"].Insert(0, "Segoe UI Historic"); - MapScriptToTypefaces["egyp"].Insert(0, "Segoe UI Historic"); - MapScriptToTypefaces["armi"].Insert(0, "Segoe UI Historic"); - MapScriptToTypefaces["phli"].Insert(0, "Segoe UI Historic"); - MapScriptToTypefaces["prti"].Insert(0, "Segoe UI Historic"); - MapScriptToTypefaces["khar"].Insert(0, "Segoe UI Historic"); - MapScriptToTypefaces["lyci"].Insert(0, "Segoe UI Historic"); - MapScriptToTypefaces["lydi"].Insert(0, "Segoe UI Historic"); - MapScriptToTypefaces["phnx"].Insert(0, "Segoe UI Historic"); - MapScriptToTypefaces["xpeo"].Insert(0, "Segoe UI Historic"); - MapScriptToTypefaces["sarb"].Insert(0, "Segoe UI Historic"); - MapScriptToTypefaces["shaw"].Insert(0, "Segoe UI Historic"); - MapScriptToTypefaces["xsux"].Insert(0, "Segoe UI Historic"); - MapScriptToTypefaces["ugar"].Insert(0, "Segoe UI Historic"); - // Segoe UI Symbol -> Segoe UI Historic - MapScriptToTypefaces["glag"].Insert(0, "Segoe UI Historic"); - MapScriptToTypefaces["goth"].Insert(0, "Segoe UI Historic"); - MapScriptToTypefaces["merc"].Insert(0, "Segoe UI Historic"); - MapScriptToTypefaces["ogam"].Insert(0, "Segoe UI Historic"); - MapScriptToTypefaces["ital"].Insert(0, "Segoe UI Historic"); - MapScriptToTypefaces["orkh"].Insert(0, "Segoe UI Historic"); - MapScriptToTypefaces["runr"].Insert(0, "Segoe UI Historic"); - // - MapScriptToTypefaces["jpan"].Insert(0, "Yu Gothic UI"); - MapScriptToTypefaces["zsym"].Add("Segoe MDL2 Assets"); - } - } - protected override IEnumerable EnumerateAllTypefaces() { return ScanDirectoryForTypefaces("C:/Windows/Fonts"); } - - public override IEnumerable MatchScript(string script = null) { - if (string.IsNullOrEmpty(script)) script = ScriptUtils.UltimateFallbackScript; - List candidates; - IEnumerable candidateScripts = new string[] { script }; - while (candidateScripts != null) { - foreach (var candidateScript in candidateScripts) { - if (MapScriptToTypefaces.TryGetValue(candidateScript, out candidates)) { - foreach (var candidate in candidates) { - Typeface typeface; - if (MapFullNameToTypeface.TryGetValue(candidate, out typeface)) { - yield return typeface; - } - IReadOnlyCollection typefaces; - if (MapNameToTypefaces.TryGetValue(candidate, out typefaces)) { - foreach (var typeface2 in typefaces) { - if (typeface2 == typeface) continue; - yield return typeface2; - } - } - } - } - } - candidateScripts = ScriptUtils.EnumerateFallbackScripts(script); - } - } - - public override IEnumerable MatchFamily(string[] candidates) { - throw new NotImplementedException(); - } } } diff --git a/Assets/Cryville/Common/Font/FontMatcher.cs b/Assets/Cryville/Common/Font/FontMatcher.cs new file mode 100644 index 0000000..3c7374e --- /dev/null +++ b/Assets/Cryville/Common/Font/FontMatcher.cs @@ -0,0 +1,329 @@ +using Cryville.Common.Culture; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Cryville.Common.Font { + public abstract class FontMatcher { + protected FontManager Manager { get; private set; } + public FontMatcher(FontManager manafer) { Manager = manafer; } + public abstract IEnumerable MatchScript(string script = null, bool distinctFamily = false); + } + public class FallbackListFontMatcher : FontMatcher { + public Dictionary> MapScriptToTypefaces = new Dictionary>(); + public void LoadDefaultWindowsFallbackList() { + if (Environment.OSVersion.Platform != PlatformID.Win32NT) return; + MapScriptToTypefaces.Clear(); + ScriptUtils.FillKeysWithScripts(MapScriptToTypefaces, () => new List()); + // Reference: https://github.com/chromium/chromium/blob/main/third_party/blink/renderer/platform/fonts/win/font_fallback_win.cc + MapScriptToTypefaces["zyyy"].Insert(0, "SimSun"); // Custom + MapScriptToTypefaces["zyyy"].Insert(0, "SimHei"); // Custom + MapScriptToTypefaces["zyyy"].Insert(0, "Microsoft YaHei"); // Custom + MapScriptToTypefaces["zyyy"].Insert(0, "Arial"); + MapScriptToTypefaces["zyyy"].Insert(0, "Times New Roman"); + MapScriptToTypefaces["zyyy"].Insert(0, "Segoe UI"); // Custom + MapScriptToTypefaces["arab"].Insert(0, "Tahoma"); + MapScriptToTypefaces["cyrl"].Insert(0, "Times New Roman"); + MapScriptToTypefaces["grek"].Insert(0, "Times New Roman"); + MapScriptToTypefaces["hebr"].Insert(0, "David"); + MapScriptToTypefaces["jpan"].Insert(0, "MS PGothic"); + MapScriptToTypefaces["latn"].Insert(0, "Times New Roman"); + MapScriptToTypefaces["hans"].Insert(0, "SimSun"); + MapScriptToTypefaces["hans"].Insert(0, "SimHei"); // Custom + MapScriptToTypefaces["thai"].Insert(0, "Tahoma"); + MapScriptToTypefaces["hans"].Insert(0, "PMingLiU"); + // Reference: https://learn.microsoft.com/en-us/globalization/input/font-support + var ver = Environment.OSVersion.Version; + if (ver >= new Version(5, 0)) { // Windows 2000 + MapScriptToTypefaces["armn"].Insert(0, "Sylfaen"); + MapScriptToTypefaces["deva"].Insert(0, "Mangal"); + MapScriptToTypefaces["geor"].Insert(0, "Sylfaen"); + MapScriptToTypefaces["taml"].Insert(0, "Latha"); + } + if (ver >= new Version(5, 1)) { // Windows XP + MapScriptToTypefaces["gujr"].Insert(0, "Shruti"); + MapScriptToTypefaces["guru"].Insert(0, "Raavi"); + MapScriptToTypefaces["knda"].Insert(0, "Tunga"); + MapScriptToTypefaces["syrc"].Insert(0, "Estrangelo Edessa"); + MapScriptToTypefaces["telu"].Insert(0, "Gautami"); + MapScriptToTypefaces["thaa"].Insert(0, "MV Boli"); + // SP2 + MapScriptToTypefaces["beng"].Insert(0, "Vrinda"); + MapScriptToTypefaces["mlym"].Insert(0, "Kartika"); + } + if (ver >= new Version(6, 0)) { // Windows Vista + MapScriptToTypefaces["cans"].Insert(0, "Euphemia"); + MapScriptToTypefaces["cher"].Insert(0, "Plantagenet"); + MapScriptToTypefaces["ethi"].Insert(0, "Nyala"); + MapScriptToTypefaces["khmr"].Insert(0, "DaunPenh MoolBoran"); + MapScriptToTypefaces["laoo"].Insert(0, "DokChampa"); + MapScriptToTypefaces["mong"].Insert(0, "Mongolian Baiti"); + MapScriptToTypefaces["orya"].Insert(0, "Kalinga"); + MapScriptToTypefaces["sinh"].Insert(0, "Iskoola Pota"); + MapScriptToTypefaces["tibt"].Insert(0, "Microsoft Himalaya"); + MapScriptToTypefaces["yiii"].Insert(0, "Microsoft Yi Baiti"); + MapScriptToTypefaces["arab"].Insert(0, "Segoe UI"); + MapScriptToTypefaces["cyrl"].Insert(0, "Segoe UI"); + MapScriptToTypefaces["grek"].Insert(0, "Segoe UI"); + MapScriptToTypefaces["latn"].Insert(0, "Segoe UI"); + MapScriptToTypefaces["hans"].Add("SimSun-ExtB"); + MapScriptToTypefaces["hant"].Add("MingLiU-ExtB"); + MapScriptToTypefaces["hant"].Add("MingLiU_HKSCS-ExtB"); + MapScriptToTypefaces["arab"].Add("Microsoft Uighur"); + MapScriptToTypefaces["zmth"].Insert(0, "Cambria Math"); + // Reference: https://en.wikipedia.org/wiki/List_of_CJK_fonts + MapScriptToTypefaces["jpan"].Insert(0, "Meiryo"); + MapScriptToTypefaces["hans"].Insert(0, "Microsoft YaHei"); + } + if (ver >= new Version(6, 1)) { // Windows 7 + MapScriptToTypefaces["brai"].Insert(0, "Segoe UI Symbol"); + MapScriptToTypefaces["dsrt"].Insert(0, "Segoe UI Symbol"); + MapScriptToTypefaces["talu"].Insert(0, "Microsoft New Tai Lue"); + MapScriptToTypefaces["ogam"].Insert(0, "Segoe UI Symbol"); + MapScriptToTypefaces["osma"].Insert(0, "Ebrima"); + MapScriptToTypefaces["phag"].Insert(0, "Microsoft PhagsPa"); + MapScriptToTypefaces["runr"].Insert(0, "Segoe UI Symbol"); + MapScriptToTypefaces["zsym"].Insert(0, "Segoe UI Symbol"); + MapScriptToTypefaces["tale"].Insert(0, "Microsoft Tai Le"); + MapScriptToTypefaces["tfng"].Insert(0, "Ebrima"); + MapScriptToTypefaces["vaii"].Insert(0, "Ebrima"); + } + if (ver >= new Version(6, 2)) { // Windows 8 + MapScriptToTypefaces["glag"].Insert(0, "Segoe UI Symbol"); + MapScriptToTypefaces["goth"].Insert(0, "Segoe UI Symbol"); + MapScriptToTypefaces["hang"].Add("Malgun Gothic"); + MapScriptToTypefaces["ital"].Insert(0, "Segoe UI Symbol"); + MapScriptToTypefaces["lisu"].Insert(0, "Segoe UI"); + MapScriptToTypefaces["mymr"].Insert(0, "Myanmar Text"); + MapScriptToTypefaces["nkoo"].Insert(0, "Ebrima"); + MapScriptToTypefaces["orkh"].Insert(0, "Segoe UI Symbol"); + MapScriptToTypefaces["ethi"].Insert(0, "Ebrima"); + MapScriptToTypefaces["cans"].Insert(0, "Gadugi"); + MapScriptToTypefaces["hant"].Insert(0, "Microsoft JhengHei UI"); + MapScriptToTypefaces["hans"].Insert(0, "Microsoft YaHei UI"); + MapScriptToTypefaces["beng"].Insert(0, "Nirmala UI"); + MapScriptToTypefaces["deva"].Insert(0, "Nirmala UI"); + MapScriptToTypefaces["gujr"].Insert(0, "Nirmala UI"); + MapScriptToTypefaces["guru"].Insert(0, "Nirmala UI"); // NOT DOCUMENTED, UNVERIFIED + MapScriptToTypefaces["knda"].Insert(0, "Nirmala UI"); // NOT DOCUMENTED, UNVERIFIED + MapScriptToTypefaces["mlym"].Insert(0, "Nirmala UI"); + MapScriptToTypefaces["orya"].Insert(0, "Nirmala UI"); + MapScriptToTypefaces["sinh"].Insert(0, "Nirmala UI"); // NOT DOCUMENTED, UNVERIFIED + MapScriptToTypefaces["taml"].Insert(0, "Nirmala UI"); // NOT DOCUMENTED, UNVERIFIED + MapScriptToTypefaces["telu"].Insert(0, "Nirmala UI"); + MapScriptToTypefaces["armn"].Insert(0, "Segoe UI"); + MapScriptToTypefaces["geor"].Insert(0, "Segoe UI"); + MapScriptToTypefaces["hebr"].Insert(0, "Segoe UI"); + } + if (ver >= new Version(6, 3)) { // Windows 8.1 + MapScriptToTypefaces["bugi"].Insert(0, "Leelawadee UI"); + MapScriptToTypefaces["copt"].Insert(0, "Segoe UI Symbol"); + MapScriptToTypefaces["java"].Insert(0, "Javanese Text"); + MapScriptToTypefaces["merc"].Insert(0, "Segoe UI Symbol"); + MapScriptToTypefaces["olck"].Insert(0, "Nirmala UI"); + MapScriptToTypefaces["sora"].Insert(0, "Nirmala UI"); + MapScriptToTypefaces["khmr"].Insert(0, "Leelawadee UI"); + MapScriptToTypefaces["laoo"].Insert(0, "Leelawadee UI"); + MapScriptToTypefaces["thai"].Insert(0, "Leelawadee UI"); + MapScriptToTypefaces["zsye"].Insert(0, "Segoe UI Emoji"); + } + if (ver >= new Version(10, 0)) { // Windows 10 + MapScriptToTypefaces["brah"].Insert(0, "Segoe UI Historic"); + MapScriptToTypefaces["cari"].Insert(0, "Segoe UI Historic"); + MapScriptToTypefaces["cprt"].Insert(0, "Segoe UI Historic"); + MapScriptToTypefaces["egyp"].Insert(0, "Segoe UI Historic"); + MapScriptToTypefaces["armi"].Insert(0, "Segoe UI Historic"); + MapScriptToTypefaces["phli"].Insert(0, "Segoe UI Historic"); + MapScriptToTypefaces["prti"].Insert(0, "Segoe UI Historic"); + MapScriptToTypefaces["khar"].Insert(0, "Segoe UI Historic"); + MapScriptToTypefaces["lyci"].Insert(0, "Segoe UI Historic"); + MapScriptToTypefaces["lydi"].Insert(0, "Segoe UI Historic"); + MapScriptToTypefaces["phnx"].Insert(0, "Segoe UI Historic"); + MapScriptToTypefaces["xpeo"].Insert(0, "Segoe UI Historic"); + MapScriptToTypefaces["sarb"].Insert(0, "Segoe UI Historic"); + MapScriptToTypefaces["shaw"].Insert(0, "Segoe UI Historic"); + MapScriptToTypefaces["xsux"].Insert(0, "Segoe UI Historic"); + MapScriptToTypefaces["ugar"].Insert(0, "Segoe UI Historic"); + // Segoe UI Symbol -> Segoe UI Historic + MapScriptToTypefaces["glag"].Insert(0, "Segoe UI Historic"); + MapScriptToTypefaces["goth"].Insert(0, "Segoe UI Historic"); + MapScriptToTypefaces["merc"].Insert(0, "Segoe UI Historic"); + MapScriptToTypefaces["ogam"].Insert(0, "Segoe UI Historic"); + MapScriptToTypefaces["ital"].Insert(0, "Segoe UI Historic"); + MapScriptToTypefaces["orkh"].Insert(0, "Segoe UI Historic"); + MapScriptToTypefaces["runr"].Insert(0, "Segoe UI Historic"); + // + MapScriptToTypefaces["jpan"].Insert(0, "Yu Gothic UI"); + MapScriptToTypefaces["zsym"].Add("Segoe MDL2 Assets"); + } + } + public void LoadDefaultAndroidFallbackList() { + if (Environment.OSVersion.Platform != PlatformID.Unix) return; + MapScriptToTypefaces.Clear(); + ScriptUtils.FillKeysWithScripts(MapScriptToTypefaces, () => new List()); + MapScriptToTypefaces["zyyy"].Insert(0, "Noto Sans CJK TC"); // TODO Modify default fallback + MapScriptToTypefaces["zyyy"].Insert(0, "Noto Sans CJK JP"); + MapScriptToTypefaces["zyyy"].Insert(0, "Noto Sans CJK SC"); + MapScriptToTypefaces["zyyy"].Insert(0, "Roboto"); + MapScriptToTypefaces["zsye"].Insert(0, "Noto Color Emoji"); + MapScriptToTypefaces["zsye"].Add("Noto Color Emoji Flags"); + MapScriptToTypefaces["arab"].Insert(0, "Noto Naskh Arabic"); + MapScriptToTypefaces["adlm"].Insert(0, "Noto Sans Adlam"); + MapScriptToTypefaces["ahom"].Insert(0, "Noto Sans Ahom"); + MapScriptToTypefaces["hluw"].Insert(0, "Noto Sans Anatolian Hieroglyphs"); + MapScriptToTypefaces["armn"].Insert(0, "Noto Sans Armenian"); + MapScriptToTypefaces["avst"].Insert(0, "Noto Sans Avestan"); + MapScriptToTypefaces["bali"].Insert(0, "Noto Sans Balinese"); + MapScriptToTypefaces["bamu"].Insert(0, "Noto Sans Bamum"); + MapScriptToTypefaces["bass"].Insert(0, "Noto Sans Bassa Vah"); + MapScriptToTypefaces["batk"].Insert(0, "Noto Sans Batak"); + MapScriptToTypefaces["beng"].Insert(0, "Noto Sans Bengali"); + MapScriptToTypefaces["bhks"].Insert(0, "Noto Sans Bhaiksuki"); + MapScriptToTypefaces["brah"].Insert(0, "Noto Sans Brahmi"); + MapScriptToTypefaces["bugi"].Insert(0, "Noto Sans Buginese"); + MapScriptToTypefaces["buhd"].Insert(0, "Noto Sans Buhid"); + MapScriptToTypefaces["jpan"].Insert(0, "Noto Sans CJK JP"); + MapScriptToTypefaces["kore"].Insert(0, "Noto Sans CJK KR"); + MapScriptToTypefaces["hans"].Insert(0, "Noto Sans CJK SC"); + MapScriptToTypefaces["hant"].Insert(0, "Noto Sans CJK TC"); + MapScriptToTypefaces["hant"].Add("Noto Sans CJK HK"); + MapScriptToTypefaces["cans"].Insert(0, "Noto Sans Canadian Aboriginal"); + MapScriptToTypefaces["cari"].Insert(0, "Noto Sans Carian"); + MapScriptToTypefaces["cakm"].Insert(0, "Noto Sans Chakma"); + MapScriptToTypefaces["cham"].Insert(0, "Noto Sans Cham"); + MapScriptToTypefaces["cher"].Insert(0, "Noto Sans Cherokee"); + MapScriptToTypefaces["copt"].Insert(0, "Noto Sans Coptic"); + MapScriptToTypefaces["xsux"].Insert(0, "Noto Sans Cuneiform"); + MapScriptToTypefaces["cprt"].Insert(0, "Noto Sans Cypriot"); + MapScriptToTypefaces["dsrt"].Insert(0, "Noto Sans Deseret"); + MapScriptToTypefaces["deva"].Insert(0, "Noto Sans Devanagari"); + MapScriptToTypefaces["egyp"].Insert(0, "Noto Sans Egyptian Hieroglyphs"); + MapScriptToTypefaces["elba"].Insert(0, "Noto Sans Elbasan"); + MapScriptToTypefaces["ethi"].Insert(0, "Noto Sans Ethiopic"); + MapScriptToTypefaces["geor"].Insert(0, "Noto Sans Georgian"); + MapScriptToTypefaces["glag"].Insert(0, "Noto Sans Glagolitic"); + MapScriptToTypefaces["goth"].Insert(0, "Noto Sans Gothic"); + MapScriptToTypefaces["gran"].Insert(0, "Noto Sans Grantha"); + MapScriptToTypefaces["gujr"].Insert(0, "Noto Sans Gujarati"); + MapScriptToTypefaces["gong"].Insert(0, "Noto Sans Gunjala Gondi"); + MapScriptToTypefaces["guru"].Insert(0, "Noto Sans Gurmukhi"); + MapScriptToTypefaces["rohg"].Insert(0, "Noto Sans Hanifi Rohingya"); + MapScriptToTypefaces["hano"].Insert(0, "Noto Sans Hanunoo"); + MapScriptToTypefaces["hatr"].Insert(0, "Noto Sans Hatran"); + MapScriptToTypefaces["hebr"].Insert(0, "Noto Sans Hebrew"); + MapScriptToTypefaces["armi"].Insert(0, "Noto Sans Imperial Aramaic"); + MapScriptToTypefaces["phli"].Insert(0, "Noto Sans Inscriptional Pahlavi"); + MapScriptToTypefaces["prti"].Insert(0, "Noto Sans Inscriptional Parthian"); + MapScriptToTypefaces["java"].Insert(0, "Noto Sans Javanese"); + MapScriptToTypefaces["kthi"].Insert(0, "Noto Sans Kaithi"); + MapScriptToTypefaces["knda"].Insert(0, "Noto Sans Kannada"); + MapScriptToTypefaces["kali"].Insert(0, "Noto Sans KayahLi"); + MapScriptToTypefaces["khar"].Insert(0, "Noto Sans Kharoshthi"); + MapScriptToTypefaces["khmr"].Insert(0, "Noto Sans Khmer"); + MapScriptToTypefaces["khoj"].Insert(0, "Noto Sans Khojki"); + MapScriptToTypefaces["laoo"].Insert(0, "Noto Sans Lao"); + MapScriptToTypefaces["lepc"].Insert(0, "Noto Sans Lepcha"); + MapScriptToTypefaces["limb"].Insert(0, "Noto Sans Limbu"); + MapScriptToTypefaces["lina"].Insert(0, "Noto Sans Linear A"); + MapScriptToTypefaces["linb"].Insert(0, "Noto Sans Linear B"); + MapScriptToTypefaces["lisu"].Insert(0, "Noto Sans Lisu"); + MapScriptToTypefaces["lyci"].Insert(0, "Noto Sans Lycian"); + MapScriptToTypefaces["lydi"].Insert(0, "Noto Sans Lydian"); + MapScriptToTypefaces["mlym"].Insert(0, "Noto Sans Malayalam"); + MapScriptToTypefaces["mand"].Insert(0, "Noto Sans Mandiac"); + MapScriptToTypefaces["mani"].Insert(0, "Noto Sans Manichaean"); + MapScriptToTypefaces["marc"].Insert(0, "Noto Sans Marchen"); + MapScriptToTypefaces["gonm"].Insert(0, "Noto Sans Masaram Gondi"); + MapScriptToTypefaces["medf"].Insert(0, "Noto Sans Medefaidrin"); + MapScriptToTypefaces["mtei"].Insert(0, "Noto Sans Meetei Mayek"); + MapScriptToTypefaces["merc"].Insert(0, "Noto Sans Meroitic"); + MapScriptToTypefaces["mero"].Insert(0, "Noto Sans Meroitic"); + MapScriptToTypefaces["plrd"].Insert(0, "Noto Sans Miao"); + MapScriptToTypefaces["modi"].Insert(0, "Noto Sans Modi"); + MapScriptToTypefaces["mong"].Insert(0, "Noto Sans Mongolian"); + MapScriptToTypefaces["mroo"].Insert(0, "Noto Sans Mro"); + MapScriptToTypefaces["mult"].Insert(0, "Noto Sans Multani"); + MapScriptToTypefaces["mymr"].Insert(0, "Noto Sans Myanmar"); + MapScriptToTypefaces["nkoo"].Insert(0, "Noto Sans Nko"); + MapScriptToTypefaces["nbat"].Insert(0, "Noto Sans Nabataean"); + MapScriptToTypefaces["talu"].Insert(0, "Noto Sans New Tai Lue"); + MapScriptToTypefaces["newa"].Insert(0, "Noto Sans Newa"); + MapScriptToTypefaces["ogam"].Insert(0, "Noto Sans Ogham"); + MapScriptToTypefaces["olck"].Insert(0, "Noto Sans Ol Chiki"); + MapScriptToTypefaces["ital"].Insert(0, "Noto Sans Old Italian"); + MapScriptToTypefaces["narb"].Insert(0, "Noto Sans Old North Arabian"); + MapScriptToTypefaces["perm"].Insert(0, "Noto Sans Old Permic"); + MapScriptToTypefaces["xpeo"].Insert(0, "Noto Sans Old Persian"); + MapScriptToTypefaces["sarb"].Insert(0, "Noto Sans Old South Arabian"); + MapScriptToTypefaces["orkh"].Insert(0, "Noto Sans Old Turkic"); + MapScriptToTypefaces["orya"].Insert(0, "Noto Sans Oriya"); + MapScriptToTypefaces["osge"].Insert(0, "Noto Sans Osage"); + MapScriptToTypefaces["osma"].Insert(0, "Noto Sans Osmanya"); + MapScriptToTypefaces["hmng"].Insert(0, "Noto Sans Pahawh Hmong"); + MapScriptToTypefaces["palm"].Insert(0, "Noto Sans Palmyrene"); + MapScriptToTypefaces["pauc"].Insert(0, "Noto Sans Pau Cin Hau"); + MapScriptToTypefaces["phag"].Insert(0, "Noto Sans Phags Pa"); + MapScriptToTypefaces["phnx"].Insert(0, "Noto Sans Phoenician"); + MapScriptToTypefaces["rjng"].Insert(0, "Noto Sans Rejang"); + MapScriptToTypefaces["runr"].Insert(0, "Noto Sans Runic"); + MapScriptToTypefaces["samr"].Insert(0, "Noto Sans Samaritan"); + MapScriptToTypefaces["saur"].Insert(0, "Noto Sans Saurashtra"); + MapScriptToTypefaces["shrd"].Insert(0, "Noto Sans Sharada"); + MapScriptToTypefaces["shaw"].Insert(0, "Noto Sans Shavian"); + MapScriptToTypefaces["sinh"].Insert(0, "Noto Sans Sinhala"); + MapScriptToTypefaces["sora"].Insert(0, "Noto Sans Sora Sompeng"); + MapScriptToTypefaces["soyo"].Insert(0, "Noto Sans Soyombo"); + MapScriptToTypefaces["sund"].Insert(0, "Noto Sans Sundanese"); + MapScriptToTypefaces["sylo"].Insert(0, "Noto Sans Syloti Nagri"); + MapScriptToTypefaces["zsym"].Insert(0, "Noto Sans Symbols"); + MapScriptToTypefaces["syrn"].Insert(0, "Noto Sans Syriac Eastern"); + MapScriptToTypefaces["syre"].Insert(0, "Noto Sans Syriac Estrangela"); + MapScriptToTypefaces["syrj"].Insert(0, "Noto Sans Syriac Western"); + MapScriptToTypefaces["tglg"].Insert(0, "Noto Sans Tagalog"); + MapScriptToTypefaces["tagb"].Insert(0, "Noto Sans Tagbanwa"); + MapScriptToTypefaces["tale"].Insert(0, "Noto Sans Tai Le"); + MapScriptToTypefaces["lana"].Insert(0, "Noto Sans Tai Tham"); + MapScriptToTypefaces["tavt"].Insert(0, "Noto Sans Tai Viet"); + MapScriptToTypefaces["takr"].Insert(0, "Noto Sans Takri"); + MapScriptToTypefaces["taml"].Insert(0, "Noto Sans Tamil"); + MapScriptToTypefaces["telu"].Insert(0, "Noto Sans Telugu"); + MapScriptToTypefaces["thaa"].Insert(0, "Noto Sans Thaana"); + MapScriptToTypefaces["thai"].Insert(0, "Noto Sans Thai"); + MapScriptToTypefaces["tfng"].Insert(0, "Noto Sans Tifinagh"); + MapScriptToTypefaces["ugar"].Insert(0, "Noto Sans Ugaritic"); + MapScriptToTypefaces["vaii"].Insert(0, "Noto Sans Vai"); + MapScriptToTypefaces["wcho"].Insert(0, "Noto Sans Wancho"); + MapScriptToTypefaces["wara"].Insert(0, "Noto Sans Warang Citi"); + MapScriptToTypefaces["yiii"].Insert(0, "Noto Sans Yi"); + } + public FallbackListFontMatcher(FontManager manager) : base(manager) { } + public override IEnumerable MatchScript(string script = null, bool distinctFamily = false) { + if (string.IsNullOrEmpty(script)) script = ScriptUtils.UltimateFallbackScript; + List candidates; + IEnumerable candidateScripts = new string[] { script }; + while (candidateScripts != null) { + foreach (var candidateScript in candidateScripts) { + if (MapScriptToTypefaces.TryGetValue(candidateScript, out candidates)) { + foreach (var candidate in candidates) { + IReadOnlyCollection typefaces1; + if (Manager.MapFullNameToTypeface.TryGetValue(candidate, out typefaces1)) { + foreach (var typeface in typefaces1) { + yield return typeface; + } + } + if (distinctFamily) continue; + IReadOnlyCollection typefaces2; + if (Manager.MapNameToTypefaces.TryGetValue(candidate, out typefaces2)) { + foreach (var typeface in typefaces2) { + if (typefaces1.Contains(typeface)) continue; + yield return typeface; + } + } + } + } + } + candidateScripts = ScriptUtils.EnumerateFallbackScripts(script); + } + } + } +} diff --git a/Assets/Cryville/Common/Font/FontMatcher.cs.meta b/Assets/Cryville/Common/Font/FontMatcher.cs.meta new file mode 100644 index 0000000..a915df1 --- /dev/null +++ b/Assets/Cryville/Common/Font/FontMatcher.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: afcde0ad1865db24da79ca1ce7256791 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Cryville/Common/Unity/UI/TMPAutoFont.cs b/Assets/Cryville/Common/Unity/UI/TMPAutoFont.cs index 5a031e2..12fd7f3 100644 --- a/Assets/Cryville/Common/Unity/UI/TMPAutoFont.cs +++ b/Assets/Cryville/Common/Unity/UI/TMPAutoFont.cs @@ -11,17 +11,17 @@ namespace Cryville.Common.Unity.UI { [RequireComponent(typeof(TextMeshProUGUI))] public class TMPAutoFont : MonoBehaviour { public static Shader DefaultShader; - public static FontManager FontManager; + public static FontMatcher FontMatcher; static FontAsset _font; TextMeshProUGUI _text; [SerializeField] Shader m_shader; void Awake() { - if (FontManager == null) return; + if (FontMatcher == null) return; _text = GetComponent(); if (_font == null) { - foreach (var typeface in FontManager.MatchScript()) { + foreach (var typeface in FontMatcher.MatchScript(null, true)) { try { var _ifont = new IFont(typeface.File.FullName); _font = (FontAsset)typeof(FontAsset).GetMethod("CreateFontAsset", BindingFlags.Static | BindingFlags.NonPublic, null, new Type[] { typeof(IFont), typeof(int), typeof(int), typeof(int), typeof(GlyphRenderMode), typeof(int), typeof(int), typeof(AtlasPopulationMode), typeof(bool) }, diff --git a/Assets/Cryville/Crtr/Game.cs b/Assets/Cryville/Crtr/Game.cs index 4aa0994..a22954a 100644 --- a/Assets/Cryville/Crtr/Game.cs +++ b/Assets/Cryville/Crtr/Game.cs @@ -131,10 +131,14 @@ namespace Cryville.Crtr { Logger.Log("main", 1, "UI", "Initializing font manager"); #if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN - TMPAutoFont.FontManager = new FontManagerWindows(); + var fontMatcher = new FallbackListFontMatcher(new FontManagerWindows()); + fontMatcher.LoadDefaultWindowsFallbackList(); + TMPAutoFont.FontMatcher = fontMatcher; TMPAutoFont.DefaultShader = Resources.Load("TextMesh Pro/Shaders/TMP_SDF SSD"); #elif UNITY_ANDROID - TMPAutoFont.FontManager = new FontManagerAndroid(); + var fontMatcher = new FallbackListFontMatcher(new FontManagerAndroid()); + fontMatcher.LoadDefaultAndroidFallbackList(); + TMPAutoFont.FontMatcher = fontMatcher; TMPAutoFont.DefaultShader = Resources.Load("TextMesh Pro/Shaders/TMP_SDF-Mobile SSD"); #else #error No font manager initialization logic.