[kitty] most of sprite_kitty_cell_wipe()

This commit is contained in:
nick black 2021-03-20 04:44:40 -04:00 committed by Nick Black
parent 9270a58b2d
commit fc4c0a2d9c
6 changed files with 59 additions and 28 deletions

View File

@ -53,15 +53,15 @@ struct ncvisual_details;
typedef struct sprixel {
char* glyph; // glyph; can be quite large
int id; // embedded into glusters field of nccell
struct ncplane* n; // associated ncplane, provides location and size
struct ncplane* n; // associated ncplane
enum {
SPRIXEL_NOCHANGE,
SPRIXEL_INVALIDATED,
SPRIXEL_HIDE,
} invalidated;
struct sprixel* next;
int y, x; // only defined when being hidden (n is NULL)
int dimy, dimx; // likewise only defined when being hidden
int y, x;
int dimy, dimx;
} sprixel;
// A plane is memory for some rectilinear virtual window, plus current cursor
@ -318,7 +318,7 @@ typedef struct tinfo {
// wipe out a cell's worth of pixels from within a sprixel. for sixel, this
// means leaving out the pixels (and likely resizes the string). for kitty,
// this means dialing down their alpha to 0 (in equivalent space).
int (*pixel_cell_wipe)(sprixel* s, int y, int x);
int (*pixel_cell_wipe)(struct notcurses* nc, sprixel* s, int y, int x);
bool pixel_query_done; // have we yet performed pixel query?
bool sextants; // do we have (good, vetted) Unicode 13 sextant support?
bool braille; // do we have Braille support? (linux console does not)
@ -699,7 +699,8 @@ plane_debug(const ncplane* n, bool details){
void sprixel_free(sprixel* s);
void sprixel_hide(sprixel* s);
sprixel* sprixel_create(ncplane* n, const char* s, int bytes, int sprixelid);
// dimy and dimx are cell geometry, not pixel
sprixel* sprixel_create(ncplane* n, const char* s, int bytes, int sprixelid, int dimy, int dimx);
int sprite_kitty_annihilate(notcurses* nc, const ncpile* p, FILE* out, sprixel* s);
int sprite_sixel_annihilate(notcurses* nc, const ncpile* p, FILE* out, sprixel* s);
@ -1097,7 +1098,7 @@ egc_rtl(const char* egc, int* bytes){
static inline int
plane_blit_sixel(ncplane* n, const char* s, int bytes, int leny, int lenx,
int sprixelid){
sprixel* spx = sprixel_create(n, s, bytes, sprixelid);
sprixel* spx = sprixel_create(n, s, bytes, sprixelid, leny, lenx);
if(spx == NULL){
return -1;
}
@ -1261,8 +1262,8 @@ ncdirect_bg_default_p(const struct ncdirect* nc){
return channels_bg_default_p(ncdirect_channels(nc));
}
int sprite_sixel_cell_wipe(sprixel* s, int y, int x);
int sprite_kitty_cell_wipe(sprixel* s, int y, int x);
int sprite_sixel_cell_wipe(notcurses* nc, sprixel* s, int y, int x);
int sprite_kitty_cell_wipe(notcurses* nc, sprixel* s, int y, int x);
int sixel_blit(ncplane* nc, int linesize, const void* data, int begy, int begx,
int leny, int lenx, const blitterargs* bargs);

View File

@ -1,5 +1,40 @@
#include "internal.h"
#define RGBA_MAXLEN 768 // 768 base64-encoded pixels in 4096 bytes
int sprite_kitty_cell_wipe(notcurses* nc, sprixel* s, int ycell, int xcell){
if(ycell >= s->dimy){
return -1;
}
if(xcell >= s->dimx){
return -1;
}
int xpixels = nc->tcache.cellpixx;
int ypixels = nc->tcache.cellpixy;
int xpx = xpixels * xcell; // pixel coordinates where we start erasing
int ypx = ypixels * ycell;
char* c = s->glyph;
// every pixel was 4 source bytes, 32 bits, 6.33 base64 bytes. every 3 input pixels is
// 12 bytes (96 bits), an even 16 base64 bytes. there is chunking to worry about. there
// are up to 768 pixels in a chunk.
int chunks = (xcell + s->dimx * ycell) / RGBA_MAXLEN;
do{
while(*c != ';'){
++c;
}
++c;
if(chunks == 0){
// we're in the proper chunk. find the pixel offset of the first
// pixel (within the chunk).
int offset = (xpx + s->dimx * ypx) % RGBA_MAXLEN;
// skip the 16-byte pixel triples
int bytes = (offset / 3) * 16;
// FIXME
return 0;
}
}while(--chunks);
return -1;
}
static unsigned const char b64subs[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
@ -64,12 +99,10 @@ base64_rgba3(const uint32_t* pixels, size_t pcount, char* b64){
static int
write_kitty_data(FILE* fp, int linesize, int leny, int lenx,
const uint32_t* data, int sprixelid){
#define KITTY_MAXLEN 4096 // 4096B maximum payload
if(linesize % sizeof(*data)){
return -1;
}
int total = leny * lenx; // total number of pixels (4 * total == bytecount)
#define RGBA_MAXLEN 768 // 768 base64-encoded pixels in 4096 bytes
// number of 4KiB chunks we'll need
int chunks = (total + (RGBA_MAXLEN - 1)) / RGBA_MAXLEN;
int totalout = 0; // total pixels of payload out
@ -114,7 +147,6 @@ write_kitty_data(FILE* fp, int linesize, int leny, int lenx,
}
return 0;
#undef RGBA_MAXLEN
#undef KITTY_MAXLEN
}
// Kitty graphics blitter. Kitty can take in up to 4KiB at a time of (optionally
@ -146,7 +178,6 @@ int kitty_blit(ncplane* nc, int linesize, const void* data, int begy, int begx,
int leny, int lenx, const blitterargs* bargs){
(void)begy;
(void)begx;
//fprintf(stderr, "s=%d,v=%d\n", lenx, leny);
int r = kitty_blit_inner(nc, linesize, leny, lenx, data, bargs);
if(r < 0){
return -1;

View File

@ -922,11 +922,6 @@ emit_bg_palindex(notcurses* nc, FILE* out, const nccell* srccell){
return 0;
}
int sprite_kitty_cell_wipe(sprixel* s, int y, int x){
// FIXME
return 0;
}
int sprite_kitty_annihilate(notcurses* nc, const ncpile* p, FILE* out, sprixel* s){
(void)p;
(void)nc;
@ -936,7 +931,7 @@ int sprite_kitty_annihilate(notcurses* nc, const ncpile* p, FILE* out, sprixel*
return 0;
}
int sprite_sixel_cell_wipe(sprixel* s, int y, int x){
int sprite_sixel_cell_wipe(notcurses* nc, sprixel* s, int y, int x){
return 0; // FIXME
}

View File

@ -15,7 +15,9 @@ void sprixel_hide(sprixel* s){
s->n = NULL;
}
sprixel* sprixel_create(ncplane* n, const char* s, int bytes, int sprixelid){
// y and x are the cell geometry, not the pixel geometry
sprixel* sprixel_create(ncplane* n, const char* s, int bytes, int sprixelid,
int dimy, int dimx){
sprixel* ret = malloc(sizeof(sprixel));
if(ret){
if((ret->glyph = memdup(s, bytes + 1)) == NULL){
@ -24,6 +26,8 @@ sprixel* sprixel_create(ncplane* n, const char* s, int bytes, int sprixelid){
}
ret->invalidated = SPRIXEL_INVALIDATED;
ret->n = n;
ret->dimy = dimy;
ret->dimx = dimx;
if(ncplane_pile(n)){
notcurses* nc = ncplane_notcurses(n);
ret->next = nc->sprixelcache;

View File

@ -484,12 +484,12 @@ ncplane* ncvisual_render_cells(notcurses* nc, ncvisual* ncv, const struct blitse
ncplane* ncvisual_render_pixels(notcurses* nc, ncvisual* ncv, const struct blitset* bset,
int placey, int placex, int begy, int begx,
ncplane* n, ncscale_e scaling, ncplane* stdn){
int disprows, dispcols;
int disprows = 0, dispcols = 0;
if(scaling == NCSCALE_NONE || scaling == NCSCALE_NONE_HIRES){
dispcols = ncv->cols;
disprows = ncv->rows;
}
//fprintf(stderr, "INPUT N: %p\n", vopts ? vopts->n : NULL);
//fprintf(stderr, "INPUT N: %p rows: %d cols: %d\n", n ? n : NULL, disprows, dispcols);
if(n == NULL){ // create plane
if(scaling != NCSCALE_NONE && scaling != NCSCALE_NONE_HIRES){
ncplane_dim_yx(stdn, &disprows, &dispcols);
@ -524,7 +524,7 @@ ncplane* ncvisual_render_pixels(notcurses* nc, ncvisual* ncv, const struct blits
if(scaling == NCSCALE_SCALE || scaling == NCSCALE_SCALE_HIRES){
scale_visual(ncv, &disprows, &dispcols);
}
//fprintf(stderr, "pblit: %dx%d <- %dx%d of %d/%d stride %u @%dx%d %p %u\n", disprows, dispcols, begy, begx, ncv->rows, ncv->cols, ncv->rowstride, placey, placex, ncv->data, ncplane_notcurses(stdn)->nc->tcache.cellpixx);
//fprintf(stderr, "pblit: %dx%d <- %dx%d of %d/%d stride %u @%dx%d %p %u\n", disprows, dispcols, begy, begx, ncv->rows, ncv->cols, ncv->rowstride, placey, placex, ncv->data, nc->tcache.cellpixx);
blitterargs bargs;
bargs.pixel.celldimx = nc->tcache.cellpixx;
bargs.pixel.celldimy = nc->tcache.cellpixy;

View File

@ -39,8 +39,8 @@ TEST_CASE("Pixel") {
SUBCASE("PixelCellWipe") {
// first, assemble a visual equivalent to 4 cells
auto y = nc_->tcache.cellpixy;
auto x = nc_->tcache.cellpixx;
auto y = 2 * nc_->tcache.cellpixy;
auto x = 2 * nc_->tcache.cellpixx;
std::vector<uint32_t> v(x * y, 0xffffffff);
auto ncv = ncvisual_from_rgba(v.data(), y, sizeof(decltype(v)::value_type) * x, x);
REQUIRE(nullptr != ncv);
@ -58,13 +58,13 @@ TEST_CASE("Pixel") {
auto s = n->sprite;
REQUIRE(nullptr != s);
CHECK(0 == notcurses_render(nc_));
CHECK(0 == nc_->tcache.pixel_cell_wipe(s, 0, 0));
CHECK(0 == nc_->tcache.pixel_cell_wipe(nc_, s, 0, 0));
CHECK(0 == notcurses_render(nc_));
CHECK(0 == nc_->tcache.pixel_cell_wipe(s, 1, 1));
CHECK(0 == nc_->tcache.pixel_cell_wipe(nc_, s, 1, 1));
CHECK(0 == notcurses_render(nc_));
CHECK(0 == nc_->tcache.pixel_cell_wipe(s, 1, 0));
CHECK(0 == nc_->tcache.pixel_cell_wipe(nc_, s, 1, 0));
CHECK(0 == notcurses_render(nc_));
CHECK(0 == nc_->tcache.pixel_cell_wipe(s, 0, 1));
CHECK(0 == nc_->tcache.pixel_cell_wipe(nc_, s, 0, 1));
CHECK(0 == notcurses_render(nc_));
ncplane_destroy(n);
ncvisual_destroy(ncv);