From 5243878d810d4817c81acc9ae346d46757fcf602 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Mon, 12 Oct 2020 17:29:01 +0200 Subject: [PATCH] =?UTF-8?q?Less=20vecs=20in=20layouting=20=E2=9A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/layout/document.rs | 2 +- src/layout/fixed.rs | 2 +- src/layout/mod.rs | 11 +++++---- src/layout/node.rs | 2 +- src/layout/pad.rs | 51 ++++++++++++++++++++++++++---------------- src/layout/par.rs | 21 +++++++++-------- src/layout/spacing.rs | 4 ++-- src/layout/stack.rs | 21 +++++++++-------- src/layout/text.rs | 6 ++--- 9 files changed, 71 insertions(+), 49 deletions(-) diff --git a/src/layout/document.rs b/src/layout/document.rs index b233ffd87..407dcda42 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 { 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 df0997318..8a42a9d34 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 { + 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 643f1a432..de1120835 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; + 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), + /// Multiple boxes. + Boxes(Vec<(BoxLayout, Gen)>), } impl Layouted { /// Return the box if this if its a box variant. - pub fn into_boxed(self) -> Option { + pub fn into_boxes(self) -> Vec { 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 4cba3d4ff..aa4b990f2 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 { + 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 2994dd59f..b26bea711 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 { - 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) -> 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) { + 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 for LayoutNode { fn from(pad: Pad) -> Self { Self::dynamic(pad) diff --git a/src/layout/par.rs b/src/layout/par.rs index e77bb4e78..ad71cffc5 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 { + 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, areas: Areas, - layouted: Vec, + layouted: Vec<(BoxLayout, Gen)>, lines: Vec<(Length, BoxLayout, Align)>, lines_size: Gen, 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 { + fn finish(mut self) -> Vec<(BoxLayout, Gen)> { self.finish_run(); self.finish_area(); self.layouted diff --git a/src/layout/spacing.rs b/src/layout/spacing.rs index f64c79680..c44f92e4a 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 { - 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 9aeb80aa0..228293bc7 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 { + 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, areas: Areas, - layouted: Vec, + layouted: Vec<(BoxLayout, Gen)>, boxes: Vec<(Length, BoxLayout, Gen)>, used: Gen, 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 { + fn finish(mut self) -> Vec<(BoxLayout, Gen)> { self.finish_area(); self.layouted } diff --git a/src/layout/text.rs b/src/layout/text.rs index 5e047069a..31ae19cdc 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 { + 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, - )] + ) } }