Notcurses 3.0.13
a blingful library for TUIs and character graphics
Loading...
Searching...
No Matches
sprite.h File Reference
#include <stdint.h>
#include <stdbool.h>
#include "fbuf.h"
Include dependency graph for sprite.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  tament
 
struct  sprixel
 

Macros

#define SIXEL_MAX_REGISTERS   65534
 

Typedefs

typedef struct tament tament
 
typedef struct sprixel sprixel
 

Enumerations

enum  sprixel_e {
  SPRIXEL_QUIESCENT , SPRIXEL_UNSEEN , SPRIXEL_LOADED , SPRIXEL_INVALIDATED ,
  SPRIXEL_HIDE , SPRIXEL_MOVED
}
 
enum  sprixcell_e {
  SPRIXCELL_TRANSPARENT , SPRIXCELL_OPAQUE_SIXEL , SPRIXCELL_OPAQUE_KITTY , SPRIXCELL_MIXED_SIXEL ,
  SPRIXCELL_MIXED_KITTY , SPRIXCELL_ANNIHILATED , SPRIXCELL_ANNIHILATED_TRANS
}
 

Functions

int sprite_init (struct tinfo *t, int fd)
 
int sixel_wipe (sprixel *s, int ycell, int xcell)
 
int kitty_wipe (sprixel *s, int ycell, int xcell)
 
int kitty_wipe_animation (sprixel *s, int ycell, int xcell)
 
int kitty_wipe_selfref (sprixel *s, int ycell, int xcell)
 
int fbcon_wipe (sprixel *s, int ycell, int xcell)
 
int sixel_rebuild (sprixel *s, int ycell, int xcell, uint8_t *auxvec)
 
int kitty_rebuild (sprixel *s, int ycell, int xcell, uint8_t *auxvec)
 
int fbcon_rebuild (sprixel *s, int ycell, int xcell, uint8_t *auxvec)
 
int kitty_rebuild_animation (sprixel *s, int ycell, int xcell, uint8_t *auxvec)
 
int kitty_rebuild_selfref (sprixel *s, int ycell, int xcell, uint8_t *auxvec)
 
int sixel_draw (const struct tinfo *ti, const struct ncpile *p, sprixel *s, fbuf *f, int yoff, int xoff)
 
int kitty_draw (const struct tinfo *ti, const struct ncpile *p, sprixel *s, fbuf *f, int yoff, int xoff)
 
int kitty_move (sprixel *s, fbuf *f, unsigned noscroll, int yoff, int xoff)
 
int sixel_scrub (const struct ncpile *p, sprixel *s)
 
int kitty_scrub (const struct ncpile *p, sprixel *s)
 
int fbcon_scrub (const struct ncpile *p, sprixel *s)
 
int kitty_remove (int id, fbuf *f)
 
int kitty_clear_all (fbuf *f)
 
int sixel_init_forcesdm (struct tinfo *ti, int fd)
 
int sixel_init_inverted (struct tinfo *ti, int fd)
 
int sixel_init (struct tinfo *ti, int fd)
 
uint8_t * sixel_trans_auxvec (const struct ncpile *p)
 
uint8_t * kitty_trans_auxvec (const struct ncpile *p)
 
int kitty_commit (fbuf *f, sprixel *s, unsigned noscroll)
 
int sixel_blit (struct ncplane *nc, int linesize, const void *data, int leny, int lenx, const struct blitterargs *bargs)
 
int kitty_blit (struct ncplane *nc, int linesize, const void *data, int leny, int lenx, const struct blitterargs *bargs)
 
int kitty_blit_animated (struct ncplane *n, int linesize, const void *data, int leny, int lenx, const struct blitterargs *bargs)
 
int kitty_blit_selfref (struct ncplane *nc, int linesize, const void *data, int leny, int lenx, const struct blitterargs *bargs)
 
int fbcon_blit (struct ncplane *nc, int linesize, const void *data, int leny, int lenx, const struct blitterargs *bargs)
 
int fbcon_draw (const struct tinfo *ti, sprixel *s, int yoff, int xoff)
 
void fbcon_scroll (const struct ncpile *p, struct tinfo *ti, int rows)
 
void sixel_refresh (const struct ncpile *p, sprixel *s)
 
int sprixel_load (sprixel *spx, fbuf *f, unsigned pixy, unsigned pixx, int parse_start, sprixel_e state)
 
int sprixel_rescale (sprixel *spx, unsigned ncellpixy, unsigned ncellpixx)
 
void sixel_cleanup (struct tinfo *ti)
 

Macro Definition Documentation

◆ SIXEL_MAX_REGISTERS

#define SIXEL_MAX_REGISTERS   65534

Definition at line 12 of file sprite.h.

Typedef Documentation

◆ sprixel

typedef struct sprixel sprixel

◆ tament

typedef struct tament tament

Enumeration Type Documentation

◆ sprixcell_e

Enumerator
SPRIXCELL_TRANSPARENT 
SPRIXCELL_OPAQUE_SIXEL 
SPRIXCELL_OPAQUE_KITTY 
SPRIXCELL_MIXED_SIXEL 
SPRIXCELL_MIXED_KITTY 
SPRIXCELL_ANNIHILATED 
SPRIXCELL_ANNIHILATED_TRANS 

Definition at line 114 of file sprite.h.

114 {
115 SPRIXCELL_TRANSPARENT, // all pixels are naturally transparent
116 SPRIXCELL_OPAQUE_SIXEL, // no transparent pixels in this cell
118 SPRIXCELL_MIXED_SIXEL, // this cell has both opaque and transparent pixels
120 SPRIXCELL_ANNIHILATED, // this cell has been wiped (all trans)
121 SPRIXCELL_ANNIHILATED_TRANS, // this transparent cell is covered
sprixcell_e
Definition sprite.h:114
@ SPRIXCELL_ANNIHILATED
Definition sprite.h:120
@ SPRIXCELL_TRANSPARENT
Definition sprite.h:115
@ SPRIXCELL_ANNIHILATED_TRANS
Definition sprite.h:121
@ SPRIXCELL_MIXED_SIXEL
Definition sprite.h:118
@ SPRIXCELL_MIXED_KITTY
Definition sprite.h:119
@ SPRIXCELL_OPAQUE_SIXEL
Definition sprite.h:116
@ SPRIXCELL_OPAQUE_KITTY
Definition sprite.h:117

◆ sprixel_e

enum sprixel_e
Enumerator
SPRIXEL_QUIESCENT 
SPRIXEL_UNSEEN 
SPRIXEL_LOADED 
SPRIXEL_INVALIDATED 
SPRIXEL_HIDE 
SPRIXEL_MOVED 

Definition at line 20 of file sprite.h.

20 {
21 SPRIXEL_QUIESCENT, // up-to-date and visible at the proper place
22 SPRIXEL_UNSEEN, // not yet loaded, invisible, but wants loading
23 SPRIXEL_LOADED, // loaded, but not yet made visible (kitty-only)
24 SPRIXEL_INVALIDATED, // not up-to-date, need reload
25 SPRIXEL_HIDE, // queued for destruction
26 SPRIXEL_MOVED, // visible, up-to-date, but in the wrong place
27} sprixel_e;
sprixel_e
Definition sprite.h:20
@ SPRIXEL_UNSEEN
Definition sprite.h:22
@ SPRIXEL_LOADED
Definition sprite.h:23
@ SPRIXEL_QUIESCENT
Definition sprite.h:21
@ SPRIXEL_INVALIDATED
Definition sprite.h:24
@ SPRIXEL_HIDE
Definition sprite.h:25
@ SPRIXEL_MOVED
Definition sprite.h:26

Function Documentation

◆ fbcon_blit()

int fbcon_blit ( struct ncplane nc,
int  linesize,
const void *  data,
int  leny,
int  lenx,
const struct blitterargs bargs 
)

Definition at line 44 of file linux.c.

45 {
46 uint32_t transcolor = bargs->transcolor;
47 sprixel* s = bargs->u.pixel.spx;
48 int cdimx = bargs->u.pixel.cellpxx;
49 int cdimy = bargs->u.pixel.cellpxy;
50 // FIXME this will need be a copy of the tinfo's fbuf map
51 size_t flen = leny * lenx * 4;
52 if(fbuf_reserve(&s->glyph, flen)){
53 return -1;
54 }
55 for(int l = 0 ; l < leny ; ++l){
56 int ycell = l / cdimy;
57 size_t soffset = l * linesize;
58 const uint8_t* src = (const unsigned char*)data + soffset;
59 size_t toffset = l * lenx * 4;
60 char* dst = (char *)s->glyph.buf + toffset;
61 for(int c = 0 ; c < lenx ; ++c){
62 int xcell = c / cdimx;
63 int tyx = xcell + ycell * bargs->u.pixel.spx->dimx;
64 if(n->tam[tyx].state >= SPRIXCELL_ANNIHILATED){
65 if(rgba_trans_p(*(uint32_t*)src, transcolor)){
66 ncpixel_set_a((uint32_t*)src, 0); // in case it was transcolor
67 if(c % cdimx == 0 && l % cdimy == 0){
68 n->tam[tyx].state = SPRIXCELL_ANNIHILATED_TRANS;
69 }
70 }else{
71 n->tam[tyx].state = SPRIXCELL_ANNIHILATED;
72 }
73 dst[3] = 0;
74 const int vyx = (l % cdimy) * cdimx + (c % cdimx);
75 ((uint8_t*)n->tam[tyx].auxvector)[vyx] = src[3];
76 }else{
77 if(rgba_trans_p(*(uint32_t*)src, transcolor)){
78 ncpixel_set_a((uint32_t*)src, 0); // in case it was transcolor
79 if(c % cdimx == 0 && l % cdimy == 0){
80 n->tam[tyx].state = SPRIXCELL_TRANSPARENT;
81 }else if(n->tam[tyx].state == SPRIXCELL_OPAQUE_SIXEL){
82 n->tam[tyx].state = SPRIXCELL_MIXED_SIXEL;
83 }
84 dst[3] = 0;
85 }else{
86 if(c % cdimx == 0 && l % cdimy == 0){
87 n->tam[tyx].state = SPRIXCELL_OPAQUE_SIXEL;
88 }else if(n->tam[tyx].state == SPRIXCELL_TRANSPARENT){
89 n->tam[tyx].state = SPRIXCELL_MIXED_SIXEL;
90 }
91 memcpy(dst + 3, src + 3, 1);
92 }
93 }
94 memcpy(dst, src + 2, 1);
95 memcpy(dst + 1, src + 1, 1);
96 memcpy(dst + 2, src, 1);
97 dst += 4;
98 src += 4;
99 }
100 }
101 scrub_tam_boundaries(n->tam, leny, lenx, cdimy, cdimx);
102 if(plane_blit_sixel(s, &s->glyph, leny, lenx, 0, n->tam, SPRIXEL_INVALIDATED) < 0){
103 goto error;
104 }
105 return 1;
106
107error:
108 fbuf_free(&s->glyph);
109 s->glyph.size = 0;
110 return -1;
111}
const nccell * c
Definition egcpool.h:296
vopts n
Definition notcurses.h:3502
struct blitterargs::@3::@5 pixel
sprixel * spx
Definition internal.h:388
union blitterargs::@3 u
uint32_t transcolor
Definition internal.h:380
char * buf
Definition fbuf.h:28
uint64_t size
Definition fbuf.h:26
unsigned dimx
Definition sprite.h:146
fbuf glyph
Definition sprite.h:138

◆ fbcon_draw()

int fbcon_draw ( const struct tinfo ti,
sprixel s,
int  yoff,
int  xoff 
)

◆ fbcon_rebuild()

int fbcon_rebuild ( sprixel s,
int  ycell,
int  xcell,
uint8_t *  auxvec 
)

Definition at line 791 of file linux.c.

791 {
792 (void)s;
793 (void)ycell;
794 (void)xcell;
795 (void)auxvec;
796 return 0;
797}

◆ fbcon_scroll()

void fbcon_scroll ( const struct ncpile p,
struct tinfo ti,
int  rows 
)

Definition at line 807 of file linux.c.

807 {
808 (void)p;
809 (void)ti;
810 (void)rows;
811}

◆ fbcon_scrub()

int fbcon_scrub ( const struct ncpile p,
sprixel s 
)

Definition at line 113 of file linux.c.

113 {
114 return sixel_scrub(p, s);
115}
int sixel_scrub(const ncpile *p, sprixel *s)
Definition sixel.c:1439
Here is the call graph for this function:

◆ fbcon_wipe()

int fbcon_wipe ( sprixel s,
int  ycell,
int  xcell 
)

Definition at line 16 of file linux.c.

16 {
17 uint8_t* auxvec = fbcon_auxiliary_vector(s);
18 if(auxvec == NULL){
19 return -1;
20 }
21 const int cellpxy = ncplane_pile(s->n)->cellpxy;
22 const int cellpxx = ncplane_pile(s->n)->cellpxx;
23 char* glyph = s->glyph.buf;
24 for(int y = 0 ; y < cellpxy ; ++y){
25 if(ycell * cellpxy + y >= s->pixy){
26 break;
27 }
28 // number of pixels total above our pixel row
29 const size_t yoff = s->pixx * (ycell * cellpxy + y);
30 for(int x = 0 ; x < cellpxx ; ++x){
31 if(xcell * cellpxx + x >= s->pixx){
32 break;
33 }
34 size_t offset = (yoff + xcell * cellpxx + x) * 4;
35 const int vyx = (y % cellpxy) * cellpxx + x;
36 auxvec[vyx] = glyph[offset + 3];
37 glyph[offset + 3] = 0;
38 }
39 }
40 s->n->tam[s->dimx * ycell + xcell].auxvector = auxvec;
41 return 0;
42}
int y
Definition notcurses.h:1905
int int x
Definition notcurses.h:1905
tament * tam
Definition internal.h:106
int pixx
Definition sprite.h:147
int pixy
Definition sprite.h:147
struct ncplane * n
Definition sprite.h:142
void * auxvector
Definition sprite.h:128
return NULL
Definition termdesc.h:229

◆ kitty_blit()

int kitty_blit ( struct ncplane nc,
int  linesize,
const void *  data,
int  leny,
int  lenx,
const struct blitterargs bargs 
)

◆ kitty_blit_animated()

int kitty_blit_animated ( struct ncplane n,
int  linesize,
const void *  data,
int  leny,
int  lenx,
const struct blitterargs bargs 
)

◆ kitty_blit_selfref()

int kitty_blit_selfref ( struct ncplane nc,
int  linesize,
const void *  data,
int  leny,
int  lenx,
const struct blitterargs bargs 
)

◆ kitty_clear_all()

int kitty_clear_all ( fbuf f)

Definition at line 1210 of file kitty.c.

1210 {
1211//fprintf(stderr, "KITTY UNIVERSAL ERASE\n");
1212 if(fbuf_putn(f, "\x1b_Ga=d,q=2\x1b\\", 12) < 0){
1213 return -1;
1214 }
1215 return 0;
1216}

◆ kitty_commit()

int kitty_commit ( fbuf f,
sprixel s,
unsigned  noscroll 
)

Definition at line 534 of file kitty.c.

534 {
535 loginfo("committing Kitty graphic id %u", s->id);
536 int i;
537 if(s->pxoffx || s->pxoffy){
538 i = fbuf_printf(f, "\e_Ga=p,i=%u,p=1,X=%u,Y=%u%s,q=2\e\\", s->id,
539 s->pxoffx, s->pxoffy, noscroll ? ",C=1" : "");
540 }else{
541 i = fbuf_printf(f, "\e_Ga=p,i=%u,p=1,q=2%s\e\\", s->id, noscroll ? ",C=1" : "");
542 }
543 if(i < 0){
544 return -1;
545 }
547 return 0;
548}
#define loginfo(fmt,...)
Definition logging.h:42
int pxoffx
Definition sprite.h:154
int pxoffy
Definition sprite.h:154
uint32_t id
Definition sprite.h:139
sprixel_e invalidated
Definition sprite.h:143

◆ kitty_draw()

int kitty_draw ( const struct tinfo ti,
const struct ncpile p,
sprixel s,
fbuf f,
int  yoff,
int  xoff 
)

◆ kitty_move()

int kitty_move ( sprixel s,
fbuf f,
unsigned  noscroll,
int  yoff,
int  xoff 
)

Definition at line 1194 of file kitty.c.

1194 {
1195 const int targy = s->n->absy;
1196 const int targx = s->n->absx;
1197 logdebug("moving %u to %d %d", s->id, targy, targx);
1198 int ret = 0;
1199 if(goto_location(ncplane_notcurses(s->n), f, targy + yoff, targx + xoff, s->n)){
1200 ret = -1;
1201 }else if(fbuf_printf(f, "\e_Ga=p,i=%d,p=1,q=2%s\e\\", s->id,
1202 noscroll ? ",C=1" : "") < 0){
1203 ret = -1;
1204 }
1206 return ret;
1207}
#define logdebug(fmt,...)
Definition logging.h:52
notcurses * ncplane_notcurses(const ncplane *n)
Definition notcurses.c:2626
int absy
Definition internal.h:83
int absx
Definition internal.h:83
Here is the call graph for this function:

◆ kitty_rebuild()

int kitty_rebuild ( sprixel s,
int  ycell,
int  xcell,
uint8_t *  auxvec 
)

Definition at line 219 of file kitty.c.

219 {
220 const int totalpixels = s->pixy * s->pixx;
221 const int xpixels = ncplane_pile(s->n)->cellpxx;
222 const int ypixels = ncplane_pile(s->n)->cellpxy;
223 int targx = xpixels;
224 if((xcell + 1) * xpixels > s->pixx){
225 targx = s->pixx - xcell * xpixels;
226 }
227 int targy = ypixels;
228 if((ycell + 1) * ypixels > s->pixy){
229 targy = s->pixy - ycell * ypixels;
230 }
231 char* c = (char*)s->glyph.buf + s->parse_start;
232 int nextpixel = (s->pixx * ycell * ypixels) + (xpixels * xcell);
233 int thisrow = targx;
234 int chunkedhandled = 0;
236 const int chunks = totalpixels / RGBA_MAXLEN + !!(totalpixels % RGBA_MAXLEN);
237 int auxvecidx = 0;
238 while(targy && chunkedhandled < chunks){ // need to null out |targy| rows of |targx| pixels, track with |thisrow|
239 int inchunk = totalpixels - chunkedhandled * RGBA_MAXLEN;
240 if(inchunk > RGBA_MAXLEN){
241 inchunk = RGBA_MAXLEN;
242 }
243 const int curpixel = chunkedhandled * RGBA_MAXLEN;
244 // a full chunk is 4096 + 2 + 7 (5005)
245 while(nextpixel - curpixel < RGBA_MAXLEN && thisrow){
246 // our next pixel is within this chunk. find the pixel offset of the
247 // first pixel (within the chunk).
248 int pixoffset = nextpixel - curpixel;
249 int triples = pixoffset / 3;
250 int tripbytes = triples * 16;
251 int tripskip = pixoffset - triples * 3;
252 // we start within a 16-byte chunk |tripbytes| into the chunk. determine
253 // the number of bits.
254//fprintf(stderr, "pixoffset: %d next: %d tripbytes: %d tripskip: %d thisrow: %d\n", pixoffset, nextpixel, tripbytes, tripskip, thisrow);
255 // the maximum number of pixels we can convert is the minimum of the
256 // pixels remaining in the target row, and the pixels left in the chunk.
257//fprintf(stderr, "inchunk: %d total: %d triples: %d\n", inchunk, totalpixels, triples);
258 int chomped = kitty_restore(c + tripbytes, tripskip, thisrow,
259 inchunk - triples * 3, auxvec + auxvecidx,
260 &state);
261 assert(chomped >= 0);
262 auxvecidx += chomped;
263 thisrow -= chomped;
264//fprintf(stderr, "POSTCHIMP CHOMP: %d pixoffset: %d next: %d tripbytes: %d tripskip: %d thisrow: %d\n", chomped, pixoffset, nextpixel, tripbytes, tripskip, thisrow);
265 if(thisrow == 0){
266//fprintf(stderr, "CLEARED ROW, TARGY: %d\n", targy - 1);
267 if(--targy == 0){
268 s->n->tam[s->dimx * ycell + xcell].state = state;
270 return 1;
271 }
272 thisrow = targx;
273//fprintf(stderr, "BUMP IT: %d %d %d %d\n", nextpixel, s->pixx, targx, chomped);
274 nextpixel += s->pixx - targx + chomped;
275 }else{
276 nextpixel += chomped;
277 }
278 }
279 c += RGBA_MAXLEN * 4 * 4 / 3; // 4bpp * 4/3 for base64, 4096b per chunk
280 c += 8; // new chunk header
281 ++chunkedhandled;
282//fprintf(stderr, "LOOKING NOW AT %u [%s]\n", c - s->glyph, c);
283 while(*c != ';'){
284 ++c;
285 }
286 ++c;
287 }
288 return -1;
289}
assert(false)
#define RGBA_MAXLEN
Definition kitty.c:216
int parse_start
Definition sprite.h:153
sprixcell_e state
Definition sprite.h:127
Here is the call graph for this function:

◆ kitty_rebuild_animation()

int kitty_rebuild_animation ( sprixel s,
int  ycell,
int  xcell,
uint8_t *  auxvec 
)

Definition at line 972 of file kitty.c.

972 {
973 logdebug("rebuilding sprixel %u %d at %d/%d", s->id, s->invalidated, ycell, xcell);
974 if(init_sprixel_animation(s)){
975 return -1;
976 }
977 fbuf* f = &s->glyph;
978 const int cellpxy = ncplane_pile(s->n)->cellpxy;
979 const int cellpxx = ncplane_pile(s->n)->cellpxx;
980 const int ystart = ycell * cellpxy;
981 const int xstart = xcell * cellpxx;
982 const int xlen = xstart + cellpxx > s->pixx ? s->pixx - xstart : cellpxx;
983 const int ylen = ystart + cellpxy > s->pixy ? s->pixy - ystart : cellpxy;
984 const int linesize = xlen * 4;
985 const int total = xlen * ylen;
986 const int tyx = xcell + ycell * s->dimx;
987 int chunks = (total + (RGBA_MAXLEN - 1)) / RGBA_MAXLEN;
988 int totalout = 0; // total pixels of payload out
989 int y = 0; // position within source image (pixels)
990 int x = 0;
991 int targetout = 0; // number of pixels expected out after this chunk
992//fprintf(stderr, "total: %d chunks = %d, s=%d,v=%d\n", total, chunks, lenx, leny);
993 // FIXME this ought be factored out and shared with write_kitty_data()
994 logdebug("placing %d/%d at %d/%d", ylen, xlen, ycell * cellpxy, xcell * cellpxx);
995 while(chunks--){
996 if(totalout == 0){
997 const int c = kitty_anim_auxvec_blitsource_p(s, auxvec) ? 2 : 1;
998 const int r = kitty_anim_auxvec_blitsource_p(s, auxvec) ? 1 : 2;
999 if(fbuf_printf(f, "\e_Ga=f,x=%d,y=%d,s=%d,v=%d,i=%d,X=1,c=%d,r=%d,%s;",
1000 xcell * cellpxx, ycell * cellpxy, xlen, ylen,
1001 s->id, c, r, chunks ? "m=1" : "q=2") < 0){
1002 return -1;
1003 }
1004 }else{
1005 if(fbuf_putn(f, "\x1b_G", 3) < 0){
1006 return -1;
1007 }
1008 if(!chunks){
1009 if(fbuf_putn(f, "q=2,", 4) < 0){
1010 return -1;
1011 }
1012 }
1013 if(fbuf_putn(f, "m=", 2) < 0){
1014 return -1;
1015 }
1016 if(fbuf_putint(f, chunks ? 1 : 0) < 0){
1017 return -1;
1018 }
1019 if(fbuf_putc(f, ';') != 1){
1020 return -1;
1021 }
1022 }
1023 if((targetout += RGBA_MAXLEN) > total){
1024 targetout = total;
1025 }
1026 while(totalout < targetout){
1027 int encodeable = targetout - totalout;
1028 if(encodeable > 3){
1029 encodeable = 3;
1030 }
1031 uint32_t source[3]; // we encode up to 3 pixels at a time
1032 bool wipe[3];
1033 for(int e = 0 ; e < encodeable ; ++e){
1034 if(x == xlen){
1035 x = 0;
1036 ++y;
1037 }
1038 const uint32_t* line = (const uint32_t*)(auxvec + linesize * y);
1039 source[e] = line[x];
1040//fprintf(stderr, "%u/%u/%u -> %c%c%c%c %u %u %u %u\n", r, g, b, b64[0], b64[1], b64[2], b64[3], b64[0], b64[1], b64[2], b64[3]);
1041//fprintf(stderr, "Tyx: %d y: %d (%d) * %d x: %d (%d) state %d %p\n", tyx, y, y / cdimy, cols, x, x / cdimx, tam[tyx].state, tam[tyx].auxvector);
1042 wipe[e] = 0;
1043 if(rgba_trans_p(source[e], 0)){
1044 if(x % cellpxx == 0 && y % cellpxy == 0){
1045 s->n->tam[tyx].state = SPRIXCELL_TRANSPARENT;
1046 }else if(s->n->tam[tyx].state == SPRIXCELL_OPAQUE_KITTY){
1047 s->n->tam[tyx].state = SPRIXCELL_MIXED_KITTY;
1048 }
1049 }else{
1050 if(x % cellpxx == 0 && y % cellpxy == 0){
1051 s->n->tam[tyx].state = SPRIXCELL_OPAQUE_KITTY;
1052 }else if(s->n->tam[tyx].state == SPRIXCELL_TRANSPARENT){
1053 s->n->tam[tyx].state = SPRIXCELL_MIXED_KITTY;
1054 }
1055 }
1056 ++x;
1057 }
1058 totalout += encodeable;
1059 char out[17];
1060 base64_rgba3(source, encodeable, out, wipe, 0);
1061 if(fbuf_puts(f, out) < 0){
1062 return -1;
1063 }
1064 }
1065 if(fbuf_putn(f, "\x1b\\", 2) < 0){
1066 return -1;
1067 }
1068 }
1069//fprintf(stderr, "EMERGED WITH TAM STATE %d\n", s->n->tam[tyx].state);
1071 return 0;
1072}
API int API int API int uint64_t uint64_t uint64_t uint64_t unsigned unsigned xlen
Definition direct.h:217
API int API int API int uint64_t uint64_t uint64_t uint64_t unsigned ylen
Definition direct.h:217
int r
Definition fbuf.h:226
Definition fbuf.h:25
static escape_e e
Definition termdesc.h:224

◆ kitty_rebuild_selfref()

int kitty_rebuild_selfref ( sprixel s,
int  ycell,
int  xcell,
uint8_t *  auxvec 
)

Definition at line 950 of file kitty.c.

950 {
951 if(init_sprixel_animation(s)){
952 return -1;
953 }
954 fbuf* f = &s->glyph;
955 const int cellpxy = ncplane_pile(s->n)->cellpxy;
956 const int cellpxx = ncplane_pile(s->n)->cellpxx;
957 const int ystart = ycell * cellpxy;
958 const int xstart = xcell * cellpxx;
959 const int xlen = xstart + cellpxx > s->pixx ? s->pixx - xstart : cellpxx;
960 const int ylen = ystart + cellpxy > s->pixy ? s->pixy - ystart : cellpxy;
961 logdebug("rematerializing %u at %d/%d (%dx%d)", s->id, ycell, xcell, ylen, xlen);
962 fbuf_printf(f, "\e_Ga=c,x=%d,y=%d,X=%d,Y=%d,w=%d,h=%d,i=%d,r=1,c=2,q=2;\x1b\\",
963 xcell * cellpxx, ycell * cellpxy,
964 xcell * cellpxx, ycell * cellpxy,
965 xlen, ylen, s->id);
966 const int tyx = xcell + ycell * s->dimx;
967 memcpy(&s->n->tam[tyx].state, auxvec, sizeof(s->n->tam[tyx].state));
969 return 0;
970}

◆ kitty_remove()

int kitty_remove ( int  id,
fbuf f 
)

Definition at line 1130 of file kitty.c.

1130 {
1131 loginfo("removing graphic %u", id);
1132 if(fbuf_printf(f, "\e_Ga=d,d=I,i=%d\e\\", id) < 0){
1133 return -1;
1134 }
1135 return 0;
1136}

◆ kitty_scrub()

int kitty_scrub ( const struct ncpile p,
sprixel s 
)

◆ kitty_trans_auxvec()

uint8_t * kitty_trans_auxvec ( const struct ncpile p)

◆ kitty_wipe()

int kitty_wipe ( sprixel s,
int  ycell,
int  xcell 
)

Definition at line 448 of file kitty.c.

448 {
449//fprintf(stderr, "NEW WIPE %d %d/%d\n", s->id, ycell, xcell);
450 uint8_t* auxvec = kitty_auxiliary_vector(s);
451 if(auxvec == NULL){
452 return -1;
453 }
454 const int totalpixels = s->pixy * s->pixx;
455 const int xpixels = ncplane_pile(s->n)->cellpxx;
456 const int ypixels = ncplane_pile(s->n)->cellpxy;
457 // if the cell is on the right or bottom borders, it might only be partially
458 // filled by actual graphic data, and we need to cap our target area.
459 int targx = xpixels;
460 if((xcell + 1) * xpixels > s->pixx){
461 targx = s->pixx - xcell * xpixels;
462 }
463 int targy = ypixels;
464 if((ycell + 1) * ypixels > s->pixy){
465 targy = s->pixy - ycell * ypixels;
466 }
467 char* c = (char*)s->glyph.buf + s->parse_start;
468//fprintf(stderr, "TARGET AREA: %d x %d @ %dx%d of %d/%d (%d/%d) len %zu\n", targy, targx, ycell, xcell, s->dimy, s->dimx, s->pixy, s->pixx, strlen(c));
469 // every pixel was 4 source bytes, 32 bits, 6.33 base64 bytes. every 3 input pixels is
470 // 12 bytes (96 bits), an even 16 base64 bytes. there is chunking to worry about. there
471 // are up to 768 pixels in a chunk.
472 int nextpixel = (s->pixx * ycell * ypixels) + (xpixels * xcell);
473 int thisrow = targx;
474 int chunkedhandled = 0;
475 const int chunks = totalpixels / RGBA_MAXLEN + !!(totalpixels % RGBA_MAXLEN);
476 int auxvecidx = 0;
477 while(targy && chunkedhandled < chunks){ // need to null out |targy| rows of |targx| pixels, track with |thisrow|
478//fprintf(stderr, "PLUCKING FROM [%s]\n", c);
479 int inchunk = totalpixels - chunkedhandled * RGBA_MAXLEN;
480 if(inchunk > RGBA_MAXLEN){
481 inchunk = RGBA_MAXLEN;
482 }
483 const int curpixel = chunkedhandled * RGBA_MAXLEN;
484 // a full chunk is 4096 + 2 + 7 (5005)
485 while(nextpixel - curpixel < RGBA_MAXLEN && thisrow){
486 // our next pixel is within this chunk. find the pixel offset of the
487 // first pixel (within the chunk).
488 int pixoffset = nextpixel - curpixel;
489 int triples = pixoffset / 3;
490 int tripbytes = triples * 16;
491 // we start within a 16-byte chunk |tripbytes| into the chunk. determine
492 // the number of bits.
493 int tripskip = pixoffset - triples * 3;
494//fprintf(stderr, "pixoffset: %d next: %d tripbytes: %d tripskip: %d thisrow: %d\n", pixoffset, nextpixel, tripbytes, tripskip, thisrow);
495 // the maximum number of pixels we can convert is the minimum of the
496 // pixels remaining in the target row, and the pixels left in the chunk.
497//fprintf(stderr, "inchunk: %d total: %d triples: %d\n", inchunk, totalpixels, triples);
498//fprintf(stderr, "PRECHOMP: [%.16s]\n", c + tripbytes);
499 int chomped = kitty_null(c + tripbytes, tripskip, thisrow,
500 inchunk - triples * 3, auxvec + auxvecidx);
501//fprintf(stderr, "POSTCHOMP: [%.16s]\n", c + tripbytes);
502 assert(chomped >= 0);
503 auxvecidx += chomped;
504 assert(auxvecidx <= ypixels * xpixels);
505 thisrow -= chomped;
506//fprintf(stderr, "POSTCHIMP CHOMP: %d pixoffset: %d next: %d tripbytes: %d tripskip: %d thisrow: %d\n", chomped, pixoffset, nextpixel, tripbytes, tripskip, thisrow);
507 if(thisrow == 0){
508//fprintf(stderr, "CLEARED ROW, TARGY: %d\n", targy - 1);
509 if(--targy == 0){
510 s->n->tam[s->dimx * ycell + xcell].auxvector = auxvec;
512 return 1;
513 }
514 thisrow = targx;
515//fprintf(stderr, "BUMP IT: %d %d %d %d\n", nextpixel, s->pixx, targx, chomped);
516 nextpixel += s->pixx - targx + chomped;
517 }else{
518 nextpixel += chomped;
519 }
520 }
521 c += RGBA_MAXLEN * 4 * 4 / 3; // 4bpp * 4/3 for base64, 4096b per chunk
522 c += 8; // new chunk header
523 ++chunkedhandled;
524//fprintf(stderr, "LOOKING NOW AT %u [%s]\n", c - s->glyph, c);
525 while(*c != ';'){
526 ++c;
527 }
528 ++c;
529 }
530 free(auxvec);
531 return -1;
532}
free(duplicated)
Here is the call graph for this function:

◆ kitty_wipe_animation()

int kitty_wipe_animation ( sprixel s,
int  ycell,
int  xcell 
)

Definition at line 394 of file kitty.c.

394 {
395 logdebug("wiping sprixel %u at %d/%d", s->id, ycell, xcell);
396 if(init_sprixel_animation(s)){
397 return -1;
398 }
399 fbuf* f = &s->glyph;
400 if(kitty_blit_wipe_selfref(s, f, ycell, xcell) < 0){
401 return -1;
402 }
403 int tamidx = ycell * s->dimx + xcell;
404 uint8_t* auxvec = s->n->tam[tamidx].auxvector;
405 auxvec[ncplane_pile(s->n)->cellpxx * ncplane_pile(s->n)->cellpxy * 4] = 0;
407 return 1;
408}

◆ kitty_wipe_selfref()

int kitty_wipe_selfref ( sprixel s,
int  ycell,
int  xcell 
)

Definition at line 410 of file kitty.c.

410 {
411 if(init_sprixel_animation(s)){
412 return -1;
413 }
414 const int tyx = xcell + ycell * s->dimx;
415 int state = s->n->tam[tyx].state;
416 void* auxvec = s->n->tam[tyx].auxvector;
417 logdebug("wiping sprixel %u at %d/%d auxvec: %p state: %d", s->id, ycell, xcell, auxvec, state);
418 fbuf* f = &s->glyph;
419 if(kitty_blit_wipe_selfref(s, f, ycell, xcell)){
420 return -1;
421 }
423 memcpy(auxvec, &state, sizeof(state));
424 return 1;
425}

◆ sixel_blit()

int sixel_blit ( struct ncplane nc,
int  linesize,
const void *  data,
int  leny,
int  lenx,
const struct blitterargs bargs 
)

◆ sixel_cleanup()

void sixel_cleanup ( struct tinfo ti)

Definition at line 1764 of file sixel.c.

1764 {
1765 sixel_engine* sengine = ti->sixelengine;
1766 const unsigned tids = POPULATION;
1767 pthread_mutex_lock(&sengine->lock);
1768 sengine->done = 1;
1769 pthread_mutex_unlock(&sengine->lock);
1770 pthread_cond_broadcast(&sengine->cond);
1771 loginfo("joining %u sixel thread%s", tids, tids == 1 ? "" : "s");
1772 for(unsigned t = 0 ; t < tids ; ++t){
1773 pthread_join(sengine->tids[t], NULL);
1774 }
1775 pthread_mutex_destroy(&sengine->lock);
1776 pthread_cond_destroy(&sengine->cond);
1777 free(sengine);
1778 loginfo("reaped sixel engine");
1779 ti->sixelengine = NULL;
1780 // no way to know what the state was before; we ought use XTSAVE/XTRESTORE
1781}
#define POPULATION
Definition sixel.c:10
pthread_cond_t cond
Definition sixel.c:124
pthread_mutex_t lock
Definition sixel.c:123
bool done
Definition sixel.c:127
pthread_t tids[POPULATION]
Definition sixel.c:126
void * sixelengine
Definition termdesc.h:175
Here is the call graph for this function:

◆ sixel_draw()

int sixel_draw ( const struct tinfo ti,
const struct ncpile p,
sprixel s,
fbuf f,
int  yoff,
int  xoff 
)

◆ sixel_init()

int sixel_init ( struct tinfo ti,
int  fd 
)

Definition at line 1602 of file sixel.c.

1602 {
1603 return sixel_init_core(ti, "\e[?8452h", fd);
1604}

◆ sixel_init_forcesdm()

int sixel_init_forcesdm ( struct tinfo ti,
int  fd 
)

Definition at line 1588 of file sixel.c.

1588 {
1589 return sixel_init_core(ti, "\e[?80l\e[?8452h", fd);
1590}

◆ sixel_init_inverted()

int sixel_init_inverted ( struct tinfo ti,
int  fd 
)

Definition at line 1592 of file sixel.c.

1592 {
1593 // some terminals, at some versions, invert the sense of DECSDM. for those,
1594 // we must use 80h rather than the correct 80l. this grows out of a
1595 // misunderstanding in XTerm through patchlevel 368, which was widely
1596 // copied into other terminals.
1597 return sixel_init_core(ti, "\e[?80h\e[?8452h", fd);
1598}

◆ sixel_rebuild()

int sixel_rebuild ( sprixel s,
int  ycell,
int  xcell,
uint8_t *  auxvec 
)

Definition at line 1724 of file sixel.c.

1724 {
1725//fprintf(stderr, "REBUILDING %d/%d\n", ycell, xcell);
1726 if(auxvec == NULL){
1727 return -1;
1728 }
1729 const int cellpxy = ncplane_pile(s->n)->cellpxy;
1730 const int cellpxx = ncplane_pile(s->n)->cellpxx;
1731 sixelmap* smap = s->smap;
1732 const int startx = xcell * cellpxx;
1733 const int starty = ycell * cellpxy;
1734 int endx = ((xcell + 1) * cellpxx);
1735 if(endx >= s->pixx){
1736 endx = s->pixx;
1737 }
1738 int endy = ((ycell + 1) * cellpxy);
1739 if(endy >= s->pixy){
1740 endy = s->pixy;
1741 }
1742 const int startband = starty / 6;
1743 const int endband = (endy - 1) / 6;
1744//fprintf(stderr, "%d/%d start: %d/%d end: %d/%d bands: %d-%d\n", ycell, xcell, starty, startx, endy, endx, starty / 6, endy / 6);
1745 // walk through each color, and wipe the necessary sixels from each band
1746 int w = 0;
1747 for(int b = startband ; b <= endband ; ++b){
1748 w += restore_band(smap, b, startx, endx, starty, endy, s->pixx,
1749 cellpxy, cellpxx, auxvec);
1750 }
1751 s->wipes_outstanding = true;
1752 sprixcell_e newstate;
1753 if(w == cellpxx * cellpxy){
1754 newstate = SPRIXCELL_TRANSPARENT;
1755 }else if(w){
1756 newstate = SPRIXCELL_MIXED_SIXEL;
1757 }else{
1758 newstate = SPRIXCELL_OPAQUE_SIXEL;
1759 }
1760 s->n->tam[s->dimx * ycell + xcell].state = newstate;
1761 return 1;
1762}
bool wipes_outstanding
Definition sprite.h:158
struct sixelmap * smap
Definition sprite.h:157

◆ sixel_refresh()

void sixel_refresh ( const struct ncpile p,
sprixel s 
)

◆ sixel_scrub()

int sixel_scrub ( const struct ncpile p,
sprixel s 
)

◆ sixel_trans_auxvec()

uint8_t * sixel_trans_auxvec ( const struct ncpile p)

◆ sixel_wipe()

int sixel_wipe ( sprixel s,
int  ycell,
int  xcell 
)

Definition at line 655 of file sixel.c.

655 {
656//fprintf(stderr, "WIPING %d/%d\n", ycell, xcell);
657 uint8_t* auxvec = sixel_trans_auxvec(ncplane_pile(s->n));
658 if(auxvec == NULL){
659 return -1;
660 }
661 const int cellpxy = ncplane_pile(s->n)->cellpxy;
662 const int cellpxx = ncplane_pile(s->n)->cellpxx;
663 sixelmap* smap = s->smap;
664 const int startx = xcell * cellpxx;
665 const int starty = ycell * cellpxy;
666 int endx = ((xcell + 1) * cellpxx);
667 if(endx >= s->pixx){
668 endx = s->pixx;
669 }
670 int endy = ((ycell + 1) * cellpxy);
671 if(endy >= s->pixy){
672 endy = s->pixy;
673 }
674 const int startband = starty / 6;
675 const int endband = (endy - 1) / 6;
676//fprintf(stderr, "y/x: %d/%d bands: %d-%d start: %d/%d end: %d/%d\n", ycell, xcell, startband, endband - 1, starty, startx, endy, endx);
677 // walk through each color, and wipe the necessary sixels from each band
678 int w = 0;
679 for(int b = startband ; b <= endband ; ++b){
680 w += wipe_band(smap, b, startx, endx, starty, endy, s->pixx,
681 cellpxy, cellpxx, auxvec);
682 }
683 if(w){
684 s->wipes_outstanding = true;
685 }
686 change_p2(s->glyph.buf, SIXEL_P2_TRANS);
687 assert(NULL == s->n->tam[s->dimx * ycell + xcell].auxvector);
688 s->n->tam[s->dimx * ycell + xcell].auxvector = auxvec;
689 // FIXME this invalidation ought not be necessary, since we're simply
690 // wiping, and thus a glyph is going to be printed over whatever we've
691 // just destroyed. in alacritty, however, this isn't sufficient to knock
692 // out a graphic; we need repaint with the transparency.
693 // see https://github.com/dankamongmen/notcurses/issues/2142
694 int absx, absy;
695 ncplane_abs_yx(s->n, &absy, &absx);
696 sprixel_invalidate(s, absy, absx);
697 return 0;
698}
void sprixel_invalidate(sprixel *s, int y, int x)
Definition sprite.c:103
void ncplane_abs_yx(const ncplane *n, int *RESTRICT y, int *RESTRICT x)
Definition notcurses.c:2642
uint8_t * sixel_trans_auxvec(const ncpile *p)
Definition sixel.c:1786
@ SIXEL_P2_TRANS
Definition sixel.c:57
Here is the call graph for this function:

◆ sprite_init()

int sprite_init ( struct tinfo t,
int  fd 
)

Definition at line 214 of file sprite.c.

214 {
215 struct timeval tv;
216 gettimeofday(&tv, NULL);
217 int stir = (tv.tv_sec >> 3) ^ tv.tv_usec;
218 sprixelid_nonce = (rand() ^ stir) % 0xffffffu;
219 if(t->pixel_init == NULL){
220 return 0;
221 }
222 return t->pixel_init(t, fd);
223}
int(* pixel_init)(struct tinfo *ti, int fd)
Definition termdesc.h:146

◆ sprixel_load()

int sprixel_load ( sprixel spx,
fbuf f,
unsigned  pixy,
unsigned  pixx,
int  parse_start,
sprixel_e  state 
)

Definition at line 154 of file sprite.c.

155 {
156 assert(spx->n);
157 if(&spx->glyph != f){
158 fbuf_free(&spx->glyph);
159 memcpy(&spx->glyph, f, sizeof(*f));
160 }
161 spx->invalidated = state;
162 spx->pixx = pixx;
163 spx->pixy = pixy;
164 spx->parse_start = parse_start;
165 return 0;
166}
Here is the call graph for this function:

◆ sprixel_rescale()

int sprixel_rescale ( sprixel spx,
unsigned  ncellpixy,
unsigned  ncellpixx 
)

Definition at line 225 of file sprite.c.

225 {
226 assert(spx->n);
227 loginfo("rescaling -> %ux%u", ncellpxy, ncellpxx);
228 // FIXME need adjust for sixel (scale_height)
229 int nrows = (spx->pixy + (ncellpxy - 1)) / ncellpxy;
230 int ncols = (spx->pixx + (ncellpxx - 1)) / ncellpxx;
231 tament* ntam = create_tam(nrows, ncols);
232 if(ntam == NULL){
233 return -1;
234 }
235 for(unsigned y = 0 ; y < spx->dimy ; ++y){
236 for(unsigned x = 0 ; x < spx->dimx ; ++x){
237 sprite_rebuild(ncplane_notcurses(spx->n), spx, y, x);
238 }
239 }
240 ncplane* ncopy = spx->n;
241 destroy_tam(spx->n);
242 // spx->n->tam has been reset, so it will not be resized herein
243 ncplane_resize_simple(spx->n, nrows, ncols);
244 spx->n = ncopy;
245 spx->n->sprite = spx;
246 spx->n->tam = ntam;
247 spx->dimy = nrows;
248 spx->dimx = ncols;
249 return 0;
250}
sprixel * sprite
Definition internal.h:105
unsigned dimy
Definition sprite.h:146
Here is the call graph for this function:
Here is the caller graph for this function: