def renameClasses(self, oldToNew): """ Renames all class names (in each StateRow, and in the class table) as specified by the oldToNew dict, which maps old strings to new ones. If an old name is not present as a key in oldToNew, that class name will not be changed. """ ct = classtable.ClassTable() for glyph, className in self.classTable.items(): ct[glyph] = oldToNew.get(className, className) self.classTable = ct for stateName in self: stateRow = self[stateName] sr = staterow_ligature.StateRow() for className, entryObj in stateRow.items(): sr[oldToNew.get(className, className)] = entryObj self[stateName] = sr
def _makeObj(): GLYPH_c = 70 GLYPH_e = 72 GLYPH_f = 73 GLYPH_i = 76 GLYPH_l = 79 GLYPH_o = 82 GLYPH_fi = 192 GLYPH_fl = 193 GLYPH_ff = 330 GLYPH_ffi = 331 GLYPH_ffl = 332 GLYPH_special = 873 Entry = entry_ligature.Entry GTD = glyphtupledict.GlyphTupleDict GTI = glyphtuple.GlyphTupleInput GTO = glyphtuple.GlyphTupleOutput StateRow = staterow_ligature.StateRow classTable = classtable.ClassTable({ GLYPH_c: "c", GLYPH_e: "e", GLYPH_f: "f", GLYPH_i: "i", GLYPH_l: "l", GLYPH_o: "o"}) cov = coverage.Coverage(always=True, kind=2) entry0 = Entry( newState = "Start of text") entry1 = Entry( newState = "Saw f", push = True) entry2 = Entry( newState = "Saw o", push = True) entry3 = Entry( newState = "Saw ff", push = True, actions = GTD({ GTI((GLYPH_f, GLYPH_f)): GTO((GLYPH_ff, None))})) entry4 = Entry( newState = "Start of text", push = True, actions = GTD({ GTI((GLYPH_f, GLYPH_i)): GTO((GLYPH_fi, None)), GTI((GLYPH_f, GLYPH_l)): GTO((GLYPH_fl, None))})) entry5 = Entry( newState = "Start of text", push = True, actions = GTD({ GTI((GLYPH_ff, GLYPH_i)): GTO((GLYPH_ffi, None)), GTI((GLYPH_ff, GLYPH_l)): GTO((GLYPH_ffl, None))})) entry6 = Entry( newState = "Saw of", push = True) entry7 = Entry( newState = "Saw off", push = True, actions = GTD({ GTI((GLYPH_f, GLYPH_f)): GTO((GLYPH_ff, None))})) entry8 = Entry( newState = "Saw offi", push = True, actions = GTD({ GTI((GLYPH_ff, GLYPH_i)): GTO((GLYPH_ffi, None))})) entry9 = Entry( newState = "Saw offic", push = True) entry10 = Entry( newState = "Start of text", push = True, actions = GTD({ GTI((GLYPH_o, GLYPH_ffi, GLYPH_c, GLYPH_e)): GTO((GLYPH_special, None, None, None))})) row_SOT = StateRow({ "End of text": entry0, "Out of bounds": entry0, "Deleted glyph": entry0, "End of line": entry0, "c": entry0, "e": entry0, "f": entry1, "i": entry0, "l": entry0, "o": entry2}) row_SOL = StateRow({ "End of text": entry0, "Out of bounds": entry0, "Deleted glyph": entry0, "End of line": entry0, "c": entry0, "e": entry0, "f": entry1, "i": entry0, "l": entry0, "o": entry2}) row_Sawf = StateRow({ "End of text": entry0, "Out of bounds": entry0, "Deleted glyph": entry0, "End of line": entry0, "c": entry0, "e": entry0, "f": entry3, "i": entry4, "l": entry4, "o": entry2}) row_Sawff = StateRow({ "End of text": entry0, "Out of bounds": entry0, "Deleted glyph": entry0, "End of line": entry0, "c": entry0, "e": entry0, "f": entry1, "i": entry5, "l": entry5, "o": entry2}) row_Sawo = StateRow({ "End of text": entry0, "Out of bounds": entry0, "Deleted glyph": entry0, "End of line": entry0, "c": entry0, "e": entry0, "f": entry6, "i": entry0, "l": entry0, "o": entry2}) row_Sawof = StateRow({ "End of text": entry0, "Out of bounds": entry0, "Deleted glyph": entry0, "End of line": entry0, "c": entry0, "e": entry0, "f": entry7, "i": entry4, "l": entry4, "o": entry2}) row_Sawoff = StateRow({ "End of text": entry0, "Out of bounds": entry0, "Deleted glyph": entry0, "End of line": entry0, "c": entry0, "e": entry0, "f": entry1, "i": entry8, "l": entry5, "o": entry2}) row_Sawoffi = StateRow({ "End of text": entry0, "Out of bounds": entry0, "Deleted glyph": entry0, "End of line": entry0, "c": entry9, "e": entry0, "f": entry1, "i": entry0, "l": entry0, "o": entry2}) row_Sawoffic = StateRow({ "End of text": entry0, "Out of bounds": entry0, "Deleted glyph": entry0, "End of line": entry0, "c": entry0, "e": entry10, "f": entry1, "i": entry0, "l": entry0, "o": entry2}) ligTable = Ligature( { "Start of text": row_SOT, "Start of line": row_SOL, "Saw f": row_Sawf, "Saw ff": row_Sawff, "Saw o": row_Sawo, "Saw of": row_Sawof, "Saw off": row_Sawoff, "Saw offi": row_Sawoffi, "Saw offic": row_Sawoffic}, coverage = cov, maskValue = 0x00000080, classTable = classTable) return ligTable
def _classTableFromKeyGroup(keyGroup, nm): """ Creates and returns a new ClassTable object based on an analysis of the specified keyGroup, which should be a dict mapping input glyph tuples to ligature glyphs. This analysis takes into account sharing classes for glyphs whose behaviors are similar enough. Note that partial overlaps should already have been resolved (i.e. the keyGroup passed in should have passed a prior _separatedKeys() call) before this method is called. <<< tm = _getTestDataModule() <<< ligObj = tm.makeGSUBObj() <<< postObj = tm.makePOSTObj() <<< vKeyGroups = ligObj._separatedKeys() <<< len(vKeyGroups) 1 <<< nm = lambda n: postObj[n] <<< Ligature._classTableFromKeyGroup(ligObj, nm).pprint() 4: group candrabindudeva 5: group candrabindudeva 11: group iideva 16: group iideva 17: group iideva 19: group iideva 20: group iideva 21: group iideva 22: group iideva 23: group iideva 65: group iivowelsigndeva 70: group iivowelsigndeva 71: group iivowelsigndeva 72: group iivowelsigndeva 73: group iivowelsigndeva 74: group iivowelsigndeva 75: group iivowelsigndeva 76: group iivowelsigndeva 77: group iivowelsigndeva 110: group iideva 122: group iideva 125: group iideva 126: group iideva 128: group iideva 129: group iideva 130: group iideva 131: group iideva 132: group iideva 158: group rephdeva 412: group rephdeva """ from fontio3.morx import classtable ct = classtable.ClassTable() d = {} for inTuple, lig in keyGroup.items(): currState = "SOT" for i, glyph in enumerate(inTuple): sr = d.setdefault(currState, {}) if i == (len(inTuple) - 1): t = ("SOT", lig) else: if i: s = "%s-%d" % (currState, glyph) else: s = "Saw %d" % (glyph,) t = (s, None) sr[glyph] = t currState = t[0] leafTriggers = {k[-1] for k in keyGroup} dTailSames = {} for trigger in leafTriggers: s = { stateName for stateName, dSub in d.items() if (stateName != "SOT") and (trigger in dSub)} dTailSames.setdefault(frozenset(s), set()).add(trigger) for tailSameSet in dTailSames.values(): if len(tailSameSet) == 1: trigger = tailSameSet.pop() ct[trigger] = nm(trigger) else: s = "group %s" % (nm(min(tailSameSet)),) for trigger in tailSameSet: ct[trigger] = s headTriggers = set(d) - {'SOT'} dHeadSames = {} for trigger in headTriggers: dSub = d[trigger] dHeadSames.setdefault(frozenset(dSub), set()).add(trigger) for headSameSet in dHeadSames.values(): if len(headSameSet) > 1: glyphs = {int(s[4:]) for s in headSameSet if '-' not in s} if glyphs: s = "group %s" % (nm(min(glyphs)),) for glyph in glyphs: ct[glyph] = s allSingleGlyphs = {glyph for key in keyGroup for glyph in key} for glyph in allSingleGlyphs: if glyph not in ct: ct[glyph] = nm(glyph) return ct
# if 0: def __________________(): pass if __debug__: from fontio3 import utilities from fontio3.morx import coverage from fontio3.utilities import namer # The test case does an AxD => DxA rearrangement on a grouping starting # with glyph 12 and ending with glyph 19, but only if glyph 50 has been # seen first. _classTable = classtable.ClassTable({ 12: "First", 19: "Last", 50: "Trigger"}) E = entry_rearrangement.Entry V = verbs_rearrangement.Verb _entry_NOP_noTrigger = E() _entry_NOP_trigger = E(newState="Saw trigger") _entry_first = E(newState="Saw first", markFirst=True) _entry_NOP_first = E(newState="Saw first") _entry_last = E(markLast=True, verb=V(3)) del E, V _row_SOT = staterow_rearrangement.StateRow({ "End of text": _entry_NOP_noTrigger, "Out of bounds": _entry_NOP_noTrigger, "Deleted glyph": _entry_NOP_noTrigger,
def fromglyphdict(cls, d, **kwArgs): """ Given a dict mapping trigger glyphs to to-be-inserted sequences, returns an Insertion subtable that does this. This is a simple table, with only the two fixed states. >>> d = {20: (50, 51), 21: (52, 53, 54, 55)} >>> Insertion.fromglyphdict(d).pprint(onlySignificant=True) State 'Start of text': Class 'glyph 20': Insert glyphs before current: False Glyphs to insert at current: 0: 50 1: 51 Current insertion is kashida-like: True Name of next state: Start of text Class 'glyph 21': Insert glyphs before current: False Glyphs to insert at current: 0: 52 1: 53 2: 54 3: 55 Current insertion is kashida-like: True Name of next state: Start of text State 'Start of line': Class 'glyph 20': Insert glyphs before current: False Glyphs to insert at current: 0: 50 1: 51 Current insertion is kashida-like: True Name of next state: Start of text Class 'glyph 21': Insert glyphs before current: False Glyphs to insert at current: 0: 52 1: 53 2: 54 3: 55 Current insertion is kashida-like: True Name of next state: Start of text Class table: 20: glyph 20 21: glyph 21 Mask value: (no data) Coverage: (no data) """ ct = classtable.ClassTable({g: "glyph %d" % (g, ) for g in d}) sot = staterow_insertion.StateRow() entryNOP = entry_insertion.Entry() sot["End of text"] = entryNOP sot["Out of bounds"] = entryNOP sot["Deleted glyph"] = entryNOP sot["End of line"] = entryNOP for g, v in d.items(): sot["glyph %d" % (g, )] = entry_insertion.Entry( currentInsertBefore=False, currentInsertGlyphs=glyphtuple.GlyphTupleOutput(v), currentIsKashidaLike=True) kwArgs.pop('classTable', None) r = cls({}, classTable=ct, **utilities.filterKWArgs(cls, kwArgs)) r["Start of text"] = sot r["Start of line"] = sot return r
if __debug__: from fontio3 import utilities from fontio3.morx import coverage # _testingValues[0] is an insertion action that looks for the string "Dave" # and, if found, puts a fleuron at each end. The glyph codes are as follow: # # 'D' is glyph 12 # 'a' is glyph 41 # 'v' is glyph 62 # 'e' is glyph 45 # left fleuron is glyph 96 # right fleuron is glyph 97 _classTable = classtable.ClassTable({12: "D", 41: "a", 62: "v", 45: "e"}) E = entry_insertion.Entry GTO = glyphtuple.GlyphTupleOutput _entry_NOP = E() _entry_D = E(newState="Saw D", mark=True) _entry_D_nomark = E(newState="Saw D") _entry_Da = E(newState="Saw Da") _entry_Dav = E(newState="Saw Dav") _entry_Dave = E(newState="Start of text", currentInsertGlyphs=GTO([97]), currentIsKashidaLike=True, markedInsertGlyphs=GTO([96]), markedIsKashidaLike=True, markedInsertBefore=True)
def __________________(): pass if __debug__: from fontio3.morx import coverage from fontio3.utilities import namer # The test case changes input glyphs 22-25 into output glyphs 95-98, but # only if glyph 50 is seen earlier in the run. _classTable = classtable.ClassTable({ 22: "Swash", 23: "Swash", 24: "Swash", 25: "Swash", 50: "Trigger" }) _entry_NOP_noTrigger = entry_contextual.Entry(newState="Start of text") _entry_NOP_trigger = entry_contextual.Entry(newState="Saw trigger") _entry_doSubst = entry_contextual.Entry( newState="Saw trigger", currSubstitutionDict=glyphdict.GlyphDict({ 22: 95, 23: 96, 24: 97, 25: 98 }))