1#!/usr/bin/env python3 2 3import argparse 4import logging 5import os 6import sys 7 8from fontTools.ttLib import TTFont 9 10 11def ProcessTable(table): 12 found = set() 13 14 for rec in table.ScriptList.ScriptRecord: 15 if rec.ScriptTag == "DFLT" and rec.Script.LangSysCount != 0: 16 tags = [r.LangSysTag for r in rec.Script.LangSysRecord] 17 logging.info( 18 "Removing %d extraneous LangSys records: %s", 19 rec.Script.LangSysCount, 20 " ".join(tags), 21 ) 22 rec.Script.LangSysRecord = [] 23 rec.Script.LangSysCount = 0 24 found.update(tags) 25 26 if not found: 27 logging.info("All fine") 28 return False 29 else: 30 for rec in table.ScriptList.ScriptRecord: 31 tags = set([r.LangSysTag for r in rec.Script.LangSysRecord]) 32 found -= tags 33 34 if found: 35 logging.warning( 36 "Records are missing from non-DFLT scripts: %s", " ".join(found) 37 ) 38 return True 39 40 41def ProcessFont(font): 42 found = False 43 for tag in ("GSUB", "GPOS"): 44 if tag in font: 45 logging.info("Processing %s table", tag) 46 if ProcessTable(font[tag].table): 47 found = True 48 else: 49 # Unmark the table as loaded so that it is read from disk when 50 # writing the font, to avoid any unnecessary changes caused by 51 # decompiling then recompiling again. 52 del font.tables[tag] 53 54 return found 55 56 57def ProcessFiles(filenames): 58 for filename in filenames: 59 logging.info("Processing %s", filename) 60 font = TTFont(filename) 61 name, ext = os.path.splitext(filename) 62 fixedname = name + ".fixed" + ext 63 if ProcessFont(font): 64 logging.info("Saving fixed font to %s\n", fixedname) 65 font.save(fixedname) 66 else: 67 logging.info("Font file is fine, nothing to fix\n") 68 69 70def main(): 71 parser = argparse.ArgumentParser(description="Fix LangSys records for DFLT script") 72 parser.add_argument( 73 "files", metavar="FILE", type=str, nargs="+", help="input font to process" 74 ) 75 parser.add_argument( 76 "-s", "--silent", action="store_true", help="suppress normal messages" 77 ) 78 79 args = parser.parse_args() 80 81 logformat = "%(levelname)s: %(message)s" 82 if args.silent: 83 logging.basicConfig(format=logformat, level=logging.DEBUG) 84 else: 85 logging.basicConfig(format=logformat, level=logging.INFO) 86 87 ProcessFiles(args.files) 88 89 90if __name__ == "__main__": 91 sys.exit(main()) 92