notcurses_render: set colors naively #5

pull/13/head
nick black 5 years ago committed by Nick Black
parent 691d3d97b8
commit c8d11459ec

@ -31,7 +31,6 @@ int main(void){
if(notcurses_render(nc)){
goto err;
}
sleep(5);
if(notcurses_stop(nc)){
return EXIT_FAILURE;
}

@ -30,7 +30,10 @@
// (pretty large) 500x200 terminal. At 80x43, it's less than 200KB.
typedef struct cell {
wchar_t cchar[CCHARW_MAX]; // 5 * 4b == 20b
uint64_t attrs; // 16 MSB of attr bits, 24 of fg, 24 of bg
// The attrword covers classic NCURSES attributes (16 bits), plus foreground
// and background color, stored as 3x8bits of RGB. At render time, these
// 24-bit values are quantized down to terminal capabilities, if necessary.
uint64_t attrs;
uint32_t reserved; // 0 for now, serves to pad out struct
} cell;
@ -91,6 +94,11 @@ const char* notcurses_version(void){
return NOTCURSES_VERSION;
}
static inline int
fbcellidx(const ncplane* n, int row, int col){
return row * n->lenx + col;
}
void ncplane_dimensions(const ncplane* n, int* rows, int* cols){
*rows = n->leny;
*cols = n->lenx;
@ -350,29 +358,72 @@ erpchar(int c){
return EOF;
}
#define CELL_RMASK 0x0000ff0000000000ull
#define CELL_GMASK 0x000000ff00000000ull
#define CELL_BMASK 0x00000000ff000000ull
#define CELL_RGBMASK (CELL_RMASK | CELL_GMASK | CELL_BMASK)
static void
cell_set_fg(cell* c, unsigned r, unsigned g, unsigned b){
uint64_t rgb = (r & 0xffull) << 40u;
rgb += (g & 0xffull) << 32u;
rgb += (b & 0xffull) << 24u;
c->attrs = (c->attrs & ~CELL_RGBMASK) | rgb;
}
static void
cell_get_fb(const cell* c, unsigned* r, unsigned* g, unsigned* b){
*r = (c->attrs & CELL_RMASK) >> 40u;
*g = (c->attrs & CELL_GMASK) >> 32;
*b = (c->attrs & CELL_BMASK) >> 24u;
}
int ncplane_fg_rgb8(ncplane* n, unsigned r, unsigned g, unsigned b){
if(r >= 256 || g >= 256 || b >= 256){
return -1;
}
if(n->nc->setaf == NULL){
return -1;
}
cell_set_fg(&n->fb[fbcellidx(n, n->y, n->x)], r, g, b);
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.
static char rgbesc[] = "\x1b[38;2;%u;%u;%um";
if(n->nc->RGBflag){
if(write(n->nc->ttyfd, rgbesc, sizeof(rgbesc)) != sizeof(rgbesc)){
if(nc->RGBflag){
#define RGBESC "\x1b[38;2;"
// rrr;ggg;bbb;m
char rgbesc[] = RGBESC " ";
size_t len = strlen(RGBESC);
if(r > 99){ rgbesc[len++] = r / 100; }
if(r > 9){ rgbesc[len++] = (r % 100) / 10; }
rgbesc[len++] = r % 10;
rgbesc[len++] = ';';
if(g > 99){ rgbesc[len++] = g / 100; }
if(g > 9){ rgbesc[len++] = (g % 100) / 10; }
rgbesc[len++] = g % 10;
rgbesc[len++] = ';';
if(b > 99){ rgbesc[len++] = b / 100; }
if(b > 9){ rgbesc[len++] = (b % 100) / 10; }
rgbesc[len++] = b % 10;
rgbesc[len++] = ';';
rgbesc[len++] = 'm';
rgbesc[len] = '\0';
ssize_t w;
if((w = write(nc->ttyfd, rgbesc, len)) < 0 || (size_t)w != len){
return -1;
}
}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
fprintf(stderr, "you need more colors, fool\n");
return -1;
}
return 0;
@ -399,7 +450,11 @@ int notcurses_render(notcurses* nc){
return -1;
}
for(y = 0 ; y < nc->stdscr->leny ; ++y){
for(x = 0 ; x < nc->stdscr->lenx ; ++y){
for(x = 0 ; x < nc->stdscr->lenx ; ++x){
unsigned r, g, b;
// FIXME z-culling
cell_get_fb(&nc->stdscr->fb[fbcellidx(nc->stdscr, y, x)], &r, &g, &b);
term_fg_rgb8(nc, r, g, b);
// FIXME blit those fuckers
}
}

Loading…
Cancel
Save