diff --git a/src/lib/direct.c b/src/lib/direct.c index 9078f7497..be3a69e8d 100644 --- a/src/lib/direct.c +++ b/src/lib/direct.c @@ -380,7 +380,7 @@ ncdirect_dump_plane(ncdirect* n, const ncplane* np, int xoff){ int dimy, dimx; ncplane_dim_yx(np, &dimy, &dimx); if(np->sprite){ - if(fputs(np->sprite->glyph, n->ttyfp) == EOF){ + if(ncfputs(np->sprite->glyph, n->ttyfp) == EOF){ return -1; } return 0; diff --git a/src/lib/internal.h b/src/lib/internal.h index ce1552887..a95e07f11 100644 --- a/src/lib/internal.h +++ b/src/lib/internal.h @@ -45,6 +45,12 @@ struct ncvisual_details; // we can't define multipart ncvisual here, because OIIO requires C++ syntax, // and we can't go throwing C++ syntax into this header. so it goes. +typedef enum { + SPRIXEL_NOCHANGE, + SPRIXEL_INVALIDATED, + SPRIXEL_HIDE, +} sprixel_e; + // there is a context-wide set of displayed pixel glyphs ("sprixels"); i.e. // these are independent of particular piles. there should never be very many // associated with a context (a dozen or so at max). with the kitty protocol, @@ -54,11 +60,7 @@ typedef struct sprixel { char* glyph; // glyph; can be quite large int id; // embedded into glusters field of nccell struct ncplane* n; // associated ncplane - enum { - SPRIXEL_NOCHANGE, - SPRIXEL_INVALIDATED, - SPRIXEL_HIDE, - } invalidated; + sprixel_e invalidated; struct sprixel* next; int y, x; int dimy, dimx; // cell geometry @@ -450,6 +452,26 @@ struct blitset { #include "blitset.h" +static inline int +ncfputs(const char* ext, FILE* out){ + int r; +#ifdef __USE_GNU + r = fputs_unlocked(ext, out); +#else + r = fputs(ext, out); +#endif + return r; +} + +static inline int +ncfputc(char c, FILE* out){ +#ifdef __USE_GNU + return fputc_unlocked(c, out); +#else + return fputc(c, out); +#endif +} + void reset_stats(ncstats* stats); void summarize_stats(notcurses* nc); @@ -635,7 +657,7 @@ term_emit(const char* seq, FILE* out, bool flush){ if(!seq){ return -1; } - if(fputs(seq, out) == EOF){ + if(ncfputs(seq, out) == EOF){ //fprintf(stderr, "Error emitting %zub escape (%s)\n", strlen(seq), strerror(errno)); return -1; } diff --git a/src/lib/kitty.c b/src/lib/kitty.c index 76c54af32..1378d73b4 100644 --- a/src/lib/kitty.c +++ b/src/lib/kitty.c @@ -227,7 +227,7 @@ write_kitty_data(FILE* fp, int linesize, int leny, int lenx, totalout += encodeable; char out[17]; base64_rgba3(source, encodeable, out); - fputs(out, fp); + ncfputs(out, fp); } fprintf(fp, "\e\\"); } diff --git a/src/lib/render.c b/src/lib/render.c index 6c72cfc62..2f66245ff 100644 --- a/src/lib/render.c +++ b/src/lib/render.c @@ -554,26 +554,6 @@ int ncplane_mergedown_simple(const ncplane* restrict src, ncplane* restrict dst) return ncplane_mergedown(src, dst, 0, 0, ncplane_dim_y(src), ncplane_dim_x(src), 0, 0); } -static inline int -ncfputs(const char* ext, FILE* out){ - int r; -#ifdef __USE_GNU - r = fputs_unlocked(ext, out); -#else - r = fputs(ext, out); -#endif - return r; -} - -static inline int -ncfputc(char c, FILE* out){ -#ifdef __USE_GNU - return fputc_unlocked(c, out); -#else - return fputc(c, out); -#endif -} - // write the nccell's UTF-8 extended grapheme cluster to the provided FILE*. static int term_putc(FILE* out, const egcpool* e, const nccell* c){ @@ -973,7 +953,7 @@ rasterize_sprixels(notcurses* nc, const ncpile* p, FILE* out){ ncplane_yx(s->n, &y, &x); y += s->y; x += s->x; -//fprintf(stderr, "DRAWING BITMAP AT %d/%d\n", y, x); +//fprintf(stderr, "DRAWING BITMAP AT %d/%d\n", y + nc->stdplane->absy, x + nc->stdplane->absx); if(goto_location(nc, out, y + nc->stdplane->absy, x + nc->stdplane->absx)){ return -1; } @@ -991,7 +971,6 @@ rasterize_sprixels(notcurses* nc, const ncpile* p, FILE* out){ }else if(r > 0){ ret = 1; } - // FIXME delete it in kitty *parent = s->next; sprixel_free(s); }else{ diff --git a/src/tests/pixel.cpp b/src/tests/pixel.cpp index a42c777f8..a8ef0a6d8 100644 --- a/src/tests/pixel.cpp +++ b/src/tests/pixel.cpp @@ -107,5 +107,47 @@ TEST_CASE("Pixel") { ncvisual_destroy(ncv); CHECK(0 == notcurses_render(nc_)); } + + SUBCASE("PixelBigCellWipePolychromatic") { + // first, assemble a visual equivalent to 4 cells + auto y = 10 * nc_->tcache.cellpixy; + auto x = 10 * nc_->tcache.cellpixx; + std::vector v(x * y, 0xffffffff); + for(auto& e : v){ + e -= random() % 0x1000000; + } + auto ncv = ncvisual_from_rgba(v.data(), y, sizeof(decltype(v)::value_type) * x, x); + REQUIRE(nullptr != ncv); + struct ncvisual_options vopts = { + .n = nullptr, + .scaling = NCSCALE_NONE, + .y = 0, .x = 0, + .begy = 0, .begx = 0, + .leny = y, .lenx = x, + .blitter = NCBLIT_PIXEL, + .flags = NCVISUAL_OPTION_NODEGRADE, + }; + auto n = ncvisual_render(nc_, ncv, &vopts); + REQUIRE(nullptr != n); + auto s = n->sprite; + REQUIRE(nullptr != s); + CHECK(0 == notcurses_render(nc_)); + CHECK(0 == nc_->tcache.pixel_cell_wipe(nc_, s, 5, 5)); + s->invalidated = SPRIXEL_INVALIDATED; + CHECK(0 == notcurses_render(nc_)); + CHECK(0 == nc_->tcache.pixel_cell_wipe(nc_, s, 3, 3)); + s->invalidated = SPRIXEL_INVALIDATED; + CHECK(0 == notcurses_render(nc_)); + CHECK(0 == nc_->tcache.pixel_cell_wipe(nc_, s, 8, 8)); + s->invalidated = SPRIXEL_INVALIDATED; + CHECK(0 == notcurses_render(nc_)); + CHECK(0 == nc_->tcache.pixel_cell_wipe(nc_, s, 8, 3)); + s->invalidated = SPRIXEL_INVALIDATED; + CHECK(0 == notcurses_render(nc_)); + ncplane_destroy(n); + ncvisual_destroy(ncv); + CHECK(0 == notcurses_render(nc_)); + } + CHECK(!notcurses_stop(nc_)); }