using System.Collections.Generic; using System.IO; using System.Linq; namespace Cryville.Common.Font { public abstract class FontManager { public IReadOnlyDictionary MapFullNameToTypeface { get; private set; } public IReadOnlyDictionary> MapNameToTypefaces { get; private set; } public FontManager() { var map1 = new Dictionary(); var map2 = new Dictionary>(); foreach (var f in EnumerateAllTypefaces()) { if (!map1.ContainsKey(f.FullName)) { map1.Add(f.FullName, f); } else { continue; } List set2; if (!map2.TryGetValue(f.FamilyName, out set2)) { map2.Add(f.FamilyName, set2 = new List()); } set2.Add(f); } MapFullNameToTypeface = map1; MapNameToTypefaces = map2.ToDictionary(i => i.Key, i => (IReadOnlyCollection)i.Value); } protected abstract IEnumerable EnumerateAllTypefaces(); protected static IEnumerable ScanDirectoryForTypefaces(string dir) { foreach (var f in new DirectoryInfo(dir).EnumerateFiles()) { FontFile file; try { file = FontFile.Create(f); } catch (InvalidDataException) { continue; } if (file == null) continue; var enumerator = file.GetEnumerator(); while (enumerator.MoveNext()) { Typeface ret; try { ret = enumerator.Current; } catch (InvalidDataException) { continue; } yield return ret; } file.Close(); } } } public class FontManagerAndroid : FontManager { protected override IEnumerable EnumerateAllTypefaces() { return ScanDirectoryForTypefaces("/system/fonts"); } } public class FontManagerWindows : FontManager { protected override IEnumerable EnumerateAllTypefaces() { return ScanDirectoryForTypefaces("C:/Windows/Fonts"); } } }