Browse Source

Only use IGlyphTypeface

pull/20304/head
Benedikt Stebner 4 months ago
parent
commit
c71db14859
  1. 24
      api/Avalonia.nupkg.xml
  2. 4
      samples/RenderDemo/Pages/GlyphRunPage.xaml.cs
  3. 4
      samples/TextTestApp/MainWindow.axaml.cs
  4. 4
      src/Avalonia.Base/Media/FontManager.cs
  5. 46
      src/Avalonia.Base/Media/Fonts/FontCollectionBase.cs
  6. 16
      src/Avalonia.Base/Media/Fonts/IFontCollection.cs
  7. 31
      src/Avalonia.Base/Media/Fonts/SystemFontCollection.cs
  8. 8
      src/Avalonia.Base/Media/GlyphRun.cs
  9. 5
      src/Avalonia.Base/Media/IPlatformTypeface.cs
  10. 6
      src/Avalonia.Base/Media/TextFormatting/ShapedBuffer.cs
  11. 4
      src/Avalonia.Base/Media/TextFormatting/TextCharacters.cs
  12. 2
      src/Avalonia.Base/Media/TextFormatting/TextMetrics.cs
  13. 4
      src/Avalonia.Base/Media/TextFormatting/TextRunProperties.cs
  14. 6
      src/Avalonia.Base/Media/TextFormatting/TextShaperOptions.cs
  15. 2
      src/Avalonia.Base/Media/Typeface.cs
  16. 2
      src/Avalonia.Base/Rendering/Composition/Server/DiagnosticTextRenderer.cs
  17. 4
      src/Headless/Avalonia.Headless/HeadlessPlatformStubs.cs
  18. 2
      tests/Avalonia.Base.UnitTests/Media/GlyphTypefaceTests.cs
  19. 6
      tests/Avalonia.Skia.UnitTests/Media/EmbeddedFontCollectionTests.cs
  20. 6
      tests/Avalonia.Skia.UnitTests/Media/FontCollectionTests.cs
  21. 13
      tests/Avalonia.Skia.UnitTests/Media/FontManagerTests.cs

24
api/Avalonia.nupkg.xml

@ -703,6 +703,12 @@
<Left>baseline/Avalonia/lib/net10.0/Avalonia.Base.dll</Left>
<Right>current/Avalonia/lib/net10.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>M:Avalonia.Media.Fonts.IFontCollection.TryCreateSyntheticGlyphTypeface(Avalonia.Media.IGlyphTypeface,Avalonia.Media.FontStyle,Avalonia.Media.FontWeight,Avalonia.Media.FontStretch,Avalonia.Media.IGlyphTypeface@)</Target>
<Left>baseline/Avalonia/lib/net10.0/Avalonia.Base.dll</Left>
<Right>current/Avalonia/lib/net10.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>M:Avalonia.Media.Fonts.IFontCollection.TryGetFamilyTypefaces(System.String,System.Collections.Generic.IReadOnlyList{Avalonia.Media.Typeface}@)</Target>
@ -721,6 +727,12 @@
<Left>baseline/Avalonia/lib/net10.0/Avalonia.Base.dll</Left>
<Right>current/Avalonia/lib/net10.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>M:Avalonia.Media.Fonts.IFontCollection.TryGetNearestMatch(System.String,Avalonia.Media.FontStyle,Avalonia.Media.FontWeight,Avalonia.Media.FontStretch,Avalonia.Media.IGlyphTypeface@)</Target>
<Left>baseline/Avalonia/lib/net10.0/Avalonia.Base.dll</Left>
<Right>current/Avalonia/lib/net10.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>M:Avalonia.Media.IGlyphTypeface.GetGlyphAdvance(System.UInt16)</Target>
@ -961,6 +973,12 @@
<Left>baseline/Avalonia/lib/net8.0/Avalonia.Base.dll</Left>
<Right>current/Avalonia/lib/net8.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>M:Avalonia.Media.Fonts.IFontCollection.TryCreateSyntheticGlyphTypeface(Avalonia.Media.IGlyphTypeface,Avalonia.Media.FontStyle,Avalonia.Media.FontWeight,Avalonia.Media.FontStretch,Avalonia.Media.IGlyphTypeface@)</Target>
<Left>baseline/Avalonia/lib/net8.0/Avalonia.Base.dll</Left>
<Right>current/Avalonia/lib/net8.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>M:Avalonia.Media.Fonts.IFontCollection.TryGetFamilyTypefaces(System.String,System.Collections.Generic.IReadOnlyList{Avalonia.Media.Typeface}@)</Target>
@ -979,6 +997,12 @@
<Left>baseline/Avalonia/lib/net8.0/Avalonia.Base.dll</Left>
<Right>current/Avalonia/lib/net8.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>M:Avalonia.Media.Fonts.IFontCollection.TryGetNearestMatch(System.String,Avalonia.Media.FontStyle,Avalonia.Media.FontWeight,Avalonia.Media.FontStretch,Avalonia.Media.IGlyphTypeface@)</Target>
<Left>baseline/Avalonia/lib/net8.0/Avalonia.Base.dll</Left>
<Right>current/Avalonia/lib/net8.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>M:Avalonia.Media.IGlyphTypeface.GetGlyphAdvance(System.UInt16)</Target>

4
samples/RenderDemo/Pages/GlyphRunPage.xaml.cs

@ -22,7 +22,7 @@ namespace RenderDemo.Pages
public class GlyphRunControl : Control
{
private GlyphTypeface _glyphTypeface = Typeface.Default.GlyphTypeface;
private IGlyphTypeface _glyphTypeface = Typeface.Default.GlyphTypeface;
private readonly Random _rand = new Random();
private ushort[] _glyphIndices = new ushort[1];
private char[] _characters = new char[1];
@ -81,7 +81,7 @@ namespace RenderDemo.Pages
public class GlyphRunGeometryControl : Control
{
private GlyphTypeface _glyphTypeface = Typeface.Default.GlyphTypeface;
private IGlyphTypeface _glyphTypeface = Typeface.Default.GlyphTypeface;
private readonly Random _rand = new Random();
private ushort[] _glyphIndices = new ushort[1];
private char[] _characters = new char[1];

4
samples/TextTestApp/MainWindow.axaml.cs

@ -223,12 +223,12 @@ namespace TextTestApp
}
}
private IImage CreateGlyphDrawing(GlyphTypeface glyphTypeface, double emSize, GlyphInfo info)
private IImage CreateGlyphDrawing(IGlyphTypeface glyphTypeface, double emSize, GlyphInfo info)
{
return new DrawingImage { Drawing = new GeometryDrawing { Brush = Brushes.Black, Geometry = GetGlyphOutline(glyphTypeface, emSize, info) } };
}
private Geometry GetGlyphOutline(GlyphTypeface typeface, double emSize, GlyphInfo info)
private Geometry GetGlyphOutline(IGlyphTypeface typeface, double emSize, GlyphInfo info)
{
// substitute for GlyphTypeface.GetGlyphOutline
return new GlyphRun(typeface, emSize, new[] { '\0' }, [info]).BuildGeometry();

4
src/Avalonia.Base/Media/FontManager.cs

@ -98,7 +98,7 @@ namespace Avalonia.Media
/// <returns>
/// <c>True</c>, if the <see cref="FontManager"/> could create the glyph typeface, <c>False</c> otherwise.
/// </returns>
public bool TryGetGlyphTypeface(Typeface typeface, [NotNullWhen(true)] out GlyphTypeface? glyphTypeface)
public bool TryGetGlyphTypeface(Typeface typeface, [NotNullWhen(true)] out IGlyphTypeface? glyphTypeface)
{
glyphTypeface = null;
@ -187,7 +187,7 @@ namespace Avalonia.Media
}
}
private bool TryGetGlyphTypefaceByKeyAndName(Typeface typeface, FontFamilyKey key, string familyName, [NotNullWhen(true)] out GlyphTypeface? glyphTypeface)
private bool TryGetGlyphTypefaceByKeyAndName(Typeface typeface, FontFamilyKey key, string familyName, [NotNullWhen(true)] out IGlyphTypeface? glyphTypeface)
{
var source = key.Source.EnsureAbsolute(key.BaseUri);

46
src/Avalonia.Base/Media/Fonts/FontCollectionBase.cs

@ -15,7 +15,7 @@ namespace Avalonia.Media.Fonts
Comparer<FontFamily>.Create((a, b) => string.Compare(a.Name, b.Name, StringComparison.OrdinalIgnoreCase));
// Make this internal for testing purposes
internal readonly ConcurrentDictionary<string, ConcurrentDictionary<FontCollectionKey, GlyphTypeface?>> _glyphTypefaceCache = new();
internal readonly ConcurrentDictionary<string, ConcurrentDictionary<FontCollectionKey, IGlyphTypeface?>> _glyphTypefaceCache = new();
private readonly object _fontFamiliesLock = new();
private volatile FontFamily[] _fontFamilies = Array.Empty<FontFamily>();
@ -87,11 +87,11 @@ namespace Avalonia.Media.Fonts
}
public virtual bool TryCreateSyntheticGlyphTypeface(
GlyphTypeface glyphTypeface,
IGlyphTypeface glyphTypeface,
FontStyle style,
FontWeight weight,
FontStretch stretch,
[NotNullWhen(true)] out GlyphTypeface? syntheticGlyphTypeface)
[NotNullWhen(true)] out IGlyphTypeface? syntheticGlyphTypeface)
{
syntheticGlyphTypeface = null;
@ -154,7 +154,7 @@ namespace Avalonia.Media.Fonts
public IEnumerator<FontFamily> GetEnumerator() => ((IEnumerable<FontFamily>)_fontFamilies).GetEnumerator();
public virtual bool TryGetGlyphTypeface(string familyName, FontStyle style, FontWeight weight,
FontStretch stretch, [NotNullWhen(true)] out GlyphTypeface? glyphTypeface)
FontStretch stretch, [NotNullWhen(true)] out IGlyphTypeface? glyphTypeface)
{
var typeface = new Typeface(familyName, style, weight, stretch).Normalize(out familyName);
@ -189,7 +189,7 @@ namespace Avalonia.Media.Fonts
return false;
}
public bool TryGetNearestMatch(string familyName, FontStyle style, FontWeight weight, FontStretch stretch, [NotNullWhen(true)] out GlyphTypeface? glyphTypeface)
public bool TryGetNearestMatch(string familyName, FontStyle style, FontWeight weight, FontStretch stretch, [NotNullWhen(true)] out IGlyphTypeface? glyphTypeface)
{
if (!_glyphTypefaceCache.TryGetValue(familyName, out var glyphTypefaces))
{
@ -206,15 +206,15 @@ namespace Avalonia.Media.Fonts
/// <summary>
/// Attempts to add the specified <see cref="IGlyphTypeface"/> to the font collection.
/// </summary>
/// <remarks>This method checks the <see cref="GlyphTypeface.FamilyName"/> and, if applicable,
/// the typographic family name and other family names provided by the <see cref="GlyphTypeface"/> interface.
/// <remarks>This method checks the <see cref="IGlyphTypeface.FamilyName"/> and, if applicable,
/// the typographic family name and other family names provided by the <see cref="IGlyphTypeface"/> interface.
/// If any of these names can be associated with the glyph typeface, the typeface is added to the collection.
/// The method ensures that duplicate entries are not added.</remarks>
/// <param name="glyphTypeface">The glyph typeface to add. Must not be <see langword="null"/> and must have a non-empty <see
/// cref="IGlyphTypeface.FamilyName"/>.</param>
/// <returns><see langword="true"/> if the glyph typeface was successfully added to the collection; otherwise, <see
/// langword="false"/>.</returns>
public bool TryAddGlyphTypeface(GlyphTypeface glyphTypeface)
public bool TryAddGlyphTypeface(IGlyphTypeface glyphTypeface)
{
if (glyphTypeface == null || string.IsNullOrEmpty(glyphTypeface.FamilyName))
{
@ -263,7 +263,7 @@ namespace Avalonia.Media.Fonts
/// succeeds; otherwise, <see langword="null"/>.</param>
/// <returns><see langword="true"/> if the glyph typeface was successfully created and added; otherwise, <see
/// langword="false"/>.</returns>
public bool TryAddGlyphTypeface(Stream stream, [NotNullWhen(true)] out GlyphTypeface? glyphTypeface)
public bool TryAddGlyphTypeface(Stream stream, [NotNullWhen(true)] out IGlyphTypeface? glyphTypeface)
{
glyphTypeface = null;
@ -272,7 +272,7 @@ namespace Avalonia.Media.Fonts
return false;
}
glyphTypeface = new GlyphTypeface(platformTypeface, FontSimulations.None);
glyphTypeface = new GlyphTypeface(platformTypeface);
return TryAddGlyphTypeface(glyphTypeface);
}
@ -313,7 +313,7 @@ namespace Avalonia.Media.Fonts
continue;
}
var glyphTypeface = new GlyphTypeface(platformTypeface, FontSimulations.None);
var glyphTypeface = new GlyphTypeface(platformTypeface);
var key = glyphTypeface.ToFontCollectionKey();
@ -348,7 +348,7 @@ namespace Avalonia.Media.Fonts
if (_fontManagerImpl.TryCreateGlyphTypeface(stream, FontSimulations.None, out var platformTypeface))
{
var glyphTypeface = new GlyphTypeface(platformTypeface, FontSimulations.None);
var glyphTypeface = new GlyphTypeface(platformTypeface);
if (TryAddGlyphTypeface(glyphTypeface))
{
@ -372,7 +372,7 @@ namespace Avalonia.Media.Fonts
if (_fontManagerImpl.TryCreateGlyphTypeface(stream, FontSimulations.None, out var platformTypeface))
{
var glyphTypeface = new GlyphTypeface(platformTypeface, FontSimulations.None);
var glyphTypeface = new GlyphTypeface(platformTypeface);
if (TryAddGlyphTypeface(glyphTypeface))
{
@ -452,7 +452,7 @@ namespace Avalonia.Media.Fonts
/// <param name="glyphTypeface">When this method returns, contains the matching <see cref="IGlyphTypeface"/> if a match is found; otherwise,
/// <see langword="null"/>.</param>
/// <returns><see langword="true"/> if a matching glyph typeface is found; otherwise, <see langword="false"/>.</returns>
protected bool TryGetGlyphTypeface(string familyName, FontCollectionKey key, [NotNullWhen(true)] out GlyphTypeface? glyphTypeface)
protected bool TryGetGlyphTypeface(string familyName, FontCollectionKey key, [NotNullWhen(true)] out IGlyphTypeface? glyphTypeface)
{
glyphTypeface = null;
@ -558,7 +558,8 @@ namespace Avalonia.Media.Fonts
/// provided collection of glyph typefaces.
/// </summary>
/// <remarks>This method attempts to find the best match for the specified font key by considering
/// various fallback strategies, such as normalizing the font style, stretch, and weight. If no suitable match is found, the method will return the first available non-null <see cref="IGlyphTypeface"/> from the
/// various fallback strategies, such as normalizing the font style, stretch, and weight.
/// If no suitable match is found, the method will return the first available non-null <see cref="IGlyphTypeface"/> from the
/// collection, if any.</remarks>
/// <param name="glyphTypefaces">A collection of glyph typefaces, indexed by <see cref="FontCollectionKey"/>.</param>
/// <param name="key">The <see cref="FontCollectionKey"/> representing the desired font attributes.</param>
@ -566,7 +567,8 @@ namespace Avalonia.Media.Fonts
/// key, if a match is found; otherwise, <see langword="null"/>.</param>
/// <returns><see langword="true"/> if a matching <see cref="IGlyphTypeface"/> is found; otherwise, <see
/// langword="false"/>.</returns>
protected bool TryGetNearestMatch(IDictionary<FontCollectionKey, GlyphTypeface?> glyphTypefaces, FontCollectionKey key, [NotNullWhen(true)] out GlyphTypeface? glyphTypeface)
protected bool TryGetNearestMatch(IDictionary<FontCollectionKey, IGlyphTypeface?> glyphTypefaces,
FontCollectionKey key, [NotNullWhen(true)] out IGlyphTypeface? glyphTypeface)
{
if (glyphTypefaces.TryGetValue(key, out glyphTypeface) && glyphTypeface != null)
{
@ -631,7 +633,7 @@ namespace Avalonia.Media.Fonts
/// <param name="glyphTypeface">The glyph typeface to add to the cache. Can be null.</param>
/// <returns><see langword="true"/> if the glyph typeface was successfully added to the cache; otherwise, <see
/// langword="false"/>.</returns>
protected bool TryAddGlyphTypeface(string familyName, FontCollectionKey key, GlyphTypeface? glyphTypeface)
protected bool TryAddGlyphTypeface(string familyName, FontCollectionKey key, IGlyphTypeface? glyphTypeface)
{
if (string.IsNullOrEmpty(familyName))
{
@ -655,7 +657,7 @@ namespace Avalonia.Media.Fonts
}
// Family doesn't exist yet. Create a new dictionary instance and try to install it.
var newDict = new ConcurrentDictionary<FontCollectionKey, GlyphTypeface?>();
var newDict = new ConcurrentDictionary<FontCollectionKey, IGlyphTypeface?>();
// GetOrAdd will return the instance that ended up in the dictionary. If it's our
// newDict instance then we won the race to add the family and should publish it.
@ -697,9 +699,9 @@ namespace Avalonia.Media.Fonts
/// null.</param>
/// <returns>true if a suitable fallback glyph typeface is found; otherwise, false.</returns>
private static bool TryFindStretchFallback(
IDictionary<FontCollectionKey, GlyphTypeface?> glyphTypefaces,
IDictionary<FontCollectionKey, IGlyphTypeface?> glyphTypefaces,
FontCollectionKey key,
[NotNullWhen(true)] out GlyphTypeface? glyphTypeface)
[NotNullWhen(true)] out IGlyphTypeface? glyphTypeface)
{
glyphTypeface = null;
@ -744,9 +746,9 @@ namespace Avalonia.Media.Fonts
/// null.</param>
/// <returns>true if a fallback glyph typeface matching the requested weight is found; otherwise, false.</returns>
private static bool TryFindWeightFallback(
IDictionary<FontCollectionKey, GlyphTypeface?> glyphTypefaces,
IDictionary<FontCollectionKey, IGlyphTypeface?> glyphTypefaces,
FontCollectionKey key,
[NotNullWhen(true)] out GlyphTypeface? glyphTypeface)
[NotNullWhen(true)] out IGlyphTypeface? glyphTypeface)
{
glyphTypeface = null;
var weight = (int)key.Weight;

16
src/Avalonia.Base/Media/Fonts/IFontCollection.cs

@ -5,6 +5,12 @@ using System.Globalization;
namespace Avalonia.Media.Fonts
{
/// <summary>
/// Represents a collection of font families and provides methods for querying and managing font typefaces
/// within the collection.
/// </summary>
/// <remarks>Implementations of this interface allow applications to retrieve font families, match
/// characters to typefaces, and obtain glyph typefaces based on specific font properties.</remarks>
public interface IFontCollection : IReadOnlyList<FontFamily>, IDisposable
{
/// <summary>
@ -22,7 +28,7 @@ namespace Avalonia.Media.Fonts
/// <param name="glyphTypeface">The glyph typeface.</param>
/// <returns>Returns <c>true</c> if a glyph typface can be found; otherwise, <c>false</c></returns>
bool TryGetGlyphTypeface(string familyName, FontStyle style, FontWeight weight,
FontStretch stretch, [NotNullWhen(true)] out GlyphTypeface? glyphTypeface);
FontStretch stretch, [NotNullWhen(true)] out IGlyphTypeface? glyphTypeface);
/// <summary>
/// Tries to match a specified character to a <see cref="Typeface"/> that supports specified font properties.
@ -59,7 +65,8 @@ namespace Avalonia.Media.Fonts
/// <param name="stretch">The font stretch.</param>
/// <param name="syntheticGlyphTypeface"></param>
/// <returns>Returns <c>true</c> if a synthetic glyph typface can be created; otherwise, <c>false</c></returns>
bool TryCreateSyntheticGlyphTypeface(GlyphTypeface glyphTypeface, FontStyle style, FontWeight weight, FontStretch stretch, [NotNullWhen(true)] out GlyphTypeface? syntheticGlyphTypeface);
bool TryCreateSyntheticGlyphTypeface(IGlyphTypeface glyphTypeface, FontStyle style, FontWeight weight, FontStretch stretch,
[NotNullWhen(true)] out IGlyphTypeface? syntheticGlyphTypeface);
/// <summary>
/// Attempts to retrieve the glyph typeface that most closely matches the specified font family name, style,
@ -74,9 +81,10 @@ namespace Avalonia.Media.Fonts
/// <param name="style">The desired font style.</param>
/// <param name="weight">The desired font weight.</param>
/// <param name="stretch">The desired font stretch.</param>
/// <param name="glyphTypeface">When this method returns, contains the <see cref="GlyphTypeface"/> that most closely matches the specified
/// <param name="glyphTypeface">When this method returns, contains the <see cref="IGlyphTypeface"/> that most closely matches the specified
/// parameters, if a match is found; otherwise, <see langword="null"/>. This parameter is passed uninitialized.</param>
/// <returns><see langword="true"/> if a matching glyph typeface is found; otherwise, <see langword="false"/>.</returns>
bool TryGetNearestMatch(string familyName, FontStyle style, FontWeight weight, FontStretch stretch, [NotNullWhen(true)] out GlyphTypeface? glyphTypeface);
bool TryGetNearestMatch(string familyName, FontStyle style, FontWeight weight, FontStretch stretch,
[NotNullWhen(true)] out IGlyphTypeface? glyphTypeface);
}
}

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

@ -26,7 +26,7 @@ namespace Avalonia.Media.Fonts
public override Uri Key => FontManager.SystemFontsKey;
public override bool TryGetGlyphTypeface(string familyName, FontStyle style, FontWeight weight,
FontStretch stretch, [NotNullWhen(true)] out GlyphTypeface? glyphTypeface)
FontStretch stretch, [NotNullWhen(true)] out IGlyphTypeface? glyphTypeface)
{
var typeface = new Typeface(familyName, style, weight, stretch).Normalize(out familyName);
@ -86,13 +86,34 @@ namespace Avalonia.Media.Fonts
if (_platformImpl.TryMatchCharacter(codepoint, style, weight, stretch, familyName, culture, out var platformTypeface))
{
var glyphTypeface = new GlyphTypeface(platformTypeface);
// Construct the resulting Typeface
match = new Typeface(platformTypeface.FamilyName, platformTypeface.Style, platformTypeface.Weight,
platformTypeface.Stretch);
// Add to cache if not already present
return TryAddGlyphTypeface(glyphTypeface);
// Compute the key for cache lookup this can be different from the requested key
var key = match.ToFontCollectionKey();
// Check cache first: if an entry exists and is non-null, match succeeded and we can return true.
if (_glyphTypefaceCache.TryGetValue(platformTypeface.FamilyName, out var glyphTypefaces) && glyphTypefaces.TryGetValue(key, out var existing))
{
return existing != null;
}
// Not in cache yet: create glyph typeface and try to add it.
var glyphTypeface = new GlyphTypeface(platformTypeface);
if (TryAddGlyphTypeface(platformTypeface.FamilyName, key, glyphTypeface))
{
return true;
}
// TryAddGlyphTypeface failed: another thread may have added an entry. Re-check the cache.
if (_glyphTypefaceCache.TryGetValue(platformTypeface.FamilyName, out glyphTypefaces) && glyphTypefaces.TryGetValue(key, out existing))
{
return existing != null;
}
return false;
}
return false;

8
src/Avalonia.Base/Media/GlyphRun.cs

@ -39,7 +39,7 @@ namespace Avalonia.Media
/// <param name="baselineOrigin">The baseline origin of the run.</param>
/// <param name="biDiLevel">The bidi level.</param>
public GlyphRun(
GlyphTypeface glyphTypeface,
IGlyphTypeface glyphTypeface,
double fontRenderingEmSize,
ReadOnlyMemory<char> characters,
IReadOnlyList<ushort> glyphIndices,
@ -61,7 +61,7 @@ namespace Avalonia.Media
/// <param name="baselineOrigin">The baseline origin of the run.</param>
/// <param name="biDiLevel">The bidi level.</param>
public GlyphRun(
GlyphTypeface glyphTypeface,
IGlyphTypeface glyphTypeface,
double fontRenderingEmSize,
ReadOnlyMemory<char> characters,
IReadOnlyList<GlyphInfo> glyphInfos,
@ -90,7 +90,7 @@ namespace Avalonia.Media
}
private static IReadOnlyList<GlyphInfo> CreateGlyphInfos(IReadOnlyList<ushort> glyphIndices,
double fontRenderingEmSize, GlyphTypeface glyphTypeface)
double fontRenderingEmSize, IGlyphTypeface glyphTypeface)
{
var glyphIndexSpan = ListToSpan(glyphIndices);
@ -142,7 +142,7 @@ namespace Avalonia.Media
/// <summary>
/// Gets the <see cref="GlyphTypeface"/> for the <see cref="GlyphRun"/>.
/// </summary>
public GlyphTypeface GlyphTypeface { get; }
public IGlyphTypeface GlyphTypeface { get; }
/// <summary>
/// Gets or sets the em size used for rendering the <see cref="GlyphRun"/>.

5
src/Avalonia.Base/Media/IPlatformTypeface.cs

@ -31,6 +31,11 @@ namespace Avalonia.Media
/// </summary>
FontStretch Stretch { get; }
/// <summary>
/// Gets the algorithmic style simulations applied to <see cref="IPlatformTypeface"/> object.
/// </summary>
FontSimulations FontSimulations { get; }
/// <summary>
/// Returns the font file stream represented by the <see cref="IGlyphTypeface"/>.
/// </summary>

6
src/Avalonia.Base/Media/TextFormatting/ShapedBuffer.cs

@ -13,7 +13,7 @@ namespace Avalonia.Media.TextFormatting
private GlyphInfo[]? _rentedBuffer;
private ArraySlice<GlyphInfo> _glyphInfos;
public ShapedBuffer(ReadOnlyMemory<char> text, int bufferLength, GlyphTypeface glyphTypeface, double fontRenderingEmSize, sbyte bidiLevel)
public ShapedBuffer(ReadOnlyMemory<char> text, int bufferLength, IGlyphTypeface glyphTypeface, double fontRenderingEmSize, sbyte bidiLevel)
{
Text = text;
_rentedBuffer = ArrayPool<GlyphInfo>.Shared.Rent(bufferLength);
@ -23,7 +23,7 @@ namespace Avalonia.Media.TextFormatting
BidiLevel = bidiLevel;
}
internal ShapedBuffer(ReadOnlyMemory<char> text, ArraySlice<GlyphInfo> glyphInfos, GlyphTypeface glyphTypeface, double fontRenderingEmSize, sbyte bidiLevel)
internal ShapedBuffer(ReadOnlyMemory<char> text, ArraySlice<GlyphInfo> glyphInfos, IGlyphTypeface glyphTypeface, double fontRenderingEmSize, sbyte bidiLevel)
{
Text = text;
_glyphInfos = glyphInfos;
@ -40,7 +40,7 @@ namespace Avalonia.Media.TextFormatting
/// <summary>
/// The buffer's glyph typeface.
/// </summary>
public GlyphTypeface GlyphTypeface { get; }
public IGlyphTypeface GlyphTypeface { get; }
/// <summary>
/// The buffers font rendering em size.

4
src/Avalonia.Base/Media/TextFormatting/TextCharacters.cs

@ -167,8 +167,8 @@ namespace Avalonia.Media.TextFormatting
/// <returns></returns>
internal static bool TryGetShapeableLength(
ReadOnlySpan<char> text,
GlyphTypeface glyphTypeface,
GlyphTypeface? defaultGlyphTypeface,
IGlyphTypeface glyphTypeface,
IGlyphTypeface? defaultGlyphTypeface,
out int length)
{
length = 0;

2
src/Avalonia.Base/Media/TextFormatting/TextMetrics.cs

@ -5,7 +5,7 @@
/// </summary>
public readonly record struct TextMetrics
{
public TextMetrics(GlyphTypeface glyphTypeface, double fontRenderingEmSize)
public TextMetrics(IGlyphTypeface glyphTypeface, double fontRenderingEmSize)
{
var fontMetrics = glyphTypeface.Metrics;

4
src/Avalonia.Base/Media/TextFormatting/TextRunProperties.cs

@ -12,7 +12,7 @@ namespace Avalonia.Media.TextFormatting
/// </remarks>
public abstract class TextRunProperties : IEquatable<TextRunProperties>
{
private GlyphTypeface? _cachedGlyphTypeFace;
private IGlyphTypeface? _cachedGlyphTypeFace;
/// <summary>
/// Run typeface
@ -54,7 +54,7 @@ namespace Avalonia.Media.TextFormatting
/// </summary>
public virtual BaselineAlignment BaselineAlignment => BaselineAlignment.Baseline;
internal GlyphTypeface CachedGlyphTypeface
internal IGlyphTypeface CachedGlyphTypeface
=> _cachedGlyphTypeFace ??= Typeface.GlyphTypeface;
public bool Equals(TextRunProperties? other)

6
src/Avalonia.Base/Media/TextFormatting/TextShaperOptions.cs

@ -10,7 +10,7 @@ namespace Avalonia.Media.TextFormatting
{
// TODO12: Remove in 12.0.0 and make fontFeatures parameter in main ctor optional
public TextShaperOptions(
GlyphTypeface typeface,
IGlyphTypeface typeface,
double fontRenderingEmSize = 12,
sbyte bidiLevel = 0,
CultureInfo? culture = null,
@ -22,7 +22,7 @@ namespace Avalonia.Media.TextFormatting
// TODO12:Change signature in 12.0.0
public TextShaperOptions(
GlyphTypeface typeface,
IGlyphTypeface typeface,
IReadOnlyList<FontFeature>? fontFeatures,
double fontRenderingEmSize = 12,
sbyte bidiLevel = 0,
@ -42,7 +42,7 @@ namespace Avalonia.Media.TextFormatting
/// <summary>
/// Get the typeface.
/// </summary>
public GlyphTypeface GlyphTypeface { get; }
public IGlyphTypeface GlyphTypeface { get; }
/// <summary>
/// Get the font rendering em size.
/// </summary>

2
src/Avalonia.Base/Media/Typeface.cs

@ -83,7 +83,7 @@ namespace Avalonia.Media
/// <value>
/// The glyph typeface.
/// </value>
public GlyphTypeface GlyphTypeface
public IGlyphTypeface GlyphTypeface
{
get
{

2
src/Avalonia.Base/Rendering/Composition/Server/DiagnosticTextRenderer.cs

@ -29,7 +29,7 @@ namespace Avalonia.Rendering.Composition.Server
return maxHeight;
}
public DiagnosticTextRenderer(GlyphTypeface glyphTypeface, double fontRenderingEmSize)
public DiagnosticTextRenderer(IGlyphTypeface glyphTypeface, double fontRenderingEmSize)
{
var chars = new char[LastChar - FirstChar + 1];
for (var c = FirstChar; c <= LastChar; c++)

4
src/Headless/Avalonia.Headless/HeadlessPlatformStubs.cs

@ -76,7 +76,7 @@ namespace Avalonia.Headless
{
_fontMemory = UnmanagedFontMemory.LoadFromStream(stream);
var dummy = new GlyphTypeface(this, FontSimulations.None);
var dummy = new GlyphTypeface(this);
FamilyName = familyName;
Weight = dummy.Weight;
@ -92,6 +92,8 @@ namespace Avalonia.Headless
public FontStretch Stretch { get; }
public FontSimulations FontSimulations => FontSimulations.None;
public void Dispose()
{
_fontMemory.Dispose();

2
tests/Avalonia.Base.UnitTests/Media/GlyphTypefaceTests.cs

@ -90,6 +90,8 @@ namespace Avalonia.Base.UnitTests.Media
public string FamilyName { get; }
public FontSimulations FontSimulations => FontSimulations.None;
public void Dispose()
{
_fontMemory.Dispose();

6
tests/Avalonia.Skia.UnitTests/Media/EmbeddedFontCollectionTests.cs

@ -139,14 +139,14 @@ namespace Avalonia.Skia.UnitTests.Media
_createSyntheticTypefaces = createSyntheticTypefaces;
}
public IDictionary<string, ConcurrentDictionary<FontCollectionKey, GlyphTypeface?>> GlyphTypefaceCache => _glyphTypefaceCache;
public IDictionary<string, ConcurrentDictionary<FontCollectionKey, IGlyphTypeface?>> GlyphTypefaceCache => _glyphTypefaceCache;
public override bool TryCreateSyntheticGlyphTypeface(
GlyphTypeface glyphTypeface,
IGlyphTypeface glyphTypeface,
FontStyle style,
FontWeight weight,
FontStretch stretch,
[NotNullWhen(true)] out GlyphTypeface? syntheticGlyphTypeface)
[NotNullWhen(true)] out IGlyphTypeface? syntheticGlyphTypeface)
{
if (!_createSyntheticTypefaces)
{

6
tests/Avalonia.Skia.UnitTests/Media/FontCollectionTests.cs

@ -45,7 +45,7 @@ namespace Avalonia.Skia.UnitTests.Media
{
}
public IDictionary<string, ConcurrentDictionary<FontCollectionKey, GlyphTypeface?>> GlyphTypefaceCache => _glyphTypefaceCache;
public IDictionary<string, ConcurrentDictionary<FontCollectionKey, IGlyphTypeface?>> GlyphTypefaceCache => _glyphTypefaceCache;
}
[Fact]
@ -126,11 +126,11 @@ namespace Avalonia.Skia.UnitTests.Media
}
public override bool TryCreateSyntheticGlyphTypeface(
GlyphTypeface glyphTypeface,
IGlyphTypeface glyphTypeface,
FontStyle style,
FontWeight weight,
FontStretch stretch,
[NotNullWhen(true)] out GlyphTypeface? syntheticGlyphTypeface)
[NotNullWhen(true)] out IGlyphTypeface? syntheticGlyphTypeface)
{
syntheticGlyphTypeface = null;

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

@ -313,13 +313,18 @@ namespace Avalonia.Skia.UnitTests.Media
new Uri(s_fontUri, UriKind.Absolute)));
Assert.True(FontManager.Current.TryGetGlyphTypeface(new Typeface("Noto Mono", FontStyle.Italic, FontWeight.Bold),
out var glyphTypeface));
out var italicBoldTypeface));
Assert.Equal("Noto Mono", glyphTypeface.FamilyName);
Assert.Equal("Noto Mono", italicBoldTypeface.FamilyName);
Assert.Equal(FontWeight.Bold, glyphTypeface.Weight);
Assert.True(italicBoldTypeface.PlatformTypeface.FontSimulations.HasFlag(FontSimulations.Bold));
Assert.Equal(FontStyle.Italic, glyphTypeface.Style);
Assert.True(italicBoldTypeface.PlatformTypeface.FontSimulations.HasFlag(FontSimulations.Oblique));
Assert.True(FontManager.Current.TryGetGlyphTypeface(new Typeface("Noto Mono", FontStyle.Normal, FontWeight.Normal),
out var regularTypeface));
Assert.NotEqual(((SkiaTypeface)regularTypeface.PlatformTypeface).SKTypeface, ((SkiaTypeface)italicBoldTypeface.PlatformTypeface).SKTypeface);
}
}
}

Loading…
Cancel
Save