add kitty_blit, divert to it in kitty #1095

pull/1398/head
nick black 3 years ago committed by Nick Black
parent bc84987af5
commit 4d5fd3c465

@ -826,7 +826,7 @@ braille_blit(ncplane* nc, int placey, int placex, int linesize,
// NCBLIT_DEFAULT is not included, as it has no defined properties. It ought // NCBLIT_DEFAULT is not included, as it has no defined properties. It ought
// be replaced with some real blitter implementation by the calling widget. // be replaced with some real blitter implementation by the calling widget.
static const struct blitset notcurses_blitters[] = { static struct blitset notcurses_blitters[] = {
{ .geom = NCBLIT_8x1, .width = 1, .height = 8, .egcs = L" ▁▂▃▄▅▆▇█", { .geom = NCBLIT_8x1, .width = 1, .height = 8, .egcs = L" ▁▂▃▄▅▆▇█",
.blit = tria_blit, .name = "eightstep", .fill = false, }, .blit = tria_blit, .name = "eightstep", .fill = false, },
{ .geom = NCBLIT_1x1, .width = 1, .height = 1, .egcs = L"", { .geom = NCBLIT_1x1, .width = 1, .height = 1, .egcs = L"",
@ -847,29 +847,83 @@ static const struct blitset notcurses_blitters[] = {
.blit = NULL, .name = NULL, .fill = false, }, .blit = NULL, .name = NULL, .fill = false, },
}; };
int notcurses_lex_blitter(const char* op, ncblitter_e* blitter){ void set_pixel_blitter(blitter blitfxn){
struct blitset* b = notcurses_blitters;
while(b->geom != NCBLIT_PIXEL){
++b;
}
b->blit = blitfxn;
}
const struct blitset* lookup_blitset(const tinfo* tcache, ncblitter_e setid, bool may_degrade) {
if(setid == NCBLIT_DEFAULT){ // ought have resolved NCBLIT_DEFAULT before now
return NULL;
}
// without braille support, NCBLIT_BRAILLE decays to NCBLIT_3x2
if(!tcache->braille && setid == NCBLIT_BRAILLE){
if(may_degrade){
setid = NCBLIT_3x2;
}else{
return NULL;
}
}
// without pixel support, NCBLIT_PIXEL decays to NCBLIT_3x2
if(!tcache->sixel_supported && setid == NCBLIT_PIXEL){
if(may_degrade){
setid = NCBLIT_3x2;
}else{
return NULL;
}
}
// without sextant support, NCBLIT_3x2 decays to NCBLIT_2x2
if(!tcache->sextants && setid == NCBLIT_3x2){
if(may_degrade){
setid = NCBLIT_2x2;
}else{
return NULL;
}
}
// the only viable blitter in ASCII is NCBLIT_1x1
if(!tcache->utf8 && setid != NCBLIT_1x1){
if(may_degrade){
setid = NCBLIT_1x1;
}else{
return NULL;
}
}
const struct blitset* bset = notcurses_blitters;
while(bset->egcs){
if(bset->geom == setid){
return bset;
}
++bset;
}
return NULL;
}
int notcurses_lex_blitter(const char* op, ncblitter_e* blitfxn){
const struct blitset* bset = notcurses_blitters; const struct blitset* bset = notcurses_blitters;
while(bset->name){ while(bset->name){
if(strcasecmp(bset->name, op) == 0){ if(strcasecmp(bset->name, op) == 0){
*blitter = bset->geom; *blitfxn = bset->geom;
return 0; return 0;
} }
++bset; ++bset;
} }
if(strcasecmp("default", op) == 0){ if(strcasecmp("default", op) == 0){
*blitter = NCBLIT_DEFAULT; *blitfxn = NCBLIT_DEFAULT;
return 0; return 0;
} }
return -1; return -1;
} }
const char* notcurses_str_blitter(ncblitter_e blitter){ const char* notcurses_str_blitter(ncblitter_e blitfxn){
if(blitter == NCBLIT_DEFAULT){ if(blitfxn == NCBLIT_DEFAULT){
return "default"; return "default";
} }
const struct blitset* bset = notcurses_blitters; const struct blitset* bset = notcurses_blitters;
while(bset->name){ while(bset->name){
if(bset->geom == blitter){ if(bset->geom == blitfxn){
return bset->name; return bset->name;
} }
++bset; ++bset;
@ -909,15 +963,15 @@ int ncblit_rgba(const void* data, int linesize, const struct ncvisual_options* v
if(begy < 0 || begx < 0 || lenx < -1 || leny < -1){ if(begy < 0 || begx < 0 || lenx < -1 || leny < -1){
return -1; return -1;
} }
ncblitter_e blitter; ncblitter_e blitfxn;
if(!vopts || vopts->blitter == NCBLIT_DEFAULT){ if(!vopts || vopts->blitter == NCBLIT_DEFAULT){
blitter = ncvisual_media_defblitter(ncplane_notcurses(nc), NCSCALE_NONE); blitfxn = ncvisual_media_defblitter(ncplane_notcurses(nc), NCSCALE_NONE);
}else{ }else{
blitter = vopts->blitter; blitfxn = vopts->blitter;
} }
const bool degrade = !(vopts->flags & NCVISUAL_OPTION_NODEGRADE); const bool degrade = !(vopts->flags & NCVISUAL_OPTION_NODEGRADE);
const notcurses* notc = ncplane_notcurses(nc); const notcurses* notc = ncplane_notcurses(nc);
const struct blitset* bset = lookup_blitset(&notc->tcache, blitter, degrade); const struct blitset* bset = lookup_blitset(&notc->tcache, blitfxn, degrade);
if(bset == NULL){ if(bset == NULL){
return -1; return -1;
} }
@ -926,52 +980,6 @@ int ncblit_rgba(const void* data, int linesize, const struct ncvisual_options* v
leny, lenx, blend); leny, lenx, blend);
} }
const struct blitset* lookup_blitset(const tinfo* tcache, ncblitter_e setid, bool may_degrade) {
if(setid == NCBLIT_DEFAULT){ // ought have resolved NCBLIT_DEFAULT before now
return NULL;
}
// without braille support, NCBLIT_BRAILLE decays to NCBLIT_3x2
if(!tcache->braille && setid == NCBLIT_BRAILLE){
if(may_degrade){
setid = NCBLIT_3x2;
}else{
return NULL;
}
}
// without pixel support, NCBLIT_PIXEL decays to NCBLIT_3x2
if(!tcache->sixel_supported && setid == NCBLIT_PIXEL){
if(may_degrade){
setid = NCBLIT_3x2;
}else{
return NULL;
}
}
// without sextant support, NCBLIT_3x2 decays to NCBLIT_2x2
if(!tcache->sextants && setid == NCBLIT_3x2){
if(may_degrade){
setid = NCBLIT_2x2;
}else{
return NULL;
}
}
// the only viable blitter in ASCII is NCBLIT_1x1
if(!tcache->utf8 && setid != NCBLIT_1x1){
if(may_degrade){
setid = NCBLIT_1x1;
}else{
return NULL;
}
}
const struct blitset* bset = notcurses_blitters;
while(bset->egcs){
if(bset->geom == setid){
return bset;
}
++bset;
}
return NULL;
}
ncblitter_e ncvisual_media_defblitter(const notcurses* nc, ncscale_e scale){ ncblitter_e ncvisual_media_defblitter(const notcurses* nc, ncscale_e scale){
return rgba_blitter_default(&nc->tcache, scale); return rgba_blitter_default(&nc->tcache, scale);
} }

@ -44,4 +44,6 @@ ncplot_defblitter(const notcurses* nc){
return NCBLIT_1x1; return NCBLIT_1x1;
} }
void set_pixel_blitter(blitter blitfxn);
#endif #endif

@ -457,7 +457,7 @@ int ncdirect_raster_frame(ncdirect* n, ncdirectv* ncdv, ncalign_e align){
} }
ncdirectv* ncdirect_render_frame(ncdirect* n, const char* file, ncdirectv* ncdirect_render_frame(ncdirect* n, const char* file,
ncblitter_e blitter, ncscale_e scale){ ncblitter_e blitfxn, ncscale_e scale){
struct ncvisual* ncv = ncvisual_from_file(file); struct ncvisual* ncv = ncvisual_from_file(file);
if(ncv == nullptr){ if(ncv == nullptr){
return nullptr; return nullptr;
@ -470,7 +470,7 @@ ncdirectv* ncdirect_render_frame(ncdirect* n, const char* file,
return nullptr; return nullptr;
} }
//fprintf(stderr, "render %d/%d to %d+%d scaling: %d\n", ncv->rows, ncv->cols, leny, lenx, scale); //fprintf(stderr, "render %d/%d to %d+%d scaling: %d\n", ncv->rows, ncv->cols, leny, lenx, scale);
auto bset = rgba_blitter_low(&n->tcache, scale, true, blitter); auto bset = rgba_blitter_low(&n->tcache, scale, true, blitfxn);
if(!bset){ if(!bset){
ncvisual_destroy(ncv); ncvisual_destroy(ncv);
return nullptr; return nullptr;
@ -524,8 +524,8 @@ ncdirectv* ncdirect_render_frame(ncdirect* n, const char* file,
} }
int ncdirect_render_image(ncdirect* n, const char* file, ncalign_e align, int ncdirect_render_image(ncdirect* n, const char* file, ncalign_e align,
ncblitter_e blitter, ncscale_e scale){ ncblitter_e blitfxn, ncscale_e scale){
auto faken = ncdirect_render_frame(n, file, blitter, scale); auto faken = ncdirect_render_frame(n, file, blitfxn, scale);
if(!faken){ if(!faken){
return -1; return -1;
} }

@ -574,7 +574,7 @@ qrcode_cols(int version){
} }
int ncplane_qrcode(ncplane* n, int* ymax, int* xmax, const void* data, size_t len){ int ncplane_qrcode(ncplane* n, int* ymax, int* xmax, const void* data, size_t len){
const ncblitter_e blitter = NCBLIT_2x1; const ncblitter_e blitfxn = NCBLIT_2x1;
const int MAX_QR_VERSION = 40; // QR library only supports up to 40 const int MAX_QR_VERSION = 40; // QR library only supports up to 40
if(*ymax <= 0 || *xmax <= 0){ if(*ymax <= 0 || *xmax <= 0){
return -1; return -1;
@ -639,7 +639,7 @@ int ncplane_qrcode(ncplane* n, int* ymax, int* xmax, const void* data, size_t le
ret = square; ret = square;
struct ncvisual_options vopts = { struct ncvisual_options vopts = {
.n = n, .n = n,
.blitter = blitter, .blitter = blitfxn,
}; };
if(ncvisual_render(ncplane_notcurses(n), ncv, &vopts) == n){ if(ncvisual_render(ncplane_notcurses(n), ncv, &vopts) == n){
ret = square; ret = square;

@ -380,6 +380,10 @@ typedef struct notcurses {
unsigned stdio_blocking_save; // was stdio blocking at entry? restore on stop. unsigned stdio_blocking_save; // was stdio blocking at entry? restore on stop.
} notcurses; } notcurses;
typedef int (*blitter)(struct ncplane* n, int placey, int placex,
int linesize, const void* data, int begy, int begx,
int leny, int lenx, unsigned blendcolors);
// a system for rendering RGBA pixels as text glyphs // a system for rendering RGBA pixels as text glyphs
struct blitset { struct blitset {
ncblitter_e geom; ncblitter_e geom;
@ -390,9 +394,7 @@ struct blitset {
// quickly, i.e. it can be indexed as height arrays of 1 + height glyphs. i.e. // quickly, i.e. it can be indexed as height arrays of 1 + height glyphs. i.e.
// the first five braille EGCs are all 0 on the left, [0..4] on the right. // the first five braille EGCs are all 0 on the left, [0..4] on the right.
const wchar_t* egcs; const wchar_t* egcs;
int (*blit)(struct ncplane* n, int placey, int placex, blitter blit;
int linesize, const void* data, int begy, int begx,
int leny, int lenx, unsigned blendcolors);
const char* name; const char* name;
bool fill; bool fill;
}; };
@ -719,26 +721,6 @@ memdup(const void* src, size_t len){
ALLOC void* bgra_to_rgba(const void* data, int rows, int rowstride, int cols); ALLOC void* bgra_to_rgba(const void* data, int rows, int rowstride, int cols);
API const struct blitset* lookup_blitset(const tinfo* tcache, ncblitter_e setid, bool may_degrade);
static inline const struct blitset*
rgba_blitter_low(const tinfo* tcache, ncscale_e scale, bool maydegrade,
ncblitter_e blitrec) {
if(blitrec == NCBLIT_DEFAULT){
blitrec = rgba_blitter_default(tcache, scale);
}
return lookup_blitset(tcache, blitrec, maydegrade);
}
// RGBA visuals all use NCBLIT_2x1 by default (or NCBLIT_1x1 if not in
// UTF-8 mode), but an alternative can be specified.
static inline const struct blitset*
rgba_blitter(const struct notcurses* nc, const struct ncvisual_options* opts) {
const bool maydegrade = !(opts && (opts->flags & NCVISUAL_OPTION_NODEGRADE));
const ncscale_e scale = opts ? opts->scaling : NCSCALE_NONE;
return rgba_blitter_low(&nc->tcache, scale, maydegrade, opts ? opts->blitter : NCBLIT_DEFAULT);
}
// find the "center" cell of two lengths. in the case of even rows/columns, we // find the "center" cell of two lengths. in the case of even rows/columns, we
// place the center on the top/left. in such a case there will be one more // place the center on the top/left. in such a case there will be one more
// cell to the bottom/right of the center. // cell to the bottom/right of the center.
@ -1214,9 +1196,15 @@ int sixel_blit(ncplane* nc, int placey, int placex, int linesize,
const void* data, int begy, int begx, const void* data, int begy, int begx,
int leny, int lenx, unsigned cellpixx); int leny, int lenx, unsigned cellpixx);
int kitty_blit(ncplane* nc, int placey, int placex, int linesize,
const void* data, int begy, int begx,
int leny, int lenx, unsigned cellpixx);
int term_fg_rgb8(bool RGBflag, const char* setaf, int colors, FILE* out, int term_fg_rgb8(bool RGBflag, const char* setaf, int colors, FILE* out,
unsigned r, unsigned g, unsigned b); unsigned r, unsigned g, unsigned b);
API const struct blitset* lookup_blitset(const tinfo* tcache, ncblitter_e setid, bool may_degrade);
static inline int static inline int
rgba_blit_dispatch(ncplane* nc, const struct blitset* bset, int placey, rgba_blit_dispatch(ncplane* nc, const struct blitset* bset, int placey,
int placex, int linesize, const void* data, int begy, int placex, int linesize, const void* data, int begy,
@ -1225,6 +1213,24 @@ rgba_blit_dispatch(ncplane* nc, const struct blitset* bset, int placey,
leny, lenx, blendcolors); leny, lenx, blendcolors);
} }
static inline const struct blitset*
rgba_blitter_low(const tinfo* tcache, ncscale_e scale, bool maydegrade,
ncblitter_e blitrec) {
if(blitrec == NCBLIT_DEFAULT){
blitrec = rgba_blitter_default(tcache, scale);
}
return lookup_blitset(tcache, blitrec, maydegrade);
}
// RGBA visuals all use NCBLIT_2x1 by default (or NCBLIT_1x1 if not in
// UTF-8 mode), but an alternative can be specified.
static inline const struct blitset*
rgba_blitter(const struct notcurses* nc, const struct ncvisual_options* opts) {
const bool maydegrade = !(opts && (opts->flags & NCVISUAL_OPTION_NODEGRADE));
const ncscale_e scale = opts ? opts->scaling : NCSCALE_NONE;
return rgba_blitter_low(&nc->tcache, scale, maydegrade, opts ? opts->blitter : NCBLIT_DEFAULT);
}
typedef struct ncvisual_implementation { typedef struct ncvisual_implementation {
int (*visual_init)(int loglevel); int (*visual_init)(int loglevel);
void (*visual_printbanner)(const struct notcurses* nc); void (*visual_printbanner)(const struct notcurses* nc);

@ -0,0 +1,7 @@
#include "internal.h"
int kitty_blit(ncplane* nc, int placey, int placex, int linesize,
const void* data, int begy, int begx,
int leny, int lenx, unsigned cellpixx){
return 0;
}

@ -43,12 +43,12 @@ class ncppplot {
return false; return false;
} }
const notcurses* notc = ncplane_notcurses(n); const notcurses* notc = ncplane_notcurses(n);
ncblitter_e blitter = opts ? opts->gridtype : NCBLIT_DEFAULT; ncblitter_e blitfxn = opts ? opts->gridtype : NCBLIT_DEFAULT;
if(blitter == NCBLIT_DEFAULT){ if(blitfxn == NCBLIT_DEFAULT){
blitter = ncplot_defblitter(notc); blitfxn = ncplot_defblitter(notc);
} }
bool degrade_blitter = !(opts && (opts->flags & NCPLOT_OPTION_NODEGRADE)); bool degrade_blitter = !(opts && (opts->flags & NCPLOT_OPTION_NODEGRADE));
auto bset = lookup_blitset(&notc->tcache, blitter, degrade_blitter); auto bset = lookup_blitset(&notc->tcache, blitfxn, degrade_blitter);
if(bset == nullptr){ if(bset == nullptr){
ncplane_destroy(n); ncplane_destroy(n);
return false; return false;

@ -58,6 +58,9 @@ apply_term_heuristics(tinfo* ti, const char* termname){
// be RGB(0, 0, 0) (the default). we could also just set it, i guess. // be RGB(0, 0, 0) (the default). we could also just set it, i guess.
ti->bg_collides_default = 0x1000000; ti->bg_collides_default = 0x1000000;
ti->sextants = true; // work since bugfix in 0.19.3 ti->sextants = true; // work since bugfix in 0.19.3
ti->pixel_query_done = true;
ti->sixel_supported = true;
set_pixel_blitter(kitty_blit);
/*}else if(strstr(termname, "alacritty")){ /*}else if(strstr(termname, "alacritty")){
ti->sextants = true; // alacritty https://github.com/alacritty/alacritty/issues/4409 */ ti->sextants = true; // alacritty https://github.com/alacritty/alacritty/issues/4409 */
}else if(strstr(termname, "vte") || strstr(termname, "gnome") || strstr(termname, "xfce")){ }else if(strstr(termname, "vte") || strstr(termname, "gnome") || strstr(termname, "xfce")){

@ -72,14 +72,14 @@ auto ncvisual_geom(const notcurses* nc, const ncvisual* n,
const struct ncvisual_options* vopts, const struct ncvisual_options* vopts,
int* y, int* x, int* toy, int* tox) -> int { int* y, int* x, int* toy, int* tox) -> int {
const ncscale_e scale = vopts ? vopts->scaling : NCSCALE_NONE; const ncscale_e scale = vopts ? vopts->scaling : NCSCALE_NONE;
ncblitter_e blitter; ncblitter_e blitfxn;
if(!vopts || vopts->blitter == NCBLIT_DEFAULT){ if(!vopts || vopts->blitter == NCBLIT_DEFAULT){
blitter = ncvisual_media_defblitter(nc, scale); blitfxn = ncvisual_media_defblitter(nc, scale);
}else{ }else{
blitter = vopts->blitter; blitfxn = vopts->blitter;
} }
const bool maydegrade = !(vopts && (vopts->flags & NCVISUAL_OPTION_NODEGRADE)); const bool maydegrade = !(vopts && (vopts->flags & NCVISUAL_OPTION_NODEGRADE));
const struct blitset* bset = lookup_blitset(&nc->tcache, blitter, maydegrade); const struct blitset* bset = lookup_blitset(&nc->tcache, blitfxn, maydegrade);
if(!bset){ if(!bset){
return -1; return -1;
} }

Loading…
Cancel
Save