Unable to load font for use with ImageSharp in Xamarin Android app

1k Views Asked by At

I have a Xamarin Forms app where I've included a font file called Roboto-Regular.ttf in the Assets folder of the Android project. Its Build Action is set to AndroidAsset.

Using the SixLabors.Fonts NuGet package, I'm trying to load this font to use it for watermarking.

However, trying to install the font using the asset stream, an exception is thrown saying:

System.NotSupportedException: Specified method is not supported.

var fonts = new FontCollection();

FontFamily fontFamily;

using (var fontStream = Assets.Open("Roboto-Regular.ttf"))
{
    fontFamily = fonts.Install(fontStream); // Fails with "method not supported"
}

return fontFamily;

Any ideas what might be causing this, or if there is a better way to load fonts for use with the SixLabors.ImageSharp package?

Edit: I tried the suggestion below by SushiHangover, but it yields the same result:

Android asset stream in Xamarin

2

There are 2 best solutions below

1
On BEST ANSWER

Seems the underlying Stream did not have Length or Position properties (which explains the exception), so for now I resorted to converting to a seekable MemoryStream instead:

using (var assetStreamReader = new StreamReader(Assets.Open("Roboto-Regular.ttf"))
{   
    using (var ms = new MemoryStream())
    {
        assetStreamReader.BaseStream.CopyTo(ms);

        ms.Position = 0;

        var fontFamily = new FontCollection().Install(ms);
    }
}

Looking at the FontReader implementation, the error now makes even more sense: https://github.com/SixLabors/Fonts/blob/master/src/SixLabors.Fonts/FontReader.cs

However, I'm not sure why Assets doesn't return a seekable stream?

1
On

There is are two Assets.Open methods and one provides an accessMode (C# Access enum flag set):

using (var fontStream = Assets.Open("Roboto-Regular.ttf", Android.Content.Res.Access.Random))
{
    fontFamily = fonts.Install(fontStream); 
}

re: https://developer.android.com/reference/android/content/res/AssetManager.html#open(java.lang.String,%20int)

public enum Access
{
    [IntDefinition (null, JniField = "android/content/res/AssetManager.ACCESS_BUFFER")]
    Buffer = 3,
    [IntDefinition (null, JniField = "android/content/res/AssetManager.ACCESS_RANDOM")]
    Random = 1,
    [IntDefinition (null, JniField = "android/content/res/AssetManager.ACCESS_STREAMING")]
    Streaming,
    [IntDefinition (null, JniField = "android/content/res/AssetManager.ACCESS_UNKNOWN")]
    Unknown = 0
}