mirror of
https://github.com/typst/typst
synced 2025-05-13 20:46:23 +08:00
No more excessive region cloning
This commit is contained in:
parent
56cbf96fe2
commit
7aa3d2c2d6
@ -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(®ions) {
|
||||
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)))
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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";
|
||||
|
Loading…
x
Reference in New Issue
Block a user