ncplane: background directcolor works

This commit is contained in:
nick black 2019-11-23 12:39:54 -05:00
parent fd04c55d16
commit 8856f67822
No known key found for this signature in database
GPG Key ID: 5F43400C21CBFACC
3 changed files with 96 additions and 26 deletions

View File

@ -267,7 +267,15 @@ cell_rgb_set_fg(uint64_t* channels, unsigned r, unsigned g, unsigned b){
uint64_t rgb = (r & 0xffull) << 48u;
rgb |= (g & 0xffull) << 40u;
rgb |= (b & 0xffull) << 32u;
*channels = (*channels & 0x00ffffff00000000ull) | rgb;
*channels = (*channels & ~0x00ffffff00000000ull) | rgb;
}
static inline void
cell_rgb_set_bg(uint64_t* channels, unsigned r, unsigned g, unsigned b){
uint64_t rgb = (r & 0xffull) << 16u;
rgb |= (g & 0xffull) << 8u;
rgb |= (b & 0xffull);
*channels = (*channels & ~0x0000000000ffffffull) | rgb;
}
static inline void
@ -276,12 +284,24 @@ cell_set_fg(cell* c, unsigned r, unsigned g, unsigned b){
}
static inline void
cell_get_fb(const cell* c, unsigned* r, unsigned* g, unsigned* b){
cell_set_bg(cell* c, unsigned r, unsigned g, unsigned b){
cell_rgb_set_bg(&c->channels, r, g, b);
}
static inline void
cell_get_fg(const cell* c, unsigned* r, unsigned* g, unsigned* b){
*r = cell_rgb_red(cell_fg_rgb(c->channels));
*g = cell_rgb_green(cell_fg_rgb(c->channels));
*b = cell_rgb_blue(cell_fg_rgb(c->channels));
}
static inline void
cell_get_bg(const cell* c, unsigned* r, unsigned* g, unsigned* b){
*r = cell_rgb_red(cell_bg_rgb(c->channels));
*g = cell_rgb_green(cell_bg_rgb(c->channels));
*b = cell_rgb_blue(cell_bg_rgb(c->channels));
}
#ifdef __cplusplus
} // extern "C"
#endif

View File

@ -48,7 +48,10 @@ int main(void){
if(ncplane_cursor_move_yx(ncp, y / 2, (x - wcslen(lstr)) / 2)){
goto err;
}
if(ncplane_fg_rgb8(ncp, 255, 255, 255)){
if(ncplane_fg_rgb8(ncp, 176, 121, 176)){
goto err;
}
if(ncplane_bg_rgb8(ncp, 255, 255, 255)){
goto err;
}
if(ncplane_putwstr(ncp, lstr) != (int)wcslen(lstr)){

View File

@ -395,6 +395,17 @@ erpchar(int c){
return EOF;
}
int ncplane_bg_rgb8(ncplane* n, int r, int g, int b){
if(r >= 256 || g >= 256 || b >= 256){
return -1;
}
if(r < 0 || g < 0 || b < 0){
return -1;
}
cell_rgb_set_bg(&n->channels, r, g, b);
return 0;
}
int ncplane_fg_rgb8(ncplane* n, int r, int g, int b){
if(r >= 256 || g >= 256 || b >= 256){
return -1;
@ -406,18 +417,16 @@ int ncplane_fg_rgb8(ncplane* n, int r, int g, int b){
return 0;
}
// 3 for foreground, 4 for background, ugh FIXME
static int
term_fg_rgb8(notcurses* nc, unsigned r, unsigned g, unsigned b){
// We typically want to use tputs() and tiperm() to acquire and write the
// escapes, as these take into account terminal-specific delays, padding,
// etc. For the case of DirectColor, there is no suitable terminfo entry, but
// we're also in that case working with hopefully more robust terminals.
// If it doesn't work, eh, it doesn't work. Fuck the world; save yourself.
if(nc->RGBflag){
#define RGBESC "\x1b[38;2;"
term_esc_rgb(notcurses* nc, int esc, unsigned r, unsigned g, unsigned b){
#define RGBESC1 "\x1b["
#define RGBESC2 "8;2;"
// rrr;ggg;bbbm
char rgbesc[] = RGBESC " ";
size_t len = strlen(RGBESC);
char rgbesc[] = RGBESC1 " " RGBESC2 " ";
size_t len = strlen(RGBESC1);
rgbesc[len++] = esc + '0';
len += strlen(RGBESC2);
if(r > 99){ rgbesc[len++] = r / 100 + '0'; }
if(r > 9){ rgbesc[len++] = (r % 100) / 10 + '0'; }
rgbesc[len++] = (r % 10) + '0';
@ -435,6 +444,40 @@ term_fg_rgb8(notcurses* nc, unsigned r, unsigned g, unsigned b){
if((w = write(nc->ttyfd, rgbesc, len)) < 0 || (size_t)w != len){
return -1;
}
return 0;
}
static int
term_bg_rgb8(notcurses* nc, unsigned r, unsigned g, unsigned b){
// We typically want to use tputs() and tiperm() to acquire and write the
// escapes, as these take into account terminal-specific delays, padding,
// etc. For the case of DirectColor, there is no suitable terminfo entry, but
// we're also in that case working with hopefully more robust terminals.
// If it doesn't work, eh, it doesn't work. Fuck the world; save yourself.
if(nc->RGBflag){
return term_esc_rgb(nc, 4, r, g, b);
}else{
if(nc->setaf == NULL){
return -1;
}
// For 256-color indexed mode, start constructing a palette based off
// the inputs *if we can change the palette*. If more than 256 are used on
// a single screen, start... combining close ones? For 8-color mode, simple
// interpolation. I have no idea what to do for 88 colors. FIXME
return -1;
}
return 0;
}
static int
term_fg_rgb8(notcurses* nc, unsigned r, unsigned g, unsigned b){
// We typically want to use tputs() and tiperm() to acquire and write the
// escapes, as these take into account terminal-specific delays, padding,
// etc. For the case of DirectColor, there is no suitable terminfo entry, but
// we're also in that case working with hopefully more robust terminals.
// If it doesn't work, eh, it doesn't work. Fuck the world; save yourself.
if(nc->RGBflag){
return term_esc_rgb(nc, 3, r, g, b);
}else{
if(nc->setaf == NULL){
return -1;
@ -493,12 +536,14 @@ int notcurses_render(notcurses* nc){
unsigned pr, pg, pb;
for(y = 0 ; y < nc->stdscr->leny ; ++y){
for(x = 0 ; x < nc->stdscr->lenx ; ++x){
unsigned r, g, b;
unsigned r, g, b, br, bg, bb;
// FIXME z-culling
const cell* c = &nc->stdscr->fb[fbcellidx(nc->stdscr, y, x)];
cell_get_fb(c, &r, &g, &b);
cell_get_fg(c, &r, &g, &b);
cell_get_bg(c, &br, &bg, &bb);
if(r != pr || g != pg || b != pb || (x == 0 && y == 0)){
term_fg_rgb8(nc, r, g, b);
term_bg_rgb8(nc, br, bg, bb);
pr = r;
pg = g;
pb = b;
@ -571,6 +616,8 @@ int ncplane_putwstr(ncplane* n, const wchar_t* wstr){
memset(&c, 0, sizeof(c));
uint32_t rgb = cell_fg_rgb(n->channels);
cell_set_fg(&c, cell_rgb_red(rgb), cell_rgb_green(rgb), cell_rgb_blue(rgb));
rgb = cell_bg_rgb(n->channels);
cell_set_bg(&c, cell_rgb_red(rgb), cell_rgb_green(rgb), cell_rgb_blue(rgb));
while(*wstr != L'\0'){
int wcs = load_cell(&c, wstr);
if(wcs < 0){