Posterize to 8 colors when outer terminal does not support 256 colors

Fixes #58 github issue.
This commit is contained in:
Keith Winstein
2012-03-16 17:42:36 -04:00
parent bdb0ecc2fd
commit 170bc8366a
6 changed files with 96 additions and 7 deletions
+6 -2
View File
@@ -148,7 +148,7 @@ int main( void )
}
/* Print a frame if the last frame was more than 1/50 seconds ago */
bool tick( Terminal::Framebuffer &state, const Terminal::Framebuffer &new_frame,
bool tick( Terminal::Framebuffer &state, Terminal::Framebuffer &new_frame,
const Terminal::Display &display )
{
static bool initialized = false;
@@ -165,6 +165,8 @@ bool tick( Terminal::Framebuffer &state, const Terminal::Framebuffer &new_frame,
if ( (!initialized)
|| (diff >= 0.02) ) {
display.downgrade( new_frame );
std::string update = display.new_frame( initialized, state, new_frame );
swrite( STDOUT_FILENO, update.c_str() );
state = new_frame;
@@ -314,7 +316,9 @@ void emulate_terminal( int fd )
break;
}
if ( tick( state, complete.get_fb(), display ) ) { /* there was a frame */
Terminal::Framebuffer new_frame( complete.get_fb() );
if ( tick( state, new_frame, display ) ) { /* there was a frame */
poll_timeout = -1;
} else {
poll_timeout = 20;
+3
View File
@@ -158,6 +158,9 @@ void STMClient::output_new_frame( void )
/* apply local overlays */
overlays.apply( *new_state );
/* apply any mutations */
display.downgrade( *new_state );
/* calculate minimal difference from where we are */
const string diff( display.new_frame( !repaint_requested,
*local_framebuffer,
+4
View File
@@ -54,9 +54,13 @@ namespace Terminal {
bool has_bce; /* erases result in cell filled with background color */
int posterize_colors; /* downsample input colors >8 to [0..7] */
void put_cell( bool initialized, FrameState &frame, const Framebuffer &f ) const;
public:
void downgrade( Framebuffer &f ) const { if ( posterize_colors ) { f.posterize(); } }
std::string new_frame( bool initialized, const Framebuffer &last, const Framebuffer &f ) const;
Display( bool use_environment );
+12 -5
View File
@@ -29,7 +29,7 @@
using namespace Terminal;
Display::Display( bool use_environment )
: has_ech( true ), has_bce( true )
: has_ech( true ), has_bce( true ), posterize_colors( false )
{
if ( use_environment ) {
int errret = -2;
@@ -57,8 +57,7 @@ Display::Display( bool use_environment )
char *val = tigetstr( ech_name );
if ( val == (char *)-1 ) {
throw std::string( "Invalid terminfo string capability " ) + ech_name;
}
if ( val == 0 ) {
} else if ( val == 0 ) {
has_ech = false;
}
@@ -67,9 +66,17 @@ Display::Display( bool use_environment )
int bce_val = tigetflag( bce_name );
if ( bce_val == -1 ) {
throw std::string( "Invalid terminfo boolean capability " ) + bce_name;
}
if ( bce_val == 0 ) {
} else if ( bce_val == 0 ) {
has_bce = false;
}
/* check colors */
char colors_name[] = "colors";
int color_val = tigetnum( colors_name );
if ( color_val == -2 ) {
throw std::string( "Invalid terminfo numeric capability " ) + colors_name;
} else if ( color_val < 256 ) {
posterize_colors = true;
}
}
}
+67
View File
@@ -320,6 +320,15 @@ void Framebuffer::soft_reset( void )
ds.clear_saved_cursor();
}
void Framebuffer::posterize( void )
{
for ( BOOST_AUTO( i, rows.begin() ); i != rows.end(); i++ ) {
for ( BOOST_AUTO( j, i->cells.begin() ); j != i->cells.end(); j++ ) {
j->renditions.posterize();
}
}
}
void Framebuffer::resize( int s_width, int s_height )
{
assert( s_width > 0 );
@@ -453,6 +462,64 @@ std::string Renditions::sgr( void ) const
return ret;
}
/* Reduce 256 "standard" colors to the 8 ANSI colors. */
/* We could do something fancy like find the nearest system color in
the deltaE(2000) sense, but for "business graphics," the colorimetric
intent is probably less important than just having separate colors
be separate as much as possible. */
/* Terminal emulators generally agree on the (R',G',B') values of the
"standard" 256-color pallette beyond #15, but for the first 16
colors there is disagreement. Most terminal emulators are roughly
self-consistent, except on Ubuntu's gnome-terminal where "ANSI
blue" (#4) has been replaced with the aubergine system-wide
color. See
https://lists.ubuntu.com/archives/ubuntu-devel/2011-March/032726.html
For purposes of this routine, we just treat the eight colors as
taking each possible assignment of 0 or 255 to their components.
Terminal emulators that advertise "xterm" are inconsistent on the
handling of initc to change the contents of a cell in the color
pallette. On RIS (reset to initial state) or choosing reset from
the user interface, xterm resets all entries, but gnome-terminal
only resets entries beyond 16. (rxvt doesn't reset any entries,
and Terminal.app ignores initc.) On initc, xterm applies changes
immediately (but slowly), but gnome-terminal's changes are only
prospective unless the user resizes the terminal.
mosh ignores initc for now, despite advertising xterm-256color. */
static const char standard_posterization[] = {
0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
0, 0, 4, 4, 4, 4, 0, 0, 4, 4, 4, 4, 2, 2, 6, 6,
6, 6, 2, 2, 6, 6, 6, 6, 2, 2, 6, 6, 6, 6, 2, 2,
6, 6, 6, 6, 0, 0, 4, 4, 4, 4, 0, 0, 4, 4, 4, 4,
2, 2, 6, 6, 6, 6, 2, 2, 6, 6, 6, 6, 2, 2, 6, 6,
6, 6, 2, 2, 6, 6, 6, 6, 1, 1, 5, 5, 5, 5, 1, 1,
5, 5, 5, 5, 3, 3, 7, 7, 7, 7, 3, 3, 7, 7, 7, 7,
3, 3, 7, 7, 7, 7, 3, 3, 7, 7, 7, 7, 1, 1, 5, 5,
5, 5, 1, 1, 5, 5, 5, 5, 3, 3, 7, 7, 7, 7, 3, 3,
7, 7, 7, 7, 3, 3, 7, 7, 7, 7, 3, 3, 7, 7, 7, 7,
1, 1, 5, 5, 5, 5, 1, 1, 5, 5, 5, 5, 3, 3, 7, 7,
7, 7, 3, 3, 7, 7, 7, 7, 3, 3, 7, 7, 7, 7, 3, 3,
7, 7, 7, 7, 1, 1, 5, 5, 5, 5, 1, 1, 5, 5, 5, 5,
3, 3, 7, 7, 7, 7, 3, 3, 7, 7, 7, 7, 3, 3, 7, 7,
7, 7, 3, 3, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 };
void Renditions::posterize( void )
{
if ( foreground_color ) {
foreground_color = 30 + standard_posterization[ foreground_color - 30 ];
}
if ( background_color ) {
background_color = 40 + standard_posterization[ background_color - 40 ];
}
}
void Row::reset( int background_color )
{
for ( std::vector<Cell>::iterator i = cells.begin();
+4
View File
@@ -40,6 +40,8 @@ namespace Terminal {
void set_rendition( int num );
std::string sgr( void ) const;
void posterize( void );
bool operator==( const Renditions &x ) const
{
return (bold == x.bold) && (underlined == x.underlined)
@@ -285,6 +287,8 @@ namespace Terminal {
void reset_cell( Cell *c ) { c->reset( ds.get_background_rendition() ); }
void reset_row( Row *r ) { r->reset( ds.get_background_rendition() ); }
void posterize( void );
void ring_bell( void ) { bell_count++; }
unsigned int get_bell_count( void ) const { return bell_count; }