diff --git a/src/lib/blit.c b/src/lib/blit.c index 25f77c705..6491b28d8 100644 --- a/src/lib/blit.c +++ b/src/lib/blit.c @@ -830,50 +830,21 @@ const char* notcurses_str_blitter(ncblitter_e blitter){ } int ncblit_bgrx(const void* data, int linesize, const struct ncvisual_options* vopts){ - if(vopts->flags > NCVISUAL_OPTION_BLEND){ - return -1; - } - if(linesize <= 0 || (size_t)linesize < vopts->lenx * sizeof(uint32_t)){ - return -1; - } - struct ncplane* nc = vopts->n; - if(nc == NULL){ + if(vopts->leny <= 0 || vopts->lenx <= 0){ return -1; } - int lenx = vopts->lenx; - int leny = vopts->leny; - int begy = vopts->begy; - int begx = vopts->begx; -//fprintf(stderr, "render %dx%d+%dx%d %p\n", begy, begx, leny, lenx, ncv->data); - if(begy < 0 || begx < 0 || lenx < -1 || leny < -1){ - return -1; - } - ncblitter_e blitter; - if(!vopts || vopts->blitter == NCBLIT_DEFAULT){ - blitter = ncvisual_default_blitter(nc, NCSCALE_NONE); - }else{ - blitter = vopts->blitter; - } - const bool degrade = !(vopts->flags & NCVISUAL_OPTION_NODEGRADE); - const struct blitset* bset = lookup_blitset(notcurses_canutf8(nc->nc), - blitter, degrade); - if(bset == NULL){ - return -1; - } - const bool blend = (vopts->flags & NCVISUAL_OPTION_BLEND); - void* rdata = bgra_to_rgba(data, leny, linesize, lenx); + void* rdata = bgra_to_rgba(data, vopts->leny, linesize, vopts->lenx); if(rdata == NULL){ return -1; } - int r = bset->blit(nc, vopts->y, vopts->x, linesize, rdata, begy, begx, - leny, lenx, blend); + int r = ncblit_rgba(rdata, linesize, vopts); free(rdata); return r; } int ncblit_rgba(const void* data, int linesize, const struct ncvisual_options* vopts){ if(vopts->flags > NCVISUAL_OPTION_BLEND){ - return -1; + fprintf(stderr, "Warning: unknown ncvisual options %016lx\n", vopts->flags); } if(linesize <= 0 || (size_t)linesize < vopts->lenx * sizeof(uint32_t)){ return -1; diff --git a/src/lib/visual.cpp b/src/lib/visual.cpp index d8aac8817..e5bc6fcf8 100644 --- a/src/lib/visual.cpp +++ b/src/lib/visual.cpp @@ -65,8 +65,10 @@ auto bgra_to_rgba(const void* data, int rows, int rowstride, int cols) -> void* for(int x = 0 ; x < cols ; ++x){ const uint32_t* src = (const uint32_t*)data + (rowstride / 4) * y + x; uint32_t* dst = ret + (rowstride / 4) * y + x; - *dst = ((*src & 0xff00u) << 16u) | (*src & 0xff00ffu) | ((*src & 0xff000000) >> 16u); -//fprintf(stderr, "y: %d x: %d SRC: %x DST: %x\n", y, x, *src, *dst); + ncpixel_set_a(dst, 0xff); + ncpixel_set_r(dst, ncpixel_b(*src)); + ncpixel_set_g(dst, ncpixel_g(*src)); + ncpixel_set_b(dst, ncpixel_r(*src)); } } } @@ -362,7 +364,7 @@ auto ncvisual_from_bgra(const void* bgra, int rows, int rowstride, auto ncvisual_render(notcurses* nc, ncvisual* ncv, const struct ncvisual_options* vopts) -> ncplane* { if(vopts && vopts->flags > NCVISUAL_OPTION_BLEND){ - return nullptr; + fprintf(stderr, "Warning: unknown ncvisual options %016lx\n", vopts->flags); } int lenx = vopts ? vopts->lenx : 0; int leny = vopts ? vopts->leny : 0; diff --git a/tests/blit.cpp b/tests/blit.cpp new file mode 100644 index 000000000..843babb55 --- /dev/null +++ b/tests/blit.cpp @@ -0,0 +1,89 @@ +#include "main.h" +#include + +TEST_CASE("Blitting") { + auto nc_ = testing_notcurses(); + REQUIRE(nullptr != nc_); + ncplane* ncp_ = notcurses_stdplane(nc_); + REQUIRE(ncp_); + auto n_ = notcurses_stdplane(nc_); + REQUIRE(n_); + + SUBCASE("BgraToRgba") { + const uint32_t data[8] = { + 0xffffffff, 0xff0088ff, 0xffff8800, 0xff88ff00, + 0xffff0088, 0xff8800ff, 0Xff00ff88, 0xff000000, + }; + auto ncp = ncplane_new(n_, 2, 4, 0, 0, nullptr, nullptr); + REQUIRE(nullptr != ncp); + struct ncvisual_options vopts = { + .n = ncp, + .scaling = NCSCALE_NONE, + .y = 0, + .x = 0, + .begy = 0, + .begx = 0, + .leny = 2, + .lenx = 4, + .blitter = NCBLIT_1x1, + .flags = 0, + }; + ncblit_bgrx(data, 16, &vopts); + for(int y = 0 ; y < 2 ; ++y){ + for(int x = 0 ; x < 4 ; ++x){ + uint32_t bgra = data[(y * 4) + x]; + uint16_t stylemask; + uint64_t channels; + auto egc = ncplane_at_yx(ncp, y, x, &stylemask, &channels); + CHECK(0 == strcmp(" ", egc)); + free(egc); + CHECK(0 == stylemask); + uint32_t rgb = channels_bg_rgb(channels); + CHECK(ncpixel_r(bgra) == ncpixel_r(rgb)); + CHECK(ncpixel_g(bgra) == ncpixel_g(rgb)); + CHECK(ncpixel_b(bgra) == ncpixel_b(rgb)); + } + } + ncplane_destroy(ncp); + } + + SUBCASE("BgraToRgbaWithStride") { + const uint32_t data[10] = { + 0xffffffff, 0xff0088ff, 0xffff8800, 0xff88ff00, 0x00000000, + 0xffff0088, 0xff8800ff, 0xff00ff88, 0xff000000, 0x00000000, + }; + auto ncp = ncplane_new(n_, 2, 4, 0, 0, nullptr, nullptr); + REQUIRE(nullptr != ncp); + struct ncvisual_options vopts = { + .n = ncp, + .scaling = NCSCALE_NONE, + .y = 0, + .x = 0, + .begy = 0, + .begx = 0, + .leny = 2, + .lenx = 4, + .blitter = NCBLIT_1x1, + .flags = 0, + }; + ncblit_bgrx(data, 20, &vopts); + for(int y = 0 ; y < 2 ; ++y){ + for(int x = 0 ; x < 4 ; ++x){ + uint32_t bgra = data[(y * 5) + x]; + uint16_t stylemask; + uint64_t channels; + auto egc = ncplane_at_yx(ncp, y, x, &stylemask, &channels); + CHECK(0 == strcmp(" ", egc)); + free(egc); + CHECK(0 == stylemask); + uint32_t rgb = channels_bg_rgb(channels); + CHECK(ncpixel_r(bgra) == ncpixel_r(rgb)); + CHECK(ncpixel_g(bgra) == ncpixel_g(rgb)); + CHECK(ncpixel_b(bgra) == ncpixel_b(rgb)); + } + } + ncplane_destroy(ncp); + } + + CHECK(!notcurses_stop(nc_)); +}