Browse Source

caching

pull/1535/head
Benedikt Schroeder 9 years ago
parent
commit
9f29e9a8f4
  1. 4
      samples/ControlCatalog.Desktop/Program.cs
  2. 137
      src/Avalonia.Visuals/Media/FontFamily.cs
  3. 38
      src/Markup/Avalonia.Markup.Xaml/Converters/FontFamilyTypeConverter.cs
  4. 6
      src/Windows/Avalonia.Direct2D1/Media/FormattedTextImpl.cs

4
samples/ControlCatalog.Desktop/Program.cs

@ -3,6 +3,7 @@ using System.Linq;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Logging.Serilog;
using Avalonia.Media;
using Avalonia.Platform;
using Serilog;
@ -15,6 +16,7 @@ namespace ControlCatalog
{
// TODO: Make this work with GTK/Skia/Cairo depending on command-line args
// again.
AvaloniaLocator.CurrentMutable.Bind<IFontFamilyCache>().ToConstant(new FontFamilyCache());
BuildAvaloniaApp().Start<MainWindow>();
}
@ -28,7 +30,7 @@ namespace ControlCatalog
{
AvaloniaLocator.CurrentMutable
.GetService<IAssetLoader>()
.SetDefaultAssembly(typeof(App).Assembly);
.SetDefaultAssembly(typeof(App).Assembly);
}
}
}

137
src/Avalonia.Visuals/Media/FontFamily.cs

@ -2,15 +2,15 @@
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
namespace Avalonia.Media
{
public class FontFamily
{
private IFontFamily _loadedFamily;
public FontFamily(string familyName) : this(familyName, null) { }
public FontFamily(string familyName, Uri baseUri)
@ -25,30 +25,20 @@ namespace Avalonia.Media
public Uri BaseUri => FontFamilyKey.BaseUri;
internal FontFamilyKey FontFamilyKey { get; }
internal IFontFamily LoadedFamily => _loadedFamily ?? (_loadedFamily = AvaloniaLocator.Current
.GetService<IFontFamilyLoader>()
.LoadFontFamily(FontFamilyKey));
public IEnumerable<FamilyTypeface> AvailableTypefaces => LoadedFamily.SupportedTypefaces;
}
public class FamilyTypeface
{
public FamilyTypeface()
{
FontStyle = FontStyle.Normal;
FontWeight = FontWeight.Normal;
}
public FamilyTypeface(Typeface typeface)
public FamilyTypeface(Uri resourceUri = null, FontWeight fontWeight = FontWeight.Normal, FontStyle fontStyle = FontStyle.Normal)
{
FontStyle = typeface.Style;
FontWeight = typeface.Weight;
ResourceUri = resourceUri;
FontStyle = fontStyle;
FontWeight = fontWeight;
}
public FontStyle FontStyle { get; }
public Uri ResourceUri { get; }
public FontWeight FontWeight { get; }
public FontStyle FontStyle { get; }
}
public class FontFamilyKey
@ -64,39 +54,118 @@ namespace Avalonia.Media
public string FriendlyName { get; }
public Uri BaseUri { get; }
}
internal interface IFontFamily
{
IEnumerable<FamilyTypeface> SupportedTypefaces { get; }
public override int GetHashCode()
{
unchecked
{
var hash = (int)2166136261;
if (FriendlyName != null)
{
hash = (hash * 16777619) ^ FriendlyName.GetHashCode();
}
if (BaseUri != null)
{
hash = (hash * 16777619) ^ BaseUri.GetHashCode();
}
return hash;
}
}
public override bool Equals(object obj)
{
if (!(obj is FontFamilyKey other)) return false;
if (FriendlyName != other.FriendlyName) return false;
if (BaseUri != other.BaseUri) return false;
return true;
}
}
internal class SystemFont : IFontFamily
public class FamilyTypefaceKey
{
public SystemFont() : this(new List<FamilyTypeface> { new FamilyTypeface() }) { }
public FamilyTypefaceKey(FontWeight fontWeight = FontWeight.Normal, FontStyle fontStyle = FontStyle.Normal)
{
FontWeight = fontWeight;
FontStyle = fontStyle;
}
public FontWeight FontWeight { get; }
public FontStyle FontStyle { get; }
public SystemFont(IEnumerable<FamilyTypeface> supportedTypefaces)
public override int GetHashCode()
{
SupportedTypefaces = new ReadOnlyCollection<FamilyTypeface>(new List<FamilyTypeface>(supportedTypefaces));
unchecked
{
var hash = (int)2166136261;
hash = (hash * 16777619) ^ FontWeight.GetHashCode();
hash = (hash * 16777619) ^ FontStyle.GetHashCode();
return hash;
}
}
public IEnumerable<FamilyTypeface> SupportedTypefaces { get; }
public override bool Equals(object obj)
{
if (!(obj is FamilyTypefaceKey other)) return false;
if (FontWeight != other.FontWeight) return false;
if (FontStyle != other.FontStyle) return false;
return true;
}
}
internal class CustomFont : IFontFamily
public class CachedFontFamily
{
public CustomFont() : this(new List<FamilyTypeface> { new FamilyTypeface() }) { }
private readonly ConcurrentDictionary<FamilyTypefaceKey, FamilyTypeface> _typefaces =
new ConcurrentDictionary<FamilyTypefaceKey, FamilyTypeface>();
public IEnumerable<FamilyTypeface> SupportedTypefaces => _typefaces.Values;
public bool TryGetFamilyTypeface(out FamilyTypeface typeface, FontWeight fontWeight = FontWeight.Normal,
FontStyle fontStyle = FontStyle.Normal)
{
return _typefaces.TryGetValue(new FamilyTypefaceKey(fontWeight, fontStyle), out typeface);
}
public CustomFont(IEnumerable<FamilyTypeface> supportedTypefaces)
public FamilyTypeface GetOrAddFamilyTypeface(Uri resourceUri, FontWeight fontWeight = FontWeight.Normal, FontStyle fontStyle = FontStyle.Normal)
{
SupportedTypefaces = new ReadOnlyCollection<FamilyTypeface>(new List<FamilyTypeface>(supportedTypefaces));
return _typefaces.GetOrAdd(new FamilyTypefaceKey(fontWeight, fontStyle), x => CreateFamilyTypeface(x, resourceUri));
}
public IEnumerable<FamilyTypeface> SupportedTypefaces { get; }
private static FamilyTypeface CreateFamilyTypeface(FamilyTypefaceKey familyTypefaceKey, Uri resourceUri)
{
return new FamilyTypeface(resourceUri, familyTypefaceKey.FontWeight, familyTypefaceKey.FontStyle);
}
}
public interface IFontFamilyCache
{
CachedFontFamily GetOrAddFontFamily(FontFamily fontFamily);
}
internal interface IFontFamilyLoader
public class FontFamilyCache : IFontFamilyCache
{
IFontFamily LoadFontFamily(FontFamilyKey fontFamilyKey);
private readonly ConcurrentDictionary<FontFamilyKey, CachedFontFamily> _cachedFontFamilies = new ConcurrentDictionary<FontFamilyKey, CachedFontFamily>();
public CachedFontFamily GetOrAddFontFamily(FontFamily fontFamily)
{
return _cachedFontFamilies.GetOrAdd(fontFamily.FontFamilyKey, CreateCachedFontFamily);
}
private static CachedFontFamily CreateCachedFontFamily(FontFamilyKey fontFamilyKey)
{
return new CachedFontFamily();
}
}
}

38
src/Markup/Avalonia.Markup.Xaml/Converters/FontFamilyTypeConverter.cs

@ -20,21 +20,55 @@ namespace Avalonia.Markup.Xaml.Converters
var fontFamilyExpression = s.Split('#');
string familyName;
Uri baseUri = null;
var fontWeight = FontWeight.Normal;
var fontStyle = FontStyle.Normal;
switch (fontFamilyExpression.Length)
{
case 1:
{
return new FontFamily(fontFamilyExpression[0]);
familyName = fontFamilyExpression[0];
break;
}
case 2:
{
return new FontFamily(fontFamilyExpression[1], new Uri(fontFamilyExpression[0], UriKind.RelativeOrAbsolute));
baseUri = new Uri(fontFamilyExpression[0], UriKind.RelativeOrAbsolute);
familyName = fontFamilyExpression[1];
break;
}
//case 3:
// {
// baseUri = new Uri(fontFamilyExpression[0], UriKind.RelativeOrAbsolute);
// familyName = fontFamilyExpression[1];
// fontWeight = (FontWeight)Enum.Parse(typeof(FontWeight), fontFamilyExpression[2]);
// break;
// }
//case 4:
// {
// baseUri = new Uri(fontFamilyExpression[0], UriKind.RelativeOrAbsolute);
// familyName = fontFamilyExpression[1];
// fontWeight = (FontWeight)Enum.Parse(typeof(FontWeight), fontFamilyExpression[2]);
// fontStyle = (FontStyle)Enum.Parse(typeof(FontStyle), fontFamilyExpression[3]);
// break;
// }
default:
{
throw new ArgumentException("Specified family is not supported.");
}
}
var fontFamily = new FontFamily(familyName, baseUri);
var cachedFontFamily = AvaloniaLocator.Current.GetService<IFontFamilyCache>().GetOrAddFontFamily(fontFamily);
cachedFontFamily.GetOrAddFamilyTypeface(baseUri, fontWeight, fontStyle);
return fontFamily;
}
}
}

6
src/Windows/Avalonia.Direct2D1/Media/FormattedTextImpl.cs

@ -28,7 +28,11 @@ namespace Avalonia.Direct2D1.Media
if (typeface.FontFamily.BaseUri != null)
{
var fontLoader = new ResourceFontLoader(factory, typeface.FontFamily.BaseUri);
var fontFamily = AvaloniaLocator.Current.GetService<IFontFamilyCache>().GetOrAddFontFamily(typeface.FontFamily);
fontFamily.TryGetFamilyTypeface(out var familyTypeface);
var fontLoader = new ResourceFontLoader(factory, familyTypeface.ResourceUri);
var fontCollection = new DWrite.FontCollection(factory, fontLoader, fontLoader.Key);

Loading…
Cancel
Save