-
-
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
font.getsize() changes after installing libraqm #4483
Comments
Well, libraqm is a library for complex text layout. So it doesn't seem unreasonable that it would want to layout text slightly differently. If you don't want to use raqm, instead of font=ImageFont.truetype('Microsoft/msyhl.ttc',size=14,layout_engine=ImageFont.LAYOUT_RAQM) you can use font=ImageFont.truetype('Microsoft/msyhl.ttc',size=14,layout_engine=ImageFont.LAYOUT_RAQM) Regarding the fact that 8+9+7 doesn't equal to 23, it is certainly possible in other languages that the width of a combination of two characters is not the same as the width of the two characters separately. It's also conceivable if the English font were slanted - one letter might easily stray into the space of the previous one. I imagine that this is less obvious in your font. If you'd like to follow this further, it would be helpful to provide a copy of a font that we could use to reproduce this. However, I don't think it's necessarily true that 'a', 'b' and 'c' should combine to make the width of 'abc'. |
The font I believe this is caused by rounding. Looking at the source code in a debugger, it looks like basic text layout is using FreeType's hinting to round advance values (glyph widths) to the nearest integer, while Raqm layout is returning unrounded values, the sum of which is then rounded up in For example, the unrounded advance width of the glyph 'a' is 7.46875px, which is rounded to 7px for basic layout. If rendering the string 'a' with Raqm, the sum of 7.46875px is rounded up to 8px at the end of getsize. from PIL import ImageFont
basic = ImageFont.truetype("msyhl.ttc", 14, layout_engine=ImageFont.LAYOUT_BASIC)
print(basic.getsize("a")) # (7, 16)
print(basic.getsize("a" * 10)) # (70, 16)
raqm = ImageFont.truetype("msyhl.ttc", 14, layout_engine=ImageFont.LAYOUT_RAQM)
print(raqm.getsize("a")) # (8, 16)
print(raqm.getsize("a" * 10)) # (75, 16) Let's look at the 10 character string 'aaaaaaaaaa'. With basic layout, the width of each 'a' is rounded to 7px before computing the size, so the sum will be 10×7px=70px. With raqm, the sum will be 74.6875px, which gets rounded up to 75px. Adding Line 550 in 394f7a0
This even passes all tests, except for those using the oldest versions of FreeType (the failing test runners don't support raqm either): https://github.com/nulano/Pillow/runs/605844576 I'm not sure what the pros and cons of this change are regarding the appearance of text, but I don't think it's worth changing for Pillow backwards compatibility reasons. The Raqm values cannot be rounded before rendering, because this could misalign complex glyphs. Note also, that this difference can make it harder (confusing) to write tests for ImageFont, as tests in |
Thanks @nulano for your analysis. Sounds to me like raqm made a decision to do things differently, and this is the consequence. I agree that we shouldn't make changes to fight against the complex rendering of Raqm. Am I correct in thinking that your intention with #4959 is that the new method print(font.getlength('a'))
print(font.getlength('b'))
print(font.getlength('c'))
print(font.getlength('abc')) will mean that 'a + b + c' will equal 'abc' regardless of using Raqm or not, because the increased precision will mean that rounding is no longer a problem? |
That is correct. Note that this is not the only advantage, |
Cool. Closing then, as it sounds like users could use that moving forward, and breaking backwards compatibility to fix this more directly is likely to be more trouble than it's worth. |
I am using PIL to render text on images with position annotation. The text size changes after installing libraqm.
Result without libraqm
The sum of character's width 7+8+7=22 is correct.
Result after installing libraqm
The sum of character's width 8+9+7=24 doesn't equal to 23.
Also I find that the text size changes differently on different font after installing libraqm.
Why are these happening after installing libraqm?
The text was updated successfully, but these errors were encountered: