Repository: googlefonts/ufo2ft
Pull request #845 (2024-05-23 17:24:14)

Old kern writer: Convert groups back
This fixes an oversight in https://github.com/googlefonts/ufo2ft/pull/841.

The kerning pair sides have to be converted back to fea AST classes. Since groups aren't filtered in `getVariableKerningPairs`, it should hopefully be okay to just grab them by their members 😬 


Patch:
diff --git a/Lib/ufo2ft/featureWriters/kernFeatureWriter2.py b/Lib/ufo2ft/featureWriters/kernFeatureWriter2.py
index 13c8c95..de4eb66 100644
--- a/Lib/ufo2ft/featureWriters/kernFeatureWriter2.py
+++ b/Lib/ufo2ft/featureWriters/kernFeatureWriter2.py
@@ -251,7 +251,39 @@ class KernFeatureWriter(BaseFeatureWriter):
                 glyphSet or {},
                 options or SimpleNamespace(**KernFeatureWriter.options),
             )
-            return [KerningPair(pair.side1, pair.side2, pair.value) for pair in pairs]
+            pairs.sort()
+            side1toClass: Mapping[tuple[str, ...], ast.GlyphClassDefinition] = {
+                tuple(
+                    glyph
+                    for glyphs in glyph_defs.glyphSet()
+                    for glyph in glyphs.glyphSet()
+                ): glyph_defs
+                for glyph_defs in side1Classes.values()
+            }
+            side2toClass: Mapping[tuple[str, ...], ast.GlyphClassDefinition] = {
+                tuple(
+                    glyph
+                    for glyphs in glyph_defs.glyphSet()
+                    for glyph in glyphs.glyphSet()
+                ): glyph_defs
+                for glyph_defs in side2Classes.values()
+            }
+            return [
+                KerningPair(
+                    (
+                        side1toClass[pair.side1]
+                        if isinstance(pair.side1, tuple)
+                        else pair.side1
+                    ),
+                    (
+                        side2toClass[pair.side2]
+                        if isinstance(pair.side2, tuple)
+                        else pair.side2
+                    ),
+                    pair.value,
+                )
+                for pair in pairs
+            ]
 
         if glyphSet:
             allGlyphs = set(glyphSet.keys())


Test patch:
diff --git a/tests/featureWriters/variableFeatureWriter_test.py b/tests/featureWriters/variableFeatureWriter_test.py
index 077fd4f..b501c03 100644
--- a/tests/featureWriters/variableFeatureWriter_test.py
+++ b/tests/featureWriters/variableFeatureWriter_test.py
@@ -90,6 +90,11 @@ def test_variable_features_old_kern_writer(FontClass):
             "class": "CursFeatureWriter",
         },
     ]
+    for index, source in enumerate(designspace.sources):
+        font = source.font
+        font.groups["public.kern1.alef"] = ["alef-ar.fina"]
+        font.groups["public.kern2.alef"] = ["alef-ar.fina"]
+        font.kerning[("public.kern1.alef", "public.kern2.alef")] = index
 
     _ = compileVariableTTF(designspace, debugFeatureFile=tmp)
 
@@ -98,9 +103,13 @@ def test_variable_features_old_kern_writer(FontClass):
         markClass dotabove-ar <anchor (wght=100:100 wght=1000:125) (wght=100:320 wght=1000:416)> @MC_top;
         markClass gravecmb <anchor 250 400> @MC_top;
 
+        @kern1.alef = [alef-ar.fina];
+        @kern2.alef = [alef-ar.fina];
+
         lookup kern_rtl {
             lookupflag IgnoreMarks;
             pos alef-ar.fina alef-ar.fina <(wght=100:15 wght=1000:35) 0 (wght=100:15 wght=1000:35) 0>;
+            pos @kern1.alef @kern2.alef <(wght=100:0 wght=1000:1) 0 (wght=100:0 wght=1000:1) 0>;
         } kern_rtl;
 
         feature kern {