micropython-font-to-py/writer/WRITER.md

308 wiersze
13 KiB
Markdown
Czysty Zwykły widok Historia

2018-08-14 16:22:21 +00:00
# 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).
Basic support is for scrolling text display using multiple fonts. The
`writer_gui` module provides optional extensions for user interface objects
displayed at arbitrary locations on screen.
2018-08-14 16:22:21 +00:00
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 (from writer_gui.py).
2018-08-14 16:22:21 +00:00
# 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 writer_gui module](./WRITER.md#3-the-writer_gui-module)
2018-08-14 16:22:21 +00:00
3.1 [The Label class](./WRITER.md#31-the-label-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. `writer_gui.py` Provides optional GUI objects.
3. `ssd1306_setup.py` Hardware initialisation for SSD1306. Requires the
2018-08-14 16:22:21 +00:00
official [SSD1306 driver](https://github.com/micropython/micropython/blob/master/drivers/display/ssd1306.py).
4. `writer_demo.py` Demo using a 128*64 SSD1306 OLED display. Import to see
2018-08-14 16:22:21 +00:00
usage information.
5. `writer_tests.py` Test/demo scripts. Import to see usage information.
6. `writer_minimal.py` A minimal version for highly resource constrained
2018-08-14 16:22:21 +00:00
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. A color value is an integer whose interpretation is dependent on the
display hardware and device driver.
2018-08-14 16:22:21 +00:00
### 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 following args:
2018-08-14 16:22:21 +00:00
1. `device` The hardware device driver instance for the screen in use.
2. `font` A Python font instance.
3. `fgcolor=None` Foreground color. If `None` a monochrome display is assumed.
4. `bgcolor=None` Background color. If `None` a monochrome display is assumed.
5. `verbose=True` If `True` the constructor emits console printout.
2018-08-14 16:22:21 +00:00
### 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 one is `None` that value is left unchanged. If both
are `None` the constructor defaults are restored. Constructor defaults are
1 and 0 for monochrome displays (`Writer`). Returns foreground
2018-08-14 16:22:21 +00:00
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. The writer_gui module
2018-08-14 16:22:21 +00:00
This supports user interface objects whose text components are drawn using the
`Writer` or `CWriter` classes. Upside down rendering is not supported: attempts
to specify it will produce unexpected results.
The objects are drawn at specific locations on screen and are incompatible with
the display of scrolling text: they are therefore not intended for use with the
writer's `printstring` method.
2018-08-14 16:22:21 +00:00
## 3.1 The Label class
This supports applications where text is to be rendered at specific screen
locations.
2018-08-14 16:22:21 +00:00
Text can be static or dynamic. In the case of dynamic text the background is
cleared to ensure that short strings can cleanly replace longer ones.
2018-08-14 16:22:21 +00:00
Labels can be displayed with an optional single pixel border.
2018-08-14 16:22:21 +00:00
Colors are handled flexibly. By default the colors used are those of the
`Writer` instance, however they can be changed dynamically, for example to warn
of overrange values.
2018-08-14 16:22:21 +00:00
Constructor args:
2018-08-14 16:22:21 +00:00
1. `writer` The `Writer` instance (font and screen) to use.
2. `row` Location on screen.
3. `col`
4. `text` If a string is passed it is displayed: typically used for static
text. If an integer is passed it is interpreted as the maximum text length
in pixels; typically obtained from `writer.stringlen('-99.99')`. Nothing is
dsplayed until `.value()` is called. Intended for dynamic text fields.
5. `invert=False` Display in inverted or normal style.
6. `fgcolor=None` Optionally override the `Writer` colors.
7. `bgcolor=None`
8. `bordercolor=False` If `False` no border is displayed. If `None` a border
is shown in the `Writer` forgeround color. If a color is passed, it is used.
2018-08-14 16:22:21 +00:00
The constructor displays the string at the required location.
2018-08-14 16:22:21 +00:00
Methods:
1. `value` Redraws the label. This takes the following args:
1. `text=None` The text to display. If `None` displays last value.
2. ` invert=False` If true, show inverse text.
3. `fgcolor=None` Foreground color: if `None` the `Writer` default is used.
4. `bgcolor=None` Background color, as per foreground.
5. `bordercolor=None` As per above except that if `False` is passed, no
border is displayed. This clears a previously drawn border.
Returns the current text string.
2. `show` No args. (Re)draws the label. For future/subclass use.
2018-08-14 16:22:21 +00:00
# 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)