diff --git a/zephcore/helpers/ui-button/ui_pages.c b/zephcore/helpers/ui-button/ui_pages.c index cb25f3e..82f3e44 100644 --- a/zephcore/helpers/ui-button/ui_pages.c +++ b/zephcore/helpers/ui-button/ui_pages.c @@ -92,20 +92,26 @@ static inline int ui_content_y(void) * mc_display_has_color(); monochrome displays keep the existing CFB path. */ #define UI_COLOR_BG MC_COLOR_BLACK #define UI_COLOR_HEADER_BG 0x2104 /* dark neutral panel */ -#define UI_COLOR_TITLE MC_COLOR_GRAY /* warm white */ +#define UI_COLOR_TITLE MC_COLOR_LIGHT_GRAY /* soft white, slightly recessed vs values */ #define UI_COLOR_LABEL MC_COLOR_WHITE /* small-TFT gamma renders mid-gray near-black */ #define UI_COLOR_VALUE MC_COLOR_WHITE #define UI_COLOR_OK MC_COLOR_GREEN #define UI_COLOR_ACTIVE UI_COLOR_OK #define UI_COLOR_WARN 0xffa0 #define UI_COLOR_ERROR MC_COLOR_RED -#define UI_COLOR_DIM MC_COLOR_GRAY -#define UI_COLOR_DISABLED UI_COLOR_DIM /* off/disabled states stay as faint as possible */ +#define UI_COLOR_DIM MC_COLOR_LIGHT_GRAY /* small-TFT gamma (T114) crushes anything + * darker toward black — in person this reads + * as a proper gray, not white (PR #62) */ +#define UI_COLOR_DISABLED UI_COLOR_DIM /* off/disabled states dimmer than values */ +#define UI_COLOR_FAINT 0x4208 /* dark structural fills (badge bg, separators, bar tracks) — + * decoration, must stay subtle so content pops against it */ #define UI_COLOR_TX MC_COLOR_ORANGE #define UI_COLOR_RX UI_COLOR_OK -#define COLOR_FONT_W mc_display_font_width() -#define COLOR_FONT_H mc_display_font_height() +/* Glyph cell of the color renderer (display.c upscales the 6x8 font under + * LARGE_FONT) — NOT the CFB font metrics, which can differ (10x16 vs 9x12). */ +#define COLOR_FONT_W mc_display_color_font_width() +#define COLOR_FONT_H mc_display_color_font_height() #define ACTIVITY_GRAPH_SAMPLES 16 /* Vertically center `total` rows of text within the content area and @@ -339,7 +345,7 @@ static void render_page_indicator(void) /* Separator line below dots */ if (color) { - mc_display_color_fill_rect(0, SEP_Y, DISP_W, 1, UI_COLOR_DIM); + mc_display_color_fill_rect(0, SEP_Y, DISP_W, 1, UI_COLOR_FAINT); } else { mc_display_hline(0, SEP_Y, DISP_W); } @@ -392,7 +398,7 @@ static void draw_badge(int x, int y, const char *text, uint16_t color) { int w = color_text_width(text) + 4; - mc_display_color_fill_rect(x, y - 1, w, COLOR_FONT_H + 2, UI_COLOR_DIM); + mc_display_color_fill_rect(x, y - 1, w, COLOR_FONT_H + 2, UI_COLOR_FAINT); mc_display_color_text(x + 2, y, text, color); } @@ -414,7 +420,7 @@ static void draw_metric_bar(int x, int y, int w, int h, int value, int filled = (w * value) / max_value; - mc_display_color_fill_rect(x, y, w, h, UI_COLOR_DIM); + mc_display_color_fill_rect(x, y, w, h, UI_COLOR_FAINT); if (filled > 0) { mc_display_color_fill_rect(x, y, filled, h, color); } @@ -503,7 +509,7 @@ static void draw_activity_graph(int x, int y, int w, int h) sample_activity_graph(); mc_display_color_fill_rect(x, y, w, h, UI_COLOR_BG); - mc_display_color_fill_rect(x, mid, w, 1, UI_COLOR_DIM); + mc_display_color_fill_rect(x, mid, w, 1, UI_COLOR_FAINT); for (int i = 0; i < ACTIVITY_GRAPH_SAMPLES; i++) { uint8_t idx = (uint8_t)((activity_head + 1U + i) % diff --git a/zephcore/helpers/ui/display.c b/zephcore/helpers/ui/display.c index 8e7dc58..1a675f0 100644 --- a/zephcore/helpers/ui/display.c +++ b/zephcore/helpers/ui/display.c @@ -273,24 +273,18 @@ static void color_write_char_now(int x, int y, uint8_t c, uint16_t color) uint16_t fg = sys_cpu_to_be16(color); uint16_t bg = sys_cpu_to_be16(MC_COLOR_BLACK); - for (int row = 0; row < 8; row++) { - for (int col = 0; col < 6; col++) { - uint16_t pixel = + /* Nearest-neighbour upscale of the 6x8 glyph, mapped dest→src so + * every output pixel is written exactly once (a src→dest block copy + * with a fractional scale overwrites neighbouring blocks and thins + * strokes unevenly). */ + for (int py = 0; py < COLOR_FONT_H; py++) { + int row = py * COLOR_FONT_SCALE_DEN / COLOR_FONT_SCALE_NUM; + + for (int px = 0; px < COLOR_FONT_W; px++) { + int col = px * COLOR_FONT_SCALE_DEN / COLOR_FONT_SCALE_NUM; + + glyph_buf[py * COLOR_FONT_W + px] = ((glyph[col] >> row) & 0x01) ? fg : bg; - - int dx = col * COLOR_FONT_SCALE_NUM / COLOR_FONT_SCALE_DEN; - int dy = row * COLOR_FONT_SCALE_NUM / COLOR_FONT_SCALE_DEN; - - for (int sy = 0; sy < COLOR_FONT_SCALE_NUM; sy++) { - for (int sx = 0; sx < COLOR_FONT_SCALE_NUM; sx++) { - int px = dx + sx; - int py = dy + sy; - - if (px < COLOR_FONT_W && py < COLOR_FONT_H) { - glyph_buf[py * COLOR_FONT_W + px] = pixel; - } - } - } } } @@ -587,6 +581,18 @@ uint8_t mc_display_font_height(void) return font_h; } +#if MC_DISPLAY_COLOR_PANEL +uint8_t mc_display_color_font_width(void) +{ + return COLOR_FONT_W; +} + +uint8_t mc_display_color_font_height(void) +{ + return COLOR_FONT_H; +} +#endif + void mc_display_on(void) { if (!disp_initialized) { diff --git a/zephcore/helpers/ui/display.h b/zephcore/helpers/ui/display.h index 628ece1..bed9f81 100644 --- a/zephcore/helpers/ui/display.h +++ b/zephcore/helpers/ui/display.h @@ -105,6 +105,29 @@ static inline bool mc_display_has_color(void) } #endif +/** + * Glyph cell size of the color overlay renderer in pixels. The 6x8 font + * is upscaled 1.5x under CONFIG_ZEPHCORE_DISPLAY_LARGE_FONT, so this can + * differ from the CFB font metrics — layout math for color pages must use + * these, not mc_display_font_width/height(). On monochrome builds + * mc_display_color_text() falls back to the CFB path, so these fall back + * to the CFB metrics too. + */ +#if MC_DISPLAY_COLOR_PANEL +uint8_t mc_display_color_font_width(void); +uint8_t mc_display_color_font_height(void); +#else +static inline uint8_t mc_display_color_font_width(void) +{ + return mc_display_font_width(); +} + +static inline uint8_t mc_display_color_font_height(void) +{ + return mc_display_font_height(); +} +#endif + /** * Clear the framebuffer (fill with black). * Call before rendering a new frame. @@ -130,7 +153,8 @@ void mc_display_text(int x, int y, const char *text, bool invert); #define MC_COLOR_ORANGE 0xfd20 #define MC_COLOR_RED 0xf800 #define MC_COLOR_BLUE 0x001f -#define MC_COLOR_GRAY 0xEF7D +#define MC_COLOR_GRAY 0x8410 /* true mid-gray — small-TFT gamma may crush it near-black */ +#define MC_COLOR_LIGHT_GRAY 0xef7d /* ~93% white — reads as soft white on small TFTs */ /** * Draw text using RGB565 color when supported. On non-color displays this