libgdiplus
libgdiplus copied to clipboard
Bug with MeasureCharacterRanges on Linux, if text contains LF/CR
I'm using the System.Drawing.Common NuGet package. Main problem: there is a difference in how method MeasureCharacterRanges work on Windows and on Linux. On Windows this code works correctly: each char -> rectangle, CR/LF -> empty rectangle. On Linux: CR symbols disappear, the first symbols of each line after LF also disappear.
Code:
var g = Graphics.FromImage(new Bitmap(1, 1));
var font = new Font("Arial", 11f);
var rect = new RectangleF(0, 0, 99999, 99999);
var sf = new StringFormat();
string text = "12\r\n34\r\n56";
var count = text.Length;
CharacterRange[] cr = new CharacterRange[count];
for (int index = 0; index < count; index++)
{
cr[index].First = index;
cr[index].Length = 1;
}
sf.SetMeasurableCharacterRanges(cr);
Region[] ranges = g.MeasureCharacterRanges(text, font, rect, sf);
RectangleF?[] rects = new RectangleF?[count];
for (int index = 0; index < count; index++)
{
rects[index] = ranges[index].GetBounds(g);
}
Results on Windows:
Results on Linux:
I highlighted the symbols and their rectangles in yellow.
I have an idea where the problem might be. I analysed method cairo_MeasureCharacterRanges in libgdiplus/src/text-cairo.c This method call MeasureString and use resulting StringDetails from it. But inside MeasureString the input string is processed (CR ignored, LF to STRING_DETAIL_LF) and resulting StringDetails will be SHORTER than the input string! So now is impossible to match the input char and corresponding rectangle ....
The Cairo text code is known to be broken (https://github.com/mono/libgdiplus/pull/137 for some background). Newer versions of libgdiplus try to use Pango for the text layout and rendering instead.
How can I use the newer version of libgdiplus ? The only way - to rebuild sources with --with-pango ? Or wait a few months while this will be enabled in the official build ?
Depending on your distro and how you acquired the libgdiplus (Mono repositories vs distro repositories) it may already be included.
I'm a newbie to Linux and Docker, use Dockerfile:
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 AS base
RUN apt-get update &&
apt-get install -y libgdiplus libc6-dev
I'd recommend to follow the first step from https://www.mono-project.com/download/stable/#download-lin for your particular distribution. Then apt-get install -y libgdiplus
or something similar.
Thanks for the help here @filipnavara. Might be good to add this URL in the repo readme.
cc: @directhex