5static const uint32_t zeroes32;
6static const unsigned char zeroes[] =
"\x00\x00\x00\x00";
10lerp(uint32_t c0, uint32_t c1,
unsigned nointerpolate){
11 unsigned r0, g0, b0, r1, g1, b1;
13 ncchannel_rgb8(c0, &r0, &g0, &b0);
15 ncchannel_rgb8(c1, &r1, &g1, &b1);
16 ncchannel_set_rgb8(&ret, (r0 + r1 + 1) / 2,
20 ncchannel_set_rgb8(&ret, r0, g0, b0);
27trilerp(uint32_t c0, uint32_t c1, uint32_t c2,
unsigned nointerpolate){
29 unsigned r0, g0, b0, r1, g1, b1, r2, g2, b2;
30 ncchannel_rgb8(c0, &r0, &g0, &b0);
32 ncchannel_rgb8(c1, &r1, &g1, &b1);
33 ncchannel_rgb8(c2, &r2, &g2, &b2);
34 ncchannel_set_rgb8(&ret, (r0 + r1 + r2 + 2) / 3,
35 (g0 + g1 + g2 + 2) / 3,
36 (b0 + b1 + b2 + 2) / 3);
38 ncchannel_set_rgb8(&ret, r0, g0, b0);
45generalerp(
unsigned rsum,
unsigned gsum,
unsigned bsum,
int count){
53 (gsum + (count - 1)) / count,
54 (bsum + (count - 1)) / count);
58rgba_trans_q(
const unsigned char* p, uint32_t transcolor){
60 memcpy(&q, p,
sizeof(q));
61 return rgba_trans_p(q, transcolor);
66tria_blit_ascii(
ncplane* nc,
int linesize,
const void* data,
70 unsigned dimy, dimx,
x,
y;
74 const unsigned char* dat = data;
75 int visy = bargs->
begy;
80 int visx = bargs->
begx;
82 const unsigned char* rgbbase_up = dat + (linesize * visy) + (visx * 4);
84 nccell*
c = ncplane_cell_ref_yx(nc,
y,
x);
93 if(rgba_trans_q(rgbbase_up, bargs->
transcolor)){
96 cell_set_blitquadrants(
c, 0, 0, 0, 0);
99 nccell_set_fg_rgb8(
c, rgbbase_up[0], rgbbase_up[1], rgbbase_up[2]);
100 nccell_set_bg_rgb8(
c, rgbbase_up[0], rgbbase_up[1], rgbbase_up[2]);
101 cell_set_blitquadrants(
c, 1, 1, 1, 1);
102 if(pool_blit_direct(&nc->
pool,
c,
" ", 1, 1) <= 0){
115tria_blit(
ncplane* nc,
int linesize,
const void* data,
int leny,
int lenx,
120 unsigned dimy, dimx,
x,
y;
124 const unsigned char* dat = data;
125 int visy = bargs->
begy;
126 for(
y = bargs->
u.
cell.
placey ; visy < (bargs->
begy + leny) &&
y < dimy ; ++
y, visy += 2){
130 int visx = bargs->
begx;
131 for(
x = bargs->
u.
cell.
placex ; visx < (bargs->
begx + lenx) &&
x < dimx ; ++
x, ++visx){
132 const unsigned char* rgbbase_up = dat + (linesize * visy) + (visx * 4);
133 const unsigned char* rgbbase_down = zeroes;
134 if(visy < bargs->begy + leny - 1){
135 rgbbase_down = dat + (linesize * (visy + 1)) + (visx * 4);
138 nccell*
c = ncplane_cell_ref_yx(nc,
y,
x);
147 if(rgba_trans_q(rgbbase_up, transcolor) || rgba_trans_q(rgbbase_down, transcolor)){
149 if(rgba_trans_q(rgbbase_up, transcolor) && rgba_trans_q(rgbbase_down, transcolor)){
152 }
else if(rgba_trans_q(rgbbase_up, transcolor)){
153 if(pool_blit_direct(&nc->
pool,
c,
"\u2584", strlen(
"\u2584"), 1) <= 0){
156 nccell_set_fg_rgb8(
c, rgbbase_down[0], rgbbase_down[1], rgbbase_down[2]);
157 cell_set_blitquadrants(
c, 0, 0, 1, 1);
161 if(pool_blit_direct(&nc->
pool,
c,
"\u2580", strlen(
"\u2580"), 1) <= 0){
164 nccell_set_fg_rgb8(
c, rgbbase_up[0], rgbbase_up[1], rgbbase_up[2]);
165 cell_set_blitquadrants(
c, 1, 1, 0, 0);
169 if(memcmp(rgbbase_up, rgbbase_down, 3) == 0){
170 nccell_set_fg_rgb8(
c, rgbbase_down[0], rgbbase_down[1], rgbbase_down[2]);
171 nccell_set_bg_rgb8(
c, rgbbase_down[0], rgbbase_down[1], rgbbase_down[2]);
172 cell_set_blitquadrants(
c, 0, 0, 0, 0);
173 if(pool_blit_direct(&nc->
pool,
c,
" ", 1, 1) <= 0){
177 nccell_set_fg_rgb8(
c, rgbbase_up[0], rgbbase_up[1], rgbbase_up[2]);
178 nccell_set_bg_rgb8(
c, rgbbase_down[0], rgbbase_down[1], rgbbase_down[2]);
179 cell_set_blitquadrants(
c, 1, 1, 1, 1);
180 if(pool_blit_direct(&nc->
pool,
c,
"\u2580", strlen(
"\u2580"), 1) <= 0){
195static const struct qdriver {
201} quadrant_drivers[6] = {
202 { .pair = { 0, 1 }, .others = { 2, 3 }, .egc =
"▀", .oth0egc =
"▛", .oth1egc =
"▜", },
203 { .pair = { 0, 2 }, .others = { 1, 3 }, .egc =
"▌", .oth0egc =
"▛", .oth1egc =
"▙", },
204 { .pair = { 0, 3 }, .others = { 1, 2 }, .egc =
"▚", .oth0egc =
"▜", .oth1egc =
"▙", },
205 { .pair = { 1, 2 }, .others = { 0, 3 }, .egc =
"▞", .oth0egc =
"▛", .oth1egc =
"▟", },
206 { .pair = { 1, 3 }, .others = { 0, 2 }, .egc =
"▐", .oth0egc =
"▜", .oth1egc =
"▟", },
207 { .pair = { 2, 3 }, .others = { 0, 1 }, .egc =
"▄", .oth0egc =
"▙", .oth1egc =
"▟", },
213rgb_4diff(uint32_t* diffs, uint32_t tl, uint32_t tr, uint32_t bl, uint32_t br){
217 ncchannel_rgb8(tl, &colors[0].
r, &colors[0].g, &colors[0].b);
218 ncchannel_rgb8(tr, &colors[1].
r, &colors[1].g, &colors[1].b);
219 ncchannel_rgb8(bl, &colors[2].
r, &colors[2].g, &colors[2].b);
220 ncchannel_rgb8(br, &colors[3].
r, &colors[3].g, &colors[3].b);
221 for(
size_t idx = 0 ;
idx <
sizeof(quadrant_drivers) /
sizeof(*quadrant_drivers) ; ++
idx){
222 const struct qdriver* qd = quadrant_drivers +
idx;
223 const struct rgb* rgb0 = colors + qd->pair[0];
224 const struct rgb* rgb1 = colors + qd->pair[1];
225 diffs[
idx] = rgb_diff(rgb0->r, rgb0->g, rgb0->b,
226 rgb1->r, rgb1->g, rgb1->b);
232static inline const char*
233quadrant_solver(uint32_t tl, uint32_t tr, uint32_t bl, uint32_t br,
234 uint32_t* fore, uint32_t* back,
unsigned nointerpolate){
235 const uint32_t colors[4] = { tl, tr, bl, br };
237 uint32_t diffs[
sizeof(quadrant_drivers) /
sizeof(*quadrant_drivers)];
238 rgb_4diff(diffs, tl, tr, bl, br);
241 size_t mindiffidx = 0;
242 unsigned mindiff = diffs[0];
244 bool allzerodiffs = (mindiff == 0);
245 for(
size_t idx = 1 ;
idx <
sizeof(diffs) /
sizeof(*diffs) ; ++
idx){
246 if(diffs[
idx] < mindiff){
248 mindiff = diffs[
idx];
251 allzerodiffs =
false;
262 const struct qdriver* qd = &quadrant_drivers[mindiffidx];
266 *fore = lerp(colors[qd->pair[0]], colors[qd->pair[1]], nointerpolate);
267 *back = lerp(colors[qd->others[0]], colors[qd->others[1]], nointerpolate);
269 const char*
egc = qd->egc;
271 unsigned r0, r1, r2, g0, g1, g2, b0, b1, b2;
272 unsigned roth, goth, both, rlerp, glerp, blerp;
273 ncchannel_rgb8(*back, &roth, &goth, &both);
274 ncchannel_rgb8(*fore, &rlerp, &glerp, &blerp);
277 ncchannel_rgb8(colors[qd->others[0]], &r0, &g0, &b0);
278 ncchannel_rgb8(colors[qd->others[1]], &r1, &g1, &b1);
279 diffs[0] = rgb_diff(r0, g0, b0, roth, goth, both);
280 diffs[1] = rgb_diff(r1, g1, b1, roth, goth, both);
281 diffs[2] = rgb_diff(r0, g0, b0, rlerp, glerp, blerp);
282 diffs[3] = rgb_diff(r1, g1, b1, rlerp, glerp, blerp);
284 ncchannel_rgb8(colors[qd->pair[0]], &r0, &g0, &b0);
285 ncchannel_rgb8(colors[qd->pair[1]], &r1, &g1, &b1);
286 diffs[4] = rgb_diff(r0, g0, b0, rlerp, glerp, blerp);
287 diffs[5] = rgb_diff(r1, g1, b1, rlerp, glerp, blerp);
288 unsigned curdiff = diffs[0] + diffs[1] + diffs[4] + diffs[5];
292 if(diffs[2] < diffs[3]){
293 unsigned tri = trilerp(colors[qd->pair[0]], colors[qd->pair[1]], colors[qd->others[0]],
295 ncchannel_rgb8(colors[qd->others[0]], &r2, &g2, &b2);
296 ncchannel_rgb8(tri, &roth, &goth, &both);
297 if(rgb_diff(r0, g0, b0, roth, goth, both) +
298 rgb_diff(r1, g1, b1, roth, goth, both) +
299 rgb_diff(r2, g2, b2, roth, goth, both) < curdiff){
301 *back = colors[qd->others[1]];
306 unsigned tri = trilerp(colors[qd->pair[0]], colors[qd->pair[1]], colors[qd->others[1]],
308 ncchannel_rgb8(colors[qd->others[1]], &r2, &g2, &b2);
309 ncchannel_rgb8(tri, &roth, &goth, &both);
310 if(rgb_diff(r0, g0, b0, roth, goth, both) +
311 rgb_diff(r1, g1, b1, roth, goth, both) +
312 rgb_diff(r2, g2, b2, roth, goth, both) < curdiff){
314 *back = colors[qd->others[0]];
330static inline const char*
331qtrans_check(
nccell*
c,
unsigned blendcolors,
332 const unsigned char* rgbbase_tl,
const unsigned char* rgbbase_tr,
333 const unsigned char* rgbbase_bl,
const unsigned char* rgbbase_br,
334 uint32_t transcolor,
unsigned nointerpolate){
335 uint32_t tl = 0, tr = 0, bl = 0, br = 0;
336 ncchannel_set_rgb8(&tl, rgbbase_tl[0], rgbbase_tl[1], rgbbase_tl[2]);
337 ncchannel_set_rgb8(&tr, rgbbase_tr[0], rgbbase_tr[1], rgbbase_tr[2]);
338 ncchannel_set_rgb8(&bl, rgbbase_bl[0], rgbbase_bl[1], rgbbase_bl[2]);
339 ncchannel_set_rgb8(&br, rgbbase_br[0], rgbbase_br[1], rgbbase_br[2]);
341 if(rgba_trans_q(rgbbase_tl, transcolor)){
343 if(rgba_trans_q(rgbbase_tr, transcolor)){
345 if(rgba_trans_q(rgbbase_bl, transcolor)){
347 if(rgba_trans_q(rgbbase_br, transcolor)){
349 nccell_set_fg_default(
c);
350 cell_set_blitquadrants(
c, 0, 0, 0, 0);
353 nccell_set_fg_rgb8(
c, rgbbase_br[0], rgbbase_br[1], rgbbase_br[2]);
354 cell_set_blitquadrants(
c, 0, 0, 0, 1);
358 if(rgba_trans_q(rgbbase_br, transcolor)){
359 nccell_set_fg_rgb8(
c, rgbbase_bl[0], rgbbase_bl[1], rgbbase_bl[2]);
360 cell_set_blitquadrants(
c, 0, 0, 1, 0);
363 cell_set_fchannel(
c, lerp(bl, br, nointerpolate));
364 cell_set_blitquadrants(
c, 0, 0, 1, 1);
369 if(rgba_trans_q(rgbbase_bl, transcolor)){
370 if(rgba_trans_q(rgbbase_br, transcolor)){
371 nccell_set_fg_rgb8(
c, rgbbase_tr[0], rgbbase_tr[1], rgbbase_tr[2]);
372 cell_set_blitquadrants(
c, 0, 1, 0, 0);
375 cell_set_fchannel(
c, lerp(tr, br, nointerpolate));
376 cell_set_blitquadrants(
c, 0, 1, 0, 1);
379 }
else if(rgba_trans_q(rgbbase_br, transcolor)){
380 cell_set_fchannel(
c, lerp(tr, bl, nointerpolate));
381 cell_set_blitquadrants(
c, 0, 1, 1, 0);
384 cell_set_fchannel(
c, trilerp(tr, bl, br, nointerpolate));
385 cell_set_blitquadrants(
c, 0, 1, 1, 1);
390 if(rgba_trans_q(rgbbase_tr, transcolor)){
391 if(rgba_trans_q(rgbbase_bl, transcolor)){
392 if(rgba_trans_q(rgbbase_br, transcolor)){
393 nccell_set_fg_rgb8(
c, rgbbase_tl[0], rgbbase_tl[1], rgbbase_tl[2]);
394 cell_set_blitquadrants(
c, 1, 0, 0, 0);
397 cell_set_fchannel(
c, lerp(tl, br, nointerpolate));
398 cell_set_blitquadrants(
c, 1, 0, 0, 1);
401 }
else if(rgba_trans_q(rgbbase_br, transcolor)){
402 cell_set_fchannel(
c, lerp(tl, bl, nointerpolate));
403 cell_set_blitquadrants(
c, 1, 0, 1, 0);
406 cell_set_fchannel(
c, trilerp(tl, bl, br, nointerpolate));
407 cell_set_blitquadrants(
c, 1, 0, 1, 1);
410 }
else if(rgba_trans_q(rgbbase_bl, transcolor)){
411 if(rgba_trans_q(rgbbase_br, transcolor)){
412 cell_set_fchannel(
c, lerp(tl, tr, nointerpolate));
413 cell_set_blitquadrants(
c, 1, 1, 0, 0);
416 cell_set_fchannel(
c, trilerp(tl, tr, br, nointerpolate));
417 cell_set_blitquadrants(
c, 1, 1, 0, 1);
420 }
else if(rgba_trans_q(rgbbase_br, transcolor)){
421 cell_set_fchannel(
c, trilerp(tl, tr, bl, nointerpolate));
422 cell_set_blitquadrants(
c, 1, 1, 1, 0);
432 }
else if(blendcolors){
442quadrant_blit(
ncplane* nc,
int linesize,
const void* data,
int leny,
int lenx,
446 unsigned dimy, dimx,
x,
y;
451 const unsigned char* dat = data;
452 int visy = bargs->
begy;
453 for(
y = bargs->
u.
cell.
placey ; visy < (bargs->
begy + leny) &&
y < dimy ; ++
y, visy += 2){
457 int visx = bargs->
begx;
458 for(
x = bargs->
u.
cell.
placex ; visx < (bargs->
begx + lenx) &&
x < dimx ; ++
x, visx += 2){
459 const unsigned char* rgbbase_tl = dat + (linesize * visy) + (visx * 4);
460 const unsigned char* rgbbase_tr = zeroes;
461 const unsigned char* rgbbase_bl = zeroes;
462 const unsigned char* rgbbase_br = zeroes;
463 if(visx < bargs->begx + lenx - 1){
464 rgbbase_tr = dat + (linesize * visy) + ((visx + 1) * 4);
465 if(visy < bargs->begy + leny - 1){
466 rgbbase_br = dat + (linesize * (visy + 1)) + ((visx + 1) * 4);
469 if(visy < bargs->begy + leny - 1){
470 rgbbase_bl = dat + (linesize * (visy + 1)) + (visx * 4);
473 nccell*
c = ncplane_cell_ref_yx(nc,
y,
x);
476 const char*
egc = qtrans_check(
c, blendcolors, rgbbase_tl, rgbbase_tr,
480 uint32_t tl = 0, tr = 0, bl = 0, br = 0;
481 ncchannel_set_rgb8(&tl, rgbbase_tl[0], rgbbase_tl[1], rgbbase_tl[2]);
482 ncchannel_set_rgb8(&tr, rgbbase_tr[0], rgbbase_tr[1], rgbbase_tr[2]);
483 ncchannel_set_rgb8(&bl, rgbbase_bl[0], rgbbase_bl[1], rgbbase_bl[2]);
484 ncchannel_set_rgb8(&br, rgbbase_br[0], rgbbase_br[1], rgbbase_br[2]);
487 egc = quadrant_solver(tl, tr, bl, br, &fg, &bg, nointerpolate);
490 cell_set_fchannel(
c, fg);
491 cell_set_bchannel(
c, bg);
496 cell_set_blitquadrants(
c, 1, 1, 1, 1);
499 if(pool_blit_direct(&nc->
pool,
c,
egc, strlen(
egc), 1) <= 0){
518hires_solver(
const uint32_t rgbas[6], uint64_t* channels,
unsigned blendcolors,
519 unsigned nointerpolate,
unsigned cellheight,
520 const char*
const* transegcs,
const unsigned* partitions){
521 const unsigned parcount = 1u << (cellheight * 2 - 1);
526 uint32_t mindiff = UINT_MAX;
528 for(
size_t glyph = 0 ; glyph < parcount ; ++glyph){
529 unsigned rsum0 = 0, rsum1 = 0;
530 unsigned gsum0 = 0, gsum1 = 0;
531 unsigned bsum0 = 0, bsum1 = 0;
534 for(
unsigned mask = 0 ; mask < cellheight * 2 ; ++mask){
535 if(partitions[glyph] & (1u << mask)){
536 if(!nointerpolate || !insum){
537 rsum0 += ncpixel_r(rgbas[mask]);
538 gsum0 += ncpixel_g(rgbas[mask]);
539 bsum0 += ncpixel_b(rgbas[mask]);
543 if(!nointerpolate || !outsum){
544 rsum1 += ncpixel_r(rgbas[mask]);
545 gsum1 += ncpixel_g(rgbas[mask]);
546 bsum1 += ncpixel_b(rgbas[mask]);
551 uint32_t l0 = generalerp(rsum0, gsum0, bsum0, insum);
552 uint32_t l1 = generalerp(rsum1, gsum1, bsum1, outsum);
554 uint32_t totaldiff = 0;
555 for(
unsigned mask = 0 ; mask < cellheight * 2 ; ++mask){
557 if(partitions[glyph] & (1u << mask)){
558 ncchannel_rgb8(l0, &
r, &g, &b);
560 ncchannel_rgb8(l1, &
r, &g, &b);
562 uint32_t rdiff = rgb_diff(ncpixel_r(rgbas[mask]), ncpixel_g(rgbas[mask]),
563 ncpixel_b(rgbas[mask]),
r, g, b);
568 if(totaldiff < mindiff){
571 ncchannels_set_fchannel(channels, l0);
572 ncchannels_set_bchannel(channels, l1);
583 best = parcount * 2 - 1 - partitions[best];
584 return transegcs[best];
592static const char*
const sextrans[64] = {
593 "█",
"🬻",
"🬺",
"🬹",
"🬸",
"🬷",
"🬶",
"🬵",
594 "🬴",
"🬳",
"🬲",
"🬱",
"🬰",
"🬯",
"🬮",
"🬭",
595 "🬬",
"🬫",
"🬪",
"🬩",
"🬨",
"▐",
"🬧",
"🬦",
596 "🬥",
"🬤",
"🬣",
"🬢",
"🬡",
"🬠",
"🬟",
"🬞",
597 "🬝",
"🬜",
"🬛",
"🬚",
"🬙",
"🬘",
"🬗",
"🬖",
598 "🬕",
"🬔",
"▌",
"🬓",
"🬒",
"🬑",
"🬐",
"🬏",
599 "🬎",
"🬍",
"🬌",
"🬋",
"🬊",
"🬉",
"🬈",
"🬇",
600 "🬆",
"🬅",
"🬄",
"🬃",
"🬂",
"🬁",
"🬀",
" ",
608static const char*
const octtrans[256] = {
868hires_trans_check(
nccell*
c,
const uint32_t* rgbas,
unsigned blendcolors,
869 uint32_t transcolor,
unsigned nointerpolate,
int cellheight,
870 const char*
const* transegcs){
871 unsigned transstring = 0;
872 unsigned r = 0, g = 0, b = 0;
875 for(
int mask = 0 ; mask < cellheight * 2 ; ++mask){
876 if(rgba_trans_p(rgbas[mask], transcolor)){
877 transstring |= (1u << mask);
878 }
else if(!nointerpolate || !div){
879 r += ncpixel_r(rgbas[mask]);
880 g += ncpixel_g(rgbas[mask]);
881 b += ncpixel_b(rgbas[mask]);
885 if(transstring == 0){
892 const char*
egc = transegcs[transstring];
900 cell_set_fchannel(
c, generalerp(
r, g, b, div));
905 cell_set_blitquadrants(
c, !(transstring & 0x5), !(transstring & 0xa),
906 !(transstring & 0x14), !(transstring & 0x28));
908 cell_set_blitquadrants(
c, !(transstring & 0x5), !(transstring & 0xa),
909 !(transstring & 0x50), !(transstring & 0xa0));
920hires_blit(
ncplane* nc,
int linesize,
const void* data,
int leny,
int lenx,
922 const char*
const* transegcs,
const unsigned* partitions){
925 unsigned dimy, dimx,
x,
y;
929 const unsigned char* dat = data;
930 int visy = bargs->
begy;
932 for(
y = bargs->
u.
cell.
placey ; visy < (bargs->
begy + leny) &&
y < dimy ; ++
y, visy += cellheight){
936 int visx = bargs->
begx;
937 for(
x = bargs->
u.
cell.
placex ; visx < (bargs->
begx + lenx) &&
x < dimx ; ++
x, visx += 2){
939 memset(rgbas, 0,
sizeof(rgbas));
940 memcpy(&rgbas[0], (dat + (linesize * visy) + (visx * 4)),
sizeof(*rgbas));
942 for(
int yoff = 1 ; yoff < cellheight ; ++yoff){
943 if(visy < bargs->begy + leny - yoff){
944 memcpy(&rgbas[yoff * 2], (dat + (linesize * (visy + yoff)) + (visx * 4)),
sizeof(*rgbas));
948 if(visx < bargs->begx + lenx - 1){
949 memcpy(&rgbas[1], (dat + (linesize * visy) + ((visx + 1) * 4)),
sizeof(*rgbas));
950 for(
int yoff = 1 ; yoff < cellheight ; ++yoff){
951 if(visy < bargs->begy + leny - yoff){
952 memcpy(&rgbas[1 + yoff * 2], (dat + (linesize * (visy + yoff)) + ((visx + 1) * 4)),
sizeof(*rgbas));
956 nccell*
c = ncplane_cell_ref_yx(nc,
y,
x);
959 const char*
egc = hires_trans_check(
c, rgbas, blendcolors, bargs->
transcolor,
960 nointerpolate, cellheight, transegcs);
962 egc = hires_solver(rgbas, &
c->
channels, blendcolors, nointerpolate,
963 cellheight, transegcs, partitions);
964 cell_set_blitquadrants(
c, 1, 1, 1, 1);
968 if(pool_blit_direct(&nc->
pool,
c,
egc, strlen(
egc), 1) <= 0){
981sextant_blit(
ncplane* nc,
int linesize,
const void* data,
int leny,
int lenx,
987 static const unsigned sextitions[32] = {
990 3, 5, 9, 17, 33, 6, 10, 18, 34, 12, 20, 36, 24, 40, 48,
992 7, 11, 19, 35, 13, 21, 37, 25, 41, 49
994 return hires_blit(nc, linesize, data, leny, lenx, bargs, 3, sextrans, sextitions);
998octant_blit(
ncplane* nc,
int linesize,
const void* data,
int leny,
int lenx,
1004#define E(bits) (1u << (bits))
1005 static const unsigned octitions[128] = {
1008 E(0),
E(1),
E(2),
E(3),
E(4),
E(5),
E(6),
E(7),
1010 E(0) +
E(1),
E(0) +
E(2),
E(0) +
E(3),
E(0) +
E(4),
E(0) +
E(5),
E(0) +
E(6),
E(0) +
E(7),
1011 E(1) +
E(2),
E(1) +
E(3),
E(1) +
E(4),
E(1) +
E(5),
E(1) +
E(6),
E(1) +
E(7),
1012 E(2) +
E(3),
E(2) +
E(4),
E(2) +
E(5),
E(2) +
E(6),
E(2) +
E(7),
1013 E(3) +
E(4),
E(3) +
E(5),
E(3) +
E(6),
E(3) +
E(7),
1014 E(4) +
E(5),
E(4) +
E(6),
E(4) +
E(7),
1015 E(5) +
E(6),
E(5) +
E(7),
1018 E(0) +
E(1) +
E(2),
E(0) +
E(1) +
E(3),
E(0) +
E(1) +
E(4),
E(0) +
E(1) +
E(5),
1019 E(0) +
E(1) +
E(6),
E(0) +
E(1) +
E(7),
E(0) +
E(2) +
E(3),
E(0) +
E(2) +
E(4),
1020 E(0) +
E(2) +
E(5),
E(0) +
E(2) +
E(6),
E(0) +
E(2) +
E(7),
E(0) +
E(3) +
E(4),
1021 E(0) +
E(3) +
E(5),
E(0) +
E(3) +
E(6),
E(0) +
E(3) +
E(7),
E(0) +
E(4) +
E(5),
1022 E(0) +
E(4) +
E(6),
E(0) +
E(4) +
E(7),
E(0) +
E(5) +
E(6),
E(0) +
E(5) +
E(7),
1024 E(1) +
E(2) +
E(3),
E(1) +
E(2) +
E(4),
E(1) +
E(2) +
E(5),
E(1) +
E(2) +
E(6),
1025 E(1) +
E(2) +
E(7),
E(1) +
E(3) +
E(4),
E(1) +
E(3) +
E(5),
E(1) +
E(3) +
E(6),
1026 E(1) +
E(3) +
E(7),
E(1) +
E(4) +
E(5),
E(1) +
E(4) +
E(6),
E(1) +
E(4) +
E(7),
1027 E(1) +
E(5) +
E(6),
E(1) +
E(5) +
E(7),
E(1) +
E(6) +
E(7),
1028 E(2) +
E(3) +
E(4),
E(2) +
E(3) +
E(5),
E(2) +
E(3) +
E(6),
E(2) +
E(3) +
E(7),
1029 E(2) +
E(4) +
E(5),
E(2) +
E(4) +
E(6),
E(2) +
E(4) +
E(7),
E(2) +
E(5) +
E(6),
1030 E(2) +
E(5) +
E(7),
E(2) +
E(6) +
E(7),
1031 E(3) +
E(4) +
E(5),
E(3) +
E(4) +
E(6),
E(3) +
E(4) +
E(7),
E(3) +
E(5) +
E(6),
1032 E(3) +
E(5) +
E(7),
E(3) +
E(6) +
E(7),
1033 E(4) +
E(5) +
E(6),
E(4) +
E(5) +
E(7),
E(4) +
E(6) +
E(7),
1036 E(0) +
E(1) +
E(2) +
E(3),
E(0) +
E(1) +
E(2) +
E(4),
E(0) +
E(1) +
E(2) +
E(5),
1037 E(0) +
E(1) +
E(2) +
E(6),
E(0) +
E(1) +
E(2) +
E(7),
E(0) +
E(1) +
E(3) +
E(4),
1038 E(0) +
E(1) +
E(3) +
E(5),
E(0) +
E(1) +
E(3) +
E(6),
E(0) +
E(1) +
E(3) +
E(7),
1039 E(0) +
E(1) +
E(4) +
E(5),
E(0) +
E(1) +
E(4) +
E(6),
E(0) +
E(1) +
E(4) +
E(7),
1040 E(0) +
E(1) +
E(5) +
E(6),
E(0) +
E(1) +
E(5) +
E(7),
E(0) +
E(1) +
E(6) +
E(7),
1041 E(0) +
E(2) +
E(3) +
E(4),
E(0) +
E(2) +
E(3) +
E(5),
E(0) +
E(2) +
E(3) +
E(6),
1042 E(0) +
E(2) +
E(3) +
E(7),
E(0) +
E(2) +
E(4) +
E(5),
E(0) +
E(2) +
E(4) +
E(6),
1043 E(0) +
E(2) +
E(4) +
E(7),
E(0) +
E(2) +
E(5) +
E(6),
E(0) +
E(2) +
E(5) +
E(7),
1044 E(0) +
E(2) +
E(6) +
E(7),
E(0) +
E(3) +
E(4) +
E(5),
E(0) +
E(3) +
E(4) +
E(6),
1045 E(0) +
E(3) +
E(4) +
E(7),
E(0) +
E(3) +
E(5) +
E(6),
E(0) +
E(3) +
E(5) +
E(7),
1046 E(0) +
E(3) +
E(6) +
E(7),
E(0) +
E(4) +
E(5) +
E(6),
E(0) +
E(4) +
E(5) +
E(7),
1047 E(0) +
E(4) +
E(6) +
E(7),
E(0) +
E(5) +
E(6) +
E(7),
1050 return hires_blit(nc, linesize, data, leny, lenx, bargs, 4, octtrans, octitions);
1059static const char braille_egcs[256][5] = {
1060 "\u2800",
"\u2801",
"\u2808",
"\u2809",
"\u2802",
"\u2803",
"\u280a",
"\u280b",
1061 "\u2810",
"\u2811",
"\u2818",
"\u2819",
"\u2812",
"\u2813",
"\u281a",
"\u281b",
1062 "\u2804",
"\u2805",
"\u280c",
"\u280d",
"\u2806",
"\u2807",
"\u280e",
"\u280f",
1063 "\u2814",
"\u2815",
"\u281c",
"\u281d",
"\u2816",
"\u2817",
"\u281e",
"\u281f",
1064 "\u2820",
"\u2821",
"\u2828",
"\u2829",
"\u2822",
"\u2823",
"\u282a",
"\u282b",
1065 "\u2830",
"\u2831",
"\u2838",
"\u2839",
"\u2832",
"\u2833",
"\u283a",
"\u283b",
1066 "\u2824",
"\u2825",
"\u282c",
"\u282d",
"\u2826",
"\u2827",
"\u282e",
"\u282f",
1067 "\u2834",
"\u2835",
"\u283c",
"\u283d",
"\u2836",
"\u2837",
"\u283e",
"\u283f",
1068 "\u2840",
"\u2841",
"\u2848",
"\u2849",
"\u2842",
"\u2843",
"\u284a",
"\u284b",
1069 "\u2850",
"\u2851",
"\u2858",
"\u2859",
"\u2852",
"\u2853",
"\u285a",
"\u285b",
1070 "\u2844",
"\u2845",
"\u284c",
"\u284d",
"\u2846",
"\u2847",
"\u284e",
"\u284f",
1071 "\u2854",
"\u2855",
"\u285c",
"\u285d",
"\u2856",
"\u2857",
"\u285e",
"\u285f",
1072 "\u2860",
"\u2861",
"\u2868",
"\u2869",
"\u2862",
"\u2863",
"\u286a",
"\u286b",
1073 "\u2870",
"\u2871",
"\u2878",
"\u2879",
"\u2872",
"\u2873",
"\u287a",
"\u287b",
1074 "\u2864",
"\u2865",
"\u286c",
"\u286d",
"\u2866",
"\u2867",
"\u286e",
"\u286f",
1075 "\u2874",
"\u2875",
"\u287c",
"\u287d",
"\u2876",
"\u2877",
"\u287e",
"\u287f",
1076 "\u2880",
"\u2881",
"\u2888",
"\u2889",
"\u2882",
"\u2883",
"\u288a",
"\u288b",
1077 "\u2890",
"\u2891",
"\u2898",
"\u2899",
"\u2892",
"\u2893",
"\u289a",
"\u289b",
1078 "\u2884",
"\u2885",
"\u288c",
"\u288d",
"\u2886",
"\u2887",
"\u288e",
"\u288f",
1079 "\u2894",
"\u2895",
"\u289c",
"\u289d",
"\u2896",
"\u2897",
"\u289e",
"\u289f",
1080 "\u28a0",
"\u28a1",
"\u28a8",
"\u28a9",
"\u28a2",
"\u28a3",
"\u28aa",
"\u28ab",
1081 "\u28b0",
"\u28b1",
"\u28b8",
"\u28b9",
"\u28b2",
"\u28b3",
"\u28ba",
"\u28bb",
1082 "\u28a4",
"\u28a5",
"\u28ac",
"\u28ad",
"\u28a6",
"\u28a7",
"\u28ae",
"\u28af",
1083 "\u28b4",
"\u28b5",
"\u28bc",
"\u28bd",
"\u28b6",
"\u28b7",
"\u28be",
"\u28bf",
1084 "\u28c0",
"\u28c1",
"\u28c8",
"\u28c9",
"\u28c2",
"\u28c3",
"\u28ca",
"\u28cb",
1085 "\u28d0",
"\u28d1",
"\u28d8",
"\u28d9",
"\u28d2",
"\u28d3",
"\u28da",
"\u28db",
1086 "\u28c4",
"\u28c5",
"\u28cc",
"\u28cd",
"\u28c6",
"\u28c7",
"\u28ce",
"\u28cf",
1087 "\u28d4",
"\u28d5",
"\u28dc",
"\u28dd",
"\u28d6",
"\u28d7",
"\u28de",
"\u28df",
1088 "\u28e0",
"\u28e1",
"\u28e8",
"\u28e9",
"\u28e2",
"\u28e3",
"\u28ea",
"\u28eb",
1089 "\u28f0",
"\u28f1",
"\u28f8",
"\u28f9",
"\u28f2",
"\u28f3",
"\u28fa",
"\u28fb",
1090 "\u28e4",
"\u28e5",
"\u28ec",
"\u28ed",
"\u28e6",
"\u28e7",
"\u28ee",
"\u28ef",
1091 "\u28f4",
"\u28f5",
"\u28fc",
"\u28fd",
"\u28f6",
"\u28f7",
"\u28fe",
"\u28ff",
1097fold_rgb8(
unsigned* restrict
r,
unsigned* restrict g,
unsigned* restrict b,
1098 const uint32_t* pixel,
unsigned* foldcount){
1099 *
r += ncpixel_r(*pixel);
1100 *g += ncpixel_g(*pixel);
1101 *b += ncpixel_b(*pixel);
1107braille_blit(
ncplane* nc,
int linesize,
const void* data,
int leny,
int lenx,
1110 unsigned dimy, dimx,
x,
y;
1114 const unsigned char* dat = data;
1115 int visy = bargs->
begy;
1116 for(
y = bargs->
u.
cell.
placey ; visy < (bargs->
begy + leny) &&
y < dimy ; ++
y, visy += 4){
1120 int visx = bargs->
begx;
1121 for(
x = bargs->
u.
cell.
placex ; visx < (bargs->
begx + lenx) &&
x < dimx ; ++
x, visx += 2){
1122 const uint32_t* rgbbase_l0 = (
const uint32_t*)(dat + (linesize * visy) + (visx * 4));
1123 const uint32_t* rgbbase_r0 = &zeroes32;
1124 const uint32_t* rgbbase_l1 = &zeroes32;
1125 const uint32_t* rgbbase_r1 = &zeroes32;
1126 const uint32_t* rgbbase_l2 = &zeroes32;
1127 const uint32_t* rgbbase_r2 = &zeroes32;
1128 const uint32_t* rgbbase_l3 = &zeroes32;
1129 const uint32_t* rgbbase_r3 = &zeroes32;
1130 unsigned r = 0, g = 0, b = 0;
1131 unsigned blends = 0;
1132 unsigned egcidx = 0;
1133 if(visx < bargs->begx + lenx - 1){
1134 rgbbase_r0 = (
const uint32_t*)(dat + (linesize * visy) + ((visx + 1) * 4));
1135 if(visy < bargs->begy + leny - 1){
1136 rgbbase_r1 = (
const uint32_t*)(dat + (linesize * (visy + 1)) + ((visx + 1) * 4));
1137 if(visy < bargs->begy + leny - 2){
1138 rgbbase_r2 = (
const uint32_t*)(dat + (linesize * (visy + 2)) + ((visx + 1) * 4));
1139 if(visy < bargs->begy + leny - 3){
1140 rgbbase_r3 = (
const uint32_t*)(dat + (linesize * (visy + 3)) + ((visx + 1) * 4));
1145 if(visy < bargs->begy + leny - 1){
1146 rgbbase_l1 = (
const uint32_t*)(dat + (linesize * (visy + 1)) + (visx * 4));
1147 if(visy < bargs->begy + leny - 2){
1148 rgbbase_l2 = (
const uint32_t*)(dat + (linesize * (visy + 2)) + (visx * 4));
1149 if(visy < bargs->begy + leny - 3){
1150 rgbbase_l3 = (
const uint32_t*)(dat + (linesize * (visy + 3)) + (visx * 4));
1160 if(!rgba_trans_p(*rgbbase_l0, bargs->
transcolor)){
1162 fold_rgb8(&
r, &g, &b, rgbbase_l0, &blends);
1164 if(!rgba_trans_p(*rgbbase_r0, bargs->
transcolor)){
1166 fold_rgb8(&
r, &g, &b, rgbbase_r0, &blends);
1168 if(!rgba_trans_p(*rgbbase_l1, bargs->
transcolor)){
1170 fold_rgb8(&
r, &g, &b, rgbbase_l1, &blends);
1172 if(!rgba_trans_p(*rgbbase_r1, bargs->
transcolor)){
1174 fold_rgb8(&
r, &g, &b, rgbbase_r1, &blends);
1176 if(!rgba_trans_p(*rgbbase_l2, bargs->
transcolor)){
1178 fold_rgb8(&
r, &g, &b, rgbbase_l2, &blends);
1180 if(!rgba_trans_p(*rgbbase_r2, bargs->
transcolor)){
1182 fold_rgb8(&
r, &g, &b, rgbbase_r2, &blends);
1184 if(!rgba_trans_p(*rgbbase_l3, bargs->
transcolor)){
1186 fold_rgb8(&
r, &g, &b, rgbbase_l3, &blends);
1188 if(!rgba_trans_p(*rgbbase_r3, bargs->
transcolor)){
1190 fold_rgb8(&
r, &g, &b, rgbbase_r3, &blends);
1193 nccell*
c = ncplane_cell_ref_yx(nc,
y,
x);
1210 nccell_set_fg_rgb8(
c,
r / blends, g / blends, b / blends);
1212 const char*
egc = braille_egcs[egcidx];
1213 if(pool_blit_direct(&nc->
pool,
c,
egc, strlen(
egc), 1) <= 0){
1230static struct blitset notcurses_blitters[] = {
1232 .egcs = L
" █", .plotegcs = L
" █",
1233 .blit = tria_blit_ascii,.name =
"ascii", .fill =
false, },
1234 { .geom =
NCBLIT_2x1, .width = 1, .height = 2,
1236 .blit = tria_blit, .name =
"half", .fill =
false, },
1237 { .geom =
NCBLIT_2x2, .width = 2, .height = 2,
1239 .blit = quadrant_blit, .name =
"quad", .fill =
false, },
1240 { .geom =
NCBLIT_3x2, .width = 2, .height = 3,
1241 .egcs =
NCSEXBLOCKS, .plotegcs = L
" 🬞🬦▐🬏🬭🬵🬷🬓🬱🬹🬻▌🬲🬺█",
1242 .blit = sextant_blit, .name =
"sex", .fill =
false, },
1243 { .geom =
NCBLIT_4x2, .width = 2, .height = 4,
1245 .plotegcs = (L
"\0x20"
1273 .plotegcs = L
"⠀⢀⢠⢰⢸⡀⣀⣠⣰⣸⡄⣄⣤⣴⣼⡆⣆⣦⣶⣾⡇⣇⣧⣷⣿",
1274 .blit = braille_blit, .name =
"braille", .fill =
true, },
1276 .egcs = L
"", .plotegcs =
NULL,
1277 .blit =
NULL, .name =
"pixel", .fill =
true, },
1278 { .geom =
NCBLIT_4x1, .width = 1, .height = 4,
1279 .egcs =
NULL, .plotegcs = L
" ▂▄▆█",
1280 .blit = tria_blit, .name =
"fourstep", .fill =
false, },
1281 { .geom =
NCBLIT_8x1, .width = 1, .height = 8,
1283 .blit = tria_blit, .name =
"eightstep", .fill =
false, },
1284 { .geom = 0, .width = 0, .height = 0,
1286 .blit =
NULL, .name =
NULL, .fill =
false, },
1290 struct blitset* b = notcurses_blitters;
1305 return ¬curses_blitters[setid - 1];
1306 }
else if(!may_degrade){
1314 return ¬curses_blitters[setid - 1];
1315 }
else if(!may_degrade){
1323 return ¬curses_blitters[setid - 1];
1324 }
else if(!may_degrade){
1332 return ¬curses_blitters[setid - 1];
1333 }
else if(!may_degrade){
1341 return ¬curses_blitters[setid - 1];
1342 }
else if(!may_degrade){
1350 return ¬curses_blitters[setid - 1];
1351 }
else if(!may_degrade){
1359 return ¬curses_blitters[setid - 1];
1360 }
else if(!may_degrade){
1368 return ¬curses_blitters[setid - 1];
1369 }
else if(!may_degrade){
1375 return ¬curses_blitters[setid - 1];
1379 const struct blitset* bset = notcurses_blitters;
1381 if(strcasecmp(bset->
name, op) == 0){
1382 *blitfxn = bset->
geom;
1387 if(strcasecmp(
"default", op) == 0){
1398 const struct blitset* bset = notcurses_blitters;
1400 if(bset->
geom == blitfxn){
1476 return rgba_blitter_default(&nc->
tcache, scale);
int ncblit_rgba(const void *data, int linesize, const struct ncvisual_options *vopts)
ncblitter_e ncvisual_media_defblitter(const notcurses *nc, ncscale_e scale)
int ncblit_rgb_loose(const void *data, int linesize, const struct ncvisual_options *vopts, int alpha)
const char * notcurses_str_blitter(ncblitter_e blitfxn)
int notcurses_lex_blitter(const char *op, ncblitter_e *blitfxn)
const struct blitset * lookup_blitset(const tinfo *tcache, ncblitter_e setid, bool may_degrade)
int ncblit_bgrx(const void *data, int linesize, const struct ncvisual_options *vopts)
int ncblit_rgb_packed(const void *data, int linesize, const struct ncvisual_options *vopts, int alpha)
void set_pixel_blitter(ncblitter blitfxn)
int(* ncblitter)(struct ncplane *n, int linesize, const void *data, int scaledy, int scaledx, const struct blitterargs *bargs)
ALLOC void * rgb_loose_to_rgba(const void *data, int rows, int *rowstride, int cols, int alpha)
ALLOC void * bgra_to_rgba(const void *data, int rows, int *rowstride, int cols, int alpha)
ALLOC void * rgb_packed_to_rgba(const void *data, int rows, int *rowstride, int cols, int alpha)
#define logerror(fmt,...)
int ncplane_cursor_move_yx(ncplane *n, int y, int x)
notcurses * ncplane_notcurses(const ncplane *n)
void ncplane_dim_yx(const ncplane *n, unsigned *rows, unsigned *cols)
const struct ncplane_options struct ncvisual * ncv
#define NCCHANNEL_INITIALIZER(r, g, b)
const struct ncplane_options struct ncvisual struct ncvisual_options * vopts
#define NCVISUAL_OPTION_NOINTERPOLATE
#define NCALPHA_TRANSPARENT
#define NCVISUAL_OPTION_BLEND
void nccell_release(ncplane *n, nccell *c)
struct blitterargs::@3::@4 cell
int(* pixel_draw_late)(const struct tinfo *, struct sprixel *s, int yoff, int xoff)
int(* pixel_draw)(const struct tinfo *, const struct ncpile *p, struct sprixel *s, fbuf *f, int y, int x)
ncvisual * ncvisual_from_rgba(const void *rgba, int rows, int rowstride, int cols)
void ncvisual_destroy(ncvisual *ncv)
ncplane * ncvisual_blit(notcurses *nc, ncvisual *ncv, const struct ncvisual_options *vopts)