Skip to content

Commit

Permalink
New check: com.google.fonts/check/name/italic_names
Browse files Browse the repository at this point in the history
Check name table IDs 1, 2, 16, 17 to conform to Italic style.

This check ensures that several entries in the name table
conform to the font's Upright or Italic style,
namely IDs 1 & 2 as well as 16 & 17 if they're present.

(issues #3666 and #3667)
  • Loading branch information
yanone authored and felipesanches committed Jan 17, 2023
1 parent 80a7bb5 commit b7050bb
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ A more detailed list of changes is available in the corresponding milestones for

#### Added to the Open Type Profile
- **[com.thetypefounders/check/vendor_id]:** When a font project's Vendor ID is specified explicitely on FontBakery's configuration file, all binaries must have a matching vendor identifier value in the OS/2 table. (PR #3941)
- **[com.google.fonts/check/name/italic_names]:** Implemented checks for name IDs 1, 2, 16, 17 for Italic fonts (issues #3666 and #3667)

#### Added to the Google Fonts Profile
- **[com.google.fonts/check/colorfont_tables]:** Check if fonts contain the correct color tables. (issue #3886)
Expand Down
68 changes: 66 additions & 2 deletions Lib/fontbakery/profiles/name.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from fontbakery.callable import check
from fontbakery.status import FAIL, PASS, WARN, INFO
from fontbakery.status import FAIL, PASS, WARN, INFO, SKIP
from fontbakery.message import Message
from fontbakery.constants import (NameID,
PlatformID,
Expand Down Expand Up @@ -550,7 +550,7 @@ def com_adobe_fonts_check_name_postscript_name_consistency(ttFont):
""",
)
def com_adobe_fonts_check_family_max_4_fonts_per_family_name(ttFonts):
"""Verify that each group of fonts with the same nameID 1 has maximum of 4 fonts"""
"""Verify that each group of fonts with the same nameID 1 has maximum of 4 fonts."""
from collections import Counter
from fontbakery.utils import get_name_entry_strings

Expand Down Expand Up @@ -578,3 +578,67 @@ def com_adobe_fonts_check_family_max_4_fonts_per_family_name(ttFonts):
f" (should be 4 or fewer).")
if passed:
yield PASS, ("There were no more than 4 fonts per family name.")


@check(
id = 'com.google.fonts/check/name/italic_names',
conditions = ['style'],
rationale = """
This check ensures that several entries in the name table
conform to the font's Upright or Italic style,
namely IDs 1 & 2 as well as 16 & 17 if they're present.
""",
)
def com_google_fonts_check_name_italic_names(ttFont, style):
"""Check name table IDs 1, 2, 16, 17 to conform to Italic style."""

def get_name(nameID):
for entry in ttFont['name'].names:
if entry.nameID == nameID:
return entry.toUnicode()

if "Italic" not in style:
yield SKIP, ("Font is not Italic.")
else:
passed = True
# Name ID 1 (Family Name)
if "Italic" in get_name(NameID.FONT_FAMILY_NAME):
yield FAIL,\
Message("bad-familyname",
"Name ID 1 (Family Name) must not contain 'Italic'.")
passed = False

# Name ID 2 (Subfamily Name)
subfamily_name_from_style = style
if not subfamily_name_from_style.startswith("Italic"):
subfamily_name_from_style = subfamily_name_from_style.replace("Italic", " Italic")

subfamily_name = get_name(NameID.FONT_SUBFAMILY_NAME)
if subfamily_name_from_style != subfamily_name:
yield FAIL,\
Message("bad-subfamilyname",
f"Name ID 2 (Subfamily Name) does not conform to font style.\n"
f"Expected: '{subfamily_name_from_style}'\n
f"Got: '{subfamily_name}'.")
passed = False

# Name ID 16 (Typographic Family Name)
if get_name(NameID.TYPOGRAPHIC_FAMILY_NAME):
if "Italic" in get_name(NameID.TYPOGRAPHIC_FAMILY_NAME):
yield FAIL,\
Message("bad-typographicfamilyname",
"Name ID 16 (Typographic Family Name)"
" must not contain 'Italic'.")
passed = False

# Name ID 17 (Typographic Subfamily Name)
if get_name(NameID.TYPOGRAPHIC_SUBFAMILY_NAME):
if not get_name(NameID.TYPOGRAPHIC_SUBFAMILY_NAME).endswith("Italic"):
yield FAIL,\
Message("bad-typographicsubfamilyname",
"Name ID 17 (Typographic Subfamily Name)"
" must contain 'Italic'.")
passed = False

if passed:
yield PASS, ("All font names are good for Italic fonts.")
1 change: 1 addition & 0 deletions Lib/fontbakery/profiles/opentype.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
'com.google.fonts/check/italic_angle',
'com.google.fonts/check/mac_style',
'com.google.fonts/check/fsselection',
'com.google.fonts/check/name/italic_names',
'com.adobe.fonts/check/varfont/valid_axis_nameid',
'com.adobe.fonts/check/varfont/valid_subfamily_nameid',
'com.adobe.fonts/check/varfont/valid_postscript_nameid',
Expand Down
66 changes: 66 additions & 0 deletions tests/profiles/name_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
MacintoshLanguageID)
from fontbakery.checkrunner import INFO, WARN, PASS, FAIL, SKIP
from fontbakery.codetesting import (assert_PASS,
assert_SKIP,
assert_results_contain,
CheckTester,
portable_path,
Expand Down Expand Up @@ -493,3 +494,68 @@ def test_check_family_max_4_fonts_per_family_name():
assert_results_contain(check(test_fonts),
FAIL, 'too-many')


def test_check_italic_names():
check = CheckTester(opentype_profile,
"com.google.fonts/check/name/italic_names")

def get_name(font, nameID):
for entry in font['name'].names:
if entry.nameID == nameID:
return entry.toUnicode()

def set_name(font, nameID, string):
for record in font["name"].names:
if record.nameID == nameID:
old_string = record.toUnicode()
if string != old_string:
font["name"].setName(
string,
record.nameID,
record.platformID,
record.platEncID,
record.langID,
)

# Fonts without Name ID 16 & 17

# PASS or SKIP
ttFont = TTFont(TEST_FILE("cabin/Cabin-Regular.ttf"))
assert_SKIP(check(ttFont))

ttFont = TTFont(TEST_FILE("cabin/Cabin-Italic.ttf"))
assert_PASS(check(ttFont), PASS)

ttFont = TTFont(TEST_FILE("cabin/Cabin-Bold.ttf"))
assert_SKIP(check(ttFont))

ttFont = TTFont(TEST_FILE("cabin/Cabin-BoldItalic.ttf"))
assert_PASS(check(ttFont), PASS)

# FAIL
ttFont = TTFont(TEST_FILE("cabin/Cabin-Italic.ttf"))
set_name(ttFont, 1, get_name(ttFont, 1) + " Italic")
assert_results_contain(check(ttFont), FAIL, "bad-familyname")

ttFont = TTFont(TEST_FILE("cabin/Cabin-Italic.ttf"))
set_name(ttFont, 2, "Regular")
assert_results_contain(check(ttFont), FAIL, "bad-subfamilyname")


# Fonts with Name ID 16 & 17

# PASS or SKIP
ttFont = TTFont(TEST_FILE("shantell/ShantellSans[BNCE,INFM,SPAC,wght].ttf"))
assert_SKIP(check(ttFont))

ttFont = TTFont(TEST_FILE("shantell/ShantellSans-Italic[BNCE,INFM,SPAC,wght].fixed.ttf"))
assert_PASS(check(ttFont), PASS)

# FAIL
ttFont = TTFont(TEST_FILE("shantell/ShantellSans-Italic[BNCE,INFM,SPAC,wght].fixed.ttf"))
set_name(ttFont, 16, "Shantell Sans Italic")
assert_results_contain(check(ttFont), FAIL, "bad-typographicfamilyname")

ttFont = TTFont(TEST_FILE("shantell/ShantellSans-Italic[BNCE,INFM,SPAC,wght].fixed.ttf"))
set_name(ttFont, 17, "Light")
assert_results_contain(check(ttFont), FAIL, "bad-typographicsubfamilyname")

0 comments on commit b7050bb

Please sign in to comment.