Browse Source

Merge pull request #13191 from Gillibald/featurer/customSystemFonts

Introduce AppBuilder extension to customize system fonts
pull/13241/head
Jumar Macato 2 years ago
committed by GitHub
parent
commit
ccf74f62b9
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 56
      src/Avalonia.Base/Media/Fonts/SystemFontCollection.cs
  2. 19
      src/Avalonia.Controls/SystemFontAppBuilderExtension.cs
  3. 22
      tests/Avalonia.Skia.UnitTests/Media/FontManagerTests.cs

56
src/Avalonia.Base/Media/Fonts/SystemFontCollection.cs

@ -2,6 +2,7 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Avalonia.Platform;
namespace Avalonia.Media.Fonts
@ -9,12 +10,12 @@ namespace Avalonia.Media.Fonts
internal class SystemFontCollection : FontCollectionBase
{
private readonly FontManager _fontManager;
private readonly string[] _familyNames;
private readonly List<string> _familyNames;
public SystemFontCollection(FontManager fontManager)
{
_fontManager = fontManager;
_familyNames = fontManager.PlatformImpl.GetInstalledFontFamilyNames();
_familyNames = fontManager.PlatformImpl.GetInstalledFontFamilyNames().ToList();
}
public override Uri Key => FontManager.SystemFontsKey;
@ -29,7 +30,15 @@ namespace Avalonia.Media.Fonts
}
}
public override int Count => _familyNames.Length;
public override int Count => _familyNames.Count;
public override IEnumerator<FontFamily> GetEnumerator()
{
foreach (var familyName in _familyNames)
{
yield return new FontFamily(familyName);
}
}
public override bool TryGetGlyphTypeface(string familyName, FontStyle style, FontWeight weight,
FontStretch stretch, [NotNullWhen(true)] out IGlyphTypeface? glyphTypeface)
@ -58,11 +67,46 @@ namespace Avalonia.Media.Fonts
//We initialize the system font collection during construction.
}
public override IEnumerator<FontFamily> GetEnumerator()
public void AddCustomFontSource(Uri source)
{
foreach (var familyName in _familyNames)
if (source is null)
{
yield return new FontFamily(familyName);
return;
}
LoadGlyphTypefaces(_fontManager.PlatformImpl, source);
}
private void LoadGlyphTypefaces(IFontManagerImpl fontManager, Uri source)
{
var assetLoader = AvaloniaLocator.Current.GetRequiredService<IAssetLoader>();
var fontAssets = FontFamilyLoader.LoadFontAssets(source);
foreach (var fontAsset in fontAssets)
{
var stream = assetLoader.Open(fontAsset);
if (fontManager.TryCreateGlyphTypeface(stream, out var glyphTypeface))
{
if (!_glyphTypefaceCache.TryGetValue(glyphTypeface.FamilyName, out var glyphTypefaces))
{
glyphTypefaces = new ConcurrentDictionary<FontCollectionKey, IGlyphTypeface?>();
if (_glyphTypefaceCache.TryAdd(glyphTypeface.FamilyName, glyphTypefaces))
{
//Move the user defined system font to the start of the collection
_familyNames.Insert(0, glyphTypeface.FamilyName);
}
}
var key = new FontCollectionKey(
glyphTypeface.Style,
glyphTypeface.Weight,
glyphTypeface.Stretch);
glyphTypefaces.TryAdd(key, glyphTypeface);
}
}
}
}

19
src/Avalonia.Controls/SystemFontAppBuilderExtension.cs

@ -0,0 +1,19 @@
using System;
using Avalonia.Media.Fonts;
namespace Avalonia
{
public static class SystemFontAppBuilderExtension
{
public static AppBuilder WithSystemFontSource(this AppBuilder appBuilder, Uri fontSource)
{
return appBuilder.ConfigureFonts(fontManager =>
{
if(fontManager.SystemFonts is SystemFontCollection systemFontCollection)
{
systemFontCollection.AddCustomFontSource(fontSource);
}
});
}
}
}

22
tests/Avalonia.Skia.UnitTests/Media/FontManagerTests.cs

@ -1,6 +1,8 @@
using System;
using System.Linq;
using Avalonia.Headless;
using Avalonia.Media;
using Avalonia.Media.Fonts;
using Avalonia.UnitTests;
using SkiaSharp;
using Xunit;
@ -217,5 +219,25 @@ namespace Avalonia.Skia.UnitTests.Media
}
}
}
[Fact]
public void Should_Use_Custom_SystemFont()
{
using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface.With(fontManagerImpl: new FontManagerImpl())))
{
using (AvaloniaLocator.EnterScope())
{
var systemFontCollection = FontManager.Current.SystemFonts as SystemFontCollection;
Assert.NotNull(systemFontCollection);
systemFontCollection.AddCustomFontSource(new Uri(s_fontUri, UriKind.Absolute));
Assert.True(FontManager.Current.TryGetGlyphTypeface(new Typeface("Noto Mono"), out var glyphTypeface));
Assert.Equal("Noto Mono", glyphTypeface.FamilyName);
}
}
}
}
}

Loading…
Cancel
Save