From 8d55a3e70256f17f48f947fd0df1dba5ec50e189 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niccol=C3=B2=20Izzo?= Date: Sat, 19 Dec 2020 15:00:33 +0100 Subject: [PATCH] Implement alpha channel in graphics library Alpha channel can be used to draw transparent objects. --- openrtx/include/interfaces/graphics.h | 1 + openrtx/src/graphics.c | 36 +++++++++++++++++++-------- openrtx/src/ui.c | 12 ++++++--- 3 files changed, 35 insertions(+), 14 deletions(-) diff --git a/openrtx/include/interfaces/graphics.h b/openrtx/include/interfaces/graphics.h index 4686b0a4..56a1e720 100644 --- a/openrtx/include/interfaces/graphics.h +++ b/openrtx/include/interfaces/graphics.h @@ -77,6 +77,7 @@ typedef struct color_t uint8_t r; uint8_t g; uint8_t b; + uint8_t alpha; } color_t; typedef enum diff --git a/openrtx/src/graphics.c b/openrtx/src/graphics.c index 6e34c295..22e03299 100644 --- a/openrtx/src/graphics.c +++ b/openrtx/src/graphics.c @@ -162,12 +162,28 @@ inline void gfx_setPixel(point_t pos, color_t color) return; // off the screen #ifdef PIX_FMT_RGB565 - buf[pos.x + pos.y*SCREEN_WIDTH] = _true2highColor(color); + // Blend old pixel value and new one + if (color.alpha < 255) { + uint8_t alpha = color.alpha; + rgb565_t new_pixel = _true2highColor(color); + uint16_t raw_pixel = __builtin_bswap16( + *((uint16_t *)buf + pos.x + pos.y*SCREEN_WIDTH)); + rgb565_t old_pixel = *((rgb565_t*) &raw_pixel); + rgb565_t pixel = {((255-alpha)*old_pixel.b+alpha*new_pixel.b)/255, + ((255-alpha)*old_pixel.g+alpha*new_pixel.g)/255, + ((255-alpha)*old_pixel.r+alpha*new_pixel.r)/255}; + buf[pos.x + pos.y*SCREEN_WIDTH] = pixel; + } else { + buf[pos.x + pos.y*SCREEN_WIDTH] = _true2highColor(color); + } #elif defined PIX_FMT_BW - uint16_t cell = (pos.x + pos.y*SCREEN_WIDTH) / 8; - uint16_t elem = (pos.x + pos.y*SCREEN_WIDTH) % 8; - buf[cell] &= ~(1 << elem); - buf[cell] |= (_color2bw(color) << elem); + // Ignore more than half transparent pixels + if (color.alpha >= 128) { + uint16_t cell = (pos.x + pos.y*SCREEN_WIDTH) / 8; + uint16_t elem = (pos.x + pos.y*SCREEN_WIDTH) % 8; + buf[cell] &= ~(1 << elem); + buf[cell] |= (_color2bw(color) << elem); + } #endif } @@ -349,16 +365,16 @@ void gfx_print(point_t start, const char *text, fontSize_t size, textAlign_t ali * */ void gfx_drawBattery(point_t start, uint16_t width, uint16_t height, float percentage) { - color_t white = {255, 255, 255}; - color_t black = {0, 0, 0 }; + color_t white = {255, 255, 255, 255}; + color_t black = {0, 0, 0 , 255}; // Cap percentage to 1 percentage = (percentage > 1.0f) ? 1.0f : percentage; #ifdef PIX_FMT_RGB565 - color_t green = {0, 255, 0 }; - color_t yellow = {250, 180, 19 }; - color_t red = {255, 0, 0 }; + color_t green = {0, 255, 0 , 255}; + color_t yellow = {250, 180, 19 , 255}; + color_t red = {255, 0, 0 , 255}; // Select color according to percentage color_t bat_color = yellow; diff --git a/openrtx/src/ui.c b/openrtx/src/ui.c index 8357449d..eec2e306 100644 --- a/openrtx/src/ui.c +++ b/openrtx/src/ui.c @@ -105,9 +105,9 @@ typedef struct layout_t fontSize_t bottom_font; } layout_t; -const color_t color_white = {255, 255, 255}; -const color_t color_grey = {60, 60, 60}; -const color_t yellow_fab413 = {250, 180, 19}; +const color_t color_white = {255, 255, 255, 255}; +const color_t color_grey = {60, 60, 60, 255}; +const color_t yellow_fab413 = {250, 180, 19, 255}; layout_t layout; bool layout_ready = false; @@ -286,6 +286,11 @@ bool _ui_drawMainVFO(state_t* last_state) { gfx_clearScreen(); _ui_drawBackground(); + point_t splash_origin = {0, SCREEN_HEIGHT / 2 - 6}; + color_t yellow = yellow_fab413; + yellow.alpha = 0.1f * 255; + gfx_print(splash_origin, "O P N\nR T X", FONT_SIZE_12PT, TEXT_ALIGN_CENTER, + yellow); _ui_drawTopBar(last_state); _ui_drawMiddleVFO(last_state); _ui_drawBottomBar(); @@ -361,7 +366,6 @@ bool _ui_drawLowBatteryScreen() gfx_drawBattery(bat_pos, bat_width, bat_height, 0.1f); point_t text_pos_1 = {0, SCREEN_HEIGHT * 2 / 3}; point_t text_pos_2 = {0, SCREEN_HEIGHT * 2 / 3 + 16}; - const color_t color_white = {255, 255, 255}; gfx_print(text_pos_1, "For emergency use",