summaryrefslogtreecommitdiff
path: root/library/src
diff options
context:
space:
mode:
Diffstat (limited to 'library/src')
-rw-r--r--library/src/graphics/hide.rs18
-rw-r--r--library/src/graphics/image.rs12
-rw-r--r--library/src/graphics/line.rs14
-rw-r--r--library/src/graphics/shape.rs16
-rw-r--r--library/src/layout/align.rs16
-rw-r--r--library/src/layout/columns.rs14
-rw-r--r--library/src/layout/container.rs24
-rw-r--r--library/src/layout/flow.rs24
-rw-r--r--library/src/layout/grid.rs37
-rw-r--r--library/src/layout/mod.rs60
-rw-r--r--library/src/layout/pad.rs14
-rw-r--r--library/src/layout/page.rs10
-rw-r--r--library/src/layout/place.rs14
-rw-r--r--library/src/layout/stack.rs18
-rw-r--r--library/src/layout/transform.rs52
-rw-r--r--library/src/math/mod.rs10
-rw-r--r--library/src/math/tex.rs5
-rw-r--r--library/src/prelude.rs2
-rw-r--r--library/src/shared/ext.rs28
-rw-r--r--library/src/structure/document.rs3
-rw-r--r--library/src/structure/list.rs10
-rw-r--r--library/src/structure/table.rs10
-rw-r--r--library/src/text/par.rs32
23 files changed, 213 insertions, 230 deletions
diff --git a/library/src/graphics/hide.rs b/library/src/graphics/hide.rs
index 3a21c2c7..64cbee64 100644
--- a/library/src/graphics/hide.rs
+++ b/library/src/graphics/hide.rs
@@ -4,22 +4,26 @@ use crate::prelude::*;
#[derive(Debug, Hash)]
pub struct HideNode(pub Content);
-#[node(LayoutInline)]
+#[node(Layout, Inline)]
impl HideNode {
fn construct(_: &Vm, args: &mut Args) -> SourceResult<Content> {
Ok(Self(args.expect("body")?).pack())
}
}
-impl LayoutInline for HideNode {
- fn layout_inline(
+impl Layout for HideNode {
+ fn layout(
&self,
world: Tracked<dyn World>,
styles: StyleChain,
regions: &Regions,
- ) -> SourceResult<Frame> {
- let mut frame = self.0.layout_inline(world, styles, regions)?;
- frame.clear();
- Ok(frame)
+ ) -> SourceResult<Fragment> {
+ let mut fragment = self.0.layout(world, styles, regions)?;
+ for frame in &mut fragment {
+ frame.clear();
+ }
+ Ok(fragment)
}
}
+
+impl Inline for HideNode {}
diff --git a/library/src/graphics/image.rs b/library/src/graphics/image.rs
index de3384df..2c58496c 100644
--- a/library/src/graphics/image.rs
+++ b/library/src/graphics/image.rs
@@ -9,7 +9,7 @@ use crate::text::LinkNode;
#[derive(Debug, Hash)]
pub struct ImageNode(pub Image);
-#[node(LayoutInline)]
+#[node(Layout, Inline)]
impl ImageNode {
/// How the image should adjust itself to a given area.
pub const FIT: ImageFit = ImageFit::Cover;
@@ -37,13 +37,13 @@ impl ImageNode {
}
}
-impl LayoutInline for ImageNode {
- fn layout_inline(
+impl Layout for ImageNode {
+ fn layout(
&self,
_: Tracked<dyn World>,
styles: StyleChain,
regions: &Regions,
- ) -> SourceResult<Frame> {
+ ) -> SourceResult<Fragment> {
let pxw = self.0.width() as f64;
let pxh = self.0.height() as f64;
let px_ratio = pxw / pxh;
@@ -94,10 +94,12 @@ impl LayoutInline for ImageNode {
frame.link(url.clone());
}
- Ok(frame)
+ Ok(Fragment::frame(frame))
}
}
+impl Inline for ImageNode {}
+
/// How an image should adjust itself to a given area.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum ImageFit {
diff --git a/library/src/graphics/line.rs b/library/src/graphics/line.rs
index 11f0be32..8acf5bb6 100644
--- a/library/src/graphics/line.rs
+++ b/library/src/graphics/line.rs
@@ -9,7 +9,7 @@ pub struct LineNode {
delta: Axes<Rel<Length>>,
}
-#[node(LayoutInline)]
+#[node(Layout, Inline)]
impl LineNode {
/// How to stroke the line.
#[property(resolve, fold)]
@@ -36,13 +36,13 @@ impl LineNode {
}
}
-impl LayoutInline for LineNode {
- fn layout_inline(
+impl Layout for LineNode {
+ fn layout(
&self,
_: Tracked<dyn World>,
styles: StyleChain,
regions: &Regions,
- ) -> SourceResult<Frame> {
+ ) -> SourceResult<Fragment> {
let stroke = styles.get(Self::STROKE).unwrap_or_default();
let origin = self
@@ -58,11 +58,13 @@ impl LayoutInline for LineNode {
.map(|(l, b)| l.relative_to(b));
let target = regions.expand.select(regions.first, Size::zero());
- let mut frame = Frame::new(target);
+ let mut frame = Frame::new(target);
let shape = Geometry::Line(delta.to_point()).stroked(stroke);
frame.push(origin.to_point(), Element::Shape(shape));
- Ok(frame)
+ Ok(Fragment::frame(frame))
}
}
+
+impl Inline for LineNode {}
diff --git a/library/src/graphics/shape.rs b/library/src/graphics/shape.rs
index 4c9fec07..114182e5 100644
--- a/library/src/graphics/shape.rs
+++ b/library/src/graphics/shape.rs
@@ -19,7 +19,7 @@ pub type CircleNode = ShapeNode<CIRCLE>;
/// A ellipse with optional content.
pub type EllipseNode = ShapeNode<ELLIPSE>;
-#[node(LayoutInline)]
+#[node(Layout, Inline)]
impl<const S: ShapeKind> ShapeNode<S> {
/// How to fill the shape.
pub const FILL: Option<Paint> = None;
@@ -72,13 +72,13 @@ impl<const S: ShapeKind> ShapeNode<S> {
}
}
-impl<const S: ShapeKind> LayoutInline for ShapeNode<S> {
- fn layout_inline(
+impl<const S: ShapeKind> Layout for ShapeNode<S> {
+ fn layout(
&self,
world: Tracked<dyn World>,
styles: StyleChain,
regions: &Regions,
- ) -> SourceResult<Frame> {
+ ) -> SourceResult<Fragment> {
let mut frame;
if let Some(child) = &self.0 {
let mut inset = styles.get(Self::INSET);
@@ -90,7 +90,7 @@ impl<const S: ShapeKind> LayoutInline 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_inline(world, styles, &pod)?;
+ frame = child.layout(world, 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> LayoutInline for ShapeNode<S> {
pod.first = Size::splat(length);
pod.expand = Axes::splat(true);
- frame = child.layout_inline(world, styles, &pod)?;
+ frame = child.layout(world, styles, &pod)?.into_frame();
}
} else {
// The default size that a shape takes on if it has no child and
@@ -165,10 +165,12 @@ impl<const S: ShapeKind> LayoutInline for ShapeNode<S> {
frame.link(url.clone());
}
- Ok(frame)
+ Ok(Fragment::frame(frame))
}
}
+impl<const S: ShapeKind> Inline for ShapeNode<S> {}
+
/// A category of shape.
pub type ShapeKind = usize;
diff --git a/library/src/layout/align.rs b/library/src/layout/align.rs
index 10a4a2ed..d8b6d92e 100644
--- a/library/src/layout/align.rs
+++ b/library/src/layout/align.rs
@@ -10,14 +10,14 @@ pub struct AlignNode {
pub child: Content,
}
-#[node(LayoutBlock)]
+#[node(Layout)]
impl AlignNode {
fn construct(_: &Vm, args: &mut Args) -> SourceResult<Content> {
let aligns: Axes<Option<GenAlign>> = args.find()?.unwrap_or_default();
let body: Content = args.expect("body")?;
if let Axes { x: Some(x), y: None } = aligns {
- if !body.has::<dyn LayoutBlock>() {
+ if !body.has::<dyn Layout>() || body.has::<dyn Inline>() {
return Ok(body.styled(ParNode::ALIGN, HorizontalAlign(x)));
}
}
@@ -26,13 +26,13 @@ impl AlignNode {
}
}
-impl LayoutBlock for AlignNode {
- fn layout_block(
+impl Layout for AlignNode {
+ fn layout(
&self,
world: Tracked<dyn World>,
styles: StyleChain,
regions: &Regions,
- ) -> SourceResult<Vec<Frame>> {
+ ) -> SourceResult<Fragment> {
// The child only needs to expand along an axis if there's no alignment.
let mut pod = regions.clone();
pod.expand &= self.aligns.as_ref().map(Option::is_none);
@@ -44,8 +44,8 @@ impl LayoutBlock for AlignNode {
}
// Layout the child.
- let mut frames = self.child.layout_block(world, styles.chain(&map), &pod)?;
- for (region, frame) in regions.iter().zip(&mut frames) {
+ let mut fragment = self.child.layout(world, 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.
let target = regions.expand.select(region, frame.size());
@@ -57,6 +57,6 @@ impl LayoutBlock for AlignNode {
frame.resize(target, aligns);
}
- Ok(frames)
+ Ok(fragment)
}
}
diff --git a/library/src/layout/columns.rs b/library/src/layout/columns.rs
index b18ba49f..257cc62f 100644
--- a/library/src/layout/columns.rs
+++ b/library/src/layout/columns.rs
@@ -11,7 +11,7 @@ pub struct ColumnsNode {
pub child: Content,
}
-#[node(LayoutBlock)]
+#[node(Layout)]
impl ColumnsNode {
/// The size of the gutter space between each column.
#[property(resolve)]
@@ -26,17 +26,17 @@ impl ColumnsNode {
}
}
-impl LayoutBlock for ColumnsNode {
- fn layout_block(
+impl Layout for ColumnsNode {
+ fn layout(
&self,
world: Tracked<dyn World>,
styles: StyleChain,
regions: &Regions,
- ) -> SourceResult<Vec<Frame>> {
+ ) -> SourceResult<Fragment> {
// Separating the infinite space into infinite columns does not make
// much sense.
if !regions.first.x.is_finite() {
- return self.child.layout_block(world, styles, regions);
+ return self.child.layout(world, styles, regions);
}
// Determine the width of the gutter and each column.
@@ -58,7 +58,7 @@ impl LayoutBlock for ColumnsNode {
};
// Layout the children.
- let mut frames = self.child.layout_block(world, styles, &pod)?.into_iter();
+ let mut frames = self.child.layout(world, styles, &pod)?.into_iter();
let mut finished = vec![];
let dir = styles.get(TextNode::DIR);
@@ -94,7 +94,7 @@ impl LayoutBlock for ColumnsNode {
finished.push(output);
}
- Ok(finished)
+ Ok(Fragment::frames(finished))
}
}
diff --git a/library/src/layout/container.rs b/library/src/layout/container.rs
index b299c0fc..1c1f8762 100644
--- a/library/src/layout/container.rs
+++ b/library/src/layout/container.rs
@@ -10,7 +10,7 @@ pub struct BoxNode {
pub child: Content,
}
-#[node(LayoutInline)]
+#[node(Layout, Inline)]
impl BoxNode {
fn construct(_: &Vm, args: &mut Args) -> SourceResult<Content> {
let width = args.named("width")?;
@@ -20,13 +20,13 @@ impl BoxNode {
}
}
-impl LayoutInline for BoxNode {
- fn layout_inline(
+impl Layout for BoxNode {
+ fn layout(
&self,
world: Tracked<dyn World>,
styles: StyleChain,
regions: &Regions,
- ) -> SourceResult<Frame> {
+ ) -> SourceResult<Fragment> {
// The "pod" is the region into which the child will be layouted.
let pod = {
// Resolve the sizing to a concrete size.
@@ -47,21 +47,23 @@ impl LayoutInline for BoxNode {
};
// Layout the child.
- let mut frame = self.child.layout_inline(world, styles, &pod)?;
+ let mut frame = self.child.layout(world, styles, &pod)?.into_frame();
// Ensure frame size matches regions size if expansion is on.
let target = regions.expand.select(regions.first, frame.size());
frame.resize(target, Align::LEFT_TOP);
- Ok(frame)
+ Ok(Fragment::frame(frame))
}
}
+impl Inline for BoxNode {}
+
/// A block-level container that places content into a separate flow.
#[derive(Debug, Hash)]
pub struct BlockNode(pub Content);
-#[node(LayoutBlock)]
+#[node(Layout)]
impl BlockNode {
/// The spacing between the previous and this block.
#[property(skip)]
@@ -87,13 +89,13 @@ impl BlockNode {
}
}
-impl LayoutBlock for BlockNode {
- fn layout_block(
+impl Layout for BlockNode {
+ fn layout(
&self,
world: Tracked<dyn World>,
styles: StyleChain,
regions: &Regions,
- ) -> SourceResult<Vec<Frame>> {
- self.0.layout_block(world, styles, regions)
+ ) -> SourceResult<Fragment> {
+ self.0.layout(world, styles, regions)
}
}
diff --git a/library/src/layout/flow.rs b/library/src/layout/flow.rs
index 3338da09..fd3e5fc7 100644
--- a/library/src/layout/flow.rs
+++ b/library/src/layout/flow.rs
@@ -11,23 +11,23 @@ use crate::text::ParNode;
#[derive(Hash)]
pub struct FlowNode(pub StyleVec<Content>);
-#[node(LayoutBlock)]
+#[node(Layout)]
impl FlowNode {}
-impl LayoutBlock for FlowNode {
- fn layout_block(
+impl Layout for FlowNode {
+ fn layout(
&self,
world: Tracked<dyn World>,
styles: StyleChain,
regions: &Regions,
- ) -> SourceResult<Vec<Frame>> {
+ ) -> SourceResult<Fragment> {
let mut layouter = FlowLayouter::new(regions);
for (child, map) in self.0.iter() {
let styles = styles.chain(&map);
if let Some(&node) = child.to::<VNode>() {
layouter.layout_spacing(node.amount, styles);
- } else if child.has::<dyn LayoutBlock>() {
+ } else if child.has::<dyn Layout>() {
layouter.layout_block(world, child, styles)?;
} else if child.is::<ColbreakNode>() {
layouter.finish_region();
@@ -136,7 +136,7 @@ impl FlowLayouter {
// aligned later.
if let Some(placed) = block.to::<PlaceNode>() {
if placed.out_of_flow() {
- let frame = block.layout_block(world, styles, &self.regions)?.remove(0);
+ let frame = block.layout(world, styles, &self.regions)?.into_frame();
self.items.push(FlowItem::Placed(frame));
return Ok(());
}
@@ -166,9 +166,9 @@ impl FlowLayouter {
}
// Layout the block itself.
- let frames = block.layout_block(world, chained, &self.regions)?;
- let len = frames.len();
- for (i, frame) in frames.into_iter().enumerate() {
+ let fragment = block.layout(world, chained, &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.
let size = frame.size();
self.used.y += size.y;
@@ -234,8 +234,8 @@ impl FlowLayouter {
self.finished.push(output);
}
- /// Finish layouting and return the resulting frames.
- fn finish(mut self) -> Vec<Frame> {
+ /// Finish layouting and return the resulting fragment.
+ fn finish(mut self) -> Fragment {
if self.expand.y {
while !self.regions.backlog.is_empty() {
self.finish_region();
@@ -243,6 +243,6 @@ impl FlowLayouter {
}
self.finish_region();
- self.finished
+ Fragment::frames(self.finished)
}
}
diff --git a/library/src/layout/grid.rs b/library/src/layout/grid.rs
index 4cbef421..470b1f3b 100644
--- a/library/src/layout/grid.rs
+++ b/library/src/layout/grid.rs
@@ -13,7 +13,7 @@ pub struct GridNode {
pub cells: Vec<Content>,
}
-#[node(LayoutBlock)]
+#[node(Layout)]
impl GridNode {
fn construct(_: &Vm, args: &mut Args) -> SourceResult<Content> {
let TrackSizings(columns) = args.named("columns")?.unwrap_or_default();
@@ -33,13 +33,13 @@ impl GridNode {
}
}
-impl LayoutBlock for GridNode {
- fn layout_block(
+impl Layout for GridNode {
+ fn layout(
&self,
world: Tracked<dyn World>,
styles: StyleChain,
regions: &Regions,
- ) -> SourceResult<Vec<Frame>> {
+ ) -> SourceResult<Fragment> {
// Prepare grid layout by unifying content and gutter tracks.
let layouter = GridLayouter::new(
world,
@@ -222,7 +222,7 @@ impl<'a> GridLayouter<'a> {
}
/// Determines the columns sizes and then layouts the grid row-by-row.
- fn layout(mut self) -> SourceResult<Vec<Frame>> {
+ fn layout(mut self) -> SourceResult<Fragment> {
self.measure_columns()?;
for y in 0..self.rows.len() {
@@ -243,7 +243,7 @@ impl<'a> GridLayouter<'a> {
}
self.finish_region()?;
- Ok(self.finished)
+ Ok(Fragment::frames(self.finished))
}
/// Determine all column sizes.
@@ -320,8 +320,7 @@ impl<'a> GridLayouter<'a> {
v.resolve(self.styles).relative_to(self.regions.base.y);
}
- let frame =
- cell.layout_block(self.world, self.styles, &pod)?.remove(0);
+ let frame = cell.layout(self.world, self.styles, &pod)?.into_frame();
resolved.set_max(frame.width());
}
}
@@ -391,7 +390,7 @@ impl<'a> GridLayouter<'a> {
}
let mut sizes = cell
- .layout_block(self.world, self.styles, &pod)?
+ .layout(self.world, self.styles, &pod)?
.into_iter()
.map(|frame| frame.height());
@@ -429,9 +428,9 @@ impl<'a> GridLayouter<'a> {
}
// Layout into multiple regions.
- let frames = self.layout_multi_row(&resolved, y)?;
- let len = frames.len();
- for (i, frame) in frames.into_iter().enumerate() {
+ let fragment = self.layout_multi_row(&resolved, y)?;
+ let len = fragment.len();
+ for (i, frame) in fragment.into_iter().enumerate() {
self.push_row(frame);
if i + 1 < len {
self.finish_region()?;
@@ -480,7 +479,7 @@ impl<'a> GridLayouter<'a> {
.select(self.regions.base, size);
let pod = Regions::one(size, base, Axes::splat(true));
- let frame = cell.layout_block(self.world, self.styles, &pod)?.remove(0);
+ let frame = cell.layout(self.world, self.styles, &pod)?.into_frame();
output.push_frame(pos, frame);
}
@@ -491,11 +490,7 @@ impl<'a> GridLayouter<'a> {
}
/// Layout a row spanning multiple regions.
- fn layout_multi_row(
- &mut self,
- heights: &[Abs],
- y: usize,
- ) -> SourceResult<Vec<Frame>> {
+ fn layout_multi_row(&mut self, heights: &[Abs], y: usize) -> SourceResult<Fragment> {
// Prepare frames.
let mut outputs: Vec<_> = heights
.iter()
@@ -520,8 +515,8 @@ impl<'a> GridLayouter<'a> {
}
// Push the layouted frames into the individual output frames.
- let frames = cell.layout_block(self.world, self.styles, &pod)?;
- for (output, frame) in outputs.iter_mut().zip(frames) {
+ let fragment = cell.layout(self.world, self.styles, &pod)?;
+ for (output, frame) in outputs.iter_mut().zip(fragment) {
output.push_frame(pos, frame);
}
}
@@ -529,7 +524,7 @@ impl<'a> GridLayouter<'a> {
pos.x += rcol;
}
- Ok(outputs)
+ Ok(Fragment::frames(outputs))
}
/// Push a row frame into the current region.
diff --git a/library/src/layout/mod.rs b/library/src/layout/mod.rs
index e63a072e..3481a6bd 100644
--- a/library/src/layout/mod.rs
+++ b/library/src/layout/mod.rs
@@ -29,7 +29,6 @@ use std::mem;
use comemo::Tracked;
use typed_arena::Arena;
use typst::diag::SourceResult;
-use typst::doc::Frame;
use typst::geom::*;
use typst::model::{
applicable, capability, realize, Content, Node, SequenceNode, Style, StyleChain,
@@ -70,72 +69,37 @@ impl LayoutRoot for Content {
}
}
-/// Block-level layout.
+/// Layout into regions.
#[capability]
-pub trait LayoutBlock {
+pub trait Layout {
/// Layout into one frame per region.
- fn layout_block(
+ fn layout(
&self,
world: Tracked<dyn World>,
styles: StyleChain,
regions: &Regions,
- ) -> SourceResult<Vec<Frame>>;
+ ) -> SourceResult<Fragment>;
}
-impl LayoutBlock for Content {
+impl Layout for Content {
#[comemo::memoize]
- fn layout_block(
+ fn layout(
&self,
world: Tracked<dyn World>,
styles: StyleChain,
regions: &Regions,
- ) -> SourceResult<Vec<Frame>> {
+ ) -> 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 LayoutBlock>()
- .unwrap()
- .layout_block(world, styles, regions)
+ realized.with::<dyn Layout>().unwrap().layout(world, styles, regions)
}
}
/// Inline-level layout.
#[capability]
-pub trait LayoutInline {
- /// Layout into a single frame.
- fn layout_inline(
- &self,
- world: Tracked<dyn World>,
- styles: StyleChain,
- regions: &Regions,
- ) -> SourceResult<Frame>;
-}
-
-impl LayoutInline for Content {
- #[comemo::memoize]
- fn layout_inline(
- &self,
- world: Tracked<dyn World>,
- styles: StyleChain,
- regions: &Regions,
- ) -> SourceResult<Frame> {
- assert!(regions.backlog.is_empty());
- assert!(regions.last.is_none());
-
- if self.has::<dyn LayoutInline>() && !applicable(self, styles) {
- let barrier = Style::Barrier(self.id());
- let styles = styles.chain_one(&barrier);
- return self
- .with::<dyn LayoutInline>()
- .unwrap()
- .layout_inline(world, styles, regions);
- }
-
- Ok(self.layout_block(world, styles, regions)?.remove(0))
- }
-}
+pub trait Inline: Layout {}
/// A sequence of regions to layout into.
#[derive(Debug, Clone, Hash)]
@@ -255,7 +219,7 @@ fn realize_block<'a>(
content: &'a Content,
styles: StyleChain<'a>,
) -> SourceResult<(Content, StyleChain<'a>)> {
- if content.has::<dyn LayoutBlock>() && !applicable(content, styles) {
+ if content.has::<dyn Layout>() && !applicable(content, styles) {
return Ok((content.clone(), styles));
}
@@ -497,7 +461,7 @@ impl<'a> FlowBuilder<'a> {
return true;
}
- if content.has::<dyn LayoutBlock>() {
+ if content.has::<dyn Layout>() {
let is_tight_list = if let Some(node) = content.to::<ListNode>() {
node.tight
} else if let Some(node) = content.to::<EnumNode>() {
@@ -542,7 +506,7 @@ impl<'a> ParBuilder<'a> {
|| content.is::<HNode>()
|| content.is::<SmartQuoteNode>()
|| content.is::<TextNode>()
- || content.has::<dyn LayoutInline>()
+ || content.has::<dyn Inline>()
{
self.0.push(content.clone(), styles);
return true;
diff --git a/library/src/layout/pad.rs b/library/src/layout/pad.rs
index 4389d990..c688dd47 100644
--- a/library/src/layout/pad.rs
+++ b/library/src/layout/pad.rs
@@ -9,7 +9,7 @@ pub struct PadNode {
pub child: Content,
}
-#[node(LayoutBlock)]
+#[node(Layout)]
impl PadNode {
fn construct(_: &Vm, args: &mut Args) -> SourceResult<Content> {
let all = args.named("rest")?.or(args.find()?);
@@ -25,19 +25,19 @@ impl PadNode {
}
}
-impl LayoutBlock for PadNode {
- fn layout_block(
+impl Layout for PadNode {
+ fn layout(
&self,
world: Tracked<dyn World>,
styles: StyleChain,
regions: &Regions,
- ) -> SourceResult<Vec<Frame>> {
+ ) -> SourceResult<Fragment> {
// Layout child into padded regions.
let padding = self.padding.resolve(styles);
let pod = regions.map(|size| shrink(size, padding));
- let mut frames = self.child.layout_block(world, styles, &pod)?;
+ let mut fragment = self.child.layout(world, styles, &pod)?;
- for frame in &mut frames {
+ for frame in &mut fragment {
// Apply the padding inversely such that the grown size padded
// yields the frame's size.
let padded = grow(frame.size(), padding);
@@ -49,7 +49,7 @@ impl LayoutBlock for PadNode {
frame.translate(offset);
}
- Ok(frames)
+ Ok(fragment)
}
}
diff --git a/library/src/layout/page.rs b/library/src/layout/page.rs
index 42db02c3..9fe608ee 100644
--- a/library/src/layout/page.rs
+++ b/library/src/layout/page.rs
@@ -60,7 +60,7 @@ impl PageNode {
world: Tracked<dyn World>,
mut page: usize,
styles: StyleChain,
- ) -> SourceResult<Vec<Frame>> {
+ ) -> SourceResult<Fragment> {
// When one of the lengths is infinite the page fits its content along
// that axis.
let width = styles.get(Self::WIDTH).unwrap_or(Abs::inf());
@@ -97,7 +97,7 @@ impl PageNode {
// Layout the child.
let regions = Regions::repeat(size, size, size.map(Abs::is_finite));
- let mut frames = child.layout_block(world, styles, &regions)?;
+ let mut fragment = child.layout(world, styles, &regions)?;
let header = styles.get(Self::HEADER);
let footer = styles.get(Self::FOOTER);
@@ -105,7 +105,7 @@ impl PageNode {
let background = styles.get(Self::BACKGROUND);
// Realize overlays.
- for frame in &mut frames {
+ for frame in &mut fragment {
let size = frame.size();
let pad = padding.resolve(styles).relative_to(size);
let pw = size.x - pad.left - pad.right;
@@ -118,7 +118,7 @@ impl PageNode {
] {
if let Some(content) = marginal.resolve(world, page)? {
let pod = Regions::one(area, area, Axes::splat(true));
- let sub = content.layout_block(world, styles, &pod)?.remove(0);
+ let sub = content.layout(world, styles, &pod)?.into_frame();
if std::ptr::eq(marginal, background) {
frame.prepend_frame(pos, sub);
} else {
@@ -130,7 +130,7 @@ impl PageNode {
page += 1;
}
- Ok(frames)
+ Ok(fragment)
}
}
diff --git a/library/src/layout/place.rs b/library/src/layout/place.rs
index af313073..215b5b9f 100644
--- a/library/src/layout/place.rs
+++ b/library/src/layout/place.rs
@@ -5,7 +5,7 @@ use crate::prelude::*;
#[derive(Debug, Hash)]
pub struct PlaceNode(pub Content);
-#[node(LayoutBlock, Behave)]
+#[node(Layout, Behave)]
impl PlaceNode {
fn construct(_: &Vm, args: &mut Args) -> SourceResult<Content> {
let aligns = args.find()?.unwrap_or(Axes::with_x(Some(GenAlign::Start)));
@@ -16,13 +16,13 @@ impl PlaceNode {
}
}
-impl LayoutBlock for PlaceNode {
- fn layout_block(
+impl Layout for PlaceNode {
+ fn layout(
&self,
world: Tracked<dyn World>,
styles: StyleChain,
regions: &Regions,
- ) -> SourceResult<Vec<Frame>> {
+ ) -> SourceResult<Fragment> {
let out_of_flow = self.out_of_flow();
// The pod is the base area of the region because for absolute
@@ -33,14 +33,14 @@ impl LayoutBlock for PlaceNode {
Regions::one(regions.base, regions.base, expand)
};
- let mut frames = self.0.layout_block(world, styles, &pod)?;
+ let mut frame = self.0.layout(world, 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.
let target = regions.expand.select(regions.first, Size::zero());
- frames[0].resize(target, Align::LEFT_TOP);
+ frame.resize(target, Align::LEFT_TOP);
- Ok(frames)
+ Ok(Fragment::frame(frame))
}
}
diff --git a/library/src/layout/stack.rs b/library/src/layout/stack.rs
index c935d971..7de1d34a 100644
--- a/library/src/layout/stack.rs
+++ b/library/src/layout/stack.rs
@@ -15,7 +15,7 @@ pub struct StackNode {
pub children: Vec<StackChild>,
}
-#[node(LayoutBlock)]
+#[node(Layout)]
impl StackNode {
fn construct(_: &Vm, args: &mut Args) -> SourceResult<Content> {
Ok(Self {
@@ -27,13 +27,13 @@ impl StackNode {
}
}
-impl LayoutBlock for StackNode {
- fn layout_block(
+impl Layout for StackNode {
+ fn layout(
&self,
world: Tracked<dyn World>,
styles: StyleChain,
regions: &Regions,
- ) -> SourceResult<Vec<Frame>> {
+ ) -> SourceResult<Fragment> {
let mut layouter = StackLayouter::new(self.dir, regions, styles);
// Spacing to insert before the next block.
@@ -196,9 +196,9 @@ impl<'a> StackLayouter<'a> {
self.dir.start().into()
});
- let frames = block.layout_block(world, styles, &self.regions)?;
- let len = frames.len();
- for (i, frame) in frames.into_iter().enumerate() {
+ let fragment = block.layout(world, 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.
let size = frame.size();
let size = match self.axis {
@@ -276,9 +276,9 @@ impl<'a> StackLayouter<'a> {
}
/// Finish layouting and return the resulting frames.
- fn finish(mut self) -> Vec<Frame> {
+ fn finish(mut self) -> Fragment {
self.finish_region();
- self.finished
+ Fragment::frames(self.finished)
}
}
diff --git a/library/src/layout/transform.rs b/library/src/layout/transform.rs
index f09b4e65..cfc4ac83 100644
--- a/library/src/layout/transform.rs
+++ b/library/src/layout/transform.rs
@@ -11,7 +11,7 @@ pub struct MoveNode {
pub child: Content,
}
-#[node(LayoutInline)]
+#[node(Layout, Inline)]
impl MoveNode {
fn construct(_: &Vm, args: &mut Args) -> SourceResult<Content> {
let dx = args.named("dx")?.unwrap_or_default();
@@ -24,21 +24,25 @@ impl MoveNode {
}
}
-impl LayoutInline for MoveNode {
- fn layout_inline(
+impl Layout for MoveNode {
+ fn layout(
&self,
world: Tracked<dyn World>,
styles: StyleChain,
regions: &Regions,
- ) -> SourceResult<Frame> {
- let mut frame = self.child.layout_inline(world, styles, regions)?;
- let delta = self.delta.resolve(styles);
- let delta = delta.zip(frame.size()).map(|(d, s)| d.relative_to(s));
- frame.translate(delta.to_point());
- Ok(frame)
+ ) -> SourceResult<Fragment> {
+ let mut fragment = self.child.layout(world, 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));
+ frame.translate(delta.to_point());
+ }
+ Ok(fragment)
}
}
+impl Inline for MoveNode {}
+
/// Transform content without affecting layout.
#[derive(Debug, Hash)]
pub struct TransformNode<const T: TransformKind> {
@@ -54,7 +58,7 @@ pub type RotateNode = TransformNode<ROTATE>;
/// Scale content without affecting layout.
pub type ScaleNode = TransformNode<SCALE>;
-#[node(LayoutInline)]
+#[node(Layout, Inline)]
impl<const T: TransformKind> TransformNode<T> {
/// The origin of the transformation.
#[property(resolve)]
@@ -78,26 +82,28 @@ impl<const T: TransformKind> TransformNode<T> {
}
}
-impl<const T: TransformKind> LayoutInline for TransformNode<T> {
- fn layout_inline(
+impl<const T: TransformKind> Layout for TransformNode<T> {
+ fn layout(
&self,
world: Tracked<dyn World>,
styles: StyleChain,
regions: &Regions,
- ) -> SourceResult<Frame> {
- let mut frame = self.child.layout_inline(world, styles, regions)?;
-
- 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));
- let transform = Transform::translate(x, y)
- .pre_concat(self.transform)
- .pre_concat(Transform::translate(-x, -y));
- frame.transform(transform);
-
- Ok(frame)
+ ) -> SourceResult<Fragment> {
+ let mut fragment = self.child.layout(world, 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));
+ let transform = Transform::translate(x, y)
+ .pre_concat(self.transform)
+ .pre_concat(Transform::translate(-x, -y));
+ frame.transform(transform);
+ }
+ Ok(fragment)
}
}
+impl<const T: TransformKind> Inline for TransformNode<T> {}
+
/// Kinds of transformations.
///
/// The move transformation is handled separately.
diff --git a/library/src/math/mod.rs b/library/src/math/mod.rs
index 3b1d66e9..7136c8b9 100644
--- a/library/src/math/mod.rs
+++ b/library/src/math/mod.rs
@@ -19,7 +19,7 @@ pub struct MathNode {
pub display: bool,
}
-#[node(Show, LayoutInline, Texify)]
+#[node(Show, Layout, Inline, Texify)]
impl MathNode {
fn field(&self, name: &str) -> Option<Value> {
match name {
@@ -48,17 +48,19 @@ impl Show for MathNode {
}
}
-impl LayoutInline for MathNode {
- fn layout_inline(
+impl Layout for MathNode {
+ fn layout(
&self,
world: Tracked<dyn World>,
styles: StyleChain,
_: &Regions,
- ) -> SourceResult<Frame> {
+ ) -> SourceResult<Fragment> {
layout_tex(world, &self.texify(), self.display, styles)
}
}
+impl Inline for MathNode {}
+
impl Texify for MathNode {
fn texify(&self) -> EcoString {
self.children.iter().map(Texify::texify).collect()
diff --git a/library/src/math/tex.rs b/library/src/math/tex.rs
index a85bab18..5f332f3c 100644
--- a/library/src/math/tex.rs
+++ b/library/src/math/tex.rs
@@ -39,7 +39,7 @@ pub fn layout_tex(
tex: &str,
display: bool,
styles: StyleChain,
-) -> SourceResult<Frame> {
+) -> SourceResult<Fragment> {
// Load the font.
let variant = variant(styles);
let mut font = None;
@@ -98,7 +98,8 @@ pub fn layout_tex(
// Render into the frame.
renderer.render(&layout, &mut backend);
- Ok(backend.frame)
+
+ Ok(Fragment::frame(backend.frame))
}
/// A ReX rendering backend that renders into a frame.
diff --git a/library/src/prelude.rs b/library/src/prelude.rs
index bc0ec31d..87fc8e0d 100644
--- a/library/src/prelude.rs
+++ b/library/src/prelude.rs
@@ -27,6 +27,6 @@ pub use typst::util::{format_eco, EcoString};
pub use typst::World;
#[doc(no_inline)]
-pub use crate::layout::{LayoutBlock, LayoutInline, Regions};
+pub use crate::layout::{Inline, Layout, Regions};
#[doc(no_inline)]
pub use crate::shared::{Behave, Behaviour, ContentExt, StyleMapExt};
diff --git a/library/src/shared/ext.rs b/library/src/shared/ext.rs
index f90260ad..54a1598a 100644
--- a/library/src/shared/ext.rs
+++ b/library/src/shared/ext.rs
@@ -99,22 +99,22 @@ struct FillNode {
child: Content,
}
-#[node(LayoutBlock)]
+#[node(Layout)]
impl FillNode {}
-impl LayoutBlock for FillNode {
- fn layout_block(
+impl Layout for FillNode {
+ fn layout(
&self,
world: Tracked<dyn World>,
styles: StyleChain,
regions: &Regions,
- ) -> SourceResult<Vec<Frame>> {
- let mut frames = self.child.layout_block(world, styles, regions)?;
- for frame in &mut frames {
+ ) -> SourceResult<Fragment> {
+ let mut fragment = self.child.layout(world, styles, regions)?;
+ for frame in &mut fragment {
let shape = Geometry::Rect(frame.size()).filled(self.fill);
frame.prepend(Point::zero(), Element::Shape(shape));
}
- Ok(frames)
+ Ok(fragment)
}
}
@@ -127,21 +127,21 @@ struct StrokeNode {
child: Content,
}
-#[node(LayoutBlock)]
+#[node(Layout)]
impl StrokeNode {}
-impl LayoutBlock for StrokeNode {
- fn layout_block(
+impl Layout for StrokeNode {
+ fn layout(
&self,
world: Tracked<dyn World>,
styles: StyleChain,
regions: &Regions,
- ) -> SourceResult<Vec<Frame>> {
- let mut frames = self.child.layout_block(world, styles, regions)?;
- for frame in &mut frames {
+ ) -> SourceResult<Fragment> {
+ let mut fragment = self.child.layout(world, styles, regions)?;
+ for frame in &mut fragment {
let shape = Geometry::Rect(frame.size()).stroked(self.stroke);
frame.prepend(Point::zero(), Element::Shape(shape));
}
- Ok(frames)
+ Ok(fragment)
}
}
diff --git a/library/src/structure/document.rs b/library/src/structure/document.rs
index 2e5761e0..e52c92ad 100644
--- a/library/src/structure/document.rs
+++ b/library/src/structure/document.rs
@@ -26,7 +26,8 @@ impl LayoutRoot for DocumentNode {
let mut pages = vec![];
for (page, map) in self.0.iter() {
let number = 1 + pages.len();
- pages.extend(page.layout(world, number, styles.chain(map))?);
+ let fragment = page.layout(world, number, styles.chain(map))?;
+ pages.extend(fragment);
}
Ok(Document {
diff --git a/library/src/structure/list.rs b/library/src/structure/list.rs
index 6bfddd2e..b51284a8 100644
--- a/library/src/structure/list.rs
+++ b/library/src/structure/list.rs
@@ -18,7 +18,7 @@ pub type EnumNode = ListNode<ENUM>;
/// A description list.
pub type DescNode = ListNode<DESC>;
-#[node(LayoutBlock)]
+#[node(Layout)]
impl<const L: ListKind> ListNode<L> {
/// How the list is labelled.
#[property(referenced)]
@@ -75,13 +75,13 @@ impl<const L: ListKind> ListNode<L> {
}
}
-impl<const L: ListKind> LayoutBlock for ListNode<L> {
- fn layout_block(
+impl<const L: ListKind> Layout for ListNode<L> {
+ fn layout(
&self,
world: Tracked<dyn World>,
styles: StyleChain,
regions: &Regions,
- ) -> SourceResult<Vec<Frame>> {
+ ) -> SourceResult<Fragment> {
let mut cells = vec![];
let mut number = 1;
@@ -137,7 +137,7 @@ impl<const L: ListKind> LayoutBlock for ListNode<L> {
gutter: Axes::with_y(vec![gutter.into()]),
cells,
}
- .layout_block(world, styles, regions)
+ .layout(world, styles, regions)
}
}
diff --git a/library/src/structure/table.rs b/library/src/structure/table.rs
index 4dd14cdd..bb900f3d 100644
--- a/library/src/structure/table.rs
+++ b/library/src/structure/table.rs
@@ -12,7 +12,7 @@ pub struct TableNode {
pub cells: Vec<Content>,
}
-#[node(LayoutBlock)]
+#[node(Layout)]
impl TableNode {
/// How to fill the cells.
#[property(referenced)]
@@ -50,13 +50,13 @@ impl TableNode {
}
}
-impl LayoutBlock for TableNode {
- fn layout_block(
+impl Layout for TableNode {
+ fn layout(
&self,
world: Tracked<dyn World>,
styles: StyleChain,
regions: &Regions,
- ) -> SourceResult<Vec<Frame>> {
+ ) -> SourceResult<Fragment> {
let fill = styles.get(Self::FILL);
let stroke = styles.get(Self::STROKE).map(PartialStroke::unwrap_or_default);
let padding = styles.get(Self::PADDING);
@@ -89,7 +89,7 @@ impl LayoutBlock for TableNode {
gutter: self.gutter.clone(),
cells,
}
- .layout_block(world, styles, regions)
+ .layout(world, styles, regions)
}
}
diff --git a/library/src/text/par.rs b/library/src/text/par.rs
index 4c22c034..9dc87873 100644
--- a/library/src/text/par.rs
+++ b/library/src/text/par.rs
@@ -15,7 +15,7 @@ use crate::prelude::*;
#[derive(Hash)]
pub struct ParNode(pub StyleVec<Content>);
-#[node(LayoutBlock)]
+#[node(Layout)]
impl ParNode {
/// The indent the first line of a consecutive paragraph should have.
#[property(resolve)]
@@ -43,13 +43,13 @@ impl ParNode {
}
}
-impl LayoutBlock for ParNode {
- fn layout_block(
+impl Layout for ParNode {
+ fn layout(
&self,
world: Tracked<dyn World>,
styles: StyleChain,
regions: &Regions,
- ) -> SourceResult<Vec<Frame>> {
+ ) -> SourceResult<Fragment> {
// Collect all text into one string for BiDi analysis.
let (text, segments) = collect(self, &styles);
@@ -130,24 +130,26 @@ impl Unlabellable for ParbreakNode {}
#[derive(Debug, Hash)]
pub struct RepeatNode(pub Content);
-#[node(LayoutInline)]
+#[node(Layout, Inline)]
impl RepeatNode {
fn construct(_: &Vm, args: &mut Args) -> SourceResult<Content> {
Ok(Self(args.expect("body")?).pack())
}
}
-impl LayoutInline for RepeatNode {
- fn layout_inline(
+impl Layout for RepeatNode {
+ fn layout(
&self,
world: Tracked<dyn World>,
styles: StyleChain,
regions: &Regions,
- ) -> SourceResult<Frame> {
- self.0.layout_inline(world, styles, regions)
+ ) -> SourceResult<Fragment> {
+ self.0.layout(world, styles, regions)
}
}
+impl Inline for RepeatNode {}
+
/// Range of a substring of text.
type Range = std::ops::Range<usize>;
@@ -405,7 +407,7 @@ fn collect<'a>(
.find_map(|child| {
if child.is::<TextNode>() || child.is::<SmartQuoteNode>() {
Some(true)
- } else if child.has::<dyn LayoutInline>() {
+ } else if child.has::<dyn Inline>() {
Some(false)
} else {
None
@@ -460,7 +462,7 @@ fn collect<'a>(
} else if let Some(&node) = child.to::<HNode>() {
full.push(SPACING_REPLACE);
Segment::Spacing(node.amount)
- } else if child.has::<dyn LayoutInline>() {
+ } else if child.has::<dyn Inline>() {
full.push(NODE_REPLACE);
Segment::Inline(child)
} else {
@@ -530,7 +532,7 @@ fn prepare<'a>(
} 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_inline(world, styles, &pod)?;
+ let mut frame = inline.layout(world, styles, &pod)?.into_frame();
frame.translate(Point::with_y(styles.get(TextNode::BASELINE)));
items.push(Item::Frame(frame));
}
@@ -1011,7 +1013,7 @@ fn line<'a>(
}
/// Combine layouted lines into one frame per region.
-fn stack(p: &Preparation, lines: &[Line], regions: &Regions) -> SourceResult<Vec<Frame>> {
+fn stack(p: &Preparation, lines: &[Line], regions: &Regions) -> 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;
@@ -1050,7 +1052,7 @@ fn stack(p: &Preparation, lines: &[Line], regions: &Regions) -> SourceResult<Vec
}
finished.push(output);
- Ok(finished)
+ Ok(Fragment::frames(finished))
}
/// Commit to a line and build its frame.
@@ -1137,7 +1139,7 @@ fn commit(
let fill = Fr::one().share(fr, remaining);
let size = Size::new(fill, regions.base.y);
let pod = Regions::one(size, regions.base, Axes::new(false, false));
- let frame = repeat.layout_inline(p.world, *styles, &pod)?;
+ let frame = repeat.layout(p.world, *styles, &pod)?.into_frame();
let width = frame.width();
let count = (fill / width).floor();
let remaining = fill % width;