From b22ce6f8b84e0a75d162feb6f3699e26f86f2453 Mon Sep 17 00:00:00 2001 From: Martin Haug Date: Sat, 18 Dec 2021 18:04:26 +0100 Subject: [PATCH] Introduce equal-width columns --- src/eval/node.rs | 12 ++- src/library/columns.rs | 157 +++++++++++++++++++++++++++++++++++ src/library/flow.rs | 24 ++++-- src/library/mod.rs | 4 + src/library/page.rs | 22 ++++- tests/ref/layout/columns.png | Bin 0 -> 42011 bytes tests/typ/layout/columns.typ | 97 ++++++++++++++++++++++ 7 files changed, 305 insertions(+), 11 deletions(-) create mode 100644 src/library/columns.rs create mode 100644 tests/ref/layout/columns.png create mode 100644 tests/typ/layout/columns.typ diff --git a/src/eval/node.rs b/src/eval/node.rs index 34a4f275..d5b67adb 100644 --- a/src/eval/node.rs +++ b/src/eval/node.rs @@ -32,6 +32,8 @@ pub enum Node { Linebreak, /// A paragraph break. Parbreak, + /// A column break. + Colbreak, /// A page break. Pagebreak, /// Plain text. @@ -212,6 +214,14 @@ impl Packer { // paragraph. self.parbreak(Some(styles)); } + Node::Colbreak => { + // Explicit column breaks end the current paragraph and then + // discards the paragraph break. + self.parbreak(None); + self.make_flow_compatible(&styles); + self.flow.children.push(FlowChild::Skip); + self.flow.last.hard(); + } Node::Pagebreak => { // We must set the flow styles after the page break such that an // empty page created by two page breaks in a row has styles at @@ -345,7 +355,7 @@ impl Packer { // Take the flow and erase any styles that will be inherited anyway. let Builder { mut children, styles, .. } = mem::take(&mut self.flow); for child in &mut children { - child.styles_mut().erase(&styles); + child.styles_mut().map(|s| s.erase(&styles)); } let flow = FlowNode(children).pack(); diff --git a/src/library/columns.rs b/src/library/columns.rs new file mode 100644 index 00000000..88ad8172 --- /dev/null +++ b/src/library/columns.rs @@ -0,0 +1,157 @@ +use super::prelude::*; +use super::ParNode; + +/// `columns`: Stack children along an axis. +pub fn columns(_: &mut EvalContext, args: &mut Args) -> TypResult { + let count = args.expect("column count")?; + let gutter = args.named("gutter")?.unwrap_or(Relative::new(0.04).into()); + let body: Node = args.expect("body")?; + + Ok(Value::block(ColumnsNode { + columns: count, + gutter, + child: body.into_block(), + })) +} + +/// `colbreak`: Start a new column. +pub fn colbreak(_: &mut EvalContext, _: &mut Args) -> TypResult { + Ok(Value::Node(Node::Colbreak)) +} + +/// A node that separates a region into multiple equally sized columns. +#[derive(Debug, Hash)] +pub struct ColumnsNode { + /// How many columns there should be. + pub columns: usize, + /// The size of the gutter space between each column. + pub gutter: Linear, + /// The child to be layouted into the columns. Most likely, this should be a + /// flow or stack node. + pub child: PackedNode, +} + +impl Layout for ColumnsNode { + fn layout( + &self, + ctx: &mut LayoutContext, + regions: &Regions, + ) -> Vec>> { + // Separating the infinite space into infinite columns does not make + // much sense. + if regions.current.x.is_infinite() { + return self.child.layout(ctx, regions); + } + + // All gutters in the document. (Can be different because the relative + // component is calculated seperately for each region.) + let mut gutters = vec![]; + // Sizes of all columns resulting from `region.current` and + // `region.backlog`. + let mut sizes = vec![]; + + // Assure there is at least one column. + let columns = self.columns.max(1); + + for (current, base) in std::iter::once((regions.current, regions.base)) + .chain(regions.backlog.clone().into_iter().map(|s| (s, s))) + { + let gutter = self.gutter.resolve(base.x); + gutters.push(gutter); + let size = Spec::new( + (current.x - gutter * (columns - 1) as f64) / columns as f64, + current.y, + ); + for _ in 0 .. columns { + sizes.push(size); + } + } + + let first = sizes.remove(0); + let mut col_regions = Regions::one(first, first, regions.expand); + col_regions.backlog = sizes.clone().into_iter(); + + // We have to treat the last region separately. + let last_column_gutter = regions.last.map(|last| { + let gutter = self.gutter.resolve(last.x); + let size = Spec::new( + (last.x - gutter * (columns - 1) as f64) / columns as f64, + last.y, + ); + col_regions.last = Some(size); + (size, gutter) + }); + + let frames = self.child.layout(ctx, &col_regions); + let dir = ctx.styles.get(ParNode::DIR); + + // Dealing with infinite height areas here. + let height = if regions.current.y.is_infinite() { + frames + .iter() + .map(|frame| frame.item.size.y) + .max() + .unwrap_or(Length::zero()) + } else { + regions.current.y + }; + + let mut regions = regions.clone(); + + let to = |cursor: Length, width: Length, regions: &Regions| { + if dir.is_positive() { + cursor + } else { + regions.current.x - cursor - width + } + }; + let mut cursor = Length::zero(); + + let mut res = vec![]; + let mut frame = Frame::new(Spec::new(regions.current.x, height)); + + for (i, child_frame) in frames.into_iter().enumerate() { + let region = i / columns; + let size = std::iter::once(&first) + .chain(sizes.iter()) + .nth(i) + .copied() + .unwrap_or_else(|| last_column_gutter.unwrap().0); + + frame.push_frame( + Point::new(to(cursor, size.x, ®ions), Length::zero()), + child_frame.item, + ); + + cursor += size.x; + + if i % columns == columns - 1 { + // Refresh column height for non-infinite regions here. + let height = if regions.current.y.is_infinite() { + height + } else { + regions.current.y + }; + + regions.next(); + let old_frame = std::mem::replace( + &mut frame, + Frame::new(Spec::new(regions.current.x, height)), + ); + res.push(old_frame.constrain(Constraints::tight(®ions))); + cursor = Length::zero(); + } else { + cursor += gutters + .get(region) + .copied() + .unwrap_or_else(|| last_column_gutter.unwrap().1); + } + } + + if !frame.elements.is_empty() { + res.push(frame.constrain(Constraints::tight(®ions))); + } + + res + } +} diff --git a/src/library/flow.rs b/src/library/flow.rs index cfa761b6..ca730db1 100644 --- a/src/library/flow.rs +++ b/src/library/flow.rs @@ -32,6 +32,8 @@ impl Debug for FlowNode { pub enum FlowChild { /// A paragraph/block break. Break(Styles), + /// Skip the rest of the region and move to the next. + Skip, /// Vertical spacing between other children. Spacing(SpacingNode), /// An arbitrary node. @@ -40,20 +42,22 @@ pub enum FlowChild { impl FlowChild { /// A reference to the child's styles. - pub fn styles(&self) -> &Styles { + pub fn styles(&self) -> Option<&Styles> { match self { - Self::Break(styles) => styles, - Self::Spacing(node) => &node.styles, - Self::Node(node) => &node.styles, + Self::Break(styles) => Some(styles), + Self::Spacing(node) => Some(&node.styles), + Self::Node(node) => Some(&node.styles), + Self::Skip => None, } } /// A mutable reference to the child's styles. - pub fn styles_mut(&mut self) -> &mut Styles { + pub fn styles_mut(&mut self) -> Option<&mut Styles> { match self { - Self::Break(styles) => styles, - Self::Spacing(node) => &mut node.styles, - Self::Node(node) => &mut node.styles, + Self::Break(styles) => Some(styles), + Self::Spacing(node) => Some(&mut node.styles), + Self::Node(node) => Some(&mut node.styles), + Self::Skip => None, } } } @@ -69,6 +73,7 @@ impl Debug for FlowChild { } Self::Spacing(node) => node.fmt(f), Self::Node(node) => node.fmt(f), + Self::Skip => write!(f, "Skip"), } } } @@ -138,6 +143,9 @@ impl<'a> FlowLayouter<'a> { let amount = chain.get(ParNode::SPACING).resolve(em); self.layout_absolute(amount.into()); } + FlowChild::Skip => { + self.finish_region(); + } FlowChild::Spacing(node) => match node.kind { SpacingKind::Linear(v) => self.layout_absolute(v), SpacingKind::Fractional(v) => { diff --git a/src/library/mod.rs b/src/library/mod.rs index b2dd0dbe..313d423b 100644 --- a/src/library/mod.rs +++ b/src/library/mod.rs @@ -4,6 +4,7 @@ //! definitions. mod align; +mod columns; mod flow; mod grid; mod heading; @@ -42,6 +43,7 @@ mod prelude { pub use self::image::*; pub use align::*; +pub use columns::*; pub use flow::*; pub use grid::*; pub use heading::*; @@ -83,6 +85,7 @@ pub fn new() -> Scope { // Break and spacing functions. std.def_func("pagebreak", pagebreak); + std.def_func("colbreak", colbreak); std.def_func("parbreak", parbreak); std.def_func("linebreak", linebreak); std.def_func("h", h); @@ -96,6 +99,7 @@ pub fn new() -> Scope { std.def_func("stack", stack); std.def_func("grid", grid); std.def_func("pad", pad); + std.def_func("columns", columns); std.def_func("align", align); std.def_func("place", place); std.def_func("move", move_); diff --git a/src/library/page.rs b/src/library/page.rs index 0e690770..6585edb9 100644 --- a/src/library/page.rs +++ b/src/library/page.rs @@ -4,7 +4,7 @@ use std::fmt::{self, Display, Formatter}; use std::str::FromStr; use super::prelude::*; -use super::PadNode; +use super::{ColumnsNode, PadNode}; /// `pagebreak`: Start a new page. pub fn pagebreak(_: &mut EvalContext, _: &mut Args) -> TypResult { @@ -40,6 +40,10 @@ impl PageNode { pub const BOTTOM: Smart = Smart::Auto; /// The page's background color. pub const FILL: Option = None; + /// How many columns the page has. + pub const COLUMNS: usize = 1; + /// How many columns the page has. + pub const COLUMN_GUTTER: Linear = Relative::new(0.04).into(); } impl Construct for PageNode { @@ -76,6 +80,8 @@ impl Set for PageNode { styles.set_opt(Self::RIGHT, args.named("right")?.or(margins)); styles.set_opt(Self::BOTTOM, args.named("bottom")?.or(margins)); styles.set_opt(Self::FILL, args.named("fill")?); + styles.set_opt(Self::COLUMNS, args.named("columns")?); + styles.set_opt(Self::COLUMN_GUTTER, args.named("column-gutter")?); Ok(()) } @@ -112,8 +118,20 @@ impl PageNode { bottom: ctx.styles.get(Self::BOTTOM).unwrap_or(default.bottom), }; + let columns = ctx.styles.get(Self::COLUMNS); + let child = if ctx.styles.get(Self::COLUMNS) > 1 { + ColumnsNode { + child: self.child.clone(), + columns, + gutter: ctx.styles.get(Self::COLUMN_GUTTER), + } + .pack() + } else { + self.child.clone() + }; + // Pad the child. - let padded = PadNode { child: self.child.clone(), padding }.pack(); + let padded = PadNode { child, padding }.pack(); // Layout the child. let expand = size.map(Length::is_finite); diff --git a/tests/ref/layout/columns.png b/tests/ref/layout/columns.png new file mode 100644 index 0000000000000000000000000000000000000000..a1aee61cb7cbd36a96533acdf01a34ab16c34c44 GIT binary patch literal 42011 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 literal 0 HcmV?d00001 diff --git a/tests/typ/layout/columns.typ b/tests/typ/layout/columns.typ new file mode 100644 index 00000000..b6019a8a --- /dev/null +++ b/tests/typ/layout/columns.typ @@ -0,0 +1,97 @@ +// Test the column layouter. + +--- +// Test columns for a sized page. +#set page(height: 4.3cm, width: 7.05cm, columns: 2) + +Lorem ipsum dolor sit amet is a common blind text +and I again am in need of filling up this page so I'm +returning to this trusty tool of tangible terror. +Sure, it is not the most creative way of filling up +a page for a test but it does get the job done. + +--- +// Test the `columns` function. +#set page(width: auto) + +#rect(width: 180pt, height: 100pt, padding: 8pt, columns(2, [ + A special plight has befallen our document. + Columns in text boxes reigned down unto the soil + to waste a year's crop of rich layouts. + The columns at least were graciously balanced. +])) + +--- +// Test more than two columns. +#set page(height: 2cm, width: 7.05cm, columns: 3) +#set par(align: center) + +#circle(fill: eastern) +#circle(fill: conifer) +#circle(fill: eastern) + +--- +// Test setting a column gutter. +#set page(height: 3.25cm, width: 7.05cm, columns: 2, column-gutter: 30pt) + +#rect(width: 100%, height: 2.5cm, fill: conifer) +#rect(width: 100%, height: 2cm, fill: eastern) + +--- +// Test RTL columns. +#set page(height: 3.25cm, width: 7.05cm, columns: 2, column-gutter: 30pt) +#set text("Noto Sans Arabic", serif) +#set par(lang: "ar") + +#rect(fill: conifer, height: 8pt, width: 6pt) وتحفيز +العديد من التفاعلات الكيميائية. (DNA) من أهم الأحماض النووية التي تُشكِّل +إلى جانب كل من البروتينات والليبيدات والسكريات المتعددة +#rect(fill: eastern, height: 8pt, width: 6pt) +الجزيئات الضخمة الأربعة الضرورية للحياة. +--- +// Test the `colbreak` function. +#set page(height: 1cm, width: 7.05cm, columns: 2) + +A +#colbreak() +#colbreak() +B +#colbreak() +C + +--- +// Test an empty second column. +#set page(width: 7.05cm, columns: 2) + +#rect(width: 100%, padding: 3pt)[So there isn't anything in the second column?] + +--- +// Test columns when one of them is empty. +#set page(width: auto, columns: 3) + +The page can grow as much as it wants horizontally. + +--- +// Test columns in an infinitely wide frame. +#set page(width: 7.05cm, columns: 2) + +There can be as much content as you want in the left column +and the document will grow with it. + +#rect(fill: conifer, width: 100%, height: 30pt) + +Only an explicit #colbreak() `#colbreak()` can put content in the +second column. + +--- +// Test a page with a single column. +#set page(height: auto, width: 7.05cm, columns: 1) + +This is a normal page. Very normal. + +--- +// Test a page with zero columns. +#set page(height: auto, width: 7.05cm, columns: 0) + +This makes less sense but will still +produce a normal page.