Repository: googlefonts/ufo2ft
Pull request #569 (2021-12-15 15:21:07)

Don't crash when there are only base-mark kerns
ufo2ft's kernFeatureWriter splits base-to-base and mark-to-base kerns like this:

https://github.com/googlefonts/ufo2ft/blob/db8302b4df2a9a1bd599d467d76a63c09d5b0e85/Lib/ufo2ft/featureWriters/kernFeatureWriter.py#L449-L452

There's a horrible corner case (which I've just hit!) if the only kerns in the font are between bases and marks: `basePairs` is empty and the assertion here fails:

https://github.com/googlefonts/ufo2ft/blob/db8302b4df2a9a1bd599d467d76a63c09d5b0e85/Lib/ufo2ft/featureWriters/kernFeatureWriter.py#L371-L374

This fixes that.


Patch:
diff --git a/Lib/ufo2ft/featureWriters/kernFeatureWriter.py b/Lib/ufo2ft/featureWriters/kernFeatureWriter.py
index 79ae099..29b4833 100644
--- a/Lib/ufo2ft/featureWriters/kernFeatureWriter.py
+++ b/Lib/ufo2ft/featureWriters/kernFeatureWriter.py
@@ -434,7 +434,8 @@ class KernFeatureWriter(BaseFeatureWriter):
                 # If there are pairs with a mix of mark/base then the IgnoreMarks
                 # flag is unnecessary and should not be set
                 basePairs, markPairs = self._splitBaseAndMarkPairs(pairs, marks)
-                self._makeSplitDirectionKernLookups(lookups, basePairs)
+                if basePairs:
+                    self._makeSplitDirectionKernLookups(lookups, basePairs)
                 if markPairs:
                     self._makeSplitDirectionKernLookups(
                         lookups, markPairs, ignoreMarks=False, suffix="_marks"
@@ -447,7 +448,11 @@ class KernFeatureWriter(BaseFeatureWriter):
             pairs = self.context.kerning.pairs
             if self.options.ignoreMarks:
                 basePairs, markPairs = self._splitBaseAndMarkPairs(pairs, marks)
-                lookups["LTR"] = [self._makeKerningLookup("kern_ltr", basePairs)]
+                lookups["LTR"] = []
+                if basePairs:
+                    lookups["LTR"].append(
+                        self._makeKerningLookup("kern_ltr", basePairs)
+                    )
                 if markPairs:
                     lookups["LTR"].append(
                         self._makeKerningLookup(


Test patch:
diff --git a/tests/featureWriters/kernFeatureWriter_test.py b/tests/featureWriters/kernFeatureWriter_test.py
index 9e11e68..fc2906f 100644
--- a/tests/featureWriters/kernFeatureWriter_test.py
+++ b/tests/featureWriters/kernFeatureWriter_test.py
@@ -178,6 +178,37 @@ class KernFeatureWriterTest(FeatureWriterTest):
             """
         )
 
+    def test_mark_to_base_only(self, FontClass):
+        font = FontClass()
+        for name in ("A", "B", "C"):
+            font.newGlyph(name)
+        font.newGlyph("acutecomb").unicode = 0x0301
+        font.kerning.update({("A", "acutecomb"): -55.0})
+
+        font.features.text = dedent(
+            """\
+            @Bases = [A B C];
+            @Marks = [acutecomb];
+            table GDEF {
+                GlyphClassDef @Bases, [], @Marks, ;
+            } GDEF;
+            """
+        )
+
+        # default is ignoreMarks=True
+        feaFile = self.writeFeatures(font)
+        assert str(feaFile) == dedent(
+            """
+            lookup kern_ltr_marks {
+                pos A acutecomb -55;
+            } kern_ltr_marks;
+
+            feature kern {
+                lookup kern_ltr_marks;
+            } kern;
+            """
+        )
+
     def test_mode(self, FontClass):
         ufo = FontClass()
         for name in ("one", "four", "six", "seven"):