def __generateForWeight(self, weight: str, font: Font) -> None: package = self.__core.package base_dir = self.__core.directories.webfonts output_dir = base_dir.joinpath(f"./{package.version}/{weight}") font_path = self.__core.findFontfilePath(font) output_dir.mkdir(parents=True, exist_ok=True) metadata = self.__generateMetadata() fake = Faker() fake.seed(package.id) subset_fontname: str = fake.name() options = Options() options.font_number = font.number options.hinting = False options.desubroutinize = True options.drop_tables += [ 'FFTM', 'PfEd', 'TeX', 'BDF', 'cvt', 'fpgm', 'prep', 'gasp', 'VORG', 'CBDT', 'CBLC', 'sbix' ] for ignored in ['rvrn', 'locl']: options.layout_features.remove(ignored) for unicodes_file in FILE_DIR.UNICODE_TEXT.glob('./**/*.txt'): idx = unicodes_file.stem unicodes: List[str] = [] with open(unicodes_file, 'r') as unicode_read_io: for line in unicode_read_io.readlines(): unicodes.extend(parse_unicodes(line.split('#')[0])) with load_font(font_path, options) as ttfont: subsetter = Subsetter(options=options) subsetter.populate(unicodes=unicodes) subsetter.subset(ttfont) for record in ttfont['name'].names: if record.nameID == NAME_ID.COPYRIGHT: record.string = '\n'.join(package.copyrights) elif record.nameID in FAMILY_RELATED_NAME_ID: record.string = subset_fontname woff_file = output_dir.joinpath(f"{idx}.woff") with open(woff_file, 'wb') as woff_write_io: options.flavor = 'woff' ttfont.flavorData = WOFFFlavorData() ttfont.flavorData.metaData = metadata save_font(ttfont, woff_write_io, options) woff2_file = output_dir.joinpath(f"{idx}.woff2") with open(woff2_file, 'wb') as woff2_write_io: options.flavor = 'woff2' ttfont.flavorData = WOFF2FlavorData() ttfont.flavorData.metaData = metadata save_font(ttfont, woff2_write_io, options)
def subset(fontfile, outfile_basename, glyphs): options = Options() # Fonttools has this "feature" that if you enable 'dlig', it will also give # you glyphs that you did not ask for, but if you do not enable 'dlig', # then discretionary ligatures do not render properly. # See https://github.com/behdad/fonttools/issues/43. # As a workaround, only enable 'dlig' if there are glyphs for discretionary # ligatures. dligs = set(glyphs).intersection([ 'c_b', 'c_h', 'c_k', 'c_p', 'ct', 'g_i', 'q_u', 's_b', 's_h', 's_k', 's_p', 'st' ]) if len(dligs) > 0: options.layout_features.append('dlig') else: # Due to a bug in Fonttools, options are actually global, so the # remnants of the previous instance are visible here. # See https://github.com/behdad/fonttools/issues/413. if 'dlig' in options.layout_features: options.layout_features.remove('dlig') # Same for small caps, it needs to be enabled explicitly. Luckily, only the # glyphs in the list get included, no extra ones. if any(g.endswith('.smcp') for g in glyphs): options.layout_features.append('smcp') options.layout_features.append('c2sc') else: if 'smcp' in options.layout_features: options.layout_features.remove('smcp') if 'c2sc' in options.layout_features: options.layout_features.remove('c2sc') # Fonts that went through the FontForge roundtrip will have subroutinized # programs in the CFF table. This presumably reduces file size for full # fonts, but on subsetted fonts it hurts file size and compressability, so # desubroutinize. options.desubroutinize = True font = load_font(fontfile, options) subsetter = Subsetter(options=options) subsetter.populate(glyphs=glyphs) subsetter.subset(font) prune_cmaps(font) options.flavor = "woff" save_font(font, outfile_basename + ".woff", options) options.flavor = "woff2" save_font(font, outfile_basename + ".woff2", options) font.close()
def subset(fontfile, outfile_basename, glyphs): options = Options() # Fonttools has this feature that if you enable 'dlig', it will also give # you glyphs that you did not ask for, but if you do not enable 'dlig', # then discretionary ligatures do not render properly. # See https://github.com/behdad/fonttools/issues/43. # As a workaround, only enable 'dlig' if there are glyphs for discretionary # ligatures. # TODO: This should be fixed, consider upgrading. # https://github.com/fonttools/fonttools/commit/022536212be4cf022a2cb9a286fec8be1931d19b. dligs = set(glyphs).intersection(['c_b', 'c_h', 'c_k', 'c_p', 'ct', 'g_i', 'q_u', 's_b', 's_h', 's_k', 's_p', 'st']) if len(dligs) > 0: options.layout_features.append('dlig') else: # Due to a bug in Fonttools, options are actually global, so the # remnants of the previous instance are visible here. # See https://github.com/behdad/fonttools/issues/413. if 'dlig' in options.layout_features: options.layout_features.remove('dlig') # Same for small caps, it needs to be enabled explicitly. Luckily, only the # glyphs in the list get included, no extra ones. if any(g.endswith('.smcp') for g in glyphs): options.layout_features.append('smcp') options.layout_features.append('c2sc') else: if 'smcp' in options.layout_features: options.layout_features.remove('smcp') if 'c2sc' in options.layout_features: options.layout_features.remove('c2sc') # Fonts that went through the FontForge roundtrip will have subroutinized # programs in the CFF table. This presumably reduces file size for full # fonts, but on subsetted fonts it hurts file size and compressability, so # desubroutinize. options.desubroutinize = True font = load_font(fontfile, options) subsetter = Subsetter(options = options) subsetter.populate(glyphs = glyphs) subsetter.subset(font) prune_cmaps(font) options.flavor = "woff" save_font(font, outfile_basename + ".woff", options) options.flavor = "woff2" save_font(font, outfile_basename + ".woff2", options) font.close()
def subset(fontfile, outfile_basename, glyphs): options = Options() # Fonttools has this "feature" that if you enable 'dlig', it will also give # you glyphs that you did not ask for, but if you do not enable 'dlig', # then discretionary ligatures do not render properly. # See https://github.com/behdad/fonttools/issues/43. # As a workaround, only enable 'dlig' if there are glyphs for discretionary # ligatures. dligs = set(glyphs).intersection(["c_b", "c_h", "c_k", "c_p", "ct", "g_i", "q_u", "s_b", "s_h", "s_k", "s_p", "st"]) if len(dligs) > 0: options.layout_features.append("dlig") else: # Due to a bug in Fonttools, options are actually global, so the # remnants of the previous instance are visible here. # See https://github.com/behdad/fonttools/issues/413. if "dlig" in options.layout_features: options.layout_features.remove("dlig") # Same for small caps, it needs to be enabled explicitly. Luckily, only the # glyphs in the list get included, no extra ones. if any(g.endswith(".smcp") for g in glyphs): options.layout_features.append("smcp") options.layout_features.append("c2sc") else: if "smcp" in options.layout_features: options.layout_features.remove("smcp") if "c2sc" in options.layout_features: options.layout_features.remove("c2sc") # Fonts that went through the FontForge roundtrip will have subroutinized # programs in the CFF table. This presumably reduces file size for full # fonts, but on subsetted fonts it hurts file size and compressability, so # desubroutinize. options.desubroutinize = True font = load_font(fontfile, options) subsetter = Subsetter(options=options) subsetter.populate(glyphs=glyphs) subsetter.subset(font) prune_cmaps(font) options.flavor = "woff" save_font(font, outfile_basename + ".woff", options) options.flavor = "woff2" save_font(font, outfile_basename + ".woff2", options) font.close()
def subsetFont(base64, subset): # tmp file names tmpInputFontName = tmpFileName(".ttf") tmpOutputFontName = tmpFileName(".woff") # remove data header from base64 fontbase64 = base64.split(",")[1] with open(tmpInputFontName, "wb") as f: fontinput = f.write(fontbase64.decode('base64')) f.close() # open the font with fontTools font = TTFont(tmpInputFontName) options = Options() options.desubroutinize = True # export the font as woff for web use options.with_zopfli = True options.flavor = "woff" subsetter = Subsetter(options=options) subsetter.populate(text=subset) subsetter.subset(font) save_font(font, tmpOutputFontName, options) subsettedFont = open(tmpOutputFontName, "rb").read().encode("base64") os.unlink(tmpOutputFontName) os.unlink(tmpInputFontName) return {'subset': subsettedFont}
def convertFont(fontPath, fontType): options = Options() tmpOutputTtf = tmpFileName(".ttf") tmpOutputWoff = tmpFileName(".woff") font = TTFont(fontPath) ttfOptions = Options() # export the font as woff for web use woffOptions = Options() woffOptions.with_zopfli = True woffOptions.flavor = "woff" if fontType == "otf": # convert the font to ttf ttfFont = otf_to_ttf(font) # save font can also convert to woff! save_font(ttfFont, tmpOutputTtf, ttfOptions) save_font(ttfFont, tmpOutputWoff, woffOptions) elif fontType == "ttf": save_font(font, tmpOutputTtf, ttfOptions) save_font(font, tmpOutputWoff, woffOptions) else: print "wrong type" ttfBase64 = "data:;base64," + toBase64(tmpOutputTtf) woffBase64 = "data:;base64," + toBase64(tmpOutputWoff) #cleanup files cleanUp([tmpOutputWoff, tmpOutputTtf]) print woffBase64.replace("\n", "") print ttfBase64.replace("\n", "")
def subset_font(basefile_path, buff, text): options = Options() options.name_IDs = [] options.obfuscate_names = True options.flavor = 'woff' font = load_font(basefile_path, options) subsetter = Subsetter(options=options) subsetter.populate(text=text) subsetter.subset(font) save_font(font, buff, options) font.close() buff.seek(0) return
def convertFont(base64, type): options = Options() # tmp file names tmpInputFontName = tmpFileName("." + type) tmpOutputTtf = tmpFileName(".ttf") tmpOutputWoff = tmpFileName(".woff") # remove data header from base64 # now we have a clean input source fontbase64 = base64.split(",")[1] with open(tmpInputFontName, "wb") as f: fontinput = f.write(fontbase64.decode('base64')) f.close() # we always work from a TTFont Object (also takes OTF) font = TTFont(tmpInputFontName) ttfOptions = Options() # export the font as woff for web use woffOptions = Options() woffOptions.with_zopfli = True woffOptions.flavor = "woff" if type == 'otf': # convert the font to ttf ttfFont = otf_to_ttf(font) # save font can also convert to woff! save_font(ttfFont, tmpOutputTtf, ttfOptions) save_font(ttfFont, tmpOutputWoff, woffOptions) elif type == 'ttf': save_font(font, tmpOutputTtf, ttfOptions) save_font(font, tmpOutputWoff, woffOptions) else: return {'error': 'please give a valid type'} ttfBase64 = toBase64(tmpOutputTtf) woffBase64 = toBase64(tmpOutputWoff) #cleanup files cleanUp([tmpInputFontName, tmpOutputWoff, tmpOutputTtf]) return {'woff': woffBase64, 'ttf': ttfBase64}
def subsetFont(fontPath, subset): tmpOutputFontName = os.path.dirname( os.path.abspath(__file__)) + "/tmp/" + str(uuid.uuid4()) + ".woff" font = TTFont(fontPath) options = Options() options.desubroutinize = True options.with_zopfli = True options.flavor = "woff" subsetter = Subsetter(options=options) subsetter.populate(text=subset) subsetter.subset(font) save_font(font, tmpOutputFontName, options) subsettedFont = 'data:;base64,' + open(tmpOutputFontName, "rb").read().encode("base64") cleanUp([tmpOutputFontName]) print subsettedFont.replace('\n', '')