|
| 1 | +#!/usr/bin/python2 |
| 2 | + |
| 3 | +# MIT License. |
| 4 | + |
| 5 | +# Copyright (c) 2016 William Skellenger |
| 6 | +# |
| 7 | +# Permission is hereby granted, free of charge, to any person obtaining a |
| 8 | +# copy of this software and associated documentation files (the "Software"), |
| 9 | +# to deal in the Software without restriction, including without limitation |
| 10 | +# the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| 11 | +# and/or sell copies of the Software, and to permit persons to whom the |
| 12 | +# Software is furnished to do so, subject to the following conditions: |
| 13 | +# |
| 14 | +# The above copyright notice and this permission notice shall be included |
| 15 | +# in all copies or substantial portions of the Software. |
| 16 | +# |
| 17 | +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| 18 | +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 19 | +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 20 | +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 21 | +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| 22 | +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
| 23 | +# IN THE SOFTWARE. |
| 24 | + |
| 25 | +# This small script is designed to mostly take a BDF file and convert it to a |
| 26 | +# format that can largely be cut/pasted as an Adafruit-format font. |
| 27 | +# It was written in an hour or so and did what I needed it to do. |
| 28 | +# I used it for one file. Maybe it bombs on other files. |
| 29 | +# William Skellenger, Feb 2016 |
| 30 | + |
| 31 | +# (Twitter: @skelliam) |
| 32 | +# |
| 33 | +# Usage: bdf2adafruit.py <somefont.bdf> > out.txt |
| 34 | +# |
| 35 | +# Once you have out.txt you can cut/paste the contents into a new font |
| 36 | +# header file as part of the Adafruit GFX library. |
| 37 | + |
| 38 | +import sys |
| 39 | + |
| 40 | +myfile = open(sys.argv[1]) |
| 41 | + |
| 42 | +processing = 0 |
| 43 | +getting_rows = 0 |
| 44 | + |
| 45 | +chars = [] |
| 46 | +bitmapData = [] |
| 47 | + |
| 48 | +class Glyph: |
| 49 | + encoding = -1 |
| 50 | + rows = [] |
| 51 | + comment = "" |
| 52 | + offset = -1 |
| 53 | + width = 0 |
| 54 | + height = 0 |
| 55 | + advance = 0 |
| 56 | + xoffs = 0 |
| 57 | + yoffs = 0 |
| 58 | + def __init__(self, comment): |
| 59 | + self.comment = comment |
| 60 | + self.rows = [] |
| 61 | + |
| 62 | +for line in myfile.readlines(): |
| 63 | + if 'STARTCHAR' in line: |
| 64 | + processing = 1 |
| 65 | + vals = line.split() |
| 66 | + g = Glyph(vals[1]) |
| 67 | + #g.width = 8 #in this example always 8 bits wide |
| 68 | + elif 'ENDCHAR' in line: |
| 69 | + dataByteCompressed = 0 |
| 70 | + dataByteCompressedIndex = 8 |
| 71 | + g.height = len(bitmapData) |
| 72 | + for value in bitmapData: |
| 73 | + bitIndex = 0 |
| 74 | + while bitIndex < g.width: |
| 75 | + bit = (value >> (7 - bitIndex)) & 0x01 |
| 76 | + dataByteCompressed |= bit << (dataByteCompressedIndex - 1) |
| 77 | + dataByteCompressedIndex -= 1 |
| 78 | + if dataByteCompressedIndex == 0: |
| 79 | + dataByteCompressedIndex = 8 |
| 80 | + g.rows.append(dataByteCompressed) |
| 81 | + dataByteCompressed = 0 |
| 82 | + bitIndex += 1 |
| 83 | + if 8 != dataByteCompressedIndex: |
| 84 | + g.rows.append(dataByteCompressed) |
| 85 | + |
| 86 | + chars.append(g) #append the completed glyph into list |
| 87 | + processing = 0 |
| 88 | + getting_rows = 0 |
| 89 | + bitmapData.clear() |
| 90 | + |
| 91 | + if processing: |
| 92 | + if 'ENCODING' in line: |
| 93 | + vals = line.split() |
| 94 | + g.encoding = int(vals[1]) |
| 95 | + elif 'DWIDTH' in line: |
| 96 | + vals = line.split() |
| 97 | + #g.advance = int(vals[1]) #cursor advance seems to be the first number in DWIDTH |
| 98 | + elif 'BBX' in line: |
| 99 | + vals = line.split() |
| 100 | + g.xoffs = 0 |
| 101 | + g.yoffs = -(int(vals[2]) + int(vals[4])) |
| 102 | + g.advance = (int(vals[1]) + 1) #x bounding box + 1 |
| 103 | + g.width = int(vals[1]) |
| 104 | + elif 'BITMAP' in line: |
| 105 | + getting_rows = 1 |
| 106 | + elif getting_rows: |
| 107 | + #g.rows.append(int(line, 16)) #append pixel rows into glyph's list of rows |
| 108 | + bitmapData.append(int(line, 16)) |
| 109 | + |
| 110 | +print |
| 111 | + |
| 112 | +i=0 |
| 113 | +for char in chars: |
| 114 | + char.offset = i |
| 115 | + print("\t", end='') |
| 116 | + num = 3 |
| 117 | + for row in char.rows: |
| 118 | + if num != 3: |
| 119 | + print(" ", end = '') |
| 120 | + print("0x%02X," %(row), end = ''), |
| 121 | + i+=1 |
| 122 | + num-=1 |
| 123 | + |
| 124 | + if num == 1: |
| 125 | + print("\t\t", end = '') |
| 126 | + if num == 2: |
| 127 | + print("\t\t\t", end = '') |
| 128 | + print("\t/* 0x%02X %s */" %(char.encoding, char.comment)) |
| 129 | + |
| 130 | +for char in chars: |
| 131 | + # offset, bit-width, bit-height, advance cursor, x offset, y offset |
| 132 | + print("\t{ %d, %d, %d, %d, %d, %d }, /* 0x%02X %s */" %( |
| 133 | + char.offset, char.width, char.height, |
| 134 | + char.advance, char.xoffs, char.yoffs, |
| 135 | + char.encoding, char.comment)) |
0 commit comments