try: from rpi_ws281x import Color except (ImportError, RuntimeError): from mock_rpi_ws281x import Color from config import PANEL_PIXEL_COUNT, DISPLAY_MAX_X, DISPLAY_MAX_Y from fonts import FONT_7X5 # Set by main.py after strip is created strip = None def _pixel_index(x, y): if x % 2 == 1: y = PANEL_PIXEL_COUNT - 1 - y return y + (x * PANEL_PIXEL_COUNT) def set_pixel(x, y, r, g, b): if x < 0 or y < 0 or x > DISPLAY_MAX_X or y > DISPLAY_MAX_Y: return strip.setPixelColor(_pixel_index(x, y), Color(r, g, b)) def get_pixel_color(x, y): """Returns (r, g, b) tuple.""" if x < 0 or y < 0 or x > DISPLAY_MAX_X or y > DISPLAY_MAX_Y: return (0, 0, 0) c = strip.getPixelColor(_pixel_index(x, y)) return ((c >> 16) & 0xFF, (c >> 8) & 0xFF, c & 0xFF) def fill_pixels(x1, y1, x2, y2, r, g, b): if x1 > x2: x1, x2 = x2, x1 if y1 > y2: y1, y2 = y2, y1 for y in range(y1, y2 + 1): for x in range(x1, x2 + 1): set_pixel(x, y, r, g, b) def shift_rectangle_left(x1, y1, x2, y2, shift_by): if not shift_by: return if x1 > x2: x1, x2 = x2, x1 if y1 > y2: y1, y2 = y2, y1 for y in range(y1, y2 + 1): if y < 0 or y > DISPLAY_MAX_Y: continue for x in range(x1, x2 + 1): src_x = x1 + (x - x1) dest_x = src_x - shift_by color = (0, 0, 0) if 0 <= src_x <= DISPLAY_MAX_X: color = get_pixel_color(src_x, y) if 0 <= dest_x <= DISPLAY_MAX_X: set_pixel(dest_x, y, *color) for y in range(y1, y2 + 1): if y < 0 or y > DISPLAY_MAX_Y: continue for x in range(x2 - shift_by + 1, x2 + 1): if 0 <= x <= DISPLAY_MAX_X: set_pixel(x, y, 0, 0, 0) def draw_character_part(row_data, width, r, g, b, start_x, start_y): for col in range(width): if row_data[col]: px = col + start_x py = start_y if 0 <= px <= DISPLAY_MAX_X and 0 <= py <= DISPLAY_MAX_Y: set_pixel(px, py, r, g, b) def draw_character(char_data, height, width, r, g, b, cursor): """Draws one character at cursor position, advances cursor.x by width+1.""" for row in range(height): draw_character_part(char_data[row], width, r, g, b, cursor['x'], row + cursor['y']) cursor['x'] += width + 1