Initial.
commit
31e2f1ea56
|
@ -0,0 +1 @@
|
|||
/target
|
|
@ -0,0 +1,16 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "bitstream-io"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06c9989a51171e2e81038ab168b6ae22886fe9ded214430dbb4f41c28cf176da"
|
||||
|
||||
[[package]]
|
||||
name = "pictext"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bitstream-io",
|
||||
]
|
|
@ -0,0 +1,9 @@
|
|||
[package]
|
||||
name = "pictext"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
bitstream-io = "2.2.0"
|
|
@ -0,0 +1,243 @@
|
|||
/*
|
||||
|
||||
All graphics are 64x64 points.
|
||||
First bit of every octet indicates next byte is part of current character.
|
||||
|
||||
- Control?
|
||||
- - 0
|
||||
- - - 7 bit control code
|
||||
- - 1
|
||||
- - - Graphical Data
|
||||
- - - - bit X
|
||||
- - - - bit Y
|
||||
- - - - X? 7 bit signed int horizontal offset in points
|
||||
- - - - Y? 7 bit signed int vertical offset in points
|
||||
- - - - Bit Quadtree that caches homogeneity
|
||||
- - - - - Homogenous?
|
||||
- - - - - - 0
|
||||
- - - - - - - Read next level
|
||||
- - - - - - 1
|
||||
- - - - - - - Fill quadrant with next bit.
|
||||
|
||||
Empty graphical data (all 0s) indicates whitespace. Interpretation left to
|
||||
renderer. May utilize offsets for extra data or interpretation of whitespace,
|
||||
eg "x > 0" means space or "y < 0" means newline.
|
||||
*/
|
||||
|
||||
use bitstream_io::{BigEndian, BitRead, BitReader, Endianness};
|
||||
use std::io::Read;
|
||||
|
||||
pub struct BitReaderWrapper<T: Read, E: Endianness> {
|
||||
bit_count: usize,
|
||||
bitreader: BitReader<T, E>,
|
||||
}
|
||||
|
||||
// Subject to change
|
||||
pub enum ControlCode {
|
||||
DirectionRightDown = 4,
|
||||
DirectionLeftDown = 5,
|
||||
DirectionRightUp = 6,
|
||||
DirectionLeftUp = 7,
|
||||
}
|
||||
|
||||
impl<T: Read, E: Endianness> BitRead for BitReaderWrapper<T, E> {
|
||||
fn read_bit(&mut self) -> std::io::Result<bool> {
|
||||
if self.bit_count % 8 == 0 {
|
||||
self.bitreader.read_bit().ok();
|
||||
self.bit_count += 1;
|
||||
}
|
||||
self.bit_count += 1;
|
||||
self.bitreader.read_bit()
|
||||
}
|
||||
|
||||
fn read<U>(&mut self, mut bits: u32) -> std::io::Result<U>
|
||||
where
|
||||
U: bitstream_io::Numeric,
|
||||
{
|
||||
let mut n = U::default();
|
||||
while bits > 0 {
|
||||
if self.bit_count % 8 == 0 {
|
||||
self.bitreader.read_bit().ok();
|
||||
self.bit_count += 1;
|
||||
}
|
||||
n <<= 1;
|
||||
if self.bitreader.read_bit().unwrap() {
|
||||
n |= U::ONE;
|
||||
}
|
||||
self.bit_count += 1;
|
||||
bits -= 1;
|
||||
}
|
||||
Ok(n)
|
||||
}
|
||||
|
||||
fn read_signed<S>(&mut self, bits: u32) -> std::io::Result<S>
|
||||
where
|
||||
S: bitstream_io::SignedNumeric,
|
||||
{
|
||||
if self.bit_count % 8 == 0 {
|
||||
self.bitreader.read_bit().ok();
|
||||
self.bit_count += 1;
|
||||
}
|
||||
let sign = self.bitreader.read_bit().unwrap();
|
||||
self.bit_count += 1;
|
||||
let n = self.read::<S>(bits - 1).unwrap();
|
||||
if sign {
|
||||
Ok(n.as_negative(bits))
|
||||
} else {
|
||||
Ok(n)
|
||||
}
|
||||
}
|
||||
|
||||
fn read_to<V>(&mut self) -> std::io::Result<V>
|
||||
where
|
||||
V: bitstream_io::Primitive,
|
||||
{
|
||||
unimplemented![]
|
||||
}
|
||||
|
||||
fn read_as_to<F, V>(&mut self) -> std::io::Result<V>
|
||||
where
|
||||
F: Endianness,
|
||||
V: bitstream_io::Primitive,
|
||||
{
|
||||
unimplemented![]
|
||||
}
|
||||
|
||||
fn skip(&mut self, bits: u32) -> std::io::Result<()> {
|
||||
self.bit_count += bits as usize;
|
||||
self.bitreader.skip(bits)
|
||||
}
|
||||
|
||||
fn byte_aligned(&self) -> bool {
|
||||
unimplemented![]
|
||||
}
|
||||
|
||||
fn byte_align(&mut self) {
|
||||
unimplemented![]
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Character {
|
||||
pub x_offset: i8,
|
||||
pub y_offset: i8,
|
||||
pub control_code: Option<u8>,
|
||||
pub graphical_data: Option<[u8; 512]>,
|
||||
}
|
||||
|
||||
pub fn decode(input: &[u8]) -> Vec<Character> {
|
||||
let mut input = BitReaderWrapper {
|
||||
bit_count: 0,
|
||||
bitreader: BitReader::<&[u8], BigEndian>::new(input),
|
||||
};
|
||||
let mut output = vec![];
|
||||
while let Ok(graphical) = input.bitreader.read_bit() {
|
||||
input.bit_count += 1;
|
||||
if graphical {
|
||||
let offset_x = input.read_bit().unwrap();
|
||||
let offset_y = input.read_bit().unwrap();
|
||||
let mut x_offset = 0i8;
|
||||
let mut y_offset = 0i8;
|
||||
if offset_x {
|
||||
x_offset = input.read::<i8>(7).unwrap();
|
||||
}
|
||||
if offset_y {
|
||||
y_offset = input.read_signed::<i8>(7).unwrap();
|
||||
}
|
||||
let mut map = [0u64; 64];
|
||||
let mut value = None;
|
||||
for q0 in 0..4 {
|
||||
let mut erase = false;
|
||||
if input.read_bit().unwrap() {
|
||||
erase = true;
|
||||
value = Some(input.read_bit().unwrap());
|
||||
}
|
||||
for q1 in 0..4 {
|
||||
let mut erase = false;
|
||||
if value.is_none() && input.read_bit().unwrap() {
|
||||
erase = true;
|
||||
value = Some(input.read_bit().unwrap());
|
||||
}
|
||||
for q2 in 0..4 {
|
||||
let mut erase = false;
|
||||
if value.is_none() && input.read_bit().unwrap() {
|
||||
erase = true;
|
||||
value = Some(input.read_bit().unwrap());
|
||||
}
|
||||
for q3 in 0..4 {
|
||||
let mut erase = false;
|
||||
if value.is_none() && input.read_bit().unwrap() {
|
||||
erase = true;
|
||||
value = Some(input.read_bit().unwrap());
|
||||
}
|
||||
for q4 in 0..4 {
|
||||
let mut erase = false;
|
||||
if value.is_none() && input.read_bit().unwrap() {
|
||||
erase = true;
|
||||
value = Some(input.read_bit().unwrap());
|
||||
}
|
||||
for q5 in 0..4 {
|
||||
let index = (q0 / 2 * 32)
|
||||
+ (q1 / 2 * 16)
|
||||
+ (q2 / 2 * 8)
|
||||
+ (q3 / 2 * 4)
|
||||
+ (q4 / 2 * 2)
|
||||
+ (q5 / 2);
|
||||
let shift = (q0 % 2 * 32)
|
||||
+ (q1 % 2 * 16)
|
||||
+ (q2 % 2 * 8)
|
||||
+ (q3 % 2 * 4)
|
||||
+ (q4 % 2 * 2)
|
||||
+ (q5 % 2);
|
||||
map[index] |= if let Some(v) = value {
|
||||
if v {
|
||||
1 << shift
|
||||
} else {
|
||||
0
|
||||
}
|
||||
} else if input.read_bit().unwrap() {
|
||||
1 << shift
|
||||
} else {
|
||||
0
|
||||
};
|
||||
}
|
||||
if erase {
|
||||
value = None;
|
||||
}
|
||||
}
|
||||
if erase {
|
||||
value = None;
|
||||
}
|
||||
}
|
||||
if erase {
|
||||
value = None;
|
||||
}
|
||||
}
|
||||
if erase {
|
||||
value = None;
|
||||
}
|
||||
}
|
||||
if erase {
|
||||
value = None;
|
||||
}
|
||||
}
|
||||
let mut raster_data: [u8; 512] = [0; 512];
|
||||
let mut iter = map.iter().map(|t6| t6.to_le_bytes()).flatten();
|
||||
raster_data.fill_with(|| iter.next().unwrap());
|
||||
output.push(Character {
|
||||
x_offset,
|
||||
y_offset,
|
||||
control_code: None,
|
||||
graphical_data: Some(raster_data),
|
||||
});
|
||||
input.skip(8 - input.bit_count as u32 % 8).ok();
|
||||
} else {
|
||||
output.push(Character {
|
||||
x_offset: 0,
|
||||
y_offset: 0,
|
||||
control_code: input.read::<u8>(7).unwrap().into(),
|
||||
graphical_data: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
output
|
||||
}
|
Loading…
Reference in New Issue