-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcreate_new_font.py
220 lines (181 loc) · 9.13 KB
/
create_new_font.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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# used for preparing fonts
# input is the file path to the .c file received from https://littlevgl.com/ttf-font-to-c-array
import fileinput
import sys
import re
import os
fontSourceFileName = "font_source.py"
destFolder = "src"
def createSourceFontFile() -> int:
foundOpen = False # indicate if the beginning of c source array is found
foundFirstChar = False # whether first character in the c header file is found
newestFoundWidth = 0 # width of the most recent character, used for building the dict
firstCharFound = 0 # ascii of the name of first char found(ie 97 for a)
widthPattern = re.compile(".*Width: ([0-9]*) \*/") # find character width in c comment
charNamePattern = re.compile(".*Unicode: U\+([0-9]*).*\*/") # find character name in a c comment
# create scratch file to store bit map
try:
processedFontFile = open(fontSourceFileName, 'w')
except:
print("Can't create new files")
sys.exit(0) # quit Python
for line in fileinput.input():
if(foundOpen):
searchResult = re.search("\s*};\s*", line)
if(searchResult != None):
processedFontFile.write("]}]")
processedFontFile.close()
break
tempLine = line
tempLine = re.sub("{", "", tempLine)
tempLine = re.sub("\w*//.*", "", tempLine) # delete all c comments
widthResult = widthPattern.match(line)
if(widthResult != None):
newestFoundWidth = int(widthResult.group(1))
if(foundFirstChar):
# start creating opening of python dict
tempLine = re.sub("/\*", "]}#", tempLine)
tempLine = re.sub("\*/", "\n,{ \"length\": " + str(newestFoundWidth) + ", \n\"bitmap\": [", tempLine)
else:
searchResult = re.search("/\*", line)
if(searchResult != None):
firstCharSearchRes = charNamePattern.match(line)
if(firstCharSearchRes != None):
firstCharFound = int(firstCharSearchRes.group(1), 16)
tempLine = re.sub("/\*", "#", tempLine)
tempLine = re.sub("\*/", "\n{ \"length\": " + str(newestFoundWidth) + ", \n\"bitmap\": [", tempLine)
foundFirstChar = True
processedFontFile.write(tempLine)
# check for beginning of c array
if(False == foundOpen):
searchResult = re.search("\s*static const uint8_t source_code_pro_oled_glyph_bitmap\[\] =\s*", line)
if(searchResult != None):
foundOpen = True
processedFontFile.write("bitmapData = [")
return firstCharFound
def makeCFile(firstCharFound: int):
import numpy as np
import font_source as ft
BITS_PER_COLUMN = 8
TOTAL_PAGE = 2
MIN_REMOVAL_LEN = 5 # must be at least this long to have empty line removed
tempMatrix = []
finalList = []
for currChar, bitDict in enumerate(ft.bitmapData):
# build a matrix representation of the character
for index in range(0, len(bitDict["bitmap"])):
tempMatrix.append([])
# print(hex(bitDict["bitmap"][index]))
for bitOrder in range(7, -1, -1):
# print(1 << bitOrder)
if (bitDict["bitmap"][index] & (1 << bitOrder)) > 0:
tempMatrix[index].append(1)
else:
tempMatrix[index].append(0)
# print(tempMatrix)
m = np.array(tempMatrix)
m = np.transpose(m)
# print(np.array(tempMatrix))
print("Before removal: ")
print(m)
m = m.tolist()
lineToRemove = []
# remove blank line to make character look consistent
if(bitDict["length"] >= MIN_REMOVAL_LEN):
for currPosition, vertLine in enumerate(m):
print(currPosition)
if (all(bit == 0 for bit in vertLine)):
lineToRemove.append(currPosition)
lineToRemove.sort(reverse= True)
for index in lineToRemove:
del m[index]
print("After removal: ")
print(m)
finalList.append([])
for currPosition, i in enumerate(m):
tempSum = 0
tempCounter = 0
# package the number
for j in i:
tempSum = tempSum + (j << tempCounter)
tempCounter += 1
appendCounter = 0
# spread the number into 8 bit packs
while(tempSum > 0):
finalList[currChar].append(tempSum & 0xff)
tempSum >>= BITS_PER_COLUMN
appendCounter += 1
# pad unoccupied page
for k in range(0, TOTAL_PAGE - appendCounter):
finalList[currChar].append(0)
tempMatrix = []
# create c header file
try:
currDir = os.path.dirname(os.path.abspath(__file__))
# print(currDir)
relDir = destFolder + "/" + "oled_font_" + sys.argv[2] + ".h"
finalPath = os.path.join(currDir, relDir)
# print(finalPath)
cHeaderFile = open(finalPath, 'w')
except:
print("Can't create new files\n")
sys.exit(0)
cHeaderFile.write("#ifndef _OLED_FONT_H_" + (sys.argv[2]).upper() + "\n")
cHeaderFile.write("#define _OLED_FONT_H_" + (sys.argv[2]).upper() + "\n")
cHeaderFile.write("" + "\n")
cHeaderFile.write("#ifdef __cplusplus" + "\n")
cHeaderFile.write("extern \"C\" {" + "\n")
cHeaderFile.write("#endif" + "\n")
cHeaderFile.write("#include <stdint.h>" + "\n")
cHeaderFile.write('#include "oled_font.h"' + "\n")
cHeaderFile.write("" + "\n")
cHeaderFile.write("extern const fontSetDesc " + sys.argv[2] + "_set;" + "\n")
cHeaderFile.write("" + "\n")
cHeaderFile.write("#ifdef __cplusplus" + "\n")
cHeaderFile.write("}" + "\n")
cHeaderFile.write("#endif" + "\n")
cHeaderFile.write("#endif" + "\n")
try:
cHeaderFile.close()
except:
print("Can't close c header file")
sys.exit(0)
try:
currDir = os.path.dirname(os.path.abspath(__file__))
# print(currDir)
relDir = destFolder + "/" + "oled_font_" + sys.argv[2] + ".c"
finalPath = os.path.join(currDir, relDir)
# print(finalPath)
cSourceFile = open(finalPath, 'w')
except:
print("Can't create new files\n")
sys.exit(0)
# start writing to the c source file
cSourceFile.write('#include "oled_font_' + sys.argv[2] + '.h"\n')
cSourceFile.write("#include <stdint.h>\n")
cSourceFile.write("\n")
cSourceFile.write("#define TOTAL_CHAR " + str(len(finalList)) + "\n")
cSourceFile.write("#define CHAR_LIST_OFFSET " + str(firstCharFound) + "\n\n")
cSourceFile.write("const fontDescList " + sys.argv[2] + "[TOTAL_CHAR] = {\n")
structMember = ""
for charMoved in finalList:
structMember = structMember.join(["{.glyphLen = ", str(len(charMoved)), ", .glyphBitmap=(uint8_t[]){", ', '.join(map(str, charMoved)), "}}, /* " + chr(firstCharFound) + " */ \n"])
cSourceFile.write(structMember)
structMember = ""
firstCharFound += 1
cSourceFile.write("\n};\n\n")
# write font set definition
cSourceFile.write("const fontSetDesc " + sys.argv[2] + "_set = {\n")
cSourceFile.write("\t.totalChar = TOTAL_CHAR,\n")
cSourceFile.write("\t.charOffset = CHAR_LIST_OFFSET,\n")
cSourceFile.write("\t.descList = " + sys.argv[2] + ", \n};\n")
try:
cSourceFile.close()
except:
print("Can't close c source file")
sys.exit(0)
def main():
makeCFile(createSourceFontFile())
os.remove(fontSourceFileName)
if __name__ == '__main__':
main()