def test_us_weight(self): "Tests the usWeight of the fonts to be correct." "" for font in self.fonts: weight = roboto_data.extract_weight_name(font_data.font_name(font)) expected_numeric_weight = roboto_data.WEIGHTS[weight] self.assertEqual(font['OS/2'].usWeightClass, expected_numeric_weight)
def test_inclusion_of_sound_recording_copyright(self): """Tests that sound recording copyright symbol is in the fonts.""" for font in self.fonts: charset = coverage.character_set(font) self.assertIn( 0x2117, charset, # SOUND RECORDING COPYRIGHT 'U+2117 not found in %s.' % font_data.font_name(font))
def parse_metadata(self, font): """Parse font name to infer weight and slope.""" font_name = font_data.font_name(font) bold = ('Bold' in font_name) or (self.mark_heavier_as_bold and 'Black' in font_name) italic = 'Italic' in font_name return bold, italic
def parse_metadata(self, font): """Parse font name to infer weight and slope.""" font_name = font_data.font_name(font) bold = ('Bold' in font_name) or ( self.mark_heavier_as_bold and 'Black' in font_name) italic = 'Italic' in font_name return bold, italic
def test_us_weight(self): "Tests the usWeight of the fonts to be correct.""" for font in self.fonts: weight = noto_fonts.parse_weight(font_data.font_name(font)) expected_numeric_weight = noto_fonts.WEIGHTS[weight] self.assertEqual( font['OS/2'].usWeightClass, expected_numeric_weight)
def test_us_weight(self): "Tests the usWeight of the fonts to be correct." "" for font in self.fonts: weight = noto_fonts.parse_weight(font_data.font_name(font)) expected_numeric_weight = noto_fonts.WEIGHTS[weight] # hack for windows GDI expected_numeric_weight = max(expected_numeric_weight, 250) self.assertEqual(font['OS/2'].usWeightClass, expected_numeric_weight)
def test_italic_angle(self): """Tests the italic angle of fonts to be correct.""" for font in self.fonts: post_table = font['post'] if 'Italic' in font_data.font_name(font): expected_angle = self.expected_italic_angle else: expected_angle = 0.0 self.assertEqual(post_table.italicAngle, expected_angle)
def test_mac_style(self): """Tests the macStyle of the fonts to be correct.""" for font in self.fonts: font_name = font_data.font_name(font) bold = ('Bold' in font_name) or (self.mark_heavier_as_bold and 'Black' in font_name) italic = 'Italic' in font_name expected_mac_style = (italic << 1) | bold self.assertEqual(font['head'].macStyle, expected_mac_style)
def test_mac_style(self): """Tests the macStyle of the fonts to be correct.""" for font in self.fonts: font_name = font_data.font_name(font) bold = ('Bold' in font_name) or ( self.mark_heavier_as_bold and 'Black' in font_name) italic = 'Italic' in font_name expected_mac_style = (italic << 1) | bold self.assertEqual(font['head'].macStyle, expected_mac_style)
def test_mac_style(self): """Tests the macStyle of the fonts to be correct. Bug: https://code.google.com/a/google.com/p/roboto/issues/detail?id=8 """ for font in self.fonts: font_name = font_data.font_name(font) bold = ('Bold' in font_name) or ('Black' in font_name) italic = 'Italic' in font_name expected_mac_style = (italic << 1) | bold self.assertEqual(font['head'].macStyle, expected_mac_style)
def output_protruding_glyphs(font, ymin, ymax): """Outputs all glyphs going outside the specified vertical range.""" protruding_glyphs = [] glyf_table = font['glyf'] for glyph_name in glyf_table.keys(): glyph = glyf_table[glyph_name] if glyph.numberOfContours == 0: continue if glyph.yMin < ymin or glyph.yMax > ymax: protruding_glyphs.append(glyph_name) if protruding_glyphs: print("Protruding glyphs in %s:" % font_data.font_name(font)) print(', '.join(sorted(protruding_glyphs)))
def apply_temporary_fixes(font): """Apply some temporary fixes.""" # Fix usWeight: font_name = font_data.font_name(font) weight = noto_fonts.parse_weight(font_name) weight_number = noto_fonts.WEIGHTS[weight] font['OS/2'].usWeightClass = weight_number # Set ascent, descent, and lineGap values to Android K values hhea = font['hhea'] hhea.ascent = 1900 hhea.descent = -500 hhea.lineGap = 0
def output_protruding_glyphs(font, ymin, ymax): """Outputs all glyphs going outside the specified vertical range.""" protruding_glyphs = [] glyf_table = font['glyf'] for glyph_name in glyf_table.keys(): glyph = glyf_table[glyph_name] if glyph.numberOfContours == 0: continue if glyph.yMin < ymin or glyph.yMax > ymax: protruding_glyphs.append(glyph_name) if protruding_glyphs: print "Protruding glyphs in %s:" % font_data.font_name(font), print ', '.join(sorted(protruding_glyphs))
def test_existance_of_hints(self): """Tests all glyphs and makes sure non-composite ones have hints.""" missing_hints = [] for font in self.fonts: glyf_table = font['glyf'] for glyph_name in font.getGlyphOrder(): glyph = glyf_table[glyph_name] if glyph.numberOfContours <= 0: # composite or empty glyph continue if len(glyph.program.bytecode) <= 0: missing_hints.append( (glyph_name, font_data.font_name(font))) self.assertTrue(missing_hints == [])
def apply_temporary_fixes(font): """Apply some temporary fixes.""" # Fix usWeight: font_name = font_data.font_name(font) weight = roboto_data.extract_weight_name(font_name) weight_number = roboto_data.WEIGHTS[weight] font['OS/2'].usWeightClass = weight_number # Set ascent, descent, and lineGap values to Android K values hhea = font['hhea'] hhea.ascent = 1900 hhea.descent = -500 hhea.lineGap = 0 # Copyright message font_data.set_name_record( font, 0, 'Copyright 2011 Google Inc. All Rights Reserved.')
def apply_temporary_fixes(font): """Apply some temporary fixes.""" # Fix usWeight: font_name = font_data.font_name(font) weight = noto_fonts.parse_weight(font_name) weight_number = noto_fonts.WEIGHTS[weight] font['OS/2'].usWeightClass = weight_number # Set ascent, descent, and lineGap values to Android K values hhea = font['hhea'] hhea.ascent = 1900 hhea.descent = -500 hhea.lineGap = 0 # Copyright message font_data.set_name_record( font, 0, 'Copyright 2011 Google Inc. All Rights Reserved.')
def main(): """Checkes the coverage of all Roboto fonts.""" with open('res/char_requirements.tsv') as char_reqs_file: char_reqs_data = char_reqs_file.read() # The format of the data to be parsed is like the following: # General Punctuation\t2000..206F\t111\t35\t54\t0\tEverything except 2028..202E, 2060..2064, and 2066..206F # Currency Symbols\t20A0..20CF\t29\t5\t24\t1\t required_set = set() for line in char_reqs_data.split('\n'): if line.startswith('#'): # Skip comment lines continue line = line.split('\t') if not line[0]: continue # Skip the first line and empty lines block_range = line[1] full_coverage_required = (line[5] == '1') exceptions = line[6] required_set.update( _find_required_chars(block_range, full_coverage_required, exceptions)) # Skip Unicode 8.0 characters required_set = { ch for ch in required_set if float(unicode_data.age(ch)) <= 7.0 } # Skip ASCII and C1 controls required_set -= set(range(0, 0x20) + range(0x7F, 0xA0)) missing_char_found = False for font in load_fonts(): font_coverage = coverage.character_set(font) missing_chars = required_set - font_coverage if missing_chars: missing_char_found = True font_name = font_data.font_name(font) print 'Characters missing from %s:' % font_name for char in sorted(missing_chars): _print_char(char) print if missing_char_found: sys.exit(1)
def apply_temporary_fixes(font, is_for_cros=False): """Apply some temporary fixes.""" # Fix usWeight: font_name = font_data.font_name(font) weight = noto_fonts.parse_weight(font_name) weight_number = noto_fonts.WEIGHTS[weight] # Chrome OS wants Thin to have usWeightClass=100 if is_for_cros and weight == 'Thin': weight_number = 100 font['OS/2'].usWeightClass = weight_number # Set bold bits for Black (macStyle bit 0, fsSelection bit 5) name_records = font_data.get_name_records(font) family_name = name_records[1] if family_name.endswith('Black'): font['head'].macStyle |= (1 << 0) font['OS/2'].fsSelection |= (1 << 5) font['OS/2'].fsSelection &= ~(1 << 6)
def main(): """Checkes the coverage of all Roboto fonts.""" with open('res/char_requirements.tsv') as char_reqs_file: char_reqs_data = char_reqs_file.read() # The format of the data to be parsed is like the following: # General Punctuation\t2000..206F\t111\t35\t54\t0\tEverything except 2028..202E, 2060..2064, and 2066..206F # Currency Symbols\t20A0..20CF\t29\t5\t24\t1\t required_set = set() for line in char_reqs_data.split('\n'): if line.startswith('#'): # Skip comment lines continue line = line.split('\t') if not line[0]: continue # Skip the first line and empty lines block_range = line[1] full_coverage_required = (line[5] == '1') exceptions = line[6] required_set.update( _find_required_chars(block_range, full_coverage_required, exceptions)) # Skip Unicode 8.0 characters required_set = {ch for ch in required_set if float(unicode_data.age(ch)) <= 7.0} # Skip ASCII and C1 controls required_set -= set(range(0, 0x20) + range(0x7F, 0xA0)) missing_char_found = False for font in load_fonts(): font_coverage = coverage.character_set(font) missing_chars = required_set - font_coverage if missing_chars: missing_char_found = True font_name = font_data.font_name(font) print 'Characters missing from %s:' % font_name for char in sorted(missing_chars): _print_char(char) print if missing_char_found: sys.exit(1)
def fix_font(src_root, dst_root, file_path, is_hinted, save_unmodified): """Fix font under src_root and write to similar path under dst_root, modulo fixes to the filename. If is_hinted is false, strip hints. If unmodified, don't write destination unless save_unmodified is true.""" src_file = os.path.join(src_root, file_path) print 'Font file: %s' % src_file font = ttLib.TTFont(src_file) modified = False modified |= fix_revision(font) modified |= fix_fstype(font) modified |= fix_vendor_id(font) modified |= fix_name_table(font) modified |= fix_attachlist(font) modified |= fix_os2_unicoderange(font) # leave line gap for non-noto fonts alone, metrics are more constrained there if font_data.font_name(font).find('Noto') != -1: modified |= fix_linegap(font) tables_to_drop = TABLES_TO_DROP if not is_hinted: modified |= drop_hints(font) tables_to_drop += ['fpgm', 'prep', 'cvt'] modified |= drop_tables(font, tables_to_drop) fixed_path = fix_path(file_path, is_hinted) if fixed_path != file_path: print 'changed file_path from "%s" to "%s"' % (file_path, fixed_path) modified = True if not modified: print 'No modification necessary' if modified or save_unmodified: # wait until we need it before we create the dest directory dst_file = os.path.join(dst_root, fixed_path) dst_dir = path.dirname(dst_file) if not path.isdir(dst_dir): os.makedirs(dst_dir) font.save(dst_file) print 'Wrote %s' % dst_file
def apply_temporary_fixes(font): """Apply some temporary fixes.""" # Fix usWeight: font_name = font_data.font_name(font) weight = noto_fonts.parse_weight(font_name) weight_number = noto_fonts.WEIGHTS[weight] font['OS/2'].usWeightClass = weight_number # Set ascent, descent, and lineGap values to Android K values hhea = font['hhea'] hhea.ascent = 1900 hhea.descent = -500 hhea.lineGap = 0 # Set bold bits for Black (macStyle bit 0, fsSelection bit 5) name_records = font_data.get_name_records(font) family_name = name_records[1] if family_name.endswith('Black'): font['head'].macStyle |= (1 << 0) font['OS/2'].fsSelection |= (1 << 5) font['OS/2'].fsSelection &= ~(1 << 6)