summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2021-07-26 00:29:37 +0200
committerLaurenz <laurmaedje@gmail.com>2021-07-26 00:29:37 +0200
commit7aa3d2c2d6c60c9d4696bf2fb91982a5be64f9b0 (patch)
tree3fbbebbb3540294fada6fc356cd12c31825dcff8
parent56cbf96fe2b3b82d34b2e69a49bcb7b0c0267f6a (diff)
No more excessive region cloning
-rw-r--r--src/layout/incremental.rs33
-rw-r--r--src/layout/mod.rs15
-rw-r--r--src/layout/tree.rs2
-rw-r--r--tests/typeset.rs5
4 files changed, 33 insertions, 22 deletions
diff --git a/src/layout/incremental.rs b/src/layout/incremental.rs
index e5bad892..60486d2f 100644
--- a/src/layout/incremental.rs
+++ b/src/layout/incremental.rs
@@ -50,11 +50,11 @@ impl LayoutCache {
pub fn get(
&mut self,
hash: u64,
- regions: Regions,
+ regions: &Regions,
) -> Option<Vec<Constrained<Rc<Frame>>>> {
let entries = self.frames.get_mut(&hash)?;
for entry in entries {
- if let Some(frames) = entry.check(regions.clone()) {
+ if let Some(frames) = entry.check(regions) {
return Some(frames);
}
}
@@ -136,9 +136,11 @@ impl FramesEntry {
/// Checks if the cached frames are valid in the given regions and returns
/// them if so.
- pub fn check(&mut self, mut regions: Regions) -> Option<Vec<Constrained<Rc<Frame>>>> {
- for (i, frame) in self.frames.iter().enumerate() {
- if (i != 0 && !regions.next()) || !frame.constraints.check(&regions) {
+ pub fn check(&mut self, regions: &Regions) -> Option<Vec<Constrained<Rc<Frame>>>> {
+ let mut iter = regions.iter();
+ for frame in &self.frames {
+ let (current, base) = iter.next()?;
+ if !frame.constraints.check(current, base, regions.expand) {
return None;
}
}
@@ -175,11 +177,13 @@ impl FramesEntry {
}
}
-/// Carries an item that only applies to certain regions and the constraints
+/// Carries an item that is only valid in certain regions and the constraints
/// that describe these regions.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct Constrained<T> {
+ /// The item that is only valid if the constraints are fullfilled.
pub item: T,
+ /// Constraints on regions in which the item is valid.
pub constraints: Constraints,
}
@@ -218,16 +222,13 @@ impl Constraints {
}
}
- #[cfg(feature = "layout-cache")]
- fn check(&self, regions: &Regions) -> bool {
- if self.expand != regions.expand {
- return false;
- }
-
- let base = regions.base.to_spec();
- let current = regions.current.to_spec();
-
- current.eq_by(&self.min, |x, y| y.map_or(true, |y| x.fits(y)))
+ /// Check whether the constraints are fullfilled in a region with the given
+ /// properties.
+ pub fn check(&self, current: Size, base: Size, expand: Spec<bool>) -> bool {
+ let current = current.to_spec();
+ let base = base.to_spec();
+ self.expand == expand
+ && current.eq_by(&self.min, |x, y| y.map_or(true, |y| x.fits(y)))
&& current.eq_by(&self.max, |x, y| y.map_or(true, |y| x < &y))
&& current.eq_by(&self.exact, |x, y| y.map_or(true, |y| x.approx_eq(y)))
&& base.eq_by(&self.base, |x, y| y.map_or(true, |y| x.approx_eq(y)))
diff --git a/src/layout/mod.rs b/src/layout/mod.rs
index 22e6e8c8..0f88d150 100644
--- a/src/layout/mod.rs
+++ b/src/layout/mod.rs
@@ -140,14 +140,21 @@ impl Regions {
self.backlog.is_empty() && self.last.map_or(true, |size| self.current == size)
}
+ /// An iterator that returns pairs of `(current, base)` that are equivalent
+ /// to what would be produced by calling [`next()`](Self::next) repeatedly
+ /// until all regions are exhausted.
+ pub fn iter(&self) -> impl Iterator<Item = (Size, Size)> + '_ {
+ let first = std::iter::once((self.current, self.base));
+ let backlog = self.backlog.iter().rev();
+ let last = self.last.iter().cycle();
+ first.chain(backlog.chain(last).map(|&s| (s, s)))
+ }
+
/// Advance to the next region if there is any.
- pub fn next(&mut self) -> bool {
+ pub fn next(&mut self) {
if let Some(size) = self.backlog.pop().or(self.last) {
self.current = size;
self.base = size;
- true
- } else {
- false
}
}
diff --git a/src/layout/tree.rs b/src/layout/tree.rs
index 77b01ad2..4b21e05c 100644
--- a/src/layout/tree.rs
+++ b/src/layout/tree.rs
@@ -86,7 +86,7 @@ impl Layout for LayoutNode {
return self.node.layout(ctx, regions);
#[cfg(feature = "layout-cache")]
- ctx.layouts.get(self.hash, regions.clone()).unwrap_or_else(|| {
+ ctx.layouts.get(self.hash, regions).unwrap_or_else(|| {
ctx.level += 1;
let frames = self.node.layout(ctx, regions);
ctx.level -= 1;
diff --git a/tests/typeset.rs b/tests/typeset.rs
index 59eb008f..3e83fcb5 100644
--- a/tests/typeset.rs
+++ b/tests/typeset.rs
@@ -16,12 +16,15 @@ use typst::eval::{eval, Scope, Value};
use typst::exec::{exec, State};
use typst::geom::{self, Length, PathElement, Point, Sides, Size};
use typst::image::ImageId;
-use typst::layout::{layout, Element, Frame, Geometry, LayoutTree, Paint, Text};
+use typst::layout::{layout, Element, Frame, Geometry, Paint, Text};
use typst::loading::{FileId, FsLoader};
use typst::parse::{parse, LineMap, Scanner};
use typst::syntax::{Location, Pos};
use typst::Context;
+#[cfg(feature = "layout-cache")]
+use typst::layout::LayoutTree;
+
const TYP_DIR: &str = "./typ";
const REF_DIR: &str = "./ref";
const PNG_DIR: &str = "./png";