add ncplane_fadein() #40

pull/100/head
nick black 5 years ago committed by Nick Black
parent 02b30c822e
commit 966239747c

@ -353,6 +353,11 @@ API unsigned ncplane_styles(const struct ncplane* n);
// It is not safe to resize or destroy the plane during the fadeout FIXME.
API int ncplane_fadeout(struct ncplane* n, const struct timespec* ts);
// Fade the ncplane in over the specified time. Load the ncplane with the
// target cells without rendering, then call this function. When it's done, the
// ncplane will have reached the target levels, starting from zeroes.
API int ncplane_fadein(struct ncplane* n, const struct timespec* ts);
// Working with cells
#define CELL_TRIVIAL_INITIALIZER { .gcluster = '\0', .attrword = 0, .channels = 0, }

@ -312,10 +312,12 @@ int widecolor_demo(struct notcurses* nc){
if(notcurses_render(nc)){
return -1;
}
/*if(i){ FIXME
fadein(w, count, palette, FADE_MILLISECONDS);
if(i){
struct timespec tv = {
.tv_sec = 0, .tv_nsec = FADE_MILLISECONDS * 1000000,
};
ncplane_fadein(n, &tv);
}
*/
int key;
do{
key = notcurses_getc_blocking(nc, &c, &special);

@ -1648,6 +1648,68 @@ alloc_ncplane_palette(ncplane* n, planepalette* pp){
return 0;
}
int ncplane_fadein(ncplane* n, const struct timespec* ts){
planepalette pp;
if(!n->nc->RGBflag && !n->nc->CCCflag){ // terminal can't fade
notcurses_render(n->nc); // render at the target levels (ought we delay?)
return -1;
}
if(alloc_ncplane_palette(n, &pp)){
return -1;
}
int maxfsteps = pp.maxg > pp.maxr ? (pp.maxb > pp.maxg ? pp.maxb : pp.maxg) :
(pp.maxb > pp.maxr ? pp.maxb : pp.maxr);
int maxbsteps = pp.maxbg > pp.maxbr ? (pp.maxbb > pp.maxbg ? pp.maxbb : pp.maxbg) :
(pp.maxbb > pp.maxbr ? pp.maxbb : pp.maxbr);
int maxsteps = maxfsteps > maxbsteps ? maxfsteps : maxbsteps;
uint64_t nanosecs_total = ts->tv_sec * NANOSECS_IN_SEC + ts->tv_nsec;
uint64_t nanosecs_step = nanosecs_total / maxsteps;
struct timespec times;
clock_gettime(CLOCK_MONOTONIC, &times);
// Start time in absolute nanoseconds
uint64_t startns = times.tv_sec * NANOSECS_IN_SEC + times.tv_nsec;
// Current time, sampled each iteration
uint64_t curns;
do{
clock_gettime(CLOCK_MONOTONIC, &times);
curns = times.tv_sec * NANOSECS_IN_SEC + times.tv_nsec;
int iter = (curns - startns) / nanosecs_step + 1;
if(iter > maxsteps){
break;
}
int p;
for(p = 0 ; p < pp.size ; ++p){
cell* c = &n->fb[p];
unsigned r, g, b;
cell_rgb_get_fg(pp.channels[p], &r, &g, &b);
unsigned br, bg, bb;
cell_rgb_get_bg(pp.channels[p], &br, &bg, &bb);
r = r * iter / maxsteps;
g = g * iter / maxsteps;
b = b * iter / maxsteps;
cell_set_fg(c, r, g, b);
br = br * iter / maxsteps;
bg = bg * iter / maxsteps;
bb = bb * iter / maxsteps;
cell_set_bg(c, br, bg, bb);
}
notcurses_render(n->nc);
uint64_t nextwake = (iter + 1) * nanosecs_step + startns;
struct timespec sleepspec;
sleepspec.tv_sec = nextwake / NANOSECS_IN_SEC;
sleepspec.tv_nsec = nextwake % NANOSECS_IN_SEC;
int r;
// clock_nanosleep() has no love for CLOCK_MONOTONIC_RAW, at least as
// of Glibc 2.29 + Linux 5.3 :/.
r = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &sleepspec, NULL);
if(r){
break;
}
}while(true);
free(pp.channels);
return 0;
}
int ncplane_fadeout(ncplane* n, const struct timespec* ts){
planepalette pp;
if(!n->nc->RGBflag && !n->nc->CCCflag){ // terminal can't fade

Loading…
Cancel
Save