kopia lustrzana https://github.com/peterhinch/micropython-font-to-py
font_to_py.py Add --charset_file option.
rodzic
32cdb86fed
commit
2955368b22
|
@ -0,0 +1 @@
|
|||
ЀЁЂЃЄЅІЇЈЉЊЋЌЍЎЏАБВГДЕЖЗИЙКЛМНОПРС
|
|
@ -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.')
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
Ładowanie…
Reference in New Issue