def makeLookup1(): # make a variation of the shell TTX data f = open(shellSourcePath) ttxData = f.read() f.close() ttxData = ttxData.replace("__familyName__", "gsubtest-lookup1") tempShellSourcePath = shellSourcePath + ".temp" f = open(tempShellSourcePath, "wb") f.write(ttxData) f.close() # compile the shell shell = TTFont(sfntVersion="OTTO") shell.importXML(tempShellSourcePath) shell.save(shellTempPath) os.remove(tempShellSourcePath) # load the shell shell = TTFont(shellTempPath) # grab the PASS and FAIL data hmtx = shell["hmtx"] glyphSet = shell.getGlyphSet() failGlyph = glyphSet["F"] failGlyph.decompile() failGlyphProgram = list(failGlyph.program) failGlyphMetrics = hmtx["F"] passGlyph = glyphSet["P"] passGlyph.decompile() passGlyphProgram = list(passGlyph.program) passGlyphMetrics = hmtx["P"] # grab some tables hmtx = shell["hmtx"] cmap = shell["cmap"] # start the glyph order existingGlyphs = [".notdef", "space", "F", "P"] glyphOrder = list(existingGlyphs) # start the CFF cff = shell["CFF "].cff globalSubrs = cff.GlobalSubrs topDict = cff.topDictIndex[0] topDict.charset = existingGlyphs private = topDict.Private charStrings = topDict.CharStrings charStringsIndex = charStrings.charStringsIndex features = sorted(mapping) # build the outline, hmtx and cmap data cp = baseCodepoint for index, tag in enumerate(features): # tag.pass glyphName = "%s.pass" % tag glyphOrder.append(glyphName) addGlyphToCFF( glyphName=glyphName, program=passGlyphProgram, private=private, globalSubrs=globalSubrs, charStringsIndex=charStringsIndex, topDict=topDict, charStrings=charStrings, ) hmtx[glyphName] = passGlyphMetrics for table in cmap.tables: if table.format == 4: table.cmap[cp] = glyphName else: raise NotImplementedError("Unsupported cmap table format: %d" % table.format) cp += 1 # tag.fail glyphName = "%s.fail" % tag glyphOrder.append(glyphName) addGlyphToCFF( glyphName=glyphName, program=failGlyphProgram, private=private, globalSubrs=globalSubrs, charStringsIndex=charStringsIndex, topDict=topDict, charStrings=charStrings, ) hmtx[glyphName] = failGlyphMetrics for table in cmap.tables: if table.format == 4: table.cmap[cp] = glyphName else: raise NotImplementedError("Unsupported cmap table format: %d" % table.format) # bump this up so that the sequence is the same as the lookup 3 font cp += 3 # set the glyph order shell.setGlyphOrder(glyphOrder) # start the GSUB shell["GSUB"] = newTable("GSUB") gsub = shell["GSUB"].table = GSUB() gsub.Version = 1.0 # make a list of all the features we will make featureCount = len(features) # set up the script list scriptList = gsub.ScriptList = ScriptList() scriptList.ScriptCount = 1 scriptList.ScriptRecord = [] scriptRecord = ScriptRecord() scriptList.ScriptRecord.append(scriptRecord) scriptRecord.ScriptTag = "DFLT" script = scriptRecord.Script = Script() defaultLangSys = script.DefaultLangSys = DefaultLangSys() defaultLangSys.FeatureCount = featureCount defaultLangSys.FeatureIndex = range(defaultLangSys.FeatureCount) defaultLangSys.ReqFeatureIndex = 65535 defaultLangSys.LookupOrder = None script.LangSysCount = 0 script.LangSysRecord = [] # set up the feature list featureList = gsub.FeatureList = FeatureList() featureList.FeatureCount = featureCount featureList.FeatureRecord = [] for index, tag in enumerate(features): # feature record featureRecord = FeatureRecord() featureRecord.FeatureTag = tag feature = featureRecord.Feature = Feature() featureList.FeatureRecord.append(featureRecord) # feature feature.FeatureParams = None feature.LookupCount = 1 feature.LookupListIndex = [index] # write the lookups lookupList = gsub.LookupList = LookupList() lookupList.LookupCount = featureCount lookupList.Lookup = [] for tag in features: # lookup lookup = Lookup() lookup.LookupType = 1 lookup.LookupFlag = 0 lookup.SubTableCount = 1 lookup.SubTable = [] lookupList.Lookup.append(lookup) # subtable subtable = SingleSubst() subtable.Format = 2 subtable.LookupType = 1 subtable.mapping = { "%s.pass" % tag: "%s.fail" % tag, "%s.fail" % tag: "%s.pass" % tag, } lookup.SubTable.append(subtable) path = outputPath % 1 + ".otf" if os.path.exists(path): os.remove(path) shell.save(path) # get rid of the shell if os.path.exists(shellTempPath): os.remove(shellTempPath)
def buildGSUB(self): """Constructs a basic GSUB table. Test cases can modify this table for their own usage. Return: { LookupList: { Lookup: [ { LookupType: 4, # Ligature LookupFlag: 0, SubTable: [ ligatures: { 'f': { LigGlyph: 'f_i', Component: 'i', CompCount: 2, }, }, Format: 1, LookupType: 4, # Ligature ], SubTableCount = 1, }, ], LookupCount = 1, }, FeatureList: { FeatureRecord: [ { FeatureTag: 'liga', Feature: { FeatureParams: None, LookupCount: 1, LookupListIndex: [0], }, }, ], FeatureCount: 1, }, ScriptList: { ScriptRecord: [ { ScriptTag: 'tag1', Script: { DefaultLangSys: { LookupOrder: None, ReqFeatureIndex: 0xffff, FeatureIndex: [0], FeatureCount: 1, } } } ], ScriptCount: 1, }, } """ # Construct GSUB table bottom-up. li_fi = Ligature() li_fi.LigGlyph = 'f_i' li_fi.Component = ['i'] li_fi.CompCount = 2 liSubst = LigatureSubst() liSubst.ligatures = {'f': li_fi} liSubst.Format = 1 liSubst.LookupType = 4 lookup = Lookup() lookup.LookupType = 4 # Ligature lookup.LookupFlag = 0 lookup.SubTable = [liSubst] lookup.SubTableCount = len(lookup.SubTable) lookupList = LookupList() lookupList.Lookup = [lookup] lookupList.LookupCount = len(lookupList.Lookup) fea = Feature() fea.FeatureParams = None fea.LookupCount = 1 fea.LookupListIndex = [0] feaRecord = FeatureRecord() feaRecord.FeatureTag = 'liga' feaRecord.Feature = fea feaList = FeatureList() feaList.FeatureRecord = [feaRecord] feaList.FeatureCount = len(feaList.FeatureRecord) langSys = LangSys() langSys.LookupOrder = None langSys.ReqFeatureIndex = 0xFFFF langSys.FeatureIndex = [0] langSys.FeatureCount = len(langSys.FeatureIndex) sct = Script() sct.DefaultLangSys = langSys sct.LangSysRecord = [] sct.LangSysCount = len(sct.LangSysRecord) sctRec = ScriptRecord() sctRec.ScriptTag = 'tag1' sctRec.Script = sct sctList = ScriptList() sctList.ScriptRecord = [sctRec] sctList.ScriptCount = len(sctList.ScriptRecord) gsub = GSUB() gsub.LookupList = lookupList gsub.FeatureList = feaList gsub.ScriptList = sctList table = ttLib.newTable('GSUB') table.table = gsub return table