diff --git a/src/Avalonia.Visuals/Media/FontFamily.cs b/src/Avalonia.Visuals/Media/FontFamily.cs
index d263097e6a..b57b4a0ca8 100644
--- a/src/Avalonia.Visuals/Media/FontFamily.cs
+++ b/src/Avalonia.Visuals/Media/FontFamily.cs
@@ -8,11 +8,11 @@ using Avalonia.Media.Fonts;
namespace Avalonia.Media
{
- public class FontFamily
+ public sealed class FontFamily
{
static FontFamily()
{
- Default = new FontFamily(FontManager.DefaultFontFamilyName);
+ Default = new FontFamily(FontManager.Default.DefaultFontFamilyName);
}
///
@@ -64,7 +64,7 @@ namespace Avalonia.Media
/// Consider using the new instead.
///
public static IEnumerable SystemFontFamilies =>
- FontManager.GetInstalledFontFamilyNames().Select(name => new FontFamily(name));
+ FontManager.Default.GetInstalledFontFamilyNames().Select(name => new FontFamily(name));
///
/// Gets the primary family name of the font family.
diff --git a/src/Avalonia.Visuals/Media/FontManager.cs b/src/Avalonia.Visuals/Media/FontManager.cs
index 95d91e7df1..be1bd269ed 100644
--- a/src/Avalonia.Visuals/Media/FontManager.cs
+++ b/src/Avalonia.Visuals/Media/FontManager.cs
@@ -7,50 +7,106 @@ using Avalonia.Platform;
namespace Avalonia.Media
{
- public static class FontManager
+ ///
+ /// The font manager is used to query the system's installed fonts and is responsible for caching loaded fonts.
+ /// It is also responsible for the font fallback.
+ ///
+ public abstract class FontManager
{
- private static readonly IFontManagerImpl s_platformImpl = GetPlatformImpl();
+ public static readonly FontManager Default = CreateDefault();
- ///
- public static string DefaultFontFamilyName => s_platformImpl.DefaultFontFamilyName;
+ ///
+ /// Gets the system's default font family's name.
+ ///
+ public string DefaultFontFamilyName
+ {
+ get;
+ protected set;
+ }
- ///
- public static IEnumerable GetInstalledFontFamilyNames(bool checkForUpdates = false) =>
- s_platformImpl.GetInstalledFontFamilyNames(checkForUpdates);
+ ///
+ /// Get all installed fonts in the system.
+ /// If true the font collection is updated.
+ ///
+ public abstract IEnumerable GetInstalledFontFamilyNames(bool checkForUpdates = false);
- ///
- public static Typeface GetTypeface(FontFamily fontFamily, FontWeight fontWeight, FontStyle fontStyle) =>
- s_platformImpl.GetTypeface(fontFamily, fontWeight, fontStyle);
+ ///
+ /// Get a cached typeface from specified parameters.
+ ///
+ /// The font family.
+ /// The font weight.
+ /// The font style.
+ ///
+ /// The cached typeface.
+ ///
+ public abstract Typeface GetCachedTypeface(FontFamily fontFamily, FontWeight fontWeight, FontStyle fontStyle);
- ///
- public static Typeface MatchCharacter(int codepoint, FontWeight fontWeight = default,
+ ///
+ /// Tries to match a specified character to a typeface that supports specified font properties.
+ /// Returns null if no fallback was found.
+ ///
+ /// The codepoint to match against.
+ /// The font weight.
+ /// The font style.
+ /// The font family. This is optional and used for fallback lookup.
+ /// The culture.
+ ///
+ /// The matched typeface.
+ ///
+ public abstract Typeface MatchCharacter(int codepoint, FontWeight fontWeight = default,
FontStyle fontStyle = default,
- FontFamily fontFamily = null, CultureInfo culture = null) =>
- s_platformImpl.MatchCharacter(codepoint, fontWeight, fontStyle, fontFamily, culture);
+ FontFamily fontFamily = null, CultureInfo culture = null);
- private static IFontManagerImpl GetPlatformImpl()
+ public static FontManager CreateDefault()
{
var platformImpl = AvaloniaLocator.Current.GetService();
- return platformImpl ?? new EmptyFontManagerImpl();
+ if (platformImpl != null)
+ {
+ return new PlatformFontManager(platformImpl);
+ }
+
+ return new EmptyFontManager();
}
- private class EmptyFontManagerImpl : IFontManagerImpl
+ private class PlatformFontManager : FontManager
{
- public string DefaultFontFamilyName => "Arial";
-
- public IEnumerable GetInstalledFontFamilyNames(bool checkForUpdates = false) => new[] { "Arial" };
+ private readonly IFontManagerImpl _platformImpl;
- public Typeface GetTypeface(FontFamily fontFamily, FontWeight fontWeight, FontStyle fontStyle)
+ public PlatformFontManager(IFontManagerImpl platformImpl)
{
- return new Typeface(fontFamily, fontWeight, fontStyle);
+ _platformImpl = platformImpl;
+
+ DefaultFontFamilyName = _platformImpl.DefaultFontFamilyName;
}
- public Typeface MatchCharacter(int codepoint, FontWeight fontWeight = default, FontStyle fontStyle = default,
- FontFamily fontFamily = null, CultureInfo culture = null)
+ public override IEnumerable GetInstalledFontFamilyNames(bool checkForUpdates = false) =>
+ _platformImpl.GetInstalledFontFamilyNames(checkForUpdates);
+
+ public override Typeface GetCachedTypeface(FontFamily fontFamily, FontWeight fontWeight, FontStyle fontStyle) =>
+ _platformImpl.GetTypeface(fontFamily, fontWeight, fontStyle);
+
+ public override Typeface MatchCharacter(int codepoint, FontWeight fontWeight = default,
+ FontStyle fontStyle = default,
+ FontFamily fontFamily = null, CultureInfo culture = null) =>
+ _platformImpl.MatchCharacter(codepoint, fontWeight, fontStyle, fontFamily, culture);
+ }
+
+ private class EmptyFontManager : FontManager
+ {
+ public EmptyFontManager()
{
- return null;
+ DefaultFontFamilyName = "Empty";
}
+
+ public override IEnumerable GetInstalledFontFamilyNames(bool checkForUpdates = false) =>
+ new[] { DefaultFontFamilyName };
+
+ public override Typeface GetCachedTypeface(FontFamily fontFamily, FontWeight fontWeight, FontStyle fontStyle) => new Typeface(fontFamily, fontWeight, fontStyle);
+
+ public override Typeface MatchCharacter(int codepoint, FontWeight fontWeight = default,
+ FontStyle fontStyle = default,
+ FontFamily fontFamily = null, CultureInfo culture = null) => null;
}
}
}
diff --git a/src/Avalonia.Visuals/Media/Fonts/FamilyNameCollection.cs b/src/Avalonia.Visuals/Media/Fonts/FamilyNameCollection.cs
index 0c161131dc..e777d93315 100644
--- a/src/Avalonia.Visuals/Media/Fonts/FamilyNameCollection.cs
+++ b/src/Avalonia.Visuals/Media/Fonts/FamilyNameCollection.cs
@@ -9,7 +9,7 @@ using System.Text;
namespace Avalonia.Media.Fonts
{
- public class FamilyNameCollection : IReadOnlyList
+ public sealed class FamilyNameCollection : IReadOnlyList
{
///
/// Initializes a new instance of the class.
diff --git a/src/Avalonia.Visuals/Media/GlyphTypeface.cs b/src/Avalonia.Visuals/Media/GlyphTypeface.cs
index cba7c8c795..3ba31f7e84 100644
--- a/src/Avalonia.Visuals/Media/GlyphTypeface.cs
+++ b/src/Avalonia.Visuals/Media/GlyphTypeface.cs
@@ -7,7 +7,7 @@ using Avalonia.Platform;
namespace Avalonia.Media
{
- public class GlyphTypeface : IDisposable
+ public sealed class GlyphTypeface : IDisposable
{
private static readonly IPlatformRenderInterface s_platformRenderInterface =
AvaloniaLocator.Current.GetService();
diff --git a/src/Avalonia.Visuals/Media/Typeface.cs b/src/Avalonia.Visuals/Media/Typeface.cs
index 2d3c7e6ffa..a6d5c8a43c 100644
--- a/src/Avalonia.Visuals/Media/Typeface.cs
+++ b/src/Avalonia.Visuals/Media/Typeface.cs
@@ -10,7 +10,7 @@ namespace Avalonia.Media
///
/// Represents a typeface.
///
- [DebuggerDisplay("Name = {FontFamily.Name}, Style = {Style}, Weight = {Weight}")]
+ [DebuggerDisplay("Name = {FontFamily.Name}, Weight = {Weight}, Style = {Style}")]
public class Typeface : IEquatable
{
public static readonly Typeface Default = new Typeface(FontFamily.Default);
diff --git a/src/Skia/Avalonia.Skia/GlyphTypefaceImpl.cs b/src/Skia/Avalonia.Skia/GlyphTypefaceImpl.cs
index b9b5b07d7d..e46f766255 100644
--- a/src/Skia/Avalonia.Skia/GlyphTypefaceImpl.cs
+++ b/src/Skia/Avalonia.Skia/GlyphTypefaceImpl.cs
@@ -10,7 +10,7 @@ using SkiaSharp;
namespace Avalonia.Skia
{
- internal class GlyphTypefaceImpl : IGlyphTypefaceImpl
+ public class GlyphTypefaceImpl : IGlyphTypefaceImpl
{
private bool _isDisposed;
diff --git a/src/Windows/Avalonia.Direct2D1/Media/GlyphTypefaceImpl.cs b/src/Windows/Avalonia.Direct2D1/Media/GlyphTypefaceImpl.cs
index 66cf397110..32def01c39 100644
--- a/src/Windows/Avalonia.Direct2D1/Media/GlyphTypefaceImpl.cs
+++ b/src/Windows/Avalonia.Direct2D1/Media/GlyphTypefaceImpl.cs
@@ -9,7 +9,7 @@ using SharpDX.DirectWrite;
namespace Avalonia.Direct2D1.Media
{
- internal class GlyphTypefaceImpl : IGlyphTypefaceImpl
+ public class GlyphTypefaceImpl : IGlyphTypefaceImpl
{
private bool _isDisposed;