1 #!/usr/bin/env python 2 3 """ 4 Convert simple font bitmaps to GNU assembler data. 5 6 Copyright (C) 2018 Paul Boddie <paul@boddie.org.uk> 7 8 This program is free software; you can redistribute it and/or modify it under 9 the terms of the GNU General Public License as published by the Free Software 10 Foundation; either version 3 of the License, or (at your option) any later 11 version. 12 13 This program is distributed in the hope that it will be useful, but WITHOUT ANY 14 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 15 PARTICULAR PURPOSE. See the GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License along 18 with this program. If not, see <http://www.gnu.org/licenses/>. 19 """ 20 21 import sys 22 23 class MissingRow(Exception): 24 25 "Indicate a missing row in a character definition." 26 27 def __init__(self, lineno): 28 self.lineno = lineno 29 30 def __repr__(self): 31 return "MissingRow(%r)" % self.lineno 32 33 34 35 def get_character_row(f, lineno=0): 36 37 "Return a row of characters from 'f', employing 'lineno' for reference." 38 39 line = f.readline().strip() 40 rows = [] 41 42 while line: 43 row = line.split() 44 if rows and len(row) != len(rows[-1]): 45 raise MissingRow, lineno 46 47 rows.append(row) 48 lineno += 1 49 line = f.readline().strip() 50 51 chars = [] 52 53 if rows: 54 for i in range(0, len(rows[0])): 55 char = [] 56 for row in rows: 57 char.append(row[i]) 58 chars.append(char) 59 60 return chars 61 62 63 64 def convert(infile, outfile, base=33): 65 66 "Convert textual data in 'infile' to assembler data in 'outfile'." 67 68 f_in = open(infile) 69 f_out = open(outfile, "w") 70 try: 71 print >>f_out, """\ 72 .globl fontchars 73 .globl fonttable 74 .globl fontbase 75 .globl fontlimit 76 77 .section .flash, "a" 78 79 fontbase: 80 .word %d 81 82 fontchars:""" % base 83 84 lineno = 1 85 offset = 0 86 offsets = [] 87 point = base 88 89 # Get each row of characters. 90 91 chars = get_character_row(f_in, lineno) 92 93 while chars: 94 lineno += len(chars[0]) + 1 95 96 # Write each character definition. 97 98 for point, char in enumerate(chars, point): 99 offsets.append(offset) 100 offset += write_character(f_out, point, char) 101 102 point += 1 103 104 # Get the next row. 105 106 chars = get_character_row(f_in, lineno) 107 108 # Write the limit of characters. 109 110 print >>f_out, """\ 111 fontlimit: 112 .word %d""" % point 113 114 # Write the offset table. 115 116 print >>f_out, """\ 117 fonttable:""" 118 119 for offset in offsets: 120 print >>f_out, ".word %d" % offset 121 122 finally: 123 f_in.close() 124 f_out.close() 125 126 127 128 def write_character(f, point, char): 129 130 "Write to 'f' for the given 'point' the indicated 'char' definition." 131 132 # Write a comment and pixel width information. 133 134 print >>f, """\ 135 /* %d */ 136 .byte %d /* width in pixels */ 137 .byte %d /* height in pixels */ 138 """ % (point, len(char[0]), len(char)) 139 140 # Write the pixel rows to a sequence of bytes. 141 142 for row in char: 143 print >>f, ".byte 0b%s" % row.replace("-", "0").replace("#", "1") 144 145 print >>f 146 147 # Return the size of the definition as the number of rows plus the width 148 # and height bytes. 149 150 return len(char) + 2 151 152 153 154 # Main program. 155 156 if __name__ == "__main__": 157 158 # Obtain filenames. 159 160 try: 161 infile, outfile = sys.argv[1:3] 162 except ValueError: 163 print >>sys.stderr, """\ 164 Usage: %s <input filename> <output filename> 165 """ 166 sys.exit(1) 167 168 # Perform the conversion. 169 170 try: 171 convert(infile, outfile) 172 except MissingRow, exc: 173 print >>sys.stderr, """\ 174 Missing character information at line %d in file %s. 175 """ % (exc.lineno, infile) 176 177 # vim: tabstop=4 expandtab shiftwidth=4