Posterize to 8 colors when outer terminal does not support 256 colors
Fixes #58 github issue.
This commit is contained in:
@@ -148,7 +148,7 @@ int main( void )
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Print a frame if the last frame was more than 1/50 seconds ago */
|
/* 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 )
|
const Terminal::Display &display )
|
||||||
{
|
{
|
||||||
static bool initialized = false;
|
static bool initialized = false;
|
||||||
@@ -165,6 +165,8 @@ bool tick( Terminal::Framebuffer &state, const Terminal::Framebuffer &new_frame,
|
|||||||
|
|
||||||
if ( (!initialized)
|
if ( (!initialized)
|
||||||
|| (diff >= 0.02) ) {
|
|| (diff >= 0.02) ) {
|
||||||
|
display.downgrade( new_frame );
|
||||||
|
|
||||||
std::string update = display.new_frame( initialized, state, new_frame );
|
std::string update = display.new_frame( initialized, state, new_frame );
|
||||||
swrite( STDOUT_FILENO, update.c_str() );
|
swrite( STDOUT_FILENO, update.c_str() );
|
||||||
state = new_frame;
|
state = new_frame;
|
||||||
@@ -314,7 +316,9 @@ void emulate_terminal( int fd )
|
|||||||
break;
|
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;
|
poll_timeout = -1;
|
||||||
} else {
|
} else {
|
||||||
poll_timeout = 20;
|
poll_timeout = 20;
|
||||||
|
|||||||
@@ -158,6 +158,9 @@ void STMClient::output_new_frame( void )
|
|||||||
/* apply local overlays */
|
/* apply local overlays */
|
||||||
overlays.apply( *new_state );
|
overlays.apply( *new_state );
|
||||||
|
|
||||||
|
/* apply any mutations */
|
||||||
|
display.downgrade( *new_state );
|
||||||
|
|
||||||
/* calculate minimal difference from where we are */
|
/* calculate minimal difference from where we are */
|
||||||
const string diff( display.new_frame( !repaint_requested,
|
const string diff( display.new_frame( !repaint_requested,
|
||||||
*local_framebuffer,
|
*local_framebuffer,
|
||||||
|
|||||||
@@ -54,9 +54,13 @@ namespace Terminal {
|
|||||||
|
|
||||||
bool has_bce; /* erases result in cell filled with background color */
|
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;
|
void put_cell( bool initialized, FrameState &frame, const Framebuffer &f ) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
void downgrade( Framebuffer &f ) const { if ( posterize_colors ) { f.posterize(); } }
|
||||||
|
|
||||||
std::string new_frame( bool initialized, const Framebuffer &last, const Framebuffer &f ) const;
|
std::string new_frame( bool initialized, const Framebuffer &last, const Framebuffer &f ) const;
|
||||||
|
|
||||||
Display( bool use_environment );
|
Display( bool use_environment );
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
using namespace Terminal;
|
using namespace Terminal;
|
||||||
|
|
||||||
Display::Display( bool use_environment )
|
Display::Display( bool use_environment )
|
||||||
: has_ech( true ), has_bce( true )
|
: has_ech( true ), has_bce( true ), posterize_colors( false )
|
||||||
{
|
{
|
||||||
if ( use_environment ) {
|
if ( use_environment ) {
|
||||||
int errret = -2;
|
int errret = -2;
|
||||||
@@ -57,8 +57,7 @@ Display::Display( bool use_environment )
|
|||||||
char *val = tigetstr( ech_name );
|
char *val = tigetstr( ech_name );
|
||||||
if ( val == (char *)-1 ) {
|
if ( val == (char *)-1 ) {
|
||||||
throw std::string( "Invalid terminfo string capability " ) + ech_name;
|
throw std::string( "Invalid terminfo string capability " ) + ech_name;
|
||||||
}
|
} else if ( val == 0 ) {
|
||||||
if ( val == 0 ) {
|
|
||||||
has_ech = false;
|
has_ech = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,9 +66,17 @@ Display::Display( bool use_environment )
|
|||||||
int bce_val = tigetflag( bce_name );
|
int bce_val = tigetflag( bce_name );
|
||||||
if ( bce_val == -1 ) {
|
if ( bce_val == -1 ) {
|
||||||
throw std::string( "Invalid terminfo boolean capability " ) + bce_name;
|
throw std::string( "Invalid terminfo boolean capability " ) + bce_name;
|
||||||
}
|
} else if ( bce_val == 0 ) {
|
||||||
if ( bce_val == 0 ) {
|
|
||||||
has_bce = false;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -320,6 +320,15 @@ void Framebuffer::soft_reset( void )
|
|||||||
ds.clear_saved_cursor();
|
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 )
|
void Framebuffer::resize( int s_width, int s_height )
|
||||||
{
|
{
|
||||||
assert( s_width > 0 );
|
assert( s_width > 0 );
|
||||||
@@ -453,6 +462,64 @@ std::string Renditions::sgr( void ) const
|
|||||||
return ret;
|
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 )
|
void Row::reset( int background_color )
|
||||||
{
|
{
|
||||||
for ( std::vector<Cell>::iterator i = cells.begin();
|
for ( std::vector<Cell>::iterator i = cells.begin();
|
||||||
|
|||||||
@@ -40,6 +40,8 @@ namespace Terminal {
|
|||||||
void set_rendition( int num );
|
void set_rendition( int num );
|
||||||
std::string sgr( void ) const;
|
std::string sgr( void ) const;
|
||||||
|
|
||||||
|
void posterize( void );
|
||||||
|
|
||||||
bool operator==( const Renditions &x ) const
|
bool operator==( const Renditions &x ) const
|
||||||
{
|
{
|
||||||
return (bold == x.bold) && (underlined == x.underlined)
|
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_cell( Cell *c ) { c->reset( ds.get_background_rendition() ); }
|
||||||
void reset_row( Row *r ) { r->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++; }
|
void ring_bell( void ) { bell_count++; }
|
||||||
unsigned int get_bell_count( void ) const { return bell_count; }
|
unsigned int get_bell_count( void ) const { return bell_count; }
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user