diff --git a/adafruit_display_text/bitmap_label.py b/adafruit_display_text/bitmap_label.py index bb5c723..c35e522 100755 --- a/adafruit_display_text/bitmap_label.py +++ b/adafruit_display_text/bitmap_label.py @@ -121,7 +121,7 @@ def __init__( ) # the local_group will always stay in the self Group self._font = font - self._text = text + self._text = " ".join(text.split("\t")) # Create the two-color palette self.palette = displayio.Palette(2) @@ -204,7 +204,7 @@ def _reset_text( text = self._text if self._save_text: # text string will be saved - self._text = text + self._text = " ".join(text.split("\t")) else: self._text = None # save a None value since text string is not saved @@ -239,7 +239,7 @@ def _reset_text( loose_box_y, loose_y_offset, ) = self._text_bounding_box( - text, + self._text, self._font, self._line_spacing, ) # calculate the box size for a tight and loose backgrounds @@ -262,7 +262,7 @@ def _reset_text( # Place the text into the Bitmap self._place_text( self.bitmap, - text, + self._text, self._font, self._line_spacing, self._padding_left - x_offset, @@ -632,6 +632,7 @@ def text(self): @text.setter # Cannot set color or background color with text setter, use separate setter def text(self, new_text): + new_text = " ".join(new_text.split("\t")) self._reset_text(text=new_text, scale=self.scale) @property diff --git a/adafruit_display_text/label.py b/adafruit_display_text/label.py index 5549871..72ab41d 100755 --- a/adafruit_display_text/label.py +++ b/adafruit_display_text/label.py @@ -21,7 +21,7 @@ https://github.com/adafruit/circuitpython/releases """ - +from typing import Tuple import displayio __version__ = "0.0.0-auto.0" @@ -70,30 +70,31 @@ def __init__( self, font, *, - x=0, - y=0, - text="", - max_glyphs=None, - color=0xFFFFFF, - background_color=None, - line_spacing=1.25, - background_tight=False, - padding_top=0, - padding_bottom=0, - padding_left=0, - padding_right=0, - anchor_point=None, - anchored_position=None, - scale=1, - base_alignment=False, + x: int = 0, + y: int = 0, + text: str = "", + max_glyphs: int = None, + color: int = 0xFFFFFF, + background_color: int = None, + line_spacing: float = 1.25, + background_tight: bool = False, + padding_top: int = 0, + padding_bottom: int = 0, + padding_left: int = 0, + padding_right: int = 0, + anchor_point: Tuple[float, float] = None, + anchored_position: Tuple[int, int] = None, + scale: int = 1, + base_alignment: bool = False, **kwargs - ): + ) -> None: if not max_glyphs and not text: raise RuntimeError("Please provide a max size, or initial text") + text = " ".join(text.split("\t")) if not max_glyphs: max_glyphs = len(text) - # add one to max_size for the background bitmap tileGrid + # add one to max_size for the background bitmap tileGrid # instance the Group # self Group will contain a single local_group which contains a Group (self.local_group) # which contains a TileGrid @@ -133,13 +134,14 @@ def __init__( self._padding_left = padding_left self._padding_right = padding_right self.base_alignment = base_alignment + self.baseline = -1.0 if text is not None: self._update_text(str(text)) if (anchored_position is not None) and (anchor_point is not None): self.anchored_position = anchored_position - def _create_background_box(self, lines, y_offset): + def _create_background_box(self, lines: int, y_offset: int) -> None: """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""" @@ -181,7 +183,7 @@ def _create_background_box(self, lines, y_offset): return tile_grid - def _get_ascent_descent(self): + def _get_ascent_descent(self) -> Tuple[int, int]: """ Private function to calculate ascent and descent font values """ if hasattr(self.font, "ascent"): return self.font.ascent, self.font.descent @@ -202,10 +204,10 @@ def _get_ascent_descent(self): descender_max = max(descender_max, -this_glyph.dy) return ascender_max, descender_max - def _get_ascent(self): + def _get_ascent(self) -> int: return self._get_ascent_descent()[0] - def _update_background_color(self, new_color): + def _update_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.""" @@ -260,9 +262,8 @@ def _update_background_color(self, new_color): self.local_group.pop(0) self._added_background_tilegrid = False - def _update_text( - self, new_text - ): # pylint: disable=too-many-locals ,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 x = 0 y = 0 if self._added_background_tilegrid: @@ -271,9 +272,9 @@ def _update_text( i = 0 tilegrid_count = i if self.base_alignment: - y_offset = 0 + self.y_offset = 0 else: - y_offset = self._get_ascent() // 2 + self.y_offset = self._get_ascent() // 2 right = top = bottom = 0 left = None @@ -293,9 +294,9 @@ def _update_text( else: left = min(left, glyph.dx) if y == 0: # first line, find the Ascender height - top = min(top, -glyph.height - glyph.dy + y_offset) - bottom = max(bottom, y - glyph.dy + y_offset) - position_y = y - glyph.height - glyph.dy + y_offset + top = min(top, -glyph.height - glyph.dy + self.y_offset) + bottom = max(bottom, y - glyph.dy + self.y_offset) + position_y = y - glyph.height - glyph.dy + self.y_offset position_x = x + glyph.dx if glyph.width > 0 and glyph.height > 0: try: @@ -325,7 +326,6 @@ def _update_text( tilegrid_count += 1 x += glyph.shift_x i += 1 - # Remove the rest if left is None: left = 0 @@ -339,19 +339,19 @@ def _update_text( self._update_background_color(self._background_color) @property - def bounding_box(self): + def bounding_box(self) -> Tuple[int, int, int, int]: """An (x, y, w, h) tuple that completely covers all glyphs. The first two numbers are offset from the x, y origin of this group""" return tuple(self._boundingbox) @property - def line_spacing(self): + def line_spacing(self) -> float: """The amount of space between lines of text, in multiples of the font's bounding-box height. (E.g. 1.0 is the bounding-box height)""" return self._line_spacing @line_spacing.setter - def line_spacing(self, spacing): + def line_spacing(self, spacing: float) -> None: self._line_spacing = spacing self.text = self._text # redraw the box @@ -361,7 +361,7 @@ def color(self): return self.palette[1] @color.setter - def color(self, new_color): + def color(self, new_color: int) -> None: self._color = new_color if new_color is not None: self.palette[1] = new_color @@ -371,21 +371,22 @@ def color(self, new_color): self.palette.make_transparent(1) @property - def background_color(self): + def background_color(self) -> int: """Color of the background as an RGB hex number.""" return self._background_color @background_color.setter - def background_color(self, new_color): + def background_color(self, new_color: int) -> None: self._update_background_color(new_color) @property - def text(self): + def text(self) -> str: """Text to display.""" return self._text @text.setter - def text(self, new_text): + def text(self, new_text: str) -> None: + new_text = " ".join(new_text.split("\t")) try: current_anchored_position = self.anchored_position self._update_text(str(new_text)) @@ -394,12 +395,12 @@ def text(self, new_text): raise RuntimeError("Text length exceeds max_glyphs") from run_error @property - def scale(self): + def scale(self) -> int: """Set the scaling of the label, in integer values""" return self.local_group.scale @scale.setter - def scale(self, new_scale): + def scale(self, new_scale: int) -> None: current_anchored_position = self.anchored_position self.local_group.scale = new_scale self.anchored_position = current_anchored_position @@ -410,7 +411,7 @@ def font(self): return self._font @font.setter - def font(self, new_font): + def font(self, new_font) -> None: old_text = self._text current_anchored_position = self.anchored_position self._text = "" @@ -420,23 +421,30 @@ def font(self, new_font): self.anchored_position = current_anchored_position @property - def anchor_point(self): + def anchor_point(self) -> Tuple[float, float]: """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.)""" return self._anchor_point @anchor_point.setter - def anchor_point(self, new_anchor_point): + def anchor_point(self, new_anchor_point: Tuple[float, float]) -> None: if self._anchor_point is not None: current_anchored_position = self.anchored_position - self._anchor_point = new_anchor_point - self.anchored_position = current_anchored_position + if new_anchor_point[1] == self.baseline: + self._anchor_point = (new_anchor_point[0], -1) + self.anchored_position = current_anchored_position + else: + self._anchor_point = new_anchor_point + self.anchored_position = current_anchored_position else: - self._anchor_point = new_anchor_point + if new_anchor_point[1] == self.baseline: + self._anchor_point = (new_anchor_point[0], -1.0) + else: + self._anchor_point = new_anchor_point @property - def anchored_position(self): + def anchored_position(self) -> Tuple[int, int]: """Position relative to the anchor_point. Tuple containing x,y pixel coordinates.""" if self._anchor_point is None: @@ -455,7 +463,7 @@ def anchored_position(self): ) @anchored_position.setter - def anchored_position(self, new_position): + def anchored_position(self, new_position: Tuple[int, int]) -> None: if (self._anchor_point is None) or (new_position is None): return # Note: anchor_point must be set before setting anchored_position self.x = int( @@ -463,8 +471,14 @@ def anchored_position(self, new_position): - (self._boundingbox[0] * self.scale) - round(self._anchor_point[0] * (self._boundingbox[2] * self.scale)) ) - self.y = int( - new_position[1] - - (self._boundingbox[1] * self.scale) - - round(self._anchor_point[1] * self._boundingbox[3] * self.scale) - ) + if self._anchor_point[1] == self.baseline: + self.y = int( + new_position[1] + - (self.y_offset * self.scale) + ) + else: + self.y = int( + new_position[1] + - (self._boundingbox[1] * self.scale) + - round(self._anchor_point[1] * self._boundingbox[3] * self.scale) + )