use boxworks::ds;
pub struct Font {
pub default_space: core::Glue,
}
#[derive(Default)]
pub struct TextPreprocessorImpl {
fonts: Vec<Font>,
current_font: u32,
}
impl boxworks::TextPreprocessor for TextPreprocessorImpl {
fn add_text(&mut self, text: &str, list: &mut Vec<ds::Horizontal>) {
for c in text.chars() {
list.push(ds::Horizontal::Char(ds::Char {
char: c,
font: self.current_font,
}));
}
}
fn add_space(&mut self, list: &mut Vec<ds::Horizontal>) {
list.push(ds::Horizontal::Glue(
self.fonts[self.current_font as usize].default_space.into(),
));
}
}
impl TextPreprocessorImpl {
pub fn register_font(&mut self, id: u32, font: Font) {
assert_eq!(id as usize, self.fonts.len());
self.fonts.push(font);
}
pub fn activate_font(&mut self, id: u32) {
self.current_font = id;
}
}
#[cfg(test)]
mod tests {
use super::*;
use boxworks::TextPreprocessor;
use boxworks_lang as bwl;
macro_rules! preprocessor_tests {
( $( ( $name: ident, $input: expr, $want: expr, ), )+ ) => {
$(
#[test]
fn $name() {
let input = $input;
let want = $want;
run_preprocessor_test(input, want)
}
)+
};
}
preprocessor_tests!(
(
cmr10_basic,
"second",
r#"
text("second", font=0)
"#,
),
(
cmr10_basic_with_space,
"sec ond",
r#"
text("sec", font=0)
glue(3.33333pt, 1.66666pt, 1.11111pt)
text("ond", font=0)
"#,
),
);
fn run_preprocessor_test(input: &str, want: &str) {
let want = bwl::parse_horizontal_list(want).unwrap();
let mut tp: TextPreprocessorImpl = Default::default();
tp.register_font(
0,
Font {
default_space: core::Glue {
width: core::Scaled::ONE * 10 / 3,
stretch: core::Scaled::ONE * 5 / 3,
stretch_order: core::GlueOrder::Normal,
shrink: core::Scaled::ONE * 10 / 9 + core::Scaled(1),
shrink_order: core::GlueOrder::Normal,
},
},
);
tp.activate_font(0);
let mut got = vec![];
for word in input.split_inclusive(' ') {
tp.add_text(word.trim_matches(' '), &mut got);
if word.ends_with(" ") {
tp.add_space(&mut got);
}
}
assert_eq!(got, want);
}
}