Skip to content

Introduce GlyphTypeface.FaceNames #18392

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
Mar 9, 2025
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
48 changes: 13 additions & 35 deletions src/Avalonia.Base/Media/Fonts/Tables/Name/NameTable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,25 @@
// Licensed under the Apache License, Version 2.0.
// Ported from: https://github.com/SixLabors/Fonts/blob/034a440aece357341fcc6b02db58ffbe153e54ef/src/SixLabors.Fonts

using System.Collections;
using System.Collections.Generic;
using System.IO;
using Avalonia.Utilities;

namespace Avalonia.Media.Fonts.Tables.Name
{
internal class NameTable
internal class NameTable : IEnumerable<NameRecord>
{
internal const string TableName = "name";
internal static readonly OpenTypeTag Tag = OpenTypeTag.Parse(TableName);

private readonly NameRecord[] _names;

internal NameTable(NameRecord[] names, IReadOnlyList<ushort> languages)
internal NameTable(NameRecord[] names)
{
_names = names;
Languages = languages;
}

public IReadOnlyList<ushort> Languages { get; }

/// <summary>
/// Gets the name of the font.
/// </summary>
Expand Down Expand Up @@ -133,22 +132,6 @@ public static NameTable Load(BigEndianBinaryReader reader)
}
}

//var languageNames = Array.Empty<StringLoader>();

//if (format == 1)
//{
// // Format 1 adds language data.
// var langCount = reader.ReadUInt16();
// languageNames = new StringLoader[langCount];

// for (var i = 0; i < langCount; i++)
// {
// languageNames[i] = StringLoader.Create(reader);

// strings.Add(languageNames[i]);
// }
//}

foreach (var readable in strings)
{
var readableStartOffset = stringOffset + readable.Offset;
Expand All @@ -158,22 +141,17 @@ public static NameTable Load(BigEndianBinaryReader reader)
readable.LoadValue(reader);
}

var cultures = new List<ushort>();

foreach (var nameRecord in names)
{
if (nameRecord.NameID != KnownNameIds.FontFamilyName || nameRecord.Platform != PlatformIDs.Windows || nameRecord.LanguageID == 0)
{
continue;
}
return new NameTable(names);
}

if (!cultures.Contains(nameRecord.LanguageID))
{
cultures.Add(nameRecord.LanguageID);
}
}
public IEnumerator<NameRecord> GetEnumerator()
{
return new ImmutableReadOnlyListStructEnumerator<NameRecord>(_names);
}

return new NameTable(names, cultures);
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}
6 changes: 6 additions & 0 deletions src/Avalonia.Base/Media/IGlyphTypeface2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,11 @@ internal interface IGlyphTypeface2 : IGlyphTypeface
/// Gets supported font features.
/// </summary>
IReadOnlyList<OpenTypeTag> SupportedFeatures { get; }

/// <summary>
/// Gets the localized face names.
/// <para>Keys are culture identifiers.</para>
/// </summary>
IReadOnlyDictionary<ushort, string> FaceNames { get; }
}
}
35 changes: 32 additions & 3 deletions src/Skia/Avalonia.Skia/GlyphTypefaceImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,25 +111,54 @@ public GlyphTypefaceImpl(SKTypeface typeface, FontSimulations fontSimulations)

if(_nameTable != null)
{
var familyNames = new Dictionary<ushort, string>(_nameTable.Languages.Count);
var familyNames = new Dictionary<ushort, string>(1);
var faceNames = new Dictionary<ushort, string>(1);

foreach (var language in _nameTable.Languages)
foreach (var nameRecord in _nameTable)
{
familyNames.Add(language, _nameTable.FontFamilyName(language));
if(nameRecord.NameID == KnownNameIds.FontFamilyName)
{
if (nameRecord.Platform != PlatformIDs.Windows || nameRecord.LanguageID == 0)
{
continue;
}

if (!familyNames.ContainsKey(nameRecord.LanguageID))
{
familyNames[nameRecord.LanguageID] = nameRecord.Value;
}
}

if(nameRecord.NameID == KnownNameIds.FontSubfamilyName)
{
if (nameRecord.Platform != PlatformIDs.Windows || nameRecord.LanguageID == 0)
{
continue;
}

if (!faceNames.ContainsKey(nameRecord.LanguageID))
{
faceNames[nameRecord.LanguageID] = nameRecord.Value;
}
}
}

FamilyNames = familyNames;
FaceNames = faceNames;
}
else
{
FamilyNames = new Dictionary<ushort, string> { { (ushort)CultureInfo.InvariantCulture.LCID, FamilyName } };
FaceNames = new Dictionary<ushort, string> { { (ushort)CultureInfo.InvariantCulture.LCID, Weight.ToString() } };
}
}

public string TypographicFamilyName { get; }

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

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

public IReadOnlyList<OpenTypeTag> SupportedFeatures
{
get
Expand Down
Loading