generate_update_fa_glyph_ranges.py (3945B)
1 #!/usr/bin/env python3 2 3 import code 4 import sys 5 import os 6 import glob 7 import re 8 9 #src_file = "src/duckstation-qt/qttranslations.cpp" 10 src_dir = os.path.join(os.path.dirname(__file__), "..", "src") 11 fa_file = os.path.join(os.path.dirname(__file__), "..", "dep", "imgui", "include", "IconsFontAwesome5.h") 12 pf_file = os.path.join(os.path.dirname(__file__), "..", "dep", "imgui", "include", "IconsPromptFont.h") 13 emoji_file = os.path.join(os.path.dirname(__file__), "..", "dep", "imgui", "include", "IconsEmoji.h") 14 dst_file = os.path.join(os.path.dirname(__file__), "..", "src", "util", "imgui_glyph_ranges.inl") 15 16 all_source_files = glob.glob(os.path.join(src_dir, "**", "*.cpp"), recursive=True) + \ 17 glob.glob(os.path.join(src_dir, "**", "*.h"), recursive=True) + \ 18 glob.glob(os.path.join(src_dir, "**", "*.inl"), recursive=True) 19 20 tokens = set() 21 pf_tokens = set() 22 emoji_tokens = set() 23 for filename in all_source_files: 24 data = None 25 with open(filename, "r") as f: 26 try: 27 data = f.read() 28 except: 29 continue 30 31 tokens = tokens.union(set(re.findall("(ICON_FA_[a-zA-Z0-9_]+)", data))) 32 pf_tokens = pf_tokens.union(set(re.findall("(ICON_PF_[a-zA-Z0-9_]+)", data))) 33 emoji_tokens = emoji_tokens.union(set(re.findall("(ICON_EMOJI_[a-zA-Z0-9_]+)", data))) 34 35 print("{}/{}/{} tokens found.".format(len(tokens), len(pf_tokens), len(emoji_tokens))) 36 if len(tokens) == 0 and len(pf_tokens) == 0: 37 sys.exit(0) 38 39 u8_encodings = {} 40 with open(fa_file, "r") as f: 41 for line in f.readlines(): 42 match = re.match("#define (ICON_FA_[^ ]+) \"([^\"]+)\"", line) 43 if match is None: 44 continue 45 u8_encodings[match[1]] = bytes.fromhex(match[2].replace("\\x", "")) 46 with open(pf_file, "r") as f: 47 for line in f.readlines(): 48 match = re.match("#define (ICON_PF_[^ ]+) \"([^\"]+)\"", line) 49 if match is None: 50 continue 51 u8_encodings[match[1]] = bytes.fromhex(match[2].replace("\\x", "")) 52 with open(emoji_file, "r") as f: 53 for line in f.readlines(): 54 match = re.match("#define (ICON_EMOJI_[^ ]+) \"([^\"]+)\"", line) 55 if match is None: 56 continue 57 u8_encodings[match[1]] = bytes.fromhex(match[2].replace("\\x", "")) 58 59 out_pattern = "(static constexpr ImWchar FA_ICON_RANGE\[\] = \{)[0-9A-Z_a-z, \n]+(\};)" 60 out_pf_pattern = "(static constexpr ImWchar PF_ICON_RANGE\[\] = \{)[0-9A-Z_a-z, \n]+(\};)" 61 out_emoji_pattern = "(static constexpr ImWchar EMOJI_ICON_RANGE\[\] = \{)[0-9A-Z_a-z, \n]+(\};)" 62 63 def get_pairs(tokens): 64 codepoints = list() 65 for token in tokens: 66 u8_bytes = u8_encodings[token] 67 u8 = str(u8_bytes, "utf-8") 68 u32 = u8.encode("utf-32le") 69 if len(u32) > 4: 70 raise ValueError("{} {} too long".format(u8_bytes, token)) 71 72 codepoint = int.from_bytes(u32, byteorder="little", signed=False) 73 codepoints.append(codepoint) 74 codepoints.sort() 75 codepoints.append(0) # null terminator 76 77 startc = codepoints[0] 78 endc = None 79 pairs = [startc] 80 for codepoint in codepoints: 81 if endc is not None and (endc + 1) != codepoint: 82 pairs.append(endc) 83 pairs.append(codepoint) 84 startc = codepoint 85 endc = codepoint 86 else: 87 endc = codepoint 88 pairs.append(endc) 89 90 pairs_str = ",".join(list(map(lambda x: "0x{:x}".format(x), pairs))) 91 return pairs_str 92 93 with open(dst_file, "r") as f: 94 original = f.read() 95 updated = re.sub(out_pattern, "\\1 " + get_pairs(tokens) + " \\2", original) 96 updated = re.sub(out_pf_pattern, "\\1 " + get_pairs(pf_tokens) + " \\2", updated) 97 updated = re.sub(out_emoji_pattern, "\\1 " + get_pairs(emoji_tokens) + " \\2", updated) 98 if original != updated: 99 with open(dst_file, "w") as f: 100 f.write(updated) 101 print("Updated {}".format(dst_file)) 102 else: 103 print("Skipping updating {}".format(dst_file)) 104