|
|
|
@ -366,18 +366,6 @@ change_p2(char* sixel, sixel_p2_e value){
|
|
|
|
|
sixel[4] = value + '0';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// one for each color in the band we're building. |rle| tracks the number of
|
|
|
|
|
// consecutive unwritten instances of the current non-0 rep, which is itself
|
|
|
|
|
// tracked in |rep|. |wrote| tracks the number of sixels written out for this
|
|
|
|
|
// color. whenever we get a new rep (this only happens for non-zero reps),
|
|
|
|
|
// we must write any old rle rep, plus any zero-reps since then.
|
|
|
|
|
struct band_extender {
|
|
|
|
|
int length; // current length of the vector
|
|
|
|
|
int rle; // current rep count of non-zero sixel for this color
|
|
|
|
|
int wrote; // number of sixels we've written out
|
|
|
|
|
int rep; // representation, 0..63
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
|
write_rle(char* vec, int* voff, int rle, int rep){
|
|
|
|
|
if(rle > 2){
|
|
|
|
@ -388,17 +376,30 @@ write_rle(char* vec, int* voff, int rle, int rep){
|
|
|
|
|
if(rle){
|
|
|
|
|
vec[(*voff)++] = rep;
|
|
|
|
|
}
|
|
|
|
|
vec[*voff] = '\0';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// one for each color in the band we're building. |rle| tracks the number of
|
|
|
|
|
// consecutive unwritten instances of the current non-0 rep, which is itself
|
|
|
|
|
// tracked in |rep|. |wrote| tracks the number of sixels written out for this
|
|
|
|
|
// color. whenever we get a new rep (this only happens for non-zero reps),
|
|
|
|
|
// we must write any old rle rep, plus any zero-reps since then.
|
|
|
|
|
struct band_extender {
|
|
|
|
|
int length; // current length of the vector
|
|
|
|
|
int rle; // current rep count of non-zero sixel for this color
|
|
|
|
|
int wrote; // number of sixels we've written out
|
|
|
|
|
int rep; // representation, 0..63
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// add the supplied rle section to the appropriate vector, which might
|
|
|
|
|
// need to be created. we are writing out [bes->wrote, curx) (i.e. curx
|
|
|
|
|
// ought *not* describe the |bes| element, and ought equal |dimx| when
|
|
|
|
|
// finalizing the band). caller must update bes->wrote afterwards!
|
|
|
|
|
static inline char*
|
|
|
|
|
sixelband_extend(char* vec, struct band_extender* bes, int dimx, int curx){
|
|
|
|
|
assert(dimx >= rle);
|
|
|
|
|
assert(dimx >= bes->rle);
|
|
|
|
|
assert(0 <= bes->rle);
|
|
|
|
|
assert(0 < bes->rep);
|
|
|
|
|
assert(0 <= bes->rep);
|
|
|
|
|
assert(64 > bes->rep);
|
|
|
|
|
if(vec == NULL){
|
|
|
|
|
// FIXME for now we make it as big as it could possibly need to be. ps,
|
|
|
|
@ -413,23 +414,33 @@ sixelband_extend(char* vec, struct band_extender* bes, int dimx, int curx){
|
|
|
|
|
write_rle(vec, &bes->length, bes->rle, bes->rep + 63);
|
|
|
|
|
int clearlen = curx - (bes->rle + bes->wrote);
|
|
|
|
|
write_rle(vec, &bes->length, clearlen, '?');
|
|
|
|
|
vec[bes->length] = '\0';
|
|
|
|
|
return vec;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// wipe the color within this band from startx to endx, from starty to
|
|
|
|
|
// endy (0-offset in the band). returns the number of pixels actually wiped.
|
|
|
|
|
// the sixel |rep| is being wiped. the active pixels need be written to the
|
|
|
|
|
// |auxvec|, which is (|ey| - |sy| + 1) rows of (|ex| - |sx| + 1) columns.
|
|
|
|
|
// we are wiping the sixel |rep|, changing it to |mask|.
|
|
|
|
|
static inline void
|
|
|
|
|
write_auxvec(uint8_t* auxvec, int color, int x, int len, int sx, int ex,
|
|
|
|
|
int sy, int ey, char rep, char mask){
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// wipe the color within this band from startx to endx - 1, from starty to
|
|
|
|
|
// endy - 1 (0-offset in the band, a cell-sized region), writing out the
|
|
|
|
|
// auxvec. mask is the allowable sixel, y-wise. returns a positive number if
|
|
|
|
|
// pixels were wiped.
|
|
|
|
|
static inline int
|
|
|
|
|
wipe_color(sixelband* b, int color, int startx, int endx,
|
|
|
|
|
char mask, int dimx, int cellpixy, int cellpixx,
|
|
|
|
|
uint8_t* auxvec){
|
|
|
|
|
int starty, int endy, char mask, int dimx, uint8_t* auxvec){
|
|
|
|
|
const char* vec = b->vecs[color];
|
|
|
|
|
if(vec == NULL){
|
|
|
|
|
return 0; // no work to be done here
|
|
|
|
|
}
|
|
|
|
|
int wiped = 0;
|
|
|
|
|
/*
|
|
|
|
|
char* newvec = NULL;
|
|
|
|
|
char* newvec = malloc(dimx);
|
|
|
|
|
if(newvec == NULL){
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
//fprintf(stderr, "sixels: %d color: %d B: %d-%d Y: %d-%d X: %d-%d coff: %d\n", smap->sixelcount, color, sband, eband, starty, endy, startx, endx, coff);
|
|
|
|
|
//fprintf(stderr, "s/e: %d/%d mask: %02x\n", starty, endy, mask);
|
|
|
|
|
// we decode the color within the sixelband, and rebuild it without the
|
|
|
|
@ -440,10 +451,7 @@ wipe_color(sixelband* b, int color, int startx, int endx,
|
|
|
|
|
// otherwise, starting at startx, it can be affected. once x > endx, we
|
|
|
|
|
// are done, and can copy the remaining elements blindly.
|
|
|
|
|
int x = 0;
|
|
|
|
|
struct band_extender bes = {
|
|
|
|
|
.length = 0, // index into newvec
|
|
|
|
|
.next = 0,
|
|
|
|
|
};
|
|
|
|
|
int voff = 0;
|
|
|
|
|
while(*vec){
|
|
|
|
|
if(isdigit(*vec)){
|
|
|
|
|
rle *= 10;
|
|
|
|
@ -454,45 +462,58 @@ wipe_color(sixelband* b, int color, int startx, int endx,
|
|
|
|
|
if(rle == 0){
|
|
|
|
|
rle = 1;
|
|
|
|
|
}
|
|
|
|
|
char rep = *vec - 63;
|
|
|
|
|
x += rle - 1;
|
|
|
|
|
char rep = *vec;
|
|
|
|
|
char masked = ((rep - 63) & mask) + 63;
|
|
|
|
|
if(x + rle < startx){ // not wiped material; reproduce as-is
|
|
|
|
|
newvec = sixelband_extend(newvec, &bes, dimx, rep, rle, x);
|
|
|
|
|
}else if((rep & mask) == rep){ // not changed by wipe
|
|
|
|
|
newvec = sixelband_extend(newvec, &bes, dimx, rep, rle, x);
|
|
|
|
|
write_rle(newvec, &voff, rle, rep);
|
|
|
|
|
x += rle;
|
|
|
|
|
}else if(masked == rep){ // not changed by wipe; reproduce as-is
|
|
|
|
|
write_rle(newvec, &voff, rle, rep);
|
|
|
|
|
x += rle;
|
|
|
|
|
}else{ // changed by wipe; might have to break it up
|
|
|
|
|
wiped = 1;
|
|
|
|
|
if(x < startx){
|
|
|
|
|
newvec = sixelband_extend(newvec, &bes, dimx, rep, startx - x, x);
|
|
|
|
|
x += startx - x;
|
|
|
|
|
write_rle(newvec, &voff, startx - x, rep);
|
|
|
|
|
rle -= startx - x;
|
|
|
|
|
x = startx;
|
|
|
|
|
}
|
|
|
|
|
if(x + rle >= endx){
|
|
|
|
|
// FIXME this new rep might equal the next rep, in which case we ought combine
|
|
|
|
|
write_rle(newvec, &voff, endx - x, masked);
|
|
|
|
|
write_auxvec(auxvec, color, x, endx - x, startx, endx, starty, endy, rep, mask);
|
|
|
|
|
rle -= endx - x;
|
|
|
|
|
x = endx;
|
|
|
|
|
}else{
|
|
|
|
|
write_rle(newvec, &voff, rle, masked);
|
|
|
|
|
write_auxvec(auxvec, color, x, rle, startx, endx, starty, endy, rep, mask);
|
|
|
|
|
x += rle;
|
|
|
|
|
rle = 0;
|
|
|
|
|
}
|
|
|
|
|
// FIXME this new rep might equal the next rep, in which case we ought combine
|
|
|
|
|
newvec = sixelband_extend(newvec, &bes, dimx, rep & mask, endx - x, x);
|
|
|
|
|
x += startx - x;
|
|
|
|
|
rle -= startx - x;
|
|
|
|
|
wiped += startx - x;
|
|
|
|
|
if(rle){
|
|
|
|
|
newvec = sixelband_extend(newvec, &bes, dimx, rep, rle, x);
|
|
|
|
|
write_rle(newvec, &voff, rle, rep);
|
|
|
|
|
x += rle;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(newvec == NULL){
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
rle = 0;
|
|
|
|
|
}
|
|
|
|
|
++vec;
|
|
|
|
|
if(x > endx){
|
|
|
|
|
strcpy(newvec + bes.length, vec); // there is always room
|
|
|
|
|
strcpy(newvec + voff, vec); // there is always room
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
free(b->vecs[color]);
|
|
|
|
|
// FIXME check for empty vector; free such, and assign NULL
|
|
|
|
|
if(voff == 0){
|
|
|
|
|
// FIXME check for other null vectors; free such, and assign NULL
|
|
|
|
|
free(newvec);
|
|
|
|
|
newvec = NULL;
|
|
|
|
|
}
|
|
|
|
|
b->vecs[color] = newvec;
|
|
|
|
|
*/
|
|
|
|
|
//fprintf(stderr, "WIPED %d y [%d..%d) x [%d..%d) mask: %d\n", color, starty, endy, startx, endx, mask);
|
|
|
|
|
return wiped;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// wipe the band from startx to endx, from starty to endy. returns the
|
|
|
|
|
// wipe the band from startx to endx - 1, from starty to endy - 1. returns the
|
|
|
|
|
// number of pixels actually wiped.
|
|
|
|
|
static inline int
|
|
|
|
|
wipe_band(sixelmap* smap, int band, int startx, int endx,
|
|
|
|
@ -500,22 +521,21 @@ wipe_band(sixelmap* smap, int band, int startx, int endx,
|
|
|
|
|
uint8_t* auxvec){
|
|
|
|
|
int wiped = 0;
|
|
|
|
|
// get 0-offset start and end row bounds for our band.
|
|
|
|
|
const int sy = starty - band * 6;
|
|
|
|
|
const int ey = ((band + 1) * 6 > endy ? endy - band * 6 : (band + 1) * 6);
|
|
|
|
|
const int sy = band * 6 < starty ? starty - band * 6 : 0;
|
|
|
|
|
const int ey = (band + 1) * 6 > endy ? 6 - ((band + 1) * 6 - endy) : 6;
|
|
|
|
|
// we've got a mask that we'll AND with the decoded sixels; set it to
|
|
|
|
|
// 0 wherever we're wiping.
|
|
|
|
|
unsigned char mask = 0;
|
|
|
|
|
unsigned char mask = 63;
|
|
|
|
|
// knock out a bit for each row we're wiping within the band
|
|
|
|
|
for(int i = 0 ; i < 6 ; ++i){
|
|
|
|
|
if(i < sy || i > ey){
|
|
|
|
|
mask |= ~(1u << i);
|
|
|
|
|
if(i >= sy && i <= ey){
|
|
|
|
|
mask &= ~(1u << i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
sixelband* b = &smap->bands[band];
|
|
|
|
|
// offset into map->data where our color starts
|
|
|
|
|
for(int i = 0 ; i < b->size ; ++i){
|
|
|
|
|
wiped += wipe_color(b, i, startx, endx, mask, dimx,
|
|
|
|
|
cellpixy, cellpixx, auxvec);
|
|
|
|
|
wiped += wipe_color(b, i, startx, endx, starty, endy, mask, dimx, auxvec);
|
|
|
|
|
}
|
|
|
|
|
return wiped;
|
|
|
|
|
}
|
|
|
|
@ -535,20 +555,20 @@ int sixel_wipe(sprixel* s, int ycell, int xcell){
|
|
|
|
|
sixelmap* smap = s->smap;
|
|
|
|
|
const int startx = xcell * cellpxx;
|
|
|
|
|
const int starty = ycell * cellpxy;
|
|
|
|
|
int endx = ((xcell + 1) * cellpxx) - 1;
|
|
|
|
|
int endx = ((xcell + 1) * cellpxx);
|
|
|
|
|
if(endx >= s->pixx){
|
|
|
|
|
endx = s->pixx - 1;
|
|
|
|
|
endx = s->pixx;
|
|
|
|
|
}
|
|
|
|
|
int endy = ((ycell + 1) * cellpxy) - 1;
|
|
|
|
|
int endy = ((ycell + 1) * cellpxy);
|
|
|
|
|
if(endy >= s->pixy){
|
|
|
|
|
endy = s->pixy - 1;
|
|
|
|
|
endy = s->pixy;
|
|
|
|
|
}
|
|
|
|
|
const int startband = starty / 6;
|
|
|
|
|
const int endband = endy / 6;
|
|
|
|
|
//fprintf(stderr, "y/x: %d/%d start: %d/%d end: %d/%d\n", ycell, xcell, starty, startx, endy, endx);
|
|
|
|
|
// walk through each color, and wipe the necessary sixels from each band
|
|
|
|
|
int w = 0;
|
|
|
|
|
for(int b = startband ; b <= endband ; ++b){
|
|
|
|
|
for(int b = startband ; b < endband ; ++b){
|
|
|
|
|
w += wipe_band(smap, b, startx, endx, starty, endy, s->pixx,
|
|
|
|
|
cellpxy, cellpxx, auxvec);
|
|
|
|
|
}
|
|
|
|
@ -1456,8 +1476,6 @@ int sixel_init(int fd){
|
|
|
|
|
// just like wiping. this is necessary due to the complex nature of
|
|
|
|
|
// modifying a Sixel -- we want to do them all in one batch.
|
|
|
|
|
int sixel_rebuild(sprixel* s, int ycell, int xcell, uint8_t* auxvec){
|
|
|
|
|
// FIXME
|
|
|
|
|
/*
|
|
|
|
|
s->wipes_outstanding = true;
|
|
|
|
|
sixelmap* smap = s->smap;
|
|
|
|
|
const int cellpxx = ncplane_pile(s->n)->cellpxx;
|
|
|
|
@ -1474,6 +1492,7 @@ int sixel_rebuild(sprixel* s, int ycell, int xcell, uint8_t* auxvec){
|
|
|
|
|
}
|
|
|
|
|
int transparent = 0;
|
|
|
|
|
//fprintf(stderr, "%d/%d start: %d/%d end: %d/%d bands: %d-%d\n", ycell, xcell, starty, startx, endy, endx, starty / 6, endy / 6);
|
|
|
|
|
/* FIXME
|
|
|
|
|
for(int x = startx ; x <= endx ; ++x){
|
|
|
|
|
for(int y = starty ; y <= endy ; ++y){
|
|
|
|
|
int auxvecidx = (y - starty) * cellpxx + (x - startx);
|
|
|
|
@ -1491,6 +1510,7 @@ int sixel_rebuild(sprixel* s, int ycell, int xcell, uint8_t* auxvec){
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
sprixcell_e newstate;
|
|
|
|
|
if(transparent == cellpxx * cellpxy){
|
|
|
|
|
newstate = SPRIXCELL_TRANSPARENT;
|
|
|
|
@ -1500,7 +1520,6 @@ int sixel_rebuild(sprixel* s, int ycell, int xcell, uint8_t* auxvec){
|
|
|
|
|
newstate = SPRIXCELL_OPAQUE_SIXEL;
|
|
|
|
|
}
|
|
|
|
|
s->n->tam[s->dimx * ycell + xcell].state = newstate;
|
|
|
|
|
*/
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|