diff options
Diffstat (limited to 'src/layout')
| -rw-r--r-- | src/layout/mod.rs | 94 | ||||
| -rw-r--r-- | src/layout/model.rs | 113 |
2 files changed, 99 insertions, 108 deletions
diff --git a/src/layout/mod.rs b/src/layout/mod.rs index 75d34409..1cc16a26 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -5,7 +5,7 @@ use smallvec::SmallVec; use toddle::query::{SharedFontLoader, FontIndex}; use crate::error::Error; -use crate::syntax::SpanVec; +use crate::syntax::{SyntaxModel, SpanVec}; use crate::size::{Size, Size2D, SizeBox}; use crate::style::LayoutStyle; @@ -26,7 +26,7 @@ pub mod prelude { /// Different kinds of layouters (fully re-exported). pub mod layouters { - pub use super::model::layout; + pub use super::model::ModelLayouter; pub use super::line::{LineLayouter, LineContext}; pub use super::stack::{StackLayouter, StackContext}; pub use super::text::{layout_text, TextContext}; @@ -37,20 +37,6 @@ pub use self::layouters::*; pub use self::prelude::*; -pub struct Layouted<T> { - pub output: T, - pub errors: SpanVec<Error>, -} - -impl<T> Layouted<T> { - pub fn map<F, U>(self, f: F) -> Layouted<U> where F: FnOnce(T) -> U { - Layouted { - output: f(self.output), - errors: self.errors, - } - } -} - /// A collection of layouts. pub type MultiLayout = Vec<Layout>; @@ -80,34 +66,6 @@ impl Layout { } } -/// Layout components that can be serialized. -pub trait Serialize { - /// Serialize the data structure into an output writable. - fn serialize<W: Write>(&self, f: &mut W) -> io::Result<()>; -} - -impl Serialize for Layout { - fn serialize<W: Write>(&self, f: &mut W) -> io::Result<()> { - writeln!(f, "{:.4} {:.4}", self.dimensions.x.to_pt(), self.dimensions.y.to_pt())?; - writeln!(f, "{}", self.actions.len())?; - for action in &self.actions { - action.serialize(f)?; - writeln!(f)?; - } - Ok(()) - } -} - -impl Serialize for MultiLayout { - fn serialize<W: Write>(&self, f: &mut W) -> io::Result<()> { - writeln!(f, "{}", self.len())?; - for layout in self { - layout.serialize(f)?; - } - Ok(()) - } -} - /// The general context for layouting. #[derive(Debug, Clone)] pub struct LayoutContext<'a, 'p> { @@ -133,6 +91,26 @@ pub struct LayoutContext<'a, 'p> { pub debug: bool, } +pub struct Layouted<T> { + pub output: T, + pub errors: SpanVec<Error>, +} + +impl<T> Layouted<T> { + pub fn map<F, U>(self, f: F) -> Layouted<U> where F: FnOnce(T) -> U { + Layouted { + output: f(self.output), + errors: self.errors, + } + } +} + +pub async fn layout(model: &SyntaxModel, ctx: LayoutContext<'_, '_>) -> Layouted<MultiLayout> { + let mut layouter = ModelLayouter::new(ctx); + layouter.layout_syntax_model(model).await; + layouter.finish() +} + /// A possibly stack-allocated vector of layout spaces. pub type LayoutSpaces = SmallVec<[LayoutSpace; 2]>; @@ -397,3 +375,31 @@ impl LastSpacing { } } } + +/// Layout components that can be serialized. +pub trait Serialize { + /// Serialize the data structure into an output writable. + fn serialize<W: Write>(&self, f: &mut W) -> io::Result<()>; +} + +impl Serialize for Layout { + fn serialize<W: Write>(&self, f: &mut W) -> io::Result<()> { + writeln!(f, "{:.4} {:.4}", self.dimensions.x.to_pt(), self.dimensions.y.to_pt())?; + writeln!(f, "{}", self.actions.len())?; + for action in &self.actions { + action.serialize(f)?; + writeln!(f)?; + } + Ok(()) + } +} + +impl Serialize for MultiLayout { + fn serialize<W: Write>(&self, f: &mut W) -> io::Result<()> { + writeln!(f, "{}", self.len())?; + for layout in self { + layout.serialize(f)?; + } + Ok(()) + } +} diff --git a/src/layout/model.rs b/src/layout/model.rs index bcec5ceb..73492dd9 100644 --- a/src/layout/model.rs +++ b/src/layout/model.rs @@ -1,5 +1,3 @@ -use std::pin::Pin; -use std::future::Future; use smallvec::smallvec; use crate::error::Error; @@ -9,17 +7,8 @@ use crate::syntax::{SpanVec, Spanned, Span, offset_spans}; use super::*; -pub async fn layout( - model: &SyntaxModel, - ctx: LayoutContext<'_, '_> -) -> Layouted<MultiLayout> { - let mut layouter = ModelLayouter::new(ctx); - layouter.layout_syntax_model(model).await; - layouter.finish() -} - #[derive(Debug, Clone)] -struct ModelLayouter<'a, 'p> { +pub struct ModelLayouter<'a, 'p> { ctx: LayoutContext<'a, 'p>, layouter: LineLayouter, style: LayoutStyle, @@ -28,7 +17,7 @@ struct ModelLayouter<'a, 'p> { impl<'a, 'p> ModelLayouter<'a, 'p> { /// Create a new syntax tree layouter. - fn new(ctx: LayoutContext<'a, 'p>) -> ModelLayouter<'a, 'p> { + pub fn new(ctx: LayoutContext<'a, 'p>) -> ModelLayouter<'a, 'p> { ModelLayouter { layouter: LineLayouter::new(LineContext { spaces: ctx.spaces.clone(), @@ -44,7 +33,7 @@ impl<'a, 'p> ModelLayouter<'a, 'p> { } } - fn layout<'r>( + pub fn layout<'r>( &'r mut self, model: Spanned<&'r dyn Model> ) -> DynFuture<'r, ()> { Box::pin(async move { @@ -60,14 +49,54 @@ impl<'a, 'p> ModelLayouter<'a, 'p> { self.errors.extend(offset_spans(layouted.errors, model.span.start)); for command in commands { - self.execute_command(command, model.span); + self.execute_command(command, model.span).await; } }) } + pub fn layout_syntax_model<'r>( + &'r mut self, + model: &'r SyntaxModel + ) -> DynFuture<'r, ()> { Box::pin(async move { + use Node::*; + + for node in &model.nodes { + match &node.v { + Space => self.layout_space(), + Newline => self.layout_paragraph(), + Text(text) => self.layout_text(text).await, + + ToggleItalic => self.style.text.variant.style.toggle(), + ToggleBolder => { + let fac = if self.style.text.bolder { -1 } else { 1 }; + self.style.text.variant.weight.0 += 300 * fac; + self.style.text.bolder = !self.style.text.bolder; + } + 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::Model(model) => { + self.layout(Spanned::new(model.as_ref(), node.span)).await; + } + } + } + }) } + + pub fn finish(self) -> Layouted<MultiLayout> { + Layouted { + output: self.layouter.finish(), + errors: self.errors, + } + } + fn execute_command<'r>( &'r mut self, command: Command<'r>, - model_span: Span, + span: Span, ) -> DynFuture<'r, ()> { Box::pin(async move { use Command::*; @@ -86,10 +115,8 @@ impl<'a, 'p> ModelLayouter<'a, 'p> { BreakParagraph => self.layout_paragraph(), BreakPage => { if self.ctx.nested { - self.errors.push(Spanned::new( - Error::new( "page break cannot be issued from nested context"), - model_span, - )); + self.errors.push(err!(span; + "page break cannot be issued from nested context")); } else { self.layouter.finish_space(true) } @@ -101,10 +128,8 @@ impl<'a, 'p> ModelLayouter<'a, 'p> { } SetPageStyle(style) => { if self.ctx.nested { - self.errors.push(Spanned::new( - Error::new("page style cannot be changed from nested context"), - model_span, - )); + self.errors.push(err!(span; + "page style cannot be changed from nested context")); } else { self.style.page = style; @@ -128,39 +153,6 @@ impl<'a, 'p> ModelLayouter<'a, 'p> { } }) } - fn layout_syntax_model<'r>( - &'r mut self, - model: &'r SyntaxModel - ) -> DynFuture<'r, ()> { Box::pin(async move { - use Node::*; - - for node in &model.nodes { - match &node.v { - Space => self.layout_space(), - Newline => self.layout_paragraph(), - Text(text) => self.layout_text(text).await, - - ToggleItalic => self.style.text.variant.style.toggle(), - ToggleBolder => { - let fac = if self.style.text.bolder { -1 } else { 1 }; - self.style.text.variant.weight.0 += 300 * fac; - self.style.text.bolder = !self.style.text.bolder; - } - 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::Model(model) => { - self.layout(Spanned::new(model.as_ref(), node.span)).await; - } - } - } - }) } - async fn layout_text(&mut self, text: &str) { self.layouter.add(layout_text(text, TextContext { loader: &self.ctx.loader, @@ -183,11 +175,4 @@ impl<'a, 'p> ModelLayouter<'a, 'p> { SpacingKind::PARAGRAPH, ); } - - fn finish(self) -> Layouted<MultiLayout> { - Layouted { - output: self.layouter.finish(), - errors: self.errors, - } - } } |
