duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

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