Compare commits
No commits in common. "master" and "setup-py-disabled" have entirely different histories.
master
...
setup-py-d
12 changed files with 94 additions and 5382 deletions
|
|
@ -6,7 +6,7 @@ Introduction
|
|||
:alt: Documentation Status
|
||||
|
||||
.. image:: https://img.shields.io/discord/327254708534116352.svg
|
||||
:target: https://adafru.it/discord
|
||||
:target: https://discord.gg/nBQh6qu
|
||||
:alt: Discord
|
||||
|
||||
.. image:: https://github.com/adafruit/Adafruit_CircuitPython_Display_Text/workflows/Build%20CI/badge.svg
|
||||
|
|
|
|||
|
|
@ -1,528 +0,0 @@
|
|||
# The MIT License (MIT)
|
||||
#
|
||||
# Copyright (c) 2020 Kevin Matocha
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
"""
|
||||
`bitmap_label`
|
||||
================================================================================
|
||||
|
||||
Text graphics handling for CircuitPython, including text boxes
|
||||
|
||||
|
||||
* Author(s): Kevin Matocha
|
||||
|
||||
Implementation Notes
|
||||
--------------------
|
||||
|
||||
**Hardware:**
|
||||
|
||||
**Software and Dependencies:**
|
||||
|
||||
* Adafruit CircuitPython firmware for the supported boards:
|
||||
https://github.com/adafruit/circuitpython/releases
|
||||
|
||||
"""
|
||||
|
||||
import displayio
|
||||
|
||||
__version__ = "0.0.0-auto.0"
|
||||
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Display_Text.git"
|
||||
|
||||
|
||||
class Label(displayio.Group):
|
||||
"""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``.
|
||||
For the bitmap_label library, the font, text, and line_spacing must be set at
|
||||
instancing and are immutable. The ``max_glyphs`` parameter is ignored and is present
|
||||
only for direct compatability with label.py.
|
||||
For use cases where text changes are required after the initial instancing, please
|
||||
use the `label.py` library.
|
||||
For further reduction in memory usage, set save_text to False (text string will not
|
||||
be stored).
|
||||
|
||||
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,
|
||||
it will try to have it be center-left as close as possible.
|
||||
|
||||
: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 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
|
||||
:param boolean background_tight: Set `True` only if you want background box to tightly
|
||||
surround text
|
||||
: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
|
||||
:param int padding_left: Additional pixels added to background bounding box at left
|
||||
:param int padding_right: Additional pixels added to background bounding box at right
|
||||
:param (double,double) 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.)
|
||||
: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.
|
||||
"""
|
||||
|
||||
# pylint: disable=unused-argument, too-many-instance-attributes, too-many-locals, too-many-arguments
|
||||
# pylint: disable=too-many-branches, no-self-use
|
||||
# Note: max_glyphs parameter is unnecessary, this is used for direct
|
||||
# compatibility with label.py
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
font,
|
||||
x=0,
|
||||
y=0,
|
||||
text="",
|
||||
max_glyphs=None, # This input parameter is ignored, only present for compatibility
|
||||
# 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
|
||||
**kwargs
|
||||
):
|
||||
|
||||
if text == "":
|
||||
raise RuntimeError(
|
||||
"Please provide text string, or use label.py for mutable text"
|
||||
)
|
||||
|
||||
self._font = font
|
||||
|
||||
# Scale will be passed to Group using kwargs.
|
||||
if "scale" in kwargs.keys():
|
||||
self._scale = kwargs["scale"]
|
||||
else:
|
||||
self._scale = 1
|
||||
|
||||
self._line_spacing = line_spacing
|
||||
self._save_text = save_text
|
||||
|
||||
if self._save_text: # text string will be saved
|
||||
self._text = text
|
||||
else:
|
||||
self._text = None # save a None value since text string is not saved
|
||||
|
||||
# limit padding to >= 0
|
||||
padding_top = max(0, padding_top)
|
||||
padding_bottom = max(0, padding_bottom)
|
||||
padding_left = max(0, padding_left)
|
||||
padding_right = max(0, padding_right)
|
||||
|
||||
# Calculate the text bounding box
|
||||
|
||||
# Calculate tight box to provide bounding box dimensions to match label for
|
||||
# anchor_position calculations
|
||||
(
|
||||
tight_box_x,
|
||||
tight_box_y,
|
||||
tight_x_offset,
|
||||
tight_y_offset,
|
||||
) = self._text_bounding_box(
|
||||
text, font, self._line_spacing, background_tight=True,
|
||||
)
|
||||
|
||||
if background_tight:
|
||||
box_x = tight_box_x
|
||||
box_y = tight_box_y
|
||||
y_offset = tight_y_offset
|
||||
x_offset = tight_x_offset
|
||||
|
||||
else:
|
||||
(box_x, box_y, x_offset, y_offset) = self._text_bounding_box(
|
||||
text, font, self._line_spacing, background_tight=background_tight,
|
||||
)
|
||||
# Calculate the background size including padding
|
||||
box_x = box_x + padding_left + padding_right
|
||||
box_y = box_y + padding_top + padding_bottom
|
||||
|
||||
# Create the two-color palette
|
||||
self.palette = displayio.Palette(2)
|
||||
|
||||
self.background_color = background_color
|
||||
self.color = color
|
||||
|
||||
# Create the bitmap and TileGrid
|
||||
self.bitmap = displayio.Bitmap(box_x, box_y, len(self.palette))
|
||||
|
||||
# Place the text into the Bitmap
|
||||
self._place_text(
|
||||
self.bitmap,
|
||||
text,
|
||||
font,
|
||||
self._line_spacing,
|
||||
padding_left - x_offset,
|
||||
padding_top + y_offset,
|
||||
)
|
||||
|
||||
label_position_yoffset = int( # To calibrate with label.py positioning
|
||||
(font.get_glyph(ord("M")).height) / 2
|
||||
)
|
||||
|
||||
self.tilegrid = displayio.TileGrid(
|
||||
self.bitmap,
|
||||
pixel_shader=self.palette,
|
||||
width=1,
|
||||
height=1,
|
||||
tile_width=box_x,
|
||||
tile_height=box_y,
|
||||
default_tile=0,
|
||||
x=-padding_left + x_offset,
|
||||
y=label_position_yoffset - y_offset - padding_top,
|
||||
)
|
||||
|
||||
# instance the Group
|
||||
# this Group will contain just one TileGrid with one contained bitmap
|
||||
super().__init__(
|
||||
max_size=1, x=x, y=y, **kwargs
|
||||
) # this will include any arguments, including scale
|
||||
self.append(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.
|
||||
|
||||
self._bounding_box = (
|
||||
self.tilegrid.x,
|
||||
self.tilegrid.y,
|
||||
tight_box_x,
|
||||
tight_box_y,
|
||||
)
|
||||
|
||||
self._anchored_position = anchored_position
|
||||
self.anchor_point = anchor_point
|
||||
self.anchored_position = (
|
||||
self._anchored_position
|
||||
) # sets anchored_position with setter after bitmap is created
|
||||
|
||||
@staticmethod
|
||||
def _line_spacing_ypixels(font, line_spacing):
|
||||
# Note: Scale is not implemented at this time, any scaling is pushed up to 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, background_tight=False):
|
||||
|
||||
# This empirical approach checks several glyphs for maximum ascender and descender height
|
||||
# (consistent with label.py)
|
||||
glyphs = "M j'" # choose glyphs with highest ascender and lowest
|
||||
# descender, will depend upon font used
|
||||
|
||||
try:
|
||||
self._font.load_glyphs(text + glyphs)
|
||||
except AttributeError:
|
||||
# ignore if font does not have load_glyphs
|
||||
pass
|
||||
|
||||
ascender_max = descender_max = 0
|
||||
for char in glyphs:
|
||||
this_glyph = font.get_glyph(ord(char))
|
||||
if this_glyph:
|
||||
ascender_max = max(ascender_max, this_glyph.height + this_glyph.dy)
|
||||
descender_max = max(descender_max, -this_glyph.dy)
|
||||
|
||||
lines = 1
|
||||
|
||||
xposition = (
|
||||
x_start
|
||||
) = yposition = y_start = 0 # starting x and y position (left margin)
|
||||
|
||||
left = None
|
||||
right = x_start
|
||||
top = bottom = y_start
|
||||
|
||||
y_offset_tight = int((font.get_glyph(ord("M")).height) / 2)
|
||||
# this needs to be reviewed (also in label.py), since it doesn't respond
|
||||
# properly to the number of newlines.
|
||||
|
||||
newline = False
|
||||
|
||||
for char in text:
|
||||
|
||||
if char == "\n": # newline
|
||||
newline = True
|
||||
|
||||
else:
|
||||
|
||||
my_glyph = font.get_glyph(ord(char))
|
||||
|
||||
if my_glyph is None: # Error checking: no glyph found
|
||||
print("Glyph not found: {}".format(repr(char)))
|
||||
else:
|
||||
if newline:
|
||||
newline = False
|
||||
xposition = x_start # reset to left column
|
||||
yposition = yposition + self._line_spacing_ypixels(
|
||||
font, line_spacing
|
||||
) # Add a newline
|
||||
lines += 1
|
||||
if xposition == x_start:
|
||||
if left is None:
|
||||
left = my_glyph.dx
|
||||
else:
|
||||
left = min(left, my_glyph.dx)
|
||||
xright = xposition + my_glyph.width + my_glyph.dx
|
||||
xposition += my_glyph.shift_x
|
||||
|
||||
right = max(right, xposition, xright)
|
||||
|
||||
if yposition == y_start: # first line, find the Ascender height
|
||||
top = min(top, -my_glyph.height - my_glyph.dy + y_offset_tight)
|
||||
bottom = max(bottom, yposition - my_glyph.dy + y_offset_tight)
|
||||
|
||||
if left is None:
|
||||
left = 0
|
||||
|
||||
final_box_width = right - left
|
||||
if background_tight:
|
||||
final_box_height = bottom - top
|
||||
final_y_offset = -top + y_offset_tight
|
||||
|
||||
else:
|
||||
final_box_height = (lines - 1) * self._line_spacing_ypixels(
|
||||
font, line_spacing
|
||||
) + (ascender_max + descender_max)
|
||||
final_y_offset = ascender_max
|
||||
|
||||
return (final_box_width, final_box_height, left, final_y_offset)
|
||||
|
||||
# pylint: disable=too-many-nested-blocks
|
||||
def _place_text(
|
||||
self,
|
||||
bitmap,
|
||||
text,
|
||||
font,
|
||||
line_spacing,
|
||||
xposition,
|
||||
yposition,
|
||||
text_palette_index=1,
|
||||
background_palette_index=0,
|
||||
print_only_pixels=True, # print_only_pixels = True: only update the bitmap where the glyph
|
||||
# pixel color is > 0. This is especially useful for script fonts where glyph
|
||||
# bounding boxes overlap
|
||||
# Set `print_only_pixels=False` to write all pixels
|
||||
):
|
||||
# placeText - Writes text into a bitmap at the specified location.
|
||||
#
|
||||
# Verify paletteIndex is working properly with * operator, especially
|
||||
# if accommodating multicolored fonts
|
||||
#
|
||||
# Note: Scale is not implemented at this time, is pushed up to Group level
|
||||
|
||||
bitmap_width = bitmap.width
|
||||
bitmap_height = bitmap.height
|
||||
|
||||
x_start = xposition # starting x position (left margin)
|
||||
y_start = yposition
|
||||
|
||||
left = None
|
||||
right = x_start
|
||||
top = bottom = y_start
|
||||
|
||||
for char in text:
|
||||
|
||||
if char == "\n": # newline
|
||||
xposition = x_start # reset to left column
|
||||
yposition = yposition + self._line_spacing_ypixels(
|
||||
font, line_spacing
|
||||
) # Add a newline
|
||||
|
||||
else:
|
||||
|
||||
my_glyph = font.get_glyph(ord(char))
|
||||
|
||||
if my_glyph is None: # Error checking: no glyph found
|
||||
print("Glyph not found: {}".format(repr(char)))
|
||||
else:
|
||||
if xposition == x_start:
|
||||
if left is None:
|
||||
left = my_glyph.dx
|
||||
else:
|
||||
left = min(left, my_glyph.dx)
|
||||
|
||||
right = max(
|
||||
right,
|
||||
xposition + my_glyph.shift_x,
|
||||
xposition + my_glyph.width + my_glyph.dx,
|
||||
)
|
||||
if yposition == y_start: # first line, find the Ascender height
|
||||
top = min(top, -my_glyph.height - my_glyph.dy)
|
||||
bottom = max(bottom, yposition - my_glyph.dy)
|
||||
|
||||
glyph_offset_x = (
|
||||
my_glyph.tile_index * my_glyph.width
|
||||
) # for type BuiltinFont, this creates the x-offset in the glyph bitmap.
|
||||
# for BDF loaded fonts, this should equal 0
|
||||
|
||||
for y in range(my_glyph.height):
|
||||
for x in range(my_glyph.width):
|
||||
x_placement = x + xposition + my_glyph.dx
|
||||
y_placement = y + yposition - my_glyph.height - my_glyph.dy
|
||||
|
||||
if (bitmap_width > x_placement >= 0) and (
|
||||
bitmap_height > y_placement >= 0
|
||||
):
|
||||
|
||||
# Allows for remapping the bitmap indexes using paletteIndex
|
||||
# for background and text.
|
||||
palette_indexes = (
|
||||
background_palette_index,
|
||||
text_palette_index,
|
||||
)
|
||||
|
||||
this_pixel_color = palette_indexes[
|
||||
my_glyph.bitmap[
|
||||
y * my_glyph.bitmap.width + x + glyph_offset_x
|
||||
]
|
||||
]
|
||||
|
||||
if not print_only_pixels or this_pixel_color > 0:
|
||||
# write all characters if printOnlyPixels = False,
|
||||
# or if thisPixelColor is > 0
|
||||
bitmap[
|
||||
y_placement * bitmap_width + x_placement
|
||||
] = this_pixel_color
|
||||
elif y_placement > bitmap_height:
|
||||
break
|
||||
|
||||
xposition = xposition + my_glyph.shift_x
|
||||
|
||||
return (left, top, right - left, bottom - top) # bounding_box
|
||||
|
||||
@property
|
||||
def bounding_box(self):
|
||||
"""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 self._bounding_box
|
||||
|
||||
@property
|
||||
def line_spacing(self):
|
||||
"""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, new_line_spacing):
|
||||
raise RuntimeError(
|
||||
"line_spacing is immutable for bitmap_label.py; use label.py for mutable line_spacing"
|
||||
)
|
||||
|
||||
@property
|
||||
def color(self):
|
||||
"""Color of the text as an RGB hex number."""
|
||||
return self._color
|
||||
|
||||
@color.setter
|
||||
def color(self, new_color):
|
||||
self._color = new_color
|
||||
if new_color is not None:
|
||||
self.palette[1] = new_color
|
||||
self.palette.make_opaque(1)
|
||||
else:
|
||||
self.palette[1] = 0
|
||||
self.palette.make_transparent(1)
|
||||
|
||||
@property
|
||||
def background_color(self):
|
||||
"""Color of the background as an RGB hex number."""
|
||||
return self._background_color
|
||||
|
||||
@background_color.setter
|
||||
def 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)
|
||||
else:
|
||||
self.palette[0] = 0
|
||||
self.palette.make_transparent(0)
|
||||
|
||||
@property
|
||||
def text(self):
|
||||
"""Text to displayed."""
|
||||
return self._text
|
||||
|
||||
@text.setter
|
||||
def text(self, new_text):
|
||||
raise RuntimeError(
|
||||
"text is immutable for bitmap_label.py; use label.py library for mutable text"
|
||||
)
|
||||
|
||||
@property
|
||||
def font(self):
|
||||
"""Font to use for text display."""
|
||||
return self.font
|
||||
|
||||
@font.setter
|
||||
def font(self, new_font):
|
||||
raise RuntimeError(
|
||||
"font is immutable for bitmap_label.py; use label.py library for mutable font"
|
||||
)
|
||||
|
||||
@property
|
||||
def anchor_point(self):
|
||||
"""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):
|
||||
self._anchor_point = new_anchor_point
|
||||
self.anchored_position = (
|
||||
self._anchored_position
|
||||
) # update the anchored_position using setter
|
||||
|
||||
@property
|
||||
def anchored_position(self):
|
||||
"""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):
|
||||
self._anchored_position = new_position
|
||||
|
||||
# Set anchored_position
|
||||
if (self._anchor_point is not None) and (self._anchored_position is not None):
|
||||
self.x = int(
|
||||
new_position[0]
|
||||
- (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)
|
||||
)
|
||||
310
adafruit_display_text/label.py
Executable file → Normal file
310
adafruit_display_text/label.py
Executable file → Normal file
|
|
@ -58,214 +58,84 @@ class Label(displayio.Group):
|
|||
:param int color: Color of all text in RGB hex
|
||||
:param double line_spacing: Line spacing of text to display"""
|
||||
|
||||
# pylint: disable=too-many-instance-attributes, too-many-locals
|
||||
# This has a lot of getters/setters, maybe it needs cleanup.
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
font,
|
||||
*,
|
||||
x=0,
|
||||
y=0,
|
||||
text="",
|
||||
text=None,
|
||||
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,
|
||||
**kwargs
|
||||
):
|
||||
if "scale" in kwargs.keys():
|
||||
self._scale = kwargs["scale"]
|
||||
else:
|
||||
self._scale = 1
|
||||
if not max_glyphs and not text:
|
||||
raise RuntimeError("Please provide a max size, or initial text")
|
||||
if not max_glyphs:
|
||||
max_glyphs = len(text)
|
||||
# add one to max_size for the background bitmap tileGrid
|
||||
super().__init__(max_size=max_glyphs + 1, **kwargs)
|
||||
|
||||
super().__init__(max_size=max_glyphs, **kwargs)
|
||||
self.width = max_glyphs
|
||||
self._font = font
|
||||
self.font = font
|
||||
self._text = None
|
||||
self._anchor_point = anchor_point
|
||||
self._anchor_point = (0, 0)
|
||||
self.x = x
|
||||
self.y = y
|
||||
|
||||
self.height = self._font.get_bounding_box()[1]
|
||||
self.palette = displayio.Palette(2)
|
||||
if background_color is not None:
|
||||
self.palette[0] = background_color
|
||||
self.palette.make_opaque(0)
|
||||
self._transparent_background = False
|
||||
else:
|
||||
self.palette[0] = 0
|
||||
self.palette.make_transparent(0)
|
||||
self._transparent_background = True
|
||||
self.palette[1] = color
|
||||
|
||||
bounds = self.font.get_bounding_box()
|
||||
self.height = bounds[1]
|
||||
self._line_spacing = line_spacing
|
||||
self._boundingbox = None
|
||||
|
||||
self._background_tight = (
|
||||
background_tight # sets padding status for text background box
|
||||
)
|
||||
|
||||
# Create the two-color text palette
|
||||
self.palette = displayio.Palette(2)
|
||||
self.palette[0] = 0
|
||||
self.palette.make_transparent(0)
|
||||
self.color = color
|
||||
|
||||
self._background_color = background_color
|
||||
self._background_palette = displayio.Palette(1)
|
||||
self._added_background_tilegrid = False
|
||||
|
||||
self._padding_top = padding_top
|
||||
self._padding_bottom = padding_bottom
|
||||
self._padding_left = padding_left
|
||||
self._padding_right = padding_right
|
||||
|
||||
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):
|
||||
|
||||
left = self._boundingbox[0]
|
||||
|
||||
if self._background_tight: # draw a tight bounding box
|
||||
box_width = self._boundingbox[2]
|
||||
box_height = self._boundingbox[3]
|
||||
x_box_offset = 0
|
||||
y_box_offset = self._boundingbox[1]
|
||||
|
||||
else: # draw a "loose" bounding box to include any ascenders/descenders.
|
||||
|
||||
# check a few glyphs for maximum ascender and descender height
|
||||
# Enhancement: it would be preferred to access the font "FONT_ASCENT" and
|
||||
# "FONT_DESCENT" in the imported BDF file
|
||||
glyphs = "M j'" # choose glyphs with highest ascender and lowest
|
||||
# descender, will depend upon font used
|
||||
ascender_max = descender_max = 0
|
||||
for char in glyphs:
|
||||
this_glyph = self._font.get_glyph(ord(char))
|
||||
if this_glyph:
|
||||
ascender_max = max(ascender_max, this_glyph.height + this_glyph.dy)
|
||||
descender_max = max(descender_max, -this_glyph.dy)
|
||||
|
||||
box_width = self._boundingbox[2] + self._padding_left + self._padding_right
|
||||
x_box_offset = -self._padding_left
|
||||
box_height = (
|
||||
(ascender_max + descender_max)
|
||||
+ int((lines - 1) * self.height * self._line_spacing)
|
||||
+ self._padding_top
|
||||
+ self._padding_bottom
|
||||
)
|
||||
y_box_offset = -ascender_max + y_offset - self._padding_top
|
||||
|
||||
box_width = max(0, box_width) # remove any negative values
|
||||
box_height = max(0, box_height) # remove any negative values
|
||||
|
||||
background_bitmap = displayio.Bitmap(box_width, box_height, 1)
|
||||
tile_grid = displayio.TileGrid(
|
||||
background_bitmap,
|
||||
pixel_shader=self._background_palette,
|
||||
x=left + x_box_offset,
|
||||
y=y_box_offset,
|
||||
)
|
||||
|
||||
return tile_grid
|
||||
|
||||
def _update_background_color(self, new_color):
|
||||
|
||||
if new_color is None:
|
||||
self._background_palette.make_transparent(0)
|
||||
if self._added_background_tilegrid:
|
||||
self.pop(0)
|
||||
self._added_background_tilegrid = False
|
||||
else:
|
||||
self._background_palette.make_opaque(0)
|
||||
self._background_palette[0] = new_color
|
||||
self._background_color = new_color
|
||||
|
||||
lines = self._text.rstrip("\n").count("\n") + 1
|
||||
y_offset = int((self._font.get_glyph(ord("M")).height) / 2)
|
||||
|
||||
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 (
|
||||
(len(self._text) > 0)
|
||||
and (
|
||||
self._boundingbox[2] + self._padding_left + self._padding_right > 0
|
||||
)
|
||||
and (
|
||||
self._boundingbox[3] + self._padding_top + self._padding_bottom > 0
|
||||
)
|
||||
):
|
||||
if len(self) > 0:
|
||||
self.insert(0, self._create_background_box(lines, y_offset))
|
||||
else:
|
||||
self.append(self._create_background_box(lines, y_offset))
|
||||
self._added_background_tilegrid = True
|
||||
|
||||
else: # a bitmap is present in the self Group
|
||||
# update bitmap if text is present and bitmap sizes > 0 pixels
|
||||
if (
|
||||
(len(self._text) > 0)
|
||||
and (
|
||||
self._boundingbox[2] + self._padding_left + self._padding_right > 0
|
||||
)
|
||||
and (
|
||||
self._boundingbox[3] + self._padding_top + self._padding_bottom > 0
|
||||
)
|
||||
):
|
||||
self[0] = self._create_background_box(lines, y_offset)
|
||||
else: # delete the existing bitmap
|
||||
self.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): # pylint: disable=too-many-locals
|
||||
x = 0
|
||||
y = 0
|
||||
if self._added_background_tilegrid:
|
||||
i = 1
|
||||
else:
|
||||
i = 0
|
||||
tilegrid_count = i
|
||||
|
||||
try:
|
||||
self._font.load_glyphs(new_text + "M")
|
||||
except AttributeError:
|
||||
# ignore if font does not have load_glyphs
|
||||
pass
|
||||
|
||||
y_offset = int((self._font.get_glyph(ord("M")).height) / 2)
|
||||
|
||||
right = top = bottom = 0
|
||||
left = None
|
||||
|
||||
old_c = 0
|
||||
y_offset = int(
|
||||
(
|
||||
self.font.get_glyph(ord("M")).height
|
||||
- new_text.count("\n") * self.height * self.line_spacing
|
||||
)
|
||||
/ 2
|
||||
)
|
||||
# print("y offset from baseline", y_offset)
|
||||
left = right = top = bottom = 0
|
||||
for character in new_text:
|
||||
if character == "\n":
|
||||
y += int(self.height * self._line_spacing)
|
||||
x = 0
|
||||
continue
|
||||
glyph = self._font.get_glyph(ord(character))
|
||||
glyph = self.font.get_glyph(ord(character))
|
||||
if not glyph:
|
||||
continue
|
||||
right = max(right, x + glyph.shift_x, x + glyph.width + glyph.dx)
|
||||
if x == 0:
|
||||
if left is None:
|
||||
left = glyph.dx
|
||||
else:
|
||||
left = min(left, glyph.dx)
|
||||
right = max(right, x + glyph.width)
|
||||
if y == 0: # first line, find the Ascender height
|
||||
top = min(top, -glyph.height - glyph.dy + y_offset)
|
||||
top = min(top, -glyph.height + y_offset)
|
||||
bottom = max(bottom, y - glyph.dy + y_offset)
|
||||
position_y = y - glyph.height - glyph.dy + y_offset
|
||||
position_x = x + glyph.dx
|
||||
if glyph.width > 0 and glyph.height > 0:
|
||||
if (
|
||||
not self._text
|
||||
or old_c >= len(self._text)
|
||||
or character != self._text[old_c]
|
||||
):
|
||||
try:
|
||||
# pylint: disable=unexpected-keyword-arg
|
||||
face = displayio.TileGrid(
|
||||
glyph.bitmap,
|
||||
pixel_shader=self.palette,
|
||||
|
|
@ -284,25 +154,37 @@ class Label(displayio.Group):
|
|||
x=position_x,
|
||||
y=position_y,
|
||||
)
|
||||
if tilegrid_count < len(self):
|
||||
self[tilegrid_count] = face
|
||||
if i < len(self):
|
||||
self[i] = face
|
||||
else:
|
||||
self.append(face)
|
||||
tilegrid_count += 1
|
||||
elif self._text and character == self._text[old_c]:
|
||||
try:
|
||||
self[i].position = (position_x, position_y)
|
||||
except AttributeError:
|
||||
self[i].x = position_x
|
||||
self[i].y = position_y
|
||||
|
||||
x += glyph.shift_x
|
||||
|
||||
# TODO skip this for control sequences or non-printables.
|
||||
i += 1
|
||||
old_c += 1
|
||||
# skip all non-prinables in the old string
|
||||
while (
|
||||
self._text
|
||||
and old_c < len(self._text)
|
||||
and (
|
||||
self._text[old_c] == "\n"
|
||||
or not self.font.get_glyph(ord(self._text[old_c]))
|
||||
)
|
||||
):
|
||||
old_c += 1
|
||||
# Remove the rest
|
||||
|
||||
if left is None:
|
||||
left = 0
|
||||
|
||||
while len(self) > tilegrid_count: # i:
|
||||
while len(self) > i:
|
||||
self.pop()
|
||||
self._text = new_text
|
||||
self._boundingbox = (left, top, right - left, bottom - top)
|
||||
|
||||
if self.background_color is not None:
|
||||
self._update_background_color(self._background_color)
|
||||
self._boundingbox = (left, top, left + right, bottom - top)
|
||||
|
||||
@property
|
||||
def bounding_box(self):
|
||||
|
|
@ -327,22 +209,25 @@ class Label(displayio.Group):
|
|||
|
||||
@color.setter
|
||||
def color(self, new_color):
|
||||
self._color = new_color
|
||||
if new_color is not None:
|
||||
self.palette[1] = new_color
|
||||
self.palette.make_opaque(1)
|
||||
else:
|
||||
self.palette[1] = 0
|
||||
self.palette.make_transparent(1)
|
||||
|
||||
@property
|
||||
def background_color(self):
|
||||
"""Color of the background as an RGB hex number."""
|
||||
return self._background_color
|
||||
if not self._transparent_background:
|
||||
return self.palette[0]
|
||||
return None
|
||||
|
||||
@background_color.setter
|
||||
def background_color(self, new_color):
|
||||
self._update_background_color(new_color)
|
||||
if new_color is not None:
|
||||
self.palette[0] = new_color
|
||||
self.palette.make_opaque(0)
|
||||
self._transparent_background = False
|
||||
else:
|
||||
self.palette[0] = 0
|
||||
self.palette.make_transparent(0)
|
||||
self._transparent_background = True
|
||||
|
||||
@property
|
||||
def text(self):
|
||||
|
|
@ -351,27 +236,7 @@ class Label(displayio.Group):
|
|||
|
||||
@text.setter
|
||||
def text(self, new_text):
|
||||
try:
|
||||
current_anchored_position = self.anchored_position
|
||||
self._update_text(str(new_text))
|
||||
self.anchored_position = current_anchored_position
|
||||
except RuntimeError as run_error:
|
||||
raise RuntimeError("Text length exceeds max_glyphs") from run_error
|
||||
|
||||
@property
|
||||
def font(self):
|
||||
"""Font to use for text display."""
|
||||
return self._font
|
||||
|
||||
@font.setter
|
||||
def font(self, new_font):
|
||||
old_text = self._text
|
||||
current_anchored_position = self.anchored_position
|
||||
self._text = ""
|
||||
self._font = new_font
|
||||
self.height = self._font.get_bounding_box()[1]
|
||||
self._update_text(str(old_text))
|
||||
self.anchored_position = current_anchored_position
|
||||
|
||||
@property
|
||||
def anchor_point(self):
|
||||
|
|
@ -382,43 +247,18 @@ class Label(displayio.Group):
|
|||
|
||||
@anchor_point.setter
|
||||
def anchor_point(self, new_anchor_point):
|
||||
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
|
||||
else:
|
||||
self._anchor_point = new_anchor_point
|
||||
|
||||
@property
|
||||
def anchored_position(self):
|
||||
"""Position relative to the anchor_point. Tuple containing x,y
|
||||
pixel coordinates."""
|
||||
if self._anchor_point is None:
|
||||
return None
|
||||
return (
|
||||
int(
|
||||
self.x
|
||||
+ (self._boundingbox[0] * self._scale)
|
||||
+ round(self._anchor_point[0] * self._boundingbox[2] * self._scale)
|
||||
),
|
||||
int(
|
||||
self.y
|
||||
+ (self._boundingbox[1] * self._scale)
|
||||
+ round(self._anchor_point[1] * self._boundingbox[3] * self._scale)
|
||||
),
|
||||
self.x - self._boundingbox[2] * self._anchor_point[0],
|
||||
self.y - self._boundingbox[3] * self._anchor_point[1],
|
||||
)
|
||||
|
||||
@anchored_position.setter
|
||||
def anchored_position(self, new_position):
|
||||
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(
|
||||
new_position[0]
|
||||
- (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)
|
||||
)
|
||||
self.x = int(new_position[0] - (self._boundingbox[2] * self._anchor_point[0]))
|
||||
self.y = int(new_position[1] - (self._boundingbox[3] * self._anchor_point[1]))
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ This examples shows the use of anchor_point and anchored_position.
|
|||
"""
|
||||
import board
|
||||
import terminalio
|
||||
import displayio
|
||||
from adafruit_display_text import label
|
||||
import displayio
|
||||
|
||||
DISPLAY_WIDTH = 320
|
||||
DISPLAY_HEIGHT = 240
|
||||
|
|
@ -12,19 +12,19 @@ TEXT = "Hello"
|
|||
|
||||
text_area_top_left = label.Label(terminalio.FONT, text=TEXT)
|
||||
text_area_top_left.anchor_point = (0.0, 0.0)
|
||||
text_area_top_left.anchored_position = (0, 0)
|
||||
text_area_top_left.anchored_position = (10, 10)
|
||||
|
||||
text_area_top_middle = label.Label(terminalio.FONT, text=TEXT)
|
||||
text_area_top_middle.anchor_point = (0.5, 0.0)
|
||||
text_area_top_middle.anchored_position = (DISPLAY_WIDTH / 2, 0)
|
||||
text_area_top_middle.anchored_position = (DISPLAY_WIDTH / 2, 10)
|
||||
|
||||
text_area_top_right = label.Label(terminalio.FONT, text=TEXT)
|
||||
text_area_top_right.anchor_point = (1.0, 0.0)
|
||||
text_area_top_right.anchored_position = (DISPLAY_WIDTH, 0)
|
||||
text_area_top_right.anchored_position = (DISPLAY_WIDTH - 10, 10)
|
||||
|
||||
text_area_middle_left = label.Label(terminalio.FONT, text=TEXT)
|
||||
text_area_middle_left.anchor_point = (0.0, 0.5)
|
||||
text_area_middle_left.anchored_position = (0, DISPLAY_HEIGHT / 2)
|
||||
text_area_middle_left.anchored_position = (10, DISPLAY_HEIGHT / 2)
|
||||
|
||||
text_area_middle_middle = label.Label(terminalio.FONT, text=TEXT)
|
||||
text_area_middle_middle.anchor_point = (0.5, 0.5)
|
||||
|
|
@ -32,11 +32,11 @@ text_area_middle_middle.anchored_position = (DISPLAY_WIDTH / 2, DISPLAY_HEIGHT /
|
|||
|
||||
text_area_middle_right = label.Label(terminalio.FONT, text=TEXT)
|
||||
text_area_middle_right.anchor_point = (1.0, 0.5)
|
||||
text_area_middle_right.anchored_position = (DISPLAY_WIDTH, DISPLAY_HEIGHT / 2)
|
||||
text_area_middle_right.anchored_position = (DISPLAY_WIDTH - 10, DISPLAY_HEIGHT / 2)
|
||||
|
||||
text_area_bottom_left = label.Label(terminalio.FONT, text=TEXT)
|
||||
text_area_bottom_left.anchor_point = (0.0, 1.0)
|
||||
text_area_bottom_left.anchored_position = (0, DISPLAY_HEIGHT)
|
||||
text_area_bottom_left.anchored_position = (10, DISPLAY_HEIGHT)
|
||||
|
||||
text_area_bottom_middle = label.Label(terminalio.FONT, text=TEXT)
|
||||
text_area_bottom_middle.anchor_point = (0.5, 1.0)
|
||||
|
|
@ -44,7 +44,7 @@ text_area_bottom_middle.anchored_position = (DISPLAY_WIDTH / 2, DISPLAY_HEIGHT)
|
|||
|
||||
text_area_bottom_right = label.Label(terminalio.FONT, text=TEXT)
|
||||
text_area_bottom_right.anchor_point = (1.0, 1.0)
|
||||
text_area_bottom_right.anchored_position = (DISPLAY_WIDTH, DISPLAY_HEIGHT)
|
||||
text_area_bottom_right.anchored_position = (DISPLAY_WIDTH - 10, DISPLAY_HEIGHT)
|
||||
|
||||
text_group = displayio.Group(max_size=9)
|
||||
text_group.append(text_area_top_middle)
|
||||
|
|
|
|||
|
|
@ -1,125 +0,0 @@
|
|||
"""
|
||||
This examples shows the use color and background_color
|
||||
"""
|
||||
import time
|
||||
import board
|
||||
import displayio
|
||||
|
||||
|
||||
# from adafruit_st7789 import ST7789
|
||||
from adafruit_ili9341 import ILI9341
|
||||
from adafruit_bitmap_font import bitmap_font
|
||||
from adafruit_display_text import label
|
||||
|
||||
# Setup the SPI display
|
||||
|
||||
print("Starting the display...") # goes to serial only
|
||||
displayio.release_displays()
|
||||
|
||||
|
||||
spi = board.SPI()
|
||||
tft_cs = board.D9 # arbitrary, pin not used
|
||||
tft_dc = board.D10
|
||||
tft_backlight = board.D12
|
||||
tft_reset = board.D11
|
||||
|
||||
while not spi.try_lock():
|
||||
spi.configure(baudrate=32000000)
|
||||
spi.unlock()
|
||||
|
||||
display_bus = displayio.FourWire(
|
||||
spi,
|
||||
command=tft_dc,
|
||||
chip_select=tft_cs,
|
||||
reset=tft_reset,
|
||||
baudrate=32000000,
|
||||
polarity=1,
|
||||
phase=1,
|
||||
)
|
||||
|
||||
print("spi.frequency: {}".format(spi.frequency))
|
||||
|
||||
DISPLAY_WIDTH = 320
|
||||
DISPLAY_HEIGHT = 240
|
||||
|
||||
# display = ST7789(display_bus, width=240, height=240, rotation=0, rowstart=80, colstart=0)
|
||||
display = ILI9341(
|
||||
display_bus,
|
||||
width=DISPLAY_WIDTH,
|
||||
height=DISPLAY_HEIGHT,
|
||||
rotation=180,
|
||||
auto_refresh=True,
|
||||
)
|
||||
|
||||
display.show(None)
|
||||
|
||||
# font=terminalio.FONT # this is the Builtin fixed dimension font
|
||||
|
||||
font = bitmap_font.load_font("fonts/Helvetica-Bold-16.bdf")
|
||||
|
||||
|
||||
text = []
|
||||
text.append("none") # no ascenders or descenders
|
||||
text.append("pop quops") # only descenders
|
||||
text.append("MONSTERs are tall") # only ascenders
|
||||
text.append("MONSTERs ate pop quops") # both ascenders and descenders
|
||||
text.append("MONSTER quops\nnewline quops") # with newline
|
||||
|
||||
display.auto_refresh = True
|
||||
myGroup = displayio.Group(max_size=6)
|
||||
display.show(myGroup)
|
||||
|
||||
text_area = []
|
||||
myPadding = 4
|
||||
|
||||
for i, thisText in enumerate(text):
|
||||
text_area.append(
|
||||
label.Label(
|
||||
font,
|
||||
text=thisText,
|
||||
color=0xFFFFFF,
|
||||
background_color=None,
|
||||
background_tight=False,
|
||||
padding_top=myPadding,
|
||||
padding_bottom=myPadding,
|
||||
padding_left=myPadding,
|
||||
padding_right=myPadding,
|
||||
)
|
||||
)
|
||||
|
||||
this_x = 10
|
||||
this_y = 10 + i * 40
|
||||
text_area[i].x = 10
|
||||
text_area[i].y = 3 + i * 50
|
||||
text_area[i].anchor_point = (0, 0)
|
||||
text_area[i].anchored_position = (this_x, this_y)
|
||||
myGroup.append(text_area[i])
|
||||
|
||||
print("background color is {}".format(text_area[0].background_color))
|
||||
|
||||
|
||||
while True:
|
||||
time.sleep(2)
|
||||
text_area[0].text = "text" # change some text in an existing text box
|
||||
# Note: changed text must fit within existing number of characters
|
||||
# when the Label was created
|
||||
|
||||
for area in text_area:
|
||||
area.background_color = 0xFF0000
|
||||
print("background color is {:06x}".format(text_area[0].background_color))
|
||||
time.sleep(2)
|
||||
for area in text_area:
|
||||
area.background_color = 0x000088
|
||||
print("background color is {:06x}".format(text_area[0].background_color))
|
||||
time.sleep(2)
|
||||
for area in text_area:
|
||||
area.background_color = 0x00FF00
|
||||
print("background color is {:06x}".format(text_area[0].background_color))
|
||||
time.sleep(2)
|
||||
for area in text_area:
|
||||
area.background_color = 0xFF0000
|
||||
print("background color is {:06x}".format(text_area[0].background_color))
|
||||
time.sleep(2)
|
||||
for area in text_area:
|
||||
area.background_color = None
|
||||
print("background color is {}".format(text_area[0].background_color))
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
import board
|
||||
import terminalio
|
||||
from adafruit_display_text import bitmap_label
|
||||
|
||||
|
||||
text = "Hello world"
|
||||
text_area = bitmap_label.Label(terminalio.FONT, text=text)
|
||||
text_area.x = 10
|
||||
text_area.y = 10
|
||||
board.DISPLAY.show(text_area)
|
||||
while True:
|
||||
pass
|
||||
|
|
@ -1,222 +0,0 @@
|
|||
# Sample for comparing label and bitmap_label positioning with Builtin or loaded BDF fonts
|
||||
|
||||
# pylint: disable=no-member
|
||||
|
||||
import gc
|
||||
import board
|
||||
import displayio
|
||||
import terminalio
|
||||
from adafruit_bitmap_font import bitmap_font
|
||||
|
||||
from adafruit_display_text import bitmap_label
|
||||
from adafruit_display_text import label
|
||||
|
||||
# pylint: disable=no-member
|
||||
|
||||
|
||||
##########
|
||||
# Use this Boolean variables to select which font style to use
|
||||
##########
|
||||
use_builtinfont = False # Set True to use the terminalio.FONT BuiltinFont,
|
||||
fontToUse = terminalio.FONT
|
||||
# Set False to use a BDF loaded font, see "fontFiles" below
|
||||
##########
|
||||
|
||||
if not use_builtinfont:
|
||||
# load the fonts
|
||||
print("loading font...")
|
||||
|
||||
fontList = []
|
||||
|
||||
# Load some proportional fonts
|
||||
fontFile = "fonts/Helvetica-Bold-16.bdf"
|
||||
fontToUse = bitmap_font.load_font(fontFile)
|
||||
|
||||
# Set scaling factor for display text
|
||||
my_scale = 1
|
||||
|
||||
# Setup the SPI display
|
||||
if "DISPLAY" not in dir(board):
|
||||
# Setup the LCD display with driver
|
||||
# You may need to change this to match the display driver for the chipset
|
||||
# used on your display
|
||||
from adafruit_ili9341 import ILI9341
|
||||
|
||||
displayio.release_displays()
|
||||
|
||||
# setup the SPI bus
|
||||
spi = board.SPI()
|
||||
tft_cs = board.D9 # arbitrary, pin not used
|
||||
tft_dc = board.D10
|
||||
tft_backlight = board.D12
|
||||
tft_reset = board.D11
|
||||
|
||||
while not spi.try_lock():
|
||||
spi.configure(baudrate=32000000)
|
||||
spi.unlock()
|
||||
|
||||
display_bus = displayio.FourWire(
|
||||
spi,
|
||||
command=tft_dc,
|
||||
chip_select=tft_cs,
|
||||
reset=tft_reset,
|
||||
baudrate=32000000,
|
||||
polarity=1,
|
||||
phase=1,
|
||||
)
|
||||
|
||||
# Number of pixels in the display
|
||||
DISPLAY_WIDTH = 320
|
||||
DISPLAY_HEIGHT = 240
|
||||
|
||||
# create the display
|
||||
display = ILI9341(
|
||||
display_bus,
|
||||
width=DISPLAY_WIDTH,
|
||||
height=DISPLAY_HEIGHT,
|
||||
rotation=180, # The rotation can be adjusted to match your configuration.
|
||||
auto_refresh=True,
|
||||
native_frames_per_second=90,
|
||||
)
|
||||
|
||||
# reset the display to show nothing.
|
||||
display.show(None)
|
||||
else:
|
||||
# built-in display
|
||||
display = board.DISPLAY
|
||||
|
||||
print("Display is started")
|
||||
|
||||
|
||||
preload_glyphs = (
|
||||
True # set this to True if you want to preload the font glyphs into memory
|
||||
)
|
||||
# preloading the glyphs will help speed up the rendering of text but will use more RAM
|
||||
|
||||
if preload_glyphs and not use_builtinfont:
|
||||
|
||||
# identify the glyphs to load into memory -> increases rendering speed
|
||||
glyphs = (
|
||||
b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/-_,.:?!'\n "
|
||||
)
|
||||
|
||||
print("loading glyphs...")
|
||||
fontToUse.load_glyphs(glyphs)
|
||||
|
||||
print("Glyphs are loaded.")
|
||||
|
||||
print("Fonts completed loading.")
|
||||
|
||||
# create group
|
||||
|
||||
long_string = "The purple snake\nbrings python fun\nto everyone."
|
||||
label2_padding = 10
|
||||
|
||||
#####
|
||||
# Create the "bitmap_label.py" versions of the text labels.
|
||||
|
||||
gc.collect()
|
||||
bitmap_label_start = gc.mem_free()
|
||||
|
||||
bmap_label1 = bitmap_label.Label(
|
||||
font=fontToUse,
|
||||
text="bitmap_label",
|
||||
color=0xFFFFFF,
|
||||
background_color=0xFF0000,
|
||||
padding_bottom=0,
|
||||
padding_left=0,
|
||||
padding_right=0,
|
||||
padding_top=0,
|
||||
background_tight=True,
|
||||
line_spacing=1.25,
|
||||
scale=my_scale,
|
||||
anchor_point=(0.0, 0),
|
||||
anchored_position=(10, 60),
|
||||
)
|
||||
|
||||
bmap_label2 = bitmap_label.Label(
|
||||
font=fontToUse,
|
||||
text=long_string,
|
||||
color=0x000000,
|
||||
max_glyphs=len(long_string),
|
||||
background_color=0xFFFF00,
|
||||
padding_bottom=label2_padding,
|
||||
padding_left=0,
|
||||
padding_right=0,
|
||||
padding_top=label2_padding,
|
||||
background_tight=False,
|
||||
line_spacing=1.25,
|
||||
scale=my_scale,
|
||||
anchor_point=(0.0, 0),
|
||||
anchored_position=(10, 120),
|
||||
)
|
||||
|
||||
gc.collect()
|
||||
bitmap_label_end = gc.mem_free()
|
||||
|
||||
print("bitmap_label used: {} memory".format(bitmap_label_start - bitmap_label_end))
|
||||
|
||||
bmap_group = displayio.Group(max_size=4) # Create a group for displaying
|
||||
bmap_group.append(bmap_label1)
|
||||
bmap_group.append(bmap_label2)
|
||||
|
||||
|
||||
#####
|
||||
# Create the "label.py" versions of the text labels.
|
||||
|
||||
gc.collect()
|
||||
label_start = gc.mem_free()
|
||||
|
||||
label1 = label.Label(
|
||||
font=fontToUse,
|
||||
text="label",
|
||||
color=0xFFFFFF,
|
||||
background_color=0xFF0000,
|
||||
padding_bottom=0,
|
||||
padding_left=0,
|
||||
padding_right=0,
|
||||
padding_top=0,
|
||||
background_tight=True,
|
||||
line_spacing=1.25,
|
||||
scale=my_scale,
|
||||
anchor_point=(1.0, 0),
|
||||
anchored_position=(display.width - 10, 60),
|
||||
)
|
||||
|
||||
label2 = label.Label(
|
||||
font=fontToUse,
|
||||
text=long_string,
|
||||
color=0x000000,
|
||||
max_glyphs=len(long_string),
|
||||
background_color=0xFFFF00,
|
||||
padding_bottom=label2_padding,
|
||||
padding_left=0,
|
||||
padding_right=0,
|
||||
padding_top=label2_padding,
|
||||
background_tight=False,
|
||||
line_spacing=1.25,
|
||||
scale=my_scale,
|
||||
anchor_point=(1.0, 0),
|
||||
anchored_position=(display.width - 10, 120),
|
||||
)
|
||||
|
||||
gc.collect()
|
||||
label_end = gc.mem_free()
|
||||
|
||||
print("label used: {} memory".format(label_start - label_end))
|
||||
label_group = displayio.Group(max_size=4) # Create a group for displaying
|
||||
label_group.append(label1)
|
||||
label_group.append(label2)
|
||||
|
||||
|
||||
print("***")
|
||||
|
||||
main_group = displayio.Group()
|
||||
main_group.append(label_group)
|
||||
main_group.append(bmap_group)
|
||||
|
||||
display.auto_refresh = True
|
||||
|
||||
display.show(main_group)
|
||||
while True:
|
||||
pass
|
||||
|
|
@ -1,9 +1,8 @@
|
|||
import os
|
||||
import board
|
||||
import displayio
|
||||
from adafruit_bitmap_font import bitmap_font
|
||||
from adafruit_display_text.label import Label
|
||||
|
||||
from adafruit_bitmap_font import bitmap_font
|
||||
|
||||
# the current working directory (where this file is)
|
||||
cwd = ("/" + __file__).rsplit("/", 1)[0]
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,2 +1,2 @@
|
|||
Adafruit-Blinka
|
||||
adafruit-blinka-displayio
|
||||
|
||||
|
|
|
|||
50
setup.py
50
setup.py
|
|
@ -1,50 +0,0 @@
|
|||
"""A setuptools based setup module.
|
||||
See:
|
||||
https://packaging.python.org/en/latest/distributing.html
|
||||
https://github.com/pypa/sampleproject
|
||||
"""
|
||||
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
# To use a consistent encoding
|
||||
from codecs import open
|
||||
from os import path
|
||||
|
||||
here = path.abspath(path.dirname(__file__))
|
||||
|
||||
# Get the long description from the README file
|
||||
with open(path.join(here, "README.rst"), encoding="utf-8") as f:
|
||||
long_description = f.read()
|
||||
|
||||
setup(
|
||||
name="adafruit-circuitpython-display-text",
|
||||
use_scm_version=True,
|
||||
setup_requires=["setuptools_scm"],
|
||||
description="Displays text using CircuitPython's displayio.",
|
||||
long_description=long_description,
|
||||
long_description_content_type="text/x-rst",
|
||||
# The project's main homepage.
|
||||
url="https://github.com/adafruit/Adafruit_CircuitPython_Display_Text",
|
||||
# Author details
|
||||
author="Adafruit Industries",
|
||||
author_email="circuitpython@adafruit.com",
|
||||
install_requires=["Adafruit-Blinka", "adafruit-blinka-displayio",],
|
||||
# Choose your license
|
||||
license="MIT",
|
||||
# See https://pypi.python.org/pypi?%3Aaction=list_classifiers
|
||||
classifiers=[
|
||||
"Development Status :: 3 - Alpha",
|
||||
"Intended Audience :: Developers",
|
||||
"Topic :: Software Development :: Libraries",
|
||||
"Topic :: System :: Hardware",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.4",
|
||||
"Programming Language :: Python :: 3.5",
|
||||
],
|
||||
# What does your project relate to?
|
||||
keywords="adafruit blinka circuitpython micropython bitmap fonts text display tft lcd displayio",
|
||||
# You can just specify the packages manually here if your project is
|
||||
# simple. Or you can use find_packages().
|
||||
packages=["adafruit_display_text"],
|
||||
)
|
||||
4
setup.py.disabled
Normal file
4
setup.py.disabled
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
"""
|
||||
This library is not deployed to PyPI. It is either a board-specific helper library, or
|
||||
does not make sense for use on or is incompatible with single board computers and Linux.
|
||||
"""
|
||||
Loading…
Reference in a new issue