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 name = { 101 "gxvalid": "gxv", 102 "otvalid": "otv", 103 }.get(module, module) 104 result += ( 105 "FT_USE_MODULE( FT_Module_Class, %s_module_class )\n" % name 106 ) 107 108 result += "/* EOF */\n" 109 return result 110 111 112def generate_main_modules(lists): 113 return "\n".join( 114 lists["FONT_MODULES"] 115 + lists["HINTING_MODULES"] 116 + lists["RASTER_MODULES"] 117 ) 118 119 120def generate_aux_modules(lists): 121 return "\n".join(lists["AUX_MODULES"]) 122 123 124def generate_base_extensions(lists): 125 return "\n".join(lists["BASE_EXTENSIONS"]) 126 127 128def main(): 129 parser = argparse.ArgumentParser(description=__doc__) 130 131 parser.add_argument( 132 "--format", 133 required=True, 134 choices=( 135 "ftmodule.h", 136 "main-modules", 137 "aux-modules", 138 "base-extensions-list", 139 ), 140 help="Select output format.", 141 ) 142 143 parser.add_argument( 144 "input", 145 metavar="CONFIGURE_RAW", 146 help="The input configure.raw file to parse.", 147 ) 148 149 parser.add_argument("--output", help="Output file (default is stdout).") 150 151 args = parser.parse_args() 152 with open(args.input) as f: 153 input_data = f.read() 154 155 lists = parse_modules_cfg(input_data) 156 157 if args.format == "ftmodule.h": 158 result = generate_ftmodule(lists) 159 elif args.format == "main-modules": 160 result = generate_main_modules(lists) 161 elif args.format == "aux-modules": 162 result = generate_aux_modules(lists) 163 elif args.format == "base-extensions-list": 164 result = generate_base_extensions(lists) 165 else: 166 assert False, "Invalid output format!" 167 168 if args.output: 169 with open(args.output, "w") as f: 170 f.write(result) 171 else: 172 print(result) 173 return 0 174 175 176if __name__ == "__main__": 177 sys.exit(main()) 178