diff options
Diffstat (limited to 'src/layout')
| -rw-r--r-- | src/layout/actions.rs | 6 | ||||
| -rw-r--r-- | src/layout/line.rs | 1 | ||||
| -rw-r--r-- | src/layout/mod.rs | 125 | ||||
| -rw-r--r-- | src/layout/model.rs | 82 | ||||
| -rw-r--r-- | src/layout/text.rs | 28 |
5 files changed, 131 insertions, 111 deletions
diff --git a/src/layout/actions.rs b/src/layout/actions.rs index 1bf5d684..710d92b4 100644 --- a/src/layout/actions.rs +++ b/src/layout/actions.rs @@ -1,10 +1,12 @@ //! Drawing and cofiguration actions composing layouts. +use std::io::{self, Write}; use std::fmt::{self, Display, Formatter}; use toddle::query::FontIndex; -use super::*; -use LayoutAction::*; +use crate::size::{Size, Size2D}; +use super::{Layout, Serialize}; +use self::LayoutAction::*; /// A layouting action. diff --git a/src/layout/line.rs b/src/layout/line.rs index f7777ae0..5e0839b1 100644 --- a/src/layout/line.rs +++ b/src/layout/line.rs @@ -1,3 +1,4 @@ +use super::stack::{StackLayouter, StackContext}; use super::*; diff --git a/src/layout/mod.rs b/src/layout/mod.rs index 209874a1..f8074524 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -3,40 +3,26 @@ use std::io::{self, Write}; use std::fmt::{self, Display, Formatter}; use smallvec::SmallVec; -use toddle::query::{SharedFontLoader, FontIndex}; +use toddle::query::FontIndex; -use crate::error::Errors; -use crate::syntax::{SyntaxModel, SpanVec}; use crate::size::{Size, Size2D, SizeBox}; -use crate::style::LayoutStyle; +use self::{GenericAxis::*, SpecificAxis::*, Direction::*, Alignment::*}; -mod actions; -mod model; -mod line; -mod stack; -mod text; +pub mod line; +pub mod stack; +pub mod text; -/// Common types for layouting. -pub mod prelude { - pub use super::*; - pub use GenericAxis::*; - pub use SpecificAxis::*; - pub use Direction::*; - pub use Alignment::*; -} +pub_use_mod!(actions); +pub_use_mod!(model); -/// Different kinds of layouters (fully re-exported). -pub mod layouters { - pub use super::model::ModelLayouter; - pub use super::line::{LineLayouter, LineContext}; - pub use super::stack::{StackLayouter, StackContext}; - pub use super::text::{layout_text, TextContext}; +pub mod prelude { + pub use super::{LayoutSpace, LayoutExpansion, LayoutAxes, LayoutAlignment}; + pub use super::GenericAxis::{self, *}; + pub use super::SpecificAxis::{self, *}; + pub use super::Direction::{self, *}; + pub use super::Alignment::{self, *}; } -pub use self::actions::{LayoutAction, LayoutActions}; -pub use self::layouters::*; -pub use self::prelude::*; - /// A collection of layouts. pub type MultiLayout = Vec<Layout>; @@ -67,49 +53,32 @@ impl Layout { } } -/// The general context for layouting. -#[derive(Debug, Clone)] -pub struct LayoutContext<'a, 'p> { - /// The font loader to retrieve fonts from when typesetting text - /// using [`layout_text`]. - pub loader: &'a SharedFontLoader<'p>, - /// The style for pages and text. - pub style: &'a LayoutStyle, - /// The base unpadded dimensions of this container (for relative sizing). - pub base: Size2D, - /// The spaces to layout in. - pub spaces: LayoutSpaces, - /// Whether to have repeated spaces or to use only the first and only once. - pub repeat: bool, - /// The initial axes along which content is laid out. - pub axes: LayoutAxes, - /// The alignment of the finished layout. - pub alignment: LayoutAlignment, - /// Whether the layout that is to be created will be nested in a parent - /// container. - pub nested: bool, - /// Whether to debug render a box around the layout. - pub debug: bool, -} - -pub struct Layouted<T> { - pub output: T, - pub errors: Errors, +/// 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<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, +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(()) } } -pub async fn layout(model: &SyntaxModel, ctx: LayoutContext<'_, '_>) -> Layouted<MultiLayout> { - let mut layouter = ModelLayouter::new(ctx); - layouter.layout_syntax_model(model).await; - layouter.finish() +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(()) + } } /// A possibly stack-allocated vector of layout spaces. @@ -405,31 +374,3 @@ 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 13d38083..2e61b453 100644 --- a/src/layout/model.rs +++ b/src/layout/model.rs @@ -1,9 +1,15 @@ +use std::future::Future; +use std::pin::Pin; use smallvec::smallvec; +use toddle::query::SharedFontLoader; use crate::error::Errors; -use crate::func::Command; -use crate::syntax::{Model, DynFuture, SyntaxModel, Node}; -use crate::syntax::{SpanVec, Spanned, Span, offset_spans}; +use crate::style::{LayoutStyle, PageStyle, TextStyle}; +use crate::size::{Size, Size2D}; +use crate::syntax::{Model, SyntaxModel, Node}; +use crate::syntax::span::{Spanned, Span, offset_spans}; +use super::line::{LineLayouter, LineContext}; +use super::text::{layout_text, TextContext}; use super::*; @@ -15,6 +21,76 @@ pub struct ModelLayouter<'a, 'p> { errors: Errors, } +/// The general context for layouting. +#[derive(Debug, Clone)] +pub struct LayoutContext<'a, 'p> { + /// The font loader to retrieve fonts from when typesetting text + /// using [`layout_text`]. + pub loader: &'a SharedFontLoader<'p>, + /// The style for pages and text. + pub style: &'a LayoutStyle, + /// The base unpadded dimensions of this container (for relative sizing). + pub base: Size2D, + /// The spaces to layout in. + pub spaces: LayoutSpaces, + /// Whether to have repeated spaces or to use only the first and only once. + pub repeat: bool, + /// The initial axes along which content is laid out. + pub axes: LayoutAxes, + /// The alignment of the finished layout. + pub alignment: LayoutAlignment, + /// Whether the layout that is to be created will be nested in a parent + /// container. + pub nested: bool, + /// Whether to debug render a box around the layout. + pub debug: bool, +} + +pub struct Layouted<T> { + pub output: T, + pub errors: Errors, +} + +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 sequence of layouting commands. +pub type Commands<'a> = Vec<Command<'a>>; + +/// Layouting commands from functions to the typesetting engine. +#[derive(Debug)] +pub enum Command<'a> { + LayoutSyntaxModel(&'a SyntaxModel), + + Add(Layout), + AddMultiple(MultiLayout), + AddSpacing(Size, SpacingKind, GenericAxis), + + FinishLine, + FinishSpace, + BreakParagraph, + BreakPage, + + SetTextStyle(TextStyle), + SetPageStyle(PageStyle), + SetAlignment(LayoutAlignment), + SetAxes(LayoutAxes), +} + +pub async fn layout(model: &SyntaxModel, ctx: LayoutContext<'_, '_>) -> Layouted<MultiLayout> { + let mut layouter = ModelLayouter::new(ctx); + layouter.layout_syntax_model(model).await; + layouter.finish() +} + +pub type DynFuture<'a, T> = Pin<Box<dyn Future<Output=T> + 'a>>; + impl<'a, 'p> ModelLayouter<'a, 'p> { /// Create a new syntax tree layouter. pub fn new(ctx: LayoutContext<'a, 'p>) -> ModelLayouter<'a, 'p> { diff --git a/src/layout/text.rs b/src/layout/text.rs index 16ae93da..eb598e2f 100644 --- a/src/layout/text.rs +++ b/src/layout/text.rs @@ -6,12 +6,14 @@ use crate::style::TextStyle; use super::*; -/// Layouts text into a box. -/// -/// There is no complex layout involved. The text is simply laid out left- -/// to-right using the correct font for each character. -pub async fn layout_text(text: &str, ctx: TextContext<'_, '_>) -> Layout { - TextLayouter::new(text, ctx).layout().await +/// Layouts text into boxes. +struct TextLayouter<'a, 'p> { + ctx: TextContext<'a, 'p>, + text: &'a str, + actions: LayoutActions, + buffer: String, + active_font: FontIndex, + width: Size, } /// The context for text layouting. @@ -25,14 +27,12 @@ pub struct TextContext<'a, 'p> { pub alignment: LayoutAlignment, } -/// Layouts text into boxes. -struct TextLayouter<'a, 'p> { - ctx: TextContext<'a, 'p>, - text: &'a str, - actions: LayoutActions, - buffer: String, - active_font: FontIndex, - width: Size, +/// Layouts text into a box. +/// +/// There is no complex layout involved. The text is simply laid out left- +/// to-right using the correct font for each character. +pub async fn layout_text(text: &str, ctx: TextContext<'_, '_>) -> Layout { + TextLayouter::new(text, ctx).layout().await } impl<'a, 'p> TextLayouter<'a, 'p> { |
