From 44d6aeda9a43ac541e25c23c98cd9fd16bcea506 Mon Sep 17 00:00:00 2001 From: James Carr Date: Thu, 8 Jul 2021 21:02:44 +0100 Subject: [PATCH 01/27] Raise an error if a required method if not overridden when called --- adafruit_display_text/__init__.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/adafruit_display_text/__init__.py b/adafruit_display_text/__init__.py index ad10da8..708ed27 100644 --- a/adafruit_display_text/__init__.py +++ b/adafruit_display_text/__init__.py @@ -274,8 +274,7 @@ def font(self) -> None: return self._font def _set_font(self, new_font) -> None: - # subclasses should override this - pass + raise NotImplementedError("{} MUST override '_set_font'".format(type(self))) @font.setter def font(self, new_font) -> None: @@ -362,8 +361,7 @@ def scale(self, new_scale: int) -> None: self.anchored_position = self._anchored_position # update the anchored_position def _set_text(self, new_text: str, scale: int) -> None: - # subclasses should override this - pass + raise NotImplementedError("{} MUST override '_set_text'".format(type(self))) @property def text(self) -> str: @@ -387,8 +385,9 @@ def line_spacing(self) -> float: return self._line_spacing def _set_line_spacing(self, new_line_spacing: float) -> None: - # subclass should override this. - pass + raise NotImplementedError( + "{} MUST override '_set_line_spacing'".format(type(self)) + ) @line_spacing.setter def line_spacing(self, new_line_spacing: float) -> None: From 381a890b4eb23ff7a3b97a1640a640198c1b1786 Mon Sep 17 00:00:00 2001 From: James Carr Date: Thu, 8 Jul 2021 21:13:42 +0100 Subject: [PATCH 02/27] Remove references to 'max_glyphs' from __init__ and bitmap_label, it is only used in label --- adafruit_display_text/__init__.py | 3 --- adafruit_display_text/bitmap_label.py | 6 ------ 2 files changed, 9 deletions(-) diff --git a/adafruit_display_text/__init__.py b/adafruit_display_text/__init__.py index 708ed27..d4863f3 100644 --- a/adafruit_display_text/__init__.py +++ b/adafruit_display_text/__init__.py @@ -164,8 +164,6 @@ class LabelBase(Group): :param Font font: A font class that has ``get_bounding_box`` and ``get_glyph``. Must include a capital M for measuring character size. :param str text: Text to display - :param int max_glyphs: Unnecessary parameter (provided only for direct compability - with :py:func:`~adafruit_display_text.label.Label`) :param int color: Color of all text in RGB hex :param int background_color: Color of the background, use `None` for transparent :param float line_spacing: Line spacing of text to display @@ -199,7 +197,6 @@ def __init__( x: int = 0, y: int = 0, text: str = "", - max_glyphs: int = None, color: int = 0xFFFFFF, background_color: int = None, line_spacing: float = 1.25, diff --git a/adafruit_display_text/bitmap_label.py b/adafruit_display_text/bitmap_label.py index f603fab..f6fba09 100755 --- a/adafruit_display_text/bitmap_label.py +++ b/adafruit_display_text/bitmap_label.py @@ -38,8 +38,6 @@ class Label(LabelBase): """A label displaying a string of text that is stored in a bitmap. Note: This ``bitmap_label.py`` library utilizes a bitmap to display the text. This method is memory-conserving relative to ``label.py``. - The ``max_glyphs`` parameter is ignored and is present - only for direct compatibility with label.py. For further reduction in memory usage, set ``save_text=False`` (text string will not be stored and ``line_spacing`` and ``font`` are immutable with ``save_text`` @@ -53,8 +51,6 @@ class Label(LabelBase): :param Font font: A font class that has ``get_bounding_box`` and ``get_glyph``. Must include a capital M for measuring character size. :param str text: Text to display - :param int max_glyphs: Unnecessary parameter (provided only for direct compatibility - with label.py) :param int color: Color of all text in RGB hex :param int background_color: Color of the background, use `None` for transparent :param double line_spacing: Line spacing of text to display @@ -83,8 +79,6 @@ class Label(LabelBase): # pylint: disable=unused-argument, too-many-instance-attributes, too-many-locals, too-many-arguments # pylint: disable=too-many-branches, no-self-use, too-many-statements - # Note: max_glyphs parameter is unnecessary, this is used for direct - # compatibility with label.py def __init__(self, font, **kwargs) -> None: From 60590f1540fd92dbedde04a33368c3f8e3643e34 Mon Sep 17 00:00:00 2001 From: James Carr Date: Thu, 8 Jul 2021 21:50:55 +0100 Subject: [PATCH 03/27] Refactor line_spacing --- adafruit_display_text/__init__.py | 1 + adafruit_display_text/bitmap_label.py | 13 ++++++------- adafruit_display_text/label.py | 1 - 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/adafruit_display_text/__init__.py b/adafruit_display_text/__init__.py index d4863f3..716e939 100644 --- a/adafruit_display_text/__init__.py +++ b/adafruit_display_text/__init__.py @@ -217,6 +217,7 @@ def __init__( super().__init__(x=x, y=y, scale=1) self._font = font + self._line_spacing = line_spacing self._ascent, self._descent = self._get_ascent_descent() self.palette = Palette(2) self._color = color diff --git a/adafruit_display_text/bitmap_label.py b/adafruit_display_text/bitmap_label.py index f6fba09..90a89d9 100755 --- a/adafruit_display_text/bitmap_label.py +++ b/adafruit_display_text/bitmap_label.py @@ -53,7 +53,7 @@ class Label(LabelBase): :param str text: Text to display :param int color: Color of all text in RGB hex :param int background_color: Color of the background, use `None` for transparent - :param double line_spacing: Line spacing of text to display + :param float line_spacing: Line spacing of text to display :param boolean background_tight: Set `True` only if you want background box to tightly surround text. When set to 'True' Padding parameters will be ignored. :param int padding_top: Additional pixels added to background bounding box at top @@ -116,7 +116,7 @@ def __init__(self, font, **kwargs) -> None: x=kwargs.get("x", 0), y=kwargs.get("y", 0), text=kwargs.get("text", ""), - line_spacing=kwargs.get("line_spacing", 1.25), + line_spacing=self._line_spacing, background_tight=kwargs.get("background_tight", False), padding_top=kwargs.get("padding_top", 0), padding_bottom=kwargs.get("padding_bottom", 0), @@ -228,7 +228,6 @@ def _reset_text( ) = self._text_bounding_box( self._text, self._font, - self._line_spacing, ) # calculate the box size for a tight and loose backgrounds if self._background_tight: @@ -251,7 +250,6 @@ def _reset_text( self.bitmap, self._text, self._font, - self._line_spacing, self._padding_left - x_offset, self._padding_top + y_offset, ) @@ -325,7 +323,7 @@ def _line_spacing_ypixels(font, line_spacing: float) -> int: return return_value def _text_bounding_box( - self, text: str, font, line_spacing: float + self, text: str, font ) -> Tuple[int, int, int, int, int, int]: ascender_max, descender_max = self._ascent, self._descent @@ -342,6 +340,7 @@ def _text_bounding_box( y_offset_tight = self._ascent // 2 newline = False + line_spacing = self._line_spacing for char in text: @@ -406,14 +405,13 @@ def _place_text( bitmap, text: str, font, - line_spacing: float, xposition: int, yposition: int, text_palette_index: int = 1, background_palette_index: int = 0, skip_index: int = 0, # set to None to write all pixels, other wise skip this palette index # when copying glyph bitmaps (this is important for slanted text - # where rectangulary glyph boxes overlap) + # where rectangular glyph boxes overlap) ) -> Tuple[int, int, int, int]: # placeText - Writes text into a bitmap at the specified location. # @@ -425,6 +423,7 @@ def _place_text( left = None right = x_start top = bottom = y_start + line_spacing = self._line_spacing for char in text: diff --git a/adafruit_display_text/label.py b/adafruit_display_text/label.py index bb2fd2a..85fe48b 100755 --- a/adafruit_display_text/label.py +++ b/adafruit_display_text/label.py @@ -100,7 +100,6 @@ def __init__(self, font, **kwargs) -> None: self.y = kwargs.get("y", 0) self.height = self._font.get_bounding_box()[1] - self._line_spacing = kwargs.get("line_spacing", 1.25) self._bounding_box = None self._background_tight = kwargs.get( From 9552fdc7ad38db6bcc15c178cfe175dded233e6c Mon Sep 17 00:00:00 2001 From: James Carr Date: Thu, 8 Jul 2021 21:58:30 +0100 Subject: [PATCH 04/27] Refactor background_tight --- adafruit_display_text/__init__.py | 1 + adafruit_display_text/bitmap_label.py | 4 ---- adafruit_display_text/label.py | 4 ---- 3 files changed, 1 insertion(+), 8 deletions(-) diff --git a/adafruit_display_text/__init__.py b/adafruit_display_text/__init__.py index 716e939..8c5b9a2 100644 --- a/adafruit_display_text/__init__.py +++ b/adafruit_display_text/__init__.py @@ -218,6 +218,7 @@ def __init__( self._font = font self._line_spacing = line_spacing + self._background_tight = background_tight self._ascent, self._descent = self._get_ascent_descent() self.palette = Palette(2) self._color = color diff --git a/adafruit_display_text/bitmap_label.py b/adafruit_display_text/bitmap_label.py index 90a89d9..b9b1b60 100755 --- a/adafruit_display_text/bitmap_label.py +++ b/adafruit_display_text/bitmap_label.py @@ -117,7 +117,6 @@ def __init__(self, font, **kwargs) -> None: y=kwargs.get("y", 0), text=kwargs.get("text", ""), line_spacing=self._line_spacing, - background_tight=kwargs.get("background_tight", False), padding_top=kwargs.get("padding_top", 0), padding_bottom=kwargs.get("padding_bottom", 0), padding_left=kwargs.get("padding_left", 0), @@ -138,7 +137,6 @@ def _reset_text( y: int = None, text: str = None, line_spacing: float = None, - background_tight: bool = None, padding_top: int = None, padding_bottom: int = None, padding_left: int = None, @@ -161,8 +159,6 @@ def _reset_text( self.y = y if line_spacing is not None: self._line_spacing = line_spacing - if background_tight is not None: - self._background_tight = background_tight if padding_top is not None: self._padding_top = max(0, padding_top) if padding_bottom is not None: diff --git a/adafruit_display_text/label.py b/adafruit_display_text/label.py index 85fe48b..3aae17a 100755 --- a/adafruit_display_text/label.py +++ b/adafruit_display_text/label.py @@ -102,10 +102,6 @@ def __init__(self, font, **kwargs) -> None: self.height = self._font.get_bounding_box()[1] self._bounding_box = None - self._background_tight = kwargs.get( - "background_tight", False - ) # sets padding status for text background box - # Create the two-color text palette self.palette = displayio.Palette(2) self.palette[0] = 0 From 64a7d3e506d260f172a80adce639c5c729506bdd Mon Sep 17 00:00:00 2001 From: James Carr Date: Thu, 8 Jul 2021 22:13:45 +0100 Subject: [PATCH 05/27] Refactor x & y --- adafruit_display_text/bitmap_label.py | 8 -------- adafruit_display_text/label.py | 2 -- 2 files changed, 10 deletions(-) diff --git a/adafruit_display_text/bitmap_label.py b/adafruit_display_text/bitmap_label.py index b9b1b60..9a9a9d3 100755 --- a/adafruit_display_text/bitmap_label.py +++ b/adafruit_display_text/bitmap_label.py @@ -113,8 +113,6 @@ def __init__(self, font, **kwargs) -> None: # call the text updater with all the arguments. self._reset_text( font=font, - x=kwargs.get("x", 0), - y=kwargs.get("y", 0), text=kwargs.get("text", ""), line_spacing=self._line_spacing, padding_top=kwargs.get("padding_top", 0), @@ -133,8 +131,6 @@ def __init__(self, font, **kwargs) -> None: def _reset_text( self, font=None, - x: int = None, - y: int = None, text: str = None, line_spacing: float = None, padding_top: int = None, @@ -153,10 +149,6 @@ def _reset_text( # Store all the instance variables if font is not None: self._font = font - if x is not None: - self.x = x - if y is not None: - self.y = y if line_spacing is not None: self._line_spacing = line_spacing if padding_top is not None: diff --git a/adafruit_display_text/label.py b/adafruit_display_text/label.py index 3aae17a..346c55b 100755 --- a/adafruit_display_text/label.py +++ b/adafruit_display_text/label.py @@ -96,8 +96,6 @@ def __init__(self, font, **kwargs) -> None: self._font = font self._text = None self._anchor_point = kwargs.get("anchor_point", None) - self.x = kwargs.get("x", 0) - self.y = kwargs.get("y", 0) self.height = self._font.get_bounding_box()[1] self._bounding_box = None From 889679e3c2a1e26cca6e5f492c3fe06a16f2de35 Mon Sep 17 00:00:00 2001 From: James Carr Date: Thu, 8 Jul 2021 22:31:33 +0100 Subject: [PATCH 06/27] Refactor padding --- adafruit_display_text/__init__.py | 4 ++++ adafruit_display_text/bitmap_label.py | 16 ---------------- adafruit_display_text/label.py | 4 ---- 3 files changed, 4 insertions(+), 20 deletions(-) diff --git a/adafruit_display_text/__init__.py b/adafruit_display_text/__init__.py index 8c5b9a2..e2818c4 100644 --- a/adafruit_display_text/__init__.py +++ b/adafruit_display_text/__init__.py @@ -219,6 +219,10 @@ def __init__( self._font = font self._line_spacing = line_spacing self._background_tight = background_tight + self._padding_top = padding_top + self._padding_bottom = padding_bottom + self._padding_left = padding_left + self._padding_right = padding_right self._ascent, self._descent = self._get_ascent_descent() self.palette = Palette(2) self._color = color diff --git a/adafruit_display_text/bitmap_label.py b/adafruit_display_text/bitmap_label.py index 9a9a9d3..a496e9c 100755 --- a/adafruit_display_text/bitmap_label.py +++ b/adafruit_display_text/bitmap_label.py @@ -115,10 +115,6 @@ def __init__(self, font, **kwargs) -> None: font=font, text=kwargs.get("text", ""), line_spacing=self._line_spacing, - padding_top=kwargs.get("padding_top", 0), - padding_bottom=kwargs.get("padding_bottom", 0), - padding_left=kwargs.get("padding_left", 0), - padding_right=kwargs.get("padding_right", 0), anchor_point=kwargs.get("anchor_point", None), anchored_position=kwargs.get("anchored_position", None), save_text=kwargs.get("save_text", True), @@ -133,10 +129,6 @@ def _reset_text( font=None, text: str = None, line_spacing: float = None, - padding_top: int = None, - padding_bottom: int = None, - padding_left: int = None, - padding_right: int = None, anchor_point: Tuple[float, float] = None, anchored_position: Tuple[int, int] = None, save_text: bool = None, @@ -151,14 +143,6 @@ def _reset_text( self._font = font if line_spacing is not None: self._line_spacing = line_spacing - if padding_top is not None: - self._padding_top = max(0, padding_top) - if padding_bottom is not None: - self._padding_bottom = max(0, padding_bottom) - if padding_left is not None: - self._padding_left = max(0, padding_left) - if padding_right is not None: - self._padding_right = max(0, padding_right) if anchor_point is not None: self._anchor_point = anchor_point if anchored_position is not None: diff --git a/adafruit_display_text/label.py b/adafruit_display_text/label.py index 346c55b..42baef6 100755 --- a/adafruit_display_text/label.py +++ b/adafruit_display_text/label.py @@ -110,10 +110,6 @@ def __init__(self, font, **kwargs) -> None: self._background_palette = displayio.Palette(1) self._added_background_tilegrid = False - self._padding_top = kwargs.get("padding_top", 0) - self._padding_bottom = kwargs.get("padding_bottom", 0) - self._padding_left = kwargs.get("padding_left", 0) - self._padding_right = kwargs.get("padding_right", 0) self.base_alignment = kwargs.get("base_alignment", False) self._label_direction = kwargs.get("label_direction", "LTR") From 6eb5dd0183a7a63902102552a725edbcdfb8395f Mon Sep 17 00:00:00 2001 From: James Carr Date: Thu, 8 Jul 2021 22:36:18 +0100 Subject: [PATCH 07/27] Refactor padding --- adafruit_display_text/label.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/adafruit_display_text/label.py b/adafruit_display_text/label.py index 42baef6..85a7956 100755 --- a/adafruit_display_text/label.py +++ b/adafruit_display_text/label.py @@ -45,17 +45,17 @@ class Label(LabelBase): :param bool background_tight: Set `True` only if you want background box to tightly surround text. When set to 'True' Padding parameters will be ignored. :param int padding_top: Additional pixels added to background bounding box at top. - This parameter could be negative indicating additional pixels subtracted to background - bounding box. + This parameter could be negative indicating additional pixels subtracted from the + background bounding box. :param int padding_bottom: Additional pixels added to background bounding box at bottom. - This parameter could be negative indicating additional pixels subtracted to background - bounding box. + This parameter could be negative indicating additional pixels subtracted from the + background bounding box. :param int padding_left: Additional pixels added to background bounding box at left. - This parameter could be negative indicating additional pixels subtracted to background - bounding box. + This parameter could be negative indicating additional pixels subtracted from the + background bounding box. :param int padding_right: Additional pixels added to background bounding box at right. - This parameter could be negative indicating additional pixels subtracted to background - bounding box. + This parameter could be negative indicating additional pixels subtracted from the + background bounding box. :param (float,float) anchor_point: Point that anchored_position moves relative to. Tuple with decimal percentage of width and height. (E.g. (0,0) is top left, (1.0, 0.5): is middle right.) From ff473a48d323508fb9578a5d40648b883a862ef9 Mon Sep 17 00:00:00 2001 From: James Carr Date: Thu, 8 Jul 2021 22:56:35 +0100 Subject: [PATCH 08/27] Refactor save_text --- adafruit_display_text/__init__.py | 3 --- adafruit_display_text/bitmap_label.py | 7 ++----- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/adafruit_display_text/__init__.py b/adafruit_display_text/__init__.py index e2818c4..bd1ab39 100644 --- a/adafruit_display_text/__init__.py +++ b/adafruit_display_text/__init__.py @@ -179,8 +179,6 @@ class LabelBase(Group): :param (int,int) anchored_position: Position relative to the anchor_point. Tuple containing x,y pixel coordinates. :param int scale: Integer value of the pixel scaling - :param bool save_text: Set True to save the text string as a constant in the - label structure. Set False to reduce memory use. :param bool base_alignment: when True allows to align text label to the baseline. This is helpful when two or more labels need to be aligned to the same baseline :param (int,str) tab_replacement: tuple with tab character replace information. When @@ -207,7 +205,6 @@ def __init__( padding_right: int = 0, anchor_point: Tuple[float, float] = None, anchored_position: Tuple[int, int] = None, - save_text: bool = True, # can reduce memory use if save_text = False scale: int = 1, base_alignment: bool = False, tab_replacement: Tuple[int, str] = (4, " "), diff --git a/adafruit_display_text/bitmap_label.py b/adafruit_display_text/bitmap_label.py index a496e9c..662aed7 100755 --- a/adafruit_display_text/bitmap_label.py +++ b/adafruit_display_text/bitmap_label.py @@ -80,7 +80,7 @@ class Label(LabelBase): # pylint: disable=unused-argument, too-many-instance-attributes, too-many-locals, too-many-arguments # pylint: disable=too-many-branches, no-self-use, too-many-statements - def __init__(self, font, **kwargs) -> None: + def __init__(self, font, save_text=True, **kwargs) -> None: super().__init__(font, **kwargs) @@ -94,6 +94,7 @@ def __init__(self, font, **kwargs) -> None: self._tab_replacement = kwargs.get("tab_replacement", (4, " ")) self._tab_text = self._tab_replacement[1] * self._tab_replacement[0] text = kwargs.get("text", "") + self._save_text = save_text self._text = self._tab_text.join(text.split("\t")) # Create the two-color palette @@ -117,7 +118,6 @@ def __init__(self, font, **kwargs) -> None: line_spacing=self._line_spacing, anchor_point=kwargs.get("anchor_point", None), anchored_position=kwargs.get("anchored_position", None), - save_text=kwargs.get("save_text", True), scale=kwargs.get("scale", 1), base_alignment=kwargs.get("base_alignment", False), tab_replacement=kwargs.get("tab_replacement", (4, " ")), @@ -131,7 +131,6 @@ def _reset_text( line_spacing: float = None, anchor_point: Tuple[float, float] = None, anchored_position: Tuple[int, int] = None, - save_text: bool = None, scale: int = None, base_alignment: bool = None, tab_replacement: Tuple[int, str] = None, @@ -147,8 +146,6 @@ def _reset_text( self._anchor_point = anchor_point if anchored_position is not None: self._anchored_position = anchored_position - if save_text is not None: - self._save_text = save_text if base_alignment is not None: self.base_alignment = base_alignment if tab_replacement is not None: From 31ad1213420bf1077b2ed8d2ca10083891b0867c Mon Sep 17 00:00:00 2001 From: James Carr Date: Thu, 8 Jul 2021 23:25:41 +0100 Subject: [PATCH 09/27] Refactor tab_replacement --- adafruit_display_text/__init__.py | 5 +++++ adafruit_display_text/bitmap_label.py | 13 +++---------- adafruit_display_text/label.py | 7 ++----- 3 files changed, 10 insertions(+), 15 deletions(-) diff --git a/adafruit_display_text/__init__.py b/adafruit_display_text/__init__.py index bd1ab39..d8efe66 100644 --- a/adafruit_display_text/__init__.py +++ b/adafruit_display_text/__init__.py @@ -241,6 +241,8 @@ def __init__( self.baseline = -1.0 self.base_alignment = base_alignment + self._tab_replacement = tab_replacement + self._tab_text = self._tab_replacement[1] * self._tab_replacement[0] if self.base_alignment: self._y_offset = 0 @@ -408,3 +410,6 @@ def label_direction(self, new_label_direction: str) -> None: if new_label_direction not in ["LTR", "RTL", "UPR", "DWR", "TTB"]: raise RuntimeError("Please provide a valid text direction") self._set_label_direction(new_label_direction) + + def _replace_tabs(self, text): + return self._tab_text.join(text.split("\t")) diff --git a/adafruit_display_text/bitmap_label.py b/adafruit_display_text/bitmap_label.py index 662aed7..c748afa 100755 --- a/adafruit_display_text/bitmap_label.py +++ b/adafruit_display_text/bitmap_label.py @@ -91,11 +91,9 @@ def __init__(self, font, save_text=True, **kwargs) -> None: self.local_group ) # the local_group will always stay in the self Group - self._tab_replacement = kwargs.get("tab_replacement", (4, " ")) - self._tab_text = self._tab_replacement[1] * self._tab_replacement[0] text = kwargs.get("text", "") self._save_text = save_text - self._text = self._tab_text.join(text.split("\t")) + self._text = self._replace_tabs(text) # Create the two-color palette @@ -120,7 +118,6 @@ def __init__(self, font, save_text=True, **kwargs) -> None: anchored_position=kwargs.get("anchored_position", None), scale=kwargs.get("scale", 1), base_alignment=kwargs.get("base_alignment", False), - tab_replacement=kwargs.get("tab_replacement", (4, " ")), label_direction=kwargs.get("label_direction", "LTR"), ) @@ -133,7 +130,6 @@ def _reset_text( anchored_position: Tuple[int, int] = None, scale: int = None, base_alignment: bool = None, - tab_replacement: Tuple[int, str] = None, label_direction: str = "LTR", ) -> None: @@ -148,8 +144,6 @@ def _reset_text( self._anchored_position = anchored_position if base_alignment is not None: self.base_alignment = base_alignment - if tab_replacement is not None: - self._tab_replacement = tab_replacement if label_direction is not None: self._label_direction = label_direction @@ -158,7 +152,7 @@ def _reset_text( text = self._text if self._save_text: # text string will be saved - self._text = self._tab_text.join(text.split("\t")) + self._text = self._replace_tabs(text) if self._label_direction == "RTL": self._text = "".join(reversed(self._text)) else: @@ -553,8 +547,7 @@ def _set_font(self, new_font) -> None: raise RuntimeError("font is immutable when save_text is False") def _set_text(self, new_text: str, scale: int) -> None: - new_text = self._tab_text.join(new_text.split("\t")) - self._reset_text(text=new_text, scale=self.scale) + self._reset_text(text=self._replace_tabs(new_text), scale=self.scale) def _set_background_color(self, new_color): self._background_color = new_color diff --git a/adafruit_display_text/label.py b/adafruit_display_text/label.py index 85a7956..7f74aad 100755 --- a/adafruit_display_text/label.py +++ b/adafruit_display_text/label.py @@ -82,9 +82,7 @@ def __init__(self, font, **kwargs) -> None: if not max_glyphs and not text: raise RuntimeError("Please provide a max_glyphs, or initial text") - self._tab_replacement = kwargs.get("tab_replacement", (4, " ")) - self._tab_text = self._tab_replacement[1] * self._tab_replacement[0] - text = self._tab_text.join(text.split("\t")) + text = self._replace_tabs(text) if not max_glyphs: max_glyphs = len(text) @@ -431,10 +429,9 @@ def _update_text( self._update_background_color(self._background_color) def _reset_text(self, new_text: str) -> None: - new_text = self._tab_text.join(new_text.split("\t")) try: current_anchored_position = self.anchored_position - self._update_text(str(new_text)) + self._update_text(str(self._replace_tabs(new_text))) self.anchored_position = current_anchored_position except RuntimeError as run_error: raise RuntimeError("Text length exceeds max_glyphs") from run_error From b259e6b3814ca53ffe65aa1f2bf51a622026d683 Mon Sep 17 00:00:00 2001 From: James Carr Date: Fri, 9 Jul 2021 09:03:52 +0100 Subject: [PATCH 10/27] Refactor label_direction --- adafruit_display_text/__init__.py | 17 +++++++++----- adafruit_display_text/bitmap_label.py | 27 +++++++++++---------- adafruit_display_text/label.py | 34 +++++++++++++-------------- 3 files changed, 42 insertions(+), 36 deletions(-) diff --git a/adafruit_display_text/__init__.py b/adafruit_display_text/__init__.py index d8efe66..f751390 100644 --- a/adafruit_display_text/__init__.py +++ b/adafruit_display_text/__init__.py @@ -184,9 +184,8 @@ class LabelBase(Group): :param (int,str) tab_replacement: tuple with tab character replace information. When (4, " ") will indicate a tab replacement of 4 spaces, defaults to 4 spaces by tab character - :param str label_direction: string defining the label text orientation. There are 5 - configurations possibles ``LTR``-Left-To-Right ``RTL``-Right-To-Left - ``TTB``-Top-To-Bottom ``UPR``-Upwards ``DWR``-Downwards. It defaults to ``LTR``""" + :param str label_direction: string defining the label text orientation. See the + subclass documentation for the possible values.""" # pylint: disable=unused-argument, too-many-instance-attributes, too-many-locals, too-many-arguments def __init__( @@ -401,13 +400,19 @@ def label_direction(self) -> str: return self._label_direction def _set_label_direction(self, new_label_direction: str) -> None: - # subclass should override this. - pass + raise NotImplementedError( + "{} MUST override '_set_label_direction'".format(type(self)) + ) + + def _get_valid_label_directions(self) -> Tuple[str, ...]: + raise NotImplementedError( + "{} MUST override '_get_valid_label_direction'".format(type(self)) + ) @label_direction.setter def label_direction(self, new_label_direction: str) -> None: """Set the text direction of the label""" - if new_label_direction not in ["LTR", "RTL", "UPR", "DWR", "TTB"]: + if new_label_direction not in self._get_valid_label_directions(): raise RuntimeError("Please provide a valid text direction") self._set_label_direction(new_label_direction) diff --git a/adafruit_display_text/bitmap_label.py b/adafruit_display_text/bitmap_label.py index c748afa..a8ea26f 100755 --- a/adafruit_display_text/bitmap_label.py +++ b/adafruit_display_text/bitmap_label.py @@ -22,14 +22,17 @@ https://circuitpython.org/downloads """ + +__version__ = "0.0.0-auto.0" +__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Display_Text.git" + + try: from typing import Tuple except ImportError: pass -import displayio -__version__ = "0.0.0-auto.0" -__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Display_Text.git" +import displayio from adafruit_display_text import LabelBase @@ -96,13 +99,8 @@ def __init__(self, font, save_text=True, **kwargs) -> None: self._text = self._replace_tabs(text) # Create the two-color palette - self.color = kwargs.get("color", 0xFFFFFF) self.background_color = kwargs.get("background_color", None) - self._label_direction = kwargs.get("label_direction", "LTR") - - if self._label_direction not in ["LTR", "RTL", "UPD", "UPR", "DWR"]: - raise RuntimeError("Please provide a valid text direction") if self._label_direction == "RTL": self._text = "".join(reversed(self._text)) @@ -118,7 +116,6 @@ def __init__(self, font, save_text=True, **kwargs) -> None: anchored_position=kwargs.get("anchored_position", None), scale=kwargs.get("scale", 1), base_alignment=kwargs.get("base_alignment", False), - label_direction=kwargs.get("label_direction", "LTR"), ) def _reset_text( @@ -130,7 +127,6 @@ def _reset_text( anchored_position: Tuple[int, int] = None, scale: int = None, base_alignment: bool = None, - label_direction: str = "LTR", ) -> None: # Store all the instance variables @@ -144,8 +140,6 @@ def _reset_text( self._anchored_position = anchored_position if base_alignment is not None: self.base_alignment = base_alignment - if label_direction is not None: - self._label_direction = label_direction # if text is not provided as a parameter (text is None), use the previous value. if (text is None) and self._save_text: @@ -254,7 +248,7 @@ def _reset_text( # Update bounding_box values. Note: To be consistent with label.py, # this is the bounding box for the text only, not including the background. - if label_direction == "UPR" or self._label_direction == "DWR": + if self._label_direction in ("UPR", "DWR"): self._bounding_box = ( self.tilegrid.x, self.tilegrid.y, @@ -557,3 +551,10 @@ def _set_background_color(self, new_color): else: self.palette[0] = 0 self.palette.make_transparent(0) + + def _set_label_direction(self, new_label_direction: str) -> None: + self._label_direction = new_label_direction + self._reset_text(text=str(self._text)) # Force a recalculation + + def _get_valid_label_directions(self) -> Tuple[str, ...]: + return "LTR", "RTL", "UPD", "UPR", "DWR" diff --git a/adafruit_display_text/label.py b/adafruit_display_text/label.py index 7f74aad..1165cad 100755 --- a/adafruit_display_text/label.py +++ b/adafruit_display_text/label.py @@ -22,11 +22,17 @@ """ -import displayio - __version__ = "0.0.0-auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Display_Text.git" + +try: + from typing import Tuple +except ImportError: + pass + +import displayio + from adafruit_display_text import LabelBase @@ -109,10 +115,6 @@ def __init__(self, font, **kwargs) -> None: self._added_background_tilegrid = False self.base_alignment = kwargs.get("base_alignment", False) - self._label_direction = kwargs.get("label_direction", "LTR") - - if self._label_direction not in ["LTR", "RTL", "UPR", "DWR", "TTB"]: - raise RuntimeError("Please provide a valid text direction") if text is not None: self._update_text(str(text)) @@ -136,11 +138,7 @@ def _create_background_box(self, lines: int, y_offset: int) -> None: else: # draw a "loose" bounding box to include any ascenders/descenders. ascent, descent = self._ascent, self._descent - if ( - self._label_direction == "UPR" - or self._label_direction == "DWR" - or self._label_direction == "TTB" - ): + if self._label_direction in ("UPR", "DWR", "TTB"): box_height = ( self._bounding_box[3] + self._padding_top + self._padding_bottom ) @@ -284,7 +282,7 @@ def _update_text( if not glyph: continue - if self._label_direction == "LTR" or self._label_direction == "RTL": + if self._label_direction in ("LTR", "RTL"): bottom = max(bottom, y - glyph.dy + self._y_offset) if y == 0: # first line, find the Ascender height top = min(top, -glyph.height - glyph.dy + self._y_offset) @@ -309,7 +307,7 @@ def _update_text( right = max(right, glyph.dx) position_x = x - glyph.width - if self._label_direction == "TTB": + elif self._label_direction == "TTB": if x == 0: if left is None: left = glyph.dx @@ -325,7 +323,7 @@ def _update_text( position_y = y + glyph.dy position_x = x - glyph.width // 2 + self._y_offset - if self._label_direction == "UPR": + elif self._label_direction == "UPR": if x == 0: if bottom is None: bottom = -glyph.dx @@ -338,7 +336,7 @@ def _update_text( position_y = y - glyph.width - glyph.dx position_x = x - glyph.height - glyph.dy + self._y_offset - if self._label_direction == "DWR": + elif self._label_direction == "DWR": if y == 0: if top is None: top = -glyph.dx @@ -457,5 +455,7 @@ def _set_background_color(self, new_color: int) -> None: def _set_label_direction(self, new_label_direction: str) -> None: self._label_direction = new_label_direction - old_text = self._text - self._update_text(str(old_text)) + self._update_text(str(self._text)) + + def _get_valid_label_directions(self) -> Tuple[str, ...]: + return "LTR", "RTL", "UPR", "DWR", "TTB" From c4d43e260cd17c3d23a23baa861e50821360ab49 Mon Sep 17 00:00:00 2001 From: James Carr Date: Fri, 9 Jul 2021 10:54:28 +0100 Subject: [PATCH 11/27] Refactor color, background_color & palette --- adafruit_display_text/__init__.py | 41 ++++++++++++++------------- adafruit_display_text/bitmap_label.py | 16 ++++------- adafruit_display_text/label.py | 33 +++++++++++---------- 3 files changed, 43 insertions(+), 47 deletions(-) diff --git a/adafruit_display_text/__init__.py b/adafruit_display_text/__init__.py index f751390..9fd7081 100644 --- a/adafruit_display_text/__init__.py +++ b/adafruit_display_text/__init__.py @@ -213,36 +213,36 @@ def __init__( super().__init__(x=x, y=y, scale=1) self._font = font + self._text = text + self._palette = Palette(2) + self._color = 0xFFFFFF + self._background_color = None self._line_spacing = line_spacing self._background_tight = background_tight self._padding_top = padding_top self._padding_bottom = padding_bottom self._padding_left = padding_left self._padding_right = padding_right - self._ascent, self._descent = self._get_ascent_descent() - self.palette = Palette(2) - self._color = color - self._background_color = background_color - - self._bounding_box = None self._anchor_point = anchor_point self._anchored_position = anchored_position + self.base_alignment = base_alignment + self._label_direction = label_direction + self._tab_replacement = tab_replacement + self._tab_text = self._tab_replacement[1] * self._tab_replacement[0] + + self._ascent, self._descent = self._get_ascent_descent() + self._bounding_box = None + + self.color = color + self.background_color = background_color # local group will hold background and text # the self group scale should always remain at 1, the self.local_group will # be used to set the scale of the label self.local_group = None - self._text = text - - self._label_direction = label_direction - self.baseline = -1.0 - self.base_alignment = base_alignment - self._tab_replacement = tab_replacement - self._tab_text = self._tab_replacement[1] * self._tab_replacement[0] - if self.base_alignment: self._y_offset = 0 else: @@ -290,11 +290,11 @@ def color(self) -> int: def color(self, new_color: int): self._color = new_color if new_color is not None: - self.palette[1] = new_color - self.palette.make_opaque(1) + self._palette[1] = new_color + self._palette.make_opaque(1) else: - self.palette[1] = 0 - self.palette.make_transparent(1) + self._palette[1] = 0 + self._palette.make_transparent(1) @property def background_color(self) -> int: @@ -302,8 +302,9 @@ def background_color(self) -> int: return self._background_color def _set_background_color(self, new_color): - # subclasses should override this - pass + raise NotImplementedError( + "{} MUST override '_set_background_color'".format(type(self)) + ) @background_color.setter def background_color(self, new_color: int) -> None: diff --git a/adafruit_display_text/bitmap_label.py b/adafruit_display_text/bitmap_label.py index a8ea26f..b24d34b 100755 --- a/adafruit_display_text/bitmap_label.py +++ b/adafruit_display_text/bitmap_label.py @@ -98,10 +98,6 @@ def __init__(self, font, save_text=True, **kwargs) -> None: self._save_text = save_text self._text = self._replace_tabs(text) - # Create the two-color palette - self.color = kwargs.get("color", 0xFFFFFF) - self.background_color = kwargs.get("background_color", None) - if self._label_direction == "RTL": self._text = "".join(reversed(self._text)) @@ -200,7 +196,7 @@ def _reset_text( 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)) + self.bitmap = displayio.Bitmap(box_x, box_y, len(self._palette)) # Place the text into the Bitmap self._place_text( @@ -218,7 +214,7 @@ def _reset_text( self.tilegrid = displayio.TileGrid( self.bitmap, - pixel_shader=self.palette, + pixel_shader=self._palette, width=1, height=1, tile_width=box_x, @@ -546,11 +542,11 @@ def _set_text(self, new_text: str, scale: int) -> None: def _set_background_color(self, new_color): self._background_color = new_color if new_color is not None: - self.palette[0] = new_color - self.palette.make_opaque(0) + self._palette[0] = new_color + self._palette.make_opaque(0) else: - self.palette[0] = 0 - self.palette.make_transparent(0) + self._palette[0] = 0 + self._palette.make_transparent(0) def _set_label_direction(self, new_label_direction: str) -> None: self._label_direction = new_label_direction diff --git a/adafruit_display_text/label.py b/adafruit_display_text/label.py index 1165cad..e8310c2 100755 --- a/adafruit_display_text/label.py +++ b/adafruit_display_text/label.py @@ -47,6 +47,7 @@ class Label(LabelBase): :param str text: Text to display :param int max_glyphs: The largest quantity of glyphs we will display :param int color: Color of all text in RGB hex + :param int background_color: Color of the background, use `None` for transparent :param float line_spacing: Line spacing of text to display :param bool background_tight: Set `True` only if you want background box to tightly surround text. When set to 'True' Padding parameters will be ignored. @@ -81,6 +82,9 @@ class Label(LabelBase): # This has a lot of getters/setters, maybe it needs cleanup. def __init__(self, font, **kwargs) -> None: + self._background_palette = displayio.Palette(1) + self._added_background_tilegrid = False + super().__init__(font, **kwargs) max_glyphs = kwargs.get("max_glyphs", None) @@ -105,14 +109,8 @@ def __init__(self, font, **kwargs) -> None: self._bounding_box = None # Create the two-color text palette - self.palette = displayio.Palette(2) - self.palette[0] = 0 - self.palette.make_transparent(0) - self.color = kwargs.get("color", 0xFFFFFF) - - self._background_color = kwargs.get("background_color", None) - self._background_palette = displayio.Palette(1) - self._added_background_tilegrid = False + self._palette[0] = 0 + self._palette.make_transparent(0) self.base_alignment = kwargs.get("base_alignment", False) @@ -192,9 +190,9 @@ def _create_background_box(self, lines: int, y_offset: int) -> None: return tile_grid - def _update_background_color(self, new_color: int) -> None: + def _set_background_color(self, new_color: int) -> None: """Private class function that allows updating the font box background color - :param new_color: int color as an RGB hex number.""" + :param int new_color: color as an RGB hex number.""" if new_color is None: self._background_palette.make_transparent(0) @@ -209,6 +207,10 @@ def _update_background_color(self, new_color: int) -> None: lines = self._text.rstrip("\n").count("\n") + 1 y_offset = self._ascent // 2 + if self._bounding_box is None: + # Still in initialization + return + if not self._added_background_tilegrid: # no bitmap is in the self Group # add bitmap if text is present and bitmap sizes > 0 pixels if ( @@ -354,7 +356,7 @@ def _update_text( # pylint: disable=unexpected-keyword-arg face = displayio.TileGrid( glyph.bitmap, - pixel_shader=self.palette, + pixel_shader=self._palette, default_tile=glyph.tile_index, tile_width=glyph.width, tile_height=glyph.height, @@ -363,7 +365,7 @@ def _update_text( except TypeError: face = displayio.TileGrid( glyph.bitmap, - pixel_shader=self.palette, + pixel_shader=self._palette, default_tile=glyph.tile_index, tile_width=glyph.width, tile_height=glyph.height, @@ -423,8 +425,8 @@ def _update_text( self._text = new_text - if self.background_color is not None: - self._update_background_color(self._background_color) + if self._background_color is not None: + self._set_background_color(self._background_color) def _reset_text(self, new_text: str) -> None: try: @@ -450,9 +452,6 @@ def _set_line_spacing(self, new_line_spacing: float) -> None: def _set_text(self, new_text: str, scale: int) -> None: self._reset_text(new_text) - def _set_background_color(self, new_color: int) -> None: - self._update_background_color(new_color) - def _set_label_direction(self, new_label_direction: str) -> None: self._label_direction = new_label_direction self._update_text(str(self._text)) From fb75d669b27770e47930576bb488697a69a1a20f Mon Sep 17 00:00:00 2001 From: James Carr Date: Fri, 9 Jul 2021 11:22:48 +0100 Subject: [PATCH 12/27] Refactor base_alignment --- adafruit_display_text/__init__.py | 4 ++-- adafruit_display_text/bitmap_label.py | 8 +------- adafruit_display_text/label.py | 6 ++---- 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/adafruit_display_text/__init__.py b/adafruit_display_text/__init__.py index 9fd7081..71f36d5 100644 --- a/adafruit_display_text/__init__.py +++ b/adafruit_display_text/__init__.py @@ -225,7 +225,7 @@ def __init__( self._padding_right = padding_right self._anchor_point = anchor_point self._anchored_position = anchored_position - self.base_alignment = base_alignment + self._base_alignment = base_alignment self._label_direction = label_direction self._tab_replacement = tab_replacement self._tab_text = self._tab_replacement[1] * self._tab_replacement[0] @@ -243,7 +243,7 @@ def __init__( self.baseline = -1.0 - if self.base_alignment: + if self._base_alignment: self._y_offset = 0 else: self._y_offset = self._ascent // 2 diff --git a/adafruit_display_text/bitmap_label.py b/adafruit_display_text/bitmap_label.py index b24d34b..b786ba1 100755 --- a/adafruit_display_text/bitmap_label.py +++ b/adafruit_display_text/bitmap_label.py @@ -101,8 +101,6 @@ def __init__(self, font, save_text=True, **kwargs) -> None: if self._label_direction == "RTL": self._text = "".join(reversed(self._text)) - self.base_alignment = kwargs.get("base_alignment", False) - # call the text updater with all the arguments. self._reset_text( font=font, @@ -111,7 +109,6 @@ def __init__(self, font, save_text=True, **kwargs) -> None: anchor_point=kwargs.get("anchor_point", None), anchored_position=kwargs.get("anchored_position", None), scale=kwargs.get("scale", 1), - base_alignment=kwargs.get("base_alignment", False), ) def _reset_text( @@ -122,7 +119,6 @@ def _reset_text( anchor_point: Tuple[float, float] = None, anchored_position: Tuple[int, int] = None, scale: int = None, - base_alignment: bool = None, ) -> None: # Store all the instance variables @@ -134,8 +130,6 @@ def _reset_text( self._anchor_point = anchor_point if anchored_position is not None: self._anchored_position = anchored_position - if base_alignment is not None: - self.base_alignment = base_alignment # if text is not provided as a parameter (text is None), use the previous value. if (text is None) and self._save_text: @@ -207,7 +201,7 @@ def _reset_text( self._padding_top + y_offset, ) - if self.base_alignment: + if self._base_alignment: label_position_yoffset = 0 else: label_position_yoffset = self._ascent // 2 diff --git a/adafruit_display_text/label.py b/adafruit_display_text/label.py index e8310c2..4823db6 100755 --- a/adafruit_display_text/label.py +++ b/adafruit_display_text/label.py @@ -112,8 +112,6 @@ def __init__(self, font, **kwargs) -> None: self._palette[0] = 0 self._palette.make_transparent(0) - self.base_alignment = kwargs.get("base_alignment", False) - if text is not None: self._update_text(str(text)) if (kwargs.get("anchored_position", None) is not None) and ( @@ -159,7 +157,7 @@ def _create_background_box(self, lines: int, y_offset: int) -> None: + self._padding_bottom ) - if self.base_alignment: + if self._base_alignment: y_box_offset = -ascent - self._padding_top else: y_box_offset = -ascent + y_offset - self._padding_top @@ -260,7 +258,7 @@ def _update_text( else: i = 0 tilegrid_count = i - if self.base_alignment: + if self._base_alignment: self._y_offset = 0 else: self._y_offset = self._ascent // 2 From 4bef3927858a3c7755d71d00902f5bf0af21c8df Mon Sep 17 00:00:00 2001 From: James Carr Date: Fri, 9 Jul 2021 12:48:26 +0100 Subject: [PATCH 13/27] Refactor anchor_point & anchored_position --- adafruit_display_text/__init__.py | 8 ++++---- adafruit_display_text/bitmap_label.py | 13 ++----------- adafruit_display_text/label.py | 7 +------ 3 files changed, 7 insertions(+), 21 deletions(-) diff --git a/adafruit_display_text/__init__.py b/adafruit_display_text/__init__.py index 71f36d5..0bfe0b0 100644 --- a/adafruit_display_text/__init__.py +++ b/adafruit_display_text/__init__.py @@ -323,9 +323,9 @@ def anchor_point(self, new_anchor_point: Tuple[float, float]) -> None: self._anchor_point = (new_anchor_point[0], -1.0) else: self._anchor_point = new_anchor_point - self.anchored_position = ( - self._anchored_position - ) # update the anchored_position using setter + + # update the anchored_position using setter + self.anchored_position = self._anchored_position @property def anchored_position(self) -> Tuple[int, int]: @@ -336,7 +336,7 @@ def anchored_position(self) -> Tuple[int, int]: @anchored_position.setter def anchored_position(self, new_position: Tuple[int, int]) -> None: self._anchored_position = new_position - # Set anchored_position + # Calculate (x,y) position if (self._anchor_point is not None) and (self._anchored_position is not None): self.x = int( new_position[0] diff --git a/adafruit_display_text/bitmap_label.py b/adafruit_display_text/bitmap_label.py index b786ba1..25acb81 100755 --- a/adafruit_display_text/bitmap_label.py +++ b/adafruit_display_text/bitmap_label.py @@ -106,8 +106,6 @@ def __init__(self, font, save_text=True, **kwargs) -> None: font=font, text=kwargs.get("text", ""), line_spacing=self._line_spacing, - anchor_point=kwargs.get("anchor_point", None), - anchored_position=kwargs.get("anchored_position", None), scale=kwargs.get("scale", 1), ) @@ -116,8 +114,6 @@ def _reset_text( font=None, text: str = None, line_spacing: float = None, - anchor_point: Tuple[float, float] = None, - anchored_position: Tuple[int, int] = None, scale: int = None, ) -> None: @@ -126,10 +122,6 @@ def _reset_text( self._font = font if line_spacing is not None: self._line_spacing = line_spacing - if anchor_point is not None: - self._anchor_point = anchor_point - if anchored_position is not None: - self._anchored_position = anchored_position # if text is not provided as a parameter (text is None), use the previous value. if (text is None) and self._save_text: @@ -258,10 +250,9 @@ def _reset_text( ): # Scale will be defined in local_group (Note: self should have scale=1) self.scale = scale # call the setter - self.anchored_position = ( - self._anchored_position - ) # set the anchored_position with setter after bitmap is created, sets the + # set the anchored_position with setter after bitmap is created, sets the # x,y positions of the label + self.anchored_position = self._anchored_position @staticmethod def _line_spacing_ypixels(font, line_spacing: float) -> int: diff --git a/adafruit_display_text/label.py b/adafruit_display_text/label.py index 4823db6..9620631 100755 --- a/adafruit_display_text/label.py +++ b/adafruit_display_text/label.py @@ -103,7 +103,6 @@ def __init__(self, font, **kwargs) -> None: self.width = max_glyphs self._font = font self._text = None - self._anchor_point = kwargs.get("anchor_point", None) self.height = self._font.get_bounding_box()[1] self._bounding_box = None @@ -113,11 +112,7 @@ def __init__(self, font, **kwargs) -> None: self._palette.make_transparent(0) if text is not None: - self._update_text(str(text)) - if (kwargs.get("anchored_position", None) is not None) and ( - kwargs.get("anchor_point", None) is not None - ): - self.anchored_position = kwargs.get("anchored_position", None) + self._reset_text(str(text)) def _create_background_box(self, lines: int, y_offset: int) -> None: """Private Class function to create a background_box From 3f9a6b6cd4fe94738a254d31086fde3ea55e3feb Mon Sep 17 00:00:00 2001 From: James Carr Date: Fri, 9 Jul 2021 19:25:58 +0100 Subject: [PATCH 14/27] Refactor max_glyphs away (Closes #131) --- adafruit_display_text/label.py | 21 +++++-------------- examples/display_text_advance_example.py | 12 ++++------- ...y_text_label_vs_bitmap_label_comparison.py | 2 -- 3 files changed, 9 insertions(+), 26 deletions(-) diff --git a/adafruit_display_text/label.py b/adafruit_display_text/label.py index 9620631..8089613 100755 --- a/adafruit_display_text/label.py +++ b/adafruit_display_text/label.py @@ -45,7 +45,6 @@ class Label(LabelBase): :param Font font: A font class that has ``get_bounding_box`` and ``get_glyph``. Must include a capital M for measuring character size. :param str text: Text to display - :param int max_glyphs: The largest quantity of glyphs we will display :param int color: Color of all text in RGB hex :param int background_color: Color of the background, use `None` for transparent :param float line_spacing: Line spacing of text to display @@ -87,20 +86,13 @@ def __init__(self, font, **kwargs) -> None: super().__init__(font, **kwargs) - max_glyphs = kwargs.get("max_glyphs", None) - text = kwargs.get("text", "") - - if not max_glyphs and not text: - raise RuntimeError("Please provide a max_glyphs, or initial text") - text = self._replace_tabs(text) - if not max_glyphs: - max_glyphs = len(text) + text = self._replace_tabs(self._text) # local_group will set the scale self.local_group = displayio.Group(scale=kwargs.get("scale", 1)) self.append(self.local_group) - self.width = max_glyphs + self.width = len(text) self._font = font self._text = None @@ -422,12 +414,9 @@ def _update_text( self._set_background_color(self._background_color) def _reset_text(self, new_text: str) -> None: - try: - current_anchored_position = self.anchored_position - self._update_text(str(self._replace_tabs(new_text))) - self.anchored_position = current_anchored_position - except RuntimeError as run_error: - raise RuntimeError("Text length exceeds max_glyphs") from run_error + current_anchored_position = self.anchored_position + self._update_text(str(self._replace_tabs(new_text))) + self.anchored_position = current_anchored_position def _set_font(self, new_font) -> None: old_text = self._text diff --git a/examples/display_text_advance_example.py b/examples/display_text_advance_example.py index 393c976..53c675d 100644 --- a/examples/display_text_advance_example.py +++ b/examples/display_text_advance_example.py @@ -31,7 +31,7 @@ vertica_line = displayio.TileGrid(bitmap, pixel_shader=palette, x=0, y=110) main_group.append(vertica_line) # Tests -text_area = label.Label(terminalio.FONT, text="Circuit Python", max_glyphs=40) +text_area = label.Label(terminalio.FONT, text="Circuit Python") main_group.append(text_area) display.show(main_group) time.sleep(TIME_PAUSE) @@ -43,7 +43,7 @@ # Testing creating label with initial position text_area.text = "Testing initiating without text" try: - text_middle = label.Label(terminalio.FONT, max_glyphs=40) + text_middle = label.Label(terminalio.FONT) except SyntaxError: print("Fail setting-up label without text") warning_text = label.Label( @@ -121,7 +121,6 @@ BIG_FONT, text="aaaaq~", x=0, - max_glyphs=6, y=display.height // 2, color=0xFFFFFF, background_color=0x990099, @@ -132,7 +131,6 @@ BIG_FONT, text="aaaaq~", x=90, - max_glyphs=6, y=display.height // 2, color=0xFFFFFF, background_color=0x990099, @@ -338,7 +336,7 @@ # Testing creating label with initial position display.show(main_group) time.sleep(TIME_PAUSE) -text_area = bitmap_label.Label(terminalio.FONT, text="Circuit Python", max_glyphs=40) +text_area = bitmap_label.Label(terminalio.FONT, text="Circuit Python") main_group.append(text_area) display.show(main_group) time.sleep(TIME_PAUSE) @@ -349,7 +347,7 @@ time.sleep(TIME_PAUSE) text_area.text = "Testing initiating without text" try: - text_middle = label.Label(terminalio.FONT, max_glyphs=40) + text_middle = label.Label(terminalio.FONT) except TypeError: print("Fail setting-up label without text") warning_text = label.Label( @@ -426,7 +424,6 @@ BIG_FONT, text="aaaaq~", x=0, - max_glyphs=6, y=display.height // 2, color=0xFFFFFF, background_color=0x990099, @@ -437,7 +434,6 @@ BIG_FONT, text="aaaaq~", x=90, - max_glyphs=6, y=display.height // 2, color=0xFFFFFF, background_color=0x990099, diff --git a/examples/display_text_label_vs_bitmap_label_comparison.py b/examples/display_text_label_vs_bitmap_label_comparison.py index 29f01f4..69fba87 100644 --- a/examples/display_text_label_vs_bitmap_label_comparison.py +++ b/examples/display_text_label_vs_bitmap_label_comparison.py @@ -143,7 +143,6 @@ font=fontToUse, text=long_string, color=0x000000, - max_glyphs=len(long_string), background_color=0xFFFF00, padding_bottom=label2_padding, padding_left=0, @@ -192,7 +191,6 @@ font=fontToUse, text=long_string, color=0x000000, - max_glyphs=len(long_string), background_color=0xFFFF00, padding_bottom=label2_padding, padding_left=0, From 48357d484fae3c31204c5a1514a91e2b7a7d24c7 Mon Sep 17 00:00:00 2001 From: James Carr Date: Fri, 9 Jul 2021 22:45:53 +0100 Subject: [PATCH 15/27] Refactor local_group to a protected variable. --- adafruit_display_text/__init__.py | 19 +++---- adafruit_display_text/bitmap_label.py | 28 ++++------ adafruit_display_text/label.py | 75 +++++++++++---------------- 3 files changed, 49 insertions(+), 73 deletions(-) diff --git a/adafruit_display_text/__init__.py b/adafruit_display_text/__init__.py index 0bfe0b0..594aad8 100644 --- a/adafruit_display_text/__init__.py +++ b/adafruit_display_text/__init__.py @@ -37,15 +37,15 @@ def wrap_text_to_pixels( # pylint: disable=too-many-locals, too-many-branches if font is None: - def measure(string): - return len(string) + def measure(text): + return len(text) else: if hasattr(font, "load_glyphs"): font.load_glyphs(string) - def measure(string): - return sum(font.get_glyph(ord(c)).shift_x for c in string) + def measure(text): + return sum(font.get_glyph(ord(c)).shift_x for c in text) lines = [] partial = [indent0] @@ -237,9 +237,10 @@ def __init__( self.background_color = background_color # local group will hold background and text - # the self group scale should always remain at 1, the self.local_group will + # the self group scale should always remain at 1, the self._local_group will # be used to set the scale of the label - self.local_group = None + self._local_group = Group(scale=scale) + self.append(self._local_group) self.baseline = -1.0 @@ -250,7 +251,7 @@ def __init__( def _get_ascent_descent(self) -> Tuple[int, int]: """ Private function to calculate ascent and descent font values """ - if hasattr(self.font, "ascent"): + if hasattr(self.font, "ascent") and hasattr(self.font, "descent"): return self.font.ascent, self.font.descent # check a few glyphs for maximum ascender and descender height @@ -355,11 +356,11 @@ def anchored_position(self, new_position: Tuple[int, int]) -> None: @property def scale(self) -> int: """Set the scaling of the label, in integer values""" - return self.local_group.scale + return self._local_group.scale @scale.setter def scale(self, new_scale: int) -> None: - self.local_group.scale = new_scale + self._local_group.scale = new_scale self.anchored_position = self._anchored_position # update the anchored_position def _set_text(self, new_text: str, scale: int) -> None: diff --git a/adafruit_display_text/bitmap_label.py b/adafruit_display_text/bitmap_label.py index 25acb81..e417c5d 100755 --- a/adafruit_display_text/bitmap_label.py +++ b/adafruit_display_text/bitmap_label.py @@ -87,13 +87,6 @@ def __init__(self, font, save_text=True, **kwargs) -> None: super().__init__(font, **kwargs) - self.local_group = displayio.Group( - scale=kwargs.get("scale", 1) - ) # local_group holds the tileGrid and sets the scaling - self.append( - self.local_group - ) # the local_group will always stay in the self Group - text = kwargs.get("text", "") self._save_text = save_text self._text = self._replace_tabs(text) @@ -145,10 +138,10 @@ def _reset_text( 0, # zero width with text == "" 0, # zero height with text == "" ) - # Clear out any items in the self.local_group Group, in case this is an + # Clear out any items in the self._local_group Group, in case this is an # update to the bitmap_label - for _ in self.local_group: - self.local_group.pop(0) + for _ in self._local_group: + self._local_group.pop(0) else: # The text string is not empty, so create the Bitmap and TileGrid and # append to the self Group @@ -222,9 +215,9 @@ def _reset_text( # 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( + for _ in self._local_group: + self._local_group.pop(0) + self._local_group.append( self.tilegrid ) # add the bitmap's tilegrid to the group @@ -345,8 +338,6 @@ def _place_text( font, xposition: int, yposition: int, - text_palette_index: int = 1, - background_palette_index: int = 0, skip_index: int = 0, # set to None to write all pixels, other wise skip this palette index # when copying glyph bitmaps (this is important for slanted text # where rectangular glyph boxes overlap) @@ -403,8 +394,8 @@ def _place_text( # Clip glyph y-direction if outside the font ascent/descent metrics. # Note: bitmap.blit will automatically clip the bottom of the glyph. y_clip = 0 - if (y_blit_target) < 0: - y_clip = -(y_blit_target) # clip this amount from top of bitmap + if y_blit_target < 0: + y_clip = -y_blit_target # clip this amount from top of bitmap y_blit_target = 0 # draw the clipped bitmap at y=0 print( @@ -434,7 +425,8 @@ def _place_text( xposition = xposition + my_glyph.shift_x - return (left, top, right - left, bottom - top) # bounding_box + # bounding_box + return left, top, right - left, bottom - top def _blit( self, diff --git a/adafruit_display_text/label.py b/adafruit_display_text/label.py index 8089613..4114630 100755 --- a/adafruit_display_text/label.py +++ b/adafruit_display_text/label.py @@ -31,7 +31,7 @@ except ImportError: pass -import displayio +from displayio import Bitmap, Palette, TileGrid from adafruit_display_text import LabelBase @@ -81,17 +81,13 @@ class Label(LabelBase): # This has a lot of getters/setters, maybe it needs cleanup. def __init__(self, font, **kwargs) -> None: - self._background_palette = displayio.Palette(1) + self._background_palette = Palette(1) self._added_background_tilegrid = False super().__init__(font, **kwargs) text = self._replace_tabs(self._text) - # local_group will set the scale - self.local_group = displayio.Group(scale=kwargs.get("scale", 1)) - self.append(self.local_group) - self.width = len(text) self._font = font self._text = None @@ -106,7 +102,7 @@ def __init__(self, font, **kwargs) -> None: if text is not None: self._reset_text(str(text)) - def _create_background_box(self, lines: int, y_offset: int) -> None: + def _create_background_box(self, lines: int, y_offset: int) -> TileGrid: """Private Class function to create a background_box :param lines: int number of lines :param y_offset: int y pixel bottom coordinate for the background_box""" @@ -165,8 +161,8 @@ def _create_background_box(self, lines: int, y_offset: int) -> None: movx = left + x_box_offset movy = y_box_offset - background_bitmap = displayio.Bitmap(box_width, box_height, 1) - tile_grid = displayio.TileGrid( + background_bitmap = Bitmap(box_width, box_height, 1) + tile_grid = TileGrid( background_bitmap, pixel_shader=self._background_palette, x=movx, @@ -182,7 +178,7 @@ def _set_background_color(self, new_color: int) -> None: if new_color is None: self._background_palette.make_transparent(0) if self._added_background_tilegrid: - self.local_group.pop(0) + self._local_group.pop(0) self._added_background_tilegrid = False else: self._background_palette.make_opaque(0) @@ -207,15 +203,9 @@ def _set_background_color(self, new_color: int) -> None: self._bounding_box[3] + self._padding_top + self._padding_bottom > 0 ) ): - # This can be simplified in CP v6.0, when group.append(0) bug is corrected - if len(self.local_group) > 0: - self.local_group.insert( - 0, self._create_background_box(lines, y_offset) - ) - else: - self.local_group.append( - self._create_background_box(lines, y_offset) - ) + self._local_group.insert( + 0, self._create_background_box(lines, y_offset) + ) self._added_background_tilegrid = True else: # a bitmap is present in the self Group @@ -229,9 +219,11 @@ def _set_background_color(self, new_color: int) -> None: self._bounding_box[3] + self._padding_top + self._padding_bottom > 0 ) ): - self.local_group[0] = self._create_background_box(lines, self._y_offset) + self._local_group[0] = self._create_background_box( + lines, self._y_offset + ) else: # delete the existing bitmap - self.local_group.pop(0) + self._local_group.pop(0) self._added_background_tilegrid = False # pylint: disable = too-many-branches, too-many-statements @@ -269,6 +261,8 @@ def _update_text( if not glyph: continue + position_x, position_y = 0, 0 + if self._label_direction in ("LTR", "RTL"): bottom = max(bottom, y - glyph.dy + self._y_offset) if y == 0: # first line, find the Ascender height @@ -337,26 +331,15 @@ def _update_text( position_x = x + glyph.dy - self._y_offset if glyph.width > 0 and glyph.height > 0: - try: - # pylint: disable=unexpected-keyword-arg - face = displayio.TileGrid( - glyph.bitmap, - pixel_shader=self._palette, - default_tile=glyph.tile_index, - tile_width=glyph.width, - tile_height=glyph.height, - position=(position_x, position_y), - ) - except TypeError: - face = displayio.TileGrid( - glyph.bitmap, - pixel_shader=self._palette, - default_tile=glyph.tile_index, - tile_width=glyph.width, - tile_height=glyph.height, - x=position_x, - y=position_y, - ) + face = TileGrid( + glyph.bitmap, + pixel_shader=self._palette, + default_tile=glyph.tile_index, + tile_width=glyph.width, + tile_height=glyph.height, + x=position_x, + y=position_y, + ) if self._label_direction == "UPR": face.transpose_xy = True @@ -365,10 +348,10 @@ def _update_text( face.transpose_xy = True face.flip_y = True - if tilegrid_count < len(self.local_group): - self.local_group[tilegrid_count] = face + if tilegrid_count < len(self._local_group): + self._local_group[tilegrid_count] = face else: - self.local_group.append(face) + self._local_group.append(face) tilegrid_count += 1 if self._label_direction == "RTL": @@ -394,8 +377,8 @@ def _update_text( if self._label_direction == "TTB" and top is None: top = 0 - while len(self.local_group) > tilegrid_count: # i: - self.local_group.pop() + while len(self._local_group) > tilegrid_count: # i: + self._local_group.pop() # pylint: disable=invalid-unary-operand-type if self._label_direction == "RTL": self._bounding_box = (-left, top, left - right, bottom - top) From 068599c1e82419cb77603c5cf36d77dff4fd93c6 Mon Sep 17 00:00:00 2001 From: James Carr Date: Fri, 9 Jul 2021 23:37:42 +0100 Subject: [PATCH 16/27] Remove and update all pylint disables --- adafruit_display_text/__init__.py | 10 +++++++--- adafruit_display_text/bitmap_label.py | 10 ++++++---- adafruit_display_text/label.py | 16 ++++++++-------- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/adafruit_display_text/__init__.py b/adafruit_display_text/__init__.py index 594aad8..1dbf7ee 100644 --- a/adafruit_display_text/__init__.py +++ b/adafruit_display_text/__init__.py @@ -17,6 +17,8 @@ def wrap_text_to_pixels( string: str, max_width: int, font=None, indent0: str = "", indent1: str = "" ) -> List[str]: + # pylint: disable=too-many-branches, too-many-locals + """wrap_text_to_pixels function A helper that will return a list of lines with word-break wrapping. Leading and trailing whitespace in your string will be removed. If @@ -34,7 +36,6 @@ def wrap_text_to_pixels( :rtype: List[str] """ - # pylint: disable=too-many-locals, too-many-branches if font is None: def measure(text): @@ -153,6 +154,8 @@ def chunks(lst, n): class LabelBase(Group): + # pylint: disable=too-many-instance-attributes + """Superclass that all other types of labels will extend. This contains all of the properties and functions that work the same way in all labels. @@ -187,7 +190,6 @@ class LabelBase(Group): :param str label_direction: string defining the label text orientation. See the subclass documentation for the possible values.""" - # pylint: disable=unused-argument, too-many-instance-attributes, too-many-locals, too-many-arguments def __init__( self, font, @@ -208,8 +210,10 @@ def __init__( base_alignment: bool = False, tab_replacement: Tuple[int, str] = (4, " "), label_direction: str = "LTR", - **kwargs, + **kwargs, # pylint: disable=unused-argument ) -> None: + # pylint: disable=too-many-arguments, too-many-locals + super().__init__(x=x, y=y, scale=1) self._font = font diff --git a/adafruit_display_text/bitmap_label.py b/adafruit_display_text/bitmap_label.py index e417c5d..081928d 100755 --- a/adafruit_display_text/bitmap_label.py +++ b/adafruit_display_text/bitmap_label.py @@ -80,9 +80,6 @@ class Label(LabelBase): configurations possibles ``LTR``-Left-To-Right ``RTL``-Right-To-Left ``UPD``-Upside Down ``UPR``-Upwards ``DWR``-Downwards. It defaults to ``LTR``""" - # pylint: disable=unused-argument, too-many-instance-attributes, too-many-locals, too-many-arguments - # pylint: disable=too-many-branches, no-self-use, too-many-statements - def __init__(self, font, save_text=True, **kwargs) -> None: super().__init__(font, **kwargs) @@ -109,6 +106,7 @@ def _reset_text( line_spacing: float = None, scale: int = None, ) -> None: + # pylint: disable=too-many-branches, too-many-statements # Store all the instance variables if font is not None: @@ -256,6 +254,8 @@ def _line_spacing_ypixels(font, line_spacing: float) -> int: def _text_bounding_box( self, text: str, font ) -> Tuple[int, int, int, int, int, int]: + # pylint: disable=too-many-locals + ascender_max, descender_max = self._ascent, self._descent lines = 1 @@ -330,7 +330,6 @@ def _text_bounding_box( final_y_offset_loose, ) - # pylint: disable=too-many-nested-blocks def _place_text( self, bitmap, @@ -342,6 +341,8 @@ def _place_text( # when copying glyph bitmaps (this is important for slanted text # where rectangular glyph boxes overlap) ) -> Tuple[int, int, int, int]: + # pylint: disable=too-many-arguments, too-many-locals + # placeText - Writes text into a bitmap at the specified location. # # Note: scale is pushed up to Group level @@ -441,6 +442,7 @@ def _blit( skip_index: int = None, # palette index that will not be copied # (for example: the background color of a glyph) ) -> None: + # pylint: disable=no-self-use, too-many-arguments if hasattr(bitmap, "blit"): # if bitmap has a built-in blit function, call it # this function should perform its own input checks diff --git a/adafruit_display_text/label.py b/adafruit_display_text/label.py index 4114630..bf05758 100755 --- a/adafruit_display_text/label.py +++ b/adafruit_display_text/label.py @@ -37,6 +37,8 @@ class Label(LabelBase): + # pylint: disable=too-many-instance-attributes + """A label displaying a string of text. The origin point set by ``x`` and ``y`` properties will be the left edge of the bounding box, and in the center of a M glyph (if its one line), or the (number of lines * linespacing + M)/2. That is, @@ -77,9 +79,6 @@ class Label(LabelBase): configurations possibles ``LTR``-Left-To-Right ``RTL``-Right-To-Left ``TTB``-Top-To-Bottom ``UPR``-Upwards ``DWR``-Downwards. It defaults to ``LTR``""" - # pylint: disable=too-many-instance-attributes, too-many-locals - # This has a lot of getters/setters, maybe it needs cleanup. - def __init__(self, font, **kwargs) -> None: self._background_palette = Palette(1) self._added_background_tilegrid = False @@ -226,10 +225,9 @@ def _set_background_color(self, new_color: int) -> None: self._local_group.pop(0) self._added_background_tilegrid = False - # pylint: disable = too-many-branches, too-many-statements - def _update_text( - self, new_text: str - ) -> None: # pylint: disable=too-many-locals ,too-many-branches, too-many-statements + def _update_text(self, new_text: str) -> None: + # pylint: disable=too-many-branches,too-many-statements + x = 0 y = 0 if self._added_background_tilegrid: @@ -379,8 +377,10 @@ def _update_text( while len(self._local_group) > tilegrid_count: # i: self._local_group.pop() - # pylint: disable=invalid-unary-operand-type + if self._label_direction == "RTL": + # pylint: disable=invalid-unary-operand-type + # type-checkers think left can be None self._bounding_box = (-left, top, left - right, bottom - top) if self._label_direction == "TTB": self._bounding_box = (left, top, right - left, bottom - top) From aedccd9ed5e5eea9c1f57468b814d2ef320d08da Mon Sep 17 00:00:00 2001 From: James Carr Date: Sat, 10 Jul 2021 09:38:28 +0100 Subject: [PATCH 17/27] Reduce unnecessary kwarg usage --- adafruit_display_text/bitmap_label.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/adafruit_display_text/bitmap_label.py b/adafruit_display_text/bitmap_label.py index 081928d..5ab8d49 100755 --- a/adafruit_display_text/bitmap_label.py +++ b/adafruit_display_text/bitmap_label.py @@ -84,9 +84,8 @@ def __init__(self, font, save_text=True, **kwargs) -> None: super().__init__(font, **kwargs) - text = kwargs.get("text", "") self._save_text = save_text - self._text = self._replace_tabs(text) + self._text = self._replace_tabs(self._text) if self._label_direction == "RTL": self._text = "".join(reversed(self._text)) @@ -94,9 +93,9 @@ def __init__(self, font, save_text=True, **kwargs) -> None: # call the text updater with all the arguments. self._reset_text( font=font, - text=kwargs.get("text", ""), + text=self._text, line_spacing=self._line_spacing, - scale=kwargs.get("scale", 1), + scale=self.scale, ) def _reset_text( From 915b3603f58e57d517819c4cace6200c7ac092c9 Mon Sep 17 00:00:00 2001 From: James Carr Date: Sat, 10 Jul 2021 10:58:47 +0100 Subject: [PATCH 18/27] Minor tweaks to advanced example --- examples/display_text_advance_example.py | 41 +++++++++++++++++++++--- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/examples/display_text_advance_example.py b/examples/display_text_advance_example.py index 53c675d..750728a 100644 --- a/examples/display_text_advance_example.py +++ b/examples/display_text_advance_example.py @@ -28,18 +28,21 @@ main_group.append(horizontal_line) bitmap = displayio.Bitmap(display.width, 4, 2) -vertica_line = displayio.TileGrid(bitmap, pixel_shader=palette, x=0, y=110) -main_group.append(vertica_line) +vertical_line = displayio.TileGrid(bitmap, pixel_shader=palette, x=0, y=110) +main_group.append(vertical_line) + # Tests text_area = label.Label(terminalio.FONT, text="Circuit Python") main_group.append(text_area) display.show(main_group) time.sleep(TIME_PAUSE) + # Testing position setter text_area.x = 10 text_area.y = 10 display.show(main_group) time.sleep(TIME_PAUSE) + # Testing creating label with initial position text_area.text = "Testing initiating without text" try: @@ -64,17 +67,20 @@ main_group.append(text_middle) display.show(main_group) time.sleep(TIME_PAUSE) + # Testing Text Setter text_area.text = "Testing Changing Text" text_middle.text = "Python" display.show(main_group) time.sleep(TIME_PAUSE) + # Testing a and y getter and setter text_area.text = "Testing Changing Position" text_middle.x = text_middle.x - 50 text_middle.y = text_middle.y - 50 display.show(main_group) time.sleep(TIME_PAUSE) + # Testing font Getter and setter text_area.text = "Testing Changing FONT" if isinstance(text_middle.font, fontio.BuiltinFont): @@ -84,6 +90,7 @@ # Once this working we create another label with all the initial specs main_group.pop() + # Testing Color text_area.text = "Testing Color" text_initial_specs = label.Label( @@ -95,10 +102,12 @@ main_group.append(text_initial_specs) display.show(main_group) time.sleep(TIME_PAUSE) + text_initial_specs.color = 0x004400 display.show(main_group) time.sleep(TIME_PAUSE) main_group.pop() + # Testing Background Color text_area.text = "Testing Background Color" text_initial_specs = label.Label( @@ -111,10 +120,12 @@ main_group.append(text_initial_specs) display.show(main_group) time.sleep(TIME_PAUSE) + text_initial_specs.background_color = 0x990099 display.show(main_group) time.sleep(TIME_PAUSE) main_group.pop() + # Testing Background Color text_area.text = "Testing Background Tight" text_initial_specs = label.Label( @@ -177,7 +188,8 @@ ) main_group.append(text_initial_specs) display.show(main_group) -time.sleep(1) +time.sleep(TIME_PAUSE) + try: text_initial_specs.anchored_position = (100, 100) text_initial_specs.anchor_point = (0.5, 0.5) @@ -217,6 +229,7 @@ main_group.append(text_initial_specs) display.show(main_group) time.sleep(TIME_PAUSE) + text_initial_specs.scale = 2 display.show(main_group) time.sleep(TIME_PAUSE) @@ -270,6 +283,7 @@ display.show(main_group) time.sleep(TIME_PAUSE) main_group.pop() + text_area.text = "Testing Direction-DWR" text_initial_specs = label.Label( MEDIUM_FONT, @@ -290,6 +304,7 @@ display.show(main_group) time.sleep(TIME_PAUSE) main_group.pop() + text_area.text = "Testing Direction-TTB" text_initial_specs = label.Label( MEDIUM_FONT, @@ -310,6 +325,7 @@ display.show(main_group) time.sleep(TIME_PAUSE) main_group.pop() + text_area.text = "Testing Direction-RTL" text_initial_specs = label.Label( MEDIUM_FONT, @@ -367,26 +383,31 @@ main_group.append(text_middle) display.show(main_group) time.sleep(TIME_PAUSE) + # Testing Text Setter text_area.text = "Testing Changing Text" text_middle.text = "Python" display.show(main_group) time.sleep(TIME_PAUSE) + # Testing a and y getter and setter text_area.text = "Testing Changing Position" text_middle.x = text_middle.x - 50 text_middle.y = text_middle.y - 50 display.show(main_group) time.sleep(TIME_PAUSE) + # Testing font Getter and setter text_area.text = "Testing Changing FONT" if isinstance(text_middle.font, fontio.BuiltinFont): + print("Font was BuiltinFont") text_middle.font = MEDIUM_FONT display.show(main_group) time.sleep(TIME_PAUSE) # Once this working we create another label with all the initial specs main_group.pop() + # Testing Color text_area.text = "Testing Color" text_initial_specs = bitmap_label.Label( @@ -398,10 +419,12 @@ main_group.append(text_initial_specs) display.show(main_group) time.sleep(TIME_PAUSE) + text_initial_specs.color = 0x004400 display.show(main_group) time.sleep(TIME_PAUSE) main_group.pop() + # Testing Background Color text_area.text = "Testing Background Color" text_initial_specs = bitmap_label.Label( @@ -414,10 +437,12 @@ main_group.append(text_initial_specs) display.show(main_group) time.sleep(TIME_PAUSE) + text_initial_specs.background_color = 0x990099 display.show(main_group) time.sleep(TIME_PAUSE) main_group.pop() + # Testing Background Color text_area.text = "Testing Background Tight" text_initial_specs = bitmap_label.Label( @@ -480,7 +505,8 @@ ) main_group.append(text_initial_specs) display.show(main_group) -time.sleep(1) +time.sleep(TIME_PAUSE) + try: text_initial_specs.anchored_position = (100, 100) text_initial_specs.anchor_point = (0.5, 0.5) @@ -520,6 +546,7 @@ main_group.append(text_initial_specs) display.show(main_group) time.sleep(TIME_PAUSE) + text_initial_specs.scale = 2 display.show(main_group) time.sleep(TIME_PAUSE) @@ -573,6 +600,7 @@ display.show(main_group) time.sleep(TIME_PAUSE) main_group.pop() + text_area.text = "Testing Direction-DWR" text_initial_specs = bitmap_label.Label( MEDIUM_FONT, @@ -593,6 +621,7 @@ display.show(main_group) time.sleep(TIME_PAUSE) main_group.pop() + text_area.text = "Testing Direction-UPD" text_initial_specs = bitmap_label.Label( MEDIUM_FONT, @@ -613,6 +642,7 @@ display.show(main_group) time.sleep(TIME_PAUSE) main_group.pop() + text_area.text = "Testing Direction-RTL" text_initial_specs = bitmap_label.Label( MEDIUM_FONT, @@ -633,3 +663,6 @@ display.show(main_group) time.sleep(TIME_PAUSE) main_group.pop() + +text_area.text = "Finished" +print("Tests finished") From 95a822a7ad493bb7e3d98ef77256896c17ac1638 Mon Sep 17 00:00:00 2001 From: James Carr Date: Sat, 10 Jul 2021 11:00:18 +0100 Subject: [PATCH 19/27] Refactor label __init__ --- adafruit_display_text/label.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/adafruit_display_text/label.py b/adafruit_display_text/label.py index bf05758..c1fe28d 100755 --- a/adafruit_display_text/label.py +++ b/adafruit_display_text/label.py @@ -88,11 +88,7 @@ def __init__(self, font, **kwargs) -> None: text = self._replace_tabs(self._text) self.width = len(text) - self._font = font - self._text = None - self.height = self._font.get_bounding_box()[1] - self._bounding_box = None # Create the two-color text palette self._palette[0] = 0 From 46fec3a3a2d3d3cb7b01267ca37f1d512ae37e9b Mon Sep 17 00:00:00 2001 From: James Carr Date: Sat, 10 Jul 2021 22:16:35 +0100 Subject: [PATCH 20/27] Refactor baseline --- adafruit_display_text/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/adafruit_display_text/__init__.py b/adafruit_display_text/__init__.py index 1dbf7ee..342984b 100644 --- a/adafruit_display_text/__init__.py +++ b/adafruit_display_text/__init__.py @@ -246,7 +246,7 @@ def __init__( self._local_group = Group(scale=scale) self.append(self._local_group) - self.baseline = -1.0 + self._baseline = -1.0 if self._base_alignment: self._y_offset = 0 @@ -324,7 +324,7 @@ def anchor_point(self) -> Tuple[float, float]: @anchor_point.setter def anchor_point(self, new_anchor_point: Tuple[float, float]) -> None: - if new_anchor_point[1] == self.baseline: + if new_anchor_point[1] == self._baseline: self._anchor_point = (new_anchor_point[0], -1.0) else: self._anchor_point = new_anchor_point @@ -348,7 +348,7 @@ def anchored_position(self, new_position: Tuple[int, int]) -> None: - (self._bounding_box[0] * self.scale) - round(self._anchor_point[0] * (self._bounding_box[2] * self.scale)) ) - if self._anchor_point[1] == self.baseline: + if self._anchor_point[1] == self._baseline: self.y = int(new_position[1] - (self._y_offset * self.scale)) else: self.y = int( From d557cf8ab3d93c5f7d71dbbc04a2e75594350fe0 Mon Sep 17 00:00:00 2001 From: James Carr Date: Sat, 10 Jul 2021 22:36:47 +0100 Subject: [PATCH 21/27] Refactor bitmap --- adafruit_display_text/bitmap_label.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/adafruit_display_text/bitmap_label.py b/adafruit_display_text/bitmap_label.py index 5ab8d49..1818f14 100755 --- a/adafruit_display_text/bitmap_label.py +++ b/adafruit_display_text/bitmap_label.py @@ -82,6 +82,8 @@ class Label(LabelBase): def __init__(self, font, save_text=True, **kwargs) -> None: + self._bitmap = None + super().__init__(font, **kwargs) self._save_text = save_text @@ -172,11 +174,11 @@ def _reset_text( 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)) + self._bitmap = displayio.Bitmap(box_x, box_y, len(self._palette)) # Place the text into the Bitmap self._place_text( - self.bitmap, + self._bitmap, self._text, self._font, self._padding_left - x_offset, @@ -189,7 +191,7 @@ def _reset_text( label_position_yoffset = self._ascent // 2 self.tilegrid = displayio.TileGrid( - self.bitmap, + self._bitmap, pixel_shader=self._palette, width=1, height=1, From a001c02224d9257b53cc451683c17626c84166e7 Mon Sep 17 00:00:00 2001 From: James Carr Date: Sat, 10 Jul 2021 22:43:26 +0100 Subject: [PATCH 22/27] Refactor width & height --- adafruit_display_text/label.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/adafruit_display_text/label.py b/adafruit_display_text/label.py index c1fe28d..943755f 100755 --- a/adafruit_display_text/label.py +++ b/adafruit_display_text/label.py @@ -87,8 +87,8 @@ def __init__(self, font, **kwargs) -> None: text = self._replace_tabs(self._text) - self.width = len(text) - self.height = self._font.get_bounding_box()[1] + self._width = len(text) + self._height = self._font.get_bounding_box()[1] # Create the two-color text palette self._palette[0] = 0 @@ -119,7 +119,7 @@ def _create_background_box(self, lines: int, y_offset: int) -> TileGrid: x_box_offset = -self._padding_bottom box_width = ( (ascent + descent) - + int((lines - 1) * self.width * self._line_spacing) + + int((lines - 1) * self._width * self._line_spacing) + self._padding_left + self._padding_right ) @@ -130,7 +130,7 @@ def _create_background_box(self, lines: int, y_offset: int) -> TileGrid: x_box_offset = -self._padding_left box_height = ( (ascent + descent) - + int((lines - 1) * self.height * self._line_spacing) + + int((lines - 1) * self._height * self._line_spacing) + self._padding_top + self._padding_bottom ) @@ -248,7 +248,7 @@ def _update_text(self, new_text: str) -> None: for character in new_text: if character == "\n": - y += int(self.height * self._line_spacing) + y += int(self._height * self._line_spacing) x = 0 continue glyph = self._font.get_glyph(ord(character)) @@ -402,7 +402,7 @@ def _set_font(self, new_font) -> None: current_anchored_position = self.anchored_position self._text = "" self._font = new_font - self.height = self._font.get_bounding_box()[1] + self._height = self._font.get_bounding_box()[1] self._update_text(str(old_text)) self.anchored_position = current_anchored_position From 5014b3d0ef1496f9a9b1bb90a7c94a017d8eeb5f Mon Sep 17 00:00:00 2001 From: James Carr Date: Sat, 10 Jul 2021 23:05:04 +0100 Subject: [PATCH 23/27] Refactor tilegrid --- adafruit_display_text/bitmap_label.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/adafruit_display_text/bitmap_label.py b/adafruit_display_text/bitmap_label.py index 1818f14..cc2e23d 100755 --- a/adafruit_display_text/bitmap_label.py +++ b/adafruit_display_text/bitmap_label.py @@ -190,7 +190,7 @@ def _reset_text( else: label_position_yoffset = self._ascent // 2 - self.tilegrid = displayio.TileGrid( + self._tilegrid = displayio.TileGrid( self._bitmap, pixel_shader=self._palette, width=1, @@ -203,36 +203,36 @@ def _reset_text( ) if self._label_direction == "UPR": - self.tilegrid.transpose_xy = True - self.tilegrid.flip_x = True + 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 + 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 + 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 + self._tilegrid ) # add the bitmap's tilegrid to the group # Update bounding_box values. Note: To be consistent with label.py, # this is the bounding box for the text only, not including the background. if self._label_direction in ("UPR", "DWR"): self._bounding_box = ( - self.tilegrid.x, - self.tilegrid.y, + self._tilegrid.x, + self._tilegrid.y, tight_box_y, box_x, ) else: self._bounding_box = ( - self.tilegrid.x, - self.tilegrid.y, + self._tilegrid.x, + self._tilegrid.y, box_x, tight_box_y, ) From 58c6644db2b04892a7c10b98bcd37b129aa30d24 Mon Sep 17 00:00:00 2001 From: James Carr Date: Sat, 10 Jul 2021 23:36:53 +0100 Subject: [PATCH 24/27] Refactor boolean to bool --- adafruit_display_text/bitmap_label.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adafruit_display_text/bitmap_label.py b/adafruit_display_text/bitmap_label.py index cc2e23d..a613039 100755 --- a/adafruit_display_text/bitmap_label.py +++ b/adafruit_display_text/bitmap_label.py @@ -57,7 +57,7 @@ class Label(LabelBase): :param int color: Color of all text in RGB hex :param int background_color: Color of the background, use `None` for transparent :param float line_spacing: Line spacing of text to display - :param boolean background_tight: Set `True` only if you want background box to tightly + :param bool background_tight: Set `True` only if you want background box to tightly surround text. When set to 'True' Padding parameters will be ignored. :param int padding_top: Additional pixels added to background bounding box at top :param int padding_bottom: Additional pixels added to background bounding box at bottom From fbe1fbda823af55a93cb10e30f9dfbf9fbc3ef1a Mon Sep 17 00:00:00 2001 From: James Carr Date: Thu, 15 Jul 2021 09:25:56 +0100 Subject: [PATCH 25/27] Tweak the PyPortal example to specify the Font directory --- examples/display_text_pyportal.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/examples/display_text_pyportal.py b/examples/display_text_pyportal.py index edcfabb..3691ec8 100644 --- a/examples/display_text_pyportal.py +++ b/examples/display_text_pyportal.py @@ -14,10 +14,13 @@ from adafruit_bitmap_font import bitmap_font from adafruit_display_text.label import Label +FONT_DIR = "/fonts/" fonts = list( - filter(lambda x: x.endswith("bdf") and not x.startswith("."), os.listdir("/")) + filter(lambda x: x.endswith("bdf") and not x.startswith("."), os.listdir(FONT_DIR)) ) -fonts = [bitmap_font.load_font(x) for x in fonts] +fonts = [bitmap_font.load_font(FONT_DIR + x) for x in fonts] +if len(fonts) == 0: + print("No fonts found in '{}'".format(FONT_DIR)) print("fade up") # Fade up the backlight @@ -30,12 +33,17 @@ splash = displayio.Group() board.DISPLAY.show(splash) max_y = 0 -y = 2 +y = 0 for demo_text in demos: for font in fonts: + if y >= board.DISPLAY.height: + y = 0 + while len(splash): + splash.pop() print("Font load {}".format(font.name)) - area = Label(font, text=demo_text) - area.y = y + area = Label( + font, text=demo_text, anchor_point=(0, 0), anchored_position=(0, y) + ) splash.append(area) y += area.height @@ -46,8 +54,8 @@ except AttributeError: board.DISPLAY.wait_for_frame() -# Wait for 10 minutes (600 seconds) -time.sleep(600) +# Wait for 1 minute (60 seconds) +time.sleep(60) # Fade down the backlight for b in range(100, -1, -1): From adddcf2b877a2c46ab44adc6ca4418b81520e516 Mon Sep 17 00:00:00 2001 From: James Carr Date: Thu, 15 Jul 2021 09:27:03 +0100 Subject: [PATCH 26/27] Add height & width properties to LabelBase --- adafruit_display_text/__init__.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/adafruit_display_text/__init__.py b/adafruit_display_text/__init__.py index 342984b..0b933ce 100644 --- a/adafruit_display_text/__init__.py +++ b/adafruit_display_text/__init__.py @@ -385,6 +385,16 @@ def bounding_box(self) -> Tuple[int, int]: first two numbers are offset from the x, y origin of this group""" return tuple(self._bounding_box) + @property + def height(self) -> int: + """The height of the label determined from the bounding box.""" + return self._bounding_box[3] - self._bounding_box[1] + + @property + def width(self) -> int: + """The width of the label determined from the bounding box.""" + return self._bounding_box[2] - self._bounding_box[0] + @property def line_spacing(self) -> float: """The amount of space between lines of text, in multiples of the font's From b3acf4f2207bc066283a7850d7522c55820d0bc4 Mon Sep 17 00:00:00 2001 From: James Carr Date: Thu, 15 Jul 2021 09:48:22 +0100 Subject: [PATCH 27/27] Print a message if max_glyphs is passed in --- adafruit_display_text/__init__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/adafruit_display_text/__init__.py b/adafruit_display_text/__init__.py index 0b933ce..e7e91be 100644 --- a/adafruit_display_text/__init__.py +++ b/adafruit_display_text/__init__.py @@ -234,6 +234,9 @@ def __init__( self._tab_replacement = tab_replacement self._tab_text = self._tab_replacement[1] * self._tab_replacement[0] + if "max_glyphs" in kwargs: + print("Please update your code: 'max_glyphs' is not needed anymore.") + self._ascent, self._descent = self._get_ascent_descent() self._bounding_box = None