A cross-platform UI framework for .NET
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

230 lines
7.1 KiB

using System;
using Avalonia.Media.Fonts;
namespace Avalonia.Media
{
public sealed class FontFamily
{
public const string DefaultFontFamilyName = "$Default";
static FontFamily()
{
Default = new FontFamily(DefaultFontFamilyName);
}
/// <inheritdoc />
/// <summary>
/// Initializes a new instance of the <see cref="T:Avalonia.Media.FontFamily" /> class.
/// </summary>
/// <param name="name">The name of the <see cref="T:Avalonia.Media.FontFamily" />.</param>
public FontFamily(string name) : this(null, name)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="T:Avalonia.Media.FontFamily" /> class.
/// </summary>
/// <param name="baseUri">Specifies the base uri that is used to resolve font family assets.</param>
/// <param name="name">The name of the <see cref="T:Avalonia.Media.FontFamily" />.</param>
/// <exception cref="T:System.ArgumentException">Base uri must be an absolute uri.</exception>
public FontFamily(Uri? baseUri, string name)
{
if (string.IsNullOrEmpty(name))
{
throw new ArgumentNullException(nameof(name));
}
var fontFamilySegment = GetFontFamilyIdentifier(name);
if (fontFamilySegment.Source != null)
{
if (baseUri != null && !baseUri.IsAbsoluteUri)
{
throw new ArgumentException("Base uri must be an absolute uri.", nameof(baseUri));
}
Key = new FontFamilyKey(fontFamilySegment.Source, baseUri);
}
FamilyNames = new FamilyNameCollection(fontFamilySegment.Name);
}
/// <summary>
/// Represents the default font family
/// </summary>
public static FontFamily Default { get; }
/// <summary>
/// Gets the primary family name of the font family.
/// </summary>
/// <value>
/// The primary name of the font family.
/// </value>
public string Name => FamilyNames.PrimaryFamilyName;
/// <summary>
/// Gets the family names.
/// </summary>
/// <value>
/// The family familyNames.
/// </value>
public FamilyNameCollection FamilyNames { get; }
/// <summary>
/// Gets the key for associated assets.
/// </summary>
/// <value>
/// The family key.
/// </value>
/// <remarks>Key is only used for custom fonts.</remarks>
public FontFamilyKey? Key { get; }
/// <summary>
/// Returns <c>True</c> if this instance is the system's default.
/// </summary>
public bool IsDefault => Name.Equals(DefaultFontFamilyName);
/// <summary>
/// Implicit conversion of string to FontFamily
/// </summary>
/// <param name="s"></param>
public static implicit operator FontFamily(string s)
{
return new FontFamily(s);
}
private struct FontFamilyIdentifier
{
public FontFamilyIdentifier(string name, Uri? source)
{
Name = name;
Source = source;
}
public string Name { get; }
public Uri? Source { get; }
}
private static FontFamilyIdentifier GetFontFamilyIdentifier(string name)
{
var segments = name.Split('#');
switch (segments.Length)
{
case 1:
{
return new FontFamilyIdentifier(segments[0], null);
}
case 2:
{
var source = segments[0].StartsWith("/", StringComparison.Ordinal)
? new Uri(segments[0], UriKind.Relative)
: new Uri(segments[0], UriKind.RelativeOrAbsolute);
return new FontFamilyIdentifier(segments[1], source);
}
default:
{
return new FontFamilyIdentifier(name, null);
}
}
}
/// <summary>
/// Parses a <see cref="T:Avalonia.Media.FontFamily"/> string.
/// </summary>
/// <param name="s">The <see cref="T:Avalonia.Media.FontFamily"/> string.</param>
/// <returns></returns>
/// <exception cref="ArgumentException">
/// Specified family is not supported.
/// </exception>
public static FontFamily Parse(string s) => Parse(s, null);
/// <summary>
/// Parses a <see cref="T:Avalonia.Media.FontFamily"/> string.
/// </summary>
/// <param name="s">The <see cref="T:Avalonia.Media.FontFamily"/> string.</param>
/// <param name="baseUri">Specifies the base uri that is used to resolve font family assets.</param>
/// <returns></returns>
/// <exception cref="ArgumentException">
/// Specified family is not supported.
/// </exception>
public static FontFamily Parse(string s, Uri? baseUri)
{
if (string.IsNullOrEmpty(s))
{
throw new ArgumentException("Specified family is not supported.", nameof(s));
}
return new FontFamily(baseUri, s);
}
/// <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)
{
return Key + "#" + FamilyNames;
}
return FamilyNames.ToString();
}
/// <summary>
/// Returns a hash code for this instance.
/// </summary>
/// <returns>
/// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
/// </returns>
public override int GetHashCode()
{
unchecked
{
return (FamilyNames.GetHashCode() * 397) ^ (Key is not null ? Key.GetHashCode() : 0);
}
}
public static bool operator !=(FontFamily? a, FontFamily? b)
{
return !(a == b);
}
public static bool operator ==(FontFamily? a, FontFamily? b)
{
if (ReferenceEquals(a, b))
{
return true;
}
return !(a is null) && a.Equals(b);
}
public override bool Equals(object? obj)
{
if (ReferenceEquals(this, obj))
{
return true;
}
if (!(obj is FontFamily other))
{
return false;
}
if (!Equals(Key, other.Key))
{
return false;
}
return other.FamilyNames.Equals(FamilyNames);
}
}
}