degesch: color cleanup
This commit is contained in:
parent
b5a7ea63c2
commit
2d040cae73
142
degesch.c
142
degesch.c
@ -1563,40 +1563,6 @@ free_terminal (void)
|
||||
del_curterm (cur_term);
|
||||
}
|
||||
|
||||
// NOTE: commonly terminals have 8 colors (worst), 16 colors (allows brightness
|
||||
// without the bold/blink attributes), 88 colors (the same plus a 4^3 RGB cube
|
||||
// and a few shades of gray), or 256 colors (best)
|
||||
|
||||
static int
|
||||
index_to_terminal_palette (int color)
|
||||
{
|
||||
hard_assert (color >= 0 && color < 256);
|
||||
|
||||
// No conversion
|
||||
if (max_colors == 256)
|
||||
return color;
|
||||
// These colours are the same everywhere
|
||||
if (color < 16 && max_colors > color)
|
||||
return color;
|
||||
|
||||
// Outside the 16-color range, we only support the 88-color palette,
|
||||
// which we can interpolate to from the 256-color one on input
|
||||
if (max_colors != 88)
|
||||
return -1;
|
||||
|
||||
// 24 -> 8 extra shades of gray
|
||||
if (color >= 232)
|
||||
return 80 + (color - 232) / 3;
|
||||
|
||||
// 6 * 6 * 6 cube -> 4 * 4 * 4 cube
|
||||
int x[6] = { 0, 1, 1, 2, 2, 3 };
|
||||
int index = color - 16;
|
||||
return 16 +
|
||||
( x[ index / 36 ] << 8
|
||||
| x[(index / 6) % 6 ] << 4
|
||||
| x[(index % 6) ] );
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
typedef int (*terminal_printer_fn) (int);
|
||||
@ -1726,7 +1692,8 @@ enum
|
||||
ATTRIBUTE_BOLD = 1 << 0,
|
||||
ATTRIBUTE_ITALIC = 1 << 1,
|
||||
ATTRIBUTE_UNDERLINE = 1 << 2,
|
||||
ATTRIBUTE_INVERSE = 1 << 3
|
||||
ATTRIBUTE_INVERSE = 1 << 3,
|
||||
ATTRIBUTE_BLINK = 1 << 4
|
||||
};
|
||||
|
||||
struct attribute_printer
|
||||
@ -1773,50 +1740,94 @@ attribute_printer_apply (struct attribute_printer *self, int attribute)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: 256-color output
|
||||
// - 8 color -> maybe bold, maybe inverse (should text be bold now?)
|
||||
// - 16 color -> just use the fallback color
|
||||
// - 88 color -> use the 256color value if available
|
||||
// - 256 color -> use the 256color value if available
|
||||
// NOTE: commonly terminals have:
|
||||
// 8 colors (worst, bright fg with BOLD, bg sometimes with BLINK)
|
||||
// 16 colors (okayish, we have the full basic range guaranteed)
|
||||
// 88 colors (the same plus a 4^3 RGB cube and a few shades of gray)
|
||||
// 256 colors (best, like above but with a larger cube and more gray)
|
||||
|
||||
/// Interpolate from the 256-color palette to the 88-color one
|
||||
static int
|
||||
attribute_printer_256_to_88 (int color)
|
||||
{
|
||||
// These colours are the same everywhere
|
||||
if (color < 16)
|
||||
return color;
|
||||
|
||||
// 24 -> 8 extra shades of gray
|
||||
if (color >= 232)
|
||||
return 80 + (color - 232) / 3;
|
||||
|
||||
// 6 * 6 * 6 cube -> 4 * 4 * 4 cube
|
||||
int x[6] = { 0, 1, 1, 2, 2, 3 };
|
||||
int index = color - 16;
|
||||
return 16 +
|
||||
( x[ index / 36 ] << 8
|
||||
| x[(index / 6) % 6 ] << 4
|
||||
| x[(index % 6) ] );
|
||||
}
|
||||
|
||||
static int
|
||||
attribute_printer_decode_color (int color, bool *is_bright)
|
||||
{
|
||||
int16_t c16 = color; hard_assert (c16 < 16);
|
||||
int16_t c256 = color >> 16; hard_assert (c256 < 256);
|
||||
|
||||
*is_bright = false;
|
||||
switch (max_colors)
|
||||
{
|
||||
case 8:
|
||||
if (c16 >= 8)
|
||||
{
|
||||
c16 -= 8;
|
||||
*is_bright = true;
|
||||
}
|
||||
case 16:
|
||||
return c16;
|
||||
|
||||
case 88:
|
||||
return c256 <= 0 ? c16 : attribute_printer_256_to_88 (c256);
|
||||
case 256:
|
||||
return c256 <= 0 ? c16 : c256;
|
||||
|
||||
default:
|
||||
// Unsupported palette
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
attribute_printer_update (struct attribute_printer *self)
|
||||
{
|
||||
int fg = 0;
|
||||
if ((int16_t) (self->want_foreground >> 16) > 0)
|
||||
fg = index_to_terminal_palette ((int16_t) (self->want_foreground >> 16));
|
||||
int bg = 0;
|
||||
if ((int16_t) (self->want_background >> 16) > 0)
|
||||
bg = index_to_terminal_palette ((int16_t) (self->want_background >> 16));
|
||||
if (fg <= 0) fg = (int16_t) (self->want_foreground);
|
||||
if (bg <= 0) bg = (int16_t) (self->want_background);
|
||||
bool fg_is_bright;
|
||||
int fg = attribute_printer_decode_color
|
||||
(self->want_foreground, &fg_is_bright);
|
||||
bool bg_is_bright;
|
||||
int bg = attribute_printer_decode_color
|
||||
(self->want_background, &bg_is_bright);
|
||||
|
||||
// TODO: (INVERSE | BOLD) should be used for bright backgrounds
|
||||
// when possible, i.e. when the foreground shouldn't be bright as well
|
||||
// and when the BOLD attribute hasn't already been set
|
||||
int attributes = self->want;
|
||||
if (max_colors == 8)
|
||||
if (attributes & ATTRIBUTE_INVERSE)
|
||||
{
|
||||
if (fg >= 8)
|
||||
{
|
||||
attributes |= ATTRIBUTE_BOLD;
|
||||
fg -= 8;
|
||||
}
|
||||
if (bg >= 8)
|
||||
{
|
||||
attributes |= ATTRIBUTE_BOLD;
|
||||
bg -= 8;
|
||||
}
|
||||
bool tmp = fg_is_bright;
|
||||
fg_is_bright = bg_is_bright;
|
||||
bg_is_bright = tmp;
|
||||
}
|
||||
|
||||
attribute_printer_reset (self);
|
||||
if (fg_is_bright) attributes |= ATTRIBUTE_BOLD;
|
||||
if (bg_is_bright) attributes |= ATTRIBUTE_BLINK;
|
||||
|
||||
if (fg >= 0) tputs (g_terminal.color_set_fg[fg], 1, self->printer);
|
||||
if (bg >= 0) tputs (g_terminal.color_set_bg[bg], 1, self->printer);
|
||||
attribute_printer_reset (self);
|
||||
|
||||
if (attributes)
|
||||
tputs (tparm (set_attributes,
|
||||
0, // standout
|
||||
attributes & ATTRIBUTE_UNDERLINE,
|
||||
attributes & ATTRIBUTE_INVERSE,
|
||||
0, // blink
|
||||
attributes & ATTRIBUTE_BLINK,
|
||||
0, // dim
|
||||
attributes & ATTRIBUTE_BOLD,
|
||||
0, // blank
|
||||
@ -1824,6 +1835,11 @@ attribute_printer_update (struct attribute_printer *self)
|
||||
0) // acs
|
||||
, 1, self->printer);
|
||||
|
||||
if (fg >= 0)
|
||||
tputs (g_terminal.color_set_fg[fg], 1, self->printer);
|
||||
if (bg >= 0)
|
||||
tputs (g_terminal.color_set_bg[bg], 1, self->printer);
|
||||
|
||||
self->dirty = true;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user