Support directly setting RGB fg/bg colors via ISO-8613-3 24-bit
ANSI color escapes:
ESC[38;2;<r>;<g>;<b>m Select RGB foreground color
ESC[48;2;<r>;<g>;<b>m Select RGB background color
The killer applications for me are vim in tmux. It'll not only modenize
their look and feeling, but also bring more eye friendly color schemes.
To avoid memory overheads and keep the patch non-intrusive, it takes the
approach to adapt the nearest color in the existing 4x4x4 (88-color mode)
or 6x6x6 (256-color mode) color cube to the new 24-bit RGB color.
The pros/cons are:
+) least memory footprint (close to 0)
comparing to konsole, gnome-terminal etc. real 24-bit arrays
+) exact colors and excellent user feelings
comparing to xterm, mlterm, etc. approximating to 256 palette
+) usable in both the existing 88/256-color modes
Most vim GUI color schemes show up the same as gvim in rxvt-unicode's
88-color mode, not to mention the 256-color mode. Typical applications
only use one or two dozens of colors at the same time.
-) may impact existing 88/256-color users
When 24-bit and 256-color applications run in the same window, either
in parallel (in tmux) or one-after-the-other, the latter's appearance
may be slightly impacted by the former, if they happen to use similar
colors. It'll be a less problem when the remaining applications join
the 24-bit camp in future.
-) may not be able to show 2+ close 24-bit colors
RGB colors close to each other will likely fall into the same slot in
the 4x4x4 or 6x6x6 color cube. If necessary, it could be improved
effectively by implementing some collision avoidance logic.
The CPU overheads of adapto_truecolor() look ignoreable: I feel no
perceptable slow down when doing vim operations in 24-bit color mode.
A micro benchmark running a test script from [1]:
% time (for i in {1..100}; do 24-bit-color.sh; done)
vanilla rxvt-unicode
====================
2.42s user 1.88s system 31% cpu 13.555 total
2.59s user 1.74s system 31% cpu 13.615 total
2.46s user 1.85s system 31% cpu 13.631 total
THIS PATCH (adapt 4x4x4/6x6x6 color cube to 24-bit)
===================================================
2.33s user 1.97s system 31% cpu 13.598 total
2.46s user 1.89s system 31% cpu 13.613 total
2.51s user 1.82s system 31% cpu 13.556 total
https://github.com/spudowiar/rxvt-unicode (real 24-bit array)
=============================================================
2.61s user 1.75s system 31% cpu 13.721 total
2.48s user 1.82s system 31% cpu 13.566 total
2.60s user 1.76s system 31% cpu 13.631 total
USE_256_COLORS is defined in all the above rxvt-unicode builds.
References:
[1] True Colour (16 million colours) support in various terminal
applications and terminals
https://gist.github.com/XVilka/8346728
[2] https://en.wikipedia.org/wiki/ANSI_escape_code#Colors
CC: Saleem Rashid <[email protected]>
Signed-off-by: Fengguang Wu <[email protected]>
---
doc/rxvt.1.pod | 4 ++++
doc/rxvt.7.pod | 2 ++
src/command.C | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/rxvt.h | 1 +
4 files changed, 72 insertions(+)
diff --git a/doc/rxvt.1.pod b/doc/rxvt.1.pod
index 19317ef..7c8ec8a 100644
--- a/doc/rxvt.1.pod
+++ b/doc/rxvt.1.pod
@@ -1598,6 +1598,10 @@ high-intensity (potentially bold/blink) versions of the
same, and 72 (or
240 in 256 colour mode) colours arranged in an 4x4x4 (or 6x6x6) colour RGB
cube plus a 8 (24) colour greyscale ramp.
+When applications set direct 24-bit fg/bg RGB colours through escapes
+C< ESC [ 38 ; 2 ; R ; G ; Bm > / C< ESC [ 48 ; 2; R ; G ; Bm >,
B<@@RXVT_NAME@@>
+will adapt the nearest colour in the 4x4x4/6x6x6 cube to the 24-bit RGB colour.
+
Here is a list of the ANSI colours with their names.
=begin table
diff --git a/doc/rxvt.7.pod b/doc/rxvt.7.pod
index 7ee8b72..0c5d2b7 100644
--- a/doc/rxvt.7.pod
+++ b/doc/rxvt.7.pod
@@ -1605,6 +1605,8 @@ Character Attributes (SGR)
B<< C<Pm = 36 / 46> >> fg/bg Cyan
B<< C<Pm = 37 / 47> >> fg/bg White
B<< C<Pm = 38;5 / 48;5> >> set fg/bg to colour #m (ISO 8613-6)
+ B<< C<Pm = 38;2;R;G;B> >> set fg to 24-bit colour #RGB (ISO
8613-3)
+ B<< C<Pm = 48;2;R;G;B> >> set bg to 24-bit colour #RGB (ISO
8613-3)
B<< C<Pm = 39 / 49> >> fg/bg Default
B<< C<Pm = 90 / 100> >> fg/bg Bright Black
B<< C<Pm = 91 / 101> >> fg/bg Bright Red
diff --git a/src/command.C b/src/command.C
index ff41967..48973e4 100644
--- a/src/command.C
+++ b/src/command.C
@@ -3341,6 +3341,52 @@ rxvt_term::process_osc_seq ()
}
}
+/*
+ * Rule of thumb boundaries for segmenting the nonlinear RGB color space.
+ */
+#if USE_256_COLORS
+static unsigned int colorcube_map[5] = { 0x42, 0x77, 0x99, 0xc6, 0xec };
+#else
+static unsigned int colorcube_map[3] = { 0x5c, 0xb2, 0xe8 };
+#endif
+
+#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
+#define COLORCUBE_SIZE (ARRAY_SIZE(colorcube_map)+1)
+
+static unsigned int colorcube_index (unsigned int c)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(colorcube_map); i++)
+ if (c < colorcube_map[i])
+ break;
+
+ return i;
+}
+
+/*
+ * Find the nearest color slot in the 4x4x4 or 6x6x6 color cube,
+ * adapt its value to the 24bit RGB color.
+ */
+unsigned int
+rxvt_term::adapto_truecolor (unsigned int r, unsigned int g, unsigned int b)
+{
+ unsigned int idx;
+
+ idx = minTermCOLOR + colorcube_index (r) * COLORCUBE_SIZE * COLORCUBE_SIZE +
+ colorcube_index (g) * COLORCUBE_SIZE +
+ colorcube_index (b);
+
+ pix_colors_focused [idx].free (this);
+ pix_colors_focused [idx].set (this, rgba (r * 0x0101,
+ g * 0x0101,
+ b * 0x0101));
+
+ // update_fade_color (idx, false); // who cares?
+
+ return idx;
+}
+
void
rxvt_term::process_color_seq (int report, int color, const char *str, char
resp)
{
@@ -3983,6 +4029,15 @@ rxvt_term::process_sgr_mode (unsigned int nargs, const
int *arg)
scr_color ((unsigned int) (minCOLOR + arg[i + 2]), Color_fg);
i += 2;
}
+ else if (nargs > i + 4 && arg[i + 1] == 2)
+ {
+ unsigned int r = arg[i + 2];
+ unsigned int g = arg[i + 3];
+ unsigned int b = arg[i + 4];
+ unsigned int idx = adapto_truecolor (r, g, b);
+ scr_color (idx, Color_fg);
+ i += 4;
+ }
break;
case 39: /* default fg */
scr_color (Color_fg, Color_fg);
@@ -4004,6 +4059,15 @@ rxvt_term::process_sgr_mode (unsigned int nargs, const
int *arg)
scr_color ((unsigned int) (minCOLOR + arg[i + 2]), Color_bg);
i += 2;
}
+ else if (nargs > i + 4 && arg[i + 1] == 2)
+ {
+ unsigned int r = arg[i + 2];
+ unsigned int g = arg[i + 3];
+ unsigned int b = arg[i + 4];
+ unsigned int idx = adapto_truecolor (r, g, b);
+ scr_color (idx, Color_bg);
+ i += 4;
+ }
break;
case 49: /* default bg */
scr_color (Color_bg, Color_bg);
@@ -4159,3 +4223,4 @@ void rxvt_term::pty_write ()
/*----------------------- end-of-file (C source) -----------------------*/
+// vim:et:ts=2:sw=2
diff --git a/src/rxvt.h b/src/rxvt.h
index f97422d..8dabd37 100644
--- a/src/rxvt.h
+++ b/src/rxvt.h
@@ -1390,6 +1390,7 @@ struct rxvt_term : zero_initialized, rxvt_vars,
rxvt_screen
void process_osc_seq ();
void process_color_seq (int report, int color, const char *str, char resp);
void process_xterm_seq (int op, char *str, char resp);
+ unsigned int adapto_truecolor (unsigned int r, unsigned int g, unsigned int
b);
int privcases (int mode, unsigned long bit);
void process_terminal_mode (int mode, int priv, unsigned int nargs, const
int *arg);
void process_sgr_mode (unsigned int nargs, const int *arg);
--
2.8.1
_______________________________________________
rxvt-unicode mailing list
[email protected]
http://lists.schmorp.de/mailman/listinfo/rxvt-unicode