diff options
| author | Laurenz <laurmaedje@gmail.com> | 2019-06-17 10:08:16 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2019-06-17 10:08:16 +0200 |
| commit | b53ad6b1ec8b2fd05566a83c9b895f265e61d281 (patch) | |
| tree | 1c6d590ead7180fbef12915cfcd04418c9ea7902 /src/layout/mod.rs | |
| parent | 236ebab23a106ca817de527ce6b6440d3b66c150 (diff) | |
Introduce flex layouting 🎈
Diffstat (limited to 'src/layout/mod.rs')
| -rw-r--r-- | src/layout/mod.rs | 174 |
1 files changed, 63 insertions, 111 deletions
diff --git a/src/layout/mod.rs b/src/layout/mod.rs index 1c1f743e..8b0c3004 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -1,74 +1,35 @@ //! The layouting engine. -use crate::doc::{Document, Page, TextAction}; -use crate::font::{Font, FontLoader, FontFamily, FontError}; +use crate::font::{FontLoader, FontError}; +use crate::size::{Size2D, SizeBox}; use crate::syntax::{SyntaxTree, Node}; +use crate::style::TextStyle; -mod size; -mod text; mod boxed; +mod flex; -pub use size::{Size, Position, Extent}; -pub use text::TextLayouter; -pub use boxed::BoxLayouter; +pub use flex::{FlexLayout, FlexLayouter}; +pub use boxed::{BoxLayout, BoxLayouter}; -/// Layout a syntax tree in a given context. -pub fn layout(tree: &SyntaxTree, ctx: &LayoutContext) -> LayoutResult<Layout> { - let mut layouter = TextLayouter::new(ctx); - - let mut italic = false; - let mut bold = false; - - for node in &tree.nodes { - match node { - Node::Text(text) => layouter.add_text(text)?, - Node::Space => layouter.add_space()?, - Node::Newline => layouter.add_paragraph()?, - - Node::ToggleItalics => { - italic = !italic; - layouter.set_italic(italic); - }, - Node::ToggleBold => { - bold = !bold; - layouter.set_bold(bold); - } +/// Types that layout components and can be finished into some kind of layout. +pub trait Layouter { + type Layout; - Node::Func(_) => unimplemented!(), - } - } + /// Finish the layouting and create the layout from this. + fn finish(self) -> Self::Layout; - layouter.finish() + /// Whether this layouter contains any items. + fn is_empty(&self) -> bool; } /// A collection of layouted content. #[derive(Debug, Clone)] -pub struct Layout { - /// The extent of this layout into all directions. - extent: Extent, - /// Actions composing this layout. - actions: Vec<TextAction>, -} - -impl Layout { - /// Convert this layout into a document given the list of fonts referenced by it. - pub fn into_document(self, fonts: Vec<Font>) -> Document { - Document { - pages: vec![Page { - width: self.extent.width, - height: self.extent.height, - actions: self.actions, - }], - fonts, - } - } -} - -/// Types supporting some kind of layouting. -pub trait Layouter { - /// Finishing the current layouting process and return a layout. - fn finish(self) -> LayoutResult<Layout>; +pub enum Layout { + /// A box layout. + Boxed(BoxLayout), + /// A flexible layout. + Flex(FlexLayout), } /// The context for layouting. @@ -76,70 +37,61 @@ pub trait Layouter { pub struct LayoutContext<'a, 'p> { /// Loads fonts matching queries. pub loader: &'a FontLoader<'p>, - /// The spacial constraints to layout in. - pub max_extent: Extent, /// Base style to set text with. - pub text_style: TextStyle, + pub style: TextStyle, + /// The space to layout in. + pub space: LayoutSpace, } -/// Default styles for text. +/// Spacial constraints for layouting. #[derive(Debug, Clone)] -pub struct TextStyle { - /// A fallback list of font families to use. - pub font_families: Vec<FontFamily>, - /// The font size. - pub font_size: f32, - /// The line spacing (as a multiple of the font size). - pub line_spacing: f32, - /// The paragraphs spacing (as a multiple of the line spacing). - pub paragraph_spacing: f32, +pub struct LayoutSpace { + /// The maximum size of the box to layout in. + pub dimensions: Size2D, + /// Padding that should be respected on each side. + pub padding: SizeBox, } -impl Default for TextStyle { - fn default() -> TextStyle { - use FontFamily::*; - TextStyle { - // Default font family, font size and line spacing. - font_families: vec![SansSerif, Serif, Monospace], - font_size: 11.0, - line_spacing: 1.25, - paragraph_spacing: 1.5, - } - } -} +/// Layout a syntax tree in a given context. +pub fn layout(tree: &SyntaxTree, ctx: &LayoutContext) -> LayoutResult<BoxLayout> { + // The top-level layouter and the sub-level layouter. + let mut box_layouter = BoxLayouter::new(ctx); + let mut flex_layouter = FlexLayouter::new(ctx); -/// Default styles for pages. -#[derive(Debug, Clone)] -pub struct PageStyle { - /// The width of the page. - pub width: Size, - /// The height of the page. - pub height: Size, - - /// The amount of white space on the left side. - pub margin_left: Size, - /// The amount of white space on the top side. - pub margin_top: Size, - /// The amount of white space on the right side. - pub margin_right: Size, - /// The amount of white space on the bottom side. - pub margin_bottom: Size, -} + // The current text style. + let mut italic = false; + let mut bold = false; -impl Default for PageStyle { - fn default() -> PageStyle { - PageStyle { - // A4 paper. - width: Size::from_mm(210.0), - height: Size::from_mm(297.0), - - // All the same margins. - margin_left: Size::from_cm(3.0), - margin_top: Size::from_cm(3.0), - margin_right: Size::from_cm(3.0), - margin_bottom: Size::from_cm(3.0), + // Walk all nodes and layout them. + for node in &tree.nodes { + match node { + Node::Text(text) => { + unimplemented!() + }, + Node::Space => { + unimplemented!() + }, + Node::Newline => { + unimplemented!() + }, + + // Toggle the text styles. + Node::ToggleItalics => italic = !italic, + Node::ToggleBold => bold = !bold, + + Node::Func(func) => { + unimplemented!() + } } } + + // If there are remainings, add them to the layout. + if !flex_layouter.is_empty() { + let boxed = flex_layouter.finish().into_box(); + box_layouter.add_box(boxed); + } + + Ok(box_layouter.finish()) } /// The error type for layouting. |
