Xamarin.forms: [Bug] Some Font Image are cropped on iOS

Created on 11 Jun 2019  ·  9Comments  ·  Source: xamarin/Xamarin.Forms

Description

I'm using fontawesome 5 free solid to display some images.
A few of these images are cropped when I use FontImageSource on a button or toolbaritem.
I think the problem is on images where width is greater than height, for example fa-cloud https://fontawesome.com/icons/cloud?style=solid

Steps to Reproduce

  1. Add a button on any layout with a fontimagesource with fa-cloud icon ("uf0c2")

Expected Behavior

The image should not be cropped

Actual Behavior

The image is cropped

Basic Information

  • Version with issue: last 4.0
  • IDE:
  • Platform Target Frameworks:

    • iOS: 12.2

Screenshots

First image is cropped on the right.
image

Reproduction Link

https://github.com/Luca7993/FontImageIosProblem

2 in-progress iOS 🍎 bug

Most helpful comment

Opened a PR with a fix for this!

All 9 comments

Does this also happen on Android or just iOS?

Only on ios

Il 11 giu 2019 1:03 PM, Gerald Versluis notifications@github.com ha scritto:

Does this also happen on Android or just iOS?


You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHubhttps://github.com/xamarin/Xamarin.Forms/issues/6491?email_source=notifications&email_token=AAIDGP5QM5B43LWH4W2FBHLPZ6BAFA5CNFSM4HW4QSP2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODXMX64Y#issuecomment-500793203, or mute the threadhttps://github.com/notifications/unsubscribe-auth/AAIDGPZN3YZ3JP2QNA7SED3PZ6BAFANCNFSM4HW4QSPQ.

Any news or tip how to try to create a custom renderer for FontImageSource?

EDIT:
I wasn't able to find the root of the problem.
I was able to create a custom renderer with a hack where I just add 25 percent to the width if the font family is fontawesome:

using System.Drawing;
using System.Threading;
using System.Threading.Tasks;
using Foundation;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using RectangleF = CoreGraphics.CGRect;

[assembly: ExportImageSourceHandler(typeof(FontImageSource), typeof(CloudMatic.iOS.ControlsRenderer.FontImageSourceHandler))]
namespace CloudMatic.iOS.ControlsRenderer
{
    public sealed class FontImageSourceHandler : IImageSourceHandler
    {
        readonly Xamarin.Forms.Color _defaultColor = Xamarin.Forms.Color.White;

        public Task<UIImage> LoadImageAsync(ImageSource imagesource, CancellationToken cancelationToken = default, float scale = 1)
        {
            UIImage image = null;
            var fontsource = imagesource as FontImageSource;
            if (fontsource != null)
            {
                var iconcolor = fontsource.Color.IsDefault ? _defaultColor : fontsource.Color;
                var font = UIFont.FromName(fontsource.FontFamily ?? string.Empty, (float)fontsource.Size) ??
                    UIFont.SystemFontOfSize((float)fontsource.Size);

                // HACK, we add 25 percent of current width if we use fontawesome...
                var isFontAwesome = Utils.Converter.ToBool(fontsource?.FontFamily?.ToString()?.Contains("fontawesome", System.StringComparison.OrdinalIgnoreCase));
                var widthToAdd = isFontAwesome ? (float)fontsource.Size / 100 * 25 : 0;
                var imagesize = new SizeF((float)fontsource.Size + widthToAdd, (float)fontsource.Size);

                UIGraphics.BeginImageContextWithOptions(imagesize, false, 0f);
                var attString = new NSAttributedString(fontsource.Glyph, font: font, foregroundColor: iconcolor.ToUIColor());
                var ctx = new NSStringDrawingContext();
                var boundingRect = attString.GetBoundingRect(imagesize, (NSStringDrawingOptions)0, ctx);
                attString.DrawString(new RectangleF(
                    imagesize.Width / 2 - boundingRect.Size.Width / 2,
                    imagesize.Height / 2 - boundingRect.Size.Height / 2,
                    imagesize.Width,
                    imagesize.Height));
                image = UIGraphics.GetImageFromCurrentImageContext();
                UIGraphics.EndImageContext();

                if (iconcolor != _defaultColor)
                    image = image.ImageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal);
            }
            return Task.FromResult(image);
        }
    }
}

Code from source can be found here

Thanks,
Eddy

I would also like to report that we are running into this issue as well. We use font awesome icon set and if the particular icon is wider than it is tall it will be cut off.

This behavior is also on UWP as well. The only platform that seems to do it correctly is android.

If a separate issue needs to be made for UWP let me know but we need it fixed for both.

@squinn7 if you could create a separate issue for UWP that would be great, that way we can track progress on both platforms. You can refer to this one. If you would also be so kind to attach a sample project that shows this behavior you will be my personal hero.

Same problem here. We create our own custom Font.otf file with custom branded vector icons by our UX designer. Icons are cropped on iOS only but only those which are in width larger than in heigth or if height is larger than width. On Android and on UWP looks fine.

Opened a PR with a fix for this!

It's seem like it still not be fixed in v4.2 like this https://github.com/xamarin/Xamarin.Forms/issues/7017

It might not have made it into the last release. New versions of the Xamarin.Forms packages should be released soon, please retest with those when they come.

Was this page helpful?
0 / 5 - 0 ratings