diff options
author | 2017-10-27 02:47:24 +0800 | |
---|---|---|
committer | 2017-10-29 20:20:03 -0400 | |
commit | 6cfa4aef598146cfbde7f7a4a83438c3769a2835 (patch) | |
tree | 887dee60d26b9f5c37641988daf90a6bc3f284b9 | |
parent | 70d1ca444f25b9e1d062d34ca73bfbd6c5e67f73 (diff) |
Add true color support.
Implement true color support define in:
https://en.wikipedia.org/wiki/ANSI_escape_code
The sequence is:
ESC[ … 38;2;;; … m Select RGB foreground color
ESC[ … 48;2;;; … m Select RGB background color
-rw-r--r-- | src/terminal/terminalframebuffer.cc | 22 | ||||
-rw-r--r-- | src/terminal/terminalframebuffer.h | 14 | ||||
-rw-r--r-- | src/terminal/terminalfunctions.cc | 21 |
3 files changed, 52 insertions, 5 deletions
diff --git a/src/terminal/terminalframebuffer.cc b/src/terminal/terminalframebuffer.cc index 222f533..84b06cb 100644 --- a/src/terminal/terminalframebuffer.cc +++ b/src/terminal/terminalframebuffer.cc @@ -505,6 +505,8 @@ void Renditions::set_foreground_color( int num ) { if ( (0 <= num) && (num <= 255) ) { foreground_color = 30 + num; + } else if ( is_true_color( num ) ) { + foreground_color = num; } } @@ -512,6 +514,8 @@ void Renditions::set_background_color( int num ) { if ( (0 <= num) && (num <= 255) ) { background_color = 40 + num; + } else if ( is_true_color( num ) ) { + background_color = num; } } @@ -544,13 +548,27 @@ std::string Renditions::sgr( void ) const ret.append( "m" ); - if ( foreground_color > 37 ) { /* use 256-color set */ + if ( is_true_color( foreground_color ) ) { + char col[64]; + snprintf( col, 64, "\033[38;2;%d;%d;%dm", + (foreground_color >> 16) & 0xff, + (foreground_color >> 8) & 0xff, + foreground_color & 0xff); + ret.append( col ); + } else if ( foreground_color > 37 ) { /* use 256-color set */ char col[ 64 ]; snprintf( col, 64, "\033[38;5;%dm", foreground_color - 30 ); ret.append( col ); } - if ( background_color > 47 ) { /* use 256-color set */ + if ( is_true_color( background_color ) ) { + char col[64]; + snprintf( col, 64, "\033[48;2;%d;%d;%dm", + (background_color >> 16) & 0xff, + (background_color >> 8) & 0xff, + background_color & 0xff); + ret.append( col ); + } else if ( background_color > 47 ) { /* use 256-color set */ char col[ 64 ]; snprintf( col, 64, "\033[48;5;%dm", background_color - 40 ); ret.append( col ); diff --git a/src/terminal/terminalframebuffer.h b/src/terminal/terminalframebuffer.h index f159aea..723dc0a 100644 --- a/src/terminal/terminalframebuffer.h +++ b/src/terminal/terminalframebuffer.h @@ -55,9 +55,9 @@ namespace Terminal { public: typedef enum { bold, faint, italic, underlined, blink, inverse, invisible, SIZE } attribute_type; - // all together, a 32 bit word now... - unsigned int foreground_color : 12; - unsigned int background_color : 12; + static const unsigned int true_color_mask = 0x80000000; + unsigned int foreground_color; + unsigned int background_color; private: unsigned int attributes : 8; @@ -68,6 +68,14 @@ namespace Terminal { void set_rendition( color_type num ); std::string sgr( void ) const; + static unsigned int make_true_color( unsigned int r, unsigned int g, unsigned int b ) { + return true_color_mask | (r << 16) | (g << 8) | b; + } + + static bool is_true_color(unsigned int color) { + return (color & true_color_mask) != 0; + } + bool operator==( const Renditions &x ) const { return ( attributes == x.attributes ) diff --git a/src/terminal/terminalfunctions.cc b/src/terminal/terminalfunctions.cc index a0210e3..c53a4fa 100644 --- a/src/terminal/terminalfunctions.cc +++ b/src/terminal/terminalfunctions.cc @@ -424,6 +424,27 @@ static void CSI_SGR( Framebuffer *fb, Dispatcher *dispatch ) i += 2; continue; } + + /* True color support: ESC[ ... [34]8;2;<r>;<g>;<b> ... m */ + if ( (rendition == 38 || rendition == 48) && + (dispatch->param_count() - i >= 5) && + (dispatch->getparam( i+1, -1 ) == 2)) { + unsigned int red = dispatch->getparam(i+2, 0); + unsigned int green = dispatch->getparam(i+3, 0); + unsigned int blue = dispatch->getparam(i+4, 0); + unsigned int color; + + color = Renditions::make_true_color( red, green, blue ); + + if ( rendition == 38 ) { + fb->ds.set_foreground_color( color ); + } else { + fb->ds.set_background_color( color ); + } + i += 4; + continue; + } + fb->ds.add_rendition( rendition ); } } |