#include #include #include #include "epd_draw.h" void epd_draw_pixel(uint8_t *frame, int x, int y, epd_color_t color) { if (x < 0 || x >= EPD_WIDTH || y < 0 || y >= EPD_HEIGHT) { return; } size_t byte_index = (size_t)y * EPD_BYTES_PER_ROW + (size_t)x / 2; uint8_t nibble = (uint8_t)color & 0x0F; if (x % 2 == 0) { frame[byte_index] = (frame[byte_index] & 0x0F) | (nibble << 4); } else { frame[byte_index] = (frame[byte_index] & 0xF0) | nibble; } } /* fonts.h's sFONT tables cover the printable ASCII range starting at ' ' * (0x20), one glyph per character, MSB-first within each row (see * components/epaper_fonts). */ static bool font_pixel_set(const sFONT *font, char c, int row, int col) { if (c < ' ' || (unsigned char)c > 0x7E) { return false; } int bytes_per_row = (font->Width + 7) / 8; size_t glyph_index = (size_t)(c - ' '); const uint8_t *glyph = font->table + glyph_index * font->Height * bytes_per_row + (size_t)row * bytes_per_row; int byte_idx = col / 8; int bit_in_byte = 7 - (col % 8); return (glyph[byte_idx] >> bit_in_byte) & 0x1; } void epd_draw_text(uint8_t *frame, const sFONT *font, const char *text, int origin_x, int origin_y) { int cursor_x = origin_x; for (const char *p = text; *p != '\0'; p++) { char c = (char)toupper((unsigned char)*p); for (int row = 0; row < font->Height; row++) { for (int col = 0; col < font->Width; col++) { if (font_pixel_set(font, c, row, col)) { epd_draw_pixel(frame, cursor_x + col, origin_y + row, EPD_COLOR_BLACK); } } } cursor_x += font->Width; } } void epd_draw_text_centered(uint8_t *frame, const sFONT *font, const char *text, int center_x, int y) { int width = (int)strlen(text) * font->Width; epd_draw_text(frame, font, text, center_x - width / 2, y); } void epd_draw_line(uint8_t *frame, int x0, int y0, int x1, int y1, int thickness) { int dx = x1 - x0; int dy = y1 - y0; int steps = abs(dx) > abs(dy) ? abs(dx) : abs(dy); if (steps == 0) { steps = 1; } int half = thickness / 2; for (int i = 0; i <= steps; i++) { int x = x0 + dx * i / steps; int y = y0 + dy * i / steps; for (int oy = -half; oy <= half; oy++) { for (int ox = -half; ox <= half; ox++) { epd_draw_pixel(frame, x + ox, y + oy, EPD_COLOR_BLACK); } } } } void epd_draw_checkmark(uint8_t *frame, int x, int y, int size) { int thickness = size / 6; if (thickness < 2) { thickness = 2; } /* Short down-stroke, then long up-stroke -- classic checkmark proportions. */ epd_draw_line(frame, x, y + size / 2, x + size / 3, y + size - thickness, thickness); epd_draw_line(frame, x + size / 3, y + size - thickness, x + size, y, thickness); }