🐝 I really like where this mua is(was?) headed, but it seems as though there has not been much activity recently.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

442 lines
21 KiB

/*
* 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/>.
*/
/*! Terminal grid cells, keys, colors, etc.
*/
extern crate serde;
use self::serde::de::Visitor;
use self::serde::{de, Deserialize, Deserializer};
extern crate unicode_segmentation;
#[macro_use]
mod position;
#[macro_use]
mod cells;
#[macro_use]
mod keys;
pub mod embed;
mod text_editing;
pub use self::cells::*;
pub use self::keys::*;
pub use self::position::*;
pub use self::text_editing::*;
use std::fmt;
/*
* CSI events we use
*/
// Some macros taken from termion:
/// Create a CSI-introduced sequence.
macro_rules! csi {
($( $l:expr ),*) => { concat!("\x1b[", $( $l ),*) };
}
/// Derive a CSI sequence struct.
macro_rules! derive_csi_sequence {
($(#[$outer:meta])*
($name:ident, $value:expr)) => {
$(#[$outer])*
#[derive(Copy, Clone)]
pub struct $name;
impl fmt::Display for $name {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, csi!($value))
}
}
impl AsRef<[u8]> for $name {
fn as_ref(&self) -> &'static [u8] {
csi!($value).as_bytes()
}
}
impl AsRef<str> for $name {
fn as_ref(&self) -> &'static str {
csi!($value)
}
}
};
}
/*
derive_csi_sequence!(
#[doc = ""]
(DisableMouse, "?1000l")
);
derive_csi_sequence!(
#[doc = ""]
(EnableMouse, "?1000h")
);
*/
derive_csi_sequence!(
#[doc = "`CSI Ps ; Ps ; Ps t`, where `Ps = 2 2 ; 0` -> Save xterm icon and window title on stack."]
(SaveWindowTitleIconToStack, "22;0t")
);
derive_csi_sequence!(
#[doc = "Restore window title and icon from terminal's title stack. `CSI Ps ; Ps ; Ps t`, where `Ps = 2 3 ; 0` -> Restore xterm icon and window title from stack."]
(RestoreWindowTitleIconFromStack, "23;0t")
);
derive_csi_sequence!(
#[doc = "Empty struct with a Display implementation that returns the byte sequence to start [Bracketed Paste Mode](http://www.xfree86.org/current/ctlseqs.html#Bracketed%20Paste%20Mode)"]
(BracketModeStart, "?2004h")
);
derive_csi_sequence!(
#[doc = "Empty struct with a Display implementation that returns the byte sequence to end [Bracketed Paste Mode](http://www.xfree86.org/current/ctlseqs.html#Bracketed%20Paste%20Mode)"]
(BracketModeEnd, "?2004l")
);
pub const BRACKET_PASTE_START: &[u8] = b"\x1B[200~";
pub const BRACKET_PASTE_END: &[u8] = b"\x1B[201~";
pub use braille::BraillePixelIter;
mod braille {
mod tests {
const _X_QRCODE: [u16; 3 * 48] = [
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,
];
const _XTTHOMAS: [u16; 3 * 48] = [
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,
];
const _FBIRD_SCALED_DOWN: [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, 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,
];
const _FBIRD: [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, 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,
];
const _XFISH: [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, 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,
];
const _XFACE: [u16; 3 * 48] = [
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,
];
#[test]
fn test_braille() {
/* 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,
* ];
*/
println!("Thomas: ");
for lines in _XTTHOMAS.chunks(12) {
let iter = super::BraillePixelIter::from(lines);
for b in iter {
print!("{}", b);
}
println!("");
}
println!("fbird: ");
for lines in _FBIRD.chunks(12) {
let iter = super::BraillePixelIter::from(lines);
for b in iter {
print!("{}", b);
}
println!("");
}
println!("ABC QR code: ");
for lines in _X_QRCODE.chunks(12) {
let iter = super::BraillePixelIter::from(lines);
for b in iter {
print!("{}", b);
}
println!("");
}
}
}
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 = ui::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 {
BraillePixelIter {
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;
}
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) })
}
}
}