Skip to content

Commit f23910c

Browse files
committed
Breakout blit function, improve handling of builtin builtin bitmap.blit, add back kwargs passing to self Group instance
1 parent 4bab6cf commit f23910c

File tree

2 files changed

+106
-61
lines changed

2 files changed

+106
-61
lines changed

adafruit_display_text/bitmap_label.py

Lines changed: 95 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -112,14 +112,18 @@ def __init__(
112112
anchored_position=None,
113113
save_text=True, # can reduce memory use if save_text = False
114114
scale=1,
115+
**kwargs,
115116
):
116117

117118
# instance the Group
118-
# self Group will contain a single local_group which contains one TileGrid which contains
119-
# the text bitmap
119+
# self Group will contain a single local_group which contains a Group (self.local_group)
120+
# which contains a TileGrid (self.tilegrid) which contains the text bitmap (self.bitmap)
120121
super().__init__(
121-
max_size=1, x=x, y=y,
122-
) # this will include any arguments, including scale
122+
max_size=1, x=x, y=y, scale=1, **kwargs,
123+
)
124+
# the self group scale should always remain at 1, the self.local_group will
125+
# be used to set the scale
126+
# **kwargs will pass any additional arguments provided to the Label
123127

124128
self.local_group = displayio.Group(
125129
max_size=1, scale=scale
@@ -418,18 +422,14 @@ def _place_text(
418422
yposition,
419423
text_palette_index=1,
420424
background_palette_index=0,
421-
print_only_pixels=True, # print_only_pixels = True: only update the bitmap where the glyph
422-
# pixel color is > 0. This is especially useful for script fonts where glyph
423-
# bounding boxes overlap
424-
# Set `print_only_pixels=False` to write all pixels
425+
skip_index=0, # set to None to write all pixels, other wise skip this palette index
426+
# when copying glyph bitmaps (this is important for slanted text
427+
# where rectangulary glyph boxes overlap)
425428
):
426429
# placeText - Writes text into a bitmap at the specified location.
427430
#
428431
# Note: scale is pushed up to Group level
429432

430-
bitmap_width = bitmap.width
431-
bitmap_height = bitmap.height
432-
433433
x_start = xposition # starting x position (left margin)
434434
y_start = yposition
435435

@@ -472,58 +472,94 @@ def _place_text(
472472
) # for type BuiltinFont, this creates the x-offset in the glyph bitmap.
473473
# for BDF loaded fonts, this should equal 0
474474

475-
try:
476-
bitmap.blit(
477-
xposition + my_glyph.dx,
478-
yposition - my_glyph.height - my_glyph.dy,
479-
my_glyph.bitmap,
480-
x1=glyph_offset_x,
481-
y1=0,
482-
x2=glyph_offset_x + my_glyph.width,
483-
y2=0 + my_glyph.height,
484-
skip_index=0, # do not copy over any 0 background pixels
485-
)
486-
487-
except AttributeError:
488-
for y in range(my_glyph.height):
489-
for x in range(my_glyph.width):
490-
x_placement = x + xposition + my_glyph.dx
491-
y_placement = (
492-
y + yposition - my_glyph.height - my_glyph.dy
493-
)
494-
495-
if (bitmap_width > x_placement >= 0) and (
496-
bitmap_height > y_placement >= 0
497-
):
498-
499-
# Allows for remapping the bitmap indexes using paletteIndex
500-
# for background and text.
501-
palette_indexes = (
502-
background_palette_index,
503-
text_palette_index,
504-
)
505-
506-
this_pixel_color = palette_indexes[
507-
my_glyph.bitmap[
508-
y * my_glyph.bitmap.width
509-
+ x
510-
+ glyph_offset_x
511-
]
512-
]
513-
514-
if not print_only_pixels or this_pixel_color > 0:
515-
# write all characters if printOnlyPixels = False,
516-
# or if thisPixelColor is > 0
517-
bitmap[
518-
y_placement * bitmap_width + x_placement
519-
] = this_pixel_color
520-
elif y_placement > bitmap_height:
521-
break
475+
self._blit(
476+
bitmap,
477+
xposition + my_glyph.dx,
478+
yposition - my_glyph.height - my_glyph.dy,
479+
my_glyph.bitmap,
480+
x_1=glyph_offset_x,
481+
y_1=0,
482+
x_2=glyph_offset_x + my_glyph.width,
483+
y_2=0 + my_glyph.height,
484+
skip_index=skip_index, # do not copy over any 0 background pixels
485+
)
522486

523487
xposition = xposition + my_glyph.shift_x
524488

525489
return (left, top, right - left, bottom - top) # bounding_box
526490

491+
def _blit(
492+
self,
493+
bitmap, # target bitmap
494+
x, # target x upper left corner
495+
y, # target y upper left corner
496+
source_bitmap, # source bitmap
497+
x_1=0, # source x start
498+
y_1=0, # source y start
499+
x_2=None, # source x end
500+
y_2=None, # source y end
501+
skip_index=None, # palette index that will not be copied
502+
# (for example: the background color of a glyph)
503+
):
504+
505+
if hasattr(bitmap, "blit"): # if bitmap has a built-in blit function, call it
506+
# this function should perform its own input checks
507+
bitmap.blit(
508+
x,
509+
y,
510+
source_bitmap,
511+
x1=x_1,
512+
y1=y_1,
513+
x2=x_2,
514+
y2=y_2,
515+
skip_index=skip_index,
516+
)
517+
518+
else: # perform pixel by pixel copy of the bitmap
519+
520+
# Perform input checks
521+
522+
if x_2 is None:
523+
x_2 = source_bitmap.width
524+
if y_2 is None:
525+
y_2 = source_bitmap.height
526+
527+
# Rearrange so that x_1 < x_2 and y1 < y2
528+
if x_1 > x_2:
529+
x_1, x_2 = x_2, x_1
530+
if y_1 > y_2:
531+
y_1, y_2 = y_2, y_1
532+
533+
# Ensure that x2 and y2 are within source bitmap size
534+
x_2 = min(x_2, source_bitmap.width)
535+
y_2 = min(y_2, source_bitmap.height)
536+
537+
for y_count in range(y_2 - y_1):
538+
for x_count in range(x_2 - x_1):
539+
x_placement = x + x_count
540+
y_placement = y + y_count
541+
542+
if (bitmap.width > x_placement >= 0) and (
543+
bitmap.height > y_placement >= 0
544+
): # ensure placement is within target bitmap
545+
546+
# get the palette index from the source bitmap
547+
this_pixel_color = source_bitmap[
548+
y_1
549+
+ (
550+
y_count * source_bitmap.width
551+
) # Direct index into a bitmap array is speedier than [x,y] tuple
552+
+ x_1
553+
+ x_count
554+
]
555+
556+
if (skip_index is None) or (this_pixel_color != skip_index):
557+
bitmap[ # Direct index into a bitmap array is speedier than [x,y] tuple
558+
y_placement * bitmap.width + x_placement
559+
] = this_pixel_color
560+
elif y_placement > bitmap.height:
561+
break
562+
527563
@property
528564
def bounding_box(self):
529565
"""An (x, y, w, h) tuple that completely covers all glyphs. The
@@ -532,7 +568,7 @@ def bounding_box(self):
532568

533569
@property
534570
def scale(self):
535-
"""Set the scaling of the label"""
571+
"""Set the scaling of the label, in integer values"""
536572
return self._scale
537573

538574
@scale.setter

adafruit_display_text/label.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,23 @@ def __init__(
8080
anchor_point=None,
8181
anchored_position=None,
8282
scale=1,
83+
**kwargs
8384
):
8485
if not max_glyphs and not text:
8586
raise RuntimeError("Please provide a max size, or initial text")
8687
if not max_glyphs:
8788
max_glyphs = len(text)
8889
# add one to max_size for the background bitmap tileGrid
89-
super().__init__(max_size=1)
90-
self.local_group = displayio.Group(max_size=max_glyphs + 1, scale=scale)
90+
91+
# instance the Group
92+
# self Group will contain a single local_group which contains a Group (self.local_group)
93+
# which contains a TileGrid
94+
super().__init__(
95+
max_size=1, scale=1, **kwargs
96+
) # The self scale should always be 1
97+
self.local_group = displayio.Group(
98+
max_size=max_glyphs + 1, scale=scale
99+
) # local_group will set the scale
91100
self.append(self.local_group)
92101

93102
self.width = max_glyphs

0 commit comments

Comments
 (0)