mirror of
https://github.com/typst/typst
synced 2025-05-14 04:56:26 +08:00
Put incremental compilation behind feature
This commit is contained in:
parent
8ea05739af
commit
21d919e2d2
@ -5,9 +5,10 @@ authors = ["The Typst Project Developers"]
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["cli", "fs"]
|
default = ["cli", "fs", "layout-cache"]
|
||||||
cli = ["anyhow", "fs", "same-file"]
|
cli = ["anyhow", "fs", "same-file"]
|
||||||
fs = ["dirs", "memmap2", "same-file", "walkdir"]
|
fs = ["dirs", "memmap2", "same-file", "walkdir"]
|
||||||
|
layout-cache = []
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
members = ["bench"]
|
members = ["bench"]
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
use crate::font::FontCache;
|
use crate::font::FontCache;
|
||||||
use crate::image::ImageCache;
|
use crate::image::ImageCache;
|
||||||
|
#[cfg(feature = "layout-cache")]
|
||||||
use crate::layout::LayoutCache;
|
use crate::layout::LayoutCache;
|
||||||
use crate::loading::Loader;
|
use crate::loading::Loader;
|
||||||
|
|
||||||
@ -12,6 +13,7 @@ pub struct Cache {
|
|||||||
/// Caches decoded images.
|
/// Caches decoded images.
|
||||||
pub image: ImageCache,
|
pub image: ImageCache,
|
||||||
/// Caches layouting artifacts.
|
/// Caches layouting artifacts.
|
||||||
|
#[cfg(feature = "layout-cache")]
|
||||||
pub layout: LayoutCache,
|
pub layout: LayoutCache,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -21,6 +23,7 @@ impl Cache {
|
|||||||
Self {
|
Self {
|
||||||
font: FontCache::new(loader),
|
font: FontCache::new(loader),
|
||||||
image: ImageCache::new(),
|
image: ImageCache::new(),
|
||||||
|
#[cfg(feature = "layout-cache")]
|
||||||
layout: LayoutCache::new(),
|
layout: LayoutCache::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
/// A node that places a rectangular filled background behind its child.
|
/// A node that places a rectangular filled background behind its child.
|
||||||
#[derive(Debug, Clone, PartialEq, Hash)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "layout-cache", derive(Hash))]
|
||||||
pub struct BackgroundNode {
|
pub struct BackgroundNode {
|
||||||
/// The kind of shape to use as a background.
|
/// The kind of shape to use as a background.
|
||||||
pub shape: BackgroundShape,
|
pub shape: BackgroundShape,
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
/// A node that can fix its child's width and height.
|
/// A node that can fix its child's width and height.
|
||||||
#[derive(Debug, Clone, PartialEq, Hash)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "layout-cache", derive(Hash))]
|
||||||
pub struct FixedNode {
|
pub struct FixedNode {
|
||||||
/// The fixed width, if any.
|
/// The fixed width, if any.
|
||||||
pub width: Option<Linear>,
|
pub width: Option<Linear>,
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
/// A node that arranges its children in a grid.
|
/// A node that arranges its children in a grid.
|
||||||
#[derive(Debug, Clone, PartialEq, Hash)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "layout-cache", derive(Hash))]
|
||||||
pub struct GridNode {
|
pub struct GridNode {
|
||||||
/// The `main` and `cross` directions of this grid.
|
/// The `main` and `cross` directions of this grid.
|
||||||
///
|
///
|
||||||
|
@ -4,7 +4,8 @@ use crate::image::ImageId;
|
|||||||
use ::image::GenericImageView;
|
use ::image::GenericImageView;
|
||||||
|
|
||||||
/// An image node.
|
/// An image node.
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Hash)]
|
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "layout-cache", derive(Hash))]
|
||||||
pub struct ImageNode {
|
pub struct ImageNode {
|
||||||
/// The id of the image file.
|
/// The id of the image file.
|
||||||
pub id: ImageId,
|
pub id: ImageId,
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#[cfg(feature = "layout-cache")]
|
||||||
use std::collections::{hash_map::Entry, HashMap};
|
use std::collections::{hash_map::Entry, HashMap};
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
@ -5,6 +6,7 @@ use super::*;
|
|||||||
|
|
||||||
/// Caches layouting artifacts.
|
/// Caches layouting artifacts.
|
||||||
#[derive(Default, Debug, Clone)]
|
#[derive(Default, Debug, Clone)]
|
||||||
|
#[cfg(feature = "layout-cache")]
|
||||||
pub struct LayoutCache {
|
pub struct LayoutCache {
|
||||||
/// Maps from node hashes to the resulting frames and regions in which the
|
/// Maps from node hashes to the resulting frames and regions in which the
|
||||||
/// frames are valid. The right hand side of the hash map is a vector of
|
/// frames are valid. The right hand side of the hash map is a vector of
|
||||||
@ -15,6 +17,7 @@ pub struct LayoutCache {
|
|||||||
age: usize,
|
age: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "layout-cache")]
|
||||||
impl LayoutCache {
|
impl LayoutCache {
|
||||||
/// Create a new, empty layout cache.
|
/// Create a new, empty layout cache.
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
@ -100,6 +103,7 @@ impl LayoutCache {
|
|||||||
|
|
||||||
/// Cached frames from past layouting.
|
/// Cached frames from past layouting.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
#[cfg(feature = "layout-cache")]
|
||||||
pub struct FramesEntry {
|
pub struct FramesEntry {
|
||||||
/// The cached frames for a node.
|
/// The cached frames for a node.
|
||||||
pub frames: Vec<Constrained<Rc<Frame>>>,
|
pub frames: Vec<Constrained<Rc<Frame>>>,
|
||||||
@ -112,6 +116,7 @@ pub struct FramesEntry {
|
|||||||
temperature: [usize; 5],
|
temperature: [usize; 5],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "layout-cache")]
|
||||||
impl FramesEntry {
|
impl FramesEntry {
|
||||||
/// Construct a new instance.
|
/// Construct a new instance.
|
||||||
pub fn new(frames: Vec<Constrained<Rc<Frame>>>, level: usize) -> Self {
|
pub fn new(frames: Vec<Constrained<Rc<Frame>>>, level: usize) -> Self {
|
||||||
@ -205,6 +210,7 @@ impl Constraints {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "layout-cache")]
|
||||||
fn check(&self, regions: &Regions) -> bool {
|
fn check(&self, regions: &Regions) -> bool {
|
||||||
if self.expand != regions.expand {
|
if self.expand != regions.expand {
|
||||||
return false;
|
return false;
|
||||||
|
@ -24,9 +24,12 @@ pub use stack::*;
|
|||||||
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::fmt::{self, Debug, Formatter};
|
use std::fmt::{self, Debug, Formatter};
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::Hash;
|
||||||
|
#[cfg(feature = "layout-cache")]
|
||||||
|
use std::hash::Hasher;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
#[cfg(feature = "layout-cache")]
|
||||||
use fxhash::FxHasher64;
|
use fxhash::FxHasher64;
|
||||||
|
|
||||||
use crate::cache::Cache;
|
use crate::cache::Cache;
|
||||||
@ -35,7 +38,12 @@ use crate::loading::Loader;
|
|||||||
|
|
||||||
/// Layout a tree into a collection of frames.
|
/// Layout a tree into a collection of frames.
|
||||||
pub fn layout(loader: &mut dyn Loader, cache: &mut Cache, tree: &Tree) -> Vec<Rc<Frame>> {
|
pub fn layout(loader: &mut dyn Loader, cache: &mut Cache, tree: &Tree) -> Vec<Rc<Frame>> {
|
||||||
tree.layout(&mut LayoutContext { loader, cache, level: 0 })
|
tree.layout(&mut LayoutContext {
|
||||||
|
loader,
|
||||||
|
cache,
|
||||||
|
#[cfg(feature = "layout-cache")]
|
||||||
|
level: 0,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A tree of layout nodes.
|
/// A tree of layout nodes.
|
||||||
@ -77,22 +85,35 @@ impl PageRun {
|
|||||||
/// A wrapper around a dynamic layouting node.
|
/// A wrapper around a dynamic layouting node.
|
||||||
pub struct AnyNode {
|
pub struct AnyNode {
|
||||||
node: Box<dyn Bounds>,
|
node: Box<dyn Bounds>,
|
||||||
|
#[cfg(feature = "layout-cache")]
|
||||||
hash: u64,
|
hash: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AnyNode {
|
impl AnyNode {
|
||||||
/// Create a new instance from any node that satisifies the required bounds.
|
/// Create a new instance from any node that satisifies the required bounds.
|
||||||
|
#[cfg(feature = "layout-cache")]
|
||||||
pub fn new<T>(node: T) -> Self
|
pub fn new<T>(node: T) -> Self
|
||||||
where
|
where
|
||||||
T: Layout + Debug + Clone + PartialEq + Hash + 'static,
|
T: Layout + Debug + Clone + PartialEq + Hash + 'static,
|
||||||
{
|
{
|
||||||
|
let hash = {
|
||||||
let mut state = FxHasher64::default();
|
let mut state = FxHasher64::default();
|
||||||
node.type_id().hash(&mut state);
|
node.type_id().hash(&mut state);
|
||||||
node.hash(&mut state);
|
node.hash(&mut state);
|
||||||
let hash = state.finish();
|
state.finish()
|
||||||
|
};
|
||||||
|
|
||||||
Self { node: Box::new(node), hash }
|
Self { node: Box::new(node), hash }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a new instance from any node that satisifies the required bounds.
|
||||||
|
#[cfg(not(feature = "layout-cache"))]
|
||||||
|
pub fn new<T>(node: T) -> Self
|
||||||
|
where
|
||||||
|
T: Layout + Debug + Clone + PartialEq + 'static,
|
||||||
|
{
|
||||||
|
Self { node: Box::new(node) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Layout for AnyNode {
|
impl Layout for AnyNode {
|
||||||
@ -101,6 +122,8 @@ impl Layout for AnyNode {
|
|||||||
ctx: &mut LayoutContext,
|
ctx: &mut LayoutContext,
|
||||||
regions: &Regions,
|
regions: &Regions,
|
||||||
) -> Vec<Constrained<Rc<Frame>>> {
|
) -> Vec<Constrained<Rc<Frame>>> {
|
||||||
|
#[cfg(feature = "layout-cache")]
|
||||||
|
{
|
||||||
ctx.level += 1;
|
ctx.level += 1;
|
||||||
let frames =
|
let frames =
|
||||||
ctx.cache.layout.get(self.hash, regions.clone()).unwrap_or_else(|| {
|
ctx.cache.layout.get(self.hash, regions.clone()).unwrap_or_else(|| {
|
||||||
@ -111,12 +134,16 @@ impl Layout for AnyNode {
|
|||||||
ctx.level -= 1;
|
ctx.level -= 1;
|
||||||
frames
|
frames
|
||||||
}
|
}
|
||||||
|
#[cfg(not(feature = "layout-cache"))]
|
||||||
|
self.node.layout(ctx, regions)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for AnyNode {
|
impl Clone for AnyNode {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
Self {
|
Self {
|
||||||
node: self.node.dyn_clone(),
|
node: self.node.dyn_clone(),
|
||||||
|
#[cfg(feature = "layout-cache")]
|
||||||
hash: self.hash,
|
hash: self.hash,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -128,6 +155,7 @@ impl PartialEq for AnyNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "layout-cache")]
|
||||||
impl Hash for AnyNode {
|
impl Hash for AnyNode {
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
state.write_u64(self.hash);
|
state.write_u64(self.hash);
|
||||||
@ -184,6 +212,7 @@ pub struct LayoutContext<'a> {
|
|||||||
/// A cache for loaded fonts and artifacts from past layouting.
|
/// A cache for loaded fonts and artifacts from past layouting.
|
||||||
pub cache: &'a mut Cache,
|
pub cache: &'a mut Cache,
|
||||||
/// How deeply nested the current layout tree position is.
|
/// How deeply nested the current layout tree position is.
|
||||||
|
#[cfg(feature = "layout-cache")]
|
||||||
pub level: usize,
|
pub level: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
/// A node that adds padding to its child.
|
/// A node that adds padding to its child.
|
||||||
#[derive(Debug, Clone, PartialEq, Hash)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "layout-cache", derive(Hash))]
|
||||||
pub struct PadNode {
|
pub struct PadNode {
|
||||||
/// The amount of padding.
|
/// The amount of padding.
|
||||||
pub padding: Sides<Linear>,
|
pub padding: Sides<Linear>,
|
||||||
|
@ -11,7 +11,8 @@ use crate::util::{RangeExt, SliceExt};
|
|||||||
type Range = std::ops::Range<usize>;
|
type Range = std::ops::Range<usize>;
|
||||||
|
|
||||||
/// A node that arranges its children into a paragraph.
|
/// A node that arranges its children into a paragraph.
|
||||||
#[derive(Debug, Clone, PartialEq, Hash)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "layout-cache", derive(Hash))]
|
||||||
pub struct ParNode {
|
pub struct ParNode {
|
||||||
/// The inline direction of this paragraph.
|
/// The inline direction of this paragraph.
|
||||||
pub dir: Dir,
|
pub dir: Dir,
|
||||||
@ -22,7 +23,8 @@ pub struct ParNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A child of a paragraph node.
|
/// A child of a paragraph node.
|
||||||
#[derive(Clone, PartialEq, Hash)]
|
#[derive(Clone, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "layout-cache", derive(Hash))]
|
||||||
pub enum ParChild {
|
pub enum ParChild {
|
||||||
/// Spacing between other nodes.
|
/// Spacing between other nodes.
|
||||||
Spacing(Length),
|
Spacing(Length),
|
||||||
|
@ -3,7 +3,8 @@ use decorum::N64;
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
/// A node that stacks its children.
|
/// A node that stacks its children.
|
||||||
#[derive(Debug, Clone, PartialEq, Hash)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "layout-cache", derive(Hash))]
|
||||||
pub struct StackNode {
|
pub struct StackNode {
|
||||||
/// The `main` and `cross` directions of this stack.
|
/// The `main` and `cross` directions of this stack.
|
||||||
///
|
///
|
||||||
@ -19,7 +20,8 @@ pub struct StackNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A child of a stack node.
|
/// A child of a stack node.
|
||||||
#[derive(Debug, Clone, PartialEq, Hash)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "layout-cache", derive(Hash))]
|
||||||
pub enum StackChild {
|
pub enum StackChild {
|
||||||
/// Spacing between other nodes.
|
/// Spacing between other nodes.
|
||||||
Spacing(Length),
|
Spacing(Length),
|
||||||
|
@ -272,6 +272,8 @@ fn test_part(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "layout-cache")]
|
||||||
|
{
|
||||||
let reference_cache = cache.layout.clone();
|
let reference_cache = cache.layout.clone();
|
||||||
for level in 0 .. reference_cache.levels() {
|
for level in 0 .. reference_cache.levels() {
|
||||||
cache.layout = reference_cache.clone();
|
cache.layout = reference_cache.clone();
|
||||||
@ -311,6 +313,7 @@ fn test_part(
|
|||||||
|
|
||||||
cache.layout = reference_cache;
|
cache.layout = reference_cache;
|
||||||
cache.layout.turnaround();
|
cache.layout.turnaround();
|
||||||
|
}
|
||||||
|
|
||||||
if !compare_ref {
|
if !compare_ref {
|
||||||
layouted.clear();
|
layouted.clear();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user