# HG changeset patch # User Paul Boddie # Date 1527112629 -7200 # Node ID 05788bc55c390e0fced8652ca1ea864073875e4d # Parent 4e4cf2e64a7203c602084556b4b297f2cddf2d96 Introduced tools and a placeholder that causes the Unifont binary to be built. diff -r 4e4cf2e64a72 -r 05788bc55c39 pkg/landfall-examples/input_event_client/unifont.tff Binary file pkg/landfall-examples/input_event_client/unifont.tff has changed diff -r 4e4cf2e64a72 -r 05788bc55c39 pkg/landfall-examples/input_event_client/unifont.tff.needed --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/landfall-examples/input_event_client/unifont.tff.needed Wed May 23 23:57:09 2018 +0200 @@ -0,0 +1,1 @@ +If unifont.tff is missing, generate it using the tools/makefonts.sh script. diff -r 4e4cf2e64a72 -r 05788bc55c39 tools/install.sh --- a/tools/install.sh Mon May 21 00:52:45 2018 +0200 +++ b/tools/install.sh Wed May 23 23:57:09 2018 +0200 @@ -1,5 +1,10 @@ #!/bin/sh +if ! which realpath > /dev/null ; then + echo "Please install the realpath program." 1>&2 + exit 1 +fi + THISDIR=`dirname "$0"` DIRNAME=`realpath "$THISDIR/.."` PROGNAME=`basename "$0"` @@ -40,7 +45,7 @@ L4DIR=$1 -# Copy (or remove) each of the objects. +# Determine the mode. if [ "$2" = '--clean' ] ; then CLEAN=$2 @@ -48,6 +53,14 @@ CLEAN= fi +# Generate binaries if appropriate. + +if [ ! "$CLEAN" ] ; then + "$THISDIR/makefonts.sh" -q +fi + +# Copy (or remove) each of the objects. + for OBJTYPE in 'conf' 'pkg' ; do TARGETDIR=`realpath "$L4DIR"`/$OBJTYPE SOURCEDIR="$DIRNAME/$OBJTYPE" diff -r 4e4cf2e64a72 -r 05788bc55c39 tools/makefonts.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/makefonts.sh Wed May 23 23:57:09 2018 +0200 @@ -0,0 +1,62 @@ +#!/bin/sh + +if ! which realpath > /dev/null ; then + echo "Please install the realpath program." 1>&2 + exit 1 +fi + +THISDIR=`dirname "$0"` +DIRNAME=`realpath "$THISDIR/.."` +PROGNAME=`basename "$0"` + +UNIFONT='/usr/share/unifont/unifont.hex' + +if [ "$1" = '--help' ] ; then + cat 1>&2 <&2 + fi + continue + fi + + if [ "$FONTNAME" != 'unifont' ] ; then + if [ ! "$QUIET" ] ; then + echo "Unrecognised ($FONTNAME), not generated: $FONTPATH" 1>&2 + fi + continue + fi + + if [ ! "$QUIET" ] ; then + echo "$FONTPATH" + fi + "$THISDIR/readfont.py" "$UNIFONT" "$FONTPATH" +done diff -r 4e4cf2e64a72 -r 05788bc55c39 tools/readfont.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/readfont.py Wed May 23 23:57:09 2018 +0200 @@ -0,0 +1,244 @@ +#!/usr/bin/env python + +""" +Convert GNU Unifont format definitions into the .tff font format used by L4Re. +Note that this .tff format is *not* .ttf, the latter being TrueType format. +Searching the Internet for .tff will yield lots of .ttf nonsense. + +Copyright (C) 2017, 2018 Paul Boddie + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 3 of the License, or (at your option) any later +version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program. If not, see . +""" + +from os.path import split +import sys + +def convert_font(fin, fout, points, missing=32): + + """ + Convert the font obtained via 'fin' to an assembly language representation, + writing to 'fout' the characters for the chosen sequence of 'points'. + + A table of offsets is written to permit each character to be found in the + generated data. + + If 'missing' is specified, the character of the given value will be used + for missing character data. + """ + + points.sort() + base = points[0] + limit = points[-1] + + # Store the offset of each chosen character. + + table = [] + + # Search for each character until no more remain to be found. + + index = 0 + end = len(points) + + # Record character widths and bitmaps. + + widths = [] + bitmaps = [] + height = 16 + + line = fin.readline() + + while line and index < end: + point, width, bytes = read_entry(line, height) + + # Add a null offset for unselected characters. + + if point < points[index]: + if point >= base: + widths.append(None) + bitmaps.append(None) + line = fin.readline() + continue + + bitmaps.append(bytes) + widths.append(width) + + index += 1 + line = fin.readline() + + # Generate the offsets. + + line_step = 0 + + for width in widths: + if width is None: + width = widths[missing - base] + table.append(line_step) + line_step += width + + # Write the offset table. + + for offset in table: + if offset is None: + offset = table[missing - base] + fout.write(uint32_out(offset)) + + # Write the widths table. + + for width in widths: + if width is None: + width = widths[missing - base] + fout.write(uint32_out(width)) + + # Write the line data step size and common height. + + fout.write(uint32_out(line_step)) + fout.write(uint32_out(height)) + + # Write the bitmaps. + + line = 0 + while line < height: + for width, bitmap in zip(widths, bitmaps): + if bitmap is None: + bitmap = bitmaps[missing - base] + + bytes_per_line = width / 8 + start = line * bytes_per_line + + data = bitmap[start:start+bytes_per_line] + fout.write(bits_out(data)) + + line += 1 + +def read_entry(line, height): + + # Obtain the code point and data. + + point, data = line.rstrip().split(":") + point = int(point, 16) + + # Each data digit represents four bits. + + width = (len(data) * 4) / height + + # Obtain the byte values from the data. + + bytes = [] + i = 0 + while i < len(data): + bytes.append(int(data[i:i+2], 16)) + i += 2 + + return point, width, bytes + +# Utilities for writing .tff fonts. + +def bits_out(s): + result = [] + for value in s[::-1]: + i = 0 + while i < 8: + result.insert(0, (value & 0x01) and "\xff" or "\x00") + value >>= 1 + i += 1 + return "".join(result) + +def uint32_out(value): + result = [] + i = 0 + while i < 4: + result.append(chr(value & 0xff)) + value >>= 8 + i += 1 + return "".join(result) + +# Utilities for reading .tff fonts. + +def uint32(s): + result = 0 + i = 3 + while i >= 0: + result = (result << 8) + ord(s[i]) + i -= 1 + return result + +def words(s): + l = [] + i = 0 + while i < len(s): + l.append(s[i:i+4]) + i += 4 + return l + +class Font: + + "An abstraction for the .tff format." + + def __init__(self, filename): + f = open(filename) + try: + self.otab = map(uint32, words(f.read(1024))) + self.wtab = map(uint32, words(f.read(1024))) + self.w = uint32(f.read(4)) + self.h = uint32(f.read(4)) + self.img = f.read() + finally: + f.close() + + def show(self, c): + num = ord(c) + offset = self.otab[num] + row = 0 + while row < self.h: + start = offset + row * self.w + print self.img[start:start + self.wtab[num]].replace("\xff", "#").replace("\x00", ".") + row += 1 + +# Main program. + +if __name__ == "__main__": + + # Test options. + + if "--help" in sys.argv or len(sys.argv) < 3: + basename = split(sys.argv[0])[1] + print >>sys.stderr, """\ +Usage: + +%s +""" % basename + sys.exit(1) + + base = 0 + points = range(base, 256) + + filename_or_option, tff_filename = sys.argv[1:3] + + if filename_or_option == "--show": + f = Font(tff_filename) + for arg in sys.argv[3:]: + for char in arg: + f.show(char) + + # Convert from the input to the output file. + + else: + fin = open(filename_or_option) + fout = open(tff_filename, "w") + try: + convert_font(fin, fout, points, base) + finally: + fin.close() + fout.close() + +# vim: tabstop=4 expandtab shiftwidth=4