Merge branch 'master' of github.com:dankamongmen/notcurses

pull/1157/head
nick black 4 years ago
commit 911f4eccc4
No known key found for this signature in database
GPG Key ID: 5F43400C21CBFACC

@ -37,8 +37,8 @@
<a href="notcurses-tester.1.html">notcurses-tester</a>—unit test driver<br/>
<a href="notcurses-tetris.1.html">notcurses-tetris</a>—Tetris in a terminal<br/>
<a href="notcurses-view.1.html">notcurses-view</a>—renders images and video to a terminal<br/>
<h3>C library (section 3)</h3>
<div style="float:left">
<h3>C library (section 3)</h3>
<a href="notcurses_capabilities.3.html">notcurses_capabilities</a>—runtime capability detection<br/>
<a href="notcurses_cell.3.html">notcurses_cell</a>—operations on <tt>cell</tt> objects<br/>
<a href="notcurses_channels.3.html">notcurses_channels</a>—operations on the <tt>channel</tt> type<br/>

@ -13,12 +13,14 @@
#include <signal.h>
#include <limits.h>
#include <stdbool.h>
// take host byte order and turn it into network (reverse on LE, no-op on BE),
// then reverse that, guaranteeing LE. htole(x) == ltohe(x).
#ifdef __linux__
#include <byteswap.h>
#define ntole(x) (bswap_32(htonl(x)))
#define htole(x) (bswap_32(htonl(x)))
#else
#include <sys/endian.h>
#define ntole(x) (bswap32(htonl(x)))
#define htole(x) (bswap32(htonl(x)))
#endif
#include <netinet/in.h>
#include <notcurses/nckeys.h>
@ -576,8 +578,8 @@ typedef struct cell {
} cell;
#define CELL_TRIVIAL_INITIALIZER { }
#define CELL_CHAR_INITIALIZER(c) { .gcluster = (ntole(c)), .gcluster_backstop = 0, .reserved = 0, .stylemask = 0, .channels = 0, }
#define CELL_INITIALIZER(c, s, chan) { .gcluster = (ntole(c)), .gcluster_backstop = 0, .reserved = 0, .stylemask = (s), .channels = (chan), }
#define CELL_CHAR_INITIALIZER(c) { .gcluster = (htole(c)), .gcluster_backstop = 0, .reserved = 0, .stylemask = 0, .channels = 0, }
#define CELL_INITIALIZER(c, s, chan) { .gcluster = (htole(c)), .gcluster_backstop = 0, .reserved = 0, .stylemask = (s), .channels = (chan), }
static inline void
cell_init(cell* c){
@ -729,7 +731,7 @@ static inline int
cell_load_char(struct ncplane* n, cell* c, char ch){
cell_release(n, c);
c->channels &= ~(CELL_WIDEASIAN_MASK | CELL_NOBACKGROUND_MASK);
c->gcluster = ntole((uint32_t)ch);
c->gcluster = htole((uint32_t)ch);
return 1;
}
@ -2417,83 +2419,94 @@ API int ncblit_bgrx(const void* data, int linesize,
// The ncpixel API facilitates direct management of the pixels within an
// ncvisual (ncvisuals keep a backing store of 32-bit RGBA pixels, and render
// them down to terminal graphics in ncvisual_render()).
// Extract the 8-bit alpha component from a pixel
static inline uint32_t
ncpixel(int r, int g, int b){
if(r < 0) r = 0;
if(r > 255) r = 255;
if(g < 0) g = 0;
if(g > 255) g = 255;
if(b < 0) b = 0;
if(b > 255) b = 255;
return 0xff000000ul | r | (b << 8u) | (g << 16u);
}
//
// Per libav, we "store as BGRA on little-endian, and ARGB on big-endian".
// This is an RGBA *byte-order* scheme. libav emits bytes, not words. Those
// bytes are R-G-B-A. When read as words, on little endian this will be ABGR,
// and on big-endian this will be RGBA. force everything to LE ABGR, a no-op on
// and thus favoring little-endian. Take that, big-endian mafia!
// Extract the 8-bit alpha component from a pixel
static inline unsigned
ncpixel_a(uint32_t pixel){
return (pixel & 0xff000000ul) >> 24u;
return (htole(pixel) & 0xff000000ul) >> 24u;
}
// Extract the 8-bit red component from a pixel
// Extract the 8-bit red component from an ABGR pixel
static inline unsigned
ncpixel_r(uint32_t pixel){
return (pixel & 0x000000fful);
return (htole(pixel) & 0x000000fful);
}
// Extract the 8-bit green component from a pixel
// Extract the 8-bit green component from an ABGR pixel
static inline unsigned
ncpixel_g(uint32_t pixel){
return (pixel & 0x0000ff00ul) >> 8u;
return (htole(pixel) & 0x0000ff00ul) >> 8u;
}
// Extract the 8-bit blue component from a pixel
// Extract the 8-bit blue component from an ABGR pixel
static inline unsigned
ncpixel_b(uint32_t pixel){
return (pixel & 0x00ff0000ul) >> 16u;
return (htole(pixel) & 0x00ff0000ul) >> 16u;
}
// Set the 8-bit alpha component of a pixel
// Set the 8-bit alpha component of an ABGR pixel
static inline int
ncpixel_set_a(uint32_t* pixel, int a){
if(a > 255 || a < 0){
return -1;
}
*pixel = (*pixel & 0x00fffffful) | (a << 24u);
*pixel = htole((htole(*pixel) & 0x00fffffful) | (a << 24u));
return 0;
}
// Set the 8-bit red component of a pixel
// Set the 8-bit red component of an ABGR pixel
static inline int
ncpixel_set_r(uint32_t* pixel, int r){
if(r > 255 || r < 0){
return -1;
}
*pixel = (*pixel & 0xffffff00ul) | r;
*pixel = htole((htole(*pixel) & 0xffffff00ul) | r);
return 0;
}
// Set the 8-bit green component of a pixel
// Set the 8-bit green component of an ABGR pixel
static inline int
ncpixel_set_g(uint32_t* pixel, int g){
if(g > 255 || g < 0){
return -1;
}
*pixel = (*pixel & 0xffff00fful) | (g << 8u);
*pixel = htole((htole(*pixel) & 0xffff00fful) | (g << 8u));
return 0;
}
// Set the 8-bit blue component of a pixel
// Set the 8-bit blue component of an ABGR pixel
static inline int
ncpixel_set_b(uint32_t* pixel, int b){
if(b > 255 || b < 0){
return -1;
}
*pixel = (*pixel & 0xff00fffful) | (b << 16u);
*pixel = htole((htole(*pixel) & 0xff00fffful) | (b << 16u));
return 0;
}
// Construct a libav-compatible ABGR pixel, clipping at [0, 255).
static inline uint32_t
ncpixel(int r, int g, int b){
uint32_t pixel = 0;
ncpixel_set_a(&pixel, 0xff);
if(r < 0) r = 0;
if(r > 255) r = 255;
ncpixel_set_r(&pixel, r);
if(g < 0) g = 0;
if(g > 255) g = 255;
ncpixel_set_g(&pixel, g);
if(b < 0) b = 0;
if(b > 255) b = 255;
ncpixel_set_b(&pixel, b);
return pixel;
}
// set the RGB values of an RGB pixel
static inline int
ncpixel_set_rgb8(uint32_t* pixel, int r, int g, int b){

@ -213,7 +213,7 @@ int input_demo(ncpp::NotCurses* nc) {
popts.minchannels = popts.maxchannels = 0;
channels_set_fg_rgb8(&popts.minchannels, 0x40, 0x50, 0xb0);
channels_set_fg_rgb8(&popts.maxchannels, 0x40, 0xff, 0xd0);
popts.gridtype = static_cast<ncblitter_e>(NCBLIT_2x2);
popts.gridtype = static_cast<ncblitter_e>(NCBLIT_3x2);
plot = ncuplot_create(pplane, &popts, 0, 0);
if(!plot){
return EXIT_FAILURE;

@ -252,13 +252,13 @@ egcpool_dump(egcpool* pool){
// unsafe results if called on a simple cell.
static inline uint32_t
cell_egc_idx(const cell* c){
return ntole(c->gcluster) & 0x00fffffflu;
return htole(c->gcluster) & 0x00fffffflu;
}
// Is the cell simple (a UTF8-encoded EGC of four bytes or fewer)?
static inline bool
cell_simple_p(const cell* c){
return (ntole(c->gcluster) & 0xff000000ul) != 0x01000000ul;
return (htole(c->gcluster) & 0xff000000ul) != 0x01000000ul;
}
// only applies to complex cells, do not use on simple cells

@ -639,7 +639,7 @@ pool_release(egcpool* pool, cell* c){
// set the cell 'c' to point into the egcpool at location 'eoffset'
static inline void
set_gcluster_egc(cell* c, int eoffset){
c->gcluster = ntole(0x01000000ul) + eoffset;
c->gcluster = htole(0x01000000ul) + htole(eoffset);
}
// Duplicate one cell onto another, possibly crossing ncplanes.
@ -969,15 +969,13 @@ pool_blit_direct(egcpool* pool, cell* c, const char* gcluster, int bytes, int co
}
if(bytes <= 1){
assert(cols < 2);
c->gcluster = 0;
((unsigned char*)&c->gcluster)[0] = *gcluster;
c->gcluster = htole((uint32_t)*gcluster);
return bytes;
}
if(bytes <= 4){
if(strcmp(gcluster, (const char*)&c->gcluster)){
c->gcluster = 0;
memcpy(&c->gcluster, gcluster, bytes);
}
c->gcluster = 0;
memcpy(&c->gcluster, gcluster, bytes);
c->gcluster = htole(c->gcluster);
return bytes;
}
int eoffset = egcpool_stash(pool, gcluster, bytes);

@ -2,13 +2,14 @@
#include "egcpool.h"
TEST_CASE("Cell") {
if(!enforce_utf8()){
return;
}
auto nc_ = testing_notcurses();
if(!nc_){
return;
}
if(!notcurses_canutf8(nc_)){
CHECK(0 == notcurses_stop(nc_));
return;
}
struct ncplane* n_ = notcurses_stdplane(nc_);
REQUIRE(nullptr != n_);

@ -12,9 +12,15 @@ TEST_CASE("EGCpool") {
CHECK(!pool_.poolused);
}
if(!enforce_utf8()){
auto nc_ = testing_notcurses();
if(!nc_){
return;
}
if(!notcurses_canutf8(nc_)){
CHECK(0 == notcurses_stop(nc_));
return;
}
CHECK(0 == notcurses_stop(nc_));
SUBCASE("UTF8EGC") {
const char* wstr = "";

@ -3,13 +3,14 @@
#include "main.h"
TEST_CASE("Fills") {
if(!enforce_utf8()){
return;
}
auto nc_ = testing_notcurses();
if(!nc_){
return;
}
if(!notcurses_canutf8(nc_)){
CHECK(0 == notcurses_stop(nc_));
return;
}
struct ncplane* n_ = notcurses_stdplane(nc_);
REQUIRE(n_);

@ -189,7 +189,7 @@ TEST_CASE("TextLayout") {
// lay out text where a wide word crosses the boundary
SUBCASE("LayoutCrossBoundaryWide") {
if(enforce_utf8()){
if(notcurses_canutf8(nc_)){
struct ncplane_options nopts = {
.y = 0,
.x = 0,
@ -245,7 +245,7 @@ TEST_CASE("TextLayout") {
// a long word (one requiring a split no matter what) ought not force the
// next line, but instead be printed where it starts
SUBCASE("LayoutTransPlanarWide") {
if(enforce_utf8()){
if(notcurses_canutf8(nc_)){
struct ncplane_options nopts = {
.y = 0,
.x = 0,
@ -428,7 +428,7 @@ TEST_CASE("TextLayout") {
// create a plane of three rows, and exactly fill two with wide chars
SUBCASE("LayoutFillsPlaneWide") {
if(enforce_utf8()){
if(notcurses_canutf8(nc_)){
struct ncplane_options nopts = {
.y = 0,
.x = 0,

@ -28,17 +28,6 @@ auto find_data(const char* datum) -> char* {
return strdup(p.c_str());
}
auto enforce_utf8() -> bool {
char* enc = nl_langinfo(CODESET);
if(!enc){
return false;
}
if(strcmp(enc, "UTF-8")){
return false;
}
return true;
}
static void
handle_opts(const char** argv){
bool inarg = false;

@ -11,7 +11,6 @@
#include "internal.h"
auto find_data(const char* datum) -> char*;
auto enforce_utf8() -> bool;
auto testing_notcurses() -> struct notcurses*;
auto ncreel_validate(const ncreel* n) -> bool;

@ -421,8 +421,17 @@ TEST_CASE("Metric") {
}
SUBCASE("NegativePowersOfTen") {
auto nc_ = testing_notcurses();
if(!nc_){
return;
}
if(!notcurses_canutf8(nc_)){
CHECK(0 == notcurses_stop(nc_));
return;
}
CHECK(0 == notcurses_stop(nc_));
const wchar_t* smallsuffixes;
if(enforce_utf8()){
if(notcurses_canutf8(nc_)){
smallsuffixes = L"yzafpnµm";
}else{
smallsuffixes = L"yzafpnum";

@ -18,13 +18,14 @@ void BoxPermutationsRounded(struct notcurses* nc, struct ncplane* n, unsigned ed
}
TEST_CASE("NCPlane") {
if(!enforce_utf8()){
return;
}
auto nc_ = testing_notcurses();
if(!nc_){
return;
}
if(!notcurses_canutf8(nc_)){
CHECK(0 == notcurses_stop(nc_));
return;
}
struct ncplane* n_ = notcurses_stdplane(nc_);
REQUIRE(n_);

@ -3,13 +3,14 @@
#include <iostream>
TEST_CASE("Plot") {
if(!enforce_utf8()){
return;
}
auto nc_ = testing_notcurses();
if(!nc_){
return;
}
if(!notcurses_canutf8(nc_)){
CHECK(0 == notcurses_stop(nc_));
return;
}
auto n_ = notcurses_stdplane(nc_);
REQUIRE(n_);
REQUIRE(0 == ncplane_cursor_move_yx(n_, 0, 0));

@ -26,7 +26,8 @@ TEST_CASE("Readers") {
};
auto ncp = ncplane_create(notcurses_stdplane(nc_), &nopts);
uint64_t echannels = CHANNELS_RGB_INITIALIZER(0xff, 0x44, 0xff, 0, 0, 0);
ncplane_set_base(ncp, enforce_utf8() ? strdup("") : strdup("x"), 0, echannels);
ncplane_set_base(ncp, notcurses_canutf8(nc_) ? strdup("") : strdup("x"),
0, echannels);
auto nr = ncreader_create(ncp, &opts);
REQUIRE(nullptr != nr);
CHECK(0 == notcurses_render(nc_));

@ -27,13 +27,14 @@ void RotateCCW(struct notcurses* nc, struct ncplane* n) {
}
TEST_CASE("Rotate") {
if(!enforce_utf8()){
return;
}
auto nc_ = testing_notcurses();
if(!nc_){
return;
}
if(!notcurses_canutf8(nc_)){
CHECK(0 == notcurses_stop(nc_));
return;
}
int dimy, dimx;
struct ncplane* n_ = notcurses_stddim_yx(nc_, &dimy, &dimx);
REQUIRE(n_);

@ -272,7 +272,7 @@ TEST_CASE("Visual") {
// write a checkerboard pattern and verify the NCBLIT_2x1 output
SUBCASE("Dualblitter") {
if(enforce_utf8()){
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];
@ -312,7 +312,7 @@ TEST_CASE("Visual") {
// write a checkerboard pattern and verify the NCBLIT_2x2 output
SUBCASE("Quadblitter") {
if(enforce_utf8()){
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];
@ -352,7 +352,7 @@ TEST_CASE("Visual") {
// close-in verification of each quadblitter output EGC
SUBCASE("QuadblitterEGCs") {
if(enforce_utf8()){
if(notcurses_canutf8(nc_)){
// there are 16 configurations, each mapping four (2x2) pixels
int DIMX = 32;
int DIMY = 2;
@ -426,7 +426,7 @@ TEST_CASE("Visual") {
// quadblitter with all 4 colors equal ought generate space
SUBCASE("Quadblitter4Same") {
if(enforce_utf8()){
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);
@ -462,7 +462,7 @@ TEST_CASE("Visual") {
// quadblitter with three pixels equal ought generate three-quarter block
SUBCASE("Quadblitter3Same") {
if(enforce_utf8()){
if(notcurses_canutf8(nc_)){
const uint32_t pixels[4][4] = {
{ 0xffcccccc, 0xff605040, 0xff605040, 0xff605040 },
{ 0xff605040, 0xffcccccc, 0xff605040, 0xff605040 },
@ -505,7 +505,7 @@ TEST_CASE("Visual") {
// quadblitter with two sets of two equal pixels
SUBCASE("Quadblitter2Pairs") {
if(enforce_utf8()){
if(notcurses_canutf8(nc_)){
const uint32_t pixels[6][4] = {
{ 0xffcccccc, 0xffcccccc, 0xff605040, 0xff605040 },
{ 0xffcccccc, 0xff605040, 0xffcccccc, 0xff605040 },
@ -555,7 +555,7 @@ TEST_CASE("Visual") {
// quadblitter with one pair plus two split
SUBCASE("Quadblitter1Pair") {
if(enforce_utf8()){
if(notcurses_canutf8(nc_)){
const uint32_t pixels[6][4] = {
{ 0xffcccccc, 0xff444444, 0xff605040, 0xff605040 },
{ 0xff444444, 0xff605040, 0xffcccccc, 0xff605040 },
@ -605,7 +605,7 @@ TEST_CASE("Visual") {
// quadblitter with one pair plus two split
SUBCASE("QuadblitterAllDifferent") {
if(enforce_utf8()){
if(notcurses_canutf8(nc_)){
const uint32_t pixels[6][4] = {
{ 0xffdddddd, 0xff000000, 0xff111111, 0xff222222 },
{ 0xff000000, 0xff111111, 0xffdddddd, 0xff222222 },

@ -8,11 +8,12 @@ const char SCORPION[] = "\xf0\x9f\xa6\x82"; // U+1F982 SCORPION
const char FROG[] = "\xf0\x9f\x90\xb8"; // U+1F438 FROG FACE
TEST_CASE("Wide") {
if(!enforce_utf8()){
return;
}
auto nc_ = testing_notcurses();
REQUIRE(nullptr != nc_);
if(!notcurses_canutf8(nc_)){
CHECK(0 == notcurses_stop(nc_));
return;
}
struct ncplane* n_ = notcurses_stdplane(nc_);
REQUIRE(n_);

Loading…
Cancel
Save