546 lines
14 KiB
C
546 lines
14 KiB
C
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
|
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
|
│ │
|
|
│ This program is free software; you can redistribute it and/or modify │
|
|
│ it under the terms of the GNU General Public License as published by │
|
|
│ the Free Software Foundation; version 2 of the License. │
|
|
│ │
|
|
│ This program is distributed in the hope that it will be useful, but │
|
|
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
|
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
|
│ General Public License for more details. │
|
|
│ │
|
|
│ You should have received a copy of the GNU General Public License │
|
|
│ along with this program; if not, write to the Free Software │
|
|
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
|
│ 02110-1301 USA │
|
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
|
|
|
// The modes below use various unicodes for 'progresssive' pixelization:
|
|
// each mode supersets the previous to increase resolution more and more.
|
|
// Ideally, a fully dense mapping of the (Y*X) space defined by kGlyph size
|
|
// would produce a picture perfect image, but at the cost of sampling speed.
|
|
// Therefore, supersets are parcimonious: they only add the minimal set of
|
|
// missing shapes that can increase resolution.
|
|
// Ideally, this should be based on a study of the residual, but some logic
|
|
// can go a long way: after some block pixelization, will need diagonals
|
|
// FIXME: then shouldn't box drawing go right after braille?
|
|
|
|
// TODO: explain the differences between each mode:
|
|
// Mode A is full, empty, half blocks top and bottom: , █,▄,▀
|
|
// Mode B superset: with quadrants: ▐,▌,▝,▙,▗,▛,▖,▜,▘,▟,▞,▚,
|
|
// Mode C superset: with fractional eights along X and Y
|
|
// _,▁,▂,▃,▄,▅,▆,▇ :█:▉,▊,▋,▌,▍,▎,▏
|
|
// Mode X use box drawing, mode X use diagonal blocks, mode X use braille etc
|
|
|
|
#define W(B, S) B##U << S
|
|
#define G(AA, AB, AC, AD, BA, BB, BC, BD, CA, CB, CC, CD, DA, DB, DC, DD, EA, \
|
|
EB, EC, ED, FA, FB, FC, FD, GA, GB, GC, GD, HA, HB, HC, HD) \
|
|
(W(AA, 000) | W(AB, 001) | W(AC, 002) | W(AD, 003) | W(BA, 004) | \
|
|
W(BB, 005) | W(BC, 006) | W(BD, 007) | W(CA, 010) | W(CB, 011) | \
|
|
W(CC, 012) | W(CD, 013) | W(DA, 014) | W(DB, 015) | W(DC, 016) | \
|
|
W(DD, 017) | W(EA, 020) | W(EB, 021) | W(EC, 022) | W(ED, 023) | \
|
|
W(FA, 024) | W(FB, 025) | W(FC, 026) | W(FD, 027) | W(GA, 030) | \
|
|
W(GB, 031) | W(GC, 032) | W(GD, 033) | W(HA, 034) | W(HB, 035) | \
|
|
W(HC, 036) | W(HD, 037))
|
|
|
|
// The glyph size it set by the resolution of the most precise mode, ex:
|
|
// - Mode C: along the X axis, need >= 8 steps for the 8 fractional width
|
|
// FIXME: now we can only use 4 chars instead of the extra ▉,▊,▋,▌,▍,▎,▏
|
|
//
|
|
// - Mode X: along the Y axis, need >= 8 steps to separate the maximal 6 dots
|
|
// from the space left below, seen by overimposing an underline ⠿_
|
|
// along the 3 dots, the Y axis is least 1,0,1,0,1,0,0,1 so 8 steps
|
|
//
|
|
// Problem: fonts are taller than wider, and terminals are tradionally 80x24, so
|
|
// - we shouldn't use square glyphs, 8x16 seems to be the minimal size
|
|
// - we should adapt the conversion to BMP to avoid accidental Y downsampling
|
|
|
|
const uint32_t kGlyphs[] = /* clang-format off */ {
|
|
/* U+0020 ' ' empty block [ascii:20,cp437:20] */
|
|
G(0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0),
|
|
/* U+2588 '█' full block [cp437] */
|
|
G(1,1,1,1,
|
|
1,1,1,1,
|
|
1,1,1,1,
|
|
1,1,1,1,
|
|
1,1,1,1,
|
|
1,1,1,1,
|
|
1,1,1,1,
|
|
1,1,1,1),
|
|
/* U+2584 '▄' lower half block [cp437:dc] */
|
|
G(0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
1,1,1,1,
|
|
1,1,1,1,
|
|
1,1,1,1,
|
|
1,1,1,1),
|
|
/* U+2580 '▀' upper half block [cp437] */
|
|
G(1,1,1,1,
|
|
1,1,1,1,
|
|
1,1,1,1,
|
|
1,1,1,1,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0),
|
|
// Mode B
|
|
/* U+2590 '▐' right half block [cp437:de] */
|
|
G(0,0,1,1,
|
|
0,0,1,1,
|
|
0,0,1,1,
|
|
0,0,1,1,
|
|
0,0,1,1,
|
|
0,0,1,1,
|
|
0,0,1,1,
|
|
0,0,1,1),
|
|
/* U+258c '▌' left half block [cp437] */
|
|
G(1,1,0,0,
|
|
1,1,0,0,
|
|
1,1,0,0,
|
|
1,1,0,0,
|
|
1,1,0,0,
|
|
1,1,0,0,
|
|
1,1,0,0,
|
|
1,1,0,0),
|
|
/* U+259d '▝' quadrant upper right */
|
|
G(0,0,1,1,
|
|
0,0,1,1,
|
|
0,0,1,1,
|
|
0,0,1,1,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0),
|
|
/* U+2599 '▙' quadrant upper left and lower left and lower right */
|
|
G(1,1,0,0,
|
|
1,1,0,0,
|
|
1,1,0,0,
|
|
1,1,0,0,
|
|
1,1,1,1,
|
|
1,1,1,1,
|
|
1,1,1,1,
|
|
1,1,1,0),
|
|
/* U+2597 '▗' quadrant lower right */
|
|
G(0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,1,1,
|
|
0,0,1,1,
|
|
0,0,1,1,
|
|
0,0,1,1),
|
|
/* U+259b '▛' quadrant upper left and upper right and lower left */
|
|
G(1,1,1,1,
|
|
1,1,1,1,
|
|
1,1,1,1,
|
|
1,1,1,1,
|
|
1,1,0,0,
|
|
1,1,0,0,
|
|
1,1,0,0,
|
|
1,1,0,1),
|
|
/* U+2596 '▖' quadrant lower left */
|
|
G(0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
1,1,0,0,
|
|
1,1,0,0,
|
|
1,1,0,0,
|
|
1,1,0,0),
|
|
/* U+259c '▜' quadrant upper left and upper right and lower right */
|
|
G(1,1,1,1,
|
|
1,1,1,1,
|
|
1,1,1,1,
|
|
1,1,1,1,
|
|
0,0,1,1,
|
|
0,0,1,1,
|
|
0,0,1,1,
|
|
0,0,1,0),
|
|
/* U+2598 '▘' quadrant upper left */
|
|
G(1,1,0,0,
|
|
1,1,0,0,
|
|
1,1,0,0,
|
|
1,1,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0),
|
|
/* U+259F '▟' quadrant upper right and lower left and lower right */
|
|
G(0,0,1,1,
|
|
0,0,1,1,
|
|
0,0,1,1,
|
|
0,0,1,1,
|
|
1,1,1,1,
|
|
1,1,1,1,
|
|
1,1,1,1,
|
|
1,1,1,0),
|
|
/* U+259e '▞' quadrant upper right and lower left */
|
|
G(0,0,1,1,
|
|
0,0,1,1,
|
|
0,0,1,1,
|
|
0,0,1,1,
|
|
1,1,0,0,
|
|
1,1,0,0,
|
|
1,1,0,0,
|
|
1,1,0,0),
|
|
/* U+259a '▚' quadrant upper left and lower right */
|
|
G(1,1,0,0,
|
|
1,1,0,0,
|
|
1,1,0,0,
|
|
1,1,0,0,
|
|
0,0,1,1,
|
|
0,0,1,1,
|
|
0,0,1,1,
|
|
0,0,1,0),
|
|
// Mode C
|
|
/* U+2594 '▔' upper one eighth block */
|
|
G(1,1,1,1,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0),
|
|
/* U+2581 '▁' lower one eighth block */
|
|
G(0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
1,1,1,1),
|
|
/* U+2582 '▂' lower one quarter block */
|
|
G(0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
1,1,1,1,
|
|
1,1,1,1),
|
|
/* U+2583 '▃' lower three eighths block */
|
|
G(0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
1,1,1,1,
|
|
1,1,1,1,
|
|
1,1,1,1),
|
|
/* U+2585 '▃' lower five eighths block */
|
|
G(0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
1,1,1,1,
|
|
1,1,1,1,
|
|
1,1,1,1,
|
|
1,1,1,1,
|
|
1,1,1,1),
|
|
/* U+2586 '▆' lower three quarters block */
|
|
G(0,0,0,0,
|
|
0,0,0,0,
|
|
1,1,1,1,
|
|
1,1,1,1,
|
|
1,1,1,1,
|
|
1,1,1,1,
|
|
1,1,1,1,
|
|
1,1,1,1),
|
|
/* U+2587 '▇' lower seven eighths block */
|
|
G(0,0,0,0,
|
|
1,1,1,1,
|
|
1,1,1,1,
|
|
1,1,1,1,
|
|
1,1,1,1,
|
|
1,1,1,1,
|
|
1,1,1,1,
|
|
1,1,1,1),
|
|
/* U+258e '▎' left one quarter block */
|
|
G(1,0,0,0,
|
|
1,0,0,0,
|
|
1,0,0,0,
|
|
1,0,0,0,
|
|
1,0,0,0,
|
|
1,0,0,0,
|
|
1,0,0,0,
|
|
1,0,0,0),
|
|
/* U+258a '▊' left three quarters block */
|
|
G(1,1,1,0,
|
|
1,1,1,0,
|
|
1,1,1,0,
|
|
1,1,1,0,
|
|
1,1,1,0,
|
|
1,1,1,0,
|
|
1,1,1,0,
|
|
1,1,1,0),
|
|
/* ▁ *\
|
|
2501▕━▎box drawings heavy horizontal
|
|
\* ▔ */
|
|
G(0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
1,1,1,1,
|
|
1,1,1,1,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0),
|
|
/* ▁ *\
|
|
25019▕┉▎box drawings heavy quadruple dash horizontal
|
|
\* ▔ */
|
|
G(0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
1,0,1,0,
|
|
0,1,0,1,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0),
|
|
/* ▁ *\
|
|
2503▕┃▎box drawings heavy vertical
|
|
\* ▔ */
|
|
G(0,1,1,0,
|
|
0,1,1,0,
|
|
0,1,1,0,
|
|
0,1,1,0,
|
|
0,1,1,0,
|
|
0,1,1,0,
|
|
0,1,1,0,
|
|
0,1,1,0),
|
|
/* ▁ *\
|
|
254b▕╋▎box drawings heavy vertical and horizontal
|
|
\* ▔ */
|
|
G(0,1,1,0,
|
|
0,1,1,0,
|
|
0,1,1,0,
|
|
1,1,1,1,
|
|
1,1,1,1,
|
|
0,1,1,0,
|
|
0,1,1,0,
|
|
0,1,1,0),
|
|
/* ▁ *\
|
|
2579▕╹▎box drawings heavy up
|
|
\* ▔ */
|
|
G(0,1,1,0,
|
|
0,1,1,0,
|
|
0,1,1,0,
|
|
0,1,1,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0),
|
|
/* ▁ *\
|
|
257a▕╺▎box drawings heavy right
|
|
\* ▔ */
|
|
G(0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,1,1,
|
|
0,0,1,1,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0),
|
|
/* ▁ *\
|
|
257b▕╻▎box drawings heavy down
|
|
\* ▔ */
|
|
G(0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,1,1,0,
|
|
0,1,1,0,
|
|
0,1,1,0,
|
|
0,1,1,0),
|
|
/* ▁ *\
|
|
2578▕╸▎box drawings heavy left
|
|
\* ▔ */
|
|
G(0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
1,1,0,0,
|
|
1,1,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0),
|
|
/* ▁ *\
|
|
250f▕┏▎box drawings heavy down and right
|
|
\* ▔ */
|
|
G(0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,1,1,1,
|
|
0,1,1,1,
|
|
0,1,1,0,
|
|
0,1,1,0,
|
|
0,1,1,0),
|
|
/* ▁ *\
|
|
251b▕┛▎box drawings heavy up and left
|
|
\* ▔ */
|
|
G(0,1,1,0,
|
|
0,1,1,0,
|
|
0,1,1,0,
|
|
1,1,1,0,
|
|
1,1,1,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0),
|
|
/* ▁ *\
|
|
2513▕┓▎box drawings heavy down and left
|
|
\* ▔ */
|
|
G(0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
1,1,1,0,
|
|
1,1,1,0,
|
|
0,1,1,0,
|
|
0,1,1,0,
|
|
0,1,1,0),
|
|
/* ▁ *\
|
|
2517▕┗▎box drawings heavy up and right
|
|
\* ▔ */
|
|
G(0,1,1,0,
|
|
0,1,1,0,
|
|
0,1,1,0,
|
|
0,1,1,1,
|
|
0,1,1,1,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0),
|
|
/* ▁ *\
|
|
25E2▕◢▎black lower right triangle
|
|
\* ▔ */
|
|
G(0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,1,
|
|
0,0,1,1,
|
|
1,1,1,1,
|
|
0,0,0,0,
|
|
0,0,0,0),
|
|
/* ▁ *\
|
|
25E3▕◣▎black lower left triangle
|
|
\* ▔ */
|
|
G(0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
1,0,0,0,
|
|
1,1,0,0,
|
|
1,1,1,1,
|
|
0,0,0,0,
|
|
0,0,0,0),
|
|
/* ▁ *\
|
|
25E4▕◥▎black upper right triangle
|
|
\* ▔ */
|
|
G(0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
1,1,1,1,
|
|
0,0,1,1,
|
|
0,0,0,1,
|
|
0,0,0,0,
|
|
0,0,0,0),
|
|
/* ▁ *\
|
|
25E5▕◤▎black upper left triangle
|
|
\* ▔ */
|
|
G(0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
1,1,1,1,
|
|
1,1,0,0,
|
|
1,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0),
|
|
/* ▁ *\
|
|
2500▕═▎box drawings double horizontal
|
|
\* ▔ */
|
|
G(0,0,0,0,
|
|
0,0,0,0,
|
|
1,1,1,1,
|
|
0,0,0,0,
|
|
1,1,1,1,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0),
|
|
/* ▁ *\
|
|
23BB▕⎻▎horizontal scan line 3
|
|
\* ▔ */
|
|
G(0,0,0,0,
|
|
0,0,0,0,
|
|
1,1,1,1,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0),
|
|
/* ▁ *\
|
|
23BD▕⎼▎horizontal scan line 9
|
|
\* ▔ */
|
|
G(0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
0,0,0,0,
|
|
1,1,1,1,
|
|
0,0,0,0,
|
|
0,0,0,0),
|
|
} /* clang-format on */;
|
|
|
|
const char16_t kRunes[] = {
|
|
u' ', /* 0020 empty block [ascii:20,cp437:20] */
|
|
u'█', /* 2588 full block [cp437] */
|
|
u'▄', /* 2584 lower half block [cp437:dc] */
|
|
u'▀', /* 2580 upper half block [cp437] */
|
|
u'▐', /* 2590 right half block [cp437:de] */
|
|
u'▌', /* 258C left half block */
|
|
u'▝', /* 259D quadrant upper right */
|
|
u'▙', /* 2599 quadrant upper left and lower left and lower right */
|
|
u'▗', /* 2597 quadrant lower right */
|
|
u'▛', /* 259B quadrant upper left and upper right and lower left */
|
|
u'▖', /* 2596 quadrant lower left */
|
|
u'▜', /* 259C quadrant upper left and upper right and lower right */
|
|
u'▘', /* 2598 quadrant upper left */
|
|
u'▟', /* 259F quadrant upper right and lower left and lower right */
|
|
u'▞', /* 259E quadrant upper right and lower left */
|
|
u'▚', /* 259A quadrant upper left and lower right */
|
|
u'▔', /* 2594 upper one eighth block */
|
|
u'▁', /* 2581 lower one eighth block */
|
|
u'▂', /* 2582 lower one quarter block */
|
|
u'▃', /* 2583 lower three eighths block */
|
|
u'▅', /* 2585 lower five eighths block */
|
|
u'▆', /* 2586 lower three quarters block */
|
|
u'▇', /* 2587 lower seven eighths block */
|
|
u'▎', /* 258E left one quarter block */
|
|
u'▊', /* 258A left three quarters block */
|
|
u'━', /* 2501 box drawings heavy horizontal */
|
|
u'┉', /* 2509 box drawings heavy quadruple dash horizontal */
|
|
u'┃', /* 2503 box drawings heavy vertical */
|
|
u'╋', /* 254B box drawings heavy vertical & horiz. */
|
|
u'╹', /* 2579 box drawings heavy up */
|
|
u'╺', /* 257A box drawings heavy right */
|
|
u'╻', /* 257B box drawings heavy down */
|
|
u'╸', /* 2578 box drawings heavy left */
|
|
u'┏', /* 250F box drawings heavy down and right */
|
|
u'┛', /* 251B box drawings heavy up and left */
|
|
u'┓', /* 2513 box drawings heavy down and left */
|
|
u'┗', /* 2517 box drawings heavy up and right */
|
|
u'◢', /* 25E2 black lower right triangle */
|
|
u'◣', /* 25E3 black lower left triangle */
|
|
u'◥', /* 25E4 black upper right triangle */
|
|
u'◤', /* 25E5 black upper left triangle */
|
|
u'═', /* 2550 box drawings double horizontal */
|
|
u'⎻', /* 23BB horizontal scan line 3 */
|
|
u'⎼', /* 23BD horizontal scan line 9 */
|
|
};
|