Repository: googlefonts/ufo2ft
Pull request #817 (2024-02-06 17:04:08)

don't drop implied oncurves for interpolatable TTFs when building a VF
this should only be done at the end in the final VF, otherwise masters may end up with incompatible glyphs...


Patch:
diff --git a/Lib/ufo2ft/_compilers/interpolatableTTFCompiler.py b/Lib/ufo2ft/_compilers/interpolatableTTFCompiler.py
index a5d8b0f..4244a06 100644
--- a/Lib/ufo2ft/_compilers/interpolatableTTFCompiler.py
+++ b/Lib/ufo2ft/_compilers/interpolatableTTFCompiler.py
@@ -75,6 +75,9 @@ class InterpolatableTTFCompiler(BaseInterpolatableCompiler):
         # can compute impliable on-curve points from unrounded coordinates before
         # building the VF
         kwargs["roundCoordinates"] = False
+        # keep impliable oncurve points in the interpolatable master TTFs, they will
+        # be pruned at the end by varLib in the final VF.
+        kwargs["dropImpliedOnCurves"] = False
         outlineCompiler = self.outlineCompilerClass(ufo, glyphSet=glyphSet, **kwargs)
         return outlineCompiler.compile()
 


Test patch:
diff --git a/tests/data/OTestFont-Bold.ufo/fontinfo.plist b/tests/data/OTestFont-Bold.ufo/fontinfo.plist
new file mode 100644
index 0000000..9d4278b
--- /dev/null
+++ b/tests/data/OTestFont-Bold.ufo/fontinfo.plist
@@ -0,0 +1,30 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+  <dict>
+    <key>ascender</key>
+    <integer>800</integer>
+    <key>capHeight</key>
+    <integer>700</integer>
+    <key>descender</key>
+    <integer>-200</integer>
+    <key>familyName</key>
+    <string>O Test Font</string>
+    <key>italicAngle</key>
+    <integer>0</integer>
+    <key>styleMapFamilyName</key>
+    <string>O Test Font</string>
+    <key>styleMapStyleName</key>
+    <string>bold</string>
+    <key>styleName</key>
+    <string>Bold</string>
+    <key>unitsPerEm</key>
+    <integer>1000</integer>
+    <key>versionMajor</key>
+    <integer>1</integer>
+    <key>versionMinor</key>
+    <integer>0</integer>
+    <key>xHeight</key>
+    <integer>500</integer>
+  </dict>
+</plist>
diff --git a/tests/data/OTestFont-Bold.ufo/glyphs/contents.plist b/tests/data/OTestFont-Bold.ufo/glyphs/contents.plist
new file mode 100644
index 0000000..7d434ff
--- /dev/null
+++ b/tests/data/OTestFont-Bold.ufo/glyphs/contents.plist
@@ -0,0 +1,10 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+  <dict>
+    <key>o</key>
+    <string>o.glif</string>
+    <key>space</key>
+    <string>space.glif</string>
+  </dict>
+</plist>
diff --git a/tests/data/OTestFont-Bold.ufo/glyphs/o.glif b/tests/data/OTestFont-Bold.ufo/glyphs/o.glif
new file mode 100644
index 0000000..bbbd312
--- /dev/null
+++ b/tests/data/OTestFont-Bold.ufo/glyphs/o.glif
@@ -0,0 +1,35 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<glyph name="o" format="2">
+  <advance width="650"/>
+  <unicode hex="006F"/>
+  <outline>
+    <contour>
+      <point x="345" y="-15" type="curve" smooth="yes"/>
+      <point x="510" y="-15"/>
+      <point x="572" y="110"/>
+      <point x="572" y="265" type="curve" smooth="yes"/>
+      <point x="572" y="420"/>
+      <point x="510" y="545"/>
+      <point x="345" y="545" type="curve" smooth="yes"/>
+      <point x="150" y="545"/>
+      <point x="98" y="420"/>
+      <point x="98" y="265" type="curve" smooth="yes"/>
+      <point x="98" y="110"/>
+      <point x="150" y="-15"/>
+    </contour>
+    <contour>
+      <point x="334" y="107" type="curve" smooth="yes"/>
+      <point x="237" y="107"/>
+      <point x="211" y="187"/>
+      <point x="211" y="262" type="curve" smooth="yes"/>
+      <point x="211" y="336"/>
+      <point x="237" y="426"/>
+      <point x="334" y="426" type="curve" smooth="yes"/>
+      <point x="461" y="426"/>
+      <point x="467" y="336"/>
+      <point x="467" y="262" type="curve" smooth="yes"/>
+      <point x="467" y="187"/>
+      <point x="461" y="107"/>
+    </contour>
+  </outline>
+</glyph>
diff --git a/tests/data/OTestFont-Bold.ufo/glyphs/space.glif b/tests/data/OTestFont-Bold.ufo/glyphs/space.glif
new file mode 100644
index 0000000..9833481
--- /dev/null
+++ b/tests/data/OTestFont-Bold.ufo/glyphs/space.glif
@@ -0,0 +1,7 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<glyph name="space" format="2">
+  <advance width="600"/>
+  <unicode hex="0020"/>
+  <outline>
+  </outline>
+</glyph>
diff --git a/tests/data/OTestFont-Bold.ufo/layercontents.plist b/tests/data/OTestFont-Bold.ufo/layercontents.plist
new file mode 100644
index 0000000..b9c1a4f
--- /dev/null
+++ b/tests/data/OTestFont-Bold.ufo/layercontents.plist
@@ -0,0 +1,10 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+  <array>
+    <array>
+      <string>public.default</string>
+      <string>glyphs</string>
+    </array>
+  </array>
+</plist>
diff --git a/tests/data/OTestFont-Bold.ufo/metainfo.plist b/tests/data/OTestFont-Bold.ufo/metainfo.plist
new file mode 100644
index 0000000..7b8b34a
--- /dev/null
+++ b/tests/data/OTestFont-Bold.ufo/metainfo.plist
@@ -0,0 +1,10 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+  <dict>
+    <key>creator</key>
+    <string>com.github.fonttools.ufoLib</string>
+    <key>formatVersion</key>
+    <integer>3</integer>
+  </dict>
+</plist>
diff --git a/tests/data/OTestFont-Regular.ufo/fontinfo.plist b/tests/data/OTestFont-Regular.ufo/fontinfo.plist
new file mode 100644
index 0000000..c8d3bba
--- /dev/null
+++ b/tests/data/OTestFont-Regular.ufo/fontinfo.plist
@@ -0,0 +1,30 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+  <dict>
+    <key>ascender</key>
+    <integer>800</integer>
+    <key>capHeight</key>
+    <integer>700</integer>
+    <key>descender</key>
+    <integer>-200</integer>
+    <key>familyName</key>
+    <string>O Test Font</string>
+    <key>italicAngle</key>
+    <integer>0</integer>
+    <key>styleMapFamilyName</key>
+    <string>O Test Font</string>
+    <key>styleMapStyleName</key>
+    <string>regular</string>
+    <key>styleName</key>
+    <string>Regular</string>
+    <key>unitsPerEm</key>
+    <integer>1000</integer>
+    <key>versionMajor</key>
+    <integer>1</integer>
+    <key>versionMinor</key>
+    <integer>0</integer>
+    <key>xHeight</key>
+    <integer>500</integer>
+  </dict>
+</plist>
diff --git a/tests/data/OTestFont-Regular.ufo/glyphs/contents.plist b/tests/data/OTestFont-Regular.ufo/glyphs/contents.plist
new file mode 100644
index 0000000..7d434ff
--- /dev/null
+++ b/tests/data/OTestFont-Regular.ufo/glyphs/contents.plist
@@ -0,0 +1,10 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+  <dict>
+    <key>o</key>
+    <string>o.glif</string>
+    <key>space</key>
+    <string>space.glif</string>
+  </dict>
+</plist>
diff --git a/tests/data/OTestFont-Regular.ufo/glyphs/o.glif b/tests/data/OTestFont-Regular.ufo/glyphs/o.glif
new file mode 100644
index 0000000..09a2332
--- /dev/null
+++ b/tests/data/OTestFont-Regular.ufo/glyphs/o.glif
@@ -0,0 +1,35 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<glyph name="o" format="2">
+  <advance width="600"/>
+  <unicode hex="006F"/>
+  <outline>
+    <contour>
+      <point x="305" y="-15" type="curve" smooth="yes"/>
+      <point x="460" y="-15"/>
+      <point x="522" y="110"/>
+      <point x="522" y="265" type="curve" smooth="yes"/>
+      <point x="522" y="420"/>
+      <point x="460" y="545"/>
+      <point x="305" y="545" type="curve" smooth="yes"/>
+      <point x="120" y="545"/>
+      <point x="68" y="420"/>
+      <point x="68" y="265" type="curve" smooth="yes"/>
+      <point x="68" y="110"/>
+      <point x="120" y="-15"/>
+    </contour>
+    <contour>
+      <point x="294" y="54" type="curve" smooth="yes"/>
+      <point x="207" y="54"/>
+      <point x="181" y="157"/>
+      <point x="181" y="262" type="curve" smooth="yes"/>
+      <point x="181" y="366"/>
+      <point x="207" y="461"/>
+      <point x="294" y="461" type="curve" smooth="yes"/>
+      <point x="411" y="461"/>
+      <point x="417" y="366"/>
+      <point x="417" y="262" type="curve" smooth="yes"/>
+      <point x="417" y="157"/>
+      <point x="411" y="54"/>
+    </contour>
+  </outline>
+</glyph>
diff --git a/tests/data/OTestFont-Regular.ufo/glyphs/space.glif b/tests/data/OTestFont-Regular.ufo/glyphs/space.glif
new file mode 100644
index 0000000..c05cd73
--- /dev/null
+++ b/tests/data/OTestFont-Regular.ufo/glyphs/space.glif
@@ -0,0 +1,7 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<glyph name="space" format="2">
+  <advance width="200"/>
+  <unicode hex="0020"/>
+  <outline>
+  </outline>
+</glyph>
diff --git a/tests/data/OTestFont-Regular.ufo/layercontents.plist b/tests/data/OTestFont-Regular.ufo/layercontents.plist
new file mode 100644
index 0000000..b9c1a4f
--- /dev/null
+++ b/tests/data/OTestFont-Regular.ufo/layercontents.plist
@@ -0,0 +1,10 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+  <array>
+    <array>
+      <string>public.default</string>
+      <string>glyphs</string>
+    </array>
+  </array>
+</plist>
diff --git a/tests/data/OTestFont-Regular.ufo/metainfo.plist b/tests/data/OTestFont-Regular.ufo/metainfo.plist
new file mode 100644
index 0000000..7b8b34a
--- /dev/null
+++ b/tests/data/OTestFont-Regular.ufo/metainfo.plist
@@ -0,0 +1,10 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+  <dict>
+    <key>creator</key>
+    <string>com.github.fonttools.ufoLib</string>
+    <key>formatVersion</key>
+    <integer>3</integer>
+  </dict>
+</plist>
diff --git a/tests/data/OTestFont.designspace b/tests/data/OTestFont.designspace
new file mode 100644
index 0000000..b3d554f
--- /dev/null
+++ b/tests/data/OTestFont.designspace
@@ -0,0 +1,18 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<designspace format="5.0">
+  <axes>
+    <axis tag="wght" name="Weight" minimum="400" maximum="700" default="400"/>
+  </axes>
+  <sources>
+    <source filename="OTestFont-Regular.ufo" name="O Test Font Regular">
+      <location>
+        <dimension name="Weight" xvalue="400"/>
+      </location>
+    </source>
+    <source filename="OTestFont-Bold.ufo" name="O Test Font Bold">
+      <location>
+        <dimension name="Weight" xvalue="700"/>
+      </location>
+    </source>
+  </sources>
+</designspace>
diff --git a/tests/integration_test.py b/tests/integration_test.py
index a3798d5..41bef31 100644
--- a/tests/integration_test.py
+++ b/tests/integration_test.py
@@ -592,6 +592,24 @@ class IntegrationTest:
         expectTTX(fonts["MyFontVF1"], "TestVarFont-MyFontVF1.ttx", ["head", "name"])
         expectTTX(fonts["MyFontVF2"], "TestVarFont-MyFontVF2.ttx", ["head", "name"])
 
+    def test_compile_variable_ttf_drop_implied_oncurves(self, FontClass, caplog):
+        # https://github.com/googlefonts/ufo2ft/pull/817
+        designspace = DesignSpaceDocument.fromfile(getpath("OTestFont.designspace"))
+        designspace.loadSourceFonts(FontClass)
+
+        # dropImpliedOnCurves is False by default
+        vf1 = compileVariableTTF(designspace)
+
+        with caplog.at_level(logging.INFO, logger="fontTools.varLib"):
+            vf2 = compileVariableTTF(designspace, dropImpliedOnCurves=True)
+
+        assert "Failed to drop implied oncurves" not in caplog.text
+        assert "Dropped 4 on-curve points" in caplog.text
+
+        o1 = vf1["glyf"]["o"].coordinates
+        o2 = vf2["glyf"]["o"].coordinates
+        assert len(o1) == len(o2) + 4
+
 
 if __name__ == "__main__":
     sys.exit(pytest.main(sys.argv))