Skip to content

FOP-3343: A font configured with kerning="false" is not kerned through GPOS either - #112

Open
plutext wants to merge 1 commit into
apache:mainfrom
plutext:FOP-3343
Open

plutext wants to merge 1 commit into
apache:mainfrom
plutext:FOP-3343

Conversation

@plutext

@plutext plutext commented Oct 2, 2026

Copy link
Copy Markdown

Fixes FOP-3343.

The font configuration's kerning attribute is documented as enabling or disabling kerning
for the font. It did so only for the legacy kern table: OFFontLoader skips copyKerning when
it is false, and GlyphMapping.useKerningAdjustments then finds no kerning info. GPOS
positioning was independent of it: MultiByteFont.performPositioning ran whenever the font
had a GPOS table, and every script processor's positioning feature list carries kern. So a
font with a GPOS kern feature, which is nearly every current font, was kerned whatever the
flag said. Underneath, the loader never recorded the flag on the font object, so
CustomFont.isKerningEnabled() was true for every TrueType font however it was configured.

OFFontLoader now records the flag (setKerningEnabled). MultiByteFont.performPositioning
passes it down, and with kerning disabled the script processor positions with the kern
feature left out of its feature list; mark and mkmk still apply, since they are not
kerning. GlyphPositioningTable.position and ScriptProcessor.position gain an overload
taking the flag; the existing signatures delegate with true.

Measured on this branch, Carlito 14pt (no legacy kern table, GPOS kern only), no language,
word widths from pdftotext -bbox:

                     kerning="true"       kerning="false"
                     AVATAR   Toffee      AVATAR   Toffee
  before             43.19    34.71       43.19    34.71
  after              43.19    34.71       46.62    36.27

After, the unkerned Toffee still carries its ligature (36.27 against 36.65 unligated):
substitution is unaffected.

KerningFlagTestCase: the flag reaches the font, and DejaVuLGCSerif's "AV" is adjusted
through GPOS with kerning on and not with it off. PositioningWithoutKerningTestCase: kern
is removed from a feature list and the marks stay.

🤖 Generated with Claude Code

…h GPOS either

The font configuration's kerning attribute is documented as enabling or disabling kerning
for the font. It did so only for the legacy kern table: OFFontLoader skips copyKerning when
it is false, and GlyphMapping.useKerningAdjustments then finds no kerning info. GPOS
positioning was independent of it: MultiByteFont.performPositioning ran whenever the font
had a GPOS table, and every script processor's positioning feature list carries kern. So a
font with a GPOS kern feature, which is nearly every current font, was kerned whatever the
flag said. Underneath, the loader never recorded the flag on the font object, so
CustomFont.isKerningEnabled() was true for every TrueType font however it was configured.

OFFontLoader now records the flag (setKerningEnabled). MultiByteFont.performPositioning
passes it down, and with kerning disabled the script processor positions with the kern
feature left out of its feature list; mark and mkmk still apply, since they are not
kerning. GlyphPositioningTable.position and ScriptProcessor.position gain an overload
taking the flag; the existing signatures delegate with true.

Measured on this branch, Carlito 14pt (no legacy kern table, GPOS kern only), no language,
word widths from pdftotext -bbox:

                     kerning="true"       kerning="false"
                     AVATAR   Toffee      AVATAR   Toffee
  before             43.19    34.71       43.19    34.71
  after              43.19    34.71       46.62    36.27

After, the unkerned Toffee still carries its ligature (36.27 against 36.65 unligated):
substitution is unaffected.

KerningFlagTestCase: the flag reaches the font, and DejaVuLGCSerif's "AV" is adjusted
through GPOS with kerning on and not with it off. PositioningWithoutKerningTestCase: kern
is removed from a feature list and the marks stay.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant