use std::fmt::Display;
use std::string::ToString;
static CHAR_ARRAY: [u64; 95] = [
0x0000000000000000,
0x183c3c1818001800,
0x3636000000000000,
0x36367f367f363600,
0x0c3e031e301f0c00,
0x006333180c666300,
0x1c361c6e3b336e00,
0x0606030000000000,
0x180c0606060c1800,
0x060c1818180c0600,
0x00663cff3c660000,
0x000c0c3f0c0c0000,
0x00000000000c0c06,
0x0000003f00000000,
0x00000000000c0c00,
0x6030180c06030100,
0x3e63737b6f673e00,
0x0c0e0c0c0c0c3f00,
0x1e33301c06333f00,
0x1e33301c30331e00,
0x383c36337f307800,
0x3f031f3030331e00,
0x1c06031f33331e00,
0x3f3330180c0c0c00,
0x1e33331e33331e00,
0x1e33333e30180e00,
0x000c0c00000c0c00,
0x000c0c00000c0c06,
0x180c0603060c1800,
0x00003f00003f0000,
0x060c1830180c0600,
0x1e3330180c000c00,
0x3e637b7b7b031e00,
0x0c1e33333f333300,
0x3f66663e66663f00,
0x3c66030303663c00,
0x1f36666666361f00,
0x7f46161e16467f00,
0x7f46161e16060f00,
0x3c66030373667c00,
0x3333333f33333300,
0x1e0c0c0c0c0c1e00,
0x7830303033331e00,
0x6766361e36666700,
0x0f06060646667f00,
0x63777f7f6b636300,
0x63676f7b73636300,
0x1c36636363361c00,
0x3f66663e06060f00,
0x1e3333333b1e3800,
0x3f66663e36666700,
0x1e33070e38331e00,
0x3f2d0c0c0c0c1e00,
0x3333333333333f00,
0x33333333331e0c00,
0x6363636b7f776300,
0x6363361c1c366300,
0x3333331e0c0c1e00,
0x7f6331184c667f00,
0x1e06060606061e00,
0x03060c1830604000,
0x1e18181818181e00,
0x081c366300000000,
0x00000000000000ff,
0x0c0c180000000000,
0x00001e303e336e00,
0x0706063e66663b00,
0x00001e3303331e00,
0x3830303e33336e00,
0x00001e333f031e00,
0x1c36060f06060f00,
0x00006e33333e301f,
0x0706366e66666700,
0x0c000e0c0c0c1e00,
0x300030303033331e,
0x070666361e366700,
0x0e0c0c0c0c0c1e00,
0x0000337f7f6b6300,
0x00001f3333333300,
0x00001e3333331e00,
0x00003b66663e060f,
0x00006e33333e3078,
0x00003b6e66060f00,
0x00003e031e301f00,
0x080c3e0c0c2c1800,
0x0000333333336e00,
0x00003333331e0c00,
0x0000636b7f7f3600,
0x000063361c366300,
0x00003333333e301f,
0x00003f190c263f00,
0x380c0c070c0c3800,
0x1818180018181800,
0x070c0c380c0c0700,
0x6e3b000000000000,
];
fn char_code(c: char) -> Option<u64> {
if (c as usize) < 0x20 || c as usize > 127 {
None
} else {
Some(CHAR_ARRAY[c as usize - 0x20])
}
}
fn char_map(c: char) -> Option<[bool; 64]> {
char_code(c).map(|n| {
let mut m = [false; 64];
for shf0 in (0..8).rev() {
for shf1 in 0..8 {
let shf = shf0 * 8 + shf1;
m[shf] = (n >> shf) & 1 == 1;
}
}
m
})
}
pub struct Moji {
foreground: String,
background: String,
max_chars: usize,
}
impl Moji {
pub fn new<T, U>(fg: T, bg: Option<U>, max_chars: usize) -> Self
where
T: Display,
U: Display,
{
Self {
foreground: format!(":{}:", fg),
background: if let Some(bg) = bg {
format!(":{}:", bg)
} else {
" ".to_string()
},
max_chars,
}
}
fn draw_row(&self, maps: &[[bool; 64]]) -> String {
let mut out = String::new();
for row in (0..8).rev() {
for map in maps {
for column in 0..8 {
out += if map[row * 8 + column] {
&self.foreground
} else {
&self.background
};
}
}
out += "\n";
}
out
}
pub fn draw<T: ToString>(&self, s: T) -> String {
let mut out = String::new();
let maps = s.to_string().chars().filter_map(char_map).collect::<Vec<_>>();
if self.max_chars == 0 {
out += &self.draw_row(&maps);
} else {
for maps_ch in maps.chunks(self.max_chars) {
out += &self.draw_row(maps_ch);
out += "\n";
}
}
out
}
}