summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/typst/src/math/fragment.rs2
-rw-r--r--crates/typst/src/math/lr.rs47
-rw-r--r--crates/typst/src/math/mod.rs1
-rw-r--r--crates/typst/src/math/stretch.rs1
-rw-r--r--tests/ref/math/delimited.pngbin25691 -> 29571 bytes
-rw-r--r--tests/typ/math/delimited.typ7
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
index c83764ec..1a67cd1d 100644
--- a/tests/ref/math/delimited.png
+++ b/tests/ref/math/delimited.png
Binary files differ
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) } $