summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2023-02-12 16:40:00 +0100
committerLaurenz <laurmaedje@gmail.com>2023-02-12 16:40:00 +0100
commit697ae1f925f1be80b34c1da697ba8db7327a6b61 (patch)
tree21193e849497de236e5034a2ff01a94067c6cfec
parentebbee6274cafa6865a0d9123b78cae305c3c12aa (diff)
Extract regions into separate module
-rw-r--r--library/src/layout/mod.rs123
-rw-r--r--library/src/layout/regions.rs123
2 files changed, 125 insertions, 121 deletions
diff --git a/library/src/layout/mod.rs b/library/src/layout/mod.rs
index 6c01759c..f603ef6c 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<Abs>,
- /// Whether nodes should expand to fill the regions instead of shrinking to
- /// fit the content.
- pub expand: Axes<bool>,
-}
-
-impl<'a> Regions<'a> {
- /// Create a new region sequence with exactly one region.
- pub fn one(size: Size, base: Size, expand: Axes<bool>) -> 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<bool>) -> 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<Abs>, 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<Item = Size> + '_ {
- 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 00000000..2592210b
--- /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<Abs>,
+ /// Whether nodes should expand to fill the regions instead of shrinking to
+ /// fit the content.
+ pub expand: Axes<bool>,
+}
+
+impl<'a> Regions<'a> {
+ /// Create a new region sequence with exactly one region.
+ pub fn one(size: Size, base: Size, expand: Axes<bool>) -> 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<bool>) -> 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<Abs>, 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<Item = Size> + '_ {
+ 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()
+ }
+}