diff --git a/core/embed/lib/gl_color.h b/core/embed/lib/gl_color.h index ce7e16b1e..11d61069a 100644 --- a/core/embed/lib/gl_color.h +++ b/core/embed/lib/gl_color.h @@ -61,6 +61,26 @@ typedef uint32_t gl_color32_t; #error "GL_COLOR_16BIT/32BIT not specified" #endif +// Extracts red component from gl_color16_t and converts it to 8-bit value +#define gl_color16_to_r(c) ((((c) & 0xF800) >> 8) | (((c) & 0xF800) >> 13)) +// Extracts green component from gl_color16_t and converts it to 8-bit value +#define gl_color16_to_g(c) ((((c) & 0x07E0) >> 3) | (((c) & 0x07E0) >> 9)) +// Extracts blue component from gl_color16_t and converts it to 8-bit value +#define gl_color16_to_b(c) ((((c) & 0x001F) << 3) | (((c) & 0x001F) >> 2)) + +// Extracts red component from gl_color32_t +#define gl_color32_to_r(c) (((c) & 0x00FF0000) >> 16) +// Extracts green component from gl_color32_t +#define gl_color32_to_g(c) (((c) & 0x0000FF00) >> 8) +// Extracts blue component from gl_color32_t +#define gl_color32_to_b(c) (((c) & 0x000000FF) >> 0) + +// 4-bit linear interpolation between `fg` and `bg` +#define a4_lerp(fg, bg, alpha) (((fg) * (alpha) + ((bg) * (15 - (alpha)))) / 15) +// 8-bit linear interpolation between `fg` and `bg` +#define a8_lerp(fg, bg, alpha) (((fg) * (alpha) + ((bg) * (255 - (alpha)))) / 255) + + // Constructs a 16-bit color from the given red (r), // green (g), and blue (b) values in the range 0..255 static inline gl_color16_t gl_color16_rgb(uint8_t r, uint8_t g, uint8_t b) { @@ -76,15 +96,11 @@ static inline gl_color32_t gl_color32_rgb(uint8_t r, uint8_t g, uint8_t b) { // Converts a 16-bit color to a 32-bit color; alpha is set to 255 static inline gl_color32_t gl_color16_to_color32(gl_color16_t color) { - uint32_t r = (color & 0xF800) >> 8; - uint32_t g = (color & 0x07E0) >> 3; - uint32_t b = (color & 0x001F) << 3; + uint32_t r = gl_color16_to_r(color); + uint32_t g = gl_color16_to_g(color); + uint32_t b = gl_color16_to_b(color); - r |= (r >> 5); - g |= (g >> 6); - b |= (b >> 5); - - return (0xFFU << 24) | (r << 16) | (g << 8) | b; + return gl_color32_rgb(r, g, b); } // Converts 32-bit color to 16-bit color, alpha is ignored @@ -98,13 +114,9 @@ static inline gl_color16_t gl_color32_to_color16(gl_color32_t color) { // Converts 16-bit color into luminance (ranging from 0 to 255) static inline uint8_t gl_color16_lum(gl_color16_t color) { - uint32_t r = (color & 0xF800) >> 8; - uint32_t g = (color & 0x07E0) >> 3; - uint32_t b = (color & 0x001F) << 3; - - r |= (r >> 5); - g |= (g >> 6); - b |= (b >> 5); + uint32_t r = gl_color16_to_r(color); + uint32_t g = gl_color16_to_g(color); + uint32_t b = gl_color16_to_b(color); return (r + g + b) / 3; } @@ -120,21 +132,20 @@ static inline gl_color16_t gl_color16_blend_a4(gl_color16_t fg, gl_color16_t bg, uint8_t alpha) { uint16_t fg_r = (fg & 0xF800) >> 11; uint16_t bg_r = (bg & 0xF800) >> 11; - - uint16_t r = (fg_r * alpha + (bg_r * (15 - alpha))) / 15; + uint16_t r = a4_lerp(fg_r, bg_r, alpha); uint16_t fg_g = (fg & 0x07E0) >> 5; uint16_t bg_g = (bg & 0x07E0) >> 5; - uint16_t g = (fg_g * alpha + (bg_g * (15 - alpha))) / 15; + uint16_t g = a4_lerp(fg_g, bg_g, alpha); uint16_t fg_b = (fg & 0x001F) >> 0; uint16_t bg_b = (bg & 0x001F) >> 0; - uint16_t b = (fg_b * alpha + (bg_b * (15 - alpha))) / 15; + uint16_t b = a4_lerp(fg_b, bg_b, alpha); return (r << 11) | (g << 5) | b; } -// Blends foreground and background colors with 4-bit alpha +// Blends foreground and background colors with 8-bit alpha // // Returns a color in 16-bit format // @@ -144,16 +155,15 @@ static inline gl_color16_t gl_color16_blend_a8(gl_color16_t fg, gl_color16_t bg, uint8_t alpha) { uint16_t fg_r = (fg & 0xF800) >> 11; uint16_t bg_r = (bg & 0xF800) >> 11; - - uint16_t r = (fg_r * alpha + (bg_r * (255 - alpha))) / 255; + uint16_t r = a8_lerp(fg_r, bg_r, alpha); uint16_t fg_g = (fg & 0x07E0) >> 5; uint16_t bg_g = (bg & 0x07E0) >> 5; - uint16_t g = (fg_g * alpha + (bg_g * (255 - alpha))) / 255; + uint16_t g = a8_lerp(fg_g, bg_g, alpha); uint16_t fg_b = (fg & 0x001F) >> 0; uint16_t bg_b = (bg & 0x001F) >> 0; - uint16_t b = (fg_b * alpha + (bg_b * (255 - alpha))) / 255; + uint16_t b = a8_lerp(fg_b, bg_b, alpha); return (r << 11) | (g << 5) | b; } @@ -166,26 +176,19 @@ static inline gl_color16_t gl_color16_blend_a8(gl_color16_t fg, gl_color16_t bg, // If alpha is 15, the function returns the foreground color static inline gl_color32_t gl_color32_blend_a4(gl_color16_t fg, gl_color16_t bg, uint8_t alpha) { - uint16_t fg_r = (fg & 0xF800) >> 8; - fg_r |= fg_r >> 5; - uint16_t bg_r = (bg & 0xF800) >> 8; - bg_r |= bg_r >> 5; - - uint16_t r = (fg_r * alpha + (bg_r * (15 - alpha))) / 15; + uint16_t fg_r = gl_color16_to_r(fg); + uint16_t bg_r = gl_color16_to_r(bg); + uint16_t r = a4_lerp(fg_r, bg_r, alpha); - uint16_t fg_g = (fg & 0x07E0) >> 3; - fg_g |= fg_g >> 6; - uint16_t bg_g = (bg & 0x07E0) >> 3; - bg_g |= bg_g >> 6; - uint16_t g = (fg_g * alpha + (bg_g * (15 - alpha))) / 15; + uint16_t fg_g = gl_color16_to_g(fg); + uint16_t bg_g = gl_color16_to_g(bg); + uint16_t g = a4_lerp(fg_g, bg_g, alpha); - uint16_t fg_b = (fg & 0x001F) << 3; - fg_b |= fg_b >> 5; - uint16_t bg_b = (bg & 0x001F) << 3; - bg_b |= bg_b >> 5; - uint16_t b = (fg_b * alpha + (bg_b * (15 - alpha))) / 15; + uint16_t fg_b = gl_color16_to_b(fg); + uint16_t bg_b = gl_color16_to_b(bg); + uint16_t b = a4_lerp(fg_b, bg_b, alpha); - return (0xFFU << 24) | ((uint32_t)r << 16) | ((uint32_t)g << 8) | b; + return gl_color32_rgb(r, g, b); } // Blends foreground and background colors with 8-bit alpha @@ -196,26 +199,19 @@ static inline gl_color32_t gl_color32_blend_a4(gl_color16_t fg, gl_color16_t bg, // If `alpha` is 255, the function returns the foreground color static inline gl_color32_t gl_color32_blend_a8(gl_color16_t fg, gl_color16_t bg, uint8_t alpha) { - uint16_t fg_r = (fg & 0xF800) >> 8; - fg_r |= fg_r >> 5; - uint16_t bg_r = (bg & 0xF800) >> 8; - bg_r |= bg_r >> 5; + uint16_t fg_r = gl_color16_to_r(fg); + uint16_t bg_r = gl_color16_to_r(bg); + uint16_t r = a8_lerp(fg_r, bg_r, alpha); - uint16_t r = (fg_r * alpha + (bg_r * (255 - alpha))) / 255; + uint16_t fg_g = gl_color16_to_g(fg); + uint16_t bg_g = gl_color16_to_g(bg); + uint16_t g = a8_lerp(fg_g, bg_g, alpha); - uint16_t fg_g = (fg & 0x07E0) >> 3; - fg_g |= fg_g >> 6; - uint16_t bg_g = (bg & 0x07E0) >> 3; - bg_g |= bg_g >> 6; - uint16_t g = (fg_g * alpha + (bg_g * (255 - alpha))) / 255; + uint16_t fg_b = gl_color16_to_b(fg); + uint16_t bg_b = gl_color16_to_b(bg); + uint16_t b = a8_lerp(fg_b, bg_b, alpha); - uint16_t fg_b = (fg & 0x001F) << 3; - fg_b |= fg_b >> 5; - uint16_t bg_b = (bg & 0x001F) << 3; - bg_b |= bg_b >> 5; - uint16_t b = (fg_b * alpha + (bg_b * (255 - alpha))) / 255; - - return (0xFFU << 24) | ((uint32_t)r << 16) | ((uint32_t)g << 8) | b; + return gl_color32_rgb(r, g, b); } #elif GL_COLOR_32BIT @@ -228,17 +224,17 @@ static inline gl_color32_t gl_color32_blend_a8(gl_color16_t fg, gl_color16_t bg, // If `alpha` is 15, the function returns the foreground color static inline gl_color16_t gl_color16_blend_a4(gl_color32_t fg, gl_color32_t bg, uint8_t alpha) { - uint16_t fg_r = (fg & 0x00FF0000) >> 16; - uint16_t bg_r = (bg & 0x00FF0000) >> 16; - uint16_t r = (fg_r * alpha + (bg_r * (15 - alpha))) / 15; + uint16_t fg_r = gl_color32_to_r(fg); + uint16_t bg_r = gl_color32_to_r(bg); + uint16_t r = a4_lerp(fg_r, bg_r, alpha); - uint16_t fg_g = (fg & 0x0000FF00) >> 8; - uint16_t bg_g = (bg & 0x0000FF00) >> 8; - uint16_t g = (fg_g * alpha + (bg_g * (15 - alpha))) / 15; + uint16_t fg_g = gl_color32_to_g(fg); + uint16_t bg_g = gl_color32_to_g(bg); + uint16_t g = a4_lerp(fg_g, bg_g, alpha); - uint16_t fg_b = (fg & 0x000000FF) >> 0; - uint16_t bg_b = (bg & 0x000000FF) >> 0; - uint16_t b = (fg_b * alpha + (bg_b * (15 - alpha))) / 15; + uint16_t fg_b = gl_color32_to_b(fg); + uint16_t bg_b = gl_color32_to_b(bg); + uint16_t b = a4_lerp(fg_b, bg_b, alpha); return gl_color16_rgb(r, g, b) } @@ -251,17 +247,17 @@ static inline gl_color16_t gl_color16_blend_a4(gl_color32_t fg, gl_color32_t bg, // If `alpha` is 255, the function returns the foreground color static inline gl_color16_t gl_color16_blend_a8(gl_color32_t fg, gl_color32_t bg, uint8_t alpha) { - uint16_t fg_r = (fg & 0x00FF0000) >> 16; - uint16_t bg_r = (bg & 0x00FF0000) >> 16; - uint16_t r = (fg_r * alpha + (bg_r * (255 - alpha))) / 255; + uint16_t fg_r = gl_color32_to_r(fg); + uint16_t bg_r = gl_color32_to_r(bg); + uint16_t r = a8_lerp(fg_r, bg_r, alpha); - uint16_t fg_g = (fg & 0x0000FF00) >> 8; - uint16_t bg_g = (bg & 0x0000FF00) >> 8; - uint16_t g = (fg_g * alpha + (bg_g * (255 - alpha))) / 255; + uint16_t fg_g = gl_color32_to_g(fg); + uint16_t bg_g = gl_color32_to_g(bg); + uint16_t g = a8_lerp(fg_g, bg_g, alpha); - uint16_t fg_b = (fg & 0x000000FF) >> 0; - uint16_t bg_b = (bg & 0x000000FF) >> 0; - uint16_t b = (fg_b * alpha + (bg_b * (255 - alpha))) / 255; + uint16_t fg_b = gl_color32_to_b(fg); + uint16_t bg_b = gl_color32_to_b(bg); + uint16_t b = g = a8_lerp(fg_b, bg_b, alpha); return gl_color16_rgb(r, g, b) } @@ -274,17 +270,17 @@ static inline gl_color16_t gl_color16_blend_a8(gl_color32_t fg, gl_color32_t bg, // If `alpha` is 15, the function returns the foreground color static inline gl_color32_t gl_color32_blend_a4(gl_color32_t fg, gl_color32_t bg, uint8_t alpha) { - uint16_t fg_r = (fg & 0x00FF0000) >> 16; - uint16_t bg_r = (bg & 0x00FF0000) >> 16; - uint16_t r = (fg_r * alpha + (bg_r * (15 - alpha))) / 15; + uint16_t fg_r = gl_color32_to_r(fg); + uint16_t bg_r = gl_color32_to_r(bg); + uint16_t r = g = a4_lerp(fg_r, bg_r, alpha); - uint16_t fg_g = (fg & 0x0000FF00) >> 8; - uint16_t bg_g = (bg & 0x0000FF00) >> 8; - uint16_t g = (fg_g * alpha + (bg_g * (15 - alpha))) / 15; + uint16_t fg_g = gl_color32_to_g(fg); + uint16_t bg_g = gl_color32_to_g(bg); + uint16_t g = a4_lerp(fg_g, bg_g, alpha); - uint16_t fg_b = (fg & 0x000000FF) >> 0; - uint16_t bg_b = (bg & 0x000000FF) >> 0; - uint16_t b = (fg_b * alpha + (bg_b * (15 - alpha))) / 15; + uint16_t fg_b = gl_color32_to_b(fg); + uint16_t bg_b = gl_color32_to_b(bg); + uint16_t b = a4_lerp(fg_b, bg_b, alpha); return gl_color32_rgb(r, g, b); }