GPOS (in OTF font) not working in Windows based GDI-interface app

Hi there,

I’m working on a client font. They used to use a legacy Windows 7 environment. They’ve now moved to WindowsXP, using EasySign software. An old font they used didn’t work anymore.

They’ve had a freelancer from Bangladesh recreate the font for them, but this didn’t work out. Now they’ve asked me to save the day.

I’ve created an OTF font for them, but apparently the GPOS table is not exported, so the kerning doesn’t work on Windows.

This is the feedback I get from the vendor:

“The font we received from you only contains GPOS information. However, the EasySIGN application doesn’t see any kerning pairs in this font via the GDI interface used in EasySIGN, so kerning from your font isn’t applied.

I then used the FontForge utility to convert your OTF font to an equivalent TTF font. This TTF font contains, in addition to GPOS, kerning pairs automatically generated from GPOS. These kerning pairs are correctly recognized by EasySIGN’s GDI interface.”

How do I create the correct font file from Glyphs to further prevent this issue? Does a “simple TTF” file do the job? Or do I need to make more settings?
The Font Info > Features tab is (except for the Languagesystems) empty, although all the kerning pairs and info is available.

Thanks in advance.

René

See the Make your font work in Windows tutorial. In short: always use TTF; if possible add an empty fvar table to make GPOS work. But that may not work for Windows XP. If that is the case, resort to old-style kern table kerning (which effectively breaks your font, but you gotta break an egg for making that proverbial omelet).

1 Like

That gets an Oy. :wink:

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. :grinning_face_with_smiling_eyes:

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:

  1. 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.
  2. Even after switching to TTF, the kern table is not written by default in Glyphs — you have to explicitly request it.
  3. 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)

:warning: 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.

:warning: 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 :white_check_mark: Yes — only kerning source
Kerning GPOS kern feature :cross_mark: No
Mark/mkmk positioning GPOS :cross_mark: No
Ligatures, calt, swsh GSUB :cross_mark: No
Variable font axes fvar / gvar :cross_mark: Not supported
Unicode character mapping cmap Plat 3 Enc 1 :white_check_mark: Required
Embedding rights OS/2 fsType :white_check_mark: Checked
TrueType hinting cvt/fpgm/prep/gasp :white_check_mark: 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. :joy:


René — Characters Font Foundry

2 Likes

Thank you, René, for your hard work and tenacity!

You’re welcome. Long live AI. Through Perplexity Computer I understood this (for me) complex and ultimately stupid-simple problem. So I wanted at least to output a solid feedback that other typedesigners might need in the future.

1 Like