diff options
Diffstat (limited to 'library/src/math/attach.rs')
| -rw-r--r-- | library/src/math/attach.rs | 79 |
1 files changed, 54 insertions, 25 deletions
diff --git a/library/src/math/attach.rs b/library/src/math/attach.rs index cbf083c0..eee1e80e 100644 --- a/library/src/math/attach.rs +++ b/library/src/math/attach.rs @@ -77,18 +77,9 @@ impl LayoutMath for AttachElem { let b = layout_attachment(ctx, Self::b)?; ctx.unstyle(); - let as_limits = self.base().is::<LimitsElem>() - || (!self.base().is::<ScriptsElem>() - && ctx.style.size == MathSize::Display - && base.class() == Some(MathClass::Large) - && match &base { - MathFragment::Variant(variant) => LIMITS.contains(&variant.c), - MathFragment::Frame(fragment) => fragment.limits, - _ => false, - }); - - let (t, tr) = if as_limits || tr.is_some() { (t, tr) } else { (None, t) }; - let (b, br) = if as_limits || br.is_some() { (b, br) } else { (None, b) }; + let limits = base.limits().active(ctx); + let (t, tr) = if limits || tr.is_some() { (t, tr) } else { (None, t) }; + let (b, br) = if limits || br.is_some() { (b, br) } else { (None, b) }; layout_attachments(ctx, base, [tl, t, tr, bl, b, br]) } } @@ -112,7 +103,10 @@ pub struct ScriptsElem { impl LayoutMath for ScriptsElem { #[tracing::instrument(skip(ctx))] fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> { - self.body().layout_math(ctx) + let mut fragment = ctx.layout_fragment(&self.body())?; + fragment.set_limits(Limits::Never); + ctx.push(fragment); + Ok(()) } } @@ -135,10 +129,56 @@ pub struct LimitsElem { impl LayoutMath for LimitsElem { #[tracing::instrument(skip(ctx))] fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> { - self.body().layout_math(ctx) + let mut fragment = ctx.layout_fragment(&self.body())?; + fragment.set_limits(Limits::Always); + ctx.push(fragment); + Ok(()) } } +/// Describes in which situation a frame should use limits for attachments. +#[derive(Debug, Copy, Clone)] +pub enum Limits { + /// Always scripts. + Never, + /// Display limits only in `display` math. + Display, + /// Always limits. + Always, +} + +impl Limits { + /// The default limit configuration if the given character is the base. + pub fn for_char(c: char) -> Self { + if Self::DEFAULT_TO_LIMITS.contains(&c) { + Limits::Display + } else { + Limits::Never + } + } + + /// Whether limits should be displayed in this context + pub fn active(&self, ctx: &MathContext) -> bool { + match self { + Self::Always => true, + Self::Display => ctx.style.size == MathSize::Display, + Self::Never => false, + } + } + + /// Unicode codepoints that should show attachments as limits in display + /// mode. + #[rustfmt::skip] + const DEFAULT_TO_LIMITS: &[char] = &[ + /* ∏ */ '\u{220F}', /* ∐ */ '\u{2210}', /* ∑ */ '\u{2211}', + /* ⋀ */ '\u{22C0}', /* ⋁ */ '\u{22C1}', + /* ⋂ */ '\u{22C2}', /* ⋃ */ '\u{22C3}', + /* ⨀ */ '\u{2A00}', /* ⨁ */ '\u{2A01}', /* ⨂ */ '\u{2A02}', + /* ⨃ */ '\u{2A03}', /* ⨄ */ '\u{2A04}', + /* ⨅ */ '\u{2A05}', /* ⨆ */ '\u{2A06}', + ]; +} + macro_rules! measure { ($e: ident, $attr: ident) => { $e.as_ref().map(|e| e.$attr()).unwrap_or_default() @@ -358,14 +398,3 @@ fn is_atomic_text_frame(frame: &Frame) -> bool { .filter(|item| !matches!(item, FrameItem::Meta(_, _))); matches!(iter.next(), Some(FrameItem::Text(_))) && iter.next().is_none() } - -/// Unicode codepoints that should have sub- and superscripts attached as limits. -#[rustfmt::skip] -const LIMITS: &[char] = &[ - /* ∏ */ '\u{220F}', /* ∐ */ '\u{2210}', /* ∑ */ '\u{2211}', - /* ⋀ */ '\u{22C0}', /* ⋁ */ '\u{22C1}', - /* ⋂ */ '\u{22C2}', /* ⋃ */ '\u{22C3}', - /* ⨀ */ '\u{2A00}', /* ⨁ */ '\u{2A01}', /* ⨂ */ '\u{2A02}', - /* ⨃ */ '\u{2A03}', /* ⨄ */ '\u{2A04}', - /* ⨅ */ '\u{2A05}', /* ⨆ */ '\u{2A06}', -]; |
