Skip to content

Commit

Permalink
chore: Wasm - in progress
Browse files Browse the repository at this point in the history
  • Loading branch information
Youssef1313 committed Jun 18, 2024
1 parent 4482696 commit 9fdb66b
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 78 deletions.
58 changes: 0 additions & 58 deletions src/Uno.UI/UI/Xaml/FontFamily.wasm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,69 +14,11 @@ public partial class FontFamily
{
private FontFamilyLoader _loader;


/// <summary>
/// Contains the font-face name to use in CSS.
/// </summary>
internal string CssFontName { get; private set; }

internal string? ExternalSource { get; private set; }

partial void Init(string fontName)
{
ParseSource(Source);
_loader = FontFamilyLoader.GetLoaderForFontFamily(this);
}

[MemberNotNull(nameof(CssFontName))]
private void ParseSource(string source)
{
var sourceParts = source.Split('#', 2, StringSplitOptions.RemoveEmptyEntries);

if (sourceParts.Length > 0)
{
if (TryGetExternalUri(sourceParts[0], out var externalUri) && externalUri is { })
{
ExternalSource = externalUri.OriginalString;
CssFontName = "font" + ExternalSource.GetHashCode();
}
else
{
CssFontName = sourceParts[sourceParts.Length == 2 ? 1 : 0];
}
}
else
{
throw new InvalidOperationException("FontFamily source cannot be empty");
}
}

private static bool TryGetExternalUri(string? source, out Uri? uri)
{
if (source is not null && (source.IndexOf('.') > -1 || source.IndexOf('/') > -1))
{
uri = new Uri(source, UriKind.RelativeOrAbsolute);

if (!uri.IsAbsoluteUri || source.StartsWith('/'))
{
// Support for implicit ms-appx resolution
var assetUri = AssetsPathBuilder.BuildAssetUri(Uri.EscapeDataString(source.TrimStart('/')).Replace("%2F", "/"));
uri = new Uri(assetUri, UriKind.RelativeOrAbsolute);
}

if (Uno.UI.Xaml.XamlFilePathHelper.TryGetMsAppxAssetPath(uri, out var path))
{
var assetUri = AssetsPathBuilder.BuildAssetUri(path);
uri = new Uri(assetUri, UriKind.RelativeOrAbsolute);
}

return true;
}

uri = default;
return false;
}

/// <summary>
/// Use this to launch the loading of a font before it is actually required to
/// minimize loading time and prevent potential flicking.
Expand Down
86 changes: 67 additions & 19 deletions src/Uno.UI/UI/Xaml/FontFamilyLoader.wasm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace Microsoft.UI.Xaml.Media;
/// </summary>
internal partial class FontFamilyLoader
{
private static readonly Dictionary<FontFamily, FontFamilyLoader> _loaders = new(new FontFamilyComparer());
private static readonly Dictionary<string, FontFamilyLoader> _loaders = new();
private static readonly Dictionary<string, FontFamilyLoader> _loadersFromCssName = new();

private readonly FontFamily _fontFamily;
Expand All @@ -29,12 +29,19 @@ internal partial class FontFamilyLoader

public bool IsLoading { get; private set; }

/// <summary>
/// Contains the font-face name to use in CSS.
/// </summary>
internal string CssFontName { get; private set; }

internal string? ExternalSource { get; private set; }

/// <summary>
/// Gets a loader for the specific <see cref="FontFamily"/>
/// </summary>
internal static FontFamilyLoader GetLoaderForFontFamily(FontFamily forFamily)
{
if (_loaders.TryGetValue(forFamily, out var loader))
if (_loaders.TryGetValue(forFamily.Source, out var loader))
{
// There is already a loader for this font family
return loader;
Expand All @@ -48,13 +55,63 @@ internal static FontFamilyLoader GetLoaderForFontFamily(FontFamily forFamily)
private FontFamilyLoader(FontFamily fontFamily)
{
_fontFamily = fontFamily;
ParseSource(fontFamily.Source);

if (this.Log().IsEnabled(LogLevel.Debug))
{
this.Log().Debug($"Creating font loader for {fontFamily.Source}");
}

_loaders.Add(fontFamily, this);
_loaders.Add(fontFamily.Source, this);
}

[MemberNotNull(nameof(CssFontName))]
private void ParseSource(string source)
{
var sourceParts = source.Split('#', 2, StringSplitOptions.RemoveEmptyEntries);

if (sourceParts.Length > 0)
{
if (TryGetExternalUri(sourceParts[0], out var externalUri) && externalUri is { })
{
ExternalSource = externalUri.OriginalString;
CssFontName = "font" + ExternalSource.GetHashCode();
}
else
{
CssFontName = sourceParts[sourceParts.Length == 2 ? 1 : 0];
}
}
else
{
throw new InvalidOperationException("FontFamily source cannot be empty");
}
}

private static bool TryGetExternalUri(string? source, out Uri? uri)
{
if (source is not null && (source.IndexOf('.') > -1 || source.IndexOf('/') > -1))
{
uri = new Uri(source, UriKind.RelativeOrAbsolute);

if (!uri.IsAbsoluteUri || source.StartsWith('/'))
{
// Support for implicit ms-appx resolution
var assetUri = AssetsPathBuilder.BuildAssetUri(Uri.EscapeDataString(source.TrimStart('/')).Replace("%2F", "/"));
uri = new Uri(assetUri, UriKind.RelativeOrAbsolute);
}

if (Uno.UI.Xaml.XamlFilePathHelper.TryGetMsAppxAssetPath(uri, out var path))
{
var assetUri = AssetsPathBuilder.BuildAssetUri(path);
uri = new Uri(assetUri, UriKind.RelativeOrAbsolute);
}

return true;
}

uri = default;
return false;
}

/// <summary>
Expand Down Expand Up @@ -178,19 +235,19 @@ internal async Task<bool> LoadFontAsync()

if (this.Log().IsEnabled(LogLevel.Debug))
{
this.Log().Debug($"Loading font: {_fontFamily.Source} ({_fontFamily.CssFontName}/{_fontFamily.ExternalSource}, {_loadersFromCssName.Count} loaders active)");
this.Log().Debug($"Loading font: {_fontFamily.Source} ({CssFontName}/{ExternalSource}, {_loadersFromCssName.Count} loaders active)");
}

IsLoading = true;
_loadersFromCssName.Add(_fontFamily.CssFontName, this);
_loadersFromCssName.Add(CssFontName, this);

if (_fontFamily.ExternalSource is { Length: > 0 })
if (ExternalSource is { Length: > 0 })
{
NativeMethods.LoadFont(_fontFamily.CssFontName, _fontFamily.ExternalSource);
NativeMethods.LoadFont(CssFontName, ExternalSource);
}
else
{
NativeMethods.ForceFontUsage(_fontFamily.CssFontName);
NativeMethods.ForceFontUsage(CssFontName);
}

_loadOperation = new TaskCompletionSource<bool>();
Expand All @@ -200,21 +257,12 @@ internal async Task<bool> LoadFontAsync()
{
if (this.Log().IsEnabled(LogLevel.Error))
{
this.Log().Error($"Failed loading font: {_fontFamily.Source} ({_fontFamily.CssFontName}/{_fontFamily.ExternalSource}, {_loadersFromCssName.Count} loaders active)", e);
this.Log().Error($"Failed loading font: {_fontFamily.Source} ({CssFontName}/{ExternalSource}, {_loadersFromCssName.Count} loaders active)", e);
}

NotifyFontLoadFailed(_fontFamily.CssFontName);
NotifyFontLoadFailed(CssFontName);

return false;
}
}

private class FontFamilyComparer : IEqualityComparer<FontFamily>
{
public bool Equals(FontFamily? x, FontFamily? y)
=> string.Equals(x!.CssFontName, y!.CssFontName, StringComparison.OrdinalIgnoreCase);

public int GetHashCode(FontFamily obj)
=> obj.CssFontName.GetHashCode();
}
}
2 changes: 1 addition & 1 deletion src/Uno.UI/UI/Xaml/UIElement.TextHelper.wasm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ internal void SetFontFamily(object localValue)
{
font = FontFamily.Default;
}

// TODO: Maybe introduce CssFontNamePrefix to FontFamily, and use something like $"{font.CssFontNamePrefix}_{FontStyle}_{FontWeight}_{FontStretch}" ?
SetStyle("font-family", font.CssFontName);

font.RegisterForInvalidateMeasureOnFontLoaded(this);
Expand Down

0 comments on commit 9fdb66b

Please sign in to comment.