summaryrefslogtreecommitdiff
path: root/src/layout
diff options
context:
space:
mode:
Diffstat (limited to 'src/layout')
-rw-r--r--src/layout/flex.rs28
-rw-r--r--src/layout/mod.rs12
-rw-r--r--src/layout/stacked.rs45
-rw-r--r--src/layout/tree.rs15
4 files changed, 65 insertions, 35 deletions
diff --git a/src/layout/flex.rs b/src/layout/flex.rs
index c3d88e1b..053954a4 100644
--- a/src/layout/flex.rs
+++ b/src/layout/flex.rs
@@ -14,7 +14,7 @@ pub struct FlexLayouter {
#[derive(Debug, Clone)]
enum FlexUnit {
Boxed(Layout),
- Space(Size, bool),
+ Space(Size, SpaceKind),
SetAxes(LayoutAxes),
Break,
}
@@ -102,15 +102,15 @@ impl FlexLayouter {
self.units.push(FlexUnit::Break);
}
- pub fn add_primary_space(&mut self, space: Size, soft: bool) {
- self.units.push(FlexUnit::Space(space, soft))
+ pub fn add_primary_space(&mut self, space: Size, kind: SpaceKind) {
+ self.units.push(FlexUnit::Space(space, kind))
}
- pub fn add_secondary_space(&mut self, space: Size, soft: bool) -> LayoutResult<()> {
+ pub fn add_secondary_space(&mut self, space: Size, kind: SpaceKind) -> LayoutResult<()> {
if !self.run_is_empty() {
self.finish_run()?;
}
- Ok(self.stack.add_space(space, soft))
+ Ok(self.stack.add_space(space, kind))
}
pub fn set_axes(&mut self, axes: LayoutAxes) {
@@ -169,7 +169,7 @@ impl FlexLayouter {
for unit in units {
match unit {
FlexUnit::Boxed(boxed) => self.layout_box(boxed)?,
- FlexUnit::Space(space, soft) => self.layout_space(space, soft),
+ FlexUnit::Space(space, kind) => self.layout_space(space, kind),
FlexUnit::SetAxes(axes) => self.layout_set_axes(axes),
FlexUnit::Break => { self.finish_line()?; },
}
@@ -186,13 +186,13 @@ impl FlexLayouter {
}
self.stack.add(Layout {
- dimensions: self.axes.specialize(
- self.line.combined_dimensions+ Size2D::with_y(self.flex_spacing)
- ),
+ dimensions: self.axes.specialize(self.line.combined_dimensions),
actions: self.line.actions.to_vec(),
debug_render: false,
})?;
+ self.stack.add_space(self.flex_spacing, SpaceKind::Independent);
+
let remaining = self.axes.specialize(Size2D {
x: self.part.usable
- self.part.dimensions.x
@@ -250,7 +250,7 @@ impl FlexLayouter {
}
if let SpaceState::Soft(space) = self.part.space {
- self.layout_space(space, false);
+ self.layout_space(space, SpaceKind::Hard);
}
let offset = self.part.dimensions.x;
@@ -263,8 +263,8 @@ impl FlexLayouter {
Ok(())
}
- fn layout_space(&mut self, space: Size, soft: bool) {
- if soft {
+ fn layout_space(&mut self, space: Size, kind: SpaceKind) {
+ if kind == SpaceKind::Soft {
if self.part.space != SpaceState::Forbidden {
self.part.space = SpaceState::Soft(space);
}
@@ -275,7 +275,9 @@ impl FlexLayouter {
self.part.dimensions.x += space;
}
- self.part.space = SpaceState::Forbidden;
+ if kind == SpaceKind::Hard {
+ self.part.space = SpaceState::Forbidden;
+ }
}
}
diff --git a/src/layout/mod.rs b/src/layout/mod.rs
index e78e6067..2e643295 100644
--- a/src/layout/mod.rs
+++ b/src/layout/mod.rs
@@ -308,7 +308,17 @@ pub enum Alignment {
}
#[derive(Debug, Copy, Clone, PartialEq)]
-pub enum SpaceState {
+pub enum SpaceKind {
+ /// Soft spaces are eaten up by hard spaces before or after them.
+ Soft,
+ /// Independent do not eat up soft spaces and are not eaten up by hard spaces.
+ Independent,
+ /// Hard spaces eat up soft spaces before or after them.
+ Hard,
+}
+
+#[derive(Debug, Copy, Clone, PartialEq)]
+enum SpaceState {
Soft(Size),
Forbidden,
Allowed,
diff --git a/src/layout/stacked.rs b/src/layout/stacked.rs
index 55e1b2b8..a6999dee 100644
--- a/src/layout/stacked.rs
+++ b/src/layout/stacked.rs
@@ -32,10 +32,14 @@ impl Space {
#[derive(Debug, Clone)]
struct Subspace {
origin: Size2D,
- usable: Size2D,
anchor: Size2D,
factor: i32,
+
+ boxes: Vec<(Size, Size, Layout)>,
+
+ usable: Size2D,
dimensions: Size2D,
+
space: SpaceState,
}
@@ -43,9 +47,10 @@ impl Subspace {
fn new(origin: Size2D, usable: Size2D, axes: LayoutAxes) -> Subspace {
Subspace {
origin,
- usable: axes.generalize(usable),
anchor: axes.anchor(usable),
factor: axes.secondary.axis.factor(),
+ boxes: vec![],
+ usable: axes.generalize(usable),
dimensions: Size2D::zero(),
space: SpaceState::Forbidden,
}
@@ -78,7 +83,7 @@ impl StackLayouter {
pub fn add(&mut self, layout: Layout) -> LayoutResult<()> {
if let SpaceState::Soft(space) = self.sub.space {
- self.add_space(space, false);
+ self.add_space(space, SpaceKind::Hard);
}
let size = self.ctx.axes.generalize(layout.dimensions);
@@ -90,9 +95,6 @@ impl StackLayouter {
while !self.sub.usable.fits(new_dimensions) {
if self.space_is_last() && self.space_is_empty() {
- println!("usable: {}", self.sub.usable);
- println!("dims: {}", new_dimensions);
- println!("size: {}", size);
Err(LayoutError::NotEnoughSpace("failed to add box to stack"))?;
}
@@ -101,14 +103,9 @@ impl StackLayouter {
}
let offset = self.sub.dimensions.y;
- let anchor = self.ctx.axes.anchor(size);
-
- let pos = self.sub.origin + self.ctx.axes.specialize(
- (self.sub.anchor - anchor)
- + Size2D::with_y(self.space.combined_dimensions.y + self.sub.factor * offset)
- );
+ let anchor = self.ctx.axes.primary.anchor(size.x);
- self.space.actions.add_layout(pos, layout);
+ self.sub.boxes.push((offset, anchor, layout));
self.sub.dimensions = new_dimensions;
self.sub.space = SpaceState::Allowed;
@@ -122,8 +119,8 @@ impl StackLayouter {
Ok(())
}
- pub fn add_space(&mut self, space: Size, soft: bool) {
- if soft {
+ pub fn add_space(&mut self, space: Size, kind: SpaceKind) {
+ if kind == SpaceKind::Soft {
if self.sub.space != SpaceState::Forbidden {
self.sub.space = SpaceState::Soft(space);
}
@@ -134,7 +131,9 @@ impl StackLayouter {
self.sub.dimensions.y += space;
}
- self.sub.space = SpaceState::Forbidden;
+ if kind == SpaceKind::Hard {
+ self.sub.space = SpaceState::Forbidden;
+ }
}
}
@@ -220,6 +219,20 @@ impl StackLayouter {
}
fn finish_subspace(&mut self) {
+ let factor = self.ctx.axes.secondary.axis.factor();
+ let anchor =
+ self.ctx.axes.anchor(self.sub.usable)
+ - self.ctx.axes.anchor(Size2D::with_y(self.sub.dimensions.y));
+
+ for (offset, layout_anchor, layout) in self.sub.boxes.drain(..) {
+ let pos = self.sub.origin
+ + self.ctx.axes.specialize(
+ anchor + Size2D::new(-layout_anchor, factor * offset)
+ );
+
+ self.space.actions.add_layout(pos, layout);
+ }
+
if self.ctx.axes.primary.needs_expansion() {
self.sub.dimensions.x = self.sub.usable.x;
}
diff --git a/src/layout/tree.rs b/src/layout/tree.rs
index f6a8f408..f5ae2435 100644
--- a/src/layout/tree.rs
+++ b/src/layout/tree.rs
@@ -58,16 +58,19 @@ impl<'a, 'p> TreeLayouter<'a, 'p> {
}
fn layout_space(&mut self) {
- self.flex.add_primary_space(word_spacing(&self.style), true);
+ self.flex.add_primary_space(word_spacing(&self.style), SpaceKind::Soft);
}
fn layout_paragraph(&mut self) -> LayoutResult<()> {
- self.flex.add_secondary_space(paragraph_spacing(&self.style), true)
+ self.flex.add_secondary_space(paragraph_spacing(&self.style), SpaceKind::Soft)
}
fn layout_func(&mut self, func: &FuncCall) -> LayoutResult<()> {
let (first, second) = self.flex.remaining()?;
+ let mut axes = self.ctx.axes.expanding(false);
+ axes.secondary.alignment = Alignment::Origin;
+
let ctx = |spaces| {
LayoutContext {
loader: self.ctx.loader,
@@ -75,7 +78,7 @@ impl<'a, 'p> TreeLayouter<'a, 'p> {
text_style: &self.style,
page_style: self.ctx.page_style,
spaces,
- axes: self.ctx.axes.expanding(false),
+ axes,
expand: false,
}
};
@@ -106,8 +109,10 @@ impl<'a, 'p> TreeLayouter<'a, 'p> {
Command::Add(layout) => self.flex.add(layout),
Command::AddMultiple(layouts) => self.flex.add_multiple(layouts),
- Command::AddPrimarySpace(space) => self.flex.add_primary_space(space, false),
- Command::AddSecondarySpace(space) => self.flex.add_secondary_space(space, false)?,
+ Command::AddPrimarySpace(space)
+ => self.flex.add_primary_space(space, SpaceKind::Hard),
+ Command::AddSecondarySpace(space)
+ => self.flex.add_secondary_space(space, SpaceKind::Hard)?,
Command::FinishLine => self.flex.add_break(),
Command::FinishRun => { self.flex.finish_run()?; },