From 697ae1f925f1be80b34c1da697ba8db7327a6b61 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Sun, 12 Feb 2023 16:40:00 +0100 Subject: [PATCH] Extract regions into separate module --- library/src/layout/mod.rs | 123 +--------------------------------- library/src/layout/regions.rs | 123 ++++++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+), 121 deletions(-) create mode 100644 library/src/layout/regions.rs diff --git a/library/src/layout/mod.rs b/library/src/layout/mod.rs index 6c01759cb..f603ef6c1 100644 --- a/library/src/layout/mod.rs +++ b/library/src/layout/mod.rs @@ -14,6 +14,7 @@ mod pad; mod page; mod par; mod place; +mod regions; mod repeat; mod spacing; mod stack; @@ -34,6 +35,7 @@ pub use self::pad::*; pub use self::page::*; pub use self::par::*; pub use self::place::*; +pub use self::regions::*; pub use self::repeat::*; pub use self::spacing::*; pub use self::stack::*; @@ -45,7 +47,6 @@ use std::mem; use typed_arena::Arena; use typst::diag::SourceResult; -use typst::geom::*; use typst::model::{ applicable, capability, realize, Content, Node, SequenceNode, Style, StyleChain, StyleVecBuilder, StyledNode, @@ -147,126 +148,6 @@ impl Layout for Content { #[capability] pub trait Inline: Layout {} -/// A sequence of regions to layout into. -#[derive(Copy, Clone, Hash)] -pub struct Regions<'a> { - /// The (remaining) size of the first region. - pub first: Size, - /// The base size for relative sizing. - pub base: Size, - /// The height of followup regions. The width is the same for all regions. - pub backlog: &'a [Abs], - /// The height of the final region that is repeated once the backlog is - /// drained. The width is the same for all regions. - pub last: Option, - /// Whether nodes should expand to fill the regions instead of shrinking to - /// fit the content. - pub expand: Axes, -} - -impl<'a> Regions<'a> { - /// Create a new region sequence with exactly one region. - pub fn one(size: Size, base: Size, expand: Axes) -> Self { - Self { - first: size, - base, - backlog: &[], - last: None, - expand, - } - } - - /// Create a new sequence of same-size regions that repeats indefinitely. - pub fn repeat(size: Size, base: Size, expand: Axes) -> Self { - Self { - first: size, - base, - backlog: &[], - last: Some(size.y), - expand, - } - } - - /// Create new regions where all sizes are mapped with `f`. - /// - /// Note that since all regions must have the same width, the width returned - /// by `f` is ignored for the backlog and the final region. - pub fn map<'v, F>(&self, backlog: &'v mut Vec, mut f: F) -> Regions<'v> - where - F: FnMut(Size) -> Size, - { - let x = self.first.x; - backlog.clear(); - backlog.extend(self.backlog.iter().map(|&y| f(Size::new(x, y)).y)); - Regions { - first: f(self.first), - base: f(self.base), - backlog, - last: self.last.map(|y| f(Size::new(x, y)).y), - expand: self.expand, - } - } - - /// Whether the first region is full and a region break is called for. - pub fn is_full(&self) -> bool { - Abs::zero().fits(self.first.y) && !self.in_last() - } - - /// Whether the first region is the last usable region. - /// - /// If this is true, calling `next()` will have no effect. - pub fn in_last(&self) -> bool { - self.backlog.is_empty() && self.last.map_or(true, |height| self.first.y == height) - } - - /// Advance to the next region if there is any. - pub fn next(&mut self) { - if let Some(height) = self - .backlog - .split_first() - .map(|(first, tail)| { - self.backlog = tail; - *first - }) - .or(self.last) - { - self.first.y = height; - self.base.y = height; - } - } - - /// An iterator that returns the sizes of the first and all following - /// regions, equivalently to what would be produced by calling - /// [`next()`](Self::next) repeatedly until all regions are exhausted. - /// This iterator may be infinite. - pub fn iter(&self) -> impl Iterator + '_ { - let first = std::iter::once(self.first); - let backlog = self.backlog.iter(); - let last = self.last.iter().cycle(); - first.chain(backlog.chain(last).map(|&h| Size::new(self.first.x, h))) - } -} - -impl Debug for Regions<'_> { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - f.write_str("Regions ")?; - let mut list = f.debug_list(); - let mut prev = self.first.y; - list.entry(&self.first); - for &height in self.backlog { - list.entry(&Size::new(self.first.x, height)); - prev = height; - } - if let Some(last) = self.last { - if last != prev { - list.entry(&Size::new(self.first.x, last)); - } - list.entry(&(..)); - } - list.finish() - } -} - /// Realize into a node that is capable of root-level layout. fn realize_root<'a>( vt: &mut Vt, diff --git a/library/src/layout/regions.rs b/library/src/layout/regions.rs new file mode 100644 index 000000000..2592210b0 --- /dev/null +++ b/library/src/layout/regions.rs @@ -0,0 +1,123 @@ +use std::fmt::{self, Debug, Formatter}; + +use typst::geom::{Abs, Axes, Size}; + +/// A sequence of regions to layout into. +#[derive(Copy, Clone, Hash)] +pub struct Regions<'a> { + /// The (remaining) size of the first region. + pub first: Size, + /// The base size for relative sizing. + pub base: Size, + /// The height of followup regions. The width is the same for all regions. + pub backlog: &'a [Abs], + /// The height of the final region that is repeated once the backlog is + /// drained. The width is the same for all regions. + pub last: Option, + /// Whether nodes should expand to fill the regions instead of shrinking to + /// fit the content. + pub expand: Axes, +} + +impl<'a> Regions<'a> { + /// Create a new region sequence with exactly one region. + pub fn one(size: Size, base: Size, expand: Axes) -> Self { + Self { + first: size, + base, + backlog: &[], + last: None, + expand, + } + } + + /// Create a new sequence of same-size regions that repeats indefinitely. + pub fn repeat(size: Size, base: Size, expand: Axes) -> Self { + Self { + first: size, + base, + backlog: &[], + last: Some(size.y), + expand, + } + } + + /// Create new regions where all sizes are mapped with `f`. + /// + /// Note that since all regions must have the same width, the width returned + /// by `f` is ignored for the backlog and the final region. + pub fn map<'v, F>(&self, backlog: &'v mut Vec, mut f: F) -> Regions<'v> + where + F: FnMut(Size) -> Size, + { + let x = self.first.x; + backlog.clear(); + backlog.extend(self.backlog.iter().map(|&y| f(Size::new(x, y)).y)); + Regions { + first: f(self.first), + base: f(self.base), + backlog, + last: self.last.map(|y| f(Size::new(x, y)).y), + expand: self.expand, + } + } + + /// Whether the first region is full and a region break is called for. + pub fn is_full(&self) -> bool { + Abs::zero().fits(self.first.y) && !self.in_last() + } + + /// Whether the first region is the last usable region. + /// + /// If this is true, calling `next()` will have no effect. + pub fn in_last(&self) -> bool { + self.backlog.is_empty() && self.last.map_or(true, |height| self.first.y == height) + } + + /// Advance to the next region if there is any. + pub fn next(&mut self) { + if let Some(height) = self + .backlog + .split_first() + .map(|(first, tail)| { + self.backlog = tail; + *first + }) + .or(self.last) + { + self.first.y = height; + self.base.y = height; + } + } + + /// An iterator that returns the sizes of the first and all following + /// regions, equivalently to what would be produced by calling + /// [`next()`](Self::next) repeatedly until all regions are exhausted. + /// This iterator may be infinite. + pub fn iter(&self) -> impl Iterator + '_ { + let first = std::iter::once(self.first); + let backlog = self.backlog.iter(); + let last = self.last.iter().cycle(); + first.chain(backlog.chain(last).map(|&h| Size::new(self.first.x, h))) + } +} + +impl Debug for Regions<'_> { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.write_str("Regions ")?; + let mut list = f.debug_list(); + let mut prev = self.first.y; + list.entry(&self.first); + for &height in self.backlog { + list.entry(&Size::new(self.first.x, height)); + prev = height; + } + if let Some(last) = self.last { + if last != prev { + list.entry(&Size::new(self.first.x, last)); + } + list.entry(&(..)); + } + list.finish() + } +}