summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/layout/document.rs2
-rw-r--r--src/layout/fixed.rs2
-rw-r--r--src/layout/mod.rs11
-rw-r--r--src/layout/node.rs2
-rw-r--r--src/layout/pad.rs51
-rw-r--r--src/layout/par.rs21
-rw-r--r--src/layout/spacing.rs4
-rw-r--r--src/layout/stack.rs21
-rw-r--r--src/layout/text.rs6
9 files changed, 71 insertions, 49 deletions
diff --git a/src/layout/document.rs b/src/layout/document.rs
index b233ffd8..407dcda4 100644
--- a/src/layout/document.rs
+++ b/src/layout/document.rs
@@ -34,6 +34,6 @@ impl Pages {
pub fn layout(&self, ctx: &mut LayoutContext) -> Vec<BoxLayout> {
let areas = Areas::repeat(self.size);
let layouted = self.child.layout(ctx, &areas);
- layouted.into_iter().filter_map(Layouted::into_boxed).collect()
+ layouted.into_boxes()
}
}
diff --git a/src/layout/fixed.rs b/src/layout/fixed.rs
index df099731..8a42a9d3 100644
--- a/src/layout/fixed.rs
+++ b/src/layout/fixed.rs
@@ -13,7 +13,7 @@ pub struct Fixed {
}
impl Layout for Fixed {
- fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Vec<Layouted> {
+ fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Layouted {
let Area { rem, full } = areas.current;
let size = Size::new(
self.width.map(|w| w.eval(full.width)).unwrap_or(rem.width),
diff --git a/src/layout/mod.rs b/src/layout/mod.rs
index 643f1a43..de112083 100644
--- a/src/layout/mod.rs
+++ b/src/layout/mod.rs
@@ -38,7 +38,7 @@ pub struct LayoutContext {
/// Layout a node.
pub trait Layout {
/// Layout the node in the given layout context.
- fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Vec<Layouted>;
+ fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Layouted;
}
/// A sequence of areas to layout into.
@@ -129,14 +129,17 @@ pub enum Layouted {
Spacing(Length),
/// A box that should be added to and aligned in the parent.
Boxed(BoxLayout, Gen<Align>),
+ /// Multiple boxes.
+ Boxes(Vec<(BoxLayout, Gen<Align>)>),
}
impl Layouted {
/// Return the box if this if its a box variant.
- pub fn into_boxed(self) -> Option<BoxLayout> {
+ pub fn into_boxes(self) -> Vec<BoxLayout> {
match self {
- Self::Spacing(_) => None,
- Self::Boxed(boxed, _) => Some(boxed),
+ Self::Spacing(_) => vec![],
+ Self::Boxed(boxed, _) => vec![boxed],
+ Self::Boxes(boxes) => boxes.into_iter().map(|p| p.0).collect(),
}
}
}
diff --git a/src/layout/node.rs b/src/layout/node.rs
index 4cba3d4f..aa4b990f 100644
--- a/src/layout/node.rs
+++ b/src/layout/node.rs
@@ -25,7 +25,7 @@ impl LayoutNode {
}
impl Layout for LayoutNode {
- fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Vec<Layouted> {
+ fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Layouted {
match self {
Self::Spacing(spacing) => spacing.layout(ctx, areas),
Self::Text(text) => text.layout(ctx, areas),
diff --git a/src/layout/pad.rs b/src/layout/pad.rs
index 2994dd59..b26bea71 100644
--- a/src/layout/pad.rs
+++ b/src/layout/pad.rs
@@ -11,27 +11,16 @@ pub struct Pad {
}
impl Layout for Pad {
- fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Vec<Layouted> {
- let shrink = |size| size - self.padding.eval(size).size();
- let areas = Areas {
- current: Area {
- rem: shrink(areas.current.rem),
- full: shrink(areas.current.full),
- },
- backlog: areas.backlog.iter().copied().map(shrink).collect(),
- last: areas.last.map(shrink),
- };
+ fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Layouted {
+ let areas = shrink_areas(areas, self.padding);
let mut layouted = self.child.layout(ctx, &areas);
-
- for item in &mut layouted {
- if let Layouted::Boxed(boxed, _) = item {
- let padding = self.padding.eval(boxed.size);
- let origin = Point::new(padding.left, padding.top);
-
- boxed.size += padding.size();
- for (point, _) in &mut boxed.elements {
- *point += origin;
+ match &mut layouted {
+ Layouted::Spacing(_) => {}
+ Layouted::Boxed(boxed, _) => pad_box(boxed, self.padding),
+ Layouted::Boxes(boxes) => {
+ for (boxed, _) in boxes {
+ pad_box(boxed, self.padding);
}
}
}
@@ -40,6 +29,30 @@ impl Layout for Pad {
}
}
+/// Shrink all areas by the padding.
+fn shrink_areas(areas: &Areas, padding: Sides<Linear>) -> Areas {
+ let shrink = |size| size - padding.eval(size).size();
+ Areas {
+ current: Area {
+ rem: shrink(areas.current.rem),
+ full: shrink(areas.current.full),
+ },
+ backlog: areas.backlog.iter().copied().map(shrink).collect(),
+ last: areas.last.map(shrink),
+ }
+}
+
+/// Enlarge the box and move all elements inwards.
+fn pad_box(boxed: &mut BoxLayout, padding: Sides<Linear>) {
+ let padding = padding.eval(boxed.size);
+ let origin = Point::new(padding.left, padding.top);
+
+ boxed.size += padding.size();
+ for (point, _) in &mut boxed.elements {
+ *point += origin;
+ }
+}
+
impl From<Pad> for LayoutNode {
fn from(pad: Pad) -> Self {
Self::dynamic(pad)
diff --git a/src/layout/par.rs b/src/layout/par.rs
index e77bb4e7..ad71cffc 100644
--- a/src/layout/par.rs
+++ b/src/layout/par.rs
@@ -19,17 +19,20 @@ pub struct Par {
}
impl Layout for Par {
- fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Vec<Layouted> {
+ fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Layouted {
let mut layouter = ParLayouter::new(self, areas.clone());
for child in &self.children {
- for layouted in child.layout(ctx, &layouter.areas) {
- match layouted {
- Layouted::Spacing(spacing) => layouter.spacing(spacing),
- Layouted::Boxed(boxed, aligns) => layouter.boxed(boxed, aligns.cross),
+ match child.layout(ctx, &layouter.areas) {
+ Layouted::Spacing(spacing) => layouter.spacing(spacing),
+ Layouted::Boxed(boxed, aligns) => layouter.boxed(boxed, aligns.cross),
+ Layouted::Boxes(boxes) => {
+ for (boxed, aligns) in boxes {
+ layouter.boxed(boxed, aligns.cross);
+ }
}
}
}
- layouter.finish()
+ Layouted::Boxes(layouter.finish())
}
}
@@ -45,7 +48,7 @@ struct ParLayouter<'a> {
cross: SpecAxis,
dirs: Gen<Dir>,
areas: Areas,
- layouted: Vec<Layouted>,
+ layouted: Vec<(BoxLayout, Gen<Align>)>,
lines: Vec<(Length, BoxLayout, Align)>,
lines_size: Gen<Length>,
run: Vec<(Length, BoxLayout, Align)>,
@@ -169,13 +172,13 @@ impl<'a> ParLayouter<'a> {
output.push_layout(pos, run);
}
- self.layouted.push(Layouted::Boxed(output, self.par.aligns));
+ self.layouted.push((output, self.par.aligns));
self.areas.next();
self.lines_size = Gen::ZERO;
}
- fn finish(mut self) -> Vec<Layouted> {
+ fn finish(mut self) -> Vec<(BoxLayout, Gen<Align>)> {
self.finish_run();
self.finish_area();
self.layouted
diff --git a/src/layout/spacing.rs b/src/layout/spacing.rs
index f64c7968..c44f92e4 100644
--- a/src/layout/spacing.rs
+++ b/src/layout/spacing.rs
@@ -15,8 +15,8 @@ pub struct Spacing {
}
impl Layout for Spacing {
- fn layout(&self, _: &mut LayoutContext, _: &Areas) -> Vec<Layouted> {
- vec![Layouted::Spacing(self.amount)]
+ fn layout(&self, _: &mut LayoutContext, _: &Areas) -> Layouted {
+ Layouted::Spacing(self.amount)
}
}
diff --git a/src/layout/stack.rs b/src/layout/stack.rs
index 9aeb80aa..228293bc 100644
--- a/src/layout/stack.rs
+++ b/src/layout/stack.rs
@@ -17,17 +17,20 @@ pub struct Stack {
}
impl Layout for Stack {
- fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Vec<Layouted> {
+ fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Layouted {
let mut layouter = StackLayouter::new(self, areas.clone());
for child in &self.children {
- for layouted in child.layout(ctx, &layouter.areas) {
- match layouted {
- Layouted::Spacing(spacing) => layouter.spacing(spacing),
- Layouted::Boxed(boxed, aligns) => layouter.boxed(boxed, aligns),
+ match child.layout(ctx, &layouter.areas) {
+ Layouted::Spacing(spacing) => layouter.spacing(spacing),
+ Layouted::Boxed(boxed, aligns) => layouter.boxed(boxed, aligns),
+ Layouted::Boxes(boxes) => {
+ for (boxed, aligns) in boxes {
+ layouter.boxed(boxed, aligns);
+ }
}
}
}
- layouter.finish()
+ Layouted::Boxes(layouter.finish())
}
}
@@ -42,7 +45,7 @@ struct StackLayouter<'a> {
main: SpecAxis,
dirs: Gen<Dir>,
areas: Areas,
- layouted: Vec<Layouted>,
+ layouted: Vec<(BoxLayout, Gen<Align>)>,
boxes: Vec<(Length, BoxLayout, Gen<Align>)>,
used: Gen<Length>,
ruler: Align,
@@ -134,14 +137,14 @@ impl<'a> StackLayouter<'a> {
output.push_layout(pos, layout);
}
- self.layouted.push(Layouted::Boxed(output, self.stack.aligns));
+ self.layouted.push((output, self.stack.aligns));
self.areas.next();
self.used = Gen::ZERO;
self.ruler = Align::Start;
}
- fn finish(mut self) -> Vec<Layouted> {
+ fn finish(mut self) -> Vec<(BoxLayout, Gen<Align>)> {
self.finish_area();
self.layouted
}
diff --git a/src/layout/text.rs b/src/layout/text.rs
index 5e047069..31ae19cd 100644
--- a/src/layout/text.rs
+++ b/src/layout/text.rs
@@ -24,9 +24,9 @@ pub struct Text {
}
impl Layout for Text {
- fn layout(&self, ctx: &mut LayoutContext, _: &Areas) -> Vec<Layouted> {
+ fn layout(&self, ctx: &mut LayoutContext, _: &Areas) -> Layouted {
let mut loader = ctx.loader.borrow_mut();
- vec![Layouted::Boxed(
+ Layouted::Boxed(
shaping::shape(
&mut loader,
&self.text,
@@ -36,7 +36,7 @@ impl Layout for Text {
self.variant,
),
self.aligns,
- )]
+ )
}
}