Notcurses 3.0.16
a blingful library for TUIs and character graphics
Loading...
Searching...
No Matches
fill.c
Go to the documentation of this file.
1#include "internal.h"
2
4 for(unsigned y = 0 ; y < n->leny ; ++y){
5 for(unsigned x = 0 ; x < n->lenx ; ++x){
6 nccell* c = &n->fb[nfbcellidx(n, y, x)];
7 unsigned r, g, b;
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);
14 }
15 }
16}
17
18// if this is not polyfillable cell, we return 0. if it is, we attempt to fill
19// it, then recurse out. return -1 on error, or number of cells filled on
20// success. so a return of 0 means there's no work to be done here, and N means
21// we did some work here, filling everything we could reach. out-of-plane is 0.
22static int
23ncplane_polyfill_inner(ncplane* n, unsigned y, unsigned x, const nccell* c, const char* filltarg){
24 struct topolyfill* stack = NULL;
25 if(create_polyfill_op(y, x, &stack) == NULL){
26 return -1;
27 }
28 int ret = 0;
29 struct topolyfill* s;
30 do{
31 s = stack;
32 stack = stack->next;
33 y = s->y;
34 x = s->x;
35 nccell* cur = &n->fb[nfbcellidx(n, y, x)];
36 const char* glust = nccell_extended_gcluster(n, cur);
37//fprintf(stderr, "checking %d/%d (%s) for [%s]\n", y, x, glust, filltarg);
38 if(strcmp(glust, filltarg) == 0){
39 ++ret;
40 if(nccell_duplicate(n, cur, c) < 0){
41 goto err;
42 }
43//fprintf(stderr, "blooming from %d/%d ret: %d\n", y, x, ret);
44 if(y){
45 if(create_polyfill_op(y - 1, x, &stack) == NULL){
46 goto err;
47 }
48 }
49 if(y + 1 < n->leny){
50 if(create_polyfill_op(y + 1, x, &stack) == NULL){
51 goto err;
52 }
53 }
54 if(x){
55 if(create_polyfill_op(y, x - 1, &stack) == NULL){
56 goto err;
57 }
58 }
59 if(x + 1 < n->lenx){
60 if(create_polyfill_op(y, x + 1, &stack) == NULL){
61 goto err;
62 }
63 }
64 }
65 free(s);
66 }while(stack);
67 return ret;
68
69err:
70 free(s);
71 while(stack){
72 struct topolyfill* tmp = stack->next;
73 free(stack);
74 stack = tmp;
75 }
76 return -1;
77}
78
79// at the initial step only, invalid ystart, xstart is an error, so explicitly check.
80int ncplane_polyfill_yx(ncplane* n, int ystart, int xstart, const nccell* c){
81 if(ystart < 0){
82 if(ystart != -1){
83 logerror("invalid y: %d", ystart);
84 return -1;
85 }
86 ystart = n->y;
87 }
88 unsigned y = ystart;
89 if(xstart < 0){
90 if(xstart != -1){
91 logerror("invalid x: %d", xstart);
92 return -1;
93 }
94 xstart = n->x;
95 }
96 unsigned x = xstart;
97 if(y >= n->leny || x >= n->lenx){
98 logerror("invalid start: %u/%u (%u/%u)", y, x, n->leny, n->lenx);
99 return -1;
100 }
101 const nccell* cur = &n->fb[nfbcellidx(n, y, x)];
102 const char* targ = nccell_extended_gcluster(n, cur);
103 const char* fillegc = nccell_extended_gcluster(n, c);
104//fprintf(stderr, "checking %d/%d (%s) for [%s]\n", y, x, targ, fillegc);
105 if(strcmp(fillegc, targ) == 0){
106 return 0;
107 }
108 int ret = -1;
109 // we need an external copy of this, since we'll be writing to it on
110 // the first call into ncplane_polyfill_inner()
111 char* targcopy = strdup(targ);
112 if(targcopy){
113 ret = ncplane_polyfill_inner(n, y, x, c, targcopy);
114 free(targcopy);
115 }
116 return ret;
117}
118
119static bool
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");
126 return true;
127 }
128 }
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");
133 return true;
134 }
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");
138 return true;
139 }
140 return false;
141}
142
143// Given the four channels arguments, verify that:
144//
145// - if any is default foreground, all are default foreground
146// - if any is default background, all are default background
147// - all foregrounds must have the same alpha
148// - all backgrounds must have the same alpha
149// - palette-indexed color must not be used
150bool check_gradient_args(uint64_t ul, uint64_t ur, uint64_t bl, uint64_t br){
151 if(check_gradient_channel_args(ncchannels_fchannel(ul), ncchannels_fchannel(ur),
152 ncchannels_fchannel(bl), ncchannels_fchannel(br))){
153 return true;
154 }
155 if(check_gradient_channel_args(ncchannels_bchannel(ul), ncchannels_bchannel(ur),
156 ncchannels_bchannel(bl), ncchannels_bchannel(br))){
157 return true;
158 }
159 return false;
160}
161
162// calculate both channels of a gradient at a particular point, knowing that
163// we're using double halfblocks, into `c`->channels.
164static inline void
165calc_highgradient(nccell* c, uint32_t ul, uint32_t ur, uint32_t ll,
166 uint32_t lr, unsigned y, unsigned x,
167 unsigned ylen, unsigned xlen){
168 if(!ncchannel_default_p(ul)){
169 cell_set_fchannel(c, calc_gradient_channel(ul, ur, ll, lr,
170 y * 2, x, ylen, xlen));
171 cell_set_bchannel(c, calc_gradient_channel(ul, ur, ll, lr,
172 y * 2 + 1, x, ylen, xlen));
173 }else{
174 nccell_set_fg_default(c);
175 nccell_set_bg_default(c);
176 }
177}
178
179int ncplane_gradient2x1(ncplane* n, int y, int x, unsigned ylen, unsigned xlen,
180 uint32_t ul, uint32_t ur, uint32_t ll, uint32_t lr){
181 if(!notcurses_canutf8(ncplane_notcurses(n))){
182 logerror("highdef gradients require utf8");
183 return -1;
184 }
185 if(check_gradient_channel_args(ul, ur, ll, lr)){
186 return -1;
187 }
188 unsigned ystart, xstart;
189 if(check_geometry_args(n, y, x, &ylen, &xlen, &ystart, &xstart)){
190 return -1;
191 }
192 if(xlen == 1){
193 if(ul != ur || ll != lr){
194 logerror("horizontal channel variation in single column");
195 return -1;
196 }
197 }
198 int total = 0;
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);
202 targc->channels = 0;
203 if(pool_blit_direct(&n->pool, targc, "▀", strlen("▀"), 1) <= 0){
204 return -1;
205 }
206 calc_highgradient(targc, ul, ur, ll, lr, yy - ystart, xx - xstart, ylen * 2, xlen);
207 ++total;
208 }
209 }
210 return total;
211}
212
213// FIXME remove in abi3
214int ncplane_highgradient_sized(ncplane* n, uint32_t ul, uint32_t ur,
215 uint32_t ll, uint32_t lr, int ylen, int xlen){
216 if(ylen < 1 || xlen < 1){
217 return -1;
218 }
219 if(!notcurses_canutf8(ncplane_notcurses_const(n))){
220 // this works because the uin32_ts we pass in will be promoted to uint64_ts
221 // via extension, and the space will employ the background. mwahh!
222 return ncplane_gradient(n, -1, -1, ylen, xlen, " ", 0, ul, ur, ll, lr);
223 }
224 return ncplane_gradient2x1(n, -1, -1, ylen, xlen, ul, ur, ll, lr);
225}
226
227int ncplane_gradient(ncplane* n, int y, int x, unsigned ylen, unsigned xlen,
228 const char* egc, uint16_t stylemask,
229 uint64_t ul, uint64_t ur, uint64_t bl, uint64_t br){
230 if(check_gradient_args(ul, ur, bl, br)){
231 return -1;
232 }
233 unsigned ystart, xstart;
234 if(check_geometry_args(n, y, x, &ylen, &xlen, &ystart, &xstart)){
235 return -1;
236 }
237 if(ylen == 1){
238 if(xlen == 1){
239 if(ul != ur || ur != br || br != bl){
240 logerror("channel variation in 1x1 area");
241 return -1;
242 }
243 }else{
244 if(ul != bl || ur != br){
245 logerror("vertical channel variation in single row");
246 return -1;
247 }
248 }
249 }else if(xlen == 1){
250 if(ul != ur || bl != br){
251 logerror("horizontal channel variation in single column");
252 return -1;
253 }
254 }
255 int total = 0;
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);
259 targc->channels = 0;
260 if(nccell_load(n, targc, egc) < 0){
261 return -1;
262 }
263 targc->stylemask = stylemask;
264 calc_gradient_channels(&targc->channels, ul, ur, bl, br,
265 yy - ystart, xx - xstart, ylen, xlen);
266 ++total;
267 }
268 }
269 return total;
270}
271
272int ncplane_stain(ncplane* n, int y, int x, unsigned ylen, unsigned xlen,
273 uint64_t tl, uint64_t tr, uint64_t bl, uint64_t br){
274 // Can't use default or palette-indexed colors in a gradient
275 if(check_gradient_args(tl, tr, bl, br)){
276 return -1;
277 }
278 unsigned ystart, xstart;
279 if(check_geometry_args(n, y, x, &ylen, &xlen, &ystart, &xstart)){
280 return -1;
281 }
282 int total = 0;
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);
286 if(targc->gcluster){
287 calc_gradient_channels(&targc->channels, tl, tr, bl, br,
288 yy - ystart, xx - xstart, ylen, xlen);
289 }
290 ++total;
291 }
292 }
293 return total;
294}
295
296int ncplane_format(ncplane* n, int y, int x, unsigned ylen,
297 unsigned xlen, uint16_t stylemask){
298 unsigned ystart, xstart;
299 if(check_geometry_args(n, y, x, &ylen, &xlen, &ystart, &xstart)){
300 return -1;
301 }
302 int total = 0;
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);
306 targc->stylemask = stylemask;
307 ++total;
308 }
309 }
310 return total;
311}
312
313// if we're a half block, reverse the channels. if we're a space, set both to
314// the background. if we're a full block, set both to the foreground.
315static int
316rotate_channels(ncplane* src, const nccell* c, uint32_t* fchan, uint32_t* bchan){
317 const char* egc = nccell_extended_gcluster(src, c);
318 if(egc[0] == ' ' || egc[0] == 0){
319 *fchan = *bchan;
320 return 0;
321 }else if(strcmp(egc, "▄") == 0 || strcmp(egc, "▀") == 0){
322 uint32_t tmp = *fchan;
323 *fchan = *bchan;
324 *bchan = tmp;
325 return 0;
326 }else if(strcmp(egc, "█") == 0){
327 *bchan = *fchan;
328 return 0;
329 }
330 logerror("invalid EGC for rotation [%s]", egc);
331 return -1;
332}
333
334static int
335rotate_output(ncplane* dst, uint32_t tchan, uint32_t bchan){
336 dst->channels = ncchannels_combine(tchan, bchan);
337 if(tchan != bchan){
338 return ncplane_putegc(dst, "▀", NULL);
339 }
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);
344 }
345 return ncplane_putegc(dst, "█", NULL);
346}
347
348// rotation works at two levels:
349// 1) each 1x2 block is rotated into a 1x2 block ala
350// ab cw ca ccw ab ccw bd ccw dc ccw ca ccw ab
351// cd --> db --> cd --> ac --> ba --> db --> cd
352// 2) each 1x2 block is rotated into its new location
353//
354// Characters which can be rotated must be RGB, to differentiate full blocks,
355// spaces, and nuls. For clockwise rotations:
356//
357// nul: converts to two half defaults
358// space: converts to two half backgrounds
359// full: converts to two half foregrounds
360// upper: converts to half background + half foreground
361// lower: converts to half foreground + half background
362//
363// Fore/background carry full channel, including transparency.
364//
365// Ideally, rotation through 360 degrees will restore the original 2x1 squre.
366// Unfortunately, the case where a half block occupies a cell having the same
367// fore- and background will see it rotated into a single full block. In
368// addition, lower blocks eventually become upper blocks with their channels
369// reversed. In general:
370//
371// if a "row" (the bottom or top halves) are the same forechannel, merge to a
372// single full block of that color (what is its background?).
373// if a "row" is two different channels, they become a upper block (why not
374// lower?) having the two channels as fore- and background.
375static int
376rotate_2x1_cw(ncplane* src, ncplane* dst, int srcy, int srcx, int dsty, int dstx){
379 if(ncplane_at_yx_cell(src, srcy, srcx, &c1) < 0){
380 return -1;
381 }
382 if(ncplane_at_yx_cell(src, srcy, srcx + 1, &c2) < 0){
383 nccell_release(src, &c1);
384 return -1;
385 }
386 // there can be at most 4 colors and 4 transparencies:
387 // - c1fg, c1bg, c2fg, c2bg, c1ftrans, c2ftrans, c1btrans, c2btrans
388 // but not all are necessarily used:
389 // - topleft gets lowerleft. if lowerleft is foreground, c1fg c1ftrans.
390 // otherwise, c1bg c1btrans
391 // - topright gets upperleft. if upperleft is foreground, c1fg c1ftrans.
392 // otherwise, c1bg c1btrans
393 // - botleft get botright. if botright is foreground, c2fg c2ftrans.
394 // otherwise, c2bg c2btrans
395 // - botright gets topright. if topright is foreground, c2fg c2ftrans.
396 // otherwise, c2bg c2btrans
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);
401 int ret = 0;
402 ret |= rotate_channels(src, &c1, &c1t, &c1b);
403 ret |= rotate_channels(src, &c2, &c2t, &c2b);
404 // right char comes from two tops. left char comes from two bottoms. if
405 // they're the same channel, they become a:
406 //
407 // nul if the channel is default
408 // space if the fore is default
409 // full if the back is default
410 ncplane_cursor_move_yx(dst, dsty, dstx);
411 rotate_output(dst, c1b, c2b);
412 rotate_output(dst, c1t, c2t);
413 return ret;
414}
415
416static int
417rotate_2x1_ccw(ncplane* src, ncplane* dst, int srcy, int srcx, int dsty, int dstx){
420 if(ncplane_at_yx_cell(src, srcy, srcx, &c1) < 0){
421 return -1;
422 }
423 if(ncplane_at_yx_cell(src, srcy, srcx + 1, &c2) < 0){
424 nccell_release(src, &c1);
425 return -1;
426 }
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);
431 int ret = 0;
432 ret |= rotate_channels(src, &c1, &c1t, &c1b);
433 ret |= rotate_channels(src, &c2, &c2t, &c2b);
434 ncplane_cursor_move_yx(dst, dsty, dstx);
435 rotate_output(dst, c1t, c2t);
436 rotate_output(dst, c1b, c2b);
437 return ret;
438}
439
440// copy 'newp' into 'n' after resizing 'n' to match 'newp'
441static int
442rotate_merge(ncplane* n, ncplane* newp){
443 unsigned dimy, dimx;
444 ncplane_dim_yx(newp, &dimy, &dimx);
445 int ret = ncplane_resize(n, 0, 0, 0, 0, 0, 0, dimy, dimx);
446 if(ret == 0){
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){
452 return -1;
453 }
454 }
455 }
456 }
457 return ret;
458}
459
460// generate a temporary plane that can hold the contents of n, rotated 90°
461static ncplane*
462rotate_plane(ncplane* n){
463 int absy, absx;
464 ncplane_yx(n, &absy, &absx);
465 unsigned dimy, dimx;
466 ncplane_dim_yx(n, &dimy, &dimx);
467 if(dimx % 2 != 0){
468 return NULL;
469 }
470 const int newy = dimx / 2;
471 const int newx = dimy * 2;
472 struct ncplane_options nopts = {
473 .y = absy,
474 .x = absx,
475 .rows = newy,
476 .cols = newx,
477 .userptr = n->userptr,
478 .name = "copy",
479 };
480 ncplane* newp = ncplane_create(n, &nopts);
481 return newp;
482}
483
485 ncplane* newp = rotate_plane(n);
486 if(newp == NULL){
487 return -1;
488 }
489 unsigned dimy, dimx;
490 ncplane_dim_yx(n, &dimy, &dimx);
491 int centy, centx;
492 ncplane_center_abs(n, &centy, &centx);
493 // the topmost row consists of the leftmost two columns. the rightmost column
494 // of the topmost row consists of the top half of the top two leftmost cells.
495 // the penultimate column of the topmost row consists of the bottom half of
496 // the top two leftmost cells. work from the bottom up on the source, so we
497 // can copy to the top row from the left to the right.
498 int targx, targy = 0;
499 for(unsigned x = 0 ; x < dimx ; x += 2){
500 targx = 0;
501 for(int y = (int)dimy - 1 ; y >= 0 ; --y){
502 if(rotate_2x1_cw(n, newp, y, x, targy, targx)){
503 ncplane_destroy(newp);
504 return -1;
505 }
506 targx += 2;
507 }
508 ++targy;
509 }
510 int ret = rotate_merge(n, newp);
511 ret |= ncplane_destroy(newp);
512 return ret;
513}
514
516 ncplane* newp = rotate_plane(n);
517 if(newp == NULL){
518 return -1;
519 }
520 unsigned dimy, dimx, targdimy, targdimx;
521 ncplane_dim_yx(n, &dimy, &dimx);
522 ncplane_dim_yx(newp, &targdimy, &targdimx);
523 int x = (int)dimx - 2;
524 int y;
525 // Each row of the target plane is taken from a column of the source plane.
526 // As the target row grows (down), the source column shrinks (moves left).
527 for(unsigned targy = 0 ; targy < targdimy ; ++targy){
528 y = 0;
529 for(unsigned targx = 0 ; targx < targdimx ; targx += 2){
530 if(rotate_2x1_ccw(n, newp, y, x, targy, targx)){
531 ncplane_destroy(newp);
532 return -1;
533 }
534 ++y;
535 }
536 x -= 2;
537 }
538 int ret = rotate_merge(n, newp);
539 ret |= ncplane_destroy(newp);
540 return ret;
541}
542
543#ifdef USE_QRCODEGEN
544#include <qrcodegen/qrcodegen.h>
545#define QR_BASE_SIZE 17
546#define PER_QR_VERSION 4
547
548static inline unsigned
549qrcode_rows(unsigned version){
550 return QR_BASE_SIZE + (version * PER_QR_VERSION);
551}
552
553static inline unsigned
554qrcode_cols(unsigned version){
555 return QR_BASE_SIZE + (version * PER_QR_VERSION);
556}
557
558int ncplane_qrcode(ncplane* n, unsigned* ymax, unsigned* xmax, const void* data, size_t len){
559 const ncblitter_e blitfxn = NCBLIT_2x1;
560 const int MAX_QR_VERSION = 40; // QR library only supports up to 40
561 if(*ymax <= 0 || *xmax <= 0){
562 return -1;
563 }
564 if(len == 0){
565 return -1;
566 }
567 const int starty = n->y;
568 const int startx = n->x;
569 if(*xmax > n->lenx - startx){
570 return -1;
571 }
572 if(*ymax > n->leny - starty){
573 return -1;
574 }
575 if(*ymax * 2 < qrcode_rows(1)){
576 return -1;
577 }
578 if(*xmax < qrcode_cols(1)){
579 return -1;
580 }
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;
585 }
586 const size_t bsize = qrcodegen_BUFFER_LEN_FOR_VERSION(roomforver);
587 if(bsize < len){
588 return -1;
589 }
590 uint8_t* src = malloc(bsize);
591 uint8_t* dst = malloc(bsize);
592 if(src == NULL || dst == NULL){
593 free(src);
594 free(dst);
595 return -1;
596 }
597 unsigned r, g, b;
598 // FIXME default might not be all-white
599 if(ncplane_fg_default_p(n)){
600 r = g = b = 0xff;
601 }else{
602 ncplane_fg_rgb8(n, &r, &g, &b);
603 }
604 memcpy(src, data, len);
605 int ret = -1;
606 int yscale, xscale;
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));
610 if(rgba){
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);
616 }
617 }
618 struct ncvisual* ncv = ncvisual_from_rgba(rgba, square, square * sizeof(uint32_t), square);
619 free(rgba);
620 if(ncv){
621 ret = square;
622 // we don't allow degredation because 2x1 is the only blitter which
623 // can generate a qrcode with proper aspect ratio. ascii is thus out.
624 struct ncvisual_options vopts = {
625 .n = n,
626 .blitter = blitfxn,
628 };
630 ret = square;
631 }
632 ncvgeom geom;
634 yscale = geom.scaley;
635 xscale = geom.scalex;
636 }
638 }
639 }
640 free(src);
641 free(dst);
642 if(ret > 0){
643 ret = (ret - QR_BASE_SIZE) / PER_QR_VERSION;
644 *ymax = qrcode_rows(ret) / yscale;
645 *xmax = qrcode_cols(ret) / xscale;
646 return ret;
647 }
648 return -1;
649}
650#else
651int ncplane_qrcode(ncplane* n, unsigned* ymax, unsigned* xmax, const void* data, size_t len){
652 (void)n;
653 (void)ymax;
654 (void)xmax;
655 (void)data;
656 (void)len;
657 return -1;
658}
659#endif
API int API int API int uint64_t uint64_t uint64_t uint64_t lr
Definition direct.h:216
API int API int API int uint64_t uint64_t uint64_t ll
Definition direct.h:216
API int API int API int uint64_t uint64_t uint64_t uint64_t unsigned unsigned xlen
Definition direct.h:217
API int API int API int uint64_t uint64_t uint64_t uint64_t unsigned ylen
Definition direct.h:217
API int API int API int uint64_t ul
Definition direct.h:215
API int API int API int uint64_t uint64_t ur
Definition direct.h:215
const char * egc
Definition egcpool.h:162
const nccell * c
Definition egcpool.h:207
int r
Definition fbuf.h:226
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)
Definition fill.c:179
void ncplane_greyscale(ncplane *n)
Definition fill.c:3
int ncplane_rotate_ccw(ncplane *n)
Definition fill.c:515
int ncplane_polyfill_yx(ncplane *n, int ystart, int xstart, const nccell *c)
Definition fill.c:80
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)
Definition fill.c:227
bool check_gradient_args(uint64_t ul, uint64_t ur, uint64_t bl, uint64_t br)
Definition fill.c:150
int ncplane_format(ncplane *n, int y, int x, unsigned ylen, unsigned xlen, uint16_t stylemask)
Definition fill.c:296
int ncplane_qrcode(ncplane *n, unsigned *ymax, unsigned *xmax, const void *data, size_t len)
Definition fill.c:651
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)
Definition fill.c:272
int ncplane_rotate_cw(ncplane *n)
Definition fill.c:484
int ncplane_highgradient_sized(ncplane *n, uint32_t ul, uint32_t ur, uint32_t ll, uint32_t lr, int ylen, int xlen)
Definition fill.c:214
#define logerror(fmt,...)
Definition logging.h:32
int ncplane_cursor_move_yx(ncplane *n, int y, int x)
Definition notcurses.c:723
int ncplane_destroy(ncplane *ncp)
Definition notcurses.c:1021
const char * nccell_extended_gcluster(const ncplane *n, const nccell *c)
Definition notcurses.c:1576
const notcurses * ncplane_notcurses_const(const ncplane *n)
Definition notcurses.c:2635
int nccell_load(ncplane *n, nccell *c, const char *gcluster)
Definition notcurses.c:1836
void ncplane_yx(const ncplane *n, int *y, int *x)
Definition notcurses.c:2454
int ncplane_at_yx_cell(ncplane *n, int y, int x, nccell *c)
Definition notcurses.c:273
int ncplane_resize(ncplane *n, int keepy, int keepx, unsigned keepleny, unsigned keeplenx, int yoff, int xoff, unsigned ylen, unsigned xlen)
Definition notcurses.c:1009
notcurses * ncplane_notcurses(const ncplane *n)
Definition notcurses.c:2631
ncplane * ncplane_create(ncplane *n, const ncplane_options *nopts)
Definition notcurses.c:710
void ncplane_center_abs(const ncplane *n, int *RESTRICT y, int *RESTRICT x)
Definition notcurses.c:3270
void ncplane_dim_yx(const ncplane *n, unsigned *rows, unsigned *cols)
Definition notcurses.c:304
int y
Definition notcurses.h:1905
const struct ncplane_options struct ncvisual * ncv
Definition notcurses.h:3488
const struct ncplane_options struct ncvisual struct ncvisual_options * vopts
Definition notcurses.h:3488
ncblitter_e
Definition notcurses.h:65
@ NCBLIT_2x1
Definition notcurses.h:68
vopts n
Definition notcurses.h:3506
int int x
Definition notcurses.h:1905
#define NCCELL_TRIVIAL_INITIALIZER
Definition notcurses.h:737
API int API int const nccell unsigned len
Definition notcurses.h:2592
#define NCVISUAL_OPTION_NODEGRADE
Definition notcurses.h:3341
void nccell_release(ncplane *n, nccell *c)
Definition render.c:128
int nccell_duplicate(ncplane *n, nccell *targ, const nccell *c)
Definition render.c:133
uint64_t channels
Definition notcurses.h:723
uint16_t stylemask
Definition notcurses.h:703
uint32_t gcluster
Definition notcurses.h:693
uint64_t channels
Definition internal.h:88
nccell * fb
Definition internal.h:77
unsigned scaley
Definition notcurses.h:3406
unsigned scalex
Definition notcurses.h:3406
struct topolyfill * next
Definition internal.h:1773
return NULL
Definition termdesc.h:229
ncvisual * ncvisual_from_rgba(const void *rgba, int rows, int rowstride, int cols)
Definition visual.c:779
void ncvisual_destroy(ncvisual *ncv)
Definition visual.c:1231
int ncvisual_geom(const notcurses *nc, const ncvisual *n, const struct ncvisual_options *vopts, ncvgeom *geom)
Definition visual.c:452
ncplane * ncvisual_blit(notcurses *nc, ncvisual *ncv, const struct ncvisual_options *vopts)
Definition visual.c:1142