kopia lustrzana https://github.com/peterhinch/micropython-font-to-py
Height determination improved. Better user feedback.
rodzic
4058de707a
commit
67ea344993
35
DRIVERS.md
35
DRIVERS.md
|
@ -78,6 +78,14 @@ Where the buffer is located on the display device the means of controlling the
|
|||
text insertion point will be device dependent. The driver will need to
|
||||
implement the functionality of the ``Writer`` class itself.
|
||||
|
||||
## Fixed width fonts
|
||||
|
||||
If a Python font file is created with the ``-f`` argument, all characters will
|
||||
be saved with the width of the widest. In general it is not necessary to
|
||||
specify this option. The driver can perform fixed pich rendering by rendering
|
||||
the character as variable pitch, then advancing the pixel column by the value
|
||||
returned by ``font.max_width()``.
|
||||
|
||||
## Drivers with local buffers
|
||||
|
||||
The writer of a device driver need not be concerned with the structure of a
|
||||
|
@ -127,7 +135,7 @@ things as the text insertion point. Consideration should be given to employing
|
|||
the same interface as the ``Writer`` class to simplify the porting of user code
|
||||
between displays with differing hardware.
|
||||
|
||||
## Font files
|
||||
## Python Font files
|
||||
|
||||
Assume the user has run the utility to produce a file ``myfont.py`` This then
|
||||
has the following outline definition (in practice the bytes objects are large):
|
||||
|
@ -182,6 +190,28 @@ character check.
|
|||
and contains all the bytes required to render the character including trailing
|
||||
space.
|
||||
|
||||
## Binary font files
|
||||
|
||||
These are unlikely to find application beyond the e-paper driver, but for
|
||||
completeness the format is as follows. They are binary files with a four byte
|
||||
header and 126 fixed length records. The header consists of two file identifiers
|
||||
enabling the file format to be checked, followed by bytes specifying the width
|
||||
and height. The length of each record is (width + 1) bytes.
|
||||
|
||||
The file indentifiers depend on the -x and -r arguments specified to ``font_to_py.py``
|
||||
and are as follows:
|
||||
|
||||
hmap reverse byte
|
||||
-x -r 0 1
|
||||
0 0 0x3f 0xe7
|
||||
1 0 0x40 0xe7
|
||||
0 1 0x41 0xe7
|
||||
1 1 0x42 0xe7
|
||||
|
||||
Each record starts with a width byte specifying the x dimension of the glyph if
|
||||
rendered proportionally spaced, followed by the glyph data. This data includes
|
||||
trailing space ensuring that all records have the size specified in the header.
|
||||
|
||||
## Mapping
|
||||
|
||||
A character occupies a space where (0, 0) represents the coordinates of the top
|
||||
|
@ -215,4 +245,5 @@ The approach has been tested on SSD1306 devices using both the pseudo-horizontal
|
|||
and true vertical mapping.
|
||||
|
||||
The ``font_to_py`` utility has been extensively tested with each of the mapping
|
||||
options.
|
||||
options. It has been used with drivers for SSD1306 OLEDs, SSD1963 LCD displays,
|
||||
and the e-paper display.
|
||||
|
|
|
@ -24,7 +24,7 @@ Example usage to produce a file ``myfont.py`` with height of 23 pixels:
|
|||
1. Font file path. Must be a ttf or otf file.
|
||||
2. Height in pixels.
|
||||
3. Output file path. Must have a .py extension otherwise a binary font file
|
||||
will be created; in this instance a warning message is output.
|
||||
will be created.
|
||||
|
||||
### Optional arguments:
|
||||
|
||||
|
@ -36,6 +36,15 @@ Example usage to produce a file ``myfont.py`` with height of 23 pixels:
|
|||
Optional arguments other than the fixed pitch argument will be specified in the
|
||||
device driver documentation. Bit reversal is required by some display hardware.
|
||||
|
||||
### Output
|
||||
|
||||
The specified height is a target. The algorithm gets as close to the target
|
||||
height as possible (usually within one pixel). The actual height achieved is
|
||||
displayed on completion.
|
||||
|
||||
A warning is output if the output filename does not have a .py extension as the
|
||||
creation of a binary font file may not be intended.
|
||||
|
||||
## The font file
|
||||
|
||||
Assume that the you have employed the utility to create a file ``myfont.py``. In
|
||||
|
|
|
@ -280,18 +280,19 @@ class Font(dict):
|
|||
max_ascent = 0
|
||||
for char in self.charset:
|
||||
glyph = self._glyph_for_character(char)
|
||||
max_ascent = max(max_ascent, int(glyph.ascent))
|
||||
max_descent = max(max_descent, int(glyph.descent))
|
||||
max_ascent = max(max_ascent, glyph.ascent)
|
||||
max_descent = max(max_descent, glyph.descent)
|
||||
# for a few chars e.g. _ glyph.width > glyph.advance_width
|
||||
max_width = int(max(max_width, glyph.advance_width,
|
||||
glyph.width))
|
||||
|
||||
error = required_height - (max_ascent + max_descent)
|
||||
if error == 0:
|
||||
new_error = required_height - (max_ascent + max_descent)
|
||||
if (new_error == 0) or (abs(new_error) - abs(error) == 0):
|
||||
break
|
||||
print('Height set in {} passes'.format(npass))
|
||||
self.height = max_ascent + max_descent
|
||||
self._max_descent = max_descent
|
||||
error = new_error
|
||||
self.height = int(max_ascent + max_descent)
|
||||
print('Height set in {} passes. Actual height {} pixels'.format(npass + 1, self.height))
|
||||
self._max_descent = int(max_descent)
|
||||
return max_width
|
||||
|
||||
|
||||
|
@ -332,8 +333,8 @@ class Font(dict):
|
|||
index += (len(data)).to_bytes(2, byteorder='little')
|
||||
return data, index
|
||||
|
||||
def build_binary_array(self, hmap, reverse):
|
||||
data = bytearray((0x3f, 0xe7, self.max_width, self.height))
|
||||
def build_binary_array(self, hmap, reverse, sig):
|
||||
data = bytearray((0x3f + sig, 0xe7, self.max_width, self.height))
|
||||
for char in self.charset:
|
||||
width = self[char][2]
|
||||
data += bytes((width,))
|
||||
|
@ -401,16 +402,23 @@ def write_data(stream, fnt, font_path, monospaced, hmap, reverse):
|
|||
stream.write(STR02.format(height, height))
|
||||
|
||||
# BINARY OUTPUT
|
||||
|
||||
# hmap reverse magic bytes
|
||||
# 0 0 0x3f 0xe7
|
||||
# 1 0 0x40 0xe7
|
||||
# 0 1 0x41 0xe7
|
||||
# 1 1 0x42 0xe7
|
||||
def write_binary_font(op_path, font_path, height, hmap, reverse):
|
||||
try:
|
||||
fnt = Font(font_path, height, True) # All chars have same width
|
||||
except freetype.ft_errors.FT_Exception:
|
||||
print("Can't open", font_path)
|
||||
return False
|
||||
sig = 1 if hmap else 0
|
||||
if reverse:
|
||||
sig += 2
|
||||
try:
|
||||
with open(op_path, 'wb') as stream:
|
||||
data = fnt.build_binary_array(hmap, reverse)
|
||||
data = fnt.build_binary_array(hmap, reverse, sig)
|
||||
stream.write(data)
|
||||
except OSError:
|
||||
print("Can't open", op_path, 'for writing')
|
||||
|
|
Ładowanie…
Reference in New Issue