diff options
| author | Laurenz <laurmaedje@gmail.com> | 2022-02-17 17:25:57 +0100 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2022-02-17 17:41:45 +0100 |
| commit | 35610a8c6a1721010b933324dacfe2c4d58761a3 (patch) | |
| tree | 2d02a53f541b7ebc48ace29dacedf534b670c6c1 /src | |
| parent | c5e67af22bd6242366819879be84c10c4dd135be (diff) | |
Fallible layout
Diffstat (limited to 'src')
| -rw-r--r-- | src/eval/show.rs | 8 | ||||
| -rw-r--r-- | src/eval/template.rs | 36 | ||||
| -rw-r--r-- | src/layout/mod.rs | 33 | ||||
| -rw-r--r-- | src/lib.rs | 4 | ||||
| -rw-r--r-- | src/library/align.rs | 6 | ||||
| -rw-r--r-- | src/library/columns.rs | 6 | ||||
| -rw-r--r-- | src/library/deco.rs | 6 | ||||
| -rw-r--r-- | src/library/flow.rs | 21 | ||||
| -rw-r--r-- | src/library/grid.rs | 74 | ||||
| -rw-r--r-- | src/library/heading.rs | 6 | ||||
| -rw-r--r-- | src/library/hide.rs | 6 | ||||
| -rw-r--r-- | src/library/image.rs | 4 | ||||
| -rw-r--r-- | src/library/link.rs | 4 | ||||
| -rw-r--r-- | src/library/list.rs | 6 | ||||
| -rw-r--r-- | src/library/math.rs | 4 | ||||
| -rw-r--r-- | src/library/pad.rs | 6 | ||||
| -rw-r--r-- | src/library/page.rs | 8 | ||||
| -rw-r--r-- | src/library/par.rs | 12 | ||||
| -rw-r--r-- | src/library/place.rs | 6 | ||||
| -rw-r--r-- | src/library/raw.rs | 4 | ||||
| -rw-r--r-- | src/library/shape.rs | 8 | ||||
| -rw-r--r-- | src/library/stack.rs | 17 | ||||
| -rw-r--r-- | src/library/table.rs | 6 | ||||
| -rw-r--r-- | src/library/text.rs | 8 | ||||
| -rw-r--r-- | src/library/transform.rs | 6 |
25 files changed, 170 insertions, 135 deletions
diff --git a/src/eval/show.rs b/src/eval/show.rs index 6157485d..a6a48e6f 100644 --- a/src/eval/show.rs +++ b/src/eval/show.rs @@ -4,12 +4,14 @@ use std::hash::{Hash, Hasher}; use std::sync::Arc; use super::{StyleChain, Template}; +use crate::diag::TypResult; use crate::util::Prehashed; +use crate::Vm; /// A node that can be realized given some styles. pub trait Show { /// Realize the template in the given styles. - fn show(&self, styles: StyleChain) -> Template; + fn show(&self, vm: &mut Vm, styles: StyleChain) -> TypResult<Template>; /// Convert to a packed show node. fn pack(self) -> ShowNode @@ -40,8 +42,8 @@ impl ShowNode { } impl Show for ShowNode { - fn show(&self, styles: StyleChain) -> Template { - self.0.show(styles) + fn show(&self, vm: &mut Vm, styles: StyleChain) -> TypResult<Template> { + self.0.show(vm, styles) } fn pack(self) -> ShowNode { diff --git a/src/eval/template.rs b/src/eval/template.rs index 2cd6797a..b1fe07fe 100644 --- a/src/eval/template.rs +++ b/src/eval/template.rs @@ -165,20 +165,22 @@ impl Template { } /// Layout this template into a collection of pages. - pub fn layout(&self, vm: &mut Vm) -> Vec<Arc<Frame>> { + pub fn layout(&self, vm: &mut Vm) -> TypResult<Vec<Arc<Frame>>> { let style_arena = Arena::new(); let template_arena = Arena::new(); let mut builder = Builder::new(&style_arena, &template_arena, true); let chain = StyleChain::new(vm.styles); - builder.process(self, chain); + builder.process(self, vm, chain)?; builder.finish_page(true, false, chain); + let mut frames = vec![]; let (pages, shared) = builder.pages.unwrap().finish(); - pages - .iter() - .flat_map(|(page, map)| page.layout(vm, map.chain(&shared))) - .collect() + for (page, map) in pages.iter() { + frames.extend(page.layout(vm, map.chain(&shared))?); + } + + Ok(frames) } } @@ -269,12 +271,12 @@ impl Layout for Template { vm: &mut Vm, regions: &Regions, styles: StyleChain, - ) -> Vec<Constrained<Arc<Frame>>> { + ) -> TypResult<Vec<Constrained<Arc<Frame>>>> { let style_arena = Arena::new(); let template_arena = Arena::new(); let mut builder = Builder::new(&style_arena, &template_arena, false); - builder.process(self, styles); + builder.process(self, vm, styles)?; builder.finish_par(styles); let (flow, shared) = builder.flow.finish(); @@ -323,7 +325,12 @@ impl<'a> Builder<'a> { } /// Process a template. - fn process(&mut self, template: &'a Template, styles: StyleChain<'a>) { + fn process( + &mut self, + template: &'a Template, + vm: &mut Vm, + styles: StyleChain<'a>, + ) -> TypResult<()> { match template { Template::Space => { self.par.weak(ParChild::Text(' '.into()), 0, styles); @@ -382,8 +389,9 @@ impl<'a> Builder<'a> { } } Template::Show(node) => { - let template = self.template_arena.alloc(node.show(styles)); - self.process(template, styles.unscoped(node.id())); + let template = node.show(vm, styles)?; + let stored = self.template_arena.alloc(template); + self.process(stored, vm, styles.unscoped(node.id()))?; } Template::Styled(styled) => { let (sub, map) = styled.as_ref(); @@ -397,7 +405,7 @@ impl<'a> Builder<'a> { None => {} } - self.process(sub, styles); + self.process(sub, vm, styles)?; match interruption { Some(Interruption::Page) => self.finish_page(true, false, styles), @@ -407,10 +415,12 @@ impl<'a> Builder<'a> { } Template::Sequence(seq) => { for sub in seq.iter() { - self.process(sub, styles); + self.process(sub, vm, styles)?; } } } + + Ok(()) } /// Finish the currently built paragraph. diff --git a/src/layout/mod.rs b/src/layout/mod.rs index d47e37bb..0d1836fd 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -15,6 +15,7 @@ use std::fmt::{self, Debug, Formatter}; use std::hash::{Hash, Hasher}; use std::sync::Arc; +use crate::diag::TypResult; use crate::eval::StyleChain; use crate::frame::{Element, Frame, Geometry, Shape, Stroke}; use crate::geom::{Align, Linear, Paint, Point, Sides, Size, Spec, Transform}; @@ -33,7 +34,7 @@ pub trait Layout { vm: &mut Vm, regions: &Regions, styles: StyleChain, - ) -> Vec<Constrained<Arc<Frame>>>; + ) -> TypResult<Vec<Constrained<Arc<Frame>>>>; /// Convert to a packed node. fn pack(self) -> LayoutNode @@ -137,7 +138,7 @@ impl Layout for LayoutNode { vm: &mut Vm, regions: &Regions, styles: StyleChain, - ) -> Vec<Constrained<Arc<Frame>>> { + ) -> TypResult<Vec<Constrained<Arc<Frame>>>> { let styles = styles.barred(self.id()); #[cfg(not(feature = "layout-cache"))] @@ -155,10 +156,10 @@ impl Layout for LayoutNode { // #[track_caller] annotation doesn't work. #[cfg(feature = "layout-cache")] if let Some(frames) = vm.layout_cache.get(hash, regions) { - frames + Ok(frames) } else { vm.level += 1; - let frames = self.0.layout(vm, regions, styles); + let frames = self.0.layout(vm, regions, styles)?; vm.level -= 1; let entry = FramesEntry::new(frames.clone(), vm.level); @@ -175,7 +176,7 @@ impl Layout for LayoutNode { } vm.layout_cache.insert(hash, entry); - frames + Ok(frames) } } @@ -248,11 +249,11 @@ impl Layout for EmptyNode { _: &mut Vm, regions: &Regions, _: StyleChain, - ) -> Vec<Constrained<Arc<Frame>>> { + ) -> TypResult<Vec<Constrained<Arc<Frame>>>> { let size = regions.expand.select(regions.current, Size::zero()); let mut cts = Constraints::new(regions.expand); cts.exact = regions.current.filter(regions.expand); - vec![Frame::new(size).constrain(cts)] + Ok(vec![Frame::new(size).constrain(cts)]) } } @@ -271,7 +272,7 @@ impl Layout for SizedNode { vm: &mut Vm, regions: &Regions, styles: StyleChain, - ) -> Vec<Constrained<Arc<Frame>>> { + ) -> TypResult<Vec<Constrained<Arc<Frame>>>> { let is_auto = self.sizing.map_is_none(); let is_rel = self.sizing.map(|s| s.map_or(false, Linear::is_relative)); @@ -292,7 +293,7 @@ impl Layout for SizedNode { Regions::one(size, base, expand) }; - let mut frames = self.child.layout(vm, &pod, styles); + let mut frames = self.child.layout(vm, &pod, styles)?; let Constrained { item: frame, cts } = &mut frames[0]; // Ensure frame size matches regions size if expansion is on. @@ -306,7 +307,7 @@ impl Layout for SizedNode { cts.exact = regions.current.filter(regions.expand | is_auto); cts.base = regions.base.filter(is_rel | is_auto); - frames + Ok(frames) } } @@ -325,13 +326,13 @@ impl Layout for FillNode { vm: &mut Vm, regions: &Regions, styles: StyleChain, - ) -> Vec<Constrained<Arc<Frame>>> { - let mut frames = self.child.layout(vm, regions, styles); + ) -> TypResult<Vec<Constrained<Arc<Frame>>>> { + let mut frames = self.child.layout(vm, regions, styles)?; for Constrained { item: frame, .. } in &mut frames { let shape = Shape::filled(Geometry::Rect(frame.size), self.fill); Arc::make_mut(frame).prepend(Point::zero(), Element::Shape(shape)); } - frames + Ok(frames) } } @@ -350,12 +351,12 @@ impl Layout for StrokeNode { vm: &mut Vm, regions: &Regions, styles: StyleChain, - ) -> Vec<Constrained<Arc<Frame>>> { - let mut frames = self.child.layout(vm, regions, styles); + ) -> TypResult<Vec<Constrained<Arc<Frame>>>> { + let mut frames = self.child.layout(vm, regions, styles)?; for Constrained { item: frame, .. } in &mut frames { let shape = Shape::stroked(Geometry::Rect(frame.size), self.stroke); Arc::make_mut(frame).prepend(Point::zero(), Element::Shape(shape)); } - frames + Ok(frames) } } @@ -283,9 +283,7 @@ impl<'a> Vm<'a> { /// diagnostics in the form of a vector of error message with file and span /// information. pub fn typeset(&mut self, id: SourceId) -> TypResult<Vec<Arc<Frame>>> { - let module = self.evaluate(id)?; - let frames = module.template.layout(self); - Ok(frames) + self.evaluate(id)?.template.layout(self) } /// Resolve a user-entered path (relative to the source file) to be diff --git a/src/library/align.rs b/src/library/align.rs index 5b50937e..3ffd5ec8 100644 --- a/src/library/align.rs +++ b/src/library/align.rs @@ -27,7 +27,7 @@ impl Layout for AlignNode { vm: &mut Vm, regions: &Regions, styles: StyleChain, - ) -> Vec<Constrained<Arc<Frame>>> { + ) -> TypResult<Vec<Constrained<Arc<Frame>>>> { // The child only needs to expand along an axis if there's no alignment. let mut pod = regions.clone(); pod.expand &= self.aligns.map_is_none(); @@ -39,7 +39,7 @@ impl Layout for AlignNode { } // Layout the child. - let mut frames = self.child.layout(vm, &pod, passed.chain(&styles)); + let mut frames = self.child.layout(vm, &pod, passed.chain(&styles))?; for ((current, base), Constrained { item: frame, cts }) in regions.iter().zip(&mut frames) @@ -57,7 +57,7 @@ impl Layout for AlignNode { cts.exact = current.filter(regions.expand | cts.exact.map_is_some()); } - frames + Ok(frames) } } diff --git a/src/library/columns.rs b/src/library/columns.rs index 61da6177..049fa8b9 100644 --- a/src/library/columns.rs +++ b/src/library/columns.rs @@ -32,7 +32,7 @@ impl Layout for ColumnsNode { vm: &mut Vm, regions: &Regions, styles: StyleChain, - ) -> Vec<Constrained<Arc<Frame>>> { + ) -> TypResult<Vec<Constrained<Arc<Frame>>>> { // Separating the infinite space into infinite columns does not make // much sense. if regions.current.x.is_infinite() { @@ -59,7 +59,7 @@ impl Layout for ColumnsNode { }; // Layout the children. - let mut frames = self.child.layout(vm, &pod, styles).into_iter(); + let mut frames = self.child.layout(vm, &pod, styles)?.into_iter(); let dir = styles.get(ParNode::DIR); let total_regions = (frames.len() as f32 / columns as f32).ceil() as usize; @@ -102,7 +102,7 @@ impl Layout for ColumnsNode { finished.push(output.constrain(cts)); } - finished + Ok(finished) } } diff --git a/src/library/deco.rs b/src/library/deco.rs index 92fcf09f..79026288 100644 --- a/src/library/deco.rs +++ b/src/library/deco.rs @@ -32,15 +32,15 @@ impl<const L: DecoLine> DecoNode<L> { } impl<const L: DecoLine> Show for DecoNode<L> { - fn show(&self, styles: StyleChain) -> Template { - self.0.clone().styled(TextNode::LINES, vec![Decoration { + fn show(&self, _: &mut Vm, styles: StyleChain) -> TypResult<Template> { + Ok(self.0.clone().styled(TextNode::LINES, vec![Decoration { line: L, stroke: styles.get(Self::STROKE), thickness: styles.get(Self::THICKNESS), offset: styles.get(Self::OFFSET), extent: styles.get(Self::EXTENT), evade: styles.get(Self::EVADE), - }]) + }])) } } diff --git a/src/library/flow.rs b/src/library/flow.rs index 95469b65..135fd327 100644 --- a/src/library/flow.rs +++ b/src/library/flow.rs @@ -31,7 +31,7 @@ impl Layout for FlowNode { vm: &mut Vm, regions: &Regions, styles: StyleChain, - ) -> Vec<Constrained<Arc<Frame>>> { + ) -> TypResult<Vec<Constrained<Arc<Frame>>>> { let mut layouter = FlowLayouter::new(regions); for (child, map) in self.0.iter() { @@ -56,12 +56,12 @@ impl Layout for FlowNode { layouter.layout_spacing(*kind); } FlowChild::Node(ref node) => { - layouter.layout_node(vm, node, styles); + layouter.layout_node(vm, node, styles)?; } } } - layouter.finish() + Ok(layouter.finish()) } } @@ -161,7 +161,12 @@ impl FlowLayouter { } /// Layout a node. - pub fn layout_node(&mut self, vm: &mut Vm, node: &LayoutNode, styles: StyleChain) { + pub fn layout_node( + &mut self, + vm: &mut Vm, + node: &LayoutNode, + styles: StyleChain, + ) -> TypResult<()> { // Don't even try layouting into a full region. if self.regions.is_full() { self.finish_region(); @@ -171,9 +176,9 @@ impl FlowLayouter { // aligned later. if let Some(placed) = node.downcast::<PlaceNode>() { if placed.out_of_flow() { - let frame = node.layout(vm, &self.regions, styles).remove(0); + let frame = node.layout(vm, &self.regions, styles)?.remove(0); self.items.push(FlowItem::Placed(frame.item)); - return; + return Ok(()); } } @@ -188,7 +193,7 @@ impl FlowLayouter { .unwrap_or(Align::Top), ); - let frames = node.layout(vm, &self.regions, styles); + let frames = node.layout(vm, &self.regions, styles)?; let len = frames.len(); for (i, frame) in frames.into_iter().enumerate() { // Grow our size, shrink the region and save the frame for later. @@ -202,6 +207,8 @@ impl FlowLayouter { self.finish_region(); } } + + Ok(()) } /// Finish the frame for one region. diff --git a/src/library/grid.rs b/src/library/grid.rs index 78ac375f..5f1edb1c 100644 --- a/src/library/grid.rs +++ b/src/library/grid.rs @@ -38,7 +38,7 @@ impl Layout for GridNode { vm: &mut Vm, regions: &Regions, styles: StyleChain, - ) -> Vec<Constrained<Arc<Frame>>> { + ) -> TypResult<Vec<Constrained<Arc<Frame>>>> { // Prepare grid layout by unifying content and gutter tracks. let layouter = GridLayouter::new( self.tracks.as_deref(), @@ -48,7 +48,7 @@ impl Layout for GridNode { styles, ); - // Measure the columsna nd layout the grid row-by-row. + // Measure the columns and layout the grid row-by-row. layouter.layout(vm) } } @@ -205,19 +205,19 @@ impl<'a> GridLayouter<'a> { } /// Determines the columns sizes and then layouts the grid row-by-row. - pub fn layout(mut self, vm: &mut Vm) -> Vec<Constrained<Arc<Frame>>> { - self.measure_columns(vm); + pub fn layout(mut self, vm: &mut Vm) -> TypResult<Vec<Constrained<Arc<Frame>>>> { + self.measure_columns(vm)?; for y in 0 .. self.rows.len() { // Skip to next region if current one is full, but only for content // rows, not for gutter rows. if y % 2 == 0 && self.regions.is_full() { - self.finish_region(vm); + self.finish_region(vm)?; } match self.rows[y] { - TrackSizing::Auto => self.layout_auto_row(vm, y), - TrackSizing::Linear(v) => self.layout_linear_row(vm, v, y), + TrackSizing::Auto => self.layout_auto_row(vm, y)?, + TrackSizing::Linear(v) => self.layout_linear_row(vm, v, y)?, TrackSizing::Fractional(v) => { self.cts.exact.y = Some(self.full); self.lrows.push(Row::Fr(v, y)); @@ -226,12 +226,12 @@ impl<'a> GridLayouter<'a> { } } - self.finish_region(vm); - self.finished + self.finish_region(vm)?; + Ok(self.finished) } /// Determine all column sizes. - fn measure_columns(&mut self, vm: &mut Vm) { + fn measure_columns(&mut self, vm: &mut Vm) -> TypResult<()> { enum Case { /// The column sizing is only determined by specified linear sizes. PurelyLinear, @@ -277,7 +277,7 @@ impl<'a> GridLayouter<'a> { let available = self.regions.current.x - linear; if available >= Length::zero() { // Determine size of auto columns. - let (auto, count) = self.measure_auto_columns(vm, available); + let (auto, count) = self.measure_auto_columns(vm, available)?; // If there is remaining space, distribute it to fractional columns, // otherwise shrink auto columns. @@ -308,6 +308,8 @@ impl<'a> GridLayouter<'a> { // Sum up the resolved column sizes once here. self.used.x = self.rcols.iter().sum(); + + Ok(()) } /// Measure the size that is available to auto columns. @@ -315,7 +317,7 @@ impl<'a> GridLayouter<'a> { &mut self, vm: &mut Vm, available: Length, - ) -> (Length, usize) { + ) -> TypResult<(Length, usize)> { let mut auto = Length::zero(); let mut count = 0; @@ -340,7 +342,7 @@ impl<'a> GridLayouter<'a> { pod.base.y = v.resolve(self.regions.base.y); } - let frame = node.layout(vm, &pod, self.styles).remove(0).item; + let frame = node.layout(vm, &pod, self.styles)?.remove(0).item; resolved.set_max(frame.size.x); } } @@ -350,7 +352,7 @@ impl<'a> GridLayouter<'a> { count += 1; } - (auto, count) + Ok((auto, count)) } /// Distribute remaining space to fractional columns. @@ -394,7 +396,7 @@ impl<'a> GridLayouter<'a> { /// Layout a row with automatic height. Such a row may break across multiple /// regions. - fn layout_auto_row(&mut self, vm: &mut Vm, y: usize) { + fn layout_auto_row(&mut self, vm: &mut Vm, y: usize) -> TypResult<()> { let mut resolved: Vec<Length> = vec![]; // Determine the size for each region of the row. @@ -409,7 +411,7 @@ impl<'a> GridLayouter<'a> { } let mut sizes = node - .layout(vm, &pod, self.styles) + .layout(vm, &pod, self.styles)? .into_iter() .map(|frame| frame.item.size.y); @@ -427,14 +429,14 @@ impl<'a> GridLayouter<'a> { // Nothing to layout. if resolved.is_empty() { - return; + return Ok(()); } // Layout into a single region. if let &[first] = resolved.as_slice() { - let frame = self.layout_single_row(vm, first, y); + let frame = self.layout_single_row(vm, first, y)?; self.push_row(frame); - return; + return Ok(()); } // Expand all but the last region if the space is not @@ -449,36 +451,40 @@ impl<'a> GridLayouter<'a> { } // Layout into multiple regions. - let frames = self.layout_multi_row(vm, &resolved, y); + let frames = self.layout_multi_row(vm, &resolved, y)?; let len = frames.len(); for (i, frame) in frames.into_iter().enumerate() { self.push_row(frame); if i + 1 < len { self.cts.exact.y = Some(self.full); - self.finish_region(vm); + self.finish_region(vm)?; } } + + Ok(()) } /// Layout a row with linear height. Such a row cannot break across multiple /// regions, but it may force a region break. - fn layout_linear_row(&mut self, vm: &mut Vm, v: Linear, y: usize) { + fn layout_linear_row(&mut self, vm: &mut Vm, v: Linear, y: usize) -> TypResult<()> { let resolved = v.resolve(self.regions.base.y); - let frame = self.layout_single_row(vm, resolved, y); + let frame = self.layout_single_row(vm, resolved, y)?; // Skip to fitting region. let height = frame.size.y; while !self.regions.current.y.fits(height) && !self.regions.in_last() { self.cts.max.y = Some(self.used.y + height); - self.finish_region(vm); + self.finish_region(vm)?; // Don't skip multiple regions for gutter and don't push a row. if y % 2 == 1 { - return; + return Ok(()); } } self.push_row(frame); + + Ok(()) } /// Layout a row with fixed height and return its frame. @@ -487,7 +493,7 @@ impl<'a> GridLayouter<'a> { vm: &mut Vm, height: Length, y: usize, - ) -> Frame { + ) -> TypResult<Frame> { let mut output = Frame::new(Size::new(self.used.x, height)); let mut pos = Point::zero(); @@ -502,14 +508,14 @@ impl<'a> GridLayouter<'a> { .select(self.regions.base, size); let pod = Regions::one(size, base, Spec::splat(true)); - let frame = node.layout(vm, &pod, self.styles).remove(0); + let frame = node.layout(vm, &pod, self.styles)?.remove(0); output.push_frame(pos, frame.item); } pos.x += rcol; } - output + Ok(output) } /// Layout a row spanning multiple regions. @@ -518,7 +524,7 @@ impl<'a> GridLayouter<'a> { vm: &mut Vm, heights: &[Length], y: usize, - ) -> Vec<Frame> { + ) -> TypResult<Vec<Frame>> { // Prepare frames. let mut outputs: Vec<_> = heights .iter() @@ -542,7 +548,7 @@ impl<'a> GridLayouter<'a> { } // Push the layouted frames into the individual output frames. - let frames = node.layout(vm, &pod, self.styles); + let frames = node.layout(vm, &pod, self.styles)?; for (output, frame) in outputs.iter_mut().zip(frames) { output.push_frame(pos, frame.item); } @@ -551,7 +557,7 @@ impl<'a> GridLayouter<'a> { pos.x += rcol; } - outputs + Ok(outputs) } /// Push a row frame into the current region. @@ -562,7 +568,7 @@ impl<'a> GridLayouter<'a> { } /// Finish rows for one region. - fn finish_region(&mut self, vm: &mut Vm) { + fn finish_region(&mut self, vm: &mut Vm) -> TypResult<()> { // Determine the size of the grid in this region, expanding fully if // there are fr rows. let mut size = self.used; @@ -584,7 +590,7 @@ impl<'a> GridLayouter<'a> { Row::Fr(v, y) => { let remaining = self.full - self.used.y; let height = v.resolve(self.fr, remaining); - self.layout_single_row(vm, height, y) + self.layout_single_row(vm, height, y)? } }; @@ -600,6 +606,8 @@ impl<'a> GridLayouter<'a> { self.used.y = Length::zero(); self.fr = Fractional::zero(); self.cts = Constraints::new(self.expand); + + Ok(()) } /// Get the node in the cell in column `x` and row `y`. diff --git a/src/library/heading.rs b/src/library/heading.rs index 2123116b..2044355e 100644 --- a/src/library/heading.rs +++ b/src/library/heading.rs @@ -43,7 +43,7 @@ impl HeadingNode { } impl Show for HeadingNode { - fn show(&self, styles: StyleChain) -> Template { + fn show(&self, _: &mut Vm, styles: StyleChain) -> TypResult<Template> { let mut map = StyleMap::new(); let upscale = (1.6 - 0.1 * self.level as f64).max(0.75); @@ -93,6 +93,8 @@ impl Show for HeadingNode { seq.push(Template::Vertical(below.into())); } - Template::block(Template::sequence(seq).styled_with_map(map)) + Ok(Template::block( + Template::sequence(seq).styled_with_map(map), + )) } } diff --git a/src/library/hide.rs b/src/library/hide.rs index 230300d2..ea2227f1 100644 --- a/src/library/hide.rs +++ b/src/library/hide.rs @@ -19,14 +19,14 @@ impl Layout for HideNode { vm: &mut Vm, regions: &Regions, styles: StyleChain, - ) -> Vec<Constrained<Arc<Frame>>> { - let mut frames = self.0.layout(vm, regions, styles); + ) -> TypResult<Vec<Constrained<Arc<Frame>>>> { + let mut frames = self.0.layout(vm, regions, styles)?; // Clear the frames. for Constrained { item: frame, .. } in &mut frames { *frame = Arc::new(Frame { elements: vec![], ..**frame }); } - frames + Ok(frames) } } diff --git a/src/library/image.rs b/src/library/image.rs index 5527fbdc..05877126 100644 --- a/src/library/image.rs +++ b/src/library/image.rs @@ -39,7 +39,7 @@ impl Layout for ImageNode { vm: &mut Vm, regions: &Regions, styles: StyleChain, - ) -> Vec<Constrained<Arc<Frame>>> { + ) -> TypResult<Vec<Constrained<Arc<Frame>>>> { let img = vm.images.get(self.0); let pxw = img.width() as f64; let pxh = img.height() as f64; @@ -91,7 +91,7 @@ impl Layout for ImageNode { frame.link(url); } - vec![frame.constrain(Constraints::tight(regions))] + Ok(vec![frame.constrain(Constraints::tight(regions))]) } } diff --git a/src/library/link.rs b/src/library/link.rs index 58c7e550..95fff089 100644 --- a/src/library/link.rs +++ b/src/library/link.rs @@ -37,7 +37,7 @@ impl LinkNode { } impl Show for LinkNode { - fn show(&self, styles: StyleChain) -> Template { + fn show(&self, _: &mut Vm, styles: StyleChain) -> TypResult<Template> { let mut map = StyleMap::new(); map.set(TextNode::LINK, Some(self.url.clone())); @@ -50,6 +50,6 @@ impl Show for LinkNode { body = body.underlined(); } - body.styled_with_map(map) + Ok(body.styled_with_map(map)) } } diff --git a/src/library/list.rs b/src/library/list.rs index 7f76a178..08ccfc18 100644 --- a/src/library/list.rs +++ b/src/library/list.rs @@ -30,7 +30,7 @@ impl<const L: Labelling> ListNode<L> { } impl<const L: Labelling> Show for ListNode<L> { - fn show(&self, styles: StyleChain) -> Template { + fn show(&self, _: &mut Vm, styles: StyleChain) -> TypResult<Template> { let em = styles.get(TextNode::SIZE).abs; let label_indent = styles.get(Self::LABEL_INDENT).resolve(em); let body_indent = styles.get(Self::BODY_INDENT).resolve(em); @@ -40,7 +40,7 @@ impl<const L: Labelling> Show for ListNode<L> { ORDERED | _ => format_eco!("{}.", self.number.unwrap_or(1)), }; - Template::block(GridNode { + Ok(Template::block(GridNode { tracks: Spec::with_x(vec![ TrackSizing::Linear(label_indent.into()), TrackSizing::Auto, @@ -54,7 +54,7 @@ impl<const L: Labelling> Show for ListNode<L> { LayoutNode::default(), self.child.clone(), ], - }) + })) } } diff --git a/src/library/math.rs b/src/library/math.rs index 29367cd5..d3c8b5e5 100644 --- a/src/library/math.rs +++ b/src/library/math.rs @@ -22,11 +22,11 @@ impl MathNode { } impl Show for MathNode { - fn show(&self, _: StyleChain) -> Template { + fn show(&self, _: &mut Vm, _: StyleChain) -> TypResult<Template> { let mut template = Template::Text(self.formula.trim().into()); if self.display { template = Template::Block(template.pack()); } - template.monospaced() + Ok(template.monospaced()) } } diff --git a/src/library/pad.rs b/src/library/pad.rs index 84e83939..76647645 100644 --- a/src/library/pad.rs +++ b/src/library/pad.rs @@ -37,10 +37,10 @@ impl Layout for PadNode { vm: &mut Vm, regions: &Regions, styles: StyleChain, - ) -> Vec<Constrained<Arc<Frame>>> { + ) -> TypResult<Vec<Constrained<Arc<Frame>>>> { // Layout child into padded regions. let pod = regions.map(|size| shrink(size, self.padding)); - let mut frames = self.child.layout(vm, &pod, styles); + let mut frames = self.child.layout(vm, &pod, styles)?; for ((current, base), Constrained { item: frame, cts }) in regions.iter().zip(&mut frames) @@ -70,7 +70,7 @@ impl Layout for PadNode { } } - frames + Ok(frames) } } diff --git a/src/library/page.rs b/src/library/page.rs index 155f60dd..160ac1ed 100644 --- a/src/library/page.rs +++ b/src/library/page.rs @@ -60,7 +60,7 @@ impl PageNode { impl PageNode { /// Layout the page run into a sequence of frames, one per page. - pub fn layout(&self, vm: &mut Vm, styles: StyleChain) -> Vec<Arc<Frame>> { + pub fn layout(&self, vm: &mut Vm, styles: StyleChain) -> TypResult<Vec<Arc<Frame>>> { // When one of the lengths is infinite the page fits its content along // that axis. let width = styles.get(Self::WIDTH).unwrap_or(Length::inf()); @@ -103,11 +103,11 @@ impl PageNode { // Layout the child. let expand = size.map(Length::is_finite); let regions = Regions::repeat(size, size, expand); - child - .layout(vm, ®ions, styles) + Ok(child + .layout(vm, ®ions, styles)? .into_iter() .map(|c| c.item) - .collect() + .collect()) } } diff --git a/src/library/par.rs b/src/library/par.rs index 02633612..dd0ee5d0 100644 --- a/src/library/par.rs +++ b/src/library/par.rs @@ -85,7 +85,7 @@ impl Layout for ParNode { vm: &mut Vm, regions: &Regions, styles: StyleChain, - ) -> Vec<Constrained<Arc<Frame>>> { + ) -> TypResult<Vec<Constrained<Arc<Frame>>>> { // Collect all text into one string used for BiDi analysis. let text = self.collect_text(); @@ -95,10 +95,10 @@ impl Layout for ParNode { // Prepare paragraph layout by building a representation on which we can // do line breaking without layouting each and every line from scratch. - let layouter = ParLayouter::new(self, vm, regions, &styles, bidi); + let layouter = ParLayouter::new(self, vm, regions, &styles, bidi)?; // Find suitable linebreaks. - layouter.layout(vm, regions.clone()) + Ok(layouter.layout(vm, regions.clone())) } } @@ -220,7 +220,7 @@ impl<'a> ParLayouter<'a> { regions: &Regions, styles: &'a StyleChain<'a>, bidi: BidiInfo<'a>, - ) -> Self { + ) -> TypResult<Self> { let mut items = vec![]; let mut ranges = vec![]; @@ -255,7 +255,7 @@ impl<'a> ParLayouter<'a> { ParChild::Node(node) => { let size = Size::new(regions.current.x, regions.base.y); let pod = Regions::one(size, regions.base, Spec::splat(false)); - let frame = node.layout(vm, &pod, styles).remove(0); + let frame = node.layout(vm, &pod, styles)?.remove(0); items.push(ParItem::Frame(Arc::take(frame.item))); ranges.push(range); } @@ -266,7 +266,7 @@ impl<'a> ParLayouter<'a> { let align = styles.get(ParNode::ALIGN); let leading = styles.get(ParNode::LEADING).resolve(em); - Self { align, leading, bidi, items, ranges } + Ok(Self { align, leading, bidi, items, ranges }) } /// Find first-fit line breaks and build the paragraph. diff --git a/src/library/place.rs b/src/library/place.rs index c2c9ac25..9bcd3c37 100644 --- a/src/library/place.rs +++ b/src/library/place.rs @@ -26,7 +26,7 @@ impl Layout for PlaceNode { vm: &mut Vm, regions: &Regions, styles: StyleChain, - ) -> Vec<Constrained<Arc<Frame>>> { + ) -> TypResult<Vec<Constrained<Arc<Frame>>>> { let out_of_flow = self.out_of_flow(); // The pod is the base area of the region because for absolute @@ -37,7 +37,7 @@ impl Layout for PlaceNode { Regions::one(regions.base, regions.base, expand) }; - let mut frames = self.0.layout(vm, &pod, styles); + let mut frames = self.0.layout(vm, &pod, styles)?; let Constrained { item: frame, cts } = &mut frames[0]; // If expansion is off, zero all sizes so that we don't take up any @@ -51,7 +51,7 @@ impl Layout for PlaceNode { cts.base = regions.base.map(Some); cts.exact = regions.current.filter(regions.expand | out_of_flow); - frames + Ok(frames) } } diff --git a/src/library/raw.rs b/src/library/raw.rs index 45733fd0..da926679 100644 --- a/src/library/raw.rs +++ b/src/library/raw.rs @@ -40,7 +40,7 @@ impl RawNode { } impl Show for RawNode { - fn show(&self, styles: StyleChain) -> Template { + fn show(&self, _: &mut Vm, styles: StyleChain) -> TypResult<Template> { let lang = styles.get_ref(Self::LANG).as_ref(); let foreground = THEME .settings @@ -87,7 +87,7 @@ impl Show for RawNode { template = Template::Block(template.pack()); } - template.monospaced() + Ok(template.monospaced()) } } diff --git a/src/library/shape.rs b/src/library/shape.rs index acb011ea..518254ce 100644 --- a/src/library/shape.rs +++ b/src/library/shape.rs @@ -49,7 +49,7 @@ impl<const S: ShapeKind> Layout for ShapeNode<S> { vm: &mut Vm, regions: &Regions, styles: StyleChain, - ) -> Vec<Constrained<Arc<Frame>>> { + ) -> TypResult<Vec<Constrained<Arc<Frame>>>> { let mut frames; if let Some(child) = &self.0 { let mut padding = styles.get(Self::PADDING); @@ -61,7 +61,7 @@ impl<const S: ShapeKind> Layout for ShapeNode<S> { let child = child.clone().padded(Sides::splat(padding)); let mut pod = Regions::one(regions.current, regions.base, regions.expand); - frames = child.layout(vm, &pod, styles); + frames = child.layout(vm, &pod, styles)?; // Relayout with full expansion into square region to make sure // the result is really a square or circle. @@ -77,7 +77,7 @@ impl<const S: ShapeKind> Layout for ShapeNode<S> { pod.current = Size::splat(length); pod.expand = Spec::splat(true); - frames = child.layout(vm, &pod, styles); + frames = child.layout(vm, &pod, styles)?; frames[0].cts = Constraints::tight(regions); } } else { @@ -127,7 +127,7 @@ impl<const S: ShapeKind> Layout for ShapeNode<S> { frame.link(url); } - frames + Ok(frames) } } diff --git a/src/library/stack.rs b/src/library/stack.rs index 287731b8..c7985d87 100644 --- a/src/library/stack.rs +++ b/src/library/stack.rs @@ -31,7 +31,7 @@ impl Layout for StackNode { vm: &mut Vm, regions: &Regions, styles: StyleChain, - ) -> Vec<Constrained<Arc<Frame>>> { + ) -> TypResult<Vec<Constrained<Arc<Frame>>>> { let mut layouter = StackLayouter::new(self.dir, regions); // Spacing to insert before the next node. @@ -48,13 +48,13 @@ impl Layout for StackNode { layouter.layout_spacing(kind); } - layouter.layout_node(vm, node, styles); + layouter.layout_node(vm, node, styles)?; deferred = self.spacing; } } } - layouter.finish() + Ok(layouter.finish()) } } @@ -163,7 +163,12 @@ impl StackLayouter { } /// Layout an arbitrary node. - pub fn layout_node(&mut self, vm: &mut Vm, node: &LayoutNode, styles: StyleChain) { + pub fn layout_node( + &mut self, + vm: &mut Vm, + node: &LayoutNode, + styles: StyleChain, + ) -> TypResult<()> { if self.regions.is_full() { self.finish_region(); } @@ -174,7 +179,7 @@ impl StackLayouter { .and_then(|node| node.aligns.get(self.axis)) .unwrap_or(self.dir.start().into()); - let frames = node.layout(vm, &self.regions, styles); + let frames = node.layout(vm, &self.regions, styles)?; let len = frames.len(); for (i, frame) in frames.into_iter().enumerate() { // Grow our size, shrink the region and save the frame for later. @@ -188,6 +193,8 @@ impl StackLayouter { self.finish_region(); } } + + Ok(()) } /// Advance to the next region. diff --git a/src/library/table.rs b/src/library/table.rs index dfefa21d..8c088c09 100644 --- a/src/library/table.rs +++ b/src/library/table.rs @@ -55,7 +55,7 @@ impl TableNode { } impl Show for TableNode { - fn show(&self, styles: StyleChain) -> Template { + fn show(&self, _: &mut Vm, styles: StyleChain) -> TypResult<Template> { let primary = styles.get(Self::PRIMARY); let secondary = styles.get(Self::SECONDARY); let thickness = styles.get(Self::THICKNESS); @@ -85,10 +85,10 @@ impl Show for TableNode { }) .collect(); - Template::block(GridNode { + Ok(Template::block(GridNode { tracks: self.tracks.clone(), gutter: self.gutter.clone(), children, - }) + })) } } diff --git a/src/library/text.rs b/src/library/text.rs index 9fbc8605..721a8eac 100644 --- a/src/library/text.rs +++ b/src/library/text.rs @@ -123,8 +123,8 @@ impl StrongNode { } impl Show for StrongNode { - fn show(&self, _: StyleChain) -> Template { - self.0.clone().styled(TextNode::STRONG, true) + fn show(&self, _: &mut Vm, _: StyleChain) -> TypResult<Template> { + Ok(self.0.clone().styled(TextNode::STRONG, true)) } } @@ -140,8 +140,8 @@ impl EmphNode { } impl Show for EmphNode { - fn show(&self, _: StyleChain) -> Template { - self.0.clone().styled(TextNode::EMPH, true) + fn show(&self, _: &mut Vm, _: StyleChain) -> TypResult<Template> { + Ok(self.0.clone().styled(TextNode::EMPH, true)) } } diff --git a/src/library/transform.rs b/src/library/transform.rs index 91d4b574..5cdb2f6f 100644 --- a/src/library/transform.rs +++ b/src/library/transform.rs @@ -49,9 +49,9 @@ impl<const T: TransformKind> Layout for TransformNode<T> { vm: &mut Vm, regions: &Regions, styles: StyleChain, - ) -> Vec<Constrained<Arc<Frame>>> { + ) -> TypResult<Vec<Constrained<Arc<Frame>>>> { let origin = styles.get(Self::ORIGIN).unwrap_or(Align::CENTER_HORIZON); - let mut frames = self.child.layout(vm, regions, styles); + let mut frames = self.child.layout(vm, regions, styles)?; for Constrained { item: frame, .. } in &mut frames { let Spec { x, y } = origin.zip(frame.size).map(|(o, s)| o.resolve(s)); @@ -62,7 +62,7 @@ impl<const T: TransformKind> Layout for TransformNode<T> { Arc::make_mut(frame).transform(transform); } - frames + Ok(frames) } } |
