diff options
| author | Laurenz <laurmaedje@gmail.com> | 2020-01-06 12:41:42 +0100 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2020-01-06 12:41:42 +0100 |
| commit | 2ee5810fecb96a8d4e0d078faecc8c91096d6881 (patch) | |
| tree | 702c746a3021f5034e1b31cd07e8fadba0e4dd7a /src/layout/tree.rs | |
| parent | bd384a2a633e21cd7deff7ed2a29a9c03a63a20e (diff) | |
Asyncify font loading 🪐
Diffstat (limited to 'src/layout/tree.rs')
| -rw-r--r-- | src/layout/tree.rs | 179 |
1 files changed, 91 insertions, 88 deletions
diff --git a/src/layout/tree.rs b/src/layout/tree.rs index 4ed3d82a..f645a35d 100644 --- a/src/layout/tree.rs +++ b/src/layout/tree.rs @@ -1,3 +1,5 @@ +use std::pin::Pin; +use std::future::Future; use smallvec::smallvec; use crate::func::Command; @@ -5,10 +7,13 @@ use crate::syntax::{SyntaxTree, Node, FuncCall}; use crate::style::TextStyle; use super::*; + +type RecursiveResult<'a, T> = Pin<Box<dyn Future<Output=LayoutResult<T>> + 'a>>; + /// Layout a syntax tree into a multibox. -pub fn layout(tree: &SyntaxTree, ctx: LayoutContext) -> LayoutResult<MultiLayout> { +pub async fn layout(tree: &SyntaxTree, ctx: LayoutContext<'_, '_>) -> LayoutResult<MultiLayout> { let mut layouter = TreeLayouter::new(ctx); - layouter.layout(tree)?; + layouter.layout(tree).await?; layouter.finish() } @@ -36,42 +41,44 @@ impl<'a, 'p> TreeLayouter<'a, 'p> { } } - fn layout(&mut self, tree: &SyntaxTree) -> LayoutResult<()> { - for node in &tree.nodes { - match &node.v { - Node::Text(text) => self.layout_text(text)?, + fn layout<'b>(&'b mut self, tree: &'b SyntaxTree) -> RecursiveResult<'b, ()> { + Box::pin(async move { + for node in &tree.nodes { + match &node.v { + Node::Text(text) => self.layout_text(text).await?, - Node::Space => self.layout_space(), - Node::Newline => self.layout_paragraph()?, + Node::Space => self.layout_space(), + Node::Newline => self.layout_paragraph()?, - Node::ToggleItalics => self.style.text.variant.style.toggle(), - Node::ToggleBolder => { - self.style.text.variant.weight.0 += 300 * - if self.style.text.bolder { -1 } else { 1 }; - self.style.text.bolder = !self.style.text.bolder; - } - Node::ToggleMonospace => { - let list = &mut self.style.text.fallback.list; - match list.get(0).map(|s| s.as_str()) { - Some("monospace") => { list.remove(0); }, - _ => list.insert(0, "monospace".to_string()), + Node::ToggleItalics => self.style.text.variant.style.toggle(), + Node::ToggleBolder => { + self.style.text.variant.weight.0 += 300 * + if self.style.text.bolder { -1 } else { 1 }; + self.style.text.bolder = !self.style.text.bolder; + } + Node::ToggleMonospace => { + let list = &mut self.style.text.fallback.list; + match list.get(0).map(|s| s.as_str()) { + Some("monospace") => { list.remove(0); }, + _ => list.insert(0, "monospace".to_string()), + } } - } - Node::Func(func) => self.layout_func(func)?, + Node::Func(func) => self.layout_func(func).await?, + } } - } - Ok(()) + Ok(()) + }) } - fn layout_text(&mut self, text: &str) -> LayoutResult<()> { + async fn layout_text(&mut self, text: &str) -> LayoutResult<()> { let layout = layout_text(text, TextContext { loader: &self.ctx.loader, style: &self.style.text, axes: self.ctx.axes, alignment: self.ctx.alignment, - })?; + }).await?; self.layouter.add(layout) } @@ -84,75 +91,71 @@ impl<'a, 'p> TreeLayouter<'a, 'p> { self.layouter.add_secondary_spacing(self.style.text.paragraph_spacing(), PARAGRAPH_KIND) } - fn layout_func(&mut self, func: &FuncCall) -> LayoutResult<()> { - let commands = func.0.layout(LayoutContext { - style: &self.style, - spaces: self.layouter.remaining(), - nested: true, - debug: false, - .. self.ctx - })?; - - for command in commands { - self.execute(command)?; - } - - Ok(()) - } - - fn execute(&mut self, command: Command) -> LayoutResult<()> { - use Command::*; - - match command { - LayoutTree(tree) => self.layout(tree)?, - - Add(layout) => self.layouter.add(layout)?, - AddMultiple(layouts) => self.layouter.add_multiple(layouts)?, - SpacingFunc(space, kind, axis) => match axis { - Primary => self.layouter.add_primary_spacing(space, kind), - Secondary => self.layouter.add_secondary_spacing(space, kind)?, - } - - FinishLine => self.layouter.finish_line()?, - FinishSpace => self.layouter.finish_space(true)?, - BreakParagraph => self.layout_paragraph()?, - BreakPage => { - if self.ctx.nested { - error!("page break cannot be issued from nested context"); - } - - self.layouter.finish_space(true)? - } + fn layout_func<'b>(&'b mut self, func: &'b FuncCall) -> RecursiveResult<'b, ()> { + Box::pin(async move { + let commands = func.0.layout(LayoutContext { + style: &self.style, + spaces: self.layouter.remaining(), + nested: true, + debug: false, + .. self.ctx + }).await?; + + for command in commands { + use Command::*; + + match command { + LayoutTree(tree) => self.layout(tree).await?, + + Add(layout) => self.layouter.add(layout)?, + AddMultiple(layouts) => self.layouter.add_multiple(layouts)?, + SpacingFunc(space, kind, axis) => match axis { + Primary => self.layouter.add_primary_spacing(space, kind), + Secondary => self.layouter.add_secondary_spacing(space, kind)?, + } - SetTextStyle(style) => { - self.layouter.set_line_spacing(style.line_spacing()); - self.style.text = style; - } - SetPageStyle(style) => { - if self.ctx.nested { - error!("page style cannot be altered in nested context"); - } + FinishLine => self.layouter.finish_line()?, + FinishSpace => self.layouter.finish_space(true)?, + BreakParagraph => self.layout_paragraph()?, + BreakPage => { + if self.ctx.nested { + error!("page break cannot be issued from nested context"); + } - self.style.page = style; + self.layouter.finish_space(true)? + } - let margins = style.margins(); - self.ctx.base = style.dimensions.unpadded(margins); - self.layouter.set_spaces(smallvec![ - LayoutSpace { - dimensions: style.dimensions, - padding: margins, - expansion: LayoutExpansion::new(true, true), + SetTextStyle(style) => { + self.layouter.set_line_spacing(style.line_spacing()); + self.style.text = style; } - ], true); - } - SetAlignment(alignment) => self.ctx.alignment = alignment, - SetAxes(axes) => { - self.layouter.set_axes(axes); - self.ctx.axes = axes; + SetPageStyle(style) => { + if self.ctx.nested { + error!("page style cannot be altered in nested context"); + } + + self.style.page = style; + + let margins = style.margins(); + self.ctx.base = style.dimensions.unpadded(margins); + self.layouter.set_spaces(smallvec![ + LayoutSpace { + dimensions: style.dimensions, + padding: margins, + expansion: LayoutExpansion::new(true, true), + } + ], true); + } + SetAlignment(alignment) => self.ctx.alignment = alignment, + SetAxes(axes) => { + self.layouter.set_axes(axes); + self.ctx.axes = axes; + } + } } - } - Ok(()) + Ok(()) + }) } fn finish(self) -> LayoutResult<MultiLayout> { |
