From fb632f0460bbf990466c98e97a3b18c7fc4bd9b3 Mon Sep 17 00:00:00 2001 From: Julien Lebosquain Date: Wed, 13 Mar 2024 06:08:03 +0100 Subject: [PATCH] Fix font fallback for composite keys containing relative URIs (#14943) * Add failing test for font fallback with relative URI * Fix font fallback for composite keys containing relative URIs --- src/Avalonia.Base/Media/FontManager.cs | 23 +++++-------------- .../Media/FontManagerTests.cs | 8 ++++--- 2 files changed, 11 insertions(+), 20 deletions(-) diff --git a/src/Avalonia.Base/Media/FontManager.cs b/src/Avalonia.Base/Media/FontManager.cs index 4d14e57a32..65ade1a413 100644 --- a/src/Avalonia.Base/Media/FontManager.cs +++ b/src/Avalonia.Base/Media/FontManager.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using Avalonia.Media.Fonts; @@ -141,22 +142,7 @@ namespace Avalonia.Media private bool TryGetGlyphTypefaceByKeyAndName(Typeface typeface, FontFamilyKey key, string familyName, [NotNullWhen(true)] out IGlyphTypeface? glyphTypeface) { - var source = key.Source; - - if (!source.IsAbsoluteUri) - { - if (key.BaseUri == null) - { - throw new NotSupportedException($"{nameof(key.BaseUri)} can't be null."); - } - - source = new Uri(key.BaseUri, source); - } - - if (source.Scheme == SystemFontScheme) - { - return SystemFonts.TryGetGlyphTypeface(familyName, typeface.Style, typeface.Weight, typeface.Stretch, out glyphTypeface); - } + var source = key.Source.EnsureAbsolute(key.BaseUri); if (TryGetFontCollection(source, out var fontCollection) && fontCollection.TryGetGlyphTypeface(familyName, typeface.Style, typeface.Weight, typeface.Stretch, out glyphTypeface)) @@ -248,8 +234,9 @@ namespace Avalonia.Media { var key = compositeKey.Keys[i]; var familyName = fontFamily.FamilyNames[i]; + var source = key.Source.EnsureAbsolute(key.BaseUri); - if (TryGetFontCollection(key.Source, out var fontCollection) && + if (TryGetFontCollection(source, out var fontCollection) && fontCollection.TryMatchCharacter(codepoint, fontStyle, fontWeight, fontStretch, familyName, culture, out typeface)) { return true; @@ -263,6 +250,8 @@ namespace Avalonia.Media private bool TryGetFontCollection(Uri source, [NotNullWhen(true)] out IFontCollection? fontCollection) { + Debug.Assert(source.IsAbsoluteUri); + if (source.Scheme == SystemFontScheme) { source = SystemFontsKey; diff --git a/tests/Avalonia.Skia.UnitTests/Media/FontManagerTests.cs b/tests/Avalonia.Skia.UnitTests/Media/FontManagerTests.cs index d70f770a11..322645a914 100644 --- a/tests/Avalonia.Skia.UnitTests/Media/FontManagerTests.cs +++ b/tests/Avalonia.Skia.UnitTests/Media/FontManagerTests.cs @@ -200,14 +200,16 @@ namespace Avalonia.Skia.UnitTests.Media } } - [Fact] - public void Should_Match_Chararcter_Width_Fallbacks() + [Theory] + [InlineData("NotFound, Unknown", null)] // system fonts + [InlineData("/#NotFound, /#Unknown", "avares://some/path")] // embedded fonts + public void Should_Match_Character_With_Fallbacks(string familyName, string baseUri) { using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface.With(fontManagerImpl: new FontManagerImpl()))) { using (AvaloniaLocator.EnterScope()) { - var fontFamily = FontFamily.Parse("NotFound, Unknown"); + var fontFamily = FontFamily.Parse(familyName, baseUri is null ? null : new Uri(baseUri)); Assert.True(FontManager.Current.TryMatchCharacter('A', FontStyle.Normal, FontWeight.Normal, FontStretch.Normal, fontFamily, null, out var typeface));