commit 37bc640e61bf2f5833dd5373bc5e8dbee99c5e43
parent 2abf293ba0c01cd37dac3c93e34258f6cda3f977
Author: Santtu Lakkala <inz@inz.fi>
Date: Mon, 20 Jul 2020 14:40:33 +0300
Add support for background color
Background color is passed without modification. Also foreground 256 and
RGB colors are parsed.
Diffstat:
M | nyancat.c | | | 161 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------- |
1 file changed, 142 insertions(+), 19 deletions(-)
diff --git a/nyancat.c b/nyancat.c
@@ -42,13 +42,18 @@ struct lolcat {
int sy;
uint32_t fg;
uint32_t bg;
+ bool bg_set;
bool bold;
bool reverse;
bool underline;
bool was_bold;
bool was_reverse;
bool was_underline;
+ bool was_bgset;
enum { TRUECOLOR, INDEXED256, INDEXED16 } mode;
+ enum { NONE,
+ FCOLOR, FI256, FR, FG, FB,
+ BCOLOR, BI256, BR, BG, BB } cstate;
void (*write)(const char *buffer, size_t buflen, void *data);
void *write_data;
@@ -143,12 +148,97 @@ struct lolcat *lolcat_init(void (*write_cb)(const char *buffer, size_t buflen,
return rv;
}
+static inline int _bold(int color)
+{
+ if (!color)
+ return 0x808080;
+ if (color == 0xc0c0c0)
+ return 0xffffff;
+ return (color << 1) - (color >> 7);
+}
+
+static uint32_t _color8(uint8_t color)
+{
+ if (color == 7)
+ return 0xc0c0c0;
+ return (color & 1) << 23 |
+ (color & 2) << 14 |
+ (color & 4) << 5;
+}
+
+static uint32_t _ccube(uint8_t idx)
+{
+ if (!idx)
+ return 0;
+ return 255 - 40 * (5 - idx);
+}
+
+static uint32_t _color256(uint8_t color)
+{
+ if (color < 8)
+ return _color8(color);
+ if (color < 16)
+ return _bold(_color8(color));
+ if (color < 232)
+ return _ccube((color - 16) / 36) << 16 |
+ _ccube((color - 16) / 6 % 6) << 8 |
+ _ccube((color - 16) % 6);
+ return 0x010101 * (0xee - 10 * (255 - color));
+}
+
static int _lc_arg_m(int arg, void *data)
{
struct lolcat *lc = data;
- if (arg == 38 || arg == 48)
- return 1;
+ switch (lc->cstate) {
+ case FCOLOR:
+ if (arg == 2)
+ lc->cstate = FR;
+ else if (arg == 5)
+ lc->cstate = FI256;
+ else
+ return 1;
+ lc->fg = 0;
+ return 0;
+ case FI256:
+ lc->fg = _color256(arg);
+ lc->cstate = NONE;
+ return 0;
+ case FB:
+ lc->cstate = -1;
+ /* fall-through */
+ case FR:
+ case FG:
+ lc->fg = lc->fg << 8 | arg;
+ lc->cstate++;
+ return 0;
+
+ case BCOLOR:
+ if (arg == 2)
+ lc->cstate = BR;
+ else if (arg == 5)
+ lc->cstate = BI256;
+ else
+ return 1;
+ lc->bg = 0;
+ return 0;
+ case BI256:
+ lc->bg = _color256(arg);
+ lc->bg_set = true;
+ lc->cstate = NONE;
+ return 0;
+ case BB:
+ lc->cstate = -1;
+ lc->bg_set = true;
+ /* fall-through */
+ case BR:
+ case BG:
+ lc->bg = lc->bg << 8 | arg;
+ lc->cstate++;
+ return 0;
+ default:
+ break;
+ }
switch (arg) {
case 0:
@@ -156,6 +246,7 @@ static int _lc_arg_m(int arg, void *data)
lc->reverse = false;
lc->fg = 0xc0c0c0;
lc->bg = 0x000000;
+ lc->bg_set = false;
break;
case 1:
lc->bold = true;
@@ -177,12 +268,15 @@ static int _lc_arg_m(int arg, void *data)
case 35:
case 36:
lc->fg = ((arg - 30) & 1) << 23 |
- ((arg - 30) & 2) << 14 |
- ((arg - 30) & 4) << 5;
+ ((arg - 30) & 2) << 14 |
+ ((arg - 30) & 4) << 5;
break;
case 37:
lc->fg = 0xc0c0c0;
break;
+ case 38:
+ lc->cstate = FCOLOR;
+ break;
case 40:
case 41:
case 42:
@@ -191,8 +285,16 @@ static int _lc_arg_m(int arg, void *data)
case 45:
case 46:
lc->bg = ((arg - 40) & 1) << 23 |
- ((arg - 40) & 2) << 14 |
- ((arg - 40) & 4) << 5;
+ ((arg - 40) & 2) << 14 |
+ ((arg - 40) & 4) << 5;
+ lc->bg_set = true;
+ break;
+ case 47:
+ lc->bg = 0xc0c0c0;
+ lc->bg_set = true;
+ break;
+ case 48:
+ lc->cstate = BCOLOR;
break;
default:
@@ -202,15 +304,6 @@ static int _lc_arg_m(int arg, void *data)
return 0;
}
-static inline int _bold(int color)
-{
- if (!color)
- return 0x808080;
- if (color == 0xc0c0c0)
- return 0xffffff;
- return (color << 1) - (color >> 7);
-}
-
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) < (b) ? (b) : (a))
#define CLAMP(a, b, c) MIN(MAX(a, b), c)
@@ -245,9 +338,11 @@ static inline int _index16(uint32_t col, bool *bright)
ri = r > 127U;
gi = g > 127U;
bi = b > 127U;
- *bright = true;
+ if (bright)
+ *bright = true;
} else {
- *bright = false;
+ if (bright)
+ *bright = false;
}
return ri | bi << 1 | gi << 2;
@@ -283,7 +378,8 @@ static void _lc_colorize(struct lolcat *lc, const char *u8_char, size_t len)
char *bw = buffer + 2;
if (len == 1 && u8_char[0] == ' ' &&
- !lc->reverse && !lc->was_reverse) {
+ !lc->reverse && !lc->was_reverse &&
+ !lc->bg_set && !lc->was_bgset) {
lc->write(" ", 1, lc->write_data);
return;
}
@@ -300,10 +396,12 @@ static void _lc_colorize(struct lolcat *lc, const char *u8_char, size_t len)
col = _index256(col);
if ((lc->was_bold && !lc->bold) ||
- (lc->was_reverse && !lc->reverse)) {
+ (lc->was_reverse && !lc->reverse) ||
+ (lc->was_bgset && !lc->bg_set)) {
lc->was_underline = false;
lc->was_bold = false;
lc->was_reverse = false;
+ lc->was_bgset = false;
*bw++ = '0';
*bw++ = ';';
}
@@ -325,6 +423,21 @@ static void _lc_colorize(struct lolcat *lc, const char *u8_char, size_t len)
lc->was_reverse = true;
}
+ if (lc->bg_set) {
+ if (lc->mode == INDEXED16)
+ bw += sprintf(bw, "4%d;",
+ _index16(lc->bg, NULL));
+ else if (lc->mode == INDEXED256)
+ bw += sprintf(bw, "48;5;%d;",
+ _index256(lc->bg));
+ else
+ bw += sprintf(bw, "48;2;%d;%d;%d;",
+ lc->bg >> 16,
+ (lc->bg >> 8) & 255,
+ lc->bg & 255);
+ lc->was_bgset = true;
+ }
+
if (lc->mode == INDEXED16)
bw += sprintf(bw, "3%dm%.*s",
col, (int)len, u8_char);
@@ -379,6 +492,7 @@ ssize_t lc_process(struct lolcat *lc, const char *buffer, size_t len)
return ip;
if (c == '\x1b') {
+ lc->cstate = NONE;
if (i >= len)
return ip;
if (buffer[i] == '[') {
@@ -519,6 +633,15 @@ ssize_t lc_process(struct lolcat *lc, const char *buffer, size_t len)
lc->write("", 1, lc->write_data);
continue;
} else if (c == '\n') {
+ if ((lc->was_bgset && !lc->bg) ||
+ (lc->was_reverse && !lc->reverse)) {
+ const char buffer[] = "\x1b[0m";
+ lc->was_bgset = lc->was_reverse =
+ lc->was_bold = lc->was_underline =
+ false;
+ lc->write(buffer, sizeof(buffer),
+ lc->write_data);
+ }
lc->x = 0;
lc->y++;
lc->write("\n", 1, lc->write_data);