xref: /aosp_15_r20/external/fonttools/Snippets/fix-dflt-langsys.py (revision e1fe3e4ad2793916b15cccdc4a7da52a7e1dd0e9)
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