mirror of
https://github.com/WerWolv/ImHex.git
synced 2026-03-29 08:20:02 -05:00
dist: Added scripts for pre-processing future icon fonts
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,6 +2,7 @@
|
|||||||
/.idea/
|
/.idea/
|
||||||
/.kdev4/
|
/.kdev4/
|
||||||
/.vs/
|
/.vs/
|
||||||
|
.venv/
|
||||||
|
|
||||||
/cmake-build-*/
|
/cmake-build-*/
|
||||||
/build*/
|
/build*/
|
||||||
|
|||||||
69
dist/fonts/move_private_use_area.py
vendored
Normal file
69
dist/fonts/move_private_use_area.py
vendored
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
from fontTools.ttLib import TTFont
|
||||||
|
from fontTools.ttLib.tables._c_m_a_p import CmapSubtable
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
# Default PUAs
|
||||||
|
SOURCE_PUA_START = 0xEA00
|
||||||
|
SOURCE_PUA_END = 0x100F2
|
||||||
|
TARGET_PUA_START = 0xF0000
|
||||||
|
|
||||||
|
def move_pua_glyphs(input_font_path, output_font_path):
|
||||||
|
font = TTFont(input_font_path)
|
||||||
|
|
||||||
|
cmap_table = font['cmap']
|
||||||
|
glyph_set = font.getGlyphSet()
|
||||||
|
|
||||||
|
# Track moved glyphs
|
||||||
|
moved = 0
|
||||||
|
new_mapping = {}
|
||||||
|
|
||||||
|
# Collect original mappings in the PUA
|
||||||
|
for cmap in cmap_table.tables:
|
||||||
|
if cmap.isUnicode():
|
||||||
|
for codepoint, glyph_name in cmap.cmap.items():
|
||||||
|
if SOURCE_PUA_START <= codepoint <= SOURCE_PUA_END:
|
||||||
|
offset = codepoint - SOURCE_PUA_START
|
||||||
|
new_codepoint = TARGET_PUA_START + offset
|
||||||
|
new_mapping[new_codepoint] = glyph_name
|
||||||
|
moved += 1
|
||||||
|
|
||||||
|
if moved == 0:
|
||||||
|
print("No glyphs found in the source Private Use Area.")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Remove old PUA entries from existing cmap subtables
|
||||||
|
for cmap in cmap_table.tables:
|
||||||
|
if cmap.isUnicode():
|
||||||
|
cmap.cmap = {
|
||||||
|
cp: gn for cp, gn in cmap.cmap.items()
|
||||||
|
if not (SOURCE_PUA_START <= cp <= SOURCE_PUA_END)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create or update a format 12 cmap subtable
|
||||||
|
found_format12 = False
|
||||||
|
for cmap in cmap_table.tables:
|
||||||
|
if cmap.format == 12 and cmap.platformID == 3 and cmap.platEncID in (10, 1):
|
||||||
|
cmap.cmap.update(new_mapping)
|
||||||
|
found_format12 = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if not found_format12:
|
||||||
|
# Create a new format 12 subtable
|
||||||
|
cmap12 = CmapSubtable.newSubtable(12)
|
||||||
|
cmap12.platformID = 3
|
||||||
|
cmap12.platEncID = 10 # UCS-4
|
||||||
|
cmap12.language = 0
|
||||||
|
cmap12.cmap = new_mapping
|
||||||
|
cmap_table.tables.append(cmap12)
|
||||||
|
|
||||||
|
print(f"Moved {moved} glyphs from U+{SOURCE_PUA_START:X}–U+{SOURCE_PUA_END:X} to U+{TARGET_PUA_START:X}+")
|
||||||
|
font.save(output_font_path)
|
||||||
|
print(f"Saved modified font to {output_font_path}")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
parser = argparse.ArgumentParser(description="Move PUA glyphs in a TTF file to another Unicode range.")
|
||||||
|
parser.add_argument("input", help="Input TTF file path")
|
||||||
|
parser.add_argument("output", help="Output TTF file path")
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
move_pua_glyphs(args.input, args.output)
|
||||||
60
dist/fonts/ttf_to_header_file.py
vendored
Normal file
60
dist/fonts/ttf_to_header_file.py
vendored
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
import argparse
|
||||||
|
from fontTools.ttLib import TTFont
|
||||||
|
import os
|
||||||
|
|
||||||
|
def unicode_to_utf8_escape(codepoint):
|
||||||
|
return ''.join([f'\\x{b:02x}' for b in chr(codepoint).encode('utf-8')])
|
||||||
|
|
||||||
|
def format_macro_name(prefix, glyph_name):
|
||||||
|
# Convert names like 'repo-forked' -> 'ICON_VS_REPO_FORKED'
|
||||||
|
return "ICON_" + prefix + "_" + glyph_name.upper().replace('-', '_')
|
||||||
|
|
||||||
|
def generate_font_header(font_path, output_path, font_macro_name, font_file_macro):
|
||||||
|
font = TTFont(font_path)
|
||||||
|
|
||||||
|
# Use cmap to get Unicode to glyph mapping
|
||||||
|
codepoint_to_names = {}
|
||||||
|
for table in font["cmap"].tables:
|
||||||
|
if table.isUnicode():
|
||||||
|
for codepoint, glyph_name in table.cmap.items():
|
||||||
|
codepoint_to_names.setdefault(codepoint, []).append(glyph_name)
|
||||||
|
|
||||||
|
if not codepoint_to_names:
|
||||||
|
print("No Unicode-mapped glyphs found in the font.")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Remove any glyph that is lower than 0xFF
|
||||||
|
codepoint_to_names = {cp: names for cp, names in codepoint_to_names.items() if cp >= 0xFF}
|
||||||
|
|
||||||
|
min_cp = min(codepoint_to_names)
|
||||||
|
max_cp = max(codepoint_to_names)
|
||||||
|
|
||||||
|
with open(output_path, "w", encoding="utf-8") as out:
|
||||||
|
out.write("#pragma once\n\n")
|
||||||
|
out.write(f'#define FONT_ICON_FILE_NAME_{font_macro_name} "{font_file_macro}"\n\n')
|
||||||
|
out.write(f"#define ICON_MIN_{font_macro_name} 0x{min_cp:04x}\n")
|
||||||
|
out.write(f"#define ICON_MAX_16_{font_macro_name} 0x{max_cp:04x}\n")
|
||||||
|
out.write(f"#define ICON_MAX_{font_macro_name} 0x{max_cp:04x}\n")
|
||||||
|
|
||||||
|
written = set()
|
||||||
|
for codepoint in sorted(codepoint_to_names):
|
||||||
|
utf8 = unicode_to_utf8_escape(codepoint)
|
||||||
|
comment = f"// U+{codepoint:04X}"
|
||||||
|
glyph_names = sorted(set(codepoint_to_names[codepoint]))
|
||||||
|
for i, glyph_name in enumerate(glyph_names):
|
||||||
|
macro = format_macro_name(font_macro_name, glyph_name)
|
||||||
|
if macro in written:
|
||||||
|
continue
|
||||||
|
out.write(f"#define {macro} \"{utf8}\"\t{comment}\n")
|
||||||
|
written.add(macro)
|
||||||
|
|
||||||
|
print(f"Header generated at {output_path}")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
parser = argparse.ArgumentParser(description="Generate C header file from TTF glyphs.")
|
||||||
|
parser.add_argument("font", help="Input .ttf font file")
|
||||||
|
parser.add_argument("output", help="Output .h file")
|
||||||
|
parser.add_argument("macro_name", help="Macro prefix")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
generate_font_header(args.font, args.output, args.macro_name, os.path.basename(args.font))
|
||||||
Reference in New Issue
Block a user