diff --git a/Lib/fontbakery/checks/opentype_fvar_regular_coords_correct.py b/Lib/fontbakery/checks/opentype_fvar_regular_coords_correct.py index fc9c78ba64..73f008ccd0 100644 --- a/Lib/fontbakery/checks/opentype_fvar_regular_coords_correct.py +++ b/Lib/fontbakery/checks/opentype_fvar_regular_coords_correct.py @@ -1,161 +1,60 @@ -from fontbakery.prelude import check, Message, FAIL, PASS, WARN +from fontbakery.prelude import check, Message, FAIL, WARN @check( - id="opentype/varfont/regular_wght_coord", + id="opentype/fvar/regular_coords_correct", rationale=""" - According to the OpenType spec's - registered design-variation tag 'wght' available at - https://docs.microsoft.com/en-gb/typography/opentype/spec/dvaraxistag_wght - - If a variable font has a 'wght' (Weight) axis, then the coordinate of - its 'Regular' instance is required to be 400. - """, - conditions=["is_variable_font", "has_wght_axis"], - proposal="https://github.com/fonttools/fontbakery/issues/1707", -) -def check_varfont_regular_wght_coord(ttFont, regular_wght_coord): - """The variable font 'wght' (Weight) axis coordinate must be 400 on the - 'Regular' instance.""" - - if regular_wght_coord is None: - yield FAIL, Message("no-regular-instance", '"Regular" instance not present.') - elif regular_wght_coord == 400: - yield PASS, "Regular:wght is 400." - else: - yield FAIL, Message( - "wght-not-400", - f'The "wght" axis coordinate of' - f' the "Regular" instance must be 400.' - f" Got {regular_wght_coord} instead.", - ) - - -@check( - id="opentype/varfont/regular_wdth_coord", - rationale=""" - According to the OpenType spec's - registered design-variation tag 'wdth' available at - https://docs.microsoft.com/en-gb/typography/opentype/spec/dvaraxistag_wdth - - If a variable font has a 'wdth' (Width) axis, then the coordinate of - its 'Regular' instance is required to be 100. - """, - conditions=["is_variable_font", "has_wdth_axis"], - proposal="https://github.com/fonttools/fontbakery/issues/1707", -) -def check_varfont_regular_wdth_coord(ttFont, regular_wdth_coord): - """ - The variable font 'wdth' (Width) axis coordinate must be 100 on the 'Regular' - instance. - """ - - if regular_wdth_coord is None: - yield FAIL, Message("no-regular-instance", '"Regular" instance not present.') - elif regular_wdth_coord == 100: - yield PASS, "Regular:wdth is 100." - else: - yield FAIL, Message( - "wdth-not-100", - f'The "wdth" axis coordinate of' - f' the "Regular" instance must be 100.' - f" Got {regular_wdth_coord} as a default value instead.", - ) - - -@check( - id="opentype/varfont/regular_slnt_coord", - rationale=""" - According to the OpenType spec's - registered design-variation tag 'slnt' available at - https://docs.microsoft.com/en-gb/typography/opentype/spec/dvaraxistag_slnt - - If a variable font has a 'slnt' (Slant) axis, then the coordinate of - its 'Regular' instance is required to be zero. + According to the Open-Type spec's registered design-variation tags,instances in a variable font should have certain prescribed values. + If a variable font has a 'wght' (Weight) axis, the valid coordinate range is 1-1000. + If a variable font has a 'wdth' (Width) axis, the valid numeric range is strictly greater than zero. + If a variable font has a 'slnt' (Slant) axis, then the coordinate of its 'Regular' instance is required to be 0. + If a variable font has a 'ital' (Slant) axis, then the coordinate of its 'Regular' instance is required to be 0. """, - conditions=["is_variable_font", "has_slnt_axis"], - proposal="https://github.com/fonttools/fontbakery/issues/1707", + conditions=["is_variable_font"], + proposal=[ + "https://github.com/fonttools/fontbakery/issues/1707", + "https://github.com/fonttools/fontbakery/issues/2572", + ], ) -def check_varfont_regular_slnt_coord(ttFont, regular_slnt_coord): - """ - The variable font 'slnt' (Slant) axis coordinate must be zero on the 'Regular' - instance. - """ - - if regular_slnt_coord is None: - yield FAIL, Message("no-regular-instance", '"Regular" instance not present.') - elif regular_slnt_coord == 0: - yield PASS, "Regular:slnt is zero." - else: - yield FAIL, Message( - "slnt-not-0", - f'The "slnt" axis coordinate of' - f' the "Regular" instance must be zero.' - f" Got {regular_slnt_coord} as a default value instead.", - ) - - -@check( - id="opentype/varfont/regular_ital_coord", - rationale=""" - According to the OpenType spec's - registered design-variation tag 'ital' available at - https://docs.microsoft.com/en-gb/typography/opentype/spec/dvaraxistag_ital - - If a variable font has a 'ital' (Italic) axis, then the coordinate of - its 'Regular' instance is required to be zero. - """, - conditions=["is_variable_font", "has_ital_axis"], - proposal="https://github.com/fonttools/fontbakery/issues/1707", -) -def check_varfont_regular_ital_coord(ttFont, regular_ital_coord): - """ - The variable font 'ital' (Italic) axis coordinate must be zero on the 'Regular' - instance. - """ - - if regular_ital_coord is None: - yield FAIL, Message("no-regular-instance", '"Regular" instance not present.') - elif regular_ital_coord == 0: - yield PASS, "Regular:ital is zero." - else: - yield FAIL, Message( - "ital-not-0", - f'The "ital" axis coordinate of' - f' the "Regular" instance must be zero.' - f" Got {regular_ital_coord} as a default value instead.", - ) - - -@check( - id="opentype/varfont/regular_opsz_coord", - rationale=""" - According to the OpenType spec's - registered design-variation tag 'opsz' available at - https://docs.microsoft.com/en-gb/typography/opentype/spec/dvaraxistag_opsz - - If a variable font has an 'opsz' (Optical Size) axis, then - the coordinate of its 'Regular' instance is recommended to be - a value in the range 10 to 16. - """, - conditions=["is_variable_font", "has_opsz_axis"], - proposal="https://github.com/fonttools/fontbakery/issues/1707", -) -def check_varfont_regular_opsz_coord(ttFont, regular_opsz_coord): - """ - The variable font 'opsz' (Optical Size) axis coordinate should be between 10 and 16 - on the 'Regular' instance. - """ - - if regular_opsz_coord is None: +def check_fvar_regular_coords_correct( + ttFont, + regular_wght_coord, + regular_wdth_coord, + regular_slnt_coord, + regular_ital_coord, + regular_opsz_coord, +): + """Axes and named instances fall within correct ranges?""" + + REGULAR_COORDINATE_EXPECTATIONS = [ + ("wght", 400, regular_wght_coord), + ("wdth", 100, regular_wdth_coord), + ("slnt", 0, regular_slnt_coord), + ("ital", 0, regular_ital_coord), + ] + + if ( + regular_wght_coord is None + and regular_wdth_coord is None + and regular_slnt_coord is None + and regular_ital_coord is None + and regular_opsz_coord is None + ): yield FAIL, Message("no-regular-instance", '"Regular" instance not present.') - elif regular_opsz_coord >= 10 and regular_opsz_coord <= 16: - yield PASS, f"Regular:opsz coordinate ({regular_opsz_coord}) looks good." - else: + return + + for axis, expected, actual in REGULAR_COORDINATE_EXPECTATIONS: + if actual is not None and actual != expected: + yield FAIL, Message( + f"{axis}-not-{expected}", + f"Regular instance has {axis} coordinate of {actual}," + f" expected {expected}", + ) + + actual = regular_opsz_coord + if actual and not (10 <= actual <= 16): yield WARN, Message( - "opsz-out-of-range", - f'The "opsz" (Optical Size) coordinate' - f' on the "Regular" instance is recommended' - f" to be a value in the range 10 to 16." - f" Got {regular_opsz_coord} instead.", + "opsz", + f"Regular instance has opsz coordinate of {actual}," + f" expected between 10 and 16", ) diff --git a/Lib/fontbakery/profiles/adobefonts.py b/Lib/fontbakery/profiles/adobefonts.py index 46cba7b480..e9b3e1b1a0 100644 --- a/Lib/fontbakery/profiles/adobefonts.py +++ b/Lib/fontbakery/profiles/adobefonts.py @@ -176,35 +176,7 @@ "reason": "Adobe strongly recommends, but does not require having a Bold instance, and that instance should have coordinate 700 on the 'wght' axis.", }, ], - "opentype/varfont/regular_ital_coord": [ - { - "code": "no-regular-instance", - "status": "WARN", - "reason": "Adobe strongly recommends, but does not require having a Regular instance.", - }, - ], - "opentype/varfont/regular_opsz_coord": [ - { - "code": "no-regular-instance", - "status": "WARN", - "reason": "Adobe strongly recommends, but does not require having a Regular instance.", - }, - ], - "opentype/varfont/regular_slnt_coord": [ - { - "code": "no-regular-instance", - "status": "WARN", - "reason": "Adobe strongly recommends, but does not require having a Regular instance.", - }, - ], - "opentype/varfont/regular_wdth_coord": [ - { - "code": "no-regular-instance", - "status": "WARN", - "reason": "Adobe strongly recommends, but does not require having a Regular instance.", - }, - ], - "opentype/varfont/regular_wght_coord": [ + "opentype/fvar/regular_coords_correct": [ { "code": "no-regular-instance", "status": "WARN", diff --git a/Lib/fontbakery/profiles/opentype.py b/Lib/fontbakery/profiles/opentype.py index 7680495637..61617c1f27 100644 --- a/Lib/fontbakery/profiles/opentype.py +++ b/Lib/fontbakery/profiles/opentype.py @@ -19,6 +19,7 @@ "opentype/fsselection", "opentype/fsselection_matches_macstyle", "opentype/fvar/axis_ranges_correct", + "opentype/fvar/regular_coords_correct", "opentype/gdef_mark_chars", "opentype/gdef_non_mark_chars", "opentype/gdef_spacing_marks", @@ -49,11 +50,6 @@ "opentype/varfont/distinct_instance_records", "opentype/varfont/family_axis_ranges", "opentype/varfont/foundry_defined_tag_name", - "opentype/varfont/regular_ital_coord", - "opentype/varfont/regular_opsz_coord", - "opentype/varfont/regular_slnt_coord", - "opentype/varfont/regular_wdth_coord", - "opentype/varfont/regular_wght_coord", "opentype/varfont/same_size_instance_records", "opentype/varfont/stat_axis_record_for_each_axis", "opentype/varfont/valid_default_instance_nameids", diff --git a/Lib/fontbakery/profiles/typenetwork.py b/Lib/fontbakery/profiles/typenetwork.py index 1111456769..d7162e4653 100644 --- a/Lib/fontbakery/profiles/typenetwork.py +++ b/Lib/fontbakery/profiles/typenetwork.py @@ -132,39 +132,7 @@ "the 'wght' axis.", }, ], - "opentype/varfont/regular_ital_coord": [ - { - "code": "no-regular-instance", - "status": "WARN", - "reason": "Adobe and Type Network recommend, but do not require" - " having a Regular instance.", - }, - ], - "opentype/varfont/regular_opsz_coord": [ - { - "code": "no-regular-instance", - "status": "WARN", - "reason": "Adobe and Type Network recommend, but do not require" - " having a Regular instance.", - }, - ], - "opentype/varfont/regular_slnt_coord": [ - { - "code": "no-regular-instance", - "status": "WARN", - "reason": "Adobe and Type Network recommend, but do not require" - " having a Regular instance.", - }, - ], - "opentype/varfont/regular_wdth_coord": [ - { - "code": "no-regular-instance", - "status": "WARN", - "reason": "Adobe and Type Network recommend, but do not require" - " having a Regular instance.", - }, - ], - "opentype/varfont/regular_wght_coord": [ + "opentype/fvar/regular_coords_correct": [ { "code": "no-regular-instance", "status": "WARN", diff --git a/tests/test_checks_opentype_fvar_regular_coords_correct.py b/tests/test_checks_opentype_fvar_regular_coords_correct.py index 605021c914..eb74ca51ae 100644 --- a/tests/test_checks_opentype_fvar_regular_coords_correct.py +++ b/tests/test_checks_opentype_fvar_regular_coords_correct.py @@ -2,19 +2,24 @@ from fontTools.ttLib.tables._f_v_a_r import Axis from conftest import check_id -from fontbakery.status import FAIL, WARN, SKIP +from fontbakery.status import FAIL, WARN from fontbakery.codetesting import ( assert_PASS, + assert_SKIP, assert_results_contain, TEST_FILE, MockFont, ) -@check_id("opentype/varfont/regular_wght_coord") -def test_check_varfont_regular_wght_coord(check): - """The variable font 'wght' (Weight) axis coordinate - must be 400 on the 'Regular' instance.""" +@check_id("opentype/fvar/regular_coords_correct") +def test_check_opentype_fvar_regular_coords_correct(check): + # test with a static font. + ttFont = TTFont(TEST_FILE("source-sans-pro/TTF/SourceSansPro-It.ttf")) + assert_SKIP(check(ttFont)) + + #### The variable font 'wght' (Weight) axis coordinate + # must be 400 on the 'Regular' instance. # Our reference varfont CabinVFBeta.ttf # has a good Regular:wght coordinate @@ -24,41 +29,21 @@ def test_check_varfont_regular_wght_coord(check): # We then ensure the check detects it when we # introduce the problem by setting a bad value: ttFont["fvar"].instances[0].coordinates["wght"] = 500 - msg = assert_results_contain(check(ttFont), FAIL, "wght-not-400") - assert msg == ( - 'The "wght" axis coordinate of the "Regular" instance must be 400.' - " Got 500 instead." - ) + assert_results_contain(check(ttFont), FAIL, "wght-not-400") # Reload the original font. ttFont = TTFont("data/test/cabinvfbeta/CabinVFBeta.ttf") # Change the name of the first instance from 'Regular' (nameID 258) # to 'Medium' (nameID 259). The font now has no Regular instance. ttFont["fvar"].instances[0].subfamilyNameID = 259 - msg = assert_results_contain(check(ttFont), FAIL, "no-regular-instance") - assert msg == ('"Regular" instance not present.') - - # Test with a variable font that doesn't have a 'wght' (Weight) axis. - # The check should yield SKIP. - ttFont = TTFont(TEST_FILE("BadGrades/BadGrades-VF.ttf")) - msg = assert_results_contain(check(ttFont), SKIP, "unfulfilled-conditions") - assert "Unfulfilled Conditions: has_wght_axis" in msg + assert_results_contain(check(ttFont), FAIL, "no-regular-instance") # Test with an italic variable font. The Italic instance must also be 400 ttFont = TTFont(TEST_FILE("varfont/OpenSans-Italic[wdth,wght].ttf")) assert_PASS(check(ttFont)) - # Now test with a static font. - # The test should be skipped due to an unfulfilled condition. - ttFont = TTFont(TEST_FILE("source-sans-pro/TTF/SourceSansPro-Bold.ttf")) - msg = assert_results_contain(check(ttFont), SKIP, "unfulfilled-conditions") - assert "Unfulfilled Conditions: is_variable_font, has_wght_axis" in msg - - -@check_id("opentype/varfont/regular_wdth_coord") -def test_check_varfont_regular_wdth_coord(check): - """The variable font 'wdth' (Width) axis coordinate - must be 100 on the 'Regular' instance.""" + #### The variable font 'wdth' (Width) axis coordinate + # must be 100 on the 'Regular' instance. # Our reference varfont CabinVFBeta.ttf # has a good Regular:wdth coordinate @@ -68,41 +53,21 @@ def test_check_varfont_regular_wdth_coord(check): # We then ensure the check detects it when we # introduce the problem by setting a bad value: ttFont["fvar"].instances[0].coordinates["wdth"] = 0 - msg = assert_results_contain(check(ttFont), FAIL, "wdth-not-100") - assert msg == ( - 'The "wdth" axis coordinate of the "Regular" instance must be 100.' - " Got 0 as a default value instead." - ) + assert_results_contain(check(ttFont), FAIL, "wdth-not-100") # Reload the original font. ttFont = TTFont("data/test/cabinvfbeta/CabinVFBeta.ttf") # Change the name of the first instance from 'Regular' (nameID 258) # to 'Medium' (nameID 259). The font now has no Regular instance. ttFont["fvar"].instances[0].subfamilyNameID = 259 - msg = assert_results_contain(check(ttFont), FAIL, "no-regular-instance") - assert msg == ('"Regular" instance not present.') - - # Test with a variable font that doesn't have a 'wdth' (Width) axis. - # The check should yield SKIP. - ttFont = TTFont(TEST_FILE("source-sans-pro/VAR/SourceSansVariable-Italic.otf")) - msg = assert_results_contain(check(ttFont), SKIP, "unfulfilled-conditions") - assert "Unfulfilled Conditions: has_wdth_axis" in msg + assert_results_contain(check(ttFont), FAIL, "no-regular-instance") # Test with an italic variable font. The Italic instance must also be 100 ttFont = TTFont(TEST_FILE("varfont/OpenSans-Italic[wdth,wght].ttf")) assert_PASS(check(ttFont)) - # Now test with a static font. - # The test should be skipped due to an unfulfilled condition. - ttFont = TTFont(TEST_FILE("source-sans-pro/TTF/SourceSansPro-Bold.ttf")) - msg = assert_results_contain(check(ttFont), SKIP, "unfulfilled-conditions") - assert "Unfulfilled Conditions: is_variable_font, has_wdth_axis" in msg - - -@check_id("opentype/varfont/regular_slnt_coord") -def test_check_varfont_regular_slnt_coord(check): - """The variable font 'slnt' (Slant) axis coordinate - must be zero on the 'Regular' instance.""" + #### The variable font 'slnt' (Slant) axis coordinate + # must be zero on the 'Regular' instance. # Our reference varfont, CabinVFBeta.ttf, lacks a 'slnt' variation axis. ttFont = TTFont("data/test/cabinvfbeta/CabinVFBeta.ttf") @@ -119,11 +84,7 @@ def test_check_varfont_regular_slnt_coord(check): # I inspected our reference CabinVF using ttx # And with this the check must detect the problem: - msg = assert_results_contain(check(ttFont), FAIL, "slnt-not-0") - assert msg == ( - 'The "slnt" axis coordinate of the "Regular" instance must be zero.' - " Got 12 as a default value instead." - ) + assert_results_contain(check(ttFont), FAIL, "slnt-not-0") # We correct the slant coordinate value to make the check PASS. first_instance.coordinates["slnt"] = 0 @@ -132,26 +93,10 @@ def test_check_varfont_regular_slnt_coord(check): # Change the name of the first instance from 'Regular' (nameID 258) # to 'Medium' (nameID 259). The font now has no Regular instance. first_instance.subfamilyNameID = 259 - msg = assert_results_contain(check(ttFont), FAIL, "no-regular-instance") - assert msg == ('"Regular" instance not present.') - - # Test with a variable font that doesn't have a 'slnt' (Slant) axis. - # The check should yield SKIP. - ttFont = TTFont(TEST_FILE("source-sans-pro/VAR/SourceSansVariable-Italic.otf")) - msg = assert_results_contain(check(ttFont), SKIP, "unfulfilled-conditions") - assert "Unfulfilled Conditions: has_slnt_axis" in msg - - # Now test with a static font. - # The test should be skipped due to an unfulfilled condition. - ttFont = TTFont(TEST_FILE("source-sans-pro/TTF/SourceSansPro-Bold.ttf")) - msg = assert_results_contain(check(ttFont), SKIP, "unfulfilled-conditions") - assert "Unfulfilled Conditions: is_variable_font, has_slnt_axis" in msg + assert_results_contain(check(ttFont), FAIL, "no-regular-instance") - -@check_id("opentype/varfont/regular_ital_coord") -def test_check_varfont_regular_ital_coord(check): - """The variable font 'ital' (Italic) axis coordinate - must be zero on the 'Regular' instance.""" + #### The variable font 'ital' (Italic) axis coordinate + # must be zero on the 'Regular' instance. # Our reference varfont, CabinVFBeta.ttf, lacks an 'ital' variation axis. ttFont = TTFont("data/test/cabinvfbeta/CabinVFBeta.ttf") @@ -168,11 +113,7 @@ def test_check_varfont_regular_ital_coord(check): # I inspected the our reference CabinVF using ttx # And with this the check must detect the problem: - msg = assert_results_contain(check(ttFont), FAIL, "ital-not-0") - assert msg == ( - 'The "ital" axis coordinate of the "Regular" instance must be zero.' - " Got 123 as a default value instead." - ) + assert_results_contain(check(ttFont), FAIL, "ital-not-0") # We correct the italic coordinate value to make the check PASS. first_instance.coordinates["ital"] = 0 @@ -181,26 +122,10 @@ def test_check_varfont_regular_ital_coord(check): # Change the name of the first instance from 'Regular' (nameID 258) # to 'Medium' (nameID 259). The font now has no Regular instance. first_instance.subfamilyNameID = 259 - msg = assert_results_contain(check(ttFont), FAIL, "no-regular-instance") - assert msg == ('"Regular" instance not present.') + assert_results_contain(check(ttFont), FAIL, "no-regular-instance") - # Test with a variable font that doesn't have an 'ital' (Italic) axis. - # The check should yield SKIP. - ttFont = TTFont(TEST_FILE("source-sans-pro/VAR/SourceSansVariable-Italic.otf")) - msg = assert_results_contain(check(ttFont), SKIP, "unfulfilled-conditions") - assert "Unfulfilled Conditions: has_ital_axis" in msg - - # Now test with a static font. - # The test should be skipped due to an unfulfilled condition. - ttFont = TTFont(TEST_FILE("source-sans-pro/TTF/SourceSansPro-It.ttf")) - msg = assert_results_contain(check(ttFont), SKIP, "unfulfilled-conditions") - assert "Unfulfilled Conditions: is_variable_font, has_ital_axis" in msg - - -@check_id("opentype/varfont/regular_opsz_coord") -def test_check_varfont_regular_opsz_coord(check): - """The variable font 'opsz' (Optical Size) axis coordinate - should be between 10 and 16 on the 'Regular' instance.""" + #### The variable font 'opsz' (Optical Size) axis coordinate + # should be between 10 and 16 on the 'Regular' instance. # Our reference varfont, CabinVFBeta.ttf, lacks an 'opsz' variation axis. ttFont = TTFont("data/test/cabinvfbeta/CabinVFBeta.ttf") @@ -218,10 +143,7 @@ def test_check_varfont_regular_opsz_coord(check): # Then we ensure the problem is detected: assert_results_contain( - check(ttFont), - WARN, - "opsz-out-of-range", - "with a bad Regular:opsz coordinate (9)...", + check(ttFont), WARN, "opsz", "with a bad Regular:opsz coordinate (9)..." ) # We try yet another bad value @@ -229,7 +151,7 @@ def test_check_varfont_regular_opsz_coord(check): assert_results_contain( check(MockFont(ttFont=ttFont, regular_opsz_coord=17)), WARN, - "opsz-out-of-range", + "opsz", "with another bad Regular:opsz value (17)...", ) @@ -243,5 +165,4 @@ def test_check_varfont_regular_opsz_coord(check): # Change the name of the first instance from 'Regular' (nameID 258) # to 'Medium' (nameID 259). The font now has no Regular instance. first_instance.subfamilyNameID = 259 - msg = assert_results_contain(check(ttFont), FAIL, "no-regular-instance") - assert msg == ('"Regular" instance not present.') + assert_results_contain(check(ttFont), FAIL, "no-regular-instance") diff --git a/tests/test_external_profile.py b/tests/test_external_profile.py index 80ed096198..05b4d2379a 100644 --- a/tests/test_external_profile.py +++ b/tests/test_external_profile.py @@ -26,11 +26,11 @@ def test_external_profile(): fakemodule, "PROFILE", { - "include_profiles": ["opentype"], + "include_profiles": ["universal"], "sections": { "Dalton Maag OpenType": [ "opentype/family/panose_familytype", - "opentype/varfont/regular_opsz_coord", + "opentype/fvar/regular_coords_correct", ] }, },