Less vecs in layouting

This commit is contained in:
Laurenz 2020-10-12 17:29:01 +02:00
parent 38157b0e0c
commit 5243878d81
9 changed files with 71 additions and 49 deletions

View File

@ -34,6 +34,6 @@ impl Pages {
pub fn layout(&self, ctx: &mut LayoutContext) -> Vec<BoxLayout> { pub fn layout(&self, ctx: &mut LayoutContext) -> Vec<BoxLayout> {
let areas = Areas::repeat(self.size); let areas = Areas::repeat(self.size);
let layouted = self.child.layout(ctx, &areas); let layouted = self.child.layout(ctx, &areas);
layouted.into_iter().filter_map(Layouted::into_boxed).collect() layouted.into_boxes()
} }
} }

View File

@ -13,7 +13,7 @@ pub struct Fixed {
} }
impl Layout for 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 Area { rem, full } = areas.current;
let size = Size::new( let size = Size::new(
self.width.map(|w| w.eval(full.width)).unwrap_or(rem.width), self.width.map(|w| w.eval(full.width)).unwrap_or(rem.width),

View File

@ -38,7 +38,7 @@ pub struct LayoutContext {
/// Layout a node. /// Layout a node.
pub trait Layout { pub trait Layout {
/// Layout the node in the given layout context. /// 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. /// A sequence of areas to layout into.
@ -129,14 +129,17 @@ pub enum Layouted {
Spacing(Length), Spacing(Length),
/// A box that should be added to and aligned in the parent. /// A box that should be added to and aligned in the parent.
Boxed(BoxLayout, Gen<Align>), Boxed(BoxLayout, Gen<Align>),
/// Multiple boxes.
Boxes(Vec<(BoxLayout, Gen<Align>)>),
} }
impl Layouted { impl Layouted {
/// Return the box if this if its a box variant. /// 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 { match self {
Self::Spacing(_) => None, Self::Spacing(_) => vec![],
Self::Boxed(boxed, _) => Some(boxed), Self::Boxed(boxed, _) => vec![boxed],
Self::Boxes(boxes) => boxes.into_iter().map(|p| p.0).collect(),
} }
} }
} }

View File

@ -25,7 +25,7 @@ impl LayoutNode {
} }
impl Layout for 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 { match self {
Self::Spacing(spacing) => spacing.layout(ctx, areas), Self::Spacing(spacing) => spacing.layout(ctx, areas),
Self::Text(text) => text.layout(ctx, areas), Self::Text(text) => text.layout(ctx, areas),

View File

@ -11,27 +11,16 @@ pub struct Pad {
} }
impl Layout for Pad { impl Layout for Pad {
fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Vec<Layouted> { fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Layouted {
let shrink = |size| size - self.padding.eval(size).size(); let areas = shrink_areas(areas, self.padding);
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),
};
let mut layouted = self.child.layout(ctx, &areas); let mut layouted = self.child.layout(ctx, &areas);
match &mut layouted {
for item in &mut layouted { Layouted::Spacing(_) => {}
if let Layouted::Boxed(boxed, _) = item { Layouted::Boxed(boxed, _) => pad_box(boxed, self.padding),
let padding = self.padding.eval(boxed.size); Layouted::Boxes(boxes) => {
let origin = Point::new(padding.left, padding.top); for (boxed, _) in boxes {
pad_box(boxed, self.padding);
boxed.size += padding.size();
for (point, _) in &mut boxed.elements {
*point += origin;
} }
} }
} }
@ -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 { impl From<Pad> for LayoutNode {
fn from(pad: Pad) -> Self { fn from(pad: Pad) -> Self {
Self::dynamic(pad) Self::dynamic(pad)

View File

@ -19,17 +19,20 @@ pub struct Par {
} }
impl Layout for 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()); let mut layouter = ParLayouter::new(self, areas.clone());
for child in &self.children { for child in &self.children {
for layouted in child.layout(ctx, &layouter.areas) { match child.layout(ctx, &layouter.areas) {
match layouted {
Layouted::Spacing(spacing) => layouter.spacing(spacing), Layouted::Spacing(spacing) => layouter.spacing(spacing),
Layouted::Boxed(boxed, aligns) => layouter.boxed(boxed, aligns.cross), 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, cross: SpecAxis,
dirs: Gen<Dir>, dirs: Gen<Dir>,
areas: Areas, areas: Areas,
layouted: Vec<Layouted>, layouted: Vec<(BoxLayout, Gen<Align>)>,
lines: Vec<(Length, BoxLayout, Align)>, lines: Vec<(Length, BoxLayout, Align)>,
lines_size: Gen<Length>, lines_size: Gen<Length>,
run: Vec<(Length, BoxLayout, Align)>, run: Vec<(Length, BoxLayout, Align)>,
@ -169,13 +172,13 @@ impl<'a> ParLayouter<'a> {
output.push_layout(pos, run); 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.areas.next();
self.lines_size = Gen::ZERO; self.lines_size = Gen::ZERO;
} }
fn finish(mut self) -> Vec<Layouted> { fn finish(mut self) -> Vec<(BoxLayout, Gen<Align>)> {
self.finish_run(); self.finish_run();
self.finish_area(); self.finish_area();
self.layouted self.layouted

View File

@ -15,8 +15,8 @@ pub struct Spacing {
} }
impl Layout for Spacing { impl Layout for Spacing {
fn layout(&self, _: &mut LayoutContext, _: &Areas) -> Vec<Layouted> { fn layout(&self, _: &mut LayoutContext, _: &Areas) -> Layouted {
vec![Layouted::Spacing(self.amount)] Layouted::Spacing(self.amount)
} }
} }

View File

@ -17,17 +17,20 @@ pub struct Stack {
} }
impl Layout for 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()); let mut layouter = StackLayouter::new(self, areas.clone());
for child in &self.children { for child in &self.children {
for layouted in child.layout(ctx, &layouter.areas) { match child.layout(ctx, &layouter.areas) {
match layouted {
Layouted::Spacing(spacing) => layouter.spacing(spacing), Layouted::Spacing(spacing) => layouter.spacing(spacing),
Layouted::Boxed(boxed, aligns) => layouter.boxed(boxed, aligns), 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, main: SpecAxis,
dirs: Gen<Dir>, dirs: Gen<Dir>,
areas: Areas, areas: Areas,
layouted: Vec<Layouted>, layouted: Vec<(BoxLayout, Gen<Align>)>,
boxes: Vec<(Length, BoxLayout, Gen<Align>)>, boxes: Vec<(Length, BoxLayout, Gen<Align>)>,
used: Gen<Length>, used: Gen<Length>,
ruler: Align, ruler: Align,
@ -134,14 +137,14 @@ impl<'a> StackLayouter<'a> {
output.push_layout(pos, layout); 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.areas.next();
self.used = Gen::ZERO; self.used = Gen::ZERO;
self.ruler = Align::Start; self.ruler = Align::Start;
} }
fn finish(mut self) -> Vec<Layouted> { fn finish(mut self) -> Vec<(BoxLayout, Gen<Align>)> {
self.finish_area(); self.finish_area();
self.layouted self.layouted
} }

View File

@ -24,9 +24,9 @@ pub struct Text {
} }
impl Layout for 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(); let mut loader = ctx.loader.borrow_mut();
vec![Layouted::Boxed( Layouted::Boxed(
shaping::shape( shaping::shape(
&mut loader, &mut loader,
&self.text, &self.text,
@ -36,7 +36,7 @@ impl Layout for Text {
self.variant, self.variant,
), ),
self.aligns, self.aligns,
)] )
} }
} }