csharpc-sharpdotnetxamlavaloniauicross-platformcross-platform-xamlavaloniaguimulti-platformuser-interfacedotnetcore
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
226 lines
10 KiB
226 lines
10 KiB
using System;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using Avalonia.Media;
|
|
using Avalonia.Media.Fonts;
|
|
using Avalonia.Platform;
|
|
using Avalonia.UnitTests;
|
|
using Xunit;
|
|
|
|
namespace Avalonia.Skia.UnitTests.Media
|
|
{
|
|
public class CustomFontCollectionTests
|
|
{
|
|
private const string AssetsNamespace = "Avalonia.Skia.UnitTests.Assets";
|
|
private const string AssetFonts = $"resm:{AssetsNamespace}?assembly=Avalonia.Skia.UnitTests";
|
|
|
|
[Fact]
|
|
public void Should_AddGlyphTypeface_By_Stream()
|
|
{
|
|
using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface.With(fontManagerImpl: new FontManagerImpl())))
|
|
{
|
|
var fontManager = FontManager.Current;
|
|
|
|
var fontCollection = new CustomFontCollection(new Uri("fonts:custom", UriKind.Absolute));
|
|
|
|
fontManager.AddFontCollection(fontCollection);
|
|
|
|
var assetLoader = AvaloniaLocator.Current.GetRequiredService<IAssetLoader>();
|
|
|
|
var infos = new[]
|
|
{
|
|
new FontAssetInfo($"{AssetsNamespace}.AdobeBlank2VF.ttf", "Adobe Blank 2 VF R", FontWeight.Normal),
|
|
new FontAssetInfo($"{AssetsNamespace}.Inter-Bold.ttf", "Inter", FontWeight.Bold),
|
|
new FontAssetInfo($"{AssetsNamespace}.Inter-Regular.ttf", "Inter", FontWeight.Normal),
|
|
new FontAssetInfo($"{AssetsNamespace}.Manrope-Light.ttf", "Manrope Light", FontWeight.Light),
|
|
new FontAssetInfo($"{AssetsNamespace}.MiSans-Normal.ttf", "MiSans Normal", (FontWeight)305),
|
|
new FontAssetInfo($"{AssetsNamespace}.NISC18030.ttf", "GB18030 Bitmap", FontWeight.Normal),
|
|
new FontAssetInfo($"{AssetsNamespace}.NotoMono-Regular.ttf", "Noto Mono", FontWeight.Normal),
|
|
new FontAssetInfo($"{AssetsNamespace}.NotoSans-Italic.ttf", "Noto Sans", FontWeight.Normal),
|
|
new FontAssetInfo($"{AssetsNamespace}.NotoSansArabic-Regular.ttf", "Noto Sans Arabic", FontWeight.Normal),
|
|
new FontAssetInfo($"{AssetsNamespace}.NotoSansDeseret-Regular.ttf", "Noto Sans Deseret", FontWeight.Normal),
|
|
new FontAssetInfo($"{AssetsNamespace}.NotoSansHebrew-Regular.ttf", "Noto Sans Hebrew", FontWeight.Normal),
|
|
new FontAssetInfo($"{AssetsNamespace}.NotoSansMiao-Regular.ttf", "Noto Sans Miao", FontWeight.Normal),
|
|
new FontAssetInfo($"{AssetsNamespace}.NotoSansTamil-Regular.ttf", "Noto Sans Tamil", FontWeight.Normal),
|
|
new FontAssetInfo($"{AssetsNamespace}.SourceSerif4_36pt-Italic.ttf", "Source Serif 4 36pt", FontWeight.Normal),
|
|
new FontAssetInfo($"{AssetsNamespace}.TwitterColorEmoji-SVGinOT.ttf", "Twitter Color Emoji", FontWeight.Normal)
|
|
};
|
|
|
|
var assets = assetLoader.GetAssets(new Uri(AssetFonts, UriKind.Absolute), null)
|
|
.OrderBy(uri => uri.AbsoluteUri, StringComparer.OrdinalIgnoreCase)
|
|
.ToArray();
|
|
|
|
Assert.Equal(infos.Length, assets.Length);
|
|
|
|
var glyphTypefaces = new GlyphTypeface[infos.Length];
|
|
|
|
// Load fonts
|
|
for (var i = 0; i < infos.Length; ++i)
|
|
{
|
|
var info = infos[i];
|
|
var asset = assets[i];
|
|
|
|
Assert.Equal(info.Path, asset.AbsolutePath);
|
|
|
|
using var fontStream = assetLoader.Open(asset);
|
|
Assert.NotNull(fontStream);
|
|
|
|
Assert.True(fontCollection.TryAddGlyphTypeface(fontStream, out var glyphTypeface));
|
|
Assert.Equal(info.FamilyName, glyphTypeface.FamilyName);
|
|
Assert.Equal(info.Weight, glyphTypeface.Weight);
|
|
|
|
glyphTypefaces[i] = glyphTypeface;
|
|
}
|
|
|
|
// Check against the custom collection
|
|
for (var i = 0; i < infos.Length; ++i)
|
|
{
|
|
var info = infos[i];
|
|
var glyphTypeface = glyphTypefaces[i];
|
|
|
|
Assert.True(fontManager.TryGetGlyphTypeface(new Typeface($"fonts:custom#{info.FamilyName}", weight: info.Weight), out var secondGlyphTypeface));
|
|
Assert.Same(glyphTypeface, secondGlyphTypeface);
|
|
}
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void Should_Enumerate_FontFamilies()
|
|
{
|
|
using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface.With(fontManagerImpl: new FontManagerImpl())))
|
|
{
|
|
var fontManager = FontManager.Current;
|
|
|
|
var fontCollection = new CustomFontCollection(new Uri("fonts:custom", UriKind.Absolute));
|
|
|
|
fontManager.AddFontCollection(fontCollection);
|
|
|
|
var assetLoader = AvaloniaLocator.Current.GetRequiredService<IAssetLoader>();
|
|
|
|
var assets = assetLoader.GetAssets(new Uri(AssetFonts, UriKind.Absolute), null).Where(x => x.AbsolutePath.EndsWith(".ttf")).ToArray();
|
|
|
|
foreach (var asset in assets)
|
|
{
|
|
fontCollection.TryAddGlyphTypeface(assetLoader.Open(asset), out _);
|
|
}
|
|
|
|
var families = fontCollection.ToArray();
|
|
|
|
Assert.True(families.Length >= assets.Length);
|
|
|
|
var other = new CustomFontCollection(new Uri("fonts:other", UriKind.Absolute));
|
|
|
|
foreach (var family in families)
|
|
{
|
|
var familyTypefaces = family.FamilyTypefaces;
|
|
|
|
foreach (var typeface in familyTypefaces)
|
|
{
|
|
other.TryAddGlyphTypeface(typeface.GlyphTypeface);
|
|
}
|
|
}
|
|
|
|
Assert.Equal(families.Length, other.Count);
|
|
|
|
for (int i = 0; i < families.Length; i++)
|
|
{
|
|
Assert.Equal(families[i].Name, other[i].Name);
|
|
}
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void Should_AddFontSource_From_File()
|
|
{
|
|
using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface.With(fontManagerImpl: new FontManagerImpl())))
|
|
{
|
|
var fontManager = FontManager.Current;
|
|
var fontCollection = new CustomFontCollection(new Uri("fonts:custom", UriKind.Absolute));
|
|
fontManager.AddFontCollection(fontCollection);
|
|
|
|
// Path to the test font
|
|
var fontPath = Path.Combine(AppContext.BaseDirectory, "Assets", "Inter-Regular.ttf");
|
|
Assert.True(File.Exists(fontPath));
|
|
|
|
var fontUri = new Uri(fontPath, UriKind.Absolute);
|
|
|
|
// Add the font file
|
|
Assert.True(fontCollection.TryAddFontSource(fontUri));
|
|
|
|
// Check if the font was loaded
|
|
Assert.True(fontCollection.TryGetGlyphTypeface("Inter", FontStyle.Normal, FontWeight.Regular, FontStretch.Normal, out var glyphTypeface));
|
|
Assert.Equal("Inter", glyphTypeface.FamilyName);
|
|
|
|
// Check if the FontManager can find the font
|
|
Assert.True(fontManager.TryGetGlyphTypeface(new Typeface("fonts:custom#Inter"), out var glyphTypeface2));
|
|
Assert.Equal(glyphTypeface, glyphTypeface2);
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void Should_AddFontSource_From_Folder()
|
|
{
|
|
using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface.With(fontManagerImpl: new FontManagerImpl())))
|
|
{
|
|
var fontManager = FontManager.Current;
|
|
var fontCollection = new CustomFontCollection(new Uri("fonts:custom", UriKind.Absolute));
|
|
fontManager.AddFontCollection(fontCollection);
|
|
|
|
// Path to the test fonts
|
|
var fontsFolder = Path.Combine(AppContext.BaseDirectory, "Assets");
|
|
Assert.True(Directory.Exists(fontsFolder));
|
|
|
|
var folderUri = new Uri(fontsFolder + Path.DirectorySeparatorChar, UriKind.Absolute);
|
|
|
|
// Add the fonts
|
|
Assert.True(fontCollection.TryAddFontSource(folderUri));
|
|
|
|
// Check if the font was loaded
|
|
Assert.True(fontCollection.TryGetGlyphTypeface("Inter", FontStyle.Normal, FontWeight.Regular, FontStretch.Normal, out var glyphTypeface));
|
|
Assert.Equal("Inter", glyphTypeface.FamilyName);
|
|
|
|
// Check if the FontManager can find the font
|
|
Assert.True(fontManager.TryGetGlyphTypeface(new Typeface("fonts:custom#Inter"), out var glyphTypeface2));
|
|
Assert.Equal(glyphTypeface, glyphTypeface2);
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void Should_AddFontSource_From_Resource()
|
|
{
|
|
using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface.With(fontManagerImpl: new FontManagerImpl())))
|
|
{
|
|
var fontManager = FontManager.Current;
|
|
var fontCollection = new CustomFontCollection(new Uri("fonts:custom", UriKind.Absolute));
|
|
fontManager.AddFontCollection(fontCollection);
|
|
|
|
var allFontsUri = new Uri(AssetFonts, UriKind.Absolute);
|
|
|
|
// Add the font resource
|
|
Assert.True(fontCollection.TryAddFontSource(allFontsUri));
|
|
|
|
// Get the loaded family names
|
|
var families = fontCollection.ToArray();
|
|
|
|
Assert.NotEmpty(families);
|
|
|
|
// Try to get a GlyphTypeface
|
|
Assert.True(fontCollection.TryGetGlyphTypeface("Noto Mono", FontStyle.Normal, FontWeight.Regular, FontStretch.Normal, out var glyphTypeface));
|
|
Assert.Equal("Noto Mono", glyphTypeface.FamilyName);
|
|
|
|
// Check if the FontManager can find the font
|
|
Assert.True(fontManager.TryGetGlyphTypeface(new Typeface("fonts:custom#Noto Mono"), out var glyphTypeface2));
|
|
Assert.Equal(glyphTypeface, glyphTypeface2);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private class CustomFontCollection(Uri key) : FontCollectionBase
|
|
{
|
|
public override Uri Key { get; } = key;
|
|
}
|
|
|
|
private record struct FontAssetInfo(string Path, string FamilyName, FontWeight Weight);
|
|
}
|
|
}
|
|
|