boxworks/
lib.rs

1//! # Boxworks
2//!
3//! Boxworks is an in-progress implementation of the typesetting engine inside TeX.
4//! It is independent of the TeX language.
5//! One of the main goals of Boxworks is to support creating new typesetting
6//! languages that use this engine to perform the actual typesetting.
7
8pub mod ds;
9pub mod lang;
10pub mod tex;
11
12pub trait TextPreprocessor {
13    fn new_paragraph(&mut self);
14
15    fn add_word(&mut self, word: &str, list: &mut Vec<ds::Horizontal>);
16
17    fn add_space(&mut self, list: &mut Vec<ds::Horizontal>);
18
19    fn add_text(&mut self, text: &str, list: &mut Vec<ds::Horizontal>) {
20        self.new_paragraph();
21        let mut pending_space = text.chars().next().unwrap_or(' ').is_ascii_whitespace();
22        for word in text.split_ascii_whitespace() {
23            if pending_space {
24                self.add_space(list);
25            }
26            let word = word.trim_matches(' ');
27            self.add_word(word.trim_matches(' '), list);
28            pending_space = true;
29        }
30    }
31}
32
33#[derive(Default, Debug)]
34pub struct SimpleTextPreprocessor {
35    font: u32,
36}
37
38impl TextPreprocessor for SimpleTextPreprocessor {
39    fn new_paragraph(&mut self) {}
40
41    fn add_word(&mut self, word: &str, list: &mut Vec<ds::Horizontal>) {
42        for char in word.chars() {
43            list.push(
44                ds::Char {
45                    char,
46                    font: self.font,
47                }
48                .into(),
49            );
50        }
51    }
52    fn add_space(&mut self, list: &mut Vec<ds::Horizontal>) {
53        list.push(
54            ds::Glue {
55                kind: ds::GlueKind::Normal,
56                value: common::Glue {
57                    width: common::Scaled::ONE * 10,
58                    stretch: common::Scaled::ONE * 4,
59                    shrink: common::Scaled::ONE * 4,
60                    ..Default::default()
61                },
62            }
63            .into(),
64        );
65    }
66}
67
68pub trait FontRepo {
69    fn width(&self, c: char, font: u32) -> Option<common::Scaled>;
70    fn height(&self, c: char, font: u32) -> Option<common::Scaled>;
71    fn depth(&self, c: char, font: u32) -> Option<common::Scaled>;
72
73    fn width_height_depth(&self, c: char, font: u32) -> Option<[common::Scaled; 3]> {
74        Some([
75            self.width(c, font)?,
76            self.height(c, font).unwrap_or(common::Scaled::ZERO),
77            self.depth(c, font).unwrap_or(common::Scaled::ZERO),
78        ])
79    }
80}
81
82pub trait LineBreaker {
83    fn break_line<F: FontRepo>(
84        self,
85        font_repo: &F,
86        v_list: &mut Vec<ds::Vertical>,
87        h_list: &mut Vec<ds::Horizontal>,
88    );
89}
90
91pub trait Hyphenator {
92    fn hyphenate(&self, list: &mut Vec<ds::Horizontal>);
93}