Пример #1
0
 def _makeTV():
     from fontio3.GSUB import single
     
     from fontio3.opentype import (
       classdef,
       lookup,
       pschainclass_classtuple,
       pschainclass_key,
       pslookupgroup,
       pslookuprecord)
     
     single_obj = single.Single({2: 41, 4: 42, 6: 43})
     lookup_obj = lookup.Lookup([single_obj], sequence=0)
     pslookuprecord_obj = pslookuprecord.PSLookupRecord(0, lookup_obj)
     pslookupgroup_obj = pslookupgroup.PSLookupGroup([pslookuprecord_obj])
     tBack = pschainclass_classtuple.ClassTuple([1, 2])
     tIn = pschainclass_classtuple.ClassTuple([1])
     tLook = pschainclass_classtuple.ClassTuple([1])
     key_obj = pschainclass_key.Key([tBack, tIn, tLook])
     cdBack = classdef.ClassDef({51: 1, 52: 1, 54: 2, 55: 2})
     cdIn = classdef.ClassDef({2: 1, 4: 1, 6: 1})
     cdLook = classdef.ClassDef({80: 1, 81: 1, 82: 1})
     
     return ChainClass(
       {key_obj: pslookupgroup_obj},
       classDefBacktrack = cdBack,
       classDefInput = cdIn,
       classDefLookahead = cdLook)
Пример #2
0
    def _makeTV():
        from fontio3.GSUB import single

        from fontio3.opentype import (coverageset, lookup,
                                      pschaincoverage_coveragetuple,
                                      pschaincoverage_key, pslookupgroup,
                                      pslookuprecord)

        single_obj = single.Single({2: 41, 6: 43})
        lookup_obj = lookup.Lookup([single_obj], sequence=0)
        pslookuprecord_obj = pslookuprecord.PSLookupRecord(0, lookup_obj)
        pslookupgroup_obj = pslookupgroup.PSLookupGroup([pslookuprecord_obj])

        tBack = pschaincoverage_coveragetuple.CoverageTuple([
            coverageset.CoverageSet([3, 18, 29]),
            coverageset.CoverageSet([29, 90])
        ])

        tIn = pschaincoverage_coveragetuple.CoverageTuple(
            [coverageset.CoverageSet([2, 6])])

        tLook = pschaincoverage_coveragetuple.CoverageTuple([
            coverageset.CoverageSet([52, 53]),
            coverageset.CoverageSet([53, 54, 55])
        ])

        key_obj = pschaincoverage_key.Key([tBack, tIn, tLook])
        return ChainCoverage({key_obj: pslookupgroup_obj})
Пример #3
0
    def _makeTest():
        """
        The test case here recognizes the glyph sequence 25-80-26, where 25 is
        the backtrack and 26 the lookahead. The position of glyph 80 is
        adjusted.
        """

        from fontio3 import hmtx, utilities
        from fontio3.GPOS import single, value

        from fontio3.opentype import (lookup, pschainglyph_glyphtuple,
                                      pschainglyph_key, pslookupgroup,
                                      pslookuprecord)

        s1 = single.Single({80: value.Value(xPlacement=-25)})
        lk1 = lookup.Lookup([s1])
        psr1 = pslookuprecord.PSLookupRecord(0, lk1)
        psg1 = pslookupgroup.PSLookupGroup([psr1])
        backPart = pschainglyph_glyphtuple.GlyphTuple([25])
        inPart = pschainglyph_glyphtuple.GlyphTuple([80])
        lookPart = pschainglyph_glyphtuple.GlyphTuple([26])
        key1 = pschainglyph_key.Key([backPart, inPart, lookPart])
        r = ChainGlyph({key1: psg1})
        e = utilities.fakeEditor(0x10000)
        e.hmtx = hmtx.Hmtx()
        e.hmtx[25] = hmtx.MtxEntry(900, 50)
        e.hmtx[26] = hmtx.MtxEntry(970, 40)
        e.hmtx[80] = hmtx.MtxEntry(1020, 55)

        return r, e
Пример #4
0
    def _makeTest():
        """
        The test case here recognizes the glyph sequence 25-80-26, and adjusts
        the positioning of glyphs 25 and 26.
        """

        from fontio3 import hmtx
        from fontio3.GPOS import single, value

        from fontio3.opentype import (lookup, pscontextglyph_key,
                                      pslookupgroup, pslookuprecord)

        s1 = single.Single({25: value.Value(xPlacement=-25)})
        s2 = single.Single({26: value.Value(xPlacement=25)})
        s3 = single.Single({12: value.Value(xPlacement=-15)})
        s4 = single.Single({12: value.Value(xPlacement=15)})

        lk1 = lookup.Lookup([s1])
        lk2 = lookup.Lookup([s2])
        lk3 = lookup.Lookup([s3])
        lk4 = lookup.Lookup([s4])

        psr1 = pslookuprecord.PSLookupRecord(0, lk1)
        psr2 = pslookuprecord.PSLookupRecord(2, lk2)
        psr3 = pslookuprecord.PSLookupRecord(0, lk3)
        psr4 = pslookuprecord.PSLookupRecord(2, lk4)

        psg1 = pslookupgroup.PSLookupGroup([psr1, psr2])
        psg2 = pslookupgroup.PSLookupGroup([psr3, psr4])
        key1 = pscontextglyph_key.Key([25, 80, 26], ruleOrder=0)
        key2 = pscontextglyph_key.Key([12, 15, 12], ruleOrder=1)

        r = ContextGlyph({key1: psg1, key2: psg2})
        e = utilities.fakeEditor(0x10000)
        e.hmtx = hmtx.Hmtx()
        e.hmtx[12] = hmtx.MtxEntry(700, 50)
        e.hmtx[15] = hmtx.MtxEntry(690, 50)
        e.hmtx[25] = hmtx.MtxEntry(900, 50)
        e.hmtx[26] = hmtx.MtxEntry(970, 40)
        e.hmtx[80] = hmtx.MtxEntry(1020, 55)

        return r, e
Пример #5
0
    def _makeTV():
        from fontio3.GSUB import single

        from fontio3.opentype import (lookup, pscontextglyph_key,
                                      pslookupgroup, pslookuprecord)

        single_obj = single.Single({2: 41})
        lookup_obj = lookup.Lookup([single_obj], sequence=0)
        pslookuprecord_obj = pslookuprecord.PSLookupRecord(1, lookup_obj)
        pslookupgroup_obj = pslookupgroup.PSLookupGroup([pslookuprecord_obj])
        key_obj = pscontextglyph_key.Key([1, 2, 3, 4, 5])
        return ContextGlyph({key_obj: pslookupgroup_obj})
Пример #6
0
    def _makeTV():
        from fontio3.GSUB import single

        from fontio3.opentype import (classdef, lookup, pscontextclass_key,
                                      pslookupgroup, pslookuprecord)

        single_obj = single.Single({2: 41, 8: 42})
        lookup_obj = lookup.Lookup([single_obj], sequence=0)
        pslookuprecord_obj = pslookuprecord.PSLookupRecord(1, lookup_obj)
        pslookupgroup_obj = pslookupgroup.PSLookupGroup([pslookuprecord_obj])
        key_obj = pscontextclass_key.Key([1, 2, 1, 3])
        classdef_obj = classdef.ClassDef({19: 1, 2: 2, 8: 2, 12: 3})

        return ContextClass({key_obj: pslookupgroup_obj},
                            classDef=classdef_obj)
Пример #7
0
    def _makeTV():
        from fontio3.GSUB import single

        from fontio3.opentype import (lookup, pschainglyph_glyphtuple,
                                      pschainglyph_key, pslookupgroup,
                                      pslookuprecord)

        single_obj = single.Single({2: 41})
        lookup_obj = lookup.Lookup([single_obj], sequence=0)
        pslookuprecord_obj = pslookuprecord.PSLookupRecord(0, lookup_obj)
        pslookupgroup_obj = pslookupgroup.PSLookupGroup([pslookuprecord_obj])
        tBack = pschainglyph_glyphtuple.GlyphTuple([12, 8])
        tIn = pschainglyph_glyphtuple.GlyphTuple([2])
        tLook = pschainglyph_glyphtuple.GlyphTuple([5, 8, 9, 30])
        key_obj = pschainglyph_key.Key([tBack, tIn, tLook])
        return ChainGlyph({key_obj: pslookupgroup_obj})
Пример #8
0
    def _makeTV():
        from fontio3.GSUB import single

        from fontio3.opentype import (coverageset, lookup,
                                      pscontextcoverage_key, pslookupgroup,
                                      pslookuprecord)

        single_obj = single.Single({2: 41, 5: 42})
        lookup_obj = lookup.Lookup([single_obj], sequence=0)
        pslookuprecord_obj = pslookuprecord.PSLookupRecord(1, lookup_obj)
        pslookupgroup_obj = pslookupgroup.PSLookupGroup([pslookuprecord_obj])
        coverageset_obj_1 = coverageset.CoverageSet([2, 9, 10])
        coverageset_obj_2 = coverageset.CoverageSet([2, 5])

        key_obj = pscontextcoverage_key.Key(
            [coverageset_obj_1, coverageset_obj_2])

        return ContextCoverage({key_obj: pslookupgroup_obj})
Пример #9
0
    def _makeTest():
        """
        The test case here recognizes the glyph sequence 1-2-3, and adjusts the
        positioning of class 2.
        """

        from fontio3 import hmtx, utilities
        from fontio3.GPOS import single, value

        from fontio3.opentype import (classdef, lookup,
                                      pschainclass_classtuple,
                                      pschainclass_key, pslookupgroup,
                                      pslookuprecord)

        v1 = value.Value(xPlacement=-25)
        v2 = value.Value(xPlacement=-29)
        s1 = single.Single({80: v1, 81: v2, 82: v1})
        lk1 = lookup.Lookup([s1])
        psr1 = pslookuprecord.PSLookupRecord(0, lk1)
        psg = pslookupgroup.PSLookupGroup([psr1])
        backPart = pschainclass_classtuple.ClassTuple([1])
        inPart = pschainclass_classtuple.ClassTuple([1])
        lookPart = pschainclass_classtuple.ClassTuple([1])
        key = pschainclass_key.Key([backPart, inPart, lookPart])
        cdBack = classdef.ClassDef({25: 1})
        cdIn = classdef.ClassDef({80: 1, 81: 1, 82: 1})
        cdLook = classdef.ClassDef({26: 1})

        r = ChainClass({key: psg},
                       classDefBacktrack=cdBack,
                       classDefInput=cdIn,
                       classDefLookahead=cdLook)

        e = utilities.fakeEditor(0x10000)
        e.hmtx = hmtx.Hmtx()
        e.hmtx[25] = hmtx.MtxEntry(900, 50)
        e.hmtx[26] = hmtx.MtxEntry(970, 40)
        e.hmtx[80] = hmtx.MtxEntry(1020, 55)
        e.hmtx[81] = hmtx.MtxEntry(1090, 85)
        e.hmtx[82] = hmtx.MtxEntry(1050, 70)

        return r, e
Пример #10
0
    def _makeTV():
        from fontio3.GSUB import single

        cdBack = classdef.ClassDef({10: 1, 11: 1})
        cdIn = classdef.ClassDef({20: 1, 21: 1, 22: 2, 40: 3, 41: 3})
        cdLook = classdef.ClassDef({30: 1})
        back1 = pschainclass_classtuple.ClassTuple([1])
        in1 = pschainclass_classtuple.ClassTuple([1, 2])
        look1 = pschainclass_classtuple.ClassTuple([1])
        key1 = pschainclass_key.Key([back1, in1, look1], ruleOrder=0)
        sgl1 = single.Single({20: 40, 21: 41})
        lkup1 = lookup.Lookup([sgl1], sequence=22)
        rec1 = pslookuprecord.PSLookupRecord(sequenceIndex=0, lookup=lkup1)
        grp1 = pslookupgroup.PSLookupGroup([rec1])

        obj = PSChainClass({key1: grp1},
                           classDefBacktrack=cdBack,
                           classDefInput=cdIn,
                           classDefLookahead=cdLook)

        return obj
Пример #11
0
 def _makeTest():
     from fontio3 import hmtx, utilities
     from fontio3.GPOS import single, value
     
     from fontio3.opentype import (
       coverageset,
       lookup,
       pscontextcoverage_key,
       pslookupgroup,
       pslookuprecord)
     
     v1 = value.Value(xPlacement=-25)
     v2 = value.Value(xPlacement=-29)
     s1 = single.Single({20: v1, 25: v2})
     lk1 = lookup.Lookup([s1])
     psr1 = pslookuprecord.PSLookupRecord(0, lk1)
     v1 = value.Value(xPlacement=-31)
     v2 = value.Value(xPlacement=-19)
     s2 = single.Single({25: v1, 26: v2})
     lk2 = lookup.Lookup([s2])
     psr2 = pslookuprecord.PSLookupRecord(2, lk2)
     psg = pslookupgroup.PSLookupGroup([psr1, psr2])
     
     key = pscontextcoverage_key.Key([
       coverageset.CoverageSet([20, 25]),
       coverageset.CoverageSet([81, 82]),
       coverageset.CoverageSet([25, 26])])
     
     r = ContextCoverage({key: psg})
     e = utilities.fakeEditor(0x10000)
     e.hmtx = hmtx.Hmtx()
     e.hmtx[20] = hmtx.MtxEntry(910, 42)
     e.hmtx[25] = hmtx.MtxEntry(900, 50)
     e.hmtx[26] = hmtx.MtxEntry(970, 40)
     e.hmtx[80] = hmtx.MtxEntry(1020, 55)
     e.hmtx[81] = hmtx.MtxEntry(1090, 85)
     
     return r, e
Пример #12
0
    def _makeTest():
        from fontio3 import hmtx, utilities
        from fontio3.GPOS import single, value

        from fontio3.opentype import (coverageset, lookup,
                                      pschaincoverage_coveragetuple,
                                      pschaincoverage_key, pslookupgroup,
                                      pslookuprecord)

        v1 = value.Value(xPlacement=-25)
        v2 = value.Value(xPlacement=-29)
        s1 = single.Single({80: v1, 81: v2, 82: v1})
        lk1 = lookup.Lookup([s1])
        psr1 = pslookuprecord.PSLookupRecord(0, lk1)
        psg = pslookupgroup.PSLookupGroup([psr1])

        cs1 = coverageset.CoverageSet([20, 22])
        cs2 = coverageset.CoverageSet([23])
        cs3 = coverageset.CoverageSet([80, 81, 82])
        cs4 = coverageset.CoverageSet([22])
        cs5 = coverageset.CoverageSet([20, 40])
        ct1 = pschaincoverage_coveragetuple.CoverageTuple([cs1, cs2])
        ct2 = pschaincoverage_coveragetuple.CoverageTuple([cs3])
        ct3 = pschaincoverage_coveragetuple.CoverageTuple([cs4, cs5])
        key = pschaincoverage_key.Key([ct1, ct2, ct3])

        r = ChainCoverage({key: psg})
        e = utilities.fakeEditor(0x10000)
        e.hmtx = hmtx.Hmtx()
        e.hmtx[20] = hmtx.MtxEntry(910, 42)
        e.hmtx[22] = hmtx.MtxEntry(900, 50)
        e.hmtx[23] = hmtx.MtxEntry(970, 40)
        e.hmtx[40] = hmtx.MtxEntry(890, 8)
        e.hmtx[80] = hmtx.MtxEntry(1020, 55)
        e.hmtx[81] = hmtx.MtxEntry(1090, 85)
        e.hmtx[82] = hmtx.MtxEntry(1020, 55)

        return r, e
Пример #13
0
 def _makeTest():
     """
     The test case here recognizes the glyph sequence 1-2-3, and adjusts the
     positioning of classes 1 and 3.
     """
     
     from fontio3 import hmtx, utilities
     from fontio3.GPOS import single, value
     
     from fontio3.opentype import (
       classdef,
       lookup,
       pscontextclass_key,
       pslookupgroup,
       pslookuprecord)
     
     v1 = value.Value(xPlacement=-25)
     v2 = value.Value(xPlacement=-29)
     s1 = single.Single({20: v1, 25: v2})
     lk1 = lookup.Lookup([s1])
     psr1 = pslookuprecord.PSLookupRecord(0, lk1)
     s2 = single.Single({26: value.Value(xPlacement=25)})
     lk2 = lookup.Lookup([s2])
     psr2 = pslookuprecord.PSLookupRecord(2, lk2)
     psg = pslookupgroup.PSLookupGroup([psr1, psr2])
     key = pscontextclass_key.Key([1, 2, 3])
     cd = classdef.ClassDef({20: 1, 25: 1, 80: 2, 81: 2, 26: 3})
     r = ContextClass({key: psg}, classDef=cd)
     e = utilities.fakeEditor(0x10000)
     e.hmtx = hmtx.Hmtx()
     e.hmtx[20] = hmtx.MtxEntry(910, 42)
     e.hmtx[25] = hmtx.MtxEntry(900, 50)
     e.hmtx[26] = hmtx.MtxEntry(970, 40)
     e.hmtx[80] = hmtx.MtxEntry(1020, 55)
     e.hmtx[81] = hmtx.MtxEntry(1090, 85)
     
     return r, e
Пример #14
0
    def fromValidatedFontWorkerSource(cls, fws, **kwArgs):
        """
        Creates and returns a new PSContextCoverage from the specified
        FontWorkerSource, with source validation.

        >>> logger = utilities.makeDoctestLogger("FW_test")
        >>> obj = PSContextCoverage.fromValidatedFontWorkerSource(
        ...   _test_FW_fws2,
        ...   namer = _test_FW_namer,
        ...   forGPOS = True,
        ...   lookupDict = _test_FW_lookupDict,
        ...   logger = logger,
        ...   editor={})
        FW_test.pscontextcoverage - WARNING - line 14 -- unexpected token: foo
        FW_test.pscontextcoverage - WARNING - line 0 -- did not find matching 'subtable end/lookup end'
        >>> obj.pprint()
        Key((CoverageSet(frozenset({2})), CoverageSet(frozenset({5})), CoverageSet(frozenset({11})))):
          Effect #1:
            Sequence index: 0
            Lookup:
              3:
                FUnit adjustment to horizontal advance: 678
          Effect #2:
            Sequence index: 0
            Lookup:
              3:
                FUnit adjustment to horizontal advance: 901
        """
        
        logger = kwArgs.pop('logger', logging.getLogger())
        logger = logger.getChild("pscontextcoverage")
        terminalStrings = ('subtable end', 'lookup end')
        startingLineNumber=fws.lineNumber

        Key = pscontextcoverage_key.Key
        CoverageSet = coverageset.CoverageSet

        coverageList = []
        lookupGroups = {}
        fVFWS = CoverageSet.fromValidatedFontWorkerSource
        
        for line in fws:
            if line.lower() in terminalStrings:
                return cls(lookupGroups)
            
            if len(line) > 0:
                tokens = [x.strip() for x in line.split('\t')]
                
                if tokens[0].lower() == 'coverage definition begin':
                    coverageSet = fVFWS(fws, logger=logger, **kwArgs)
                    coverageList.append(coverageSet)
                
                elif tokens[0].lower() == 'coverage':
                    lookupList = []
                    
                    for effect in tokens[1:]:
                        effectTokens = [x.strip() for x in effect.split(',')]
                        sequenceIndex = int(effectTokens[0]) - 1
                        lookupName = effectTokens[1]
                        
                        lookupList.append(
                          pslookuprecord.PSLookupRecord(
                            sequenceIndex,
                            lookup.Lookup.fromValidatedFontWorkerSource(
                              fws,
                              lookupName,
                              logger=logger,
                              **kwArgs)))
                    
                    key = Key(coverageList)
                    lookupGroup = pslookupgroup.PSLookupGroup(lookupList)
                    lookupGroups[key] = lookupGroup
                
                else:
                    logger.warning((
                      'V0960',
                      (fws.lineNumber, tokens[0]),
                      'line %d -- unexpected token: %s'))
                
        logger.warning((
          'V0958',
           (startingLineNumber, "/".join(terminalStrings)),
           "line %d -- did not find matching '%s'"))
    
        return cls(lookupGroups)
Пример #15
0
    def fromValidatedFontWorkerSource(cls, fws, **kwArgs):
        """
        Creates and returns a new PSChainGlyph from the specified
        FontWorkerSource, doing source validation.

        >>> logger = utilities.makeDoctestLogger("FW_test")
        >>> obj = PSChainGlyph.fromValidatedFontWorkerSource(
        ...   _test_FW_fws2,
        ...   namer = _test_FW_namer,
        ...   forGPOS = True,
        ...   lookupDict = _test_FW_lookupDict,
        ...   logger=logger,
        ...   editor={})
        FW_test.pschainglyph - WARNING - line 2 -- unexpected token: foo
        FW_test.pschainglyph - WARNING - line 3 -- glyph 'X' not found
        FW_test.pschainglyph - WARNING - line 3 -- glyph 'Y' not found
        FW_test.pschainglyph - WARNING - line 3 -- glyph 'Z' not found
        FW_test.pschainglyph - WARNING - line 5 -- context '(A,B), (C,D,E), (F,G)' previously defined at line 4
        FW_test.pschainglyph - WARNING - line 0 -- did not find matching 'subtable end/lookup end'
        >>> obj.pprint()
        Key((GlyphTuple((2, 1)), GlyphTuple((3, 4, 5)), GlyphTuple((6, 7))), ruleOrder=0):
          Effect #1:
            Sequence index: 0
            Lookup:
              3:
                FUnit adjustment to horizontal advance: 678
          Effect #2:
            Sequence index: 0
            Lookup:
              3:
                FUnit adjustment to horizontal advance: 901
        """

        logger = kwArgs.pop('logger', logging.getLogger())
        logger = logger.getChild("pschainglyph")

        terminalStrings = ('subtable end', 'lookup end')
        namer = kwArgs['namer']
        startingLineNumber = fws.lineNumber

        ruleOrders = {}
        lookupGroups = {}
        stringKeys = {}

        GT = pschainglyph_glyphtuple.GlyphTuple
        gIFS = namer.glyphIndexFromString
        bNFGI = namer.bestNameForGlyphIndex

        for line in fws:
            if line in terminalStrings:
                return cls(lookupGroups)

            if len(line) > 0:
                tokens = [x.strip() for x in line.split('\t')]

                if tokens[0].lower() == 'glyph':

                    if len(tokens) < 4:
                        logger.warning(('Vxxxx', (fws.lineNumber, ),
                                        "line %d -- unexpected input"))
                        continue

                    glyphTuples = {}

                    glyphNamesOK = True
                    for i in range(1, 4):
                        if tokens[i].strip():
                            glyphNames = tokens[i].split(',')
                            glyphIndices = [
                                gIFS(t.strip()) for t in glyphNames
                            ]
                            for j in range(len(glyphIndices)):
                                if glyphIndices[j] is None:
                                    glyphNamesOK = False
                                    logger.warning(
                                        ('V0956', (fws.lineNumber,
                                                   glyphNames[j]),
                                         "line %d -- glyph '%s' not found"))
                        else:
                            glyphIndices = []

                        glyphTuples[i] = glyphIndices

                    if glyphNamesOK:
                        glyphTuples[1].reverse()
                        glyphTuple1 = GT(glyphTuples[1])
                        glyphTuple2 = GT(glyphTuples[2])
                        glyphTuple3 = GT(glyphTuples[3])

                        lookupList = []

                        for effect in tokens[4:]:
                            effectTokens = [
                                x.strip() for x in effect.split(',')
                            ]

                            sequenceIndex = int(effectTokens[0]) - 1
                            lookupName = effectTokens[1]

                            lookupList.append(
                                pslookuprecord.PSLookupRecord(
                                    sequenceIndex,
                                    lookup.Lookup.
                                    fromValidatedFontWorkerSource(
                                        fws,
                                        lookupName,
                                        logger=logger,
                                        **kwArgs)))

                        stringKey = "(%s), (%s), (%s)" % (",".join(
                            [bNFGI(gi) for gi in glyphTuple1[::-1]]), ",".join(
                                [bNFGI(gi) for gi in glyphTuple2]), ",".join(
                                    [bNFGI(gi) for gi in glyphTuple3]))

                        if stringKey in stringKeys:
                            logger.warning(('Vxxxx', (
                                fws.lineNumber, stringKey,
                                stringKeys[stringKey]
                            ), "line %d -- context '%s' previously defined at line %d"
                                            ))
                        else:
                            stringKeys[stringKey] = fws.lineNumber

                            key = pschainglyph_key.Key(
                                [glyphTuple1, glyphTuple2, glyphTuple3])

                            ruleOrder = ruleOrders.get(glyphTuple2[0], 0)
                            key.ruleOrder = ruleOrder
                            ruleOrders[glyphTuple2[0]] = ruleOrder + 1
                            lookupGroup = pslookupgroup.PSLookupGroup(
                                lookupList)
                            lookupGroups[key] = lookupGroup

                else:
                    logger.warning(('V0960', (fws.lineNumber, tokens[0]),
                                    'line %d -- unexpected token: %s'))

        logger.warning(
            ('V0958', (startingLineNumber, "/".join(terminalStrings)),
             "line %d -- did not find matching '%s'"))

        return cls(lookupGroups)
Пример #16
0
    def fromValidatedFontWorkerSource(cls, fws, **kwArgs):
        """
        Creates and returns a new PSContextGlyph from the specified
        FontWorkerSource, doing source validation.

        >>> logger = utilities.makeDoctestLogger("FW_test")
        >>> obj = PSContextGlyph.fromValidatedFontWorkerSource(
        ...   _test_FW_fws2,
        ...   namer = _test_FW_namer,
        ...   forGPOS = True,
        ...   lookupDict = _test_FW_lookupDict,
        ...   logger = logger,
        ...   editor={})
        FW_test.pscontextglyph - WARNING - line 2 -- unexpected token: foo
        FW_test.pscontextglyph - WARNING - line 0 -- did not find matching 'subtable end/lookup end'
        >>> obj.pprint()
        Key((1, 3, 5), ruleOrder=0):
          Effect #1:
            Sequence index: 0
            Lookup:
              3:
                FUnit adjustment to horizontal advance: 678
          Effect #2:
            Sequence index: 0
            Lookup:
              3:
                FUnit adjustment to horizontal advance: 901
        """

        logger = kwArgs.pop('logger', logging.getLogger())
        logger = logger.getChild("pscontextglyph")
        terminalStrings = ('subtable end', 'lookup end')
        namer = kwArgs['namer']
        startingLineNumber = fws.lineNumber
        ruleOrder = 0
        lookupGroups = {}

        gIFS = namer.glyphIndexFromString

        for line in fws:
            if line in terminalStrings:
                return cls(lookupGroups)

            if len(line) > 0:
                tokens = [x.strip() for x in line.split('\t')]

                if tokens[0].lower() == 'glyph':
                    glyphNames = tokens[1].split(',')
                    glyphIndices = [gIFS(t.strip()) for t in glyphNames]
                    glyphsOK = True
                    for i in range(len(glyphIndices)):
                        if glyphIndices[i] is None:
                            glyphsOK = False
                            logger.warning(
                                ('V0956', (fws.lineNumber, glyphNames[i]),
                                 "line %d -- glyph '%s' not found; "
                                 "will not make entry for this line."))

                    if glyphsOK:
                        glyphTuple = tuple(glyphIndices)

                        lookupList = []

                        for effect in tokens[2:]:
                            effectTokens = [
                                x.strip() for x in effect.split(',')
                            ]
                            sequenceIndex = int(effectTokens[0]) - 1
                            lookupName = effectTokens[1]

                            lookupList.append(
                                pslookuprecord.PSLookupRecord(
                                    sequenceIndex,
                                    lookup.Lookup.
                                    fromValidatedFontWorkerSource(
                                        fws,
                                        lookupName,
                                        logger=logger,
                                        **kwArgs)))

                        key = pscontextglyph_key.Key(glyphTuple)
                        key.ruleOrder = ruleOrder
                        ruleOrder += 1
                        lookupGroup = pslookupgroup.PSLookupGroup(lookupList)
                        lookupGroups[key] = lookupGroup

                else:
                    logger.warning(('V0960', (fws.lineNumber, tokens[0]),
                                    'line %d -- unexpected token: %s'))

        logger.warning(
            ('V0958', (startingLineNumber, "/".join(terminalStrings)),
             'line %d -- did not find matching \'%s\''))

        return cls(lookupGroups)
Пример #17
0
    def fromValidatedFontWorkerSource(cls, fws, **kwArgs):
        """
        Creates and returns a new PSChainClass from the specified
        FontWorkerSource.

        >>> logger = utilities.makeDoctestLogger("FW_test")
        >>> obj = PSChainClass.fromValidatedFontWorkerSource(
        ...   _test_FW_fws2,
        ...   namer = _test_FW_namer,
        ...   forGPOS = True,
        ...   lookupDict = _test_FW_lookupDict,
        ...   logger = logger,
        ...   editor = {})
        FW_test.pschainclass - WARNING - line 20 -- unexpected token: foo
        FW_test.pschainclass - WARNING - line 22 -- invalid backtrack class: 4
        FW_test.pschainclass - WARNING - line 22 -- invalid input class: 7
        FW_test.pschainclass - WARNING - line 22 -- invalid lookahead class: 6
        FW_test.pschainclass - WARNING - line 0 -- did not find matching 'subtable end/lookup end'
        >>> obj.pprint()
        Key((ClassTuple((2, 1, 0)), ClassTuple((0, 5)), ClassTuple((7, 8, 9, 0))), ruleOrder=0):
          Effect #1:
            Sequence index: 0
            Lookup:
              3:
                FUnit adjustment to horizontal advance: 678
          Effect #2:
            Sequence index: 0
            Lookup:
              3:
                FUnit adjustment to horizontal advance: 901
        Class definition table (backtrack):
          1: 1
          2: 2
          3: 3
        Class definition table (input):
          1: 4
          2: 5
          3: 6
        Class definition table (lookahead):
          1: 7
          2: 8
          3: 9
        """

        logger = kwArgs.pop('logger', logging.getLogger())
        logger = logger.getChild("pschainclass")
        terminalStrings = ('subtable end', 'lookup end')
        startingLineNumber = fws.lineNumber

        # place-holders
        classDefBacktrack = classdef.ClassDef()
        classDefInput = classdef.ClassDef()
        classDefLookahead = classdef.ClassDef()

        ruleOrders = {}
        lookupGroups = {}
        stringKeys = {}

        for line in fws:
            if line.lower() in terminalStrings:
                r = cls(lookupGroups,
                        classDefBacktrack=classDefBacktrack,
                        classDefInput=classDefInput,
                        classDefLookahead=classDefLookahead)

                return r

            if len(line) > 0:
                tokens = [x.strip() for x in line.split('\t')]
                fVFWS = classdef.ClassDef.fromValidatedFontWorkerSource

                if tokens[0].lower() == 'backtrackclass definition begin':
                    classDefBacktrack = fVFWS(fws, logger=logger, **kwArgs)
                    cdBackSet = set(classDefBacktrack.values())

                elif tokens[0].lower() == 'class definition begin':
                    classDefInput = fVFWS(fws, logger=logger, **kwArgs)
                    cdInputSet = set(classDefInput.values())

                elif tokens[0].lower() == 'lookaheadclass definition begin':
                    classDefLookahead = fVFWS(fws,
                                              logger=logger,
                                              dbg=True,
                                              **kwArgs)
                    cdLookSet = set(classDefLookahead.values())

                elif tokens[0].lower() == 'class-chain':
                    CT = pschainclass_classtuple.ClassTuple
                    classTuple1 = CT()
                    classTuple2 = CT()
                    classTuple3 = CT()
                    classesOK = True

                    if tokens[1] != '':
                        try:
                            classList1 = [int(x) for x in tokens[1].split(',')]
                            classList1.reverse(
                            )  # backtrack goes in reverse order
                        except:
                            logger.warning((
                                'Vxxxx', (fws.lineNumber, tokens[1]),
                                'line %d -- invalid backtrack definition: %s'))

                            classesOK = False

                        for classNum in classList1:
                            if classNum == 0:
                                continue

                            if not classNum in cdBackSet:
                                logger.warning(
                                    ('V0962', (fws.lineNumber, classNum),
                                     'line %d -- invalid backtrack class: %d'))

                                classesOK = False

                        classTuple1 = CT(classList1)

                    if tokens[2] != '':
                        try:
                            classList2 = [int(x) for x in tokens[2].split(',')]
                        except ValueError:
                            logger.warning(
                                ('Vxxxx', (fws.lineNumber, tokens[2]),
                                 'line %d -- invalid input definition: %s'))

                            classesOK = False

                        for classNum in classList2:
                            if classNum == 0:
                                continue

                            if not classNum in cdInputSet:
                                logger.warning(
                                    ('V0962', (fws.lineNumber, classNum),
                                     'line %d -- invalid input class: %d'))

                                classesOK = False

                        classTuple2 = CT(classList2)

                    if tokens[3] != '':
                        try:
                            classList3 = [int(x) for x in tokens[3].split(',')]
                        except ValueError:
                            logger.warning((
                                'Vxxxx', (fws.lineNumber, tokens[3]),
                                'line %d -- invalid lookahead definition: %s'))

                            classesOK = False

                        for classNum in classList3:
                            if classNum == 0:
                                continue

                            if not classNum in cdLookSet:
                                logger.warning(
                                    ('V0962', (fws.lineNumber, classNum),
                                     'line %d -- invalid lookahead class: %d'))

                                classesOK = False

                        classTuple3 = CT(classList3)

                    if not classesOK:
                        continue

                    lookupList = []

                    for effect in tokens[4:]:
                        effectTokens = [x.strip() for x in effect.split(',')]
                        sequenceIndex = int(effectTokens[0]) - 1
                        lookupName = effectTokens[1]

                        lookupList.append(
                            pslookuprecord.PSLookupRecord(
                                sequenceIndex,
                                lookup.Lookup.fromValidatedFontWorkerSource(
                                    fws, lookupName, logger=logger, **kwArgs)))

                    stringKey = "(%s), (%s), (%s)" % (",".join([
                        str(ci) for ci in classTuple1[::-1]
                    ]), ",".join([str(ci) for ci in classTuple2]), ",".join(
                        [str(ci) for ci in classTuple3]))

                    if stringKey in stringKeys:
                        logger.warning(('Vxxxx', (
                            fws.lineNumber, stringKey, stringKeys[stringKey]
                        ), "line %d -- context '%s' previously defined at line %d"
                                        ))

                    else:
                        stringKeys[stringKey] = fws.lineNumber

                        key = pschainclass_key.Key(
                            [classTuple1, classTuple2, classTuple3])

                        ruleOrder = ruleOrders.get(classTuple2[0], 0)
                        key.ruleOrder = ruleOrder
                        ruleOrders[classTuple2[0]] = ruleOrder + 1
                        lookupGroup = pslookupgroup.PSLookupGroup(lookupList)
                        lookupGroups[key] = lookupGroup

                else:
                    logger.warning(('V0960', (fws.lineNumber, tokens[0]),
                                    'line %d -- unexpected token: %s'))

        logger.warning(
            ('V0958', (startingLineNumber, "/".join(terminalStrings)),
             "line %d -- did not find matching '%s'"))

        r = cls(lookupGroups,
                classDefBacktrack=classDefBacktrack,
                classDefInput=classDefInput,
                classDefLookahead=classDefLookahead)

        return r
Пример #18
0
    def fromValidatedFontWorkerSource(cls, fws, **kwArgs):
        """
        Creates and returns a new PSChainCoverage from the specified
        FontWorkerSource, doing source validation.

        >>> logger = utilities.makeDoctestLogger("FW_test")
        >>> obj = PSChainCoverage.fromValidatedFontWorkerSource(
        ...   _test_FW_fws2,
        ...   namer = _test_FW_namer,
        ...   forGPOS = True,
        ...   lookupDict = _test_FW_lookupDict,
        ...   logger = logger,
        ...   editor = {})
        FW_test.pschaincoverage - WARNING - line 16 -- unexpected token: foo
        FW_test.pschaincoverage - WARNING - line 0 -- did not find matching 'subtable end/lookup end'
        >>> obj.pprint()
        Key((CoverageTuple((CoverageSet(frozenset({2})),)), CoverageTuple((CoverageSet(frozenset({5, 7})),)), CoverageTuple((CoverageSet(frozenset({11, 13})),)))):
          Effect #1:
            Sequence index: 0
            Lookup:
              3:
                FUnit adjustment to horizontal advance: 678
          Effect #2:
            Sequence index: 0
            Lookup:
              3:
                FUnit adjustment to horizontal advance: 901
        """
        logger = kwArgs.pop('logger', logging.getLogger())
        logger = logger.getChild("pschaincoverage")

        terminalStrings = ('subtable end', 'lookup end')
        startingLineNumber = fws.lineNumber

        CoverageTuple = pschaincoverage_coveragetuple.CoverageTuple
        Key = pschaincoverage_key.Key
        fVFWS = coverageset.CoverageSet.fromValidatedFontWorkerSource

        # initial lists; will be converted to CoverageTuple later
        backtracks = []
        inputs = []
        lookaheads = []

        lookupGroups = {}

        for line in fws:
            if len(line) > 0:
                tokens = [x.strip() for x in line.split('\t')]

                # NOTE: added '.lower()' to token parsing as FontWorker seems to
                # write 'Backtrackcoverage', 'Inputcoverage', and
                # 'LookAheadcoverage', unlike other lookups which are all
                # lowercase.

                if tokens[0].lower() in terminalStrings:
                    return cls(lookupGroups)

                if tokens[0].lower() == 'backtrackcoverage definition begin':
                    backtracks.append(fVFWS(fws, logger=logger, **kwArgs))

                elif tokens[0].lower() == 'inputcoverage definition begin':
                    inputs.append(fVFWS(fws, logger=logger, **kwArgs))

                elif tokens[0].lower() == 'lookaheadcoverage definition begin':
                    lookaheads.append(fVFWS(fws, logger=logger, **kwArgs))

                elif tokens[0].lower() == 'coverage':
                    lookupList = []

                    for effect in tokens[1:]:
                        effectTokens = [x.strip() for x in effect.split(',')]
                        sequenceIndex = int(effectTokens[0]) - 1
                        lookupName = effectTokens[1]

                        lookupList.append(
                            pslookuprecord.PSLookupRecord(
                                sequenceIndex,
                                lookup.Lookup.fromValidatedFontWorkerSource(
                                    fws, lookupName, logger=logger, **kwArgs)))

                    key = Key(
                        (CoverageTuple(reversed(backtracks)),
                         CoverageTuple(inputs), CoverageTuple(lookaheads)))

                    lookupGroup = pslookupgroup.PSLookupGroup(lookupList)
                    lookupGroups[key] = lookupGroup

                else:
                    logger.warning(('V0960', (fws.lineNumber, tokens[0]),
                                    'line %d -- unexpected token: %s'))

        logger.warning(
            ('V0958', (startingLineNumber, "/".join(terminalStrings)),
             "line %d -- did not find matching '%s'"))

        return cls(lookupGroups)