-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmain.py
executable file
·174 lines (151 loc) · 4.88 KB
/
main.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
#!/usr/bin/python3
# SPDX-License-Identifier: AGPL-3.0-only
import argparse
try:
import png # type: ignore
except ModuleNotFoundError:
png = None
BLACK = 0
WHITE = 255
def sl(fret: str, n: int) -> str:
if fret in ['x', 'X', '0']:
return fret
return str(int(fret) - n)
# Fonts are 6 wide and 8 tall.
def load_font() -> dict[str, list[list[int]]]:
font: dict[str, list[list[int]]] = {}
curchar = None
with open("font", "r") as f:
while line := f.readline():
if line[-1] == '\n':
line = line[:-1]
if line == '':
continue
if line.startswith("SPDX"): # font license
continue
if ":" in line:
curchar = line[0]
font[curchar] = []
continue
row = [BLACK if c != ' ' else WHITE for c in list(line)]
assert(curchar)
font[curchar].append(row)
for k in font.keys():
glyph = font[k]
for i in range(len(glyph)):
while len(glyph[i]) < 6:
glyph[i].append(WHITE)
while len(glyph) < 8:
glyph.append([WHITE] * 6)
font[k] = glyph
return font
def dump_png(path: str, rows: list[list[str]], scale: int) -> None:
# Fonts are 6x8, though most characters actually define as 5x7. By
# implicitly anchoring them to the top left, we can slam them together
# without worrying about spacing.
font = load_font()
arr = []
for row in rows:
if '-' in row:
continue
for i in range(8):
line = []
seen_space = False
seen_nonspace = False
leftside = True
for j, c in enumerate(row):
if not seen_space and c == ' ':
seen_space = True
continue
if c == ' ' and seen_nonspace:
continue
if c != ' ':
seen_nonspace = True
if j == len(row) - 1:
if c == '|':
c = 'c'
elif c == '*':
c = 'r'
if leftside and c == '|':
leftside = False
c = 'o'
elif leftside and c == '*':
leftside = False
c = 'l'
if c == 'x':
c = 'X'
elif c == 't':
c = 'T'
line += font[c][i]
arr.append(line)
# padding
rowlen = len(arr[0])
arr.insert(0, [WHITE] * rowlen)
arr.append([WHITE] * rowlen)
for out_row in arr:
out_row.insert(0, WHITE)
if scale != 1:
bigger = []
for out_row in arr:
nr = []
for p in out_row:
for _ in range(scale):
nr.append(p)
for _ in range(scale):
bigger.append(nr)
arr = bigger
png.from_array(arr, 'L').save(args.output_png)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("-p", "--position", type=int, default=0)
parser.add_argument("-o", "--output-png", type=str)
parser.add_argument("-x", "--scale-by", type=int)
parser.add_argument("frets")
parser.add_argument("fingers")
args = parser.parse_args()
if args.output_png and not png:
print("python3-pypng is required to output images")
exit(1)
if args.scale_by and not args.output_png:
print("Scale is not usable unless outputting an image")
parser.print_help()
exit(1)
fingers = args.fingers.split(",")
frets = args.frets.split(",")
minfret = -1
maxfret = 0
for fret in frets:
if fret in ['x', 'X', '0']:
continue
fret = int(fret)
if fret > maxfret:
maxfret = fret
if minfret == -1 or fret < minfret:
minfret = fret
position = args.position
if position == 0:
position = minfret if maxfret > 5 else 1
if position > 1: # automatic position adjustment
frets = [sl(fret, position - 1) for fret in frets]
maxfret -= position - 1
rows = []
pad = ' ' * len(str(position))
rows.append(list(f"{pad} {' '.join(fingers)}"))
rows.append(list(f"{pad} -----------"))
for i in range(1, max(maxfret, 5) + 1):
row = []
if i == 1 and position != 1:
row.append(str(position))
else:
row.append(pad)
for fret in frets:
if fret != 0 and str(i) == fret:
row.append(" *")
else:
row.append(" |")
row = list(''.join(row))
rows.append(row)
if not args.output_png:
print("\n".join([''.join(r) for r in rows]))
exit(0)
dump_png(args.output_png, rows, args.scale_by)