/*-*- 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                              â
â                                                                              â
â 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.      â
â                                                                              â
â 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.                                                â
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ*/

// The modes below use various unicodes for 'progressive' 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 parsimonious: 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 traditionally 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 */
};
