From a59cf3a135e4785571f1b80c569e0b6e2ec34f3b Mon Sep 17 00:00:00 2001 From: Benedikt Schroeder Date: Wed, 23 May 2018 19:36:42 +0200 Subject: [PATCH] New asset loader Added unit test for wildcard --- src/Avalonia.Base/Platform/IAssetLoader.cs | 26 ++++++------ .../Media/Fonts/FontFamilyLoader.cs | 7 ++-- src/Shared/PlatformSupport/AssetLoader.cs | 34 +++++++++------ tests/Avalonia.UnitTests/MockAssetLoader.cs | 7 ++-- .../Media/Fonts/FontFamilyLoaderTests.cs | 42 ++++++++++++++++--- 5 files changed, 77 insertions(+), 39 deletions(-) diff --git a/src/Avalonia.Base/Platform/IAssetLoader.cs b/src/Avalonia.Base/Platform/IAssetLoader.cs index 767ce4ad8e..dda2cbc2d5 100644 --- a/src/Avalonia.Base/Platform/IAssetLoader.cs +++ b/src/Avalonia.Base/Platform/IAssetLoader.cs @@ -19,8 +19,8 @@ namespace Avalonia.Platform /// AssetLoader needs a refactor cause right now it lives in 3+ platforms which /// can all be loaded on Windows. /// - /// - void SetDefaultAssembly(Assembly asm); + /// + void SetDefaultAssembly(Assembly assembly); /// /// Checks if an asset with the specified URI exists. @@ -33,39 +33,39 @@ namespace Avalonia.Platform bool Exists(Uri uri, Uri baseUri = null); /// - /// Opens the resource with the requested URI. + /// Opens the asset with the requested URI. /// /// The URI. /// /// A base URI to use if is relative. /// - /// A stream containing the resource contents. + /// A stream containing the asset contents. /// - /// The resource was not found. + /// The asset could not be found. /// Stream Open(Uri uri, Uri baseUri = null); /// - /// Opens the resource with the requested URI and returns the resource string and the - /// assembly containing the resource. + /// Opens the asset with the requested URI and returns the asset stream and the + /// assembly containing the asset. /// /// The URI. /// /// A base URI to use if is relative. /// /// - /// The stream containing the resource contents together with the assembly. + /// The stream containing the asset contents together with the assembly. /// /// - /// The resource was not found. + /// The asset could not be found. /// (Stream stream, Assembly assembly) OpenAndGetAssembly(Uri uri, Uri baseUri = null); /// - /// Gets all assets at a specific location. + /// Gets all assets of a folder and subfolders that match specified uri. /// - /// The location of assets. - /// A tuple containing the absolute path to the resource and the owner assembly - IEnumerable<(string absolutePath, Assembly assembly)> GetAssets(Uri location); + /// The URI. + /// All matching assets as a tuple of the absolute path to the asset and the assembly containing the asset + IEnumerable<(string absolutePath, Assembly assembly)> GetAssets(Uri uri); } } diff --git a/src/Avalonia.Visuals/Media/Fonts/FontFamilyLoader.cs b/src/Avalonia.Visuals/Media/Fonts/FontFamilyLoader.cs index 803d15d49f..2b77371bb5 100644 --- a/src/Avalonia.Visuals/Media/Fonts/FontFamilyLoader.cs +++ b/src/Avalonia.Visuals/Media/Fonts/FontFamilyLoader.cs @@ -34,9 +34,7 @@ namespace Avalonia.Media.Fonts { var availableAssets = s_assetLoader.GetAssets(location); - var locationPath = location.AbsolutePath; - - var matchingAssets = availableAssets.Where(x => x.absolutePath.Contains(locationPath) && x.absolutePath.EndsWith(".ttf")); + var matchingAssets = availableAssets.Where(x => x.absolutePath.EndsWith(".ttf")); return matchingAssets.Select(x => GetAssetUri(x.absolutePath, x.assembly)); } @@ -54,7 +52,8 @@ namespace Avalonia.Media.Fonts var compareTo = location.AbsolutePath + "." + fileName.Split('*').First(); - var matchingResources = availableResources.Where(x => x.absolutePath.Contains(compareTo)); + var matchingResources = + availableResources.Where(x => x.absolutePath.Contains(compareTo) && x.absolutePath.EndsWith(".ttf")); return matchingResources.Select(x => GetAssetUri(x.absolutePath, x.assembly)); } diff --git a/src/Shared/PlatformSupport/AssetLoader.cs b/src/Shared/PlatformSupport/AssetLoader.cs index d4f0ba6d17..b4d17b22a1 100644 --- a/src/Shared/PlatformSupport/AssetLoader.cs +++ b/src/Shared/PlatformSupport/AssetLoader.cs @@ -57,21 +57,21 @@ namespace Avalonia.Shared.PlatformSupport } /// - /// Opens the resource with the requested URI. + /// Opens the asset with the requested URI. /// /// The URI. /// /// A base URI to use if is relative. /// - /// A stream containing the resource contents. + /// A stream containing the asset contents. /// - /// The resource was not found. + /// The asset could not be found. /// - public Stream Open(Uri uri, Uri baseUri = null) => OpenAndGetAssembly(uri, baseUri).stream; + public Stream Open(Uri uri, Uri baseUri = null) => OpenAndGetAssembly(uri, baseUri).Item1; /// - /// Opens the resource with the requested URI and returns the resource string and the - /// assembly containing the resource. + /// Opens the asset with the requested URI and returns the asset stream and the + /// assembly containing the asset. /// /// The URI. /// @@ -81,7 +81,7 @@ namespace Avalonia.Shared.PlatformSupport /// The stream containing the resource contents together with the assembly. /// /// - /// The resource was not found. + /// The asset could not be found. /// public (Stream stream, Assembly assembly) OpenAndGetAssembly(Uri uri, Uri baseUri = null) { @@ -95,11 +95,17 @@ namespace Avalonia.Shared.PlatformSupport return (asset.GetStream(), asset.Assembly); } - public IEnumerable<(string absolutePath, Assembly assembly)> GetAssets(Uri location) + /// + /// Gets all assets of a folder and subfolders that match specified uri. + /// + /// The URI. + /// All matching assets as a tuple of the absolute path to the asset and the assembly containing the asset + public IEnumerable<(string absolutePath, Assembly assembly)> GetAssets(Uri uri) { - var assembly = GetAssembly(location); + var assembly = GetAssembly(uri); - return assembly?.Resources.Select(x => (x.Key, x.Value.Assembly)) ?? + return assembly?.Resources.Where(x => x.Key.Contains(uri.AbsolutePath)) + .Select(x => (x.Key, x.Value.Assembly)) ?? Enumerable.Empty<(string AbsolutePath, Assembly Assembly)>(); } @@ -130,8 +136,9 @@ namespace Avalonia.Shared.PlatformSupport if (uri != null) { var qs = ParseQueryString(uri); + string assemblyName; - if (qs.TryGetValue("assembly", out var assemblyName)) + if (qs.TryGetValue("assembly", out assemblyName)) { return GetAssembly(assemblyName); } @@ -147,7 +154,8 @@ namespace Avalonia.Shared.PlatformSupport return _defaultAssembly; } - if (!AssemblyNameCache.TryGetValue(name, out var rv)) + AssemblyDescriptor rv; + if (!AssemblyNameCache.TryGetValue(name, out rv)) { var loadedAssemblies = AvaloniaLocator.Current.GetService().GetLoadedAssemblies(); var match = loadedAssemblies.FirstOrDefault(a => a.GetName().Name == name); @@ -225,4 +233,4 @@ namespace Avalonia.Shared.PlatformSupport public string Name { get; } } } -} +} \ No newline at end of file diff --git a/tests/Avalonia.UnitTests/MockAssetLoader.cs b/tests/Avalonia.UnitTests/MockAssetLoader.cs index cebd88b6a0..11d66128a7 100644 --- a/tests/Avalonia.UnitTests/MockAssetLoader.cs +++ b/tests/Avalonia.UnitTests/MockAssetLoader.cs @@ -26,15 +26,16 @@ namespace Avalonia.UnitTests { return new MemoryStream(Encoding.UTF8.GetBytes(_assets[uri])); } - + public (Stream stream, Assembly assembly) OpenAndGetAssembly(Uri uri, Uri baseUri = null) { return (Open(uri, baseUri), (Assembly)null); } - public IEnumerable<(string absolutePath, Assembly assembly)> GetAssets(Uri location) + public IEnumerable<(string absolutePath, Assembly assembly)> GetAssets(Uri uri) { - return _assets.Keys.Select(x => (x.AbsolutePath, Assembly.GetEntryAssembly())); + return _assets.Keys.Where(x => x.AbsolutePath.Contains(uri.AbsolutePath)) + .Select(x => (x.AbsolutePath, Assembly.GetEntryAssembly())); } public void SetDefaultAssembly(Assembly asm) diff --git a/tests/Avalonia.Visuals.UnitTests/Media/Fonts/FontFamilyLoaderTests.cs b/tests/Avalonia.Visuals.UnitTests/Media/Fonts/FontFamilyLoaderTests.cs index ef7171d651..81bf638f14 100644 --- a/tests/Avalonia.Visuals.UnitTests/Media/Fonts/FontFamilyLoaderTests.cs +++ b/tests/Avalonia.Visuals.UnitTests/Media/Fonts/FontFamilyLoaderTests.cs @@ -11,20 +11,50 @@ namespace Avalonia.Visuals.UnitTests.Media.Fonts { public class FontFamilyLoaderTests { + private const string fontName = "#MyFont"; + private const string assembly = "?assembly=Avalonia.Visuals.UnitTests"; + private const string assetLocation = "resm:Avalonia.Visuals.UnitTests.Assets"; + + [Fact] + public void Should_Load_Single_FontAsset() + { + const string fontAsset = assetLocation + ".MyFont-Regular.ttf" + assembly + fontName; + + using (StartWithResources((fontAsset, "AssetData"))) + { + var source = new Uri(fontAsset, UriKind.RelativeOrAbsolute); + + var key = new FontFamilyKey(source); + + var fontAssets = FontFamilyLoader.LoadFontAssets(key); + + Assert.Single(fontAssets); + } + } + [Fact] - public void Should_Load_Single_FontResource() + public void Should_Load_Matching_Assets() { - const string resourcePath = "resm:Avalonia.Visuals.UnitTests.Assets.MyFont.ttf?assembly=Avalonia.Visuals.UnitTests#MyFont"; + const string assetMyFontRegular = assetLocation + ".MyFont-Regular.ttf" + assembly + fontName; + const string assetMyFontBold = assetLocation + ".MyFont-Bold.ttf" + assembly + fontName; + const string assetYourFont = assetLocation + ".YourFont.ttf" + assembly + fontName; + + var fontLocations = new[] + { + (assetMyFontRegular, "AssetData"), + (assetMyFontBold, "AssetData"), + (assetYourFont, "AssetData") + }; - using (StartWithResources((resourcePath, "MyFont.ttf"))) + using (StartWithResources(fontLocations)) { - var source = new Uri(resourcePath, UriKind.RelativeOrAbsolute); + var source = new Uri(assetLocation + ".MyFont-*.ttf", UriKind.RelativeOrAbsolute); var key = new FontFamilyKey(source); - var resources = FontFamilyLoader.LoadFontAssets(key); + var fontAssets = FontFamilyLoader.LoadFontAssets(key); - Assert.Single(resources); + Assert.Equal(2, fontAssets.Count()); } }