kopia lustrzana https://github.com/peterhinch/micropython-font-to-py
Writer version 0.3
rodzic
0d4883fa4e
commit
c341ee9bd2
250
DRIVERS.md
250
DRIVERS.md
|
@ -1,250 +0,0 @@
|
|||
# DRIVERS.md
|
||||
|
||||
This document comprises two sections, the first for users of an existing device
|
||||
driver and the second for writers of device drivers.
|
||||
|
||||
# User Documentation: the Writer class
|
||||
|
||||
This class facilitates rendering characters from Python font files to a device,
|
||||
assuming the device has a driver conforming to the specification below. Typical
|
||||
use is as follows:
|
||||
|
||||
```python
|
||||
from writer import Writer
|
||||
from device_driver import Display
|
||||
import freeserif
|
||||
import freesans20
|
||||
display = Display(args_required_by_driver)
|
||||
wri_serif = Writer(display, freeserif)
|
||||
wri_sans = Writer(display, freesans20)
|
||||
Writer.set_clip(True, True)
|
||||
wri_serif.printstring('Tuesday\n')
|
||||
wri_sans.printstring('8 Nov 2016\n')
|
||||
wri_sans.printstring('10.30am')
|
||||
|
||||
display.show() # Display the result
|
||||
```
|
||||
|
||||
The file ``driver_test.py`` illustrates the use of font files with an SSD1306
|
||||
display and a complete example of an SSD1306 driver may be found
|
||||
[here](https://github.com/peterhinch/micropython-samples/tree/master/SSD1306).
|
||||
|
||||
## Class Methods
|
||||
|
||||
The ``Writer`` class exposes the following class methods:
|
||||
|
||||
1. ``set_textpos`` Args: ``row``, ``col``. This determines where on screen any
|
||||
subsequent text is to be rendered. The initial value is (0, 0) - the top left
|
||||
corner. Arguments are in pixels with positive values representing down and
|
||||
right respectively. They reference the top left hand corner of the first
|
||||
character to be output.
|
||||
2. ``set_clip`` Args: boolean ``row_clip``, ``col_clip``. If these are
|
||||
``True``, characters will be clipped if they extend beyond the boundaries of
|
||||
the physical display. If ``col_clip`` is ``False`` characters will wrap onto
|
||||
the next line. If ``row_clip`` is ``False`` the display will, where necessary,
|
||||
scroll up to ensure the line is rendered.
|
||||
|
||||
As class methods these settings apply to all font objects. The insertion point
|
||||
of characters is maintained regardless of the font in use.
|
||||
|
||||
## Method
|
||||
|
||||
1. ``printstring`` Arg: a text string. Outputs a text string at the current
|
||||
insertion point. Newline characters are honoured.
|
||||
|
||||
## Note on the Writer class
|
||||
|
||||
This is more a proof of concept than a final implementation. Obvious
|
||||
enhancements include rendering to a rectangular area, support for proper word
|
||||
wrap and support for format control characters such as tabs.
|
||||
|
||||
# Device Driver Implementation
|
||||
|
||||
Display devices comprise two varieties, depending on whether the framebuffer is
|
||||
located on the controlling system or on the physical display device. In the
|
||||
former case the ``Writer`` class simplifies the design of the driver. It merely
|
||||
has to expose certin attributes and methods with ``Writer`` instances taking
|
||||
care of text rendering. It is strongly recommended that such device drivers use
|
||||
the oficial ``framebuf`` module, as per the official SSD1306 driver which
|
||||
exposes the required components.
|
||||
|
||||
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
|
||||
Python font file so long as the driver exposes certain attributes and methods
|
||||
required by the ``Writer`` class. These are as follows:
|
||||
|
||||
Attributes:
|
||||
|
||||
1. ``buffer`` The underlying ``bytearray`` instance holding the display
|
||||
buffer.
|
||||
2. ``height`` The screen height in pixels.
|
||||
3. ``width`` The screen width in pixels.
|
||||
|
||||
Methods:
|
||||
|
||||
1. ``show`` Display the current buffer contents.
|
||||
2. ``scroll`` Arguments ``x``, ``y`` amount to scroll horizontal and vertical.
|
||||
3. ``fill`` Argument ``col`` colour 1 == fill 0 == clear.
|
||||
|
||||
An example of such a driver, using the official ``framebuf`` module, is the
|
||||
SSD1306 driver (drivers/display/ssd1306.py in the source tree).
|
||||
|
||||
The driver documentation should specify the arguments for font_to_py.py to
|
||||
ensure users create font files with a layout corresponding to that of the
|
||||
buffer/device.
|
||||
|
||||
## Drivers for remote buffers
|
||||
|
||||
### Specifying the font file
|
||||
|
||||
Each font file has a ``get_ch()`` function accepting an ASCII character as its
|
||||
argument. It returns a memoryview instance providing access to a bytearray
|
||||
corresponding to the individual glyph. The layout of this data is determined by
|
||||
the command line arguments presented to the ``font_to_py.py`` utility. It is
|
||||
the responsibility of the driver to copy that data to the physical device.
|
||||
|
||||
The purpose of the ``font_to_py.py`` command line arguments specified to the
|
||||
user is to ensure that the data layout is optimised for the device so that this
|
||||
copy operation is a fast bytewise copy or SPI/I2C transfer. The driver
|
||||
documentation should therefore specify these arguments to ensure the layout is
|
||||
optimal. Mapping may be horizontal or vertical, and the bit order of individual
|
||||
bytes may be defined. These are detailed below.
|
||||
|
||||
In the case of devices with their own frame buffer the ``Writer`` class will need
|
||||
to be re-written or adapted to match the hardware's method of tracking such
|
||||
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.
|
||||
|
||||
## 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):
|
||||
|
||||
```python
|
||||
# Code generated by font-to-py.py.
|
||||
# Font: FreeSerif.ttf
|
||||
version = '0.2'
|
||||
|
||||
def height():
|
||||
return 21
|
||||
|
||||
def max_width():
|
||||
return 22
|
||||
|
||||
def hmap():
|
||||
return False
|
||||
|
||||
def reverse():
|
||||
return False
|
||||
|
||||
def monospaced():
|
||||
return False
|
||||
|
||||
def min_ch():
|
||||
return 32
|
||||
|
||||
def max_ch():
|
||||
return 126
|
||||
|
||||
_font =\
|
||||
b'\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x08\x00\xfe\xc7\x00\x7e\xc0\x00\x00\x00\x00\x00'\
|
||||
|
||||
_index =\
|
||||
b'\x00\x00\x14\x00\x2e\x00\x4b\x00\x71\x00\x97\x00\xd2\x00\x0a\x01'\
|
||||
b'\x1b\x01\x35\x01\x4f\x01\x75\x01\x9e\x01\xb2\x01\xcc\x01\xe0\x01'\
|
||||
|
||||
_mvfont = memoryview(_font)
|
||||
# Boilerplate code omitted
|
||||
|
||||
def get_ch(ch):
|
||||
# validate ch, if out of range use '?'
|
||||
# get offsets into _font and retrieve char width
|
||||
# Return: memoryview of bitmap, height and width
|
||||
return mvfont[offset + 2, next_offset], height, width
|
||||
```
|
||||
|
||||
``height`` and ``width`` are specified in bits (pixels).
|
||||
|
||||
In the case of monospaced fonts the ``max_width`` function returns the width of
|
||||
every character. For variable pitch fonts it returns the width of the widest
|
||||
character. Device drivers can use this to rapidly determine whether a string
|
||||
will fit the available space. If it will fit on the assumption that all chars
|
||||
are maximum width, it can be rendered rapidly without doing a character by
|
||||
character check.
|
||||
|
||||
``get_ch()`` returns a memoryview of an individual glyph with its dimensions
|
||||
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
|
||||
left hand corner of the bitmap. It comprises a set of pixels where increasing x
|
||||
values represent locations to the right of the origin and increasing y values
|
||||
represent downward positions. Mapping defines the relationship between this
|
||||
abstract two dimensional array of bits and the physical linear sequence of bytes.
|
||||
|
||||
Vertical mapping means that the LSB of first byte is pixel (0,0), MSB of first
|
||||
byte is (0, 7). The second byte (assuming the height is greater than 8 pixels)
|
||||
is (0, 8) to (0, 15). Once the column is complete the next byte represents
|
||||
(1, 0) to (1, 7).
|
||||
|
||||
Horizontal mapping means that the MSB of byte 0 is pixel (0,0) with LSB at
|
||||
(7,0), with the second byte covering (8, 0) to (15, 0) if the width is greater
|
||||
than 8.
|
||||
|
||||
Bit reversal provides for the case where the bit order of each byte is reversed
|
||||
i.e. a byte comprising bits [b7b6b5b4b3b2b1b0] becomes [b0b1b2b3b4b5b6b7].
|
||||
|
||||
# Specification and Project Notes
|
||||
|
||||
The design aims primarily to minimise RAM usage. Minimising the size of the
|
||||
bytecode is a secondary aim. Indexed addressing is used to reduce this in
|
||||
the case of proportional fonts, at a small cost in performance. The size of the
|
||||
Python source file is a lesser consideration, with readability being prioritised
|
||||
over size. Hence they are "pretty formatted" with the large bytes objects
|
||||
split over multiple lines for readability.
|
||||
|
||||
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. It has been used with drivers for SSD1306 OLEDs, SSD1963 LCD displays,
|
||||
and the e-paper display.
|
|
@ -5,10 +5,12 @@ is to save RAM on resource-limited targets: the font file may be incorporated
|
|||
into a firmware build such that it occupies flash memory rather than scarce
|
||||
RAM. Python code built into firmware is known as frozen bytecode.
|
||||
|
||||
# Dependency
|
||||
###### [Main README](./README.md)
|
||||
|
||||
The utility requires `freetype` which may be installed using `pip3`. On Linux
|
||||
at a root prompt:
|
||||
# Dependencies
|
||||
|
||||
The utility requires Python 3.2 or greater, also `freetype` which may be
|
||||
installed using `pip3`. On Linux at a root prompt:
|
||||
|
||||
```shell
|
||||
# apt-get install python3-pip
|
||||
|
@ -81,7 +83,7 @@ import myfont
|
|||
|
||||
The `myfont` module name will then be used to instantiate a `Writer` object
|
||||
to render strings on demand. A practical example may be studied
|
||||
[here](https://github.com/peterhinch/micropython-samples/blob/master/SSD1306/ssd1306_test.py).
|
||||
[here](https://github.com/peterhinch/micropython-samples/blob/master/SSD1306/ssd1306_demo.py).
|
||||
The detailed layout of the Python file may be seen [here](./DRIVERS.md).
|
||||
|
||||
### Binary font files
|
||||
|
@ -116,39 +118,45 @@ may be viewed [here](https://dbader.org/blog/monochrome-font-rendering-with-free
|
|||
|
||||
# Appendix: RAM utilisation Test Results
|
||||
|
||||
A font file was created, frozen as bytecode and deployed to a version 1.0
|
||||
Pyboard. The font was saved as variable pitch with a height of 19 pixels. The
|
||||
following code was then pasted at the REPL:
|
||||
The supplied `freesans20.py` and `courier20.py` files were frozen as bytecode
|
||||
on a Pyboard V1.0. The following code was pasted at the REPL:
|
||||
|
||||
```python
|
||||
import gc, micropython
|
||||
gc.collect()
|
||||
micropython.mem_info()
|
||||
|
||||
import freeserif
|
||||
import freesans20
|
||||
|
||||
gc.collect()
|
||||
micropython.mem_info()
|
||||
|
||||
import courier20
|
||||
|
||||
gc.collect()
|
||||
micropython.mem_info()
|
||||
|
||||
def foo():
|
||||
addr, height, width = freeserif.get_ch('a')
|
||||
addr, height, width = freesans20.get_ch('a')
|
||||
|
||||
foo()
|
||||
|
||||
gc.collect()
|
||||
micropython.mem_info()
|
||||
print(len(freeserif._font) + len(freeserif._index))
|
||||
print(len(freesans20._font) + len(freesans20._index))
|
||||
```
|
||||
|
||||
The memory used was 5408, 5648, and 5696 bytes. As increments over the initial
|
||||
state this corresponds to 240 and 288 bytes. The `print` statement shows the
|
||||
RAM which would be consumed by the data arrays: this was 3271 bytes.
|
||||
The memory used was 1712, 2048, 2400 and 2416 bytes. As increments over the
|
||||
prior state this corresponds to 336, 352 and 16 bytes. The `print` statement
|
||||
shows the RAM which would be consumed by the data arrays: this was 3766 bytes
|
||||
for `freesans20`.
|
||||
|
||||
The `foo()` function emulates the behaviour of a device driver in rendering a
|
||||
character to a display. The local variables constitute memory which will be
|
||||
reclaimed on exit from the function. Its additional RAM use was 48 bytes.
|
||||
character to a display. The local variables constitute memory which is
|
||||
reclaimed on exit from the function. Its additional RAM use was 16 bytes.
|
||||
|
||||
## Conclusion
|
||||
|
||||
With a font of height 19 pixels RAM saving was an order of magnitude. The
|
||||
saving will be greater if larger fonts are used
|
||||
With a font of height 20 pixels RAM saving was an order of magnitude. The
|
||||
saving will be greater if larger fonts are used as RAM usage is independent of
|
||||
the array sizes.
|
||||
|
|
30
README.md
30
README.md
|
@ -1,7 +1,9 @@
|
|||
# MicroPython font handling
|
||||
|
||||
This is an attempt to offer a standard method of creating and deploying fonts
|
||||
to MicroPython display drivers.
|
||||
This repository defines a method of creating and deploying fonts for use with
|
||||
MicroPython display drivers. A PC utility converts industry standard font files
|
||||
to Python sourcecode and a MicroPython module enables these to be rendered to
|
||||
suitable device drivers, notably OLED displays using the SSD1306 chip.
|
||||
|
||||
# Introduction
|
||||
|
||||
|
@ -19,28 +21,28 @@ directory. On import very little RAM is used, yet the data may be accessed
|
|||
fast. Note that the use of frozen bytecode is entirely optional: font files may
|
||||
be imported in the normal way if RAM usage is not an issue.
|
||||
|
||||
It is intended that the resultant file be usable with two varieties of display
|
||||
devices and drivers. These comprise:
|
||||
The resultant file is usable with two varieties of display device drivers:
|
||||
|
||||
1. Drivers using `bytearray` instances as frame buffers, including the
|
||||
official `framebuffer` class.
|
||||
1. Drivers where the display class is subclassed from the official
|
||||
`framebuffer` class.
|
||||
2. Drivers for displays where the frame buffer is implemented in the display
|
||||
device hardware.
|
||||
|
||||
# The proposed solution
|
||||
# Solution
|
||||
|
||||
This consists of three components:
|
||||
This comprises three components:
|
||||
|
||||
1. font_to_py.py This is a utility intended to be run on a PC and converts a
|
||||
1. [font_to_py.py](./FONT_TO_PY.md) This utility runs on a PC and converts a
|
||||
font file to Python source. See below.
|
||||
2. The Writer class (writer.py) This facilitates writing text to a device
|
||||
given a suitably designed device driver. See [here](./DRIVERS.md).
|
||||
3. A device driver specification. This includes an example for rendering text
|
||||
to an SSD1306 device with arbitrary fonts. Also described in the above reference.
|
||||
2. [The Writer class](./writer/WRITER.md) This facilitates rendering text to a
|
||||
device having a suitably designed device driver.
|
||||
3. [Device driver notes](./writer/DRIVERS.md). Notes for authors of display
|
||||
device drivers. Provides details of the font file format and information on
|
||||
ensuring comptibility with the `Writer` classes.
|
||||
|
||||
# font_to_py.py
|
||||
|
||||
This is a command line utility written in Python 3 to be run on a PC. It takes
|
||||
This command line utility is written in Python 3 and runs on a PC. It takes
|
||||
as input a font file in `ttf` or `otf` form together with a height in pixels
|
||||
and outputs a Python source file containing the font data. Fixed and variable
|
||||
pitch rendering are supported. The design has the following aims:
|
||||
|
|
|
@ -1,84 +0,0 @@
|
|||
# driver_test.py Simple test for rendering text to an ssd1306 display in
|
||||
# arbitrary fonts
|
||||
# V0.1 Peter Hinch Nov 2016
|
||||
|
||||
# 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.
|
||||
|
||||
# This demo uses a modified version of the official SSD1306 driver to fix an
|
||||
# issue with the scroll method. Once the official version is fixed, it should
|
||||
# be substituted for ssd1306_drv
|
||||
|
||||
import machine
|
||||
import utime
|
||||
from writer import Writer
|
||||
from ssd1306 import SSD1306_I2C, SSD1306_SPI
|
||||
import freeserif
|
||||
import freesans20
|
||||
import inconsolata16
|
||||
|
||||
# Display parameters
|
||||
WIDTH = const(128)
|
||||
SPI = False
|
||||
# Note that HEIGHT is set below
|
||||
|
||||
if SPI:
|
||||
# Pyb SSD
|
||||
# 3v3 Vin
|
||||
# Gnd Gnd
|
||||
# X1 DC
|
||||
# X2 CS
|
||||
# X3 Rst
|
||||
# X6 CLK
|
||||
# X8 DATA
|
||||
HEIGHT = 32
|
||||
pdc = machine.Pin('X1', machine.Pin.OUT_PP)
|
||||
pcs = machine.Pin('X2', machine.Pin.OUT_PP)
|
||||
prst = machine.Pin('X3', machine.Pin.OUT_PP)
|
||||
spi = machine.SPI(1)
|
||||
display = SSD1306_SPI(WIDTH, HEIGHT, spi, pdc, prst, pcs)
|
||||
else: # I2C
|
||||
# Pyb SSD
|
||||
# 3v3 Vin
|
||||
# Gnd Gnd
|
||||
# Y9 CLK
|
||||
# Y10 DATA
|
||||
HEIGHT = 64
|
||||
pscl = machine.Pin('Y9', machine.Pin.OUT_PP)
|
||||
psda = machine.Pin('Y10', machine.Pin.OUT_PP)
|
||||
i2c = machine.I2C(scl=pscl, sda=psda)
|
||||
display = SSD1306_I2C(WIDTH, HEIGHT, i2c)
|
||||
|
||||
serif = Writer(display, freeserif)
|
||||
sans = Writer(display, freesans20)
|
||||
Writer.set_clip(True, True) # Disable auto scrolling and wrapping.
|
||||
serif.printstring('Tuesday\n')
|
||||
sans.printstring('8 Nov 2016\n')
|
||||
sans.printstring('10.30am')
|
||||
display.show()
|
||||
|
||||
|
||||
def scroll_test(x, y):
|
||||
t = utime.ticks_us()
|
||||
display.scroll(x, y) # 125ms
|
||||
print(utime.ticks_diff(utime.ticks_us(), t))
|
||||
display.show()
|
|
@ -0,0 +1,193 @@
|
|||
# Device Driver Implementation
|
||||
|
||||
Display devices comprise two varieties, depending on whether the hardware
|
||||
includes a frame buffer or whether the frame buffer is located on the
|
||||
controlling system.
|
||||
|
||||
In the latter case the [Writer](./WRITER.md) class extends the capability of
|
||||
the driver to use multiple fonts plus additional functionality.
|
||||
|
||||
Where the buffer is located on the display device, the means of controlling the
|
||||
text insertion point and the means of performing partial buffer updates will be
|
||||
device dependent. If the functionality of the `Writer` class is required it
|
||||
must be implemented at device driver level.
|
||||
|
||||
###### [Main README](../README.md)
|
||||
|
||||
## Drivers for unbuffered displays
|
||||
|
||||
Where the buffer is held on the MicroPython host the driver should be
|
||||
subclassed from the official `framebuf` module. An example of such a driver is
|
||||
the [official SSD1306 driver](https://github.com/micropython/micropython/blob/master/drivers/display/ssd1306.py).
|
||||
In addition the driver class should have bound variables `width` and `height`
|
||||
containing the size of the display in pixels.
|
||||
|
||||
The device driver defines a buffer of the correct size to hold a full frame of
|
||||
data and instantiates the `framebuf.FrameBuffer` superclass to reference it.
|
||||
The `FrameBuffer` mode is selected to match the layout of the target display.
|
||||
The driver implements a `show` method to efficiently copy the buffer contents
|
||||
to the display hardware.
|
||||
|
||||
This design enables the supplied `Writer` and `CWriter` classes to be used for
|
||||
rendering arbitrary fonts to the display. The author of the device driver need
|
||||
not be concerned with the format of Python font files.
|
||||
|
||||
The `Writer` and `CWriter` classes require horizontally mapped fonts. This is
|
||||
regardless of the mapping used in the device driver's `FrameBuffer`: the
|
||||
`Writer.printstring` method deals transparently with any mismatch.
|
||||
|
||||
## Drivers for buffered displays
|
||||
|
||||
Authors of such drivers will need to have an understanding of the font file
|
||||
format.
|
||||
|
||||
### Specifying the font layout
|
||||
|
||||
Each font file has a `get_ch()` function accepting an ASCII character as its
|
||||
argument. It returns a memoryview instance providing access to a bytearray
|
||||
corresponding to the individual glyph. The layout of this data is determined by
|
||||
the command line arguments presented to the `font_to_py.py` utility. It is
|
||||
the responsibility of the driver to copy that data to the physical device.
|
||||
|
||||
The purpose of the `font_to_py.py` command line arguments specified to the
|
||||
user is to ensure that the data layout is optimised for the device so that this
|
||||
copy operation is a fast bytewise copy or SPI/I2C transfer. The driver
|
||||
documentation should therefore specify these arguments to ensure the layout is
|
||||
optimal. Mapping may be horizontal or vertical, and the bit order of individual
|
||||
bytes may be defined. These are detailed below.
|
||||
|
||||
In the case of devices with their own frame buffer the `Writer` class will need
|
||||
to be re-written or adapted to match the hardware's method of tracking such
|
||||
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.
|
||||
|
||||
## 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):
|
||||
|
||||
```python
|
||||
# Code generated by font-to-py.py.
|
||||
# Font: FreeSerif.ttf
|
||||
version = '0.2'
|
||||
|
||||
def height():
|
||||
return 21
|
||||
|
||||
def max_width():
|
||||
return 22
|
||||
|
||||
def hmap():
|
||||
return False
|
||||
|
||||
def reverse():
|
||||
return False
|
||||
|
||||
def monospaced():
|
||||
return False
|
||||
|
||||
def min_ch():
|
||||
return 32
|
||||
|
||||
def max_ch():
|
||||
return 126
|
||||
|
||||
_font =\
|
||||
b'\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x08\x00\xfe\xc7\x00\x7e\xc0\x00\x00\x00\x00\x00'\
|
||||
|
||||
_index =\
|
||||
b'\x00\x00\x14\x00\x2e\x00\x4b\x00\x71\x00\x97\x00\xd2\x00\x0a\x01'\
|
||||
b'\x1b\x01\x35\x01\x4f\x01\x75\x01\x9e\x01\xb2\x01\xcc\x01\xe0\x01'\
|
||||
|
||||
_mvfont = memoryview(_font)
|
||||
# Boilerplate code omitted
|
||||
|
||||
def get_ch(ch):
|
||||
# validate ch, if out of range use '?'
|
||||
# get offsets into _font and retrieve char width
|
||||
# Return: memoryview of bitmap, height and width
|
||||
return mvfont[offset + 2, next_offset], height, width
|
||||
```
|
||||
|
||||
`height` and `width` are specified in bits (pixels).
|
||||
|
||||
In the case of monospaced fonts the `max_width` function returns the width of
|
||||
every character. For variable pitch fonts it returns the width of the widest
|
||||
character. Device drivers can use this to rapidly determine whether a string
|
||||
will fit the available space. If it will fit on the assumption that all chars
|
||||
are maximum width, it can be rendered rapidly without doing a character by
|
||||
character check.
|
||||
|
||||
`get_ch()` returns a memoryview of an individual glyph with its dimensions
|
||||
and contains all the bytes required to render the character including trailing
|
||||
space.
|
||||
|
||||
## 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 blanking and advancing the pixel column
|
||||
by the value returned by `font.max_width()`.
|
||||
|
||||
## Binary font files
|
||||
|
||||
This format is unlikely to find application beyond the e-paper driver. It was
|
||||
designed for micropower applications where the Pyboard has no SD card. Fonts
|
||||
are stored as random access files on power-switched Flash storage or SD card.
|
||||
This method is probably too slow for anything other than e-paper displays.
|
||||
|
||||
The format is as follows. Files are binary 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 (Python and Binary fonts)
|
||||
|
||||
A character occupies a space where (0, 0) represents the coordinates of the top
|
||||
left hand corner of the bitmap. It comprises a set of pixels where increasing x
|
||||
values represent locations to the right of the origin and increasing y values
|
||||
represent downward positions. Mapping defines the relationship between this
|
||||
abstract two dimensional array of bits and the physical linear sequence of bytes.
|
||||
|
||||
Vertical mapping means that the LSB of first byte is pixel (0,0), MSB of first
|
||||
byte is (0, 7). The second byte (assuming the height is greater than 8 pixels)
|
||||
is (0, 8) to (0, 15). Once the column is complete the next byte represents
|
||||
(1, 0) to (1, 7).
|
||||
|
||||
Horizontal mapping means that the MSB of byte 0 is pixel (0,0) with LSB at
|
||||
(7,0), with the second byte covering (8, 0) to (15, 0) if the width is greater
|
||||
than 8.
|
||||
|
||||
Bit reversal provides for the case where the bit order of each byte is reversed
|
||||
i.e. a byte comprising bits [b7b6b5b4b3b2b1b0] becomes [b0b1b2b3b4b5b6b7].
|
||||
|
||||
# Specification and Project Notes
|
||||
|
||||
The design aims primarily to minimise RAM usage. Minimising the size of the
|
||||
bytecode is a secondary aim. Indexed addressing is used to reduce this in
|
||||
the case of proportional fonts, at a small cost in performance. The size of the
|
||||
Python source file is a lesser consideration, with readability being prioritised
|
||||
over size. Hence they are "pretty formatted" with the large bytes objects
|
||||
split over multiple lines for readability.
|
||||
|
||||
Fonts created with the `font_to_py` utility have been extensively tested with
|
||||
each of the mapping options. They are used with drivers for SSD1306 OLEDs,
|
||||
SSD1963 LCD displays, the official LCD160CR and the Digital Artists 2.7 inch
|
||||
e-paper display.
|
|
@ -0,0 +1,290 @@
|
|||
# Writer and Cwriter classes
|
||||
|
||||
These classes facilitate rendering Python font files to displays where the
|
||||
display driver is subclassed from the `framebuf` class. An example is the
|
||||
official [SSD1306 driver](https://github.com/micropython/micropython/blob/master/drivers/display/ssd1306.py).
|
||||
|
||||
Example code and images are for 128*64 SSD1306 OLED displays.
|
||||
|
||||
![Image](images/IMG_2866.JPG)
|
||||
Scrolling text, multiple fonts.
|
||||
|
||||
![Image](images/IMG_2861.JPG)
|
||||
A field containing variable length text with a border.
|
||||
|
||||
![Image](images/rjust.JPG)
|
||||
Right justified text.
|
||||
|
||||
![Image](images/mixed.JPG)
|
||||
Mixed text and graphics.
|
||||
|
||||
![Image](images/fields.JPG)
|
||||
Labels and Fields.
|
||||
|
||||
# Contents
|
||||
|
||||
1. [Introduction](./WRITER.md#1-introduction)
|
||||
1.1 [Hardware](./WRITER.md#11-hardware)
|
||||
1.2 [Files](./WRITER.md#11-files)
|
||||
1.3 [Fonts](./WRITER.md#11-fonts)
|
||||
2. [Writer and CWriter classes](./WRITER.md#2-writer-and-cwriter-classes)
|
||||
2.1 [The Writer class](./WRITER.md#21-the-writer-class) For monochrome displays.
|
||||
2.1.1 [Static Method](./WRITER.md#211-static-method)
|
||||
2.1.2.[Constructor](./WRITER.md#212-constructor)
|
||||
2.1.3 [Methods](./WRITER.md#213-methods)
|
||||
2.2 [The CWriter class](./WRITER.md#22-the-cwriter-class) For colour displays
|
||||
and for upside-down rendering.
|
||||
2.2.1 [Static Method](./WRITER.md#221-static-method)
|
||||
2.2.2 [Constructor](./WRITER.md#222-constructor)
|
||||
2.2.3 [Methods](./WRITER.md#223-methods)
|
||||
3. [The Label and Field classes](./WRITER.md#3-the-label-and-field-classes)
|
||||
3.1 [The Label class](./WRITER.md#31-the-label-class)
|
||||
3.2 [The Field class](./WRITER.md#32-the-field-class)
|
||||
4. [Notes](./WRITER.md#4-notes)
|
||||
|
||||
###### [Main README](../README.md)
|
||||
|
||||
# 1. Introduction
|
||||
|
||||
The original `Writer` class was a proof of concept intended to demonstrate
|
||||
rendering, on an SSD1306 OLED display, fonts created by`font_to_py.py`.
|
||||
|
||||
This update for practical applications has the following features:
|
||||
* Genarality: capable of working with any `framebuf` derived driver.
|
||||
* Multiple display operation.
|
||||
* Text display of fixed and variable pitch fonts with wrapping and vertical
|
||||
scrolling.
|
||||
* Wrap/clip options: clip, character wrap or word wrap.
|
||||
* Tab support.
|
||||
* String metrics to enable right or centre justification.
|
||||
* Inverse (background color on foreground color) display.
|
||||
* Labels: render static text at a fixed location.
|
||||
* Fields - render dynamically changing text to a fixed rectangular region.
|
||||
* Inverted display option.
|
||||
|
||||
## 1.1 Hardware
|
||||
|
||||
Tests and demos assume a 128*64 SSD1306 OLED display connected via I2C or SPI.
|
||||
Wiring is specified in `ssd1306_setup.py`. Edit this to use a different bus or
|
||||
for a non-Pyboard target. At the time of writing the default of software I2C
|
||||
should be used: the official SSD1306 driver is not compatible with hardware I2C
|
||||
(see [Notes](./WRITER.md#4-notes)).
|
||||
|
||||
## 1.2 Files
|
||||
|
||||
1. `writer.py` Supports `Writer` and `CWriter` classes.
|
||||
2. `ssd1306_setup.py` Hardware initialisation for SSD1306. Requires the
|
||||
official [SSD1306 driver](https://github.com/micropython/micropython/blob/master/drivers/display/ssd1306.py).
|
||||
3. `writer_demo.py` Demo using a 128*64 SSD1306 OLED display. Import to see
|
||||
usage information.
|
||||
4. `writer_tests.py` Test/demo scripts. Import to see usage information.
|
||||
5. `writer_minimal.py` A minimal version for highly resource constrained
|
||||
devices.
|
||||
|
||||
Sample fonts:
|
||||
1. `freesans20.py` Variable pitch font file.
|
||||
2. `courier20.py` Fixed pitch font file.
|
||||
3. `font10.py` Smaller variable pitch fonts.
|
||||
4. `font6.py`
|
||||
|
||||
## 1.3 Fonts
|
||||
|
||||
Python font files should be created using `font-to-py.py` using horizontal
|
||||
mapping (`-x` option). The `-r` option is not required. If RAM is critical
|
||||
fonts may be frozen as bytecode reducing the RAM impact of each font to about
|
||||
340 bytes.
|
||||
|
||||
###### [Contents](./WRITER.md#contents)
|
||||
|
||||
# 2. Writer and CWriter classes
|
||||
|
||||
The `Writer` class provides fast rendering to monochrome displays using bit
|
||||
blitting. Most applications will use this class.
|
||||
|
||||
The `CWriter` class is a subclass of `Writer`. It can optionally support color
|
||||
displays. It provides additional functionality in the form of an upside-down
|
||||
display option. Owing to limitations in the `frmebuf.blit` method the
|
||||
`CWriter` class renders glyphs one pixel at a time; rendering is therefore
|
||||
slower than the `Writer` class.
|
||||
|
||||
Multiple screens are supported. On any screen multiple `Writer` or `CWriter`
|
||||
instances may be used, each using a different font. A class variable holds the
|
||||
state of each screen to ensure that the insertion point is managed across
|
||||
multiple instances/fonts.
|
||||
|
||||
###### [Contents](./WRITER.md#contents)
|
||||
|
||||
## 2.1 The Writer class
|
||||
|
||||
This class facilitates rendering characters from Python font files to a device,
|
||||
assuming the device has a driver subclassed from `framebuf`. It supports three
|
||||
ways of handling text which would overflow the display: clipping, character
|
||||
wrapping and simple word wrapping.
|
||||
|
||||
It handles newline and tab characters, black-on-white inversion, and field
|
||||
blanking to enable variable length contents to be updated at a fixed location.
|
||||
|
||||
Typical use with an SSD1306 display and the official driver is as follows:
|
||||
|
||||
```python
|
||||
from ssd1306_setup import WIDTH, HEIGHT, setup
|
||||
from writer import Writer
|
||||
import freesans20 # Font to use
|
||||
|
||||
use_spi=False # Tested with a 128*64 I2C connected SSD1306 display
|
||||
ssd = setup(use_spi) # Instantiate display: must inherit from framebuf
|
||||
# Demo drawing geometric shpes
|
||||
rhs = WIDTH -1
|
||||
ssd.line(rhs - 20, 0, rhs, 20, 1) # Demo underlying framebuf methods
|
||||
square_side = 10
|
||||
ssd.fill_rect(rhs - square_side, 0, square_side, square_side, 1)
|
||||
# Instantiate a writer for a specific font
|
||||
wri = Writer(ssd, freesans20) # verbose = False to suppress console output
|
||||
Writer.set_textpos(ssd, 0, 0) # In case a previous test has altered this
|
||||
wri.printstring('Sunday\n12 Aug 2018\n10.30am')
|
||||
ssd.show()
|
||||
```
|
||||
|
||||
The file `writer_demo.py` illustrates the use of font files with a 128*64
|
||||
SSD1306 OLED display and the official
|
||||
[SSD1306 driver](https://github.com/micropython/micropython/blob/master/drivers/display/ssd1306.py).
|
||||
|
||||
### 2.1.1 Static Method
|
||||
|
||||
The `Writer` class exposes the following static method:
|
||||
|
||||
1. `set_textpos` Args: `device`,`row=None`, `col=None`. The `device` is the
|
||||
display instance. This method determines where on screen subsequent text is to
|
||||
be rendered. The initial value is (0, 0) - the top left corner. Arguments are
|
||||
in pixels with positive values representing down and right respectively. The
|
||||
insertion point defines the top left hand corner of the next character to be
|
||||
output.
|
||||
|
||||
Where `None` is passed, the setting is left unchanged.
|
||||
Return: `row`, `col` current settings.
|
||||
|
||||
The insertion point applies to all `Writer` instances having the same device.
|
||||
The insertion point on a given screen is maintained regardless of the font in
|
||||
use.
|
||||
|
||||
### 2.1.2 Constructor
|
||||
|
||||
This takes the following args:
|
||||
1. `device` The hardware device driver instance for the screen in use.
|
||||
2. `font` A Python font instance.
|
||||
3. `verbose=True` If `True` the constructor emits console printout.
|
||||
|
||||
### 2.1.3 Methods
|
||||
|
||||
1. `printstring` Args: `string`, `invert=False`. Outputs a text string at the
|
||||
current insertion point. Newline and Tab characters are honoured. If `invert`
|
||||
is `True` the text is output as black on white.
|
||||
2. `height` No args. Returns the font height in pixels.
|
||||
3. `stringlen` Arg: `string`. Returns the length of a string in pixels. Used
|
||||
for right or centre justification.
|
||||
4. `set_clip` Args: `row_clip=None`, `col_clip=None`, `wrap=None`. If
|
||||
`row_clip` and/or `col_clip` are `True`, characters will be clipped if they
|
||||
extend beyond the boundaries of the physical display. If `col_clip` is
|
||||
`False` characters will wrap onto the next line. If `row_clip` is `False` the
|
||||
display will, where necessary, scroll up to ensure the line is rendered. If
|
||||
`wrap` is `True` word-wrapping will be performed, assuming words are separated
|
||||
by spaces.
|
||||
If any arg is `None`, that value will be left unchanged.
|
||||
Returns the current values of `row_clip`, `col_clip` and `wrap`.
|
||||
5. `tabsize` Arg `value=None`. If `value` is an integer sets the tab size.
|
||||
Returns the current tab size (initial default is 4). Tabs only work properly
|
||||
with fixed pitch fonts.
|
||||
|
||||
###### [Contents](./WRITER.md#contents)
|
||||
|
||||
## 2.2 The CWriter class
|
||||
|
||||
This extends the `Writer` class by adding support for upside-down and/or color
|
||||
displays.
|
||||
|
||||
### 2.2.1 Static method
|
||||
|
||||
The following static method is added:
|
||||
1. `invert_display` Args `device`, `value=True`. The `device` is the display
|
||||
instance. If `value` is set, causes text to be rendered upside down. The
|
||||
`set_textpos` method should be called to ensure that text is rendered from the
|
||||
bottom right hand corner (viewing the display in its normal orientation).
|
||||
|
||||
If a display is to be run inverted, this method must be called prior to
|
||||
instantiating a `Writer` for this display.
|
||||
|
||||
### 2.2.2 Constructor
|
||||
|
||||
This takes the same args as the `Writer` constructor:
|
||||
1. `device` The hardware device driver instance for the screen in use.
|
||||
2. `font` A Python font instance.
|
||||
3. `verbose=True` If `True` the constructor emits console printout.
|
||||
|
||||
### 2.2.3 Methods
|
||||
|
||||
All methods of the base class are supported. Additional method:
|
||||
1. `setcolor` Args: `fgcolor=None`, `bgcolor=None`. Sets the foreground and
|
||||
background colors. If either is `None` that value is left unchanged. Initial
|
||||
constructor defaults are 1 and 0 for monochrome displays. Returns foreground
|
||||
and background color values.
|
||||
|
||||
The `printstring` method works as per the base class except that the string is
|
||||
rendered in foreground color on background color (or reversed if `invert` is
|
||||
`True`).
|
||||
|
||||
# 3. Label and Field classes
|
||||
|
||||
These support applications where text is to be rendered at specific screen
|
||||
locations. These classes change the text insertion point as required and are
|
||||
therefore not intended for use with the writer's `printstring` method.
|
||||
|
||||
## 3.1 The Label class
|
||||
|
||||
This renders a fixed text string to a defined screen location.
|
||||
|
||||
Constructor args:
|
||||
1. `writer` The `Writer` instance (font and screen) to use.
|
||||
2. `row` Location on screen.
|
||||
3. `col`
|
||||
4. `text` Text to display
|
||||
5. `invert=False` Display in inverted or normal style.
|
||||
|
||||
The constructor displays the string at the required location.
|
||||
|
||||
Method:
|
||||
1. `show` No args. For future use.
|
||||
|
||||
## 3.2 The Field class
|
||||
|
||||
Constructor args:
|
||||
1. `writer` The `Writer` instance (font and screen) to use.
|
||||
2. `row` Location on screen.
|
||||
3. `col`
|
||||
4. `max_text` Defines the longest text string the field must display. Can
|
||||
either be an integer number of pixels or a text string. In the latter case the
|
||||
length of the string in pixels is calculated and stored.
|
||||
5. `border=False` Optional sigle pixel border around text.
|
||||
|
||||
The constructor does not cause anything to be displayed. The location of a
|
||||
field is that of the top left hand corner of its text contents. If a border is
|
||||
drawn, it extends in all directions beyond the text size by two pixels.
|
||||
|
||||
Methods:
|
||||
1. `value` Args `text`, `invert=False`. Causes the text to be displayed in
|
||||
normal or inverted style.
|
||||
2. `show` No args. For future use.
|
||||
|
||||
# 4. Notes
|
||||
|
||||
Possible future enhancements:
|
||||
1. General rendering to a rectangular area. This may be problematic as the
|
||||
`framebuf` scroll method is only capable of scrolling the entire buffer.
|
||||
2. Extend word wrapping to cases where words are separated by tabs or hyphens.
|
||||
3. An asynchronous version.
|
||||
|
||||
As stated above the official SSD1306 drriver is incompatible with hardware I2C
|
||||
and this problem cannot efficiently be fixed. [PR4020](https://github.com/micropython/micropython/pull/4020)
|
||||
proposes an enhncement which will facilitate an improved SSD1306 driver capable
|
||||
of using hard or soft I2C.
|
||||
|
||||
###### [Contents](./WRITER.md#contents)
|
|
@ -0,0 +1,308 @@
|
|||
# Code generated by font-to-py.py.
|
||||
# Font: Courier Prime.ttf
|
||||
version = '0.2'
|
||||
|
||||
def height():
|
||||
return 20
|
||||
|
||||
def max_width():
|
||||
return 14
|
||||
|
||||
def hmap():
|
||||
return True
|
||||
|
||||
def reverse():
|
||||
return False
|
||||
|
||||
def monospaced():
|
||||
return True
|
||||
|
||||
def min_ch():
|
||||
return 32
|
||||
|
||||
def max_ch():
|
||||
return 126
|
||||
|
||||
_font =\
|
||||
b'\x0e\x00\x00\x00\x00\x00\x7c\x00\xfe\x00\xc7\x00\xc3\x00\x03\x00'\
|
||||
b'\x07\x00\x1e\x00\x18\x00\x18\x00\x18\x00\x3c\x00\x3c\x00\x18\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x60\x00\x60\x00\x60\x00'\
|
||||
b'\x60\x00\x60\x00\x60\x00\x60\x00\x60\x00\x00\x00\x60\x00\xf0\x00'\
|
||||
b'\xf0\x00\x60\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00'\
|
||||
b'\x00\x00\x00\x00\xe6\x00\xe6\x00\x66\x00\x66\x00\x66\x00\x66\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x03\x30\x02\x20'\
|
||||
b'\x02\x20\x06\x60\x3f\xf8\x3f\xf8\x0c\xc0\x08\x80\x7f\xf0\xff\xf0'\
|
||||
b'\x19\x80\x11\x00\x33\x00\x33\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x0e\x00\x0c\x00\x0c\x00\x3d\x80\x7f\x80\xcd\x80\xcc\x80'\
|
||||
b'\xec\x00\x7f\x00\x0f\x80\x0c\xc0\xcc\xc0\xcd\xc0\xff\x80\xcf\x00'\
|
||||
b'\x0c\x00\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00'\
|
||||
b'\x00\x00\x38\x00\xfe\x18\xc6\x30\xc6\x60\xfe\xc0\x39\x80\x03\x00'\
|
||||
b'\x06\x70\x1d\xfc\x39\x8c\x71\x8c\x61\xfc\x00\x70\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x1e\x00\x3f\x00'\
|
||||
b'\x63\x00\x63\x00\x60\x00\x30\x00\x31\xc0\x49\xc0\xc7\x00\xc3\x00'\
|
||||
b'\xe3\x00\x7f\xc0\x39\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x0e\x00\x00\x00\x00\x00\x60\x00\x60\x00\x60\x00\x60\x00\x60\x00'\
|
||||
b'\x60\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x04\x00\x0e\x00'\
|
||||
b'\x18\x00\x30\x00\x30\x00\x60\x00\x60\x00\xc0\x00\xc0\x00\xc0\x00'\
|
||||
b'\xc0\x00\xc0\x00\xc0\x00\x60\x00\x60\x00\x30\x00\x38\x00\x1c\x00'\
|
||||
b'\x0e\x00\x04\x00\x0e\x00\x40\x00\xe0\x00\x30\x00\x18\x00\x18\x00'\
|
||||
b'\x0c\x00\x0c\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00'\
|
||||
b'\x0c\x00\x0c\x00\x18\x00\x38\x00\x70\x00\xe0\x00\x80\x00\x0e\x00'\
|
||||
b'\x00\x00\x00\x00\x0c\x00\x0c\x00\x0c\x00\xed\xc0\x7f\x80\x0c\x00'\
|
||||
b'\x1e\x00\x33\x00\x23\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x0c\x00\x0c\x00\x0c\x00\x0c\x00\xff\xc0\xff\xc0\x0c\x00\x0c\x00'\
|
||||
b'\x0c\x00\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x78\x00\x70\x00'\
|
||||
b'\x60\x00\x60\x00\xc0\x00\xc0\x00\x00\x00\x00\x00\x0e\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xc0\xff\xc0'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x60\x00'\
|
||||
b'\xf0\x00\xf0\x00\x60\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x0e\x00\x00\xc0\x01\x80\x01\x80\x03\x00\x03\x00\x02\x00\x06\x00'\
|
||||
b'\x04\x00\x0c\x00\x0c\x00\x18\x00\x18\x00\x30\x00\x30\x00\x20\x00'\
|
||||
b'\x60\x00\x40\x00\xc0\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00'\
|
||||
b'\x1e\x00\x3f\x00\x61\x80\xe1\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0'\
|
||||
b'\xc0\xc0\xe1\xc0\x61\x80\x3f\x00\x1e\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x0c\x00\x7c\x00\xec\x00'\
|
||||
b'\x0c\x00\x0c\x00\x0c\x00\x0c\x00\x0c\x00\x0c\x00\x0c\x00\x0c\x00'\
|
||||
b'\xff\xc0\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00'\
|
||||
b'\x00\x00\x00\x00\x3e\x00\xff\x00\xc3\x80\xc1\x80\x01\x80\x01\x00'\
|
||||
b'\x02\x00\x04\x00\x08\x00\x11\x80\x21\x80\xff\x80\xff\x80\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x3e\x00'\
|
||||
b'\x7f\x00\x61\x80\x61\x80\x01\x80\x1f\x00\x1f\x00\x03\x80\x01\x80'\
|
||||
b'\x01\x80\xc3\x80\xff\x00\x3e\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x0e\x00\x00\x00\x00\x00\x03\x00\x07\x00\x0b\x00\x1b\x00'\
|
||||
b'\x13\x00\x23\x00\x63\x00\xff\xc0\xff\xe0\x03\x00\x03\x00\x0f\xc0'\
|
||||
b'\x0f\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00'\
|
||||
b'\x00\x00\x7f\x80\x7f\x80\x60\x00\x60\x00\x7e\x00\x7f\x00\x63\x80'\
|
||||
b'\x01\x80\x01\x80\x01\x80\xc3\x80\xff\x00\x3c\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x07\x80\x1f\x80'\
|
||||
b'\x3c\x00\x70\x00\x60\x00\xcf\x00\xff\x80\xe1\xc0\xc0\xc0\xc0\xc0'\
|
||||
b'\x61\xc0\x7f\x80\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x0e\x00\x00\x00\x00\x00\xff\x80\xff\x80\xc1\x80\xc1\x00\x03\x00'\
|
||||
b'\x02\x00\x06\x00\x06\x00\x0c\x00\x0c\x00\x08\x00\x18\x00\x10\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00'\
|
||||
b'\x1e\x00\x3f\x00\x61\x80\x61\x80\x73\x80\x3f\x00\x7f\x00\xe3\x80'\
|
||||
b'\xc1\x80\xc1\x80\xe3\x80\x7f\x00\x3e\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x3e\x00\x7f\x80\xe1\x80'\
|
||||
b'\xc0\xc0\xc0\xc0\xe1\xc0\x7f\xc0\x3c\xc0\x01\x80\x03\x80\x0f\x00'\
|
||||
b'\x7e\x00\x78\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x60\x00\xf0\x00\xf0\x00'\
|
||||
b'\x60\x00\x00\x00\x00\x00\x60\x00\xf0\x00\xf0\x00\x60\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x30\x00\x78\x00\x78\x00\x30\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x78\x00\x70\x00\x60\x00\x60\x00\xc0\x00\xc0\x00\x00\x00'\
|
||||
b'\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x60\x01\xe0\x07\x80'\
|
||||
b'\x1e\x00\x78\x00\xe0\x00\x78\x00\x0e\x00\x03\x80\x00\xe0\x00\x40'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\xff\xc0\xff\xc0\x00\x00\x00\x00'\
|
||||
b'\x00\x00\xff\xc0\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x80\x00'\
|
||||
b'\xe0\x00\x38\x00\x0e\x00\x03\xc0\x00\xc0\x03\x80\x0e\x00\x38\x00'\
|
||||
b'\xe0\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x0e\x00\x00\x00\x00\x00\x7c\x00\xfe\x00\xc7\x00\xc3\x00\x03\x00'\
|
||||
b'\x07\x00\x1e\x00\x18\x00\x18\x00\x18\x00\x3c\x00\x3c\x00\x18\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x0f\x80\x1f\xc0\x38\xe0\x66\xf0\x6f\xb0\xcd\x30\xd9\x30'\
|
||||
b'\xd9\x30\xdb\x70\xdf\xe0\x6c\xc0\x70\x00\x3f\xc0\x0f\x80\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x3f\x00\x3f\x00\x07\x80'\
|
||||
b'\x0c\x80\x0c\x80\x18\xc0\x18\x40\x3f\xe0\x3f\xe0\x30\x60\x60\x30'\
|
||||
b'\xf8\xf8\xf8\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00'\
|
||||
b'\x00\x00\x00\x00\xff\x00\xff\xc0\x30\xc0\x30\xc0\x30\xc0\x3f\x80'\
|
||||
b'\x3f\xc0\x30\xe0\x30\x60\x30\x60\x30\xe0\xff\xc0\xff\x80\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x1f\x60'\
|
||||
b'\x3f\xe0\x70\xe0\x60\x60\xc0\x60\xc0\x40\xc0\x00\xc0\x00\xc0\x00'\
|
||||
b'\x60\x00\x70\x60\x3f\xe0\x1f\x80\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x0e\x00\x00\x00\x00\x00\xff\x00\xff\x80\x31\xc0\x30\xe0'\
|
||||
b'\x30\x60\x30\x60\x30\x60\x30\x60\x30\x60\x30\xe0\x31\xc0\xff\x80'\
|
||||
b'\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00'\
|
||||
b'\x00\x00\xff\xe0\xff\xe0\x30\x60\x33\x60\x33\x00\x3f\x00\x3f\x00'\
|
||||
b'\x33\x00\x33\x00\x30\x60\x30\x60\xff\xe0\xff\xe0\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\xff\xe0\xff\xe0'\
|
||||
b'\x30\x60\x33\x60\x33\x00\x3f\x00\x3f\x00\x33\x00\x33\x00\x30\x00'\
|
||||
b'\x30\x00\xfe\x00\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x0e\x00\x00\x00\x00\x00\x1e\xc0\x3f\xc0\x71\xc0\x60\xc0\xc0\xc0'\
|
||||
b'\xc0\x00\xc0\x00\xc7\xf0\xc7\xf0\x60\xc0\x70\xc0\x3f\xc0\x1f\x80'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00'\
|
||||
b'\xfd\xf8\xfd\xf8\x30\x60\x30\x60\x30\x60\x3f\xe0\x3f\xe0\x30\x60'\
|
||||
b'\x30\x60\x30\x60\x30\x60\xfd\xf8\xfd\xf8\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\xff\xc0\xff\xc0\x0c\x00'\
|
||||
b'\x0c\x00\x0c\x00\x0c\x00\x0c\x00\x0c\x00\x0c\x00\x0c\x00\x0c\x00'\
|
||||
b'\xff\xc0\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00'\
|
||||
b'\x00\x00\x00\x00\x3f\xf8\x3f\xf8\x01\x80\x01\x80\x01\x80\x01\x80'\
|
||||
b'\x81\x80\xc1\x80\xc1\x80\xc1\x80\xc3\x80\x7f\x00\x3e\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\xfc\xf0'\
|
||||
b'\xfc\xf0\x30\x40\x31\x80\x33\x00\x34\x00\x3f\x00\x31\x80\x30\x80'\
|
||||
b'\x30\xc0\x30\x40\xfc\x70\xfc\x30\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x0e\x00\x00\x00\x00\x00\x7f\x00\xff\x00\x18\x00\x18\x00'\
|
||||
b'\x18\x00\x18\x00\x18\x00\x18\x30\x18\x30\x18\x30\x18\x30\x7f\xf0'\
|
||||
b'\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00'\
|
||||
b'\x00\x00\xf0\xf0\xf0\xf0\x70\xe0\x79\xe0\x69\x60\x69\x60\x6f\x60'\
|
||||
b'\x66\x60\x66\x60\x66\x60\x60\x60\xf9\xf0\xf9\xf0\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\xf0\xf8\xf8\xf8'\
|
||||
b'\x3c\x30\x34\x30\x32\x30\x32\x30\x31\x30\x31\x30\x30\xb0\x30\x70'\
|
||||
b'\x30\x70\x7c\x30\x7c\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x0e\x00\x00\x00\x00\x00\x1f\x80\x3f\xc0\x70\xe0\x60\x60\xc0\x30'\
|
||||
b'\xc0\x30\xc0\x30\xc0\x30\xc0\x30\x60\x60\x70\xe0\x3f\xc0\x1f\x80'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00'\
|
||||
b'\x7f\xc0\xff\xe0\x18\x70\x18\x30\x18\x30\x18\x70\x1f\xe0\x1f\xc0'\
|
||||
b'\x18\x00\x18\x00\x18\x00\x7f\x00\xff\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x1f\x80\x3f\xc0\x70\xe0'\
|
||||
b'\x60\x60\xc0\x30\xc0\x30\xc0\x30\xc0\x30\xc0\x30\x60\x60\x70\xe0'\
|
||||
b'\x3f\xc0\x0f\x80\x18\x20\x3f\xe0\x3f\xc0\x20\x00\x00\x00\x0e\x00'\
|
||||
b'\x00\x00\x00\x00\xff\x80\xff\xc0\x30\xe0\x30\x60\x30\xe0\x3f\xc0'\
|
||||
b'\x3f\x00\x31\x80\x30\xc0\x30\xc0\x30\x60\xfc\x78\xfc\x38\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x3c\xc0'\
|
||||
b'\x7f\xc0\xe1\xc0\xc0\xc0\xc0\x00\x70\x00\x1f\x00\x01\x80\x00\xc0'\
|
||||
b'\xc0\xc0\xe1\xc0\xff\x80\xdf\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x0e\x00\x00\x00\x00\x00\xff\xc0\xff\xc0\xcc\xc0\xcc\xc0'\
|
||||
b'\xcc\xc0\xcc\xc0\x0c\x00\x0c\x00\x0c\x00\x0c\x00\x0c\x00\x7f\x80'\
|
||||
b'\x7f\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00'\
|
||||
b'\x00\x00\xfc\xfc\xfc\xfc\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30'\
|
||||
b'\x30\x30\x30\x30\x30\x30\x38\x70\x1f\xe0\x0f\xc0\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\xfc\x7c\xfc\x7c'\
|
||||
b'\x30\x30\x30\x30\x10\x20\x18\x60\x18\x40\x0c\xc0\x0c\xc0\x04\x80'\
|
||||
b'\x07\x80\x07\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x0e\x00\x00\x00\x00\x00\xf8\x7c\xf8\x7c\x60\x18\x63\x18\x23\x10'\
|
||||
b'\x23\x90\x37\x90\x37\xb0\x34\xb0\x3c\xf0\x1c\xe0\x18\x60\x18\x60'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00'\
|
||||
b'\xf9\xf0\xf9\xf0\x30\xc0\x19\x80\x1f\x80\x0f\x00\x06\x00\x0f\x00'\
|
||||
b'\x19\x80\x30\xc0\x60\x60\xf9\xf0\xf9\xf0\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\xf9\xf0\xf9\xf0\x30\xc0'\
|
||||
b'\x30\xc0\x19\x80\x0f\x00\x0f\x00\x06\x00\x06\x00\x06\x00\x06\x00'\
|
||||
b'\x3f\xc0\x3f\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00'\
|
||||
b'\x00\x00\x00\x00\xff\xc0\xff\xc0\xc1\x80\xc3\x00\x02\x00\x04\x00'\
|
||||
b'\x0c\x00\x18\x00\x10\xc0\x20\xc0\x40\xc0\xff\xc0\xff\xc0\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\xfc\x00\xfc\x00\xc0\x00'\
|
||||
b'\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00'\
|
||||
b'\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xfc\x00\xfc\x00'\
|
||||
b'\x00\x00\x0e\x00\xc0\x00\x40\x00\x60\x00\x20\x00\x30\x00\x30\x00'\
|
||||
b'\x18\x00\x18\x00\x0c\x00\x0c\x00\x04\x00\x06\x00\x02\x00\x03\x00'\
|
||||
b'\x03\x00\x01\x80\x01\x80\x00\xc0\x00\x00\x00\x00\x0e\x00\xfc\x00'\
|
||||
b'\xfc\x00\x0c\x00\x0c\x00\x0c\x00\x0c\x00\x0c\x00\x0c\x00\x0c\x00'\
|
||||
b'\x0c\x00\x0c\x00\x0c\x00\x0c\x00\x0c\x00\x0c\x00\x0c\x00\x0c\x00'\
|
||||
b'\xfc\x00\xfc\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x18\x00\x18\x00'\
|
||||
b'\x3c\x00\x24\x00\x66\x00\xc6\x00\xc3\x00\x83\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\xff\xfc\xff\xfc\x00\x00\x00\x00\x00\x00\x0e\x00\xe0\x00\xf8\x00'\
|
||||
b'\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x3e\x00\xff\x00\xc1\x80\x3f\x80\x7f\x80\xc1\x80\xc1\x80\xc3\x80'\
|
||||
b'\xff\x80\x7c\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00'\
|
||||
b'\xf0\x00\xf0\x00\x30\x00\x30\x00\x30\x00\x37\xc0\x3f\xe0\x38\x60'\
|
||||
b'\x30\x30\x30\x30\x30\x30\x30\x30\x38\x60\xff\xe0\xf3\xc0\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x1f\x60\x7f\xe0\x70\xe0\xc0\x60\xc0\x00\xc0\x00'\
|
||||
b'\xc0\x00\x70\x60\x7f\xc0\x1f\x80\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x0e\x00\x03\xc0\x03\xc0\x00\xc0\x00\xc0\x00\xc0\x3e\xc0'\
|
||||
b'\x7f\xc0\x61\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\x61\xc0\x7f\xf0'\
|
||||
b'\x3c\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x1f\x00\x7f\x80\x60\xc0\xff\xc0'\
|
||||
b'\xff\xc0\xc0\x00\xc0\x00\x60\xc0\x7f\xc0\x1f\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x0e\x00\x0f\x80\x1f\xc0\x38\x40\x30\x00'\
|
||||
b'\x30\x00\xff\x80\xff\x80\x30\x00\x30\x00\x30\x00\x30\x00\x30\x00'\
|
||||
b'\x30\x00\xff\x80\xff\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1e\x78\x7f\xf8'\
|
||||
b'\x60\xe0\xc0\x60\xc0\x60\xc0\x60\xc0\x60\x60\xe0\x7f\xe0\x1e\x60'\
|
||||
b'\x00\x60\x20\xe0\x3f\xc0\x1f\x80\x00\x00\x0e\x00\xf0\x00\xf0\x00'\
|
||||
b'\x30\x00\x30\x00\x30\x00\x37\xc0\x3f\xe0\x3c\x60\x38\x60\x30\x60'\
|
||||
b'\x30\x60\x30\x60\x30\x60\xfd\xf8\xfd\xf8\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x0e\x00\x0c\x00\x0c\x00\x0c\x00\x00\x00\x00\x00'\
|
||||
b'\x7c\x00\x7c\x00\x0c\x00\x0c\x00\x0c\x00\x0c\x00\x0c\x00\x0c\x00'\
|
||||
b'\xff\xc0\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00'\
|
||||
b'\x03\x00\x03\x00\x03\x00\x00\x00\x00\x00\x7f\x00\x7f\x00\x03\x00'\
|
||||
b'\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00'\
|
||||
b'\xc3\x00\xfe\x00\x3c\x00\x00\x00\x0e\x00\xf0\x00\xf0\x00\x30\x00'\
|
||||
b'\x30\x00\x30\x00\x33\xe0\x33\xe0\x31\x80\x33\x00\x34\x00\x3a\x00'\
|
||||
b'\x31\x80\x30\xc0\xfd\xf0\xfd\xf0\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x0e\x00\x7c\x00\x7c\x00\x0c\x00\x0c\x00\x0c\x00\x0c\x00'\
|
||||
b'\x0c\x00\x0c\x00\x0c\x00\x0c\x00\x0c\x00\x0c\x00\x0c\x00\xff\xc0'\
|
||||
b'\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\xf6\x70\xff\xf8\x3b\x98\x33\x18'\
|
||||
b'\x33\x18\x33\x18\x33\x18\x33\x18\xfb\x9c\xfb\x9c\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\xf3\xc0\xf7\xe0\x38\x60\x38\x60\x30\x60\x30\x60\x30\x60'\
|
||||
b'\x30\x60\xfd\xf8\xfd\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1f\x80\x3f\xc0'\
|
||||
b'\x70\xe0\xc0\x30\xc0\x30\xc0\x30\xc0\x30\x70\xe0\x3f\xc0\x1f\x80'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\xf7\xc0\xff\xe0\x38\x60\x30\x30\x30\x30'\
|
||||
b'\x30\x30\x30\x30\x38\x60\x3f\xe0\x37\xc0\x30\x00\x30\x00\xfc\x00'\
|
||||
b'\xfc\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x3e\xf0\x7f\xf0\x61\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\x61\xc0'\
|
||||
b'\x7f\xc0\x3c\xc0\x00\xc0\x00\xc0\x03\xf0\x03\xf0\x00\x00\x0e\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf1\xc0\xf7\xe0\x3e\x40'\
|
||||
b'\x38\x00\x30\x00\x30\x00\x30\x00\x30\x00\xff\x00\xff\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x7d\x80\xff\x80\xc1\x80\xc0\x80\x7c\x00\x03\x80'\
|
||||
b'\xc0\xc0\xe1\xc0\xff\xc0\xdf\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x0e\x00\x00\x00\x30\x00\x30\x00\x30\x00\x30\x00\xff\x80'\
|
||||
b'\xff\x80\x30\x00\x30\x00\x30\x00\x30\x00\x30\x00\x30\xc0\x1f\xc0'\
|
||||
b'\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\xf1\xe0\xf1\xe0\x30\x60\x30\x60'\
|
||||
b'\x30\x60\x30\x60\x30\xe0\x30\xe0\x3f\xf8\x1e\x78\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\xf8\xf0\xf9\xf0\x20\x60\x30\xc0\x10\xc0\x18\x80\x09\x80'\
|
||||
b'\x0d\x00\x0f\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf8\x3c\xf8\x3c'\
|
||||
b'\x63\x18\x63\x18\x27\x90\x37\xb0\x34\xb0\x1c\xe0\x1c\xe0\x18\x60'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\xf9\xf0\xf9\xf0\x30\xc0\x19\x80\x0f\x00'\
|
||||
b'\x0f\x00\x19\x80\x30\xc0\xf9\xf0\xf9\xf0\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\xf8\xf0\xf9\xf0\x30\x60\x30\xc0\x18\xc0\x19\x80\x0d\x80\x07\x00'\
|
||||
b'\x07\x00\x06\x00\x0c\x00\x1c\x00\x78\x00\x70\x00\x00\x00\x0e\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xc0\xff\x80\xc1\x00'\
|
||||
b'\xc2\x00\x04\x00\x18\x00\x30\xc0\x60\xc0\xff\xc0\xff\xc0\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x06\x00\x0e\x00\x18\x00'\
|
||||
b'\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x38\x00\xf0\x00\xf0\x00'\
|
||||
b'\x38\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x1e\x00\x0e\x00'\
|
||||
b'\x00\x00\x0e\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00'\
|
||||
b'\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00'\
|
||||
b'\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\x00\x00\x0e\x00\xc0\x00'\
|
||||
b'\xe0\x00\x30\x00\x30\x00\x30\x00\x30\x00\x30\x00\x30\x00\x38\x00'\
|
||||
b'\x1e\x00\x1e\x00\x38\x00\x30\x00\x30\x00\x30\x00\x30\x00\x30\x00'\
|
||||
b'\xf0\x00\xe0\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x78\x40\xff\xc0\x87\x80\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
|
||||
_index =\
|
||||
b'\x00\x00\x2a\x00\x54\x00\x7e\x00\xa8\x00\xd2\x00\xfc\x00\x26\x01'\
|
||||
b'\x50\x01\x7a\x01\xa4\x01\xce\x01\xf8\x01\x22\x02\x4c\x02\x76\x02'\
|
||||
b'\xa0\x02\xca\x02\xf4\x02\x1e\x03\x48\x03\x72\x03\x9c\x03\xc6\x03'\
|
||||
b'\xf0\x03\x1a\x04\x44\x04\x6e\x04\x98\x04\xc2\x04\xec\x04\x16\x05'\
|
||||
b'\x40\x05\x6a\x05\x94\x05\xbe\x05\xe8\x05\x12\x06\x3c\x06\x66\x06'\
|
||||
b'\x90\x06\xba\x06\xe4\x06\x0e\x07\x38\x07\x62\x07\x8c\x07\xb6\x07'\
|
||||
b'\xe0\x07\x0a\x08\x34\x08\x5e\x08\x88\x08\xb2\x08\xdc\x08\x06\x09'\
|
||||
b'\x30\x09\x5a\x09\x84\x09\xae\x09\xd8\x09\x02\x0a\x2c\x0a\x56\x0a'\
|
||||
b'\x80\x0a\xaa\x0a\xd4\x0a\xfe\x0a\x28\x0b\x52\x0b\x7c\x0b\xa6\x0b'\
|
||||
b'\xd0\x0b\xfa\x0b\x24\x0c\x4e\x0c\x78\x0c\xa2\x0c\xcc\x0c\xf6\x0c'\
|
||||
b'\x20\x0d\x4a\x0d\x74\x0d\x9e\x0d\xc8\x0d\xf2\x0d\x1c\x0e\x46\x0e'\
|
||||
b'\x70\x0e\x9a\x0e\xc4\x0e\xee\x0e\x18\x0f\x42\x0f\x6c\x0f\x96\x0f'\
|
||||
b'\xc0\x0f'
|
||||
|
||||
_mvfont = memoryview(_font)
|
||||
|
||||
def _chr_addr(ordch):
|
||||
offset = 2 * (ordch - 32)
|
||||
return int.from_bytes(_index[offset:offset + 2], 'little')
|
||||
|
||||
def get_ch(ch):
|
||||
ordch = ord(ch)
|
||||
ordch = ordch + 1 if ordch >= 32 and ordch <= 126 else 32
|
||||
offset = _chr_addr(ordch)
|
||||
width = int.from_bytes(_font[offset:offset + 2], 'little')
|
||||
next_offs = _chr_addr(ordch +1)
|
||||
return _mvfont[offset + 2:next_offs], 20, width
|
||||
|
|
@ -0,0 +1,229 @@
|
|||
# Code generated by font-to-py.py.
|
||||
# Font: FreeSans.ttf
|
||||
version = '0.1'
|
||||
|
||||
def height():
|
||||
return 17
|
||||
|
||||
def max_width():
|
||||
return 17
|
||||
|
||||
def hmap():
|
||||
return True
|
||||
|
||||
def reverse():
|
||||
return False
|
||||
|
||||
def monospaced():
|
||||
return False
|
||||
|
||||
_font =\
|
||||
b'\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x06\x00\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\x80'\
|
||||
b'\x00\xc0\x00\x00\x00\x00\x06\x00\x00\xf0\xf0\xf0\xa0\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x09\x00\x00\x00\x00\x00\x19'\
|
||||
b'\x00\x19\x00\x13\x00\x7f\x80\x12\x00\x32\x00\x32\x00\xff\x80\x26'\
|
||||
b'\x00\x24\x00\x64\x00\x00\x00\x00\x00\x00\x00\x00\x00\x09\x00\x10'\
|
||||
b'\x00\x3c\x00\x56\x00\xd3\x00\xd3\x00\xd0\x00\xd0\x00\x3c\x00\x17'\
|
||||
b'\x00\x13\x00\xd3\x00\xd6\x00\x7c\x00\x10\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x0f\x00\x00\x00\x78\x20\xcc\x40\xcc\x80\xcc\x80\xc9\x00\x31'\
|
||||
b'\x00\x02\x78\x04\xcc\x04\xcc\x08\xcc\x08\xcc\x10\x78\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x0b\x00\x00\x00\x1e\x00\x33\x00\x33\x00\x33'\
|
||||
b'\x00\x1e\x00\x18\x00\x74\xc0\xe6\xc0\xc3\x80\xc1\x80\xe3\x80\x3c'\
|
||||
b'\x40\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\xc0\xc0\xc0\x80'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x10\x20'\
|
||||
b'\x20\x60\x40\xc0\xc0\xc0\xc0\xc0\xc0\x40\x60\x20\x30\x10\x00\x06'\
|
||||
b'\x00\x80\xc0\x40\x60\x20\x30\x30\x30\x30\x30\x30\x20\x60\x40\xc0'\
|
||||
b'\x80\x00\x07\x00\x20\xa8\x70\x50\x50\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x30\x00\x30\x00\x30\x00\xfc\x00\x30\x00\x30\x00\x30'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\xc0\x40\x40\x80\x00\x06\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x04'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x00\x00'\
|
||||
b'\x00\x00\x05\x00\x08\x08\x10\x10\x10\x20\x20\x20\x40\x40\x40\x80'\
|
||||
b'\x80\x00\x00\x00\x00\x09\x00\x00\x00\x3c\x00\x66\x00\x42\x00\xc3'\
|
||||
b'\x00\xc3\x00\xc3\x00\xc3\x00\xc3\x00\xc3\x00\x42\x00\x66\x00\x3c'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x09\x00\x00\x00\x10\x00\x30'\
|
||||
b'\x00\xf0\x00\x30\x00\x30\x00\x30\x00\x30\x00\x30\x00\x30\x00\x30'\
|
||||
b'\x00\x30\x00\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x09\x00\x00'\
|
||||
b'\x00\x3c\x00\x66\x00\xc3\x00\xc3\x00\x03\x00\x06\x00\x0c\x00\x38'\
|
||||
b'\x00\x60\x00\x40\x00\xc0\x00\xff\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x09\x00\x00\x00\x7c\x00\xe7\x00\xc3\x00\x03\x00\x02\x00\x1c'\
|
||||
b'\x00\x07\x00\x03\x00\x03\x00\xc3\x00\xe6\x00\x3c\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x09\x00\x00\x00\x0c\x00\x0c\x00\x1c\x00\x2c'\
|
||||
b'\x00\x2c\x00\x4c\x00\x8c\x00\x8c\x00\xfe\x00\x0c\x00\x0c\x00\x0c'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x09\x00\x00\x00\x7e\x00\x40'\
|
||||
b'\x00\x40\x00\x80\x00\xbc\x00\xe6\x00\x03\x00\x03\x00\x03\x00\xc3'\
|
||||
b'\x00\x66\x00\x3c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x09\x00\x00'\
|
||||
b'\x00\x3c\x00\x66\x00\x43\x00\xc0\x00\xc0\x00\xfc\x00\xe6\x00\xc3'\
|
||||
b'\x00\xc3\x00\xc3\x00\x66\x00\x3c\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x09\x00\x00\x00\xff\x00\x03\x00\x02\x00\x06\x00\x04\x00\x0c'\
|
||||
b'\x00\x08\x00\x18\x00\x18\x00\x10\x00\x30\x00\x30\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x09\x00\x00\x00\x3c\x00\x66\x00\xc3\x00\xc3'\
|
||||
b'\x00\x66\x00\x3c\x00\x66\x00\xc3\x00\xc3\x00\xc3\x00\x66\x00\x3c'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x09\x00\x00\x00\x3c\x00\x66'\
|
||||
b'\x00\xc3\x00\xc3\x00\xc3\x00\x67\x00\x3b\x00\x03\x00\x03\x00\xc2'\
|
||||
b'\x00\x66\x00\x3c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00'\
|
||||
b'\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x00\x00\xc0\x00\x00\x00\x00'\
|
||||
b'\x04\x00\x00\x00\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x00\xc0\x40'\
|
||||
b'\x40\x80\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03'\
|
||||
b'\x00\x0e\x00\x38\x00\xc0\x00\xe0\x00\x38\x00\x07\x00\x01\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\xff\x00\x00\x00\x00\x00\xff\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\xc0\x00\x70\x00\x1c\x00\x03\x00\x07'\
|
||||
b'\x00\x1c\x00\xe0\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x09'\
|
||||
b'\x00\x3c\x00\xc7\x00\xc3\x00\x03\x00\x03\x00\x06\x00\x0c\x00\x08'\
|
||||
b'\x00\x18\x00\x18\x00\x00\x00\x00\x00\x18\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x11\x00\x07\xe0\x00\x0c\x38\x00\x30\x0c\x00\x20\x06'\
|
||||
b'\x00\x63\xb7\x00\x4c\x73\x00\xcc\x63\x00\xd8\x63\x00\xd8\x63\x00'\
|
||||
b'\xd8\x46\x00\xdc\xce\x00\x6f\x78\x00\x30\x00\x00\x18\x00\x00\x0f'\
|
||||
b'\xe0\x00\x00\x00\x00\x00\x00\x00\x0b\x00\x06\x00\x0e\x00\x0b\x00'\
|
||||
b'\x1b\x00\x1b\x00\x11\x80\x31\x80\x31\x80\x3f\xc0\x60\xc0\x60\x40'\
|
||||
b'\x40\x60\xc0\x60\x00\x00\x00\x00\x00\x00\x00\x00\x0b\x00\xfe\x00'\
|
||||
b'\xc3\x80\xc1\x80\xc1\x80\xc1\x80\xc3\x00\xfe\x00\xc1\x80\xc0\xc0'\
|
||||
b'\xc0\xc0\xc0\xc0\xc1\x80\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x0c\x00\x1f\x80\x30\xc0\x60\x60\x40\x60\xc0\x00\xc0\x00\xc0\x00'\
|
||||
b'\xc0\x00\xc0\x00\x40\x60\x60\x60\x30\xc0\x1f\x80\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x0c\x00\xff\x00\xc1\x80\xc0\xc0\xc0\x60\xc0\x60'\
|
||||
b'\xc0\x60\xc0\x60\xc0\x60\xc0\x60\xc0\x60\xc0\xc0\xc1\x80\xff\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x0b\x00\xff\x00\xc0\x00\xc0\x00'\
|
||||
b'\xc0\x00\xc0\x00\xc0\x00\xff\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00'\
|
||||
b'\xc0\x00\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x00\xff\x00'\
|
||||
b'\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xfe\x00\xc0\x00\xc0\x00'\
|
||||
b'\xc0\x00\xc0\x00\xc0\x00\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x0d\x00\x0f\xc0\x30\x60\x60\x30\x60\x00\xc0\x00\xc0\x00\xc1\xf0'\
|
||||
b'\xc0\x30\xc0\x30\x60\x30\x60\x70\x30\xf0\x0f\x10\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x0c\x00\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0'\
|
||||
b'\xc0\xc0\xff\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\xc0\xc0\xc0\xc0\xc0\xc0'\
|
||||
b'\xc0\xc0\xc0\xc0\xc0\xc0\xc0\x00\x00\x00\x00\x09\x00\x06\x00\x06'\
|
||||
b'\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\xc6'\
|
||||
b'\x00\xc6\x00\xc4\x00\x78\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0b'\
|
||||
b'\x00\xc0\xc0\xc1\x80\xc3\x00\xc6\x00\xcc\x00\xd8\x00\xfc\x00\xe6'\
|
||||
b'\x00\xc6\x00\xc3\x00\xc1\x80\xc1\x80\xc0\xc0\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x0a\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0'\
|
||||
b'\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xfe\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x0e\x00\xe0\x38\xe0\x38\xf0\x78\xf0'\
|
||||
b'\x78\xd0\x58\xd8\xd8\xd8\xd8\xc8\x98\xcd\x98\xcd\x98\xc5\x18\xc7'\
|
||||
b'\x18\xc7\x18\x00\x00\x00\x00\x00\x00\x00\x00\x0c\x00\xe0\x60\xe0'\
|
||||
b'\x60\xf0\x60\xd0\x60\xd8\x60\xcc\x60\xc4\x60\xc6\x60\xc3\x60\xc3'\
|
||||
b'\x60\xc1\xe0\xc0\xe0\xc0\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x0d'\
|
||||
b'\x00\x1f\x80\x30\xc0\x60\x60\xe0\x60\xc0\x30\xc0\x30\xc0\x30\xc0'\
|
||||
b'\x30\xc0\x30\xe0\x60\x60\x60\x30\xc0\x1f\x80\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x0b\x00\xff\x00\xc1\x80\xc0\xc0\xc0\xc0\xc0\xc0\xc1'\
|
||||
b'\x80\xff\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x0d\x00\x1f\x80\x30\xc0\x60\x60\xe0'\
|
||||
b'\x60\xc0\x30\xc0\x30\xc0\x30\xc0\x30\xc0\x30\xe1\x60\x61\xe0\x30'\
|
||||
b'\xc0\x1f\xe0\x00\x20\x00\x00\x00\x00\x00\x00\x0c\x00\xff\x00\xc1'\
|
||||
b'\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc1\x80\xff\x00\xc1\xc0\xc0\xc0\xc0'\
|
||||
b'\xc0\xc0\xc0\xc0\xc0\xc0\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x0b'\
|
||||
b'\x00\x3f\x00\x61\x80\xc0\xc0\xc0\x00\xc0\x00\x60\x00\x3e\x00\x07'\
|
||||
b'\x80\x01\xc0\xc0\xc0\xc0\xc0\x61\x80\x3f\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x0b\x00\xff\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18'\
|
||||
b'\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x0c\x00\xc0\xc0\xc0\xc0\xc0\xc0\xc0'\
|
||||
b'\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\x61'\
|
||||
b'\x80\x3f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0b\x00\xc0\x60\x40'\
|
||||
b'\x40\x60\xc0\x60\xc0\x20\x80\x31\x80\x31\x80\x11\x00\x1b\x00\x0b'\
|
||||
b'\x00\x0a\x00\x0e\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10'\
|
||||
b'\x00\xc1\x83\xc1\x82\x42\x86\x62\xc6\x62\xc6\x62\x44\x24\x44\x24'\
|
||||
b'\x6c\x34\x2c\x3c\x28\x18\x38\x18\x38\x18\x18\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x0b\x00\x60\x40\x20\xc0\x31\x80\x19\x00\x1b\x00\x0e'\
|
||||
b'\x00\x06\x00\x0e\x00\x1b\x00\x11\x80\x31\x80\x60\xc0\x40\x60\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x0c\x00\x40\x60\x60\x60\x30\xc0\x30'\
|
||||
b'\xc0\x19\x80\x0d\x00\x0f\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06'\
|
||||
b'\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x00\xff\x80\x01'\
|
||||
b'\x80\x03\x00\x06\x00\x06\x00\x0c\x00\x18\x00\x18\x00\x30\x00\x60'\
|
||||
b'\x00\x60\x00\xc0\x00\xff\x80\x00\x00\x00\x00\x00\x00\x00\x00\x05'\
|
||||
b'\x00\xe0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0'\
|
||||
b'\xc0\xe0\x05\x00\x80\x80\x40\x40\x40\x20\x20\x20\x10\x10\x10\x08'\
|
||||
b'\x08\x00\x00\x00\x00\x05\x00\xe0\x60\x60\x60\x60\x60\x60\x60\x60'\
|
||||
b'\x60\x60\x60\x60\x60\x60\x60\xe0\x08\x00\x00\x30\x30\x78\x48\x48'\
|
||||
b'\x84\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x00\x00\x04'\
|
||||
b'\x00\xc0\x40\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7c\x00\xc6\x00'\
|
||||
b'\x06\x00\x06\x00\x7e\x00\xc6\x00\xc6\x00\xce\x00\x77\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x09\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00'\
|
||||
b'\xde\x00\xe3\x00\xc1\x80\xc1\x80\xc1\x80\xc1\x80\xc1\x80\xe3\x00'\
|
||||
b'\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x09\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x3c\x00\x66\x00\xc3\x00\xc0\x00\xc0\x00\xc0\x00'\
|
||||
b'\xc3\x00\x66\x00\x3c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x00'\
|
||||
b'\x03\x00\x03\x00\x03\x00\x03\x00\x3b\x00\x67\x00\xc3\x00\xc3\x00'\
|
||||
b'\xc3\x00\xc3\x00\xc3\x00\x67\x00\x3b\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3c\x00\x66\x00'\
|
||||
b'\xc3\x00\xc3\x00\xff\x00\xc0\x00\xc3\x00\x66\x00\x3c\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x05\x00\x30\x60\x60\x60\xf0\x60\x60\x60'\
|
||||
b'\x60\x60\x60\x60\x60\x00\x00\x00\x00\x09\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x3b\x00\x67\x00\xc3\x00\xc3\x00\xc3\x00\xc3\x00\xc3'\
|
||||
b'\x00\x67\x00\x3b\x00\x03\x00\x03\x00\xc6\x00\x7c\x00\x09\x00\xc0'\
|
||||
b'\x00\xc0\x00\xc0\x00\xc0\x00\xde\x00\xe3\x00\xc3\x00\xc3\x00\xc3'\
|
||||
b'\x00\xc3\x00\xc3\x00\xc3\x00\xc3\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x04\x00\xc0\x00\x00\x00\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0'\
|
||||
b'\x00\x00\x00\x00\x04\x00\x60\x00\x00\x00\x60\x60\x60\x60\x60\x60'\
|
||||
b'\x60\x60\x60\x60\x60\x60\xc0\x09\x00\xc0\x00\xc0\x00\xc0\x00\xc0'\
|
||||
b'\x00\xc6\x00\xcc\x00\xd8\x00\xf8\x00\xe8\x00\xcc\x00\xc6\x00\xc6'\
|
||||
b'\x00\xc3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\xc0\xc0\xc0'\
|
||||
b'\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\x00\x00\x00\x00\x0e\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\xdd\xe0\xe7\x30\xc6\x30\xc6\x30'\
|
||||
b'\xc6\x30\xc6\x30\xc6\x30\xc6\x30\xc6\x30\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\xde\x00\xe3\x00'\
|
||||
b'\xc3\x00\xc3\x00\xc3\x00\xc3\x00\xc3\x00\xc3\x00\xc3\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x3c\x00\x66\x00\xc3\x00\xc3\x00\xc3\x00\xc3\x00\xc3\x00\x66\x00'\
|
||||
b'\x3c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x09\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\xde\x00\xe3\x00\xc1\x80\xc1\x80\xc1\x80\xc1\x80'\
|
||||
b'\xc1\x80\xe3\x00\xde\x00\xc0\x00\xc0\x00\xc0\x00\x00\x00\x0a\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x3b\x00\x67\x00\xc3\x00\xc3\x00'\
|
||||
b'\xc3\x00\xc3\x00\xc3\x00\x67\x00\x3b\x00\x03\x00\x03\x00\x03\x00'\
|
||||
b'\x00\x00\x06\x00\x00\x00\x00\x00\xd8\xe0\xc0\xc0\xc0\xc0\xc0\xc0'\
|
||||
b'\xc0\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x7c\xc6\xc0\xc0\x70'\
|
||||
b'\x0e\xc6\xc6\x7c\x00\x00\x00\x00\x05\x00\x00\x00\x60\x60\xf0\x60'\
|
||||
b'\x60\x60\x60\x60\x60\x60\x70\x00\x00\x00\x00\x09\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\xc3\x00\xc3\x00\xc3\x00\xc3\x00\xc3\x00\xc3'\
|
||||
b'\x00\xc3\x00\xc7\x00\x7b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08'\
|
||||
b'\x00\x00\x00\x00\x00\xc3\x43\x62\x66\x26\x34\x3c\x18\x18\x00\x00'\
|
||||
b'\x00\x00\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc6\x30\x46\x30'\
|
||||
b'\x47\x20\x6f\x20\x69\x60\x29\x60\x29\xc0\x39\xc0\x10\xc0\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x42\x66\x34\x18'\
|
||||
b'\x18\x1c\x24\x66\x43\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\xc3'\
|
||||
b'\x42\x42\x66\x24\x24\x3c\x18\x18\x18\x10\x30\x60\x08\x00\x00\x00'\
|
||||
b'\x00\x00\xfe\x0c\x08\x18\x30\x60\x40\xc0\xfe\x00\x00\x00\x00\x06'\
|
||||
b'\x00\x30\x60\x60\x60\x60\x60\x60\xe0\xc0\xe0\x60\x60\x60\x60\x60'\
|
||||
b'\x60\x30\x04\x00\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0'\
|
||||
b'\xc0\xc0\xc0\xc0\x00\x06\x00\xc0\x60\x60\x60\x60\x60\x60\x70\x30'\
|
||||
b'\x70\x60\x60\x60\x60\x60\x60\xc0\x09\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x62\x00\x9e\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||
|
||||
_index =\
|
||||
b'\x00\x00\x13\x00\x26\x00\x39\x00\x5d\x00\x81\x00\xa5\x00\xc9\x00'\
|
||||
b'\xdc\x00\xef\x00\x02\x01\x15\x01\x39\x01\x4c\x01\x5f\x01\x72\x01'\
|
||||
b'\x85\x01\xa9\x01\xcd\x01\xf1\x01\x15\x02\x39\x02\x5d\x02\x81\x02'\
|
||||
b'\xa5\x02\xc9\x02\xed\x02\x00\x03\x13\x03\x37\x03\x5b\x03\x7f\x03'\
|
||||
b'\xa3\x03\xd8\x03\xfc\x03\x20\x04\x44\x04\x68\x04\x8c\x04\xb0\x04'\
|
||||
b'\xd4\x04\xf8\x04\x0b\x05\x2f\x05\x53\x05\x77\x05\x9b\x05\xbf\x05'\
|
||||
b'\xe3\x05\x07\x06\x2b\x06\x4f\x06\x73\x06\x97\x06\xbb\x06\xdf\x06'\
|
||||
b'\x03\x07\x27\x07\x4b\x07\x6f\x07\x82\x07\x95\x07\xa8\x07\xbb\x07'\
|
||||
b'\xdf\x07\xf2\x07\x16\x08\x3a\x08\x5e\x08\x82\x08\xa6\x08\xb9\x08'\
|
||||
b'\xdd\x08\x01\x09\x14\x09\x27\x09\x4b\x09\x5e\x09\x82\x09\xa6\x09'\
|
||||
b'\xca\x09\xee\x09\x12\x0a\x25\x0a\x38\x0a\x4b\x0a\x6f\x0a\x82\x0a'\
|
||||
b'\xa6\x0a\xb9\x0a\xcc\x0a\xdf\x0a\xf2\x0a\x05\x0b\x18\x0b\x3c\x0b'\
|
||||
|
||||
_mvfont = memoryview(_font)
|
||||
|
||||
def _chr_addr(ordch):
|
||||
offset = 2 * (ordch - 32)
|
||||
return int.from_bytes(_index[offset:offset + 2], 'little')
|
||||
|
||||
def get_ch(ch):
|
||||
ordch = ord(ch)
|
||||
ordch = ordch if ordch >= 32 and ordch <= 126 else ord('?')
|
||||
offset = _chr_addr(ordch)
|
||||
width = int.from_bytes(_font[offset:offset + 2], 'little')
|
||||
next_offs = _chr_addr(ordch +1)
|
||||
return _mvfont[offset + 2:next_offs], 17, width
|
||||
|
|
@ -0,0 +1,176 @@
|
|||
# Code generated by font-to-py.py.
|
||||
# Font: FreeSans.ttf
|
||||
version = '0.2'
|
||||
|
||||
def height():
|
||||
return 14
|
||||
|
||||
def max_width():
|
||||
return 14
|
||||
|
||||
def hmap():
|
||||
return True
|
||||
|
||||
def reverse():
|
||||
return False
|
||||
|
||||
def monospaced():
|
||||
return False
|
||||
|
||||
def min_ch():
|
||||
return 32
|
||||
|
||||
def max_ch():
|
||||
return 126
|
||||
|
||||
_font =\
|
||||
b'\x08\x00\x00\x78\x8c\x84\x04\x18\x30\x20\x20\x00\x20\x00\x00\x00'\
|
||||
b'\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x05\x00\x00\x80\x80\x80\x80\x80\x80\x80\x80\x00\x80\x00\x00\x00'\
|
||||
b'\x05\x00\x00\xa0\xa0\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x08\x00\x00\x00\x12\x14\x7f\x24\x24\xfe\x28\x48\x48\x00\x00\x00'\
|
||||
b'\x08\x00\x20\x78\xac\xa4\xa0\xa0\x78\x2c\xa4\xac\x78\x20\x00\x00'\
|
||||
b'\x0c\x00\x00\x00\x70\x80\x89\x00\x89\x00\x8a\x00\x72\x00\x04\xe0'\
|
||||
b'\x05\x10\x09\x10\x09\x10\x10\xe0\x00\x00\x00\x00\x00\x00\x09\x00'\
|
||||
b'\x00\x00\x30\x00\x48\x00\x48\x00\x78\x00\x20\x00\x52\x00\x9e\x00'\
|
||||
b'\x8c\x00\x8e\x00\x73\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x80'\
|
||||
b'\x80\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x20'\
|
||||
b'\x40\x40\x80\x80\x80\x80\x80\x80\x80\x40\x40\x20\x05\x00\x00\x80'\
|
||||
b'\x40\x40\x20\x20\x20\x20\x20\x20\x20\x40\x40\x80\x05\x00\x00\x20'\
|
||||
b'\xf8\x20\x50\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x20\x20\xf8\x20\x20\x20\x00\x00\x00\x04\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x80\x80\x80\x00\x05\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x04\x00\x00\x10'\
|
||||
b'\x10\x20\x20\x20\x40\x40\x40\x80\x80\x00\x00\x00\x08\x00\x00\x78'\
|
||||
b'\x48\x84\x84\x84\x84\x84\x84\x48\x78\x00\x00\x00\x08\x00\x00\x20'\
|
||||
b'\x60\xe0\x20\x20\x20\x20\x20\x20\x20\x00\x00\x00\x08\x00\x00\x78'\
|
||||
b'\xcc\x84\x04\x0c\x18\x60\x40\x80\xfc\x00\x00\x00\x08\x00\x00\x78'\
|
||||
b'\xc4\x84\x04\x38\x04\x04\x84\xcc\x78\x00\x00\x00\x08\x00\x00\x08'\
|
||||
b'\x18\x38\x28\x48\x88\xfc\x08\x08\x08\x00\x00\x00\x08\x00\x00\x7c'\
|
||||
b'\x80\x80\xb8\xcc\x04\x04\x04\x88\x78\x00\x00\x00\x08\x00\x00\x38'\
|
||||
b'\x48\x84\x80\xf8\xcc\x84\x84\x4c\x78\x00\x00\x00\x08\x00\x00\xfc'\
|
||||
b'\x0c\x08\x10\x10\x20\x20\x20\x40\x40\x00\x00\x00\x08\x00\x00\x78'\
|
||||
b'\x84\x84\x84\x78\xcc\x84\x84\xcc\x78\x00\x00\x00\x08\x00\x00\x78'\
|
||||
b'\xc8\x84\x84\xcc\x74\x04\x04\x88\x70\x00\x00\x00\x04\x00\x00\x00'\
|
||||
b'\x00\x80\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x04\x00\x00\x00'\
|
||||
b'\x00\x00\x80\x00\x00\x00\x00\x00\x80\x80\x80\x00\x08\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x1c\x70\x80\x60\x1c\x04\x00\x00\x00\x08\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\xfc\x00\xfc\x00\x00\x00\x00\x00\x08\x00\x00\x00'\
|
||||
b'\x00\x00\x00\xe0\x38\x06\x1c\x60\x80\x00\x00\x00\x08\x00\x00\x78'\
|
||||
b'\x8c\x84\x04\x18\x30\x20\x20\x00\x20\x00\x00\x00\x0e\x00\x00\x00'\
|
||||
b'\x07\xc0\x18\x60\x20\x10\x43\x48\x84\xc8\x88\xc8\x88\x88\x89\x90'\
|
||||
b'\xc6\xe0\x60\x00\x30\x00\x0f\xc0\x00\x00\x09\x00\x00\x00\x0c\x00'\
|
||||
b'\x1c\x00\x14\x00\x16\x00\x32\x00\x22\x00\x7f\x00\x41\x00\x41\x80'\
|
||||
b'\xc1\x80\x00\x00\x00\x00\x00\x00\x09\x00\x00\x00\xfc\x00\x82\x00'\
|
||||
b'\x82\x00\x82\x00\xfc\x00\x86\x00\x82\x00\x82\x00\x86\x00\xfc\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x3c\x00\x42\x00\x41\x00'\
|
||||
b'\x80\x00\x80\x00\x80\x00\x81\x00\xc1\x00\x62\x00\x3c\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x0a\x00\x00\x00\xfc\x00\x82\x00\x83\x00\x81\x00'\
|
||||
b'\x81\x00\x81\x00\x81\x00\x83\x00\x82\x00\xfc\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x09\x00\x00\x00\xfe\x00\x80\x00\x80\x00\x80\x00\xfc\x00'\
|
||||
b'\x80\x00\x80\x00\x80\x00\x80\x00\xfe\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x08\x00\x00\xfc\x80\x80\x80\xfc\x80\x80\x80\x80\x80\x00\x00\x00'\
|
||||
b'\x0b\x00\x00\x00\x1e\x00\x61\x00\x40\x80\x80\x00\x80\x00\x87\x80'\
|
||||
b'\x80\x80\xc0\x80\x61\x80\x3e\x80\x00\x00\x00\x00\x00\x00\x0a\x00'\
|
||||
b'\x00\x00\x81\x00\x81\x00\x81\x00\x81\x00\xff\x00\x81\x00\x81\x00'\
|
||||
b'\x81\x00\x81\x00\x81\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x80'\
|
||||
b'\x80\x80\x80\x80\x80\x80\x80\x80\x80\x00\x00\x00\x07\x00\x00\x04'\
|
||||
b'\x04\x04\x04\x04\x04\x04\x84\x84\x78\x00\x00\x00\x09\x00\x00\x00'\
|
||||
b'\x82\x00\x84\x00\x88\x00\x90\x00\xb0\x00\xd8\x00\x88\x00\x84\x00'\
|
||||
b'\x86\x00\x82\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x80\x80\x80'\
|
||||
b'\x80\x80\x80\x80\x80\x80\xfc\x00\x00\x00\x0c\x00\x00\x00\xc1\x80'\
|
||||
b'\xc1\x80\xc1\x80\xa2\x80\xa2\x80\xa2\x80\x94\x80\x94\x80\x94\x80'\
|
||||
b'\x88\x80\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\xc1\x00\xc1\x00'\
|
||||
b'\xe1\x00\xb1\x00\x91\x00\x89\x00\x8d\x00\x87\x00\x83\x00\x83\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x0b\x00\x00\x00\x3e\x00\x63\x00\xc1\x00'\
|
||||
b'\x80\x80\x80\x80\x80\x80\x80\x80\xc1\x00\x63\x00\x3e\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x09\x00\x00\x00\xfc\x00\x86\x00\x82\x00\x82\x00'\
|
||||
b'\x86\x00\xfc\x00\x80\x00\x80\x00\x80\x00\x80\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x0b\x00\x00\x00\x3e\x00\x63\x00\xc1\x00\x80\x80\x80\x80'\
|
||||
b'\x80\x80\x80\x80\xc5\x80\x63\x00\x3f\x00\x00\x80\x00\x00\x00\x00'\
|
||||
b'\x0a\x00\x00\x00\xfc\x00\x82\x00\x82\x00\x82\x00\x82\x00\xfc\x00'\
|
||||
b'\x82\x00\x82\x00\x82\x00\x83\x00\x00\x00\x00\x00\x00\x00\x09\x00'\
|
||||
b'\x00\x00\x7c\x00\xc6\x00\x82\x00\xc0\x00\x78\x00\x0e\x00\x02\x00'\
|
||||
b'\x82\x00\xc6\x00\x7c\x00\x00\x00\x00\x00\x00\x00\x09\x00\x00\x00'\
|
||||
b'\xfe\x00\x10\x00\x10\x00\x10\x00\x10\x00\x10\x00\x10\x00\x10\x00'\
|
||||
b'\x10\x00\x10\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x81\x00'\
|
||||
b'\x81\x00\x81\x00\x81\x00\x81\x00\x81\x00\x81\x00\x81\x00\xc3\x00'\
|
||||
b'\x3c\x00\x00\x00\x00\x00\x00\x00\x09\x00\x00\x00\xc1\x80\x41\x00'\
|
||||
b'\x41\x00\x63\x00\x22\x00\x32\x00\x16\x00\x14\x00\x1c\x00\x08\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x0d\x00\x00\x00\xc2\x18\x45\x18\x45\x10'\
|
||||
b'\x65\x10\x65\xb0\x28\xa0\x28\xa0\x38\xa0\x38\xe0\x10\x40\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x09\x00\x00\x00\x41\x00\x63\x00\x32\x00\x14\x00'\
|
||||
b'\x0c\x00\x1c\x00\x16\x00\x22\x00\x63\x00\x41\x80\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x09\x00\x00\x00\xc1\x80\x63\x00\x22\x00\x36\x00\x14\x00'\
|
||||
b'\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x09\x00\x00\x00\x7f\x00\x03\x00\x06\x00\x04\x00\x0c\x00\x18\x00'\
|
||||
b'\x30\x00\x20\x00\x40\x00\xff\x00\x00\x00\x00\x00\x00\x00\x04\x00'\
|
||||
b'\x00\xc0\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\xc0\x04\x00'\
|
||||
b'\x00\x80\x80\x40\x40\x40\x20\x20\x20\x10\x10\x00\x00\x00\x04\x00'\
|
||||
b'\x00\xc0\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\xc0\x07\x00'\
|
||||
b'\x00\x20\x60\x50\x90\x88\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\x00\x00\x04\x00'\
|
||||
b'\x00\x40\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00'\
|
||||
b'\x00\x00\x00\x78\x84\x04\x04\x7c\x84\x8c\x76\x00\x00\x00\x08\x00'\
|
||||
b'\x00\x80\x80\xb8\xcc\x84\x84\x84\x84\xc8\xb8\x00\x00\x00\x07\x00'\
|
||||
b'\x00\x00\x00\x78\x44\x80\x80\x80\x80\x44\x78\x00\x00\x00\x08\x00'\
|
||||
b'\x00\x02\x02\x3a\x46\x82\x82\x82\x82\x46\x3a\x00\x00\x00\x07\x00'\
|
||||
b'\x00\x00\x00\x3c\x44\x82\xfe\x80\x80\x46\x3c\x00\x00\x00\x04\x00'\
|
||||
b'\x00\x60\x40\xe0\x40\x40\x40\x40\x40\x40\x40\x00\x00\x00\x08\x00'\
|
||||
b'\x00\x00\x00\x3a\x46\x82\x82\x82\x82\x46\x7a\x02\x84\x7c\x08\x00'\
|
||||
b'\x00\x80\x80\xb0\xc8\x88\x88\x88\x88\x88\x88\x00\x00\x00\x03\x00'\
|
||||
b'\x00\x80\x00\x80\x80\x80\x80\x80\x80\x80\x80\x00\x00\x00\x03\x00'\
|
||||
b'\x00\x40\x00\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\xc0\x07\x00'\
|
||||
b'\x00\x80\x80\x88\x90\xa0\xe0\x90\x98\x88\x8c\x00\x00\x00\x03\x00'\
|
||||
b'\x00\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x00\x00\x00\x0b\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\xb7\x00\xcc\x80\x88\x80\x88\x80\x88\x80'\
|
||||
b'\x88\x80\x88\x80\x88\x80\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00'\
|
||||
b'\x00\xb8\xc4\x84\x84\x84\x84\x84\x84\x00\x00\x00\x07\x00\x00\x00'\
|
||||
b'\x00\x38\x44\x82\x82\x82\x82\x44\x38\x00\x00\x00\x08\x00\x00\x00'\
|
||||
b'\x00\xb8\xc8\x84\x84\x84\x84\xc8\xb8\x80\x80\x00\x08\x00\x00\x00'\
|
||||
b'\x00\x3a\x46\x82\x82\x82\x82\x46\x7a\x02\x02\x00\x05\x00\x00\x00'\
|
||||
b'\x00\xa0\xc0\x80\x80\x80\x80\x80\x80\x00\x00\x00\x07\x00\x00\x00'\
|
||||
b'\x00\x70\x88\x80\xc0\x70\x08\x88\x70\x00\x00\x00\x04\x00\x00\x00'\
|
||||
b'\x40\xe0\x40\x40\x40\x40\x40\x40\x60\x00\x00\x00\x08\x00\x00\x00'\
|
||||
b'\x00\x84\x84\x84\x84\x84\x84\x8c\x74\x00\x00\x00\x07\x00\x00\x00'\
|
||||
b'\x00\xc6\x44\x44\x6c\x28\x28\x38\x10\x00\x00\x00\x0a\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x8c\x40\xcc\xc0\x4c\x80\x5c\x80\x52\x80\x73\x80'\
|
||||
b'\x33\x00\x33\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x00\x44'\
|
||||
b'\x68\x28\x30\x30\x28\x4c\xc4\x00\x00\x00\x07\x00\x00\x00\x00\xc6'\
|
||||
b'\x44\x44\x6c\x28\x28\x30\x10\x10\x20\x60\x07\x00\x00\x00\x00\x7c'\
|
||||
b'\x0c\x08\x10\x30\x60\x40\xfc\x00\x00\x00\x05\x00\x00\x60\x40\x40'\
|
||||
b'\x40\x40\x40\x80\x40\x40\x40\x40\x40\x60\x04\x00\x00\x80\x80\x80'\
|
||||
b'\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x05\x00\x00\xc0\x40\x40'\
|
||||
b'\x40\x40\x40\x20\x40\x40\x40\x40\x40\xc0\x07\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x62\x9e\x00\x00\x00\x00\x00\x00\x00'
|
||||
|
||||
_index =\
|
||||
b'\x00\x00\x10\x00\x20\x00\x30\x00\x40\x00\x50\x00\x60\x00\x7e\x00'\
|
||||
b'\x9c\x00\xac\x00\xbc\x00\xcc\x00\xdc\x00\xec\x00\xfc\x00\x0c\x01'\
|
||||
b'\x1c\x01\x2c\x01\x3c\x01\x4c\x01\x5c\x01\x6c\x01\x7c\x01\x8c\x01'\
|
||||
b'\x9c\x01\xac\x01\xbc\x01\xcc\x01\xdc\x01\xec\x01\xfc\x01\x0c\x02'\
|
||||
b'\x1c\x02\x2c\x02\x4a\x02\x68\x02\x86\x02\xa4\x02\xc2\x02\xe0\x02'\
|
||||
b'\xf0\x02\x0e\x03\x2c\x03\x3c\x03\x4c\x03\x6a\x03\x7a\x03\x98\x03'\
|
||||
b'\xb6\x03\xd4\x03\xf2\x03\x10\x04\x2e\x04\x4c\x04\x6a\x04\x88\x04'\
|
||||
b'\xa6\x04\xc4\x04\xe2\x04\x00\x05\x1e\x05\x2e\x05\x3e\x05\x4e\x05'\
|
||||
b'\x5e\x05\x6e\x05\x7e\x05\x8e\x05\x9e\x05\xae\x05\xbe\x05\xce\x05'\
|
||||
b'\xde\x05\xee\x05\xfe\x05\x0e\x06\x1e\x06\x2e\x06\x3e\x06\x5c\x06'\
|
||||
b'\x6c\x06\x7c\x06\x8c\x06\x9c\x06\xac\x06\xbc\x06\xcc\x06\xdc\x06'\
|
||||
b'\xec\x06\x0a\x07\x1a\x07\x2a\x07\x3a\x07\x4a\x07\x5a\x07\x6a\x07'\
|
||||
b'\x7a\x07'
|
||||
|
||||
_mvfont = memoryview(_font)
|
||||
|
||||
def _chr_addr(ordch):
|
||||
offset = 2 * (ordch - 32)
|
||||
return int.from_bytes(_index[offset:offset + 2], 'little')
|
||||
|
||||
def get_ch(ch):
|
||||
ordch = ord(ch)
|
||||
ordch = ordch + 1 if ordch >= 32 and ordch <= 126 else 32
|
||||
offset = _chr_addr(ordch)
|
||||
width = int.from_bytes(_font[offset:offset + 2], 'little')
|
||||
next_offs = _chr_addr(ordch +1)
|
||||
return _mvfont[offset + 2:next_offs], 14, width
|
||||
|
|
@ -0,0 +1,280 @@
|
|||
# Code generated by font-to-py.py.
|
||||
# Font: FreeSans.ttf
|
||||
version = '0.2'
|
||||
|
||||
def height():
|
||||
return 20
|
||||
|
||||
def max_width():
|
||||
return 20
|
||||
|
||||
def hmap():
|
||||
return True
|
||||
|
||||
def reverse():
|
||||
return False
|
||||
|
||||
def monospaced():
|
||||
return False
|
||||
|
||||
def min_ch():
|
||||
return 32
|
||||
|
||||
def max_ch():
|
||||
return 126
|
||||
|
||||
_font =\
|
||||
b'\x0b\x00\x00\x00\x3c\x00\x7e\x00\xc7\x00\xc3\x00\x03\x00\x03\x00'\
|
||||
b'\x06\x00\x0c\x00\x08\x00\x18\x00\x18\x00\x00\x00\x00\x00\x18\x00'\
|
||||
b'\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x07\x00\x00\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\x00\x00'\
|
||||
b'\xc0\xc0\x00\x00\x00\x00\x07\x00\x00\x00\xd8\xd8\xd8\xd8\x90\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0b\x00\x00\x00'\
|
||||
b'\x00\x00\x0c\xc0\x08\x80\x08\x80\x7f\xe0\x7f\xe0\x19\x80\x11\x00'\
|
||||
b'\x11\x00\xff\xc0\xff\xc0\x33\x00\x33\x00\x22\x00\x22\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x0b\x00\x08\x00\x3e\x00\x7f\x80\xe9\xc0'\
|
||||
b'\xc8\xc0\xc8\xc0\xc8\x00\xe8\x00\x7c\x00\x1f\x80\x09\xc0\x08\xc0'\
|
||||
b'\xc8\xc0\xe9\xc0\x7f\x80\x3e\x00\x08\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x12\x00\x00\x00\x00\x00\x00\x00\x38\x10\x00\x7c\x10\x00\xc6\x20'\
|
||||
b'\x00\xc6\x20\x00\xc6\x40\x00\x7c\xc0\x00\x38\x80\x00\x01\x1e\x00'\
|
||||
b'\x01\x3f\x00\x02\x73\x80\x02\x61\x80\x04\x73\x80\x04\x3f\x00\x08'\
|
||||
b'\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0d\x00'\
|
||||
b'\x00\x00\x00\x00\x0e\x00\x1f\x00\x31\x80\x31\x80\x31\x80\x1f\x00'\
|
||||
b'\x1c\x00\x76\x60\xe3\x60\xc1\xc0\xc0\xc0\xe1\xc0\x7f\x60\x3e\x30'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\xc0\xc0\xc0\xc0'\
|
||||
b'\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07\x00'\
|
||||
b'\x00\x10\x10\x20\x20\x60\x40\xc0\xc0\xc0\xc0\xc0\xc0\xc0\x40\x60'\
|
||||
b'\x20\x30\x10\x18\x07\x00\x00\x40\x40\x20\x20\x30\x10\x18\x18\x18'\
|
||||
b'\x18\x18\x18\x18\x10\x30\x20\x60\x40\xc0\x08\x00\x00\x20\x20\xf8'\
|
||||
b'\x20\x50\x50\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x18\x00\x18\x00\x18\x00\xff\x00\xff\x00\x18\x00\x18\x00\x18\x00'\
|
||||
b'\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc0\xc0\x40\x40\x80\x00'\
|
||||
b'\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf8\xf8\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\xc0\xc0\x00\x00\x00\x00\x06\x00\x00\x04'\
|
||||
b'\x0c\x08\x08\x18\x10\x10\x30\x20\x20\x60\x40\x40\xc0\x80\x00\x00'\
|
||||
b'\x00\x00\x0b\x00\x00\x00\x00\x00\x3e\x00\x7f\x00\x63\x00\xe3\x80'\
|
||||
b'\xc1\x80\xc1\x80\xc1\x80\xc1\x80\xc1\x80\xc1\x80\xe3\x80\x63\x00'\
|
||||
b'\x7f\x00\x3e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0b\x00\x00\x00'\
|
||||
b'\x00\x00\x10\x00\x30\x00\xf0\x00\xf0\x00\x30\x00\x30\x00\x30\x00'\
|
||||
b'\x30\x00\x30\x00\x30\x00\x30\x00\x30\x00\x30\x00\x30\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x0b\x00\x00\x00\x00\x00\x3e\x00\x7f\x00'\
|
||||
b'\xe3\x80\xc1\x80\x01\x80\x01\x80\x03\x00\x0e\x00\x1c\x00\x30\x00'\
|
||||
b'\x60\x00\xc0\x00\xff\x80\xff\x80\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x0b\x00\x00\x00\x00\x00\x3e\x00\x7f\x00\xe3\x80\xc1\x80\x01\x80'\
|
||||
b'\x0f\x00\x0f\x00\x03\x80\x01\x80\x01\x80\xc1\x80\xe3\x80\x7f\x00'\
|
||||
b'\x3e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0b\x00\x00\x00\x00\x00'\
|
||||
b'\x06\x00\x06\x00\x0e\x00\x1e\x00\x16\x00\x26\x00\x46\x00\x46\x00'\
|
||||
b'\x86\x00\xff\x00\xff\x00\x06\x00\x06\x00\x06\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x0b\x00\x00\x00\x00\x00\x7f\x00\x7f\x00\x60\x00'\
|
||||
b'\x60\x00\xde\x00\xff\x00\xe3\x80\x01\x80\x01\x80\x01\x80\x01\x80'\
|
||||
b'\xc3\x00\x7f\x00\x3e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0b\x00'\
|
||||
b'\x00\x00\x00\x00\x1e\x00\x3f\x00\x63\x00\x61\x80\xc0\x00\xde\x00'\
|
||||
b'\xff\x00\xe3\x80\xc1\x80\xc1\x80\xc1\x80\x63\x80\x7f\x00\x3e\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x0b\x00\x00\x00\x00\x00\xff\x80'\
|
||||
b'\xff\x80\x01\x00\x03\x00\x02\x00\x06\x00\x04\x00\x0c\x00\x08\x00'\
|
||||
b'\x18\x00\x18\x00\x10\x00\x30\x00\x30\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x0b\x00\x00\x00\x00\x00\x1c\x00\x3e\x00\x63\x00\x63\x00'\
|
||||
b'\x63\x00\x3e\x00\x3e\x00\x63\x00\xc1\x80\xc1\x80\xc1\x80\x63\x00'\
|
||||
b'\x7f\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0b\x00\x00\x00'\
|
||||
b'\x00\x00\x3e\x00\x7f\x00\xe3\x00\xc1\x80\xc1\x80\xc1\x80\xe3\x80'\
|
||||
b'\x7f\x80\x3d\x80\x01\x80\x03\x00\xe3\x00\x7e\x00\x3c\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\xc0\xc0\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\xc0\xc0\x00\x00\x00\x00\x05\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\xc0\xc0\x00\x00\x00\x00\x00\x00\xc0\xc0\x40\x40'\
|
||||
b'\x80\x00\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x40\x01\xc0\x07\x00\x3c\x00\xe0\x00\xe0\x00\x78\x00\x0f\x00'\
|
||||
b'\x03\xc0\x00\x40\x00\x00\x00\x00\x00\x00\x00\x00\x0c\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xc0'\
|
||||
b'\xff\xc0\x00\x00\x00\x00\xff\xc0\xff\xc0\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\xe0\x00\x78\x00\x0e\x00\x03\xc0\x01\xc0'\
|
||||
b'\x07\x00\x3c\x00\xf0\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x0b\x00\x00\x00\x3c\x00\x7e\x00\xc7\x00\xc3\x00\x03\x00\x03\x00'\
|
||||
b'\x06\x00\x0c\x00\x08\x00\x18\x00\x18\x00\x00\x00\x00\x00\x18\x00'\
|
||||
b'\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14\x00\x00\x00\x00\x03'\
|
||||
b'\xf0\x00\x0f\xfc\x00\x1e\x0f\x00\x38\x03\x80\x71\xe1\x80\x63\xe9'\
|
||||
b'\xc0\x67\x18\xc0\xce\x18\xc0\xcc\x18\xc0\xcc\x10\xc0\xcc\x31\x80'\
|
||||
b'\xce\x73\x80\x67\xff\x00\x63\x9e\x00\x30\x00\x00\x3c\x00\x00\x0f'\
|
||||
b'\xf8\x00\x03\xf0\x00\x00\x00\x00\x0d\x00\x00\x00\x07\x00\x07\x00'\
|
||||
b'\x07\x80\x0d\x80\x0d\x80\x08\xc0\x18\xc0\x18\xc0\x10\x60\x3f\xe0'\
|
||||
b'\x3f\xe0\x30\x30\x60\x30\x60\x38\xc0\x18\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x0d\x00\x00\x00\xff\x00\xff\x80\xc1\xc0\xc0\xc0\xc0\xc0'\
|
||||
b'\xc1\xc0\xff\x00\xff\x80\xc0\xc0\xc0\x60\xc0\x60\xc0\x60\xc0\xe0'\
|
||||
b'\xff\xc0\xff\x80\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00'\
|
||||
b'\x0f\x80\x3f\xe0\x70\x60\x60\x30\xe0\x00\xc0\x00\xc0\x00\xc0\x00'\
|
||||
b'\xc0\x00\xc0\x00\xe0\x30\x60\x70\x70\x60\x3f\xe0\x0f\x80\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00\xff\x00\xff\x80\xc1\xc0'\
|
||||
b'\xc0\xc0\xc0\x60\xc0\x60\xc0\x60\xc0\x60\xc0\x60\xc0\x60\xc0\x60'\
|
||||
b'\xc0\xc0\xc1\xc0\xff\x80\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x0d\x00\x00\x00\xff\xc0\xff\xc0\xc0\x00\xc0\x00\xc0\x00\xc0\x00'\
|
||||
b'\xff\x80\xff\x80\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xff\xc0'\
|
||||
b'\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x0c\x00\x00\x00\xff\x80'\
|
||||
b'\xff\x80\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xff\x00\xff\x00\xc0\x00'\
|
||||
b'\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x0f\x00\x00\x00\x0f\xc0\x3f\xf0\x38\x30\x60\x18'\
|
||||
b'\x60\x00\xc0\x00\xc0\x00\xc1\xf8\xc1\xf8\xc0\x18\xe0\x18\x60\x38'\
|
||||
b'\x78\x78\x3f\xd8\x0f\x88\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00'\
|
||||
b'\x00\x00\xc0\x60\xc0\x60\xc0\x60\xc0\x60\xc0\x60\xc0\x60\xff\xe0'\
|
||||
b'\xff\xe0\xc0\x60\xc0\x60\xc0\x60\xc0\x60\xc0\x60\xc0\x60\xc0\x60'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\xc0\xc0\xc0\xc0\xc0'\
|
||||
b'\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\x00\x00\x00\x00\x0b\x00'\
|
||||
b'\x00\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00'\
|
||||
b'\x03\x00\x03\x00\x03\x00\xc3\x00\xc3\x00\xe7\x00\x7e\x00\x3c\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x0d\x00\x00\x00\xc0\x60\xc0\xc0'\
|
||||
b'\xc1\x80\xc3\x00\xc6\x00\xcc\x00\xdc\x00\xf6\x00\xe6\x00\xc3\x00'\
|
||||
b'\xc1\x80\xc1\x80\xc0\xc0\xc0\x60\xc0\x60\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x0b\x00\x00\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00'\
|
||||
b'\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00'\
|
||||
b'\xff\x80\xff\x80\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00\x00\x00'\
|
||||
b'\x00\xe0\x1c\x00\xe0\x1c\x00\xf0\x3c\x00\xf0\x3c\x00\xd0\x2c\x00'\
|
||||
b'\xd8\x6c\x00\xd8\x6c\x00\xc8\x4c\x00\xcc\xcc\x00\xcc\xcc\x00\xc4'\
|
||||
b'\x8c\x00\xc6\x8c\x00\xc7\x8c\x00\xc3\x0c\x00\xc3\x0c\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x00\x00\xe0\x60'\
|
||||
b'\xe0\x60\xf0\x60\xf0\x60\xd8\x60\xd8\x60\xcc\x60\xc4\x60\xc6\x60'\
|
||||
b'\xc2\x60\xc3\x60\xc1\xe0\xc1\xe0\xc0\xe0\xc0\xe0\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x10\x00\x00\x00\x0f\xc0\x1f\xe0\x38\x70\x60\x18'\
|
||||
b'\x60\x1c\xc0\x0c\xc0\x0c\xc0\x0c\xc0\x0c\xc0\x0c\x60\x1c\x60\x18'\
|
||||
b'\x38\x70\x1f\xe0\x0f\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x0d\x00'\
|
||||
b'\x00\x00\xff\x00\xff\x80\xc1\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc1\xc0'\
|
||||
b'\xff\x80\xff\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x0f\xc0\x1f\xe0'\
|
||||
b'\x38\x70\x60\x18\x60\x1c\xc0\x0c\xc0\x0c\xc0\x0c\xc0\x0c\xc0\x0c'\
|
||||
b'\x60\x18\x60\xd8\x38\x70\x1f\xf8\x0f\x98\x00\x08\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x0e\x00\x00\x00\xff\x80\xff\xc0\xc0\xe0\xc0\x60\xc0\x60'\
|
||||
b'\xc0\x60\xc0\xc0\xff\x80\xff\xc0\xc0\xe0\xc0\x60\xc0\x60\xc0\x60'\
|
||||
b'\xc0\x60\xc0\x70\x00\x00\x00\x00\x00\x00\x00\x00\x0d\x00\x00\x00'\
|
||||
b'\x1f\x80\x7f\xe0\xe0\x70\xc0\x30\xc0\x00\xe0\x00\x78\x00\x3f\x80'\
|
||||
b'\x03\xe0\x00\x70\xc0\x30\xc0\x30\x70\x60\x7f\xe0\x1f\x80\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x0d\x00\x00\x00\xff\xc0\xff\xc0\x0c\x00'\
|
||||
b'\x0c\x00\x0c\x00\x0c\x00\x0c\x00\x0c\x00\x0c\x00\x0c\x00\x0c\x00'\
|
||||
b'\x0c\x00\x0c\x00\x0c\x00\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x0e\x00\x00\x00\xc0\x60\xc0\x60\xc0\x60\xc0\x60\xc0\x60\xc0\x60'\
|
||||
b'\xc0\x60\xc0\x60\xc0\x60\xc0\x60\xc0\x60\xc0\x60\x60\xc0\x7f\xc0'\
|
||||
b'\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0d\x00\x00\x00\xc0\x30'\
|
||||
b'\x60\x30\x60\x30\x20\x20\x30\x60\x30\x60\x10\x40\x18\xc0\x18\xc0'\
|
||||
b'\x08\x80\x0d\x80\x0d\x80\x07\x00\x07\x00\x07\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x13\x00\x00\x00\x00\xc0\xc0\xc0\x60\xe0\xc0\x60'\
|
||||
b'\xe0\xc0\x61\xe0\xc0\x61\xb1\x80\x31\xb1\x80\x31\xb1\x80\x33\x11'\
|
||||
b'\x80\x33\x19\x00\x13\x1b\x00\x1f\x1b\x00\x1e\x0b\x00\x1e\x0e\x00'\
|
||||
b'\x0e\x0e\x00\x0c\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x0d\x00\x00\x00\x60\x30\x30\x70\x30\x60\x18\xc0\x0c\xc0'\
|
||||
b'\x0d\x80\x07\x00\x07\x00\x07\x00\x0d\x80\x18\xc0\x18\xe0\x30\x60'\
|
||||
b'\x70\x30\x60\x38\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00'\
|
||||
b'\x60\x18\x70\x38\x30\x30\x18\x60\x18\x60\x0c\xc0\x0f\xc0\x07\x80'\
|
||||
b'\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x0c\x00\x00\x00\xff\xe0\xff\xe0\x00\xc0'\
|
||||
b'\x01\x80\x03\x80\x03\x00\x06\x00\x0c\x00\x1c\x00\x38\x00\x30\x00'\
|
||||
b'\x60\x00\xc0\x00\xff\xe0\xff\xe0\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x06\x00\x00\xe0\xe0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0'\
|
||||
b'\xc0\xc0\xc0\xc0\xe0\xe0\x06\x00\x00\x80\xc0\x40\x40\x60\x20\x20'\
|
||||
b'\x30\x10\x10\x18\x08\x08\x0c\x04\x00\x00\x00\x00\x06\x00\x00\xe0'\
|
||||
b'\xe0\x60\x60\x60\x60\x60\x60\x60\x60\x60\x60\x60\x60\x60\x60\x60'\
|
||||
b'\xe0\xe0\x09\x00\x00\x00\x00\x00\x18\x00\x38\x00\x28\x00\x2c\x00'\
|
||||
b'\x64\x00\x46\x00\xc2\x00\x82\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0c\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xf0'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x05\x00\x00\xc0\x60\x30\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0b\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x3e\x00\xff\x80\xc1\x80\x01\x80'\
|
||||
b'\x01\x80\x3f\x80\xf1\x80\xc1\x80\xc3\x80\xff\xc0\x78\xc0\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x0b\x00\x00\x00\xc0\x00\xc0\x00\xc0\x00'\
|
||||
b'\xc0\x00\xdf\x00\xff\x80\xe1\x80\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0'\
|
||||
b'\xc0\xc0\xe1\x80\xff\x80\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1e\x00\x7f\x00'\
|
||||
b'\x61\x80\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc1\x80\x63\x80\x7f\x00'\
|
||||
b'\x3e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0b\x00\x00\x00\x01\x80'\
|
||||
b'\x01\x80\x01\x80\x01\x80\x3d\x80\x7f\x80\x63\x80\xc1\x80\xc1\x80'\
|
||||
b'\xc1\x80\xc1\x80\xc1\x80\x63\x80\x7f\x80\x3d\x80\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x3e\x00\x7f\x00\x63\x00\xc1\x80\xff\x80\xff\x80\xc0\x00\xc0\x00'\
|
||||
b'\x63\x80\x7f\x00\x3e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00'\
|
||||
b'\x00\x30\x70\x60\x60\xf0\xf0\x60\x60\x60\x60\x60\x60\x60\x60\x60'\
|
||||
b'\x00\x00\x00\x00\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x3d\x80\x7f\x80\x63\x80\xc1\x80\xc1\x80\xc1\x80\xc1\x80\xc1\x80'\
|
||||
b'\x63\x80\x7f\x80\x3d\x80\x01\x80\xc3\x80\x7f\x00\x3e\x00\x0b\x00'\
|
||||
b'\x00\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xdf\x00\xdf\x80\xe3\x80'\
|
||||
b'\xc1\x80\xc1\x80\xc1\x80\xc1\x80\xc1\x80\xc1\x80\xc1\x80\xc1\x80'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\xc0\xc0\x00\x00\xc0'\
|
||||
b'\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\x00\x00\x00\x00\x05\x00'\
|
||||
b'\x00\x30\x30\x00\x00\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30'\
|
||||
b'\x30\x30\xf0\xe0\x0a\x00\x00\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00'\
|
||||
b'\xc3\x00\xc6\x00\xcc\x00\xd8\x00\xf8\x00\xec\x00\xce\x00\xc6\x00'\
|
||||
b'\xc3\x00\xc3\x00\xc1\x80\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00'\
|
||||
b'\x00\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0'\
|
||||
b'\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\xde\x78\xfe\xfc\xe3\x8c\xc3\x0c\xc3\x0c\xc3\x0c\xc3\x0c\xc3\x0c'\
|
||||
b'\xc3\x0c\xc3\x0c\xc3\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x0b\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xcf\x00\xdf\x80\xe3\x80'\
|
||||
b'\xc1\x80\xc1\x80\xc1\x80\xc1\x80\xc1\x80\xc1\x80\xc1\x80\xc1\x80'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x0b\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x3e\x00\x7f\x00\x63\x00\xc1\x80\xc1\x80\xc1\x80'\
|
||||
b'\xc1\x80\xc1\x80\x63\x00\x7f\x00\x3e\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xde\x00'\
|
||||
b'\xff\x80\xe1\x80\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xe1\x80'\
|
||||
b'\xff\x80\xde\x00\xc0\x00\xc0\x00\xc0\x00\x00\x00\x0b\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x3d\x80\x7f\x80\x63\x80\xc1\x80'\
|
||||
b'\xc1\x80\xc1\x80\xc1\x80\xc1\x80\x63\x80\x7f\x80\x3d\x80\x01\x80'\
|
||||
b'\x01\x80\x01\x80\x00\x00\x07\x00\x00\x00\x00\x00\x00\xd8\xf8\xe0'\
|
||||
b'\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\x00\x00\x00\x00\x0a\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x3c\x00\x7f\x00\xc3\x00\xc0\x00'\
|
||||
b'\xf0\x00\x7e\x00\x0f\x00\x03\x00\xc3\x00\xfe\x00\x7c\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x60\x60\xf0\xf0\x60'\
|
||||
b'\x60\x60\x60\x60\x60\x60\x70\x70\x00\x00\x00\x00\x0b\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\xc1\x80\xc1\x80\xc1\x80\xc1\x80'\
|
||||
b'\xc1\x80\xc1\x80\xc1\x80\xc1\x80\xe3\x80\xfd\x80\x79\x80\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\xc0\xc0\x61\x80\x61\x80\x61\x00\x23\x00\x33\x00\x32\x00'\
|
||||
b'\x16\x00\x1e\x00\x1c\x00\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc3\x0c\xc3\x8c'\
|
||||
b'\x63\x8c\x67\x88\x66\x98\x24\xd8\x34\xd0\x3c\xd0\x3c\x70\x18\x70'\
|
||||
b'\x18\x60\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x61\x80\x63\x00\x33\x00\x1e\x00\x1c\x00'\
|
||||
b'\x0c\x00\x1c\x00\x16\x00\x33\x00\x63\x00\x41\x80\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\xc0\x80\x41\x80\x61\x80\x61\x00\x23\x00\x33\x00\x32\x00\x16\x00'\
|
||||
b'\x1c\x00\x1c\x00\x0c\x00\x08\x00\x18\x00\x78\x00\x70\x00\x0a\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\x00\xff\x00\x06\x00'\
|
||||
b'\x06\x00\x0c\x00\x18\x00\x30\x00\x60\x00\xc0\x00\xff\x00\xff\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x18\x38\x30\x30\x30'\
|
||||
b'\x30\x30\x30\x70\xc0\x70\x30\x30\x30\x30\x30\x30\x38\x18\x05\x00'\
|
||||
b'\x00\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0'\
|
||||
b'\xc0\xc0\xc0\xc0\x07\x00\x00\xc0\xe0\x60\x60\x60\x60\x60\x60\x70'\
|
||||
b'\x18\x70\x60\x60\x60\x60\x60\x60\xe0\xc0\x0a\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x60\x00\xf1\x00\x9f\x00'\
|
||||
b'\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
|
||||
b'\x00\x00\x00\x00'
|
||||
|
||||
_index =\
|
||||
b'\x00\x00\x2a\x00\x40\x00\x56\x00\x6c\x00\x96\x00\xc0\x00\xfe\x00'\
|
||||
b'\x28\x01\x3e\x01\x54\x01\x6a\x01\x80\x01\xaa\x01\xc0\x01\xd6\x01'\
|
||||
b'\xec\x01\x02\x02\x2c\x02\x56\x02\x80\x02\xaa\x02\xd4\x02\xfe\x02'\
|
||||
b'\x28\x03\x52\x03\x7c\x03\xa6\x03\xbc\x03\xd2\x03\xfc\x03\x26\x04'\
|
||||
b'\x50\x04\x7a\x04\xb8\x04\xe2\x04\x0c\x05\x36\x05\x60\x05\x8a\x05'\
|
||||
b'\xb4\x05\xde\x05\x08\x06\x1e\x06\x48\x06\x72\x06\x9c\x06\xda\x06'\
|
||||
b'\x04\x07\x2e\x07\x58\x07\x82\x07\xac\x07\xd6\x07\x00\x08\x2a\x08'\
|
||||
b'\x54\x08\x92\x08\xbc\x08\xe6\x08\x10\x09\x26\x09\x3c\x09\x52\x09'\
|
||||
b'\x7c\x09\xa6\x09\xbc\x09\xe6\x09\x10\x0a\x3a\x0a\x64\x0a\x8e\x0a'\
|
||||
b'\xa4\x0a\xce\x0a\xf8\x0a\x0e\x0b\x24\x0b\x4e\x0b\x64\x0b\x8e\x0b'\
|
||||
b'\xb8\x0b\xe2\x0b\x0c\x0c\x36\x0c\x4c\x0c\x76\x0c\x8c\x0c\xb6\x0c'\
|
||||
b'\xe0\x0c\x0a\x0d\x34\x0d\x5e\x0d\x88\x0d\x9e\x0d\xb4\x0d\xca\x0d'\
|
||||
b'\xf4\x0d'
|
||||
|
||||
_mvfont = memoryview(_font)
|
||||
|
||||
def _chr_addr(ordch):
|
||||
offset = 2 * (ordch - 32)
|
||||
return int.from_bytes(_index[offset:offset + 2], 'little')
|
||||
|
||||
def get_ch(ch):
|
||||
ordch = ord(ch)
|
||||
ordch = ordch + 1 if ordch >= 32 and ordch <= 126 else 32
|
||||
offset = _chr_addr(ordch)
|
||||
width = int.from_bytes(_font[offset:offset + 2], 'little')
|
||||
next_offs = _chr_addr(ordch +1)
|
||||
return _mvfont[offset + 2:next_offs], 20, width
|
||||
|
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 19 KiB |
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 16 KiB |
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 19 KiB |
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 18 KiB |
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 18 KiB |
|
@ -0,0 +1,69 @@
|
|||
# ssd1306_setup.py Demo pogram for rendering arbitrary fonts to an SSD1306 OLED display.
|
||||
# Device initialisation
|
||||
|
||||
# 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.
|
||||
|
||||
|
||||
# https://learn.adafruit.com/monochrome-oled-breakouts/wiring-128x32-spi-oled-display
|
||||
# https://www.proto-pic.co.uk/monochrome-128x32-oled-graphic-display.html
|
||||
|
||||
# V0.3 12th Aug 2018
|
||||
|
||||
import machine
|
||||
from ssd1306 import SSD1306_SPI, SSD1306_I2C
|
||||
|
||||
WIDTH = const(128)
|
||||
HEIGHT = const(64)
|
||||
|
||||
def setup(use_spi=False, soft=True):
|
||||
if use_spi:
|
||||
# Pyb SSD
|
||||
# 3v3 Vin
|
||||
# Gnd Gnd
|
||||
# X1 DC
|
||||
# X2 CS
|
||||
# X3 Rst
|
||||
# X6 CLK
|
||||
# X8 DATA
|
||||
pdc = machine.Pin('X1', machine.Pin.OUT_PP)
|
||||
pcs = machine.Pin('X2', machine.Pin.OUT_PP)
|
||||
prst = machine.Pin('X3', machine.Pin.OUT_PP)
|
||||
if soft:
|
||||
spi = machine.SPI(sck=machine.Pin('X6'), mosi=machine.Pin('X8'), miso=machine.Pin('X7'))
|
||||
else:
|
||||
spi = machine.SPI(1)
|
||||
ssd = SSD1306_SPI(WIDTH, HEIGHT, spi, pdc, prst, pcs)
|
||||
else: # I2C
|
||||
# Pyb SSD
|
||||
# 3v3 Vin
|
||||
# Gnd Gnd
|
||||
# Y9 CLK
|
||||
# Y10 DATA
|
||||
if soft:
|
||||
pscl = machine.Pin('Y9', machine.Pin.OPEN_DRAIN)
|
||||
psda = machine.Pin('Y10', machine.Pin.OPEN_DRAIN)
|
||||
i2c = machine.I2C(scl=pscl, sda=psda)
|
||||
else:
|
||||
i2c = machine.I2C(2)
|
||||
ssd = SSD1306_I2C(WIDTH, HEIGHT, i2c)
|
||||
return ssd
|
|
@ -0,0 +1,343 @@
|
|||
# writer.py Implements the Writer class.
|
||||
# V0.3 Peter Hinch 11th Aug 2018
|
||||
# Handles colour, upside down diplays, word wrap and tab stops
|
||||
|
||||
# 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.
|
||||
|
||||
# A Writer supports rendering text to a Display instance in a given font.
|
||||
# Multiple Writer instances may be created, each rendering a font to the
|
||||
# same Display object.
|
||||
|
||||
# Timings based on a 20 pixel high proportional font, run on a pyboard V1.0.
|
||||
# Using CWriter's slow rendering: _printchar 9.5ms typ, 13.5ms max.
|
||||
# Using Writer's fast rendering: _printchar 115μs min 480μs typ 950μs max.
|
||||
|
||||
import framebuf
|
||||
|
||||
class DisplayState():
|
||||
def __init__(self):
|
||||
self.text_row = 0
|
||||
self.text_col = 0
|
||||
self.usd = False
|
||||
|
||||
def _get_id(device):
|
||||
if not isinstance(device, framebuf.FrameBuffer):
|
||||
raise ValueError('Device must be derived from FrameBuffer.')
|
||||
return id(device)
|
||||
|
||||
# Basic Writer class for monochrome displays
|
||||
class Writer():
|
||||
|
||||
state = {} # Holds a display state for each device
|
||||
|
||||
@staticmethod
|
||||
def set_textpos(device, row=None, col=None):
|
||||
devid = _get_id(device)
|
||||
if devid not in Writer.state:
|
||||
Writer.state[devid] = DisplayState()
|
||||
s = Writer.state[devid] # Current state
|
||||
if row is not None:
|
||||
if row < 0 or row >= device.height:
|
||||
raise ValueError('row is out of range')
|
||||
s.text_row = device.height - 1 - row if s.usd else row
|
||||
if col is not None:
|
||||
if col < 0 or col >= device.width:
|
||||
raise ValueError('col is out of range')
|
||||
s.text_col = device.width -1 - col if s.usd else col
|
||||
return s.text_row, s.text_col
|
||||
|
||||
def __init__(self, device, font, verbose=True):
|
||||
self.devid = _get_id(device)
|
||||
self.device = device
|
||||
if self.devid not in Writer.state:
|
||||
Writer.state[self.devid] = DisplayState()
|
||||
self.font = font
|
||||
self.usd = Writer.state[self.devid].usd
|
||||
|
||||
# Allow to work with reverse or normal font mapping
|
||||
if font.hmap():
|
||||
self.map = framebuf.MONO_HMSB if font.reverse() else framebuf.MONO_HLSB
|
||||
else:
|
||||
raise ValueError('Font must be horizontally mapped.')
|
||||
if verbose:
|
||||
fstr = 'Orientation: Horizontal. Reversal: {}. Width: {}. Height: {}.'
|
||||
print(fstr.format(font.reverse(), device.width, device.height))
|
||||
print('Start row = {} col = {}'.format(self._getstate().text_row, self._getstate().text_col))
|
||||
self.screenwidth = device.width # In pixels
|
||||
self.screenheight = device.height
|
||||
self.bgcolor = 0 # Monochrome background and foreground colors
|
||||
self.fgcolor = 1
|
||||
self.row_clip = False # Clip or scroll when screen full
|
||||
self.col_clip = False # Clip or new line when row is full
|
||||
self.wrap = True # Word wrap
|
||||
self.cpos = 0
|
||||
self.tab = 4
|
||||
|
||||
self.glyph = None # Current char
|
||||
self.char_height = 0
|
||||
self.char_width = 0
|
||||
|
||||
def _getstate(self):
|
||||
return Writer.state[self.devid]
|
||||
|
||||
def _newline(self):
|
||||
s = self._getstate()
|
||||
height = self.height()
|
||||
if self.usd:
|
||||
s.text_row -= height
|
||||
s.text_col = self.screenwidth - 1
|
||||
margin = s.text_row - height
|
||||
y = 0
|
||||
else:
|
||||
s.text_row += height
|
||||
s.text_col = 0
|
||||
margin = self.screenheight - (s.text_row + height)
|
||||
y = self.screenheight + margin
|
||||
if margin < 0:
|
||||
if not self.row_clip:
|
||||
if self.usd:
|
||||
margin = -margin
|
||||
self.device.scroll(0, margin)
|
||||
self.device.fill_rect(0, y, self.screenwidth, abs(margin), self.bgcolor)
|
||||
s.text_row += margin
|
||||
|
||||
def set_clip(self, row_clip=None, col_clip=None, wrap=None):
|
||||
if row_clip is not None:
|
||||
self.row_clip = row_clip
|
||||
if col_clip is not None:
|
||||
self.col_clip = col_clip
|
||||
if wrap is not None:
|
||||
self.wrap = wrap
|
||||
return self.row_clip, self.col_clip, self.wrap
|
||||
|
||||
def height(self):
|
||||
return self.font.height()
|
||||
|
||||
def printstring(self, string, invert=False):
|
||||
# word wrapping. Assumes words separated by single space.
|
||||
while True:
|
||||
lines = string.split('\n', 1)
|
||||
s = lines[0]
|
||||
if s:
|
||||
self._printline(s, invert)
|
||||
if len(lines) == 1:
|
||||
break
|
||||
else:
|
||||
self._printchar('\n')
|
||||
string = lines[1]
|
||||
|
||||
def _printline(self, string, invert):
|
||||
rstr = None
|
||||
if self.wrap and self.stringlen(string) > self.screenwidth:
|
||||
pos = 0
|
||||
lstr = string[:]
|
||||
while self.stringlen(lstr) > self.screenwidth:
|
||||
pos = lstr.rfind(' ')
|
||||
lstr = lstr[:pos].rstrip()
|
||||
if pos > 0:
|
||||
rstr = string[pos + 1:]
|
||||
string = lstr
|
||||
|
||||
for char in string:
|
||||
self._printchar(char, invert)
|
||||
if rstr is not None:
|
||||
self._printchar('\n')
|
||||
self._printline(rstr, invert) # Recurse
|
||||
|
||||
def stringlen(self, string):
|
||||
l = 0
|
||||
for char in string:
|
||||
l += self._charlen(char)
|
||||
return l
|
||||
|
||||
def _charlen(self, char):
|
||||
if char == '\n':
|
||||
char_width = 0
|
||||
else:
|
||||
_, _, char_width = self.font.get_ch(char)
|
||||
return char_width
|
||||
|
||||
def _get_char(self, char, recurse):
|
||||
if not recurse: # Handle tabs
|
||||
if char == '\n':
|
||||
self.cpos = 0
|
||||
elif char == '\t':
|
||||
nspaces = self.tab - (self.cpos % self.tab)
|
||||
if nspaces == 0:
|
||||
nspaces = self.tab
|
||||
while nspaces:
|
||||
nspaces -= 1
|
||||
self._printchar(' ', recurse=True)
|
||||
self.glyph = None # All done
|
||||
return
|
||||
|
||||
self.glyph = None # Assume all done
|
||||
if char == '\n':
|
||||
self._newline()
|
||||
return
|
||||
glyph, char_height, char_width = self.font.get_ch(char)
|
||||
s = self._getstate()
|
||||
if self.usd:
|
||||
if s.text_row - char_height < 0:
|
||||
if self.row_clip:
|
||||
return
|
||||
self._newline()
|
||||
if s.text_col - char_width < 0:
|
||||
if self.col_clip:
|
||||
return
|
||||
else:
|
||||
self._newline()
|
||||
else:
|
||||
if s.text_row + char_height > self.screenheight:
|
||||
if self.row_clip:
|
||||
return
|
||||
self._newline()
|
||||
if s.text_col + char_width > self.screenwidth:
|
||||
if self.col_clip:
|
||||
return
|
||||
else:
|
||||
self._newline()
|
||||
self.glyph = glyph
|
||||
self.char_height = char_height
|
||||
self.char_width = char_width
|
||||
|
||||
# Method using blitting. Efficient rendering for monochrome displays.
|
||||
# Tested on SSD1306. Invert is for black-on-white rendering.
|
||||
def _printchar(self, char, invert=False, recurse=False):
|
||||
s = self._getstate()
|
||||
self._get_char(char, recurse)
|
||||
if self.glyph is None:
|
||||
return # All done
|
||||
buf = bytearray(self.glyph)
|
||||
if invert:
|
||||
for i, v in enumerate(buf):
|
||||
buf[i] = 0xFF & ~ v
|
||||
fbc = framebuf.FrameBuffer(buf, self.char_width, self.char_height, self.map)
|
||||
self.device.blit(fbc, s.text_col, s.text_row)
|
||||
s.text_col += self.char_width
|
||||
self.cpos += 1
|
||||
|
||||
def tabsize(self, value=None):
|
||||
if value is not None:
|
||||
self.tab = value
|
||||
return self.tab
|
||||
|
||||
|
||||
# Writer for colour displays or upside down rendering
|
||||
class CWriter(Writer):
|
||||
|
||||
@staticmethod
|
||||
def invert_display(device, value=True):
|
||||
devid = id(device)
|
||||
if devid not in Writer.state:
|
||||
Writer.state[devid] = DisplayState()
|
||||
Writer.state[devid].usd = value
|
||||
|
||||
def __init__(self,device, font, verbose=True):
|
||||
super().__init__(device, font, verbose)
|
||||
|
||||
def setcolor(self, fgcolor=None, bgcolor=None):
|
||||
if fgcolor is not None:
|
||||
self.fgcolor = fgcolor
|
||||
if bgcolor is not None:
|
||||
self.bgcolor = bgcolor
|
||||
return self.fgcolor, self.bgcolor
|
||||
|
||||
def _printchar(self, char, invert=False, recurse=False):
|
||||
s = self._getstate()
|
||||
self._get_char(char, recurse)
|
||||
if self.glyph is None:
|
||||
return # All done
|
||||
char_height = self.char_height
|
||||
char_width = self.char_width
|
||||
|
||||
div, mod = divmod(char_width, 8)
|
||||
gbytes = div + 1 if mod else div # No. of bytes per row of glyph
|
||||
device = self.device
|
||||
fgcolor = self.bgcolor if invert else self.fgcolor
|
||||
bgcolor = self.fgcolor if invert else self.bgcolor
|
||||
usd = self.usd
|
||||
drow = s.text_row # Destination row
|
||||
wcol = s.text_col # Destination column of character start
|
||||
for srow in range(char_height): # Source row
|
||||
for scol in range(char_width): # Source column
|
||||
# Destination column: add/subtract writer column
|
||||
if usd:
|
||||
dcol = wcol - scol
|
||||
else:
|
||||
dcol = wcol + scol
|
||||
gbyte, gbit = divmod(scol, 8)
|
||||
if gbit == 0: # Next glyph byte
|
||||
data = self.glyph[srow * gbytes + gbyte]
|
||||
pixel = fgcolor if data & (1 << (7 - gbit)) else bgcolor
|
||||
device.pixel(dcol, drow, pixel)
|
||||
drow += -1 if usd else 1
|
||||
if drow >= self.screenheight or drow < 0:
|
||||
break
|
||||
s.text_col += -char_width if usd else char_width
|
||||
self.cpos += 1
|
||||
|
||||
class Label():
|
||||
def __init__(self, writer, row, col, text, invert=False):
|
||||
self.writer = writer
|
||||
self.row = row
|
||||
self.col = col
|
||||
self.invert = invert
|
||||
if isinstance(text, int):
|
||||
self.length = text
|
||||
self.text = ''
|
||||
else:
|
||||
self.length = writer.stringlen(text)
|
||||
self.text = text
|
||||
if not isinstance(self, Field):
|
||||
self.show()
|
||||
|
||||
def show(self):
|
||||
wri = self.writer
|
||||
dev = wri.device
|
||||
Writer.set_textpos(dev, self.row, self.col)
|
||||
wri.printstring(self.text, self.invert)
|
||||
|
||||
class Field(Label):
|
||||
def __init__(self, writer, row, col, max_text, border=False):
|
||||
super().__init__(writer, row, col, max_text, False)
|
||||
self.border = border
|
||||
|
||||
def value(self, text, invert=False):
|
||||
self.text = text
|
||||
self.invert = invert
|
||||
self.show()
|
||||
|
||||
def show(self):
|
||||
wri = self.writer
|
||||
dev = wri.device
|
||||
if wri._getstate().usd:
|
||||
row = dev.height - self.row - wri.height()
|
||||
col = dev.width - self.col - self.length
|
||||
else:
|
||||
row = self.row
|
||||
col = self.col
|
||||
dev.fill_rect(col, row, self.length, wri.height(), wri.bgcolor)
|
||||
if self.border:
|
||||
dev.rect(col - 2, row - 2, self.length + 4, wri.height() + 4, wri.fgcolor)
|
||||
super().show()
|
|
@ -0,0 +1,56 @@
|
|||
# ssd1306_test.py Demo pogram for rendering arbitrary fonts to an SSD1306 OLED display.
|
||||
|
||||
# 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.
|
||||
|
||||
|
||||
# https://learn.adafruit.com/monochrome-oled-breakouts/wiring-128x32-spi-oled-display
|
||||
# https://www.proto-pic.co.uk/monochrome-128x32-oled-graphic-display.html
|
||||
|
||||
# V0.3 13th Aug 2018
|
||||
|
||||
import machine
|
||||
from ssd1306_setup import WIDTH, HEIGHT, setup
|
||||
from writer import Writer
|
||||
|
||||
# Font
|
||||
import freesans20
|
||||
|
||||
def test(use_spi=False):
|
||||
ssd = setup(use_spi) # Create a display instance
|
||||
rhs = WIDTH -1
|
||||
ssd.line(rhs - 20, 0, rhs, 20, 1)
|
||||
square_side = 10
|
||||
ssd.fill_rect(rhs - square_side, 0, square_side, square_side, 1)
|
||||
|
||||
wri = Writer(ssd, freesans20)
|
||||
Writer.set_textpos(ssd, 0, 0) # verbose = False to suppress console output
|
||||
wri.printstring('Sunday\n')
|
||||
wri.printstring('12 Aug 2018\n')
|
||||
wri.printstring('10.30am')
|
||||
ssd.show()
|
||||
|
||||
print('Test assumes a 128*64 (w*h) display. Edit WIDTH and HEIGHT in ssd1306_setup.py for others.')
|
||||
print('Device pinouts are comments in ssd1306_setup.py.')
|
||||
print('Issue:')
|
||||
print('writer_demo.test() for an I2C connected device.')
|
||||
print('writer_demo.test(True) for an SPI connected device.')
|
|
@ -1,5 +1,6 @@
|
|||
# writer.py Implements the Writer class.
|
||||
# V0.2 Peter Hinch Dec 2016
|
||||
# writer_minimal.py Implements the Writer class.
|
||||
# Minimal version for SSD1306
|
||||
# V0.22 Peter Hinch 3rd Jan 2018: Supports new SSD1306 driver.
|
||||
|
||||
# The MIT License (MIT)
|
||||
#
|
||||
|
@ -27,8 +28,9 @@
|
|||
# Multiple Writer instances may be created, each rendering a font to the
|
||||
# same Display object.
|
||||
|
||||
import framebuf
|
||||
|
||||
class Writer(object):
|
||||
class Writer():
|
||||
text_row = 0 # attributes common to all Writer instances
|
||||
text_col = 0
|
||||
row_clip = False # Clip or scroll when screen full
|
||||
|
@ -44,12 +46,16 @@ class Writer(object):
|
|||
cls.row_clip = row_clip
|
||||
cls.col_clip = col_clip
|
||||
|
||||
def __init__(self, device, font):
|
||||
super().__init__()
|
||||
def __init__(self, device, font, verbose=True):
|
||||
self.device = device
|
||||
self.font = font
|
||||
# Allow to work with any font mapping
|
||||
if font.hmap():
|
||||
raise OSError('Font must be vertically mapped')
|
||||
self.map = framebuf.MONO_HMSB if font.reverse() else framebuf.MONO_HLSB
|
||||
else:
|
||||
raise ValueError('Font must be horizontally mapped.')
|
||||
if verbose:
|
||||
print('Orientation: {} Reversal: {}'.format('horiz' if font.hmap() else 'vert', font.reverse()))
|
||||
self.screenwidth = device.width # In pixels
|
||||
self.screenheight = device.height
|
||||
|
||||
|
@ -67,7 +73,9 @@ class Writer(object):
|
|||
for char in string:
|
||||
self._printchar(char)
|
||||
|
||||
def _printchar(self, char):
|
||||
# Method using blitting. Efficient rendering for monochrome displays.
|
||||
# Tested on SSD1306. Invert is for black-on-white rendering.
|
||||
def _printchar(self, char, invert=False):
|
||||
if char == '\n':
|
||||
self._newline()
|
||||
return
|
||||
|
@ -81,19 +89,10 @@ class Writer(object):
|
|||
return
|
||||
else:
|
||||
self._newline()
|
||||
|
||||
div, mod = divmod(char_height, 8)
|
||||
gbytes = div + 1 if mod else div # No. of bytes per column of glyph
|
||||
device = self.device
|
||||
for scol in range(char_width): # Source column
|
||||
dcol = scol + Writer.text_col # Destination column
|
||||
drow = Writer.text_row # Destination row
|
||||
for srow in range(char_height): # Source row
|
||||
gbyte, gbit = divmod(srow, 8)
|
||||
if drow >= self.screenheight:
|
||||
break
|
||||
if gbit == 0: # Next glyph byte
|
||||
data = glyph[scol * gbytes + gbyte]
|
||||
device.pixel(dcol, drow, data & (1 << gbit))
|
||||
drow += 1
|
||||
buf = bytearray(glyph)
|
||||
if invert:
|
||||
for i, v in enumerate(buf):
|
||||
buf[i] = 0xFF & ~ v
|
||||
fbc = framebuf.FrameBuffer(buf, char_width, char_height, self.map)
|
||||
self.device.blit(fbc, Writer.text_col, Writer.text_row)
|
||||
Writer.text_col += char_width
|
|
@ -0,0 +1,292 @@
|
|||
# ssd1306_test.py Demo pogram for rendering arbitrary fonts to an SSD1306 OLED display.
|
||||
|
||||
# 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.
|
||||
|
||||
|
||||
# https://learn.adafruit.com/monochrome-oled-breakouts/wiring-128x32-spi-oled-display
|
||||
# https://www.proto-pic.co.uk/monochrome-128x32-oled-graphic-display.html
|
||||
|
||||
# V0.3 12th Aug 2018
|
||||
|
||||
import machine
|
||||
import utime
|
||||
import uos
|
||||
from ssd1306_setup import WIDTH, HEIGHT, setup
|
||||
from writer import Writer, CWriter, Field, Label
|
||||
|
||||
# Fonts
|
||||
import freesans20
|
||||
import courier20 as fixed
|
||||
import font6 as small
|
||||
|
||||
def inverse(use_spi=False, soft=True):
|
||||
ssd = setup(use_spi, soft) # Create a display instance
|
||||
rhs = WIDTH -1
|
||||
ssd.line(rhs - 20, 0, rhs, 20, 1)
|
||||
square_side = 10
|
||||
ssd.fill_rect(rhs - square_side, 0, square_side, square_side, 1)
|
||||
|
||||
Writer.set_textpos(ssd, 0, 0) # In case previous tests have altered it
|
||||
wri = Writer(ssd, freesans20, verbose=False)
|
||||
wri.set_clip(False, False, False) # Char wrap
|
||||
wri.printstring('Sunday\n')
|
||||
wri.printstring('12 Aug 2018\n')
|
||||
wri.printstring('10.30am', True) # Inverse text
|
||||
ssd.show()
|
||||
|
||||
def scroll(use_spi=False, soft=True):
|
||||
ssd = setup(use_spi, soft) # Create a display instance
|
||||
rhs = WIDTH -1
|
||||
ssd.line(rhs - 20, 0, rhs, 20, 1)
|
||||
square_side = 10
|
||||
ssd.fill_rect(rhs - square_side, 0, square_side, square_side, 1)
|
||||
|
||||
Writer.set_textpos(ssd, 0, 0) # In case previous tests have altered it
|
||||
wri = Writer(ssd, freesans20, verbose=False)
|
||||
wri.set_clip(False, False, False) # Char wrap
|
||||
wri.printstring('Sunday\n')
|
||||
wri.printstring('12 Aug 2018\n')
|
||||
wri.printstring('10.30am')
|
||||
for x in range(5):
|
||||
ssd.show()
|
||||
utime.sleep(2)
|
||||
wri.printstring('\nCount = {:2d}'.format(x))
|
||||
ssd.show()
|
||||
utime.sleep(2)
|
||||
wri.printstring('\nDone.')
|
||||
ssd.show()
|
||||
|
||||
def usd_scroll(use_spi=False, soft=True):
|
||||
ssd = setup(use_spi, soft) # Create a display instance
|
||||
# Only CWriter can do usd
|
||||
CWriter.invert_display(ssd)
|
||||
CWriter.set_textpos(ssd, 0, 0)
|
||||
wri = CWriter(ssd, freesans20, verbose=False)
|
||||
wri.set_clip(False, False, False) # Char wrap
|
||||
|
||||
wri.printstring('Sunday\n')
|
||||
wri.printstring('12 Aug 2018\n')
|
||||
wri.printstring('10.30am')
|
||||
for x in range(5):
|
||||
ssd.show()
|
||||
utime.sleep(2)
|
||||
wri.printstring('\nCount = {:2d}'.format(x))
|
||||
ssd.show()
|
||||
utime.sleep(2)
|
||||
wri.printstring('\nDone.')
|
||||
ssd.show()
|
||||
CWriter.invert_display(ssd, False) # For subsequent tests
|
||||
|
||||
def usd(use_spi=False, soft=True):
|
||||
ssd = setup(use_spi, soft) # Create a display instance
|
||||
# Only CWriter can do usd
|
||||
CWriter.invert_display(ssd)
|
||||
CWriter.set_textpos(ssd, 0, 0)
|
||||
wri = CWriter(ssd, freesans20, verbose=False)
|
||||
wri.set_clip(False, False, False) # Char wrap
|
||||
wri.printstring('Sunday\n')
|
||||
wri.printstring('12 Aug 2018\n')
|
||||
wri.printstring('10.30am')
|
||||
ssd.show()
|
||||
CWriter.invert_display(ssd, False) # For subsequent tests
|
||||
|
||||
def rjust(use_spi=False, soft=True):
|
||||
ssd = setup(use_spi, soft) # Create a display instance
|
||||
Writer.set_textpos(ssd, 0, 0) # Previous tests may have altered it
|
||||
wri = Writer(ssd, freesans20, verbose=False)
|
||||
wri.set_clip(False, False, False) # Char wrap
|
||||
|
||||
my_str = 'Sunday\n'
|
||||
l = wri.stringlen(my_str)
|
||||
Writer.set_textpos(ssd, col = WIDTH - l)
|
||||
wri.printstring(my_str)
|
||||
|
||||
my_str = '12 Aug 2018\n'
|
||||
l = wri.stringlen(my_str)
|
||||
Writer.set_textpos(ssd, col = WIDTH - l)
|
||||
wri.printstring(my_str)
|
||||
|
||||
my_str = '10.30am'
|
||||
l = wri.stringlen(my_str)
|
||||
Writer.set_textpos(ssd, col = WIDTH - l)
|
||||
wri.printstring(my_str)
|
||||
ssd.show()
|
||||
|
||||
def fonts(use_spi=False, soft=True):
|
||||
ssd = setup(use_spi, soft) # Create a display instance
|
||||
Writer.set_textpos(ssd, 0, 0) # In case previous tests have altered it
|
||||
wri = Writer(ssd, freesans20, verbose=False)
|
||||
wri.set_clip(False, False, False) # Char wrap
|
||||
wri_f = Writer(ssd, small, verbose=False)
|
||||
wri_f.set_clip(False, False, False) # Char wrap
|
||||
wri_f.printstring('Sunday\n')
|
||||
wri.printstring('12 Aug 2018\n')
|
||||
wri.printstring('10.30am')
|
||||
ssd.show()
|
||||
|
||||
def tabs(use_spi=False, soft=True):
|
||||
ssd = setup(use_spi, soft) # Create a display instance
|
||||
Writer.set_textpos(ssd, 0, 0) # In case previous tests have altered it
|
||||
wri = Writer(ssd, fixed, verbose=False)
|
||||
wri.set_clip(False, False, False) # Char wrap
|
||||
wri.printstring('1\t2\n')
|
||||
wri.printstring('111\t22\n')
|
||||
wri.printstring('1111\t1')
|
||||
ssd.show()
|
||||
|
||||
def usd_tabs(use_spi=False, soft=True):
|
||||
ssd = setup(use_spi, soft) # Create a display instance
|
||||
CWriter.invert_display(ssd)
|
||||
CWriter.set_textpos(ssd, 0, 0)
|
||||
wri = CWriter(ssd, fixed, verbose=False)
|
||||
wri.set_clip(False, False, False) # Char wrap
|
||||
wri.printstring('1\t2\n')
|
||||
wri.printstring('111\t22\n')
|
||||
wri.printstring('1111\t1')
|
||||
ssd.show()
|
||||
CWriter.invert_display(ssd, False) # For subsequent tests
|
||||
|
||||
def wrap(use_spi=False, soft=True):
|
||||
ssd = setup(use_spi, soft) # Create a display instance
|
||||
Writer.set_textpos(ssd, 0, 0) # In case previous tests have altered it
|
||||
wri = Writer(ssd, freesans20, verbose=False)
|
||||
wri.set_clip(False, False, True) # Word wrap
|
||||
wri.printstring('the quick brown fox jumps over')
|
||||
ssd.show()
|
||||
|
||||
def fields(use_spi=False, soft=True):
|
||||
ssd = setup(use_spi, soft) # Create a display instance
|
||||
Writer.set_textpos(ssd, 0, 0) # In case previous tests have altered it
|
||||
wri = Writer(ssd, fixed, verbose=False)
|
||||
wri.set_clip(False, False, False)
|
||||
textfield = Field(wri, 0, 2, 'longer', False)
|
||||
numfield = Field(wri, 25, 2, '99.99', True)
|
||||
countfield = Field(wri, 0, 90, '1', False)
|
||||
n = 1
|
||||
for s in ('short', 'longer', '1', ''):
|
||||
textfield.value(s)
|
||||
numfield.value('{:5.2f}'.format(int.from_bytes(uos.urandom(2),'little')/1000))
|
||||
countfield.value('{:1d}'.format(n))
|
||||
n += 1
|
||||
ssd.show()
|
||||
utime.sleep(2)
|
||||
textfield.value('Done', True)
|
||||
ssd.show()
|
||||
|
||||
def usd_fields(use_spi=False, soft=True):
|
||||
ssd = setup(use_spi, soft) # Create a display instance
|
||||
CWriter.invert_display(ssd)
|
||||
CWriter.set_textpos(ssd, 0, 0) # In case previous tests have altered it
|
||||
wri = CWriter(ssd, fixed, verbose=False)
|
||||
wri.set_clip(False, False, False)
|
||||
textfield = Field(wri, 25, 2, 'longer', False)
|
||||
numfield = Field(wri, 2, 2, '99.99', True)
|
||||
countfield = Field(wri, 25, 100, '1', False)
|
||||
n = 1
|
||||
for s in ('short', 'longer', '1', ''):
|
||||
textfield.value(s)
|
||||
numfield.value('{:5.2f}'.format(int.from_bytes(uos.urandom(2),'little')/1000))
|
||||
countfield.value('{:1d}'.format(n))
|
||||
n += 1
|
||||
ssd.show()
|
||||
utime.sleep(2)
|
||||
textfield.value('Done', True)
|
||||
ssd.show()
|
||||
|
||||
def multi_fields(use_spi=False, soft=True):
|
||||
ssd = setup(use_spi, soft) # Create a display instance
|
||||
Writer.set_textpos(ssd, 0, 0) # In case previous tests have altered it
|
||||
wri = Writer(ssd, small, verbose=False)
|
||||
wri.set_clip(False, False, False)
|
||||
|
||||
nfields = []
|
||||
dy = small.height() + 6
|
||||
y = 2
|
||||
col = 15
|
||||
for txt in ('X:', 'Y:', 'Z:'):
|
||||
Label(wri, y, 0, txt)
|
||||
nfields.append(Field(wri, y, col, '99.99', True))
|
||||
y += dy
|
||||
|
||||
for _ in range(10):
|
||||
for field in nfields:
|
||||
field.value('{:5.2f}'.format(int.from_bytes(uos.urandom(2),'little')/1000))
|
||||
ssd.show()
|
||||
utime.sleep(1)
|
||||
Label(wri, 0, 64, ' DONE ', True)
|
||||
ssd.show()
|
||||
|
||||
def dual(use_spi=False, soft=True):
|
||||
ssd0 = setup(False, soft) # I2C display
|
||||
ssd1 = setup(True, False) # SPI instance
|
||||
Writer.set_textpos(ssd0, 0, 0) # In case previous tests have altered it
|
||||
wri0 = Writer(ssd0, small, verbose=False)
|
||||
wri0.set_clip(False, False, False)
|
||||
Writer.set_textpos(ssd1, 0, 0) # In case previous tests have altered it
|
||||
wri1 = Writer(ssd1, small, verbose=False)
|
||||
wri1.set_clip(False, False, False)
|
||||
|
||||
nfields = []
|
||||
dy = small.height() + 6
|
||||
col = 15
|
||||
for n, wri in enumerate((wri0, wri1)):
|
||||
nfields.append([])
|
||||
y = 2
|
||||
for txt in ('X:', 'Y:', 'Z:'):
|
||||
Label(wri, y, 0, txt)
|
||||
nfields[n].append(Field(wri, y, col, '99.99', True))
|
||||
y += dy
|
||||
|
||||
for _ in range(10):
|
||||
for n, wri in enumerate((wri0, wri1)):
|
||||
for field in nfields[n]:
|
||||
field.value('{:5.2f}'.format(int.from_bytes(uos.urandom(2),'little')/1000))
|
||||
wri.device.show()
|
||||
utime.sleep(1)
|
||||
for wri in (wri0, wri1):
|
||||
Label(wri, 0, 64, ' DONE ', True)
|
||||
wri.device.show()
|
||||
|
||||
|
||||
tstr = '''Test assumes a 128*64 (w*h) display. Edit WIDTH and HEIGHT in ssd1306_setup.py for others.
|
||||
Device pinouts are comments in ssd1306_setup.py.
|
||||
All tests take two boolean args:
|
||||
use_spi = False. Set True for SPI connected device
|
||||
soft=True set False to use hardware I2C/SPI. Hardware I2C option currently fails with official SSD1306 driver.
|
||||
|
||||
Available tests:
|
||||
inverse() Show black on white text.
|
||||
scroll() Illustrate scrolling
|
||||
usd() Upside-down display.
|
||||
usd_scroll() Upside-down scroll test.
|
||||
rjust() Right justification.
|
||||
fonts() Two fonts.
|
||||
tabs() Tab stops.
|
||||
usd_tabs() Upside-down tabs.
|
||||
wrap() Word wrapping
|
||||
fields() Field test with dynamic data.
|
||||
usd_fields() Upside down fields.
|
||||
multi_fields() Fields and labels.
|
||||
dual() Test two displays on one host.'''
|
||||
|
||||
print(tstr)
|
Ładowanie…
Reference in New Issue