mono / libgdiplus

C-based implementation of the GDI+ API
http://www.mono-project.com/
MIT License
329 stars 171 forks source link

Fix text baseline position for some fonts #669

Open PreferLinux opened 3 years ago

PreferLinux commented 3 years ago

Text drawn with some fonts (for example Calibri and the free metric-equivalent Carlito) is not aligned to the same baseline as on Windows.

This is because fonts have three sets of roughly equivalent metrics, and different platforms use different ones. Windows uses one set, and Pango primarily uses a combination of the other two. The set Windows uses has the line spacing included in the ascent and descent. The other sets allow the gap to be specified separately, but for many fonts (even most) the one Pango uses has got only a minimal gap with the ascent roughly matching Window's one (hence why this problem is not common). For the first line of text the baseline is positioned according to the ascent.

However, these two fonts have a significant difference between the Windows ascent and the other two. As the text baseline is positioned according to the ascent, the text is positioned equivalently higher in the bounding box: Screenshot_20200902_204938

This works around the problem by calculating the correct baseline and adding the difference between it and the baseline used by Pango to the offset for text drawn with StringFormat->lineAlignment set to Near. As long as the metrics returned by GdipGetCellAscent and co are correct this should not make drawing wrong.

With fix: Screenshot_20200902_204817

Windows 8.1: screenshot-Windows-font-alignment

PreferLinux commented 3 years ago

This has some significant issues, both before and after the changes. In particular, both versions have issues with measuring. I'll continue to work on the problem though.