Repository: googlefonts/ufo2ft
Pull request #821 (2024-02-27 13:43:03)

Fix variable GDEF building
This is an obscure one. If you're building a variable font and a glyph has its ligature carets at the same position across masters, the caret value will be collapsed (by `collapse_varscalar` inside of `getAnchor`) into an int, and the current sort function won't work. We need a sort function which can sort both variable and static scalars.

anthrotype: +1 for small test if not too much trouble, thanks

Patch:
diff --git a/Lib/ufo2ft/featureWriters/gdefFeatureWriter.py b/Lib/ufo2ft/featureWriters/gdefFeatureWriter.py
index fcd41f1..eda11bf 100644
--- a/Lib/ufo2ft/featureWriters/gdefFeatureWriter.py
+++ b/Lib/ufo2ft/featureWriters/gdefFeatureWriter.py
@@ -1,8 +1,15 @@
+from fontTools.feaLib.variableScalar import VariableScalar
 from fontTools.misc.fixedTools import otRound
 
 from ufo2ft.featureWriters import BaseFeatureWriter, ast
 
 
+def caretSortKey(caret):
+    if isinstance(caret, VariableScalar):
+        return list(caret.values.values())[0]
+    return caret
+
+
 class GdefFeatureWriter(BaseFeatureWriter):
     """Generates a GDEF table based on OpenType Category and glyph anchors.
 
@@ -67,9 +74,7 @@ class GdefFeatureWriter(BaseFeatureWriter):
 
             if glyphCarets:
                 if self.context.isVariable:
-                    carets[glyphName] = sorted(
-                        glyphCarets, key=lambda caret: list(caret.values.values())[0]
-                    )
+                    carets[glyphName] = sorted(glyphCarets, key=caretSortKey)
                 else:
                     carets[glyphName] = [otRound(c) for c in sorted(glyphCarets)]
 


Test patch:
diff --git a/tests/data/TestVarfea-Bold.ufo/glyphs/peh-ar.init.glif b/tests/data/TestVarfea-Bold.ufo/glyphs/peh-ar.init.glif
index a8e8750..ed2734b 100644
--- a/tests/data/TestVarfea-Bold.ufo/glyphs/peh-ar.init.glif
+++ b/tests/data/TestVarfea-Bold.ufo/glyphs/peh-ar.init.glif
@@ -2,6 +2,7 @@
 <glyph name="peh-ar.init" format="2">
   <advance width="600"/>
   <unicode hex="067E"/>
+  <anchor x="100" y="100" name="caret_1"/>
   <anchor x="73" y="89" name="exit"/>
   <outline>
     <contour>
diff --git a/tests/data/TestVarfea-Regular.ufo/glyphs/peh-ar.init.glif b/tests/data/TestVarfea-Regular.ufo/glyphs/peh-ar.init.glif
index 03c6ba3..25a15b4 100644
--- a/tests/data/TestVarfea-Regular.ufo/glyphs/peh-ar.init.glif
+++ b/tests/data/TestVarfea-Regular.ufo/glyphs/peh-ar.init.glif
@@ -2,6 +2,7 @@
 <glyph name="peh-ar.init" format="2">
   <advance width="600"/>
   <unicode hex="067E"/>
+  <anchor x="100" y="100" name="caret_1"/>
   <anchor x="161" y="54" name="exit"/>
   <outline>
     <contour>
diff --git a/tests/featureWriters/variableFeatureWriter_test.py b/tests/featureWriters/variableFeatureWriter_test.py
index 92092c6..b6be9c9 100644
--- a/tests/featureWriters/variableFeatureWriter_test.py
+++ b/tests/featureWriters/variableFeatureWriter_test.py
@@ -41,6 +41,10 @@ def test_variable_features(FontClass):
 
         } mark;
 
+        table GDEF {
+            LigatureCaretByPos peh-ar.init 100;
+        } GDEF;
+
         feature curs {
             lookup curs {
                 lookupflag RightToLeft IgnoreMarks;