diff options
| author | Laurenz <laurmaedje@gmail.com> | 2019-12-13 23:59:01 +0100 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2019-12-13 23:59:01 +0100 |
| commit | 665b4d2aca81af48b8e0eaca4e709ef2e7825844 (patch) | |
| tree | 4ada33f607455f14b6a170fe4b7fbe173056567b /src/layout | |
| parent | 971ff3a2dcff1e68bf7e19017113469aad5a30c2 (diff) | |
More consistent library code and functions 🎄
Diffstat (limited to 'src/layout')
| -rw-r--r-- | src/layout/flex.rs | 6 | ||||
| -rw-r--r-- | src/layout/mod.rs | 39 | ||||
| -rw-r--r-- | src/layout/stack.rs | 27 | ||||
| -rw-r--r-- | src/layout/text.rs | 6 | ||||
| -rw-r--r-- | src/layout/tree.rs | 21 |
5 files changed, 67 insertions, 32 deletions
diff --git a/src/layout/flex.rs b/src/layout/flex.rs index 48853863..72878a29 100644 --- a/src/layout/flex.rs +++ b/src/layout/flex.rs @@ -66,6 +66,7 @@ pub struct FlexContext { pub axes: LayoutAxes, pub alignment: LayoutAlignment, pub flex_spacing: Size, + pub repeat: bool, pub debug: bool, } @@ -76,6 +77,7 @@ impl FlexLayouter { spaces: ctx.spaces, axes: ctx.axes, alignment: ctx.alignment, + repeat: ctx.repeat, debug: ctx.debug, }); @@ -144,7 +146,7 @@ impl FlexLayouter { pub fn finish(mut self) -> LayoutResult<MultiLayout> { self.finish_space(false)?; - Ok(self.stack.finish()) + self.stack.finish() } pub fn finish_space(&mut self, hard: bool) -> LayoutResult<()> { @@ -152,7 +154,7 @@ impl FlexLayouter { self.finish_run()?; } - self.stack.finish_space(hard); + self.stack.finish_space(hard)?; Ok(self.start_line()) } diff --git a/src/layout/mod.rs b/src/layout/mod.rs index 58c56dd4..b2b10264 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -16,7 +16,7 @@ mod text; /// Common types for layouting. pub mod prelude { pub use super::{ - layout_tree, LayoutResult, + layout, LayoutResult, MultiLayout, Layout, LayoutContext, LayoutSpaces, LayoutSpace, LayoutExpansion, LayoutAxes, GenericAxis, SpecificAxis, Direction, LayoutAlignment, Alignment, SpacingKind, @@ -29,7 +29,7 @@ pub mod prelude { /// Different kinds of layouters (fully re-exported). pub mod layouters { - pub use super::tree::layout_tree; + pub use super::tree::layout; pub use super::flex::{FlexLayouter, FlexContext}; pub use super::stack::{StackLayouter, StackContext}; pub use super::text::{layout_text, TextContext}; @@ -107,10 +107,11 @@ pub struct LayoutContext<'a, 'p> { 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 repeat the last space or quit with an error if more space - /// would be needed. + /// 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, @@ -172,6 +173,14 @@ impl LayoutExpansion { pub fn new(horizontal: bool, vertical: bool) -> LayoutExpansion { LayoutExpansion { horizontal, vertical } } + + /// Borrow the spcified component mutably. + pub fn get_mut(&mut self, axis: SpecificAxis) -> &mut bool { + match axis { + Horizontal => &mut self.horizontal, + Vertical => &mut self.vertical, + } + } } /// The axes along which the content is laid out. @@ -192,16 +201,24 @@ impl LayoutAxes { } /// Return the direction of the specified generic axis. - pub fn get_generic(self, axis: GenericAxis) -> Direction { + pub fn get(self, axis: GenericAxis) -> Direction { match axis { Primary => self.primary, Secondary => self.secondary, } } + /// Borrow the direction of the specified generic axis mutably. + pub fn get_mut(&mut self, axis: GenericAxis) -> &mut Direction { + match axis { + Primary => &mut self.primary, + Secondary => &mut self.secondary, + } + } + /// Return the direction of the specified specific axis. pub fn get_specific(self, axis: SpecificAxis) -> Direction { - self.get_generic(axis.to_generic(self)) + self.get(axis.to_generic(self)) } } @@ -215,7 +232,7 @@ pub enum GenericAxis { impl GenericAxis { /// The specific version of this axis in the given system of axes. pub fn to_specific(self, axes: LayoutAxes) -> SpecificAxis { - axes.get_generic(self).axis() + axes.get(self).axis() } /// The other axis. @@ -306,11 +323,11 @@ impl LayoutAlignment { LayoutAlignment { primary, secondary } } - /// Return the alignment of the specified generic axis. - pub fn get(self, axis: GenericAxis) -> Alignment { + /// Borrow the alignment of the specified generic axis mutably. + pub fn get_mut(&mut self, axis: GenericAxis) -> &mut Alignment { match axis { - Primary => self.primary, - Secondary => self.secondary, + Primary => &mut self.primary, + Secondary => &mut self.secondary, } } } diff --git a/src/layout/stack.rs b/src/layout/stack.rs index a2ffdc9b..3c659d8a 100644 --- a/src/layout/stack.rs +++ b/src/layout/stack.rs @@ -27,6 +27,8 @@ pub struct StackContext { /// Which alignment to set on the resulting layout. This affects how it will /// be positioned in a parent box. pub alignment: LayoutAlignment, + /// Whether to have repeated spaces or to use only the first and only once. + pub repeat: bool, /// Whether to output a command which renders a debugging box showing the /// extent of the layout. pub debug: bool, @@ -77,8 +79,9 @@ impl StackLayouter { /// Add a layout to the stack. pub fn add(&mut self, layout: Layout) -> LayoutResult<()> { + // If the alignment cannot be fit in this space, finish it. if !self.update_rulers(layout.alignment) { - self.finish_space(true); + self.finish_space(true)?; } // Now, we add a possibly cached soft space. If the secondary alignment @@ -91,11 +94,11 @@ impl StackLayouter { // Find the first space that fits the layout. while !self.space.usable.fits(layout.dimensions) { if self.space_is_last() && self.space_is_empty() { - error!("box of size {} does not fit into remaining usable size {}", + error!("cannot fit box of size {} into usable size of {}", layout.dimensions, self.space.usable); } - self.finish_space(true); + self.finish_space(true)?; } // Change the usable space and size of the space. @@ -257,15 +260,19 @@ impl StackLayouter { } /// Compute the finished multi-layout. - pub fn finish(mut self) -> MultiLayout { + pub fn finish(mut self) -> LayoutResult<MultiLayout> { if self.space.hard || !self.space_is_empty() { - self.finish_space(false); + self.finish_space(false)?; } - self.layouts + Ok(self.layouts) } /// Finish the current space and start a new one. - pub fn finish_space(&mut self, hard: bool) { + pub fn finish_space(&mut self, hard: bool) -> LayoutResult<()> { + if !self.ctx.repeat && hard { + error!("cannot create new space in a non-repeating context"); + } + let space = self.ctx.spaces[self.space.index]; // ------------------------------------------------------------------ // @@ -304,7 +311,7 @@ impl StackLayouter { // layout uses up space from the origin to the end. Thus, it reduces // the usable space for following layouts at it's origin by its // extent along the secondary axis. - *bound.get_mut(*axes, Secondary, Origin) + *bound.get_mut(axes.secondary, Origin) += axes.secondary.factor() * layout.dimensions.get_secondary(*axes); } @@ -333,7 +340,7 @@ impl StackLayouter { // We reduce the bounding box of this layout at it's end by the // accumulated secondary extent of all layouts we have seen so far, // which are the layouts after this one since we iterate reversed. - *bound.get_mut(*axes, Secondary, End) + *bound.get_mut(axes.secondary, End) -= axes.secondary.factor() * extent.y; // Then, we add this layout's secondary extent to the accumulator. @@ -378,7 +385,7 @@ impl StackLayouter { // ------------------------------------------------------------------ // // Step 5: Start the next space. - self.start_space(self.next_space(), hard); + Ok(self.start_space(self.next_space(), hard)) } /// Start a new space with the given index. diff --git a/src/layout/text.rs b/src/layout/text.rs index af74df13..996c5139 100644 --- a/src/layout/text.rs +++ b/src/layout/text.rs @@ -61,7 +61,7 @@ impl<'a, 'p> TextLayouter<'a, 'p> { self.buffer = String::new(); } - self.actions.add(LayoutAction::SetFont(index, self.ctx.style.font_size)); + self.actions.add(LayoutAction::SetFont(index, self.ctx.style.font_size())); self.active_font = index; } @@ -73,7 +73,7 @@ impl<'a, 'p> TextLayouter<'a, 'p> { } Ok(Layout { - dimensions: Size2D::new(self.width, self.ctx.style.font_size), + dimensions: Size2D::new(self.width, self.ctx.style.font_size()), alignment: self.ctx.alignment, actions: self.actions.to_vec(), }) @@ -108,7 +108,7 @@ impl<'a, 'p> TextLayouter<'a, 'p> { .advance_width as f32; let char_width = font_unit_to_size(glyph_width) - * self.ctx.style.font_size.to_pt(); + * self.ctx.style.font_size().to_pt(); return Ok((index, char_width)); } diff --git a/src/layout/tree.rs b/src/layout/tree.rs index e9d8850d..3c6a4274 100644 --- a/src/layout/tree.rs +++ b/src/layout/tree.rs @@ -7,7 +7,7 @@ use crate::style::TextStyle; use super::*; /// Layout a syntax tree into a multibox. -pub fn layout_tree(tree: &SyntaxTree, ctx: LayoutContext) -> LayoutResult<MultiLayout> { +pub fn layout(tree: &SyntaxTree, ctx: LayoutContext) -> LayoutResult<MultiLayout> { let mut layouter = TreeLayouter::new(ctx); layouter.layout(tree)?; layouter.finish() @@ -28,6 +28,7 @@ impl<'a, 'p> TreeLayouter<'a, 'p> { spaces: ctx.spaces.clone(), axes: ctx.axes, alignment: ctx.alignment, + repeat: ctx.repeat, debug: ctx.debug, }), style: ctx.style.clone(), @@ -106,8 +107,15 @@ impl<'a, 'p> TreeLayouter<'a, 'p> { FinishLine => {}, FinishRun => {}, - FinishSpace => self.stack.finish_space(true), + FinishSpace => self.stack.finish_space(true)?, BreakParagraph => self.layout_paragraph()?, + BreakPage => { + if self.ctx.nested { + error!("page break cannot be issued from nested context"); + } + + self.stack.finish_space(true)? + } SetTextStyle(style) => self.style.text = style, SetPageStyle(style) => { @@ -116,6 +124,7 @@ impl<'a, 'p> TreeLayouter<'a, 'p> { } self.style.page = style; + self.ctx.base = style.dimensions.unpadded(style.margins); self.stack.set_spaces(smallvec