summaryrefslogtreecommitdiff
path: root/library
diff options
context:
space:
mode:
Diffstat (limited to 'library')
-rw-r--r--library/Cargo.toml2
-rw-r--r--library/src/basics/heading.rs2
-rw-r--r--library/src/basics/list.rs10
-rw-r--r--library/src/basics/table.rs15
-rw-r--r--library/src/compute/foundations.rs1
-rw-r--r--library/src/layout/align.rs4
-rw-r--r--library/src/layout/columns.rs6
-rw-r--r--library/src/layout/container.rs8
-rw-r--r--library/src/layout/flow.rs25
-rw-r--r--library/src/layout/grid.rs22
-rw-r--r--library/src/layout/hide.rs4
-rw-r--r--library/src/layout/mod.rs85
-rw-r--r--library/src/layout/pad.rs4
-rw-r--r--library/src/layout/page.rs16
-rw-r--r--library/src/layout/par.rs117
-rw-r--r--library/src/layout/place.rs4
-rw-r--r--library/src/layout/repeat.rs4
-rw-r--r--library/src/layout/stack.rs8
-rw-r--r--library/src/layout/transform.rs8
-rw-r--r--library/src/math/mod.rs6
-rw-r--r--library/src/math/tex.rs3
-rw-r--r--library/src/meta/document.rs8
-rw-r--r--library/src/meta/link.rs2
-rw-r--r--library/src/meta/reference.rs2
-rw-r--r--library/src/prelude.rs6
-rw-r--r--library/src/shared/ext.rs8
-rw-r--r--library/src/text/deco.rs2
-rw-r--r--library/src/text/misc.rs4
-rw-r--r--library/src/text/raw.rs2
-rw-r--r--library/src/text/shaping.rs31
-rw-r--r--library/src/text/shift.rs7
-rw-r--r--library/src/visualize/image.rs2
-rw-r--r--library/src/visualize/line.rs2
-rw-r--r--library/src/visualize/shape.rs6
34 files changed, 234 insertions, 202 deletions
diff --git a/library/Cargo.toml b/library/Cargo.toml
index 75cb8efc..e0a0c1f6 100644
--- a/library/Cargo.toml
+++ b/library/Cargo.toml
@@ -11,7 +11,7 @@ bench = false
[dependencies]
typst = { path = ".." }
-comemo = "0.1"
+comemo = { git = "https://github.com/typst/comemo" }
csv = "1"
hypher = "0.1"
kurbo = "0.8"
diff --git a/library/src/basics/heading.rs b/library/src/basics/heading.rs
index b251f27b..d1ea9da6 100644
--- a/library/src/basics/heading.rs
+++ b/library/src/basics/heading.rs
@@ -34,7 +34,7 @@ impl HeadingNode {
}
impl Show for HeadingNode {
- fn show(&self, _: Tracked<dyn World>, _: StyleChain) -> Content {
+ fn show(&self, _: &mut Vt, _: &Content, _: StyleChain) -> Content {
BlockNode(self.body.clone()).pack()
}
}
diff --git a/library/src/basics/list.rs b/library/src/basics/list.rs
index c73ffea6..e35fe9fa 100644
--- a/library/src/basics/list.rs
+++ b/library/src/basics/list.rs
@@ -78,7 +78,7 @@ impl<const L: ListKind> ListNode<L> {
impl<const L: ListKind> Layout for ListNode<L> {
fn layout(
&self,
- world: Tracked<dyn World>,
+ vt: &mut Vt,
styles: StyleChain,
regions: &Regions,
) -> SourceResult<Fragment> {
@@ -104,7 +104,7 @@ impl<const L: ListKind> Layout for ListNode<L> {
cells.push(Content::empty());
let label = if L == LIST || L == ENUM {
- label.resolve(world, L, number)?.styled_with_map(map.clone())
+ label.resolve(vt, L, number)?.styled_with_map(map.clone())
} else {
Content::empty()
};
@@ -137,7 +137,7 @@ impl<const L: ListKind> Layout for ListNode<L> {
gutter: Axes::with_y(vec![gutter.into()]),
cells,
}
- .layout(world, styles, regions)
+ .layout(vt, styles, regions)
}
}
@@ -232,7 +232,7 @@ impl Label {
/// Resolve the label based on the level.
pub fn resolve(
&self,
- world: Tracked<dyn World>,
+ vt: &Vt,
kind: ListKind,
number: usize,
) -> SourceResult<Content> {
@@ -246,7 +246,7 @@ impl Label {
Self::Content(content) => content.clone(),
Self::Func(func, span) => {
let args = Args::new(*span, [Value::Int(number as i64)]);
- func.call_detached(world, args)?.display()
+ func.call_detached(vt.world(), args)?.display()
}
})
}
diff --git a/library/src/basics/table.rs b/library/src/basics/table.rs
index bb900f3d..38ee57a0 100644
--- a/library/src/basics/table.rs
+++ b/library/src/basics/table.rs
@@ -53,7 +53,7 @@ impl TableNode {
impl Layout for TableNode {
fn layout(
&self,
- world: Tracked<dyn World>,
+ vt: &mut Vt,
styles: StyleChain,
regions: &Regions,
) -> SourceResult<Fragment> {
@@ -76,7 +76,7 @@ impl Layout for TableNode {
let x = i % cols;
let y = i / cols;
- if let Some(fill) = fill.resolve(world, x, y)? {
+ if let Some(fill) = fill.resolve(vt, x, y)? {
child = child.filled(fill);
}
@@ -89,7 +89,7 @@ impl Layout for TableNode {
gutter: self.gutter.clone(),
cells,
}
- .layout(world, styles, regions)
+ .layout(vt, styles, regions)
}
}
@@ -104,17 +104,12 @@ pub enum Celled<T> {
impl<T: Cast + Clone> Celled<T> {
/// Resolve the value based on the cell position.
- pub fn resolve(
- &self,
- world: Tracked<dyn World>,
- x: usize,
- y: usize,
- ) -> SourceResult<T> {
+ pub fn resolve(&self, vt: &Vt, x: usize, y: usize) -> SourceResult<T> {
Ok(match self {
Self::Value(value) => value.clone(),
Self::Func(func, span) => {
let args = Args::new(*span, [Value::Int(x as i64), Value::Int(y as i64)]);
- func.call_detached(world, args)?.cast().at(*span)?
+ func.call_detached(vt.world(), args)?.cast().at(*span)?
}
})
}
diff --git a/library/src/compute/foundations.rs b/library/src/compute/foundations.rs
index 3e410185..5134d4ac 100644
--- a/library/src/compute/foundations.rs
+++ b/library/src/compute/foundations.rs
@@ -1,7 +1,6 @@
use crate::prelude::*;
use comemo::Track;
-
use typst::model;
use typst::syntax::Source;
diff --git a/library/src/layout/align.rs b/library/src/layout/align.rs
index a06f7edb..42bf86e1 100644
--- a/library/src/layout/align.rs
+++ b/library/src/layout/align.rs
@@ -29,7 +29,7 @@ impl AlignNode {
impl Layout for AlignNode {
fn layout(
&self,
- world: Tracked<dyn World>,
+ vt: &mut Vt,
styles: StyleChain,
regions: &Regions,
) -> SourceResult<Fragment> {
@@ -44,7 +44,7 @@ impl Layout for AlignNode {
}
// Layout the child.
- let mut fragment = self.child.layout(world, styles.chain(&map), &pod)?;
+ let mut fragment = self.child.layout(vt, styles.chain(&map), &pod)?;
for (region, frame) in regions.iter().zip(&mut fragment) {
// Align in the target size. The target size depends on whether we
// should expand.
diff --git a/library/src/layout/columns.rs b/library/src/layout/columns.rs
index 257cc62f..a5d5aff5 100644
--- a/library/src/layout/columns.rs
+++ b/library/src/layout/columns.rs
@@ -29,14 +29,14 @@ impl ColumnsNode {
impl Layout for ColumnsNode {
fn layout(
&self,
- world: Tracked<dyn World>,
+ vt: &mut Vt,
styles: StyleChain,
regions: &Regions,
) -> SourceResult<Fragment> {
// Separating the infinite space into infinite columns does not make
// much sense.
if !regions.first.x.is_finite() {
- return self.child.layout(world, styles, regions);
+ return self.child.layout(vt, styles, regions);
}
// Determine the width of the gutter and each column.
@@ -58,7 +58,7 @@ impl Layout for ColumnsNode {
};
// Layout the children.
- let mut frames = self.child.layout(world, styles, &pod)?.into_iter();
+ let mut frames = self.child.layout(vt, styles, &pod)?.into_iter();
let mut finished = vec![];
let dir = styles.get(TextNode::DIR);
diff --git a/library/src/layout/container.rs b/library/src/layout/container.rs
index a77e0249..5790aae6 100644
--- a/library/src/layout/container.rs
+++ b/library/src/layout/container.rs
@@ -23,7 +23,7 @@ impl BoxNode {
impl Layout for BoxNode {
fn layout(
&self,
- world: Tracked<dyn World>,
+ vt: &mut Vt,
styles: StyleChain,
regions: &Regions,
) -> SourceResult<Fragment> {
@@ -47,7 +47,7 @@ impl Layout for BoxNode {
};
// Layout the child.
- let mut frame = self.child.layout(world, styles, &pod)?.into_frame();
+ let mut frame = self.child.layout(vt, styles, &pod)?.into_frame();
// Ensure frame size matches regions size if expansion is on.
let target = regions.expand.select(regions.first, frame.size());
@@ -95,10 +95,10 @@ impl BlockNode {
impl Layout for BlockNode {
fn layout(
&self,
- world: Tracked<dyn World>,
+ vt: &mut Vt,
styles: StyleChain,
regions: &Regions,
) -> SourceResult<Fragment> {
- self.0.layout(world, styles, regions)
+ self.0.layout(vt, styles, regions)
}
}
diff --git a/library/src/layout/flow.rs b/library/src/layout/flow.rs
index b644d73f..2994d9c6 100644
--- a/library/src/layout/flow.rs
+++ b/library/src/layout/flow.rs
@@ -20,7 +20,7 @@ impl FlowNode {
impl Layout for FlowNode {
fn layout(
&self,
- world: Tracked<dyn World>,
+ vt: &mut Vt,
styles: StyleChain,
regions: &Regions,
) -> SourceResult<Fragment> {
@@ -33,9 +33,9 @@ impl Layout for FlowNode {
} else if let Some(node) = child.to::<ParNode>() {
let barrier = Style::Barrier(child.id());
let styles = styles.chain_one(&barrier);
- layouter.layout_par(world, node, styles)?;
+ layouter.layout_par(vt, node, styles)?;
} else if child.has::<dyn Layout>() {
- layouter.layout_block(world, child, styles)?;
+ layouter.layout_block(vt, child, styles)?;
} else if child.is::<ColbreakNode>() {
layouter.finish_region(false);
} else {
@@ -122,16 +122,23 @@ impl FlowLayouter {
/// Layout a paragraph.
fn layout_par(
&mut self,
- world: Tracked<dyn World>,
+ vt: &mut Vt,
par: &ParNode,
styles: StyleChain,
) -> SourceResult<()> {
let aligns = Axes::new(styles.get(ParNode::ALIGN), Align::Top);
let leading = styles.get(ParNode::LEADING);
let consecutive = self.last_was_par;
- let fragment = par.layout(world, styles, &self.regions, consecutive)?;
- let len = fragment.len();
+ let fragment = par.layout(
+ vt,
+ styles,
+ consecutive,
+ self.regions.first.x,
+ self.regions.base,
+ self.regions.expand.x,
+ )?;
+ let len = fragment.len();
for (i, frame) in fragment.into_iter().enumerate() {
if i > 0 {
self.layout_item(FlowItem::Leading(leading));
@@ -151,7 +158,7 @@ impl FlowLayouter {
/// Layout a block.
fn layout_block(
&mut self,
- world: Tracked<dyn World>,
+ vt: &mut Vt,
block: &Content,
styles: StyleChain,
) -> SourceResult<()> {
@@ -159,7 +166,7 @@ impl FlowLayouter {
// aligned later.
if let Some(placed) = block.to::<PlaceNode>() {
if placed.out_of_flow() {
- let frame = block.layout(world, styles, &self.regions)?.into_frame();
+ let frame = block.layout(vt, styles, &self.regions)?.into_frame();
self.layout_item(FlowItem::Placed(frame));
return Ok(());
}
@@ -180,7 +187,7 @@ impl FlowLayouter {
// Layout the block itself.
let sticky = styles.get(BlockNode::STICKY);
- let fragment = block.layout(world, styles, &self.regions)?;
+ let fragment = block.layout(vt, styles, &self.regions)?;
for frame in fragment {
self.layout_item(FlowItem::Frame(frame, aligns, sticky));
}
diff --git a/library/src/layout/grid.rs b/library/src/layout/grid.rs
index a848a650..ab189423 100644
--- a/library/src/layout/grid.rs
+++ b/library/src/layout/grid.rs
@@ -36,13 +36,13 @@ impl GridNode {
impl Layout for GridNode {
fn layout(
&self,
- world: Tracked<dyn World>,
+ vt: &mut Vt,
styles: StyleChain,
regions: &Regions,
) -> SourceResult<Fragment> {
// Prepare grid layout by unifying content and gutter tracks.
let layouter = GridLayouter::new(
- world,
+ vt,
self.tracks.as_deref(),
self.gutter.as_deref(),
&self.cells,
@@ -110,9 +110,9 @@ castable! {
}
/// Performs grid layout.
-struct GridLayouter<'a> {
+struct GridLayouter<'a, 'v> {
/// The core context.
- world: Tracked<'a, dyn World>,
+ vt: &'a mut Vt<'v>,
/// The grid cells.
cells: &'a [Content],
/// The column tracks including gutter tracks.
@@ -147,12 +147,12 @@ enum Row {
Fr(Fr, usize),
}
-impl<'a> GridLayouter<'a> {
+impl<'a, 'v> GridLayouter<'a, 'v> {
/// Create a new grid layouter.
///
/// This prepares grid layout by unifying content and gutter tracks.
fn new(
- world: Tracked<'a, dyn World>,
+ vt: &'a mut Vt<'v>,
tracks: Axes<&[TrackSizing]>,
gutter: Axes<&[TrackSizing]>,
cells: &'a [Content],
@@ -206,7 +206,7 @@ impl<'a> GridLayouter<'a> {
regions.expand = Axes::new(true, false);
Self {
- world,
+ vt,
cells,
cols,
rows,
@@ -318,7 +318,7 @@ impl<'a> GridLayouter<'a> {
v.resolve(self.styles).relative_to(self.regions.base.y);
}
- let frame = cell.layout(self.world, self.styles, &pod)?.into_frame();
+ let frame = cell.layout(self.vt, self.styles, &pod)?.into_frame();
resolved.set_max(frame.width());
}
}
@@ -395,7 +395,7 @@ impl<'a> GridLayouter<'a> {
}
let mut sizes = cell
- .layout(self.world, self.styles, &pod)?
+ .layout(self.vt, self.styles, &pod)?
.into_iter()
.map(|frame| frame.height());
@@ -483,7 +483,7 @@ impl<'a> GridLayouter<'a> {
.select(self.regions.base, size);
let pod = Regions::one(size, base, Axes::splat(true));
- let frame = cell.layout(self.world, self.styles, &pod)?.into_frame();
+ let frame = cell.layout(self.vt, self.styles, &pod)?.into_frame();
output.push_frame(pos, frame);
}
@@ -519,7 +519,7 @@ impl<'a> GridLayouter<'a> {
}
// Push the layouted frames into the individual output frames.
- let fragment = cell.layout(self.world, self.styles, &pod)?;
+ let fragment = cell.layout(self.vt, self.styles, &pod)?;
for (output, frame) in outputs.iter_mut().zip(fragment) {
output.push_frame(pos, frame);
}
diff --git a/library/src/layout/hide.rs b/library/src/layout/hide.rs
index 64cbee64..136dae2f 100644
--- a/library/src/layout/hide.rs
+++ b/library/src/layout/hide.rs
@@ -14,11 +14,11 @@ impl HideNode {
impl Layout for HideNode {
fn layout(
&self,
- world: Tracked<dyn World>,
+ vt: &mut Vt,
styles: StyleChain,
regions: &Regions,
) -> SourceResult<Fragment> {
- let mut fragment = self.0.layout(world, styles, regions)?;
+ let mut fragment = self.0.layout(vt, styles, regions)?;
for frame in &mut fragment {
frame.clear();
}
diff --git a/library/src/layout/mod.rs b/library/src/layout/mod.rs
index 8f9337ba..e3691732 100644
--- a/library/src/layout/mod.rs
+++ b/library/src/layout/mod.rs
@@ -32,7 +32,6 @@ pub use self::transform::*;
use std::mem;
-use comemo::Tracked;
use typed_arena::Arena;
use typst::diag::SourceResult;
use typst::geom::*;
@@ -40,7 +39,6 @@ use typst::model::{
applicable, capability, realize, Content, Node, SequenceNode, Style, StyleChain,
StyleVecBuilder, StyledNode,
};
-use typst::World;
use crate::basics::{DescNode, EnumNode, ListItem, ListNode, DESC, ENUM, LIST};
use crate::meta::DocumentNode;
@@ -52,23 +50,27 @@ use crate::text::{LinebreakNode, SmartQuoteNode, SpaceNode, TextNode};
#[capability]
pub trait LayoutRoot {
/// Layout into one frame per page.
- fn layout_root(
- &self,
- world: Tracked<dyn World>,
- styles: StyleChain,
- ) -> SourceResult<Document>;
+ fn layout_root(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<Document>;
}
impl LayoutRoot for Content {
- #[comemo::memoize]
- fn layout_root(
- &self,
- world: Tracked<dyn World>,
- styles: StyleChain,
- ) -> SourceResult<Document> {
- let scratch = Scratch::default();
- let (realized, styles) = realize_root(world, &scratch, self, styles)?;
- realized.with::<dyn LayoutRoot>().unwrap().layout_root(world, styles)
+ fn layout_root(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<Document> {
+ #[comemo::memoize]
+ fn cached(
+ node: &Content,
+ world: comemo::Tracked<dyn World>,
+ styles: StyleChain,
+ ) -> SourceResult<Document> {
+ let mut vt = Vt { world };
+ let scratch = Scratch::default();
+ let (realized, styles) = realize_root(&mut vt, &scratch, node, styles)?;
+ realized
+ .with::<dyn LayoutRoot>()
+ .unwrap()
+ .layout_root(&mut vt, styles)
+ }
+
+ cached(self, vt.world, styles)
}
}
@@ -78,25 +80,38 @@ pub trait Layout {
/// Layout into one frame per region.
fn layout(
&self,
- world: Tracked<dyn World>,
+ vt: &mut Vt,
styles: StyleChain,
regions: &Regions,
) -> SourceResult<Fragment>;
}
impl Layout for Content {
- #[comemo::memoize]
fn layout(
&self,
- world: Tracked<dyn World>,
+ vt: &mut Vt,
styles: StyleChain,
regions: &Regions,
) -> SourceResult<Fragment> {
- let scratch = Scratch::default();
- let (realized, styles) = realize_block(world, &scratch, self, styles)?;
- let barrier = Style::Barrier(realized.id());
- let styles = styles.chain_one(&barrier);
- realized.with::<dyn Layout>().unwrap().layout(world, styles, regions)
+ #[comemo::memoize]
+ fn cached(
+ node: &Content,
+ world: comemo::Tracked<dyn World>,
+ styles: StyleChain,
+ regions: &Regions,
+ ) -> SourceResult<Fragment> {
+ let mut vt = Vt { world };
+ let scratch = Scratch::default();
+ let (realized, styles) = realize_block(&mut vt, &scratch, node, styles)?;
+ let barrier = Style::Barrier(realized.id());
+ let styles = styles.chain_one(&barrier);
+ realized
+ .with::<dyn Layout>()
+ .unwrap()
+ .layout(&mut vt, styles, regions)
+ }
+
+ cached(self, vt.world, styles, regions)
}
}
@@ -199,7 +214,7 @@ impl Regions {
/// Realize into a node that is capable of root-level layout.
fn realize_root<'a>(
- world: Tracked<'a, dyn World>,
+ vt: &mut Vt,
scratch: &'a Scratch<'a>,
content: &'a Content,
styles: StyleChain<'a>,
@@ -208,7 +223,7 @@ fn realize_root<'a>(
return Ok((content.clone(), styles));
}
- let mut builder = Builder::new(world, &scratch, true);
+ let mut builder = Builder::new(vt, &scratch, true);
builder.accept(content, styles)?;
builder.interrupt_page(Some(styles))?;
let (pages, shared) = builder.doc.unwrap().pages.finish();
@@ -217,7 +232,7 @@ fn realize_root<'a>(
/// Realize into a node that is capable of block-level layout.
fn realize_block<'a>(
- world: Tracked<'a, dyn World>,
+ vt: &mut Vt,
scratch: &'a Scratch<'a>,
content: &'a Content,
styles: StyleChain<'a>,
@@ -226,7 +241,7 @@ fn realize_block<'a>(
return Ok((content.clone(), styles));
}
- let mut builder = Builder::new(world, &scratch, false);
+ let mut builder = Builder::new(vt, &scratch, false);
builder.accept(content, styles)?;
builder.interrupt_par()?;
let (children, shared) = builder.flow.0.finish();
@@ -234,9 +249,9 @@ fn realize_block<'a>(
}
/// Builds a document or a flow node from content.
-struct Builder<'a> {
- /// The core context.
- world: Tracked<'a, dyn World>,
+struct Builder<'a, 'v, 't> {
+ /// The virtual typesetter.
+ vt: &'v mut Vt<'t>,
/// Scratch arenas for building.
scratch: &'a Scratch<'a>,
/// The current document building state.
@@ -258,10 +273,10 @@ struct Scratch<'a> {
content: Arena<Content>,
}
-impl<'a> Builder<'a> {
- fn new(world: Tracked<'a, dyn World>, scratch: &'a Scratch<'a>, top: bool) -> Self {
+impl<'a, 'v, 't> Builder<'a, 'v, 't> {
+ fn new(vt: &'v mut Vt<'t>, scratch: &'a Scratch<'a>, top: bool) -> Self {
Self {
- world,
+ vt,
scratch,
doc: top.then(|| DocBuilder::default()),
flow: FlowBuilder::default(),
@@ -286,7 +301,7 @@ impl<'a> Builder<'a> {
return Ok(());
}
- if let Some(realized) = realize(self.world, content, styles)? {
+ if let Some(realized) = realize(self.vt, content, styles)? {
let stored = self.scratch.content.alloc(realized);
return self.accept(stored, styles);
}
diff --git a/library/src/layout/pad.rs b/library/src/layout/pad.rs
index c688dd47..5b36c8c3 100644
--- a/library/src/layout/pad.rs
+++ b/library/src/layout/pad.rs
@@ -28,14 +28,14 @@ impl PadNode {
impl Layout for PadNode {
fn layout(
&self,
- world: Tracked<dyn World>,
+ vt: &mut Vt,
styles: StyleChain,
regions: &Regions,
) -> SourceResult<Fragment> {
// Layout child into padded regions.
let padding = self.padding.resolve(styles);
let pod = regions.map(|size| shrink(size, padding));
- let mut fragment = self.child.layout(world, styles, &pod)?;
+ let mut fragment = self.child.layout(vt, styles, &pod)?;
for frame in &mut fragment {
// Apply the padding inversely such that the grown size padded
diff --git a/library/src/layout/page.rs b/library/src/layout/page.rs
index 9fe608ee..08411ad1 100644
--- a/library/src/layout/page.rs
+++ b/library/src/layout/page.rs
@@ -57,7 +57,7 @@ impl PageNode {
/// Layout the page run into a sequence of frames, one per page.
pub fn layout(
&self,
- world: Tracked<dyn World>,
+ vt: &mut Vt,
mut page: usize,
styles: StyleChain,
) -> SourceResult<Fragment> {
@@ -97,7 +97,7 @@ impl PageNode {
// Layout the child.
let regions = Regions::repeat(size, size, size.map(Abs::is_finite));
- let mut fragment = child.layout(world, styles, &regions)?;
+ let mut fragment = child.layout(vt, styles, &regions)?;
let header = styles.get(Self::HEADER);
let footer = styles.get(Self::FOOTER);
@@ -116,9 +116,9 @@ impl PageNode {
(foreground, Point::zero(), size),
(background, Point::zero(), size),
] {
- if let Some(content) = marginal.resolve(world, page)? {
+ if let Some(content) = marginal.resolve(vt, page)? {
let pod = Regions::one(area, area, Axes::splat(true));
- let sub = content.layout(world, styles, &pod)?.into_frame();
+ let sub = content.layout(vt, styles, &pod)?.into_frame();
if std::ptr::eq(marginal, background) {
frame.prepend_frame(pos, sub);
} else {
@@ -169,17 +169,13 @@ pub enum Marginal {
impl Marginal {
/// Resolve the marginal based on the page number.
- pub fn resolve(
- &self,
- world: Tracked<dyn World>,
- page: usize,
- ) -> SourceResult<Option<Content>> {
+ pub fn resolve(&self, vt: &Vt, page: usize) -> SourceResult<Option<Content>> {
Ok(match self {
Self::None => None,
Self::Content(content) => Some(content.clone()),
Self::Func(func, span) => {
let args = Args::new(*span, [Value::Int(page as i64)]);
- Some(func.call_detached(world, args)?.display())
+ Some(func.call_detached(vt.world(), args)?.display())
}
})
}
diff --git a/library/src/layout/par.rs b/library/src/layout/par.rs
index 82bea1b5..e96845dd 100644
--- a/library/src/layout/par.rs
+++ b/library/src/layout/par.rs
@@ -44,27 +44,43 @@ impl ParNode {
impl ParNode {
/// Layout the paragraph into a collection of lines.
- #[comemo::memoize]
pub fn layout(
&self,
- world: Tracked<dyn World>,
+ vt: &mut Vt,
styles: StyleChain,
- regions: &Regions,
consecutive: bool,
+ width: Abs,
+ base: Size,
+ expand: bool,
) -> SourceResult<Fragment> {
- // Collect all text into one string for BiDi analysis.
- let (text, segments) = collect(self, &styles, consecutive);
-
- // Perform BiDi analysis and then prepare paragraph layout by building a
- // representation on which we can do line breaking without layouting
- // each and every line from scratch.
- let p = prepare(world, self, &text, segments, regions, styles)?;
-
- // Break the paragraph into lines.
- let lines = linebreak(&p, regions.first.x);
+ #[comemo::memoize]
+ fn cached(
+ par: &ParNode,
+ world: Tracked<dyn World>,
+ styles: StyleChain,
+ consecutive: bool,
+ width: Abs,
+ base: Size,
+ expand: bool,
+ ) -> SourceResult<Fragment> {
+ let mut vt = Vt { world };
+
+ // Collect all text into one string for BiDi analysis.
+ let (text, segments) = collect(par, &styles, consecutive);
+
+ // Perform BiDi analysis and then prepare paragraph layout by building a
+ // representation on which we can do line breaking without layouting
+ // each and every line from scratch.
+ let p = prepare(&mut vt, par, &text, segments, styles, width, base)?;
+
+ // Break the paragraph into lines.
+ let lines = linebreak(&vt, &p, width);
+
+ // Stack the lines into one frame per region.
+ finalize(&mut vt, &p, &lines, width, base, expand)
+ }
- // Stack the lines into one frame per region.
- finalize(&p, &lines, regions)
+ cached(self, vt.world, styles, consecutive, width, base, expand)
}
}
@@ -143,8 +159,6 @@ const NODE_REPLACE: char = '\u{FFFC}'; // Object Replacement Character
/// Only when a line break falls onto a text index that is not safe-to-break per
/// rustybuzz, we have to reshape that portion.
struct Preparation<'a> {
- /// The compilation environment.
- world: Tracked<'a, dyn World>,
/// Bidirectional text embedding levels for the paragraph.
bidi: BidiInfo<'a>,
/// Text runs, spacing and layouted nodes.
@@ -470,12 +484,13 @@ fn collect<'a>(
/// Prepare paragraph layout by shaping the whole paragraph and layouting all
/// contained inline-level content.
fn prepare<'a>(
- world: Tracked<'a, dyn World>,
+ vt: &mut Vt,
par: &'a ParNode,
text: &'a str,
segments: Vec<(Segment<'a>, StyleChain<'a>)>,
- regions: &Regions,
styles: StyleChain<'a>,
+ width: Abs,
+ base: Size,
) -> SourceResult<Preparation<'a>> {
let bidi = BidiInfo::new(
text,
@@ -494,11 +509,11 @@ fn prepare<'a>(
let end = cursor + segment.len();
match segment {
Segment::Text(_) => {
- shape_range(&mut items, world, &bidi, cursor..end, styles);
+ shape_range(&mut items, vt, &bidi, cursor..end, styles);
}
Segment::Spacing(spacing) => match spacing {
Spacing::Relative(v) => {
- let resolved = v.resolve(styles).relative_to(regions.base.x);
+ let resolved = v.resolve(styles).relative_to(base.x);
items.push(Item::Absolute(resolved));
}
Spacing::Fractional(v) => {
@@ -509,9 +524,9 @@ fn prepare<'a>(
if let Some(repeat) = inline.to::<RepeatNode>() {
items.push(Item::Repeat(repeat, styles));
} else {
- let size = Size::new(regions.first.x, regions.base.y);
- let pod = Regions::one(size, regions.base, Axes::splat(false));
- let mut frame = inline.layout(world, styles, &pod)?.into_frame();
+ let size = Size::new(width, base.y);
+ let pod = Regions::one(size, base, Axes::splat(false));
+ let mut frame = inline.layout(vt, styles, &pod)?.into_frame();
frame.translate(Point::with_y(styles.get(TextNode::BASELINE)));
items.push(Item::Frame(frame));
}
@@ -522,7 +537,6 @@ fn prepare<'a>(
}
Ok(Preparation {
- world,
bidi,
items,
styles,
@@ -537,14 +551,14 @@ fn prepare<'a>(
/// items for them.
fn shape_range<'a>(
items: &mut Vec<Item<'a>>,
- world: Tracked<dyn World>,
+ vt: &Vt,
bidi: &BidiInfo<'a>,
range: Range,
styles: StyleChain<'a>,
) {
let mut process = |text, level: BidiLevel| {
let dir = if level.is_ltr() { Dir::LTR } else { Dir::RTL };
- let shaped = shape(world, text, styles, dir);
+ let shaped = shape(vt, text, styles, dir);
items.push(Item::Text(shaped));
};
@@ -601,7 +615,7 @@ fn shared_get<'a, K: Key>(
}
/// Find suitable linebreaks.
-fn linebreak<'a>(p: &'a Preparation<'a>, width: Abs) -> Vec<Line<'a>> {
+fn linebreak<'a>(vt: &Vt, p: &'a Preparation<'a>, width: Abs) -> Vec<Line<'a>> {
let linebreaks = p.styles.get(ParNode::LINEBREAKS).unwrap_or_else(|| {
if p.styles.get(ParNode::JUSTIFY) {
Linebreaks::Optimized
@@ -611,22 +625,22 @@ fn linebreak<'a>(p: &'a Preparation<'a>, width: Abs) -> Vec<Line<'a>> {
});
match linebreaks {
- Linebreaks::Simple => linebreak_simple(p, width),
- Linebreaks::Optimized => linebreak_optimized(p, width),
+ Linebreaks::Simple => linebreak_simple(vt, p, width),
+ Linebreaks::Optimized => linebreak_optimized(vt, p, width),
}
}
/// Perform line breaking in simple first-fit style. This means that we build
/// lines greedily, always taking the longest possible line. This may lead to
/// very unbalanced line, but is fast and simple.
-fn linebreak_simple<'a>(p: &'a Preparation<'a>, width: Abs) -> Vec<Line<'a>> {
+fn linebreak_simple<'a>(vt: &Vt, p: &'a Preparation<'a>, width: Abs) -> Vec<Line<'a>> {
let mut lines = vec![];
let mut start = 0;
let mut last = None;
for (end, mandatory, hyphen) in breakpoints(p) {
// Compute the line and its size.
- let mut attempt = line(p, start..end, mandatory, hyphen);
+ let mut attempt = line(vt, p, start..end, mandatory, hyphen);
// If the line doesn't fit anymore, we push the last fitting attempt
// into the stack and rebuild the line from the attempt's end. The
@@ -635,7 +649,7 @@ fn linebreak_simple<'a>(p: &'a Preparation<'a>, width: Abs) -> Vec<Line<'a>> {
if let Some((last_attempt, last_end)) = last.take() {
lines.push(last_attempt);
start = last_end;
- attempt = line(p, start..end, mandatory, hyphen);
+ attempt = line(vt, p, start..end, mandatory, hyphen);
}
}
@@ -675,7 +689,7 @@ fn linebreak_simple<'a>(p: &'a Preparation<'a>, width: Abs) -> Vec<Line<'a>> {
/// computed and stored in dynamic programming table) is minimal. The final
/// result is simply the layout determined for the last breakpoint at the end of
/// text.
-fn linebreak_optimized<'a>(p: &'a Preparation<'a>, width: Abs) -> Vec<Line<'a>> {
+fn linebreak_optimized<'a>(vt: &Vt, p: &'a Preparation<'a>, width: Abs) -> Vec<Line<'a>> {
/// The cost of a line or paragraph layout.
type Cost = f64;
@@ -698,7 +712,7 @@ fn linebreak_optimized<'a>(p: &'a Preparation<'a>, width: Abs) -> Vec<Line<'a>>
let mut table = vec![Entry {
pred: 0,
total: 0.0,
- line: line(p, 0..0, false, false),
+ line: line(vt, p, 0..0, false, false),
}];
let em = p.styles.get(TextNode::SIZE);
@@ -712,7 +726,7 @@ fn linebreak_optimized<'a>(p: &'a Preparation<'a>, width: Abs) -> Vec<Line<'a>>
for (i, pred) in table.iter_mut().enumerate().skip(active) {
// Layout the line.
let start = pred.line.end;
- let attempt = line(p, start..end, mandatory, hyphen);
+ let attempt = line(vt, p, start..end, mandatory, hyphen);
// Determine how much the line's spaces would need to be stretched
// to make it the desired width.
@@ -787,7 +801,7 @@ fn linebreak_optimized<'a>(p: &'a Preparation<'a>, width: Abs) -> Vec<Line<'a>>
/// Returns for each breakpoint the text index, whether the break is mandatory
/// (after `\n`) and whether a hyphen is required (when breaking inside of a
/// word).
-fn breakpoints<'a>(p: &'a Preparation) -> Breakpoints<'a> {
+fn breakpoints<'a>(p: &'a Preparation<'a>) -> Breakpoints<'a> {
Breakpoints {
p,
linebreaks: LineBreakIterator::new(p.bidi.text),
@@ -885,6 +899,7 @@ impl Breakpoints<'_> {
/// Create a line which spans the given range.
fn line<'a>(
+ vt: &Vt,
p: &'a Preparation,
mut range: Range,
mandatory: bool,
@@ -940,9 +955,9 @@ fn line<'a>(
if hyphen || start + shaped.text.len() > range.end {
if hyphen || start < range.end || before.is_empty() {
let shifted = start - base..range.end - base;
- let mut reshaped = shaped.reshape(p.world, shifted);
+ let mut reshaped = shaped.reshape(vt, shifted);
if hyphen || shy {
- reshaped.push_hyphen(p.world);
+ reshaped.push_hyphen(vt);
}
width += reshaped.width;
last = Some(Item::Text(reshaped));
@@ -963,7 +978,7 @@ fn line<'a>(
if range.start + shaped.text.len() > end {
if range.start < end {
let shifted = range.start - base..end - base;
- let reshaped = shaped.reshape(p.world, shifted);
+ let reshaped = shaped.reshape(vt, shifted);
width += reshaped.width;
first = Some(Item::Text(reshaped));
}
@@ -992,27 +1007,35 @@ fn line<'a>(
/// Combine layouted lines into one frame per region.
fn finalize(
+ vt: &mut Vt,
p: &Preparation,
lines: &[Line],
- regions: &Regions,
+ mut width: Abs,
+ base: Size,
+ expand: bool,
) -> SourceResult<Fragment> {
// Determine the paragraph's width: Full width of the region if we
// should expand or there's fractional spacing, fit-to-width otherwise.
- let mut width = regions.first.x;
- if !regions.expand.x && lines.iter().all(|line| line.fr().is_zero()) {
+ if !expand && lines.iter().all(|line| line.fr().is_zero()) {
width = lines.iter().map(|line| line.width).max().unwrap_or_default();
}
// Stack the lines into one frame per region.
lines
.iter()
- .map(|line| commit(p, line, regions.base, width))
+ .map(|line| commit(vt, p, line, base, width))
.collect::<SourceResult<_>>()
.map(Fragment::frames)
}
/// Commit to a line and build its frame.
-fn commit(p: &Preparation, line: &Line, base: Size, width: Abs) -> SourceResult<Frame> {
+fn commit(
+ vt: &mut Vt,
+ p: &Preparation,
+ line: &Line,
+ base: Size,
+ width: Abs,
+) -> SourceResult<Frame> {
let mut remaining = width - line.width;
let mut offset = Abs::zero();
@@ -1079,7 +1102,7 @@ fn commit(p: &Preparation, line: &Line, base: Size, width: Abs) -> SourceResult<
offset += v.share(fr, remaining);
}
Item::Text(shaped) => {
- let frame = shaped.build(p.world, justification);
+ let frame = shaped.build(vt, justification);
push(&mut offset, frame);
}
Item::Frame(frame) => {
@@ -1090,7 +1113,7 @@ fn commit(p: &Preparation, line: &Line, base: Size, width: Abs) -> SourceResult<
let fill = Fr::one().share(fr, remaining);
let size = Size::new(fill, base.y);
let pod = Regions::one(size, base, Axes::new(false, false));
- let frame = repeat.layout(p.world, *styles, &pod)?.into_frame();
+ let frame = repeat.layout(vt, *styles, &pod)?.into_frame();
let width = frame.width();
let count = (fill / width).floor();
let remaining = fill % width;
diff --git a/library/src/layout/place.rs b/library/src/layout/place.rs
index 215b5b9f..f95aff6a 100644
--- a/library/src/layout/place.rs
+++ b/library/src/layout/place.rs
@@ -19,7 +19,7 @@ impl PlaceNode {
impl Layout for PlaceNode {
fn layout(
&self,
- world: Tracked<dyn World>,
+ vt: &mut Vt,
styles: StyleChain,
regions: &Regions,
) -> SourceResult<Fragment> {
@@ -33,7 +33,7 @@ impl Layout for PlaceNode {
Regions::one(regions.base, regions.base, expand)
};
- let mut frame = self.0.layout(world, styles, &pod)?.into_frame();
+ let mut frame = self.0.layout(vt, styles, &pod)?.into_frame();
// If expansion is off, zero all sizes so that we don't take up any
// space in our parent. Otherwise, respect the expand settings.
diff --git a/library/src/layout/repeat.rs b/library/src/layout/repeat.rs
index d9323e1d..a0fceee9 100644
--- a/library/src/layout/repeat.rs
+++ b/library/src/layout/repeat.rs
@@ -14,11 +14,11 @@ impl RepeatNode {
impl Layout for RepeatNode {
fn layout(
&self,
- world: Tracked<dyn World>,
+ vt: &mut Vt,
styles: StyleChain,
regions: &Regions,
) -> SourceResult<Fragment> {
- self.0.layout(world, styles, regions)
+ self.0.layout(vt, styles, regions)
}
}
diff --git a/library/src/layout/stack.rs b/library/src/layout/stack.rs
index c1073b26..5d0b072f 100644
--- a/library/src/layout/stack.rs
+++ b/library/src/layout/stack.rs
@@ -29,7 +29,7 @@ impl StackNode {
impl Layout for StackNode {
fn layout(
&self,
- world: Tracked<dyn World>,
+ vt: &mut Vt,
styles: StyleChain,
regions: &Regions,
) -> SourceResult<Fragment> {
@@ -49,7 +49,7 @@ impl Layout for StackNode {
layouter.layout_spacing(kind);
}
- layouter.layout_block(world, block, styles)?;
+ layouter.layout_block(vt, block, styles)?;
deferred = self.spacing;
}
}
@@ -170,7 +170,7 @@ impl<'a> StackLayouter<'a> {
/// Layout an arbitrary block.
fn layout_block(
&mut self,
- world: Tracked<dyn World>,
+ vt: &mut Vt,
block: &Content,
styles: StyleChain,
) -> SourceResult<()> {
@@ -195,7 +195,7 @@ impl<'a> StackLayouter<'a> {
self.dir.start().into()
});
- let fragment = block.layout(world, styles, &self.regions)?;
+ let fragment = block.layout(vt, styles, &self.regions)?;
let len = fragment.len();
for (i, frame) in fragment.into_iter().enumerate() {
// Grow our size, shrink the region and save the frame for later.
diff --git a/library/src/layout/transform.rs b/library/src/layout/transform.rs
index cfc4ac83..16ee3316 100644
--- a/library/src/layout/transform.rs
+++ b/library/src/layout/transform.rs
@@ -27,11 +27,11 @@ impl MoveNode {
impl Layout for MoveNode {
fn layout(
&self,
- world: Tracked<dyn World>,
+ vt: &mut Vt,
styles: StyleChain,
regions: &Regions,
) -> SourceResult<Fragment> {
- let mut fragment = self.child.layout(world, styles, regions)?;
+ let mut fragment = self.child.layout(vt, styles, regions)?;
for frame in &mut fragment {
let delta = self.delta.resolve(styles);
let delta = delta.zip(frame.size()).map(|(d, s)| d.relative_to(s));
@@ -85,11 +85,11 @@ impl<const T: TransformKind> TransformNode<T> {
impl<const T: TransformKind> Layout for TransformNode<T> {
fn layout(
&self,
- world: Tracked<dyn World>,
+ vt: &mut Vt,
styles: StyleChain,
regions: &Regions,
) -> SourceResult<Fragment> {
- let mut fragment = self.child.layout(world, styles, regions)?;
+ let mut fragment = self.child.layout(vt, styles, regions)?;
for frame in &mut fragment {
let origin = styles.get(Self::ORIGIN).unwrap_or(Align::CENTER_HORIZON);
let Axes { x, y } = origin.zip(frame.size()).map(|(o, s)| o.position(s));
diff --git a/library/src/math/mod.rs b/library/src/math/mod.rs
index 7136c8b9..9d25d485 100644
--- a/library/src/math/mod.rs
+++ b/library/src/math/mod.rs
@@ -30,7 +30,7 @@ impl MathNode {
}
impl Show for MathNode {
- fn show(&self, _: Tracked<dyn World>, styles: StyleChain) -> Content {
+ fn show(&self, _: &mut Vt, _: &Content, styles: StyleChain) -> Content {
let mut map = StyleMap::new();
map.set_family(FontFamily::new("NewComputerModernMath"), styles);
@@ -51,11 +51,11 @@ impl Show for MathNode {
impl Layout for MathNode {
fn layout(
&self,
- world: Tracked<dyn World>,
+ vt: &mut Vt,
styles: StyleChain,
_: &Regions,
) -> SourceResult<Fragment> {
- layout_tex(world, &self.texify(), self.display, styles)
+ layout_tex(vt, &self.texify(), self.display, styles)
}
}
diff --git a/library/src/math/tex.rs b/library/src/math/tex.rs
index 5f332f3c..b2b6486e 100644
--- a/library/src/math/tex.rs
+++ b/library/src/math/tex.rs
@@ -35,13 +35,14 @@ impl Texify for Content {
/// Layout a TeX formula into a frame.
pub fn layout_tex(
- world: Tracked<dyn World>,
+ vt: &Vt,
tex: &str,
display: bool,
styles: StyleChain,
) -> SourceResult<Fragment> {
// Load the font.
let variant = variant(styles);
+ let world = vt.world();
let mut font = None;
for family in families(styles) {
font = world.book().select(family, variant).and_then(|id| world.font(id));
diff --git a/library/src/meta/document.rs b/library/src/meta/document.rs
index 309e1bda..77181671 100644
--- a/library/src/meta/document.rs
+++ b/library/src/meta/document.rs
@@ -18,15 +18,11 @@ impl DocumentNode {
impl LayoutRoot for DocumentNode {
/// Layout the document into a sequence of frames, one per page.
- fn layout_root(
- &self,
- world: Tracked<dyn World>,
- styles: StyleChain,
- ) -> SourceResult<Document> {
+ fn layout_root(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<Document> {
let mut pages = vec![];
for (page, map) in self.0.iter() {
let number = 1 + pages.len();
- let fragment = page.layout(world, number, styles.chain(map))?;
+ let fragment = page.layout(vt, number, styles.chain(map))?;
pages.extend(fragment);
}
diff --git a/library/src/meta/link.rs b/library/src/meta/link.rs
index 44da9c5d..e7d217e7 100644
--- a/library/src/meta/link.rs
+++ b/library/src/meta/link.rs
@@ -54,7 +54,7 @@ impl LinkNode {
}
impl Show for LinkNode {
- fn show(&self, _: Tracked<dyn World>, _: StyleChain) -> Content {
+ fn show(&self, _: &mut Vt, _: &Content, _: StyleChain) -> Content {
self.body.clone()
}
}
diff --git a/library/src/meta/reference.rs b/library/src/meta/reference.rs
index 948aa6f6..c8e8ebdc 100644
--- a/library/src/meta/reference.rs
+++ b/library/src/meta/reference.rs
@@ -20,7 +20,7 @@ impl RefNode {
}
impl Show for RefNode {
- fn show(&self, _: Tracked<dyn World>, _: StyleChain) -> Content {
+ fn show(&self, _: &mut Vt, _: &Content, _: StyleChain) -> Content {
TextNode::packed(format_eco!("@{}", self.0))
}
}
diff --git a/library/src/prelude.rs b/library/src/prelude.rs
index 87fc8e0d..e7d824cc 100644
--- a/library/src/prelude.rs
+++ b/library/src/prelude.rs
@@ -6,7 +6,7 @@ pub use std::fmt::{self, Debug, Formatter};
pub use std::num::NonZeroUsize;
#[doc(no_inline)]
-pub use comemo::Tracked;
+pub use comemo::{Track, Tracked, TrackedMut};
#[doc(no_inline)]
pub use typst::diag::{bail, error, with_alternative, At, SourceResult, StrResult};
#[doc(no_inline)]
@@ -16,8 +16,8 @@ pub use typst::geom::*;
#[doc(no_inline)]
pub use typst::model::{
array, capability, castable, dict, dynamic, format_str, node, Args, Array, Cast,
- Content, Dict, Finalize, Fold, Func, Label, Node, NodeId, Resolve, Show, Smart, Str,
- StyleChain, StyleMap, StyleVec, Unlabellable, Value, Vm,
+ Content, Dict, Finalize, Fold, Func, Label, Node, NodeId, Resolve, Selector, Show,
+ Smart, Str, StyleChain, StyleMap, StyleVec, Unlabellable, Value, Vm, Vt,
};
#[doc(no_inline)]
pub use typst::syntax::{Span, Spanned};
diff --git a/library/src/shared/ext.rs b/library/src/shared/ext.rs
index 54a1598a..2d2dc751 100644
--- a/library/src/shared/ext.rs
+++ b/library/src/shared/ext.rs
@@ -105,11 +105,11 @@ impl FillNode {}
impl Layout for FillNode {
fn layout(
&self,
- world: Tracked<dyn World>,
+ vt: &mut Vt,
styles: StyleChain,
regions: &Regions,
) -> SourceResult<Fragment> {
- let mut fragment = self.child.layout(world, styles, regions)?;
+ let mut fragment = self.child.layout(vt, styles, regions)?;
for frame in &mut fragment {
let shape = Geometry::Rect(frame.size()).filled(self.fill);
frame.prepend(Point::zero(), Element::Shape(shape));
@@ -133,11 +133,11 @@ impl StrokeNode {}
impl Layout for StrokeNode {
fn layout(
&self,
- world: Tracked<dyn World>,
+ vt: &mut Vt,
styles: StyleChain,
regions: &Regions,
) -> SourceResult<Fragment> {
- let mut fragment = self.child.layout(world, styles, regions)?;
+ let mut fragment = self.child.layout(vt, styles, regions)?;
for frame in &mut fragment {
let shape = Geometry::Rect(frame.size()).stroked(self.stroke);
frame.prepend(Point::zero(), Element::Shape(shape));
diff --git a/library/src/text/deco.rs b/library/src/text/deco.rs
index e81b219c..4c9f6dcd 100644
--- a/library/src/text/deco.rs
+++ b/library/src/text/deco.rs
@@ -47,7 +47,7 @@ impl<const L: DecoLine> DecoNode<L> {
}
impl<const L: DecoLine> Show for DecoNode<L> {
- fn show(&self, _: Tracked<dyn World>, styles: StyleChain) -> Content {
+ fn show(&self, _: &mut Vt, _: &Content, styles: StyleChain) -> Content {
self.0.clone().styled(
TextNode::DECO,
Decoration {
diff --git a/library/src/text/misc.rs b/library/src/text/misc.rs
index 32e0cc1d..c3897a8e 100644
--- a/library/src/text/misc.rs
+++ b/library/src/text/misc.rs
@@ -62,7 +62,7 @@ impl StrongNode {
}
impl Show for StrongNode {
- fn show(&self, _: Tracked<dyn World>, styles: StyleChain) -> Content {
+ fn show(&self, _: &mut Vt, _: &Content, styles: StyleChain) -> Content {
self.0.clone().styled(TextNode::DELTA, Delta(styles.get(Self::DELTA)))
}
}
@@ -104,7 +104,7 @@ impl EmphNode {
}
impl Show for EmphNode {
- fn show(&self, _: Tracked<dyn World>, _: StyleChain) -> Content {
+ fn show(&self, _: &mut Vt, _: &Content, _: StyleChain) -> Content {
self.0.clone().styled(TextNode::EMPH, Toggle)
}
}
diff --git a/library/src/text/raw.rs b/library/src/text/raw.rs
index 6c726513..c0bf105f 100644
--- a/library/src/text/raw.rs
+++ b/library/src/text/raw.rs
@@ -43,7 +43,7 @@ impl RawNode {
}
impl Show for RawNode {
- fn show(&self, _: Tracked<dyn World>, styles: StyleChain) -> Content {
+ fn show(&self, _: &mut Vt, _: &Content, styles: StyleChain) -> Content {
let lang = styles.get(Self::LANG).as_ref().map(|s| s.to_lowercase());
let foreground = THEME
.settings
diff --git a/library/src/text/shaping.rs b/library/src/text/shaping.rs
index 88fec39d..6dbbb535 100644
--- a/library/src/text/shaping.rs
+++ b/library/src/text/shaping.rs
@@ -81,8 +81,8 @@ impl<'a> ShapedText<'a> {
///
/// The `justification` defines how much extra advance width each
/// [justifiable glyph](ShapedGlyph::is_justifiable) will get.
- pub fn build(&self, world: Tracked<dyn World>, justification: Abs) -> Frame {
- let (top, bottom) = self.measure(world);
+ pub fn build(&self, vt: &Vt, justification: Abs) -> Frame {
+ let (top, bottom) = self.measure(vt);
let size = Size::new(self.width, top + bottom);
let mut offset = Abs::zero();
@@ -137,7 +137,7 @@ impl<'a> ShapedText<'a> {
}
/// Measure the top and bottom extent of this text.
- fn measure(&self, world: Tracked<dyn World>) -> (Abs, Abs) {
+ fn measure(&self, vt: &Vt) -> (Abs, Abs) {
let mut top = Abs::zero();
let mut bottom = Abs::zero();
@@ -154,6 +154,7 @@ impl<'a> ShapedText<'a> {
if self.glyphs.is_empty() {
// When there are no glyphs, we just use the vertical metrics of the
// first available font.
+ let world = vt.world();
for family in families(self.styles) {
if let Some(font) = world
.book()
@@ -190,11 +191,7 @@ impl<'a> ShapedText<'a> {
/// Reshape a range of the shaped text, reusing information from this
/// shaping process if possible.
- pub fn reshape(
- &'a self,
- world: Tracked<dyn World>,
- text_range: Range<usize>,
- ) -> ShapedText<'a> {
+ pub fn reshape(&'a self, vt: &Vt, text_range: Range<usize>) -> ShapedText<'a> {
if let Some(glyphs) = self.slice_safe_to_break(text_range.clone()) {
Self {
text: &self.text[text_range],
@@ -206,13 +203,14 @@ impl<'a> ShapedText<'a> {
glyphs: Cow::Borrowed(glyphs),
}
} else {
- shape(world, &self.text[text_range], self.styles, self.dir)
+ shape(vt, &self.text[text_range], self.styles, self.dir)
}
}
/// Push a hyphen to end of the text.
- pub fn push_hyphen(&mut self, world: Tracked<dyn World>) {
+ pub fn push_hyphen(&mut self, vt: &Vt) {
families(self.styles).find_map(|family| {
+ let world = vt.world();
let font = world
.book()
.select(family, self.variant)
@@ -303,7 +301,7 @@ impl Debug for ShapedText<'_> {
/// Holds shaping results and metadata common to all shaped segments.
struct ShapingContext<'a> {
- world: Tracked<'a, dyn World>,
+ vt: &'a Vt<'a>,
glyphs: Vec<ShapedGlyph>,
used: Vec<Font>,
styles: StyleChain<'a>,
@@ -316,7 +314,7 @@ struct ShapingContext<'a> {
/// Shape text into [`ShapedText`].
pub fn shape<'a>(
- world: Tracked<dyn World>,
+ vt: &Vt,
text: &'a str,
styles: StyleChain<'a>,
dir: Dir,
@@ -324,7 +322,7 @@ pub fn shape<'a>(
let size = styles.get(TextNode::SIZE);
let mut ctx = ShapingContext {
- world,
+ vt,
size,
glyphs: vec![],
used: vec![],
@@ -365,10 +363,11 @@ fn shape_segment<'a>(
}
// Find the next available family.
- let book = ctx.world.book();
+ let world = ctx.vt.world();
+ let book = world.book();
let mut selection = families.find_map(|family| {
book.select(family, ctx.variant)
- .and_then(|id| ctx.world.font(id))
+ .and_then(|id| world.font(id))
.filter(|font| !ctx.used.contains(font))
});
@@ -377,7 +376,7 @@ fn shape_segment<'a>(
let first = ctx.used.first().map(Font::info);
selection = book
.select_fallback(first, ctx.variant, text)
- .and_then(|id| ctx.world.font(id))
+ .and_then(|id| world.font(id))
.filter(|font| !ctx.used.contains(font));
}
diff --git a/library/src/text/shift.rs b/library/src/text/shift.rs
index df8ec5e6..3419cc91 100644
--- a/library/src/text/shift.rs
+++ b/library/src/text/shift.rs
@@ -43,11 +43,11 @@ impl<const S: ShiftKind> ShiftNode<S> {
}
impl<const S: ShiftKind> Show for ShiftNode<S> {
- fn show(&self, world: Tracked<dyn World>, styles: StyleChain) -> Content {
+ fn show(&self, vt: &mut Vt, _: &Content, styles: StyleChain) -> Content {
let mut transformed = None;
if styles.get(Self::TYPOGRAPHIC) {
if let Some(text) = search_text(&self.0, S) {
- if is_shapable(world, &text, styles) {
+ if is_shapable(vt, &text, styles) {
transformed = Some(TextNode::packed(text));
}
}
@@ -85,7 +85,8 @@ fn search_text(content: &Content, mode: ShiftKind) -> Option<EcoString> {
/// Checks whether the first retrievable family contains all code points of the
/// given string.
-fn is_shapable(world: Tracked<dyn World>, text: &str, styles: StyleChain) -> bool {
+fn is_shapable(vt: &Vt, text: &str, styles: StyleChain) -> bool {
+ let world = vt.world();
for family in styles.get(TextNode::FAMILY).0.iter() {
if let Some(font) = world
.book()
diff --git a/library/src/visualize/image.rs b/library/src/visualize/image.rs
index 6e8b6147..077fe76d 100644
--- a/library/src/visualize/image.rs
+++ b/library/src/visualize/image.rs
@@ -40,7 +40,7 @@ impl ImageNode {
impl Layout for ImageNode {
fn layout(
&self,
- _: Tracked<dyn World>,
+ _: &mut Vt,
styles: StyleChain,
regions: &Regions,
) -> SourceResult<Fragment> {
diff --git a/library/src/visualize/line.rs b/library/src/visualize/line.rs
index 8acf5bb6..505ad4df 100644
--- a/library/src/visualize/line.rs
+++ b/library/src/visualize/line.rs
@@ -39,7 +39,7 @@ impl LineNode {
impl Layout for LineNode {
fn layout(
&self,
- _: Tracked<dyn World>,
+ _: &mut Vt,
styles: StyleChain,
regions: &Regions,
) -> SourceResult<Fragment> {
diff --git a/library/src/visualize/shape.rs b/library/src/visualize/shape.rs
index daecd580..f2d15cab 100644
--- a/library/src/visualize/shape.rs
+++ b/library/src/visualize/shape.rs
@@ -75,7 +75,7 @@ impl<const S: ShapeKind> ShapeNode<S> {
impl<const S: ShapeKind> Layout for ShapeNode<S> {
fn layout(
&self,
- world: Tracked<dyn World>,
+ vt: &mut Vt,
styles: StyleChain,
regions: &Regions,
) -> SourceResult<Fragment> {
@@ -90,7 +90,7 @@ impl<const S: ShapeKind> Layout for ShapeNode<S> {
let child = child.clone().padded(inset.map(|side| side.map(Length::from)));
let mut pod = Regions::one(regions.first, regions.base, regions.expand);
- frame = child.layout(world, styles, &pod)?.into_frame();
+ frame = child.layout(vt, styles, &pod)?.into_frame();
// Relayout with full expansion into square region to make sure
// the result is really a square or circle.
@@ -106,7 +106,7 @@ impl<const S: ShapeKind> Layout for ShapeNode<S> {
pod.first = Size::splat(length);
pod.expand = Axes::splat(true);
- frame = child.layout(world, styles, &pod)?.into_frame();
+ frame = child.layout(vt, styles, &pod)?.into_frame();
}
} else {
// The default size that a shape takes on if it has no child and