Skip to content

Commit

Permalink
Support reading fonts from files (#14783)
Browse files Browse the repository at this point in the history
  • Loading branch information
mattleibow authored Apr 26, 2023
1 parent 05d68fd commit 55091d4
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 34 deletions.
22 changes: 14 additions & 8 deletions src/Core/src/Fonts/FontManager.Windows.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
using System.IO;
using Microsoft.Extensions.Logging;
using Microsoft.Graphics.Canvas.Text;
using Microsoft.Maui.ApplicationModel;
using Microsoft.Maui.Storage;
using Microsoft.UI.Xaml.Media;

namespace Microsoft.Maui
Expand Down Expand Up @@ -146,16 +148,20 @@ IEnumerable<string> GetAllFontPossibilities(string fontFamily)
{
var fontUri = new Uri(fontFile, UriKind.RelativeOrAbsolute);

// CanvasFontSet only supports ms-appx:// and ms-appdata:// font URIs
if (fontUri.IsAbsoluteUri && (fontUri.Scheme == "ms-appx" || fontUri.Scheme == "ms-appdata"))
// unpackaged apps can't load files using packaged schemes
if (!AppInfoUtils.IsPackagedApp)
{
using (var fontSet = new CanvasFontSet(fontUri))
var path = fontUri.AbsolutePath.TrimStart('/');
if (FileSystemUtils.TryGetAppPackageFileUri(path, out var uri))
fontUri = new Uri(uri, UriKind.RelativeOrAbsolute);
}

using (var fontSet = new CanvasFontSet(fontUri))
{
if (fontSet.Fonts.Count != 0)
{
if (fontSet.Fonts.Count != 0)
{
var props = fontSet.GetPropertyValues(CanvasFontPropertyIdentifier.FamilyName);
return props.Length == 0 ? null : props[0].Value;
}
var props = fontSet.GetPropertyValues(CanvasFontPropertyIdentifier.FamilyName);
return props.Length == 0 ? null : props[0].Value;
}
}

Expand Down
11 changes: 10 additions & 1 deletion src/Core/tests/DeviceTests/Core.DeviceTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@
<ApplicationVersion>1</ApplicationVersion>
</PropertyGroup>

<PropertyGroup>
<!--
Uncomment the below to enabled unpackaged apps and change the
value of the "commandName" in the Properties\launchSettings.json
from "MsixPackage" to "Project".
-->
<!-- <WindowsPackageType>None</WindowsPackageType> -->
</PropertyGroup>

<ItemGroup>
<MauiIcon Include="Resources\appicon.svg" ForegroundFile="Resources\appiconfg.svg" Color="#512BD4" />
<MauiSplashScreen Include="Resources\appiconfg.svg" Color="#512BD4" BaseSize="128,128" />
Expand Down Expand Up @@ -45,10 +54,10 @@
<None Include="@(Compile)" />
</ItemGroup>
<ItemGroup Condition="$(TargetFramework.Contains('-windows'))">
<Compile Remove="Handlers\Fonts\*.cs" />
<Compile Remove="Handlers\Image\*.cs" />
<Compile Remove="Handlers\ImageButton\*.cs" />
<Compile Remove="Handlers\ShapeView\*.cs" />
<Content Include="Platforms\Windows\Assets\**" Link="Assets\%(RecursiveDir)%(Filename)%(Extension)" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
<ItemGroup Condition="!$(TargetFramework.Contains('-android'))">
<Compile Remove="**\*.Android.cs" />
Expand Down
Binary file not shown.
40 changes: 40 additions & 0 deletions src/Core/tests/DeviceTests/Services/FontManagerTests.Windows.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System;
using System.Threading.Tasks;
using Xunit;

namespace Microsoft.Maui.DeviceTests;

public partial class FontManagerTests : TestBase
{
[Theory]
[InlineData("dokdo_regular", "ms-appx:///dokdo_regular.ttf#Dokdo")]
[InlineData("dokdo_regular.ttf", "ms-appx:///dokdo_regular.ttf#Dokdo")]
[InlineData("dokdo_regular#dokdo", "ms-appx:///dokdo_regular.ttf#Dokdo")]
[InlineData("dokdo_regular.ttf#dokdo", "ms-appx:///dokdo_regular.ttf#Dokdo")]
[InlineData("myalias", "ms-appx:///dokdo_regular.ttf#Dokdo")]
public Task CanLoadFonts(string fontName, string actualFontFamily) =>
InvokeOnMainThreadAsync(() =>
{
var registrar = new FontRegistrar(fontLoader: null);
registrar.Register("dokdo_regular.ttf", "myalias");
var manager = new FontManager(registrar);

var actual = manager.GetFontFamily(Font.OfSize(fontName, 12, FontWeight.Regular));

Assert.Equal(actualFontFamily, actual.Source);
});

// TODO: this is not going to work in unpackaged
[Fact]
public Task CanLoadEmbeddedFont() =>
InvokeOnMainThreadAsync(() =>
{
var registrar = new FontRegistrar(new EmbeddedFontLoader());
registrar.Register("dokdo_regular.ttf", "myalias", GetType().Assembly);
var manager = new FontManager(registrar);

var actual = manager.GetFontFamily(Font.OfSize("myalias", 12, FontWeight.Regular));

Assert.Equal("ms-appdata:///local/fonts/dokdo_regular.ttf#Dokdo", actual.Source);
});
}
25 changes: 0 additions & 25 deletions src/Essentials/src/FileSystem/FileSystem.uwp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,31 +50,6 @@ Task<bool> PlatformAppPackageFileExistsAsync(string filename)
}
}

static partial class FileSystemUtils
{
public static bool AppPackageFileExists(string filename)
{
var file = PlatformGetFullAppPackageFilePath(filename);
return File.Exists(file);
}

public static string PlatformGetFullAppPackageFilePath(string filename)
{
if (filename == null)
throw new ArgumentNullException(nameof(filename));

filename = NormalizePath(filename);

string root;
if (AppInfoUtils.IsPackagedApp)
root = Package.Current.InstalledLocation.Path;
else
root = AppContext.BaseDirectory;

return Path.Combine(root, filename);
}
}

public partial class FileBase
{
internal FileBase(IStorageFile file)
Expand Down
52 changes: 52 additions & 0 deletions src/Essentials/src/FileSystem/FileSystemUtils.uwp.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#nullable enable
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using Microsoft.Maui.ApplicationModel;
using Package = Windows.ApplicationModel.Package;

namespace Microsoft.Maui.Storage
{
static partial class FileSystemUtils
{
public static bool AppPackageFileExists(string filename)
{
var file = PlatformGetFullAppPackageFilePath(filename);
return File.Exists(file);
}

public static string PlatformGetFullAppPackageFilePath(string filename)
{
if (filename is null)
throw new ArgumentNullException(nameof(filename));

filename = NormalizePath(filename);

string root;
if (AppInfoUtils.IsPackagedApp)
root = Package.Current.InstalledLocation.Path;
else
root = AppContext.BaseDirectory;

return Path.Combine(root, filename);
}

public static bool TryGetAppPackageFileUri(string filename, [NotNullWhen(true)] out string? uri)
{
var path = PlatformGetFullAppPackageFilePath(filename);

if (File.Exists(path))
{
if (AppInfoUtils.IsPackagedApp)
uri = $"ms-appx:///{filename.Replace('\\', '/')}";
else
uri = $"file:///{path.Replace('\\', '/')}";

return true;
}

uri = null;
return false;
}
}
}

0 comments on commit 55091d4

Please sign in to comment.