From dc2c565fac0fe747b33899eea0425bac101ddf6d Mon Sep 17 00:00:00 2001 From: Eden Bynever Date: Sun, 19 May 2024 07:19:40 -0400 Subject: Draw truecolor icons using dual-color half blocks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The vast majority of monospaced fonts are roughly half as wide as they are tall; to account for this when displaying icons, `xprop` draws each pixel twice in the horizontal, which nicely evens out the proportions. This patch utilizes the Lower Half Block character (▄) to obtain the same result in a quarter of the space. By setting both a background and a foreground color, we can draw two pixels per character cell, thereby halving the apparent height of an icon rather than doubling its width. Signed-off-by: Eden Bynever Part-of: --- xprop.c | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) (limited to 'xprop.c') diff --git a/xprop.c b/xprop.c index df45477..2de41b5 100644 --- a/xprop.c +++ b/xprop.c @@ -780,18 +780,21 @@ Format_Icons (const unsigned long *icon, int len) while (icon < end) { - unsigned long width, height, display_width; + unsigned long width, height, display_width, display_height; unsigned int icon_pixel_bytes; unsigned int icon_line_bytes; int offset; - width = *icon++; - height = *icon++; - display_width = width * 2; /* Two characters per icon pixel. */ + width = display_width = *icon++; + height = display_height = *icon++; + if (is_truecolor_term()) + display_height /= 2; /* Two vertical icon pixels per character. */ + else + display_width *= 2; /* Two horizontal characters per icon pixel. */ icon_pixel_bytes = 1; if (is_truecolor_term()) - icon_pixel_bytes = 25; /* 16 control characters, and up to 9 chars of RGB. */ + icon_pixel_bytes = 39; /* 21 control characters, and up to 18 chars of RGB. */ else if (is_utf8_locale()) icon_pixel_bytes = 3; /* Up to 3 bytes per character in that mode. */ @@ -801,7 +804,7 @@ Format_Icons (const unsigned long *icon, int len) offset = (tail - result); alloced += 80; /* For the header, final newline, color reset */ - alloced += icon_line_bytes * height; /* For the rows */ + alloced += icon_line_bytes * display_height; /* For the rows */ result = realloc (result, alloced); if (!result) @@ -820,7 +823,7 @@ Format_Icons (const unsigned long *icon, int len) continue; } - for (unsigned int h = 0; h < height; ++h) + for (unsigned int h = 0; h < display_height; ++h) { tail += sprintf (tail, "\t"); @@ -843,12 +846,19 @@ Format_Icons (const unsigned long *icon, int len) if (is_truecolor_term()) { float opacity = a / 255.0; + unsigned long pixel2 = *(icon + width - 1); r = r * opacity; g = g * opacity; b = b * opacity; + tail += sprintf (tail, "\033[48;2;%d;%d;%d;", r, g, b); + + opacity = ((pixel2 & 0xff000000) >> 24) / 255.0; + r = ((pixel2 & 0x00ff0000) >> 16) * opacity; + g = ((pixel2 & 0x0000ff00) >> 8) * opacity; + b = ((pixel2 & 0x000000ff) >> 0) * opacity; + tail += sprintf (tail, "38;2;%d;%d;%dm\342\226\204", r, g, b); - tail += sprintf (tail, "\033[38;2;%d;%d;%dm\342\226\210\342\226\210", r, g, b ); } else if (is_utf8_locale()) { @@ -879,13 +889,14 @@ Format_Icons (const unsigned long *icon, int len) } } + if (is_truecolor_term()) { + /* Reset colors before newline to avoid bleed. */ + tail += sprintf (tail, "\033[0m"); + icon += width; /* Advance past handled row. */ + } tail += sprintf (tail, "\n"); } - /* Reset colors. */ - if (is_truecolor_term()) - tail += sprintf (tail, "\033[0m"); - tail += sprintf (tail, "\n"); } -- cgit v1.2.3