#!/usr/bin/env python3 # Fixes a bunch of inconsistencies and wrong properties in MonacoB fonts. import os import shutil import sys import fontforge print("=== MonacoB font patcher ===") def usage(): sys.exit(f"Usage: {sys.argv[0]} [--output-dir ] ") argc = len(sys.argv) if argc < 2: usage() output_dir = None if sys.argv[1] == "--output-dir": if argc < 3: usage() output_dir = sys.argv[2] if not os.path.isdir(output_dir): sys.exit(f"Error: Output directory '{output_dir}' does not exist.") output_dir = os.path.realpath(output_dir) fonts_list = sys.argv[3:] else: fonts_list = sys.argv[1:] total = len(fonts_list) if total == 0: usage() for i, font_file in enumerate(fonts_list): print(f"\n=== Patching font #{i + 1} of #{total} ===") try: file_full_path = os.path.realpath(font_file) except OSError: print(f" -> ERROR: Failed to resolve the real path of '{font_file}'.") sys.exit(1) file_name = os.path.basename(file_full_path) print(f"==> Opening font file: '{file_name}'...") try: font = fontforge.open(file_full_path) except: print(" -> ERROR: Failed to open font.") sys.exit(1) font_changed = False # Uncomment for debugging. # print(f" -> font.fontname: {font.fontname}") # 'Fontname' # print(f" -> font.familyname: {font.familyname}") # 'Family Name' # print(f" -> font.fullname: {font.fullname}") # 'Name For Humans' # print(f" -> font.weight: {font.weight}") # 'Weight' # print(f" -> font.italicangle: {font.italicangle}") # 'Italic Angle' # print(f" -> font.sfnt_names: {font.sfnt_names}") # 'TTF Names' proper_fontname = font.fullname.replace(" ", "-") if font.fontname != proper_fontname: print(f" -> Fixing font's `fontname`: '{font.fontname}' -> '{proper_fontname}'") font.fontname = proper_fontname font_changed = True # Try to extract font family and style from font.fontname. if "-" in font.fontname: font_family, font_style = font.fontname.split("-", 1) else: font_family = font.fontname font_style = "Regular" removed_count = 0 # Iterate over the 'TTF Names' table. for lang, strid, string in font.sfnt_names: # Remove any row that's not 'English (US)'. if lang != "English (US)" or strid.startswith("Preferred"): removed_count += 1 font.appendSFNTName(lang, strid, None) font_changed = True continue # Remove any row that's not either 'Copyright', 'UniqueID' or 'Version'. # Ideally, we should be updating 'Family', 'SubFamily' and 'PostScriptName', # but for whatever reason, appendSFNTName() does not work when we add values. # Fortunately, removing these properties seem to also work in our case, so let's just do that. if strid != "Copyright" and strid != "UniqueID" and strid != "Version": removed_count += 1 font.appendSFNTName(lang, strid, None) continue print(f" -> Removed a total of {removed_count} rows from SFNT name table.") if font_style == "Italic" and font.italicangle >= 0: print(f" -> Fixing font's `italicangle`: '{font.italicangle}' -> '-12.0'") font.italicangle = -12.0 font_changed = True if font.familyname != font_family: print(f" -> Fixing font's `familyname`: '{font.familyname}' -> '{font_family}'") font.familyname = font_family font_changed = True file_name_without_ext, file_ext = os.path.splitext(file_name) if output_dir: new_file_full_path = output_dir + os.sep + proper_fontname + file_ext else: new_file_full_path = file_full_path if font_changed: print(" -> Re-generating font...") if output_dir: print(f" -> Writing font file '{os.path.basename(new_file_full_path)}' to output directory '{output_dir}'...") else: print(" -> Overwriting font file...") try: font.generate(new_file_full_path) font.close() except: print(" -> ERROR: Failed to re-generate font.") sys.exit(1) elif output_dir and not os.path.isfile(new_file_full_path): print(f" -> Writing font file '{os.path.basename(new_file_full_path)}' to output directory '{output_dir}'...") shutil.copy2(file_full_path, new_file_full_path) else: print(" -> Font does not need to be re-generated/overwritten...") print(" -> Done!")