summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/typst/src/layout/flow.rs36
-rw-r--r--crates/typst/src/layout/mod.rs20
-rw-r--r--crates/typst/src/realize/mod.rs32
-rw-r--r--crates/typst/src/realize/process.rs9
-rw-r--r--tests/ref/grid-cell-override.pngbin3546 -> 3539 bytes
-rw-r--r--tests/ref/grid-rowspan-split-2.pngbin1004 -> 966 bytes
-rw-r--r--tests/ref/grid-rtl-rowspan.pngbin1012 -> 978 bytes
-rw-r--r--tests/ref/place-float-columns.pngbin28138 -> 28346 bytes
-rw-r--r--tests/ref/table-cell-override.pngbin3546 -> 3539 bytes
9 files changed, 51 insertions, 46 deletions
diff --git a/crates/typst/src/layout/flow.rs b/crates/typst/src/layout/flow.rs
index c550ac28..2f985f28 100644
--- a/crates/typst/src/layout/flow.rs
+++ b/crates/typst/src/layout/flow.rs
@@ -46,7 +46,23 @@ impl LayoutMultiple for Packed<FlowElem> {
bail!(self.span(), "cannot expand into infinite height");
}
- let mut layouter = FlowLayouter::new(regions, styles);
+ // Check whether we have just a single multiple-layoutable element. In
+ // that case, we do not set `expand.y` to `false`, but rather keep it at
+ // its original value (since that element can take the full space).
+ //
+ // Consider the following code: `block(height: 5cm, pad(10pt, align(bottom, ..)))`
+ // Thanks to the code below, the expansion will be passed all the way
+ // through the block & pad and reach the innermost flow, so that things
+ // are properly bottom-aligned.
+ let mut alone = false;
+ if let [child] = self.children().as_slice() {
+ alone = child
+ .to_packed::<StyledElem>()
+ .map_or(child, |styled| &styled.child)
+ .can::<dyn LayoutMultiple>();
+ }
+
+ let mut layouter = FlowLayouter::new(regions, styles, alone);
for mut child in self.children().iter() {
let outer = styles;
let mut styles = styles;
@@ -70,8 +86,8 @@ impl LayoutMultiple for Packed<FlowElem> {
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 if let Some(layoutable) = child.with::<dyn LayoutMultiple>() {
+ layouter.layout_multiple(engine, child, layoutable, styles)?;
} else {
bail!(child.span(), "unexpected flow child");
}
@@ -179,11 +195,16 @@ impl FlowItem {
impl<'a> FlowLayouter<'a> {
/// Create a new flow layouter.
- fn new(mut regions: Regions<'a>, styles: StyleChain<'a>) -> Self {
+ fn new(mut regions: Regions<'a>, styles: StyleChain<'a>, alone: bool) -> Self {
let expand = regions.expand;
- // Disable vertical expansion & root for children.
- regions.expand.y = false;
+ // Disable vertical expansion when there are multiple or not directly
+ // layoutable children.
+ if !alone {
+ regions.expand.y = false;
+ }
+
+ // Disable root.
let root = std::mem::replace(&mut regions.root, false);
Self {
@@ -340,6 +361,7 @@ impl<'a> FlowLayouter<'a> {
&mut self,
engine: &mut Engine,
child: &Content,
+ layoutable: &dyn LayoutMultiple,
styles: StyleChain,
) -> SourceResult<()> {
// Temporarily delegerate rootness to the columns.
@@ -368,7 +390,7 @@ impl<'a> FlowLayouter<'a> {
// Layout the block itself.
let sticky = BlockElem::sticky_in(styles);
- let fragment = child.layout(engine, styles, self.regions)?;
+ let fragment = layoutable.layout(engine, styles, self.regions)?;
for (i, mut frame) in fragment.into_iter().enumerate() {
// Find footnotes in the frame.
diff --git a/crates/typst/src/layout/mod.rs b/crates/typst/src/layout/mod.rs
index 23a08c5f..0fd8e6b1 100644
--- a/crates/typst/src/layout/mod.rs
+++ b/crates/typst/src/layout/mod.rs
@@ -77,7 +77,7 @@ use crate::eval::Tracer;
use crate::foundations::{category, Category, Content, Scope, StyleChain};
use crate::introspection::{Introspector, Locator};
use crate::model::Document;
-use crate::realize::{realize_block, realize_root, Arenas};
+use crate::realize::{realize_doc, realize_flow, Arenas};
use crate::World;
/// Arranging elements on the page in different ways.
@@ -207,7 +207,7 @@ impl LayoutRoot for Content {
tracer,
};
let arenas = Arenas::default();
- let (document, styles) = realize_root(&mut engine, &arenas, content, styles)?;
+ let (document, styles) = realize_doc(&mut engine, &arenas, content, styles)?;
document.layout_root(&mut engine, styles)
}
@@ -258,14 +258,16 @@ impl LayoutMultiple for Content {
);
}
+ // If we are in a `PageElem`, this might already be a realized flow.
+ if let Some(flow) = content.to_packed::<FlowElem>() {
+ return flow.layout(&mut engine, styles, regions);
+ }
+
+ // Layout the content by first turning it into a `FlowElem` and then
+ // layouting that.
let arenas = Arenas::default();
- let (realized, styles) =
- realize_block(&mut engine, &arenas, content, styles)?;
- realized.with::<dyn LayoutMultiple>().unwrap().layout(
- &mut engine,
- styles,
- regions,
- )
+ let (flow, styles) = realize_flow(&mut engine, &arenas, content, styles)?;
+ flow.layout(&mut engine, styles, regions)
}
let fragment = cached(
diff --git a/crates/typst/src/realize/mod.rs b/crates/typst/src/realize/mod.rs
index 98b5c127..4679a61c 100644
--- a/crates/typst/src/realize/mod.rs
+++ b/crates/typst/src/realize/mod.rs
@@ -12,9 +12,7 @@ mod process;
pub use self::arenas::Arenas;
pub use self::behaviour::{Behave, BehavedBuilder, Behaviour};
-pub use self::process::{process, processable};
-
-use std::borrow::Cow;
+pub use self::process::process;
use std::mem;
@@ -36,9 +34,10 @@ use crate::model::{
use crate::syntax::Span;
use crate::text::{LinebreakElem, SmartQuoteElem, SpaceElem, TextElem};
-/// Realize into an element that is capable of root-level layout.
-#[typst_macros::time(name = "realize root")]
-pub fn realize_root<'a>(
+/// Realize into a `DocumentElem`, an element that is capable of root-level
+/// layout.
+#[typst_macros::time(name = "realize doc")]
+pub fn realize_doc<'a>(
engine: &mut Engine,
arenas: &'a Arenas<'a>,
content: &'a Content,
@@ -47,30 +46,21 @@ pub fn realize_root<'a>(
let mut builder = Builder::new(engine, arenas, true);
builder.accept(content, styles)?;
builder.interrupt_page(Some(styles), true)?;
- let (doc, trunk) = builder.doc.unwrap().finish();
- Ok((doc, trunk))
+ Ok(builder.doc.unwrap().finish())
}
-/// Realize into an element that is capable of block-level layout.
-#[typst_macros::time(name = "realize block")]
-pub fn realize_block<'a>(
+/// Realize into a `FlowElem`, an element that is capable of block-level layout.
+#[typst_macros::time(name = "realize flow")]
+pub fn realize_flow<'a>(
engine: &mut Engine,
arenas: &'a Arenas<'a>,
content: &'a Content,
styles: StyleChain<'a>,
-) -> SourceResult<(Cow<'a, Content>, StyleChain<'a>)> {
- // These elements implement `Layout` but still require a flow for
- // proper layout.
- if content.can::<dyn LayoutMultiple>() && !processable(engine, content, styles) {
- return Ok((Cow::Borrowed(content), styles));
- }
-
+) -> SourceResult<(Packed<FlowElem>, StyleChain<'a>)> {
let mut builder = Builder::new(engine, arenas, false);
builder.accept(content, styles)?;
builder.interrupt_par()?;
-
- let (flow, trunk) = builder.flow.finish();
- Ok((Cow::Owned(flow.pack()), trunk))
+ Ok(builder.flow.finish())
}
/// Builds a document or a flow element from content.
diff --git a/crates/typst/src/realize/process.rs b/crates/typst/src/realize/process.rs
index 6ddb493d..4212ecb4 100644
--- a/crates/typst/src/realize/process.rs
+++ b/crates/typst/src/realize/process.rs
@@ -31,15 +31,6 @@ enum ShowStep<'a> {
Builtin,
}
-/// Returns whether the `target` element needs processing.
-pub fn processable<'a>(
- engine: &mut Engine,
- target: &'a Content,
- styles: StyleChain<'a>,
-) -> bool {
- verdict(engine, target, styles).is_some()
-}
-
/// Processes the given `target` element when encountering it during realization.
pub fn process(
engine: &mut Engine,
diff --git a/tests/ref/grid-cell-override.png b/tests/ref/grid-cell-override.png
index d6f37d63..a38efca5 100644
--- a/tests/ref/grid-cell-override.png
+++ b/tests/ref/grid-cell-override.png
Binary files differ
diff --git a/tests/ref/grid-rowspan-split-2.png b/tests/ref/grid-rowspan-split-2.png
index 43a5eed7..fad27f49 100644
--- a/tests/ref/grid-rowspan-split-2.png
+++ b/tests/ref/grid-rowspan-split-2.png
Binary files differ
diff --git a/tests/ref/grid-rtl-rowspan.png b/tests/ref/grid-rtl-rowspan.png
index 2465164b..7b51f97b 100644
--- a/tests/ref/grid-rtl-rowspan.png
+++ b/tests/ref/grid-rtl-rowspan.png
Binary files differ
diff --git a/tests/ref/place-float-columns.png b/tests/ref/place-float-columns.png
index 97065b68..5bc50c46 100644
--- a/tests/ref/place-float-columns.png
+++ b/tests/ref/place-float-columns.png
Binary files differ
diff --git a/tests/ref/table-cell-override.png b/tests/ref/table-cell-override.png
index d6f37d63..a38efca5 100644
--- a/tests/ref/table-cell-override.png
+++ b/tests/ref/table-cell-override.png
Binary files differ