Definitely a bug with with getStringWidth*, should be a nice small UI win for the JUCE team.
I’m grateful for @migizo for pointing it out. I do a lot of horizontal centering (buttons, etc) of fonts with letter-spacing and things often feel not quite right…
Not to muddy the waters, but I believe another issue here is JUCE conflates kerning with letter spacing.
Kerning is spacing between letters. It’s something that type designers meticulously take care of. The amount of space differs for every character combo.
Tracking or letter spacing (see: css and every design tool) adds/removes a constant amount of spacing between glyphs— while keeping the carefully designed kerning intact. This is so designers/implementers (like us!) can tighten up a font or make it feel more spacious without ruining the font’s internal knowledge of how characters relate to each other. The kerning is not touched or altered.
I’m not 100% on this, but it looks like JUCE’s withExtraKerningFactor does something different, it’s a multiplier that overrides the kerning of the font’s glyphs at a low level, for example via kCTKernAttributeName on macOS. As far as I can tell this replaces the kerning between glyphs with a constant amount of space — getting rid of the meticulous work done by the type designer. I haven’t “proven” this with a demo, but this would explain the discrepancy @migizo is seeing in their test as well as some issues I’ve noticed when going adjusting (what I assumed was) letter-spacing.
Edit: I should have tested this before jumping to conclusions, sorry about that, see below.
Better to embrace breaking changes to align JUCE with other tools and well-defined standards. Any projects relying on bugs should expect issues when those bugs are fixed!
But wouldn’t this be very obvious? Isn’t it something you would immediately see in the font demo, as soon as you moved the kerning slider?
Also, the proposed change to Font::getStringWidthFloat() messes up the spacing in the textEditor when a kerning factor is applied. Screenshot from the demoRunner:
Sorry about that, I jumped to conclusions based on the code and apple docs without first verifying behavior. The Apple docs seemed to imply that it was replacing/specifying the kerning. The docs for the sibling kCTTrackingAttributeName are clearer that it’s additive, and more modern (also named correctly). This is interesting too:
it treats tracking as trailing whitespace and a nonzero amount disables nonessential ligatures, unless overridden by the presence of kCTLigatureAttributeName.
Testing things out in the font demo (good call!) it looks that withExtraKerningFactor behaves identically to Figma’s letter-spacing. It’s correctly adding a constant factor (%) of the font’s height in points.
tail between legs (though perhaps the JUCE function should still be renamed for clarity)
Exactly. It’s very good to know that the function includes a trailing tracking space, if one wants to use it directly! But when centering text JUCE does not seem to use that function.
The change I posted above to juce_GlyphArrangment.cpp apparently solves the centering issue by itself, but I have no idea if it breaks something somewhere else.