Follow-up: solved — here’s exactly what was wrong and how I fixed it
Thanks @mekkablue for pointing me to the Windows tutorial, and @dezcom for the moral support. 
I wanted to post a proper technical follow-up because this problem kept me busy for a while, and I think the full picture is worth documenting for anyone who searches for “EasySign kerning GDI” in the future.
What the actual problem was
The root cause is a fundamental architectural split between GDI (the legacy Windows rendering layer) and OpenType Layout (GPOS/GSUB). EasySign uses GDI to render text. GDI predates OpenType Layout entirely and has no awareness of the GPOS table whatsoever. It does not matter how complete or correct your GPOS kern feature is — GDI simply never reads it.
What GDI does read for kerning is the old-style kern table — the pre-OpenType format, where every kerning pair is stored as an explicit glyph-to-glyph entry (no group kerning, no classes). This table is largely invisible in Glyphs because Glyphs, correctly, writes all kerning into GPOS. The kern table has been considered legacy since OpenType 1.0.
So the full chain of failures was:
- I exported OTF (CFF outlines) — the spec explicitly forbids a
kern table in CFF fonts, so there was never any chance of GDI kerning working regardless of other settings.
- Even after switching to TTF, the
kern table is not written by default in Glyphs — you have to explicitly request it.
- The EasySign vendor’s FontForge conversion worked because FontForge, when converting OTF → TTF, automatically generates a legacy
kern table from the GPOS data. That was the hint I needed.
How I diagnosed it
I built an AI Agent using Perplexity Computer (an AI assistant with tool-use capabilities) to create a proper font inspection and compatibility reporting toolkit. I described the problem — GDI, EasySign, GPOS, kern table — and had it write a Python script around fontTools/TTX and otfinfo that inspects any .otf or .ttf and produces a pass/fail checklist specifically for GDI/EasySign compatibility.
The script checks for:
- GPOS table presence and lookup types (pair kern, mark, mkmk, cursive)
- Legacy
kern table presence and pair count
- GSUB features (liga, calt, locl, ccmp)
fvar presence (variable fonts are unsupported by GDI)
- Windows Unicode BMP
cmap (Platform 3, Encoding 1) — required by GDI
- OS/2
fsType embedding flags
- TrueType hinting tables (
cvt, fpgm, prep, gasp)
- Outline format (CFF vs TrueType)
- Name table completeness
- UPM value
Running the first version of the font through this inspector immediately produced:
[kern]
[FAIL (CRITICAL)] Legacy 'kern' table present (GDI requirement)
→ MISSING — GDI-based apps (EasySign, old Windows apps) IGNORE GPOS
and rely solely on the legacy kern table. Without it, no kerning applies.
No ambiguity. No digging through XML dumps. Just a clear critical failure with an explanation of why.
The fix in Glyphs
Once the diagnosis was confirmed, the fix was a single custom parameter. In File → Font Info → Exports, on the TTF instance:
Add custom parameter: Export kern Table → checked (boolean)
This parameter does not appear in the autocomplete dropdown in Glyphs 3. You have to type the full name Export kern Table manually in the search field and press Add. The checkbox on the left of the parameter row must be enabled.
TTF only. This parameter is silently ignored for OTF/CFF exports. The OpenType spec forbids a kern table in CFF fonts (section ‘kern’ in the spec: “OpenType fonts containing CFF outlines are not supported by the ‘kern’ table”). So if you’re delivering for a GDI-based app, TTF is non-negotiable.
What Glyphs does when this parameter is enabled: it takes all your GPOS kerning (including group/class-based kerning) and flattens it into individual glyph-to-glyph pairs in the kern table. For Groot Natuursteen, that turned ~194 GPOS pairs (169 individual + 25 class-based) into 453 legacy kern pairs — the class expansion accounts for the difference.
After re-exporting as v0.004, the inspector result:
[kern]
[PASS] Legacy 'kern' table present (GDI requirement)
→ 453 pairs in 1 subtable(s).
[PASS] Legacy 'kern' table has pairs
→ 453 pair(s).
TOTAL: 23/25 passed | 0 critical failures
✅ LIKELY COMPATIBLE with EasySign / GDI
A note on Rainer’s fvar suggestion
Rainer mentioned adding an empty fvar table to make GPOS work. This is a known workaround for some Windows apps where the presence of fvar triggers the DirectWrite rendering path instead of GDI, which does understand GPOS. However:
- It doesn’t help for Windows XP, which predates DirectWrite.
- EasySign explicitly uses GDI regardless of font format flags.
- An empty
fvar technically makes a static font declare itself as variable, which can cause issues in other environments (PDF renderers, some print workflows).
For a dedicated GDI-target deployment like EasySign, the legacy kern table is the only reliable solution.
The GDI feature support table (for reference)
For anyone hitting similar issues with other GDI-based Windows apps (label printers, sign software, legacy office apps, etc.):
| Feature |
Table |
GDI reads it? |
| Kerning |
Legacy kern table |
Yes — only kerning source |
| Kerning |
GPOS kern feature |
No |
| Mark/mkmk positioning |
GPOS |
No |
| Ligatures, calt, swsh |
GSUB |
No |
| Variable font axes |
fvar / gvar |
Not supported |
| Unicode character mapping |
cmap Plat 3 Enc 1 |
Required |
| Embedding rights |
OS/2 fsType |
Checked |
| TrueType hinting |
cvt/fpgm/prep/gasp |
Applied |
The practical consequences: in EasySign (and any GDI app), your ligatures don’t form, contextual alternates don’t activate, diacritic positioning via mark/mkmk is ignored, and kerning only works if the legacy kern table is present. For Latin text fonts this is mostly manageable. For complex scripts (Arabic, Devanagari) it’s a much deeper problem.
On the “broken font” comment
Rainer noted that using Export kern Table “effectively breaks your font”. That’s a fair characterisation from a type design perspective — you end up with two kerning sources that can theoretically diverge, and the kern table’s lack of group support means any future kerning updates have to be re-flattened. But for a client font being delivered exclusively for a GDI target, it’s the correct trade-off. The font works correctly in EasySign, and it still works correctly in any modern OpenType-aware app (which will use GPOS and ignore the kern table).
The omelet was worth it. 
René — Characters Font Foundry