diff options
| -rw-r--r-- | crates/typst/src/math/fragment.rs | 2 | ||||
| -rw-r--r-- | crates/typst/src/math/lr.rs | 47 | ||||
| -rw-r--r-- | crates/typst/src/math/mod.rs | 1 | ||||
| -rw-r--r-- | crates/typst/src/math/stretch.rs | 1 | ||||
| -rw-r--r-- | tests/ref/math/delimited.png | bin | 25691 -> 29571 bytes | |||
| -rw-r--r-- | tests/typ/math/delimited.typ | 7 |
6 files changed, 58 insertions, 0 deletions
diff --git a/crates/typst/src/math/fragment.rs b/crates/typst/src/math/fragment.rs index fb1420bf..d176dd96 100644 --- a/crates/typst/src/math/fragment.rs +++ b/crates/typst/src/math/fragment.rs @@ -297,6 +297,7 @@ impl GlyphFragment { span: self.span, limits: self.limits, frame: self.into_frame(), + mid_stretched: None, } } @@ -360,6 +361,7 @@ pub struct VariantFragment { pub class: Option<MathClass>, pub span: Span, pub limits: Limits, + pub mid_stretched: Option<bool>, } impl VariantFragment { diff --git a/crates/typst/src/math/lr.rs b/crates/typst/src/math/lr.rs index 93e5a43c..1631623b 100644 --- a/crates/typst/src/math/lr.rs +++ b/crates/typst/src/math/lr.rs @@ -57,6 +57,7 @@ impl LayoutMath for LrElem { .resolve(ctx.styles()) .relative_to(2.0 * max_extent); + // Scale up fragments at both ends. match fragments.as_mut_slice() { [one] => scale(ctx, one, height, None), [first, .., last] => { @@ -66,12 +67,58 @@ impl LayoutMath for LrElem { _ => {} } + // Handle MathFragment::Variant fragments that should be scaled up. + for fragment in &mut fragments { + if let MathFragment::Variant(ref mut variant) = fragment { + if variant.mid_stretched == Some(false) { + variant.mid_stretched = Some(true); + scale(ctx, fragment, height, Some(MathClass::Large)); + } + } + } + ctx.extend(fragments); Ok(()) } } +/// Scales contents vertically to the nearest surrounding lr() group. +/// +/// ```example +/// $ { x mid(|) sum_(i=1)^oo phi_i (x) < 1 } $ +/// ``` +#[elem(LayoutMath)] +pub struct MidElem { + /// The content to be scaled. + #[required] + pub body: Content, +} + +impl LayoutMath for MidElem { + #[tracing::instrument(skip(ctx))] + fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> { + let mut fragments = ctx.layout_fragments(self.body())?; + + for fragment in &mut fragments { + match fragment { + MathFragment::Glyph(glyph) => { + let mut new = glyph.clone().into_variant(); + new.mid_stretched = Some(false); + *fragment = MathFragment::Variant(new); + } + MathFragment::Variant(variant) => { + variant.mid_stretched = Some(false); + } + _ => {} + } + } + + ctx.extend(fragments); + Ok(()) + } +} + /// Scale a math fragment to a height. fn scale( ctx: &mut MathContext, diff --git a/crates/typst/src/math/mod.rs b/crates/typst/src/math/mod.rs index d84d9b40..85227fc1 100644 --- a/crates/typst/src/math/mod.rs +++ b/crates/typst/src/math/mod.rs @@ -161,6 +161,7 @@ pub fn module() -> Module { math.define_elem::<EquationElem>(); math.define_elem::<TextElem>(); math.define_elem::<LrElem>(); + math.define_elem::<MidElem>(); math.define_elem::<AttachElem>(); math.define_elem::<ScriptsElem>(); math.define_elem::<LimitsElem>(); diff --git a/crates/typst/src/math/stretch.rs b/crates/typst/src/math/stretch.rs index a8e22af4..bfeb80ef 100644 --- a/crates/typst/src/math/stretch.rs +++ b/crates/typst/src/math/stretch.rs @@ -187,6 +187,7 @@ fn assemble( class: base.class, span: base.span, limits: base.limits, + mid_stretched: None, } } diff --git a/tests/ref/math/delimited.png b/tests/ref/math/delimited.png Binary files differindex c83764ec..1a67cd1d 100644 --- a/tests/ref/math/delimited.png +++ b/tests/ref/math/delimited.png diff --git a/tests/typ/math/delimited.typ b/tests/typ/math/delimited.typ index e5b93cd6..6607c302 100644 --- a/tests/typ/math/delimited.typ +++ b/tests/typ/math/delimited.typ @@ -43,3 +43,10 @@ $ lr( text("(", fill: #green) a/b text(")", fill: #blue) ) $ + +--- +// Test middle functions +$ { x mid(|) sum_(i=1)^oo phi_i (x) < 1 } \ + { integral |x| dif x + mid(bar.v.double) + floor(hat(A) mid(|) { x mid(|) y } mid(|) A) } $ |
