|  | 
| 25 | 25 | 
 | 
| 26 | 26 | CircuitPython pure-python framebuf module, based on the micropython framebuf module. | 
| 27 | 27 | 
 | 
| 28 |  | -* Author(s): Kattni Rembor, Tony DiCola, original file created by Damien P. George | 
|  | 28 | +* Author(s): Melissa LeBlanc-Williams, Kattni Rembor, Tony DiCola, original file | 
|  | 29 | +             created by Damien P. George | 
| 29 | 30 | 
 | 
| 30 | 31 | Implementation Notes | 
| 31 | 32 | -------------------- | 
|  | 
| 52 | 53 | RGB565 = 1  # 16-bit color displays | 
| 53 | 54 | GS4_HMSB = 2  # Unimplemented! | 
| 54 | 55 | MHMSB = 3  # Single bit displays like the Sharp Memory | 
|  | 56 | +RGB888 = 4  # Neopixels and Dotstars | 
| 55 | 57 | 
 | 
| 56 | 58 | 
 | 
| 57 | 59 | class MHMSBFormat: | 
| @@ -142,6 +144,46 @@ def fill_rect(framebuf, x, y, width, height, color): | 
| 142 | 144 |             height -= 1 | 
| 143 | 145 | 
 | 
| 144 | 146 | 
 | 
|  | 147 | +class RGB888Format: | 
|  | 148 | +    """RGB888Format""" | 
|  | 149 | + | 
|  | 150 | +    @staticmethod | 
|  | 151 | +    def set_pixel(framebuf, x, y, color): | 
|  | 152 | +        """Set a given pixel to a color.""" | 
|  | 153 | +        index = (y * framebuf.stride + x) * 3 | 
|  | 154 | +        framebuf.buf[index : index + 3] = bytes( | 
|  | 155 | +            ((color >> 16) & 255, (color >> 8) & 255, color & 255) | 
|  | 156 | +        ) | 
|  | 157 | + | 
|  | 158 | +    @staticmethod | 
|  | 159 | +    def get_pixel(framebuf, x, y): | 
|  | 160 | +        """Get the color of a given pixel""" | 
|  | 161 | +        index = (y * framebuf.stride + x) * 3 | 
|  | 162 | +        return ( | 
|  | 163 | +            (framebuf.buf[index] << 16) | 
|  | 164 | +            | (framebuf.buf[index + 1] << 8) | 
|  | 165 | +            | framebuf.buf[index + 2] | 
|  | 166 | +        ) | 
|  | 167 | + | 
|  | 168 | +    @staticmethod | 
|  | 169 | +    def fill(framebuf, color): | 
|  | 170 | +        """completely fill/clear the buffer with a color""" | 
|  | 171 | +        fill = (color >> 16) & 255, (color >> 8) & 255, color & 255 | 
|  | 172 | +        for i in range(0, len(framebuf.buf), 3): | 
|  | 173 | +            framebuf.buf[i : i + 3] = bytes(fill) | 
|  | 174 | + | 
|  | 175 | +    @staticmethod | 
|  | 176 | +    def fill_rect(framebuf, x, y, width, height, color): | 
|  | 177 | +        """Draw a rectangle at the given location, size and color. The ``fill_rect`` method draws | 
|  | 178 | +        both the outline and interior.""" | 
|  | 179 | +        # pylint: disable=too-many-arguments | 
|  | 180 | +        fill = (color >> 16) & 255, (color >> 8) & 255, color & 255 | 
|  | 181 | +        for _x in range(x, x + width): | 
|  | 182 | +            for _y in range(y, y + height): | 
|  | 183 | +                index = (_y * framebuf.stride + _x) * 3 | 
|  | 184 | +                framebuf.buf[index : index + 3] = bytes(fill) | 
|  | 185 | + | 
|  | 186 | + | 
| 145 | 187 | class FrameBuffer: | 
| 146 | 188 |     """FrameBuffer object. | 
| 147 | 189 | 
 | 
| @@ -174,6 +216,8 @@ def __init__(self, buf, width, height, buf_format=MVLSB, stride=None): | 
| 174 | 216 |             self.format = MVLSBFormat() | 
| 175 | 217 |         elif buf_format == MHMSB: | 
| 176 | 218 |             self.format = MHMSBFormat() | 
|  | 219 | +        elif buf_format == RGB888: | 
|  | 220 | +            self.format = RGB888Format() | 
| 177 | 221 |         else: | 
| 178 | 222 |             raise ValueError("invalid format") | 
| 179 | 223 |         self._rotation = 0 | 
| @@ -360,12 +404,18 @@ def text(self, string, x, y, color, *, font_name="font5x8.bin", size=1): | 
| 360 | 404 |             if not self._font or self._font.font_name != font_name: | 
| 361 | 405 |                 # load the font! | 
| 362 | 406 |                 self._font = BitmapFont(font_name) | 
| 363 |  | -            w = self._font.font_width | 
|  | 407 | +            width = self._font.font_width | 
|  | 408 | +            height = self._font.font_height | 
| 364 | 409 |             for i, char in enumerate(chunk): | 
| 365 |  | -                self._font.draw_char( | 
| 366 |  | -                    char, x + (i * (w + 1)) * size, y, self, color, size=size | 
| 367 |  | -                ) | 
| 368 |  | -            y += self._font.font_height * size | 
|  | 410 | +                char_x = x + (i * (width + 1)) * size | 
|  | 411 | +                if ( | 
|  | 412 | +                    char_x + (width * size) > 0 | 
|  | 413 | +                    and char_x < self.width | 
|  | 414 | +                    and y + (height * size) > 0 | 
|  | 415 | +                    and y < self.height | 
|  | 416 | +                ): | 
|  | 417 | +                    self._font.draw_char(char, char_x, y, self, color, size=size) | 
|  | 418 | +            y += height * size | 
| 369 | 419 | 
 | 
| 370 | 420 |     # pylint: enable=too-many-arguments | 
| 371 | 421 | 
 | 
|  | 
0 commit comments