kopia lustrzana https://github.com/peterhinch/micropython-font-to-py
177 wiersze
6.0 KiB
Python
177 wiersze
6.0 KiB
Python
#! /usr/bin/python3
|
|
# -*- coding: utf-8 -*-
|
|
|
|
# The MIT License (MIT)
|
|
#
|
|
# Copyright (c) 2016 Peter Hinch
|
|
#
|
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
# of this software and associated documentation files (the "Software"), to deal
|
|
# in the Software without restriction, including without limitation the rights
|
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
# copies of the Software, and to permit persons to whom the Software is
|
|
# furnished to do so, subject to the following conditions:
|
|
#
|
|
# The above copyright notice and this permission notice shall be included in
|
|
# all copies or substantial portions of the Software.
|
|
#
|
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
# THE SOFTWARE.
|
|
|
|
# Test programs for the utility font_to_py and for font files created by it.
|
|
# The test of most general use is test_font which enables a string to be
|
|
# output to the REPL using a font file created by this utility.
|
|
|
|
import sys
|
|
import os
|
|
from importlib import import_module
|
|
from font_to_py import Font, write_font
|
|
|
|
# Utility functions
|
|
|
|
def validate_hmap(data, height, width):
|
|
bpr = (width - 1)//8 + 1
|
|
msg = 'Horizontal map, invalid data length'
|
|
assert len(data) == bpr * height, msg
|
|
|
|
|
|
def validate_vmap(data, height, width):
|
|
bpc = (height - 1)//8 + 1
|
|
msg = 'Vertical map, invalid data length'
|
|
assert len(data) == bpc * width, msg
|
|
|
|
|
|
# Routines to render to REPL
|
|
def render_row_hmap(data, row, height, width, reverse):
|
|
validate_hmap(data, height, width)
|
|
bytes_per_row = (width - 1)//8 + 1
|
|
for col in range(width):
|
|
byte = data[row * bytes_per_row + col // 8]
|
|
if reverse:
|
|
bit = (byte & (1 << (col % 8))) > 0
|
|
else:
|
|
bit = (byte & (1 << (7 - (col % 8)))) > 0
|
|
char = '#' if bit else '.'
|
|
print(char, end='')
|
|
|
|
|
|
def render_row_vmap(data, row, height, width, reverse):
|
|
validate_vmap(data, height, width)
|
|
bytes_per_col = (height - 1)//8 + 1
|
|
for col in range(width):
|
|
byte = data[col * bytes_per_col + row//8]
|
|
if reverse:
|
|
bit = (byte & (1 << (7 - (row % 8)))) > 0
|
|
else:
|
|
bit = (byte & (1 << (row % 8))) > 0
|
|
char = '#' if bit else '.'
|
|
print(char, end='')
|
|
|
|
|
|
def display(data, hmap, height, width, reverse):
|
|
bpr = (width - 1)//8 + 1
|
|
bpc = (height - 1)//8 + 1
|
|
print('Height: {} Width: {}'.format(height, width))
|
|
print('Bytes/row: {} Bytes/col: {}'.format(bpr, bpc))
|
|
print('Data length: {}'.format(len(data)))
|
|
# Check bytearray is the correct length
|
|
if hmap:
|
|
validate_hmap(data, height, width)
|
|
else:
|
|
validate_vmap(data, height, width)
|
|
|
|
for row in range(height):
|
|
if hmap:
|
|
render_row_hmap(data, row, height, width, reverse)
|
|
else:
|
|
render_row_vmap(data, row, height, width, reverse)
|
|
print()
|
|
|
|
|
|
# TESTS: in order of code coverage
|
|
# Basic test of Font class functionality
|
|
# Usage font_test.font_test()
|
|
def font_test():
|
|
fnt = Font('FreeSans.ttf', 20)
|
|
for char in 'WM_eg!.,':
|
|
fnt[char][0].display()
|
|
print(fnt.width)
|
|
|
|
# Font character streaming
|
|
# Usage font_test.test_stream('abc', 20, False, False, False)
|
|
def test_stream(string, height, monospaced, hmap, reverse):
|
|
fnt = Font("FreeSans.ttf", height, monospaced)
|
|
height = fnt.height
|
|
for char in string:
|
|
width = fnt[char][1]
|
|
data = bytearray(fnt.stream_char(char, hmap, reverse))
|
|
display(data, hmap, height, width, reverse)
|
|
|
|
|
|
def chr_addr(index, ordch):
|
|
offset = 2 * (ordch - 32)
|
|
return int.from_bytes(index[offset:offset + 2], 'little')
|
|
|
|
|
|
# Font.build_arrays
|
|
# Usage font_test.test_arrays('abc', 20, False, False, False)
|
|
def test_arrays(string, height, monospaced, hmap, reverse):
|
|
fnt = Font("FreeSans.ttf", height, monospaced)
|
|
height = fnt.height
|
|
data, index = fnt.build_arrays(hmap, reverse)
|
|
for char in string:
|
|
ordch = ord(char)
|
|
offset = chr_addr(index, ordch)
|
|
width = int.from_bytes(data[offset:offset + 2], 'little')
|
|
offset += 2
|
|
next_offs = chr_addr(index, ordch + 1)
|
|
display(data[offset:next_offs], hmap, height, width, reverse)
|
|
|
|
|
|
# Render a string to REPL using a specified Python font file
|
|
# usage font_test.test_font('freeserif', 'abc')
|
|
def test_font(fontfile, string):
|
|
if fontfile in sys.modules:
|
|
del sys.modules[fontfile] # force reload
|
|
myfont = import_module(fontfile)
|
|
|
|
height = myfont.height()
|
|
for row in range(height):
|
|
for char in string:
|
|
data, _, width = myfont.get_ch(char)
|
|
if myfont.hmap():
|
|
render_row_hmap(data, row, height, width, myfont.reverse())
|
|
else:
|
|
render_row_vmap(data, row, height, width, myfont.reverse())
|
|
print()
|
|
|
|
|
|
# Create font file, render a string to REPL using it
|
|
# usage font_test.test_file('FreeSans.ttf', 20, 'xyz')
|
|
def test_file(fontfile, height, string, *, minchar=32, maxchar=126, defchar=ord('?'),
|
|
fixed=False, hmap=False, reverse=False):
|
|
if not write_font('myfont.py', fontfile, height, fixed,
|
|
hmap, reverse, minchar, maxchar, defchar):
|
|
print('Failed to create font file.')
|
|
return
|
|
|
|
if 'myfont' in sys.modules:
|
|
del sys.modules['myfont'] # force reload
|
|
import myfont
|
|
|
|
height = myfont.height()
|
|
for row in range(height):
|
|
for char in string:
|
|
data, _, width = myfont.get_ch(char)
|
|
if myfont.hmap():
|
|
render_row_hmap(data, row, height, width, myfont.reverse())
|
|
else:
|
|
render_row_vmap(data, row, height, width, myfont.reverse())
|
|
print()
|
|
os.unlink('myfont.py')
|