From 9a0f0c66fe56b1c7eb3194dbe902e09995dd10c1 Mon Sep 17 00:00:00 2001 From: nick black Date: Fri, 5 Jun 2020 03:47:13 -0400 Subject: [PATCH] ncblit: accept an ncvisual_options #680 --- NEWS.md | 10 ++--- USAGE.md | 26 +++++------ include/ncpp/Plane.hh | 8 ++-- include/notcurses/notcurses.h | 26 +++++------ python/src/notcurses/build_notcurses.py | 4 +- src/demo/normal.c | 7 ++- src/lib/blit.c | 58 ++++++++++++++++++------- src/poc/rotator.c | 30 ++++++++----- 8 files changed, 101 insertions(+), 68 deletions(-) diff --git a/NEWS.md b/NEWS.md index 1c29bda27..15bb90fe3 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,11 +1,11 @@ This document attempts to list user-visible changes and any major internal rearrangements of Notcurses. -* 1.5.0 (not yet released) - * `ncblit_rgba()` and `ncblit_bgrx()` have been renamed `ncplane_blit_rgba()` - and `ncplane_blit_bgrx()`, to match every other existing ncplane function. - In addition, they both now accept an `ncblitter_e` to select the blitting - method. `NCBLIT_DEFAULT` will use `NCBLITTER_2x1`. +* 1.4.5 (not yet released) + * `ncblit_rgba()` and `ncblit_bgrx()` have replaced most of their arguments + with a `const struct ncvisual_options*`. `NCBLIT_DEFAULT` will use + `NCBLITTER_2x1` (with fallback) in this context. The `->n` field must + be non-`NULL`--new planes will not be created. * Added `ncplane_notcurses_const()`. * 1.4.4.1 (2020-06-01) diff --git a/USAGE.md b/USAGE.md index 5b38d5807..237446829 100644 --- a/USAGE.md +++ b/USAGE.md @@ -1249,21 +1249,19 @@ void ncfadectx_free(struct ncfadectx* nctx); Raw streams of RGBA or BGRx data can be blitted directly to an ncplane: ```c -// Blit a flat array 'data' of BGRx 32-bit values to the ncplane 'nc', offset -// from the upper left by 'placey' and 'placex'. Each row ought occupy -// 'linesize' bytes (this might be greater than lenx * 4 due to padding). A -// subregion of the input can be specified with 'begy'x'begx' and 'leny'x'lenx'. -int ncplane_blit_bgrx(struct ncplane* nc, int placey, int placex, int linesize, - ncblitter_e blitter, const unsigned char* data, - int begy, int begx, int leny, int lenx); +// Blit a flat array 'data' of RGBA 32-bit values to the ncplane 'vopts->n', +// which mustn't be NULL. the blit begins at 'vopts->y' and 'vopts->x' relative +// to the specified plane. Each source row ought occupy 'linesize' bytes (this +// might be greater than 'vopts->lenx' * 4 due to padding or partial blits). A +// subregion of the input can be specified with the 'begy'x'begx' and +// 'leny'x'lenx' fields from 'vopts'. Returns the number of pixels blitted, or +// -1 on error. +int ncblit_rgba(const void* data, int linesize, + const struct ncvisual_options* vopts); -// Blit a flat array 'data' of RGBA 32-bit values to the ncplane 'nc', offset -// from the upper left by 'placey' and 'placex'. Each row ought occupy -// 'linesize' bytes (this might be greater than lenx * 4 due to padding). A -// subregion of the input can be specified with 'begy'x'begx' and 'leny'x'lenx'. -int ncplane_blit_rgba(struct ncplane* nc, int placey, int placex, int linesize, - ncblitter_e blitter, const unsigned char* data, - int begy, int begx, int leny, int lenx); +// Same as ncblit_rgba(), but for BGRx. +int ncblit_bgrx(const void* data, int linesize, + const struct ncvisual_options* vopts); ``` diff --git a/include/ncpp/Plane.hh b/include/ncpp/Plane.hh index 5258ebce2..169c7531c 100644 --- a/include/ncpp/Plane.hh +++ b/include/ncpp/Plane.hh @@ -1015,15 +1015,15 @@ namespace ncpp static Plane* map_plane (ncplane *ncp, Plane *associated_plane = nullptr) noexcept; - bool blit_bgrx (int placey, int placex, int linesize, const void* data, int begy, int begx, int leny, int lenx) const NOEXCEPT_MAYBE + bool blit_bgrx (const void* data, int linesize, const struct ncvisual_options *vopts) const NOEXCEPT_MAYBE { - bool ret = ncplane_blit_bgrx (plane, placey, placex, linesize, NCBLIT_DEFAULT, data, begy, begx, leny, lenx) < 0; + bool ret = ncblit_bgrx (data, linesize, vopts) < 0; return error_guard_cond (ret, ret); } - bool blit_rgba (int placey, int placex, int linesize, const void* data, int begy, int begx, int leny, int lenx) const NOEXCEPT_MAYBE + bool blit_rgba (const void* data, int linesize, const struct ncvisual_options *vopts) const NOEXCEPT_MAYBE { - bool ret = ncplane_blit_rgba (plane, placey, placex, linesize, NCBLIT_DEFAULT, data, begy, begx, leny, lenx) < 0; + bool ret = ncblit_rgba (data, linesize, vopts) < 0; return error_guard_cond (ret, ret); } diff --git a/include/notcurses/notcurses.h b/include/notcurses/notcurses.h index 09b162e56..8283890a8 100644 --- a/include/notcurses/notcurses.h +++ b/include/notcurses/notcurses.h @@ -2233,21 +2233,19 @@ API int ncvisual_stream(struct notcurses* nc, struct ncvisual* ncv, nc_err_e* ncerr, float timescale, streamcb streamer, const struct ncvisual_options* vopts, void* curry); -// Blit a flat array 'data' of BGRx 32-bit values to the ncplane 'nc', offset -// from the upper left by 'placey' and 'placex'. Each row ought occupy -// 'linesize' bytes (this might be greater than lenx * 4 due to padding). A -// subregion of the input can be specified with 'begy'x'begx' and 'leny'x'lenx'. -API int ncplane_blit_bgrx(struct ncplane* nc, int placey, int placex, - int linesize, ncblitter_e blitter, const void* data, - int begy, int begx, int leny, int lenx); +// Blit a flat array 'data' of RGBA 32-bit values to the ncplane 'vopts->n', +// which mustn't be NULL. the blit begins at 'vopts->y' and 'vopts->x' relative +// to the specified plane. Each source row ought occupy 'linesize' bytes (this +// might be greater than 'vopts->lenx' * 4 due to padding or partial blits). A +// subregion of the input can be specified with the 'begy'x'begx' and +// 'leny'x'lenx' fields from 'vopts'. Returns the number of pixels blitted, or +// -1 on error. +API int ncblit_rgba(const void* data, int linesize, + const struct ncvisual_options* vopts); -// Blit a flat array 'data' of RGBA 32-bit values to the ncplane 'nc', offset -// from the upper left by 'placey' and 'placex'. Each row ought occupy -// 'linesize' bytes (this might be greater than lenx * 4 due to padding). A -// subregion of the input can be specified with 'begy'x'begx' and 'leny'x'lenx'. -API int ncplane_blit_rgba(struct ncplane* nc, int placey, int placex, - int linesize, ncblitter_e blitter, const void* data, - int begy, int begx, int leny, int lenx); +// Same as ncblit_rgba(), but for BGRx. +API int ncblit_bgrx(const void* data, int linesize, + const struct ncvisual_options* vopts); // An ncreel is a notcurses region devoted to displaying zero or more // line-oriented, contained panels between which the user may navigate. If at diff --git a/python/src/notcurses/build_notcurses.py b/python/src/notcurses/build_notcurses.py index d32259195..661298362 100644 --- a/python/src/notcurses/build_notcurses.py +++ b/python/src/notcurses/build_notcurses.py @@ -323,8 +323,8 @@ struct ncvisual_options { ncblitter_e blitter; uint64_t flags; }; -int ncplane_blit_bgrx(struct ncplane* nc, int placey, int placex, int linesize, ncblitter_e blitter, const unsigned char* data, int begy, int begx, int leny, int lenx); -int ncplane_blit_rgba(struct ncplane* nc, int placey, int placex, int linesize, ncblitter_e blitter, const unsigned char* data, int begy, int begx, int leny, int lenx); +struct ncplane* ncblit_bgrx(const void* data, int linesize, const struct ncvisual_options *vopts); +struct ncplane* ncblit_rgba(const void* data, int linesize, const struct ncvisual_options *vopts); struct ncselector_item { char* option; char* desc; diff --git a/src/demo/normal.c b/src/demo/normal.c index 0693ad4cf..0461b024a 100644 --- a/src/demo/normal.c +++ b/src/demo/normal.c @@ -173,7 +173,12 @@ int normal_demo(struct notcurses* nc){ goto err; } } - if(ncplane_blit_rgba(nstd, 0, 0, dx * sizeof(*rgba), NCBLIT_DEFAULT, rgba, 0, 0, dy, dx) < 0){ + struct ncvisual_options vopts = { + .n = nstd, + .leny = dy, + .lenx = dx, + }; + if(ncblit_rgba(rgba, dx * sizeof(*rgba), &vopts) < 0){ goto err; } if( (r = demo_render(nc)) ){ diff --git a/src/lib/blit.c b/src/lib/blit.c index 58e4a782c..2f93aacf7 100644 --- a/src/lib/blit.c +++ b/src/lib/blit.c @@ -443,30 +443,56 @@ const struct blitset notcurses_blitters[] = { .blit = NULL, .fill = false, }, }; -// Blit a flat array 'data' of BGRx 32-bit values to the ncplane 'nc', offset -// from the upper left by 'placey' and 'placex'. Each row ought occupy -// 'linesize' bytes (this might be greater than lenx * 4 due to padding). A -// subregion of the input can be specified with 'begy'x'begx' and 'leny'x'lenx'. -int ncplane_blit_bgrx(ncplane* nc, int placey, int placex, int linesize, - ncblitter_e blitter, const void* data, - int begy, int begx, int leny, int lenx){ - const struct blitset* bset = lookup_blitset(ncplane_notcurses(nc), blitter, true); +int ncblit_bgrx(const void* data, int linesize, const struct ncvisual_options* vopts){ + if(vopts->flags > NCVISUAL_OPTION_BLEND){ + return -1; + } + struct ncplane* nc = vopts->n; + if(nc == NULL){ + 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; + } + const bool degrade = (vopts->flags & NCVISUAL_OPTION_MAYDEGRADE); + const struct blitset* bset = lookup_blitset(nc->nc, vopts->blitter, degrade); if(bset == NULL){ return -1; } - return bset->blit(nc, placey, placex, linesize, data, begy, begx, - leny, lenx, true, false); + const bool blend = (vopts->flags & NCVISUAL_OPTION_BLEND); + return bset->blit(nc, vopts->y, vopts->x, linesize, data, begy, begx, + leny, lenx, true, blend); } -int ncplane_blit_rgba(ncplane* nc, int placey, int placex, int linesize, - ncblitter_e blitter, const void* data, - int begy, int begx, int leny, int lenx){ - const struct blitset* bset = lookup_blitset(ncplane_notcurses(nc), blitter, true); +int ncblit_rgba(const void* data, int linesize, const struct ncvisual_options* vopts){ + if(vopts->flags > NCVISUAL_OPTION_BLEND){ + return -1; + } + struct ncplane* nc = vopts->n; + if(nc == NULL){ + 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; + } + const bool degrade = (vopts->flags & NCVISUAL_OPTION_MAYDEGRADE); + const struct blitset* bset = lookup_blitset(nc->nc, vopts->blitter, degrade); if(bset == NULL){ return -1; } - return bset->blit(nc, placey, placex, linesize, data, begy, begx, - leny, lenx, false, false); + const bool blend = (vopts->flags & NCVISUAL_OPTION_BLEND); + return bset->blit(nc, vopts->y, vopts->x, linesize, data, begy, begx, + leny, lenx, false, blend); } int rgba_blit_dispatch(ncplane* nc, const struct blitset* bset, int placey, diff --git a/src/poc/rotator.c b/src/poc/rotator.c index 31049def8..875e3ee29 100644 --- a/src/poc/rotator.c +++ b/src/poc/rotator.c @@ -31,8 +31,12 @@ rotate_grad(struct notcurses* nc){ notcurses_render(nc); clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);; - if(ncplane_blit_rgba(n, 0, 0, dimx * 4, NCBLIT_DEFAULT, - rgba, 0, 0, dimy * 2, dimx) < 0){ + struct ncvisual_options vopts = { + .n = n, + .leny = dimy * 2, + .lenx = dimx, + }; + if(ncblit_rgba(rgba, dimx * 4, &vopts) == NULL){ free(rgba); return -1; } @@ -49,9 +53,8 @@ rotate_grad(struct notcurses* nc){ if(v == NULL){ return -1; } - struct ncvisual_options vopts = { - .n = n, - }; + vopts.leny = 0; + vopts.lenx = 0; if(n != ncvisual_render(nc, v, &vopts)){ ncvisual_destroy(v); return -1; @@ -161,8 +164,14 @@ rotate(struct notcurses* nc){ notcurses_render(nc); clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);; - if(ncplane_blit_rgba(n, dimy / 2, XSIZE, XSIZE * 4, NCBLIT_DEFAULT, - rgba, 0, 0, 4, XSIZE) < 0){ + struct ncvisual_options vopts = { + .lenx = XSIZE, + .leny = 4, + .y = dimy / 2, + .x = XSIZE, + .n = n, + }; + if(ncblit_rgba(rgba, XSIZE * 4, &vopts) == NULL){ free(rgba); return -1; } @@ -179,11 +188,8 @@ rotate(struct notcurses* nc){ if(v == NULL){ return -1; } - struct ncvisual_options vopts = { - .x = (dimx - XSIZE) / 2, - .y = dimy / 2, - .n = n, - }; + vopts.x = (dimx - XSIZE) / 2; + vopts.y = dimy / 2; ncvisual_render(nc, v, &vopts); notcurses_render(nc); clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);;