diff --git a/src/Avalonia.Base/Media/FontManager.cs b/src/Avalonia.Base/Media/FontManager.cs index 5890b90954..cc9bc6f30a 100644 --- a/src/Avalonia.Base/Media/FontManager.cs +++ b/src/Avalonia.Base/Media/FontManager.cs @@ -119,7 +119,9 @@ namespace Avalonia.Media } } - if (fontCollection != null && fontCollection.TryGetGlyphTypeface(fontFamily.FamilyNames.PrimaryFamilyName, + var familyName = fontFamily.FamilyNames.PrimaryFamilyName.ToUpperInvariant(); + + if (fontCollection != null && fontCollection.TryGetGlyphTypeface(familyName, typeface.Style, typeface.Weight, typeface.Stretch, out glyphTypeface)) { return true; @@ -133,13 +135,13 @@ namespace Avalonia.Media foreach (var familyName in fontFamily.FamilyNames) { - if (SystemFonts.TryGetGlyphTypeface(familyName, typeface.Style, typeface.Weight, typeface.Stretch, out glyphTypeface)) + if (SystemFonts.TryGetGlyphTypeface(familyName.ToUpperInvariant(), typeface.Style, typeface.Weight, typeface.Stretch, out glyphTypeface)) { return true; } } - return SystemFonts.TryGetGlyphTypeface(DefaultFontFamilyName, typeface.Style, typeface.Weight, typeface.Stretch, out glyphTypeface); + return TryGetGlyphTypeface(new Typeface(DefaultFontFamilyName, typeface.Style, typeface.Weight, typeface.Stretch), out glyphTypeface); } /// diff --git a/src/Avalonia.Base/Media/Fonts/EmbeddedFontCollection.cs b/src/Avalonia.Base/Media/Fonts/EmbeddedFontCollection.cs index f2fb490592..3350358d68 100644 --- a/src/Avalonia.Base/Media/Fonts/EmbeddedFontCollection.cs +++ b/src/Avalonia.Base/Media/Fonts/EmbeddedFontCollection.cs @@ -3,7 +3,6 @@ using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; -using System.Globalization; using Avalonia.Platform; namespace Avalonia.Media.Fonts @@ -43,11 +42,13 @@ namespace Avalonia.Media.Fonts if (fontManager.TryCreateGlyphTypeface(stream, out var glyphTypeface)) { - if (!_glyphTypefaceCache.TryGetValue(glyphTypeface.FamilyName, out var glyphTypefaces)) + var familyName = glyphTypeface.FamilyName.ToUpperInvariant(); + + if (!_glyphTypefaceCache.TryGetValue(familyName, out var glyphTypefaces)) { glyphTypefaces = new ConcurrentDictionary(); - if (_glyphTypefaceCache.TryAdd(glyphTypeface.FamilyName, glyphTypefaces)) + if (_glyphTypefaceCache.TryAdd(familyName, glyphTypefaces)) { _fontFamilies.Add(new FontFamily(_key, glyphTypeface.FamilyName)); } @@ -86,6 +87,8 @@ namespace Avalonia.Media.Fonts public bool TryGetGlyphTypeface(string familyName, FontStyle style, FontWeight weight, FontStretch stretch, [NotNullWhen(true)] out IGlyphTypeface? glyphTypeface) { + familyName = familyName.ToUpperInvariant(); + var key = new FontCollectionKey(style, weight, stretch); if (_glyphTypefaceCache.TryGetValue(familyName, out var glyphTypefaces)) @@ -101,9 +104,11 @@ namespace Avalonia.Media.Fonts { var fontFamily = _fontFamilies[i]; - if (fontFamily.Name.ToLower(CultureInfo.InvariantCulture).StartsWith(familyName.ToLower(CultureInfo.InvariantCulture))) + if (fontFamily.Name.ToUpperInvariant().StartsWith(familyName.ToUpperInvariant())) { - if (_glyphTypefaceCache.TryGetValue(fontFamily.Name, out glyphTypefaces) && + familyName = fontFamily.Name.ToUpperInvariant(); + + if (_glyphTypefaceCache.TryGetValue(familyName, out glyphTypefaces) && TryGetNearestMatch(glyphTypefaces, key, out glyphTypeface)) { return true; diff --git a/src/Avalonia.Base/Media/Fonts/SystemFontCollection.cs b/src/Avalonia.Base/Media/Fonts/SystemFontCollection.cs index fd332c6ebe..1687deb37b 100644 --- a/src/Avalonia.Base/Media/Fonts/SystemFontCollection.cs +++ b/src/Avalonia.Base/Media/Fonts/SystemFontCollection.cs @@ -42,6 +42,8 @@ namespace Avalonia.Media.Fonts familyName = _fontManager.DefaultFontFamilyName; } + familyName = familyName.ToUpperInvariant(); + var key = new FontCollectionKey(style, weight, stretch); if (_glyphTypefaceCache.TryGetValue(familyName, out var glyphTypefaces)) diff --git a/tests/Avalonia.Skia.UnitTests/Media/CustomFontManagerImpl.cs b/tests/Avalonia.Skia.UnitTests/Media/CustomFontManagerImpl.cs index e18344580b..4b91209e5b 100644 --- a/tests/Avalonia.Skia.UnitTests/Media/CustomFontManagerImpl.cs +++ b/tests/Avalonia.Skia.UnitTests/Media/CustomFontManagerImpl.cs @@ -68,66 +68,6 @@ namespace Avalonia.Skia.UnitTests.Media return true; } - public IGlyphTypeface CreateGlyphTypeface(Typeface typeface) - { - SKTypeface skTypeface; - - Uri source = null; - - switch (typeface.FontFamily.Name) - { - case "Twitter Color Emoji": - { - source = _emojiTypeface.FontFamily.Key.Source; - break; - } - case "Noto Sans": - { - source = _italicTypeface.FontFamily.Key.Source; - break; - } - case "Noto Sans Arabic": - { - source = _arabicTypeface.FontFamily.Key.Source; - break; - } - case "Noto Sans Hebrew": - { - source = _hebrewTypeface.FontFamily.Key.Source; - break; - } - case FontFamily.DefaultFontFamilyName: - case "Noto Mono": - { - source = _defaultTypeface.FontFamily.Key.Source; - break; - } - default: - { - - break; - } - } - - if (source is null) - { - skTypeface = SKTypeface.FromFamilyName(typeface.FontFamily.Name, - (SKFontStyleWeight)typeface.Weight, SKFontStyleWidth.Normal, (SKFontStyleSlant)typeface.Style); - } - else - { - var assetLoader = AvaloniaLocator.Current.GetRequiredService(); - - var assetUri = FontFamilyLoader.LoadFontAssets(source).First(); - - var stream = assetLoader.Open(assetUri); - - skTypeface = SKTypeface.FromStream(stream); - } - - return new GlyphTypefaceImpl(skTypeface, FontSimulations.None); - } - public bool TryCreateGlyphTypeface(string familyName, FontStyle style, FontWeight weight, FontStretch stretch, [NotNullWhen(true)] out IGlyphTypeface glyphTypeface) { @@ -137,54 +77,40 @@ namespace Avalonia.Skia.UnitTests.Media switch (familyName) { - case "Twitter Color Emoji": + case "TWITTER COLOR EMOJI": { source = _emojiTypeface.FontFamily.Key.Source; break; } - case "Noto Sans": + case "NOTO SANS": { source = _italicTypeface.FontFamily.Key.Source; break; } - case "Noto Sans Arabic": + case "NOTO SANS ARABIC": { source = _arabicTypeface.FontFamily.Key.Source; break; } - case "Noto Sans Hebrew": + case "NOTO SANS HEBREW": { source = _hebrewTypeface.FontFamily.Key.Source; break; } - case FontFamily.DefaultFontFamilyName: - case "Noto Mono": - { - source = _defaultTypeface.FontFamily.Key.Source; - break; - } default: { - + source = _defaultTypeface.FontFamily.Key.Source; break; } } - if (source is null) - { - skTypeface = SKTypeface.FromFamilyName(familyName, - (SKFontStyleWeight)weight, SKFontStyleWidth.Normal, (SKFontStyleSlant)style); - } - else - { - var assetLoader = AvaloniaLocator.Current.GetRequiredService(); + var assetLoader = AvaloniaLocator.Current.GetRequiredService(); - var assetUri = FontFamilyLoader.LoadFontAssets(source).First(); + var assetUri = FontFamilyLoader.LoadFontAssets(source).First(); - var stream = assetLoader.Open(assetUri); + var stream = assetLoader.Open(assetUri); - skTypeface = SKTypeface.FromStream(stream); - } + skTypeface = SKTypeface.FromStream(stream); glyphTypeface = new GlyphTypefaceImpl(skTypeface, FontSimulations.None); diff --git a/tests/Avalonia.Skia.UnitTests/Media/FontManagerImplTests.cs b/tests/Avalonia.Skia.UnitTests/Media/FontManagerTests.cs similarity index 72% rename from tests/Avalonia.Skia.UnitTests/Media/FontManagerImplTests.cs rename to tests/Avalonia.Skia.UnitTests/Media/FontManagerTests.cs index 859726e871..37f275484a 100644 --- a/tests/Avalonia.Skia.UnitTests/Media/FontManagerImplTests.cs +++ b/tests/Avalonia.Skia.UnitTests/Media/FontManagerTests.cs @@ -1,5 +1,4 @@ using System; -using System.Linq; using Avalonia.Media; using Avalonia.UnitTests; using SkiaSharp; @@ -7,7 +6,7 @@ using Xunit; namespace Avalonia.Skia.UnitTests.Media { - public class FontManagerImplTests + public class FontManagerTests { private static string s_fontUri = "resm:Avalonia.Skia.UnitTests.Assets?assembly=Avalonia.Skia.UnitTests#Noto Mono"; @@ -87,5 +86,36 @@ namespace Avalonia.Skia.UnitTests.Media Assert.False(result); } } + + [Fact] + public void Should_Load_Embedded_Font_With_Wrong_CharacterCasing() + { + using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface.With(fontManagerImpl: new FontManagerImpl()))) + { + var result = FontManager.Current.TryGetGlyphTypeface(new Typeface("resm:Avalonia.Skia.UnitTests.Assets?assembly=Avalonia.Skia.UnitTests#noto mOnO"), out var glyphTypeface); + + Assert.True(result); + + Assert.Equal("Noto Mono", glyphTypeface.FamilyName); + } + } + + [Fact] + public void Should_Load_Embedded_DefaultFontFamily() + { + using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface.With(fontManagerImpl: new FontManagerImpl()))) + { + using (AvaloniaLocator.EnterScope()) + { + AvaloniaLocator.CurrentMutable.BindToSelf(new FontManagerOptions { DefaultFamilyName = s_fontUri }); + + var result = FontManager.Current.TryGetGlyphTypeface(new Typeface(FontFamily.DefaultFontFamilyName), out var glyphTypeface); + + Assert.True(result); + + Assert.Equal("Noto Mono", glyphTypeface.FamilyName); + } + } + } } } diff --git a/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextFormatterTests.cs b/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextFormatterTests.cs index dc8744b292..ce974472e7 100644 --- a/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextFormatterTests.cs +++ b/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextFormatterTests.cs @@ -416,14 +416,14 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting } [InlineData("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor", - new[] { "Lorem ipsum ", "dolor sit amet, ", "consectetur ", "adipisicing elit, ", "sed do eiusmod " })] + new[] { "Lorem ipsum ", "dolor sit ", "amet, ", "consectetur ", "adipisicing ", "elit, sed do ", "eiusmod tempor" })] [Theory] public void Should_Produce_Wrapped_And_Trimmed_Lines(string text, string[] expectedLines) { using (Start()) { - var typeface = new Typeface("Verdana"); + var typeface = Typeface.Default; var defaultProperties = new GenericTextRunProperties(typeface, 32, foregroundBrush: Brushes.Black); @@ -432,9 +432,9 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting new ValueSpan(0, 5, new GenericTextRunProperties(typeface, 48)), new ValueSpan(6, 11, - new GenericTextRunProperties(new Typeface("Verdana", weight: FontWeight.Bold), 32)), + new GenericTextRunProperties(new Typeface(FontFamily.Default, weight: FontWeight.Bold), 32)), new ValueSpan(28, 28, - new GenericTextRunProperties(new Typeface("Verdana", FontStyle.Italic),32)) + new GenericTextRunProperties(new Typeface(FontFamily.Default, FontStyle.Italic),32)) }; var textSource = new FormattedTextSource(text, defaultProperties, styleSpans);