Skip to content

Add TypographicFamilyName to GlyphTypeface and use it for FontCollection #16844

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Aug 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions src/Avalonia.Base/Media/Fonts/EmbeddedFontCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -131,11 +131,15 @@ private void AddGlyphTypeface(IGlyphTypeface glyphTypeface)
{
if (glyphTypeface is IGlyphTypeface2 glyphTypeface2)
{
foreach (var kvp in glyphTypeface2.FamilyNames)
//Add the TypographicFamilyName to the cache
if (!string.IsNullOrEmpty(glyphTypeface2.TypographicFamilyName))
{
var familyName = kvp.Value;
AddGlyphTypefaceByFamilyName(glyphTypeface2.TypographicFamilyName, glyphTypeface);
}

AddGlyphTypefaceByFamilyName(familyName, glyphTypeface);
foreach (var kvp in glyphTypeface2.FamilyNames)
{
AddGlyphTypefaceByFamilyName(kvp.Value, glyphTypeface);
}
}
else
Expand All @@ -150,7 +154,7 @@ void AddGlyphTypefaceByFamilyName(string familyName, IGlyphTypeface glyphTypefac
var typefaces = _glyphTypefaceCache.GetOrAdd(familyName,
x =>
{
_fontFamilies.Add(new FontFamily(_key, glyphTypeface.FamilyName));
_fontFamilies.Add(new FontFamily(_key, familyName));

return new ConcurrentDictionary<FontCollectionKey, IGlyphTypeface?>();
});
Expand Down
41 changes: 25 additions & 16 deletions src/Avalonia.Base/Media/Fonts/SystemFontCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -160,26 +160,35 @@ private void LoadGlyphTypefaces(IFontManagerImpl fontManager, Uri source)
{
var stream = assetLoader.Open(fontAsset);

if (fontManager.TryCreateGlyphTypeface(stream, FontSimulations.None, out var glyphTypeface))
if (!fontManager.TryCreateGlyphTypeface(stream, FontSimulations.None, out var glyphTypeface))
{
if (!_glyphTypefaceCache.TryGetValue(glyphTypeface.FamilyName, out var glyphTypefaces))
{
glyphTypefaces = new ConcurrentDictionary<FontCollectionKey, IGlyphTypeface?>();
continue;
}

if (_glyphTypefaceCache.TryAdd(glyphTypeface.FamilyName, glyphTypefaces))
{
//Move the user defined system font to the start of the collection
_familyNames.Insert(0, glyphTypeface.FamilyName);
}
}
//Add TypographicFamilyName to the cache
if (glyphTypeface is IGlyphTypeface2 glyphTypeface2 && !string.IsNullOrEmpty(glyphTypeface2.TypographicFamilyName))
{
AddGlyphTypefaceByFamilyName(glyphTypeface2.TypographicFamilyName, glyphTypeface);
}

AddGlyphTypefaceByFamilyName(glyphTypeface.FamilyName, glyphTypeface);
}

var key = new FontCollectionKey(
glyphTypeface.Style,
glyphTypeface.Weight,
glyphTypeface.Stretch);
return;

glyphTypefaces.TryAdd(key, glyphTypeface);
}
void AddGlyphTypefaceByFamilyName(string familyName, IGlyphTypeface glyphTypeface)
{
var typefaces = _glyphTypefaceCache.GetOrAdd(familyName,
x =>
{
_familyNames.Insert(0, familyName);

return new ConcurrentDictionary<FontCollectionKey, IGlyphTypeface?>();
});

typefaces.TryAdd(
new FontCollectionKey(glyphTypeface.Style, glyphTypeface.Weight, glyphTypeface.Stretch),
glyphTypeface);
}
}
}
Expand Down
5 changes: 5 additions & 0 deletions src/Avalonia.Base/Media/IGlyphTypeface2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ internal interface IGlyphTypeface2 : IGlyphTypeface
/// <returns>Returns <c>true</c> if the stream can be obtained, otherwise <c>false</c>.</returns>
bool TryGetStream([NotNullWhen(true)] out Stream? stream);

/// <summary>
/// Gets the typographic family name.
/// </summary>
string TypographicFamilyName { get; }

/// <summary>
/// Gets the localized family names.
/// <para>Keys are culture identifiers.</para>
Expand Down
4 changes: 4 additions & 0 deletions src/Skia/Avalonia.Skia/GlyphTypefaceImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ public GlyphTypefaceImpl(SKTypeface typeface, FontSimulations fontSimulations)

_nameTable = NameTable.Load(this);

TypographicFamilyName = _nameTable.GetNameById((ushort)CultureInfo.InvariantCulture.LCID, KnownNameIds.TypographicFamilyName);

FamilyName = _nameTable.FontFamilyName((ushort)CultureInfo.InvariantCulture.LCID);

var familyNames = new Dictionary<ushort, string>(_nameTable.Languages.Count);
Expand All @@ -112,6 +114,8 @@ public GlyphTypefaceImpl(SKTypeface typeface, FontSimulations fontSimulations)
FamilyNames = familyNames;
}

public string TypographicFamilyName { get; }

public IReadOnlyDictionary<ushort, string> FamilyNames { get; }

public IReadOnlyList<OpenTypeTag> SupportedFeatures
Expand Down
2 changes: 2 additions & 0 deletions tests/Avalonia.Skia.UnitTests/Avalonia.Skia.UnitTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
<ItemGroup>
<EmbeddedResource Include="..\Avalonia.RenderTests\*\*.ttf" />
<None Remove="Fonts\DejaVuSans.ttf" />
<None Remove="Fonts\Manrope-Light.ttf" />
<EmbeddedResource Include="Fonts\DejaVuSans.ttf" />
<EmbeddedResource Include="Fonts\Manrope-Light.ttf" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Avalonia.Base\Avalonia.Base.csproj" />
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ public class EmbeddedFontCollectionTests
{
private const string s_notoMono =
"resm:Avalonia.Skia.UnitTests.Assets?assembly=Avalonia.Skia.UnitTests#Noto Mono";


private const string s_manrope = "resm:Avalonia.Skia.UnitTests.Fonts?assembly=Avalonia.Skia.UnitTests#Manrope";

[InlineData(FontWeight.SemiLight, FontStyle.Normal)]
[InlineData(FontWeight.Bold, FontStyle.Italic)]
[InlineData(FontWeight.Heavy, FontStyle.Oblique)]
Expand Down Expand Up @@ -64,5 +66,28 @@ public void Should_Get_Typeface_For_Partial_FamilyName()
Assert.Equal("Twitter Color Emoji", glyphTypeface.FamilyName);
}
}

[Fact]
public void Should_Get_Typeface_For_TypographicFamilyName()
{
using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{
var source = new Uri(s_manrope, UriKind.Absolute);

var fontCollection = new EmbeddedFontCollection(source, source);

fontCollection.Initialize(new CustomFontManagerImpl());

Assert.True(fontCollection.TryGetGlyphTypeface("Manrope", FontStyle.Normal, FontWeight.Light, FontStretch.Normal, out var glyphTypeface));

Assert.Equal("Manrope Light", glyphTypeface.FamilyName);

Assert.True(glyphTypeface is IGlyphTypeface2);

var glyphTypeface2 = (IGlyphTypeface2)glyphTypeface;

Assert.Equal("Manrope", glyphTypeface2.TypographicFamilyName);
}
}
}
}
Loading