|
74 | 74 | 'com.google.fonts/check/metadata/filenames',
|
75 | 75 | 'com.google.fonts/check/metadata/italic_style',
|
76 | 76 | 'com.google.fonts/check/metadata/normal_style',
|
77 |
| - 'com.google.fonts/check/metadata/fontname_not_camel_cased', |
78 | 77 | 'com.google.fonts/check/metadata/match_name_familyname',
|
79 | 78 | 'com.google.fonts/check/metadata/canonical_weight_value',
|
80 | 79 | 'com.google.fonts/check/metadata/os2_weightclass',
|
|
120 | 119 | 'com.google.fonts/check/name/license_url',
|
121 | 120 | 'com.google.fonts/check/name/family_and_style_max_length',
|
122 | 121 | 'com.google.fonts/check/name/line_breaks',
|
123 |
| - 'com.google.fonts/check/name/rfn' |
| 122 | + 'com.google.fonts/check/name/rfn', |
| 123 | + 'com.google.fonts/check/name/family_name_compliance', |
124 | 124 | ]
|
125 | 125 |
|
126 | 126 |
|
@@ -2755,32 +2755,6 @@ def com_google_fonts_check_metadata_nameid_family_and_full_names(ttFont, font_me
|
2755 | 2755 | " match corresponding name table entries.")
|
2756 | 2756 |
|
2757 | 2757 |
|
2758 |
| -@check( |
2759 |
| - id = 'com.google.fonts/check/metadata/fontname_not_camel_cased', |
2760 |
| - rationale = """ |
2761 |
| - We currently have a policy of avoiding camel-cased font family names other |
2762 |
| - than in a very small set of exceptions. |
2763 |
| - |
2764 |
| - If you want to have your family name added to the exceptions list, please read |
2765 |
| - the instructions at https://github.com/googlefonts/fontbakery/issues/3270 |
2766 |
| - """, |
2767 |
| - conditions = ['font_metadata', |
2768 |
| - 'not camelcased_familyname_exception'], |
2769 |
| - proposal = 'legacy:check/109' |
2770 |
| -) |
2771 |
| -def com_google_fonts_check_metadata_fontname_not_camel_cased(font_metadata): |
2772 |
| - """METADATA.pb: Check if fontname is not camel cased.""" |
2773 |
| - import re |
2774 |
| - if bool(re.match(r'([A-Z][a-z]+){2,}', font_metadata.name)): |
2775 |
| - yield FAIL,\ |
2776 |
| - Message("camelcase", |
2777 |
| - f'METADATA.pb: "{font_metadata.name}" is a CamelCased name.' |
2778 |
| - f' To solve this, simply use spaces' |
2779 |
| - f' instead in the font name.') |
2780 |
| - else: |
2781 |
| - yield PASS, "Font name is not camel-cased." |
2782 |
| - |
2783 |
| - |
2784 | 2758 | @check(
|
2785 | 2759 | id = 'com.google.fonts/check/metadata/match_name_familyname',
|
2786 | 2760 | conditions = ['family_metadata', # that's the family-wide metadata!
|
@@ -4377,6 +4351,113 @@ def com_google_fonts_check_name_rfn(ttFont, familyname):
|
4377 | 4351 | yield PASS, 'None of the name table strings contain "Reserved Font Name".'
|
4378 | 4352 |
|
4379 | 4353 |
|
| 4354 | +@check( |
| 4355 | + id = 'com.google.fonts/check/name/family_name_compliance', |
| 4356 | + rationale = """ |
| 4357 | + Checks the family name for compliance with the Google Fonts Guide. |
| 4358 | + https://googlefonts.github.io/gf-guide/onboarding.html#new-fonts |
| 4359 | + |
| 4360 | + If you want to have your family name added to the CamelCase |
| 4361 | + exceptions list, please submit a pull request to the |
| 4362 | + camelcased_familyname_exceptions.txt file. |
| 4363 | +
|
| 4364 | + Similarly, abbreviations can be submitted to the |
| 4365 | + abbreviations_familyname_exceptions.txt file. |
| 4366 | +
|
| 4367 | + These are located in the Lib/fontbakery/data/googlefonts/ directory |
| 4368 | + of the FontBakery source code currently hosted at |
| 4369 | + https://github.com/googlefonts/fontbakery/ |
| 4370 | + """, |
| 4371 | + conditions = [], |
| 4372 | + proposal = "https://github.com/googlefonts/fontbakery/issues/4049" |
| 4373 | +) |
| 4374 | +def com_google_fonts_check_name_family_name_compliance(ttFont): |
| 4375 | + """Check family name for GF Guide compliance.""" |
| 4376 | + import re |
| 4377 | + from pkg_resources import resource_filename |
| 4378 | + from fontbakery.utils import get_name_entries |
| 4379 | + camelcase_exceptions_txt = 'data/googlefonts/camelcased_familyname_exceptions.txt' |
| 4380 | + abbreviations_exceptions_txt = 'data/googlefonts/abbreviations_familyname_exceptions.txt' |
| 4381 | + passed = True |
| 4382 | + |
| 4383 | + if get_name_entries(ttFont, NameID.TYPOGRAPHIC_FAMILY_NAME): |
| 4384 | + family_name = get_name_entries(ttFont, NameID.TYPOGRAPHIC_FAMILY_NAME)[0].toUnicode() |
| 4385 | + else: |
| 4386 | + family_name = get_name_entries(ttFont, NameID.FONT_FAMILY_NAME)[0].toUnicode() |
| 4387 | + |
| 4388 | + # CamelCase |
| 4389 | + if bool(re.match(r'([A-Z][a-z]+){2,}', family_name)): |
| 4390 | + known_exception = False |
| 4391 | + |
| 4392 | + # Process exceptions |
| 4393 | + filename = resource_filename('fontbakery', camelcase_exceptions_txt) |
| 4394 | + for exception in open(filename, "r").readlines(): |
| 4395 | + exception = exception.split('#')[0].strip() |
| 4396 | + if exception == "": |
| 4397 | + continue |
| 4398 | + if exception in family_name: |
| 4399 | + known_exception = True |
| 4400 | + yield PASS,\ |
| 4401 | + Message("known-camelcase-exception", |
| 4402 | + "Family name is a known exception" |
| 4403 | + " to the CamelCase rule.") |
| 4404 | + break |
| 4405 | + |
| 4406 | + if not known_exception: |
| 4407 | + passed = False |
| 4408 | + yield FAIL,\ |
| 4409 | + Message("camelcase", |
| 4410 | + f'"{family_name}" is a CamelCased name.' |
| 4411 | + f' To solve this, simply use spaces' |
| 4412 | + f' instead in the font name.') |
| 4413 | + |
| 4414 | + # Abbreviations |
| 4415 | + if bool(re.match(r'([A-Z]){2,}', family_name)): |
| 4416 | + known_exception = False |
| 4417 | + |
| 4418 | + # Process exceptions |
| 4419 | + filename = resource_filename('fontbakery', abbreviations_exceptions_txt) |
| 4420 | + for exception in open(filename, "r").readlines(): |
| 4421 | + exception = exception.split('#')[0].strip() |
| 4422 | + if exception == "": |
| 4423 | + continue |
| 4424 | + if exception in family_name: |
| 4425 | + known_exception = True |
| 4426 | + yield PASS,\ |
| 4427 | + Message("known-abbreviation-exception", |
| 4428 | + "Family name is a known exception" |
| 4429 | + " to the abbreviation rule.") |
| 4430 | + break |
| 4431 | + |
| 4432 | + if not known_exception: |
| 4433 | + # Allow SC ending |
| 4434 | + if not family_name.endswith("SC"): |
| 4435 | + failed = True |
| 4436 | + yield FAIL,\ |
| 4437 | + Message("abbreviation", |
| 4438 | + f'"{family_name}" contains an abbreviation.') |
| 4439 | + |
| 4440 | + # Allowed characters |
| 4441 | + forbidden_characters = re.findall(r'[^a-zA-Z0-9 ]', family_name) |
| 4442 | + if forbidden_characters: |
| 4443 | + forbidden_characters = "".join(sorted(list(set(forbidden_characters)))) |
| 4444 | + failed = True |
| 4445 | + yield FAIL,\ |
| 4446 | + Message("forbidden-characters", |
| 4447 | + f'"{family_name}" contains the following characters' |
| 4448 | + f' which are not allowed: "{forbidden_characters}".') |
| 4449 | + |
| 4450 | + # Starts with uppercase |
| 4451 | + if not bool(re.match(r'^[A-Z]', family_name)): |
| 4452 | + failed = True |
| 4453 | + yield FAIL,\ |
| 4454 | + Message("starts-with-not-uppercase", |
| 4455 | + f'"{family_name}" doesn\'t start with an uppercase letter.') |
| 4456 | + |
| 4457 | + if not failed: |
| 4458 | + yield PASS, "Font name looks good." |
| 4459 | + |
| 4460 | + |
4380 | 4461 | @check(
|
4381 | 4462 | id = 'com.google.fonts/check/family/control_chars',
|
4382 | 4463 | conditions = ['are_ttf'],
|
|
0 commit comments