Exemple #1
0
 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
Exemple #2
0
 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
Exemple #3
0
 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,
Exemple #5
0
    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
Exemple #6
0
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
        }))