mirror of
https://github.com/dankamongmen/notcurses
synced 2025-03-09 17:19:03 -04:00
Open some whoopass on ncvisual rotation (#677)
Whip the ol' llama's ass (fix ncvisual rotation) * notcurses: flush cursor change requests #673 * rotator: verify ncplane_rgba and ncblit_rgba * ncblit: rename, accept ncblitter_e #674 * rotator: render from rgba * rotator: get to rotation * rotator: add a pi/4 turn at the end * normal: reuse incoming plane for rendering #672 * rotator poc: rotate a fullplane gradient #672 * normal demo: place visual correctly * rotator: verify ncplane_rgba and ncblit_rgba * ncblit: rename, accept ncblitter_e #674 * rotator: render from rgba * rotator: add a pi/4 turn at the end * normal: reuse incoming plane for rendering #672 * rotator poc: rotate a fullplane gradient #672 * normal demo: place visual correctly * rotator poc: throw some red into gradient * rotator poc: done #662 * oiio: ncvisual_resize() needs set ibuf pointer #662 * normal: only need erase at top of loop * visual poc: shorter delay * normal demo: center rendered visual * comment ncvisual_resize() call * ncvisual_rotate: call ncvisual_details_seed() * ffmpeg ncvisual: fix rotation #662
This commit is contained in:
parent
dbe779365b
commit
de23139111
6
NEWS.md
6
NEWS.md
@ -1,6 +1,12 @@
|
||||
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.4.1 (2020-06-01)
|
||||
* Got the `ncvisual` API ready for API freeze: `ncvisual_render()` and
|
||||
`ncvisual_stream()` now take a `struct ncvisual_options`. `ncstyle_e`
|
||||
|
12
USAGE.md
12
USAGE.md
@ -1253,17 +1253,17 @@ Raw streams of RGBA or BGRx data can be blitted directly to an ncplane:
|
||||
// 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 ncblit_bgrx(struct ncplane* nc, int placey, int placex, int linesize,
|
||||
const unsigned char* data, int begy, int begx,
|
||||
int leny, int 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 '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 ncblit_rgba(struct ncplane* nc, int placey, int placex, int linesize,
|
||||
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);
|
||||
```
|
||||
|
||||
|
||||
|
@ -128,9 +128,9 @@ notcurses_plane - operations on ncplanes
|
||||
|
||||
**void ncplane_greyscale(struct ncplane* n);**
|
||||
|
||||
**int ncblit_bgrx(struct ncplane* nc, int placey, int placex, int linesize, const unsigned char* data, int begy, int begx, int leny, int 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);**
|
||||
|
||||
**int ncblit_rgba(struct ncplane* nc, int placey, int placex, int linesize, 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);**
|
||||
|
||||
**int ncplane_destroy(struct ncplane* ncp);**
|
||||
|
||||
|
@ -1017,13 +1017,13 @@ namespace ncpp
|
||||
|
||||
bool blit_bgrx (int placey, int placex, int linesize, const void* data, int begy, int begx, int leny, int lenx) const NOEXCEPT_MAYBE
|
||||
{
|
||||
bool ret = ncblit_bgrx (plane, placey, placex, linesize, data, begy, begx, leny, lenx) < 0;
|
||||
bool ret = ncplane_blit_bgrx (plane, placey, placex, linesize, NCBLIT_DEFAULT, data, begy, begx, leny, lenx) < 0;
|
||||
return error_guard_cond<bool, bool> (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 ret = ncblit_rgba (plane, placey, placex, linesize, data, begy, begx, leny, lenx) < 0;
|
||||
bool ret = ncplane_blit_rgba (plane, placey, placex, linesize, NCBLIT_DEFAULT, data, begy, begx, leny, lenx) < 0;
|
||||
return error_guard_cond<bool, bool> (ret, ret);
|
||||
}
|
||||
|
||||
|
@ -2236,15 +2236,17 @@ API int ncvisual_stream(struct notcurses* nc, struct ncvisual* ncv,
|
||||
// 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 ncblit_bgrx(struct ncplane* nc, int placey, int placex, int linesize,
|
||||
const void* data, int begy, int begx, int leny, int 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 '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 ncblit_rgba(struct ncplane* nc, int placey, int placex, int linesize,
|
||||
const void* data, int begy, int begx, int leny, int 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);
|
||||
|
||||
// An ncreel is a notcurses region devoted to displaying zero or more
|
||||
// line-oriented, contained panels between which the user may navigate. If at
|
||||
|
@ -323,8 +323,8 @@ struct ncvisual_options {
|
||||
ncblitter_e blitter;
|
||||
uint64_t flags;
|
||||
};
|
||||
int ncblit_bgrx(struct ncplane* nc, int placey, int placex, int linesize, const unsigned char* data, int begy, int begx, int leny, int lenx);
|
||||
int ncblit_rgba(struct ncplane* nc, int placey, int placex, int linesize, const unsigned char* data, int begy, int begx, int leny, int 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);
|
||||
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 ncselector_item {
|
||||
char* option;
|
||||
char* desc;
|
||||
|
@ -53,21 +53,27 @@ rotate_visual(struct notcurses* nc, struct ncplane* n, int dy, int dx){
|
||||
ncvisual_destroy(ncv);
|
||||
return -1;
|
||||
}
|
||||
ncplane_erase(n);
|
||||
ncplane_destroy(n);
|
||||
int dimy, dimx;
|
||||
n = notcurses_stddim_yx(nc, &dimy, &dimx);
|
||||
bool failed = false;
|
||||
const int ROTATIONS = 128;
|
||||
timespec_div(&demodelay, ROTATIONS, &scaled);
|
||||
timespec_div(&demodelay, ROTATIONS / 8, &scaled);
|
||||
struct ncvisual_options vopts = {
|
||||
.n = n,
|
||||
};
|
||||
ncplane_erase(n);
|
||||
for(double i = 0 ; i < ROTATIONS ; ++i){
|
||||
demo_nanosleep(nc, &scaled);
|
||||
if(ncvisual_rotate(ncv, M_PI / 16)){
|
||||
if(ncvisual_rotate(ncv, M_PI / 2)){
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
ncplane_cursor_move_yx(n, 0, 0);
|
||||
if(ncvisual_render(nc, ncv, &vopts) == NULL){
|
||||
int vy, vx, vyscale, vxscale;
|
||||
ncvisual_geom(nc, ncv, NCBLIT_DEFAULT, &vy, &vx, &vyscale, &vxscale);
|
||||
vopts.x = (dimx - (vx / vxscale)) / 2;
|
||||
vopts.y = (dimy - (vy / vyscale)) / 2;
|
||||
struct ncplane* newn;
|
||||
if((newn = ncvisual_render(nc, ncv, &vopts)) == NULL){
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
@ -75,6 +81,7 @@ rotate_visual(struct notcurses* nc, struct ncplane* n, int dy, int dx){
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
ncplane_destroy(newn);
|
||||
}
|
||||
ncvisual_destroy(ncv);
|
||||
return failed ? -1 : 0;
|
||||
@ -117,7 +124,7 @@ int normal_demo(struct notcurses* nc){
|
||||
int r = -1;
|
||||
struct ncplane* nstd = notcurses_stddim_yx(nc, &dy, &dx);
|
||||
ncplane_erase(nstd);
|
||||
cell c = CELL_SIMPLE_INITIALIZER(' ');
|
||||
cell c = CELL_TRIVIAL_INITIALIZER;
|
||||
cell_set_fg_rgb(&c, 0xff, 0xff, 0xff);
|
||||
cell_set_bg_rgb(&c, 0xff, 0xff, 0xff);
|
||||
ncplane_set_base_cell(nstd, &c);
|
||||
@ -151,7 +158,7 @@ int normal_demo(struct notcurses* nc){
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
if(ncblit_rgba(nstd, 0, 0, dx * sizeof(*rgba), rgba, 0, 0, dy, dx) < 0){
|
||||
if(ncplane_blit_rgba(nstd, 0, 0, dx * sizeof(*rgba), NCBLIT_DEFAULT, rgba, 0, 0, dy, dx) < 0){
|
||||
goto err;
|
||||
}
|
||||
if( (r = demo_render(nc)) ){
|
||||
@ -191,7 +198,6 @@ int normal_demo(struct notcurses* nc){
|
||||
ncplane_set_base_cell(nstd, &c);
|
||||
cell_release(nstd, &c);
|
||||
bool failed = rotate_visual(nc, n, dy, dx);
|
||||
ncplane_destroy(n);
|
||||
return failed ? -1 : 0;
|
||||
|
||||
err:
|
||||
|
@ -447,25 +447,25 @@ const struct blitset notcurses_blitters[] = {
|
||||
// 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 ncblit_bgrx(ncplane* nc, int placey, int placex,
|
||||
int linesize, const void* data, int begy, int begx, int leny,
|
||||
int lenx){
|
||||
if(!nc->nc->utf8){
|
||||
return tria_blit_ascii(nc, placey, placex, linesize, data, begy, begx,
|
||||
leny, lenx, true, false);
|
||||
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);
|
||||
if(bset == NULL){
|
||||
return -1;
|
||||
}
|
||||
return tria_blit(nc, placey, placex, linesize, data, begy, begx,
|
||||
return bset->blit(nc, placey, placex, linesize, data, begy, begx,
|
||||
leny, lenx, true, false);
|
||||
}
|
||||
|
||||
int ncblit_rgba(ncplane* nc, int placey, int placex,
|
||||
int linesize, const void* data, int begy, int begx, int leny,
|
||||
int lenx){
|
||||
if(!nc->nc->utf8){
|
||||
return tria_blit_ascii(nc, placey, placex, linesize, data, begy, begx,
|
||||
leny, lenx, false, false);
|
||||
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);
|
||||
if(bset == NULL){
|
||||
return -1;
|
||||
}
|
||||
return tria_blit(nc, placey, placex, linesize, data, begy, begx,
|
||||
return bset->blit(nc, placey, placex, linesize, data, begy, begx,
|
||||
leny, lenx, false, false);
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,10 @@
|
||||
|
||||
static inline const struct blitset*
|
||||
lookup_blitset(const struct notcurses* nc, ncblitter_e setid, bool may_degrade) {
|
||||
if(setid == NCBLIT_DEFAULT){
|
||||
setid = NCBLIT_2x1;
|
||||
may_degrade = true;
|
||||
}
|
||||
// the only viable blitter in ASCII is NCBLIT_1x1
|
||||
if(!notcurses_canutf8(nc) && setid != NCBLIT_1x1){
|
||||
if(may_degrade){
|
||||
|
@ -170,14 +170,15 @@ nc_err_e ncvisual_decode(ncvisual* nc){
|
||||
|
||||
// resize frame to oframe, converting to RGBA (if necessary) along the way
|
||||
nc_err_e ncvisual_resize(ncvisual* nc, int rows, int cols) {
|
||||
if(nc->details.oframe){
|
||||
const int targformat = AV_PIX_FMT_RGBA;
|
||||
AVFrame* inf = nc->details.oframe ? nc->details.oframe : nc->details.frame;
|
||||
//fprintf(stderr, "got format: %d (%d/%d) want format: %d (%d/%d)\n", inf->format, nc->rows, nc->cols, targformat, rows, cols);
|
||||
if(inf->format == targformat && nc->rows == rows && nc->cols == cols){
|
||||
return NCERR_SUCCESS;
|
||||
}
|
||||
const int targformat = AV_PIX_FMT_RGBA;
|
||||
//fprintf(stderr, "got format: %d want format: %d\n", nc->details.frame->format, targformat);
|
||||
auto swsctx = sws_getContext(nc->details.frame->width,
|
||||
nc->details.frame->height,
|
||||
static_cast<AVPixelFormat>(nc->details.frame->format),
|
||||
auto swsctx = sws_getContext(inf->width,
|
||||
inf->height,
|
||||
static_cast<AVPixelFormat>(inf->format),
|
||||
cols, rows,
|
||||
static_cast<AVPixelFormat>(targformat),
|
||||
SWS_LANCZOS, nullptr, nullptr, nullptr);
|
||||
@ -185,42 +186,56 @@ nc_err_e ncvisual_resize(ncvisual* nc, int rows, int cols) {
|
||||
//fprintf(stderr, "Error retrieving swsctx\n");
|
||||
return NCERR_NOMEM;
|
||||
}
|
||||
if((nc->details.oframe = av_frame_alloc()) == nullptr){
|
||||
AVFrame* sframe;
|
||||
if((sframe = av_frame_alloc()) == nullptr){
|
||||
// fprintf(stderr, "Couldn't allocate frame for %s\n", filename);
|
||||
sws_freeContext(swsctx);
|
||||
return NCERR_NOMEM; // no need to free swsctx
|
||||
}
|
||||
memcpy(nc->details.oframe, nc->details.frame, sizeof(*nc->details.oframe));
|
||||
nc->details.oframe->format = targformat;
|
||||
nc->details.oframe->width = cols;
|
||||
nc->details.oframe->height = rows;
|
||||
//fprintf(stderr, "SIZE DECODED: %d %d (%d) (want %d %d)\n", nc->rows, nc->cols, nc->details.frame->linesize[0], rows, cols);
|
||||
int size = av_image_alloc(nc->details.oframe->data, nc->details.oframe->linesize,
|
||||
nc->details.oframe->width, nc->details.oframe->height,
|
||||
static_cast<AVPixelFormat>(nc->details.oframe->format),
|
||||
memcpy(sframe, inf, sizeof(*sframe));
|
||||
sframe->format = targformat;
|
||||
sframe->width = cols;
|
||||
sframe->height = rows;
|
||||
//fprintf(stderr, "SIZE DECODED: %d %d (%d) (want %d %d)\n", nc->rows, nc->cols, inf->linesize[0], rows, cols);
|
||||
int size = av_image_alloc(sframe->data, sframe->linesize,
|
||||
sframe->width, sframe->height,
|
||||
static_cast<AVPixelFormat>(sframe->format),
|
||||
IMGALLOCALIGN);
|
||||
if(size < 0){
|
||||
//fprintf(stderr, "Error allocating visual data (%d)\n", size);
|
||||
av_freep(&sframe);
|
||||
sws_freeContext(swsctx);
|
||||
return NCERR_NOMEM;
|
||||
}
|
||||
int height = sws_scale(swsctx, nc->details.frame->data,
|
||||
nc->details.frame->linesize, 0,
|
||||
nc->details.frame->height, nc->details.oframe->data,
|
||||
nc->details.oframe->linesize);
|
||||
int height = sws_scale(swsctx, inf->data,
|
||||
inf->linesize, 0,
|
||||
inf->height, sframe->data,
|
||||
sframe->linesize);
|
||||
sws_freeContext(swsctx);
|
||||
if(height < 0){
|
||||
//fprintf(stderr, "Error applying scaling (%s)\n", av_err2str(height));
|
||||
av_freep(sframe->data);
|
||||
av_freep(&sframe);
|
||||
return NCERR_DECODE;
|
||||
}
|
||||
const AVFrame* f = nc->details.oframe;
|
||||
const AVFrame* f = sframe;
|
||||
int bpp = av_get_bits_per_pixel(av_pix_fmt_desc_get(static_cast<AVPixelFormat>(f->format)));
|
||||
if(bpp != 32){
|
||||
//fprintf(stderr, "Bad bits-per-pixel (wanted 32, got %d)\n", bpp);
|
||||
av_freep(sframe->data);
|
||||
av_freep(&sframe);
|
||||
return NCERR_DECODE;
|
||||
}
|
||||
nc->rowstride = nc->details.oframe->linesize[0];
|
||||
nc->rowstride = sframe->linesize[0];
|
||||
nc->rows = rows;
|
||||
nc->cols = cols;
|
||||
ncvisual_set_data(nc, reinterpret_cast<uint32_t*>(nc->details.oframe->data[0]), true);
|
||||
ncvisual_set_data(nc, reinterpret_cast<uint32_t*>(sframe->data[0]), true);
|
||||
if(nc->details.oframe){
|
||||
//av_freep(nc->details.oframe->data);
|
||||
av_freep(&nc->details.oframe);
|
||||
}
|
||||
nc->details.oframe = sframe;
|
||||
|
||||
//fprintf(stderr, "SIZE SCALED: %d %d (%u)\n", nc->details.oframe->height, nc->details.oframe->width, nc->details.oframe->linesize[0]);
|
||||
return NCERR_SUCCESS;
|
||||
}
|
||||
@ -396,6 +411,7 @@ nc_err_e ncvisual_blit(ncvisual* ncv, int rows, int cols, ncplane* n,
|
||||
int begy, int begx, int leny, int lenx,
|
||||
bool blendcolors) {
|
||||
const AVFrame* inframe = ncv->details.oframe ? ncv->details.oframe : ncv->details.frame;
|
||||
//fprintf(stderr, "inframe: %p oframe: %p frame: %p\n", inframe, ncv->details.oframe, ncv->details.frame);
|
||||
void* data = nullptr;
|
||||
int stride = 0;
|
||||
AVFrame* sframe = nullptr;
|
||||
|
@ -100,6 +100,7 @@ nc_err_e ncvisual_resize(ncvisual* nc, int rows, int cols) {
|
||||
nc->rowstride = cols * 4;
|
||||
ncvisual_set_data(nc, static_cast<uint32_t*>(ibuf->localpixels()), false);
|
||||
//fprintf(stderr, "HAVE SOME NEW DATA: %p\n", ibuf->localpixels());
|
||||
nc->details.ibuf = std::move(ibuf);
|
||||
}
|
||||
return NCERR_SUCCESS;
|
||||
}
|
||||
|
@ -272,6 +272,7 @@ rotate_bounding_box(double stheta, double ctheta, int* leny, int* lenx,
|
||||
}
|
||||
|
||||
auto ncvisual_rotate(ncvisual* ncv, double rads) -> nc_err_e {
|
||||
// done to force conversion into RGBA
|
||||
nc_err_e err = ncvisual_resize(ncv, ncv->rows, ncv->cols);
|
||||
if(err != NCERR_SUCCESS){
|
||||
return err;
|
||||
@ -329,7 +330,7 @@ auto ncvisual_rotate(ncvisual* ncv, double rads) -> nc_err_e {
|
||||
ncv->cols = bbx;
|
||||
ncv->rows = bby;
|
||||
ncv->rowstride = bbx * 4;
|
||||
//ncplane_erase(ncv->ncp);
|
||||
ncvisual_details_seed(ncv);
|
||||
return NCERR_SUCCESS;
|
||||
}
|
||||
|
||||
@ -343,8 +344,8 @@ auto ncvisual_from_rgba(const void* rgba, int rows, int rowstride,
|
||||
ncv->rowstride = rowstride;
|
||||
ncv->cols = cols;
|
||||
ncv->rows = rows;
|
||||
//fprintf(stderr, "MADE INITIAL ONE %d/%d\n", disprows, ncv->cols);
|
||||
auto data = static_cast<uint32_t*>(memdup(rgba, rowstride * ncv->rows));
|
||||
//fprintf(stderr, "COPY US %zu (%d)\n", rowstride * ncv->rows, ncv->rows);
|
||||
if(data == nullptr){
|
||||
ncvisual_destroy(ncv);
|
||||
return nullptr;
|
||||
@ -390,7 +391,7 @@ auto ncvisual_render(notcurses* nc, ncvisual* ncv,
|
||||
if(begy < 0 || begx < 0 || lenx < -1 || leny < -1){
|
||||
return nullptr;
|
||||
}
|
||||
//fprintf(stderr, "OUR DATA: %p cols/rows: %d/%d\n", ncv->data, ncv->cols, ncv->rows);
|
||||
//fprintf(stderr, "OUR DATA: %p rows/cols: %d/%d\n", ncv->data, ncv->rows, ncv->cols);
|
||||
if(ncv->data == nullptr){
|
||||
return nullptr;
|
||||
}
|
||||
@ -442,6 +443,7 @@ auto ncvisual_render(notcurses* nc, ncvisual* ncv,
|
||||
}else{
|
||||
return nullptr;
|
||||
}
|
||||
//fprintf(stderr, "PLACING NEW PLANE: %d/%d @ %d/%d\n", disprows, dispcols, placey, placex);
|
||||
n = ncplane_new(nc, disprows, dispcols, placey, placex, nullptr);
|
||||
if(n == nullptr){
|
||||
return nullptr;
|
||||
@ -483,9 +485,9 @@ auto ncvisual_from_plane(const ncplane* n, int begy, int begx,
|
||||
lenx = n->lenx - begx;
|
||||
}
|
||||
if(leny == -1){
|
||||
leny = n->leny - begy;
|
||||
leny = (n->leny - begy);
|
||||
}
|
||||
auto* ncv = ncvisual_from_rgba(rgba, leny, lenx * 4, lenx);
|
||||
auto* ncv = ncvisual_from_rgba(rgba, leny * 2, lenx * 4, lenx);
|
||||
free(rgba);
|
||||
if(ncv == nullptr){
|
||||
return nullptr;
|
||||
|
231
src/poc/rotator.c
Normal file
231
src/poc/rotator.c
Normal file
@ -0,0 +1,231 @@
|
||||
#include <math.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <locale.h>
|
||||
#include <notcurses/notcurses.h>
|
||||
|
||||
static int
|
||||
rotate_grad(struct notcurses* nc){
|
||||
struct timespec ts = {
|
||||
.tv_sec = 0,
|
||||
.tv_nsec = 750000000,
|
||||
};
|
||||
int dimy, dimx;
|
||||
struct ncplane* n = notcurses_stddim_yx(nc, &dimy, &dimx);
|
||||
ncplane_cursor_move_yx(n, 0, 0);
|
||||
uint64_t tl = 0, tr = 0, bl = 0, br = 0;
|
||||
channels_set_fg_rgb(&tl, 0xff, 0, 0);
|
||||
channels_set_fg_rgb(&tr, 0, 0, 0xff);
|
||||
channels_set_fg_rgb(&bl, 0, 0xff, 0);
|
||||
channels_set_fg_rgb(&br, 0, 0xff, 0xff);
|
||||
channels_set_bg_rgb(&tl, 0xff, 0, 0);
|
||||
channels_set_bg_rgb(&tr, 0, 0xff, 0);
|
||||
channels_set_bg_rgb(&bl, 0, 0, 0xff);
|
||||
channels_set_bg_rgb(&br, 0, 0xff, 0xff);
|
||||
if(ncplane_highgradient(n, tl, tr, bl, br, dimy - 1, dimx - 1) <= 0){
|
||||
return -1;
|
||||
}
|
||||
notcurses_render(nc);
|
||||
clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);
|
||||
uint32_t* rgba = ncplane_rgba(n, 0, 0, dimy, dimx);
|
||||
if(rgba == NULL){
|
||||
return -1;
|
||||
}
|
||||
ncplane_erase(n);
|
||||
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){
|
||||
free(rgba);
|
||||
return -1;
|
||||
}
|
||||
notcurses_render(nc);
|
||||
clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);;
|
||||
|
||||
ncplane_erase(n);
|
||||
notcurses_render(nc);
|
||||
clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);;
|
||||
|
||||
// now promote it to a visual
|
||||
struct ncvisual* v = ncvisual_from_rgba(rgba, dimy * 2, dimx * 4, dimx);
|
||||
free(rgba);
|
||||
if(v == NULL){
|
||||
return -1;
|
||||
}
|
||||
struct ncvisual_options vopts = {
|
||||
.n = n,
|
||||
};
|
||||
if(n != ncvisual_render(nc, v, &vopts)){
|
||||
ncvisual_destroy(v);
|
||||
return -1;
|
||||
}
|
||||
notcurses_render(nc);
|
||||
clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);;
|
||||
vopts.n = NULL;
|
||||
ncplane_erase(n);
|
||||
for(int i = 0 ; i < 4 ; ++i){
|
||||
int vy, vx, scaley, scalex;
|
||||
if(NCERR_SUCCESS != ncvisual_rotate(v, M_PI / 2)){
|
||||
return -1;
|
||||
}
|
||||
ncvisual_geom(nc, v, NCBLIT_DEFAULT, &vy, &vx, &scaley, &scalex);
|
||||
vopts.x = (dimx - (vx / scalex)) / 2;
|
||||
vopts.y = (dimy - (vy / scaley)) / 2;
|
||||
struct ncplane* newn = ncvisual_render(nc, v, &vopts);
|
||||
if(newn == NULL){
|
||||
return -1;
|
||||
}
|
||||
notcurses_render(nc);
|
||||
ncplane_destroy(newn);
|
||||
clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);;
|
||||
}
|
||||
|
||||
for(int i = 0 ; i < 8 ; ++i){
|
||||
int vy, vx, scaley, scalex;
|
||||
ncvisual_geom(nc, v, NCBLIT_DEFAULT, &vy, &vx, &scaley, &scalex);
|
||||
vopts.x = (dimx - (vx / scalex)) / 2;
|
||||
vopts.y = (dimy - (vy / scaley)) / 2;
|
||||
if(NCERR_SUCCESS != ncvisual_rotate(v, M_PI / 4)){
|
||||
return -1;
|
||||
}
|
||||
ncplane_erase(n);
|
||||
struct ncplane* newn = ncvisual_render(nc, v, &vopts);
|
||||
if(newn == NULL){
|
||||
return -1;
|
||||
}
|
||||
notcurses_render(nc);
|
||||
ncplane_destroy(newn);
|
||||
clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);;
|
||||
}
|
||||
|
||||
ncvisual_destroy(v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
rotate(struct notcurses* nc){
|
||||
struct timespec ts = {
|
||||
.tv_sec = 0,
|
||||
.tv_nsec = 250000000,
|
||||
};
|
||||
const int XSIZE = 16;
|
||||
int dimy, dimx;
|
||||
struct ncplane* n = notcurses_stddim_yx(nc, &dimy, &dimx);
|
||||
if(dimy < XSIZE || dimx < 2){
|
||||
return -1;
|
||||
}
|
||||
int r = 255;
|
||||
int g = 0;
|
||||
int b = 0;
|
||||
for(int x = 0 ; x < XSIZE ; ++x){
|
||||
if(ncplane_set_fg_rgb(n, r, g, b)){
|
||||
return -1;
|
||||
}
|
||||
if(ncplane_set_bg_rgb(n, b, r, g)){
|
||||
return -1;
|
||||
}
|
||||
if(ncplane_putegc_yx(n, dimy / 2, x, "▀", NULL) < 0){
|
||||
return -1;
|
||||
}
|
||||
g += 15;
|
||||
r -= 14;
|
||||
}
|
||||
g = 0;
|
||||
b = 255;
|
||||
for(int x = 0 ; x < XSIZE ; ++x){
|
||||
if(ncplane_set_fg_rgb(n, r, g, b)){
|
||||
return -1;
|
||||
}
|
||||
if(ncplane_set_bg_rgb(n, b, r, g)){
|
||||
return -1;
|
||||
}
|
||||
if(ncplane_putegc_yx(n, dimy / 2 + 1, x, "▄", NULL) < 0){
|
||||
return -1;
|
||||
}
|
||||
g += 14;
|
||||
b -= 15;
|
||||
}
|
||||
notcurses_render(nc);
|
||||
clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);;
|
||||
|
||||
// we now have 2 rows of 20 cells each, with gradients. load 'em.
|
||||
uint32_t* rgba = ncplane_rgba(n, dimy / 2, 0, 2, XSIZE);
|
||||
if(rgba == NULL){
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
for(int y = 0 ; y < 4 ; ++y){
|
||||
for(int x = 0 ; x < XSIZE ; ++x){
|
||||
fprintf(stderr, "rgba %02d/%02d: %08x\n", y, x, rgba[y * XSIZE + x]);
|
||||
}
|
||||
}
|
||||
*/
|
||||
ncplane_erase(n);
|
||||
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){
|
||||
free(rgba);
|
||||
return -1;
|
||||
}
|
||||
notcurses_render(nc);
|
||||
clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);;
|
||||
|
||||
ncplane_erase(n);
|
||||
notcurses_render(nc);
|
||||
clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);;
|
||||
|
||||
// now promote it to a visual
|
||||
struct ncvisual* v = ncvisual_from_rgba(rgba, 4, XSIZE * 4, XSIZE);
|
||||
free(rgba);
|
||||
if(v == NULL){
|
||||
return -1;
|
||||
}
|
||||
struct ncvisual_options vopts = {
|
||||
.x = (dimx - XSIZE) / 2,
|
||||
.y = dimy / 2,
|
||||
.n = n,
|
||||
};
|
||||
ncvisual_render(nc, v, &vopts);
|
||||
notcurses_render(nc);
|
||||
clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);;
|
||||
|
||||
for(int i = 0 ; i < 4 ; ++i){
|
||||
if(NCERR_SUCCESS != ncvisual_rotate(v, M_PI / 2)){
|
||||
return -1;
|
||||
}
|
||||
ncplane_erase(n);
|
||||
ncvisual_render(nc, v, &vopts);
|
||||
notcurses_render(nc);
|
||||
clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);;
|
||||
}
|
||||
|
||||
for(int i = 0 ; i < 8 ; ++i){
|
||||
if(NCERR_SUCCESS != ncvisual_rotate(v, M_PI / 4)){
|
||||
return -1;
|
||||
}
|
||||
ncplane_erase(n);
|
||||
ncvisual_render(nc, v, &vopts);
|
||||
notcurses_render(nc);
|
||||
clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);;
|
||||
}
|
||||
|
||||
ncvisual_destroy(v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(void){
|
||||
setlocale(LC_ALL, "");
|
||||
struct notcurses_options nopts = {
|
||||
.inhibit_alternate_screen = true,
|
||||
.flags = NCOPTION_INHIBIT_SETLOCALE,
|
||||
};
|
||||
struct notcurses* nc = notcurses_init(&nopts, NULL);
|
||||
int r = 0;
|
||||
r |= rotate(nc);
|
||||
r |= rotate_grad(nc);
|
||||
r |= notcurses_stop(nc);
|
||||
return r ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||
}
|
@ -7,6 +7,10 @@
|
||||
#include <notcurses/notcurses.h>
|
||||
|
||||
int main(int argc, char** argv){
|
||||
struct timespec ts = {
|
||||
.tv_sec = 0,
|
||||
.tv_nsec = 250000000,
|
||||
};
|
||||
const char* file = "../data/changes.jpg";
|
||||
setlocale(LC_ALL, "");
|
||||
if(argc > 2){
|
||||
@ -17,6 +21,7 @@ int main(int argc, char** argv){
|
||||
}
|
||||
notcurses_options opts{};
|
||||
opts.inhibit_alternate_screen = true;
|
||||
opts.loglevel = NCLOGLEVEL_TRACE;
|
||||
opts.flags = NCOPTION_INHIBIT_SETLOCALE;
|
||||
struct notcurses* nc;
|
||||
if((nc = notcurses_init(&opts, nullptr)) == nullptr){
|
||||
@ -43,7 +48,9 @@ int main(int argc, char** argv){
|
||||
if(notcurses_render(nc)){
|
||||
goto err;
|
||||
}
|
||||
sleep(1);
|
||||
clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);
|
||||
|
||||
ncplane_erase(n);
|
||||
ncvisual_geom(nc, ncv, NCBLIT_DEFAULT, nullptr, nullptr, &scaley, &scalex);
|
||||
ncvisual_resize(ncv, dimy * scaley, dimx * scalex);
|
||||
vopts.n = n;
|
||||
@ -53,21 +60,31 @@ int main(int argc, char** argv){
|
||||
if(notcurses_render(nc)){
|
||||
goto err;
|
||||
}
|
||||
clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);
|
||||
|
||||
vopts.n = NULL;
|
||||
ncplane_destroy(n);
|
||||
for(double i = 0 ; i < 256 ; ++i){
|
||||
sleep(1);
|
||||
if(ncvisual_rotate(ncv, M_PI / 2)){
|
||||
clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);
|
||||
if(ncvisual_rotate(ncv, M_PI / ((i / 32) + 2))){
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
ncplane_erase(n);
|
||||
if(ncvisual_render(nc, ncv, &vopts) == nullptr){
|
||||
int vy, vx;
|
||||
ncvisual_geom(nc, ncv, NCBLIT_DEFAULT, &vy, &vx, &scaley, &scalex);
|
||||
vopts.x = (dimx - (vx / scalex)) / 2;
|
||||
vopts.y = (dimy - (vy / scaley)) / 2;
|
||||
struct ncplane* newn;
|
||||
if((newn = ncvisual_render(nc, ncv, &vopts)) == nullptr){
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
if(notcurses_render(nc)){
|
||||
ncplane_destroy(newn);
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
ncplane_destroy(newn);
|
||||
}
|
||||
ncvisual_destroy(ncv);
|
||||
return notcurses_stop(nc) || failed ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||
|
Loading…
x
Reference in New Issue
Block a user