ImageSharp.Drawing
ImageSharp.Drawing copied to clipboard
TextBuilder.GenerateGlyphs places the characters incorrectly with the specific word 'all'
Prerequisites
- [ ] I have written a descriptive issue title
- [ ] I have verified that I am running the latest version of Fonts
- [ ] I have verified if the problem exist in both
DEBUG
andRELEASE
mode - [ ] I have searched open and closed issues to ensure it has not already been reported
Description
On one particular Font, for one particular word, the text renderer is placing the letters incorrectly. The word is "all". It is placing the second 'l' to the left of the 'a'.
Steps to Reproduce
Here is my test application that demonstrates this. I have attached the font file I am using and also the resulting image.
using SixLabors.Fonts;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Drawing;
using SixLabors.ImageSharp.Drawing.Processing;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
var imgAll = new Image<Rgba32>(720, 720);
imgAll.Mutate(
imageProcessingContext =>
{
imageProcessingContext.Fill(Color.White);
var fontCollection = new FontCollection();
FontFamily fontFamily = fontCollection.Add("./NettoOffc.ttf");
Font font = new Font(fontFamily, 300, FontStyle.Regular);
var textOptions = new TextOptions(font)
{
HorizontalAlignment = HorizontalAlignment.Left,
VerticalAlignment = VerticalAlignment.Top,
};
var text = "all";
var bounds = TextMeasurer.MeasureBounds(text, textOptions);
var pathLine = new[] {
new PointF(200, 224),
new PointF(200 + bounds.Width, 224)
};
var path = new PathBuilder().AddLine(
pathLine[0],
pathLine[1]
).Build();
imageProcessingContext.DrawLines(new Pen(Color.Red, 30), pathLine);
imageProcessingContext.Fill(
new DrawingOptions { GraphicsOptions = { Antialias = true } },
Brushes.Solid(Color.Black),
TextBuilder.GenerateGlyphs(text, path, textOptions)
);
}
);
using FileStream? fileStream = File.OpenWrite("output.png");
imgAll.SaveAsPng(fileStream);
fileStream.Close();
Some other observations:
- If I set the horizontal alignment to 'center' the problem goes away. It's only if it is left or right.
- If I add an extra 100 pixels to the right part of the path then the problem goes away. But, as the red line indicates, there is enough space for the second 'l'
System Configuration
This is a .NET 6.0 application running on windows. Here are the packages I am including.
<ItemGroup>
<PackageReference Include="SixLabors.ImageSharp" Version="2.1.2" />
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta14.16" />
<PackageReference Include="SixLabors.Fonts" Version="1.0.0-beta17.8" />
</ItemGroup>
Other attachments include:
- The Font File (NettoOffc.zip)
- The entire project that demonstrates this (RenderWords.zip)
Oooh this is an interesting one! At first I thought it must be an incorrect GPOS update but the alignment behavior is puzzling.
Can you please try Fonts 1.0.0-beta17.13
. I'm not seeing this.
Hold on.... I'm still seeing it in your demo app. It's not the Fonts library, it's the TextBuilder
when a path is provided. I'll transfer the issue.
As a workaround you can set the TextOptions .Origin
property to match your path origin.
I've finally had the chance to have a look at this properly.
The issue is caused by our code which calculates the position of a point along the given path at a given distance. The code works well for closed paths since it reduces the distance to the remainder (distance %= path.Length)
which makes a nice loop.
For open paths we don't want to do that, we want to create a new virtual point at the correct angle and distance calculated from the last two points in the path.
The below image demonstrates the product of two approaches drawing the text overlapped following my local updates.
- Black =
DrawText
with origin set at the path origin. - Pink diagonal =
TextBuilder
+FillPath
As you can see the match is exact.
I'll open a PR once #261 is merged.