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