SkiaSharp icon indicating copy to clipboard operation
SkiaSharp copied to clipboard

[BUG] Text size measured improperly in Linux OS

Open VijayRM opened this issue 5 years ago • 21 comments

Description

Particular text width was calculated wrongly in Linux OS. The same text was measured properly in Windows.

Code

        SKPaint paint = new SKPaint();
        paint.TextEncoding = SKTextEncoding.Utf8;
        paint.IsAntialias = true;
        paint.Typeface = SKTypeface.FromFamilyName("Arial", SKFontStyleWeight.Bold, SKFontStyleWidth.Normal, SKFontStyleSlant.Upright);
        paint.TextSize = 9;
        paint.TextAlign = SKTextAlign.Left;

        SKRect rect = new SKRect();
        float width = paint.MeasureText("Locatio", ref rect);
        Console.WriteLine(width);

        string text = ((char)61608).ToString();
        paint.Typeface = SKTypeface.FromFamilyName("Wingdings", SKFontStyleWeight.Bold, SKFontStyleWidth.Normal, SKFontStyleSlant.Upright);
        paint.TextSize = 12;
        rect = new SKRect();
        width = paint.MeasureText(text, ref rect);
        Console.WriteLine(width);

Expected Behavior

The width of the text should be same as Windows OS.

Text Expected Width
 Locatio  32.00098
   10.93359

Actual Behavior

Text Actual Width
 Locatio  34
   11

Basic Information

  • Version with issue: 1.59.3
  • IDE: MonoDevelop
  • Platform Target Frameworks: .NET Core 2.1
  • Linux: Ubuntu 18.04

VijayRM avatar May 08 '19 13:05 VijayRM

You have to load the same font file from stream to get the same result. Using SKTypeface.FromFamilyName("Arial") will load different fonts depending on the platform. On Linux for example FontConfig is used to query the font and most likely "Arial" is mapped as an alias to a similar font but not the same as on Windows.

Gillibald avatar May 08 '19 14:05 Gillibald

Could you please suggest me the best alternative overload for below method, as the suggested SKTypeface.FromStream() overload doesn't have option to specify the SKFontStyleWeight, SKFontStyleWidth and SKFontStyleSlant?

SKTypeface.FromFamilyName("Arial", SKFontStyleWeight.Bold, SKFontStyleWidth.Normal, SKFontStyleSlant.Upright);

VijayRM avatar May 08 '19 15:05 VijayRM

Most font files .ttf and .otf only contain one set of glyphs. For example MyFont-Regular.ttf which will be loaded as a SKTypeface with weight set to normal etc.

https://fonts.google.com/specimen/Roboto for example

Gillibald avatar May 08 '19 16:05 Gillibald

SKTypeface.FromStream() also causes the same problem in Linux OS.

        SKPaint paint = new SKPaint();
        paint.TextEncoding = SKTextEncoding.Utf8;
        paint.IsAntialias = true;
        FileStream fStream = new FileStream(@"arialbd.ttf", FileMode.Open, FileAccess.Read);
        paint.Typeface = SKTypeface.FromStream(fStream);//SKTypeface.FromFamilyName("Arial", SKFontStyleWeight.Bold, SKFontStyleWidth.Normal, SKFontStyleSlant.Upright);
        paint.TextSize = 9;
        paint.TextAlign = SKTextAlign.Left;

        SKRect rect = new SKRect();
        float width = paint.MeasureText("Locatio", ref rect);
        Console.WriteLine(width);

I think it could be a bug, as most of other cases are working fine in both Windows and Linux by using below overload. Could you please confirm this?

SKTypeface.FromFamilyName("Arial", SKFontStyleWeight.Bold, SKFontStyleWidth.Normal, SKFontStyleSlant.Upright);

Please provide solution to resolve the issue by using above overload, as the Font stream overload requires the installed font location in all the environment. I hope already getting font from the installed location may handled internally in above API.

VijayRM avatar May 09 '19 09:05 VijayRM

Can you try to set paint.SubpixelText = true? Maybe that isn't set by default on Linux. I will investigate this further if I find some spare time.

Gillibald avatar May 09 '19 10:05 Gillibald

The default value of paint.SubpixelText is false in both Windows and Linux OS.

As per your suggestion, if paint.SubpixelText property was set as true, then width of the text size was calculated as expected in Linux OS.

Could you please provide more information about the use of this property? Whether this changes will introduce any side effects in Linux or Windows?

VijayRM avatar May 09 '19 12:05 VijayRM

It seems that on Windows Subpixel positioning of glyphs is always used. There should be no side effects. You should enable it to get better rendering results. I can't give you more info. If you need more info about this you have to contact the Skia devs.

Gillibald avatar May 09 '19 12:05 Gillibald

Thanks @Gillibald . I will do the necessary changes and update you the confirmation once after ensuring the complete testing.

VijayRM avatar May 09 '19 12:05 VijayRM

@Gillibald - Although the provided suggestions resolved the above problems. I have found that the same problem exist for another text. Please find the example code to reproduce the issue.

        SKPaint paint = new SKPaint();
        paint.TextEncoding = SKTextEncoding.Utf8;
        paint.IsAntialias = true;
        paint.TextAlign = SKTextAlign.Left;
        //As per your suggestion, I have enabled SubpixelText property.
        paint.SubpixelText = true;
         string text = char.ConvertFromUtf32(254);
        paint.Typeface = SKTypeface.FromFile(@"wingding.ttf");
        paint.TextSize = 12;
        SKRect rect = new SKRect();
        float width = paint.MeasureText(text, ref rect);
        Console.WriteLine(width);

The width of the text was calculated in Linux is invalid. Please find the size difference between Windows & Linux from below.

Windows - 10.69922 Linux - 6

VijayRM avatar May 13 '19 07:05 VijayRM

@Gillibald - Could you please provide solution for this issue?

VijayRM avatar May 22 '19 12:05 VijayRM

I need the font file you are using to investigate this further. If you measure a string your should set paint.TextEncoding = SKTextEncoding.Utf16 not Utf8. That can result in errors.

Gillibald avatar May 22 '19 12:05 Gillibald

I have attached the fonts file wingding.zip. Even if i use Utf16 encoding the same issue still exists.

VijayRM avatar May 23 '19 09:05 VijayRM

Hi, I've faced this problem, yesterday and I guess that I had found a workaround.

Try this: SKTypeface.FromData(SKData.Create(stream));

It has worked for me, :).

martinhonovais avatar Jun 17 '19 13:06 martinhonovais

@Tazjoubire so are you saying that you get different results when loading the font via a stream vs a data? That seems to be a bug somewhere...

mattleibow avatar Jun 29 '19 09:06 mattleibow

Yes there is a bug. That's why I implemented the GetTableData etc

Gillibald avatar Jun 29 '19 09:06 Gillibald

This fails on Linux https://github.com/mono/SkiaSharp/blob/master/source/SkiaSharp.HarfBuzz/SkiaSharp.HarfBuzz.Shared/BlobExtensions.cs#L28

GetMemoryBase returns IntPtr.Zero on Linux

Gillibald avatar Jun 29 '19 09:06 Gillibald

Hi all!

Yes @mattleibow, If I load the font from stream it does not work, otherwise, if I load font from SKData it works perfectly in both environments linux and windows.

Additional, I am trying to load a barcode font and it works very well.

Thanks.

martinhonovais avatar Jul 01 '19 15:07 martinhonovais

For me, loading from SKData is still same. The only thing that fixed it is by setting SubpixelText to true as suggested by Gillibald. Thanks :)

Ghasan avatar Apr 03 '20 15:04 Ghasan

Facing same issue even if we load from SKData and setting SubpixelText to true. Can any one please suggest to overcome this issue.

parthipanr avatar Oct 06 '20 06:10 parthipanr

Not sure if it's related, the lineheight is also off in linux (is it calculated from the font size? ) see the related link on QuestPDF for detail.

kyugoa avatar Jun 23 '22 14:06 kyugoa

This might be unrelated to the issue, but as this is one of the few bug reports I can find that seems to be related, I add this here:

I still can't set the font size to be easily readable as a user. No matter to what I set the DPI with Xft.dpi. And MONO_MWF_SCALING doesn't seem to do anything either.

Yes, this is a serious accessibility issue.

Somebody did a patch. https://web.archive.org/web/20161025103319/http://www.vakuumverpackt.de/configurablesystemfontsformono/ which sadly isn't available any more; but I'm wondering why something like this still isn't in mono.

Seegras avatar Dec 28 '23 23:12 Seegras