def _construct_ttc_fonts(fonts, dst_root, dry_run): # _ttc_fonts contains a map from a font path to a list of likely names # of the component fonts. The component names are based off the # postscript name in the name table of the component, so 1) might not # accurately represent the font, and 2) don't indicate whether the # component is hinted. We deal with the former by rejecting and # reporting ttcs where any name fails to match, and with the latter # by assuming all the components are hinted or not based on whether # the original is in a 'hinted' or 'unhinted' directory. # build a map from basename to a list of noto_font objects basename_to_fonts = collections.defaultdict(list) for font in fonts: if font.fmt != 'ttc': basename = path.basename(font.filepath) basename_to_fonts[basename].append(font) for ttcfont, components in sorted(_ttc_fonts.iteritems()): rel_filepath = _noto_relative_path(ttcfont.filepath) print '-----\nBuilding %s' % rel_filepath component_list = [] # note the component order must match the original ttc, so # we must process in the provided order. for component in components: possible_components = basename_to_fonts.get(component) if not possible_components: print '! no match for component named %s in %s' % ( component, rel_path) component_list = [] break matched_possible_component = None for possible_component in possible_components: if possible_component.is_hinted == ttcfont.is_hinted: if matched_possible_component: print '! already matched possible component %s for %s' % ( matched_possible_component.filename, possible_component_filename) matched_possible_component = None break matched_possible_component = possible_component if not matched_possible_component: print 'no matched component named %s' % component component_list = [] break component_list.append(matched_possible_component) if not component_list: print '! cannot generate ttc font %s' % rel_path continue print 'components:\n ' + '\n '.join( _noto_relative_path(font.filepath) for font in component_list) if dry_run: continue dst_ttc = path.join(dst_root, rel_filepath) src_files = [path.join(dst_root, _noto_relative_path(font.filepath)) for font in component_list] ttc_utils.build_ttc(dst_ttc, src_files) print 'Built %s' % dst_ttc
def _construct_ttc_fonts(fonts, dst_root, dry_run): # _ttc_fonts contains a map from a font path to a list of likely names # of the component fonts. The component names are based off the # postscript name in the name table of the component, so 1) might not # accurately represent the font, and 2) don't indicate whether the # component is hinted. We deal with the former by rejecting and # reporting ttcs where any name fails to match, and with the latter # by assuming all the components are hinted or not based on whether # the original is in a 'hinted' or 'unhinted' directory. # build a map from basename to a list of noto_font objects basename_to_fonts = collections.defaultdict(list) for font in fonts: if font.fmt != 'ttc': basename = path.basename(font.filepath) basename_to_fonts[basename].append(font) for ttcfont, components in sorted(_ttc_fonts.iteritems()): rel_filepath = _noto_relative_path(ttcfont.filepath) print '-----\nBuilding %s' % rel_filepath component_list = [] # note the component order must match the original ttc, so # we must process in the provided order. for component in components: possible_components = basename_to_fonts.get(component) if not possible_components: print '! no match for component named %s in %s' % (component, rel_path) component_list = [] break matched_possible_component = None for possible_component in possible_components: if possible_component.is_hinted == ttcfont.is_hinted: if matched_possible_component: print '! already matched possible component %s for %s' % ( matched_possible_component.filename, possible_component_filename) matched_possible_component = None break matched_possible_component = possible_component if not matched_possible_component: print 'no matched component named %s' % component component_list = [] break component_list.append(matched_possible_component) if not component_list: print '! cannot generate ttc font %s' % rel_path continue print 'components:\n ' + '\n '.join( _noto_relative_path(font.filepath) for font in component_list) if dry_run: continue dst_ttc = path.join(dst_root, rel_filepath) src_files = [ path.join(dst_root, _noto_relative_path(font.filepath)) for font in component_list ] ttc_utils.build_ttc(dst_ttc, src_files) print 'Built %s' % dst_ttc
} def remove_from_cmap(infile, outfile, exclude=frozenset()): """Removes a set of characters from a font file's cmap table.""" font = ttLib.TTFont(infile) font_data.delete_from_cmap(font, exclude) font.save(outfile) TTC_NAME = 'NotoSansCJK-Regular.ttc' OTF_NAMES = [ 'NotoSans%sCJK%s-Regular.otf' % (mono, variant) for mono in ['', 'Mono'] for variant in ['jp', 'kr', 'sc', 'tc'] ] TEMP_DIR = 'no-emoji' if not os.path.exists(TEMP_DIR): os.mkdir(TEMP_DIR) for index, otf_name in enumerate(OTF_NAMES): print 'Subsetting %s...' % otf_name font = ttLib.TTFont(TTC_NAME, fontNumber=index) font.save(otf_name) remove_from_cmap(otf_name, os.path.join(TEMP_DIR, otf_name), exclude=sorted(EMOJI_IN_CJK | ANDROID_EMOJI)) os.chdir(TEMP_DIR) ttc_utils.build_ttc(TTC_NAME, OTF_NAMES)