adafruit / Adafruit_CircuitPython_Display_Text

Library to display text using displayio
MIT License
57 stars 38 forks source link

Should setting background_tight=True change the label's bounding box? #103

Closed endico closed 3 years ago

endico commented 3 years ago

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.

endico commented 3 years ago

I found a property of adafruit_bitmap_font.bdf called ascent which is: The number of pixels above the baseline of a typical ascender. The ascender property solves my layout problem nicely although when I try to print font.ascent i get "AttributeError: 'BDF' object has no attribute 'ascent'" https://circuitpython.readthedocs.io/projects/bitmap-font/en/latest/api.html#module-adafruit_bitmap_font.bdf

endico commented 3 years ago
import board
from adafruit_display_text import label
import displayio
from adafruit_bitmap_font import bitmap_font

display = board.DISPLAY

main_group = displayio.Group()
medium_font = bitmap_font.load_font("/fonts/Exo-SemiBold-18.bdf")
big_font = bitmap_font.load_font("/fonts/Exo-Bold-42.bdf")
# print("big_font.ascent= ", big_font.ascent)

margin = 10

left_text = label.Label(
    big_font,
    max_glyphs=6,
    text="0",
    color=0x000000,
#    background_tight=True,
    background_color=0x999999,
    anchor_point=(0.0, 0.0),
    anchored_position=(margin, margin),
)
main_group.append(left_text)

right_text = label.Label(
    medium_font,
    text="MG",
    color=0x000000,
    background_color=0x999999,
    x=0,
    y=0,
)
# Pretend to assign new value from json
#
left_text.text = "32.47"

# re-locate label based on size of new text
right_text.x = left_text.x + left_text.bounding_box[2] + margin
right_text.y = left_text.y + left_text.bounding_box[3] - right_text.bounding_box[3]
print("left_text.bounding_box= ", left_text.bounding_box)
print("right_text.bounding_box= ", right_text.bounding_box)

main_group.append(right_text)
display.show(main_group)
display.refresh()

while True:
    pass
endico commented 3 years ago

This shows what its like when left_text.background_tight=True

IMG_2620

endico commented 3 years ago

When I run the above code I expect the two labels to align at the bottom but surprisingly the baseline of the text on the right aligns with the bottom of the left's bounding box. This is more proof that the CP code knows something about baselines. Alas, it seems to be a bug. IMG_2621

endico commented 3 years ago

That doesn't happen when the text on the right label has a descender.

IMG_2622

endico commented 3 years ago

Here's the Adobe BDF spec https://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5005.BDF_Spec.pdf

endico commented 3 years ago

There are actually 3 issues here.

  1. Should the bounding box change in the case were there are no ascenders or no descenders. e.g. "123", "ooo"
  2. Expose the ascent property in adafruit_bitmap_font. Maybe it already is and my newbie self is just doing it wrong. This one solves my original problem
  3. The layout bug in my code where right_text gets laid out differently depending on whether or not there's a descender. The good news is that the baseline of some text is getting lined up with something. The bad news is that its lined up with the wrong thing. I haven't verified this yet but in line 41 it seems like the bounding box for left_text includes the padding for descenders and the one for right_text does not.
endico commented 3 years ago

That doesn't happen when the text on the right label has a descender.

IMG_2622

Oh wait, it does happen with a descender. It looks like the bottom of the Q aligns with the baseline of the label on the left. I didn't notice this at first but the bottoms of the two labels are a bit off.

kmatch98 commented 3 years ago

@endico some new features of ascent And descent were added. Will this resolve your issue with text placement?

Please see this recent pull request. https://github.com/adafruit/Adafruit_CircuitPython_Display_Text/pull/110

endico commented 3 years ago

@kmatch98 This is great. I'm now able to position the text on the right relative to the text on the left. I can tweak the position of the text on the left and the text on the right goes to the correct location without any additional edits. That's the main thing I was trying to do here. However, I notice that the bounding box still doesn't change when you toggle background_tight. I don't depend on the bonding box any more but it does seem like a bug that should probably be fixed.

I caught the end of foamyguy's #livebroadcastchat today where people were discussing Jose David M.'s pull request and that seems like the real solution. It sounds like it will let you align two labels along the baseline by setting a property. https://github.com/jposada202020/Adafruit_CircuitPython_Display_Text

Here's the way I did it with the latest CP and libraries that I installed last night.

import board
from adafruit_display_text import label
import displayio
from adafruit_bitmap_font import bitmap_font

display = board.DISPLAY

main_group = displayio.Group()
medium_font = bitmap_font.load_font("/fonts/Exo-SemiBold-18.bdf")
big_font = bitmap_font.load_font("/fonts/Exo-Bold-42.bdf")

margin = 10

left_text = label.Label(
    big_font,
    max_glyphs=6,
    text="0",
    color=0x000000,
#    background_tight=True,
    background_color=0x999999,
    anchor_point=(0.0, 0.0),
    anchored_position=(margin + 25, margin + 11),
)
main_group.append(left_text)

right_text = label.Label(
    medium_font,
    text="MQ",
    color=0x000000,
    background_color=0x999999,
    x=0,
    y=0,
)
# Pretend to assign new value from json
#
left_text.text = "32.47"

# re-locate right label based on size of new text in left label
right_text.x = left_text.x + left_text.bounding_box[2] + margin
right_text.y = left_text.y + big_font.ascent - medium_font.ascent - big_font.descent

print("left_text.bounding_box= ", left_text.bounding_box)
print("right_text.bounding_box= ", right_text.bounding_box)

main_group.append(right_text)
display.show(main_group)
display.refresh()

while True:
    pass
jposada202020 commented 3 years ago

@endico HAve you tested the new feature in the library, I would like to hear your input regarding this. Thanks

endico commented 3 years ago

It works great, thanks!

FoamyGuy commented 3 years ago

It looks like the new baseline alignment features solved the core of this issue. Closing for now. We can re-open or make a new one in the future if there is further discussion around the background_tight behavior.