Skip to content

Adds RGB888 Support and optimizes text drawing #34

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 3 commits into from
Sep 10, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 56 additions & 6 deletions adafruit_framebuf.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@

CircuitPython pure-python framebuf module, based on the micropython framebuf module.

* Author(s): Kattni Rembor, Tony DiCola, original file created by Damien P. George
* Author(s): Melissa LeBlanc-Williams, Kattni Rembor, Tony DiCola, original file
created by Damien P. George

Implementation Notes
--------------------
Expand All @@ -52,6 +53,7 @@
RGB565 = 1 # 16-bit color displays
GS4_HMSB = 2 # Unimplemented!
MHMSB = 3 # Single bit displays like the Sharp Memory
RGB888 = 4 # Neopixels and Dotstars


class MHMSBFormat:
Expand Down Expand Up @@ -142,6 +144,46 @@ def fill_rect(framebuf, x, y, width, height, color):
height -= 1


class RGB888Format:
"""RGB888Format"""

@staticmethod
def set_pixel(framebuf, x, y, color):
"""Set a given pixel to a color."""
index = (y * framebuf.stride + x) * 3
framebuf.buf[index : index + 3] = bytes(
((color >> 16) & 255, (color >> 8) & 255, color & 255)
)

@staticmethod
def get_pixel(framebuf, x, y):
"""Get the color of a given pixel"""
index = (y * framebuf.stride + x) * 3
return (
(framebuf.buf[index] << 16)
| (framebuf.buf[index + 1] << 8)
| framebuf.buf[index + 2]
)

@staticmethod
def fill(framebuf, color):
"""completely fill/clear the buffer with a color"""
fill = (color >> 16) & 255, (color >> 8) & 255, color & 255
for i in range(0, len(framebuf.buf), 3):
framebuf.buf[i : i + 3] = bytes(fill)

@staticmethod
def fill_rect(framebuf, x, y, width, height, color):
"""Draw a rectangle at the given location, size and color. The ``fill_rect`` method draws
both the outline and interior."""
# pylint: disable=too-many-arguments
fill = (color >> 16) & 255, (color >> 8) & 255, color & 255
for _x in range(x, x + width):
for _y in range(y, y + height):
index = (_y * framebuf.stride + _x) * 3
framebuf.buf[index : index + 3] = bytes(fill)


class FrameBuffer:
"""FrameBuffer object.

Expand Down Expand Up @@ -174,6 +216,8 @@ def __init__(self, buf, width, height, buf_format=MVLSB, stride=None):
self.format = MVLSBFormat()
elif buf_format == MHMSB:
self.format = MHMSBFormat()
elif buf_format == RGB888:
self.format = RGB888Format()
else:
raise ValueError("invalid format")
self._rotation = 0
Expand Down Expand Up @@ -360,12 +404,18 @@ def text(self, string, x, y, color, *, font_name="font5x8.bin", size=1):
if not self._font or self._font.font_name != font_name:
# load the font!
self._font = BitmapFont(font_name)
w = self._font.font_width
width = self._font.font_width
height = self._font.font_height
for i, char in enumerate(chunk):
self._font.draw_char(
char, x + (i * (w + 1)) * size, y, self, color, size=size
)
y += self._font.font_height * size
char_x = x + (i * (width + 1)) * size
if (
char_x + (width * size) > 0
and char_x < self.width
and y + (height * size) > 0
and y < self.height
):
self._font.draw_char(char, char_x, y, self, color, size=size)
y += height * size

# pylint: enable=too-many-arguments

Expand Down