def asFea(self, indent=""): res = "" pres = (" ".join(map(asFea, self.prefix)) + " ") if len(self.prefix) else "" sufs = (" " + " ".join(map(asFea, self.suffix))) if len(self.suffix) else "" mark = "'" if len(self.prefix) or len( self.suffix) or self.forceChain else "" if self.mode == 'literal': res += "sub " + pres + " ".join( asFea(g) + mark for g in self.glyphs) + sufs + " by " res += self.replacements.asFea() + ";" return res glyphs = self.glyphs[self.multindex].glyphSet() replacements = self.replacement.glyphSet() lenreplace = len(replacements) count = max(len(glyphs), len(replacements)) for i in range(count): res += ("\n" + indent if i > 0 else "") + "sub " + pres res += " ".join( asFea(g) + mark for g in self.glyphs[:self.multindex] + [glyphs[i]] + self.glyphs[self.multindex + 1:]) res += sufs + " by " res += asFea(replacements[i if lenreplace > 1 else 0]) res += ";" return res
def asFea(g): if hasattr(g, 'asClassFea'): return g.asClassFea() elif hasattr(g, 'asFea'): return g.asFea() elif isinstance(g, tuple) and len(g) == 2: return asFea(g[0]) + "-" + asFea(g[1]) # a range elif g.lower() in ast.fea_keywords: return "\\" + g else: return g
def asFea(self, indent=""): res = "" pres = (" ".join(map(asFea, self.prefix)) + " ") if len(self.prefix) else "" sufs = (" " + " ".join(map(asFea, self.suffix))) if len(self.suffix) else "" mark = "'" if len(self.prefix) or len(self.suffix) else "" if self.mode == 'literal': res += "sub " + pres + self.glyph.asFea() + sufs + " by " res += " ".join(asFea(g)+mark for g in self.replacement) + ";" return res glyphs = self.glyph.glyphSet() replacements = self.replacement[self.multindex].glyphSet() for i in range(min(len(glyphs), len(replacements))) : res += ("\n" + indent if i > 0 else "") + "sub " + pres res += asFea(glyphs[i]) + sufs res += " by " res += " ".join(asFea(g)+mark for g in self.replacement[0:self.multindex] + [replacements[i]] + self.replacement[self.multindex+1:]) res += ";" return res
def to_asts( self, class_asts: Mapping[str, fontTools.feaLib.ast.GlyphClassDefinition], named_lookup_asts: Mapping[str, fontTools.feaLib.ast.LookupBlock], name: Union[str, int], ) -> Sequence[fontTools.feaLib.ast.Block]: """Converts this lookup to fontTools feaLib ASTs. Args: class_asts: A map to glyph classes from their names. named_lookup_asts: A map to named lookup ASTs from their names. name: The name of this lookup, if it is a named lookup, or else an arbitrary number uniquely identifying this lookup among all anonymous lookups. Returns: A list of one or two fontTools feaLib ASTs corresponding to this lookup. The first AST is always a `fontTools.feaLib.ast.LookupBlock`. If this is an anonymous lookup, the second AST is a `fontTools.feaLib.ast.FeatureBlock`. """ named_lookup = self.feature is None assert named_lookup == isinstance(name, str) contextual = any(r.is_contextual() for r in self.rules) multiple = any(r.is_multiple() for r in self.rules) if named_lookup: lookup_block = fontTools.feaLib.ast.LookupBlock(name) asts = [lookup_block] else: lookup_block = fontTools.feaLib.ast.LookupBlock(f'lookup_{name}') feature_block = fontTools.feaLib.ast.FeatureBlock(self.feature) for script in self.scripts: feature_block.statements.append( fontTools.feaLib.ast.ScriptStatement(script)) feature_block.statements.append( fontTools.feaLib.ast.LanguageStatement(self.language)) feature_block.statements.append( fontTools.feaLib.ast.LookupReferenceStatement( lookup_block)) asts = [lookup_block, feature_block] lookup_block.statements.append( fontTools.feaLib.ast.LookupFlagStatement( self.flags, markFilteringSet=fontTools.feaLib.ast.GlyphClassName( class_asts[self.mark_filtering_set]) if self.mark_filtering_set else None)) lookup_block.statements.extend({ ast.asFea(): ast for r in self.rules for ast in r.to_asts(class_asts, named_lookup_asts, contextual, multiple, self.reversed) }.values()) return asts
def asFea(self, indent=""): res = "" l = len(self.glyphs.glyphSet()) for i, glyph in enumerate(self.glyphs.glyphSet()): if i > 0: res += "\n" + indent res += "sub " if len(self.prefix) or len(self.suffix): if len(self.prefix): res += " ".join(map(asFea, self.prefix)) + " " res += asFea(glyph) + "'" # even though we really only use 1 if len(self.suffix): res += " " + " ".join(map(asFea, self.suffix)) else: res += asFea(glyph) res += " from " replacements = ast.GlyphClass(glyphs=self.replacements.glyphSet()[i::l], location=self.location) res += asFea(replacements) res += ";" return res
def asFea(self, indent=""): res = "" pres = " ".join(map(asFea, self.prefix)) if len(self.prefix) else "" sufs = " ".join(map(asFea, self.suffix)) if len(self.suffix) else "" glyphs = self.glyphs[self.multindex].glyphSet() replacements = self.replacement.glyphSet() for i in range(min(len(glyphs), len(replacements))) : res += ("\n" + indent if i > 0 else "") + "sub " if len(self.prefix) > 0 or len(self.suffix) > 0 : if len(self.prefix) : res += pres + " " res += " ".join(asFea(g) + "'" for g in self.glyphs[:self.multindex] + [glyphs[i]] + self.glyphs[self.multindex+1:]) if len(self.suffix) : res += " " + sufs else : res += " ".join(map(asFea, self.glyphs[:self.multindex] + [glyphs[i]] + self.glyphs[self.multindex+1:])) res += " by " res += asFea(replacements[i]) res += ";" return res
def asFea(self, indent=""): if not self.classBased or self.mode == "literal": return super(ast_MarkLigPosStatement, self).asFea(indent) res = [] for g in self.ligatures.glyphSet(): comps = [] for l in self.marks: onecomp = [] if l is not None and len(l): for a, m in l: if not isinstance(a, ast.Anchor): if g not in a.markClass.glyphs: continue left = a.markClass.glyphs[g].anchor.asFea() else: left = a.asFea() onecomp.append("{} mark @{}".format(left, m.name)) if not len(onecomp): onecomp = ["<anchor NULL>"] comps.append(" ".join(onecomp)) res.append("pos ligature {} ".format(asFea(g)) + ("\n"+indent+SHIFT+"ligComponent ").join(comps)) return (";\n"+indent).join(res) + ";"