diff --git a/samples/ControlCatalog/Pages/TextBoxPage.xaml b/samples/ControlCatalog/Pages/TextBoxPage.xaml
index 2c292b1478..67b60568e5 100644
--- a/samples/ControlCatalog/Pages/TextBoxPage.xaml
+++ b/samples/ControlCatalog/Pages/TextBoxPage.xaml
@@ -44,10 +44,10 @@
res fonts
-
-
-
-
+
+
+
+
diff --git a/src/Avalonia.Visuals/Media/FontFamily.cs b/src/Avalonia.Visuals/Media/FontFamily.cs
index 16dba573fd..d32db4ef28 100644
--- a/src/Avalonia.Visuals/Media/FontFamily.cs
+++ b/src/Avalonia.Visuals/Media/FontFamily.cs
@@ -40,9 +40,10 @@ namespace Avalonia.Media
///
/// The name of the .
/// The source of font resources.
- public FontFamily(string name, Uri source) : this(name)
+ ///
+ public FontFamily(string name, Uri source, Uri baseUri = null) : this(name)
{
- Key = new FontFamilyKey(source);
+ Key = new FontFamilyKey(source, baseUri);
}
///
@@ -87,11 +88,12 @@ namespace Avalonia.Media
/// Parses a string.
///
/// The string.
+ ///
///
///
/// Specified family is not supported.
///
- public static FontFamily Parse(string s)
+ public static FontFamily Parse(string s, Uri baseUri = null)
{
if (string.IsNullOrEmpty(s))
{
@@ -112,7 +114,13 @@ namespace Avalonia.Media
case 2:
{
- return new FontFamily(segments[1], new Uri(segments[0], UriKind.RelativeOrAbsolute));
+ var uri = s.StartsWith("/")
+ ? new Uri(s, UriKind.Relative)
+ : new Uri(s, UriKind.RelativeOrAbsolute);
+
+ return uri.IsAbsoluteUri
+ ? new FontFamily(segments[1], uri)
+ : new FontFamily(segments[1], uri, baseUri);
}
default:
diff --git a/src/Avalonia.Visuals/Media/Fonts/FontFamilyKey.cs b/src/Avalonia.Visuals/Media/Fonts/FontFamilyKey.cs
index 90ccac0e46..67b53cf8b4 100644
--- a/src/Avalonia.Visuals/Media/Fonts/FontFamilyKey.cs
+++ b/src/Avalonia.Visuals/Media/Fonts/FontFamilyKey.cs
@@ -2,7 +2,6 @@
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
-using System.Linq;
namespace Avalonia.Media.Fonts
{
@@ -12,48 +11,26 @@ namespace Avalonia.Media.Fonts
public class FontFamilyKey
{
///
- /// Creates a new instance of and extracts and from given
+ /// Creates a new instance of
///
///
- public FontFamilyKey(Uri source)
+ ///
+ public FontFamilyKey(Uri source, Uri baseUri = null)
{
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
+ Source = source ?? throw new ArgumentNullException(nameof(source));
- if (source.AbsolutePath.Contains(".ttf"))
- {
- var filePathWithoutExtension = source.AbsolutePath.Replace(".ttf", string.Empty);
- var fileNameWithoutExtension = filePathWithoutExtension.Split('.').Last();
- FileName = fileNameWithoutExtension + ".ttf";
- Location = new Uri(source.OriginalString.Replace("." + FileName, string.Empty), UriKind.RelativeOrAbsolute);
- }
- else
- {
- if (source.AbsolutePath.Contains(".otf"))
- {
- var filePathWithoutExtension = source.AbsolutePath.Replace(".otf", string.Empty);
- var fileNameWithoutExtension = filePathWithoutExtension.Split('.').Last();
- FileName = fileNameWithoutExtension + ".otf";
- Location = new Uri(source.OriginalString.Replace("." + FileName, string.Empty), UriKind.RelativeOrAbsolute);
- }
- else
- {
- Location = source;
- }
- }
+ BaseUri = baseUri;
}
///
- /// Location of stored font asset that belongs to a
+ /// Source of stored font asset that belongs to a
///
- public Uri Location { get; }
+ public Uri Source { get; }
///
- /// Optional filename for a font asset that belongs to a
+ ///
///
- public string FileName { get; }
+ public Uri BaseUri { get; }
///
/// Returns a hash code for this instance.
@@ -67,14 +44,14 @@ namespace Avalonia.Media.Fonts
{
var hash = (int)2166136261;
- if (Location != null)
+ if (Source != null)
{
- hash = (hash * 16777619) ^ Location.GetHashCode();
+ hash = (hash * 16777619) ^ Source.GetHashCode();
}
- if (FileName != null)
+ if (BaseUri != null)
{
- hash = (hash * 16777619) ^ FileName.GetHashCode();
+ hash = (hash * 16777619) ^ BaseUri.GetHashCode();
}
return hash;
@@ -95,12 +72,12 @@ namespace Avalonia.Media.Fonts
return false;
}
- if (Location != other.Location)
+ if (Source != other.Source)
{
return false;
}
- if (FileName != other.FileName)
+ if (BaseUri != other.BaseUri)
{
return false;
}
@@ -116,16 +93,17 @@ namespace Avalonia.Media.Fonts
///
public override string ToString()
{
- if (FileName == null)
+ if (Source.IsAbsoluteUri)
{
- return Location.PathAndQuery;
+ return Source.ToString();
}
- var builder = new UriBuilder(Location);
-
- builder.Path += "." + FileName;
+ if (BaseUri != null)
+ {
+ return BaseUri + "/" + Source;
+ }
- return builder.ToString();
+ return Source.ToString();
}
}
}
diff --git a/src/Avalonia.Visuals/Media/Fonts/FontFamilyLoader.cs b/src/Avalonia.Visuals/Media/Fonts/FontFamilyLoader.cs
index 166eb4a661..e1eabf7237 100644
--- a/src/Avalonia.Visuals/Media/Fonts/FontFamilyLoader.cs
+++ b/src/Avalonia.Visuals/Media/Fonts/FontFamilyLoader.cs
@@ -4,7 +4,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Reflection;
using Avalonia.Platform;
namespace Avalonia.Media.Fonts
@@ -20,21 +19,26 @@ namespace Avalonia.Media.Fonts
public static IEnumerable LoadFontAssets(FontFamilyKey fontFamilyKey)
{
- return fontFamilyKey.FileName != null
- ? GetFontAssetsByFileName(fontFamilyKey.Location, fontFamilyKey.FileName)
- : GetFontAssetsByLocation(fontFamilyKey.Location);
+ if (fontFamilyKey.Source.OriginalString.Contains(".ttf")
+ || fontFamilyKey.Source.OriginalString.Contains(".otf"))
+ {
+ return GetFontAssetsByExpression(fontFamilyKey);
+ }
+
+ return GetFontAssetsBySource(fontFamilyKey);
}
///
/// Searches for font assets at a given location and returns a quantity of found assets
///
- ///
+ ///
///
- private static IEnumerable GetFontAssetsByLocation(Uri location)
+ private static IEnumerable GetFontAssetsBySource(FontFamilyKey fontFamilyKey)
{
- var availableAssets = s_assetLoader.GetAssets(location, null);
+ var availableAssets = s_assetLoader.GetAssets(fontFamilyKey.Source, fontFamilyKey.BaseUri);
- var matchingAssets = availableAssets.Where(x => x.AbsolutePath.EndsWith(".ttf") || x.AbsolutePath.EndsWith(".otf"));
+ var matchingAssets =
+ availableAssets.Where(x => x.AbsolutePath.EndsWith(".ttf") || x.AbsolutePath.EndsWith(".otf"));
return matchingAssets;
}
@@ -43,20 +47,74 @@ namespace Avalonia.Media.Fonts
/// Searches for font assets at a given location and only accepts assets that fit to a given filename expression.
/// File names can target multiple files with * wildcard. For example "FontFile*.ttf"
///
- ///
- ///
+ ///
///
- private static IEnumerable GetFontAssetsByFileName(Uri location, string fileName)
+ private static IEnumerable GetFontAssetsByExpression(FontFamilyKey fontFamilyKey)
{
- var availableResources = s_assetLoader.GetAssets(location, null);
+ var fileName = GetFileName(fontFamilyKey, out var fileExtension, out var location);
+
+ var availableResources = s_assetLoader.GetAssets(location, fontFamilyKey.BaseUri);
- var compareTo = location.AbsolutePath + "." + fileName.Split('*').First();
+ string compareTo;
- var matchingResources =
- availableResources.Where(x => x.AbsolutePath.Contains(compareTo) && (x.AbsolutePath.EndsWith(".ttf") || x.AbsolutePath.EndsWith(".otf")));
+ if (fontFamilyKey.Source.IsAbsoluteUri)
+ {
+ if (fontFamilyKey.Source.Scheme == "resm")
+ {
+ compareTo = location.AbsolutePath + "." + fileName.Split('*').First();
+ }
+ else
+ {
+ compareTo = location.AbsolutePath + fileName.Split('*').First();
+ }
+ }
+ else
+ {
+ compareTo = location.AbsolutePath + fileName.Split('*').First();
+ }
+
+ var matchingResources = availableResources.Where(
+ x => x.AbsolutePath.Contains(compareTo)
+ && x.AbsolutePath.EndsWith(fileExtension));
return matchingResources;
}
+ private static string GetFileName(FontFamilyKey fontFamilyKey, out string fileExtension, out Uri location)
+ {
+ if (fontFamilyKey.Source.IsAbsoluteUri && fontFamilyKey.Source.Scheme == "resm")
+ {
+ fileExtension = "." + fontFamilyKey.Source.AbsolutePath.Split('.').LastOrDefault();
+
+ var fileName = fontFamilyKey.Source.LocalPath.Replace(fileExtension, string.Empty).Split('.').LastOrDefault();
+
+ location = new Uri(fontFamilyKey.Source.AbsoluteUri.Replace("." + fileName + fileExtension, string.Empty), UriKind.RelativeOrAbsolute);
+
+ return fileName;
+ }
+
+ var pathSegments = fontFamilyKey.Source.OriginalString.Split('/');
+
+ var fileNameWithExtension = pathSegments.Last().Split('#').First();
+
+ var fileNameSegments = fileNameWithExtension.Split('.');
+
+ fileExtension = "." + fileNameSegments.Last();
+
+ if (fontFamilyKey.BaseUri != null)
+ {
+ location = new Uri(
+ fontFamilyKey.BaseUri,
+ fontFamilyKey.Source.OriginalString.Split('#')
+ .First()
+ .Replace(fileNameWithExtension, string.Empty));
+ }
+ else
+ {
+ location = new Uri(fontFamilyKey.Source.AbsolutePath.Replace(fileNameWithExtension, string.Empty));
+ }
+
+ return fileNameSegments.First();
+ }
}
}
diff --git a/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj b/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
index ec73859a0a..bb3883285a 100644
--- a/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
+++ b/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
@@ -10,6 +10,7 @@
+
diff --git a/src/Markup/Avalonia.Markup.Xaml/AvaloniaTypeConverters.cs b/src/Markup/Avalonia.Markup.Xaml/AvaloniaTypeConverters.cs
index 93db025343..fa9d364fc0 100644
--- a/src/Markup/Avalonia.Markup.Xaml/AvaloniaTypeConverters.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/AvaloniaTypeConverters.cs
@@ -11,6 +11,8 @@ using Avalonia.Controls.Templates;
namespace Avalonia.Markup.Xaml
{
+ using Avalonia.Media;
+
///
/// Maintains a repository of s for XAML parsing on top of those
/// maintained by .
@@ -37,8 +39,9 @@ namespace Avalonia.Markup.Xaml
{ typeof(Selector), typeof(SelectorTypeConverter) },
{ typeof(TimeSpan), typeof(TimeSpanTypeConverter) },
{ typeof(WindowIcon), typeof(IconTypeConverter) },
- { typeof(CultureInfo), typeof(CultureInfoConverter)},
- { typeof(Uri), typeof(AvaloniaUriTypeConverter)}
+ { typeof(CultureInfo), typeof(CultureInfoConverter) },
+ { typeof(Uri), typeof(AvaloniaUriTypeConverter) },
+ { typeof(FontFamily), typeof(FontFamilyTypeConverter) }
};
///
@@ -84,4 +87,4 @@ namespace Avalonia.Markup.Xaml
/// The converter type. Maybe be a non-constructed generic type.
public static void Register(Type type, Type converterType) => _converters[type] = converterType;
}
-}
\ No newline at end of file
+}
diff --git a/src/Markup/Avalonia.Markup.Xaml/Converters/FontFamilyTypeConverter.cs b/src/Markup/Avalonia.Markup.Xaml/Converters/FontFamilyTypeConverter.cs
new file mode 100644
index 0000000000..9b0e7a2b6b
--- /dev/null
+++ b/src/Markup/Avalonia.Markup.Xaml/Converters/FontFamilyTypeConverter.cs
@@ -0,0 +1,28 @@
+// Copyright (c) The Avalonia Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System;
+using System.ComponentModel;
+using System.Globalization;
+
+using Avalonia.Media;
+
+using Portable.Xaml.ComponentModel;
+
+namespace Avalonia.Markup.Xaml.Converters
+{
+ public class FontFamilyTypeConverter : TypeConverter
+ {
+ public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
+ {
+ return sourceType == typeof(string);
+ }
+
+ public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
+ {
+ var s = (string)value;
+
+ return FontFamily.Parse(s, context.GetBaseUri());
+ }
+ }
+}
diff --git a/tests/Avalonia.Visuals.UnitTests/Media/Fonts/FontFamilyKeyTests.cs b/tests/Avalonia.Visuals.UnitTests/Media/Fonts/FontFamilyKeyTests.cs
index 96464b5784..38ad9e1866 100644
--- a/tests/Avalonia.Visuals.UnitTests/Media/Fonts/FontFamilyKeyTests.cs
+++ b/tests/Avalonia.Visuals.UnitTests/Media/Fonts/FontFamilyKeyTests.cs
@@ -22,7 +22,7 @@ namespace Avalonia.Visuals.UnitTests.Media.Fonts
var fontFamilyKey = new FontFamilyKey(source);
- Assert.Equal(new Uri("resm:Avalonia.Visuals.UnitTests"), fontFamilyKey.Location);
+ Assert.Equal(new Uri("resm:Avalonia.Visuals.UnitTests"), fontFamilyKey.Source);
Assert.Null(fontFamilyKey.FileName);
}
@@ -34,7 +34,7 @@ namespace Avalonia.Visuals.UnitTests.Media.Fonts
var fontFamilyKey = new FontFamilyKey(source);
- Assert.Equal(new Uri("resm:Avalonia.Visuals.UnitTests"), fontFamilyKey.Location);
+ Assert.Equal(new Uri("resm:Avalonia.Visuals.UnitTests"), fontFamilyKey.Source);
Assert.Equal("MyFont.ttf", fontFamilyKey.FileName);
}