From 872cef0176713fdc31514ea2b03751eaaa2ee387 Mon Sep 17 00:00:00 2001 From: Benedikt Schroeder Date: Sun, 3 Nov 2019 11:33:57 +0100 Subject: [PATCH] Introduce abstract font manager --- src/Avalonia.Visuals/Media/FontFamily.cs | 6 +- src/Avalonia.Visuals/Media/FontManager.cs | 106 +++++++++++++----- .../Media/Fonts/FamilyNameCollection.cs | 2 +- src/Avalonia.Visuals/Media/GlyphTypeface.cs | 2 +- src/Avalonia.Visuals/Media/Typeface.cs | 2 +- src/Skia/Avalonia.Skia/GlyphTypefaceImpl.cs | 2 +- .../Media/GlyphTypefaceImpl.cs | 2 +- 7 files changed, 89 insertions(+), 33 deletions(-) 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;