-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmicrofont.py
95 lines (76 loc) · 2.84 KB
/
microfont.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
from array import array
import displayio
import fs
import sys
large = None
small = None
def init():
global large
global small
large = get('kairon-16', sys.path)
small = get('kairon-10', sys.path)
def get(font_id, dirs):
for dir in dirs:
path = dir + '/' + font_id + '.mcf'
if fs.isfile(path):
return Microfont(path)
raise ValueError(font_id + ' not found.')
class Microfont:
# All glyphs are concatenated horizontally into a single bitmap.
# The set of available characters is represented as the union of
# one or more codepoint ranges. The file begins with a magic
# number, the dimensions of the bitmap, and the number of ranges.
# Then comes the bitmap data, followed by arrays that specify:
# - The starting and ending codepoints of each codepoint range
# - The x-offset into the bitmap of each glyph
# - The x-offset of each glyph within its bounding box
# - The advance width of each glyph
def __init__(self, path):
with fs.open(path) as file:
assert file.read(4) == b'\xc2\xb5f1'
wh, wl, h, num_ranges = file.read(4)
w = (wh << 8) + wl
bitmap = displayio.Bitmap(w, h, 2)
if hasattr(bitmap, 'readbits'):
bitmap.readbits(file)
else:
file.readinto(memoryview(bitmap))
starts = array('H', range(num_ranges))
file.readinto(memoryview(starts))
stops = array('H', range(num_ranges))
file.readinto(memoryview(stops))
num_chars = 0
for i in range(num_ranges):
num_chars += stops[i] - starts[i]
sxs = array('H', range(num_chars + 1))
file.readinto(memoryview(sxs))
dxs = bytearray(num_chars)
file.readinto(dxs)
cws = bytearray(num_chars)
file.readinto(cws)
(self.w, self.h, self.bitmap, self.starts, self.stops, self.sxs,
self.dxs, self.cws) = w, h, bitmap, starts, stops, sxs, dxs, cws
def get_index(self, ch):
c = ord(ch)
r, nr = 0, len(self.starts)
offset = 0
while r < nr:
start, stop = self.starts[r], self.stops[r]
if c >= start and c < stop:
return offset + c - start
offset += stop - start
r += 1
return 0
def measure(self, text):
return sum(self.cws[self.get_index(ch)] for ch in text)
def draw(self, text, bitmap, x=0, y=0, pi=1):
for ch in text:
i = self.get_index(ch)
bitmap.freeblit(
x + self.dxs[i], y,
self.bitmap,
self.sxs[i], 0, self.sxs[i + 1] - self.sxs[i], self.h,
source_bg=0, dest_value=pi
)
x += self.cws[i]
return x