summaryrefslogtreecommitdiff
path: root/library/src
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2022-12-09 10:21:11 +0100
committerLaurenz <laurmaedje@gmail.com>2022-12-09 10:21:11 +0100
commitcd089b6194c57b2e8dff70efaa7cbd53035f7327 (patch)
treef5466a0e2f8633aa609276c0c2794911c7e9252a /library/src
parent495b525694aa5901385f3acad043b4a9f3ebb911 (diff)
Align set rule
Diffstat (limited to 'library/src')
-rw-r--r--library/src/layout/align.rs64
-rw-r--r--library/src/layout/flow.rs14
-rw-r--r--library/src/layout/mod.rs4
-rw-r--r--library/src/layout/par.rs6
-rw-r--r--library/src/layout/place.rs8
-rw-r--r--library/src/layout/stack.rs22
-rw-r--r--library/src/lib.rs2
-rw-r--r--library/src/math/mod.rs8
-rw-r--r--library/src/shared/ext.rs2
9 files changed, 36 insertions, 94 deletions
diff --git a/library/src/layout/align.rs b/library/src/layout/align.rs
index ae60b4c6..506ef684 100644
--- a/library/src/layout/align.rs
+++ b/library/src/layout/align.rs
@@ -1,62 +1,22 @@
-use super::{HorizontalAlign, ParNode};
use crate::prelude::*;
-/// Align content along the layouting axes.
+/// Just an empty shell to scope styles.
#[derive(Debug, Hash)]
-pub struct AlignNode {
- /// How to align the content horizontally and vertically.
- pub aligns: Axes<Option<GenAlign>>,
- /// The content to be aligned.
- pub body: Content,
-}
+pub enum AlignNode {}
-#[node(Layout)]
+#[node]
impl AlignNode {
- fn construct(_: &Vm, args: &mut Args) -> SourceResult<Content> {
- let aligns: Axes<Option<GenAlign>> = args.find()?.unwrap_or_default();
- let body: Content = args.expect("body")?;
+ /// The alignment.
+ #[property(fold, skip)]
+ pub const ALIGNS: Axes<Option<GenAlign>> =
+ Axes::new(GenAlign::Start, GenAlign::Specific(Align::Top));
- if let Axes { x: Some(x), y: None } = aligns {
- if !body.has::<dyn Layout>() || body.has::<dyn Inline>() {
- return Ok(body.styled(ParNode::ALIGN, HorizontalAlign(x)));
- }
- }
-
- Ok(Self { aligns, body }.pack())
+ fn construct(_: &Vm, args: &mut Args) -> SourceResult<Content> {
+ args.expect("body")
}
-}
-impl Layout for AlignNode {
- fn layout(
- &self,
- vt: &mut Vt,
- styles: StyleChain,
- regions: Regions,
- ) -> SourceResult<Fragment> {
- // The child only needs to expand along an axis if there's no alignment.
- let mut pod = regions.clone();
- pod.expand &= self.aligns.as_ref().map(Option::is_none);
-
- // Align paragraphs inside the child.
- let mut map = StyleMap::new();
- if let Some(align) = self.aligns.x {
- map.set(ParNode::ALIGN, HorizontalAlign(align));
- }
-
- // Layout the child.
- let mut fragment = self.body.layout(vt, styles.chain(&map), pod)?;
- for (region, frame) in regions.iter().zip(&mut fragment) {
- // Align in the target size. The target size depends on whether we
- // should expand.
- let target = regions.expand.select(region, frame.size());
- let aligns = self
- .aligns
- .map(|align| align.resolve(styles))
- .unwrap_or(Axes::new(Align::Left, Align::Top));
-
- frame.resize(target, aligns);
- }
-
- Ok(fragment)
+ fn set(...) {
+ let aligns: Axes<Option<GenAlign>> = args.find()?.unwrap_or_default();
+ styles.set(Self::ALIGNS, aligns);
}
}
diff --git a/library/src/layout/flow.rs b/library/src/layout/flow.rs
index 0b6454a0..b78f3932 100644
--- a/library/src/layout/flow.rs
+++ b/library/src/layout/flow.rs
@@ -125,7 +125,7 @@ impl<'a> FlowLayouter<'a> {
par: &ParNode,
styles: StyleChain,
) -> SourceResult<()> {
- let aligns = Axes::new(styles.get(ParNode::ALIGN), Align::Top);
+ let aligns = styles.get(AlignNode::ALIGNS).resolve(styles);
let leading = styles.get(ParNode::LEADING);
let consecutive = self.last_was_par;
let fragment = par.layout(
@@ -172,17 +172,7 @@ impl<'a> FlowLayouter<'a> {
}
// How to align the block.
- let aligns = Axes::new(
- // For non-expanding paragraphs it is crucial that we align the
- // whole paragraph as it is itself aligned.
- styles.get(ParNode::ALIGN),
- // Vertical align node alignment is respected by the flow.
- block
- .to::<AlignNode>()
- .and_then(|aligned| aligned.aligns.y)
- .map(|align| align.resolve(styles))
- .unwrap_or(Align::Top),
- );
+ let aligns = styles.get(AlignNode::ALIGNS).resolve(styles);
// Layout the block itself.
let sticky = styles.get(BlockNode::STICKY);
diff --git a/library/src/layout/mod.rs b/library/src/layout/mod.rs
index 00b1f9be..afa1344f 100644
--- a/library/src/layout/mod.rs
+++ b/library/src/layout/mod.rs
@@ -412,7 +412,9 @@ impl<'a, 'v, 't> Builder<'a, 'v, 't> {
bail!(span, "not allowed here");
}
self.interrupt_page(styles)?;
- } else if map.interruption::<ParNode>().is_some() {
+ } else if map.interruption::<ParNode>().is_some()
+ || map.interruption::<AlignNode>().is_some()
+ {
self.interrupt_par()?;
} else if map.interruption::<ListNode>().is_some()
|| map.interruption::<EnumNode>().is_some()
diff --git a/library/src/layout/par.rs b/library/src/layout/par.rs
index c0e7c6c9..d93bfba7 100644
--- a/library/src/layout/par.rs
+++ b/library/src/layout/par.rs
@@ -5,6 +5,7 @@ use xi_unicode::LineBreakIterator;
use typst::model::Key;
use super::{HNode, RepeatNode, Spacing};
+use crate::layout::AlignNode;
use crate::prelude::*;
use crate::text::{
shape, LinebreakNode, Quoter, Quotes, ShapedText, SmartQuoteNode, SpaceNode, TextNode,
@@ -22,9 +23,6 @@ impl ParNode {
/// The spacing between lines.
#[property(resolve)]
pub const LEADING: Length = Em::new(0.65).into();
- /// How to align text and inline objects in their line.
- #[property(resolve)]
- pub const ALIGN: HorizontalAlign = HorizontalAlign(GenAlign::Start);
/// Whether to justify text in its line.
pub const JUSTIFY: bool = false;
/// How to determine line breaks.
@@ -554,7 +552,7 @@ fn prepare<'a>(
styles,
hyphenate: shared_get(styles, &par.0, TextNode::HYPHENATE),
lang: shared_get(styles, &par.0, TextNode::LANG),
- align: styles.get(ParNode::ALIGN),
+ align: styles.get(AlignNode::ALIGNS).x.resolve(styles),
justify: styles.get(ParNode::JUSTIFY),
})
}
diff --git a/library/src/layout/place.rs b/library/src/layout/place.rs
index 2e2c81a1..28d231b7 100644
--- a/library/src/layout/place.rs
+++ b/library/src/layout/place.rs
@@ -1,9 +1,8 @@
-use super::AlignNode;
use crate::prelude::*;
/// Place content at an absolute position.
#[derive(Debug, Hash)]
-pub struct PlaceNode(pub Content);
+pub struct PlaceNode(pub Content, bool);
#[node(Layout, Behave)]
impl PlaceNode {
@@ -12,7 +11,8 @@ impl PlaceNode {
let dx = args.named("dx")?.unwrap_or_default();
let dy = args.named("dy")?.unwrap_or_default();
let body = args.expect::<Content>("body")?;
- Ok(Self(body.moved(Axes::new(dx, dy)).aligned(aligns)).pack())
+ let out_of_flow = aligns.y.is_some();
+ Ok(Self(body.moved(Axes::new(dx, dy)).aligned(aligns), out_of_flow).pack())
}
}
@@ -49,7 +49,7 @@ impl PlaceNode {
/// origin. Instead of relative to the parent's current flow/cursor
/// position.
pub fn out_of_flow(&self) -> bool {
- self.0.to::<AlignNode>().map_or(false, |node| node.aligns.y.is_some())
+ self.1
}
}
diff --git a/library/src/layout/stack.rs b/library/src/layout/stack.rs
index 6432f4ac..d44dcb48 100644
--- a/library/src/layout/stack.rs
+++ b/library/src/layout/stack.rs
@@ -1,6 +1,6 @@
use typst::model::StyledNode;
-use super::{AlignNode, ParNode, Spacing};
+use super::{AlignNode, Spacing};
use crate::prelude::*;
/// Arrange content and spacing along an axis.
@@ -180,21 +180,13 @@ impl<'a> StackLayouter<'a> {
// Block-axis alignment of the `AlignNode` is respected
// by the stack node.
- let align = block
- .to::<AlignNode>()
- .and_then(|node| node.aligns.get(self.axis))
- .map(|align| align.resolve(styles))
- .unwrap_or_else(|| {
- if let Some(styled) = block.to::<StyledNode>() {
- let map = &styled.map;
- if map.contains(ParNode::ALIGN) {
- return StyleChain::new(map).get(ParNode::ALIGN);
- }
- }
-
- self.dir.start().into()
- });
+ let aligns = if let Some(styled) = block.to::<StyledNode>() {
+ styles.chain(&styled.map).get(AlignNode::ALIGNS)
+ } else {
+ styles.get(AlignNode::ALIGNS)
+ };
+ let align = aligns.get(self.axis).resolve(styles);
let fragment = block.layout(vt, styles, self.regions)?;
let len = fragment.len();
for (i, frame) in fragment.into_iter().enumerate() {
diff --git a/library/src/lib.rs b/library/src/lib.rs
index e41e7c0d..86bef0b9 100644
--- a/library/src/lib.rs
+++ b/library/src/lib.rs
@@ -208,6 +208,6 @@ fn items() -> LangItems {
math_atom: |atom| math::AtomNode(atom).pack(),
math_script: |base, sub, sup| math::ScriptNode { base, sub, sup }.pack(),
math_frac: |num, denom| math::FracNode { num, denom }.pack(),
- math_align: |count| math::AlignNode(count).pack(),
+ math_align_point: |count| math::AlignPointNode(count).pack(),
}
}
diff --git a/library/src/math/mod.rs b/library/src/math/mod.rs
index 1139296c..62432b12 100644
--- a/library/src/math/mod.rs
+++ b/library/src/math/mod.rs
@@ -442,14 +442,14 @@ impl Texify for ScriptNode {
}
}
-/// A math alignment indicator: `&`, `&&`.
+/// A math alignment point: `&`, `&&`.
#[derive(Debug, Hash)]
-pub struct AlignNode(pub usize);
+pub struct AlignPointNode(pub usize);
#[node(Texify)]
-impl AlignNode {}
+impl AlignPointNode {}
-impl Texify for AlignNode {
+impl Texify for AlignPointNode {
fn texify(&self, _: &mut Texifier) -> SourceResult<()> {
Ok(())
}
diff --git a/library/src/shared/ext.rs b/library/src/shared/ext.rs
index 811ae757..23db71f9 100644
--- a/library/src/shared/ext.rs
+++ b/library/src/shared/ext.rs
@@ -57,7 +57,7 @@ impl ContentExt for Content {
}
fn aligned(self, aligns: Axes<Option<GenAlign>>) -> Self {
- crate::layout::AlignNode { aligns, body: self }.pack()
+ self.styled(crate::layout::AlignNode::ALIGNS, aligns)
}
fn padded(self, padding: Sides<Rel<Length>>) -> Self {