Skip to content

Commit

Permalink
feat: Support for Font manifest on iOS
Browse files Browse the repository at this point in the history
  • Loading branch information
MartinZikmund committed Jul 5, 2024
1 parent 9c473e6 commit 96b74ae
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 32 deletions.
8 changes: 6 additions & 2 deletions src/Uno.UI/Controls/UIStringAttributesHelper.iOS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using Microsoft.UI.Xaml.Documents;
using UIKit;
using Uno.Extensions;
using Uno.UI.Xaml;

namespace Uno.UI
{
Expand All @@ -15,6 +16,7 @@ private static Func<
(
FontWeight fontWeight,
FontStyle fontStyle,
FontStretch fontStretch,
FontFamily fontFamily,
Brush foreground,
double fontSize,
Expand All @@ -35,6 +37,7 @@ static UIStringAttributesHelper()
internal static UIStringAttributes GetAttributes(
FontWeight fontWeight,
FontStyle fontStyle,
FontStretch fontStretch,
FontFamily fontFamily,
Brush foreground,
double fontSize,
Expand All @@ -43,12 +46,13 @@ internal static UIStringAttributes GetAttributes(
TextDecorations textDecorations
)
{
return _getAttributes((fontWeight, fontStyle, fontFamily, foreground, fontSize, characterSpacing, baseLineAlignment, textDecorations, UIFont.PreferredBody.FontDescriptor.FontAttributes.Size));
return _getAttributes((fontWeight, fontStyle, fontStretch, fontFamily, foreground, fontSize, characterSpacing, baseLineAlignment, textDecorations, UIFont.PreferredBody.FontDescriptor.FontAttributes.Size));
}

private static UIStringAttributes InternalGetAttributes((
FontWeight fontWeight,
FontStyle fontStyle,
FontStretch fontStretch,
FontFamily fontFamily,
Brush foreground,
double fontSize,
Expand All @@ -74,7 +78,7 @@ private static UIStringAttributes InternalGetAttributes((
}
}

var font = FontHelper.TryGetFont((float)tuple.fontSize, tuple.fontWeight, tuple.fontStyle, tuple.fontFamily, tuple.preferredBodyFontSize);
var font = FontHelper.TryGetFont(new((float)tuple.fontSize, tuple.fontWeight, tuple.fontStyle, tuple.fontStretch), tuple.fontFamily, tuple.preferredBodyFontSize);
var attributes = new UIStringAttributes()
{
// TODO: Handle other brushes.
Expand Down
1 change: 1 addition & 0 deletions src/Uno.UI/UI/Xaml/Documents/InlineExtensions.iOS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ internal static UIStringAttributes GetAttributes(this Inline inline)
return Uno.UI.UIStringAttributesHelper.GetAttributes(
inline.FontWeight,
inline.FontStyle,
inline.FontStretch,
inline.FontFamily,
inline.Foreground,
inline.FontSize,
Expand Down
96 changes: 66 additions & 30 deletions src/Uno.UI/UI/Xaml/Extensions/FontHelper.iOS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,27 +115,25 @@ private static nfloat GetScaledFontSize(nfloat size, nfloat? basePreferredSize)

return ApplyStyle(
UIFont.SystemFontOfSize(properties.Size, properties.Weight.ToUIFontWeight()),
properties.Size,
properties.Style);
properties);
}

#region Load Custom Font

private static string TryAdjustFromManifest(string source, FontProperties properties)
private static string TryAdjustFromManifest(NSUrl manifestUrl, FontProperties properties)
{
var manifestPath = source + ".manifest";
manifestPath = AssetsHelper.FindAssetFile(manifestPath);
var fontData = NSData.FromUrl(manifestUrl);

if (manifestPath is not null)
{
using var jsonStream = ContextHelper.Current.Assets!.Open(manifestPath);
var fontStyle = (style & TypefaceStyle.Italic) != 0 ? FontStyle.Italic : FontStyle.Normal;
var familyName = FontManifestHelpers.GetFamilyNameFromManifest(jsonStream, properties.Weight, properties.Style, properties.Stretch);
familyName = familyName.TrimStart("ms-appx://", ignoreCase: true);
return encodePath ? AndroidResourceNameEncoder.EncodeFileSystemPath(familyName, prefix: "") : familyName;
}
using var jsonStream = new MemoryStream(fontData.ToArray());
var familyName = FontManifestHelpers.GetFamilyNameFromManifest(
jsonStream,
properties.Weight,
properties.Style,
properties.Stretch);

familyName = familyName.TrimStart("ms-appx://", ignoreCase: true);

return source;
return familyName;
}

private static UIFont? GetCustomFont(string fontPath, FontProperties fontProperties)
Expand All @@ -149,7 +147,31 @@ private static string TryAdjustFromManifest(string source, FontProperties proper
UIFont? font;
//In Windows we define FontFamily with the path to the font file followed by the font family name, separated by a #
var indexOfHash = fontPath.IndexOf('#');

var actualFontPath = "";
bool testFontFamilyName = false;
bool skipAdjustments = false;
if (indexOfHash > 0 && indexOfHash < fontPath.Length - 1)
{
actualFontPath = fontPath.Substring(0, indexOfHash);
}
else
{
actualFontPath = fontPath;
}

if (GetFontManifestUrl(actualFontPath) is { } manifestUrl &&
TryAdjustFromManifest(manifestUrl, fontProperties) is { } adjustedPath)
{
fontPath = adjustedPath;
skipAdjustments = true;
}
else
{
testFontFamilyName = true;
}

if (testFontFamilyName && indexOfHash > 0 && indexOfHash < fontPath.Length - 1)
{
font = GetFontFromFamilyName(fontProperties.Size, fontPath.Substring(indexOfHash + 1))
?? GetFontFromFile(fontProperties.Size, fontPath.Substring(0, indexOfHash));
Expand All @@ -164,45 +186,59 @@ private static string TryAdjustFromManifest(string source, FontProperties proper
font = GetDefaultFont(fontProperties);
}

if (font is not null)
if (font is not null && !skipAdjustments)
{
font = ApplyFontProperties(font, fontProperties);
//font = ApplyFontProperties(font, fontProperties);
}

return font;
}

private static NSUrl? GetFontManifestUrl(string actualFontPath)
{
var fileName = actualFontPath;
var fileExtension = "manifest";

var url = NSBundle
.MainBundle
.GetUrlForResource(
name: Path.GetFileName(fileName),
fileExtension: fileExtension,
subdirectory: Path.GetDirectoryName(actualFontPath));

return url;
}

private static UIFont ApplyFontProperties(UIFont font, FontProperties fontProperties)
{
font = ApplyWeight(font, size, fontWeight);
font = ApplyStyle(font, size, fontStyle);
font = ApplyStretch(font, size, FontStretch);
font = ApplyWeight(font, fontProperties);
font = ApplyStyle(font, fontProperties);
return font;
}

private static UIFont ApplyWeight(UIFont font, nfloat size, FontWeight fontWeight)
private static UIFont ApplyWeight(UIFont font, FontProperties fontProperties)
{
if (fontWeight.Weight == FontWeights.Bold.Weight && !font.FontDescriptor.SymbolicTraits.HasFlag(UIFontDescriptorSymbolicTraits.Bold))
if (fontProperties.Weight.Weight == FontWeights.Bold.Weight && !font.FontDescriptor.SymbolicTraits.HasFlag(UIFontDescriptorSymbolicTraits.Bold))
{
var descriptor = font.FontDescriptor.CreateWithTraits(font.FontDescriptor.SymbolicTraits | UIFontDescriptorSymbolicTraits.Bold);
if (descriptor != null)
{
font = UIFont.FromDescriptor(descriptor, size);
font = UIFont.FromDescriptor(descriptor, fontProperties.Size);
}
else
{
typeof(FontHelper).Log().Error($"Can't apply Bold on font \"{font.Name}\". Make sure the font supports it or use another FontFamily.");
}
}
else if (
fontWeight.Weight != FontWeights.SemiBold.Weight && // For some reason, when we load a Semibold font, we must keep the native Bold flag.
fontWeight.Weight < FontWeights.Bold.Weight &&
fontProperties.Weight.Weight != FontWeights.SemiBold.Weight && // For some reason, when we load a Semibold font, we must keep the native Bold flag.
fontProperties.Weight.Weight < FontWeights.Bold.Weight &&
font.FontDescriptor.SymbolicTraits.HasFlag(UIFontDescriptorSymbolicTraits.Bold))
{
var descriptor = font.FontDescriptor.CreateWithTraits(font.FontDescriptor.SymbolicTraits & ~UIFontDescriptorSymbolicTraits.Bold);
if (descriptor != null)
{
font = UIFont.FromDescriptor(descriptor, size);
font = UIFont.FromDescriptor(descriptor, fontProperties.Size);
}
else
{
Expand All @@ -213,26 +249,26 @@ private static UIFont ApplyWeight(UIFont font, nfloat size, FontWeight fontWeigh
return font;
}

private static UIFont ApplyStyle(UIFont font, nfloat size, FontStyle fontStyle)
private static UIFont ApplyStyle(UIFont font, FontProperties fontProperties)
{
if (fontStyle == FontStyle.Italic && !font.FontDescriptor.SymbolicTraits.HasFlag(UIFontDescriptorSymbolicTraits.Italic))
if (fontProperties.Style == FontStyle.Italic && !font.FontDescriptor.SymbolicTraits.HasFlag(UIFontDescriptorSymbolicTraits.Italic))
{
var descriptor = font.FontDescriptor.CreateWithTraits(font.FontDescriptor.SymbolicTraits | UIFontDescriptorSymbolicTraits.Italic);
if (descriptor != null)
{
font = UIFont.FromDescriptor(descriptor, size);
font = UIFont.FromDescriptor(descriptor, fontProperties.Size);
}
else
{
typeof(FontHelper).Log().Error($"Can't apply Italic on font \"{font.Name}\". Make sure the font supports it or use another FontFamily.");
}
}
else if (fontStyle == FontStyle.Normal && font.FontDescriptor.SymbolicTraits.HasFlag(UIFontDescriptorSymbolicTraits.Italic))
else if (fontProperties.Style == FontStyle.Normal && font.FontDescriptor.SymbolicTraits.HasFlag(UIFontDescriptorSymbolicTraits.Italic))
{
var descriptor = font.FontDescriptor.CreateWithTraits(font.FontDescriptor.SymbolicTraits & ~UIFontDescriptorSymbolicTraits.Italic);
if (descriptor != null)
{
font = UIFont.FromDescriptor(descriptor, size);
font = UIFont.FromDescriptor(descriptor, fontProperties.Size);
}
else
{
Expand Down

0 comments on commit 96b74ae

Please sign in to comment.