def __init__(self, ufo, inplace=False, layerName=None, **kwargs): self.ufo = ufo self.inplace = inplace self.layerName = layerName self.glyphSet = _GlyphSet.from_layer(ufo, layerName, copy=not inplace) self.defaultFilters = self.initDefaultFilters(**kwargs) self.preFilters, self.postFilters = loadFilters(ufo)
def __init__(self, ufos, inplace=False, conversionError=None, reverseDirection=True, rememberCurveType=True, layerNames=None): from cu2qu.ufo import DEFAULT_MAX_ERR self.ufos = ufos self.inplace = inplace if layerNames is None: layerNames = [None] * len(ufos) assert len(ufos) == len(layerNames) self.layerNames = layerNames self.glyphSets = [ _GlyphSet.from_layer(ufo, layerName, copy=not inplace) for ufo, layerName in zip(ufos, layerNames) ] self._conversionErrors = [ (conversionError or DEFAULT_MAX_ERR) * ufo.info.unitsPerEm for ufo in ufos ] self._reverseDirection = reverseDirection self._rememberCurveType = rememberCurveType
def __init__( self, ufos, inplace=False, flattenComponents=False, conversionError=None, reverseDirection=True, rememberCurveType=True, layerNames=None, skipExportGlyphs=None, filters=None, ): from cu2qu.ufo import DEFAULT_MAX_ERR self.ufos = ufos self.inplace = inplace self.flattenComponents = flattenComponents if layerNames is None: layerNames = [None] * len(ufos) assert len(ufos) == len(layerNames) self.layerNames = layerNames self.glyphSets = [ _GlyphSet.from_layer( ufo, layerName, copy=not inplace, skipExportGlyphs=skipExportGlyphs ) for ufo, layerName in zip(ufos, layerNames) ] self._conversionErrors = [ (conversionError or DEFAULT_MAX_ERR) * getAttrWithFallback(ufo.info, "unitsPerEm") for ufo in ufos ] self._reverseDirection = reverseDirection self._rememberCurveType = rememberCurveType self.preFilters, self.postFilters = [], [] if filters is None: for ufo in ufos: pre, post = loadFilters(ufo) self.preFilters.append(pre) self.postFilters.append(post) else: pre = [f for f in filters if f.pre] post = [f for f in filters if not f.pre] for _ in ufos: self.preFilters.append(pre) self.postFilters.append(post)
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 test_skip_export_glyphs_filter(self, FontClass): from ufo2ft.util import _GlyphSet ufo = FontClass(getpath("IncompatibleMasters/NewFont-Regular.ufo")) skipExportGlyphs = ["b", "d"] glyphSet = _GlyphSet.from_layer(ufo, skipExportGlyphs=skipExportGlyphs) assert set(glyphSet.keys()) == {"a", "c", "e", "f"} assert len(glyphSet["a"]) == 1 assert not glyphSet["a"].components assert len(glyphSet["c"]) == 5 # 4 "d" components decomposed plus 1 outline assert list(c.baseGlyph for c in glyphSet["c"].components) == ["a"] assert len(glyphSet["e"]) == 1 assert list(c.baseGlyph for c in glyphSet["e"].components) == ["c", "c"] assert not glyphSet["f"] assert list(c.baseGlyph for c in glyphSet["f"].components) == ["a", "a"]
def test_skip_export_glyphs_filter_nested(self, FontClass): from ufo2ft.util import _GlyphSet ufo = FontClass() glyph_N = ufo.newGlyph("N") glyph_N.width = 100 pen = glyph_N.getPen() pen.moveTo((0, 0)) pen.lineTo((300, 0)) pen.lineTo((300, 400)) pen.lineTo((0, 400)) pen.closePath() glyph_o = ufo.newGlyph("o") glyph_o.width = 100 pen = glyph_o.getPen() pen.moveTo((0, 0)) pen.lineTo((300, 0)) pen.lineTo((300, 300)) pen.lineTo((0, 300)) pen.closePath() glyph_onumero = ufo.newGlyph("_o.numero") glyph_onumero.width = 100 pen = glyph_onumero.getPen() pen.addComponent("o", (-1, 0, 0, -1, 0, 100)) pen.moveTo((0, 0)) pen.lineTo((300, 0)) pen.lineTo((300, 50)) pen.lineTo((0, 50)) pen.closePath() glyph_numero = ufo.newGlyph("numero") glyph_numero.width = 200 pen = glyph_numero.getPen() pen.addComponent("N", (1, 0, 0, 1, 0, 0)) pen.addComponent("_o.numero", (1, 0, 0, 1, 400, 0)) skipExportGlyphs = ["_o.numero"] glyphSet = _GlyphSet.from_layer(ufo, skipExportGlyphs=skipExportGlyphs) assert len(glyphSet["numero"].components) == 1 # The "N" component assert len( glyphSet["numero"]) == 2 # The two contours of "o" and "_o.numero"
def __call__(self, font, glyphSet=None): """Run this filter on all the included glyphs. Return the set of glyph names that were modified, if any. If `glyphSet` (dict) argument is provided, run the filter on the glyphs contained therein (which may be copies). Otherwise, run the filter in-place on the font's default glyph set. """ fontName = _LazyFontName(font) if glyphSet is not None and getattr(glyphSet, "name", None): logger.info("Running %s on %s-%s", self.name, fontName, glyphSet.name) else: logger.info("Running %s on %s", self.name, fontName) if glyphSet is None: glyphSet = _GlyphSet.from_layer(font) context = self.set_context(font, glyphSet) filter_ = self.filter include = self.include modified = context.modified with Timer() as t: # we sort the glyph names to make loop deterministic for glyphName in sorted(glyphSet.keys()): if glyphName in modified: continue glyph = glyphSet[glyphName] if include(glyph) and filter_(glyph): modified.add(glyphName) num = len(modified) if num > 0: logger.debug( "Took %.3fs to run %s on %d glyph%s", t, self.name, len(modified), "" if num == 1 else "s", ) return modified
def __init__( self, ufo, inplace=False, layerName=None, skipExportGlyphs=None, filters=None, **kwargs ): self.ufo = ufo self.inplace = inplace self.layerName = layerName self.glyphSet = _GlyphSet.from_layer( ufo, layerName, copy=not inplace, skipExportGlyphs=skipExportGlyphs ) self.defaultFilters = self.initDefaultFilters(**kwargs) if filters is None: self.preFilters, self.postFilters = loadFilters(ufo) else: self.preFilters = [f for f in filters if f.pre] self.postFilters = [f for f in filters if not f.pre]
def __init__( self, ufos, inplace=False, conversionError=None, reverseDirection=True, rememberCurveType=True, layerNames=None, skipExportGlyphs=None, ): from cu2qu.ufo import DEFAULT_MAX_ERR self.ufos = ufos self.inplace = inplace if layerNames is None: layerNames = [None] * len(ufos) assert len(ufos) == len(layerNames) self.layerNames = layerNames self.glyphSets = [ _GlyphSet.from_layer(ufo, layerName, copy=not inplace, skipExportGlyphs=skipExportGlyphs) for ufo, layerName in zip(ufos, layerNames) ] self._conversionErrors = [ (conversionError or DEFAULT_MAX_ERR) * ufo.info.unitsPerEm for ufo in ufos ] self._reverseDirection = reverseDirection self._rememberCurveType = rememberCurveType self.preFilters, self.postFilters = [], [] for ufo in ufos: pre, post = loadFilters(ufo) self.preFilters.append(pre) self.postFilters.append(post)
def _getLayer(self, font, layerName): layer = self.context.layerGlyphSets.get(layerName) if layer is None: layer = _GlyphSet.from_layer(font, layerName) self.context.layerGlyphSets[layerName] = layer return layer