def fix_font(f, dstdir, version_info, autohint, dry_run): print '\n-----\nfont:', f font = ttLib.TTFont(f) fname = path.basename(f) expected_font_revision = get_revision(font, fname) if expected_font_revision != None: font_revision = font_data.printable_font_revision(font, 3) if font_revision != expected_font_revision: _alert('revision', font_revision, expected_font_revision) font['head'].fontRevision = float(expected_font_revision) names = font_data.get_name_records(font) NAME_ID = 5 font_version = names[NAME_ID] expected_version = ( 'Version %s;%s' % (expected_font_revision, version_info)) if font_version != expected_version: _alert('version string', font_version, expected_version) font_data.set_name_record(font, NAME_ID, expected_version) expected_upem = 2048 upem = font['head'].unitsPerEm if upem != expected_upem: print 'expected %d upem but got %d upem' % (expected_upem, upem) if _is_ui_metrics(fname): if upem == 2048: expected_ascent = 2163 expected_descent = -555 elif upem == 1000: expected_ascent = 1069 expected_descent = -293 else: raise Exception('no expected ui ascent/descent for upem: %d' % upem) font_ascent = font['hhea'].ascent font_descent = font['hhea'].descent if font_ascent != expected_ascent: _alert_and_check('ascent', font_ascent, expected_ascent, 2) font['hhea'].ascent = expected_ascent font['OS/2'].sTypoAscender = expected_ascent font['OS/2'].usWinAscent = expected_ascent if font_descent != expected_descent: _alert_and_check('descent', font_descent, expected_descent, 2) font['hhea'].descent = expected_descent font['OS/2'].sTypoDescender = expected_descent font['OS/2'].usWinDescent = -expected_descent tool_utils.ensure_dir_exists(path.join(dstdir, 'unhinted')) dst = path.join(dstdir, 'unhinted', fname) if dry_run: print 'dry run would write:\n "%s"' % dst else: font.save(dst) print 'wrote %s' % dst if autohint: autohint_font(dst, path.join(dstdir, 'hinted', fname), autohint, dry_run)
def test_version_numbers(self): "Tests the two version numbers of the font to be correct." "" for font in self.fonts: version = font_data.font_version(font) usable_part_of_version = version.split(';')[0] self.assertEqual(usable_part_of_version, 'Version ' + self.expected_version) revision = font_data.printable_font_revision(font, accuracy=3) self.assertEqual(revision, self.expected_version)
def test_version_numbers(self): "Tests the two version numbers of the font to be correct.""" for font in self.fonts: version = font_data.font_version(font) usable_part_of_version = version.split(';')[0] self.assertEqual(usable_part_of_version, 'Version ' + self.expected_version) revision = font_data.printable_font_revision(font, accuracy=3) self.assertEqual(revision, self.expected_version)
def test_version_numbers(self): "Tests the two version numbers of the font to be correct.""" for font in self.fonts: build_number = roboto_data.get_build_number() expected_version = '2.' + build_number version = font_data.font_version(font) usable_part_of_version = version.split(';')[0] self.assertEqual(usable_part_of_version, 'Version ' + expected_version) revision = font_data.printable_font_revision(font, accuracy=5) self.assertEqual(revision, expected_version)
def test_version_numbers(self): "Tests the two version numbers of the font to be correct." "" for font in self.fonts: build_number = roboto_data.get_build_number() expected_version = '2.' + build_number version = font_data.font_version(font) usable_part_of_version = version.split(';')[0] self.assertEqual(usable_part_of_version, 'Version ' + expected_version) revision = font_data.printable_font_revision(font, accuracy=5) self.assertEqual(revision, expected_version)
def get_bumped_version(ttfont, is_hinted=None): """Return bumped values for the header and name tables.""" names = font_data.get_name_records(ttfont) version = names[_VERSION_ID] m = re.match(r'Version (\d{1,5})\.(\d{1,5})( uh)?(;.*)?', version) if not m: print('! Could not match version string (%s)' % version) return None, None major_version = m.group(1) minor_version = m.group(2) print('old version: "%s"' % version) if is_hinted == None: is_hinted = not bool(m.group(3)) print('computed hinted = %s' % is_hinted) version_remainder = m.group(4) accuracy = len(minor_version) print_revision = font_data.printable_font_revision(ttfont, accuracy) # sanity check expected_revision = major_version + '.' + minor_version if expected_revision != print_revision: raise ValueError('! Expected revision \'%s\' but got revision \'%s\'' % (expected_revision, print_revision)) # bump the minor version keeping significant digits: new_minor_version = str(int(minor_version) + 1).zfill(accuracy) new_revision = major_version + '.' + new_minor_version print('Update revision from \'%s\' to \'%s\'' % (expected_revision, new_revision)) # double check we are going to properly round-trip this value float_revision = float(new_revision) fixed_revision = misc.fixedTools.floatToFixed(float_revision, 16) rt_float_rev = misc.fixedTools.fixedToFloat(fixed_revision, 16) rt_float_rev_int = int(rt_float_rev) rt_float_rev_frac = int( round((rt_float_rev - rt_float_rev_int) * 10**accuracy)) rt_new_revision = (str(rt_float_rev_int) + '.' + str(rt_float_rev_frac).zfill(accuracy)) if new_revision != rt_new_revision: raise ValueError( '! Could not update new revision, expected \'%s\' but got \'%s\'' % (new_revision, rt_new_revision)) new_version_string = 'Version ' + new_revision if not is_hinted: new_version_string += ' uh' if version_remainder: new_version_string += version_remainder return float_revision, new_version_string
def get_bumped_version(ttfont, is_hinted=None): """Return bumped values for the header and name tables.""" names = font_data.get_name_records(ttfont) version = names[_VERSION_ID] m = re.match(r'Version (\d{1,5})\.(\d{1,5})( uh)?(;.*)?', version) if not m: print '! Could not match version string (%s)' % version return None, None major_version = m.group(1) minor_version = m.group(2) print 'old version: "%s"' % version if is_hinted == None: is_hinted = not bool(m.group(3)) print 'computed hinted = %s' % is_hinted version_remainder = m.group(4) accuracy = len(minor_version) print_revision = font_data.printable_font_revision(ttfont, accuracy) # sanity check expected_revision = major_version + '.' + minor_version if expected_revision != print_revision: raise ValueError('! Expected revision \'%s\' but got revision \'%s\'' % ( expected_revision, print_revision)) # bump the minor version keeping significant digits: new_minor_version = str(int(minor_version) + 1).zfill(accuracy) new_revision = major_version + '.' + new_minor_version print 'Update revision from \'%s\' to \'%s\'' % ( expected_revision, new_revision) # double check we are going to properly round-trip this value float_revision = float(new_revision) fixed_revision = misc.fixedTools.floatToFixed(float_revision, 16) rt_float_rev = misc.fixedTools.fixedToFloat(fixed_revision, 16) rt_float_rev_int = int(rt_float_rev) rt_float_rev_frac = int(round((rt_float_rev - rt_float_rev_int) * 10 ** accuracy)) rt_new_revision = (str(rt_float_rev_int) + '.' + str(rt_float_rev_frac).zfill(accuracy)) if new_revision != rt_new_revision: raise ValueError( '! Could not update new revision, expected \'%s\' but got \'%s\'' % ( new_revision, rt_new_revision)) new_version_string = 'Version ' + new_revision if not is_hinted: new_version_string += ' uh' if version_remainder: new_version_string += version_remainder return float_revision, new_version_string
def fix_revision(font): """Fix the revision of the font to match its version.""" version = font_data.font_version(font) match = re.match(r'Version (\d{1,5})\.(\d{1,5})', version) major_version = match.group(1) minor_version = match.group(2) accuracy = len(minor_version) font_revision = font_data.printable_font_revision(font, accuracy) expected_font_revision = major_version + '.' + minor_version if font_revision != expected_font_revision: font['head'].fontRevision = float(expected_font_revision) print 'Fixed fontRevision to %s' % expected_font_revision return True return False
def fix_revision(font): """Fix the revision of the font to match its version.""" version = font_data.font_version(font) match = re.match(r'Version (\d{1,5})\.(\d{1,5})', version) major_version = match.group(1) minor_version = match.group(2) accuracy = len(minor_version) font_revision = font_data.printable_font_revision(font, accuracy) expected_font_revision = major_version+'.'+minor_version if font_revision != expected_font_revision: font['head'].fontRevision = float(expected_font_revision) print 'Fixed fontRevision to %s' % expected_font_revision return True return False
def check_spreadsheet(src_file): filenames = set() prev_script_name = None fontdata = {} filedata = {} with open(src_file) as csvfile: reader = csv.DictReader(csvfile) for index, row in enumerate(reader): font = row['Fonts'].replace('\xc2\xa0', ' ').strip() hinting = row['Hinting'].strip() status = row['Status'].strip() accepted_version = row['Accepted Version'].strip() note = row['Note'].strip() # family script style (variant UI) weight, mostly m = re.match( r'Noto (Kufi|Naskh|Color Emoji|Emoji|Sans|Serif|Nastaliq)' r'(?: (.*?))?' r'(?: (UI))?' r' (Thin|Light|DemiLight|Regular|Medium|Bold Italic' r'|Bold|Black|Italic)(?: \(merged\))?$', font) if not m: m = re.match(r'Noto (Sans) (Myanmar) (UI)(.*)', font) if not m: print 'could not parse Myanmar exception: "%s"' % font continue style, script, ui, weight = m.groups() weight = weight or 'Regular' weight = weight.replace(' ', '') ui = ui or '' script = script or '' script = re.sub('-| ', '', script) style = style.replace(' ', '') ext = 'ttf' if script == 'CJK': ext = 'ttc' elif script.startswith('TTC'): ext = 'ttc' script = '' elif script == '(LGC)': script = '' elif script == 'UI': ui = 'UI' script = '' elif script == 'Phagspa': script = 'PhagsPa' elif script == 'SumeroAkkadianCuneiform': script = 'Cuneiform' fontname = ''.join(['Noto', style, script, ui, '-', weight, '.', ext]) # print '%s:\n--> %s\n--> %s' % ( # font, str((style, script, ui, weight)), fontname) if not hinting in [ 'hinted', 'hinted (CFF)', 'unhinted']: print 'unrecognized hinting value \'%s\' on line %d (%s)' % ( hinting, index, fontname) continue hinted = 'hinted' if hinting in ['hinted', 'hinted (CFF)'] else 'unhinted' if not status in [ 'In finishing', 'Released w. lint errors', 'Approved & Released', 'Approved & Not Released', 'In design', 'Design approved', 'Design re-approved', 'Released']: print 'unrecognized status value \'%s\' on line %d (%s)' % ( status, index, fontname) continue expect_font = status in [ 'Released w. lint errors', 'Approved & Released', 'Approved & Not Released', 'Released'] data = (fontname, (index, font, style, script, ui, weight), hinted, status, accepted_version, note, expect_font) filedata[hinted + '/' + fontname] = data # ok, now let's see if we can find these files all_noto = noto_fonts.get_noto_fonts() notodata = { ('hinted' if f.is_hinted else 'unhinted') + '/' + path.basename(f.filepath) : f for f in all_noto } noto_filenames = frozenset(notodata.keys()) spreadsheet_filenames = frozenset(k for k in filedata if filedata[k][6]) spreadsheet_extra = spreadsheet_filenames - noto_filenames spreadsheet_missing = noto_filenames - spreadsheet_filenames if spreadsheet_extra: print 'spreadsheet extra:\n ' + '\n '.join( sorted(spreadsheet_extra)) if spreadsheet_missing: print 'spreadsheet missing:\n ' + '\n '.join( sorted(spreadsheet_missing)) spreadsheet_match = spreadsheet_filenames & noto_filenames for filename in sorted(spreadsheet_match): data = filedata[filename] filepath = notodata[filename].filepath ttfont = ttLib.TTFont(filepath, fontNumber=0) font_version = font_data.printable_font_revision(ttfont) approved_version = data[4] if approved_version: warn = '!!!' if approved_version != font_version else '' print '%s%s version: %s approved: %s' % ( warn, filename, font_version, approved_version) else: print '%s version: %s' % (filename, font_version)
def check_spreadsheet(src_file): filenames = set() prev_script_name = None fontdata = {} filedata = {} with open(src_file) as csvfile: reader = csv.DictReader(csvfile) for index, row in enumerate(reader): font = row["Fonts"].replace("\xc2\xa0", " ").strip() hinting = row["Hinting"].strip() status = row["Status"].strip() accepted_version = row["Accepted Version"].strip() note = row["Note"].strip() # family script style (variant UI) weight, mostly m = re.match( r"Noto (Kufi|Naskh|Color Emoji|Emoji|Sans|Serif|Nastaliq|Rashi|Traditional)" r"(?: (.*?))?" r"(?: (UI))?" r" (Thin|Light|DemiLight|Regular|Medium|Bold Italic" r"|Bold|Black|Italic)(?: \(merged\))?$", font, ) if not m: m = re.match(r"Noto (Sans) (Myanmar) (UI)(.*)", font) if not m: print('could not parse Myanmar exception: "%s"' % font) continue style, script, ui, weight = m.groups() weight = weight or "Regular" weight = weight.replace(" ", "") ui = ui or "" script = script or "" script = re.sub("-| ", "", script) style = style.replace(" ", "") ext = "ttf" if script == "CJK": ext = "ttc" elif script.startswith("TTC"): ext = "ttc" script = "" elif script == "(LGC)": script = "" elif script == "UI": ui = "UI" script = "" elif script == "Phagspa": script = "PhagsPa" elif script == "SumeroAkkadianCuneiform": script = "Cuneiform" fontname = "".join(["Noto", style, script, ui, "-", weight, ".", ext]) # print('%s:\n--> %s\n--> %s' % ( # font, str((style, script, ui, weight)), fontname)) if not hinting in ["hinted", "hinted (CFF)", "unhinted"]: print( "unrecognized hinting value '%s' on line %d (%s)" % (hinting, index, fontname) ) continue hinted = "hinted" if hinting in ["hinted", "hinted (CFF)"] else "unhinted" if not status in [ "In finishing", "Released w. lint errors", "Approved & Released", "Approved & Not Released", "In design", "Design approved", "Design re-approved", "Released", ]: print( "unrecognized status value '%s' on line %d (%s)" % (status, index, fontname) ) continue expect_font = status in [ "Released w. lint errors", "Approved & Released", "Approved & Not Released", "Released", ] data = ( fontname, (index, font, style, script, ui, weight), hinted, status, accepted_version, note, expect_font, ) filedata[hinted + "/" + fontname] = data # ok, now let's see if we can find these files all_noto = noto_fonts.get_noto_fonts() notodata = { ("hinted" if f.is_hinted else "unhinted") + "/" + path.basename(f.filepath): f for f in all_noto } noto_filenames = frozenset(notodata.keys()) spreadsheet_filenames = frozenset(k for k in filedata if filedata[k][6]) spreadsheet_extra = spreadsheet_filenames - noto_filenames spreadsheet_missing = noto_filenames - spreadsheet_filenames if spreadsheet_extra: print("spreadsheet extra:\n " + "\n ".join(sorted(spreadsheet_extra))) if spreadsheet_missing: print("spreadsheet missing:\n " + "\n ".join(sorted(spreadsheet_missing))) spreadsheet_match = spreadsheet_filenames & noto_filenames for filename in sorted(spreadsheet_match): data = filedata[filename] filepath = notodata[filename].filepath ttfont = ttLib.TTFont(filepath, fontNumber=0) font_version = font_data.printable_font_revision(ttfont) approved_version = data[4] if approved_version: warn = "!!!" if approved_version != font_version else "" print( "%s%s version: %s approved: %s" % (warn, filename, font_version, approved_version) ) else: print("%s version: %s" % (filename, font_version))
def _swat_font(noto_font, dst_root, dry_run): filepath = noto_font.filepath basename = path.basename(filepath) if noto_font.is_cjk: print '# Skipping cjk font %s' % basename return if noto_font.fmt == 'ttc': print '# Deferring ttc font %s' % basename _ttc_fonts[noto_font] = ttc_utils.ttcfile_filenames(filepath) return ttfont = ttLib.TTFont(filepath, fontNumber=0) names = font_data.get_name_records(ttfont) # create relative root path rel_filepath = _noto_relative_path(filepath) if not rel_filepath: raise ValueError('Could not identify noto root of %s' % filepath) print '-----\nUpdating %s' % rel_filepath dst_file = path.join(dst_root, rel_filepath) version = names[_VERSION_ID] m = re.match(r'Version (\d{1,5})\.(\d{1,5})(.*)', version) if not m: print '! Could not match version string (%s)' % version return major_version = m.group(1) minor_version = m.group(2) version_remainder = m.group(3) accuracy = len(minor_version) print_revision = font_data.printable_font_revision(ttfont, accuracy) # sanity check expected_revision = major_version + '.' + minor_version if expected_revision != print_revision: print '! Expected revision \'%s\' but got revision \'%s\'' % ( expected_revision, print_revision) return # bump the minor version keeping significant digits: new_minor_version = str(int(minor_version) + 1).zfill(accuracy) new_revision = major_version + '.' + new_minor_version print 'Update revision from \'%s\' to \'%s\'' % (expected_revision, new_revision) # double check we are going to properly round-trip this value float_revision = float(new_revision) fixed_revision = misc.fixedTools.floatToFixed(float_revision, 16) rt_float_rev = misc.fixedTools.fixedToFloat(fixed_revision, 16) rt_float_rev_int = int(rt_float_rev) rt_float_rev_frac = int( round((rt_float_rev - rt_float_rev_int) * 10**accuracy)) rt_new_revision = (str(rt_float_rev_int) + '.' + str(rt_float_rev_frac).zfill(accuracy)) if new_revision != rt_new_revision: print '! Could not update new revision, expected \'%s\' but got \'%s\'' % ( new_revision, rt_new_revision) return new_version_string = 'Version ' + new_revision if not noto_font.is_hinted: new_version_string += ' uh' print '%s: %s' % ('Would write' if dry_run else 'Writing', dst_file) new_trademark = "%s is a trademark of Google Inc." % noto_font.family # description field should be set. # Roozbeh has note, make sure design field has information # on whether the font is hinted. # Missing in Lao and Khmer, default in Cham. if (cldr_data.get_english_script_name(noto_font.script) in ['Lao', 'Khmer', 'Cham']): new_description = 'Data %shinted.' % ('' if noto_font.is_hinted else 'un') # elif noto_font.vendor is 'Monotype': elif not noto_font.is_cjk and noto_font.family == 'Noto': new_description = ('Data %shinted. Designed by Monotype design team.' % ('' if noto_font.is_hinted else 'un')) else: new_description = None if re.match(r'^Copyright 201\d Google Inc. All Rights Reserved\.$', names[_COPYRIGHT_ID]): new_copyright = None else: new_copyright = '!!' if names.get(_DESIGNER_ID) in [ 'Steve Matteson', 'Monotype Design Team', 'Danh Hong', ]: new_designer = None elif names.get(_DESIGNER_ID) == 'Monotype Design team': new_designer = 'Monotype Design Team' elif (_DESIGNER_ID not in names and cldr_data.get_english_script_name(noto_font.script) == 'Khmer'): new_designer = 'Danh Hong' else: new_designer = '!!' if names.get(_DESIGNER_URL_ID) in [ 'http://www.monotype.com/studio', 'http://www.khmertype.org', ]: new_designer_url = None elif names.get(_DESIGNER_URL_ID) in [ 'http://www.monotypeimaging.com/ProductsServices/TypeDesignerShowcase', ]: new_designer_url = 'http://www.monotype.com/studio' elif names.get(_DESIGNER_URL_ID) in [ 'http://www.khmertype.blogspot.com', 'http://www.khmertype.blogspot.com/', 'http://khmertype.blogspot.com/', 'http://wwwkhmertype.blogspot.com.com/', ]: new_designer_url = 'http://www.khmertype.org' else: new_designer_url = '!!!' if names.get(_MANUFACTURER_ID) in [ 'Monotype Imaging Inc.', 'Danh Hong', ]: new_manufacturer = None else: new_manufacturer = '!!!' def update(name_id, new, newText=None): old = names.get(name_id) if new and (new != old): if not dry_run and not '!!!' in new: font_data.set_name_record(ttfont, name_id, new, addIfMissing='win') label = _NAME_ID_LABELS[name_id] oldText = '\'%s\'' % old if old else 'None' newText = newText or ('\'%s\'' % new) print '%s:\n old: %s\n new: %s' % (label, oldText, newText or new) label_change = _changes.get(label) if not label_change: label_change = {} _changes[label] = label_change new_val_change = label_change.get(new) if not new_val_change: new_val_change = {} label_change[new] = new_val_change old_val_fonts = new_val_change.get(old) if not old_val_fonts: old_val_fonts = [] new_val_change[old] = old_val_fonts old_val_fonts.append(noto_font.filepath) update(_COPYRIGHT_ID, new_copyright) update(_VERSION_ID, new_version_string) update(_TRADEMARK_ID, new_trademark) update(_MANUFACTURER_ID, new_manufacturer) update(_DESIGNER_ID, new_designer) update(_DESCRIPTION_ID, new_description) update(_VENDOR_URL_ID, _NOTO_URL) update(_DESIGNER_URL_ID, new_designer_url) update(_LICENSE_ID, _SIL_LICENSE, newText='(OFL)') update(_LICENSE_URL_ID, _SIL_LICENSE_URL) if autofix_for_release.fix_fstype(ttfont): _autofix['fstype'].append(noto_font.filepath) if autofix_for_release.fix_vendor_id(ttfont): _autofix['vendor_id'].append(noto_font.filepath) if autofix_for_release.fix_attachlist(ttfont): _autofix['attachlist'].append(noto_font.filepath) if noto_font.is_hinted: tables_to_drop = _HINTED_TABLES_TO_DROP else: tables_to_drop = _UNHINTED_TABLES_TO_DROP if autofix_for_release.drop_hints(ttfont): _autofix['drop_hints'].append(noto_font.filepath) if autofix_for_release.drop_tables(ttfont, tables_to_drop): _autofix['drop_tables'].append(noto_font.filepath) if noto_font.family == 'Noto': if autofix_for_release.fix_linegap(ttfont): _autofix['linegap'].append(noto_font.filepath) if autofix_for_release.fix_os2_unicoderange(ttfont): _autofix['os2_unicoderange'].append(noto_font.filepath) if dry_run: return ttfont['head'].fontRevision = float_revision dst_dir = path.dirname(dst_file) if not path.isdir(dst_dir): os.makedirs(dst_dir) ttfont.save(dst_file) print 'Wrote file.'
def _swat_font(noto_font, dst_root, dry_run): filepath = noto_font.filepath basename = path.basename(filepath) if noto_font.is_cjk: print '# Skipping cjk font %s' % basename return if noto_font.fmt == 'ttc': print '# Deferring ttc font %s' % basename _ttc_fonts[noto_font] = ttc_utils.ttcfile_filenames(filepath) return ttfont = ttLib.TTFont(filepath, fontNumber=0) names = font_data.get_name_records(ttfont) # create relative root path rel_filepath = _noto_relative_path(filepath) if not rel_filepath: raise ValueError('Could not identify noto root of %s' % filepath) print '-----\nUpdating %s' % rel_filepath dst_file = path.join(dst_root, rel_filepath) version = names[_VERSION_ID] m = re.match(r'Version (\d{1,5})\.(\d{1,5})(.*)', version) if not m: print '! Could not match version string (%s)' % version return major_version = m.group(1) minor_version = m.group(2) version_remainder = m.group(3) accuracy = len(minor_version) print_revision = font_data.printable_font_revision(ttfont, accuracy) # sanity check expected_revision = major_version + '.' + minor_version if expected_revision != print_revision: print '! Expected revision \'%s\' but got revision \'%s\'' % ( expected_revision, print_revision) return # bump the minor version keeping significant digits: new_minor_version = str(int(minor_version) + 1).zfill(accuracy) new_revision = major_version + '.' + new_minor_version print 'Update revision from \'%s\' to \'%s\'' % ( expected_revision, new_revision) # double check we are going to properly round-trip this value float_revision = float(new_revision) fixed_revision = misc.fixedTools.floatToFixed(float_revision, 16) rt_float_rev = misc.fixedTools.fixedToFloat(fixed_revision, 16) rt_float_rev_int = int(rt_float_rev) rt_float_rev_frac = int(round((rt_float_rev - rt_float_rev_int) * 10 ** accuracy)) rt_new_revision = (str(rt_float_rev_int) + '.' + str(rt_float_rev_frac).zfill(accuracy)) if new_revision != rt_new_revision: print '! Could not update new revision, expected \'%s\' but got \'%s\'' % ( new_revision, rt_new_revision) return new_version_string = 'Version ' + new_revision if not noto_font.is_hinted: new_version_string += ' uh' print '%s: %s' % ('Would write' if dry_run else 'Writing', dst_file) new_trademark = "%s is a trademark of Google Inc." % noto_font.family # description field should be set. # Roozbeh has note, make sure design field has information # on whether the font is hinted. # Missing in Lao and Khmer, default in Cham. if (cldr_data.get_english_script_name(noto_font.script) in ['Lao', 'Khmer', 'Cham']): new_description = 'Data %shinted.' % ('' if noto_font.is_hinted else 'un') # elif noto_font.vendor is 'Monotype': elif not noto_font.is_cjk and noto_font.family == 'Noto': new_description = ( 'Data %shinted. Designed by Monotype design team.' % ('' if noto_font.is_hinted else 'un')) else: new_description = None if re.match(r'^Copyright 201\d Google Inc. All Rights Reserved\.$', names[_COPYRIGHT_ID]): new_copyright = None else: new_copyright = '!!' if names.get(_DESIGNER_ID) in [ 'Steve Matteson', 'Monotype Design Team', 'Danh Hong', ]: new_designer = None elif names.get(_DESIGNER_ID) == 'Monotype Design team': new_designer = 'Monotype Design Team' elif (_DESIGNER_ID not in names and cldr_data.get_english_script_name(noto_font.script) == 'Khmer'): new_designer = 'Danh Hong' else: new_designer = '!!' if names.get(_DESIGNER_URL_ID) in [ 'http://www.monotype.com/studio', 'http://www.khmertype.org', ]: new_designer_url = None elif names.get(_DESIGNER_URL_ID) in [ 'http://www.monotypeimaging.com/ProductsServices/TypeDesignerShowcase', ]: new_designer_url = 'http://www.monotype.com/studio' elif names.get(_DESIGNER_URL_ID) in [ 'http://www.khmertype.blogspot.com', 'http://www.khmertype.blogspot.com/', 'http://khmertype.blogspot.com/', 'http://wwwkhmertype.blogspot.com.com/', ]: new_designer_url = 'http://www.khmertype.org' else: new_designer_url = '!!!' if names.get(_MANUFACTURER_ID) in [ 'Monotype Imaging Inc.', 'Danh Hong', ]: new_manufacturer = None else: new_manufacturer = '!!!' def update(name_id, new, newText=None): old = names.get(name_id) if new and (new != old): if not dry_run and not '!!!' in new: font_data.set_name_record(ttfont, name_id, new, addIfMissing='win') label = _NAME_ID_LABELS[name_id] oldText = '\'%s\'' % old if old else 'None' newText = newText or ('\'%s\'' % new) print '%s:\n old: %s\n new: %s' % (label, oldText, newText or new) label_change = _changes.get(label) if not label_change: label_change = {} _changes[label] = label_change new_val_change = label_change.get(new) if not new_val_change: new_val_change = {} label_change[new] = new_val_change old_val_fonts = new_val_change.get(old) if not old_val_fonts: old_val_fonts = [] new_val_change[old] = old_val_fonts old_val_fonts.append(noto_font.filepath) update(_COPYRIGHT_ID, new_copyright) update(_VERSION_ID, new_version_string) update(_TRADEMARK_ID, new_trademark) update(_MANUFACTURER_ID, new_manufacturer) update(_DESIGNER_ID, new_designer) update(_DESCRIPTION_ID, new_description) update(_VENDOR_URL_ID, _NOTO_URL) update(_DESIGNER_URL_ID, new_designer_url) update(_LICENSE_ID, _SIL_LICENSE, newText='(OFL)') update(_LICENSE_URL_ID, _SIL_LICENSE_URL) if autofix_for_release.fix_fstype(ttfont): _autofix['fstype'].append(noto_font.filepath) if autofix_for_release.fix_vendor_id(ttfont): _autofix['vendor_id'].append(noto_font.filepath) if autofix_for_release.fix_attachlist(ttfont): _autofix['attachlist'].append(noto_font.filepath) if noto_font.is_hinted: tables_to_drop = _HINTED_TABLES_TO_DROP else: tables_to_drop = _UNHINTED_TABLES_TO_DROP if autofix_for_release.drop_hints(ttfont): _autofix['drop_hints'].append(noto_font.filepath) if autofix_for_release.drop_tables(ttfont, tables_to_drop): _autofix['drop_tables'].append(noto_font.filepath) if noto_font.family == 'Noto': if autofix_for_release.fix_linegap(ttfont): _autofix['linegap'].append(noto_font.filepath) if autofix_for_release.fix_os2_unicoderange(ttfont): _autofix['os2_unicoderange'].append(noto_font.filepath) if dry_run: return ttfont['head'].fontRevision = float_revision dst_dir = path.dirname(dst_file) if not path.isdir(dst_dir): os.makedirs(dst_dir) ttfont.save(dst_file) print 'Wrote file.'
def check_spreadsheet(src_file): filenames = set() prev_script_name = None fontdata = {} filedata = {} with open(src_file) as csvfile: reader = csv.DictReader(csvfile) for index, row in enumerate(reader): font = row['Fonts'].replace('\xc2\xa0', ' ').strip() hinting = row['Hinting'].strip() status = row['Status'].strip() accepted_version = row['Accepted Version'].strip() note = row['Note'].strip() # family script style (variant UI) weight, mostly m = re.match( r'Noto (Kufi|Naskh|Color Emoji|Emoji|Sans|Serif|Nastaliq)' r'(?: (.*?))?' r'(?: (UI))?' r' (Thin|Light|DemiLight|Regular|Medium|Bold Italic' r'|Bold|Black|Italic)(?: \(merged\))?$', font) if not m: m = re.match(r'Noto (Sans) (Myanmar) (UI)(.*)', font) if not m: print 'could not parse Myanmar exception: "%s"' % font continue style, script, ui, weight = m.groups() weight = weight or 'Regular' weight = weight.replace(' ', '') ui = ui or '' script = script or '' script = re.sub('-| ', '', script) style = style.replace(' ', '') ext = 'ttf' if script == 'CJK': ext = 'ttc' elif script.startswith('TTC'): ext = 'ttc' script = '' elif script == '(LGC)': script = '' elif script == 'UI': ui = 'UI' script = '' elif script == 'Phagspa': script = 'PhagsPa' elif script == 'SumeroAkkadianCuneiform': script = 'Cuneiform' fontname = ''.join( ['Noto', style, script, ui, '-', weight, '.', ext]) # print '%s:\n--> %s\n--> %s' % ( # font, str((style, script, ui, weight)), fontname) if not hinting in ['hinted', 'hinted (CFF)', 'unhinted']: print 'unrecognized hinting value \'%s\' on line %d (%s)' % ( hinting, index, fontname) continue hinted = 'hinted' if hinting in ['hinted', 'hinted (CFF)' ] else 'unhinted' if not status in [ 'In finishing', 'Released w. lint errors', 'Approved & Released', 'Approved & Not Released', 'In design', 'Design approved', 'Design re-approved', 'Released' ]: print 'unrecognized status value \'%s\' on line %d (%s)' % ( status, index, fontname) continue expect_font = status in [ 'Released w. lint errors', 'Approved & Released', 'Approved & Not Released', 'Released' ] data = (fontname, (index, font, style, script, ui, weight), hinted, status, accepted_version, note, expect_font) filedata[hinted + '/' + fontname] = data # ok, now let's see if we can find these files all_noto = noto_fonts.get_noto_fonts() notodata = {('hinted' if f.is_hinted else 'unhinted') + '/' + path.basename(f.filepath): f for f in all_noto} noto_filenames = frozenset(notodata.keys()) spreadsheet_filenames = frozenset(k for k in filedata if filedata[k][6]) spreadsheet_extra = spreadsheet_filenames - noto_filenames spreadsheet_missing = noto_filenames - spreadsheet_filenames if spreadsheet_extra: print 'spreadsheet extra:\n ' + '\n '.join( sorted(spreadsheet_extra)) if spreadsheet_missing: print 'spreadsheet missing:\n ' + '\n '.join( sorted(spreadsheet_missing)) spreadsheet_match = spreadsheet_filenames & noto_filenames for filename in sorted(spreadsheet_match): data = filedata[filename] filepath = notodata[filename].filepath ttfont = ttLib.TTFont(filepath, fontNumber=0) font_version = font_data.printable_font_revision(ttfont) approved_version = data[4] if approved_version: warn = '!!!' if approved_version != font_version else '' print '%s%s version: %s approved: %s' % ( warn, filename, font_version, approved_version) else: print '%s version: %s' % (filename, font_version)
def fix_font(f, dst_dir, rel_dir, version, version_info, autohint, dry_run): print '\n-----\nfont:', f font = ttLib.TTFont(f) relfont = _get_release_font(f, rel_dir) expected_font_revision = get_new_version(font, relfont, version) if expected_font_revision != None: font_revision = font_data.printable_font_revision(font, 3) if font_revision != expected_font_revision: _alert('revision', font_revision, expected_font_revision) font['head'].fontRevision = float(expected_font_revision) names = font_data.get_name_records(font) NAME_ID = 5 font_version = names[NAME_ID] expected_version = ( 'Version %s;%s' % (expected_font_revision, version_info)) if font_version != expected_version: _alert('version string', font_version, expected_version) font_data.set_name_record(font, NAME_ID, expected_version) expected_upem = 1000 upem = font['head'].unitsPerEm if upem != expected_upem: print 'expected %d upem but got %d upem' % (expected_upem, upem) if _is_ui_metrics(f): if upem == 2048: expected_ascent = 2163 expected_descent = -555 elif upem == 1000: expected_ascent = 1069 expected_descent = -293 else: raise Exception('no expected ui ascent/descent for upem: %d' % upem) font_ascent = font['hhea'].ascent font_descent = font['hhea'].descent if font_ascent != expected_ascent: _alert_and_check('ascent', font_ascent, expected_ascent, 2) font['hhea'].ascent = expected_ascent font['OS/2'].sTypoAscender = expected_ascent font['OS/2'].usWinAscent = expected_ascent if font_descent != expected_descent: _alert_and_check('descent', font_descent, expected_descent, -2) font['hhea'].descent = expected_descent font['OS/2'].sTypoDescender = expected_descent font['OS/2'].usWinDescent = -expected_descent tool_utils.ensure_dir_exists(path.join(dst_dir, 'unhinted')) fname = path.basename(f) udst = path.join(dst_dir, 'unhinted', fname) if dry_run: print 'dry run would write:\n "%s"' % udst else: font.save(udst) print 'wrote %s' % udst if autohint: hdst = path.join(dst_dir, 'hinted', fname) autohint_font(udst, hdst, autohint, dry_run)