-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Multiline font line spacing ignores baselines #1540
Comments
I think that information should be enough to fix the issue, yes. I have tried to make the change to allow access the baseline from Python, but without success. |
We've had nearly this exact bug before, and even have a test for it in test_imagefont.py. (the ones that use "hey you\nyou are awesome\nthis looks awkward" ) |
https://github.com/python-pillow/Pillow/blob/master/Tests/images/multiline_text.png: That one actually looks ok, 20px between baselines, but I think only by circumstance of the letters used: |
That particular problem of baseline shifting, was what was being tested by that string. Apparently it predates the multiline text, and the multiline text call didn't use the same method to determine line spacing vs line height that was previously fixed. It's also possible that the test doesn't discriminate enough, because it's too small or something, and the differences are within a pixel. |
Ok, checked on this a bit more, and there are some metrics we can get from Freetype, and some that we're already getting. I added height, x_ppem (pixels per em, oddly enough, it's the font size), and y_ppem, which are mostly useless. Height is the minimum line to line spacing, which isn't really what we're worried about. It's recommended to use ascent + descent in the Freetype docs. Ascent (which we have) is the baseline to top of character. Descent is from the baseline to the bottom of the descenders.
Looking at the generated sizes here, there are three things that pop out:
So, if we follow the approach in test_render_multiline, that of using constant spacing, everything should work out correctly:
I've put both of these changes in my multiline_text branch: https://github.com/wiredfool/Pillow/tree/multiline_text but haven't tweaked the tests yet. I think this is the right approach. |
Here's the diff: master...wiredfool:multiline_text Looks good. |
I've added a PR that updates the tests: #1573. I noticed the lines are a bit close, and would benefit with some more default spacing, rather than zero. We had four pixels before, so created a parallel PR with extra spacing: #1574. Also both PRs decrease coverage because the changes in _imagingft.c to add getters for |
I'm not sure that we need x/y_ppem. OTOH, I don't see any reason that we shouldn't expose them. A quick test should do it, and make sure that we're not shipping broken. Height is at least interesting in that it's not the same as the font size. |
Some example code to draw three lines of text:
Produces:
The line spacing is a bit off.
The line spacing is worked out by simply calculating the height of each line of rasterised text (then adding some optional spacing, not done in this example):
https://github.com/python-pillow/Pillow/blob/master/PIL/ImageDraw.py#L275-L278
But because the first line and last line has ascenders but no descenders, and the second has both, it gives wonky output.
Instead, the lines should be offset by the _baselines_ of each line, not their absolute heights. Here's an example from the web:
Is this something that can be fixed?
ImageDraw.multiline_text
gets the line height fromImageDraw. textsize()
<-ImageFont.getsize
<-Image.core.font.getsize
<- andImagingFontObject
does have abaseline
used internally, but not returned.What does
ImageDraw.multiline_text
need for its calculations? Just height of the bitmap line and the bitmap's offset from the baseline?cc @radarhere
The text was updated successfully, but these errors were encountered: