use super::span_style::*;
use swash::text::{cluster::CharInfo, Script};
use swash::Setting;
#[derive(Copy, Debug, Clone)]
pub struct FragmentData {
pub span: usize,
pub break_shaping: bool,
pub start: usize,
pub end: usize,
pub vars: FontSettingKey,
}
#[derive(Copy, Debug, Clone)]
pub struct ItemData {
pub script: Script,
pub level: u8,
pub start: usize,
pub end: usize,
pub vars: FontSettingKey,
}
#[derive(Default)]
pub struct BuilderLineText {
pub content: Vec<char>,
pub frags: Vec<u32>,
pub spans: Vec<usize>,
pub info: Vec<CharInfo>,
pub offsets: Vec<u32>,
}
#[derive(Default)]
pub struct BuilderLine {
pub text: BuilderLineText,
pub fragments: Vec<FragmentData>,
pub items: Vec<ItemData>,
pub styles: Vec<FragmentStyle>,
pub hash: Option<u64>,
}
#[derive(Default)]
pub struct BuilderState {
pub lines: Vec<BuilderLine>,
pub vars: FontSettingCache<f32>,
pub scale: f32,
}
impl BuilderState {
pub fn new() -> Self {
let mut lines = vec![BuilderLine::default()];
lines[0].styles.push(FragmentStyle::default());
Self {
lines,
..BuilderState::default()
}
}
#[inline]
pub fn new_line(&mut self) {
self.lines.push(BuilderLine::default());
let last = self.lines.len() - 1;
self.lines[last]
.styles
.push(FragmentStyle::scaled_default(self.scale));
}
#[inline]
pub fn current_line(&self) -> usize {
let size = self.lines.len();
if size == 0 {
0
} else {
size - 1
}
}
#[inline]
pub fn clear(&mut self) {
self.lines.clear();
self.vars.clear();
}
#[inline]
pub fn begin(&mut self) {
self.lines.push(BuilderLine::default());
}
}
pub type FontSettingKey = u32;
#[derive(Default)]
pub struct FontSettingCache<T: Copy + PartialOrd + PartialEq> {
settings: Vec<Setting<T>>,
lists: Vec<FontSettingList>,
tmp: Vec<Setting<T>>,
}
impl<T: Copy + PartialOrd + PartialEq> FontSettingCache<T> {
pub fn get(&self, key: u32) -> &[Setting<T>] {
if key == !0 {
&[]
} else {
self.lists
.get(key as usize)
.map(|list| list.get(&self.settings))
.unwrap_or(&[])
}
}
pub fn clear(&mut self) {
self.settings.clear();
self.lists.clear();
self.tmp.clear();
}
}
pub const EMPTY_FONT_SETTINGS: FontSettingKey = !0;
#[derive(Copy, Clone)]
struct FontSettingList {
pub start: u32,
pub end: u32,
}
impl FontSettingList {
pub fn get<T>(self, elements: &[T]) -> &[T] {
elements
.get(self.start as usize..self.end as usize)
.unwrap_or(&[])
}
}