From f0d04478fa344e5bfd78facb7e0b8d35b5d4957c Mon Sep 17 00:00:00 2001 From: jposada202020 Date: Tue, 9 Mar 2021 21:42:12 -0500 Subject: [PATCH 1/7] base_alignment anchor point --- adafruit_display_text/__init__.py | 29 +++++++++++++++++++++++------ adafruit_display_text/label.py | 10 +++++----- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/adafruit_display_text/__init__.py b/adafruit_display_text/__init__.py index acdb2e5..1e21b4b 100644 --- a/adafruit_display_text/__init__.py +++ b/adafruit_display_text/__init__.py @@ -221,6 +221,14 @@ def __init__( self.local_group = None self._text = text + self._baseline = -1.0 + + self.base_alignment = base_alignment + + if self.base_alignment: + self._y_offset = 0 + else: + self._y_offset = self._get_ascent() // 2 def _get_ascent_descent(self): """ Private function to calculate ascent and descent font values """ @@ -298,7 +306,10 @@ def anchor_point(self): @anchor_point.setter def anchor_point(self, new_anchor_point): - 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 self.anchored_position = ( self._anchored_position ) # update the anchored_position using setter @@ -319,11 +330,17 @@ def anchored_position(self, new_position): - (self._bounding_box[0] * self.scale) - round(self._anchor_point[0] * (self._bounding_box[2] * self.scale)) ) - self.y = int( - new_position[1] - - (self._bounding_box[1] * self.scale) - - round(self._anchor_point[1] * self._bounding_box[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._bounding_box[1] * self.scale) + - round(self._anchor_point[1] * self._bounding_box[3] * self.scale) + ) @property def scale(self): diff --git a/adafruit_display_text/label.py b/adafruit_display_text/label.py index b93b969..88b5309 100755 --- a/adafruit_display_text/label.py +++ b/adafruit_display_text/label.py @@ -238,9 +238,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 @@ -260,9 +260,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: From b52126b15a6b60093058f822a4d90ce07760cbd3 Mon Sep 17 00:00:00 2001 From: jposada202020 Date: Tue, 9 Mar 2021 21:46:55 -0500 Subject: [PATCH 2/7] making baseline public to use it in CP code --- 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 1e21b4b..1e2464c 100644 --- a/adafruit_display_text/__init__.py +++ b/adafruit_display_text/__init__.py @@ -221,7 +221,7 @@ def __init__( self.local_group = None self._text = text - self._baseline = -1.0 + self.baseline = -1.0 self.base_alignment = base_alignment @@ -306,7 +306,7 @@ def anchor_point(self): @anchor_point.setter def anchor_point(self, new_anchor_point): - 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 @@ -330,7 +330,7 @@ def anchored_position(self, new_position): - (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) From 88163142a623b6b08fdb7b629435c81b2d2a2c2e Mon Sep 17 00:00:00 2001 From: jposada202020 Date: Tue, 9 Mar 2021 22:08:38 -0500 Subject: [PATCH 3/7] black and pylint --- adafruit_display_text/__init__.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/adafruit_display_text/__init__.py b/adafruit_display_text/__init__.py index 1e2464c..a41003e 100644 --- a/adafruit_display_text/__init__.py +++ b/adafruit_display_text/__init__.py @@ -331,10 +331,7 @@ def anchored_position(self, new_position): - round(self._anchor_point[0] * (self._bounding_box[2] * self.scale)) ) if self._anchor_point[1] == self.baseline: - self.y = int( - new_position[1] - - (self._y_offset * self.scale) - ) + self.y = int(new_position[1] - (self._y_offset * self.scale)) else: self.y = int( new_position[1] From 33bffb8a054a4446c8bd0c974eca13e74bd35408 Mon Sep 17 00:00:00 2001 From: jposada202020 Date: Tue, 9 Mar 2021 22:42:51 -0500 Subject: [PATCH 4/7] Type Annotations --- adafruit_display_text/__init__.py | 88 ++++++++++++++++--------------- adafruit_display_text/label.py | 22 ++++---- 2 files changed, 58 insertions(+), 52 deletions(-) diff --git a/adafruit_display_text/__init__.py b/adafruit_display_text/__init__.py index a41003e..f48d871 100644 --- a/adafruit_display_text/__init__.py +++ b/adafruit_display_text/__init__.py @@ -6,7 +6,10 @@ Display Text module helper functions """ from displayio import Group, Palette - +try: + from typing import Tuple +except: + pass def wrap_text_to_pixels(string, max_width, font=None, indent0="", indent1=""): """wrap_text_to_pixels function @@ -183,27 +186,26 @@ class LabelBase(Group): def __init__( self, font, - x=0, - y=0, - text="", - max_glyphs=None, - # with label.py - 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, - save_text=True, # can reduce memory use if save_text = False - scale=1, - base_alignment=False, - tab_replacement=(4, " "), + 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, + 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, " "), **kwargs, - ): + ) -> None: super().__init__(max_size=1, x=x, y=y, scale=1) self._font = font @@ -230,7 +232,7 @@ def __init__( else: self._y_offset = self._get_ascent() // 2 - 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 @@ -251,29 +253,29 @@ 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] @property - def font(self): + def font(self) -> None: """Font to use for text display.""" return self._font - def _set_font(self, new_font): + def _set_font(self, new_font) -> None: # subclasses should override this pass @font.setter - def font(self, new_font): + def font(self, new_font) -> None: self._set_font(new_font) @property - def color(self): + def color(self) -> int: """Color of the text as an RGB hex number.""" return self._color @color.setter - def color(self, new_color): + def color(self, new_color: int): self._color = new_color if new_color is not None: self.palette[1] = new_color @@ -283,12 +285,12 @@ 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._background_color = new_color if new_color is not None: self.palette[0] = new_color @@ -298,14 +300,14 @@ def background_color(self, new_color): self.palette.make_transparent(0) @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 new_anchor_point[1] == self.baseline: self._anchor_point = (new_anchor_point[0], -1.0) else: @@ -315,13 +317,13 @@ def anchor_point(self, new_anchor_point): ) # update the anchored_position using setter @property - def anchored_position(self): + def anchored_position(self) -> Tuple[int, int]: """Position relative to the anchor_point. Tuple containing x,y pixel coordinates.""" return self._anchored_position @anchored_position.setter - def anchored_position(self, new_position): + def anchored_position(self, new_position: Tuple[int, int]) -> None: self._anchored_position = new_position # Set anchored_position if (self._anchor_point is not None) and (self._anchored_position is not None): @@ -340,44 +342,44 @@ def anchored_position(self, new_position): ) @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: self.local_group.scale = new_scale self.anchored_position = self._anchored_position # update the anchored_position - def _set_text(self, new_text, scale): + def _set_text(self, new_text: str, scale: int) -> None: # subclasses should override this pass @property - def text(self): + def text(self) -> str: """Text to be displayed.""" return self._text @text.setter # Cannot set color or background color with text setter, use separate setter - def text(self, new_text): + def text(self, new_text: str) -> None: self._set_text(new_text, self.scale) @property - def bounding_box(self): + def bounding_box(self) -> Tuple[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._bounding_box) @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 - def _set_line_spacing(self, new_line_spacing): + def _set_line_spacing(self, new_line_spacing: float) -> None: # subclass should override this. pass @line_spacing.setter - def line_spacing(self, new_line_spacing): + def line_spacing(self, new_line_spacing: float) -> None: self._set_line_spacing(new_line_spacing) diff --git a/adafruit_display_text/label.py b/adafruit_display_text/label.py index 88b5309..d5af2ef 100755 --- a/adafruit_display_text/label.py +++ b/adafruit_display_text/label.py @@ -23,6 +23,10 @@ """ import displayio +try: + from typing import Tuple +except: + pass __version__ = "0.0.0-auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Display_Text.git" @@ -71,7 +75,7 @@ class Label(LabelBase): # 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): + def __init__(self, font, **kwargs) -> None: super().__init__(font, **kwargs) max_glyphs = kwargs.get("max_glyphs", None) @@ -130,7 +134,7 @@ def __init__(self, font, **kwargs): ): self.anchored_position = kwargs.get("anchored_position", None) - 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""" @@ -172,7 +176,7 @@ def _create_background_box(self, lines, y_offset): return tile_grid - 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.""" @@ -228,8 +232,8 @@ def _update_background_color(self, new_color): self._added_background_tilegrid = False def _update_text( - self, new_text - ): # pylint: disable=too-many-locals ,too-many-branches, too-many-statements + 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: @@ -305,7 +309,7 @@ def _update_text( if self.background_color is not None: self._update_background_color(self._background_color) - def _reset_text(self, new_text): + 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 @@ -314,7 +318,7 @@ def _reset_text(self, new_text): except RuntimeError as run_error: raise RuntimeError("Text length exceeds max_glyphs") from run_error - def _set_font(self, new_font): + def _set_font(self, new_font) -> None: old_text = self._text current_anchored_position = self.anchored_position self._text = "" @@ -323,9 +327,9 @@ def _set_font(self, new_font): self._update_text(str(old_text)) self.anchored_position = current_anchored_position - def _set_line_spacing(self, new_line_spacing): + def _set_line_spacing(self, new_line_spacing: float) -> None: self._line_spacing = new_line_spacing self.text = self._text # redraw the box - def _set_text(self, new_text, scale): + def _set_text(self, new_text: str, scale: int) -> None: self._reset_text(new_text) From 865501202c928339c2b3cb91de5a101ca88ff699 Mon Sep 17 00:00:00 2001 From: jposada202020 Date: Tue, 9 Mar 2021 22:59:40 -0500 Subject: [PATCH 5/7] Type Annotations changes --- adafruit_display_text/__init__.py | 5 +- adafruit_display_text/bitmap_label.py | 83 ++++++++++++++------------- adafruit_display_text/label.py | 4 -- 3 files changed, 47 insertions(+), 45 deletions(-) diff --git a/adafruit_display_text/__init__.py b/adafruit_display_text/__init__.py index f48d871..aa2c3c1 100644 --- a/adafruit_display_text/__init__.py +++ b/adafruit_display_text/__init__.py @@ -5,11 +5,12 @@ """ Display Text module helper functions """ -from displayio import Group, Palette try: from typing import Tuple except: pass +from displayio import Group, Palette + def wrap_text_to_pixels(string, max_width, font=None, indent0="", indent1=""): """wrap_text_to_pixels function @@ -201,7 +202,7 @@ def __init__( 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, + scale: int = 1, base_alignment: bool = False, tab_replacement: Tuple[int, str] = (4, " "), **kwargs, diff --git a/adafruit_display_text/bitmap_label.py b/adafruit_display_text/bitmap_label.py index 027a691..84ebf79 100755 --- a/adafruit_display_text/bitmap_label.py +++ b/adafruit_display_text/bitmap_label.py @@ -22,7 +22,10 @@ https://github.com/adafruit/circuitpython/releases """ - +try: + from typing import Tuple +except: + pass import displayio __version__ = "0.0.0-auto.0" @@ -80,7 +83,7 @@ class Label(LabelBase): # Note: max_glyphs parameter is unnecessary, this is used for direct # compatibility with label.py - def __init__(self, font, **kwargs): + def __init__(self, font, **kwargs) -> None: super().__init__(font, **kwargs) @@ -126,22 +129,22 @@ def __init__(self, font, **kwargs): def _reset_text( self, font=None, - x=None, - y=None, - text=None, - line_spacing=None, - background_tight=None, - padding_top=None, - padding_bottom=None, - padding_left=None, - padding_right=None, - anchor_point=None, - anchored_position=None, - save_text=None, - scale=None, - base_alignment=None, - tab_replacement=None, - ): + x: int = None, + 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, + padding_right: int = 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, + ) -> None: # Store all the instance variables if font is not None: @@ -288,12 +291,14 @@ def _reset_text( # x,y positions of the label @staticmethod - def _line_spacing_ypixels(font, line_spacing): + def _line_spacing_ypixels(font, line_spacing: float) -> int: # Note: Scaling is provided at the Group level return_value = int(line_spacing * font.get_bounding_box()[1]) return return_value - def _text_bounding_box(self, text, font, line_spacing): + def _text_bounding_box( + self, text: str, font, line_spacing: float + ) -> Tuple[int, int, int, int, int, int]: ascender_max, descender_max = self._get_ascent_descent() lines = 1 @@ -371,17 +376,17 @@ def _text_bounding_box(self, text, font, line_spacing): def _place_text( self, bitmap, - text, + text: str, font, - line_spacing, - xposition, - yposition, - text_palette_index=1, - background_palette_index=0, - skip_index=0, # set to None to write all pixels, other wise skip this palette index + 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) - ): + ) -> Tuple[int, int, int, int]: # placeText - Writes text into a bitmap at the specified location. # # Note: scale is pushed up to Group level @@ -469,16 +474,16 @@ def _place_text( def _blit( self, bitmap, # target bitmap - x, # target x upper left corner - y, # target y upper left corner + x: int, # target x upper left corner + y: int, # target y upper left corner source_bitmap, # source bitmap - x_1=0, # source x start - y_1=0, # source y start - x_2=None, # source x end - y_2=None, # source y end - skip_index=None, # palette index that will not be copied + x_1: int = 0, # source x start + y_1: int = 0, # source y start + x_2: int = None, # source x end + y_2: int = None, # source y end + skip_index: int = None, # palette index that will not be copied # (for example: the background color of a glyph) - ): + ) -> None: if hasattr(bitmap, "blit"): # if bitmap has a built-in blit function, call it # this function should perform its own input checks @@ -538,19 +543,19 @@ def _blit( elif y_placement > bitmap.height: break - def _set_line_spacing(self, new_line_spacing): + def _set_line_spacing(self, new_line_spacing: float) -> None: if self._save_text: self._reset_text(line_spacing=new_line_spacing, scale=self.scale) else: raise RuntimeError("line_spacing is immutable when save_text is False") - def _set_font(self, new_font): + def _set_font(self, new_font) -> None: self._font = new_font if self._save_text: self._reset_text(font=new_font, scale=self.scale) else: raise RuntimeError("font is immutable when save_text is False") - def _set_text(self, new_text, scale): + 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) diff --git a/adafruit_display_text/label.py b/adafruit_display_text/label.py index d5af2ef..aa7c23c 100755 --- a/adafruit_display_text/label.py +++ b/adafruit_display_text/label.py @@ -23,10 +23,6 @@ """ import displayio -try: - from typing import Tuple -except: - pass __version__ = "0.0.0-auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Display_Text.git" From 69e3c7c41e7f28170734398008ca9baa69fafaa2 Mon Sep 17 00:00:00 2001 From: jposada202020 Date: Tue, 9 Mar 2021 23:15:43 -0500 Subject: [PATCH 6/7] Pylint corrections --- adafruit_display_text/__init__.py | 9 ++++++--- adafruit_display_text/bitmap_label.py | 2 +- adafruit_display_text/label.py | 1 + 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/adafruit_display_text/__init__.py b/adafruit_display_text/__init__.py index aa2c3c1..4ed611d 100644 --- a/adafruit_display_text/__init__.py +++ b/adafruit_display_text/__init__.py @@ -5,14 +5,17 @@ """ Display Text module helper functions """ + try: from typing import Tuple -except: +except ImportError: pass from displayio import Group, Palette -def wrap_text_to_pixels(string, max_width, font=None, indent0="", indent1=""): +def wrap_text_to_pixels( + string: str, max_width: int, font=None, indent0: str = "", indent1: str = "" +) -> None: """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 @@ -30,7 +33,7 @@ def wrap_text_to_pixels(string, max_width, font=None, indent0="", indent1=""): input text at max_width pixels size """ - # pylint: disable=too-many-locals too-many-branches + # pylint: disable=too-many-locals, too-many-branches if font is None: def measure(string): diff --git a/adafruit_display_text/bitmap_label.py b/adafruit_display_text/bitmap_label.py index 84ebf79..6fda123 100755 --- a/adafruit_display_text/bitmap_label.py +++ b/adafruit_display_text/bitmap_label.py @@ -24,7 +24,7 @@ """ try: from typing import Tuple -except: +except ImportError: pass import displayio diff --git a/adafruit_display_text/label.py b/adafruit_display_text/label.py index aa7c23c..b231d74 100755 --- a/adafruit_display_text/label.py +++ b/adafruit_display_text/label.py @@ -227,6 +227,7 @@ def _update_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 From bbe9e8cdda288610772d77743d8b22483c4dfb5a Mon Sep 17 00:00:00 2001 From: foamyguy Date: Sat, 13 Mar 2021 20:16:44 -0600 Subject: [PATCH 7/7] remove extra colons in docstring --- adafruit_display_text/bitmap_label.py | 4 ++-- adafruit_display_text/label.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/adafruit_display_text/bitmap_label.py b/adafruit_display_text/bitmap_label.py index d0b757c..b459388 100755 --- a/adafruit_display_text/bitmap_label.py +++ b/adafruit_display_text/bitmap_label.py @@ -72,9 +72,9 @@ class Label(LabelBase): :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. + :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 + :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""" diff --git a/adafruit_display_text/label.py b/adafruit_display_text/label.py index c6325af..5c4472c 100755 --- a/adafruit_display_text/label.py +++ b/adafruit_display_text/label.py @@ -64,7 +64,7 @@ class Label(LabelBase): :param int scale: Integer value of the pixel scaling :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 + :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"""