mirror of
https://github.com/dankamongmen/notcurses.git
synced 2024-11-02 09:40:15 +00:00
4e58747709
Introduce limited plane rotation capability. We currently support clockwise and counterclockwise rotation of planes. Square and rectangular geometries are both supported, but there must be an even number of columns. The atomic unit of rotation is a 2x1 "square" (this assumes .5 cell aspect ratio). We can only rotate those glyphs which have rotated equivalents, and not even all of those. We currently handle only: * null glyph * space * upper half block * lower half block * full block I've added unit tests as well. This functionality is used by our Tetris example in the book
112 lines
4.1 KiB
C++
112 lines
4.1 KiB
C++
#include "main.h"
|
|
|
|
void RotateCW(struct notcurses* nc, struct ncplane* n) {
|
|
CHECK(0 == notcurses_render(nc));
|
|
CHECK(0 == ncplane_rotate_cw(n));
|
|
CHECK(0 == notcurses_render(nc));
|
|
CHECK(0 == ncplane_rotate_cw(n));
|
|
CHECK(0 == notcurses_render(nc));
|
|
CHECK(0 == ncplane_rotate_cw(n));
|
|
CHECK(0 == notcurses_render(nc));
|
|
CHECK(0 == ncplane_rotate_cw(n));
|
|
CHECK(0 == notcurses_render(nc));
|
|
}
|
|
|
|
void RotateCCW(struct notcurses* nc, struct ncplane* n) {
|
|
CHECK(0 == notcurses_render(nc));
|
|
CHECK(0 == ncplane_rotate_ccw(n));
|
|
CHECK(0 == notcurses_render(nc));
|
|
CHECK(0 == ncplane_rotate_ccw(n));
|
|
CHECK(0 == notcurses_render(nc));
|
|
CHECK(0 == ncplane_rotate_ccw(n));
|
|
CHECK(0 == notcurses_render(nc));
|
|
CHECK(0 == ncplane_rotate_ccw(n));
|
|
CHECK(0 == notcurses_render(nc));
|
|
}
|
|
|
|
TEST_CASE("Rotate") {
|
|
if(getenv("TERM") == nullptr){
|
|
return;
|
|
}
|
|
notcurses_options nopts{};
|
|
nopts.inhibit_alternate_screen = true;
|
|
nopts.suppress_banner = true;
|
|
FILE* outfp_ = fopen("/dev/tty", "wb");
|
|
REQUIRE(outfp_);
|
|
struct notcurses* nc_ = notcurses_init(&nopts, outfp_);
|
|
REQUIRE(nc_);
|
|
int dimy, dimx;
|
|
struct ncplane* n_ = notcurses_stddim_yx(nc_, &dimy, &dimx);
|
|
REQUIRE(n_);
|
|
|
|
uint64_t ul, ur, ll, lr;
|
|
ul = ur = ll = lr = 0;
|
|
channels_set_fg(&ul, 0x40f040);
|
|
channels_set_bg(&ul, 0x40f040);
|
|
channels_set_fg(&ll, 0xf040f0);
|
|
channels_set_bg(&ll, 0xf040f0);
|
|
channels_set_fg(&ur, 0x40f040);
|
|
channels_set_bg(&ur, 0x40f040);
|
|
channels_set_fg(&lr, 0xf040f0);
|
|
channels_set_bg(&lr, 0xf040f0);
|
|
|
|
SUBCASE("RotateTransparentCW") {
|
|
struct ncplane* testn = ncplane_new(nc_, 8, 16, dimy / 2, dimx / 2, nullptr);
|
|
uint64_t channels = 0;
|
|
CHECK(0 == channels_set_fg_alpha(&channels, CELL_ALPHA_TRANSPARENT));
|
|
CHECK(0 == channels_set_bg_alpha(&channels, CELL_ALPHA_TRANSPARENT));
|
|
REQUIRE(0 >= ncplane_set_base(testn, channels, 0, ""));
|
|
cell tl = CELL_TRIVIAL_INITIALIZER; cell tr = CELL_TRIVIAL_INITIALIZER;
|
|
cell bl = CELL_TRIVIAL_INITIALIZER; cell br = CELL_TRIVIAL_INITIALIZER;
|
|
cell hl = CELL_TRIVIAL_INITIALIZER; cell vl = CELL_TRIVIAL_INITIALIZER;
|
|
CHECK(-1 < cell_prime(testn, &tl, "█", 0, ul));
|
|
CHECK(-1 < cell_prime(testn, &tr, "█", 0, ur));
|
|
CHECK(-1 < cell_prime(testn, &bl, "█", 0, ll));
|
|
CHECK(-1 < cell_prime(testn, &br, "█", 0, lr));
|
|
CHECK(-1 < cell_prime(testn, &hl, "█", 0, ll));
|
|
CHECK(-1 < cell_prime(testn, &vl, "█", 0, lr));
|
|
CHECK(0 == ncplane_perimeter(testn, &tl, &tr, &bl, &br, &hl, &vl, 0));
|
|
RotateCW(nc_, testn);
|
|
cell_release(testn, &tl); cell_release(testn, &tr);
|
|
cell_release(testn, &bl); cell_release(testn, &br);
|
|
cell_release(testn, &hl); cell_release(testn, &vl);
|
|
CHECK(0 == ncplane_destroy(testn));
|
|
}
|
|
|
|
SUBCASE("RotateGradientCW") {
|
|
// should be a square, and should remain a square through rotations
|
|
struct ncplane* testn = ncplane_new(nc_, 8, 16, dimy / 2, dimx / 2, nullptr);
|
|
REQUIRE(0 == ncplane_gradient_sized(testn, " ", 0, ul, ur, ll, lr, 8, 16));
|
|
RotateCW(nc_, testn);
|
|
CHECK(0 == ncplane_destroy(testn));
|
|
}
|
|
|
|
SUBCASE("RotateRectangleCW") {
|
|
// should be a square, and should remain a square through rotations
|
|
struct ncplane* testn = ncplane_new(nc_, 8, 32, dimy / 2, dimx / 2, nullptr);
|
|
REQUIRE(0 == ncplane_gradient_sized(testn, " ", 0, ul, ur, ll, lr, 8, 32));
|
|
RotateCW(nc_, testn);
|
|
CHECK(0 == ncplane_destroy(testn));
|
|
}
|
|
|
|
SUBCASE("RotateGradientCCW") {
|
|
// should be a square, and should remain a square through rotations
|
|
struct ncplane* testn = ncplane_new(nc_, 8, 16, dimy / 2, dimx / 2, nullptr);
|
|
REQUIRE(0 == ncplane_gradient_sized(testn, " ", 0, ul, ur, ll, lr, 8, 16));
|
|
RotateCCW(nc_, testn);
|
|
CHECK(0 == ncplane_destroy(testn));
|
|
}
|
|
|
|
SUBCASE("RotateRectangleCCW") {
|
|
// should be a square, and should remain a square through rotations
|
|
struct ncplane* testn = ncplane_new(nc_, 8, 32, 0, 0, nullptr);
|
|
REQUIRE(0 == ncplane_gradient_sized(testn, " ", 0, ul, ur, ll, lr, 8, 32));
|
|
RotateCCW(nc_, testn);
|
|
CHECK(0 == ncplane_destroy(testn));
|
|
}
|
|
|
|
CHECK(0 == notcurses_stop(nc_));
|
|
CHECK(0 == fclose(outfp_));
|
|
|
|
}
|