Skip to content

Adding the wrap_by_pixels function #111

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Feb 24, 2021
88 changes: 87 additions & 1 deletion adafruit_display_text/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2020 Tim C for Adafruit Industries
# SPDX-FileCopyrightText: 2020 Tim C, 2021 Jeff Epler for Adafruit Industries
#
# SPDX-License-Identifier: MIT

Expand All @@ -7,6 +7,92 @@
"""


def wrap_text_to_pixels(string, max_width, font=None, indent0="", indent1=""):
"""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
you wish to use leading whitespace see `indend0` and `indent1`
parameters.

:param str string: The text to be wrapped.
:param int max_width: The maximum number of pixels on a line before wrapping.
:param Font font: The font to use for measuring the text.
:param str indent0: Additional character(s) to add to the first line.
:param str indent1: Additional character(s) to add to all other lines.


:return list lines: A list of the lines resulting from wrapping the
input text at max_width pixels size

"""
# pylint: disable=too-many-locals too-many-branches
if font is None:

def measure(string):
return len(string)

else:
if hasattr(font, "load_glyphs"):
font.load_glyphs(string)

def measure(string):
return sum(font.get_glyph(ord(c)).shift_x for c in string)

lines = []
partial = [indent0]
width = measure(indent0)
swidth = measure(" ")
firstword = True
for line_in_input in string.split("\n"):
for index, word in enumerate(line_in_input.split(" ")):
wwidth = measure(word)
word_parts = []
cur_part = ""

if wwidth > max_width:
for char in word:
if (
measure("".join(partial))
+ measure(cur_part)
+ measure(char)
+ measure("-")
> max_width
):
word_parts.append("".join(partial) + cur_part + "-")
cur_part = char
partial = [indent1]
else:
cur_part += char
if cur_part:
word_parts.append(cur_part)
for line in word_parts[:-1]:
lines.append(line)
partial.append(word_parts[-1])
width = measure(word_parts[-1])
if firstword:
firstword = False
else:
if firstword:
partial.append(word)
firstword = False
width += wwidth
elif width + swidth + wwidth < max_width:
if index > 0:
partial.append(" ")
partial.append(word)
width += wwidth + swidth
else:
lines.append("".join(partial))
partial = [indent1, word]
width = measure(indent1) + wwidth

lines.append("".join(partial))
partial = [indent1]
width = measure(indent1)

return lines


def wrap_text_to_lines(string, max_chars):
"""wrap_text_to_lines function
A helper that will return a list of lines with word-break wrapping
Expand Down
63 changes: 63 additions & 0 deletions examples/display_text_wrap_pixels_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# SPDX-FileCopyrightText: 2021 Tim C, written for Adafruit Industries
#
# SPDX-License-Identifier: MIT
"""
Test the wrap_text_to_pixels function. Try changing WRAP_WIDTH or text
and observe the results. The red bar represents the full size of
WRAP_WIDTH.
"""

import board
import displayio
import terminalio
from adafruit_display_text import label, wrap_text_to_pixels

WRAP_WIDTH = 140
text = (
"CircuitPython is a programming language designed to simplify experimenting "
"and learning to code on low-cost microcontroller boards. "
)

# use built in display (PyPortal, PyGamer, PyBadge, CLUE, etc.)
# see guide for setting up external displays (TFT / OLED breakouts, RGB matrices, etc.)
# https://learn.adafruit.com/circuitpython-display-support-using-displayio/display-and-display-bus
display = board.DISPLAY

# Make the display context
main_group = displayio.Group(max_size=10)
display.show(main_group)

font = terminalio.FONT

print(text)
print(display.width)

text_area = label.Label(
font,
text="\n".join(wrap_text_to_pixels(text, WRAP_WIDTH, font)),
background_color=0x0000DD,
)

text_area.anchor_point = (0, 0)
text_area.anchored_position = (0, 0)

main_group.append(text_area)

# Create a bitmap with two colors
size_checker = displayio.Bitmap(WRAP_WIDTH, 10, 2)
# Create a two color palette
palette = displayio.Palette(2)
palette[0] = 0x0000DD
palette[1] = 0xDD0000

# Create a TileGrid using the Bitmap and Palette
tile_grid = displayio.TileGrid(size_checker, pixel_shader=palette)

tile_grid.y = text_area.bounding_box[1] + text_area.bounding_box[3] + 10

size_checker.fill(1)

main_group.append(tile_grid)

while True:
pass