1#!/usr/bin/env python3 2# 3# Copyright (C) 2020-2023 by 4# David Turner, Robert Wilhelm, and Werner Lemberg. 5# 6# This file is part of the FreeType project, and may only be used, modified, 7# and distributed under the terms of the FreeType project license, 8# LICENSE.TXT. By continuing to use, modify, or distribute this file you 9# indicate that you have read the license and understand and accept it 10# fully. 11 12"""Parse modules.cfg and dump its output either as ftmodule.h or a list of 13base extensions. 14""" 15 16from __future__ import print_function 17 18import argparse 19import os 20import re 21import sys 22 23# Expected input: 24# 25# ... 26# FONT_MODULES += <name> 27# HINTING_MODULES += <name> 28# RASTER_MODULES += <name> 29# AUX_MODULES += <name> 30# BASE_EXTENSIONS += <name> 31# ... 32 33 34def parse_modules_cfg(input_file): 35 36 lists = { 37 "FONT_MODULES": [], 38 "HINTING_MODULES": [], 39 "RASTER_MODULES": [], 40 "AUX_MODULES": [], 41 "BASE_EXTENSIONS": [], 42 } 43 44 for line in input_file.splitlines(): 45 line = line.rstrip() 46 # Ignore empty lines and those that start with a comment. 47 if not line or line[0] == "#": 48 continue 49 50 items = line.split() 51 assert len(items) == 3 and items[1] == "+=", ( 52 "Unexpected input line [%s]" % line 53 ) 54 assert items[0] in lists, ( 55 "Unexpected configuration variable name " + items[0] 56 ) 57 58 lists[items[0]].append(items[2]) 59 60 return lists 61 62 63def generate_ftmodule(lists): 64 result = "/* This is a generated file. */\n" 65 for driver in lists["FONT_MODULES"]: 66 if driver == "sfnt": # Special case for the sfnt 'driver'. 67 result += "FT_USE_MODULE( FT_Module_Class, sfnt_module_class )\n" 68 continue 69 70 name = { 71 "truetype": "tt", 72 "type1": "t1", 73 "cid": "t1cid", 74 "type42": "t42", 75 "winfonts": "winfnt", 76 }.get(driver, driver) 77 result += ( 78 "FT_USE_MODULE( FT_Driver_ClassRec, %s_driver_class )\n" % name 79 ) 80 81 for module in lists["HINTING_MODULES"]: 82 result += ( 83 "FT_USE_MODULE( FT_Module_Class, %s_module_class )\n" % module 84 ) 85 86 for module in lists["RASTER_MODULES"]: 87 names = { 88 "raster": ("ft_raster1",), 89 "smooth": ("ft_smooth",), 90 "svg": ("ft_svg",), 91 "sdf": ("ft_sdf", "ft_bitmap_sdf"), 92 }.get(module) 93 for name in names: 94 result += ( 95 "FT_USE_MODULE( FT_Renderer_Class, %s_renderer_class )\n" % name 96 ) 97 98 for module in lists["AUX_MODULES"]: 99 if module in ("psaux", "psnames", "otvalid", "gxvalid"): 100 result += ( 101 "FT_USE_MODULE( FT_Module_Class, %s_module_class )\n" % module 102 ) 103 104 result += "/* EOF */\n" 105 return result 106 107 108def generate_main_modules(lists): 109 return "\n".join( 110 lists["FONT_MODULES"] 111 + lists["HINTING_MODULES"] 112 + lists["RASTER_MODULES"] 113 ) 114 115 116def generate_aux_modules(lists): 117 return "\n".join(lists["AUX_MODULES"]) 118 119 120def generate_base_extensions(lists): 121 return "\n".join(lists["BASE_EXTENSIONS"]) 122 123 124def main(): 125 parser = argparse.ArgumentParser(description=__doc__) 126 127 parser.add_argument( 128 "--format", 129 required=True, 130 choices=( 131 "ftmodule.h", 132 "main-modules", 133 "aux-modules", 134 "base-extensions-list", 135 ), 136 help="Select output format.", 137 ) 138 139 parser.add_argument( 140 "input", 141 metavar="CONFIGURE_RAW", 142 help="The input configure.raw file to parse.", 143 ) 144 145 parser.add_argument("--output", help="Output file (default is stdout).") 146 147 args = parser.parse_args() 148 with open(args.input) as f: 149 input_data = f.read() 150 151 lists = parse_modules_cfg(input_data) 152 153 if args.format == "ftmodule.h": 154 result = generate_ftmodule(lists) 155 elif args.format == "main-modules": 156 result = generate_main_modules(lists) 157 elif args.format == "aux-modules": 158 result = generate_aux_modules(lists) 159 elif args.format == "base-extensions-list": 160 result = generate_base_extensions(lists) 161 else: 162 assert False, "Invalid output format!" 163 164 if args.output: 165 with open(args.output, "w") as f: 166 f.write(result) 167 else: 168 print(result) 169 return 0 170 171 172if __name__ == "__main__": 173 sys.exit(main()) 174