Пример #1
0
 def test_check_italic_angle_agreement(self):
     """ Check italicangle property zero or negative """
     font = Font.get_ttfont(self.operator.path)
     if font.italicAngle > 0:
         self.fail('italicAngle must be less or equal zero')
     if abs(font.italicAngle) > 20:
         self.fail('italicAngle can\'t be larger than 20 degrees')
Пример #2
0
 def test_check_font_has_dsig_table(self):
     """ Check that font has DSIG table """
     font = Font.get_ttfont(self.operator.path)
     try:
         font['DSIG']
     except KeyError:
         self.fail('Font does not have "DSIG" table')
    def test_fontname_is_equal_to_macstyle(self):
        """ Check that fontname is equal to macstyle flags """
        font = Font.get_ttfont(self.operator.path)

        macStyle = font.macStyle

        try:
            fontname_style = font.fullname.split('-')[1]
        except IndexError:
            fontname_style = ''

        expected_style = ''
        if macStyle & 0b01:
            expected_style += 'Bold'

        if macStyle & 0b10:
            expected_style += 'Italic'

        if not bool(macStyle & 0b11):
            expected_style = 'Regular'

        if fontname_style != expected_style:
            _ = 'macStyle ({0}) supposed style ended with "{1}"'

            if fontname_style:
                _ += ' but ends with "{2}"'
            self.fail(
                _.format(bin(macStyle)[-2:], expected_style, fontname_style))
Пример #4
0
    def test_metrics_descents_equal_bbox(self):
        """ Check that descents values are same as min glyph point """
        dirname = os.path.dirname(self.operator.path)

        directory = UpstreamDirectory(dirname)

        fonts_descents_not_bbox = []
        ymin = 0

        _cache = {}
        for filename in directory.get_binaries():
            ttfont = Font.get_ttfont(os.path.join(dirname, filename))

            ymin_, _ = ttfont.get_bounding()
            ymin = min(ymin, ymin_)

            _cache[filename] = {
                'os2typo': abs(ttfont.descents.os2typo),
                'os2win': abs(ttfont.descents.os2win),
                'hhea': abs(ttfont.descents.hhea)
            }

        for filename, data in _cache.items():
            datas = [data['os2typo'], data['os2win'], data['hhea']]
            if datas != [abs(ymin)] * 3:
                fonts_descents_not_bbox.append(filename)

        if fonts_descents_not_bbox:
            _ = '[%s] ascents differ to minimum value: %s'
            self.fail(_ % (', '.join(fonts_descents_not_bbox), ymin))
Пример #5
0
    def test_metrics_descents_equal_bbox(self):
        """ Check that descents values are same as min glyph point """
        dirname = os.path.dirname(self.operator.path)

        directory = UpstreamDirectory(dirname)

        fonts_descents_not_bbox = []
        ymin = 0

        _cache = {}
        for filename in directory.get_binaries():
            ttfont = Font.get_ttfont(os.path.join(dirname, filename))

            ymin_, _ = ttfont.get_bounding()
            ymin = min(ymin, ymin_)

            _cache[filename] = {
                'os2typo': abs(ttfont.descents.os2typo),
                'os2win': abs(ttfont.descents.os2win),
                'hhea': abs(ttfont.descents.hhea)
            }

        for filename, data in _cache.items():
            datas = [data['os2typo'], data['os2win'], data['hhea']]
            if datas != [abs(ymin)] * 3:
                fonts_descents_not_bbox.append(filename)

        if fonts_descents_not_bbox:
            _ = '[%s] ascents differ to minimum value: %s'
            self.fail(_ % (', '.join(fonts_descents_not_bbox), ymin))
    def test_fontname_is_equal_to_macstyle(self):
        """ Check that fontname is equal to macstyle flags """
        font = Font.get_ttfont(self.path)

        fontname = font.fullname
        macStyle = font.macStyle

        try:
            fontname_style = fontname.split('-')[1]
        except IndexError:
            self.fail(('Fontname is not canonical. Expected it contains '
                       'style. eg.: Italic, BoldItalic, Regular'))

        style = ''
        if macStyle & 0b01:
            style += 'Bold'

        if macStyle & 0b10:
            style += 'Italic'

        if not bool(macStyle & 0b11):
            style = 'Regular'

        if not fontname_style.endswith(style):
            _ = 'macStyle (%s) supposed style ended with "%s" but ends with "%s"'
            self.fail(_ % (bin(macStyle)[-2:], style, fontname_style))
Пример #7
0
 def test_check_italic_angle_agreement(self):
     """ Check italicangle property zero or negative """
     font = Font.get_ttfont(self.path)
     if font.italicAngle > 0:
         self.fail('italicAngle must be less or equal zero')
     if abs(font.italicAngle) > 20:
         self.fail('italicAngle can\'t be larger than 20 degrees')
    def test_fontname_is_equal_to_macstyle(self):
        """ Check that fontname is equal to macstyle flags """
        font = Font.get_ttfont(self.operator.path)

        macStyle = font.macStyle

        try:
            fontname_style = font.fullname.split('-')[1]
        except IndexError:
            fontname_style = ''

        expected_style = ''
        if macStyle & 0b01:
            expected_style += 'Bold'

        if macStyle & 0b10:
            expected_style += 'Italic'

        if not bool(macStyle & 0b11):
            expected_style = 'Regular'

        if fontname_style != expected_style:
            _ = 'macStyle ({0}) supposed style ended with "{1}"'

            if fontname_style:
                _ += ' but ends with "{2}"'
            self.fail(_.format(bin(macStyle)[-2:], expected_style, fontname_style))
Пример #9
0
 def test_suggested_subfamily_name(self):
     """ Family does not contain subfamily in `name` table """
     # Currently we just look that family does not contain any spaces
     # in its name. This prevent us from incorrect suggestions of names
     font = Font.get_ttfont(self.operator.path)
     suggestedvalues = getSuggestedFontNameValues(font.ttfont)
     self.assertEqual(font.familyname, suggestedvalues['family'])
     self.assertEqual(font.stylename, suggestedvalues['subfamily'])
    def test_check_names_are_ascii_only(self):
        """ NAME and CFF tables must not contain non-ascii characters """
        font = Font.get_ttfont(self.operator.path)

        for name in font.names:
            string = Font.bin2unistring(name)
            expected = normalizestr(string)
            self.assertEqual(string, expected)
Пример #11
0
 def test_no_kern_table_exists(self):
     """ Check that no "KERN" table exists """
     font = Font.get_ttfont(self.operator.path)
     try:
         font['KERN']
         self.fail('Font does have "KERN" table')
     except KeyError:
         pass
Пример #12
0
 def test_suggested_subfamily_name(self):
     """ Family does not contain subfamily in `name` table """
     # Currently we just look that family does not contain any spaces
     # in its name. This prevent us from incorrect suggestions of names
     font = Font.get_ttfont(self.operator.path)
     suggestedvalues = getSuggestedFontNameValues(font.ttfont)
     self.assertEqual(font.familyname, suggestedvalues['family'])
     self.assertEqual(font.stylename, suggestedvalues['subfamily'])
 def test_check_upm_heigths_less_120(self):
     """ Check if UPM Heights NOT more than 120% """
     ttfont = Font.get_ttfont(self.path)
     value = ttfont.ascents.get_max() + abs(ttfont.descents.get_min())
     value = value * 100 / float(ttfont.get_upm_height())
     if value > 120:
         _ = "UPM:Height is %d%%, consider redesigning to 120%% or less"
         self.fail(_ % value)
Пример #14
0
    def test_check_names_are_ascii_only(self):
        """ NAME and CFF tables must not contain non-ascii characters """
        font = Font.get_ttfont(self.operator.path)

        for name in font.names:
            string = Font.bin2unistring(name)
            marks = CharacterSymbolsFixer.unicode_marks(string)
            if marks:
                self.fail('Contains {}'.format(marks))
Пример #15
0
    def test_check_names_are_ascii_only(self):
        """ NAME and CFF tables must not contain non-ascii characters """
        font = Font.get_ttfont(self.operator.path)

        for name in font.names:
            string = Font.bin2unistring(name)
            marks = CharacterSymbolsFixer.unicode_marks(string)
            if marks:
                self.fail('Contains {}'.format(marks))
    def test_check_names_are_ascii_only(self):
        """ NAME and CFF tables must not contain non-ascii characters """
        font = Font.get_ttfont(self.path)

        for name_record in font.names:
            string = Font.bin2unistring(name_record)
            try:
                string.encode('ascii')
            except UnicodeEncodeError:
                self.fail("%s contain non-ascii chars" % name_record.nameID)
Пример #17
0
 def test_prep_magic_code(self):
     """ Font contains in PREP table magic code """
     magiccode = '\xb8\x01\xff\x85\xb0\x04\x8d'
     font = Font.get_ttfont(self.operator.path)
     try:
         bytecode = font.get_program_bytecode()
     except KeyError:
         bytecode = ''
     self.assertTrue(bytecode == magiccode,
                     msg='PREP does not contain magic code')
Пример #18
0
    def test_check_hmtx_hhea_max_advance_width_agreement(self):
        """ Check if MaxAdvanceWidth agree in the Hmtx and Hhea tables """
        font = Font.get_ttfont(self.path)

        hmtx_advance_width_max = font.get_hmtx_max_advanced_width()
        hhea_advance_width_max = font.advance_width_max
        error = ("AdvanceWidthMax mismatch: expected %s (from hmtx);"
                 " got %s (from hhea)") % (hmtx_advance_width_max,
                                           hhea_advance_width_max)
        self.assertEqual(hmtx_advance_width_max, hhea_advance_width_max, error)
 def test_prep_magic_code(self):
     """ Font contains in PREP table magic code """
     magiccode = '\xb8\x01\xff\x85\xb0\x04\x8d'
     font = Font.get_ttfont(self.operator.path)
     try:
         bytecode = font.get_program_bytecode()
     except KeyError:
         bytecode = ''
     self.assertTrue(bytecode == magiccode,
                     msg='PREP does not contain magic code')
    def test_check_hmtx_hhea_max_advance_width_agreement(self):
        """ Check if MaxAdvanceWidth agree in the Hmtx and Hhea tables """
        font = Font.get_ttfont(self.operator.path)

        hmtx_advance_width_max = font.get_hmtx_max_advanced_width()
        hhea_advance_width_max = font.advance_width_max
        error = ("AdvanceWidthMax mismatch: expected %s (from hmtx);"
                 " got %s (from hhea)") % (hmtx_advance_width_max,
                                           hhea_advance_width_max)
        self.assertEqual(hmtx_advance_width_max,
                         hhea_advance_width_max, error)
Пример #21
0
def set(fontpath, value):
    ttfont = Font.get_ttfont(fontpath)

    try:
        ttfont['gasp']
    except:
        print('no table gasp', file=sys.stderr)
        return

    ttfont['gasp'].gaspRange[65535] = value

    ttfont.save(fontpath + '.fix')
Пример #22
0
def fix(fontpath):
    ttfont = Font.get_ttfont(fontpath)

    ot_namerecord = findOrCreateNameRecord(ttfont['name'].names, 16)
    ot_namerecord.string = ttfont.familyname.encode("utf_16_be")

    ot_namerecord = findOrCreateNameRecord(ttfont['name'].names, 17)
    ot_namerecord.string = mapping.get(ttfont.stylename, 'Regular').encode("utf_16_be")

    ot_namerecord = findOrCreateNameRecord(ttfont['name'].names, 18)
    ot_namerecord.string = ttfont.fullname.encode("utf_16_be")

    ttfont.save(fontpath + '.fix')
Пример #23
0
def show(fontpath):
    ttfont = Font.get_ttfont(fontpath)

    try:
        ttfont['gasp']
    except:
        print('no table gasp', file=sys.stderr)
        return

    try:
        print(ttfont['gasp'].gaspRange[65535])
    except IndexError:
        print('no index 65535', file=sys.stderr)
Пример #24
0
    def test_check_panose_identification(self):
        font = Font.get_ttfont(self.path)

        if font['OS/2'].panose['bProportion'] == 9:
            prev = 0
            for g in font.glyphs():
                if prev and font.advance_width(g) != prev:
                    link = ('http://www.thomasphinney.com/2013/01'
                            '/obscure-panose-issues-for-font-makers/')
                    self.fail(('Your font does not seem monospaced but PANOSE'
                               ' bProportion set to monospace. It may have '
                               ' a bug in windows. Details: %s' % link))
                prev = font.advance_width(g)
    def test_check_nbsp_width_matches_sp_width(self):
        """ Check non-breaking space's advancewidth is the same as space """
        tf = Font.get_ttfont(self.operator.path)
        space_advance_width = tf.advance_width('space')
        nbsp_advance_width = tf.advance_width('uni00A0')

        _ = "Font does not contain a space glyph"
        self.assertTrue(space_advance_width, _)
        _ = "Font does not contain a nbsp glyph"
        self.assertTrue(nbsp_advance_width, _)

        _ = ("The nbsp advance width does not match "
             "the space advance width")
        self.assertEqual(space_advance_width, nbsp_advance_width, _)
Пример #26
0
    def test_ttx_duplicate_glyphs(self):
        """ Font contains unique glyph names? """
        # (Duplicate glyph names prevent font installation on Mac OS X.)
        font = Font.get_ttfont(self.operator.path)
        glyphs = []
        for _, g in enumerate(font.ttfont.getGlyphOrder()):
            self.assertFalse(re.search(r'#\w+$', g),
                             msg="Font contains incorrectly named glyph %s" % g)
            glyphID = re.sub(r'#\w+', '', g)

            # Each GlyphID has to be unique in TTX
            self.assertFalse(glyphID in glyphs,
                             msg="GlyphID %s occurs twice in TTX" % g)
            glyphs.append(glyphs)
Пример #27
0
    def test_check_unused_glyph_data(self):
        f = Font.get_ttfont(self.path)
        glyf_length = f.get_glyf_length()

        loca_num_glyphs = f.get_loca_num_glyphs()

        last_glyph_offset = f.get_loca_glyph_offset(loca_num_glyphs - 1)
        last_glyph_length = f.get_loca_glyph_length(loca_num_glyphs - 1)

        unused_data = glyf_length - (last_glyph_offset + last_glyph_length)

        error = ("there were %s bytes of unused data at the end"
                 " of the glyf table") % unused_data
        self.assertEqual(unused_data, 0, error)
    def test_source_ttf_font_filename_equals_familystyle(self):
        """ Source TTF Font filename equals family style """
        ttfont = Font.get_ttfont(self.operator.path)

        style_name = ttfont.stylename
        if style_name == 'Normal' or style_name == 'Roman':
            style_name = 'Regular'

        expectedname = '{0}-{1}'.format(ttfont.familyname.replace(' ', ''),
                                        style_name.replace(' ', ''))
        actualname, extension = os.path.splitext(self.operator.path)

        self.expectedfilename = '{0}{1}'.format(expectedname, extension)
        self.assertEqual(os.path.basename(actualname), expectedname)
Пример #29
0
    def test_ttx_duplicate_glyphs(self):
        """ Font contains unique glyph names? """
        # (Duplicate glyph names prevent font installation on Mac OS X.)
        font = Font.get_ttfont(self.operator.path)
        glyphs = []
        for _, g in enumerate(font.ttfont.getGlyphOrder()):
            self.assertFalse(re.search(r'#\w+$', g),
                             msg="Font contains incorrectly named glyph %s" % g)
            glyphID = re.sub(r'#\w+', '', g)

            # Each GlyphID has to be unique in TTX
            self.assertFalse(glyphID in glyphs,
                             msg="GlyphID %s occurs twice in TTX" % g)
            glyphs.append(glyphs)
Пример #30
0
    def test_metrics_linegaps_are_zero(self):
        """ Check that linegaps in tables are zero """
        dirname = os.path.dirname(self.operator.path)

        directory = UpstreamDirectory(dirname)

        fonts_gaps_are_not_zero = []
        for filename in directory.BIN:
            ttfont = Font.get_ttfont(os.path.join(dirname, filename))
            if bool(ttfont.linegaps.os2typo) or bool(ttfont.linegaps.hhea):
                fonts_gaps_are_not_zero.append(filename)

        if fonts_gaps_are_not_zero:
            _ = '[%s] have not zero linegaps'
            self.fail(_ % ', '.join(fonts_gaps_are_not_zero))
Пример #31
0
    def test_metrics_linegaps_are_zero(self):
        """ Check that linegaps in tables are zero """
        dirname = os.path.dirname(self.operator.path)

        directory = UpstreamDirectory(dirname)

        fonts_gaps_are_not_zero = []
        for filename in directory.BIN:
            ttfont = Font.get_ttfont(os.path.join(dirname, filename))
            if bool(ttfont.linegaps.os2typo) or bool(ttfont.linegaps.hhea):
                fonts_gaps_are_not_zero.append(filename)

        if fonts_gaps_are_not_zero:
            _ = '[%s] have not zero linegaps'
            self.fail(_ % ', '.join(fonts_gaps_are_not_zero))
    def test_license_included_in_font_names(self):
        """ Check font has a correct license url """
        font = Font.get_ttfont(self.path)

        regex = re.compile(
            r'^(?:http|ftp)s?://'  # http:// or https://
            r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+'
            r'(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|'  # domain...
            r'localhost|'  # localhost...
            r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})'  # ...or ip
            r'(?::\d+)?'  # optional port
            r'(?:/?|[/?]\S+)$', re.IGNORECASE)

        if not regex.match(font.license_url):
            self.fail("LicenseUrl is required and must be correct url")
Пример #33
0
    def test_license_included_in_font_names(self):
        """ Check font has a correct license url """
        font = Font.get_ttfont(self.operator.path)

        regex = re.compile(
            r'^(?:http|ftp)s?://'  # http:// or https://
            r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+'
            r'(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|'  # domain...
            r'localhost|'  # localhost...
            r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})'  # ...or ip
            r'(?::\d+)?'  # optional port
            r'(?:/?|[/?]\S+)$', re.IGNORECASE)

        if not regex.match(font.license_url):
            self.fail("LicenseUrl is required and must be correct url")
    def test_check_names_same_across_platforms(self):
        """ Font names are same across specific-platforms """
        font = Font.get_ttfont(self.operator.path)

        for name in font.names:
            for name2 in font.names:
                if name.nameID != name2.nameID:
                    continue

                if self.diff_platform(name, name2) or self.diff_platform(name2, name):
                    _name = Font.bin2unistring(name)
                    _name2 = Font.bin2unistring(name2)
                    if _name != _name2:
                        msg = ('Names in "name" table are not the same'
                               ' across specific-platforms')
                        self.fail(msg)
Пример #35
0
    def test_gpos_table_has_kerning_info(self):
        """ GPOS table has kerning information """
        font = Font.get_ttfont(self.operator.path)

        try:
            font['GPOS']
        except KeyError:
            self.fail('"GPOS" does not exist in font')
        flaglookup = False
        for lookup in font['GPOS'].table.LookupList.Lookup:
            if lookup.LookupType == 2:  # Adjust position of a pair of glyphs
                flaglookup = lookup
                break  # break for..loop to avoid reading all kerning info
        self.assertTrue(flaglookup, msg='GPOS doesnt have kerning information')
        self.assertGreater(flaglookup.SubTableCount, 0)
        self.assertGreater(flaglookup.SubTable[0].PairSetCount, 0)
Пример #36
0
    def test_source_ttf_font_filename_equals_familystyle(self):
        """ Source TTF Font filename equals family style """
        ttfont = Font.get_ttfont(self.operator.path)

        suggestedvalues = getSuggestedFontNameValues(ttfont.ttfont)

        family_name = suggestedvalues['family']
        subfamily_name = suggestedvalues['subfamily']

        expectedname = '{0}-{1}'.format(family_name.replace(' ', ''),
                                        subfamily_name.replace(' ', ''))
        actualname, extension = os.path.splitext(self.operator.path)

        expected_filename = '{0}{1}'.format(expectedname, extension)
        setattr(self, 'expectedfilename', expected_filename)
        self.assertEqual(os.path.basename(actualname), expectedname)
Пример #37
0
    def test_gpos_table_has_kerning_info(self):
        """ GPOS table has kerning information """
        font = Font.get_ttfont(self.operator.path)

        try:
            font['GPOS']
        except KeyError:
            self.fail('"GPOS" does not exist in font')
        flaglookup = False
        for lookup in font['GPOS'].table.LookupList.Lookup:
            if lookup.LookupType == 2:  # Adjust position of a pair of glyphs
                flaglookup = lookup
                break  # break for..loop to avoid reading all kerning info
        self.assertTrue(flaglookup, msg='GPOS doesnt have kerning information')
        self.assertGreater(flaglookup.SubTableCount, 0)
        self.assertGreater(flaglookup.SubTable[0].PairSetCount, 0)
Пример #38
0
def fix(fontpath):
    ttfont = Font.get_ttfont(fontpath)

    values = getSuggestedFontNameValues(ttfont.ttfont)

    family_name = values['family']

    subfamily_name = values['subfamily']

    for pair in [[4, 3, 1], [4, 1, 0]]:
        name = ttfont.ttfont['name'].getName(*pair)
        if name:
            name.string = ' '.join(
                [family_name.replace(' ', ''),
                 subfamily_name]).encode('utf_16_be')

    for pair in [[6, 3, 1], [6, 1, 0]]:
        name = ttfont.ttfont['name'].getName(*pair)
        if name:
            name.string = '-'.join([
                family_name.replace(' ', ''),
                subfamily_name.replace(' ', '')
            ]).encode('utf_16_be')

    for pair in [[1, 3, 1], [1, 1, 0]]:
        name = ttfont.ttfont['name'].getName(*pair)
        if name:
            name.string = family_name.replace(' ', '').encode('utf_16_be')

    for pair in [[2, 3, 1], [2, 1, 0]]:
        name = ttfont.ttfont['name'].getName(*pair)
        if name:
            name.string = subfamily_name.encode('utf_16_be')

    ot_namerecord = findOrCreateNameRecord(ttfont['name'], 16)
    ot_namerecord.string = family_name.replace(' ', '').encode("utf_16_be")

    ot_namerecord = findOrCreateNameRecord(ttfont['name'], 17)
    ot_namerecord.string = mapping.get(subfamily_name,
                                       'Regular').encode("utf_16_be")

    ot_namerecord = findOrCreateNameRecord(ttfont['name'], 18)
    ot_namerecord.string = ' '.join(
        [family_name.replace(' ', ''),
         mapping.get(subfamily_name, 'Regular')]).encode("utf_16_be")

    ttfont.save(fontpath + '.fix')
 def test_Check_Postscriptname_Glyph_Conventions(self):
     """ Check glyphs names comply with PostScript conventions """
     font = Font.get_ttfont(self.path)
     for glyph in font.glyphs():
         if glyph == '.notdef':
             continue
         if not re.match('(^[.0-9])[a-zA-Z_][a-zA-Z_0-9]{,30}', glyph):
             self.fail(
                 ('Glyph "%s" does not comply conventions.'
                  ' A glyph name may be up to 31 characters in length,'
                  ' must be entirely comprised of characters from'
                  ' the following set:'
                  ' A-Z a-z 0-9 .(period) _(underscore). and must not'
                  ' start with a digit or period. The only exception'
                  ' is the special character ".notdef". "twocents",'
                  ' "a1", and "_" are valid glyph names. "2cents"'
                  ' and ".twocents" are not.'))
Пример #40
0
    def test_glyphname_does_not_contain_disallowed_chars(self):
        """ GlyphName length < 30 and does contain allowed chars only """
        font = Font.get_ttfont(self.operator.path)

        for _, glyphName in enumerate(font.ttfont.getGlyphOrder()):
            if glyphName == '.notdef':
                continue
            if not re.match(r'(?![.0-9])[a-zA-Z_][a-zA-Z_0-9]{,30}', glyphName):
                self.fail(('Glyph "%s" does not comply conventions.'
                           ' A glyph name may be up to 31 characters in length,'
                           ' must be entirely comprised of characters from'
                           ' the following set:'
                           ' A-Z a-z 0-9 .(period) _(underscore). and must not'
                           ' start with a digit or period. The only exception'
                           ' is the special character ".notdef". "twocents",'
                           ' "a1", and "_" are valid glyph names. "2cents"'
                           ' and ".twocents" are not.') % glyphName)
Пример #41
0
    def test_check_names_same_across_platforms(self):
        """ Font names are same across specific-platforms """
        font = Font.get_ttfont(self.operator.path)

        for name in font.names:
            for name2 in font.names:
                if name.nameID != name2.nameID:
                    continue

                if self.diff_platform(name, name2) \
                        or self.diff_platform(name2, name):
                    _name = Font.bin2unistring(name)
                    _name2 = Font.bin2unistring(name2)
                    if _name != _name2:
                        msg = ('Names in "name" table are not the same'
                               ' across specific-platforms')
                        self.fail(msg)
    def test_glyphname_does_not_contain_disallowed_chars(self):
        """ GlyphName length < 30 and does contain allowed chars only """
        font = Font.get_ttfont(self.operator.path)

        for _, glyphName in enumerate(font.ttfont.getGlyphOrder()):
            if glyphName == '.notdef':
                continue
            if not re.match(r'(?![.0-9])[a-zA-Z_][a-zA-Z_0-9]{,30}', glyphName):
                self.fail(('Glyph "%s" does not comply conventions.'
                           ' A glyph name may be up to 31 characters in length,'
                           ' must be entirely comprised of characters from'
                           ' the following set:'
                           ' A-Z a-z 0-9 .(period) _(underscore). and must not'
                           ' start with a digit or period. The only exception'
                           ' is the special character ".notdef". "twocents",'
                           ' "a1", and "_" are valid glyph names. "2cents"'
                           ' and ".twocents" are not.') % glyphName)
Пример #43
0
    def test_check_gasp_table_type(self):
        """ Font table gasp should be 15 """
        font = Font.get_ttfont(self.operator.path)
        try:
            font['gasp']
        except KeyError:
            self.fail('"GASP" table not found')

        if not isinstance(font['gasp'].gaspRange, dict):
            self.fail('GASP.gaspRange method value have wrong type')

        if 65535 not in font['gasp'].gaspRange:
            self.fail("GASP does not have 65535 gaspRange")

        # XXX: Needs review
        if font['gasp'].gaspRange[65535] != 15:
            self.fail('gaspRange[65535] value is not 15')
Пример #44
0
    def test_check_nbsp_width_matches_sp_width(self):
        """ Check non-breaking space's advancewidth is the same as space """
        tf = Font.get_ttfont(self.operator.path)

        space = getGlyph(tf.ttfont, 0x0020)
        nbsp = getGlyph(tf.ttfont, 0x00A0)

        _ = "Font does not contain a space glyph"
        self.assertTrue(space, _)
        _ = "Font does not contain a nbsp glyph"
        self.assertTrue(nbsp, _)

        _ = ("The nbsp advance width does not match "
             "the space advance width")

        spaceWidth = getWidth(tf.ttfont, space)
        nbspWidth = getWidth(tf.ttfont, nbsp)
        self.assertEqual(spaceWidth, nbspWidth, _)
Пример #45
0
    def test_check_glyf_table_length(self):
        """ Check if there is unused data at the end of the glyf table """
        font = Font.get_ttfont(self.operator.path)

        expected = font.get_loca_length()
        actual = font.get_glyf_length()
        diff = actual - expected

        # allow up to 3 bytes of padding
        if diff > 3:
            _ = ("Glyf table has unreachable data at the end of the table."
                 " Expected glyf table length %s (from loca table), got length"
                 " %s (difference: %s)") % (expected, actual, diff)
            self.fail(_)
        elif diff < 0:
            _ = ("Loca table references data beyond the end of the glyf table."
                 " Expected glyf table length %s (from loca table), got length"
                 " %s (difference: %s)") % (expected, actual, diff)
            self.fail(_)
Пример #46
0
    def test_check_glyf_table_length(self):
        """ Check if there is unused data at the end of the glyf table """
        font = Font.get_ttfont(self.operator.path)

        expected = font.get_loca_length()
        actual = font.get_glyf_length()
        diff = actual - expected

        # allow up to 3 bytes of padding
        if diff > 3:
            _ = ("Glyf table has unreachable data at the end of the table."
                 " Expected glyf table length %s (from loca table), got length"
                 " %s (difference: %s)") % (expected, actual, diff)
            self.fail(_)
        elif diff < 0:
            _ = ("Loca table references data beyond the end of the glyf table."
                 " Expected glyf table length %s (from loca table), got length"
                 " %s (difference: %s)") % (expected, actual, diff)
            self.fail(_)
Пример #47
0
    def test_check_full_font_name_begins_with_family_name(self):
        """ Check if full font name begins with the font family name """
        font = Font.get_ttfont(self.operator.path)
        for entry in font.names:
            if entry.nameID != 1:
                continue
            for entry2 in font.names:
                if entry2.nameID != 4:
                    continue
                if (entry.platformID == entry2.platformID
                        and entry.platEncID == entry2.platEncID
                        and entry.langID == entry2.langID):

                    entry2value = Font.bin2unistring(entry2)
                    entryvalue = Font.bin2unistring(entry)
                    if not entry2value.startswith(entryvalue):
                        _ = ('Full font name does not begin with family'
                             ' name: FontFamilyName = "%s";'
                             ' FullFontName = "%s"')
                        self.fail(_ % (entryvalue, entry2value))
Пример #48
0
    def test_check_full_font_name_begins_with_family_name(self):
        """ Check if full font name begins with the font family name """
        font = Font.get_ttfont(self.operator.path)
        for entry in font.names:
            if entry.nameID != 1:
                continue
            for entry2 in font.names:
                if entry2.nameID != 4:
                    continue
                if (entry.platformID == entry2.platformID
                        and entry.platEncID == entry2.platEncID
                        and entry.langID == entry2.langID):

                    entry2value = Font.bin2unistring(entry2)
                    entryvalue = Font.bin2unistring(entry)
                    if not entry2value.startswith(entryvalue):
                        _ = ('Full font name does not begin with family'
                             ' name: FontFamilyName = "%s";'
                             ' FullFontName = "%s"')
                        self.fail(_ % (entryvalue, entry2value))