cosmopolitan/tool/viz/lib/glyphs.c

545 lines
14 KiB
C
Raw Normal View History

2020-06-15 14:18:57 +00:00
/*-*- 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
2020-12-28 01:18:44 +00:00
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
2020-06-15 14:18:57 +00:00
2020-12-28 01:18:44 +00:00
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
2020-06-15 14:18:57 +00:00
*/
// 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),
/* ▁ *\
2501box 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),
/* ▁ *\
25019box 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),
/* ▁ *\
2503box 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),
/* ▁ *\
254bbox 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),
/* ▁ *\
2579box 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),
/* ▁ *\
257abox 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),
/* ▁ *\
257bbox 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),
/* ▁ *\
2578box 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),
/* ▁ *\
250fbox 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),
/* ▁ *\
251bbox 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),
/* ▁ *\
2513box 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),
/* ▁ *\
2517box 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),
/* ▁ *\
25E2black 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),
/* ▁ *\
25E3black 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),
/* ▁ *\
25E4black 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),
/* ▁ *\
25E5black 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),
/* ▁ *\
2500box 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),
/* ▁ *\
23BBhorizontal 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),
/* ▁ *\
23BDhorizontal 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 */
};