adafruit/Adafruit_CircuitPython_Display_Text

bitmap_label issue with lowercase letters

FoamyGuy opened this issue · 4 comments

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.

The blit error message indicates that the code is trying to write pixels into a region outside of the target bitmap.

Maybe the target bitmap size is wrong? I'll take a look.

I think there's something strange with the typeface that is making the BDF file strange to me. I actually tried regenerating it from a .OTF file I found. The BDF file was slightly different but I think wrong in the same ways.

From your BDF file:

FONT_ASCENT 15
FONT_DESCENT 4

So, taking the maximum ascent as 15, the bitmap_label creates the bounding box size with a "top" height of 15.

Now, when decoding the "d" glyph, the height of the glyph is my_glyph.height=16, but the y-offset my_glyph.dy=0. So, when it tries to place it in the bitmap, it targets to put the upper edge at y=-1, which is out of bounds of the destination bitmap (minimum bounds x=0 and y=0).

Here's the section from BDF file for the "d" glyph (encoded as 0064). The BBX line gives the width, height, dx, dy values. So for this glyph the height is 16 and the y-offset is 0. That makes it 16 pixels above the baseline, which is actually 1 higher than the ASCENT value. Strange.

STARTCHAR 0064
ENCODING 100
SWIDTH 540 0
DWIDTH 12 0
BBX 11 16 0 0
BITMAP
00E0
00E0
00E0
00E0
00E0
00E0
00E0
1EE0
3FE0
7FE0
70E0
F0E0
70E0
7FE0
3FE0
1EE0
ENDCHAR

In looking at the typeface in fontforge, it looks like the ascenders are actually off the top. I only have rudimentary knowledge of using this tool, but it definitely looks strange to me. When I re-generated the BDF file of the same typeface with fontforge, now both the UpperCase and lowercase characters are larger than the "ASCENT" value.

Here's a look at the "d" glyph:
image

Here are some other characters that show it clipped off the top.
image

Main issue

So, I think the issue is related to your BDF file, but it's unclear to me how the font can be generated where the ascent doesn't match the glyph size and baseline positioning. Now that we're expecting the "ASCENT" and "DESCENT" values to be accurate, the bitmap_label library is going to be sensitive to these kinds of discrepancies.


For reference, here's a diagram that defines the BDF glyph size and positioning from the BDF specification:
image

Maybe this is a related existing issue with fontforge?

fontforge/fontforge#4550

Ok, I've got a proposal to clip the bitmap and give a warning. Give me a few minutes to "git-ify" it.