SkiaSharp
SkiaSharp copied to clipboard
[BUG] Text size measured improperly in Linux OS
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
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.
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);
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
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.
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.
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?
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.
Thanks @Gillibald . I will do the necessary changes and update you the confirmation once after ensuring the complete testing.
@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
@Gillibald - Could you please provide solution for this issue?
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.
I have attached the fonts file wingding.zip. Even if i use Utf16 encoding the same issue still exists.
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, :).
@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...
Yes there is a bug. That's why I implemented the GetTableData etc
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
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.
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 :)
Facing same issue even if we load from SKData and setting SubpixelText to true. Can any one please suggest to overcome this issue.
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.
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.