From 8ca8663dc956ada1e712f027955bbef4ef9b200d Mon Sep 17 00:00:00 2001 From: Kevin J Walters Date: Sat, 12 Mar 2022 21:18:31 +0000 Subject: [PATCH 1/4] Reusing bitmap if dimensions have not changed of the text. The tilegrid is also reused if bitmap has not changed. New self._prev_label_direction to allow for tilegrid properties to be set efficiently. Reusing existing bitmap needs clearing due to required use of skip_index on blit(). #166 --- adafruit_display_text/bitmap_label.py | 83 ++++++++++++++++----------- 1 file changed, 51 insertions(+), 32 deletions(-) diff --git a/adafruit_display_text/bitmap_label.py b/adafruit_display_text/bitmap_label.py index 606cb7c..f244230 100755 --- a/adafruit_display_text/bitmap_label.py +++ b/adafruit_display_text/bitmap_label.py @@ -84,11 +84,22 @@ class Label(LabelBase): configurations possibles ``LTR``-Left-To-Right ``RTL``-Right-To-Left ``UPD``-Upside Down ``UPR``-Upwards ``DWR``-Downwards. It defaults to ``LTR``""" + # This maps label_direction to TileGrid's transpose_xy, flip_x, flip_y + _DIR_MAP = { + "UPR": (True, True, False), + "DWR": (True, False, True), + "UPD": (False, True, True), + "LTR": (False, False, False), + "RTL": (False, False, False), + } + def __init__( self, font: Union[BuiltinFont, BDF, PCF], save_text: bool = True, **kwargs ) -> None: self._bitmap = None + self._tilegrid = None + self._prev_label_direction = None super().__init__(font, **kwargs) @@ -113,7 +124,7 @@ def _reset_text( line_spacing: Optional[float] = None, scale: Optional[int] = None, ) -> None: - # pylint: disable=too-many-branches, too-many-statements + # pylint: disable=too-many-branches, too-many-statements, too-many-locals # Store all the instance variables if font is not None: @@ -179,8 +190,17 @@ def _reset_text( box_x = box_x + self._padding_left + self._padding_right box_y = box_y + self._padding_top + self._padding_bottom - # Create the bitmap and TileGrid - self._bitmap = displayio.Bitmap(box_x, box_y, len(self._palette)) + # Create the Bitmap unless it can be reused + new_bitmap = None + if ( + self._bitmap is None + or self._bitmap.width != box_x + or self._bitmap.height != box_y + ): + new_bitmap = displayio.Bitmap(box_x, box_y, len(self._palette)) + self._bitmap = new_bitmap + else: + self._bitmap.fill(0) # Place the text into the Bitmap self._place_text( @@ -196,35 +216,33 @@ def _reset_text( else: label_position_yoffset = self._ascent // 2 - self._tilegrid = displayio.TileGrid( - self._bitmap, - pixel_shader=self._palette, - width=1, - height=1, - tile_width=box_x, - tile_height=box_y, - default_tile=0, - x=-self._padding_left + x_offset, - y=label_position_yoffset - y_offset - self._padding_top, - ) - - if self._label_direction == "UPR": - self._tilegrid.transpose_xy = True - self._tilegrid.flip_x = True - if self._label_direction == "DWR": - self._tilegrid.transpose_xy = True - self._tilegrid.flip_y = True - if self._label_direction == "UPD": - self._tilegrid.flip_x = True - self._tilegrid.flip_y = True - - # Clear out any items in the local_group Group, in case this is an update to - # the bitmap_label - for _ in self._local_group: - self._local_group.pop(0) - self._local_group.append( - self._tilegrid - ) # add the bitmap's tilegrid to the group + # Create the TileGrid if not created bitmap unchanged + if self._tilegrid is None or new_bitmap: + self._tilegrid = displayio.TileGrid( + self._bitmap, + pixel_shader=self._palette, + width=1, + height=1, + tile_width=box_x, + tile_height=box_y, + default_tile=0, + x=-self._padding_left + x_offset, + y=label_position_yoffset - y_offset - self._padding_top, + ) + # Clear out any items in the local_group Group, in case this is an update to + # the bitmap_label + for _ in self._local_group: + self._local_group.pop(0) + self._local_group.append( + self._tilegrid + ) # add the bitmap's tilegrid to the group + + # Set TileGrid properties based on label_direction + if self._label_direction != self._prev_label_direction: + tg = self._tilegrid + tg.transpose_xy, tg.flip_x, tg.flip_y = self._DIR_MAP[ + self._label_direction + ] # Update bounding_box values. Note: To be consistent with label.py, # this is the bounding box for the text only, not including the background. @@ -537,6 +555,7 @@ def _set_background_color(self, new_color: Optional[int]): self._palette.make_transparent(0) def _set_label_direction(self, new_label_direction: str) -> None: + self._prev_label_direction = self._label_direction self._label_direction = new_label_direction self._reset_text(text=str(self._text)) # Force a recalculation From 148131cc21e946ddb234f43c16cae2ee1e6af6d8 Mon Sep 17 00:00:00 2001 From: Kevin J Walters Date: Sat, 12 Mar 2022 21:20:55 +0000 Subject: [PATCH 2/4] Making text updates more memory/gc efficient by only splitting on tabs if a tab is present. #166 --- adafruit_display_text/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/adafruit_display_text/__init__.py b/adafruit_display_text/__init__.py index 86079bf..81c9073 100644 --- a/adafruit_display_text/__init__.py +++ b/adafruit_display_text/__init__.py @@ -283,7 +283,7 @@ def __init__( self._y_offset = self._ascent // 2 def _get_ascent_descent(self) -> Tuple[int, int]: - """ Private function to calculate ascent and descent font values """ + """Private function to calculate ascent and descent font values""" if hasattr(self.font, "ascent") and hasattr(self.font, "descent"): return self.font.ascent, self.font.descent @@ -462,4 +462,4 @@ def label_direction(self, new_label_direction: str) -> None: self._set_label_direction(new_label_direction) def _replace_tabs(self, text: str) -> str: - return self._tab_text.join(text.split("\t")) + return text if text.find("\t") < 0 else self._tab_text.join(text.split("\t")) From fd656fc36f545f0738d072f17cb72cc9be51ec21 Mon Sep 17 00:00:00 2001 From: Kevin J Walters Date: Sat, 12 Mar 2022 22:34:00 +0000 Subject: [PATCH 3/4] Bugfix for RTL label_direction which was alternating direction. #166 --- adafruit_display_text/bitmap_label.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/adafruit_display_text/bitmap_label.py b/adafruit_display_text/bitmap_label.py index f244230..f7c7ce7 100755 --- a/adafruit_display_text/bitmap_label.py +++ b/adafruit_display_text/bitmap_label.py @@ -106,9 +106,6 @@ def __init__( self._save_text = save_text self._text = self._replace_tabs(self._text) - if self._label_direction == "RTL": - self._text = "".join(reversed(self._text)) - # call the text updater with all the arguments. self._reset_text( font=font, @@ -138,8 +135,6 @@ def _reset_text( if self._save_text: # text string will be saved self._text = self._replace_tabs(text) - if self._label_direction == "RTL": - self._text = "".join(reversed(self._text)) else: self._text = None # save a None value since text string is not saved @@ -205,7 +200,9 @@ def _reset_text( # Place the text into the Bitmap self._place_text( self._bitmap, - text, + text + if self._label_direction != "RTL" + else "".join(reversed(self._text)), self._font, self._padding_left - x_offset, self._padding_top + y_offset, From 161b99b72ea0d1726c62e8e61bc16c413b4be7d3 Mon Sep 17 00:00:00 2001 From: Kevin J Walters Date: Sat, 12 Mar 2022 23:59:35 +0000 Subject: [PATCH 4/4] Make pylint happy. #166 --- adafruit_display_text/bitmap_label.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/adafruit_display_text/bitmap_label.py b/adafruit_display_text/bitmap_label.py index f7c7ce7..7987b6a 100755 --- a/adafruit_display_text/bitmap_label.py +++ b/adafruit_display_text/bitmap_label.py @@ -39,7 +39,7 @@ from adafruit_display_text import LabelBase - +# pylint: disable=too-many-instance-attributes class Label(LabelBase): """A label displaying a string of text that is stored in a bitmap. Note: This ``bitmap_label.py`` library utilizes a :py:class:`~displayio.Bitmap` @@ -236,8 +236,8 @@ def _reset_text( # Set TileGrid properties based on label_direction if self._label_direction != self._prev_label_direction: - tg = self._tilegrid - tg.transpose_xy, tg.flip_x, tg.flip_y = self._DIR_MAP[ + tg1 = self._tilegrid + tg1.transpose_xy, tg1.flip_x, tg1.flip_y = self._DIR_MAP[ self._label_direction ]