sprixels: introduce sprixel cache #1401

This commit is contained in:
nick black 2021-03-14 17:54:36 -04:00 committed by Nick Black
parent 15aab20d21
commit 08b65a8699
4 changed files with 53 additions and 0 deletions

View File

@ -346,6 +346,19 @@ typedef struct ncpile {
int dimy, dimx; // rows and cols at time of render int dimy, dimx; // rows and cols at time of render
} ncpile; } ncpile;
// there is a context-wide set of displayed pixel glyphs ("sprixels"); i.e.
// these are independent of particular piles. there should never be very many
// associated with a context (a dozen or so at max). with the kitty protocol,
// we can register them, and then manipulate them by id. with the sixel
// protocol, we just have to rewrite them.
typedef struct sprixel {
char* glyph; // glyph; can be quite large
int id; // embedded into glusters field of nccell
int cols;
int rows;
struct sprixel* next;
} sprixel;
// the standard pile can be reached through ->stdplane. // the standard pile can be reached through ->stdplane.
typedef struct notcurses { typedef struct notcurses {
ncplane* stdplane; // standard plane, covers screen ncplane* stdplane; // standard plane, covers screen
@ -377,6 +390,8 @@ typedef struct notcurses {
pthread_mutex_t pilelock; // guards pile list, locks resize in render pthread_mutex_t pilelock; // guards pile list, locks resize in render
bool suppress_banner; // from notcurses_options bool suppress_banner; // from notcurses_options
sprixel* sprixelcache; // list of pixel graphics currently displayed
// desired margins (best-effort only), copied in from notcurses_options // desired margins (best-effort only), copied in from notcurses_options
int margin_t, margin_b, margin_r, margin_l; int margin_t, margin_b, margin_r, margin_l;
int loglevel; int loglevel;
@ -666,6 +681,8 @@ plane_debug(const ncplane* n, bool details){
} }
} }
void sprixel_free(sprixel* s);
static inline unsigned static inline unsigned
channels_pixel_p(uint64_t channels){ channels_pixel_p(uint64_t channels){
return channels & CELL_PIXEL_GRAPHICS; return channels & CELL_PIXEL_GRAPHICS;

View File

@ -946,6 +946,7 @@ notcurses* notcurses_core_init(const notcurses_options* opts, FILE* outfp){
ret->margin_l = opts->margin_l; ret->margin_l = opts->margin_l;
ret->margin_r = opts->margin_r; ret->margin_r = opts->margin_r;
ret->cursory = ret->cursorx = -1; ret->cursory = ret->cursorx = -1;
ret->sprixelcache = NULL;
memset(&ret->stats, 0, sizeof(ret->stats)); memset(&ret->stats, 0, sizeof(ret->stats));
memset(&ret->stashed_stats, 0, sizeof(ret->stashed_stats)); memset(&ret->stashed_stats, 0, sizeof(ret->stashed_stats));
reset_stats(&ret->stats); reset_stats(&ret->stats);
@ -1102,6 +1103,15 @@ ncpile_drop(notcurses* nc, ncpile** pile){
} }
} }
static void
free_sprixels(notcurses* nc){
while(nc->sprixelcache){
sprixel* tmp = nc->sprixelcache->next;
sprixel_free(nc->sprixelcache);
nc->sprixelcache = tmp;
}
}
// drop all piles and all planes, save the standard plane and its pile // drop all piles and all planes, save the standard plane and its pile
void notcurses_drop_planes(notcurses* nc){ void notcurses_drop_planes(notcurses* nc){
pthread_mutex_lock(&nc->pilelock); pthread_mutex_lock(&nc->pilelock);
@ -1137,6 +1147,7 @@ int notcurses_stop(notcurses* nc){
if(nc->ttyfd >= 0){ if(nc->ttyfd >= 0){
ret |= close(nc->ttyfd); ret |= close(nc->ttyfd);
} }
free_sprixels(nc);
egcpool_dump(&nc->pool); egcpool_dump(&nc->pool);
free(nc->lastframe); free(nc->lastframe);
free(nc->rstate.mstream); free(nc->rstate.mstream);

8
src/lib/sprite.c Normal file
View File

@ -0,0 +1,8 @@
#include "internal.h"
void sprixel_free(sprixel* s){
if(s){
free(s->glyph);
free(s);
}
}

17
src/tests/pixel.cpp Normal file
View File

@ -0,0 +1,17 @@
#include "main.h"
TEST_CASE("Pixel") {
auto nc_ = testing_notcurses();
REQUIRE(nullptr != nc_);
ncplane* ncp_ = notcurses_stdplane(nc_);
REQUIRE(ncp_);
auto n_ = notcurses_stdplane(nc_);
REQUIRE(n_);
if(!notcurses_check_pixel_support(nc_)){
CHECK(!notcurses_stop(nc_));
return;
}
CHECK(!notcurses_stop(nc_));
}