From fec1f41106862617797abf65d4eba8061cf4497b Mon Sep 17 00:00:00 2001 From: Martin Date: Sat, 12 Jun 2021 18:19:18 +0200 Subject: [PATCH] Allow grid cells to span multiple regions. (#30) --- src/geom/length.rs | 6 +- src/layout/grid.rs | 290 ++++++++++++++++++++++++++++-------- src/layout/mod.rs | 28 ++++ src/library/grid.rs | 4 +- tests/ref/layout/grid-3.png | Bin 0 -> 44758 bytes tests/typ/layout/grid-1.typ | 4 +- tests/typ/layout/grid-3.typ | 79 ++++++++++ 7 files changed, 346 insertions(+), 65 deletions(-) create mode 100644 tests/ref/layout/grid-3.png create mode 100644 tests/typ/layout/grid-3.typ diff --git a/src/geom/length.rs b/src/geom/length.rs index e9ba0853b..21843d3e8 100644 --- a/src/geom/length.rs +++ b/src/geom/length.rs @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize}; use super::*; /// An absolute length. -#[derive(Default, Copy, Clone, PartialEq, PartialOrd, Hash)] +#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] #[derive(Serialize, Deserialize)] #[serde(transparent)] pub struct Length { @@ -85,7 +85,7 @@ impl Length { /// Set to the minimum of this and another length. pub fn set_min(&mut self, other: Self) { - *self = self.min(other); + *self = (*self).min(other); } /// The maximum of this and another length. @@ -95,7 +95,7 @@ impl Length { /// Set to the maximum of this and another length. pub fn set_max(&mut self, other: Self) { - *self = self.max(other); + *self = (*self).max(other); } /// Whether the other length fits into this one (i.e. is smaller). diff --git a/src/layout/grid.rs b/src/layout/grid.rs index 3ba6c16bd..64c330977 100644 --- a/src/layout/grid.rs +++ b/src/layout/grid.rs @@ -25,6 +25,7 @@ impl From for AnyNode { } } +#[derive(Debug)] struct GridLayouter<'a> { cross: SpecAxis, main: SpecAxis, @@ -32,11 +33,12 @@ struct GridLayouter<'a> { rows: Vec, cells: Vec>, regions: Regions, - rrows: Vec<(usize, Option)>, + rrows: Vec<(usize, Option, Option>>)>, rcols: Vec, finished: Vec, } +#[derive(Debug)] enum Cell<'a> { Node(&'a AnyNode), Gutter, @@ -233,95 +235,263 @@ impl<'a> GridLayouter<'a> { for y in 0 .. self.rows.len() { let resolved = match self.rows[y] { TrackSizing::Linear(l) => { - Some(l.resolve(self.regions.base.get(self.main))) + (Some(l.resolve(self.regions.base.get(self.main))), None) } TrackSizing::Auto => { let mut max = Length::zero(); - for (x, len) in self.rcols.iter().enumerate() { + let mut local_max = max; + let mut multi_region = false; + let mut last_size = vec![]; + for (x, &col_size) in self.rcols.iter().enumerate() { if let Cell::Node(node) = self.get(x, y) { - let regions = Regions::one( - Gen::new(*len, current).to_size(self.main), - Spec::splat(false), - ); - let frame = node.layout(ctx, ®ions).remove(0); - max = max.max(frame.size.get(self.main)); + let colsize = Gen::new(col_size, current).to_size(self.main); + + let mut regions = self.regions.map(|mut s| { + *s.get_mut(self.cross) = col_size; + s + }); + + regions.base = colsize; + regions.current = colsize; + regions.expand = Spec::splat(false); + + let mut frames = node.layout(ctx, ®ions); + multi_region |= frames.len() > 1; + last_size.push(( + frames.len() - 1, + frames.last().unwrap().size.get(self.main), + )); + let frame = frames.remove(0); + local_max = local_max.max(frame.size.get(self.main)); + + if !multi_region { + max = local_max; + } + } else { + last_size.push((0, Length::zero())) } } - Some(max) + + let overshoot = if multi_region { + self.rrows.push((y, Some(local_max), None)); + let res = self.finish_region(ctx, total_frs, Some(last_size)); + max = if let Some(overflow) = res.as_ref() { + overflow.iter() + .filter_map(|x| x.as_ref()) + .map(|x| x.size.get(self.main)) + .max() + .unwrap_or(Length::zero()) + } else { + local_max + }; + + current = self.regions.current.get(self.main); + total_frs = 0.0; + if res.is_none() { + continue; + } + + res + } else { + None + }; + + // If multi-region results: finish_regions, returning + // the last non-set frames. + (Some(max), overshoot) } TrackSizing::Fractional(f) => { total_frs += f.get(); - None + (None, None) } }; - if let Some(resolved) = resolved { + if let (Some(resolved), _) = resolved { while !current.fits(resolved) && !self.regions.in_full_last() { - self.finish_region(ctx, total_frs); + self.finish_region(ctx, total_frs, None); current = self.regions.current.get(self.main); total_frs = 0.0; } current -= resolved; } - self.rrows.push((y, resolved)); + self.rrows.push((y, resolved.0, resolved.1)); } - self.finish_region(ctx, total_frs); + self.finish_region(ctx, total_frs, None); self.finished } - fn finish_region(&mut self, ctx: &mut LayoutContext, total_frs: f64) { - let mut pos = Gen::splat(Length::zero()); - let mut frame = Frame::new(Size::zero(), Length::zero()); - let mut total_cross = Length::zero(); - let mut total_main = Length::zero(); - - for (x, &w) in self.rcols.iter().enumerate() { - let total: Length = self.rrows.iter().filter_map(|(_, x)| *x).sum(); - let available = self.regions.current.get(self.main) - total; - total_cross += w; - - for (y, h) in self.rrows.iter() { - let element = self.get(x, *y); - let h = if let Some(len) = h { - *len - } else if let TrackSizing::Fractional(f) = self.rows[*y] { - if total_frs > 0.0 { - let res = available * (f.get() / total_frs); - if res.is_finite() { res } else { Length::zero() } - } else { - Length::zero() - } - } else { - unreachable!("non-fractional tracks are already resolved"); - }; - - if x == 0 { - total_main += h; - } - - if let Cell::Node(n) = element { - let regions = Regions::one( - Gen::new(w, h).to_size(self.main), - Spec::splat(false), - ); - let item = n.layout(ctx, ®ions).remove(0); - frame.push_frame(pos.to_point(self.main), item); - } - - pos.main += h; - } - pos.main = Length::zero(); - pos.cross += w; + fn finish_region( + &mut self, + ctx: &mut LayoutContext, + total_frs: f64, + multiregion_sizing: Option>, + ) -> Option>> { + if self.rrows.is_empty() { + return None; } + let mut pos = Gen::splat(Length::zero()); + let frame = Frame::new(Size::zero(), Length::zero()); + let mut total_cross = Length::zero(); + let mut total_main = Length::zero(); + let mut max_regions = 0; + let mut collected_frames = if multiregion_sizing.is_some() { + Some(vec![None; self.rcols.len()]) + } else { + None + }; + + self.finished.push(frame); + + let frame_len = self.finished.len(); + + let total_row_height: Length = self.rrows.iter().filter_map(|(_, x, _)| *x).sum(); + + for &(y, h, ref layouted) in self.rrows.iter().as_ref() { + let last = self.rrows.last().map_or(false, |(o, _, _)| &y == o); + let available = self.regions.current.get(self.main) - total_row_height; + let h = if let Some(len) = h { + len + } else if let TrackSizing::Fractional(f) = self.rows[y] { + if total_frs > 0.0 { + let res = available * (f.get() / total_frs); + if res.is_finite() { res } else { Length::zero() } + } else { + Length::zero() + } + } else { + unreachable!("non-fractional tracks are already resolved"); + }; + total_main += h; + + if let Some(layouted) = layouted { + + for (col_index, frame) in layouted.into_iter().enumerate() { + if let Some(frame) = frame { + self.finished + .get_mut(frame_len - 1) + .unwrap() + .push_frame(pos.to_point(self.main), frame.clone()); + } + pos.cross += self.rcols[col_index]; + } + } else { + let mut overshoot_columns = vec![]; + for (x, &w) in self.rcols.iter().enumerate() { + let element = self.get(x, y); + + if y == 0 { + total_cross += w; + } + + if let Cell::Node(n) = element { + let region_size = Gen::new(w, h).to_size(self.main); + let regions = if last { + if let Some(last_sizes) = multiregion_sizing.as_ref() { + let mut regions = self.regions.map(|mut s| { + *s.get_mut(self.cross) = w; + s + }); + + regions.base = region_size; + regions.current = region_size; + regions.expand = Spec::splat(true); + + let (last_region, last_size) = last_sizes[x]; + regions.unique_regions(last_region + 1); + *regions.nth_mut(last_region).unwrap().get_mut(self.main) = last_size; + regions + } else { + Regions::one(region_size, Spec::splat(true)) + } + } else { + Regions::one(region_size, Spec::splat(true)) + }; + let mut items = n.layout(ctx, ®ions); + let item = items.remove(0); + + if last && multiregion_sizing.is_some() { + max_regions = max_regions.max(items.len()); + overshoot_columns.push((x, items)); + } else { + assert_eq!(items.len(), 0); + } + + self.finished + .get_mut(frame_len - 1) + .unwrap() + .push_frame(pos.to_point(self.main), item); + } + + pos.cross += w; + } + + if overshoot_columns.iter().any(|(_, items)| !items.is_empty()) { + for (x, col) in overshoot_columns { + let mut cross_offset = Length::zero(); + for col in 0..x { + cross_offset += self.rcols[col]; + } + + + let collected_frames = collected_frames.as_mut().unwrap(); + *collected_frames.get_mut(x).unwrap() = + col.get(max_regions - 1).cloned(); + + for (cell_index, subcell) in col.into_iter().enumerate() { + if cell_index >= max_regions - 1 { + continue; + } + let frame = if let Some(frame) = + self.finished.get_mut(frame_len + cell_index) + { + frame + } else { + let frame = Frame::new(Size::zero(), Length::zero()); + // The previous frame always exists: either the + // last iteration created it or it is the normal + // frame. + self.finished.push(frame); + self.finished.last_mut().unwrap() + }; + let pos = Gen::new(cross_offset, Length::zero()); + frame + .size + .get_mut(self.cross) + .set_max(pos.cross + subcell.size.get(self.cross)); + frame + .size + .get_mut(self.main) + .set_max(subcell.size.get(self.main)); + frame.baseline = frame.size.height; + frame.push_frame(pos.to_point(self.main), subcell); + } + } + } + } + + pos.cross = Length::zero(); + pos.main += h; + } + + let frame = self.finished.get_mut(frame_len - 1).unwrap(); frame.size = Gen::new(total_cross, total_main).to_size(self.main); frame.baseline = frame.size.height; self.rrows.clear(); - self.regions.next(); - self.finished.push(frame); + for _ in 0 .. (max_regions.max(1)) { + self.regions.next(); + } + + if let Some(frames) = collected_frames.as_ref() { + if frames.iter().all(|i| i.is_none()) { + collected_frames = None; + } + } + + collected_frames } fn get(&self, x: usize, y: usize) -> &Cell<'a> { diff --git a/src/layout/mod.rs b/src/layout/mod.rs index 4153fc3cd..6f536e20d 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -280,4 +280,32 @@ impl Regions { let height = width / aspect.into_inner(); self.current = Size::new(width, height); } + + /// Appends new elements to the backlog such that the behavior of `next` + /// does not change. Panics when used with finite regions. + pub fn backlogify(&mut self, count: usize) { + for _ in 0 .. count { + self.backlog.push(self.last.unwrap()) + } + } + + /// Ensures that enough unique regions are present, including the current + /// and last ones. Panics when used with finite regions. + pub fn unique_regions(&mut self, count: usize) { + if self.backlog.len() < count.max(2) - 2 { + self.backlogify((count - 2) - self.backlog.len()); + } + } + + /// Returns a mutable reference to the size of the `n`th region. + pub fn nth_mut(&mut self, n: usize) -> Option<&mut Size> { + let backlog_len = self.backlog.len(); + if n == 0 { + Some(&mut self.current) + } else if n <= backlog_len { + self.backlog.get_mut(backlog_len - n) + } else { + self.last.as_mut() + } + } } diff --git a/src/library/grid.rs b/src/library/grid.rs index 79070e796..192dee9dd 100644 --- a/src/library/grid.rs +++ b/src/library/grid.rs @@ -36,7 +36,9 @@ pub fn grid(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { let columns = args.eat_named::(ctx, "columns").unwrap_or_default(); let rows = args.eat_named::(ctx, "rows").unwrap_or_default(); let column_dir = args.eat_named(ctx, "column-dir"); - let gutter = args.eat_named::(ctx, "gutter").unwrap_or_default(); + let gutter = args.eat_named::(ctx, "gutter") + .map(|v| Tracks(vec![TrackSizing::Linear(v)])) + .unwrap_or_default(); let gutter_columns = args.eat_named::(ctx, "gutter-columns"); let gutter_rows = args.eat_named::(ctx, "gutter-rows"); let children = args.eat_all::(ctx); diff --git a/tests/ref/layout/grid-3.png b/tests/ref/layout/grid-3.png new file mode 100644 index 0000000000000000000000000000000000000000..ec37e46e24436b149db224726e23a43ce89f0cb9 GIT binary patch literal 44758 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 L&?q^7CH(&Y?69GU literal 0 HcmV?d00001 diff --git a/tests/typ/layout/grid-1.typ b/tests/typ/layout/grid-1.typ index 6a4aee870..827a98a72 100644 --- a/tests/typ/layout/grid-1.typ +++ b/tests/typ/layout/grid-1.typ @@ -25,7 +25,8 @@ --- #grid( columns: (auto, auto, 40%), - gutter: (1fr,), + gutter-columns: (1fr,), + gutter-rows: (1fr,), rect(fill: eastern)[dddaa aaa aaa], rect(fill: conifer)[ccc], rect(width: 100%, fill: #dddddd)[aaa], @@ -52,3 +53,4 @@ rows: (1fr, auto, 2fr), [], rect(width: 100%)[A bit more to the top], [], ) + diff --git a/tests/typ/layout/grid-3.typ b/tests/typ/layout/grid-3.typ new file mode 100644 index 000000000..6ef0ab831 --- /dev/null +++ b/tests/typ/layout/grid-3.typ @@ -0,0 +1,79 @@ +// Test grid cells that overflow to the next region. + +--- +#page(width: 5cm, height: 3cm) +#grid( + columns: 2, + gutter-rows: 3 * (8pt,), + [Lorem ipsum dolor sit amet, consectetuer adipiscing elit. + + Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis.], + [Text that is rather short], + [Fireflies], + [Critical], + [Decorum], + [Rampage], +) + +--- +// Test a column that starts overflowing right after another row/column did +// that. +#page(width: 5cm, height: 2cm) +#grid( + columns: 4 * (1fr,), + gutter-rows: (10pt,), + gutter-columns: (0pt, 10%), + image("../../res/rhino.png"), + align(right, rect(width: 100%, fill: eastern)[LoL]), + "rofl", + "\nA" * 3, + "Ha!\n" * 3, +) + +--- +// Test two columns in the same row overflowing by a different amount. +#page(width: 5cm, height: 2cm) +#grid( + columns: 3 * (1fr,), + gutter-rows: (8pt,), + gutter-columns: (0pt, 10%), + [A], [B], [C], + "Ha!\n" * 6, + "rofl", + "\nA" * 3, + [hello], + [darkness], + [my old] +) + +--- +// Test grid within a grid, overflowing. +#page(width: 5cm, height: 2.25cm) +#grid( + columns: 4 * (1fr,), + gutter-rows: (10pt,), + gutter-columns: (0pt, 10%), + [A], [B], [C], [D], + grid(columns: 2, [A], [B], "C\n"*3, [D]), + align(right, rect(width: 100%, fill: eastern)[LoL]), + "rofl", + "E\n"*4, +) + +--- +// Test partition of `fr` units before and after multi-region layout. +#page(width: 5cm, height: 4cm) +#grid( + columns: 2 * (1fr,), + rows: (1fr, 2fr, auto, 1fr, 1cm), + gutter-rows: 4 * (10pt,), + rect(height: 100%, width: 100%, fill: #ff0000)[No height], + [foo], + rect(height: 100%, width: 100%, fill: #fc0030)[Still no height], + [bar], + [The nature of being itself is in question. Am I One? Am I Many? What is being alive?], + [baz], + [The answer], + [42], + [Other text of interest], +)