1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2024-12-23 17:34:00 +03:00
systemd-stable/tools/compile-unifont.py
David Herrmann 86db5dfb6d terminal: add unifont font-handling
The unifont layer of libsystemd-terminal provides a fallback font for
situations where no system-fonts are available, or if you don't want to
deal with traditional font-formats for some reasons.

The unifont API mmaps a pre-compiled bitmap font that was generated out of
GNU-Unifont font-data. This guarantees, that all users of the font will
share the pages in memory. Furthermore, the layout of the binary file
allows accessing glyph data in O(1) without pre-rendering glyphs etc. That
is, the OS can skip loading pages for glyphs that we never access.

Note that this is currently a test-run and we want to include the binary
file in the GNU-Unifont package. However, until it was considered stable
and accepted by the maintainers, we will ship it as part of systemd. So
far it's only enabled with the experimental --enable-terminal, anyway.
2014-07-18 17:45:33 +02:00

117 lines
3.5 KiB
Python
Executable File

# -*- 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)