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
// 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" ▁▂▃▄▅▆▇█",
.blit = tria_blit, .name = "eightstep", .fill = false, },
{ .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, },
};
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;
while(bset->name){
if(strcasecmp(bset->name, op) == 0){
*blitter = bset->geom;
*blitfxn = bset->geom;
return 0;
}
++bset;
}
if(strcasecmp("default", op) == 0){
*blitter = NCBLIT_DEFAULT;
*blitfxn = NCBLIT_DEFAULT;
return 0;
}
return -1;
}
const char* notcurses_str_blitter(ncblitter_e blitter){
if(blitter == NCBLIT_DEFAULT){
const char* notcurses_str_blitter(ncblitter_e blitfxn){
if(blitfxn == NCBLIT_DEFAULT){
return "default";
}
const struct blitset* bset = notcurses_blitters;
while(bset->name){
if(bset->geom == blitter){
if(bset->geom == blitfxn){
return bset->name;
}
++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){
return -1;
}
ncblitter_e blitter;
ncblitter_e blitfxn;
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{
blitter = vopts->blitter;
blitfxn = vopts->blitter;
}
const bool degrade = !(vopts->flags & NCVISUAL_OPTION_NODEGRADE);
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){
return -1;
}
@ -926,52 +980,6 @@ int ncblit_rgba(const void* data, int linesize, const struct ncvisual_options* v
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){
return rgba_blitter_default(&nc->tcache, scale);
}

@ -44,4 +44,6 @@ ncplot_defblitter(const notcurses* nc){
return NCBLIT_1x1;
}
void set_pixel_blitter(blitter blitfxn);
#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,
ncblitter_e blitter, ncscale_e scale){
ncblitter_e blitfxn, ncscale_e scale){
struct ncvisual* ncv = ncvisual_from_file(file);
if(ncv == nullptr){
return nullptr;
@ -470,7 +470,7 @@ ncdirectv* ncdirect_render_frame(ncdirect* n, const char* file,
return nullptr;
}
//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){
ncvisual_destroy(ncv);
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,
ncblitter_e blitter, ncscale_e scale){
auto faken = ncdirect_render_frame(n, file, blitter, scale);
ncblitter_e blitfxn, ncscale_e scale){
auto faken = ncdirect_render_frame(n, file, blitfxn, scale);
if(!faken){
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){
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
if(*ymax <= 0 || *xmax <= 0){
return -1;
@ -639,7 +639,7 @@ int ncplane_qrcode(ncplane* n, int* ymax, int* xmax, const void* data, size_t le
ret = square;
struct ncvisual_options vopts = {
.n = n,
.blitter = blitter,
.blitter = blitfxn,
};
if(ncvisual_render(ncplane_notcurses(n), ncv, &vopts) == n){
ret = square;

@ -380,6 +380,10 @@ typedef struct notcurses {
unsigned stdio_blocking_save; // was stdio blocking at entry? restore on stop.
} 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
struct blitset {
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.
// the first five braille EGCs are all 0 on the left, [0..4] on the right.
const wchar_t* egcs;
int (*blit)(struct ncplane* n, int placey, int placex,
int linesize, const void* data, int begy, int begx,
int leny, int lenx, unsigned blendcolors);
blitter blit;
const char* name;
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);
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
// place the center on the top/left. in such a case there will be one more
// 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,
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,
unsigned r, unsigned g, unsigned b);
API const struct blitset* lookup_blitset(const tinfo* tcache, ncblitter_e setid, bool may_degrade);
static inline int
rgba_blit_dispatch(ncplane* nc, const struct blitset* bset, int placey,
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);
}
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 {
int (*visual_init)(int loglevel);
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;
}
const notcurses* notc = ncplane_notcurses(n);
ncblitter_e blitter = opts ? opts->gridtype : NCBLIT_DEFAULT;
if(blitter == NCBLIT_DEFAULT){
blitter = ncplot_defblitter(notc);
ncblitter_e blitfxn = opts ? opts->gridtype : NCBLIT_DEFAULT;
if(blitfxn == NCBLIT_DEFAULT){
blitfxn = ncplot_defblitter(notc);
}
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){
ncplane_destroy(n);
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.
ti->bg_collides_default = 0x1000000;
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")){
ti->sextants = true; // alacritty https://github.com/alacritty/alacritty/issues/4409 */
}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,
int* y, int* x, int* toy, int* tox) -> int {
const ncscale_e scale = vopts ? vopts->scaling : NCSCALE_NONE;
ncblitter_e blitter;
ncblitter_e blitfxn;
if(!vopts || vopts->blitter == NCBLIT_DEFAULT){
blitter = ncvisual_media_defblitter(nc, scale);
blitfxn = ncvisual_media_defblitter(nc, scale);
}else{
blitter = vopts->blitter;
blitfxn = vopts->blitter;
}
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){
return -1;
}

Loading…
Cancel
Save