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)
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})
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
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
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})
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)
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})
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})
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
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
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
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
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
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)
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)
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)
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
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)