Skip to content

Commit

Permalink
Update max-length rules for nameID entries
Browse files Browse the repository at this point in the history
Updated max length requirements according to feedback from @vv-monsalve and
improved description of problems to inform the users.

Entries longer than 32 chars now emmit a FAIL.

com.google.fonts/check/name/family_and_style_max_length
on Google Fonts profile

(issue #2179)
  • Loading branch information
felipesanches committed Jan 24, 2024
1 parent 6f7fcaf commit 3fc0ad3
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 26 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
- **[com.google.fonts/check/font_copyright]:** Accept date ranges. (issue #4386)
- **[com.google.fonts/check/metadata/unsupported_subsets]** and **[com.google.fonts/check/metadata/unreachable_subsetting]**: Updated to use the new `gfsubsets` package. (PR #4434)
- **[com.google.fonts/check/glyphsets/shape_languages]:** Check requires internet access. (issue #4396)
- **[com.google.fonts/check/name/family_and_style_max_length]:** Updated max length requirements according to feedback from @vv-monsalve and improved description of problems to inform the users. Entries longer than 32 chars now emmit a FAIL. (issue #2179)


## 0.10.9 (2024-Jan-12)
Expand Down
45 changes: 25 additions & 20 deletions Lib/fontbakery/profiles/googlefonts.py
Original file line number Diff line number Diff line change
Expand Up @@ -4918,18 +4918,15 @@ def ligatures_sequences(pairs):
id="com.google.fonts/check/name/family_and_style_max_length",
rationale="""
This check ensures that the length of name table entries is not
too long, as this causes problems in some environments. For
details as to the latest requirements and the reason for them,
please see https://github.com/fonttools/fontbakery/issues/2179
too long, as this causes problems in some environments.
""",
proposal="https://github.com/fonttools/fontbakery/issues/1488",
misc_metadata={
"affects": [("Windows", "unspecified")],
},
proposal=[
"https://github.com/fonttools/fontbakery/issues/1488",
"https://github.com/fonttools/fontbakery/issues/2179"
],
)
def com_google_fonts_check_name_family_and_style_max_length(ttFont):
"""Combined length of family and style must not exceed 31 characters."""
"""Combined length of family and style must not exceed 32 characters."""
from fontbakery.utils import get_name_entry_strings
import re

Expand All @@ -4942,31 +4939,35 @@ def strip_ribbi(x):

checks = [
[
FAIL,
NameID.FULL_FONT_NAME,
31,
"with the dropdown menu in old versions of Microsoft Word",
32,
("with the dropdown menu in old versions of Microsoft Word"
" as well as shaping issues for some accented letters in"
" Microsoft Word on Windows 10 and 11"),
strip_ribbi,
],
[
WARN,
NameID.POSTSCRIPT_NAME,
27,
"with PostScript printers, especially on Mac platforms",
lambda x: x,
],
]
for nameid, maxlen, reason, transform in checks:
for loglevel, nameid, maxlen, reason, transform in checks:
for the_name in get_name_entry_strings(ttFont, nameid):
the_name = transform(the_name)
if len(the_name) > maxlen:
passed = False
yield WARN, Message(
yield loglevel, Message(
f"nameid{nameid}-too-long",
f"Name ID {nameid} '{the_name}' exceeds"
f" {maxlen} characters. This has been found to"
f" cause problems {reason}",
f" cause problems {reason}.",
)

# name ID 1 + fvar instance name > 31 : WARN : problems with Windows
# name ID 1 + fvar instance name > 32 : FAIL : problems with Windows
if "fvar" in ttFont:
for instance in ttFont["fvar"].instances:
for instance_name in get_name_entry_strings(
Expand All @@ -4976,12 +4977,16 @@ def strip_ribbi(x):
ttFont, NameID.FONT_FAMILY_NAME
):
full_instance_name = instance_name + " " + family_name
if len(full_instance_name) > 31:
yield WARN, Message(
if len(full_instance_name) > 32:
yield FAIL, Message(
"instance-too-long",
f"Variable font instance name {full_instance_name}"
" exceeds 31 characters. This has been found to "
" cause problems in Microsoft Windows 11",
f"Variable font instance name '{full_instance_name}'"
f" formed by space-separated concatenation of"
f" instance subfamily nameID {instance.subfamilyNameID}"
f" and font family name (nameID {NameID.FONT_FAMILY_NAME})"
f" exceeds 32 characters.\n\n"
f"This has been found to cause shaping issues for some"
f" accented letters in Microsoft Word on Windows 10 and 11.",
)

if passed:
Expand Down
14 changes: 8 additions & 6 deletions tests/profiles/googlefonts_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -430,23 +430,23 @@ def test_check_name_family_and_style_max_length():
# So it must PASS the check:
assert_PASS(check(ttFont), "with a good font...")

# Then we emit a WARNing with long family/style names
# Then we emit a FAIL with long family/style names
# See https://github.com/fonttools/fontbakery/issues/2179 for
# a discussion of the requirements

for index, name in enumerate(ttFont["name"].names):
if name.nameID == NameID.FULL_FONT_NAME:
# This has 33 chars, while the max currently allowed is 31
# This has 33 chars, while the max currently allowed is 32
bad = "An Absurdly Long Family Name Font"
assert len(bad) == 33
ttFont["name"].names[index].string = bad.encode(name.getEncoding())
if name.nameID == NameID.POSTSCRIPT_NAME:
bad = "AnAbsurdlyLongFontName-Regular"
assert len(bad) == 30
bad = "AbsurdlyLongFontName-Regular"
assert len(bad) == 28
ttFont["name"].names[index].string = bad.encode(name.getEncoding())

results = check(ttFont)
assert_results_contain(results, WARN, "nameid4-too-long", "with a bad font...")
assert_results_contain(results, FAIL, "nameid4-too-long", "with a bad font...")
assert_results_contain(results, WARN, "nameid6-too-long", "with a bad font...")

# Restore the original VF
Expand All @@ -455,13 +455,15 @@ def test_check_name_family_and_style_max_length():
# ...and break the check again with a bad fvar instance name:
nameid_to_break = ttFont["fvar"].instances[0].subfamilyNameID
for index, name in enumerate(ttFont["name"].names):
if name.nameID == NameID.FONT_FAMILY_NAME:
assert len(ttFont["name"].names[index].string) + 28 > 32
if name.nameID == nameid_to_break:
bad = "WithAVeryLongAndBadStyleName"
assert len(bad) == 28
ttFont["name"].names[index].string = bad.encode(name.getEncoding())
break
assert_results_contain(
check(ttFont), WARN, "instance-too-long", "with a bad font..."
check(ttFont), FAIL, "instance-too-long", "with a bad font..."
)


Expand Down

0 comments on commit 3fc0ad3

Please sign in to comment.