mirror of
https://github.com/typst/typst
synced 2025-05-14 04:56:26 +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(
|
pub fn get(
|
||||||
&mut self,
|
&mut self,
|
||||||
hash: u64,
|
hash: u64,
|
||||||
regions: Regions,
|
regions: &Regions,
|
||||||
) -> Option<Vec<Constrained<Rc<Frame>>>> {
|
) -> Option<Vec<Constrained<Rc<Frame>>>> {
|
||||||
let entries = self.frames.get_mut(&hash)?;
|
let entries = self.frames.get_mut(&hash)?;
|
||||||
for entry in entries {
|
for entry in entries {
|
||||||
if let Some(frames) = entry.check(regions.clone()) {
|
if let Some(frames) = entry.check(regions) {
|
||||||
return Some(frames);
|
return Some(frames);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -136,9 +136,11 @@ impl FramesEntry {
|
|||||||
|
|
||||||
/// Checks if the cached frames are valid in the given regions and returns
|
/// Checks if the cached frames are valid in the given regions and returns
|
||||||
/// them if so.
|
/// them if so.
|
||||||
pub fn check(&mut self, mut regions: Regions) -> Option<Vec<Constrained<Rc<Frame>>>> {
|
pub fn check(&mut self, regions: &Regions) -> Option<Vec<Constrained<Rc<Frame>>>> {
|
||||||
for (i, frame) in self.frames.iter().enumerate() {
|
let mut iter = regions.iter();
|
||||||
if (i != 0 && !regions.next()) || !frame.constraints.check(®ions) {
|
for frame in &self.frames {
|
||||||
|
let (current, base) = iter.next()?;
|
||||||
|
if !frame.constraints.check(current, base, regions.expand) {
|
||||||
return None;
|
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.
|
/// that describe these regions.
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
pub struct Constrained<T> {
|
pub struct Constrained<T> {
|
||||||
|
/// The item that is only valid if the constraints are fullfilled.
|
||||||
pub item: T,
|
pub item: T,
|
||||||
|
/// Constraints on regions in which the item is valid.
|
||||||
pub constraints: Constraints,
|
pub constraints: Constraints,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,16 +222,13 @@ impl Constraints {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "layout-cache")]
|
/// Check whether the constraints are fullfilled in a region with the given
|
||||||
fn check(&self, regions: &Regions) -> bool {
|
/// properties.
|
||||||
if self.expand != regions.expand {
|
pub fn check(&self, current: Size, base: Size, expand: Spec<bool>) -> bool {
|
||||||
return false;
|
let current = current.to_spec();
|
||||||
}
|
let base = base.to_spec();
|
||||||
|
self.expand == expand
|
||||||
let base = regions.base.to_spec();
|
&& current.eq_by(&self.min, |x, y| y.map_or(true, |y| x.fits(y)))
|
||||||
let current = regions.current.to_spec();
|
|
||||||
|
|
||||||
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.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)))
|
&& 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)))
|
&& 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)
|
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.
|
/// 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) {
|
if let Some(size) = self.backlog.pop().or(self.last) {
|
||||||
self.current = size;
|
self.current = size;
|
||||||
self.base = size;
|
self.base = size;
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ impl Layout for LayoutNode {
|
|||||||
return self.node.layout(ctx, regions);
|
return self.node.layout(ctx, regions);
|
||||||
|
|
||||||
#[cfg(feature = "layout-cache")]
|
#[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;
|
ctx.level += 1;
|
||||||
let frames = self.node.layout(ctx, regions);
|
let frames = self.node.layout(ctx, regions);
|
||||||
ctx.level -= 1;
|
ctx.level -= 1;
|
||||||
|
@ -16,12 +16,15 @@ use typst::eval::{eval, Scope, Value};
|
|||||||
use typst::exec::{exec, State};
|
use typst::exec::{exec, State};
|
||||||
use typst::geom::{self, Length, PathElement, Point, Sides, Size};
|
use typst::geom::{self, Length, PathElement, Point, Sides, Size};
|
||||||
use typst::image::ImageId;
|
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::loading::{FileId, FsLoader};
|
||||||
use typst::parse::{parse, LineMap, Scanner};
|
use typst::parse::{parse, LineMap, Scanner};
|
||||||
use typst::syntax::{Location, Pos};
|
use typst::syntax::{Location, Pos};
|
||||||
use typst::Context;
|
use typst::Context;
|
||||||
|
|
||||||
|
#[cfg(feature = "layout-cache")]
|
||||||
|
use typst::layout::LayoutTree;
|
||||||
|
|
||||||
const TYP_DIR: &str = "./typ";
|
const TYP_DIR: &str = "./typ";
|
||||||
const REF_DIR: &str = "./ref";
|
const REF_DIR: &str = "./ref";
|
||||||
const PNG_DIR: &str = "./png";
|
const PNG_DIR: &str = "./png";
|
||||||
|
Loading…
x
Reference in New Issue
Block a user