4 for(
unsigned y = 0 ;
y <
n->leny ; ++
y){
5 for(
unsigned x = 0 ;
x <
n->lenx ; ++
x){
8 nccell_fg_rgb8(
c, &
r, &g, &b);
9 int gy = rgb_greyscale(
r, g, b);
10 nccell_set_fg_rgb8(
c, gy, gy, gy);
11 nccell_bg_rgb8(
c, &
r, &g, &b);
12 gy = rgb_greyscale(
r, g, b);
13 nccell_set_bg_rgb8(
c, gy, gy, gy);
23ncplane_polyfill_inner(
ncplane*
n,
unsigned y,
unsigned x,
const nccell*
c,
const char* filltarg){
25 if(create_polyfill_op(
y,
x, &stack) ==
NULL){
38 if(strcmp(glust, filltarg) == 0){
45 if(create_polyfill_op(
y - 1,
x, &stack) ==
NULL){
50 if(create_polyfill_op(
y + 1,
x, &stack) ==
NULL){
55 if(create_polyfill_op(
y,
x - 1, &stack) ==
NULL){
60 if(create_polyfill_op(
y,
x + 1, &stack) ==
NULL){
97 if(
y >=
n->leny ||
x >=
n->lenx){
98 logerror(
"invalid start: %u/%u (%u/%u)",
y,
x,
n->leny,
n->lenx);
101 const nccell* cur = &
n->fb[nfbcellidx(
n,
y,
x)];
105 if(strcmp(fillegc, targ) == 0){
111 char* targcopy = strdup(targ);
113 ret = ncplane_polyfill_inner(
n,
y,
x,
c, targcopy);
120check_gradient_channel_args(uint32_t
ul, uint32_t
ur, uint32_t bl, uint32_t br){
121 if(ncchannel_default_p(
ul) || ncchannel_default_p(
ur) ||
122 ncchannel_default_p(bl) || ncchannel_default_p(br)){
123 if(!(ncchannel_default_p(
ul) && ncchannel_default_p(
ur) &&
124 ncchannel_default_p(bl) && ncchannel_default_p(br))){
125 logerror(
"some (not all) channels were defaults");
129 if(ncchannel_alpha(
ul) != ncchannel_alpha(
ur) ||
130 ncchannel_alpha(
ur) != ncchannel_alpha(bl) ||
131 ncchannel_alpha(bl) != ncchannel_alpha(br)){
132 logerror(
"channel alphas didn't match");
135 if(ncchannel_palindex_p(
ul) || ncchannel_palindex_p(bl) ||
136 ncchannel_palindex_p(br) || ncchannel_palindex_p(
ur)){
137 logerror(
"can't blend palette-indexed color");
151 if(check_gradient_channel_args(ncchannels_fchannel(
ul), ncchannels_fchannel(
ur),
152 ncchannels_fchannel(bl), ncchannels_fchannel(br))){
155 if(check_gradient_channel_args(ncchannels_bchannel(
ul), ncchannels_bchannel(
ur),
156 ncchannels_bchannel(bl), ncchannels_bchannel(br))){
165calc_highgradient(
nccell*
c, uint32_t
ul, uint32_t
ur, uint32_t
ll,
166 uint32_t
lr,
unsigned y,
unsigned x,
168 if(!ncchannel_default_p(
ul)){
169 cell_set_fchannel(
c, calc_gradient_channel(
ul,
ur,
ll,
lr,
171 cell_set_bchannel(
c, calc_gradient_channel(
ul,
ur,
ll,
lr,
174 nccell_set_fg_default(
c);
175 nccell_set_bg_default(
c);
180 uint32_t
ul, uint32_t
ur, uint32_t
ll, uint32_t
lr){
182 logerror(
"highdef gradients require utf8");
185 if(check_gradient_channel_args(
ul,
ur,
ll,
lr)){
188 unsigned ystart, xstart;
189 if(check_geometry_args(
n,
y,
x, &
ylen, &
xlen, &ystart, &xstart)){
194 logerror(
"horizontal channel variation in single column");
199 for(
unsigned yy = ystart ; yy < ystart +
ylen ; ++yy){
200 for(
unsigned xx = xstart ; xx < xstart +
xlen ; ++xx){
201 nccell* targc = ncplane_cell_ref_yx(
n, yy, xx);
203 if(pool_blit_direct(&
n->pool, targc,
"▀", strlen(
"▀"), 1) <= 0){
206 calc_highgradient(targc,
ul,
ur,
ll,
lr, yy - ystart, xx - xstart,
ylen * 2,
xlen);
222 return ncplane_gradient(
n, -1, -1,
ylen,
xlen,
" ", 0,
ul,
ur,
ll,
lr);
228 const char*
egc, uint16_t stylemask,
229 uint64_t
ul, uint64_t
ur, uint64_t bl, uint64_t br){
233 unsigned ystart, xstart;
234 if(check_geometry_args(
n,
y,
x, &
ylen, &
xlen, &ystart, &xstart)){
239 if(
ul !=
ur ||
ur != br || br != bl){
240 logerror(
"channel variation in 1x1 area");
244 if(
ul != bl ||
ur != br){
245 logerror(
"vertical channel variation in single row");
250 if(
ul !=
ur || bl != br){
251 logerror(
"horizontal channel variation in single column");
256 for(
unsigned yy = ystart ; yy < ystart +
ylen ; ++yy){
257 for(
unsigned xx = xstart ; xx < xstart +
xlen ; ++xx){
258 nccell* targc = ncplane_cell_ref_yx(
n, yy, xx);
264 calc_gradient_channels(&targc->
channels,
ul,
ur, bl, br,
265 yy - ystart, xx - xstart,
ylen,
xlen);
273 uint64_t tl, uint64_t tr, uint64_t bl, uint64_t br){
278 unsigned ystart, xstart;
279 if(check_geometry_args(
n,
y,
x, &
ylen, &
xlen, &ystart, &xstart)){
283 for(
unsigned yy = ystart ; yy < ystart +
ylen ; ++yy){
284 for(
unsigned xx = xstart ; xx < xstart +
xlen ; ++xx){
285 nccell* targc = ncplane_cell_ref_yx(
n, yy, xx);
287 calc_gradient_channels(&targc->
channels, tl, tr, bl, br,
288 yy - ystart, xx - xstart,
ylen,
xlen);
297 unsigned xlen, uint16_t stylemask){
298 unsigned ystart, xstart;
299 if(check_geometry_args(
n,
y,
x, &
ylen, &
xlen, &ystart, &xstart)){
303 for(
unsigned yy = ystart ; yy < ystart +
ylen ; ++yy){
304 for(
unsigned xx = xstart ; xx < xstart +
xlen ; ++xx){
305 nccell* targc = ncplane_cell_ref_yx(
n, yy, xx);
316rotate_channels(
ncplane* src,
const nccell*
c, uint32_t* fchan, uint32_t* bchan){
318 if(
egc[0] ==
' ' ||
egc[0] == 0){
321 }
else if(strcmp(
egc,
"▄") == 0 || strcmp(
egc,
"▀") == 0){
322 uint32_t tmp = *fchan;
326 }
else if(strcmp(
egc,
"█") == 0){
335rotate_output(
ncplane* dst, uint32_t tchan, uint32_t bchan){
336 dst->
channels = ncchannels_combine(tchan, bchan);
338 return ncplane_putegc(dst,
"▀",
NULL);
340 if(ncchannel_default_p(tchan) && ncchannel_default_p(bchan)){
341 return ncplane_putegc(dst,
"",
NULL);
342 }
else if(ncchannel_default_p(tchan)){
343 return ncplane_putegc(dst,
" ",
NULL);
345 return ncplane_putegc(dst,
"█",
NULL);
376rotate_2x1_cw(
ncplane* src,
ncplane* dst,
int srcy,
int srcx,
int dsty,
int dstx){
397 uint32_t c1b = cell_bchannel_common(&c1);
398 uint32_t c2b = cell_bchannel_common(&c2);
399 uint32_t c1t = cell_fchannel_common(&c1);
400 uint32_t c2t = cell_fchannel_common(&c2);
402 ret |= rotate_channels(src, &c1, &c1t, &c1b);
403 ret |= rotate_channels(src, &c2, &c2t, &c2b);
411 rotate_output(dst, c1b, c2b);
412 rotate_output(dst, c1t, c2t);
417rotate_2x1_ccw(
ncplane* src,
ncplane* dst,
int srcy,
int srcx,
int dsty,
int dstx){
427 uint32_t c1b = cell_bchannel_common(&c1);
428 unsigned c2b = cell_bchannel_common(&c2);
429 unsigned c1t = cell_fchannel_common(&c1);
430 unsigned c2t = cell_fchannel_common(&c2);
432 ret |= rotate_channels(src, &c1, &c1t, &c1b);
433 ret |= rotate_channels(src, &c2, &c2t, &c2b);
435 rotate_output(dst, c1t, c2t);
436 rotate_output(dst, c1b, c2b);
447 for(
unsigned y = 0 ;
y < dimy ; ++
y){
448 for(
unsigned x = 0 ;
x < dimx ; ++
x){
449 const nccell* src = &newp->
fb[fbcellidx(
y, dimx,
x)];
450 nccell* targ = &
n->fb[fbcellidx(
y, dimx,
x)];
451 if(cell_duplicate_far(&
n->pool, targ, newp, src) < 0){
470 const int newy = dimx / 2;
471 const int newx = dimy * 2;
477 .userptr =
n->userptr,
498 int targx, targy = 0;
499 for(
unsigned x = 0 ;
x < dimx ;
x += 2){
501 for(
int y = (
int)dimy - 1 ;
y >= 0 ; --
y){
502 if(rotate_2x1_cw(
n, newp,
y,
x, targy, targx)){
510 int ret = rotate_merge(
n, newp);
520 unsigned dimy, dimx, targdimy, targdimx;
523 int x = (int)dimx - 2;
527 for(
unsigned targy = 0 ; targy < targdimy ; ++targy){
529 for(
unsigned targx = 0 ; targx < targdimx ; targx += 2){
530 if(rotate_2x1_ccw(
n, newp,
y,
x, targy, targx)){
538 int ret = rotate_merge(
n, newp);
544#include <qrcodegen/qrcodegen.h>
545#define QR_BASE_SIZE 17
546#define PER_QR_VERSION 4
548static inline unsigned
549qrcode_rows(
unsigned version){
550 return QR_BASE_SIZE + (version * PER_QR_VERSION);
553static inline unsigned
554qrcode_cols(
unsigned version){
555 return QR_BASE_SIZE + (version * PER_QR_VERSION);
560 const int MAX_QR_VERSION = 40;
561 if(*ymax <= 0 || *xmax <= 0){
567 const int starty =
n->y;
568 const int startx =
n->x;
569 if(*xmax >
n->lenx - startx){
572 if(*ymax >
n->leny - starty){
575 if(*ymax * 2 < qrcode_rows(1)){
578 if(*xmax < qrcode_cols(1)){
581 const int availsquare = *ymax * 2 < *xmax ? *ymax * 2 : *xmax;
582 int roomforver = (availsquare - QR_BASE_SIZE) / PER_QR_VERSION;
583 if(roomforver > MAX_QR_VERSION){
584 roomforver = MAX_QR_VERSION;
586 const size_t bsize = qrcodegen_BUFFER_LEN_FOR_VERSION(roomforver);
590 uint8_t* src = malloc(bsize);
591 uint8_t* dst = malloc(bsize);
599 if(ncplane_fg_default_p(
n)){
602 ncplane_fg_rgb8(
n, &
r, &g, &b);
604 memcpy(src, data,
len);
607 if(qrcodegen_encodeBinary(src,
len, dst, qrcodegen_Ecc_HIGH, 1, roomforver, qrcodegen_Mask_AUTO,
true)){
608 const int square = qrcodegen_getSize(dst);
609 uint32_t* rgba = malloc(square * square *
sizeof(uint32_t));
611 for(
int y = starty ;
y < starty + square ; ++
y){
612 for(
int x = startx ;
x < startx + square ; ++
x){
613 const bool pixel = qrcodegen_getModule(dst,
x,
y);
614 ncpixel_set_a(&rgba[
y * square +
x], 0xff);
615 ncpixel_set_rgb8(&rgba[
y * square +
x],
r * pixel, g * pixel, b * pixel);
643 ret = (ret - QR_BASE_SIZE) / PER_QR_VERSION;
644 *ymax = qrcode_rows(ret) / yscale;
645 *xmax = qrcode_cols(ret) / xscale;
API int API int API int uint64_t uint64_t uint64_t uint64_t lr
API int API int API int uint64_t uint64_t uint64_t ll
API int API int API int uint64_t uint64_t uint64_t uint64_t unsigned unsigned xlen
API int API int API int uint64_t uint64_t uint64_t uint64_t unsigned ylen
API int API int API int uint64_t ul
API int API int API int uint64_t uint64_t ur
int ncplane_gradient2x1(ncplane *n, int y, int x, unsigned ylen, unsigned xlen, uint32_t ul, uint32_t ur, uint32_t ll, uint32_t lr)
void ncplane_greyscale(ncplane *n)
int ncplane_rotate_ccw(ncplane *n)
int ncplane_polyfill_yx(ncplane *n, int ystart, int xstart, const nccell *c)
int ncplane_gradient(ncplane *n, int y, int x, unsigned ylen, unsigned xlen, const char *egc, uint16_t stylemask, uint64_t ul, uint64_t ur, uint64_t bl, uint64_t br)
bool check_gradient_args(uint64_t ul, uint64_t ur, uint64_t bl, uint64_t br)
int ncplane_format(ncplane *n, int y, int x, unsigned ylen, unsigned xlen, uint16_t stylemask)
int ncplane_qrcode(ncplane *n, unsigned *ymax, unsigned *xmax, const void *data, size_t len)
int ncplane_stain(ncplane *n, int y, int x, unsigned ylen, unsigned xlen, uint64_t tl, uint64_t tr, uint64_t bl, uint64_t br)
int ncplane_rotate_cw(ncplane *n)
int ncplane_highgradient_sized(ncplane *n, uint32_t ul, uint32_t ur, uint32_t ll, uint32_t lr, int ylen, int xlen)
#define logerror(fmt,...)
int ncplane_cursor_move_yx(ncplane *n, int y, int x)
int ncplane_destroy(ncplane *ncp)
const char * nccell_extended_gcluster(const ncplane *n, const nccell *c)
const notcurses * ncplane_notcurses_const(const ncplane *n)
int nccell_load(ncplane *n, nccell *c, const char *gcluster)
void ncplane_yx(const ncplane *n, int *y, int *x)
int ncplane_at_yx_cell(ncplane *n, int y, int x, nccell *c)
int ncplane_resize(ncplane *n, int keepy, int keepx, unsigned keepleny, unsigned keeplenx, int yoff, int xoff, unsigned ylen, unsigned xlen)
notcurses * ncplane_notcurses(const ncplane *n)
ncplane * ncplane_create(ncplane *n, const ncplane_options *nopts)
void ncplane_center_abs(const ncplane *n, int *RESTRICT y, int *RESTRICT x)
void ncplane_dim_yx(const ncplane *n, unsigned *rows, unsigned *cols)
const struct ncplane_options struct ncvisual * ncv
const struct ncplane_options struct ncvisual struct ncvisual_options * vopts
#define NCCELL_TRIVIAL_INITIALIZER
API int API int const nccell unsigned len
#define NCVISUAL_OPTION_NODEGRADE
void nccell_release(ncplane *n, nccell *c)
int nccell_duplicate(ncplane *n, nccell *targ, const nccell *c)
ncvisual * ncvisual_from_rgba(const void *rgba, int rows, int rowstride, int cols)
void ncvisual_destroy(ncvisual *ncv)
int ncvisual_geom(const notcurses *nc, const ncvisual *n, const struct ncvisual_options *vopts, ncvgeom *geom)
ncplane * ncvisual_blit(notcurses *nc, ncvisual *ncv, const struct ncvisual_options *vopts)