Cleaner separation between single and multi-region layout

This commit is contained in:
Laurenz 2024-01-18 11:47:45 +01:00
parent 6ac71eeaf7
commit fae358968f
30 changed files with 191 additions and 206 deletions

View File

@ -4,7 +4,8 @@ use crate::diag::SourceResult;
use crate::engine::Engine; use crate::engine::Engine;
use crate::foundations::{elem, Behave, Behaviour, Content, Packed, StyleChain}; use crate::foundations::{elem, Behave, Behaviour, Content, Packed, StyleChain};
use crate::layout::{ use crate::layout::{
Abs, Axes, Dir, Fragment, Frame, Layout, Length, Point, Ratio, Regions, Rel, Size, Abs, Axes, Dir, Fragment, Frame, LayoutMultiple, Length, Point, Ratio, Regions, Rel,
Size,
}; };
use crate::text::TextElem; use crate::text::TextElem;
use crate::util::Numeric; use crate::util::Numeric;
@ -40,7 +41,7 @@ use crate::util::Numeric;
/// increasingly been used to solve a /// increasingly been used to solve a
/// variety of problems. /// variety of problems.
/// ``` /// ```
#[elem(Layout)] #[elem(LayoutMultiple)]
pub struct ColumnsElem { pub struct ColumnsElem {
/// The number of columns. /// The number of columns.
#[positional] #[positional]
@ -57,7 +58,7 @@ pub struct ColumnsElem {
pub body: Content, pub body: Content,
} }
impl Layout for Packed<ColumnsElem> { impl LayoutMultiple for Packed<ColumnsElem> {
#[typst_macros::time(name = "columns", span = self.span())] #[typst_macros::time(name = "columns", span = self.span())]
fn layout( fn layout(
&self, &self,

View File

@ -4,8 +4,8 @@ use crate::foundations::{
cast, elem, AutoValue, Content, Packed, Resolve, Smart, StyleChain, Value, cast, elem, AutoValue, Content, Packed, Resolve, Smart, StyleChain, Value,
}; };
use crate::layout::{ use crate::layout::{
Abs, Axes, Corners, Em, Fr, Fragment, FrameKind, Layout, Length, Ratio, Regions, Rel, Abs, Axes, Corners, Em, Fr, Fragment, Frame, FrameKind, LayoutMultiple, Length,
Sides, Size, Spacing, VElem, Ratio, Regions, Rel, Sides, Size, Spacing, VElem,
}; };
use crate::util::Numeric; use crate::util::Numeric;
use crate::visualize::{clip_rect, Paint, Stroke}; use crate::visualize::{clip_rect, Paint, Stroke};
@ -26,7 +26,7 @@ use crate::visualize::{clip_rect, Paint, Stroke};
/// ) /// )
/// for more information. /// for more information.
/// ``` /// ```
#[elem(Layout)] #[elem]
pub struct BoxElem { pub struct BoxElem {
/// The width of the box. /// The width of the box.
/// ///
@ -109,14 +109,14 @@ pub struct BoxElem {
pub body: Option<Content>, pub body: Option<Content>,
} }
impl Layout for Packed<BoxElem> { impl Packed<BoxElem> {
#[typst_macros::time(name = "box", span = self.span())] #[typst_macros::time(name = "box", span = self.span())]
fn layout( pub fn layout(
&self, &self,
engine: &mut Engine, engine: &mut Engine,
styles: StyleChain, styles: StyleChain,
regions: Regions, regions: Regions,
) -> SourceResult<Fragment> { ) -> SourceResult<Frame> {
let width = match self.width(styles) { let width = match self.width(styles) {
Sizing::Auto => Smart::Auto, Sizing::Auto => Smart::Auto,
Sizing::Rel(rel) => Smart::Custom(rel), Sizing::Rel(rel) => Smart::Custom(rel),
@ -174,7 +174,7 @@ impl Layout for Packed<BoxElem> {
// Apply metadata. // Apply metadata.
frame.set_kind(FrameKind::Hard); frame.set_kind(FrameKind::Hard);
Ok(Fragment::frame(frame)) Ok(frame)
} }
} }
@ -207,7 +207,7 @@ impl Layout for Packed<BoxElem> {
/// = Blocky /// = Blocky
/// More text. /// More text.
/// ``` /// ```
#[elem(Layout)] #[elem(LayoutMultiple)]
pub struct BlockElem { pub struct BlockElem {
/// The block's width. /// The block's width.
/// ///
@ -340,7 +340,7 @@ pub struct BlockElem {
pub sticky: bool, pub sticky: bool,
} }
impl Layout for Packed<BlockElem> { impl LayoutMultiple for Packed<BlockElem> {
#[typst_macros::time(name = "block", span = self.span())] #[typst_macros::time(name = "block", span = self.span())]
fn layout( fn layout(
&self, &self,

View File

@ -10,28 +10,24 @@ use crate::foundations::{
use crate::introspection::{Meta, MetaElem}; use crate::introspection::{Meta, MetaElem};
use crate::layout::{ use crate::layout::{
Abs, AlignElem, Axes, BlockElem, ColbreakElem, ColumnsElem, FixedAlignment, Fr, Abs, AlignElem, Axes, BlockElem, ColbreakElem, ColumnsElem, FixedAlignment, Fr,
Fragment, Frame, FrameItem, Layout, PlaceElem, Point, Regions, Rel, Size, Spacing, Fragment, Frame, FrameItem, LayoutMultiple, LayoutSingle, PlaceElem, Point, Regions,
VAlignment, VElem, Rel, Size, Spacing, VAlignment, VElem,
}; };
use crate::model::{FootnoteElem, FootnoteEntry, ParElem}; use crate::model::{FootnoteElem, FootnoteEntry, ParElem};
use crate::util::Numeric; use crate::util::Numeric;
use crate::visualize::{
CircleElem, EllipseElem, ImageElem, LineElem, PathElem, PolygonElem, RectElem,
SquareElem,
};
/// Arranges spacing, paragraphs and block-level elements into a flow. /// Arranges spacing, paragraphs and block-level elements into a flow.
/// ///
/// This element is responsible for layouting both the top-level content flow /// This element is responsible for layouting both the top-level content flow
/// and the contents of boxes. /// and the contents of boxes.
#[elem(Debug, Layout)] #[elem(Debug, LayoutMultiple)]
pub struct FlowElem { pub struct FlowElem {
/// The children that will be arranges into a flow. /// The children that will be arranges into a flow.
#[variadic] #[variadic]
pub children: Vec<Prehashed<Content>>, pub children: Vec<Prehashed<Content>>,
} }
impl Layout for Packed<FlowElem> { impl LayoutMultiple for Packed<FlowElem> {
#[typst_macros::time(name = "flow", span = self.span())] #[typst_macros::time(name = "flow", span = self.span())]
fn layout( fn layout(
&self, &self,
@ -45,8 +41,8 @@ impl Layout for Packed<FlowElem> {
if !regions.size.y.is_finite() && regions.expand.y { if !regions.size.y.is_finite() && regions.expand.y {
bail!(self.span(), "cannot expand into infinite height"); bail!(self.span(), "cannot expand into infinite height");
} }
let mut layouter = FlowLayouter::new(regions, styles);
let mut layouter = FlowLayouter::new(regions, styles);
for mut child in self.children().iter().map(|c| &**c) { for mut child in self.children().iter().map(|c| &**c) {
let outer = styles; let outer = styles;
let mut styles = styles; let mut styles = styles;
@ -55,32 +51,23 @@ impl Layout for Packed<FlowElem> {
styles = outer.chain(map); styles = outer.chain(map);
} }
if let Some(elem) = child.to_packed::<VElem>() { if child.is::<MetaElem>() {
layouter.layout_spacing(engine, elem, styles)?;
} else if let Some(elem) = child.to_packed::<ParElem>() {
layouter.layout_par(engine, elem, styles)?;
} else if child.is::<LineElem>()
|| child.is::<RectElem>()
|| child.is::<SquareElem>()
|| child.is::<EllipseElem>()
|| child.is::<CircleElem>()
|| child.is::<ImageElem>()
|| child.is::<PolygonElem>()
|| child.is::<PathElem>()
{
let layoutable = child.with::<dyn Layout>().unwrap();
layouter.layout_single(engine, layoutable, styles)?;
} else if child.is::<MetaElem>() {
layouter.layout_meta(styles); layouter.layout_meta(styles);
} else if let Some(elem) = child.to_packed::<VElem>() {
layouter.layout_spacing(engine, elem, styles)?;
} else if let Some(placed) = child.to_packed::<PlaceElem>() { } else if let Some(placed) = child.to_packed::<PlaceElem>() {
layouter.layout_placed(engine, placed, styles)?; layouter.layout_placed(engine, placed, styles)?;
} else if child.can::<dyn Layout>() {
layouter.layout_multiple(engine, child, styles)?;
} else if child.is::<ColbreakElem>() { } else if child.is::<ColbreakElem>() {
if !layouter.regions.backlog.is_empty() || layouter.regions.last.is_some() if !layouter.regions.backlog.is_empty() || layouter.regions.last.is_some()
{ {
layouter.finish_region(engine, true)?; layouter.finish_region(engine, true)?;
} }
} else if let Some(elem) = child.to_packed::<ParElem>() {
layouter.layout_par(engine, elem, styles)?;
} else if let Some(layoutable) = child.with::<dyn LayoutSingle>() {
layouter.layout_single(engine, layoutable, styles)?;
} else if child.can::<dyn LayoutMultiple>() {
layouter.layout_multiple(engine, child, styles)?;
} else { } else {
bail!(child.span(), "unexpected flow child"); bail!(child.span(), "unexpected flow child");
} }
@ -207,6 +194,18 @@ impl<'a> FlowLayouter<'a> {
} }
} }
/// Place explicit metadata into the flow.
fn layout_meta(&mut self, styles: StyleChain) {
let mut frame = Frame::soft(Size::zero());
frame.meta(styles, true);
self.items.push(FlowItem::Frame {
frame,
align: Axes::splat(FixedAlignment::Start),
sticky: true,
movable: false,
});
}
/// Layout vertical spacing. /// Layout vertical spacing.
fn layout_spacing( fn layout_spacing(
&mut self, &mut self,
@ -284,13 +283,13 @@ impl<'a> FlowLayouter<'a> {
fn layout_single( fn layout_single(
&mut self, &mut self,
engine: &mut Engine, engine: &mut Engine,
content: &dyn Layout, layoutable: &dyn LayoutSingle,
styles: StyleChain, styles: StyleChain,
) -> SourceResult<()> { ) -> SourceResult<()> {
let align = AlignElem::alignment_in(styles).resolve(styles); let align = AlignElem::alignment_in(styles).resolve(styles);
let sticky = BlockElem::sticky_in(styles); let sticky = BlockElem::sticky_in(styles);
let pod = Regions::one(self.regions.base(), Axes::splat(false)); let pod = Regions::one(self.regions.base(), Axes::splat(false));
let mut frame = content.layout(engine, styles, pod)?.into_frame(); let mut frame = layoutable.layout(engine, styles, pod)?;
frame.meta(styles, false); frame.meta(styles, false);
self.layout_item( self.layout_item(
engine, engine,
@ -300,18 +299,6 @@ impl<'a> FlowLayouter<'a> {
Ok(()) Ok(())
} }
/// Place explicit metadata into the flow.
fn layout_meta(&mut self, styles: StyleChain) {
let mut frame = Frame::soft(Size::zero());
frame.meta(styles, true);
self.items.push(FlowItem::Frame {
frame,
align: Axes::splat(FixedAlignment::Start),
sticky: true,
movable: false,
});
}
/// Layout a placed element. /// Layout a placed element.
fn layout_placed( fn layout_placed(
&mut self, &mut self,
@ -337,12 +324,12 @@ impl<'a> FlowLayouter<'a> {
fn layout_multiple( fn layout_multiple(
&mut self, &mut self,
engine: &mut Engine, engine: &mut Engine,
block: &Content, child: &Content,
styles: StyleChain, styles: StyleChain,
) -> SourceResult<()> { ) -> SourceResult<()> {
// Temporarily delegerate rootness to the columns. // Temporarily delegerate rootness to the columns.
let is_root = self.root; let is_root = self.root;
if is_root && block.is::<ColumnsElem>() { if is_root && child.is::<ColumnsElem>() {
self.root = false; self.root = false;
self.regions.root = true; self.regions.root = true;
} }
@ -355,9 +342,9 @@ impl<'a> FlowLayouter<'a> {
} }
// How to align the block. // How to align the block.
let align = if let Some(align) = block.to_packed::<AlignElem>() { let align = if let Some(align) = child.to_packed::<AlignElem>() {
align.alignment(styles) align.alignment(styles)
} else if let Some((_, local)) = block.to_styled() { } else if let Some((_, local)) = child.to_styled() {
AlignElem::alignment_in(styles.chain(local)) AlignElem::alignment_in(styles.chain(local))
} else { } else {
AlignElem::alignment_in(styles) AlignElem::alignment_in(styles)
@ -366,7 +353,7 @@ impl<'a> FlowLayouter<'a> {
// Layout the block itself. // Layout the block itself.
let sticky = BlockElem::sticky_in(styles); let sticky = BlockElem::sticky_in(styles);
let fragment = block.layout(engine, styles, self.regions)?; let fragment = child.layout(engine, styles, self.regions)?;
for (i, mut frame) in fragment.into_iter().enumerate() { for (i, mut frame) in fragment.into_iter().enumerate() {
// Find footnotes in the frame. // Find footnotes in the frame.

View File

@ -9,8 +9,8 @@ use crate::foundations::{
StyleChain, Value, StyleChain, Value,
}; };
use crate::layout::{ use crate::layout::{
Abs, Alignment, Axes, Dir, Fr, Fragment, Frame, FrameItem, Layout, Length, Point, Abs, Alignment, Axes, Dir, Fr, Fragment, Frame, FrameItem, LayoutMultiple, Length,
Regions, Rel, Sides, Size, Sizing, Point, Regions, Rel, Sides, Size, Sizing,
}; };
use crate::syntax::Span; use crate::syntax::Span;
use crate::text::TextElem; use crate::text::TextElem;
@ -102,7 +102,7 @@ impl From<Content> for Cell {
} }
} }
impl Layout for Cell { impl LayoutMultiple for Cell {
fn layout( fn layout(
&self, &self,
engine: &mut Engine, engine: &mut Engine,

View File

@ -13,8 +13,8 @@ use crate::foundations::{
cast, elem, scope, Array, Content, Fold, Packed, Show, Smart, StyleChain, Value, cast, elem, scope, Array, Content, Fold, Packed, Show, Smart, StyleChain, Value,
}; };
use crate::layout::{ use crate::layout::{
Abs, AlignElem, Alignment, Axes, Fragment, Layout, Length, Regions, Rel, Sides, Abs, AlignElem, Alignment, Axes, Fragment, LayoutMultiple, Length, Regions, Rel,
Sizing, Sides, Sizing,
}; };
use crate::syntax::Span; use crate::syntax::Span;
use crate::visualize::{Paint, Stroke}; use crate::visualize::{Paint, Stroke};
@ -154,7 +154,7 @@ use crate::visualize::{Paint, Stroke};
/// grid.cell(y: 2, fill: aqua)[Walk], /// grid.cell(y: 2, fill: aqua)[Walk],
/// ) /// )
/// ``` /// ```
#[elem(scope, Layout)] #[elem(scope, LayoutMultiple)]
pub struct GridElem { pub struct GridElem {
/// The column sizes. /// The column sizes.
/// ///
@ -279,7 +279,7 @@ impl GridElem {
type GridCell; type GridCell;
} }
impl Layout for Packed<GridElem> { impl LayoutMultiple for Packed<GridElem> {
#[typst_macros::time(name = "grid", span = self.span())] #[typst_macros::time(name = "grid", span = self.span())]
fn layout( fn layout(
&self, &self,

View File

@ -17,7 +17,7 @@ use crate::foundations::{Content, Packed, Resolve, Smart, StyleChain};
use crate::introspection::{Introspector, Locator, MetaElem}; use crate::introspection::{Introspector, Locator, MetaElem};
use crate::layout::{ use crate::layout::{
Abs, AlignElem, Axes, BoxElem, Dir, Em, FixedAlignment, Fr, Fragment, Frame, HElem, Abs, AlignElem, Axes, BoxElem, Dir, Em, FixedAlignment, Fr, Fragment, Frame, HElem,
Layout, Point, Regions, Size, Sizing, Spacing, Point, Regions, Size, Sizing, Spacing,
}; };
use crate::math::{EquationElem, MathParItem}; use crate::math::{EquationElem, MathParItem};
use crate::model::{Linebreaks, ParElem}; use crate::model::{Linebreaks, ParElem};
@ -594,7 +594,7 @@ fn prepare<'a>(
items.push(Item::Fractional(v, Some((elem, styles)))); items.push(Item::Fractional(v, Some((elem, styles))));
} else { } else {
let pod = Regions::one(region, Axes::splat(false)); let pod = Regions::one(region, Axes::splat(false));
let mut frame = elem.layout(engine, styles, pod)?.into_frame(); let mut frame = elem.layout(engine, styles, pod)?;
frame.meta(styles, false); frame.meta(styles, false);
frame.translate(Point::with_y(TextElem::baseline_in(styles))); frame.translate(Point::with_y(TextElem::baseline_in(styles)));
items.push(Item::Frame(frame)); items.push(Item::Frame(frame));
@ -1319,7 +1319,7 @@ fn commit(
if let Some((elem, styles)) = elem { if let Some((elem, styles)) = elem {
let region = Size::new(amount, full); let region = Size::new(amount, full);
let pod = Regions::one(region, Axes::new(true, false)); let pod = Regions::one(region, Axes::new(true, false));
let mut frame = elem.layout(engine, *styles, pod)?.into_frame(); let mut frame = elem.layout(engine, *styles, pod)?;
frame.meta(*styles, false); frame.meta(*styles, false);
frame.translate(Point::with_y(TextElem::baseline_in(*styles))); frame.translate(Point::with_y(TextElem::baseline_in(*styles)));
push(&mut offset, frame); push(&mut offset, frame);

View File

@ -3,7 +3,7 @@ use crate::engine::Engine;
use crate::foundations::{ use crate::foundations::{
dict, elem, func, Content, Func, NativeElement, Packed, StyleChain, dict, elem, func, Content, Func, NativeElement, Packed, StyleChain,
}; };
use crate::layout::{Fragment, Layout, Regions, Size}; use crate::layout::{Fragment, LayoutMultiple, Regions, Size};
use crate::syntax::Span; use crate::syntax::Span;
/// Provides access to the current outer container's (or page's, if none) size /// Provides access to the current outer container's (or page's, if none) size
@ -63,14 +63,14 @@ pub fn layout(
} }
/// Executes a `layout` call. /// Executes a `layout` call.
#[elem(Layout)] #[elem(LayoutMultiple)]
struct LayoutElem { struct LayoutElem {
/// The function to call with the outer container's (or page's) size. /// The function to call with the outer container's (or page's) size.
#[required] #[required]
func: Func, func: Func,
} }
impl Layout for Packed<LayoutElem> { impl LayoutMultiple for Packed<LayoutElem> {
#[typst_macros::time(name = "layout", span = self.span())] #[typst_macros::time(name = "layout", span = self.span())]
fn layout( fn layout(
&self, &self,

View File

@ -1,7 +1,7 @@
use crate::diag::SourceResult; use crate::diag::SourceResult;
use crate::engine::Engine; use crate::engine::Engine;
use crate::foundations::{dict, func, Content, Dict, StyleChain, Styles}; use crate::foundations::{dict, func, Content, Dict, StyleChain, Styles};
use crate::layout::{Abs, Axes, Layout, Regions, Size}; use crate::layout::{Abs, Axes, LayoutMultiple, Regions, Size};
/// Measures the layouted size of content. /// Measures the layouted size of content.
/// ///

View File

@ -120,7 +120,7 @@ pub fn define(global: &mut Scope) {
/// Root-level layout. /// Root-level layout.
pub trait LayoutRoot { pub trait LayoutRoot {
/// Layout into one frame per page. /// Layout into a document with one frame per page.
fn layout_root( fn layout_root(
&self, &self,
engine: &mut Engine, engine: &mut Engine,
@ -128,8 +128,8 @@ pub trait LayoutRoot {
) -> SourceResult<Document>; ) -> SourceResult<Document>;
} }
/// Layout into regions. /// Layout into multiple regions.
pub trait Layout { pub trait LayoutMultiple {
/// Layout into one frame per region. /// Layout into one frame per region.
fn layout( fn layout(
&self, &self,
@ -160,8 +160,18 @@ pub trait Layout {
} }
} }
/// Layout into a single region.
pub trait LayoutSingle {
/// Layout into one frame per region.
fn layout(
&self,
engine: &mut Engine,
styles: StyleChain,
regions: Regions,
) -> SourceResult<Frame>;
}
impl LayoutRoot for Content { impl LayoutRoot for Content {
#[typst_macros::time(name = "layout root", span = self.span())]
fn layout_root( fn layout_root(
&self, &self,
engine: &mut Engine, engine: &mut Engine,
@ -186,12 +196,9 @@ impl LayoutRoot for Content {
tracer, tracer,
}; };
let scratch = Scratch::default(); let scratch = Scratch::default();
let (realized, styles) = let (document, styles) =
realize_root(&mut engine, &scratch, content, styles)?; realize_root(&mut engine, &scratch, content, styles)?;
realized document.layout_root(&mut engine, styles)
.with::<dyn LayoutRoot>()
.unwrap()
.layout_root(&mut engine, styles)
} }
cached( cached(
@ -206,7 +213,7 @@ impl LayoutRoot for Content {
} }
} }
impl Layout for Content { impl LayoutMultiple for Content {
fn layout( fn layout(
&self, &self,
engine: &mut Engine, engine: &mut Engine,
@ -244,10 +251,11 @@ impl Layout for Content {
let scratch = Scratch::default(); let scratch = Scratch::default();
let (realized, styles) = let (realized, styles) =
realize_block(&mut engine, &scratch, content, styles)?; realize_block(&mut engine, &scratch, content, styles)?;
realized realized.with::<dyn LayoutMultiple>().unwrap().layout(
.with::<dyn Layout>() &mut engine,
.unwrap() styles,
.layout(&mut engine, styles, regions) regions,
)
} }
let fragment = cached( let fragment = cached(

View File

@ -1,7 +1,9 @@
use crate::diag::SourceResult; use crate::diag::SourceResult;
use crate::engine::Engine; use crate::engine::Engine;
use crate::foundations::{elem, Content, Packed, Resolve, StyleChain}; use crate::foundations::{elem, Content, Packed, Resolve, StyleChain};
use crate::layout::{Abs, Fragment, Layout, Length, Point, Regions, Rel, Sides, Size}; use crate::layout::{
Abs, Fragment, LayoutMultiple, Length, Point, Regions, Rel, Sides, Size,
};
/// Adds spacing around content. /// Adds spacing around content.
/// ///
@ -16,7 +18,7 @@ use crate::layout::{Abs, Fragment, Layout, Length, Point, Regions, Rel, Sides, S
/// _Typing speeds can be /// _Typing speeds can be
/// measured in words per minute._ /// measured in words per minute._
/// ``` /// ```
#[elem(title = "Padding", Layout)] #[elem(title = "Padding", LayoutMultiple)]
pub struct PadElem { pub struct PadElem {
/// The padding at the left side. /// The padding at the left side.
#[parse( #[parse(
@ -58,7 +60,7 @@ pub struct PadElem {
pub body: Content, pub body: Content,
} }
impl Layout for Packed<PadElem> { impl LayoutMultiple for Packed<PadElem> {
#[typst_macros::time(name = "pad", span = self.span())] #[typst_macros::time(name = "pad", span = self.span())]
fn layout( fn layout(
&self, &self,

View File

@ -11,8 +11,8 @@ use crate::foundations::{
}; };
use crate::introspection::{Counter, CounterKey, ManualPageCounter}; use crate::introspection::{Counter, CounterKey, ManualPageCounter};
use crate::layout::{ use crate::layout::{
Abs, AlignElem, Alignment, Axes, ColumnsElem, Dir, Frame, HAlignment, Layout, Length, Abs, AlignElem, Alignment, Axes, ColumnsElem, Dir, Frame, HAlignment, LayoutMultiple,
Point, Ratio, Regions, Rel, Sides, Size, VAlignment, Length, Point, Ratio, Regions, Rel, Sides, Size, VAlignment,
}; };
use crate::model::Numbering; use crate::model::Numbering;

View File

@ -2,7 +2,7 @@ use crate::diag::{bail, At, Hint, SourceResult};
use crate::engine::Engine; use crate::engine::Engine;
use crate::foundations::{elem, Behave, Behaviour, Content, Packed, Smart, StyleChain}; use crate::foundations::{elem, Behave, Behaviour, Content, Packed, Smart, StyleChain};
use crate::layout::{ use crate::layout::{
Alignment, Axes, Em, Fragment, Layout, Length, Regions, Rel, VAlignment, Alignment, Axes, Em, Fragment, LayoutMultiple, Length, Regions, Rel, VAlignment,
}; };
/// Places content at an absolute position. /// Places content at an absolute position.
@ -25,7 +25,7 @@ use crate::layout::{
/// ), /// ),
/// ) /// )
/// ``` /// ```
#[elem(Layout, Behave)] #[elem(Behave)]
pub struct PlaceElem { pub struct PlaceElem {
/// Relative to which position in the parent container to place the content. /// Relative to which position in the parent container to place the content.
/// ///
@ -86,9 +86,9 @@ pub struct PlaceElem {
pub body: Content, pub body: Content,
} }
impl Layout for Packed<PlaceElem> { impl Packed<PlaceElem> {
#[typst_macros::time(name = "place", span = self.span())] #[typst_macros::time(name = "place", span = self.span())]
fn layout( pub fn layout(
&self, &self,
engine: &mut Engine, engine: &mut Engine,
styles: StyleChain, styles: StyleChain,

View File

@ -2,7 +2,7 @@ use crate::diag::{bail, SourceResult};
use crate::engine::Engine; use crate::engine::Engine;
use crate::foundations::{elem, Content, Packed, Resolve, StyleChain}; use crate::foundations::{elem, Content, Packed, Resolve, StyleChain};
use crate::layout::{ use crate::layout::{
Abs, AlignElem, Axes, Fragment, Frame, Layout, Point, Regions, Size, Abs, AlignElem, Axes, Fragment, Frame, LayoutMultiple, Point, Regions, Size,
}; };
use crate::util::Numeric; use crate::util::Numeric;
@ -27,14 +27,14 @@ use crate::util::Numeric;
/// Berlin, the 22nd of December, 2022 /// Berlin, the 22nd of December, 2022
/// ] /// ]
/// ``` /// ```
#[elem(Layout)] #[elem(LayoutMultiple)]
pub struct RepeatElem { pub struct RepeatElem {
/// The content to repeat. /// The content to repeat.
#[required] #[required]
pub body: Content, pub body: Content,
} }
impl Layout for Packed<RepeatElem> { impl LayoutMultiple for Packed<RepeatElem> {
#[typst_macros::time(name = "repeat", span = self.span())] #[typst_macros::time(name = "repeat", span = self.span())]
fn layout( fn layout(
&self, &self,

View File

@ -4,8 +4,8 @@ use crate::diag::SourceResult;
use crate::engine::Engine; use crate::engine::Engine;
use crate::foundations::{cast, elem, Content, Packed, Resolve, StyleChain}; use crate::foundations::{cast, elem, Content, Packed, Resolve, StyleChain};
use crate::layout::{ use crate::layout::{
Abs, AlignElem, Axes, Axis, Dir, FixedAlignment, Fr, Fragment, Frame, Layout, Point, Abs, AlignElem, Axes, Axis, Dir, FixedAlignment, Fr, Fragment, Frame, LayoutMultiple,
Regions, Size, Spacing, Point, Regions, Size, Spacing,
}; };
use crate::util::{Get, Numeric}; use crate::util::{Get, Numeric};
@ -23,7 +23,7 @@ use crate::util::{Get, Numeric};
/// rect(width: 90pt), /// rect(width: 90pt),
/// ) /// )
/// ``` /// ```
#[elem(Layout)] #[elem(LayoutMultiple)]
pub struct StackElem { pub struct StackElem {
/// The direction along which the items are stacked. Possible values are: /// The direction along which the items are stacked. Possible values are:
/// ///
@ -51,7 +51,7 @@ pub struct StackElem {
pub children: Vec<StackChild>, pub children: Vec<StackChild>,
} }
impl Layout for Packed<StackElem> { impl LayoutMultiple for Packed<StackElem> {
#[typst_macros::time(name = "stack", span = self.span())] #[typst_macros::time(name = "stack", span = self.span())]
fn layout( fn layout(
&self, &self,

View File

@ -2,8 +2,8 @@ use crate::diag::SourceResult;
use crate::engine::Engine; use crate::engine::Engine;
use crate::foundations::{elem, Content, Packed, Resolve, StyleChain}; use crate::foundations::{elem, Content, Packed, Resolve, StyleChain};
use crate::layout::{ use crate::layout::{
Abs, Alignment, Angle, Axes, FixedAlignment, Fragment, Frame, HAlignment, Layout, Abs, Alignment, Angle, Axes, FixedAlignment, Frame, HAlignment, LayoutMultiple,
Length, Point, Ratio, Regions, Rel, Size, VAlignment, LayoutSingle, Length, Point, Ratio, Regions, Rel, Size, VAlignment,
}; };
/// Moves content without affecting layout. /// Moves content without affecting layout.
@ -24,7 +24,7 @@ use crate::layout::{
/// ) /// )
/// )) /// ))
/// ``` /// ```
#[elem(Layout)] #[elem(LayoutSingle)]
pub struct MoveElem { pub struct MoveElem {
/// The horizontal displacement of the content. /// The horizontal displacement of the content.
pub dx: Rel<Length>, pub dx: Rel<Length>,
@ -37,20 +37,20 @@ pub struct MoveElem {
pub body: Content, pub body: Content,
} }
impl Layout for Packed<MoveElem> { impl LayoutSingle for Packed<MoveElem> {
#[typst_macros::time(name = "move", span = self.span())] #[typst_macros::time(name = "move", span = self.span())]
fn layout( fn layout(
&self, &self,
engine: &mut Engine, engine: &mut Engine,
styles: StyleChain, styles: StyleChain,
regions: Regions, regions: Regions,
) -> SourceResult<Fragment> { ) -> SourceResult<Frame> {
let pod = Regions::one(regions.base(), Axes::splat(false)); let pod = Regions::one(regions.base(), Axes::splat(false));
let mut frame = self.body().layout(engine, styles, pod)?.into_frame(); let mut frame = self.body().layout(engine, styles, pod)?.into_frame();
let delta = Axes::new(self.dx(styles), self.dy(styles)).resolve(styles); let delta = Axes::new(self.dx(styles), self.dy(styles)).resolve(styles);
let delta = delta.zip_map(regions.base(), Rel::relative_to); let delta = delta.zip_map(regions.base(), Rel::relative_to);
frame.translate(delta.to_point()); frame.translate(delta.to_point());
Ok(Fragment::frame(frame)) Ok(frame)
} }
} }
@ -68,7 +68,7 @@ impl Layout for Packed<MoveElem> {
/// .map(i => rotate(24deg * i)[X]), /// .map(i => rotate(24deg * i)[X]),
/// ) /// )
/// ``` /// ```
#[elem(Layout)] #[elem(LayoutSingle)]
pub struct RotateElem { pub struct RotateElem {
/// The amount of rotation. /// The amount of rotation.
/// ///
@ -115,14 +115,14 @@ pub struct RotateElem {
pub body: Content, pub body: Content,
} }
impl Layout for Packed<RotateElem> { impl LayoutSingle for Packed<RotateElem> {
#[typst_macros::time(name = "rotate", span = self.span())] #[typst_macros::time(name = "rotate", span = self.span())]
fn layout( fn layout(
&self, &self,
engine: &mut Engine, engine: &mut Engine,
styles: StyleChain, styles: StyleChain,
regions: Regions, regions: Regions,
) -> SourceResult<Fragment> { ) -> SourceResult<Frame> {
let angle = self.angle(styles); let angle = self.angle(styles);
let align = self.origin(styles).resolve(styles); let align = self.origin(styles).resolve(styles);
@ -157,7 +157,7 @@ impl Layout for Packed<RotateElem> {
/// #scale(x: -100%)[This is mirrored.] /// #scale(x: -100%)[This is mirrored.]
/// #scale(x: -100%, reflow: true)[This is mirrored.] /// #scale(x: -100%, reflow: true)[This is mirrored.]
/// ``` /// ```
#[elem(Layout)] #[elem(LayoutSingle)]
pub struct ScaleElem { pub struct ScaleElem {
/// The horizontal scaling factor. /// The horizontal scaling factor.
/// ///
@ -203,14 +203,14 @@ pub struct ScaleElem {
pub body: Content, pub body: Content,
} }
impl Layout for Packed<ScaleElem> { impl LayoutSingle for Packed<ScaleElem> {
#[typst_macros::time(name = "scale", span = self.span())] #[typst_macros::time(name = "scale", span = self.span())]
fn layout( fn layout(
&self, &self,
engine: &mut Engine, engine: &mut Engine,
styles: StyleChain, styles: StyleChain,
regions: Regions, regions: Regions,
) -> SourceResult<Fragment> { ) -> SourceResult<Frame> {
let sx = self.x(styles); let sx = self.x(styles);
let sy = self.y(styles); let sy = self.y(styles);
let align = self.origin(styles).resolve(styles); let align = self.origin(styles).resolve(styles);
@ -370,7 +370,7 @@ fn measure_and_layout(
transform: Transform, transform: Transform,
align: Axes<FixedAlignment>, align: Axes<FixedAlignment>,
reflow: bool, reflow: bool,
) -> SourceResult<Fragment> { ) -> SourceResult<Frame> {
if !reflow { if !reflow {
// Layout the body. // Layout the body.
let pod = Regions::one(base_size, Axes::splat(false)); let pod = Regions::one(base_size, Axes::splat(false));
@ -383,7 +383,7 @@ fn measure_and_layout(
.pre_concat(Transform::translate(-x, -y)); .pre_concat(Transform::translate(-x, -y));
frame.transform(ts); frame.transform(ts);
return Ok(Fragment::frame(frame)); return Ok(frame);
} }
// Measure the size of the body. // Measure the size of the body.
@ -405,7 +405,7 @@ fn measure_and_layout(
frame.transform(ts); frame.transform(ts);
frame.translate(offset); frame.translate(offset);
frame.set_size(size); frame.set_size(size);
Ok(Fragment::frame(frame)) Ok(frame)
} }
/// Computes the bounding box and offset of a transformed frame. /// Computes the bounding box and offset of a transformed frame.

View File

@ -13,7 +13,7 @@ use unicode_segmentation::UnicodeSegmentation;
use crate::diag::SourceResult; use crate::diag::SourceResult;
use crate::engine::Engine; use crate::engine::Engine;
use crate::foundations::{Content, Packed, Smart, StyleChain, Styles}; use crate::foundations::{Content, Packed, Smart, StyleChain, Styles};
use crate::layout::{Abs, Axes, BoxElem, Em, Frame, Layout, Regions, Size}; use crate::layout::{Abs, Axes, BoxElem, Em, Frame, LayoutMultiple, Regions, Size};
use crate::math::{ use crate::math::{
FrameFragment, GlyphFragment, LayoutMath, MathFragment, MathRow, MathSize, MathStyle, FrameFragment, GlyphFragment, LayoutMath, MathFragment, MathRow, MathSize, MathStyle,
MathVariant, THICK, MathVariant, THICK,
@ -174,9 +174,7 @@ impl<'a, 'b, 'v> MathContext<'a, 'b, 'v> {
} }
pub fn layout_box(&mut self, boxed: &Packed<BoxElem>) -> SourceResult<Frame> { pub fn layout_box(&mut self, boxed: &Packed<BoxElem>) -> SourceResult<Frame> {
Ok(boxed boxed.layout(self.engine, self.outer.chain(&self.local), self.regions)
.layout(self.engine, self.outer.chain(&self.local), self.regions)?
.into_frame())
} }
pub fn layout_content(&mut self, content: &Content) -> SourceResult<Frame> { pub fn layout_content(&mut self, content: &Content) -> SourceResult<Frame> {

View File

@ -8,8 +8,8 @@ use crate::foundations::{
}; };
use crate::introspection::{Count, Counter, CounterUpdate, Locatable}; use crate::introspection::{Count, Counter, CounterUpdate, Locatable};
use crate::layout::{ use crate::layout::{
Abs, AlignElem, Alignment, Axes, Dir, Em, FixedAlignment, Fragment, Frame, Layout, Abs, AlignElem, Alignment, Axes, Dir, Em, FixedAlignment, Frame, LayoutMultiple,
Point, Regions, Size, LayoutSingle, Point, Regions, Size,
}; };
use crate::math::{LayoutMath, MathContext}; use crate::math::{LayoutMath, MathContext};
use crate::model::{Numbering, Outlinable, ParElem, Refable, Supplement}; use crate::model::{Numbering, Outlinable, ParElem, Refable, Supplement};
@ -45,7 +45,15 @@ use crate::World;
/// horizontally. For more details about math syntax, see the /// horizontally. For more details about math syntax, see the
/// [main math page]($category/math). /// [main math page]($category/math).
#[elem( #[elem(
Locatable, Synthesize, Show, Finalize, Layout, LayoutMath, Count, LocalName, Refable, Locatable,
Synthesize,
Show,
Finalize,
LayoutSingle,
LayoutMath,
Count,
LocalName,
Refable,
Outlinable Outlinable
)] )]
pub struct EquationElem { pub struct EquationElem {
@ -194,14 +202,14 @@ impl Packed<EquationElem> {
} }
} }
impl Layout for Packed<EquationElem> { impl LayoutSingle for Packed<EquationElem> {
#[typst_macros::time(name = "math.equation", span = self.span())] #[typst_macros::time(name = "math.equation", span = self.span())]
fn layout( fn layout(
&self, &self,
engine: &mut Engine, engine: &mut Engine,
styles: StyleChain, styles: StyleChain,
regions: Regions, regions: Regions,
) -> SourceResult<Fragment> { ) -> SourceResult<Frame> {
const NUMBER_GUTTER: Em = Em::new(0.5); const NUMBER_GUTTER: Em = Em::new(0.5);
assert!(self.block(styles)); assert!(self.block(styles));
@ -248,7 +256,7 @@ impl Layout for Packed<EquationElem> {
frame.push_frame(Point::new(x, y), counter) frame.push_frame(Point::new(x, y), counter)
} }
Ok(Fragment::frame(frame)) Ok(frame)
} }
} }

View File

@ -67,7 +67,6 @@ impl Construct for DocumentElem {
} }
impl LayoutRoot for Packed<DocumentElem> { impl LayoutRoot for Packed<DocumentElem> {
/// Layout the document into a sequence of frames, one per page.
#[typst_macros::time(name = "document", span = self.span())] #[typst_macros::time(name = "document", span = self.span())]
fn layout_root( fn layout_root(
&self, &self,

View File

@ -7,7 +7,7 @@ use crate::foundations::{
}; };
use crate::layout::{ use crate::layout::{
Alignment, Axes, BlockElem, Cell, CellGrid, Em, Fragment, GridLayouter, HAlignment, Alignment, Axes, BlockElem, Cell, CellGrid, Em, Fragment, GridLayouter, HAlignment,
Layout, Length, Regions, Sizing, Spacing, VAlignment, LayoutMultiple, Length, Regions, Sizing, Spacing, VAlignment,
}; };
use crate::model::{Numbering, NumberingPattern, ParElem}; use crate::model::{Numbering, NumberingPattern, ParElem};
use crate::text::TextElem; use crate::text::TextElem;
@ -68,7 +68,7 @@ use crate::text::TextElem;
/// Enumeration items can contain multiple paragraphs and other block-level /// Enumeration items can contain multiple paragraphs and other block-level
/// content. All content that is indented more than an item's marker becomes /// content. All content that is indented more than an item's marker becomes
/// part of that item. /// part of that item.
#[elem(scope, title = "Numbered List", Layout)] #[elem(scope, title = "Numbered List", LayoutMultiple)]
pub struct EnumElem { pub struct EnumElem {
/// If this is `{false}`, the items are spaced apart with /// If this is `{false}`, the items are spaced apart with
/// [enum spacing]($enum.spacing). If it is `{true}`, they use normal /// [enum spacing]($enum.spacing). If it is `{true}`, they use normal
@ -208,7 +208,7 @@ impl EnumElem {
type EnumItem; type EnumItem;
} }
impl Layout for Packed<EnumElem> { impl LayoutMultiple for Packed<EnumElem> {
#[typst_macros::time(name = "enum", span = self.span())] #[typst_macros::time(name = "enum", span = self.span())]
fn layout( fn layout(
&self, &self,

View File

@ -4,8 +4,8 @@ use crate::foundations::{
cast, elem, scope, Array, Content, Fold, Func, Packed, Smart, StyleChain, Value, cast, elem, scope, Array, Content, Fold, Func, Packed, Smart, StyleChain, Value,
}; };
use crate::layout::{ use crate::layout::{
Axes, BlockElem, Cell, CellGrid, Em, Fragment, GridLayouter, HAlignment, Layout, Axes, BlockElem, Cell, CellGrid, Em, Fragment, GridLayouter, HAlignment,
Length, Regions, Sizing, Spacing, VAlignment, LayoutMultiple, Length, Regions, Sizing, Spacing, VAlignment,
}; };
use crate::model::ParElem; use crate::model::ParElem;
use crate::text::TextElem; use crate::text::TextElem;
@ -41,7 +41,7 @@ use crate::text::TextElem;
/// followed by a space to create a list item. A list item can contain multiple /// followed by a space to create a list item. A list item can contain multiple
/// paragraphs and other block-level content. All content that is indented /// paragraphs and other block-level content. All content that is indented
/// more than an item's marker becomes part of that item. /// more than an item's marker becomes part of that item.
#[elem(scope, title = "Bullet List", Layout)] #[elem(scope, title = "Bullet List", LayoutMultiple)]
pub struct ListElem { pub struct ListElem {
/// If this is `{false}`, the items are spaced apart with /// If this is `{false}`, the items are spaced apart with
/// [list spacing]($list.spacing). If it is `{true}`, they use normal /// [list spacing]($list.spacing). If it is `{true}`, they use normal
@ -133,7 +133,7 @@ impl ListElem {
type ListItem; type ListItem;
} }
impl Layout for Packed<ListElem> { impl LayoutMultiple for Packed<ListElem> {
#[typst_macros::time(name = "list", span = self.span())] #[typst_macros::time(name = "list", span = self.span())]
fn layout( fn layout(
&self, &self,

View File

@ -7,7 +7,7 @@ use crate::foundations::{
}; };
use crate::layout::{ use crate::layout::{
show_grid_cell, Abs, Alignment, Axes, Cell, CellGrid, Celled, Fragment, GridLayouter, show_grid_cell, Abs, Alignment, Axes, Cell, CellGrid, Celled, Fragment, GridLayouter,
Layout, Length, Regions, Rel, ResolvableCell, Sides, TrackSizings, LayoutMultiple, Length, Regions, Rel, ResolvableCell, Sides, TrackSizings,
}; };
use crate::model::Figurable; use crate::model::Figurable;
use crate::syntax::Span; use crate::syntax::Span;
@ -86,7 +86,7 @@ use crate::visualize::{Paint, Stroke};
/// ..(table.cell(y: 4, fill: aqua)[B],) * 2, /// ..(table.cell(y: 4, fill: aqua)[B],) * 2,
/// ) /// )
/// ``` /// ```
#[elem(scope, Layout, LocalName, Figurable)] #[elem(scope, LayoutMultiple, LocalName, Figurable)]
pub struct TableElem { pub struct TableElem {
/// The column sizes. See the [grid documentation]($grid) for more /// The column sizes. See the [grid documentation]($grid) for more
/// information on track sizing. /// information on track sizing.
@ -205,7 +205,7 @@ impl TableElem {
type TableCell; type TableCell;
} }
impl Layout for Packed<TableElem> { impl LayoutMultiple for Packed<TableElem> {
#[typst_macros::time(name = "table", span = self.span())] #[typst_macros::time(name = "table", span = self.span())]
fn layout( fn layout(
&self, &self,
@ -240,7 +240,6 @@ impl Layout for Packed<TableElem> {
.trace(engine.world, tracepoint, self.span())?; .trace(engine.world, tracepoint, self.span())?;
let layouter = GridLayouter::new(&grid, &stroke, regions, styles, self.span()); let layouter = GridLayouter::new(&grid, &stroke, regions, styles, self.span());
layouter.layout(engine) layouter.layout(engine)
} }
} }

View File

@ -4,7 +4,7 @@ use crate::foundations::{
cast, elem, scope, Array, Content, NativeElement, Packed, Smart, StyleChain, cast, elem, scope, Array, Content, NativeElement, Packed, Smart, StyleChain,
}; };
use crate::layout::{ use crate::layout::{
BlockElem, Em, Fragment, HElem, Layout, Length, Regions, Spacing, VElem, BlockElem, Em, Fragment, HElem, LayoutMultiple, Length, Regions, Spacing, VElem,
}; };
use crate::model::ParElem; use crate::model::ParElem;
use crate::util::Numeric; use crate::util::Numeric;
@ -25,7 +25,7 @@ use crate::util::Numeric;
/// # Syntax /// # Syntax
/// This function also has dedicated syntax: Starting a line with a slash, /// This function also has dedicated syntax: Starting a line with a slash,
/// followed by a term, a colon and a description creates a term list item. /// followed by a term, a colon and a description creates a term list item.
#[elem(scope, title = "Term List", Layout)] #[elem(scope, title = "Term List", LayoutMultiple)]
pub struct TermsElem { pub struct TermsElem {
/// If this is `{false}`, the items are spaced apart with /// If this is `{false}`, the items are spaced apart with
/// [term list spacing]($terms.spacing). If it is `{true}`, they use normal /// [term list spacing]($terms.spacing). If it is `{true}`, they use normal
@ -107,7 +107,7 @@ impl TermsElem {
type TermItem; type TermItem;
} }
impl Layout for Packed<TermsElem> { impl LayoutMultiple for Packed<TermsElem> {
#[typst_macros::time(name = "terms", span = self.span())] #[typst_macros::time(name = "terms", span = self.span())]
fn layout( fn layout(
&self, &self,

View File

@ -18,8 +18,8 @@ use crate::foundations::{
}; };
use crate::introspection::{Locatable, Meta, MetaElem}; use crate::introspection::{Locatable, Meta, MetaElem};
use crate::layout::{ use crate::layout::{
AlignElem, BlockElem, BoxElem, ColbreakElem, FlowElem, HElem, Layout, LayoutRoot, AlignElem, BlockElem, BoxElem, ColbreakElem, FlowElem, HElem, LayoutMultiple,
PageElem, PagebreakElem, Parity, PlaceElem, VElem, LayoutSingle, PageElem, PagebreakElem, Parity, PlaceElem, VElem,
}; };
use crate::math::{EquationElem, LayoutMath}; use crate::math::{EquationElem, LayoutMath};
use crate::model::{ use crate::model::{
@ -29,10 +29,6 @@ use crate::model::{
use crate::syntax::Span; use crate::syntax::Span;
use crate::text::{LinebreakElem, SmartQuoteElem, SpaceElem, TextElem}; use crate::text::{LinebreakElem, SmartQuoteElem, SpaceElem, TextElem};
use crate::util::hash128; use crate::util::hash128;
use crate::visualize::{
CircleElem, EllipseElem, ImageElem, LineElem, PathElem, PolygonElem, RectElem,
SquareElem,
};
/// Realize into an element that is capable of root-level layout. /// Realize into an element that is capable of root-level layout.
#[typst_macros::time(name = "realize root")] #[typst_macros::time(name = "realize root")]
@ -41,17 +37,13 @@ pub fn realize_root<'a>(
scratch: &'a Scratch<'a>, scratch: &'a Scratch<'a>,
content: &'a Content, content: &'a Content,
styles: StyleChain<'a>, styles: StyleChain<'a>,
) -> SourceResult<(Cow<'a, Content>, StyleChain<'a>)> { ) -> SourceResult<(Packed<DocumentElem>, StyleChain<'a>)> {
if content.can::<dyn LayoutRoot>() && !applicable(content, styles) {
return Ok((Cow::Borrowed(content), styles));
}
let mut builder = Builder::new(engine, scratch, true); let mut builder = Builder::new(engine, scratch, true);
builder.accept(content, styles)?; builder.accept(content, styles)?;
builder.interrupt_page(Some(styles), true)?; builder.interrupt_page(Some(styles), true)?;
let (pages, shared) = builder.doc.unwrap().pages.finish(); let (pages, shared) = builder.doc.unwrap().pages.finish();
let span = first_span(&pages); let span = first_span(&pages);
Ok((Cow::Owned(DocumentElem::new(pages.to_vec()).pack().spanned(span)), shared)) Ok((Packed::new(DocumentElem::new(pages.to_vec())).spanned(span), shared))
} }
/// Realize into an element that is capable of block-level layout. /// Realize into an element that is capable of block-level layout.
@ -64,19 +56,7 @@ pub fn realize_block<'a>(
) -> SourceResult<(Cow<'a, Content>, StyleChain<'a>)> { ) -> SourceResult<(Cow<'a, Content>, StyleChain<'a>)> {
// These elements implement `Layout` but still require a flow for // These elements implement `Layout` but still require a flow for
// proper layout. // proper layout.
if content.can::<dyn Layout>() if content.can::<dyn LayoutMultiple>() && !applicable(content, styles) {
&& !content.is::<BoxElem>()
&& !content.is::<LineElem>()
&& !content.is::<RectElem>()
&& !content.is::<SquareElem>()
&& !content.is::<EllipseElem>()
&& !content.is::<CircleElem>()
&& !content.is::<ImageElem>()
&& !content.is::<PolygonElem>()
&& !content.is::<PathElem>()
&& !content.is::<PlaceElem>()
&& !applicable(content, styles)
{
return Ok((Cow::Borrowed(content), styles)); return Ok((Cow::Borrowed(content), styles));
} }
@ -560,7 +540,10 @@ impl<'a> FlowBuilder<'a> {
return true; return true;
} }
if content.can::<dyn Layout>() || content.is::<ParElem>() { if content.can::<dyn LayoutSingle>()
|| content.can::<dyn LayoutMultiple>()
|| content.is::<ParElem>()
{
let is_tight_list = if let Some(elem) = content.to_packed::<ListElem>() { let is_tight_list = if let Some(elem) = content.to_packed::<ListElem>() {
elem.tight(styles) elem.tight(styles)
} else if let Some(elem) = content.to_packed::<EnumElem>() { } else if let Some(elem) = content.to_packed::<EnumElem>() {

View File

@ -20,8 +20,8 @@ use crate::foundations::{
StyleChain, StyleChain,
}; };
use crate::layout::{ use crate::layout::{
Abs, Axes, FixedAlignment, Fragment, Frame, FrameItem, Layout, Length, Point, Abs, Axes, FixedAlignment, Frame, FrameItem, LayoutSingle, Length, Point, Regions,
Regions, Rel, Size, Rel, Size,
}; };
use crate::loading::Readable; use crate::loading::Readable;
use crate::model::Figurable; use crate::model::Figurable;
@ -51,7 +51,7 @@ use crate::World;
/// ``` /// ```
/// ///
/// [gh-svg]: https://github.com/typst/typst/issues?q=is%3Aopen+is%3Aissue+label%3Asvg /// [gh-svg]: https://github.com/typst/typst/issues?q=is%3Aopen+is%3Aissue+label%3Asvg
#[elem(scope, Layout, LocalName, Figurable)] #[elem(scope, LayoutSingle, LocalName, Figurable)]
pub struct ImageElem { pub struct ImageElem {
/// Path to an image file. /// Path to an image file.
#[required] #[required]
@ -144,14 +144,14 @@ impl ImageElem {
} }
} }
impl Layout for Packed<ImageElem> { impl LayoutSingle for Packed<ImageElem> {
#[typst_macros::time(name = "image", span = self.span())] #[typst_macros::time(name = "image", span = self.span())]
fn layout( fn layout(
&self, &self,
engine: &mut Engine, engine: &mut Engine,
styles: StyleChain, styles: StyleChain,
regions: Regions, regions: Regions,
) -> SourceResult<Fragment> { ) -> SourceResult<Frame> {
// Take the format that was explicitly defined, or parse the extension, // Take the format that was explicitly defined, or parse the extension,
// or try to detect the format. // or try to detect the format.
let data = self.data(); let data = self.data();
@ -239,7 +239,7 @@ impl Layout for Packed<ImageElem> {
frame.clip(Path::rect(frame.size())); frame.clip(Path::rect(frame.size()));
} }
Ok(Fragment::frame(frame)) Ok(frame)
} }
} }

View File

@ -2,7 +2,7 @@ use crate::diag::{bail, SourceResult};
use crate::engine::Engine; use crate::engine::Engine;
use crate::foundations::{elem, Packed, StyleChain}; use crate::foundations::{elem, Packed, StyleChain};
use crate::layout::{ use crate::layout::{
Abs, Angle, Axes, Fragment, Frame, FrameItem, Layout, Length, Regions, Rel, Size, Abs, Angle, Axes, Frame, FrameItem, LayoutSingle, Length, Regions, Rel, Size,
}; };
use crate::util::Numeric; use crate::util::Numeric;
use crate::visualize::{Geometry, Stroke}; use crate::visualize::{Geometry, Stroke};
@ -20,7 +20,7 @@ use crate::visualize::{Geometry, Stroke};
/// stroke: 2pt + maroon, /// stroke: 2pt + maroon,
/// ) /// )
/// ``` /// ```
#[elem(Layout)] #[elem(LayoutSingle)]
pub struct LineElem { pub struct LineElem {
/// The start point of the line. /// The start point of the line.
/// ///
@ -58,14 +58,14 @@ pub struct LineElem {
pub stroke: Stroke, pub stroke: Stroke,
} }
impl Layout for Packed<LineElem> { impl LayoutSingle for Packed<LineElem> {
#[typst_macros::time(name = "line", span = self.span())] #[typst_macros::time(name = "line", span = self.span())]
fn layout( fn layout(
&self, &self,
_: &mut Engine, _: &mut Engine,
styles: StyleChain, styles: StyleChain,
regions: Regions, regions: Regions,
) -> SourceResult<Fragment> { ) -> SourceResult<Frame> {
let resolve = let resolve =
|axes: Axes<Rel<Abs>>| axes.zip_map(regions.base(), Rel::relative_to); |axes: Axes<Rel<Abs>>| axes.zip_map(regions.base(), Rel::relative_to);
let start = resolve(self.start(styles)); let start = resolve(self.start(styles));
@ -89,6 +89,6 @@ impl Layout for Packed<LineElem> {
let mut frame = Frame::soft(target); let mut frame = Frame::soft(target);
let shape = Geometry::Line(delta.to_point()).stroked(stroke); let shape = Geometry::Line(delta.to_point()).stroked(stroke);
frame.push(start.to_point(), FrameItem::Shape(shape, self.span())); frame.push(start.to_point(), FrameItem::Shape(shape, self.span()));
Ok(Fragment::frame(frame)) Ok(frame)
} }
} }

View File

@ -6,7 +6,8 @@ use crate::foundations::{
array, cast, elem, Array, Packed, Reflect, Resolve, Smart, StyleChain, array, cast, elem, Array, Packed, Reflect, Resolve, Smart, StyleChain,
}; };
use crate::layout::{ use crate::layout::{
Abs, Axes, Fragment, Frame, FrameItem, Layout, Length, Point, Regions, Rel, Size, Abs, Axes, Fragment, Frame, FrameItem, LayoutMultiple, Length, Point, Regions, Rel,
Size,
}; };
use crate::visualize::{FixedStroke, Geometry, Paint, Shape, Stroke}; use crate::visualize::{FixedStroke, Geometry, Paint, Shape, Stroke};
@ -25,7 +26,7 @@ use PathVertex::{AllControlPoints, MirroredControlPoint, Vertex};
/// ((50%, 0pt), (40pt, 0pt)), /// ((50%, 0pt), (40pt, 0pt)),
/// ) /// )
/// ``` /// ```
#[elem(Layout)] #[elem(LayoutMultiple)]
pub struct PathElem { pub struct PathElem {
/// How to fill the path. /// How to fill the path.
/// ///
@ -70,7 +71,7 @@ pub struct PathElem {
pub vertices: Vec<PathVertex>, pub vertices: Vec<PathVertex>,
} }
impl Layout for Packed<PathElem> { impl LayoutMultiple for Packed<PathElem> {
#[typst_macros::time(name = "path", span = self.span())] #[typst_macros::time(name = "path", span = self.span())]
fn layout( fn layout(
&self, &self,

View File

@ -7,7 +7,7 @@ use ecow::{eco_format, EcoString};
use crate::diag::{bail, SourceResult}; use crate::diag::{bail, SourceResult};
use crate::engine::Engine; use crate::engine::Engine;
use crate::foundations::{func, repr, scope, ty, Content, Smart, StyleChain}; use crate::foundations::{func, repr, scope, ty, Content, Smart, StyleChain};
use crate::layout::{Abs, Axes, Frame, Layout, Length, Regions, Size}; use crate::layout::{Abs, Axes, Frame, LayoutMultiple, Length, Regions, Size};
use crate::syntax::{Span, Spanned}; use crate::syntax::{Span, Spanned};
use crate::util::Numeric; use crate::util::Numeric;
use crate::visualize::RelativeTo; use crate::visualize::RelativeTo;

View File

@ -6,7 +6,7 @@ use crate::foundations::{
elem, func, scope, Content, NativeElement, Packed, Resolve, Smart, StyleChain, elem, func, scope, Content, NativeElement, Packed, Resolve, Smart, StyleChain,
}; };
use crate::layout::{ use crate::layout::{
Axes, Em, Fragment, Frame, FrameItem, Layout, Length, Point, Regions, Rel, Axes, Em, Frame, FrameItem, LayoutSingle, Length, Point, Regions, Rel,
}; };
use crate::syntax::Span; use crate::syntax::Span;
use crate::util::Numeric; use crate::util::Numeric;
@ -27,7 +27,7 @@ use crate::visualize::{FixedStroke, Geometry, Paint, Path, Shape, Stroke};
/// (0%, 2cm), /// (0%, 2cm),
/// ) /// )
/// ``` /// ```
#[elem(scope, Layout)] #[elem(scope, LayoutSingle)]
pub struct PolygonElem { pub struct PolygonElem {
/// How to fill the polygon. /// How to fill the polygon.
/// ///
@ -125,14 +125,14 @@ impl PolygonElem {
} }
} }
impl Layout for Packed<PolygonElem> { impl LayoutSingle for Packed<PolygonElem> {
#[typst_macros::time(name = "polygon", span = self.span())] #[typst_macros::time(name = "polygon", span = self.span())]
fn layout( fn layout(
&self, &self,
_: &mut Engine, _: &mut Engine,
styles: StyleChain, styles: StyleChain,
regions: Regions, regions: Regions,
) -> SourceResult<Fragment> { ) -> SourceResult<Frame> {
let points: Vec<Point> = self let points: Vec<Point> = self
.vertices() .vertices()
.iter() .iter()
@ -150,7 +150,7 @@ impl Layout for Packed<PolygonElem> {
// Only create a path if there are more than zero points. // Only create a path if there are more than zero points.
if points.is_empty() { if points.is_empty() {
return Ok(Fragment::frame(frame)); return Ok(frame);
} }
// Prepare fill and stroke. // Prepare fill and stroke.
@ -171,7 +171,6 @@ impl Layout for Packed<PolygonElem> {
let shape = Shape { geometry: Geometry::Path(path), stroke, fill }; let shape = Shape { geometry: Geometry::Path(path), stroke, fill };
frame.push(Point::zero(), FrameItem::Shape(shape, self.span())); frame.push(Point::zero(), FrameItem::Shape(shape, self.span()));
Ok(frame)
Ok(Fragment::frame(frame))
} }
} }

View File

@ -4,8 +4,8 @@ use crate::diag::SourceResult;
use crate::engine::Engine; use crate::engine::Engine;
use crate::foundations::{elem, Content, Packed, Resolve, Smart, StyleChain}; use crate::foundations::{elem, Content, Packed, Resolve, Smart, StyleChain};
use crate::layout::{ use crate::layout::{
Abs, Axes, Corner, Corners, Fragment, Frame, FrameItem, Layout, Length, Point, Ratio, Abs, Axes, Corner, Corners, Frame, FrameItem, LayoutMultiple, LayoutSingle, Length,
Regions, Rel, Sides, Size, Point, Ratio, Regions, Rel, Sides, Size,
}; };
use crate::syntax::Span; use crate::syntax::Span;
use crate::util::Get; use crate::util::Get;
@ -24,7 +24,7 @@ use crate::visualize::{FixedStroke, Paint, Path, Stroke};
/// to fit the content. /// to fit the content.
/// ] /// ]
/// ``` /// ```
#[elem(title = "Rectangle", Layout)] #[elem(title = "Rectangle", LayoutSingle)]
pub struct RectElem { pub struct RectElem {
/// The rectangle's width, relative to its parent container. /// The rectangle's width, relative to its parent container.
pub width: Smart<Rel<Length>>, pub width: Smart<Rel<Length>>,
@ -131,14 +131,14 @@ pub struct RectElem {
pub body: Option<Content>, pub body: Option<Content>,
} }
impl Layout for Packed<RectElem> { impl LayoutSingle for Packed<RectElem> {
#[typst_macros::time(name = "rect", span = self.span())] #[typst_macros::time(name = "rect", span = self.span())]
fn layout( fn layout(
&self, &self,
engine: &mut Engine, engine: &mut Engine,
styles: StyleChain, styles: StyleChain,
regions: Regions, regions: Regions,
) -> SourceResult<Fragment> { ) -> SourceResult<Frame> {
layout( layout(
engine, engine,
styles, styles,
@ -169,7 +169,7 @@ impl Layout for Packed<RectElem> {
/// sized to fit. /// sized to fit.
/// ] /// ]
/// ``` /// ```
#[elem(Layout)] #[elem(LayoutSingle)]
pub struct SquareElem { pub struct SquareElem {
/// The square's side length. This is mutually exclusive with `width` and /// The square's side length. This is mutually exclusive with `width` and
/// `height`. /// `height`.
@ -237,14 +237,14 @@ pub struct SquareElem {
pub body: Option<Content>, pub body: Option<Content>,
} }
impl Layout for Packed<SquareElem> { impl LayoutSingle for Packed<SquareElem> {
#[typst_macros::time(name = "square", span = self.span())] #[typst_macros::time(name = "square", span = self.span())]
fn layout( fn layout(
&self, &self,
engine: &mut Engine, engine: &mut Engine,
styles: StyleChain, styles: StyleChain,
regions: Regions, regions: Regions,
) -> SourceResult<Fragment> { ) -> SourceResult<Frame> {
layout( layout(
engine, engine,
styles, styles,
@ -276,7 +276,7 @@ impl Layout for Packed<SquareElem> {
/// to fit the content. /// to fit the content.
/// ] /// ]
/// ``` /// ```
#[elem(Layout)] #[elem(LayoutSingle)]
pub struct EllipseElem { pub struct EllipseElem {
/// The ellipse's width, relative to its parent container. /// The ellipse's width, relative to its parent container.
pub width: Smart<Rel<Length>>, pub width: Smart<Rel<Length>>,
@ -315,14 +315,14 @@ pub struct EllipseElem {
pub body: Option<Content>, pub body: Option<Content>,
} }
impl Layout for Packed<EllipseElem> { impl LayoutSingle for Packed<EllipseElem> {
#[typst_macros::time(name = "ellipse", span = self.span())] #[typst_macros::time(name = "ellipse", span = self.span())]
fn layout( fn layout(
&self, &self,
engine: &mut Engine, engine: &mut Engine,
styles: StyleChain, styles: StyleChain,
regions: Regions, regions: Regions,
) -> SourceResult<Fragment> { ) -> SourceResult<Frame> {
layout( layout(
engine, engine,
styles, styles,
@ -354,7 +354,7 @@ impl Layout for Packed<EllipseElem> {
/// sized to fit. /// sized to fit.
/// ] /// ]
/// ``` /// ```
#[elem(Layout)] #[elem(LayoutSingle)]
pub struct CircleElem { pub struct CircleElem {
/// The circle's radius. This is mutually exclusive with `width` and /// The circle's radius. This is mutually exclusive with `width` and
/// `height`. /// `height`.
@ -418,14 +418,14 @@ pub struct CircleElem {
pub body: Option<Content>, pub body: Option<Content>,
} }
impl Layout for Packed<CircleElem> { impl LayoutSingle for Packed<CircleElem> {
#[typst_macros::time(name = "circle", span = self.span())] #[typst_macros::time(name = "circle", span = self.span())]
fn layout( fn layout(
&self, &self,
engine: &mut Engine, engine: &mut Engine,
styles: StyleChain, styles: StyleChain,
regions: Regions, regions: Regions,
) -> SourceResult<Fragment> { ) -> SourceResult<Frame> {
layout( layout(
engine, engine,
styles, styles,
@ -458,7 +458,7 @@ fn layout(
outset: Sides<Rel<Abs>>, outset: Sides<Rel<Abs>>,
radius: Corners<Rel<Abs>>, radius: Corners<Rel<Abs>>,
span: Span, span: Span,
) -> SourceResult<Fragment> { ) -> SourceResult<Frame> {
let resolved = sizing let resolved = sizing
.zip_map(regions.base(), |s, r| s.map(|v| v.resolve(styles).relative_to(r))); .zip_map(regions.base(), |s, r| s.map(|v| v.resolve(styles).relative_to(r)));
@ -523,7 +523,7 @@ fn layout(
} }
} }
Ok(Fragment::frame(frame)) Ok(frame)
} }
/// A category of shape. /// A category of shape.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 58 KiB