internal static UIFont BestFont(string family, nfloat size, bool bold = false, bool italic = false, Assembly assembly = null) { if (family == null) { family = "sans-serif"; } if (family.ToLower() == "monospace") { family = "Menlo"; } if (family.ToLower() == "serif") { family = "Times New Roman"; } if (family.ToLower() == "sans-serif") { family = "Arial"; } if (size < 0) { size = (nfloat)(UIFont.LabelFontSize * Math.Abs(size)); } // is it in the cache? var key = new FontKey(family, size, bold, italic); Dictionary <FontKey, UIFont> dictionary = UiFontCache; lock (dictionary) { if (dictionary.TryGetValue(key, out UIFont storedUiFont)) { return(storedUiFont); } } UIFont bestAttemptFont = null; if (UIFont.FamilyNames.Contains(family)) { // a system font var fontNames = FontFamilies.FontsForFamily(family); string baseFontName = null; string reqFontName = null; //string fallbackFontName = null; if (fontNames != null && fontNames.Count > 0) { if (fontNames.Count == 1) { baseFontName = fontNames[0]; if (!bold && !italic) { reqFontName = fontNames[0]; } } else { int shortestMatchLength = int.MaxValue; int shortestBaseLength = int.MaxValue; foreach (var fontName in fontNames) { var lowerName = fontName.ToLower(); bool nameHasBold = lowerName.Contains("bold") || lowerName == "avenir-black"; bool nameHasItalic = lowerName.Contains("italic") || lowerName.Contains("oblique"); // assume the shortest name is the base font name if (lowerName.Length < shortestBaseLength) { baseFontName = fontName; shortestBaseLength = lowerName.Length; } // assume the shortest name with matching attributes is a match if (nameHasBold == bold && nameHasItalic == italic && lowerName.Length < shortestMatchLength) { reqFontName = fontName; shortestMatchLength = lowerName.Length; } if (lowerName.Contains("-regular")) { baseFontName = fontName; shortestBaseLength = -1; if (!bold && !italic) { reqFontName = fontName; shortestMatchLength = -1; break; } } } } } if (reqFontName != null) { bestAttemptFont = UIFont.FromName(reqFontName, size); } if (bestAttemptFont == null && baseFontName != null && !bold && !italic) { bestAttemptFont = UIFont.FromName(baseFontName, size); } } else { // an embedded font or a explicitly named system font? bestAttemptFont = EmbeddedFont(family, size, assembly); if (bestAttemptFont == null) { bestAttemptFont = UIFont.FromName(family, size); } } if (bestAttemptFont != null) { // we have a match but is wasn't cached - so let's cache it for future reference lock (dictionary) { if (!dictionary.TryGetValue(key, out UIFont storedUiFont)) { // It could have been added by another thread so only add if we're really sure it's no there! dictionary.Add(key, bestAttemptFont); } } return(bestAttemptFont); } // fall back to a system font if (bold && italic) { UIFont systemFont = UIFont.SystemFontOfSize(size); var descriptor = systemFont.FontDescriptor.CreateWithTraits(UIFontDescriptorSymbolicTraits.Bold | UIFontDescriptorSymbolicTraits.Italic); bestAttemptFont = UIFont.FromDescriptor(descriptor, size); } if (bestAttemptFont == null && italic) { bestAttemptFont = UIFont.ItalicSystemFontOfSize(size); } if (bestAttemptFont == null && bold) { bestAttemptFont = UIFont.BoldSystemFontOfSize(size); } if (bestAttemptFont == null) { bestAttemptFont = UIFont.SystemFontOfSize(size); } return(bestAttemptFont); }
internal static UIFont BestFont(string family, nfloat size, bool bold = false, bool italic = false, Assembly assembly = null) { if (family == null) { family = ".AppleSystemUIFont"; } if (family.ToLower() == "monospace") { family = "Menlo"; } if (family.ToLower() == "serif") { family = "Times New Roman"; } if (family.ToLower() == "sans-serif") { family = ".AppleSystemUIFont"; } if (size < 0) { size = (nfloat)(UIFont.LabelFontSize * Math.Abs(size)); } // is it in the cache? var key = new FontKey(family, size, bold, italic); Dictionary <FontKey, UIFont> dictionary = UiFontCache; lock (dictionary) { if (dictionary.TryGetValue(key, out UIFont storedUiFont)) { return(storedUiFont); } } UIFont bestAttemptFont = null; if (UIFont.FamilyNames.Contains(family)) { // a system font var fontNames = FontFamilies.FontsForFamily(family); string baseFontName = null; string reqFontName = null; //string fallbackFontName = null; if (fontNames != null && fontNames.Count > 0) { if (fontNames.Count == 1) { baseFontName = fontNames[0]; if (!bold && !italic) { reqFontName = fontNames[0]; } } else { int shortestMatchLength = int.MaxValue; int shortestBaseLength = int.MaxValue; foreach (var fontName in fontNames) { var lowerName = fontName.ToLower(); bool nameHasBold = lowerName.Contains("bold") || lowerName == "avenir-black"; bool nameHasItalic = lowerName.Contains("italic") || lowerName.Contains("oblique"); // assume the shortest name is the base font name if (lowerName.Length < shortestBaseLength) { baseFontName = fontName; shortestBaseLength = lowerName.Length; } // assume the shortest name with matching attributes is a match if (nameHasBold == bold && nameHasItalic == italic && lowerName.Length < shortestMatchLength) { reqFontName = fontName; shortestMatchLength = lowerName.Length; } if (lowerName.Contains("-regular")) { baseFontName = fontName; shortestBaseLength = -1; if (!bold && !italic) { reqFontName = fontName; shortestMatchLength = -1; break; } } } } } if (reqFontName != null) { bestAttemptFont = UIFont.FromName(reqFontName, size); } if (bestAttemptFont == null && baseFontName != null && !bold && !italic) { bestAttemptFont = UIFont.FromName(baseFontName, size); } } else { // an embedded font or a explicitly named system font? bestAttemptFont = EmbeddedFont(family, size, assembly); if (bestAttemptFont == null && !family.StartsWith(".SFUI")) { bestAttemptFont = UIFont.FromName(family, size); } } if (bestAttemptFont != null) { if (bold || italic) { if (bestAttemptFont.FontDescriptor.CreateWithTraits( (bold ? UIFontDescriptorSymbolicTraits.Bold : UIFontDescriptorSymbolicTraits.ClassUnknown) | (italic ? UIFontDescriptorSymbolicTraits.Italic : UIFontDescriptorSymbolicTraits.ClassUnknown) ) is UIFontDescriptor descriptor) { bestAttemptFont = UIFont.FromDescriptor(descriptor, size); } } // we have a match but is wasn't cached - so let's cache it for future reference lock (dictionary) { if (!dictionary.TryGetValue(key, out UIFont storedUiFont)) { // It could have been added by another thread so only add if we're really sure it's no there! dictionary.Add(key, bestAttemptFont); } } return(bestAttemptFont); } UIFontWeight fontWeight = UIFontWeight.Regular; if (family.StartsWith(".SFUI")) { var parts = family.Split("-"); if (parts.Length > 1) { var weightText = parts[1]; switch (weightText) { case nameof(UIFontWeight.Black): fontWeight = UIFontWeight.Black; break; case nameof(UIFontWeight.Bold): fontWeight = UIFontWeight.Bold; break; case nameof(UIFontWeight.Heavy): fontWeight = UIFontWeight.Heavy; break; case nameof(UIFontWeight.Light): fontWeight = UIFontWeight.Light; break; case nameof(UIFontWeight.Medium): fontWeight = UIFontWeight.Medium; break; case nameof(UIFontWeight.Regular): fontWeight = UIFontWeight.Medium; break; case nameof(UIFontWeight.Semibold): fontWeight = UIFontWeight.Semibold; break; case nameof(UIFontWeight.Thin): fontWeight = UIFontWeight.Thin; break; case nameof(UIFontWeight.UltraLight): fontWeight = UIFontWeight.UltraLight; break; default: fontWeight = UIFontWeight.Regular; break; } } // fall back to a system font } // fall back to a system font if (bold && italic || (fontWeight != UIFontWeight.Regular && (bold || italic))) { UIFont systemFont = UIFont.SystemFontOfSize(size, fontWeight); UIFontDescriptorSymbolicTraits traits = (bold ? UIFontDescriptorSymbolicTraits.Bold : (UIFontDescriptorSymbolicTraits)0) | (italic ? UIFontDescriptorSymbolicTraits.Italic : (UIFontDescriptorSymbolicTraits)0); var descriptor = systemFont.FontDescriptor.CreateWithTraits(traits); bestAttemptFont = UIFont.FromDescriptor(descriptor, size); } if (bestAttemptFont == null && italic) { bestAttemptFont = UIFont.ItalicSystemFontOfSize(size); } if (bestAttemptFont == null && bold) { bestAttemptFont = UIFont.BoldSystemFontOfSize(size); } if (bestAttemptFont == null) { bestAttemptFont = UIFont.SystemFontOfSize(size, fontWeight); } return(bestAttemptFont); }