/*-*- 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 */ };