pub(crate) struct PlainChars {
slots: Box<[u64; SLOTS]>,
row_of: Box<[u8; SLOTS]>,
rows: Vec<[u8; SLOTS]>,
kerns: Vec<i16>,
inked: bool,
}
#[derive(Clone, Copy)]
pub(crate) struct PlainChar {
pub(crate) glyph: u16,
pub(crate) advance: i16,
pub(crate) pairs: bool,
slot: u8,
}
impl PlainChar {
fn of(packed: u64, slot: u8) -> Self {
Self {
glyph: (packed >> 16) as u16,
advance: packed as u16 as i16,
pairs: packed & PAIRS != 0,
slot,
}
}
}
pub(crate) struct CharGlyph {
pub(crate) glyph: u32,
pub(crate) advance: i32,
pub(crate) pairs: bool,
pub(crate) inks_out: bool,
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub(crate) enum PairFit {
Kern(i32),
Joins,
}
const SLOT_BITS: u32 = 7;
const SLOTS: usize = 1 << SLOT_BITS;
const FILLED: u64 = 1 << 63;
const PLAIN: u64 = 1 << 62;
const PAIRS: u64 = 1 << 61;
const INKS_OUT: u64 = 1 << 60;
const UNREAD: u8 = 0;
const JOINS: u8 = 1;
const UNKERNED: u8 = 2;
const KERNED: u8 = 3;
const MOST_KERNS: usize = (u8::MAX - KERNED) as usize + 1;
impl Default for PlainChars {
fn default() -> Self {
Self {
slots: Box::new([0; SLOTS]),
row_of: Box::new([0; SLOTS]),
rows: Vec::new(),
kerns: Vec::new(),
inked: false,
}
}
}
impl PlainChars {
pub(crate) fn char(
&mut self,
ch: char,
read: &impl Fn(char) -> Option<CharGlyph>,
) -> Option<PlainChar> {
let code = u32::from(ch);
let slot = (code & (SLOTS as u32 - 1)) as u8;
let packed = self.slots[usize::from(slot)];
let known = (FILLED >> 32) | u64::from(code);
if (packed >> 32) & !(PAIRS >> 32) == known | (PLAIN >> 32) {
return Some(PlainChar::of(packed, slot));
}
self.uncommon_char(slot, (packed, known), ch, read)
}
pub(crate) fn take_inked(&mut self) -> bool {
std::mem::take(&mut self.inked)
}
#[inline(never)]
fn uncommon_char(
&mut self,
slot: u8,
(packed, known): (u64, u64),
ch: char,
read: &impl Fn(char) -> Option<CharGlyph>,
) -> Option<PlainChar> {
if (packed >> 32) & !((PAIRS | INKS_OUT) >> 32) == known | (PLAIN >> 32) {
self.inked = true;
return Some(PlainChar::of(packed, slot));
}
if packed >> 32 == known {
return None;
}
let read = read(ch);
let inks_out = read.as_ref().is_some_and(|read| read.inks_out);
let plain = read.and_then(|read| {
Some(PlainChar {
glyph: u16::try_from(read.glyph).ok()?,
advance: i16::try_from(read.advance).ok()?,
pairs: read.pairs,
slot,
})
});
let inks_out = plain.is_some() && inks_out;
self.inked |= inks_out;
if packed & FILLED != 0 {
self.forget(slot);
}
self.slots[usize::from(slot)] = known << 32
| plain.map_or(0, |plain| {
let pairs = if plain.pairs { PAIRS } else { 0 };
let inks_out = if inks_out { INKS_OUT } else { 0 };
PLAIN
| pairs
| inks_out
| u64::from(plain.glyph) << 16
| u64::from(plain.advance as u16)
});
plain
}
pub(crate) fn pair(
&mut self,
first: PlainChar,
second: PlainChar,
read: impl FnOnce() -> PairFit,
) -> PairFit {
let number = self.row_of[usize::from(first.slot)];
if number != 0 {
match self.rows[usize::from(number - 1)][usize::from(second.slot)] {
UNREAD => {}
JOINS => return PairFit::Joins,
UNKERNED => return PairFit::Kern(0),
kerned => {
let kern = self.kerns[usize::from(kerned - KERNED)];
return PairFit::Kern(i32::from(kern));
}
}
}
self.read_pair(first, second, read)
}
#[inline(never)]
fn read_pair(
&mut self,
first: PlainChar,
second: PlainChar,
read: impl FnOnce() -> PairFit,
) -> PairFit {
let number = &mut self.row_of[usize::from(first.slot)];
if *number == 0 {
self.rows.reserve_exact(1);
self.rows.push([UNREAD; SLOTS]);
*number = u8::try_from(self.rows.len()).unwrap_or(u8::MAX);
}
let row = usize::from(*number - 1);
let fit = read();
if first.slot == second.slot && first.glyph != second.glyph {
return fit;
}
let cell = &mut self.rows[row][usize::from(second.slot)];
*cell = match fit {
PairFit::Joins => JOINS,
PairFit::Kern(0) => UNKERNED,
PairFit::Kern(kern) => {
let Some(name) = kern_name(&mut self.kerns, kern) else {
return fit;
};
name
}
};
fit
}
fn forget(&mut self, slot: u8) {
if let Some(number) = self.row_of[usize::from(slot)].checked_sub(1) {
self.rows[usize::from(number)] = [UNREAD; SLOTS];
}
for row in &mut self.rows {
row[usize::from(slot)] = UNREAD;
}
}
}
fn kern_name(kerns: &mut Vec<i16>, kern: i32) -> Option<u8> {
let kern = i16::try_from(kern).ok()?;
let index = match kerns.iter().position(|&known| known == kern) {
Some(index) => index,
None if kerns.len() < MOST_KERNS => {
kerns.push(kern);
kerns.len() - 1
}
None => return None,
};
u8::try_from(index).ok().map(|index| index + KERNED)
}