-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathfontcreate.py
executable file
·147 lines (123 loc) · 4.05 KB
/
fontcreate.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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#!/usr/bin/env python3
# Written 2022 by Josh Cogliati
# This program is licensed under the terms of the GPL, version 2 or later
#See similar/2d/font.cpp and grs_font_read for format info
import sys,os
import glob
import struct
import PIL
import PIL.Image
def write_pack(format, file, data):
pack = struct.pack(format, *data)
file.write(pack)
if len(sys.argv) < 2:
print(sys.argv[0]," fontfile [kerning_info baseline]")
print("creates fontfile from png files in current directory")
sys.exit(-1)
image_files = glob.glob("*.png")
font_images = {}
minheight = None
maxheight = None
minwidth = None
maxwidth = None
width_sum = 0
for image_filename in image_files:
num = int(image_filename[:-4])
char_image = PIL.Image.open(image_filename)
font_images[num] = char_image
width, height = char_image.size
width_sum += width
if minheight is None:
minwidth = width
maxwidth = minwidth
minheight = height
maxheight = minheight
else:
minwidth = min(width, minwidth)
maxwidth = max(width, maxwidth)
minheight = min(height, minheight)
maxheight = max(height, maxheight)
print("width",minwidth,maxwidth,"height", minheight, maxheight)
if minheight != maxheight:
print("different heights, can't create font", minheight, maxheight)
sys.exit(-2)
font_height = minheight
minchar = min(font_images)
maxchar = max(font_images)
print("character range", minchar, maxchar)
all_in = True
mode = font_images[minchar].mode
same_mode = True
for i in range(minchar, maxchar+1):
if i not in font_images:
all_in = False
print("missing", i, chr(i))
else:
if mode != font_images[i].mode:
same_mode = False
if not all_in:
print("missing characters, quiting")
sys.exit(-3)
if not same_mode:
print("images not same mode")
sys.exit(-4)
print("mode", mode)
if mode not in ["1", "L", "P"]:
print("unsupported mode")
sys.exit(-5)
f = open(sys.argv[1], "wb")
kerning_info = []
if len(sys.argv) > 2:
kerning_filename = sys.argv[2]
kerning_file = open(kerning_filename, "r")
for line in kerning_file.readlines():
line = line.strip().split("#")[0] #Strip comments starting with #
kerning_info.append([int(s) for s in line.split()])
char_num = maxchar - minchar + 1
f.write(b"PSFN")
GRS_FONT_SIZE = 28
if mode == "1":
# 28 bytes header, char_num*font_height image data, char_num*2 width info, 1 byte to end kerning info plus 3 bytes per item of kerning_info
length = GRS_FONT_SIZE + char_num*(font_height + 2) + 1 + 3*len(kerning_info)
else:
length = GRS_FONT_SIZE + font_height*width_sum + char_num*2 + 1 + 3*len(kerning_info)
write_pack("<I", f, (length,))
FT_COLOR = 1
FT_PROPORTIONAL = 2
FT_KERNED = 4
if len(sys.argv) > 3:
baseline = int(sys.argv[3])
else:
baseline = font_height
write_pack("<HHHHBB", f, (maxwidth, font_height,
FT_PROPORTIONAL | FT_KERNED | (mode != "1"),
baseline,
minchar, maxchar))
write_pack("<HIIII", f, (0, GRS_FONT_SIZE + char_num*2, 0,
GRS_FONT_SIZE, length - 1 - 3*len(kerning_info)))
for i in range(minchar, maxchar +1):
cwidth = font_images[i].size[0]
write_pack("<H", f, (cwidth,))
for i in range(minchar, maxchar + 1):
img = font_images[i]
cwidth = img.size[0]
if mode == "1":
for h in range(font_height):
l = 0
k = 128
for w in range(cwidth):
if img.getpixel((w,h))>0:
l = l | k
k = k >> 1
#print(img.getpixel((w,h)), l)
#print("l", l, bin(l))
write_pack("B",f, (l,))
else:
for h in range(font_height):
for w in range(cwidth):
write_pack("B", f, (img.getpixel((w,h)),))
for kern_info in kerning_info:
first, second, kwidth = kern_info
write_pack("BBB", f, (first - minchar, second - minchar, kwidth))
print(first,second,kwidth, end=" ")
f.write(b"\xff") #XXX write actual kerning info