-
Notifications
You must be signed in to change notification settings - Fork 1
/
update_font_data_r.py
120 lines (96 loc) · 4.11 KB
/
update_font_data_r.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import json
import re
import argparse
from math import ceil
from collections import OrderedDict
from os.path import join as path_join
from PIL import Image, ImageFont, ImageDraw, ImageChops
from app.models.fif import FifFile, FifEntry
NONE_CHARACTER_REGEX = r"(\{color:(\d+)\})|(\{\/color\})|(\{clear\})|(\{arrow\})|(\{speed:(\d+)\})|(\{wait:(\d+)\})|(\n)|(\\u[a-fA-F0-9]{4})"
def px_to_pt(pt):
return round(pt / 1.25)
def get_characters(path, entry_wrapper_index=0):
with open(path, "r", encoding="utf-8") as json_f:
obj = json.load(json_f)
character_set = set()
for entry in obj["Entries"][entry_wrapper_index]:
entry = re.sub(NONE_CHARACTER_REGEX, "", entry, re.M)
for character in entry:
character_set.add(character)
characters = sorted(list(character_set))
return characters
def update_fif(fif, characters):
fif.entry_count = len(characters)
fif.characters_per_row = fif.width // fif.column_width
fif.row_count = fif.height // fif.row_height
fif.characters_per_texture = fif.characters_per_row * fif.row_count
fif.texture_count = ceil(fif.entry_count / fif.characters_per_texture)
def generate_entries(fif, characters, font, font_size, color, font_top_margin, output):
character_index = 0
new_entries = OrderedDict()
for texture_index in range(fif.texture_count):
texture_character_count = 0
pos_width = 0
pos_height = 0
image = Image.new("RGB", (fif.width, fif.height), (0, 0, 0))
alpha = Image.new("L", image.size, "black")
imtext = Image.new("L", image.size, 0)
drtext = ImageDraw.Draw(imtext)
while (
texture_character_count < fif.characters_per_texture
and character_index < len(characters)
):
character = characters[character_index]
glyph_size = font.getsize(character)
pos = (
pos_width + 1,
round(pos_height - font_size * 0.1 + 1) + font_top_margin,
)
drtext.text(pos, character, font=font, fill="white")
if character.isspace():
new_entries[character] = FifEntry(0, 10, 1)
if character.isalpha():
new_entries[character] = FifEntry(0, 0, glyph_size[0])
else:
new_entries[character] = FifEntry(0, 2, glyph_size[0])
character_index += 1
texture_character_count += 1
if texture_character_count % fif.characters_per_row == 0:
pos_width = 0
pos_height += fif.row_height
else:
pos_width += fif.column_width
alpha = ImageChops.lighter(alpha, imtext)
solidcolor = Image.new("RGBA", image.size, color)
immask = Image.eval(imtext, lambda p: 255 * (int(p != 0)))
image = Image.composite(solidcolor, image, immask)
image.putalpha(alpha)
image.save(output + f"_{texture_index:02}.dds.png", "PNG")
return new_entries
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Generate font data(fif and image) files from mtx json"
)
parser.add_argument(
"-f", "--font", help="Font file path to generate font image", required=True
)
parser.add_argument(
"--font_top_margin", help="Top margin for font", default=0, type=int
)
parser.add_argument(
"--font_rel_size", help="Font relative size factor", default=0, type=int
)
args = parser.parse_args()
output = path_join(args.output_dir, args.name)
with open(args.fif_json, "r", encoding="utf-8") as json_f:
obj = json.load(json_f, object_pairs_hook=OrderedDict)
fif = FifFile.import_obj(obj)
font_size = px_to_pt(fif.character_height) - 2 + args.font_rel_size
font = ImageFont.truetype(args.font, size=font_size)
characters = get_characters(args.text_json, args.index)
update_fif(fif, characters)
new_entries = generate_entries(
fif, characters, font, font_size, "#ffffff", args.font_top_margin, output
)
fif.entries = new_entries
fif.save(output + ".fif")