def doit(args): font = args.ifont args.type = args.type.upper() for tag in ('GSUB', 'GPOS'): if tag == args.type or args.type == 'BOTH': table = ttLib.getTableClass(tag)() t = getattr(otTables, tag, None)() t.Version = 1.0 t.ScriptList = otTables.ScriptList() t.ScriptList.ScriptRecord = [] t.FeatureList = otTables.FeatureList() t.FeatureList.FeatureRecord = [] t.LookupList = otTables.LookupList() t.LookupList.Lookup = [] srec = otTables.ScriptRecord() srec.ScriptTag = args.script srec.Script = otTables.Script() srec.Script.DefaultLangSys = None srec.Script.LangSysRecord = [] t.ScriptList.ScriptRecord.append(srec) t.ScriptList.ScriptCount = 1 t.FeatureList.FeatureCount = 0 t.LookupList.LookupCount = 0 table.table = t font[tag] = table return font
def add_gsub_to_font(fontfile): """Adds an empty GSUB table to a font.""" font = ttLib.TTFont(fontfile) gsub_table = ttLib.getTableClass('GSUB')('GSUB') gsub_table.table = otTables.GSUB() gsub_table.table.Version = 1.0 gsub_table.table.ScriptList = otTables.ScriptList() gsub_table.table.ScriptCount = 1 gsub_table.table.LookupList = otTables.LookupList() gsub_table.table.LookupList.LookupCount = 0 gsub_table.table.LookupList.Lookup = [] gsub_table.table.FeatureList = otTables.FeatureList() gsub_table.table.FeatureList.FeatureCount = 0 gsub_table.table.LookupList.FeatureRecord = [] script_record = otTables.ScriptRecord() script_record.ScriptTag = get_opentype_script_tag(fontfile) script_record.Script = otTables.Script() script_record.Script.LangSysCount = 0 script_record.Script.LangSysRecord = [] default_lang_sys = otTables.DefaultLangSys() default_lang_sys.FeatureIndex = [] default_lang_sys.FeatureCount = 0 default_lang_sys.LookupOrder = None default_lang_sys.ReqFeatureIndex = 65535 script_record.Script.DefaultLangSys = default_lang_sys gsub_table.table.ScriptList.ScriptRecord = [script_record] font['GSUB'] = gsub_table target_file = tempfile.gettempdir() + '/' + os.path.basename(fontfile) font.save(target_file) return target_file
def buildGSUB(): """Build a GSUB table from scratch.""" fontTable = newTable("GSUB") gsub = fontTable.table = ot.GSUB() gsub.Version = 0x00010001 # allow gsub.FeatureVariations gsub.ScriptList = ot.ScriptList() gsub.ScriptList.ScriptRecord = [] gsub.FeatureList = ot.FeatureList() gsub.FeatureList.FeatureRecord = [] gsub.LookupList = ot.LookupList() gsub.LookupList.Lookup = [] srec = ot.ScriptRecord() srec.ScriptTag = 'DFLT' srec.Script = ot.Script() srec.Script.DefaultLangSys = None srec.Script.LangSysRecord = [] langrec = ot.LangSysRecord() langrec.LangSys = ot.LangSys() langrec.LangSys.ReqFeatureIndex = 0xFFFF langrec.LangSys.FeatureIndex = [0] srec.Script.DefaultLangSys = langrec.LangSys gsub.ScriptList.ScriptRecord.append(srec) gsub.FeatureVariations = None return fontTable
def create_script_record(self): lang_sys = otTables.LangSys() lang_sys.ReqFeatureIndex = 0xFFFF # No required features lang_sys.FeatureIndex = [] script = otTables.Script() script.DefaultLangSys = lang_sys script.LangSysRecord = [] script_record = otTables.ScriptRecord() script_record.ScriptTag = "DFLT" script_record.Script = script return script_record
def parseScriptList(lines, featureMap=None): self = ot.ScriptList() records = [] with lines.between('script table'): for line in lines: while len(line) < 4: line.append('') scriptTag, langSysTag, defaultFeature, features = line log.debug("Adding script %s language-system %s", scriptTag, langSysTag) langSys = ot.LangSys() langSys.LookupOrder = None if defaultFeature: setReference(mapFeature, featureMap, defaultFeature, setattr, langSys, 'ReqFeatureIndex') else: langSys.ReqFeatureIndex = 0xFFFF syms = stripSplitComma(features) langSys.FeatureIndex = theList = [3] * len(syms) for i, sym in enumerate(syms): setReference(mapFeature, featureMap, sym, setitem, theList, i) langSys.FeatureCount = len(langSys.FeatureIndex) script = [s for s in records if s.ScriptTag == scriptTag] if script: script = script[0].Script else: scriptRec = ot.ScriptRecord() scriptRec.ScriptTag = scriptTag scriptRec.Script = ot.Script() records.append(scriptRec) script = scriptRec.Script script.DefaultLangSys = None script.LangSysRecord = [] script.LangSysCount = 0 if langSysTag == 'default': script.DefaultLangSys = langSys else: langSysRec = ot.LangSysRecord() langSysRec.LangSysTag = langSysTag + ' ' * (4 - len(langSysTag)) langSysRec.LangSys = langSys script.LangSysRecord.append(langSysRec) script.LangSysCount = len(script.LangSysRecord) for script in records: script.Script.LangSysRecord = sorted(script.Script.LangSysRecord, key=lambda rec: rec.LangSysTag) self.ScriptRecord = sorted(records, key=lambda rec: rec.ScriptTag) self.ScriptCount = len(self.ScriptRecord) return self
def mergeScriptRecords(lst): d = {} for l in lst: for s in l: tag = s.ScriptTag if tag not in d: d[tag] = [] d[tag].append(s.Script) ret = [] for tag in sorted(d.keys()): rec = otTables.ScriptRecord() rec.ScriptTag = tag rec.Script = mergeScripts(d[tag]) ret.append(rec) return ret
def create_script_list(script_tag='DFLT'): """Create a ScriptList for the GSUB table.""" def_lang_sys = otTables.DefaultLangSys() def_lang_sys.ReqFeatureIndex = 0xFFFF def_lang_sys.FeatureCount = 1 def_lang_sys.FeatureIndex = [0] def_lang_sys.LookupOrder = None script_record = otTables.ScriptRecord() script_record.ScriptTag = script_tag script_record.Script = otTables.Script() script_record.Script.DefaultLangSys = def_lang_sys script_record.Script.LangSysCount = 0 script_record.Script.LangSysRecord = [] script_list = otTables.ScriptList() script_list.ScriptCount = 1 script_list.ScriptRecord = [script_record] return script_list
def parseScriptList(lines, featureMap=None): self = ot.ScriptList() records = [] with lines.between('script table'): for line in lines: scriptTag, langSysTag, defaultFeature, features = line debug("Adding script", scriptTag, "language-system", langSysTag) langSys = ot.LangSys() langSys.LookupOrder = None langSys.ReqFeatureIndex = mapFeature(defaultFeature, featureMap) if defaultFeature else 0xFFFF langSys.FeatureIndex = [mapFeature(sym, featureMap) for sym in stripSplitComma(features)] langSys.FeatureCount = len(langSys.FeatureIndex) script = [s for s in records if s.ScriptTag == scriptTag] if script: script = script[0].Script else: scriptRec = ot.ScriptRecord() scriptRec.ScriptTag = scriptTag scriptRec.Script = ot.Script() records.append(scriptRec) script = scriptRec.Script script.DefaultLangSys = None script.LangSysRecord = [] script.LangSysCount = 0 if langSysTag == 'default': script.DefaultLangSys = langSys else: langSysRec = ot.LangSysRecord() langSysRec.LangSysTag = langSysTag + ' '*(4 - len(langSysTag)) langSysRec.LangSys = langSys script.LangSysRecord.append(langSysRec) script.LangSysCount = len(script.LangSysRecord) for script in records: script.Script.LangSysRecord = sorted(script.Script.LangSysRecord, key=lambda rec: rec.LangSysTag) self.ScriptRecord = sorted(records, key=lambda rec: rec.ScriptTag) self.ScriptCount = len(self.ScriptRecord) return self
def makeTable(self, tag): table = getattr(otTables, tag, None)() table.Version = 1.0 table.ScriptList = otTables.ScriptList() table.ScriptList.ScriptRecord = [] table.FeatureList = otTables.FeatureList() table.FeatureList.FeatureRecord = [] table.LookupList = otTables.LookupList() table.LookupList.Lookup = [] for lookup in self.lookups_: lookup.lookup_index = None for i, lookup_builder in enumerate(self.lookups_): if lookup_builder.table != tag: continue # If multiple lookup builders would build equivalent lookups, # emit them only once. This is quadratic in the number of lookups, # but the checks are cheap. If performance ever becomes an issue, # we could hash the lookup content and only compare those with # the same hash value. equivalent_builder = None for other_builder in self.lookups_[:i]: if lookup_builder.equals(other_builder): equivalent_builder = other_builder if equivalent_builder is not None: lookup_builder.lookup_index = equivalent_builder.lookup_index continue lookup_builder.lookup_index = len(table.LookupList.Lookup) table.LookupList.Lookup.append(lookup_builder.build()) # Build a table for mapping (tag, lookup_indices) to feature_index. # For example, ('liga', (2,3,7)) --> 23. feature_indices = {} required_feature_indices = {} # ('latn', 'DEU') --> 23 scripts = {} # 'latn' --> {'DEU': [23, 24]} for feature #23,24 for key, lookups in sorted(self.features_.items()): script, lang, feature_tag = key # l.lookup_index will be None when a lookup is not needed # for the table under construction. For example, substitution # rules will have no lookup_index while building GPOS tables. lookup_indices = tuple([ l.lookup_index for l in lookups if l.lookup_index is not None ]) if len(lookup_indices) == 0: continue feature_key = (feature_tag, lookup_indices) feature_index = feature_indices.get(feature_key) if feature_index is None: feature_index = len(table.FeatureList.FeatureRecord) frec = otTables.FeatureRecord() frec.FeatureTag = feature_tag frec.Feature = otTables.Feature() frec.Feature.FeatureParams = None frec.Feature.LookupListIndex = lookup_indices frec.Feature.LookupCount = len(lookup_indices) table.FeatureList.FeatureRecord.append(frec) feature_indices[feature_key] = feature_index scripts.setdefault(script, {}).setdefault(lang, []).append(feature_index) if self.required_features_.get((script, lang)) == feature_tag: required_feature_indices[(script, lang)] = feature_index # Build ScriptList. for script, lang_features in sorted(scripts.items()): srec = otTables.ScriptRecord() srec.ScriptTag = script srec.Script = otTables.Script() srec.Script.DefaultLangSys = None srec.Script.LangSysRecord = [] for lang, feature_indices in sorted(lang_features.items()): langrec = otTables.LangSysRecord() langrec.LangSys = otTables.LangSys() langrec.LangSys.LookupOrder = None req_feature_index = \ required_feature_indices.get((script, lang)) if req_feature_index is None: langrec.LangSys.ReqFeatureIndex = 0xFFFF else: langrec.LangSys.ReqFeatureIndex = req_feature_index langrec.LangSys.FeatureIndex = [ i for i in feature_indices if i != req_feature_index ] langrec.LangSys.FeatureCount = \ len(langrec.LangSys.FeatureIndex) if lang == "dflt": srec.Script.DefaultLangSys = langrec.LangSys else: langrec.LangSysTag = lang srec.Script.LangSysRecord.append(langrec) srec.Script.LangSysCount = len(srec.Script.LangSysRecord) table.ScriptList.ScriptRecord.append(srec) table.ScriptList.ScriptCount = len(table.ScriptList.ScriptRecord) table.FeatureList.FeatureCount = len(table.FeatureList.FeatureRecord) table.LookupList.LookupCount = len(table.LookupList.Lookup) return table
parser.add_argument('infont', help='Input font file') parser.add_argument('outfont', help='Output font file') parser.add_argument('-s','--script',default='DFLT', help='Script tag to generate [DFLT]') parser.add_argument('-t','--type',default='both', help='Table to create: gpos, gsub, [both]') args = parser.parse_args() inf = ttLib.TTFont(args.infont) for tag in ('GSUB', 'GPOS') : if tag.lower() == args.type or args.type == 'both' : table = ttLib.getTableClass(tag)() t = getattr(otTables, tag, None)() t.Version = 1.0 t.ScriptList = otTables.ScriptList() t.ScriptList.ScriptRecord = [] t.FeatureList = otTables.FeatureList() t.FeatureList.FeatureRecord = [] t.LookupList = otTables.LookupList() t.LookupList.Lookup = [] srec = otTables.ScriptRecord() srec.ScriptTag = args.script srec.Script = otTables.Script() srec.Script.DefaultLangSys = None srec.Script.LangSysRecord = [] t.ScriptList.ScriptRecord.append(srec) t.ScriptList.ScriptCount = 1 t.FeatureList.FeatureCount = 0 t.LookupList.LookupCount = 0 table.table = t inf[tag] = table inf.save(args.outfont)
def makeTable(self, tag): table = getattr(otTables, tag, None)() table.Version = 1.0 table.ScriptList = otTables.ScriptList() table.ScriptList.ScriptRecord = [] table.FeatureList = otTables.FeatureList() table.FeatureList.FeatureRecord = [] table.LookupList = otTables.LookupList() table.LookupList.Lookup = self.buildLookups_(tag) # Build a table for mapping (tag, lookup_indices) to feature_index. # For example, ('liga', (2,3,7)) --> 23. feature_indices = {} required_feature_indices = {} # ('latn', 'DEU') --> 23 scripts = {} # 'latn' --> {'DEU': [23, 24]} for feature #23,24 for key, lookups in sorted(self.features_.items()): script, lang, feature_tag = key # l.lookup_index will be None when a lookup is not needed # for the table under construction. For example, substitution # rules will have no lookup_index while building GPOS tables. lookup_indices = tuple([l.lookup_index for l in lookups if l.lookup_index is not None]) if len(lookup_indices) == 0: continue feature_key = (feature_tag, lookup_indices) feature_index = feature_indices.get(feature_key) if feature_index is None: feature_index = len(table.FeatureList.FeatureRecord) frec = otTables.FeatureRecord() frec.FeatureTag = feature_tag frec.Feature = otTables.Feature() frec.Feature.FeatureParams = None frec.Feature.LookupListIndex = lookup_indices frec.Feature.LookupCount = len(lookup_indices) table.FeatureList.FeatureRecord.append(frec) feature_indices[feature_key] = feature_index scripts.setdefault(script, {}).setdefault(lang, []).append( feature_index) if self.required_features_.get((script, lang)) == feature_tag: required_feature_indices[(script, lang)] = feature_index # Build ScriptList. for script, lang_features in sorted(scripts.items()): srec = otTables.ScriptRecord() srec.ScriptTag = script srec.Script = otTables.Script() srec.Script.DefaultLangSys = None srec.Script.LangSysRecord = [] for lang, feature_indices in sorted(lang_features.items()): langrec = otTables.LangSysRecord() langrec.LangSys = otTables.LangSys() langrec.LangSys.LookupOrder = None req_feature_index = \ required_feature_indices.get((script, lang)) if req_feature_index is None: langrec.LangSys.ReqFeatureIndex = 0xFFFF else: langrec.LangSys.ReqFeatureIndex = req_feature_index langrec.LangSys.FeatureIndex = [i for i in feature_indices if i != req_feature_index] langrec.LangSys.FeatureCount = \ len(langrec.LangSys.FeatureIndex) if lang == "dflt": srec.Script.DefaultLangSys = langrec.LangSys else: langrec.LangSysTag = lang srec.Script.LangSysRecord.append(langrec) srec.Script.LangSysCount = len(srec.Script.LangSysRecord) table.ScriptList.ScriptRecord.append(srec) table.ScriptList.ScriptCount = len(table.ScriptList.ScriptRecord) table.FeatureList.FeatureCount = len(table.FeatureList.FeatureRecord) table.LookupList.LookupCount = len(table.LookupList.Lookup) return table