Skip to content
This repository has been archived by the owner on May 1, 2024. It is now read-only.

Fix for issue #10307, embedded fonts not working on UWP #11741

Merged
merged 2 commits into from
Aug 31, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using Xamarin.Forms.CustomAttributes;
using Xamarin.Forms.Internals;

#if UITEST
using Xamarin.Forms.Core.UITests;
using Xamarin.UITest;
using NUnit.Framework;
#endif

namespace Xamarin.Forms.Controls.Issues
{
#if UITEST
[Category(UITestCategories.ManualReview)]
#endif
[Preserve(AllMembers = true)]
[Issue(IssueTracker.Github, 10307, "Embedded Fonts not working", PlatformAffected.UWP)]
public class Issue10307 : TestContentPage // or TestMasterDetailPage, etc ...
{
protected override void Init()
{
Content = new StackLayout()
{
Children =
{
new Label() { Text = "Four bell icons should be visible below", Margin = new Thickness(10)},

new Label { FontFamily = "FontAwesome", FontSize = 50, TextColor = Color.Black, Text = "\xf0f3" },
new Label { FontFamily = "fa-regular-400.ttf", FontSize = 50, TextColor = Color.Black, Text = "\xf0f3" },
new Image() { Source = new FontImageSource() { FontFamily = "FontAwesome", Glyph = "\xf0f3", Color = Color.Black, Size = 50}, HorizontalOptions = LayoutOptions.Start},
new Image() { Source = new FontImageSource() { FontFamily = "fa-regular-400.ttf", Glyph = "\xf0f3", Color = Color.Black, Size = 50}, HorizontalOptions = LayoutOptions.Start},
}
};


BindingContext = new ViewModelIssue1();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -835,6 +835,7 @@
</Compile>
<Compile Include="$(MSBuildThisFileDirectory)Issue10699.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue11185.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue10307.cs" />
<Compile Include="$(MSBuildThisFileDirectory)_TemplateMarkup.xaml.cs">
<DependentUpon>_TemplateMarkup.xaml</DependentUpon>
<SubType>Code</SubType>
Expand Down
2 changes: 1 addition & 1 deletion Xamarin.Forms.Controls/GalleryPages/EmbeddedFonts.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
[assembly: ExportFont("CuteFont-Regular.ttf", Alias = "Foo")]
[assembly: ExportFont("PTM55FT.ttf")]
[assembly: ExportFont("Dokdo-Regular.ttf")]
[assembly: ExportFont("fa-regular-400.ttf")]
[assembly: ExportFont("fa-regular-400.ttf", Alias="FontAwesome")]

namespace Xamarin.Forms.Controls.GalleryPages
{
Expand Down
1 change: 1 addition & 0 deletions Xamarin.Forms.Core/ExportFontAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ namespace Xamarin.Forms
public class ExportFontAttribute : Attribute
{
public string Alias { get; set; }

public ExportFontAttribute(string fontFileName)
{
FontFileName = fontFileName;
Expand Down
31 changes: 24 additions & 7 deletions Xamarin.Forms.Platform.UAP/FontExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Graphics.Canvas.Text;
using Windows.UI.Text;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
Expand Down Expand Up @@ -105,16 +107,27 @@ public static FontFamily ToFontFamily(this string fontFamily)
return font;
}

static string FindFontFamilyName(string fontFile)
{
using (var fontSet = new CanvasFontSet(new Uri(fontFile)))
{
if (fontSet.Fonts.Count == 0)
return null;

return fontSet.GetPropertyValues(CanvasFontPropertyIdentifier.FamilyName).FirstOrDefault().Value;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will FirstOrDefault here always return something?

Does this need a null check?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What @mattleibow said. Also, I was thinking about caching the return value but it would be pointless because the resulting FontFamily objects are already being cached here.

}
}

static IEnumerable<string> GetAllFontPossibilities(string fontFamily)
{
//First check Alias
var (hasFontAlias, fontPostScriptName) = FontRegistrar.HasFont(fontFamily);
if (hasFontAlias)
{
var familyName = FindFontFamilyName(fontPostScriptName);
var file = FontFile.FromString(IOPath.GetFileName(fontPostScriptName));
var formated = $"{fontPostScriptName}#{file.GetPostScriptNameWithSpaces()}";
yield return formated;
yield return fontFamily;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: this line was not needed when the font was found in the FontRegistrar. In fact, it caused problems when setting FontFamily in a CanvasTextFormat object (see FontImageSourceHandler.cs)

var formatted = $"{fontPostScriptName}#{familyName ?? file.GetPostScriptNameWithSpaces()}";
yield return formatted;
yield break;
}

Expand All @@ -133,8 +146,9 @@ static IEnumerable<string> GetAllFontPossibilities(string fontFamily)
var (hasFont, filePath) = FontRegistrar.HasFont(fontFile.FileNameWithExtension());
if (hasFont)
{
var formated = $"{filePath}#{fontFile.GetPostScriptNameWithSpaces()}";
yield return formated;
var familyName = FindFontFamilyName(filePath);
var formatted = $"{filePath}#{familyName ?? fontFile.GetPostScriptNameWithSpaces()}";
yield return formatted;
yield break;
}
else
Expand All @@ -147,7 +161,8 @@ static IEnumerable<string> GetAllFontPossibilities(string fontFamily)
var (hasFont, filePath) = FontRegistrar.HasFont(fontFile.FileNameWithExtension(ext));
if (hasFont)
{
var formatted = $"{filePath}#{fontFile.GetPostScriptNameWithSpaces()}";
var familyName = FindFontFamilyName(filePath);
var formatted = $"{filePath}#{familyName ?? fontFile.GetPostScriptNameWithSpaces()}";
yield return formatted;
yield break;
}
Expand All @@ -158,7 +173,9 @@ static IEnumerable<string> GetAllFontPossibilities(string fontFamily)

foreach (var ext in extensions)
{
var formatted = $"{path}{fontFile.FileNameWithExtension(ext)}#{fontFile.GetPostScriptNameWithSpaces()}";
var fileName = $"{path}{fontFile.FileNameWithExtension(ext)}";
var familyName = FindFontFamilyName(fileName);
var formatted = $"{fileName}#{familyName ?? fontFile.GetPostScriptNameWithSpaces()}";
yield return formatted;
}
}
Expand Down
14 changes: 9 additions & 5 deletions Xamarin.Forms.Platform.UAP/FontImageSourceHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public sealed class FontImageSourceHandler : IImageSourceHandler, IIconElementHa

var textFormat = new CanvasTextFormat
{
FontFamily = fontsource.FontFamily,
FontFamily = fontsource.FontFamily.ToFontFamily().Source,
FontSize = (float)fontsource.Size,
HorizontalAlignment = CanvasHorizontalAlignment.Center,
VerticalAlignment = CanvasVerticalAlignment.Center,
Expand Down Expand Up @@ -65,8 +65,10 @@ public sealed class FontImageSourceHandler : IImageSourceHandler, IIconElementHa
Foreground = fontImageSource.Color.ToBrush()
};

if (!string.IsNullOrEmpty(fontImageSource.FontFamily))
((WFontIconSource)image).FontFamily = new FontFamily(fontImageSource.FontFamily);
var uwpFontFamily = fontImageSource.FontFamily.ToFontFamily().Source;

if (!string.IsNullOrEmpty(uwpFontFamily))
((WFontIconSource)image).FontFamily = new FontFamily(uwpFontFamily);
}

return Task.FromResult(image);
Expand All @@ -85,8 +87,10 @@ public sealed class FontImageSourceHandler : IImageSourceHandler, IIconElementHa
Foreground = fontImageSource.Color.ToBrush()
};

if (!string.IsNullOrEmpty(fontImageSource.FontFamily))
((FontIcon)image).FontFamily = new FontFamily(fontImageSource.FontFamily);
var uwpFontFamily = fontImageSource.FontFamily.ToFontFamily().Source;

if (!string.IsNullOrEmpty(uwpFontFamily))
((FontIcon)image).FontFamily = new FontFamily(uwpFontFamily);
}

return Task.FromResult(image);
Expand Down