def __init__(self, ufo, ttFont=None, glyphSet=None, **kwargs): """ Args: ufo: an object representing a UFO (defcon.Font or equivalent) containing the features source data. ttFont: a fontTools TTFont object where the generated OpenType tables are added. If None, an empty TTFont is used, with the same glyph order as the ufo object. glyphSet: a (optional) dict containing pre-processed copies of the UFO glyphs. """ self.ufo = ufo if ttFont is None: from fontTools.ttLib import TTFont from ufo2ft.util import makeOfficialGlyphOrder ttFont = TTFont() ttFont.setGlyphOrder(makeOfficialGlyphOrder(ufo)) self.ttFont = ttFont glyphOrder = ttFont.getGlyphOrder() if glyphSet is not None: assert set(glyphOrder) == set(glyphSet.keys()) else: glyphSet = ufo self.glyphSet = OrderedDict((gn, glyphSet[gn]) for gn in glyphOrder)
def makeOfficialGlyphOrder(self, glyphOrder): """ Make the final glyph order. **This should not be called externally.** Subclasses may override this method to handle the order creation in a different way if desired. """ return makeOfficialGlyphOrder(self.allGlyphs, glyphOrder)
def subset_otf_from_ufo(self, otf_path, ufo): """Subset a font using export flags set by glyphsLib. There are two more settings that can change export behavior: "Export Glyphs" and "Remove Glyphs", which are currently not supported for complexity reasons. See https://github.com/googlei18n/glyphsLib/issues/295. """ from fontTools import subset # ufo2ft always inserts a ".notdef" glyph as the first glyph ufo_order = makeOfficialGlyphOrder(ufo) if ".notdef" not in ufo_order: ufo_order.insert(0, ".notdef") ot_order = TTFont(otf_path).getGlyphOrder() assert ot_order[0] == ".notdef" assert len(ufo_order) == len(ot_order) for key in (KEEP_GLYPHS_NEW_KEY, KEEP_GLYPHS_OLD_KEY): keep_glyphs_list = ufo.lib.get(key) if keep_glyphs_list is not None: keep_glyphs = set(keep_glyphs_list) break else: keep_glyphs = None include = [] for source_name, binary_name in zip(ufo_order, ot_order): if keep_glyphs and source_name not in keep_glyphs: continue if source_name in ufo: exported = ufo[source_name].lib.get(GLYPH_EXPORT_KEY, True) if not exported: continue include.append(binary_name) # copied from nototools.subset opt = subset.Options() opt.name_IDs = ['*'] opt.name_legacy = True opt.name_languages = ['*'] opt.layout_features = ['*'] opt.notdef_outline = True opt.recalc_bounds = True opt.recalc_timestamp = True opt.canonical_order = True opt.glyph_names = True font = subset.load_font(otf_path, opt, lazy=False) subsetter = subset.Subsetter(options=opt) subsetter.populate(glyphs=include) subsetter.subset(font) subset.save_font(font, otf_path, opt)
def set_context(self, font): ctx = super(MarkFeatureWriter, self).set_context(font) glyphOrder = makeOfficialGlyphOrder(font) ctx.glyphSet = OrderedDict(((gn, font[gn]) for gn in glyphOrder)) ctx.accentGlyphNames = set() self.setupAnchorPairs() return ctx
def getOrderedGlyphSet(self): """Return OrderedDict[glyphName, glyph] sorted by glyphOrder. """ compiler = self.context.compiler if compiler is not None: return compiler.glyphSet from ufo2ft.util import makeOfficialGlyphOrder glyphSet = self.context.font glyphOrder = makeOfficialGlyphOrder(self.context.font) return OrderedDict((gn, glyphSet[gn]) for gn in glyphOrder)
def _makeOrderedGlyphSet(font, compiler=None): """ Return glyph set as an OrderedDict sorted by glyphOrder to write mark/mkmk classes and rules in a deterministic order. """ if compiler is not None: glyphSet = compiler.glyphSet glyphOrder = compiler.ttFont.getGlyphOrder() else: from ufo2ft.util import makeOfficialGlyphOrder glyphSet = font glyphOrder = makeOfficialGlyphOrder(font) return OrderedDict((gn, glyphSet[gn]) for gn in glyphOrder)
def _makeOrderedGlyphSet(font, compiler=None): """ Return glyph set as an OrderedDict sorted by glyphOrder to write mark/mkmk classes and rules in a deterministic order. """ if compiler is not None: glyphSet = compiler.glyphSet glyphOrder = compiler.ttFont.getGlyphOrder() else: from ufo2ft.util import makeOfficialGlyphOrder glyphSet = font glyphOrder = makeOfficialGlyphOrder(font) return OrderedDict((gn, glyphSet[gn]) for gn in glyphOrder)
def getOrderedGlyphSet(self): """Return OrderedDict[glyphName, glyph] sorted by glyphOrder.""" compiler = self.context.compiler if compiler is not None: return compiler.glyphSet from ufo2ft.util import _GlyphSet, makeOfficialGlyphOrder font = self.context.font # subset glyphSet by skipExportGlyphs if any glyphSet = _GlyphSet.from_layer( font, skipExportGlyphs=set(font.lib.get("public.skipExportGlyphs", [])), ) glyphOrder = makeOfficialGlyphOrder(glyphSet, font.glyphOrder) return OrderedDict((gn, glyphSet[gn]) for gn in glyphOrder)
def subset_otf_from_ufo(self, otf_path, ufo): """Subset a font using "Keep Glyphs" custom parameter and export flags as set by glyphsLib. "Export Glyphs" and "Remove Glyphs" are currently not supported: https://github.com/googlei18n/glyphsLib/issues/295. """ from fontTools import subset # we must exclude from the final UFO glyphOrder all the glyphs that were not # exported to OTF because included in 'public.skipExportGlyphs' skip_export_glyphs = set(ufo.lib.get("public.skipExportGlyphs", ())) exported_glyphs = dict.fromkeys(g for g in ufo.keys() if g not in skip_export_glyphs) ufo_order = makeOfficialGlyphOrder(exported_glyphs, glyphOrder=ufo.glyphOrder) # ufo2ft always inserts a ".notdef" glyph as the first glyph if ".notdef" not in exported_glyphs: ufo_order.insert(0, ".notdef") ot_order = TTFont(otf_path).getGlyphOrder() assert ot_order[0] == ".notdef" assert len(ufo_order) == len(ot_order) for key in (KEEP_GLYPHS_NEW_KEY, KEEP_GLYPHS_OLD_KEY): keep_glyphs_list = ufo.lib.get(key) if keep_glyphs_list is not None: keep_glyphs = set(keep_glyphs_list) break else: keep_glyphs = None include = [] for source_name, binary_name in zip(ufo_order, ot_order): if keep_glyphs and source_name not in keep_glyphs: continue if source_name in ufo: exported = ufo[source_name].lib.get(GLYPH_EXPORT_KEY, True) if not exported: continue include.append(binary_name) # copied from nototools.subset opt = subset.Options() opt.name_IDs = ["*"] opt.name_legacy = True opt.name_languages = ["*"] opt.layout_features = ["*"] opt.notdef_outline = True opt.recalc_bounds = True opt.recalc_timestamp = True opt.canonical_order = True opt.glyph_names = True font = subset.load_font(otf_path, opt, lazy=False) subsetter = subset.Subsetter(options=opt) subsetter.populate(glyphs=include) subsetter.subset(font) subset.save_font(font, otf_path, opt)