xamarin / Xamarin.Forms

Xamarin.Forms is no longer supported. Migrate your apps to .NET MAUI.
https://aka.ms/xamarin-upgrade
Other
5.62k stars 1.87k forks source link

[Bug] ExportFont not working on UWP #10307

Closed JasonLooney closed 4 years ago

JasonLooney commented 4 years ago

Description

Custom fonts are not showing up in UWP when the new ExportFontAttribute is used.

Steps to Reproduce

  1. Add a TTF or OTF file from Google Fonts, FontAwesome, icomoon, etc. as an embedded resource in your shared project
  2. Add the ExportFont attribute to your assembly. e.g. [assembly: ExportFont("FA5Regular.otf", Alias = "FontAwesome")]
  3. Reference the font family in XAML markup
  4. Compile and run the UWP app

Expected Behavior

Custom font should be used.

Actual Behavior

Custom font is used in iOS and Android, but not UWP.

Basic Information

Reproduction Link

https://github.com/jfversluis/EmbeddedFontsSample

jsuarezruiz commented 4 years ago

Embedded Fonts with format TTF or OTF are working in Android and iOS.

Captura de pantalla 2020-04-20 a las 16 17 49

In UWP, Fontawesome OTF font is not working as expected:

Captura de pantalla 2020-04-20 a las 16 17 59
scottkuhl commented 4 years ago

I am experiencing the same issue. It seems like UWP is always an afterthought with Xamarin.Forms and isn't supported nearly as well. I understand it's usage is probably far less than Android or iOS, but it's very frustrating.

ktd12 commented 4 years ago

I had this problem on UWP as well. However I got it to work when I dropped the Alias from the ExportFont declaration.

Here's what I did:

  1. I created my own font. The glyphs I used were all mapped to lowercase characters
  2. In my shared projected in App.xaml.cs I added: [assembly: ExportFont("karenfont.ttf")]
  3. I added karenfont.ttf as an embedded resource to the top level directory of my shared project.
  4. In my xamarin forms xaml file I had this: <Button Text="b" FontFamily="karenfont"/>

This now works on UWP. It does not work on Android. I am using Xamarin Forms v4.5.0.617

MitchBomcanhao commented 4 years ago

I am experiencing the same issue. It seems like UWP is always an afterthought with Xamarin.Forms and isn't supported nearly as well. I understand it's usage is probably far less than Android or iOS, but it's very frustrating.

I think that a lot of Xamarin developers (and visual studio developers that work on stuff that relates to Xamarin) only use macs, and when they use windows they purely ignore UWP. sometimes they include UWP in the sample projects, but RARELY are they shown on video presentations - so I'm not even sure that the features being demoed actually function on UWP.

@jsuarezruiz I am now trying ExportFont on the first release version of Xamarin 4.6, I've followed the example shown on a Xamarin video and guess what, it doesn't work on UWP, I just get squares. Works just fine on Android. As per the example in the FlyMe app, I'm not using an Alias. the font file is on the top level of the shared project. doesn't work.

joshminor commented 4 years ago

I'm in the unfortunate position of having to support iOS,Android, and UWP for our product and the fact that UWP gets left behind so often had led to us having to wait several release cycles to actually use new features. We've got three custom fonts that we load. For whatever reason the icon font is the only one I can't get to load for UWP. The other two platforms have no issues.

MitchBomcanhao commented 4 years ago

@joshminor so you get 2 out of 3 fonts working on UWP with this method? Maybe there's something specific to some fonts that is causing the issue...

joshminor commented 4 years ago

Actually, I just realized that the two fonts that work are installed as system fonts on my Windows test machine... so that may have something to do with it. Edit I tried installing the non-working font, it changed nothing. I tried an entirely different font from Google WebFonts ("Lobster") and it works without any issues (except aliases don't work)

MitchBomcanhao commented 4 years ago

I've tried the lobster font and the only way it worked was if I had it installed on the system. the font embedding didn't work.

Edit: I take it back, it did work (I had a typo in the name). so, it seems that some fonts work and some fonts don't? very intriguing

MitchBomcanhao commented 4 years ago

a bit more info

I've grabbed this google font, renamed the file and its references in the code from Lobster-Regular.ttf to Lobster-Regular-renamed.ttf - this made it stop working. Put the original name back on, and it works again. this likely indicates that the filename must match some internal property in the font itself in order for it to work, and could explain why people have different results with the same implementation - it depends on something within the font file itself.

ktd12 commented 4 years ago

I just upgraded to Xamarin Forms 4.6.0.726 and my embedded font, karenfont, is still working on UWP (Windows 10 1903). It is still not working on Android (Android 10).

joshminor commented 4 years ago

The font that won't load for me is a custom icon font, I verified with FontForge that the internal font family names are exactly the same as the file name, still won't load. I'm sure there is a pattern here somewhere. For the time being I'm going to fallback to the way we loaded fonts before (per-platform resources)

ktd12 commented 4 years ago

I created my custom font using the IcoMoon App. What may be of interest is that embedding karenfont didn't work until I mapped the glyphs to letters and then referenced the letter in my xaml (as opposed to using the hex code like: &#xf57e; )

MitchBomcanhao commented 4 years ago

I've recreated my font file and see that it can work, but it seems like the fontname and the filename need to be similar for it to have a chance of working.

I've also found that even when it appears to work, not all UI elements work as expected, ie toolbar icons with font image source don't seem to be working, I just get a square instead of the proper icon.

jdinnen commented 4 years ago

I'm having the same issue using the MaterialDesignIcons Font (https://materialdesignicons.com/), works fine on iOS and Android but all rectangles on UWP.

CliffAgius commented 4 years ago

See the same here if the Font pack is installed it seems to work but if it's part of the project like FontAwesome or MaterialDesignIcons which are not installed on the machine it will not work just little rectangles.

Going back to the old way of adding to each project and referencing in the ResourceDictionary works but that is more work and not the new hotness.

Not sure if this is a regression or it's never worked as my other projects have not included UWP.

MSiccDev commented 4 years ago

same here, seeing only squares on UWP...

RyanGaudion commented 4 years ago

Any update as to when this will be resolved?

Adrien6 commented 4 years ago

Same here... hopeless UWP...

AlleSchonWeg commented 4 years ago

Same here. Looks like UWP is dead.

CliffAgius commented 4 years ago

Ok All I need this fixed for my current project so I am going to take a look at fixing it.

@samhouts @jsuarezruiz can you please show this as being worked on. Thanks

CliffAgius commented 4 years ago

OK I think I have found what is happening here and it doesn't need a PR.

For UWP the old way of doing it was that you added the FontPack with an OnPlatform to the ResourcesDictionary and it looked something like this:

<ResourceDictionary>
  <OnPlatform x:TypeArguments="x:String"
            x:Key="IconFont">
    <On Platform="Android"
        Value="materialdesignicons-webfont.ttf#Material Design Icons" />
    <On Platform="iOS"
        Value="Material Design Icons" />
    <On Platform="UWP"
        Value="/Assets/materialdesignicons-webfont.ttf#Material Design Icons" />
  </OnPlatform>
</ResourceDictionary>

Notice that for the Android and UWP there is the #Material Design Icons for it to work with Embedded Font this part is still needed by UWP.

I found this as in the Xamarin Codebase for the Control Gallery the XAML had this line for the EmbeddedFonts page:

<Label Text="Mono Font" FontFamily="PTM55FT#PTMono-Regular"/>

Notice the #PTMono-Regular there at the end of the Font Name!

So I added the #Material Design Icons to the end of my Font Name like so:

FontFamily="materialdesignicons-webfont#MaterialDesignIcons"

And Hey Presto it works, I checked and it works on UWP/Droid and iOS as that's all I need for my current project.

If you want to know the part that goes after the # it's the name of the Font inside the Font File and easiest way to get this is to (On Win10 anyway!) open the font file and right there at the top is the name:

image

I hope that helps you and I guess it closes this issue @samhouts @jsuarezruiz as there isn't anything to fix except the Docs.

VladislavAntonyuk commented 4 years ago

I think XF should get first font name from the file if it is not specified by user

ktd12 commented 4 years ago

Yes! I have this in my app.xaml and the fonts have been working for me: `

        <On Platform="UWP" Value="Assets/Fonts/materialdesignicons-webfont.ttf#Material Design Icons" />
    </OnPlatform>`
CliffAgius commented 4 years ago

@ktd12 but are you using the new EmbeddedFonts?

@VladislavAntonyuk Maybe it does need looking into then. I haven't tried it with an older version of XF so not sure if it's ever worked on UWP or it's a new issue, my current project highlighted it to me. Happy to take a look if thats how you believe it should work.

ktd12 commented 4 years ago

Sorry - I spoke too soon. The font that I am using as an embedded font is one I created called karenfont. I have the opposite problem as everyone else: It works on UWP but not on Android. I am using XF 4.6.0.726, Windows 10 1903 on a Surface Pro 7 and Android 10 on a Samsung Galaxy s10 <Button x:Name="btnBackup" Text="b" HorizontalOptions="FillAndExpand" FontSize="Medium" FontFamily="karenfont"/>

ktd12 commented 4 years ago

On Windows the letter "b" looks like: b on windows

On Android the letter "b" looks like:

b on android

What the font looks like:

karenfont
AlleSchonWeg commented 4 years ago

OK I think I have found what is happening here and it doesn't need a PR.

For UWP the old way of doing it was that you added the FontPack with an OnPlatform to the ResourcesDictionary and it looked something like this:

<ResourceDictionary>
  <OnPlatform x:TypeArguments="x:String"
            x:Key="IconFont">
    <On Platform="Android"
        Value="materialdesignicons-webfont.ttf#Material Design Icons" />
    <On Platform="iOS"
        Value="Material Design Icons" />
    <On Platform="UWP"
        Value="/Assets/materialdesignicons-webfont.ttf#Material Design Icons" />
  </OnPlatform>
</ResourceDictionary>

Notice that for the Android and UWP there is the #Material Design Icons for it to work with Embedded Font this part is still needed by UWP.

I found this as in the Xamarin Codebase for the Control Gallery the XAML had this line for the EmbeddedFonts page:

<Label Text="Mono Font" FontFamily="PTM55FT#PTMono-Regular"/>

Notice the #PTMono-Regular there at the end of the Font Name!

So I added the #Material Design Icons to the end of my Font Name like so:

FontFamily="materialdesignicons-webfont#MaterialDesignIcons"

And Hey Presto it works, I checked and it works on UWP/Droid and iOS as that's all I need for my current project.

If you want to know the part that goes after the # it's the name of the Font inside the Font File and easiest way to get this is to (On Win10 anyway!) open the font file and right there at the top is the name:

image

I hope that helps you and I guess it closes this issue @samhouts @jsuarezruiz as there isn't anything to fix except the Docs.

Hi, do you get this working on the sample project? https://github.com/jfversluis/EmbeddedFontsSample I tried, but without success.

joshminor commented 4 years ago

Adding the #fontname didn't seem to do anything for me. I thought it worked at first, but I after I uninstalled the font from the system it went back to displaying squares. I confirmed with another coworker that if you install the font it will start displaying correctly.

I did a little more digging and this has something to do with the font file. I can swap out to different fonts and things will work fine. I'm going to try re-exporting our font and see if I can get anything to work.

UdaraAlwis commented 4 years ago

Yes agree, it doesn't work on UWP. Neither adding the #FontName as suggested by @CliffAgius, unless you install the Font file manually in the OS, Windows 10. Therefore no, that is not a fix. :) and it needs to be addressed by the team @samhouts @jsuarezruiz please.

The sample project that features in Xamarin release blog itself doesn't work for UWP, https://github.com/jfversluis/EmbeddedFontsSample https://devblogs.microsoft.com/xamarin/embedded-fonts-xamarin-forms/

image

It seems like they are intentionally discarding out support for Windows 10, whenever they push a new feature out in Xamarin.Forms these days! :(

CliffAgius commented 4 years ago

@UdaraAlwis yes thanks for posting as I had totally forgot about this, my fix worked as I had the FotPack loaded onto the dev machine for something else so thought it was working. As soon as I pushed to a client for a preview it broke. I have had to revert to the Old long winded way of adding fonts for this project as it targets UWP for some users.

I don't agree that the team are disregarding UWP in builds it's just that the UI tests are not written to pick this up and a lot of devs use Macs so can't test the UWP. There needs to be a better way to do this maybe a #HotRestart style thing for windows when building on a Mac.

solomonfried commented 4 years ago

Just adding my vote. ExportFont only works on UWP if the font is already installed on the Windows machine. So it will not work on the client machine when the app gets installed.

For now, I had to place the fonts into a folder and set the Action as Contents and the refer to it with the # notation

/fonts/xyx.ttf#xyz.ttf

joshminor commented 4 years ago

I managed to get fonts to display correctly when in debug mode or when "compile with .net native tool chain" is turned off. Turning .net native compile back on will immediately break all the fonts.

Samit-BTE commented 4 years ago

I am new to Xamarin, so this solution might be misleading. i used approach explained by @CliffAgius Again, I might be using old way or completely wrong.

For me, I don't have to install any font. The only way it works for me in all the 3 platform is by using ".otf" files rather than ".ttf" files.

".ttf" files only work for text font family but dose not work for Glyph. Along with this I have to add ".otf" to a respective platform specific folder.

Following is my usage and resource file.

Below code not tested for IOS.

Resource FIle:

<?xml version="1.0" encoding="utf-8" ?>
<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
                    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                    xmlns:d="http://xamarin.com/schemas/2014/forms/design"
                    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                    xmlns:local="clr-namespace:ProjectName.Themes.FontIcon;assembly=ProjectName.Themes"
                    mc:Ignorable="d"
                    x:Class="ProjectName.Themes.Styles.IconImage">
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="ColorsResource.xaml" />
    </ResourceDictionary.MergedDictionaries>
    <OnAppTheme x:Key="ImageLogoSample"
                x:TypeArguments="FileImageSource"
                Light="{x:Static local:AwesomeFontSolid.TicketAlt}"
                Dark="{x:Static local:AwesomeFontSolid.PersonBooth}" />  
    <!-- Sizes -->
    <x:Double x:Key="SizeTabIcon">24</x:Double>

    <!-- Fonts Icon -->

    <OnPlatform x:TypeArguments="x:String"
                x:Key="FontAwesomeBrand">
        <On Platform="Android"
            Value="FABrand.otf#Font Awesome 5 Brands" />
        <On Platform="iOS"
            Value="FABrand-Regular" />
        <On Platform="UWP"
            Value="/Assets/FABrand.otf#Font Awesome 5 Brands" />
    </OnPlatform>

    <OnPlatform x:TypeArguments="x:String"
                x:Key="FontAwesomeRegular">
        <On Platform="Android"
            Value="FARegular.otf#Font Awesome 5 Pro" />
        <On Platform="iOS"
            Value="FontAwesome5Free-Regular" />
        <On Platform="UWP"
            Value="/Assets/FARegular.otf#Font Awesome 5 Pro" />
    </OnPlatform>

    <OnPlatform x:TypeArguments="x:String"
                x:Key="FontAwesomeSolid">
        <On Platform="Android"
            Value="FASolid.otf#Font Awesome 5 Pro" />
        <On Platform="iOS"
            Value="FontAwesome5Free-Solid" />
        <On Platform="UWP"
            Value="/Assets/FASolid.otf#Font Awesome 5 Pro" />
    </OnPlatform>

    <OnPlatform x:TypeArguments="x:String"
                x:Key="FontAwesomeLight">
        <On Platform="Android"
            Value="FALight.otf#Font Awesome 5 Pro" />
        <On Platform="iOS"
            Value="Font Awesome 5 Pro" />
        <On Platform="UWP"
            Value="/Assets/FALight.otf#Font Awesome 5 Pro" />
    </OnPlatform>

    <OnPlatform x:TypeArguments="x:String"
                x:Key="FontAwesomeSolidDuoTone">
        <On Platform="Android"
            Value="FASolidDuotone.otf#Font Awesome 5 Duotone" />
        <On Platform="iOS"
            Value="Font Awesome 5 Duotone" />
        <On Platform="UWP"
            Value="/Assets/FASolidDuotone.otf#Font Awesome 5 Duotone" />
    </OnPlatform>

    <OnPlatform x:TypeArguments="x:String"
                x:Key="MaterialDesign">
        <On Platform="Android"
            Value="MD.otf#Material Design Icons" />
        <On Platform="iOS"
            Value="Material Design Icons" />
        <On Platform="UWP"
            Value="/Assets/MD.otf#Material Design Icons" />
    </OnPlatform>

    <!--ICONS 30 by 30-->  
    <!--Black-->
    <FontImageSource x:Key="IconPowerOff"
                     FontFamily="{DynamicResource FontAwesomeSolid}"
                     Glyph="{x:Static local:AwesomeFontSolid.PowerOff}"
                     Size="30"
                     Color="Black" />
    <!--ICONS 100 by 100-->
    <FontImageSource x:Key="IconHand"
                     FontFamily="{DynamicResource FontAwesomeSolid}"
                     Glyph="{x:Static local:AwesomeFontSolid.Hands}"
                     Size="100"
                     Color="Black" />   
</ResourceDictionary>

And in Xamal Usage

  <Image Margin="20,0" WidthRequest="30">
                        <Image.Source>
                            <FontImageSource
                                FontFamily="{StaticResource FontAwesomeSolid}"
                                Glyph="{x:Static local:AwesomeFontSolid.Users}"
                                Color="{DynamicResource SurfaceTextColor}" />
                        </Image.Source>
                    </Image>
chrisgull commented 4 years ago

Samit, I have .ttf font working using embedded/ExportFont on Android/iOS.

Troubleshooting is a hit or miss though - no messages or metrics to help you understand why it doesn't work. This is something I don't like with the Xamarin codebase, in many cases where you pass in an incorrect parameter the function just does nothing instead of informing you that a parameter value is incorrect. Error messages/logging/exceptions can be really helpful.

Samit-BTE commented 4 years ago

Samit, I have .ttf font working using embedded/ExportFont on Android/iOS.

Troubleshooting is a hit or miss though - no messages or metrics to help you understand why it doesn't work. This is something I don't like with the Xamarin codebase, in many cases where you pass in an incorrect parameter the function just does nothing instead of informing you that a parameter value is incorrect. Error messages/logging/exceptions can be really helpful.

Hello Chris,

Yes, I did observe same behavior and it was difficult to understand or debug what's wrong, ".ttf" file works for android and IOS but not for UWP (Glyph ). So I tried using .otf file and it work for All three platforms for image (Glyph ).

Also strange thing is ".ttf" does work in all three platforms for text font (not sure how to explain but the Roboto-Italic.ttf file will work on all 3 platforms) but as I said before Glyph from .ttf file is not working.

Hope we will have a fix for this soon. Till then I am using an .otf file as a workaround.

solomonfried commented 4 years ago

@Samit. I believe your code is referring to the "legacy" way of supporting custom fonts in Xamarin. In that scenario you install your font file in each project folder and add some manifest code, and then refer to the font name as you present in your resource file example where each platform get a slightly different variation of the file name. The issue that was reported here with "ExportFont" feature which was recently introduced with Xamarin and allows you to include the font once in the Shared project and then make it known to the app with an ExportFont directive. [assembly: ExportFont("Samantha.ttf", Alias = "MyAwesomeCustomFont")]

https://devblogs.microsoft.com/xamarin/embedded-fonts-xamarin-forms/

The bug reported that this works for Android and iOS projects but not for UWP where we need to revert back to the previous method.

ninaada commented 4 years ago

Facing the same issue here. We were using the font embedding which works like a breeze on Android and iOS. And we added an additional UWP project due to some client requirements. It doesn't work at all and all we see is some boxes.

solomonfried commented 4 years ago

Samit, I have .ttf font working using embedded/ExportFont on Android/iOS. Troubleshooting is a hit or miss though - no messages or metrics to help you understand why it doesn't work. This is something I don't like with the Xamarin codebase, in many cases where you pass in an incorrect parameter the function just does nothing instead of informing you that a parameter value is incorrect. Error messages/logging/exceptions can be really helpful.

Hello Chris,

Yes, I did observe same behavior and it was difficult to understand or debug what's wrong, ".ttf" file works for android and IOS but not for UWP (Glyph ). So I tried using .otf file and it work for All three platforms for image (Glyph ).

Also strange thing is ".ttf" does work in all three platforms for text font (not sure how to explain but the Roboto-Italic.ttf file will work on all 3 platforms) but as I said before Glyph from .ttf file is not working.

Hope we will have a fix for this soon. Till then I am using an .otf file as a workaround.

You may want to check that the reason that the "Roboto-Italic.ttf" works on all 3 platforms is because it is physically installed on the Windows machine that you are using to test. It took me a long time to figure out why some fonts worked, with ExportFont, on UWP and others did not until I realized that it was only using fonts that were already installed in Windows.

activa commented 4 years ago

The problem is that UWP wants the font name as part of the font family name. Xamarin Forms wrongly assumes that the font name is the same as the font file name. For many fonts that doesn't work (FontAwesome for example)

I will create a PR to fix this issue.

johncao158 commented 4 years ago

Xamarin.Forms: 4.8.0.1269 ExportFont works for Android, but not UWP

Instead of using ExportFont in the shared project, here's a workaround:

  1. Copy your font file (xxx.ttf) to the Assets folder in Androind and UWP project:

[Android]: Assets/xxx.ttf Build Action: AndroidAsset Copy to Output Directory: Do not copy

[UWP]: Assets/xxx.ttf Build Action: Content Copy to Output Directory: Do not copy

  1. Sets the FontFamily property for your text:

       <Label.FontFamily>
            <OnPlatform x:TypeArguments="x:String">
                <On Platform="Android"
                    Value="xxx.ttf#Font Name" />
                <On Platform="UWP"
                    Value="/Assets/xxx.ttf#Font Name" />
            </OnPlatform>
        </Label.FontFamily>

Now it works as expected!

activa commented 4 years ago

@johncao158 That's the legacy way of using custom fonts in Xamarin Forms, which has worked since the beginning. This issue is specifically about [ExportFont] not working on UWP. The workaround you suggested still doesn't allow you to add the fonts as an embedded resource.

RobertoGFilho commented 4 years ago

My project works this way:

[SHARED PROJECT] AssemblyInfo.cs [assembly: ExportFont("entypo.ttf", Alias = "entypo-plus")] Fonts/entypo.ttf "for iOS and Android"

[UWP]: Assets/entypo.ttf Build Action: Content Copy to Output Directory: Do not copy

solomonfried commented 4 years ago

My project works this way:

[SHARED PROJECT] AssemblyInfo.cs [assembly: ExportFont("entypo.ttf", Alias = "entypo-plus")] Fonts/entypo.ttf "for iOS and Android"

Build Action: Content Copy to Output Directory: Do not copy

You are correct. This new feature works on iOS and Android. The issue is that it will not work on Windows unless the font is already installed on the machine.

BillyMartin1964 commented 4 years ago

Why was this closed? Although custom fonts work in UWP debug, they don't work in a release version.

When i use them in a release version sideload, the page that the custom font is on is completely blank. When I comment out the font family in xaml, the page appears fine... but without custom fonts, of course.

I also checked in the windows/font folder and the font was on the laptop I installed the app on.

ArtjomP commented 4 years ago

I have the same issue as @BillyMartin1964 on UWP release even with the latest XF 4.8.0.1534+384-sha.712849b9d-azdo.4114742

kevcrooks commented 4 years ago

We have the same issue too as @BillyMartin1964 - it was very confusing as the fonts work fine on Android/iOS and even UWP in Debug mode, but not in Release mode.

@samhouts is there a work-around we can use for this, and can the issue be re-opened to fix for UWP release mode too?

BillyMartin1964 commented 4 years ago

At the very least, can we have code that ignores the custom font if it isn't installed in the user's computer/XBox?

ArtjomP commented 4 years ago

At the very least, can we have code that ignores the custom font if it isn't installed in the user's computer/XBox?

I think you can add two elements on the page and make them visible depending on the platform they're running on. Use OnPlatform for that.

BillyMartin1964 commented 4 years ago

@ArtjomP , that's not the problem. The entire page is blank when we use the embedded font on a release build sideload to another PC. Someone said it's because the other PC did not have the font previously installed. I'm not sure about this, but if that is the case, we need to test for the installed font and not use it if it isn't installed.

Personally, I think it's another issue because it appears that the font was in the font folder on the user's machine.

ArtjomP commented 4 years ago

@BillyMartin1964 pretty strange my pages all work well on UWP release. The labels with custom font only show square as on the picture above from @jsuarezruiz