[visual] pipe transcolor through, use it everywhere #1518

pull/1521/head
nick black 3 years ago committed by Nick Black
parent 0c566cd74a
commit bac7d634d9

@ -105,6 +105,7 @@ impl NcVisualOptions {
lenx: NcDim,
blitter: NcBlitter,
flags: u64,
transcolor: u32,
) -> Self {
Self {
// provided plane
@ -123,6 +124,7 @@ impl NcVisualOptions {
blitter,
// bitmask over NCVISUAL_OPTION_*
flags,
transcolor,
}
}
@ -135,6 +137,7 @@ impl NcVisualOptions {
lenx: NcDim,
blitter: NcBlitter,
flags: u64,
transcolor: u32,
) -> Self {
Self {
n: null_mut(),
@ -152,6 +155,7 @@ impl NcVisualOptions {
blitter,
// bitmask over NCVISUAL_OPTION_*
flags,
transcolor,
}
}

@ -31,6 +31,11 @@ trilerp(uint32_t c0, uint32_t c1, uint32_t c2){
return ret;
}
static inline unsigned
rgba_trans_q(const unsigned char* p, uint32_t transcolor){
return rgba_trans_p(*(const uint32_t*)p, transcolor);
}
// Retarded RGBA blitter (ASCII only).
static inline int
tria_blit_ascii(ncplane* nc, int linesize, const void* data,
@ -66,7 +71,7 @@ tria_blit_ascii(ncplane* nc, int linesize, const void* data,
cell_set_bg_alpha(c, CELL_ALPHA_BLEND);
cell_set_fg_alpha(c, CELL_ALPHA_BLEND);
}
if(rgba_trans_p(rgbbase_up[3])){
if(rgba_trans_q(rgbbase_up, bargs->transcolor)){
cell_set_bg_alpha(c, CELL_ALPHA_TRANSPARENT);
cell_set_fg_alpha(c, CELL_ALPHA_TRANSPARENT);
cell_set_blitquadrants(c, 0, 0, 0, 0);
@ -90,6 +95,7 @@ static inline int
tria_blit(ncplane* nc, int linesize, const void* data,
int leny, int lenx, const blitterargs* bargs){
//fprintf(stderr, "HALF %d X %d @ %d X %d (%p) place: %d X %d\n", leny, lenx, bargs->begy, bargs->begx, data, bargs->placey, bargs->placex);
uint32_t transcolor = bargs->transcolor;
const int bpp = 32;
int dimy, dimx, x, y;
int total = 0; // number of cells written
@ -124,11 +130,11 @@ tria_blit(ncplane* nc, int linesize, const void* data,
cell_set_bg_alpha(c, CELL_ALPHA_BLEND);
cell_set_fg_alpha(c, CELL_ALPHA_BLEND);
}
if(rgba_trans_p(rgbbase_up[3]) || rgba_trans_p(rgbbase_down[3])){
if(rgba_trans_q(rgbbase_up, transcolor) || rgba_trans_q(rgbbase_down, transcolor)){
cell_set_bg_alpha(c, CELL_ALPHA_TRANSPARENT);
if(rgba_trans_p(rgbbase_up[3]) && rgba_trans_p(rgbbase_down[3])){
if(rgba_trans_q(rgbbase_up, transcolor) && rgba_trans_q(rgbbase_down, transcolor)){
cell_set_fg_alpha(c, CELL_ALPHA_TRANSPARENT);
}else if(rgba_trans_p(rgbbase_up[3])){ // down has the color
}else if(rgba_trans_q(rgbbase_up, transcolor)){ // down has the color
if(pool_blit_direct(&nc->pool, c, "\u2584", strlen("\u2584"), 1) <= 0){
return -1;
}
@ -307,20 +313,21 @@ quadrant_solver(uint32_t tl, uint32_t tr, uint32_t bl, uint32_t br,
static inline const char*
qtrans_check(nccell* c, unsigned blendcolors,
const unsigned char* rgbbase_tl, const unsigned char* rgbbase_tr,
const unsigned char* rgbbase_bl, const unsigned char* rgbbase_br){
const unsigned char* rgbbase_bl, const unsigned char* rgbbase_br,
uint32_t transcolor){
uint32_t tl = 0, tr = 0, bl = 0, br = 0;
channel_set_rgb8(&tl, rgbbase_tl[0], rgbbase_tl[1], rgbbase_tl[2]);
channel_set_rgb8(&tr, rgbbase_tr[0], rgbbase_tr[1], rgbbase_tr[2]);
channel_set_rgb8(&bl, rgbbase_bl[0], rgbbase_bl[1], rgbbase_bl[2]);
channel_set_rgb8(&br, rgbbase_br[0], rgbbase_br[1], rgbbase_br[2]);
const char* egc = NULL;
if(rgba_trans_p(rgbbase_tl[3])){
if(rgba_trans_q(rgbbase_tl, transcolor)){
// top left is transparent
if(rgba_trans_p(rgbbase_tr[3])){
if(rgba_trans_q(rgbbase_tr, transcolor)){
// all of top is transparent
if(rgba_trans_p(rgbbase_bl[3])){
if(rgba_trans_q(rgbbase_bl, transcolor)){
// top and left are transparent
if(rgba_trans_p(rgbbase_br[3])){
if(rgba_trans_q(rgbbase_br, transcolor)){
// entirety is transparent, load with nul (but not NULL)
cell_set_fg_default(c);
cell_set_blitquadrants(c, 0, 0, 0, 0);
@ -331,7 +338,7 @@ qtrans_check(nccell* c, unsigned blendcolors,
egc = "";
}
}else{
if(rgba_trans_p(rgbbase_br[3])){
if(rgba_trans_q(rgbbase_br, transcolor)){
cell_set_fg_rgb8(c, rgbbase_bl[0], rgbbase_bl[1], rgbbase_bl[2]);
cell_set_blitquadrants(c, 0, 0, 1, 0);
egc = "";
@ -342,8 +349,8 @@ qtrans_check(nccell* c, unsigned blendcolors,
}
}
}else{ // top right is foreground, top left is transparent
if(rgba_trans_p(rgbbase_bl[3])){
if(rgba_trans_p(rgbbase_br[3])){ // entire bottom is transparent
if(rgba_trans_q(rgbbase_bl, transcolor)){
if(rgba_trans_q(rgbbase_br, transcolor)){ // entire bottom is transparent
cell_set_fg_rgb8(c, rgbbase_tr[0], rgbbase_tr[1], rgbbase_tr[2]);
cell_set_blitquadrants(c, 0, 1, 0, 0);
egc = "";
@ -352,7 +359,7 @@ qtrans_check(nccell* c, unsigned blendcolors,
cell_set_blitquadrants(c, 0, 1, 0, 1);
egc = "";
}
}else if(rgba_trans_p(rgbbase_br[3])){ // only br is transparent
}else if(rgba_trans_q(rgbbase_br, transcolor)){ // only br is transparent
cell_set_fchannel(c, lerp(tr, bl));
cell_set_blitquadrants(c, 0, 1, 1, 0);
egc = "";
@ -363,9 +370,9 @@ qtrans_check(nccell* c, unsigned blendcolors,
}
}
}else{ // topleft is foreground for all here
if(rgba_trans_p(rgbbase_tr[3])){
if(rgba_trans_p(rgbbase_bl[3])){
if(rgba_trans_p(rgbbase_br[3])){
if(rgba_trans_q(rgbbase_tr, transcolor)){
if(rgba_trans_q(rgbbase_bl, transcolor)){
if(rgba_trans_q(rgbbase_br, transcolor)){
cell_set_fg_rgb8(c, rgbbase_tl[0], rgbbase_tl[1], rgbbase_tl[2]);
cell_set_blitquadrants(c, 1, 0, 0, 0);
egc = "";
@ -374,7 +381,7 @@ qtrans_check(nccell* c, unsigned blendcolors,
cell_set_blitquadrants(c, 1, 0, 0, 1);
egc = "";
}
}else if(rgba_trans_p(rgbbase_br[3])){
}else if(rgba_trans_q(rgbbase_br, transcolor)){
cell_set_fchannel(c, lerp(tl, bl));
cell_set_blitquadrants(c, 1, 0, 1, 0);
egc = "";
@ -383,8 +390,8 @@ qtrans_check(nccell* c, unsigned blendcolors,
cell_set_blitquadrants(c, 1, 0, 1, 1);
egc = "";
}
}else if(rgba_trans_p(rgbbase_bl[3])){
if(rgba_trans_p(rgbbase_br[3])){ // entire bottom is transparent
}else if(rgba_trans_q(rgbbase_bl, transcolor)){
if(rgba_trans_q(rgbbase_br, transcolor)){ // entire bottom is transparent
cell_set_fchannel(c, lerp(tl, tr));
cell_set_blitquadrants(c, 1, 1, 0, 0);
egc = "";
@ -393,7 +400,7 @@ qtrans_check(nccell* c, unsigned blendcolors,
cell_set_blitquadrants(c, 1, 1, 0, 1);
egc = "";
}
}else if(rgba_trans_p(rgbbase_br[3])){ // only br is transparent
}else if(rgba_trans_q(rgbbase_br, transcolor)){ // only br is transparent
cell_set_fchannel(c, trilerp(tl, tr, bl));
cell_set_blitquadrants(c, 1, 1, 1, 0);
egc = "";
@ -454,7 +461,7 @@ quadrant_blit(ncplane* nc, int linesize, const void* data,
nccell* c = ncplane_cell_ref_yx(nc, y, x);
c->channels = 0;
c->stylemask = 0;
const char* egc = qtrans_check(c, bargs->u.cell.blendcolors, rgbbase_tl, rgbbase_tr, rgbbase_bl, rgbbase_br);
const char* egc = qtrans_check(c, bargs->u.cell.blendcolors, rgbbase_tl, rgbbase_tr, rgbbase_bl, rgbbase_br, bargs->transcolor);
if(egc == NULL){
uint32_t tl = 0, tr = 0, bl = 0, br = 0;
channel_set_rgb8(&tl, rgbbase_tl[0], rgbbase_tl[1], rgbbase_tl[2]);
@ -587,7 +594,8 @@ sex_solver(const uint32_t rgbas[6], uint64_t* channels, unsigned blendcolors){
}
static const char*
sex_trans_check(cell* c, const uint32_t rgbas[6], unsigned blendcolors){
sex_trans_check(cell* c, const uint32_t rgbas[6], unsigned blendcolors,
uint32_t transcolor){
// bit is *set* where sextant *is not*
// 32: bottom right 16: bottom left
// 8: middle right 4: middle left
@ -606,7 +614,7 @@ sex_trans_check(cell* c, const uint32_t rgbas[6], unsigned blendcolors){
unsigned r = 0, g = 0, b = 0;
unsigned div = 0;
for(unsigned mask = 0 ; mask < 6 ; ++mask){
if(rgba_trans_p(ncpixel_a(rgbas[mask]))){
if(rgba_trans_p(rgbas[mask], transcolor)){
transstring |= (1u << mask);
}else{
r += ncpixel_r(rgbas[mask]);
@ -684,7 +692,7 @@ sextant_blit(ncplane* nc, int linesize, const void* data,
nccell* c = ncplane_cell_ref_yx(nc, y, x);
c->channels = 0;
c->stylemask = 0;
const char* egc = sex_trans_check(c, rgbas, bargs->u.cell.blendcolors);
const char* egc = sex_trans_check(c, rgbas, bargs->u.cell.blendcolors, bargs->transcolor);
if(egc == NULL){ // no transparency; run a full solver
egc = sex_solver(rgbas, &c->channels, bargs->u.cell.blendcolors);
cell_set_blitquadrants(c, 1, 1, 1, 1);
@ -771,35 +779,35 @@ braille_blit(ncplane* nc, int linesize, const void* data,
}
}
// FIXME fold this into the above?
if(!rgba_trans_p(ncpixel_a(*rgbbase_l0))){
if(!rgba_trans_p(*rgbbase_l0, bargs->transcolor)){
egcidx |= 1u;
fold_rgb8(&r, &g, &b, rgbbase_l0, &blends);
}
if(!rgba_trans_p(ncpixel_a(*rgbbase_l1))){
if(!rgba_trans_p(*rgbbase_l1, bargs->transcolor)){
egcidx |= 2u;
fold_rgb8(&r, &g, &b, rgbbase_l1, &blends);
}
if(!rgba_trans_p(ncpixel_a(*rgbbase_l2))){
if(!rgba_trans_p(*rgbbase_l2, bargs->transcolor)){
egcidx |= 4u;
fold_rgb8(&r, &g, &b, rgbbase_l2, &blends);
}
if(!rgba_trans_p(ncpixel_a(*rgbbase_r0))){
if(!rgba_trans_p(*rgbbase_r0, bargs->transcolor)){
egcidx |= 8u;
fold_rgb8(&r, &g, &b, rgbbase_r0, &blends);
}
if(!rgba_trans_p(ncpixel_a(*rgbbase_r1))){
if(!rgba_trans_p(*rgbbase_r1, bargs->transcolor)){
egcidx |= 16u;
fold_rgb8(&r, &g, &b, rgbbase_r1, &blends);
}
if(!rgba_trans_p(ncpixel_a(*rgbbase_r2))){
if(!rgba_trans_p(*rgbbase_r2, bargs->transcolor)){
egcidx |= 32u;
fold_rgb8(&r, &g, &b, rgbbase_r2, &blends);
}
if(!rgba_trans_p(ncpixel_a(*rgbbase_l3))){
if(!rgba_trans_p(*rgbbase_l3, bargs->transcolor)){
egcidx |= 64u;
fold_rgb8(&r, &g, &b, rgbbase_l3, &blends);
}
if(!rgba_trans_p(ncpixel_a(*rgbbase_r3))){
if(!rgba_trans_p(*rgbbase_r3, bargs->transcolor)){
egcidx |= 128u;
fold_rgb8(&r, &g, &b, rgbbase_r3, &blends);
}

@ -1370,10 +1370,17 @@ int drop_signals(void* nc);
void ncvisual_printbanner(const notcurses* nc);
// alpha comes to us 0--255, but we have only 3 alpha values to map them to.
// settled on experimentally.
// settled on experimentally. if transcolor is non-zero, match its lower 24
// bits against the color, and treat a match as transparent.
static inline bool
rgba_trans_p(unsigned alpha){
if(alpha < 192){
rgba_trans_p(uint32_t p, uint32_t transcolor){
if(ncpixel_a(p) < 192){
return true;
}
if(transcolor &&
(ncpixel_r(p) == (transcolor & 0xff0000ull)) &&
(ncpixel_g(p) == (transcolor & 0xff00ull)) &&
(ncpixel_b(p) == (transcolor & 0xffull))){
return true;
}
return false;

@ -53,12 +53,13 @@ b64idx(char b64){
// is only 1 pixel available, those 32 bits become 8 bytes. (pcount + 1) * 4
// bytes are used, plus a null terminator. we thus must receive 17.
static inline void
base64_rgba3(const uint32_t* pixels, size_t pcount, char* b64, bool wipe[static 3]){
base64_rgba3(const uint32_t* pixels, size_t pcount, char* b64, bool wipe[static 3],
uint32_t transcolor){
uint32_t pixel = *pixels++;
unsigned r = ncpixel_r(pixel);
unsigned g = ncpixel_g(pixel);
unsigned b = ncpixel_b(pixel);
unsigned a = wipe[0] ? 0 : rgba_trans_p(ncpixel_a(pixel)) ? 0 : 255;
unsigned a = wipe[0] ? 0 : rgba_trans_p(pixel, transcolor) ? 0 : 255;
//fprintf(stderr, "WIPE: %d %d %d\n", wipe[0], wipe[1], wipe[2]);
b64[0] = b64subs[(r & 0xfc) >> 2];
b64[1] = b64subs[(r & 0x3 << 4) | ((g & 0xf0) >> 4)];
@ -77,7 +78,7 @@ base64_rgba3(const uint32_t* pixels, size_t pcount, char* b64, bool wipe[static
r = ncpixel_r(pixel);
g = ncpixel_g(pixel);
b = ncpixel_b(pixel);
a = wipe[1] ? 0 : rgba_trans_p(ncpixel_a(pixel)) ? 0 : 255;
a = wipe[1] ? 0 : rgba_trans_p(pixel, transcolor) ? 0 : 255;
b64[5] = b64subs[b64[5] | ((r & 0xf0) >> 4)];
b64[6] = b64subs[((r & 0xf) << 2) | ((g & 0xc0) >> 6u)];
b64[7] = b64subs[g & 0x3f];
@ -94,7 +95,7 @@ base64_rgba3(const uint32_t* pixels, size_t pcount, char* b64, bool wipe[static
r = ncpixel_r(pixel);
g = ncpixel_g(pixel);
b = ncpixel_b(pixel);
a = wipe[2] ? 0 : rgba_trans_p(ncpixel_a(pixel)) ? 0 : 255;
a = wipe[2] ? 0 : rgba_trans_p(pixel, transcolor) ? 0 : 255;
b64[10] = b64subs[b64[10] | ((r & 0xc0) >> 6)];
b64[11] = b64subs[r & 0x3f];
b64[12] = b64subs[(g & 0xfc) >> 2];
@ -227,7 +228,8 @@ int sprite_kitty_cell_wipe(const notcurses* nc, sprixel* s, int ycell, int xcell
static int
write_kitty_data(FILE* fp, int linesize, int leny, int lenx,
int cols, const uint32_t* data, int cdimy, int cdimx,
int sprixelid, sprixcell_e* tacache, int* parse_start){
int sprixelid, sprixcell_e* tacache, int* parse_start,
uint32_t transcolor){
if(linesize % sizeof(*data)){
fclose(fp);
return -1;
@ -271,7 +273,7 @@ write_kitty_data(FILE* fp, int linesize, int leny, int lenx,
wipe[e] = 1;
}else{
wipe[e] = 0;
if(rgba_trans_p(ncpixel_a(source[e]))){
if(rgba_trans_p(source[e], transcolor)){
tacache[tyx] = SPRIXCELL_CONTAINS_TRANS;
}
}
@ -279,7 +281,7 @@ write_kitty_data(FILE* fp, int linesize, int leny, int lenx,
}
totalout += encodeable;
char out[17];
base64_rgba3(source, encodeable, out, wipe);
base64_rgba3(source, encodeable, out, wipe, transcolor);
ncfputs(out, fp);
}
fprintf(fp, "\e\\");
@ -326,7 +328,8 @@ int kitty_blit(ncplane* n, int linesize, const void* data,
// closes fp on all paths
if(write_kitty_data(fp, linesize, leny, lenx, cols, data,
bargs->u.pixel.celldimy, bargs->u.pixel.celldimx,
bargs->u.pixel.spx->id, tacache, &parse_start)){
bargs->u.pixel.spx->id, tacache, &parse_start,
bargs->transcolor)){
if(!reuse){
free(tacache);
}

@ -139,7 +139,7 @@ update_deets(uint32_t rgb, cdetails* deets){
static inline int
extract_color_table(const uint32_t* data, int linesize, int begy, int begx, int cols,
int leny, int lenx, int cdimy, int cdimx, sixeltable* stab,
sprixcell_e* tacache){
sprixcell_e* tacache, uint32_t transcolor){
unsigned char mask = 0xc0;
int pos = 0; // pixel position
for(int visy = begy ; visy < (begy + leny) ; visy += 6){ // pixel row
@ -147,7 +147,7 @@ extract_color_table(const uint32_t* data, int linesize, int begy, int begx, int
for(int sy = visy ; sy < (begy + leny) && sy < visy + 6 ; ++sy){ // offset within sprixel
const uint32_t* rgb = (data + (linesize / 4 * sy) + visx);
int txyidx = (sy / cdimy) * cols + (visx / cdimx);
if(rgba_trans_p(ncpixel_a(*rgb))){
if(rgba_trans_p(ncpixel_a(*rgb), transcolor)){
if(tacache[txyidx] == SPRIXCELL_NORMAL){
tacache[txyidx] = SPRIXCELL_CONTAINS_TRANS;
}
@ -460,7 +460,7 @@ int sixel_blit(ncplane* n, int linesize, const void* data,
}
if(extract_color_table(data, linesize, bargs->begy, bargs->begx, cols, leny, lenx,
bargs->u.pixel.celldimy, bargs->u.pixel.celldimx,
&stable, tacache)){
&stable, tacache, bargs->transcolor)){
if(!reuse){
free(tacache);
}

Loading…
Cancel
Save