From 4ee0582321dbee1d5f12b1df52215a8f3b97e5da Mon Sep 17 00:00:00 2001 From: nick black Date: Sat, 27 Mar 2021 10:48:50 -0400 Subject: [PATCH] [bitmaps] introduce sprixcell_e enum #1457 --- TERMINALS.md | 2 +- src/lib/internal.h | 34 +++++++++++++++++++++------------- src/lib/kitty.c | 8 ++++---- src/lib/render.c | 2 +- src/lib/sixel.c | 4 ++-- src/lib/sprite.c | 14 +++++++++++--- 6 files changed, 40 insertions(+), 24 deletions(-) diff --git a/TERMINALS.md b/TERMINALS.md index a1e4a07b0..f3b903bcf 100644 --- a/TERMINALS.md +++ b/TERMINALS.md @@ -35,7 +35,7 @@ relies on the font. Patches to correct/complete this table are very welcome! | st ("suckless") | ✅ | ✅ |? |`TERM=st-256color` `COLORTERM=24bit` | | | Terminator | ✅ | ? |? | ? | | | Terminology | ❌ | ? |? | ? | | -| Tilda | | ? |? | ? | | +| [Tilda](https://github.com/lanoxx/tilda) | | ? |? | ? | | | [tmux](https://github.com/tmux/tmux/wiki) | | ❌ |n/a |`TERM=tmux-256color` `COLORTERM=24bit` | `tmux.conf` must apply `Tc`; see below. `bce` is available with the `tmux-256color-bce` definition. | | [wezterm](https://github.com/wez/wezterm) | | ✅ |? |`TERM=wezterm` `COLORTERM=24bit` | | | [Windows Terminal](https://github.com/microsoft/terminal)| | ? |? | ? | | diff --git a/src/lib/internal.h b/src/lib/internal.h index d70d38e73..841c36835 100644 --- a/src/lib/internal.h +++ b/src/lib/internal.h @@ -46,27 +46,34 @@ struct ncvisual_details; // and we can't go throwing C++ syntax into this header. so it goes. typedef enum { - SPRIXEL_NOCHANGE, - SPRIXEL_INVALIDATED, - SPRIXEL_HIDE, + SPRIXEL_QUIESCENT, // sprixel has been drawn + SPRIXEL_INVALIDATED, // sprixel needs to be redrawn + SPRIXEL_HIDE, // sprixel queued for destruction } sprixel_e; +// elements of the T-A matrix +typedef enum { + SPRIXCELL_NORMAL, // no transparent pixels in this cell + SPRIXCELL_CONTAINS_TRANS, // this cell has transparent pixels + SPRIXCELL_ANNIHILATED, // this cell has been wiped +} sprixcell_e; + // 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 glyphlen; - uint32_t id; // embedded into glusters field of nccell, 24 bits - struct ncplane* n; // associated ncplane - sprixel_e invalidated; + char* glyph; // glyph; can be quite large + int glyphlen; // length of the glyph in bytes + uint32_t id; // embedded into glusters field of nccell, 24 bits + struct ncplane* n; // associated ncplane + sprixel_e invalidated;// sprixel invalidation state struct sprixel* next; int y, x; - int dimy, dimx; // cell geometry - int pixy, pixx; // pixel geometry (might be smaller than cell geo) - int* tacache; // transparency-annihilation cache (dimy * dimx) + int dimy, dimx; // cell geometry + int pixy, pixx; // pixel geometry (might be smaller than cell geo) + sprixcell_e* tacache; // transparency-annihilation cache (dimy * dimx) // each tacache entry is one of 0 (standard opaque cell), 1 (cell with // some transparency), 2 (annihilated, excised) int parse_start; // where to start parsing for cell wipes @@ -755,9 +762,10 @@ void sprixel_free(sprixel* s); void sprixel_invalidate(sprixel* s); void sprixel_hide(sprixel* s); // dimy and dimx are cell geometry, not pixel +sprixel* sprixel_update(sprixel* s, char* g, int bytes); sprixel* sprixel_create(ncplane* n, char* s, int bytes, int placey, int placex, int sprixelid, int dimy, int dimx, int pixy, int pixx, - int parse_start, int* tacache); + int parse_start, sprixcell_e* tacache); API int sprite_wipe_cell(const notcurses* nc, sprixel* s, int y, int x); int sprite_kitty_annihilate(const notcurses* nc, const ncpile* p, FILE* out, sprixel* s); int sprite_kitty_init(int fd); @@ -1162,7 +1170,7 @@ egc_rtl(const char* egc, int* bytes){ static inline int plane_blit_sixel(ncplane* n, char* s, int bytes, int placey, int placex, int leny, int lenx, int sprixelid, int dimy, int dimx, - int parse_start, int* tacache){ + int parse_start, sprixcell_e * tacache){ sprixel* spx = sprixel_create(n, s, bytes, placey, placex, sprixelid, leny, lenx, dimy, dimx, parse_start, tacache); if(spx == NULL){ diff --git a/src/lib/kitty.c b/src/lib/kitty.c index b82b8e1df..7868866ab 100644 --- a/src/lib/kitty.c +++ b/src/lib/kitty.c @@ -222,13 +222,13 @@ int sprite_kitty_cell_wipe(const notcurses* nc, sprixel* s, int ycell, int xcell // we can only write 4KiB at a time. we're writing base64-encoded RGBA. each // pixel is 4B raw (32 bits). each chunk of three pixels is then 12 bytes, or // 16 base64-encoded bytes. 4096 / 16 == 256 3-pixel groups, or 768 pixels. -static int* +static sprixcell_e* write_kitty_data(FILE* fp, int rows, int cols, int linesize, int leny, int lenx, const uint32_t* data, int sprixelid, int* parse_start){ if(linesize % sizeof(*data)){ return NULL; } - int* tacache = malloc(sizeof(*tacache) * rows * cols); + sprixcell_e* tacache = malloc(sizeof(*tacache) * rows * cols); if(tacache == NULL){ return NULL; } @@ -296,8 +296,8 @@ int kitty_blit(ncplane* nc, int linesize, const void* data, return -1; } int parse_start = 0; - int* tacache = write_kitty_data(fp, rows, cols, linesize, leny, lenx, data, - bargs->u.pixel.sprixelid, &parse_start); + sprixcell_e* tacache = write_kitty_data(fp, rows, cols, linesize, leny, lenx, data, + bargs->u.pixel.sprixelid, &parse_start); if(tacache == NULL){ fclose(fp); free(buf); diff --git a/src/lib/render.c b/src/lib/render.c index 0d3e1660d..be5e95c7e 100644 --- a/src/lib/render.c +++ b/src/lib/render.c @@ -965,7 +965,7 @@ rasterize_sprixels(notcurses* nc, const ncpile* p, FILE* out){ if(fwrite(s->glyph, s->glyphlen, 1, out) != 1){ return -1; } - s->invalidated = SPRIXEL_NOCHANGE; + s->invalidated = SPRIXEL_QUIESCENT; nc->rstate.hardcursorpos = true; parent = &s->next; }else if(s->invalidated == SPRIXEL_HIDE){ diff --git a/src/lib/sixel.c b/src/lib/sixel.c index 8ee4704cf..6e8ae2c07 100644 --- a/src/lib/sixel.c +++ b/src/lib/sixel.c @@ -415,7 +415,7 @@ write_rle(int* printed, int color, FILE* fp, int seenrle, unsigned char crle){ // Emit the sprixel in its entirety, plus enable and disable pixel mode. static int -write_sixel_data(FILE* fp, int lenx, sixeltable* stab, int* parse_start, int* tacache){ +write_sixel_data(FILE* fp, int lenx, sixeltable* stab, int* parse_start, sprixcell_e* tacache){ *parse_start = fprintf(fp, "\ePq"); // Set Raster Attributes - pan/pad=1 (pixel aspect ratio), Ph=lenx, Pv=leny // using Ph/Pv causes a background to be drawn using color register 0 for all @@ -496,7 +496,7 @@ int sixel_blit_inner(ncplane* nc, int leny, int lenx, sixeltable* stab, int parse_start = 0; unsigned cols = lenx / bargs->u.pixel.celldimx + !!(lenx % bargs->u.pixel.celldimx); unsigned rows = leny / bargs->u.pixel.celldimy + !!(leny % bargs->u.pixel.celldimy); - int* tacache = malloc(sizeof(*tacache) * rows * cols); + sprixcell_e* tacache = malloc(sizeof(*tacache) * rows * cols); memset(tacache, 0, sizeof(*tacache) * rows * cols); if(tacache == NULL){ free(buf); diff --git a/src/lib/sprite.c b/src/lib/sprite.c index 84637fedc..03db8a832 100644 --- a/src/lib/sprite.c +++ b/src/lib/sprite.c @@ -29,10 +29,18 @@ sprixel* sprixel_by_id(notcurses* nc, uint32_t id){ return NULL; } +// s ought already have been scrubbed according to the T-A matrix +sprixel* sprixel_update(sprixel* s, const char* g, int bytes){ + free(s->glyph); + s->glyph = g; + s->glyphlen = bytes; + s->invalidated = SPRIXEL_INVALIDATED; +} + // y and x are the cell geometry, not the pixel geometry sprixel* sprixel_create(ncplane* n, char* s, int bytes, int placey, int placex, int sprixelid, int dimy, int dimx, int pixy, int pixx, - int parse_start, int* tacache){ + int parse_start, sprixcell_e* tacache){ sprixel* ret = malloc(sizeof(sprixel)); if(ret){ ret->glyph = s; @@ -73,11 +81,11 @@ int sprite_wipe_cell(const notcurses* nc, sprixel* s, int ycell, int xcell){ return -1; } if(s->tacache[s->dimx * ycell + xcell] == 2){ -//fprintf(stderr, "CACHED WIPE %d %d/%d\n", s->id, ycell, xcell); +fprintf(stderr, "CACHED WIPE %d %d/%d\n", s->id, ycell, xcell); return 0; // already annihilated } s->tacache[s->dimx * ycell + xcell] = 2; -//fprintf(stderr, "WIPING %d %d/%d\n", s->id, ycell, xcell); +fprintf(stderr, "WIPING %d %d/%d\n", s->id, ycell, xcell); int r = nc->tcache.pixel_cell_wipe(nc, s, ycell, xcell); if(r == 0){ s->invalidated = SPRIXEL_INVALIDATED;