diff options
| author | Laurenz <laurmaedje@gmail.com> | 2019-03-30 16:58:45 +0100 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2019-03-30 16:58:45 +0100 |
| commit | db96ecae94a7c06d04528e8d4461ebca86d2d249 (patch) | |
| tree | 9f1bdbaa65b424ef522dadda02bfa4826acfc836 /src/engine.rs | |
| parent | f683bba4004cc07f9ac91d5d99a6bab76f335dba (diff) | |
Move some types into better places 🧱
Diffstat (limited to 'src/engine.rs')
| -rw-r--r-- | src/engine.rs | 162 |
1 files changed, 0 insertions, 162 deletions
diff --git a/src/engine.rs b/src/engine.rs deleted file mode 100644 index ff89d674..00000000 --- a/src/engine.rs +++ /dev/null @@ -1,162 +0,0 @@ -//! Core typesetting engine. - -use crate::syntax::{SyntaxTree, Node}; -use crate::doc::{Document, Size, Page, Text, TextCommand}; -use crate::font::{Font, FontConfig, FontError}; -use crate::Context; - - -/// The core typesetting engine, transforming an abstract syntax tree into a document. -pub(crate) struct Engine<'a> { - // Immutable - tree: &'a SyntaxTree<'a>, - ctx: &'a Context<'a>, - - // Mutable - fonts: Vec<Font>, - active_font: usize, - text_commands: Vec<TextCommand>, - current_line: String, - current_width: Size, -} - -impl<'a> Engine<'a> { - /// Create a new generator from a syntax tree. - pub fn new(tree: &'a SyntaxTree<'a>, context: &'a Context<'a>) -> Engine<'a> { - Engine { - tree, - ctx: context, - fonts: Vec::new(), - active_font: 0, - text_commands: Vec::new(), - current_line: String::new(), - current_width: Size::zero(), - } - } - - /// Generate the abstract document. - pub fn typeset(mut self) -> TypeResult<Document> { - // Load font defined by style - let mut font = None; - let config = FontConfig::new(self.ctx.style.font_families.clone()); - for provider in &self.ctx.font_providers { - if let Some(mut source) = provider.provide(&config) { - let mut program = Vec::new(); - source.read_to_end(&mut program)?; - font = Some(Font::new(program)?); - break; - } - } - - let font = match font { - Some(font) => font, - None => return Err(TypesetError::MissingFont), - }; - - self.fonts.push(font); - self.active_font = 0; - - // Move cursor to top-left position - self.text_commands.push(TextCommand::Move( - self.ctx.style.margin_left, - self.ctx.style.height - self.ctx.style.margin_top - )); - - // Set the current font - self.text_commands.push(TextCommand::SetFont(0, self.ctx.style.font_size)); - - // Iterate through the documents nodes. - for node in &self.tree.nodes { - match node { - Node::Word(word) => self.write_word(word), - - Node::Space => self.write_space(), - Node::Newline => (), - - Node::ToggleItalics | Node::ToggleBold | Node::ToggleMath => unimplemented!(), - Node::Func(_) => unimplemented!(), - } - } - - // Create a page from the contents. - let page = Page { - width: self.ctx.style.width, - height: self.ctx.style.height, - text: vec![Text { - commands: self.text_commands, - }], - }; - - Ok(Document { - pages: vec![page], - fonts: self.fonts, - }) - } - - fn write_word(&mut self, word: &str) { - let font = &self.fonts[self.active_font]; - - let width = self.width(word); - if self.would_overflow(width) { - let vertical_move = - self.ctx.style.font_size - * self.ctx.style.line_spacing - * font.metrics.ascender; - self.text_commands.push(TextCommand::Move(Size::zero(), vertical_move)); - - self.current_line.clear(); - self.current_width = Size::zero(); - } - - self.text_commands.push(TextCommand::Text(word.to_owned())); - self.current_line.push_str(word); - self.current_width += width; - } - - fn write_space(&mut self) { - let space_width = self.width(" "); - - if !self.would_overflow(space_width) && !self.current_line.is_empty() { - self.text_commands.push(TextCommand::Text(" ".to_owned())); - self.current_line.push_str(" "); - self.current_width += space_width; - } - } - - fn width(&self, word: &str) -> Size { - let font = &self.fonts[self.active_font]; - word.chars() - .map(|c| font.widths[font.map(c) as usize] * self.ctx.style.font_size) - .sum() - } - - fn would_overflow(&self, width: Size) -> bool { - let max_width = self.ctx.style.width - - self.ctx.style.margin_left - - self.ctx.style.margin_right; - - self.current_width + width > max_width - } -} - -/// The error type for typesetting. -pub enum TypesetError { - /// There was no suitable font. - MissingFont, - /// An error occured while gathering font data. - Font(FontError), -} - -error_type! { - err: TypesetError, - res: TypeResult, - show: f => match err { - TypesetError::MissingFont => write!(f, "missing font"), - TypesetError::Font(err) => write!(f, "font error: {}", err), - }, - source: match err { - TypesetError::Font(err) => Some(err), - _ => None, - }, - from: (std::io::Error, TypesetError::Font(FontError::Io(err))), - from: (FontError, TypesetError::Font(err)), -} |
