def parse_position_base_(self, enumerated, vertical): location = self.cur_token_location_ self.expect_keyword_("base") if enumerated: raise FeatureLibError( '"enumerate" is not allowed with ' 'mark-to-base attachment positioning', location) base = self.parse_glyphclass_(accept_glyphname=True).glyphSet() marks = self.parse_anchor_marks_() self.expect_symbol_(";") return ast.MarkBasePosStatement(location, base, marks)
def _gposLookup(self, lookup, fealookup): statements = fealookup.statements pos = lookup.pos if isinstance(pos, VAst.PositionAdjustPairDefinition): for (idx1, idx2), (pos1, pos2) in pos.adjust_pair.items(): coverage_1 = pos.coverages_1[idx1 - 1] coverage_2 = pos.coverages_2[idx2 - 1] # If not both are groups, use “enum pos” otherwise makeotf will # fail. enumerated = False for item in coverage_1 + coverage_2: if not isinstance(item, VAst.GroupName): enumerated = True glyphs1 = self._coverage(coverage_1) glyphs2 = self._coverage(coverage_2) record1 = self._adjustment(pos1) record2 = self._adjustment(pos2) assert len(glyphs1) == 1 assert len(glyphs2) == 1 statements.append( ast.PairPosStatement(glyphs1[0], record1, glyphs2[0], record2, enumerated=enumerated)) elif isinstance(pos, VAst.PositionAdjustSingleDefinition): for a, b in pos.adjust_single: glyphs = self._coverage(a) record = self._adjustment(b) assert len(glyphs) == 1 statements.append( ast.SinglePosStatement([(glyphs[0], record)], [], [], False)) elif isinstance(pos, VAst.PositionAttachDefinition): anchors = {} for marks, classname in pos.coverage_to: for mark in marks: # Set actually used mark classes. Basically a hack to get # around the feature file syntax limitation of making mark # classes global and not allowing mark positioning to # specify mark coverage. for name in mark.glyphSet(): key = (name, "MARK_" + classname) self._markclasses[key].used = True markclass = ast.MarkClass(self._className(classname)) for base in pos.coverage: for name in base.glyphSet(): if name not in anchors: anchors[name] = [] if classname not in anchors[name]: anchors[name].append(classname) for name in anchors: components = 1 if name in self._ligatures: components = self._ligatures[name] marks = [] for mark in anchors[name]: markclass = ast.MarkClass(self._className(mark)) for component in range(1, components + 1): if len(marks) < component: marks.append([]) anchor = None if component in self._anchors[name][mark]: anchor = self._anchors[name][mark][component] marks[component - 1].append((anchor, markclass)) base = self._glyphName(name) if name in self._marks: mark = ast.MarkMarkPosStatement(base, marks[0]) elif name in self._ligatures: mark = ast.MarkLigPosStatement(base, marks) else: mark = ast.MarkBasePosStatement(base, marks[0]) statements.append(mark) elif isinstance(pos, VAst.PositionAttachCursiveDefinition): # Collect enter and exit glyphs enter_coverage = [] for coverage in pos.coverages_enter: for base in coverage: for name in base.glyphSet(): enter_coverage.append(name) exit_coverage = [] for coverage in pos.coverages_exit: for base in coverage: for name in base.glyphSet(): exit_coverage.append(name) # Write enter anchors, also check if the glyph has exit anchor and # write it, too. for name in enter_coverage: glyph = self._glyphName(name) entry = self._anchors[name]["entry"][1] exit = None if name in exit_coverage: exit = self._anchors[name]["exit"][1] exit_coverage.pop(exit_coverage.index(name)) statements.append(ast.CursivePosStatement(glyph, entry, exit)) # Write any remaining exit anchors. for name in exit_coverage: glyph = self._glyphName(name) exit = self._anchors[name]["exit"][1] statements.append(ast.CursivePosStatement(glyph, None, exit)) else: raise NotImplementedError(pos)