diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /layout/reftests/fonts/gsubtest/makegsubfonts.py | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip |
Add m-esr52 at 52.6.0
Diffstat (limited to 'layout/reftests/fonts/gsubtest/makegsubfonts.py')
-rw-r--r-- | layout/reftests/fonts/gsubtest/makegsubfonts.py | 486 |
1 files changed, 486 insertions, 0 deletions
diff --git a/layout/reftests/fonts/gsubtest/makegsubfonts.py b/layout/reftests/fonts/gsubtest/makegsubfonts.py new file mode 100644 index 000000000..a8aedef0f --- /dev/null +++ b/layout/reftests/fonts/gsubtest/makegsubfonts.py @@ -0,0 +1,486 @@ + +import os +import textwrap +from xml.etree import ElementTree +from fontTools.ttLib import TTFont, newTable +from fontTools.misc.psCharStrings import T2CharString +from fontTools.ttLib.tables.otTables import GSUB,\ + ScriptList, ScriptRecord, Script, DefaultLangSys,\ + FeatureList, FeatureRecord, Feature,\ + LookupList, Lookup, AlternateSubst, SingleSubst + +# paths +directory = os.path.dirname(__file__) +shellSourcePath = os.path.join(directory, "gsubtest-shell.ttx") +shellTempPath = os.path.join(directory, "gsubtest-shell.otf") +featureList = os.path.join(directory, "gsubtest-features.txt") +javascriptData = os.path.join(directory, "gsubtest-features.js") +outputPath = os.path.join(os.path.dirname(directory), "gsubtest-lookup%d") + +baseCodepoint = 0xe000 + +# ------- +# Features +# ------- + +f = open(featureList, "rb") +text = f.read() +f.close() +mapping = [] +for line in text.splitlines(): + line = line.strip() + if not line: + continue + if line.startswith("#"): + continue + # parse + values = line.split("\t") + tag = values.pop(0) + mapping.append(tag); + +# -------- +# Outlines +# -------- + +def addGlyphToCFF(glyphName=None, program=None, private=None, globalSubrs=None, charStringsIndex=None, topDict=None, charStrings=None): + charString = T2CharString(program=program, private=private, globalSubrs=globalSubrs) + charStringsIndex.append(charString) + glyphID = len(topDict.charset) + charStrings.charStrings[glyphName] = glyphID + topDict.charset.append(glyphName) + +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 makeLookup3(): + # make a variation of the shell TTX data + f = open(shellSourcePath) + ttxData = f.read() + f.close() + ttxData = ttxData.replace("__familyName__", "gsubtest-lookup3") + 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 + + # 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 + + # tag.default + glyphName = "%s.default" % 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.alt1,2,3 + for i in range(1,4): + glyphName = "%s.alt%d" % (tag, i) + 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 + cp += 1 + + # 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 = 3 + lookup.LookupFlag = 0 + lookup.SubTableCount = 1 + lookup.SubTable = [] + lookupList.Lookup.append(lookup) + # subtable + subtable = AlternateSubst() + subtable.Format = 1 + subtable.LookupType = 3 + subtable.alternates = { + "%s.default" % tag : ["%s.fail" % tag, "%s.fail" % tag, "%s.fail" % tag], + "%s.alt1" % tag : ["%s.pass" % tag, "%s.fail" % tag, "%s.fail" % tag], + "%s.alt2" % tag : ["%s.fail" % tag, "%s.pass" % tag, "%s.fail" % tag], + "%s.alt3" % tag : ["%s.fail" % tag, "%s.fail" % tag, "%s.pass" % tag] + } + lookup.SubTable.append(subtable) + + path = outputPath % 3 + ".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 makeJavascriptData(): + features = sorted(mapping) + outStr = [] + + outStr.append("") + outStr.append("/* This file is autogenerated by makegsubfonts.py */") + outStr.append("") + outStr.append("/* ") + outStr.append(" Features defined in gsubtest fonts with associated base") + outStr.append(" codepoints for each feature:") + outStr.append("") + outStr.append(" cp = codepoint for feature featX") + outStr.append("") + outStr.append(" cp default PASS") + outStr.append(" cp featX=1 FAIL") + outStr.append(" cp featX=2 FAIL") + outStr.append("") + outStr.append(" cp+1 default FAIL") + outStr.append(" cp+1 featX=1 PASS") + outStr.append(" cp+1 featX=2 FAIL") + outStr.append("") + outStr.append(" cp+2 default FAIL") + outStr.append(" cp+2 featX=1 FAIL") + outStr.append(" cp+2 featX=2 PASS") + outStr.append("") + outStr.append("*/") + outStr.append("") + outStr.append("var gFeatures = {"); + cp = baseCodepoint + + taglist = [] + for tag in features: + taglist.append("\"%s\": 0x%x" % (tag, cp)) + cp += 4 + + outStr.append(textwrap.fill(", ".join(taglist), initial_indent=" ", subsequent_indent=" ")) + outStr.append("};"); + outStr.append(""); + + if os.path.exists(javascriptData): + os.remove(javascriptData) + + f = open(javascriptData, "wb") + f.write("\n".join(outStr)) + f.close() + + +# build fonts + +print "Making lookup type 1 font..." +makeLookup1() + +print "Making lookup type 3 font..." +makeLookup3() + +# output javascript data + +print "Making javascript data file..." +makeJavascriptData()
\ No newline at end of file |