summaryrefslogtreecommitdiff
path: root/tools/compile-unifont.py
blob: 7004b946d29fbb8c1865b3bffc163133235a6b79 (plain)
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
#  -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
#
#  This file is part of systemd.
#
#  Copyright 2013-2014 David Herrmann <dh.herrmann@gmail.com>
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.
#
#  systemd is distributed in the hope that it will be useful, but
#  WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
#  Lesser General Public License for more details.
#
#  You should have received a copy of the GNU Lesser General Public License
#  along with systemd; If not, see <http://www.gnu.org/licenses/>.

#
# Parse a unifont.hex file and produce a compressed binary-format.
#

from __future__ import print_function
import re
import sys
import fileinput
import struct

#
# Write "bits" array as binary output.
#

def write_bin_entry(entry):
    l = len(entry)
    if l != 32 and l != 64:
        entry = "0" * 64
        l = 0
    elif l < 64:
        entry += "0" * (64 - l)

    sys.stdout.buffer.write(struct.pack('B', int(l / 32)))  # width
    sys.stdout.buffer.write(struct.pack('B', 0))            # padding
    sys.stdout.buffer.write(struct.pack('H', 0))            # padding
    sys.stdout.buffer.write(struct.pack('I', 0))            # padding

    i = 0
    for j in range(0, 16):
        for k in range(0, 2):
            if l <= k * 16 * 2:
                c = 0
            else:
                c = int(entry[i:i+2], 16)
                i += 2

            sys.stdout.buffer.write(struct.pack('B', c))

def write_bin(bits):
    sys.stdout.buffer.write(struct.pack('B', 0x44))         # ASCII: 'D'
    sys.stdout.buffer.write(struct.pack('B', 0x56))         # ASCII: 'V'
    sys.stdout.buffer.write(struct.pack('B', 0x44))         # ASCII: 'D'
    sys.stdout.buffer.write(struct.pack('B', 0x48))         # ASCII: 'H'
    sys.stdout.buffer.write(struct.pack('B', 0x52))         # ASCII: 'R'
    sys.stdout.buffer.write(struct.pack('B', 0x4d))         # ASCII: 'M'
    sys.stdout.buffer.write(struct.pack('B', 0x55))         # ASCII: 'U'
    sys.stdout.buffer.write(struct.pack('B', 0x46))         # ASCII: 'F'
    sys.stdout.buffer.write(struct.pack('<I', 0))           # compatible-flags
    sys.stdout.buffer.write(struct.pack('<I', 0))           # incompatible-flags
    sys.stdout.buffer.write(struct.pack('<I', 32))          # header-size
    sys.stdout.buffer.write(struct.pack('<H', 8))           # glyph-header-size
    sys.stdout.buffer.write(struct.pack('<H', 2))           # glyph-stride
    sys.stdout.buffer.write(struct.pack('<Q', 32))          # glyph-body-size

    # write glyphs
    for idx in range(len(bits)):
        write_bin_entry(bits[idx])

#
# Parse hex file into "bits" array
#

def parse_hex_line(bits, line):
    m = re.match(r"^([0-9A-Fa-f]+):([0-9A-Fa-f]+)$", line)
    if m == None:
        return

    idx = int(m.group(1), 16)
    val = m.group(2)

    # insert skipped lines
    for i in range(len(bits), idx):
        bits.append("")

    bits.insert(idx, val)

def parse_hex():
    bits = []

    for line in sys.stdin:
        if not line:
            continue
        if line.startswith("#"):
            continue

        parse_hex_line(bits, line)

    return bits

#
# In normal mode we simply read line by line from standard-input and write the
# binary-file to standard-output.
#

if __name__ == "__main__":
    bits = parse_hex()
    write_bin(bits)