Exemple #1
0
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))
Exemple #2
0
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))
Exemple #3
0
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...')
Exemple #5
0
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...')
Exemple #7
0
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
Exemple #9
0
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
Exemple #10
0
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))