meli/meli/src/terminal/braille.rs

489 lines
25 KiB
Rust
Raw Blame History

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

/*
* meli
*
* Copyright 2017-2018 Manos Pitsidianakis
*
* This file is part of meli.
*
* meli 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, either version 3 of the License, or
* (at your option) any later version.
*
* meli 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 meli. If not, see <http://www.gnu.org/licenses/>.
*/
struct Braille16bitColumn {
// each u16 in the tuple is one line ( first_line, second_line, third_line, fourth line) */
bitmaps: (u16, u16, u16, u16),
// reverse 1-indexing, so column: 1 means the left-most column in 16bit word */
bitcolumn: u32,
}
/*
impl std::fmt::Debug for Braille16bitColumn {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(
f,
"Braille16bitColumn {{\n bitmaps: \n{:x}\n{:x}\n{:x}\n{:x},\n bitcolumn: {}\n\n{}\n{:016b}\n{:016b}\n{:016b}\n{:016b},\n
}}",self.bitmaps.0, self.bitmaps.1, self.bitmaps.2, self.bitmaps.3, self.bitcolumn, format!("{:016b}", 0x0001_u16.rotate_left(self.bitcolumn)).replace("0"," ").replace("1", "v"), self.bitmaps.0, self.bitmaps.1, self.bitmaps.2, self.bitmaps.3,
)
}
}
*/
/// Iterate on 2x4 pixel blocks from a bitmap and return a unicode braille
/// character for each block. The iterator holds four lines of bitmaps
/// encoded as `u16` numbers in swapped bit order, like the `xbm`
/// graphics format. The bitmap is split to `u16` columns.
///
/// ## Usage
/// ```no_run
/// /* BEE is the contents of a 48x48 xbm file. xbm is a C-like array of 8bit values, and
/// * each pair was manually (macro-ually?) condensed into a single 16bit value. Each 3 items
/// * represent one pixel row.
/// */
/// const BEE: [u16; 3 * 48] = [
/// 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/// 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/// 0x0000, 0x0002, 0x0000, 0x0000, 0xe003, 0x0000, 0x0000, 0xfc00, 0x0000, 0x0000, 0x3f00,
/// 0x0000, 0x00e0, 0x0f00, 0x0000, 0x00f8, 0x0300, 0x0000, 0x00fe, 0x0000, 0x0080, 0x8f0d,
/// 0x0000, 0x00e0, 0xff7f, 0x0000, 0x00f8, 0xffff, 0x0300, 0x00fc, 0xffff, 0x0f00, 0x00fe,
/// 0xffff, 0x3f00, 0x00ff, 0xffff, 0xff00, 0xc0ff, 0xffff, 0xff01, 0xc0ff, 0xff77, 0xff07,
/// 0xf0f9, 0xffff, 0xff07, 0xf0f0, 0xffef, 0xfd0f, 0xf0e0, 0xffff, 0xfb1f, 0xf0e1, 0xffc1,
/// 0xfb0f, 0xe0f3, 0xffc3, 0xf307, 0xc0f7, 0xffc0, 0xe100, 0xc0ff, 0xd9e0, 0x3f00, 0x803e,
/// 0xc1f8, 0x5f00, 0x8076, 0x43f4, 0xbf18, 0x806c, 0x43fc, 0xf325, 0x0009, 0xc3df, 0x4326,
/// 0x001a, 0xcf3f, 0x622d, 0x0034, 0xff01, 0x2224, 0x00f0, 0xff00, 0x8312, 0x00a0, 0x5700,
/// 0x0309, 0x00f8, 0x1b00, 0x8f06, 0x0048, 0x6000, 0xcd03, 0x0018, 0x6624, 0xdf00, 0x0030,
/// 0x820f, 0x3f00, 0x00c0, 0xf0ff, 0x3f00, 0x0080, 0x03fe, 0x7f00, 0x0000, 0x7ce0, 0x0f00,
/// 0x0000, 0x809f, 0x1c00, 0x0000, 0x0000, 0x3800, 0x0000, 0x0000, 0x7000, 0x0000, 0x0000,
/// 0xe000,
/// ];
///
/// for lines in BEE.chunks(12) {
/// let iter = meli::BraillePixelIter::from(lines);
/// for b in iter {
/// print!("{}", b);
/// }
/// println!("");
/// }
/// ```
///
/// Output:
///
/// ```text
/// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠀⠀⠀
/// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣤⣶⠾⠛⠉⠀⠀⠀
/// ⠀⠀⠀⠀⠀⠀⢀⣠⣤⣤⣀⣠⣔⣾⣛⡛⠉⠀⠀⠀⠀⠀⠀⠀
/// ⠀⠀⠀⠀⣠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⣤⣀⠀⠀⠀⠀
/// ⠀⠀⣤⣿⠟⠻⣿⣿⣿⣿⣿⣿⣿⣯⢿⣯⡿⣿⣿⣿⣷⣆⠀⠀
/// ⠀⠀⠻⣿⣦⡀⣼⣿⣿⣿⣿⣿⠯⠉⠉⣿⡿⠘⢿⣿⠿⠟⠁⠀
/// ⠀⠀⠀⢹⠹⣟⢿⡍⣧⠈⠁⡟⠀⣔⣾⣿⣿⠿⣯⣢⡀⡠⢄⠀
/// ⠀⠀⠀⠀⠑⠜⣦⣀⣿⣶⣤⣿⠟⠛⠓⠉⣹⠀⠰⢃⢊⠗⡸⠀
/// ⠀⠀⠀⠀⠀⢰⡚⠞⢛⡑⢣⡅⠀⡀⢀⠀⣟⣶⡀⣴⠵⠊⠀⠀
/// ⠀⠀⠀⠀⠀⠀⠉⠲⠬⣀⣒⡚⠻⠿⢶⣶⣿⣿⠿⠄⠀⠀⠀⠀
/// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠉⠁⠈⠀⠙⢷⣄⠀⠀⠀
/// ```
///
///
/// ## Explanation:
/// For the following bitmap:
///
/// ```text
/// ◻◼◻◻◼◻◻◼◻◻◻◼◼◼◼◼
/// ◼◼◼◼◼◼◻◻◼◻◼◻◻◼◼◼
/// ◻◼◼◼◼◼◼◼◻◻◻◻◼◼◻◻
/// ◼◻◼◼◻◼◼◻◼◼◼◻◻◻◻◻
/// ```
///
/// Iteration on each step examines two columns:
///
/// ```text
/// ⇩⇩
/// ◻◼┆◻◻┆◼◻┆◻◼┆◻◻┆◻◼┆◼◼┆◼◼
/// ◼◼┆◼◼┆◼◼┆◻◻┆◼◻┆◼◻┆◻◼┆◼◼
/// ◻◼┆◼◼┆◼◼┆◼◼┆◻◻┆◻◻┆◼◼┆◻◻
/// ◼◻┆◼◼┆◻◼┆◼◻┆◼◼┆◼◻┆◻◻┆◻◻
/// ```
///
/// The first two columns are encoded as:
///
/// ```text
/// ┏━━━━━━┳━━━━┓
/// ┃pixels┃bits┃
/// ┡━━━━━━╇━━━━┩
/// │ ◻◼ │ 14 │
/// │ ◼◼ │ 25 │
/// │ ◻◻ │ 36 │
/// │ ◼◻ │ 78 │
/// └──────┴────┘
/// =
/// braille bitmap is
/// ◻◼◻◼◼◻◼◻ = 0b01011010 = 0x5A
/// 12345678
/// ```
///
/// and braille character is bitmap + 0x2800 (Braille block's position in
/// Unicode)
///
/// ```text
/// 0x5A + 0x2800 = 0x285A = '⡚'
/// ```
///
/// Why three columns? I originally wrote this for X-Face bitmaps, which are
/// 48x48 pixels.
pub struct BraillePixelIter {
columns: [Braille16bitColumn; 3],
column_ptr: usize,
}
impl From<&[u16]> for BraillePixelIter {
fn from(from: &[u16]) -> Self {
Self {
columns: [
Braille16bitColumn {
bitmaps: (
from[0].swap_bytes().reverse_bits(),
from[3].swap_bytes().reverse_bits(),
from[6].swap_bytes().reverse_bits(),
from[9].swap_bytes().reverse_bits(),
),
bitcolumn: 1,
},
Braille16bitColumn {
bitmaps: (
from[1].swap_bytes().reverse_bits(),
from[4].swap_bytes().reverse_bits(),
from[7].swap_bytes().reverse_bits(),
from[10].swap_bytes().reverse_bits(),
),
bitcolumn: 1,
},
Braille16bitColumn {
bitmaps: (
from[2].swap_bytes().reverse_bits(),
from[5].swap_bytes().reverse_bits(),
from[8].swap_bytes().reverse_bits(),
from[11].swap_bytes().reverse_bits(),
),
bitcolumn: 1,
},
],
column_ptr: 0,
}
}
}
impl Iterator for BraillePixelIter {
type Item = char;
fn next(&mut self) -> Option<char> {
if self.columns[self.column_ptr].bitcolumn == 17 {
if self.column_ptr == 2 {
return None;
}
self.column_ptr += 1;
return self.next();
}
let Braille16bitColumn {
ref bitmaps,
ref mut bitcolumn,
} = &mut self.columns[self.column_ptr];
/* First bitcolumn out of two (braille is 2x4) */
let mut bits: u16 = 0x1 & (bitmaps.0.rotate_left(*bitcolumn)); // * 0x1;
bits += (0x1 & (bitmaps.1.rotate_left(*bitcolumn))) * 0x2;
bits += (0x1 & (bitmaps.2.rotate_left(*bitcolumn))) * 0x4;
bits += (0x1 & (bitmaps.3.rotate_left(*bitcolumn))) * 0x40;
/* Second bitcolumn */
*bitcolumn += 1;
bits += (0x1 & (bitmaps.0.rotate_left(*bitcolumn))) * 0x8;
bits += (0x1 & (bitmaps.1.rotate_left(*bitcolumn))) * 0x10;
bits += (0x1 & (bitmaps.2.rotate_left(*bitcolumn))) * 0x20;
bits += (0x1 & (bitmaps.3.rotate_left(*bitcolumn))) * 0x80;
*bitcolumn += 1;
/* The Braille Patterns block spans the entire [U+2800, U+28FF] range and
* bits is a 16bit integer ∈ [0x00, 0xFF] so this is guaranteed
* to be a Unicode char */
Some(unsafe { std::char::from_u32_unchecked(bits as u32 + 0x2800) })
}
}
#[cfg(test)]
mod tests {
type Xbm = [u16; 3 * 48];
const _X_QRCODE: (Xbm, &str) = (
[
0xff3f, 0x3cf3, 0xff03, 0xff3f, 0x3cf3, 0xff03, 0x0330, 0x0333, 0x0003, 0x0330, 0x0333,
0x0003, 0xf333, 0xf030, 0x3f03, 0xf333, 0xf030, 0x3f03, 0xf333, 0xfc33, 0x3f03, 0xf333,
0xfc33, 0x3f03, 0xf333, 0x0f33, 0x3f03, 0xf333, 0x0f33, 0x3f03, 0x0330, 0x3033, 0x0003,
0x0330, 0x3033, 0x0003, 0xff3f, 0x33f3, 0xff03, 0xff3f, 0x33f3, 0xff03, 0x0000, 0xc003,
0x0000, 0x0000, 0xc003, 0x0000, 0x3333, 0xfc00, 0xc300, 0x3333, 0xfc00, 0xc300, 0xc3c0,
0x3f30, 0x0c00, 0xc3c0, 0x3f30, 0x0c00, 0xcff0, 0x3f03, 0xcf00, 0xcff0, 0x3f03, 0xcf00,
0x0ccf, 0x0f30, 0xcc00, 0x0ccf, 0x0f30, 0xcc00, 0x0033, 0x3033, 0xf300, 0x0033, 0x3033,
0xf300, 0x0000, 0xffcc, 0x0c00, 0x0000, 0xffcc, 0x0c00, 0xff3f, 0xccfc, 0x3000, 0xff3f,
0xccfc, 0x3000, 0x0330, 0xf0cf, 0x0f00, 0x0330, 0xf0cf, 0x0f00, 0xf333, 0xcffc, 0x3003,
0xf333, 0xcffc, 0x3003, 0xf333, 0x0030, 0xf000, 0xf333, 0x0030, 0xf000, 0xf333, 0x3f03,
0x0303, 0xf333, 0x3f03, 0x0303, 0x0330, 0x3030, 0xf003, 0x0330, 0x3030, 0xf003, 0xff3f,
0x0333, 0x3303, 0xff3f, 0x0333, 0x3303, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000,
],
r#"
⣿⠛⠛⠛⠛⠛⣿⠀⣤⠛⠛⠀⣿⠀⣿⠛⠛⠛⠛⠛⣿⠀⠀⠀
⣿⠀⣿⣿⣿⠀⣿⠀⠀⣤⣿⣿⣤⠀⣿⠀⣿⣿⣿⠀⣿⠀⠀⠀
⣿⠀⠛⠛⠛⠀⣿⠀⠛⠛⣤⠀⣿⠀⣿⠀⠛⠛⠛⠀⣿⠀⠀⠀
⠛⠛⠛⠛⠛⠛⠛⠀⠛⠀⠛⣤⣿⠀⠛⠛⠛⠛⠛⠛⠛⠀⠀⠀
⣿⠀⠛⣤⠛⠀⠛⣤⣤⣿⣿⠛⠀⠀⣤⠀⠛⣤⠀⠛⠀⠀⠀⠀
⠛⣿⠀⠛⣤⣤⠛⣿⣿⣿⠛⠀⠛⠀⣤⠀⠛⣿⠀⣿⠀⠀⠀⠀
⠀⠀⠀⠀⠛⠀⠛⠀⣤⣤⣿⣤⠛⣤⠛⣤⠛⣤⠛⠛⠀⠀⠀⠀
⣿⠛⠛⠛⠛⠛⣿⠀⠀⠛⣤⣿⣤⣿⠛⣿⣤⣤⠛⠀⠀⠀⠀⠀
⣿⠀⣿⣿⣿⠀⣿⠀⠛⠛⠀⠛⠀⠛⣿⠛⠀⠀⣿⣤⠛⠀⠀⠀
⣿⠀⠛⠛⠛⠀⣿⠀⠛⠛⣿⠀⠛⠀⣤⠀⠛⠀⣤⣤⣿⠀⠀⠀
⠛⠛⠛⠛⠛⠛⠛⠀⠛⠀⠀⠀⠛⠀⠛⠀⠛⠀⠛⠀⠛⠀⠀⠀
"#,
);
const XTTHOMAS: (Xbm, &str) = (
[
0xFFFF, 0xFF0F, 0x0000, 0xFFFF, 0xFF0F, 0x0000, 0x1FFC, 0xC10F, 0x0000, 0x0FFC, 0x810F,
0x0000, 0x07FC, 0x010F, 0x0000, 0x07FC, 0x010F, 0x0000, 0x03FC, 0x010E, 0x0000, 0x03FC,
0x010E, 0x0000, 0x01FC, 0x010C, 0x0000, 0x00FC, 0x0100, 0x0000, 0x00FC, 0x0100, 0x0000,
0x00FC, 0x0100, 0x0000, 0x00FC, 0x0100, 0x0000, 0x00FC, 0x0100, 0x0000, 0x00FC, 0x0100,
0x0000, 0x00FC, 0x0100, 0x0000, 0x00FC, 0x0100, 0x0000, 0x00FC, 0xFDFF, 0xFF7F, 0x00FC,
0xFDFF, 0xFF7F, 0x00FC, 0xFDE0, 0x0F7E, 0x00FC, 0x7DE0, 0x0F7C, 0x00FC, 0x3DE0, 0x0F78,
0x00FC, 0x3DE0, 0x0F78, 0x00FC, 0x1DE0, 0x0F70, 0x00FC, 0x1DE0, 0x0F70, 0x00FC, 0x0DE0,
0x0F60, 0x00FC, 0x01E0, 0x0F00, 0x00FE, 0x07E0, 0x0F00, 0xC0FF, 0x1FE0, 0x0F00, 0xC0FF,
0x1FE0, 0x0F00, 0x0000, 0x00E0, 0x0F00, 0x0000, 0x00E0, 0x0F00, 0x0000, 0x00E0, 0x0F00,
0x0000, 0x00E0, 0x0F00, 0x0000, 0x00E0, 0x0F00, 0x0000, 0x00E0, 0x0F00, 0x0000, 0x00E0,
0x0F00, 0x0000, 0x00E0, 0x0F00, 0x0000, 0x00E0, 0x0F00, 0x0000, 0x00E0, 0x0F00, 0x0000,
0x00E0, 0x0F00, 0x0000, 0x00E0, 0x0F00, 0x0000, 0x00E0, 0x0F00, 0x0000, 0x00E0, 0x0F00,
0x0000, 0x00F0, 0x3F00, 0x0000, 0x00FE, 0xFF00, 0x0000, 0x00FE, 0xFF00, 0x0000, 0x0000,
0x0000,
],
r#"⣿⣿⠟⠛⠛⣿⣿⣿⡟⠛⠛⢿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⣿⠃⠀⠀⠀⣿⣿⣿⡇⠀⠀⠀⢻⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠁⠀⠀⠀⠀⣿⣿⣿⡇⠀⠀⠀⠀⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⣿⣿⣿⡇⣶⣶⣶⠶⠶⢶⣶⣶⣶⠶⠶⢶⣶⣶⡆
⠀⠀⠀⠀⠀⣿⣿⣿⡇⣿⡿⠁⠀⠀⢸⣿⣿⣿⠀⠀⠀⠹⣿⡇
⠀⠀⠀⠀⢀⣿⣿⣿⣇⡛⠁⠀⠀⠀⢸⣿⣿⣿⠀⠀⠀⠀⠙⠃
⠀⠀⠀⠛⠛⠛⠛⠛⠛⠛⠃⠀⠀⠀⢸⣿⣿⣿⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠰⠶⠿⠿⠿⠿⠿⠶⠀⠀⠀⠀
"#,
);
const FBIRD_SCALED_DOWN: (Xbm, &str) = (
[
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x00e0, 0x0100, 0x0000, 0x0000, 0x0f00, 0x0000, 0x0000, 0x3c00, 0x0000, 0x00e0,
0x790c, 0x0000, 0x00fc, 0xff3f, 0x0000, 0x0043, 0xffff, 0x0300, 0x0000, 0xfc0f, 0x0000,
0x0000, 0xf00f, 0x0000, 0x0000, 0xf00f, 0x0000, 0x0000, 0xf00f, 0x0000, 0x0000, 0xfc07,
0x0000, 0x0000, 0xfc03, 0x0000, 0x0000, 0xfc00, 0x0000, 0x0000, 0x0e00, 0x0000, 0x0000,
0x0700, 0x0000, 0x0000, 0x0700, 0x0000, 0x0040, 0x0300, 0x0000, 0x0000, 0x0200, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000,
],
r#"
⠀⠀⠀⠀⠀⠀⢀⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⣀⣠⣤⣍⣻⣶⣄⣀⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠉⠀⠀⠁⠉⠛⣿⣿⣿⣿⠉⠉⠉⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⣶⣿⣿⠿⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⡀⣾⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
"#,
);
const SYS: (Xbm, &str) = (
[
0x0000, 0x0000, 0x0000, 0x0000, 0x0002, 0x0000, 0x0000, 0x0000, 0x0100, 0x0000, 0x8080,
0x0200, 0x0000, 0x0088, 0x2200, 0x0000, 0x00b4, 0x5a00, 0x0000, 0x0248, 0x2400, 0x0000,
0x0008, 0x2000, 0x0020, 0x0090, 0x1300, 0x0000, 0x10ce, 0xe700, 0x0000, 0x28c1, 0x0701,
0x0088, 0x28ce, 0xe700, 0x0040, 0xab95, 0x1300, 0x0080, 0x440a, 0x2000, 0x0080, 0x004a,
0x2400, 0x0000, 0x39b5, 0x5a04, 0x00e0, 0x7c8e, 0x2200, 0x0012, 0x7c90, 0x0200, 0x00e0,
0x7c0e, 0x0101, 0x0000, 0x3901, 0x0000, 0x0080, 0x0002, 0x2000, 0x0080, 0x4412, 0x0000,
0x0040, 0xab2d, 0x0000, 0x0080, 0xa82a, 0x0200, 0x0000, 0x68ab, 0x0500, 0x0000, 0x9044,
0x4200, 0x0000, 0x8000, 0x0200, 0x0020, 0x0039, 0x0100, 0x0002, 0xe07c, 0x8e00, 0x0080,
0x107c, 0x1000, 0x8040, 0xe17c, 0x0e00, 0x0044, 0x1139, 0x0100, 0x405a, 0xad00, 0x8200,
0x0024, 0x9244, 0x0200, 0x0004, 0x50ab, 0x0500, 0x20c8, 0x8928, 0x0200, 0x00e7, 0x7328,
0x2000, 0x80e0, 0x8310, 0x0000, 0x00e7, 0x7300, 0x0000, 0x00c8, 0x0900, 0x0000, 0x0004,
0x1000, 0x0000, 0x0024, 0x1202, 0x0000, 0x005a, 0x2d00, 0x0000, 0x0044, 0x1100, 0x0000,
0x0040, 0x8100, 0x0000, 0x0080, 0x0000, 0x0000, 0x0000, 0x1000, 0x0000, 0x0000, 0x0000,
0x0000,
],
r#"⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠐⠀⠀⢀⢄⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠠⠀⠀⠀⠀⢪⠒⠜⠘⠔⢪⠂⠀⠀⠀⠀
⠀⠀⠀⠀⠀⢀⠈⢀⠀⢠⢢⠀⢔⣒⠁⣾⣿⡆⢑⣒⠄⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠱⡉⢊⣈⠊⡱⡱⣁⢌⢉⢄⡱⡀⠀⡀⠀⠀
⠀⠀⠀⠀⠐⠀⠪⠭⡀⢿⣿⠇⡨⠭⠂⠘⠜⠀⠈⠀⠄⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⢜⠤⢢⢠⢢⢜⢤⢢⠀⢀⠀⠈⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⢀⠀⠀⠈⠊⠱⡉⢊⣈⠊⡱⠁⠀⠂⠀⠀⠀⠀
⠀⠀⠀⠠⠈⡀⠀⡔⡄⠀⡪⠭⡀⢿⣿⠇⡨⠭⠂⠈⠀⠀⠀⠀
⠀⠀⢀⠁⠈⢎⠑⣁⡑⢉⠎⢜⠤⢢⢠⠢⢜⠄⠀⠈⠀⠀⠀⠀
⠀⠀⠀⠐⠭⢅⠸⣿⡿⢀⠭⠕⠀⠈⠊⠀⠀⠀⠈⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠠⡣⠔⡄⡔⠤⡣⠀⠐⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠑⠁⠀⠄⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
"#,
);
const FBIRD: (Xbm, &str) = (
[
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x007E, 0x0000, 0x0000, 0x00E0, 0x0700, 0x0000, 0x0080, 0x1F00, 0x0000,
0x0000, 0x7F00, 0x0000, 0x007E, 0xFCE0, 0x0000, 0xC0FF, 0xFFF9, 0x0300, 0xF0FF, 0xFFFF,
0x0700, 0x0CE8, 0xFFFF, 0xFF00, 0x0080, 0xFFFF, 0x0103, 0x0000, 0xFEFF, 0x0000, 0x0000,
0xF8FF, 0x0000, 0x0000, 0xF07F, 0x0000, 0x0000, 0xF07F, 0x0000, 0x0000, 0xF87F, 0x0000,
0x0000, 0xFC3F, 0x0000, 0x0000, 0xFE3F, 0x0000, 0x0000, 0xFE1F, 0x0000, 0x0000, 0xFF07,
0x0000, 0x0000, 0xFF01, 0x0000, 0x0080, 0x0F00, 0x0000, 0x0080, 0x0700, 0x0000, 0x00C0,
0x0300, 0x0000, 0x00E0, 0x0300, 0x0000, 0x00F0, 0x0300, 0x0000, 0x00E8, 0x0100, 0x0000,
0x0080, 0x0100, 0x0000, 0x0000, 0x0100, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000,
],
r#"
⠀⠀⠀⠀⠈⠉⠙⠳⣶⣦⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⣀⠤⠶⠾⢿⢿⣷⣶⣿⣿⣿⣦⣴⣾⣿⣶⣄⣀⣀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠈⠙⠻⣿⣿⣿⣿⣿⡿⠁⠀⠀⠀⠉⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⣿⣿⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⠿⠿⠟⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⣠⣾⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠈⠈⠙⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
"#,
);
const XFACE: (Xbm, &str) = (
[
0xAAAA, 0xAAAA, 0xAAAA, 0x0000, 0x0000, 0x0000, 0xAAAA, 0xAAAA, 0xAAA8, 0x0000, 0x0000,
0x0000, 0xA222, 0x2222, 0x222A, 0x0000, 0x0000, 0x0000, 0xAAAA, 0xAAAA, 0xAAA2, 0x0000,
0x0000, 0x0000, 0xA222, 0x2222, 0x2228, 0x0000, 0x0000, 0x0000, 0xAAAA, 0xAAAA, 0xAAAA,
0x0000, 0x0000, 0x0000, 0xA222, 0x2222, 0x2222, 0x0000, 0x0000, 0x0000, 0xAAAA, 0xAAAA,
0xAAA8, 0x0000, 0x0000, 0x0000, 0xA222, 0x2222, 0x222A, 0x0000, 0x0000, 0x0000, 0xAAAA,
0xAAAA, 0xAAA2, 0x0000, 0x0000, 0x0000, 0xA222, 0x2222, 0x2228, 0x0000, 0x0000, 0x0000,
0xAAAA, 0xAAAA, 0xAAAA, 0x0000, 0x0000, 0x0000, 0xA222, 0x2222, 0x2222, 0x0000, 0x0000,
0x0000, 0xAAAA, 0xAAAA, 0xAAA8, 0x0000, 0x0000, 0x0000, 0xA222, 0x2222, 0x222A, 0x0000,
0x0000, 0x0000, 0xAAAA, 0xAAAA, 0xAAA2, 0x0000, 0x0000, 0x0000, 0xA222, 0x2222, 0x2228,
0x0000, 0x0000, 0x0000, 0xAAAA, 0xAAAA, 0xAAAA, 0x0000, 0x0000, 0x0000, 0xA222, 0x2222,
0x2222, 0x0000, 0x0000, 0x0000, 0xAAAA, 0xAAAA, 0xAAA8, 0x0000, 0x0000, 0x0000, 0xA222,
0x2222, 0x222A, 0x0000, 0x0000, 0x0000, 0xAAAA, 0xAAAA, 0xAAA2, 0x0000, 0x0000, 0x0000,
0xA222, 0x2222, 0x2228, 0x0000, 0x0000, 0x0000, 0xAAAA, 0xAAAA, 0xAAAA, 0x0000, 0x0000,
0x0000,
],
r#"⠨⠨⠨⠨⠨⠨⠨⠨⠨⠨⠨⠨⠨⠨⠨⠨⠨⠨⠨⠨⠈⠨⠨⠨
⠨⠠⠨⠨⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠨⠈⠨⠠
⠨⠠⠨⠨⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠠⠨⠨⠠
⠨⠠⠨⠨⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠈⠠⠨⠠
⠨⠠⠨⠨⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠨⠈⠨⠠
⠨⠠⠨⠨⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠠⠨⠨⠠
⠨⠠⠨⠨⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠈⠠⠨⠠
⠨⠠⠨⠨⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠨⠈⠨⠠
⠨⠠⠨⠨⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠠⠨⠨⠠
⠨⠠⠨⠨⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠈⠠⠨⠠
⠨⠠⠨⠨⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠨⠈⠨⠠
⠨⠠⠨⠨⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠨⠠⠠⠨⠨⠠
"#,
);
const MAILQ: (Xbm, &str) = (
[
0x0000, 0x0000, 0x0000, 0xffff, 0xff00, 0x0000, 0x0100, 0x8000, 0x0000, 0x5501, 0xb800,
0x0000, 0xa900, 0xb800, 0x0000, 0x5501, 0x8000, 0x0000, 0x0100, 0x8000, 0x0000, 0x01f0,
0xffff, 0x0f00, 0x0110, 0x0000, 0x0800, 0x0150, 0x1580, 0x0b00, 0xff9f, 0x0a80, 0x0b00,
0x0050, 0x1500, 0x0800, 0x0010, 0x0000, 0x0800, 0x0010, 0x00ff, 0xffff, 0x0010, 0x0001,
0x0080, 0x0010, 0x0055, 0x01b8, 0x00f0, 0xffa9, 0x00b8, 0x0000, 0x0055, 0x0180, 0x0000,
0x0001, 0x4095, 0x00f0, 0xffff, 0x8f8a, 0x0010, 0x0000, 0x4895, 0x0050, 0x1580, 0x0b80,
0x0090, 0x0a80, 0xfbff, 0x0050, 0x1500, 0x0800, 0x0010, 0x0054, 0x0900, 0xffff, 0xffa8,
0x0800, 0x0100, 0x8054, 0x0900, 0x5501, 0xb800, 0x0800, 0xa900, 0xb8ff, 0x0f00, 0x5501,
0x8000, 0x0000, 0x0100, 0x8000, 0x0000, 0x01f0, 0xffff, 0x0f00, 0x0110, 0x0000, 0x0800,
0x0150, 0x1580, 0x0b00, 0xff9f, 0x0a80, 0x0b00, 0x0050, 0x1500, 0x0800, 0x0010, 0x0000,
0x0800, 0x0010, 0x00ff, 0xffff, 0x0010, 0x0001, 0x0080, 0x0010, 0x0055, 0x01b8, 0x00f0,
0xffa9, 0x00b8, 0x0000, 0x0055, 0x0180, 0x0000, 0x0001, 0x4095, 0x0000, 0x0001, 0x808a,
0x0000, 0x0001, 0x4095, 0x0000, 0x0001, 0x0080, 0x0000, 0x00ff, 0xffff, 0x0000, 0x0000,
0x0000,
],
r#"⡖⡒⡒⡒⡒⠒⠒⠒⠒⢒⣒⢲⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⡇⠊⠊⠊⠂⠀⣀⣀⣀⣈⣉⣸⣀⣀⣀⣀⣀⣀⠀⠀⠀⠀⠀⠀
⠧⠤⠤⠤⠤⠤⡇⡢⡢⡢⡂⠀⠀⠀⠀⠰⠶⢸⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⡖⡒⡒⡒⡒⠚⠒⠒⠒⢒⣒⢲
⠀⠀⠀⠀⠀⠀⣉⣉⣉⣉⣉⣉⣇⣊⣊⣊⣂⣀⠀⢄⢄⢌⠍⢸
⠀⠀⠀⠀⠀⠀⡇⡢⡢⡢⡂⠀⠀⠀⠀⠰⠶⢸⠤⠥⠥⠥⠥⠼
⡖⡒⡒⡒⡒⠒⠓⠒⠒⢒⣒⢲⠀⠕⠕⠕⠅⢸⠀⠀⠀⠀⠀⠀
⡇⠊⠊⠊⠂⠀⣀⣀⣀⣈⣉⣸⣉⣉⣉⣉⣉⣉⠀⠀⠀⠀⠀⠀
⠧⠤⠤⠤⠤⠤⡇⡢⡢⡢⡂⠀⠀⠀⠀⠰⠶⢸⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⡖⡒⡒⡒⡒⠚⠒⠒⠒⢒⣒⢲
⠀⠀⠀⠀⠀⠀⠉⠉⠉⠉⠉⠉⡇⠊⠊⠊⠂⠀⠀⢄⢄⢌⠍⢸
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠧⠤⠤⠤⠤⠤⠤⠥⠥⠥⠥⠼
"#,
);
macro_rules! add_to_all {
($($xbm:ident),*$(,)?) => {
&[
$((stringify!($xbm), $xbm),)*
]
};
}
const ALL: &[(&str, (Xbm, &str))] = add_to_all! {
FBIRD,
FBIRD_SCALED_DOWN,
MAILQ,
SYS,
XFACE,
XTTHOMAS,
};
#[test]
fn test_braille_xface() {
/* lines has 12 bitmaps, with 3 bitmap making each line that is 4 lines.
* lines = [
* a_0, a_1, a_2,
* b_0, b_1, b_2,
* c_0, c_1, c_2,
* d_0, d_1, d_2,
* ];
*/
for (name, (face, output)) in ALL {
println!("{name}: \n--------------------------------------");
let mut printed = String::new();
for lines in face.chunks(12) {
let iter = super::BraillePixelIter::from(lines);
print!("`");
for b in iter {
print!("{b}");
printed.push(b);
}
printed.push('\n');
println!("`");
}
assert_eq!(printed.as_bytes(), output.as_bytes());
}
}
}