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> {
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()
}
}

View File

@ -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),

View File

@ -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(),
}
}
}

View File

@ -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),

View File

@ -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)

View File

@ -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 {
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

View File

@ -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)
}
}

View File

@ -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 {
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
}

View File

@ -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,
)]
)
}
}