def test_metadata_family(self): """ Font and METADATA.json have the same name """ for font_metadata in self.metadata.fonts: font = Font.get_ttfont_from_metadata(self.path, font_metadata) if font.familyname != font_metadata.name: msg = 'Family name in TTF is "%s" but in METADATA "%s"' self.fail(msg % (font.familyname, font_metadata.name))
def test_check_menu_contains_proper_glyphs(self): """ Check menu file contains proper glyphs """ contents = self.read_metadata_contents() fm = Metadata.get_family_metadata(contents) for font_metadata in fm.fonts: tf = Font.get_ttfont_from_metadata(self.path, font_metadata, is_menu=True) self.check_retrieve_glyphs(tf, font_metadata)
def test_check_normal_style_matches_names(self): """ Check metadata.json font.style `italic` matches font internal """ contents = self.read_metadata_contents() family = Metadata.get_family_metadata(contents) for font_metadata in family.fonts: if font_metadata.style != 'normal': continue font = Font.get_ttfont_from_metadata(self.path, font_metadata) if bool(font.macStyle & 0b10): self.fail(('Metadata style has been set to normal' ' but font second bit (italic) in macStyle has' ' been set')) style = font.familyname.split('-')[-1] if style.endswith('Italic'): self.fail(('macStyle second bit is not set but postScriptName "%s"' ' is ended with "Italic"') % font.familyname) style = font.fullname.split('-')[-1] if style.endswith('Italic'): self.fail(('macStyle second bit is not set but fullName "%s"' ' is ended with "Italic"') % font.fullname)
def test_metrics_descents_equal_bbox(self): """ Check that descents values are same as min glyph point """ contents = self.read_metadata_contents() family_metadata = Metadata.get_family_metadata(contents) fonts_descents_not_bbox = [] ymin = 0 _cache = {} for font_metadata in family_metadata.fonts: ttfont = Font.get_ttfont_from_metadata(self.path, font_metadata) ymin_, ymax_ = ttfont.get_bounding() ymin = min(ymin, ymin_) _cache[font_metadata.filename] = { 'os2typo': abs(ttfont.descents.os2typo), 'os2win': abs(ttfont.descents.os2win), 'hhea': abs(ttfont.descents.hhea) } for filename, data in _cache.items(): if [data['os2typo'], data['os2win'], data['hhea']] != [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_font_name_matches_family(self): """ METADATA.json fonts 'name' property should be same as font familyname """ for font_metadata in self.metadata.fonts: font = Font.get_ttfont_from_metadata(self.path, font_metadata) if font_metadata.name != font.familyname: msg = '"fonts.name" property is not the same as TTF familyname' self.fail(msg)
def test_the_same_names_of_glyphs_across_family(self): """ The same names of glyphs across family? """ glyphs = None for font_metadata in self.familymetadata.fonts: ttfont = Font.get_ttfont_from_metadata(self.path, font_metadata) if not glyphs: glyphs = len(ttfont.glyphs) if glyphs != len(ttfont.glyphs): self.fail('Family has a different glyphs\'s names in fonts')
def test_the_same_number_of_glyphs_across_family(self): """ The same number of glyphs across family? """ glyphs_count = 0 for font_metadata in self.familymetadata.fonts: ttfont = Font.get_ttfont_from_metadata(self.path, font_metadata) if not glyphs_count: glyphs_count = len(ttfont.glyphs) if glyphs_count != len(ttfont.glyphs): self.fail('Family has a different glyphs\'s count in fonts')
def test_postscriptname_contains_correct_weight(self): """ Metadata weight matches postScriptName """ contents = self.read_metadata_contents() fm = Metadata.get_family_metadata(contents) for font_metadata in fm.fonts: font = Font.get_ttfont_from_metadata(self.path, font_metadata) if font.OS2_usWeightClass != font_metadata.weight: msg = 'METADATA.JSON has weight %s but in TTF it is %s' self.fail(msg % (font_metadata.weight, font.OS2_usWeightClass))
def test_check_metadata_matches_nametable(self): contents = self.read_metadata_contents() fm = Metadata.get_family_metadata(contents) for font_metadata in fm.fonts: ttfont = Font.get_ttfont_from_metadata(self.path, font_metadata) report = '%s: Family name was supposed to be "%s" but is "%s"' report = report % (font_metadata.name, fm.name, ttfont.familyname) self.assertEqual(ttfont.familyname, fm.name, report) self.assertEqual(ttfont.fullname, font_metadata.full_name)
def test_the_same_encodings_of_glyphs_across_family(self): """ The same unicode encodings of glyphs across family? """ encoding = None for font_metadata in self.familymetadata.fonts: ttfont = Font.get_ttfont_from_metadata(self.path, font_metadata) cmap = ttfont.retrieve_cmap_format_4() if not encoding: encoding = cmap.platEncID if encoding != cmap.platEncID: self.fail('Family has different encoding across fonts')
def test_metadata_fonts_fields_have_fontname(self): """ METADATA.json fonts items fields "name", "postScriptName", "fullName", "filename" contains font name right format """ for x in self.metadata.fonts: font = Font.get_ttfont_from_metadata(self.path, x) self.assertIn(font.familyname, x.name) self.assertIn(font.familyname, x.full_name) self.assertIn("".join(str(font.familyname).split()), x.filename) self.assertIn("".join(str(font.familyname).split()), x.post_script_name)
def test_metrics_linegaps_are_zero(self): """ Check that linegaps in tables are zero """ contents = self.read_metadata_contents() family_metadata = Metadata.get_family_metadata(contents) fonts_gaps_are_not_zero = [] for font_metadata in family_metadata.fonts: ttfont = Font.get_ttfont_from_metadata(self.path, font_metadata) if bool(ttfont.linegaps.os2typo) or bool(ttfont.linegaps.hhea): fonts_gaps_are_not_zero.append(font_metadata.filename) if fonts_gaps_are_not_zero: _ = '[%s] have not zero linegaps' self.fail(_ % ', '.join(fonts_gaps_are_not_zero))
def test_check_nbsp_width_matches_sp_width(self): """ Check NO-BREAK SPACE advanceWidth is the same as SPACE """ contents = self.read_metadata_contents() fm = Metadata.get_family_metadata(contents) for font_metadata in fm.fonts: tf = Font.get_ttfont_from_metadata(self.path, font_metadata) space_advance_width = tf.advance_width('space') nbsp_advance_width = tf.advance_width('uni00A0') _ = "%s: The font does not contain a sp glyph" self.assertTrue(space_advance_width, _ % font_metadata.filename) _ = "%s: The font does not contain a nbsp glyph" self.assertTrue(nbsp_advance_width, _ % font_metadata.filename) _ = ("%s: The nbsp advance width does not match " "the sp advance width") % font_metadata.filename self.assertEqual(space_advance_width, nbsp_advance_width, _)
def test_check_canonical_weights(self): """ Check that weights have canonical value """ contents = self.read_metadata_contents() fm = Metadata.get_family_metadata(contents) for font_metadata in fm.fonts: weight = font_metadata.weight first_digit = weight / 100 is_invalid = (weight % 100) != 0 or (first_digit < 1 or first_digit > 9) _ = ("%s: The weight is %d which is not a " "multiple of 100 between 1 and 9") self.assertFalse(is_invalid, _ % (op.basename(self.path), font_metadata.weight)) tf = Font.get_ttfont_from_metadata(self.path, font_metadata) _ = ("%s: METADATA.json overwrites the weight. " " The METADATA.json weight is %d and the font" " file %s weight is %d") _ = _ % (font_metadata.filename, font_metadata.weight, font_metadata.filename, tf.OS2_usWeightClass) self.assertEqual(tf.OS2_usWeightClass, font_metadata.weight)
def test_metadata_contains_current_font(self): """ METADATA.json should contains testing font, under canonic name""" contents = self.read_metadata_contents() fm = Metadata.get_family_metadata(contents) for font_metadata in fm.fonts: font = Font.get_ttfont_from_metadata(self.path, font_metadata) _weights = [] for value, intvalue in weights.items(): if intvalue == font.OS2_usWeightClass: _weights.append(value) for w in _weights: current_font = "%s %s" % (font.familyname, w) if font_metadata.full_name != current_font: is_canonical = True if not is_canonical: v = map(lambda x: font.familyname + ' ' + x, _weights) msg = 'Canonical name in font expected: [%s] but %s' self.fail(msg % (v, font_metadata.full_name))
def test_metadata_postScriptName_matches_ttf_fontname(self): """ Checks METADATA.json 'postScriptName' matches TTF 'postScriptName' """ for font_metadata in self.metadata.fonts: font = Font.get_ttfont_from_metadata(self.path, font_metadata) self.assertEqual(font.post_script_name, font_metadata.post_script_name)
def test_metadata_fullname_is_equal_to_internal_font_fullname(self): """ METADATA.json 'fullname' value matches internal 'fullname' """ for font_metadata in self.metadata.fonts: font = Font.get_ttfont_from_metadata(self.path, font_metadata) self.assertEqual(font.fullname, font_metadata.full_name)
def is_italic(self, font_metadata): ttfont = Font.get_ttfont_from_metadata(self.path, font_metadata) return (ttfont.macStyle & self.ITALIC_MASK or ttfont.italicAngle or self.find_italic_in_name_table(ttfont))