adafruit / adafruit_circuitpython_display_text Goto Github PK
View Code? Open in Web Editor NEWLibrary to display text using displayio
License: MIT License
Library to display text using displayio
License: MIT License
When creating a text label: label
processes each character at a time with get_glyph
. If font glyphs are not preloaded, the adafruit_bitmap_font
library function get_glyph
calls the load_glyphs
command on each individual character.
The load_glyphs
function parses each line of the font file until the required glyph is found. So, if we process each character individually (like we do now), each new glyph that is encountered will require a new parsing of the font file.
I propose to perform the load_glyphs
command on the full text input string prior to entering the character loop. By performing load_glyphs
on the full input string will require a maximum of one time parsing through the font file.
When the glyphs are already loaded, this will add some time overhead due to checking if the glyphs are already present. But this checking adds only a small overhead (see snippet below from load_glyphs
).
for code_point in remaining:
if code_point in self._glyphs and self._glyphs[code_point]:
remaining.remove(code_point)
if not remaining:
return
Issue and test code outlined here: #137 (comment)
Ok, so when I pushed a release, I noticed it was failing on deploy because setup.py is missing. So it looks like we either need to create a setup.py file or to set env: - DEPLOY_PYPI="false"
in .travis.yml
so it doesn't attempt to deploy.
Not all fonts have all expected characters used to check height. Maybe add some try/except to catch this?
Adafruit CircuitPython 5.3.0 on 2020-04-29; Adafruit Circuit Playground Bluefruit with nRF52840
>>> from adafruit_bitmap_font import bitmap_font
>>> from adafruit_display_text import label
>>> font = bitmap_font.load_font("/monoMMM_5_90.bdf")
>>> my_label = label.Label(font, text="hello", color=0xFFFFFF)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "adafruit_display_text/label.py", line 122, in __init__
File "adafruit_display_text/label.py", line 264, in _update_text
File "adafruit_display_text/label.py", line 144, in _create_background_box
AttributeError: 'NoneType' object has no attribute 'height'
>>> glyph = font.get_glyph(ord("M"))
>>> type(glyph)
<class 'Glyph'>
>>> glyph = font.get_glyph(ord(" "))
>>> type(glyph)
<class 'NoneType'>
>>> glyph = font.get_glyph(ord("j"))
>>> type(glyph)
<class 'NoneType'>
>>>
in #85 we add a call to load_glyphs
inside of _update_text
and this made the label building / rendering work faster.
It looks like in some cases however this is resulting in an error when used with builtin font:
Traceback (most recent call last):
File "code.py", line 15, in <module>
File "adafruit_clue.py", line 913, in simple_text_display
File "adafruit_clue.py", line 117, in __init__
File "adafruit_clue.py", line 128, in add_text_line
File "adafruit_display_text/label.py", line 125, in __init__
File "adafruit_display_text/label.py", line 240, in _update_text
AttributeError: 'BuiltinFont' object has no attribute 'load_glyphs'
This was pointed out by a user in the #help-with-circuitpython channel on discord. They were working on the Clue Temperature and Humidity example project from here: https://learn.adafruit.com/adafruit-clue/clue-temperature-and-humidity-monitor I was able to recreate it with that project on a CLUE.
But I do suspect this issue might be more wide spread, perhaps any label that is using terminalio.FONT.
I think we could resolve this by putting the load_glyphs
call inside of an if statement checking to make sure we aren't currently using terminalio.FONT
When I create a label, and then update it's text parameter later, the text will completely disappear upon the second change.
code:
label = Label(terminalio.FONT, x=10, y=32, text="Test1", max_glyphs=5, color=0xFFFFFF)
group.append(label)
time.sleep(1)
label.text = "Test2"
time.sleep(1)
label.text = "Test3"
time.sleep(1)
label.text = "Test4"
time.sleep(1)
After "Text2" It will disappear, although, sometimes I will see "Test3" For a fraction of a second.
Perhaps I am using this wrong, in which case any help would be much appreciated!
It turns out the issue with skipping the glyphs with zero-length tilegrids results in a List index out of range error:
Traceback (most recent call last):
File "electioncal.py", line 58, in <module>
gfx.elections_cycle()
File "/home/pi/electioncal_graphics.py", line 86, in elections_cycle
self.election_name_text_line2.text, self.election_name_text.text = self.paragrapher(self.electioncal["dates"][i]["name"], 40)
File "/home/pi/.local/lib/python3.7/site-packages/adafruit_display_text/label.py", line 362, in text
self._update_text(str(new_text))
File "/home/pi/.local/lib/python3.7/site-packages/adafruit_display_text/label.py", line 292, in _update_text
self[i].position = (position_x, position_y)
File "/home/pi/.local/lib/python3.7/site-packages/displayio/group.py", line 142, in __getitem__
return self._layers[index]
IndexError: list index out of range
Perhaps a better solution would be to check the width and height of the glyph and if zero, just substitute a 1. That essentially how I was doing it as a work-around, though it's possible that may cause text alignment issues. Another option may be just putting a None
in there for face as an empty placeholder and checking for that when the text is rendered.
When setting the scale of text created with Label, the scale appears to be applied twice causing the scale to be squared.
In the test script below the word 'Scale' is printed to screen in scale=1, 2 and 3
text_scale_test.py.txt
The output txt follows, note the scale in the absolute_transform:
text_test_output.txt
Below is a photograph of the resulting image on my Pimoroni 128x128 OLED:
When using label.py
to create transparent text with color=None
the following error is received:
File "/lib/adafruit_display_text/label.py", line 105, in __init__
TypeError: color buffer must be a buffer, tuple, list, or int
Here is my input code:
from adafruit_display_text import label
...
text_area = label.Label(terminalio.FONT, text="Hello world", color=None)
The only time I envision that a Label’s color might be desired to be set to None
is when using the builtinFont where the background is done the “old way” that saves memory on the Clue.
In bitmap_label.py
we currently accommodate transparent text.
Main question: Should we accommodate transparent text color with label.py
? There are two cases where this might be used:
BuiltinFont
with the “old way” of creating the background color and using transparent text.I've not followed the recent changes to this library but somewhere since https://github.com/adafruit/Adafruit_CircuitPython_Bundle/releases/tag/20200327 an extra bitmap is created for a background feature. This is the likely candidate for the primary cause of a MemoryError
exception that now occurs using this library for the application in Adafruit Learn: CLUE Sensor Plotter in CircuitPython. An example of this exception output can be seen in the description of the second issue in Adafruit Forums: Clue_Plotter Problem.
This may affect other existing applications too. I'd guess ones with lots of text on screen, large (possibly scaled) text and/or memory tight ones are more at risk.
I'm not sure what the new bitmap is for but a decision on whether this feature should be off by default would be useful and dictate whether existing applications need testing/reviewing/changing.
Initializing a label takes about 10 seconds with a bitmap font. Here's my code:
font = bitmap_font.load_font('terminalpants.bdf')
text_area = label.Label(font, text='Hello world') # VERY SLOW ~ 10 seconds
text_area.x = 10
text_area.y = 10
display.show(text_area)
Here's the bdf font: https://github.com/pixelmasochist/terminalpants
File "pyportal.py", line 30, in <module>
ValueError: max_size must be >= 1
I think this was introduced by #57. I think what is happening is that as the text is updated, it is being shifted.
See adafruit/Adafruit_Blinka_PyPortal#11 for more details.
Currently, the label instance position is defined by x
and y
when the instance is created. Then the anchored_position
and anchor_point
setters can be used only after the instance is created.
I think it would be more intuitive if the anchor_point
and anchored_position
were considered as the "default" input parameters and that these parameters be made available when creating a label instance.
I updated my libraries last night to ones from adafruit-circuitpython-bundle-5.x-mpy-20200806.zip
. I noticed the performance improvement with moving around text but I also spotted one solitary piece of text that was misplaced slightly off screen.
I've just made a simple recreation of this, I think it's when text
is not specified or it is empty string, y
is set, and then text
is set. I am using scaled text here.
Press any key to enter the REPL. Use CTRL-D to reload.
Adafruit CircuitPython 5.3.0 on 2020-04-29; Adafruit CLUE nRF52840 Express with nRF52840
>>>
>>> import displayio, terminalio, board
>>> from adafruit_display_text.label import Label
>>> fdim = terminalio.FONT.get_bounding_box()
>>> l1 = Label(terminalio.FONT, max_glyphs=9, scale=3, color=0xff0000)
>>> l2 = Label(terminalio.FONT, text="", max_glyphs=9, scale=3, color=0x00ff00)
>>> l3 = Label(terminalio.FONT, text="Chad", max_glyphs=9, scale=3, color=0x0000ff)
>>> l1.y = l2.y = l3.y = round(240 - (3 * fdim[1] / 2))
>>> (l1.y, l2.y, l3.y)
(219, 219, 219)
>>> l2.x = 80
>>> l3.x = 160
>>> tg = displayio.Group(max_size=3)
>>> tg.append(l1)
>>> tg.append(l2)
>>> tg.append(l3)
>>> board.DISPLAY.show(tg)
>>> l1.text="Wot"
>>> l2.text="No"
>>> (l1.y, l2.y, l3.y)
(240, 240, 219)
Only l3
is correctly position, l1
and l2
are half off screen.
I see #78 which sounds like it could be in the same area?
Setting to whitespace seems to be a workaround for me, e.g. text=" "
, and might be able to re-order my code to set text
once in constructor.
fails with this error message:
Traceback (most recent call last):
File "code.py", line 136, in <module>
File "/lib/adafruit_display_text/bitmap_label.py", line 146, in __init__
File "/lib/adafruit_display_text/bitmap_label.py", line 201, in _reset_text
File "/lib/adafruit_display_text/bitmap_label.py", line 656, in anchor_point
File "/lib/adafruit_display_text/bitmap_label.py", line 672, in anchored_position
AttributeError: 'Label' object has no attribute '_bounding_box'
label is unaffected by this issue.
Currently, all tabs '\n'
are ignored in both label and bitmap_label.
actions failure with details on duplicated sections is here
We want to avoid having duplicated code if possible. One way to avoid it here will be to make a LabelBase
class in __init__.py
with the duplicated parts and extend that in the other types of labels.
It uses the old style for the backlight pin and is from a demo rev.
The base_alignment example script uses two fonts, but only one is currently checked in to the repo.
We can find a permissively licensed extra font to include so that the example can run with only files contained in the repo.
After a single character label with an empty text-attribute is defined, the label's y-attribute is incremented by 7 when the label's text-attribute is loaded with a character (TEST 1). Conversely, if the label is defined with a character in the text-attribute, the y-attribute will decrement by 7 when the text-attributed is emptied (TEST 3). In either case, the y-attribute shouldn't change. Looks like something associated with the anchor point calculation updating the y-attribute.
Adafruit CircuitPython 5.3.1 on 2020-07-13; Adafruit ItsyBitsy M4 Express with samd51g19
CircuitPython 5.x Library Bundle 20210-08-26
Test code:
from adafruit_display_text.label import Label
font_0 = terminalio.FONT # Internal font
print('CircuitPython 5.x Library Bundle 20210-08-26')
address = (12, 14)
print('adress:', address)
print()
print('TEST 0: pre-load Label text, change text later')
test_0 = Label(font_0, text='0', color=0xFFFFFF, max_glyphs=1)
test_0.x, test_0.y = address
print('x =', test_0.x, 'y=', test_0.y)
test_0.text = '1'
print('x =', test_0.x, 'y=', test_0.y)
print()
print('TEST 1: no Label text, change text later')
test_1 = Label(font_0, text='', color=0xFFFFFF, max_glyphs=1)
test_1.x, test_1.y = address
print('x =', test_1.x, 'y=', test_1.y)
test_1.text = '1'
print('x =', test_1.x, 'y=', test_1.y)
print()
print('TEST 2: no Label text, no text in change')
test_2 = Label(font_0, text='', color=0xFFFFFF, max_glyphs=1)
test_2.x, test_2.y = address
print('x =', test_2.x, 'y=', test_2.y)
test_2.text = ''
print('x =', test_2.x, 'y=', test_2.y)
print()
print('TEST 3: pre-load Label text, no text in change')
test_3 = Label(font_0, text='0', color=0xFFFFFF, max_glyphs=1)
test_3.x, test_3.y = address
print('x =', test_3.x, 'y=', test_3.y)
test_3.text = ''
print('x =', test_3.x, 'y=', test_3.y)
REPL output:
>>>
soft reboot
Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.
code.py output:
CircuitPython 5.x Library Bundle 20210-08-26
adress: (12, 14)
TEST 0: pre-load Label text, change text later
x = 12 y= 14
x = 12 y= 14
TEST 1: no Label text, change text later
x = 12 y= 14
x = 12 y= 21
TEST 2: no Label text, no text in change
x = 12 y= 14
x = 12 y= 14
TEST 3: pre-load Label text, no text in change
x = 12 y= 14
x = 12 y= 7
Press any key to enter the REPL. Use CTRL-D to reload.```
I updated my libraries (from adafruit-circuitpython-bundle-5.x-mpy-20200625
) and tried this,
Adafruit CircuitPython 5.3.0 on 2020-04-29; Adafruit CLUE nRF52840 Express with nRF52840
>>> import terminalio, displayio, board
>>> from adafruit_display_text import label
>>> text_area = label.Label(terminalio.FONT, text="Scale!", scale=5, color=0xc0c0c0)
>>> board.DISPLAY.show(text_area)
>>> text_area.anchor_point
(0, 0)
>>> text_area.anchored_position
(0, -7)
>>> text_area.anchored_position = (0, 0) ### expectation is text will be on screen at top left
The position of that text is not entirely on screen, the top is chopped off. This is presumably due to issues with a scale
which isn't the default value of 1
. Discussed this a little bit recently with @FoamyGuy in Discord.
I just tested the CLUE sensor plotter with latest libraries from the 20201020 bundle and noticed its button guide screen has the text incorrectly positioned. You can see how it should look from the image at the top of https://learn.adafruit.com/clue-sensor-plotter-circuitpython/circuitpython-sensor-plotter but now it appears with the first line saying Button Guide
half way down the screen.
I think this code reproduces the problem. Line 1
initially appears in the middle of the screen but then stays exactly where it is at lines are added. Judging by the plotter code this wasn't the behaviour of the original library with multi-line text.
Adafruit CircuitPython 5.3.1 on 2020-07-13; Adafruit CLUE nRF52840 Express with nRF52840
>>>
>>> import displayio
>>> import terminalio
>>> import board
>>> import time
>>> from adafruit_display_text.label import Label
>>> text = Label(terminalio.FONT, text="line 1", max_glyphs=200)
>>> board.DISPLAY.show(text)
>>> text.y = board.DISPLAY.height // 2
>>> for lines in range(2, 13 + 1):
... text.text = "\n".join(["Line " + str(line) for line in range(1, lines + 1)])
... time.sleep(2)
...
...
...
I just confirmed this using Label
from an older version of the library (27-Mar-2020) and the text stays centred on the screen as it grows and all the lines fit on the screen.
>>> from adafruit_display_text_20200327.label import Label
When ussing the setter for background text, the text does not show correctly. I am assuming that this applies for anchor point setter, as I was receiving complains from the code that I was testing. However I thought it was my new PR. Did not test this for anchor_point.
So sorry for not to catching this before the Refactor, but normally I do all the test with list iterations. sorry @FoamyGuy .
import terminalio
import displayio
from os import uname
if uname()[0] == 'samd51':
import board
else:
from blinka_displayio_pygamedisplay import PyGameDisplay
from adafruit_display_text import label
from adafruit_bitmap_font import bitmap_font
if uname()[0] == 'samd51':
display= board.DISPLAY
else:
display = PyGameDisplay(width=320, height=240)
splash = displayio.Group(max_size=10)
MEDIUM_FONT = bitmap_font.load_font("fonts/LibreBodoniv2002-Bold-10.bdf")
bitmap = displayio.Bitmap(4, 320, 2)
palette = displayio.Palette(2)
palette[0] = 0x004400
palette[1] = 0x00FFFF
tile_grid = displayio.TileGrid(bitmap,
pixel_shader=palette,
x=155,
y=0)
splash.append(tile_grid)
bitmap = displayio.Bitmap(320, 4, 2)
tile_grid = displayio.TileGrid(bitmap,
pixel_shader=palette,
x=0,
y=110)
splash.append(tile_grid)
text = "CircuitPython"
text_area = label.Label(MEDIUM_FONT,
text=text,
x=155,
y=155,
padding_left=10,
padding_top=10,
padding_bottom=10,
background_color = 0x990099,
padding_right=10)
splash.append(text_area)
text = "CircuitPython"
text_area = label.Label(MEDIUM_FONT,
text=text,
background_tight=True,
padding_left=10,
padding_top=10,
padding_bottom=10,
padding_right=10)
text_area.x = 155
text_area.y = 110
text_area.background_color = 0x990099
splash.append(text_area)
display.show(splash)
I have this issue, when I use the adafruit_bitmap_font library in conjunction with Adafruit_CircuitPython_Display_Text
This the program
# Write your code here :-)
import os
import board
import displayio
from adafruit_display_text.label import Label
from adafruit_bitmap_font import bitmap_font
from adafruit_st7735r import ST7735R
spi = board.SPI()
tft_cs = board.D5
tft_dc = board.D6
rst = board.D7
displayio.release_displays()
display_bus = displayio.FourWire(spi, command=tft_dc, chip_select=tft_cs, reset=rst)
display = ST7735R(display_bus, width=160, height=83, colstart=24, rowstart=1, rotation=90)
#display = ST7735R(display_bus, width=160, height=80, colstart=24, rotation=90)
# the current working directory (where this file is)
cwd = ("/"+__file__).rsplit('/', 1)[0]
fonts = [file for file in os.listdir(cwd+"/fonts/")
if (file.endswith(".bdf") and not file.startswith("._"))]
for i, filename in enumerate(fonts):
fonts[i] = cwd+"/fonts/"+filename
print(fonts)
##########################################################################
THE_FONT = fonts[0]
DISPLAY_STRING = "A multi-line-\nexample of\n font bounding!"
WRAP_CHARS = 20
##########################################################################
# Make the display context
splash = displayio.Group()
display.show(splash)
# Make a background color fill
color_bitmap = displayio.Bitmap(160, 80, 1)
color_palette = displayio.Palette(1)
color_palette[0] = 0xFFFFFF
bg_sprite = displayio.TileGrid(color_bitmap,
pixel_shader=color_palette,
x=0, y=0)
splash.append(bg_sprite)
# Load the font
font = bitmap_font.load_font(THE_FONT)
font.load_glyphs(DISPLAY_STRING.encode('utf-8'))
print(DISPLAY_STRING)
text = Label(font, text=DISPLAY_STRING)
text.x = 20
text.y = 40
text.color = 0x0
# Make a background color fill
dims = text.bounding_box
print(dims)
textbg_bitmap = displayio.Bitmap(dims[2], dims[3], 1)
textbg_palette = displayio.Palette(1)
textbg_palette[0] = 0xFF0000
textbg_sprite = displayio.TileGrid(textbg_bitmap,
pixel_shader=textbg_palette,
x=text.x+dims[0], y=text.y+dims[1])
splash.append(textbg_sprite)
splash.append(text)
board.DISPLAY.refresh_soon()
board.DISPLAY.wait_for_frame()
while True:
pass
and this is the error.
>>> import text3
['/fonts/Helvetica-Bold-16.bdf', '/fonts/Alef-Bold-18.bdf', '/fonts/Arial-12.bdf', '/fonts/Comic-Bold-18.bdf', '/fonts/Noto-18.bdf', '/fonts/Verdana-Bold-18.bdf']
A multi-line-
example of
font bounding!
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "text3.py", line 52, in <module>
File "adafruit_display_text/label.py", line 79, in __init__
File "adafruit_display_text/label.py", line 114, in _update_text
MemoryError: memory allocation failed, allocating 92 bytes
>>>
I'm getting this even when background_color is None.
File "code.py", line 50, in <module>
File "code.py", line 47, in <module>
File "adafruit_pyportal.py", line 1028, in fetch
File "adafruit_pyportal.py", line 601, in set_text
File "adafruit_display_text/label.py", line 123, in __init__
File "adafruit_display_text/label.py", line 295, in _update_text
File "adafruit_display_text/label.py", line 205, in _update_background_color
File "adafruit_display_text/label.py", line 162, in _create_background_box
MemoryError: memory allocation failed, allocating 3780 bytes
Making an issue now so that we keep this in mind. I do think we'll want to hold off on making this change at least until there is a stable release made that includes the changes to Group though so it might be a little bit until we actually need to do anything further.
displayio.Group has been updated to allow it's size to be mutable so more things can be added, and there is no need to use the max_size
any longer.
We will be able to change label.Label to make use of this and remove the max_glyphs
restriction.
This sample code illustrates the issue:
import board
import time
import terminalio
from adafruit_display_text import label
from adafruit_bitmap_font import bitmap_font
text = "Helloworld"
font = bitmap_font.load_font("fonts/Helvetica-Bold-16.bdf")
text_area = label.Label(font, text=text*5)
text_area.anchor_point = (0.75,0)
text_area.anchored_position = (190, 10)
board.DISPLAY.show(text_area)
i = 0
while True:
time.sleep(0.01)
if i % 2 == 0:
text_area.text = "Hello world1".format(i)
else:
text_area.text = "Hello\nworld {}".format(i)
i += 1
The label will move itself left until it reaches the edge of the screen.
This appears to be a rounding issue with floating point math in the anchored_position getter and setter which get called when the text is updated.
The y_offset
is currently incorrectly calculated with the inclusion of a multiple related to the quantity of newlines '\n' in the text string.
However y_offset
should be independent of the number of lines in the string, and should just be related to the glyph dimensions, since this acts as a baseline offset to the vertical center of the "M" glyph.
I observed this issue when calibrating text to the upcoming bitmap_label.py
file.
Hello, while looking into this library the first time I noticed that the display_text_simpletest.py is blank. The README.md file illustrates a simple test that I think would be great, however I would also like to suggest making one small improvement.
Currently the usage example is:
import board
import terminalio
from adafruit_display_text import label
text = "Hello world"
text_area = label.Label(terminalio.FONT, text=text)
text_area.x = 10
text_area.y = 10
board.DISPLAY.show(text_area)
Which does seem to work in my testing, however after updating the display with the text_area object the code immediately ends which leads to circuitpython displaying the message that the code is done running. My only concern is that beginners might not have the intuition to think that it is working fine but some additional control needs to be used in order for it to be visible for more than a moment, and then the beginner might be chasing down a ghost thinking it isn't working right.
I think a beginner friendly improvement would be to add a delay so that they should be able to see the output but then also see that when the code is done executing it will be replaced by the circuit python "Code done running" message.
Like so:
import board
import terminalio
from adafruit_display_text import label
from time import sleep
text = "Hello world"
text_area = label.Label(terminalio.FONT, text=text)
text_area.x = 10
text_area.y = 10
board.DISPLAY.show(text_area)
sleep(3)
Another simple option might be to put the board.DISPLAY.show call in a loop (maybe infinite like while True:
) but maybe that's not setting a great example for beginners or is otherwise adding irrelevant logic to the example.
I would be happy to make these changes and submit a pull request. I don't think I have submitted a pull request to any of your repos yet so I thought I would introduce the idea here. Perhaps there is some reason that example is currently missing or if you have any thoughts about the change please let me know.
bitmap_label will not draw text if it's set after creation instead of passing text
in the constructor
import board
import terminalio
from adafruit_display_text import bitmap_label
from adafruit_display_text import label
text = "Hello world"
# text_area = label.Label(terminalio.FONT, max_glyphs=50) # regular label does show the text afterward.
text_area = bitmap_label.Label(terminalio.FONT)
# text_area = bitmap_label.Label(terminalio.FONT, text=" ") # if we init with a space it will show the text
text_area.text = text
text_area.x = 10
text_area.y = 10
board.DISPLAY.show(text_area)
while True:
pass
I can take a look into making the bitmap_label work the same as label in this scenario. Also am curious if @kmatch98 have any ideas if you have a chance to take a look.
I have discovered this example script (it's a trimmed down example from bitmap_font):
import board
from adafruit_display_text import bitmap_label as label
from adafruit_bitmap_font import bitmap_font
display = board.DISPLAY
font_file = "fonts/LeagueSpartan-Bold-16.bdf"
text = "HELLO WORLd" # ValueError
#text = "HELLO WORLD" # works
font = bitmap_font.load_font(font_file)
color = 0xFF00FF
# Create the tet label
text_area = label.Label(font, text=text, color=color)
# Set the location
text_area.x = 20
text_area.y = 20
# Show it
display.show(text_area)
while True:
pass
When the text has any lower case letters in it the bitmap_label will raise this exception:
Traceback (most recent call last):
File "code.py", line 17, in <module>
File "/lib/adafruit_display_text/bitmap_label.py", line 124, in __init__
File "/lib/adafruit_display_text/bitmap_label.py", line 241, in _reset_text
File "/lib/adafruit_display_text/bitmap_label.py", line 437, in _place_text
File "/lib/adafruit_display_text/bitmap_label.py", line 461, in _blit
ValueError: out of range of target
The text with all upper case letters does render correctly however. label does not have the same issue, it will render both text versions fine.
I'm not sure what the root cause of this issue is, perhaps something odd within this specific font? The font is here
Tested on:
Adafruit CircuitPython 6.2.0-beta.3-36-g103632f44 on 2021-03-07; Adafruit PyPortal with samd51j20
@kmatch98 I'm interested if you have any ideas about it this if you get a moment to check it out.
I have the recent Adabox016 (Adafruit Matrix Portal) and when I try to use the simpletest.py, I get:
Traceback (most recent call last):
File "code.py", line 10, in <module>
AttributeError: 'module' object has no attribute 'DISPLAY'
I'm using the library from adafruit-circuitpython-bundle-6.x-mpy-20201030
easy text alignment based on x, y would allow for pretty UI elements!
needs adafruit/Adafruit_CircuitPython_Bitmap_Font#5
Right now only the text color can be selected, and the background color is transparent.
Being able to optionally define the background color would be great.
I discovered this when working on Blinka Displayio and looking at the circuitpython code as well, it appears a divide by zero error is happening in the background, but it's silently recovering from that. In order to avoid that, we'd like to add warnings if 0-width/height bitmaps are used, but it should be removed from here first as that would break this library.
It's being used here: https://github.com/adafruit/Adafruit_CircuitPython_Display_Text/blob/master/adafruit_display_text/label.py#L113
I believe it's also using 0-width or height later in the code as well, though I can't pinpoint the exact location.
I put a workaround in place for Blinka Displayio for now. See adafruit/Adafruit_Blinka_Displayio#27 (review) for more info.
I have two labels with different sized fonts which I would like to place next to each other along the same baseline. My solution was to place the one on the right in relation to the one on the left using the information in the left's bounding box. This is still a bit off though because the labels have different font sizes so each label has a different amount of padding at the bottom (where the descenders go).
These labels have a contrasting background color and I noticed that when I set background_tight on a label containing numerals that the padding at the bottom disappears and the bottom of the label seems to coincide with the font's baseline. Unfortunately, doing this doesn't change the bounding box. If it did, that would make laying out my numerals a lot easier. And the code would still work after changing the font, adjusting margins or possibly dragging multiple labels around with a touchscreen.
FoamyGuy helped me with a workaround that works fine in my app but this seems useful. I guess the downside is that it won't be very useful for text since a lot of it will have descenders.
Maybe its not worth the trouble? I guess this is more hacky than I originally thought and maybe it would break existing code. However, it does seem to make sense that the bounding box should move when the padding changes.
Anchoring text along a baseline (rather than or in addition to bounding rect) would be very Very very helpful. Maybe this could be indicated without breaking existing code by expressing a Label’s anchor_point as a single value or single-element tuple rather than a 2-element tuple (so it still can do left/center/right alignment, while y coord is then just the baseline, period).
As it currently stands, text bounds can vary with descenders, punctuation, etc. This makes it impossible to guarantee a consistent baseline when there are multiple Label elements that are trying to align as a well-formatted and legible unit. Also, for text that changes value, the current use of bounding rect alignment can cause Label elements to move up or down as the value changes, rather than maintaining their original baseline.
Attached image shows example of desired baseline behavior, which was approximated with some hacks. For the first two items on each line, baseline alignment is forced by using bottom alignment and applying upper() to the location strings (though none of these locations have descenders…but if any of them did, say a “j” or “g,” and were not upper() filtered, those descenders would alter the text bounds, placing the Label bottom-aligned by bounds, but with a baseline that jumps up a few pixels and Looks Bad). The third element on each line here is also bottom aligned…but with +2 added to each anchored position’s Y value…it works here because we know that a comma in this font and this size descends 2 pixels below the baseline, but that’s just a quick workaround and not going to be true for all fonts and sizes. Baseline anchoring would take care of all of that.
In order to reduce the amount of memory for displaying text, @FoamyGuy and I are developing a new "label" class that will use a bitmap instead of a group of TileGrids to store the text. Here is a proposed strategy for this new "bitmap_label" Class:
bitmap_label
Class definitionInput parameters:
text
a required parameter (Note: This will flag if someone creates a bitmap_label with no text, which doesn’t make any sense.)max_glyphs
parameter, but ignore it.Do we want to keep self._memorySaver? (Note: If so, update this to a class variable)
None
if self._memorySaver == True.Since the bitmap_label has limited edit capability after creation, minimize the instance variables that are stored
Add getters/setters for:
Getters only (or does it regenerate from scratch if this is changed?)
_memory_saver
option)Add scale capability (this should be handled in the Group)
_init_
of a bitmap_label instance:bounding_box
values.Maybe I'm incorrectly assuming the mutability of a Label? You can reassign the text, but if it is longer than the original text, then you exceed a Group limit.
Adafruit CircuitPython 4.0.0 on 2019-05-20; Adafruit PyPortal with samd51j20
>>> import terminalio
>>> from adafruit_display_text import label
>>> label = label.Label(terminalio.FONT, text="123456789")
>>> label.text = "1"
>>> label.text = "1234"
>>> label.text = "1234567"
>>> label.text = "123456789"
>>> label.text = "1234567890"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "adafruit_display_text/label.py", line 174, in text
File "adafruit_display_text/label.py", line 119, in _update_text
RuntimeError: Group full
>>>
I'm attempting to load a 16 point kanji font into Circuitpython (attached)
kanji16.bdf.zip
, but I'm encountering the following error:
Traceback (most recent call last):
File "code.py", line 78, in <module>
File "adafruit_display_text/label.py", line 90, in __init__
File "adafruit_display_text/label.py", line 98, in _update_text
AttributeError: 'NoneType' object has no attribute 'height'
I'm not sure if this is related to the font itself - is it possible for a .bdf to not include the correct glyph properties for this library? It loads correctly in FontForge.
Would be nice if the documentation of the font parameter also explicitly said something to the effect of "must include M glyph".
@FoamyGuy Here are my collection of thoughts on updates for the learn guide for adafruit_display_text\label.py
. I just realized that maybe this belongs in a separate repository with the learn guides, but I couldn't identify the location. If you know an alternate location, let me know. If you have time to review this list, please add your suggestions and then we can discuss how you want to coordinate or divvy-up any work on the learn guide.
Briefly describe differences in font typefaces: Fixed width vs variable width (proportional). We can handle both! Explain that BuiltinFont
's terminalio.FONT
can be used with a TileGrid resource-efficiently since it is a fixed-size font. (There is an open issue over in circuitpython about using TileGrid with BuiltinFont
(issue adafruit/circuitpython#2566.)
Define the baseline position (halfway up the M glyph). There is already an image in the current learn guide. Indicate that is is mostly important if you are formatting multiple lines of text and they need to align. Define ascenders/descenders, since this useful for understanding the background options.
anchor_point
and anchor_position
: reference the candy hearts example
background_tight = False
(default): Background dimensions include room for ascenders and descenders for the font, even if the text does not have any ascenders/descenders. [Note: Ascenders and descender dimensions are sampled from these letters: M, j, ' (apostrophe)]
background_tight = True
: Background dimensions are set with the minimum bounding box for the text.
padding_*
: adds (positive numbers) or subtracts (negative numbers) this many pixels from the bounding box on the specified side (_top, _bottom, _left, _right)
Performance degradation was noted by @kevinjwalters
I'm getting IndexError: str index out of range on wrapping strings with:
from adafruit_display_text import wrap_text_to_lines
print(wrap_text_to_lines("Hello World!", 5))
The recent changes in 2.6.0 have introduced an exception if the text is not set on a label when it is created, but is set later.
To reproduce:
import board
import terminalio
from adafruit_display_text import label
text = "Hello world"
text_area = label.Label(terminalio.FONT, max_glyphs=15)
text_area.x = 10
text_area.y = 10
text_area.text = text
board.DISPLAY.show(text_area)
while True:
pass
This is a version of the SimpleTest example but instead of setting the text in the Label
constructor, the text is set later.
Not setting the text
parameter causes the _boundingbox
property to be initialized to None
.
When the text
property is set later, the property setter retrieves the anchored_position
value:
@text.setter
def text(self, new_text):
current_anchored_position = self.anchored_position
This in turn uses the bounding box and assumes that it has a value rather than being None:
@property
def anchored_position(self):
"""Position relative to the anchor_point. Tuple containing x,y
pixel coordinates."""
return (
int(
self.x
+ self._boundingbox[0]
+ self._anchor_point[0] * self._boundingbox[2]
),
int(
self.y
+ self._boundingbox[1]
+ self._anchor_point[1] * self._boundingbox[3]
),
)
This raises an exception:
Traceback (most recent call last):
File "code.py", line 109, in <module>
File "adafruit_display_text/label.py", line 241, in text
File "adafruit_display_text/label.py", line 281, in anchored_position
TypeError: 'NoneType' object is not subscriptable
The workaround is to always set the text in the constructor. A quick fix could be to change the default value from None
to ""
, that way the bounding box is always created.
Using the example file display_text_background_color_padding.py
the text "none" is changed to say "text". In the process, the "text" label changes position and walks down the screen.
I think that either the getter or setter for anchored_position is not working properly.
dynamic changin' of text would be rad
It takes me to a page that says
\ SORRY /
\ /
\ This page does /
] not exist yet. [ ,'|
] [ / |
]___ ___[ ,' |
] ]\ /[ [ |: |
] ] \ / [ [ |: |
] ] ] [ [ [ |: |
] ] ]__ __[ [ [ |: |
] ] ] ]\ _ /[ [ [ [ |: |
] ] ] ] (#) [ [ [ [ :===='
] ] ]_].nHn.[_[ [ [
] ] ] HHHHH. [ [ [
] ] / `HH("N \ [ [
]__]/ HHH " \[__[
] NNN [
] N/" [
] N H [
/ N \
/ q, \
/ \
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.