def test_check_unique_glyphnames(): """ Font contains unique glyph names? """ import io from fontbakery.profiles.universal import com_google_fonts_check_unique_glyphnames as check test_font_path = TEST_FILE("nunito/Nunito-Regular.ttf") test_font = TTFont(test_font_path) assert_PASS(check(test_font)) # Fonttools renames duplicate glyphs with #1, #2, ... on load. # Code snippet from https://github.com/fonttools/fonttools/issues/149. glyph_names = test_font.getGlyphOrder() glyph_names[2] = glyph_names[3] # Load again, we changed the font directly. test_font = TTFont(test_font_path) test_font.setGlyphOrder(glyph_names) test_font['post'] # Just access the data to make fonttools generate it. test_file = io.BytesIO() test_font.save(test_file) test_font = TTFont(test_file) message = assert_results_contain( check(test_font), FAIL, None) # FIXME: This needs a message keyword assert "space" in message # Upgrade to post format 3.0 and roundtrip data to update TTF object. test_font = TTFont(test_font_path) test_font.setGlyphOrder(glyph_names) test_font["post"].formatType = 3.0 test_file = io.BytesIO() test_font.save(test_file) test_font = TTFont(test_file) assert_SKIP(check(test_font))
def test_check_unique_glyphnames(): """ Font contains unique glyph names? """ check = CheckTester(universal_profile, "com.google.fonts/check/unique_glyphnames") ttFont = TTFont(TEST_FILE("nunito/Nunito-Regular.ttf")) assert_PASS(check(ttFont)) # Fonttools renames duplicate glyphs with #1, #2, ... on load. # Code snippet from https://github.com/fonttools/fonttools/issues/149. glyph_names = ttFont.getGlyphOrder() glyph_names[2] = glyph_names[3] # Load again, we changed the font directly. ttFont = TTFont(TEST_FILE("nunito/Nunito-Regular.ttf")) ttFont.setGlyphOrder(glyph_names) ttFont['post'] # Just access the data to make fonttools generate it. _file = io.BytesIO() _file.name = ttFont.reader.file.name ttFont.save(_file) ttFont = TTFont(_file) message = assert_results_contain(check(ttFont), FAIL, "duplicated-glyph-names") assert "space" in message # Upgrade to post format 3.0 and roundtrip data to update TTF object. ttFont = TTFont(TEST_FILE("nunito/Nunito-Regular.ttf")) ttFont.setGlyphOrder(glyph_names) ttFont["post"].formatType = 3.0 _file = io.BytesIO() _file.name = ttFont.reader.file.name ttFont.save(_file) ttFont = TTFont(_file) assert_SKIP(check(ttFont))
def test_check_valid_glyphnames(): """ Glyph names are all valid? """ import io from fontbakery.profiles.universal import com_google_fonts_check_valid_glyphnames as check # We start with a good font file: test_font_path = TEST_FILE("nunito/Nunito-Regular.ttf") test_font = TTFont(test_font_path) assert_PASS(check(test_font)) # There used to be a 31 char max-length limit. # This was good: test_font.glyphOrder[2] = "a" * 31 assert_PASS(check(test_font)) # And this was bad: legacy_too_long = "a" * 32 test_font.glyphOrder[2] = legacy_too_long message = assert_results_contain(check(test_font), WARN, 'legacy-long-names') assert legacy_too_long in message # Nowadays, it seems most implementations can deal with # up to 63 char glyph names: good_name = "b" * 63 bad_name1 = "a" * 64 bad_name2 = "3cents" bad_name3 = ".threecents" test_font.glyphOrder[2] = bad_name1 test_font.glyphOrder[3] = bad_name2 test_font.glyphOrder[4] = bad_name3 test_font.glyphOrder[5] = good_name message = assert_results_contain(check(test_font), FAIL, 'found-invalid-names') assert good_name not in message assert bad_name1 in message assert bad_name2 in message assert bad_name3 in message # TrueType fonts with a format 3.0 post table contain # no glyph names, so the check must be SKIP'd in that case. # # Upgrade to post format 3.0 and roundtrip data to update TTF object. test_font = TTFont(test_font_path) test_font["post"].formatType = 3.0 test_file = io.BytesIO() test_font.save(test_file) test_font = TTFont(test_file) assert_SKIP(check(test_font))
def test_check_gdef_spacing_marks(): """ Are some spacing glyphs in GDEF mark glyph class? """ check = CheckTester(opentype_profile, "com.google.fonts/check/gdef_spacing_marks") ttFont = get_test_font() assert_SKIP(check(ttFont), 'if a font lacks a GDEF table...') add_gdef_table(ttFont, {}) assert_PASS(check(ttFont), 'with an empty GDEF table...') # Add a table with 'A' defined as a mark glyph: add_gdef_table(ttFont, {'A': 3}) assert_results_contain(check(ttFont), WARN, 'spacing-mark-glyphs', 'if a mark glyph has non-zero width...')
def test_check_gdef_spacing_marks(): """ Are some spacing glyphs in GDEF mark glyph class? """ from fontbakery.profiles.gdef import com_google_fonts_check_gdef_spacing_marks as check test_font = get_test_font() assert_SKIP(check(test_font), 'if a font lacks a GDEF table...') add_gdef_table(test_font, {}) assert_PASS(check(test_font), 'with an empty GDEF table...') # Add a table with 'A' defined as a mark glyph: add_gdef_table(test_font, {'A': 3}) assert_results_contain(check(test_font), WARN, 'spacing-mark-glyphs', 'if a mark glyph has non-zero width...')
def test_check_gdef_mark_chars(): """ Are some mark characters not in in GDEF mark glyph class? """ check = CheckTester(opentype_profile, "com.google.fonts/check/gdef_mark_chars") ttFont = get_test_font() assert_SKIP(check(ttFont), 'if a font lacks a GDEF table...') # Add a GDEF table not including `acutecomb` (U+0301) as a mark char: add_gdef_table(ttFont, {}) message = assert_results_contain(check(ttFont), WARN, 'mark-chars', 'if a mark-char is not listed...') assert 'U+0301' in message # Include it in the table to see the check PASS: add_gdef_table(ttFont, {'acutecomb': 3}) assert_PASS(check(ttFont), 'when properly declared...')
def test_check_gdef_mark_chars(): """ Are some mark characters not in in GDEF mark glyph class? """ from fontbakery.profiles.gdef import com_google_fonts_check_gdef_mark_chars as check test_font = get_test_font() assert_SKIP(check(test_font), 'if a font lacks a GDEF table...') # Add a GDEF table not including `acutecomb` (U+0301) as a mark char: add_gdef_table(test_font, {}) message = assert_results_contain(check(test_font), WARN, 'mark-chars', 'if a mark-char is not listed...') assert 'U+0301' in message # Include it in the table to see the check PASS: add_gdef_table(test_font, {'acutecomb': 3}) assert_PASS(check(test_font), 'when properly declared...')
def test_check_gdef_non_mark_chars(): """ Are some non-mark characters in GDEF mark glyph class spacing? """ check = CheckTester(opentype_profile, "com.google.fonts/check/gdef_non_mark_chars") ttFont = get_test_font() assert_SKIP(check(ttFont), 'if a font lacks a GDEF table...') add_gdef_table(ttFont, {}) assert_PASS(check(ttFont), 'with an empty GDEF table.') add_gdef_table(ttFont, {'acutecomb': 3}) assert_PASS(check(ttFont), 'with an GDEF with only properly declared mark chars.') add_gdef_table(ttFont, {'acute': 3, 'acutecomb': 3}) message = assert_results_contain( check(ttFont), WARN, 'non-mark-chars', 'with an GDEF with a non-mark char (U+00B4, "acute") misdeclared') assert 'U+00B4' in message
def test_check_gdef_non_mark_chars(): """ Are some non-mark characters in GDEF mark glyph class spacing? """ from fontbakery.profiles.gdef import com_google_fonts_check_gdef_non_mark_chars as check test_font = get_test_font() assert_SKIP(check(test_font), 'if a font lacks a GDEF table...') add_gdef_table(test_font, {}) assert_PASS(check(test_font), 'with an empty GDEF table.') add_gdef_table(test_font, {'acutecomb': 3}) assert_PASS(check(test_font), 'with an GDEF with only properly declared mark chars.') add_gdef_table(test_font, {'acute': 3, 'acutecomb': 3}) message = assert_results_contain(check(test_font), WARN, 'non-mark-chars', 'with an GDEF with a non-mark char (U+00B4, "acute") misdeclared') assert 'U+00B4' in message
def test_check_whitespace_glyphnames(): """ Font has **proper** whitespace glyph names? """ check = CheckTester(universal_profile, "com.google.fonts/check/whitespace_glyphnames") def deleteGlyphEncodings(font, cp): """ This routine is used on to introduce errors in a given font by removing specific entries in the cmap tables. """ for subtable in font['cmap'].tables: if subtable.isUnicode(): subtable.cmap = { codepoint: name for codepoint, name in subtable.cmap.items() if codepoint != cp } def editCmap(font, cp, name): """ Corrupt the cmap by changing the glyph name for a given code point. """ for subtable in font['cmap'].tables: if subtable.isUnicode(): # Copy the map subtable.cmap = subtable.cmap.copy() # edit it subtable.cmap[cp] = name # Our reference Mada Regular font is good here: ttFont = TTFont(TEST_FILE("mada/Mada-Regular.ttf")) assert_PASS(check(ttFont), 'with a good font...') value = ttFont["post"].formatType ttFont["post"].formatType = 3.0 assert_SKIP(check(ttFont), 'with post.formatType == 3.0 ...') # restore good value: ttFont["post"].formatType = value deleteGlyphEncodings(ttFont, 0x0020) assert_results_contain(check(ttFont), FAIL, 'missing-0020', 'with missing glyph name for char 0x0020 ...') # restore the original font object in preparation for the next test-case: ttFont = TTFont(TEST_FILE("mada/Mada-Regular.ttf")) deleteGlyphEncodings(ttFont, 0x00A0) assert_results_contain(check(ttFont), FAIL, 'missing-00a0', 'with missing glyph name for char 0x00A0 ...') # restore the original font object in preparation for the next test-case: ttFont = TTFont(TEST_FILE("mada/Mada-Regular.ttf")) # See https://github.com/googlefonts/fontbakery/issues/2624 # nbsp is not Adobe Glyph List compliant. editCmap(ttFont, 0x00A0, "nbsp") assert_results_contain( check(ttFont), FAIL, 'non-compliant-00a0', 'with not AGL-compliant glyph name "nbsp" for char 0x00A0...') editCmap(ttFont, 0x00A0, "nbspace") assert_results_contain(check(ttFont), WARN, 'not-recommended-00a0', 'for naming 0x00A0 "nbspace"...') editCmap(ttFont, 0x0020, "foo") assert_results_contain( check(ttFont), FAIL, 'non-compliant-0020', 'with not AGL-compliant glyph name "foo" for char 0x0020...') editCmap(ttFont, 0x0020, "uni0020") assert_results_contain(check(ttFont), WARN, 'not-recommended-0020', 'for naming 0x0020 "uni0020"...') editCmap(ttFont, 0x0020, "space") editCmap(ttFont, 0x00A0, "uni00A0") assert_PASS(check(ttFont))