bitmap_label losing direction
TerryCornall opened this issue ยท 6 comments
Hi!
I'm using adafruit-circuitpython-bundle-7.x-mpy-20220507.zip with Circuitpython adafruit-circuitpython-feather_m4_express-en_US-7.2.5.uf2
It's running on an Adafruit feather m4 express with a 2.7" Adafruit Sharp Memory display. (Lovely rig, BTW works very well other than this little issue)
I noticed an issue with adafruit_display_text.bitmap_label just recently where despite the label_direction being set to 'UPR' the label would reset to 'LTR'
After chasing thru my code and making sure I wasn't resetting it to LTR myself, I tried using adafruit_display_text.label rather than a bitmap_label and the problem went away.
Here's a cut-down version (original is waaaaay too big) of the code and it exhibits the same issues.
At first, it appears to work and the label is indeed upwards but if I tell it again that its label_direction is 'UPR' (see down bottom of code marked by ####### )
it suddenly goes LTR orientation and stays that way, despite reporting UPR. It doesn't matter if you do this every cycle or just once, it stays broken.
If I switch to using adafruit_display_text.label rather than a bitmap_label the problem doesn't happen.
Thanks!
from adafruit_display_text.bitmap_label import Label #use this instead of adafruit_display_text.label.Label
#from adafruit_display_text.label import Label #no, use this because bitmap_label loses orientation sometimes
import time
import sharpdisplay
import displayio
import framebufferio
import board
from adafruit_bitmap_font import bitmap_font
class sharp_display():
def __init__(self):
self.spi = board.SPI()
self.disp_cs_pin = board.D4 #D4 is on same side as the SCK, MO, 3,3V, etc so use that
self.disp_w = 400
self.disp_h = 240
self.disp_ncolrs = 2
self.rotation = 180
self.framebuffer = sharpdisplay.SharpMemoryFramebuffer(self.spi, self.disp_cs_pin, self.disp_w, self.disp_h)
self.display = framebufferio.FramebufferDisplay(self.framebuffer, rotation=self.rotation,
auto_refresh=True)
self.font = bitmap_font.load_font("fonts/LeagueSpartan-Bold-16.bdf") #big, use scale 1 or 2
self.palette = displayio.Palette(2)
self.palette[0] = 0xFFFFFF #so a color of FFFFFF puts a 0 makes display show black
self.palette[1] = 0x000000 #A value of 0 puts 1 into bitmap. White
self.page0 = displayio.Group()
self.bmp0 = displayio.Bitmap(self.disp_w, self.disp_h, self.disp_ncolrs)
self.tg0 = displayio.TileGrid(self.bmp0,pixel_shader=self.palette) #need a tilegrid for bmp0
self.labelStatus = Label(font=self.font, background_tight=True, padding_left=0, padding_top =0,
text="DON'T PANIC",
color =0, line_spacing=0.7,
background_color=0xFFFFFF, #color, not palette index.
label_direction = 'UPR', #oooh, a direction!
scale=1,
anchored_position=(0, self.display.height),
anchor_point=(0,1), #bottom left because of the UPR direction
#LTR-Left-To-Right RTL-Right-To-Left TTB-Top-To-Bottom UPR-Upwards DWR-Downwards.
# It defaults to LTR
save_text=True #if you don't make this true it gives grief when changing scale or direction?
)
self.page0.append(self.tg0) #attach the tilegroup with bitmap 0 to page0
self.page0.append(self.labelStatus) #
self.display.show(self.page0) #show me
############## here's the problem
self.labelStatus.label_direction = 'UPR' #Telling it again what it's dir is apparently breaks it
#main code
displayio.release_displays() #Do this to get display away from CircuitPython
app = sharp_display()
print('Testing bitmap_label')
first_time = True
while True:
time.sleep(1) #at first the label is upwards (UPR)
app.labelStatus.text='OK, PANIC' # but when I change the text it becomes LTR
time.sleep(1)
while True: #stop Circuitpython stealing the display back
time.sleep(1)
Thanks for reporting this and sharing the pared down reproducer code.
My guess is we have somewhere inside of bitmap_label where it's not correctly checking and using the direction setting. I'll look into this over the upcoming weekend and see if I can pin it down if no one else gets to it sooner.
No worries. Thanks for the great work!
Hello! ๐โโฌ ๐โโฌ
If a fix is still needed for this bug, I think I found the problem.
The class in bitmap_label
is saving 2 values, the current _label_direction
, and the previous _prev_label_direction
,
probably for avoiding too many text manipulations, if unnecessary.
The problem is when someone sets the label_direction
to the same value twice in a row, like in the code above:
self.labelStatus = Label(font=self.font, background_tight=True, padding_left=0, padding_top =0,
......
label_direction = 'UPR', #oooh, a direction!
......
############## here's the problem
self.labelStatus.label_direction = 'UPR' #Telling it again what it's dir is apparently breaks it
_label_direction
and _prev_label_direction
will have the same value.
That means when the text value is changed, and the _reset_text()
function is called, this portion of the code (lines 234-239) will do nothing, and the label will get the defaul orientation (LTR).
# Set TileGrid properties based on label_direction
if self._label_direction != self._prev_label_direction:
tg1 = self._tilegrid
tg1.transpose_xy, tg1.flip_x, tg1.flip_y = self._DIR_MAP[
self._label_direction
]
I reproduced this bug on both Pyportal Titano, and the PyGamer boards. I could only do a fix on the PyGamer though, for the Titano I would have had to recompile CircuitPython without the frozen module ๐
The fix I found was to add a check in the _set_label_direction
function (line 549), and only change the class values if the new one is different.
def _set_label_direction(self, new_label_direction: str) -> None:
if self._label_direction != new_label_direction:
self._prev_label_direction = self._label_direction
self._label_direction = new_label_direction
self._reset_text(text=str(self._text)) # Force a recalculation
Please let me know if this looks right to you! ๐ฑ @FoamyGuy
@snkYmkrct Thanks for looking further into this and submitting the fix!! I'll try it out today.
I could only do a fix on the PyGamer though, for the Titano I would have had to recompile CircuitPython without the frozen module
There is A nifty trick for this type of situation where you want to test a library that is frozen in to a build. If you put the library files in the root of the CIRCUITPY drive it will override the frozen in one allowing you to test your custom one. So the structure would be:
CIRCUITPY/adafruit_display_text/
instead of the more normal:
CIRCUITPY/lib/adafruit_display_text/
The one in the root gets precedence, even over the frozen in library if there is one.