Skip to content

Commit

Permalink
Add true color support.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
kangjianbin authored and cgull committed Oct 30, 2017
1 parent 70d1ca4 commit 6cfa4ae
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 5 deletions.
22 changes: 20 additions & 2 deletions src/terminal/terminalframebuffer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -505,13 +505,17 @@ 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;
}
}

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

Expand Down Expand Up @@ -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 );
Expand Down
14 changes: 11 additions & 3 deletions src/terminal/terminalframebuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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 )
Expand Down
21 changes: 21 additions & 0 deletions src/terminal/terminalfunctions.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
}
}
Expand Down

0 comments on commit 6cfa4ae

Please sign in to comment.