Fix FontCollection glyph typeface caching (#17519)

* Make sure we always cache the created glyph typeface before we try to find the nearest match

* Cleanup usings

* Add failing test

* Cache the matched glyph typeface for EmbeddedFontCollection
This commit is contained in:
Benedikt Stebner 2024-11-19 15:27:55 +01:00 коммит произвёл GitHub
Родитель 9091d66e30
Коммит 28c21078f5
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
4 изменённых файлов: 80 добавлений и 1 удалений

Просмотреть файл

@ -76,6 +76,9 @@ namespace Avalonia.Media.Fonts
glyphTypeface = syntheticGlyphTypeface;
}
//Make sure we cache the found match
glyphTypefaces.TryAdd(key, glyphTypeface);
return true;
}
}

Просмотреть файл

@ -81,6 +81,9 @@ namespace Avalonia.Media.Fonts
//No exact match
if (createdKey != key)
{
//Add the created glyph typeface to the cache so we can match it.
glyphTypefaces.TryAdd(createdKey, glyphTypeface);
//Try to find nearest match if possible
if (TryGetNearestMatch(glyphTypefaces, key, out var nearestMatch))
{

Просмотреть файл

@ -1,4 +1,7 @@
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using Avalonia.Media;
using Avalonia.Media.Fonts;
using Avalonia.UnitTests;
@ -89,5 +92,37 @@ namespace Avalonia.Skia.UnitTests.Media
Assert.Equal("Manrope", glyphTypeface2.TypographicFamilyName);
}
}
[Fact]
public void Should_Cache_Synthetic_GlyphTypeface()
{
using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{
var source = new Uri(s_manrope, UriKind.Absolute);
var fontCollection = new TestEmbeddedFontCollection(source, source);
fontCollection.Initialize(new CustomFontManagerImpl());
Assert.True(fontCollection.TryGetGlyphTypeface("Manrope", FontStyle.Normal, FontWeight.ExtraBlack, FontStretch.Normal, out var glyphTypeface));
Assert.True(fontCollection.GlyphTypefaceCache.TryGetValue("Manrope", out var glyphTypefaces));
Assert.Equal(2, glyphTypefaces.Count);
fontCollection.TryGetGlyphTypeface("Manrope", FontStyle.Normal, FontWeight.ExtraBlack, FontStretch.Normal, out var otherGlyphTypeface);
Assert.Equal(glyphTypeface, otherGlyphTypeface);
}
}
private class TestEmbeddedFontCollection : EmbeddedFontCollection
{
public TestEmbeddedFontCollection(Uri key, Uri source) : base(key, source)
{
}
public IDictionary<string, ConcurrentDictionary<FontCollectionKey, IGlyphTypeface?>> GlyphTypefaceCache => _glyphTypefaceCache;
}
}
}

Просмотреть файл

@ -1,5 +1,8 @@
using Avalonia.Media;
using System.Collections.Concurrent;
using System.Collections.Generic;
using Avalonia.Media;
using Avalonia.Media.Fonts;
using Avalonia.UnitTests;
using Xunit;
namespace Avalonia.Skia.UnitTests.Media
@ -24,5 +27,40 @@ namespace Avalonia.Skia.UnitTests.Media
Assert.Equal(weight, result.Weight);
Assert.Equal(FontStretch.Normal, result.Stretch);
}
[Win32Fact("Relies on some installed font family")]
public void Should_Cache_Nearest_Match()
{
using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface.With(fontManagerImpl: new FontManagerImpl())))
{
var fontManager = FontManager.Current;
var fontCollection = new TestSystemFontCollection(FontManager.Current);
Assert.True(fontCollection.TryGetGlyphTypeface("Arial", FontStyle.Normal, FontWeight.ExtraBlack, FontStretch.Normal, out var glyphTypeface));
Assert.True(glyphTypeface.FontSimulations == FontSimulations.Bold);
Assert.True(fontCollection.GlyphTypfaceCache.TryGetValue("Arial", out var glyphTypefaces));
Assert.Equal(2, glyphTypefaces.Count);
Assert.True(glyphTypefaces.ContainsKey(new FontCollectionKey(FontStyle.Normal, FontWeight.Black, FontStretch.Normal)));
fontCollection.TryGetGlyphTypeface("Arial", FontStyle.Normal, FontWeight.ExtraBlack, FontStretch.Normal, out var otherGlyphTypeface);
Assert.Equal(glyphTypeface, otherGlyphTypeface);
}
}
private class TestSystemFontCollection : SystemFontCollection
{
public TestSystemFontCollection(FontManager fontManager) : base(fontManager)
{
}
public IDictionary<string, ConcurrentDictionary<FontCollectionKey, IGlyphTypeface?>> GlyphTypfaceCache => _glyphTypefaceCache;
}
}
}