Browse Source

Added comments

repros/custom-fonts-pr
Benedikt Schroeder 8 years ago
parent
commit
0da9083ba3
  1. 5
      samples/ControlCatalog.Desktop/Program.cs
  2. 48
      samples/ControlCatalog/Pages/BorderPage.xaml
  3. 29
      src/Avalonia.Visuals/Media/FontFamily.cs
  4. 20
      src/Avalonia.Visuals/Media/Fonts/CachedFontFamily.cs
  5. 13
      src/Avalonia.Visuals/Media/Fonts/FontFamilyCache.cs
  6. 26
      src/Avalonia.Visuals/Media/Fonts/FontFamilyKey.cs
  7. 6
      src/Avalonia.Visuals/Media/Fonts/FontResource.cs
  8. 19
      src/Avalonia.Visuals/Media/Fonts/FontResourceCollection.cs
  9. 75
      src/Avalonia.Visuals/Media/Fonts/FontResourceLoader.cs
  10. 8
      src/Avalonia.Visuals/Media/Fonts/IFontResourceLoader.cs

5
samples/ControlCatalog.Desktop/Program.cs

@ -3,7 +3,6 @@ using System.Linq;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Logging.Serilog;
using Avalonia.Media;
using Avalonia.Platform;
using Serilog;
@ -23,13 +22,13 @@ namespace ControlCatalog
/// This method is needed for IDE previewer infrastructure
/// </summary>
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>().LogToDebug().UsePlatformDetect().UseSkia();
=> AppBuilder.Configure<App>().LogToDebug().UsePlatformDetect();
private static void ConfigureAssetAssembly(AppBuilder builder)
{
AvaloniaLocator.CurrentMutable
.GetService<IAssetLoader>()
.SetDefaultAssembly(typeof(App).Assembly);
.SetDefaultAssembly(typeof(App).Assembly);
}
}
}

48
samples/ControlCatalog/Pages/BorderPage.xaml

@ -1,38 +1,32 @@
<UserControl xmlns="https://github.com/avaloniaui">
<StackPanel Orientation="Vertical" Gap="4">
<TextBlock Classes="h1">Border</TextBlock>
<TextBlock Classes="h2">A control which decorates a child with a border and background</TextBlock>
<StackPanel Orientation="Vertical" Gap="4">
<TextBlock Classes="h1">Border</TextBlock>
<TextBlock Classes="h2">A control which decorates a child with a border and background</TextBlock>
<StackPanel Orientation="Vertical"
<StackPanel Orientation="Vertical"
Margin="0,16,0,0"
HorizontalAlignment="Center"
Gap="16">
<Border BorderBrush="{DynamicResource ThemeAccentBrush}" BorderThickness="2" Padding="16">
<TextBlock>Border</TextBlock>
</Border>
<Border Background="{DynamicResource ThemeAccentBrush2}"
BorderBrush="{DynamicResource ThemeAccentBrush}"
BorderThickness="4"
<Border BorderBrush="{DynamicResource ThemeAccentBrush}" BorderThickness="2" Padding="16">
<TextBlock>Border</TextBlock>
</Border>
<Border Background="{DynamicResource ThemeAccentBrush2}"
BorderBrush="{DynamicResource ThemeAccentBrush}"
BorderThickness="4"
Padding="16">
<TextBlock>Border and Background</TextBlock>
</Border>
<Border BorderBrush="{DynamicResource ThemeAccentBrush}"
BorderThickness="4"
<TextBlock>Border and Background</TextBlock>
</Border>
<Border BorderBrush="{DynamicResource ThemeAccentBrush}"
BorderThickness="4"
CornerRadius="8"
Padding="16">
<TextBlock>Rounded Corners</TextBlock>
</Border>
<Border Background="{DynamicResource ThemeAccentBrush2}"
<TextBlock>Rounded Corners</TextBlock>
</Border>
<Border Background="{DynamicResource ThemeAccentBrush2}"
CornerRadius="8"
Padding="16">
<StackPanel>
<TextBlock FontFamily="res:/Fonts?assembly=ControlCatalog#Pixel Operator">Rounded Corners</TextBlock>
<TextBlock FontFamily="res:/Fonts?assembly=ControlCatalog#Pink Highway" FontWeight="Bold">Rounded Corners</TextBlock>
<TextBlock FontFamily="res:/Fonts/Aspergit*.ttf?assembly=ControlCatalog#Aspergit" FontWeight="Bold">Rounded Corners</TextBlock>
<TextBlock FontFamily="res:/Fonts/Aspergit*.ttf?assembly=ControlCatalog#Aspergit" FontWeight="Bold" FontStyle="Italic">Rounded Corners</TextBlock>
<TextBlock FontFamily="res:/Fonts/Aspergit*.ttf?assembly=ControlCatalog#Aspergit" FontStyle="Italic">Rounded Corners</TextBlock>
</StackPanel>
</Border>
</StackPanel>
</StackPanel>
<TextBlock>Rounded Corners</TextBlock>
</Border>
</StackPanel>
</StackPanel>
</UserControl>

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

@ -8,20 +8,49 @@ namespace Avalonia.Media
{
public class FontFamily
{
/// <summary>
/// Initializes a new instance of the <see cref="FontFamily"/> class.
/// </summary>
/// <param name="name">The name.</param>
/// <exception cref="ArgumentNullException">name</exception>
public FontFamily(string name = "Courier New")
{
Name = name ?? throw new ArgumentNullException(nameof(name));
}
/// <inheritdoc />
/// <summary>
/// Initializes a new instance of the <see cref="T:Avalonia.Media.FontFamily" /> class.
/// </summary>
/// <param name="name">The name.</param>
/// <param name="source">The source.</param>
public FontFamily(string name, Uri source) : this(name)
{
Key = new FontFamilyKey(source);
}
/// <summary>
/// Gets the name.
/// </summary>
/// <value>
/// The name.
/// </value>
public string Name { get; }
/// <summary>
/// Gets the key.
/// </summary>
/// <value>
/// The key.
/// </value>
public FontFamilyKey Key { get; }
/// <summary>
/// Returns a <see cref="string" /> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="string" /> that represents this instance.
/// </returns>
public override string ToString()
{
if (Key != null)

20
src/Avalonia.Visuals/Media/Fonts/CachedFontFamily.cs

@ -5,18 +5,38 @@ using System.Collections.Generic;
namespace Avalonia.Media.Fonts
{
/// <summary>
/// Holds a quantity of <see cref="FontResource"/> that belongs to a specific <see cref="FontFamilyKey"/>
/// </summary>
public class CachedFontFamily
{
private readonly FontResourceCollection _fontResourceCollection;
/// <summary>
/// Initializes a new instance of the <see cref="CachedFontFamily"/> class.
/// </summary>
/// <param name="key">The key.</param>
/// <param name="fontResourceCollection">The font resource collection.</param>
public CachedFontFamily(FontFamilyKey key, FontResourceCollection fontResourceCollection)
{
Key = key;
_fontResourceCollection = fontResourceCollection;
}
/// <summary>
/// Gets the key.
/// </summary>
/// <value>
/// The key.
/// </value>
public FontFamilyKey Key { get; }
/// <summary>
/// Gets the font resources.
/// </summary>
/// <value>
/// The font resources.
/// </value>
public IEnumerable<FontResource> FontResources => _fontResourceCollection.FontResources;
}
}

13
src/Avalonia.Visuals/Media/Fonts/FontFamilyCache.cs

@ -5,15 +5,28 @@ using System.Collections.Concurrent;
namespace Avalonia.Media.Fonts
{
/// <summary>
/// Caches all <see cref="CachedFontFamily"/> instances to reduce memory usage and speed up loading times of custom font families
/// </summary>
public static class FontFamilyCache
{
private static readonly ConcurrentDictionary<FontFamilyKey, CachedFontFamily> s_cachedFontFamilies = new ConcurrentDictionary<FontFamilyKey, CachedFontFamily>();
/// <summary>
/// Gets the or add cached font family.
/// </summary>
/// <param name="key">The key.</param>
/// <returns></returns>
public static CachedFontFamily GetOrAddFontFamily(FontFamilyKey key)
{
return s_cachedFontFamilies.GetOrAdd(key, CreateCachedFontFamily);
}
/// <summary>
/// Creates the cached font family.
/// </summary>
/// <param name="fontFamilyKey">The font family key.</param>
/// <returns></returns>
private static CachedFontFamily CreateCachedFontFamily(FontFamilyKey fontFamilyKey)
{
return new CachedFontFamily(fontFamilyKey, new FontResourceCollection(fontFamilyKey));

26
src/Avalonia.Visuals/Media/Fonts/FontFamilyKey.cs

@ -6,8 +6,15 @@ using System.Linq;
namespace Avalonia.Media.Fonts
{
/// <summary>
/// Unique idetifier for a quantity of <see cref="FontResource"/> that is stored at a given location.
/// </summary>
public class FontFamilyKey
{
/// <summary>
/// Creates a new instance of <see cref="FontFamilyKey"/> and extracts <see cref="Location"/> and <see cref="FileName"/> from given <see cref="Uri"/>
/// </summary>
/// <param name="source"></param>
public FontFamilyKey(Uri source)
{
if (source.AbsolutePath.Contains(".ttf"))
@ -31,8 +38,14 @@ namespace Avalonia.Media.Fonts
}
}
/// <summary>
/// Location of stored <see cref="FontResource"/> that belong to a <see cref="FontFamily"/>
/// </summary>
public Uri Location { get; }
/// <summary>
/// Optional filename for <see cref="FontResource"/> that belong to a <see cref="FontFamily"/>
/// </summary>
public string FileName { get; }
public override int GetHashCode()
@ -55,6 +68,13 @@ namespace Avalonia.Media.Fonts
}
}
/// <summary>
/// Determines whether the specified <see cref="object" />, is equal to this instance.
/// </summary>
/// <param name="obj">The <see cref="object" /> to compare with this instance.</param>
/// <returns>
/// <c>true</c> if the specified <see cref="object" /> is equal to this instance; otherwise, <c>false</c>.
/// </returns>
public override bool Equals(object obj)
{
if (!(obj is FontFamilyKey other)) return false;
@ -66,6 +86,12 @@ namespace Avalonia.Media.Fonts
return true;
}
/// <summary>
/// Returns a <see cref="string" /> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="string" /> that represents this instance.
/// </returns>
public override string ToString()
{
if (FileName != null)

6
src/Avalonia.Visuals/Media/Fonts/FontResource.cs

@ -5,6 +5,9 @@ using System;
namespace Avalonia.Media.Fonts
{
/// <summary>
/// Represents a font resource
/// </summary>
public class FontResource
{
public FontResource(Uri source)
@ -12,6 +15,9 @@ namespace Avalonia.Media.Fonts
Source = source;
}
/// <summary>
/// Source of the font resource.
/// </summary>
public Uri Source { get; }
}
}

19
src/Avalonia.Visuals/Media/Fonts/FontResourceCollection.cs

@ -7,6 +7,9 @@ using System.Linq;
namespace Avalonia.Media.Fonts
{
/// <summary>
/// Represents a collection of <see cref="FontResource"/> that is identified by a unique <see cref="FontFamilyKey"/>
/// </summary>
public class FontResourceCollection
{
private Dictionary<Uri, FontResource> _fontResources;
@ -17,8 +20,20 @@ namespace Avalonia.Media.Fonts
Key = key;
}
/// <summary>
/// Gets the key.
/// </summary>
/// <value>
/// The key.
/// </value>
public FontFamilyKey Key { get; }
/// <summary>
/// Gets the font resources.
/// </summary>
/// <value>
/// The font resources.
/// </value>
public IEnumerable<FontResource> FontResources
{
get
@ -32,6 +47,10 @@ namespace Avalonia.Media.Fonts
}
}
/// <summary>
/// Creates the font resources.
/// </summary>
/// <returns></returns>
private Dictionary<Uri, FontResource> CreateFontResources()
{
return _fontResourceLoader.GetFontResources(Key).ToDictionary(x => x.Source);

75
src/Avalonia.Visuals/Media/Fonts/FontResourceLoader.cs

@ -9,6 +9,10 @@ using Avalonia.Platform;
namespace Avalonia.Media.Fonts
{
/// <inheritdoc />
/// <summary>
/// Implementation of <see cref="T:Avalonia.Media.Fonts.IFontResourceLoader" />
/// </summary>
public class FontResourceLoader : IFontResourceLoader
{
private static readonly Dictionary<string, AssemblyDescriptor> s_assemblyNameCache
@ -16,6 +20,10 @@ namespace Avalonia.Media.Fonts
private readonly AssemblyDescriptor _defaultAssembly;
/// <summary>
/// Initializes a new instance of the <see cref="FontResourceLoader"/> class.
/// </summary>
/// <param name="assembly">The default assembly.</param>
public FontResourceLoader(Assembly assembly = null)
{
if (assembly == null)
@ -28,6 +36,12 @@ namespace Avalonia.Media.Fonts
}
}
/// <inheritdoc />
/// <summary>
/// Returns a quanity of <see cref="T:Avalonia.Media.Fonts.FontResource" /> that belongs to a given <see cref="T:Avalonia.Media.Fonts.FontFamilyKey" />
/// </summary>
/// <param name="fontFamilyKey"></param>
/// <returns></returns>
public IEnumerable<FontResource> GetFontResources(FontFamilyKey fontFamilyKey)
{
return fontFamilyKey.FileName != null
@ -35,6 +49,11 @@ namespace Avalonia.Media.Fonts
: GetFontResourcesByLocation(fontFamilyKey.Location);
}
/// <summary>
/// Searches for font resources at a given location and returns a quanity of found resources
/// </summary>
/// <param name="location"></param>
/// <returns></returns>
private IEnumerable<FontResource> GetFontResourcesByLocation(Uri location)
{
var assembly = GetAssembly(location);
@ -46,6 +65,13 @@ namespace Avalonia.Media.Fonts
return matchingResources.Select(x => new FontResource(GetResourceUri(x, assembly.Name)));
}
/// <summary>
/// Searches for font resources at a given location and only accepts resources that fit to a given filename expression.
/// <para>Filenames can target multible files with * wildcard. For example "FontFile*.ttf"</para>
/// </summary>
/// <param name="location"></param>
/// <param name="fileName"></param>
/// <returns></returns>
private IEnumerable<FontResource> GetFontResourcesByFileName(Uri location, string fileName)
{
var assembly = GetAssembly(location);
@ -57,11 +83,22 @@ namespace Avalonia.Media.Fonts
return matchingResources.Select(x => new FontResource(GetResourceUri(x, assembly.Name)));
}
/// <summary>
/// Returns a valid resource <see cref="Uri"/> that follows the resm scheme
/// </summary>
/// <param name="path"></param>
/// <param name="assemblyName"></param>
/// <returns></returns>
private static Uri GetResourceUri(string path, string assemblyName)
{
return new Uri("resm:" + path + "?assembly=" + assemblyName);
}
/// <summary>
/// Translates a given <see cref="Uri"/> to a <see cref="Uri"/> that follows the resm scheme.
/// </summary>
/// <param name="uri"></param>
/// <returns></returns>
private static string GetLocationPath(Uri uri)
{
if (uri.Scheme == "resm") return uri.AbsolutePath;
@ -71,6 +108,11 @@ namespace Avalonia.Media.Fonts
return path;
}
/// <summary>
/// Extracts a <see cref="AssemblyDescriptor"/> from a given <see cref="Uri"/>
/// </summary>
/// <param name="uri"></param>
/// <returns></returns>
private AssemblyDescriptor GetAssembly(Uri uri)
{
if (uri == null) return null;
@ -80,6 +122,14 @@ namespace Avalonia.Media.Fonts
return parameters.TryGetValue("assembly", out var assemblyName) ? GetAssembly(assemblyName) : null;
}
/// <summary>
/// Returns a <see cref="AssemblyDescriptor"/> that is identified by a given name.
/// <para>
/// If name is <value>null</value> the default assembly is used.
/// </para>
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
private AssemblyDescriptor GetAssembly(string name)
{
if (name == null)
@ -113,6 +163,11 @@ namespace Avalonia.Media.Fonts
return rv;
}
/// <summary>
/// Parses the parameters.
/// </summary>
/// <param name="uri">The URI.</param>
/// <returns></returns>
private static Dictionary<string, string> ParseParameters(Uri uri)
{
return uri.Query.TrimStart('?')
@ -134,8 +189,28 @@ namespace Avalonia.Media.Fonts
Name = Assembly.GetName().Name;
}
/// <summary>
/// Gets the name.
/// </summary>
/// <value>
/// The name.
/// </value>
public string Name { get; }
/// <summary>
/// Gets the assembly.
/// </summary>
/// <value>
/// The assembly.
/// </value>
public Assembly Assembly { get; }
/// <summary>
/// Gets the resources.
/// </summary>
/// <value>
/// The resources.
/// </value>
public List<string> Resources { get; }
}
}

8
src/Avalonia.Visuals/Media/Fonts/IFontResourceLoader.cs

@ -5,8 +5,16 @@ using System.Collections.Generic;
namespace Avalonia.Media.Fonts
{
/// <summary>
/// Loads <see cref="FontResource"/> that can be identified by a given <see cref="FontFamilyKey"/>
/// </summary>
public interface IFontResourceLoader
{
/// <summary>
/// Returns a quanity of <see cref="FontResource"/> that belongs to a given <see cref="FontFamilyKey"/>
/// </summary>
/// <param name="fontFamilyKey"></param>
/// <returns></returns>
IEnumerable<FontResource> GetFontResources(FontFamilyKey fontFamilyKey);
}
}
Loading…
Cancel
Save