font_to_py.py Add --charset_file option.

pull/16/head
Peter Hinch 2018-08-28 11:37:21 +01:00
rodzic 32cdb86fed
commit 2955368b22
6 zmienionych plików z 105 dodań i 122 usunięć

1
cyrillic_subset 100644
Wyświetl plik

@ -0,0 +1 @@
ЀЁЂЃЄЅІЇЈЉЊЋЌЍЎЏАБВГДЕЖЗИЙКЛМНОПРС

Wyświetl plik

@ -514,6 +514,11 @@ if __name__ == "__main__":
help = 'Character set. e.g. 1234567890: to restrict for a clock display.',
default = '')
parser.add_argument('-k', '--charset_file',
type = str,
help = 'File containing charset e.g. cyrillic_subset.',
default = '')
args = parser.parse_args()
if not args.infile[0].isalpha():
quit('Font filenames must be valid Python variable names.')
@ -552,10 +557,19 @@ if __name__ == "__main__":
if args.charset and (args.smallest != 32 or args.largest != 126):
print('WARNING: specified smallest and largest values ignored.')
if args.charset_file:
try:
with open(args.charset_file, 'r') as f:
cset = f.read()
except OSError:
print("Can't open", args.charset_file, 'for reading.')
sys.exit(1)
else:
cset = args.charset
print('Writing Python font file.')
if not write_font(args.outfile, args.infile, args.height, args.fixed,
args.xmap, args.reverse, args.smallest, args.largest,
args.errchar, args.charset):
args.errchar, cset):
sys.exit(1)
print(args.outfile, 'written successfully.')

Wyświetl plik

@ -20,7 +20,8 @@ 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.
containing the size of the display in pixels. Color displays should have a
bound variable `mode` holding the `framebuf` color mode.
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.

Wyświetl plik

@ -4,6 +4,10 @@ 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.
Example code and images are for 128*64 SSD1306 OLED displays.
![Image](images/IMG_2866.JPG)
@ -19,7 +23,7 @@ Right justified text.
Mixed text and graphics.
![Image](images/fields.JPG)
Labels and Fields.
Labels and Fields (from writer_gui.py).
# Contents
@ -37,9 +41,8 @@ Labels and Fields.
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. [The writer_gui module](./WRITER.md#3-the-writer_gui-module)
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)
@ -73,12 +76,13 @@ should be used: the official SSD1306 driver is not compatible with hardware I2C
## 1.2 Files
1. `writer.py` Supports `Writer` and `CWriter` classes.
2. `ssd1306_setup.py` Hardware initialisation for SSD1306. Requires the
2. `writer_gui.py` Provides optional GUI objects.
3. `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
4. `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
5. `writer_tests.py` Test/demo scripts. Import to see usage information.
6. `writer_minimal.py` A minimal version for highly resource constrained
devices.
Sample fonts:
@ -200,7 +204,8 @@ This takes the following args:
## 2.2 The CWriter class
This extends the `Writer` class by adding support for upside-down and/or color
displays.
displays. A color value is an integer whose interpretation is dependent on the
display hardware and device driver.
### 2.2.1 Static method
@ -215,64 +220,76 @@ The following static method is added:
### 2.2.2 Constructor
This takes the same args as the `Writer` 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.
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.
### 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
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
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
# 3. The writer_gui module
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.
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.
## 3.1 The Label class
This renders a fixed text string to a defined screen location.
This supports applications where text is to be rendered at specific screen
locations.
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.
Labels can be displayed with an optional single pixel border.
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.
Constructor args:
1. `writer` The `Writer` instance (font and screen) to use.
2. `row` Location on screen.
3. `col`
4. `text` Text to display
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.
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.
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.
# 4. Notes

Wyświetl plik

@ -242,6 +242,8 @@ class Writer():
self.tab = value
return self.tab
def setcolor(self, *_):
return self.fgcolor, self.bgcolor
# Writer for colour displays or upside down rendering
class CWriter(Writer):
@ -253,14 +255,24 @@ class CWriter(Writer):
Writer.state[devid] = DisplayState()
Writer.state[devid].usd = value
def __init__(self,device, font, verbose=True):
def __init__(self, device, font, fgcolor=None, bgcolor=None, verbose=True):
super().__init__(device, font, verbose)
def setcolor(self, fgcolor=None, bgcolor=None):
if bgcolor is not None: # Assume monochrome.
self.bgcolor = bgcolor
if fgcolor is not None:
self.fgcolor = fgcolor
if bgcolor is not None:
self.bgcolor = bgcolor
self.def_bgcolor = self.bgcolor
self.def_fgcolor = self.fgcolor
def setcolor(self, fgcolor=None, bgcolor=None):
if fgcolor is None and bgcolor is None:
self.fgcolor = self.def_fgcolor
self.bgcolor = self.def_bgcolor
else:
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):
@ -296,48 +308,3 @@ class CWriter(Writer):
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()

Wyświetl plik

@ -32,7 +32,8 @@ import machine
import utime
import uos
from ssd1306_setup import WIDTH, HEIGHT, setup
from writer import Writer, CWriter, Field, Label
from writer import Writer, CWriter
from writer_gui import Label
# Fonts
import freesans20
@ -179,29 +180,9 @@ def fields(use_spi=False, soft=True):
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)
textfield = Label(wri, 0, 2, wri.stringlen('longer'))
numfield = Label(wri, 25, 2, wri.stringlen('99.99'), bordercolor=None)
countfield = Label(wri, 0, 90, wri.stringlen('1'))
n = 1
for s in ('short', 'longer', '1', ''):
textfield.value(s)
@ -223,14 +204,16 @@ def multi_fields(use_spi=False, soft=True):
dy = small.height() + 6
y = 2
col = 15
width = wri.stringlen('99.99')
for txt in ('X:', 'Y:', 'Z:'):
Label(wri, y, 0, txt)
nfields.append(Field(wri, y, col, '99.99', True))
nfields.append(Label(wri, y, col, width, bordercolor=None)) # Draw border
y += dy
for _ in range(10):
for field in nfields:
field.value('{:5.2f}'.format(int.from_bytes(uos.urandom(2),'little')/1000))
value = int.from_bytes(uos.urandom(3),'little')/167722
field.value('{:5.2f}'.format(value))
ssd.show()
utime.sleep(1)
Label(wri, 0, 64, ' DONE ', True)
@ -254,13 +237,14 @@ def dual(use_spi=False, soft=True):
y = 2
for txt in ('X:', 'Y:', 'Z:'):
Label(wri, y, 0, txt)
nfields[n].append(Field(wri, y, col, '99.99', True))
nfields[n].append(Label(wri, y, col, wri.stringlen('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))
value = int.from_bytes(uos.urandom(3),'little')/167722
field.value('{:5.2f}'.format(value))
wri.device.show()
utime.sleep(1)
for wri in (wri0, wri1):
@ -284,9 +268,8 @@ 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.
fields() Label test with dynamic data.
multi_fields() More Labels.
dual() Test two displays on one host.'''
print(tstr)