summaryrefslogtreecommitdiff
path: root/src/layout
diff options
context:
space:
mode:
Diffstat (limited to 'src/layout')
-rw-r--r--src/layout/mod.rs94
-rw-r--r--src/layout/model.rs113
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,
- }
- }
}