Skip to content

Commit 35b6410

Browse files
authored
Merge pull request #167 from kevinjwalters/kjw-efficient-text-updates
Improved memory efficiency for some text updates to bitmap_label.Label
2 parents 144cbf9 + 161b99b commit 35b6410

File tree

2 files changed

+57
-41
lines changed

2 files changed

+57
-41
lines changed

adafruit_display_text/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ def __init__(
283283
self._y_offset = self._ascent // 2
284284

285285
def _get_ascent_descent(self) -> Tuple[int, int]:
286-
""" Private function to calculate ascent and descent font values """
286+
"""Private function to calculate ascent and descent font values"""
287287
if hasattr(self.font, "ascent") and hasattr(self.font, "descent"):
288288
return self.font.ascent, self.font.descent
289289

@@ -462,4 +462,4 @@ def label_direction(self, new_label_direction: str) -> None:
462462
self._set_label_direction(new_label_direction)
463463

464464
def _replace_tabs(self, text: str) -> str:
465-
return self._tab_text.join(text.split("\t"))
465+
return text if text.find("\t") < 0 else self._tab_text.join(text.split("\t"))

adafruit_display_text/bitmap_label.py

Lines changed: 55 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939

4040
from adafruit_display_text import LabelBase
4141

42-
42+
# pylint: disable=too-many-instance-attributes
4343
class Label(LabelBase):
4444
"""A label displaying a string of text that is stored in a bitmap.
4545
Note: This ``bitmap_label.py`` library utilizes a :py:class:`~displayio.Bitmap`
@@ -84,20 +84,28 @@ class Label(LabelBase):
8484
configurations possibles ``LTR``-Left-To-Right ``RTL``-Right-To-Left
8585
``UPD``-Upside Down ``UPR``-Upwards ``DWR``-Downwards. It defaults to ``LTR``"""
8686

87+
# This maps label_direction to TileGrid's transpose_xy, flip_x, flip_y
88+
_DIR_MAP = {
89+
"UPR": (True, True, False),
90+
"DWR": (True, False, True),
91+
"UPD": (False, True, True),
92+
"LTR": (False, False, False),
93+
"RTL": (False, False, False),
94+
}
95+
8796
def __init__(
8897
self, font: Union[BuiltinFont, BDF, PCF], save_text: bool = True, **kwargs
8998
) -> None:
9099

91100
self._bitmap = None
101+
self._tilegrid = None
102+
self._prev_label_direction = None
92103

93104
super().__init__(font, **kwargs)
94105

95106
self._save_text = save_text
96107
self._text = self._replace_tabs(self._text)
97108

98-
if self._label_direction == "RTL":
99-
self._text = "".join(reversed(self._text))
100-
101109
# call the text updater with all the arguments.
102110
self._reset_text(
103111
font=font,
@@ -113,7 +121,7 @@ def _reset_text(
113121
line_spacing: Optional[float] = None,
114122
scale: Optional[int] = None,
115123
) -> None:
116-
# pylint: disable=too-many-branches, too-many-statements
124+
# pylint: disable=too-many-branches, too-many-statements, too-many-locals
117125

118126
# Store all the instance variables
119127
if font is not None:
@@ -127,8 +135,6 @@ def _reset_text(
127135

128136
if self._save_text: # text string will be saved
129137
self._text = self._replace_tabs(text)
130-
if self._label_direction == "RTL":
131-
self._text = "".join(reversed(self._text))
132138
else:
133139
self._text = None # save a None value since text string is not saved
134140

@@ -179,13 +185,24 @@ def _reset_text(
179185
box_x = box_x + self._padding_left + self._padding_right
180186
box_y = box_y + self._padding_top + self._padding_bottom
181187

182-
# Create the bitmap and TileGrid
183-
self._bitmap = displayio.Bitmap(box_x, box_y, len(self._palette))
188+
# Create the Bitmap unless it can be reused
189+
new_bitmap = None
190+
if (
191+
self._bitmap is None
192+
or self._bitmap.width != box_x
193+
or self._bitmap.height != box_y
194+
):
195+
new_bitmap = displayio.Bitmap(box_x, box_y, len(self._palette))
196+
self._bitmap = new_bitmap
197+
else:
198+
self._bitmap.fill(0)
184199

185200
# Place the text into the Bitmap
186201
self._place_text(
187202
self._bitmap,
188-
text,
203+
text
204+
if self._label_direction != "RTL"
205+
else "".join(reversed(self._text)),
189206
self._font,
190207
self._padding_left - x_offset,
191208
self._padding_top + y_offset,
@@ -196,35 +213,33 @@ def _reset_text(
196213
else:
197214
label_position_yoffset = self._ascent // 2
198215

199-
self._tilegrid = displayio.TileGrid(
200-
self._bitmap,
201-
pixel_shader=self._palette,
202-
width=1,
203-
height=1,
204-
tile_width=box_x,
205-
tile_height=box_y,
206-
default_tile=0,
207-
x=-self._padding_left + x_offset,
208-
y=label_position_yoffset - y_offset - self._padding_top,
209-
)
210-
211-
if self._label_direction == "UPR":
212-
self._tilegrid.transpose_xy = True
213-
self._tilegrid.flip_x = True
214-
if self._label_direction == "DWR":
215-
self._tilegrid.transpose_xy = True
216-
self._tilegrid.flip_y = True
217-
if self._label_direction == "UPD":
218-
self._tilegrid.flip_x = True
219-
self._tilegrid.flip_y = True
220-
221-
# Clear out any items in the local_group Group, in case this is an update to
222-
# the bitmap_label
223-
for _ in self._local_group:
224-
self._local_group.pop(0)
225-
self._local_group.append(
226-
self._tilegrid
227-
) # add the bitmap's tilegrid to the group
216+
# Create the TileGrid if not created bitmap unchanged
217+
if self._tilegrid is None or new_bitmap:
218+
self._tilegrid = displayio.TileGrid(
219+
self._bitmap,
220+
pixel_shader=self._palette,
221+
width=1,
222+
height=1,
223+
tile_width=box_x,
224+
tile_height=box_y,
225+
default_tile=0,
226+
x=-self._padding_left + x_offset,
227+
y=label_position_yoffset - y_offset - self._padding_top,
228+
)
229+
# Clear out any items in the local_group Group, in case this is an update to
230+
# the bitmap_label
231+
for _ in self._local_group:
232+
self._local_group.pop(0)
233+
self._local_group.append(
234+
self._tilegrid
235+
) # add the bitmap's tilegrid to the group
236+
237+
# Set TileGrid properties based on label_direction
238+
if self._label_direction != self._prev_label_direction:
239+
tg1 = self._tilegrid
240+
tg1.transpose_xy, tg1.flip_x, tg1.flip_y = self._DIR_MAP[
241+
self._label_direction
242+
]
228243

229244
# Update bounding_box values. Note: To be consistent with label.py,
230245
# this is the bounding box for the text only, not including the background.
@@ -537,6 +552,7 @@ def _set_background_color(self, new_color: Optional[int]):
537552
self._palette.make_transparent(0)
538553

539554
def _set_label_direction(self, new_label_direction: str) -> None:
555+
self._prev_label_direction = self._label_direction
540556
self._label_direction = new_label_direction
541557
self._reset_text(text=str(self._text)) # Force a recalculation
542558

0 commit comments

Comments
 (0)