You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
notcurses/tests/visual.cpp

652 lines
21 KiB
C++

#include "main.h"
#include <vector>
TEST_CASE("Visual") {
auto nc_ = testing_notcurses();
REQUIRE(nullptr != nc_);
ncplane* ncp_ = notcurses_stdplane(nc_);
REQUIRE(ncp_);
auto n_ = notcurses_stdplane(nc_);
REQUIRE(n_);
#ifndef NOTCURSES_USE_MULTIMEDIA
SUBCASE("VisualDisabled"){
REQUIRE(!notcurses_canopen_images(nc_));
REQUIRE(!notcurses_canopen_videos(nc_));
}
#else
SUBCASE("ImagesEnabled"){
REQUIRE(notcurses_canopen_images(nc_));
}
SUBCASE("LoadImageCreatePlane") {
int dimy, dimx;
ncplane_dim_yx(ncp_, &dimy, &dimx);
auto ncv = ncvisual_from_file(find_data("changes.jpg"));
REQUIRE(ncv);
/*CHECK(dimy * 2 == frame->height);
CHECK(dimx == frame->width); FIXME */
Fully general ncvisual layer (#647) This represents an essentially complete rewrite of ncvisual and associated code. It had two major goals: Improve the ncvisual API based off lessons learned, pursuant to the upcoming API freeze. In particular, I wanted to: decouple ncvisuals from ncplanes. It should be possible to render a ncvisual to multiple planes, with different scaling each time. It should be possible to create an ncvisual without a plane, etc. normalize the various ways of constructing an ncvisual -- file, memory, plane, etc. Support multiple blitters, from 7-bit ASCII to Sixel. This required writing the blitters in several cases, and they're not yet in their final implementations (but the API is fine) I have not yet unified Plots and Visuals, and might not, given that the Plot code works fine. We could at this point implement Plots in terms of Visuals, though -- the blitter backend range has been unified. Sixel is not yet implemented, though it is listed. There is a new POC tool, blitter. It renders its arguments using all possible blitter+scaling combinations. Another new POC, resize, displays its argument, then resizes it to the screen size and displays that, explicitly making use of ncvisual_resize() rather than a scaling parameter to ncvisual_render(). This also eliminates some memory leaks and bugs we were seeing in trunk, and brings in Sixel scaffolding. The C++ wrapper will also need patching back up; I cut most of it down while wrestling with this crap, urk. Closes #638, #562, and #622.
4 years ago
struct ncvisual_options opts{};
opts.scaling = NCSCALE_STRETCH;
auto newn = ncvisual_render(nc_, ncv, &opts);
CHECK(newn);
CHECK(0 == notcurses_render(nc_));
CHECK(1 == ncvisual_decode(ncv));
Fully general ncvisual layer (#647) This represents an essentially complete rewrite of ncvisual and associated code. It had two major goals: Improve the ncvisual API based off lessons learned, pursuant to the upcoming API freeze. In particular, I wanted to: decouple ncvisuals from ncplanes. It should be possible to render a ncvisual to multiple planes, with different scaling each time. It should be possible to create an ncvisual without a plane, etc. normalize the various ways of constructing an ncvisual -- file, memory, plane, etc. Support multiple blitters, from 7-bit ASCII to Sixel. This required writing the blitters in several cases, and they're not yet in their final implementations (but the API is fine) I have not yet unified Plots and Visuals, and might not, given that the Plot code works fine. We could at this point implement Plots in terms of Visuals, though -- the blitter backend range has been unified. Sixel is not yet implemented, though it is listed. There is a new POC tool, blitter. It renders its arguments using all possible blitter+scaling combinations. Another new POC, resize, displays its argument, then resizes it to the screen size and displays that, explicitly making use of ncvisual_resize() rather than a scaling parameter to ncvisual_render(). This also eliminates some memory leaks and bugs we were seeing in trunk, and brings in Sixel scaffolding. The C++ wrapper will also need patching back up; I cut most of it down while wrestling with this crap, urk. Closes #638, #562, and #622.
4 years ago
ncplane_destroy(newn);
ncvisual_destroy(ncv);
}
SUBCASE("LoadImage") {
int dimy, dimx;
ncplane_dim_yx(ncp_, &dimy, &dimx);
auto ncv = ncvisual_from_file(find_data("changes.jpg"));
REQUIRE(ncv);
/*CHECK(dimy * 2 == frame->height);
CHECK(dimx == frame->width); FIXME */
Fully general ncvisual layer (#647) This represents an essentially complete rewrite of ncvisual and associated code. It had two major goals: Improve the ncvisual API based off lessons learned, pursuant to the upcoming API freeze. In particular, I wanted to: decouple ncvisuals from ncplanes. It should be possible to render a ncvisual to multiple planes, with different scaling each time. It should be possible to create an ncvisual without a plane, etc. normalize the various ways of constructing an ncvisual -- file, memory, plane, etc. Support multiple blitters, from 7-bit ASCII to Sixel. This required writing the blitters in several cases, and they're not yet in their final implementations (but the API is fine) I have not yet unified Plots and Visuals, and might not, given that the Plot code works fine. We could at this point implement Plots in terms of Visuals, though -- the blitter backend range has been unified. Sixel is not yet implemented, though it is listed. There is a new POC tool, blitter. It renders its arguments using all possible blitter+scaling combinations. Another new POC, resize, displays its argument, then resizes it to the screen size and displays that, explicitly making use of ncvisual_resize() rather than a scaling parameter to ncvisual_render(). This also eliminates some memory leaks and bugs we were seeing in trunk, and brings in Sixel scaffolding. The C++ wrapper will also need patching back up; I cut most of it down while wrestling with this crap, urk. Closes #638, #562, and #622.
4 years ago
struct ncvisual_options opts{};
opts.scaling = NCSCALE_STRETCH;
opts.n = ncp_;
CHECK(ncvisual_render(nc_, ncv, &opts));
CHECK(0 == notcurses_render(nc_));
CHECK(1 == ncvisual_decode(ncv));
ncvisual_destroy(ncv);
}
SUBCASE("PlaneDuplicate") {
int dimy, dimx;
ncplane_dim_yx(ncp_, &dimy, &dimx);
auto ncv = ncvisual_from_file(find_data("changes.jpg"));
REQUIRE(ncv);
/*CHECK(dimy * 2 == frame->height);
CHECK(dimx == frame->width); FIXME */
Fully general ncvisual layer (#647) This represents an essentially complete rewrite of ncvisual and associated code. It had two major goals: Improve the ncvisual API based off lessons learned, pursuant to the upcoming API freeze. In particular, I wanted to: decouple ncvisuals from ncplanes. It should be possible to render a ncvisual to multiple planes, with different scaling each time. It should be possible to create an ncvisual without a plane, etc. normalize the various ways of constructing an ncvisual -- file, memory, plane, etc. Support multiple blitters, from 7-bit ASCII to Sixel. This required writing the blitters in several cases, and they're not yet in their final implementations (but the API is fine) I have not yet unified Plots and Visuals, and might not, given that the Plot code works fine. We could at this point implement Plots in terms of Visuals, though -- the blitter backend range has been unified. Sixel is not yet implemented, though it is listed. There is a new POC tool, blitter. It renders its arguments using all possible blitter+scaling combinations. Another new POC, resize, displays its argument, then resizes it to the screen size and displays that, explicitly making use of ncvisual_resize() rather than a scaling parameter to ncvisual_render(). This also eliminates some memory leaks and bugs we were seeing in trunk, and brings in Sixel scaffolding. The C++ wrapper will also need patching back up; I cut most of it down while wrestling with this crap, urk. Closes #638, #562, and #622.
4 years ago
struct ncvisual_options opts{};
opts.n = ncp_;
opts.scaling = NCSCALE_STRETCH;
CHECK(ncvisual_render(nc_, ncv, &opts));
void* needle = malloc(1);
REQUIRE(nullptr != needle);
Fully general ncvisual layer (#647) This represents an essentially complete rewrite of ncvisual and associated code. It had two major goals: Improve the ncvisual API based off lessons learned, pursuant to the upcoming API freeze. In particular, I wanted to: decouple ncvisuals from ncplanes. It should be possible to render a ncvisual to multiple planes, with different scaling each time. It should be possible to create an ncvisual without a plane, etc. normalize the various ways of constructing an ncvisual -- file, memory, plane, etc. Support multiple blitters, from 7-bit ASCII to Sixel. This required writing the blitters in several cases, and they're not yet in their final implementations (but the API is fine) I have not yet unified Plots and Visuals, and might not, given that the Plot code works fine. We could at this point implement Plots in terms of Visuals, though -- the blitter backend range has been unified. Sixel is not yet implemented, though it is listed. There is a new POC tool, blitter. It renders its arguments using all possible blitter+scaling combinations. Another new POC, resize, displays its argument, then resizes it to the screen size and displays that, explicitly making use of ncvisual_resize() rather than a scaling parameter to ncvisual_render(). This also eliminates some memory leaks and bugs we were seeing in trunk, and brings in Sixel scaffolding. The C++ wrapper will also need patching back up; I cut most of it down while wrestling with this crap, urk. Closes #638, #562, and #622.
4 years ago
struct ncplane* newn = ncplane_dup(ncp_, needle);
int ndimx, ndimy;
REQUIRE(nullptr != newn);
ncvisual_destroy(ncv);
ncplane_erase(ncp_);
// should still have the image
CHECK(0 == notcurses_render(nc_));
ncplane_dim_yx(newn, &ndimy, &ndimx);
CHECK(ndimy == dimy);
CHECK(ndimx == dimx);
}
SUBCASE("LoadVideoASCII") {
if(notcurses_canopen_videos(nc_)){
int dimy, dimx;
ncplane_dim_yx(ncp_, &dimy, &dimx);
auto ncv = ncvisual_from_file(find_data("notcursesII.mkv"));
REQUIRE(ncv);
for(;;){ // run at the highest speed we can
int ret = ncvisual_decode(ncv);
if(1 == ret){
break;
}
CHECK(0 == ret);
Fully general ncvisual layer (#647) This represents an essentially complete rewrite of ncvisual and associated code. It had two major goals: Improve the ncvisual API based off lessons learned, pursuant to the upcoming API freeze. In particular, I wanted to: decouple ncvisuals from ncplanes. It should be possible to render a ncvisual to multiple planes, with different scaling each time. It should be possible to create an ncvisual without a plane, etc. normalize the various ways of constructing an ncvisual -- file, memory, plane, etc. Support multiple blitters, from 7-bit ASCII to Sixel. This required writing the blitters in several cases, and they're not yet in their final implementations (but the API is fine) I have not yet unified Plots and Visuals, and might not, given that the Plot code works fine. We could at this point implement Plots in terms of Visuals, though -- the blitter backend range has been unified. Sixel is not yet implemented, though it is listed. There is a new POC tool, blitter. It renders its arguments using all possible blitter+scaling combinations. Another new POC, resize, displays its argument, then resizes it to the screen size and displays that, explicitly making use of ncvisual_resize() rather than a scaling parameter to ncvisual_render(). This also eliminates some memory leaks and bugs we were seeing in trunk, and brings in Sixel scaffolding. The C++ wrapper will also need patching back up; I cut most of it down while wrestling with this crap, urk. Closes #638, #562, and #622.
4 years ago
struct ncvisual_options opts{};
opts.scaling = NCSCALE_STRETCH;
opts.n = ncp_;
opts.blitter = NCBLIT_1x1;
CHECK(ncvisual_render(nc_, ncv, &opts));
CHECK(0 == notcurses_render(nc_));
}
ncvisual_destroy(ncv);
}
}
SUBCASE("LoadVideoHalfblocks") {
if(notcurses_canopen_videos(nc_)){
int dimy, dimx;
ncplane_dim_yx(ncp_, &dimy, &dimx);
auto ncv = ncvisual_from_file(find_data("notcursesII.mkv"));
REQUIRE(ncv);
for(;;){ // run at the highest speed we can
int ret = ncvisual_decode(ncv);
if(1 == ret){
break;
}
CHECK(0 == ret);
struct ncvisual_options opts{};
opts.scaling = NCSCALE_STRETCH;
opts.n = ncp_;
opts.blitter = NCBLIT_2x1;
CHECK(ncvisual_render(nc_, ncv, &opts));
CHECK(0 == notcurses_render(nc_));
}
ncvisual_destroy(ncv);
}
}
// quadblitter is default for NCSCALE_STRETCH
SUBCASE("LoadVideoQuadblitter") {
if(notcurses_canopen_videos(nc_)){
int dimy, dimx;
ncplane_dim_yx(ncp_, &dimy, &dimx);
auto ncv = ncvisual_from_file(find_data("notcursesII.mkv"));
REQUIRE(ncv);
for(;;){ // run at the highest speed we can
int ret = ncvisual_decode(ncv);
if(1 == ret){
break;
}
CHECK(0 == ret);
struct ncvisual_options opts{};
opts.scaling = NCSCALE_STRETCH;
opts.n = ncp_;
opts.blitter = NCBLIT_2x2;
CHECK(ncvisual_render(nc_, ncv, &opts));
CHECK(0 == notcurses_render(nc_));
}
ncvisual_destroy(ncv);
}
}
SUBCASE("LoadVideoSexblitter") {
if(notcurses_canopen_videos(nc_)){
int dimy, dimx;
ncplane_dim_yx(ncp_, &dimy, &dimx);
auto ncv = ncvisual_from_file(find_data("notcursesII.mkv"));
REQUIRE(ncv);
for(;;){ // run at the highest speed we can
int ret = ncvisual_decode(ncv);
if(1 == ret){
break;
}
CHECK(0 == ret);
struct ncvisual_options opts{};
opts.scaling = NCSCALE_STRETCH;
opts.n = ncp_;
opts.blitter = NCBLIT_3x2;
CHECK(ncvisual_render(nc_, ncv, &opts));
CHECK(0 == notcurses_render(nc_));
}
ncvisual_destroy(ncv);
}
}
SUBCASE("LoadVideoBraille") {
if(notcurses_canopen_videos(nc_)){
int dimy, dimx;
ncplane_dim_yx(ncp_, &dimy, &dimx);
auto ncv = ncvisual_from_file(find_data("notcursesII.mkv"));
REQUIRE(ncv);
for(;;){ // run at the highest speed we can
int ret = ncvisual_decode(ncv);
if(1 == ret){
break;
}
CHECK(0 == ret);
struct ncvisual_options opts{};
opts.scaling = NCSCALE_STRETCH;
opts.n = ncp_;
opts.blitter = NCBLIT_BRAILLE;
Fully general ncvisual layer (#647) This represents an essentially complete rewrite of ncvisual and associated code. It had two major goals: Improve the ncvisual API based off lessons learned, pursuant to the upcoming API freeze. In particular, I wanted to: decouple ncvisuals from ncplanes. It should be possible to render a ncvisual to multiple planes, with different scaling each time. It should be possible to create an ncvisual without a plane, etc. normalize the various ways of constructing an ncvisual -- file, memory, plane, etc. Support multiple blitters, from 7-bit ASCII to Sixel. This required writing the blitters in several cases, and they're not yet in their final implementations (but the API is fine) I have not yet unified Plots and Visuals, and might not, given that the Plot code works fine. We could at this point implement Plots in terms of Visuals, though -- the blitter backend range has been unified. Sixel is not yet implemented, though it is listed. There is a new POC tool, blitter. It renders its arguments using all possible blitter+scaling combinations. Another new POC, resize, displays its argument, then resizes it to the screen size and displays that, explicitly making use of ncvisual_resize() rather than a scaling parameter to ncvisual_render(). This also eliminates some memory leaks and bugs we were seeing in trunk, and brings in Sixel scaffolding. The C++ wrapper will also need patching back up; I cut most of it down while wrestling with this crap, urk. Closes #638, #562, and #622.
4 years ago
CHECK(ncvisual_render(nc_, ncv, &opts));
CHECK(0 == notcurses_render(nc_));
}
ncvisual_destroy(ncv);
}
}
SUBCASE("LoopVideo") {
if(notcurses_canopen_videos(nc_)){
int dimy, dimx;
ncplane_dim_yx(ncp_, &dimy, &dimx);
auto ncv = ncvisual_from_file(find_data("notcursesII.mkv"));
REQUIRE(ncv);
int ret;
while((ret = ncvisual_decode(ncv)) == 0){
;
}
// FIXME verify that it is last frame?
CHECK(1 == ret);
ret = ncvisual_decode_loop(ncv);
CHECK(1 == ret);
struct ncplane* ncp = ncvisual_render(nc_, ncv, nullptr);
CHECK(nullptr != ncp);
ncplane_destroy(ncp);
// FIXME verify that it is first frame, not last?
ret = ncvisual_decode_loop(ncv);
CHECK(0 == ret);
ncp = ncvisual_render(nc_, ncv, nullptr);
CHECK(nullptr != ncp);
ncplane_destroy(ncp);
ncvisual_destroy(ncv);
}
}
SUBCASE("LoadVideoCreatePlane") {
if(notcurses_canopen_videos(nc_)){
int dimy, dimx;
ncplane_dim_yx(ncp_, &dimy, &dimx);
auto ncv = ncvisual_from_file(find_data("notcursesII.mkv"));
REQUIRE(ncv);
CHECK(0 == ncvisual_decode(ncv));
/*CHECK(dimy * 2 == frame->height);
CHECK(dimx == frame->width); FIXME */
Fully general ncvisual layer (#647) This represents an essentially complete rewrite of ncvisual and associated code. It had two major goals: Improve the ncvisual API based off lessons learned, pursuant to the upcoming API freeze. In particular, I wanted to: decouple ncvisuals from ncplanes. It should be possible to render a ncvisual to multiple planes, with different scaling each time. It should be possible to create an ncvisual without a plane, etc. normalize the various ways of constructing an ncvisual -- file, memory, plane, etc. Support multiple blitters, from 7-bit ASCII to Sixel. This required writing the blitters in several cases, and they're not yet in their final implementations (but the API is fine) I have not yet unified Plots and Visuals, and might not, given that the Plot code works fine. We could at this point implement Plots in terms of Visuals, though -- the blitter backend range has been unified. Sixel is not yet implemented, though it is listed. There is a new POC tool, blitter. It renders its arguments using all possible blitter+scaling combinations. Another new POC, resize, displays its argument, then resizes it to the screen size and displays that, explicitly making use of ncvisual_resize() rather than a scaling parameter to ncvisual_render(). This also eliminates some memory leaks and bugs we were seeing in trunk, and brings in Sixel scaffolding. The C++ wrapper will also need patching back up; I cut most of it down while wrestling with this crap, urk. Closes #638, #562, and #622.
4 years ago
struct ncvisual_options opts{};
opts.scaling = NCSCALE_STRETCH;
auto newn = ncvisual_render(nc_, ncv, &opts);
CHECK(newn);
CHECK(0 == notcurses_render(nc_));
Fully general ncvisual layer (#647) This represents an essentially complete rewrite of ncvisual and associated code. It had two major goals: Improve the ncvisual API based off lessons learned, pursuant to the upcoming API freeze. In particular, I wanted to: decouple ncvisuals from ncplanes. It should be possible to render a ncvisual to multiple planes, with different scaling each time. It should be possible to create an ncvisual without a plane, etc. normalize the various ways of constructing an ncvisual -- file, memory, plane, etc. Support multiple blitters, from 7-bit ASCII to Sixel. This required writing the blitters in several cases, and they're not yet in their final implementations (but the API is fine) I have not yet unified Plots and Visuals, and might not, given that the Plot code works fine. We could at this point implement Plots in terms of Visuals, though -- the blitter backend range has been unified. Sixel is not yet implemented, though it is listed. There is a new POC tool, blitter. It renders its arguments using all possible blitter+scaling combinations. Another new POC, resize, displays its argument, then resizes it to the screen size and displays that, explicitly making use of ncvisual_resize() rather than a scaling parameter to ncvisual_render(). This also eliminates some memory leaks and bugs we were seeing in trunk, and brings in Sixel scaffolding. The C++ wrapper will also need patching back up; I cut most of it down while wrestling with this crap, urk. Closes #638, #562, and #622.
4 years ago
ncplane_destroy(newn);
ncvisual_destroy(ncv);
}
}
#endif
Per-line damage map, ~50% increase in FPS on notcurses-demo (#144) Implement a fairly conservative, line-granularity, two-level damage map. One on the overall notcurses object is dirtied by planar moves, creations, deletions, and resizes. One on each ncplane is dirtied by glyph output, media rendering, fades, and erasure. #83 This has some definite false positives: a hidden plane which moves will damage a bunch of lines unnecessarily. For now, don't do things like that :D. Extra byte per line per plane, shouldn't be a problem. Two new stats for cell elisions and emissions Allow keypress to interrupt view-demo ncvisual_stream() now allows a callback per frame Allow ncvisual_open() to create its own, perfectly-sized, ncplane #128 Typical performance prior to this PR: 4655 renders, 18.3s total (0.000305s min, 0.196s max, 0.0039s avg 253.9 fps) 401046.505KB total (9.688KB min, 139.697KB max, 86.15KB avg) Emits/elides: def 1082115/116196 fg 10547624/7236460 bg 10602717/6208644 Elide rates: 9.70% 40.69% 36.93% 4680 renders, 18.4s total (0.000285s min, 0.15s max, 0.0039s avg 255.0 fps) 403078.188KB total (9.688KB min, 139.697KB max, 86.13KB avg) Emits/elides: def 1088994/116196 fg 10604983/7267750 bg 10655426/6237472 Elide rates: 9.64% 40.66% 36.92% 4699 renders, 17.8s total (0.000227s min, 0.192s max, 0.0038s avg 263.8 fps) 403266.907KB total (9.688KB min, 139.697KB max, 85.82KB avg) Emits/elides: def 1086511/116196 fg 10601709/7359116 bg 10661910/6326744 Elide rates: 9.66% 40.97% 37.24% After this PR: 5625 renders, 15s total (9.36e-05s min, 0.187s max, 0.0027s avg 375.2 fps) 168365.640KB total (0.930KB min, 139.600KB max, 29.93KB avg) Emits/elides: def 310575/116196 fg 4486002/4473416 bg 4116835/4630666 Elide rates: 27.23% 49.93% 52.94% Cells emitted; 9928000 elided: 12572000 (55.88%) 5642 renders, 14.2s total (9.17e-05s min, 0.154s max, 0.0025s avg 397.0 fps) 168669.009KB total (0.605KB min, 139.600KB max, 29.90KB avg) Emits/elides: def 310819/116196 fg 4499833/4482134 bg 4118562/4652470 Elide rates: 27.21% 49.90% 53.04% Cells emitted; 9962160 elided: 12605840 (55.86%) 5650 renders, 14.3s total (0.000118s min, 0.143s max, 0.0025s avg 395.7 fps) 169461.884KB total (0.860KB min, 139.600KB max, 29.99KB avg) Emits/elides: def 305431/116196 fg 4515396/4456376 bg 4149967/4613668 Elide rates: 27.56% 49.67% 52.65% Cells emitted; 9945200 elided: 12654800 (55.99%) on netcurses-demo, we're eliding about half of the total cells via this damage map. that's pretty fucking sweet! FPS increase of about 50% -- I'll take that any day of the fuckin' week, boyo. w00t! https://www.youtube.com/watch?v=XbGs_qK2PQA
5 years ago
SUBCASE("LoadRGBAFromMemory") {
int dimy, dimx;
ncplane_dim_yx(ncp_, &dimy, &dimx);
std::vector<uint32_t> rgba(dimx * dimy * 2, 0xff88bbcc);
Fully general ncvisual layer (#647) This represents an essentially complete rewrite of ncvisual and associated code. It had two major goals: Improve the ncvisual API based off lessons learned, pursuant to the upcoming API freeze. In particular, I wanted to: decouple ncvisuals from ncplanes. It should be possible to render a ncvisual to multiple planes, with different scaling each time. It should be possible to create an ncvisual without a plane, etc. normalize the various ways of constructing an ncvisual -- file, memory, plane, etc. Support multiple blitters, from 7-bit ASCII to Sixel. This required writing the blitters in several cases, and they're not yet in their final implementations (but the API is fine) I have not yet unified Plots and Visuals, and might not, given that the Plot code works fine. We could at this point implement Plots in terms of Visuals, though -- the blitter backend range has been unified. Sixel is not yet implemented, though it is listed. There is a new POC tool, blitter. It renders its arguments using all possible blitter+scaling combinations. Another new POC, resize, displays its argument, then resizes it to the screen size and displays that, explicitly making use of ncvisual_resize() rather than a scaling parameter to ncvisual_render(). This also eliminates some memory leaks and bugs we were seeing in trunk, and brings in Sixel scaffolding. The C++ wrapper will also need patching back up; I cut most of it down while wrestling with this crap, urk. Closes #638, #562, and #622.
4 years ago
auto ncv = ncvisual_from_rgba(rgba.data(), dimy * 2, dimx * 4, dimx);
REQUIRE(ncv);
Fully general ncvisual layer (#647) This represents an essentially complete rewrite of ncvisual and associated code. It had two major goals: Improve the ncvisual API based off lessons learned, pursuant to the upcoming API freeze. In particular, I wanted to: decouple ncvisuals from ncplanes. It should be possible to render a ncvisual to multiple planes, with different scaling each time. It should be possible to create an ncvisual without a plane, etc. normalize the various ways of constructing an ncvisual -- file, memory, plane, etc. Support multiple blitters, from 7-bit ASCII to Sixel. This required writing the blitters in several cases, and they're not yet in their final implementations (but the API is fine) I have not yet unified Plots and Visuals, and might not, given that the Plot code works fine. We could at this point implement Plots in terms of Visuals, though -- the blitter backend range has been unified. Sixel is not yet implemented, though it is listed. There is a new POC tool, blitter. It renders its arguments using all possible blitter+scaling combinations. Another new POC, resize, displays its argument, then resizes it to the screen size and displays that, explicitly making use of ncvisual_resize() rather than a scaling parameter to ncvisual_render(). This also eliminates some memory leaks and bugs we were seeing in trunk, and brings in Sixel scaffolding. The C++ wrapper will also need patching back up; I cut most of it down while wrestling with this crap, urk. Closes #638, #562, and #622.
4 years ago
struct ncvisual_options opts{};
opts.n = ncp_;
CHECK(nullptr != ncvisual_render(nc_, ncv, &opts));
CHECK(0 == notcurses_render(nc_));
// FIXME check cell for color -- want ccbb88
ncvisual_destroy(ncv);
CHECK(0 == notcurses_render(nc_));
}
SUBCASE("LoadBGRAFromMemory") {
int dimy, dimx;
ncplane_dim_yx(ncp_, &dimy, &dimx);
std::vector<uint32_t> rgba(dimx * dimy * 2, 0xff88bbcc);
Fully general ncvisual layer (#647) This represents an essentially complete rewrite of ncvisual and associated code. It had two major goals: Improve the ncvisual API based off lessons learned, pursuant to the upcoming API freeze. In particular, I wanted to: decouple ncvisuals from ncplanes. It should be possible to render a ncvisual to multiple planes, with different scaling each time. It should be possible to create an ncvisual without a plane, etc. normalize the various ways of constructing an ncvisual -- file, memory, plane, etc. Support multiple blitters, from 7-bit ASCII to Sixel. This required writing the blitters in several cases, and they're not yet in their final implementations (but the API is fine) I have not yet unified Plots and Visuals, and might not, given that the Plot code works fine. We could at this point implement Plots in terms of Visuals, though -- the blitter backend range has been unified. Sixel is not yet implemented, though it is listed. There is a new POC tool, blitter. It renders its arguments using all possible blitter+scaling combinations. Another new POC, resize, displays its argument, then resizes it to the screen size and displays that, explicitly making use of ncvisual_resize() rather than a scaling parameter to ncvisual_render(). This also eliminates some memory leaks and bugs we were seeing in trunk, and brings in Sixel scaffolding. The C++ wrapper will also need patching back up; I cut most of it down while wrestling with this crap, urk. Closes #638, #562, and #622.
4 years ago
auto ncv = ncvisual_from_bgra(rgba.data(), dimy * 2, dimx * 4, dimx);
REQUIRE(ncv);
Fully general ncvisual layer (#647) This represents an essentially complete rewrite of ncvisual and associated code. It had two major goals: Improve the ncvisual API based off lessons learned, pursuant to the upcoming API freeze. In particular, I wanted to: decouple ncvisuals from ncplanes. It should be possible to render a ncvisual to multiple planes, with different scaling each time. It should be possible to create an ncvisual without a plane, etc. normalize the various ways of constructing an ncvisual -- file, memory, plane, etc. Support multiple blitters, from 7-bit ASCII to Sixel. This required writing the blitters in several cases, and they're not yet in their final implementations (but the API is fine) I have not yet unified Plots and Visuals, and might not, given that the Plot code works fine. We could at this point implement Plots in terms of Visuals, though -- the blitter backend range has been unified. Sixel is not yet implemented, though it is listed. There is a new POC tool, blitter. It renders its arguments using all possible blitter+scaling combinations. Another new POC, resize, displays its argument, then resizes it to the screen size and displays that, explicitly making use of ncvisual_resize() rather than a scaling parameter to ncvisual_render(). This also eliminates some memory leaks and bugs we were seeing in trunk, and brings in Sixel scaffolding. The C++ wrapper will also need patching back up; I cut most of it down while wrestling with this crap, urk. Closes #638, #562, and #622.
4 years ago
struct ncvisual_options opts{};
opts.n = ncp_;
CHECK(nullptr != ncvisual_render(nc_, ncv, &opts));
CHECK(0 == notcurses_render(nc_));
// FIXME check cell for color -- want 88bbcc
ncvisual_destroy(ncv);
CHECK(0 == notcurses_render(nc_));
}
// write a checkerboard pattern and verify the NCBLIT_2x1 output
SUBCASE("Dualblitter") {
if(notcurses_canutf8(nc_)){
constexpr int DIMY = 10;
constexpr int DIMX = 11; // odd number to get checkerboard effect
auto rgba = new uint32_t[DIMY * DIMX];
for(int i = 0 ; i < DIMY * DIMX ; ++i){
CHECK(0 == ncpixel_set_a(&rgba[i], 0xff));
if(i % 2){
CHECK(0 == ncpixel_set_b(&rgba[i], 0xff));
CHECK(0 == ncpixel_set_r(&rgba[i], 0));
}else{
CHECK(0 == ncpixel_set_r(&rgba[i], 0xff));
CHECK(0 == ncpixel_set_b(&rgba[i], 0));
}
CHECK(0 == ncpixel_set_g(&rgba[i], 0));
}
auto ncv = ncvisual_from_rgba(rgba, DIMY, DIMX * sizeof(uint32_t), DIMX);
REQUIRE(nullptr != ncv);
struct ncvisual_options vopts{};
vopts.n = n_;
vopts.blitter = NCBLIT_2x1;
vopts.flags = NCVISUAL_OPTION_NODEGRADE;
CHECK(n_ == ncvisual_render(nc_, ncv, &vopts));
CHECK(0 == notcurses_render(nc_));
for(int y = 0 ; y < DIMY / 2 ; ++y){
for(int x = 0 ; x < DIMX ; ++x){
uint16_t stylemask;
uint64_t channels;
char* egc = notcurses_at_yx(nc_, y, x, &stylemask, &channels);
REQUIRE(nullptr != egc);
CHECK((rgba[y * 2 * DIMX + x] & 0xffffff) == channels_bg_rgb(channels));
CHECK((rgba[(y * 2 + 1) * DIMX + x] & 0xffffff) == channels_fg_rgb(channels));
free(egc);
}
}
delete[] rgba;
}
}
// write a checkerboard pattern and verify the NCBLIT_2x2 output
SUBCASE("Quadblitter") {
if(notcurses_canutf8(nc_)){
constexpr int DIMY = 10;
constexpr int DIMX = 11; // odd number to get checkerboard effect
auto rgba = new uint32_t[DIMY * DIMX];
for(int i = 0 ; i < DIMY * DIMX ; ++i){
CHECK(0 == ncpixel_set_a(&rgba[i], 0xff));
if(i % 2){
CHECK(0 == ncpixel_set_b(&rgba[i], 0xff));
CHECK(0 == ncpixel_set_g(&rgba[i], 0));
}else{
CHECK(0 == ncpixel_set_g(&rgba[i], 0xff));
CHECK(0 == ncpixel_set_b(&rgba[i], 0));
}
CHECK(0 == ncpixel_set_r(&rgba[i], 0));
}
auto ncv = ncvisual_from_rgba(rgba, DIMY, DIMX * sizeof(uint32_t), DIMX);
REQUIRE(nullptr != ncv);
struct ncvisual_options vopts{};
vopts.n = n_;
vopts.blitter = NCBLIT_2x2;
vopts.flags = NCVISUAL_OPTION_NODEGRADE;
CHECK(n_ == ncvisual_render(nc_, ncv, &vopts));
CHECK(0 == notcurses_render(nc_));
for(int y = 0 ; y < DIMY / 2 ; ++y){
for(int x = 0 ; x < DIMX / 2 ; ++x){
uint16_t stylemask;
uint64_t channels;
char* egc = notcurses_at_yx(nc_, y, x, &stylemask, &channels);
REQUIRE(nullptr != egc);
CHECK((rgba[(y * 2 * DIMX) + (x * 2)] & 0xffffff) == channels_fg_rgb(channels));
CHECK((rgba[(y * 2 + 1) * DIMX + (x * 2) + 1] & 0xffffff) == channels_fg_rgb(channels));
free(egc);
}
}
delete[] rgba;
}
}
// close-in verification of each quadblitter output EGC
SUBCASE("QuadblitterEGCs") {
if(notcurses_canutf8(nc_)){
// there are 16 configurations, each mapping four (2x2) pixels
int DIMX = 32;
int DIMY = 2;
auto rgba = new uint32_t[DIMY * DIMX];
memset(rgba, 0, sizeof(*rgba) * DIMY * DIMX);
// the top has 4 configurations of 4 each, each being 2 columns
for(int top = 0 ; top < 4 ; ++top){
for(int idx = 0 ; idx < 4 ; ++idx){
const int itop = (top * 4 + idx) * 2; // index of first column
CHECK(0 == ncpixel_set_a(&rgba[itop], 0xff));
CHECK(0 == ncpixel_set_a(&rgba[itop + 1], 0xff));
if(top == 1 || top == 3){
CHECK(0 == ncpixel_set_r(&rgba[itop], 0xff));
}
if(top == 2 || top == 3){
CHECK(0 == ncpixel_set_r(&rgba[itop + 1], 0xff));
}
}
}
for(int bot = 0 ; bot < 4 ; ++bot){
for(int idx = 0 ; idx < 4 ; ++idx){
const int ibot = (bot * 4 + idx) * 2 + DIMX;
CHECK(0 == ncpixel_set_a(&rgba[ibot], 0xff));
CHECK(0 == ncpixel_set_a(&rgba[ibot + 1], 0xff));
if(idx == 1 || idx == 3){
CHECK(0 == ncpixel_set_r(&rgba[ibot], 0xff));
}
if(idx == 2 || idx == 3){
CHECK(0 == ncpixel_set_r(&rgba[ibot + 1], 0xff));
}
}
}
auto ncv = ncvisual_from_rgba(rgba, DIMY, DIMX * sizeof(uint32_t), DIMX);
REQUIRE(nullptr != ncv);
struct ncvisual_options vopts{};
vopts.n = n_;
vopts.blitter = NCBLIT_2x2;
vopts.flags = NCVISUAL_OPTION_NODEGRADE;
CHECK(n_ == ncvisual_render(nc_, ncv, &vopts));
CHECK(0 == notcurses_render(nc_));
for(int y = 0 ; y < DIMY / 2 ; ++y){
for(int x = 0 ; x < DIMX / 2 ; ++x){
uint16_t stylemask;
uint64_t channels;
char* egc = notcurses_at_yx(nc_, y, x, &stylemask, &channels);
REQUIRE(nullptr != egc);
/* FIXME need to match
[] 00000000 00000000
[] 00000000 00ff0000
[] 00000000 00ff0000
[] 00000000 00ff0000
[] 00000000 00ff0000
[] 00ff0000 00000000
[] 00ff0000 00000000
[] 00ff0000 00000000
[] 00000000 00ff0000
[] 00000000 00ff0000
[] 00000000 00ff0000
[] 00ff0000 00000000
[] 00ff0000 00000000
[] 00ff0000 00000000
[] 00ff0000 00000000
[] 00ff0000 00ff0000
*/
free(egc);
}
}
delete[] rgba;
}
}
// quadblitter with all 4 colors equal ought generate space
SUBCASE("Quadblitter4Same") {
if(notcurses_canutf8(nc_)){
const uint32_t pixels[4] = { 0xff605040, 0xff605040, 0xff605040, 0xff605040 };
auto ncv = ncvisual_from_rgba(pixels, 2, 2 * sizeof(*pixels), 2);
REQUIRE(nullptr != ncv);
struct ncvisual_options vopts = {
.n = nullptr,
.scaling = NCSCALE_NONE,
.y = 0,
.x = 0,
.begy = 0,
.begx = 0,
.leny = 0,
.lenx = 0,
.blitter = NCBLIT_2x2,
.flags = 0,
};
auto ncvp = ncvisual_render(nc_, ncv, &vopts);
REQUIRE(nullptr != ncvp);
int dimy, dimx;
ncplane_dim_yx(ncvp, &dimy, &dimx);
CHECK(1 == dimy);
CHECK(1 == dimx);
uint16_t stylemask;
uint64_t channels;
auto egc = ncplane_at_yx(ncvp, 0, 0, &stylemask, &channels);
CHECK(0 == strcmp(" ", egc));
CHECK(0 == stylemask);
CHECK(0x405060 == channels_fg_rgb(channels));
CHECK(0x405060 == channels_bg_rgb(channels));
free(egc);
ncvisual_destroy(ncv);
}
}
// quadblitter with three pixels equal ought generate three-quarter block
SUBCASE("Quadblitter3Same") {
if(notcurses_canutf8(nc_)){
const uint32_t pixels[4][4] = {
{ 0xffcccccc, 0xff605040, 0xff605040, 0xff605040 },
{ 0xff605040, 0xffcccccc, 0xff605040, 0xff605040 },
{ 0xff605040, 0xff605040, 0xffcccccc, 0xff605040 },
{ 0xff605040, 0xff605040, 0xff605040, 0xffcccccc } };
const char* egcs[] = { "", "", "", "" };
for(int i = 0 ; i < 4 ; ++i){
auto ncv = ncvisual_from_rgba(pixels[i], 2, 2 * sizeof(**pixels), 2);
REQUIRE(nullptr != ncv);
struct ncvisual_options vopts = {
.n = nullptr,
.scaling = NCSCALE_NONE,
.y = 0,
.x = 0,
.begy = 0,
.begx = 0,
.leny = 0,
.lenx = 0,
.blitter = NCBLIT_2x2,
.flags = 0,
};
auto ncvp = ncvisual_render(nc_, ncv, &vopts);
REQUIRE(nullptr != ncvp);
int dimy, dimx;
ncplane_dim_yx(ncvp, &dimy, &dimx);
CHECK(1 == dimy);
CHECK(1 == dimx);
uint16_t stylemask;
uint64_t channels;
auto egc = ncplane_at_yx(ncvp, 0, 0, &stylemask, &channels);
CHECK(0 == strcmp(egcs[i], egc));
CHECK(0 == stylemask);
CHECK(0x405060 == channels_fg_rgb(channels));
CHECK(0xcccccc == channels_bg_rgb(channels));
free(egc);
ncvisual_destroy(ncv);
}
}
}
// quadblitter with two sets of two equal pixels
SUBCASE("Quadblitter2Pairs") {
if(notcurses_canutf8(nc_)){
const uint32_t pixels[6][4] = {
{ 0xffcccccc, 0xffcccccc, 0xff605040, 0xff605040 },
{ 0xffcccccc, 0xff605040, 0xffcccccc, 0xff605040 },
{ 0xffcccccc, 0xff605040, 0xff605040, 0xffcccccc },
{ 0xff605040, 0xffcccccc, 0xffcccccc, 0xff605040 },
{ 0xff605040, 0xffcccccc, 0xff605040, 0xffcccccc },
{ 0xff605040, 0xff605040, 0xffcccccc, 0xffcccccc } };
const char* egcs[] = { "", "", "", "", "", "" };
for(size_t i = 0 ; i < sizeof(egcs) / sizeof(*egcs) ; ++i){
auto ncv = ncvisual_from_rgba(pixels[i], 2, 2 * sizeof(**pixels), 2);
REQUIRE(nullptr != ncv);
struct ncvisual_options vopts = {
.n = nullptr,
.scaling = NCSCALE_NONE,
.y = 0,
.x = 0,
.begy = 0,
.begx = 0,
.leny = 0,
.lenx = 0,
.blitter = NCBLIT_2x2,
.flags = 0,
};
auto ncvp = ncvisual_render(nc_, ncv, &vopts);
REQUIRE(nullptr != ncvp);
int dimy, dimx;
ncplane_dim_yx(ncvp, &dimy, &dimx);
CHECK(1 == dimy);
CHECK(1 == dimx);
uint16_t stylemask;
uint64_t channels;
auto egc = ncplane_at_yx(ncvp, 0, 0, &stylemask, &channels);
CHECK(0 == strcmp(egcs[i], egc));
CHECK(0 == stylemask);
if(i >= 3){
CHECK(0x405060 == channels_fg_rgb(channels));
CHECK(0xcccccc == channels_bg_rgb(channels));
}else{
CHECK(0x405060 == channels_bg_rgb(channels));
CHECK(0xcccccc == channels_fg_rgb(channels));
}
free(egc);
ncvisual_destroy(ncv);
}
}
}
// quadblitter with one pair plus two split
SUBCASE("Quadblitter1Pair") {
if(notcurses_canutf8(nc_)){
const uint32_t pixels[6][4] = {
{ 0xffcccccc, 0xff444444, 0xff605040, 0xff605040 },
{ 0xff444444, 0xff605040, 0xffcccccc, 0xff605040 },
{ 0xffcccccc, 0xff605040, 0xff605040, 0xff444444 },
{ 0xff605040, 0xffcccccc, 0xff444444, 0xff605040 },
{ 0xff605040, 0xffeeeeee, 0xff605040, 0xffcccccc },
{ 0xff605040, 0xff605040, 0xffeeeeee, 0xffcccccc } };
const char* egcs[] = { "", "", "", "", "", "" };
for(size_t i = 0 ; i < sizeof(egcs) / sizeof(*egcs) ; ++i){
auto ncv = ncvisual_from_rgba(pixels[i], 2, 2 * sizeof(**pixels), 2);
REQUIRE(nullptr != ncv);
struct ncvisual_options vopts = {
.n = nullptr,
.scaling = NCSCALE_NONE,
.y = 0,
.x = 0,
.begy = 0,
.begx = 0,
.leny = 0,
.lenx = 0,
.blitter = NCBLIT_2x2,
.flags = 0,
};
auto ncvp = ncvisual_render(nc_, ncv, &vopts);
REQUIRE(nullptr != ncvp);
int dimy, dimx;
ncplane_dim_yx(ncvp, &dimy, &dimx);
CHECK(1 == dimy);
CHECK(1 == dimx);
uint16_t stylemask;
uint64_t channels;
auto egc = ncplane_at_yx(ncvp, 0, 0, &stylemask, &channels);
CHECK(0 == strcmp(egcs[i], egc));
CHECK(0 == stylemask);
if(i > 3){
CHECK(0x405060 == channels_fg_rgb(channels));
CHECK(0xdddddd == channels_bg_rgb(channels));
}else{
CHECK(0x424c57 == channels_fg_rgb(channels));
CHECK(0xcccccc == channels_bg_rgb(channels));
}
free(egc);
ncvisual_destroy(ncv);
}
}
}
// quadblitter with one pair plus two split
SUBCASE("QuadblitterAllDifferent") {
if(notcurses_canutf8(nc_)){
const uint32_t pixels[6][4] = {
{ 0xffdddddd, 0xff000000, 0xff111111, 0xff222222 },
{ 0xff000000, 0xff111111, 0xffdddddd, 0xff222222 },
{ 0xff111111, 0xffdddddd, 0xff000000, 0xff222222 },
{ 0xff000000, 0xffcccccc, 0xff222222, 0xffeeeeee },
{ 0xff222222, 0xff000000, 0xffeeeeee, 0xffcccccc, } };
const char* egcs[] = { "", "", "", "", "" };
for(size_t i = 0 ; i < sizeof(egcs) / sizeof(*egcs) ; ++i){
auto ncv = ncvisual_from_rgba(pixels[i], 2, 2 * sizeof(**pixels), 2);
REQUIRE(nullptr != ncv);
struct ncvisual_options vopts = {
.n = nullptr,
.scaling = NCSCALE_NONE,
.y = 0,
.x = 0,
.begy = 0,
.begx = 0,
.leny = 0,
.lenx = 0,
.blitter = NCBLIT_2x2,
.flags = 0,
};
auto ncvp = ncvisual_render(nc_, ncv, &vopts);
REQUIRE(nullptr != ncvp);
int dimy, dimx;
ncplane_dim_yx(ncvp, &dimy, &dimx);
CHECK(1 == dimy);
CHECK(1 == dimx);
uint16_t stylemask;
uint64_t channels;
auto egc = ncplane_at_yx(ncvp, 0, 0, &stylemask, &channels);
CHECK(0 == strcmp(egcs[i], egc));
CHECK(0 == stylemask);
CHECK(0x111111 == channels_fg_rgb(channels));
CHECK(0xdddddd == channels_bg_rgb(channels));
free(egc);
ncvisual_destroy(ncv);
}
}
}
CHECK(!notcurses_stop(nc_));
}