degesch: color cleanup

This commit is contained in:
Přemysl Eric Janouch 2015-05-12 02:43:53 +02:00
parent b5a7ea63c2
commit 2d040cae73
1 changed files with 79 additions and 63 deletions

142
degesch.c
View File

@ -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;
}