mirror of
https://github.com/dankamongmen/notcurses.git
synced 2024-10-31 15:20:13 +00:00
Add convenience function ncplane_home(). Add an ncblitter_e param to ncplane_qrcode(), and split int maxversion into value-result int* ymax and int* xmax. Write the actual sizes of the resulting visual into these parameters. Update the qrcode demo. Add the qrcode PoC. Update demos to ncplane_home(), where possible. ncplane_qrcode() now takes an ncblitter_e and two value-result int*s in the place of a single value int. The final size of the displayed qrcode is written to *ymax and *xmax. If the code can't fit within the specified dimensions, an error is returned. Standard rules for pluggable blitters apply regarding fallback etc. #699
This commit is contained in:
parent
22dc5014cc
commit
0084dbaa6d
5
NEWS.md
5
NEWS.md
@ -15,6 +15,11 @@ rearrangements of Notcurses.
|
||||
can be taken into account (the latter contains a `blitter_e` field).
|
||||
* Added `ncuplot_sample()` and `ncdplot_sample()`, allowing retrieval of
|
||||
sample data from `ncuplot`s and `ncdplot`s, respectively.
|
||||
* Added convenience function `ncplane_home()`, which sets the cursor
|
||||
to the plane's origin (and returns `void`, since it cannot fail).
|
||||
* `ncplane_qrcode()` now accepts an `ncblitter_e`, and two value-result
|
||||
`int*`s `ymax` and `xmax`. The actual size of the drawn code is
|
||||
returned in these parameters.
|
||||
|
||||
* 1.5.0 (2020-07-08)
|
||||
* The various `bool`s of `struct notcurses_options` have been folded into
|
||||
|
18
USAGE.md
18
USAGE.md
@ -11,7 +11,7 @@ version 2, notcurses will honor Semantic Versioning.
|
||||
* [Reels](#reels) ([ncreel Examples](#ncreel-examples))
|
||||
* [Widgets](#widgets) ([Readers](#readers))
|
||||
* [Channels](#channels)
|
||||
* [Visuals](#visuals) ([Multimedia](#multimedia))
|
||||
* [Visuals](#visuals) ([QR codes](#qrcodes)) ([Multimedia](#multimedia)) ([Pixels](#pixels))
|
||||
* [C++](#c++)
|
||||
|
||||
A full API reference [is available](https://nick-black.com/notcurses/). Manual
|
||||
@ -2675,6 +2675,22 @@ int ncvisual_stream(struct notcurses* nc, struct ncvisual* ncv,
|
||||
const struct ncvisual_options* vopts, void* curry);
|
||||
```
|
||||
|
||||
### QR codes
|
||||
|
||||
If build with libqrcodegen support, `ncplane_qrcode()` can be used to draw
|
||||
a QR code for arbitrary data.
|
||||
|
||||
```c
|
||||
// Draw a QR code at the current position on the plane. If there is insufficient
|
||||
// room to draw the code here, or there is any other error, non-zero will be
|
||||
// returned. Otherwise, the QR code "version" (size) is returned. The QR code
|
||||
// is (version * 4 + 17) columns wide, and ⌈version * 4 + 17⌉ rows tall (the
|
||||
// properly-scaled values are written back to '*ymax' and '*xmax').
|
||||
int ncplane_qrcode(struct ncplane* n, ncblitter_e blitter, int* ymax,
|
||||
int* xmax, const void* data, size_t len);
|
||||
```
|
||||
|
||||
|
||||
### Multimedia
|
||||
|
||||
When compiled against a suitable engine (FFmpeg and OpenImageIO are both
|
||||
|
@ -1027,9 +1027,9 @@ namespace ncpp
|
||||
return error_guard_cond<bool, bool> (ret, ret);
|
||||
}
|
||||
|
||||
int qrcode (int maxversion, const void *data, size_t len) const NOEXCEPT_MAYBE
|
||||
int qrcode (ncblitter_e blitter, int* ymax, int* xmax, const void *data, size_t len) const NOEXCEPT_MAYBE
|
||||
{
|
||||
int ret = ncplane_qrcode (plane, maxversion, data, len);
|
||||
int ret = ncplane_qrcode (plane, blitter, ymax, xmax, data, len);
|
||||
return error_guard_cond<int> (ret, ret < 0);
|
||||
}
|
||||
|
||||
|
@ -1339,6 +1339,9 @@ ncplane_align(const struct ncplane* n, ncalign_e align, int c){
|
||||
// plane's dimensions.
|
||||
API int ncplane_cursor_move_yx(struct ncplane* n, int y, int x);
|
||||
|
||||
// Move the cursor to 0, 0. Can't fail.
|
||||
API void ncplane_home(struct ncplane* n);
|
||||
|
||||
// Get the current position of the cursor within n. y and/or x may be NULL.
|
||||
API void ncplane_cursor_yx(const struct ncplane* n, int* RESTRICT y, int* RESTRICT x);
|
||||
|
||||
@ -1998,12 +2001,24 @@ ncplane_fg_alpha(const struct ncplane* nc){
|
||||
return channels_fg_alpha(ncplane_channels(nc));
|
||||
}
|
||||
|
||||
// Is the plane's foreground using the "default foreground color"?
|
||||
static inline bool
|
||||
ncplane_fg_default_p(const struct ncplane* nc){
|
||||
return channels_fg_default_p(ncplane_channels(nc));
|
||||
}
|
||||
|
||||
// Extract 2 bits of background alpha from 'struct ncplane', shifted to LSBs.
|
||||
static inline unsigned
|
||||
ncplane_bg_alpha(const struct ncplane* nc){
|
||||
return channels_bg_alpha(ncplane_channels(nc));
|
||||
}
|
||||
|
||||
// Is the plane's background using the "default background color"?
|
||||
static inline bool
|
||||
ncplane_bg_default_p(const struct ncplane* nc){
|
||||
return channels_bg_default_p(ncplane_channels(nc));
|
||||
}
|
||||
|
||||
// Extract 24 bits of foreground RGB from 'n', split into components.
|
||||
static inline unsigned
|
||||
ncplane_fg_rgb(const struct ncplane* n, unsigned* r, unsigned* g, unsigned* b){
|
||||
@ -2947,11 +2962,10 @@ API int ncsubproc_destroy(struct ncsubproc* n);
|
||||
// Draw a QR code at the current position on the plane. If there is insufficient
|
||||
// room to draw the code here, or there is any other error, non-zero will be
|
||||
// returned. Otherwise, the QR code "version" (size) is returned. The QR code
|
||||
// is (version * 4 + 17) columns wide, and ⌈version * 4 + 17 / 2⌉ rows tall. If
|
||||
// maxversion is not zero, it plays a hard limit on the QR code size. Though the
|
||||
// max version of current QR codes is 40, greater values are allowed, for
|
||||
// future compatability (provide 0 for no artificial bound).
|
||||
API int ncplane_qrcode(struct ncplane* n, int maxversion, const void* data, size_t len);
|
||||
// is (version * 4 + 17) columns wide, and ⌈version * 4 + 17⌉ rows tall (the
|
||||
// properly-scaled values are written back to '*ymax' and '*xmax').
|
||||
API int ncplane_qrcode(struct ncplane* n, ncblitter_e blitter, int* ymax,
|
||||
int* xmax, const void* data, size_t len);
|
||||
|
||||
#define NCREADER_OPTION_HORSCROLL 0x0001ull
|
||||
#define NCREADER_OPTION_VERSCROLL 0x0002ull
|
||||
|
@ -502,6 +502,7 @@ void ncreader_destroy(struct ncreader* n, char** contents);
|
||||
int ncplane_puttext(struct ncplane* n, int y, ncalign_e align, const char* text, size_t* bytes);
|
||||
int ncplane_putnstr_yx(struct ncplane* n, int y, int x, size_t s, const char* gclusters);
|
||||
int ncplane_putnstr_aligned(struct ncplane* n, int y, ncalign_e align, size_t s, const char* gclustarr);
|
||||
int ncplane_qrcode(struct ncplane* n, ncblitter_e blitter, int* ymax, int* xmax, const void* data, size_t len);
|
||||
""")
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
@ -55,7 +55,7 @@ int allglyphs_demo(struct notcurses* nc){
|
||||
int dimy, dimx;
|
||||
struct ncplane* n = notcurses_stddim_yx(nc, &dimy, &dimx);
|
||||
ncplane_erase(n);
|
||||
ncplane_cursor_move_yx(n, 0, 0);
|
||||
ncplane_home(n);
|
||||
uint32_t tl = 0, tr = 0, bl = 0, br = 0;
|
||||
channel_set_rgb(&tl, 0, 0, 0);
|
||||
channel_set_rgb(&tr, 0, 0xff, 0);
|
||||
|
@ -7,30 +7,32 @@ static int y, x, dy, dx;
|
||||
|
||||
static int
|
||||
dragonmayer(struct ncvisual* ncv, const char* str, int iters){
|
||||
int total = 0;
|
||||
char c;
|
||||
int r;
|
||||
while( (c = *str++) ){
|
||||
switch(c){
|
||||
case 'X':
|
||||
if(iters > 1){
|
||||
if( (r = dragonmayer(ncv, "X+YF+", iters - 1)) ){
|
||||
if((r = dragonmayer(ncv, "X+YF+", iters - 1)) < 0){
|
||||
return r;
|
||||
}
|
||||
total += r;
|
||||
}
|
||||
break;
|
||||
case 'Y':
|
||||
if(iters > 1){
|
||||
if( (r = dragonmayer(ncv, "-FX-Y", iters - 1)) ){
|
||||
if((r = dragonmayer(ncv, "-FX-Y", iters - 1)) < 0){
|
||||
return r;
|
||||
}
|
||||
total += r;
|
||||
}
|
||||
break;
|
||||
case '+': { int tmp = dy; dy = -dx; dx = tmp; break; }
|
||||
case '-': { int tmp = -dy; dy = dx; dx = tmp; break; }
|
||||
case 'F': // FIXME want a line
|
||||
// FIXME some of these will fail...hella lame, check against dims
|
||||
if(ncvisual_set_yx(ncv, y, x, pixel) < 0){
|
||||
done = true;
|
||||
if(ncvisual_set_yx(ncv, y, x, pixel) == 0){
|
||||
++total;
|
||||
}
|
||||
x += dx;
|
||||
y += dy;
|
||||
@ -39,7 +41,7 @@ dragonmayer(struct ncvisual* ncv, const char* str, int iters){
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return total;
|
||||
}
|
||||
|
||||
int dragon_demo(struct notcurses* nc){
|
||||
@ -78,17 +80,20 @@ int dragon_demo(struct notcurses* nc){
|
||||
free(rgba);
|
||||
struct timespec scaled;
|
||||
timespec_div(&demodelay, 4, &scaled);
|
||||
int lasttotal = 0;
|
||||
int iters = 0;
|
||||
int r = 0;
|
||||
do{
|
||||
++iters;
|
||||
lasttotal = r;
|
||||
pixel = 0xffffffffull;
|
||||
ncpixel_set_rgb(&pixel, 0, 0x11 * iters, 0);
|
||||
ncpixel_set_rgb(&pixel, 0, 0xb * iters, 0);
|
||||
dx = dxstart;
|
||||
dy = dystart;
|
||||
x = dimx / 2;
|
||||
y = dimy / 2;
|
||||
int r = dragonmayer(ncv, LINDENSTART, iters);
|
||||
if(r){
|
||||
y = dimy / 3;
|
||||
r = dragonmayer(ncv, LINDENSTART, iters);
|
||||
if(r < 0){
|
||||
ncvisual_destroy(ncv);
|
||||
return r;
|
||||
}
|
||||
@ -102,8 +107,7 @@ int dragon_demo(struct notcurses* nc){
|
||||
}
|
||||
DEMO_RENDER(nc);
|
||||
demo_nanosleep(nc, &scaled);
|
||||
ncplane_erase(n);
|
||||
}while(!done);
|
||||
}while(lasttotal != r);
|
||||
ncvisual_destroy(ncv);
|
||||
return 0;
|
||||
}
|
||||
|
@ -51,11 +51,11 @@ zoom_map(struct notcurses* nc, const char* map, int* ret){
|
||||
// we start at the lower left corner of the outzoomed map
|
||||
int truex, truey; // dimensions of true display
|
||||
notcurses_term_dim_yx(nc, &truey, &truex);
|
||||
int delty = yscale;
|
||||
int deltx = xscale;
|
||||
int delty = 2;
|
||||
int deltx = 2;
|
||||
if(truey > truex){
|
||||
++delty;
|
||||
}else if(truex > truey * 2){
|
||||
}else if(truex > truey){
|
||||
++deltx;
|
||||
}
|
||||
// to zoom in on the map, we're going to scale the full image to a plane
|
||||
|
@ -32,9 +32,7 @@ int intro(struct notcurses* nc){
|
||||
channel_set_rgb(&ccll, 0x88, 0, 0xcc);
|
||||
channel_set_rgb(&cclr, 0, 0, 0);
|
||||
// we use full block rather+fg than space+bg to conflict less with the menu
|
||||
if(ncplane_cursor_move_yx(ncp, 0, 0)){
|
||||
return -1;
|
||||
}
|
||||
ncplane_home(ncp);
|
||||
if(ncplane_highgradient_sized(ncp, ccul, ccur, ccll, cclr, rows, cols) <= 0){
|
||||
return -1;
|
||||
}
|
||||
|
@ -199,12 +199,12 @@ int normal_demo(struct notcurses* nc){
|
||||
}
|
||||
if(notcurses_canutf8(nc)){
|
||||
ncplane_erase(nstd);
|
||||
ncplane_cursor_move_yx(n, 0, 0);
|
||||
ncplane_home(n);
|
||||
if(rotate_plane(nc, n)){
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
ncplane_cursor_move_yx(n, 0, 0);
|
||||
ncplane_home(n);
|
||||
uint64_t tl, tr, bl, br;
|
||||
tl = tr = bl = br = 0;
|
||||
channels_set_fg_rgb(&tl, 0, 0, 0);
|
||||
|
@ -1,20 +1,5 @@
|
||||
#include "demo.h"
|
||||
|
||||
#ifdef USE_QRCODEGEN
|
||||
#include <sys/random.h>
|
||||
// FIXME duplicated--ought these just be exported?
|
||||
#define QR_BASE_SIZE 17
|
||||
#define PER_QR_VERSION 4
|
||||
static inline int
|
||||
qrcode_rows(int version){
|
||||
return (QR_BASE_SIZE + (version * PER_QR_VERSION)) / 2;
|
||||
}
|
||||
|
||||
static inline int
|
||||
qrcode_cols(int version){
|
||||
return QR_BASE_SIZE + (version * PER_QR_VERSION);
|
||||
}
|
||||
#endif
|
||||
|
||||
int qrcode_demo(struct notcurses* nc){
|
||||
if(!notcurses_canutf8(nc)){
|
||||
@ -36,33 +21,19 @@ int qrcode_demo(struct notcurses* nc){
|
||||
memcpy(data + done, &r, sizeof(r));
|
||||
done += sizeof(r);
|
||||
}
|
||||
if(ncplane_cursor_move_yx(n, 0, 0)){
|
||||
ncplane_destroy(n);
|
||||
return -1;
|
||||
}
|
||||
int qlen = ncplane_qrcode(n, 0, data, len);
|
||||
// can fail due to being too large for the terminal (FIXME), or ASCII mode
|
||||
if(qlen > 0){
|
||||
ncplane_move_yx(n, dimy / 2 - qrcode_rows(qlen) / 2,
|
||||
dimx / 2 - qrcode_cols(qlen) / 2);
|
||||
if(ncplane_cursor_move_yx(n, 0, 0)){
|
||||
ncplane_destroy(n);
|
||||
return -1;
|
||||
}
|
||||
uint64_t tl = 0, bl = 0, br = 0, tr = 0;
|
||||
channels_set_fg_rgb(&tl, random() % 255 + 1, random() % 255 + 1, random() % 255 + 1);
|
||||
channels_set_fg_rgb(&tr, random() % 255 + 1, random() % 255 + 1, random() % 255 + 1);
|
||||
channels_set_fg_rgb(&bl, random() % 255 + 1, random() % 255 + 1, random() % 255 + 1);
|
||||
channels_set_fg_rgb(&br, random() % 255 + 1, random() % 255 + 1, random() % 255 + 1);
|
||||
if(ncplane_stain(n, qrcode_rows(qlen), qrcode_cols(qlen), tl, tr, bl, br) <= 0){
|
||||
ncplane_destroy(n);
|
||||
return -1;
|
||||
}
|
||||
ncplane_home(n);
|
||||
int y = dimy, x = dimx;
|
||||
ncplane_home(n);
|
||||
int qlen = ncplane_qrcode(n, NCBLIT_DEFAULT, &y, &x, data, len);
|
||||
if(qlen > 0){ // FIXME can fail due to being too large for display; distinguish this case
|
||||
ncplane_move_yx(n, (dimy - y) / 2, (dimx - x) / 2);
|
||||
ncplane_home(n);
|
||||
ncplane_set_fg_rgb(n, random() % 255 + 1, random() % 255 + 1, random() % 255 + 1);
|
||||
DEMO_RENDER(nc);
|
||||
}
|
||||
}
|
||||
ncplane_mergedown(n, stdn); // leave the last one on-screen
|
||||
ncplane_destroy(n);
|
||||
#endif
|
||||
DEMO_RENDER(nc);
|
||||
return 0;
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ draw_block(struct ncplane* nn, uint32_t blockstart){
|
||||
cell_set_fg_rgb(&vl, 255, 255, 255);
|
||||
cell_set_bg_rgb(&hl, 0, 0, 0);
|
||||
cell_set_bg_rgb(&vl, 0, 0, 0);
|
||||
ncplane_cursor_move_yx(nn, 0, 0);
|
||||
ncplane_home(nn);
|
||||
unsigned control = NCBOXGRAD_TOP | NCBOXGRAD_BOTTOM | NCBOXGRAD_LEFT | NCBOXGRAD_RIGHT;
|
||||
if(ncplane_box_sized(nn, &ul, &ur, &ll, &lr, &hl, &vl, dimy, dimx, control)){
|
||||
return -1;
|
||||
|
@ -534,7 +534,7 @@ int ncplane_rotate_ccw(ncplane* n){
|
||||
|
||||
static inline int
|
||||
qrcode_rows(int version){
|
||||
return (QR_BASE_SIZE + (version * PER_QR_VERSION)) / 2;
|
||||
return QR_BASE_SIZE + (version * PER_QR_VERSION);
|
||||
}
|
||||
|
||||
static inline int
|
||||
@ -542,9 +542,10 @@ qrcode_cols(int version){
|
||||
return QR_BASE_SIZE + (version * PER_QR_VERSION);
|
||||
}
|
||||
|
||||
int ncplane_qrcode(ncplane* n, int maxversion, const void* data, size_t len){
|
||||
int ncplane_qrcode(ncplane* n, ncblitter_e blitter, int* ymax,
|
||||
int* xmax, const void* data, size_t len){
|
||||
const int MAX_QR_VERSION = 40; // QR library only supports up to 40
|
||||
if(maxversion < 0){
|
||||
if(*ymax <= 0 || *xmax <= 0){
|
||||
return -1;
|
||||
}
|
||||
if(len == 0){
|
||||
@ -552,25 +553,24 @@ int ncplane_qrcode(ncplane* n, int maxversion, const void* data, size_t len){
|
||||
}
|
||||
const int starty = n->y;
|
||||
const int startx = n->x;
|
||||
const int availx = n->lenx - startx;
|
||||
const int availy = n->leny - starty;
|
||||
if(availy < qrcode_rows(1)){
|
||||
if(*xmax > n->lenx - startx){
|
||||
return -1;
|
||||
}
|
||||
if(availx < qrcode_cols(1)){
|
||||
if(*ymax > n->leny - starty){
|
||||
return -1;
|
||||
}
|
||||
const int availsquare = availy * 2 < availx ? availy * 2 : availx;
|
||||
const int roomforver = (availsquare - QR_BASE_SIZE) / 4;
|
||||
if(maxversion == 0){
|
||||
maxversion = roomforver;
|
||||
}else if(maxversion > roomforver){
|
||||
maxversion = roomforver;
|
||||
if(*ymax < qrcode_rows(1)){
|
||||
return -1;
|
||||
}
|
||||
if(maxversion > MAX_QR_VERSION){
|
||||
maxversion = MAX_QR_VERSION;
|
||||
if(*xmax < qrcode_cols(1)){
|
||||
return -1;
|
||||
}
|
||||
const size_t bsize = qrcodegen_BUFFER_LEN_FOR_VERSION(maxversion);
|
||||
const int availsquare = *ymax * 2 < *xmax ? *ymax * 2 : *xmax;
|
||||
int roomforver = (availsquare - QR_BASE_SIZE) / PER_QR_VERSION;
|
||||
if(roomforver > MAX_QR_VERSION){
|
||||
roomforver = MAX_QR_VERSION;
|
||||
}
|
||||
const size_t bsize = qrcodegen_BUFFER_LEN_FOR_VERSION(roomforver);
|
||||
if(bsize < len){
|
||||
return -1;
|
||||
}
|
||||
@ -581,40 +581,59 @@ int ncplane_qrcode(ncplane* n, int maxversion, const void* data, size_t len){
|
||||
free(dst);
|
||||
return -1;
|
||||
}
|
||||
unsigned r, g, b;
|
||||
// FIXME default might not be all-white
|
||||
if(ncplane_fg_default_p(n)){
|
||||
r = g = b = 0xff;
|
||||
}else{
|
||||
ncplane_fg_rgb(n, &r, &g, &b);
|
||||
}
|
||||
memcpy(src, data, len);
|
||||
int ret = -1;
|
||||
if(qrcodegen_encodeBinary(src, len, dst, qrcodegen_Ecc_HIGH, 1, maxversion, qrcodegen_Mask_AUTO, true)){
|
||||
ret = qrcodegen_getSize(dst);
|
||||
for(int y = starty ; y < starty + (ret + 1) / 2 ; ++y){
|
||||
for(int x = startx ; x < startx + ret ; ++x){
|
||||
const bool top = qrcodegen_getModule(dst, x, y);
|
||||
const bool bot = qrcodegen_getModule(dst, x, y + 1);
|
||||
const char* egc;
|
||||
if(top && bot){
|
||||
egc = "█";
|
||||
}else if(top){
|
||||
egc = "▀";
|
||||
}else if(bot){
|
||||
egc = "▄";
|
||||
}else{
|
||||
egc = " ";
|
||||
int yscale, xscale;
|
||||
if(qrcodegen_encodeBinary(src, len, dst, qrcodegen_Ecc_HIGH, 1, roomforver, qrcodegen_Mask_AUTO, true)){
|
||||
const int square = qrcodegen_getSize(dst);
|
||||
uint32_t* rgba = malloc(square * square * sizeof(uint32_t));
|
||||
if(rgba){
|
||||
for(int y = starty ; y < starty + square ; ++y){
|
||||
for(int x = startx ; x < startx + square ; ++x){
|
||||
const bool pixel = qrcodegen_getModule(dst, x, y);
|
||||
ncpixel_set_a(&rgba[y * square + x], 0xff);
|
||||
ncpixel_set_rgb(&rgba[y * square + x], r * pixel, g * pixel, b * pixel);
|
||||
}
|
||||
int sbytes;
|
||||
if(ncplane_putegc_yx(n, y, x, egc, &sbytes) <= 0){
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
struct ncvisual* ncv = ncvisual_from_rgba(rgba, square, square * sizeof(uint32_t), square);
|
||||
free(rgba);
|
||||
if(ncv){
|
||||
ret = square;
|
||||
struct ncvisual_options vopts = {
|
||||
.n = n,
|
||||
.blitter = blitter,
|
||||
};
|
||||
if(ncvisual_render(n->nc, ncv, &vopts) == n){
|
||||
ret = square;
|
||||
}
|
||||
ncvisual_geom(n->nc, ncv, &vopts, NULL, NULL, &yscale, &xscale);
|
||||
}
|
||||
}
|
||||
}
|
||||
free(src);
|
||||
free(dst);
|
||||
return ret < 0 ? ret : (ret - QR_BASE_SIZE) / PER_QR_VERSION;
|
||||
if(ret > 0){
|
||||
ret = (ret - QR_BASE_SIZE) / PER_QR_VERSION;
|
||||
*ymax = qrcode_rows(ret) / yscale;
|
||||
*xmax = qrcode_cols(ret) / xscale;
|
||||
return ret;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
int ncplane_qrcode(ncplane* n, int maxversion, const void* data, size_t len){
|
||||
int ncplane_qrcode(ncplane* n, ncblitter_e blitter, int* ymax, int* xmax,
|
||||
const void* data, size_t len){
|
||||
(void)n;
|
||||
(void)maxversion;
|
||||
(void)blitter;
|
||||
(void)ymax;
|
||||
(void)xmax;
|
||||
(void)data;
|
||||
(void)len;
|
||||
return -1;
|
||||
|
@ -340,6 +340,11 @@ ncplane* ncplane_aligned(ncplane* n, int rows, int cols, int yoff,
|
||||
return ncplane_create(n->nc, n, rows, cols, yoff, ncplane_align(n, align, cols), opaque);
|
||||
}
|
||||
|
||||
void ncplane_home(ncplane* n){
|
||||
n->x = 0;
|
||||
n->y = 0;
|
||||
}
|
||||
|
||||
inline int ncplane_cursor_move_yx(ncplane* n, int y, int x){
|
||||
if(x >= n->lenx){
|
||||
return -1;
|
||||
|
@ -241,9 +241,7 @@ class ncppplot {
|
||||
}
|
||||
}
|
||||
}
|
||||
if(ncplane_cursor_move_yx(ncp, 0, 0)){
|
||||
return -1;
|
||||
}
|
||||
ncplane_home(ncp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -142,7 +142,7 @@ int runreels(NotCurses& nc, ncreel_options& nopts){
|
||||
case 'q':
|
||||
return 0;
|
||||
case 'a':{
|
||||
TabletCtx* tctx = new TabletCtx();
|
||||
auto tctx = new TabletCtx();
|
||||
nr->add(nullptr, nullptr, tabletfxn, tctx);
|
||||
break;
|
||||
}
|
||||
|
47
src/poc/qrcode.c
Normal file
47
src/poc/qrcode.c
Normal file
@ -0,0 +1,47 @@
|
||||
#include <unistd.h>
|
||||
#include <locale.h>
|
||||
#include <notcurses/notcurses.h>
|
||||
|
||||
static int
|
||||
render_qrcode(struct ncplane* n, int dimy, int dimx, const char* text){
|
||||
int y = dimy, x = dimx;
|
||||
ncplane_home(n);
|
||||
int ver = ncplane_qrcode(n, NCBLIT_DEFAULT, &y, &x, text, strlen(text));
|
||||
if(ver < 0){
|
||||
return -1;
|
||||
}
|
||||
if(ncplane_putstr_yx(n, y + 1, 0, text) < 0){
|
||||
return -1;
|
||||
}
|
||||
if(notcurses_render(ncplane_notcurses(n))){
|
||||
return -1;
|
||||
}
|
||||
sleep(2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, const char** argv){
|
||||
if(setlocale(LC_ALL, "") == NULL){
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
struct notcurses_options opts = {
|
||||
.flags = NCOPTION_INHIBIT_SETLOCALE | NCOPTION_NO_ALTERNATE_SCREEN,
|
||||
};
|
||||
struct notcurses* nc = notcurses_init(&opts, NULL);
|
||||
int dimy, dimx;
|
||||
struct ncplane* std = notcurses_stddim_yx(nc, &dimy, &dimx);
|
||||
while(*++argv){
|
||||
if(render_qrcode(std, dimy, dimx, *argv)){
|
||||
notcurses_stop(nc);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
if(argc < 2){
|
||||
if(render_qrcode(std, dimy, dimx, "https://nick-black.com")){
|
||||
notcurses_stop(nc);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
notcurses_stop(nc);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
@ -12,7 +12,7 @@ rotate_grad(struct notcurses* nc){
|
||||
};
|
||||
int dimy, dimx;
|
||||
struct ncplane* n = notcurses_stddim_yx(nc, &dimy, &dimx);
|
||||
ncplane_cursor_move_yx(n, 0, 0);
|
||||
ncplane_home(n);
|
||||
uint32_t tl = 0, tr = 0, bl = 0, br = 0;
|
||||
channel_set_rgb(&tl, 0xff, 0, 0);
|
||||
channel_set_rgb(&tr, 0, 0, 0xff);
|
||||
|
@ -440,7 +440,9 @@ TEST_CASE("Fills") {
|
||||
#ifdef USE_QRCODEGEN
|
||||
SUBCASE("QRCodes") {
|
||||
const char* qr = "a very simple qr code";
|
||||
CHECK(0 < ncplane_qrcode(n_, 0, qr, strlen(qr)));
|
||||
int dimy, dimx;
|
||||
ncplane_dim_yx(n_, &dimy, &dimx);
|
||||
CHECK(0 < ncplane_qrcode(n_, NCBLIT_DEFAULT, &dimy, &dimx, qr, strlen(qr)));
|
||||
CHECK(0 == notcurses_render(nc_));
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user