Skip to content

Commit

Permalink
Resolve and load fonts from filename first
Browse files Browse the repository at this point in the history
Instead of loading font files into an NSData object via a .NET managed stream, load them by filename via the CGDataProvider directly (no need to marshal the file byte data).

This also mitigates the issue addressed in dotnet/runtime#61153 for the specific instance encountered by loading fonts this way.
  • Loading branch information
Redth committed Dec 8, 2021
1 parent eafe047 commit f3cc3bb
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 13 deletions.
23 changes: 17 additions & 6 deletions src/Core/src/Fonts/EmbeddedFontLoader.iOS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,25 @@ public partial class EmbeddedFontLoader
{
try
{
CGFont? cgFont;

if (font.ResourceStream == null)
throw new InvalidOperationException("ResourceStream was null.");
{
if (!System.IO.File.Exists(font.FontName))
throw new InvalidOperationException("ResourceStream was null.");

var data = NSData.FromStream(font.ResourceStream);
if (data == null)
throw new InvalidOperationException("Unable to load font stream data.");
var provider = new CGDataProvider(data);
var cgFont = CGFont.CreateFromProvider(provider);
var provider = new CGDataProvider(font.FontName);
cgFont = CGFont.CreateFromProvider(provider);
}
else
{
var data = NSData.FromStream(font.ResourceStream);
if (data == null)
throw new InvalidOperationException("Unable to load font stream data.");
var provider = new CGDataProvider(data);
cgFont = CGFont.CreateFromProvider(provider);
}

if (cgFont == null)
throw new InvalidOperationException("Unable to load font from the stream.");

Expand Down
12 changes: 12 additions & 0 deletions src/Core/src/Fonts/FontRegistrar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,18 @@ public void Register(string filename, string? alias)
return _fontLookupCache[font] = null;
}

string? LoadFileSystemFont(string cacheKey, string filename, string? alias)
{
var font = new EmbeddedFont { FontName = filename };

if (_fontLoader == null)
throw new InvalidOperationException("Font loader was not set on the font registrar.");

var result = _fontLoader.LoadFont(font);

return _fontLookupCache[cacheKey] = result;
}

string? LoadEmbeddedFont(string cacheKey, string filename, string? alias, Stream stream)
{
var font = new EmbeddedFont { FontName = filename, ResourceStream = stream };
Expand Down
29 changes: 22 additions & 7 deletions src/Core/src/Fonts/FontRegistrar.iOS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@ public partial class FontRegistrar : IFontRegistrar
{
string? LoadNativeAppFont(string font, string filename, string? alias)
{
using var stream = GetNativeFontStream(filename, alias);
var resolvedFilename = ResolveFileSystemFont(filename);

return LoadEmbeddedFont(font, filename, alias, stream);
if (!string.IsNullOrEmpty(resolvedFilename))
return LoadFileSystemFont(font, resolvedFilename, alias);

return LoadEmbeddedFont(font, filename, alias, GetNativeFontStream(filename, alias));
}

Stream GetNativeFontStream(string filename, string? alias)
string? ResolveFileSystemFont(string filename)
{
var mainBundlePath = Foundation.NSBundle.MainBundle.BundlePath;

Expand All @@ -23,22 +26,34 @@ Stream GetNativeFontStream(string filename, string? alias)

var fontBundlePath = Path.Combine(mainBundlePath, filename);
if (File.Exists(fontBundlePath))
return File.OpenRead(fontBundlePath);
return fontBundlePath;

fontBundlePath = Path.Combine(mainBundlePath, "Resources", filename);
if (File.Exists(fontBundlePath))
return File.OpenRead(fontBundlePath);
return fontBundlePath;

fontBundlePath = Path.Combine(mainBundlePath, "Fonts", filename);
if (File.Exists(fontBundlePath))
return File.OpenRead(fontBundlePath);
return fontBundlePath;

fontBundlePath = Path.Combine(mainBundlePath, "Resources", "Fonts", filename);
if (File.Exists(fontBundlePath))
return File.OpenRead(fontBundlePath);
return fontBundlePath;

// TODO: check other folders as well

return null;
}

Stream GetNativeFontStream(string filename, string? alias)
{
var resolvedFilename = ResolveFileSystemFont(filename);

if (!string.IsNullOrEmpty(resolvedFilename) && File.Exists(resolvedFilename))
{
return File.OpenRead(resolvedFilename);
}

throw new FileNotFoundException($"Native font with the name {filename} was not found.");
}
}
Expand Down

0 comments on commit f3cc3bb

Please sign in to comment.