diff --git a/Lib/fontmake/__main__.py b/Lib/fontmake/__main__.py
index 0ce9dc13..f45a5f64 100644
--- a/Lib/fontmake/__main__.py
+++ b/Lib/fontmake/__main__.py
@@ -539,7 +539,19 @@ def main(args=None):
"--no-auto-use-my-metrics",
dest="auto_use_my_metrics",
action="store_false",
- help="Don't automatically set USE_MY_METRICS glyf component flags (0x0200).",
+ default=None,
+ )
+ contourGroup.add_argument(
+ "--auto-use-my-metrics",
+ dest="auto_use_my_metrics",
+ action="store_true",
+ default=None,
+ help=(
+ "Automatically set (or not) USE_MY_METRICS glyf component flags (0x0200). "
+ "By default, fontmake only enables this for static fonts, though it can "
+ "also be enabled for variable fonts. This is not needed unless the font "
+ "is going to have hinted horizontal glyph metrics."
+ ),
)
contourGroup.add_argument(
"--drop-implied-oncurves",
@@ -605,8 +617,7 @@ def main(args=None):
"--production-names",
dest="use_production_names",
action="store_true",
- help="Rename glyphs with production names if available otherwise use "
- "uninames.",
+ help="Rename glyphs with production names if available otherwise use uninames.",
)
glyphnamesGroup.add_argument(
"--no-production-names", dest="use_production_names", action="store_false"
@@ -743,6 +754,9 @@ def main(args=None):
)
args.pop("ufo_structure", None) # unused for UFO output
args.pop("indent_json", None)
+ # keep the old default for statics, where it doesn't harm
+ if args["auto_use_my_metrics"] is None:
+ args["auto_use_my_metrics"] = True
project.run_from_ufos(
inputs.ufo_paths, is_instance=args.pop("masters_as_instances"), **args
)
diff --git a/Lib/fontmake/font_project.py b/Lib/fontmake/font_project.py
index 606839b8..ee88f682 100644
--- a/Lib/fontmake/font_project.py
+++ b/Lib/fontmake/font_project.py
@@ -332,7 +332,7 @@ def _build_interpolatable_masters(
fea_include_dir=None,
flatten_components=False,
filters=None,
- auto_use_my_metrics=True,
+ auto_use_my_metrics=False,
**kwargs,
):
if ttf:
@@ -395,7 +395,7 @@ def build_variable_fonts(
fea_include_dir=None,
flatten_components=False,
filters=None,
- auto_use_my_metrics=True,
+ auto_use_my_metrics=False,
drop_implied_oncurves=False,
variable_features=True,
**kwargs,
@@ -1098,6 +1098,7 @@ def run_from_designspace(
filters=None,
expand_features_to_instances=False,
check_compatibility=None,
+ auto_use_my_metrics=None,
**kwargs,
):
"""Run toolchain from a DesignSpace document to produce either static
@@ -1194,6 +1195,9 @@ def run_from_designspace(
try:
if static_outputs:
+ # keep setting the USE_MY_METRICS flag for the static outputs only
+ if auto_use_my_metrics is None:
+ auto_use_my_metrics = True
self._run_from_designspace_static(
designspace,
outputs=static_outputs,
@@ -1204,9 +1208,19 @@ def run_from_designspace(
feature_writers=feature_writers,
expand_features_to_instances=expand_features_to_instances,
filters=filters,
+ auto_use_my_metrics=auto_use_my_metrics,
**kwargs,
)
if interp_outputs:
+ # for interpolatable outputs, prefer not to set the flag automatically
+ # and let the user decide. For VFs in particular this is either useless
+ # (if the VF isn't going to be hinted) or wrong (if the composite and
+ # component metrics are not the same throughout the variation space,
+ # leading to potential mismatch between the metrics computed from HVAR
+ # vs glyf+gvar phantom points, depending on whether the flag is honored
+ # by the renderer).
+ if auto_use_my_metrics is None:
+ auto_use_my_metrics = False
self._run_from_designspace_interpolatable(
designspace,
outputs=interp_outputs,
@@ -1214,6 +1228,7 @@ def run_from_designspace(
feature_writers=feature_writers,
filters=filters,
variable_features=variable_features,
+ auto_use_my_metrics=auto_use_my_metrics,
**kwargs,
)
except FontmakeError as e:
diff --git a/tests/data/AutoUseMyMetrics/WghtVarComposite-Bold.ufo/fontinfo.plist b/tests/data/AutoUseMyMetrics/WghtVarComposite-Bold.ufo/fontinfo.plist
new file mode 100644
index 00000000..6109b22a
--- /dev/null
+++ b/tests/data/AutoUseMyMetrics/WghtVarComposite-Bold.ufo/fontinfo.plist
@@ -0,0 +1,28 @@
+
+
+
+
+ ascender
+ 800
+ capHeight
+ 700
+ descender
+ -200
+ familyName
+ WghtVar Composite
+ styleMapFamilyName
+ WghtVar Composite
+ styleMapStyleName
+ bold
+ styleName
+ Bold
+ unitsPerEm
+ 1000
+ versionMajor
+ 42
+ versionMinor
+ 42
+ xHeight
+ 500
+
+
diff --git a/tests/data/AutoUseMyMetrics/WghtVarComposite-Bold.ufo/glyphs/contents.plist b/tests/data/AutoUseMyMetrics/WghtVarComposite-Bold.ufo/glyphs/contents.plist
new file mode 100644
index 00000000..4d791006
--- /dev/null
+++ b/tests/data/AutoUseMyMetrics/WghtVarComposite-Bold.ufo/glyphs/contents.plist
@@ -0,0 +1,10 @@
+
+
+
+
+ equal
+ equal.glif
+ hyphen
+ hyphen.glif
+
+
diff --git a/tests/data/AutoUseMyMetrics/WghtVarComposite-Bold.ufo/glyphs/equal.glif b/tests/data/AutoUseMyMetrics/WghtVarComposite-Bold.ufo/glyphs/equal.glif
new file mode 100644
index 00000000..c9236297
--- /dev/null
+++ b/tests/data/AutoUseMyMetrics/WghtVarComposite-Bold.ufo/glyphs/equal.glif
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/tests/data/AutoUseMyMetrics/WghtVarComposite-Bold.ufo/glyphs/hyphen.glif b/tests/data/AutoUseMyMetrics/WghtVarComposite-Bold.ufo/glyphs/hyphen.glif
new file mode 100644
index 00000000..4bc2c734
--- /dev/null
+++ b/tests/data/AutoUseMyMetrics/WghtVarComposite-Bold.ufo/glyphs/hyphen.glif
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/data/AutoUseMyMetrics/WghtVarComposite-Bold.ufo/layercontents.plist b/tests/data/AutoUseMyMetrics/WghtVarComposite-Bold.ufo/layercontents.plist
new file mode 100644
index 00000000..b9c1a4f2
--- /dev/null
+++ b/tests/data/AutoUseMyMetrics/WghtVarComposite-Bold.ufo/layercontents.plist
@@ -0,0 +1,10 @@
+
+
+
+
+
+ public.default
+ glyphs
+
+
+
diff --git a/tests/data/AutoUseMyMetrics/WghtVarComposite-Bold.ufo/lib.plist b/tests/data/AutoUseMyMetrics/WghtVarComposite-Bold.ufo/lib.plist
new file mode 100644
index 00000000..33362f3d
--- /dev/null
+++ b/tests/data/AutoUseMyMetrics/WghtVarComposite-Bold.ufo/lib.plist
@@ -0,0 +1,11 @@
+
+
+
+
+ public.glyphOrder
+
+ hyphen
+ equal
+
+
+
diff --git a/tests/data/AutoUseMyMetrics/WghtVarComposite-Bold.ufo/metainfo.plist b/tests/data/AutoUseMyMetrics/WghtVarComposite-Bold.ufo/metainfo.plist
new file mode 100644
index 00000000..7b8b34ac
--- /dev/null
+++ b/tests/data/AutoUseMyMetrics/WghtVarComposite-Bold.ufo/metainfo.plist
@@ -0,0 +1,10 @@
+
+
+
+
+ creator
+ com.github.fonttools.ufoLib
+ formatVersion
+ 3
+
+
diff --git a/tests/data/AutoUseMyMetrics/WghtVarComposite-Regular.ufo/fontinfo.plist b/tests/data/AutoUseMyMetrics/WghtVarComposite-Regular.ufo/fontinfo.plist
new file mode 100644
index 00000000..5a5b8469
--- /dev/null
+++ b/tests/data/AutoUseMyMetrics/WghtVarComposite-Regular.ufo/fontinfo.plist
@@ -0,0 +1,28 @@
+
+
+
+
+ ascender
+ 737
+ capHeight
+ 702
+ descender
+ -42
+ familyName
+ WghtVar Composite
+ styleMapFamilyName
+ WghtVar Composite
+ styleMapStyleName
+ regular
+ styleName
+ Regular
+ unitsPerEm
+ 1000
+ versionMajor
+ 42
+ versionMinor
+ 42
+ xHeight
+ 501
+
+
diff --git a/tests/data/AutoUseMyMetrics/WghtVarComposite-Regular.ufo/glyphs/contents.plist b/tests/data/AutoUseMyMetrics/WghtVarComposite-Regular.ufo/glyphs/contents.plist
new file mode 100644
index 00000000..4d791006
--- /dev/null
+++ b/tests/data/AutoUseMyMetrics/WghtVarComposite-Regular.ufo/glyphs/contents.plist
@@ -0,0 +1,10 @@
+
+
+
+
+ equal
+ equal.glif
+ hyphen
+ hyphen.glif
+
+
diff --git a/tests/data/AutoUseMyMetrics/WghtVarComposite-Regular.ufo/glyphs/equal.glif b/tests/data/AutoUseMyMetrics/WghtVarComposite-Regular.ufo/glyphs/equal.glif
new file mode 100644
index 00000000..ef8f9741
--- /dev/null
+++ b/tests/data/AutoUseMyMetrics/WghtVarComposite-Regular.ufo/glyphs/equal.glif
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/tests/data/AutoUseMyMetrics/WghtVarComposite-Regular.ufo/glyphs/hyphen.glif b/tests/data/AutoUseMyMetrics/WghtVarComposite-Regular.ufo/glyphs/hyphen.glif
new file mode 100644
index 00000000..78fe1378
--- /dev/null
+++ b/tests/data/AutoUseMyMetrics/WghtVarComposite-Regular.ufo/glyphs/hyphen.glif
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/data/AutoUseMyMetrics/WghtVarComposite-Regular.ufo/layercontents.plist b/tests/data/AutoUseMyMetrics/WghtVarComposite-Regular.ufo/layercontents.plist
new file mode 100644
index 00000000..b9c1a4f2
--- /dev/null
+++ b/tests/data/AutoUseMyMetrics/WghtVarComposite-Regular.ufo/layercontents.plist
@@ -0,0 +1,10 @@
+
+
+
+
+
+ public.default
+ glyphs
+
+
+
diff --git a/tests/data/AutoUseMyMetrics/WghtVarComposite-Regular.ufo/lib.plist b/tests/data/AutoUseMyMetrics/WghtVarComposite-Regular.ufo/lib.plist
new file mode 100644
index 00000000..33362f3d
--- /dev/null
+++ b/tests/data/AutoUseMyMetrics/WghtVarComposite-Regular.ufo/lib.plist
@@ -0,0 +1,11 @@
+
+
+
+
+ public.glyphOrder
+
+ hyphen
+ equal
+
+
+
diff --git a/tests/data/AutoUseMyMetrics/WghtVarComposite-Regular.ufo/metainfo.plist b/tests/data/AutoUseMyMetrics/WghtVarComposite-Regular.ufo/metainfo.plist
new file mode 100644
index 00000000..7b8b34ac
--- /dev/null
+++ b/tests/data/AutoUseMyMetrics/WghtVarComposite-Regular.ufo/metainfo.plist
@@ -0,0 +1,10 @@
+
+
+
+
+ creator
+ com.github.fonttools.ufoLib
+ formatVersion
+ 3
+
+
diff --git a/tests/data/AutoUseMyMetrics/WghtVarComposite.designspace b/tests/data/AutoUseMyMetrics/WghtVarComposite.designspace
new file mode 100644
index 00000000..e306b9f5
--- /dev/null
+++ b/tests/data/AutoUseMyMetrics/WghtVarComposite.designspace
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/data/AutoUseMyMetrics/WghtVarComposite.glyphs b/tests/data/AutoUseMyMetrics/WghtVarComposite.glyphs
new file mode 100644
index 00000000..d69e2531
--- /dev/null
+++ b/tests/data/AutoUseMyMetrics/WghtVarComposite.glyphs
@@ -0,0 +1,183 @@
+{
+.appVersion = "3419";
+.formatVersion = 3;
+DisplayStrings = (
+"="
+);
+axes = (
+{
+name = Weight;
+tag = wght;
+}
+);
+date = "2025-08-27 10:48:24 +0000";
+familyName = "WghtVar Composite";
+fontMaster = (
+{
+axesValues = (
+400
+);
+id = m01;
+metricValues = (
+{
+over = 16;
+pos = 737;
+},
+{
+over = -16;
+},
+{
+over = -16;
+pos = -42;
+},
+{
+pos = 702;
+},
+{
+pos = 501;
+}
+);
+name = Regular;
+},
+{
+axesValues = (
+700
+);
+iconName = Bold;
+id = "E09E0C54-128D-4FEA-B209-1B70BEFE300B";
+metricValues = (
+{
+pos = 800;
+},
+{
+},
+{
+pos = -200;
+},
+{
+pos = 700;
+},
+{
+pos = 500;
+}
+);
+name = Bold;
+}
+);
+glyphs = (
+{
+glyphname = hyphen;
+layers = (
+{
+layerId = m01;
+shapes = (
+{
+closed = 1;
+nodes = (
+(131,250,l,{
+name = hr00;
+}),
+(470,250,l),
+(470,330,l),
+(131,330,l)
+);
+}
+);
+width = 600;
+},
+{
+layerId = "E09E0C54-128D-4FEA-B209-1B70BEFE300B";
+shapes = (
+{
+closed = 1;
+nodes = (
+(92,224,l),
+(508,224,l),
+(508,356,l),
+(92,356,l)
+);
+}
+);
+width = 600;
+}
+);
+unicode = 45;
+},
+{
+glyphname = equal;
+layers = (
+{
+layerId = m01;
+shapes = (
+{
+pos = (0,50);
+ref = hyphen;
+},
+{
+pos = (0,-50);
+ref = hyphen;
+}
+);
+width = 600;
+},
+{
+layerId = "E09E0C54-128D-4FEA-B209-1B70BEFE300B";
+shapes = (
+{
+pos = (0,70);
+ref = hyphen;
+},
+{
+pos = (0,-100);
+ref = hyphen;
+}
+);
+width = 600;
+}
+);
+unicode = 61;
+}
+);
+instances = (
+{
+axesValues = (
+400
+);
+instanceInterpolations = {
+m01 = 1;
+};
+name = Regular;
+},
+{
+axesValues = (
+700
+);
+instanceInterpolations = {
+"E09E0C54-128D-4FEA-B209-1B70BEFE300B" = 1;
+};
+isBold = 1;
+name = Bold;
+weightClass = 700;
+}
+);
+metrics = (
+{
+type = ascender;
+},
+{
+type = baseline;
+},
+{
+type = descender;
+},
+{
+type = "cap height";
+},
+{
+type = "x-height";
+}
+);
+unitsPerEm = 1000;
+versionMajor = 42;
+versionMinor = 42;
+}
diff --git a/tests/test_main.py b/tests/test_main.py
index 22d53333..fa874d79 100644
--- a/tests/test_main.py
+++ b/tests/test_main.py
@@ -11,6 +11,7 @@
import pytest
import ufoLib2
from fontTools.misc.testTools import getXML
+from fontTools.ttLib.tables._g_l_y_f import USE_MY_METRICS
from ufo2ft.util import zip_strict
import fontmake.__main__
@@ -1478,3 +1479,217 @@ def assert_charstring_regions(charstring, expected_regions):
{"wght": (0.8, 1.0, 1.0)},
],
)
+
+
+def has_use_my_metrics_flag(font_file, composite_glyph_name) -> bool:
+ font = fontTools.ttLib.TTFont(font_file)
+ glyf = font["glyf"]
+
+ glyph = glyf[composite_glyph_name]
+ assert glyph.isComposite()
+ assert len(glyph.components) > 0
+ return any(comp.flags & USE_MY_METRICS != 0 for comp in glyph.components)
+
+
+@pytest.mark.parametrize(
+ "source_type, source_name",
+ [
+ pytest.param("-g", "WghtVarComposite.glyphs", id="glyphs"),
+ pytest.param("-m", "WghtVarComposite.designspace", id="designspace"),
+ ],
+)
+def test_auto_use_my_metrics_disabled_by_default_for_variable(
+ data_dir, tmp_path, source_type, source_name
+):
+ fontmake.__main__.main(
+ [
+ source_type,
+ str(data_dir / "AutoUseMyMetrics" / source_name),
+ "-o",
+ "variable",
+ "--output-path",
+ str(tmp_path / "WghtVarComposite-VF.ttf"),
+ ]
+ )
+
+ assert not has_use_my_metrics_flag(tmp_path / "WghtVarComposite-VF.ttf", "equal")
+
+
+@pytest.mark.parametrize("auto_use_my_metrics", [True, False])
+@pytest.mark.parametrize(
+ "source_type, source_name",
+ [
+ pytest.param("-g", "WghtVarComposite.glyphs", id="glyphs"),
+ pytest.param("-m", "WghtVarComposite.designspace", id="designspace"),
+ ],
+)
+def test_auto_use_my_metrics_flag_for_variable(
+ data_dir, tmp_path, source_type, source_name, auto_use_my_metrics
+):
+ fontmake.__main__.main(
+ [
+ source_type,
+ str(data_dir / "AutoUseMyMetrics" / source_name),
+ "-o",
+ "variable",
+ f"--{'no-' if not auto_use_my_metrics else ''}auto-use-my-metrics",
+ "--output-path",
+ str(tmp_path / "WghtVarComposite-VF.ttf"),
+ ]
+ )
+
+ assert (
+ has_use_my_metrics_flag(tmp_path / "WghtVarComposite-VF.ttf", "equal")
+ == auto_use_my_metrics
+ )
+
+
+@pytest.mark.parametrize(
+ "source_type, source_name",
+ [
+ pytest.param("-g", "WghtVarComposite.glyphs", id="glyphs"),
+ pytest.param("-m", "WghtVarComposite.designspace", id="designspace"),
+ ],
+)
+def test_auto_use_my_metrics_disabled_by_default_for_interpolatable_ttfs(
+ data_dir, tmp_path, source_type, source_name
+):
+ fontmake.__main__.main(
+ [
+ source_type,
+ str(data_dir / "AutoUseMyMetrics" / source_name),
+ "-o",
+ "ttf-interpolatable",
+ "--output-dir",
+ str(tmp_path),
+ ]
+ )
+
+ font_files = list(tmp_path.glob("*.ttf"))
+ assert len(list(font_files)) == 2
+ for font_file in font_files:
+ assert not has_use_my_metrics_flag(font_file, "equal")
+
+
+@pytest.mark.parametrize("auto_use_my_metrics", [True, False])
+@pytest.mark.parametrize(
+ "source_type, source_name",
+ [
+ pytest.param("-g", "WghtVarComposite.glyphs", id="glyphs"),
+ pytest.param("-m", "WghtVarComposite.designspace", id="designspace"),
+ ],
+)
+def test_auto_use_my_metrics_flag_for_interpolatable_ttfs(
+ data_dir, tmp_path, source_type, source_name, auto_use_my_metrics
+):
+ fontmake.__main__.main(
+ [
+ source_type,
+ str(data_dir / "AutoUseMyMetrics" / source_name),
+ "-o",
+ "ttf-interpolatable",
+ f"--{'no-' if not auto_use_my_metrics else ''}auto-use-my-metrics",
+ "--output-dir",
+ str(tmp_path),
+ ]
+ )
+
+ font_files = list(tmp_path.glob("*.ttf"))
+ assert len(list(font_files)) == 2
+ for font_file in font_files:
+ assert has_use_my_metrics_flag(font_file, "equal") == auto_use_my_metrics
+
+
+@pytest.mark.parametrize(
+ "source_type, source_name",
+ [
+ pytest.param("-g", "WghtVarComposite.glyphs", id="glyphs"),
+ pytest.param("-m", "WghtVarComposite.designspace", id="designspace"),
+ ],
+)
+def test_auto_use_my_metrics_enabled_by_default_for_interpolated_statics(
+ data_dir, tmp_path, source_type, source_name
+):
+ fontmake.__main__.main(
+ [
+ source_type,
+ str(data_dir / "AutoUseMyMetrics" / source_name),
+ "--interpolate",
+ "-o",
+ "ttf",
+ "--output-dir",
+ str(tmp_path),
+ ]
+ )
+
+ font_files = list(tmp_path.glob("*.ttf"))
+ assert len(list(font_files)) == 2
+ for font_file in font_files:
+ assert has_use_my_metrics_flag(font_file, "equal")
+
+
+@pytest.mark.parametrize("auto_use_my_metrics", [True, False])
+@pytest.mark.parametrize(
+ "source_type, source_name",
+ [
+ pytest.param("-g", "WghtVarComposite.glyphs", id="glyphs"),
+ pytest.param("-m", "WghtVarComposite.designspace", id="designspace"),
+ ],
+)
+def test_auto_use_my_metrics_flag_for_interpolated_statics(
+ data_dir, tmp_path, source_type, source_name, auto_use_my_metrics
+):
+ fontmake.__main__.main(
+ [
+ source_type,
+ str(data_dir / "AutoUseMyMetrics" / source_name),
+ "--interpolate",
+ "-o",
+ "ttf",
+ f"--{'no-' if not auto_use_my_metrics else ''}auto-use-my-metrics",
+ "--output-dir",
+ str(tmp_path),
+ ]
+ )
+
+ font_files = list(tmp_path.glob("*.ttf"))
+ assert len(list(font_files)) == 2
+ for font_file in font_files:
+ assert has_use_my_metrics_flag(font_file, "equal") == auto_use_my_metrics
+
+
+def test_auto_use_my_metrics_enabled_by_default_for_single_ufo(data_dir, tmp_path):
+ fontmake.__main__.main(
+ [
+ "-u",
+ str(data_dir / "AutoUseMyMetrics" / "WghtVarComposite-Regular.ufo"),
+ "-o",
+ "ttf",
+ "--output-path",
+ str(tmp_path / "WghtVarComposite-Regular.ttf"),
+ ]
+ )
+
+ assert has_use_my_metrics_flag(tmp_path / "WghtVarComposite-Regular.ttf", "equal")
+
+
+@pytest.mark.parametrize("auto_use_my_metrics", [True, False])
+def test_auto_use_my_metrics_flag_for_single_ufo(
+ data_dir, tmp_path, auto_use_my_metrics
+):
+ fontmake.__main__.main(
+ [
+ "-u",
+ str(data_dir / "AutoUseMyMetrics" / "WghtVarComposite-Regular.ufo"),
+ "-o",
+ "ttf",
+ f"--{'no-' if not auto_use_my_metrics else ''}auto-use-my-metrics",
+ "--output-path",
+ str(tmp_path / "WghtVarComposite-Regular.ttf"),
+ ]
+ )
+
+ assert (
+ has_use_my_metrics_flag(tmp_path / "WghtVarComposite-Regular.ttf", "equal")
+ == auto_use_my_metrics
+ )