|
@@ -9,13 +9,13 @@ using Avalonia.Platform;
|
|
|
|
|
|
|
|
namespace Avalonia.Media.Fonts
|
|
namespace Avalonia.Media.Fonts
|
|
|
{
|
|
{
|
|
|
- public abstract class FontCollectionBase : IFontCollection2
|
|
|
|
|
|
|
+ public abstract class FontCollectionBase : IFontCollection
|
|
|
{
|
|
{
|
|
|
private static readonly Comparer<FontFamily> FontFamilyNameComparer =
|
|
private static readonly Comparer<FontFamily> FontFamilyNameComparer =
|
|
|
Comparer<FontFamily>.Create((a, b) => string.Compare(a.Name, b.Name, StringComparison.OrdinalIgnoreCase));
|
|
Comparer<FontFamily>.Create((a, b) => string.Compare(a.Name, b.Name, StringComparison.OrdinalIgnoreCase));
|
|
|
|
|
|
|
|
// Make this internal for testing purposes
|
|
// Make this internal for testing purposes
|
|
|
- internal readonly ConcurrentDictionary<string, ConcurrentDictionary<FontCollectionKey, IGlyphTypeface?>> _glyphTypefaceCache = new();
|
|
|
|
|
|
|
+ internal readonly ConcurrentDictionary<string, ConcurrentDictionary<FontCollectionKey, GlyphTypeface?>> _glyphTypefaceCache = new();
|
|
|
|
|
|
|
|
private readonly object _fontFamiliesLock = new();
|
|
private readonly object _fontFamiliesLock = new();
|
|
|
private volatile FontFamily[] _fontFamilies = Array.Empty<FontFamily>();
|
|
private volatile FontFamily[] _fontFamilies = Array.Empty<FontFamily>();
|
|
@@ -39,12 +39,14 @@ namespace Avalonia.Media.Fonts
|
|
|
{
|
|
{
|
|
|
match = default;
|
|
match = default;
|
|
|
|
|
|
|
|
|
|
+ var key = new FontCollectionKey { Style = style, Weight = weight, Stretch = stretch };
|
|
|
|
|
+
|
|
|
//If a font family is defined we try to find a match inside that family first
|
|
//If a font family is defined we try to find a match inside that family first
|
|
|
if (familyName != null && _glyphTypefaceCache.TryGetValue(familyName, out var glyphTypefaces))
|
|
if (familyName != null && _glyphTypefaceCache.TryGetValue(familyName, out var glyphTypefaces))
|
|
|
{
|
|
{
|
|
|
- if (TryGetNearestMatch(glyphTypefaces, new FontCollectionKey { Style = style, Weight = weight, Stretch = stretch }, out var glyphTypeface))
|
|
|
|
|
|
|
+ if (TryGetNearestMatch(glyphTypefaces, key, out var glyphTypeface))
|
|
|
{
|
|
{
|
|
|
- if (glyphTypeface.TryGetGlyph((uint)codepoint, out _))
|
|
|
|
|
|
|
+ if (glyphTypeface.CharacterToGlyphMap.TryGetGlyph(codepoint, out _))
|
|
|
{
|
|
{
|
|
|
match = new Typeface(new FontFamily(null, Key.AbsoluteUri + "#" + glyphTypeface.FamilyName), style, weight, stretch);
|
|
match = new Typeface(new FontFamily(null, Key.AbsoluteUri + "#" + glyphTypeface.FamilyName), style, weight, stretch);
|
|
|
|
|
|
|
@@ -64,15 +66,17 @@ namespace Avalonia.Media.Fonts
|
|
|
|
|
|
|
|
glyphTypefaces = pair.Value;
|
|
glyphTypefaces = pair.Value;
|
|
|
|
|
|
|
|
- if (TryGetNearestMatch(glyphTypefaces, new FontCollectionKey { Style = style, Weight = weight, Stretch = stretch }, out var glyphTypeface))
|
|
|
|
|
|
|
+ if (TryGetNearestMatch(glyphTypefaces, key, out var glyphTypeface))
|
|
|
{
|
|
{
|
|
|
- if (glyphTypeface.TryGetGlyph((uint)codepoint, out _))
|
|
|
|
|
|
|
+ if (glyphTypeface.CharacterToGlyphMap.TryGetGlyph(codepoint, out _))
|
|
|
{
|
|
{
|
|
|
|
|
+ var platformTypeface = glyphTypeface.PlatformTypeface;
|
|
|
|
|
+
|
|
|
// Found a match
|
|
// Found a match
|
|
|
- match = new Typeface(new FontFamily(null, Key.AbsoluteUri + "#" + glyphTypeface.FamilyName),
|
|
|
|
|
- glyphTypeface.Style,
|
|
|
|
|
- glyphTypeface.Weight,
|
|
|
|
|
- glyphTypeface.Stretch);
|
|
|
|
|
|
|
+ match = new Typeface(new FontFamily(null, Key.AbsoluteUri + "#" + glyphTypeface.FamilyName),
|
|
|
|
|
+ platformTypeface.Style,
|
|
|
|
|
+ platformTypeface.Weight,
|
|
|
|
|
+ platformTypeface.Stretch);
|
|
|
|
|
|
|
|
return true;
|
|
return true;
|
|
|
}
|
|
}
|
|
@@ -83,11 +87,11 @@ namespace Avalonia.Media.Fonts
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public virtual bool TryCreateSyntheticGlyphTypeface(
|
|
public virtual bool TryCreateSyntheticGlyphTypeface(
|
|
|
- IGlyphTypeface glyphTypeface,
|
|
|
|
|
|
|
+ GlyphTypeface glyphTypeface,
|
|
|
FontStyle style,
|
|
FontStyle style,
|
|
|
FontWeight weight,
|
|
FontWeight weight,
|
|
|
FontStretch stretch,
|
|
FontStretch stretch,
|
|
|
- [NotNullWhen(true)] out IGlyphTypeface? syntheticGlyphTypeface)
|
|
|
|
|
|
|
+ [NotNullWhen(true)] out GlyphTypeface? syntheticGlyphTypeface)
|
|
|
{
|
|
{
|
|
|
syntheticGlyphTypeface = null;
|
|
syntheticGlyphTypeface = null;
|
|
|
|
|
|
|
@@ -99,44 +103,40 @@ namespace Avalonia.Media.Fonts
|
|
|
|
|
|
|
|
var key = new FontCollectionKey(style, weight, stretch);
|
|
var key = new FontCollectionKey(style, weight, stretch);
|
|
|
|
|
|
|
|
- var currentKey =
|
|
|
|
|
- new FontCollectionKey(glyphTypeface.Style, glyphTypeface.Weight, glyphTypeface.Stretch);
|
|
|
|
|
-
|
|
|
|
|
|
|
+ var currentKey = glyphTypeface.ToFontCollectionKey();
|
|
|
|
|
+
|
|
|
if (currentKey == key)
|
|
if (currentKey == key)
|
|
|
{
|
|
{
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if (glyphTypeface is not IGlyphTypeface2 glyphTypeface2)
|
|
|
|
|
- {
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
var fontSimulations = FontSimulations.None;
|
|
var fontSimulations = FontSimulations.None;
|
|
|
|
|
|
|
|
- if (style != FontStyle.Normal && glyphTypeface2.Style != style)
|
|
|
|
|
|
|
+ if (style != FontStyle.Normal && glyphTypeface.Style != style)
|
|
|
{
|
|
{
|
|
|
fontSimulations |= FontSimulations.Oblique;
|
|
fontSimulations |= FontSimulations.Oblique;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if ((int)weight >= 600 && glyphTypeface2.Weight < weight)
|
|
|
|
|
|
|
+ if ((int)weight >= 600 && glyphTypeface.Weight < weight)
|
|
|
{
|
|
{
|
|
|
fontSimulations |= FontSimulations.Bold;
|
|
fontSimulations |= FontSimulations.Bold;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if (fontSimulations != FontSimulations.None && glyphTypeface2.TryGetStream(out var stream))
|
|
|
|
|
|
|
+ if (fontSimulations != FontSimulations.None && glyphTypeface.PlatformTypeface.TryGetStream(out var stream))
|
|
|
{
|
|
{
|
|
|
using (stream)
|
|
using (stream)
|
|
|
{
|
|
{
|
|
|
- if (_fontManagerImpl.TryCreateGlyphTypeface(stream, fontSimulations, out syntheticGlyphTypeface))
|
|
|
|
|
|
|
+ if (_fontManagerImpl.TryCreateGlyphTypeface(stream, fontSimulations, out var platformTypeface))
|
|
|
{
|
|
{
|
|
|
|
|
+ syntheticGlyphTypeface = new GlyphTypeface(platformTypeface, fontSimulations);
|
|
|
|
|
+
|
|
|
//Add the TypographicFamilyName to the cache
|
|
//Add the TypographicFamilyName to the cache
|
|
|
- if (!string.IsNullOrEmpty(glyphTypeface2.TypographicFamilyName))
|
|
|
|
|
|
|
+ if (!string.IsNullOrEmpty(glyphTypeface.TypographicFamilyName))
|
|
|
{
|
|
{
|
|
|
- TryAddGlyphTypeface(glyphTypeface2.TypographicFamilyName, key, syntheticGlyphTypeface);
|
|
|
|
|
|
|
+ TryAddGlyphTypeface(glyphTypeface.TypographicFamilyName, key, syntheticGlyphTypeface);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- foreach (var kvp in glyphTypeface2.FamilyNames)
|
|
|
|
|
|
|
+ foreach (var kvp in glyphTypeface.FamilyNames)
|
|
|
{
|
|
{
|
|
|
TryAddGlyphTypeface(kvp.Value, key, syntheticGlyphTypeface);
|
|
TryAddGlyphTypeface(kvp.Value, key, syntheticGlyphTypeface);
|
|
|
}
|
|
}
|
|
@@ -154,17 +154,11 @@ namespace Avalonia.Media.Fonts
|
|
|
public IEnumerator<FontFamily> GetEnumerator() => ((IEnumerable<FontFamily>)_fontFamilies).GetEnumerator();
|
|
public IEnumerator<FontFamily> GetEnumerator() => ((IEnumerable<FontFamily>)_fontFamilies).GetEnumerator();
|
|
|
|
|
|
|
|
public virtual bool TryGetGlyphTypeface(string familyName, FontStyle style, FontWeight weight,
|
|
public virtual bool TryGetGlyphTypeface(string familyName, FontStyle style, FontWeight weight,
|
|
|
- FontStretch stretch, [NotNullWhen(true)] out IGlyphTypeface? glyphTypeface)
|
|
|
|
|
|
|
+ FontStretch stretch, [NotNullWhen(true)] out GlyphTypeface? glyphTypeface)
|
|
|
{
|
|
{
|
|
|
var typeface = new Typeface(familyName, style, weight, stretch).Normalize(out familyName);
|
|
var typeface = new Typeface(familyName, style, weight, stretch).Normalize(out familyName);
|
|
|
|
|
|
|
|
- style = typeface.Style;
|
|
|
|
|
-
|
|
|
|
|
- weight = typeface.Weight;
|
|
|
|
|
-
|
|
|
|
|
- stretch = typeface.Stretch;
|
|
|
|
|
-
|
|
|
|
|
- var key = new FontCollectionKey(style, weight, stretch);
|
|
|
|
|
|
|
+ var key = typeface.ToFontCollectionKey();
|
|
|
|
|
|
|
|
return TryGetGlyphTypeface(familyName, key, out glyphTypeface);
|
|
return TryGetGlyphTypeface(familyName, key, out glyphTypeface);
|
|
|
}
|
|
}
|
|
@@ -195,7 +189,7 @@ namespace Avalonia.Media.Fonts
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- public bool TryGetNearestMatch(string familyName, FontStyle style, FontWeight weight, FontStretch stretch, [NotNullWhen(true)] out IGlyphTypeface? glyphTypeface)
|
|
|
|
|
|
|
+ public bool TryGetNearestMatch(string familyName, FontStyle style, FontWeight weight, FontStretch stretch, [NotNullWhen(true)] out GlyphTypeface? glyphTypeface)
|
|
|
{
|
|
{
|
|
|
if (!_glyphTypefaceCache.TryGetValue(familyName, out var glyphTypefaces))
|
|
if (!_glyphTypefaceCache.TryGetValue(familyName, out var glyphTypefaces))
|
|
|
{
|
|
{
|
|
@@ -210,52 +204,59 @@ namespace Avalonia.Media.Fonts
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// <summary>
|
|
|
- /// Attempts to add the specified <see cref="IGlyphTypeface"/> to the font collection.
|
|
|
|
|
|
|
+ /// Attempts to add the specified <see cref="GlyphTypeface"/> to the font collection.
|
|
|
/// </summary>
|
|
/// </summary>
|
|
|
- /// <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="IGlyphTypeface2"/> interface.
|
|
|
|
|
|
|
+ /// <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.
|
|
|
/// If any of these names can be associated with the glyph typeface, the typeface is added to the collection.
|
|
/// 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>
|
|
/// 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
|
|
/// <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>
|
|
|
|
|
|
|
+ /// cref="GlyphTypeface.FamilyName"/>.</param>
|
|
|
/// <returns><see langword="true"/> if the glyph typeface was successfully added to the collection; otherwise, <see
|
|
/// <returns><see langword="true"/> if the glyph typeface was successfully added to the collection; otherwise, <see
|
|
|
/// langword="false"/>.</returns>
|
|
/// langword="false"/>.</returns>
|
|
|
- public bool TryAddGlyphTypeface(IGlyphTypeface glyphTypeface)
|
|
|
|
|
|
|
+ public bool TryAddGlyphTypeface(GlyphTypeface glyphTypeface)
|
|
|
|
|
+ {
|
|
|
|
|
+ var key = glyphTypeface.ToFontCollectionKey();
|
|
|
|
|
+
|
|
|
|
|
+ return TryAddGlyphTypeface(glyphTypeface, key);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /// <summary>
|
|
|
|
|
+ /// Attempts to add the specified glyph typeface to the collection using the provided key.
|
|
|
|
|
+ /// </summary>
|
|
|
|
|
+ /// <remarks>The method adds the glyph typeface using both its typographic family name and all
|
|
|
|
|
+ /// available family names. If the glyph typeface or its family name is invalid, the method returns false and
|
|
|
|
|
+ /// does not add the typeface.</remarks>
|
|
|
|
|
+ /// <param name="glyphTypeface">The glyph typeface to add. Cannot be null, and its FamilyName property must not be null or empty.</param>
|
|
|
|
|
+ /// <param name="key">The key that identifies the font collection to which the glyph typeface will be added.</param>
|
|
|
|
|
+ /// <returns>true if the glyph typeface was successfully added to the collection; otherwise, false.</returns>
|
|
|
|
|
+ public bool TryAddGlyphTypeface(GlyphTypeface glyphTypeface, FontCollectionKey key)
|
|
|
{
|
|
{
|
|
|
if (glyphTypeface == null || string.IsNullOrEmpty(glyphTypeface.FamilyName))
|
|
if (glyphTypeface == null || string.IsNullOrEmpty(glyphTypeface.FamilyName))
|
|
|
{
|
|
{
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- var key = new FontCollectionKey(glyphTypeface.Style, glyphTypeface.Weight, glyphTypeface.Stretch);
|
|
|
|
|
|
|
+ var result = false;
|
|
|
|
|
|
|
|
- if (glyphTypeface is IGlyphTypeface2 glyphTypeface2)
|
|
|
|
|
|
|
+ //Add the TypographicFamilyName to the cache
|
|
|
|
|
+ if (!string.IsNullOrEmpty(glyphTypeface.TypographicFamilyName))
|
|
|
{
|
|
{
|
|
|
- var result = false;
|
|
|
|
|
-
|
|
|
|
|
- //Add the TypographicFamilyName to the cache
|
|
|
|
|
- if (!string.IsNullOrEmpty(glyphTypeface2.TypographicFamilyName))
|
|
|
|
|
|
|
+ if (TryAddGlyphTypeface(glyphTypeface.TypographicFamilyName, key, glyphTypeface))
|
|
|
{
|
|
{
|
|
|
- if (TryAddGlyphTypeface(glyphTypeface2.TypographicFamilyName, key, glyphTypeface))
|
|
|
|
|
- {
|
|
|
|
|
- result = true;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ result = true;
|
|
|
}
|
|
}
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- foreach (var kvp in glyphTypeface2.FamilyNames)
|
|
|
|
|
|
|
+ foreach (var kvp in glyphTypeface.FamilyNames)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (TryAddGlyphTypeface(kvp.Value, key, glyphTypeface))
|
|
|
{
|
|
{
|
|
|
- if (TryAddGlyphTypeface(kvp.Value, key, glyphTypeface))
|
|
|
|
|
- {
|
|
|
|
|
- result = true;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ result = true;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- return result;
|
|
|
|
|
- }
|
|
|
|
|
- else
|
|
|
|
|
- {
|
|
|
|
|
- return TryAddGlyphTypeface(glyphTypeface.FamilyName, key, glyphTypeface);
|
|
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ return result;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// <summary>
|
|
@@ -265,17 +266,21 @@ namespace Avalonia.Media.Fonts
|
|
|
/// If successful, it adds the created glyph typeface to the collection.</remarks>
|
|
/// If successful, it adds the created glyph typeface to the collection.</remarks>
|
|
|
/// <param name="stream">The font stream containing the font data. The stream must be readable and positioned at the beginning of the
|
|
/// <param name="stream">The font stream containing the font data. The stream must be readable and positioned at the beginning of the
|
|
|
/// font data.</param>
|
|
/// font data.</param>
|
|
|
- /// <param name="glyphTypeface">When this method returns, contains the created <see cref="IGlyphTypeface"/> instance if the operation
|
|
|
|
|
|
|
+ /// <param name="glyphTypeface">When this method returns, contains the created <see cref="GlyphTypeface"/> instance if the operation
|
|
|
/// succeeds; otherwise, <see langword="null"/>.</param>
|
|
/// succeeds; otherwise, <see langword="null"/>.</param>
|
|
|
/// <returns><see langword="true"/> if the glyph typeface was successfully created and added; otherwise, <see
|
|
/// <returns><see langword="true"/> if the glyph typeface was successfully created and added; otherwise, <see
|
|
|
/// langword="false"/>.</returns>
|
|
/// langword="false"/>.</returns>
|
|
|
- public bool TryAddGlyphTypeface(Stream stream, [NotNullWhen(true)] out IGlyphTypeface? glyphTypeface)
|
|
|
|
|
|
|
+ public bool TryAddGlyphTypeface(Stream stream, [NotNullWhen(true)] out GlyphTypeface? glyphTypeface)
|
|
|
{
|
|
{
|
|
|
- if (!_fontManagerImpl.TryCreateGlyphTypeface(stream, FontSimulations.None, out glyphTypeface))
|
|
|
|
|
|
|
+ glyphTypeface = null;
|
|
|
|
|
+
|
|
|
|
|
+ if (!_fontManagerImpl.TryCreateGlyphTypeface(stream, FontSimulations.None, out var platformTypeface))
|
|
|
{
|
|
{
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ glyphTypeface = new GlyphTypeface(platformTypeface);
|
|
|
|
|
+
|
|
|
return TryAddGlyphTypeface(glyphTypeface);
|
|
return TryAddGlyphTypeface(glyphTypeface);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -310,17 +315,19 @@ namespace Avalonia.Media.Fonts
|
|
|
{
|
|
{
|
|
|
var stream = _assetLoader.Open(fontAsset);
|
|
var stream = _assetLoader.Open(fontAsset);
|
|
|
|
|
|
|
|
- if (!_fontManagerImpl.TryCreateGlyphTypeface(stream, FontSimulations.None, out var glyphTypeface))
|
|
|
|
|
|
|
+ if (!_fontManagerImpl.TryCreateGlyphTypeface(stream, FontSimulations.None, out var platformTypeface))
|
|
|
{
|
|
{
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- var key = new FontCollectionKey(glyphTypeface.Style, glyphTypeface.Weight, glyphTypeface.Stretch);
|
|
|
|
|
|
|
+ var glyphTypeface = new GlyphTypeface(platformTypeface);
|
|
|
|
|
+
|
|
|
|
|
+ var key = glyphTypeface.ToFontCollectionKey();
|
|
|
|
|
|
|
|
//Add TypographicFamilyName to the cache
|
|
//Add TypographicFamilyName to the cache
|
|
|
- if (glyphTypeface is IGlyphTypeface2 glyphTypeface2 && !string.IsNullOrEmpty(glyphTypeface2.TypographicFamilyName))
|
|
|
|
|
|
|
+ if (!string.IsNullOrEmpty(glyphTypeface.TypographicFamilyName))
|
|
|
{
|
|
{
|
|
|
- if (TryAddGlyphTypeface(glyphTypeface2.TypographicFamilyName, key, glyphTypeface))
|
|
|
|
|
|
|
+ if (TryAddGlyphTypeface(glyphTypeface.TypographicFamilyName, key, glyphTypeface))
|
|
|
{
|
|
{
|
|
|
result = true;
|
|
result = true;
|
|
|
}
|
|
}
|
|
@@ -346,8 +353,10 @@ namespace Avalonia.Media.Fonts
|
|
|
|
|
|
|
|
using var stream = File.OpenRead(source.LocalPath);
|
|
using var stream = File.OpenRead(source.LocalPath);
|
|
|
|
|
|
|
|
- if (_fontManagerImpl.TryCreateGlyphTypeface(stream, FontSimulations.None, out var glyphTypeface))
|
|
|
|
|
|
|
+ if (_fontManagerImpl.TryCreateGlyphTypeface(stream, FontSimulations.None, out var platformTypeface))
|
|
|
{
|
|
{
|
|
|
|
|
+ var glyphTypeface = new GlyphTypeface(platformTypeface);
|
|
|
|
|
+
|
|
|
if (TryAddGlyphTypeface(glyphTypeface))
|
|
if (TryAddGlyphTypeface(glyphTypeface))
|
|
|
{
|
|
{
|
|
|
result = true;
|
|
result = true;
|
|
@@ -368,8 +377,10 @@ namespace Avalonia.Media.Fonts
|
|
|
{
|
|
{
|
|
|
using var stream = File.OpenRead(file);
|
|
using var stream = File.OpenRead(file);
|
|
|
|
|
|
|
|
- if (_fontManagerImpl.TryCreateGlyphTypeface(stream, FontSimulations.None, out var glyphTypeface))
|
|
|
|
|
|
|
+ if (_fontManagerImpl.TryCreateGlyphTypeface(stream, FontSimulations.None, out var platformTypeface))
|
|
|
{
|
|
{
|
|
|
|
|
+ var glyphTypeface = new GlyphTypeface(platformTypeface);
|
|
|
|
|
+
|
|
|
if (TryAddGlyphTypeface(glyphTypeface))
|
|
if (TryAddGlyphTypeface(glyphTypeface))
|
|
|
{
|
|
{
|
|
|
result = true;
|
|
result = true;
|
|
@@ -445,10 +456,10 @@ namespace Avalonia.Media.Fonts
|
|
|
/// find the best match based on the provided <paramref name="key"/>.</remarks>
|
|
/// find the best match based on the provided <paramref name="key"/>.</remarks>
|
|
|
/// <param name="familyName">The name of the font family to search for. This parameter is case-insensitive.</param>
|
|
/// <param name="familyName">The name of the font family to search for. This parameter is case-insensitive.</param>
|
|
|
/// <param name="key">The key representing the desired font collection attributes.</param>
|
|
/// <param name="key">The key representing the desired font collection attributes.</param>
|
|
|
- /// <param name="glyphTypeface">When this method returns, contains the matching <see cref="IGlyphTypeface"/> if a match is found; otherwise,
|
|
|
|
|
|
|
+ /// <param name="glyphTypeface">When this method returns, contains the matching <see cref="GlyphTypeface"/> if a match is found; otherwise,
|
|
|
/// <see langword="null"/>.</param>
|
|
/// <see langword="null"/>.</param>
|
|
|
/// <returns><see langword="true"/> if a matching glyph typeface is found; otherwise, <see langword="false"/>.</returns>
|
|
/// <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 IGlyphTypeface? glyphTypeface)
|
|
|
|
|
|
|
+ protected bool TryGetGlyphTypeface(string familyName, FontCollectionKey key, [NotNullWhen(true)] out GlyphTypeface? glyphTypeface)
|
|
|
{
|
|
{
|
|
|
glyphTypeface = null;
|
|
glyphTypeface = null;
|
|
|
|
|
|
|
@@ -461,7 +472,7 @@ namespace Avalonia.Media.Fonts
|
|
|
|
|
|
|
|
if (TryGetNearestMatch(glyphTypefaces, key, out glyphTypeface))
|
|
if (TryGetNearestMatch(glyphTypefaces, key, out glyphTypeface))
|
|
|
{
|
|
{
|
|
|
- var matchedKey = new FontCollectionKey(glyphTypeface.Style, glyphTypeface.Weight, glyphTypeface.Stretch);
|
|
|
|
|
|
|
+ var matchedKey = glyphTypeface.ToFontCollectionKey();
|
|
|
|
|
|
|
|
if (matchedKey != key)
|
|
if (matchedKey != key)
|
|
|
{
|
|
{
|
|
@@ -550,19 +561,21 @@ namespace Avalonia.Media.Fonts
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// <summary>
|
|
|
- /// Attempts to retrieve the nearest matching <see cref="IGlyphTypeface"/> for the specified font key from the
|
|
|
|
|
|
|
+ /// Attempts to retrieve the nearest matching <see cref="GlyphTypeface"/> for the specified font key from the
|
|
|
/// provided collection of glyph typefaces.
|
|
/// provided collection of glyph typefaces.
|
|
|
/// </summary>
|
|
/// </summary>
|
|
|
/// <remarks>This method attempts to find the best match for the specified font key by considering
|
|
/// <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="GlyphTypeface"/> from the
|
|
|
/// collection, if any.</remarks>
|
|
/// collection, if any.</remarks>
|
|
|
/// <param name="glyphTypefaces">A collection of glyph typefaces, indexed by <see cref="FontCollectionKey"/>.</param>
|
|
/// <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>
|
|
/// <param name="key">The <see cref="FontCollectionKey"/> representing the desired font attributes.</param>
|
|
|
- /// <param name="glyphTypeface">When this method returns, contains the <see cref="IGlyphTypeface"/> that most closely matches the specified
|
|
|
|
|
|
|
+ /// <param name="glyphTypeface">When this method returns, contains the <see cref="GlyphTypeface"/> that most closely matches the specified
|
|
|
/// key, if a match is found; otherwise, <see langword="null"/>.</param>
|
|
/// 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
|
|
|
|
|
|
|
+ /// <returns><see langword="true"/> if a matching <see cref="GlyphTypeface"/> is found; otherwise, <see
|
|
|
/// langword="false"/>.</returns>
|
|
/// langword="false"/>.</returns>
|
|
|
- protected bool TryGetNearestMatch(IDictionary<FontCollectionKey, IGlyphTypeface?> glyphTypefaces, FontCollectionKey key, [NotNullWhen(true)] out IGlyphTypeface? glyphTypeface)
|
|
|
|
|
|
|
+ protected bool TryGetNearestMatch(IDictionary<FontCollectionKey, GlyphTypeface?> glyphTypefaces,
|
|
|
|
|
+ FontCollectionKey key, [NotNullWhen(true)] out GlyphTypeface? glyphTypeface)
|
|
|
{
|
|
{
|
|
|
if (glyphTypefaces.TryGetValue(key, out glyphTypeface) && glyphTypeface != null)
|
|
if (glyphTypefaces.TryGetValue(key, out glyphTypeface) && glyphTypeface != null)
|
|
|
{
|
|
{
|
|
@@ -627,7 +640,7 @@ namespace Avalonia.Media.Fonts
|
|
|
/// <param name="glyphTypeface">The glyph typeface to add to the cache. Can be null.</param>
|
|
/// <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
|
|
/// <returns><see langword="true"/> if the glyph typeface was successfully added to the cache; otherwise, <see
|
|
|
/// langword="false"/>.</returns>
|
|
/// langword="false"/>.</returns>
|
|
|
- protected bool TryAddGlyphTypeface(string familyName, FontCollectionKey key, IGlyphTypeface? glyphTypeface)
|
|
|
|
|
|
|
+ protected bool TryAddGlyphTypeface(string familyName, FontCollectionKey key, GlyphTypeface? glyphTypeface)
|
|
|
{
|
|
{
|
|
|
if (string.IsNullOrEmpty(familyName))
|
|
if (string.IsNullOrEmpty(familyName))
|
|
|
{
|
|
{
|
|
@@ -651,7 +664,7 @@ namespace Avalonia.Media.Fonts
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Family doesn't exist yet. Create a new dictionary instance and try to install it.
|
|
// Family doesn't exist yet. Create a new dictionary instance and try to install it.
|
|
|
- var newDict = new ConcurrentDictionary<FontCollectionKey, IGlyphTypeface?>();
|
|
|
|
|
|
|
+ var newDict = new ConcurrentDictionary<FontCollectionKey, GlyphTypeface?>();
|
|
|
|
|
|
|
|
// GetOrAdd will return the instance that ended up in the dictionary. If it's our
|
|
// 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.
|
|
// newDict instance then we won the race to add the family and should publish it.
|
|
@@ -693,9 +706,9 @@ namespace Avalonia.Media.Fonts
|
|
|
/// null.</param>
|
|
/// null.</param>
|
|
|
/// <returns>true if a suitable fallback glyph typeface is found; otherwise, false.</returns>
|
|
/// <returns>true if a suitable fallback glyph typeface is found; otherwise, false.</returns>
|
|
|
private static bool TryFindStretchFallback(
|
|
private static bool TryFindStretchFallback(
|
|
|
- IDictionary<FontCollectionKey, IGlyphTypeface?> glyphTypefaces,
|
|
|
|
|
|
|
+ IDictionary<FontCollectionKey, GlyphTypeface?> glyphTypefaces,
|
|
|
FontCollectionKey key,
|
|
FontCollectionKey key,
|
|
|
- [NotNullWhen(true)] out IGlyphTypeface? glyphTypeface)
|
|
|
|
|
|
|
+ [NotNullWhen(true)] out GlyphTypeface? glyphTypeface)
|
|
|
{
|
|
{
|
|
|
glyphTypeface = null;
|
|
glyphTypeface = null;
|
|
|
|
|
|
|
@@ -740,9 +753,9 @@ namespace Avalonia.Media.Fonts
|
|
|
/// null.</param>
|
|
/// null.</param>
|
|
|
/// <returns>true if a fallback glyph typeface matching the requested weight is found; otherwise, false.</returns>
|
|
/// <returns>true if a fallback glyph typeface matching the requested weight is found; otherwise, false.</returns>
|
|
|
private static bool TryFindWeightFallback(
|
|
private static bool TryFindWeightFallback(
|
|
|
- IDictionary<FontCollectionKey, IGlyphTypeface?> glyphTypefaces,
|
|
|
|
|
|
|
+ IDictionary<FontCollectionKey, GlyphTypeface?> glyphTypefaces,
|
|
|
FontCollectionKey key,
|
|
FontCollectionKey key,
|
|
|
- [NotNullWhen(true)] out IGlyphTypeface? glyphTypeface)
|
|
|
|
|
|
|
+ [NotNullWhen(true)] out GlyphTypeface? glyphTypeface)
|
|
|
{
|
|
{
|
|
|
glyphTypeface = null;
|
|
glyphTypeface = null;
|
|
|
var weight = (int)key.Weight;
|
|
var weight = (int)key.Weight;
|