Bad/no kerning in PowerPoint
Describe the bug The missing kerning makes Inter unusable in PowerPoint.
To Reproduce
- A clean install of Inter 4.1 via
Inter.ttc. - Create a fresh slide deck in PowerPoint.
- Add "Test" text in Inter and Inter Display.
- The kerning is very bad. Screenshots below.
Screenshots
PowerPoint (bad kerning)
LibreOffice (better kerning)
Environment
- OS: Windows
- App that renders the font PowerPoint 365
- Version of font Inter 4.1
Appears to be a problem in PowerPoint. PowerPoint 2024 does the same thing - no kerning at all. Checked the settings and Kerning is On. Works fine in Word 2024.
The Microsoft Aptos font does not work either - no kerning at all. Appears to be a problem in PowerPoint.
Appears to be a problem in PowerPoint.
Look like it.
In addition, I'm not entirely happy with the kerning of "Inter" in Libreoffice.
"Inter Display" tucks the e under the T, "Inter" does not.
But that might be the actual font, not the software.
I remembered something about PowerPoint kerning.
It only works with the old legacy kern table.
If you test with some of the Windows fonts which have just the kern table, or both the new GPOS table and the kern table - it appears to work.
Aptos has both - and in further testing it seems to work.
Goudy Old Style has just kern - it works.
Arial has both - and it works.
Arial Narrow has just kern - and it works.
Gill Sans and Gill San Nova have just (kern) - both work.
Etc. etc.
Fonts which have only the modern OpenType kerning do not work. Like Inter. Helvetica Now Display - does not work. Nunito Sans - does not work. Etc., etc.
So it appears that PowerPoint requires the font to have the old legacy kern table for kerning to work.
Font handling in PowerPoint has been way behind for years.
So it appears that PowerPoint requires the font to have the old legacy kern table for kerning to work.
Is it much effort to make Inter provide both OpenType and legacy kern tables?
The issue probably makes us steer away from Inter.
The font has to just work everywhere for professional use.
Legacy kern tables have a number of drawbacks.
You cannot have differences for different languages.
You cannot use classes - it is one long list of single pairs.
This can make the list very long.
Inter kerning as one long list would have around 480,000 pairs.
This adds a large table and a lot of size to the fonts.
You will not find kern tables in GF fonts.
There is a limit on the number of pairs - ~65,000 I think
(don't remember exactly, could be 65k per subtable, dunno)
Applications (and broswers) can have limits on the size of the kern table they will read and use.
Some of the Windows fonts which have both tables have very limited kern tables.
PowerPoint has been waaaay behind on font support for many years. Very little OpenType support at all. You can find MC Community requests for PP to add support for proper kerning, like here, and there are also some feedback threads.
Anyway, I think it is unlikely the Inter developer will add a kern table.
You can try it yourself.
I think FontForge can be used to add a kern table.
I think this should be reported to Microsoft Answers as well.
I built a script with FontTools to extract GPOS kernings for the Latin subset to manually create a kern table.
But it returns GPOS kernings only for Inter Thin. What am I missing?
Here is the script to extract kerning pairs:
from fontTools.ttLib.ttCollection import TTCollection
def get_kerning_value(gpos_table, glyph1, glyph2):
for lookup in gpos_table.LookupList.Lookup:
if lookup.LookupType == 2: # Pair Adjustment
for subtable in lookup.SubTable:
# Format 1: Direct Pair Kerning
if subtable.Format == 1:
if glyph1 in subtable.Coverage.glyphs:
pair_set_index = subtable.Coverage.glyphs.index(glyph1)
pair_set = subtable.PairSet[pair_set_index]
for pair_value_record in pair_set.PairValueRecord:
if pair_value_record.SecondGlyph == glyph2:
return pair_value_record.Value1.XAdvance
# Format 2: Class-Based Kerning
elif subtable.Format == 2:
class1_idx = subtable.ClassDef1.classDefs.get(glyph1, 0)
class2_idx = subtable.ClassDef2.classDefs.get(glyph2, 0)
value_record = subtable.Class1Record[class1_idx].Class2Record[class2_idx].Value1
if value_record:
return value_record.XAdvance
return 0 # No kerning found
def get_font_name(font):
name_table = font["name"]
for record in name_table.names:
if record.nameID == 4: # Full Font Name
return record.toUnicode()
col = TTCollection('Inter-4.1/Inter.ttc')
for f in col:
font_name = get_font_name(f)
k1 = get_kerning_value(f['GPOS'].table, "A", "V")
k2 = get_kerning_value(f['GPOS'].table, "T", "e")
print(f"{font_name} - AV: {k1}, Te: {k2}")
And this is the output for the AV and Te kerning pairs:
Inter Regular - AV: 0, Te: 0
Inter Black - AV: 0, Te: 0
Inter Black Italic - AV: 0, Te: 0
Inter Italic - AV: 0, Te: 0
Inter Thin - AV: -140, Te: -160
Inter Thin Italic - AV: -140, Te: -160
Inter Light - AV: 0, Te: 0
Inter Light Italic - AV: 0, Te: 0
Inter ExtraLight - AV: 0, Te: 0
Inter ExtraLight Italic - AV: 0, Te: 0
Inter Medium - AV: 0, Te: 0
Inter Medium Italic - AV: 0, Te: 0
Inter SemiBold - AV: 0, Te: 0
Inter SemiBold Italic - AV: 0, Te: 0
Inter Bold - AV: 0, Te: 0
Inter Bold Italic - AV: 0, Te: 0
Inter ExtraBold - AV: 0, Te: 0
Inter ExtraBold Italic - AV: 0, Te: 0
Inter Display Black - AV: 0, Te: 0
Inter Display Black Italic - AV: 0, Te: 0
Inter Display Regular - AV: 0, Te: 0
Inter Display Italic - AV: 0, Te: 0
Inter Display Thin - AV: -190, Te: -280
Inter Display Thin Italic - AV: -190, Te: -280
Inter Display Light - AV: 0, Te: 0
Inter Display Light Italic - AV: 0, Te: 0
Inter Display ExtraLight - AV: 0, Te: 0
Inter Display ExtraLight Italic - AV: 0, Te: 0
Inter Display Medium - AV: 0, Te: 0
Inter Display Medium Italic - AV: 0, Te: 0
Inter Display SemiBold - AV: 0, Te: 0
Inter Display SemiBold Italic - AV: 0, Te: 0
Inter Display Bold - AV: 0, Te: 0
Inter Display Bold Italic - AV: 0, Te: 0
Inter Display ExtraBold - AV: 0, Te: 0
Inter Display ExtraBold Italic - AV: 0, Te: 0