From cd34c8597224adae5aa1a59d34a1a144231d8712 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Fri, 7 Jul 2023 17:54:41 -0500 Subject: [PATCH 1/5] initial commit for outlined_label --- adafruit_display_text/__init__.py | 0 adafruit_display_text/bitmap_label.py | 0 adafruit_display_text/label.py | 0 adafruit_display_text/outlined_label.py | 137 ++++++++++++++++++++++++ 4 files changed, 137 insertions(+) mode change 100755 => 100644 adafruit_display_text/__init__.py mode change 100755 => 100644 adafruit_display_text/bitmap_label.py mode change 100755 => 100644 adafruit_display_text/label.py create mode 100644 adafruit_display_text/outlined_label.py diff --git a/adafruit_display_text/__init__.py b/adafruit_display_text/__init__.py old mode 100755 new mode 100644 diff --git a/adafruit_display_text/bitmap_label.py b/adafruit_display_text/bitmap_label.py old mode 100755 new mode 100644 diff --git a/adafruit_display_text/label.py b/adafruit_display_text/label.py old mode 100755 new mode 100644 diff --git a/adafruit_display_text/outlined_label.py b/adafruit_display_text/outlined_label.py new file mode 100644 index 0000000..405e5af --- /dev/null +++ b/adafruit_display_text/outlined_label.py @@ -0,0 +1,137 @@ +# SPDX-FileCopyrightText: 2023 Tim C +# +# SPDX-License-Identifier: MIT + +""" +`adafruit_display_text.outlined_label` +==================================================== + +Subclass of BitmapLabel that adds outline color and stroke size +functionalities. + +* Author(s): Tim Cocks + +Implementation Notes +-------------------- + +**Hardware:** + +**Software and Dependencies:** + +* Adafruit CircuitPython firmware for the supported boards: + https://circuitpython.org/downloads + +""" +__version__ = "0.0.0+auto.0" +__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Display_Text.git" + +import bitmaptools +import traceback +from adafruit_display_text import bitmap_label +from displayio import Palette, Bitmap + +try: + from typing import Optional, Tuple + from fontio import FontProtocol +except ImportError: + pass + + +class OutlinedLabel(bitmap_label.Label): + def __init__(self, font, outline_color=0x999999, outline_size=1, **kwargs): + super().__init__(font, **kwargs) + + _background_color = self._palette[0] + _foreground_color = self._palette[1] + _background_is_transparent = self._palette.is_transparent(0) + self._palette = Palette(3) + self._palette[0] = _background_color + self._palette[1] = _foreground_color + self._palette[2] = outline_color + if _background_is_transparent: + self._palette.make_transparent(0) + + self._outline_size = outline_size + self._stamp_source = Bitmap((outline_size * 2) + 1, (outline_size * 2) + 1, 3) + self._stamp_source.fill(2) + + self._bitmap = None + + self._reset_text( + font=font, + text=self._text, + line_spacing=self._line_spacing, + scale=self.scale, + ) + + def _add_outline(self): + try: + # before = time.monotonic() + + for y in range(self.bitmap.height): + for x in range(self.bitmap.width): + if self.bitmap[x, y] == 1: + # bitmap.blit(x-size,y-size, stamp_source, skip_self_index=target_color_index) + bitmaptools.blit( + self.bitmap, + self._stamp_source, + x - self._outline_size, + y - self._outline_size, + skip_dest_index=1, + ) + # bitmaptools.blit(bitmap, stamp_source, x - size, y - size) + # for y_loc in range(-size, size+1): + # for x_loc in range(-size, size+1): + # if bitmap[x+x_loc, y+y_loc] != target_color_index: + # bitmap[x + x_loc, y + y_loc] = outline_color_index + except ValueError as ve: + # print(traceback.print_exception(ve)) + pass + except AttributeError as ae: + # print(traceback.print_exception(ae)) + pass + + def _place_text( + self, + bitmap: Bitmap, + text: str, + font: FontProtocol, + xposition: int, + yposition: int, + 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) + ) -> Tuple[int, int, int, int]: + parent_result = super()._place_text( + bitmap, text, font, xposition, yposition, skip_index=skip_index + ) + + self._add_outline() + + return parent_result + + @property + def outline_color(self): + return self._palette[2] + + @outline_color.setter + def outline_color(self, new_outline_color): + self._palette[2] = new_outline_color + + @property + def outline_size(self): + return self._outline_size + + @outline_size.setter + def outline_size(self, new_outline_size): + self._outline_size = new_outline_size + self._stamp_source = Bitmap( + (new_outline_size * 2) + 1, (new_outline_size * 2) + 1, 3 + ) + self._stamp_source.fill(2) + self._reset_text( + font=self._font, + text=self._text, + line_spacing=self._line_spacing, + scale=self.scale, + ) From caa41001866fff361498df2ef2dff73b51a31ed6 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Sat, 8 Jul 2023 11:19:56 -0500 Subject: [PATCH 2/5] handle padding, fix format and pylint issues --- adafruit_display_text/outlined_label.py | 86 ++++++++++++++----- docs/api.rst | 3 + docs/examples.rst | 9 ++ .../display_text_outlined_label_simpletest.py | 21 +++++ 4 files changed, 97 insertions(+), 22 deletions(-) create mode 100644 examples/display_text_outlined_label_simpletest.py diff --git a/adafruit_display_text/outlined_label.py b/adafruit_display_text/outlined_label.py index 405e5af..a42b912 100644 --- a/adafruit_display_text/outlined_label.py +++ b/adafruit_display_text/outlined_label.py @@ -26,20 +26,55 @@ __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Display_Text.git" import bitmaptools -import traceback -from adafruit_display_text import bitmap_label from displayio import Palette, Bitmap +from adafruit_display_text import bitmap_label try: - from typing import Optional, Tuple + from typing import Optional, Tuple, Union from fontio import FontProtocol except ImportError: pass class OutlinedLabel(bitmap_label.Label): - def __init__(self, font, outline_color=0x999999, outline_size=1, **kwargs): - super().__init__(font, **kwargs) + """ + OutlinedLabel - A BitmapLabel subclass that includes arguments and properties for specifying + outline_size and outline_color to get drawn as a stroke around the text. + + :param Union[Tuple, int] outline_color: The color of the outline stroke as RGB tuple, or hex. + :param int outline_size: The size in pixels of the outline stroke. + + """ + + # pylint: disable=too-many-arguments + def __init__( + self, + font, + outline_color: Union[int, Tuple] = 0x999999, + outline_size: int = 1, + padding_top: Optional[int] = None, + padding_bottom: Optional[int] = None, + padding_left: Optional[int] = None, + padding_right: Optional[int] = None, + **kwargs + ): + if padding_top is None: + padding_top = outline_size + 0 + if padding_bottom is None: + padding_bottom = outline_size + 2 + if padding_left is None: + padding_left = outline_size + 0 + if padding_right is None: + padding_right = outline_size + 0 + + super().__init__( + font, + padding_top=padding_top, + padding_bottom=padding_bottom, + padding_left=padding_left, + padding_right=padding_right, + **kwargs + ) _background_color = self._palette[0] _foreground_color = self._palette[1] @@ -65,31 +100,30 @@ def __init__(self, font, outline_color=0x999999, outline_size=1, **kwargs): ) def _add_outline(self): - try: - # before = time.monotonic() - + if hasattr(self, "_stamp_source"): for y in range(self.bitmap.height): for x in range(self.bitmap.width): if self.bitmap[x, y] == 1: - # bitmap.blit(x-size,y-size, stamp_source, skip_self_index=target_color_index) - bitmaptools.blit( - self.bitmap, - self._stamp_source, - x - self._outline_size, - y - self._outline_size, - skip_dest_index=1, - ) + try: + bitmaptools.blit( + self.bitmap, + self._stamp_source, + x - self._outline_size, + y - self._outline_size, + skip_dest_index=1, + ) + except ValueError as value_error: + raise ValueError( + "Padding must be big enough to fit outline_size " + "all the way around the text. " + "Try using either larger padding sizes, or smaller outline_size." + ) from value_error + # bitmaptools.blit(bitmap, stamp_source, x - size, y - size) # for y_loc in range(-size, size+1): # for x_loc in range(-size, size+1): # if bitmap[x+x_loc, y+y_loc] != target_color_index: # bitmap[x + x_loc, y + y_loc] = outline_color_index - except ValueError as ve: - # print(traceback.print_exception(ve)) - pass - except AttributeError as ae: - # print(traceback.print_exception(ae)) - pass def _place_text( self, @@ -112,6 +146,7 @@ def _place_text( @property def outline_color(self): + """Color of the outline to draw around the text.""" return self._palette[2] @outline_color.setter @@ -120,11 +155,18 @@ def outline_color(self, new_outline_color): @property def outline_size(self): + """Stroke size of the outline to draw around the text.""" return self._outline_size @outline_size.setter def outline_size(self, new_outline_size): self._outline_size = new_outline_size + + self._padding_top = new_outline_size + 0 + self._padding_bottom = new_outline_size + 2 + self._padding_left = new_outline_size + 0 + self._padding_right = new_outline_size + 0 + self._stamp_source = Bitmap( (new_outline_size * 2) + 1, (new_outline_size * 2) + 1, 3 ) diff --git a/docs/api.rst b/docs/api.rst index 8e456ce..00350e7 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -16,3 +16,6 @@ .. automodule:: adafruit_display_text.scrolling_label :members: + +.. automodule:: adafruit_display_text.outlined_label + :members: diff --git a/docs/examples.rst b/docs/examples.rst index bf00290..e29c190 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -25,6 +25,15 @@ Simple test using scrolling_label to display text :caption: examples/display_text_scrolling_label.py :linenos: +OutlinedLabel Simple Test +------------------------- + +Simple test using outlined_label to display text with a stroke outline + +.. literalinclude:: ../examples/display_text_outlined_label_simpletest.py + :caption: examples/display_text_outlined_label_simpletest.py + :linenos: + Label vs Bitmap_label Comparison -------------------------------- diff --git a/examples/display_text_outlined_label_simpletest.py b/examples/display_text_outlined_label_simpletest.py new file mode 100644 index 0000000..d341e6a --- /dev/null +++ b/examples/display_text_outlined_label_simpletest.py @@ -0,0 +1,21 @@ +# SPDX-FileCopyrightText: 2023 Tim C +# SPDX-License-Identifier: MIT + +import board +import terminalio +from adafruit_display_text import outlined_label + +text = "Hello world" +text_area = outlined_label.OutlinedLabel( + terminalio.FONT, + text=text, + color=0xFF00FF, + outline_color=0x00FF00, + outline_size=1, + scale=2, +) +text_area.x = 10 +text_area.y = 14 +board.DISPLAY.show(text_area) +while True: + pass From a88968ffcbad0e775a53ac92f5932980f1e16303 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Fri, 15 Mar 2024 17:04:11 -0500 Subject: [PATCH 3/5] 9.X API, anchor positioning, bigger scale, set paddings in example. allow smaller screens. --- adafruit_display_text/outlined_label.py | 21 +++++++++++++------ .../display_text_outlined_label_simpletest.py | 18 +++++++++++----- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/adafruit_display_text/outlined_label.py b/adafruit_display_text/outlined_label.py index a42b912..1c66a99 100644 --- a/adafruit_display_text/outlined_label.py +++ b/adafruit_display_text/outlined_label.py @@ -100,6 +100,11 @@ def __init__( ) def _add_outline(self): + """ + Blit the outline into the labels Bitmap. We will stamp self._stamp_source for each + pixel of the foreground color but skip the foreground color when we blit. + :return: None + """ if hasattr(self, "_stamp_source"): for y in range(self.bitmap.height): for x in range(self.bitmap.width): @@ -119,12 +124,6 @@ def _add_outline(self): "Try using either larger padding sizes, or smaller outline_size." ) from value_error - # bitmaptools.blit(bitmap, stamp_source, x - size, y - size) - # for y_loc in range(-size, size+1): - # for x_loc in range(-size, size+1): - # if bitmap[x+x_loc, y+y_loc] != target_color_index: - # bitmap[x + x_loc, y + y_loc] = outline_color_index - def _place_text( self, bitmap: Bitmap, @@ -136,6 +135,16 @@ def _place_text( # when copying glyph bitmaps (this is important for slanted text # where rectangular glyph boxes overlap) ) -> Tuple[int, int, int, int]: + """ + Copy the glpyphs that represent the value of the string into the labels Bitmap. + :param bitmap: The bitmap to place text into + :param text: The text to render + :param font: The font to render the text in + :param xposition: x location of the starting point within the bitmap + :param yposition: y location of the starting point within the bitmap + :param skip_index: Color index to skip during rendering instead of covering up + :return Tuple bounding_box: tuple with x, y, width, height values of the bitmap + """ parent_result = super()._place_text( bitmap, text, font, xposition, yposition, skip_index=skip_index ) diff --git a/examples/display_text_outlined_label_simpletest.py b/examples/display_text_outlined_label_simpletest.py index d341e6a..cc80124 100644 --- a/examples/display_text_outlined_label_simpletest.py +++ b/examples/display_text_outlined_label_simpletest.py @@ -5,17 +5,25 @@ import terminalio from adafruit_display_text import outlined_label -text = "Hello world" +if board.DISPLAY.width <= 150: + text = "Hello\nworld" +else: + text = "Hello world" + text_area = outlined_label.OutlinedLabel( terminalio.FONT, text=text, color=0xFF00FF, outline_color=0x00FF00, outline_size=1, - scale=2, + padding_left=2, + padding_right=2, + padding_top=2, + padding_bottom=2, + scale=3, ) -text_area.x = 10 -text_area.y = 14 -board.DISPLAY.show(text_area) +text_area.anchor_point = (0,0) +text_area.anchored_position = (10, 10) +board.DISPLAY.root_group = text_area while True: pass From c543874ac4d89e7ae29ceeb6ccfd1962863aea53 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Fri, 15 Mar 2024 17:08:40 -0500 Subject: [PATCH 4/5] revert chmod to match main --- adafruit_display_text/__init__.py | 0 adafruit_display_text/bitmap_label.py | 0 adafruit_display_text/label.py | 0 3 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 adafruit_display_text/__init__.py mode change 100644 => 100755 adafruit_display_text/bitmap_label.py mode change 100644 => 100755 adafruit_display_text/label.py diff --git a/adafruit_display_text/__init__.py b/adafruit_display_text/__init__.py old mode 100644 new mode 100755 diff --git a/adafruit_display_text/bitmap_label.py b/adafruit_display_text/bitmap_label.py old mode 100644 new mode 100755 diff --git a/adafruit_display_text/label.py b/adafruit_display_text/label.py old mode 100644 new mode 100755 From 88775e0251c18e5d74076dc5179009dc047989ca Mon Sep 17 00:00:00 2001 From: foamyguy Date: Fri, 15 Mar 2024 17:21:07 -0500 Subject: [PATCH 5/5] format --- examples/display_text_outlined_label_simpletest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/display_text_outlined_label_simpletest.py b/examples/display_text_outlined_label_simpletest.py index cc80124..f82ca15 100644 --- a/examples/display_text_outlined_label_simpletest.py +++ b/examples/display_text_outlined_label_simpletest.py @@ -22,7 +22,7 @@ padding_bottom=2, scale=3, ) -text_area.anchor_point = (0,0) +text_area.anchor_point = (0, 0) text_area.anchored_position = (10, 10) board.DISPLAY.root_group = text_area while True: